diff --git a/SOURCES/kvm-Add-support-to-KVM_GET_MSR_FEATURE_INDEX_LIST-an.patch b/SOURCES/kvm-Add-support-to-KVM_GET_MSR_FEATURE_INDEX_LIST-an.patch index 246bd33..d3e7931 100644 --- a/SOURCES/kvm-Add-support-to-KVM_GET_MSR_FEATURE_INDEX_LIST-an.patch +++ b/SOURCES/kvm-Add-support-to-KVM_GET_MSR_FEATURE_INDEX_LIST-an.patch @@ -1,17 +1,17 @@ -From 792618b0b553323919ae9b8067bc13c9e0222526 Mon Sep 17 00:00:00 2001 +From 90b8d9d17a9c252427df71fbe5bd76f897529e71 Mon Sep 17 00:00:00 2001 From: "plai@redhat.com" -Date: Tue, 20 Aug 2019 00:24:36 +0100 -Subject: [PATCH 5/9] kvm: Add support to KVM_GET_MSR_FEATURE_INDEX_LIST and +Date: Wed, 3 Apr 2019 15:54:30 +0100 +Subject: [PATCH 06/10] kvm: Add support to KVM_GET_MSR_FEATURE_INDEX_LIST and KVM_GET_MSRS system ioctl RH-Author: plai@redhat.com -Message-id: <1566260680-20995-6-git-send-email-plai@redhat.com> -Patchwork-id: 90070 -O-Subject: [RHEL8.0 qemu-kvm PATCH v3 5/9] kvm: Add support to KVM_GET_MSR_FEATURE_INDEX_LIST and KVM_GET_MSRS system ioctl -Bugzilla: 1718235 +Message-id: <1554306874-28796-7-git-send-email-plai@redhat.com> +Patchwork-id: 85384 +O-Subject: [RHEL8.1 qemu-kvm PATCH resend 06/10] kvm: Add support to KVM_GET_MSR_FEATURE_INDEX_LIST and KVM_GET_MSRS system ioctl +Bugzilla: 1561761 RH-Acked-by: Eduardo Habkost -RH-Acked-by: John Snow RH-Acked-by: Igor Mammedov +RH-Acked-by: Michael S. Tsirkin From: Robert Hoo @@ -44,7 +44,7 @@ index 23669c4..3d8f294 100644 void kvm_set_sigmask_len(KVMState *s, unsigned int sigmask_len); diff --git a/target/i386/kvm.c b/target/i386/kvm.c -index 187ee19..d2cb91e 100644 +index 702e3bf..096ed24 100644 --- a/target/i386/kvm.c +++ b/target/i386/kvm.c @@ -106,6 +106,7 @@ static int has_pit_state2; diff --git a/SOURCES/kvm-Disable-VXHS-support.patch b/SOURCES/kvm-Disable-VXHS-support.patch new file mode 100644 index 0000000..5729ca9 --- /dev/null +++ b/SOURCES/kvm-Disable-VXHS-support.patch @@ -0,0 +1,457 @@ +From 88780a41e05b8079cde07466c252b42c113f9e5c Mon Sep 17 00:00:00 2001 +From: Miroslav Rezanina +Date: Sun, 9 Jun 2019 09:35:09 +0100 +Subject: [PATCH 8/8] Disable VXHS support + +RH-Author: Miroslav Rezanina +Message-id: <1560072909-1725-1-git-send-email-mrezanin@redhat.com> +Patchwork-id: 88629 +O-Subject: [RHEL-8 qemu-kvm PATCH] Disable VXHS support +Bugzilla: 1714933 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Markus Armbruster +RH-Acked-by: Danilo de Paula + +From: Miroslav Rezanina + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1714933 +Brew: https://brewweb.engineering.redhat.com/brew/taskinfo?taskID=22065429 +Branch: rhel-8.1.0 +Upstream: n/a + +Reverting commit e9aff9d4ab1f9c10a4cb88fc5b92c4835e8b2688 introducing +downstream modularizaiton of VXHS driver as we do not need to support +VXHS driver anymore. + +Patch is not pure revert as we changed way we handle configuration +of qemu build after this patch. In addition, reverting downstream only +removing of vxhs.o from block/Makefile.obj. + +Signed-off-by: Miroslav Rezanina +Signed-off-by: Danilo C. L. de Paula +--- + block/Makefile.objs | 2 +- + block/vxhs.c | 123 ++++-------------------------------- + configure | 33 +++++++++- + include/block/vxhs_shim.h | 143 ------------------------------------------ + redhat/qemu-kvm.spec.template | 9 --- + 5 files changed, 42 insertions(+), 268 deletions(-) + delete mode 100644 include/block/vxhs_shim.h + +diff --git a/block/Makefile.objs b/block/Makefile.objs +index 037c76b..ac7a1f8 100644 +--- a/block/Makefile.objs ++++ b/block/Makefile.objs +@@ -29,7 +29,7 @@ block-obj-$(CONFIG_LIBNFS) += nfs.o + block-obj-$(CONFIG_CURL) += curl.o + block-obj-$(CONFIG_RBD) += rbd.o + block-obj-$(CONFIG_GLUSTERFS) += gluster.o +-#block-obj-$(CONFIG_VXHS) += vxhs.o ++block-obj-$(CONFIG_VXHS) += vxhs.o + block-obj-$(CONFIG_LIBSSH2) += ssh.o + block-obj-y += accounting.o dirty-bitmap.o + block-obj-y += write-threshold.o +diff --git a/block/vxhs.c b/block/vxhs.c +index 25fea7f..d2a1f4e 100644 +--- a/block/vxhs.c ++++ b/block/vxhs.c +@@ -9,8 +9,7 @@ + */ + + #include "qemu/osdep.h" +-#include "block/vxhs_shim.h" +-#include ++#include + #include + #include "block/block_int.h" + #include "block/qdict.h" +@@ -60,97 +59,6 @@ typedef struct BDRVVXHSState { + char *tlscredsid; /* tlscredsid */ + } BDRVVXHSState; + +-#define LIBVXHS_FULL_PATHNAME "/usr/lib64/qemu/libvxhs.so.1" +-static bool libvxhs_loaded; +-static GModule *libvxhs_handle; +- +-static LibVXHSFuncs libvxhs; +- +-typedef struct LibVXHSSymbols { +- const char *name; +- gpointer *addr; +-} LibVXHSSymbols; +- +-static LibVXHSSymbols libvxhs_symbols[] = { +- {"iio_init", (gpointer *) &libvxhs.iio_init}, +- {"iio_fini", (gpointer *) &libvxhs.iio_fini}, +- {"iio_min_version", (gpointer *) &libvxhs.iio_min_version}, +- {"iio_max_version", (gpointer *) &libvxhs.iio_max_version}, +- {"iio_open", (gpointer *) &libvxhs.iio_open}, +- {"iio_close", (gpointer *) &libvxhs.iio_close}, +- {"iio_writev", (gpointer *) &libvxhs.iio_writev}, +- {"iio_readv", (gpointer *) &libvxhs.iio_readv}, +- {"iio_ioctl", (gpointer *) &libvxhs.iio_ioctl}, +- {NULL} +-}; +- +-static void bdrv_vxhs_set_funcs(GModule *handle, Error **errp) +-{ +- int i = 0; +- while (libvxhs_symbols[i].name) { +- const char *name = libvxhs_symbols[i].name; +- if (!g_module_symbol(handle, name, libvxhs_symbols[i].addr)) { +- error_setg(errp, "%s could not be loaded from libvxhs: %s", +- name, g_module_error()); +- return; +- } +- ++i; +- } +-} +- +-static void bdrv_vxhs_load_libs(Error **errp) +-{ +- Error *local_err = NULL; +- int32_t ver; +- +- if (libvxhs_loaded) { +- return; +- } +- +- if (!g_module_supported()) { +- error_setg(errp, "modules are not supported on this platform: %s", +- g_module_error()); +- return; +- } +- +- libvxhs_handle = g_module_open(LIBVXHS_FULL_PATHNAME, +- G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL); +- if (!libvxhs_handle) { +- error_setg(errp, "The VXHS library from Veritas might not be installed " +- "correctly (%s)", g_module_error()); +- return; +- } +- +- g_module_make_resident(libvxhs_handle); +- +- bdrv_vxhs_set_funcs(libvxhs_handle, &local_err); +- if (local_err) { +- error_propagate(errp, local_err); +- return; +- } +- +- /* Now check to see if the libvxhs we are using here is supported +- * by the loaded version */ +- +- ver = (*libvxhs.iio_min_version)(); +- if (ver > QNIO_VERSION) { +- error_setg(errp, "Trying to use libvxhs version %"PRId32" API, but " +- "only %"PRId32" or newer is supported by %s", +- QNIO_VERSION, ver, LIBVXHS_FULL_PATHNAME); +- return; +- } +- +- ver = (*libvxhs.iio_max_version)(); +- if (ver < QNIO_VERSION) { +- error_setg(errp, "Trying to use libvxhs version %"PRId32" API, but " +- "only %"PRId32" or earlier is supported by %s", +- QNIO_VERSION, ver, LIBVXHS_FULL_PATHNAME); +- return; +- } +- +- libvxhs_loaded = true; +-} +- + static void vxhs_complete_aio_bh(void *opaque) + { + VXHSAIOCB *acb = opaque; +@@ -312,7 +220,7 @@ static void vxhs_parse_filename(const char *filename, QDict *options, + static int vxhs_init_and_ref(void) + { + if (vxhs_ref++ == 0) { +- if ((*libvxhs.iio_init)(QNIO_VERSION, vxhs_iio_callback)) { ++ if (iio_init(QNIO_VERSION, vxhs_iio_callback)) { + return -ENODEV; + } + } +@@ -322,7 +230,7 @@ static int vxhs_init_and_ref(void) + static void vxhs_unref(void) + { + if (--vxhs_ref == 0) { +- (*libvxhs.iio_fini)(); ++ iio_fini(); + } + } + +@@ -392,17 +300,8 @@ static int vxhs_open(BlockDriverState *bs, QDict *options, + char *client_key = NULL; + char *client_cert = NULL; + +- bdrv_vxhs_load_libs(&local_err); +- if (local_err) { +- error_propagate(errp, local_err); +- /* on error, cannot cleanup because the iio_fini() function +- * is not loaded */ +- return -EINVAL; +- } +- + ret = vxhs_init_and_ref(); + if (ret < 0) { +- error_setg(&local_err, "libvxhs iio_init() failed"); + ret = -EINVAL; + goto out; + } +@@ -487,8 +386,8 @@ static int vxhs_open(BlockDriverState *bs, QDict *options, + /* + * Open qnio channel to storage agent if not opened before + */ +- dev_handlep = (*libvxhs.iio_open)(of_vsa_addr, s->vdisk_guid, 0, +- cacert, client_key, client_cert); ++ dev_handlep = iio_open(of_vsa_addr, s->vdisk_guid, 0, ++ cacert, client_key, client_cert); + if (dev_handlep == NULL) { + trace_vxhs_open_iio_open(of_vsa_addr); + ret = -ENODEV; +@@ -552,12 +451,12 @@ static BlockAIOCB *vxhs_aio_rw(BlockDriverState *bs, int64_t sector_num, + + switch (iodir) { + case VDISK_AIO_WRITE: +- ret = (*libvxhs.iio_writev)(dev_handle, acb, qiov->iov, qiov->niov, +- offset, (uint64_t)size, iio_flags); ++ ret = iio_writev(dev_handle, acb, qiov->iov, qiov->niov, ++ offset, (uint64_t)size, iio_flags); + break; + case VDISK_AIO_READ: +- ret = (*libvxhs.iio_readv)(dev_handle, acb, qiov->iov, qiov->niov, +- offset, (uint64_t)size, iio_flags); ++ ret = iio_readv(dev_handle, acb, qiov->iov, qiov->niov, ++ offset, (uint64_t)size, iio_flags); + break; + default: + trace_vxhs_aio_rw_invalid(iodir); +@@ -607,7 +506,7 @@ static void vxhs_close(BlockDriverState *bs) + * Close vDisk device + */ + if (s->vdisk_hostinfo.dev_handle) { +- (*libvxhs.iio_close)(s->vdisk_hostinfo.dev_handle); ++ iio_close(s->vdisk_hostinfo.dev_handle); + s->vdisk_hostinfo.dev_handle = NULL; + } + +@@ -629,7 +528,7 @@ static int64_t vxhs_get_vdisk_stat(BDRVVXHSState *s) + int ret = 0; + void *dev_handle = s->vdisk_hostinfo.dev_handle; + +- ret = (*libvxhs.iio_ioctl)(dev_handle, IOR_VDISK_STAT, &vdisk_size, 0); ++ ret = iio_ioctl(dev_handle, IOR_VDISK_STAT, &vdisk_size, 0); + if (ret < 0) { + trace_vxhs_get_vdisk_stat_err(s->vdisk_guid, ret, errno); + return -EIO; +diff --git a/configure b/configure +index 858b456..6d61b14 100755 +--- a/configure ++++ b/configure +@@ -3428,7 +3428,7 @@ else + glib_req_ver=2.22 + fi + glib_modules=gthread-2.0 +-if test "$modules" = yes -o "$vxhs" = yes; then ++if test "$modules" = yes; then + glib_modules="$glib_modules gmodule-export-2.0" + fi + +@@ -5391,6 +5391,33 @@ if compile_prog "" "" ; then + fi + + ########################################## ++# Veritas HyperScale block driver VxHS ++# Check if libvxhs is installed ++ ++if test "$vxhs" != "no" ; then ++ cat > $TMPC < ++#include ++ ++void *vxhs_callback; ++ ++int main(void) { ++ iio_init(QNIO_VERSION, vxhs_callback); ++ return 0; ++} ++EOF ++ vxhs_libs="-lvxhs -lssl" ++ if compile_prog "" "$vxhs_libs" ; then ++ vxhs=yes ++ else ++ if test "$vxhs" = "yes" ; then ++ feature_not_found "vxhs block device" "Install libvxhs See github" ++ fi ++ vxhs=no ++ fi ++fi ++ ++########################################## + # check for _Static_assert() + + have_static_assert=no +@@ -6707,8 +6734,8 @@ if test "$pthread_setname_np" = "yes" ; then + fi + + if test "$vxhs" = "yes" ; then +- echo "CONFIG_VXHS=m" >> $config_host_mak +- echo "VXHS_LIBS= -lssl" >> $config_host_mak ++ echo "CONFIG_VXHS=y" >> $config_host_mak ++ echo "VXHS_LIBS=$vxhs_libs" >> $config_host_mak + fi + + if test "$bochs" = "yes" ; then +diff --git a/include/block/vxhs_shim.h b/include/block/vxhs_shim.h +deleted file mode 100644 +index 42519ae..0000000 +--- a/include/block/vxhs_shim.h ++++ /dev/null +@@ -1,143 +0,0 @@ +-/* +- * Network IO library for VxHS QEMU block driver (Veritas Technologies) +- * +- * This work is licensed under the terms of the GNU GPL, version 2. See +- * the COPYING file in the top-level directory. +- * +- * Contributions after 2014-08-15 are licensed under the terms of the +- * GNU GPL, version 2 or (at your option) any later version. +- */ +- +-#ifndef QNIO_API_H +-#define QNIO_API_H +- +-#include +- +-/* +- * Bump up the version everytime this file is modified +- */ +-#define QNIO_VERSION 34 +- +-/* +- * These are the opcodes referenced by callback routine. +- */ +-#define IRP_READ_REQUEST 0x1FFF +-#define IRP_WRITE_REQUEST 0x2FFF +-#define IRP_VDISK_CHECK_IO_FAILOVER_READY 2020 +- +-/* +- * opcodes for iio_ioctl. +- */ +-#define IOR_VDISK_STAT 1005 +- +-/* +- * Error values for iio_cb_t callback function. +- */ +-#define QNIOERROR_HUP 901 /* Retriable error */ +-#define QNIOERROR_NOCONN 902 /* Non-retriable error */ +- +- +-/* Operation Flags */ +-#define IIO_FLAG_ASYNC 0x0001 /* Do an async send */ +- +-/* +- * INPUT: +- * ctx - opaque context +- * opcode - Operation +- * error - 0 for sucess, non-zero for failure. +- * RETURNS: +- * void +- * DESCRIPTION: +- * This callback is called, after Async request completes. +- * +- * CONTEXT: +- * The callback should be wait-free. +- */ +-typedef void (*iio_cb_t) (void *ctx, uint32_t opcode, uint32_t error); +- +-typedef struct LibVXHSFuncs { +-/* +- * RETURNS: +- * 0 for sucess, non-zero for failure. +- * DESCRIPTION: +- * Intilize the library state. This should be called at the +- * begining before issuing any library call. +- */ +- int (*iio_init)(int32_t version, iio_cb_t cb); +-/* +- * RETURNS: +- * void +- * DESCRIPTION: +- * Relinquish library resources. This should be called on the +- * close of last open device. +- */ +- void (*iio_fini)(void); +-/* +- * DESCRIPTION: +- * Returns minimum QNIO API version supported by library. +- */ +- int32_t (*iio_min_version)(void); +-/* +- * DESCRIPTION: +- * Returns maximum QNIO API version supported by library. +- */ +- int32_t (*iio_max_version)(void); +-/* +- * INPUT: +- * uri - const string of the format of://:port +- * devid - Device ID. +- * flags - currently unused, this must be set to 0 +- * cacert - CA certificates file in PEM format +- * client_key - Client private key file in PEM format +- * client_cert - Client certificate file in PEM format +- * RETURNS: +- * opeque device handle on success, NULL on failure. +- * DESCRIPTION: +- * This call returns device handle on success. Returns NULL on +- * failure with errno set +- * errno can be one of: +- * ENODEV - remote device not found +- * EBADF - Unable to open communication channel. +- * EBUSY - The call cannot be completed right now +- */ +- void *(*iio_open)(const char *uri, const char *devid, uint32_t flags, +- const char *cacert, const char *client_key, +- const char *client_cert); +-/* +- * Close the device. +- * For every matching iio_open() there should be a matching iio_close() +- * The last close free all data structures associated with the device. +- */ +- int32_t (*iio_close)(void *dev_handle); +-/* +- * INPUT: +- * dev_handle - device descriptor on which read/write needs to be performed +- * ctx - an opaque context that is not interpreted This is set for +- * async calls only. It can be NULL. +- * iov - an array of iovecs (This is a scatter gather operation) +- * iovcnt - the number of iovecs +- * offset - an offset to perform the write +- * size - I/O size +- * flags - can be one of +- * IIO_FLAG_ASYNC - indicating this is a aio call. +- * RETURNS: +- * -1 on error, sets errno +- * EBADF - the remote fd is bad +- * EBUSY - The call cannot be completed right now +- * EPIPE - the channel got disconnected, call back would be called in +- * addition to this. +- */ +- int32_t (*iio_writev)(void *dev_handle, void *ctx, struct iovec *iov, +- int iovcnt, uint64_t offset, uint64_t size, +- uint32_t flags); +- +- int32_t (*iio_readv)(void *dev_handle, void *ctx, struct iovec *iov, +- int iovcnt, uint64_t offset, uint64_t size, +- uint32_t flags); +- +- int32_t (*iio_ioctl)(void *dev_handle, uint32_t opcode, void *opaque, +- uint32_t flags); +- +-} LibVXHSFuncs; +- +-#endif +-- +1.8.3.1 + diff --git a/SOURCES/kvm-Fix-heap-overflow-in-ip_reass-on-big-packet-input.patch b/SOURCES/kvm-Fix-heap-overflow-in-ip_reass-on-big-packet-input.patch index d74ef55..bb26025 100644 --- a/SOURCES/kvm-Fix-heap-overflow-in-ip_reass-on-big-packet-input.patch +++ b/SOURCES/kvm-Fix-heap-overflow-in-ip_reass-on-big-packet-input.patch @@ -1,7 +1,7 @@ -From e356fafe02c3ce32bad9b8d96ae9cfd6fcbb40a9 Mon Sep 17 00:00:00 2001 +From 486e74dd9b8515f478698fee494086b339015d51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Date: Wed, 31 Jul 2019 18:45:29 +0100 -Subject: [PATCH 5/5] Fix heap overflow in ip_reass on big packet input +Subject: [PATCH 14/14] Fix heap overflow in ip_reass on big packet input MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -10,7 +10,7 @@ RH-Author: Philippe Mathieu-Daudé Message-id: <20190731184529.21905-2-philmd@redhat.com> Patchwork-id: 89820 O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 1/1] Fix heap overflow in ip_reass on big packet input -Bugzilla: 1734750 +Bugzilla: 1734751 RH-Acked-by: Marc-André Lureau RH-Acked-by: Stefan Hajnoczi RH-Acked-by: Thomas Huth diff --git a/SOURCES/kvm-Introduce-kvm_arch_destroy_vcpu.patch b/SOURCES/kvm-Introduce-kvm_arch_destroy_vcpu.patch new file mode 100644 index 0000000..606b719 --- /dev/null +++ b/SOURCES/kvm-Introduce-kvm_arch_destroy_vcpu.patch @@ -0,0 +1,182 @@ +From e7dc49f6bf6fd242b5b7a83bc270664a1ca45879 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Mon, 22 Jul 2019 18:22:08 +0100 +Subject: [PATCH 27/39] KVM: Introduce kvm_arch_destroy_vcpu() + +RH-Author: Paolo Bonzini +Message-id: <20190722182220.19374-7-pbonzini@redhat.com> +Patchwork-id: 89623 +O-Subject: [RHEL-8.1.0 PATCH qemu-kvm v3 06/18] KVM: Introduce kvm_arch_destroy_vcpu() +Bugzilla: 1689269 +RH-Acked-by: Peter Xu +RH-Acked-by: Laurent Vivier +RH-Acked-by: Dr. David Alan Gilbert + +From: Liran Alon + +Simiar to how kvm_init_vcpu() calls kvm_arch_init_vcpu() to perform +arch-dependent initialisation, introduce kvm_arch_destroy_vcpu() +to be called from kvm_destroy_vcpu() to perform arch-dependent +destruction. + +This was added because some architectures (Such as i386) +currently do not free memory that it have allocated in +kvm_arch_init_vcpu(). + +Suggested-by: Maran Wilson +Reviewed-by: Maran Wilson +Signed-off-by: Liran Alon +Message-Id: <20190619162140.133674-3-liran.alon@oracle.com> +Signed-off-by: Paolo Bonzini +(cherry picked from commit b1115c99919cf158bb859865f14c3198a0e6f679) +Signed-off-by: Danilo C. L. de Paula +--- + accel/kvm/kvm-all.c | 5 +++++ + include/sysemu/kvm.h | 1 + + target/arm/kvm32.c | 5 +++++ + target/arm/kvm64.c | 5 +++++ + target/i386/kvm.c | 12 ++++++++++++ + target/mips/kvm.c | 5 +++++ + target/ppc/kvm.c | 5 +++++ + target/s390x/kvm.c | 10 ++++++++++ + 8 files changed, 48 insertions(+) + +diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c +index 3a7c8a3..a939b26 100644 +--- a/accel/kvm/kvm-all.c ++++ b/accel/kvm/kvm-all.c +@@ -290,6 +290,11 @@ int kvm_destroy_vcpu(CPUState *cpu) + + DPRINTF("kvm_destroy_vcpu\n"); + ++ ret = kvm_arch_destroy_vcpu(cpu); ++ if (ret < 0) { ++ goto err; ++ } ++ + mmap_size = kvm_ioctl(s, KVM_GET_VCPU_MMAP_SIZE, 0); + if (mmap_size < 0) { + ret = mmap_size; +diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h +index 3d8f294..a5a6dff 100644 +--- a/include/sysemu/kvm.h ++++ b/include/sysemu/kvm.h +@@ -372,6 +372,7 @@ int kvm_arch_put_registers(CPUState *cpu, int level); + int kvm_arch_init(MachineState *ms, KVMState *s); + + int kvm_arch_init_vcpu(CPUState *cpu); ++int kvm_arch_destroy_vcpu(CPUState *cpu); + + bool kvm_vcpu_id_is_valid(int vcpu_id); + +diff --git a/target/arm/kvm32.c b/target/arm/kvm32.c +index 1740cda..056f016 100644 +--- a/target/arm/kvm32.c ++++ b/target/arm/kvm32.c +@@ -237,6 +237,11 @@ int kvm_arch_init_vcpu(CPUState *cs) + return kvm_arm_init_cpreg_list(cpu); + } + ++int kvm_arch_destroy_vcpu(CPUState *cs) ++{ ++ return 0; ++} ++ + typedef struct Reg { + uint64_t id; + int offset; +diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c +index e0b8246..c9c761e 100644 +--- a/target/arm/kvm64.c ++++ b/target/arm/kvm64.c +@@ -549,6 +549,11 @@ int kvm_arch_init_vcpu(CPUState *cs) + return kvm_arm_init_cpreg_list(cpu); + } + ++int kvm_arch_destroy_vcpu(CPUState *cs) ++{ ++ return 0; ++} ++ + bool kvm_arm_reg_syncs_via_cpreg_list(uint64_t regidx) + { + /* Return true if the regidx is a register we should synchronize +diff --git a/target/i386/kvm.c b/target/i386/kvm.c +index 8e861a1..305809f 100644 +--- a/target/i386/kvm.c ++++ b/target/i386/kvm.c +@@ -1196,6 +1196,18 @@ int kvm_arch_init_vcpu(CPUState *cs) + return r; + } + ++int kvm_arch_destroy_vcpu(CPUState *cs) ++{ ++ X86CPU *cpu = X86_CPU(cs); ++ ++ if (cpu->kvm_msr_buf) { ++ g_free(cpu->kvm_msr_buf); ++ cpu->kvm_msr_buf = NULL; ++ } ++ ++ return 0; ++} ++ + void kvm_arch_reset_vcpu(X86CPU *cpu) + { + CPUX86State *env = &cpu->env; +diff --git a/target/mips/kvm.c b/target/mips/kvm.c +index 8e72850..938f8f1 100644 +--- a/target/mips/kvm.c ++++ b/target/mips/kvm.c +@@ -91,6 +91,11 @@ int kvm_arch_init_vcpu(CPUState *cs) + return ret; + } + ++int kvm_arch_destroy_vcpu(CPUState *cs) ++{ ++ return 0; ++} ++ + void kvm_mips_reset_vcpu(MIPSCPU *cpu) + { + CPUMIPSState *env = &cpu->env; +diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c +index 058dcbe..b9858fa 100644 +--- a/target/ppc/kvm.c ++++ b/target/ppc/kvm.c +@@ -607,6 +607,11 @@ int kvm_arch_init_vcpu(CPUState *cs) + return ret; + } + ++int kvm_arch_destroy_vcpu(CPUState *cs) ++{ ++ return 0; ++} ++ + static void kvm_sw_tlb_put(PowerPCCPU *cpu) + { + CPUPPCState *env = &cpu->env; +diff --git a/target/s390x/kvm.c b/target/s390x/kvm.c +index 1d6cc33..0814333 100644 +--- a/target/s390x/kvm.c ++++ b/target/s390x/kvm.c +@@ -370,6 +370,16 @@ int kvm_arch_init_vcpu(CPUState *cs) + return 0; + } + ++int kvm_arch_destroy_vcpu(CPUState *cs) ++{ ++ S390CPU *cpu = S390_CPU(cs); ++ ++ g_free(cpu->irqstate); ++ cpu->irqstate = NULL; ++ ++ return 0; ++} ++ + void kvm_s390_reset_vcpu(S390CPU *cpu) + { + CPUState *cs = CPU(cpu); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-Introduce-new-no_guest_reset-parameter-for-usb-host-.patch b/SOURCES/kvm-Introduce-new-no_guest_reset-parameter-for-usb-host-.patch index 68e8ff2..bed1b54 100644 --- a/SOURCES/kvm-Introduce-new-no_guest_reset-parameter-for-usb-host-.patch +++ b/SOURCES/kvm-Introduce-new-no_guest_reset-parameter-for-usb-host-.patch @@ -1,14 +1,14 @@ -From b52bdeda7653879d007bbd2ee776ec5201d0c786 Mon Sep 17 00:00:00 2001 +From 7efd1d899d2478ad9fffcf0584907f38cd6d20ff Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 4 Jun 2019 05:12:43 +0100 -Subject: [PATCH 1/5] Introduce new "no_guest_reset" parameter for usb-host +Subject: [PATCH 1/8] Introduce new "no_guest_reset" parameter for usb-host device RH-Author: Gerd Hoffmann Message-id: <20190604051246.11374-2-kraxel@redhat.com> Patchwork-id: 88470 O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 1/4] Introduce new "no_guest_reset" parameter for usb-host device -Bugzilla: 1719228 +Bugzilla: 1713677 RH-Acked-by: Dr. David Alan Gilbert RH-Acked-by: Max Reitz RH-Acked-by: Danilo de Paula diff --git a/SOURCES/kvm-RHEL-disable-hostmem-memfd.patch b/SOURCES/kvm-RHEL-disable-hostmem-memfd.patch new file mode 100644 index 0000000..5781a40 --- /dev/null +++ b/SOURCES/kvm-RHEL-disable-hostmem-memfd.patch @@ -0,0 +1,56 @@ +From bf545f4a8f40a4ac8f6d63d887a63d9f08329eb6 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= +Date: Wed, 14 Aug 2019 08:52:10 +0100 +Subject: [PATCH 10/10] RHEL: disable hostmem-memfd +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Marc-André Lureau +Message-id: <20190814085210.18462-1-marcandre.lureau@redhat.com> +Patchwork-id: 89974 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH] RHEL: disable hostmem-memfd +Bugzilla: 1740797 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: John Snow + +BZ: https://bugzilla.redhat.com/show_bug.cgi?id=1740797 +BRANCH: rhel8/rhel-8.1.0 +UPSTREAM: n/a (downstream only) +BREW: 23060214 + +Signed-off-by: Marc-André Lureau +Signed-off-by: Danilo C. L. de Paula +--- + backends/Makefile.objs | 3 ++- + util/memfd.c | 2 +- + 2 files changed, 3 insertions(+), 2 deletions(-) + +diff --git a/backends/Makefile.objs b/backends/Makefile.objs +index ad7c032..673fc55 100644 +--- a/backends/Makefile.objs ++++ b/backends/Makefile.objs +@@ -15,4 +15,5 @@ common-obj-$(call land,$(CONFIG_VHOST_USER),$(CONFIG_LINUX)) += \ + cryptodev-vhost-user.o + endif + +-common-obj-$(CONFIG_LINUX) += hostmem-memfd.o ++# RHEL: disable memfd ++# common-obj-$(CONFIG_LINUX) += hostmem-memfd.o +diff --git a/util/memfd.c b/util/memfd.c +index b3ecbac..9312653 100644 +--- a/util/memfd.c ++++ b/util/memfd.c +@@ -202,7 +202,7 @@ bool qemu_memfd_alloc_check(void) + */ + bool qemu_memfd_check(void) + { +-#ifdef CONFIG_LINUX ++#if 0 /* RHEL: memfd support disabled */ + static int memfd_check = MEMFD_TODO; + + if (memfd_check == MEMFD_TODO) { +-- +1.8.3.1 + diff --git a/SOURCES/kvm-Revert-i386-Add-CPUID-bit-for-PCONFIG.patch b/SOURCES/kvm-Revert-i386-Add-CPUID-bit-for-PCONFIG.patch new file mode 100644 index 0000000..3d2bac2 --- /dev/null +++ b/SOURCES/kvm-Revert-i386-Add-CPUID-bit-for-PCONFIG.patch @@ -0,0 +1,58 @@ +From 6a1d536006d9b6f888bd56ba1ff03c6e66acb020 Mon Sep 17 00:00:00 2001 +From: "plai@redhat.com" +Date: Wed, 3 Apr 2019 15:54:34 +0100 +Subject: [PATCH 10/10] Revert "i386: Add CPUID bit for PCONFIG" + +RH-Author: plai@redhat.com +Message-id: <1554306874-28796-11-git-send-email-plai@redhat.com> +Patchwork-id: 85388 +O-Subject: [RHEL8.1 qemu-kvm PATCH resend 10/10] Revert "i386: Add CPUID bit for PCONFIG" +Bugzilla: 1561761 +RH-Acked-by: Eduardo Habkost +RH-Acked-by: Igor Mammedov +RH-Acked-by: Michael S. Tsirkin + +From: Robert Hoo + +This reverts commit 5131dc433df54b37e8e918d8fba7fe10344e7a7b. +For new instruction 'PCONFIG' will not be exposed to guest. + +Signed-off-by: Robert Hoo +Message-Id: <1545227081-213696-3-git-send-email-robert.hu@linux.intel.com> +Signed-off-by: Paolo Bonzini +(cherry picked from commit 712f807e1965c8f1f1da5bbec2b92a8c540e6631) +Signed-off-by: Paul Lai +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.c | 2 +- + target/i386/cpu.h | 1 - + 2 files changed, 1 insertion(+), 2 deletions(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index ad369be..8e63db6 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -1042,7 +1042,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, +- NULL, NULL, "pconfig", NULL, ++ NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, "spec-ctrl", "stibp", + NULL, "arch-capabilities", NULL, "ssbd", +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index 63f692f..3ae0e8c 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -687,7 +687,6 @@ typedef uint32_t FeatureWordArray[FEATURE_WORDS]; + + #define CPUID_7_0_EDX_AVX512_4VNNIW (1U << 2) /* AVX512 Neural Network Instructions */ + #define CPUID_7_0_EDX_AVX512_4FMAPS (1U << 3) /* AVX512 Multiply Accumulation Single Precision */ +-#define CPUID_7_0_EDX_PCONFIG (1U << 18) /* Platform Configuration */ + #define CPUID_7_0_EDX_SPEC_CTRL (1U << 26) /* Speculation Control */ + #define CPUID_7_0_EDX_ARCH_CAPABILITIES (1U << 29) /*Arch Capabilities*/ + #define CPUID_7_0_EDX_SPEC_CTRL_SSBD (1U << 31) /* Speculative Store Bypass Disable */ +-- +1.8.3.1 + diff --git a/SOURCES/kvm-Use-KVM_GET_MSR_INDEX_LIST-for-MSR_IA32_ARCH_CAP.patch b/SOURCES/kvm-Use-KVM_GET_MSR_INDEX_LIST-for-MSR_IA32_ARCH_CAP.patch index 12ea887..14dccc0 100644 --- a/SOURCES/kvm-Use-KVM_GET_MSR_INDEX_LIST-for-MSR_IA32_ARCH_CAP.patch +++ b/SOURCES/kvm-Use-KVM_GET_MSR_INDEX_LIST-for-MSR_IA32_ARCH_CAP.patch @@ -1,17 +1,18 @@ -From ff712825c31188b19ece7b9388630f6456bb10db Mon Sep 17 00:00:00 2001 -From: "plai@redhat.com" -Date: Tue, 20 Aug 2019 00:24:37 +0100 -Subject: [PATCH 6/9] kvm: Use KVM_GET_MSR_INDEX_LIST for +From e6e62ad1e8a33076b67b19ce5f03ea6ca6571eef Mon Sep 17 00:00:00 2001 +From: Eduardo Habkost +Date: Thu, 9 May 2019 22:43:17 +0100 +Subject: [PATCH 1/2] kvm: Use KVM_GET_MSR_INDEX_LIST for MSR_IA32_ARCH_CAPABILITIES support -RH-Author: plai@redhat.com -Message-id: <1566260680-20995-7-git-send-email-plai@redhat.com> -Patchwork-id: 90065 -O-Subject: [RHEL8.0 qemu-kvm PATCH v3 6/9] kvm: Use KVM_GET_MSR_INDEX_LIST for MSR_IA32_ARCH_CAPABILITIES support -Bugzilla: 1718235 -RH-Acked-by: Eduardo Habkost -RH-Acked-by: John Snow +RH-Author: Eduardo Habkost +Message-id: <20190509224318.23376-2-ehabkost@redhat.com> +Patchwork-id: 87251 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 1/2] kvm: Use KVM_GET_MSR_INDEX_LIST for MSR_IA32_ARCH_CAPABILITIES support +Bugzilla: 1707706 +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Paolo Bonzini RH-Acked-by: Igor Mammedov +RH-Acked-by: Bandan Das From: Bandan Das @@ -25,14 +26,14 @@ Signed-off-by: Bandan Das Message-Id: Signed-off-by: Eduardo Habkost (cherry picked from commit aec5e9c3a94cf8b7920f59bef69a6f426092c4a0) -Signed-off-by: Paul Lai +Signed-off-by: Eduardo Habkost Signed-off-by: Danilo C. L. de Paula --- target/i386/kvm.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/target/i386/kvm.c b/target/i386/kvm.c -index d2cb91e..6f661b2 100644 +index f1626a4..e3e8c78 100644 --- a/target/i386/kvm.c +++ b/target/i386/kvm.c @@ -94,6 +94,7 @@ static bool has_msr_xss; diff --git a/SOURCES/kvm-block-Add-bdrv_get_request_alignment.patch b/SOURCES/kvm-block-Add-bdrv_get_request_alignment.patch new file mode 100644 index 0000000..42c08e1 --- /dev/null +++ b/SOURCES/kvm-block-Add-bdrv_get_request_alignment.patch @@ -0,0 +1,65 @@ +From f551451a4b9975121424cb0837df67d31d2528dc Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Tue, 23 Jul 2019 14:45:45 +0100 +Subject: [PATCH 07/14] block: Add bdrv_get_request_alignment() + +RH-Author: Max Reitz +Message-id: <20190723144546.23701-7-mreitz@redhat.com> +Patchwork-id: 89653 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 6/7] block: Add bdrv_get_request_alignment() +Bugzilla: 1678979 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Stefano Garzarella +RH-Acked-by: John Snow + +From: Eric Blake + +The next patch needs access to a device's minimum permitted +alignment, since NBD wants to advertise this to clients. Add +an accessor function, borrowing from blk_get_max_transfer() +for accessing a backend's block limits. + +Signed-off-by: Eric Blake +Reviewed-by: Vladimir Sementsov-Ogievskiy +Message-Id: <20190329042750.14704-6-eblake@redhat.com> +(cherry picked from commit 4841211e0d1628cd386b35835676d7f6f9a4fa9d) +Signed-off-by: Max Reitz +Signed-off-by: Danilo C. L. de Paula +--- + block/block-backend.c | 7 +++++++ + include/sysemu/block-backend.h | 1 + + 2 files changed, 8 insertions(+) + +diff --git a/block/block-backend.c b/block/block-backend.c +index 7ae5832..0d623e4 100644 +--- a/block/block-backend.c ++++ b/block/block-backend.c +@@ -1807,6 +1807,13 @@ int blk_get_flags(BlockBackend *blk) + } + } + ++/* Returns the minimum request alignment, in bytes; guaranteed nonzero */ ++uint32_t blk_get_request_alignment(BlockBackend *blk) ++{ ++ BlockDriverState *bs = blk_bs(blk); ++ return bs ? bs->bl.request_alignment : BDRV_SECTOR_SIZE; ++} ++ + /* Returns the maximum transfer length, in bytes; guaranteed nonzero */ + uint32_t blk_get_max_transfer(BlockBackend *blk) + { +diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h +index 830d873..20f8bbb 100644 +--- a/include/sysemu/block-backend.h ++++ b/include/sysemu/block-backend.h +@@ -176,6 +176,7 @@ bool blk_is_available(BlockBackend *blk); + void blk_lock_medium(BlockBackend *blk, bool locked); + void blk_eject(BlockBackend *blk, bool eject_flag); + int blk_get_flags(BlockBackend *blk); ++uint32_t blk_get_request_alignment(BlockBackend *blk); + uint32_t blk_get_max_transfer(BlockBackend *blk); + int blk_get_max_iov(BlockBackend *blk); + void blk_set_guest_block_size(BlockBackend *blk, int align); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-block-Fix-AioContext-switch-for-bs-drv-NULL.patch b/SOURCES/kvm-block-Fix-AioContext-switch-for-bs-drv-NULL.patch new file mode 100644 index 0000000..b7241e8 --- /dev/null +++ b/SOURCES/kvm-block-Fix-AioContext-switch-for-bs-drv-NULL.patch @@ -0,0 +1,118 @@ +From 808d2c94f53b9b29f44c2c5d9baea66d63ceddfc Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Wed, 14 Aug 2019 09:20:43 +0100 +Subject: [PATCH 07/10] block: Fix AioContext switch for bs->drv == NULL + +RH-Author: Kevin Wolf +Message-id: <20190814092043.15421-2-kwolf@redhat.com> +Patchwork-id: 89976 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 1/1] block: Fix AioContext switch for bs->drv == NULL +Bugzilla: 1716347 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Max Reitz +RH-Acked-by: John Snow + +Even for block nodes with bs->drv == NULL, we can't just ignore a +bdrv_set_aio_context() call. Leaving the node in its old context can +mean that it's still in an iothread context in bdrv_close_all() during +shutdown, resulting in an attempted unlock of the AioContext lock which +we don't hold. + +This is an example stack trace of a related crash: + + #0 0x00007ffff59da57f in raise () at /lib64/libc.so.6 + #1 0x00007ffff59c4895 in abort () at /lib64/libc.so.6 + #2 0x0000555555b97b1e in error_exit (err=, msg=msg@entry=0x555555d386d0 <__func__.19059> "qemu_mutex_unlock_impl") at util/qemu-thread-posix.c:36 + #3 0x0000555555b97f7f in qemu_mutex_unlock_impl (mutex=mutex@entry=0x5555568002f0, file=file@entry=0x555555d378df "util/async.c", line=line@entry=507) at util/qemu-thread-posix.c:97 + #4 0x0000555555b92f55 in aio_context_release (ctx=ctx@entry=0x555556800290) at util/async.c:507 + #5 0x0000555555b05cf8 in bdrv_prwv_co (child=child@entry=0x7fffc80012f0, offset=offset@entry=131072, qiov=qiov@entry=0x7fffffffd4f0, is_write=is_write@entry=true, flags=flags@entry=0) + at block/io.c:833 + #6 0x0000555555b060a9 in bdrv_pwritev (qiov=0x7fffffffd4f0, offset=131072, child=0x7fffc80012f0) at block/io.c:990 + #7 0x0000555555b060a9 in bdrv_pwrite (child=0x7fffc80012f0, offset=131072, buf=, bytes=) at block/io.c:990 + #8 0x0000555555ae172b in qcow2_cache_entry_flush (bs=bs@entry=0x555556810680, c=c@entry=0x5555568cc740, i=i@entry=0) at block/qcow2-cache.c:51 + #9 0x0000555555ae18dd in qcow2_cache_write (bs=bs@entry=0x555556810680, c=0x5555568cc740) at block/qcow2-cache.c:248 + #10 0x0000555555ae15de in qcow2_cache_flush (bs=0x555556810680, c=) at block/qcow2-cache.c:259 + #11 0x0000555555ae16b1 in qcow2_cache_flush_dependency (c=0x5555568a1700, c=0x5555568a1700, bs=0x555556810680) at block/qcow2-cache.c:194 + #12 0x0000555555ae16b1 in qcow2_cache_entry_flush (bs=bs@entry=0x555556810680, c=c@entry=0x5555568a1700, i=i@entry=0) at block/qcow2-cache.c:194 + #13 0x0000555555ae18dd in qcow2_cache_write (bs=bs@entry=0x555556810680, c=0x5555568a1700) at block/qcow2-cache.c:248 + #14 0x0000555555ae15de in qcow2_cache_flush (bs=bs@entry=0x555556810680, c=) at block/qcow2-cache.c:259 + #15 0x0000555555ad242c in qcow2_inactivate (bs=bs@entry=0x555556810680) at block/qcow2.c:2124 + #16 0x0000555555ad2590 in qcow2_close (bs=0x555556810680) at block/qcow2.c:2153 + #17 0x0000555555ab0c62 in bdrv_close (bs=0x555556810680) at block.c:3358 + #18 0x0000555555ab0c62 in bdrv_delete (bs=0x555556810680) at block.c:3542 + #19 0x0000555555ab0c62 in bdrv_unref (bs=0x555556810680) at block.c:4598 + #20 0x0000555555af4d72 in blk_remove_bs (blk=blk@entry=0x5555568103d0) at block/block-backend.c:785 + #21 0x0000555555af4dbb in blk_remove_all_bs () at block/block-backend.c:483 + #22 0x0000555555aae02f in bdrv_close_all () at block.c:3412 + #23 0x00005555557f9796 in main (argc=, argv=, envp=) at vl.c:4776 + +The reproducer I used is a qcow2 image on gluster volume, where the +virtual disk size (4 GB) is larger than the gluster volume size (64M), +so we can easily trigger an ENOSPC. This backend is assigned to a +virtio-blk device using an iothread, and then from the guest a +'dd if=/dev/zero of=/dev/vda bs=1G count=1' causes the VM to stop +because of an I/O error. qemu_gluster_co_flush_to_disk() sets +bs->drv = NULL on error, so when virtio-blk stops the dataplane, the +block nodes stay in the iothread AioContext. A 'quit' monitor command +issued from this paused state crashes the process. + +Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1631227 +Cc: qemu-stable@nongnu.org +Signed-off-by: Kevin Wolf +Reviewed-by: Eric Blake +Reviewed-by: Max Reitz +Reviewed-by: Stefano Garzarella +(cherry picked from commit 1bffe1ae7a7b707c3a14ea2ccd00d3609d3ce4d8) +Signed-off-by: Kevin Wolf +Signed-off-by: Danilo C. L. de Paula +--- + block.c | 12 ++---------- + 1 file changed, 2 insertions(+), 10 deletions(-) + +diff --git a/block.c b/block.c +index 8f3ceea..37af100 100644 +--- a/block.c ++++ b/block.c +@@ -4923,10 +4923,6 @@ void bdrv_detach_aio_context(BlockDriverState *bs) + BdrvAioNotifier *baf, *baf_tmp; + BdrvChild *child; + +- if (!bs->drv) { +- return; +- } +- + assert(!bs->walking_aio_notifiers); + bs->walking_aio_notifiers = true; + QLIST_FOREACH_SAFE(baf, &bs->aio_notifiers, list, baf_tmp) { +@@ -4941,7 +4937,7 @@ void bdrv_detach_aio_context(BlockDriverState *bs) + */ + bs->walking_aio_notifiers = false; + +- if (bs->drv->bdrv_detach_aio_context) { ++ if (bs->drv && bs->drv->bdrv_detach_aio_context) { + bs->drv->bdrv_detach_aio_context(bs); + } + QLIST_FOREACH(child, &bs->children, next) { +@@ -4960,10 +4956,6 @@ void bdrv_attach_aio_context(BlockDriverState *bs, + BdrvAioNotifier *ban, *ban_tmp; + BdrvChild *child; + +- if (!bs->drv) { +- return; +- } +- + if (bs->quiesce_counter) { + aio_disable_external(new_context); + } +@@ -4973,7 +4965,7 @@ void bdrv_attach_aio_context(BlockDriverState *bs, + QLIST_FOREACH(child, &bs->children, next) { + bdrv_attach_aio_context(child->bs, new_context); + } +- if (bs->drv->bdrv_attach_aio_context) { ++ if (bs->drv && bs->drv->bdrv_attach_aio_context) { + bs->drv->bdrv_attach_aio_context(bs, new_context); + } + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-block-Fix-AioContext-switch-for-drained-node.patch b/SOURCES/kvm-block-Fix-AioContext-switch-for-drained-node.patch new file mode 100644 index 0000000..4306d18 --- /dev/null +++ b/SOURCES/kvm-block-Fix-AioContext-switch-for-drained-node.patch @@ -0,0 +1,57 @@ +From ee7b9d7867634d052f2c695fcebf68f585fe59c0 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Wed, 14 Aug 2019 08:42:27 +0100 +Subject: [PATCH 04/10] block: Fix AioContext switch for drained node + +RH-Author: Kevin Wolf +Message-id: <20190814084229.6458-4-kwolf@redhat.com> +Patchwork-id: 89969 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 3/5] block: Fix AioContext switch for drained node +Bugzilla: 1716349 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Max Reitz +RH-Acked-by: Paolo Bonzini + +When a drained node changes its AioContext, we need to move its +aio_disable_external() to the new context, too. + +Without this fix, drain_end will try to reenable the new context, which +has never been disabled, so an assertion failure is triggered. + +Signed-off-by: Kevin Wolf +Reviewed-by: Eric Blake +(cherry picked from commit e64f25f30b80a71bd4e409ed518c39eeb5905166) +Signed-off-by: Kevin Wolf +Signed-off-by: Danilo C. L. de Paula +--- + block.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/block.c b/block.c +index 82b16df..9d9b8a9 100644 +--- a/block.c ++++ b/block.c +@@ -4948,6 +4948,9 @@ void bdrv_detach_aio_context(BlockDriverState *bs) + bdrv_detach_aio_context(child->bs); + } + ++ if (bs->quiesce_counter) { ++ aio_enable_external(bs->aio_context); ++ } + bs->aio_context = NULL; + } + +@@ -4961,6 +4964,10 @@ void bdrv_attach_aio_context(BlockDriverState *bs, + return; + } + ++ if (bs->quiesce_counter) { ++ aio_disable_external(new_context); ++ } ++ + bs->aio_context = new_context; + + QLIST_FOREACH(child, &bs->children, next) { +-- +1.8.3.1 + diff --git a/SOURCES/kvm-block-Fix-invalidate_cache-error-path-for-parent-act.patch b/SOURCES/kvm-block-Fix-invalidate_cache-error-path-for-parent-act.patch new file mode 100644 index 0000000..65fbd97 --- /dev/null +++ b/SOURCES/kvm-block-Fix-invalidate_cache-error-path-for-parent-act.patch @@ -0,0 +1,69 @@ +From 6123c29fcf385010a683061fd7f948f256713b48 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Fri, 17 May 2019 14:23:15 +0100 +Subject: [PATCH 4/5] block: Fix invalidate_cache error path for parent + activation + +RH-Author: Kevin Wolf +Message-id: <20190517142315.16266-2-kwolf@redhat.com> +Patchwork-id: 88024 +O-Subject: [RHEL-8.1 qemu-kvm PATCH 1/1] block: Fix invalidate_cache error path for parent activation +Bugzilla: 1673010 +RH-Acked-by: John Snow +RH-Acked-by: Sergio Lopez Pascual +RH-Acked-by: Stefano Garzarella + +bdrv_co_invalidate_cache() clears the BDRV_O_INACTIVE flag before +actually activating a node so that the correct permissions etc. are +taken. In case of errors, the flag must be restored so that the next +call to bdrv_co_invalidate_cache() retries activation. + +Restoring the flag was missing in the error path for a failed +parent->role->activate() call. The consequence is that this attempt to +activate all images correctly fails because we still set errp, however +on the next attempt BDRV_O_INACTIVE is already clear, so we return +success without actually retrying the failed action. + +An example where this is observable in practice is migration to a QEMU +instance that has a raw format block node attached to a guest device +with share-rw=off (the default) while another process holds +BLK_PERM_WRITE for the same image. In this case, all activation steps +before parent->role->activate() succeed because raw can tolerate other +writers to the image. Only the parent callback (in particular +blk_root_activate()) tries to implement the share-rw=on property and +requests exclusive write permissions. This fails when the migration +completes and correctly displays an error. However, a manual 'cont' will +incorrectly resume the VM without calling blk_root_activate() again. + +This case is described in more detail in the following bug report: +https://bugzilla.redhat.com/show_bug.cgi?id=1531888 + +Fix this by correctly restoring the BDRV_O_INACTIVE flag in the error +path. + +Cc: qemu-stable@nongnu.org +Signed-off-by: Kevin Wolf +Tested-by: Markus Armbruster +Reviewed-by: Stefan Hajnoczi +(cherry picked from commit 78fc3b3a26c145eebcdee992988644974b243a74) +Signed-off-by: Kevin Wolf +Signed-off-by: Danilo C. L. de Paula +--- + block.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/block.c b/block.c +index d0f0dc6..82b16df 100644 +--- a/block.c ++++ b/block.c +@@ -4417,6 +4417,7 @@ static void coroutine_fn bdrv_co_invalidate_cache(BlockDriverState *bs, + if (parent->role->activate) { + parent->role->activate(parent, &local_err); + if (local_err) { ++ bs->open_flags |= BDRV_O_INACTIVE; + error_propagate(errp, local_err); + return; + } +-- +1.8.3.1 + diff --git a/SOURCES/kvm-block-Use-normal-drain-for-bdrv_set_aio_context.patch b/SOURCES/kvm-block-Use-normal-drain-for-bdrv_set_aio_context.patch new file mode 100644 index 0000000..b8d168e --- /dev/null +++ b/SOURCES/kvm-block-Use-normal-drain-for-bdrv_set_aio_context.patch @@ -0,0 +1,76 @@ +From cf6bc30f7b525f0d646db62e49cbf02f3f28a1f2 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Wed, 14 Aug 2019 08:42:29 +0100 +Subject: [PATCH 06/10] block: Use normal drain for bdrv_set_aio_context() + +RH-Author: Kevin Wolf +Message-id: <20190814084229.6458-6-kwolf@redhat.com> +Patchwork-id: 89968 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 5/5] block: Use normal drain for bdrv_set_aio_context() +Bugzilla: 1716349 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Max Reitz +RH-Acked-by: Paolo Bonzini + +Now that bdrv_set_aio_context() works inside drained sections, it can +also use the real drain function instead of open coding something +similar. + +Signed-off-by: Kevin Wolf +(cherry picked from commit d70d595429ecd9ac4917e53453dd8979db8e5ffd) + +RHEL: This conflicts because we didn't backport the removal of the +polling loop. The conflict is resolved so that the polling loop moves to +above the drain and any requests a BH would spawn would still be +correctly drained afterwards. The changed order alone would have +compensated for the virtio-blk bug and it potentially compensates for +other bugs, too (we know of bugs in the NBD client at least), so leaving +the polling loop in, with the new ordering, feels like the safe way for +a downstream backport. + +Signed-off-by: Kevin Wolf +Signed-off-by: Danilo C. L. de Paula +--- + block.c | 11 +++++------ + 1 file changed, 5 insertions(+), 6 deletions(-) + +diff --git a/block.c b/block.c +index 9d9b8a9..8f3ceea 100644 +--- a/block.c ++++ b/block.c +@@ -4989,18 +4989,18 @@ void bdrv_attach_aio_context(BlockDriverState *bs, + bs->walking_aio_notifiers = false; + } + ++/* The caller must own the AioContext lock for the old AioContext of bs, but it ++ * must not own the AioContext lock for new_context (unless new_context is ++ * the same as the current context of bs). */ + void bdrv_set_aio_context(BlockDriverState *bs, AioContext *new_context) + { + AioContext *ctx = bdrv_get_aio_context(bs); + +- aio_disable_external(ctx); +- bdrv_parent_drained_begin(bs, NULL, false); +- bdrv_drain(bs); /* ensure there are no in-flight requests */ +- + while (aio_poll(ctx, false)) { + /* wait for all bottom halves to execute */ + } + ++ bdrv_drained_begin(bs); + bdrv_detach_aio_context(bs); + + /* This function executes in the old AioContext so acquire the new one in +@@ -5008,8 +5008,7 @@ void bdrv_set_aio_context(BlockDriverState *bs, AioContext *new_context) + */ + aio_context_acquire(new_context); + bdrv_attach_aio_context(bs, new_context); +- bdrv_parent_drained_end(bs, NULL, false); +- aio_enable_external(ctx); ++ bdrv_drained_end(bs); + aio_context_release(new_context); + } + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-block-backend-Make-blk_inc-dec_in_flight-public.patch b/SOURCES/kvm-block-backend-Make-blk_inc-dec_in_flight-public.patch new file mode 100644 index 0000000..2068d3f --- /dev/null +++ b/SOURCES/kvm-block-backend-Make-blk_inc-dec_in_flight-public.patch @@ -0,0 +1,62 @@ +From 0e5a55b3556fdd23bbeeaca40a151e7062d42c1e Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Wed, 14 Aug 2019 08:42:25 +0100 +Subject: [PATCH 02/10] block-backend: Make blk_inc/dec_in_flight public + +RH-Author: Kevin Wolf +Message-id: <20190814084229.6458-2-kwolf@redhat.com> +Patchwork-id: 89966 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 1/5] block-backend: Make blk_inc/dec_in_flight public +Bugzilla: 1716349 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Max Reitz +RH-Acked-by: Paolo Bonzini + +For some users of BlockBackends, just increasing the in_flight counter +is easier than implementing separate handlers in BlockDevOps. Make the +helper functions for this public. + +Signed-off-by: Kevin Wolf +(cherry picked from commit c90e2a9cfd94bd02d92c53b97f04fd595001de7e) +Signed-off-by: Kevin Wolf +Signed-off-by: Danilo C. L. de Paula +--- + block/block-backend.c | 4 ++-- + include/sysemu/block-backend.h | 2 ++ + 2 files changed, 4 insertions(+), 2 deletions(-) + +diff --git a/block/block-backend.c b/block/block-backend.c +index 0d623e4..e941520 100644 +--- a/block/block-backend.c ++++ b/block/block-backend.c +@@ -1294,12 +1294,12 @@ int blk_make_zero(BlockBackend *blk, BdrvRequestFlags flags) + return bdrv_make_zero(blk->root, flags); + } + +-static void blk_inc_in_flight(BlockBackend *blk) ++void blk_inc_in_flight(BlockBackend *blk) + { + atomic_inc(&blk->in_flight); + } + +-static void blk_dec_in_flight(BlockBackend *blk) ++void blk_dec_in_flight(BlockBackend *blk) + { + atomic_dec(&blk->in_flight); + aio_wait_kick(); +diff --git a/include/sysemu/block-backend.h b/include/sysemu/block-backend.h +index 20f8bbb..815b6e5 100644 +--- a/include/sysemu/block-backend.h ++++ b/include/sysemu/block-backend.h +@@ -157,6 +157,8 @@ int blk_co_pdiscard(BlockBackend *blk, int64_t offset, int bytes); + int blk_co_flush(BlockBackend *blk); + int blk_flush(BlockBackend *blk); + int blk_commit_all(void); ++void blk_inc_in_flight(BlockBackend *blk); ++void blk_dec_in_flight(BlockBackend *blk); + void blk_drain(BlockBackend *blk); + void blk_drain_all(void); + void blk_set_on_error(BlockBackend *blk, BlockdevOnError on_read_error, +-- +1.8.3.1 + diff --git a/SOURCES/kvm-block-file-posix-Unaligned-O_DIRECT-block-status.patch b/SOURCES/kvm-block-file-posix-Unaligned-O_DIRECT-block-status.patch new file mode 100644 index 0000000..6ced895 --- /dev/null +++ b/SOURCES/kvm-block-file-posix-Unaligned-O_DIRECT-block-status.patch @@ -0,0 +1,98 @@ +From 29592218d57f1fe49c1254fffd9b0206cfe29ec7 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Tue, 23 Jul 2019 14:45:40 +0100 +Subject: [PATCH 02/14] block/file-posix: Unaligned O_DIRECT block-status + +RH-Author: Max Reitz +Message-id: <20190723144546.23701-2-mreitz@redhat.com> +Patchwork-id: 89647 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 1/7] block/file-posix: Unaligned O_DIRECT block-status +Bugzilla: 1678979 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Stefano Garzarella +RH-Acked-by: John Snow + +Currently, qemu crashes whenever someone queries the block status of an +unaligned image tail of an O_DIRECT image: +$ echo > foo +$ qemu-img map --image-opts driver=file,filename=foo,cache.direct=on +Offset Length Mapped to File +qemu-img: block/io.c:2093: bdrv_co_block_status: Assertion `*pnum && +QEMU_IS_ALIGNED(*pnum, align) && align > offset - aligned_offset' +failed. + +This is because bdrv_co_block_status() checks that the result returned +by the driver's implementation is aligned to the request_alignment, but +file-posix can fail to do so, which is actually mentioned in a comment +there: "[...] possibly including a partial sector at EOF". + +Fix this by rounding up those partial sectors. + +There are two possible alternative fixes: +(1) We could refuse to open unaligned image files with O_DIRECT + altogether. That sounds reasonable until you realize that qcow2 + does necessarily not fill up its metadata clusters, and that nobody + runs qemu-img create with O_DIRECT. Therefore, unpreallocated qcow2 + files usually have an unaligned image tail. + +(2) bdrv_co_block_status() could ignore unaligned tails. It actually + throws away everything past the EOF already, so that sounds + reasonable. + Unfortunately, the block layer knows file lengths only with a + granularity of BDRV_SECTOR_SIZE, so bdrv_co_block_status() usually + would have to guess whether its file length information is inexact + or whether the driver is broken. + +Fixing what raw_co_block_status() returns is the safest thing to do. + +There seems to be no other block driver that sets request_alignment and +does not make sure that it always returns aligned values. + +Cc: qemu-stable@nongnu.org +Signed-off-by: Max Reitz +Reviewed-by: Eric Blake +Signed-off-by: Kevin Wolf +(cherry picked from commit 9c3db310ff0b7473272ae8dce5e04e2f8a825390) +Signed-off-by: Max Reitz +Signed-off-by: Danilo C. L. de Paula +--- + block/file-posix.c | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/block/file-posix.c b/block/file-posix.c +index 5fb5a9a..4b404e4 100644 +--- a/block/file-posix.c ++++ b/block/file-posix.c +@@ -2413,6 +2413,8 @@ static int coroutine_fn raw_co_block_status(BlockDriverState *bs, + off_t data = 0, hole = 0; + int ret; + ++ assert(QEMU_IS_ALIGNED(offset | bytes, bs->bl.request_alignment)); ++ + ret = fd_open(bs); + if (ret < 0) { + return ret; +@@ -2438,6 +2440,20 @@ static int coroutine_fn raw_co_block_status(BlockDriverState *bs, + /* On a data extent, compute bytes to the end of the extent, + * possibly including a partial sector at EOF. */ + *pnum = MIN(bytes, hole - offset); ++ ++ /* ++ * We are not allowed to return partial sectors, though, so ++ * round up if necessary. ++ */ ++ if (!QEMU_IS_ALIGNED(*pnum, bs->bl.request_alignment)) { ++ int64_t file_length = raw_getlength(bs); ++ if (file_length > 0) { ++ /* Ignore errors, this is just a safeguard */ ++ assert(hole == file_length); ++ } ++ *pnum = ROUND_UP(*pnum, bs->bl.request_alignment); ++ } ++ + ret = BDRV_BLOCK_DATA; + } else { + /* On a hole, compute bytes to the beginning of the next extent. */ +-- +1.8.3.1 + diff --git a/SOURCES/kvm-block-file-posix-do-not-fail-on-unlock-bytes.patch b/SOURCES/kvm-block-file-posix-do-not-fail-on-unlock-bytes.patch new file mode 100644 index 0000000..f6ae185 --- /dev/null +++ b/SOURCES/kvm-block-file-posix-do-not-fail-on-unlock-bytes.patch @@ -0,0 +1,58 @@ +From 87240c5fcfb3e3ba68c5c87d2175f2dd98921a7e Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Wed, 3 Apr 2019 17:13:15 +0100 +Subject: [PATCH 08/11] block/file-posix: do not fail on unlock bytes + +RH-Author: Max Reitz +Message-id: <20190403171315.20841-9-mreitz@redhat.com> +Patchwork-id: 85406 +O-Subject: [RHEL-8.1 qemu-kvm PATCH 8/8] block/file-posix: do not fail on unlock bytes +Bugzilla: 1694148 +RH-Acked-by: John Snow +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Stefano Garzarella + +From: Vladimir Sementsov-Ogievskiy + +bdrv_replace_child() calls bdrv_check_perm() with error_abort on +loosening permissions. However file-locking operations may fail even +in this case, for example on NFS. And this leads to Qemu crash. + +Let's avoid such errors. Note, that we ignore such things anyway on +permission update commit and abort. + +Signed-off-by: Vladimir Sementsov-Ogievskiy +Signed-off-by: Kevin Wolf +(cherry picked from commit 696aaaed579ac5bf5fa336216909b46d3d8f07a8) +Signed-off-by: Max Reitz +Signed-off-by: Danilo C. L. de Paula +--- + block/file-posix.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/block/file-posix.c b/block/file-posix.c +index deecf58..5fb5a9a 100644 +--- a/block/file-posix.c ++++ b/block/file-posix.c +@@ -800,6 +800,18 @@ static int raw_handle_perm_lock(BlockDriverState *bs, + + switch (op) { + case RAW_PL_PREPARE: ++ if ((s->perm | new_perm) == s->perm && ++ (s->shared_perm & new_shared) == s->shared_perm) ++ { ++ /* ++ * We are going to unlock bytes, it should not fail. If it fail due ++ * to some fs-dependent permission-unrelated reasons (which occurs ++ * sometimes on NFS and leads to abort in bdrv_replace_child) we ++ * can't prevent such errors by any check here. And we ignore them ++ * anyway in ABORT and COMMIT. ++ */ ++ return 0; ++ } + ret = raw_apply_lock_bytes(s, s->fd, s->perm | new_perm, + ~s->shared_perm | ~new_shared, + false, errp); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-block-gluster-limit-the-transfer-size-to-512-MiB.patch b/SOURCES/kvm-block-gluster-limit-the-transfer-size-to-512-MiB.patch new file mode 100644 index 0000000..d061535 --- /dev/null +++ b/SOURCES/kvm-block-gluster-limit-the-transfer-size-to-512-MiB.patch @@ -0,0 +1,101 @@ +From 1788135e55dd9e68e54ba32582702df09819a8fe Mon Sep 17 00:00:00 2001 +From: Stefano Garzarella +Date: Tue, 16 Jul 2019 08:13:10 +0100 +Subject: [PATCH 16/39] block/gluster: limit the transfer size to 512 MiB + +RH-Author: Stefano Garzarella +Message-id: <20190716081310.29528-2-sgarzare@redhat.com> +Patchwork-id: 89533 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 1/1] block/gluster: limit the transfer size to 512 MiB +Bugzilla: 1728657 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Kevin Wolf +RH-Acked-by: Max Reitz + +Several versions of GlusterFS (3.12? -> 6.0.1) fail when the +transfer size is greater or equal to 1024 MiB, so we are +limiting the transfer size to 512 MiB to avoid this rare issue. + +Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=1691320 +Signed-off-by: Stefano Garzarella +Reviewed-by: Niels de Vos +Signed-off-by: Kevin Wolf +(cherry picked from commit de23e72bb7515888fdea2a58c58a2e02370123bd) +Signed-off-by: Stefano Garzarella +Signed-off-by: Danilo C. L. de Paula +--- + block/gluster.c | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/block/gluster.c b/block/gluster.c +index a6ac2b1..9b29d96 100644 +--- a/block/gluster.c ++++ b/block/gluster.c +@@ -9,6 +9,7 @@ + */ + + #include "qemu/osdep.h" ++#include "qemu/units.h" + #include + #include "block/block_int.h" + #include "block/qdict.h" +@@ -41,6 +42,12 @@ + #define GLUSTER_DEBUG_MAX 9 + #define GLUSTER_OPT_LOGFILE "logfile" + #define GLUSTER_LOGFILE_DEFAULT "-" /* handled in libgfapi as /dev/stderr */ ++/* ++ * Several versions of GlusterFS (3.12? -> 6.0.1) fail when the transfer size ++ * is greater or equal to 1024 MiB, so we are limiting the transfer size to 512 ++ * MiB to avoid this rare issue. ++ */ ++#define GLUSTER_MAX_TRANSFER (512 * MiB) + + #define GERR_INDEX_HINT "hint: check in 'server' array index '%d'\n" + +@@ -887,6 +894,11 @@ out: + return ret; + } + ++static void qemu_gluster_refresh_limits(BlockDriverState *bs, Error **errp) ++{ ++ bs->bl.max_transfer = GLUSTER_MAX_TRANSFER; ++} ++ + static int qemu_gluster_reopen_prepare(BDRVReopenState *state, + BlockReopenQueue *queue, Error **errp) + { +@@ -1527,6 +1539,7 @@ static BlockDriver bdrv_gluster = { + .bdrv_co_pwrite_zeroes = qemu_gluster_co_pwrite_zeroes, + #endif + .bdrv_co_block_status = qemu_gluster_co_block_status, ++ .bdrv_refresh_limits = qemu_gluster_refresh_limits, + .create_opts = &qemu_gluster_create_opts, + }; + +@@ -1556,6 +1569,7 @@ static BlockDriver bdrv_gluster_tcp = { + .bdrv_co_pwrite_zeroes = qemu_gluster_co_pwrite_zeroes, + #endif + .bdrv_co_block_status = qemu_gluster_co_block_status, ++ .bdrv_refresh_limits = qemu_gluster_refresh_limits, + .create_opts = &qemu_gluster_create_opts, + }; + +@@ -1585,6 +1599,7 @@ static BlockDriver bdrv_gluster_unix = { + .bdrv_co_pwrite_zeroes = qemu_gluster_co_pwrite_zeroes, + #endif + .bdrv_co_block_status = qemu_gluster_co_block_status, ++ .bdrv_refresh_limits = qemu_gluster_refresh_limits, + .create_opts = &qemu_gluster_create_opts, + }; + +@@ -1620,6 +1635,7 @@ static BlockDriver bdrv_gluster_rdma = { + .bdrv_co_pwrite_zeroes = qemu_gluster_co_pwrite_zeroes, + #endif + .bdrv_co_block_status = qemu_gluster_co_block_status, ++ .bdrv_refresh_limits = qemu_gluster_refresh_limits, + .create_opts = &qemu_gluster_create_opts, + }; + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-block-posix-Always-allocate-the-first-block.patch b/SOURCES/kvm-block-posix-Always-allocate-the-first-block.patch new file mode 100644 index 0000000..08fbcba --- /dev/null +++ b/SOURCES/kvm-block-posix-Always-allocate-the-first-block.patch @@ -0,0 +1,392 @@ +From 273237507842493f78cd492cd54137e828a986ef Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Fri, 30 Aug 2019 12:56:27 +0100 +Subject: [PATCH 09/10] block: posix: Always allocate the first block + +RH-Author: Thomas Huth +Message-id: <20190830125628.23668-5-thuth@redhat.com> +Patchwork-id: 90210 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v2 4/5] block: posix: Always allocate the first block +Bugzilla: 1738839 +RH-Acked-by: Cornelia Huck +RH-Acked-by: Max Reitz +RH-Acked-by: David Hildenbrand + +From: Nir Soffer + +When creating an image with preallocation "off" or "falloc", the first +block of the image is typically not allocated. When using Gluster +storage backed by XFS filesystem, reading this block using direct I/O +succeeds regardless of request length, fooling alignment detection. + +In this case we fallback to a safe value (4096) instead of the optimal +value (512), which may lead to unneeded data copying when aligning +requests. Allocating the first block avoids the fallback. + +Since we allocate the first block even with preallocation=off, we no +longer create images with zero disk size: + + $ ./qemu-img create -f raw test.raw 1g + Formatting 'test.raw', fmt=raw size=1073741824 + + $ ls -lhs test.raw + 4.0K -rw-r--r--. 1 nsoffer nsoffer 1.0G Aug 16 23:48 test.raw + +And converting the image requires additional cluster: + + $ ./qemu-img measure -f raw -O qcow2 test.raw + required size: 458752 + fully allocated size: 1074135040 + +When using format like vmdk with multiple files per image, we allocate +one block per file: + + $ ./qemu-img create -f vmdk -o subformat=twoGbMaxExtentFlat test.vmdk 4g + Formatting 'test.vmdk', fmt=vmdk size=4294967296 compat6=off hwversion=undefined subformat=twoGbMaxExtentFlat + + $ ls -lhs test*.vmdk + 4.0K -rw-r--r--. 1 nsoffer nsoffer 2.0G Aug 27 03:23 test-f001.vmdk + 4.0K -rw-r--r--. 1 nsoffer nsoffer 2.0G Aug 27 03:23 test-f002.vmdk + 4.0K -rw-r--r--. 1 nsoffer nsoffer 353 Aug 27 03:23 test.vmdk + +I did quick performance test for copying disks with qemu-img convert to +new raw target image to Gluster storage with sector size of 512 bytes: + + for i in $(seq 10); do + rm -f dst.raw + sleep 10 + time ./qemu-img convert -f raw -O raw -t none -T none src.raw dst.raw + done + +Here is a table comparing the total time spent: + +Type Before(s) After(s) Diff(%) +--------------------------------------- +real 530.028 469.123 -11.4 +user 17.204 10.768 -37.4 +sys 17.881 7.011 -60.7 + +We can see very clear improvement in CPU usage. + +Signed-off-by: Nir Soffer +Message-id: 20190827010528.8818-2-nsoffer@redhat.com +Reviewed-by: Max Reitz +Signed-off-by: Max Reitz +(cherry picked from commit 3f900188502670a15f8915d5363533512ecd035f) +Signed-off-by: Danilo C. L. de Paula + +Conflicts: + block/file-posix.c (simple contextual conflict) + tests/qemu-iotests/059.out (Needed to adapt output a little bit) + +Signed-off-by: Thomas Huth +Signed-off-by: Danilo C. L. de Paula +--- + block/file-posix.c | 51 ++++++++++++++++++++++++++++++++++++++++ + tests/qemu-iotests/059.out | 2 +- + tests/qemu-iotests/150.out | 11 --------- + tests/qemu-iotests/150.out.qcow2 | 11 +++++++++ + tests/qemu-iotests/150.out.raw | 12 ++++++++++ + tests/qemu-iotests/175 | 19 ++++++++++----- + tests/qemu-iotests/175.out | 8 +++---- + tests/qemu-iotests/178.out.qcow2 | 4 ++-- + tests/qemu-iotests/221.out | 12 ++++++---- + tests/qemu-iotests/253.out | 12 ++++++---- + 10 files changed, 110 insertions(+), 32 deletions(-) + delete mode 100644 tests/qemu-iotests/150.out + create mode 100644 tests/qemu-iotests/150.out.qcow2 + create mode 100644 tests/qemu-iotests/150.out.raw + +diff --git a/block/file-posix.c b/block/file-posix.c +index 84c5a31..dfe0bca 100644 +--- a/block/file-posix.c ++++ b/block/file-posix.c +@@ -1605,6 +1605,43 @@ static ssize_t handle_aiocb_discard(RawPosixAIOData *aiocb) + return ret; + } + ++/* ++ * Help alignment probing by allocating the first block. ++ * ++ * When reading with direct I/O from unallocated area on Gluster backed by XFS, ++ * reading succeeds regardless of request length. In this case we fallback to ++ * safe alignment which is not optimal. Allocating the first block avoids this ++ * fallback. ++ * ++ * fd may be opened with O_DIRECT, but we don't know the buffer alignment or ++ * request alignment, so we use safe values. ++ * ++ * Returns: 0 on success, -errno on failure. Since this is an optimization, ++ * caller may ignore failures. ++ */ ++static int allocate_first_block(int fd, size_t max_size) ++{ ++ size_t write_size = (max_size < MAX_BLOCKSIZE) ++ ? BDRV_SECTOR_SIZE ++ : MAX_BLOCKSIZE; ++ size_t max_align = MAX(MAX_BLOCKSIZE, getpagesize()); ++ void *buf; ++ ssize_t n; ++ int ret; ++ ++ buf = qemu_memalign(max_align, write_size); ++ memset(buf, 0, write_size); ++ ++ do { ++ n = pwrite(fd, buf, write_size, 0); ++ } while (n == -1 && errno == EINTR); ++ ++ ret = (n == -1) ? -errno : 0; ++ ++ qemu_vfree(buf); ++ return ret; ++} ++ + static int handle_aiocb_truncate(RawPosixAIOData *aiocb) + { + int result = 0; +@@ -1642,6 +1679,17 @@ static int handle_aiocb_truncate(RawPosixAIOData *aiocb) + /* posix_fallocate() doesn't set errno. */ + error_setg_errno(errp, -result, + "Could not preallocate new data"); ++ } else if (current_length == 0) { ++ /* ++ * posix_fallocate() uses fallocate() if the filesystem ++ * supports it, or fallback to manually writing zeroes. If ++ * fallocate() was used, unaligned reads from the fallocated ++ * area in raw_probe_alignment() will succeed, hence we need to ++ * allocate the first block. ++ * ++ * Optimize future alignment probing; ignore failures. ++ */ ++ allocate_first_block(fd, offset); + } + } else { + result = 0; +@@ -1700,6 +1748,9 @@ static int handle_aiocb_truncate(RawPosixAIOData *aiocb) + if (ftruncate(fd, offset) != 0) { + result = -errno; + error_setg_errno(errp, -result, "Could not resize file"); ++ } else if (current_length == 0 && offset > current_length) { ++ /* Optimize future alignment probing; ignore failures. */ ++ allocate_first_block(fd, offset); + } + return result; + default: +diff --git a/tests/qemu-iotests/059.out b/tests/qemu-iotests/059.out +index f6dce79..19cd591 100644 +--- a/tests/qemu-iotests/059.out ++++ b/tests/qemu-iotests/059.out +@@ -27,7 +27,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1073741824000 subformat=twoGbMax + image: TEST_DIR/t.vmdk + file format: vmdk + virtual size: 1.0T (1073741824000 bytes) +-disk size: 16K ++disk size: 2.0M + Format specific information: + cid: XXXXXXXX + parent cid: XXXXXXXX +diff --git a/tests/qemu-iotests/150.out b/tests/qemu-iotests/150.out +deleted file mode 100644 +index 2a54e8d..0000000 +--- a/tests/qemu-iotests/150.out ++++ /dev/null +@@ -1,11 +0,0 @@ +-QA output created by 150 +- +-=== Mapping sparse conversion === +- +-Offset Length File +- +-=== Mapping non-sparse conversion === +- +-Offset Length File +-0 0x100000 TEST_DIR/t.IMGFMT +-*** done +diff --git a/tests/qemu-iotests/150.out.qcow2 b/tests/qemu-iotests/150.out.qcow2 +new file mode 100644 +index 0000000..2a54e8d +--- /dev/null ++++ b/tests/qemu-iotests/150.out.qcow2 +@@ -0,0 +1,11 @@ ++QA output created by 150 ++ ++=== Mapping sparse conversion === ++ ++Offset Length File ++ ++=== Mapping non-sparse conversion === ++ ++Offset Length File ++0 0x100000 TEST_DIR/t.IMGFMT ++*** done +diff --git a/tests/qemu-iotests/150.out.raw b/tests/qemu-iotests/150.out.raw +new file mode 100644 +index 0000000..3cdc772 +--- /dev/null ++++ b/tests/qemu-iotests/150.out.raw +@@ -0,0 +1,12 @@ ++QA output created by 150 ++ ++=== Mapping sparse conversion === ++ ++Offset Length File ++0 0x1000 TEST_DIR/t.IMGFMT ++ ++=== Mapping non-sparse conversion === ++ ++Offset Length File ++0 0x100000 TEST_DIR/t.IMGFMT ++*** done +diff --git a/tests/qemu-iotests/175 b/tests/qemu-iotests/175 +index 2e37c9a..b3b7712 100755 +--- a/tests/qemu-iotests/175 ++++ b/tests/qemu-iotests/175 +@@ -38,14 +38,16 @@ trap "_cleanup; exit \$status" 0 1 2 3 15 + # the file size. This function hides the resulting difference in the + # stat -c '%b' output. + # Parameter 1: Number of blocks an empty file occupies +-# Parameter 2: Image size in bytes ++# Parameter 2: Minimal number of blocks in an image ++# Parameter 3: Image size in bytes + _filter_blocks() + { + extra_blocks=$1 +- img_size=$2 ++ min_blocks=$2 ++ img_size=$3 + +- sed -e "s/blocks=$extra_blocks\\(\$\\|[^0-9]\\)/nothing allocated/" \ +- -e "s/blocks=$((extra_blocks + img_size / 512))\\(\$\\|[^0-9]\\)/everything allocated/" ++ sed -e "s/blocks=$min_blocks\\(\$\\|[^0-9]\\)/min allocation/" \ ++ -e "s/blocks=$((extra_blocks + img_size / 512))\\(\$\\|[^0-9]\\)/max allocation/" + } + + # get standard environment, filters and checks +@@ -61,16 +63,21 @@ size=$((1 * 1024 * 1024)) + touch "$TEST_DIR/empty" + extra_blocks=$(stat -c '%b' "$TEST_DIR/empty") + ++# We always write the first byte; check how many blocks this filesystem ++# allocates to match empty image alloation. ++printf "\0" > "$TEST_DIR/empty" ++min_blocks=$(stat -c '%b' "$TEST_DIR/empty") ++ + echo + echo "== creating image with default preallocation ==" + _make_test_img $size | _filter_imgfmt +-stat -c "size=%s, blocks=%b" $TEST_IMG | _filter_blocks $extra_blocks $size ++stat -c "size=%s, blocks=%b" $TEST_IMG | _filter_blocks $extra_blocks $min_blocks $size + + for mode in off full falloc; do + echo + echo "== creating image with preallocation $mode ==" + IMGOPTS=preallocation=$mode _make_test_img $size | _filter_imgfmt +- stat -c "size=%s, blocks=%b" $TEST_IMG | _filter_blocks $extra_blocks $size ++ stat -c "size=%s, blocks=%b" $TEST_IMG | _filter_blocks $extra_blocks $min_blocks $size + done + + # success, all done +diff --git a/tests/qemu-iotests/175.out b/tests/qemu-iotests/175.out +index 6d9a5ed..263e521 100644 +--- a/tests/qemu-iotests/175.out ++++ b/tests/qemu-iotests/175.out +@@ -2,17 +2,17 @@ QA output created by 175 + + == creating image with default preallocation == + Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 +-size=1048576, nothing allocated ++size=1048576, min allocation + + == creating image with preallocation off == + Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 preallocation=off +-size=1048576, nothing allocated ++size=1048576, min allocation + + == creating image with preallocation full == + Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 preallocation=full +-size=1048576, everything allocated ++size=1048576, max allocation + + == creating image with preallocation falloc == + Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 preallocation=falloc +-size=1048576, everything allocated ++size=1048576, max allocation + *** done +diff --git a/tests/qemu-iotests/178.out.qcow2 b/tests/qemu-iotests/178.out.qcow2 +index d42d4a4..12edc3d 100644 +--- a/tests/qemu-iotests/178.out.qcow2 ++++ b/tests/qemu-iotests/178.out.qcow2 +@@ -96,7 +96,7 @@ converted image file size in bytes: 196608 + == raw input image with data (human) == + + Formatting 'TEST_DIR/t.qcow2', fmt=IMGFMT size=1073741824 +-required size: 393216 ++required size: 458752 + fully allocated size: 1074135040 + wrote 512/512 bytes at offset 512 + 512 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +@@ -240,7 +240,7 @@ converted image file size in bytes: 196608 + + Formatting 'TEST_DIR/t.qcow2', fmt=IMGFMT size=1073741824 + { +- "required": 393216, ++ "required": 458752, + "fully-allocated": 1074135040 + } + wrote 512/512 bytes at offset 512 +diff --git a/tests/qemu-iotests/221.out b/tests/qemu-iotests/221.out +index 9f9dd52..dca024a 100644 +--- a/tests/qemu-iotests/221.out ++++ b/tests/qemu-iotests/221.out +@@ -3,14 +3,18 @@ QA output created by 221 + === Check mapping of unaligned raw image === + + Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=65537 +-[{ "start": 0, "length": 66048, "depth": 0, "zero": true, "data": false, "offset": OFFSET}] +-[{ "start": 0, "length": 66048, "depth": 0, "zero": true, "data": false, "offset": OFFSET}] ++[{ "start": 0, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": OFFSET}, ++{ "start": 4096, "length": 61952, "depth": 0, "zero": true, "data": false, "offset": OFFSET}] ++[{ "start": 0, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": OFFSET}, ++{ "start": 4096, "length": 61952, "depth": 0, "zero": true, "data": false, "offset": OFFSET}] + wrote 1/1 bytes at offset 65536 + 1 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +-[{ "start": 0, "length": 65536, "depth": 0, "zero": true, "data": false, "offset": OFFSET}, ++[{ "start": 0, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": OFFSET}, ++{ "start": 4096, "length": 61440, "depth": 0, "zero": true, "data": false, "offset": OFFSET}, + { "start": 65536, "length": 1, "depth": 0, "zero": false, "data": true, "offset": OFFSET}, + { "start": 65537, "length": 511, "depth": 0, "zero": true, "data": false, "offset": OFFSET}] +-[{ "start": 0, "length": 65536, "depth": 0, "zero": true, "data": false, "offset": OFFSET}, ++[{ "start": 0, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": OFFSET}, ++{ "start": 4096, "length": 61440, "depth": 0, "zero": true, "data": false, "offset": OFFSET}, + { "start": 65536, "length": 1, "depth": 0, "zero": false, "data": true, "offset": OFFSET}, + { "start": 65537, "length": 511, "depth": 0, "zero": true, "data": false, "offset": OFFSET}] + *** done +diff --git a/tests/qemu-iotests/253.out b/tests/qemu-iotests/253.out +index 607c0ba..3d08b30 100644 +--- a/tests/qemu-iotests/253.out ++++ b/tests/qemu-iotests/253.out +@@ -3,12 +3,16 @@ QA output created by 253 + === Check mapping of unaligned raw image === + + Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048575 +-[{ "start": 0, "length": 1048576, "depth": 0, "zero": true, "data": false, "offset": OFFSET}] +-[{ "start": 0, "length": 1048576, "depth": 0, "zero": true, "data": false, "offset": OFFSET}] ++[{ "start": 0, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": OFFSET}, ++{ "start": 4096, "length": 1044480, "depth": 0, "zero": true, "data": false, "offset": OFFSET}] ++[{ "start": 0, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": OFFSET}, ++{ "start": 4096, "length": 1044480, "depth": 0, "zero": true, "data": false, "offset": OFFSET}] + wrote 65535/65535 bytes at offset 983040 + 63.999 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +-[{ "start": 0, "length": 983040, "depth": 0, "zero": true, "data": false, "offset": OFFSET}, ++[{ "start": 0, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": OFFSET}, ++{ "start": 4096, "length": 978944, "depth": 0, "zero": true, "data": false, "offset": OFFSET}, + { "start": 983040, "length": 65536, "depth": 0, "zero": false, "data": true, "offset": OFFSET}] +-[{ "start": 0, "length": 983040, "depth": 0, "zero": true, "data": false, "offset": OFFSET}, ++[{ "start": 0, "length": 4096, "depth": 0, "zero": false, "data": true, "offset": OFFSET}, ++{ "start": 4096, "length": 978944, "depth": 0, "zero": true, "data": false, "offset": OFFSET}, + { "start": 983040, "length": 65536, "depth": 0, "zero": false, "data": true, "offset": OFFSET}] + *** done +-- +1.8.3.1 + diff --git a/SOURCES/kvm-block-ssh-Convert-from-DPRINTF-macro-to-trace-events.patch b/SOURCES/kvm-block-ssh-Convert-from-DPRINTF-macro-to-trace-events.patch new file mode 100644 index 0000000..c12051d --- /dev/null +++ b/SOURCES/kvm-block-ssh-Convert-from-DPRINTF-macro-to-trace-events.patch @@ -0,0 +1,220 @@ +From f087aa3581b13254e4de34784631f1852a9ddbec Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Mon, 8 Jul 2019 15:25:52 +0100 +Subject: [PATCH 06/39] block/ssh: Convert from DPRINTF() macro to trace events +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Pino Toscano +Message-id: <20190708152601.21123-2-ptoscano@redhat.com> +Patchwork-id: 89415 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v3 01/10] block/ssh: Convert from DPRINTF() macro to trace events +Bugzilla: 1513367 +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Max Reitz +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Markus Armbruster + +From: Laurent Vivier + +Signed-off-by: Laurent Vivier +Reviewed-by: Richard W.M. Jones +Reviewed-by: Philippe Mathieu-Daudé +Message-id: 20181213162727.17438-2-lvivier@redhat.com +[mreitz: Fixed type of ssh_{read,write}_return's parameter to be ssize_t + instead of size_t] +Signed-off-by: Max Reitz +(cherry picked from commit 023908a24de4f264dbcd22352e8a304424005bd4) +Signed-off-by: Pino Toscano + +Signed-off-by: Danilo C. L. de Paula +--- + block/ssh.c | 46 +++++++++++++++++----------------------------- + block/trace-events | 17 +++++++++++++++++ + 2 files changed, 34 insertions(+), 29 deletions(-) + +diff --git a/block/ssh.c b/block/ssh.c +index 6a55d82..dfb3e3c 100644 +--- a/block/ssh.c ++++ b/block/ssh.c +@@ -41,27 +41,17 @@ + #include "qapi/qmp/qstring.h" + #include "qapi/qobject-input-visitor.h" + #include "qapi/qobject-output-visitor.h" ++#include "trace.h" + +-/* DEBUG_SSH=1 enables the DPRINTF (debugging printf) statements in +- * this block driver code. +- * ++/* + * TRACE_LIBSSH2= enables tracing in libssh2 itself. Note + * that this requires that libssh2 was specially compiled with the + * `./configure --enable-debug' option, so most likely you will have + * to compile it yourself. The meaning of is described + * here: http://www.libssh2.org/libssh2_trace.html + */ +-#define DEBUG_SSH 0 + #define TRACE_LIBSSH2 0 /* or try: LIBSSH2_TRACE_SFTP */ + +-#define DPRINTF(fmt, ...) \ +- do { \ +- if (DEBUG_SSH) { \ +- fprintf(stderr, "ssh: %-15s " fmt "\n", \ +- __func__, ##__VA_ARGS__); \ +- } \ +- } while (0) +- + typedef struct BDRVSSHState { + /* Coroutine. */ + CoMutex lock; +@@ -336,7 +326,7 @@ static int check_host_key_knownhosts(BDRVSSHState *s, + switch (r) { + case LIBSSH2_KNOWNHOST_CHECK_MATCH: + /* OK */ +- DPRINTF("host key OK: %s", found->key); ++ trace_ssh_check_host_key_knownhosts(found->key); + break; + case LIBSSH2_KNOWNHOST_CHECK_MISMATCH: + ret = -EINVAL; +@@ -721,8 +711,7 @@ static int connect_to_ssh(BDRVSSHState *s, BlockdevOptionsSsh *opts, + } + + /* Open the remote file. */ +- DPRINTF("opening file %s flags=0x%x creat_mode=0%o", +- opts->path, ssh_flags, creat_mode); ++ trace_ssh_connect_to_ssh(opts->path, ssh_flags, creat_mode); + s->sftp_handle = libssh2_sftp_open(s->sftp, opts->path, ssh_flags, + creat_mode); + if (!s->sftp_handle) { +@@ -890,7 +879,7 @@ static int coroutine_fn ssh_co_create_opts(const char *filename, QemuOpts *opts, + /* Get desired file size. */ + ssh_opts->size = ROUND_UP(qemu_opt_get_size_del(opts, BLOCK_OPT_SIZE, 0), + BDRV_SECTOR_SIZE); +- DPRINTF("total_size=%" PRIi64, ssh_opts->size); ++ trace_ssh_co_create_opts(ssh_opts->size); + + uri_options = qdict_new(); + ret = parse_uri(filename, uri_options, errp); +@@ -946,7 +935,7 @@ static void restart_coroutine(void *opaque) + BDRVSSHState *s = bs->opaque; + AioContext *ctx = bdrv_get_aio_context(bs); + +- DPRINTF("co=%p", restart->co); ++ trace_ssh_restart_coroutine(restart->co); + aio_set_fd_handler(ctx, s->sock, false, NULL, NULL, NULL, NULL); + + aio_co_wake(restart->co); +@@ -974,13 +963,12 @@ static coroutine_fn void co_yield(BDRVSSHState *s, BlockDriverState *bs) + wr_handler = restart_coroutine; + } + +- DPRINTF("s->sock=%d rd_handler=%p wr_handler=%p", s->sock, +- rd_handler, wr_handler); ++ trace_ssh_co_yield(s->sock, rd_handler, wr_handler); + + aio_set_fd_handler(bdrv_get_aio_context(bs), s->sock, + false, rd_handler, wr_handler, NULL, &restart); + qemu_coroutine_yield(); +- DPRINTF("s->sock=%d - back", s->sock); ++ trace_ssh_co_yield_back(s->sock); + } + + /* SFTP has a function `libssh2_sftp_seek64' which seeks to a position +@@ -1003,7 +991,7 @@ static void ssh_seek(BDRVSSHState *s, int64_t offset, int flags) + bool force = (flags & SSH_SEEK_FORCE) != 0; + + if (force || op_read != s->offset_op_read || offset != s->offset) { +- DPRINTF("seeking to offset=%" PRIi64, offset); ++ trace_ssh_seek(offset); + libssh2_sftp_seek64(s->sftp_handle, offset); + s->offset = offset; + s->offset_op_read = op_read; +@@ -1019,7 +1007,7 @@ static coroutine_fn int ssh_read(BDRVSSHState *s, BlockDriverState *bs, + char *buf, *end_of_vec; + struct iovec *i; + +- DPRINTF("offset=%" PRIi64 " size=%zu", offset, size); ++ trace_ssh_read(offset, size); + + ssh_seek(s, offset, SSH_SEEK_READ); + +@@ -1038,9 +1026,9 @@ static coroutine_fn int ssh_read(BDRVSSHState *s, BlockDriverState *bs, + */ + for (got = 0; got < size; ) { + again: +- DPRINTF("sftp_read buf=%p size=%zu", buf, end_of_vec - buf); ++ trace_ssh_read_buf(buf, end_of_vec - buf); + r = libssh2_sftp_read(s->sftp_handle, buf, end_of_vec - buf); +- DPRINTF("sftp_read returned %zd", r); ++ trace_ssh_read_return(r); + + if (r == LIBSSH2_ERROR_EAGAIN || r == LIBSSH2_ERROR_TIMEOUT) { + co_yield(s, bs); +@@ -1094,7 +1082,7 @@ static int ssh_write(BDRVSSHState *s, BlockDriverState *bs, + char *buf, *end_of_vec; + struct iovec *i; + +- DPRINTF("offset=%" PRIi64 " size=%zu", offset, size); ++ trace_ssh_write(offset, size); + + ssh_seek(s, offset, SSH_SEEK_WRITE); + +@@ -1108,9 +1096,9 @@ static int ssh_write(BDRVSSHState *s, BlockDriverState *bs, + + for (written = 0; written < size; ) { + again: +- DPRINTF("sftp_write buf=%p size=%zu", buf, end_of_vec - buf); ++ trace_ssh_write_buf(buf, end_of_vec - buf); + r = libssh2_sftp_write(s->sftp_handle, buf, end_of_vec - buf); +- DPRINTF("sftp_write returned %zd", r); ++ trace_ssh_write_return(r); + + if (r == LIBSSH2_ERROR_EAGAIN || r == LIBSSH2_ERROR_TIMEOUT) { + co_yield(s, bs); +@@ -1185,7 +1173,7 @@ static coroutine_fn int ssh_flush(BDRVSSHState *s, BlockDriverState *bs) + { + int r; + +- DPRINTF("fsync"); ++ trace_ssh_flush(); + again: + r = libssh2_sftp_fsync(s->sftp_handle); + if (r == LIBSSH2_ERROR_EAGAIN || r == LIBSSH2_ERROR_TIMEOUT) { +@@ -1236,7 +1224,7 @@ static int64_t ssh_getlength(BlockDriverState *bs) + + /* Note we cannot make a libssh2 call here. */ + length = (int64_t) s->attrs.filesize; +- DPRINTF("length=%" PRIi64, length); ++ trace_ssh_getlength(length); + + return length; + } +diff --git a/block/trace-events b/block/trace-events +index c35287b..4c69548 100644 +--- a/block/trace-events ++++ b/block/trace-events +@@ -150,3 +150,20 @@ nvme_free_req_queue_wait(void *q) "q %p" + nvme_cmd_map_qiov(void *s, void *cmd, void *req, void *qiov, int entries) "s %p cmd %p req %p qiov %p entries %d" + nvme_cmd_map_qiov_pages(void *s, int i, uint64_t page) "s %p page[%d] 0x%"PRIx64 + nvme_cmd_map_qiov_iov(void *s, int i, void *page, int pages) "s %p iov[%d] %p pages %d" ++ ++# block/ssh.c ++ssh_restart_coroutine(void *co) "co=%p" ++ssh_flush(void) "fsync" ++ssh_check_host_key_knownhosts(const char *key) "host key OK: %s" ++ssh_connect_to_ssh(char *path, int flags, int mode) "opening file %s flags=0x%x creat_mode=0%o" ++ssh_co_yield(int sock, void *rd_handler, void *wr_handler) "s->sock=%d rd_handler=%p wr_handler=%p" ++ssh_co_yield_back(int sock) "s->sock=%d - back" ++ssh_getlength(int64_t length) "length=%" PRIi64 ++ssh_co_create_opts(uint64_t size) "total_size=%" PRIu64 ++ssh_read(int64_t offset, size_t size) "offset=%" PRIi64 " size=%zu" ++ssh_read_buf(void *buf, size_t size) "sftp_read buf=%p size=%zu" ++ssh_read_return(ssize_t ret) "sftp_read returned %zd" ++ssh_write(int64_t offset, size_t size) "offset=%" PRIi64 " size=%zu" ++ssh_write_buf(void *buf, size_t size) "sftp_write buf=%p size=%zu" ++ssh_write_return(ssize_t ret) "sftp_write returned %zd" ++ssh_seek(int64_t offset) "seeking to offset=%" PRIi64 +-- +1.8.3.1 + diff --git a/SOURCES/kvm-block-ssh-Do-not-report-read-write-flush-errors-to-t.patch b/SOURCES/kvm-block-ssh-Do-not-report-read-write-flush-errors-to-t.patch new file mode 100644 index 0000000..51dc4f5 --- /dev/null +++ b/SOURCES/kvm-block-ssh-Do-not-report-read-write-flush-errors-to-t.patch @@ -0,0 +1,132 @@ +From 2deb556f99ae439125674fa3c6d77424048fd30c Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Mon, 8 Jul 2019 15:25:53 +0100 +Subject: [PATCH 07/39] block/ssh: Do not report read/write/flush errors to the + user +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Pino Toscano +Message-id: <20190708152601.21123-3-ptoscano@redhat.com> +Patchwork-id: 89418 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v3 02/10] block/ssh: Do not report read/write/flush errors to the user +Bugzilla: 1513367 +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Max Reitz +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Markus Armbruster + +From: Markus Armbruster + +Callbacks ssh_co_readv(), ssh_co_writev(), ssh_co_flush() report +errors to the user with error_printf(). They shouldn't, it's their +caller's job. Replace by a suitable trace point. While there, drop +the unreachable !s->sftp case. + +Perhaps we should convert this part of the block driver interface to +Error, so block drivers can pass more detail to their callers. Not +today. + +Cc: "Richard W.M. Jones" +Cc: Kevin Wolf +Cc: Max Reitz +Cc: qemu-block@nongnu.org +Signed-off-by: Markus Armbruster +Reviewed-by: Eric Blake +Message-Id: <20190417190641.26814-3-armbru@redhat.com> +(cherry picked from commit 6b3048cee0e0eccd27b62954ecc57c4a1bceb976) +Signed-off-by: Philippe Mathieu-Daudé +Signed-off-by: Danilo C. L. de Paula +--- + block/ssh.c | 38 +++++++++++++------------------------- + block/trace-events | 3 +++ + 2 files changed, 16 insertions(+), 25 deletions(-) + +diff --git a/block/ssh.c b/block/ssh.c +index dfb3e3c..89abce0 100644 +--- a/block/ssh.c ++++ b/block/ssh.c +@@ -159,31 +159,19 @@ sftp_error_setg(Error **errp, BDRVSSHState *s, const char *fs, ...) + g_free(msg); + } + +-static void GCC_FMT_ATTR(2, 3) +-sftp_error_report(BDRVSSHState *s, const char *fs, ...) ++static void sftp_error_trace(BDRVSSHState *s, const char *op) + { +- va_list args; +- +- va_start(args, fs); +- error_vprintf(fs, args); ++ char *ssh_err; ++ int ssh_err_code; ++ unsigned long sftp_err_code; + +- if ((s)->sftp) { +- char *ssh_err; +- int ssh_err_code; +- unsigned long sftp_err_code; ++ /* This is not an errno. See . */ ++ ssh_err_code = libssh2_session_last_error(s->session, ++ &ssh_err, NULL, 0); ++ /* See . */ ++ sftp_err_code = libssh2_sftp_last_error((s)->sftp); + +- /* This is not an errno. See . */ +- ssh_err_code = libssh2_session_last_error(s->session, +- &ssh_err, NULL, 0); +- /* See . */ +- sftp_err_code = libssh2_sftp_last_error((s)->sftp); +- +- error_printf(": %s (libssh2 error code: %d, sftp error code: %lu)", +- ssh_err, ssh_err_code, sftp_err_code); +- } +- +- va_end(args); +- error_printf("\n"); ++ trace_sftp_error(op, ssh_err, ssh_err_code, sftp_err_code); + } + + static int parse_uri(const char *filename, QDict *options, Error **errp) +@@ -1035,7 +1023,7 @@ static coroutine_fn int ssh_read(BDRVSSHState *s, BlockDriverState *bs, + goto again; + } + if (r < 0) { +- sftp_error_report(s, "read failed"); ++ sftp_error_trace(s, "read"); + s->offset = -1; + return -EIO; + } +@@ -1105,7 +1093,7 @@ static int ssh_write(BDRVSSHState *s, BlockDriverState *bs, + goto again; + } + if (r < 0) { +- sftp_error_report(s, "write failed"); ++ sftp_error_trace(s, "write"); + s->offset = -1; + return -EIO; + } +@@ -1186,7 +1174,7 @@ static coroutine_fn int ssh_flush(BDRVSSHState *s, BlockDriverState *bs) + return 0; + } + if (r < 0) { +- sftp_error_report(s, "fsync failed"); ++ sftp_error_trace(s, "fsync"); + return -EIO; + } + +diff --git a/block/trace-events b/block/trace-events +index 4c69548..23c9963 100644 +--- a/block/trace-events ++++ b/block/trace-events +@@ -167,3 +167,6 @@ ssh_write(int64_t offset, size_t size) "offset=%" PRIi64 " size=%zu" + ssh_write_buf(void *buf, size_t size) "sftp_write buf=%p size=%zu" + ssh_write_return(ssize_t ret) "sftp_write returned %zd" + ssh_seek(int64_t offset) "seeking to offset=%" PRIi64 ++ ++# ssh.c ++sftp_error(const char *op, const char *ssh_err, int ssh_err_code, unsigned long sftp_err_code) "%s failed: %s (libssh2 error code: %d, sftp error code: %lu)" +-- +1.8.3.1 + diff --git a/SOURCES/kvm-block-ssh-Implement-.bdrv_refresh_filename.patch b/SOURCES/kvm-block-ssh-Implement-.bdrv_refresh_filename.patch new file mode 100644 index 0000000..ec1b7fb --- /dev/null +++ b/SOURCES/kvm-block-ssh-Implement-.bdrv_refresh_filename.patch @@ -0,0 +1,291 @@ +From cd8ddc9c29115f6f8428fc17fbded67f0ce99004 Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Mon, 8 Jul 2019 15:25:57 +0100 +Subject: [PATCH 11/39] block/ssh: Implement .bdrv_refresh_filename() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Pino Toscano +Message-id: <20190708152601.21123-7-ptoscano@redhat.com> +Patchwork-id: 89417 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v3 06/10] block/ssh: Implement .bdrv_refresh_filename() +Bugzilla: 1513367 +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Max Reitz +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Markus Armbruster + +From: Max Reitz + +This requires some changes to keep iotests 104 and 207 working. + +qemu-img info in 104 will now return a filename including the user name +and the port, which need to be filtered by adjusting REMOTE_TEST_DIR in +common.rc. This additional information has to be marked optional, +however (which is simple as REMOTE_TEST_DIR is a regex), because +otherwise 197 and 215 would fail: They use it (indirectly) to filter +qemu-img create output which contains a backing filename they have +passed to it -- which probably does not contain a user name or port +number. + +The problem in 207 is a nice one to have: qemu-img info used to return +json:{} filenames, but with this patch it returns nice plain ones. We +now need to adjust the filtering to hide the user name (and port number +while we are at it). The simplest way to do this is to include both in +iotests.remote_filename() so that bdrv_refresh_filename() will not +change it, and then iotests.img_info_log() will filter it correctly +automatically. + +Signed-off-by: Max Reitz +Tested-by: Richard W.M. Jones +Message-id: 20190225190828.17726-2-mreitz@redhat.com +Signed-off-by: Max Reitz +(cherry picked from commit b8c1f90118ee81090ff9093790f88bf335132814) +This patch was modified for the lack of 998b3a1e5a2dd23bf89a853e15fab, +by adding the 'QDict *options' parameter to ssh_refresh_filename(), +matching the requested prototype, and setting bs->full_open_options to +the specified option (following the hint of Max Reitz). +Signed-off-by: Pino Toscano + +Signed-off-by: Danilo C. L. de Paula +--- + block/ssh.c | 55 +++++++++++++++++++++++++++++++++++++++---- + tests/qemu-iotests/207 | 10 ++++---- + tests/qemu-iotests/207.out | 10 ++++---- + tests/qemu-iotests/common.rc | 2 +- + tests/qemu-iotests/iotests.py | 2 +- + 5 files changed, 62 insertions(+), 17 deletions(-) + +diff --git a/block/ssh.c b/block/ssh.c +index 89abce0..f0ef874 100644 +--- a/block/ssh.c ++++ b/block/ssh.c +@@ -75,6 +75,14 @@ typedef struct BDRVSSHState { + + /* Used to warn if 'flush' is not supported. */ + bool unsafe_flush_warning; ++ ++ /* ++ * Store the user name for ssh_refresh_filename() because the ++ * default depends on the system you are on -- therefore, when we ++ * generate a filename, it should always contain the user name we ++ * are actually using. ++ */ ++ char *user; + } BDRVSSHState; + + static void ssh_state_init(BDRVSSHState *s) +@@ -87,6 +95,8 @@ static void ssh_state_init(BDRVSSHState *s) + + static void ssh_state_free(BDRVSSHState *s) + { ++ g_free(s->user); ++ + if (s->sftp_handle) { + libssh2_sftp_close(s->sftp_handle); + } +@@ -628,14 +638,13 @@ static int connect_to_ssh(BDRVSSHState *s, BlockdevOptionsSsh *opts, + int ssh_flags, int creat_mode, Error **errp) + { + int r, ret; +- const char *user; + long port = 0; + + if (opts->has_user) { +- user = opts->user; ++ s->user = g_strdup(opts->user); + } else { +- user = g_get_user_name(); +- if (!user) { ++ s->user = g_strdup(g_get_user_name()); ++ if (!s->user) { + error_setg_errno(errp, errno, "Can't get user name"); + ret = -errno; + goto err; +@@ -685,7 +694,7 @@ static int connect_to_ssh(BDRVSSHState *s, BlockdevOptionsSsh *opts, + } + + /* Authenticate. */ +- ret = authenticate(s, user, errp); ++ ret = authenticate(s, s->user, errp); + if (ret < 0) { + goto err; + } +@@ -1240,6 +1249,41 @@ static int coroutine_fn ssh_co_truncate(BlockDriverState *bs, int64_t offset, + return ssh_grow_file(s, offset, errp); + } + ++static void ssh_refresh_filename(BlockDriverState *bs, QDict *options) ++{ ++ BDRVSSHState *s = bs->opaque; ++ const char *path, *host_key_check; ++ int ret; ++ ++ qdict_put_str(options, "driver", "ssh"); ++ bs->full_open_options = qobject_ref(options); ++ ++ /* ++ * None of these options can be represented in a plain "host:port" ++ * format, so if any was given, we have to abort. ++ */ ++ if (s->inet->has_ipv4 || s->inet->has_ipv6 || s->inet->has_to || ++ s->inet->has_numeric) ++ { ++ return; ++ } ++ ++ path = qdict_get_try_str(bs->full_open_options, "path"); ++ assert(path); /* mandatory option */ ++ ++ host_key_check = qdict_get_try_str(bs->full_open_options, "host_key_check"); ++ ++ ret = snprintf(bs->exact_filename, sizeof(bs->exact_filename), ++ "ssh://%s@%s:%s%s%s%s", ++ s->user, s->inet->host, s->inet->port, path, ++ host_key_check ? "?host_key_check=" : "", ++ host_key_check ?: ""); ++ if (ret >= sizeof(bs->exact_filename)) { ++ /* An overflow makes the filename unusable, so do not report any */ ++ bs->exact_filename[0] = '\0'; ++ } ++} ++ + static BlockDriver bdrv_ssh = { + .format_name = "ssh", + .protocol_name = "ssh", +@@ -1255,6 +1299,7 @@ static BlockDriver bdrv_ssh = { + .bdrv_getlength = ssh_getlength, + .bdrv_co_truncate = ssh_co_truncate, + .bdrv_co_flush_to_disk = ssh_co_flush, ++ .bdrv_refresh_filename = ssh_refresh_filename, + .create_opts = &ssh_create_opts, + }; + +diff --git a/tests/qemu-iotests/207 b/tests/qemu-iotests/207 +index 444ae23..8202bd1 100755 +--- a/tests/qemu-iotests/207 ++++ b/tests/qemu-iotests/207 +@@ -62,7 +62,7 @@ with iotests.FilePath('t.img') as disk_path, \ + 'size': 4194304 }) + vm.shutdown() + +- iotests.img_info_log(remote_path, filter_path=disk_path) ++ iotests.img_info_log(remote_path) + iotests.log("") + iotests.img_info_log(disk_path) + +@@ -87,7 +87,7 @@ with iotests.FilePath('t.img') as disk_path, \ + 'size': 8388608 }) + vm.shutdown() + +- iotests.img_info_log(remote_path, filter_path=disk_path) ++ iotests.img_info_log(remote_path) + + vm.launch() + blockdev_create(vm, { 'driver': 'ssh', +@@ -104,7 +104,7 @@ with iotests.FilePath('t.img') as disk_path, \ + 'size': 4194304 }) + vm.shutdown() + +- iotests.img_info_log(remote_path, filter_path=disk_path) ++ iotests.img_info_log(remote_path) + + md5_key = subprocess.check_output( + 'ssh-keyscan -t rsa 127.0.0.1 2>/dev/null | grep -v "\\^#" | ' + +@@ -142,7 +142,7 @@ with iotests.FilePath('t.img') as disk_path, \ + 'size': 8388608 }) + vm.shutdown() + +- iotests.img_info_log(remote_path, filter_path=disk_path) ++ iotests.img_info_log(remote_path) + + sha1_key = subprocess.check_output( + 'ssh-keyscan -t rsa 127.0.0.1 2>/dev/null | grep -v "\\^#" | ' + +@@ -180,7 +180,7 @@ with iotests.FilePath('t.img') as disk_path, \ + 'size': 4194304 }) + vm.shutdown() + +- iotests.img_info_log(remote_path, filter_path=disk_path) ++ iotests.img_info_log(remote_path) + + # + # Invalid path and user +diff --git a/tests/qemu-iotests/207.out b/tests/qemu-iotests/207.out +index 078b7e6..fc131a6 100644 +--- a/tests/qemu-iotests/207.out ++++ b/tests/qemu-iotests/207.out +@@ -5,7 +5,7 @@ + {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} + {u'return': {}} + +-image: json:{"driver": "IMGFMT", "file": {"server.host": "127.0.0.1", "server.port": "22", "driver": "ssh", "path": "TEST_IMG"}} ++image: TEST_IMG + file format: IMGFMT + virtual size: 4.0M (4194304 bytes) + +@@ -21,7 +21,7 @@ virtual size: 4.0M (4194304 bytes) + {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} + {u'return': {}} + +-image: json:{"driver": "IMGFMT", "file": {"server.host": "127.0.0.1", "server.port": "22", "driver": "ssh", "path": "TEST_IMG"}} ++image: TEST_IMG + file format: IMGFMT + virtual size: 8.0M (8388608 bytes) + +@@ -30,7 +30,7 @@ virtual size: 8.0M (8388608 bytes) + {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} + {u'return': {}} + +-image: json:{"driver": "IMGFMT", "file": {"server.host": "127.0.0.1", "server.port": "22", "driver": "ssh", "path": "TEST_IMG"}} ++image: TEST_IMG + file format: IMGFMT + virtual size: 4.0M (4194304 bytes) + +@@ -45,7 +45,7 @@ Job failed: remote host key does not match host_key_check 'wrong' + {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} + {u'return': {}} + +-image: json:{"driver": "IMGFMT", "file": {"server.host": "127.0.0.1", "server.port": "22", "driver": "ssh", "path": "TEST_IMG"}} ++image: TEST_IMG + file format: IMGFMT + virtual size: 8.0M (8388608 bytes) + +@@ -60,7 +60,7 @@ Job failed: remote host key does not match host_key_check 'wrong' + {'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} + {u'return': {}} + +-image: json:{"driver": "IMGFMT", "file": {"server.host": "127.0.0.1", "server.port": "22", "driver": "ssh", "path": "TEST_IMG"}} ++image: TEST_IMG + file format: IMGFMT + virtual size: 4.0M (4194304 bytes) + +diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc +index 6490c8d..9ff8fa1 100644 +--- a/tests/qemu-iotests/common.rc ++++ b/tests/qemu-iotests/common.rc +@@ -145,7 +145,7 @@ else + TEST_IMG="nbd:127.0.0.1:10810" + elif [ "$IMGPROTO" = "ssh" ]; then + TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT +- REMOTE_TEST_DIR="ssh://127.0.0.1$TEST_DIR" ++ REMOTE_TEST_DIR="ssh://\\($USER@\\)\\?127.0.0.1\\(:[0-9]\\+\\)\\?$TEST_DIR" + TEST_IMG="ssh://127.0.0.1$TEST_IMG_FILE" + elif [ "$IMGPROTO" = "nfs" ]; then + TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT +diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py +index 4e67fbb..0f6980a 100644 +--- a/tests/qemu-iotests/iotests.py ++++ b/tests/qemu-iotests/iotests.py +@@ -325,7 +325,7 @@ def remote_filename(path): + if imgproto == 'file': + return path + elif imgproto == 'ssh': +- return "ssh://127.0.0.1%s" % (path) ++ return "ssh://%s@127.0.0.1:22%s" % (os.environ.get('USER'), path) + else: + raise Exception("Protocol %s not supported" % (imgproto)) + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-console-Avoid-segfault-in-screendump.patch b/SOURCES/kvm-console-Avoid-segfault-in-screendump.patch new file mode 100644 index 0000000..9c1c18e --- /dev/null +++ b/SOURCES/kvm-console-Avoid-segfault-in-screendump.patch @@ -0,0 +1,69 @@ +From 60df0d1b59e02c4ef2964473f84b707153ccad58 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Tue, 13 Aug 2019 12:21:56 +0100 +Subject: [PATCH 1/3] console: Avoid segfault in screendump +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Gerd Hoffmann +Message-id: <20190813122156.5609-2-kraxel@redhat.com> +Patchwork-id: 89958 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 1/1] console: Avoid segfault in screendump +Bugzilla: 1684383 +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: John Snow + +From: Michal Privoznik + +After f771c5440e04626f1 it is possible to select device and +head which to take screendump from. And even though we check if +provided head number falls within range, it may still happen that +the console has no surface yet leading to SIGSEGV: + + qemu.git $ ./x86_64-softmmu/qemu-system-x86_64 \ + -qmp stdio \ + -device virtio-vga,id=video0,max_outputs=4 + + {"execute":"qmp_capabilities"} + {"execute":"screendump", "arguments":{"filename":"/tmp/screen.ppm", "device":"video0", "head":1}} + Segmentation fault + + #0 0x00005628249dda88 in ppm_save (filename=0x56282826cbc0 "/tmp/screen.ppm", ds=0x0, errp=0x7fff52a6fae0) at ui/console.c:304 + #1 0x00005628249ddd9b in qmp_screendump (filename=0x56282826cbc0 "/tmp/screen.ppm", has_device=true, device=0x5628276902d0 "video0", has_head=true, head=1, errp=0x7fff52a6fae0) at ui/console.c:375 + #2 0x00005628247740df in qmp_marshal_screendump (args=0x562828265e00, ret=0x7fff52a6fb68, errp=0x7fff52a6fb60) at qapi/qapi-commands-ui.c:110 + +Here, @ds from frame #0 (or @surface from frame #1) is +dereferenced at the very beginning of ppm_save(). And because +it's NULL crash happens. + +Signed-off-by: Michal Privoznik +Reviewed-by: Thomas Huth +Message-id: cb05bb1909daa6ba62145c0194aafa05a14ed3d1.1526569138.git.mprivozn@redhat.com +Signed-off-by: Gerd Hoffmann +(cherry picked from commit 08d9864fa4e0c616e076ca8b225d39a7ecb189af) +Signed-off-by: Danilo C. L. de Paula +--- + ui/console.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/ui/console.c b/ui/console.c +index 594ec63..4e4052f 100644 +--- a/ui/console.c ++++ b/ui/console.c +@@ -370,6 +370,11 @@ void qmp_screendump(const char *filename, bool has_device, const char *device, + + graphic_hw_update(con); + surface = qemu_console_surface(con); ++ if (!surface) { ++ error_setg(errp, "no surface"); ++ return; ++ } ++ + ppm_save(filename, surface, errp); + } + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-crypto-add-testing-for-unaligned-buffers-with-XTS-ci.patch b/SOURCES/kvm-crypto-add-testing-for-unaligned-buffers-with-XTS-ci.patch new file mode 100644 index 0000000..e529f28 --- /dev/null +++ b/SOURCES/kvm-crypto-add-testing-for-unaligned-buffers-with-XTS-ci.patch @@ -0,0 +1,136 @@ +From a5301e637be3cdd123a3688901118e8d8099d29c Mon Sep 17 00:00:00 2001 +From: "Daniel P. Berrange" +Date: Wed, 24 Apr 2019 09:56:43 +0100 +Subject: [PATCH 9/9] crypto: add testing for unaligned buffers with XTS cipher + mode +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Daniel P. Berrange +Message-id: <20190424095643.796-10-berrange@redhat.com> +Patchwork-id: 85886 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 9/9] crypto: add testing for unaligned buffers with XTS cipher mode +Bugzilla: 1680231 +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: John Snow +RH-Acked-by: Eric Blake + +Validate that the XTS cipher mode will correctly operate with plain +text, cipher text and IV buffers that are not 64-bit aligned. + +Reviewed-by: Alberto Garcia +Signed-off-by: Daniel P. Berrangé +(cherry picked from commit 1e0fa32c6c952d2ce9c19d35717c609804dd55d5) +Signed-off-by: Danilo C. L. de Paula +--- + tests/test-crypto-xts.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 86 insertions(+) + +diff --git a/tests/test-crypto-xts.c b/tests/test-crypto-xts.c +index 81606d9..6fb61cf 100644 +--- a/tests/test-crypto-xts.c ++++ b/tests/test-crypto-xts.c +@@ -416,6 +416,88 @@ static void test_xts_split(const void *opaque) + } + + ++static void test_xts_unaligned(const void *opaque) ++{ ++#define BAD_ALIGN 3 ++ const QCryptoXTSTestData *data = opaque; ++ uint8_t in[512 + BAD_ALIGN], out[512 + BAD_ALIGN]; ++ uint8_t Torg[16], T[16 + BAD_ALIGN]; ++ uint64_t seq; ++ struct TestAES aesdata; ++ struct TestAES aestweak; ++ ++ AES_set_encrypt_key(data->key1, data->keylen / 2 * 8, &aesdata.enc); ++ AES_set_decrypt_key(data->key1, data->keylen / 2 * 8, &aesdata.dec); ++ AES_set_encrypt_key(data->key2, data->keylen / 2 * 8, &aestweak.enc); ++ AES_set_decrypt_key(data->key2, data->keylen / 2 * 8, &aestweak.dec); ++ ++ seq = data->seqnum; ++ STORE64L(seq, Torg); ++ memset(Torg + 8, 0, 8); ++ ++ /* IV not aligned */ ++ memcpy(T + BAD_ALIGN, Torg, 16); ++ memcpy(in, data->PTX, data->PTLEN); ++ xts_encrypt(&aesdata, &aestweak, ++ test_xts_aes_encrypt, ++ test_xts_aes_decrypt, ++ T + BAD_ALIGN, data->PTLEN, out, in); ++ ++ g_assert(memcmp(out, data->CTX, data->PTLEN) == 0); ++ ++ /* plain text not aligned */ ++ memcpy(T, Torg, 16); ++ memcpy(in + BAD_ALIGN, data->PTX, data->PTLEN); ++ xts_encrypt(&aesdata, &aestweak, ++ test_xts_aes_encrypt, ++ test_xts_aes_decrypt, ++ T, data->PTLEN, out, in + BAD_ALIGN); ++ ++ g_assert(memcmp(out, data->CTX, data->PTLEN) == 0); ++ ++ /* cipher text not aligned */ ++ memcpy(T, Torg, 16); ++ memcpy(in, data->PTX, data->PTLEN); ++ xts_encrypt(&aesdata, &aestweak, ++ test_xts_aes_encrypt, ++ test_xts_aes_decrypt, ++ T, data->PTLEN, out + BAD_ALIGN, in); ++ ++ g_assert(memcmp(out + BAD_ALIGN, data->CTX, data->PTLEN) == 0); ++ ++ ++ /* IV not aligned */ ++ memcpy(T + BAD_ALIGN, Torg, 16); ++ memcpy(in, data->CTX, data->PTLEN); ++ xts_decrypt(&aesdata, &aestweak, ++ test_xts_aes_encrypt, ++ test_xts_aes_decrypt, ++ T + BAD_ALIGN, data->PTLEN, out, in); ++ ++ g_assert(memcmp(out, data->PTX, data->PTLEN) == 0); ++ ++ /* cipher text not aligned */ ++ memcpy(T, Torg, 16); ++ memcpy(in + BAD_ALIGN, data->CTX, data->PTLEN); ++ xts_decrypt(&aesdata, &aestweak, ++ test_xts_aes_encrypt, ++ test_xts_aes_decrypt, ++ T, data->PTLEN, out, in + BAD_ALIGN); ++ ++ g_assert(memcmp(out, data->PTX, data->PTLEN) == 0); ++ ++ /* plain text not aligned */ ++ memcpy(T, Torg, 16); ++ memcpy(in, data->CTX, data->PTLEN); ++ xts_decrypt(&aesdata, &aestweak, ++ test_xts_aes_encrypt, ++ test_xts_aes_decrypt, ++ T, data->PTLEN, out + BAD_ALIGN, in); ++ ++ g_assert(memcmp(out + BAD_ALIGN, data->PTX, data->PTLEN) == 0); ++} ++ ++ + int main(int argc, char **argv) + { + size_t i; +@@ -437,6 +519,10 @@ int main(int argc, char **argv) + g_test_add_data_func(path, &test_data[i], test_xts_split); + g_free(path); + } ++ ++ path = g_strdup_printf("%s/unaligned", test_data[i].path); ++ g_test_add_data_func(path, &test_data[i], test_xts_unaligned); ++ g_free(path); + } + + return g_test_run(); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-crypto-annotate-xts_tweak_encdec-as-inlineable.patch b/SOURCES/kvm-crypto-annotate-xts_tweak_encdec-as-inlineable.patch new file mode 100644 index 0000000..6f00492 --- /dev/null +++ b/SOURCES/kvm-crypto-annotate-xts_tweak_encdec-as-inlineable.patch @@ -0,0 +1,55 @@ +From 8e0e5d4ff6afd4e869ff1974df13b9b3003f035b Mon Sep 17 00:00:00 2001 +From: "Daniel P. Berrange" +Date: Wed, 24 Apr 2019 09:56:41 +0100 +Subject: [PATCH 7/9] crypto: annotate xts_tweak_encdec as inlineable +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Daniel P. Berrange +Message-id: <20190424095643.796-8-berrange@redhat.com> +Patchwork-id: 85884 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 7/9] crypto: annotate xts_tweak_encdec as inlineable +Bugzilla: 1680231 +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: John Snow +RH-Acked-by: Eric Blake + +Encouraging the compiler to inline xts_tweak_encdec increases the +performance for xts-aes-128 when built with gcrypt: + + Encrypt: 545 MB/s -> 580 MB/s + Decrypt: 568 MB/s -> 602 MB/s + +Reviewed-by: Alberto Garcia +Signed-off-by: Daniel P. Berrangé +(cherry picked from commit aa895bd439341a8f218d8f1a3d21359ba058c13f) +Signed-off-by: Danilo C. L. de Paula +--- + crypto/xts.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/crypto/xts.c b/crypto/xts.c +index 10ec83f..4277ad4 100644 +--- a/crypto/xts.c ++++ b/crypto/xts.c +@@ -81,11 +81,11 @@ static void xts_mult_x(xts_uint128 *I) + * + * Encrypt/decrypt data with a tweak + */ +-static void xts_tweak_encdec(const void *ctx, +- xts_cipher_func *func, +- const xts_uint128 *src, +- xts_uint128 *dst, +- xts_uint128 *iv) ++static inline void xts_tweak_encdec(const void *ctx, ++ xts_cipher_func *func, ++ const xts_uint128 *src, ++ xts_uint128 *dst, ++ xts_uint128 *iv) + { + /* tweak encrypt block i */ + xts_uint128_xor(dst, src, iv); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-crypto-convert-xts_mult_x-to-use-xts_uint128-type.patch b/SOURCES/kvm-crypto-convert-xts_mult_x-to-use-xts_uint128-type.patch new file mode 100644 index 0000000..6c88181 --- /dev/null +++ b/SOURCES/kvm-crypto-convert-xts_mult_x-to-use-xts_uint128-type.patch @@ -0,0 +1,109 @@ +From 5249fe526e66a92e293bc638ab53eb3d8cd68881 Mon Sep 17 00:00:00 2001 +From: "Daniel P. Berrange" +Date: Wed, 24 Apr 2019 09:56:40 +0100 +Subject: [PATCH 6/9] crypto: convert xts_mult_x to use xts_uint128 type +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Daniel P. Berrange +Message-id: <20190424095643.796-7-berrange@redhat.com> +Patchwork-id: 85879 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 6/9] crypto: convert xts_mult_x to use xts_uint128 type +Bugzilla: 1680231 +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: John Snow +RH-Acked-by: Eric Blake + +Using 64-bit arithmetic increases the performance for xts-aes-128 +when built with gcrypt: + + Encrypt: 355 MB/s -> 545 MB/s + Decrypt: 362 MB/s -> 568 MB/s + +Reviewed-by: Alberto Garcia +Signed-off-by: Daniel P. Berrangé +(cherry picked from commit 7dac0dd67426753646df0c23c819609b9e704f59) +Signed-off-by: Danilo C. L. de Paula +--- + crypto/xts.c | 40 ++++++++++++++++++++++++++++------------ + 1 file changed, 28 insertions(+), 12 deletions(-) + +diff --git a/crypto/xts.c b/crypto/xts.c +index 0ad231f..10ec83f 100644 +--- a/crypto/xts.c ++++ b/crypto/xts.c +@@ -24,6 +24,7 @@ + */ + + #include "qemu/osdep.h" ++#include "qemu/bswap.h" + #include "crypto/xts.h" + + typedef union { +@@ -39,19 +40,34 @@ static inline void xts_uint128_xor(xts_uint128 *D, + D->u[1] = S1->u[1] ^ S2->u[1]; + } + +-static void xts_mult_x(uint8_t *I) ++static inline void xts_uint128_cpu_to_les(xts_uint128 *v) + { +- int x; +- uint8_t t, tt; ++ cpu_to_le64s(&v->u[0]); ++ cpu_to_le64s(&v->u[1]); ++} + +- for (x = t = 0; x < 16; x++) { +- tt = I[x] >> 7; +- I[x] = ((I[x] << 1) | t) & 0xFF; +- t = tt; +- } +- if (tt) { +- I[0] ^= 0x87; ++static inline void xts_uint128_le_to_cpus(xts_uint128 *v) ++{ ++ le64_to_cpus(&v->u[0]); ++ le64_to_cpus(&v->u[1]); ++} ++ ++static void xts_mult_x(xts_uint128 *I) ++{ ++ uint64_t tt; ++ ++ xts_uint128_le_to_cpus(I); ++ ++ tt = I->u[0] >> 63; ++ I->u[0] <<= 1; ++ ++ if (I->u[1] >> 63) { ++ I->u[0] ^= 0x87; + } ++ I->u[1] <<= 1; ++ I->u[1] |= tt; ++ ++ xts_uint128_cpu_to_les(I); + } + + +@@ -79,7 +95,7 @@ static void xts_tweak_encdec(const void *ctx, + xts_uint128_xor(dst, dst, iv); + + /* LFSR the tweak */ +- xts_mult_x(iv->b); ++ xts_mult_x(iv); + } + + +@@ -134,7 +150,7 @@ void xts_decrypt(const void *datactx, + if (mo > 0) { + xts_uint128 S, D; + memcpy(&CC, &T, XTS_BLOCK_SIZE); +- xts_mult_x(CC.b); ++ xts_mult_x(&CC); + + /* PP = tweak decrypt block m-1 */ + memcpy(&S, src, XTS_BLOCK_SIZE); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-crypto-convert-xts_tweak_encdec-to-use-xts_uint128-t.patch b/SOURCES/kvm-crypto-convert-xts_tweak_encdec-to-use-xts_uint128-t.patch new file mode 100644 index 0000000..d09813f --- /dev/null +++ b/SOURCES/kvm-crypto-convert-xts_tweak_encdec-to-use-xts_uint128-t.patch @@ -0,0 +1,184 @@ +From 8e7643e39fc0c539f55d85263e87f64dca52efea Mon Sep 17 00:00:00 2001 +From: "Daniel P. Berrange" +Date: Wed, 24 Apr 2019 09:56:39 +0100 +Subject: [PATCH 5/9] crypto: convert xts_tweak_encdec to use xts_uint128 type +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Daniel P. Berrange +Message-id: <20190424095643.796-6-berrange@redhat.com> +Patchwork-id: 85883 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 5/9] crypto: convert xts_tweak_encdec to use xts_uint128 type +Bugzilla: 1680231 +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: John Snow +RH-Acked-by: Eric Blake + +Using 64-bit arithmetic increases the performance for xts-aes-128 +when built with gcrypt: + + Encrypt: 272 MB/s -> 355 MB/s + Decrypt: 275 MB/s -> 362 MB/s + +Reviewed-by: Alberto Garcia +Signed-off-by: Daniel P. Berrangé +(cherry picked from commit db217c69f0849add67cfa2cd6601c329398be12c) +Signed-off-by: Danilo C. L. de Paula +--- + crypto/xts.c | 84 +++++++++++++++++++++++++++++++++++++++++------------------- + 1 file changed, 58 insertions(+), 26 deletions(-) + +diff --git a/crypto/xts.c b/crypto/xts.c +index bee23f8..0ad231f 100644 +--- a/crypto/xts.c ++++ b/crypto/xts.c +@@ -31,6 +31,13 @@ typedef union { + uint64_t u[2]; + } xts_uint128; + ++static inline void xts_uint128_xor(xts_uint128 *D, ++ const xts_uint128 *S1, ++ const xts_uint128 *S2) ++{ ++ D->u[0] = S1->u[0] ^ S2->u[0]; ++ D->u[1] = S1->u[1] ^ S2->u[1]; ++} + + static void xts_mult_x(uint8_t *I) + { +@@ -60,25 +67,19 @@ static void xts_mult_x(uint8_t *I) + */ + static void xts_tweak_encdec(const void *ctx, + xts_cipher_func *func, +- const uint8_t *src, +- uint8_t *dst, +- uint8_t *iv) ++ const xts_uint128 *src, ++ xts_uint128 *dst, ++ xts_uint128 *iv) + { +- unsigned long x; +- + /* tweak encrypt block i */ +- for (x = 0; x < XTS_BLOCK_SIZE; x++) { +- dst[x] = src[x] ^ iv[x]; +- } ++ xts_uint128_xor(dst, src, iv); + +- func(ctx, XTS_BLOCK_SIZE, dst, dst); ++ func(ctx, XTS_BLOCK_SIZE, dst->b, dst->b); + +- for (x = 0; x < XTS_BLOCK_SIZE; x++) { +- dst[x] = dst[x] ^ iv[x]; +- } ++ xts_uint128_xor(dst, dst, iv); + + /* LFSR the tweak */ +- xts_mult_x(iv); ++ xts_mult_x(iv->b); + } + + +@@ -110,20 +111,34 @@ void xts_decrypt(const void *datactx, + /* encrypt the iv */ + encfunc(tweakctx, XTS_BLOCK_SIZE, T.b, iv); + +- for (i = 0; i < lim; i++) { +- xts_tweak_encdec(datactx, decfunc, src, dst, T.b); +- +- src += XTS_BLOCK_SIZE; +- dst += XTS_BLOCK_SIZE; ++ if (QEMU_PTR_IS_ALIGNED(src, sizeof(uint64_t)) && ++ QEMU_PTR_IS_ALIGNED(dst, sizeof(uint64_t))) { ++ xts_uint128 *S = (xts_uint128 *)src; ++ xts_uint128 *D = (xts_uint128 *)dst; ++ for (i = 0; i < lim; i++, S++, D++) { ++ xts_tweak_encdec(datactx, decfunc, S, D, &T); ++ } ++ } else { ++ xts_uint128 D; ++ ++ for (i = 0; i < lim; i++) { ++ memcpy(&D, src, XTS_BLOCK_SIZE); ++ xts_tweak_encdec(datactx, decfunc, &D, &D, &T); ++ memcpy(dst, &D, XTS_BLOCK_SIZE); ++ src += XTS_BLOCK_SIZE; ++ dst += XTS_BLOCK_SIZE; ++ } + } + + /* if length is not a multiple of XTS_BLOCK_SIZE then */ + if (mo > 0) { ++ xts_uint128 S, D; + memcpy(&CC, &T, XTS_BLOCK_SIZE); + xts_mult_x(CC.b); + + /* PP = tweak decrypt block m-1 */ +- xts_tweak_encdec(datactx, decfunc, src, PP.b, CC.b); ++ memcpy(&S, src, XTS_BLOCK_SIZE); ++ xts_tweak_encdec(datactx, decfunc, &S, &PP, &CC); + + /* Pm = first length % XTS_BLOCK_SIZE bytes of PP */ + for (i = 0; i < mo; i++) { +@@ -135,7 +150,8 @@ void xts_decrypt(const void *datactx, + } + + /* Pm-1 = Tweak uncrypt CC */ +- xts_tweak_encdec(datactx, decfunc, CC.b, dst, T.b); ++ xts_tweak_encdec(datactx, decfunc, &CC, &D, &T); ++ memcpy(dst, &D, XTS_BLOCK_SIZE); + } + + /* Decrypt the iv back */ +@@ -171,17 +187,32 @@ void xts_encrypt(const void *datactx, + /* encrypt the iv */ + encfunc(tweakctx, XTS_BLOCK_SIZE, T.b, iv); + +- for (i = 0; i < lim; i++) { +- xts_tweak_encdec(datactx, encfunc, src, dst, T.b); ++ if (QEMU_PTR_IS_ALIGNED(src, sizeof(uint64_t)) && ++ QEMU_PTR_IS_ALIGNED(dst, sizeof(uint64_t))) { ++ xts_uint128 *S = (xts_uint128 *)src; ++ xts_uint128 *D = (xts_uint128 *)dst; ++ for (i = 0; i < lim; i++, S++, D++) { ++ xts_tweak_encdec(datactx, encfunc, S, D, &T); ++ } ++ } else { ++ xts_uint128 D; ++ ++ for (i = 0; i < lim; i++) { ++ memcpy(&D, src, XTS_BLOCK_SIZE); ++ xts_tweak_encdec(datactx, encfunc, &D, &D, &T); ++ memcpy(dst, &D, XTS_BLOCK_SIZE); + +- dst += XTS_BLOCK_SIZE; +- src += XTS_BLOCK_SIZE; ++ dst += XTS_BLOCK_SIZE; ++ src += XTS_BLOCK_SIZE; ++ } + } + + /* if length is not a multiple of XTS_BLOCK_SIZE then */ + if (mo > 0) { ++ xts_uint128 S, D; + /* CC = tweak encrypt block m-1 */ +- xts_tweak_encdec(datactx, encfunc, src, CC.b, T.b); ++ memcpy(&S, src, XTS_BLOCK_SIZE); ++ xts_tweak_encdec(datactx, encfunc, &S, &CC, &T); + + /* Cm = first length % XTS_BLOCK_SIZE bytes of CC */ + for (i = 0; i < mo; i++) { +@@ -194,7 +225,8 @@ void xts_encrypt(const void *datactx, + } + + /* Cm-1 = Tweak encrypt PP */ +- xts_tweak_encdec(datactx, encfunc, PP.b, dst, T.b); ++ xts_tweak_encdec(datactx, encfunc, &PP, &D, &T); ++ memcpy(dst, &D, XTS_BLOCK_SIZE); + } + + /* Decrypt the iv back */ +-- +1.8.3.1 + diff --git a/SOURCES/kvm-crypto-expand-algorithm-coverage-for-cipher-benchmar.patch b/SOURCES/kvm-crypto-expand-algorithm-coverage-for-cipher-benchmar.patch new file mode 100644 index 0000000..6380fbd --- /dev/null +++ b/SOURCES/kvm-crypto-expand-algorithm-coverage-for-cipher-benchmar.patch @@ -0,0 +1,228 @@ +From 9f7d3aa69a0ab745301f6811df498e7aa2a51a26 Mon Sep 17 00:00:00 2001 +From: "Daniel P. Berrange" +Date: Wed, 24 Apr 2019 09:56:36 +0100 +Subject: [PATCH 2/9] crypto: expand algorithm coverage for cipher benchmark +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Daniel P. Berrange +Message-id: <20190424095643.796-3-berrange@redhat.com> +Patchwork-id: 85880 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 2/9] crypto: expand algorithm coverage for cipher benchmark +Bugzilla: 1680231 +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: John Snow +RH-Acked-by: Eric Blake + +Add testing coverage for AES with XTS, ECB and CTR modes + +Reviewed-by: Marc-André Lureau +Reviewed-by: Alberto Garcia +Signed-off-by: Daniel P. Berrangé +(cherry picked from commit a9e08155bd4ae096688a8ff19669023ab0fbc170) +Signed-off-by: Danilo C. L. de Paula +--- + tests/benchmark-crypto-cipher.c | 149 +++++++++++++++++++++++++++++++++------- + 1 file changed, 126 insertions(+), 23 deletions(-) + +diff --git a/tests/benchmark-crypto-cipher.c b/tests/benchmark-crypto-cipher.c +index f5a0d0b..67fdf8c 100644 +--- a/tests/benchmark-crypto-cipher.c ++++ b/tests/benchmark-crypto-cipher.c +@@ -15,17 +15,27 @@ + #include "crypto/init.h" + #include "crypto/cipher.h" + +-static void test_cipher_speed(const void *opaque) ++static void test_cipher_speed(size_t chunk_size, ++ QCryptoCipherMode mode, ++ QCryptoCipherAlgorithm alg) + { + QCryptoCipher *cipher; + Error *err = NULL; + double total = 0.0; +- size_t chunk_size = (size_t)opaque; + uint8_t *key = NULL, *iv = NULL; + uint8_t *plaintext = NULL, *ciphertext = NULL; +- size_t nkey = qcrypto_cipher_get_key_len(QCRYPTO_CIPHER_ALG_AES_128); +- size_t niv = qcrypto_cipher_get_iv_len(QCRYPTO_CIPHER_ALG_AES_128, +- QCRYPTO_CIPHER_MODE_CBC); ++ size_t nkey; ++ size_t niv; ++ ++ if (!qcrypto_cipher_supports(alg, mode)) { ++ return; ++ } ++ ++ nkey = qcrypto_cipher_get_key_len(alg); ++ niv = qcrypto_cipher_get_iv_len(alg, mode); ++ if (mode == QCRYPTO_CIPHER_MODE_XTS) { ++ nkey *= 2; ++ } + + key = g_new0(uint8_t, nkey); + memset(key, g_test_rand_int(), nkey); +@@ -38,14 +48,14 @@ static void test_cipher_speed(const void *opaque) + plaintext = g_new0(uint8_t, chunk_size); + memset(plaintext, g_test_rand_int(), chunk_size); + +- cipher = qcrypto_cipher_new(QCRYPTO_CIPHER_ALG_AES_128, +- QCRYPTO_CIPHER_MODE_CBC, ++ cipher = qcrypto_cipher_new(alg, mode, + key, nkey, &err); + g_assert(cipher != NULL); + +- g_assert(qcrypto_cipher_setiv(cipher, +- iv, niv, +- &err) == 0); ++ if (mode != QCRYPTO_CIPHER_MODE_ECB) ++ g_assert(qcrypto_cipher_setiv(cipher, ++ iv, niv, ++ &err) == 0); + + g_test_timer_start(); + do { +@@ -55,13 +65,26 @@ static void test_cipher_speed(const void *opaque) + chunk_size, + &err) == 0); + total += chunk_size; +- } while (g_test_timer_elapsed() < 5.0); ++ } while (g_test_timer_elapsed() < 1.0); + + total /= MiB; +- g_print("cbc(aes128): "); +- g_print("Testing chunk_size %zu bytes ", chunk_size); +- g_print("done: %.2f MB in %.2f secs: ", total, g_test_timer_last()); +- g_print("%.2f MB/sec\n", total / g_test_timer_last()); ++ g_print("Enc chunk %zu bytes ", chunk_size); ++ g_print("%.2f MB/sec ", total / g_test_timer_last()); ++ ++ total = 0.0; ++ g_test_timer_start(); ++ do { ++ g_assert(qcrypto_cipher_decrypt(cipher, ++ plaintext, ++ ciphertext, ++ chunk_size, ++ &err) == 0); ++ total += chunk_size; ++ } while (g_test_timer_elapsed() < 1.0); ++ ++ total /= MiB; ++ g_print("Dec chunk %zu bytes ", chunk_size); ++ g_print("%.2f MB/sec ", total / g_test_timer_last()); + + qcrypto_cipher_free(cipher); + g_free(plaintext); +@@ -70,19 +93,99 @@ static void test_cipher_speed(const void *opaque) + g_free(key); + } + +-int main(int argc, char **argv) ++ ++static void test_cipher_speed_ecb_aes_128(const void *opaque) ++{ ++ size_t chunk_size = (size_t)opaque; ++ test_cipher_speed(chunk_size, ++ QCRYPTO_CIPHER_MODE_ECB, ++ QCRYPTO_CIPHER_ALG_AES_128); ++} ++ ++static void test_cipher_speed_ecb_aes_256(const void *opaque) + { +- size_t i; +- char name[64]; ++ size_t chunk_size = (size_t)opaque; ++ test_cipher_speed(chunk_size, ++ QCRYPTO_CIPHER_MODE_ECB, ++ QCRYPTO_CIPHER_ALG_AES_256); ++} ++ ++static void test_cipher_speed_cbc_aes_128(const void *opaque) ++{ ++ size_t chunk_size = (size_t)opaque; ++ test_cipher_speed(chunk_size, ++ QCRYPTO_CIPHER_MODE_CBC, ++ QCRYPTO_CIPHER_ALG_AES_128); ++} + ++static void test_cipher_speed_cbc_aes_256(const void *opaque) ++{ ++ size_t chunk_size = (size_t)opaque; ++ test_cipher_speed(chunk_size, ++ QCRYPTO_CIPHER_MODE_CBC, ++ QCRYPTO_CIPHER_ALG_AES_256); ++} ++ ++static void test_cipher_speed_ctr_aes_128(const void *opaque) ++{ ++ size_t chunk_size = (size_t)opaque; ++ test_cipher_speed(chunk_size, ++ QCRYPTO_CIPHER_MODE_CTR, ++ QCRYPTO_CIPHER_ALG_AES_128); ++} ++ ++static void test_cipher_speed_ctr_aes_256(const void *opaque) ++{ ++ size_t chunk_size = (size_t)opaque; ++ test_cipher_speed(chunk_size, ++ QCRYPTO_CIPHER_MODE_CTR, ++ QCRYPTO_CIPHER_ALG_AES_256); ++} ++ ++static void test_cipher_speed_xts_aes_128(const void *opaque) ++{ ++ size_t chunk_size = (size_t)opaque; ++ test_cipher_speed(chunk_size, ++ QCRYPTO_CIPHER_MODE_XTS, ++ QCRYPTO_CIPHER_ALG_AES_128); ++} ++ ++static void test_cipher_speed_xts_aes_256(const void *opaque) ++{ ++ size_t chunk_size = (size_t)opaque; ++ test_cipher_speed(chunk_size, ++ QCRYPTO_CIPHER_MODE_XTS, ++ QCRYPTO_CIPHER_ALG_AES_256); ++} ++ ++ ++int main(int argc, char **argv) ++{ + g_test_init(&argc, &argv, NULL); + g_assert(qcrypto_init(NULL) == 0); + +- for (i = 512; i <= 64 * KiB; i *= 2) { +- memset(name, 0 , sizeof(name)); +- snprintf(name, sizeof(name), "/crypto/cipher/speed-%zu", i); +- g_test_add_data_func(name, (void *)i, test_cipher_speed); +- } ++#define ADD_TEST(mode, cipher, keysize, chunk) \ ++ g_test_add_data_func( \ ++ "/crypto/cipher/" #mode "-" #cipher "-" #keysize "/chunk-" #chunk, \ ++ (void *)chunk, \ ++ test_cipher_speed_ ## mode ## _ ## cipher ## _ ## keysize) ++ ++#define ADD_TESTS(chunk) \ ++ do { \ ++ ADD_TEST(ecb, aes, 128, chunk); \ ++ ADD_TEST(ecb, aes, 256, chunk); \ ++ ADD_TEST(cbc, aes, 128, chunk); \ ++ ADD_TEST(cbc, aes, 256, chunk); \ ++ ADD_TEST(ctr, aes, 128, chunk); \ ++ ADD_TEST(ctr, aes, 256, chunk); \ ++ ADD_TEST(xts, aes, 128, chunk); \ ++ ADD_TEST(xts, aes, 256, chunk); \ ++ } while (0) ++ ++ ADD_TESTS(512); ++ ADD_TESTS(4096); ++ ADD_TESTS(16384); ++ ADD_TESTS(65536); + + return g_test_run(); + } +-- +1.8.3.1 + diff --git a/SOURCES/kvm-crypto-introduce-a-xts_uint128-data-type.patch b/SOURCES/kvm-crypto-introduce-a-xts_uint128-data-type.patch new file mode 100644 index 0000000..ac53a49 --- /dev/null +++ b/SOURCES/kvm-crypto-introduce-a-xts_uint128-data-type.patch @@ -0,0 +1,158 @@ +From e485d0702e2acf9b83aaf42f4cc62d804c1c282a Mon Sep 17 00:00:00 2001 +From: "Daniel P. Berrange" +Date: Wed, 24 Apr 2019 09:56:38 +0100 +Subject: [PATCH 4/9] crypto: introduce a xts_uint128 data type +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Daniel P. Berrange +Message-id: <20190424095643.796-5-berrange@redhat.com> +Patchwork-id: 85882 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 4/9] crypto: introduce a xts_uint128 data type +Bugzilla: 1680231 +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: John Snow +RH-Acked-by: Eric Blake + +The new type is designed to allow use of 64-bit arithmetic instead +of operating 1-byte at a time. The following patches will use this to +improve performance. + +Reviewed-by: Alberto Garcia +Signed-off-by: Daniel P. Berrangé +(cherry picked from commit cc36930e4077eb3dbee6cd30d2d826ec62b3490a) +Signed-off-by: Danilo C. L. de Paula +--- + crypto/xts.c | 46 ++++++++++++++++++++++++++-------------------- + 1 file changed, 26 insertions(+), 20 deletions(-) + +diff --git a/crypto/xts.c b/crypto/xts.c +index 3c1a92f..bee23f8 100644 +--- a/crypto/xts.c ++++ b/crypto/xts.c +@@ -26,6 +26,12 @@ + #include "qemu/osdep.h" + #include "crypto/xts.h" + ++typedef union { ++ uint8_t b[XTS_BLOCK_SIZE]; ++ uint64_t u[2]; ++} xts_uint128; ++ ++ + static void xts_mult_x(uint8_t *I) + { + int x; +@@ -85,7 +91,7 @@ void xts_decrypt(const void *datactx, + uint8_t *dst, + const uint8_t *src) + { +- uint8_t PP[XTS_BLOCK_SIZE], CC[XTS_BLOCK_SIZE], T[XTS_BLOCK_SIZE]; ++ xts_uint128 PP, CC, T; + unsigned long i, m, mo, lim; + + /* get number of blocks */ +@@ -102,10 +108,10 @@ void xts_decrypt(const void *datactx, + } + + /* encrypt the iv */ +- encfunc(tweakctx, XTS_BLOCK_SIZE, T, iv); ++ encfunc(tweakctx, XTS_BLOCK_SIZE, T.b, iv); + + for (i = 0; i < lim; i++) { +- xts_tweak_encdec(datactx, decfunc, src, dst, T); ++ xts_tweak_encdec(datactx, decfunc, src, dst, T.b); + + src += XTS_BLOCK_SIZE; + dst += XTS_BLOCK_SIZE; +@@ -113,27 +119,27 @@ void xts_decrypt(const void *datactx, + + /* if length is not a multiple of XTS_BLOCK_SIZE then */ + if (mo > 0) { +- memcpy(CC, T, XTS_BLOCK_SIZE); +- xts_mult_x(CC); ++ memcpy(&CC, &T, XTS_BLOCK_SIZE); ++ xts_mult_x(CC.b); + + /* PP = tweak decrypt block m-1 */ +- xts_tweak_encdec(datactx, decfunc, src, PP, CC); ++ xts_tweak_encdec(datactx, decfunc, src, PP.b, CC.b); + + /* Pm = first length % XTS_BLOCK_SIZE bytes of PP */ + for (i = 0; i < mo; i++) { +- CC[i] = src[XTS_BLOCK_SIZE + i]; +- dst[XTS_BLOCK_SIZE + i] = PP[i]; ++ CC.b[i] = src[XTS_BLOCK_SIZE + i]; ++ dst[XTS_BLOCK_SIZE + i] = PP.b[i]; + } + for (; i < XTS_BLOCK_SIZE; i++) { +- CC[i] = PP[i]; ++ CC.b[i] = PP.b[i]; + } + + /* Pm-1 = Tweak uncrypt CC */ +- xts_tweak_encdec(datactx, decfunc, CC, dst, T); ++ xts_tweak_encdec(datactx, decfunc, CC.b, dst, T.b); + } + + /* Decrypt the iv back */ +- decfunc(tweakctx, XTS_BLOCK_SIZE, iv, T); ++ decfunc(tweakctx, XTS_BLOCK_SIZE, iv, T.b); + } + + +@@ -146,7 +152,7 @@ void xts_encrypt(const void *datactx, + uint8_t *dst, + const uint8_t *src) + { +- uint8_t PP[XTS_BLOCK_SIZE], CC[XTS_BLOCK_SIZE], T[XTS_BLOCK_SIZE]; ++ xts_uint128 PP, CC, T; + unsigned long i, m, mo, lim; + + /* get number of blocks */ +@@ -163,10 +169,10 @@ void xts_encrypt(const void *datactx, + } + + /* encrypt the iv */ +- encfunc(tweakctx, XTS_BLOCK_SIZE, T, iv); ++ encfunc(tweakctx, XTS_BLOCK_SIZE, T.b, iv); + + for (i = 0; i < lim; i++) { +- xts_tweak_encdec(datactx, encfunc, src, dst, T); ++ xts_tweak_encdec(datactx, encfunc, src, dst, T.b); + + dst += XTS_BLOCK_SIZE; + src += XTS_BLOCK_SIZE; +@@ -175,22 +181,22 @@ void xts_encrypt(const void *datactx, + /* if length is not a multiple of XTS_BLOCK_SIZE then */ + if (mo > 0) { + /* CC = tweak encrypt block m-1 */ +- xts_tweak_encdec(datactx, encfunc, src, CC, T); ++ xts_tweak_encdec(datactx, encfunc, src, CC.b, T.b); + + /* Cm = first length % XTS_BLOCK_SIZE bytes of CC */ + for (i = 0; i < mo; i++) { +- PP[i] = src[XTS_BLOCK_SIZE + i]; +- dst[XTS_BLOCK_SIZE + i] = CC[i]; ++ PP.b[i] = src[XTS_BLOCK_SIZE + i]; ++ dst[XTS_BLOCK_SIZE + i] = CC.b[i]; + } + + for (; i < XTS_BLOCK_SIZE; i++) { +- PP[i] = CC[i]; ++ PP.b[i] = CC.b[i]; + } + + /* Cm-1 = Tweak encrypt PP */ +- xts_tweak_encdec(datactx, encfunc, PP, dst, T); ++ xts_tweak_encdec(datactx, encfunc, PP.b, dst, T.b); + } + + /* Decrypt the iv back */ +- decfunc(tweakctx, XTS_BLOCK_SIZE, iv, T); ++ decfunc(tweakctx, XTS_BLOCK_SIZE, iv, T.b); + } +-- +1.8.3.1 + diff --git a/SOURCES/kvm-crypto-refactor-XTS-cipher-mode-test-suite.patch b/SOURCES/kvm-crypto-refactor-XTS-cipher-mode-test-suite.patch new file mode 100644 index 0000000..9bf3997 --- /dev/null +++ b/SOURCES/kvm-crypto-refactor-XTS-cipher-mode-test-suite.patch @@ -0,0 +1,203 @@ +From 8b0cd52cde37fa503ab36eb7ce31bdd3a8e88aac Mon Sep 17 00:00:00 2001 +From: "Daniel P. Berrange" +Date: Wed, 24 Apr 2019 09:56:42 +0100 +Subject: [PATCH 8/9] crypto: refactor XTS cipher mode test suite +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Daniel P. Berrange +Message-id: <20190424095643.796-9-berrange@redhat.com> +Patchwork-id: 85885 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 8/9] crypto: refactor XTS cipher mode test suite +Bugzilla: 1680231 +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: John Snow +RH-Acked-by: Eric Blake + +The current XTS test overloads two different tests in a single function +making the code a little hard to follow. Split it into distinct test +cases. + +Reviewed-by: Alberto Garcia +Signed-off-by: Daniel P. Berrangé +(cherry picked from commit a61f682fde664467c4b4dd498ea84338598c8cbd) +Signed-off-by: Danilo C. L. de Paula +--- + tests/test-crypto-xts.c | 140 +++++++++++++++++++++++++++--------------------- + 1 file changed, 80 insertions(+), 60 deletions(-) + +diff --git a/tests/test-crypto-xts.c b/tests/test-crypto-xts.c +index 1f1412c..81606d9 100644 +--- a/tests/test-crypto-xts.c ++++ b/tests/test-crypto-xts.c +@@ -1,7 +1,7 @@ + /* + * QEMU Crypto XTS cipher mode + * +- * Copyright (c) 2015-2016 Red Hat, Inc. ++ * Copyright (c) 2015-2018 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public +@@ -340,70 +340,79 @@ static void test_xts_aes_decrypt(const void *ctx, + static void test_xts(const void *opaque) + { + const QCryptoXTSTestData *data = opaque; +- unsigned char out[512], Torg[16], T[16]; ++ uint8_t out[512], Torg[16], T[16]; + uint64_t seq; +- int j; +- unsigned long len; + struct TestAES aesdata; + struct TestAES aestweak; + +- for (j = 0; j < 2; j++) { +- /* skip the cases where +- * the length is smaller than 2*blocklen +- * or the length is not a multiple of 32 +- */ +- if ((j == 1) && ((data->PTLEN < 32) || (data->PTLEN % 32))) { +- continue; +- } +- len = data->PTLEN / 2; +- +- AES_set_encrypt_key(data->key1, data->keylen / 2 * 8, &aesdata.enc); +- AES_set_decrypt_key(data->key1, data->keylen / 2 * 8, &aesdata.dec); +- AES_set_encrypt_key(data->key2, data->keylen / 2 * 8, &aestweak.enc); +- AES_set_decrypt_key(data->key2, data->keylen / 2 * 8, &aestweak.dec); +- +- seq = data->seqnum; +- STORE64L(seq, Torg); +- memset(Torg + 8, 0, 8); +- +- memcpy(T, Torg, sizeof(T)); +- if (j == 0) { +- xts_encrypt(&aesdata, &aestweak, +- test_xts_aes_encrypt, +- test_xts_aes_decrypt, +- T, data->PTLEN, out, data->PTX); +- } else { +- xts_encrypt(&aesdata, &aestweak, +- test_xts_aes_encrypt, +- test_xts_aes_decrypt, +- T, len, out, data->PTX); +- xts_encrypt(&aesdata, &aestweak, +- test_xts_aes_encrypt, +- test_xts_aes_decrypt, +- T, len, &out[len], &data->PTX[len]); +- } ++ AES_set_encrypt_key(data->key1, data->keylen / 2 * 8, &aesdata.enc); ++ AES_set_decrypt_key(data->key1, data->keylen / 2 * 8, &aesdata.dec); ++ AES_set_encrypt_key(data->key2, data->keylen / 2 * 8, &aestweak.enc); ++ AES_set_decrypt_key(data->key2, data->keylen / 2 * 8, &aestweak.dec); + +- g_assert(memcmp(out, data->CTX, data->PTLEN) == 0); +- +- memcpy(T, Torg, sizeof(T)); +- if (j == 0) { +- xts_decrypt(&aesdata, &aestweak, +- test_xts_aes_encrypt, +- test_xts_aes_decrypt, +- T, data->PTLEN, out, data->CTX); +- } else { +- xts_decrypt(&aesdata, &aestweak, +- test_xts_aes_encrypt, +- test_xts_aes_decrypt, +- T, len, out, data->CTX); +- xts_decrypt(&aesdata, &aestweak, +- test_xts_aes_encrypt, +- test_xts_aes_decrypt, +- T, len, &out[len], &data->CTX[len]); +- } ++ seq = data->seqnum; ++ STORE64L(seq, Torg); ++ memset(Torg + 8, 0, 8); + +- g_assert(memcmp(out, data->PTX, data->PTLEN) == 0); +- } ++ memcpy(T, Torg, sizeof(T)); ++ xts_encrypt(&aesdata, &aestweak, ++ test_xts_aes_encrypt, ++ test_xts_aes_decrypt, ++ T, data->PTLEN, out, data->PTX); ++ ++ g_assert(memcmp(out, data->CTX, data->PTLEN) == 0); ++ ++ memcpy(T, Torg, sizeof(T)); ++ xts_decrypt(&aesdata, &aestweak, ++ test_xts_aes_encrypt, ++ test_xts_aes_decrypt, ++ T, data->PTLEN, out, data->CTX); ++ ++ g_assert(memcmp(out, data->PTX, data->PTLEN) == 0); ++} ++ ++ ++static void test_xts_split(const void *opaque) ++{ ++ const QCryptoXTSTestData *data = opaque; ++ uint8_t out[512], Torg[16], T[16]; ++ uint64_t seq; ++ unsigned long len = data->PTLEN / 2; ++ struct TestAES aesdata; ++ struct TestAES aestweak; ++ ++ AES_set_encrypt_key(data->key1, data->keylen / 2 * 8, &aesdata.enc); ++ AES_set_decrypt_key(data->key1, data->keylen / 2 * 8, &aesdata.dec); ++ AES_set_encrypt_key(data->key2, data->keylen / 2 * 8, &aestweak.enc); ++ AES_set_decrypt_key(data->key2, data->keylen / 2 * 8, &aestweak.dec); ++ ++ seq = data->seqnum; ++ STORE64L(seq, Torg); ++ memset(Torg + 8, 0, 8); ++ ++ memcpy(T, Torg, sizeof(T)); ++ xts_encrypt(&aesdata, &aestweak, ++ test_xts_aes_encrypt, ++ test_xts_aes_decrypt, ++ T, len, out, data->PTX); ++ xts_encrypt(&aesdata, &aestweak, ++ test_xts_aes_encrypt, ++ test_xts_aes_decrypt, ++ T, len, &out[len], &data->PTX[len]); ++ ++ g_assert(memcmp(out, data->CTX, data->PTLEN) == 0); ++ ++ memcpy(T, Torg, sizeof(T)); ++ xts_decrypt(&aesdata, &aestweak, ++ test_xts_aes_encrypt, ++ test_xts_aes_decrypt, ++ T, len, out, data->CTX); ++ xts_decrypt(&aesdata, &aestweak, ++ test_xts_aes_encrypt, ++ test_xts_aes_decrypt, ++ T, len, &out[len], &data->CTX[len]); ++ ++ g_assert(memcmp(out, data->PTX, data->PTLEN) == 0); + } + + +@@ -416,7 +425,18 @@ int main(int argc, char **argv) + g_assert(qcrypto_init(NULL) == 0); + + for (i = 0; i < G_N_ELEMENTS(test_data); i++) { +- g_test_add_data_func(test_data[i].path, &test_data[i], test_xts); ++ gchar *path = g_strdup_printf("%s/basic", test_data[i].path); ++ g_test_add_data_func(path, &test_data[i], test_xts); ++ g_free(path); ++ ++ /* skip the cases where the length is smaller than 2*blocklen ++ * or the length is not a multiple of 32 ++ */ ++ if ((test_data[i].PTLEN >= 32) && !(test_data[i].PTLEN % 32)) { ++ path = g_strdup_printf("%s/split", test_data[i].path); ++ g_test_add_data_func(path, &test_data[i], test_xts_split); ++ g_free(path); ++ } + } + + return g_test_run(); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-crypto-remove-code-duplication-in-tweak-encrypt-decr.patch b/SOURCES/kvm-crypto-remove-code-duplication-in-tweak-encrypt-decr.patch new file mode 100644 index 0000000..757734d --- /dev/null +++ b/SOURCES/kvm-crypto-remove-code-duplication-in-tweak-encrypt-decr.patch @@ -0,0 +1,162 @@ +From cfa8288b73c3a2856a56bef220b7468b402905c3 Mon Sep 17 00:00:00 2001 +From: "Daniel P. Berrange" +Date: Wed, 24 Apr 2019 09:56:37 +0100 +Subject: [PATCH 3/9] crypto: remove code duplication in tweak encrypt/decrypt +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Daniel P. Berrange +Message-id: <20190424095643.796-4-berrange@redhat.com> +Patchwork-id: 85881 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 3/9] crypto: remove code duplication in tweak encrypt/decrypt +Bugzilla: 1680231 +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: John Snow +RH-Acked-by: Eric Blake + +The tweak encrypt/decrypt functions are identical except for the +comments, so can be merged. Profiling data shows that the compiler is +in fact already merging the two merges in the object files. + +Reviewed-by: Marc-André Lureau +Reviewed-by: Alberto Garcia +Signed-off-by: Daniel P. Berrangé +(cherry picked from commit 299ec87838babdf38be618cf2d81aef2500758bd) +Signed-off-by: Danilo C. L. de Paula +--- + crypto/xts.c | 64 ++++++++++++++---------------------------------------------- + 1 file changed, 15 insertions(+), 49 deletions(-) + +diff --git a/crypto/xts.c b/crypto/xts.c +index 9521234..3c1a92f 100644 +--- a/crypto/xts.c ++++ b/crypto/xts.c +@@ -43,20 +43,20 @@ static void xts_mult_x(uint8_t *I) + + + /** +- * xts_tweak_uncrypt: ++ * xts_tweak_encdec: + * @param ctxt: the cipher context + * @param func: the cipher function +- * @src: buffer providing the cipher text of XTS_BLOCK_SIZE bytes +- * @dst: buffer to output the plain text of XTS_BLOCK_SIZE bytes ++ * @src: buffer providing the input text of XTS_BLOCK_SIZE bytes ++ * @dst: buffer to output the output text of XTS_BLOCK_SIZE bytes + * @iv: the initialization vector tweak of XTS_BLOCK_SIZE bytes + * +- * Decrypt data with a tweak ++ * Encrypt/decrypt data with a tweak + */ +-static void xts_tweak_decrypt(const void *ctx, +- xts_cipher_func *func, +- const uint8_t *src, +- uint8_t *dst, +- uint8_t *iv) ++static void xts_tweak_encdec(const void *ctx, ++ xts_cipher_func *func, ++ const uint8_t *src, ++ uint8_t *dst, ++ uint8_t *iv) + { + unsigned long x; + +@@ -105,7 +105,7 @@ void xts_decrypt(const void *datactx, + encfunc(tweakctx, XTS_BLOCK_SIZE, T, iv); + + for (i = 0; i < lim; i++) { +- xts_tweak_decrypt(datactx, decfunc, src, dst, T); ++ xts_tweak_encdec(datactx, decfunc, src, dst, T); + + src += XTS_BLOCK_SIZE; + dst += XTS_BLOCK_SIZE; +@@ -117,7 +117,7 @@ void xts_decrypt(const void *datactx, + xts_mult_x(CC); + + /* PP = tweak decrypt block m-1 */ +- xts_tweak_decrypt(datactx, decfunc, src, PP, CC); ++ xts_tweak_encdec(datactx, decfunc, src, PP, CC); + + /* Pm = first length % XTS_BLOCK_SIZE bytes of PP */ + for (i = 0; i < mo; i++) { +@@ -129,7 +129,7 @@ void xts_decrypt(const void *datactx, + } + + /* Pm-1 = Tweak uncrypt CC */ +- xts_tweak_decrypt(datactx, decfunc, CC, dst, T); ++ xts_tweak_encdec(datactx, decfunc, CC, dst, T); + } + + /* Decrypt the iv back */ +@@ -137,40 +137,6 @@ void xts_decrypt(const void *datactx, + } + + +-/** +- * xts_tweak_crypt: +- * @param ctxt: the cipher context +- * @param func: the cipher function +- * @src: buffer providing the plain text of XTS_BLOCK_SIZE bytes +- * @dst: buffer to output the cipher text of XTS_BLOCK_SIZE bytes +- * @iv: the initialization vector tweak of XTS_BLOCK_SIZE bytes +- * +- * Encrypt data with a tweak +- */ +-static void xts_tweak_encrypt(const void *ctx, +- xts_cipher_func *func, +- const uint8_t *src, +- uint8_t *dst, +- uint8_t *iv) +-{ +- unsigned long x; +- +- /* tweak encrypt block i */ +- for (x = 0; x < XTS_BLOCK_SIZE; x++) { +- dst[x] = src[x] ^ iv[x]; +- } +- +- func(ctx, XTS_BLOCK_SIZE, dst, dst); +- +- for (x = 0; x < XTS_BLOCK_SIZE; x++) { +- dst[x] = dst[x] ^ iv[x]; +- } +- +- /* LFSR the tweak */ +- xts_mult_x(iv); +-} +- +- + void xts_encrypt(const void *datactx, + const void *tweakctx, + xts_cipher_func *encfunc, +@@ -200,7 +166,7 @@ void xts_encrypt(const void *datactx, + encfunc(tweakctx, XTS_BLOCK_SIZE, T, iv); + + for (i = 0; i < lim; i++) { +- xts_tweak_encrypt(datactx, encfunc, src, dst, T); ++ xts_tweak_encdec(datactx, encfunc, src, dst, T); + + dst += XTS_BLOCK_SIZE; + src += XTS_BLOCK_SIZE; +@@ -209,7 +175,7 @@ void xts_encrypt(const void *datactx, + /* if length is not a multiple of XTS_BLOCK_SIZE then */ + if (mo > 0) { + /* CC = tweak encrypt block m-1 */ +- xts_tweak_encrypt(datactx, encfunc, src, CC, T); ++ xts_tweak_encdec(datactx, encfunc, src, CC, T); + + /* Cm = first length % XTS_BLOCK_SIZE bytes of CC */ + for (i = 0; i < mo; i++) { +@@ -222,7 +188,7 @@ void xts_encrypt(const void *datactx, + } + + /* Cm-1 = Tweak encrypt PP */ +- xts_tweak_encrypt(datactx, encfunc, PP, dst, T); ++ xts_tweak_encdec(datactx, encfunc, PP, dst, T); + } + + /* Decrypt the iv back */ +-- +1.8.3.1 + diff --git a/SOURCES/kvm-device_tree-Fix-integer-overflowing-in-load_device_t.patch b/SOURCES/kvm-device_tree-Fix-integer-overflowing-in-load_device_t.patch index b3811d7..32ac34c 100644 --- a/SOURCES/kvm-device_tree-Fix-integer-overflowing-in-load_device_t.patch +++ b/SOURCES/kvm-device_tree-Fix-integer-overflowing-in-load_device_t.patch @@ -1,4 +1,4 @@ -From 1767f904c44076c1b049eb540c6b565aac787bc3 Mon Sep 17 00:00:00 2001 +From c324a911deb04d1796a7e7734650579d381ab4ef Mon Sep 17 00:00:00 2001 From: Sergio Lopez Pascual Date: Mon, 15 Apr 2019 11:38:00 +0100 Subject: [PATCH] device_tree: Fix integer overflowing in load_device_tree() diff --git a/SOURCES/kvm-doc-fix-the-configuration-path.patch b/SOURCES/kvm-doc-fix-the-configuration-path.patch new file mode 100644 index 0000000..0c0d4ce --- /dev/null +++ b/SOURCES/kvm-doc-fix-the-configuration-path.patch @@ -0,0 +1,80 @@ +From 020cc7b26a22caf8984ecadd114904388333ed1d Mon Sep 17 00:00:00 2001 +From: Danilo de Paula +Date: Fri, 8 Feb 2019 11:51:14 +0000 +Subject: [PATCH 1/4] doc: fix the configuration path +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Danilo de Paula +Message-id: <20190208115114.24850-2-ddepaula@redhat.com> +Patchwork-id: 84320 +O-Subject: [RHEL8/rhel qemu-kvm PATCH v2 1/1] doc: fix the configuration path +Bugzilla: 1645411 +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Marc-André Lureau +RH-Acked-by: Stefano Garzarella +RH-Acked-by: Wainer dos Santos Moschetta + +From: Marc-André Lureau + +Use a CONFDIR variable to show the configured sysconf path in the +generated documentations (html, man pages etc). + +Related to: +https://bugzilla.redhat.com/show_bug.cgi?id=1644985 + +Signed-off-by: Marc-André Lureau +Signed-off-by: Danilo C. L. de Paula +--- + Makefile | 9 ++++++--- + qemu-ga.texi | 4 ++-- + 2 files changed, 8 insertions(+), 5 deletions(-) + +diff --git a/Makefile b/Makefile +index da3eedb..865602d 100644 +--- a/Makefile ++++ b/Makefile +@@ -919,11 +919,14 @@ ui/shader.o: $(SRC_PATH)/ui/shader.c \ + MAKEINFO=makeinfo + MAKEINFOINCLUDES= -I docs -I $( $@,"GEN","$@") ++docs/version.texi: $(SRC_PATH)/VERSION config-host.mak ++ $(call quiet-command,(\ ++ echo "@set VERSION $(VERSION)" && \ ++ echo "@set CONFDIR $(qemu_confdir)" \ ++ )> $@,"GEN","$@") + + %.html: %.texi docs/version.texi + $(call quiet-command,LC_ALL=C $(MAKEINFO) $(MAKEINFOFLAGS) --no-headers \ +diff --git a/qemu-ga.texi b/qemu-ga.texi +index 4c7a8fd..f00ad83 100644 +--- a/qemu-ga.texi ++++ b/qemu-ga.texi +@@ -30,7 +30,7 @@ set user's password + @end itemize + + qemu-ga will read a system configuration file on startup (located at +-@file{/etc/qemu/qemu-ga.conf} by default), then parse remaining ++@file{@value{CONFDIR}/qemu-ga.conf} by default), then parse remaining + configuration options on the command line. For the same key, the last + option wins, but the lists accumulate (see below for configuration + file format). +@@ -58,7 +58,7 @@ file format). + Enable fsfreeze hook. Accepts an optional argument that specifies + script to run on freeze/thaw. Script will be called with + 'freeze'/'thaw' arguments accordingly (default is +- @samp{/etc/qemu/fsfreeze-hook}). If using -F with an argument, do ++ @samp{@value{CONFDIR}/fsfreeze-hook}). If using -F with an argument, do + not follow -F with a space (for example: + @samp{-F/var/run/fsfreezehook.sh}). + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-file-posix-Drop-s-lock_fd.patch b/SOURCES/kvm-file-posix-Drop-s-lock_fd.patch new file mode 100644 index 0000000..745c0e1 --- /dev/null +++ b/SOURCES/kvm-file-posix-Drop-s-lock_fd.patch @@ -0,0 +1,138 @@ +From 47a21881507f1bba1cf2fbabb0f8efce57ee7fb9 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Wed, 3 Apr 2019 17:13:11 +0100 +Subject: [PATCH 04/11] file-posix: Drop s->lock_fd + +RH-Author: Max Reitz +Message-id: <20190403171315.20841-5-mreitz@redhat.com> +Patchwork-id: 85403 +O-Subject: [RHEL-8.1 qemu-kvm PATCH 4/8] file-posix: Drop s->lock_fd +Bugzilla: 1694148 +RH-Acked-by: John Snow +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Stefano Garzarella + +From: Fam Zheng + +The lock_fd field is not strictly necessary because transferring locked +bytes from old fd to the new one shouldn't fail anyway. This spares the +user one fd per image. + +Signed-off-by: Fam Zheng +Reviewed-by: Max Reitz +Signed-off-by: Kevin Wolf +(cherry picked from commit f2e3af29b70624659a50903bd075e1663b64c9da) +Signed-off-by: Max Reitz +Signed-off-by: Danilo C. L. de Paula +--- + block/file-posix.c | 37 +++++++++++++------------------------ + 1 file changed, 13 insertions(+), 24 deletions(-) + +diff --git a/block/file-posix.c b/block/file-posix.c +index 2a05193..97e7ff2 100644 +--- a/block/file-posix.c ++++ b/block/file-posix.c +@@ -142,7 +142,6 @@ do { \ + + typedef struct BDRVRawState { + int fd; +- int lock_fd; + bool use_lock; + int type; + int open_flags; +@@ -153,7 +152,7 @@ typedef struct BDRVRawState { + uint64_t shared_perm; + + /* The perms bits whose corresponding bytes are already locked in +- * s->lock_fd. */ ++ * s->fd. */ + uint64_t locked_perm; + uint64_t locked_shared_perm; + +@@ -545,18 +544,6 @@ static int raw_open_common(BlockDriverState *bs, QDict *options, + } + s->fd = fd; + +- s->lock_fd = -1; +- if (s->use_lock) { +- fd = qemu_open(filename, s->open_flags); +- if (fd < 0) { +- ret = -errno; +- error_setg_errno(errp, errno, "Could not open '%s' for locking", +- filename); +- qemu_close(s->fd); +- goto fail; +- } +- s->lock_fd = fd; +- } + s->perm = 0; + s->shared_perm = BLK_PERM_ALL; + +@@ -811,15 +798,13 @@ static int raw_handle_perm_lock(BlockDriverState *bs, + return 0; + } + +- assert(s->lock_fd > 0); +- + switch (op) { + case RAW_PL_PREPARE: +- ret = raw_apply_lock_bytes(s, s->lock_fd, s->perm | new_perm, ++ ret = raw_apply_lock_bytes(s, s->fd, s->perm | new_perm, + ~s->shared_perm | ~new_shared, + false, errp); + if (!ret) { +- ret = raw_check_lock_bytes(s->lock_fd, new_perm, new_shared, errp); ++ ret = raw_check_lock_bytes(s->fd, new_perm, new_shared, errp); + if (!ret) { + return 0; + } +@@ -830,7 +815,7 @@ static int raw_handle_perm_lock(BlockDriverState *bs, + op = RAW_PL_ABORT; + /* fall through to unlock bytes. */ + case RAW_PL_ABORT: +- raw_apply_lock_bytes(s, s->lock_fd, s->perm, ~s->shared_perm, ++ raw_apply_lock_bytes(s, s->fd, s->perm, ~s->shared_perm, + true, &local_err); + if (local_err) { + /* Theoretically the above call only unlocks bytes and it cannot +@@ -840,7 +825,7 @@ static int raw_handle_perm_lock(BlockDriverState *bs, + } + break; + case RAW_PL_COMMIT: +- raw_apply_lock_bytes(s, s->lock_fd, new_perm, ~new_shared, ++ raw_apply_lock_bytes(s, s->fd, new_perm, ~new_shared, + true, &local_err); + if (local_err) { + /* Theoretically the above call only unlocks bytes and it cannot +@@ -938,9 +923,17 @@ static void raw_reopen_commit(BDRVReopenState *state) + { + BDRVRawReopenState *rs = state->opaque; + BDRVRawState *s = state->bs->opaque; ++ Error *local_err = NULL; + + s->open_flags = rs->open_flags; + ++ /* Copy locks to the new fd before closing the old one. */ ++ raw_apply_lock_bytes(NULL, rs->fd, s->locked_perm, ++ ~s->locked_shared_perm, false, &local_err); ++ if (local_err) { ++ /* shouldn't fail in a sane host, but report it just in case. */ ++ error_report_err(local_err); ++ } + qemu_close(s->fd); + s->fd = rs->fd; + +@@ -1903,10 +1896,6 @@ static void raw_close(BlockDriverState *bs) + qemu_close(s->fd); + s->fd = -1; + } +- if (s->lock_fd >= 0) { +- qemu_close(s->lock_fd); +- s->lock_fd = -1; +- } + } + + /** +-- +1.8.3.1 + diff --git a/SOURCES/kvm-file-posix-Fix-shared-locks-on-reopen-commit.patch b/SOURCES/kvm-file-posix-Fix-shared-locks-on-reopen-commit.patch new file mode 100644 index 0000000..3ea09e6 --- /dev/null +++ b/SOURCES/kvm-file-posix-Fix-shared-locks-on-reopen-commit.patch @@ -0,0 +1,45 @@ +From eb8c3d2ca7a67da197d2b33e0b3a83efb9abe589 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Wed, 3 Apr 2019 17:13:13 +0100 +Subject: [PATCH 06/11] file-posix: Fix shared locks on reopen commit + +RH-Author: Max Reitz +Message-id: <20190403171315.20841-7-mreitz@redhat.com> +Patchwork-id: 85404 +O-Subject: [RHEL-8.1 qemu-kvm PATCH 6/8] file-posix: Fix shared locks on reopen commit +Bugzilla: 1694148 +RH-Acked-by: John Snow +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Stefano Garzarella + +s->locked_shared_perm is the set of bits locked in the file, which is +the inverse of the permissions actually shared. So we need to pass them +as they are to raw_apply_lock_bytes() instead of inverting them again. + +Reported-by: Alberto Garcia +Signed-off-by: Max Reitz +Reviewed-by: Alberto Garcia +Signed-off-by: Kevin Wolf +(cherry picked from commit 577a133988c76e4ebf01d050d0d758d207a1baf7) +Signed-off-by: Max Reitz +Signed-off-by: Danilo C. L. de Paula +--- + block/file-posix.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/block/file-posix.c b/block/file-posix.c +index 97e7ff2..deecf58 100644 +--- a/block/file-posix.c ++++ b/block/file-posix.c +@@ -929,7 +929,7 @@ static void raw_reopen_commit(BDRVReopenState *state) + + /* Copy locks to the new fd before closing the old one. */ + raw_apply_lock_bytes(NULL, rs->fd, s->locked_perm, +- ~s->locked_shared_perm, false, &local_err); ++ s->locked_shared_perm, false, &local_err); + if (local_err) { + /* shouldn't fail in a sane host, but report it just in case. */ + error_report_err(local_err); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-file-posix-Handle-undetectable-alignment.patch b/SOURCES/kvm-file-posix-Handle-undetectable-alignment.patch new file mode 100644 index 0000000..b4a7bad --- /dev/null +++ b/SOURCES/kvm-file-posix-Handle-undetectable-alignment.patch @@ -0,0 +1,127 @@ +From 5935958fc4eb9934b1493486a69f0f571e7da112 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Fri, 30 Aug 2019 12:56:24 +0100 +Subject: [PATCH 06/10] file-posix: Handle undetectable alignment + +RH-Author: Thomas Huth +Message-id: <20190830125628.23668-2-thuth@redhat.com> +Patchwork-id: 90209 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v2 1/5] file-posix: Handle undetectable alignment +Bugzilla: 1738839 +RH-Acked-by: Cornelia Huck +RH-Acked-by: Max Reitz +RH-Acked-by: David Hildenbrand + +In some cases buf_align or request_alignment cannot be detected: + +1. With Gluster, buf_align cannot be detected since the actual I/O is + done on Gluster server, and qemu buffer alignment does not matter. + Since we don't have alignment requirement, buf_align=1 is the best + value. + +2. With local XFS filesystem, buf_align cannot be detected if reading + from unallocated area. In this we must align the buffer, but we don't + know what is the correct size. Using the wrong alignment results in + I/O error. + +3. With Gluster backed by XFS, request_alignment cannot be detected if + reading from unallocated area. In this case we need to use the + correct alignment, and failing to do so results in I/O errors. + +4. With NFS, the server does not use direct I/O, so both buf_align cannot + be detected. In this case we don't need any alignment so we can use + buf_align=1 and request_alignment=1. + +These cases seems to work when storage sector size is 512 bytes, because +the current code starts checking align=512. If the check succeeds +because alignment cannot be detected we use 512. But this does not work +for storage with 4k sector size. + +To determine if we can detect the alignment, we probe first with +align=1. If probing succeeds, maybe there are no alignment requirement +(cases 1, 4) or we are probing unallocated area (cases 2, 3). Since we +don't have any way to tell, we treat this as undetectable alignment. If +probing with align=1 fails with EINVAL, but probing with one of the +expected alignments succeeds, we know that we found a working alignment. + +Practically the alignment requirements are the same for buffer +alignment, buffer length, and offset in file. So in case we cannot +detect buf_align, we can use request alignment. If we cannot detect +request alignment, we can fallback to a safe value. To use this logic, +we probe first request alignment instead of buf_align. + +Here is a table showing the behaviour with current code (the value in +parenthesis is the optimal value). + +Case Sector buf_align (opt) request_alignment (opt) result + +Signed-off-by: Danilo C. L. de Paula +--- + block/file-posix.c | 36 +++++++++++++++++++++++++----------- + 1 file changed, 25 insertions(+), 11 deletions(-) + +diff --git a/block/file-posix.c b/block/file-posix.c +index 4b404e4..84c5a31 100644 +--- a/block/file-posix.c ++++ b/block/file-posix.c +@@ -324,6 +324,7 @@ static void raw_probe_alignment(BlockDriverState *bs, int fd, Error **errp) + BDRVRawState *s = bs->opaque; + char *buf; + size_t max_align = MAX(MAX_BLOCKSIZE, getpagesize()); ++ size_t alignments[] = {1, 512, 1024, 2048, 4096}; + + /* For SCSI generic devices the alignment is not really used. + With buffered I/O, we don't have any restrictions. */ +@@ -350,25 +351,38 @@ static void raw_probe_alignment(BlockDriverState *bs, int fd, Error **errp) + } + #endif + +- /* If we could not get the sizes so far, we can only guess them */ +- if (!s->buf_align) { ++ /* ++ * If we could not get the sizes so far, we can only guess them. First try ++ * to detect request alignment, since it is more likely to succeed. Then ++ * try to detect buf_align, which cannot be detected in some cases (e.g. ++ * Gluster). If buf_align cannot be detected, we fallback to the value of ++ * request_alignment. ++ */ ++ ++ if (!bs->bl.request_alignment) { ++ int i; + size_t align; +- buf = qemu_memalign(max_align, 2 * max_align); +- for (align = 512; align <= max_align; align <<= 1) { +- if (raw_is_io_aligned(fd, buf + align, max_align)) { +- s->buf_align = align; ++ buf = qemu_memalign(max_align, max_align); ++ for (i = 0; i < ARRAY_SIZE(alignments); i++) { ++ align = alignments[i]; ++ if (raw_is_io_aligned(fd, buf, align)) { ++ /* Fallback to safe value. */ ++ bs->bl.request_alignment = (align != 1) ? align : max_align; + break; + } + } + qemu_vfree(buf); + } + +- if (!bs->bl.request_alignment) { ++ if (!s->buf_align) { ++ int i; + size_t align; +- buf = qemu_memalign(s->buf_align, max_align); +- for (align = 512; align <= max_align; align <<= 1) { +- if (raw_is_io_aligned(fd, buf, align)) { +- bs->bl.request_alignment = align; ++ buf = qemu_memalign(max_align, 2 * max_align); ++ for (i = 0; i < ARRAY_SIZE(alignments); i++) { ++ align = alignments[i]; ++ if (raw_is_io_aligned(fd, buf + align, max_align)) { ++ /* Fallback to request_aligment. */ ++ s->buf_align = (align != 1) ? align : bs->bl.request_alignment; + break; + } + } +-- +1.8.3.1 + diff --git a/SOURCES/kvm-file-posix-Include-filename-in-locking-error-message.patch b/SOURCES/kvm-file-posix-Include-filename-in-locking-error-message.patch new file mode 100644 index 0000000..edd1409 --- /dev/null +++ b/SOURCES/kvm-file-posix-Include-filename-in-locking-error-message.patch @@ -0,0 +1,345 @@ +From 494baebd78587465d90b9e873cd88c0a83ca52f9 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Wed, 3 Apr 2019 17:13:09 +0100 +Subject: [PATCH 02/11] file-posix: Include filename in locking error message + +RH-Author: Max Reitz +Message-id: <20190403171315.20841-3-mreitz@redhat.com> +Patchwork-id: 85400 +O-Subject: [RHEL-8.1 qemu-kvm PATCH 2/8] file-posix: Include filename in locking error message +Bugzilla: 1694148 +RH-Acked-by: John Snow +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Stefano Garzarella + +From: Fam Zheng + +Image locking errors happening at device initialization time doesn't say +which file cannot be locked, for instance, + + -device scsi-disk,drive=drive-1: Failed to get shared "write" lock + Is another process using the image? + +could refer to either the overlay image or its backing image. + +Hoist the error_append_hint to the caller of raw_check_lock_bytes where +file name is known, and include it in the error hint. + +Signed-off-by: Fam Zheng +Reviewed-by: Eric Blake +Signed-off-by: Kevin Wolf +(cherry picked from commit b857431d2abe3945b672b41f33690e9943a8752a) +Signed-off-by: Max Reitz +Signed-off-by: Danilo C. L. de Paula +--- + block/file-posix.c | 10 +++--- + tests/qemu-iotests/153.out | 76 +++++++++++++++++++++++----------------------- + tests/qemu-iotests/182.out | 2 +- + 3 files changed, 45 insertions(+), 43 deletions(-) + +diff --git a/block/file-posix.c b/block/file-posix.c +index 7e6869d..c2403ba 100644 +--- a/block/file-posix.c ++++ b/block/file-posix.c +@@ -738,8 +738,6 @@ static int raw_check_lock_bytes(int fd, uint64_t perm, uint64_t shared_perm, + "Failed to get \"%s\" lock", + perm_name); + g_free(perm_name); +- error_append_hint(errp, +- "Is another process using the image?\n"); + return ret; + } + } +@@ -755,8 +753,6 @@ static int raw_check_lock_bytes(int fd, uint64_t perm, uint64_t shared_perm, + "Failed to get shared \"%s\" lock", + perm_name); + g_free(perm_name); +- error_append_hint(errp, +- "Is another process using the image?\n"); + return ret; + } + } +@@ -793,6 +789,9 @@ static int raw_handle_perm_lock(BlockDriverState *bs, + if (!ret) { + return 0; + } ++ error_append_hint(errp, ++ "Is another process using the image [%s]?\n", ++ bs->filename); + } + op = RAW_PL_ABORT; + /* fall through to unlock bytes. */ +@@ -2169,6 +2168,9 @@ raw_co_create(BlockdevCreateOptions *options, Error **errp) + /* Step two: Check that nobody else has taken conflicting locks */ + result = raw_check_lock_bytes(fd, perm, shared, errp); + if (result < 0) { ++ error_append_hint(errp, ++ "Is another process using the image [%s]?\n", ++ file_opts->filename); + goto out_unlock; + } + +diff --git a/tests/qemu-iotests/153.out b/tests/qemu-iotests/153.out +index 93eaf10..8842548 100644 +--- a/tests/qemu-iotests/153.out ++++ b/tests/qemu-iotests/153.out +@@ -12,11 +12,11 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=33554432 backing_file=TEST_DIR/t + + == Launching another QEMU, opts: '' == + QEMU_PROG: -drive file=TEST_DIR/t.qcow2,if=none,: Failed to get "write" lock +-Is another process using the image? ++Is another process using the image [TEST_DIR/t.qcow2]? + + == Launching another QEMU, opts: 'read-only=on' == + QEMU_PROG: -drive file=TEST_DIR/t.qcow2,if=none,read-only=on: Failed to get shared "write" lock +-Is another process using the image? ++Is another process using the image [TEST_DIR/t.qcow2]? + + == Launching another QEMU, opts: 'read-only=on,force-share=on' == + +@@ -24,77 +24,77 @@ Is another process using the image? + + _qemu_io_wrapper -c read 0 512 TEST_DIR/t.qcow2 + can't open device TEST_DIR/t.qcow2: Failed to get "write" lock +-Is another process using the image? ++Is another process using the image [TEST_DIR/t.qcow2]? + + _qemu_io_wrapper -r -c read 0 512 TEST_DIR/t.qcow2 + can't open device TEST_DIR/t.qcow2: Failed to get shared "write" lock +-Is another process using the image? ++Is another process using the image [TEST_DIR/t.qcow2]? + + _qemu_io_wrapper -c open TEST_DIR/t.qcow2 -c read 0 512 + can't open device TEST_DIR/t.qcow2: Failed to get "write" lock +-Is another process using the image? ++Is another process using the image [TEST_DIR/t.qcow2]? + no file open, try 'help open' + + _qemu_io_wrapper -c open -r TEST_DIR/t.qcow2 -c read 0 512 + can't open device TEST_DIR/t.qcow2: Failed to get shared "write" lock +-Is another process using the image? ++Is another process using the image [TEST_DIR/t.qcow2]? + no file open, try 'help open' + + _qemu_img_wrapper info TEST_DIR/t.qcow2 + qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get shared "write" lock +-Is another process using the image? ++Is another process using the image [TEST_DIR/t.qcow2]? + + _qemu_img_wrapper check TEST_DIR/t.qcow2 + qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get shared "write" lock +-Is another process using the image? ++Is another process using the image [TEST_DIR/t.qcow2]? + + _qemu_img_wrapper compare TEST_DIR/t.qcow2 TEST_DIR/t.qcow2 + qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get shared "write" lock +-Is another process using the image? ++Is another process using the image [TEST_DIR/t.qcow2]? + + _qemu_img_wrapper map TEST_DIR/t.qcow2 + qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get shared "write" lock +-Is another process using the image? ++Is another process using the image [TEST_DIR/t.qcow2]? + + _qemu_img_wrapper amend -o TEST_DIR/t.qcow2 + qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock +-Is another process using the image? ++Is another process using the image [TEST_DIR/t.qcow2]? + + _qemu_img_wrapper commit TEST_DIR/t.qcow2 + qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock +-Is another process using the image? ++Is another process using the image [TEST_DIR/t.qcow2]? + + _qemu_img_wrapper resize TEST_DIR/t.qcow2 32M + qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock +-Is another process using the image? ++Is another process using the image [TEST_DIR/t.qcow2]? + + _qemu_img_wrapper rebase TEST_DIR/t.qcow2 -b TEST_DIR/t.qcow2.base + qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock +-Is another process using the image? ++Is another process using the image [TEST_DIR/t.qcow2]? + + _qemu_img_wrapper snapshot -l TEST_DIR/t.qcow2 + qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get shared "write" lock +-Is another process using the image? ++Is another process using the image [TEST_DIR/t.qcow2]? + + _qemu_img_wrapper convert TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.convert + qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get shared "write" lock +-Is another process using the image? ++Is another process using the image [TEST_DIR/t.qcow2]? + + _qemu_img_wrapper dd if=TEST_DIR/t.qcow2 of=TEST_DIR/t.qcow2.convert bs=512 count=1 + qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get shared "write" lock +-Is another process using the image? ++Is another process using the image [TEST_DIR/t.qcow2]? + + _qemu_img_wrapper bench -c 1 TEST_DIR/t.qcow2 + qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get shared "write" lock +-Is another process using the image? ++Is another process using the image [TEST_DIR/t.qcow2]? + + _qemu_img_wrapper bench -w -c 1 TEST_DIR/t.qcow2 + qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock +-Is another process using the image? ++Is another process using the image [TEST_DIR/t.qcow2]? + + _qemu_img_wrapper create -f qcow2 TEST_DIR/t.qcow2 -b TEST_DIR/t.qcow2.base + qemu-img: TEST_DIR/t.qcow2: Failed to get "write" lock +-Is another process using the image? ++Is another process using the image [TEST_DIR/t.qcow2]? + file format: IMGFMT + + == Running utility commands -U == +@@ -132,7 +132,7 @@ Try 'qemu-img --help' for more information + + _qemu_img_wrapper rebase -U TEST_DIR/t.qcow2 -b TEST_DIR/t.qcow2.base + qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock +-Is another process using the image? ++Is another process using the image [TEST_DIR/t.qcow2]? + + _qemu_img_wrapper snapshot -l -U TEST_DIR/t.qcow2 + +@@ -157,7 +157,7 @@ Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=33554432 backing_file=TEST_DIR/t + + == Launching another QEMU, opts: '' == + QEMU_PROG: -drive file=TEST_DIR/t.qcow2,if=none,: Failed to get "write" lock +-Is another process using the image? ++Is another process using the image [TEST_DIR/t.qcow2]? + + == Launching another QEMU, opts: 'read-only=on' == + +@@ -167,13 +167,13 @@ Is another process using the image? + + _qemu_io_wrapper -c read 0 512 TEST_DIR/t.qcow2 + can't open device TEST_DIR/t.qcow2: Failed to get "write" lock +-Is another process using the image? ++Is another process using the image [TEST_DIR/t.qcow2]? + + _qemu_io_wrapper -r -c read 0 512 TEST_DIR/t.qcow2 + + _qemu_io_wrapper -c open TEST_DIR/t.qcow2 -c read 0 512 + can't open device TEST_DIR/t.qcow2: Failed to get "write" lock +-Is another process using the image? ++Is another process using the image [TEST_DIR/t.qcow2]? + no file open, try 'help open' + + _qemu_io_wrapper -c open -r TEST_DIR/t.qcow2 -c read 0 512 +@@ -188,19 +188,19 @@ _qemu_img_wrapper map TEST_DIR/t.qcow2 + + _qemu_img_wrapper amend -o TEST_DIR/t.qcow2 + qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock +-Is another process using the image? ++Is another process using the image [TEST_DIR/t.qcow2]? + + _qemu_img_wrapper commit TEST_DIR/t.qcow2 + qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock +-Is another process using the image? ++Is another process using the image [TEST_DIR/t.qcow2]? + + _qemu_img_wrapper resize TEST_DIR/t.qcow2 32M + qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock +-Is another process using the image? ++Is another process using the image [TEST_DIR/t.qcow2]? + + _qemu_img_wrapper rebase TEST_DIR/t.qcow2 -b TEST_DIR/t.qcow2.base + qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock +-Is another process using the image? ++Is another process using the image [TEST_DIR/t.qcow2]? + + _qemu_img_wrapper snapshot -l TEST_DIR/t.qcow2 + +@@ -212,11 +212,11 @@ _qemu_img_wrapper bench -c 1 TEST_DIR/t.qcow2 + + _qemu_img_wrapper bench -w -c 1 TEST_DIR/t.qcow2 + qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock +-Is another process using the image? ++Is another process using the image [TEST_DIR/t.qcow2]? + + _qemu_img_wrapper create -f qcow2 TEST_DIR/t.qcow2 -b TEST_DIR/t.qcow2.base + qemu-img: TEST_DIR/t.qcow2: Failed to get "write" lock +-Is another process using the image? ++Is another process using the image [TEST_DIR/t.qcow2]? + file format: IMGFMT + + == Running utility commands -U == +@@ -254,7 +254,7 @@ Try 'qemu-img --help' for more information + + _qemu_img_wrapper rebase -U TEST_DIR/t.qcow2 -b TEST_DIR/t.qcow2.base + qemu-img: Could not open 'TEST_DIR/t.qcow2': Failed to get "write" lock +-Is another process using the image? ++Is another process using the image [TEST_DIR/t.qcow2]? + + _qemu_img_wrapper snapshot -l -U TEST_DIR/t.qcow2 + +@@ -372,17 +372,17 @@ Round done + + == Two devices with the same image (read-only=off - read-only=off) == + QEMU_PROG: -drive if=none,file=TEST_DIR/t.qcow2,read-only=off: Failed to get "write" lock +-Is another process using the image? ++Is another process using the image [TEST_DIR/t.qcow2]? + + == Two devices with the same image (read-only=off - read-only=on) == + QEMU_PROG: -drive if=none,file=TEST_DIR/t.qcow2,read-only=on: Failed to get shared "write" lock +-Is another process using the image? ++Is another process using the image [TEST_DIR/t.qcow2]? + + == Two devices with the same image (read-only=off - read-only=on,force-share=on) == + + == Two devices with the same image (read-only=on - read-only=off) == + QEMU_PROG: -drive if=none,file=TEST_DIR/t.qcow2,read-only=off: Failed to get "write" lock +-Is another process using the image? ++Is another process using the image [TEST_DIR/t.qcow2]? + + == Two devices with the same image (read-only=on - read-only=on) == + +@@ -403,13 +403,13 @@ Formatting 'TEST_DIR/t.IMGFMT.c', fmt=IMGFMT size=33554432 backing_file=TEST_DIR + + == Backing image also as an active device == + QEMU_PROG: -drive if=none,file=TEST_DIR/t.qcow2: Failed to get "write" lock +-Is another process using the image? ++Is another process using the image [TEST_DIR/t.qcow2]? + + == Backing image also as an active device (ro) == + + == Symbolic link == + QEMU_PROG: -drive if=none,file=TEST_DIR/t.qcow2: Failed to get "write" lock +-Is another process using the image? ++Is another process using the image [TEST_DIR/t.qcow2]? + + == Active commit to intermediate layer should work when base in use == + {"return": {}} +@@ -420,7 +420,7 @@ Adding drive + + _qemu_io_wrapper TEST_DIR/t.qcow2 -c write 0 512 + can't open device TEST_DIR/t.qcow2: Failed to get "write" lock +-Is another process using the image? ++Is another process using the image [TEST_DIR/t.qcow2]? + Creating overlay with qemu-img when the guest is running should be allowed + + _qemu_img_wrapper create -f qcow2 -b TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.overlay +@@ -433,7 +433,7 @@ _qemu_img_wrapper info TEST_DIR/t.qcow2 + + _qemu_io_wrapper TEST_DIR/t.qcow2 -c write 0 512 + can't open device TEST_DIR/t.qcow2: Failed to get "write" lock +-Is another process using the image? ++Is another process using the image [TEST_DIR/t.qcow2]? + Closing the other + + _qemu_io_wrapper TEST_DIR/t.qcow2 -c write 0 512 +diff --git a/tests/qemu-iotests/182.out b/tests/qemu-iotests/182.out +index 23a4dbf..f1463c8 100644 +--- a/tests/qemu-iotests/182.out ++++ b/tests/qemu-iotests/182.out +@@ -4,5 +4,5 @@ Starting QEMU + + Starting a second QEMU using the same image should fail + QEMU_PROG: -drive file=TEST_DIR/t.qcow2,if=none,id=drive0,file.locking=on: Failed to get "write" lock +-Is another process using the image? ++Is another process using the image [TEST_DIR/t.qcow2]? + *** done +-- +1.8.3.1 + diff --git a/SOURCES/kvm-file-posix-Skip-effectiveless-OFD-lock-operations.patch b/SOURCES/kvm-file-posix-Skip-effectiveless-OFD-lock-operations.patch new file mode 100644 index 0000000..050c944 --- /dev/null +++ b/SOURCES/kvm-file-posix-Skip-effectiveless-OFD-lock-operations.patch @@ -0,0 +1,195 @@ +From b9aaae95df14d93aab128376c40943259a453730 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Wed, 3 Apr 2019 17:13:10 +0100 +Subject: [PATCH 03/11] file-posix: Skip effectiveless OFD lock operations + +RH-Author: Max Reitz +Message-id: <20190403171315.20841-4-mreitz@redhat.com> +Patchwork-id: 85401 +O-Subject: [RHEL-8.1 qemu-kvm PATCH 3/8] file-posix: Skip effectiveless OFD lock operations +Bugzilla: 1694148 +RH-Acked-by: John Snow +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Stefano Garzarella + +From: Fam Zheng + +If we know we've already locked the bytes, don't do it again; similarly +don't unlock a byte if we haven't locked it. This doesn't change the +behavior, but fixes a corner case explained below. + +Libvirt had an error handling bug that an image can get its (ownership, +file mode, SELinux) permissions changed (RHBZ 1584982) by mistake behind +QEMU. Specifically, an image in use by Libvirt VM has: + + $ ls -lhZ b.img + -rw-r--r--. qemu qemu system_u:object_r:svirt_image_t:s0:c600,c690 b.img + +Trying to attach it a second time won't work because of image locking. +And after the error, it becomes: + + $ ls -lhZ b.img + -rw-r--r--. root root system_u:object_r:virt_image_t:s0 b.img + +Then, we won't be able to do OFD lock operations with the existing fd. +In other words, the code such as in blk_detach_dev: + + blk_set_perm(blk, 0, BLK_PERM_ALL, &error_abort); + +can abort() QEMU, out of environmental changes. + +This patch is an easy fix to this and the change is regardlessly +reasonable, so do it. + +Signed-off-by: Fam Zheng +Reviewed-by: Max Reitz +Signed-off-by: Kevin Wolf +(cherry picked from commit 2996ffad3acabe890fbb4f84a069cdc325a68108) +Signed-off-by: Max Reitz +Signed-off-by: Danilo C. L. de Paula +--- + block/file-posix.c | 54 ++++++++++++++++++++++++++++++++++++++++++++---------- + 1 file changed, 44 insertions(+), 10 deletions(-) + +diff --git a/block/file-posix.c b/block/file-posix.c +index c2403ba..2a05193 100644 +--- a/block/file-posix.c ++++ b/block/file-posix.c +@@ -152,6 +152,11 @@ typedef struct BDRVRawState { + uint64_t perm; + uint64_t shared_perm; + ++ /* The perms bits whose corresponding bytes are already locked in ++ * s->lock_fd. */ ++ uint64_t locked_perm; ++ uint64_t locked_shared_perm; ++ + #ifdef CONFIG_XFS + bool is_xfs:1; + #endif +@@ -677,43 +682,72 @@ typedef enum { + * file; if @unlock == true, also unlock the unneeded bytes. + * @shared_perm_lock_bits is the mask of all permissions that are NOT shared. + */ +-static int raw_apply_lock_bytes(int fd, ++static int raw_apply_lock_bytes(BDRVRawState *s, int fd, + uint64_t perm_lock_bits, + uint64_t shared_perm_lock_bits, + bool unlock, Error **errp) + { + int ret; + int i; ++ uint64_t locked_perm, locked_shared_perm; ++ ++ if (s) { ++ locked_perm = s->locked_perm; ++ locked_shared_perm = s->locked_shared_perm; ++ } else { ++ /* ++ * We don't have the previous bits, just lock/unlock for each of the ++ * requested bits. ++ */ ++ if (unlock) { ++ locked_perm = BLK_PERM_ALL; ++ locked_shared_perm = BLK_PERM_ALL; ++ } else { ++ locked_perm = 0; ++ locked_shared_perm = 0; ++ } ++ } + + PERM_FOREACH(i) { + int off = RAW_LOCK_PERM_BASE + i; +- if (perm_lock_bits & (1ULL << i)) { ++ uint64_t bit = (1ULL << i); ++ if ((perm_lock_bits & bit) && !(locked_perm & bit)) { + ret = qemu_lock_fd(fd, off, 1, false); + if (ret) { + error_setg(errp, "Failed to lock byte %d", off); + return ret; ++ } else if (s) { ++ s->locked_perm |= bit; + } +- } else if (unlock) { ++ } else if (unlock && (locked_perm & bit) && !(perm_lock_bits & bit)) { + ret = qemu_unlock_fd(fd, off, 1); + if (ret) { + error_setg(errp, "Failed to unlock byte %d", off); + return ret; ++ } else if (s) { ++ s->locked_perm &= ~bit; + } + } + } + PERM_FOREACH(i) { + int off = RAW_LOCK_SHARED_BASE + i; +- if (shared_perm_lock_bits & (1ULL << i)) { ++ uint64_t bit = (1ULL << i); ++ if ((shared_perm_lock_bits & bit) && !(locked_shared_perm & bit)) { + ret = qemu_lock_fd(fd, off, 1, false); + if (ret) { + error_setg(errp, "Failed to lock byte %d", off); + return ret; ++ } else if (s) { ++ s->locked_shared_perm |= bit; + } +- } else if (unlock) { ++ } else if (unlock && (locked_shared_perm & bit) && ++ !(shared_perm_lock_bits & bit)) { + ret = qemu_unlock_fd(fd, off, 1); + if (ret) { + error_setg(errp, "Failed to unlock byte %d", off); + return ret; ++ } else if (s) { ++ s->locked_shared_perm &= ~bit; + } + } + } +@@ -781,7 +815,7 @@ static int raw_handle_perm_lock(BlockDriverState *bs, + + switch (op) { + case RAW_PL_PREPARE: +- ret = raw_apply_lock_bytes(s->lock_fd, s->perm | new_perm, ++ ret = raw_apply_lock_bytes(s, s->lock_fd, s->perm | new_perm, + ~s->shared_perm | ~new_shared, + false, errp); + if (!ret) { +@@ -796,7 +830,7 @@ static int raw_handle_perm_lock(BlockDriverState *bs, + op = RAW_PL_ABORT; + /* fall through to unlock bytes. */ + case RAW_PL_ABORT: +- raw_apply_lock_bytes(s->lock_fd, s->perm, ~s->shared_perm, ++ raw_apply_lock_bytes(s, s->lock_fd, s->perm, ~s->shared_perm, + true, &local_err); + if (local_err) { + /* Theoretically the above call only unlocks bytes and it cannot +@@ -806,7 +840,7 @@ static int raw_handle_perm_lock(BlockDriverState *bs, + } + break; + case RAW_PL_COMMIT: +- raw_apply_lock_bytes(s->lock_fd, new_perm, ~new_shared, ++ raw_apply_lock_bytes(s, s->lock_fd, new_perm, ~new_shared, + true, &local_err); + if (local_err) { + /* Theoretically the above call only unlocks bytes and it cannot +@@ -2160,7 +2194,7 @@ raw_co_create(BlockdevCreateOptions *options, Error **errp) + shared = BLK_PERM_ALL & ~BLK_PERM_RESIZE; + + /* Step one: Take locks */ +- result = raw_apply_lock_bytes(fd, perm, ~shared, false, errp); ++ result = raw_apply_lock_bytes(NULL, fd, perm, ~shared, false, errp); + if (result < 0) { + goto out_close; + } +@@ -2204,7 +2238,7 @@ raw_co_create(BlockdevCreateOptions *options, Error **errp) + } + + out_unlock: +- raw_apply_lock_bytes(fd, 0, 0, true, &local_err); ++ raw_apply_lock_bytes(NULL, fd, 0, 0, true, &local_err); + if (local_err) { + /* The above call should not fail, and if it does, that does + * not mean the whole creation operation has failed. So +-- +1.8.3.1 + diff --git a/SOURCES/kvm-gluster-Handle-changed-glfs_ftruncate-signature.patch b/SOURCES/kvm-gluster-Handle-changed-glfs_ftruncate-signature.patch new file mode 100644 index 0000000..711e67c --- /dev/null +++ b/SOURCES/kvm-gluster-Handle-changed-glfs_ftruncate-signature.patch @@ -0,0 +1,97 @@ +From a30344defca0e948400587280f67d4e6bcc5834f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Wed, 19 Jun 2019 17:15:07 +0200 +Subject: [PATCH 1/2] gluster: Handle changed glfs_ftruncate signature +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Philippe Mathieu-Daudé +Message-id: <20190619171508.31981-2-philmd@redhat.com> +Patchwork-id: 88737 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 1/2] gluster: Handle changed glfs_ftruncate signature +Bugzilla: 1721983 +RH-Acked-by: Max Reitz +RH-Acked-by: Niels de Vos +RH-Acked-by: Miroslav Rezanina + +From: Prasanna Kumar Kalever + +New versions of Glusters libgfapi.so have an updated glfs_ftruncate() +function that returns additional 'struct stat' structures to enable +advanced caching of attributes. This is useful for file servers, not so +much for QEMU. Nevertheless, the API has changed and needs to be +adopted. + +Signed-off-by: Prasanna Kumar Kalever +Signed-off-by: Niels de Vos +Signed-off-by: Kevin Wolf +(cherry picked from commit e014dbe74e0484188164c61ff6843f8a04a8cb9d) +Signed-off-by: Philippe Mathieu-Daudé +Signed-off-by: Miroslav Rezanina +--- + block/gluster.c | 4 ++++ + configure | 18 ++++++++++++++++++ + 2 files changed, 22 insertions(+) + +diff --git a/block/gluster.c b/block/gluster.c +index 8c13002..e3ffa61 100644 +--- a/block/gluster.c ++++ b/block/gluster.c +@@ -20,6 +20,10 @@ + #include "qemu/option.h" + #include "qemu/cutils.h" + ++#ifdef CONFIG_GLUSTERFS_FTRUNCATE_HAS_STAT ++# define glfs_ftruncate(fd, offset) glfs_ftruncate(fd, offset, NULL, NULL) ++#endif ++ + #define GLUSTER_OPT_FILENAME "filename" + #define GLUSTER_OPT_VOLUME "volume" + #define GLUSTER_OPT_PATH "path" +diff --git a/configure b/configure +index 6d61b14..b3d337b 100755 +--- a/configure ++++ b/configure +@@ -429,6 +429,7 @@ glusterfs_xlator_opt="no" + glusterfs_discard="no" + glusterfs_fallocate="no" + glusterfs_zerofill="no" ++glusterfs_ftruncate_has_stat="no" + gtk="" + gtkabi="" + gtk_gl="no" +@@ -3919,6 +3920,19 @@ if test "$glusterfs" != "no" ; then + glusterfs_fallocate="yes" + glusterfs_zerofill="yes" + fi ++ cat > $TMPC << EOF ++#include ++ ++int ++main(void) ++{ ++ /* new glfs_ftruncate() passes two additional args */ ++ return glfs_ftruncate(NULL, 0, NULL, NULL); ++} ++EOF ++ if compile_prog "$glusterfs_cflags" "$glusterfs_libs" ; then ++ glusterfs_ftruncate_has_stat="yes" ++ fi + else + if test "$glusterfs" = "yes" ; then + feature_not_found "GlusterFS backend support" \ +@@ -6622,6 +6636,10 @@ if test "$glusterfs_zerofill" = "yes" ; then + echo "CONFIG_GLUSTERFS_ZEROFILL=y" >> $config_host_mak + fi + ++if test "$glusterfs_ftruncate_has_stat" = "yes" ; then ++ echo "CONFIG_GLUSTERFS_FTRUNCATE_HAS_STAT=y" >> $config_host_mak ++fi ++ + if test "$libssh2" = "yes" ; then + echo "CONFIG_LIBSSH2=m" >> $config_host_mak + echo "LIBSSH2_CFLAGS=$libssh2_cflags" >> $config_host_mak +-- +1.8.3.1 + diff --git a/SOURCES/kvm-gluster-the-glfs_io_cbk-callback-function-pointer-ad.patch b/SOURCES/kvm-gluster-the-glfs_io_cbk-callback-function-pointer-ad.patch new file mode 100644 index 0000000..c822f7c --- /dev/null +++ b/SOURCES/kvm-gluster-the-glfs_io_cbk-callback-function-pointer-ad.patch @@ -0,0 +1,108 @@ +From 41e53f27ba80b6479c5b7fdb34eb67ceb801c65b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Wed, 19 Jun 2019 17:15:08 +0200 +Subject: [PATCH 2/2] gluster: the glfs_io_cbk callback function pointer adds + pre/post stat args +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Philippe Mathieu-Daudé +Message-id: <20190619171508.31981-3-philmd@redhat.com> +Patchwork-id: 88738 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 2/2] gluster: the glfs_io_cbk callback function pointer adds pre/post stat args +Bugzilla: 1721983 +RH-Acked-by: Max Reitz +RH-Acked-by: Niels de Vos +RH-Acked-by: Miroslav Rezanina + +From: Niels de Vos + +The glfs_*_async() functions do a callback once finished. This callback +has changed its arguments, pre- and post-stat structures have been +added. This makes it possible to improve caching, which is useful for +Samba and NFS-Ganesha, but not so much for QEMU. Gluster 6 is the first +release that includes these new arguments. + +With an additional detection in ./configure, the new arguments can +conditionally get included in the glfs_io_cbk handler. + +Signed-off-by: Niels de Vos +Signed-off-by: Kevin Wolf +(cherry picked from commit 0e3b891fefacc0e49f3c8ffa3a753b69eb7214d2) +Signed-off-by: Philippe Mathieu-Daudé +Signed-off-by: Miroslav Rezanina +--- + block/gluster.c | 6 +++++- + configure | 24 ++++++++++++++++++++++++ + 2 files changed, 29 insertions(+), 1 deletion(-) + +diff --git a/block/gluster.c b/block/gluster.c +index e3ffa61..a6ac2b1 100644 +--- a/block/gluster.c ++++ b/block/gluster.c +@@ -729,7 +729,11 @@ static struct glfs *qemu_gluster_init(BlockdevOptionsGluster *gconf, + /* + * AIO callback routine called from GlusterFS thread. + */ +-static void gluster_finish_aiocb(struct glfs_fd *fd, ssize_t ret, void *arg) ++static void gluster_finish_aiocb(struct glfs_fd *fd, ssize_t ret, ++#ifdef CONFIG_GLUSTERFS_IOCB_HAS_STAT ++ struct glfs_stat *pre, struct glfs_stat *post, ++#endif ++ void *arg) + { + GlusterAIOCB *acb = (GlusterAIOCB *)arg; + +diff --git a/configure b/configure +index b3d337b..c9a1034 100755 +--- a/configure ++++ b/configure +@@ -430,6 +430,7 @@ glusterfs_discard="no" + glusterfs_fallocate="no" + glusterfs_zerofill="no" + glusterfs_ftruncate_has_stat="no" ++glusterfs_iocb_has_stat="no" + gtk="" + gtkabi="" + gtk_gl="no" +@@ -3933,6 +3934,25 @@ EOF + if compile_prog "$glusterfs_cflags" "$glusterfs_libs" ; then + glusterfs_ftruncate_has_stat="yes" + fi ++ cat > $TMPC << EOF ++#include ++ ++/* new glfs_io_cbk() passes two additional glfs_stat structs */ ++static void ++glusterfs_iocb(glfs_fd_t *fd, ssize_t ret, struct glfs_stat *prestat, struct glfs_stat *poststat, void *data) ++{} ++ ++int ++main(void) ++{ ++ glfs_io_cbk iocb = &glusterfs_iocb; ++ iocb(NULL, 0 , NULL, NULL, NULL); ++ return 0; ++} ++EOF ++ if compile_prog "$glusterfs_cflags" "$glusterfs_libs" ; then ++ glusterfs_iocb_has_stat="yes" ++ fi + else + if test "$glusterfs" = "yes" ; then + feature_not_found "GlusterFS backend support" \ +@@ -6640,6 +6660,10 @@ if test "$glusterfs_ftruncate_has_stat" = "yes" ; then + echo "CONFIG_GLUSTERFS_FTRUNCATE_HAS_STAT=y" >> $config_host_mak + fi + ++if test "$glusterfs_iocb_has_stat" = "yes" ; then ++ echo "CONFIG_GLUSTERFS_IOCB_HAS_STAT=y" >> $config_host_mak ++fi ++ + if test "$libssh2" = "yes" ; then + echo "CONFIG_LIBSSH2=m" >> $config_host_mak + echo "LIBSSH2_CFLAGS=$libssh2_cflags" >> $config_host_mak +-- +1.8.3.1 + diff --git a/SOURCES/kvm-hostmem-file-remove-object-id-from-pmem-error-messag.patch b/SOURCES/kvm-hostmem-file-remove-object-id-from-pmem-error-messag.patch new file mode 100644 index 0000000..6e867b8 --- /dev/null +++ b/SOURCES/kvm-hostmem-file-remove-object-id-from-pmem-error-messag.patch @@ -0,0 +1,72 @@ +From 2968c04bb24aaca2d9b8b46a5f67fe7ee3abe7fa Mon Sep 17 00:00:00 2001 +From: "plai@redhat.com" +Date: Thu, 11 Apr 2019 18:48:03 +0100 +Subject: [PATCH 09/11] hostmem-file: remove object id from pmem error message + +RH-Author: plai@redhat.com +Message-id: <1555008483-17720-1-git-send-email-plai@redhat.com> +Patchwork-id: 85563 +O-Subject: [RHEL8.1 qemu-kvm PATCH ] hostmem-file: remove object id from pmem error message +Bugzilla: 1687596 +RH-Acked-by: Eduardo Habkost +RH-Acked-by: Pankaj Gupta +RH-Acked-by: Stefano Garzarella + +From: Zhang Yi + +BZ: https://bugzilla.redhat.com/show_bug.cgi?id=1687596 +Brew: http://brewweb.devel.redhat.com/brew/taskinfo?taskID=21121663 +Branch: rhel-8.1.0 + +--- + +We will never get the canonical path from the object +before object_property_add_child. + +Signed-off-by: Zhang Yi +Message-Id: +[ehabkost: reword commit message] +Signed-off-by: Eduardo Habkost + +(cherry picked from commit 87dc3ce60a8a16b47aeb6c5f4dbc14ee975563df) +Signed-off-by: Paul Lai + +Resovled Conflicts: + backends/hostmem-file.c + +Signed-off-by: Danilo C. L. de Paula +--- + backends/hostmem-file.c | 10 ++++------ + 1 file changed, 4 insertions(+), 6 deletions(-) + +diff --git a/backends/hostmem-file.c b/backends/hostmem-file.c +index 2476dcb..4b667b7 100644 +--- a/backends/hostmem-file.c ++++ b/backends/hostmem-file.c +@@ -145,9 +145,8 @@ static void file_memory_backend_set_pmem(Object *o, bool value, Error **errp) + HostMemoryBackendFile *fb = MEMORY_BACKEND_FILE(o); + + if (host_memory_backend_mr_inited(backend)) { +- error_setg(errp, "cannot change property 'pmem' of %s '%s'", +- object_get_typename(o), +- object_get_canonical_path_component(o)); ++ error_setg(errp, "cannot change property 'pmem' of %s.", ++ object_get_typename(o)); + return; + } + +@@ -156,9 +155,8 @@ static void file_memory_backend_set_pmem(Object *o, bool value, Error **errp) + Error *local_err = NULL; + error_setg(&local_err, + "Lack of libpmem support while setting the 'pmem=on'" +- " of %s '%s'. We can't ensure data persistence.", +- object_get_typename(o), +- object_get_canonical_path_component(o)); ++ " of %s. We can't ensure data persistence.", ++ object_get_typename(o)); + error_propagate(errp, local_err); + return; + } +-- +1.8.3.1 + diff --git a/SOURCES/kvm-hw-block-pflash_cfi01-Add-missing-DeviceReset-handle.patch b/SOURCES/kvm-hw-block-pflash_cfi01-Add-missing-DeviceReset-handle.patch new file mode 100644 index 0000000..de0b450 --- /dev/null +++ b/SOURCES/kvm-hw-block-pflash_cfi01-Add-missing-DeviceReset-handle.patch @@ -0,0 +1,86 @@ +From 707a777c2992e840d2c3dd4e1fbed5b0d6c682ec Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Tue, 23 Jul 2019 11:51:05 +0100 +Subject: [PATCH 01/14] hw/block/pflash_cfi01: Add missing DeviceReset() + handler +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Philippe Mathieu-Daudé +Message-id: <20190723115105.31305-2-philmd@redhat.com> +Patchwork-id: 89645 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 1/1] hw/block/pflash_cfi01: Add missing DeviceReset() handler +Bugzilla: 1707192 +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: John Snow + +To avoid incoherent states when the machine resets (see bug report +below), add the device reset callback. + +A "system reset" sets the device state machine in READ_ARRAY mode +and, after some delay, set the SR.7 READY bit. + +Since we do not model timings, we set the SR.7 bit directly. + +Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1678713 +Reported-by: Laszlo Ersek +Reviewed-by: John Snow +Reviewed-by: Alistair Francis +Reviewed-by: Laszlo Ersek +Tested-by: Laszlo Ersek +[Laszlo Ersek: Regression tested EDK2 OVMF IA32X64, ArmVirtQemu Aarch64 + https://lists.gnu.org/archive/html/qemu-devel/2019-07/msg04373.html] +Message-Id: <20190718104837.13905-2-philmd@redhat.com> +Signed-off-by: Philippe Mathieu-Daudé +(cherry picked from commit 3a283507c03474d285196620fca506bd1a89b198) +[PMD: upstream commit e7b6274197c changed PFLASH_CFI01 <- CFI_PFLASH01, + and upstream commit 1643406520f changed PFlashCFI01 <- pflash_t] +Signed-off-by: Philippe Mathieu-Daudé + +Signed-off-by: Danilo C. L. de Paula +--- + hw/block/pflash_cfi01.c | 19 +++++++++++++++++++ + 1 file changed, 19 insertions(+) + +diff --git a/hw/block/pflash_cfi01.c b/hw/block/pflash_cfi01.c +index 2e82840..1be351e 100644 +--- a/hw/block/pflash_cfi01.c ++++ b/hw/block/pflash_cfi01.c +@@ -876,6 +876,24 @@ static void pflash_cfi01_realize(DeviceState *dev, Error **errp) + pfl->cfi_table[0x3f] = 0x01; /* Number of protection fields */ + } + ++static void pflash_cfi01_system_reset(DeviceState *dev) ++{ ++ pflash_t *pfl = CFI_PFLASH01(dev); ++ ++ /* ++ * The command 0x00 is not assigned by the CFI open standard, ++ * but QEMU historically uses it for the READ_ARRAY command (0xff). ++ */ ++ pfl->cmd = 0x00; ++ pfl->wcycle = 0; ++ memory_region_rom_device_set_romd(&pfl->mem, true); ++ /* ++ * The WSM ready timer occurs at most 150ns after system reset. ++ * This model deliberately ignores this delay. ++ */ ++ pfl->status = 0x80; ++} ++ + static Property pflash_cfi01_properties[] = { + DEFINE_PROP_DRIVE("drive", struct pflash_t, blk), + /* num-blocks is the number of blocks actually visible to the guest, +@@ -920,6 +938,7 @@ static void pflash_cfi01_class_init(ObjectClass *klass, void *data) + { + DeviceClass *dc = DEVICE_CLASS(klass); + ++ dc->reset = pflash_cfi01_system_reset; + dc->realize = pflash_cfi01_realize; + dc->props = pflash_cfi01_properties; + dc->vmsd = &vmstate_pflash; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-hw-pci-Add-missing-include.patch b/SOURCES/kvm-hw-pci-Add-missing-include.patch new file mode 100644 index 0000000..4d5c43b --- /dev/null +++ b/SOURCES/kvm-hw-pci-Add-missing-include.patch @@ -0,0 +1,71 @@ +From ff372341353d79db7e5a963d013bc6341d033337 Mon Sep 17 00:00:00 2001 +From: Danilo de Paula +Date: Wed, 22 May 2019 20:24:34 +0100 +Subject: [PATCH 12/12] hw/pci: Add missing include +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Danilo de Paula +Message-id: <20190522202434.2529-3-ddepaula@redhat.com> +Patchwork-id: 88165 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 2/2] hw/pci: Add missing include +Bugzilla: 1712946 +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Marc-André Lureau +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Stefan Hajnoczi + +From: Philippe Mathieu-Daudé + +Noted while refactoring: + + CC mips-softmmu/hw/mips/gt64xxx_pci.o + In file included from include/hw/pci-host/gt64xxx.h:2, + from hw/mips/gt64xxx_pci.c:30: + include/hw/pci/pci_bus.h:23:5: error: unknown type name ‘PCIIOMMUFunc’ + PCIIOMMUFunc iommu_fn; + ^~~~~~~~~~~~ + include/hw/pci/pci_bus.h:27:5: error: unknown type name ‘pci_set_irq_fn’ + pci_set_irq_fn set_irq; + ^~~~~~~~~~~~~~ + include/hw/pci/pci_bus.h:28:5: error: unknown type name ‘pci_map_irq_fn’ + pci_map_irq_fn map_irq; + ^~~~~~~~~~~~~~ + include/hw/pci/pci_bus.h:29:5: error: unknown type name ‘pci_route_irq_fn’ + pci_route_irq_fn route_intx_to_irq; + ^~~~~~~~~~~~~~~~ + include/hw/pci/pci_bus.h:31:24: error: ‘PCI_SLOT_MAX’ undeclared here (not in a function) + PCIDevice *devices[PCI_SLOT_MAX * PCI_FUNC_MAX]; + ^~~~~~~~~~~~ + include/hw/pci/pci_bus.h:31:39: error: ‘PCI_FUNC_MAX’ undeclared here (not in a function) + PCIDevice *devices[PCI_SLOT_MAX * PCI_FUNC_MAX]; + ^~~~~~~~~~~~ + make[1]: *** [rules.mak:69: hw/mips/gt64xxx_pci.o] Error 1 + make: *** [Makefile:482: subdir-mips-softmmu] Error 2 + +Signed-off-by: Philippe Mathieu-Daudé +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +(cherry picked from commit 2728a57a061af92b476f926b7fb66cb3ac60ab50) +Signed-off-by: Danilo C. L. de Paula +--- + include/hw/pci/pci_bus.h | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/include/hw/pci/pci_bus.h b/include/hw/pci/pci_bus.h +index b7da8f5..dfb7575 100644 +--- a/include/hw/pci/pci_bus.h ++++ b/include/hw/pci/pci_bus.h +@@ -1,6 +1,8 @@ + #ifndef QEMU_PCI_BUS_H + #define QEMU_PCI_BUS_H + ++#include "hw/pci/pci.h" ++ + /* + * PCI Bus datastructures. + * +-- +1.8.3.1 + diff --git a/SOURCES/kvm-hw-s390x-Use-the-IEC-binary-prefix-definitions.patch b/SOURCES/kvm-hw-s390x-Use-the-IEC-binary-prefix-definitions.patch new file mode 100644 index 0000000..0fc136a --- /dev/null +++ b/SOURCES/kvm-hw-s390x-Use-the-IEC-binary-prefix-definitions.patch @@ -0,0 +1,108 @@ +From 7b5de347e3786f6c2ade136cb4029344969b34ac Mon Sep 17 00:00:00 2001 +From: Cornelia Huck +Date: Wed, 17 Apr 2019 13:57:20 +0100 +Subject: [PATCH 03/24] hw/s390x: Use the IEC binary prefix definitions +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Cornelia Huck +Message-id: <20190417135741.25297-4-cohuck@redhat.com> +Patchwork-id: 85782 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v2 03/24] hw/s390x: Use the IEC binary prefix definitions +Bugzilla: 1699070 +RH-Acked-by: David Hildenbrand +RH-Acked-by: Thomas Huth +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Jens Freimann + +From: Philippe Mathieu-Daudé + +It eases code review, unit is explicit. + +Patch generated using: + + $ git grep -E '(1024|2048|4096|8192|(<<|>>).?(10|20|30))' hw/ include/hw/ + +and modified manually. + +Signed-off-by: Philippe Mathieu-Daudé +Reviewed-by: Thomas Huth +Acked-by: Cornelia Huck +Message-Id: <20180625124238.25339-20-f4bug@amsat.org> +Signed-off-by: Paolo Bonzini +(cherry picked from commit 393fc4c740d8d83d45bdbcd5f6a4cbc6be09b600) +Signed-off-by: Cornelia Huck +Signed-off-by: Danilo C. L. de Paula +--- + hw/s390x/s390-skeys.c | 3 ++- + hw/s390x/s390-stattrib.c | 3 ++- + hw/s390x/sclp.c | 3 ++- + 3 files changed, 6 insertions(+), 3 deletions(-) + +diff --git a/hw/s390x/s390-skeys.c b/hw/s390x/s390-skeys.c +index 76241c2..15f7ab0 100644 +--- a/hw/s390x/s390-skeys.c ++++ b/hw/s390x/s390-skeys.c +@@ -10,6 +10,7 @@ + */ + + #include "qemu/osdep.h" ++#include "qemu/units.h" + #include "hw/boards.h" + #include "hw/s390x/storage-keys.h" + #include "qapi/error.h" +@@ -19,7 +20,7 @@ + #include "sysemu/kvm.h" + #include "migration/register.h" + +-#define S390_SKEYS_BUFFER_SIZE 131072 /* Room for 128k storage keys */ ++#define S390_SKEYS_BUFFER_SIZE (128 * KiB) /* Room for 128k storage keys */ + #define S390_SKEYS_SAVE_FLAG_EOS 0x01 + #define S390_SKEYS_SAVE_FLAG_SKEYS 0x02 + #define S390_SKEYS_SAVE_FLAG_ERROR 0x04 +diff --git a/hw/s390x/s390-stattrib.c b/hw/s390x/s390-stattrib.c +index 70b9555..5161a16 100644 +--- a/hw/s390x/s390-stattrib.c ++++ b/hw/s390x/s390-stattrib.c +@@ -10,6 +10,7 @@ + */ + + #include "qemu/osdep.h" ++#include "qemu/units.h" + #include "hw/boards.h" + #include "cpu.h" + #include "migration/qemu-file.h" +@@ -20,7 +21,7 @@ + #include "qapi/error.h" + #include "qapi/qmp/qdict.h" + +-#define CMMA_BLOCK_SIZE (1 << 10) ++#define CMMA_BLOCK_SIZE (1 * KiB) + + #define STATTR_FLAG_EOS 0x01ULL + #define STATTR_FLAG_MORE 0x02ULL +diff --git a/hw/s390x/sclp.c b/hw/s390x/sclp.c +index 2abdb62..4510a80 100644 +--- a/hw/s390x/sclp.c ++++ b/hw/s390x/sclp.c +@@ -13,6 +13,7 @@ + */ + + #include "qemu/osdep.h" ++#include "qemu/units.h" + #include "qapi/error.h" + #include "cpu.h" + #include "sysemu/sysemu.h" +@@ -289,7 +290,7 @@ static void sclp_realize(DeviceState *dev, Error **errp) + ret = s390_set_memory_limit(machine->maxram_size, &hw_limit); + if (ret == -E2BIG) { + error_setg(&err, "host supports a maximum of %" PRIu64 " GB", +- hw_limit >> 30); ++ hw_limit / GiB); + } else if (ret) { + error_setg(&err, "setting the guest size failed"); + } +-- +1.8.3.1 + diff --git a/SOURCES/kvm-hw-s390x-s390-pci-bus-Convert-sysbus-init-function-t.patch b/SOURCES/kvm-hw-s390x-s390-pci-bus-Convert-sysbus-init-function-t.patch new file mode 100644 index 0000000..c1cc32d --- /dev/null +++ b/SOURCES/kvm-hw-s390x-s390-pci-bus-Convert-sysbus-init-function-t.patch @@ -0,0 +1,116 @@ +From 11e6368bca72590e49a7705b55ce031f543941d7 Mon Sep 17 00:00:00 2001 +From: Cornelia Huck +Date: Wed, 17 Apr 2019 13:57:23 +0100 +Subject: [PATCH 06/24] hw/s390x/s390-pci-bus: Convert sysbus init function to + realize function +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Cornelia Huck +Message-id: <20190417135741.25297-7-cohuck@redhat.com> +Patchwork-id: 85787 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v2 06/24] hw/s390x/s390-pci-bus: Convert sysbus init function to realize function +Bugzilla: 1699070 +RH-Acked-by: David Hildenbrand +RH-Acked-by: Thomas Huth +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Jens Freimann + +From: Thomas Huth + +The SysBusDeviceClass->init() interface is considered as a legacy interface +and there are currently some efforts going on to get rid of it. Thus let's +convert the init function in the s390x code to realize() instead. + +Signed-off-by: Thomas Huth +Message-Id: <1538466491-2073-1-git-send-email-thuth@redhat.com> +Reviewed-by: Philippe Mathieu-Daudé +Reviewed-by: David Hildenbrand +Signed-off-by: Cornelia Huck +(cherry picked from commit b576d582ea2b03f4eada186fff59308d22b40a6a) +Signed-off-by: Cornelia Huck +Signed-off-by: Danilo C. L. de Paula +--- + hw/s390x/s390-pci-bus.c | 34 +++++++++++++++++++++------------- + 1 file changed, 21 insertions(+), 13 deletions(-) + +diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c +index 10da874..f253774 100644 +--- a/hw/s390x/s390-pci-bus.c ++++ b/hw/s390x/s390-pci-bus.c +@@ -692,27 +692,35 @@ static void s390_pci_iommu_free(S390pciState *s, PCIBus *bus, int32_t devfn) + object_unref(OBJECT(iommu)); + } + +-static int s390_pcihost_init(SysBusDevice *dev) ++static void s390_pcihost_realize(DeviceState *dev, Error **errp) + { + PCIBus *b; + BusState *bus; + PCIHostState *phb = PCI_HOST_BRIDGE(dev); + S390pciState *s = S390_PCI_HOST_BRIDGE(dev); ++ Error *local_err = NULL; + + DPRINTF("host_init\n"); + +- b = pci_register_root_bus(DEVICE(dev), NULL, +- s390_pci_set_irq, s390_pci_map_irq, NULL, +- get_system_memory(), get_system_io(), 0, 64, +- TYPE_PCI_BUS); ++ b = pci_register_root_bus(dev, NULL, s390_pci_set_irq, s390_pci_map_irq, ++ NULL, get_system_memory(), get_system_io(), 0, ++ 64, TYPE_PCI_BUS); + pci_setup_iommu(b, s390_pci_dma_iommu, s); + + bus = BUS(b); +- qbus_set_hotplug_handler(bus, DEVICE(dev), NULL); ++ qbus_set_hotplug_handler(bus, dev, &local_err); ++ if (local_err) { ++ error_propagate(errp, local_err); ++ return; ++ } + phb->bus = b; + +- s->bus = S390_PCI_BUS(qbus_create(TYPE_S390_PCI_BUS, DEVICE(s), NULL)); +- qbus_set_hotplug_handler(BUS(s->bus), DEVICE(s), NULL); ++ s->bus = S390_PCI_BUS(qbus_create(TYPE_S390_PCI_BUS, dev, NULL)); ++ qbus_set_hotplug_handler(BUS(s->bus), dev, &local_err); ++ if (local_err) { ++ error_propagate(errp, local_err); ++ return; ++ } + + s->iommu_table = g_hash_table_new_full(g_int64_hash, g_int64_equal, + NULL, g_free); +@@ -722,9 +730,10 @@ static int s390_pcihost_init(SysBusDevice *dev) + QTAILQ_INIT(&s->zpci_devs); + + css_register_io_adapters(CSS_IO_ADAPTER_PCI, true, false, +- S390_ADAPTER_SUPPRESSIBLE, &error_abort); +- +- return 0; ++ S390_ADAPTER_SUPPRESSIBLE, &local_err); ++ if (local_err) { ++ error_propagate(errp, local_err); ++ } + } + + static int s390_pci_msix_init(S390PCIBusDevice *pbdev) +@@ -1018,12 +1027,11 @@ static void s390_pcihost_reset(DeviceState *dev) + + static void s390_pcihost_class_init(ObjectClass *klass, void *data) + { +- SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); + DeviceClass *dc = DEVICE_CLASS(klass); + HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass); + + dc->reset = s390_pcihost_reset; +- k->init = s390_pcihost_init; ++ dc->realize = s390_pcihost_realize; + hc->plug = s390_pcihost_hot_plug; + hc->unplug = s390_pcihost_hot_unplug; + msi_nonbroken = true; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-i386-Add-CPUID-bit-and-feature-words-for-IA32_ARCH_C.patch b/SOURCES/kvm-i386-Add-CPUID-bit-and-feature-words-for-IA32_ARCH_C.patch index c1ea31a..6a7fe3c 100644 --- a/SOURCES/kvm-i386-Add-CPUID-bit-and-feature-words-for-IA32_ARCH_C.patch +++ b/SOURCES/kvm-i386-Add-CPUID-bit-and-feature-words-for-IA32_ARCH_C.patch @@ -1,17 +1,17 @@ -From e5f76077a47460bcba0bdfc1d70c7b79f84d18b7 Mon Sep 17 00:00:00 2001 +From 5765ff204771d519ec6c109a8f6b15871251dff0 Mon Sep 17 00:00:00 2001 From: "plai@redhat.com" -Date: Tue, 20 Aug 2019 00:24:33 +0100 -Subject: [PATCH 2/9] i386: Add CPUID bit and feature words for +Date: Wed, 3 Apr 2019 15:54:26 +0100 +Subject: [PATCH 02/10] i386: Add CPUID bit and feature words for IA32_ARCH_CAPABILITIES MSR RH-Author: plai@redhat.com -Message-id: <1566260680-20995-3-git-send-email-plai@redhat.com> -Patchwork-id: 90066 -O-Subject: [RHEL8.0 qemu-kvm PATCH v3 2/9] i386: Add CPUID bit and feature words for IA32_ARCH_CAPABILITIES MSR -Bugzilla: 1718235 +Message-id: <1554306874-28796-3-git-send-email-plai@redhat.com> +Patchwork-id: 85386 +O-Subject: [RHEL8.1 qemu-kvm PATCH resend 02/10] i386: Add CPUID bit and feature words for IA32_ARCH_CAPABILITIES MSR +Bugzilla: 1561761 RH-Acked-by: Eduardo Habkost -RH-Acked-by: John Snow RH-Acked-by: Igor Mammedov +RH-Acked-by: Michael S. Tsirkin From: Robert Hoo diff --git a/SOURCES/kvm-i386-Add-CPUID-bit-for-PCONFIG.patch b/SOURCES/kvm-i386-Add-CPUID-bit-for-PCONFIG.patch new file mode 100644 index 0000000..1b27aab --- /dev/null +++ b/SOURCES/kvm-i386-Add-CPUID-bit-for-PCONFIG.patch @@ -0,0 +1,58 @@ +From 9785cad163ad4557e218ea40ed146bf02b02cb98 Mon Sep 17 00:00:00 2001 +From: "plai@redhat.com" +Date: Wed, 3 Apr 2019 15:54:27 +0100 +Subject: [PATCH 03/10] i386: Add CPUID bit for PCONFIG + +RH-Author: plai@redhat.com +Message-id: <1554306874-28796-4-git-send-email-plai@redhat.com> +Patchwork-id: 85381 +O-Subject: [RHEL8.1 qemu-kvm PATCH resend 03/10] i386: Add CPUID bit for PCONFIG +Bugzilla: 1561761 +RH-Acked-by: Eduardo Habkost +RH-Acked-by: Igor Mammedov +RH-Acked-by: Michael S. Tsirkin + +From: Robert Hoo + +PCONFIG: Platform configuration, enumerated by CPUID.(EAX=07H, ECX=0): +EDX[bit18]. + +Signed-off-by: Robert Hoo +Message-Id: <1530781798-183214-4-git-send-email-robert.hu@linux.intel.com> +Signed-off-by: Eduardo Habkost +(cherry picked from commit 5131dc433df54b37e8e918d8fba7fe10344e7a7b) +Signed-off-by: Paul Lai +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.c | 2 +- + target/i386/cpu.h | 1 + + 2 files changed, 2 insertions(+), 1 deletion(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index 6d38ac0..fec39bd 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -1005,7 +1005,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, +- NULL, NULL, NULL, NULL, ++ NULL, NULL, "pconfig", NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, "spec-ctrl", "stibp", + NULL, "arch-capabilities", NULL, "ssbd", +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index e5e5169..3b2ea97 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -686,6 +686,7 @@ typedef uint32_t FeatureWordArray[FEATURE_WORDS]; + + #define CPUID_7_0_EDX_AVX512_4VNNIW (1U << 2) /* AVX512 Neural Network Instructions */ + #define CPUID_7_0_EDX_AVX512_4FMAPS (1U << 3) /* AVX512 Multiply Accumulation Single Precision */ ++#define CPUID_7_0_EDX_PCONFIG (1U << 18) /* Platform Configuration */ + #define CPUID_7_0_EDX_SPEC_CTRL (1U << 26) /* Speculation Control */ + #define CPUID_7_0_EDX_ARCH_CAPABILITIES (1U << 29) /*Arch Capabilities*/ + #define CPUID_7_0_EDX_SPEC_CTRL_SSBD (1U << 31) /* Speculative Store Bypass Disable */ +-- +1.8.3.1 + diff --git a/SOURCES/kvm-i386-Add-CPUID-bit-for-WBNOINVD.patch b/SOURCES/kvm-i386-Add-CPUID-bit-for-WBNOINVD.patch new file mode 100644 index 0000000..da0b785 --- /dev/null +++ b/SOURCES/kvm-i386-Add-CPUID-bit-for-WBNOINVD.patch @@ -0,0 +1,63 @@ +From 1e661277e83c9b2e29bf5e2e77f358355aa11c8a Mon Sep 17 00:00:00 2001 +From: "plai@redhat.com" +Date: Wed, 3 Apr 2019 15:54:28 +0100 +Subject: [PATCH 04/10] i386: Add CPUID bit for WBNOINVD + +RH-Author: plai@redhat.com +Message-id: <1554306874-28796-5-git-send-email-plai@redhat.com> +Patchwork-id: 85382 +O-Subject: [RHEL8.1 qemu-kvm PATCH resend 04/10] i386: Add CPUID bit for WBNOINVD +Bugzilla: 1561761 +RH-Acked-by: Eduardo Habkost +RH-Acked-by: Igor Mammedov +RH-Acked-by: Michael S. Tsirkin + +From: Robert Hoo + +WBNOINVD: Write back and do not invalidate cache, enumerated by +CPUID.(EAX=80000008H, ECX=0):EBX[bit 9]. + +Signed-off-by: Robert Hoo +Message-Id: <1530781798-183214-5-git-send-email-robert.hu@linux.intel.com> +Signed-off-by: Eduardo Habkost +(cherry picked from commit 59a80a19ca31a6fff9fdbb6b4cf55a5a0767c3bc) +Signed-off-by: Paul Lai + +Resolved Conflicts: + target/i386/cpu.h + +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.c | 2 +- + target/i386/cpu.h | 2 ++ + 2 files changed, 3 insertions(+), 1 deletion(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index fec39bd..8b9a9f6 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -1036,7 +1036,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { + .feat_names = { + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, +- NULL, NULL, NULL, NULL, ++ NULL, "wbnoinvd", NULL, NULL, + "ibpb", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index 3b2ea97..dd4493e 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -693,6 +693,8 @@ typedef uint32_t FeatureWordArray[FEATURE_WORDS]; + + #define KVM_HINTS_DEDICATED (1U << 0) + ++#define CPUID_8000_0008_EBX_WBNOINVD (1U << 9) /* Write back and ++ do not invalidate cache */ + #define CPUID_8000_0008_EBX_IBPB (1U << 12) /* Indirect Branch Prediction Barrier */ + + #define CPUID_XSAVE_XSAVEOPT (1U << 0) +-- +1.8.3.1 + diff --git a/SOURCES/kvm-i386-Add-new-CPU-model-Icelake-Server-Client.patch b/SOURCES/kvm-i386-Add-new-CPU-model-Icelake-Server-Client.patch new file mode 100644 index 0000000..7c19874 --- /dev/null +++ b/SOURCES/kvm-i386-Add-new-CPU-model-Icelake-Server-Client.patch @@ -0,0 +1,179 @@ +From 0a8e2990b83c805fc6cc2421950a938caa9ba8a5 Mon Sep 17 00:00:00 2001 +From: "plai@redhat.com" +Date: Wed, 3 Apr 2019 15:54:29 +0100 +Subject: [PATCH 05/10] i386: Add new CPU model Icelake-{Server, Client} + +RH-Author: plai@redhat.com +Message-id: <1554306874-28796-6-git-send-email-plai@redhat.com> +Patchwork-id: 85383 +O-Subject: [RHEL8.1 qemu-kvm PATCH resend 05/10] i386: Add new CPU model Icelake-{Server, Client} +Bugzilla: 1561761 +RH-Acked-by: Eduardo Habkost +RH-Acked-by: Igor Mammedov +RH-Acked-by: Michael S. Tsirkin + +From: Robert Hoo + +New CPU models mostly inherit features from ancestor Skylake, while addin new +features: UMIP, New Instructions ( PCONIFIG (server only), WBNOINVD, +AVX512_VBMI2, GFNI, AVX512_VNNI, VPCLMULQDQ, VAES, AVX512_BITALG), +Intel PT and 5-level paging (Server only). As well as +IA32_PRED_CMD, SSBD support for speculative execution +side channel mitigations. + +Note: +For 5-level paging, Guest physical address width can be configured, with +parameter "phys-bits". Unless explicitly specified, we still use its default +value, even for Icelake-Server cpu model. +At present, hold on expose IA32_ARCH_CAPABILITIES to guest, as 1) This MSR +actually presents more than 1 'feature', maintainers are considering expanding current +features presentation of only CPUIDs to MSR bits; 2) a reasonable default value +for MSR_IA32_ARCH_CAPABILITIES needs to settled first. These 2 are actully +beyond Icelake CPU model itself but fundamental. So split these work apart +and do it later. +https://lists.gnu.org/archive/html/qemu-devel/2018-07/msg00774.html +https://lists.gnu.org/archive/html/qemu-devel/2018-07/msg00796.html + +Signed-off-by: Robert Hoo +Message-Id: <1530781798-183214-6-git-send-email-robert.hu@linux.intel.com> +Signed-off-by: Eduardo Habkost +(cherry picked from commit 8a11c62da9146dd89aee98947e6bd831e65a970d) +Signed-off-by: Paul Lai + +Resovled Conflicts: + target/i386/cpu.c + +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.c | 115 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 115 insertions(+) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index 8b9a9f6..d86b744 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -2414,6 +2414,121 @@ static X86CPUDefinition builtin_x86_defs[] = { + .model_id = "Intel Xeon Processor (Skylake, IBRS)", + }, + { ++ .name = "Icelake-Client", ++ .level = 0xd, ++ .vendor = CPUID_VENDOR_INTEL, ++ .family = 6, ++ .model = 126, ++ .stepping = 0, ++ .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_RDTSCP | CPUID_EXT2_NX | ++ CPUID_EXT2_SYSCALL, ++ .features[FEAT_8000_0001_ECX] = ++ CPUID_EXT3_ABM | CPUID_EXT3_LAHF_LM | CPUID_EXT3_3DNOWPREFETCH, ++ .features[FEAT_8000_0008_EBX] = ++ CPUID_8000_0008_EBX_WBNOINVD, ++ .features[FEAT_7_0_EBX] = ++ CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_BMI1 | ++ CPUID_7_0_EBX_HLE | CPUID_7_0_EBX_AVX2 | CPUID_7_0_EBX_SMEP | ++ CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ERMS | CPUID_7_0_EBX_INVPCID | ++ CPUID_7_0_EBX_RTM | CPUID_7_0_EBX_RDSEED | CPUID_7_0_EBX_ADX | ++ CPUID_7_0_EBX_SMAP | CPUID_7_0_EBX_MPX | CPUID_7_0_EBX_INTEL_PT, ++ .features[FEAT_7_0_ECX] = ++ CPUID_7_0_ECX_VBMI | CPUID_7_0_ECX_UMIP | CPUID_7_0_ECX_PKU | ++ CPUID_7_0_ECX_OSPKE | CPUID_7_0_ECX_VBMI2 | CPUID_7_0_ECX_GFNI | ++ CPUID_7_0_ECX_VAES | CPUID_7_0_ECX_VPCLMULQDQ | ++ CPUID_7_0_ECX_AVX512VNNI | CPUID_7_0_ECX_AVX512BITALG | ++ CPUID_7_0_ECX_AVX512_VPOPCNTDQ, ++ .features[FEAT_7_0_EDX] = ++ CPUID_7_0_EDX_SPEC_CTRL | CPUID_7_0_EDX_SPEC_CTRL_SSBD, ++ /* Missing: XSAVES (not supported by some Linux versions, ++ * including v4.1 to v4.12). ++ * KVM doesn't yet expose any XSAVES state save component, ++ * and the only one defined in Skylake (processor tracing) ++ * probably will block migration anyway. ++ */ ++ .features[FEAT_XSAVE] = ++ CPUID_XSAVE_XSAVEOPT | CPUID_XSAVE_XSAVEC | ++ CPUID_XSAVE_XGETBV1, ++ .features[FEAT_6_EAX] = ++ CPUID_6_EAX_ARAT, ++ .xlevel = 0x80000008, ++ .model_id = "Intel Core Processor (Icelake)", ++ }, ++ { ++ .name = "Icelake-Server", ++ .level = 0xd, ++ .vendor = CPUID_VENDOR_INTEL, ++ .family = 6, ++ .model = 134, ++ .stepping = 0, ++ .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_8000_0008_EBX] = ++ CPUID_8000_0008_EBX_WBNOINVD, ++ .features[FEAT_7_0_EBX] = ++ CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_BMI1 | ++ CPUID_7_0_EBX_HLE | CPUID_7_0_EBX_AVX2 | CPUID_7_0_EBX_SMEP | ++ CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ERMS | CPUID_7_0_EBX_INVPCID | ++ CPUID_7_0_EBX_RTM | CPUID_7_0_EBX_RDSEED | CPUID_7_0_EBX_ADX | ++ CPUID_7_0_EBX_SMAP | CPUID_7_0_EBX_MPX | CPUID_7_0_EBX_CLWB | ++ CPUID_7_0_EBX_AVX512F | CPUID_7_0_EBX_AVX512DQ | ++ CPUID_7_0_EBX_AVX512BW | CPUID_7_0_EBX_AVX512CD | ++ CPUID_7_0_EBX_AVX512VL | CPUID_7_0_EBX_CLFLUSHOPT | ++ CPUID_7_0_EBX_INTEL_PT, ++ .features[FEAT_7_0_ECX] = ++ CPUID_7_0_ECX_VBMI | CPUID_7_0_ECX_UMIP | CPUID_7_0_ECX_PKU | ++ CPUID_7_0_ECX_OSPKE | CPUID_7_0_ECX_VBMI2 | CPUID_7_0_ECX_GFNI | ++ CPUID_7_0_ECX_VAES | CPUID_7_0_ECX_VPCLMULQDQ | ++ CPUID_7_0_ECX_AVX512VNNI | CPUID_7_0_ECX_AVX512BITALG | ++ CPUID_7_0_ECX_AVX512_VPOPCNTDQ | CPUID_7_0_ECX_LA57, ++ .features[FEAT_7_0_EDX] = ++ CPUID_7_0_EDX_PCONFIG | CPUID_7_0_EDX_SPEC_CTRL | ++ CPUID_7_0_EDX_SPEC_CTRL_SSBD, ++ /* Missing: XSAVES (not supported by some Linux versions, ++ * including v4.1 to v4.12). ++ * KVM doesn't yet expose any XSAVES state save component, ++ * and the only one defined in Skylake (processor tracing) ++ * probably will block migration anyway. ++ */ ++ .features[FEAT_XSAVE] = ++ CPUID_XSAVE_XSAVEOPT | CPUID_XSAVE_XSAVEC | ++ CPUID_XSAVE_XGETBV1, ++ .features[FEAT_6_EAX] = ++ CPUID_6_EAX_ARAT, ++ .xlevel = 0x80000008, ++ .model_id = "Intel Xeon Processor (Icelake)", ++ }, ++ { + .name = "Opteron_G1", + .level = 5, + .vendor = CPUID_VENDOR_AMD, +-- +1.8.3.1 + diff --git a/SOURCES/kvm-i386-Add-new-MSR-indices-for-IA32_PRED_CMD-and-IA32_.patch b/SOURCES/kvm-i386-Add-new-MSR-indices-for-IA32_PRED_CMD-and-IA32_.patch index c342a58..1c77fc2 100644 --- a/SOURCES/kvm-i386-Add-new-MSR-indices-for-IA32_PRED_CMD-and-IA32_.patch +++ b/SOURCES/kvm-i386-Add-new-MSR-indices-for-IA32_PRED_CMD-and-IA32_.patch @@ -1,17 +1,17 @@ -From 98e94db3fe3a94ff3b827523ec6cf2a482c8e593 Mon Sep 17 00:00:00 2001 +From a0a63864906cd578c7bc73ea5318282fb393c147 Mon Sep 17 00:00:00 2001 From: "plai@redhat.com" -Date: Tue, 20 Aug 2019 00:24:32 +0100 -Subject: [PATCH 1/9] i386: Add new MSR indices for IA32_PRED_CMD and +Date: Wed, 3 Apr 2019 15:54:25 +0100 +Subject: [PATCH 01/10] i386: Add new MSR indices for IA32_PRED_CMD and IA32_ARCH_CAPABILITIES RH-Author: plai@redhat.com -Message-id: <1566260680-20995-2-git-send-email-plai@redhat.com> -Patchwork-id: 90063 -O-Subject: [RHEL8.0 qemu-kvm PATCH v3 1/9] i386: Add new MSR indices for IA32_PRED_CMD and IA32_ARCH_CAPABILITIES -Bugzilla: 1718235 +Message-id: <1554306874-28796-2-git-send-email-plai@redhat.com> +Patchwork-id: 85379 +O-Subject: [RHEL8.1 qemu-kvm PATCH resend 01/10] i386: Add new MSR indices for IA32_PRED_CMD and IA32_ARCH_CAPABILITIES +Bugzilla: 1561761 RH-Acked-by: Eduardo Habkost -RH-Acked-by: John Snow RH-Acked-by: Igor Mammedov +RH-Acked-by: Michael S. Tsirkin From: Robert Hoo diff --git a/SOURCES/kvm-i386-Add-new-model-of-Cascadelake-Server.patch b/SOURCES/kvm-i386-Add-new-model-of-Cascadelake-Server.patch new file mode 100644 index 0000000..8b96ddd --- /dev/null +++ b/SOURCES/kvm-i386-Add-new-model-of-Cascadelake-Server.patch @@ -0,0 +1,107 @@ +From 2d44f02611fcb0eddad08d2c5d4361d568fcfd67 Mon Sep 17 00:00:00 2001 +From: "plai@redhat.com" +Date: Mon, 1 Jul 2019 16:17:30 +0100 +Subject: [PATCH 01/39] i386: Add new model of Cascadelake-Server + +RH-Author: plai@redhat.com +Message-id: <1561997854-9646-2-git-send-email-plai@redhat.com> +Patchwork-id: 89331 +O-Subject: [RHEL8.1 qemu-kvm PATCH v6 1/5] i386: Add new model of Cascadelake-Server +Bugzilla: 1629906 +RH-Acked-by: Eduardo Habkost +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Bandan Das + +From: Tao Xu + +New CPU models mostly inherit features from ancestor Skylake-Server, +while addin new features: AVX512_VNNI, Intel PT. +SSBD support for speculative execution +side channel mitigations. + +Note: + +On Cascadelake, some capabilities (RDCL_NO, IBRS_ALL, RSBA, +SKIP_L1DFL_VMENTRY and SSB_NO) are enumerated by MSR. +These features rely on MSR based feature support patch. +Will be added later after that patch's in. +http://lists.nongnu.org/archive/html/qemu-devel/2018-09/msg00074.html + +Signed-off-by: Tao Xu +Message-Id: <20180919031122.28487-2-tao3.xu@intel.com> +Signed-off-by: Eduardo Habkost +(cherry picked from commit c7a88b52f62b30c04158eeb07f73e3f72221b6a8) +Signed-off-by: Paul Lai +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 54 insertions(+) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index 5c10093..9ba5288 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -2483,6 +2483,60 @@ static X86CPUDefinition builtin_x86_defs[] = { + .model_id = "Intel Xeon Processor (Skylake, IBRS)", + }, + { ++ .name = "Cascadelake-Server", ++ .level = 0xd, ++ .vendor = CPUID_VENDOR_INTEL, ++ .family = 6, ++ .model = 85, ++ .stepping = 5, ++ .features[FEAT_1_EDX] = ++ CPUID_VME | CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | ++ CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA | ++ CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 | ++ CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE | ++ CPUID_DE | CPUID_FP87, ++ .features[FEAT_1_ECX] = ++ CPUID_EXT_AVX | CPUID_EXT_XSAVE | CPUID_EXT_AES | ++ CPUID_EXT_POPCNT | CPUID_EXT_X2APIC | CPUID_EXT_SSE42 | ++ CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | ++ CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSE3 | ++ CPUID_EXT_TSC_DEADLINE_TIMER | CPUID_EXT_FMA | CPUID_EXT_MOVBE | ++ CPUID_EXT_PCID | CPUID_EXT_F16C | CPUID_EXT_RDRAND, ++ .features[FEAT_8000_0001_EDX] = ++ CPUID_EXT2_LM | CPUID_EXT2_PDPE1GB | CPUID_EXT2_RDTSCP | ++ CPUID_EXT2_NX | CPUID_EXT2_SYSCALL, ++ .features[FEAT_8000_0001_ECX] = ++ CPUID_EXT3_ABM | CPUID_EXT3_LAHF_LM | CPUID_EXT3_3DNOWPREFETCH, ++ .features[FEAT_7_0_EBX] = ++ CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_BMI1 | ++ CPUID_7_0_EBX_HLE | CPUID_7_0_EBX_AVX2 | CPUID_7_0_EBX_SMEP | ++ CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ERMS | CPUID_7_0_EBX_INVPCID | ++ CPUID_7_0_EBX_RTM | CPUID_7_0_EBX_RDSEED | CPUID_7_0_EBX_ADX | ++ CPUID_7_0_EBX_SMAP | CPUID_7_0_EBX_MPX | CPUID_7_0_EBX_CLWB | ++ CPUID_7_0_EBX_AVX512F | CPUID_7_0_EBX_AVX512DQ | ++ CPUID_7_0_EBX_AVX512BW | CPUID_7_0_EBX_AVX512CD | ++ CPUID_7_0_EBX_AVX512VL | CPUID_7_0_EBX_CLFLUSHOPT | ++ CPUID_7_0_EBX_INTEL_PT, ++ .features[FEAT_7_0_ECX] = ++ CPUID_7_0_ECX_PKU | CPUID_7_0_ECX_OSPKE | ++ CPUID_7_0_ECX_AVX512VNNI, ++ .features[FEAT_7_0_EDX] = ++ CPUID_7_0_EDX_SPEC_CTRL | CPUID_7_0_EDX_SPEC_CTRL_SSBD, ++ /* Missing: XSAVES (not supported by some Linux versions, ++ * including v4.1 to v4.12). ++ * KVM doesn't yet expose any XSAVES state save component, ++ * and the only one defined in Skylake (processor tracing) ++ * probably will block migration anyway. ++ */ ++ .features[FEAT_XSAVE] = ++ CPUID_XSAVE_XSAVEOPT | CPUID_XSAVE_XSAVEC | ++ CPUID_XSAVE_XGETBV1, ++ .features[FEAT_6_EAX] = ++ CPUID_6_EAX_ARAT, ++ .xlevel = 0x80000008, ++ .model_id = "Intel Xeon Processor (Cascadelake)", ++ }, ++ { + .name = "Icelake-Client", + .level = 0xd, + .vendor = CPUID_VENDOR_INTEL, +-- +1.8.3.1 + diff --git a/SOURCES/kvm-i386-Disable-OSPKE-on-CPU-model-definitions-NEW.patch b/SOURCES/kvm-i386-Disable-OSPKE-on-CPU-model-definitions-NEW.patch new file mode 100644 index 0000000..c78b32a --- /dev/null +++ b/SOURCES/kvm-i386-Disable-OSPKE-on-CPU-model-definitions-NEW.patch @@ -0,0 +1,72 @@ +From 04f34e7c0b0fada186ca7012f5f4168f46483c5f Mon Sep 17 00:00:00 2001 +From: "plai@redhat.com" +Date: Mon, 1 Jul 2019 16:17:34 +0100 +Subject: [PATCH 05/39] i386: Disable OSPKE on CPU model definitions + +RH-Author: plai@redhat.com +Message-id: <1561997854-9646-6-git-send-email-plai@redhat.com> +Patchwork-id: 89334 +O-Subject: [RHEL8.1 qemu-kvm PATCH v6 5/5] i386: Disable OSPKE on CPU model definitions +Bugzilla: 1629906 +RH-Acked-by: Eduardo Habkost +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Bandan Das + +From: Eduardo Habkost + +Currently, the Cascadelake-Server, Icelake-Client, and +Icelake-Server are always generating the following warning: + + qemu-system-x86_64: warning: \ + host doesn't support requested feature: CPUID.07H:ECX [bit 4] + +This happens because OSPKE was never returned by +GET_SUPPORTED_CPUID or x86_cpu_get_supported_feature_word(). +OSPKE is a runtime flag automatically set by the KVM module or by +TCG code, was always cleared by x86_cpu_filter_features(), and +was not supposed to appear on the CPU model table. + +Remove the OSPKE flag from the CPU model table entries, to avoid +the bogus warning and avoid returning invalid feature data on +query-cpu-* QMP commands. As OSPKE was always cleared by +x86_cpu_filter_features(), this won't have any guest-visible +impact. + +Include a test case that should detect the problem if we introduce +a similar bug again. + +Fixes: c7a88b52f62b ("i386: Add new model of Cascadelake-Server") +Fixes: 8a11c62da914 ("i386: Add new CPU model Icelake-{Server,Client}") +Cc: Tao Xu +Cc: Robert Hoo +Signed-off-by: Eduardo Habkost +Message-Id: <20190319200515.14999-1-ehabkost@redhat.com> +Signed-off-by: Eduardo Habkost +(cherry picked from commit bb4928c7cafe50ab2137a0034e350ef1bfa044d9) +Signed-off-by: Paul Lai +Signed-off-by: Danilo C. L. de Paula + +Conflicts: + target/i386/cpu.c + +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index 2538d82..af62281 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -2517,7 +2517,7 @@ static X86CPUDefinition builtin_x86_defs[] = { + CPUID_7_0_EBX_AVX512BW | CPUID_7_0_EBX_AVX512CD | + CPUID_7_0_EBX_AVX512VL | CPUID_7_0_EBX_CLFLUSHOPT, + .features[FEAT_7_0_ECX] = +- CPUID_7_0_ECX_PKU | CPUID_7_0_ECX_OSPKE | ++ CPUID_7_0_ECX_PKU | + CPUID_7_0_ECX_AVX512VNNI, + .features[FEAT_7_0_EDX] = + CPUID_7_0_EDX_SPEC_CTRL | CPUID_7_0_EDX_SPEC_CTRL_SSBD, +-- +1.8.3.1 + diff --git a/SOURCES/kvm-i386-Disable-OSPKE-on-CPU-model-definitions.patch b/SOURCES/kvm-i386-Disable-OSPKE-on-CPU-model-definitions.patch new file mode 100644 index 0000000..7b86e40 --- /dev/null +++ b/SOURCES/kvm-i386-Disable-OSPKE-on-CPU-model-definitions.patch @@ -0,0 +1,115 @@ +From 766a7ab6a7ebb9e819f6ec9a9b109ec4659388d4 Mon Sep 17 00:00:00 2001 +From: Eduardo Habkost +Date: Thu, 9 May 2019 23:21:08 +0100 +Subject: [PATCH 2/2] i386: Disable OSPKE on CPU model definitions + +RH-Author: Eduardo Habkost +Message-id: <20190509232108.25675-3-ehabkost@redhat.com> +Patchwork-id: 87254 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 2/2] i386: Disable OSPKE on CPU model definitions +Bugzilla: 1561761 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Igor Mammedov +RH-Acked-by: Danilo de Paula + +Currently, the Cascadelake-Server, Icelake-Client, and +Icelake-Server are always generating the following warning: + + qemu-system-x86_64: warning: \ + host doesn't support requested feature: CPUID.07H:ECX [bit 4] + +This happens because OSPKE was never returned by +GET_SUPPORTED_CPUID or x86_cpu_get_supported_feature_word(). +OSPKE is a runtime flag automatically set by the KVM module or by +TCG code, was always cleared by x86_cpu_filter_features(), and +was not supposed to appear on the CPU model table. + +Remove the OSPKE flag from the CPU model table entries, to avoid +the bogus warning and avoid returning invalid feature data on +query-cpu-* QMP commands. As OSPKE was always cleared by +x86_cpu_filter_features(), this won't have any guest-visible +impact. + +Include a test case that should detect the problem if we introduce +a similar bug again. + +Fixes: c7a88b52f62b ("i386: Add new model of Cascadelake-Server") +Fixes: 8a11c62da914 ("i386: Add new CPU model Icelake-{Server,Client}") +Cc: Tao Xu +Cc: Robert Hoo +Signed-off-by: Eduardo Habkost +Message-Id: <20190319200515.14999-1-ehabkost@redhat.com> +Signed-off-by: Eduardo Habkost +(cherry picked from commit bb4928c7cafe50ab2137a0034e350ef1bfa044d9) +Signed-off-by: Eduardo Habkost +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.c | 4 ++-- + tests/acceptance/cpu_queries.py | 33 +++++++++++++++++++++++++++++++++ + 2 files changed, 35 insertions(+), 2 deletions(-) + create mode 100644 tests/acceptance/cpu_queries.py + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index c56d7e7..8ff6c38 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -2518,7 +2518,7 @@ static X86CPUDefinition builtin_x86_defs[] = { + CPUID_7_0_EBX_SMAP | CPUID_7_0_EBX_MPX, + .features[FEAT_7_0_ECX] = + CPUID_7_0_ECX_VBMI | CPUID_7_0_ECX_UMIP | CPUID_7_0_ECX_PKU | +- CPUID_7_0_ECX_OSPKE | CPUID_7_0_ECX_VBMI2 | CPUID_7_0_ECX_GFNI | ++ CPUID_7_0_ECX_VBMI2 | CPUID_7_0_ECX_GFNI | + CPUID_7_0_ECX_VAES | CPUID_7_0_ECX_VPCLMULQDQ | + CPUID_7_0_ECX_AVX512VNNI | CPUID_7_0_ECX_AVX512BITALG | + CPUID_7_0_ECX_AVX512_VPOPCNTDQ, +@@ -2576,7 +2576,7 @@ static X86CPUDefinition builtin_x86_defs[] = { + CPUID_7_0_EBX_AVX512VL | CPUID_7_0_EBX_CLFLUSHOPT, + .features[FEAT_7_0_ECX] = + CPUID_7_0_ECX_VBMI | CPUID_7_0_ECX_UMIP | CPUID_7_0_ECX_PKU | +- CPUID_7_0_ECX_OSPKE | CPUID_7_0_ECX_VBMI2 | CPUID_7_0_ECX_GFNI | ++ CPUID_7_0_ECX_VBMI2 | CPUID_7_0_ECX_GFNI | + CPUID_7_0_ECX_VAES | CPUID_7_0_ECX_VPCLMULQDQ | + CPUID_7_0_ECX_AVX512VNNI | CPUID_7_0_ECX_AVX512BITALG | + CPUID_7_0_ECX_AVX512_VPOPCNTDQ | CPUID_7_0_ECX_LA57, +diff --git a/tests/acceptance/cpu_queries.py b/tests/acceptance/cpu_queries.py +new file mode 100644 +index 0000000..e71edec +--- /dev/null ++++ b/tests/acceptance/cpu_queries.py +@@ -0,0 +1,33 @@ ++# Sanity check of query-cpu-* results ++# ++# Copyright (c) 2019 Red Hat, Inc. ++# ++# Author: ++# Eduardo Habkost ++# ++# This work is licensed under the terms of the GNU GPL, version 2 or ++# later. See the COPYING file in the top-level directory. ++ ++import logging ++ ++from avocado_qemu import Test ++ ++class QueryCPUModelExpansion(Test): ++ """ ++ Run query-cpu-model-expansion for each CPU model, and validate results ++ """ ++ ++ def test(self): ++ self.vm.set_machine('none') ++ self.vm.add_args('-S') ++ self.vm.launch() ++ ++ cpus = self.vm.command('query-cpu-definitions') ++ for c in cpus: ++ print(repr(c)) ++ self.assertNotIn('', c['unavailable-features'], c['name']) ++ ++ for c in cpus: ++ model = {'name': c['name']} ++ e = self.vm.command('query-cpu-model-expansion', model=model, type='full') ++ self.assertEquals(e['model']['name'], c['name']) +-- +1.8.3.1 + diff --git a/SOURCES/kvm-i386-Make-arch_capabilities-migratable.patch b/SOURCES/kvm-i386-Make-arch_capabilities-migratable.patch index 755941f..09b869d 100644 --- a/SOURCES/kvm-i386-Make-arch_capabilities-migratable.patch +++ b/SOURCES/kvm-i386-Make-arch_capabilities-migratable.patch @@ -1,19 +1,28 @@ -From c521a837f3490e8f61d129ab1940f8fd76a87b8a Mon Sep 17 00:00:00 2001 +From 31194033bdc6f379edebe9fa818536d478a629f0 Mon Sep 17 00:00:00 2001 From: "plai@redhat.com" -Date: Tue, 20 Aug 2019 00:24:39 +0100 -Subject: [PATCH 8/9] i386: Make arch_capabilities migratable +Date: Thu, 16 May 2019 20:44:02 +0100 +Subject: [PATCH 1/8] i386: Make arch_capabilities migratable RH-Author: plai@redhat.com -Message-id: <1566260680-20995-9-git-send-email-plai@redhat.com> -Patchwork-id: 90067 -O-Subject: [RHEL8.0 qemu-kvm PATCH v3 8/9] i386: Make arch_capabilities migratable -Bugzilla: 1718235 +Message-id: <1558039442-5246-1-git-send-email-plai@redhat.com> +Patchwork-id: 87976 +O-Subject: [RHEL8.1 qemu-kvm PATCH v2] i386: Make arch_capabilities migratable +Bugzilla: 1709970 RH-Acked-by: Eduardo Habkost -RH-Acked-by: John Snow +RH-Acked-by: Bandan Das RH-Acked-by: Igor Mammedov From: Eduardo Habkost +BZ https://bugzilla.redhat.com/show_bug.cgi?id=1709970 +Brew: http://brewweb.devel.redhat.com/brew/taskinfo?taskID=21668672 +Branch: rhel-8.1.0 + +In v1, we included CascadeLake Server cpu model. That has been removed +in favor a separate submission. + +--- + Now that kvm_arch_get_supported_cpuid() will only return arch_capabilities if QEMU is able to initialize the MSR properly, we know that the feature is safely migratable. @@ -29,7 +38,7 @@ Signed-off-by: Danilo C. L. de Paula 1 file changed, 1 deletion(-) diff --git a/target/i386/cpu.c b/target/i386/cpu.c -index fbcf124..365c92c 100644 +index e9025cd..4411012 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -1053,7 +1053,6 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { diff --git a/SOURCES/kvm-i386-Save-EFER-for-32-bit-targets.patch b/SOURCES/kvm-i386-Save-EFER-for-32-bit-targets.patch new file mode 100644 index 0000000..fe1a7b3 --- /dev/null +++ b/SOURCES/kvm-i386-Save-EFER-for-32-bit-targets.patch @@ -0,0 +1,80 @@ +From 1e8e3c4fe380a2a0ed88f7a92f5bcb8600ab1258 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Mon, 22 Jul 2019 18:22:03 +0100 +Subject: [PATCH 22/39] i386: Save EFER for 32-bit targets + +RH-Author: Paolo Bonzini +Message-id: <20190722182220.19374-2-pbonzini@redhat.com> +Patchwork-id: 89619 +O-Subject: [RHEL-8.1.0 PATCH qemu-kvm v3 01/18] i386: Save EFER for 32-bit targets +Bugzilla: 1689269 +RH-Acked-by: Peter Xu +RH-Acked-by: Laurent Vivier +RH-Acked-by: Dr. David Alan Gilbert + +From: Pavel Dovgalyuk + +i386 (32 bit) emulation uses EFER in wrmsr and in MMU fault +processing. +But it does not included in VMState, because "efer" field is disabled with + +This patch adds a section for 32-bit targets which saves EFER when +it's value is non-zero. + +Signed-off-by: Pavel Dovgalyuk +Message-Id: <155913371654.8429.1659082639780315242.stgit@pasha-Precision-3630-Tower> +Reviewed-by: Peter Xu +[ehabkost: indentation fix] +Signed-off-by: Eduardo Habkost +(cherry picked from commit 89a44a103315267122119b4311218d00d2561ebe) + +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/machine.c | 24 ++++++++++++++++++++++++ + 1 file changed, 24 insertions(+) + +diff --git a/target/i386/machine.c b/target/i386/machine.c +index 2a85c91..561d4a5 100644 +--- a/target/i386/machine.c ++++ b/target/i386/machine.c +@@ -932,6 +932,27 @@ static const VMStateDescription vmstate_msr_virt_ssbd = { + } + }; + ++#ifndef TARGET_X86_64 ++static bool intel_efer32_needed(void *opaque) ++{ ++ X86CPU *cpu = opaque; ++ CPUX86State *env = &cpu->env; ++ ++ return env->efer != 0; ++} ++ ++static const VMStateDescription vmstate_efer32 = { ++ .name = "cpu/efer32", ++ .version_id = 1, ++ .minimum_version_id = 1, ++ .needed = intel_efer32_needed, ++ .fields = (VMStateField[]) { ++ VMSTATE_UINT64(env.efer, X86CPU), ++ VMSTATE_END_OF_LIST() ++ } ++}; ++#endif ++ + VMStateDescription vmstate_x86_cpu = { + .name = "cpu", + .version_id = 12, +@@ -1056,6 +1077,9 @@ VMStateDescription vmstate_x86_cpu = { + &vmstate_msr_intel_pt, + &vmstate_xsave, + &vmstate_msr_virt_ssbd, ++#ifndef TARGET_X86_64 ++ &vmstate_efer32, ++#endif + NULL + } + }; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-i386-Update-stepping-of-Cascadelake-Server.patch b/SOURCES/kvm-i386-Update-stepping-of-Cascadelake-Server.patch new file mode 100644 index 0000000..328d271 --- /dev/null +++ b/SOURCES/kvm-i386-Update-stepping-of-Cascadelake-Server.patch @@ -0,0 +1,66 @@ +From 839e9376bc82933ccacb26b660f1d3adf62aaf05 Mon Sep 17 00:00:00 2001 +From: "plai@redhat.com" +Date: Mon, 1 Jul 2019 16:17:31 +0100 +Subject: [PATCH 02/39] i386: Update stepping of Cascadelake-Server + +RH-Author: plai@redhat.com +Message-id: <1561997854-9646-3-git-send-email-plai@redhat.com> +Patchwork-id: 89329 +O-Subject: [RHEL8.1 qemu-kvm PATCH v6 2/5] i386: Update stepping of Cascadelake-Server +Bugzilla: 1629906 +RH-Acked-by: Eduardo Habkost +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Bandan Das + +From: Tao Xu + +Update the stepping from 5 to 6, in order that +the Cascadelake-Server CPU model can support AVX512VNNI +and MSR based features exposed by ARCH_CAPABILITIES. + +Signed-off-by: Tao Xu +Message-Id: <20181227024304.12182-2-tao3.xu@intel.com> +Signed-off-by: Eduardo Habkost +(cherry picked from commit b0a1980384fc265d91de7e09aa5fe531a69e6288) +Signed-off-by: Paul Lai + +Resolved Conflicts: + hw/i386/pc.c changes to include/hw/i386/pc.h + +Signed-off-by: Danilo C. L. de Paula +--- + include/hw/i386/pc.h | 4 ++++ + target/i386/cpu.c | 2 +- + 2 files changed, 5 insertions(+), 1 deletion(-) + +diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h +index 244d7b5..88ffd40 100644 +--- a/include/hw/i386/pc.h ++++ b/include/hw/i386/pc.h +@@ -318,6 +318,10 @@ bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *); + .driver = "Skylake-Server" "-" TYPE_X86_CPU,\ + .property = "clflushopt",\ + .value = "off",\ ++ },{\ ++ .driver = "Cascadelake-Server" "-" TYPE_X86_CPU,\ ++ .property = "stepping",\ ++ .value = "5",\ + }, + + #define PC_COMPAT_2_10 \ +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index 9ba5288..c4b31eb 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -2488,7 +2488,7 @@ static X86CPUDefinition builtin_x86_defs[] = { + .vendor = CPUID_VENDOR_INTEL, + .family = 6, + .model = 85, +- .stepping = 5, ++ .stepping = 6, + .features[FEAT_1_EDX] = + CPUID_VME | CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | + CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA | +-- +1.8.3.1 + diff --git a/SOURCES/kvm-i386-kvm-Disable-arch_capabilities-if-MSR-can-t-be-s.patch b/SOURCES/kvm-i386-kvm-Disable-arch_capabilities-if-MSR-can-t-be-s.patch index 1273172..b096d40 100644 --- a/SOURCES/kvm-i386-kvm-Disable-arch_capabilities-if-MSR-can-t-be-s.patch +++ b/SOURCES/kvm-i386-kvm-Disable-arch_capabilities-if-MSR-can-t-be-s.patch @@ -1,18 +1,17 @@ -From 2a73dad9463a9969e14f2496bad362547c5976eb Mon Sep 17 00:00:00 2001 -From: "plai@redhat.com" -Date: Tue, 20 Aug 2019 00:24:38 +0100 -Subject: [PATCH 7/9] i386: kvm: Disable arch_capabilities if MSR can't be set +From c48019a17552791a63cc143321944ed916de0672 Mon Sep 17 00:00:00 2001 +From: Eduardo Habkost +Date: Thu, 9 May 2019 22:43:18 +0100 +Subject: [PATCH 2/2] i386: kvm: Disable arch_capabilities if MSR can't be set -RH-Author: plai@redhat.com -Message-id: <1566260680-20995-8-git-send-email-plai@redhat.com> -Patchwork-id: 90068 -O-Subject: [RHEL8.0 qemu-kvm PATCH v3 7/9] i386: kvm: Disable arch_capabilities if MSR can't be set -Bugzilla: 1718235 -RH-Acked-by: Eduardo Habkost -RH-Acked-by: John Snow +RH-Author: Eduardo Habkost +Message-id: <20190509224318.23376-3-ehabkost@redhat.com> +Patchwork-id: 87252 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 2/2] i386: kvm: Disable arch_capabilities if MSR can't be set +Bugzilla: 1707706 +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Paolo Bonzini RH-Acked-by: Igor Mammedov - -From: Eduardo Habkost +RH-Acked-by: Bandan Das KVM has two bugs in the handling of MSR_IA32_ARCH_CAPABILITIES: @@ -39,14 +38,14 @@ Signed-off-by: Eduardo Habkost Message-Id: <20190125220606.4864-2-ehabkost@redhat.com> Signed-off-by: Eduardo Habkost (cherry picked from commit 485b1d256bcb0874bcde0223727c159b6837e6f8) -Signed-off-by: Paul Lai +Signed-off-by: Eduardo Habkost Signed-off-by: Danilo C. L. de Paula --- target/i386/kvm.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/target/i386/kvm.c b/target/i386/kvm.c -index 6f661b2..e783427 100644 +index e3e8c78..8a4d31d 100644 --- a/target/i386/kvm.c +++ b/target/i386/kvm.c @@ -374,6 +374,15 @@ uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function, diff --git a/SOURCES/kvm-i386-kvm-Do-not-sync-nested-state-during-runtime.patch b/SOURCES/kvm-i386-kvm-Do-not-sync-nested-state-during-runtime.patch new file mode 100644 index 0000000..f0d83c7 --- /dev/null +++ b/SOURCES/kvm-i386-kvm-Do-not-sync-nested-state-during-runtime.patch @@ -0,0 +1,55 @@ +From aaf60450da6b0bc4723028aeab9ced75ee03111b Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Mon, 22 Jul 2019 18:22:20 +0100 +Subject: [PATCH 39/39] i386/kvm: Do not sync nested state during runtime + +RH-Author: Paolo Bonzini +Message-id: <20190722182220.19374-19-pbonzini@redhat.com> +Patchwork-id: 89635 +O-Subject: [RHEL-8.1.0 PATCH qemu-kvm v3 18/18] i386/kvm: Do not sync nested state during runtime +Bugzilla: 1689269 +RH-Acked-by: Peter Xu +RH-Acked-by: Laurent Vivier +RH-Acked-by: Dr. David Alan Gilbert + +From: Jan Kiszka + +Writing the nested state e.g. after a vmport access can invalidate +important parts of the kernel-internal state, and it is not needed as +well. So leave this out from KVM_PUT_RUNTIME_STATE. + +Suggested-by: Paolo Bonzini +Signed-off-by: Jan Kiszka +Message-Id: +Signed-off-by: Paolo Bonzini +(cherry picked from commit 20b25d239ab7a94bb8bff3d0f13a9527ee75cf10) +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/kvm.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/target/i386/kvm.c b/target/i386/kvm.c +index 8648f1f..da5f07e 100644 +--- a/target/i386/kvm.c ++++ b/target/i386/kvm.c +@@ -3014,12 +3014,12 @@ int kvm_arch_put_registers(CPUState *cpu, int level) + + assert(cpu_is_stopped(cpu) || qemu_cpu_is_self(cpu)); + +- ret = kvm_put_nested_state(x86_cpu); +- if (ret < 0) { +- return ret; +- } +- + if (level >= KVM_PUT_RESET_STATE) { ++ ret = kvm_put_nested_state(x86_cpu); ++ if (ret < 0) { ++ return ret; ++ } ++ + ret = kvm_put_msr_feature_control(x86_cpu); + if (ret < 0) { + return ret; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-i386-kvm-ignore-masked-irqs-when-update-msi-routes.patch b/SOURCES/kvm-i386-kvm-ignore-masked-irqs-when-update-msi-routes.patch new file mode 100644 index 0000000..76f9433 --- /dev/null +++ b/SOURCES/kvm-i386-kvm-ignore-masked-irqs-when-update-msi-routes.patch @@ -0,0 +1,92 @@ +From b33299faac2ed3e7757bf1a0c733a9abb2c6ed34 Mon Sep 17 00:00:00 2001 +From: Peter Xu +Date: Tue, 2 Apr 2019 07:25:31 +0100 +Subject: [PATCH 7/7] i386/kvm: ignore masked irqs when update msi routes +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Peter Xu +Message-id: <20190402072531.23771-5-peterx@redhat.com> +Patchwork-id: 85301 +O-Subject: [RHEL-8.1 qemu-kvm PATCH 4/4] i386/kvm: ignore masked irqs when update msi routes +Bugzilla: 1662272 +RH-Acked-by: Wei Huang +RH-Acked-by: Xiao Wang +RH-Acked-by: Michael S. Tsirkin + +When we are with intel-iommu device and with IR on, KVM will register +an IEC notifier to detect interrupt updates from the guest and we'll +kick off kvm_update_msi_routes_all() when it happens to make sure +kernel IRQ cache is matching the latest. + +Though, kvm_update_msi_routes_all() is buggy in that it ignored the +mask bit of either MSI/MSIX messages and it tries to translate the +message even if the corresponding message was already masked by the +guest driver (hence the MSI/MSIX message will be invalid). + +Without this patch, we can receive an error message when we reboot a +guest with both an assigned vfio-pci device and intel-iommu enabled: + + qemu-system-x86_64: vtd_interrupt_remap_msi: MSI address low 32 bit invalid: 0x0 + +The error does not affect functionality of the guest since when we +failed to translate we'll just silently continue (which makes sense +since crashing the VM for this seems even worse), but still it's +better to fix it up. + +Signed-off-by: Peter Xu +Reviewed-by: Michael S. Tsirkin +Message-Id: <20190116030815.27273-5-peterx@redhat.com> +[PMD: this patch was first (incorrectly) introduced as a56de056c91f8] +Signed-off-by: Philippe Mathieu-Daudé +Message-Id: <20190212140621.17009-4-philmd@redhat.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +Reviewed-by: Peter Xu +(cherry picked from commit 558e8c6139a5f517433b6f1779b2df8a0b4ff610) +Signed-off-by: Peter Xu + +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/kvm.c | 14 +++++++++++--- + 1 file changed, 11 insertions(+), 3 deletions(-) + +diff --git a/target/i386/kvm.c b/target/i386/kvm.c +index 87e4771..702e3bf 100644 +--- a/target/i386/kvm.c ++++ b/target/i386/kvm.c +@@ -3590,7 +3590,7 @@ static QLIST_HEAD(, MSIRouteEntry) msi_route_list = \ + static void kvm_update_msi_routes_all(void *private, bool global, + uint32_t index, uint32_t mask) + { +- int cnt = 0; ++ int cnt = 0, vector; + MSIRouteEntry *entry; + MSIMessage msg; + PCIDevice *dev; +@@ -3598,11 +3598,19 @@ static void kvm_update_msi_routes_all(void *private, bool global, + /* TODO: explicit route update */ + QLIST_FOREACH(entry, &msi_route_list, list) { + cnt++; ++ vector = entry->vector; + dev = entry->dev; +- if (!msix_enabled(dev) && !msi_enabled(dev)) { ++ if (msix_enabled(dev) && !msix_is_masked(dev, vector)) { ++ msg = msix_get_message(dev, vector); ++ } else if (msi_enabled(dev) && !msi_is_masked(dev, vector)) { ++ msg = msi_get_message(dev, vector); ++ } else { ++ /* ++ * Either MSI/MSIX is disabled for the device, or the ++ * specific message was masked out. Skip this one. ++ */ + continue; + } +- msg = pci_get_msi_message(dev, entry->vector); + kvm_irqchip_update_msi_route(kvm_state, entry->virq, msg, dev); + } + kvm_irqchip_commit_routes(kvm_state); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-i386-remove-the-INTEL_PT-CPUID-bit-from-named-CPU-NEW.patch b/SOURCES/kvm-i386-remove-the-INTEL_PT-CPUID-bit-from-named-CPU-NEW.patch new file mode 100644 index 0000000..9e36c94 --- /dev/null +++ b/SOURCES/kvm-i386-remove-the-INTEL_PT-CPUID-bit-from-named-CPU-NEW.patch @@ -0,0 +1,52 @@ +From 6131491c7a5494c1c034973ae23fc842b1ee733e Mon Sep 17 00:00:00 2001 +From: "plai@redhat.com" +Date: Mon, 1 Jul 2019 16:17:33 +0100 +Subject: [PATCH 04/39] i386: remove the 'INTEL_PT' CPUID bit from named CPU + models + +RH-Author: plai@redhat.com +Message-id: <1561997854-9646-5-git-send-email-plai@redhat.com> +Patchwork-id: 89332 +O-Subject: [RHEL8.1 qemu-kvm PATCH v6 4/5] i386: remove the 'INTEL_PT' CPUID bit from named CPU models +Bugzilla: 1629906 +RH-Acked-by: Eduardo Habkost +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Bandan Das + +From: Paolo Bonzini + +Processor tracing is not yet implemented for KVM and it will be an +opt in feature requiring a special module parameter. +Disable it, because it is wrong to enable it by default and +it is impossible that no one has ever used it. + +Cc: qemu-stable@nongnu.org +Signed-off-by: Paolo Bonzini +(cherry picked from commit 4c257911dcc7c4189768e9651755c849ce9db4e8) +Signed-off-by: Paul Lai + +Resolved Conflicts: + target/i386/cpu.c + +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index 094f8a1..2538d82 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -2515,8 +2515,7 @@ static X86CPUDefinition builtin_x86_defs[] = { + CPUID_7_0_EBX_SMAP | CPUID_7_0_EBX_CLWB | + CPUID_7_0_EBX_AVX512F | CPUID_7_0_EBX_AVX512DQ | + CPUID_7_0_EBX_AVX512BW | CPUID_7_0_EBX_AVX512CD | +- CPUID_7_0_EBX_AVX512VL | CPUID_7_0_EBX_CLFLUSHOPT | +- CPUID_7_0_EBX_INTEL_PT, ++ CPUID_7_0_EBX_AVX512VL | CPUID_7_0_EBX_CLFLUSHOPT, + .features[FEAT_7_0_ECX] = + CPUID_7_0_ECX_PKU | CPUID_7_0_ECX_OSPKE | + CPUID_7_0_ECX_AVX512VNNI, +-- +1.8.3.1 + diff --git a/SOURCES/kvm-i386-remove-the-INTEL_PT-CPUID-bit-from-named-CPU-mo.patch b/SOURCES/kvm-i386-remove-the-INTEL_PT-CPUID-bit-from-named-CPU-mo.patch new file mode 100644 index 0000000..2d382b8 --- /dev/null +++ b/SOURCES/kvm-i386-remove-the-INTEL_PT-CPUID-bit-from-named-CPU-mo.patch @@ -0,0 +1,57 @@ +From cdca375a93add0cb9be100d7e8cdc39b59573666 Mon Sep 17 00:00:00 2001 +From: Eduardo Habkost +Date: Thu, 9 May 2019 23:21:07 +0100 +Subject: [PATCH 1/2] i386: remove the 'INTEL_PT' CPUID bit from named CPU + models + +RH-Author: Eduardo Habkost +Message-id: <20190509232108.25675-2-ehabkost@redhat.com> +Patchwork-id: 87253 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 1/2] i386: remove the 'INTEL_PT' CPUID bit from named CPU models +Bugzilla: 1561761 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Igor Mammedov +RH-Acked-by: Danilo de Paula + +From: Paolo Bonzini + +Processor tracing is not yet implemented for KVM and it will be an +opt in feature requiring a special module parameter. +Disable it, because it is wrong to enable it by default and +it is impossible that no one has ever used it. + +Cc: qemu-stable@nongnu.org +Signed-off-by: Paolo Bonzini +(cherry picked from commit 4c257911dcc7c4189768e9651755c849ce9db4e8) +Signed-off-by: Eduardo Habkost +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.c | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index 8e63db6..c56d7e7 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -2515,7 +2515,7 @@ static X86CPUDefinition builtin_x86_defs[] = { + CPUID_7_0_EBX_HLE | CPUID_7_0_EBX_AVX2 | CPUID_7_0_EBX_SMEP | + CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ERMS | CPUID_7_0_EBX_INVPCID | + CPUID_7_0_EBX_RTM | CPUID_7_0_EBX_RDSEED | CPUID_7_0_EBX_ADX | +- CPUID_7_0_EBX_SMAP | CPUID_7_0_EBX_MPX | CPUID_7_0_EBX_INTEL_PT, ++ CPUID_7_0_EBX_SMAP | CPUID_7_0_EBX_MPX, + .features[FEAT_7_0_ECX] = + CPUID_7_0_ECX_VBMI | CPUID_7_0_ECX_UMIP | CPUID_7_0_ECX_PKU | + CPUID_7_0_ECX_OSPKE | CPUID_7_0_ECX_VBMI2 | CPUID_7_0_ECX_GFNI | +@@ -2573,8 +2573,7 @@ static X86CPUDefinition builtin_x86_defs[] = { + CPUID_7_0_EBX_SMAP | CPUID_7_0_EBX_MPX | CPUID_7_0_EBX_CLWB | + CPUID_7_0_EBX_AVX512F | CPUID_7_0_EBX_AVX512DQ | + CPUID_7_0_EBX_AVX512BW | CPUID_7_0_EBX_AVX512CD | +- CPUID_7_0_EBX_AVX512VL | CPUID_7_0_EBX_CLFLUSHOPT | +- CPUID_7_0_EBX_INTEL_PT, ++ CPUID_7_0_EBX_AVX512VL | CPUID_7_0_EBX_CLFLUSHOPT, + .features[FEAT_7_0_ECX] = + CPUID_7_0_ECX_VBMI | CPUID_7_0_ECX_UMIP | CPUID_7_0_ECX_PKU | + CPUID_7_0_ECX_OSPKE | CPUID_7_0_ECX_VBMI2 | CPUID_7_0_ECX_GFNI | +-- +1.8.3.1 + diff --git a/SOURCES/kvm-i386-remove-the-new-CPUID-PCONFIG-from-Icelake-Serve.patch b/SOURCES/kvm-i386-remove-the-new-CPUID-PCONFIG-from-Icelake-Serve.patch new file mode 100644 index 0000000..da26c42 --- /dev/null +++ b/SOURCES/kvm-i386-remove-the-new-CPUID-PCONFIG-from-Icelake-Serve.patch @@ -0,0 +1,49 @@ +From 925184b9c7bd2946cff1698b1cf4a448435588e5 Mon Sep 17 00:00:00 2001 +From: "plai@redhat.com" +Date: Wed, 3 Apr 2019 15:54:33 +0100 +Subject: [PATCH 09/10] i386: remove the new CPUID 'PCONFIG' from + Icelake-Server CPU model + +RH-Author: plai@redhat.com +Message-id: <1554306874-28796-10-git-send-email-plai@redhat.com> +Patchwork-id: 85387 +O-Subject: [RHEL8.1 qemu-kvm PATCH resend 09/10] i386: remove the new CPUID 'PCONFIG' from Icelake-Server CPU model +Bugzilla: 1561761 +RH-Acked-by: Eduardo Habkost +RH-Acked-by: Igor Mammedov +RH-Acked-by: Michael S. Tsirkin + +From: Robert Hoo + +PCONFIG is not available to guests; it must be specifically enabled +using the PCONFIG_ENABLE execution control. Disable it, because +no one can ever use it. + +Signed-off-by: Robert Hoo +Message-Id: <1545227081-213696-2-git-send-email-robert.hu@linux.intel.com> +Cc: qemu-stable@nongnu.org +Signed-off-by: Paolo Bonzini +(cherry picked from commit 76e5a4d58357b9d077afccf7f7c82e17f733b722) +Signed-off-by: Paul Lai +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index 8750f64..ad369be 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -2582,8 +2582,7 @@ static X86CPUDefinition builtin_x86_defs[] = { + CPUID_7_0_ECX_AVX512VNNI | CPUID_7_0_ECX_AVX512BITALG | + CPUID_7_0_ECX_AVX512_VPOPCNTDQ | CPUID_7_0_ECX_LA57, + .features[FEAT_7_0_EDX] = +- CPUID_7_0_EDX_PCONFIG | CPUID_7_0_EDX_SPEC_CTRL | +- CPUID_7_0_EDX_SPEC_CTRL_SSBD, ++ CPUID_7_0_EDX_SPEC_CTRL | CPUID_7_0_EDX_SPEC_CTRL_SSBD, + /* Missing: XSAVES (not supported by some Linux versions, + * including v4.1 to v4.12). + * KVM doesn't yet expose any XSAVES state save component, +-- +1.8.3.1 + diff --git a/SOURCES/kvm-i386-unavailable-features-QOM-property.patch b/SOURCES/kvm-i386-unavailable-features-QOM-property.patch new file mode 100644 index 0000000..6f16eb8 --- /dev/null +++ b/SOURCES/kvm-i386-unavailable-features-QOM-property.patch @@ -0,0 +1,71 @@ +From 2adf144c57ddef54f5c42cdbc539d0249ce1b0ba Mon Sep 17 00:00:00 2001 +From: Eduardo Habkost +Date: Thu, 29 Aug 2019 20:55:32 +0100 +Subject: [PATCH 05/10] i386: "unavailable-features" QOM property + +RH-Author: Eduardo Habkost +Message-id: <20190829205532.8302-3-ehabkost@redhat.com> +Patchwork-id: 90201 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 2/2] i386: "unavailable-features" QOM property +Bugzilla: 1747185 +RH-Acked-by: Thomas Huth +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Michael S. Tsirkin + +Add a "unavailable-features" QOM property to X86CPU objects that +have the same semantics of "unavailable-features" on +query-cpu-definitions. The new property has the same goal of +"filtered-features", but is generic enough to let any kind of CPU +feature to be listed there without relying on low level details +like CPUID leaves or MSR numbers. + +Message-Id: <20190422234742.15780-3-ehabkost@redhat.com> +Signed-off-by: Eduardo Habkost +(cherry picked from commit 506174bf8219dc6d56d2b1f7e66e8cf39157466f) +Signed-off-by: Eduardo Habkost +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.c | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index 934f11b..c8f50a7 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -3580,6 +3580,17 @@ static void x86_cpu_list_feature_names(FeatureWordArray features, + } + } + ++static void x86_cpu_get_unavailable_features(Object *obj, Visitor *v, ++ const char *name, void *opaque, ++ Error **errp) ++{ ++ X86CPU *xc = X86_CPU(obj); ++ strList *result = NULL; ++ ++ x86_cpu_list_feature_names(xc->filtered_features, &result); ++ visit_type_strList(v, "unavailable-features", &result, errp); ++} ++ + /* Check for missing features that may prevent the CPU class from + * running using the current machine and accelerator. + */ +@@ -5479,6 +5490,15 @@ static void x86_cpu_initfn(Object *obj) + object_property_add(obj, "filtered-features", "X86CPUFeatureWordInfo", + x86_cpu_get_feature_words, + NULL, NULL, (void *)cpu->filtered_features, NULL); ++ /* ++ * The "unavailable-features" property has the same semantics as ++ * CpuDefinitionInfo.unavailable-features on the "query-cpu-definitions" ++ * QMP command: they list the features that would have prevented the ++ * CPU from running if the "enforce" flag was set. ++ */ ++ object_property_add(obj, "unavailable-features", "strList", ++ x86_cpu_get_unavailable_features, ++ NULL, NULL, NULL, &error_abort); + + object_property_add(obj, "crash-information", "GuestPanicInformation", + x86_cpu_get_crash_info_qom, NULL, NULL, NULL, NULL); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-i386-x86_cpu_list_feature_names-function.patch b/SOURCES/kvm-i386-x86_cpu_list_feature_names-function.patch new file mode 100644 index 0000000..e1e9895 --- /dev/null +++ b/SOURCES/kvm-i386-x86_cpu_list_feature_names-function.patch @@ -0,0 +1,90 @@ +From 61aa52146679fb00f976bc1eb7884f1ddcf7342c Mon Sep 17 00:00:00 2001 +From: Eduardo Habkost +Date: Thu, 29 Aug 2019 20:55:31 +0100 +Subject: [PATCH 04/10] i386: x86_cpu_list_feature_names() function + +RH-Author: Eduardo Habkost +Message-id: <20190829205532.8302-2-ehabkost@redhat.com> +Patchwork-id: 90200 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 1/2] i386: x86_cpu_list_feature_names() function +Bugzilla: 1747185 +RH-Acked-by: Thomas Huth +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Michael S. Tsirkin + +Extract feature name listing code from +x86_cpu_class_check_missing_features(). It will be reused to +return information about CPU filtered features at runtime. + +Message-Id: <20190422234742.15780-2-ehabkost@redhat.com> +Signed-off-by: Eduardo Habkost +(cherry picked from commit 5a853fc57a0860da4a55d1448a77845f97e7a9be) +Signed-off-by: Eduardo Habkost +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.c | 35 ++++++++++++++++++++++------------- + 1 file changed, 22 insertions(+), 13 deletions(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index f71b044..934f11b 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -3559,6 +3559,27 @@ static void x86_cpu_parse_featurestr(const char *typename, char *features, + static void x86_cpu_expand_features(X86CPU *cpu, Error **errp); + static int x86_cpu_filter_features(X86CPU *cpu); + ++/* Build a list with the name of all features on a feature word array */ ++static void x86_cpu_list_feature_names(FeatureWordArray features, ++ strList **feat_names) ++{ ++ FeatureWord w; ++ strList **next = feat_names; ++ ++ for (w = 0; w < FEATURE_WORDS; w++) { ++ uint32_t filtered = features[w]; ++ int i; ++ for (i = 0; i < 32; i++) { ++ if (filtered & (1UL << i)) { ++ strList *new = g_new0(strList, 1); ++ new->value = g_strdup(x86_cpu_feature_name(w, i)); ++ *next = new; ++ next = &new->next; ++ } ++ } ++ } ++} ++ + /* Check for missing features that may prevent the CPU class from + * running using the current machine and accelerator. + */ +@@ -3566,7 +3587,6 @@ static void x86_cpu_class_check_missing_features(X86CPUClass *xcc, + strList **missing_feats) + { + X86CPU *xc; +- FeatureWord w; + Error *err = NULL; + strList **next = missing_feats; + +@@ -3593,18 +3613,7 @@ static void x86_cpu_class_check_missing_features(X86CPUClass *xcc, + + x86_cpu_filter_features(xc); + +- for (w = 0; w < FEATURE_WORDS; w++) { +- uint32_t filtered = xc->filtered_features[w]; +- int i; +- for (i = 0; i < 32; i++) { +- if (filtered & (1UL << i)) { +- strList *new = g_new0(strList, 1); +- new->value = g_strdup(x86_cpu_feature_name(w, i)); +- *next = new; +- next = &new->next; +- } +- } +- } ++ x86_cpu_list_feature_names(xc->filtered_features, next); + + object_unref(OBJECT(xc)); + } +-- +1.8.3.1 + diff --git a/SOURCES/kvm-intel_iommu-fix-operator-in-vtd_switch_address_space.patch b/SOURCES/kvm-intel_iommu-fix-operator-in-vtd_switch_address_space.patch new file mode 100644 index 0000000..1dbaa61 --- /dev/null +++ b/SOURCES/kvm-intel_iommu-fix-operator-in-vtd_switch_address_space.patch @@ -0,0 +1,51 @@ +From 94edd1b203f3a88065ce05d9e027b24a3e8eed2f Mon Sep 17 00:00:00 2001 +From: Peter Xu +Date: Tue, 2 Apr 2019 07:25:28 +0100 +Subject: [PATCH 4/7] intel_iommu: fix operator in vtd_switch_address_space + +RH-Author: Peter Xu +Message-id: <20190402072531.23771-2-peterx@redhat.com> +Patchwork-id: 85298 +O-Subject: [RHEL-8.1 qemu-kvm PATCH 1/4] intel_iommu: fix operator in vtd_switch_address_space +Bugzilla: 1662272 +RH-Acked-by: Wei Huang +RH-Acked-by: Xiao Wang +RH-Acked-by: Michael S. Tsirkin + +When calculating use_iommu, we wanted to first detect whether DMAR is +enabled, then check whether PT is enabled if DMAR is enabled. However +in the current code we used "&" rather than "&&" so the ordering +requirement is lost (instead it'll be an "AND" operation). This could +introduce errors dumped in QEMU console when rebooting a guest with +both assigned device and vIOMMU, like: + + qemu-system-x86_64: vtd_dev_to_context_entry: invalid root entry: + rsvd=0xf000ff53f000e2c3, val=0xf000ff53f000ff53 (reserved nonzero) + +Acked-by: Jason Wang +Signed-off-by: Peter Xu +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +(cherry picked from commit 2a078b1080917dc6143783e1dd645e188d11dc8f) +Signed-off-by: Peter Xu +Signed-off-by: Danilo C. L. de Paula +--- + hw/i386/intel_iommu.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c +index 12af410..7170266 100644 +--- a/hw/i386/intel_iommu.c ++++ b/hw/i386/intel_iommu.c +@@ -1145,7 +1145,7 @@ static bool vtd_switch_address_space(VTDAddressSpace *as) + + assert(as); + +- use_iommu = as->iommu_state->dmar_enabled & !vtd_dev_pt_enabled(as); ++ use_iommu = as->iommu_state->dmar_enabled && !vtd_dev_pt_enabled(as); + + trace_vtd_switch_address_space(pci_bus_num(as->bus), + VTD_PCI_SLOT(as->devfn), +-- +1.8.3.1 + diff --git a/SOURCES/kvm-intel_iommu-reset-intr_enabled-when-system-reset.patch b/SOURCES/kvm-intel_iommu-reset-intr_enabled-when-system-reset.patch new file mode 100644 index 0000000..8339c39 --- /dev/null +++ b/SOURCES/kvm-intel_iommu-reset-intr_enabled-when-system-reset.patch @@ -0,0 +1,48 @@ +From b7229c79beaf790518048ff85b329eaa9cd6985f Mon Sep 17 00:00:00 2001 +From: Peter Xu +Date: Tue, 2 Apr 2019 07:25:29 +0100 +Subject: [PATCH 5/7] intel_iommu: reset intr_enabled when system reset +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Peter Xu +Message-id: <20190402072531.23771-3-peterx@redhat.com> +Patchwork-id: 85299 +O-Subject: [RHEL-8.1 qemu-kvm PATCH 2/4] intel_iommu: reset intr_enabled when system reset +Bugzilla: 1662272 +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Wei Huang +RH-Acked-by: Xiao Wang +RH-Acked-by: Michael S. Tsirkin + +This is found when I was debugging another problem. Until now no bug +is reported with this but we'd better reset the IR status correctly +after a system reset. + +Acked-by: Jason Wang +Signed-off-by: Peter Xu +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +(cherry picked from commit d7bb469afa015e28a443faf1600a5a28b5fa483a) +Signed-off-by: Peter Xu +Signed-off-by: Danilo C. L. de Paula +--- + hw/i386/intel_iommu.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c +index 7170266..e827c5a 100644 +--- a/hw/i386/intel_iommu.c ++++ b/hw/i386/intel_iommu.c +@@ -3133,6 +3133,7 @@ static void vtd_init(IntelIOMMUState *s) + s->root = 0; + s->root_extended = false; + s->dmar_enabled = false; ++ s->intr_enabled = false; + s->iq_head = 0; + s->iq_tail = 0; + s->iq = 0; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-iotests-153-Fix-dead-code.patch b/SOURCES/kvm-iotests-153-Fix-dead-code.patch new file mode 100644 index 0000000..c16cffe --- /dev/null +++ b/SOURCES/kvm-iotests-153-Fix-dead-code.patch @@ -0,0 +1,90 @@ +From 471ed976b9bd7ed28c1cd2bf514e69098495f4ed Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Wed, 3 Apr 2019 17:13:08 +0100 +Subject: [PATCH 01/11] iotests: 153: Fix dead code + +RH-Author: Max Reitz +Message-id: <20190403171315.20841-2-mreitz@redhat.com> +Patchwork-id: 85399 +O-Subject: [RHEL-8.1 qemu-kvm PATCH 1/8] iotests: 153: Fix dead code +Bugzilla: 1694148 +RH-Acked-by: John Snow +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Stefano Garzarella + +From: Fam Zheng + +This step was left behind my mistake. As suggested by the echoed text, +the intention was to test two devices with the same image, with +different options. The behavior should be the same as two QEMU +processes. Complete it. + +Signed-off-by: Fam Zheng +Signed-off-by: Kevin Wolf +(cherry picked from commit 0e1a582750269d3dde0481ca034b08a5784e430c) +Signed-off-by: Max Reitz +Signed-off-by: Danilo C. L. de Paula +--- + tests/qemu-iotests/153 | 2 ++ + tests/qemu-iotests/153.out | 25 +++++++++++++++++++++++++ + 2 files changed, 27 insertions(+) + +diff --git a/tests/qemu-iotests/153 b/tests/qemu-iotests/153 +index 673813c..0daeb1b 100755 +--- a/tests/qemu-iotests/153 ++++ b/tests/qemu-iotests/153 +@@ -162,6 +162,7 @@ for opts1 in "" "read-only=on" "read-only=on,force-share=on"; do + _cleanup_qemu + done + ++test_opts="read-only=off read-only=on read-only=on,force-share=on" + for opt1 in $test_opts; do + for opt2 in $test_opts; do + echo +@@ -170,6 +171,7 @@ for opt1 in $test_opts; do + done + done + ++echo + echo "== Creating ${TEST_IMG}.[abc] ==" | _filter_testdir + ( + $QEMU_IMG create -f qcow2 "${TEST_IMG}.a" -b "${TEST_IMG}" +diff --git a/tests/qemu-iotests/153.out b/tests/qemu-iotests/153.out +index 3492ba7..93eaf10 100644 +--- a/tests/qemu-iotests/153.out ++++ b/tests/qemu-iotests/153.out +@@ -369,6 +369,31 @@ _qemu_img_wrapper bench -U -w -c 1 TEST_DIR/t.qcow2 + qemu-img: Could not open 'TEST_DIR/t.qcow2': force-share=on can only be used with read-only images + + Round done ++ ++== Two devices with the same image (read-only=off - read-only=off) == ++QEMU_PROG: -drive if=none,file=TEST_DIR/t.qcow2,read-only=off: Failed to get "write" lock ++Is another process using the image? ++ ++== Two devices with the same image (read-only=off - read-only=on) == ++QEMU_PROG: -drive if=none,file=TEST_DIR/t.qcow2,read-only=on: Failed to get shared "write" lock ++Is another process using the image? ++ ++== Two devices with the same image (read-only=off - read-only=on,force-share=on) == ++ ++== Two devices with the same image (read-only=on - read-only=off) == ++QEMU_PROG: -drive if=none,file=TEST_DIR/t.qcow2,read-only=off: Failed to get "write" lock ++Is another process using the image? ++ ++== Two devices with the same image (read-only=on - read-only=on) == ++ ++== Two devices with the same image (read-only=on - read-only=on,force-share=on) == ++ ++== Two devices with the same image (read-only=on,force-share=on - read-only=off) == ++ ++== Two devices with the same image (read-only=on,force-share=on - read-only=on) == ++ ++== Two devices with the same image (read-only=on,force-share=on - read-only=on,force-share=on) == ++ + == Creating TEST_DIR/t.qcow2.[abc] == + Formatting 'TEST_DIR/t.IMGFMT.a', fmt=IMGFMT size=33554432 backing_file=TEST_DIR/t.IMGFMT + Formatting 'TEST_DIR/t.IMGFMT.b', fmt=IMGFMT size=33554432 backing_file=TEST_DIR/t.IMGFMT +-- +1.8.3.1 + diff --git a/SOURCES/kvm-iotests-Filter-175-s-allocation-information.patch b/SOURCES/kvm-iotests-Filter-175-s-allocation-information.patch new file mode 100644 index 0000000..8c91799 --- /dev/null +++ b/SOURCES/kvm-iotests-Filter-175-s-allocation-information.patch @@ -0,0 +1,138 @@ +From b897ede11c7b47cc9db8334ca44dd960d3001309 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Fri, 30 Aug 2019 12:56:26 +0100 +Subject: [PATCH 08/10] iotests: Filter 175's allocation information + +RH-Author: Thomas Huth +Message-id: <20190830125628.23668-4-thuth@redhat.com> +Patchwork-id: 90211 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v2 3/5] iotests: Filter 175's allocation information +Bugzilla: 1738839 +RH-Acked-by: Cornelia Huck +RH-Acked-by: Max Reitz +RH-Acked-by: David Hildenbrand + +From: Max Reitz + +It is possible for an empty file to take up blocks on a filesystem, for +example: + +$ qemu-img create -f raw test.img 1G +Formatting 'test.img', fmt=raw size=1073741824 +$ mkfs.ext4 -I 128 -q test.img +$ mkdir test-mount +$ sudo mount -o loop test.img test-mount +$ sudo touch test-mount/test-file +$ stat -c 'blocks=%b' test-mount/test-file +blocks=8 + +These extra blocks (one cluster) are apparently used for metadata, +because they are always there, on top of blocks used for data: + +$ sudo dd if=/dev/zero of=test-mount/test-file bs=1M count=1 +1+0 records in +1+0 records out +1048576 bytes (1.0 MB, 1.0 MiB) copied, 0.00135339 s, 775 MB/s +$ stat -c 'blocks=%b' test-mount/test-file +blocks=2056 + +Make iotest 175 take this into account. + +Reported-by: Thomas Huth +Signed-off-by: Max Reitz +Reviewed-by: Eric Blake +Reviewed-by: Nir Soffer +Message-id: 20190516144319.12570-1-mreitz@redhat.com +Signed-off-by: Max Reitz +(cherry picked from commit a3bd71b5773a3664692601e6e181f108e1e4aa41) +Signed-off-by: Danilo C. L. de Paula +--- + tests/qemu-iotests/175 | 26 ++++++++++++++++++++++---- + tests/qemu-iotests/175.out | 8 ++++---- + 2 files changed, 26 insertions(+), 8 deletions(-) + +diff --git a/tests/qemu-iotests/175 b/tests/qemu-iotests/175 +index ca56e82..2e37c9a 100755 +--- a/tests/qemu-iotests/175 ++++ b/tests/qemu-iotests/175 +@@ -29,10 +29,25 @@ status=1 # failure is the default! + + _cleanup() + { +- _cleanup_test_img ++ _cleanup_test_img ++ rm -f "$TEST_DIR/empty" + } + trap "_cleanup; exit \$status" 0 1 2 3 15 + ++# Some file systems sometimes allocate extra blocks independently of ++# the file size. This function hides the resulting difference in the ++# stat -c '%b' output. ++# Parameter 1: Number of blocks an empty file occupies ++# Parameter 2: Image size in bytes ++_filter_blocks() ++{ ++ extra_blocks=$1 ++ img_size=$2 ++ ++ sed -e "s/blocks=$extra_blocks\\(\$\\|[^0-9]\\)/nothing allocated/" \ ++ -e "s/blocks=$((extra_blocks + img_size / 512))\\(\$\\|[^0-9]\\)/everything allocated/" ++} ++ + # get standard environment, filters and checks + . ./common.rc + . ./common.filter +@@ -41,18 +56,21 @@ _supported_fmt raw + _supported_proto file + _supported_os Linux + +-size=1m ++size=$((1 * 1024 * 1024)) ++ ++touch "$TEST_DIR/empty" ++extra_blocks=$(stat -c '%b' "$TEST_DIR/empty") + + echo + echo "== creating image with default preallocation ==" + _make_test_img $size | _filter_imgfmt +-stat -c "size=%s, blocks=%b" $TEST_IMG ++stat -c "size=%s, blocks=%b" $TEST_IMG | _filter_blocks $extra_blocks $size + + for mode in off full falloc; do + echo + echo "== creating image with preallocation $mode ==" + IMGOPTS=preallocation=$mode _make_test_img $size | _filter_imgfmt +- stat -c "size=%s, blocks=%b" $TEST_IMG ++ stat -c "size=%s, blocks=%b" $TEST_IMG | _filter_blocks $extra_blocks $size + done + + # success, all done +diff --git a/tests/qemu-iotests/175.out b/tests/qemu-iotests/175.out +index 76c02c6..6d9a5ed 100644 +--- a/tests/qemu-iotests/175.out ++++ b/tests/qemu-iotests/175.out +@@ -2,17 +2,17 @@ QA output created by 175 + + == creating image with default preallocation == + Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 +-size=1048576, blocks=0 ++size=1048576, nothing allocated + + == creating image with preallocation off == + Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 preallocation=off +-size=1048576, blocks=0 ++size=1048576, nothing allocated + + == creating image with preallocation full == + Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 preallocation=full +-size=1048576, blocks=2048 ++size=1048576, everything allocated + + == creating image with preallocation falloc == + Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 preallocation=falloc +-size=1048576, blocks=2048 ++size=1048576, everything allocated + *** done +-- +1.8.3.1 + diff --git a/SOURCES/kvm-iotests-Filter-SSH-paths.patch b/SOURCES/kvm-iotests-Filter-SSH-paths.patch new file mode 100644 index 0000000..07e69e8 --- /dev/null +++ b/SOURCES/kvm-iotests-Filter-SSH-paths.patch @@ -0,0 +1,49 @@ +From 1d8ba61938b06c54749b96af34acf3fee751bc93 Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Mon, 8 Jul 2019 15:25:56 +0100 +Subject: [PATCH 10/39] iotests: Filter SSH paths +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Pino Toscano +Message-id: <20190708152601.21123-6-ptoscano@redhat.com> +Patchwork-id: 89416 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v3 05/10] iotests: Filter SSH paths +Bugzilla: 1513367 +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Max Reitz +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Markus Armbruster + +From: Max Reitz + +8908b253c4ad5f8874c8d13abec169c696a5cd32 has implemented filtering of +remote paths for NFS, but forgot SSH. This patch takes care of that. + +Signed-off-by: Max Reitz +Reviewed-by: John Snow +Message-id: 20190210145736.1486-9-mreitz@redhat.com +Signed-off-by: Max Reitz +(cherry picked from commit ac3589dc463c18e6726be2831196c7755bec39d5) +Signed-off-by: Pino Toscano +Signed-off-by: Danilo C. L. de Paula +--- + tests/qemu-iotests/common.rc | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc +index d054cb9..6490c8d 100644 +--- a/tests/qemu-iotests/common.rc ++++ b/tests/qemu-iotests/common.rc +@@ -145,6 +145,7 @@ else + TEST_IMG="nbd:127.0.0.1:10810" + elif [ "$IMGPROTO" = "ssh" ]; then + TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT ++ REMOTE_TEST_DIR="ssh://127.0.0.1$TEST_DIR" + TEST_IMG="ssh://127.0.0.1$TEST_IMG_FILE" + elif [ "$IMGPROTO" = "nfs" ]; then + TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT +-- +1.8.3.1 + diff --git a/SOURCES/kvm-iotests-Make-182-do-without-device_add.patch b/SOURCES/kvm-iotests-Make-182-do-without-device_add.patch new file mode 100644 index 0000000..5d4e5e6 --- /dev/null +++ b/SOURCES/kvm-iotests-Make-182-do-without-device_add.patch @@ -0,0 +1,95 @@ +From 58bf58e416a89ea5166865664887cfe4562b1fc0 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Wed, 26 Jun 2019 16:24:01 +0100 +Subject: [PATCH 2/2] iotests: Make 182 do without device_add +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Max Reitz +Message-id: <20190626162401.11112-2-mreitz@redhat.com> +Patchwork-id: 88951 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 1/1] iotests: Make 182 do without device_add +Bugzilla: 1707598 +RH-Acked-by: Kevin Wolf +RH-Acked-by: John Snow +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Stefan Hajnoczi + +182 fails if qemu has no support for hotplugging of a virtio-blk device. +Using an NBD server instead works just as well for the test, even on +qemus without hotplugging support. + +Fixes: 6d0a4a0fb5c8f10c8eb68b52cfda0082b00ae963 +Reported-by: Danilo C. L. de Paula +Signed-off-by: Max Reitz +Message-Id: <20190417153005.30096-1-mreitz@redhat.com> +Tested-by: Eric Blake +Reviewed-by: Eric Blake +Acked-by: Alberto Garcia +Signed-off-by: Eric Blake +(cherry picked from commit 8fabb8be37775ebb32b0d78bc7be815a29b8a107) +Signed-off-by: Max Reitz +Signed-off-by: Danilo C. L. de Paula +--- + tests/qemu-iotests/182 | 22 +++++++++++++++++----- + tests/qemu-iotests/182.out | 1 + + 2 files changed, 18 insertions(+), 5 deletions(-) + +diff --git a/tests/qemu-iotests/182 b/tests/qemu-iotests/182 +index 3b7689c..c1520ed 100755 +--- a/tests/qemu-iotests/182 ++++ b/tests/qemu-iotests/182 +@@ -32,6 +32,7 @@ _cleanup() + { + _cleanup_test_img + rm -f "$TEST_IMG.overlay" ++ rm -f "$TEST_DIR/nbd.socket" + } + trap "_cleanup; exit \$status" 0 1 2 3 15 + +@@ -127,15 +128,26 @@ success_or_failure=y _send_qemu_cmd $QEMU_HANDLE \ + 'return' \ + 'error' + +-# Now we attach the image to a virtio-blk device. This device does +-# require some permissions (at least WRITE and READ_CONSISTENT), so if ++# Start an NBD server to which we can attach node1 ++success_or_failure=y _send_qemu_cmd $QEMU_HANDLE \ ++ "{'execute': 'nbd-server-start', ++ 'arguments': { ++ 'addr': { ++ 'type': 'unix', ++ 'data': { ++ 'path': '$TEST_DIR/nbd.socket' ++ } } } }" \ ++ 'return' \ ++ 'error' ++ ++# Now we attach the image to the NBD server. This server does require ++# some permissions (at least WRITE and READ_CONSISTENT), so if + # reopening node0 unshared any (which it should not have), this will + # fail (but it should not). + success_or_failure=y _send_qemu_cmd $QEMU_HANDLE \ +- "{'execute': 'device_add', ++ "{'execute': 'nbd-server-add', + 'arguments': { +- 'driver': 'virtio-blk', +- 'drive': 'node1' ++ 'device': 'node1' + } }" \ + 'return' \ + 'error' +diff --git a/tests/qemu-iotests/182.out b/tests/qemu-iotests/182.out +index af501ca..33d41ee 100644 +--- a/tests/qemu-iotests/182.out ++++ b/tests/qemu-iotests/182.out +@@ -14,4 +14,5 @@ Formatting 'TEST_DIR/t.qcow2.overlay', fmt=qcow2 size=197120 backing_file=TEST_D + {"return": {}} + {"return": {}} + {"return": {}} ++{"return": {}} + *** done +-- +1.8.3.1 + diff --git a/SOURCES/kvm-iotests-Test-allocate_first_block-with-O_DIRECT.patch b/SOURCES/kvm-iotests-Test-allocate_first_block-with-O_DIRECT.patch new file mode 100644 index 0000000..b02cbbb --- /dev/null +++ b/SOURCES/kvm-iotests-Test-allocate_first_block-with-O_DIRECT.patch @@ -0,0 +1,108 @@ +From b4841fd40fefcffc99c4b52c8a06720edb4ef9ef Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Fri, 30 Aug 2019 12:56:28 +0100 +Subject: [PATCH 10/10] iotests: Test allocate_first_block() with O_DIRECT + +RH-Author: Thomas Huth +Message-id: <20190830125628.23668-6-thuth@redhat.com> +Patchwork-id: 90212 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v2 5/5] iotests: Test allocate_first_block() with O_DIRECT +Bugzilla: 1738839 +RH-Acked-by: Cornelia Huck +RH-Acked-by: Max Reitz +RH-Acked-by: David Hildenbrand + +From: Nir Soffer + +Using block_resize we can test allocate_first_block() with file +descriptor opened with O_DIRECT, ensuring that it works for any size +larger than 4096 bytes. + +Testing smaller sizes is tricky as the result depends on the filesystem +used for testing. For example on NFS any size will work since O_DIRECT +does not require any alignment. + +Signed-off-by: Nir Soffer +Reviewed-by: Max Reitz +Message-id: 20190827010528.8818-3-nsoffer@redhat.com +Signed-off-by: Max Reitz +(cherry picked from commit 4656fb5ebbece8c7bbca0bef56bea882c94b9132) +Signed-off-by: Danilo C. L. de Paula +--- + tests/qemu-iotests/175 | 28 ++++++++++++++++++++++++++++ + tests/qemu-iotests/175.out | 8 ++++++++ + 2 files changed, 36 insertions(+) + +diff --git a/tests/qemu-iotests/175 b/tests/qemu-iotests/175 +index b3b7712..74ca49d 100755 +--- a/tests/qemu-iotests/175 ++++ b/tests/qemu-iotests/175 +@@ -50,6 +50,23 @@ _filter_blocks() + -e "s/blocks=$((extra_blocks + img_size / 512))\\(\$\\|[^0-9]\\)/max allocation/" + } + ++# Resize image using block_resize. ++# Parameter 1: image path ++# Parameter 2: new size ++_block_resize() ++{ ++ local path=$1 ++ local size=$2 ++ ++ $QEMU -qmp stdio -nographic -nodefaults \ ++ -blockdev file,node-name=file,filename=$path,cache.direct=on \ ++ </dev/null ++ stat -c "size=%s, blocks=%b" $TEST_IMG | _filter_blocks $extra_blocks $min_blocks $new_size ++done ++ + # success, all done + echo "*** done" + rm -f $seq.full +diff --git a/tests/qemu-iotests/175.out b/tests/qemu-iotests/175.out +index 263e521..39c2ee0 100644 +--- a/tests/qemu-iotests/175.out ++++ b/tests/qemu-iotests/175.out +@@ -15,4 +15,12 @@ size=1048576, max allocation + == creating image with preallocation falloc == + Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048576 preallocation=falloc + size=1048576, max allocation ++ ++== resize empty image with block_resize == ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=0 ++size=4096, min allocation ++ ++== resize empty image with block_resize == ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=0 ++size=1048576, min allocation + *** done +-- +1.8.3.1 + diff --git a/SOURCES/kvm-iotests-Test-file-posix-locking-and-reopen.patch b/SOURCES/kvm-iotests-Test-file-posix-locking-and-reopen.patch new file mode 100644 index 0000000..03e9a9c --- /dev/null +++ b/SOURCES/kvm-iotests-Test-file-posix-locking-and-reopen.patch @@ -0,0 +1,135 @@ +From 45fd7df81a04ef0cdc2e67fee6f8047ec2a3c7cd Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Wed, 3 Apr 2019 17:13:14 +0100 +Subject: [PATCH 07/11] iotests: Test file-posix locking and reopen + +RH-Author: Max Reitz +Message-id: <20190403171315.20841-8-mreitz@redhat.com> +Patchwork-id: 85405 +O-Subject: [RHEL-8.1 qemu-kvm PATCH 7/8] iotests: Test file-posix locking and reopen +Bugzilla: 1694148 +RH-Acked-by: John Snow +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Stefano Garzarella + +Signed-off-by: Max Reitz +Reviewed-by: Alberto Garcia +Signed-off-by: Kevin Wolf +(cherry picked from commit 6d0a4a0fb5c8f10c8eb68b52cfda0082b00ae963) +Signed-off-by: Max Reitz +Signed-off-by: Danilo C. L. de Paula +--- + tests/qemu-iotests/182 | 71 ++++++++++++++++++++++++++++++++++++++++++++++ + tests/qemu-iotests/182.out | 9 ++++++ + 2 files changed, 80 insertions(+) + +diff --git a/tests/qemu-iotests/182 b/tests/qemu-iotests/182 +index 4b31592..3b7689c 100755 +--- a/tests/qemu-iotests/182 ++++ b/tests/qemu-iotests/182 +@@ -31,6 +31,7 @@ status=1 # failure is the default! + _cleanup() + { + _cleanup_test_img ++ rm -f "$TEST_IMG.overlay" + } + trap "_cleanup; exit \$status" 0 1 2 3 15 + +@@ -71,6 +72,76 @@ echo 'quit' | $QEMU -nographic -monitor stdio \ + + _cleanup_qemu + ++echo ++echo '=== Testing reopen ===' ++echo ++ ++# This tests that reopening does not unshare any permissions it should ++# not unshare ++# (There was a bug where reopening shared exactly the opposite of the ++# permissions it was supposed to share) ++ ++_launch_qemu ++ ++_send_qemu_cmd $QEMU_HANDLE \ ++ "{'execute': 'qmp_capabilities'}" \ ++ 'return' ++ ++# Open the image without any format layer (we are not going to access ++# it, so that is fine) ++# This should keep all permissions shared. ++success_or_failure=y _send_qemu_cmd $QEMU_HANDLE \ ++ "{'execute': 'blockdev-add', ++ 'arguments': { ++ 'node-name': 'node0', ++ 'driver': 'file', ++ 'filename': '$TEST_IMG', ++ 'locking': 'on' ++ } }" \ ++ 'return' \ ++ 'error' ++ ++# This snapshot will perform a reopen to drop R/W to RO. ++# It should still keep all permissions shared. ++success_or_failure=y _send_qemu_cmd $QEMU_HANDLE \ ++ "{'execute': 'blockdev-snapshot-sync', ++ 'arguments': { ++ 'node-name': 'node0', ++ 'snapshot-file': '$TEST_IMG.overlay', ++ 'snapshot-node-name': 'node1' ++ } }" \ ++ 'return' \ ++ 'error' ++ ++# Now open the same file again ++# This does not require any permissions (and does not unshare any), so ++# this will not conflict with node0. ++success_or_failure=y _send_qemu_cmd $QEMU_HANDLE \ ++ "{'execute': 'blockdev-add', ++ 'arguments': { ++ 'node-name': 'node1', ++ 'driver': 'file', ++ 'filename': '$TEST_IMG', ++ 'locking': 'on' ++ } }" \ ++ 'return' \ ++ 'error' ++ ++# Now we attach the image to a virtio-blk device. This device does ++# require some permissions (at least WRITE and READ_CONSISTENT), so if ++# reopening node0 unshared any (which it should not have), this will ++# fail (but it should not). ++success_or_failure=y _send_qemu_cmd $QEMU_HANDLE \ ++ "{'execute': 'device_add', ++ 'arguments': { ++ 'driver': 'virtio-blk', ++ 'drive': 'node1' ++ } }" \ ++ 'return' \ ++ 'error' ++ ++_cleanup_qemu ++ + # success, all done + echo "*** done" + rm -f $seq.full +diff --git a/tests/qemu-iotests/182.out b/tests/qemu-iotests/182.out +index f1463c8..af501ca 100644 +--- a/tests/qemu-iotests/182.out ++++ b/tests/qemu-iotests/182.out +@@ -5,4 +5,13 @@ Starting QEMU + Starting a second QEMU using the same image should fail + QEMU_PROG: -drive file=TEST_DIR/t.qcow2,if=none,id=drive0,file.locking=on: Failed to get "write" lock + Is another process using the image [TEST_DIR/t.qcow2]? ++ ++=== Testing reopen === ++ ++{"return": {}} ++{"return": {}} ++Formatting 'TEST_DIR/t.qcow2.overlay', fmt=qcow2 size=197120 backing_file=TEST_DIR/t.qcow2 backing_fmt=file cluster_size=65536 lazy_refcounts=off refcount_bits=16 ++{"return": {}} ++{"return": {}} ++{"return": {}} + *** done +-- +1.8.3.1 + diff --git a/SOURCES/kvm-iotests-Test-unaligned-raw-images-with-O_DIRECT.patch b/SOURCES/kvm-iotests-Test-unaligned-raw-images-with-O_DIRECT.patch new file mode 100644 index 0000000..3aefe6f --- /dev/null +++ b/SOURCES/kvm-iotests-Test-unaligned-raw-images-with-O_DIRECT.patch @@ -0,0 +1,182 @@ +From d193f7ee2bf7822408fa9a92b7e170330b7f6ec4 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Tue, 23 Jul 2019 14:45:41 +0100 +Subject: [PATCH 03/14] iotests: Test unaligned raw images with O_DIRECT + +RH-Author: Max Reitz +Message-id: <20190723144546.23701-3-mreitz@redhat.com> +Patchwork-id: 89648 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 2/7] iotests: Test unaligned raw images with O_DIRECT +Bugzilla: 1678979 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Stefano Garzarella +RH-Acked-by: John Snow + +We already have 221 for accesses through the page cache, but it is +better to create a new file for O_DIRECT instead of integrating those +test cases into 221. This way, we can make use of +_supported_cache_modes (and _default_cache_mode) so the test is +automatically skipped on filesystems that do not support O_DIRECT. + +As part of the split, add _supported_cache_modes to 221. With that, it +no longer fails when run with -c none or -c directsync. + +Signed-off-by: Max Reitz +Reviewed-by: Eric Blake +Signed-off-by: Kevin Wolf +(cherry picked from commit 2fab30c80b33cdc6157c7efe6207e54b6835cf92) +Signed-off-by: Max Reitz +Signed-off-by: Danilo C. L. de Paula +--- + tests/qemu-iotests/221 | 4 +++ + tests/qemu-iotests/253 | 84 ++++++++++++++++++++++++++++++++++++++++++++++ + tests/qemu-iotests/253.out | 14 ++++++++ + tests/qemu-iotests/group | 1 + + 4 files changed, 103 insertions(+) + create mode 100755 tests/qemu-iotests/253 + create mode 100644 tests/qemu-iotests/253.out + +diff --git a/tests/qemu-iotests/221 b/tests/qemu-iotests/221 +index 41c4e4b..2cc29ba 100755 +--- a/tests/qemu-iotests/221 ++++ b/tests/qemu-iotests/221 +@@ -1,6 +1,7 @@ + #!/bin/bash + # + # Test qemu-img vs. unaligned images ++# (See also 253, which is the O_DIRECT version) + # + # Copyright (C) 2018 Red Hat, Inc. + # +@@ -38,6 +39,9 @@ _supported_fmt raw + _supported_proto file + _supported_os Linux + ++_default_cache_mode writeback ++_supported_cache_modes writeback writethrough unsafe ++ + echo + echo "=== Check mapping of unaligned raw image ===" + echo +diff --git a/tests/qemu-iotests/253 b/tests/qemu-iotests/253 +new file mode 100755 +index 0000000..d88d5af +--- /dev/null ++++ b/tests/qemu-iotests/253 +@@ -0,0 +1,84 @@ ++#!/usr/bin/env bash ++# ++# Test qemu-img vs. unaligned images; O_DIRECT version ++# (Originates from 221) ++# ++# Copyright (C) 2019 Red Hat, Inc. ++# ++# This program is free software; you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation; either version 2 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program. If not, see . ++# ++ ++seq="$(basename $0)" ++echo "QA output created by $seq" ++ ++status=1 # failure is the default! ++ ++_cleanup() ++{ ++ _cleanup_test_img ++} ++trap "_cleanup; exit \$status" 0 1 2 3 15 ++ ++# get standard environment, filters and checks ++. ./common.rc ++. ./common.filter ++ ++_supported_fmt raw ++_supported_proto file ++_supported_os Linux ++ ++_default_cache_mode none ++_supported_cache_modes none directsync ++ ++echo ++echo "=== Check mapping of unaligned raw image ===" ++echo ++ ++# We do not know how large a physical sector is, but it is certainly ++# going to be a factor of 1 MB ++size=$((1 * 1024 * 1024 - 1)) ++ ++# qemu-img create rounds size up to BDRV_SECTOR_SIZE ++_make_test_img $size ++$QEMU_IMG map --output=json --image-opts \ ++ "driver=$IMGFMT,file.driver=file,file.filename=$TEST_IMG,cache.direct=on" \ ++ | _filter_qemu_img_map ++ ++# so we resize it and check again ++truncate --size=$size "$TEST_IMG" ++$QEMU_IMG map --output=json --image-opts \ ++ "driver=$IMGFMT,file.driver=file,file.filename=$TEST_IMG,cache.direct=on" \ ++ | _filter_qemu_img_map ++ ++# qemu-io with O_DIRECT always writes whole physical sectors. Again, ++# we do not know how large a physical sector is, so we just start ++# writing from a 64 kB boundary, which should always be aligned. ++offset=$((1 * 1024 * 1024 - 64 * 1024)) ++$QEMU_IO -c "w $offset $((size - offset))" "$TEST_IMG" | _filter_qemu_io ++$QEMU_IMG map --output=json --image-opts \ ++ "driver=$IMGFMT,file.driver=file,file.filename=$TEST_IMG,cache.direct=on" \ ++ | _filter_qemu_img_map ++ ++# Resize it and check again -- contrary to 221, we may not get partial ++# sectors here, so there should be only two areas (one zero, one ++# data). ++truncate --size=$size "$TEST_IMG" ++$QEMU_IMG map --output=json --image-opts \ ++ "driver=$IMGFMT,file.driver=file,file.filename=$TEST_IMG,cache.direct=on" \ ++ | _filter_qemu_img_map ++ ++# success, all done ++echo '*** done' ++rm -f $seq.full ++status=0 +diff --git a/tests/qemu-iotests/253.out b/tests/qemu-iotests/253.out +new file mode 100644 +index 0000000..607c0ba +--- /dev/null ++++ b/tests/qemu-iotests/253.out +@@ -0,0 +1,14 @@ ++QA output created by 253 ++ ++=== Check mapping of unaligned raw image === ++ ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=1048575 ++[{ "start": 0, "length": 1048576, "depth": 0, "zero": true, "data": false, "offset": OFFSET}] ++[{ "start": 0, "length": 1048576, "depth": 0, "zero": true, "data": false, "offset": OFFSET}] ++wrote 65535/65535 bytes at offset 983040 ++63.999 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) ++[{ "start": 0, "length": 983040, "depth": 0, "zero": true, "data": false, "offset": OFFSET}, ++{ "start": 983040, "length": 65536, "depth": 0, "zero": false, "data": true, "offset": OFFSET}] ++[{ "start": 0, "length": 983040, "depth": 0, "zero": true, "data": false, "offset": OFFSET}, ++{ "start": 983040, "length": 65536, "depth": 0, "zero": false, "data": true, "offset": OFFSET}] ++*** done +diff --git a/tests/qemu-iotests/group b/tests/qemu-iotests/group +index 5cbdc24..b356d82 100644 +--- a/tests/qemu-iotests/group ++++ b/tests/qemu-iotests/group +@@ -227,3 +227,4 @@ + 232 auto quick + 234 auto quick migration + 240 auto quick ++253 rw auto quick +-- +1.8.3.1 + diff --git a/SOURCES/kvm-iotests-Tweak-221-sizing-for-different-hole-granular.patch b/SOURCES/kvm-iotests-Tweak-221-sizing-for-different-hole-granular.patch new file mode 100644 index 0000000..228841b --- /dev/null +++ b/SOURCES/kvm-iotests-Tweak-221-sizing-for-different-hole-granular.patch @@ -0,0 +1,101 @@ +From 6f5c54a54c05143cf9f69a626b398886d1c51358 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Fri, 30 Aug 2019 12:56:25 +0100 +Subject: [PATCH 07/10] iotests: Tweak 221 sizing for different hole + granularities + +RH-Author: Thomas Huth +Message-id: <20190830125628.23668-3-thuth@redhat.com> +Patchwork-id: 90213 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v2 2/5] iotests: Tweak 221 sizing for different hole granularities +Bugzilla: 1738839 +RH-Acked-by: Cornelia Huck +RH-Acked-by: Max Reitz +RH-Acked-by: David Hildenbrand + +From: Eric Blake + +For some particular configurations of ext4, sizing an image to 84 +sectors + 1 byte causes test failures when the size of the hole is +rounded to a 4k alignment. Let's instead size things to 128 sectors + +1 byte, as the 64k boundary is more likely to work with various hole +granularities. + +Reported-by: Thomas Huth +Signed-off-by: Eric Blake +Message-Id: <20190506172111.31594-1-eblake@redhat.com> +Tested-by: Thomas Huth +(cherry picked from commit d3192de752cd6d383d38e50341b39d9550d21fa8) +Signed-off-by: Danilo C. L. de Paula +--- + tests/qemu-iotests/221 | 10 +++++----- + tests/qemu-iotests/221.out | 20 ++++++++++---------- + 2 files changed, 15 insertions(+), 15 deletions(-) + +diff --git a/tests/qemu-iotests/221 b/tests/qemu-iotests/221 +index 2cc29ba..75aa192 100755 +--- a/tests/qemu-iotests/221 ++++ b/tests/qemu-iotests/221 +@@ -3,7 +3,7 @@ + # Test qemu-img vs. unaligned images + # (See also 253, which is the O_DIRECT version) + # +-# Copyright (C) 2018 Red Hat, Inc. ++# Copyright (C) 2018-2019 Red Hat, Inc. + # + # This program is free software; you can redistribute it and/or modify + # it under the terms of the GNU General Public License as published by +@@ -46,16 +46,16 @@ echo + echo "=== Check mapping of unaligned raw image ===" + echo + +-_make_test_img 43009 # qemu-img create rounds size up ++_make_test_img 65537 # qemu-img create rounds size up + $QEMU_IMG map --output=json "$TEST_IMG" | _filter_qemu_img_map + +-truncate --size=43009 "$TEST_IMG" # so we resize it and check again ++truncate --size=65537 "$TEST_IMG" # so we resize it and check again + $QEMU_IMG map --output=json "$TEST_IMG" | _filter_qemu_img_map + +-$QEMU_IO -c 'w 43008 1' "$TEST_IMG" | _filter_qemu_io # writing also rounds up ++$QEMU_IO -c 'w 65536 1' "$TEST_IMG" | _filter_qemu_io # writing also rounds up + $QEMU_IMG map --output=json "$TEST_IMG" | _filter_qemu_img_map + +-truncate --size=43009 "$TEST_IMG" # so we resize it and check again ++truncate --size=65537 "$TEST_IMG" # so we resize it and check again + $QEMU_IMG map --output=json "$TEST_IMG" | _filter_qemu_img_map + + # success, all done +diff --git a/tests/qemu-iotests/221.out b/tests/qemu-iotests/221.out +index a9c0190..9f9dd52 100644 +--- a/tests/qemu-iotests/221.out ++++ b/tests/qemu-iotests/221.out +@@ -2,15 +2,15 @@ QA output created by 221 + + === Check mapping of unaligned raw image === + +-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=43009 +-[{ "start": 0, "length": 43520, "depth": 0, "zero": true, "data": false, "offset": OFFSET}] +-[{ "start": 0, "length": 43520, "depth": 0, "zero": true, "data": false, "offset": OFFSET}] +-wrote 1/1 bytes at offset 43008 ++Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=65537 ++[{ "start": 0, "length": 66048, "depth": 0, "zero": true, "data": false, "offset": OFFSET}] ++[{ "start": 0, "length": 66048, "depth": 0, "zero": true, "data": false, "offset": OFFSET}] ++wrote 1/1 bytes at offset 65536 + 1 bytes, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec) +-[{ "start": 0, "length": 40960, "depth": 0, "zero": true, "data": false, "offset": OFFSET}, +-{ "start": 40960, "length": 2049, "depth": 0, "zero": false, "data": true, "offset": OFFSET}, +-{ "start": 43009, "length": 511, "depth": 0, "zero": true, "data": false, "offset": OFFSET}] +-[{ "start": 0, "length": 40960, "depth": 0, "zero": true, "data": false, "offset": OFFSET}, +-{ "start": 40960, "length": 2049, "depth": 0, "zero": false, "data": true, "offset": OFFSET}, +-{ "start": 43009, "length": 511, "depth": 0, "zero": true, "data": false, "offset": OFFSET}] ++[{ "start": 0, "length": 65536, "depth": 0, "zero": true, "data": false, "offset": OFFSET}, ++{ "start": 65536, "length": 1, "depth": 0, "zero": false, "data": true, "offset": OFFSET}, ++{ "start": 65537, "length": 511, "depth": 0, "zero": true, "data": false, "offset": OFFSET}] ++[{ "start": 0, "length": 65536, "depth": 0, "zero": true, "data": false, "offset": OFFSET}, ++{ "start": 65536, "length": 1, "depth": 0, "zero": false, "data": true, "offset": OFFSET}, ++{ "start": 65537, "length": 511, "depth": 0, "zero": true, "data": false, "offset": OFFSET}] + *** done +-- +1.8.3.1 + diff --git a/SOURCES/kvm-iotests-Unify-log-outputs-between-Python-2-and-3.patch b/SOURCES/kvm-iotests-Unify-log-outputs-between-Python-2-and-3.patch new file mode 100644 index 0000000..d53070c --- /dev/null +++ b/SOURCES/kvm-iotests-Unify-log-outputs-between-Python-2-and-3.patch @@ -0,0 +1,2136 @@ +From f58a88cc157331a911eb2cf1faee6d494b0c9333 Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Mon, 8 Jul 2019 15:25:59 +0100 +Subject: [PATCH 13/39] iotests: Unify log outputs between Python 2 and 3 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Pino Toscano +Message-id: <20190708152601.21123-9-ptoscano@redhat.com> +Patchwork-id: 89420 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v3 08/10] iotests: Unify log outputs between Python 2 and 3 +Bugzilla: 1513367 +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Max Reitz +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Markus Armbruster + +From: Max Reitz + +When dumping an object into the log, there are differences between +Python 2 and 3. First, unicode strings are prefixed by 'u' in Python 2 +(they are no longer in 3, because unicode strings are the default +there). Second, the order of keys in dicts may differ. Third, +especially long numbers are longs in Python 2 and thus get an 'L' +suffix, which does not happen in Python 3. + +We can get around all of these differences by dumping objects (lists and +dicts) in a language-independent format, namely JSON. The JSON +generator even allows emitting dicts with their keys sorted +alphabetically. + +This changes the output of all tests that use these logging functions +(dict keys are ordered now, strings in dicts are now enclosed in double +quotes instead of single quotes, the 'L' suffix of large integers is +dropped, and "true" and "false" are now in lower case). +The quote change necessitates a small change to a filter used in test +207. + +Suggested-by: Eduardo Habkost +Signed-off-by: Max Reitz +Reviewed-by: Cleber Rosa +Message-Id: <20181022135307.14398-10-mreitz@redhat.com> +Signed-off-by: Eduardo Habkost +(cherry picked from commit e21b5f34d669b82087597273f3783626947291a0) +Signed-off-by: Pino Toscano +Signed-off-by: Danilo C. L. de Paula +--- + tests/qemu-iotests/194.out | 22 +- + tests/qemu-iotests/202.out | 12 +- + tests/qemu-iotests/203.out | 14 +- + tests/qemu-iotests/206.out | 218 ++++++++--------- + tests/qemu-iotests/207 | 2 +- + tests/qemu-iotests/207.out | 72 +++--- + tests/qemu-iotests/208.out | 8 +- + tests/qemu-iotests/210.out | 94 ++++---- + tests/qemu-iotests/211.out | 102 ++++---- + tests/qemu-iotests/212.out | 174 +++++++------- + tests/qemu-iotests/213.out | 182 +++++++-------- + tests/qemu-iotests/216.out | 4 +- + tests/qemu-iotests/218.out | 20 +- + tests/qemu-iotests/219.out | 526 +++++++++++++++++++++--------------------- + tests/qemu-iotests/222.out | 24 +- + tests/qemu-iotests/iotests.py | 10 +- + 16 files changed, 744 insertions(+), 740 deletions(-) + +diff --git a/tests/qemu-iotests/194.out b/tests/qemu-iotests/194.out +index 50ac50d..7185785 100644 +--- a/tests/qemu-iotests/194.out ++++ b/tests/qemu-iotests/194.out +@@ -1,18 +1,18 @@ + Launching VMs... + Launching NBD server on destination... +-{u'return': {}} +-{u'return': {}} ++{"return": {}} ++{"return": {}} + Starting `drive-mirror` on source... +-{u'return': {}} ++{"return": {}} + Waiting for `drive-mirror` to complete... +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'device': u'mirror-job0', u'type': u'mirror', u'speed': 0, u'len': 1073741824, u'offset': 1073741824}, u'event': u'BLOCK_JOB_READY'} ++{"data": {"device": "mirror-job0", "len": 1073741824, "offset": 1073741824, "speed": 0, "type": "mirror"}, "event": "BLOCK_JOB_READY", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} + Starting migration... +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'setup'}, u'event': u'MIGRATION'} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'active'}, u'event': u'MIGRATION'} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'completed'}, u'event': u'MIGRATION'} ++{"return": {}} ++{"data": {"status": "setup"}, "event": "MIGRATION", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"data": {"status": "active"}, "event": "MIGRATION", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"data": {"status": "completed"}, "event": "MIGRATION", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} + Gracefully ending the `drive-mirror` job on source... +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'device': u'mirror-job0', u'type': u'mirror', u'speed': 0, u'len': 1073741824, u'offset': 1073741824}, u'event': u'BLOCK_JOB_COMPLETED'} ++{"return": {}} ++{"data": {"device": "mirror-job0", "len": 1073741824, "offset": 1073741824, "speed": 0, "type": "mirror"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} + Stopping the NBD server on destination... +-{u'return': {}} ++{"return": {}} +diff --git a/tests/qemu-iotests/202.out b/tests/qemu-iotests/202.out +index d5ea374..9a8619e 100644 +--- a/tests/qemu-iotests/202.out ++++ b/tests/qemu-iotests/202.out +@@ -1,11 +1,11 @@ + Launching VM... + Adding IOThread... +-{u'return': {}} ++{"return": {}} + Adding blockdevs... +-{u'return': {}} +-{u'return': {}} ++{"return": {}} ++{"return": {}} + Setting iothread... +-{u'return': {}} +-{u'return': {}} ++{"return": {}} ++{"return": {}} + Creating external snapshots... +-{u'return': {}} ++{"return": {}} +diff --git a/tests/qemu-iotests/203.out b/tests/qemu-iotests/203.out +index 1a11f09..9d4abba 100644 +--- a/tests/qemu-iotests/203.out ++++ b/tests/qemu-iotests/203.out +@@ -1,11 +1,11 @@ + Launching VM... + Setting IOThreads... +-{u'return': {}} +-{u'return': {}} ++{"return": {}} ++{"return": {}} + Enabling migration QMP events... +-{u'return': {}} ++{"return": {}} + Starting migration... +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'setup'}, u'event': u'MIGRATION'} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'active'}, u'event': u'MIGRATION'} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'completed'}, u'event': u'MIGRATION'} ++{"return": {}} ++{"data": {"status": "setup"}, "event": "MIGRATION", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"data": {"status": "active"}, "event": "MIGRATION", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"data": {"status": "completed"}, "event": "MIGRATION", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +diff --git a/tests/qemu-iotests/206.out b/tests/qemu-iotests/206.out +index 789eebe..91f4db5 100644 +--- a/tests/qemu-iotests/206.out ++++ b/tests/qemu-iotests/206.out +@@ -1,16 +1,16 @@ + === Successful image creation (defaults) === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.qcow2'}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} +- +-{'execute': 'blockdev-add', 'arguments': {'node_name': 'imgfile', 'driver': 'file', 'filename': 'TEST_DIR/PID-t.qcow2'}} +-{u'return': {}} +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'qcow2', 'file': 'imgfile', 'size': 134217728}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "size": 0}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} ++ ++{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "node_name": "imgfile"}} ++{"return": {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "imgfile", "size": 134217728}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + image: TEST_IMG + file format: IMGFMT +@@ -24,15 +24,15 @@ Format specific information: + + === Successful image creation (inline blockdev-add, explicit defaults) === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'nocow': False, 'preallocation': 'off', 'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.qcow2'}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "nocow": false, "preallocation": "off", "size": 0}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 65536, 'refcount-bits': 16, 'version': 'v3', 'preallocation': 'off', 'file': {'driver': 'file', 'filename': 'TEST_DIR/PID-t.qcow2'}, 'lazy-refcounts': False, 'driver': 'qcow2', 'size': 67108864}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 65536, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2"}, "lazy-refcounts": false, "preallocation": "off", "refcount-bits": 16, "size": 67108864, "version": "v3"}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + image: TEST_IMG + file format: IMGFMT +@@ -46,15 +46,15 @@ Format specific information: + + === Successful image creation (v3 non-default options) === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'nocow': True, 'preallocation': 'falloc', 'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.qcow2'}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "nocow": true, "preallocation": "falloc", "size": 0}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 2097152, 'refcount-bits': 1, 'version': 'v3', 'preallocation': 'metadata', 'file': {'driver': 'file', 'filename': 'TEST_DIR/PID-t.qcow2'}, 'lazy-refcounts': True, 'driver': 'qcow2', 'size': 33554432}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 2097152, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2"}, "lazy-refcounts": true, "preallocation": "metadata", "refcount-bits": 1, "size": 33554432, "version": "v3"}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + image: TEST_IMG + file format: IMGFMT +@@ -68,15 +68,15 @@ Format specific information: + + === Successful image creation (v2 non-default options) === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.qcow2'}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2", "size": 0}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 512, 'backing-fmt': 'qcow2', 'driver': 'qcow2', 'version': 'v2', 'file': {'driver': 'file', 'filename': 'TEST_DIR/PID-t.qcow2'}, 'backing-file': 'TEST_DIR/PID-t.qcow2.base', 'size': 33554432}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"backing-file": "TEST_DIR/PID-t.qcow2.base", "backing-fmt": "qcow2", "cluster-size": 512, "driver": "qcow2", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2"}, "size": 33554432, "version": "v2"}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + image: TEST_IMG + file format: IMGFMT +@@ -90,10 +90,10 @@ Format specific information: + + === Successful image creation (encrypted) === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'encrypt': {'key-secret': 'keysec0', 'iter-time': 10, 'cipher-mode': 'ctr', 'ivgen-hash-alg': 'md5', 'cipher-alg': 'twofish-128', 'format': 'luks', 'ivgen-alg': 'plain64', 'hash-alg': 'sha1'}, 'driver': 'qcow2', 'file': {'driver': 'file', 'filename': 'TEST_DIR/PID-t.qcow2'}, 'size': 33554432}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "encrypt": {"cipher-alg": "twofish-128", "cipher-mode": "ctr", "format": "luks", "hash-alg": "sha1", "iter-time": 10, "ivgen-alg": "plain64", "ivgen-hash-alg": "md5", "key-secret": "keysec0"}, "file": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2"}, "size": 33554432}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + image: TEST_IMG + file format: IMGFMT +@@ -144,113 +144,113 @@ Format specific information: + + === Invalid BlockdevRef === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'qcow2', 'file': "this doesn't exist", 'size': 33554432}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "this doesn't exist", "size": 33554432}}} ++{"return": {}} + Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exist +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + === Invalid sizes === +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'qcow2', 'file': 'node0', 'size': 1234}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "size": 1234}}} ++{"return": {}} + Job failed: Image size must be a multiple of 512 bytes +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'qcow2', 'file': 'node0', 'size': 18446744073709551104L}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "size": 18446744073709551104}}} ++{"return": {}} + Job failed: Could not resize image: Image size cannot be negative +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'qcow2', 'file': 'node0', 'size': 9223372036854775808L}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "size": 9223372036854775808}}} ++{"return": {}} + Job failed: Could not resize image: Image size cannot be negative +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'qcow2', 'file': 'node0', 'size': 9223372036854775296}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "size": 9223372036854775296}}} ++{"return": {}} + Job failed: Could not resize image: Failed to grow the L1 table: File too large +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + === Invalid version === +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'version': 'v1', 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}} +-{u'error': {u'class': u'GenericError', u'desc': u"Invalid parameter 'v1'"}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "size": 67108864, "version": "v1"}}} ++{"error": {"class": "GenericError", "desc": "Invalid parameter 'v1'"}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'lazy-refcounts': True, 'version': 'v2', 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "lazy-refcounts": true, "size": 67108864, "version": "v2"}}} ++{"return": {}} + Job failed: Lazy refcounts only supported with compatibility level 1.1 and above (use version=v3 or greater) +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'refcount-bits': 8, 'version': 'v2', 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "refcount-bits": 8, "size": 67108864, "version": "v2"}}} ++{"return": {}} + Job failed: Different refcount widths than 16 bits require compatibility level 1.1 or above (use version=v3 or greater) +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + === Invalid backing file options === +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'preallocation': 'full', 'driver': 'qcow2', 'backing-file': '/dev/null', 'file': 'node0', 'size': 67108864}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"backing-file": "/dev/null", "driver": "qcow2", "file": "node0", "preallocation": "full", "size": 67108864}}} ++{"return": {}} + Job failed: Backing file and preallocation cannot be used at the same time +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'backing-fmt': 'qcow2', 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"backing-fmt": "qcow2", "driver": "qcow2", "file": "node0", "size": 67108864}}} ++{"return": {}} + Job failed: Backing format cannot be used without backing file +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + === Invalid cluster size === +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 1234, 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 1234, "driver": "qcow2", "file": "node0", "size": 67108864}}} ++{"return": {}} + Job failed: Cluster size must be a power of two between 512 and 2048k +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 128, 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 128, "driver": "qcow2", "file": "node0", "size": 67108864}}} ++{"return": {}} + Job failed: Cluster size must be a power of two between 512 and 2048k +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 4194304, 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 4194304, "driver": "qcow2", "file": "node0", "size": 67108864}}} ++{"return": {}} + Job failed: Cluster size must be a power of two between 512 and 2048k +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 0, 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 0, "driver": "qcow2", "file": "node0", "size": 67108864}}} ++{"return": {}} + Job failed: Cluster size must be a power of two between 512 and 2048k +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 512, 'driver': 'qcow2', 'file': 'node0', 'size': 281474976710656}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 512, "driver": "qcow2", "file": "node0", "size": 281474976710656}}} ++{"return": {}} + Job failed: Could not resize image: Failed to grow the L1 table: File too large +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + === Invalid refcount width === +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'refcount-bits': 128, 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "refcount-bits": 128, "size": 67108864}}} ++{"return": {}} + Job failed: Refcount width must be a power of two and may not exceed 64 bits +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'refcount-bits': 0, 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "refcount-bits": 0, "size": 67108864}}} ++{"return": {}} + Job failed: Refcount width must be a power of two and may not exceed 64 bits +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'refcount-bits': 7, 'driver': 'qcow2', 'file': 'node0', 'size': 67108864}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "qcow2", "file": "node0", "refcount-bits": 7, "size": 67108864}}} ++{"return": {}} + Job failed: Refcount width must be a power of two and may not exceed 64 bits +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +diff --git a/tests/qemu-iotests/207 b/tests/qemu-iotests/207 +index d45bf72..aaad656 100755 +--- a/tests/qemu-iotests/207 ++++ b/tests/qemu-iotests/207 +@@ -28,7 +28,7 @@ iotests.verify_image_format(supported_fmts=['raw']) + iotests.verify_protocol(supported=['ssh']) + + def filter_hash(msg): +- return re.sub("'hash': '[0-9a-f]+'", "'hash': HASH", msg) ++ return re.sub('"hash": "[0-9a-f]+"', '"hash": HASH', msg) + + def blockdev_create(vm, options): + result = vm.qmp_log('blockdev-create', job_id='job0', options=options, +diff --git a/tests/qemu-iotests/207.out b/tests/qemu-iotests/207.out +index fc131a6..789b465 100644 +--- a/tests/qemu-iotests/207.out ++++ b/tests/qemu-iotests/207.out +@@ -1,9 +1,9 @@ + === Successful image creation (defaults) === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/PID-t.img', 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 4194304}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 4194304}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + image: TEST_IMG + file format: IMGFMT +@@ -16,49 +16,49 @@ virtual size: 4.0M (4194304 bytes) + + === Test host-key-check options === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/PID-t.img', 'host-key-check': {'mode': 'none'}, 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 8388608}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"mode": "none"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 8388608}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + image: TEST_IMG + file format: IMGFMT + virtual size: 8.0M (8388608 bytes) + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/PID-t.img', 'host-key-check': {'mode': 'known_hosts'}, 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 4194304}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"mode": "known_hosts"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 4194304}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + image: TEST_IMG + file format: IMGFMT + virtual size: 4.0M (4194304 bytes) + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/PID-t.img', 'host-key-check': {'hash': 'wrong', 'type': 'md5', 'mode': 'hash'}, 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 2097152}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"hash": "wrong", "mode": "hash", "type": "md5"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 2097152}}} ++{"return": {}} + Job failed: remote host key does not match host_key_check 'wrong' +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/PID-t.img', 'host-key-check': {'hash': HASH, 'type': 'md5', 'mode': 'hash'}, 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 8388608}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"hash": HASH, "mode": "hash", "type": "md5"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 8388608}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + image: TEST_IMG + file format: IMGFMT + virtual size: 8.0M (8388608 bytes) + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/PID-t.img', 'host-key-check': {'hash': 'wrong', 'type': 'sha1', 'mode': 'hash'}, 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 2097152}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"hash": "wrong", "mode": "hash", "type": "sha1"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 2097152}}} ++{"return": {}} + Job failed: remote host key does not match host_key_check 'wrong' +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/PID-t.img', 'host-key-check': {'hash': HASH, 'type': 'sha1', 'mode': 'hash'}, 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 4194304}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"hash": HASH, "mode": "hash", "type": "sha1"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 4194304}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + image: TEST_IMG + file format: IMGFMT +@@ -66,15 +66,15 @@ virtual size: 4.0M (4194304 bytes) + + === Invalid path and user === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': '/this/is/not/an/existing/path', 'host-key-check': {'mode': 'none'}, 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 4194304}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"mode": "none"}, "path": "/this/is/not/an/existing/path", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 4194304}}} ++{"return": {}} + Job failed: failed to open remote file '/this/is/not/an/existing/path': Failed opening remote file (libssh2 error code: -31) +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'ssh', 'location': {'path': 'TEST_DIR/PID-t.img', 'host-key-check': {'mode': 'none'}, 'user': 'invalid user', 'server': {'host': '127.0.0.1', 'port': '22'}}, 'size': 4194304}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"mode": "none"}, "path": "TEST_DIR/PID-t.img", "server": {"host": "127.0.0.1", "port": "22"}, "user": "invalid user"}, "size": 4194304}}} ++{"return": {}} + Job failed: failed to authenticate using publickey authentication and the identities held by your ssh-agent +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +diff --git a/tests/qemu-iotests/208.out b/tests/qemu-iotests/208.out +index 3687e9d..9ff2582 100644 +--- a/tests/qemu-iotests/208.out ++++ b/tests/qemu-iotests/208.out +@@ -1,9 +1,9 @@ + Launching VM... + Starting NBD server... +-{u'return': {}} ++{"return": {}} + Adding NBD export... +-{u'return': {}} ++{"return": {}} + Creating external snapshot... +-{u'return': {}} ++{"return": {}} + Stopping NBD server... +-{u'return': {}} ++{"return": {}} +diff --git a/tests/qemu-iotests/210.out b/tests/qemu-iotests/210.out +index 078ba54..923cb05 100644 +--- a/tests/qemu-iotests/210.out ++++ b/tests/qemu-iotests/210.out +@@ -1,16 +1,16 @@ + === Successful image creation (defaults) === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.luks'}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} +- +-{'execute': 'blockdev-add', 'arguments': {'node_name': 'imgfile', 'driver': 'file', 'filename': 'TEST_DIR/PID-t.luks'}} +-{u'return': {}} +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'key-secret': 'keysec0', 'iter-time': 10, 'driver': 'luks', 'file': 'imgfile', 'size': 134217728}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.luks", "size": 0}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} ++ ++{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.luks", "node_name": "imgfile"}} ++{"return": {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "luks", "file": "imgfile", "iter-time": 10, "key-secret": "keysec0", "size": 134217728}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + image: json:{"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_IMG"}, "key-secret": "keysec0"} + file format: IMGFMT +@@ -54,15 +54,15 @@ Format specific information: + + === Successful image creation (with non-default options) === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.luks'}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.luks", "size": 0}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'key-secret': 'keysec0', 'hash-alg': 'sha1', 'cipher-mode': 'ctr', 'cipher-alg': 'twofish-128', 'file': {'driver': 'file', 'filename': 'TEST_DIR/PID-t.luks'}, 'iter-time': 10, 'ivgen-alg': 'plain64', 'ivgen-hash-alg': 'md5', 'driver': 'luks', 'size': 67108864}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cipher-alg": "twofish-128", "cipher-mode": "ctr", "driver": "luks", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.luks"}, "hash-alg": "sha1", "iter-time": 10, "ivgen-alg": "plain64", "ivgen-hash-alg": "md5", "key-secret": "keysec0", "size": 67108864}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + image: json:{"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_IMG"}, "key-secret": "keysec0"} + file format: IMGFMT +@@ -106,18 +106,18 @@ Format specific information: + + === Invalid BlockdevRef === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'luks', 'file': "this doesn't exist", 'size': 67108864}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "luks", "file": "this doesn't exist", "size": 67108864}}} ++{"return": {}} + Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exist +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + === Zero size === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'key-secret': 'keysec0', 'iter-time': 10, 'driver': 'luks', 'file': 'node0', 'size': 0}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "luks", "file": "node0", "iter-time": 10, "key-secret": "keysec0", "size": 0}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + image: json:{"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_IMG"}, "key-secret": "keysec0"} + file format: IMGFMT +@@ -161,34 +161,34 @@ Format specific information: + + === Invalid sizes === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'key-secret': 'keysec0', 'driver': 'luks', 'file': 'node0', 'size': 18446744073709551104L}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "luks", "file": "node0", "key-secret": "keysec0", "size": 18446744073709551104}}} ++{"return": {}} + Job failed: The requested file size is too large +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'key-secret': 'keysec0', 'driver': 'luks', 'file': 'node0', 'size': 9223372036854775808L}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "luks", "file": "node0", "key-secret": "keysec0", "size": 9223372036854775808}}} ++{"return": {}} + Job failed: The requested file size is too large +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'key-secret': 'keysec0', 'driver': 'luks', 'file': 'node0', 'size': 9223372036854775296}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "luks", "file": "node0", "key-secret": "keysec0", "size": 9223372036854775296}}} ++{"return": {}} + Job failed: The requested file size is too large +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + === Resize image with invalid sizes === + +-{'execute': 'block_resize', 'arguments': {'size': 9223372036854775296, 'node_name': 'node1'}} +-{u'error': {u'class': u'GenericError', u'desc': u'The requested file size is too large'}} +-{'execute': 'block_resize', 'arguments': {'size': 9223372036854775808L, 'node_name': 'node1'}} +-{u'error': {u'class': u'GenericError', u'desc': u"Invalid parameter type for 'size', expected: integer"}} +-{'execute': 'block_resize', 'arguments': {'size': 18446744073709551104L, 'node_name': 'node1'}} +-{u'error': {u'class': u'GenericError', u'desc': u"Invalid parameter type for 'size', expected: integer"}} +-{'execute': 'block_resize', 'arguments': {'size': -9223372036854775808, 'node_name': 'node1'}} +-{u'error': {u'class': u'GenericError', u'desc': u"Parameter 'size' expects a >0 size"}} ++{"execute": "block_resize", "arguments": {"node_name": "node1", "size": 9223372036854775296}} ++{"error": {"class": "GenericError", "desc": "The requested file size is too large"}} ++{"execute": "block_resize", "arguments": {"node_name": "node1", "size": 9223372036854775808}} ++{"error": {"class": "GenericError", "desc": "Invalid parameter type for 'size', expected: integer"}} ++{"execute": "block_resize", "arguments": {"node_name": "node1", "size": 18446744073709551104}} ++{"error": {"class": "GenericError", "desc": "Invalid parameter type for 'size', expected: integer"}} ++{"execute": "block_resize", "arguments": {"node_name": "node1", "size": -9223372036854775808}} ++{"error": {"class": "GenericError", "desc": "Parameter 'size' expects a >0 size"}} + image: json:{"driver": "IMGFMT", "file": {"driver": "file", "filename": "TEST_IMG"}, "key-secret": "keysec0"} + file format: IMGFMT + virtual size: 0 (0 bytes) +diff --git a/tests/qemu-iotests/211.out b/tests/qemu-iotests/211.out +index 6feaea3..eebb0ea 100644 +--- a/tests/qemu-iotests/211.out ++++ b/tests/qemu-iotests/211.out +@@ -1,16 +1,16 @@ + === Successful image creation (defaults) === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.vdi'}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} +- +-{'execute': 'blockdev-add', 'arguments': {'node_name': 'imgfile', 'driver': 'file', 'filename': 'TEST_DIR/PID-t.vdi'}} +-{u'return': {}} +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vdi', 'file': 'imgfile', 'size': 134217728}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi", "size": 0}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} ++ ++{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi", "node_name": "imgfile"}} ++{"return": {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vdi", "file": "imgfile", "size": 134217728}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + image: TEST_IMG + file format: IMGFMT +@@ -21,15 +21,15 @@ cluster_size: 1048576 + + === Successful image creation (explicit defaults) === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.vdi'}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi", "size": 0}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'preallocation': 'off', 'driver': 'vdi', 'file': {'driver': 'file', 'filename': 'TEST_DIR/PID-t.vdi'}, 'size': 67108864}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vdi", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi"}, "preallocation": "off", "size": 67108864}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + image: TEST_IMG + file format: IMGFMT +@@ -40,15 +40,15 @@ cluster_size: 1048576 + + === Successful image creation (with non-default options) === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.vdi'}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi", "size": 0}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'preallocation': 'metadata', 'driver': 'vdi', 'file': {'driver': 'file', 'filename': 'TEST_DIR/PID-t.vdi'}, 'size': 33554432}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vdi", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vdi"}, "preallocation": "metadata", "size": 33554432}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + image: TEST_IMG + file format: IMGFMT +@@ -60,18 +60,18 @@ cluster_size: 1048576 + + === Invalid BlockdevRef === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vdi', 'file': "this doesn't exist", 'size': 33554432}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vdi", "file": "this doesn't exist", "size": 33554432}}} ++{"return": {}} + Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exist +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + === Zero size === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vdi', 'file': 'node0', 'size': 0}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vdi", "file": "node0", "size": 0}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + image: TEST_IMG + file format: IMGFMT +@@ -80,10 +80,10 @@ cluster_size: 1048576 + + === Maximum size === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vdi', 'file': 'node0', 'size': 562949819203584}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vdi", "file": "node0", "size": 562949819203584}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + image: TEST_IMG + file format: IMGFMT +@@ -92,21 +92,21 @@ cluster_size: 1048576 + + === Invalid sizes === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vdi', 'file': 'node0', 'size': 18446744073709551104L}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vdi", "file": "node0", "size": 18446744073709551104}}} ++{"return": {}} + Job failed: Unsupported VDI image size (size is 0xfffffffffffffe00, max supported is 0x1fffff8000000) +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vdi', 'file': 'node0', 'size': 9223372036854775808L}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vdi", "file": "node0", "size": 9223372036854775808}}} ++{"return": {}} + Job failed: Unsupported VDI image size (size is 0x8000000000000000, max supported is 0x1fffff8000000) +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vdi', 'file': 'node0', 'size': 562949819203585}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vdi", "file": "node0", "size": 562949819203585}}} ++{"return": {}} + Job failed: Unsupported VDI image size (size is 0x1fffff8000001, max supported is 0x1fffff8000000) +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +diff --git a/tests/qemu-iotests/212.out b/tests/qemu-iotests/212.out +index 9150da7..01da467 100644 +--- a/tests/qemu-iotests/212.out ++++ b/tests/qemu-iotests/212.out +@@ -1,16 +1,16 @@ + === Successful image creation (defaults) === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.parallels'}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} +- +-{'execute': 'blockdev-add', 'arguments': {'node_name': 'imgfile', 'driver': 'file', 'filename': 'TEST_DIR/PID-t.parallels'}} +-{u'return': {}} +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'parallels', 'file': 'imgfile', 'size': 134217728}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels", "size": 0}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} ++ ++{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels", "node_name": "imgfile"}} ++{"return": {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "parallels", "file": "imgfile", "size": 134217728}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + image: TEST_IMG + file format: IMGFMT +@@ -18,15 +18,15 @@ virtual size: 128M (134217728 bytes) + + === Successful image creation (explicit defaults) === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.parallels'}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels", "size": 0}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 1048576, 'driver': 'parallels', 'file': {'driver': 'file', 'filename': 'TEST_DIR/PID-t.parallels'}, 'size': 67108864}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 1048576, "driver": "parallels", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels"}, "size": 67108864}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + image: TEST_IMG + file format: IMGFMT +@@ -34,15 +34,15 @@ virtual size: 64M (67108864 bytes) + + === Successful image creation (with non-default options) === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.parallels'}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels", "size": 0}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 65536, 'driver': 'parallels', 'file': {'driver': 'file', 'filename': 'TEST_DIR/PID-t.parallels'}, 'size': 33554432}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 65536, "driver": "parallels", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.parallels"}, "size": 33554432}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + image: TEST_IMG + file format: IMGFMT +@@ -50,18 +50,18 @@ virtual size: 32M (33554432 bytes) + + === Invalid BlockdevRef === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'parallels', 'file': "this doesn't exist", 'size': 33554432}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "parallels", "file": "this doesn't exist", "size": 33554432}}} ++{"return": {}} + Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exist +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + === Zero size === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'parallels', 'file': 'node0', 'size': 0}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 0}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + image: TEST_IMG + file format: IMGFMT +@@ -69,10 +69,10 @@ virtual size: 0 (0 bytes) + + === Maximum size === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'parallels', 'file': 'node0', 'size': 4503599627369984}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 4503599627369984}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + image: TEST_IMG + file format: IMGFMT +@@ -80,77 +80,77 @@ virtual size: 4096T (4503599627369984 bytes) + + === Invalid sizes === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'parallels', 'file': 'node0', 'size': 1234}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 1234}}} ++{"return": {}} + Job failed: Image size must be a multiple of 512 bytes +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'parallels', 'file': 'node0', 'size': 18446744073709551104L}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 18446744073709551104}}} ++{"return": {}} + Job failed: Image size is too large for this cluster size +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'parallels', 'file': 'node0', 'size': 9223372036854775808L}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 9223372036854775808}}} ++{"return": {}} + Job failed: Image size is too large for this cluster size +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'parallels', 'file': 'node0', 'size': 9223372036854775296}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 9223372036854775296}}} ++{"return": {}} + Job failed: Image size is too large for this cluster size +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'parallels', 'file': 'node0', 'size': 4503599627370497}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "parallels", "file": "node0", "size": 4503599627370497}}} ++{"return": {}} + Job failed: Image size is too large for this cluster size +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + === Invalid cluster size === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 1234, 'driver': 'parallels', 'file': 'node0', 'size': 67108864}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 1234, "driver": "parallels", "file": "node0", "size": 67108864}}} ++{"return": {}} + Job failed: Cluster size must be a multiple of 512 bytes +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 128, 'driver': 'parallels', 'file': 'node0', 'size': 67108864}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 128, "driver": "parallels", "file": "node0", "size": 67108864}}} ++{"return": {}} + Job failed: Cluster size must be a multiple of 512 bytes +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 4294967296, 'driver': 'parallels', 'file': 'node0', 'size': 67108864}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 4294967296, "driver": "parallels", "file": "node0", "size": 67108864}}} ++{"return": {}} + Job failed: Cluster size is too large +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 9223372036854775808L, 'driver': 'parallels', 'file': 'node0', 'size': 67108864}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 9223372036854775808, "driver": "parallels", "file": "node0", "size": 67108864}}} ++{"return": {}} + Job failed: Cluster size is too large +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 18446744073709551104L, 'driver': 'parallels', 'file': 'node0', 'size': 67108864}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 18446744073709551104, "driver": "parallels", "file": "node0", "size": 67108864}}} ++{"return": {}} + Job failed: Cluster size is too large +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 0, 'driver': 'parallels', 'file': 'node0', 'size': 67108864}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 0, "driver": "parallels", "file": "node0", "size": 67108864}}} ++{"return": {}} + Job failed: Image size is too large for this cluster size +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'cluster-size': 512, 'driver': 'parallels', 'file': 'node0', 'size': 281474976710656}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"cluster-size": 512, "driver": "parallels", "file": "node0", "size": 281474976710656}}} ++{"return": {}} + Job failed: Image size is too large for this cluster size +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +diff --git a/tests/qemu-iotests/213.out b/tests/qemu-iotests/213.out +index e1dcd47..0c9d65b 100644 +--- a/tests/qemu-iotests/213.out ++++ b/tests/qemu-iotests/213.out +@@ -1,16 +1,16 @@ + === Successful image creation (defaults) === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.vhdx'}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} +- +-{'execute': 'blockdev-add', 'arguments': {'node_name': 'imgfile', 'driver': 'file', 'filename': 'TEST_DIR/PID-t.vhdx'}} +-{u'return': {}} +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'file': 'imgfile', 'size': 134217728}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx", "size": 0}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} ++ ++{"execute": "blockdev-add", "arguments": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx", "node_name": "imgfile"}} ++{"return": {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "imgfile", "size": 134217728}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + image: TEST_IMG + file format: IMGFMT +@@ -19,15 +19,15 @@ cluster_size: 8388608 + + === Successful image creation (explicit defaults) === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.vhdx'}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx", "size": 0}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'block-size': 8388608, 'driver': 'vhdx', 'subformat': 'dynamic', 'log-size': 1048576, 'file': {'driver': 'file', 'filename': 'TEST_DIR/PID-t.vhdx'}, 'block-state-zero': True, 'size': 67108864}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"block-size": 8388608, "block-state-zero": true, "driver": "vhdx", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx"}, "log-size": 1048576, "size": 67108864, "subformat": "dynamic"}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + image: TEST_IMG + file format: IMGFMT +@@ -36,15 +36,15 @@ cluster_size: 8388608 + + === Successful image creation (with non-default options) === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'size': 0, 'driver': 'file', 'filename': 'TEST_DIR/PID-t.vhdx'}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx", "size": 0}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'block-size': 268435456, 'driver': 'vhdx', 'subformat': 'fixed', 'log-size': 8388608, 'file': {'driver': 'file', 'filename': 'TEST_DIR/PID-t.vhdx'}, 'block-state-zero': False, 'size': 33554432}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"block-size": 268435456, "block-state-zero": false, "driver": "vhdx", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.vhdx"}, "log-size": 8388608, "size": 33554432, "subformat": "fixed"}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + image: TEST_IMG + file format: IMGFMT +@@ -53,18 +53,18 @@ cluster_size: 268435456 + + === Invalid BlockdevRef === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'file': "this doesn't exist", 'size': 33554432}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "this doesn't exist", "size": 33554432}}} ++{"return": {}} + Job failed: Cannot find device=this doesn't exist nor node_name=this doesn't exist +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + === Zero size === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'file': 'node0', 'size': 0}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 0}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + image: TEST_IMG + file format: IMGFMT +@@ -73,10 +73,10 @@ cluster_size: 8388608 + + === Maximum size === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'file': 'node0', 'size': 70368744177664}}} +-{u'return': {}} +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 70368744177664}}} ++{"return": {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + image: TEST_IMG + file format: IMGFMT +@@ -85,85 +85,85 @@ cluster_size: 67108864 + + === Invalid sizes === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'file': 'node0', 'size': 18446744073709551104L}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 18446744073709551104}}} ++{"return": {}} + Job failed: Image size too large; max of 64TB +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'file': 'node0', 'size': 9223372036854775808L}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 9223372036854775808}}} ++{"return": {}} + Job failed: Image size too large; max of 64TB +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'file': 'node0', 'size': 9223372036854775296}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 9223372036854775296}}} ++{"return": {}} + Job failed: Image size too large; max of 64TB +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'file': 'node0', 'size': 70368744177665}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "size": 70368744177665}}} ++{"return": {}} + Job failed: Image size too large; max of 64TB +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + === Invalid block size === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'block-size': 1234567, 'file': 'node0', 'size': 67108864}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"block-size": 1234567, "driver": "vhdx", "file": "node0", "size": 67108864}}} ++{"return": {}} + Job failed: Block size must be a multiple of 1 MB +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'block-size': 128, 'file': 'node0', 'size': 67108864}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"block-size": 128, "driver": "vhdx", "file": "node0", "size": 67108864}}} ++{"return": {}} + Job failed: Block size must be a multiple of 1 MB +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'block-size': 3145728, 'file': 'node0', 'size': 67108864}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"block-size": 3145728, "driver": "vhdx", "file": "node0", "size": 67108864}}} ++{"return": {}} + Job failed: Block size must be a power of two +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'block-size': 536870912, 'file': 'node0', 'size': 67108864}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"block-size": 536870912, "driver": "vhdx", "file": "node0", "size": 67108864}}} ++{"return": {}} + Job failed: Block size must not exceed 268435456 +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'driver': 'vhdx', 'block-size': 0, 'file': 'node0', 'size': 67108864}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"block-size": 0, "driver": "vhdx", "file": "node0", "size": 67108864}}} ++{"return": {}} + Job failed: Block size must be a multiple of 1 MB +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + + === Invalid log size === + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'log-size': 1234567, 'driver': 'vhdx', 'file': 'node0', 'size': 67108864}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "log-size": 1234567, "size": 67108864}}} ++{"return": {}} + Job failed: Log size must be a multiple of 1 MB +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'log-size': 128, 'driver': 'vhdx', 'file': 'node0', 'size': 67108864}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "log-size": 128, "size": 67108864}}} ++{"return": {}} + Job failed: Log size must be a multiple of 1 MB +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'log-size': 4294967296, 'driver': 'vhdx', 'file': 'node0', 'size': 67108864}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "log-size": 4294967296, "size": 67108864}}} ++{"return": {}} + Job failed: Log size must be smaller than 4 GB +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +-{'execute': 'blockdev-create', 'arguments': {'job_id': 'job0', 'options': {'log-size': 0, 'driver': 'vhdx', 'file': 'node0', 'size': 67108864}}} +-{u'return': {}} ++{"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "vhdx", "file": "node0", "log-size": 0, "size": 67108864}}} ++{"return": {}} + Job failed: Log size must be a multiple of 1 MB +-{'execute': 'job-dismiss', 'arguments': {'id': 'job0'}} +-{u'return': {}} ++{"execute": "job-dismiss", "arguments": {"id": "job0"}} ++{"return": {}} + +diff --git a/tests/qemu-iotests/216.out b/tests/qemu-iotests/216.out +index 45ea857..a70aa5c 100644 +--- a/tests/qemu-iotests/216.out ++++ b/tests/qemu-iotests/216.out +@@ -7,8 +7,8 @@ Done + + --- Doing COR --- + +-{u'return': {}} +-{u'return': u''} ++{"return": {}} ++{"return": ""} + + --- Checking COR result --- + +diff --git a/tests/qemu-iotests/218.out b/tests/qemu-iotests/218.out +index 7dbf78e..825a657 100644 +--- a/tests/qemu-iotests/218.out ++++ b/tests/qemu-iotests/218.out +@@ -4,27 +4,27 @@ + --- force=false --- + + Cancelling job +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'device': u'mirror', u'type': u'mirror', u'speed': 65536, u'len': 1048576, u'offset': 65536}, u'event': u'BLOCK_JOB_CANCELLED'} ++{"return": {}} ++{"data": {"device": "mirror", "len": 1048576, "offset": 65536, "speed": 65536, "type": "mirror"}, "event": "BLOCK_JOB_CANCELLED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} + + --- force=true --- + + Cancelling job +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'device': u'mirror', u'type': u'mirror', u'speed': 65536, u'len': 1048576, u'offset': 65536}, u'event': u'BLOCK_JOB_CANCELLED'} ++{"return": {}} ++{"data": {"device": "mirror", "len": 1048576, "offset": 65536, "speed": 65536, "type": "mirror"}, "event": "BLOCK_JOB_CANCELLED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} + + === Cancel mirror job after convergence === + + --- force=false --- + +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'device': u'mirror', u'type': u'mirror', u'speed': 0, u'len': 1048576, u'offset': 1048576}, u'event': u'BLOCK_JOB_READY'} ++{"data": {"device": "mirror", "len": 1048576, "offset": 1048576, "speed": 0, "type": "mirror"}, "event": "BLOCK_JOB_READY", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} + Cancelling job +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'device': u'mirror', u'type': u'mirror', u'speed': 0, u'len': 1048576, u'offset': 1048576}, u'event': u'BLOCK_JOB_COMPLETED'} ++{"return": {}} ++{"data": {"device": "mirror", "len": 1048576, "offset": 1048576, "speed": 0, "type": "mirror"}, "event": "BLOCK_JOB_COMPLETED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} + + --- force=true --- + +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'device': u'mirror', u'type': u'mirror', u'speed': 0, u'len': 1048576, u'offset': 1048576}, u'event': u'BLOCK_JOB_READY'} ++{"data": {"device": "mirror", "len": 1048576, "offset": 1048576, "speed": 0, "type": "mirror"}, "event": "BLOCK_JOB_READY", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} + Cancelling job +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'device': u'mirror', u'type': u'mirror', u'speed': 0, u'len': 1048576, u'offset': 1048576}, u'event': u'BLOCK_JOB_CANCELLED'} ++{"return": {}} ++{"data": {"device": "mirror", "len": 1048576, "offset": 1048576, "speed": 0, "type": "mirror"}, "event": "BLOCK_JOB_CANCELLED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} +diff --git a/tests/qemu-iotests/219.out b/tests/qemu-iotests/219.out +index 6dc07bc..8ebd3fe 100644 +--- a/tests/qemu-iotests/219.out ++++ b/tests/qemu-iotests/219.out +@@ -2,326 +2,326 @@ Launching VM... + + + Starting block job: drive-mirror (auto-finalize: True; auto-dismiss: True) +-{u'return': {}} +-{u'return': [{u'status': u'running', u'current-progress': 'FILTERED', u'total-progress': 'FILTERED', u'id': u'job0', u'type': u'mirror'}]} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'created', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} ++{"return": {}} ++{"return": [{"current-progress": "FILTERED", "id": "job0", "status": "running", "total-progress": "FILTERED", "type": "mirror"}]} ++{"data": {"id": "job0", "status": "created"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} + + Pause/resume in RUNNING + === Testing block-job-pause/block-job-resume === +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'paused', u'current-progress': 65536, u'total-progress': 4194304, u'id': u'job0', u'type': u'mirror'}]} +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'running', u'current-progress': 131072, u'total-progress': 4194304, u'id': u'job0', u'type': u'mirror'}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 65536, "id": "job0", "status": "paused", "total-progress": 4194304, "type": "mirror"}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 131072, "id": "job0", "status": "running", "total-progress": 4194304, "type": "mirror"}]} + === Testing block-job-pause/job-resume === +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'paused', u'current-progress': 131072, u'total-progress': 4194304, u'id': u'job0', u'type': u'mirror'}]} +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'running', u'current-progress': 196608, u'total-progress': 4194304, u'id': u'job0', u'type': u'mirror'}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 131072, "id": "job0", "status": "paused", "total-progress": 4194304, "type": "mirror"}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 196608, "id": "job0", "status": "running", "total-progress": 4194304, "type": "mirror"}]} + === Testing job-pause/block-job-resume === +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'paused', u'current-progress': 196608, u'total-progress': 4194304, u'id': u'job0', u'type': u'mirror'}]} +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'running', u'current-progress': 262144, u'total-progress': 4194304, u'id': u'job0', u'type': u'mirror'}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 196608, "id": "job0", "status": "paused", "total-progress": 4194304, "type": "mirror"}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 262144, "id": "job0", "status": "running", "total-progress": 4194304, "type": "mirror"}]} + === Testing job-pause/job-resume === +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'paused', u'current-progress': 262144, u'total-progress': 4194304, u'id': u'job0', u'type': u'mirror'}]} +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'running', u'current-progress': 327680, u'total-progress': 4194304, u'id': u'job0', u'type': u'mirror'}]} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'complete'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'finalize'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'dismiss'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'complete'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'finalize'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'dismiss'"}} +-{u'return': {}} ++{"return": {}} ++{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 262144, "id": "job0", "status": "paused", "total-progress": 4194304, "type": "mirror"}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 327680, "id": "job0", "status": "running", "total-progress": 4194304, "type": "mirror"}]} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'complete'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'finalize'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'dismiss'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'complete'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'finalize'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'dismiss'"}} ++{"return": {}} + + Waiting for READY state... +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'ready', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'ready', u'current-progress': 4194304, u'total-progress': 4194304, u'id': u'job0', u'type': u'mirror'}]} ++{"data": {"id": "job0", "status": "ready"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 4194304, "id": "job0", "status": "ready", "total-progress": 4194304, "type": "mirror"}]} + + Pause/resume in READY + === Testing block-job-pause/block-job-resume === +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'standby', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'standby', u'current-progress': 4194304, u'total-progress': 4194304, u'id': u'job0', u'type': u'mirror'}]} +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'ready', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'ready', u'current-progress': 4194304, u'total-progress': 4194304, u'id': u'job0', u'type': u'mirror'}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "standby"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 4194304, "id": "job0", "status": "standby", "total-progress": 4194304, "type": "mirror"}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "ready"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 4194304, "id": "job0", "status": "ready", "total-progress": 4194304, "type": "mirror"}]} + === Testing block-job-pause/job-resume === +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'standby', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'standby', u'current-progress': 4194304, u'total-progress': 4194304, u'id': u'job0', u'type': u'mirror'}]} +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'ready', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'ready', u'current-progress': 4194304, u'total-progress': 4194304, u'id': u'job0', u'type': u'mirror'}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "standby"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 4194304, "id": "job0", "status": "standby", "total-progress": 4194304, "type": "mirror"}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "ready"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 4194304, "id": "job0", "status": "ready", "total-progress": 4194304, "type": "mirror"}]} + === Testing job-pause/block-job-resume === +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'standby', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'standby', u'current-progress': 4194304, u'total-progress': 4194304, u'id': u'job0', u'type': u'mirror'}]} +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'ready', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'ready', u'current-progress': 4194304, u'total-progress': 4194304, u'id': u'job0', u'type': u'mirror'}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "standby"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 4194304, "id": "job0", "status": "standby", "total-progress": 4194304, "type": "mirror"}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "ready"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 4194304, "id": "job0", "status": "ready", "total-progress": 4194304, "type": "mirror"}]} + === Testing job-pause/job-resume === +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'standby', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'standby', u'current-progress': 4194304, u'total-progress': 4194304, u'id': u'job0', u'type': u'mirror'}]} +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'ready', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'ready', u'current-progress': 4194304, u'total-progress': 4194304, u'id': u'job0', u'type': u'mirror'}]} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'ready' cannot accept command verb 'finalize'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'ready' cannot accept command verb 'dismiss'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'ready' cannot accept command verb 'finalize'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'ready' cannot accept command verb 'dismiss'"}} +-{u'return': {}} ++{"return": {}} ++{"data": {"id": "job0", "status": "standby"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 4194304, "id": "job0", "status": "standby", "total-progress": 4194304, "type": "mirror"}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "ready"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 4194304, "id": "job0", "status": "ready", "total-progress": 4194304, "type": "mirror"}]} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'ready' cannot accept command verb 'finalize'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'ready' cannot accept command verb 'dismiss'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'ready' cannot accept command verb 'finalize'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'ready' cannot accept command verb 'dismiss'"}} ++{"return": {}} + + Waiting for PENDING state... +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'waiting', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'pending', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'concluded', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'null', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': []} ++{"data": {"id": "job0", "status": "waiting"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"data": {"id": "job0", "status": "pending"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"data": {"id": "job0", "status": "concluded"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"data": {"id": "job0", "status": "null"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": []} + + + Starting block job: drive-backup (auto-finalize: True; auto-dismiss: True) +-{u'return': {}} +-{u'return': [{u'status': u'running', u'current-progress': 'FILTERED', u'total-progress': 'FILTERED', u'id': u'job0', u'type': u'backup'}]} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'created', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} ++{"return": {}} ++{"return": [{"current-progress": "FILTERED", "id": "job0", "status": "running", "total-progress": "FILTERED", "type": "backup"}]} ++{"data": {"id": "job0", "status": "created"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} + + Pause/resume in RUNNING + === Testing block-job-pause/block-job-resume === +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'paused', u'current-progress': 65536, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'running', u'current-progress': 131072, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 65536, "id": "job0", "status": "paused", "total-progress": 4194304, "type": "backup"}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 131072, "id": "job0", "status": "running", "total-progress": 4194304, "type": "backup"}]} + === Testing block-job-pause/job-resume === +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'paused', u'current-progress': 131072, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'running', u'current-progress': 196608, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 131072, "id": "job0", "status": "paused", "total-progress": 4194304, "type": "backup"}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 196608, "id": "job0", "status": "running", "total-progress": 4194304, "type": "backup"}]} + === Testing job-pause/block-job-resume === +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'paused', u'current-progress': 196608, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'running', u'current-progress': 262144, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 196608, "id": "job0", "status": "paused", "total-progress": 4194304, "type": "backup"}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 262144, "id": "job0", "status": "running", "total-progress": 4194304, "type": "backup"}]} + === Testing job-pause/job-resume === +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'paused', u'current-progress': 262144, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'running', u'current-progress': 327680, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'complete'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'finalize'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'dismiss'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'complete'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'finalize'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'dismiss'"}} +-{u'return': {}} ++{"return": {}} ++{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 262144, "id": "job0", "status": "paused", "total-progress": 4194304, "type": "backup"}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 327680, "id": "job0", "status": "running", "total-progress": 4194304, "type": "backup"}]} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'complete'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'finalize'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'dismiss'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'complete'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'finalize'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'dismiss'"}} ++{"return": {}} + + Waiting for PENDING state... +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'waiting', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'pending', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'concluded', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'null', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': []} ++{"data": {"id": "job0", "status": "waiting"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"data": {"id": "job0", "status": "pending"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"data": {"id": "job0", "status": "concluded"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"data": {"id": "job0", "status": "null"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": []} + + + Starting block job: drive-backup (auto-finalize: True; auto-dismiss: False) +-{u'return': {}} +-{u'return': [{u'status': u'running', u'current-progress': 'FILTERED', u'total-progress': 'FILTERED', u'id': u'job0', u'type': u'backup'}]} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'created', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} ++{"return": {}} ++{"return": [{"current-progress": "FILTERED", "id": "job0", "status": "running", "total-progress": "FILTERED", "type": "backup"}]} ++{"data": {"id": "job0", "status": "created"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} + + Pause/resume in RUNNING + === Testing block-job-pause/block-job-resume === +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'paused', u'current-progress': 65536, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'running', u'current-progress': 131072, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 65536, "id": "job0", "status": "paused", "total-progress": 4194304, "type": "backup"}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 131072, "id": "job0", "status": "running", "total-progress": 4194304, "type": "backup"}]} + === Testing block-job-pause/job-resume === +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'paused', u'current-progress': 131072, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'running', u'current-progress': 196608, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 131072, "id": "job0", "status": "paused", "total-progress": 4194304, "type": "backup"}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 196608, "id": "job0", "status": "running", "total-progress": 4194304, "type": "backup"}]} + === Testing job-pause/block-job-resume === +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'paused', u'current-progress': 196608, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'running', u'current-progress': 262144, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 196608, "id": "job0", "status": "paused", "total-progress": 4194304, "type": "backup"}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 262144, "id": "job0", "status": "running", "total-progress": 4194304, "type": "backup"}]} + === Testing job-pause/job-resume === +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'paused', u'current-progress': 262144, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'running', u'current-progress': 327680, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'complete'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'finalize'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'dismiss'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'complete'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'finalize'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'dismiss'"}} +-{u'return': {}} ++{"return": {}} ++{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 262144, "id": "job0", "status": "paused", "total-progress": 4194304, "type": "backup"}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 327680, "id": "job0", "status": "running", "total-progress": 4194304, "type": "backup"}]} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'complete'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'finalize'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'dismiss'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'complete'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'finalize'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'dismiss'"}} ++{"return": {}} + + Waiting for PENDING state... +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'waiting', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'pending', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'concluded', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'concluded', u'current-progress': 4194304, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'concluded' cannot accept command verb 'pause'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'concluded' cannot accept command verb 'complete'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'concluded' cannot accept command verb 'finalize'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'concluded' cannot accept command verb 'pause'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'concluded' cannot accept command verb 'complete'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'concluded' cannot accept command verb 'finalize'"}} +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'null', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': []} ++{"data": {"id": "job0", "status": "waiting"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"data": {"id": "job0", "status": "pending"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"data": {"id": "job0", "status": "concluded"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 4194304, "id": "job0", "status": "concluded", "total-progress": 4194304, "type": "backup"}]} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'concluded' cannot accept command verb 'pause'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'concluded' cannot accept command verb 'complete'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'concluded' cannot accept command verb 'finalize'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'concluded' cannot accept command verb 'pause'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'concluded' cannot accept command verb 'complete'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'concluded' cannot accept command verb 'finalize'"}} ++{"return": {}} ++{"data": {"id": "job0", "status": "null"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": []} + + + Starting block job: drive-backup (auto-finalize: False; auto-dismiss: True) +-{u'return': {}} +-{u'return': [{u'status': u'running', u'current-progress': 'FILTERED', u'total-progress': 'FILTERED', u'id': u'job0', u'type': u'backup'}]} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'created', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} ++{"return": {}} ++{"return": [{"current-progress": "FILTERED", "id": "job0", "status": "running", "total-progress": "FILTERED", "type": "backup"}]} ++{"data": {"id": "job0", "status": "created"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} + + Pause/resume in RUNNING + === Testing block-job-pause/block-job-resume === +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'paused', u'current-progress': 65536, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'running', u'current-progress': 131072, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 65536, "id": "job0", "status": "paused", "total-progress": 4194304, "type": "backup"}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 131072, "id": "job0", "status": "running", "total-progress": 4194304, "type": "backup"}]} + === Testing block-job-pause/job-resume === +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'paused', u'current-progress': 131072, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'running', u'current-progress': 196608, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 131072, "id": "job0", "status": "paused", "total-progress": 4194304, "type": "backup"}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 196608, "id": "job0", "status": "running", "total-progress": 4194304, "type": "backup"}]} + === Testing job-pause/block-job-resume === +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'paused', u'current-progress': 196608, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'running', u'current-progress': 262144, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 196608, "id": "job0", "status": "paused", "total-progress": 4194304, "type": "backup"}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 262144, "id": "job0", "status": "running", "total-progress": 4194304, "type": "backup"}]} + === Testing job-pause/job-resume === +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'paused', u'current-progress': 262144, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'running', u'current-progress': 327680, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'complete'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'finalize'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'dismiss'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'complete'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'finalize'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'dismiss'"}} +-{u'return': {}} ++{"return": {}} ++{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 262144, "id": "job0", "status": "paused", "total-progress": 4194304, "type": "backup"}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 327680, "id": "job0", "status": "running", "total-progress": 4194304, "type": "backup"}]} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'complete'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'finalize'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'dismiss'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'complete'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'finalize'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'dismiss'"}} ++{"return": {}} + + Waiting for PENDING state... +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'waiting', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'pending', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'pending', u'current-progress': 4194304, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'pending' cannot accept command verb 'pause'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'pending' cannot accept command verb 'complete'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'pending' cannot accept command verb 'dismiss'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'pending' cannot accept command verb 'pause'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'pending' cannot accept command verb 'complete'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'pending' cannot accept command verb 'dismiss'"}} +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'concluded', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'null', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': []} ++{"data": {"id": "job0", "status": "waiting"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"data": {"id": "job0", "status": "pending"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 4194304, "id": "job0", "status": "pending", "total-progress": 4194304, "type": "backup"}]} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'pending' cannot accept command verb 'pause'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'pending' cannot accept command verb 'complete'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'pending' cannot accept command verb 'dismiss'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'pending' cannot accept command verb 'pause'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'pending' cannot accept command verb 'complete'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'pending' cannot accept command verb 'dismiss'"}} ++{"return": {}} ++{"data": {"id": "job0", "status": "concluded"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"data": {"id": "job0", "status": "null"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": []} + + + Starting block job: drive-backup (auto-finalize: False; auto-dismiss: False) +-{u'return': {}} +-{u'return': [{u'status': u'running', u'current-progress': 'FILTERED', u'total-progress': 'FILTERED', u'id': u'job0', u'type': u'backup'}]} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'created', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} ++{"return": {}} ++{"return": [{"current-progress": "FILTERED", "id": "job0", "status": "running", "total-progress": "FILTERED", "type": "backup"}]} ++{"data": {"id": "job0", "status": "created"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} + + Pause/resume in RUNNING + === Testing block-job-pause/block-job-resume === +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'paused', u'current-progress': 65536, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'running', u'current-progress': 131072, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 65536, "id": "job0", "status": "paused", "total-progress": 4194304, "type": "backup"}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 131072, "id": "job0", "status": "running", "total-progress": 4194304, "type": "backup"}]} + === Testing block-job-pause/job-resume === +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'paused', u'current-progress': 131072, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'running', u'current-progress': 196608, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 131072, "id": "job0", "status": "paused", "total-progress": 4194304, "type": "backup"}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 196608, "id": "job0", "status": "running", "total-progress": 4194304, "type": "backup"}]} + === Testing job-pause/block-job-resume === +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'paused', u'current-progress': 196608, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'running', u'current-progress': 262144, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 196608, "id": "job0", "status": "paused", "total-progress": 4194304, "type": "backup"}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 262144, "id": "job0", "status": "running", "total-progress": 4194304, "type": "backup"}]} + === Testing job-pause/job-resume === +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'paused', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'paused', u'current-progress': 262144, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'running', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'running', u'current-progress': 327680, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'complete'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'finalize'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'dismiss'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'complete'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'finalize'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'running' cannot accept command verb 'dismiss'"}} +-{u'return': {}} ++{"return": {}} ++{"data": {"id": "job0", "status": "paused"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 262144, "id": "job0", "status": "paused", "total-progress": 4194304, "type": "backup"}]} ++{"return": {}} ++{"data": {"id": "job0", "status": "running"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 327680, "id": "job0", "status": "running", "total-progress": 4194304, "type": "backup"}]} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'complete'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'finalize'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'dismiss'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'complete'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'finalize'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'running' cannot accept command verb 'dismiss'"}} ++{"return": {}} + + Waiting for PENDING state... +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'waiting', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'pending', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'pending', u'current-progress': 4194304, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'pending' cannot accept command verb 'pause'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'pending' cannot accept command verb 'complete'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'pending' cannot accept command verb 'dismiss'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'pending' cannot accept command verb 'pause'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'pending' cannot accept command verb 'complete'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'pending' cannot accept command verb 'dismiss'"}} +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'concluded', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': [{u'status': u'concluded', u'current-progress': 4194304, u'total-progress': 4194304, u'id': u'job0', u'type': u'backup'}]} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'concluded' cannot accept command verb 'pause'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'concluded' cannot accept command verb 'complete'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'concluded' cannot accept command verb 'finalize'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'concluded' cannot accept command verb 'pause'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'concluded' cannot accept command verb 'complete'"}} +-{u'error': {u'class': u'GenericError', u'desc': u"Job 'job0' in state 'concluded' cannot accept command verb 'finalize'"}} +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'status': u'null', u'id': u'job0'}, u'event': u'JOB_STATUS_CHANGE'} +-{u'return': []} ++{"data": {"id": "job0", "status": "waiting"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"data": {"id": "job0", "status": "pending"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 4194304, "id": "job0", "status": "pending", "total-progress": 4194304, "type": "backup"}]} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'pending' cannot accept command verb 'pause'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'pending' cannot accept command verb 'complete'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'pending' cannot accept command verb 'dismiss'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'pending' cannot accept command verb 'pause'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'pending' cannot accept command verb 'complete'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'pending' cannot accept command verb 'dismiss'"}} ++{"return": {}} ++{"data": {"id": "job0", "status": "concluded"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": [{"current-progress": 4194304, "id": "job0", "status": "concluded", "total-progress": 4194304, "type": "backup"}]} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'concluded' cannot accept command verb 'pause'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'concluded' cannot accept command verb 'complete'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'concluded' cannot accept command verb 'finalize'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'concluded' cannot accept command verb 'pause'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'concluded' cannot accept command verb 'complete'"}} ++{"error": {"class": "GenericError", "desc": "Job 'job0' in state 'concluded' cannot accept command verb 'finalize'"}} ++{"return": {}} ++{"data": {"id": "job0", "status": "null"}, "event": "JOB_STATUS_CHANGE", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": []} +diff --git a/tests/qemu-iotests/222.out b/tests/qemu-iotests/222.out +index 48f336a..16643dd 100644 +--- a/tests/qemu-iotests/222.out ++++ b/tests/qemu-iotests/222.out +@@ -8,13 +8,13 @@ Done + + --- Setting up Fleecing Graph --- + +-{u'return': {}} +-{u'return': {}} ++{"return": {}} ++{"return": {}} + + --- Setting up NBD Export --- + +-{u'return': {}} +-{u'return': {}} ++{"return": {}} ++{"return": {}} + + --- Sanity Check --- + +@@ -29,13 +29,13 @@ read -P0 0x3fe0000 64k + --- Testing COW --- + + write -P0xab 0 64k +-{u'return': u''} ++{"return": ""} + write -P0xad 0x00f8000 64k +-{u'return': u''} ++{"return": ""} + write -P0x1d 0x2008000 64k +-{u'return': u''} ++{"return": ""} + write -P0xea 0x3fe0000 64k +-{u'return': u''} ++{"return": ""} + + --- Verifying Data --- + +@@ -49,10 +49,10 @@ read -P0 0x3fe0000 64k + + --- Cleanup --- + +-{u'return': {}} +-{u'timestamp': {u'seconds': 'SECS', u'microseconds': 'USECS'}, u'data': {u'device': u'drive0', u'type': u'backup', u'speed': 0, u'len': 67108864, u'offset': 393216}, u'event': u'BLOCK_JOB_CANCELLED'} +-{u'return': {}} +-{u'return': {}} ++{"return": {}} ++{"data": {"device": "drive0", "len": 67108864, "offset": 393216, "speed": 0, "type": "backup"}, "event": "BLOCK_JOB_CANCELLED", "timestamp": {"microseconds": "USECS", "seconds": "SECS"}} ++{"return": {}} ++{"return": {}} + + --- Confirming writes --- + +diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py +index 3d41ff0..b548e2f 100644 +--- a/tests/qemu-iotests/iotests.py ++++ b/tests/qemu-iotests/iotests.py +@@ -252,7 +252,10 @@ def filter_img_info(output, filename): + def log(msg, filters=[]): + for flt in filters: + msg = flt(msg) +- print(msg) ++ if type(msg) is dict or type(msg) is list: ++ print(json.dumps(msg, sort_keys=True)) ++ else: ++ print(msg) + + class Timeout: + def __init__(self, seconds, errmsg = "Timeout"): +@@ -440,10 +443,11 @@ class VM(qtest.QEMUQtestMachine): + return result + + def qmp_log(self, cmd, filters=[filter_testfiles], **kwargs): +- logmsg = "{'execute': '%s', 'arguments': %s}" % (cmd, kwargs) ++ logmsg = '{"execute": "%s", "arguments": %s}' % \ ++ (cmd, json.dumps(kwargs, sort_keys=True)) + log(logmsg, filters) + result = self.qmp(cmd, **kwargs) +- log(str(result), filters) ++ log(json.dumps(result, sort_keys=True), filters) + return result + + def run_job(self, job, auto_finalize=True, auto_dismiss=False): +-- +1.8.3.1 + diff --git a/SOURCES/kvm-iotests-Use-Python-byte-strings-where-appropriate.patch b/SOURCES/kvm-iotests-Use-Python-byte-strings-where-appropriate.patch new file mode 100644 index 0000000..c633b51 --- /dev/null +++ b/SOURCES/kvm-iotests-Use-Python-byte-strings-where-appropriate.patch @@ -0,0 +1,267 @@ +From 3b36d09996dbcbfc15cb83b2287940243022fd6a Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Mon, 8 Jul 2019 15:25:58 +0100 +Subject: [PATCH 12/39] iotests: Use Python byte strings where appropriate +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Pino Toscano +Message-id: <20190708152601.21123-8-ptoscano@redhat.com> +Patchwork-id: 89424 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v3 07/10] iotests: Use Python byte strings where appropriate +Bugzilla: 1513367 +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Max Reitz +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Markus Armbruster + +From: Max Reitz + +Since byte strings are no longer the default in Python 3, we have to +explicitly use them where we need to, which is mostly when working with +structures. It also means that we need to open a file in binary mode +when we want to use structures. + +On the other hand, we have to accomodate for the fact that some +functions (still) work with byte strings but we want to use unicode +strings (in Python 3 at least, and it does not matter in Python 2). +This includes base64 encoding, but it is most notable when working with +the subprocess module: Either we set universal_newlines to True so that +the default streams are opened in text mode (hence this parameter is +aliased as "text" as of 3.7), or, if that is not possible, we have to +decode the output to a normal string. + +Signed-off-by: Max Reitz +Reviewed-by: Eduardo Habkost +Message-Id: <20181022135307.14398-4-mreitz@redhat.com> +Signed-off-by: Eduardo Habkost +(cherry picked from commit 8eb5e6746feaf9e021b69ea2521899f8dc889033) +Signed-off-by: Pino Toscano +Signed-off-by: Danilo C. L. de Paula +--- + scripts/qtest.py | 2 +- + tests/qemu-iotests/044 | 8 ++++---- + tests/qemu-iotests/149 | 8 +++++--- + tests/qemu-iotests/207 | 4 ++-- + tests/qemu-iotests/iotests.py | 11 +++++++---- + tests/qemu-iotests/nbd-fault-injector.py | 4 ++-- + tests/qemu-iotests/qcow2.py | 10 +++++----- + 7 files changed, 26 insertions(+), 21 deletions(-) + +diff --git a/scripts/qtest.py b/scripts/qtest.py +index df0daf2..adf1fe3 100644 +--- a/scripts/qtest.py ++++ b/scripts/qtest.py +@@ -64,7 +64,7 @@ class QEMUQtestProtocol(object): + + @param qtest_cmd: qtest command text to be sent + """ +- self._sock.sendall(qtest_cmd + "\n") ++ self._sock.sendall((qtest_cmd + "\n").encode('utf-8')) + + def close(self): + self._sock.close() +diff --git a/tests/qemu-iotests/044 b/tests/qemu-iotests/044 +index 11ea0f4..69e736f 100755 +--- a/tests/qemu-iotests/044 ++++ b/tests/qemu-iotests/044 +@@ -53,21 +53,21 @@ class TestRefcountTableGrowth(iotests.QMPTestCase): + fd.seek(off_reftable) + + for i in xrange(0, h.refcount_table_clusters): +- sector = ''.join(struct.pack('>Q', ++ sector = b''.join(struct.pack('>Q', + off_refblock + i * 64 * 512 + j * 512) + for j in xrange(0, 64)) + fd.write(sector) + + # Write the refcount blocks + assert(fd.tell() == off_refblock) +- sector = ''.join(struct.pack('>H', 1) for j in xrange(0, 64 * 256)) ++ sector = b''.join(struct.pack('>H', 1) for j in range(0, 64 * 256)) + for block in xrange(0, h.refcount_table_clusters): + fd.write(sector) + + # Write the L1 table + assert(fd.tell() == off_l1) + assert(off_l2 + 512 * h.l1_size == off_data) +- table = ''.join(struct.pack('>Q', (1 << 63) | off_l2 + 512 * j) ++ table = b''.join(struct.pack('>Q', (1 << 63) | off_l2 + 512 * j) + for j in xrange(0, h.l1_size)) + fd.write(table) + +@@ -85,7 +85,7 @@ class TestRefcountTableGrowth(iotests.QMPTestCase): + remaining = remaining - 1024 * 512 + off = off + 1024 * 512 + +- table = ''.join(struct.pack('>Q', (1 << 63) | off + 512 * j) ++ table = b''.join(struct.pack('>Q', (1 << 63) | off + 512 * j) + for j in xrange(0, remaining / 512)) + fd.write(table) + +diff --git a/tests/qemu-iotests/149 b/tests/qemu-iotests/149 +index d3ffa25..87174b1 100755 +--- a/tests/qemu-iotests/149 ++++ b/tests/qemu-iotests/149 +@@ -79,7 +79,7 @@ class LUKSConfig(object): + + def first_password_base64(self): + (pw, slot) = self.first_password() +- return base64.b64encode(pw) ++ return base64.b64encode(pw.encode('ascii')).decode('ascii') + + def active_slots(self): + slots = [] +@@ -98,7 +98,8 @@ def verify_passwordless_sudo(): + proc = subprocess.Popen(args, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, +- stderr=subprocess.STDOUT) ++ stderr=subprocess.STDOUT, ++ universal_newlines=True) + + msg = proc.communicate()[0] + +@@ -116,7 +117,8 @@ def cryptsetup(args, password=None): + proc = subprocess.Popen(fullargs, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, +- stderr=subprocess.STDOUT) ++ stderr=subprocess.STDOUT, ++ universal_newlines=True) + + msg = proc.communicate(password)[0] + +diff --git a/tests/qemu-iotests/207 b/tests/qemu-iotests/207 +index 8202bd1..d45bf72 100755 +--- a/tests/qemu-iotests/207 ++++ b/tests/qemu-iotests/207 +@@ -109,7 +109,7 @@ with iotests.FilePath('t.img') as disk_path, \ + md5_key = subprocess.check_output( + 'ssh-keyscan -t rsa 127.0.0.1 2>/dev/null | grep -v "\\^#" | ' + + 'cut -d" " -f3 | base64 -d | md5sum -b | cut -d" " -f1', +- shell=True).rstrip() ++ shell=True).rstrip().decode('ascii') + + vm.launch() + blockdev_create(vm, { 'driver': 'ssh', +@@ -147,7 +147,7 @@ with iotests.FilePath('t.img') as disk_path, \ + sha1_key = subprocess.check_output( + 'ssh-keyscan -t rsa 127.0.0.1 2>/dev/null | grep -v "\\^#" | ' + + 'cut -d" " -f3 | base64 -d | sha1sum -b | cut -d" " -f1', +- shell=True).rstrip() ++ shell=True).rstrip().decode('ascii') + + vm.launch() + blockdev_create(vm, { 'driver': 'ssh', +diff --git a/tests/qemu-iotests/iotests.py b/tests/qemu-iotests/iotests.py +index 0f6980a..3d41ff0 100644 +--- a/tests/qemu-iotests/iotests.py ++++ b/tests/qemu-iotests/iotests.py +@@ -104,7 +104,8 @@ def qemu_img_pipe(*args): + '''Run qemu-img and return its output''' + subp = subprocess.Popen(qemu_img_args + list(args), + stdout=subprocess.PIPE, +- stderr=subprocess.STDOUT) ++ stderr=subprocess.STDOUT, ++ universal_newlines=True) + exitcode = subp.wait() + if exitcode < 0: + sys.stderr.write('qemu-img received signal %i: %s\n' % (-exitcode, ' '.join(qemu_img_args + list(args)))) +@@ -128,7 +129,8 @@ def qemu_io(*args): + '''Run qemu-io and return the stdout data''' + args = qemu_io_args + list(args) + subp = subprocess.Popen(args, stdout=subprocess.PIPE, +- stderr=subprocess.STDOUT) ++ stderr=subprocess.STDOUT, ++ universal_newlines=True) + exitcode = subp.wait() + if exitcode < 0: + sys.stderr.write('qemu-io received signal %i: %s\n' % (-exitcode, ' '.join(args))) +@@ -149,7 +151,8 @@ class QemuIoInteractive: + self.args = qemu_io_args + list(args) + self._p = subprocess.Popen(self.args, stdin=subprocess.PIPE, + stdout=subprocess.PIPE, +- stderr=subprocess.STDOUT) ++ stderr=subprocess.STDOUT, ++ universal_newlines=True) + assert self._p.stdout.read(9) == 'qemu-io> ' + + def close(self): +@@ -192,7 +195,7 @@ def compare_images(img1, img2, fmt1=imgfmt, fmt2=imgfmt): + + def create_image(name, size): + '''Create a fully-allocated raw image with sector markers''' +- file = open(name, 'w') ++ file = open(name, 'wb') + i = 0 + while i < size: + sector = struct.pack('>l504xl', i / 512, i / 512) +diff --git a/tests/qemu-iotests/nbd-fault-injector.py b/tests/qemu-iotests/nbd-fault-injector.py +index f9193c0..09668f6 100755 +--- a/tests/qemu-iotests/nbd-fault-injector.py ++++ b/tests/qemu-iotests/nbd-fault-injector.py +@@ -86,7 +86,7 @@ def recvall(sock, bufsize): + raise Exception('unexpected disconnect') + chunks.append(chunk) + received += len(chunk) +- return ''.join(chunks) ++ return b''.join(chunks) + + class Rule(object): + def __init__(self, name, event, io, when): +@@ -176,7 +176,7 @@ def handle_connection(conn, use_export): + req = read_request(conn) + if req.type == NBD_CMD_READ: + write_reply(conn, 0, req.handle) +- conn.send('\0' * req.len, event='data') ++ conn.send(b'\0' * req.len, event='data') + elif req.type == NBD_CMD_WRITE: + _ = conn.recv(req.len, event='data') + write_reply(conn, 0, req.handle) +diff --git a/tests/qemu-iotests/qcow2.py b/tests/qemu-iotests/qcow2.py +index b95a837..b392972 100755 +--- a/tests/qemu-iotests/qcow2.py ++++ b/tests/qemu-iotests/qcow2.py +@@ -10,7 +10,7 @@ class QcowHeaderExtension: + def __init__(self, magic, length, data): + if length % 8 != 0: + padding = 8 - (length % 8) +- data += "\0" * padding ++ data += b"\0" * padding + + self.magic = magic + self.length = length +@@ -103,7 +103,7 @@ class QcowHeader: + + fd.seek(self.header_length) + extensions = self.extensions +- extensions.append(QcowHeaderExtension(0, 0, "")) ++ extensions.append(QcowHeaderExtension(0, 0, b"")) + for ex in extensions: + buf = struct.pack('>II', ex.magic, ex.length) + fd.write(buf) +@@ -137,8 +137,8 @@ class QcowHeader: + for ex in self.extensions: + + data = ex.data[:ex.length] +- if all(c in string.printable for c in data): +- data = "'%s'" % data ++ if all(c in string.printable.encode('ascii') for c in data): ++ data = "'%s'" % data.decode('ascii') + else: + data = "" + +@@ -178,7 +178,7 @@ def cmd_add_header_ext(fd, magic, data): + sys.exit(1) + + h = QcowHeader(fd) +- h.extensions.append(QcowHeaderExtension.create(magic, data)) ++ h.extensions.append(QcowHeaderExtension.create(magic, data.encode('ascii'))) + h.update(fd) + + def cmd_add_header_ext_stdio(fd, magic): +-- +1.8.3.1 + diff --git a/SOURCES/kvm-iothread-fix-crash-with-invalid-properties.patch b/SOURCES/kvm-iothread-fix-crash-with-invalid-properties.patch new file mode 100644 index 0000000..1ae1c2c --- /dev/null +++ b/SOURCES/kvm-iothread-fix-crash-with-invalid-properties.patch @@ -0,0 +1,81 @@ +From 287d819f015a624f321d34491e30b62a05912298 Mon Sep 17 00:00:00 2001 +From: Stefan Hajnoczi +Date: Thu, 15 Aug 2019 13:23:10 +0100 +Subject: [PATCH 08/10] iothread: fix crash with invalid properties +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Stefan Hajnoczi +Message-id: <20190815132311.22027-2-stefanha@redhat.com> +Patchwork-id: 89995 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v2 1/2] iothread: fix crash with invalid properties +Bugzilla: 1687541 +RH-Acked-by: Peter Xu +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: John Snow +RH-Acked-by: Markus Armbruster + +From: Marc-André Lureau + +-object iothread,id=foo,? will crash qemu: + +qemu-system-x86_64:qemu-thread-posix.c:128: qemu_cond_destroy: Assertion `cond->initialized' failed. + +Use thread_id != -1 to check if iothread_complete() finished +successfully and the mutex/cond have been initialized. + +Signed-off-by: Marc-André Lureau +Message-Id: <20180821100716.13803-1-marcandre.lureau@redhat.com> +Signed-off-by: Fam Zheng +(cherry picked from commit 14a2d11825ddc37d6547a80704ae6450e9e376c7) +Signed-off-by: Stefan Hajnoczi +Signed-off-by: Danilo C. L. de Paula +--- + iothread.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/iothread.c b/iothread.c +index aff1281..2fb1cdf 100644 +--- a/iothread.c ++++ b/iothread.c +@@ -110,6 +110,7 @@ static void iothread_instance_init(Object *obj) + IOThread *iothread = IOTHREAD(obj); + + iothread->poll_max_ns = IOTHREAD_POLL_MAX_NS_DEFAULT; ++ iothread->thread_id = -1; + } + + static void iothread_instance_finalize(Object *obj) +@@ -117,6 +118,11 @@ static void iothread_instance_finalize(Object *obj) + IOThread *iothread = IOTHREAD(obj); + + iothread_stop(iothread); ++ ++ if (iothread->thread_id != -1) { ++ qemu_cond_destroy(&iothread->init_done_cond); ++ qemu_mutex_destroy(&iothread->init_done_lock); ++ } + /* + * Before glib2 2.33.10, there is a glib2 bug that GSource context + * pointer may not be cleared even if the context has already been +@@ -135,8 +141,6 @@ static void iothread_instance_finalize(Object *obj) + g_main_context_unref(iothread->worker_context); + iothread->worker_context = NULL; + } +- qemu_cond_destroy(&iothread->init_done_cond); +- qemu_mutex_destroy(&iothread->init_done_lock); + } + + static void iothread_complete(UserCreatable *obj, Error **errp) +@@ -147,7 +151,6 @@ static void iothread_complete(UserCreatable *obj, Error **errp) + + iothread->stopping = false; + iothread->running = true; +- iothread->thread_id = -1; + iothread->ctx = aio_context_new(&local_error); + if (!iothread->ctx) { + error_propagate(errp, local_error); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-iothread-replace-init_done_cond-with-a-semaphore.patch b/SOURCES/kvm-iothread-replace-init_done_cond-with-a-semaphore.patch new file mode 100644 index 0000000..aac68ac --- /dev/null +++ b/SOURCES/kvm-iothread-replace-init_done_cond-with-a-semaphore.patch @@ -0,0 +1,117 @@ +From 9db6f24509ee8a28818693d6a15257b873d9422a Mon Sep 17 00:00:00 2001 +From: Stefan Hajnoczi +Date: Thu, 15 Aug 2019 13:23:11 +0100 +Subject: [PATCH 09/10] iothread: replace init_done_cond with a semaphore + +RH-Author: Stefan Hajnoczi +Message-id: <20190815132311.22027-3-stefanha@redhat.com> +Patchwork-id: 89996 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v2 2/2] iothread: replace init_done_cond with a semaphore +Bugzilla: 1687541 +RH-Acked-by: Peter Xu +RH-Acked-by: John Snow +RH-Acked-by: Markus Armbruster + +From: Peter Xu + +Only sending an init-done message using lock+cond seems an overkill to +me. Replacing it with a simpler semaphore. + +Meanwhile, init the semaphore unconditionally, then we can destroy it +unconditionally too in finalize which seems cleaner. + +Signed-off-by: Peter Xu +Message-id: 20190306115532.23025-2-peterx@redhat.com +Message-Id: <20190306115532.23025-2-peterx@redhat.com> +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit 21c4d15b4708b7d30c450041a560df670f36cac8) +Signed-off-by: Stefan Hajnoczi +Signed-off-by: Danilo C. L. de Paula +--- + include/sysemu/iothread.h | 3 +-- + iothread.c | 17 ++++------------- + 2 files changed, 5 insertions(+), 15 deletions(-) + +diff --git a/include/sysemu/iothread.h b/include/sysemu/iothread.h +index 8a7ac2c..50411ba 100644 +--- a/include/sysemu/iothread.h ++++ b/include/sysemu/iothread.h +@@ -27,8 +27,7 @@ typedef struct { + GMainContext *worker_context; + GMainLoop *main_loop; + GOnce once; +- QemuMutex init_done_lock; +- QemuCond init_done_cond; /* is thread initialization done? */ ++ QemuSemaphore init_done_sem; /* is thread init done? */ + bool stopping; /* has iothread_stop() been called? */ + bool running; /* should iothread_run() continue? */ + int thread_id; +diff --git a/iothread.c b/iothread.c +index 2fb1cdf..b92232f 100644 +--- a/iothread.c ++++ b/iothread.c +@@ -55,10 +55,8 @@ static void *iothread_run(void *opaque) + rcu_register_thread(); + + my_iothread = iothread; +- qemu_mutex_lock(&iothread->init_done_lock); + iothread->thread_id = qemu_get_thread_id(); +- qemu_cond_signal(&iothread->init_done_cond); +- qemu_mutex_unlock(&iothread->init_done_lock); ++ qemu_sem_post(&iothread->init_done_sem); + + while (iothread->running) { + aio_poll(iothread->ctx, true); +@@ -111,6 +109,7 @@ static void iothread_instance_init(Object *obj) + + iothread->poll_max_ns = IOTHREAD_POLL_MAX_NS_DEFAULT; + iothread->thread_id = -1; ++ qemu_sem_init(&iothread->init_done_sem, 0); + } + + static void iothread_instance_finalize(Object *obj) +@@ -119,10 +118,6 @@ static void iothread_instance_finalize(Object *obj) + + iothread_stop(iothread); + +- if (iothread->thread_id != -1) { +- qemu_cond_destroy(&iothread->init_done_cond); +- qemu_mutex_destroy(&iothread->init_done_lock); +- } + /* + * Before glib2 2.33.10, there is a glib2 bug that GSource context + * pointer may not be cleared even if the context has already been +@@ -141,6 +136,7 @@ static void iothread_instance_finalize(Object *obj) + g_main_context_unref(iothread->worker_context); + iothread->worker_context = NULL; + } ++ qemu_sem_destroy(&iothread->init_done_sem); + } + + static void iothread_complete(UserCreatable *obj, Error **errp) +@@ -169,8 +165,6 @@ static void iothread_complete(UserCreatable *obj, Error **errp) + return; + } + +- qemu_mutex_init(&iothread->init_done_lock); +- qemu_cond_init(&iothread->init_done_cond); + iothread->once = (GOnce) G_ONCE_INIT; + + /* This assumes we are called from a thread with useful CPU affinity for us +@@ -184,12 +178,9 @@ static void iothread_complete(UserCreatable *obj, Error **errp) + g_free(name); + + /* Wait for initialization to complete */ +- qemu_mutex_lock(&iothread->init_done_lock); + while (iothread->thread_id == -1) { +- qemu_cond_wait(&iothread->init_done_cond, +- &iothread->init_done_lock); ++ qemu_sem_wait(&iothread->init_done_sem); + } +- qemu_mutex_unlock(&iothread->init_done_lock); + } + + typedef struct { +-- +1.8.3.1 + diff --git a/SOURCES/kvm-linux-headers-Update-for-NVLink2-passthrough-downstr.patch b/SOURCES/kvm-linux-headers-Update-for-NVLink2-passthrough-downstr.patch new file mode 100644 index 0000000..bfeb896 --- /dev/null +++ b/SOURCES/kvm-linux-headers-Update-for-NVLink2-passthrough-downstr.patch @@ -0,0 +1,96 @@ +From a0d3bac749cccf262986923b1b4f4e565472cfd8 Mon Sep 17 00:00:00 2001 +From: David Gibson +Date: Thu, 30 May 2019 04:37:24 +0100 +Subject: [PATCH 3/8] linux-headers: Update for NVLink2 passthrough [downstream + only] +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: David Gibson +Message-id: <20190530043728.32575-3-dgibson@redhat.com> +Patchwork-id: 88424 +O-Subject: [RHEL-8.1 qemu-kvm PATCH 2/6] linux-headers: Update for NVLink2 passthrough [downstream only] +Bugzilla: 1710662 +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Laurent Vivier +RH-Acked-by: Auger Eric +RH-Acked-by: Cornelia Huck + +From: David Gibson + +Update with the necessary pieces for vfio passthrough of NVLink2 +devices. Not a full header update, just pieces, since that's the +convention downwstream. + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1710662 + +Signed-off-by: David Gibson +Signed-off-by: Danilo C. L. de Paula +--- + linux-headers/linux/vfio.h | 42 ++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 42 insertions(+) + +diff --git a/linux-headers/linux/vfio.h b/linux-headers/linux/vfio.h +index 25c7b7d..12b23e5 100644 +--- a/linux-headers/linux/vfio.h ++++ b/linux-headers/linux/vfio.h +@@ -304,6 +304,21 @@ struct vfio_region_info_cap_type { + #define VFIO_REGION_SUBTYPE_INTEL_IGD_LPC_CFG (3) + + /* ++ * 10de vendor sub-type ++ * ++ * NVIDIA GPU NVlink2 RAM is coherent RAM mapped onto the host address space. ++ */ ++#define VFIO_REGION_SUBTYPE_NVIDIA_NVLINK2_RAM (1) ++ ++/* ++ * 1014 vendor sub-type ++ * ++ * IBM NPU NVlink2 ATSD (Address Translation Shootdown) register of NPU ++ * to do TLB invalidation on a GPU. ++ */ ++#define VFIO_REGION_SUBTYPE_IBM_NVLINK2_ATSD (1) ++ ++/* + * The MSIX mappable capability informs that MSIX data of a BAR can be mmapped + * which allows direct access to non-MSIX registers which happened to be within + * the same system page. +@@ -313,6 +328,33 @@ struct vfio_region_info_cap_type { + */ + #define VFIO_REGION_INFO_CAP_MSIX_MAPPABLE 3 + ++/* ++ * Capability with compressed real address (aka SSA - small system address) ++ * where GPU RAM is mapped on a system bus. Used by a GPU for DMA routing ++ * and by the userspace to associate a NVLink bridge with a GPU. ++ */ ++#define VFIO_REGION_INFO_CAP_NVLINK2_SSATGT 4 ++ ++struct vfio_region_info_cap_nvlink2_ssatgt { ++ struct vfio_info_cap_header header; ++ __u64 tgt; ++}; ++ ++/* ++ * Capability with an NVLink link speed. The value is read by ++ * the NVlink2 bridge driver from the bridge's "ibm,nvlink-speed" ++ * property in the device tree. The value is fixed in the hardware ++ * and failing to provide the correct value results in the link ++ * not working with no indication from the driver why. ++ */ ++#define VFIO_REGION_INFO_CAP_NVLINK2_LNKSPD 5 ++ ++struct vfio_region_info_cap_nvlink2_lnkspd { ++ struct vfio_info_cap_header header; ++ __u32 link_speed; ++ __u32 __pad; ++}; ++ + /** + * VFIO_DEVICE_GET_IRQ_INFO - _IOWR(VFIO_TYPE, VFIO_BASE + 9, + * struct vfio_irq_info) +-- +1.8.3.1 + diff --git a/SOURCES/kvm-linux-headers-synchronize-generic-and-x86-KVM-header.patch b/SOURCES/kvm-linux-headers-synchronize-generic-and-x86-KVM-header.patch new file mode 100644 index 0000000..e6380a7 --- /dev/null +++ b/SOURCES/kvm-linux-headers-synchronize-generic-and-x86-KVM-header.patch @@ -0,0 +1,334 @@ +From 4a8e202ddd9bde207a5a9caaee6e0f06399a3052 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Mon, 22 Jul 2019 18:22:13 +0100 +Subject: [PATCH 32/39] linux-headers: synchronize generic and x86 KVM headers + with upstream [rhel-only] + +RH-Author: Paolo Bonzini +Message-id: <20190722182220.19374-12-pbonzini@redhat.com> +Patchwork-id: 89628 +O-Subject: [RHEL-8.1.0 PATCH qemu-kvm v3 11/18] linux-headers: synchronize generic and x86 KVM headers with upstream [rhel-only] +Bugzilla: 1689269 +RH-Acked-by: Peter Xu +RH-Acked-by: Laurent Vivier +RH-Acked-by: Dr. David Alan Gilbert + +From: Liran Alon + +Relevant files copied from upstream QEMU at commit +1d33bea4d013104f01d1c4badc4c670e55c16cca. + +Signed-off-by: Danilo C. L. de Paula +--- + linux-headers/asm-x86/kvm.h | 76 ++++++++++++++++++++++++++++++++++++-- + linux-headers/linux/kvm.h | 89 +++++++++++++++++++++++++++++++++++++++++++-- + 2 files changed, 158 insertions(+), 7 deletions(-) + +diff --git a/linux-headers/asm-x86/kvm.h b/linux-headers/asm-x86/kvm.h +index dcf4dc9..6e7dd79 100644 +--- a/linux-headers/asm-x86/kvm.h ++++ b/linux-headers/asm-x86/kvm.h +@@ -288,6 +288,7 @@ struct kvm_reinject_control { + #define KVM_VCPUEVENT_VALID_SIPI_VECTOR 0x00000002 + #define KVM_VCPUEVENT_VALID_SHADOW 0x00000004 + #define KVM_VCPUEVENT_VALID_SMM 0x00000008 ++#define KVM_VCPUEVENT_VALID_PAYLOAD 0x00000010 + + /* Interrupt shadow states */ + #define KVM_X86_SHADOW_INT_MOV_SS 0x01 +@@ -299,7 +300,7 @@ struct kvm_vcpu_events { + __u8 injected; + __u8 nr; + __u8 has_error_code; +- __u8 pad; ++ __u8 pending; + __u32 error_code; + } exception; + struct { +@@ -322,7 +323,9 @@ struct kvm_vcpu_events { + __u8 smm_inside_nmi; + __u8 latched_init; + } smi; +- __u32 reserved[9]; ++ __u8 reserved[27]; ++ __u8 exception_has_payload; ++ __u64 exception_payload; + }; + + /* for KVM_GET/SET_DEBUGREGS */ +@@ -354,12 +357,79 @@ struct kvm_xcrs { + __u64 padding[16]; + }; + +-/* definition of registers in kvm_run */ ++#define KVM_SYNC_X86_REGS (1UL << 0) ++#define KVM_SYNC_X86_SREGS (1UL << 1) ++#define KVM_SYNC_X86_EVENTS (1UL << 2) ++ ++#define KVM_SYNC_X86_VALID_FIELDS \ ++ (KVM_SYNC_X86_REGS| \ ++ KVM_SYNC_X86_SREGS| \ ++ KVM_SYNC_X86_EVENTS) ++ ++/* kvm_sync_regs struct included by kvm_run struct */ + struct kvm_sync_regs { ++ /* Members of this structure are potentially malicious. ++ * Care must be taken by code reading, esp. interpreting, ++ * data fields from them inside KVM to prevent TOCTOU and ++ * double-fetch types of vulnerabilities. ++ */ ++ struct kvm_regs regs; ++ struct kvm_sregs sregs; ++ struct kvm_vcpu_events events; + }; + + #define KVM_X86_QUIRK_LINT0_REENABLED (1 << 0) + #define KVM_X86_QUIRK_CD_NW_CLEARED (1 << 1) + #define KVM_X86_QUIRK_LAPIC_MMIO_HOLE (1 << 2) ++#define KVM_X86_QUIRK_OUT_7E_INC_RIP (1 << 3) ++ ++#define KVM_STATE_NESTED_FORMAT_VMX 0 ++#define KVM_STATE_NESTED_FORMAT_SVM 1 ++ ++#define KVM_STATE_NESTED_GUEST_MODE 0x00000001 ++#define KVM_STATE_NESTED_RUN_PENDING 0x00000002 ++#define KVM_STATE_NESTED_EVMCS 0x00000004 ++ ++#define KVM_STATE_NESTED_VMX_VMCS_SIZE 0x1000 ++ ++#define KVM_STATE_NESTED_SMM_GUEST_MODE 0x00000001 ++#define KVM_STATE_NESTED_SMM_VMXON 0x00000002 ++ ++struct kvm_vmx_nested_state_data { ++ __u8 vmcs12[KVM_STATE_NESTED_VMX_VMCS_SIZE]; ++ __u8 shadow_vmcs12[KVM_STATE_NESTED_VMX_VMCS_SIZE]; ++}; ++ ++struct kvm_vmx_nested_state_hdr { ++ __u64 vmxon_pa; ++ __u64 vmcs12_pa; ++ ++ struct { ++ __u16 flags; ++ } smm; ++}; ++ ++/* for KVM_CAP_NESTED_STATE */ ++struct kvm_nested_state { ++ __u16 flags; ++ __u16 format; ++ __u32 size; ++ ++ union { ++ struct kvm_vmx_nested_state_hdr vmx; ++ ++ /* Pad the header to 128 bytes. */ ++ __u8 pad[120]; ++ } hdr; ++ ++ /* ++ * Define data region as 0 bytes to preserve backwards-compatability ++ * to old definition of kvm_nested_state in order to avoid changing ++ * KVM_{GET,PUT}_NESTED_STATE ioctl values. ++ */ ++ union { ++ struct kvm_vmx_nested_state_data vmx[0]; ++ } data; ++}; + + #endif /* _ASM_X86_KVM_H */ +diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h +index 8be1232..c8423e7 100644 +--- a/linux-headers/linux/kvm.h ++++ b/linux-headers/linux/kvm.h +@@ -396,6 +396,10 @@ struct kvm_run { + char padding[256]; + }; + ++ /* 2048 is the size of the char array used to bound/pad the size ++ * of the union that holds sync regs. ++ */ ++ #define SYNC_REGS_SIZE_BYTES 2048 + /* + * shared registers between kvm and userspace. + * kvm_valid_regs specifies the register classes set by the host +@@ -407,7 +411,7 @@ struct kvm_run { + __u64 kvm_dirty_regs; + union { + struct kvm_sync_regs regs; +- char padding[2048]; ++ char padding[SYNC_REGS_SIZE_BYTES]; + } s; + }; + +@@ -416,13 +420,19 @@ struct kvm_run { + struct kvm_coalesced_mmio_zone { + __u64 addr; + __u32 size; +- __u32 pad; ++ union { ++ __u32 pad; ++ __u32 pio; ++ }; + }; + + struct kvm_coalesced_mmio { + __u64 phys_addr; + __u32 len; +- __u32 pad; ++ union { ++ __u32 pad; ++ __u32 pio; ++ }; + __u8 data[8]; + }; + +@@ -482,6 +492,17 @@ struct kvm_dirty_log { + }; + }; + ++/* for KVM_CLEAR_DIRTY_LOG */ ++struct kvm_clear_dirty_log { ++ __u32 slot; ++ __u32 num_pages; ++ __u64 first_page; ++ union { ++ void *dirty_bitmap; /* one bit per page */ ++ __u64 padding2; ++ }; ++}; ++ + /* for KVM_SET_SIGNAL_MASK */ + struct kvm_signal_mask { + __u32 len; +@@ -672,6 +693,13 @@ struct kvm_ioeventfd { + __u8 pad[36]; + }; + ++#define KVM_X86_DISABLE_EXITS_MWAIT (1 << 0) ++#define KVM_X86_DISABLE_EXITS_HLT (1 << 1) ++#define KVM_X86_DISABLE_EXITS_PAUSE (1 << 2) ++#define KVM_X86_DISABLE_VALID_EXITS (KVM_X86_DISABLE_EXITS_MWAIT | \ ++ KVM_X86_DISABLE_EXITS_HLT | \ ++ KVM_X86_DISABLE_EXITS_PAUSE) ++ + /* for KVM_ENABLE_CAP */ + struct kvm_enable_cap { + /* in */ +@@ -708,6 +736,7 @@ struct kvm_ppc_one_seg_page_size { + + #define KVM_PPC_PAGE_SIZES_REAL 0x00000001 + #define KVM_PPC_1T_SEGMENTS 0x00000002 ++#define KVM_PPC_NO_HASH 0x00000004 + + struct kvm_ppc_smmu_info { + __u64 flags; +@@ -740,6 +769,15 @@ struct kvm_ppc_resize_hpt { + #define KVM_S390_SIE_PAGE_OFFSET 1 + + /* ++ * On arm64, machine type can be used to request the physical ++ * address size for the VM. Bits[7-0] are reserved for the guest ++ * PA size shift (i.e, log2(PA_Size)). For backward compatibility, ++ * value 0 implies the default IPA size, 40bits. ++ */ ++#define KVM_VM_TYPE_ARM_IPA_SIZE_MASK 0xffULL ++#define KVM_VM_TYPE_ARM_IPA_SIZE(x) \ ++ ((x) & KVM_VM_TYPE_ARM_IPA_SIZE_MASK) ++/* + * ioctls for /dev/kvm fds: + */ + #define KVM_GET_API_VERSION _IO(KVMIO, 0x00) +@@ -925,7 +963,7 @@ struct kvm_ppc_resize_hpt { + #define KVM_CAP_S390_GS 140 + #define KVM_CAP_S390_AIS 141 + #define KVM_CAP_SPAPR_TCE_VFIO 142 +-#define KVM_CAP_X86_GUEST_MWAIT 143 ++#define KVM_CAP_X86_DISABLE_EXITS 143 + #define KVM_CAP_ARM_USER_IRQ 144 + #define KVM_CAP_S390_CMMA_MIGRATION 145 + #define KVM_CAP_PPC_FWNMI 146 +@@ -936,11 +974,25 @@ struct kvm_ppc_resize_hpt { + #define KVM_CAP_PPC_GET_CPU_CHAR 151 + #define KVM_CAP_S390_BPB 152 + #define KVM_CAP_GET_MSR_FEATURES 153 ++#define KVM_CAP_HYPERV_EVENTFD 154 ++#define KVM_CAP_HYPERV_TLBFLUSH 155 + #define KVM_CAP_S390_HPAGE_1M 156 + #define KVM_CAP_NESTED_STATE 157 + #define KVM_CAP_ARM_INJECT_SERROR_ESR 158 + #define KVM_CAP_MSR_PLATFORM_INFO 159 + #define KVM_CAP_PPC_NESTED_HV 160 ++#define KVM_CAP_HYPERV_SEND_IPI 161 ++#define KVM_CAP_COALESCED_PIO 162 ++#define KVM_CAP_HYPERV_ENLIGHTENED_VMCS 163 ++#define KVM_CAP_EXCEPTION_PAYLOAD 164 ++#define KVM_CAP_ARM_VM_IPA_SIZE 165 ++#define KVM_CAP_MANUAL_DIRTY_LOG_PROTECT 166 /* Obsolete */ ++#define KVM_CAP_HYPERV_CPUID 167 ++#define KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2 168 ++#define KVM_CAP_PPC_IRQ_XIVE 169 ++#define KVM_CAP_ARM_SVE 170 ++#define KVM_CAP_ARM_PTRAUTH_ADDRESS 171 ++#define KVM_CAP_ARM_PTRAUTH_GENERIC 172 + + #ifdef KVM_CAP_IRQ_ROUTING + +@@ -1098,6 +1150,7 @@ struct kvm_dirty_tlb { + #define KVM_REG_SIZE_U256 0x0050000000000000ULL + #define KVM_REG_SIZE_U512 0x0060000000000000ULL + #define KVM_REG_SIZE_U1024 0x0070000000000000ULL ++#define KVM_REG_SIZE_U2048 0x0080000000000000ULL + + struct kvm_reg_list { + __u64 n; /* number of regs */ +@@ -1164,6 +1217,8 @@ enum kvm_device_type { + #define KVM_DEV_TYPE_ARM_VGIC_V3 KVM_DEV_TYPE_ARM_VGIC_V3 + KVM_DEV_TYPE_ARM_VGIC_ITS, + #define KVM_DEV_TYPE_ARM_VGIC_ITS KVM_DEV_TYPE_ARM_VGIC_ITS ++ KVM_DEV_TYPE_XIVE, ++#define KVM_DEV_TYPE_XIVE KVM_DEV_TYPE_XIVE + KVM_DEV_TYPE_MAX, + }; + +@@ -1380,6 +1435,22 @@ struct kvm_enc_region { + #define KVM_MEMORY_ENCRYPT_REG_REGION _IOR(KVMIO, 0xbb, struct kvm_enc_region) + #define KVM_MEMORY_ENCRYPT_UNREG_REGION _IOR(KVMIO, 0xbc, struct kvm_enc_region) + ++/* Available with KVM_CAP_HYPERV_EVENTFD */ ++#define KVM_HYPERV_EVENTFD _IOW(KVMIO, 0xbd, struct kvm_hyperv_eventfd) ++ ++/* Available with KVM_CAP_NESTED_STATE */ ++#define KVM_GET_NESTED_STATE _IOWR(KVMIO, 0xbe, struct kvm_nested_state) ++#define KVM_SET_NESTED_STATE _IOW(KVMIO, 0xbf, struct kvm_nested_state) ++ ++/* Available with KVM_CAP_MANUAL_DIRTY_LOG_PROTECT_2 */ ++#define KVM_CLEAR_DIRTY_LOG _IOWR(KVMIO, 0xc0, struct kvm_clear_dirty_log) ++ ++/* Available with KVM_CAP_HYPERV_CPUID */ ++#define KVM_GET_SUPPORTED_HV_CPUID _IOWR(KVMIO, 0xc1, struct kvm_cpuid2) ++ ++/* Available with KVM_CAP_ARM_SVE */ ++#define KVM_ARM_VCPU_FINALIZE _IOW(KVMIO, 0xc2, int) ++ + /* Secure Encrypted Virtualization command */ + enum sev_cmd_id { + /* Guest initialization commands */ +@@ -1520,4 +1591,14 @@ struct kvm_assigned_msix_entry { + #define KVM_ARM_DEV_EL1_PTIMER (1 << 1) + #define KVM_ARM_DEV_PMU (1 << 2) + ++struct kvm_hyperv_eventfd { ++ __u32 conn_id; ++ __s32 fd; ++ __u32 flags; ++ __u32 padding[3]; ++}; ++ ++#define KVM_HYPERV_CONN_ID_MASK 0x00ffffff ++#define KVM_HYPERV_EVENTFD_DEASSIGN (1 << 0) ++ + #endif /* __LINUX_KVM_H */ +-- +1.8.3.1 + diff --git a/SOURCES/kvm-linux-headers-update-against-Linux-5.2-rc1.patch b/SOURCES/kvm-linux-headers-update-against-Linux-5.2-rc1.patch new file mode 100644 index 0000000..097d69e --- /dev/null +++ b/SOURCES/kvm-linux-headers-update-against-Linux-5.2-rc1.patch @@ -0,0 +1,49 @@ +From a4fe0e8dfc7efe64ecc783de6d18660db10bab9d Mon Sep 17 00:00:00 2001 +From: David Hildenbrand +Date: Wed, 22 May 2019 08:03:54 +0100 +Subject: [PATCH 02/12] linux headers: update against Linux 5.2-rc1 + +RH-Author: David Hildenbrand +Message-id: <20190522080402.20173-3-david@redhat.com> +Patchwork-id: 88157 +O-Subject: [RHEL8.1 qemu-kvm PATCH v2 02/10] linux headers: update against Linux 5.2-rc1 +Bugzilla: 1660912 +RH-Acked-by: Cornelia Huck +RH-Acked-by: Jens Freimann +RH-Acked-by: Thomas Huth + +commit a188339ca5a396acc588e5851ed7e19f66b0ebd9 + +Signed-off-by: Cornelia Huck +(cherry picked from commit d9cb4336159a00bd0d9c81b93f02874ef3626057) + +This patch is based on the upstream patch 19897fbee613 +("linux headers: update against Linux 5.2-rc1"), however, due to the +many merge conflicts, this patch only includes the relevant s390x change +to support the new CPU model for HW gen15. + +Signed-off-by: David Hildenbrand +Signed-off-by: Danilo C. L. de Paula +--- + linux-headers/asm-s390/kvm.h | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/linux-headers/asm-s390/kvm.h b/linux-headers/asm-s390/kvm.h +index 0265482..03ab596 100644 +--- a/linux-headers/asm-s390/kvm.h ++++ b/linux-headers/asm-s390/kvm.h +@@ -152,7 +152,10 @@ struct kvm_s390_vm_cpu_subfunc { + __u8 pcc[16]; /* with MSA4 */ + __u8 ppno[16]; /* with MSA5 */ + __u8 kma[16]; /* with MSA8 */ +- __u8 reserved[1808]; ++ __u8 kdsa[16]; /* with MSA9 */ ++ __u8 sortl[32]; /* with STFLE.150 */ ++ __u8 dfltcc[32]; /* with STFLE.151 */ ++ __u8 reserved[1728]; + }; + + /* kvm attributes for crypto */ +-- +1.8.3.1 + diff --git a/SOURCES/kvm-loader-Check-access-size-when-calling-rom_ptr-to-avo.patch b/SOURCES/kvm-loader-Check-access-size-when-calling-rom_ptr-to-avo.patch new file mode 100644 index 0000000..5b25d7d --- /dev/null +++ b/SOURCES/kvm-loader-Check-access-size-when-calling-rom_ptr-to-avo.patch @@ -0,0 +1,239 @@ +From 6dd1f60e226cb3c8ad0791dd6c8edba2493145cd Mon Sep 17 00:00:00 2001 +From: Cornelia Huck +Date: Wed, 17 Apr 2019 13:57:19 +0100 +Subject: [PATCH 02/24] loader: Check access size when calling rom_ptr() to + avoid crashes + +RH-Author: Cornelia Huck +Message-id: <20190417135741.25297-3-cohuck@redhat.com> +Patchwork-id: 85785 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v2 02/24] loader: Check access size when calling rom_ptr() to avoid crashes +Bugzilla: 1699070 +RH-Acked-by: David Hildenbrand +RH-Acked-by: Thomas Huth +RH-Acked-by: Jens Freimann + +From: Thomas Huth + +The rom_ptr() function allows direct access to the ROM blobs that we +load during startup. However, there are currently no checks for the +size of the accesses, so it's currently possible to crash QEMU for +example with: + +$ echo "Insane in the mainframe" > /tmp/test.txt +$ s390x-softmmu/qemu-system-s390x -kernel /tmp/test.txt -append xyz +Segmentation fault (core dumped) +$ s390x-softmmu/qemu-system-s390x -kernel /tmp/test.txt -initrd /tmp/test.txt +Segmentation fault (core dumped) +$ echo -n HdrS > /tmp/hdr.txt +$ sparc64-softmmu/qemu-system-sparc64 -kernel /tmp/hdr.txt -initrd /tmp/hdr.txt +Segmentation fault (core dumped) + +We need a possibility to check the size of the ROM area that we want +to access, thus let's add a size parameter to the rom_ptr() function +to avoid these problems. + +Acked-by: Christian Borntraeger +Signed-off-by: Thomas Huth +Message-Id: <1530005740-25254-1-git-send-email-thuth@redhat.com> +Signed-off-by: Cornelia Huck +(cherry picked from commit 0f0f8b611eeea663c8d3b6021918033e257411a1) +Signed-off-by: Cornelia Huck +Signed-off-by: Danilo C. L. de Paula +--- + hw/core/loader.c | 10 +++++----- + hw/mips/mips_malta.c | 6 ++++-- + hw/s390x/ipl.c | 18 ++++++++++++------ + hw/sparc/sun4m.c | 4 ++-- + hw/sparc64/sun4u.c | 4 ++-- + include/hw/loader.h | 2 +- + target/arm/cpu.c | 2 +- + 7 files changed, 27 insertions(+), 19 deletions(-) + +diff --git a/hw/core/loader.c b/hw/core/loader.c +index 06bdbca..bbb6e65 100644 +--- a/hw/core/loader.c ++++ b/hw/core/loader.c +@@ -191,7 +191,7 @@ void pstrcpy_targphys(const char *name, hwaddr dest, int buf_size, + rom_add_blob_fixed(name, source, (nulp - source) + 1, dest); + } else { + rom_add_blob_fixed(name, source, buf_size, dest); +- ptr = rom_ptr(dest + buf_size - 1); ++ ptr = rom_ptr(dest + buf_size - 1, sizeof(*ptr)); + *ptr = 0; + } + } +@@ -1165,7 +1165,7 @@ void rom_reset_order_override(void) + fw_cfg_reset_order_override(fw_cfg); + } + +-static Rom *find_rom(hwaddr addr) ++static Rom *find_rom(hwaddr addr, size_t size) + { + Rom *rom; + +@@ -1179,7 +1179,7 @@ static Rom *find_rom(hwaddr addr) + if (rom->addr > addr) { + continue; + } +- if (rom->addr + rom->romsize < addr) { ++ if (rom->addr + rom->romsize < addr + size) { + continue; + } + return rom; +@@ -1249,11 +1249,11 @@ int rom_copy(uint8_t *dest, hwaddr addr, size_t size) + return (d + l) - dest; + } + +-void *rom_ptr(hwaddr addr) ++void *rom_ptr(hwaddr addr, size_t size) + { + Rom *rom; + +- rom = find_rom(addr); ++ rom = find_rom(addr, size); + if (!rom || !rom->data) + return NULL; + return rom->data + (addr - rom->addr); +diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c +index f6513a4..8bbea0b 100644 +--- a/hw/mips/mips_malta.c ++++ b/hw/mips/mips_malta.c +@@ -1139,11 +1139,13 @@ void mips_malta_init(MachineState *machine) + a neat trick which allows bi-endian firmware. */ + #ifndef TARGET_WORDS_BIGENDIAN + { +- uint32_t *end, *addr = rom_ptr(FLASH_ADDRESS); ++ uint32_t *end, *addr; ++ const size_t swapsize = MIN(bios_size, 0x3e0000); ++ addr = rom_ptr(FLASH_ADDRESS, swapsize); + if (!addr) { + addr = memory_region_get_ram_ptr(bios); + } +- end = (void *)addr + MIN(bios_size, 0x3e0000); ++ end = (void *)addr + swapsize; + while (addr < end) { + bswap32s(addr); + addr++; +diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c +index 617ac43..10038ec 100644 +--- a/hw/s390x/ipl.c ++++ b/hw/s390x/ipl.c +@@ -32,7 +32,6 @@ + #define KERN_PARM_AREA 0x010480UL + #define INITRD_START 0x800000UL + #define INITRD_PARM_START 0x010408UL +-#define INITRD_PARM_SIZE 0x010410UL + #define PARMFILE_START 0x001000UL + #define ZIPL_IMAGE_START 0x009000UL + #define IPL_PSW_MASK (PSW_MASK_32 | PSW_MASK_64) +@@ -164,12 +163,12 @@ static void s390_ipl_realize(DeviceState *dev, Error **errp) + goto error; + } + /* if this is Linux use KERN_IMAGE_START */ +- magic = rom_ptr(LINUX_MAGIC_ADDR); ++ magic = rom_ptr(LINUX_MAGIC_ADDR, 6); + if (magic && !memcmp(magic, "S390EP", 6)) { + pentry = KERN_IMAGE_START; + } else { + /* if not Linux load the address of the (short) IPL PSW */ +- ipl_psw = rom_ptr(4); ++ ipl_psw = rom_ptr(4, 4); + if (ipl_psw) { + pentry = be32_to_cpu(*ipl_psw) & 0x7fffffffUL; + } else { +@@ -185,9 +184,12 @@ static void s390_ipl_realize(DeviceState *dev, Error **errp) + * loader) and it won't work. For this case we force it to 0x10000, too. + */ + if (pentry == KERN_IMAGE_START || pentry == 0x800) { ++ char *parm_area = rom_ptr(KERN_PARM_AREA, strlen(ipl->cmdline) + 1); + ipl->start_addr = KERN_IMAGE_START; + /* Overwrite parameters in the kernel image, which are "rom" */ +- strcpy(rom_ptr(KERN_PARM_AREA), ipl->cmdline); ++ if (parm_area) { ++ strcpy(parm_area, ipl->cmdline); ++ } + } else { + ipl->start_addr = pentry; + } +@@ -195,6 +197,7 @@ static void s390_ipl_realize(DeviceState *dev, Error **errp) + if (ipl->initrd) { + ram_addr_t initrd_offset; + int initrd_size; ++ uint64_t *romptr; + + initrd_offset = INITRD_START; + while (kernel_size + 0x100000 > initrd_offset) { +@@ -211,8 +214,11 @@ static void s390_ipl_realize(DeviceState *dev, Error **errp) + * we have to overwrite values in the kernel image, + * which are "rom" + */ +- stq_p(rom_ptr(INITRD_PARM_START), initrd_offset); +- stq_p(rom_ptr(INITRD_PARM_SIZE), initrd_size); ++ romptr = rom_ptr(INITRD_PARM_START, 16); ++ if (romptr) { ++ stq_p(romptr, initrd_offset); ++ stq_p(romptr + 1, initrd_size); ++ } + } + } + /* +diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c +index 6471aca..a400442 100644 +--- a/hw/sparc/sun4m.c ++++ b/hw/sparc/sun4m.c +@@ -272,8 +272,8 @@ static unsigned long sun4m_load_kernel(const char *kernel_filename, + } + if (initrd_size > 0) { + for (i = 0; i < 64 * TARGET_PAGE_SIZE; i += TARGET_PAGE_SIZE) { +- ptr = rom_ptr(KERNEL_LOAD_ADDR + i); +- if (ldl_p(ptr) == 0x48647253) { // HdrS ++ ptr = rom_ptr(KERNEL_LOAD_ADDR + i, 24); ++ if (ptr && ldl_p(ptr) == 0x48647253) { /* HdrS */ + stl_p(ptr + 16, INITRD_LOAD_ADDR); + stl_p(ptr + 20, initrd_size); + break; +diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c +index 2044a52..1410c3a 100644 +--- a/hw/sparc64/sun4u.c ++++ b/hw/sparc64/sun4u.c +@@ -186,8 +186,8 @@ static uint64_t sun4u_load_kernel(const char *kernel_filename, + } + if (*initrd_size > 0) { + for (i = 0; i < 64 * TARGET_PAGE_SIZE; i += TARGET_PAGE_SIZE) { +- ptr = rom_ptr(*kernel_addr + i); +- if (ldl_p(ptr + 8) == 0x48647253) { /* HdrS */ ++ ptr = rom_ptr(*kernel_addr + i, 32); ++ if (ptr && ldl_p(ptr + 8) == 0x48647253) { /* HdrS */ + stl_p(ptr + 24, *initrd_addr + *kernel_addr); + stl_p(ptr + 28, *initrd_size); + break; +diff --git a/include/hw/loader.h b/include/hw/loader.h +index 5ed3fd8..e98b84b 100644 +--- a/include/hw/loader.h ++++ b/include/hw/loader.h +@@ -226,7 +226,7 @@ void rom_set_fw(FWCfgState *f); + void rom_set_order_override(int order); + void rom_reset_order_override(void); + int rom_copy(uint8_t *dest, hwaddr addr, size_t size); +-void *rom_ptr(hwaddr addr); ++void *rom_ptr(hwaddr addr, size_t size); + void hmp_info_roms(Monitor *mon, const QDict *qdict); + + #define rom_add_file_fixed(_f, _a, _i) \ +diff --git a/target/arm/cpu.c b/target/arm/cpu.c +index 9d030e0..6773f40 100644 +--- a/target/arm/cpu.c ++++ b/target/arm/cpu.c +@@ -219,7 +219,7 @@ static void arm_cpu_reset(CPUState *s) + + /* Load the initial SP and PC from offset 0 and 4 in the vector table */ + vecbase = env->v7m.vecbase[env->v7m.secure]; +- rom = rom_ptr(vecbase); ++ rom = rom_ptr(vecbase, 8); + if (rom) { + /* Address zero is covered by ROM which hasn't yet been + * copied into physical memory. +-- +1.8.3.1 + diff --git a/SOURCES/kvm-memory-Fix-the-memory-region-type-assignment-order.patch b/SOURCES/kvm-memory-Fix-the-memory-region-type-assignment-order.patch new file mode 100644 index 0000000..f06af3c --- /dev/null +++ b/SOURCES/kvm-memory-Fix-the-memory-region-type-assignment-order.patch @@ -0,0 +1,74 @@ +From c3d30392ea7f29823de3b4514ce3b75d7254ee58 Mon Sep 17 00:00:00 2001 +From: Gary R Hook +Date: Wed, 10 Apr 2019 00:08:02 +0100 +Subject: [PATCH 2/5] memory: Fix the memory region type assignment order + +RH-Author: Gary R Hook +Message-id: <20190410000803.1744-2-ghook@redhat.com> +Patchwork-id: 85543 +O-Subject: [RHEL-8.1 virt 1/2] memory: Fix the memory region type assignment order +Bugzilla: 1667249 +RH-Acked-by: Eduardo Habkost +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Alex Williamson + +BZ: 1667249 +Branch: rhel-8.1.0 +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1667249 +Upstream Status: 4.0.0-rc1 +Build Info: https://brewweb.engineering.redhat.com/brew/taskinfo?taskID=20980582 +Conflicts: None + +commit 2ddb89b00f947f785c9ca6742f28f954e3b75e62 +Author: Singh, Brijesh +Date: Mon Feb 4 22:23:39 2019 +0000 + + memory: Fix the memory region type assignment order + + Currently, a callback registered through the RAMBlock notifier + is not able to get the memory region type (i.e callback is not + able to use memory_region_is_ram_device function). This is + because mr->ram assignment happens _after_ the memory is allocated + whereas the callback is executed during allocation. + + Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1667249 + Suggested-by: Alex Williamson + Cc: Paolo Bonzini + Reviewed-by: Alex Williamson + Signed-off-by: Brijesh Singh + Message-Id: <20190204222322.26766-2-brijesh.singh@amd.com> + Signed-off-by: Paolo Bonzini + +Cc: Paolo Bonzini +Cc: qemu-devel@nongnu.org +Signed-off-by: Danilo C. L. de Paula +--- + memory.c | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/memory.c b/memory.c +index 4974f97..04ff5e9 100644 +--- a/memory.c ++++ b/memory.c +@@ -1631,10 +1631,17 @@ void memory_region_init_ram_device_ptr(MemoryRegion *mr, + uint64_t size, + void *ptr) + { +- memory_region_init_ram_ptr(mr, owner, name, size, ptr); ++ memory_region_init(mr, owner, name, size); ++ mr->ram = true; ++ mr->terminates = true; + mr->ram_device = true; + mr->ops = &ram_device_mem_ops; + mr->opaque = mr; ++ mr->destructor = memory_region_destructor_ram; ++ mr->dirty_log_mask = tcg_enabled() ? (1 << DIRTY_MEMORY_CODE) : 0; ++ /* qemu_ram_alloc_from_ptr cannot fail with ptr != NULL. */ ++ assert(ptr != NULL); ++ mr->ram_block = qemu_ram_alloc_from_ptr(size, ptr, mr, &error_fatal); + } + + void memory_region_init_alias(MemoryRegion *mr, +-- +1.8.3.1 + diff --git a/SOURCES/kvm-nbd-client-Lower-min_block-for-block-status-unaligne.patch b/SOURCES/kvm-nbd-client-Lower-min_block-for-block-status-unaligne.patch new file mode 100644 index 0000000..1573c0f --- /dev/null +++ b/SOURCES/kvm-nbd-client-Lower-min_block-for-block-status-unaligne.patch @@ -0,0 +1,119 @@ +From 569674a3b855f516a8bec22ca365fc7614639ce6 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Tue, 23 Jul 2019 14:45:42 +0100 +Subject: [PATCH 04/14] nbd/client: Lower min_block for block-status, unaligned + size + +RH-Author: Max Reitz +Message-id: <20190723144546.23701-4-mreitz@redhat.com> +Patchwork-id: 89650 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 3/7] nbd/client: Lower min_block for block-status, unaligned size +Bugzilla: 1678979 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Stefano Garzarella +RH-Acked-by: John Snow + +From: Eric Blake + +We have a latent bug in our NBD client code, tickled by the brand new +nbdkit 1.11.10 block status support: + +$ nbdkit --filter=log --filter=truncate -U - \ + data data="1" size=511 truncate=64K logfile=/dev/stdout \ + --run 'qemu-img convert $nbd /var/tmp/out' +... +qemu-img: block/io.c:2122: bdrv_co_block_status: Assertion `*pnum && QEMU_IS_ALIGNED(*pnum, align) && align > offset - aligned_offset' failed. + +The culprit? Our implementation of .bdrv_co_block_status can return +unaligned block status for any server that operates with a lower +actual alignment than what we tell the block layer in +request_alignment, in violation of the block layer's constraints. To +date, we've been unable to trip the bug, because qemu as NBD server +always advertises block sizing (at which point it is a server bug if +the server sends unaligned status - although qemu 3.1 is such a server +and I've sent separate patches for 4.0 both to get the server to obey +the spec, and to let the client to tolerate server oddities at EOF). + +But nbdkit does not (yet) advertise block sizing, and therefore is not +in violation of the spec for returning block status at whatever +boundaries it wants, and those unaligned results can occur anywhere +rather than just at EOF. While we are still wise to avoid sending +sub-sector read/write requests to a server of unknown origin, we MUST +consider that a server telling us block status without an advertised +block size is correct. So, we either have to munge unaligned answers +from the server into aligned ones that we hand back to the block +layer, or we have to tell the block layer about a smaller alignment. + +Similarly, if the server advertises an image size that is not +sector-aligned, we might as well assume that the server intends to let +us access those tail bytes, and therefore supports a minimum block +size of 1, regardless of whether the server supports block status +(although we still need more patches to fix the problem that with an +unaligned image, we can send read or block status requests that exceed +EOF to the server). Again, qemu as server cannot trip this problem +(because it rounds images to sector alignment), but nbdkit advertised +unaligned size even before it gained block status support. + +Solve both alignment problems at once by using better heuristics on +what alignment to report to the block layer when the server did not +give us something to work with. Note that very few NBD servers +implement block status (to date, only qemu and nbdkit are known to do +so); and as the NBD spec mentioned block sizing constraints prior to +documenting block status, it can be assumed that any future +implementations of block status are aware that they must advertise +block size if they want a minimum size other than 1. + +We've had a long history of struggles with picking the right alignment +to use in the block layer, as evidenced by the commit message of +fd8d372d (v2.12) that introduced the current choice of forced 512-byte +alignment. + +There is no iotest coverage for this fix, because qemu can't provoke +it, and I didn't want to make test 241 dependent on nbdkit. + +Fixes: fd8d372d +Reported-by: Richard W.M. Jones +Signed-off-by: Eric Blake +Message-Id: <20190329042750.14704-3-eblake@redhat.com> +Reviewed-by: Vladimir Sementsov-Ogievskiy +Tested-by: Richard W.M. Jones +(cherry picked from commit 7da537f70d929800ba9c657b8a47a7b827695ccc) +Signed-off-by: Max Reitz +Signed-off-by: Danilo C. L. de Paula +--- + block/nbd.c | 19 ++++++++++++++++++- + 1 file changed, 18 insertions(+), 1 deletion(-) + +diff --git a/block/nbd.c b/block/nbd.c +index f29c10f..3d642cd 100644 +--- a/block/nbd.c ++++ b/block/nbd.c +@@ -473,7 +473,24 @@ static void nbd_refresh_limits(BlockDriverState *bs, Error **errp) + uint32_t min = s->info.min_block; + uint32_t max = MIN_NON_ZERO(NBD_MAX_BUFFER_SIZE, s->info.max_block); + +- bs->bl.request_alignment = min ? min : BDRV_SECTOR_SIZE; ++ /* ++ * If the server did not advertise an alignment: ++ * - a size that is not sector-aligned implies that an alignment ++ * of 1 can be used to access those tail bytes ++ * - advertisement of block status requires an alignment of 1, so ++ * that we don't violate block layer constraints that block ++ * status is always aligned (as we can't control whether the ++ * server will report sub-sector extents, such as a hole at EOF ++ * on an unaligned POSIX file) ++ * - otherwise, assume the server is so old that we are safer avoiding ++ * sub-sector requests ++ */ ++ if (!min) { ++ min = (!QEMU_IS_ALIGNED(s->info.size, BDRV_SECTOR_SIZE) || ++ s->info.base_allocation) ? 1 : BDRV_SECTOR_SIZE; ++ } ++ ++ bs->bl.request_alignment = min; + bs->bl.max_pdiscard = max; + bs->bl.max_pwrite_zeroes = max; + bs->bl.max_transfer = max; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-nbd-client-Reject-inaccessible-tail-of-inconsistent-.patch b/SOURCES/kvm-nbd-client-Reject-inaccessible-tail-of-inconsistent-.patch new file mode 100644 index 0000000..9061a46 --- /dev/null +++ b/SOURCES/kvm-nbd-client-Reject-inaccessible-tail-of-inconsistent-.patch @@ -0,0 +1,64 @@ +From e49b010d5f866b3ee7efbf40398f0a0832ce8801 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Tue, 23 Jul 2019 14:45:43 +0100 +Subject: [PATCH 05/14] nbd/client: Reject inaccessible tail of inconsistent + server + +RH-Author: Max Reitz +Message-id: <20190723144546.23701-5-mreitz@redhat.com> +Patchwork-id: 89649 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 4/7] nbd/client: Reject inaccessible tail of inconsistent server +Bugzilla: 1678979 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Stefano Garzarella +RH-Acked-by: John Snow + +From: Eric Blake + +The NBD spec suggests that a server should never advertise a size +inconsistent with its minimum block alignment, as that tail is +effectively inaccessible to a compliant client obeying those block +constraints. Since we have a habit of rounding up rather than +truncating, to avoid losing the last few bytes of user input, and we +cannot access the tail when the server advertises bogus block sizing, +abort the connection to alert the server to fix their bug. And +rejecting such servers matches what we already did for a min_block +that was not a power of 2 or which was larger than max_block. + +Does not impact either qemu (which always sends properly aligned +sizes) or nbdkit (which does not send minimum block requirements yet); +so this is mostly aimed at new NBD server implementations, and ensures +that the rest of our code can assume the size is aligned. + +Signed-off-by: Eric Blake +Message-Id: <20190330155704.24191-1-eblake@redhat.com> +Reviewed-by: Vladimir Sementsov-Ogievskiy +(cherry picked from commit 3add3ab78247fd347fd6f377a4b951022ac35d35) +Signed-off-by: Max Reitz +Signed-off-by: Danilo C. L. de Paula +--- + nbd/client.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/nbd/client.c b/nbd/client.c +index 25603f2..c828faf 100644 +--- a/nbd/client.c ++++ b/nbd/client.c +@@ -416,6 +416,14 @@ static int nbd_opt_go(QIOChannel *ioc, const char *wantname, + nbd_send_opt_abort(ioc); + return -1; + } ++ if (info->min_block && ++ !QEMU_IS_ALIGNED(info->size, info->min_block)) { ++ error_setg(errp, "export size %" PRIu64 "is not multiple of " ++ "minimum block size %" PRIu32, info->size, ++ info->min_block); ++ nbd_send_opt_abort(ioc); ++ return -1; ++ } + be16_to_cpus(&info->flags); + trace_nbd_receive_negotiate_size_flags(info->size, info->flags); + break; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-nbd-client-Support-qemu-img-convert-from-unaligned-s.patch b/SOURCES/kvm-nbd-client-Support-qemu-img-convert-from-unaligned-s.patch new file mode 100644 index 0000000..fe47c31 --- /dev/null +++ b/SOURCES/kvm-nbd-client-Support-qemu-img-convert-from-unaligned-s.patch @@ -0,0 +1,132 @@ +From 25bfe4a95b02b6fefafdfa1651c50a4d0c5bc87b Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Tue, 23 Jul 2019 14:45:44 +0100 +Subject: [PATCH 06/14] nbd/client: Support qemu-img convert from unaligned + size + +RH-Author: Max Reitz +Message-id: <20190723144546.23701-6-mreitz@redhat.com> +Patchwork-id: 89651 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 5/7] nbd/client: Support qemu-img convert from unaligned size +Bugzilla: 1678979 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Stefano Garzarella +RH-Acked-by: John Snow + +From: Eric Blake + +If an NBD server advertises a size that is not a multiple of a sector, +the block layer rounds up that size, even though we set info.size to +the exact byte value sent by the server. The block layer then proceeds +to let us read or query block status on the hole that it added past +EOF, which the NBD server is unlikely to be happy with. Fortunately, +qemu as a server never advertizes an unaligned size, so we generally +don't run into this problem; but the nbdkit server makes it easy to +test: + +$ printf %1000d 1 > f1 +$ ~/nbdkit/nbdkit -fv file f1 & pid=$! +$ qemu-img convert -f raw nbd://localhost:10809 f2 +$ kill $pid +$ qemu-img compare f1 f2 + +Pre-patch, the server attempts a 1024-byte read, which nbdkit +rightfully rejects as going beyond its advertised 1000 byte size; the +conversion fails and the output files differ (not even the first +sector is copied, because qemu-img does not follow ddrescue's habit of +trying smaller reads to get as much information as possible in spite +of errors). Post-patch, the client's attempts to read (and query block +status, for new enough nbdkit) are properly truncated to the server's +length, with sane handling of the hole the block layer forced on +us. Although f2 ends up as a larger file (1024 bytes instead of 1000), +qemu-img compare shows the two images to have identical contents for +display to the guest. + +I didn't add iotests coverage since I didn't want to add a dependency +on nbdkit in iotests. I also did NOT patch write, trim, or write +zeroes - these commands continue to fail (usually with ENOSPC, but +whatever the server chose), because we really can't write to the end +of the file, and because 'qemu-img convert' is the most common case +where we care about being tolerant (which is read-only). Perhaps we +could truncate the request if the client is writing zeros to the tail, +but that seems like more work, especially if the block layer is fixed +in 4.1 to track byte-accurate sizing (in which case this patch would +be reverted as unnecessary). + +Signed-off-by: Eric Blake +Message-Id: <20190329042750.14704-5-eblake@redhat.com> +Tested-by: Richard W.M. Jones +(cherry picked from commit 9cf638508c0090b33ada4155c7cbb684e08e5ee9) +Signed-off-by: Max Reitz +Signed-off-by: Danilo C. L. de Paula +--- + block/nbd-client.c | 39 ++++++++++++++++++++++++++++++++++++++- + 1 file changed, 38 insertions(+), 1 deletion(-) + +diff --git a/block/nbd-client.c b/block/nbd-client.c +index 80d3625..6b33fe3 100644 +--- a/block/nbd-client.c ++++ b/block/nbd-client.c +@@ -790,6 +790,25 @@ int nbd_client_co_preadv(BlockDriverState *bs, uint64_t offset, + if (!bytes) { + return 0; + } ++ /* ++ * Work around the fact that the block layer doesn't do ++ * byte-accurate sizing yet - if the read exceeds the server's ++ * advertised size because the block layer rounded size up, then ++ * truncate the request to the server and tail-pad with zero. ++ */ ++ if (offset >= client->info.size) { ++ assert(bytes < BDRV_SECTOR_SIZE); ++ qemu_iovec_memset(qiov, 0, 0, bytes); ++ return 0; ++ } ++ if (offset + bytes > client->info.size) { ++ uint64_t slop = offset + bytes - client->info.size; ++ ++ assert(slop < BDRV_SECTOR_SIZE); ++ qemu_iovec_memset(qiov, bytes - slop, 0, slop); ++ request.len -= slop; ++ } ++ + ret = nbd_co_send_request(bs, &request, NULL); + if (ret < 0) { + return ret; +@@ -904,7 +923,8 @@ int coroutine_fn nbd_client_co_block_status(BlockDriverState *bs, + .from = offset, + .len = MIN(MIN_NON_ZERO(QEMU_ALIGN_DOWN(INT_MAX, + bs->bl.request_alignment), +- client->info.max_block), bytes), ++ client->info.max_block), ++ MIN(bytes, client->info.size - offset)), + .flags = NBD_CMD_FLAG_REQ_ONE, + }; + +@@ -913,6 +933,23 @@ int coroutine_fn nbd_client_co_block_status(BlockDriverState *bs, + return BDRV_BLOCK_DATA; + } + ++ /* ++ * Work around the fact that the block layer doesn't do ++ * byte-accurate sizing yet - if the status request exceeds the ++ * server's advertised size because the block layer rounded size ++ * up, we truncated the request to the server (above), or are ++ * called on just the hole. ++ */ ++ if (offset >= client->info.size) { ++ *pnum = bytes; ++ assert(bytes < BDRV_SECTOR_SIZE); ++ /* Intentionally don't report offset_valid for the hole */ ++ return BDRV_BLOCK_ZERO; ++ } ++ ++ if (client->info.min_block) { ++ assert(QEMU_IS_ALIGNED(request.len, client->info.min_block)); ++ } + ret = nbd_co_send_request(bs, &request, NULL); + if (ret < 0) { + return ret; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-nbd-server-Advertise-actual-minimum-block-size.patch b/SOURCES/kvm-nbd-server-Advertise-actual-minimum-block-size.patch new file mode 100644 index 0000000..b9312c3 --- /dev/null +++ b/SOURCES/kvm-nbd-server-Advertise-actual-minimum-block-size.patch @@ -0,0 +1,120 @@ +From 1832a90928232cb91a8542613b754079fd1f0f0e Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Tue, 23 Jul 2019 14:45:46 +0100 +Subject: [PATCH 08/14] nbd/server: Advertise actual minimum block size + +RH-Author: Max Reitz +Message-id: <20190723144546.23701-8-mreitz@redhat.com> +Patchwork-id: 89652 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 7/7] nbd/server: Advertise actual minimum block size +Bugzilla: 1678979 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Stefano Garzarella +RH-Acked-by: John Snow + +From: Eric Blake + +Both NBD_CMD_BLOCK_STATUS and structured NBD_CMD_READ will split their +reply according to bdrv_block_status() boundaries. If the block device +has a request_alignment smaller than 512, but we advertise a block +alignment of 512 to the client, then this can result in the server +reply violating client expectations by reporting a smaller region of +the export than what the client is permitted to address (although this +is less of an issue for qemu 4.0 clients, given recent client patches +to overlook our non-compliance at EOF). Since it's always better to +be strict in what we send, it is worth advertising the actual minimum +block limit rather than blindly rounding it up to 512. + +Note that this patch is not foolproof - it is still possible to +provoke non-compliant server behavior using: + +$ qemu-nbd --image-opts driver=blkdebug,align=512,image.driver=file,image.filename=/path/to/non-aligned-file + +That is arguably a bug in the blkdebug driver (it should never pass +back block status smaller than its alignment, even if it has to make +multiple bdrv_get_status calls and determine the +least-common-denominator status among the group to return). It may +also be possible to observe issues with a backing layer with smaller +alignment than the active layer, although so far I have been unable to +write a reliable iotest for that scenario (but again, an issue like +that could be argued to be a bug in the block layer, or something +where we need a flag to bdrv_block_status() to state whether the +result must be aligned to the current layer's limits or can be +subdivided for accuracy when chasing backing files). + +Anyways, as blkdebug is not normally used, and as this patch makes our +server more interoperable with qemu 3.1 clients, it is worth applying +now, even while we still work on a larger patch series for the 4.1 +timeframe to have byte-accurate file lengths. + +Note that the iotests output changes - for 223 and 233, we can see the +server's better granularity advertisement; and for 241, the three test +cases have the following effects: +- natural alignment: the server's smaller alignment is now advertised, +and the hole reported at EOF is now the right result; we've gotten rid +of the server's non-compliance +- forced server alignment: the server still advertises 512 bytes, but +still sends a mid-sector hole. This is still a server compliance bug, +which needs to be fixed in the block layer in a later patch; output +does not change because the client is already being tolerant of the +non-compliance +- forced client alignment: the server's smaller alignment means that +the client now sees the server's status change mid-sector without any +protocol violations, but the fact that the map shows an unaligned +mid-sector hole is evidence of the block layer problems with aligned +block status, to be fixed in a later patch + +Signed-off-by: Eric Blake +Message-Id: <20190329042750.14704-7-eblake@redhat.com> +Reviewed-by: Vladimir Sementsov-Ogievskiy +[eblake: rebase to enhanced iotest 241 coverage] +(cherry picked from commit b0245d6478ea5906e3d7a542244d5c015fd47bc7) + +Signed-off-by: Danilo C. L. de Paula + +Conflicts: +- tests/qemu-iotests/223.out: We are missing + ddd09448fd833d646952c769ae9ce3d39bee989f downstream, which adds + qemu-nbd --list tests to 223. (qemu-nbd --list does not exist + downstream.) + +- tests/qemu-iotests/233.out: Does not exist downstream. + +- tests/qemu-iotests/241.out: Does not exist downstream, because it + would require qemu-nbd --list. + +Signed-off-by: Max Reitz +Signed-off-by: Danilo C. L. de Paula +--- + nbd/server.c | 13 ++++++++----- + 1 file changed, 8 insertions(+), 5 deletions(-) + +diff --git a/nbd/server.c b/nbd/server.c +index e094300..96b6631 100644 +--- a/nbd/server.c ++++ b/nbd/server.c +@@ -608,13 +608,16 @@ static int nbd_negotiate_handle_info(NBDClient *client, uint16_t myflags, + /* Send NBD_INFO_BLOCK_SIZE always, but tweak the minimum size + * according to whether the client requested it, and according to + * whether this is OPT_INFO or OPT_GO. */ +- /* minimum - 1 for back-compat, or 512 if client is new enough. +- * TODO: consult blk_bs(blk)->bl.request_alignment? */ +- sizes[0] = +- (client->opt == NBD_OPT_INFO || blocksize) ? BDRV_SECTOR_SIZE : 1; ++ /* minimum - 1 for back-compat, or actual if client will obey it. */ ++ if (client->opt == NBD_OPT_INFO || blocksize) { ++ sizes[0] = blk_get_request_alignment(exp->blk); ++ } else { ++ sizes[0] = 1; ++ } ++ assert(sizes[0] <= NBD_MAX_BUFFER_SIZE); + /* preferred - Hard-code to 4096 for now. + * TODO: is blk_bs(blk)->bl.opt_transfer appropriate? */ +- sizes[1] = 4096; ++ sizes[1] = MAX(4096, sizes[0]); + /* maximum - At most 32M, but smaller as appropriate. */ + sizes[2] = MIN(blk_get_max_transfer(exp->blk), NBD_MAX_BUFFER_SIZE); + trace_nbd_negotiate_handle_info_block_size(sizes[0], sizes[1], sizes[2]); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-pci-Move-NVIDIA-vendor-id-to-the-rest-of-ids.patch b/SOURCES/kvm-pci-Move-NVIDIA-vendor-id-to-the-rest-of-ids.patch new file mode 100644 index 0000000..d6fa7c5 --- /dev/null +++ b/SOURCES/kvm-pci-Move-NVIDIA-vendor-id-to-the-rest-of-ids.patch @@ -0,0 +1,67 @@ +From 263ca3b7c89b7fd10aa03547624fe37e9a5dca32 Mon Sep 17 00:00:00 2001 +From: David Gibson +Date: Thu, 30 May 2019 04:37:25 +0100 +Subject: [PATCH 4/8] pci: Move NVIDIA vendor id to the rest of ids +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: David Gibson +Message-id: <20190530043728.32575-4-dgibson@redhat.com> +Patchwork-id: 88419 +O-Subject: [RHEL-8.1 qemu-kvm PATCH 3/6] pci: Move NVIDIA vendor id to the rest of ids +Bugzilla: 1710662 +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Laurent Vivier +RH-Acked-by: Auger Eric +RH-Acked-by: Cornelia Huck + +From: Alexey Kardashevskiy + +sPAPR code will use it too so move it from VFIO to the common code. + +Signed-off-by: Alexey Kardashevskiy +Reviewed-by: David Gibson +Reviewed-by: Alistair Francis +Message-Id: <20190214051440.59167-1-aik@ozlabs.ru> +Acked-by: Alex Williamson +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +(cherry picked from commit ee1cd0099ab04f748c6d839e4f4d9a41b21e7399) + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1710662 + +Signed-off-by: David Gibson +Signed-off-by: Danilo C. L. de Paula +--- + hw/vfio/pci-quirks.c | 2 -- + include/hw/pci/pci_ids.h | 2 ++ + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/hw/vfio/pci-quirks.c b/hw/vfio/pci-quirks.c +index cb2f79c..90859d1 100644 +--- a/hw/vfio/pci-quirks.c ++++ b/hw/vfio/pci-quirks.c +@@ -397,8 +397,6 @@ static void vfio_probe_ati_bar2_quirk(VFIOPCIDevice *vdev, int nr) + * note it for future reference. + */ + +-#define PCI_VENDOR_ID_NVIDIA 0x10de +- + /* + * Nvidia has several different methods to get to config space, the + * nouveu project has several of these documented here: +diff --git a/include/hw/pci/pci_ids.h b/include/hw/pci/pci_ids.h +index 63acc72..3ed7d10 100644 +--- a/include/hw/pci/pci_ids.h ++++ b/include/hw/pci/pci_ids.h +@@ -271,4 +271,6 @@ + + #define PCI_VENDOR_ID_SYNOPSYS 0x16C3 + ++#define PCI_VENDOR_ID_NVIDIA 0x10de ++ + #endif +-- +1.8.3.1 + diff --git a/SOURCES/kvm-pci-msi-export-msi_is_masked.patch b/SOURCES/kvm-pci-msi-export-msi_is_masked.patch new file mode 100644 index 0000000..f9090e5 --- /dev/null +++ b/SOURCES/kvm-pci-msi-export-msi_is_masked.patch @@ -0,0 +1,56 @@ +From 010bfb94c27cbdf2c8491606620be47a17d8279c Mon Sep 17 00:00:00 2001 +From: Peter Xu +Date: Tue, 2 Apr 2019 07:25:30 +0100 +Subject: [PATCH 6/7] pci/msi: export msi_is_masked() + +RH-Author: Peter Xu +Message-id: <20190402072531.23771-4-peterx@redhat.com> +Patchwork-id: 85300 +O-Subject: [RHEL-8.1 qemu-kvm PATCH 3/4] pci/msi: export msi_is_masked() +Bugzilla: 1662272 +RH-Acked-by: Wei Huang +RH-Acked-by: Xiao Wang +RH-Acked-by: Michael S. Tsirkin + +It is going to be used later on outside MSI code to detect whether one +MSI vector is masked out. + +Signed-off-by: Peter Xu +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +(cherry picked from commit afa26ecc3010d2851a065edc7817d31e07d236ec) +Signed-off-by: Peter Xu +Signed-off-by: Danilo C. L. de Paula +--- + hw/pci/msi.c | 2 +- + include/hw/pci/msi.h | 1 + + 2 files changed, 2 insertions(+), 1 deletion(-) + +diff --git a/hw/pci/msi.c b/hw/pci/msi.c +index 5e05ce5..47d2b0f 100644 +--- a/hw/pci/msi.c ++++ b/hw/pci/msi.c +@@ -286,7 +286,7 @@ void msi_reset(PCIDevice *dev) + MSI_DEV_PRINTF(dev, "reset\n"); + } + +-static bool msi_is_masked(const PCIDevice *dev, unsigned int vector) ++bool msi_is_masked(const PCIDevice *dev, unsigned int vector) + { + uint16_t flags = pci_get_word(dev->config + msi_flags_off(dev)); + uint32_t mask, data; +diff --git a/include/hw/pci/msi.h b/include/hw/pci/msi.h +index 4837bcf..8440eae 100644 +--- a/include/hw/pci/msi.h ++++ b/include/hw/pci/msi.h +@@ -39,6 +39,7 @@ int msi_init(struct PCIDevice *dev, uint8_t offset, + bool msi_per_vector_mask, Error **errp); + void msi_uninit(struct PCIDevice *dev); + void msi_reset(PCIDevice *dev); ++bool msi_is_masked(const PCIDevice *dev, unsigned int vector); + void msi_notify(PCIDevice *dev, unsigned int vector); + void msi_send_message(PCIDevice *dev, MSIMessage msg); + void msi_write_config(PCIDevice *dev, uint32_t addr, uint32_t val, int len); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-qemu-img-fix-regression-copying-secrets-during-conve.patch b/SOURCES/kvm-qemu-img-fix-regression-copying-secrets-during-conve.patch new file mode 100644 index 0000000..ead5090 --- /dev/null +++ b/SOURCES/kvm-qemu-img-fix-regression-copying-secrets-during-conve.patch @@ -0,0 +1,124 @@ +From 14768fe9b44d6c89c066ebf597b9be79f7d43f30 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Wed, 14 Aug 2019 11:28:11 +0100 +Subject: [PATCH 3/3] qemu-img: fix regression copying secrets during convert +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Kevin Wolf +Message-id: <20190814112811.28642-2-kwolf@redhat.com> +Patchwork-id: 89987 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 1/1] qemu-img: fix regression copying secrets during convert +Bugzilla: 1727821 +RH-Acked-by: Max Reitz +RH-Acked-by: John Snow +RH-Acked-by: Thomas Huth + +From: Daniel P. Berrangé + +When the convert command is creating an output file that needs +secrets, we need to ensure those secrets are passed to both the +blk_new_open and bdrv_create API calls. + +This is done by qemu-img extracting all opts matching the name +suffix "key-secret". Unfortunately the code doing this was run after the +call to bdrv_create(), which meant the QemuOpts it was extracting +secrets from was now empty. + +Previously this worked by luks as a bug meant the "key-secret" +parameters were not purged from the QemuOpts. This bug was fixed in + + commit b76b4f604521e59f857d6177bc55f6f2e41fd392 + Author: Kevin Wolf + Date: Thu Jan 11 16:18:08 2018 +0100 + + qcow2: Use visitor for options in qcow2_create() + +Exposing the latent bug in qemu-img. This fix simply moves the copying +of secrets to before the bdrv_create() call. + +Cc: qemu-stable@nongnu.org +Signed-off-by: Daniel P. Berrangé +Signed-off-by: Kevin Wolf +(cherry picked from commit 8d65a3ccfd5db7f0436e095cd952f5d0c3a873ba) +Signed-off-by: Kevin Wolf +Signed-off-by: Danilo C. L. de Paula +--- + qemu-img.c | 32 +++++++++++++++----------------- + 1 file changed, 15 insertions(+), 17 deletions(-) + +diff --git a/qemu-img.c b/qemu-img.c +index f42750a..fa0cbd7 100644 +--- a/qemu-img.c ++++ b/qemu-img.c +@@ -348,21 +348,6 @@ static int img_add_key_secrets(void *opaque, + return 0; + } + +-static BlockBackend *img_open_new_file(const char *filename, +- QemuOpts *create_opts, +- const char *fmt, int flags, +- bool writethrough, bool quiet, +- bool force_share) +-{ +- QDict *options = NULL; +- +- options = qdict_new(); +- qemu_opt_foreach(create_opts, img_add_key_secrets, options, &error_abort); +- +- return img_open_file(filename, options, fmt, flags, writethrough, quiet, +- force_share); +-} +- + + static BlockBackend *img_open(bool image_opts, + const char *filename, +@@ -1994,6 +1979,7 @@ static int img_convert(int argc, char **argv) + BlockDriverState *out_bs; + QemuOpts *opts = NULL, *sn_opts = NULL; + QemuOptsList *create_opts = NULL; ++ QDict *open_opts = NULL; + char *options = NULL; + Error *local_err = NULL; + bool writethrough, src_writethrough, quiet = false, image_opts = false, +@@ -2342,6 +2328,16 @@ static int img_convert(int argc, char **argv) + } + } + ++ /* ++ * The later open call will need any decryption secrets, and ++ * bdrv_create() will purge "opts", so extract them now before ++ * they are lost. ++ */ ++ if (!skip_create) { ++ open_opts = qdict_new(); ++ qemu_opt_foreach(opts, img_add_key_secrets, open_opts, &error_abort); ++ } ++ + if (!skip_create) { + /* Create the new image */ + ret = bdrv_create(drv, out_filename, opts, &local_err); +@@ -2368,8 +2364,9 @@ static int img_convert(int argc, char **argv) + * That has to wait for bdrv_create to be improved + * to allow filenames in option syntax + */ +- s.target = img_open_new_file(out_filename, opts, out_fmt, +- flags, writethrough, quiet, false); ++ s.target = img_open_file(out_filename, open_opts, out_fmt, ++ flags, writethrough, quiet, false); ++ open_opts = NULL; /* blk_new_open will have freed it */ + } + if (!s.target) { + ret = -1; +@@ -2437,6 +2434,7 @@ out: + qemu_opts_del(opts); + qemu_opts_free(create_opts); + qemu_opts_del(sn_opts); ++ qobject_unref(open_opts); + blk_unref(s.target); + if (s.src) { + for (bs_i = 0; bs_i < s.src_num; bs_i++) { +-- +1.8.3.1 + diff --git a/SOURCES/kvm-qemu-iotests-Filter-NFS-paths.patch b/SOURCES/kvm-qemu-iotests-Filter-NFS-paths.patch new file mode 100644 index 0000000..a891d98 --- /dev/null +++ b/SOURCES/kvm-qemu-iotests-Filter-NFS-paths.patch @@ -0,0 +1,110 @@ +From 065df0fad17065597ffb3baf5b697c82c95c2ed0 Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Mon, 8 Jul 2019 15:25:55 +0100 +Subject: [PATCH 09/39] qemu-iotests: Filter NFS paths +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Pino Toscano +Message-id: <20190708152601.21123-5-ptoscano@redhat.com> +Patchwork-id: 89419 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v3 04/10] qemu-iotests: Filter NFS paths +Bugzilla: 1513367 +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Max Reitz +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Markus Armbruster + +From: Kevin Wolf + +NFS paths were only partially filtered in _filter_img_create, _img_info +and _filter_img_info, resulting in "nfs://127.0.0.1TEST_DIR/t.IMGFMT". +This adds another replacement to the sed calls that matches the test +directory not as a host path, but as an NFS URL (the prefix as used for +$TEST_IMG). + +Signed-off-by: Kevin Wolf +Reviewed-by: Fam Zheng +(cherry picked from commit 8908b253c4ad5f8874c8d13abec169c696a5cd32) +Signed-off-by: Pino Toscano +Signed-off-by: Danilo C. L. de Paula +--- + tests/qemu-iotests/126.out | 2 +- + tests/qemu-iotests/common.filter | 6 ++++-- + tests/qemu-iotests/common.rc | 8 +++++++- + 3 files changed, 12 insertions(+), 4 deletions(-) + +diff --git a/tests/qemu-iotests/126.out b/tests/qemu-iotests/126.out +index 50d7308..17d03d5 100644 +--- a/tests/qemu-iotests/126.out ++++ b/tests/qemu-iotests/126.out +@@ -3,7 +3,7 @@ QA output created by 126 + === Testing plain files === + + Formatting 'TEST_DIR/a:b.IMGFMT', fmt=IMGFMT size=67108864 +-Formatting 'TEST_DIR/a:b.IMGFMT', fmt=IMGFMT size=67108864 ++Formatting 'file:TEST_DIR/a:b.IMGFMT', fmt=IMGFMT size=67108864 + + === Testing relative backing filename resolution === + +diff --git a/tests/qemu-iotests/common.filter b/tests/qemu-iotests/common.filter +index 7acb454..2031e35 100644 +--- a/tests/qemu-iotests/common.filter ++++ b/tests/qemu-iotests/common.filter +@@ -118,7 +118,8 @@ _filter_actual_image_size() + # replace driver-specific options in the "Formatting..." line + _filter_img_create() + { +- sed -e "s#$IMGPROTO:$TEST_DIR#TEST_DIR#g" \ ++ sed -e "s#$REMOTE_TEST_DIR#TEST_DIR#g" \ ++ -e "s#$IMGPROTO:$TEST_DIR#TEST_DIR#g" \ + -e "s#$TEST_DIR#TEST_DIR#g" \ + -e "s#$IMGFMT#IMGFMT#g" \ + -e 's#nbd:127.0.0.1:10810#TEST_DIR/t.IMGFMT#g' \ +@@ -153,7 +154,8 @@ _filter_img_info() + + discard=0 + regex_json_spec_start='^ *"format-specific": \{' +- sed -e "s#$IMGPROTO:$TEST_DIR#TEST_DIR#g" \ ++ sed -e "s#$REMOTE_TEST_DIR#TEST_DIR#g" \ ++ -e "s#$IMGPROTO:$TEST_DIR#TEST_DIR#g" \ + -e "s#$TEST_DIR#TEST_DIR#g" \ + -e "s#$IMGFMT#IMGFMT#g" \ + -e 's#nbd://127.0.0.1:10810$#TEST_DIR/t.IMGFMT#g' \ +diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc +index cb5fa14..d054cb9 100644 +--- a/tests/qemu-iotests/common.rc ++++ b/tests/qemu-iotests/common.rc +@@ -148,6 +148,7 @@ else + TEST_IMG="ssh://127.0.0.1$TEST_IMG_FILE" + elif [ "$IMGPROTO" = "nfs" ]; then + TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT ++ REMOTE_TEST_DIR="nfs://127.0.0.1$TEST_DIR" + TEST_IMG="nfs://127.0.0.1$TEST_IMG_FILE" + elif [ "$IMGPROTO" = "vxhs" ]; then + TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT +@@ -173,6 +174,10 @@ if [ ! -d "$TEST_DIR" ]; then + exit 1 + fi + ++if [ -z "$REMOTE_TEST_DIR" ]; then ++ REMOTE_TEST_DIR="$TEST_DIR" ++fi ++ + if [ ! -d "$SAMPLE_IMG_DIR" ]; then + echo "common.config: Error: \$SAMPLE_IMG_DIR ($SAMPLE_IMG_DIR) is not a directory" + exit 1 +@@ -333,7 +338,8 @@ _img_info() + discard=0 + regex_json_spec_start='^ *"format-specific": \{' + $QEMU_IMG info $QEMU_IMG_EXTRA_ARGS "$@" "$TEST_IMG" 2>&1 | \ +- sed -e "s#$IMGPROTO:$TEST_DIR#TEST_DIR#g" \ ++ sed -e "s#$REMOTE_TEST_DIR#TEST_DIR#g" \ ++ -e "s#$IMGPROTO:$TEST_DIR#TEST_DIR#g" \ + -e "s#$TEST_DIR#TEST_DIR#g" \ + -e "s#$IMGFMT#IMGFMT#g" \ + -e "/^disk size:/ D" \ +-- +1.8.3.1 + diff --git a/SOURCES/kvm-qemu-iotests-Fix-paths-for-NFS.patch b/SOURCES/kvm-qemu-iotests-Fix-paths-for-NFS.patch new file mode 100644 index 0000000..c475e51 --- /dev/null +++ b/SOURCES/kvm-qemu-iotests-Fix-paths-for-NFS.patch @@ -0,0 +1,51 @@ +From 5e41ecd75bc95d1390328218676c72ac1cf4562b Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Mon, 8 Jul 2019 15:25:54 +0100 +Subject: [PATCH 08/39] qemu-iotests: Fix paths for NFS +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Pino Toscano +Message-id: <20190708152601.21123-4-ptoscano@redhat.com> +Patchwork-id: 89423 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v3 03/10] qemu-iotests: Fix paths for NFS +Bugzilla: 1513367 +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Max Reitz +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Markus Armbruster + +From: Kevin Wolf + +Test cases were trying to use nfs:// URLs as local filenames, which made +every test fail for NFS. With TEST_IMG and TEST_IMG_FILE set like for +the other protocols, NFS tests can pass again. + +Signed-off-by: Kevin Wolf +Reviewed-by: Fam Zheng +(cherry picked from commit 655ae6bb91998a01964759406cb38ef215a6ba5b) +Signed-off-by: Pino Toscano +Signed-off-by: Danilo C. L. de Paula +--- + tests/qemu-iotests/common.rc | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc +index 9a65a11..cb5fa14 100644 +--- a/tests/qemu-iotests/common.rc ++++ b/tests/qemu-iotests/common.rc +@@ -147,8 +147,8 @@ else + TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT + TEST_IMG="ssh://127.0.0.1$TEST_IMG_FILE" + elif [ "$IMGPROTO" = "nfs" ]; then +- TEST_DIR="nfs://127.0.0.1/$TEST_DIR" +- TEST_IMG=$TEST_DIR/t.$IMGFMT ++ TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT ++ TEST_IMG="nfs://127.0.0.1$TEST_IMG_FILE" + elif [ "$IMGPROTO" = "vxhs" ]; then + TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT + TEST_IMG="vxhs://127.0.0.1:9999/t.$IMGFMT" +-- +1.8.3.1 + diff --git a/SOURCES/kvm-qxl-check-release-info-object.patch b/SOURCES/kvm-qxl-check-release-info-object.patch new file mode 100644 index 0000000..5f14dc6 --- /dev/null +++ b/SOURCES/kvm-qxl-check-release-info-object.patch @@ -0,0 +1,50 @@ +From 56a21c3a967a6cbf99e2ecb2dff30d4dca759532 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Thu, 20 Jun 2019 13:07:31 +0100 +Subject: [PATCH 1/2] qxl: check release info object +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Philippe Mathieu-Daudé +Message-id: <20190620130731.18034-2-philmd@redhat.com> +Patchwork-id: 88745 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 1/1] qxl: check release info object +Bugzilla: 1712705 +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Stefan Hajnoczi + +From: Prasad J Pandit + +When releasing spice resources in release_resource() routine, +if release info object 'ext.info' is null, it leads to null +pointer dereference. Add check to avoid it. + +Reported-by: Bugs SysSec +Signed-off-by: Prasad J Pandit +Message-id: 20190425063534.32747-1-ppandit@redhat.com +Signed-off-by: Gerd Hoffmann +(cherry picked from commit d52680fc932efb8a2f334cc6993e705ed1e31e99) +Signed-off-by: Danilo C. L. de Paula +--- + hw/display/qxl.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/hw/display/qxl.c b/hw/display/qxl.c +index b373c50..a8c953b 100644 +--- a/hw/display/qxl.c ++++ b/hw/display/qxl.c +@@ -776,6 +776,9 @@ static void interface_release_resource(QXLInstance *sin, + QXLReleaseRing *ring; + uint64_t *item, id; + ++ if (!ext.info) { ++ return; ++ } + if (ext.group_id == MEMSLOT_GROUP_HOST) { + /* host group -> vga mode update request */ + QXLCommandExt *cmdext = (void *)(intptr_t)(ext.info->id); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-redhat-s390x-cpumodel-enable-mepoch-by-default-for-z.patch b/SOURCES/kvm-redhat-s390x-cpumodel-enable-mepoch-by-default-for-z.patch new file mode 100644 index 0000000..e1316af --- /dev/null +++ b/SOURCES/kvm-redhat-s390x-cpumodel-enable-mepoch-by-default-for-z.patch @@ -0,0 +1,59 @@ +From c2c11da318c64a43bb0ed7d07f329d2f1816eb3f Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Fri, 29 Mar 2019 11:13:37 +0000 +Subject: [PATCH 3/7] redhat: s390x/cpumodel: enable mepoch by default for z14 + GA2 + +RH-Author: Thomas Huth +Message-id: <1553858017-376-4-git-send-email-thuth@redhat.com> +Patchwork-id: 85240 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 3/3] redhat: s390x/cpumodel: enable mepoch by default for z14 GA2 +Bugzilla: 1664371 +RH-Acked-by: David Hildenbrand +RH-Acked-by: Cornelia Huck +RH-Acked-by: Jens Freimann + +Upstream-status: n/a (downstream only) + +Enable the mepoch feature for the new z14 GA2 CPU model. In upstream +QEMU, this feature has already been enabled by default for the GA1 +CPU model in new machine types, too: + + 84176c7906ffaf59457bd7dff25a3ea32e00c3d8 + "s390x/cpumodel: default enable mepoch for z14 and later" + +But since we do not have new machine types in RHEL8 qemu-kvm yet, +we can not play the trick with the machine type here and thus can +only enable mepoch for the new z14 GA2 CPU. Users of the z14 GA1 +CPU will have to enable this feature manually. + +Signed-off-by: Thomas Huth +Signed-off-by: Danilo C. L. de Paula +--- + target/s390x/gen-features.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/target/s390x/gen-features.c b/target/s390x/gen-features.c +index dee8375..739d5f1 100644 +--- a/target/s390x/gen-features.c ++++ b/target/s390x/gen-features.c +@@ -556,7 +556,15 @@ static uint16_t default_GEN14_GA1[] = { + S390_FEAT_GROUP_MSA_EXT_8, + }; + +-#define default_GEN14_GA2 EmptyFeat ++/* ++ * Red Hat only: We enable the MULTIPLE_EPOCH features only for z14 GA2 and ++ * not for GA1 already, since we do not have a new s390-ccw-virtio-rhel8.y.0 ++ * machine type for applying upstream commit 84176c7906ffaf59457bd7 correctly. ++ */ ++static uint16_t default_GEN14_GA2[] = { ++ S390_FEAT_MULTIPLE_EPOCH, ++ S390_FEAT_GROUP_MULTIPLE_EPOCH_PTFF, ++}; + + /* QEMU (CPU model) features */ + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390-avoid-potential-null-dereference-in-s390_pcihos.patch b/SOURCES/kvm-s390-avoid-potential-null-dereference-in-s390_pcihos.patch new file mode 100644 index 0000000..b9957b5 --- /dev/null +++ b/SOURCES/kvm-s390-avoid-potential-null-dereference-in-s390_pcihos.patch @@ -0,0 +1,66 @@ +From fae9b269df8dc92176dad05824d8f8e911fb8269 Mon Sep 17 00:00:00 2001 +From: Cornelia Huck +Date: Wed, 17 Apr 2019 13:57:26 +0100 +Subject: [PATCH 09/24] s390: avoid potential null dereference in + s390_pcihost_unplug() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Cornelia Huck +Message-id: <20190417135741.25297-10-cohuck@redhat.com> +Patchwork-id: 85790 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v2 09/24] s390: avoid potential null dereference in s390_pcihost_unplug() +Bugzilla: 1699070 +RH-Acked-by: David Hildenbrand +RH-Acked-by: Thomas Huth +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Jens Freimann + +From: Li Qiang + +When getting the 'pbdev', the if...else has no default branch. +>From Coverity, the 'pbdev' maybe null when the 'dev' is not +the TYPE_PCI_BRIDGE/TYPE_PCI_DEVICE/TYPE_S390_PCI_DEVICE. +This patch adds a default branch for device plug and unplug. + +Spotted by Coverity: CID 1398593 + +Signed-off-by: Li Qiang +Message-Id: <20190108151114.33140-1-liq3ea@163.com> +Reviewed-by: David Hildenbrand +Reviewed-by: Halil Pasic +Reviewed-by: Collin Walling +Signed-off-by: Cornelia Huck +(cherry picked from commit 6ed675c92a80ff83638eef5e12d4aac529c12f93) +Signed-off-by: Cornelia Huck +Signed-off-by: Danilo C. L. de Paula +--- + hw/s390x/s390-pci-bus.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c +index 9c444b6..486c4b6 100644 +--- a/hw/s390x/s390-pci-bus.c ++++ b/hw/s390x/s390-pci-bus.c +@@ -916,6 +916,8 @@ static void s390_pcihost_plug(HotplugHandler *hotplug_dev, DeviceState *dev, + pbdev->fh = pbdev->idx; + QTAILQ_INSERT_TAIL(&s->zpci_devs, pbdev, link); + g_hash_table_insert(s->zpci_table, &pbdev->idx, pbdev); ++ } else { ++ g_assert_not_reached(); + } + } + +@@ -960,6 +962,8 @@ static void s390_pcihost_unplug(HotplugHandler *hotplug_dev, DeviceState *dev, + } else if (object_dynamic_cast(OBJECT(dev), TYPE_S390_PCI_DEVICE)) { + pbdev = S390_PCI_DEVICE(dev); + pci_dev = pbdev->pdev; ++ } else { ++ g_assert_not_reached(); + } + + switch (pbdev->state) { +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390-bios-Skip-bootmap-signature-entries.patch b/SOURCES/kvm-s390-bios-Skip-bootmap-signature-entries.patch new file mode 100644 index 0000000..6d78865 --- /dev/null +++ b/SOURCES/kvm-s390-bios-Skip-bootmap-signature-entries.patch @@ -0,0 +1,100 @@ +From 4a1515fe8a1343c66ca3a889897568f13eedd7f3 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Wed, 8 May 2019 13:37:49 +0100 +Subject: [PATCH] s390-bios: Skip bootmap signature entries + +RH-Author: Thomas Huth +Message-id: <20190508133749.11555-2-thuth@redhat.com> +Patchwork-id: 87209 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 1/1] s390-bios: Skip bootmap signature entries +Bugzilla: 1683275 +RH-Acked-by: David Hildenbrand +RH-Acked-by: Jens Freimann +RH-Acked-by: Cornelia Huck + +From: "Jason J. Herne" + +Newer versions of zipl have the ability to write signature entries to the boot +script for secure boot. We don't yet support secure boot, but we need to skip +over signature entries while reading the boot script in order to maintain our +ability to boot guest operating systems that have a secure bootloader. + +Signed-off-by: Jason J. Herne +Reviewed-by: Farhan Ali +Message-Id: <1556543381-12671-1-git-send-email-jjherne@linux.ibm.com> +Signed-off-by: Thomas Huth +(cherry picked from commit 2497b4a3c08426122d1a89b808c669a734469e5a) +Signed-off-by: Danilo C. L. de Paula +--- + pc-bios/s390-ccw/bootmap.c | 19 +++++++++++++++++-- + pc-bios/s390-ccw/bootmap.h | 10 ++++++---- + 2 files changed, 23 insertions(+), 6 deletions(-) + +diff --git a/pc-bios/s390-ccw/bootmap.c b/pc-bios/s390-ccw/bootmap.c +index e41e715..ffbf671 100644 +--- a/pc-bios/s390-ccw/bootmap.c ++++ b/pc-bios/s390-ccw/bootmap.c +@@ -309,7 +309,14 @@ static void run_eckd_boot_script(block_number_t bmt_block_nr, + memset(sec, FREE_SPACE_FILLER, sizeof(sec)); + read_block(block_nr, sec, "Cannot read Boot Map Script"); + +- for (i = 0; bms->entry[i].type == BOOT_SCRIPT_LOAD; i++) { ++ for (i = 0; bms->entry[i].type == BOOT_SCRIPT_LOAD || ++ bms->entry[i].type == BOOT_SCRIPT_SIGNATURE; i++) { ++ ++ /* We don't support secure boot yet, so we skip signature entries */ ++ if (bms->entry[i].type == BOOT_SCRIPT_SIGNATURE) { ++ continue; ++ } ++ + address = bms->entry[i].address.load_address; + block_nr = eckd_block_num(&bms->entry[i].blkptr.xeckd.bptr.chs); + +@@ -544,7 +551,15 @@ static void zipl_run(ScsiBlockPtr *pte) + + /* Load image(s) into RAM */ + entry = (ComponentEntry *)(&header[1]); +- while (entry->component_type == ZIPL_COMP_ENTRY_LOAD) { ++ while (entry->component_type == ZIPL_COMP_ENTRY_LOAD || ++ entry->component_type == ZIPL_COMP_ENTRY_SIGNATURE) { ++ ++ /* We don't support secure boot yet, so we skip signature entries */ ++ if (entry->component_type == ZIPL_COMP_ENTRY_SIGNATURE) { ++ entry++; ++ continue; ++ } ++ + zipl_load_segment(entry); + + entry++; +diff --git a/pc-bios/s390-ccw/bootmap.h b/pc-bios/s390-ccw/bootmap.h +index 732c111..f1ce423 100644 +--- a/pc-bios/s390-ccw/bootmap.h ++++ b/pc-bios/s390-ccw/bootmap.h +@@ -98,8 +98,9 @@ typedef struct ScsiMbr { + #define ZIPL_COMP_HEADER_IPL 0x00 + #define ZIPL_COMP_HEADER_DUMP 0x01 + +-#define ZIPL_COMP_ENTRY_LOAD 0x02 +-#define ZIPL_COMP_ENTRY_EXEC 0x01 ++#define ZIPL_COMP_ENTRY_EXEC 0x01 ++#define ZIPL_COMP_ENTRY_LOAD 0x02 ++#define ZIPL_COMP_ENTRY_SIGNATURE 0x03 + + typedef struct XEckdMbr { + uint8_t magic[4]; /* == "xIPL" */ +@@ -117,8 +118,9 @@ typedef struct BootMapScriptEntry { + BootMapPointer blkptr; + uint8_t pad[7]; + uint8_t type; /* == BOOT_SCRIPT_* */ +-#define BOOT_SCRIPT_EXEC 0x01 +-#define BOOT_SCRIPT_LOAD 0x02 ++#define BOOT_SCRIPT_EXEC 0x01 ++#define BOOT_SCRIPT_LOAD 0x02 ++#define BOOT_SCRIPT_SIGNATURE 0x03 + union { + uint64_t load_address; + uint64_t load_psw; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390-cpumodel-fix-description-for-the-new-vector-fac.patch b/SOURCES/kvm-s390-cpumodel-fix-description-for-the-new-vector-fac.patch new file mode 100644 index 0000000..9ad4f46 --- /dev/null +++ b/SOURCES/kvm-s390-cpumodel-fix-description-for-the-new-vector-fac.patch @@ -0,0 +1,48 @@ +From bd0e218dc19724fb4c61d259601d116113f114a5 Mon Sep 17 00:00:00 2001 +From: David Hildenbrand +Date: Tue, 16 Jul 2019 20:44:19 +0100 +Subject: [PATCH 17/39] s390: cpumodel: fix description for the new vector + facility + +RH-Author: David Hildenbrand +Message-id: <20190716204422.9350-2-david@redhat.com> +Patchwork-id: 89547 +O-Subject: [RHEL8.1 qemu-kvm PATCH 1/4] s390: cpumodel: fix description for the new vector facility +Bugzilla: 1729975 +RH-Acked-by: Thomas Huth +RH-Acked-by: Cornelia Huck +RH-Acked-by: Jens Freimann + +Conflicts: upstream moved the definitions + +The new facility is called "Vector-Packed-Decimal-Enhancement Facility" +and not "Vector BCD enhancements facility 1". As the shortname might +have already found its way into some backports, let's keep vxbeh. + +Fixes: 54d65de0b525 ("s390x/cpumodel: vector enhancements") +Signed-off-by: Christian Borntraeger +Message-Id: <20190708150931.93448-1-borntraeger@de.ibm.com> +Signed-off-by: Cornelia Huck +(cherry picked from commit d05be57ddc2e1722f527aa4c20d84dfd15c840ec) +Signed-off-by: David Hildenbrand +Signed-off-by: Danilo C. L. de Paula +--- + target/s390x/cpu_features.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/target/s390x/cpu_features.c b/target/s390x/cpu_features.c +index f64f581..5be6f59 100644 +--- a/target/s390x/cpu_features.c ++++ b/target/s390x/cpu_features.c +@@ -111,7 +111,7 @@ static const S390FeatDef s390_features[] = { + FEAT_INIT("vxeh2", S390_FEAT_TYPE_STFL, 148, "Vector Enhancements facility 2"), + FEAT_INIT("esort-base", S390_FEAT_TYPE_STFL, 150, "Enhanced-sort facility (excluding subfunctions)"), + FEAT_INIT("deflate-base", S390_FEAT_TYPE_STFL, 151, "Deflate-conversion facility (excluding subfunctions)"), +- FEAT_INIT("vxbeh", S390_FEAT_TYPE_STFL, 152, "Vector BCD enhancements facility 1"), ++ FEAT_INIT("vxbeh", S390_FEAT_TYPE_STFL, 152, "Vector-Packed-Decimal-Enhancement Facility"), + FEAT_INIT("msa9-base", S390_FEAT_TYPE_STFL, 155, "Message-security-assist-extension-9 facility (excluding subfunctions)"), + FEAT_INIT("etoken", S390_FEAT_TYPE_STFL, 156, "Etoken facility"), + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390-ipl-fix-ipl-with-no-reboot.patch b/SOURCES/kvm-s390-ipl-fix-ipl-with-no-reboot.patch new file mode 100644 index 0000000..598e857 --- /dev/null +++ b/SOURCES/kvm-s390-ipl-fix-ipl-with-no-reboot.patch @@ -0,0 +1,98 @@ +From 663daa42eaaff2b9c071764163005e04133af849 Mon Sep 17 00:00:00 2001 +From: Cornelia Huck +Date: Wed, 17 Apr 2019 13:57:41 +0100 +Subject: [PATCH 24/24] s390/ipl: fix ipl with -no-reboot + +RH-Author: Cornelia Huck +Message-id: <20190417135741.25297-25-cohuck@redhat.com> +Patchwork-id: 85804 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v2 24/24] s390/ipl: fix ipl with -no-reboot +Bugzilla: 1699070 +RH-Acked-by: David Hildenbrand +RH-Acked-by: Thomas Huth +RH-Acked-by: Jens Freimann + +From: Christian Borntraeger + +kexec/kdump as well as the bootloader use a subcode of diagnose 308 +that is supposed to reset the I/O subsystem but not comprise a full +"reboot". With the latest refactoring this is now broken when +-no-reboot is used or when libvirt acts on a reboot QMP event, for +example a virt-install from iso images. + +We need to mark these "subsystem resets" as special. + +Fixes: a30fb811cbe9 (s390x: refactor reset/reipl handling) +Signed-off-by: Christian Borntraeger +Reviewed-by: David Hildenbrand +Message-Id: <20180622102928.173420-1-borntraeger@de.ibm.com> +Acked-by: Paolo Bonzini +Signed-off-by: Cornelia Huck +(cherry picked from commit 76ed4b18debfe597329d1f6a9eb2ec9ffa751ecd) +Signed-off-by: Cornelia Huck +Signed-off-by: Danilo C. L. de Paula +--- + hw/s390x/ipl.c | 8 +++++++- + include/sysemu/sysemu.h | 4 ++++ + vl.c | 4 ++-- + 3 files changed, 13 insertions(+), 3 deletions(-) + +diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c +index ee6701e..21f64ad 100644 +--- a/hw/s390x/ipl.c ++++ b/hw/s390x/ipl.c +@@ -541,7 +541,13 @@ void s390_ipl_reset_request(CPUState *cs, enum s390_reset reset_type) + ipl->iplb_valid = s390_gen_initial_iplb(ipl); + } + } +- qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); ++ if (reset_type == S390_RESET_MODIFIED_CLEAR || ++ reset_type == S390_RESET_LOAD_NORMAL) { ++ /* ignore -no-reboot, send no event */ ++ qemu_system_reset_request(SHUTDOWN_CAUSE_SUBSYSTEM_RESET); ++ } else { ++ qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); ++ } + /* as this is triggered by a CPU, make sure to exit the loop */ + if (tcg_enabled()) { + cpu_loop_exit(cs); +diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h +index 2b42151..f20e4f5 100644 +--- a/include/sysemu/sysemu.h ++++ b/include/sysemu/sysemu.h +@@ -44,6 +44,10 @@ typedef enum ShutdownCause { + turns that into a shutdown */ + SHUTDOWN_CAUSE_GUEST_PANIC, /* Guest panicked, and command line turns + that into a shutdown */ ++ SHUTDOWN_CAUSE_SUBSYSTEM_RESET,/* Partial guest reset that does not trigger ++ QMP events and ignores --no-reboot. This ++ is useful for sanitize hypercalls on s390 ++ that are used during kexec/kdump/boot */ + SHUTDOWN_CAUSE__MAX, + } ShutdownCause; + +diff --git a/vl.c b/vl.c +index 9d32921..c778594 100644 +--- a/vl.c ++++ b/vl.c +@@ -1751,7 +1751,7 @@ void qemu_system_reset(ShutdownCause reason) + } else { + qemu_devices_reset(); + } +- if (reason) { ++ if (reason != SHUTDOWN_CAUSE_SUBSYSTEM_RESET) { + qapi_event_send_reset(shutdown_caused_by_guest(reason), + &error_abort); + } +@@ -1797,7 +1797,7 @@ void qemu_system_guest_panicked(GuestPanicInformation *info) + + void qemu_system_reset_request(ShutdownCause reason) + { +- if (no_reboot) { ++ if (no_reboot && reason != SHUTDOWN_CAUSE_SUBSYSTEM_RESET) { + shutdown_requested = reason; + } else { + reset_requested = reason; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390x-cpumodel-Miscellaneous-Instruction-Extensions-.patch b/SOURCES/kvm-s390x-cpumodel-Miscellaneous-Instruction-Extensions-.patch new file mode 100644 index 0000000..a0e061c --- /dev/null +++ b/SOURCES/kvm-s390x-cpumodel-Miscellaneous-Instruction-Extensions-.patch @@ -0,0 +1,57 @@ +From 2a3b4f0f979edaf74a17204565209734a2b014ef Mon Sep 17 00:00:00 2001 +From: David Hildenbrand +Date: Wed, 22 May 2019 08:03:56 +0100 +Subject: [PATCH 04/12] s390x/cpumodel: Miscellaneous-Instruction-Extensions + Facility 3 + +RH-Author: David Hildenbrand +Message-id: <20190522080402.20173-5-david@redhat.com> +Patchwork-id: 88151 +O-Subject: [RHEL8.1 qemu-kvm PATCH v2 04/10] s390x/cpumodel: Miscellaneous-Instruction-Extensions Facility 3 +Bugzilla: 1660912 +RH-Acked-by: Cornelia Huck +RH-Acked-by: Jens Freimann +RH-Acked-by: Thomas Huth + +Provide the "Miscellaneous-Instruction-Extensions Facility 3" via +stfle.61. + +Signed-off-by: Christian Borntraeger +Reviewed-by: David Hildenbrand +Message-Id: <20190429090250.7648-4-borntraeger@de.ibm.com> +Signed-off-by: Cornelia Huck +(cherry picked from commit 2ec038836fa03103596023e4a1ad7e6eb50ee7c7) +Signed-off-by: David Hildenbrand +Signed-off-by: Danilo C. L. de Paula +--- + target/s390x/cpu_features.c | 1 + + target/s390x/cpu_features_def.h | 1 + + 2 files changed, 2 insertions(+) + +diff --git a/target/s390x/cpu_features.c b/target/s390x/cpu_features.c +index 1843c84..bbd8902 100644 +--- a/target/s390x/cpu_features.c ++++ b/target/s390x/cpu_features.c +@@ -83,6 +83,7 @@ static const S390FeatDef s390_features[] = { + FEAT_INIT("minste2", S390_FEAT_TYPE_STFL, 58, "Miscellaneous-instruction-extensions facility 2"), + FEAT_INIT("sema", S390_FEAT_TYPE_STFL, 59, "Semaphore-assist facility"), + FEAT_INIT("tsi", S390_FEAT_TYPE_STFL, 60, "Time-slice Instrumentation facility"), ++ FEAT_INIT("minste3", S390_FEAT_TYPE_STFL, 61, "Miscellaneous-Instruction-Extensions Facility 3"), + FEAT_INIT("ri", S390_FEAT_TYPE_STFL, 64, "CPU runtime-instrumentation facility"), + FEAT_INIT("zpci", S390_FEAT_TYPE_STFL, 69, "z/PCI facility"), + FEAT_INIT("aen", S390_FEAT_TYPE_STFL, 71, "General-purpose-adapter-event-notification facility"), +diff --git a/target/s390x/cpu_features_def.h b/target/s390x/cpu_features_def.h +index 5fc7e7b..31dd678 100644 +--- a/target/s390x/cpu_features_def.h ++++ b/target/s390x/cpu_features_def.h +@@ -71,6 +71,7 @@ typedef enum { + S390_FEAT_MISC_INSTRUCTION_EXT, + S390_FEAT_SEMAPHORE_ASSIST, + S390_FEAT_TIME_SLICE_INSTRUMENTATION, ++ S390_FEAT_MISC_INSTRUCTION_EXT3, + S390_FEAT_RUNTIME_INSTRUMENTATION, + S390_FEAT_ZPCI, + S390_FEAT_ADAPTER_EVENT_NOTIFICATION, +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390x-cpumodel-add-Deflate-conversion-facility.patch b/SOURCES/kvm-s390x-cpumodel-add-Deflate-conversion-facility.patch new file mode 100644 index 0000000..51bd35e --- /dev/null +++ b/SOURCES/kvm-s390x-cpumodel-add-Deflate-conversion-facility.patch @@ -0,0 +1,180 @@ +From f1b43cf50155508bf93ff4bbd4e9930ab06e8359 Mon Sep 17 00:00:00 2001 +From: David Hildenbrand +Date: Wed, 22 May 2019 08:04:00 +0100 +Subject: [PATCH 08/12] s390x/cpumodel: add Deflate-conversion facility + +RH-Author: David Hildenbrand +Message-id: <20190522080402.20173-9-david@redhat.com> +Patchwork-id: 88155 +O-Subject: [RHEL8.1 qemu-kvm PATCH v2 08/10] s390x/cpumodel: add Deflate-conversion facility +Bugzilla: 1660912 +RH-Acked-by: Cornelia Huck +RH-Acked-by: Jens Freimann +RH-Acked-by: Thomas Huth + +add the deflate conversion facility. + +Signed-off-by: Christian Borntraeger +Message-Id: <20190429090250.7648-8-borntraeger@de.ibm.com> +Reviewed-by: David Hildenbrand +Signed-off-by: Cornelia Huck +(cherry picked from commit afc7b8666b62fe72fdbad7ab0c3f206d4c57c1d1) +Signed-off-by: David Hildenbrand +Signed-off-by: Danilo C. L. de Paula +--- + target/s390x/cpu_features.c | 9 +++++++++ + target/s390x/cpu_features.h | 1 + + target/s390x/cpu_features_def.h | 7 +++++++ + target/s390x/gen-features.c | 12 ++++++++++++ + target/s390x/kvm.c | 6 ++++++ + 5 files changed, 35 insertions(+) + +diff --git a/target/s390x/cpu_features.c b/target/s390x/cpu_features.c +index 1d19b30..f64f581 100644 +--- a/target/s390x/cpu_features.c ++++ b/target/s390x/cpu_features.c +@@ -110,6 +110,7 @@ static const S390FeatDef s390_features[] = { + FEAT_INIT("cmmnt", S390_FEAT_TYPE_STFL, 147, "CMM: ESSA-enhancement (no translate) facility"), + FEAT_INIT("vxeh2", S390_FEAT_TYPE_STFL, 148, "Vector Enhancements facility 2"), + FEAT_INIT("esort-base", S390_FEAT_TYPE_STFL, 150, "Enhanced-sort facility (excluding subfunctions)"), ++ FEAT_INIT("deflate-base", S390_FEAT_TYPE_STFL, 151, "Deflate-conversion facility (excluding subfunctions)"), + FEAT_INIT("vxbeh", S390_FEAT_TYPE_STFL, 152, "Vector BCD enhancements facility 1"), + FEAT_INIT("msa9-base", S390_FEAT_TYPE_STFL, 155, "Message-security-assist-extension-9 facility (excluding subfunctions)"), + FEAT_INIT("etoken", S390_FEAT_TYPE_STFL, 156, "Etoken facility"), +@@ -347,6 +348,11 @@ static const S390FeatDef s390_features[] = { + FEAT_INIT("sortl-32", S390_FEAT_TYPE_SORTL, 130, "SORTL 32 input lists"), + FEAT_INIT("sortl-128", S390_FEAT_TYPE_SORTL, 132, "SORTL 128 input lists"), + FEAT_INIT("sortl-f0", S390_FEAT_TYPE_SORTL, 192, "SORTL format 0 parameter-block"), ++ ++ FEAT_INIT("dfltcc-gdht", S390_FEAT_TYPE_DFLTCC, 1, "DFLTCC GDHT"), ++ FEAT_INIT("dfltcc-cmpr", S390_FEAT_TYPE_DFLTCC, 2, "DFLTCC CMPR"), ++ FEAT_INIT("dfltcc-xpnd", S390_FEAT_TYPE_DFLTCC, 4, "DFLTCC XPND"), ++ FEAT_INIT("dfltcc-f0", S390_FEAT_TYPE_DFLTCC, 192, "DFLTCC format 0 parameter-block"), + }; + + const S390FeatDef *s390_feat_def(S390Feat feat) +@@ -411,6 +417,7 @@ void s390_fill_feat_block(const S390FeatBitmap features, S390FeatType type, + case S390_FEAT_TYPE_KMA: + case S390_FEAT_TYPE_KDSA: + case S390_FEAT_TYPE_SORTL: ++ case S390_FEAT_TYPE_DFLTCC: + set_be_bit(0, data); /* query is always available */ + break; + default: +@@ -439,6 +446,7 @@ void s390_add_from_feat_block(S390FeatBitmap features, S390FeatType type, + break; + case S390_FEAT_TYPE_PLO: + case S390_FEAT_TYPE_SORTL: ++ case S390_FEAT_TYPE_DFLTCC: + nr_bits = 256; + break; + default: +@@ -511,6 +519,7 @@ static S390FeatGroupDef s390_feature_groups[] = { + FEAT_GROUP_INIT("msa9_pckmo", MSA_EXT_9_PCKMO, "Message-security-assist-extension 9 PCKMO subfunctions"), + FEAT_GROUP_INIT("mepochptff", MULTIPLE_EPOCH_PTFF, "PTFF enhancements introduced with Multiple-epoch facility"), + FEAT_GROUP_INIT("esort", ENH_SORT, "Enhanced-sort facility"), ++ FEAT_GROUP_INIT("deflate", DEFLATE_CONVERSION, "Deflate-conversion facility"), + }; + + const S390FeatGroupDef *s390_feat_group_def(S390FeatGroup group) +diff --git a/target/s390x/cpu_features.h b/target/s390x/cpu_features.h +index 3b8c5b2..da695a8 100644 +--- a/target/s390x/cpu_features.h ++++ b/target/s390x/cpu_features.h +@@ -41,6 +41,7 @@ typedef enum { + S390_FEAT_TYPE_KMA, + S390_FEAT_TYPE_KDSA, + S390_FEAT_TYPE_SORTL, ++ S390_FEAT_TYPE_DFLTCC, + } S390FeatType; + + /* Definition of a CPU feature */ +diff --git a/target/s390x/cpu_features_def.h b/target/s390x/cpu_features_def.h +index bb85858..292b17b 100644 +--- a/target/s390x/cpu_features_def.h ++++ b/target/s390x/cpu_features_def.h +@@ -98,6 +98,7 @@ typedef enum { + S390_FEAT_CMM_NT, + S390_FEAT_VECTOR_ENH2, + S390_FEAT_ESORT_BASE, ++ S390_FEAT_DEFLATE_BASE, + S390_FEAT_VECTOR_BCD_ENH, + S390_FEAT_MSA_EXT_9, + S390_FEAT_ETOKEN, +@@ -354,6 +355,12 @@ typedef enum { + S390_FEAT_SORTL_128, + S390_FEAT_SORTL_F0, + ++ /* DEFLATE */ ++ S390_FEAT_DEFLATE_GHDT, ++ S390_FEAT_DEFLATE_CMPR, ++ S390_FEAT_DEFLATE_XPND, ++ S390_FEAT_DEFLATE_F0, ++ + S390_FEAT_MAX, + } S390Feat; + +diff --git a/target/s390x/gen-features.c b/target/s390x/gen-features.c +index 1a94cae..c61bce2 100644 +--- a/target/s390x/gen-features.c ++++ b/target/s390x/gen-features.c +@@ -254,6 +254,13 @@ + S390_FEAT_SORTL_F0 + + ++#define S390_FEAT_GROUP_DEFLATE_CONVERSION \ ++ S390_FEAT_DEFLATE_BASE, \ ++ S390_FEAT_DEFLATE_GHDT, \ ++ S390_FEAT_DEFLATE_CMPR, \ ++ S390_FEAT_DEFLATE_XPND, \ ++ S390_FEAT_DEFLATE_F0 ++ + /* cpu feature groups */ + static uint16_t group_PLO[] = { + S390_FEAT_GROUP_PLO, +@@ -307,6 +314,10 @@ static uint16_t group_ENH_SORT[] = { + S390_FEAT_GROUP_ENH_SORT, + }; + ++static uint16_t group_DEFLATE_CONVERSION[] = { ++ S390_FEAT_GROUP_DEFLATE_CONVERSION, ++}; ++ + /* Base features (in order of release) + * Only non-hypervisor managed features belong here. + * Base feature sets are static meaning they do not change in future QEMU +@@ -765,6 +776,7 @@ static FeatGroupDefSpec FeatGroupDef[] = { + FEAT_GROUP_INITIALIZER(MSA_EXT_9_PCKMO), + FEAT_GROUP_INITIALIZER(MULTIPLE_EPOCH_PTFF), + FEAT_GROUP_INITIALIZER(ENH_SORT), ++ FEAT_GROUP_INITIALIZER(DEFLATE_CONVERSION), + }; + + #define QEMU_FEAT_INITIALIZER(_name) \ +diff --git a/target/s390x/kvm.c b/target/s390x/kvm.c +index b7e3f33..1d6cc33 100644 +--- a/target/s390x/kvm.c ++++ b/target/s390x/kvm.c +@@ -2085,6 +2085,9 @@ static int query_cpu_subfunc(S390FeatBitmap features) + if (test_bit(S390_FEAT_ESORT_BASE, features)) { + s390_add_from_feat_block(features, S390_FEAT_TYPE_SORTL, prop.sortl); + } ++ if (test_bit(S390_FEAT_DEFLATE_BASE, features)) { ++ s390_add_from_feat_block(features, S390_FEAT_TYPE_DFLTCC, prop.dfltcc); ++ } + return 0; + } + +@@ -2135,6 +2138,9 @@ static int configure_cpu_subfunc(const S390FeatBitmap features) + if (test_bit(S390_FEAT_ESORT_BASE, features)) { + s390_fill_feat_block(features, S390_FEAT_TYPE_SORTL, prop.sortl); + } ++ if (test_bit(S390_FEAT_DEFLATE_BASE, features)) { ++ s390_fill_feat_block(features, S390_FEAT_TYPE_DFLTCC, prop.dfltcc); ++ } + return kvm_vm_ioctl(kvm_state, KVM_SET_DEVICE_ATTR, &attr); + } + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390x-cpumodel-add-gen15-defintions.patch b/SOURCES/kvm-s390x-cpumodel-add-gen15-defintions.patch new file mode 100644 index 0000000..1df1118 --- /dev/null +++ b/SOURCES/kvm-s390x-cpumodel-add-gen15-defintions.patch @@ -0,0 +1,132 @@ +From 4acb439f71797a92ad4d442becdeff28fc36c83a Mon Sep 17 00:00:00 2001 +From: David Hildenbrand +Date: Wed, 22 May 2019 08:04:01 +0100 +Subject: [PATCH 09/12] s390x/cpumodel: add gen15 defintions + +RH-Author: David Hildenbrand +Message-id: <20190522080402.20173-10-david@redhat.com> +Patchwork-id: 88156 +O-Subject: [RHEL8.1 qemu-kvm PATCH v2 09/10] s390x/cpumodel: add gen15 defintions +Bugzilla: 1660912 +RH-Acked-by: Cornelia Huck +RH-Acked-by: Jens Freimann +RH-Acked-by: Thomas Huth + +add several new features (msa9, sort, deflate, additional vector +instructions, new general purpose instructions) to generation 15. + +Also disable csske and bpb from the default and base models >=15. +This will allow to migrate gen15 machines to future machines that +do not have these features. + +Signed-off-by: Christian Borntraeger +Message-Id: <20190429090250.7648-9-borntraeger@de.ibm.com> +Reviewed-by: David Hildenbrand +Signed-off-by: Cornelia Huck +(cherry picked from commit caef62430fed6e732d3e43d76752d165cf02ad67) + + Conflicts: + target/s390x/gen-features.c: + Minor contextual conflict due to a different z14-GA2 + default model definition (upstream already adds these + features to the z14-GA1 model). + +Signed-off-by: David Hildenbrand +Signed-off-by: Danilo C. L. de Paula +--- + target/s390x/gen-features.c | 37 +++++++++++++++++++++++++++++++++++++ + 1 file changed, 37 insertions(+) + +diff --git a/target/s390x/gen-features.c b/target/s390x/gen-features.c +index c61bce2..818d51c 100644 +--- a/target/s390x/gen-features.c ++++ b/target/s390x/gen-features.c +@@ -13,6 +13,7 @@ + + #include + #include ++#include + #include "cpu_features_def.h" + + #define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0])) +@@ -419,6 +420,10 @@ static uint16_t base_GEN14_GA1[] = { + + #define base_GEN14_GA2 EmptyFeat + ++static uint16_t base_GEN15_GA1[] = { ++ S390_FEAT_MISC_INSTRUCTION_EXT3, ++}; ++ + /* Full features (in order of release) + * Automatically includes corresponding base features. + * Full features are all features this hardware supports even if kvm/QEMU do not +@@ -548,6 +553,16 @@ static uint16_t full_GEN14_GA1[] = { + + #define full_GEN14_GA2 EmptyFeat + ++static uint16_t full_GEN15_GA1[] = { ++ S390_FEAT_VECTOR_ENH2, ++ S390_FEAT_GROUP_ENH_SORT, ++ S390_FEAT_GROUP_DEFLATE_CONVERSION, ++ S390_FEAT_VECTOR_BCD_ENH, ++ S390_FEAT_GROUP_MSA_EXT_9, ++ S390_FEAT_GROUP_MSA_EXT_9_PCKMO, ++ S390_FEAT_ETOKEN, ++}; ++ + /* Default features (in order of release) + * Automatically includes corresponding base features. + * Default features are all features this version of QEMU supports for this +@@ -630,6 +645,16 @@ static uint16_t default_GEN14_GA2[] = { + S390_FEAT_GROUP_MULTIPLE_EPOCH_PTFF, + }; + ++static uint16_t default_GEN15_GA1[] = { ++ S390_FEAT_VECTOR_ENH2, ++ S390_FEAT_GROUP_ENH_SORT, ++ S390_FEAT_GROUP_DEFLATE_CONVERSION, ++ S390_FEAT_VECTOR_BCD_ENH, ++ S390_FEAT_GROUP_MSA_EXT_9, ++ S390_FEAT_GROUP_MSA_EXT_9_PCKMO, ++ S390_FEAT_ETOKEN, ++}; ++ + /* QEMU (CPU model) features */ + + static uint16_t qemu_V2_11[] = { +@@ -739,6 +764,7 @@ static CpuFeatDefSpec CpuFeatDef[] = { + CPU_FEAT_INITIALIZER(GEN13_GA2), + CPU_FEAT_INITIALIZER(GEN14_GA1), + CPU_FEAT_INITIALIZER(GEN14_GA2), ++ CPU_FEAT_INITIALIZER(GEN15_GA1), + }; + + #define FEAT_GROUP_INITIALIZER(_name) \ +@@ -806,6 +832,11 @@ static void set_bits(uint64_t list[], BitSpec bits) + } + } + ++static inline void clear_bit(uint64_t list[], unsigned long nr) ++{ ++ list[nr / 64] &= ~(1ULL << (nr % 64)); ++} ++ + static void print_feature_defs(void) + { + uint64_t base_feat[S390_FEAT_MAX / 64 + 1] = {}; +@@ -816,6 +847,12 @@ static void print_feature_defs(void) + printf("\n/* CPU model feature list data */\n"); + + for (i = 0; i < ARRAY_SIZE(CpuFeatDef); i++) { ++ /* With gen15 CSSKE and BPB are deprecated */ ++ if (strcmp(CpuFeatDef[i].name, "S390_FEAT_LIST_GEN15_GA1") == 0) { ++ clear_bit(base_feat, S390_FEAT_CONDITIONAL_SSKE); ++ clear_bit(default_feat, S390_FEAT_CONDITIONAL_SSKE); ++ clear_bit(default_feat, S390_FEAT_BPB); ++ } + set_bits(base_feat, CpuFeatDef[i].base_bits); + /* add the base to the default features */ + set_bits(default_feat, CpuFeatDef[i].base_bits); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390x-cpumodel-add-z14-GA2-model.patch b/SOURCES/kvm-s390x-cpumodel-add-z14-GA2-model.patch new file mode 100644 index 0000000..3aeb598 --- /dev/null +++ b/SOURCES/kvm-s390x-cpumodel-add-z14-GA2-model.patch @@ -0,0 +1,86 @@ +From a74dac6606968b164d38aaec5bd8bc1abef4100d Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Fri, 29 Mar 2019 11:13:36 +0000 +Subject: [PATCH 2/7] s390x/cpumodel: add z14 GA2 model + +RH-Author: Thomas Huth +Message-id: <1553858017-376-3-git-send-email-thuth@redhat.com> +Patchwork-id: 85239 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 2/3] s390x/cpumodel: add z14 GA2 model +Bugzilla: 1664371 +RH-Acked-by: David Hildenbrand +RH-Acked-by: Cornelia Huck +RH-Acked-by: Jens Freimann + +From: Collin Walling + +Introduce the z14 GA2 cpu model for QEMU. There are no new features +introduced with this model, and will inherit the same feature set as +z14 GA1. + +Signed-off-by: Collin Walling +Acked-by: Christian Borntraeger +Reviewed-by: David Hildenbrand +Message-Id: <20190212011657.18324-3-walling@linux.ibm.com> +Signed-off-by: Cornelia Huck +(cherry picked from commit f2a7d1577115bda770d619ff5bc45db1f656edc3) +Signed-off-by: Danilo C. L. de Paula +--- + target/s390x/cpu_models.c | 1 + + target/s390x/gen-features.c | 7 +++++++ + 2 files changed, 8 insertions(+) + +diff --git a/target/s390x/cpu_models.c b/target/s390x/cpu_models.c +index 43f16a7..5e9b716 100644 +--- a/target/s390x/cpu_models.c ++++ b/target/s390x/cpu_models.c +@@ -79,6 +79,7 @@ static S390CPUDef s390_cpu_defs[] = { + CPUDEF_INIT(0x2964, 13, 2, 47, 0x08000000U, "z13.2", "IBM z13 GA2"), + CPUDEF_INIT(0x2965, 13, 2, 47, 0x08000000U, "z13s", "IBM z13s GA1"), + CPUDEF_INIT(0x3906, 14, 1, 47, 0x08000000U, "z14", "IBM z14 GA1"), ++ CPUDEF_INIT(0x3906, 14, 2, 47, 0x08000000U, "z14.2", "IBM z14 GA2"), + CPUDEF_INIT(0x3907, 14, 1, 47, 0x08000000U, "z14ZR1", "IBM z14 Model ZR1 GA1"), + }; + +diff --git a/target/s390x/gen-features.c b/target/s390x/gen-features.c +index 7302269..dee8375 100644 +--- a/target/s390x/gen-features.c ++++ b/target/s390x/gen-features.c +@@ -353,6 +353,8 @@ static uint16_t base_GEN14_GA1[] = { + S390_FEAT_ORDER_PRESERVING_COMPRESSION, + }; + ++#define base_GEN14_GA2 EmptyFeat ++ + /* Full features (in order of release) + * Automatically includes corresponding base features. + * Full features are all features this hardware supports even if kvm/QEMU do not +@@ -480,6 +482,8 @@ static uint16_t full_GEN14_GA1[] = { + S390_FEAT_GROUP_MULTIPLE_EPOCH_PTFF, + }; + ++#define full_GEN14_GA2 EmptyFeat ++ + /* Default features (in order of release) + * Automatically includes corresponding base features. + * Default features are all features this version of QEMU supports for this +@@ -552,6 +556,8 @@ static uint16_t default_GEN14_GA1[] = { + S390_FEAT_GROUP_MSA_EXT_8, + }; + ++#define default_GEN14_GA2 EmptyFeat ++ + /* QEMU (CPU model) features */ + + static uint16_t qemu_V2_11[] = { +@@ -660,6 +666,7 @@ static CpuFeatDefSpec CpuFeatDef[] = { + CPU_FEAT_INITIALIZER(GEN13_GA1), + CPU_FEAT_INITIALIZER(GEN13_GA2), + CPU_FEAT_INITIALIZER(GEN14_GA1), ++ CPU_FEAT_INITIALIZER(GEN14_GA2), + }; + + #define FEAT_GROUP_INITIALIZER(_name) \ +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390x-cpumodel-also-change-name-of-vxbeh.patch b/SOURCES/kvm-s390x-cpumodel-also-change-name-of-vxbeh.patch new file mode 100644 index 0000000..211a7b8 --- /dev/null +++ b/SOURCES/kvm-s390x-cpumodel-also-change-name-of-vxbeh.patch @@ -0,0 +1,56 @@ +From 0b358ba0410babbf96d5c0db6ec0502498871435 Mon Sep 17 00:00:00 2001 +From: David Hildenbrand +Date: Tue, 16 Jul 2019 20:44:21 +0100 +Subject: [PATCH 19/39] s390x/cpumodel: also change name of vxbeh + +RH-Author: David Hildenbrand +Message-id: <20190716204422.9350-4-david@redhat.com> +Patchwork-id: 89550 +O-Subject: [RHEL8.1 qemu-kvm PATCH 3/4] s390x/cpumodel: also change name of vxbeh +Bugzilla: 1729975 +RH-Acked-by: Thomas Huth +RH-Acked-by: Cornelia Huck +RH-Acked-by: Jens Freimann + +Conflicts: upstream moved the definitions + +David suggested to keep everything in sync as 4.1 is not yet released. +This patch fixes the name "vxbeh" into "vxpdeh". + +To simplify the backports this patch will not change VECTOR_BCD_ENH as +this is just an internal name. That will be done by an extra patch that +does not need to be backported. + +Suggested-by: David Hildenbrand +Fixes: d05be57ddc2e ("s390: cpumodel: fix description for the new vector facility") +Fixes: 54d65de0b525 ("s390x/cpumodel: vector enhancements") +Signed-off-by: Christian Borntraeger +Message-Id: <20190715142304.215018-3-borntraeger@de.ibm.com> +[CH: vxp->vxpdeh, as discussed] +Reviewed-by: David Hildenbrand +Reviewed-by: Thomas Huth +Signed-off-by: Cornelia Huck +(cherry picked from commit 0d4cb295db7503fbac2f5bb3e878a56630231fed) +Signed-off-by: David Hildenbrand + +Signed-off-by: Danilo C. L. de Paula +--- + target/s390x/cpu_features.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/target/s390x/cpu_features.c b/target/s390x/cpu_features.c +index 5be6f59..065db76 100644 +--- a/target/s390x/cpu_features.c ++++ b/target/s390x/cpu_features.c +@@ -111,7 +111,7 @@ static const S390FeatDef s390_features[] = { + FEAT_INIT("vxeh2", S390_FEAT_TYPE_STFL, 148, "Vector Enhancements facility 2"), + FEAT_INIT("esort-base", S390_FEAT_TYPE_STFL, 150, "Enhanced-sort facility (excluding subfunctions)"), + FEAT_INIT("deflate-base", S390_FEAT_TYPE_STFL, 151, "Deflate-conversion facility (excluding subfunctions)"), +- FEAT_INIT("vxbeh", S390_FEAT_TYPE_STFL, 152, "Vector-Packed-Decimal-Enhancement Facility"), ++ FEAT_INIT("vxpdeh", S390_FEAT_TYPE_STFL, 152, "Vector-Packed-Decimal-Enhancement Facility"), + FEAT_INIT("msa9-base", S390_FEAT_TYPE_STFL, 155, "Message-security-assist-extension-9 facility (excluding subfunctions)"), + FEAT_INIT("etoken", S390_FEAT_TYPE_STFL, 156, "Etoken facility"), + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390x-cpumodel-change-internal-name-of-vxpdeh-to-mat.patch b/SOURCES/kvm-s390x-cpumodel-change-internal-name-of-vxpdeh-to-mat.patch new file mode 100644 index 0000000..ebdb1c5 --- /dev/null +++ b/SOURCES/kvm-s390x-cpumodel-change-internal-name-of-vxpdeh-to-mat.patch @@ -0,0 +1,73 @@ +From 6bd2a32b23c4d1ea45f7aea34d95817e7f1f5e0b Mon Sep 17 00:00:00 2001 +From: David Hildenbrand +Date: Tue, 16 Jul 2019 20:44:22 +0100 +Subject: [PATCH 20/39] s390x/cpumodel: change internal name of vxpdeh to match + description + +RH-Author: David Hildenbrand +Message-id: <20190716204422.9350-5-david@redhat.com> +Patchwork-id: 89548 +O-Subject: [RHEL8.1 qemu-kvm PATCH 4/4] s390x/cpumodel: change internal name of vxpdeh to match description +Bugzilla: 1729975 +RH-Acked-by: Thomas Huth +RH-Acked-by: Cornelia Huck +RH-Acked-by: Jens Freimann + +Conflicts: upstream changed the way cpu features are defined + +The internal macro name VECTOR_BCD_ENH does not match the actual +description. Fix this. + +Signed-off-by: Christian Borntraeger +Message-Id: <20190715142304.215018-4-borntraeger@de.ibm.com> +[CH: vxp->vxpdeh, as discussed] +Reviewed-by: David Hildenbrand +Reviewed-by: Thomas Huth +Signed-off-by: Cornelia Huck +(cherry picked from commit 5d8866c89817998a3d9c3055d5dc2b5a8e78658a) +Signed-off-by: David Hildenbrand + +Signed-off-by: Danilo C. L. de Paula +--- + target/s390x/cpu_features_def.h | 2 +- + target/s390x/gen-features.c | 4 ++-- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/target/s390x/cpu_features_def.h b/target/s390x/cpu_features_def.h +index 292b17b..a7abe4d 100644 +--- a/target/s390x/cpu_features_def.h ++++ b/target/s390x/cpu_features_def.h +@@ -99,7 +99,7 @@ typedef enum { + S390_FEAT_VECTOR_ENH2, + S390_FEAT_ESORT_BASE, + S390_FEAT_DEFLATE_BASE, +- S390_FEAT_VECTOR_BCD_ENH, ++ S390_FEAT_VECTOR_PACKED_DECIMAL_ENH, + S390_FEAT_MSA_EXT_9, + S390_FEAT_ETOKEN, + +diff --git a/target/s390x/gen-features.c b/target/s390x/gen-features.c +index 384d60a..24d78e9 100644 +--- a/target/s390x/gen-features.c ++++ b/target/s390x/gen-features.c +@@ -557,7 +557,7 @@ static uint16_t full_GEN15_GA1[] = { + S390_FEAT_VECTOR_ENH2, + S390_FEAT_GROUP_ENH_SORT, + S390_FEAT_GROUP_DEFLATE_CONVERSION, +- S390_FEAT_VECTOR_BCD_ENH, ++ S390_FEAT_VECTOR_PACKED_DECIMAL_ENH, + S390_FEAT_GROUP_MSA_EXT_9, + S390_FEAT_GROUP_MSA_EXT_9_PCKMO, + S390_FEAT_ETOKEN, +@@ -648,7 +648,7 @@ static uint16_t default_GEN14_GA2[] = { + static uint16_t default_GEN15_GA1[] = { + S390_FEAT_VECTOR_ENH2, + S390_FEAT_GROUP_DEFLATE_CONVERSION, +- S390_FEAT_VECTOR_BCD_ENH, ++ S390_FEAT_VECTOR_PACKED_DECIMAL_ENH, + S390_FEAT_GROUP_MSA_EXT_9, + S390_FEAT_GROUP_MSA_EXT_9_PCKMO, + S390_FEAT_ETOKEN, +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390x-cpumodel-enhanced-sort-facility.patch b/SOURCES/kvm-s390x-cpumodel-enhanced-sort-facility.patch new file mode 100644 index 0000000..5458e2b --- /dev/null +++ b/SOURCES/kvm-s390x-cpumodel-enhanced-sort-facility.patch @@ -0,0 +1,184 @@ +From 51cdec5fac585a2bd7c2ed4fc3501cb6622ad493 Mon Sep 17 00:00:00 2001 +From: David Hildenbrand +Date: Wed, 22 May 2019 08:03:59 +0100 +Subject: [PATCH 07/12] s390x/cpumodel: enhanced sort facility + +RH-Author: David Hildenbrand +Message-id: <20190522080402.20173-8-david@redhat.com> +Patchwork-id: 88154 +O-Subject: [RHEL8.1 qemu-kvm PATCH v2 07/10] s390x/cpumodel: enhanced sort facility +Bugzilla: 1660912 +RH-Acked-by: Cornelia Huck +RH-Acked-by: Jens Freimann +RH-Acked-by: Thomas Huth + +add the enhanced sort facility. + +Signed-off-by: Christian Borntraeger +Reviewed-by: David Hildenbrand +Message-Id: <20190429090250.7648-7-borntraeger@de.ibm.com> +Signed-off-by: Cornelia Huck +(cherry picked from commit d220fabf16091ca5c26f3313541bdfb7435d6a08) +Signed-off-by: David Hildenbrand +Signed-off-by: Danilo C. L. de Paula +--- + target/s390x/cpu_features.c | 10 ++++++++++ + target/s390x/cpu_features.h | 1 + + target/s390x/cpu_features_def.h | 8 ++++++++ + target/s390x/gen-features.c | 14 ++++++++++++++ + target/s390x/kvm.c | 6 ++++++ + 5 files changed, 39 insertions(+) + +diff --git a/target/s390x/cpu_features.c b/target/s390x/cpu_features.c +index 3587325..1d19b30 100644 +--- a/target/s390x/cpu_features.c ++++ b/target/s390x/cpu_features.c +@@ -109,6 +109,7 @@ static const S390FeatDef s390_features[] = { + FEAT_INIT("msa8-base", S390_FEAT_TYPE_STFL, 146, "Message-security-assist-extension-8 facility (excluding subfunctions)"), + FEAT_INIT("cmmnt", S390_FEAT_TYPE_STFL, 147, "CMM: ESSA-enhancement (no translate) facility"), + FEAT_INIT("vxeh2", S390_FEAT_TYPE_STFL, 148, "Vector Enhancements facility 2"), ++ FEAT_INIT("esort-base", S390_FEAT_TYPE_STFL, 150, "Enhanced-sort facility (excluding subfunctions)"), + FEAT_INIT("vxbeh", S390_FEAT_TYPE_STFL, 152, "Vector BCD enhancements facility 1"), + FEAT_INIT("msa9-base", S390_FEAT_TYPE_STFL, 155, "Message-security-assist-extension-9 facility (excluding subfunctions)"), + FEAT_INIT("etoken", S390_FEAT_TYPE_STFL, 156, "Etoken facility"), +@@ -340,6 +341,12 @@ static const S390FeatDef s390_features[] = { + FEAT_INIT("kdsa-eddsa-sign-ed448", S390_FEAT_TYPE_KDSA, 44, "KDSA EdDSA-Sign-Ed448"), + FEAT_INIT("kdsa-eeddsa-sign-ed25519", S390_FEAT_TYPE_KDSA, 48, "KDSA Encrypted-EdDSA-Sign-Ed25519"), + FEAT_INIT("kdsa-eeddsa-sign-ed448", S390_FEAT_TYPE_KDSA, 52, "KDSA Encrypted-EdDSA-Sign-Ed448"), ++ ++ FEAT_INIT("sortl-sflr", S390_FEAT_TYPE_SORTL, 1, "SORTL SFLR"), ++ FEAT_INIT("sortl-svlr", S390_FEAT_TYPE_SORTL, 2, "SORTL SVLR"), ++ FEAT_INIT("sortl-32", S390_FEAT_TYPE_SORTL, 130, "SORTL 32 input lists"), ++ FEAT_INIT("sortl-128", S390_FEAT_TYPE_SORTL, 132, "SORTL 128 input lists"), ++ FEAT_INIT("sortl-f0", S390_FEAT_TYPE_SORTL, 192, "SORTL format 0 parameter-block"), + }; + + const S390FeatDef *s390_feat_def(S390Feat feat) +@@ -403,6 +410,7 @@ void s390_fill_feat_block(const S390FeatBitmap features, S390FeatType type, + case S390_FEAT_TYPE_PPNO: + case S390_FEAT_TYPE_KMA: + case S390_FEAT_TYPE_KDSA: ++ case S390_FEAT_TYPE_SORTL: + set_be_bit(0, data); /* query is always available */ + break; + default: +@@ -430,6 +438,7 @@ void s390_add_from_feat_block(S390FeatBitmap features, S390FeatType type, + nr_bits = 16384; + break; + case S390_FEAT_TYPE_PLO: ++ case S390_FEAT_TYPE_SORTL: + nr_bits = 256; + break; + default: +@@ -501,6 +510,7 @@ static S390FeatGroupDef s390_feature_groups[] = { + FEAT_GROUP_INIT("msa9", MSA_EXT_9, "Message-security-assist-extension 9 facility"), + FEAT_GROUP_INIT("msa9_pckmo", MSA_EXT_9_PCKMO, "Message-security-assist-extension 9 PCKMO subfunctions"), + FEAT_GROUP_INIT("mepochptff", MULTIPLE_EPOCH_PTFF, "PTFF enhancements introduced with Multiple-epoch facility"), ++ FEAT_GROUP_INIT("esort", ENH_SORT, "Enhanced-sort facility"), + }; + + const S390FeatGroupDef *s390_feat_group_def(S390FeatGroup group) +diff --git a/target/s390x/cpu_features.h b/target/s390x/cpu_features.h +index 5ffd3db..3b8c5b2 100644 +--- a/target/s390x/cpu_features.h ++++ b/target/s390x/cpu_features.h +@@ -40,6 +40,7 @@ typedef enum { + S390_FEAT_TYPE_PPNO, + S390_FEAT_TYPE_KMA, + S390_FEAT_TYPE_KDSA, ++ S390_FEAT_TYPE_SORTL, + } S390FeatType; + + /* Definition of a CPU feature */ +diff --git a/target/s390x/cpu_features_def.h b/target/s390x/cpu_features_def.h +index ce2223c..bb85858 100644 +--- a/target/s390x/cpu_features_def.h ++++ b/target/s390x/cpu_features_def.h +@@ -97,6 +97,7 @@ typedef enum { + S390_FEAT_MSA_EXT_8, + S390_FEAT_CMM_NT, + S390_FEAT_VECTOR_ENH2, ++ S390_FEAT_ESORT_BASE, + S390_FEAT_VECTOR_BCD_ENH, + S390_FEAT_MSA_EXT_9, + S390_FEAT_ETOKEN, +@@ -346,6 +347,13 @@ typedef enum { + S390_FEAT_EEDDSA_SIGN_ED25519, + S390_FEAT_EEDDSA_SIGN_ED448, + ++ /* SORTL */ ++ S390_FEAT_SORTL_SFLR, ++ S390_FEAT_SORTL_SVLR, ++ S390_FEAT_SORTL_32, ++ S390_FEAT_SORTL_128, ++ S390_FEAT_SORTL_F0, ++ + S390_FEAT_MAX, + } S390Feat; + +diff --git a/target/s390x/gen-features.c b/target/s390x/gen-features.c +index 39cc375..1a94cae 100644 +--- a/target/s390x/gen-features.c ++++ b/target/s390x/gen-features.c +@@ -245,6 +245,15 @@ + S390_FEAT_PCKMO_ECC_ED25519, \ + S390_FEAT_PCKMO_ECC_ED448 + ++#define S390_FEAT_GROUP_ENH_SORT \ ++ S390_FEAT_ESORT_BASE, \ ++ S390_FEAT_SORTL_SFLR, \ ++ S390_FEAT_SORTL_SVLR, \ ++ S390_FEAT_SORTL_32, \ ++ S390_FEAT_SORTL_128, \ ++ S390_FEAT_SORTL_F0 ++ ++ + /* cpu feature groups */ + static uint16_t group_PLO[] = { + S390_FEAT_GROUP_PLO, +@@ -294,6 +303,10 @@ static uint16_t group_MSA_EXT_9_PCKMO[] = { + S390_FEAT_GROUP_MSA_EXT_9_PCKMO, + }; + ++static uint16_t group_ENH_SORT[] = { ++ S390_FEAT_GROUP_ENH_SORT, ++}; ++ + /* Base features (in order of release) + * Only non-hypervisor managed features belong here. + * Base feature sets are static meaning they do not change in future QEMU +@@ -751,6 +764,7 @@ static FeatGroupDefSpec FeatGroupDef[] = { + FEAT_GROUP_INITIALIZER(MSA_EXT_9), + FEAT_GROUP_INITIALIZER(MSA_EXT_9_PCKMO), + FEAT_GROUP_INITIALIZER(MULTIPLE_EPOCH_PTFF), ++ FEAT_GROUP_INITIALIZER(ENH_SORT), + }; + + #define QEMU_FEAT_INITIALIZER(_name) \ +diff --git a/target/s390x/kvm.c b/target/s390x/kvm.c +index 898fe5e..b7e3f33 100644 +--- a/target/s390x/kvm.c ++++ b/target/s390x/kvm.c +@@ -2082,6 +2082,9 @@ static int query_cpu_subfunc(S390FeatBitmap features) + if (test_bit(S390_FEAT_MSA_EXT_9, features)) { + s390_add_from_feat_block(features, S390_FEAT_TYPE_KDSA, prop.kdsa); + } ++ if (test_bit(S390_FEAT_ESORT_BASE, features)) { ++ s390_add_from_feat_block(features, S390_FEAT_TYPE_SORTL, prop.sortl); ++ } + return 0; + } + +@@ -2129,6 +2132,9 @@ static int configure_cpu_subfunc(const S390FeatBitmap features) + if (test_bit(S390_FEAT_MSA_EXT_9, features)) { + s390_fill_feat_block(features, S390_FEAT_TYPE_KDSA, prop.kdsa); + } ++ if (test_bit(S390_FEAT_ESORT_BASE, features)) { ++ s390_fill_feat_block(features, S390_FEAT_TYPE_SORTL, prop.sortl); ++ } + return kvm_vm_ioctl(kvm_state, KVM_SET_DEVICE_ATTR, &attr); + } + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390x-cpumodel-enum-type-S390FeatGroup-now-gets-gene.patch b/SOURCES/kvm-s390x-cpumodel-enum-type-S390FeatGroup-now-gets-gene.patch new file mode 100644 index 0000000..e4f24c6 --- /dev/null +++ b/SOURCES/kvm-s390x-cpumodel-enum-type-S390FeatGroup-now-gets-gene.patch @@ -0,0 +1,149 @@ +From 442feac1a3812e235baee5868d1b6096978fc62c Mon Sep 17 00:00:00 2001 +From: David Hildenbrand +Date: Wed, 22 May 2019 08:03:53 +0100 +Subject: [PATCH 01/12] s390x/cpumodel: enum type S390FeatGroup now gets + generated + +RH-Author: David Hildenbrand +Message-id: <20190522080402.20173-2-david@redhat.com> +Patchwork-id: 88153 +O-Subject: [RHEL8.1 qemu-kvm PATCH v2 01/10] s390x/cpumodel: enum type S390FeatGroup now gets generated +Bugzilla: 1660912 +RH-Acked-by: Cornelia Huck +RH-Acked-by: Jens Freimann +RH-Acked-by: Thomas Huth + +The enumeration type S390FeatGroup is now generated as well. +This shall simplify the definition of new feature groups +without the requirement to modify existing code. + +Signed-off-by: Michael Mueller +Message-Id: <20180725143617.8731-1-mimu@linux.ibm.com> +Acked-by: David Hildenbrand +Acked-by: Christian Borntraeger +Signed-off-by: Cornelia Huck +(cherry picked from commit a5f9ecc49d63a905da6598900e0a0eeec1ef269d) +Signed-off-by: David Hildenbrand +Signed-off-by: Danilo C. L. de Paula +--- + target/s390x/cpu_features.c | 1 - + target/s390x/cpu_features.h | 19 +------------------ + target/s390x/gen-features.c | 18 +++++++++++++++++- + 3 files changed, 18 insertions(+), 20 deletions(-) + +diff --git a/target/s390x/cpu_features.c b/target/s390x/cpu_features.c +index 91e40c2..1843c84 100644 +--- a/target/s390x/cpu_features.c ++++ b/target/s390x/cpu_features.c +@@ -13,7 +13,6 @@ + #include "qemu/osdep.h" + #include "qemu/module.h" + #include "cpu_features.h" +-#include "gen-features.h" + + #define FEAT_INIT(_name, _type, _bit, _desc) \ + { \ +diff --git a/target/s390x/cpu_features.h b/target/s390x/cpu_features.h +index 968b12f..effe790 100644 +--- a/target/s390x/cpu_features.h ++++ b/target/s390x/cpu_features.h +@@ -16,6 +16,7 @@ + + #include "qemu/bitmap.h" + #include "cpu_features_def.h" ++#include "gen-features.h" + + /* CPU features are announced via different ways */ + typedef enum { +@@ -64,24 +65,6 @@ void s390_add_from_feat_block(S390FeatBitmap features, S390FeatType type, + void s390_feat_bitmap_to_ascii(const S390FeatBitmap features, void *opaque, + void (*fn)(const char *name, void *opaque)); + +-/* static groups that will never change */ +-typedef enum { +- S390_FEAT_GROUP_PLO, +- S390_FEAT_GROUP_TOD_CLOCK_STEERING, +- S390_FEAT_GROUP_GEN13_PTFF_ENH, +- S390_FEAT_GROUP_MSA, +- S390_FEAT_GROUP_MSA_EXT_1, +- S390_FEAT_GROUP_MSA_EXT_2, +- S390_FEAT_GROUP_MSA_EXT_3, +- S390_FEAT_GROUP_MSA_EXT_4, +- S390_FEAT_GROUP_MSA_EXT_5, +- S390_FEAT_GROUP_MSA_EXT_6, +- S390_FEAT_GROUP_MSA_EXT_7, +- S390_FEAT_GROUP_MSA_EXT_8, +- S390_FEAT_GROUP_MULTIPLE_EPOCH_PTFF, +- S390_FEAT_GROUP_MAX, +-} S390FeatGroup; +- + /* Definition of a CPU feature group */ + typedef struct { + const char *name; /* name exposed to the user */ +diff --git a/target/s390x/gen-features.c b/target/s390x/gen-features.c +index 739d5f1..dcc5d25 100644 +--- a/target/s390x/gen-features.c ++++ b/target/s390x/gen-features.c +@@ -680,6 +680,7 @@ static CpuFeatDefSpec CpuFeatDef[] = { + #define FEAT_GROUP_INITIALIZER(_name) \ + { \ + .name = "S390_FEAT_GROUP_LIST_" #_name, \ ++ .enum_name = "S390_FEAT_GROUP_" #_name, \ + .bits = \ + { .data = group_##_name, \ + .len = ARRAY_SIZE(group_##_name) }, \ +@@ -687,6 +688,7 @@ static CpuFeatDefSpec CpuFeatDef[] = { + + typedef struct { + const char *name; ++ const char *enum_name; + BitSpec bits; + } FeatGroupDefSpec; + +@@ -697,7 +699,6 @@ static FeatGroupDefSpec FeatGroupDef[] = { + FEAT_GROUP_INITIALIZER(PLO), + FEAT_GROUP_INITIALIZER(TOD_CLOCK_STEERING), + FEAT_GROUP_INITIALIZER(GEN13_PTFF), +- FEAT_GROUP_INITIALIZER(MULTIPLE_EPOCH_PTFF), + FEAT_GROUP_INITIALIZER(MSA), + FEAT_GROUP_INITIALIZER(MSA_EXT_1), + FEAT_GROUP_INITIALIZER(MSA_EXT_2), +@@ -707,6 +708,7 @@ static FeatGroupDefSpec FeatGroupDef[] = { + FEAT_GROUP_INITIALIZER(MSA_EXT_6), + FEAT_GROUP_INITIALIZER(MSA_EXT_7), + FEAT_GROUP_INITIALIZER(MSA_EXT_8), ++ FEAT_GROUP_INITIALIZER(MULTIPLE_EPOCH_PTFF), + }; + + #define QEMU_FEAT_INITIALIZER(_name) \ +@@ -829,6 +831,19 @@ static void print_feature_group_defs(void) + } + } + ++static void print_feature_group_enum_type(void) ++{ ++ int i; ++ ++ printf("\n/* CPU feature group enum type */\n" ++ "typedef enum {\n"); ++ for (i = 0; i < ARRAY_SIZE(FeatGroupDef); i++) { ++ printf("\t%s,\n", FeatGroupDef[i].enum_name); ++ } ++ printf("\tS390_FEAT_GROUP_MAX,\n" ++ "} S390FeatGroup;\n"); ++} ++ + int main(int argc, char *argv[]) + { + printf("/*\n" +@@ -845,6 +860,7 @@ int main(int argc, char *argv[]) + print_feature_defs(); + print_feature_group_defs(); + print_qemu_feature_defs(); ++ print_feature_group_enum_type(); + printf("\n#endif\n"); + return 0; + } +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390x-cpumodel-fix-segmentation-fault-when-baselinin.patch b/SOURCES/kvm-s390x-cpumodel-fix-segmentation-fault-when-baselinin.patch new file mode 100644 index 0000000..950f8b2 --- /dev/null +++ b/SOURCES/kvm-s390x-cpumodel-fix-segmentation-fault-when-baselinin.patch @@ -0,0 +1,73 @@ +From 10cd7878be0501be1e27b7b00c14958efcdb3d9b Mon Sep 17 00:00:00 2001 +From: Cornelia Huck +Date: Wed, 17 Apr 2019 13:57:22 +0100 +Subject: [PATCH 05/24] s390x/cpumodel: fix segmentation fault when baselining + models +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Cornelia Huck +Message-id: <20190417135741.25297-6-cohuck@redhat.com> +Patchwork-id: 85784 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v2 05/24] s390x/cpumodel: fix segmentation fault when baselining models +Bugzilla: 1699070 +RH-Acked-by: David Hildenbrand +RH-Acked-by: Thomas Huth +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Jens Freimann + +From: David Hildenbrand + +Usually, when baselining two CPU models, whereby one of them has base +CPU features disabled (e.g. z14-base,msa=off), we fallback to an older +model that did not have these features in the base model. We always try to +create a "sane" CPU model (as far as possible), and one part of it is that +removing base features is no good and to be avoided. + +Now, if we disable base features that were part of a z900, we're out of +luck. We won't find a CPU model and QEMU will segfault. This is a +scenario that should never happen in real life, but it can be used to +crash QEMU. + +So let's properly report an error if we baseline e.g.: + +{ "execute": "query-cpu-model-baseline", + "arguments" : { "modela": { "name": "z14-base", "props": {"esan3" : false}}, + "modelb": { "name": "z14"}} } + +Instead of segfaulting. + +Signed-off-by: David Hildenbrand +Message-Id: <20180718092330.19465-1-david@redhat.com> +Acked-by: Christian Borntraeger +Signed-off-by: Cornelia Huck +(cherry picked from commit 677ff32db12bcd1bca3a3df733d2478896d6df96) +Signed-off-by: Cornelia Huck +Signed-off-by: Danilo C. L. de Paula +--- + target/s390x/cpu_models.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/target/s390x/cpu_models.c b/target/s390x/cpu_models.c +index 5e9b716..d2c16b8 100644 +--- a/target/s390x/cpu_models.c ++++ b/target/s390x/cpu_models.c +@@ -720,6 +720,14 @@ CpuModelBaselineInfo *arch_query_cpu_model_baseline(CpuModelInfo *infoa, + + model.def = s390_find_cpu_def(cpu_type, max_gen, max_gen_ga, + model.features); ++ ++ /* models without early base features (esan3) are bad */ ++ if (!model.def) { ++ error_setg(errp, "No compatible CPU model could be created as" ++ " important base features are disabled"); ++ return NULL; ++ } ++ + /* strip off features not part of the max model */ + bitmap_and(model.features, model.features, model.def->full_feat, + S390_FEAT_MAX); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390x-cpumodel-ignore-csske-for-expansion.patch b/SOURCES/kvm-s390x-cpumodel-ignore-csske-for-expansion.patch new file mode 100644 index 0000000..61eabc9 --- /dev/null +++ b/SOURCES/kvm-s390x-cpumodel-ignore-csske-for-expansion.patch @@ -0,0 +1,45 @@ +From 382e149180b749ea95f62571b04ce87154d6fe54 Mon Sep 17 00:00:00 2001 +From: David Hildenbrand +Date: Wed, 22 May 2019 08:03:55 +0100 +Subject: [PATCH 03/12] s390x/cpumodel: ignore csske for expansion + +RH-Author: David Hildenbrand +Message-id: <20190522080402.20173-4-david@redhat.com> +Patchwork-id: 88158 +O-Subject: [RHEL8.1 qemu-kvm PATCH v2 03/10] s390x/cpumodel: ignore csske for expansion +Bugzilla: 1660912 +RH-Acked-by: Cornelia Huck +RH-Acked-by: Jens Freimann +RH-Acked-by: Thomas Huth + +csske will be removed in a future machine. Ignore it for expanding the +cpu model. Otherwise qemu falls back to z9. + +Signed-off-by: Christian Borntraeger +Cc: qemu-stable@nongnu.org +Reviewed-by: David Hildenbrand +Message-Id: <20190429090250.7648-3-borntraeger@de.ibm.com> +Signed-off-by: Cornelia Huck +(cherry picked from commit eaf6f642abf1d4d24791b70728d4068428fc4658) +Signed-off-by: David Hildenbrand +Signed-off-by: Danilo C. L. de Paula +--- + target/s390x/cpu_models.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/target/s390x/cpu_models.c b/target/s390x/cpu_models.c +index d2c16b8..b4d9047 100644 +--- a/target/s390x/cpu_models.c ++++ b/target/s390x/cpu_models.c +@@ -1274,6 +1274,8 @@ static void init_ignored_base_feat(void) + S390_FEAT_KM_TDEA_192, + S390_FEAT_KIMD_SHA_1, + S390_FEAT_KLMD_SHA_1, ++ /* CSSKE is deprecated on newer generations */ ++ S390_FEAT_CONDITIONAL_SSKE, + }; + int i; + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390x-cpumodel-mepochptff-warn-when-no-mepoch-and-re.patch b/SOURCES/kvm-s390x-cpumodel-mepochptff-warn-when-no-mepoch-and-re.patch new file mode 100644 index 0000000..8ce7986 --- /dev/null +++ b/SOURCES/kvm-s390x-cpumodel-mepochptff-warn-when-no-mepoch-and-re.patch @@ -0,0 +1,75 @@ +From 5bb9f99d9dbe71424f656f597b650d5088faca23 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Fri, 29 Mar 2019 11:13:35 +0000 +Subject: [PATCH 1/7] s390x/cpumodel: mepochptff: warn when no mepoch and + re-align group init + +RH-Author: Thomas Huth +Message-id: <1553858017-376-2-git-send-email-thuth@redhat.com> +Patchwork-id: 85237 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 1/3] s390x/cpumodel: mepochptff: warn when no mepoch and re-align group init +Bugzilla: 1664371 +RH-Acked-by: David Hildenbrand +RH-Acked-by: Cornelia Huck +RH-Acked-by: Jens Freimann + +From: Collin Walling + +The extended PTFF features (qsie, qtoue, stoe, stoue) are dependent +on the multiple-epoch facility (mepoch). Let's print a warning if these +features are enabled without mepoch. + +While we're at it, let's move the FEAT_GROUP_INIT for mepochptff down +the s390_feature_groups list so it can be properly indexed with its +generated S390FeatGroup enum. + +Signed-off-by: Collin Walling +Message-Id: <20190212011657.18324-1-walling@linux.ibm.com> +Reviewed-by: Christian Borntraeger +Reviewed-by: David Hildenbrand +Signed-off-by: Cornelia Huck +(cherry picked from commit ddf5d18af3ce3029d5b93222af5a9e8160d4c34b) +Signed-off-by: Danilo C. L. de Paula +--- + target/s390x/cpu_features.c | 2 +- + target/s390x/cpu_models.c | 4 ++++ + 2 files changed, 5 insertions(+), 1 deletion(-) + +diff --git a/target/s390x/cpu_features.c b/target/s390x/cpu_features.c +index 0fbee27..91e40c2 100644 +--- a/target/s390x/cpu_features.c ++++ b/target/s390x/cpu_features.c +@@ -457,7 +457,6 @@ static S390FeatGroupDef s390_feature_groups[] = { + FEAT_GROUP_INIT("plo", PLO, "Perform-locked-operation facility"), + FEAT_GROUP_INIT("tods", TOD_CLOCK_STEERING, "Tod-clock-steering facility"), + FEAT_GROUP_INIT("gen13ptff", GEN13_PTFF, "PTFF enhancements introduced with z13"), +- FEAT_GROUP_INIT("mepochptff", MULTIPLE_EPOCH_PTFF, "PTFF enhancements introduced with Multiple-epoch facility"), + FEAT_GROUP_INIT("msa", MSA, "Message-security-assist facility"), + FEAT_GROUP_INIT("msa1", MSA_EXT_1, "Message-security-assist-extension 1 facility"), + FEAT_GROUP_INIT("msa2", MSA_EXT_2, "Message-security-assist-extension 2 facility"), +@@ -467,6 +466,7 @@ static S390FeatGroupDef s390_feature_groups[] = { + FEAT_GROUP_INIT("msa6", MSA_EXT_6, "Message-security-assist-extension 6 facility"), + FEAT_GROUP_INIT("msa7", MSA_EXT_7, "Message-security-assist-extension 7 facility"), + FEAT_GROUP_INIT("msa8", MSA_EXT_8, "Message-security-assist-extension 8 facility"), ++ FEAT_GROUP_INIT("mepochptff", MULTIPLE_EPOCH_PTFF, "PTFF enhancements introduced with Multiple-epoch facility"), + }; + + const S390FeatGroupDef *s390_feat_group_def(S390FeatGroup group) +diff --git a/target/s390x/cpu_models.c b/target/s390x/cpu_models.c +index 3856104..43f16a7 100644 +--- a/target/s390x/cpu_models.c ++++ b/target/s390x/cpu_models.c +@@ -776,6 +776,10 @@ static void check_consistency(const S390CPUModel *model) + { S390_FEAT_SIE_KSS, S390_FEAT_SIE_F2 }, + { S390_FEAT_AP_QUERY_CONFIG_INFO, S390_FEAT_AP }, + { S390_FEAT_AP_FACILITIES_TEST, S390_FEAT_AP }, ++ { S390_FEAT_PTFF_QSIE, S390_FEAT_MULTIPLE_EPOCH }, ++ { S390_FEAT_PTFF_QTOUE, S390_FEAT_MULTIPLE_EPOCH }, ++ { S390_FEAT_PTFF_STOE, S390_FEAT_MULTIPLE_EPOCH }, ++ { S390_FEAT_PTFF_STOUE, S390_FEAT_MULTIPLE_EPOCH }, + }; + int i; + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390x-cpumodel-msa9-facility.patch b/SOURCES/kvm-s390x-cpumodel-msa9-facility.patch new file mode 100644 index 0000000..bb75cbb --- /dev/null +++ b/SOURCES/kvm-s390x-cpumodel-msa9-facility.patch @@ -0,0 +1,295 @@ +From 2933aa1a4c5ba743e951811080e4e1a44151e165 Mon Sep 17 00:00:00 2001 +From: David Hildenbrand +Date: Wed, 22 May 2019 08:03:57 +0100 +Subject: [PATCH 05/12] s390x/cpumodel: msa9 facility + +RH-Author: David Hildenbrand +Message-id: <20190522080402.20173-6-david@redhat.com> +Patchwork-id: 88161 +O-Subject: [RHEL8.1 qemu-kvm PATCH v2 05/10] s390x/cpumodel: msa9 facility +Bugzilla: 1660912 +RH-Acked-by: Cornelia Huck +RH-Acked-by: Jens Freimann +RH-Acked-by: Thomas Huth + +Provide the MSA9 facility (stfle.155). This also contains pckmo +subfunctions for key wrapping. Keep them in a separate group to disable +those as a block if necessary. This is for example needed when disabling +key wrapping via the HMC. + +Signed-off-by: Christian Borntraeger +Message-Id: <20190429090250.7648-5-borntraeger@de.ibm.com> +Reviewed-by: David Hildenbrand +Signed-off-by: Cornelia Huck +(cherry picked from commit 5dacbe23d23c7f0395fa0e65ff1698f632846714) +Signed-off-by: David Hildenbrand +Signed-off-by: Danilo C. L. de Paula +--- + target/s390x/cpu_features.c | 32 +++++++++++++++++++++++++++++++ + target/s390x/cpu_features.h | 1 + + target/s390x/cpu_features_def.h | 31 ++++++++++++++++++++++++++++++ + target/s390x/cpu_models.c | 2 ++ + target/s390x/gen-features.c | 42 +++++++++++++++++++++++++++++++++++++++++ + target/s390x/kvm.c | 6 ++++++ + 6 files changed, 114 insertions(+) + +diff --git a/target/s390x/cpu_features.c b/target/s390x/cpu_features.c +index bbd8902..154e2bb 100644 +--- a/target/s390x/cpu_features.c ++++ b/target/s390x/cpu_features.c +@@ -108,6 +108,7 @@ static const S390FeatDef s390_features[] = { + FEAT_INIT("irbm", S390_FEAT_TYPE_STFL, 145, "Insert-reference-bits-multiple facility"), + FEAT_INIT("msa8-base", S390_FEAT_TYPE_STFL, 146, "Message-security-assist-extension-8 facility (excluding subfunctions)"), + FEAT_INIT("cmmnt", S390_FEAT_TYPE_STFL, 147, "CMM: ESSA-enhancement (no translate) facility"), ++ FEAT_INIT("msa9-base", S390_FEAT_TYPE_STFL, 155, "Message-security-assist-extension-9 facility (excluding subfunctions)"), + FEAT_INIT("etoken", S390_FEAT_TYPE_STFL, 156, "Etoken facility"), + + /* SCLP SCCB Byte 80 - 98 (bit numbers relative to byte-80) */ +@@ -242,6 +243,11 @@ static const S390FeatDef s390_features[] = { + FEAT_INIT("pckmo-aes-128", S390_FEAT_TYPE_PCKMO, 18, "PCKMO Encrypted-AES-128-Key"), + FEAT_INIT("pckmo-aes-192", S390_FEAT_TYPE_PCKMO, 19, "PCKMO Encrypted-AES-192-Key"), + FEAT_INIT("pckmo-aes-256", S390_FEAT_TYPE_PCKMO, 20, "PCKMO Encrypted-AES-256-Key"), ++ FEAT_INIT("pckmo-ecc-p256", S390_FEAT_TYPE_PCKMO, 32, "PCKMO Encrypt-ECC-P256-Key"), ++ FEAT_INIT("pckmo-ecc-p384", S390_FEAT_TYPE_PCKMO, 33, "PCKMO Encrypt-ECC-P384-Key"), ++ FEAT_INIT("pckmo-ecc-p521", S390_FEAT_TYPE_PCKMO, 34, "PCKMO Encrypt-ECC-P521-Key"), ++ FEAT_INIT("pckmo-ecc-ed25519", S390_FEAT_TYPE_PCKMO, 40 , "PCKMO Encrypt-ECC-Ed25519-Key"), ++ FEAT_INIT("pckmo-ecc-ed448", S390_FEAT_TYPE_PCKMO, 41 , "PCKMO Encrypt-ECC-Ed448-Key"), + + FEAT_INIT("kmctr-dea", S390_FEAT_TYPE_KMCTR, 1, "KMCTR DEA"), + FEAT_INIT("kmctr-tdea-128", S390_FEAT_TYPE_KMCTR, 2, "KMCTR TDEA-128"), +@@ -298,6 +304,13 @@ static const S390FeatDef s390_features[] = { + FEAT_INIT("pcc-xts-aes-256", S390_FEAT_TYPE_PCC, 52, "PCC Compute-XTS-Parameter-Using-AES-256"), + FEAT_INIT("pcc-xts-eaes-128", S390_FEAT_TYPE_PCC, 58, "PCC Compute-XTS-Parameter-Using-Encrypted-AES-128"), + FEAT_INIT("pcc-xts-eaes-256", S390_FEAT_TYPE_PCC, 60, "PCC Compute-XTS-Parameter-Using-Encrypted-AES-256"), ++ FEAT_INIT("pcc-scalar-mult-p256", S390_FEAT_TYPE_PCC, 64, "PCC Scalar-Multiply-P256"), ++ FEAT_INIT("pcc-scalar-mult-p384", S390_FEAT_TYPE_PCC, 65, "PCC Scalar-Multiply-P384"), ++ FEAT_INIT("pcc-scalar-mult-p521", S390_FEAT_TYPE_PCC, 66, "PCC Scalar-Multiply-P521"), ++ FEAT_INIT("pcc-scalar-mult-ed25519", S390_FEAT_TYPE_PCC, 72, "PCC Scalar-Multiply-Ed25519"), ++ FEAT_INIT("pcc-scalar-mult-ed448", S390_FEAT_TYPE_PCC, 73, "PCC Scalar-Multiply-Ed448"), ++ FEAT_INIT("pcc-scalar-mult-x25519", S390_FEAT_TYPE_PCC, 80, "PCC Scalar-Multiply-X25519"), ++ FEAT_INIT("pcc-scalar-mult-x448", S390_FEAT_TYPE_PCC, 81, "PCC Scalar-Multiply-X448"), + + FEAT_INIT("ppno-sha-512-drng", S390_FEAT_TYPE_PPNO, 3, "PPNO SHA-512-DRNG"), + FEAT_INIT("prno-trng-qrtcr", S390_FEAT_TYPE_PPNO, 112, "PRNO TRNG-Query-Raw-to-Conditioned-Ratio"), +@@ -309,6 +322,22 @@ static const S390FeatDef s390_features[] = { + FEAT_INIT("kma-gcm-eaes-128", S390_FEAT_TYPE_KMA, 26, "KMA GCM-Encrypted-AES-128"), + FEAT_INIT("kma-gcm-eaes-192", S390_FEAT_TYPE_KMA, 27, "KMA GCM-Encrypted-AES-192"), + FEAT_INIT("kma-gcm-eaes-256", S390_FEAT_TYPE_KMA, 28, "KMA GCM-Encrypted-AES-256"), ++ ++ FEAT_INIT("kdsa-ecdsa-verify-p256", S390_FEAT_TYPE_KDSA, 1, "KDSA ECDSA-Verify-P256"), ++ FEAT_INIT("kdsa-ecdsa-verify-p384", S390_FEAT_TYPE_KDSA, 2, "KDSA ECDSA-Verify-P384"), ++ FEAT_INIT("kdsa-ecdsa-verify-p521", S390_FEAT_TYPE_KDSA, 3, "KDSA ECDSA-Verify-P521"), ++ FEAT_INIT("kdsa-ecdsa-sign-p256", S390_FEAT_TYPE_KDSA, 9, "KDSA ECDSA-Sign-P256"), ++ FEAT_INIT("kdsa-ecdsa-sign-p384", S390_FEAT_TYPE_KDSA, 10, "KDSA ECDSA-Sign-P384"), ++ FEAT_INIT("kdsa-ecdsa-sign-p521", S390_FEAT_TYPE_KDSA, 11, "KDSA ECDSA-Sign-P521"), ++ FEAT_INIT("kdsa-eecdsa-sign-p256", S390_FEAT_TYPE_KDSA, 17, "KDSA Encrypted-ECDSA-Sign-P256"), ++ FEAT_INIT("kdsa-eecdsa-sign-p384", S390_FEAT_TYPE_KDSA, 18, "KDSA Encrypted-ECDSA-Sign-P384"), ++ FEAT_INIT("kdsa-eecdsa-sign-p521", S390_FEAT_TYPE_KDSA, 19, "KDSA Encrypted-ECDSA-Sign-P521"), ++ FEAT_INIT("kdsa-eddsa-verify-ed25519", S390_FEAT_TYPE_KDSA, 32, "KDSA EdDSA-Verify-Ed25519"), ++ FEAT_INIT("kdsa-eddsa-verify-ed448", S390_FEAT_TYPE_KDSA, 36, "KDSA EdDSA-Verify-Ed448"), ++ FEAT_INIT("kdsa-eddsa-sign-ed25519", S390_FEAT_TYPE_KDSA, 40, "KDSA EdDSA-Sign-Ed25519"), ++ FEAT_INIT("kdsa-eddsa-sign-ed448", S390_FEAT_TYPE_KDSA, 44, "KDSA EdDSA-Sign-Ed448"), ++ FEAT_INIT("kdsa-eeddsa-sign-ed25519", S390_FEAT_TYPE_KDSA, 48, "KDSA Encrypted-EdDSA-Sign-Ed25519"), ++ FEAT_INIT("kdsa-eeddsa-sign-ed448", S390_FEAT_TYPE_KDSA, 52, "KDSA Encrypted-EdDSA-Sign-Ed448"), + }; + + const S390FeatDef *s390_feat_def(S390Feat feat) +@@ -371,6 +400,7 @@ void s390_fill_feat_block(const S390FeatBitmap features, S390FeatType type, + case S390_FEAT_TYPE_PCC: + case S390_FEAT_TYPE_PPNO: + case S390_FEAT_TYPE_KMA: ++ case S390_FEAT_TYPE_KDSA: + set_be_bit(0, data); /* query is always available */ + break; + default: +@@ -466,6 +496,8 @@ static S390FeatGroupDef s390_feature_groups[] = { + FEAT_GROUP_INIT("msa6", MSA_EXT_6, "Message-security-assist-extension 6 facility"), + FEAT_GROUP_INIT("msa7", MSA_EXT_7, "Message-security-assist-extension 7 facility"), + FEAT_GROUP_INIT("msa8", MSA_EXT_8, "Message-security-assist-extension 8 facility"), ++ FEAT_GROUP_INIT("msa9", MSA_EXT_9, "Message-security-assist-extension 9 facility"), ++ FEAT_GROUP_INIT("msa9_pckmo", MSA_EXT_9_PCKMO, "Message-security-assist-extension 9 PCKMO subfunctions"), + FEAT_GROUP_INIT("mepochptff", MULTIPLE_EPOCH_PTFF, "PTFF enhancements introduced with Multiple-epoch facility"), + }; + +diff --git a/target/s390x/cpu_features.h b/target/s390x/cpu_features.h +index effe790..5ffd3db 100644 +--- a/target/s390x/cpu_features.h ++++ b/target/s390x/cpu_features.h +@@ -39,6 +39,7 @@ typedef enum { + S390_FEAT_TYPE_PCC, + S390_FEAT_TYPE_PPNO, + S390_FEAT_TYPE_KMA, ++ S390_FEAT_TYPE_KDSA, + } S390FeatType; + + /* Definition of a CPU feature */ +diff --git a/target/s390x/cpu_features_def.h b/target/s390x/cpu_features_def.h +index 31dd678..0307848 100644 +--- a/target/s390x/cpu_features_def.h ++++ b/target/s390x/cpu_features_def.h +@@ -96,6 +96,7 @@ typedef enum { + S390_FEAT_INSERT_REFERENCE_BITS_MULT, + S390_FEAT_MSA_EXT_8, + S390_FEAT_CMM_NT, ++ S390_FEAT_MSA_EXT_9, + S390_FEAT_ETOKEN, + + /* Sclp Conf Char */ +@@ -240,6 +241,11 @@ typedef enum { + S390_FEAT_PCKMO_AES_128, + S390_FEAT_PCKMO_AES_192, + S390_FEAT_PCKMO_AES_256, ++ S390_FEAT_PCKMO_ECC_P256, ++ S390_FEAT_PCKMO_ECC_P384, ++ S390_FEAT_PCKMO_ECC_P521, ++ S390_FEAT_PCKMO_ECC_ED25519, ++ S390_FEAT_PCKMO_ECC_ED448, + + /* KMCTR */ + S390_FEAT_KMCTR_DEA, +@@ -300,6 +306,13 @@ typedef enum { + S390_FEAT_PCC_XTS_AES_256, + S390_FEAT_PCC_XTS_EAES_128, + S390_FEAT_PCC_XTS_EAES_256, ++ S390_FEAT_PCC_SCALAR_MULT_P256, ++ S390_FEAT_PCC_SCALAR_MULT_P384, ++ S390_FEAT_PCC_SCALAR_MULT_P512, ++ S390_FEAT_PCC_SCALAR_MULT_ED25519, ++ S390_FEAT_PCC_SCALAR_MULT_ED448, ++ S390_FEAT_PCC_SCALAR_MULT_X25519, ++ S390_FEAT_PCC_SCALAR_MULT_X448, + + /* PPNO/PRNO */ + S390_FEAT_PPNO_SHA_512_DRNG, +@@ -313,6 +326,24 @@ typedef enum { + S390_FEAT_KMA_GCM_EAES_128, + S390_FEAT_KMA_GCM_EAES_192, + S390_FEAT_KMA_GCM_EAES_256, ++ ++ /* KDSA */ ++ S390_FEAT_ECDSA_VERIFY_P256, ++ S390_FEAT_ECDSA_VERIFY_P384, ++ S390_FEAT_ECDSA_VERIFY_P512, ++ S390_FEAT_ECDSA_SIGN_P256, ++ S390_FEAT_ECDSA_SIGN_P384, ++ S390_FEAT_ECDSA_SIGN_P512, ++ S390_FEAT_EECDSA_SIGN_P256, ++ S390_FEAT_EECDSA_SIGN_P384, ++ S390_FEAT_EECDSA_SIGN_P512, ++ S390_FEAT_EDDSA_VERIFY_ED25519, ++ S390_FEAT_EDDSA_VERIFY_ED448, ++ S390_FEAT_EDDSA_SIGN_ED25519, ++ S390_FEAT_EDDSA_SIGN_ED448, ++ S390_FEAT_EEDDSA_SIGN_ED25519, ++ S390_FEAT_EEDDSA_SIGN_ED448, ++ + S390_FEAT_MAX, + } S390Feat; + +diff --git a/target/s390x/cpu_models.c b/target/s390x/cpu_models.c +index b4d9047..737520b 100644 +--- a/target/s390x/cpu_models.c ++++ b/target/s390x/cpu_models.c +@@ -758,6 +758,8 @@ static void check_consistency(const S390CPUModel *model) + { S390_FEAT_SIE_CMMA, S390_FEAT_SIE_GSLS }, + { S390_FEAT_SIE_PFMFI, S390_FEAT_EDAT }, + { S390_FEAT_MSA_EXT_8, S390_FEAT_MSA_EXT_3 }, ++ { S390_FEAT_MSA_EXT_9, S390_FEAT_MSA_EXT_3 }, ++ { S390_FEAT_MSA_EXT_9, S390_FEAT_MSA_EXT_4 }, + { S390_FEAT_MULTIPLE_EPOCH, S390_FEAT_TOD_CLOCK_STEERING }, + { S390_FEAT_VECTOR_PACKED_DECIMAL, S390_FEAT_VECTOR }, + { S390_FEAT_VECTOR_ENH, S390_FEAT_VECTOR }, +diff --git a/target/s390x/gen-features.c b/target/s390x/gen-features.c +index dcc5d25..39cc375 100644 +--- a/target/s390x/gen-features.c ++++ b/target/s390x/gen-features.c +@@ -213,6 +213,38 @@ + S390_FEAT_KMA_GCM_EAES_192, \ + S390_FEAT_KMA_GCM_EAES_256 + ++#define S390_FEAT_GROUP_MSA_EXT_9 \ ++ S390_FEAT_MSA_EXT_9, \ ++ S390_FEAT_ECDSA_VERIFY_P256, \ ++ S390_FEAT_ECDSA_VERIFY_P384, \ ++ S390_FEAT_ECDSA_VERIFY_P512, \ ++ S390_FEAT_ECDSA_SIGN_P256, \ ++ S390_FEAT_ECDSA_SIGN_P384, \ ++ S390_FEAT_ECDSA_SIGN_P512, \ ++ S390_FEAT_EECDSA_SIGN_P256, \ ++ S390_FEAT_EECDSA_SIGN_P384, \ ++ S390_FEAT_EECDSA_SIGN_P512, \ ++ S390_FEAT_EDDSA_VERIFY_ED25519, \ ++ S390_FEAT_EDDSA_VERIFY_ED448, \ ++ S390_FEAT_EDDSA_SIGN_ED25519, \ ++ S390_FEAT_EDDSA_SIGN_ED448, \ ++ S390_FEAT_EEDDSA_SIGN_ED25519, \ ++ S390_FEAT_EEDDSA_SIGN_ED448, \ ++ S390_FEAT_PCC_SCALAR_MULT_P256, \ ++ S390_FEAT_PCC_SCALAR_MULT_P384, \ ++ S390_FEAT_PCC_SCALAR_MULT_P512, \ ++ S390_FEAT_PCC_SCALAR_MULT_ED25519, \ ++ S390_FEAT_PCC_SCALAR_MULT_ED448, \ ++ S390_FEAT_PCC_SCALAR_MULT_X25519, \ ++ S390_FEAT_PCC_SCALAR_MULT_X448 ++ ++#define S390_FEAT_GROUP_MSA_EXT_9_PCKMO \ ++ S390_FEAT_PCKMO_ECC_P256, \ ++ S390_FEAT_PCKMO_ECC_P384, \ ++ S390_FEAT_PCKMO_ECC_P521, \ ++ S390_FEAT_PCKMO_ECC_ED25519, \ ++ S390_FEAT_PCKMO_ECC_ED448 ++ + /* cpu feature groups */ + static uint16_t group_PLO[] = { + S390_FEAT_GROUP_PLO, +@@ -254,6 +286,14 @@ static uint16_t group_MSA_EXT_8[] = { + S390_FEAT_GROUP_MSA_EXT_8, + }; + ++static uint16_t group_MSA_EXT_9[] = { ++ S390_FEAT_GROUP_MSA_EXT_9, ++}; ++ ++static uint16_t group_MSA_EXT_9_PCKMO[] = { ++ S390_FEAT_GROUP_MSA_EXT_9_PCKMO, ++}; ++ + /* Base features (in order of release) + * Only non-hypervisor managed features belong here. + * Base feature sets are static meaning they do not change in future QEMU +@@ -708,6 +748,8 @@ static FeatGroupDefSpec FeatGroupDef[] = { + FEAT_GROUP_INITIALIZER(MSA_EXT_6), + FEAT_GROUP_INITIALIZER(MSA_EXT_7), + FEAT_GROUP_INITIALIZER(MSA_EXT_8), ++ FEAT_GROUP_INITIALIZER(MSA_EXT_9), ++ FEAT_GROUP_INITIALIZER(MSA_EXT_9_PCKMO), + FEAT_GROUP_INITIALIZER(MULTIPLE_EPOCH_PTFF), + }; + +diff --git a/target/s390x/kvm.c b/target/s390x/kvm.c +index 114502d..898fe5e 100644 +--- a/target/s390x/kvm.c ++++ b/target/s390x/kvm.c +@@ -2079,6 +2079,9 @@ static int query_cpu_subfunc(S390FeatBitmap features) + if (test_bit(S390_FEAT_MSA_EXT_8, features)) { + s390_add_from_feat_block(features, S390_FEAT_TYPE_KMA, prop.kma); + } ++ if (test_bit(S390_FEAT_MSA_EXT_9, features)) { ++ s390_add_from_feat_block(features, S390_FEAT_TYPE_KDSA, prop.kdsa); ++ } + return 0; + } + +@@ -2123,6 +2126,9 @@ static int configure_cpu_subfunc(const S390FeatBitmap features) + if (test_bit(S390_FEAT_MSA_EXT_8, features)) { + s390_fill_feat_block(features, S390_FEAT_TYPE_KMA, prop.kma); + } ++ if (test_bit(S390_FEAT_MSA_EXT_9, features)) { ++ s390_fill_feat_block(features, S390_FEAT_TYPE_KDSA, prop.kdsa); ++ } + return kvm_vm_ioctl(kvm_state, KVM_SET_DEVICE_ATTR, &attr); + } + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390x-cpumodel-remove-esort-from-the-default-model.patch b/SOURCES/kvm-s390x-cpumodel-remove-esort-from-the-default-model.patch new file mode 100644 index 0000000..437c871 --- /dev/null +++ b/SOURCES/kvm-s390x-cpumodel-remove-esort-from-the-default-model.patch @@ -0,0 +1,44 @@ +From 87e37d8c60b92b595e6199f9ea6b10d8502aa564 Mon Sep 17 00:00:00 2001 +From: David Hildenbrand +Date: Tue, 16 Jul 2019 20:44:20 +0100 +Subject: [PATCH 18/39] s390x/cpumodel: remove esort from the default model + +RH-Author: David Hildenbrand +Message-id: <20190716204422.9350-3-david@redhat.com> +Patchwork-id: 89549 +O-Subject: [RHEL8.1 qemu-kvm PATCH 2/4] s390x/cpumodel: remove esort from the default model +Bugzilla: 1729975 +RH-Acked-by: Thomas Huth +RH-Acked-by: Cornelia Huck +RH-Acked-by: Jens Freimann + +esort might not be available on all models. + +Fixes: caef62430fed6e73 ("s390x/cpumodel: add gen15 defintions") +Signed-off-by: Christian Borntraeger +Message-Id: <20190715142304.215018-2-borntraeger@de.ibm.com> +Reviewed-by: David Hildenbrand +Reviewed-by: Thomas Huth +Signed-off-by: Cornelia Huck +(cherry picked from commit de6bb08570065eb318849dfd7f316448e51197b5) +Signed-off-by: David Hildenbrand +Signed-off-by: Danilo C. L. de Paula +--- + target/s390x/gen-features.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/target/s390x/gen-features.c b/target/s390x/gen-features.c +index 818d51c..384d60a 100644 +--- a/target/s390x/gen-features.c ++++ b/target/s390x/gen-features.c +@@ -647,7 +647,6 @@ static uint16_t default_GEN14_GA2[] = { + + static uint16_t default_GEN15_GA1[] = { + S390_FEAT_VECTOR_ENH2, +- S390_FEAT_GROUP_ENH_SORT, + S390_FEAT_GROUP_DEFLATE_CONVERSION, + S390_FEAT_VECTOR_BCD_ENH, + S390_FEAT_GROUP_MSA_EXT_9, +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390x-cpumodel-vector-enhancements.patch b/SOURCES/kvm-s390x-cpumodel-vector-enhancements.patch new file mode 100644 index 0000000..79c251b --- /dev/null +++ b/SOURCES/kvm-s390x-cpumodel-vector-enhancements.patch @@ -0,0 +1,57 @@ +From e7ab1956612806185d87682945e0c54989fa6aaa Mon Sep 17 00:00:00 2001 +From: David Hildenbrand +Date: Wed, 22 May 2019 08:03:58 +0100 +Subject: [PATCH 06/12] s390x/cpumodel: vector enhancements + +RH-Author: David Hildenbrand +Message-id: <20190522080402.20173-7-david@redhat.com> +Patchwork-id: 88159 +O-Subject: [RHEL8.1 qemu-kvm PATCH v2 06/10] s390x/cpumodel: vector enhancements +Bugzilla: 1660912 +RH-Acked-by: Cornelia Huck +RH-Acked-by: Jens Freimann +RH-Acked-by: Thomas Huth + +Add vector enhancements to the cpu model. + +Signed-off-by: Christian Borntraeger +Reviewed-by: David Hildenbrand +Message-Id: <20190429090250.7648-6-borntraeger@de.ibm.com> +Signed-off-by: Cornelia Huck +(cherry picked from commit 54d65de0b525272edfa66eb75c3f67b183f8aff4) +Signed-off-by: David Hildenbrand +Signed-off-by: Danilo C. L. de Paula +--- + target/s390x/cpu_features.c | 2 ++ + target/s390x/cpu_features_def.h | 2 ++ + 2 files changed, 4 insertions(+) + +diff --git a/target/s390x/cpu_features.c b/target/s390x/cpu_features.c +index 154e2bb..3587325 100644 +--- a/target/s390x/cpu_features.c ++++ b/target/s390x/cpu_features.c +@@ -108,6 +108,8 @@ static const S390FeatDef s390_features[] = { + FEAT_INIT("irbm", S390_FEAT_TYPE_STFL, 145, "Insert-reference-bits-multiple facility"), + FEAT_INIT("msa8-base", S390_FEAT_TYPE_STFL, 146, "Message-security-assist-extension-8 facility (excluding subfunctions)"), + FEAT_INIT("cmmnt", S390_FEAT_TYPE_STFL, 147, "CMM: ESSA-enhancement (no translate) facility"), ++ FEAT_INIT("vxeh2", S390_FEAT_TYPE_STFL, 148, "Vector Enhancements facility 2"), ++ FEAT_INIT("vxbeh", S390_FEAT_TYPE_STFL, 152, "Vector BCD enhancements facility 1"), + FEAT_INIT("msa9-base", S390_FEAT_TYPE_STFL, 155, "Message-security-assist-extension-9 facility (excluding subfunctions)"), + FEAT_INIT("etoken", S390_FEAT_TYPE_STFL, 156, "Etoken facility"), + +diff --git a/target/s390x/cpu_features_def.h b/target/s390x/cpu_features_def.h +index 0307848..ce2223c 100644 +--- a/target/s390x/cpu_features_def.h ++++ b/target/s390x/cpu_features_def.h +@@ -96,6 +96,8 @@ typedef enum { + S390_FEAT_INSERT_REFERENCE_BITS_MULT, + S390_FEAT_MSA_EXT_8, + S390_FEAT_CMM_NT, ++ S390_FEAT_VECTOR_ENH2, ++ S390_FEAT_VECTOR_BCD_ENH, + S390_FEAT_MSA_EXT_9, + S390_FEAT_ETOKEN, + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390x-cpumodel-wire-up-8561-and-8562-as-gen15-machin.patch b/SOURCES/kvm-s390x-cpumodel-wire-up-8561-and-8562-as-gen15-machin.patch new file mode 100644 index 0000000..8e8dc7f --- /dev/null +++ b/SOURCES/kvm-s390x-cpumodel-wire-up-8561-and-8562-as-gen15-machin.patch @@ -0,0 +1,59 @@ +From 7db16d6b16fa8f25168a7421e5c6d2f132ea06ab Mon Sep 17 00:00:00 2001 +From: David Hildenbrand +Date: Wed, 22 May 2019 08:04:02 +0100 +Subject: [PATCH 10/12] s390x/cpumodel: wire up 8561 and 8562 as gen15 machines + +RH-Author: David Hildenbrand +Message-id: <20190522080402.20173-11-david@redhat.com> +Patchwork-id: 88160 +O-Subject: [RHEL8.1 qemu-kvm PATCH v2 10/10] s390x/cpumodel: wire up 8561 and 8562 as gen15 machines +Bugzilla: 1660912 +RH-Acked-by: Cornelia Huck +RH-Acked-by: Jens Freimann +RH-Acked-by: Thomas Huth + +8561 and 8562 will be gen15 machines. There is no name yet, let us use +gen15a and gen15b as base name. Later on we can provide aliases with +the proper name. + +Signed-off-by: Christian Borntraeger +Message-Id: <20190429090250.7648-10-borntraeger@de.ibm.com> +Reviewed-by: David Hildenbrand +Signed-off-by: Cornelia Huck +(cherry picked from commit c657e84faee48d6ab36665da5a008b8f0649593d) +Signed-off-by: David Hildenbrand +Signed-off-by: Danilo C. L. de Paula +--- + target/s390x/cpu_models.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +diff --git a/target/s390x/cpu_models.c b/target/s390x/cpu_models.c +index 737520b..91afc6b 100644 +--- a/target/s390x/cpu_models.c ++++ b/target/s390x/cpu_models.c +@@ -41,10 +41,9 @@ + } + + /* +- * CPU definiton list in order of release. For now, base features of a +- * following release are always a subset of base features of the previous +- * release. Same is correct for the other feature sets. +- * A BC release always follows the corresponding EC release. ++ * CPU definition list in order of release. Up to generation 14 base features ++ * of a following release have been a superset of the previous release. With ++ * generation 15 one base feature and one optional feature have been deprecated. + */ + static S390CPUDef s390_cpu_defs[] = { + CPUDEF_INIT(0x2064, 7, 1, 38, 0x00000000U, "z900", "IBM zSeries 900 GA1"), +@@ -81,6 +80,8 @@ static S390CPUDef s390_cpu_defs[] = { + CPUDEF_INIT(0x3906, 14, 1, 47, 0x08000000U, "z14", "IBM z14 GA1"), + CPUDEF_INIT(0x3906, 14, 2, 47, 0x08000000U, "z14.2", "IBM z14 GA2"), + CPUDEF_INIT(0x3907, 14, 1, 47, 0x08000000U, "z14ZR1", "IBM z14 Model ZR1 GA1"), ++ CPUDEF_INIT(0x8561, 15, 1, 47, 0x08000000U, "gen15a", "IBM 8561 GA1"), ++ CPUDEF_INIT(0x8562, 15, 1, 47, 0x08000000U, "gen15b", "IBM 8562 GA1"), + }; + + #define QEMU_MAX_CPU_TYPE 0x2827 +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390x-ipl-Try-to-detect-Linux-vs-non-Linux-for-initi.patch b/SOURCES/kvm-s390x-ipl-Try-to-detect-Linux-vs-non-Linux-for-initi.patch new file mode 100644 index 0000000..642ae6e --- /dev/null +++ b/SOURCES/kvm-s390x-ipl-Try-to-detect-Linux-vs-non-Linux-for-initi.patch @@ -0,0 +1,89 @@ +From 8128e12a8cb09bdb6bcb1b5735a9726f689e27c3 Mon Sep 17 00:00:00 2001 +From: Cornelia Huck +Date: Wed, 17 Apr 2019 13:57:18 +0100 +Subject: [PATCH 01/24] s390x/ipl: Try to detect Linux vs non Linux for initial + IPL PSW + +RH-Author: Cornelia Huck +Message-id: <20190417135741.25297-2-cohuck@redhat.com> +Patchwork-id: 85783 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v2 01/24] s390x/ipl: Try to detect Linux vs non Linux for initial IPL PSW +Bugzilla: 1699070 +RH-Acked-by: David Hildenbrand +RH-Acked-by: Thomas Huth +RH-Acked-by: Jens Freimann + +From: Christian Borntraeger + +Right now the IPL device always starts from address 0x10000 (the usual +Linux entry point). To run other guests (e.g. test programs) it is +useful to use the IPL PSW from address 0. We can use the Linux magic +at 0x10008 to decide. + +Signed-off-by: Christian Borntraeger +Message-Id: <20180612125933.262679-1-borntraeger@de.ibm.com> +Reviewed-by: David Hildenbrand +Reviewed-by: Thomas Huth +Signed-off-by: Cornelia Huck +(cherry picked from commit acd7ef837d8987ad4ef2ab8f8e8c0f13ab413dd5) +Signed-off-by: Cornelia Huck +Signed-off-by: Danilo C. L. de Paula +--- + hw/s390x/ipl.c | 27 ++++++++++++++++++++++----- + 1 file changed, 22 insertions(+), 5 deletions(-) + +diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c +index 150f6c0..617ac43 100644 +--- a/hw/s390x/ipl.c ++++ b/hw/s390x/ipl.c +@@ -28,6 +28,7 @@ + #include "qemu/option.h" + + #define KERN_IMAGE_START 0x010000UL ++#define LINUX_MAGIC_ADDR 0x010008UL + #define KERN_PARM_AREA 0x010480UL + #define INITRD_START 0x800000UL + #define INITRD_PARM_START 0x010408UL +@@ -104,7 +105,9 @@ static uint64_t bios_translate_addr(void *opaque, uint64_t srcaddr) + static void s390_ipl_realize(DeviceState *dev, Error **errp) + { + S390IPLState *ipl = S390_IPL(dev); +- uint64_t pentry = KERN_IMAGE_START; ++ uint32_t *ipl_psw; ++ uint64_t pentry; ++ char *magic; + int kernel_size; + Error *err = NULL; + +@@ -156,10 +159,24 @@ static void s390_ipl_realize(DeviceState *dev, Error **errp) + NULL, 1, EM_S390, 0, 0); + if (kernel_size < 0) { + kernel_size = load_image_targphys(ipl->kernel, 0, ram_size); +- } +- if (kernel_size < 0) { +- error_setg(&err, "could not load kernel '%s'", ipl->kernel); +- goto error; ++ if (kernel_size < 0) { ++ error_setg(&err, "could not load kernel '%s'", ipl->kernel); ++ goto error; ++ } ++ /* if this is Linux use KERN_IMAGE_START */ ++ magic = rom_ptr(LINUX_MAGIC_ADDR); ++ if (magic && !memcmp(magic, "S390EP", 6)) { ++ pentry = KERN_IMAGE_START; ++ } else { ++ /* if not Linux load the address of the (short) IPL PSW */ ++ ipl_psw = rom_ptr(4); ++ if (ipl_psw) { ++ pentry = be32_to_cpu(*ipl_psw) & 0x7fffffffUL; ++ } else { ++ error_setg(&err, "Could not get IPL PSW"); ++ goto error; ++ } ++ } + } + /* + * Is it a Linux kernel (starting at 0x10000)? If yes, we fill in the +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390x-pci-Always-delete-and-free-the-release_timer.patch b/SOURCES/kvm-s390x-pci-Always-delete-and-free-the-release_timer.patch new file mode 100644 index 0000000..2da0a9b --- /dev/null +++ b/SOURCES/kvm-s390x-pci-Always-delete-and-free-the-release_timer.patch @@ -0,0 +1,54 @@ +From 586c02abcca49fceeca0d6f1b4e5cab30dd9a123 Mon Sep 17 00:00:00 2001 +From: Cornelia Huck +Date: Wed, 17 Apr 2019 13:57:29 +0100 +Subject: [PATCH 12/24] s390x/pci: Always delete and free the release_timer + +RH-Author: Cornelia Huck +Message-id: <20190417135741.25297-13-cohuck@redhat.com> +Patchwork-id: 85795 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v2 12/24] s390x/pci: Always delete and free the release_timer +Bugzilla: 1699070 +RH-Acked-by: David Hildenbrand +RH-Acked-by: Thomas Huth +RH-Acked-by: Jens Freimann + +From: David Hildenbrand + +We should always get rid of it. I don't see a reason to keep the timer +alive if the devices are going away. This looks like a memory leak. + +(hmp) device_add virtio-mouse-pci,id=test +(hmp) device_del test +-> guest notified, timer pending. +-> guest does not react for some reason (e.g. crash) +-> s390_pcihost_timer_cb(). Timer not pending anymore. qmp_unplug(). + +-> Device deleted. Timer expired (not pending) but not freed. + +Signed-off-by: David Hildenbrand +Message-Id: <20190114103110.10909-4-david@redhat.com> +Reviewed-by: Collin Walling +Signed-off-by: Cornelia Huck +(cherry picked from commit d648a3e62d5e726526f9df283341999792f4fbf9) +Signed-off-by: Cornelia Huck +Signed-off-by: Danilo C. L. de Paula +--- + hw/s390x/s390-pci-bus.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c +index a785acb..ea0c74c 100644 +--- a/hw/s390x/s390-pci-bus.c ++++ b/hw/s390x/s390-pci-bus.c +@@ -982,7 +982,7 @@ static void s390_pcihost_unplug(HotplugHandler *hotplug_dev, DeviceState *dev, + return; + } + +- if (pbdev->release_timer && timer_pending(pbdev->release_timer)) { ++ if (pbdev->release_timer) { + timer_del(pbdev->release_timer); + timer_free(pbdev->release_timer); + pbdev->release_timer = NULL; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390x-pci-Drop-release-timer-and-replace-it-with-a-f.patch b/SOURCES/kvm-s390x-pci-Drop-release-timer-and-replace-it-with-a-f.patch new file mode 100644 index 0000000..ee4dc3e --- /dev/null +++ b/SOURCES/kvm-s390x-pci-Drop-release-timer-and-replace-it-with-a-f.patch @@ -0,0 +1,152 @@ +From d1ce5b3af38aa7d4eb9d3a2dd90a7572a69f7d41 Mon Sep 17 00:00:00 2001 +From: Cornelia Huck +Date: Wed, 17 Apr 2019 13:57:34 +0100 +Subject: [PATCH 17/24] s390x/pci: Drop release timer and replace it with a + flag + +RH-Author: Cornelia Huck +Message-id: <20190417135741.25297-18-cohuck@redhat.com> +Patchwork-id: 85798 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v2 17/24] s390x/pci: Drop release timer and replace it with a flag +Bugzilla: 1699070 +RH-Acked-by: David Hildenbrand +RH-Acked-by: Thomas Huth +RH-Acked-by: Jens Freimann + +From: David Hildenbrand + +Let's handle it similar to x86 ACPI PCI code and don't use a timer. +Instead, remember if an unplug request is pending and keep it pending +for eternity. (a follow up patch will process the request on +reboot). + +We expect that a guest that is up and running, will process the unplug +request and trigger the unplug. This is normal operation, no timer needed. + +If the guest does not react, this usually means something in the guest +is going wrong. Simply removing the device after 30 seconds does not +really sound like a good idea. It might sometimes be wanted, but I +consider this rather an "opt-in" decision as it might harm a guest not +prepared for it. + +If we ever actually want a "forced/surprise removal", we will have to +implement something on top of the existing "device_del" framework. E.g. +also x86 might want to do a forced/surprise removal of PCI devices under +some conditions. "device_del X, forced=true" could be an option and will +require changes to the hotplug handler infrastructure. + +This will then move the responsibility on when to do a forced removal +to a higher level. Doing a forced removal right now over-complicates +things and doesn't really seem to be required. + +Let's allow to send multiple requests. + +Signed-off-by: David Hildenbrand +Message-Id: <20190130155733.32742-6-david@redhat.com> +Reviewed-by: Collin Walling +Signed-off-by: Cornelia Huck +(cherry picked from commit 9f2a46b11139cd21c41f4d97c0416af6f9e76f7b) +Signed-off-by: Cornelia Huck +Signed-off-by: Danilo C. L. de Paula +--- + hw/s390x/s390-pci-bus.c | 38 +++++++------------------------------- + hw/s390x/s390-pci-bus.h | 3 +-- + 2 files changed, 8 insertions(+), 33 deletions(-) + +diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c +index 21419df..97d3eb8 100644 +--- a/hw/s390x/s390-pci-bus.c ++++ b/hw/s390x/s390-pci-bus.c +@@ -194,7 +194,7 @@ void s390_pci_sclp_deconfigure(SCCB *sccb) + pbdev->state = ZPCI_FS_STANDBY; + rc = SCLP_RC_NORMAL_COMPLETION; + +- if (pbdev->release_timer) { ++ if (pbdev->unplug_requested) { + s390_pci_perform_unplug(pbdev); + } + } +@@ -963,23 +963,6 @@ static void s390_pcihost_plug(HotplugHandler *hotplug_dev, DeviceState *dev, + } + } + +-static void s390_pcihost_timer_cb(void *opaque) +-{ +- S390PCIBusDevice *pbdev = opaque; +- +- if (pbdev->summary_ind) { +- pci_dereg_irqs(pbdev); +- } +- if (pbdev->iommu->enabled) { +- pci_dereg_ioat(pbdev->iommu); +- } +- +- pbdev->state = ZPCI_FS_STANDBY; +- s390_pci_generate_plug_event(HP_EVENT_CONFIGURED_TO_STBRES, +- pbdev->fh, pbdev->fid); +- s390_pci_perform_unplug(pbdev); +-} +- + static void s390_pcihost_unplug(HotplugHandler *hotplug_dev, DeviceState *dev, + Error **errp) + { +@@ -1006,12 +989,6 @@ static void s390_pcihost_unplug(HotplugHandler *hotplug_dev, DeviceState *dev, + pbdev->state = ZPCI_FS_RESERVED; + } else if (object_dynamic_cast(OBJECT(dev), TYPE_S390_PCI_DEVICE)) { + pbdev = S390_PCI_DEVICE(dev); +- +- if (pbdev->release_timer) { +- timer_del(pbdev->release_timer); +- timer_free(pbdev->release_timer); +- pbdev->release_timer = NULL; +- } + pbdev->fid = 0; + QTAILQ_REMOVE(&s->zpci_devs, pbdev, link); + g_hash_table_remove(s->zpci_table, &pbdev->idx); +@@ -1058,15 +1035,14 @@ static void s390_pcihost_unplug_request(HotplugHandler *hotplug_dev, + s390_pci_perform_unplug(pbdev); + break; + default: +- if (pbdev->release_timer) { +- return; +- } ++ /* ++ * Allow to send multiple requests, e.g. if the guest crashed ++ * before releasing the device, we would not be able to send ++ * another request to the same VM (e.g. fresh OS). ++ */ ++ pbdev->unplug_requested = true; + s390_pci_generate_plug_event(HP_EVENT_DECONFIGURE_REQUEST, + pbdev->fh, pbdev->fid); +- pbdev->release_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, +- s390_pcihost_timer_cb, pbdev); +- timer_mod(pbdev->release_timer, +- qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + HOT_UNPLUG_TIMEOUT); + } + } else { + g_assert_not_reached(); +diff --git a/hw/s390x/s390-pci-bus.h b/hw/s390x/s390-pci-bus.h +index 7684658..3eae782 100644 +--- a/hw/s390x/s390-pci-bus.h ++++ b/hw/s390x/s390-pci-bus.h +@@ -35,7 +35,6 @@ + #define ZPCI_MAX_UID 0xffff + #define UID_UNDEFINED 0 + #define UID_CHECKING_ENABLED 0x01 +-#define HOT_UNPLUG_TIMEOUT (NANOSECONDS_PER_SECOND * 60 * 5) + + #define S390_PCI_HOST_BRIDGE(obj) \ + OBJECT_CHECK(S390pciState, (obj), TYPE_S390_PCI_HOST_BRIDGE) +@@ -307,8 +306,8 @@ struct S390PCIBusDevice { + MemoryRegion msix_notify_mr; + IndAddr *summary_ind; + IndAddr *indicator; +- QEMUTimer *release_timer; + bool pci_unplug_request_processed; ++ bool unplug_requested; + QTAILQ_ENTRY(S390PCIBusDevice) link; + }; + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390x-pci-Fix-hotplugging-of-PCI-bridges.patch b/SOURCES/kvm-s390x-pci-Fix-hotplugging-of-PCI-bridges.patch new file mode 100644 index 0000000..c4186cc --- /dev/null +++ b/SOURCES/kvm-s390x-pci-Fix-hotplugging-of-PCI-bridges.patch @@ -0,0 +1,103 @@ +From 72cc005ad139d9d5d4bf2cb7402cf730c6726fd3 Mon Sep 17 00:00:00 2001 +From: Cornelia Huck +Date: Wed, 17 Apr 2019 13:57:37 +0100 +Subject: [PATCH 20/24] s390x/pci: Fix hotplugging of PCI bridges + +RH-Author: Cornelia Huck +Message-id: <20190417135741.25297-21-cohuck@redhat.com> +Patchwork-id: 85801 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v2 20/24] s390x/pci: Fix hotplugging of PCI bridges +Bugzilla: 1699070 +RH-Acked-by: David Hildenbrand +RH-Acked-by: Thomas Huth +RH-Acked-by: Jens Freimann + +From: David Hildenbrand + +When hotplugging a PCI bridge right now to the root port, we resolve +pci_get_bus(pdev)->parent_dev, which results in a SEGFAULT. Hotplugging +really only works right now when hotplugging to another bridge. + +Instead, we have to properly check if we are already at the root. + +Let's cleanup the code while at it a bit and factor out updating the +subordinate bus number into a separate function. The check for +"old_nr < nr" is right now not strictly necessary, but makes it more +obvious what is actually going on. + +Most probably fixing up the topology is not our responsibility when +hotplugging. The guest has to sort this out. But let's keep it for now +and only fix current code to not crash. + +Reviewed-by: Thomas Huth +Signed-off-by: David Hildenbrand +Message-Id: <20190130155733.32742-3-david@redhat.com> +Reviewed-by: Collin Walling +Signed-off-by: Cornelia Huck +(cherry picked from commit 150f462538a6f3b78efe785c911669375032b0d2) +Signed-off-by: Cornelia Huck +Signed-off-by: Danilo C. L. de Paula +--- + hw/s390x/s390-pci-bus.c | 28 +++++++++++++++++++--------- + 1 file changed, 19 insertions(+), 9 deletions(-) + +diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c +index 309ad79..a0f7245 100644 +--- a/hw/s390x/s390-pci-bus.c ++++ b/hw/s390x/s390-pci-bus.c +@@ -881,6 +881,21 @@ static void s390_pcihost_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, + } + } + ++static void s390_pci_update_subordinate(PCIDevice *dev, uint32_t nr) ++{ ++ uint32_t old_nr; ++ ++ pci_default_write_config(dev, PCI_SUBORDINATE_BUS, nr, 1); ++ while (!pci_bus_is_root(pci_get_bus(dev))) { ++ dev = pci_get_bus(dev)->parent_dev; ++ ++ old_nr = pci_default_read_config(dev, PCI_SUBORDINATE_BUS, 1); ++ if (old_nr < nr) { ++ pci_default_write_config(dev, PCI_SUBORDINATE_BUS, nr, 1); ++ } ++ } ++} ++ + static void s390_pcihost_plug(HotplugHandler *hotplug_dev, DeviceState *dev, + Error **errp) + { +@@ -889,26 +904,21 @@ static void s390_pcihost_plug(HotplugHandler *hotplug_dev, DeviceState *dev, + S390PCIBusDevice *pbdev = NULL; + + if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_BRIDGE)) { +- BusState *bus; + PCIBridge *pb = PCI_BRIDGE(dev); +- PCIDevice *pdev = PCI_DEVICE(dev); + ++ pdev = PCI_DEVICE(dev); + pci_bridge_map_irq(pb, dev->id, s390_pci_map_irq); + pci_setup_iommu(&pb->sec_bus, s390_pci_dma_iommu, s); + +- bus = BUS(&pb->sec_bus); +- qbus_set_hotplug_handler(bus, DEVICE(s), errp); ++ qbus_set_hotplug_handler(BUS(&pb->sec_bus), DEVICE(s), errp); + + if (dev->hotplugged) { + pci_default_write_config(pdev, PCI_PRIMARY_BUS, + pci_dev_bus_num(pdev), 1); + s->bus_no += 1; + pci_default_write_config(pdev, PCI_SECONDARY_BUS, s->bus_no, 1); +- do { +- pdev = pci_get_bus(pdev)->parent_dev; +- pci_default_write_config(pdev, PCI_SUBORDINATE_BUS, +- s->bus_no, 1); +- } while (pci_get_bus(pdev) && pci_dev_bus_num(pdev)); ++ ++ s390_pci_update_subordinate(pdev, s->bus_no); + } + } else if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) { + pdev = PCI_DEVICE(dev); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390x-pci-Fix-primary-bus-number-for-PCI-bridges.patch b/SOURCES/kvm-s390x-pci-Fix-primary-bus-number-for-PCI-bridges.patch new file mode 100644 index 0000000..68d910f --- /dev/null +++ b/SOURCES/kvm-s390x-pci-Fix-primary-bus-number-for-PCI-bridges.patch @@ -0,0 +1,103 @@ +From 160715e23b00c660f0dfee3f1bdc021f9693d222 Mon Sep 17 00:00:00 2001 +From: Cornelia Huck +Date: Wed, 17 Apr 2019 13:57:36 +0100 +Subject: [PATCH 19/24] s390x/pci: Fix primary bus number for PCI bridges + +RH-Author: Cornelia Huck +Message-id: <20190417135741.25297-20-cohuck@redhat.com> +Patchwork-id: 85800 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v2 19/24] s390x/pci: Fix primary bus number for PCI bridges +Bugzilla: 1699070 +RH-Acked-by: David Hildenbrand +RH-Acked-by: Thomas Huth +RH-Acked-by: Jens Freimann + +From: David Hildenbrand + +The primary bus number corresponds always to the bus number of the +bus the bridge is attached to. + +Right now, if we have two bridges attached to the same bus (e.g. root +bus) this is however not the case. The first bridge will have primary +bus 0, the second bridge primary bus 1, which is wrong. Fix the assignment. + +While at it, drop setting the PCI_SUBORDINATE_BUS temporarily to 0xff. +Setting it temporarily to that value (as discussed e.g. in [1]), is +only relevant for a running system that probes the buses. The value is +effectively unused for us just doing a DFS. + +Also add a comment why we have to reassign during every reset (which I +found to be surprising. + +Please note that hotplugging of bridges is in general still broken, will +be fixed next. + +[1] http://www.science.unitn.it/~fiorella/guidelinux/tlk/node76.html + +Reviewed-by: Thomas Huth +Signed-off-by: David Hildenbrand +Message-Id: <20190130155733.32742-2-david@redhat.com> +Reviewed-by: Collin Walling +Signed-off-by: Cornelia Huck +(cherry picked from commit d30a7507edf1ca23d33dbf00b25f5e49a7808492) +Signed-off-by: Cornelia Huck +Signed-off-by: Danilo C. L. de Paula +--- + hw/s390x/s390-pci-bus.c | 13 ++++++++----- + 1 file changed, 8 insertions(+), 5 deletions(-) + +diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c +index 07a286a..309ad79 100644 +--- a/hw/s390x/s390-pci-bus.c ++++ b/hw/s390x/s390-pci-bus.c +@@ -900,7 +900,8 @@ static void s390_pcihost_plug(HotplugHandler *hotplug_dev, DeviceState *dev, + qbus_set_hotplug_handler(bus, DEVICE(s), errp); + + if (dev->hotplugged) { +- pci_default_write_config(pdev, PCI_PRIMARY_BUS, s->bus_no, 1); ++ pci_default_write_config(pdev, PCI_PRIMARY_BUS, ++ pci_dev_bus_num(pdev), 1); + s->bus_no += 1; + pci_default_write_config(pdev, PCI_SECONDARY_BUS, s->bus_no, 1); + do { +@@ -1053,8 +1054,6 @@ static void s390_pci_enumerate_bridge(PCIBus *bus, PCIDevice *pdev, + void *opaque) + { + S390pciState *s = opaque; +- unsigned int primary = s->bus_no; +- unsigned int subordinate = 0xff; + PCIBus *sec_bus = NULL; + + if ((pci_default_read_config(pdev, PCI_HEADER_TYPE, 1) != +@@ -1063,7 +1062,7 @@ static void s390_pci_enumerate_bridge(PCIBus *bus, PCIDevice *pdev, + } + + (s->bus_no)++; +- pci_default_write_config(pdev, PCI_PRIMARY_BUS, primary, 1); ++ pci_default_write_config(pdev, PCI_PRIMARY_BUS, pci_dev_bus_num(pdev), 1); + pci_default_write_config(pdev, PCI_SECONDARY_BUS, s->bus_no, 1); + pci_default_write_config(pdev, PCI_SUBORDINATE_BUS, s->bus_no, 1); + +@@ -1072,7 +1071,7 @@ static void s390_pci_enumerate_bridge(PCIBus *bus, PCIDevice *pdev, + return; + } + +- pci_default_write_config(pdev, PCI_SUBORDINATE_BUS, subordinate, 1); ++ /* Assign numbers to all child bridges. The last is the highest number. */ + pci_for_each_device(sec_bus, pci_bus_num(sec_bus), + s390_pci_enumerate_bridge, s); + pci_default_write_config(pdev, PCI_SUBORDINATE_BUS, s->bus_no, 1); +@@ -1083,6 +1082,10 @@ static void s390_pcihost_reset(DeviceState *dev) + S390pciState *s = S390_PCI_HOST_BRIDGE(dev); + PCIBus *bus = s->parent_obj.bus; + ++ /* ++ * When resetting a PCI bridge, the assigned numbers are set to 0. So ++ * on every system reset, we also have to reassign numbers. ++ */ + s->bus_no = 0; + pci_for_each_device(bus, pci_bus_num(bus), s390_pci_enumerate_bridge, s); + } +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390x-pci-Ignore-the-unplug-call-if-we-already-have-.patch b/SOURCES/kvm-s390x-pci-Ignore-the-unplug-call-if-we-already-have-.patch new file mode 100644 index 0000000..00814e1 --- /dev/null +++ b/SOURCES/kvm-s390x-pci-Ignore-the-unplug-call-if-we-already-have-.patch @@ -0,0 +1,58 @@ +From 231d80e36c0788378d87ad4ee376ea87dc43745d Mon Sep 17 00:00:00 2001 +From: Cornelia Huck +Date: Wed, 17 Apr 2019 13:57:30 +0100 +Subject: [PATCH 13/24] s390x/pci: Ignore the unplug call if we already have a + release_timer + +RH-Author: Cornelia Huck +Message-id: <20190417135741.25297-14-cohuck@redhat.com> +Patchwork-id: 85791 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v2 13/24] s390x/pci: Ignore the unplug call if we already have a release_timer +Bugzilla: 1699070 +RH-Acked-by: David Hildenbrand +RH-Acked-by: Thomas Huth +RH-Acked-by: Jens Freimann + +From: David Hildenbrand + +... otherwise two successive calls to qdev_unplug() (e.g. by an impatient +user) will effectively overwrite pbdev->release_timer, resulting in a +memory leak. We are already processing the unplug. + +If there is already a release_timer, the unplug will be performed after +the timeout. + +Can be easily triggered by +(hmp) device_add virtio-mouse-pci,id=test +(hmp) stop +(hmp) device_del test +(hmp) device_del test + +Signed-off-by: David Hildenbrand +Message-Id: <20190114103110.10909-5-david@redhat.com> +Reviewed-by: Collin Walling +Signed-off-by: Cornelia Huck +(cherry picked from commit 3549f8c9e4f0ef1c3417ff43b2164f68ad34b922) +Signed-off-by: Cornelia Huck +Signed-off-by: Danilo C. L. de Paula +--- + hw/s390x/s390-pci-bus.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c +index ea0c74c..24a0d78 100644 +--- a/hw/s390x/s390-pci-bus.c ++++ b/hw/s390x/s390-pci-bus.c +@@ -972,6 +972,9 @@ static void s390_pcihost_unplug(HotplugHandler *hotplug_dev, DeviceState *dev, + case ZPCI_FS_STANDBY: + break; + default: ++ if (pbdev->release_timer) { ++ return; ++ } + s390_pci_generate_plug_event(HP_EVENT_DECONFIGURE_REQUEST, + pbdev->fh, pbdev->fid); + pbdev->release_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390x-pci-Introduce-unplug-requests-and-split-unplug.patch b/SOURCES/kvm-s390x-pci-Introduce-unplug-requests-and-split-unplug.patch new file mode 100644 index 0000000..ebcbfae --- /dev/null +++ b/SOURCES/kvm-s390x-pci-Introduce-unplug-requests-and-split-unplug.patch @@ -0,0 +1,307 @@ +From db9158c9e7905a77c854b178140be79f5295bcdd Mon Sep 17 00:00:00 2001 +From: Cornelia Huck +Date: Wed, 17 Apr 2019 13:57:33 +0100 +Subject: [PATCH 16/24] s390x/pci: Introduce unplug requests and split unplug + handler + +RH-Author: Cornelia Huck +Message-id: <20190417135741.25297-17-cohuck@redhat.com> +Patchwork-id: 85799 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v2 16/24] s390x/pci: Introduce unplug requests and split unplug handler +Bugzilla: 1699070 +RH-Acked-by: David Hildenbrand +RH-Acked-by: Thomas Huth +RH-Acked-by: Jens Freimann + +From: David Hildenbrand + +PCI on s390x is really weird and how it was modeled in QEMU might not have +been the right choice. Anyhow, right now it is the case that: +- Hotplugging a PCI device will silently create a zPCI device + (if none is provided) +- Hotunplugging a zPCI device will unplug the PCI device (if any) +- Hotunplugging a PCI device will unplug also the zPCI device +As far as I can see, we can no longer change this behavior. But we +should fix it. + +Both device types are handled via a single hotplug handler call. This +is problematic for various reasons: +1. Unplugging via the zPCI device allows to unplug devices that are not + hot removable. (check performed in qdev_unplug()) - bad. +2. Hotplug handler chains are not possible for the unplug case. In the + future, the machine might want to override hotplug handlers, to + process device specific stuff and to then branch off to the actual + hotplug handler. We need separate hotplug handler calls for both the + PCI and zPCI device to make this work reliably. All other PCI + implementations are already prepared to handle this correctly, only + s390x is missing. + +Therefore, introduce the unplug_request handler and properly perform +unplug checks by redirecting to the separate unplug_request handlers. +When finally unplugging, perform two separate hotplug_handler_unplug() +calls, first for the PCI device, followed by the zPCI device. This now +nicely splits unplugging paths for both devices. + +The redirect part is a little hairy, as the user is allowed to trigger +unplug either via the PCI or the zPCI device. So redirect always to the +PCI unplug request handler first and remember if that check has been +performed in the zPCI device. Redirect then to the zPCI device unplug +request handler to perform the magic. Remembering that we already +checked the PCI device breaks the redirect loop. + +Signed-off-by: David Hildenbrand +Message-Id: <20190130155733.32742-5-david@redhat.com> +Reviewed-by: Collin Walling +Signed-off-by: Cornelia Huck +(cherry picked from commit e0998fe8910435f0e818e5c9ac58d4d2d9144a98) +Signed-off-by: Cornelia Huck +Signed-off-by: Danilo C. L. de Paula + +Conflicts: + hw/s390x/s390-pci-bus.c + We don't have 6e92c70c3754 ("s390x/pci: add common function measurement + block") downstream. + +Signed-off-by: Danilo C. L. de Paula +--- + hw/s390x/s390-pci-bus.c | 165 ++++++++++++++++++++++++++++++++---------------- + hw/s390x/s390-pci-bus.h | 1 + + 2 files changed, 113 insertions(+), 53 deletions(-) + +diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c +index e3f576a..21419df 100644 +--- a/hw/s390x/s390-pci-bus.c ++++ b/hw/s390x/s390-pci-bus.c +@@ -148,6 +148,22 @@ out: + psccb->header.response_code = cpu_to_be16(rc); + } + ++static void s390_pci_perform_unplug(S390PCIBusDevice *pbdev) ++{ ++ HotplugHandler *hotplug_ctrl; ++ ++ /* Unplug the PCI device */ ++ if (pbdev->pdev) { ++ hotplug_ctrl = qdev_get_hotplug_handler(DEVICE(pbdev->pdev)); ++ hotplug_handler_unplug(hotplug_ctrl, DEVICE(pbdev->pdev), ++ &error_abort); ++ } ++ ++ /* Unplug the zPCI device */ ++ hotplug_ctrl = qdev_get_hotplug_handler(DEVICE(pbdev)); ++ hotplug_handler_unplug(hotplug_ctrl, DEVICE(pbdev), &error_abort); ++} ++ + void s390_pci_sclp_deconfigure(SCCB *sccb) + { + IoaCfgSccb *psccb = (IoaCfgSccb *)sccb; +@@ -179,7 +195,7 @@ void s390_pci_sclp_deconfigure(SCCB *sccb) + rc = SCLP_RC_NORMAL_COMPLETION; + + if (pbdev->release_timer) { +- qdev_unplug(DEVICE(pbdev->pdev), NULL); ++ s390_pci_perform_unplug(pbdev); + } + } + out: +@@ -217,6 +233,24 @@ S390PCIBusDevice *s390_pci_find_dev_by_target(S390pciState *s, + return NULL; + } + ++static S390PCIBusDevice *s390_pci_find_dev_by_pci(S390pciState *s, ++ PCIDevice *pci_dev) ++{ ++ S390PCIBusDevice *pbdev; ++ ++ if (!pci_dev) { ++ return NULL; ++ } ++ ++ QTAILQ_FOREACH(pbdev, &s->zpci_devs, link) { ++ if (pbdev->pdev == pci_dev) { ++ return pbdev; ++ } ++ } ++ ++ return NULL; ++} ++ + S390PCIBusDevice *s390_pci_find_dev_by_idx(S390pciState *s, uint32_t idx) + { + return g_hash_table_lookup(s->zpci_table, &idx); +@@ -943,76 +977,100 @@ static void s390_pcihost_timer_cb(void *opaque) + pbdev->state = ZPCI_FS_STANDBY; + s390_pci_generate_plug_event(HP_EVENT_CONFIGURED_TO_STBRES, + pbdev->fh, pbdev->fid); +- qdev_unplug(DEVICE(pbdev), NULL); ++ s390_pci_perform_unplug(pbdev); + } + + static void s390_pcihost_unplug(HotplugHandler *hotplug_dev, DeviceState *dev, + Error **errp) + { + S390pciState *s = S390_PCI_HOST_BRIDGE(hotplug_dev); +- PCIDevice *pci_dev = NULL; +- PCIBus *bus; +- int32_t devfn; + S390PCIBusDevice *pbdev = NULL; + ++ if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) { ++ PCIDevice *pci_dev = PCI_DEVICE(dev); ++ PCIBus *bus; ++ int32_t devfn; ++ ++ pbdev = s390_pci_find_dev_by_pci(s, PCI_DEVICE(dev)); ++ g_assert(pbdev); ++ ++ s390_pci_generate_plug_event(HP_EVENT_STANDBY_TO_RESERVED, ++ pbdev->fh, pbdev->fid); ++ bus = pci_get_bus(pci_dev); ++ devfn = pci_dev->devfn; ++ object_unparent(OBJECT(pci_dev)); ++ ++ s390_pci_msix_free(pbdev); ++ s390_pci_iommu_free(s, bus, devfn); ++ pbdev->pdev = NULL; ++ pbdev->state = ZPCI_FS_RESERVED; ++ } else if (object_dynamic_cast(OBJECT(dev), TYPE_S390_PCI_DEVICE)) { ++ pbdev = S390_PCI_DEVICE(dev); ++ ++ if (pbdev->release_timer) { ++ timer_del(pbdev->release_timer); ++ timer_free(pbdev->release_timer); ++ pbdev->release_timer = NULL; ++ } ++ pbdev->fid = 0; ++ QTAILQ_REMOVE(&s->zpci_devs, pbdev, link); ++ g_hash_table_remove(s->zpci_table, &pbdev->idx); ++ object_unparent(OBJECT(pbdev)); ++ } ++} ++ ++static void s390_pcihost_unplug_request(HotplugHandler *hotplug_dev, ++ DeviceState *dev, ++ Error **errp) ++{ ++ S390pciState *s = S390_PCI_HOST_BRIDGE(hotplug_dev); ++ S390PCIBusDevice *pbdev; ++ + if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_BRIDGE)) { + error_setg(errp, "PCI bridge hot unplug currently not supported"); +- return; + } else if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) { +- pci_dev = PCI_DEVICE(dev); +- +- QTAILQ_FOREACH(pbdev, &s->zpci_devs, link) { +- if (pbdev->pdev == pci_dev) { +- break; +- } +- } +- assert(pbdev != NULL); ++ /* ++ * Redirect the unplug request to the zPCI device and remember that ++ * we've checked the PCI device already (to prevent endless recursion). ++ */ ++ pbdev = s390_pci_find_dev_by_pci(s, PCI_DEVICE(dev)); ++ g_assert(pbdev); ++ pbdev->pci_unplug_request_processed = true; ++ qdev_unplug(DEVICE(pbdev), errp); + } else if (object_dynamic_cast(OBJECT(dev), TYPE_S390_PCI_DEVICE)) { + pbdev = S390_PCI_DEVICE(dev); +- pci_dev = pbdev->pdev; +- } else { +- g_assert_not_reached(); +- } + +- switch (pbdev->state) { +- case ZPCI_FS_RESERVED: +- goto out; +- case ZPCI_FS_STANDBY: +- break; +- default: +- if (pbdev->release_timer) { ++ /* ++ * If unplug was initially requested for the zPCI device, we ++ * first have to redirect to the PCI device, which will in return ++ * redirect back to us after performing its checks (if the request ++ * is not blocked, e.g. because it's a PCI bridge). ++ */ ++ if (pbdev->pdev && !pbdev->pci_unplug_request_processed) { ++ qdev_unplug(DEVICE(pbdev->pdev), errp); + return; + } +- s390_pci_generate_plug_event(HP_EVENT_DECONFIGURE_REQUEST, +- pbdev->fh, pbdev->fid); +- pbdev->release_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, +- s390_pcihost_timer_cb, +- pbdev); +- timer_mod(pbdev->release_timer, +- qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + HOT_UNPLUG_TIMEOUT); +- return; +- } ++ pbdev->pci_unplug_request_processed = false; + +- if (pbdev->release_timer) { +- timer_del(pbdev->release_timer); +- timer_free(pbdev->release_timer); +- pbdev->release_timer = NULL; ++ switch (pbdev->state) { ++ case ZPCI_FS_STANDBY: ++ case ZPCI_FS_RESERVED: ++ s390_pci_perform_unplug(pbdev); ++ break; ++ default: ++ if (pbdev->release_timer) { ++ return; ++ } ++ s390_pci_generate_plug_event(HP_EVENT_DECONFIGURE_REQUEST, ++ pbdev->fh, pbdev->fid); ++ pbdev->release_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, ++ s390_pcihost_timer_cb, pbdev); ++ timer_mod(pbdev->release_timer, ++ qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + HOT_UNPLUG_TIMEOUT); ++ } ++ } else { ++ g_assert_not_reached(); + } +- +- s390_pci_generate_plug_event(HP_EVENT_STANDBY_TO_RESERVED, +- pbdev->fh, pbdev->fid); +- bus = pci_get_bus(pci_dev); +- devfn = pci_dev->devfn; +- object_unparent(OBJECT(pci_dev)); +- s390_pci_msix_free(pbdev); +- s390_pci_iommu_free(s, bus, devfn); +- pbdev->pdev = NULL; +- pbdev->state = ZPCI_FS_RESERVED; +-out: +- pbdev->fid = 0; +- QTAILQ_REMOVE(&s->zpci_devs, pbdev, link); +- g_hash_table_remove(s->zpci_table, &pbdev->idx); +- object_unparent(OBJECT(pbdev)); + } + + static void s390_pci_enumerate_bridge(PCIBus *bus, PCIDevice *pdev, +@@ -1062,6 +1120,7 @@ static void s390_pcihost_class_init(ObjectClass *klass, void *data) + dc->realize = s390_pcihost_realize; + hc->pre_plug = s390_pcihost_pre_plug; + hc->plug = s390_pcihost_plug; ++ hc->unplug_request = s390_pcihost_unplug_request; + hc->unplug = s390_pcihost_unplug; + msi_nonbroken = true; + } +diff --git a/hw/s390x/s390-pci-bus.h b/hw/s390x/s390-pci-bus.h +index 1f7f9b5..7684658 100644 +--- a/hw/s390x/s390-pci-bus.h ++++ b/hw/s390x/s390-pci-bus.h +@@ -308,6 +308,7 @@ struct S390PCIBusDevice { + IndAddr *summary_ind; + IndAddr *indicator; + QEMUTimer *release_timer; ++ bool pci_unplug_request_processed; + QTAILQ_ENTRY(S390PCIBusDevice) link; + }; + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390x-pci-Move-some-hotplug-checks-to-the-pre_plug-h.patch b/SOURCES/kvm-s390x-pci-Move-some-hotplug-checks-to-the-pre_plug-h.patch new file mode 100644 index 0000000..e5a03ff --- /dev/null +++ b/SOURCES/kvm-s390x-pci-Move-some-hotplug-checks-to-the-pre_plug-h.patch @@ -0,0 +1,124 @@ +From 2bbc164594e03b4ab2b436433c7757990801ef49 Mon Sep 17 00:00:00 2001 +From: Cornelia Huck +Date: Wed, 17 Apr 2019 13:57:32 +0100 +Subject: [PATCH 15/24] s390x/pci: Move some hotplug checks to the pre_plug + handler + +RH-Author: Cornelia Huck +Message-id: <20190417135741.25297-16-cohuck@redhat.com> +Patchwork-id: 85797 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v2 15/24] s390x/pci: Move some hotplug checks to the pre_plug handler +Bugzilla: 1699070 +RH-Acked-by: David Hildenbrand +RH-Acked-by: Thomas Huth +RH-Acked-by: Jens Freimann + +From: David Hildenbrand + +Let's move most of the checks to the new pre_plug handler. As a PCI +bridge is just a PCI device, we can simplify the code. + +Notes: We cannot yet move the MSIX check or device ID creation + +zPCI device creation to the pre_plug handler as both parts are not +fixed before actual device realization (and therefore after pre_plug and +before plug). Once that part is factored out, we can move these parts to +the pre_plug handler, too and therefore remove all possible errors from +the plug handler. + +Reviewed-by: Collin Walling +Signed-off-by: David Hildenbrand +Message-Id: <20190114103110.10909-3-david@redhat.com> +Signed-off-by: Cornelia Huck +(cherry picked from commit 6069bcdeaceebb91f43bc4762e3f63eee48cd390) +Signed-off-by: Cornelia Huck +Signed-off-by: Danilo C. L. de Paula +--- + hw/s390x/s390-pci-bus.c | 41 +++++++++++++++++++++++++---------------- + 1 file changed, 25 insertions(+), 16 deletions(-) + +diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c +index f1b3334..e3f576a 100644 +--- a/hw/s390x/s390-pci-bus.c ++++ b/hw/s390x/s390-pci-bus.c +@@ -822,11 +822,31 @@ static bool s390_pci_alloc_idx(S390pciState *s, S390PCIBusDevice *pbdev) + } + + pbdev->idx = idx; +- s->next_idx = (idx + 1) & FH_MASK_INDEX; +- + return true; + } + ++static void s390_pcihost_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, ++ Error **errp) ++{ ++ S390pciState *s = S390_PCI_HOST_BRIDGE(hotplug_dev); ++ ++ if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) { ++ PCIDevice *pdev = PCI_DEVICE(dev); ++ ++ if (pdev->cap_present & QEMU_PCI_CAP_MULTIFUNCTION) { ++ error_setg(errp, "multifunction not supported in s390"); ++ return; ++ } ++ } else if (object_dynamic_cast(OBJECT(dev), TYPE_S390_PCI_DEVICE)) { ++ S390PCIBusDevice *pbdev = S390_PCI_DEVICE(dev); ++ ++ if (!s390_pci_alloc_idx(s, pbdev)) { ++ error_setg(errp, "no slot for plugging zpci device"); ++ return; ++ } ++ } ++} ++ + static void s390_pcihost_plug(HotplugHandler *hotplug_dev, DeviceState *dev, + Error **errp) + { +@@ -839,11 +859,6 @@ static void s390_pcihost_plug(HotplugHandler *hotplug_dev, DeviceState *dev, + PCIBridge *pb = PCI_BRIDGE(dev); + PCIDevice *pdev = PCI_DEVICE(dev); + +- if (pdev->cap_present & QEMU_PCI_CAP_MULTIFUNCTION) { +- error_setg(errp, "multifunction not supported in s390"); +- return; +- } +- + pci_bridge_map_irq(pb, dev->id, s390_pci_map_irq); + pci_setup_iommu(&pb->sec_bus, s390_pci_dma_iommu, s); + +@@ -863,11 +878,6 @@ static void s390_pcihost_plug(HotplugHandler *hotplug_dev, DeviceState *dev, + } else if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) { + pdev = PCI_DEVICE(dev); + +- if (pdev->cap_present & QEMU_PCI_CAP_MULTIFUNCTION) { +- error_setg(errp, "multifunction not supported in s390"); +- return; +- } +- + if (!dev->id) { + /* In the case the PCI device does not define an id */ + /* we generate one based on the PCI address */ +@@ -909,10 +919,8 @@ static void s390_pcihost_plug(HotplugHandler *hotplug_dev, DeviceState *dev, + } else if (object_dynamic_cast(OBJECT(dev), TYPE_S390_PCI_DEVICE)) { + pbdev = S390_PCI_DEVICE(dev); + +- if (!s390_pci_alloc_idx(s, pbdev)) { +- error_setg(errp, "no slot for plugging zpci device"); +- return; +- } ++ /* the allocated idx is actually getting used */ ++ s->next_idx = (pbdev->idx + 1) & FH_MASK_INDEX; + pbdev->fh = pbdev->idx; + QTAILQ_INSERT_TAIL(&s->zpci_devs, pbdev, link); + g_hash_table_insert(s->zpci_table, &pbdev->idx, pbdev); +@@ -1052,6 +1060,7 @@ static void s390_pcihost_class_init(ObjectClass *klass, void *data) + + dc->reset = s390_pcihost_reset; + dc->realize = s390_pcihost_realize; ++ hc->pre_plug = s390_pcihost_pre_plug; + hc->plug = s390_pcihost_plug; + hc->unplug = s390_pcihost_unplug; + msi_nonbroken = true; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390x-pci-Send-correct-event-on-hotplug.patch b/SOURCES/kvm-s390x-pci-Send-correct-event-on-hotplug.patch new file mode 100644 index 0000000..d00e4a1 --- /dev/null +++ b/SOURCES/kvm-s390x-pci-Send-correct-event-on-hotplug.patch @@ -0,0 +1,64 @@ +From 3ff64a000649028df66c83c6647258461b0ab8c5 Mon Sep 17 00:00:00 2001 +From: Cornelia Huck +Date: Wed, 17 Apr 2019 13:57:27 +0100 +Subject: [PATCH 10/24] s390x/pci: Send correct event on hotplug + +RH-Author: Cornelia Huck +Message-id: <20190417135741.25297-11-cohuck@redhat.com> +Patchwork-id: 85794 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v2 10/24] s390x/pci: Send correct event on hotplug +Bugzilla: 1699070 +RH-Acked-by: David Hildenbrand +RH-Acked-by: Thomas Huth +RH-Acked-by: Jens Freimann + +From: David Hildenbrand + +Comit 2c28c490571f ("s390x/pci: let pci devices start in configured mode") +changed the initial state of zPCI devices from ZPCI_FS_STANDBY to +ZPCI_FS_DISABLED (a.k.a. configured). However we still only send a +HP_EVENT_RESERVED_TO_STANDBY event to the guest, indicating a wrong +state. + +Let's send a HP_EVENT_TO_CONFIGURED event instead, to match the actual +state the device is in. + +This fixes hotplugged devices having to be enabled explicitly in the +guest e.g. via echo 1 > /sys/bus/pci/slots/00000000/power. + +On real HW, a PCI device always pops up in the STANDBY state. In QEMU, +we decided to let it show up directly in the configured state (as +configuring it is otherwise just an extra burden for the admin). We can +safely bypass the STANDBY state when hotplugging PCI devices to a guest. + +Fixes: 2c28c490571f ("s390x/pci: let pci devices start in configured mode") +Reported-by: Cornelia Huck +Signed-off-by: David Hildenbrand +Message-Id: <20190110210358.24035-1-david@redhat.com> +Tested-by: Cornelia Huck +Reviewed-by: Pierre Morel +Reviewed-by: Collin Walling +Signed-off-by: Cornelia Huck +(cherry picked from commit d57d6abc33c770b77732039ebcc96e26cf6ff285) +Signed-off-by: Cornelia Huck +Signed-off-by: Danilo C. L. de Paula +--- + hw/s390x/s390-pci-bus.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c +index 486c4b6..e19e134 100644 +--- a/hw/s390x/s390-pci-bus.c ++++ b/hw/s390x/s390-pci-bus.c +@@ -903,7 +903,7 @@ static void s390_pcihost_plug(HotplugHandler *hotplug_dev, DeviceState *dev, + } + + if (dev->hotplugged) { +- s390_pci_generate_plug_event(HP_EVENT_RESERVED_TO_STANDBY, ++ s390_pci_generate_plug_event(HP_EVENT_TO_CONFIGURED , + pbdev->fh, pbdev->fid); + } + } else if (object_dynamic_cast(OBJECT(dev), TYPE_S390_PCI_DEVICE)) { +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390x-pci-Set-the-iommu-region-size-mpcifc-request.patch b/SOURCES/kvm-s390x-pci-Set-the-iommu-region-size-mpcifc-request.patch new file mode 100644 index 0000000..764793b --- /dev/null +++ b/SOURCES/kvm-s390x-pci-Set-the-iommu-region-size-mpcifc-request.patch @@ -0,0 +1,51 @@ +From 15b59b77a4c7b9ef38e82b57a1dcdeb5c88b3156 Mon Sep 17 00:00:00 2001 +From: Cornelia Huck +Date: Wed, 17 Apr 2019 13:57:28 +0100 +Subject: [PATCH 11/24] s390x/pci: Set the iommu region size mpcifc request + +RH-Author: Cornelia Huck +Message-id: <20190417135741.25297-12-cohuck@redhat.com> +Patchwork-id: 85793 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v2 11/24] s390x/pci: Set the iommu region size mpcifc request +Bugzilla: 1699070 +RH-Acked-by: David Hildenbrand +RH-Acked-by: Thomas Huth +RH-Acked-by: Jens Freimann + +From: Pierre Morel + +The size of the accessible iommu memory region in the guest +is given to the IOMMU by the guest through the mpcifc request +specifying the PCI Base Address and the PCI Address Limit. + +Let's set the size of the IOMMU region to: + (PCI Address Limit) - (PCI Base Address) + 1. + +Fixes: f7c40aa1e7 ("s390x/pci: fix failures of dma map/unmap") +Signed-off-by: Pierre Morel +Message-Id: <1547125207-16907-2-git-send-email-pmorel@linux.ibm.com> +Acked-by: Collin Walling +Signed-off-by: Cornelia Huck +(cherry picked from commit dbe9cf606c2fe7365008be2a71d7b1781bbd5435) +Signed-off-by: Cornelia Huck +Signed-off-by: Danilo C. L. de Paula +--- + hw/s390x/s390-pci-bus.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c +index e19e134..a785acb 100644 +--- a/hw/s390x/s390-pci-bus.c ++++ b/hw/s390x/s390-pci-bus.c +@@ -660,7 +660,7 @@ void s390_pci_iommu_enable(S390PCIIOMMU *iommu) + char *name = g_strdup_printf("iommu-s390-%04x", iommu->pbdev->uid); + memory_region_init_iommu(&iommu->iommu_mr, sizeof(iommu->iommu_mr), + TYPE_S390_IOMMU_MEMORY_REGION, OBJECT(&iommu->mr), +- name, iommu->pal + 1); ++ name, iommu->pal - iommu->pba + 1); + iommu->enabled = true; + memory_region_add_subregion(&iommu->mr, 0, MEMORY_REGION(&iommu->iommu_mr)); + g_free(name); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390x-pci-Unplug-remaining-requested-devices-on-pcih.patch b/SOURCES/kvm-s390x-pci-Unplug-remaining-requested-devices-on-pcih.patch new file mode 100644 index 0000000..d52f1c4 --- /dev/null +++ b/SOURCES/kvm-s390x-pci-Unplug-remaining-requested-devices-on-pcih.patch @@ -0,0 +1,72 @@ +From ed71d0c46408c9fdf4df93ddc4d0610f0b039696 Mon Sep 17 00:00:00 2001 +From: Cornelia Huck +Date: Wed, 17 Apr 2019 13:57:39 +0100 +Subject: [PATCH 22/24] s390x/pci: Unplug remaining requested devices on + pcihost reset + +RH-Author: Cornelia Huck +Message-id: <20190417135741.25297-23-cohuck@redhat.com> +Patchwork-id: 85805 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v2 22/24] s390x/pci: Unplug remaining requested devices on pcihost reset +Bugzilla: 1699070 +RH-Acked-by: David Hildenbrand +RH-Acked-by: Thomas Huth +RH-Acked-by: Jens Freimann + +From: David Hildenbrand + +When resetting the guest we should unplug and remove all devices that +are still pending. + +With this patch, the requested device will be unplugged on reboot +(S390_RESET_EXTERNAL and S390_RESET_REIPL, which reset the pcihost bridge +via qemu_devices_reset()). + +This approach is similar to what's done for acpi PCI hotplug in +acpi_pcihp_reset() -> acpi_pcihp_update() -> +acpi_pcihp_update_hotplug_bus() -> acpi_pcihp_eject_slot(). + +s390_pci_generate_plug_event()'s will still be generated, I guess this +is not an issue. The same thing would happen right now when unplugging +a device just before starting the guest. + +Signed-off-by: David Hildenbrand +Message-Id: <20190130155733.32742-7-david@redhat.com> +Reviewed-by: Collin Walling +Signed-off-by: Cornelia Huck +(cherry picked from commit 2313a88fe68cb970532ba1641ffc35c848daae86) +Signed-off-by: Cornelia Huck +Signed-off-by: Danilo C. L. de Paula +--- + hw/s390x/s390-pci-bus.c | 15 +++++++++++++++ + 1 file changed, 15 insertions(+) + +diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c +index 1ba7873..383b3e7 100644 +--- a/hw/s390x/s390-pci-bus.c ++++ b/hw/s390x/s390-pci-bus.c +@@ -1097,6 +1097,21 @@ static void s390_pcihost_reset(DeviceState *dev) + { + S390pciState *s = S390_PCI_HOST_BRIDGE(dev); + PCIBus *bus = s->parent_obj.bus; ++ S390PCIBusDevice *pbdev, *next; ++ ++ /* Process all pending unplug requests */ ++ QTAILQ_FOREACH_SAFE(pbdev, &s->zpci_devs, link, next) { ++ if (pbdev->unplug_requested) { ++ if (pbdev->summary_ind) { ++ pci_dereg_irqs(pbdev); ++ } ++ if (pbdev->iommu->enabled) { ++ pci_dereg_ioat(pbdev->iommu); ++ } ++ pbdev->state = ZPCI_FS_STANDBY; ++ s390_pci_perform_unplug(pbdev); ++ } ++ } + + /* + * When resetting a PCI bridge, the assigned numbers are set to 0. So +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390x-pci-Use-hotplug_dev-instead-of-looking-up-the-.patch b/SOURCES/kvm-s390x-pci-Use-hotplug_dev-instead-of-looking-up-the-.patch new file mode 100644 index 0000000..80d83d4 --- /dev/null +++ b/SOURCES/kvm-s390x-pci-Use-hotplug_dev-instead-of-looking-up-the-.patch @@ -0,0 +1,61 @@ +From 3fb1ffd096f874877f93af29697a5ff4038b014d Mon Sep 17 00:00:00 2001 +From: Cornelia Huck +Date: Wed, 17 Apr 2019 13:57:31 +0100 +Subject: [PATCH 14/24] s390x/pci: Use hotplug_dev instead of looking up the + host bridge + +RH-Author: Cornelia Huck +Message-id: <20190417135741.25297-15-cohuck@redhat.com> +Patchwork-id: 85789 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v2 14/24] s390x/pci: Use hotplug_dev instead of looking up the host bridge +Bugzilla: 1699070 +RH-Acked-by: David Hildenbrand +RH-Acked-by: Thomas Huth +RH-Acked-by: Jens Freimann + +From: David Hildenbrand + +We directly have it in our hands. + +Signed-off-by: David Hildenbrand +Message-Id: <20190114103110.10909-2-david@redhat.com> +Reviewed-by: Collin Walling +Signed-off-by: Cornelia Huck +(cherry picked from commit 19375e9be0ccb7ec02dffbc6ffceafd3c480b799) +Signed-off-by: Cornelia Huck +Signed-off-by: Danilo C. L. de Paula +--- + hw/s390x/s390-pci-bus.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c +index 24a0d78..f1b3334 100644 +--- a/hw/s390x/s390-pci-bus.c ++++ b/hw/s390x/s390-pci-bus.c +@@ -830,9 +830,9 @@ static bool s390_pci_alloc_idx(S390pciState *s, S390PCIBusDevice *pbdev) + static void s390_pcihost_plug(HotplugHandler *hotplug_dev, DeviceState *dev, + Error **errp) + { ++ S390pciState *s = S390_PCI_HOST_BRIDGE(hotplug_dev); + PCIDevice *pdev = NULL; + S390PCIBusDevice *pbdev = NULL; +- S390pciState *s = s390_get_phb(); + + if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_BRIDGE)) { + BusState *bus; +@@ -941,11 +941,11 @@ static void s390_pcihost_timer_cb(void *opaque) + static void s390_pcihost_unplug(HotplugHandler *hotplug_dev, DeviceState *dev, + Error **errp) + { ++ S390pciState *s = S390_PCI_HOST_BRIDGE(hotplug_dev); + PCIDevice *pci_dev = NULL; + PCIBus *bus; + int32_t devfn; + S390PCIBusDevice *pbdev = NULL; +- S390pciState *s = s390_get_phb(); + + if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_BRIDGE)) { + error_setg(errp, "PCI bridge hot unplug currently not supported"); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390x-pci-Warn-when-adding-PCI-devices-without-the-z.patch b/SOURCES/kvm-s390x-pci-Warn-when-adding-PCI-devices-without-the-z.patch new file mode 100644 index 0000000..a2c8560 --- /dev/null +++ b/SOURCES/kvm-s390x-pci-Warn-when-adding-PCI-devices-without-the-z.patch @@ -0,0 +1,59 @@ +From 9f13c7165566f442484fa6c335950465ed6a2050 Mon Sep 17 00:00:00 2001 +From: Cornelia Huck +Date: Wed, 17 Apr 2019 13:57:38 +0100 +Subject: [PATCH 21/24] s390x/pci: Warn when adding PCI devices without the + 'zpci' feature + +RH-Author: Cornelia Huck +Message-id: <20190417135741.25297-22-cohuck@redhat.com> +Patchwork-id: 85803 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v2 21/24] s390x/pci: Warn when adding PCI devices without the 'zpci' feature +Bugzilla: 1699070 +RH-Acked-by: David Hildenbrand +RH-Acked-by: Thomas Huth +RH-Acked-by: Jens Freimann + +From: David Hildenbrand + +We decided to always create the PCI host bridge, even if 'zpci' is not +enabled (due to migration compatibility). This however right now allows +to add zPCI/PCI devices to a VM although the guest will never actually see +them, confusing people that are using a simple CPU model that has no +'zpci' enabled - "Why isn't this working" (David Hildenbrand) + +Let's check for 'zpci' and at least print a warning that this will not +work as expected. We could also bail out, however that might break +existing QEMU commandlines. + +Reviewed-by: Thomas Huth +Signed-off-by: David Hildenbrand +Message-Id: <20190130155733.32742-4-david@redhat.com> +Reviewed-by: Collin Walling +Signed-off-by: Cornelia Huck +(cherry picked from commit 703fef6fcf3edcbf169c90b6196fcf88f9e9765a) +Signed-off-by: Cornelia Huck +Signed-off-by: Danilo C. L. de Paula +--- + hw/s390x/s390-pci-bus.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c +index a0f7245..1ba7873 100644 +--- a/hw/s390x/s390-pci-bus.c ++++ b/hw/s390x/s390-pci-bus.c +@@ -864,6 +864,12 @@ static void s390_pcihost_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, + { + S390pciState *s = S390_PCI_HOST_BRIDGE(hotplug_dev); + ++ if (!s390_has_feat(S390_FEAT_ZPCI)) { ++ warn_report("Plugging a PCI/zPCI device without the 'zpci' CPU " ++ "feature enabled; the guest will not be able to see/use " ++ "this device"); ++ } ++ + if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) { + PCIDevice *pdev = PCI_DEVICE(dev); + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390x-pci-mark-zpci-devices-as-unmigratable.patch b/SOURCES/kvm-s390x-pci-mark-zpci-devices-as-unmigratable.patch new file mode 100644 index 0000000..f83f741 --- /dev/null +++ b/SOURCES/kvm-s390x-pci-mark-zpci-devices-as-unmigratable.patch @@ -0,0 +1,64 @@ +From 1b270931bb1743918638b9e6f003b2f2a95f0685 Mon Sep 17 00:00:00 2001 +From: Cornelia Huck +Date: Wed, 17 Apr 2019 13:57:35 +0100 +Subject: [PATCH 18/24] s390x/pci: mark zpci devices as unmigratable + +RH-Author: Cornelia Huck +Message-id: <20190417135741.25297-19-cohuck@redhat.com> +Patchwork-id: 85796 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v2 18/24] s390x/pci: mark zpci devices as unmigratable +Bugzilla: 1699070 +RH-Acked-by: David Hildenbrand +RH-Acked-by: Thomas Huth +RH-Acked-by: Jens Freimann + +We currently don't migrate any state for zpci devices, which are +coupled with standard pci devices. This means funny things happen +when we e.g. try to migrate with a virtio-pci device but the s390x- +specific zpci state is not migrated (vfio-pci is not affected, as +it is not migratable anyway.) + +Until this is fixed, mark zpci devices as unmigratable. + +Reported-by: David Hildenbrand +Reviewed-by: David Hildenbrand +Reviewed-by: Collin Walling +Signed-off-by: Cornelia Huck +(cherry picked from commit aede5d5dfc5f3e4ea7467b28c51fda2f8945d117) +Signed-off-by: Cornelia Huck +Signed-off-by: Danilo C. L. de Paula +--- + hw/s390x/s390-pci-bus.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c +index 97d3eb8..07a286a 100644 +--- a/hw/s390x/s390-pci-bus.c ++++ b/hw/s390x/s390-pci-bus.c +@@ -1256,6 +1256,15 @@ static Property s390_pci_device_properties[] = { + DEFINE_PROP_END_OF_LIST(), + }; + ++static const VMStateDescription s390_pci_device_vmstate = { ++ .name = TYPE_S390_PCI_DEVICE, ++ /* ++ * TODO: add state handling here, so migration works at least with ++ * emulated pci devices on s390x ++ */ ++ .unmigratable = 1, ++}; ++ + static void s390_pci_device_class_init(ObjectClass *klass, void *data) + { + DeviceClass *dc = DEVICE_CLASS(klass); +@@ -1266,6 +1275,7 @@ static void s390_pci_device_class_init(ObjectClass *klass, void *data) + dc->bus_type = TYPE_S390_PCI_BUS; + dc->realize = s390_pci_device_realize; + dc->props = s390_pci_device_properties; ++ dc->vmsd = &s390_pci_device_vmstate; + } + + static const TypeInfo s390_pci_device_info = { +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390x-pci-properly-fail-if-the-zPCI-device-cannot-be.patch b/SOURCES/kvm-s390x-pci-properly-fail-if-the-zPCI-device-cannot-be.patch new file mode 100644 index 0000000..591247e --- /dev/null +++ b/SOURCES/kvm-s390x-pci-properly-fail-if-the-zPCI-device-cannot-be.patch @@ -0,0 +1,92 @@ +From c66f28ded3ebb8926eeed2ce6abea53053359c99 Mon Sep 17 00:00:00 2001 +From: Cornelia Huck +Date: Wed, 17 Apr 2019 13:57:24 +0100 +Subject: [PATCH 07/24] s390x/pci: properly fail if the zPCI device cannot be + created + +RH-Author: Cornelia Huck +Message-id: <20190417135741.25297-8-cohuck@redhat.com> +Patchwork-id: 85792 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v2 07/24] s390x/pci: properly fail if the zPCI device cannot be created +Bugzilla: 1699070 +RH-Acked-by: David Hildenbrand +RH-Acked-by: Thomas Huth +RH-Acked-by: Jens Freimann + +From: David Hildenbrand + +Right now, errors during realize()/pre_plug/plug of the zPCI device +would result in QEMU crashing instead of failing nicely when creating +a zPCI device for a PCI device. + +Reviewed-by: Thomas Huth +Reviewed-by: Collin Walling +Signed-off-by: David Hildenbrand +Message-Id: <20181113121710.18490-1-david@redhat.com> +Signed-off-by: Cornelia Huck +(cherry picked from commit b6e67ecc7b6e8938982ab94820c079f24845f623) +Signed-off-by: Cornelia Huck + +Changes: + We don't have 4b5766488f ("error: Fix use of error_prepend() with + &error_fatal, &error_abort") downstream. + +Signed-off-by: Danilo C. L. de Paula +--- + hw/s390x/s390-pci-bus.c | 25 +++++++++++++++++++------ + 1 file changed, 19 insertions(+), 6 deletions(-) + +diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c +index f253774..e6f5d91 100644 +--- a/hw/s390x/s390-pci-bus.c ++++ b/hw/s390x/s390-pci-bus.c +@@ -780,17 +780,31 @@ static void s390_pci_msix_free(S390PCIBusDevice *pbdev) + } + + static S390PCIBusDevice *s390_pci_device_new(S390pciState *s, +- const char *target) ++ const char *target, Error **errp) + { +- DeviceState *dev = NULL; ++ Error *local_err = NULL; ++ DeviceState *dev; + + dev = qdev_try_create(BUS(s->bus), TYPE_S390_PCI_DEVICE); + if (!dev) { ++ error_setg(errp, "zPCI device could not be created"); + return NULL; + } + +- qdev_prop_set_string(dev, "target", target); +- qdev_init_nofail(dev); ++ object_property_set_str(OBJECT(dev), target, "target", &local_err); ++ if (local_err) { ++ object_unparent(OBJECT(dev)); ++ error_prepend(&local_err, "zPCI device could not be created: "); ++ error_propagate(errp, local_err); ++ return NULL; ++ } ++ object_property_set_bool(OBJECT(dev), true, "realized", &local_err); ++ if (local_err) { ++ object_unparent(OBJECT(dev)); ++ error_prepend(&local_err, "zPCI device could not be created: "); ++ error_propagate(errp, local_err); ++ return NULL; ++ } + + return S390_PCI_DEVICE(dev); + } +@@ -865,9 +879,8 @@ static void s390_pcihost_hot_plug(HotplugHandler *hotplug_dev, + + pbdev = s390_pci_find_dev_by_target(s, dev->id); + if (!pbdev) { +- pbdev = s390_pci_device_new(s, dev->id); ++ pbdev = s390_pci_device_new(s, dev->id, errp); + if (!pbdev) { +- error_setg(errp, "create zpci device failed"); + return; + } + } +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390x-pci-rename-hotplug-handler-callbacks.patch b/SOURCES/kvm-s390x-pci-rename-hotplug-handler-callbacks.patch new file mode 100644 index 0000000..d798f3a --- /dev/null +++ b/SOURCES/kvm-s390x-pci-rename-hotplug-handler-callbacks.patch @@ -0,0 +1,77 @@ +From d39e15cb0f762201de719f1bf8193dc0f275f6c3 Mon Sep 17 00:00:00 2001 +From: Cornelia Huck +Date: Wed, 17 Apr 2019 13:57:25 +0100 +Subject: [PATCH 08/24] s390x/pci: rename hotplug handler callbacks +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Cornelia Huck +Message-id: <20190417135741.25297-9-cohuck@redhat.com> +Patchwork-id: 85788 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v2 08/24] s390x/pci: rename hotplug handler callbacks +Bugzilla: 1699070 +RH-Acked-by: David Hildenbrand +RH-Acked-by: Thomas Huth +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Jens Freimann + +From: David Hildenbrand + +The callbacks are also called for cold plugged devices. Drop the "hot" +to better match the actual callback names. + +Reviewed-by: David Gibson +Reviewed-by: Cornelia Huck +Reviewed-by: Igor Mammedov +Reviewed-by: Pierre Morel +Signed-off-by: David Hildenbrand +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +(cherry picked from commit fa2a7751172b6228706decfbdddb6eac39052ab1) +Signed-off-by: Cornelia Huck +Signed-off-by: Danilo C. L. de Paula +--- + hw/s390x/s390-pci-bus.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c +index e6f5d91..9c444b6 100644 +--- a/hw/s390x/s390-pci-bus.c ++++ b/hw/s390x/s390-pci-bus.c +@@ -827,8 +827,8 @@ static bool s390_pci_alloc_idx(S390pciState *s, S390PCIBusDevice *pbdev) + return true; + } + +-static void s390_pcihost_hot_plug(HotplugHandler *hotplug_dev, +- DeviceState *dev, Error **errp) ++static void s390_pcihost_plug(HotplugHandler *hotplug_dev, DeviceState *dev, ++ Error **errp) + { + PCIDevice *pdev = NULL; + S390PCIBusDevice *pbdev = NULL; +@@ -936,8 +936,8 @@ static void s390_pcihost_timer_cb(void *opaque) + qdev_unplug(DEVICE(pbdev), NULL); + } + +-static void s390_pcihost_hot_unplug(HotplugHandler *hotplug_dev, +- DeviceState *dev, Error **errp) ++static void s390_pcihost_unplug(HotplugHandler *hotplug_dev, DeviceState *dev, ++ Error **errp) + { + PCIDevice *pci_dev = NULL; + PCIBus *bus; +@@ -1045,8 +1045,8 @@ static void s390_pcihost_class_init(ObjectClass *klass, void *data) + + dc->reset = s390_pcihost_reset; + dc->realize = s390_pcihost_realize; +- hc->plug = s390_pcihost_hot_plug; +- hc->unplug = s390_pcihost_hot_unplug; ++ hc->plug = s390_pcihost_plug; ++ hc->unplug = s390_pcihost_unplug; + msi_nonbroken = true; + } + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390x-refactor-reset-reipl-handling.patch b/SOURCES/kvm-s390x-refactor-reset-reipl-handling.patch new file mode 100644 index 0000000..641570f --- /dev/null +++ b/SOURCES/kvm-s390x-refactor-reset-reipl-handling.patch @@ -0,0 +1,415 @@ +From 4949ead0219a44a8419ac6726f219aafd0f91137 Mon Sep 17 00:00:00 2001 +From: Cornelia Huck +Date: Wed, 17 Apr 2019 13:57:40 +0100 +Subject: [PATCH 23/24] s390x: refactor reset/reipl handling + +RH-Author: Cornelia Huck +Message-id: <20190417135741.25297-24-cohuck@redhat.com> +Patchwork-id: 85802 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v2 23/24] s390x: refactor reset/reipl handling +Bugzilla: 1699070 +RH-Acked-by: David Hildenbrand +RH-Acked-by: Thomas Huth +RH-Acked-by: Jens Freimann + +From: David Hildenbrand + +Calling pause_all_vcpus()/resume_all_vcpus() from a VCPU thread might +not be the best idea. As pause_all_vcpus() temporarily drops the qemu +mutex, two parallel calls to pause_all_vcpus() can be active at a time, +resulting in a deadlock. (either by two VCPUs or by the main thread and a +VCPU) + +Let's handle it via the main loop instead, as suggested by Paolo. If we +would have two parallel reset requests by two different VCPUs at the +same time, the last one would win. + +We use the existing ipl device to handle it. The nice side effect is +that we can get rid of reipl_requested. + +This change implies that all reset handling now goes via the common +path, so "no-reboot" handling is now active for all kinds of reboots. + +Let's execute any CPU initialization code on the target CPU using +run_on_cpu. + +Signed-off-by: David Hildenbrand +Message-Id: <20180424101859.10239-1-david@redhat.com> +Acked-by: Thomas Huth +Signed-off-by: Cornelia Huck +(cherry picked from commit a30fb811cbe940020a498d2cdac9326cac38b4d9) +Signed-off-by: Cornelia Huck +Signed-off-by: Danilo C. L. de Paula +--- + hw/s390x/ipl.c | 43 +++++++++++++++++++++++---- + hw/s390x/ipl.h | 16 ++++++++-- + hw/s390x/s390-virtio-ccw.c | 51 ++++++++++++++++++++++++++----- + include/hw/s390x/s390-virtio-ccw.h | 2 -- + target/s390x/cpu.h | 26 ++++++++++++++++ + target/s390x/diag.c | 61 +++----------------------------------- + target/s390x/internal.h | 6 ---- + target/s390x/kvm.c | 2 +- + 8 files changed, 127 insertions(+), 80 deletions(-) + +diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c +index 10038ec..ee6701e 100644 +--- a/hw/s390x/ipl.c ++++ b/hw/s390x/ipl.c +@@ -26,6 +26,7 @@ + #include "qemu/config-file.h" + #include "qemu/cutils.h" + #include "qemu/option.h" ++#include "exec/exec-all.h" + + #define KERN_IMAGE_START 0x010000UL + #define LINUX_MAGIC_ADDR 0x010008UL +@@ -511,12 +512,20 @@ IplParameterBlock *s390_ipl_get_iplb(void) + return &ipl->iplb; + } + +-void s390_reipl_request(void) ++void s390_ipl_reset_request(CPUState *cs, enum s390_reset reset_type) + { + S390IPLState *ipl = get_ipl_device(); + +- ipl->reipl_requested = true; +- if (ipl->iplb_valid && ++ if (reset_type == S390_RESET_EXTERNAL || reset_type == S390_RESET_REIPL) { ++ /* use CPU 0 for full resets */ ++ ipl->reset_cpu_index = 0; ++ } else { ++ ipl->reset_cpu_index = cs->cpu_index; ++ } ++ ipl->reset_type = reset_type; ++ ++ if (reset_type == S390_RESET_REIPL && ++ ipl->iplb_valid && + !ipl->netboot && + ipl->iplb.pbt == S390_IPL_TYPE_CCW && + is_virtio_scsi_device(&ipl->iplb)) { +@@ -533,6 +542,31 @@ void s390_reipl_request(void) + } + } + qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); ++ /* as this is triggered by a CPU, make sure to exit the loop */ ++ if (tcg_enabled()) { ++ cpu_loop_exit(cs); ++ } ++} ++ ++void s390_ipl_get_reset_request(CPUState **cs, enum s390_reset *reset_type) ++{ ++ S390IPLState *ipl = get_ipl_device(); ++ ++ *cs = qemu_get_cpu(ipl->reset_cpu_index); ++ if (!*cs) { ++ /* use any CPU */ ++ *cs = first_cpu; ++ } ++ *reset_type = ipl->reset_type; ++} ++ ++void s390_ipl_clear_reset_request(void) ++{ ++ S390IPLState *ipl = get_ipl_device(); ++ ++ ipl->reset_type = S390_RESET_EXTERNAL; ++ /* use CPU 0 for full resets */ ++ ipl->reset_cpu_index = 0; + } + + static void s390_ipl_prepare_qipl(S390CPU *cpu) +@@ -579,11 +613,10 @@ static void s390_ipl_reset(DeviceState *dev) + { + S390IPLState *ipl = S390_IPL(dev); + +- if (!ipl->reipl_requested) { ++ if (ipl->reset_type != S390_RESET_REIPL) { + ipl->iplb_valid = false; + memset(&ipl->iplb, 0, sizeof(IplParameterBlock)); + } +- ipl->reipl_requested = false; + } + + static void s390_ipl_class_init(ObjectClass *klass, void *data) +diff --git a/hw/s390x/ipl.h b/hw/s390x/ipl.h +index 0570d0a..4e87b89 100644 +--- a/hw/s390x/ipl.h ++++ b/hw/s390x/ipl.h +@@ -87,7 +87,17 @@ int s390_ipl_set_loadparm(uint8_t *loadparm); + void s390_ipl_update_diag308(IplParameterBlock *iplb); + void s390_ipl_prepare_cpu(S390CPU *cpu); + IplParameterBlock *s390_ipl_get_iplb(void); +-void s390_reipl_request(void); ++ ++enum s390_reset { ++ /* default is a reset not triggered by a CPU e.g. issued by QMP */ ++ S390_RESET_EXTERNAL = 0, ++ S390_RESET_REIPL, ++ S390_RESET_MODIFIED_CLEAR, ++ S390_RESET_LOAD_NORMAL, ++}; ++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); ++void s390_ipl_clear_reset_request(void); + + #define QIPL_ADDRESS 0xcc + +@@ -129,9 +139,11 @@ struct S390IPLState { + bool enforce_bios; + IplParameterBlock iplb; + bool iplb_valid; +- bool reipl_requested; + bool netboot; + QemuIplParameters qipl; ++ /* reset related properties don't have to be migrated or reset */ ++ enum s390_reset reset_type; ++ int reset_cpu_index; + + /*< public >*/ + char *kernel; +diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c +index 8f93edc..ba90e4f 100644 +--- a/hw/s390x/s390-virtio-ccw.c ++++ b/hw/s390x/s390-virtio-ccw.c +@@ -95,7 +95,7 @@ static const char *const reset_dev_types[] = { + "diag288", + }; + +-void subsystem_reset(void) ++static void subsystem_reset(void) + { + DeviceState *dev; + int i; +@@ -317,17 +317,54 @@ static void s390_cpu_plug(HotplugHandler *hotplug_dev, + } + } + ++static inline void s390_do_cpu_ipl(CPUState *cs, run_on_cpu_data arg) ++{ ++ S390CPU *cpu = S390_CPU(cs); ++ ++ s390_ipl_prepare_cpu(cpu); ++ s390_cpu_set_state(S390_CPU_STATE_OPERATING, cpu); ++} ++ + static void s390_machine_reset(void) + { +- S390CPU *ipl_cpu = S390_CPU(qemu_get_cpu(0)); ++ enum s390_reset reset_type; ++ CPUState *cs, *t; + ++ /* get the reset parameters, reset them once done */ ++ s390_ipl_get_reset_request(&cs, &reset_type); ++ ++ /* all CPUs are paused and synchronized at this point */ + s390_cmma_reset(); +- qemu_devices_reset(); +- s390_crypto_reset(); + +- /* all cpus are stopped - configure and start the ipl cpu only */ +- s390_ipl_prepare_cpu(ipl_cpu); +- s390_cpu_set_state(S390_CPU_STATE_OPERATING, ipl_cpu); ++ switch (reset_type) { ++ case S390_RESET_EXTERNAL: ++ case S390_RESET_REIPL: ++ qemu_devices_reset(); ++ s390_crypto_reset(); ++ ++ /* configure and start the ipl CPU only */ ++ run_on_cpu(cs, s390_do_cpu_ipl, RUN_ON_CPU_NULL); ++ break; ++ case S390_RESET_MODIFIED_CLEAR: ++ 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: ++ CPU_FOREACH(t) { ++ 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; ++ default: ++ g_assert_not_reached(); ++ } ++ s390_ipl_clear_reset_request(); + } + + static void s390_machine_device_plug(HotplugHandler *hotplug_dev, +diff --git a/include/hw/s390x/s390-virtio-ccw.h b/include/hw/s390x/s390-virtio-ccw.h +index ac896e3..ab88d49 100644 +--- a/include/hw/s390x/s390-virtio-ccw.h ++++ b/include/hw/s390x/s390-virtio-ccw.h +@@ -53,6 +53,4 @@ bool cpu_model_allowed(void); + */ + bool css_migration_enabled(void); + +-void subsystem_reset(void); +- + #endif +diff --git a/target/s390x/cpu.h b/target/s390x/cpu.h +index 6500f42..21b2f21 100644 +--- a/target/s390x/cpu.h ++++ b/target/s390x/cpu.h +@@ -687,6 +687,32 @@ static inline uint64_t s390_build_validity_mcic(void) + return mcic; + } + ++static inline void s390_do_cpu_full_reset(CPUState *cs, run_on_cpu_data arg) ++{ ++ cpu_reset(cs); ++} ++ ++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); ++} ++ ++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); ++} ++ ++static inline void s390_do_cpu_load_normal(CPUState *cs, run_on_cpu_data arg) ++{ ++ S390CPUClass *scc = S390_CPU_GET_CLASS(cs); ++ ++ scc->load_normal(cs); ++} ++ + + /* cpu.c */ + void s390_crypto_reset(void); +diff --git a/target/s390x/diag.c b/target/s390x/diag.c +index 50b58df..b5d5f8e 100644 +--- a/target/s390x/diag.c ++++ b/target/s390x/diag.c +@@ -22,51 +22,6 @@ + #include "hw/s390x/ipl.h" + #include "hw/s390x/s390-virtio-ccw.h" + +-static int modified_clear_reset(S390CPU *cpu) +-{ +- S390CPUClass *scc = S390_CPU_GET_CLASS(cpu); +- CPUState *t; +- +- pause_all_vcpus(); +- cpu_synchronize_all_states(); +- CPU_FOREACH(t) { +- run_on_cpu(t, s390_do_cpu_full_reset, RUN_ON_CPU_NULL); +- } +- s390_cmma_reset(); +- subsystem_reset(); +- s390_crypto_reset(); +- scc->load_normal(CPU(cpu)); +- cpu_synchronize_all_post_reset(); +- resume_all_vcpus(); +- return 0; +-} +- +-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); +-} +- +-static int load_normal_reset(S390CPU *cpu) +-{ +- S390CPUClass *scc = S390_CPU_GET_CLASS(cpu); +- CPUState *t; +- +- pause_all_vcpus(); +- cpu_synchronize_all_states(); +- CPU_FOREACH(t) { +- run_on_cpu(t, s390_do_cpu_reset, RUN_ON_CPU_NULL); +- } +- s390_cmma_reset(); +- subsystem_reset(); +- scc->initial_cpu_reset(CPU(cpu)); +- scc->load_normal(CPU(cpu)); +- cpu_synchronize_all_post_reset(); +- resume_all_vcpus(); +- return 0; +-} +- + int handle_diag_288(CPUS390XState *env, uint64_t r1, uint64_t r3) + { + uint64_t func = env->regs[r1]; +@@ -101,6 +56,7 @@ int handle_diag_288(CPUS390XState *env, uint64_t r1, uint64_t r3) + + void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3, uintptr_t ra) + { ++ CPUState *cs = CPU(s390_env_get_cpu(env)); + uint64_t addr = env->regs[r1]; + uint64_t subcode = env->regs[r3]; + IplParameterBlock *iplb; +@@ -117,22 +73,13 @@ void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3, uintptr_t ra) + + switch (subcode) { + case 0: +- modified_clear_reset(s390_env_get_cpu(env)); +- if (tcg_enabled()) { +- cpu_loop_exit(CPU(s390_env_get_cpu(env))); +- } ++ s390_ipl_reset_request(cs, S390_RESET_MODIFIED_CLEAR); + break; + case 1: +- load_normal_reset(s390_env_get_cpu(env)); +- if (tcg_enabled()) { +- cpu_loop_exit(CPU(s390_env_get_cpu(env))); +- } ++ s390_ipl_reset_request(cs, S390_RESET_LOAD_NORMAL); + break; + case 3: +- s390_reipl_request(); +- if (tcg_enabled()) { +- cpu_loop_exit(CPU(s390_env_get_cpu(env))); +- } ++ s390_ipl_reset_request(cs, S390_RESET_REIPL); + break; + case 5: + if ((r1 & 1) || (addr & 0x0fffULL)) { +diff --git a/target/s390x/internal.h b/target/s390x/internal.h +index 61a509d..f2a771e 100644 +--- a/target/s390x/internal.h ++++ b/target/s390x/internal.h +@@ -258,12 +258,6 @@ static inline hwaddr decode_basedisp_s(CPUS390XState *env, uint32_t ipb, + /* Base/displacement are at the same locations. */ + #define decode_basedisp_rs decode_basedisp_s + +-static inline void s390_do_cpu_full_reset(CPUState *cs, run_on_cpu_data arg) +-{ +- cpu_reset(cs); +-} +- +- + /* arch_dump.c */ + int s390_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs, + int cpuid, void *opaque); +diff --git a/target/s390x/kvm.c b/target/s390x/kvm.c +index 1cf117b..114502d 100644 +--- a/target/s390x/kvm.c ++++ b/target/s390x/kvm.c +@@ -1826,7 +1826,7 @@ int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run) + ret = handle_intercept(cpu); + break; + case KVM_EXIT_S390_RESET: +- s390_reipl_request(); ++ s390_ipl_reset_request(cs, S390_RESET_REIPL); + break; + case KVM_EXIT_S390_TSCH: + ret = handle_tsch(cpu); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390x-storage-attributes-fix-CMMA_BLOCK_SIZE-usage.patch b/SOURCES/kvm-s390x-storage-attributes-fix-CMMA_BLOCK_SIZE-usage.patch new file mode 100644 index 0000000..e0b1423 --- /dev/null +++ b/SOURCES/kvm-s390x-storage-attributes-fix-CMMA_BLOCK_SIZE-usage.patch @@ -0,0 +1,75 @@ +From aaec9beefcdc4e8cbef669d0115f4405498400de Mon Sep 17 00:00:00 2001 +From: Cornelia Huck +Date: Wed, 17 Apr 2019 13:57:21 +0100 +Subject: [PATCH 04/24] s390x/storage attributes: fix CMMA_BLOCK_SIZE usage + +RH-Author: Cornelia Huck +Message-id: <20190417135741.25297-5-cohuck@redhat.com> +Patchwork-id: 85786 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v2 04/24] s390x/storage attributes: fix CMMA_BLOCK_SIZE usage +Bugzilla: 1699070 +RH-Acked-by: David Hildenbrand +RH-Acked-by: Thomas Huth +RH-Acked-by: Jens Freimann + +From: Claudio Imbrenda + +The macro CMMA_BLOCK_SIZE was defined but not used, and a hardcoded +value was instead used in the code. + +This patch fixes the value of CMMA_BLOCK_SIZE and uses it in the +appropriate place in the code, and fixes another case of hardcoded +value in the KVM backend, replacing it with the more appropriate +constant KVM_S390_CMMA_SIZE_MAX. + +Signed-off-by: Claudio Imbrenda +Message-Id: <1530787170-3101-1-git-send-email-imbrenda@linux.vnet.ibm.com> +Signed-off-by: Cornelia Huck +(cherry picked from commit 17f4566657df51c5e0cb40f30491e058d74d63c8) +Signed-off-by: Cornelia Huck +Signed-off-by: Danilo C. L. de Paula +--- + hw/s390x/s390-stattrib-kvm.c | 3 ++- + hw/s390x/s390-stattrib.c | 5 +++-- + 2 files changed, 5 insertions(+), 3 deletions(-) + +diff --git a/hw/s390x/s390-stattrib-kvm.c b/hw/s390x/s390-stattrib-kvm.c +index 480551c..c7e1f35 100644 +--- a/hw/s390x/s390-stattrib-kvm.c ++++ b/hw/s390x/s390-stattrib-kvm.c +@@ -105,7 +105,8 @@ static void kvm_s390_stattrib_synchronize(S390StAttribState *sa) + KVMS390StAttribState *sas = KVM_S390_STATTRIB(sa); + MachineState *machine = MACHINE(qdev_get_machine()); + unsigned long max = machine->maxram_size / TARGET_PAGE_SIZE; +- unsigned long cx, len = 1 << 19; ++ /* We do not need to reach the maximum buffer size allowed */ ++ unsigned long cx, len = KVM_S390_SKEYS_MAX / 2; + int r; + struct kvm_s390_cmma_log clog = { + .flags = 0, +diff --git a/hw/s390x/s390-stattrib.c b/hw/s390x/s390-stattrib.c +index 5161a16..766f201 100644 +--- a/hw/s390x/s390-stattrib.c ++++ b/hw/s390x/s390-stattrib.c +@@ -21,7 +21,8 @@ + #include "qapi/error.h" + #include "qapi/qmp/qdict.h" + +-#define CMMA_BLOCK_SIZE (1 * KiB) ++/* 512KiB cover 2GB of guest memory */ ++#define CMMA_BLOCK_SIZE (512 * KiB) + + #define STATTR_FLAG_EOS 0x01ULL + #define STATTR_FLAG_MORE 0x02ULL +@@ -203,7 +204,7 @@ static int cmma_save(QEMUFile *f, void *opaque, int final) + S390StAttribClass *sac = S390_STATTRIB_GET_CLASS(sas); + uint8_t *buf; + int r, cx, reallen = 0, ret = 0; +- uint32_t buflen = 1 << 19; /* 512kB cover 2GB of guest memory */ ++ uint32_t buflen = CMMA_BLOCK_SIZE; + uint64_t start_gfn = sas->migration_cur_gfn; + + buf = g_try_malloc(buflen); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-scsi-disk-Acquire-the-AioContext-in-scsi_-_realize.patch b/SOURCES/kvm-scsi-disk-Acquire-the-AioContext-in-scsi_-_realize.patch index fc0576a..0168154 100644 --- a/SOURCES/kvm-scsi-disk-Acquire-the-AioContext-in-scsi_-_realize.patch +++ b/SOURCES/kvm-scsi-disk-Acquire-the-AioContext-in-scsi_-_realize.patch @@ -1,13 +1,13 @@ -From e0999eaacc6e74f5e56f51fcf3b3d7aeca7d3b04 Mon Sep 17 00:00:00 2001 +From f211540f531d850eb336154469d936b87398d877 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Thu, 6 Jun 2019 19:15:23 +0100 -Subject: [PATCH 6/7] scsi-disk: Acquire the AioContext in scsi_*_realize() +Subject: [PATCH 6/8] scsi-disk: Acquire the AioContext in scsi_*_realize() RH-Author: Markus Armbruster Message-id: <20190606191524.30797-3-armbru@redhat.com> Patchwork-id: 88605 O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 2/3] scsi-disk: Acquire the AioContext in scsi_*_realize() -Bugzilla: 1718992 +Bugzilla: 1673396 1673401 RH-Acked-by: Paolo Bonzini RH-Acked-by: Stefan Hajnoczi RH-Acked-by: Kevin Wolf diff --git a/SOURCES/kvm-setup b/SOURCES/kvm-setup index abbd587..3bfedf6 100644 --- a/SOURCES/kvm-setup +++ b/SOURCES/kvm-setup @@ -31,10 +31,19 @@ kvm_setup_powerpc () { fi } +kvm_setup_s390x () { + if grep -q "^features.*sie" /proc/cpuinfo; then + modprobe kvm + fi +} + case $(uname -m) in ppc64|ppc64le) kvm_setup_powerpc ;; + s390x) + kvm_setup_s390x + ;; esac exit 0 diff --git a/SOURCES/kvm-slirp-check-sscanf-result-when-emulating-ident.patch b/SOURCES/kvm-slirp-check-sscanf-result-when-emulating-ident.patch index 8ef4361..1cd1228 100644 --- a/SOURCES/kvm-slirp-check-sscanf-result-when-emulating-ident.patch +++ b/SOURCES/kvm-slirp-check-sscanf-result-when-emulating-ident.patch @@ -1,19 +1,19 @@ -From dff4ed62fe8723574ac36029574364ddf85b7fe6 Mon Sep 17 00:00:00 2001 +From 49fbfce352a678b538113598cba05c48281174a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= -Date: Mon, 8 Jul 2019 15:50:28 +0100 -Subject: [PATCH 1/7] slirp: check sscanf result when emulating ident +Date: Wed, 24 Jul 2019 15:53:34 +0100 +Subject: [PATCH 09/14] slirp: check sscanf result when emulating ident MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RH-Author: Philippe Mathieu-Daudé -Message-id: <20190708155031.7778-2-philmd@redhat.com> -Patchwork-id: 89431 -O-Subject: [RHEL-8.0.0 qemu-kvm PATCH 1/4] slirp: check sscanf result when emulating ident -Bugzilla: 1732324 +Message-id: <20190724155337.25303-2-philmd@redhat.com> +Patchwork-id: 89675 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v2 1/4] slirp: check sscanf result when emulating ident +Bugzilla: 1727642 RH-Acked-by: Stefan Hajnoczi RH-Acked-by: Marc-André Lureau -RH-Acked-by: Stefano Garzarella +RH-Acked-by: Thomas Huth From: William Bowling diff --git a/SOURCES/kvm-slirp-don-t-manipulate-so_rcv-in-tcp_emu.patch b/SOURCES/kvm-slirp-don-t-manipulate-so_rcv-in-tcp_emu.patch index c1dad3c..0ae23ce 100644 --- a/SOURCES/kvm-slirp-don-t-manipulate-so_rcv-in-tcp_emu.patch +++ b/SOURCES/kvm-slirp-don-t-manipulate-so_rcv-in-tcp_emu.patch @@ -1,19 +1,19 @@ -From a89949eb46b41533234c4dea0e5a011bc2e583ea Mon Sep 17 00:00:00 2001 +From e63645b8e4335e71721defc01db16db7cebe09b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= -Date: Mon, 8 Jul 2019 15:50:31 +0100 -Subject: [PATCH 4/7] slirp: don't manipulate so_rcv in tcp_emu() +Date: Wed, 24 Jul 2019 15:53:37 +0100 +Subject: [PATCH 12/14] slirp: don't manipulate so_rcv in tcp_emu() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RH-Author: Philippe Mathieu-Daudé -Message-id: <20190708155031.7778-5-philmd@redhat.com> -Patchwork-id: 89428 -O-Subject: [RHEL-8.0.0 qemu-kvm PATCH 4/4] slirp: don't manipulate so_rcv in tcp_emu() -Bugzilla: 1732324 +Message-id: <20190724155337.25303-5-philmd@redhat.com> +Patchwork-id: 89676 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v2 4/4] slirp: don't manipulate so_rcv in tcp_emu() +Bugzilla: 1727642 RH-Acked-by: Stefan Hajnoczi RH-Acked-by: Marc-André Lureau -RH-Acked-by: Stefano Garzarella +RH-Acked-by: Thomas Huth From: Marc-André Lureau diff --git a/SOURCES/kvm-slirp-ensure-there-is-enough-space-in-mbuf-to-null-t.patch b/SOURCES/kvm-slirp-ensure-there-is-enough-space-in-mbuf-to-null-t.patch index e3a828a..96e39d3 100644 --- a/SOURCES/kvm-slirp-ensure-there-is-enough-space-in-mbuf-to-null-t.patch +++ b/SOURCES/kvm-slirp-ensure-there-is-enough-space-in-mbuf-to-null-t.patch @@ -1,20 +1,20 @@ -From 3bcddec301bcc3c251b4aab0446427de5fe35c57 Mon Sep 17 00:00:00 2001 +From ad30988fde29143951447e7f973918eaa09c448c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= -Date: Mon, 8 Jul 2019 15:50:30 +0100 -Subject: [PATCH 3/7] slirp: ensure there is enough space in mbuf to +Date: Wed, 24 Jul 2019 15:53:36 +0100 +Subject: [PATCH 11/14] slirp: ensure there is enough space in mbuf to null-terminate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RH-Author: Philippe Mathieu-Daudé -Message-id: <20190708155031.7778-4-philmd@redhat.com> -Patchwork-id: 89430 -O-Subject: [RHEL-8.0.0 qemu-kvm PATCH 3/4] slirp: ensure there is enough space in mbuf to null-terminate -Bugzilla: 1732324 +Message-id: <20190724155337.25303-4-philmd@redhat.com> +Patchwork-id: 89678 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v2 3/4] slirp: ensure there is enough space in mbuf to null-terminate +Bugzilla: 1727642 RH-Acked-by: Stefan Hajnoczi RH-Acked-by: Marc-André Lureau -RH-Acked-by: Stefano Garzarella +RH-Acked-by: Thomas Huth From: Marc-André Lureau @@ -26,8 +26,11 @@ Signed-off-by: Marc-André Lureau (cherry picked from libslirp commit 306fef58b54d793ba4b259728c21322765bda917) + [ MA - backported with style conflicts fixes ] Signed-off-by: Marc-André Lureau +Signed-off-by: Miroslav Rezanina +(cherry picked from commit e80c12dfdbde349dcd225771a4801b47be0b3b5f) Signed-off-by: Philippe Mathieu-Daudé Signed-off-by: Danilo C. L. de Paula diff --git a/SOURCES/kvm-slirp-fix-big-little-endian-conversion-in-ident-prot.patch b/SOURCES/kvm-slirp-fix-big-little-endian-conversion-in-ident-prot.patch index cf0c398..38c4c71 100644 --- a/SOURCES/kvm-slirp-fix-big-little-endian-conversion-in-ident-prot.patch +++ b/SOURCES/kvm-slirp-fix-big-little-endian-conversion-in-ident-prot.patch @@ -1,19 +1,20 @@ -From 9ab58e678a85d9f7ec27c2a20ff10c17aa77f9e2 Mon Sep 17 00:00:00 2001 +From f4157e1c90e8986d95a57bf00cc8c0e297869c35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= -Date: Mon, 8 Jul 2019 15:50:29 +0100 -Subject: [PATCH 2/7] slirp: fix big/little endian conversion in ident protocol +Date: Wed, 24 Jul 2019 15:53:35 +0100 +Subject: [PATCH 10/14] slirp: fix big/little endian conversion in ident + protocol MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RH-Author: Philippe Mathieu-Daudé -Message-id: <20190708155031.7778-3-philmd@redhat.com> -Patchwork-id: 89427 -O-Subject: [RHEL-8.0.0 qemu-kvm PATCH 2/4] slirp: fix big/little endian conversion in ident protocol -Bugzilla: 1732324 +Message-id: <20190724155337.25303-3-philmd@redhat.com> +Patchwork-id: 89674 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v2 2/4] slirp: fix big/little endian conversion in ident protocol +Bugzilla: 1727642 RH-Acked-by: Stefan Hajnoczi RH-Acked-by: Marc-André Lureau -RH-Acked-by: Stefano Garzarella +RH-Acked-by: Thomas Huth From: Samuel Thibault diff --git a/SOURCES/kvm-spapr-Fix-ibm-max-associativity-domains-property-num.patch b/SOURCES/kvm-spapr-Fix-ibm-max-associativity-domains-property-num.patch new file mode 100644 index 0000000..b4b3ed9 --- /dev/null +++ b/SOURCES/kvm-spapr-Fix-ibm-max-associativity-domains-property-num.patch @@ -0,0 +1,137 @@ +From 4da5757f8ad715c203e2ef9320c49432e8259ee8 Mon Sep 17 00:00:00 2001 +From: David Gibson +Date: Thu, 30 May 2019 04:37:23 +0100 +Subject: [PATCH 2/8] spapr: Fix ibm, max-associativity-domains property number + of nodes + +RH-Author: David Gibson +Message-id: <20190530043728.32575-2-dgibson@redhat.com> +Patchwork-id: 88418 +O-Subject: [RHEL-8.1 qemu-kvm PATCH 1/6] spapr: Fix ibm, max-associativity-domains property number of nodes +Bugzilla: 1710662 +RH-Acked-by: Laurent Vivier +RH-Acked-by: Auger Eric +RH-Acked-by: Cornelia Huck + +From: Serhii Popovych + +Laurent Vivier reported off by one with maximum number of NUMA nodes +provided by qemu-kvm being less by one than required according to +description of "ibm,max-associativity-domains" property in LoPAPR. + +It appears that I incorrectly treated LoPAPR description of this +property assuming it provides last valid domain (NUMA node here) +instead of maximum number of domains. + + ### Before hot-add + + (qemu) info numa + 3 nodes + node 0 cpus: 0 + node 0 size: 0 MB + node 0 plugged: 0 MB + node 1 cpus: + node 1 size: 1024 MB + node 1 plugged: 0 MB + node 2 cpus: + node 2 size: 0 MB + node 2 plugged: 0 MB + + $ numactl -H + available: 2 nodes (0-1) + node 0 cpus: 0 + node 0 size: 0 MB + node 0 free: 0 MB + node 1 cpus: + node 1 size: 999 MB + node 1 free: 658 MB + node distances: + node 0 1 + 0: 10 40 + 1: 40 10 + + ### Hot-add + + (qemu) object_add memory-backend-ram,id=mem0,size=1G + (qemu) device_add pc-dimm,id=dimm1,memdev=mem0,node=2 + (qemu) [ 87.704898] pseries-hotplug-mem: Attempting to hot-add 4 ... + + [ 87.705128] lpar: Attempting to resize HPT to shift 21 + ... + + ### After hot-add + + (qemu) info numa + 3 nodes + node 0 cpus: 0 + node 0 size: 0 MB + node 0 plugged: 0 MB + node 1 cpus: + node 1 size: 1024 MB + node 1 plugged: 0 MB + node 2 cpus: + node 2 size: 1024 MB + node 2 plugged: 1024 MB + + $ numactl -H + available: 2 nodes (0-1) + ^^^^^^^^^^^^^^^^^^^^^^^^ + Still only two nodes (and memory hot-added to node 0 below) + node 0 cpus: 0 + node 0 size: 1024 MB + node 0 free: 1021 MB + node 1 cpus: + node 1 size: 999 MB + node 1 free: 658 MB + node distances: + node 0 1 + 0: 10 40 + 1: 40 10 + +After fix applied numactl(8) reports 3 nodes available and memory +plugged into node 2 as expected. + +>From David Gibson: +------------------ + Qemu makes a distinction between "non NUMA" (nb_numa_nodes == 0) and + "NUMA with one node" (nb_numa_nodes == 1). But from a PAPR guests's + point of view these are equivalent. I don't want to present two + different cases to the guest when we don't need to, so even though the + guest can handle it, I'd prefer we put a '1' here for both the + nb_numa_nodes == 0 and nb_numa_nodes == 1 case. + +This consolidates everything discussed previously on mailing list. + +Fixes: da9f80fbad21 ("spapr: Add ibm,max-associativity-domains property") +Reported-by: Laurent Vivier +Signed-off-by: Serhii Popovych + +Signed-off-by: David Gibson +Reviewed-by: Greg Kurz +Reviewed-by: Laurent Vivier +(cherry picked from commit 3908a24fcb83913079d315de0ca6d598e8616dbb) + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1710662 + +Signed-off-by: David Gibson +Signed-off-by: Danilo C. L. de Paula +--- + hw/ppc/spapr.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c +index ea72782..b57c0be 100644 +--- a/hw/ppc/spapr.c ++++ b/hw/ppc/spapr.c +@@ -915,7 +915,7 @@ static void spapr_dt_rtas(sPAPRMachineState *spapr, void *fdt) + cpu_to_be32(0), + cpu_to_be32(0), + cpu_to_be32(0), +- cpu_to_be32(nb_numa_nodes ? nb_numa_nodes - 1 : 0), ++ cpu_to_be32(nb_numa_nodes ? nb_numa_nodes : 1), + }; + + _FDT(rtas = fdt_add_subnode(fdt, 0, "rtas")); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-spapr-Support-NVIDIA-V100-GPU-with-NVLink2.patch b/SOURCES/kvm-spapr-Support-NVIDIA-V100-GPU-with-NVLink2.patch new file mode 100644 index 0000000..ab876bf --- /dev/null +++ b/SOURCES/kvm-spapr-Support-NVIDIA-V100-GPU-with-NVLink2.patch @@ -0,0 +1,1028 @@ +From 5dc7b745eb04e799b95e7e8d17868970a65621df Mon Sep 17 00:00:00 2001 +From: David Gibson +Date: Thu, 30 May 2019 04:37:28 +0100 +Subject: [PATCH 7/8] spapr: Support NVIDIA V100 GPU with NVLink2 + +RH-Author: David Gibson +Message-id: <20190530043728.32575-7-dgibson@redhat.com> +Patchwork-id: 88423 +O-Subject: [RHEL-8.1 qemu-kvm PATCH 6/6] spapr: Support NVIDIA V100 GPU with NVLink2 +Bugzilla: 1710662 +RH-Acked-by: Laurent Vivier +RH-Acked-by: Auger Eric +RH-Acked-by: Cornelia Huck + +From: Alexey Kardashevskiy + +NVIDIA V100 GPUs have on-board RAM which is mapped into the host memory +space and accessible as normal RAM via an NVLink bus. The VFIO-PCI driver +implements special regions for such GPUs and emulates an NVLink bridge. +NVLink2-enabled POWER9 CPUs also provide address translation services +which includes an ATS shootdown (ATSD) register exported via the NVLink +bridge device. + +This adds a quirk to VFIO to map the GPU memory and create an MR; +the new MR is stored in a PCI device as a QOM link. The sPAPR PCI uses +this to get the MR and map it to the system address space. +Another quirk does the same for ATSD. + +This adds additional steps to sPAPR PHB setup: + +1. Search for specific GPUs and NPUs, collect findings in +sPAPRPHBState::nvgpus, manage system address space mappings; + +2. Add device-specific properties such as "ibm,npu", "ibm,gpu", +"memory-block", "link-speed" to advertise the NVLink2 function to +the guest; + +3. Add "mmio-atsd" to vPHB to advertise the ATSD capability; + +4. Add new memory blocks (with extra "linux,memory-usable" to prevent +the guest OS from accessing the new memory until it is onlined) and +npuphb# nodes representing an NPU unit for every vPHB as the GPU driver +uses it for link discovery. + +This allocates space for GPU RAM and ATSD like we do for MMIOs by +adding 2 new parameters to the phb_placement() hook. Older machine types +set these to zero. + +This puts new memory nodes in a separate NUMA node to as the GPU RAM +needs to be configured equally distant from any other node in the system. +Unlike the host setup which assigns numa ids from 255 downwards, this +adds new NUMA nodes after the user configures nodes or from 1 if none +were configured. + +This adds requirement similar to EEH - one IOMMU group per vPHB. +The reason for this is that ATSD registers belong to a physical NPU +so they cannot invalidate translations on GPUs attached to another NPU. +It is guaranteed by the host platform as it does not mix NVLink bridges +or GPUs from different NPU in the same IOMMU group. If more than one +IOMMU group is detected on a vPHB, this disables ATSD support for that +vPHB and prints a warning. + +Signed-off-by: Alexey Kardashevskiy +[aw: for vfio portions] +Acked-by: Alex Williamson +Message-Id: <20190312082103.130561-1-aik@ozlabs.ru> +Signed-off-by: David Gibson +(cherry picked from commit ec132efaa81f09861a3bd6afad94827e74543b3f) + +Signed-off-by: Danilo C. L. de Paula + +Conflicts: + hw/ppc/spapr.c + hw/ppc/spapr_pci.c + hw/vfio/trace-events + include/hw/pci-host/spapr.h + include/hw/ppc/spapr.h + +Conflicts come for several reasons: + 1) Some contextual conflicts + 2) Downstream tree does not have PHB hotplug, so upstream changes to + that code need to be dropped, we also need to adapt some hunks to + apply to the code as it existed before PHB hotplug was added + 3) Upstream had a mass renaming of spapr types to give more + consistent CamelCasing. We don't have that change downstream, so + we need to adjust accordingly. + 4) We add an explicit include of qemu/units.h, since it's not indirectly + included downstream (and it's messy to backport the patch which adds + that) + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1710662 + +Signed-off-by: David Gibson +Signed-off-by: Danilo C. L. de Paula +--- + hw/ppc/Makefile.objs | 2 +- + hw/ppc/spapr.c | 31 ++- + hw/ppc/spapr_pci.c | 21 ++- + hw/ppc/spapr_pci_nvlink2.c | 450 ++++++++++++++++++++++++++++++++++++++++++++ + hw/vfio/pci-quirks.c | 131 +++++++++++++ + hw/vfio/pci.c | 14 ++ + hw/vfio/pci.h | 2 + + hw/vfio/trace-events | 4 + + include/hw/pci-host/spapr.h | 46 +++++ + include/hw/ppc/spapr.h | 5 +- + 10 files changed, 697 insertions(+), 9 deletions(-) + create mode 100644 hw/ppc/spapr_pci_nvlink2.c + +diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs +index a46a989..d07e999 100644 +--- a/hw/ppc/Makefile.objs ++++ b/hw/ppc/Makefile.objs +@@ -8,7 +8,7 @@ obj-$(CONFIG_PSERIES) += spapr_cpu_core.o spapr_ovec.o + # IBM PowerNV + obj-$(CONFIG_POWERNV) += pnv.o pnv_xscom.o pnv_core.o pnv_lpc.o pnv_psi.o pnv_occ.o pnv_bmc.o + ifeq ($(CONFIG_PCI)$(CONFIG_PSERIES)$(CONFIG_LINUX), yyy) +-obj-y += spapr_pci_vfio.o ++obj-y += spapr_pci_vfio.o spapr_pci_nvlink2.o + endif + obj-$(CONFIG_PSERIES) += spapr_rtas_ddw.o + # PowerPC 4xx boards +diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c +index b57c0be..c72aad1 100644 +--- a/hw/ppc/spapr.c ++++ b/hw/ppc/spapr.c +@@ -910,12 +910,13 @@ static void spapr_dt_rtas(sPAPRMachineState *spapr, void *fdt) + 0, cpu_to_be32(SPAPR_MEMORY_BLOCK_SIZE), + cpu_to_be32(max_cpus / smp_threads), + }; ++ uint32_t maxdomain = cpu_to_be32(spapr->gpu_numa_id > 1 ? 1 : 0); + uint32_t maxdomains[] = { + cpu_to_be32(4), +- cpu_to_be32(0), +- cpu_to_be32(0), +- cpu_to_be32(0), +- cpu_to_be32(nb_numa_nodes ? nb_numa_nodes : 1), ++ maxdomain, ++ maxdomain, ++ maxdomain, ++ cpu_to_be32(spapr->gpu_numa_id), + }; + + _FDT(rtas = fdt_add_subnode(fdt, 0, "rtas")); +@@ -1515,6 +1516,16 @@ static void spapr_machine_reset(void) + ppc_set_compat(first_ppc_cpu, spapr->max_compat_pvr, &error_fatal); + } + ++ /* ++ * NVLink2-connected GPU RAM needs to be placed on a separate NUMA node. ++ * We assign a new numa ID per GPU in spapr_pci_collect_nvgpu() which is ++ * called from vPHB reset handler so we initialize the counter here. ++ * If no NUMA is configured from the QEMU side, we start from 1 as GPU RAM ++ * must be equally distant from any other node. ++ * The final value of spapr->gpu_numa_id is going to be written to ++ * max-associativity-domains in spapr_build_fdt(). ++ */ ++ spapr->gpu_numa_id = MAX(1, nb_numa_nodes); + qemu_devices_reset(); + + /* DRC reset may cause a device to be unplugged. This will cause troubles +@@ -3601,7 +3612,8 @@ static const CPUArchIdList *spapr_possible_cpu_arch_ids(MachineState *machine) + static void spapr_phb_placement(sPAPRMachineState *spapr, uint32_t index, + uint64_t *buid, hwaddr *pio, + hwaddr *mmio32, hwaddr *mmio64, +- unsigned n_dma, uint32_t *liobns, Error **errp) ++ unsigned n_dma, uint32_t *liobns, ++ hwaddr *nv2gpa, hwaddr *nv2atsd, Error **errp) + { + /* + * New-style PHB window placement. +@@ -3648,6 +3660,9 @@ static void spapr_phb_placement(sPAPRMachineState *spapr, uint32_t index, + *pio = SPAPR_PCI_BASE + index * SPAPR_PCI_IO_WIN_SIZE; + *mmio32 = SPAPR_PCI_BASE + (index + 1) * SPAPR_PCI_MEM32_WIN_SIZE; + *mmio64 = SPAPR_PCI_BASE + (index + 1) * SPAPR_PCI_MEM64_WIN_SIZE; ++ ++ *nv2gpa = SPAPR_PCI_NV2RAM64_WIN_BASE + index * SPAPR_PCI_NV2RAM64_WIN_SIZE; ++ *nv2atsd = SPAPR_PCI_NV2ATSD_WIN_BASE + index * SPAPR_PCI_NV2ATSD_WIN_SIZE; + } + + static ICSState *spapr_ics_get(XICSFabric *dev, int irq) +@@ -4133,7 +4148,8 @@ DEFINE_SPAPR_MACHINE(2_8, "2.8", false); + static void phb_placement_2_7(sPAPRMachineState *spapr, uint32_t index, + uint64_t *buid, hwaddr *pio, + hwaddr *mmio32, hwaddr *mmio64, +- unsigned n_dma, uint32_t *liobns, Error **errp) ++ unsigned n_dma, uint32_t *liobns, ++ hwaddr *nv2gpa, hwaddr *nv2atsd, Error **errp) + { + /* Legacy PHB placement for pseries-2.7 and earlier machine types */ + const uint64_t base_buid = 0x800000020000000ULL; +@@ -4177,6 +4193,9 @@ static void phb_placement_2_7(sPAPRMachineState *spapr, uint32_t index, + * fallback behaviour of automatically splitting a large "32-bit" + * window into contiguous 32-bit and 64-bit windows + */ ++ ++ *nv2gpa = 0; ++ *nv2atsd = 0; + } + + #if 0 /* Disabled for Red Hat Enterprise Linux */ +diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c +index f936ce6..d82f957 100644 +--- a/hw/ppc/spapr_pci.c ++++ b/hw/ppc/spapr_pci.c +@@ -1326,6 +1326,8 @@ static void spapr_populate_pci_child_dt(PCIDevice *dev, void *fdt, int offset, + if (sphb->pcie_ecs && pci_is_express(dev)) { + _FDT(fdt_setprop_cell(fdt, offset, "ibm,pci-config-space-type", 0x1)); + } ++ ++ spapr_phb_nvgpu_populate_pcidev_dt(dev, fdt, offset, sphb); + } + + /* create OF node for pci device and required OF DT properties */ +@@ -1559,7 +1561,9 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp) + smc->phb_placement(spapr, sphb->index, + &sphb->buid, &sphb->io_win_addr, + &sphb->mem_win_addr, &sphb->mem64_win_addr, +- windows_supported, sphb->dma_liobn, &local_err); ++ windows_supported, sphb->dma_liobn, ++ &sphb->nv2_gpa_win_addr, &sphb->nv2_atsd_win_addr, ++ &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; +@@ -1764,8 +1768,14 @@ void spapr_phb_dma_reset(sPAPRPHBState *sphb) + static void spapr_phb_reset(DeviceState *qdev) + { + sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(qdev); ++ Error *errp = NULL; + + spapr_phb_dma_reset(sphb); ++ spapr_phb_nvgpu_free(sphb); ++ spapr_phb_nvgpu_setup(sphb, &errp); ++ if (errp) { ++ error_report_err(errp); ++ } + + /* Reset the IOMMU state */ + object_child_foreach(OBJECT(qdev), spapr_phb_children_reset, NULL); +@@ -1798,6 +1808,8 @@ static Property spapr_phb_properties[] = { + pre_2_8_migration, false), + DEFINE_PROP_BOOL("pcie-extended-configuration-space", sPAPRPHBState, + pcie_ecs, true), ++ DEFINE_PROP_UINT64("gpa", sPAPRPHBState, nv2_gpa_win_addr, 0), ++ DEFINE_PROP_UINT64("atsd", sPAPRPHBState, nv2_atsd_win_addr, 0), + DEFINE_PROP_END_OF_LIST(), + }; + +@@ -2089,6 +2101,7 @@ int spapr_populate_pci_dt(sPAPRPHBState *phb, + sPAPRTCETable *tcet; + PCIBus *bus = PCI_HOST_BRIDGE(phb)->bus; + sPAPRFDT s_fdt; ++ Error *errp = NULL; + + /* Start populating the FDT */ + nodename = g_strdup_printf("pci@%" PRIx64, phb->buid); +@@ -2170,6 +2183,12 @@ int spapr_populate_pci_dt(sPAPRPHBState *phb, + return ret; + } + ++ spapr_phb_nvgpu_populate_dt(phb, fdt, bus_off, &errp); ++ if (errp) { ++ error_report_err(errp); ++ } ++ spapr_phb_nvgpu_ram_populate_dt(phb, fdt); ++ + return 0; + } + +diff --git a/hw/ppc/spapr_pci_nvlink2.c b/hw/ppc/spapr_pci_nvlink2.c +new file mode 100644 +index 0000000..60b14d8 +--- /dev/null ++++ b/hw/ppc/spapr_pci_nvlink2.c +@@ -0,0 +1,450 @@ ++/* ++ * QEMU sPAPR PCI for NVLink2 pass through ++ * ++ * Copyright (c) 2019 Alexey Kardashevskiy, IBM Corporation. ++ * ++ * 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 "qapi/error.h" ++#include "qemu-common.h" ++#include "hw/pci/pci.h" ++#include "hw/pci-host/spapr.h" ++#include "qemu/error-report.h" ++#include "hw/ppc/fdt.h" ++#include "hw/pci/pci_bridge.h" ++ ++#define PHANDLE_PCIDEV(phb, pdev) (0x12000000 | \ ++ (((phb)->index) << 16) | ((pdev)->devfn)) ++#define PHANDLE_GPURAM(phb, n) (0x110000FF | ((n) << 8) | \ ++ (((phb)->index) << 16)) ++#define PHANDLE_NVLINK(phb, gn, nn) (0x00130000 | (((phb)->index) << 8) | \ ++ ((gn) << 4) | (nn)) ++ ++#define SPAPR_GPU_NUMA_ID (cpu_to_be32(1)) ++ ++struct spapr_phb_pci_nvgpu_config { ++ uint64_t nv2_ram_current; ++ uint64_t nv2_atsd_current; ++ int num; /* number of non empty (i.e. tgt!=0) entries in slots[] */ ++ struct spapr_phb_pci_nvgpu_slot { ++ uint64_t tgt; ++ uint64_t gpa; ++ unsigned numa_id; ++ PCIDevice *gpdev; ++ int linknum; ++ struct { ++ uint64_t atsd_gpa; ++ PCIDevice *npdev; ++ uint32_t link_speed; ++ } links[NVGPU_MAX_LINKS]; ++ } slots[NVGPU_MAX_NUM]; ++ Error *errp; ++}; ++ ++static struct spapr_phb_pci_nvgpu_slot * ++spapr_nvgpu_get_slot(struct spapr_phb_pci_nvgpu_config *nvgpus, uint64_t tgt) ++{ ++ int i; ++ ++ /* Search for partially collected "slot" */ ++ for (i = 0; i < nvgpus->num; ++i) { ++ if (nvgpus->slots[i].tgt == tgt) { ++ return &nvgpus->slots[i]; ++ } ++ } ++ ++ if (nvgpus->num == ARRAY_SIZE(nvgpus->slots)) { ++ return NULL; ++ } ++ ++ i = nvgpus->num; ++ nvgpus->slots[i].tgt = tgt; ++ ++nvgpus->num; ++ ++ return &nvgpus->slots[i]; ++} ++ ++static void spapr_pci_collect_nvgpu(struct spapr_phb_pci_nvgpu_config *nvgpus, ++ PCIDevice *pdev, uint64_t tgt, ++ MemoryRegion *mr, Error **errp) ++{ ++ MachineState *machine = MACHINE(qdev_get_machine()); ++ sPAPRMachineState *spapr = SPAPR_MACHINE(machine); ++ struct spapr_phb_pci_nvgpu_slot *nvslot = spapr_nvgpu_get_slot(nvgpus, tgt); ++ ++ if (!nvslot) { ++ error_setg(errp, "Found too many GPUs per vPHB"); ++ return; ++ } ++ g_assert(!nvslot->gpdev); ++ nvslot->gpdev = pdev; ++ ++ nvslot->gpa = nvgpus->nv2_ram_current; ++ nvgpus->nv2_ram_current += memory_region_size(mr); ++ nvslot->numa_id = spapr->gpu_numa_id; ++ ++spapr->gpu_numa_id; ++} ++ ++static void spapr_pci_collect_nvnpu(struct spapr_phb_pci_nvgpu_config *nvgpus, ++ PCIDevice *pdev, uint64_t tgt, ++ MemoryRegion *mr, Error **errp) ++{ ++ struct spapr_phb_pci_nvgpu_slot *nvslot = spapr_nvgpu_get_slot(nvgpus, tgt); ++ int j; ++ ++ if (!nvslot) { ++ error_setg(errp, "Found too many NVLink bridges per vPHB"); ++ return; ++ } ++ ++ j = nvslot->linknum; ++ if (j == ARRAY_SIZE(nvslot->links)) { ++ error_setg(errp, "Found too many NVLink bridges per GPU"); ++ return; ++ } ++ ++nvslot->linknum; ++ ++ g_assert(!nvslot->links[j].npdev); ++ nvslot->links[j].npdev = pdev; ++ nvslot->links[j].atsd_gpa = nvgpus->nv2_atsd_current; ++ nvgpus->nv2_atsd_current += memory_region_size(mr); ++ nvslot->links[j].link_speed = ++ object_property_get_uint(OBJECT(pdev), "nvlink2-link-speed", NULL); ++} ++ ++static void spapr_phb_pci_collect_nvgpu(PCIBus *bus, PCIDevice *pdev, ++ void *opaque) ++{ ++ PCIBus *sec_bus; ++ Object *po = OBJECT(pdev); ++ uint64_t tgt = object_property_get_uint(po, "nvlink2-tgt", NULL); ++ ++ if (tgt) { ++ Error *local_err = NULL; ++ struct spapr_phb_pci_nvgpu_config *nvgpus = opaque; ++ Object *mr_gpu = object_property_get_link(po, "nvlink2-mr[0]", NULL); ++ Object *mr_npu = object_property_get_link(po, "nvlink2-atsd-mr[0]", ++ NULL); ++ ++ g_assert(mr_gpu || mr_npu); ++ if (mr_gpu) { ++ spapr_pci_collect_nvgpu(nvgpus, pdev, tgt, MEMORY_REGION(mr_gpu), ++ &local_err); ++ } else { ++ spapr_pci_collect_nvnpu(nvgpus, pdev, tgt, MEMORY_REGION(mr_npu), ++ &local_err); ++ } ++ error_propagate(&nvgpus->errp, local_err); ++ } ++ if ((pci_default_read_config(pdev, PCI_HEADER_TYPE, 1) != ++ PCI_HEADER_TYPE_BRIDGE)) { ++ return; ++ } ++ ++ sec_bus = pci_bridge_get_sec_bus(PCI_BRIDGE(pdev)); ++ if (!sec_bus) { ++ return; ++ } ++ ++ pci_for_each_device(sec_bus, pci_bus_num(sec_bus), ++ spapr_phb_pci_collect_nvgpu, opaque); ++} ++ ++void spapr_phb_nvgpu_setup(sPAPRPHBState *sphb, Error **errp) ++{ ++ int i, j, valid_gpu_num; ++ PCIBus *bus; ++ ++ /* Search for GPUs and NPUs */ ++ if (!sphb->nv2_gpa_win_addr || !sphb->nv2_atsd_win_addr) { ++ return; ++ } ++ ++ sphb->nvgpus = g_new0(struct spapr_phb_pci_nvgpu_config, 1); ++ sphb->nvgpus->nv2_ram_current = sphb->nv2_gpa_win_addr; ++ sphb->nvgpus->nv2_atsd_current = sphb->nv2_atsd_win_addr; ++ ++ bus = PCI_HOST_BRIDGE(sphb)->bus; ++ pci_for_each_device(bus, pci_bus_num(bus), ++ spapr_phb_pci_collect_nvgpu, sphb->nvgpus); ++ ++ if (sphb->nvgpus->errp) { ++ error_propagate(errp, sphb->nvgpus->errp); ++ sphb->nvgpus->errp = NULL; ++ goto cleanup_exit; ++ } ++ ++ /* Add found GPU RAM and ATSD MRs if found */ ++ for (i = 0, valid_gpu_num = 0; i < sphb->nvgpus->num; ++i) { ++ Object *nvmrobj; ++ struct spapr_phb_pci_nvgpu_slot *nvslot = &sphb->nvgpus->slots[i]; ++ ++ if (!nvslot->gpdev) { ++ continue; ++ } ++ nvmrobj = object_property_get_link(OBJECT(nvslot->gpdev), ++ "nvlink2-mr[0]", NULL); ++ /* ATSD is pointless without GPU RAM MR so skip those */ ++ if (!nvmrobj) { ++ continue; ++ } ++ ++ ++valid_gpu_num; ++ memory_region_add_subregion(get_system_memory(), nvslot->gpa, ++ MEMORY_REGION(nvmrobj)); ++ ++ for (j = 0; j < nvslot->linknum; ++j) { ++ Object *atsdmrobj; ++ ++ atsdmrobj = object_property_get_link(OBJECT(nvslot->links[j].npdev), ++ "nvlink2-atsd-mr[0]", NULL); ++ if (!atsdmrobj) { ++ continue; ++ } ++ memory_region_add_subregion(get_system_memory(), ++ nvslot->links[j].atsd_gpa, ++ MEMORY_REGION(atsdmrobj)); ++ } ++ } ++ ++ if (valid_gpu_num) { ++ return; ++ } ++ /* We did not find any interesting GPU */ ++cleanup_exit: ++ g_free(sphb->nvgpus); ++ sphb->nvgpus = NULL; ++} ++ ++void spapr_phb_nvgpu_free(sPAPRPHBState *sphb) ++{ ++ int i, j; ++ ++ if (!sphb->nvgpus) { ++ return; ++ } ++ ++ for (i = 0; i < sphb->nvgpus->num; ++i) { ++ struct spapr_phb_pci_nvgpu_slot *nvslot = &sphb->nvgpus->slots[i]; ++ Object *nv_mrobj = object_property_get_link(OBJECT(nvslot->gpdev), ++ "nvlink2-mr[0]", NULL); ++ ++ if (nv_mrobj) { ++ memory_region_del_subregion(get_system_memory(), ++ MEMORY_REGION(nv_mrobj)); ++ } ++ for (j = 0; j < nvslot->linknum; ++j) { ++ PCIDevice *npdev = nvslot->links[j].npdev; ++ Object *atsd_mrobj; ++ atsd_mrobj = object_property_get_link(OBJECT(npdev), ++ "nvlink2-atsd-mr[0]", NULL); ++ if (atsd_mrobj) { ++ memory_region_del_subregion(get_system_memory(), ++ MEMORY_REGION(atsd_mrobj)); ++ } ++ } ++ } ++ g_free(sphb->nvgpus); ++ sphb->nvgpus = NULL; ++} ++ ++void spapr_phb_nvgpu_populate_dt(sPAPRPHBState *sphb, void *fdt, int bus_off, ++ Error **errp) ++{ ++ int i, j, atsdnum = 0; ++ uint64_t atsd[8]; /* The existing limitation of known guests */ ++ ++ if (!sphb->nvgpus) { ++ return; ++ } ++ ++ for (i = 0; (i < sphb->nvgpus->num) && (atsdnum < ARRAY_SIZE(atsd)); ++i) { ++ struct spapr_phb_pci_nvgpu_slot *nvslot = &sphb->nvgpus->slots[i]; ++ ++ if (!nvslot->gpdev) { ++ continue; ++ } ++ for (j = 0; j < nvslot->linknum; ++j) { ++ if (!nvslot->links[j].atsd_gpa) { ++ continue; ++ } ++ ++ if (atsdnum == ARRAY_SIZE(atsd)) { ++ error_report("Only %"PRIuPTR" ATSD registers supported", ++ ARRAY_SIZE(atsd)); ++ break; ++ } ++ atsd[atsdnum] = cpu_to_be64(nvslot->links[j].atsd_gpa); ++ ++atsdnum; ++ } ++ } ++ ++ if (!atsdnum) { ++ error_setg(errp, "No ATSD registers found"); ++ return; ++ } ++ ++ if (!spapr_phb_eeh_available(sphb)) { ++ /* ++ * ibm,mmio-atsd contains ATSD registers; these belong to an NPU PHB ++ * which we do not emulate as a separate device. Instead we put ++ * ibm,mmio-atsd to the vPHB with GPU and make sure that we do not ++ * put GPUs from different IOMMU groups to the same vPHB to ensure ++ * that the guest will use ATSDs from the corresponding NPU. ++ */ ++ error_setg(errp, "ATSD requires separate vPHB per GPU IOMMU group"); ++ return; ++ } ++ ++ _FDT((fdt_setprop(fdt, bus_off, "ibm,mmio-atsd", atsd, ++ atsdnum * sizeof(atsd[0])))); ++} ++ ++void spapr_phb_nvgpu_ram_populate_dt(sPAPRPHBState *sphb, void *fdt) ++{ ++ int i, j, linkidx, npuoff; ++ char *npuname; ++ ++ if (!sphb->nvgpus) { ++ return; ++ } ++ ++ npuname = g_strdup_printf("npuphb%d", sphb->index); ++ npuoff = fdt_add_subnode(fdt, 0, npuname); ++ _FDT(npuoff); ++ _FDT(fdt_setprop_cell(fdt, npuoff, "#address-cells", 1)); ++ _FDT(fdt_setprop_cell(fdt, npuoff, "#size-cells", 0)); ++ /* Advertise NPU as POWER9 so the guest can enable NPU2 contexts */ ++ _FDT((fdt_setprop_string(fdt, npuoff, "compatible", "ibm,power9-npu"))); ++ g_free(npuname); ++ ++ for (i = 0, linkidx = 0; i < sphb->nvgpus->num; ++i) { ++ for (j = 0; j < sphb->nvgpus->slots[i].linknum; ++j) { ++ char *linkname = g_strdup_printf("link@%d", linkidx); ++ int off = fdt_add_subnode(fdt, npuoff, linkname); ++ ++ _FDT(off); ++ /* _FDT((fdt_setprop_cell(fdt, off, "reg", linkidx))); */ ++ _FDT((fdt_setprop_string(fdt, off, "compatible", ++ "ibm,npu-link"))); ++ _FDT((fdt_setprop_cell(fdt, off, "phandle", ++ PHANDLE_NVLINK(sphb, i, j)))); ++ _FDT((fdt_setprop_cell(fdt, off, "ibm,npu-link-index", linkidx))); ++ g_free(linkname); ++ ++linkidx; ++ } ++ } ++ ++ /* Add memory nodes for GPU RAM and mark them unusable */ ++ for (i = 0; i < sphb->nvgpus->num; ++i) { ++ struct spapr_phb_pci_nvgpu_slot *nvslot = &sphb->nvgpus->slots[i]; ++ Object *nv_mrobj = object_property_get_link(OBJECT(nvslot->gpdev), ++ "nvlink2-mr[0]", NULL); ++ uint32_t associativity[] = { ++ cpu_to_be32(0x4), ++ SPAPR_GPU_NUMA_ID, ++ SPAPR_GPU_NUMA_ID, ++ SPAPR_GPU_NUMA_ID, ++ cpu_to_be32(nvslot->numa_id) ++ }; ++ uint64_t size = object_property_get_uint(nv_mrobj, "size", NULL); ++ uint64_t mem_reg[2] = { cpu_to_be64(nvslot->gpa), cpu_to_be64(size) }; ++ char *mem_name = g_strdup_printf("memory@%"PRIx64, nvslot->gpa); ++ int off = fdt_add_subnode(fdt, 0, mem_name); ++ ++ _FDT(off); ++ _FDT((fdt_setprop_string(fdt, off, "device_type", "memory"))); ++ _FDT((fdt_setprop(fdt, off, "reg", mem_reg, sizeof(mem_reg)))); ++ _FDT((fdt_setprop(fdt, off, "ibm,associativity", associativity, ++ sizeof(associativity)))); ++ ++ _FDT((fdt_setprop_string(fdt, off, "compatible", ++ "ibm,coherent-device-memory"))); ++ ++ mem_reg[1] = cpu_to_be64(0); ++ _FDT((fdt_setprop(fdt, off, "linux,usable-memory", mem_reg, ++ sizeof(mem_reg)))); ++ _FDT((fdt_setprop_cell(fdt, off, "phandle", ++ PHANDLE_GPURAM(sphb, i)))); ++ g_free(mem_name); ++ } ++ ++} ++ ++void spapr_phb_nvgpu_populate_pcidev_dt(PCIDevice *dev, void *fdt, int offset, ++ sPAPRPHBState *sphb) ++{ ++ int i, j; ++ ++ if (!sphb->nvgpus) { ++ return; ++ } ++ ++ for (i = 0; i < sphb->nvgpus->num; ++i) { ++ struct spapr_phb_pci_nvgpu_slot *nvslot = &sphb->nvgpus->slots[i]; ++ ++ /* Skip "slot" without attached GPU */ ++ if (!nvslot->gpdev) { ++ continue; ++ } ++ if (dev == nvslot->gpdev) { ++ uint32_t npus[nvslot->linknum]; ++ ++ for (j = 0; j < nvslot->linknum; ++j) { ++ PCIDevice *npdev = nvslot->links[j].npdev; ++ ++ npus[j] = cpu_to_be32(PHANDLE_PCIDEV(sphb, npdev)); ++ } ++ _FDT(fdt_setprop(fdt, offset, "ibm,npu", npus, ++ j * sizeof(npus[0]))); ++ _FDT((fdt_setprop_cell(fdt, offset, "phandle", ++ PHANDLE_PCIDEV(sphb, dev)))); ++ continue; ++ } ++ ++ for (j = 0; j < nvslot->linknum; ++j) { ++ if (dev != nvslot->links[j].npdev) { ++ continue; ++ } ++ ++ _FDT((fdt_setprop_cell(fdt, offset, "phandle", ++ PHANDLE_PCIDEV(sphb, dev)))); ++ _FDT(fdt_setprop_cell(fdt, offset, "ibm,gpu", ++ PHANDLE_PCIDEV(sphb, nvslot->gpdev))); ++ _FDT((fdt_setprop_cell(fdt, offset, "ibm,nvlink", ++ PHANDLE_NVLINK(sphb, i, j)))); ++ /* ++ * If we ever want to emulate GPU RAM at the same location as on ++ * the host - here is the encoding GPA->TGT: ++ * ++ * gta = ((sphb->nv2_gpa >> 42) & 0x1) << 42; ++ * gta |= ((sphb->nv2_gpa >> 45) & 0x3) << 43; ++ * gta |= ((sphb->nv2_gpa >> 49) & 0x3) << 45; ++ * gta |= sphb->nv2_gpa & ((1UL << 43) - 1); ++ */ ++ _FDT(fdt_setprop_cell(fdt, offset, "memory-region", ++ PHANDLE_GPURAM(sphb, i))); ++ _FDT(fdt_setprop_u64(fdt, offset, "ibm,device-tgt-addr", ++ nvslot->tgt)); ++ _FDT(fdt_setprop_cell(fdt, offset, "ibm,nvlink-speed", ++ nvslot->links[j].link_speed)); ++ } ++ } ++} +diff --git a/hw/vfio/pci-quirks.c b/hw/vfio/pci-quirks.c +index 92457ed..1beedca 100644 +--- a/hw/vfio/pci-quirks.c ++++ b/hw/vfio/pci-quirks.c +@@ -1968,3 +1968,134 @@ int vfio_add_virt_caps(VFIOPCIDevice *vdev, Error **errp) + + return 0; + } ++ ++static void vfio_pci_nvlink2_get_tgt(Object *obj, Visitor *v, ++ const char *name, ++ void *opaque, Error **errp) ++{ ++ uint64_t tgt = (uintptr_t) opaque; ++ visit_type_uint64(v, name, &tgt, errp); ++} ++ ++static void vfio_pci_nvlink2_get_link_speed(Object *obj, Visitor *v, ++ const char *name, ++ void *opaque, Error **errp) ++{ ++ uint32_t link_speed = (uint32_t)(uintptr_t) opaque; ++ visit_type_uint32(v, name, &link_speed, errp); ++} ++ ++int vfio_pci_nvidia_v100_ram_init(VFIOPCIDevice *vdev, Error **errp) ++{ ++ int ret; ++ void *p; ++ struct vfio_region_info *nv2reg = NULL; ++ struct vfio_info_cap_header *hdr; ++ struct vfio_region_info_cap_nvlink2_ssatgt *cap; ++ VFIOQuirk *quirk; ++ ++ ret = vfio_get_dev_region_info(&vdev->vbasedev, ++ VFIO_REGION_TYPE_PCI_VENDOR_TYPE | ++ PCI_VENDOR_ID_NVIDIA, ++ VFIO_REGION_SUBTYPE_NVIDIA_NVLINK2_RAM, ++ &nv2reg); ++ if (ret) { ++ return ret; ++ } ++ ++ hdr = vfio_get_region_info_cap(nv2reg, VFIO_REGION_INFO_CAP_NVLINK2_SSATGT); ++ if (!hdr) { ++ ret = -ENODEV; ++ goto free_exit; ++ } ++ cap = (void *) hdr; ++ ++ p = mmap(NULL, nv2reg->size, PROT_READ | PROT_WRITE | PROT_EXEC, ++ MAP_SHARED, vdev->vbasedev.fd, nv2reg->offset); ++ if (p == MAP_FAILED) { ++ ret = -errno; ++ goto free_exit; ++ } ++ ++ quirk = vfio_quirk_alloc(1); ++ memory_region_init_ram_ptr(&quirk->mem[0], OBJECT(vdev), "nvlink2-mr", ++ nv2reg->size, p); ++ QLIST_INSERT_HEAD(&vdev->bars[0].quirks, quirk, next); ++ ++ object_property_add(OBJECT(vdev), "nvlink2-tgt", "uint64", ++ vfio_pci_nvlink2_get_tgt, NULL, NULL, ++ (void *) (uintptr_t) cap->tgt, NULL); ++ trace_vfio_pci_nvidia_gpu_setup_quirk(vdev->vbasedev.name, cap->tgt, ++ nv2reg->size); ++free_exit: ++ g_free(nv2reg); ++ ++ return ret; ++} ++ ++int vfio_pci_nvlink2_init(VFIOPCIDevice *vdev, Error **errp) ++{ ++ int ret; ++ void *p; ++ struct vfio_region_info *atsdreg = NULL; ++ struct vfio_info_cap_header *hdr; ++ struct vfio_region_info_cap_nvlink2_ssatgt *captgt; ++ struct vfio_region_info_cap_nvlink2_lnkspd *capspeed; ++ VFIOQuirk *quirk; ++ ++ ret = vfio_get_dev_region_info(&vdev->vbasedev, ++ VFIO_REGION_TYPE_PCI_VENDOR_TYPE | ++ PCI_VENDOR_ID_IBM, ++ VFIO_REGION_SUBTYPE_IBM_NVLINK2_ATSD, ++ &atsdreg); ++ if (ret) { ++ return ret; ++ } ++ ++ hdr = vfio_get_region_info_cap(atsdreg, ++ VFIO_REGION_INFO_CAP_NVLINK2_SSATGT); ++ if (!hdr) { ++ ret = -ENODEV; ++ goto free_exit; ++ } ++ captgt = (void *) hdr; ++ ++ hdr = vfio_get_region_info_cap(atsdreg, ++ VFIO_REGION_INFO_CAP_NVLINK2_LNKSPD); ++ if (!hdr) { ++ ret = -ENODEV; ++ goto free_exit; ++ } ++ capspeed = (void *) hdr; ++ ++ /* Some NVLink bridges may not have assigned ATSD */ ++ if (atsdreg->size) { ++ p = mmap(NULL, atsdreg->size, PROT_READ | PROT_WRITE | PROT_EXEC, ++ MAP_SHARED, vdev->vbasedev.fd, atsdreg->offset); ++ if (p == MAP_FAILED) { ++ ret = -errno; ++ goto free_exit; ++ } ++ ++ quirk = vfio_quirk_alloc(1); ++ memory_region_init_ram_device_ptr(&quirk->mem[0], OBJECT(vdev), ++ "nvlink2-atsd-mr", atsdreg->size, p); ++ QLIST_INSERT_HEAD(&vdev->bars[0].quirks, quirk, next); ++ } ++ ++ object_property_add(OBJECT(vdev), "nvlink2-tgt", "uint64", ++ vfio_pci_nvlink2_get_tgt, NULL, NULL, ++ (void *) (uintptr_t) captgt->tgt, NULL); ++ trace_vfio_pci_nvlink2_setup_quirk_ssatgt(vdev->vbasedev.name, captgt->tgt, ++ atsdreg->size); ++ ++ object_property_add(OBJECT(vdev), "nvlink2-link-speed", "uint32", ++ vfio_pci_nvlink2_get_link_speed, NULL, NULL, ++ (void *) (uintptr_t) capspeed->link_speed, NULL); ++ trace_vfio_pci_nvlink2_setup_quirk_lnkspd(vdev->vbasedev.name, ++ capspeed->link_speed); ++free_exit: ++ g_free(atsdreg); ++ ++ return ret; ++} +diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c +index ba3a393..735dcae 100644 +--- a/hw/vfio/pci.c ++++ b/hw/vfio/pci.c +@@ -3078,6 +3078,20 @@ static void vfio_realize(PCIDevice *pdev, Error **errp) + } + } + ++ if (vdev->vendor_id == PCI_VENDOR_ID_NVIDIA) { ++ ret = vfio_pci_nvidia_v100_ram_init(vdev, errp); ++ if (ret && ret != -ENODEV) { ++ error_report("Failed to setup NVIDIA V100 GPU RAM"); ++ } ++ } ++ ++ if (vdev->vendor_id == PCI_VENDOR_ID_IBM) { ++ ret = vfio_pci_nvlink2_init(vdev, errp); ++ if (ret && ret != -ENODEV) { ++ error_report("Failed to setup NVlink2 bridge"); ++ } ++ } ++ + vfio_register_err_notifier(vdev); + vfio_register_req_notifier(vdev); + vfio_setup_resetfn_quirk(vdev); +diff --git a/hw/vfio/pci.h b/hw/vfio/pci.h +index 629c875..bf07b43 100644 +--- a/hw/vfio/pci.h ++++ b/hw/vfio/pci.h +@@ -175,6 +175,8 @@ int vfio_populate_vga(VFIOPCIDevice *vdev, Error **errp); + int vfio_pci_igd_opregion_init(VFIOPCIDevice *vdev, + struct vfio_region_info *info, + Error **errp); ++int vfio_pci_nvidia_v100_ram_init(VFIOPCIDevice *vdev, Error **errp); ++int vfio_pci_nvlink2_init(VFIOPCIDevice *vdev, Error **errp); + + int vfio_display_probe(VFIOPCIDevice *vdev, Error **errp); + void vfio_display_finalize(VFIOPCIDevice *vdev); +diff --git a/hw/vfio/trace-events b/hw/vfio/trace-events +index 9487887..c9a9c14 100644 +--- a/hw/vfio/trace-events ++++ b/hw/vfio/trace-events +@@ -84,6 +84,10 @@ vfio_pci_igd_opregion_enabled(const char *name) "%s" + vfio_pci_igd_host_bridge_enabled(const char *name) "%s" + vfio_pci_igd_lpc_bridge_enabled(const char *name) "%s" + ++vfio_pci_nvidia_gpu_setup_quirk(const char *name, uint64_t tgt, uint64_t size) "%s tgt=0x%"PRIx64" size=0x%"PRIx64 ++vfio_pci_nvlink2_setup_quirk_ssatgt(const char *name, uint64_t tgt, uint64_t size) "%s tgt=0x%"PRIx64" size=0x%"PRIx64 ++vfio_pci_nvlink2_setup_quirk_lnkspd(const char *name, uint32_t link_speed) "%s link_speed=0x%x" ++ + # hw/vfio/common.c + vfio_region_write(const char *name, int index, uint64_t addr, uint64_t data, unsigned size) " (%s:region%d+0x%"PRIx64", 0x%"PRIx64 ", %d)" + vfio_region_read(char *name, int index, uint64_t addr, unsigned size, uint64_t data) " (%s:region%d+0x%"PRIx64", %d) = 0x%"PRIx64 +diff --git a/include/hw/pci-host/spapr.h b/include/hw/pci-host/spapr.h +index 0fae4fc..cd29c59 100644 +--- a/include/hw/pci-host/spapr.h ++++ b/include/hw/pci-host/spapr.h +@@ -24,6 +24,7 @@ + #include "hw/pci/pci.h" + #include "hw/pci/pci_host.h" + #include "hw/ppc/xics.h" ++#include "qemu/units.h" + + #define TYPE_SPAPR_PCI_HOST_BRIDGE "spapr-pci-host-bridge" + +@@ -87,6 +88,9 @@ struct sPAPRPHBState { + uint32_t mig_liobn; + hwaddr mig_mem_win_addr, mig_mem_win_size; + hwaddr mig_io_win_addr, mig_io_win_size; ++ hwaddr nv2_gpa_win_addr; ++ hwaddr nv2_atsd_win_addr; ++ struct spapr_phb_pci_nvgpu_config *nvgpus; + }; + + #define SPAPR_PCI_MEM_WIN_BUS_OFFSET 0x80000000ULL +@@ -104,6 +108,22 @@ struct sPAPRPHBState { + + #define SPAPR_PCI_MSI_WINDOW 0x40000000000ULL + ++#define SPAPR_PCI_NV2RAM64_WIN_BASE SPAPR_PCI_LIMIT ++#define SPAPR_PCI_NV2RAM64_WIN_SIZE (2 * TiB) /* For up to 6 GPUs 256GB each */ ++ ++/* Max number of these GPUsper a physical box */ ++#define NVGPU_MAX_NUM 6 ++/* Max number of NVLinks per GPU in any physical box */ ++#define NVGPU_MAX_LINKS 3 ++ ++/* ++ * GPU RAM starts at 64TiB so huge DMA window to cover it all ends at 128TiB ++ * which is enough. We do not need DMA for ATSD so we put them at 128TiB. ++ */ ++#define SPAPR_PCI_NV2ATSD_WIN_BASE (128 * TiB) ++#define SPAPR_PCI_NV2ATSD_WIN_SIZE (NVGPU_MAX_NUM * NVGPU_MAX_LINKS * \ ++ 64 * KiB) ++ + static inline qemu_irq spapr_phb_lsi_qirq(struct sPAPRPHBState *phb, int pin) + { + sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine()); +@@ -135,6 +155,13 @@ int spapr_phb_vfio_eeh_get_state(sPAPRPHBState *sphb, int *state); + int spapr_phb_vfio_eeh_reset(sPAPRPHBState *sphb, int option); + int spapr_phb_vfio_eeh_configure(sPAPRPHBState *sphb); + void spapr_phb_vfio_reset(DeviceState *qdev); ++void spapr_phb_nvgpu_setup(sPAPRPHBState *sphb, Error **errp); ++void spapr_phb_nvgpu_free(sPAPRPHBState *sphb); ++void spapr_phb_nvgpu_populate_dt(sPAPRPHBState *sphb, void *fdt, int bus_off, ++ Error **errp); ++void spapr_phb_nvgpu_ram_populate_dt(sPAPRPHBState *sphb, void *fdt); ++void spapr_phb_nvgpu_populate_pcidev_dt(PCIDevice *dev, void *fdt, int offset, ++ sPAPRPHBState *sphb); + #else + static inline bool spapr_phb_eeh_available(sPAPRPHBState *sphb) + { +@@ -161,6 +188,25 @@ static inline int spapr_phb_vfio_eeh_configure(sPAPRPHBState *sphb) + static inline void spapr_phb_vfio_reset(DeviceState *qdev) + { + } ++static inline void spapr_phb_nvgpu_setup(sPAPRPHBState *sphb, Error **errp) ++{ ++} ++static inline void spapr_phb_nvgpu_free(sPAPRPHBState *sphb) ++{ ++} ++static inline void spapr_phb_nvgpu_populate_dt(sPAPRPHBState *sphb, void *fdt, ++ int bus_off, Error **errp) ++{ ++} ++static inline void spapr_phb_nvgpu_ram_populate_dt(sPAPRPHBState *sphb, ++ void *fdt) ++{ ++} ++static inline void spapr_phb_nvgpu_populate_pcidev_dt(PCIDevice *dev, void *fdt, ++ int offset, ++ sPAPRPHBState *sphb) ++{ ++} + #endif + + void spapr_phb_dma_reset(sPAPRPHBState *sphb); +diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h +index beb42bc..72cfa49 100644 +--- a/include/hw/ppc/spapr.h ++++ b/include/hw/ppc/spapr.h +@@ -104,7 +104,8 @@ struct sPAPRMachineClass { + void (*phb_placement)(sPAPRMachineState *spapr, uint32_t index, + uint64_t *buid, hwaddr *pio, + hwaddr *mmio32, hwaddr *mmio64, +- unsigned n_dma, uint32_t *liobns, Error **errp); ++ unsigned n_dma, uint32_t *liobns, hwaddr *nv2gpa, ++ hwaddr *nv2atsd, Error **errp); + sPAPRResizeHPT resize_hpt_default; + sPAPRCapabilities default_caps; + }; +@@ -171,6 +172,8 @@ struct sPAPRMachineState { + + bool cmd_line_caps[SPAPR_CAP_NUM]; + sPAPRCapabilities def, eff, mig; ++ ++ unsigned gpu_numa_id; + }; + + #define H_SUCCESS 0 +-- +1.8.3.1 + diff --git a/SOURCES/kvm-spice-set-device-address-and-device-display-ID-in-QX.patch b/SOURCES/kvm-spice-set-device-address-and-device-display-ID-in-QX.patch new file mode 100644 index 0000000..c611490 --- /dev/null +++ b/SOURCES/kvm-spice-set-device-address-and-device-display-ID-in-QX.patch @@ -0,0 +1,179 @@ +From 2d0261e575197b60fd17850f1079359375fb82a3 Mon Sep 17 00:00:00 2001 +From: Danilo de Paula +Date: Wed, 22 May 2019 20:24:33 +0100 +Subject: [PATCH 11/12] spice: set device address and device display ID in QXL + interface +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Danilo de Paula +Message-id: <20190522202434.2529-2-ddepaula@redhat.com> +Patchwork-id: 88166 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 1/2] spice: set device address and device display ID in QXL interface +Bugzilla: 1712946 +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Marc-André Lureau +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Stefan Hajnoczi + +From: Lukáš Hrázký + +Calls the new SPICE QXL interface function spice_qxl_set_device_info to +set the hardware address of the graphics device represented by the QXL +interface (e.g. a PCI path) and the device display IDs (the IDs of the +device's monitors that belong to this QXL interface). + +Also stops using the deprecated spice_qxl_set_max_monitors, the new +interface function replaces it. + +Signed-off-by: Lukáš Hrázký +Message-Id: <20190215150919.8263-1-lhrazky@redhat.com> +Signed-off-by: Gerd Hoffmann +(cherry picked from commit be812c0ab7d5ab741d0d87387a75a0e8bb6461e7) +Signed-off-by: Danilo C. L. de Paula +--- + hw/display/qxl.c | 14 ++++++++++++- + include/ui/spice-display.h | 4 ++++ + ui/spice-core.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++ + ui/spice-display.c | 11 ++++++++++ + 4 files changed, 79 insertions(+), 1 deletion(-) + +diff --git a/hw/display/qxl.c b/hw/display/qxl.c +index e36ef32..b373c50 100644 +--- a/hw/display/qxl.c ++++ b/hw/display/qxl.c +@@ -275,7 +275,8 @@ static void qxl_spice_monitors_config_async(PCIQXLDevice *qxl, int replay) + QXL_COOKIE_TYPE_POST_LOAD_MONITORS_CONFIG, + 0)); + } else { +-#if SPICE_SERVER_VERSION >= 0x000c06 /* release 0.12.6 */ ++/* >= release 0.12.6, < release 0.14.2 */ ++#if SPICE_SERVER_VERSION >= 0x000c06 && SPICE_SERVER_VERSION < 0x000e02 + if (qxl->max_outputs) { + spice_qxl_set_max_monitors(&qxl->ssd.qxl, qxl->max_outputs); + } +@@ -2161,6 +2162,17 @@ static void qxl_realize_common(PCIQXLDevice *qxl, Error **errp) + SPICE_INTERFACE_QXL_MAJOR, SPICE_INTERFACE_QXL_MINOR); + return; + } ++ ++#if SPICE_SERVER_VERSION >= 0x000e02 /* release 0.14.2 */ ++ char device_address[256] = ""; ++ if (qemu_spice_fill_device_address(qxl->vga.con, device_address, 256)) { ++ spice_qxl_set_device_info(&qxl->ssd.qxl, ++ device_address, ++ 0, ++ qxl->max_outputs); ++ } ++#endif ++ + qemu_add_vm_change_state_handler(qxl_vm_change_state_handler, qxl); + + qxl->update_irq = qemu_bh_new(qxl_update_irq_bh, qxl); +diff --git a/include/ui/spice-display.h b/include/ui/spice-display.h +index 87a84a5..53c3612 100644 +--- a/include/ui/spice-display.h ++++ b/include/ui/spice-display.h +@@ -179,3 +179,7 @@ void qemu_spice_wakeup(SimpleSpiceDisplay *ssd); + void qemu_spice_display_start(void); + void qemu_spice_display_stop(void); + int qemu_spice_display_is_running(SimpleSpiceDisplay *ssd); ++ ++bool qemu_spice_fill_device_address(QemuConsole *con, ++ char *device_address, ++ size_t size); +diff --git a/ui/spice-core.c b/ui/spice-core.c +index ae8921a..ebc2f09 100644 +--- a/ui/spice-core.c ++++ b/ui/spice-core.c +@@ -35,6 +35,7 @@ + #include "qemu/option.h" + #include "migration/misc.h" + #include "hw/hw.h" ++#include "hw/pci/pci_bus.h" + #include "ui/spice-display.h" + + /* core bits */ +@@ -872,6 +873,56 @@ bool qemu_spice_have_display_interface(QemuConsole *con) + return false; + } + ++/* ++ * Recursively (in reverse order) appends addresses of PCI devices as it moves ++ * up in the PCI hierarchy. ++ * ++ * @returns true on success, false when the buffer wasn't large enough ++ */ ++static bool append_pci_address(char *buf, size_t buf_size, const PCIDevice *pci) ++{ ++ PCIBus *bus = pci_get_bus(pci); ++ /* ++ * equivalent to if (!pci_bus_is_root(bus)), but the function is not built ++ * with PCI_CONFIG=n, avoid using an #ifdef by checking directly ++ */ ++ if (bus->parent_dev != NULL) { ++ append_pci_address(buf, buf_size, bus->parent_dev); ++ } ++ ++ size_t len = strlen(buf); ++ ssize_t written = snprintf(buf + len, buf_size - len, "/%02x.%x", ++ PCI_SLOT(pci->devfn), PCI_FUNC(pci->devfn)); ++ ++ return written > 0 && written < buf_size - len; ++} ++ ++bool qemu_spice_fill_device_address(QemuConsole *con, ++ char *device_address, ++ size_t size) ++{ ++ DeviceState *dev = DEVICE(object_property_get_link(OBJECT(con), ++ "device", ++ &error_abort)); ++ PCIDevice *pci = (PCIDevice *) object_dynamic_cast(OBJECT(dev), ++ TYPE_PCI_DEVICE); ++ ++ if (pci == NULL) { ++ warn_report("Setting device address of a display device to SPICE: " ++ "Not a PCI device."); ++ return false; ++ } ++ ++ strncpy(device_address, "pci/0000", size); ++ if (!append_pci_address(device_address, size, pci)) { ++ warn_report("Setting device address of a display device to SPICE: " ++ "Too many PCI devices in the chain."); ++ return false; ++ } ++ ++ return true; ++} ++ + int qemu_spice_add_display_interface(QXLInstance *qxlin, QemuConsole *con) + { + if (g_slist_find(spice_consoles, con)) { +diff --git a/ui/spice-display.c b/ui/spice-display.c +index fe73482..22332f4 100644 +--- a/ui/spice-display.c ++++ b/ui/spice-display.c +@@ -1115,6 +1115,17 @@ static void qemu_spice_display_init_one(QemuConsole *con) + + ssd->qxl.base.sif = &dpy_interface.base; + qemu_spice_add_display_interface(&ssd->qxl, con); ++ ++#if SPICE_SERVER_VERSION >= 0x000e02 /* release 0.14.2 */ ++ char device_address[256] = ""; ++ if (qemu_spice_fill_device_address(con, device_address, 256)) { ++ spice_qxl_set_device_info(&ssd->qxl, ++ device_address, ++ qemu_console_get_head(con), ++ 1); ++ } ++#endif ++ + qemu_spice_create_host_memslot(ssd); + + register_displaychangelistener(&ssd->dcl); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-ssh-switch-from-libssh2-to-libssh.patch b/SOURCES/kvm-ssh-switch-from-libssh2-to-libssh.patch new file mode 100644 index 0000000..9473ffc --- /dev/null +++ b/SOURCES/kvm-ssh-switch-from-libssh2-to-libssh.patch @@ -0,0 +1,1526 @@ +From 4d4eb9e793e7722c05c697812320a14ae5797bae Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Mon, 8 Jul 2019 15:26:00 +0100 +Subject: [PATCH 14/39] ssh: switch from libssh2 to libssh +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Pino Toscano +Message-id: <20190708152601.21123-10-ptoscano@redhat.com> +Patchwork-id: 89421 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v3 09/10] ssh: switch from libssh2 to libssh +Bugzilla: 1513367 +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Max Reitz +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Markus Armbruster + +Rewrite the implementation of the ssh block driver to use libssh instead +of libssh2. The libssh library has various advantages over libssh2: +- easier API for authentication (for example for using ssh-agent) +- easier API for known_hosts handling +- supports newer types of keys in known_hosts + +Use APIs/features available in libssh 0.8 conditionally, to support +older versions (which are not recommended though). + +Adjust the iotest 207 according to the different error message, and to +find the default key type for localhost (to properly compare the +fingerprint with). +Contributed-by: Max Reitz + +Adjust the various Docker/Travis scripts to use libssh when available +instead of libssh2. The mingw/mxe testing is dropped for now, as there +are no packages for it. + +Signed-off-by: Pino Toscano +Tested-by: Philippe Mathieu-Daudé +Acked-by: Alex Bennée +Message-id: 20190620200840.17655-1-ptoscano@redhat.com +Reviewed-by: Philippe Mathieu-Daudé +Message-id: 5873173.t2JhDm7DL7@lindworm.usersys.redhat.com +Signed-off-by: Max Reitz +(cherry picked from commit b10d49d7619e4957b4b971f816661b57e5061d71) +Signed-off-by: Pino Toscano +Signed-off-by: Danilo C. L. de Paula +--- + .travis.yml | 4 +- + block/Makefile.objs | 6 +- + block/ssh.c | 652 ++++++++++++--------- + block/trace-events | 14 +- + configure | 65 +- + docs/qemu-block-drivers.texi | 2 +- + tests/docker/dockerfiles/debian-win32-cross.docker | 1 - + tests/docker/dockerfiles/debian-win64-cross.docker | 1 - + tests/docker/dockerfiles/fedora.docker | 6 +- + tests/docker/dockerfiles/ubuntu.docker | 2 +- + tests/qemu-iotests/207 | 54 +- + tests/qemu-iotests/207.out | 2 +- + 12 files changed, 450 insertions(+), 359 deletions(-) + +diff --git a/.travis.yml b/.travis.yml +index c1e9923..d174d82 100644 +--- a/.travis.yml ++++ b/.travis.yml +@@ -28,7 +28,7 @@ addons: + - libseccomp-dev + - libspice-protocol-dev + - libspice-server-dev +- - libssh2-1-dev ++ - libssh-dev + - liburcu-dev + - libusb-1.0-0-dev + - libvte-2.90-dev +@@ -188,7 +188,7 @@ matrix: + - libseccomp-dev + - libspice-protocol-dev + - libspice-server-dev +- - libssh2-1-dev ++ - libssh-dev + - liburcu-dev + - libusb-1.0-0-dev + - libvte-2.90-dev +diff --git a/block/Makefile.objs b/block/Makefile.objs +index ac7a1f8..51cd336 100644 +--- a/block/Makefile.objs ++++ b/block/Makefile.objs +@@ -30,7 +30,7 @@ block-obj-$(CONFIG_CURL) += curl.o + block-obj-$(CONFIG_RBD) += rbd.o + block-obj-$(CONFIG_GLUSTERFS) += gluster.o + block-obj-$(CONFIG_VXHS) += vxhs.o +-block-obj-$(CONFIG_LIBSSH2) += ssh.o ++block-obj-$(CONFIG_LIBSSH) += ssh.o + block-obj-y += accounting.o dirty-bitmap.o + block-obj-y += write-threshold.o + block-obj-y += backup.o +@@ -51,8 +51,8 @@ rbd.o-libs := $(RBD_LIBS) + gluster.o-cflags := $(GLUSTERFS_CFLAGS) + gluster.o-libs := $(GLUSTERFS_LIBS) + vxhs.o-libs := $(VXHS_LIBS) +-ssh.o-cflags := $(LIBSSH2_CFLAGS) +-ssh.o-libs := $(LIBSSH2_LIBS) ++ssh.o-cflags := $(LIBSSH_CFLAGS) ++ssh.o-libs := $(LIBSSH_LIBS) + block-obj-dmg-bz2-$(CONFIG_BZIP2) += dmg-bz2.o + block-obj-$(if $(CONFIG_DMG),m,n) += $(block-obj-dmg-bz2-y) + dmg-bz2.o-libs := $(BZIP2_LIBS) +diff --git a/block/ssh.c b/block/ssh.c +index f0ef874..a4a374c 100644 +--- a/block/ssh.c ++++ b/block/ssh.c +@@ -24,8 +24,8 @@ + + #include "qemu/osdep.h" + +-#include +-#include ++#include ++#include + + #include "block/block_int.h" + #include "block/qdict.h" +@@ -44,13 +44,11 @@ + #include "trace.h" + + /* +- * TRACE_LIBSSH2= enables tracing in libssh2 itself. Note +- * that this requires that libssh2 was specially compiled with the +- * `./configure --enable-debug' option, so most likely you will have +- * to compile it yourself. The meaning of is described +- * here: http://www.libssh2.org/libssh2_trace.html ++ * TRACE_LIBSSH= enables tracing in libssh itself. ++ * The meaning of is described here: ++ * http://api.libssh.org/master/group__libssh__log.html + */ +-#define TRACE_LIBSSH2 0 /* or try: LIBSSH2_TRACE_SFTP */ ++#define TRACE_LIBSSH 0 /* see: SSH_LOG_* */ + + typedef struct BDRVSSHState { + /* Coroutine. */ +@@ -58,18 +56,15 @@ typedef struct BDRVSSHState { + + /* SSH connection. */ + int sock; /* socket */ +- LIBSSH2_SESSION *session; /* ssh session */ +- LIBSSH2_SFTP *sftp; /* sftp session */ +- LIBSSH2_SFTP_HANDLE *sftp_handle; /* sftp remote file handle */ ++ ssh_session session; /* ssh session */ ++ sftp_session sftp; /* sftp session */ ++ sftp_file sftp_handle; /* sftp remote file handle */ + +- /* See ssh_seek() function below. */ +- int64_t offset; +- bool offset_op_read; +- +- /* File attributes at open. We try to keep the .filesize field ++ /* ++ * File attributes at open. We try to keep the .size field + * updated if it changes (eg by writing at the end of the file). + */ +- LIBSSH2_SFTP_ATTRIBUTES attrs; ++ sftp_attributes attrs; + + InetSocketAddress *inet; + +@@ -89,7 +84,6 @@ static void ssh_state_init(BDRVSSHState *s) + { + memset(s, 0, sizeof *s); + s->sock = -1; +- s->offset = -1; + qemu_co_mutex_init(&s->lock); + } + +@@ -97,20 +91,18 @@ static void ssh_state_free(BDRVSSHState *s) + { + g_free(s->user); + ++ if (s->attrs) { ++ sftp_attributes_free(s->attrs); ++ } + if (s->sftp_handle) { +- libssh2_sftp_close(s->sftp_handle); ++ sftp_close(s->sftp_handle); + } + if (s->sftp) { +- libssh2_sftp_shutdown(s->sftp); ++ sftp_free(s->sftp); + } + if (s->session) { +- libssh2_session_disconnect(s->session, +- "from qemu ssh client: " +- "user closed the connection"); +- libssh2_session_free(s->session); +- } +- if (s->sock >= 0) { +- close(s->sock); ++ ssh_disconnect(s->session); ++ ssh_free(s->session); /* This frees s->sock */ + } + } + +@@ -125,13 +117,13 @@ session_error_setg(Error **errp, BDRVSSHState *s, const char *fs, ...) + va_end(args); + + if (s->session) { +- char *ssh_err; ++ const char *ssh_err; + int ssh_err_code; + +- /* This is not an errno. See . */ +- ssh_err_code = libssh2_session_last_error(s->session, +- &ssh_err, NULL, 0); +- error_setg(errp, "%s: %s (libssh2 error code: %d)", ++ /* This is not an errno. See . */ ++ ssh_err = ssh_get_error(s->session); ++ ssh_err_code = ssh_get_error_code(s->session); ++ error_setg(errp, "%s: %s (libssh error code: %d)", + msg, ssh_err, ssh_err_code); + } else { + error_setg(errp, "%s", msg); +@@ -150,18 +142,18 @@ sftp_error_setg(Error **errp, BDRVSSHState *s, const char *fs, ...) + va_end(args); + + if (s->sftp) { +- char *ssh_err; ++ const char *ssh_err; + int ssh_err_code; +- unsigned long sftp_err_code; ++ int sftp_err_code; + +- /* This is not an errno. See . */ +- ssh_err_code = libssh2_session_last_error(s->session, +- &ssh_err, NULL, 0); +- /* See . */ +- sftp_err_code = libssh2_sftp_last_error((s)->sftp); ++ /* This is not an errno. See . */ ++ ssh_err = ssh_get_error(s->session); ++ ssh_err_code = ssh_get_error_code(s->session); ++ /* See . */ ++ sftp_err_code = sftp_get_error(s->sftp); + + error_setg(errp, +- "%s: %s (libssh2 error code: %d, sftp error code: %lu)", ++ "%s: %s (libssh error code: %d, sftp error code: %d)", + msg, ssh_err, ssh_err_code, sftp_err_code); + } else { + error_setg(errp, "%s", msg); +@@ -171,15 +163,15 @@ sftp_error_setg(Error **errp, BDRVSSHState *s, const char *fs, ...) + + static void sftp_error_trace(BDRVSSHState *s, const char *op) + { +- char *ssh_err; ++ const char *ssh_err; + int ssh_err_code; +- unsigned long sftp_err_code; ++ int sftp_err_code; + +- /* This is not an errno. See . */ +- ssh_err_code = libssh2_session_last_error(s->session, +- &ssh_err, NULL, 0); +- /* See . */ +- sftp_err_code = libssh2_sftp_last_error((s)->sftp); ++ /* This is not an errno. See . */ ++ ssh_err = ssh_get_error(s->session); ++ ssh_err_code = ssh_get_error_code(s->session); ++ /* See . */ ++ sftp_err_code = sftp_get_error(s->sftp); + + trace_sftp_error(op, ssh_err, ssh_err_code, sftp_err_code); + } +@@ -280,82 +272,120 @@ static void ssh_parse_filename(const char *filename, QDict *options, + parse_uri(filename, options, errp); + } + +-static int check_host_key_knownhosts(BDRVSSHState *s, +- const char *host, int port, Error **errp) ++static int check_host_key_knownhosts(BDRVSSHState *s, Error **errp) + { +- const char *home; +- char *knh_file = NULL; +- LIBSSH2_KNOWNHOSTS *knh = NULL; +- struct libssh2_knownhost *found; +- int ret, r; +- const char *hostkey; +- size_t len; +- int type; +- +- hostkey = libssh2_session_hostkey(s->session, &len, &type); +- if (!hostkey) { ++ int ret; ++#ifdef HAVE_LIBSSH_0_8 ++ enum ssh_known_hosts_e state; ++ int r; ++ ssh_key pubkey; ++ enum ssh_keytypes_e pubkey_type; ++ unsigned char *server_hash = NULL; ++ size_t server_hash_len; ++ char *fingerprint = NULL; ++ ++ state = ssh_session_is_known_server(s->session); ++ trace_ssh_server_status(state); ++ ++ switch (state) { ++ case SSH_KNOWN_HOSTS_OK: ++ /* OK */ ++ trace_ssh_check_host_key_knownhosts(); ++ break; ++ case SSH_KNOWN_HOSTS_CHANGED: + ret = -EINVAL; +- session_error_setg(errp, s, "failed to read remote host key"); ++ r = ssh_get_server_publickey(s->session, &pubkey); ++ if (r == 0) { ++ r = ssh_get_publickey_hash(pubkey, SSH_PUBLICKEY_HASH_SHA256, ++ &server_hash, &server_hash_len); ++ pubkey_type = ssh_key_type(pubkey); ++ ssh_key_free(pubkey); ++ } ++ if (r == 0) { ++ fingerprint = ssh_get_fingerprint_hash(SSH_PUBLICKEY_HASH_SHA256, ++ server_hash, ++ server_hash_len); ++ ssh_clean_pubkey_hash(&server_hash); ++ } ++ if (fingerprint) { ++ error_setg(errp, ++ "host key (%s key with fingerprint %s) does not match " ++ "the one in known_hosts; this may be a possible attack", ++ ssh_key_type_to_char(pubkey_type), fingerprint); ++ ssh_string_free_char(fingerprint); ++ } else { ++ error_setg(errp, ++ "host key does not match the one in known_hosts; this " ++ "may be a possible attack"); ++ } + goto out; +- } +- +- knh = libssh2_knownhost_init(s->session); +- if (!knh) { ++ case SSH_KNOWN_HOSTS_OTHER: + ret = -EINVAL; +- session_error_setg(errp, s, +- "failed to initialize known hosts support"); ++ error_setg(errp, ++ "host key for this server not found, another type exists"); ++ goto out; ++ case SSH_KNOWN_HOSTS_UNKNOWN: ++ ret = -EINVAL; ++ error_setg(errp, "no host key was found in known_hosts"); ++ goto out; ++ case SSH_KNOWN_HOSTS_NOT_FOUND: ++ ret = -ENOENT; ++ error_setg(errp, "known_hosts file not found"); ++ goto out; ++ case SSH_KNOWN_HOSTS_ERROR: ++ ret = -EINVAL; ++ error_setg(errp, "error while checking the host"); ++ goto out; ++ default: ++ ret = -EINVAL; ++ error_setg(errp, "error while checking for known server (%d)", state); + goto out; + } ++#else /* !HAVE_LIBSSH_0_8 */ ++ int state; + +- home = getenv("HOME"); +- if (home) { +- knh_file = g_strdup_printf("%s/.ssh/known_hosts", home); +- } else { +- knh_file = g_strdup_printf("/root/.ssh/known_hosts"); +- } +- +- /* Read all known hosts from OpenSSH-style known_hosts file. */ +- libssh2_knownhost_readfile(knh, knh_file, LIBSSH2_KNOWNHOST_FILE_OPENSSH); ++ state = ssh_is_server_known(s->session); ++ trace_ssh_server_status(state); + +- r = libssh2_knownhost_checkp(knh, host, port, hostkey, len, +- LIBSSH2_KNOWNHOST_TYPE_PLAIN| +- LIBSSH2_KNOWNHOST_KEYENC_RAW, +- &found); +- switch (r) { +- case LIBSSH2_KNOWNHOST_CHECK_MATCH: ++ switch (state) { ++ case SSH_SERVER_KNOWN_OK: + /* OK */ +- trace_ssh_check_host_key_knownhosts(found->key); ++ trace_ssh_check_host_key_knownhosts(); + break; +- case LIBSSH2_KNOWNHOST_CHECK_MISMATCH: ++ case SSH_SERVER_KNOWN_CHANGED: + ret = -EINVAL; +- session_error_setg(errp, s, +- "host key does not match the one in known_hosts" +- " (found key %s)", found->key); ++ error_setg(errp, ++ "host key does not match the one in known_hosts; this " ++ "may be a possible attack"); + goto out; +- case LIBSSH2_KNOWNHOST_CHECK_NOTFOUND: ++ case SSH_SERVER_FOUND_OTHER: + ret = -EINVAL; +- session_error_setg(errp, s, "no host key was found in known_hosts"); ++ error_setg(errp, ++ "host key for this server not found, another type exists"); + goto out; +- case LIBSSH2_KNOWNHOST_CHECK_FAILURE: ++ case SSH_SERVER_FILE_NOT_FOUND: ++ ret = -ENOENT; ++ error_setg(errp, "known_hosts file not found"); ++ goto out; ++ case SSH_SERVER_NOT_KNOWN: + ret = -EINVAL; +- session_error_setg(errp, s, +- "failure matching the host key with known_hosts"); ++ error_setg(errp, "no host key was found in known_hosts"); ++ goto out; ++ case SSH_SERVER_ERROR: ++ ret = -EINVAL; ++ error_setg(errp, "server error"); + goto out; + default: + ret = -EINVAL; +- session_error_setg(errp, s, "unknown error matching the host key" +- " with known_hosts (%d)", r); ++ error_setg(errp, "error while checking for known server (%d)", state); + goto out; + } ++#endif /* !HAVE_LIBSSH_0_8 */ + + /* known_hosts checking successful. */ + ret = 0; + + out: +- if (knh != NULL) { +- libssh2_knownhost_free(knh); +- } +- g_free(knh_file); + return ret; + } + +@@ -399,18 +429,34 @@ static int compare_fingerprint(const unsigned char *fingerprint, size_t len, + + static int + check_host_key_hash(BDRVSSHState *s, const char *hash, +- int hash_type, size_t fingerprint_len, Error **errp) ++ enum ssh_publickey_hash_type type, Error **errp) + { +- const char *fingerprint; +- +- fingerprint = libssh2_hostkey_hash(s->session, hash_type); +- if (!fingerprint) { ++ int r; ++ ssh_key pubkey; ++ unsigned char *server_hash; ++ size_t server_hash_len; ++ ++#ifdef HAVE_LIBSSH_0_8 ++ r = ssh_get_server_publickey(s->session, &pubkey); ++#else ++ r = ssh_get_publickey(s->session, &pubkey); ++#endif ++ if (r != SSH_OK) { + session_error_setg(errp, s, "failed to read remote host key"); + return -EINVAL; + } + +- if(compare_fingerprint((unsigned char *) fingerprint, fingerprint_len, +- hash) != 0) { ++ r = ssh_get_publickey_hash(pubkey, type, &server_hash, &server_hash_len); ++ ssh_key_free(pubkey); ++ if (r != 0) { ++ session_error_setg(errp, s, ++ "failed reading the hash of the server SSH key"); ++ return -EINVAL; ++ } ++ ++ r = compare_fingerprint(server_hash, server_hash_len, hash); ++ ssh_clean_pubkey_hash(&server_hash); ++ if (r != 0) { + error_setg(errp, "remote host key does not match host_key_check '%s'", + hash); + return -EPERM; +@@ -419,8 +465,7 @@ check_host_key_hash(BDRVSSHState *s, const char *hash, + return 0; + } + +-static int check_host_key(BDRVSSHState *s, const char *host, int port, +- SshHostKeyCheck *hkc, Error **errp) ++static int check_host_key(BDRVSSHState *s, SshHostKeyCheck *hkc, Error **errp) + { + SshHostKeyCheckMode mode; + +@@ -436,15 +481,15 @@ static int check_host_key(BDRVSSHState *s, const char *host, int port, + case SSH_HOST_KEY_CHECK_MODE_HASH: + if (hkc->u.hash.type == SSH_HOST_KEY_CHECK_HASH_TYPE_MD5) { + return check_host_key_hash(s, hkc->u.hash.hash, +- LIBSSH2_HOSTKEY_HASH_MD5, 16, errp); ++ SSH_PUBLICKEY_HASH_MD5, errp); + } else if (hkc->u.hash.type == SSH_HOST_KEY_CHECK_HASH_TYPE_SHA1) { + return check_host_key_hash(s, hkc->u.hash.hash, +- LIBSSH2_HOSTKEY_HASH_SHA1, 20, errp); ++ SSH_PUBLICKEY_HASH_SHA1, errp); + } + g_assert_not_reached(); + break; + case SSH_HOST_KEY_CHECK_MODE_KNOWN_HOSTS: +- return check_host_key_knownhosts(s, host, port, errp); ++ return check_host_key_knownhosts(s, errp); + default: + g_assert_not_reached(); + } +@@ -452,60 +497,43 @@ static int check_host_key(BDRVSSHState *s, const char *host, int port, + return -EINVAL; + } + +-static int authenticate(BDRVSSHState *s, const char *user, Error **errp) ++static int authenticate(BDRVSSHState *s, Error **errp) + { + int r, ret; +- const char *userauthlist; +- LIBSSH2_AGENT *agent = NULL; +- struct libssh2_agent_publickey *identity; +- struct libssh2_agent_publickey *prev_identity = NULL; ++ int method; + +- userauthlist = libssh2_userauth_list(s->session, user, strlen(user)); +- if (strstr(userauthlist, "publickey") == NULL) { ++ /* Try to authenticate with the "none" method. */ ++ r = ssh_userauth_none(s->session, NULL); ++ if (r == SSH_AUTH_ERROR) { + ret = -EPERM; +- error_setg(errp, +- "remote server does not support \"publickey\" authentication"); ++ session_error_setg(errp, s, "failed to authenticate using none " ++ "authentication"); + goto out; +- } +- +- /* Connect to ssh-agent and try each identity in turn. */ +- agent = libssh2_agent_init(s->session); +- if (!agent) { +- ret = -EINVAL; +- session_error_setg(errp, s, "failed to initialize ssh-agent support"); +- goto out; +- } +- if (libssh2_agent_connect(agent)) { +- ret = -ECONNREFUSED; +- session_error_setg(errp, s, "failed to connect to ssh-agent"); +- goto out; +- } +- if (libssh2_agent_list_identities(agent)) { +- ret = -EINVAL; +- session_error_setg(errp, s, +- "failed requesting identities from ssh-agent"); ++ } else if (r == SSH_AUTH_SUCCESS) { ++ /* Authenticated! */ ++ ret = 0; + goto out; + } + +- for(;;) { +- r = libssh2_agent_get_identity(agent, &identity, prev_identity); +- if (r == 1) { /* end of list */ +- break; +- } +- if (r < 0) { ++ method = ssh_userauth_list(s->session, NULL); ++ trace_ssh_auth_methods(method); ++ ++ /* ++ * Try to authenticate with publickey, using the ssh-agent ++ * if available. ++ */ ++ if (method & SSH_AUTH_METHOD_PUBLICKEY) { ++ r = ssh_userauth_publickey_auto(s->session, NULL, NULL); ++ if (r == SSH_AUTH_ERROR) { + ret = -EINVAL; +- session_error_setg(errp, s, +- "failed to obtain identity from ssh-agent"); ++ session_error_setg(errp, s, "failed to authenticate using " ++ "publickey authentication"); + goto out; +- } +- r = libssh2_agent_userauth(agent, user, identity); +- if (r == 0) { ++ } else if (r == SSH_AUTH_SUCCESS) { + /* Authenticated! */ + ret = 0; + goto out; + } +- /* Failed to authenticate with this identity, try the next one. */ +- prev_identity = identity; + } + + ret = -EPERM; +@@ -513,13 +541,6 @@ static int authenticate(BDRVSSHState *s, const char *user, Error **errp) + "and the identities held by your ssh-agent"); + + out: +- if (agent != NULL) { +- /* Note: libssh2 implementation implicitly calls +- * libssh2_agent_disconnect if necessary. +- */ +- libssh2_agent_free(agent); +- } +- + return ret; + } + +@@ -638,7 +659,8 @@ static int connect_to_ssh(BDRVSSHState *s, BlockdevOptionsSsh *opts, + int ssh_flags, int creat_mode, Error **errp) + { + int r, ret; +- long port = 0; ++ unsigned int port = 0; ++ int new_sock = -1; + + if (opts->has_user) { + s->user = g_strdup(opts->user); +@@ -655,71 +677,147 @@ static int connect_to_ssh(BDRVSSHState *s, BlockdevOptionsSsh *opts, + s->inet = opts->server; + opts->server = NULL; + +- if (qemu_strtol(s->inet->port, NULL, 10, &port) < 0) { ++ if (qemu_strtoui(s->inet->port, NULL, 10, &port) < 0) { + error_setg(errp, "Use only numeric port value"); + ret = -EINVAL; + goto err; + } + + /* Open the socket and connect. */ +- s->sock = inet_connect_saddr(s->inet, errp); +- if (s->sock < 0) { ++ new_sock = inet_connect_saddr(s->inet, errp); ++ if (new_sock < 0) { + ret = -EIO; + goto err; + } + ++ /* ++ * Try to disable the Nagle algorithm on TCP sockets to reduce latency, ++ * but do not fail if it cannot be disabled. ++ */ ++ r = socket_set_nodelay(new_sock); ++ if (r < 0) { ++ warn_report("can't set TCP_NODELAY for the ssh server %s: %s", ++ s->inet->host, strerror(errno)); ++ } ++ + /* Create SSH session. */ +- s->session = libssh2_session_init(); ++ s->session = ssh_new(); + if (!s->session) { + ret = -EINVAL; +- session_error_setg(errp, s, "failed to initialize libssh2 session"); ++ session_error_setg(errp, s, "failed to initialize libssh session"); + goto err; + } + +-#if TRACE_LIBSSH2 != 0 +- libssh2_trace(s->session, TRACE_LIBSSH2); +-#endif ++ /* ++ * Make sure we are in blocking mode during the connection and ++ * authentication phases. ++ */ ++ ssh_set_blocking(s->session, 1); + +- r = libssh2_session_handshake(s->session, s->sock); +- if (r != 0) { ++ r = ssh_options_set(s->session, SSH_OPTIONS_USER, s->user); ++ if (r < 0) { ++ ret = -EINVAL; ++ session_error_setg(errp, s, ++ "failed to set the user in the libssh session"); ++ goto err; ++ } ++ ++ r = ssh_options_set(s->session, SSH_OPTIONS_HOST, s->inet->host); ++ if (r < 0) { ++ ret = -EINVAL; ++ session_error_setg(errp, s, ++ "failed to set the host in the libssh session"); ++ goto err; ++ } ++ ++ if (port > 0) { ++ r = ssh_options_set(s->session, SSH_OPTIONS_PORT, &port); ++ if (r < 0) { ++ ret = -EINVAL; ++ session_error_setg(errp, s, ++ "failed to set the port in the libssh session"); ++ goto err; ++ } ++ } ++ ++ r = ssh_options_set(s->session, SSH_OPTIONS_COMPRESSION, "none"); ++ if (r < 0) { ++ ret = -EINVAL; ++ session_error_setg(errp, s, ++ "failed to disable the compression in the libssh " ++ "session"); ++ goto err; ++ } ++ ++ /* Read ~/.ssh/config. */ ++ r = ssh_options_parse_config(s->session, NULL); ++ if (r < 0) { ++ ret = -EINVAL; ++ session_error_setg(errp, s, "failed to parse ~/.ssh/config"); ++ goto err; ++ } ++ ++ r = ssh_options_set(s->session, SSH_OPTIONS_FD, &new_sock); ++ if (r < 0) { ++ ret = -EINVAL; ++ session_error_setg(errp, s, ++ "failed to set the socket in the libssh session"); ++ goto err; ++ } ++ /* libssh took ownership of the socket. */ ++ s->sock = new_sock; ++ new_sock = -1; ++ ++ /* Connect. */ ++ r = ssh_connect(s->session); ++ if (r != SSH_OK) { + ret = -EINVAL; + session_error_setg(errp, s, "failed to establish SSH session"); + goto err; + } + + /* Check the remote host's key against known_hosts. */ +- ret = check_host_key(s, s->inet->host, port, opts->host_key_check, errp); ++ ret = check_host_key(s, opts->host_key_check, errp); + if (ret < 0) { + goto err; + } + + /* Authenticate. */ +- ret = authenticate(s, s->user, errp); ++ ret = authenticate(s, errp); + if (ret < 0) { + goto err; + } + + /* Start SFTP. */ +- s->sftp = libssh2_sftp_init(s->session); ++ s->sftp = sftp_new(s->session); + if (!s->sftp) { +- session_error_setg(errp, s, "failed to initialize sftp handle"); ++ session_error_setg(errp, s, "failed to create sftp handle"); ++ ret = -EINVAL; ++ goto err; ++ } ++ ++ r = sftp_init(s->sftp); ++ if (r < 0) { ++ sftp_error_setg(errp, s, "failed to initialize sftp handle"); + ret = -EINVAL; + goto err; + } + + /* Open the remote file. */ + trace_ssh_connect_to_ssh(opts->path, ssh_flags, creat_mode); +- s->sftp_handle = libssh2_sftp_open(s->sftp, opts->path, ssh_flags, +- creat_mode); ++ s->sftp_handle = sftp_open(s->sftp, opts->path, ssh_flags, creat_mode); + if (!s->sftp_handle) { +- session_error_setg(errp, s, "failed to open remote file '%s'", +- opts->path); ++ sftp_error_setg(errp, s, "failed to open remote file '%s'", ++ opts->path); + ret = -EINVAL; + goto err; + } + +- r = libssh2_sftp_fstat(s->sftp_handle, &s->attrs); +- if (r < 0) { ++ /* Make sure the SFTP file is handled in blocking mode. */ ++ sftp_file_set_blocking(s->sftp_handle); ++ ++ s->attrs = sftp_fstat(s->sftp_handle); ++ if (!s->attrs) { + sftp_error_setg(errp, s, "failed to read file attributes"); + return -EINVAL; + } +@@ -727,21 +825,27 @@ static int connect_to_ssh(BDRVSSHState *s, BlockdevOptionsSsh *opts, + return 0; + + err: ++ if (s->attrs) { ++ sftp_attributes_free(s->attrs); ++ } ++ s->attrs = NULL; + if (s->sftp_handle) { +- libssh2_sftp_close(s->sftp_handle); ++ sftp_close(s->sftp_handle); + } + s->sftp_handle = NULL; + if (s->sftp) { +- libssh2_sftp_shutdown(s->sftp); ++ sftp_free(s->sftp); + } + s->sftp = NULL; + if (s->session) { +- libssh2_session_disconnect(s->session, +- "from qemu ssh client: " +- "error opening connection"); +- libssh2_session_free(s->session); ++ ssh_disconnect(s->session); ++ ssh_free(s->session); + } + s->session = NULL; ++ s->sock = -1; ++ if (new_sock >= 0) { ++ close(new_sock); ++ } + + return ret; + } +@@ -756,9 +860,11 @@ static int ssh_file_open(BlockDriverState *bs, QDict *options, int bdrv_flags, + + ssh_state_init(s); + +- ssh_flags = LIBSSH2_FXF_READ; ++ ssh_flags = 0; + if (bdrv_flags & BDRV_O_RDWR) { +- ssh_flags |= LIBSSH2_FXF_WRITE; ++ ssh_flags |= O_RDWR; ++ } else { ++ ssh_flags |= O_RDONLY; + } + + opts = ssh_parse_options(options, errp); +@@ -773,18 +879,13 @@ static int ssh_file_open(BlockDriverState *bs, QDict *options, int bdrv_flags, + } + + /* Go non-blocking. */ +- libssh2_session_set_blocking(s->session, 0); ++ ssh_set_blocking(s->session, 0); + + qapi_free_BlockdevOptionsSsh(opts); + + return 0; + + err: +- if (s->sock >= 0) { +- close(s->sock); +- } +- s->sock = -1; +- + qapi_free_BlockdevOptionsSsh(opts); + + return ret; +@@ -795,25 +896,25 @@ static int ssh_grow_file(BDRVSSHState *s, int64_t offset, Error **errp) + { + ssize_t ret; + char c[1] = { '\0' }; +- int was_blocking = libssh2_session_get_blocking(s->session); ++ int was_blocking = ssh_is_blocking(s->session); + + /* offset must be strictly greater than the current size so we do + * not overwrite anything */ +- assert(offset > 0 && offset > s->attrs.filesize); ++ assert(offset > 0 && offset > s->attrs->size); + +- libssh2_session_set_blocking(s->session, 1); ++ ssh_set_blocking(s->session, 1); + +- libssh2_sftp_seek64(s->sftp_handle, offset - 1); +- ret = libssh2_sftp_write(s->sftp_handle, c, 1); ++ sftp_seek64(s->sftp_handle, offset - 1); ++ ret = sftp_write(s->sftp_handle, c, 1); + +- libssh2_session_set_blocking(s->session, was_blocking); ++ ssh_set_blocking(s->session, was_blocking); + + if (ret < 0) { + sftp_error_setg(errp, s, "Failed to grow file"); + return -EIO; + } + +- s->attrs.filesize = offset; ++ s->attrs->size = offset; + return 0; + } + +@@ -841,8 +942,7 @@ static int ssh_co_create(BlockdevCreateOptions *options, Error **errp) + ssh_state_init(&s); + + ret = connect_to_ssh(&s, opts->location, +- LIBSSH2_FXF_READ|LIBSSH2_FXF_WRITE| +- LIBSSH2_FXF_CREAT|LIBSSH2_FXF_TRUNC, ++ O_RDWR | O_CREAT | O_TRUNC, + 0644, errp); + if (ret < 0) { + goto fail; +@@ -911,10 +1011,8 @@ static int ssh_has_zero_init(BlockDriverState *bs) + /* Assume false, unless we can positively prove it's true. */ + int has_zero_init = 0; + +- if (s->attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) { +- if (s->attrs.permissions & LIBSSH2_SFTP_S_IFREG) { +- has_zero_init = 1; +- } ++ if (s->attrs->type == SSH_FILEXFER_TYPE_REGULAR) { ++ has_zero_init = 1; + } + + return has_zero_init; +@@ -951,12 +1049,12 @@ static coroutine_fn void co_yield(BDRVSSHState *s, BlockDriverState *bs) + .co = qemu_coroutine_self() + }; + +- r = libssh2_session_block_directions(s->session); ++ r = ssh_get_poll_flags(s->session); + +- if (r & LIBSSH2_SESSION_BLOCK_INBOUND) { ++ if (r & SSH_READ_PENDING) { + rd_handler = restart_coroutine; + } +- if (r & LIBSSH2_SESSION_BLOCK_OUTBOUND) { ++ if (r & SSH_WRITE_PENDING) { + wr_handler = restart_coroutine; + } + +@@ -968,33 +1066,6 @@ static coroutine_fn void co_yield(BDRVSSHState *s, BlockDriverState *bs) + trace_ssh_co_yield_back(s->sock); + } + +-/* SFTP has a function `libssh2_sftp_seek64' which seeks to a position +- * in the remote file. Notice that it just updates a field in the +- * sftp_handle structure, so there is no network traffic and it cannot +- * fail. +- * +- * However, `libssh2_sftp_seek64' does have a catastrophic effect on +- * performance since it causes the handle to throw away all in-flight +- * reads and buffered readahead data. Therefore this function tries +- * to be intelligent about when to call the underlying libssh2 function. +- */ +-#define SSH_SEEK_WRITE 0 +-#define SSH_SEEK_READ 1 +-#define SSH_SEEK_FORCE 2 +- +-static void ssh_seek(BDRVSSHState *s, int64_t offset, int flags) +-{ +- bool op_read = (flags & SSH_SEEK_READ) != 0; +- bool force = (flags & SSH_SEEK_FORCE) != 0; +- +- if (force || op_read != s->offset_op_read || offset != s->offset) { +- trace_ssh_seek(offset); +- libssh2_sftp_seek64(s->sftp_handle, offset); +- s->offset = offset; +- s->offset_op_read = op_read; +- } +-} +- + static coroutine_fn int ssh_read(BDRVSSHState *s, BlockDriverState *bs, + int64_t offset, size_t size, + QEMUIOVector *qiov) +@@ -1006,7 +1077,8 @@ static coroutine_fn int ssh_read(BDRVSSHState *s, BlockDriverState *bs, + + trace_ssh_read(offset, size); + +- ssh_seek(s, offset, SSH_SEEK_READ); ++ trace_ssh_seek(offset); ++ sftp_seek64(s->sftp_handle, offset); + + /* This keeps track of the current iovec element ('i'), where we + * will write to next ('buf'), and the end of the current iovec +@@ -1016,35 +1088,35 @@ static coroutine_fn int ssh_read(BDRVSSHState *s, BlockDriverState *bs, + buf = i->iov_base; + end_of_vec = i->iov_base + i->iov_len; + +- /* libssh2 has a hard-coded limit of 2000 bytes per request, +- * although it will also do readahead behind our backs. Therefore +- * we may have to do repeated reads here until we have read 'size' +- * bytes. +- */ + for (got = 0; got < size; ) { ++ size_t request_read_size; + again: +- trace_ssh_read_buf(buf, end_of_vec - buf); +- r = libssh2_sftp_read(s->sftp_handle, buf, end_of_vec - buf); +- trace_ssh_read_return(r); ++ /* ++ * The size of SFTP packets is limited to 32K bytes, so limit ++ * the amount of data requested to 16K, as libssh currently ++ * does not handle multiple requests on its own. ++ */ ++ request_read_size = MIN(end_of_vec - buf, 16384); ++ trace_ssh_read_buf(buf, end_of_vec - buf, request_read_size); ++ r = sftp_read(s->sftp_handle, buf, request_read_size); ++ trace_ssh_read_return(r, sftp_get_error(s->sftp)); + +- if (r == LIBSSH2_ERROR_EAGAIN || r == LIBSSH2_ERROR_TIMEOUT) { ++ if (r == SSH_AGAIN) { + co_yield(s, bs); + goto again; + } +- if (r < 0) { +- sftp_error_trace(s, "read"); +- s->offset = -1; +- return -EIO; +- } +- if (r == 0) { ++ if (r == SSH_EOF || (r == 0 && sftp_get_error(s->sftp) == SSH_FX_EOF)) { + /* EOF: Short read so pad the buffer with zeroes and return it. */ + qemu_iovec_memset(qiov, got, 0, size - got); + return 0; + } ++ if (r <= 0) { ++ sftp_error_trace(s, "read"); ++ return -EIO; ++ } + + got += r; + buf += r; +- s->offset += r; + if (buf >= end_of_vec && got < size) { + i++; + buf = i->iov_base; +@@ -1081,7 +1153,8 @@ static int ssh_write(BDRVSSHState *s, BlockDriverState *bs, + + trace_ssh_write(offset, size); + +- ssh_seek(s, offset, SSH_SEEK_WRITE); ++ trace_ssh_seek(offset); ++ sftp_seek64(s->sftp_handle, offset); + + /* This keeps track of the current iovec element ('i'), where we + * will read from next ('buf'), and the end of the current iovec +@@ -1092,46 +1165,37 @@ static int ssh_write(BDRVSSHState *s, BlockDriverState *bs, + end_of_vec = i->iov_base + i->iov_len; + + for (written = 0; written < size; ) { ++ size_t request_write_size; + again: +- trace_ssh_write_buf(buf, end_of_vec - buf); +- r = libssh2_sftp_write(s->sftp_handle, buf, end_of_vec - buf); +- trace_ssh_write_return(r); ++ /* ++ * Avoid too large data packets, as libssh currently does not ++ * handle multiple requests on its own. ++ */ ++ request_write_size = MIN(end_of_vec - buf, 131072); ++ trace_ssh_write_buf(buf, end_of_vec - buf, request_write_size); ++ r = sftp_write(s->sftp_handle, buf, request_write_size); ++ trace_ssh_write_return(r, sftp_get_error(s->sftp)); + +- if (r == LIBSSH2_ERROR_EAGAIN || r == LIBSSH2_ERROR_TIMEOUT) { ++ if (r == SSH_AGAIN) { + co_yield(s, bs); + goto again; + } + if (r < 0) { + sftp_error_trace(s, "write"); +- s->offset = -1; + return -EIO; + } +- /* The libssh2 API is very unclear about this. A comment in +- * the code says "nothing was acked, and no EAGAIN was +- * received!" which apparently means that no data got sent +- * out, and the underlying channel didn't return any EAGAIN +- * indication. I think this is a bug in either libssh2 or +- * OpenSSH (server-side). In any case, forcing a seek (to +- * discard libssh2 internal buffers), and then trying again +- * works for me. +- */ +- if (r == 0) { +- ssh_seek(s, offset + written, SSH_SEEK_WRITE|SSH_SEEK_FORCE); +- co_yield(s, bs); +- goto again; +- } + + written += r; + buf += r; +- s->offset += r; + if (buf >= end_of_vec && written < size) { + i++; + buf = i->iov_base; + end_of_vec = i->iov_base + i->iov_len; + } + +- if (offset + written > s->attrs.filesize) +- s->attrs.filesize = offset + written; ++ if (offset + written > s->attrs->size) { ++ s->attrs->size = offset + written; ++ } + } + + return 0; +@@ -1164,24 +1228,24 @@ static void unsafe_flush_warning(BDRVSSHState *s, const char *what) + } + } + +-#ifdef HAS_LIBSSH2_SFTP_FSYNC ++#ifdef HAVE_LIBSSH_0_8 + + static coroutine_fn int ssh_flush(BDRVSSHState *s, BlockDriverState *bs) + { + int r; + + trace_ssh_flush(); ++ ++ if (!sftp_extension_supported(s->sftp, "fsync@openssh.com", "1")) { ++ unsafe_flush_warning(s, "OpenSSH >= 6.3"); ++ return 0; ++ } + again: +- r = libssh2_sftp_fsync(s->sftp_handle); +- if (r == LIBSSH2_ERROR_EAGAIN || r == LIBSSH2_ERROR_TIMEOUT) { ++ r = sftp_fsync(s->sftp_handle); ++ if (r == SSH_AGAIN) { + co_yield(s, bs); + goto again; + } +- if (r == LIBSSH2_ERROR_SFTP_PROTOCOL && +- libssh2_sftp_last_error(s->sftp) == LIBSSH2_FX_OP_UNSUPPORTED) { +- unsafe_flush_warning(s, "OpenSSH >= 6.3"); +- return 0; +- } + if (r < 0) { + sftp_error_trace(s, "fsync"); + return -EIO; +@@ -1202,25 +1266,25 @@ static coroutine_fn int ssh_co_flush(BlockDriverState *bs) + return ret; + } + +-#else /* !HAS_LIBSSH2_SFTP_FSYNC */ ++#else /* !HAVE_LIBSSH_0_8 */ + + static coroutine_fn int ssh_co_flush(BlockDriverState *bs) + { + BDRVSSHState *s = bs->opaque; + +- unsafe_flush_warning(s, "libssh2 >= 1.4.4"); ++ unsafe_flush_warning(s, "libssh >= 0.8.0"); + return 0; + } + +-#endif /* !HAS_LIBSSH2_SFTP_FSYNC */ ++#endif /* !HAVE_LIBSSH_0_8 */ + + static int64_t ssh_getlength(BlockDriverState *bs) + { + BDRVSSHState *s = bs->opaque; + int64_t length; + +- /* Note we cannot make a libssh2 call here. */ +- length = (int64_t) s->attrs.filesize; ++ /* Note we cannot make a libssh call here. */ ++ length = (int64_t) s->attrs->size; + trace_ssh_getlength(length); + + return length; +@@ -1237,12 +1301,12 @@ static int coroutine_fn ssh_co_truncate(BlockDriverState *bs, int64_t offset, + return -ENOTSUP; + } + +- if (offset < s->attrs.filesize) { ++ if (offset < s->attrs->size) { + error_setg(errp, "ssh driver does not support shrinking files"); + return -ENOTSUP; + } + +- if (offset == s->attrs.filesize) { ++ if (offset == s->attrs->size) { + return 0; + } + +@@ -1307,12 +1371,16 @@ static void bdrv_ssh_init(void) + { + int r; + +- r = libssh2_init(0); ++ r = ssh_init(); + if (r != 0) { +- fprintf(stderr, "libssh2 initialization failed, %d\n", r); ++ fprintf(stderr, "libssh initialization failed, %d\n", r); + exit(EXIT_FAILURE); + } + ++#if TRACE_LIBSSH != 0 ++ ssh_set_log_level(TRACE_LIBSSH); ++#endif ++ + bdrv_register(&bdrv_ssh); + } + +diff --git a/block/trace-events b/block/trace-events +index 23c9963..0017e33 100644 +--- a/block/trace-events ++++ b/block/trace-events +@@ -154,19 +154,21 @@ nvme_cmd_map_qiov_iov(void *s, int i, void *page, int pages) "s %p iov[%d] %p pa + # block/ssh.c + ssh_restart_coroutine(void *co) "co=%p" + ssh_flush(void) "fsync" +-ssh_check_host_key_knownhosts(const char *key) "host key OK: %s" ++ssh_check_host_key_knownhosts(void) "host key OK" + ssh_connect_to_ssh(char *path, int flags, int mode) "opening file %s flags=0x%x creat_mode=0%o" + ssh_co_yield(int sock, void *rd_handler, void *wr_handler) "s->sock=%d rd_handler=%p wr_handler=%p" + ssh_co_yield_back(int sock) "s->sock=%d - back" + ssh_getlength(int64_t length) "length=%" PRIi64 + ssh_co_create_opts(uint64_t size) "total_size=%" PRIu64 + ssh_read(int64_t offset, size_t size) "offset=%" PRIi64 " size=%zu" +-ssh_read_buf(void *buf, size_t size) "sftp_read buf=%p size=%zu" +-ssh_read_return(ssize_t ret) "sftp_read returned %zd" ++ssh_read_buf(void *buf, size_t size, size_t actual_size) "sftp_read buf=%p size=%zu (actual size=%zu)" ++ssh_read_return(ssize_t ret, int sftp_err) "sftp_read returned %zd (sftp error=%d)" + ssh_write(int64_t offset, size_t size) "offset=%" PRIi64 " size=%zu" +-ssh_write_buf(void *buf, size_t size) "sftp_write buf=%p size=%zu" +-ssh_write_return(ssize_t ret) "sftp_write returned %zd" ++ssh_write_buf(void *buf, size_t size, size_t actual_size) "sftp_write buf=%p size=%zu (actual size=%zu)" ++ssh_write_return(ssize_t ret, int sftp_err) "sftp_write returned %zd (sftp error=%d)" + ssh_seek(int64_t offset) "seeking to offset=%" PRIi64 ++ssh_auth_methods(int methods) "auth methods=0x%x" ++ssh_server_status(int status) "server status=%d" + + # ssh.c +-sftp_error(const char *op, const char *ssh_err, int ssh_err_code, unsigned long sftp_err_code) "%s failed: %s (libssh2 error code: %d, sftp error code: %lu)" ++sftp_error(const char *op, const char *ssh_err, int ssh_err_code, int sftp_err_code) "%s failed: %s (libssh error code: %d, sftp error code: %d)" +diff --git a/configure b/configure +index c9a1034..eefec38 100755 +--- a/configure ++++ b/configure +@@ -445,7 +445,7 @@ gcrypt_kdf="no" + vte="" + virglrenderer="" + tpm="yes" +-libssh2="" ++libssh="" + live_block_migration="yes" + numa="" + tcmalloc="no" +@@ -1334,9 +1334,9 @@ for opt do + ;; + --enable-tpm) tpm="yes" + ;; +- --disable-libssh2) libssh2="no" ++ --disable-libssh) libssh="no" + ;; +- --enable-libssh2) libssh2="yes" ++ --enable-libssh) libssh="yes" + ;; + --disable-live-block-migration) live_block_migration="no" + ;; +@@ -1669,7 +1669,7 @@ disabled with --disable-FEATURE, default is enabled if available: + coroutine-pool coroutine freelist (better performance) + glusterfs GlusterFS backend + tpm TPM support +- libssh2 ssh block device support ++ libssh ssh block device support + numa libnuma support + libxml2 for Parallels image format + tcmalloc tcmalloc support +@@ -3656,43 +3656,34 @@ EOF + fi + + ########################################## +-# libssh2 probe +-min_libssh2_version=1.2.8 +-if test "$libssh2" != "no" ; then +- if $pkg_config --atleast-version=$min_libssh2_version libssh2; then +- libssh2_cflags=$($pkg_config libssh2 --cflags) +- libssh2_libs=$($pkg_config libssh2 --libs) +- libssh2=yes ++# libssh probe ++if test "$libssh" != "no" ; then ++ if $pkg_config --exists libssh; then ++ libssh_cflags=$($pkg_config libssh --cflags) ++ libssh_libs=$($pkg_config libssh --libs) ++ libssh=yes + else +- if test "$libssh2" = "yes" ; then +- error_exit "libssh2 >= $min_libssh2_version required for --enable-libssh2" ++ if test "$libssh" = "yes" ; then ++ error_exit "libssh required for --enable-libssh" + fi +- libssh2=no ++ libssh=no + fi + fi + + ########################################## +-# libssh2_sftp_fsync probe ++# Check for libssh 0.8 ++# This is done like this instead of using the LIBSSH_VERSION_* and ++# SSH_VERSION_* macros because some distributions in the past shipped ++# snapshots of the future 0.8 from Git, and those snapshots did not ++# have updated version numbers (still referring to 0.7.0). + +-if test "$libssh2" = "yes"; then ++if test "$libssh" = "yes"; then + cat > $TMPC < +-#include +-#include +-int main(void) { +- LIBSSH2_SESSION *session; +- LIBSSH2_SFTP *sftp; +- LIBSSH2_SFTP_HANDLE *sftp_handle; +- session = libssh2_session_init (); +- sftp = libssh2_sftp_init (session); +- sftp_handle = libssh2_sftp_open (sftp, "/", 0, 0); +- libssh2_sftp_fsync (sftp_handle); +- return 0; +-} ++#include ++int main(void) { return ssh_get_server_publickey(NULL, NULL); } + EOF +- # libssh2_cflags/libssh2_libs defined in previous test. +- if compile_prog "$libssh2_cflags" "$libssh2_libs" ; then +- QEMU_CFLAGS="-DHAS_LIBSSH2_SFTP_FSYNC $QEMU_CFLAGS" ++ if compile_prog "$libssh_cflags" "$libssh_libs"; then ++ libssh_cflags="-DHAVE_LIBSSH_0_8 $libssh_cflags" + fi + fi + +@@ -5998,7 +5989,7 @@ echo "GlusterFS support $glusterfs" + echo "gcov $gcov_tool" + echo "gcov enabled $gcov" + echo "TPM support $tpm" +-echo "libssh2 support $libssh2" ++echo "libssh support $libssh" + echo "TPM passthrough $tpm_passthrough" + echo "TPM emulator $tpm_emulator" + echo "QOM debugging $qom_cast_debug" +@@ -6664,10 +6655,10 @@ if test "$glusterfs_iocb_has_stat" = "yes" ; then + echo "CONFIG_GLUSTERFS_IOCB_HAS_STAT=y" >> $config_host_mak + fi + +-if test "$libssh2" = "yes" ; then +- echo "CONFIG_LIBSSH2=m" >> $config_host_mak +- echo "LIBSSH2_CFLAGS=$libssh2_cflags" >> $config_host_mak +- echo "LIBSSH2_LIBS=$libssh2_libs" >> $config_host_mak ++if test "$libssh" = "yes" ; then ++ echo "CONFIG_LIBSSH=m" >> $config_host_mak ++ echo "LIBSSH_CFLAGS=$libssh_cflags" >> $config_host_mak ++ echo "LIBSSH_LIBS=$libssh_libs" >> $config_host_mak + fi + + if test "$live_block_migration" = "yes" ; then +diff --git a/docs/qemu-block-drivers.texi b/docs/qemu-block-drivers.texi +index e0d752a..5004dec 100644 +--- a/docs/qemu-block-drivers.texi ++++ b/docs/qemu-block-drivers.texi +@@ -782,7 +782,7 @@ print a warning when @code{fsync} is not supported: + + warning: ssh server @code{ssh.example.com:22} does not support fsync + +-With sufficiently new versions of libssh2 and OpenSSH, @code{fsync} is ++With sufficiently new versions of libssh and OpenSSH, @code{fsync} is + supported. + + @node disk_images_nvme +diff --git a/tests/docker/dockerfiles/debian-win32-cross.docker b/tests/docker/dockerfiles/debian-win32-cross.docker +index dd021f2..0a4970c 100644 +--- a/tests/docker/dockerfiles/debian-win32-cross.docker ++++ b/tests/docker/dockerfiles/debian-win32-cross.docker +@@ -15,7 +15,6 @@ RUN DEBIAN_FRONTEND=noninteractive eatmydata \ + mxe-$TARGET-w64-mingw32.shared-curl \ + mxe-$TARGET-w64-mingw32.shared-glib \ + mxe-$TARGET-w64-mingw32.shared-libgcrypt \ +- mxe-$TARGET-w64-mingw32.shared-libssh2 \ + mxe-$TARGET-w64-mingw32.shared-libusb1 \ + mxe-$TARGET-w64-mingw32.shared-lzo \ + mxe-$TARGET-w64-mingw32.shared-nettle \ +diff --git a/tests/docker/dockerfiles/debian-win64-cross.docker b/tests/docker/dockerfiles/debian-win64-cross.docker +index 4542bcc..b27985b 100644 +--- a/tests/docker/dockerfiles/debian-win64-cross.docker ++++ b/tests/docker/dockerfiles/debian-win64-cross.docker +@@ -15,7 +15,6 @@ RUN DEBIAN_FRONTEND=noninteractive eatmydata \ + mxe-$TARGET-w64-mingw32.shared-curl \ + mxe-$TARGET-w64-mingw32.shared-glib \ + mxe-$TARGET-w64-mingw32.shared-libgcrypt \ +- mxe-$TARGET-w64-mingw32.shared-libssh2 \ + mxe-$TARGET-w64-mingw32.shared-libusb1 \ + mxe-$TARGET-w64-mingw32.shared-lzo \ + mxe-$TARGET-w64-mingw32.shared-nettle \ +diff --git a/tests/docker/dockerfiles/fedora.docker b/tests/docker/dockerfiles/fedora.docker +index b706f42..2dd598d 100644 +--- a/tests/docker/dockerfiles/fedora.docker ++++ b/tests/docker/dockerfiles/fedora.docker +@@ -6,18 +6,18 @@ ENV PACKAGES \ + bluez-libs-devel brlapi-devel bzip2-devel \ + device-mapper-multipath-devel glusterfs-api-devel gnutls-devel \ + gtk3-devel libattr-devel libcap-devel libcap-ng-devel libcurl-devel \ +- libjpeg-devel libpng-devel librbd-devel libssh2-devel libusbx-devel \ ++ libjpeg-devel libpng-devel librbd-devel libssh-devel libusbx-devel \ + libxml2-devel lzo-devel ncurses-devel nettle-devel nss-devel \ + numactl-devel SDL2-devel snappy-devel spice-server-devel \ + systemtap-sdt-devel usbredir-devel virglrenderer-devel vte3-devel \ + xen-devel \ + mingw32-pixman mingw32-glib2 mingw32-gmp mingw32-SDL mingw32-pkg-config \ + mingw32-gtk2 mingw32-gtk3 mingw32-gnutls mingw32-nettle mingw32-libtasn1 \ +- mingw32-libjpeg-turbo mingw32-libpng mingw32-curl mingw32-libssh2 \ ++ mingw32-libjpeg-turbo mingw32-libpng mingw32-curl \ + mingw32-bzip2 \ + mingw64-pixman mingw64-glib2 mingw64-gmp mingw64-SDL mingw64-pkg-config \ + mingw64-gtk2 mingw64-gtk3 mingw64-gnutls mingw64-nettle mingw64-libtasn1 \ +- mingw64-libjpeg-turbo mingw64-libpng mingw64-curl mingw64-libssh2 \ ++ mingw64-libjpeg-turbo mingw64-libpng mingw64-curl \ + mingw64-bzip2 + ENV QEMU_CONFIGURE_OPTS --python=/usr/bin/python3 + +diff --git a/tests/docker/dockerfiles/ubuntu.docker b/tests/docker/dockerfiles/ubuntu.docker +index dabbf2a..be37ff1 100644 +--- a/tests/docker/dockerfiles/ubuntu.docker ++++ b/tests/docker/dockerfiles/ubuntu.docker +@@ -4,7 +4,7 @@ RUN echo "deb http://archive.ubuntu.com/ubuntu/ trusty universe multiverse" >> \ + RUN apt-get update + ENV PACKAGES flex bison \ + libusb-1.0-0-dev libiscsi-dev librados-dev libncurses5-dev libncursesw5-dev \ +- libseccomp-dev libgnutls-dev libssh2-1-dev libspice-server-dev \ ++ libseccomp-dev libgnutls-dev libssh-dev libspice-server-dev \ + libspice-protocol-dev libnss3-dev libfdt-dev \ + libgtk-3-dev libvte-2.91-dev libsdl1.2-dev libpng12-dev libpixman-1-dev \ + libvdeplug-dev liblzo2-dev libsnappy-dev libbz2-dev libxen-dev librdmacm-dev libibverbs-dev \ +diff --git a/tests/qemu-iotests/207 b/tests/qemu-iotests/207 +index aaad656..219f1a6 100755 +--- a/tests/qemu-iotests/207 ++++ b/tests/qemu-iotests/207 +@@ -106,12 +106,49 @@ with iotests.FilePath('t.img') as disk_path, \ + + iotests.img_info_log(remote_path) + +- md5_key = subprocess.check_output( +- 'ssh-keyscan -t rsa 127.0.0.1 2>/dev/null | grep -v "\\^#" | ' + +- 'cut -d" " -f3 | base64 -d | md5sum -b | cut -d" " -f1', +- shell=True).rstrip().decode('ascii') ++ keys = subprocess.check_output( ++ 'ssh-keyscan 127.0.0.1 2>/dev/null | grep -v "\\^#" | ' + ++ 'cut -d" " -f3', ++ shell=True).rstrip().decode('ascii').split('\n') ++ ++ # Mappings of base64 representations to digests ++ md5_keys = {} ++ sha1_keys = {} ++ ++ for key in keys: ++ md5_keys[key] = subprocess.check_output( ++ 'echo %s | base64 -d | md5sum -b | cut -d" " -f1' % key, ++ shell=True).rstrip().decode('ascii') ++ ++ sha1_keys[key] = subprocess.check_output( ++ 'echo %s | base64 -d | sha1sum -b | cut -d" " -f1' % key, ++ shell=True).rstrip().decode('ascii') + + vm.launch() ++ ++ # Find correct key first ++ matching_key = None ++ for key in keys: ++ result = vm.qmp('blockdev-add', ++ driver='ssh', node_name='node0', path=disk_path, ++ server={ ++ 'host': '127.0.0.1', ++ 'port': '22', ++ }, host_key_check={ ++ 'mode': 'hash', ++ 'type': 'md5', ++ 'hash': md5_keys[key], ++ }) ++ ++ if 'error' not in result: ++ vm.qmp('blockdev-del', node_name='node0') ++ matching_key = key ++ break ++ ++ if matching_key is None: ++ vm.shutdown() ++ iotests.notrun('Did not find a key that fits 127.0.0.1') ++ + blockdev_create(vm, { 'driver': 'ssh', + 'location': { + 'path': disk_path, +@@ -136,7 +173,7 @@ with iotests.FilePath('t.img') as disk_path, \ + 'host-key-check': { + 'mode': 'hash', + 'type': 'md5', +- 'hash': md5_key, ++ 'hash': md5_keys[matching_key], + } + }, + 'size': 8388608 }) +@@ -144,11 +181,6 @@ with iotests.FilePath('t.img') as disk_path, \ + + iotests.img_info_log(remote_path) + +- sha1_key = subprocess.check_output( +- 'ssh-keyscan -t rsa 127.0.0.1 2>/dev/null | grep -v "\\^#" | ' + +- 'cut -d" " -f3 | base64 -d | sha1sum -b | cut -d" " -f1', +- shell=True).rstrip().decode('ascii') +- + vm.launch() + blockdev_create(vm, { 'driver': 'ssh', + 'location': { +@@ -174,7 +206,7 @@ with iotests.FilePath('t.img') as disk_path, \ + 'host-key-check': { + 'mode': 'hash', + 'type': 'sha1', +- 'hash': sha1_key, ++ 'hash': sha1_keys[matching_key], + } + }, + 'size': 4194304 }) +diff --git a/tests/qemu-iotests/207.out b/tests/qemu-iotests/207.out +index 789b465..48318ce 100644 +--- a/tests/qemu-iotests/207.out ++++ b/tests/qemu-iotests/207.out +@@ -68,7 +68,7 @@ virtual size: 4.0M (4194304 bytes) + + {"execute": "blockdev-create", "arguments": {"job_id": "job0", "options": {"driver": "ssh", "location": {"host-key-check": {"mode": "none"}, "path": "/this/is/not/an/existing/path", "server": {"host": "127.0.0.1", "port": "22"}}, "size": 4194304}}} + {"return": {}} +-Job failed: failed to open remote file '/this/is/not/an/existing/path': Failed opening remote file (libssh2 error code: -31) ++Job failed: failed to open remote file '/this/is/not/an/existing/path': SFTP server: No such file (libssh error code: 1, sftp error code: 2) + {"execute": "job-dismiss", "arguments": {"id": "job0"}} + {"return": {}} + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-tap-set-vhostfd-passed-from-qemu-cli-to-non-blocking.patch b/SOURCES/kvm-tap-set-vhostfd-passed-from-qemu-cli-to-non-blocking.patch new file mode 100644 index 0000000..1bf8142 --- /dev/null +++ b/SOURCES/kvm-tap-set-vhostfd-passed-from-qemu-cli-to-non-blocking.patch @@ -0,0 +1,66 @@ +From 689a30f211939282ce6de9d3597c0fc6ad674a6e Mon Sep 17 00:00:00 2001 +From: Laszlo Ersek +Date: Fri, 26 Jul 2019 11:29:51 +0100 +Subject: [PATCH 13/14] tap: set vhostfd passed from qemu cli to non-blocking + +RH-Author: Laszlo Ersek +Message-id: <20190726112951.11834-2-lersek@redhat.com> +Patchwork-id: 89734 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 1/1] tap: set vhostfd passed from qemu cli to non-blocking +Bugzilla: 1732642 +RH-Acked-by: Xiao Wang +RH-Acked-by: Stefano Garzarella +RH-Acked-by: John Snow + +From: Brijesh Singh + +A guest boot hangs while probing the network interface when +iommu_platform=on is used. + +The following qemu cli hangs without this patch: + +# $QEMU \ + -netdev tap,fd=3,id=hostnet0,vhost=on,vhostfd=4 3<>/dev/tap67 4<>/dev/host-net \ + -device virtio-net-pci,netdev=hostnet0,id=net0,iommu_platform=on,disable-legacy=on \ + ... + +Commit: c471ad0e9bd46 (vhost_net: device IOTLB support) took care of +setting vhostfd to non-blocking when QEMU opens /dev/host-net but if +the fd is passed from qemu cli then we need to ensure that fd is set +to non-blocking. + +Fixes: c471ad0e9bd46 ("vhost_net: device IOTLB support") +Cc: qemu-stable@nongnu.org +Cc: Michael S. Tsirkin +Cc: Jason Wang +Signed-off-by: Brijesh Singh +Signed-off-by: Jason Wang +(cherry picked from commit d542800d1edc62f63f8a29cfa6bdd1a9536ae11c) +Signed-off-by: Danilo C. L. de Paula +--- + net/tap.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/tap.c b/net/tap.c +index 2b3a36f..89c4e19 100644 +--- a/net/tap.c ++++ b/net/tap.c +@@ -40,6 +40,7 @@ + #include "qemu-common.h" + #include "qemu/cutils.h" + #include "qemu/error-report.h" ++#include "qemu/sockets.h" + + #include "net/tap.h" + +@@ -693,6 +694,7 @@ static void net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer, + } + return; + } ++ qemu_set_nonblock(vhostfd); + } else { + vhostfd = open("/dev/vhost-net", O_RDWR); + if (vhostfd < 0) { +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-Disable-MPX-support-on-named-CPU-models.patch b/SOURCES/kvm-target-i386-Disable-MPX-support-on-named-CPU-models.patch new file mode 100644 index 0000000..a8dfc93 --- /dev/null +++ b/SOURCES/kvm-target-i386-Disable-MPX-support-on-named-CPU-models.patch @@ -0,0 +1,59 @@ +From defbb3b33db7fcbc9da20c1350ce90a6b5e279bb Mon Sep 17 00:00:00 2001 +From: "plai@redhat.com" +Date: Mon, 1 Jul 2019 16:17:32 +0100 +Subject: [PATCH 03/39] target/i386: Disable MPX support on named CPU models +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: plai@redhat.com +Message-id: <1561997854-9646-4-git-send-email-plai@redhat.com> +Patchwork-id: 89333 +O-Subject: [RHEL8.1 qemu-kvm PATCH v6 3/5] target/i386: Disable MPX support on named CPU models +Bugzilla: 1629906 +RH-Acked-by: Eduardo Habkost +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Bandan Das + +From: Paolo Bonzini + +MPX support is being phased out by Intel; GCC has dropped it, Linux +is also going to do that. Even though KVM will have special code +to support MPX after the kernel proper stops enabling it in XCR0, +we probably also want to deprecate that in a few years. As a start, +do not enable it by default for any named CPU model starting with +the 4.0 machine types; this include Skylake, Icelake and Cascadelake. + +Signed-off-by: Paolo Bonzini +Message-Id: <20181220121100.21554-1-pbonzini@redhat.com> +Reviewed-by:   Wainer dos Santos Moschetta +Signed-off-by: Eduardo Habkost +(cherry picked from commit ecb85fe48cacb2f8740186e81f2f38a2e02bd963) +Signed-off-by: Paul Lai +Signed-off-by: Danilo C. L. de Paula + +Conflicts: + hw/i386/pc.c changes to include/hw/i386/pc.h + target/i386/cpu.c + +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index c4b31eb..094f8a1 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -2512,7 +2512,7 @@ static X86CPUDefinition builtin_x86_defs[] = { + CPUID_7_0_EBX_HLE | CPUID_7_0_EBX_AVX2 | CPUID_7_0_EBX_SMEP | + CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ERMS | CPUID_7_0_EBX_INVPCID | + CPUID_7_0_EBX_RTM | CPUID_7_0_EBX_RDSEED | CPUID_7_0_EBX_ADX | +- CPUID_7_0_EBX_SMAP | CPUID_7_0_EBX_MPX | CPUID_7_0_EBX_CLWB | ++ CPUID_7_0_EBX_SMAP | CPUID_7_0_EBX_CLWB | + CPUID_7_0_EBX_AVX512F | CPUID_7_0_EBX_AVX512DQ | + CPUID_7_0_EBX_AVX512BW | CPUID_7_0_EBX_AVX512CD | + CPUID_7_0_EBX_AVX512VL | CPUID_7_0_EBX_CLFLUSHOPT | +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-add-MDS-NO-feature.patch b/SOURCES/kvm-target-i386-add-MDS-NO-feature.patch index ad49667..e465737 100644 --- a/SOURCES/kvm-target-i386-add-MDS-NO-feature.patch +++ b/SOURCES/kvm-target-i386-add-MDS-NO-feature.patch @@ -1,18 +1,20 @@ -From 43f2e3a36586d9e7e12e5638ae19837f726490ff Mon Sep 17 00:00:00 2001 -From: "plai@redhat.com" -Date: Tue, 20 Aug 2019 00:24:40 +0100 -Subject: [PATCH 9/9] target/i386: add MDS-NO feature - -RH-Author: plai@redhat.com -Message-id: <1566260680-20995-10-git-send-email-plai@redhat.com> -Patchwork-id: 90071 -O-Subject: [RHEL8.0 qemu-kvm PATCH v3 9/9] target/i386: add MDS-NO feature -Bugzilla: 1718235 -RH-Acked-by: Eduardo Habkost -RH-Acked-by: John Snow -RH-Acked-by: Igor Mammedov - +From 354818b02978df635ea030462223283529711970 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini +Date: Sun, 23 Jun 2019 15:19:12 +0200 +Subject: [PATCH 1/4] target/i386: add MDS-NO feature + +RH-Author: Paolo Bonzini +Message-id: <20190623151912.7829-1-pbonzini@redhat.com> +Patchwork-id: 88872 +O-Subject: [RHEL-8.1.0 PATCH qemu-kvm] target/i386: add MDS-NO feature +Bugzilla: 1714792 +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Stefano Garzarella +RH-Acked-by: Miroslav Rezanina + +Bugzilla: 1714792 + +Brew build: 22307357 Microarchitectural Data Sampling is a hardware vulnerability which allows unprivileged speculative access to data which is available in various CPU @@ -26,14 +28,13 @@ Signed-off-by: Paolo Bonzini Message-Id: <20190516185320.28340-1-pbonzini@redhat.com> Signed-off-by: Eduardo Habkost (cherry picked from commit 20140a82c67467f53814ca197403d5e1b561a5e5) -Signed-off-by: Paul Lai -Signed-off-by: Danilo C. L. de Paula +Signed-off-by: Miroslav Rezanina --- target/i386/cpu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/i386/cpu.c b/target/i386/cpu.c -index 365c92c..07ec8bc 100644 +index 4411012..5c10093 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -1147,7 +1147,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { diff --git a/SOURCES/kvm-target-i386-define-md-clear-bit-rhev.patch b/SOURCES/kvm-target-i386-define-md-clear-bit-rhev.patch deleted file mode 100644 index 881d3af..0000000 --- a/SOURCES/kvm-target-i386-define-md-clear-bit-rhev.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 8f9887acd04e8db0bebd0ad3fe1cf5d7294abdfd Mon Sep 17 00:00:00 2001 -From: Paolo Bonzini -Date: Sat, 2 Mar 2019 00:07:10 +0100 -Subject: target/i386: define md-clear bit - -Message-id: <20190301230710.692-1-pbonzini@redhat.com> -O-Subject: [qemu PATCH] target/i386: define md-clear bit - -md-clear is a new CPUID bit which is set when microcode provides the -mechanism to invoke a flush of various exploitable CPU buffers by invoking -the VERW instruction. - -Signed-off-by: Paolo Bonzini - ---- - - target/i386/cpu.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/target/i386/cpu.c b/target/i386/cpu.c -index d990070c59..16da90562c 100644 ---- a/target/i386/cpu.c -+++ b/target/i386/cpu.c -@@ -1075,7 +1075,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { - .feat_names = { - NULL, NULL, "avx512-4vnniw", "avx512-4fmaps", - NULL, NULL, NULL, NULL, -- NULL, NULL, NULL, NULL, -+ NULL, NULL, "md-clear", NULL, - NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, --- -2.20.1 - diff --git a/SOURCES/kvm-target-i386-define-md-clear-bit.patch b/SOURCES/kvm-target-i386-define-md-clear-bit.patch new file mode 100644 index 0000000..cbf88d3 --- /dev/null +++ b/SOURCES/kvm-target-i386-define-md-clear-bit.patch @@ -0,0 +1,55 @@ +From 60e3b6eb1a611ddfb35841881689f0f6e02db3d1 Mon Sep 17 00:00:00 2001 +From: Danilo de Paula +Date: Mon, 20 May 2019 18:29:57 +0100 +Subject: [PATCH 5/5] target/i386: define md-clear bit + +RH-Author: Danilo de Paula +Message-id: <20190520182957.26425-1-ddepaula@redhat.com> +Patchwork-id: 88110 +O-Subject: [RHEL-8 + RHEL-AV qemu-kvm PATCH] target/i386: define md-clear bit +Bugzilla: 1703302 1703308 + +From: Paolo Bonzini + +BZ: 1703310 +BZ: 1703304 +BZ: 1703297 +BZ: 1707274 +branch: rhel-av-8.1.0/master-4.0.0 + +BZ: 1705851 +BZ: 1704542 +BZ: 1704538 +BZ: 1704534 +branch: rhel-av-8.0.1 + +BZ: 1703308 +BZ: 1703302 +branch: rhel-8.1.0 + +md-clear is a new CPUID bit which is set when microcode provides the +mechanism to invoke a flush of various exploitable CPU buffers by invoking +the VERW instruction. + +Signed-off-by: Paolo Bonzini +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index 77be7e8..e9025cd 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -1040,7 +1040,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { + .feat_names = { + NULL, NULL, "avx512-4vnniw", "avx512-4fmaps", + NULL, NULL, NULL, NULL, +- NULL, NULL, NULL, NULL, ++ NULL, NULL, "md-clear", NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-kvm-Add-nested-migration-blocker-only-wh.patch b/SOURCES/kvm-target-i386-kvm-Add-nested-migration-blocker-only-wh.patch new file mode 100644 index 0000000..b50ba57 --- /dev/null +++ b/SOURCES/kvm-target-i386-kvm-Add-nested-migration-blocker-only-wh.patch @@ -0,0 +1,60 @@ +From a99cae3466f0fae8a46c58f4e07ed6b6a481a0a5 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Mon, 22 Jul 2019 18:22:17 +0100 +Subject: [PATCH 36/39] target/i386: kvm: Add nested migration blocker only + when kernel lacks required capabilities + +RH-Author: Paolo Bonzini +Message-id: <20190722182220.19374-16-pbonzini@redhat.com> +Patchwork-id: 89632 +O-Subject: [RHEL-8.1.0 PATCH qemu-kvm v3 15/18] target/i386: kvm: Add nested migration blocker only when kernel lacks required capabilities +Bugzilla: 1689269 +RH-Acked-by: Peter Xu +RH-Acked-by: Laurent Vivier +RH-Acked-by: Dr. David Alan Gilbert + +From: Liran Alon + +Previous commits have added support for migration of nested virtualization +workloads. This was done by utilising two new KVM capabilities: +KVM_CAP_NESTED_STATE and KVM_CAP_EXCEPTION_PAYLOAD. Both which are +required in order to correctly migrate such workloads. + +Therefore, change code to add a migration blocker for vCPUs exposed with +Intel VMX or AMD SVM in case one of these kernel capabilities is +missing. + +Signed-off-by: Liran Alon +Reviewed-by: Maran Wilson +Message-Id: <20190619162140.133674-11-liran.alon@oracle.com> +Signed-off-by: Paolo Bonzini +(cherry picked from commit 12604092e26cdace44c901bc429e7e4c7c3e0cab) +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/kvm.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/target/i386/kvm.c b/target/i386/kvm.c +index aa2d589..0619aba 100644 +--- a/target/i386/kvm.c ++++ b/target/i386/kvm.c +@@ -1159,9 +1159,14 @@ int kvm_arch_init_vcpu(CPUState *cs) + !!(c->ecx & CPUID_EXT_SMX); + } + +- if (cpu_has_vmx(env) && !nested_virt_mig_blocker) { ++ if (cpu_has_vmx(env) && !nested_virt_mig_blocker && ++ ((kvm_max_nested_state_length() <= 0) || !has_exception_payload)) { + error_setg(&nested_virt_mig_blocker, +- "Nested virtualization does not support live migration yet"); ++ "Kernel do not provide required capabilities for " ++ "nested virtualization migration. " ++ "(CAP_NESTED_STATE=%d, CAP_EXCEPTION_PAYLOAD=%d)", ++ kvm_max_nested_state_length() > 0, ++ has_exception_payload); + r = migrate_add_blocker(nested_virt_mig_blocker, &local_err); + if (local_err) { + error_report_err(local_err); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-kvm-Add-support-for-KVM_CAP_EXCEPTION_PA.patch b/SOURCES/kvm-target-i386-kvm-Add-support-for-KVM_CAP_EXCEPTION_PA.patch new file mode 100644 index 0000000..53e4621 --- /dev/null +++ b/SOURCES/kvm-target-i386-kvm-Add-support-for-KVM_CAP_EXCEPTION_PA.patch @@ -0,0 +1,451 @@ +From 05a54f3fc44598f917d72a1f2570c43ec042cdb8 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Mon, 22 Jul 2019 18:22:16 +0100 +Subject: [PATCH 35/39] target/i386: kvm: Add support for + KVM_CAP_EXCEPTION_PAYLOAD + +RH-Author: Paolo Bonzini +Message-id: <20190722182220.19374-15-pbonzini@redhat.com> +Patchwork-id: 89631 +O-Subject: [RHEL-8.1.0 PATCH qemu-kvm v3 14/18] target/i386: kvm: Add support for KVM_CAP_EXCEPTION_PAYLOAD +Bugzilla: 1689269 +RH-Acked-by: Peter Xu +RH-Acked-by: Laurent Vivier +RH-Acked-by: Dr. David Alan Gilbert + +From: Liran Alon + +Kernel commit c4f55198c7c2 ("kvm: x86: Introduce KVM_CAP_EXCEPTION_PAYLOAD") +introduced a new KVM capability which allows userspace to correctly +distinguish between pending and injected exceptions. + +This distinguish is important in case of nested virtualization scenarios +because a L2 pending exception can still be intercepted by the L1 hypervisor +while a L2 injected exception cannot. + +Furthermore, when an exception is attempted to be injected by QEMU, +QEMU should specify the exception payload (CR2 in case of #PF or +DR6 in case of #DB) instead of having the payload already delivered in +the respective vCPU register. Because in case exception is injected to +L2 guest and is intercepted by L1 hypervisor, then payload needs to be +reported to L1 intercept (VMExit handler) while still preserving +respective vCPU register unchanged. + +This commit adds support for QEMU to properly utilise this new KVM +capability (KVM_CAP_EXCEPTION_PAYLOAD). + +Reviewed-by: Nikita Leshenko +Signed-off-by: Liran Alon +Message-Id: <20190619162140.133674-10-liran.alon@oracle.com> +Signed-off-by: Paolo Bonzini +(cherry picked from commit fd13f23b8c95311eff74426921557eee592b0ed3) +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.c | 6 ++- + target/i386/cpu.h | 6 ++- + target/i386/hvf/hvf.c | 10 +++-- + target/i386/hvf/x86hvf.c | 4 +- + target/i386/kvm.c | 101 +++++++++++++++++++++++++++++++++++++++-------- + target/i386/machine.c | 84 ++++++++++++++++++++++++++++++++++++++- + 6 files changed, 187 insertions(+), 24 deletions(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index bd0b784..f71b044 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -4645,7 +4645,11 @@ static void x86_cpu_reset(CPUState *s) + memset(env->mtrr_fixed, 0, sizeof(env->mtrr_fixed)); + + env->interrupt_injected = -1; +- env->exception_injected = -1; ++ env->exception_nr = -1; ++ env->exception_pending = 0; ++ env->exception_injected = 0; ++ env->exception_has_payload = false; ++ env->exception_payload = 0; + env->nmi_injected = false; + #if !defined(CONFIG_USER_ONLY) + /* We hard-wire the BSP to the first CPU. */ +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index 86f3d98..d120f62 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -1325,10 +1325,14 @@ typedef struct CPUX86State { + + /* For KVM */ + uint32_t mp_state; +- int32_t exception_injected; ++ int32_t exception_nr; + int32_t interrupt_injected; + uint8_t soft_interrupt; ++ uint8_t exception_pending; ++ uint8_t exception_injected; + uint8_t has_error_code; ++ uint8_t exception_has_payload; ++ uint64_t exception_payload; + uint32_t ins_len; + uint32_t sipi_vector; + bool tsc_valid; +diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c +index c367539..acc0bb9 100644 +--- a/target/i386/hvf/hvf.c ++++ b/target/i386/hvf/hvf.c +@@ -617,7 +617,9 @@ static void hvf_store_events(CPUState *cpu, uint32_t ins_len, uint64_t idtvec_in + X86CPU *x86_cpu = X86_CPU(cpu); + CPUX86State *env = &x86_cpu->env; + +- env->exception_injected = -1; ++ env->exception_nr = -1; ++ env->exception_pending = 0; ++ env->exception_injected = 0; + env->interrupt_injected = -1; + env->nmi_injected = false; + if (idtvec_info & VMCS_IDT_VEC_VALID) { +@@ -631,7 +633,8 @@ static void hvf_store_events(CPUState *cpu, uint32_t ins_len, uint64_t idtvec_in + break; + case VMCS_IDT_VEC_HWEXCEPTION: + case VMCS_IDT_VEC_SWEXCEPTION: +- env->exception_injected = idtvec_info & VMCS_IDT_VEC_VECNUM; ++ env->exception_nr = idtvec_info & VMCS_IDT_VEC_VECNUM; ++ env->exception_injected = 1; + break; + case VMCS_IDT_VEC_PRIV_SWEXCEPTION: + default: +@@ -925,7 +928,8 @@ int hvf_vcpu_exec(CPUState *cpu) + macvm_set_rip(cpu, rip + ins_len); + break; + case VMX_REASON_VMCALL: +- env->exception_injected = EXCP0D_GPF; ++ env->exception_nr = EXCP0D_GPF; ++ env->exception_injected = 1; + env->has_error_code = true; + env->error_code = 0; + break; +diff --git a/target/i386/hvf/x86hvf.c b/target/i386/hvf/x86hvf.c +index 6c88939..f0e58a8 100644 +--- a/target/i386/hvf/x86hvf.c ++++ b/target/i386/hvf/x86hvf.c +@@ -362,8 +362,8 @@ bool hvf_inject_interrupts(CPUState *cpu_state) + if (env->interrupt_injected != -1) { + vector = env->interrupt_injected; + intr_type = VMCS_INTR_T_SWINTR; +- } else if (env->exception_injected != -1) { +- vector = env->exception_injected; ++ } else if (env->exception_nr != -1) { ++ vector = env->exception_nr; + if (vector == EXCP03_INT3 || vector == EXCP04_INTO) { + intr_type = VMCS_INTR_T_SWEXCEPTION; + } else { +diff --git a/target/i386/kvm.c b/target/i386/kvm.c +index ddceb7d..aa2d589 100644 +--- a/target/i386/kvm.c ++++ b/target/i386/kvm.c +@@ -103,6 +103,7 @@ static uint32_t num_architectural_pmu_fixed_counters; + static int has_xsave; + static int has_xcrs; + static int has_pit_state2; ++static int has_exception_payload; + + static bool has_msr_mcg_ext_ctl; + +@@ -569,15 +570,56 @@ void kvm_arch_on_sigbus_vcpu(CPUState *c, int code, void *addr) + /* Hope we are lucky for AO MCE */ + } + ++static void kvm_reset_exception(CPUX86State *env) ++{ ++ env->exception_nr = -1; ++ env->exception_pending = 0; ++ env->exception_injected = 0; ++ env->exception_has_payload = false; ++ env->exception_payload = 0; ++} ++ ++static void kvm_queue_exception(CPUX86State *env, ++ int32_t exception_nr, ++ uint8_t exception_has_payload, ++ uint64_t exception_payload) ++{ ++ assert(env->exception_nr == -1); ++ assert(!env->exception_pending); ++ assert(!env->exception_injected); ++ assert(!env->exception_has_payload); ++ ++ env->exception_nr = exception_nr; ++ ++ if (has_exception_payload) { ++ env->exception_pending = 1; ++ ++ env->exception_has_payload = exception_has_payload; ++ env->exception_payload = exception_payload; ++ } else { ++ env->exception_injected = 1; ++ ++ if (exception_nr == EXCP01_DB) { ++ assert(exception_has_payload); ++ env->dr[6] = exception_payload; ++ } else if (exception_nr == EXCP0E_PAGE) { ++ assert(exception_has_payload); ++ env->cr[2] = exception_payload; ++ } else { ++ assert(!exception_has_payload); ++ } ++ } ++} ++ + static int kvm_inject_mce_oldstyle(X86CPU *cpu) + { + CPUX86State *env = &cpu->env; + +- if (!kvm_has_vcpu_events() && env->exception_injected == EXCP12_MCHK) { ++ if (!kvm_has_vcpu_events() && env->exception_nr == EXCP12_MCHK) { + unsigned int bank, bank_num = env->mcg_cap & 0xff; + struct kvm_x86_mce mce; + +- env->exception_injected = -1; ++ kvm_reset_exception(env); + + /* + * There must be at least one bank in use if an MCE is pending. +@@ -1458,6 +1500,16 @@ int kvm_arch_init(MachineState *ms, KVMState *s) + has_pit_state2 = kvm_check_extension(s, KVM_CAP_PIT_STATE2); + #endif + ++ has_exception_payload = kvm_check_extension(s, KVM_CAP_EXCEPTION_PAYLOAD); ++ if (has_exception_payload) { ++ ret = kvm_vm_enable_cap(s, KVM_CAP_EXCEPTION_PAYLOAD, 0, true); ++ if (ret < 0) { ++ error_report("kvm: Failed to enable exception payload cap: %s", ++ strerror(-ret)); ++ return ret; ++ } ++ } ++ + ret = kvm_get_supported_msrs(s); + if (ret < 0) { + return ret; +@@ -2717,8 +2769,16 @@ static int kvm_put_vcpu_events(X86CPU *cpu, int level) + return 0; + } + +- events.exception.injected = (env->exception_injected >= 0); +- events.exception.nr = env->exception_injected; ++ events.flags = 0; ++ ++ if (has_exception_payload) { ++ events.flags |= KVM_VCPUEVENT_VALID_PAYLOAD; ++ events.exception.pending = env->exception_pending; ++ events.exception_has_payload = env->exception_has_payload; ++ events.exception_payload = env->exception_payload; ++ } ++ events.exception.nr = env->exception_nr; ++ events.exception.injected = env->exception_injected; + events.exception.has_error_code = env->has_error_code; + events.exception.error_code = env->error_code; + +@@ -2731,7 +2791,6 @@ static int kvm_put_vcpu_events(X86CPU *cpu, int level) + events.nmi.masked = !!(env->hflags2 & HF2_NMI_MASK); + + events.sipi_vector = env->sipi_vector; +- events.flags = 0; + + if (has_msr_smbase) { + events.smi.smm = !!(env->hflags & HF_SMM_MASK); +@@ -2781,8 +2840,19 @@ static int kvm_get_vcpu_events(X86CPU *cpu) + if (ret < 0) { + return ret; + } +- env->exception_injected = +- events.exception.injected ? events.exception.nr : -1; ++ ++ if (events.flags & KVM_VCPUEVENT_VALID_PAYLOAD) { ++ env->exception_pending = events.exception.pending; ++ env->exception_has_payload = events.exception_has_payload; ++ env->exception_payload = events.exception_payload; ++ } else { ++ env->exception_pending = 0; ++ env->exception_has_payload = false; ++ } ++ env->exception_injected = events.exception.injected; ++ env->exception_nr = ++ (env->exception_pending || env->exception_injected) ? ++ events.exception.nr : -1; + env->has_error_code = events.exception.has_error_code; + env->error_code = events.exception.error_code; + +@@ -2834,12 +2904,12 @@ static int kvm_guest_debug_workarounds(X86CPU *cpu) + unsigned long reinject_trap = 0; + + if (!kvm_has_vcpu_events()) { +- if (env->exception_injected == EXCP01_DB) { ++ if (env->exception_nr == EXCP01_DB) { + reinject_trap = KVM_GUESTDBG_INJECT_DB; + } else if (env->exception_injected == EXCP03_INT3) { + reinject_trap = KVM_GUESTDBG_INJECT_BP; + } +- env->exception_injected = -1; ++ kvm_reset_exception(env); + } + + /* +@@ -3215,13 +3285,13 @@ int kvm_arch_process_async_events(CPUState *cs) + + kvm_cpu_synchronize_state(cs); + +- if (env->exception_injected == EXCP08_DBLE) { ++ if (env->exception_nr == EXCP08_DBLE) { + /* this means triple fault */ + qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); + cs->exit_request = 1; + return 0; + } +- env->exception_injected = EXCP12_MCHK; ++ kvm_queue_exception(env, EXCP12_MCHK, 0, 0); + env->has_error_code = 0; + + cs->halted = 0; +@@ -3436,14 +3506,13 @@ static int kvm_handle_debug(X86CPU *cpu, + } + if (ret == 0) { + cpu_synchronize_state(cs); +- assert(env->exception_injected == -1); ++ assert(env->exception_nr == -1); + + /* pass to guest */ +- env->exception_injected = arch_info->exception; ++ kvm_queue_exception(env, arch_info->exception, ++ arch_info->exception == EXCP01_DB, ++ arch_info->dr6); + env->has_error_code = 0; +- if (arch_info->exception == EXCP01_DB) { +- env->dr[6] = arch_info->dr6; +- } + } + + return ret; +diff --git a/target/i386/machine.c b/target/i386/machine.c +index a2ddbba..5ffee8f 100644 +--- a/target/i386/machine.c ++++ b/target/i386/machine.c +@@ -239,6 +239,41 @@ static int cpu_pre_save(void *opaque) + } + #endif + ++ /* ++ * When vCPU is running L2 and exception is still pending, ++ * it can potentially be intercepted by L1 hypervisor. ++ * In contrast to an injected exception which cannot be ++ * intercepted anymore. ++ * ++ * Furthermore, when a L2 exception is intercepted by L1 ++ * hypervisor, it's exception payload (CR2/DR6 on #PF/#DB) ++ * should not be set yet in the respective vCPU register. ++ * Thus, in case an exception is pending, it is ++ * important to save the exception payload seperately. ++ * ++ * Therefore, if an exception is not in a pending state ++ * or vCPU is not in guest-mode, it is not important to ++ * distinguish between a pending and injected exception ++ * and we don't need to store seperately the exception payload. ++ * ++ * In order to preserve better backwards-compatabile migration, ++ * convert a pending exception to an injected exception in ++ * case it is not important to distingiush between them ++ * as described above. ++ */ ++ if (env->exception_pending && !(env->hflags & HF_GUEST_MASK)) { ++ env->exception_pending = 0; ++ env->exception_injected = 1; ++ ++ if (env->exception_has_payload) { ++ if (env->exception_nr == EXCP01_DB) { ++ env->dr[6] = env->exception_payload; ++ } else if (env->exception_nr == EXCP0E_PAGE) { ++ env->cr[2] = env->exception_payload; ++ } ++ } ++ } ++ + return 0; + } + +@@ -296,6 +331,23 @@ static int cpu_post_load(void *opaque, int version_id) + } + #endif + ++ /* ++ * There are cases that we can get valid exception_nr with both ++ * exception_pending and exception_injected being cleared. ++ * This can happen in one of the following scenarios: ++ * 1) Source is older QEMU without KVM_CAP_EXCEPTION_PAYLOAD support. ++ * 2) Source is running on kernel without KVM_CAP_EXCEPTION_PAYLOAD support. ++ * 3) "cpu/exception_info" subsection not sent because there is no exception ++ * pending or guest wasn't running L2 (See comment in cpu_pre_save()). ++ * ++ * In those cases, we can just deduce that a valid exception_nr means ++ * we can treat the exception as already injected. ++ */ ++ if ((env->exception_nr != -1) && ++ !env->exception_pending && !env->exception_injected) { ++ env->exception_injected = 1; ++ } ++ + env->fpstt = (env->fpus_vmstate >> 11) & 7; + env->fpus = env->fpus_vmstate & ~0x3800; + env->fptag_vmstate ^= 0xff; +@@ -341,6 +393,35 @@ static bool steal_time_msr_needed(void *opaque) + return cpu->env.steal_time_msr != 0; + } + ++static bool exception_info_needed(void *opaque) ++{ ++ X86CPU *cpu = opaque; ++ CPUX86State *env = &cpu->env; ++ ++ /* ++ * It is important to save exception-info only in case ++ * we need to distingiush between a pending and injected ++ * exception. Which is only required in case there is a ++ * pending exception and vCPU is running L2. ++ * For more info, refer to comment in cpu_pre_save(). ++ */ ++ return env->exception_pending && (env->hflags & HF_GUEST_MASK); ++} ++ ++static const VMStateDescription vmstate_exception_info = { ++ .name = "cpu/exception_info", ++ .version_id = 1, ++ .minimum_version_id = 1, ++ .needed = exception_info_needed, ++ .fields = (VMStateField[]) { ++ VMSTATE_UINT8(env.exception_pending, X86CPU), ++ VMSTATE_UINT8(env.exception_injected, X86CPU), ++ VMSTATE_UINT8(env.exception_has_payload, X86CPU), ++ VMSTATE_UINT64(env.exception_payload, X86CPU), ++ VMSTATE_END_OF_LIST() ++ } ++}; ++ + static const VMStateDescription vmstate_steal_time_msr = { + .name = "cpu/steal_time_msr", + .version_id = 1, +@@ -1219,7 +1300,7 @@ VMStateDescription vmstate_x86_cpu = { + VMSTATE_INT32(env.interrupt_injected, X86CPU), + VMSTATE_UINT32(env.mp_state, X86CPU), + VMSTATE_UINT64(env.tsc, X86CPU), +- VMSTATE_INT32(env.exception_injected, X86CPU), ++ VMSTATE_INT32(env.exception_nr, X86CPU), + VMSTATE_UINT8(env.soft_interrupt, X86CPU), + VMSTATE_UINT8(env.nmi_injected, X86CPU), + VMSTATE_UINT8(env.nmi_pending, X86CPU), +@@ -1243,6 +1324,7 @@ VMStateDescription vmstate_x86_cpu = { + /* The above list is not sorted /wrt version numbers, watch out! */ + }, + .subsections = (const VMStateDescription*[]) { ++ &vmstate_exception_info, + &vmstate_async_pf_msr, + &vmstate_pv_eoi_msr, + &vmstate_steal_time_msr, +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-kvm-Add-support-for-save-and-restore-nes.patch b/SOURCES/kvm-target-i386-kvm-Add-support-for-save-and-restore-nes.patch new file mode 100644 index 0000000..176b679 --- /dev/null +++ b/SOURCES/kvm-target-i386-kvm-Add-support-for-save-and-restore-nes.patch @@ -0,0 +1,464 @@ +From 0a1fd178d9b7c054d229b60540b7d12d87eb8070 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Mon, 22 Jul 2019 18:22:15 +0100 +Subject: [PATCH 34/39] target/i386: kvm: Add support for save and restore + nested state + +RH-Author: Paolo Bonzini +Message-id: <20190722182220.19374-14-pbonzini@redhat.com> +Patchwork-id: 89629 +O-Subject: [RHEL-8.1.0 PATCH qemu-kvm v3 13/18] target/i386: kvm: Add support for save and restore nested state +Bugzilla: 1689269 +RH-Acked-by: Peter Xu +RH-Acked-by: Laurent Vivier +RH-Acked-by: Dr. David Alan Gilbert + +From: Liran Alon + +Kernel commit 8fcc4b5923af ("kvm: nVMX: Introduce KVM_CAP_NESTED_STATE") +introduced new IOCTLs to extract and restore vCPU state related to +Intel VMX & AMD SVM. + +Utilize these IOCTLs to add support for migration of VMs which are +running nested hypervisors. + +Reviewed-by: Nikita Leshenko +Reviewed-by: Maran Wilson +Tested-by: Maran Wilson +Signed-off-by: Liran Alon +Message-Id: <20190619162140.133674-9-liran.alon@oracle.com> +Signed-off-by: Paolo Bonzini +(cherry picked from commit ebbfef2f34cfc749c045a4569dedb4f748ec024a) +Signed-off-by: Danilo C. L. de Paula +--- + accel/kvm/kvm-all.c | 8 ++ + include/sysemu/kvm.h | 1 + + target/i386/cpu.h | 3 + + target/i386/kvm.c | 80 ++++++++++++++++++++ + target/i386/machine.c | 198 ++++++++++++++++++++++++++++++++++++++++++++++++++ + 5 files changed, 290 insertions(+) + +diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c +index a939b26..2130fcb 100644 +--- a/accel/kvm/kvm-all.c ++++ b/accel/kvm/kvm-all.c +@@ -87,6 +87,7 @@ struct KVMState + #ifdef KVM_CAP_SET_GUEST_DEBUG + struct kvm_sw_breakpoint_head kvm_sw_breakpoints; + #endif ++ int max_nested_state_len; + int many_ioeventfds; + int intx_set_mask; + bool sync_mmu; +@@ -1646,6 +1647,8 @@ static int kvm_init(MachineState *ms) + s->debugregs = kvm_check_extension(s, KVM_CAP_DEBUGREGS); + #endif + ++ s->max_nested_state_len = kvm_check_extension(s, KVM_CAP_NESTED_STATE); ++ + #ifdef KVM_CAP_IRQ_ROUTING + kvm_direct_msi_allowed = (kvm_check_extension(s, KVM_CAP_SIGNAL_MSI) > 0); + #endif +@@ -2207,6 +2210,11 @@ int kvm_has_debugregs(void) + return kvm_state->debugregs; + } + ++int kvm_max_nested_state_length(void) ++{ ++ return kvm_state->max_nested_state_len; ++} ++ + int kvm_has_many_ioeventfds(void) + { + if (!kvm_enabled()) { +diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h +index a5a6dff..3cf04cf 100644 +--- a/include/sysemu/kvm.h ++++ b/include/sysemu/kvm.h +@@ -211,6 +211,7 @@ bool kvm_has_sync_mmu(void); + int kvm_has_vcpu_events(void); + int kvm_has_robust_singlestep(void); + int kvm_has_debugregs(void); ++int kvm_max_nested_state_length(void); + int kvm_has_pit_state2(void); + int kvm_has_many_ioeventfds(void); + int kvm_has_gsi_routing(void); +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index f595fc3..86f3d98 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -1335,6 +1335,9 @@ typedef struct CPUX86State { + int64_t tsc_khz; + int64_t user_tsc_khz; /* for sanity check only */ + void *kvm_xsave_buf; ++#if defined(CONFIG_KVM) ++ struct kvm_nested_state *nested_state; ++#endif + #if defined(CONFIG_HVF) + HVFX86EmulatorState *hvf_emul; + #endif +diff --git a/target/i386/kvm.c b/target/i386/kvm.c +index 8a6da90..ddceb7d 100644 +--- a/target/i386/kvm.c ++++ b/target/i386/kvm.c +@@ -789,6 +789,7 @@ int kvm_arch_init_vcpu(CPUState *cs) + struct kvm_cpuid_entry2 *c; + uint32_t signature[3]; + int kvm_base = KVM_CPUID_SIGNATURE; ++ int max_nested_state_len; + int r; + Error *local_err = NULL; + +@@ -1180,6 +1181,24 @@ int kvm_arch_init_vcpu(CPUState *cs) + if (has_xsave) { + env->kvm_xsave_buf = qemu_memalign(4096, sizeof(struct kvm_xsave)); + } ++ ++ max_nested_state_len = kvm_max_nested_state_length(); ++ if (max_nested_state_len > 0) { ++ assert(max_nested_state_len >= offsetof(struct kvm_nested_state, data)); ++ env->nested_state = g_malloc0(max_nested_state_len); ++ ++ env->nested_state->size = max_nested_state_len; ++ ++ if (IS_INTEL_CPU(env)) { ++ struct kvm_vmx_nested_state_hdr *vmx_hdr = ++ &env->nested_state->hdr.vmx; ++ ++ env->nested_state->format = KVM_STATE_NESTED_FORMAT_VMX; ++ vmx_hdr->vmxon_pa = -1ull; ++ vmx_hdr->vmcs12_pa = -1ull; ++ } ++ } ++ + cpu->kvm_msr_buf = g_malloc0(MSR_BUF_SIZE); + + if (!(env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_RDTSCP)) { +@@ -1199,12 +1218,18 @@ int kvm_arch_init_vcpu(CPUState *cs) + int kvm_arch_destroy_vcpu(CPUState *cs) + { + X86CPU *cpu = X86_CPU(cs); ++ CPUX86State *env = &cpu->env; + + if (cpu->kvm_msr_buf) { + g_free(cpu->kvm_msr_buf); + cpu->kvm_msr_buf = NULL; + } + ++ if (env->nested_state) { ++ g_free(env->nested_state); ++ env->nested_state = NULL; ++ } ++ + return 0; + } + +@@ -2875,6 +2900,52 @@ static int kvm_get_debugregs(X86CPU *cpu) + return 0; + } + ++static int kvm_put_nested_state(X86CPU *cpu) ++{ ++ CPUX86State *env = &cpu->env; ++ int max_nested_state_len = kvm_max_nested_state_length(); ++ ++ if (max_nested_state_len <= 0) { ++ return 0; ++ } ++ ++ assert(env->nested_state->size <= max_nested_state_len); ++ return kvm_vcpu_ioctl(CPU(cpu), KVM_SET_NESTED_STATE, env->nested_state); ++} ++ ++static int kvm_get_nested_state(X86CPU *cpu) ++{ ++ CPUX86State *env = &cpu->env; ++ int max_nested_state_len = kvm_max_nested_state_length(); ++ int ret; ++ ++ if (max_nested_state_len <= 0) { ++ return 0; ++ } ++ ++ /* ++ * It is possible that migration restored a smaller size into ++ * nested_state->hdr.size than what our kernel support. ++ * We preserve migration origin nested_state->hdr.size for ++ * call to KVM_SET_NESTED_STATE but wish that our next call ++ * to KVM_GET_NESTED_STATE will use max size our kernel support. ++ */ ++ env->nested_state->size = max_nested_state_len; ++ ++ ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_NESTED_STATE, env->nested_state); ++ if (ret < 0) { ++ return ret; ++ } ++ ++ if (env->nested_state->flags & KVM_STATE_NESTED_GUEST_MODE) { ++ env->hflags |= HF_GUEST_MASK; ++ } else { ++ env->hflags &= ~HF_GUEST_MASK; ++ } ++ ++ return ret; ++} ++ + int kvm_arch_put_registers(CPUState *cpu, int level) + { + X86CPU *x86_cpu = X86_CPU(cpu); +@@ -2882,6 +2953,11 @@ int kvm_arch_put_registers(CPUState *cpu, int level) + + assert(cpu_is_stopped(cpu) || qemu_cpu_is_self(cpu)); + ++ ret = kvm_put_nested_state(x86_cpu); ++ if (ret < 0) { ++ return ret; ++ } ++ + if (level >= KVM_PUT_RESET_STATE) { + ret = kvm_put_msr_feature_control(x86_cpu); + if (ret < 0) { +@@ -2997,6 +3073,10 @@ int kvm_arch_get_registers(CPUState *cs) + if (ret < 0) { + goto out; + } ++ ret = kvm_get_nested_state(cpu); ++ if (ret < 0) { ++ goto out; ++ } + ret = 0; + out: + cpu_sync_bndcs_hflags(&cpu->env); +diff --git a/target/i386/machine.c b/target/i386/machine.c +index 561d4a5..a2ddbba 100644 +--- a/target/i386/machine.c ++++ b/target/i386/machine.c +@@ -230,6 +230,15 @@ static int cpu_pre_save(void *opaque) + env->segs[R_SS].flags &= ~(env->segs[R_SS].flags & DESC_DPL_MASK); + } + ++#ifdef CONFIG_KVM ++ /* Verify we have nested virtualization state from kernel if required */ ++ if (kvm_enabled() && cpu_has_vmx(env) && !env->nested_state) { ++ error_report("Guest enabled nested virtualization but kernel " ++ "does not support saving of nested state"); ++ return -EINVAL; ++ } ++#endif ++ + return 0; + } + +@@ -277,6 +286,16 @@ static int cpu_post_load(void *opaque, int version_id) + env->hflags &= ~HF_CPL_MASK; + env->hflags |= (env->segs[R_SS].flags >> DESC_DPL_SHIFT) & HF_CPL_MASK; + ++#ifdef CONFIG_KVM ++ if ((env->hflags & HF_GUEST_MASK) && ++ (!env->nested_state || ++ !(env->nested_state->flags & KVM_STATE_NESTED_GUEST_MODE))) { ++ error_report("vCPU set in guest-mode inconsistent with " ++ "migrated kernel nested state"); ++ return -EINVAL; ++ } ++#endif ++ + env->fpstt = (env->fpus_vmstate >> 11) & 7; + env->fpus = env->fpus_vmstate & ~0x3800; + env->fptag_vmstate ^= 0xff; +@@ -819,6 +838,182 @@ static const VMStateDescription vmstate_tsc_khz = { + } + }; + ++#ifdef CONFIG_KVM ++ ++static bool vmx_vmcs12_needed(void *opaque) ++{ ++ struct kvm_nested_state *nested_state = opaque; ++ return (nested_state->size > ++ offsetof(struct kvm_nested_state, data.vmx[0].vmcs12)); ++} ++ ++static const VMStateDescription vmstate_vmx_vmcs12 = { ++ .name = "cpu/kvm_nested_state/vmx/vmcs12", ++ .version_id = 1, ++ .minimum_version_id = 1, ++ .needed = vmx_vmcs12_needed, ++ .fields = (VMStateField[]) { ++ VMSTATE_UINT8_ARRAY(data.vmx[0].vmcs12, ++ struct kvm_nested_state, ++ KVM_STATE_NESTED_VMX_VMCS_SIZE), ++ VMSTATE_END_OF_LIST() ++ } ++}; ++ ++static bool vmx_shadow_vmcs12_needed(void *opaque) ++{ ++ struct kvm_nested_state *nested_state = opaque; ++ return (nested_state->size > ++ offsetof(struct kvm_nested_state, data.vmx[0].shadow_vmcs12)); ++} ++ ++static const VMStateDescription vmstate_vmx_shadow_vmcs12 = { ++ .name = "cpu/kvm_nested_state/vmx/shadow_vmcs12", ++ .version_id = 1, ++ .minimum_version_id = 1, ++ .needed = vmx_shadow_vmcs12_needed, ++ .fields = (VMStateField[]) { ++ VMSTATE_UINT8_ARRAY(data.vmx[0].shadow_vmcs12, ++ struct kvm_nested_state, ++ KVM_STATE_NESTED_VMX_VMCS_SIZE), ++ VMSTATE_END_OF_LIST() ++ } ++}; ++ ++static bool vmx_nested_state_needed(void *opaque) ++{ ++ struct kvm_nested_state *nested_state = opaque; ++ ++ return ((nested_state->format == KVM_STATE_NESTED_FORMAT_VMX) && ++ ((nested_state->hdr.vmx.vmxon_pa != -1ull) || ++ (nested_state->hdr.vmx.smm.flags & KVM_STATE_NESTED_SMM_VMXON))); ++} ++ ++static const VMStateDescription vmstate_vmx_nested_state = { ++ .name = "cpu/kvm_nested_state/vmx", ++ .version_id = 1, ++ .minimum_version_id = 1, ++ .needed = vmx_nested_state_needed, ++ .fields = (VMStateField[]) { ++ VMSTATE_U64(hdr.vmx.vmxon_pa, struct kvm_nested_state), ++ VMSTATE_U64(hdr.vmx.vmcs12_pa, struct kvm_nested_state), ++ VMSTATE_U16(hdr.vmx.smm.flags, struct kvm_nested_state), ++ VMSTATE_END_OF_LIST() ++ }, ++ .subsections = (const VMStateDescription*[]) { ++ &vmstate_vmx_vmcs12, ++ &vmstate_vmx_shadow_vmcs12, ++ NULL, ++ } ++}; ++ ++static bool svm_nested_state_needed(void *opaque) ++{ ++ struct kvm_nested_state *nested_state = opaque; ++ ++ return (nested_state->format == KVM_STATE_NESTED_FORMAT_SVM); ++} ++ ++static const VMStateDescription vmstate_svm_nested_state = { ++ .name = "cpu/kvm_nested_state/svm", ++ .version_id = 1, ++ .minimum_version_id = 1, ++ .needed = svm_nested_state_needed, ++ .fields = (VMStateField[]) { ++ VMSTATE_END_OF_LIST() ++ } ++}; ++ ++static bool nested_state_needed(void *opaque) ++{ ++ X86CPU *cpu = opaque; ++ CPUX86State *env = &cpu->env; ++ ++ return (env->nested_state && ++ (vmx_nested_state_needed(env->nested_state) || ++ svm_nested_state_needed(env->nested_state))); ++} ++ ++static int nested_state_post_load(void *opaque, int version_id) ++{ ++ X86CPU *cpu = opaque; ++ CPUX86State *env = &cpu->env; ++ struct kvm_nested_state *nested_state = env->nested_state; ++ int min_nested_state_len = offsetof(struct kvm_nested_state, data); ++ int max_nested_state_len = kvm_max_nested_state_length(); ++ ++ /* ++ * If our kernel don't support setting nested state ++ * and we have received nested state from migration stream, ++ * we need to fail migration ++ */ ++ if (max_nested_state_len <= 0) { ++ error_report("Received nested state when kernel cannot restore it"); ++ return -EINVAL; ++ } ++ ++ /* ++ * Verify that the size of received nested_state struct ++ * at least cover required header and is not larger ++ * than the max size that our kernel support ++ */ ++ if (nested_state->size < min_nested_state_len) { ++ error_report("Received nested state size less than min: " ++ "len=%d, min=%d", ++ nested_state->size, min_nested_state_len); ++ return -EINVAL; ++ } ++ if (nested_state->size > max_nested_state_len) { ++ error_report("Recieved unsupported nested state size: " ++ "nested_state->size=%d, max=%d", ++ nested_state->size, max_nested_state_len); ++ return -EINVAL; ++ } ++ ++ /* Verify format is valid */ ++ if ((nested_state->format != KVM_STATE_NESTED_FORMAT_VMX) && ++ (nested_state->format != KVM_STATE_NESTED_FORMAT_SVM)) { ++ error_report("Received invalid nested state format: %d", ++ nested_state->format); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static const VMStateDescription vmstate_kvm_nested_state = { ++ .name = "cpu/kvm_nested_state", ++ .version_id = 1, ++ .minimum_version_id = 1, ++ .fields = (VMStateField[]) { ++ VMSTATE_U16(flags, struct kvm_nested_state), ++ VMSTATE_U16(format, struct kvm_nested_state), ++ VMSTATE_U32(size, struct kvm_nested_state), ++ VMSTATE_END_OF_LIST() ++ }, ++ .subsections = (const VMStateDescription*[]) { ++ &vmstate_vmx_nested_state, ++ &vmstate_svm_nested_state, ++ NULL ++ } ++}; ++ ++static const VMStateDescription vmstate_nested_state = { ++ .name = "cpu/nested_state", ++ .version_id = 1, ++ .minimum_version_id = 1, ++ .needed = nested_state_needed, ++ .post_load = nested_state_post_load, ++ .fields = (VMStateField[]) { ++ VMSTATE_STRUCT_POINTER(env.nested_state, X86CPU, ++ vmstate_kvm_nested_state, ++ struct kvm_nested_state), ++ VMSTATE_END_OF_LIST() ++ } ++}; ++ ++#endif ++ + static bool mcg_ext_ctl_needed(void *opaque) + { + X86CPU *cpu = opaque; +@@ -1080,6 +1275,9 @@ VMStateDescription vmstate_x86_cpu = { + #ifndef TARGET_X86_64 + &vmstate_efer32, + #endif ++#ifdef CONFIG_KVM ++ &vmstate_nested_state, ++#endif + NULL + } + }; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-kvm-Block-migration-for-vCPUs-exposed-wi.patch b/SOURCES/kvm-target-i386-kvm-Block-migration-for-vCPUs-exposed-wi.patch new file mode 100644 index 0000000..c4e9269 --- /dev/null +++ b/SOURCES/kvm-target-i386-kvm-Block-migration-for-vCPUs-exposed-wi.patch @@ -0,0 +1,130 @@ +From 0d5048785d6edd2fee3b22aa6901e55539e07525 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Mon, 22 Jul 2019 18:22:11 +0100 +Subject: [PATCH 30/39] target/i386: kvm: Block migration for vCPUs exposed + with nested virtualization + +RH-Author: Paolo Bonzini +Message-id: <20190722182220.19374-10-pbonzini@redhat.com> +Patchwork-id: 89633 +O-Subject: [RHEL-8.1.0 PATCH qemu-kvm v3 09/18] target/i386: kvm: Block migration for vCPUs exposed with nested virtualization +Bugzilla: 1689269 +RH-Acked-by: Peter Xu +RH-Acked-by: Laurent Vivier +RH-Acked-by: Dr. David Alan Gilbert + +From: Liran Alon + +Commit d98f26073beb ("target/i386: kvm: add VMX migration blocker") +added a migration blocker for vCPU exposed with Intel VMX. +However, migration should also be blocked for vCPU exposed with +AMD SVM. + +Both cases should be blocked because QEMU should extract additional +vCPU state from KVM that should be migrated as part of vCPU VMState. +E.g. Whether vCPU is running in guest-mode or host-mode. + +Fixes: d98f26073beb ("target/i386: kvm: add VMX migration blocker") +Reviewed-by: Maran Wilson +Signed-off-by: Liran Alon +Message-Id: <20190619162140.133674-6-liran.alon@oracle.com> +Signed-off-by: Paolo Bonzini +(cherry picked from commit 18ab37ba1cee290923240744288dbee8be9355fb) +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.c | 6 ------ + target/i386/cpu.h | 12 ++++++++++++ + target/i386/kvm.c | 14 +++++++------- + 3 files changed, 19 insertions(+), 13 deletions(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index af62281..bd0b784 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -5034,12 +5034,6 @@ static int x86_cpu_filter_features(X86CPU *cpu) + return rv; + } + +-#define IS_INTEL_CPU(env) ((env)->cpuid_vendor1 == CPUID_VENDOR_INTEL_1 && \ +- (env)->cpuid_vendor2 == CPUID_VENDOR_INTEL_2 && \ +- (env)->cpuid_vendor3 == CPUID_VENDOR_INTEL_3) +-#define IS_AMD_CPU(env) ((env)->cpuid_vendor1 == CPUID_VENDOR_AMD_1 && \ +- (env)->cpuid_vendor2 == CPUID_VENDOR_AMD_2 && \ +- (env)->cpuid_vendor3 == CPUID_VENDOR_AMD_3) + static void x86_cpu_realizefn(DeviceState *dev, Error **errp) + { + CPUState *cs = CPU(dev); +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index 923dfcd..f595fc3 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -722,6 +722,13 @@ typedef uint32_t FeatureWordArray[FEATURE_WORDS]; + + #define CPUID_VENDOR_VIA "CentaurHauls" + ++#define IS_INTEL_CPU(env) ((env)->cpuid_vendor1 == CPUID_VENDOR_INTEL_1 && \ ++ (env)->cpuid_vendor2 == CPUID_VENDOR_INTEL_2 && \ ++ (env)->cpuid_vendor3 == CPUID_VENDOR_INTEL_3) ++#define IS_AMD_CPU(env) ((env)->cpuid_vendor1 == CPUID_VENDOR_AMD_1 && \ ++ (env)->cpuid_vendor2 == CPUID_VENDOR_AMD_2 && \ ++ (env)->cpuid_vendor3 == CPUID_VENDOR_AMD_3) ++ + #define CPUID_MWAIT_IBE (1U << 1) /* Interrupts can exit capability */ + #define CPUID_MWAIT_EMX (1U << 0) /* enumeration supported */ + +@@ -1829,6 +1836,11 @@ static inline int32_t x86_get_a20_mask(CPUX86State *env) + } + } + ++static inline bool cpu_has_vmx(CPUX86State *env) ++{ ++ return env->features[FEAT_1_ECX] & CPUID_EXT_VMX; ++} ++ + /* fpu_helper.c */ + void update_fp_status(CPUX86State *env); + void update_mxcsr_status(CPUX86State *env); +diff --git a/target/i386/kvm.c b/target/i386/kvm.c +index 1a4ff3c..f741e8b 100644 +--- a/target/i386/kvm.c ++++ b/target/i386/kvm.c +@@ -772,7 +772,7 @@ static int hyperv_handle_properties(CPUState *cs) + } + + static Error *invtsc_mig_blocker; +-static Error *vmx_mig_blocker; ++static Error *nested_virt_mig_blocker; + + #define KVM_MAX_CPUID_ENTRIES 100 + +@@ -1116,13 +1116,13 @@ int kvm_arch_init_vcpu(CPUState *cs) + !!(c->ecx & CPUID_EXT_SMX); + } + +- if ((env->features[FEAT_1_ECX] & CPUID_EXT_VMX) && !vmx_mig_blocker) { +- error_setg(&vmx_mig_blocker, +- "Nested VMX virtualization does not support live migration yet"); +- r = migrate_add_blocker(vmx_mig_blocker, &local_err); ++ if (cpu_has_vmx(env) && !nested_virt_mig_blocker) { ++ error_setg(&nested_virt_mig_blocker, ++ "Nested virtualization does not support live migration yet"); ++ r = migrate_add_blocker(nested_virt_mig_blocker, &local_err); + if (local_err) { + error_report_err(local_err); +- error_free(vmx_mig_blocker); ++ error_free(nested_virt_mig_blocker); + return r; + } + } +@@ -1191,7 +1191,7 @@ int kvm_arch_init_vcpu(CPUState *cs) + fail: + migrate_del_blocker(invtsc_mig_blocker); + fail2: +- migrate_del_blocker(vmx_mig_blocker); ++ migrate_del_blocker(nested_virt_mig_blocker); + + return r; + } +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-kvm-Delete-VMX-migration-blocker-on-vCPU.patch b/SOURCES/kvm-target-i386-kvm-Delete-VMX-migration-blocker-on-vCPU.patch new file mode 100644 index 0000000..215a425 --- /dev/null +++ b/SOURCES/kvm-target-i386-kvm-Delete-VMX-migration-blocker-on-vCPU.patch @@ -0,0 +1,72 @@ +From 9cf495aabeeaf4fdccae83d748a70936e3bf26ab Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Mon, 22 Jul 2019 18:22:07 +0100 +Subject: [PATCH 26/39] target/i386: kvm: Delete VMX migration blocker on vCPU + init failure + +RH-Author: Paolo Bonzini +Message-id: <20190722182220.19374-6-pbonzini@redhat.com> +Patchwork-id: 89624 +O-Subject: [RHEL-8.1.0 PATCH qemu-kvm v3 05/18] target/i386: kvm: Delete VMX migration blocker on vCPU init failure +Bugzilla: 1689269 +RH-Acked-by: Peter Xu +RH-Acked-by: Laurent Vivier +RH-Acked-by: Dr. David Alan Gilbert + +From: Liran Alon + +Commit d98f26073beb ("target/i386: kvm: add VMX migration blocker") +added migration blocker for vCPU exposed with Intel VMX because QEMU +doesn't yet contain code to support migration of nested virtualization +workloads. + +However, that commit missed adding deletion of the migration blocker in +case init of vCPU failed. Similar to invtsc_mig_blocker. This commit fix +that issue. + +Fixes: d98f26073beb ("target/i386: kvm: add VMX migration blocker") +Signed-off-by: Liran Alon +Reviewed-by: Maran Wilson +Message-Id: <20190619162140.133674-2-liran.alon@oracle.com> +Signed-off-by: Paolo Bonzini +(cherry picked from commit 6b2341eeea43c00b8e266026cec84d57af1484dc) +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/kvm.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/target/i386/kvm.c b/target/i386/kvm.c +index 875412c..8e861a1 100644 +--- a/target/i386/kvm.c ++++ b/target/i386/kvm.c +@@ -798,7 +798,7 @@ int kvm_arch_init_vcpu(CPUState *cs) + + r = kvm_arch_set_tsc_khz(cs); + if (r < 0) { +- goto fail; ++ return r; + } + + /* vcpu's TSC frequency is either specified by user, or following +@@ -1142,7 +1142,7 @@ int kvm_arch_init_vcpu(CPUState *cs) + if (local_err) { + error_report_err(local_err); + error_free(invtsc_mig_blocker); +- return r; ++ goto fail2; + } + /* for savevm */ + vmstate_x86_cpu.unmigratable = 1; +@@ -1190,6 +1190,9 @@ int kvm_arch_init_vcpu(CPUState *cs) + + fail: + migrate_del_blocker(invtsc_mig_blocker); ++ fail2: ++ migrate_del_blocker(vmx_mig_blocker); ++ + return r; + } + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-kvm-Demand-nested-migration-kernel-capab.patch b/SOURCES/kvm-target-i386-kvm-Demand-nested-migration-kernel-capab.patch new file mode 100644 index 0000000..07ddbfd --- /dev/null +++ b/SOURCES/kvm-target-i386-kvm-Demand-nested-migration-kernel-capab.patch @@ -0,0 +1,217 @@ +From 2427e21de274cf7b56ef79e4a7ba78a08def7a58 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Mon, 22 Jul 2019 18:22:18 +0100 +Subject: [PATCH 37/39] target/i386: kvm: Demand nested migration kernel + capabilities only when vCPU may have enabled VMX + +RH-Author: Paolo Bonzini +Message-id: <20190722182220.19374-17-pbonzini@redhat.com> +Patchwork-id: 89634 +O-Subject: [RHEL-8.1.0 PATCH qemu-kvm v3 16/18] target/i386: kvm: Demand nested migration kernel capabilities only when vCPU may have enabled VMX +Bugzilla: 1689269 +RH-Acked-by: Peter Xu +RH-Acked-by: Laurent Vivier +RH-Acked-by: Dr. David Alan Gilbert + +From: Liran Alon + +Previous to this change, a vCPU exposed with VMX running on a kernel +without KVM_CAP_NESTED_STATE or KVM_CAP_EXCEPTION_PAYLOAD resulted in +adding a migration blocker. This was because when the code was written +it was thought there is no way to reliably know if a vCPU is utilising +VMX or not at runtime. However, it turns out that this can be known to +some extent: + +In order for a vCPU to enter VMX operation it must have CR4.VMXE set. +Since it was set, CR4.VMXE must remain set as long as the vCPU is in +VMX operation. This is because CR4.VMXE is one of the bits set +in MSR_IA32_VMX_CR4_FIXED1. +There is one exception to the above statement when vCPU enters SMM mode. +When a vCPU enters SMM mode, it temporarily exits VMX operation and +may also reset CR4.VMXE during execution in SMM mode. +When the vCPU exits SMM mode, vCPU state is restored to be in VMX operation +and CR4.VMXE is restored to its original state of being set. +Therefore, when the vCPU is not in SMM mode, we can infer whether +VMX is being used by examining CR4.VMXE. Otherwise, we cannot +know for certain but assume the worse that vCPU may utilise VMX. + +Summaring all the above, a vCPU may have enabled VMX in case +CR4.VMXE is set or vCPU is in SMM mode. + +Therefore, remove migration blocker and check before migration +(cpu_pre_save()) if the vCPU may have enabled VMX. If true, only then +require relevant kernel capabilities. + +While at it, demand KVM_CAP_EXCEPTION_PAYLOAD only when the vCPU is in +guest-mode and there is a pending/injected exception. Otherwise, this +kernel capability is not required for proper migration. + +Reviewed-by: Joao Martins +Signed-off-by: Liran Alon +Reviewed-by: Maran Wilson +Tested-by: Maran Wilson +Signed-off-by: Paolo Bonzini +(cherry picked from commit 79a197ab180e75838523c58973b1221ad7bf51eb) +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.h | 22 ++++++++++++++++++++++ + target/i386/kvm.c | 26 ++++++-------------------- + target/i386/kvm_i386.h | 1 + + target/i386/machine.c | 24 ++++++++++++++++++++---- + 4 files changed, 49 insertions(+), 24 deletions(-) + +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index d120f62..273c90b 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -1848,6 +1848,28 @@ static inline bool cpu_has_vmx(CPUX86State *env) + return env->features[FEAT_1_ECX] & CPUID_EXT_VMX; + } + ++/* ++ * In order for a vCPU to enter VMX operation it must have CR4.VMXE set. ++ * Since it was set, CR4.VMXE must remain set as long as vCPU is in ++ * VMX operation. This is because CR4.VMXE is one of the bits set ++ * in MSR_IA32_VMX_CR4_FIXED1. ++ * ++ * There is one exception to above statement when vCPU enters SMM mode. ++ * When a vCPU enters SMM mode, it temporarily exit VMX operation and ++ * may also reset CR4.VMXE during execution in SMM mode. ++ * When vCPU exits SMM mode, vCPU state is restored to be in VMX operation ++ * and CR4.VMXE is restored to it's original value of being set. ++ * ++ * Therefore, when vCPU is not in SMM mode, we can infer whether ++ * VMX is being used by examining CR4.VMXE. Otherwise, we cannot ++ * know for certain. ++ */ ++static inline bool cpu_vmx_maybe_enabled(CPUX86State *env) ++{ ++ return cpu_has_vmx(env) && ++ ((env->cr[4] & CR4_VMXE_MASK) || (env->hflags & HF_SMM_MASK)); ++} ++ + /* fpu_helper.c */ + void update_fp_status(CPUX86State *env); + void update_mxcsr_status(CPUX86State *env); +diff --git a/target/i386/kvm.c b/target/i386/kvm.c +index 0619aba..0bd286e 100644 +--- a/target/i386/kvm.c ++++ b/target/i386/kvm.c +@@ -127,6 +127,11 @@ bool kvm_has_adjust_clock_stable(void) + return (ret == KVM_CLOCK_TSC_STABLE); + } + ++bool kvm_has_exception_payload(void) ++{ ++ return has_exception_payload; ++} ++ + bool kvm_allows_irq0_override(void) + { + return !kvm_irqchip_in_kernel() || kvm_has_gsi_routing(); +@@ -814,7 +819,6 @@ static int hyperv_handle_properties(CPUState *cs) + } + + static Error *invtsc_mig_blocker; +-static Error *nested_virt_mig_blocker; + + #define KVM_MAX_CPUID_ENTRIES 100 + +@@ -1159,22 +1163,6 @@ int kvm_arch_init_vcpu(CPUState *cs) + !!(c->ecx & CPUID_EXT_SMX); + } + +- if (cpu_has_vmx(env) && !nested_virt_mig_blocker && +- ((kvm_max_nested_state_length() <= 0) || !has_exception_payload)) { +- error_setg(&nested_virt_mig_blocker, +- "Kernel do not provide required capabilities for " +- "nested virtualization migration. " +- "(CAP_NESTED_STATE=%d, CAP_EXCEPTION_PAYLOAD=%d)", +- kvm_max_nested_state_length() > 0, +- has_exception_payload); +- r = migrate_add_blocker(nested_virt_mig_blocker, &local_err); +- if (local_err) { +- error_report_err(local_err); +- error_free(nested_virt_mig_blocker); +- return r; +- } +- } +- + if (env->mcg_cap & MCG_LMCE_P) { + has_msr_mcg_ext_ctl = has_msr_feature_control = true; + } +@@ -1190,7 +1178,7 @@ int kvm_arch_init_vcpu(CPUState *cs) + if (local_err) { + error_report_err(local_err); + error_free(invtsc_mig_blocker); +- goto fail2; ++ return r; + } + /* for savevm */ + vmstate_x86_cpu.unmigratable = 1; +@@ -1256,8 +1244,6 @@ int kvm_arch_init_vcpu(CPUState *cs) + + fail: + migrate_del_blocker(invtsc_mig_blocker); +- fail2: +- migrate_del_blocker(nested_virt_mig_blocker); + + return r; + } +diff --git a/target/i386/kvm_i386.h b/target/i386/kvm_i386.h +index 1de9876..df9bbf3 100644 +--- a/target/i386/kvm_i386.h ++++ b/target/i386/kvm_i386.h +@@ -41,6 +41,7 @@ + bool kvm_allows_irq0_override(void); + bool kvm_has_smm(void); + bool kvm_has_adjust_clock_stable(void); ++bool kvm_has_exception_payload(void); + void kvm_synchronize_all_tsc(void); + void kvm_arch_reset_vcpu(X86CPU *cs); + void kvm_arch_do_init_vcpu(X86CPU *cs); +diff --git a/target/i386/machine.c b/target/i386/machine.c +index 5ffee8f..8d90d98 100644 +--- a/target/i386/machine.c ++++ b/target/i386/machine.c +@@ -7,6 +7,7 @@ + #include "hw/i386/pc.h" + #include "hw/isa/isa.h" + #include "migration/cpu.h" ++#include "kvm_i386.h" + + #include "sysemu/kvm.h" + +@@ -231,10 +232,25 @@ static int cpu_pre_save(void *opaque) + } + + #ifdef CONFIG_KVM +- /* Verify we have nested virtualization state from kernel if required */ +- if (kvm_enabled() && cpu_has_vmx(env) && !env->nested_state) { +- error_report("Guest enabled nested virtualization but kernel " +- "does not support saving of nested state"); ++ /* ++ * In case vCPU may have enabled VMX, we need to make sure kernel have ++ * required capabilities in order to perform migration correctly: ++ * ++ * 1) We must be able to extract vCPU nested-state from KVM. ++ * ++ * 2) In case vCPU is running in guest-mode and it has a pending exception, ++ * we must be able to determine if it's in a pending or injected state. ++ * Note that in case KVM don't have required capability to do so, ++ * a pending/injected exception will always appear as an ++ * injected exception. ++ */ ++ if (kvm_enabled() && cpu_vmx_maybe_enabled(env) && ++ (!env->nested_state || ++ (!kvm_has_exception_payload() && (env->hflags & HF_GUEST_MASK) && ++ env->exception_injected))) { ++ error_report("Guest maybe enabled nested virtualization but kernel " ++ "does not support required capabilities to save vCPU " ++ "nested state"); + return -EINVAL; + } + #endif +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-kvm-Re-inject-DB-to-guest-with-updated-D.patch b/SOURCES/kvm-target-i386-kvm-Re-inject-DB-to-guest-with-updated-D.patch new file mode 100644 index 0000000..adb30cb --- /dev/null +++ b/SOURCES/kvm-target-i386-kvm-Re-inject-DB-to-guest-with-updated-D.patch @@ -0,0 +1,66 @@ +From c31315e765df0137cb7dfedb3869db72d6d2ca57 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Mon, 22 Jul 2019 18:22:10 +0100 +Subject: [PATCH 29/39] target/i386: kvm: Re-inject #DB to guest with updated + DR6 + +RH-Author: Paolo Bonzini +Message-id: <20190722182220.19374-9-pbonzini@redhat.com> +Patchwork-id: 89626 +O-Subject: [RHEL-8.1.0 PATCH qemu-kvm v3 08/18] target/i386: kvm: Re-inject #DB to guest with updated DR6 +Bugzilla: 1689269 +RH-Acked-by: Peter Xu +RH-Acked-by: Laurent Vivier +RH-Acked-by: Dr. David Alan Gilbert + +From: Liran Alon + +If userspace (QEMU) debug guest, when #DB is raised in guest and +intercepted by KVM, KVM forwards information on #DB to userspace +instead of injecting #DB to guest. +While doing so, KVM don't update vCPU DR6 but instead report the #DB DR6 +value to userspace for further handling. +See KVM's handle_exception() DB_VECTOR handler. + +QEMU handler for this case is kvm_handle_debug(). This handler basically +checks if #DB is related to one of user set hardware breakpoints and if +not, it re-inject #DB into guest. +The re-injection is done by setting env->exception_injected to #DB which +will later be passed as events.exception.nr to KVM_SET_VCPU_EVENTS ioctl +by kvm_put_vcpu_events(). + +However, in case userspace re-injects #DB, KVM expects userspace to set +vCPU DR6 as reported to userspace when #DB was intercepted! Otherwise, +KVM_REQ_EVENT handler will inject #DB with wrong DR6 to guest. + +Fix this issue by updating vCPU DR6 appropriately when re-inject #DB to +guest. + +Reviewed-by: Nikita Leshenko +Reviewed-by: Krish Sadhukhan +Signed-off-by: Liran Alon +Message-Id: <20190619162140.133674-5-liran.alon@oracle.com> +Signed-off-by: Paolo Bonzini +(cherry picked from commit bceeeef9e7544057659118688243260c390eceb9) +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/kvm.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/target/i386/kvm.c b/target/i386/kvm.c +index 4138fe9..1a4ff3c 100644 +--- a/target/i386/kvm.c ++++ b/target/i386/kvm.c +@@ -3363,6 +3363,9 @@ static int kvm_handle_debug(X86CPU *cpu, + /* pass to guest */ + env->exception_injected = arch_info->exception; + env->has_error_code = 0; ++ if (arch_info->exception == EXCP01_DB) { ++ env->dr[6] = arch_info->dr6; ++ } + } + + return ret; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-kvm-Use-symbolic-constant-for-DB-BP-exce.patch b/SOURCES/kvm-target-i386-kvm-Use-symbolic-constant-for-DB-BP-exce.patch new file mode 100644 index 0000000..b551bc8 --- /dev/null +++ b/SOURCES/kvm-target-i386-kvm-Use-symbolic-constant-for-DB-BP-exce.patch @@ -0,0 +1,58 @@ +From 0168573b58d5e70a60c9fef319ba510aa9648f2d Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Mon, 22 Jul 2019 18:22:09 +0100 +Subject: [PATCH 28/39] target/i386: kvm: Use symbolic constant for #DB/#BP + exception constants + +RH-Author: Paolo Bonzini +Message-id: <20190722182220.19374-8-pbonzini@redhat.com> +Patchwork-id: 89625 +O-Subject: [RHEL-8.1.0 PATCH qemu-kvm v3 07/18] target/i386: kvm: Use symbolic constant for #DB/#BP exception constants +Bugzilla: 1689269 +RH-Acked-by: Peter Xu +RH-Acked-by: Laurent Vivier +RH-Acked-by: Dr. David Alan Gilbert + +From: Liran Alon + +Reviewed-by: Nikita Leshenko +Reviewed-by: Krish Sadhukhan +Signed-off-by: Liran Alon +Message-Id: <20190619162140.133674-4-liran.alon@oracle.com> +Signed-off-by: Paolo Bonzini +(cherry picked from commit 37936ac70f6c20aec6f537349eb797fb98f9a99d) +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/kvm.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/target/i386/kvm.c b/target/i386/kvm.c +index 305809f..4138fe9 100644 +--- a/target/i386/kvm.c ++++ b/target/i386/kvm.c +@@ -2811,9 +2811,9 @@ static int kvm_guest_debug_workarounds(X86CPU *cpu) + unsigned long reinject_trap = 0; + + if (!kvm_has_vcpu_events()) { +- if (env->exception_injected == 1) { ++ if (env->exception_injected == EXCP01_DB) { + reinject_trap = KVM_GUESTDBG_INJECT_DB; +- } else if (env->exception_injected == 3) { ++ } else if (env->exception_injected == EXCP03_INT3) { + reinject_trap = KVM_GUESTDBG_INJECT_BP; + } + env->exception_injected = -1; +@@ -3325,8 +3325,8 @@ static int kvm_handle_debug(X86CPU *cpu, + int ret = 0; + int n; + +- if (arch_info->exception == 1) { +- if (arch_info->dr6 & (1 << 14)) { ++ if (arch_info->exception == EXCP01_DB) { ++ if (arch_info->dr6 & DR6_BS) { + if (cs->singlestep_enabled) { + ret = EXCP_DEBUG; + } +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-kvm-add-VMX-migration-blocker.patch b/SOURCES/kvm-target-i386-kvm-add-VMX-migration-blocker.patch new file mode 100644 index 0000000..2adbaea --- /dev/null +++ b/SOURCES/kvm-target-i386-kvm-add-VMX-migration-blocker.patch @@ -0,0 +1,60 @@ +From 9a920701b3d2d78612bc454c407cf7b0d01f51c6 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Mon, 22 Jul 2019 18:22:05 +0100 +Subject: [PATCH 24/39] target/i386: kvm: add VMX migration blocker + +RH-Author: Paolo Bonzini +Message-id: <20190722182220.19374-4-pbonzini@redhat.com> +Patchwork-id: 89621 +O-Subject: [RHEL-8.1.0 PATCH qemu-kvm v3 03/18] target/i386: kvm: add VMX migration blocker +Bugzilla: 1689269 +RH-Acked-by: Peter Xu +RH-Acked-by: Laurent Vivier +RH-Acked-by: Dr. David Alan Gilbert + +Nested VMX does not support live migration yet. Add a blocker +until that is worked out. + +Nested SVM only does not support it, but unfortunately it is +enabled by default for -cpu host so we cannot really disable it. + +Signed-off-by: Paolo Bonzini +(cherry picked from commit d98f26073bebddcd3da0ba1b86c3a34e840c0fb8) +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/kvm.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/target/i386/kvm.c b/target/i386/kvm.c +index 8a4d31d..d414187 100644 +--- a/target/i386/kvm.c ++++ b/target/i386/kvm.c +@@ -772,6 +772,7 @@ static int hyperv_handle_properties(CPUState *cs) + } + + static Error *invtsc_mig_blocker; ++static Error *vmx_mig_blocker; + + #define KVM_MAX_CPUID_ENTRIES 100 + +@@ -1115,6 +1116,17 @@ int kvm_arch_init_vcpu(CPUState *cs) + !!(c->ecx & CPUID_EXT_SMX); + } + ++ if ((env->features[FEAT_1_ECX] & CPUID_EXT_VMX) && !vmx_mig_blocker) { ++ error_setg(&vmx_mig_blocker, ++ "Nested VMX virtualization does not support live migration yet"); ++ r = migrate_add_blocker(vmx_mig_blocker, &local_err); ++ if (local_err) { ++ error_report_err(local_err); ++ error_free(vmx_mig_blocker); ++ return r; ++ } ++ } ++ + if (env->mcg_cap & MCG_LMCE_P) { + has_msr_mcg_ext_ctl = has_msr_feature_control = true; + } +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-kvm-do-not-initialize-padding-fields.patch b/SOURCES/kvm-target-i386-kvm-do-not-initialize-padding-fields.patch new file mode 100644 index 0000000..8f32cad --- /dev/null +++ b/SOURCES/kvm-target-i386-kvm-do-not-initialize-padding-fields.patch @@ -0,0 +1,52 @@ +From 61f0e94fd78c21f2d7e1b2893dc11103399a0efe Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Mon, 22 Jul 2019 18:22:12 +0100 +Subject: [PATCH 31/39] target-i386: kvm: do not initialize padding fields + +RH-Author: Paolo Bonzini +Message-id: <20190722182220.19374-11-pbonzini@redhat.com> +Patchwork-id: 89627 +O-Subject: [RHEL-8.1.0 PATCH qemu-kvm v3 10/18] target-i386: kvm: do not initialize padding fields +Bugzilla: 1689269 +RH-Acked-by: Peter Xu +RH-Acked-by: Laurent Vivier +RH-Acked-by: Dr. David Alan Gilbert + +The exception.pad field is going to be renamed to pending in an upcoming +header file update. Remove the unnecessary initialization; it was +introduced to please valgrind (commit 7e680753cfa2) but they were later +rendered unnecessary by commit 076796f8fd27f4d, which added the "= {}" +initializer to the declaration of "events". Therefore the patch does +not change behavior in any way. + +Reviewed-by: Peter Maydell +Signed-off-by: Paolo Bonzini +(cherry picked from commit b31c003895b030bea1319037d6bec976d47d9020) +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/kvm.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/target/i386/kvm.c b/target/i386/kvm.c +index f741e8b..8a6da90 100644 +--- a/target/i386/kvm.c ++++ b/target/i386/kvm.c +@@ -2696,7 +2696,6 @@ static int kvm_put_vcpu_events(X86CPU *cpu, int level) + events.exception.nr = env->exception_injected; + events.exception.has_error_code = env->has_error_code; + events.exception.error_code = env->error_code; +- events.exception.pad = 0; + + events.interrupt.injected = (env->interrupt_injected >= 0); + events.interrupt.nr = env->interrupt_injected; +@@ -2705,7 +2704,6 @@ static int kvm_put_vcpu_events(X86CPU *cpu, int level) + events.nmi.injected = env->nmi_injected; + events.nmi.pending = env->nmi_pending; + events.nmi.masked = !!(env->hflags2 & HF2_NMI_MASK); +- events.nmi.pad = 0; + + events.sipi_vector = env->sipi_vector; + events.flags = 0; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-kvm-just-return-after-migrate_add_blocke.patch b/SOURCES/kvm-target-i386-kvm-just-return-after-migrate_add_blocke.patch new file mode 100644 index 0000000..2a3cbc8 --- /dev/null +++ b/SOURCES/kvm-target-i386-kvm-just-return-after-migrate_add_blocke.patch @@ -0,0 +1,45 @@ +From 28e39ed55e3b01d883e0fa7d2d65937769fa5f72 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Mon, 22 Jul 2019 18:22:06 +0100 +Subject: [PATCH 25/39] target/i386: kvm: just return after migrate_add_blocker + failed + +RH-Author: Paolo Bonzini +Message-id: <20190722182220.19374-5-pbonzini@redhat.com> +Patchwork-id: 89622 +O-Subject: [RHEL-8.1.0 PATCH qemu-kvm v3 04/18] target/i386: kvm: just return after migrate_add_blocker failed +Bugzilla: 1689269 +RH-Acked-by: Peter Xu +RH-Acked-by: Laurent Vivier +RH-Acked-by: Dr. David Alan Gilbert + +From: Li Qiang + +When migrate_add_blocker failed, the invtsc_mig_blocker is not +appended so no need to remove. This can save several instructions. + +Signed-off-by: Li Qiang +Message-Id: <20181006091816.7659-1-liq3ea@163.com> +Signed-off-by: Paolo Bonzini +(cherry picked from commit 0c2ed83fa45aa5d80ecc7d3fff0ab38db2db5972) +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/kvm.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/target/i386/kvm.c b/target/i386/kvm.c +index d414187..875412c 100644 +--- a/target/i386/kvm.c ++++ b/target/i386/kvm.c +@@ -1142,7 +1142,7 @@ int kvm_arch_init_vcpu(CPUState *cs) + if (local_err) { + error_report_err(local_err); + error_free(invtsc_mig_blocker); +- goto fail; ++ return r; + } + /* for savevm */ + vmstate_x86_cpu.unmigratable = 1; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-rename-HF_SVMI_MASK-to-HF_GUEST_MASK.patch b/SOURCES/kvm-target-i386-rename-HF_SVMI_MASK-to-HF_GUEST_MASK.patch new file mode 100644 index 0000000..63d5112 --- /dev/null +++ b/SOURCES/kvm-target-i386-rename-HF_SVMI_MASK-to-HF_GUEST_MASK.patch @@ -0,0 +1,150 @@ +From 9d1e37615a8285d852b7d8f829b9f9aeed703f14 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Mon, 22 Jul 2019 18:22:04 +0100 +Subject: [PATCH 23/39] target/i386: rename HF_SVMI_MASK to HF_GUEST_MASK + +RH-Author: Paolo Bonzini +Message-id: <20190722182220.19374-3-pbonzini@redhat.com> +Patchwork-id: 89620 +O-Subject: [RHEL-8.1.0 PATCH qemu-kvm v3 02/18] target/i386: rename HF_SVMI_MASK to HF_GUEST_MASK +Bugzilla: 1689269 +RH-Acked-by: Peter Xu +RH-Acked-by: Laurent Vivier +RH-Acked-by: Dr. David Alan Gilbert + +This flag will be used for KVM's nested VMX migration; the HF_GUEST_MASK name +is already used in KVM, adopt it in QEMU as well. + +Signed-off-by: Paolo Bonzini +(cherry picked from commit f8dc4c645ec2956a6cd97e0ca0fdd4753181f735) +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.h | 4 ++-- + target/i386/excp_helper.c | 2 +- + target/i386/seg_helper.c | 6 +++--- + target/i386/svm_helper.c | 6 +++--- + target/i386/translate.c | 4 ++-- + 5 files changed, 11 insertions(+), 11 deletions(-) + +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index 4f9df6e..923dfcd 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -171,7 +171,7 @@ typedef enum X86Seg { + #define HF_AC_SHIFT 18 /* must be same as eflags */ + #define HF_SMM_SHIFT 19 /* CPU in SMM mode */ + #define HF_SVME_SHIFT 20 /* SVME enabled (copy of EFER.SVME) */ +-#define HF_SVMI_SHIFT 21 /* SVM intercepts are active */ ++#define HF_GUEST_SHIFT 21 /* SVM intercepts are active */ + #define HF_OSFXSR_SHIFT 22 /* CR4.OSFXSR */ + #define HF_SMAP_SHIFT 23 /* CR4.SMAP */ + #define HF_IOBPT_SHIFT 24 /* an io breakpoint enabled */ +@@ -196,7 +196,7 @@ typedef enum X86Seg { + #define HF_AC_MASK (1 << HF_AC_SHIFT) + #define HF_SMM_MASK (1 << HF_SMM_SHIFT) + #define HF_SVME_MASK (1 << HF_SVME_SHIFT) +-#define HF_SVMI_MASK (1 << HF_SVMI_SHIFT) ++#define HF_GUEST_MASK (1 << HF_GUEST_SHIFT) + #define HF_OSFXSR_MASK (1 << HF_OSFXSR_SHIFT) + #define HF_SMAP_MASK (1 << HF_SMAP_SHIFT) + #define HF_IOBPT_MASK (1 << HF_IOBPT_SHIFT) +diff --git a/target/i386/excp_helper.c b/target/i386/excp_helper.c +index cb4d1b7..7153837 100644 +--- a/target/i386/excp_helper.c ++++ b/target/i386/excp_helper.c +@@ -53,7 +53,7 @@ static int check_exception(CPUX86State *env, int intno, int *error_code, + + #if !defined(CONFIG_USER_ONLY) + if (env->old_exception == EXCP08_DBLE) { +- if (env->hflags & HF_SVMI_MASK) { ++ if (env->hflags & HF_GUEST_MASK) { + cpu_vmexit(env, SVM_EXIT_SHUTDOWN, 0, retaddr); /* does not return */ + } + +diff --git a/target/i386/seg_helper.c b/target/i386/seg_helper.c +index 600a4d7..f028045 100644 +--- a/target/i386/seg_helper.c ++++ b/target/i386/seg_helper.c +@@ -1239,7 +1239,7 @@ static void do_interrupt_all(X86CPU *cpu, int intno, int is_int, + } + if (env->cr[0] & CR0_PE_MASK) { + #if !defined(CONFIG_USER_ONLY) +- if (env->hflags & HF_SVMI_MASK) { ++ if (env->hflags & HF_GUEST_MASK) { + handle_even_inj(env, intno, is_int, error_code, is_hw, 0); + } + #endif +@@ -1254,7 +1254,7 @@ static void do_interrupt_all(X86CPU *cpu, int intno, int is_int, + } + } else { + #if !defined(CONFIG_USER_ONLY) +- if (env->hflags & HF_SVMI_MASK) { ++ if (env->hflags & HF_GUEST_MASK) { + handle_even_inj(env, intno, is_int, error_code, is_hw, 1); + } + #endif +@@ -1262,7 +1262,7 @@ static void do_interrupt_all(X86CPU *cpu, int intno, int is_int, + } + + #if !defined(CONFIG_USER_ONLY) +- if (env->hflags & HF_SVMI_MASK) { ++ if (env->hflags & HF_GUEST_MASK) { + CPUState *cs = CPU(cpu); + uint32_t event_inj = x86_ldl_phys(cs, env->vm_vmcb + + offsetof(struct vmcb, +diff --git a/target/i386/svm_helper.c b/target/i386/svm_helper.c +index 3504923..5b8458d 100644 +--- a/target/i386/svm_helper.c ++++ b/target/i386/svm_helper.c +@@ -206,7 +206,7 @@ void helper_vmrun(CPUX86State *env, int aflag, int next_eip_addend) + )); + + /* enable intercepts */ +- env->hflags |= HF_SVMI_MASK; ++ env->hflags |= HF_GUEST_MASK; + + env->tsc_offset = x86_ldq_phys(cs, env->vm_vmcb + + offsetof(struct vmcb, control.tsc_offset)); +@@ -481,7 +481,7 @@ void cpu_svm_check_intercept_param(CPUX86State *env, uint32_t type, + { + CPUState *cs = CPU(x86_env_get_cpu(env)); + +- if (likely(!(env->hflags & HF_SVMI_MASK))) { ++ if (likely(!(env->hflags & HF_GUEST_MASK))) { + return; + } + switch (type) { +@@ -674,7 +674,7 @@ void do_vmexit(CPUX86State *env, uint32_t exit_code, uint64_t exit_info_1) + + /* Reload the host state from vm_hsave */ + env->hflags2 &= ~(HF2_HIF_MASK | HF2_VINTR_MASK); +- env->hflags &= ~HF_SVMI_MASK; ++ env->hflags &= ~HF_GUEST_MASK; + env->intercept = 0; + env->intercept_exceptions = 0; + cs->interrupt_request &= ~CPU_INTERRUPT_VIRQ; +diff --git a/target/i386/translate.c b/target/i386/translate.c +index c9ed8dc..2a1b39e 100644 +--- a/target/i386/translate.c ++++ b/target/i386/translate.c +@@ -621,7 +621,7 @@ static void gen_check_io(DisasContext *s, TCGMemOp ot, target_ulong cur_eip, + tcg_abort(); + } + } +- if(s->flags & HF_SVMI_MASK) { ++ if(s->flags & HF_GUEST_MASK) { + gen_update_cc_op(s); + gen_jmp_im(cur_eip); + svm_flags |= (1 << (4 + ot)); +@@ -2305,7 +2305,7 @@ gen_svm_check_intercept_param(DisasContext *s, target_ulong pc_start, + uint32_t type, uint64_t param) + { + /* no SVM activated; fast case */ +- if (likely(!(s->flags & HF_SVMI_MASK))) ++ if (likely(!(s->flags & HF_GUEST_MASK))) + return; + gen_update_cc_op(s); + gen_jmp_im(pc_start - s->cs_base); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-sev-Do-not-pin-the-ram-device-memory-reg.patch b/SOURCES/kvm-target-i386-sev-Do-not-pin-the-ram-device-memory-reg.patch new file mode 100644 index 0000000..dcd414b --- /dev/null +++ b/SOURCES/kvm-target-i386-sev-Do-not-pin-the-ram-device-memory-reg.patch @@ -0,0 +1,75 @@ +From 660e7dc57899e79e85c19baa93be009b0382ae8e Mon Sep 17 00:00:00 2001 +From: Gary R Hook +Date: Wed, 10 Apr 2019 00:08:03 +0100 +Subject: [PATCH 3/5] target/i386: sev: Do not pin the ram device memory region + +RH-Author: Gary R Hook +Message-id: <20190410000803.1744-3-ghook@redhat.com> +Patchwork-id: 85542 +O-Subject: [RHEL-8.1 virt 2/2] target/i386: sev: Do not pin the ram device memory region +Bugzilla: 1667249 +RH-Acked-by: Eduardo Habkost +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Alex Williamson + +BZ: 1667249 +Branch: rhel-8.1.0 +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1667249 +Upstream Status: 4.0.0-rc1 +Build Info: https://brewweb.engineering.redhat.com/brew/taskinfo?taskID=20980582 +Conflicts: None + +commit cedc0ad539afbbb669dba9e73dfad2915bc1c25b +Author: Singh, Brijesh +Date: Mon Feb 4 22:23:40 2019 +0000 + + target/i386: sev: Do not pin the ram device memory region + + The RAM device presents a memory region that should be handled + as an IO region and should not be pinned. + + In the case of the vfio-pci, RAM device represents a MMIO BAR + and the memory region is not backed by pages hence + KVM_MEMORY_ENCRYPT_REG_REGION fails to lock the memory range. + + Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1667249 + Cc: Alex Williamson + Cc: Paolo Bonzini + Signed-off-by: Brijesh Singh + Message-Id: <20190204222322.26766-3-brijesh.singh@amd.com> + Signed-off-by: Paolo Bonzini + +Cc: Paolo Bonzini +Cc: Richard Henderson +Cc: Eduardo Habkost +Cc: qemu-devel@nongnu.org +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/sev.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/target/i386/sev.c b/target/i386/sev.c +index 2395171..b8009b0 100644 +--- a/target/i386/sev.c ++++ b/target/i386/sev.c +@@ -130,6 +130,17 @@ sev_ram_block_added(RAMBlockNotifier *n, void *host, size_t size) + { + int r; + struct kvm_enc_region range; ++ ram_addr_t offset; ++ MemoryRegion *mr; ++ ++ /* ++ * The RAM device presents a memory region that should be treated ++ * as IO region and should not be pinned. ++ */ ++ mr = memory_region_from_host(host, &offset); ++ if (mr && memory_region_is_ram_device(mr)) { ++ return; ++ } + + range.addr = (__u64)(unsigned long)host; + range.size = size; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-sev-Do-not-unpin-ram-device-memory-regio.patch b/SOURCES/kvm-target-i386-sev-Do-not-unpin-ram-device-memory-regio.patch new file mode 100644 index 0000000..487e127 --- /dev/null +++ b/SOURCES/kvm-target-i386-sev-Do-not-unpin-ram-device-memory-regio.patch @@ -0,0 +1,59 @@ +From b150f14fa8adcfe255c0380427e31d033bd44789 Mon Sep 17 00:00:00 2001 +From: Alex Williamson +Date: Mon, 22 Jul 2019 18:09:47 +0100 +Subject: [PATCH 21/39] target/i386: sev: Do not unpin ram device memory region + +RH-Author: Alex Williamson +Message-id: <156381893103.14196.5165276806848335745.stgit@gimli.home> +Patchwork-id: 89617 +O-Subject: [RHEL-8.1 qemu-kvm PATCH] target/i386: sev: Do not unpin ram device memory region +Bugzilla: 1728958 +RH-Acked-by: Eduardo Habkost +RH-Acked-by: Auger Eric +RH-Acked-by: Laszlo Ersek + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1728958 +Brew: https://brewweb.engineering.redhat.com/brew/taskinfo?taskID=22722091 +Branch: rhel-8.1.0 + +The commit referenced below skipped pinning ram device memory when +ram blocks are added, we need to do the same when they're removed. + +Cc: Brijesh Singh +Cc: Paolo Bonzini +Fixes: cedc0ad539af ("target/i386: sev: Do not pin the ram device memory region") +Signed-off-by: Alex Williamson +Message-Id: <156320087103.2556.10983987500488190423.stgit@gimli.home> +Reviewed-by: Singh, Brijesh +Signed-off-by: Paolo Bonzini +(cherry picked from commit 56e2ec9488b3b281130e064929f8ae5595d6ac39) +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/sev.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/target/i386/sev.c b/target/i386/sev.c +index b8009b0..7051a30 100644 +--- a/target/i386/sev.c ++++ b/target/i386/sev.c +@@ -159,6 +159,17 @@ sev_ram_block_removed(RAMBlockNotifier *n, void *host, size_t size) + { + int r; + struct kvm_enc_region range; ++ ram_addr_t offset; ++ MemoryRegion *mr; ++ ++ /* ++ * The RAM device presents a memory region that should be treated ++ * as IO region and should not have been pinned. ++ */ ++ mr = memory_region_from_host(host, &offset); ++ if (mr && memory_region_is_ram_device(mr)) { ++ return; ++ } + + range.addr = (__u64)(unsigned long)host; + range.size = size; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-skip-KVM_GET-SET_NESTED_STATE-if-VMX-dis.patch b/SOURCES/kvm-target-i386-skip-KVM_GET-SET_NESTED_STATE-if-VMX-dis.patch new file mode 100644 index 0000000..dbf7d93 --- /dev/null +++ b/SOURCES/kvm-target-i386-skip-KVM_GET-SET_NESTED_STATE-if-VMX-dis.patch @@ -0,0 +1,126 @@ +From a8a32dd460a1d838cfe97ec53a2eb76c018c5dbf Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Mon, 22 Jul 2019 18:22:19 +0100 +Subject: [PATCH 38/39] target/i386: skip KVM_GET/SET_NESTED_STATE if VMX + disabled, or for SVM + +RH-Author: Paolo Bonzini +Message-id: <20190722182220.19374-18-pbonzini@redhat.com> +Patchwork-id: 89636 +O-Subject: [RHEL-8.1.0 PATCH qemu-kvm v3 17/18] target/i386: skip KVM_GET/SET_NESTED_STATE if VMX disabled, or for SVM +Bugzilla: 1689269 +RH-Acked-by: Peter Xu +RH-Acked-by: Laurent Vivier +RH-Acked-by: Dr. David Alan Gilbert + +Do not allocate env->nested_state unless we later need to migrate the +nested virtualization state. + +With this change, nested_state_needed() will return false if the +VMX flag is not included in the virtual machine. KVM_GET/SET_NESTED_STATE +is also disabled for SVM which is safer (we know that at least the NPT +root and paging mode have to be saved/loaded), and thus the corresponding +subsection can go away as well. + +Inspired by a patch from Liran Alon. + +Signed-off-by: Paolo Bonzini +(cherry picked from commit 1e44f3ab71fb4291d266a264f7c207ae5c6d59b2) +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/kvm.c | 16 ++++++++-------- + target/i386/machine.c | 21 +-------------------- + 2 files changed, 9 insertions(+), 28 deletions(-) + +diff --git a/target/i386/kvm.c b/target/i386/kvm.c +index 0bd286e..8648f1f 100644 +--- a/target/i386/kvm.c ++++ b/target/i386/kvm.c +@@ -1220,15 +1220,15 @@ int kvm_arch_init_vcpu(CPUState *cs) + max_nested_state_len = kvm_max_nested_state_length(); + if (max_nested_state_len > 0) { + assert(max_nested_state_len >= offsetof(struct kvm_nested_state, data)); +- env->nested_state = g_malloc0(max_nested_state_len); + +- env->nested_state->size = max_nested_state_len; +- +- if (IS_INTEL_CPU(env)) { +- struct kvm_vmx_nested_state_hdr *vmx_hdr = +- &env->nested_state->hdr.vmx; ++ if (cpu_has_vmx(env)) { ++ struct kvm_vmx_nested_state_hdr *vmx_hdr; + ++ env->nested_state = g_malloc0(max_nested_state_len); ++ env->nested_state->size = max_nested_state_len; + env->nested_state->format = KVM_STATE_NESTED_FORMAT_VMX; ++ ++ vmx_hdr = &env->nested_state->hdr.vmx; + vmx_hdr->vmxon_pa = -1ull; + vmx_hdr->vmcs12_pa = -1ull; + } +@@ -2966,7 +2966,7 @@ static int kvm_put_nested_state(X86CPU *cpu) + CPUX86State *env = &cpu->env; + int max_nested_state_len = kvm_max_nested_state_length(); + +- if (max_nested_state_len <= 0) { ++ if (!env->nested_state) { + return 0; + } + +@@ -2980,7 +2980,7 @@ static int kvm_get_nested_state(X86CPU *cpu) + int max_nested_state_len = kvm_max_nested_state_length(); + int ret; + +- if (max_nested_state_len <= 0) { ++ if (!env->nested_state) { + return 0; + } + +diff --git a/target/i386/machine.c b/target/i386/machine.c +index 8d90d98..fa8d1cc 100644 +--- a/target/i386/machine.c ++++ b/target/i386/machine.c +@@ -1004,31 +1004,13 @@ static const VMStateDescription vmstate_vmx_nested_state = { + } + }; + +-static bool svm_nested_state_needed(void *opaque) +-{ +- struct kvm_nested_state *nested_state = opaque; +- +- return (nested_state->format == KVM_STATE_NESTED_FORMAT_SVM); +-} +- +-static const VMStateDescription vmstate_svm_nested_state = { +- .name = "cpu/kvm_nested_state/svm", +- .version_id = 1, +- .minimum_version_id = 1, +- .needed = svm_nested_state_needed, +- .fields = (VMStateField[]) { +- VMSTATE_END_OF_LIST() +- } +-}; +- + static bool nested_state_needed(void *opaque) + { + X86CPU *cpu = opaque; + CPUX86State *env = &cpu->env; + + return (env->nested_state && +- (vmx_nested_state_needed(env->nested_state) || +- svm_nested_state_needed(env->nested_state))); ++ vmx_nested_state_needed(env->nested_state)); + } + + static int nested_state_post_load(void *opaque, int version_id) +@@ -1090,7 +1072,6 @@ static const VMStateDescription vmstate_kvm_nested_state = { + }, + .subsections = (const VMStateDescription*[]) { + &vmstate_vmx_nested_state, +- &vmstate_svm_nested_state, + NULL + } + }; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-ppc-spapr-Add-SPAPR_CAP_CCF_ASSIST.patch b/SOURCES/kvm-target-ppc-spapr-Add-SPAPR_CAP_CCF_ASSIST.patch new file mode 100644 index 0000000..a87ebe8 --- /dev/null +++ b/SOURCES/kvm-target-ppc-spapr-Add-SPAPR_CAP_CCF_ASSIST.patch @@ -0,0 +1,244 @@ +From d63d52e74a9af9d7d45f5734c4a6e127c3ecc0b4 Mon Sep 17 00:00:00 2001 +From: Sam Bobroff +Date: Thu, 29 Aug 2019 05:53:36 +0100 +Subject: [PATCH 03/10] target/ppc/spapr: Add SPAPR_CAP_CCF_ASSIST + +RH-Author: Sam Bobroff +Message-id: <80714b6e8fc19054881e9c1eaf1b8a332f8e104f.1567057498.git.sbobroff@redhat.com> +Patchwork-id: 90189 +O-Subject: [RHEL8.1 qemu-kvm BZ1744415 PATCH 2/2] target/ppc/spapr: Add SPAPR_CAP_CCF_ASSIST +Bugzilla: 1744415 +RH-Acked-by: David Gibson +RH-Acked-by: Laurent Vivier +RH-Acked-by: Thomas Huth + +From: Suraj Jitindar Singh + +Introduce a new spapr_cap SPAPR_CAP_CCF_ASSIST to be used to indicate +the requirement for a hw-assisted version of the count cache flush +workaround. + +The count cache flush workaround is a software workaround which can be +used to flush the count cache on context switch. Some revisions of +hardware may have a hardware accelerated flush, in which case the +software flush can be shortened. This cap is used to set the +availability of such hardware acceleration for the count cache flush +routine. + +The availability of such hardware acceleration is indicated by the +H_CPU_CHAR_BCCTR_FLUSH_ASSIST flag being set in the characteristics +returned from the KVM_PPC_GET_CPU_CHAR ioctl. + +Signed-off-by: Suraj Jitindar Singh +Message-Id: <20190301031912.28809-2-sjitindarsingh@gmail.com> +[dwg: Small style fixes] +Signed-off-by: David Gibson +(cherry picked from commit 8ff43ee404d3e295839d1fd4e9e6571ca7a62a66) +[SB: Minor fixup for context change.] + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1744415 +Brew: https://brewweb.engineering.redhat.com/brew/taskinfo?taskID=23229146 +Signed-off-by: Sam Bobroff +Testing: QEMU -M cap-ibs=workaround,cap-ccf-assist=on, check guest dmesg +Signed-off-by: Danilo C. L. de Paula +--- + hw/ppc/spapr.c | 2 ++ + hw/ppc/spapr_caps.c | 25 +++++++++++++++++++++++++ + hw/ppc/spapr_hcall.c | 5 +++++ + include/hw/ppc/spapr.h | 5 ++++- + target/ppc/kvm.c | 16 ++++++++++++++++ + target/ppc/kvm_ppc.h | 6 ++++++ + 6 files changed, 58 insertions(+), 1 deletion(-) + +diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c +index c72aad1..1a2f0d9 100644 +--- a/hw/ppc/spapr.c ++++ b/hw/ppc/spapr.c +@@ -1828,6 +1828,7 @@ static const VMStateDescription vmstate_spapr = { + &vmstate_spapr_cap_sbbc, + &vmstate_spapr_cap_ibs, + &vmstate_spapr_cap_nested_kvm_hv, ++ &vmstate_spapr_cap_ccf_assist, + NULL + } + }; +@@ -3939,6 +3940,7 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data) + smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_BROKEN; + smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_BROKEN; + smc->default_caps.caps[SPAPR_CAP_NESTED_KVM_HV] = SPAPR_CAP_OFF; ++ smc->default_caps.caps[SPAPR_CAP_CCF_ASSIST] = SPAPR_CAP_OFF; + spapr_caps_add_properties(smc, &error_abort); + smc->has_power9_support = true; + } +diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c +index dfc8cce..5353255 100644 +--- a/hw/ppc/spapr_caps.c ++++ b/hw/ppc/spapr_caps.c +@@ -285,6 +285,21 @@ static void cap_nested_kvm_hv_apply(sPAPRMachineState *spapr, + } + } + ++static void cap_ccf_assist_apply(sPAPRMachineState *spapr, uint8_t val, ++ Error **errp) ++{ ++ uint8_t kvm_val = kvmppc_get_cap_count_cache_flush_assist(); ++ ++ if (tcg_enabled() && val) { ++ /* TODO - for now only allow broken for TCG */ ++ error_setg(errp, ++"Requested count cache flush assist capability level not supported by tcg, try cap-ccf-assist=off"); ++ } else if (kvm_enabled() && (val > kvm_val)) { ++ error_setg(errp, ++"Requested count cache flush assist capability level not supported by kvm, try cap-ccf-assist=off"); ++ } ++} ++ + sPAPRCapabilityInfo capability_table[SPAPR_CAP_NUM] = { + [SPAPR_CAP_HTM] = { + .name = "htm", +@@ -354,6 +369,15 @@ sPAPRCapabilityInfo capability_table[SPAPR_CAP_NUM] = { + .type = "bool", + .apply = cap_nested_kvm_hv_apply, + }, ++ [SPAPR_CAP_CCF_ASSIST] = { ++ .name = "ccf-assist", ++ .description = "Count Cache Flush Assist via HW Instruction", ++ .index = SPAPR_CAP_CCF_ASSIST, ++ .get = spapr_cap_get_bool, ++ .set = spapr_cap_set_bool, ++ .type = "bool", ++ .apply = cap_ccf_assist_apply, ++ }, + }; + + static sPAPRCapabilities default_caps_with_cpu(sPAPRMachineState *spapr, +@@ -470,6 +494,7 @@ SPAPR_CAP_MIG_STATE(cfpc, SPAPR_CAP_CFPC); + SPAPR_CAP_MIG_STATE(sbbc, SPAPR_CAP_SBBC); + SPAPR_CAP_MIG_STATE(ibs, SPAPR_CAP_IBS); + SPAPR_CAP_MIG_STATE(nested_kvm_hv, SPAPR_CAP_NESTED_KVM_HV); ++SPAPR_CAP_MIG_STATE(ccf_assist, SPAPR_CAP_CCF_ASSIST); + + void spapr_caps_reset(sPAPRMachineState *spapr) + { +diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c +index 01c4215..141d1f4 100644 +--- a/hw/ppc/spapr_hcall.c ++++ b/hw/ppc/spapr_hcall.c +@@ -1675,6 +1675,8 @@ static target_ulong h_get_cpu_characteristics(PowerPCCPU *cpu, + uint8_t safe_cache = spapr_get_cap(spapr, SPAPR_CAP_CFPC); + uint8_t safe_bounds_check = spapr_get_cap(spapr, SPAPR_CAP_SBBC); + uint8_t safe_indirect_branch = spapr_get_cap(spapr, SPAPR_CAP_IBS); ++ uint8_t count_cache_flush_assist = spapr_get_cap(spapr, ++ SPAPR_CAP_CCF_ASSIST); + + switch (safe_cache) { + case SPAPR_CAP_WORKAROUND: +@@ -1715,6 +1717,9 @@ static target_ulong h_get_cpu_characteristics(PowerPCCPU *cpu, + break; + case SPAPR_CAP_WORKAROUND: + behaviour |= H_CPU_BEHAV_FLUSH_COUNT_CACHE; ++ if (count_cache_flush_assist) { ++ characteristics |= H_CPU_CHAR_BCCTR_FLUSH_ASSIST; ++ } + break; + default: /* broken */ + assert(safe_indirect_branch == SPAPR_CAP_BROKEN); +diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h +index 8bb95bb..4aff3b6 100644 +--- a/include/hw/ppc/spapr.h ++++ b/include/hw/ppc/spapr.h +@@ -68,8 +68,10 @@ typedef enum { + #define SPAPR_CAP_IBS 0x05 + /* Nested KVM-HV */ + #define SPAPR_CAP_NESTED_KVM_HV 0x06 ++/* Count Cache Flush Assist HW Instruction */ ++#define SPAPR_CAP_CCF_ASSIST 0x07 + /* Num Caps */ +-#define SPAPR_CAP_NUM (SPAPR_CAP_NESTED_KVM_HV + 1) ++#define SPAPR_CAP_NUM (SPAPR_CAP_CCF_ASSIST + 1) + + /* + * Capability Values +@@ -807,6 +809,7 @@ extern const VMStateDescription vmstate_spapr_cap_cfpc; + extern const VMStateDescription vmstate_spapr_cap_sbbc; + extern const VMStateDescription vmstate_spapr_cap_ibs; + extern const VMStateDescription vmstate_spapr_cap_nested_kvm_hv; ++extern const VMStateDescription vmstate_spapr_cap_ccf_assist; + + static inline uint8_t spapr_get_cap(sPAPRMachineState *spapr, int cap) + { +diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c +index 0e94cfc..8f90ee5 100644 +--- a/target/ppc/kvm.c ++++ b/target/ppc/kvm.c +@@ -92,6 +92,7 @@ static int cap_ppc_pvr_compat; + static int cap_ppc_safe_cache; + static int cap_ppc_safe_bounds_check; + static int cap_ppc_safe_indirect_branch; ++static int cap_ppc_count_cache_flush_assist; + static int cap_ppc_nested_kvm_hv; + + static uint32_t debug_inst_opcode; +@@ -2526,6 +2527,14 @@ static int parse_cap_ppc_safe_indirect_branch(struct kvm_ppc_cpu_char c) + return 0; + } + ++static int parse_cap_ppc_count_cache_flush_assist(struct kvm_ppc_cpu_char c) ++{ ++ if (c.character & c.character_mask & H_CPU_CHAR_BCCTR_FLUSH_ASSIST) { ++ return 1; ++ } ++ return 0; ++} ++ + static void kvmppc_get_cpu_characteristics(KVMState *s) + { + struct kvm_ppc_cpu_char c; +@@ -2548,6 +2557,8 @@ static void kvmppc_get_cpu_characteristics(KVMState *s) + cap_ppc_safe_cache = parse_cap_ppc_safe_cache(c); + cap_ppc_safe_bounds_check = parse_cap_ppc_safe_bounds_check(c); + cap_ppc_safe_indirect_branch = parse_cap_ppc_safe_indirect_branch(c); ++ cap_ppc_count_cache_flush_assist = ++ parse_cap_ppc_count_cache_flush_assist(c); + } + + int kvmppc_get_cap_safe_cache(void) +@@ -2565,6 +2576,11 @@ int kvmppc_get_cap_safe_indirect_branch(void) + return cap_ppc_safe_indirect_branch; + } + ++int kvmppc_get_cap_count_cache_flush_assist(void) ++{ ++ return cap_ppc_count_cache_flush_assist; ++} ++ + bool kvmppc_has_cap_nested_kvm_hv(void) + { + return !!cap_ppc_nested_kvm_hv; +diff --git a/target/ppc/kvm_ppc.h b/target/ppc/kvm_ppc.h +index dc86eff..e440c75 100644 +--- a/target/ppc/kvm_ppc.h ++++ b/target/ppc/kvm_ppc.h +@@ -63,6 +63,7 @@ bool kvmppc_has_cap_mmu_hash_v3(void); + int kvmppc_get_cap_safe_cache(void); + int kvmppc_get_cap_safe_bounds_check(void); + int kvmppc_get_cap_safe_indirect_branch(void); ++int kvmppc_get_cap_count_cache_flush_assist(void); + bool kvmppc_has_cap_nested_kvm_hv(void); + int kvmppc_set_cap_nested_kvm_hv(int enable); + int kvmppc_enable_hwrng(void); +@@ -316,6 +317,11 @@ static inline int kvmppc_get_cap_safe_indirect_branch(void) + return 0; + } + ++static inline int kvmppc_get_cap_count_cache_flush_assist(void) ++{ ++ return 0; ++} ++ + static inline bool kvmppc_has_cap_nested_kvm_hv(void) + { + return false; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-ppc-spapr-Add-workaround-option-to-SPAPR_CAP_.patch b/SOURCES/kvm-target-ppc-spapr-Add-workaround-option-to-SPAPR_CAP_.patch new file mode 100644 index 0000000..456c37e --- /dev/null +++ b/SOURCES/kvm-target-ppc-spapr-Add-workaround-option-to-SPAPR_CAP_.patch @@ -0,0 +1,173 @@ +From c1bd7825b1cbe0ff34be196effc7a18992cce269 Mon Sep 17 00:00:00 2001 +From: Sam Bobroff +Date: Thu, 29 Aug 2019 05:53:35 +0100 +Subject: [PATCH 02/10] target/ppc/spapr: Add workaround option to + SPAPR_CAP_IBS + +RH-Author: Sam Bobroff +Message-id: <67946d77e95afc19f2afc5f8dfa4e89335dbb58d.1567057498.git.sbobroff@redhat.com> +Patchwork-id: 90188 +O-Subject: [RHEL8.1 qemu-kvm BZ1744415 PATCH 1/2] target/ppc/spapr: Add workaround option to SPAPR_CAP_IBS +Bugzilla: 1744415 +RH-Acked-by: David Gibson +RH-Acked-by: Laurent Vivier +RH-Acked-by: Thomas Huth + +From: Suraj Jitindar Singh + +The spapr_cap SPAPR_CAP_IBS is used to indicate the level of capability +for mitigations for indirect branch speculation. Currently the available +values are broken (default), fixed-ibs (fixed by serialising indirect +branches) and fixed-ccd (fixed by diabling the count cache). + +Introduce a new value for this capability denoted workaround, meaning that +software can work around the issue by flushing the count cache on +context switch. This option is available if the hypervisor sets the +H_CPU_BEHAV_FLUSH_COUNT_CACHE flag in the cpu behaviours returned from +the KVM_PPC_GET_CPU_CHAR ioctl. + +Signed-off-by: Suraj Jitindar Singh +Message-Id: <20190301031912.28809-1-sjitindarsingh@gmail.com> +Signed-off-by: David Gibson +(cherry picked from commit 399b2896d4948a1ec0278d896ea3a561df768d64) + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1744415 +Brew: https://brewweb.engineering.redhat.com/brew/taskinfo?taskID=23229146 +Signed-off-by: Sam Bobroff +Testing: Start QEMU with -M cap-ibs=workaround, check guest dmesg +Signed-off-by: Danilo C. L. de Paula +--- + hw/ppc/spapr_caps.c | 21 ++++++++++----------- + hw/ppc/spapr_hcall.c | 5 +++++ + include/hw/ppc/spapr.h | 7 +++++++ + target/ppc/kvm.c | 8 +++++++- + 4 files changed, 29 insertions(+), 12 deletions(-) + +diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c +index 86a7947..dfc8cce 100644 +--- a/hw/ppc/spapr_caps.c ++++ b/hw/ppc/spapr_caps.c +@@ -236,11 +236,13 @@ static void cap_safe_bounds_check_apply(sPAPRMachineState *spapr, uint8_t val, + } + + sPAPRCapPossible cap_ibs_possible = { +- .num = 4, ++ .num = 5, + /* Note workaround only maintained for compatibility */ +- .vals = {"broken", "workaround", "fixed-ibs", "fixed-ccd"}, +- .help = "broken - no protection, fixed-ibs - indirect branch serialisation," +- " fixed-ccd - cache count disabled", ++ .vals = {"broken", "workaround", "fixed-ibs", "fixed-ccd", "fixed-na"}, ++ .help = "broken - no protection, workaround - count cache flush" ++ ", fixed-ibs - indirect branch serialisation," ++ " fixed-ccd - cache count disabled," ++ " fixed-na - fixed in hardware (no longer applicable)", + }; + + static void cap_safe_indirect_branch_apply(sPAPRMachineState *spapr, +@@ -248,15 +250,11 @@ static void cap_safe_indirect_branch_apply(sPAPRMachineState *spapr, + { + uint8_t kvm_val = kvmppc_get_cap_safe_indirect_branch(); + +- if (val == SPAPR_CAP_WORKAROUND) { /* Can only be Broken or Fixed */ +- error_setg(errp, +-"Requested safe indirect branch capability level \"workaround\" not valid, try cap-ibs=%s", +- cap_ibs_possible.vals[kvm_val]); +- } else if (tcg_enabled() && val) { ++ if (tcg_enabled() && val) { + /* TODO - for now only allow broken for TCG */ + error_setg(errp, + "Requested safe indirect branch capability level not supported by tcg, try a different value for cap-ibs"); +- } else if (kvm_enabled() && val && (val != kvm_val)) { ++ } else if (kvm_enabled() && (val > kvm_val)) { + error_setg(errp, + "Requested safe indirect branch capability level not supported by kvm, try cap-ibs=%s", + cap_ibs_possible.vals[kvm_val]); +@@ -338,7 +336,8 @@ sPAPRCapabilityInfo capability_table[SPAPR_CAP_NUM] = { + [SPAPR_CAP_IBS] = { + .name = "ibs", + .description = +- "Indirect Branch Speculation (broken, fixed-ibs, fixed-ccd)", ++ "Indirect Branch Speculation (broken, workaround, fixed-ibs," ++ "fixed-ccd, fixed-na)", + .index = SPAPR_CAP_IBS, + .get = spapr_cap_get_string, + .set = spapr_cap_set_string, +diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c +index 16bccdd..01c4215 100644 +--- a/hw/ppc/spapr_hcall.c ++++ b/hw/ppc/spapr_hcall.c +@@ -1705,12 +1705,17 @@ static target_ulong h_get_cpu_characteristics(PowerPCCPU *cpu, + } + + switch (safe_indirect_branch) { ++ case SPAPR_CAP_FIXED_NA: ++ break; + case SPAPR_CAP_FIXED_CCD: + characteristics |= H_CPU_CHAR_CACHE_COUNT_DIS; + break; + case SPAPR_CAP_FIXED_IBS: + characteristics |= H_CPU_CHAR_BCCTRL_SERIALISED; + break; ++ case SPAPR_CAP_WORKAROUND: ++ behaviour |= H_CPU_BEHAV_FLUSH_COUNT_CACHE; ++ break; + default: /* broken */ + assert(safe_indirect_branch == SPAPR_CAP_BROKEN); + break; +diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h +index 72cfa49..8bb95bb 100644 +--- a/include/hw/ppc/spapr.h ++++ b/include/hw/ppc/spapr.h +@@ -77,12 +77,17 @@ typedef enum { + /* Bool Caps */ + #define SPAPR_CAP_OFF 0x00 + #define SPAPR_CAP_ON 0x01 ++ + /* Custom Caps */ ++ ++/* Generic */ + #define SPAPR_CAP_BROKEN 0x00 + #define SPAPR_CAP_WORKAROUND 0x01 + #define SPAPR_CAP_FIXED 0x02 ++/* SPAPR_CAP_IBS (cap-ibs) */ + #define SPAPR_CAP_FIXED_IBS 0x02 + #define SPAPR_CAP_FIXED_CCD 0x03 ++#define SPAPR_CAP_FIXED_NA 0x10 /* Lets leave a bit of a gap... */ + + typedef struct sPAPRCapabilities sPAPRCapabilities; + struct sPAPRCapabilities { +@@ -322,9 +327,11 @@ struct sPAPRMachineState { + #define H_CPU_CHAR_HON_BRANCH_HINTS PPC_BIT(5) + #define H_CPU_CHAR_THR_RECONF_TRIG PPC_BIT(6) + #define H_CPU_CHAR_CACHE_COUNT_DIS PPC_BIT(7) ++#define H_CPU_CHAR_BCCTR_FLUSH_ASSIST PPC_BIT(9) + #define H_CPU_BEHAV_FAVOUR_SECURITY PPC_BIT(0) + #define H_CPU_BEHAV_L1D_FLUSH_PR PPC_BIT(1) + #define H_CPU_BEHAV_BNDS_CHK_SPEC_BAR PPC_BIT(2) ++#define H_CPU_BEHAV_FLUSH_COUNT_CACHE PPC_BIT(5) + + /* Each control block has to be on a 4K boundary */ + #define H_CB_ALIGNMENT 4096 +diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c +index b9858fa..0e94cfc 100644 +--- a/target/ppc/kvm.c ++++ b/target/ppc/kvm.c +@@ -2511,7 +2511,13 @@ static int parse_cap_ppc_safe_bounds_check(struct kvm_ppc_cpu_char c) + + static int parse_cap_ppc_safe_indirect_branch(struct kvm_ppc_cpu_char c) + { +- if (c.character & c.character_mask & H_CPU_CHAR_CACHE_COUNT_DIS) { ++ if ((~c.behaviour & c.behaviour_mask & H_CPU_BEHAV_FLUSH_COUNT_CACHE) && ++ (~c.character & c.character_mask & H_CPU_CHAR_CACHE_COUNT_DIS) && ++ (~c.character & c.character_mask & H_CPU_CHAR_BCCTRL_SERIALISED)) { ++ return SPAPR_CAP_FIXED_NA; ++ } else if (c.behaviour & c.behaviour_mask & H_CPU_BEHAV_FLUSH_COUNT_CACHE) { ++ return SPAPR_CAP_WORKAROUND; ++ } else if (c.character & c.character_mask & H_CPU_CHAR_CACHE_COUNT_DIS) { + return SPAPR_CAP_FIXED_CCD; + } else if (c.character & c.character_mask & H_CPU_CHAR_BCCTRL_SERIALISED) { + return SPAPR_CAP_FIXED_IBS; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-test-bdrv-drain-AioContext-switch-in-drained-section.patch b/SOURCES/kvm-test-bdrv-drain-AioContext-switch-in-drained-section.patch new file mode 100644 index 0000000..2d8d04d --- /dev/null +++ b/SOURCES/kvm-test-bdrv-drain-AioContext-switch-in-drained-section.patch @@ -0,0 +1,76 @@ +From 7db4d6a7b791006e5b927d0a30f0106ce0c8b14d Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Wed, 14 Aug 2019 08:42:28 +0100 +Subject: [PATCH 05/10] test-bdrv-drain: AioContext switch in drained section + +RH-Author: Kevin Wolf +Message-id: <20190814084229.6458-5-kwolf@redhat.com> +Patchwork-id: 89965 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 4/5] test-bdrv-drain: AioContext switch in drained section +Bugzilla: 1716349 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Max Reitz +RH-Acked-by: Paolo Bonzini + +Signed-off-by: Kevin Wolf +Reviewed-by: Eric Blake +(cherry picked from commit 247d2737715833525725d27e5cecf5840c62f900) +Signed-off-by: Kevin Wolf +Signed-off-by: Danilo C. L. de Paula +--- + tests/test-bdrv-drain.c | 32 ++++++++++++++++++++++++++++++++ + 1 file changed, 32 insertions(+) + +diff --git a/tests/test-bdrv-drain.c b/tests/test-bdrv-drain.c +index 8641b54..05c6f12 100644 +--- a/tests/test-bdrv-drain.c ++++ b/tests/test-bdrv-drain.c +@@ -1521,6 +1521,36 @@ static void test_append_to_drained(void) + blk_unref(blk); + } + ++static void test_set_aio_context(void) ++{ ++ BlockDriverState *bs; ++ IOThread *a = iothread_new(); ++ IOThread *b = iothread_new(); ++ AioContext *ctx_a = iothread_get_aio_context(a); ++ AioContext *ctx_b = iothread_get_aio_context(b); ++ ++ bs = bdrv_new_open_driver(&bdrv_test, "test-node", BDRV_O_RDWR, ++ &error_abort); ++ ++ bdrv_drained_begin(bs); ++ bdrv_set_aio_context(bs, ctx_a); ++ ++ aio_context_acquire(ctx_a); ++ bdrv_drained_end(bs); ++ ++ bdrv_drained_begin(bs); ++ bdrv_set_aio_context(bs, ctx_b); ++ aio_context_release(ctx_a); ++ aio_context_acquire(ctx_b); ++ bdrv_set_aio_context(bs, qemu_get_aio_context()); ++ aio_context_release(ctx_b); ++ bdrv_drained_end(bs); ++ ++ bdrv_unref(bs); ++ iothread_join(a); ++ iothread_join(b); ++} ++ + int main(int argc, char **argv) + { + int ret; +@@ -1602,6 +1632,8 @@ int main(int argc, char **argv) + + g_test_add_func("/bdrv-drain/attach/drain", test_append_to_drained); + ++ g_test_add_func("/bdrv-drain/set_aio_context", test_set_aio_context); ++ + ret = g_test_run(); + qemu_event_destroy(&done_event); + return ret; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-tests-Add-unit-tests-for-image-locking.patch b/SOURCES/kvm-tests-Add-unit-tests-for-image-locking.patch new file mode 100644 index 0000000..7fd1e9d --- /dev/null +++ b/SOURCES/kvm-tests-Add-unit-tests-for-image-locking.patch @@ -0,0 +1,213 @@ +From 3722729c29997c440ff1a289228f2953d10b2e5b Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Wed, 3 Apr 2019 17:13:12 +0100 +Subject: [PATCH 05/11] tests: Add unit tests for image locking + +RH-Author: Max Reitz +Message-id: <20190403171315.20841-6-mreitz@redhat.com> +Patchwork-id: 85402 +O-Subject: [RHEL-8.1 qemu-kvm PATCH 5/8] tests: Add unit tests for image locking +Bugzilla: 1694148 +RH-Acked-by: John Snow +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Stefano Garzarella + +From: Fam Zheng + +Signed-off-by: Fam Zheng +Signed-off-by: Kevin Wolf +(cherry picked from commit aef96d7d4f0b6746e329bfa7a1ea38e1611237e3) +Signed-off-by: Max Reitz +Signed-off-by: Danilo C. L. de Paula +--- + tests/Makefile.include | 2 + + tests/test-image-locking.c | 157 +++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 159 insertions(+) + create mode 100644 tests/test-image-locking.c + +diff --git a/tests/Makefile.include b/tests/Makefile.include +index d200288..06ed6df 100644 +--- a/tests/Makefile.include ++++ b/tests/Makefile.include +@@ -97,6 +97,7 @@ check-unit-y += tests/test-bdrv-drain$(EXESUF) + check-unit-y += tests/test-blockjob$(EXESUF) + check-unit-y += tests/test-blockjob-txn$(EXESUF) + check-unit-y += tests/test-block-backend$(EXESUF) ++check-unit-y += tests/test-image-locking$(EXESUF) + check-unit-y += tests/test-x86-cpuid$(EXESUF) + # all code tested by test-x86-cpuid is inside topology.h + gcov-files-test-x86-cpuid-y = +@@ -635,6 +636,7 @@ tests/test-bdrv-drain$(EXESUF): tests/test-bdrv-drain.o $(test-block-obj-y) $(te + tests/test-blockjob$(EXESUF): tests/test-blockjob.o $(test-block-obj-y) $(test-util-obj-y) + tests/test-blockjob-txn$(EXESUF): tests/test-blockjob-txn.o $(test-block-obj-y) $(test-util-obj-y) + tests/test-block-backend$(EXESUF): tests/test-block-backend.o $(test-block-obj-y) $(test-util-obj-y) ++tests/test-image-locking$(EXESUF): tests/test-image-locking.o $(test-block-obj-y) $(test-util-obj-y) + tests/test-thread-pool$(EXESUF): tests/test-thread-pool.o $(test-block-obj-y) + tests/test-iov$(EXESUF): tests/test-iov.o $(test-util-obj-y) + tests/test-hbitmap$(EXESUF): tests/test-hbitmap.o $(test-util-obj-y) $(test-crypto-obj-y) +diff --git a/tests/test-image-locking.c b/tests/test-image-locking.c +new file mode 100644 +index 0000000..7614cbf +--- /dev/null ++++ b/tests/test-image-locking.c +@@ -0,0 +1,157 @@ ++/* ++ * Image locking tests ++ * ++ * Copyright (c) 2018 Red Hat Inc. ++ * ++ * Author: Fam Zheng ++ * ++ * 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.h" ++#include "sysemu/block-backend.h" ++#include "qapi/error.h" ++#include "qapi/qmp/qdict.h" ++ ++static BlockBackend *open_image(const char *path, ++ uint64_t perm, uint64_t shared_perm, ++ Error **errp) ++{ ++ Error *local_err = NULL; ++ BlockBackend *blk; ++ QDict *options = qdict_new(); ++ ++ qdict_put_str(options, "driver", "raw"); ++ blk = blk_new_open(path, NULL, options, BDRV_O_RDWR, &local_err); ++ if (blk) { ++ g_assert_null(local_err); ++ if (blk_set_perm(blk, perm, shared_perm, errp)) { ++ blk_unref(blk); ++ blk = NULL; ++ } ++ } else { ++ error_propagate(errp, local_err); ++ } ++ return blk; ++} ++ ++static void check_locked_bytes(int fd, uint64_t perm_locks, ++ uint64_t shared_perm_locks) ++{ ++ int i; ++ ++ if (!perm_locks && !shared_perm_locks) { ++ g_assert(!qemu_lock_fd_test(fd, 0, 0, true)); ++ return; ++ } ++ for (i = 0; (1ULL << i) <= BLK_PERM_ALL; i++) { ++ uint64_t bit = (1ULL << i); ++ bool perm_expected = !!(bit & perm_locks); ++ bool shared_perm_expected = !!(bit & shared_perm_locks); ++ g_assert_cmpint(perm_expected, ==, ++ !!qemu_lock_fd_test(fd, 100 + i, 1, true)); ++ g_assert_cmpint(shared_perm_expected, ==, ++ !!qemu_lock_fd_test(fd, 200 + i, 1, true)); ++ } ++} ++ ++static void test_image_locking_basic(void) ++{ ++ BlockBackend *blk1, *blk2, *blk3; ++ char img_path[] = "/tmp/qtest.XXXXXX"; ++ uint64_t perm, shared_perm; ++ ++ int fd = mkstemp(img_path); ++ assert(fd >= 0); ++ ++ perm = BLK_PERM_WRITE | BLK_PERM_CONSISTENT_READ; ++ shared_perm = BLK_PERM_ALL; ++ blk1 = open_image(img_path, perm, shared_perm, &error_abort); ++ g_assert(blk1); ++ ++ check_locked_bytes(fd, perm, ~shared_perm); ++ ++ /* compatible perm between blk1 and blk2 */ ++ blk2 = open_image(img_path, perm | BLK_PERM_RESIZE, shared_perm, NULL); ++ g_assert(blk2); ++ check_locked_bytes(fd, perm | BLK_PERM_RESIZE, ~shared_perm); ++ ++ /* incompatible perm with already open blk1 and blk2 */ ++ blk3 = open_image(img_path, perm, BLK_PERM_WRITE_UNCHANGED, NULL); ++ g_assert_null(blk3); ++ ++ blk_unref(blk2); ++ ++ /* Check that extra bytes in blk2 are correctly unlocked */ ++ check_locked_bytes(fd, perm, ~shared_perm); ++ ++ blk_unref(blk1); ++ ++ /* Image is unused, no lock there */ ++ check_locked_bytes(fd, 0, 0); ++ blk3 = open_image(img_path, perm, BLK_PERM_WRITE_UNCHANGED, &error_abort); ++ g_assert(blk3); ++ blk_unref(blk3); ++ close(fd); ++ unlink(img_path); ++} ++ ++static void test_set_perm_abort(void) ++{ ++ BlockBackend *blk1, *blk2; ++ char img_path[] = "/tmp/qtest.XXXXXX"; ++ uint64_t perm, shared_perm; ++ int r; ++ int fd = mkstemp(img_path); ++ assert(fd >= 0); ++ ++ perm = BLK_PERM_WRITE | BLK_PERM_CONSISTENT_READ; ++ shared_perm = BLK_PERM_ALL; ++ blk1 = open_image(img_path, perm, shared_perm, &error_abort); ++ g_assert(blk1); ++ ++ blk2 = open_image(img_path, perm, shared_perm, &error_abort); ++ g_assert(blk2); ++ ++ check_locked_bytes(fd, perm, ~shared_perm); ++ ++ /* A failed blk_set_perm mustn't change perm status (locked bytes) */ ++ r = blk_set_perm(blk2, perm | BLK_PERM_RESIZE, BLK_PERM_WRITE_UNCHANGED, ++ NULL); ++ g_assert_cmpint(r, !=, 0); ++ check_locked_bytes(fd, perm, ~shared_perm); ++ blk_unref(blk1); ++ blk_unref(blk2); ++} ++ ++int main(int argc, char **argv) ++{ ++ bdrv_init(); ++ qemu_init_main_loop(&error_abort); ++ ++ g_test_init(&argc, &argv, NULL); ++ ++ if (qemu_has_ofd_lock()) { ++ g_test_add_func("/image-locking/basic", test_image_locking_basic); ++ g_test_add_func("/image-locking/set-perm-abort", test_set_perm_abort); ++ } ++ ++ return g_test_run(); ++} +-- +1.8.3.1 + diff --git a/SOURCES/kvm-tests-crypto-Use-the-IEC-binary-prefix-definitions.patch b/SOURCES/kvm-tests-crypto-Use-the-IEC-binary-prefix-definitions.patch new file mode 100644 index 0000000..720de9a --- /dev/null +++ b/SOURCES/kvm-tests-crypto-Use-the-IEC-binary-prefix-definitions.patch @@ -0,0 +1,134 @@ +From f12961093254d12f8f7ccfd8feca7a32f558e12d Mon Sep 17 00:00:00 2001 +From: "Daniel P. Berrange" +Date: Wed, 24 Apr 2019 09:56:35 +0100 +Subject: [PATCH 1/9] tests/crypto: Use the IEC binary prefix definitions +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Daniel P. Berrange +Message-id: <20190424095643.796-2-berrange@redhat.com> +Patchwork-id: 85878 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 1/9] tests/crypto: Use the IEC binary prefix definitions +Bugzilla: 1680231 +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: John Snow +RH-Acked-by: Eric Blake + +From: Philippe Mathieu-Daudé + +It eases code review, unit is explicit. + +Patch generated using: + + $ git grep -n '[<>][<>]= ?[1-5]0' + +and modified manually. + +Suggested-by: Eric Blake +Signed-off-by: Philippe Mathieu-Daudé +Message-Id: <20180625124238.25339-45-f4bug@amsat.org> +Signed-off-by: Paolo Bonzini +(cherry picked from commit 68dbb6d05db59fe39af0c192005490576d9f5b7c) +Signed-off-by: Danilo C. L. de Paula +--- + tests/benchmark-crypto-cipher.c | 6 +++--- + tests/benchmark-crypto-hash.c | 5 +++-- + tests/benchmark-crypto-hmac.c | 6 +++--- + 3 files changed, 9 insertions(+), 8 deletions(-) + +diff --git a/tests/benchmark-crypto-cipher.c b/tests/benchmark-crypto-cipher.c +index cf98443..f5a0d0b 100644 +--- a/tests/benchmark-crypto-cipher.c ++++ b/tests/benchmark-crypto-cipher.c +@@ -11,6 +11,7 @@ + * top-level directory. + */ + #include "qemu/osdep.h" ++#include "qemu/units.h" + #include "crypto/init.h" + #include "crypto/cipher.h" + +@@ -56,8 +57,7 @@ static void test_cipher_speed(const void *opaque) + total += chunk_size; + } while (g_test_timer_elapsed() < 5.0); + +- total /= 1024 * 1024; /* to MB */ +- ++ total /= MiB; + g_print("cbc(aes128): "); + g_print("Testing chunk_size %zu bytes ", chunk_size); + g_print("done: %.2f MB in %.2f secs: ", total, g_test_timer_last()); +@@ -78,7 +78,7 @@ int main(int argc, char **argv) + g_test_init(&argc, &argv, NULL); + g_assert(qcrypto_init(NULL) == 0); + +- for (i = 512; i <= (64 * 1204); i *= 2) { ++ for (i = 512; i <= 64 * KiB; i *= 2) { + memset(name, 0 , sizeof(name)); + snprintf(name, sizeof(name), "/crypto/cipher/speed-%zu", i); + g_test_add_data_func(name, (void *)i, test_cipher_speed); +diff --git a/tests/benchmark-crypto-hash.c b/tests/benchmark-crypto-hash.c +index 122bfb6..9b6f7a9 100644 +--- a/tests/benchmark-crypto-hash.c ++++ b/tests/benchmark-crypto-hash.c +@@ -11,6 +11,7 @@ + * top-level directory. + */ + #include "qemu/osdep.h" ++#include "qemu/units.h" + #include "crypto/init.h" + #include "crypto/hash.h" + +@@ -39,7 +40,7 @@ static void test_hash_speed(const void *opaque) + total += chunk_size; + } while (g_test_timer_elapsed() < 5.0); + +- total /= 1024 * 1024; /* to MB */ ++ total /= MiB; + g_print("sha256: "); + g_print("Testing chunk_size %zu bytes ", chunk_size); + g_print("done: %.2f MB in %.2f secs: ", total, g_test_timer_last()); +@@ -57,7 +58,7 @@ int main(int argc, char **argv) + g_test_init(&argc, &argv, NULL); + g_assert(qcrypto_init(NULL) == 0); + +- for (i = 512; i <= (64 * 1204); i *= 2) { ++ for (i = 512; i <= 64 * KiB; i *= 2) { + memset(name, 0 , sizeof(name)); + snprintf(name, sizeof(name), "/crypto/hash/speed-%zu", i); + g_test_add_data_func(name, (void *)i, test_hash_speed); +diff --git a/tests/benchmark-crypto-hmac.c b/tests/benchmark-crypto-hmac.c +index c30250d..f1dfa24 100644 +--- a/tests/benchmark-crypto-hmac.c ++++ b/tests/benchmark-crypto-hmac.c +@@ -11,6 +11,7 @@ + * top-level directory. + */ + #include "qemu/osdep.h" ++#include "qemu/units.h" + #include "crypto/init.h" + #include "crypto/hmac.h" + +@@ -53,8 +54,7 @@ static void test_hmac_speed(const void *opaque) + total += chunk_size; + } while (g_test_timer_elapsed() < 5.0); + +- total /= 1024 * 1024; /* to MB */ +- ++ total /= MiB; + g_print("hmac(sha256): "); + g_print("Testing chunk_size %zu bytes ", chunk_size); + g_print("done: %.2f MB in %.2f secs: ", total, g_test_timer_last()); +@@ -72,7 +72,7 @@ int main(int argc, char **argv) + g_test_init(&argc, &argv, NULL); + g_assert(qcrypto_init(NULL) == 0); + +- for (i = 512; i <= (64 * 1204); i *= 2) { ++ for (i = 512; i <= 64 * KiB; i *= 2) { + memset(name, 0 , sizeof(name)); + snprintf(name, sizeof(name), "/crypto/hmac/speed-%zu", i); + g_test_add_data_func(name, (void *)i, test_hmac_speed); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-usb-call-reset-handler-before-updating-state.patch b/SOURCES/kvm-usb-call-reset-handler-before-updating-state.patch index 9913b7c..1048151 100644 --- a/SOURCES/kvm-usb-call-reset-handler-before-updating-state.patch +++ b/SOURCES/kvm-usb-call-reset-handler-before-updating-state.patch @@ -1,7 +1,7 @@ -From 4ab6c32432b80103b72b412e0e849cdb087c6e78 Mon Sep 17 00:00:00 2001 +From 99588fb3673a3315a66f7890b25bdca9b829925e Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 4 Jun 2019 05:12:44 +0100 -Subject: [PATCH 2/5] usb: call reset handler before updating state +Subject: [PATCH 2/8] usb: call reset handler before updating state MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -10,7 +10,7 @@ RH-Author: Gerd Hoffmann Message-id: <20190604051246.11374-3-kraxel@redhat.com> Patchwork-id: 88471 O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 2/4] usb: call reset handler before updating state -Bugzilla: 1719228 +Bugzilla: 1713677 RH-Acked-by: Dr. David Alan Gilbert RH-Acked-by: Philippe Mathieu-Daudé RH-Acked-by: Max Reitz diff --git a/SOURCES/kvm-usb-host-avoid-libusb_set_configuration-calls.patch b/SOURCES/kvm-usb-host-avoid-libusb_set_configuration-calls.patch index 4d18d92..21a84d3 100644 --- a/SOURCES/kvm-usb-host-avoid-libusb_set_configuration-calls.patch +++ b/SOURCES/kvm-usb-host-avoid-libusb_set_configuration-calls.patch @@ -1,7 +1,7 @@ -From 78a7dce49a0e3747e5aab9791434cb71297baf42 Mon Sep 17 00:00:00 2001 +From c7150963b7db0123299f2430eea956c6a83f69d4 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 4 Jun 2019 05:12:46 +0100 -Subject: [PATCH 4/5] usb-host: avoid libusb_set_configuration calls +Subject: [PATCH 4/8] usb-host: avoid libusb_set_configuration calls MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -10,7 +10,7 @@ RH-Author: Gerd Hoffmann Message-id: <20190604051246.11374-5-kraxel@redhat.com> Patchwork-id: 88472 O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 4/4] usb-host: avoid libusb_set_configuration calls -Bugzilla: 1719228 +Bugzilla: 1713677 RH-Acked-by: Dr. David Alan Gilbert RH-Acked-by: Philippe Mathieu-Daudé RH-Acked-by: Max Reitz diff --git a/SOURCES/kvm-usb-host-skip-reset-for-untouched-devices.patch b/SOURCES/kvm-usb-host-skip-reset-for-untouched-devices.patch index bc3dae0..b0646c8 100644 --- a/SOURCES/kvm-usb-host-skip-reset-for-untouched-devices.patch +++ b/SOURCES/kvm-usb-host-skip-reset-for-untouched-devices.patch @@ -1,7 +1,7 @@ -From e1ceffd58a4fc842c2a31c977c24e3ac0ced42a5 Mon Sep 17 00:00:00 2001 +From 874e4b3556ad42ff5b93b44305186be68fefce99 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 4 Jun 2019 05:12:45 +0100 -Subject: [PATCH 3/5] usb-host: skip reset for untouched devices +Subject: [PATCH 3/8] usb-host: skip reset for untouched devices MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit @@ -10,7 +10,7 @@ RH-Author: Gerd Hoffmann Message-id: <20190604051246.11374-4-kraxel@redhat.com> Patchwork-id: 88474 O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 3/4] usb-host: skip reset for untouched devices -Bugzilla: 1719228 +Bugzilla: 1713677 RH-Acked-by: Dr. David Alan Gilbert RH-Acked-by: Philippe Mathieu-Daudé RH-Acked-by: Max Reitz diff --git a/SOURCES/kvm-usb-hub-clear-suspend-on-detach.patch b/SOURCES/kvm-usb-hub-clear-suspend-on-detach.patch new file mode 100644 index 0000000..52f82f5 --- /dev/null +++ b/SOURCES/kvm-usb-hub-clear-suspend-on-detach.patch @@ -0,0 +1,43 @@ +From 24300291c98529f7d5a00ebdf6fdea68f8af97f5 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Wed, 14 Aug 2019 09:47:34 +0100 +Subject: [PATCH 2/3] usb-hub: clear suspend on detach +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Gerd Hoffmann +Message-id: <20190814094734.18110-2-kraxel@redhat.com> +Patchwork-id: 89977 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 1/1] usb-hub: clear suspend on detach +Bugzilla: 1619661 +RH-Acked-by: John Snow +RH-Acked-by: Markus Armbruster +RH-Acked-by: Philippe Mathieu-Daudé + +Signed-off-by: Gerd Hoffmann +Message-id: 20180912114012.6034-1-kraxel@redhat.com +(cherry picked from commit 3e9191acb797e4298adb853bf6c75cd31af47ef9) +Signed-off-by: Danilo C. L. de Paula +--- + hw/usb/dev-hub.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/hw/usb/dev-hub.c b/hw/usb/dev-hub.c +index 752e30c..2452e88 100644 +--- a/hw/usb/dev-hub.c ++++ b/hw/usb/dev-hub.c +@@ -191,6 +191,10 @@ static void usb_hub_detach(USBPort *port1) + port->wPortStatus &= ~PORT_STAT_ENABLE; + port->wPortChange |= PORT_STAT_C_ENABLE; + } ++ if (port->wPortStatus & PORT_STAT_SUSPEND) { ++ port->wPortStatus &= ~PORT_STAT_SUSPEND; ++ port->wPortChange |= PORT_STAT_C_SUSPEND; ++ } + usb_wakeup(s->intr, 0); + } + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-vfio-Make-vfio_get_region_info_cap-public.patch b/SOURCES/kvm-vfio-Make-vfio_get_region_info_cap-public.patch new file mode 100644 index 0000000..3d7bc97 --- /dev/null +++ b/SOURCES/kvm-vfio-Make-vfio_get_region_info_cap-public.patch @@ -0,0 +1,66 @@ +From a46c2139b02581c6d2462bc131930847efea8335 Mon Sep 17 00:00:00 2001 +From: David Gibson +Date: Thu, 30 May 2019 04:37:27 +0100 +Subject: [PATCH 6/8] vfio: Make vfio_get_region_info_cap public +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: David Gibson +Message-id: <20190530043728.32575-6-dgibson@redhat.com> +Patchwork-id: 88420 +O-Subject: [RHEL-8.1 qemu-kvm PATCH 5/6] vfio: Make vfio_get_region_info_cap public +Bugzilla: 1710662 +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Laurent Vivier +RH-Acked-by: Auger Eric +RH-Acked-by: Cornelia Huck + +From: Alexey Kardashevskiy + +This makes vfio_get_region_info_cap() to be used in quirks. + +Signed-off-by: Alexey Kardashevskiy +Acked-by: Alex Williamson +Message-Id: <20190307050518.64968-3-aik@ozlabs.ru> +Signed-off-by: David Gibson +(cherry picked from commit 013002f0fbf62545c0f5ea4c5c2d554a85919647) + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1710662 + +Signed-off-by: David Gibson +Signed-off-by: Danilo C. L. de Paula +--- + hw/vfio/common.c | 2 +- + include/hw/vfio/vfio-common.h | 2 ++ + 2 files changed, 3 insertions(+), 1 deletion(-) + +diff --git a/hw/vfio/common.c b/hw/vfio/common.c +index 3ab92bd..3dbccfc 100644 +--- a/hw/vfio/common.c ++++ b/hw/vfio/common.c +@@ -706,7 +706,7 @@ static void vfio_listener_release(VFIOContainer *container) + } + } + +-static struct vfio_info_cap_header * ++struct vfio_info_cap_header * + vfio_get_region_info_cap(struct vfio_region_info *info, uint16_t id) + { + struct vfio_info_cap_header *hdr; +diff --git a/include/hw/vfio/vfio-common.h b/include/hw/vfio/vfio-common.h +index 36ee657..7607be3 100644 +--- a/include/hw/vfio/vfio-common.h ++++ b/include/hw/vfio/vfio-common.h +@@ -197,6 +197,8 @@ int vfio_get_region_info(VFIODevice *vbasedev, int index, + int vfio_get_dev_region_info(VFIODevice *vbasedev, uint32_t type, + uint32_t subtype, struct vfio_region_info **info); + bool vfio_has_region_cap(VFIODevice *vbasedev, int region, uint16_t cap_type); ++struct vfio_info_cap_header * ++vfio_get_region_info_cap(struct vfio_region_info *info, uint16_t id); + #endif + extern const MemoryListener vfio_prereg_listener; + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-vfio-quirks-Add-common-quirk-alloc-helper.patch b/SOURCES/kvm-vfio-quirks-Add-common-quirk-alloc-helper.patch new file mode 100644 index 0000000..0653f9e --- /dev/null +++ b/SOURCES/kvm-vfio-quirks-Add-common-quirk-alloc-helper.patch @@ -0,0 +1,164 @@ +From e8b5f27c84d9a7e1b1b18b2a472a1500711da828 Mon Sep 17 00:00:00 2001 +From: David Gibson +Date: Thu, 30 May 2019 04:37:26 +0100 +Subject: [PATCH 5/8] vfio/quirks: Add common quirk alloc helper +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: David Gibson +Message-id: <20190530043728.32575-5-dgibson@redhat.com> +Patchwork-id: 88422 +O-Subject: [RHEL-8.1 qemu-kvm PATCH 4/6] vfio/quirks: Add common quirk alloc helper +Bugzilla: 1710662 +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Laurent Vivier +RH-Acked-by: Auger Eric +RH-Acked-by: Cornelia Huck + +From: Alex Williamson + +This will later be used to include list initialization. + +Reviewed-by: Eric Auger +Reviewed-by: Peter Xu +Signed-off-by: Alex Williamson +(cherry picked from commit bcf3c3d029e73d54455e1d7a51177c37d668378c) + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1710662 + +Signed-off-by: David Gibson +Signed-off-by: Danilo C. L. de Paula +--- + hw/vfio/pci-quirks.c | 48 +++++++++++++++++++++--------------------------- + 1 file changed, 21 insertions(+), 27 deletions(-) + +diff --git a/hw/vfio/pci-quirks.c b/hw/vfio/pci-quirks.c +index 90859d1..92457ed 100644 +--- a/hw/vfio/pci-quirks.c ++++ b/hw/vfio/pci-quirks.c +@@ -275,6 +275,15 @@ static const MemoryRegionOps vfio_ati_3c3_quirk = { + .endianness = DEVICE_LITTLE_ENDIAN, + }; + ++static VFIOQuirk *vfio_quirk_alloc(int nr_mem) ++{ ++ VFIOQuirk *quirk = g_new0(VFIOQuirk, 1); ++ quirk->mem = g_new0(MemoryRegion, nr_mem); ++ quirk->nr_mem = nr_mem; ++ ++ return quirk; ++} ++ + static void vfio_vga_probe_ati_3c3_quirk(VFIOPCIDevice *vdev) + { + VFIOQuirk *quirk; +@@ -288,9 +297,7 @@ static void vfio_vga_probe_ati_3c3_quirk(VFIOPCIDevice *vdev) + return; + } + +- quirk = g_malloc0(sizeof(*quirk)); +- quirk->mem = g_new0(MemoryRegion, 1); +- quirk->nr_mem = 1; ++ quirk = vfio_quirk_alloc(1); + + memory_region_init_io(quirk->mem, OBJECT(vdev), &vfio_ati_3c3_quirk, vdev, + "vfio-ati-3c3-quirk", 1); +@@ -323,9 +330,7 @@ static void vfio_probe_ati_bar4_quirk(VFIOPCIDevice *vdev, int nr) + return; + } + +- quirk = g_malloc0(sizeof(*quirk)); +- quirk->mem = g_new0(MemoryRegion, 2); +- quirk->nr_mem = 2; ++ quirk = vfio_quirk_alloc(2); + window = quirk->data = g_malloc0(sizeof(*window) + + sizeof(VFIOConfigWindowMatch)); + window->vdev = vdev; +@@ -371,10 +376,9 @@ static void vfio_probe_ati_bar2_quirk(VFIOPCIDevice *vdev, int nr) + return; + } + +- quirk = g_malloc0(sizeof(*quirk)); ++ quirk = vfio_quirk_alloc(1); + mirror = quirk->data = g_malloc0(sizeof(*mirror)); +- mirror->mem = quirk->mem = g_new0(MemoryRegion, 1); +- quirk->nr_mem = 1; ++ mirror->mem = quirk->mem; + mirror->vdev = vdev; + mirror->offset = 0x4000; + mirror->bar = nr; +@@ -546,10 +550,8 @@ static void vfio_vga_probe_nvidia_3d0_quirk(VFIOPCIDevice *vdev) + return; + } + +- quirk = g_malloc0(sizeof(*quirk)); ++ quirk = vfio_quirk_alloc(2); + quirk->data = data = g_malloc0(sizeof(*data)); +- quirk->mem = g_new0(MemoryRegion, 2); +- quirk->nr_mem = 2; + data->vdev = vdev; + + memory_region_init_io(&quirk->mem[0], OBJECT(vdev), &vfio_nvidia_3d4_quirk, +@@ -665,9 +667,7 @@ static void vfio_probe_nvidia_bar5_quirk(VFIOPCIDevice *vdev, int nr) + return; + } + +- quirk = g_malloc0(sizeof(*quirk)); +- quirk->mem = g_new0(MemoryRegion, 4); +- quirk->nr_mem = 4; ++ quirk = vfio_quirk_alloc(4); + bar5 = quirk->data = g_malloc0(sizeof(*bar5) + + (sizeof(VFIOConfigWindowMatch) * 2)); + window = &bar5->window; +@@ -760,10 +760,9 @@ static void vfio_probe_nvidia_bar0_quirk(VFIOPCIDevice *vdev, int nr) + return; + } + +- quirk = g_malloc0(sizeof(*quirk)); ++ quirk = vfio_quirk_alloc(1); + mirror = quirk->data = g_malloc0(sizeof(*mirror)); +- mirror->mem = quirk->mem = g_new0(MemoryRegion, 1); +- quirk->nr_mem = 1; ++ mirror->mem = quirk->mem; + mirror->vdev = vdev; + mirror->offset = 0x88000; + mirror->bar = nr; +@@ -779,10 +778,9 @@ static void vfio_probe_nvidia_bar0_quirk(VFIOPCIDevice *vdev, int nr) + + /* The 0x1800 offset mirror only seems to get used by legacy VGA */ + if (vdev->vga) { +- quirk = g_malloc0(sizeof(*quirk)); ++ quirk = vfio_quirk_alloc(1); + mirror = quirk->data = g_malloc0(sizeof(*mirror)); +- mirror->mem = quirk->mem = g_new0(MemoryRegion, 1); +- quirk->nr_mem = 1; ++ mirror->mem = quirk->mem; + mirror->vdev = vdev; + mirror->offset = 0x1800; + mirror->bar = nr; +@@ -943,9 +941,7 @@ static void vfio_probe_rtl8168_bar2_quirk(VFIOPCIDevice *vdev, int nr) + return; + } + +- quirk = g_malloc0(sizeof(*quirk)); +- quirk->mem = g_new0(MemoryRegion, 2); +- quirk->nr_mem = 2; ++ quirk = vfio_quirk_alloc(2); + quirk->data = rtl = g_malloc0(sizeof(*rtl)); + rtl->vdev = vdev; + +@@ -1510,9 +1506,7 @@ static void vfio_probe_igd_bar4_quirk(VFIOPCIDevice *vdev, int nr) + } + + /* Setup our quirk to munge GTT addresses to the VM allocated buffer */ +- quirk = g_malloc0(sizeof(*quirk)); +- quirk->mem = g_new0(MemoryRegion, 2); +- quirk->nr_mem = 2; ++ quirk = vfio_quirk_alloc(2); + igd = quirk->data = g_malloc0(sizeof(*igd)); + igd->vdev = vdev; + igd->index = ~0; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-virtio-blk-Increase-in_flight-for-request-restart-BH.patch b/SOURCES/kvm-virtio-blk-Increase-in_flight-for-request-restart-BH.patch new file mode 100644 index 0000000..27c6935 --- /dev/null +++ b/SOURCES/kvm-virtio-blk-Increase-in_flight-for-request-restart-BH.patch @@ -0,0 +1,62 @@ +From 2f11a1952881d9e2dcc8acb3549441dbd9ade1e3 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Wed, 14 Aug 2019 08:42:26 +0100 +Subject: [PATCH 03/10] virtio-blk: Increase in_flight for request restart BH + +RH-Author: Kevin Wolf +Message-id: <20190814084229.6458-3-kwolf@redhat.com> +Patchwork-id: 89967 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 2/5] virtio-blk: Increase in_flight for request restart BH +Bugzilla: 1716349 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Max Reitz +RH-Acked-by: Paolo Bonzini + +virtio_blk_dma_restart_bh() submits new requests, so in order to make +sure that these requests are not started inside a drained section of the +attached BlockBackend, we need to make sure that draining the +BlockBackend waits for the BH to be executed. + +This BH is still questionable because its scheduled in the main thread +instead of the configured iothread. Leave a FIXME comment for this. + +But with this fix, enabling the data plane at least waits for these +requests (in bdrv_set_aio_context()) instead of changing the AioContext +under their feet and making them run in the wrong thread, causing +crashes and failures (e.g. due to missing locking). + +Signed-off-by: Kevin Wolf +(cherry picked from commit 680f200217748e0920b79ec1d524717c2f50935b) +Signed-off-by: Kevin Wolf +Signed-off-by: Danilo C. L. de Paula +--- + hw/block/virtio-blk.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c +index b1532e4..691ade4 100644 +--- a/hw/block/virtio-blk.c ++++ b/hw/block/virtio-blk.c +@@ -678,6 +678,7 @@ static void virtio_blk_dma_restart_bh(void *opaque) + if (mrb.num_reqs) { + virtio_blk_submit_multireq(s->blk, &mrb); + } ++ blk_dec_in_flight(s->conf.conf.blk); + aio_context_release(blk_get_aio_context(s->conf.conf.blk)); + } + +@@ -691,8 +692,11 @@ static void virtio_blk_dma_restart_cb(void *opaque, int running, + } + + if (!s->bh) { ++ /* FIXME The data plane is not started yet, so these requests are ++ * processed in the main thread. */ + s->bh = aio_bh_new(blk_get_aio_context(s->conf.conf.blk), + virtio_blk_dma_restart_bh, s); ++ blk_inc_in_flight(s->conf.conf.blk); + qemu_bh_schedule(s->bh); + } + } +-- +1.8.3.1 + diff --git a/SOURCES/kvm-virtio-gpu-add-iommu-support.patch b/SOURCES/kvm-virtio-gpu-add-iommu-support.patch new file mode 100644 index 0000000..d66a172 --- /dev/null +++ b/SOURCES/kvm-virtio-gpu-add-iommu-support.patch @@ -0,0 +1,99 @@ +From c6874c974165bd783649ae9e0fb4390881c5e79c Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Thu, 4 Jul 2019 10:32:06 +0200 +Subject: [PATCH 3/4] virtio-gpu: add iommu support +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Gerd Hoffmann +Message-id: <20190704103207.29158-3-kraxel@redhat.com> +Patchwork-id: 89371 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v2 2/3] virtio-gpu: add iommu support +Bugzilla: 1531543 +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Stefan Hajnoczi + +Switch from cpu_physical_memory_map to dma_memory_map, +so iommu mappings for virtio-gpu objects work properly. + +Signed-off-by: Gerd Hoffmann +Message-Id: <20180829122101.29852-3-kraxel@redhat.com> +(cherry picked from commit 8da132a56f7ebaabc5b674b5a3a2e6fa8934be45) +Signed-off-by: Miroslav Rezanina +--- + hw/display/virtio-gpu.c | 25 ++++++++++++++----------- + 1 file changed, 14 insertions(+), 11 deletions(-) + +diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c +index cb77ece..327c2be 100644 +--- a/hw/display/virtio-gpu.c ++++ b/hw/display/virtio-gpu.c +@@ -16,6 +16,7 @@ + #include "qemu/iov.h" + #include "ui/console.h" + #include "trace.h" ++#include "sysemu/dma.h" + #include "hw/virtio/virtio.h" + #include "hw/virtio/virtio-gpu.h" + #include "hw/virtio/virtio-bus.h" +@@ -725,7 +726,8 @@ int virtio_gpu_create_mapping_iov(VirtIOGPU *g, + uint32_t l = le32_to_cpu(ents[i].length); + hwaddr len = l; + (*iov)[i].iov_len = l; +- (*iov)[i].iov_base = cpu_physical_memory_map(a, &len, 1); ++ (*iov)[i].iov_base = dma_memory_map(VIRTIO_DEVICE(g)->dma_as, ++ a, &len, DMA_DIRECTION_TO_DEVICE); + if (addr) { + (*addr)[i] = a; + } +@@ -753,8 +755,10 @@ void virtio_gpu_cleanup_mapping_iov(VirtIOGPU *g, + int i; + + for (i = 0; i < count; i++) { +- cpu_physical_memory_unmap(iov[i].iov_base, iov[i].iov_len, 1, +- iov[i].iov_len); ++ dma_memory_unmap(VIRTIO_DEVICE(g)->dma_as, ++ iov[i].iov_base, iov[i].iov_len, ++ DMA_DIRECTION_TO_DEVICE, ++ iov[i].iov_len); + } + g_free(iov); + } +@@ -1146,13 +1150,17 @@ static int virtio_gpu_load(QEMUFile *f, void *opaque, size_t size, + for (i = 0; i < res->iov_cnt; i++) { + hwaddr len = res->iov[i].iov_len; + res->iov[i].iov_base = +- cpu_physical_memory_map(res->addrs[i], &len, 1); ++ dma_memory_map(VIRTIO_DEVICE(g)->dma_as, ++ res->addrs[i], &len, DMA_DIRECTION_TO_DEVICE); + + if (!res->iov[i].iov_base || len != res->iov[i].iov_len) { + /* Clean up the half-a-mapping we just created... */ + if (res->iov[i].iov_base) { +- cpu_physical_memory_unmap(res->iov[i].iov_base, +- len, 0, 0); ++ dma_memory_unmap(VIRTIO_DEVICE(g)->dma_as, ++ res->iov[i].iov_base, ++ res->iov[i].iov_len, ++ DMA_DIRECTION_TO_DEVICE, ++ res->iov[i].iov_len); + } + /* ...and the mappings for previous loop iterations */ + res->iov_cnt = i; +@@ -1204,11 +1212,6 @@ static void virtio_gpu_device_realize(DeviceState *qdev, Error **errp) + Error *local_err = NULL; + int i; + +- if (virtio_host_has_feature(vdev, VIRTIO_F_IOMMU_PLATFORM)) { +- error_setg(errp, "virtio-gpu does not support vIOMMU yet"); +- return; +- } +- + if (g->conf.max_outputs > VIRTIO_GPU_MAX_SCANOUTS) { + error_setg(errp, "invalid max_outputs > %d", VIRTIO_GPU_MAX_SCANOUTS); + return; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-virtio-gpu-fix-unmap-in-error-path.patch b/SOURCES/kvm-virtio-gpu-fix-unmap-in-error-path.patch new file mode 100644 index 0000000..712e2e4 --- /dev/null +++ b/SOURCES/kvm-virtio-gpu-fix-unmap-in-error-path.patch @@ -0,0 +1,52 @@ +From 29e3a6aebf124a88b26fd49a2dd0a99c38f918aa Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Thu, 4 Jul 2019 10:32:07 +0200 +Subject: [PATCH 4/4] virtio-gpu: fix unmap in error path +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Gerd Hoffmann +Message-id: <20190704103207.29158-4-kraxel@redhat.com> +Patchwork-id: 89373 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v2 3/3] virtio-gpu: fix unmap in error path +Bugzilla: 1531543 +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Stefan Hajnoczi + +We land here in case not everything we've asked for could be mapped. +So unmap only the bytes which have actually been mapped. + +Also we didn't access anything, so acces_len can be 0. + +Reported-by: Laszlo Ersek +Signed-off-by: Gerd Hoffmann +Reviewed-by: Laszlo Ersek +Reviewed-by: Li Qiang +Message-id: 20190628072357.31782-1-kraxel@redhat.com +(cherry picked from commit a7f85e03b94ffaca75332cddf06426fc85ac611a) +Signed-off-by: Miroslav Rezanina +--- + hw/display/virtio-gpu.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c +index 327c2be..07712d0 100644 +--- a/hw/display/virtio-gpu.c ++++ b/hw/display/virtio-gpu.c +@@ -1158,9 +1158,9 @@ static int virtio_gpu_load(QEMUFile *f, void *opaque, size_t size, + if (res->iov[i].iov_base) { + dma_memory_unmap(VIRTIO_DEVICE(g)->dma_as, + res->iov[i].iov_base, +- res->iov[i].iov_len, ++ len, + DMA_DIRECTION_TO_DEVICE, +- res->iov[i].iov_len); ++ 0); + } + /* ...and the mappings for previous loop iterations */ + res->iov_cnt = i; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-virtio-gpu-pass-down-VirtIOGPU-pointer-to-a-bunch-of.patch b/SOURCES/kvm-virtio-gpu-pass-down-VirtIOGPU-pointer-to-a-bunch-of.patch new file mode 100644 index 0000000..33eb58b --- /dev/null +++ b/SOURCES/kvm-virtio-gpu-pass-down-VirtIOGPU-pointer-to-a-bunch-of.patch @@ -0,0 +1,193 @@ +From 5b896af413dae0e4933a6e5c277bfe7b4f2f9bb4 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Thu, 4 Jul 2019 10:32:05 +0200 +Subject: [PATCH 2/4] virtio-gpu: pass down VirtIOGPU pointer to a bunch of + functions +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Gerd Hoffmann +Message-id: <20190704103207.29158-2-kraxel@redhat.com> +Patchwork-id: 89374 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v2 1/3] virtio-gpu: pass down VirtIOGPU pointer to a bunch of functions +Bugzilla: 1531543 +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Stefan Hajnoczi + +No functional change, just preparation for a followup patch +which needs a VirtIOGPU pointer. + +Signed-off-by: Gerd Hoffmann +Message-Id: <20180829122101.29852-2-kraxel@redhat.com> +(cherry picked from commit 3bb68f798da0234d5ca0ac6062aaa084afc83069) +Signed-off-by: Miroslav Rezanina +--- + hw/display/virtio-gpu-3d.c | 8 ++++---- + hw/display/virtio-gpu.c | 25 +++++++++++++++---------- + include/hw/virtio/virtio-gpu.h | 6 ++++-- + 3 files changed, 23 insertions(+), 16 deletions(-) + +diff --git a/hw/display/virtio-gpu-3d.c b/hw/display/virtio-gpu-3d.c +index 3558f38..55d7640 100644 +--- a/hw/display/virtio-gpu-3d.c ++++ b/hw/display/virtio-gpu-3d.c +@@ -86,7 +86,7 @@ static void virgl_cmd_resource_unref(VirtIOGPU *g, + &res_iovs, + &num_iovs); + if (res_iovs != NULL && num_iovs != 0) { +- virtio_gpu_cleanup_mapping_iov(res_iovs, num_iovs); ++ virtio_gpu_cleanup_mapping_iov(g, res_iovs, num_iovs); + } + virgl_renderer_resource_unref(unref.resource_id); + } +@@ -291,7 +291,7 @@ static void virgl_resource_attach_backing(VirtIOGPU *g, + VIRTIO_GPU_FILL_CMD(att_rb); + trace_virtio_gpu_cmd_res_back_attach(att_rb.resource_id); + +- ret = virtio_gpu_create_mapping_iov(&att_rb, cmd, NULL, &res_iovs); ++ ret = virtio_gpu_create_mapping_iov(g, &att_rb, cmd, NULL, &res_iovs); + if (ret != 0) { + cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC; + return; +@@ -301,7 +301,7 @@ static void virgl_resource_attach_backing(VirtIOGPU *g, + res_iovs, att_rb.nr_entries); + + if (ret != 0) +- virtio_gpu_cleanup_mapping_iov(res_iovs, att_rb.nr_entries); ++ virtio_gpu_cleanup_mapping_iov(g, res_iovs, att_rb.nr_entries); + } + + static void virgl_resource_detach_backing(VirtIOGPU *g, +@@ -320,7 +320,7 @@ static void virgl_resource_detach_backing(VirtIOGPU *g, + if (res_iovs == NULL || num_iovs == 0) { + return; + } +- virtio_gpu_cleanup_mapping_iov(res_iovs, num_iovs); ++ virtio_gpu_cleanup_mapping_iov(g, res_iovs, num_iovs); + } + + +diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c +index 08cd567..cb77ece 100644 +--- a/hw/display/virtio-gpu.c ++++ b/hw/display/virtio-gpu.c +@@ -28,7 +28,8 @@ + static struct virtio_gpu_simple_resource* + virtio_gpu_find_resource(VirtIOGPU *g, uint32_t resource_id); + +-static void virtio_gpu_cleanup_mapping(struct virtio_gpu_simple_resource *res); ++static void virtio_gpu_cleanup_mapping(VirtIOGPU *g, ++ struct virtio_gpu_simple_resource *res); + + static void + virtio_gpu_ctrl_hdr_bswap(struct virtio_gpu_ctrl_hdr *hdr) +@@ -441,7 +442,7 @@ static void virtio_gpu_resource_destroy(VirtIOGPU *g, + } + + pixman_image_unref(res->image); +- virtio_gpu_cleanup_mapping(res); ++ virtio_gpu_cleanup_mapping(g, res); + QTAILQ_REMOVE(&g->reslist, res, next); + g->hostmem -= res->hostmem; + g_free(res); +@@ -687,7 +688,8 @@ static void virtio_gpu_set_scanout(VirtIOGPU *g, + scanout->height = ss.r.height; + } + +-int virtio_gpu_create_mapping_iov(struct virtio_gpu_resource_attach_backing *ab, ++int virtio_gpu_create_mapping_iov(VirtIOGPU *g, ++ struct virtio_gpu_resource_attach_backing *ab, + struct virtio_gpu_ctrl_command *cmd, + uint64_t **addr, struct iovec **iov) + { +@@ -731,7 +733,7 @@ int virtio_gpu_create_mapping_iov(struct virtio_gpu_resource_attach_backing *ab, + qemu_log_mask(LOG_GUEST_ERROR, "%s: failed to map MMIO memory for" + " resource %d element %d\n", + __func__, ab->resource_id, i); +- virtio_gpu_cleanup_mapping_iov(*iov, i); ++ virtio_gpu_cleanup_mapping_iov(g, *iov, i); + g_free(ents); + *iov = NULL; + if (addr) { +@@ -745,7 +747,8 @@ int virtio_gpu_create_mapping_iov(struct virtio_gpu_resource_attach_backing *ab, + return 0; + } + +-void virtio_gpu_cleanup_mapping_iov(struct iovec *iov, uint32_t count) ++void virtio_gpu_cleanup_mapping_iov(VirtIOGPU *g, ++ struct iovec *iov, uint32_t count) + { + int i; + +@@ -756,9 +759,10 @@ void virtio_gpu_cleanup_mapping_iov(struct iovec *iov, uint32_t count) + g_free(iov); + } + +-static void virtio_gpu_cleanup_mapping(struct virtio_gpu_simple_resource *res) ++static void virtio_gpu_cleanup_mapping(VirtIOGPU *g, ++ struct virtio_gpu_simple_resource *res) + { +- virtio_gpu_cleanup_mapping_iov(res->iov, res->iov_cnt); ++ virtio_gpu_cleanup_mapping_iov(g, res->iov, res->iov_cnt); + res->iov = NULL; + res->iov_cnt = 0; + g_free(res->addrs); +@@ -790,7 +794,7 @@ virtio_gpu_resource_attach_backing(VirtIOGPU *g, + return; + } + +- ret = virtio_gpu_create_mapping_iov(&ab, cmd, &res->addrs, &res->iov); ++ ret = virtio_gpu_create_mapping_iov(g, &ab, cmd, &res->addrs, &res->iov); + if (ret != 0) { + cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC; + return; +@@ -817,7 +821,7 @@ virtio_gpu_resource_detach_backing(VirtIOGPU *g, + cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID; + return; + } +- virtio_gpu_cleanup_mapping(res); ++ virtio_gpu_cleanup_mapping(g, res); + } + + static void virtio_gpu_simple_process_cmd(VirtIOGPU *g, +@@ -1143,6 +1147,7 @@ static int virtio_gpu_load(QEMUFile *f, void *opaque, size_t size, + hwaddr len = res->iov[i].iov_len; + res->iov[i].iov_base = + cpu_physical_memory_map(res->addrs[i], &len, 1); ++ + if (!res->iov[i].iov_base || len != res->iov[i].iov_len) { + /* Clean up the half-a-mapping we just created... */ + if (res->iov[i].iov_base) { +@@ -1151,7 +1156,7 @@ static int virtio_gpu_load(QEMUFile *f, void *opaque, size_t size, + } + /* ...and the mappings for previous loop iterations */ + res->iov_cnt = i; +- virtio_gpu_cleanup_mapping(res); ++ virtio_gpu_cleanup_mapping(g, res); + pixman_image_unref(res->image); + g_free(res); + return -EINVAL; +diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h +index 22ac3c2..f95f8ce 100644 +--- a/include/hw/virtio/virtio-gpu.h ++++ b/include/hw/virtio/virtio-gpu.h +@@ -158,10 +158,12 @@ void virtio_gpu_ctrl_response_nodata(VirtIOGPU *g, + enum virtio_gpu_ctrl_type type); + void virtio_gpu_get_display_info(VirtIOGPU *g, + struct virtio_gpu_ctrl_command *cmd); +-int virtio_gpu_create_mapping_iov(struct virtio_gpu_resource_attach_backing *ab, ++int virtio_gpu_create_mapping_iov(VirtIOGPU *g, ++ struct virtio_gpu_resource_attach_backing *ab, + struct virtio_gpu_ctrl_command *cmd, + uint64_t **addr, struct iovec **iov); +-void virtio_gpu_cleanup_mapping_iov(struct iovec *iov, uint32_t count); ++void virtio_gpu_cleanup_mapping_iov(VirtIOGPU *g, ++ struct iovec *iov, uint32_t count); + void virtio_gpu_process_cmdq(VirtIOGPU *g); + + /* virtio-gpu-3d.c */ +-- +1.8.3.1 + diff --git a/SOURCES/kvm-virtio-scsi-Forbid-devices-with-different-iothreads-.patch b/SOURCES/kvm-virtio-scsi-Forbid-devices-with-different-iothreads-.patch index 27676bc..70527ee 100644 --- a/SOURCES/kvm-virtio-scsi-Forbid-devices-with-different-iothreads-.patch +++ b/SOURCES/kvm-virtio-scsi-Forbid-devices-with-different-iothreads-.patch @@ -1,14 +1,14 @@ -From 98d938374f47c7473366706aa5f5754d9b752eea Mon Sep 17 00:00:00 2001 +From aff6f71a4e88ccec03f8451d9d9605589dddc6a2 Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Thu, 6 Jun 2019 19:15:24 +0100 -Subject: [PATCH 7/7] virtio-scsi: Forbid devices with different iothreads +Subject: [PATCH 7/8] virtio-scsi: Forbid devices with different iothreads sharing a blockdev RH-Author: Markus Armbruster Message-id: <20190606191524.30797-4-armbru@redhat.com> Patchwork-id: 88608 O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 3/3] virtio-scsi: Forbid devices with different iothreads sharing a blockdev -Bugzilla: 1718992 +Bugzilla: 1673396 1673401 RH-Acked-by: Paolo Bonzini RH-Acked-by: Stefan Hajnoczi RH-Acked-by: Kevin Wolf diff --git a/SOURCES/kvm-virtio-scsi-Move-BlockBackend-back-to-the-main-AioCo.patch b/SOURCES/kvm-virtio-scsi-Move-BlockBackend-back-to-the-main-AioCo.patch index aeef1c8..c948819 100644 --- a/SOURCES/kvm-virtio-scsi-Move-BlockBackend-back-to-the-main-AioCo.patch +++ b/SOURCES/kvm-virtio-scsi-Move-BlockBackend-back-to-the-main-AioCo.patch @@ -1,14 +1,14 @@ -From d06442e9c1cdd9712bfb1f41317fe91ec454601b Mon Sep 17 00:00:00 2001 +From 215a509da9a0a8918ab1bfbd0f6ccfb765578f0f Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Thu, 6 Jun 2019 19:15:22 +0100 -Subject: [PATCH 5/7] virtio-scsi: Move BlockBackend back to the main +Subject: [PATCH 5/8] virtio-scsi: Move BlockBackend back to the main AioContext on unplug RH-Author: Markus Armbruster Message-id: <20190606191524.30797-2-armbru@redhat.com> Patchwork-id: 88607 O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 1/3] virtio-scsi: Move BlockBackend back to the main AioContext on unplug -Bugzilla: 1718992 +Bugzilla: 1673396 1673401 RH-Acked-by: Paolo Bonzini RH-Acked-by: Stefan Hajnoczi RH-Acked-by: Kevin Wolf diff --git a/SOURCES/kvm-vmstate-Add-support-for-kernel-integer-types.patch b/SOURCES/kvm-vmstate-Add-support-for-kernel-integer-types.patch new file mode 100644 index 0000000..00d55c2 --- /dev/null +++ b/SOURCES/kvm-vmstate-Add-support-for-kernel-integer-types.patch @@ -0,0 +1,75 @@ +From 8f7ed484aec956d81684bc2795d3da6969b20727 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Mon, 22 Jul 2019 18:22:14 +0100 +Subject: [PATCH 33/39] vmstate: Add support for kernel integer types + +RH-Author: Paolo Bonzini +Message-id: <20190722182220.19374-13-pbonzini@redhat.com> +Patchwork-id: 89630 +O-Subject: [RHEL-8.1.0 PATCH qemu-kvm v3 12/18] vmstate: Add support for kernel integer types +Bugzilla: 1689269 +RH-Acked-by: Peter Xu +RH-Acked-by: Laurent Vivier +RH-Acked-by: Dr. David Alan Gilbert + +From: Liran Alon + +Reviewed-by: Nikita Leshenko +Reviewed-by: Maran Wilson +Signed-off-by: Liran Alon +Reviewed-by: Dr. David Alan Gilbert +Message-Id: <20190619162140.133674-8-liran.alon@oracle.com> +Signed-off-by: Paolo Bonzini +(cherry picked from commit 6cfd7639329062797c04ec79adb1023a8ba2fcb4) +Signed-off-by: Danilo C. L. de Paula +--- + include/migration/vmstate.h | 26 ++++++++++++++++++++++++++ + 1 file changed, 26 insertions(+) + +diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h +index df463fd..380a0fd 100644 +--- a/include/migration/vmstate.h ++++ b/include/migration/vmstate.h +@@ -755,6 +755,19 @@ extern const VMStateInfo vmstate_info_qtailq; + #define VMSTATE_UINT64_V(_f, _s, _v) \ + VMSTATE_SINGLE(_f, _s, _v, vmstate_info_uint64, uint64_t) + ++#ifdef CONFIG_LINUX ++ ++#define VMSTATE_U8_V(_f, _s, _v) \ ++ VMSTATE_SINGLE(_f, _s, _v, vmstate_info_uint8, __u8) ++#define VMSTATE_U16_V(_f, _s, _v) \ ++ VMSTATE_SINGLE(_f, _s, _v, vmstate_info_uint16, __u16) ++#define VMSTATE_U32_V(_f, _s, _v) \ ++ VMSTATE_SINGLE(_f, _s, _v, vmstate_info_uint32, __u32) ++#define VMSTATE_U64_V(_f, _s, _v) \ ++ VMSTATE_SINGLE(_f, _s, _v, vmstate_info_uint64, __u64) ++ ++#endif ++ + #define VMSTATE_BOOL(_f, _s) \ + VMSTATE_BOOL_V(_f, _s, 0) + +@@ -776,6 +789,19 @@ extern const VMStateInfo vmstate_info_qtailq; + #define VMSTATE_UINT64(_f, _s) \ + VMSTATE_UINT64_V(_f, _s, 0) + ++#ifdef CONFIG_LINUX ++ ++#define VMSTATE_U8(_f, _s) \ ++ VMSTATE_U8_V(_f, _s, 0) ++#define VMSTATE_U16(_f, _s) \ ++ VMSTATE_U16_V(_f, _s, 0) ++#define VMSTATE_U32(_f, _s) \ ++ VMSTATE_U32_V(_f, _s, 0) ++#define VMSTATE_U64(_f, _s) \ ++ VMSTATE_U64_V(_f, _s, 0) ++ ++#endif ++ + #define VMSTATE_UINT8_EQUAL(_f, _s, _err_hint) \ + VMSTATE_SINGLE_FULL(_f, _s, 0, 0, \ + vmstate_info_uint8_equal, uint8_t, _err_hint) +-- +1.8.3.1 + diff --git a/SOURCES/kvm-vnc-detect-and-optimize-pageflips.patch b/SOURCES/kvm-vnc-detect-and-optimize-pageflips.patch new file mode 100644 index 0000000..eb67e2b --- /dev/null +++ b/SOURCES/kvm-vnc-detect-and-optimize-pageflips.patch @@ -0,0 +1,95 @@ +From 1b209dbf4eba1f7cdd456a809a2a8576e66a1464 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Tue, 13 Aug 2019 11:20:45 +0100 +Subject: [PATCH 01/10] vnc: detect and optimize pageflips +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Gerd Hoffmann +Message-id: <20190813112045.3887-2-kraxel@redhat.com> +Patchwork-id: 89956 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 1/1] vnc: detect and optimize pageflips +Bugzilla: 1727033 +RH-Acked-by: John Snow +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Thomas Huth + +When size and format of the display surface stays the same we can just +tag the guest display as dirty and be done with it. + +There is no need need to resize the vnc server display or to touch the +vnc client dirty bits. On the next refresh cycle +vnc_refresh_server_surface() will check for actual display content +changes and update the client dirty bits as needed. + +The desktop resize and framebuffer format notifications to the vnc +client will be skipped too. + +Signed-off-by: Gerd Hoffmann +Reviewed-by: Daniel P. Berrangé +Message-id: 20190116101049.8929-1-kraxel@redhat.com +(cherry picked from commit 61e77a5f0c788495566aecb437bcf6b2cf9cda97) +Signed-off-by: Danilo C. L. de Paula +--- + ui/vnc.c | 25 ++++++++++++++++++++++--- + 1 file changed, 22 insertions(+), 3 deletions(-) + +diff --git a/ui/vnc.c b/ui/vnc.c +index 86c6762..0bd44f1 100644 +--- a/ui/vnc.c ++++ b/ui/vnc.c +@@ -743,6 +743,17 @@ static void vnc_update_server_surface(VncDisplay *vd) + width, height); + } + ++static bool vnc_check_pageflip(DisplaySurface *s1, ++ DisplaySurface *s2) ++{ ++ return (s1 != NULL && ++ s2 != NULL && ++ surface_width(s1) == surface_width(s2) && ++ surface_height(s1) == surface_height(s2) && ++ surface_format(s1) == surface_format(s2)); ++ ++} ++ + static void vnc_dpy_switch(DisplayChangeListener *dcl, + DisplaySurface *surface) + { +@@ -750,6 +761,7 @@ static void vnc_dpy_switch(DisplayChangeListener *dcl, + "Display output is not active."; + static DisplaySurface *placeholder; + VncDisplay *vd = container_of(dcl, VncDisplay, dcl); ++ bool pageflip = vnc_check_pageflip(vd->ds, surface); + VncState *vs; + + if (surface == NULL) { +@@ -762,14 +774,21 @@ static void vnc_dpy_switch(DisplayChangeListener *dcl, + vnc_abort_display_jobs(vd); + vd->ds = surface; + +- /* server surface */ +- vnc_update_server_surface(vd); +- + /* guest surface */ + qemu_pixman_image_unref(vd->guest.fb); + vd->guest.fb = pixman_image_ref(surface->image); + vd->guest.format = surface->format; + ++ if (pageflip) { ++ vnc_set_area_dirty(vd->guest.dirty, vd, 0, 0, ++ surface_width(surface), ++ surface_height(surface)); ++ return; ++ } ++ ++ /* server surface */ ++ vnc_update_server_surface(vd); ++ + QTAILQ_FOREACH(vs, &vd->clients, next) { + vnc_colordepth(vs); + vnc_desktop_resize(vs); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-x86-Data-structure-changes-to-support-MSR-based-feat.patch b/SOURCES/kvm-x86-Data-structure-changes-to-support-MSR-based-feat.patch index 401a722..ac0bad3 100644 --- a/SOURCES/kvm-x86-Data-structure-changes-to-support-MSR-based-feat.patch +++ b/SOURCES/kvm-x86-Data-structure-changes-to-support-MSR-based-feat.patch @@ -1,16 +1,17 @@ -From 2f915d53815514554da5e8ec7e81a8cbb6fa439e Mon Sep 17 00:00:00 2001 +From 1f97a7e017e09c60ca5b81062308cb951c5972a1 Mon Sep 17 00:00:00 2001 From: "plai@redhat.com" -Date: Tue, 20 Aug 2019 00:24:34 +0100 -Subject: [PATCH 3/9] x86: Data structure changes to support MSR based features +Date: Wed, 3 Apr 2019 15:54:31 +0100 +Subject: [PATCH 07/10] x86: Data structure changes to support MSR based + features RH-Author: plai@redhat.com -Message-id: <1566260680-20995-4-git-send-email-plai@redhat.com> -Patchwork-id: 90064 -O-Subject: [RHEL8.0 qemu-kvm PATCH v3 3/9] x86: Data structure changes to support MSR based features -Bugzilla: 1718235 +Message-id: <1554306874-28796-8-git-send-email-plai@redhat.com> +Patchwork-id: 85389 +O-Subject: [RHEL8.1 qemu-kvm PATCH resend 07/10] x86: Data structure changes to support MSR based features +Bugzilla: 1561761 RH-Acked-by: Eduardo Habkost -RH-Acked-by: John Snow RH-Acked-by: Igor Mammedov +RH-Acked-by: Michael S. Tsirkin From: Robert Hoo @@ -31,7 +32,7 @@ Signed-off-by: Danilo C. L. de Paula 1 file changed, 142 insertions(+), 55 deletions(-) diff --git a/target/i386/cpu.c b/target/i386/cpu.c -index 6d38ac0..bbca6f4 100644 +index d86b744..a0fdd3a 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -773,17 +773,36 @@ static void x86_cpu_vendor_words2str(char *dst, uint32_t vendor1, @@ -379,7 +380,7 @@ index 6d38ac0..bbca6f4 100644 .tcg_features = ~0U, }, }; -@@ -2846,21 +2895,41 @@ static const TypeInfo host_x86_cpu_type_info = { +@@ -2961,21 +3010,41 @@ static const TypeInfo host_x86_cpu_type_info = { #endif @@ -426,7 +427,7 @@ index 6d38ac0..bbca6f4 100644 } } } -@@ -3104,11 +3173,18 @@ static void x86_cpu_get_feature_words(Object *obj, Visitor *v, +@@ -3219,11 +3288,18 @@ static void x86_cpu_get_feature_words(Object *obj, Visitor *v, for (w = 0; w < FEATURE_WORDS; w++) { FeatureWordInfo *wi = &feature_word_info[w]; @@ -449,7 +450,7 @@ index 6d38ac0..bbca6f4 100644 qwi->features = array[w]; /* List will be in reverse order, but order shouldn't matter */ -@@ -3464,16 +3540,26 @@ static uint32_t x86_cpu_get_supported_feature_word(FeatureWord w, +@@ -3579,16 +3655,26 @@ static uint32_t x86_cpu_get_supported_feature_word(FeatureWord w, bool migratable_only) { FeatureWordInfo *wi = &feature_word_info[w]; @@ -483,7 +484,7 @@ index 6d38ac0..bbca6f4 100644 } else if (tcg_enabled()) { r = wi->tcg_features; } else { -@@ -4534,9 +4620,10 @@ static void x86_cpu_adjust_feat_level(X86CPU *cpu, FeatureWord w) +@@ -4649,9 +4735,10 @@ static void x86_cpu_adjust_feat_level(X86CPU *cpu, FeatureWord w) { CPUX86State *env = &cpu->env; FeatureWordInfo *fi = &feature_word_info[w]; diff --git a/SOURCES/kvm-x86-cpu-Enable-CLDEMOTE-Demote-Cache-Line-cpu-featur.patch b/SOURCES/kvm-x86-cpu-Enable-CLDEMOTE-Demote-Cache-Line-cpu-featur.patch new file mode 100644 index 0000000..9cc429c --- /dev/null +++ b/SOURCES/kvm-x86-cpu-Enable-CLDEMOTE-Demote-Cache-Line-cpu-featur.patch @@ -0,0 +1,56 @@ +From a10f2cff4a418edae4f3040c4bf09e5aad80316a Mon Sep 17 00:00:00 2001 +From: "plai@redhat.com" +Date: Mon, 20 May 2019 20:05:56 +0100 +Subject: [PATCH 1/5] x86/cpu: Enable CLDEMOTE(Demote Cache Line) cpu feature + +RH-Author: plai@redhat.com +Message-id: <1554409731-21082-1-git-send-email-plai@redhat.com> +Patchwork-id: 85447 +O-Subject: [RHEL8.1 qemu-kvm PATCH] x86/cpu: Enable CLDEMOTE(Demote Cache Line) cpu feature +Bugzilla: 1696436 +RH-Acked-by: Eduardo Habkost +RH-Acked-by: John Snow +RH-Acked-by: Paolo Bonzini + +From: Jingqi Liu + +BZ: https://bugzilla.redhat.com/show_bug.cgi?id=1696436 +Brew: http://brewweb.devel.redhat.com/brew/taskinfo?taskID=20946375 +Branch: rhel-8.1.0 + +Tested by Intel QA on SNR (simics) + +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.c | 2 +- + target/i386/cpu.h | 1 + + 2 files changed, 2 insertions(+), 1 deletion(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index 8ff6c38..77be7e8 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -1025,7 +1025,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { + "avx512bitalg", NULL, "avx512-vpopcntdq", NULL, + "la57", NULL, NULL, NULL, + NULL, NULL, "rdpid", NULL, +- NULL, NULL, NULL, NULL, ++ NULL, "cldemote", NULL, NULL, + NULL, NULL, NULL, NULL, + }, + .cpuid = { +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index 3ae0e8c..4f9df6e 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -684,6 +684,7 @@ typedef uint32_t FeatureWordArray[FEATURE_WORDS]; + #define CPUID_7_0_ECX_AVX512_VPOPCNTDQ (1U << 14) /* POPCNT for vectors of DW/QW */ + #define CPUID_7_0_ECX_LA57 (1U << 16) + #define CPUID_7_0_ECX_RDPID (1U << 22) ++#define CPUID_7_0_ECX_CLDEMOTE (1U << 25) /* CLDEMOTE Instruction */ + + #define CPUID_7_0_EDX_AVX512_4VNNIW (1U << 2) /* AVX512 Neural Network Instructions */ + #define CPUID_7_0_EDX_AVX512_4FMAPS (1U << 3) /* AVX512 Multiply Accumulation Single Precision */ +-- +1.8.3.1 + diff --git a/SOURCES/kvm-x86-define-a-new-MSR-based-feature-word-FEATURE_WORD.patch b/SOURCES/kvm-x86-define-a-new-MSR-based-feature-word-FEATURE_WORD.patch index 6afb822..a9c2bcd 100644 --- a/SOURCES/kvm-x86-define-a-new-MSR-based-feature-word-FEATURE_WORD.patch +++ b/SOURCES/kvm-x86-define-a-new-MSR-based-feature-word-FEATURE_WORD.patch @@ -1,17 +1,17 @@ -From 4263a1e54da9f6e1d1b0aa74d52436224a6cfd5e Mon Sep 17 00:00:00 2001 +From 8b64571f3ce90fc14c571ea588f608bce4328d34 Mon Sep 17 00:00:00 2001 From: "plai@redhat.com" -Date: Tue, 20 Aug 2019 00:24:35 +0100 -Subject: [PATCH 4/9] x86: define a new MSR based feature word -- +Date: Wed, 3 Apr 2019 15:54:32 +0100 +Subject: [PATCH 08/10] x86: define a new MSR based feature word -- FEATURE_WORDS_ARCH_CAPABILITIES RH-Author: plai@redhat.com -Message-id: <1566260680-20995-5-git-send-email-plai@redhat.com> -Patchwork-id: 90069 -O-Subject: [RHEL8.0 qemu-kvm PATCH v3 4/9] x86: define a new MSR based feature word -- FEATURE_WORDS_ARCH_CAPABILITIES -Bugzilla: 1718235 +Message-id: <1554306874-28796-9-git-send-email-plai@redhat.com> +Patchwork-id: 85385 +O-Subject: [RHEL8.1 qemu-kvm PATCH resend 08/10] x86: define a new MSR based feature word -- FEATURE_WORDS_ARCH_CAPABILITIES +Bugzilla: 1561761 RH-Acked-by: Eduardo Habkost -RH-Acked-by: John Snow RH-Acked-by: Igor Mammedov +RH-Acked-by: Michael S. Tsirkin From: Robert Hoo @@ -34,7 +34,7 @@ Signed-off-by: Danilo C. L. de Paula 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/target/i386/cpu.c b/target/i386/cpu.c -index bbca6f4..fbcf124 100644 +index a0fdd3a..8750f64 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -1143,6 +1143,27 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { @@ -65,7 +65,7 @@ index bbca6f4..fbcf124 100644 }; typedef struct X86RegisterInfo32 { -@@ -3550,7 +3571,8 @@ static uint32_t x86_cpu_get_supported_feature_word(FeatureWord w, +@@ -3665,7 +3686,8 @@ static uint32_t x86_cpu_get_supported_feature_word(FeatureWord w, wi->cpuid.reg); break; case MSR_FEATURE_WORD: @@ -76,7 +76,7 @@ index bbca6f4..fbcf124 100644 } } else if (hvf_enabled()) { diff --git a/target/i386/cpu.h b/target/i386/cpu.h -index e5e5169..6820a70 100644 +index dd4493e..63f692f 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -500,6 +500,7 @@ typedef enum FeatureWord { @@ -87,7 +87,7 @@ index e5e5169..6820a70 100644 FEATURE_WORDS, } FeatureWord; -@@ -726,6 +727,13 @@ typedef uint32_t FeatureWordArray[FEATURE_WORDS]; +@@ -729,6 +730,13 @@ typedef uint32_t FeatureWordArray[FEATURE_WORDS]; #define CPUID_TOPOLOGY_LEVEL_SMT (1U << 8) #define CPUID_TOPOLOGY_LEVEL_CORE (2U << 8) @@ -102,10 +102,10 @@ index e5e5169..6820a70 100644 #define HYPERV_SPINLOCK_NEVER_RETRY 0xFFFFFFFF #endif diff --git a/target/i386/kvm.c b/target/i386/kvm.c -index 87e4771..187ee19 100644 +index 096ed24..f1626a4 100644 --- a/target/i386/kvm.c +++ b/target/i386/kvm.c -@@ -1753,6 +1753,17 @@ static int kvm_put_msrs(X86CPU *cpu, int level) +@@ -1833,6 +1833,17 @@ static int kvm_put_msrs(X86CPU *cpu, int level) } #endif diff --git a/SPECS/qemu-kvm.spec b/SPECS/qemu-kvm.spec index 59eacd8..0fc26de 100644 --- a/SPECS/qemu-kvm.spec +++ b/SPECS/qemu-kvm.spec @@ -8,7 +8,6 @@ %global have_gluster 1 %global have_kvm_setup 0 %global have_memlock_limits 0 -%global have_vxhs 0 %ifnarch %{ix86} x86_64 %global have_usbredir 0 @@ -25,7 +24,6 @@ %endif %ifarch x86_64 %global kvm_target x86_64 - %global have_vxhs 1 %else %global have_spice 0 %global have_opengl 0 @@ -39,6 +37,7 @@ %endif %ifarch s390x %global kvm_target s390x + %global have_kvm_setup 1 %endif %ifarch ppc %global kvm_target ppc @@ -68,7 +67,7 @@ Obsoletes: %1-rhev Summary: QEMU is a machine emulator and virtualizer Name: qemu-kvm Version: 2.12.0 -Release: 65%{?dist}.5 +Release: 88%{?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 @@ -1318,52 +1317,370 @@ Patch638: kvm-qga-fix-driver-leak-in-guest-get-fsinfo.patch Patch639: kvm-slirp-check-data-length-while-emulating-ident-functi.patch # For bz#1668162 - CVE-2019-6501 qemu-kvm: QEMU: scsi-generic: possible OOB access while handling inquiry request [rhel-8] Patch640: kvm-scsi-generic-avoid-possible-out-of-bounds-access-to-.patch +# For bz#1645411 - the "fsfreeze-hook" script path shown by command "qemu-ga --help" or "man qemu-ga" is wrong +Patch641: kvm-doc-fix-the-configuration-path.patch +# For bz#1664371 - [IBM 8.1 FEAT] Update hardware CPU Model z14 (kvm) - qemu part +Patch642: kvm-s390x-cpumodel-mepochptff-warn-when-no-mepoch-and-re.patch +# For bz#1664371 - [IBM 8.1 FEAT] Update hardware CPU Model z14 (kvm) - qemu part +Patch643: kvm-s390x-cpumodel-add-z14-GA2-model.patch +# For bz#1664371 - [IBM 8.1 FEAT] Update hardware CPU Model z14 (kvm) - qemu part +Patch644: kvm-redhat-s390x-cpumodel-enable-mepoch-by-default-for-z.patch +# For bz#1662272 - Boot guest with device assignment+vIOMMU, qemu prompts "vtd_interrupt_remap_msi: MSI address low 32 bit invalid: 0x0" when first rebooting guest +Patch645: kvm-intel_iommu-fix-operator-in-vtd_switch_address_space.patch +# For bz#1662272 - Boot guest with device assignment+vIOMMU, qemu prompts "vtd_interrupt_remap_msi: MSI address low 32 bit invalid: 0x0" when first rebooting guest +Patch646: kvm-intel_iommu-reset-intr_enabled-when-system-reset.patch +# For bz#1662272 - Boot guest with device assignment+vIOMMU, qemu prompts "vtd_interrupt_remap_msi: MSI address low 32 bit invalid: 0x0" when first rebooting guest +Patch647: kvm-pci-msi-export-msi_is_masked.patch +# For bz#1662272 - Boot guest with device assignment+vIOMMU, qemu prompts "vtd_interrupt_remap_msi: MSI address low 32 bit invalid: 0x0" when first rebooting guest +Patch648: kvm-i386-kvm-ignore-masked-irqs-when-update-msi-routes.patch +# For bz#1694148 - QEMU image locking needn't double open fd number, and it should not fail when attempting to release locks +Patch649: kvm-iotests-153-Fix-dead-code.patch +# For bz#1694148 - QEMU image locking needn't double open fd number, and it should not fail when attempting to release locks +Patch650: kvm-file-posix-Include-filename-in-locking-error-message.patch +# For bz#1694148 - QEMU image locking needn't double open fd number, and it should not fail when attempting to release locks +Patch651: kvm-file-posix-Skip-effectiveless-OFD-lock-operations.patch +# For bz#1694148 - QEMU image locking needn't double open fd number, and it should not fail when attempting to release locks +Patch652: kvm-file-posix-Drop-s-lock_fd.patch +# For bz#1694148 - QEMU image locking needn't double open fd number, and it should not fail when attempting to release locks +Patch653: kvm-tests-Add-unit-tests-for-image-locking.patch +# For bz#1694148 - QEMU image locking needn't double open fd number, and it should not fail when attempting to release locks +Patch654: kvm-file-posix-Fix-shared-locks-on-reopen-commit.patch +# For bz#1694148 - QEMU image locking needn't double open fd number, and it should not fail when attempting to release locks +Patch655: kvm-iotests-Test-file-posix-locking-and-reopen.patch +# For bz#1694148 - QEMU image locking needn't double open fd number, and it should not fail when attempting to release locks +Patch656: kvm-block-file-posix-do-not-fail-on-unlock-bytes.patch +# For bz#1687596 - [Intel 8.1 BUG][KVM][Crystal Ridge]object_get_canonical_path_component: assertion failed: (obj->parent != NULL) +Patch657: kvm-hostmem-file-remove-object-id-from-pmem-error-messag.patch # For bz#1693116 - CVE-2018-20815 qemu-kvm: QEMU: device_tree: heap buffer overflow while loading device tree blob [rhel-8.0] -Patch641: kvm-device_tree-Fix-integer-overflowing-in-load_device_t.patch -# For bz#1704545 - CVE-2018-12126 virt:rhel/qemu-kvm: hardware: Microarchitectural Store Buffer Data Sampling [rhel-8.0.0.z] -Patch642: kvm-target-i386-define-md-clear-bit-rhev.patch -# For bz#1732324 - CVE-2019-6778 qemu-kvm: QEMU: slirp: heap buffer overflow in tcp_emu() [rhel-8.0.0.z] -Patch643: kvm-slirp-check-sscanf-result-when-emulating-ident.patch -# For bz#1732324 - CVE-2019-6778 qemu-kvm: QEMU: slirp: heap buffer overflow in tcp_emu() [rhel-8.0.0.z] -Patch644: kvm-slirp-fix-big-little-endian-conversion-in-ident-prot.patch -# For bz#1732324 - CVE-2019-6778 qemu-kvm: QEMU: slirp: heap buffer overflow in tcp_emu() [rhel-8.0.0.z] -Patch645: kvm-slirp-ensure-there-is-enough-space-in-mbuf-to-null-t.patch -# For bz#1732324 - CVE-2019-6778 qemu-kvm: QEMU: slirp: heap buffer overflow in tcp_emu() [rhel-8.0.0.z] -Patch646: kvm-slirp-don-t-manipulate-so_rcv-in-tcp_emu.patch -# For bz#1718992 - qemu-kvm core dumped after hotplug the deleted disk with iothread parameter [rhel-8.0.0.z] -Patch647: kvm-virtio-scsi-Move-BlockBackend-back-to-the-main-AioCo.patch -# For bz#1718992 - qemu-kvm core dumped after hotplug the deleted disk with iothread parameter [rhel-8.0.0.z] -Patch648: kvm-scsi-disk-Acquire-the-AioContext-in-scsi_-_realize.patch -# For bz#1718992 - qemu-kvm core dumped after hotplug the deleted disk with iothread parameter [rhel-8.0.0.z] -Patch649: kvm-virtio-scsi-Forbid-devices-with-different-iothreads-.patch -# For bz#1719228 - Detached device when trying to upgrade USB device firmware when in doing USB Passthrough via QEMU [rhel-8.0.0.z] -Patch650: kvm-Introduce-new-no_guest_reset-parameter-for-usb-host-.patch -# For bz#1719228 - Detached device when trying to upgrade USB device firmware when in doing USB Passthrough via QEMU [rhel-8.0.0.z] -Patch651: kvm-usb-call-reset-handler-before-updating-state.patch -# For bz#1719228 - Detached device when trying to upgrade USB device firmware when in doing USB Passthrough via QEMU [rhel-8.0.0.z] -Patch652: kvm-usb-host-skip-reset-for-untouched-devices.patch -# For bz#1719228 - Detached device when trying to upgrade USB device firmware when in doing USB Passthrough via QEMU [rhel-8.0.0.z] -Patch653: kvm-usb-host-avoid-libusb_set_configuration-calls.patch -# For bz#1734750 - CVE-2019-14378 qemu-kvm: QEMU: slirp: heap buffer overflow during packet reassembly [rhel-8.0.0.z] -Patch654: kvm-Fix-heap-overflow-in-ip_reass-on-big-packet-input.patch -# For bz#1718235 - [Intel 8.1 Bug] [KVM][CLX] CPUID_7_0_EDX_ARCH_CAPABILITIES is not enabled in VM - qemu-kvm [rhel-8.0.0.z] -Patch655: kvm-i386-Add-new-MSR-indices-for-IA32_PRED_CMD-and-IA32_.patch -# For bz#1718235 - [Intel 8.1 Bug] [KVM][CLX] CPUID_7_0_EDX_ARCH_CAPABILITIES is not enabled in VM - qemu-kvm [rhel-8.0.0.z] -Patch656: kvm-i386-Add-CPUID-bit-and-feature-words-for-IA32_ARCH_C.patch -# For bz#1718235 - [Intel 8.1 Bug] [KVM][CLX] CPUID_7_0_EDX_ARCH_CAPABILITIES is not enabled in VM - qemu-kvm [rhel-8.0.0.z] -Patch657: kvm-x86-Data-structure-changes-to-support-MSR-based-feat.patch -# For bz#1718235 - [Intel 8.1 Bug] [KVM][CLX] CPUID_7_0_EDX_ARCH_CAPABILITIES is not enabled in VM - qemu-kvm [rhel-8.0.0.z] -Patch658: kvm-x86-define-a-new-MSR-based-feature-word-FEATURE_WORD.patch -# For bz#1718235 - [Intel 8.1 Bug] [KVM][CLX] CPUID_7_0_EDX_ARCH_CAPABILITIES is not enabled in VM - qemu-kvm [rhel-8.0.0.z] -Patch659: kvm-Add-support-to-KVM_GET_MSR_FEATURE_INDEX_LIST-an.patch -# For bz#1718235 - [Intel 8.1 Bug] [KVM][CLX] CPUID_7_0_EDX_ARCH_CAPABILITIES is not enabled in VM - qemu-kvm [rhel-8.0.0.z] -Patch660: kvm-Use-KVM_GET_MSR_INDEX_LIST-for-MSR_IA32_ARCH_CAP.patch -# For bz#1718235 - [Intel 8.1 Bug] [KVM][CLX] CPUID_7_0_EDX_ARCH_CAPABILITIES is not enabled in VM - qemu-kvm [rhel-8.0.0.z] -Patch661: kvm-i386-kvm-Disable-arch_capabilities-if-MSR-can-t-be-s.patch -# For bz#1718235 - [Intel 8.1 Bug] [KVM][CLX] CPUID_7_0_EDX_ARCH_CAPABILITIES is not enabled in VM - qemu-kvm [rhel-8.0.0.z] -Patch662: kvm-i386-Make-arch_capabilities-migratable.patch -# For bz#1718235 - [Intel 8.1 Bug] [KVM][CLX] CPUID_7_0_EDX_ARCH_CAPABILITIES is not enabled in VM - qemu-kvm [rhel-8.0.0.z] -Patch663: kvm-target-i386-add-MDS-NO-feature.patch +Patch658: kvm-device_tree-Fix-integer-overflowing-in-load_device_t.patch +# For bz#1699070 - Backport s390x-related fixes for qemu-kvm +Patch659: kvm-s390x-ipl-Try-to-detect-Linux-vs-non-Linux-for-initi.patch +# For bz#1699070 - Backport s390x-related fixes for qemu-kvm +Patch660: kvm-loader-Check-access-size-when-calling-rom_ptr-to-avo.patch +# For bz#1699070 - Backport s390x-related fixes for qemu-kvm +Patch661: kvm-hw-s390x-Use-the-IEC-binary-prefix-definitions.patch +# For bz#1699070 - Backport s390x-related fixes for qemu-kvm +Patch662: kvm-s390x-storage-attributes-fix-CMMA_BLOCK_SIZE-usage.patch +# For bz#1699070 - Backport s390x-related fixes for qemu-kvm +Patch663: kvm-s390x-cpumodel-fix-segmentation-fault-when-baselinin.patch +# For bz#1699070 - Backport s390x-related fixes for qemu-kvm +Patch664: kvm-hw-s390x-s390-pci-bus-Convert-sysbus-init-function-t.patch +# For bz#1699070 - Backport s390x-related fixes for qemu-kvm +Patch665: kvm-s390x-pci-properly-fail-if-the-zPCI-device-cannot-be.patch +# For bz#1699070 - Backport s390x-related fixes for qemu-kvm +Patch666: kvm-s390x-pci-rename-hotplug-handler-callbacks.patch +# For bz#1699070 - Backport s390x-related fixes for qemu-kvm +Patch667: kvm-s390-avoid-potential-null-dereference-in-s390_pcihos.patch +# For bz#1699070 - Backport s390x-related fixes for qemu-kvm +Patch668: kvm-s390x-pci-Send-correct-event-on-hotplug.patch +# For bz#1699070 - Backport s390x-related fixes for qemu-kvm +Patch669: kvm-s390x-pci-Set-the-iommu-region-size-mpcifc-request.patch +# For bz#1699070 - Backport s390x-related fixes for qemu-kvm +Patch670: kvm-s390x-pci-Always-delete-and-free-the-release_timer.patch +# For bz#1699070 - Backport s390x-related fixes for qemu-kvm +Patch671: kvm-s390x-pci-Ignore-the-unplug-call-if-we-already-have-.patch +# For bz#1699070 - Backport s390x-related fixes for qemu-kvm +Patch672: kvm-s390x-pci-Use-hotplug_dev-instead-of-looking-up-the-.patch +# For bz#1699070 - Backport s390x-related fixes for qemu-kvm +Patch673: kvm-s390x-pci-Move-some-hotplug-checks-to-the-pre_plug-h.patch +# For bz#1699070 - Backport s390x-related fixes for qemu-kvm +Patch674: kvm-s390x-pci-Introduce-unplug-requests-and-split-unplug.patch +# For bz#1699070 - Backport s390x-related fixes for qemu-kvm +Patch675: kvm-s390x-pci-Drop-release-timer-and-replace-it-with-a-f.patch +# For bz#1699070 - Backport s390x-related fixes for qemu-kvm +Patch676: kvm-s390x-pci-mark-zpci-devices-as-unmigratable.patch +# For bz#1699070 - Backport s390x-related fixes for qemu-kvm +Patch677: kvm-s390x-pci-Fix-primary-bus-number-for-PCI-bridges.patch +# For bz#1699070 - Backport s390x-related fixes for qemu-kvm +Patch678: kvm-s390x-pci-Fix-hotplugging-of-PCI-bridges.patch +# For bz#1699070 - Backport s390x-related fixes for qemu-kvm +Patch679: kvm-s390x-pci-Warn-when-adding-PCI-devices-without-the-z.patch +# For bz#1699070 - Backport s390x-related fixes for qemu-kvm +Patch680: kvm-s390x-pci-Unplug-remaining-requested-devices-on-pcih.patch +# For bz#1699070 - Backport s390x-related fixes for qemu-kvm +Patch681: kvm-s390x-refactor-reset-reipl-handling.patch +# For bz#1699070 - Backport s390x-related fixes for qemu-kvm +Patch682: kvm-s390-ipl-fix-ipl-with-no-reboot.patch +# For bz#1680231 - severe performance impact using luks format +Patch683: kvm-tests-crypto-Use-the-IEC-binary-prefix-definitions.patch +# For bz#1680231 - severe performance impact using luks format +Patch684: kvm-crypto-expand-algorithm-coverage-for-cipher-benchmar.patch +# For bz#1680231 - severe performance impact using luks format +Patch685: kvm-crypto-remove-code-duplication-in-tweak-encrypt-decr.patch +# For bz#1680231 - severe performance impact using luks format +Patch686: kvm-crypto-introduce-a-xts_uint128-data-type.patch +# For bz#1680231 - severe performance impact using luks format +Patch687: kvm-crypto-convert-xts_tweak_encdec-to-use-xts_uint128-t.patch +# For bz#1680231 - severe performance impact using luks format +Patch688: kvm-crypto-convert-xts_mult_x-to-use-xts_uint128-type.patch +# For bz#1680231 - severe performance impact using luks format +Patch689: kvm-crypto-annotate-xts_tweak_encdec-as-inlineable.patch +# For bz#1680231 - severe performance impact using luks format +Patch690: kvm-crypto-refactor-XTS-cipher-mode-test-suite.patch +# For bz#1680231 - severe performance impact using luks format +Patch691: kvm-crypto-add-testing-for-unaligned-buffers-with-XTS-ci.patch +# For bz#1561761 - [Intel 8.1 Feat] qemu-kvm Introduce Icelake cpu model +Patch692: kvm-i386-Add-new-MSR-indices-for-IA32_PRED_CMD-and-IA32_.patch +# For bz#1561761 - [Intel 8.1 Feat] qemu-kvm Introduce Icelake cpu model +Patch693: kvm-i386-Add-CPUID-bit-and-feature-words-for-IA32_ARCH_C.patch +# For bz#1561761 - [Intel 8.1 Feat] qemu-kvm Introduce Icelake cpu model +Patch694: kvm-i386-Add-CPUID-bit-for-PCONFIG.patch +# For bz#1561761 - [Intel 8.1 Feat] qemu-kvm Introduce Icelake cpu model +Patch695: kvm-i386-Add-CPUID-bit-for-WBNOINVD.patch +# For bz#1561761 - [Intel 8.1 Feat] qemu-kvm Introduce Icelake cpu model +Patch696: kvm-i386-Add-new-CPU-model-Icelake-Server-Client.patch +# For bz#1561761 - [Intel 8.1 Feat] qemu-kvm Introduce Icelake cpu model +Patch697: kvm-Add-support-to-KVM_GET_MSR_FEATURE_INDEX_LIST-an.patch +# For bz#1561761 - [Intel 8.1 Feat] qemu-kvm Introduce Icelake cpu model +Patch698: kvm-x86-Data-structure-changes-to-support-MSR-based-feat.patch +# For bz#1561761 - [Intel 8.1 Feat] qemu-kvm Introduce Icelake cpu model +Patch699: kvm-x86-define-a-new-MSR-based-feature-word-FEATURE_WORD.patch +# For bz#1561761 - [Intel 8.1 Feat] qemu-kvm Introduce Icelake cpu model +Patch700: kvm-i386-remove-the-new-CPUID-PCONFIG-from-Icelake-Serve.patch +# For bz#1561761 - [Intel 8.1 Feat] qemu-kvm Introduce Icelake cpu model +Patch701: kvm-Revert-i386-Add-CPUID-bit-for-PCONFIG.patch +# For bz#1683275 - [IBM 8.1 FEAT] KVM: Secure Linux Boot Toleration (qemu) +Patch702: kvm-s390-bios-Skip-bootmap-signature-entries.patch +# For bz#1707706 - /builddir/build/BUILD/qemu-2.12.0/target/i386/kvm.c:2031: kvm_put_msrs: Assertion `ret == cpu->kvm_msr_buf->nmsrs' failed. +Patch703: kvm-Use-KVM_GET_MSR_INDEX_LIST-for-MSR_IA32_ARCH_CAP.patch +# For bz#1707706 - /builddir/build/BUILD/qemu-2.12.0/target/i386/kvm.c:2031: kvm_put_msrs: Assertion `ret == cpu->kvm_msr_buf->nmsrs' failed. +Patch704: kvm-i386-kvm-Disable-arch_capabilities-if-MSR-can-t-be-s.patch +# For bz#1561761 - [Intel 8.1 Feat] qemu-kvm Introduce Icelake cpu model +Patch705: kvm-i386-remove-the-INTEL_PT-CPUID-bit-from-named-CPU-mo.patch +# For bz#1561761 - [Intel 8.1 Feat] qemu-kvm Introduce Icelake cpu model +Patch706: kvm-i386-Disable-OSPKE-on-CPU-model-definitions.patch +# For bz#1696436 - [Intel 8.0 Feat] KVM Enabling SnowRidge new NIs - qemu-kvm +Patch707: kvm-x86-cpu-Enable-CLDEMOTE-Demote-Cache-Line-cpu-featur.patch +# For bz#1667249 - Fail to launch AMD SEV VM with assigned PCI device +Patch708: kvm-memory-Fix-the-memory-region-type-assignment-order.patch +# For bz#1667249 - Fail to launch AMD SEV VM with assigned PCI device +Patch709: kvm-target-i386-sev-Do-not-pin-the-ram-device-memory-reg.patch +# For bz#1673010 - Local VM and migrated VM on the same host can run with same RAW file as visual disk source while without shareable configured or lock manager enabled +Patch710: kvm-block-Fix-invalidate_cache-error-path-for-parent-act.patch +# For bz#1703302 - CVE-2018-12130 virt:rhel/qemu-kvm: hardware: Microarchitectural Fill Buffer Data Sampling (MFBDS) [rhel-8] +# For bz#1703308 - CVE-2018-12127 virt:rhel/qemu-kvm: hardware: Micro-architectural Load Port Data Sampling - Information Leak (MLPDS) [rhel-8] +Patch711: kvm-target-i386-define-md-clear-bit.patch +# For bz#1660912 - [IBM 8.1 FEAT] KVM s390x: Add hardware CPU Model - qemu part +Patch712: kvm-s390x-cpumodel-enum-type-S390FeatGroup-now-gets-gene.patch +# For bz#1660912 - [IBM 8.1 FEAT] KVM s390x: Add hardware CPU Model - qemu part +Patch713: kvm-linux-headers-update-against-Linux-5.2-rc1.patch +# For bz#1660912 - [IBM 8.1 FEAT] KVM s390x: Add hardware CPU Model - qemu part +Patch714: kvm-s390x-cpumodel-ignore-csske-for-expansion.patch +# For bz#1660912 - [IBM 8.1 FEAT] KVM s390x: Add hardware CPU Model - qemu part +Patch715: kvm-s390x-cpumodel-Miscellaneous-Instruction-Extensions-.patch +# For bz#1660912 - [IBM 8.1 FEAT] KVM s390x: Add hardware CPU Model - qemu part +Patch716: kvm-s390x-cpumodel-msa9-facility.patch +# For bz#1660912 - [IBM 8.1 FEAT] KVM s390x: Add hardware CPU Model - qemu part +Patch717: kvm-s390x-cpumodel-vector-enhancements.patch +# For bz#1660912 - [IBM 8.1 FEAT] KVM s390x: Add hardware CPU Model - qemu part +Patch718: kvm-s390x-cpumodel-enhanced-sort-facility.patch +# For bz#1660912 - [IBM 8.1 FEAT] KVM s390x: Add hardware CPU Model - qemu part +Patch719: kvm-s390x-cpumodel-add-Deflate-conversion-facility.patch +# For bz#1660912 - [IBM 8.1 FEAT] KVM s390x: Add hardware CPU Model - qemu part +Patch720: kvm-s390x-cpumodel-add-gen15-defintions.patch +# For bz#1660912 - [IBM 8.1 FEAT] KVM s390x: Add hardware CPU Model - qemu part +Patch721: kvm-s390x-cpumodel-wire-up-8561-and-8562-as-gen15-machin.patch +# For bz#1712946 - qemu-kvm build is broken due to spice_qxl_set_max_monitors being deprecated +Patch722: kvm-spice-set-device-address-and-device-display-ID-in-QX.patch +# For bz#1712946 - qemu-kvm build is broken due to spice_qxl_set_max_monitors being deprecated +Patch723: kvm-hw-pci-Add-missing-include.patch +# For bz#1713677 - Detached device when trying to upgrade USB device firmware when in doing USB Passthrough via QEMU +Patch724: kvm-Introduce-new-no_guest_reset-parameter-for-usb-host-.patch +# For bz#1713677 - Detached device when trying to upgrade USB device firmware when in doing USB Passthrough via QEMU +Patch725: kvm-usb-call-reset-handler-before-updating-state.patch +# For bz#1713677 - Detached device when trying to upgrade USB device firmware when in doing USB Passthrough via QEMU +Patch726: kvm-usb-host-skip-reset-for-untouched-devices.patch +# For bz#1713677 - Detached device when trying to upgrade USB device firmware when in doing USB Passthrough via QEMU +Patch727: kvm-usb-host-avoid-libusb_set_configuration-calls.patch +# For bz#1673396 - qemu-kvm core dumped after hotplug the deleted disk with iothread parameter +# For bz#1673401 - Qemu core dump when start guest with two disks using same drive +Patch728: kvm-virtio-scsi-Move-BlockBackend-back-to-the-main-AioCo.patch +# For bz#1673396 - qemu-kvm core dumped after hotplug the deleted disk with iothread parameter +# For bz#1673401 - Qemu core dump when start guest with two disks using same drive +Patch729: kvm-scsi-disk-Acquire-the-AioContext-in-scsi_-_realize.patch +# For bz#1673396 - qemu-kvm core dumped after hotplug the deleted disk with iothread parameter +# For bz#1673401 - Qemu core dump when start guest with two disks using same drive +Patch730: kvm-virtio-scsi-Forbid-devices-with-different-iothreads-.patch +# For bz#1714933 - Disable VXHS in qemu-kvm +Patch731: kvm-Disable-VXHS-support.patch +# For bz#1709970 - [Intel 8.1 Bug] [KVM][CLX] CPUID_7_0_EDX_ARCH_CAPABILITIES is not enabled in VM - qemu-kvm +Patch732: kvm-i386-Make-arch_capabilities-migratable.patch +# For bz#1710662 - [IBM 8.1 FEAT] POWER9 - Virt: qemu: NVLink2 passthru to guest - Nvidia Volta (GPU) (kvm) +Patch733: kvm-spapr-Fix-ibm-max-associativity-domains-property-num.patch +# For bz#1710662 - [IBM 8.1 FEAT] POWER9 - Virt: qemu: NVLink2 passthru to guest - Nvidia Volta (GPU) (kvm) +Patch734: kvm-linux-headers-Update-for-NVLink2-passthrough-downstr.patch +# For bz#1710662 - [IBM 8.1 FEAT] POWER9 - Virt: qemu: NVLink2 passthru to guest - Nvidia Volta (GPU) (kvm) +Patch735: kvm-pci-Move-NVIDIA-vendor-id-to-the-rest-of-ids.patch +# For bz#1710662 - [IBM 8.1 FEAT] POWER9 - Virt: qemu: NVLink2 passthru to guest - Nvidia Volta (GPU) (kvm) +Patch736: kvm-vfio-quirks-Add-common-quirk-alloc-helper.patch +# For bz#1710662 - [IBM 8.1 FEAT] POWER9 - Virt: qemu: NVLink2 passthru to guest - Nvidia Volta (GPU) (kvm) +Patch737: kvm-vfio-Make-vfio_get_region_info_cap-public.patch +# For bz#1710662 - [IBM 8.1 FEAT] POWER9 - Virt: qemu: NVLink2 passthru to guest - Nvidia Volta (GPU) (kvm) +Patch738: kvm-spapr-Support-NVIDIA-V100-GPU-with-NVLink2.patch +# For bz#1721983 - qemu-kvm can't be build with new gluster version (6.0.6) +Patch739: kvm-gluster-Handle-changed-glfs_ftruncate-signature.patch +# For bz#1721983 - qemu-kvm can't be build with new gluster version (6.0.6) +Patch740: kvm-gluster-the-glfs_io_cbk-callback-function-pointer-ad.patch +# For bz#1712705 - CVE-2019-12155 qemu-kvm: QEMU: qxl: null pointer dereference while releasing spice resources [rhel-8] +Patch741: kvm-qxl-check-release-info-object.patch +# For bz#1707598 - qemu-iotest 182 fails without device hotplugging support +Patch742: kvm-iotests-Make-182-do-without-device_add.patch +# For bz#1714792 - [Intel 8.1 FEAT] MDS_NO exposure to guest +Patch743: kvm-target-i386-add-MDS-NO-feature.patch +# For bz#1531543 - [RFE] add iommu support to virtio-gpu +Patch744: kvm-virtio-gpu-pass-down-VirtIOGPU-pointer-to-a-bunch-of.patch +# For bz#1531543 - [RFE] add iommu support to virtio-gpu +Patch745: kvm-virtio-gpu-add-iommu-support.patch +# For bz#1531543 - [RFE] add iommu support to virtio-gpu +Patch746: kvm-virtio-gpu-fix-unmap-in-error-path.patch +# For bz#1629906 - [Intel 8.1 Feat] qemu-kvm Introduce Cascade Lake (CLX) cpu model +Patch747: kvm-i386-Add-new-model-of-Cascadelake-Server.patch +# For bz#1629906 - [Intel 8.1 Feat] qemu-kvm Introduce Cascade Lake (CLX) cpu model +Patch748: kvm-i386-Update-stepping-of-Cascadelake-Server.patch +# For bz#1629906 - [Intel 8.1 Feat] qemu-kvm Introduce Cascade Lake (CLX) cpu model +Patch749: kvm-target-i386-Disable-MPX-support-on-named-CPU-models.patch +# For bz#1629906 - [Intel 8.1 Feat] qemu-kvm Introduce Cascade Lake (CLX) cpu model +Patch750: kvm-i386-remove-the-INTEL_PT-CPUID-bit-from-named-CPU-NEW.patch +# For bz#1629906 - [Intel 8.1 Feat] qemu-kvm Introduce Cascade Lake (CLX) cpu model +Patch751: kvm-i386-Disable-OSPKE-on-CPU-model-definitions-NEW.patch +# For bz#1513367 - qemu with libssh +Patch752: kvm-block-ssh-Convert-from-DPRINTF-macro-to-trace-events.patch +# For bz#1513367 - qemu with libssh +Patch753: kvm-block-ssh-Do-not-report-read-write-flush-errors-to-t.patch +# For bz#1513367 - qemu with libssh +Patch754: kvm-qemu-iotests-Fix-paths-for-NFS.patch +# For bz#1513367 - qemu with libssh +Patch755: kvm-qemu-iotests-Filter-NFS-paths.patch +# For bz#1513367 - qemu with libssh +Patch756: kvm-iotests-Filter-SSH-paths.patch +# For bz#1513367 - qemu with libssh +Patch757: kvm-block-ssh-Implement-.bdrv_refresh_filename.patch +# For bz#1513367 - qemu with libssh +Patch758: kvm-iotests-Use-Python-byte-strings-where-appropriate.patch +# For bz#1513367 - qemu with libssh +Patch759: kvm-iotests-Unify-log-outputs-between-Python-2-and-3.patch +# For bz#1513367 - qemu with libssh +Patch760: kvm-ssh-switch-from-libssh2-to-libssh.patch +# For bz#1728657 - 'qemu-io write' to a raw image over libgfapi fails +Patch762: kvm-block-gluster-limit-the-transfer-size-to-512-MiB.patch +# For bz#1729975 - RHEL 8.1 Pre-Beta - Fix for hardware CPU Model +Patch763: kvm-s390-cpumodel-fix-description-for-the-new-vector-fac.patch +# For bz#1729975 - RHEL 8.1 Pre-Beta - Fix for hardware CPU Model +Patch764: kvm-s390x-cpumodel-remove-esort-from-the-default-model.patch +# For bz#1729975 - RHEL 8.1 Pre-Beta - Fix for hardware CPU Model +Patch765: kvm-s390x-cpumodel-also-change-name-of-vxbeh.patch +# For bz#1729975 - RHEL 8.1 Pre-Beta - Fix for hardware CPU Model +Patch766: kvm-s390x-cpumodel-change-internal-name-of-vxpdeh-to-mat.patch +# For bz#1728958 - Hot unplug vfio-pci NIC devices from sev guest will cause qemu-kvm: sev_ram_block_removed: failed to unregister region +Patch767: kvm-target-i386-sev-Do-not-unpin-ram-device-memory-regio.patch +# For bz#1689269 - Nested KVM: support for migration of nested hypervisors - Slow Train +Patch768: kvm-i386-Save-EFER-for-32-bit-targets.patch +# For bz#1689269 - Nested KVM: support for migration of nested hypervisors - Slow Train +Patch769: kvm-target-i386-rename-HF_SVMI_MASK-to-HF_GUEST_MASK.patch +# For bz#1689269 - Nested KVM: support for migration of nested hypervisors - Slow Train +Patch770: kvm-target-i386-kvm-add-VMX-migration-blocker.patch +# For bz#1689269 - Nested KVM: support for migration of nested hypervisors - Slow Train +Patch771: kvm-target-i386-kvm-just-return-after-migrate_add_blocke.patch +# For bz#1689269 - Nested KVM: support for migration of nested hypervisors - Slow Train +Patch772: kvm-target-i386-kvm-Delete-VMX-migration-blocker-on-vCPU.patch +# For bz#1689269 - Nested KVM: support for migration of nested hypervisors - Slow Train +Patch773: kvm-Introduce-kvm_arch_destroy_vcpu.patch +# For bz#1689269 - Nested KVM: support for migration of nested hypervisors - Slow Train +Patch774: kvm-target-i386-kvm-Use-symbolic-constant-for-DB-BP-exce.patch +# For bz#1689269 - Nested KVM: support for migration of nested hypervisors - Slow Train +Patch775: kvm-target-i386-kvm-Re-inject-DB-to-guest-with-updated-D.patch +# For bz#1689269 - Nested KVM: support for migration of nested hypervisors - Slow Train +Patch776: kvm-target-i386-kvm-Block-migration-for-vCPUs-exposed-wi.patch +# For bz#1689269 - Nested KVM: support for migration of nested hypervisors - Slow Train +Patch777: kvm-target-i386-kvm-do-not-initialize-padding-fields.patch +# For bz#1689269 - Nested KVM: support for migration of nested hypervisors - Slow Train +Patch778: kvm-linux-headers-synchronize-generic-and-x86-KVM-header.patch +# For bz#1689269 - Nested KVM: support for migration of nested hypervisors - Slow Train +Patch779: kvm-vmstate-Add-support-for-kernel-integer-types.patch +# For bz#1689269 - Nested KVM: support for migration of nested hypervisors - Slow Train +Patch780: kvm-target-i386-kvm-Add-support-for-save-and-restore-nes.patch +# For bz#1689269 - Nested KVM: support for migration of nested hypervisors - Slow Train +Patch781: kvm-target-i386-kvm-Add-support-for-KVM_CAP_EXCEPTION_PA.patch +# For bz#1689269 - Nested KVM: support for migration of nested hypervisors - Slow Train +Patch782: kvm-target-i386-kvm-Add-nested-migration-blocker-only-wh.patch +# For bz#1689269 - Nested KVM: support for migration of nested hypervisors - Slow Train +Patch783: kvm-target-i386-kvm-Demand-nested-migration-kernel-capab.patch +# For bz#1689269 - Nested KVM: support for migration of nested hypervisors - Slow Train +Patch784: kvm-target-i386-skip-KVM_GET-SET_NESTED_STATE-if-VMX-dis.patch +# For bz#1689269 - Nested KVM: support for migration of nested hypervisors - Slow Train +Patch785: kvm-i386-kvm-Do-not-sync-nested-state-during-runtime.patch +# For bz#1707192 - implement missing reset handler for cfi.pflash01 - slow train +Patch786: kvm-hw-block-pflash_cfi01-Add-missing-DeviceReset-handle.patch +# For bz#1678979 - qemu-img convert abort when converting image with unaligned size (qemu-img: block/io.c:2134: bdrv_co_block_status: Assertion `*pnum && (((*pnum) % (align)) == 0) && align > offset - aligned_offset\' failed) +Patch787: kvm-block-file-posix-Unaligned-O_DIRECT-block-status.patch +# For bz#1678979 - qemu-img convert abort when converting image with unaligned size (qemu-img: block/io.c:2134: bdrv_co_block_status: Assertion `*pnum && (((*pnum) % (align)) == 0) && align > offset - aligned_offset\' failed) +Patch788: kvm-iotests-Test-unaligned-raw-images-with-O_DIRECT.patch +# For bz#1678979 - qemu-img convert abort when converting image with unaligned size (qemu-img: block/io.c:2134: bdrv_co_block_status: Assertion `*pnum && (((*pnum) % (align)) == 0) && align > offset - aligned_offset\' failed) +Patch789: kvm-nbd-client-Lower-min_block-for-block-status-unaligne.patch +# For bz#1678979 - qemu-img convert abort when converting image with unaligned size (qemu-img: block/io.c:2134: bdrv_co_block_status: Assertion `*pnum && (((*pnum) % (align)) == 0) && align > offset - aligned_offset\' failed) +Patch790: kvm-nbd-client-Reject-inaccessible-tail-of-inconsistent-.patch +# For bz#1678979 - qemu-img convert abort when converting image with unaligned size (qemu-img: block/io.c:2134: bdrv_co_block_status: Assertion `*pnum && (((*pnum) % (align)) == 0) && align > offset - aligned_offset\' failed) +Patch791: kvm-nbd-client-Support-qemu-img-convert-from-unaligned-s.patch +# For bz#1678979 - qemu-img convert abort when converting image with unaligned size (qemu-img: block/io.c:2134: bdrv_co_block_status: Assertion `*pnum && (((*pnum) % (align)) == 0) && align > offset - aligned_offset\' failed) +Patch792: kvm-block-Add-bdrv_get_request_alignment.patch +# For bz#1678979 - qemu-img convert abort when converting image with unaligned size (qemu-img: block/io.c:2134: bdrv_co_block_status: Assertion `*pnum && (((*pnum) % (align)) == 0) && align > offset - aligned_offset\' failed) +Patch793: kvm-nbd-server-Advertise-actual-minimum-block-size.patch +# For bz#1727642 - CVE-2019-6778 qemu-kvm: QEMU: slirp: heap buffer overflow in tcp_emu() +Patch794: kvm-slirp-check-sscanf-result-when-emulating-ident.patch +# For bz#1727642 - CVE-2019-6778 qemu-kvm: QEMU: slirp: heap buffer overflow in tcp_emu() +Patch795: kvm-slirp-fix-big-little-endian-conversion-in-ident-prot.patch +# For bz#1727642 - CVE-2019-6778 qemu-kvm: QEMU: slirp: heap buffer overflow in tcp_emu() +Patch796: kvm-slirp-ensure-there-is-enough-space-in-mbuf-to-null-t.patch +# For bz#1727642 - CVE-2019-6778 qemu-kvm: QEMU: slirp: heap buffer overflow in tcp_emu() +Patch797: kvm-slirp-don-t-manipulate-so_rcv-in-tcp_emu.patch +# For bz#1732642 - enable the virtio-net frontend to work with the vhost-net backend in SEV guests +Patch798: kvm-tap-set-vhostfd-passed-from-qemu-cli-to-non-blocking.patch +# For bz#1734751 - CVE-2019-14378 qemu-kvm: QEMU: slirp: heap buffer overflow during packet reassembly [rhel-8.1.0] +Patch799: kvm-Fix-heap-overflow-in-ip_reass-on-big-packet-input.patch +# For bz#1727033 - vnc server should detect page-flips and avoid sending fullscreen updates then. +Patch800: kvm-vnc-detect-and-optimize-pageflips.patch +# For bz#1716349 - qemu with iothreads enabled crashes on resume after enospc pause for disk extension +Patch801: kvm-block-backend-Make-blk_inc-dec_in_flight-public.patch +# For bz#1716349 - qemu with iothreads enabled crashes on resume after enospc pause for disk extension +Patch802: kvm-virtio-blk-Increase-in_flight-for-request-restart-BH.patch +# For bz#1716349 - qemu with iothreads enabled crashes on resume after enospc pause for disk extension +Patch803: kvm-block-Fix-AioContext-switch-for-drained-node.patch +# For bz#1716349 - qemu with iothreads enabled crashes on resume after enospc pause for disk extension +Patch804: kvm-test-bdrv-drain-AioContext-switch-in-drained-section.patch +# For bz#1716349 - qemu with iothreads enabled crashes on resume after enospc pause for disk extension +Patch805: kvm-block-Use-normal-drain-for-bdrv_set_aio_context.patch +# For bz#1716347 - Qemu Core dump when quit vm that's in status "paused(io-error)" with data plane enabled +Patch806: kvm-block-Fix-AioContext-switch-for-bs-drv-NULL.patch +# For bz#1687541 - qemu aborted when start guest with a big iothreads +Patch807: kvm-iothread-fix-crash-with-invalid-properties.patch +# For bz#1687541 - qemu aborted when start guest with a big iothreads +Patch808: kvm-iothread-replace-init_done_cond-with-a-semaphore.patch +# For bz#1740797 - Disable memfd in QEMU +Patch809: kvm-RHEL-disable-hostmem-memfd.patch +# For bz#1684383 - qemu crashed when take screenshot for 2nd head of virtio video device if the display not opened by virt-viewer +Patch810: kvm-console-Avoid-segfault-in-screendump.patch +# For bz#1619661 - the attach hub on one hub still exits in device manager after unhotplug +Patch811: kvm-usb-hub-clear-suspend-on-detach.patch +# For bz#1727821 - Failed to convert a source image to the qcow2 image encrypted by luks +Patch812: kvm-qemu-img-fix-regression-copying-secrets-during-conve.patch +# For bz#1744415 - Backport support for count cache flush Spectre v2 mitigation [slow train] +Patch814: kvm-target-ppc-spapr-Add-workaround-option-to-SPAPR_CAP_.patch +# For bz#1744415 - Backport support for count cache flush Spectre v2 mitigation [slow train] +Patch815: kvm-target-ppc-spapr-Add-SPAPR_CAP_CCF_ASSIST.patch +# For bz#1747185 - "filtered-features" QOM property is not available +Patch816: kvm-i386-x86_cpu_list_feature_names-function.patch +# For bz#1747185 - "filtered-features" QOM property is not available +Patch817: kvm-i386-unavailable-features-QOM-property.patch +# For bz#1738839 - I/O error when virtio-blk disk is backed by a raw image on 4k disk +Patch818: kvm-file-posix-Handle-undetectable-alignment.patch +# For bz#1738839 - I/O error when virtio-blk disk is backed by a raw image on 4k disk +Patch819: kvm-iotests-Tweak-221-sizing-for-different-hole-granular.patch +# For bz#1738839 - I/O error when virtio-blk disk is backed by a raw image on 4k disk +Patch820: kvm-iotests-Filter-175-s-allocation-information.patch +# For bz#1738839 - I/O error when virtio-blk disk is backed by a raw image on 4k disk +Patch821: kvm-block-posix-Always-allocate-the-first-block.patch +# For bz#1738839 - I/O error when virtio-blk disk is backed by a raw image on 4k disk +Patch822: kvm-iotests-Test-allocate_first_block-with-O_DIRECT.patch BuildRequires: zlib-devel BuildRequires: glib2-devel @@ -1390,10 +1707,10 @@ BuildRequires: libcacard-devel # For smartcard NSS support BuildRequires: nss-devel %endif -BuildRequires: libseccomp-devel >= 2.3.0 +BuildRequires: libseccomp-devel >= 2.4.0 # For network block driver BuildRequires: libcurl-devel -BuildRequires: libssh2-devel +BuildRequires: libssh-devel BuildRequires: librados-devel BuildRequires: librbd-devel %if %{have_gluster} @@ -1504,7 +1821,7 @@ Requires: ipxe-roms-qemu >= 20170123-1 Requires: SLOF >= %{SLOF_gittagdate}-1.git%{SLOF_gittagcommit} %endif Requires: %{name}-common = %{epoch}:%{version}-%{release} -Requires: libseccomp >= 2.3.0 +Requires: libseccomp >= 2.4.0 # For compressed guest memory dumps Requires: lzo snappy %if %{have_gluster} @@ -1512,6 +1829,7 @@ Requires: glusterfs-api >= 3.6.0 %endif %if %{have_kvm_setup} Requires(post): systemd-units +Requires(preun): systemd-units %ifarch %{power64} Requires: powerpc-utils %endif @@ -1652,9 +1970,6 @@ buildldflags="VL_LDFLAGS=-Wl,--build-id" %global block_drivers_list qcow2,raw,file,host_device,nbd,iscsi,rbd,blkdebug,luks,null-co,nvme,copy-on-read,throttle -%if 0%{have_vxhs} - %global block_drivers_list %{block_drivers_list},vxhs -%endif %if 0%{have_gluster} %global block_drivers_list %{block_drivers_list},gluster %endif @@ -1713,11 +2028,7 @@ buildldflags="VL_LDFLAGS=-Wl,--build-id" --disable-usb-redir \ %endif --disable-tcmalloc \ -%if 0%{have_vxhs} - --enable-vxhs \ -%else --disable-vxhs \ -%endif %ifarch x86_64 --enable-libpmem \ %else @@ -1743,7 +2054,7 @@ buildldflags="VL_LDFLAGS=-Wl,--build-id" --enable-kvm \ --enable-libiscsi \ --disable-libnfs \ - --enable-libssh2 \ + --enable-libssh \ --enable-libusb \ --disable-bzip2 \ --enable-linux-aio \ @@ -1886,8 +2197,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/python/python3/' {} \; -find $RPM_BUILD_ROOT%{testsdir}/scripts/qmp/* -maxdepth 1 -type f -exec sed -i -e '1 s/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}+' {} \; +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}+' {} \; install -p -m 0644 %{SOURCE36} $RPM_BUILD_ROOT%{testsdir}/README @@ -2071,10 +2383,6 @@ chmod +x $RPM_BUILD_ROOT%{_libdir}/qemu-kvm/block-*.so %check export DIFF=diff; make check V=1 -pushd tests/qemu-iotests -./check -v -raw 001 002 004 005 008 009 010 011 012 021 025 032 033 048 052 063 077 086 101 106 120 140 143 145 150 159 160 162 170 171 175 184 221 226 ||: -./check -v -qcow2 001 002 004 005 008 009 010 011 012 017 018 019 020 021 024 025 027 028 029 032 033 034 035 037 038 042 046 047 048 050 052 053 058 062 063 066 068 069 072 073 074 086 087 089 090 095 098 102 103 105 107 108 110 111 120 127 133 134 138 140 141 143 144 145 150 154 156 158 159 162 170 177 179 182 184 188 190 195 204 209 217 226 ||: -popd %post -n qemu-kvm-core # load kvm modules now, so we can make sure no reboot is needed. @@ -2090,6 +2398,11 @@ sh %{_sysconfdir}/sysconfig/modules/kvm.modules &> /dev/null || : fi %endif +%if %{have_kvm_setup} +%preun -n qemu-kvm-core +%systemd_preun kvm-setup.service +%endif + %post -n qemu-kvm-common %systemd_post ksm.service %systemd_post ksmtuned.service @@ -2254,63 +2567,361 @@ useradd -r -u 107 -g qemu -G kvm -d / -s /sbin/nologin \ %changelog -* Wed Aug 28 2019 Danilo Cesar Lemes de Paula - 2.12.0-65.el8_0_0.5 -- kvm-i386-Add-new-MSR-indices-for-IA32_PRED_CMD-and-IA32_.patch [bz#1718235] -- kvm-i386-Add-CPUID-bit-and-feature-words-for-IA32_ARCH_C.patch [bz#1718235] -- kvm-x86-Data-structure-changes-to-support-MSR-based-feat.patch [bz#1718235] -- kvm-x86-define-a-new-MSR-based-feature-word-FEATURE_WORD.patch [bz#1718235] -- kvm-Add-support-to-KVM_GET_MSR_FEATURE_INDEX_LIST-an.patch [bz#1718235] -- kvm-Use-KVM_GET_MSR_INDEX_LIST-for-MSR_IA32_ARCH_CAP.patch [bz#1718235] -- kvm-i386-kvm-Disable-arch_capabilities-if-MSR-can-t-be-s.patch [bz#1718235] -- kvm-i386-Make-arch_capabilities-migratable.patch [bz#1718235] -- kvm-target-i386-add-MDS-NO-feature.patch [bz#1718235] -- Resolves: bz#1718235 - ([Intel 8.1 Bug] [KVM][CLX] CPUID_7_0_EDX_ARCH_CAPABILITIES is not enabled in VM - qemu-kvm [rhel-8.0.0.z]) - -* Mon Aug 26 2019 Danilo Cesar Lemes de Paula - 2.12.0-65.el8_0_0.4 -- kvm-Introduce-new-no_guest_reset-parameter-for-usb-host-.patch [bz#1719228] -- kvm-usb-call-reset-handler-before-updating-state.patch [bz#1719228] -- kvm-usb-host-skip-reset-for-untouched-devices.patch [bz#1719228] -- kvm-usb-host-avoid-libusb_set_configuration-calls.patch [bz#1719228] -- kvm-Fix-heap-overflow-in-ip_reass-on-big-packet-input.patch [bz#1734750] -- Resolves: bz#1719228 - (Detached device when trying to upgrade USB device firmware when in doing USB Passthrough via QEMU [rhel-8.0.0.z]) -- Resolves: bz#1734750 - (CVE-2019-14378 qemu-kvm: QEMU: slirp: heap buffer overflow during packet reassembly [rhel-8.0.0.z]) - -* Wed Jul 24 2019 Danilo Cesar Lemes de Paula - 2.12.0-65.el8_0_0.3 -- kvm-slirp-check-sscanf-result-when-emulating-ident.patch [bz#1732324] -- kvm-slirp-fix-big-little-endian-conversion-in-ident-prot.patch [bz#1732324] -- kvm-slirp-ensure-there-is-enough-space-in-mbuf-to-null-t.patch [bz#1732324] -- kvm-slirp-don-t-manipulate-so_rcv-in-tcp_emu.patch [bz#1732324] -- kvm-virtio-scsi-Move-BlockBackend-back-to-the-main-AioCo.patch [bz#1718992] -- kvm-scsi-disk-Acquire-the-AioContext-in-scsi_-_realize.patch [bz#1718992] -- kvm-virtio-scsi-Forbid-devices-with-different-iothreads-.patch [bz#1718992] -- Resolves: bz#1718992 - (qemu-kvm core dumped after hotplug the deleted disk with iothread parameter [rhel-8.0.0.z]) -- Resolves: bz#1732324 - (CVE-2019-6778 qemu-kvm: QEMU: slirp: heap buffer overflow in tcp_emu() [rhel-8.0.0.z]) - -* Sun Jun 30 2019 Danilo de Paula - 15:2.12.0-65.2 +* Fri Sep 13 2019 Danilo Cesar Lemes de Paula - 2.12.0-88.el8 +- Revert fix for bz#1749724 - this got delayed to 8.2 + (CVE-2019-15890 qemu-kvm: QEMU: Slirp: use-after-free during packet reassembly [rhel-8]) + +* Tue Sep 03 2019 Danilo Cesar Lemes de Paula - 2.12.0-86.el8 +- kvm-Do-not-run-iotests-on-brew-build.patch [bz#1742819] +- kvm-target-ppc-spapr-Add-workaround-option-to-SPAPR_CAP_.patch [bz#1744415] +- kvm-target-ppc-spapr-Add-SPAPR_CAP_CCF_ASSIST.patch [bz#1744415] +- kvm-i386-x86_cpu_list_feature_names-function.patch [bz#1747185] +- kvm-i386-unavailable-features-QOM-property.patch [bz#1747185] +- kvm-file-posix-Handle-undetectable-alignment.patch [bz#1738839] +- kvm-iotests-Tweak-221-sizing-for-different-hole-granular.patch [bz#1738839] +- kvm-iotests-Filter-175-s-allocation-information.patch [bz#1738839] +- kvm-block-posix-Always-allocate-the-first-block.patch [bz#1738839] +- kvm-iotests-Test-allocate_first_block-with-O_DIRECT.patch [bz#1738839] +- Resolves: bz#1738839 + (I/O error when virtio-blk disk is backed by a raw image on 4k disk) +- Resolves: bz#1742819 + (Remove iotests from qemu-kvm builds [RHEL 8.1.0]) +- Resolves: bz#1744415 + (Backport support for count cache flush Spectre v2 mitigation [slow train]) +- Resolves: bz#1747185 + ("filtered-features" QOM property is not available) + +* Mon Aug 19 2019 Danilo Cesar Lemes de Paula - 2.12.0-85.el8 +- kvm-console-Avoid-segfault-in-screendump.patch [bz#1684383] +- kvm-usb-hub-clear-suspend-on-detach.patch [bz#1619661] +- kvm-qemu-img-fix-regression-copying-secrets-during-conve.patch [bz#1727821] +- Resolves: bz#1619661 + (the attach hub on one hub still exits in device manager after unhotplug) +- Resolves: bz#1684383 + (qemu crashed when take screenshot for 2nd head of virtio video device if the display not opened by virt-viewer) +- Resolves: bz#1727821 + (Failed to convert a source image to the qcow2 image encrypted by luks) + +* Fri Aug 16 2019 Danilo Cesar Lemes de Paula - 2.12.0-84.el8 +- kvm-vnc-detect-and-optimize-pageflips.patch [bz#1727033] +- kvm-block-backend-Make-blk_inc-dec_in_flight-public.patch [bz#1716349] +- kvm-virtio-blk-Increase-in_flight-for-request-restart-BH.patch [bz#1716349] +- kvm-block-Fix-AioContext-switch-for-drained-node.patch [bz#1716349] +- kvm-test-bdrv-drain-AioContext-switch-in-drained-section.patch [bz#1716349] +- kvm-block-Use-normal-drain-for-bdrv_set_aio_context.patch [bz#1716349] +- kvm-block-Fix-AioContext-switch-for-bs-drv-NULL.patch [bz#1716347] +- kvm-iothread-fix-crash-with-invalid-properties.patch [bz#1687541] +- kvm-iothread-replace-init_done_cond-with-a-semaphore.patch [bz#1687541] +- kvm-RHEL-disable-hostmem-memfd.patch [bz#1740797] +- Resolves: bz#1687541 + (qemu aborted when start guest with a big iothreads) +- Resolves: bz#1716347 + (Qemu Core dump when quit vm that's in status "paused(io-error)" with data plane enabled) +- Resolves: bz#1716349 + (qemu with iothreads enabled crashes on resume after enospc pause for disk extension) +- Resolves: bz#1727033 + (vnc server should detect page-flips and avoid sending fullscreen updates then.) +- Resolves: bz#1740797 + (Disable memfd in QEMU) + +* Thu Aug 01 2019 Danilo Cesar Lemes de Paula - 2.12.0-83.el8 +- kvm-hw-block-pflash_cfi01-Add-missing-DeviceReset-handle.patch [bz#1707192] +- kvm-block-file-posix-Unaligned-O_DIRECT-block-status.patch [bz#1678979] +- kvm-iotests-Test-unaligned-raw-images-with-O_DIRECT.patch [bz#1678979] +- kvm-nbd-client-Lower-min_block-for-block-status-unaligne.patch [bz#1678979] +- kvm-nbd-client-Reject-inaccessible-tail-of-inconsistent-.patch [bz#1678979] +- kvm-nbd-client-Support-qemu-img-convert-from-unaligned-s.patch [bz#1678979] +- kvm-block-Add-bdrv_get_request_alignment.patch [bz#1678979] +- kvm-nbd-server-Advertise-actual-minimum-block-size.patch [bz#1678979] +- kvm-slirp-check-sscanf-result-when-emulating-ident.patch [bz#1727642] +- kvm-slirp-fix-big-little-endian-conversion-in-ident-prot.patch [bz#1727642] +- kvm-slirp-ensure-there-is-enough-space-in-mbuf-to-null-t.patch [bz#1727642] +- kvm-slirp-don-t-manipulate-so_rcv-in-tcp_emu.patch [bz#1727642] +- kvm-tap-set-vhostfd-passed-from-qemu-cli-to-non-blocking.patch [bz#1732642] +- kvm-Fix-heap-overflow-in-ip_reass-on-big-packet-input.patch [bz#1734751] +- Resolves: bz#1678979 + (qemu-img convert abort when converting image with unaligned size (qemu-img: block/io.c:2134: bdrv_co_block_status: Assertion `*pnum && (((*pnum) % (align)) == 0) && align > offset - aligned_offset\' failed)) +- Resolves: bz#1707192 + (implement missing reset handler for cfi.pflash01 - slow train) +- Resolves: bz#1727642 + (CVE-2019-6778 qemu-kvm: QEMU: slirp: heap buffer overflow in tcp_emu()) +- Resolves: bz#1732642 + (enable the virtio-net frontend to work with the vhost-net backend in SEV guests) +- Resolves: bz#1734751 + (CVE-2019-14378 qemu-kvm: QEMU: slirp: heap buffer overflow during packet reassembly [rhel-8.1.0]) + +* Tue Jul 23 2019 Danilo Cesar Lemes de Paula - 2.12.0-82.el8 +- kvm-i386-Add-new-model-of-Cascadelake-Server.patch [bz#1629906] +- kvm-i386-Update-stepping-of-Cascadelake-Server.patch [bz#1629906] +- kvm-target-i386-Disable-MPX-support-on-named-CPU-models.patch [bz#1629906] +- kvm-i386-remove-the-INTEL_PT-CPUID-bit-from-named-CPU-NEW.patch [bz#1629906] +- kvm-i386-Disable-OSPKE-on-CPU-model-definitions-NEW.patch [bz#1629906] +- kvm-block-ssh-Convert-from-DPRINTF-macro-to-trace-events.patch [bz#1513367] +- kvm-block-ssh-Do-not-report-read-write-flush-errors-to-t.patch [bz#1513367] +- kvm-qemu-iotests-Fix-paths-for-NFS.patch [bz#1513367] +- kvm-qemu-iotests-Filter-NFS-paths.patch [bz#1513367] +- kvm-iotests-Filter-SSH-paths.patch [bz#1513367] +- kvm-block-ssh-Implement-.bdrv_refresh_filename.patch [bz#1513367] +- kvm-iotests-Use-Python-byte-strings-where-appropriate.patch [bz#1513367] +- kvm-iotests-Unify-log-outputs-between-Python-2-and-3.patch [bz#1513367] +- kvm-ssh-switch-from-libssh2-to-libssh.patch [bz#1513367] +- kvm-redhat-switch-from-libssh2-to-libssh.patch [bz#1513367] +- kvm-block-gluster-limit-the-transfer-size-to-512-MiB.patch [bz#1728657] +- kvm-s390-cpumodel-fix-description-for-the-new-vector-fac.patch [bz#1729975] +- kvm-s390x-cpumodel-remove-esort-from-the-default-model.patch [bz#1729975] +- kvm-s390x-cpumodel-also-change-name-of-vxbeh.patch [bz#1729975] +- kvm-s390x-cpumodel-change-internal-name-of-vxpdeh-to-mat.patch [bz#1729975] +- kvm-target-i386-sev-Do-not-unpin-ram-device-memory-regio.patch [bz#1728958] +- kvm-i386-Save-EFER-for-32-bit-targets.patch [bz#1689269] +- kvm-target-i386-rename-HF_SVMI_MASK-to-HF_GUEST_MASK.patch [bz#1689269] +- kvm-target-i386-kvm-add-VMX-migration-blocker.patch [bz#1689269] +- kvm-target-i386-kvm-just-return-after-migrate_add_blocke.patch [bz#1689269] +- kvm-target-i386-kvm-Delete-VMX-migration-blocker-on-vCPU.patch [bz#1689269] +- kvm-Introduce-kvm_arch_destroy_vcpu.patch [bz#1689269] +- kvm-target-i386-kvm-Use-symbolic-constant-for-DB-BP-exce.patch [bz#1689269] +- kvm-target-i386-kvm-Re-inject-DB-to-guest-with-updated-D.patch [bz#1689269] +- kvm-target-i386-kvm-Block-migration-for-vCPUs-exposed-wi.patch [bz#1689269] +- kvm-target-i386-kvm-do-not-initialize-padding-fields.patch [bz#1689269] +- kvm-linux-headers-synchronize-generic-and-x86-KVM-header.patch [bz#1689269] +- kvm-vmstate-Add-support-for-kernel-integer-types.patch [bz#1689269] +- kvm-target-i386-kvm-Add-support-for-save-and-restore-nes.patch [bz#1689269] +- kvm-target-i386-kvm-Add-support-for-KVM_CAP_EXCEPTION_PA.patch [bz#1689269] +- kvm-target-i386-kvm-Add-nested-migration-blocker-only-wh.patch [bz#1689269] +- kvm-target-i386-kvm-Demand-nested-migration-kernel-capab.patch [bz#1689269] +- kvm-target-i386-skip-KVM_GET-SET_NESTED_STATE-if-VMX-dis.patch [bz#1689269] +- kvm-i386-kvm-Do-not-sync-nested-state-during-runtime.patch [bz#1689269] +- Resolves: bz#1513367 + (qemu with libssh) +- Resolves: bz#1629906 + ([Intel 8.1 Feat] qemu-kvm Introduce Cascade Lake (CLX) cpu model) +- Resolves: bz#1689269 + (Nested KVM: support for migration of nested hypervisors - Slow Train) +- Resolves: bz#1728657 + ('qemu-io write' to a raw image over libgfapi fails) +- Resolves: bz#1728958 + (Hot unplug vfio-pci NIC devices from sev guest will cause qemu-kvm: sev_ram_block_removed: failed to unregister region) +- Resolves: bz#1729975 + (RHEL 8.1 Pre-Beta - Fix for hardware CPU Model) + +* Mon Jul 08 2019 Miroslav Rezanina - 2.12.0-81.el8 +- kvm-target-i386-add-MDS-NO-feature.patch [bz#1714792] +- kvm-virtio-gpu-pass-down-VirtIOGPU-pointer-to-a-bunch-of.patch [bz#1531543] +- kvm-virtio-gpu-add-iommu-support.patch [bz#1531543] +- kvm-virtio-gpu-fix-unmap-in-error-path.patch [bz#1531543] +- Resolves: bz#1531543 + ([RFE] add iommu support to virtio-gpu) +- Resolves: bz#1714792 + ([Intel 8.1 FEAT] MDS_NO exposure to guest) + +* Tue Jul 02 2019 Danilo Cesar Lemes de Paula - 2.12.0-80.el8 +- kvm-qxl-check-release-info-object.patch [bz#1712705] +- kvm-iotests-Make-182-do-without-device_add.patch [bz#1707598] +- Resolves: bz#1707598 + (qemu-iotest 182 fails without device hotplugging support) +- Resolves: bz#1712705 + (CVE-2019-12155 qemu-kvm: QEMU: qxl: null pointer dereference while releasing spice resources [rhel-8]) + +* Fri Jun 28 2019 Danilo de Paula - 15:2.12.0-79 - Rebuild all virt packages to fix RHEL's upgrade path -- Resolves: rhbz#1696354 - (Ensure modular RPM upgrade path [ZStream Clone] [rhel-8.0.0.z]) - -* Fri May 10 2019 Danilo Cesar Lemes de Paula - 2.12.0-64.el8.0.0.2 -- Bump release version to fix the versioning problem (zstream release lower than ystream). -- Resolves: bz#1704545 - (CVE-2018-12126 virt:rhel/qemu-kvm: hardware: Microarchitectural Store Buffer Data Sampling [rhel-8.0.0.z]) - -* Fri May 03 2019 Danilo Cesar Lemes de Paula - 2.12.0-63.el8.0.0.2 -- kvm-target-i386-define-md-clear-bit-rhev.patch [bz#1704545] -- Resolves: bz#1704545 - (CVE-2018-12126 virt:rhel/qemu-kvm: hardware: Microarchitectural Store Buffer Data Sampling [rhel-8.0.0.z]) - -* Mon Apr 22 2019 Danilo Cesar Lemes de Paula - 2.12.0-63.el8_0.1 +- Resolves: rhbz#1695587 + (Ensure modular RPM upgrade path) + +* Thu Jun 20 2019 Miroslav Rezanina - 2.12.0-78.el8 +- kvm-gluster-Handle-changed-glfs_ftruncate-signature.patch [bz#1721983] +- kvm-gluster-the-glfs_io_cbk-callback-function-pointer-ad.patch [bz#1721983] +- Resolves: bz#1721983 + (qemu-kvm can't be build with new gluster version (6.0.6)) + +* Thu Jun 13 2019 Danilo Cesar Lemes de Paula - 2.12.0-77.el8 +- kvm-i386-Make-arch_capabilities-migratable.patch [bz#1709970] +- kvm-spapr-Fix-ibm-max-associativity-domains-property-num.patch [bz#1710662] +- kvm-linux-headers-Update-for-NVLink2-passthrough-downstr.patch [bz#1710662] +- kvm-pci-Move-NVIDIA-vendor-id-to-the-rest-of-ids.patch [bz#1710662] +- kvm-vfio-quirks-Add-common-quirk-alloc-helper.patch [bz#1710662] +- kvm-vfio-Make-vfio_get_region_info_cap-public.patch [bz#1710662] +- kvm-spapr-Support-NVIDIA-V100-GPU-with-NVLink2.patch [bz#1710662] +- kvm-qemu-kvm.spec-bump-libseccomp-2.4.0.patch [bz#1719578] +- Resolves: bz#1709970 + ([Intel 8.1 Bug] [KVM][CLX] CPUID_7_0_EDX_ARCH_CAPABILITIES is not enabled in VM - qemu-kvm) +- Resolves: bz#1710662 + ([IBM 8.1 FEAT] POWER9 - Virt: qemu: NVLink2 passthru to guest - Nvidia Volta (GPU) (kvm)) +- Resolves: bz#1719578 + (VM failed to start with error "failed to install seccomp syscall filter in the kernel") + +* Tue Jun 11 2019 Danilo Cesar Lemes de Paula - 2.12.0-76.el8 +- kvm-Introduce-new-no_guest_reset-parameter-for-usb-host-.patch [bz#1713677] +- kvm-usb-call-reset-handler-before-updating-state.patch [bz#1713677] +- kvm-usb-host-skip-reset-for-untouched-devices.patch [bz#1713677] +- kvm-usb-host-avoid-libusb_set_configuration-calls.patch [bz#1713677] +- kvm-virtio-scsi-Move-BlockBackend-back-to-the-main-AioCo.patch [bz#1673396 bz#1673401] +- kvm-scsi-disk-Acquire-the-AioContext-in-scsi_-_realize.patch [bz#1673396 bz#1673401] +- kvm-virtio-scsi-Forbid-devices-with-different-iothreads-.patch [bz#1673396 bz#1673401] +- kvm-Disable-VXHS-support.patch [bz#1714933] +- Resolves: bz#1673396 + (qemu-kvm core dumped after hotplug the deleted disk with iothread parameter) +- Resolves: bz#1673401 + (Qemu core dump when start guest with two disks using same drive) +- Resolves: bz#1713677 + (Detached device when trying to upgrade USB device firmware when in doing USB Passthrough via QEMU) +- Resolves: bz#1714933 + (Disable VXHS in qemu-kvm) + +* Fri May 24 2019 Danilo Cesar Lemes de Paula - 2.12.0-75.el8 +- kvm-s390x-cpumodel-enum-type-S390FeatGroup-now-gets-gene.patch [bz#1660912] +- kvm-linux-headers-update-against-Linux-5.2-rc1.patch [bz#1660912] +- kvm-s390x-cpumodel-ignore-csske-for-expansion.patch [bz#1660912] +- kvm-s390x-cpumodel-Miscellaneous-Instruction-Extensions-.patch [bz#1660912] +- kvm-s390x-cpumodel-msa9-facility.patch [bz#1660912] +- kvm-s390x-cpumodel-vector-enhancements.patch [bz#1660912] +- kvm-s390x-cpumodel-enhanced-sort-facility.patch [bz#1660912] +- kvm-s390x-cpumodel-add-Deflate-conversion-facility.patch [bz#1660912] +- kvm-s390x-cpumodel-add-gen15-defintions.patch [bz#1660912] +- kvm-s390x-cpumodel-wire-up-8561-and-8562-as-gen15-machin.patch [bz#1660912] +- kvm-spice-set-device-address-and-device-display-ID-in-QX.patch [bz#1712946] +- kvm-hw-pci-Add-missing-include.patch [bz#1712946] +- Resolves: bz#1660912 + ([IBM 8.1 FEAT] KVM s390x: Add hardware CPU Model - qemu part) +- Resolves: bz#1712946 + (qemu-kvm build is broken due to spice_qxl_set_max_monitors being deprecated) + +* Mon May 20 2019 Danilo Cesar Lemes de Paula - 2.12.0-74.el8 +- kvm-x86-cpu-Enable-CLDEMOTE-Demote-Cache-Line-cpu-featur.patch [bz#1696436] +- kvm-memory-Fix-the-memory-region-type-assignment-order.patch [bz#1667249] +- kvm-target-i386-sev-Do-not-pin-the-ram-device-memory-reg.patch [bz#1667249] +- kvm-block-Fix-invalidate_cache-error-path-for-parent-act.patch [bz#1673010] +- kvm-target-i386-define-md-clear-bit.patch [bz#1703302 bz#1703308] +- Resolves: bz#1667249 + (Fail to launch AMD SEV VM with assigned PCI device) +- Resolves: bz#1673010 + (Local VM and migrated VM on the same host can run with same RAW file as visual disk source while without shareable configured or lock manager enabled) +- Resolves: bz#1696436 + ([Intel 8.0 Feat] KVM Enabling SnowRidge new NIs - qemu-kvm) +- Resolves: bz#1703302 + (CVE-2018-12130 virt:rhel/qemu-kvm: hardware: Microarchitectural Fill Buffer Data Sampling (MFBDS) [rhel-8]) +- Resolves: bz#1703308 + (CVE-2018-12127 virt:rhel/qemu-kvm: hardware: Micro-architectural Load Port Data Sampling - Information Leak (MLPDS) [rhel-8]) + +* Tue May 14 2019 Danilo Cesar Lemes de Paula - 2.12.0-73.el8 +- kvm-i386-remove-the-INTEL_PT-CPUID-bit-from-named-CPU-mo.patch [bz#1561761] +- kvm-i386-Disable-OSPKE-on-CPU-model-definitions.patch [bz#1561761] +- Resolves: bz#1561761 + ([Intel 8.1 Feat] qemu-kvm Introduce Icelake cpu model) + +* Tue May 14 2019 Danilo Cesar Lemes de Paula - 2.12.0-72.el8 +- kvm-Use-KVM_GET_MSR_INDEX_LIST-for-MSR_IA32_ARCH_CAP.patch [bz#1707706] +- kvm-i386-kvm-Disable-arch_capabilities-if-MSR-can-t-be-s.patch [bz#1707706] +- Resolves: bz#1707706 + (/builddir/build/BUILD/qemu-2.12.0/target/i386/kvm.c:2031: kvm_put_msrs: Assertion `ret == cpu->kvm_msr_buf->nmsrs' failed.) + +* Wed May 08 2019 Danilo Cesar Lemes de Paula - 2.12.0-71.el8 +- kvm-s390-bios-Skip-bootmap-signature-entries.patch [bz#1683275] +- Resolves: bz#1683275 + ([IBM 8.1 FEAT] KVM: Secure Linux Boot Toleration (qemu)) + +* Tue May 07 2019 Danilo Cesar Lemes de Paula - 2.12.0-70.el8 +- kvm-i386-Add-new-MSR-indices-for-IA32_PRED_CMD-and-IA32_.patch [bz#1561761] +- kvm-i386-Add-CPUID-bit-and-feature-words-for-IA32_ARCH_C.patch [bz#1561761] +- kvm-i386-Add-CPUID-bit-for-PCONFIG.patch [bz#1561761] +- kvm-i386-Add-CPUID-bit-for-WBNOINVD.patch [bz#1561761] +- kvm-i386-Add-new-CPU-model-Icelake-Server-Client.patch [bz#1561761] +- kvm-Add-support-to-KVM_GET_MSR_FEATURE_INDEX_LIST-an.patch [bz#1561761] +- kvm-x86-Data-structure-changes-to-support-MSR-based-feat.patch [bz#1561761] +- kvm-x86-define-a-new-MSR-based-feature-word-FEATURE_WORD.patch [bz#1561761] +- kvm-i386-remove-the-new-CPUID-PCONFIG-from-Icelake-Serve.patch [bz#1561761] +- kvm-Revert-i386-Add-CPUID-bit-for-PCONFIG.patch [bz#1561761] +- Resolves: bz#1561761 + ([Intel 8.1 Feat] qemu-kvm Introduce Icelake cpu model) + +* Fri May 03 2019 Danilo Cesar Lemes de Paula - 2.12.0-69.el8 +- kvm-tests-crypto-Use-the-IEC-binary-prefix-definitions.patch [bz#1680231] +- kvm-crypto-expand-algorithm-coverage-for-cipher-benchmar.patch [bz#1680231] +- kvm-crypto-remove-code-duplication-in-tweak-encrypt-decr.patch [bz#1680231] +- kvm-crypto-introduce-a-xts_uint128-data-type.patch [bz#1680231] +- kvm-crypto-convert-xts_tweak_encdec-to-use-xts_uint128-t.patch [bz#1680231] +- kvm-crypto-convert-xts_mult_x-to-use-xts_uint128-type.patch [bz#1680231] +- kvm-crypto-annotate-xts_tweak_encdec-as-inlineable.patch [bz#1680231] +- kvm-crypto-refactor-XTS-cipher-mode-test-suite.patch [bz#1680231] +- kvm-crypto-add-testing-for-unaligned-buffers-with-XTS-ci.patch [bz#1680231] +- Resolves: bz#1680231 + (severe performance impact using luks format) + +* Mon Apr 29 2019 Danilo Cesar Lemes de Paula - 2.12.0-68.el8 +- kvm-s390x-ipl-Try-to-detect-Linux-vs-non-Linux-for-initi.patch [bz#1699070] +- kvm-loader-Check-access-size-when-calling-rom_ptr-to-avo.patch [bz#1699070] +- kvm-hw-s390x-Use-the-IEC-binary-prefix-definitions.patch [bz#1699070] +- kvm-s390x-storage-attributes-fix-CMMA_BLOCK_SIZE-usage.patch [bz#1699070] +- kvm-s390x-cpumodel-fix-segmentation-fault-when-baselinin.patch [bz#1699070] +- kvm-hw-s390x-s390-pci-bus-Convert-sysbus-init-function-t.patch [bz#1699070] +- kvm-s390x-pci-properly-fail-if-the-zPCI-device-cannot-be.patch [bz#1699070] +- kvm-s390x-pci-rename-hotplug-handler-callbacks.patch [bz#1699070] +- kvm-s390-avoid-potential-null-dereference-in-s390_pcihos.patch [bz#1699070] +- kvm-s390x-pci-Send-correct-event-on-hotplug.patch [bz#1699070] +- kvm-s390x-pci-Set-the-iommu-region-size-mpcifc-request.patch [bz#1699070] +- kvm-s390x-pci-Always-delete-and-free-the-release_timer.patch [bz#1699070] +- kvm-s390x-pci-Ignore-the-unplug-call-if-we-already-have-.patch [bz#1699070] +- kvm-s390x-pci-Use-hotplug_dev-instead-of-looking-up-the-.patch [bz#1699070] +- kvm-s390x-pci-Move-some-hotplug-checks-to-the-pre_plug-h.patch [bz#1699070] +- kvm-s390x-pci-Introduce-unplug-requests-and-split-unplug.patch [bz#1699070] +- kvm-s390x-pci-Drop-release-timer-and-replace-it-with-a-f.patch [bz#1699070] +- kvm-s390x-pci-mark-zpci-devices-as-unmigratable.patch [bz#1699070] +- kvm-s390x-pci-Fix-primary-bus-number-for-PCI-bridges.patch [bz#1699070] +- kvm-s390x-pci-Fix-hotplugging-of-PCI-bridges.patch [bz#1699070] +- kvm-s390x-pci-Warn-when-adding-PCI-devices-without-the-z.patch [bz#1699070] +- kvm-s390x-pci-Unplug-remaining-requested-devices-on-pcih.patch [bz#1699070] +- kvm-s390x-refactor-reset-reipl-handling.patch [bz#1699070] +- kvm-s390-ipl-fix-ipl-with-no-reboot.patch [bz#1699070] +- Resolves: bz#1699070 + (Backport s390x-related fixes for qemu-kvm) + +* Tue Apr 23 2019 Danilo Cesar Lemes de Paula - 2.12.0-67.el8 - kvm-device_tree-Fix-integer-overflowing-in-load_device_t.patch [bz#1693116] - Resolves: bz#1693116 (CVE-2018-20815 qemu-kvm: QEMU: device_tree: heap buffer overflow while loading device tree blob [rhel-8.0]) +* Mon Apr 15 2019 Danilo Cesar Lemes de Paula - 2.12.0-66.el8 +- kvm-iotests-153-Fix-dead-code.patch [bz#1694148] +- kvm-file-posix-Include-filename-in-locking-error-message.patch [bz#1694148] +- kvm-file-posix-Skip-effectiveless-OFD-lock-operations.patch [bz#1694148] +- kvm-file-posix-Drop-s-lock_fd.patch [bz#1694148] +- kvm-tests-Add-unit-tests-for-image-locking.patch [bz#1694148] +- kvm-file-posix-Fix-shared-locks-on-reopen-commit.patch [bz#1694148] +- kvm-iotests-Test-file-posix-locking-and-reopen.patch [bz#1694148] +- kvm-block-file-posix-do-not-fail-on-unlock-bytes.patch [bz#1694148] +- kvm-hostmem-file-remove-object-id-from-pmem-error-messag.patch [bz#1687596] +- kvm-redhat-setting-target-release-to-rhel-8.1.0.patch [] +- kvm-redhat-removing-iotest-182.patch [] +- Resolves: bz#1687596 + ([Intel 8.1 BUG][KVM][Crystal Ridge]object_get_canonical_path_component: assertion failed: (obj->parent != NULL)) +- Resolves: bz#1694148 + (QEMU image locking needn't double open fd number, and it should not fail when attempting to release locks) + +* Tue Apr 09 2019 Danilo Cesar Lemes de Paula - 2.12.0-65.el8 +- kvm-s390x-cpumodel-mepochptff-warn-when-no-mepoch-and-re.patch [bz#1664371] +- kvm-s390x-cpumodel-add-z14-GA2-model.patch [bz#1664371] +- kvm-redhat-s390x-cpumodel-enable-mepoch-by-default-for-z.patch [bz#1664371] +- kvm-intel_iommu-fix-operator-in-vtd_switch_address_space.patch [bz#1662272] +- kvm-intel_iommu-reset-intr_enabled-when-system-reset.patch [bz#1662272] +- kvm-pci-msi-export-msi_is_masked.patch [bz#1662272] +- kvm-i386-kvm-ignore-masked-irqs-when-update-msi-routes.patch [bz#1662272] +- Resolves: bz#1662272 + (Boot guest with device assignment+vIOMMU, qemu prompts "vtd_interrupt_remap_msi: MSI address low 32 bit invalid: 0x0" when first rebooting guest) +- Resolves: bz#1664371 + ([IBM 8.1 FEAT] Update hardware CPU Model z14 (kvm) - qemu part) + +* Mon Apr 08 2019 Danilo Cesar Lemes de Paula - 2.12.0-64.el8 +- kvm-doc-fix-the-configuration-path.patch [bz#1645411] +- kvm-Increase-number-of-iotests-being-run-as-a-part-of-RH.patch [bz#1664463] +- kvm-Load-kvm-module-during-boot.patch [bz#1676907 bz#1685995] +- kvm-qemu-kvm.spec.template-Update-pyton-path-to-system-i.patch [] +- Resolves: bz#1645411 + (the "fsfreeze-hook" script path shown by command "qemu-ga --help" or "man qemu-ga" is wrong) +- Resolves: bz#1664463 + (Modify iotest behavior to include luks and nbd and fail build if iotests fail) +- Resolves: bz#1676907 + (/dev/kvm device exists but kernel module is not loaded on boot up causing VM start to fail in libvirt) +- Resolves: bz#1685995 + (/dev/kvm device exists but kernel module is not loaded on boot up causing VM start to fail in libvirt) + * Tue Feb 26 2019 Danilo Cesar Lemes de Paula - 2.12.0-63.el8 - kvm-scsi-generic-avoid-possible-out-of-bounds-access-to-.patch [bz#1668162] - Resolves: bz#1668162