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 new file mode 100644 index 0000000..d3e7931 --- /dev/null +++ b/SOURCES/kvm-Add-support-to-KVM_GET_MSR_FEATURE_INDEX_LIST-an.patch @@ -0,0 +1,160 @@ +From 90b8d9d17a9c252427df71fbe5bd76f897529e71 Mon Sep 17 00:00:00 2001 +From: "plai@redhat.com" +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: <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: Igor Mammedov +RH-Acked-by: Michael S. Tsirkin + +From: Robert Hoo + +Add kvm_get_supported_feature_msrs() to get supported MSR feature index list. +Add kvm_arch_get_supported_msr_feature() to get each MSR features value. + +Signed-off-by: Robert Hoo +Message-Id: <1539578845-37944-2-git-send-email-robert.hu@linux.intel.com> +Reviewed-by: Eduardo Habkost +Signed-off-by: Eduardo Habkost +(cherry picked from commit f57bceb6ab5163ddd6c41ff4344ab8cf28a9c63d) +Signed-off-by: Paul Lai +Signed-off-by: Danilo C. L. de Paula +--- + include/sysemu/kvm.h | 2 ++ + target/i386/kvm.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 82 insertions(+) + +diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h +index 23669c4..3d8f294 100644 +--- a/include/sysemu/kvm.h ++++ b/include/sysemu/kvm.h +@@ -464,6 +464,8 @@ int kvm_vm_check_extension(KVMState *s, unsigned int extension); + + uint32_t kvm_arch_get_supported_cpuid(KVMState *env, uint32_t function, + uint32_t index, int reg); ++uint32_t kvm_arch_get_supported_msr_feature(KVMState *s, uint32_t index); ++ + + void kvm_set_sigmask_len(KVMState *s, unsigned int sigmask_len); + +diff --git a/target/i386/kvm.c b/target/i386/kvm.c +index 702e3bf..096ed24 100644 +--- a/target/i386/kvm.c ++++ b/target/i386/kvm.c +@@ -106,6 +106,7 @@ static int has_pit_state2; + static bool has_msr_mcg_ext_ctl; + + static struct kvm_cpuid2 *cpuid_cache; ++static struct kvm_msr_list *kvm_feature_msrs; + + int kvm_has_pit_state2(void) + { +@@ -405,6 +406,42 @@ uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function, + return ret; + } + ++uint32_t kvm_arch_get_supported_msr_feature(KVMState *s, uint32_t index) ++{ ++ struct { ++ struct kvm_msrs info; ++ struct kvm_msr_entry entries[1]; ++ } msr_data; ++ uint32_t ret; ++ ++ if (kvm_feature_msrs == NULL) { /* Host doesn't support feature MSRs */ ++ return 0; ++ } ++ ++ /* Check if requested MSR is supported feature MSR */ ++ int i; ++ for (i = 0; i < kvm_feature_msrs->nmsrs; i++) ++ if (kvm_feature_msrs->indices[i] == index) { ++ break; ++ } ++ if (i == kvm_feature_msrs->nmsrs) { ++ return 0; /* if the feature MSR is not supported, simply return 0 */ ++ } ++ ++ msr_data.info.nmsrs = 1; ++ msr_data.entries[0].index = index; ++ ++ ret = kvm_ioctl(s, KVM_GET_MSRS, &msr_data); ++ if (ret != 1) { ++ error_report("KVM get MSR (index=0x%x) feature failed, %s", ++ index, strerror(-ret)); ++ exit(1); ++ } ++ ++ return msr_data.entries[0].data; ++} ++ ++ + typedef struct HWPoisonPage { + ram_addr_t ram_addr; + QLIST_ENTRY(HWPoisonPage) list; +@@ -1164,6 +1201,47 @@ void kvm_arch_do_init_vcpu(X86CPU *cpu) + } + } + ++static int kvm_get_supported_feature_msrs(KVMState *s) ++{ ++ int ret = 0; ++ ++ if (kvm_feature_msrs != NULL) { ++ return 0; ++ } ++ ++ if (!kvm_check_extension(s, KVM_CAP_GET_MSR_FEATURES)) { ++ return 0; ++ } ++ ++ struct kvm_msr_list msr_list; ++ ++ msr_list.nmsrs = 0; ++ ret = kvm_ioctl(s, KVM_GET_MSR_FEATURE_INDEX_LIST, &msr_list); ++ if (ret < 0 && ret != -E2BIG) { ++ error_report("Fetch KVM feature MSR list failed: %s", ++ strerror(-ret)); ++ return ret; ++ } ++ ++ assert(msr_list.nmsrs > 0); ++ kvm_feature_msrs = (struct kvm_msr_list *) \ ++ g_malloc0(sizeof(msr_list) + ++ msr_list.nmsrs * sizeof(msr_list.indices[0])); ++ ++ kvm_feature_msrs->nmsrs = msr_list.nmsrs; ++ ret = kvm_ioctl(s, KVM_GET_MSR_FEATURE_INDEX_LIST, kvm_feature_msrs); ++ ++ if (ret < 0) { ++ error_report("Fetch KVM feature MSR list failed: %s", ++ strerror(-ret)); ++ g_free(kvm_feature_msrs); ++ kvm_feature_msrs = NULL; ++ return ret; ++ } ++ ++ return 0; ++} ++ + static int kvm_get_supported_msrs(KVMState *s) + { + static int kvm_supported_msrs; +@@ -1320,6 +1398,8 @@ int kvm_arch_init(MachineState *ms, KVMState *s) + return ret; + } + ++ kvm_get_supported_feature_msrs(s); ++ + uname(&utsname); + lm_capable_kernel = strcmp(utsname.machine, "x86_64") == 0; + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-Disable-CONFIG_I2C-and-CONFIG_IOH3420.patch b/SOURCES/kvm-Disable-CONFIG_I2C-and-CONFIG_IOH3420.patch new file mode 100644 index 0000000..a20255a --- /dev/null +++ b/SOURCES/kvm-Disable-CONFIG_I2C-and-CONFIG_IOH3420.patch @@ -0,0 +1,44 @@ +From 23400c3067fab729fd0584e16f6fa84e1bb3c4f8 Mon Sep 17 00:00:00 2001 +From: Auger Eric +Date: Fri, 20 Sep 2019 17:25:08 +0100 +Subject: [PATCH 02/21] Disable CONFIG_I2C and CONFIG_IOH3420 + +RH-Author: Auger Eric +Message-id: <20190920172508.16323-1-eric.auger@redhat.com> +Patchwork-id: 90825 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH] Disable CONFIG_I2C and CONFIG_IOH3420 +Bugzilla: 1693140 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Thomas Huth +RH-Acked-by: Andrew Jones + +BZ: https://bugzilla.redhat.com/show_bug.cgi?id=1693140 +Branch: rhel-8.2.0 +Upstream: Downstream only +Brew: https://brewweb.engineering.redhat.com/brew/taskinfo?taskID=23613661 + +Remove the I2C config which is of no use on aarch64. Also remove the +IOH3420 to be consistent with AV content (See BZ 1627283). + +Signed-off-by: Eric Auger +Signed-off-by: Danilo C. L. de Paula +--- + default-configs/aarch64-softmmu.mak | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/default-configs/aarch64-softmmu.mak b/default-configs/aarch64-softmmu.mak +index 860140e..d718243 100644 +--- a/default-configs/aarch64-softmmu.mak ++++ b/default-configs/aarch64-softmmu.mak +@@ -23,8 +23,6 @@ CONFIG_GPIO_KEY=y + CONFIG_ARM_V7M=y + CONFIG_PCIE_PORT=y + CONFIG_XIO3130=y +-CONFIG_IOH3420=y + CONFIG_USB_XHCI=y + CONFIG_USB=y +-CONFIG_I2C=y + CONFIG_FW_CFG_DMA=y +-- +1.8.3.1 + diff --git a/SOURCES/kvm-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 new file mode 100644 index 0000000..bb26025 --- /dev/null +++ b/SOURCES/kvm-Fix-heap-overflow-in-ip_reass-on-big-packet-input.patch @@ -0,0 +1,56 @@ +From 486e74dd9b8515f478698fee494086b339015d51 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Wed, 31 Jul 2019 18:45:29 +0100 +Subject: [PATCH 14/14] Fix heap overflow in ip_reass on big packet input +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Philippe Mathieu-Daudé +Message-id: <20190731184529.21905-2-philmd@redhat.com> +Patchwork-id: 89820 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 1/1] Fix heap overflow in ip_reass on big packet input +Bugzilla: 1734751 +RH-Acked-by: Marc-André Lureau +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Thomas Huth + +From: Samuel Thibault + +When the first fragment does not fit in the preallocated buffer, q will +already be pointing to the ext buffer, so we mustn't try to update it. + +Signed-off-by: Samuel Thibault +(cherry picked from libslirp commit 126c04acbabd7ad32c2b018fe10dfac2a3bc1210) +Signed-off-by: Philippe Mathieu-Daudé + +Signed-off-by: Danilo C. L. de Paula +--- + slirp/ip_input.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/slirp/ip_input.c b/slirp/ip_input.c +index 348e1dc..07d8808 100644 +--- a/slirp/ip_input.c ++++ b/slirp/ip_input.c +@@ -334,6 +334,8 @@ insert: + q = fp->frag_link.next; + m = dtom(slirp, q); + ++ int was_ext = m->m_flags & M_EXT; ++ + q = (struct ipasfrag *) q->ipf_next; + while (q != (struct ipasfrag*)&fp->frag_link) { + struct mbuf *t = dtom(slirp, q); +@@ -356,7 +358,7 @@ insert: + * the old buffer (in the mbuf), so we must point ip + * into the new buffer. + */ +- if (m->m_flags & M_EXT) { ++ if (!was_ext && m->m_flags & M_EXT) { + int delta = (char *)q - m->m_dat; + q = (struct ipasfrag *)(m->m_ext + delta); + } +-- +1.8.3.1 + diff --git a/SOURCES/kvm-Introduce-kvm_arch_destroy_vcpu.patch b/SOURCES/kvm-Introduce-kvm_arch_destroy_vcpu.patch new file mode 100644 index 0000000..606b719 --- /dev/null +++ b/SOURCES/kvm-Introduce-kvm_arch_destroy_vcpu.patch @@ -0,0 +1,182 @@ +From e7dc49f6bf6fd242b5b7a83bc270664a1ca45879 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Mon, 22 Jul 2019 18:22:08 +0100 +Subject: [PATCH 27/39] KVM: Introduce kvm_arch_destroy_vcpu() + +RH-Author: Paolo Bonzini +Message-id: <20190722182220.19374-7-pbonzini@redhat.com> +Patchwork-id: 89623 +O-Subject: [RHEL-8.1.0 PATCH qemu-kvm v3 06/18] KVM: Introduce kvm_arch_destroy_vcpu() +Bugzilla: 1689269 +RH-Acked-by: Peter Xu +RH-Acked-by: Laurent Vivier +RH-Acked-by: Dr. David Alan Gilbert + +From: Liran Alon + +Simiar to how kvm_init_vcpu() calls kvm_arch_init_vcpu() to perform +arch-dependent initialisation, introduce kvm_arch_destroy_vcpu() +to be called from kvm_destroy_vcpu() to perform arch-dependent +destruction. + +This was added because some architectures (Such as i386) +currently do not free memory that it have allocated in +kvm_arch_init_vcpu(). + +Suggested-by: Maran Wilson +Reviewed-by: Maran Wilson +Signed-off-by: Liran Alon +Message-Id: <20190619162140.133674-3-liran.alon@oracle.com> +Signed-off-by: Paolo Bonzini +(cherry picked from commit b1115c99919cf158bb859865f14c3198a0e6f679) +Signed-off-by: Danilo C. L. de Paula +--- + accel/kvm/kvm-all.c | 5 +++++ + include/sysemu/kvm.h | 1 + + target/arm/kvm32.c | 5 +++++ + target/arm/kvm64.c | 5 +++++ + target/i386/kvm.c | 12 ++++++++++++ + target/mips/kvm.c | 5 +++++ + target/ppc/kvm.c | 5 +++++ + target/s390x/kvm.c | 10 ++++++++++ + 8 files changed, 48 insertions(+) + +diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c +index 3a7c8a3..a939b26 100644 +--- a/accel/kvm/kvm-all.c ++++ b/accel/kvm/kvm-all.c +@@ -290,6 +290,11 @@ int kvm_destroy_vcpu(CPUState *cpu) + + DPRINTF("kvm_destroy_vcpu\n"); + ++ ret = kvm_arch_destroy_vcpu(cpu); ++ if (ret < 0) { ++ goto err; ++ } ++ + mmap_size = kvm_ioctl(s, KVM_GET_VCPU_MMAP_SIZE, 0); + if (mmap_size < 0) { + ret = mmap_size; +diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h +index 3d8f294..a5a6dff 100644 +--- a/include/sysemu/kvm.h ++++ b/include/sysemu/kvm.h +@@ -372,6 +372,7 @@ int kvm_arch_put_registers(CPUState *cpu, int level); + int kvm_arch_init(MachineState *ms, KVMState *s); + + int kvm_arch_init_vcpu(CPUState *cpu); ++int kvm_arch_destroy_vcpu(CPUState *cpu); + + bool kvm_vcpu_id_is_valid(int vcpu_id); + +diff --git a/target/arm/kvm32.c b/target/arm/kvm32.c +index 1740cda..056f016 100644 +--- a/target/arm/kvm32.c ++++ b/target/arm/kvm32.c +@@ -237,6 +237,11 @@ int kvm_arch_init_vcpu(CPUState *cs) + return kvm_arm_init_cpreg_list(cpu); + } + ++int kvm_arch_destroy_vcpu(CPUState *cs) ++{ ++ return 0; ++} ++ + typedef struct Reg { + uint64_t id; + int offset; +diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c +index e0b8246..c9c761e 100644 +--- a/target/arm/kvm64.c ++++ b/target/arm/kvm64.c +@@ -549,6 +549,11 @@ int kvm_arch_init_vcpu(CPUState *cs) + return kvm_arm_init_cpreg_list(cpu); + } + ++int kvm_arch_destroy_vcpu(CPUState *cs) ++{ ++ return 0; ++} ++ + bool kvm_arm_reg_syncs_via_cpreg_list(uint64_t regidx) + { + /* Return true if the regidx is a register we should synchronize +diff --git a/target/i386/kvm.c b/target/i386/kvm.c +index 8e861a1..305809f 100644 +--- a/target/i386/kvm.c ++++ b/target/i386/kvm.c +@@ -1196,6 +1196,18 @@ int kvm_arch_init_vcpu(CPUState *cs) + return r; + } + ++int kvm_arch_destroy_vcpu(CPUState *cs) ++{ ++ X86CPU *cpu = X86_CPU(cs); ++ ++ if (cpu->kvm_msr_buf) { ++ g_free(cpu->kvm_msr_buf); ++ cpu->kvm_msr_buf = NULL; ++ } ++ ++ return 0; ++} ++ + void kvm_arch_reset_vcpu(X86CPU *cpu) + { + CPUX86State *env = &cpu->env; +diff --git a/target/mips/kvm.c b/target/mips/kvm.c +index 8e72850..938f8f1 100644 +--- a/target/mips/kvm.c ++++ b/target/mips/kvm.c +@@ -91,6 +91,11 @@ int kvm_arch_init_vcpu(CPUState *cs) + return ret; + } + ++int kvm_arch_destroy_vcpu(CPUState *cs) ++{ ++ return 0; ++} ++ + void kvm_mips_reset_vcpu(MIPSCPU *cpu) + { + CPUMIPSState *env = &cpu->env; +diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c +index 058dcbe..b9858fa 100644 +--- a/target/ppc/kvm.c ++++ b/target/ppc/kvm.c +@@ -607,6 +607,11 @@ int kvm_arch_init_vcpu(CPUState *cs) + return ret; + } + ++int kvm_arch_destroy_vcpu(CPUState *cs) ++{ ++ return 0; ++} ++ + static void kvm_sw_tlb_put(PowerPCCPU *cpu) + { + CPUPPCState *env = &cpu->env; +diff --git a/target/s390x/kvm.c b/target/s390x/kvm.c +index 1d6cc33..0814333 100644 +--- a/target/s390x/kvm.c ++++ b/target/s390x/kvm.c +@@ -370,6 +370,16 @@ int kvm_arch_init_vcpu(CPUState *cs) + return 0; + } + ++int kvm_arch_destroy_vcpu(CPUState *cs) ++{ ++ S390CPU *cpu = S390_CPU(cs); ++ ++ g_free(cpu->irqstate); ++ cpu->irqstate = NULL; ++ ++ return 0; ++} ++ + void kvm_s390_reset_vcpu(S390CPU *cpu) + { + CPUState *cs = CPU(cpu); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-Introduce-new-no_guest_reset-parameter-for-usb-host-.patch b/SOURCES/kvm-Introduce-new-no_guest_reset-parameter-for-usb-host-.patch new file mode 100644 index 0000000..bed1b54 --- /dev/null +++ b/SOURCES/kvm-Introduce-new-no_guest_reset-parameter-for-usb-host-.patch @@ -0,0 +1,140 @@ +From 7efd1d899d2478ad9fffcf0584907f38cd6d20ff Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Tue, 4 Jun 2019 05:12:43 +0100 +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: 1713677 +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Max Reitz +RH-Acked-by: Danilo de Paula + +From: Alexander Kappner + +With certain USB devices passed through via usb-host, a guest attempting to +reset a usb-host device can trigger a reset loop that renders the USB device +unusable. In my use case, the device was an iPhone XR that was passed through to +a Mac OS X Mojave guest. Upon connecting the device, the following happens: + +1) Guest recognizes new device, sends reset to emulated USB host +2) QEMU's USB host sends reset to host kernel +3) Host kernel resets device +4) After reset, host kernel determines that some part of the device descriptor +has changed ("device firmware changed" in dmesg), so host kernel decides to +re-enumerate the device. +5) Re-enumeration causes QEMU to disconnect and reconnect the device in the +guest. +6) goto 1) + +Here's from the host kernel (note the "device firmware changed" lines") + +[3677704.473050] usb 1-1.3: new high-speed USB device number 53 using ehci-pci +[3677704.555594] usb 1-1.3: New USB device found, idVendor=05ac, idProduct=12a8, bcdDevice=11.08 +[3677704.555599] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3 +[3677704.555602] usb 1-1.3: Product: iPhone +[3677704.555605] usb 1-1.3: Manufacturer: Apple Inc. +[3677704.555607] usb 1-1.3: SerialNumber: [[removed]] +[3677709.401040] usb 1-1.3: reset high-speed USB device number 53 using ehci-pci +[3677709.479486] usb 1-1.3: device firmware changed +[3677709.479842] usb 1-1.3: USB disconnect, device number 53 +[3677709.546039] usb 1-1.3: new high-speed USB device number 54 using ehci-pci +[3677709.627471] usb 1-1.3: New USB device found, idVendor=05ac, idProduct=12a8, bcdDevice=11.08 +[3677709.627476] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3 +[3677709.627479] usb 1-1.3: Product: iPhone +[3677709.627481] usb 1-1.3: Manufacturer: Apple Inc. +[3677709.627483] usb 1-1.3: SerialNumber: [[removed]] +[3677762.320044] usb 1-1.3: reset high-speed USB device number 54 using ehci-pci +[3677762.615630] usb 1-1.3: USB disconnect, device number 54 +[3677762.787043] usb 1-1.3: new high-speed USB device number 55 using ehci-pci +[3677762.869016] usb 1-1.3: New USB device found, idVendor=05ac, idProduct=12a8, bcdDevice=11.08 +[3677762.869024] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3 +[3677762.869028] usb 1-1.3: Product: iPhone +[3677762.869032] usb 1-1.3: Manufacturer: Apple Inc. +[3677762.869035] usb 1-1.3: SerialNumber: [[removed]] +[3677815.662036] usb 1-1.3: reset high-speed USB device number 55 using ehci-pci + +Here's from QEMU: + +libusb: error [_get_usbfs_fd] libusb couldn't open USB device /dev/bus/usb/005/022: No such file or directory +libusb: error [udev_hotplug_event] ignoring udev action bind +libusb: error [udev_hotplug_event] ignoring udev action bind +libusb: error [_open_sysfs_attr] open /sys/bus/usb/devices/5-1/bConfigurationValue failed ret=-1 errno=2 +libusb: error [_get_usbfs_fd] File doesn't exist, wait 10 ms and try again + +libusb: error [_get_usbfs_fd] libusb couldn't open USB device /dev/bus/usb/005/024: No such file or directory +libusb: error [udev_hotplug_event] ignoring udev action bind +libusb: error [udev_hotplug_event] ignoring udev action bind +libusb: error [_open_sysfs_attr] open /sys/bus/usb/devices/5-1/bConfigurationValue failed ret=-1 errno=2 +libusb: error [_get_usbfs_fd] File doesn't exist, wait 10 ms and try again + +libusb: error [_get_usbfs_fd] libusb couldn't open USB device /dev/bus/usb/005/026: No such file or directory + +The result of this is that the device remains permanently unusable in the guest. +The same problem has been previously reported for an iPad: +https://stackoverflow.com/questions/52617634/how-do-i-get-qemu-usb-passthrough-to-work-for-ipad-iphone + +This problem can be elegantly solved by interrupting step 2) above. Instead of +passing through the reset, QEMU simply ignores it. To allow this to be +configured on a per-device level, a new parameter "no_guest_reset" is +introduced for the usb-host device. I can confirm that the configuration +described above (iPhone XS + Mojave guest) works flawlessly with +no_guest_reset=True specified. + +Working command line for my scenario: +device_add usb-host,vendorid=0x05ac,productid=0x12a8,no_guest_reset=True,id=iphone + +Best regards +Alexander + +Signed-off-by: Alexander Kappner +Signed-off-by: Gerd Hoffmann +Message-id: 20190128140027.9448-1-kraxel@redhat.com + +[ kraxel: rename parameter to "guest-reset" ] + +Signed-off-by: Gerd Hoffmann +(cherry picked from commit ba4c735b4fc74e309ce4b2551d258e442ef513a5) +Signed-off-by: Danilo C. L. de Paula +--- + hw/usb/host-libusb.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/hw/usb/host-libusb.c b/hw/usb/host-libusb.c +index f31e9cb..d82a10a 100644 +--- a/hw/usb/host-libusb.c ++++ b/hw/usb/host-libusb.c +@@ -82,7 +82,7 @@ struct USBHostDevice { + uint32_t options; + uint32_t loglevel; + bool needs_autoscan; +- ++ bool allow_guest_reset; + /* state */ + QTAILQ_ENTRY(USBHostDevice) next; + int seen, errcount; +@@ -1451,6 +1451,10 @@ static void usb_host_handle_reset(USBDevice *udev) + USBHostDevice *s = USB_HOST_DEVICE(udev); + int rc; + ++ if (!s->allow_guest_reset) { ++ return; ++ } ++ + trace_usb_host_reset(s->bus_num, s->addr); + + rc = libusb_reset_device(s->dh); +@@ -1568,6 +1572,7 @@ static Property usb_host_dev_properties[] = { + DEFINE_PROP_UINT32("productid", USBHostDevice, match.product_id, 0), + DEFINE_PROP_UINT32("isobufs", USBHostDevice, iso_urb_count, 4), + DEFINE_PROP_UINT32("isobsize", USBHostDevice, iso_urb_frames, 32), ++ DEFINE_PROP_BOOL("guest-reset", USBHostDevice, allow_guest_reset, true), + DEFINE_PROP_UINT32("loglevel", USBHostDevice, loglevel, + LIBUSB_LOG_LEVEL_WARNING), + DEFINE_PROP_BIT("pipeline", USBHostDevice, options, +-- +1.8.3.1 + diff --git a/SOURCES/kvm-RHEL-disable-hostmem-memfd.patch b/SOURCES/kvm-RHEL-disable-hostmem-memfd.patch new file mode 100644 index 0000000..5781a40 --- /dev/null +++ b/SOURCES/kvm-RHEL-disable-hostmem-memfd.patch @@ -0,0 +1,56 @@ +From bf545f4a8f40a4ac8f6d63d887a63d9f08329eb6 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= +Date: Wed, 14 Aug 2019 08:52:10 +0100 +Subject: [PATCH 10/10] RHEL: disable hostmem-memfd +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Marc-André Lureau +Message-id: <20190814085210.18462-1-marcandre.lureau@redhat.com> +Patchwork-id: 89974 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH] RHEL: disable hostmem-memfd +Bugzilla: 1740797 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: John Snow + +BZ: https://bugzilla.redhat.com/show_bug.cgi?id=1740797 +BRANCH: rhel8/rhel-8.1.0 +UPSTREAM: n/a (downstream only) +BREW: 23060214 + +Signed-off-by: Marc-André Lureau +Signed-off-by: Danilo C. L. de Paula +--- + backends/Makefile.objs | 3 ++- + util/memfd.c | 2 +- + 2 files changed, 3 insertions(+), 2 deletions(-) + +diff --git a/backends/Makefile.objs b/backends/Makefile.objs +index ad7c032..673fc55 100644 +--- a/backends/Makefile.objs ++++ b/backends/Makefile.objs +@@ -15,4 +15,5 @@ common-obj-$(call land,$(CONFIG_VHOST_USER),$(CONFIG_LINUX)) += \ + cryptodev-vhost-user.o + endif + +-common-obj-$(CONFIG_LINUX) += hostmem-memfd.o ++# RHEL: disable memfd ++# common-obj-$(CONFIG_LINUX) += hostmem-memfd.o +diff --git a/util/memfd.c b/util/memfd.c +index b3ecbac..9312653 100644 +--- a/util/memfd.c ++++ b/util/memfd.c +@@ -202,7 +202,7 @@ bool qemu_memfd_alloc_check(void) + */ + bool qemu_memfd_check(void) + { +-#ifdef CONFIG_LINUX ++#if 0 /* RHEL: memfd support disabled */ + static int memfd_check = MEMFD_TODO; + + if (memfd_check == MEMFD_TODO) { +-- +1.8.3.1 + diff --git a/SOURCES/kvm-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 new file mode 100644 index 0000000..14dccc0 --- /dev/null +++ b/SOURCES/kvm-Use-KVM_GET_MSR_INDEX_LIST-for-MSR_IA32_ARCH_CAP.patch @@ -0,0 +1,77 @@ +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: 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 + +When writing to guest's MSR_IA32_ARCH_CAPABILITIES, check whether it's +supported in the guest using the KVM_GET_MSR_INDEX_LIST ioctl. + +Fixes: d86f963694df27f11b3681ffd225c9362de1b634 +Suggested-by: Eduardo Habkost +Tested-by: balducci@units.it +Signed-off-by: Bandan Das +Message-Id: +Signed-off-by: Eduardo Habkost +(cherry picked from commit aec5e9c3a94cf8b7920f59bef69a6f426092c4a0) +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 f1626a4..e3e8c78 100644 +--- a/target/i386/kvm.c ++++ b/target/i386/kvm.c +@@ -94,6 +94,7 @@ static bool has_msr_xss; + static bool has_msr_spec_ctrl; + static bool has_msr_virt_ssbd; + static bool has_msr_smi_count; ++static bool has_msr_arch_capabs; + + static uint32_t has_architectural_pmu_version; + static uint32_t num_architectural_pmu_gp_counters; +@@ -1330,6 +1331,9 @@ static int kvm_get_supported_msrs(KVMState *s) + case MSR_VIRT_SSBD: + has_msr_virt_ssbd = true; + break; ++ case MSR_IA32_ARCH_CAPABILITIES: ++ has_msr_arch_capabs = true; ++ break; + } + } + } +@@ -1834,14 +1838,9 @@ static int kvm_put_msrs(X86CPU *cpu, int level) + #endif + + /* If host supports feature MSR, write down. */ +- if (kvm_feature_msrs) { +- int i; +- for (i = 0; i < kvm_feature_msrs->nmsrs; i++) +- if (kvm_feature_msrs->indices[i] == MSR_IA32_ARCH_CAPABILITIES) { +- kvm_msr_entry_add(cpu, MSR_IA32_ARCH_CAPABILITIES, +- env->features[FEAT_ARCH_CAPABILITIES]); +- break; +- } ++ if (has_msr_arch_capabs) { ++ kvm_msr_entry_add(cpu, MSR_IA32_ARCH_CAPABILITIES, ++ env->features[FEAT_ARCH_CAPABILITIES]); + } + + /* +-- +1.8.3.1 + diff --git a/SOURCES/kvm-Using-ip_deq-after-m_free-might-read-pointers-from-a.patch b/SOURCES/kvm-Using-ip_deq-after-m_free-might-read-pointers-from-a.patch new file mode 100644 index 0000000..ce5cca1 --- /dev/null +++ b/SOURCES/kvm-Using-ip_deq-after-m_free-might-read-pointers-from-a.patch @@ -0,0 +1,61 @@ +From a4c22009a465ebe5fd0c09699e61ad0423b8849d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Fri, 6 Sep 2019 14:00:34 +0100 +Subject: [PATCH 07/22] Using ip_deq after m_free might read pointers from an + allocation reuse. +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Philippe Mathieu-Daudé +Message-id: <20190906140034.19722-2-philmd@redhat.com> +Patchwork-id: 90306 +O-Subject: [RHEL-7.7 qemu-kvm-ma + RHEL-7.7 qemu-kvm-rhev + RHEL-8.1.0 qemu-kvm PATCH 1/1] Using ip_deq after m_free might read pointers from an allocation reuse. +Bugzilla: 1749724 +RH-Acked-by: Thomas Huth +RH-Acked-by: Stefano Garzarella +RH-Acked-by: Stefan Hajnoczi + +From: Samuel Thibault + +This would be difficult to exploit, but that is still related with +CVE-2019-14378 which generates fragmented IP packets that would trigger this +issue and at least produce a DoS. + +Signed-off-by: Samuel Thibault +(cherry picked from libslirp commit c59279437eda91841b9d26079c70b8a540d41204) +Signed-off-by: Philippe Mathieu-Daudé + +Signed-off-by: Danilo C. L. de Paula +--- + slirp/ip_input.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/slirp/ip_input.c b/slirp/ip_input.c +index 07d8808..7cf0133 100644 +--- a/slirp/ip_input.c ++++ b/slirp/ip_input.c +@@ -300,6 +300,7 @@ ip_reass(Slirp *slirp, struct ip *ip, struct ipq *fp) + */ + while (q != (struct ipasfrag*)&fp->frag_link && + ip->ip_off + ip->ip_len > q->ipf_off) { ++ struct ipasfrag *prev; + i = (ip->ip_off + ip->ip_len) - q->ipf_off; + if (i < q->ipf_len) { + q->ipf_len -= i; +@@ -307,9 +308,10 @@ ip_reass(Slirp *slirp, struct ip *ip, struct ipq *fp) + m_adj(dtom(slirp, q), i); + break; + } ++ prev = q; + q = q->ipf_next; +- m_free(dtom(slirp, q->ipf_prev)); +- ip_deq(q->ipf_prev); ++ ip_deq(prev); ++ m_free(dtom(slirp, prev)); + } + + insert: +-- +1.8.3.1 + diff --git a/SOURCES/kvm-accel-use-g_strsplit-for-parsing-accelerator-names.patch b/SOURCES/kvm-accel-use-g_strsplit-for-parsing-accelerator-names.patch new file mode 100644 index 0000000..f031582 --- /dev/null +++ b/SOURCES/kvm-accel-use-g_strsplit-for-parsing-accelerator-names.patch @@ -0,0 +1,113 @@ +From 28a766b8099f5e745dbfc18834277039643214a3 Mon Sep 17 00:00:00 2001 +From: Laszlo Ersek +Date: Thu, 12 Sep 2019 13:04:58 +0100 +Subject: [PATCH 01/22] accel: use g_strsplit for parsing accelerator names +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Laszlo Ersek +Message-id: <20190912130503.14094-2-lersek@redhat.com> +Patchwork-id: 90437 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH 1/6] accel: use g_strsplit for parsing accelerator names +Bugzilla: 1749022 +RH-Acked-by: Stefano Garzarella +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Eduardo Habkost + +From: Daniel P. Berrangé + +Instead of re-using the get_opt_name() method from QemuOpts to split a +string on ':', just use g_strsplit(). + +RHEL8 notes: + +- Fix up upstream's obviously garbled UTF8 sequences in Dan's name (Author + meta-datum, Signed-off-by tags). + +- Harmless context difference due to downstream-only commit 8b53513834e6 + ("Use kvm by default", 2018-04-24). + +Signed-off-by: Daniel P. Berrangé +Message-Id: <20180416111743.8473-2-berrange@redhat.com> +Signed-off-by: Paolo Bonzini +Signed-off-by: Daniel P. Berrangé +(cherry picked from commit 20efc49ed625585809401d8293ad9267927a6a4a) +Signed-off-by: Laszlo Ersek +Signed-off-by: Danilo C. L. de Paula +--- + accel/accel.c | 16 +++++++--------- + include/qemu/option.h | 1 - + util/qemu-option.c | 3 ++- + 3 files changed, 9 insertions(+), 11 deletions(-) + +diff --git a/accel/accel.c b/accel/accel.c +index 5f3d73f..57390e5 100644 +--- a/accel/accel.c ++++ b/accel/accel.c +@@ -70,8 +70,8 @@ static int accel_init_machine(AccelClass *acc, MachineState *ms) + + void configure_accelerator(MachineState *ms) + { +- const char *accel, *p; +- char buf[10]; ++ const char *accel; ++ char **accel_list, **tmp; + int ret; + bool accel_initialised = false; + bool init_failed = false; +@@ -83,13 +83,10 @@ void configure_accelerator(MachineState *ms) + accel = "kvm:tcg"; + } + +- p = accel; +- while (!accel_initialised && *p != '\0') { +- if (*p == ':') { +- p++; +- } +- p = get_opt_name(buf, sizeof(buf), p, ':'); +- acc = accel_find(buf); ++ accel_list = g_strsplit(accel, ":", 0); ++ ++ for (tmp = accel_list; !accel_initialised && tmp && *tmp; tmp++) { ++ acc = accel_find(*tmp); + if (!acc) { + continue; + } +@@ -107,6 +104,7 @@ void configure_accelerator(MachineState *ms) + accel_initialised = true; + } + } ++ g_strfreev(accel_list); + + if (!accel_initialised) { + if (!init_failed) { +diff --git a/include/qemu/option.h b/include/qemu/option.h +index 306fdb5..1cfe5cb 100644 +--- a/include/qemu/option.h ++++ b/include/qemu/option.h +@@ -28,7 +28,6 @@ + + #include "qemu/queue.h" + +-const char *get_opt_name(char *buf, int buf_size, const char *p, char delim); + const char *get_opt_value(char *buf, int buf_size, const char *p); + + void parse_option_size(const char *name, const char *value, +diff --git a/util/qemu-option.c b/util/qemu-option.c +index 95e6cf4..a8db173 100644 +--- a/util/qemu-option.c ++++ b/util/qemu-option.c +@@ -49,7 +49,8 @@ + * The return value is the position of the delimiter/zero byte after the option + * name in p. + */ +-const char *get_opt_name(char *buf, int buf_size, const char *p, char delim) ++static const char *get_opt_name(char *buf, int buf_size, const char *p, ++ char delim) + { + char *q; + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-add-call-to-qemu_add_opts-for-overcommit-option.patch b/SOURCES/kvm-add-call-to-qemu_add_opts-for-overcommit-option.patch new file mode 100644 index 0000000..a68e498 --- /dev/null +++ b/SOURCES/kvm-add-call-to-qemu_add_opts-for-overcommit-option.patch @@ -0,0 +1,45 @@ +From 490c0121b8cd1de62776c18a0843a256b7eed3e3 Mon Sep 17 00:00:00 2001 +From: "plai@redhat.com" +Date: Tue, 26 Nov 2019 19:36:51 +0000 +Subject: [PATCH 07/11] kvm: add call to qemu_add_opts() for -overcommit option + +RH-Author: plai@redhat.com +Message-id: <1574797015-32564-4-git-send-email-plai@redhat.com> +Patchwork-id: 92694 +O-Subject: [RHEL8.2 qemu-kvm PATCH 3/7] kvm: add call to qemu_add_opts() for -overcommit option +Bugzilla: 1634827 +RH-Acked-by: Eduardo Habkost +RH-Acked-by: Michael S. Tsirkin +RH-Acked-by: Igor Mammedov + +From: Prasad Singamsetty + +qemu command fails to process -overcommit option. Add the missing +call to qemu_add_opts() in vl.c. + +Signed-off-by: Prasad Singamsetty +Message-Id: <20180815175704.105902-1-prasad.singamsetty@oracle.com> +Reviewed-by: Mark Kanda +Signed-off-by: Paolo Bonzini +(cherry picked from commit 1fdd4748711a62d863744f42b958472509a6f202) +Signed-off-by: Paul Lai +Signed-off-by: Danilo C. L. de Paula +--- + vl.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/vl.c b/vl.c +index 3cee95f..932c1cf 100644 +--- a/vl.c ++++ b/vl.c +@@ -3145,6 +3145,7 @@ int main(int argc, char **argv, char **envp) + qemu_add_opts(&qemu_object_opts); + qemu_add_opts(&qemu_tpmdev_opts); + qemu_add_opts(&qemu_realtime_opts); ++ qemu_add_opts(&qemu_overcommit_opts); + qemu_add_opts(&qemu_msg_opts); + qemu_add_opts(&qemu_name_opts); + qemu_add_opts(&qemu_numa_opts); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-arm-fixes.patch b/SOURCES/kvm-arm-fixes.patch deleted file mode 100644 index 61d3dae..0000000 --- a/SOURCES/kvm-arm-fixes.patch +++ /dev/null @@ -1,74 +0,0 @@ -diff -Naurwp a/default-configs/pci.mak b/default-configs/pci.mak ---- a/default-configs/pci.mak 2019-06-28 11:45:41.983632134 +0000 -+++ b/default-configs/pci.mak 2019-06-29 02:13:42.117191042 +0000 -@@ -15,7 +15,7 @@ CONFIG_USB_XHCI_NEC=y - CONFIG_AC97=y - CONFIG_HDA=y - #CONFIG_ES1370=y --#CONFIG_LSI_SCSI_PCI=y -+CONFIG_LSI_SCSI_PCI=y - #CONFIG_VMW_PVSCSI_SCSI_PCI=y - #CONFIG_MEGASAS_SCSI_PCI=y - #CONFIG_MPTSAS_SCSI_PCI=y -diff -Naurwp a/hw/arm/Makefile.objs b/hw/arm/Makefile.objs ---- a/hw/arm/Makefile.objs 2019-06-28 11:45:39.996700783 +0000 -+++ b/hw/arm/Makefile.objs 2019-06-28 12:41:01.139408649 +0000 -@@ -16,7 +16,7 @@ obj-$(CONFIG_STRONGARM) += collie.o - obj-$(CONFIG_VERSATILE) += vexpress.o versatilepb.o - obj-$(CONFIG_ZYNQ) += xilinx_zynq.o - --#obj-$(CONFIG_ARM_V7M) += armv7m.o -+obj-$(CONFIG_ARM_V7M) += armv7m.o - obj-$(CONFIG_EXYNOS4) += exynos4210.o - obj-$(CONFIG_PXA2XX) += pxa2xx.o pxa2xx_gpio.o pxa2xx_pic.o - obj-$(CONFIG_DIGIC) += digic.o -diff -Naurwp a/hw/arm/nseries.c b/hw/arm/nseries.c ---- a/hw/arm/nseries.c 2018-04-24 16:30:46.000000000 +0000 -+++ b/hw/arm/nseries.c 2019-06-28 12:58:48.691559918 +0000 -@@ -786,6 +786,7 @@ static void n8x0_cbus_setup(struct n800_ - - static void n8x0_uart_setup(struct n800_s *s) - { -+#if 0 //Bluetooth Disabled - Chardev *radio = uart_hci_init(); - - qdev_connect_gpio_out(s->mpu->gpio, N8X0_BT_RESET_GPIO, -@@ -794,6 +795,7 @@ static void n8x0_uart_setup(struct n800_ - csrhci_pins_get(radio)[csrhci_pin_wakeup]); - - omap_uart_attach(s->mpu->uart[BT_UART], radio); -+#endif - } - - static void n8x0_usb_setup(struct n800_s *s) -diff -Naurwp a/hw/char/exynos4210_uart.c b/hw/char/exynos4210_uart.c ---- a/hw/char/exynos4210_uart.c 2018-04-24 16:30:46.000000000 +0000 -+++ b/hw/char/exynos4210_uart.c 2019-06-28 12:07:13.338023334 +0000 -@@ -590,7 +590,7 @@ DeviceState *exynos4210_uart_create(hwad - SysBusDevice *bus; - - const char chr_name[] = "serial"; -- char label[ARRAY_SIZE(chr_name) + 1]; -+ char label[ARRAY_SIZE(chr_name) + 20]; - - dev = qdev_create(NULL, TYPE_EXYNOS4210_UART); - -diff -Naurwp a/hw/core/Makefile.objs b/hw/core/Makefile.objs ---- a/hw/core/Makefile.objs 2019-06-28 11:45:40.002700575 +0000 -+++ b/hw/core/Makefile.objs 2019-06-28 13:20:50.504941179 +0000 -@@ -16,11 +16,10 @@ common-obj-$(CONFIG_SOFTMMU) += machine. - common-obj-$(CONFIG_SOFTMMU) += loader.o - common-obj-$(CONFIG_FITLOADER) += loader-fit.o - common-obj-$(CONFIG_SOFTMMU) += qdev-properties-system.o --# Disabled in Red Hat Enterprise Linux --# common-obj-$(CONFIG_SOFTMMU) += register.o --# obj-$(CONFIG_SOFTMMU) += generic-loader.o --# common-obj-$(CONFIG_SOFTMMU) += or-irq.o --#common-obj-$(CONFIG_SOFTMMU) += split-irq.o -+common-obj-$(CONFIG_SOFTMMU) += register.o -+common-obj-$(CONFIG_SOFTMMU) += or-irq.o -+common-obj-$(CONFIG_SOFTMMU) += split-irq.o - common-obj-$(CONFIG_PLATFORM_BUS) += platform-bus.o - -+obj-$(CONFIG_SOFTMMU) += generic-loader.o - obj-$(CONFIG_SOFTMMU) += null-machine.o 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-ccid-Fix-dwProtocols-advertisement-of-T-0.patch b/SOURCES/kvm-ccid-Fix-dwProtocols-advertisement-of-T-0.patch new file mode 100644 index 0000000..5af3ea1 --- /dev/null +++ b/SOURCES/kvm-ccid-Fix-dwProtocols-advertisement-of-T-0.patch @@ -0,0 +1,67 @@ +From e541592f0c98696276261a7c36afe074a3bdd956 Mon Sep 17 00:00:00 2001 +From: Maxim Levitsky +Date: Wed, 18 Sep 2019 18:45:52 +0100 +Subject: [PATCH 11/22] ccid: Fix dwProtocols advertisement of T=0 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Maxim Levitsky +Message-id: <20190918184552.10820-2-mlevitsk@redhat.com> +Patchwork-id: 90769 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH 1/1] ccid: Fix dwProtocols advertisement of T=0 +Bugzilla: 1746361 +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Stefano Garzarella +RH-Acked-by: John Snow + +From: Jason Andryuk + +Commit d7d218ef02d87c637d20d64da8f575d434ff6f78 attempted to change +dwProtocols to only advertise support for T=0 and not T=1. The change +was incorrect as it changed 0x00000003 to 0x00010000. + +lsusb -v in a linux guest shows: +"dwProtocols 65536 (Invalid values detected)", though the +smart card could still be accessed. Windows 7 does not detect inserted +smart cards and logs the the following Error in the Event Logs: + + Source: Smart Card Service + Event ID: 610 + Smart Card Reader 'QEMU QEMU USB CCID 0' rejected IOCTL SET_PROTOCOL: + Incorrect function. If this error persists, your smart card or reader + may not be functioning correctly + + Command Header: 03 00 00 00 + +Setting to 0x00000001 fixes the Windows issue. + +Signed-off-by: Jason Andryuk +Message-id: 20180420183219.20722-1-jandryuk@gmail.com +Cc: qemu-stable@nongnu.org +Signed-off-by: Gerd Hoffmann +(cherry picked from commit 0ee86bb6c5beb6498488850104f7557c376d0bef) +Signed-off-by: Maxim Levitsky +Signed-off-by: Danilo C. L. de Paula +--- + hw/usb/dev-smartcard-reader.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c +index e646805..cabb564 100644 +--- a/hw/usb/dev-smartcard-reader.c ++++ b/hw/usb/dev-smartcard-reader.c +@@ -329,8 +329,8 @@ static const uint8_t qemu_ccid_descriptor[] = { + */ + 0x07, /* u8 bVoltageSupport; 01h - 5.0v, 02h - 3.0, 03 - 1.8 */ + +- 0x00, 0x00, /* u32 dwProtocols; RRRR PPPP. RRRR = 0000h.*/ +- 0x01, 0x00, /* PPPP: 0001h = Protocol T=0, 0002h = Protocol T=1 */ ++ 0x01, 0x00, /* u32 dwProtocols; RRRR PPPP. RRRR = 0000h.*/ ++ 0x00, 0x00, /* PPPP: 0001h = Protocol T=0, 0002h = Protocol T=1 */ + /* u32 dwDefaultClock; in kHZ (0x0fa0 is 4 MHz) */ + 0xa0, 0x0f, 0x00, 0x00, + /* u32 dwMaximumClock; */ +-- +1.8.3.1 + diff --git a/SOURCES/kvm-clean-up-callback-when-del-virtqueue.patch b/SOURCES/kvm-clean-up-callback-when-del-virtqueue.patch new file mode 100644 index 0000000..dc57895 --- /dev/null +++ b/SOURCES/kvm-clean-up-callback-when-del-virtqueue.patch @@ -0,0 +1,55 @@ +From 335e94e588ded0f1163ef20c72d78fcf725b1236 Mon Sep 17 00:00:00 2001 +From: Julia Suvorova +Date: Tue, 4 Feb 2020 18:20:04 +0000 +Subject: [PATCH 3/6] clean up callback when del virtqueue + +RH-Author: Julia Suvorova +Message-id: <20200204182007.183537-2-jusual@redhat.com> +Patchwork-id: 93703 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH 1/4] clean up callback when del virtqueue +Bugzilla: 1708480 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Cornelia Huck +RH-Acked-by: Michael S. Tsirkin + +From: liujunjie + +Before, we did not clear callback like handle_output when delete +the virtqueue which may result be segmentfault. +The scene is as follows: +1. Start a vm with multiqueue vhost-net, +2. then we write VIRTIO_PCI_GUEST_FEATURES in PCI configuration to +triger multiqueue disable in this vm which will delete the virtqueue. +In this step, the tx_bh is deleted but the callback virtio_net_handle_tx_bh +still exist. +3. Finally, we write VIRTIO_PCI_QUEUE_NOTIFY in PCI configuration to +notify the deleted virtqueue. In this way, virtio_net_handle_tx_bh +will be called and qemu will be crashed. + +Although the way described above is uncommon, we had better reinforce it. + +CC: qemu-stable@nongnu.org +Signed-off-by: liujunjie +Signed-off-by: Jason Wang +(cherry picked from commit 7da2d99fb9fbf30104125c061caaff330e362d74) +Signed-off-by: Danilo C. L. de Paula +--- + hw/virtio/virtio.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c +index fce199e..6356bf3 100644 +--- a/hw/virtio/virtio.c ++++ b/hw/virtio/virtio.c +@@ -1609,6 +1609,8 @@ void virtio_del_queue(VirtIODevice *vdev, int n) + + vdev->vq[n].vring.num = 0; + vdev->vq[n].vring.num_default = 0; ++ vdev->vq[n].handle_output = NULL; ++ vdev->vq[n].handle_aio_output = NULL; + } + + static void virtio_set_isr(VirtIODevice *vdev, int value) +-- +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-curl-Check-completion-in-curl_multi_do.patch b/SOURCES/kvm-curl-Check-completion-in-curl_multi_do.patch new file mode 100644 index 0000000..95ac20c --- /dev/null +++ b/SOURCES/kvm-curl-Check-completion-in-curl_multi_do.patch @@ -0,0 +1,87 @@ +From a09766bbc8a4208fc0f62904cebec4022beba6b0 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Tue, 19 Nov 2019 15:29:56 +0000 +Subject: [PATCH 4/8] curl: Check completion in curl_multi_do() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Max Reitz +Message-id: <20191119153000.101646-4-mreitz@redhat.com> +Patchwork-id: 92516 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH 3/7] curl: Check completion in curl_multi_do() +Bugzilla: 1744602 +RH-Acked-by: Maxim Levitsky +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Stefano Garzarella + +While it is more likely that transfers complete after some file +descriptor has data ready to read, we probably should not rely on it. +Better be safe than sorry and call curl_multi_check_completion() in +curl_multi_do(), too, just like it is done in curl_multi_read(). + +With this change, curl_multi_do() and curl_multi_read() are actually the +same, so drop curl_multi_read() and use curl_multi_do() as the sole FD +handler. + +Signed-off-by: Max Reitz +Message-id: 20190910124136.10565-4-mreitz@redhat.com +Reviewed-by: Maxim Levitsky +Reviewed-by: John Snow +Signed-off-by: Max Reitz +(cherry picked from commit 948403bcb1c7e71dcbe8ab8479cf3934a0efcbb5) +Signed-off-by: Max Reitz +Signed-off-by: Danilo C. L. de Paula +--- + block/curl.c | 14 ++------------ + 1 file changed, 2 insertions(+), 12 deletions(-) + +diff --git a/block/curl.c b/block/curl.c +index b3fe09f..8f31594 100644 +--- a/block/curl.c ++++ b/block/curl.c +@@ -148,7 +148,6 @@ typedef struct BDRVCURLState { + + static void curl_clean_state(CURLState *s); + static void curl_multi_do(void *arg); +-static void curl_multi_read(void *arg); + + #ifdef NEED_CURL_TIMER_CALLBACK + /* Called from curl_multi_do_locked, with s->mutex held. */ +@@ -195,7 +194,7 @@ static int curl_sock_cb(CURL *curl, curl_socket_t fd, int action, + switch (action) { + case CURL_POLL_IN: + aio_set_fd_handler(s->aio_context, fd, false, +- curl_multi_read, NULL, NULL, state); ++ curl_multi_do, NULL, NULL, state); + break; + case CURL_POLL_OUT: + aio_set_fd_handler(s->aio_context, fd, false, +@@ -203,7 +202,7 @@ static int curl_sock_cb(CURL *curl, curl_socket_t fd, int action, + break; + case CURL_POLL_INOUT: + aio_set_fd_handler(s->aio_context, fd, false, +- curl_multi_read, curl_multi_do, NULL, state); ++ curl_multi_do, curl_multi_do, NULL, state); + break; + case CURL_POLL_REMOVE: + aio_set_fd_handler(s->aio_context, fd, false, +@@ -427,15 +426,6 @@ static void curl_multi_do(void *arg) + + qemu_mutex_lock(&s->s->mutex); + curl_multi_do_locked(s); +- qemu_mutex_unlock(&s->s->mutex); +-} +- +-static void curl_multi_read(void *arg) +-{ +- CURLState *s = (CURLState *)arg; +- +- qemu_mutex_lock(&s->s->mutex); +- curl_multi_do_locked(s); + curl_multi_check_completion(s->s); + qemu_mutex_unlock(&s->s->mutex); + } +-- +1.8.3.1 + diff --git a/SOURCES/kvm-curl-Check-curl_multi_add_handle-s-return-code.patch b/SOURCES/kvm-curl-Check-curl_multi_add_handle-s-return-code.patch new file mode 100644 index 0000000..859023c --- /dev/null +++ b/SOURCES/kvm-curl-Check-curl_multi_add_handle-s-return-code.patch @@ -0,0 +1,54 @@ +From d8de6fc3530b5cfa05485f24e14af4ce44a8b72d Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Tue, 19 Nov 2019 15:30:00 +0000 +Subject: [PATCH 8/8] curl: Check curl_multi_add_handle()'s return code +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Max Reitz +Message-id: <20191119153000.101646-8-mreitz@redhat.com> +Patchwork-id: 92521 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH 7/7] curl: Check curl_multi_add_handle()'s return code +Bugzilla: 1744602 +RH-Acked-by: Maxim Levitsky +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Stefano Garzarella + +If we had done that all along, debugging would have been much simpler. +(Also, I/O errors are better than hangs.) + +Signed-off-by: Max Reitz +Message-id: 20190910124136.10565-8-mreitz@redhat.com +Reviewed-by: Maxim Levitsky +Reviewed-by: John Snow +Signed-off-by: Max Reitz +(cherry picked from commit c34dc07f9f01cf686e512f939aece744723072cd) +Signed-off-by: Max Reitz +Signed-off-by: Danilo C. L. de Paula +--- + block/curl.c | 8 +++++++- + 1 file changed, 7 insertions(+), 1 deletion(-) + +diff --git a/block/curl.c b/block/curl.c +index b5899e1..5d05d30 100644 +--- a/block/curl.c ++++ b/block/curl.c +@@ -891,7 +891,13 @@ static void curl_setup_preadv(BlockDriverState *bs, CURLAIOCB *acb) + acb->bytes, start, state->range); + curl_easy_setopt(state->curl, CURLOPT_RANGE, state->range); + +- curl_multi_add_handle(s->multi, state->curl); ++ if (curl_multi_add_handle(s->multi, state->curl) != CURLM_OK) { ++ state->acb[0] = NULL; ++ acb->ret = -EIO; ++ ++ curl_clean_state(state); ++ goto out; ++ } + + /* Tell curl it needs to kick things off */ + curl_multi_socket_action(s->multi, CURL_SOCKET_TIMEOUT, 0, &running); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-curl-Handle-success-in-multi_check_completion.patch b/SOURCES/kvm-curl-Handle-success-in-multi_check_completion.patch new file mode 100644 index 0000000..9fe667e --- /dev/null +++ b/SOURCES/kvm-curl-Handle-success-in-multi_check_completion.patch @@ -0,0 +1,162 @@ +From 23f5a846f6702c456cf7cc9490e50cfd23368910 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Tue, 19 Nov 2019 15:29:59 +0000 +Subject: [PATCH 7/8] curl: Handle success in multi_check_completion +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Max Reitz +Message-id: <20191119153000.101646-7-mreitz@redhat.com> +Patchwork-id: 92520 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH 6/7] curl: Handle success in multi_check_completion +Bugzilla: 1744602 +RH-Acked-by: Maxim Levitsky +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Stefano Garzarella + +Background: As of cURL 7.59.0, it verifies that several functions are +not called from within a callback. Among these functions is +curl_multi_add_handle(). + +curl_read_cb() is a callback from cURL and not a coroutine. Waking up +acb->co will lead to entering it then and there, which means the current +request will settle and the caller (if it runs in the same coroutine) +may then issue the next request. In such a case, we will enter +curl_setup_preadv() effectively from within curl_read_cb(). + +Calling curl_multi_add_handle() will then fail and the new request will +not be processed. + +Fix this by not letting curl_read_cb() wake up acb->co. Instead, leave +the whole business of settling the AIOCB objects to +curl_multi_check_completion() (which is called from our timer callback +and our FD handler, so not from any cURL callbacks). + +Reported-by: Natalie Gavrielov +Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=1740193 +Cc: qemu-stable@nongnu.org +Signed-off-by: Max Reitz +Message-id: 20190910124136.10565-7-mreitz@redhat.com +Reviewed-by: John Snow +Reviewed-by: Maxim Levitsky +Signed-off-by: Max Reitz +(cherry picked from commit bfb23b480a49114315877aacf700b49453e0f9d9) +Signed-off-by: Max Reitz +Signed-off-by: Danilo C. L. de Paula +--- + block/curl.c | 69 +++++++++++++++++++++++++----------------------------------- + 1 file changed, 29 insertions(+), 40 deletions(-) + +diff --git a/block/curl.c b/block/curl.c +index f776615..b5899e1 100644 +--- a/block/curl.c ++++ b/block/curl.c +@@ -238,7 +238,6 @@ static size_t curl_read_cb(void *ptr, size_t size, size_t nmemb, void *opaque) + { + CURLState *s = ((CURLState*)opaque); + size_t realsize = size * nmemb; +- int i; + + DPRINTF("CURL: Just reading %zd bytes\n", realsize); + +@@ -254,32 +253,6 @@ static size_t curl_read_cb(void *ptr, size_t size, size_t nmemb, void *opaque) + memcpy(s->orig_buf + s->buf_off, ptr, realsize); + s->buf_off += realsize; + +- for(i=0; iacb[i]; +- +- if (!acb) +- continue; +- +- if ((s->buf_off >= acb->end)) { +- size_t request_length = acb->bytes; +- +- qemu_iovec_from_buf(acb->qiov, 0, s->orig_buf + acb->start, +- acb->end - acb->start); +- +- if (acb->end - acb->start < request_length) { +- size_t offset = acb->end - acb->start; +- qemu_iovec_memset(acb->qiov, offset, 0, +- request_length - offset); +- } +- +- acb->ret = 0; +- s->acb[i] = NULL; +- qemu_mutex_unlock(&s->s->mutex); +- aio_co_wake(acb->co); +- qemu_mutex_lock(&s->s->mutex); +- } +- } +- + read_end: + /* curl will error out if we do not return this value */ + return size * nmemb; +@@ -360,13 +333,14 @@ static void curl_multi_check_completion(BDRVCURLState *s) + break; + + if (msg->msg == CURLMSG_DONE) { ++ int i; + CURLState *state = NULL; ++ bool error = msg->data.result != CURLE_OK; ++ + curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE, + (char **)&state); + +- /* ACBs for successful messages get completed in curl_read_cb */ +- if (msg->data.result != CURLE_OK) { +- int i; ++ if (error) { + static int errcount = 100; + + /* Don't lose the original error message from curl, since +@@ -378,20 +352,35 @@ static void curl_multi_check_completion(BDRVCURLState *s) + error_report("curl: further errors suppressed"); + } + } ++ } + +- for (i = 0; i < CURL_NUM_ACB; i++) { +- CURLAIOCB *acb = state->acb[i]; ++ for (i = 0; i < CURL_NUM_ACB; i++) { ++ CURLAIOCB *acb = state->acb[i]; + +- if (acb == NULL) { +- continue; +- } ++ if (acb == NULL) { ++ continue; ++ } ++ ++ if (!error) { ++ /* Assert that we have read all data */ ++ assert(state->buf_off >= acb->end); ++ ++ qemu_iovec_from_buf(acb->qiov, 0, ++ state->orig_buf + acb->start, ++ acb->end - acb->start); + +- acb->ret = -EIO; +- state->acb[i] = NULL; +- qemu_mutex_unlock(&s->mutex); +- aio_co_wake(acb->co); +- qemu_mutex_lock(&s->mutex); ++ if (acb->end - acb->start < acb->bytes) { ++ size_t offset = acb->end - acb->start; ++ qemu_iovec_memset(acb->qiov, offset, 0, ++ acb->bytes - offset); ++ } + } ++ ++ acb->ret = error ? -EIO : 0; ++ state->acb[i] = NULL; ++ qemu_mutex_unlock(&s->mutex); ++ aio_co_wake(acb->co); ++ qemu_mutex_lock(&s->mutex); + } + + curl_clean_state(state); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-curl-Keep-pointer-to-the-CURLState-in-CURLSocket.patch b/SOURCES/kvm-curl-Keep-pointer-to-the-CURLState-in-CURLSocket.patch new file mode 100644 index 0000000..65742ed --- /dev/null +++ b/SOURCES/kvm-curl-Keep-pointer-to-the-CURLState-in-CURLSocket.patch @@ -0,0 +1,65 @@ +From 21dbedae8100710d284b79f7ce21a6b095a4c6e0 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Tue, 19 Nov 2019 15:29:54 +0000 +Subject: [PATCH 2/8] curl: Keep pointer to the CURLState in CURLSocket +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Max Reitz +Message-id: <20191119153000.101646-2-mreitz@redhat.com> +Patchwork-id: 92515 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH 1/7] curl: Keep pointer to the CURLState in CURLSocket +Bugzilla: 1744602 +RH-Acked-by: Maxim Levitsky +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Stefano Garzarella + +A follow-up patch will make curl_multi_do() and curl_multi_read() take a +CURLSocket instead of the CURLState. They still need the latter, +though, so add a pointer to it to the former. + +Cc: qemu-stable@nongnu.org +Signed-off-by: Max Reitz +Reviewed-by: John Snow +Message-id: 20190910124136.10565-2-mreitz@redhat.com +Reviewed-by: Maxim Levitsky +Signed-off-by: Max Reitz +(cherry picked from commit 0487861685294660b23bc146e1ebd5304aa8bbe0) +Signed-off-by: Max Reitz +Signed-off-by: Danilo C. L. de Paula +--- + block/curl.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/block/curl.c b/block/curl.c +index f0df33a..fa602d1 100644 +--- a/block/curl.c ++++ b/block/curl.c +@@ -89,6 +89,7 @@ static CURLMcode __curl_multi_socket_action(CURLM *multi_handle, + #define CURL_BLOCK_OPT_PROXY_PASSWORD_SECRET "proxy-password-secret" + + struct BDRVCURLState; ++struct CURLState; + + static bool libcurl_initialized; + +@@ -106,6 +107,7 @@ typedef struct CURLAIOCB { + + typedef struct CURLSocket { + int fd; ++ struct CURLState *state; + QLIST_ENTRY(CURLSocket) next; + } CURLSocket; + +@@ -189,6 +191,7 @@ static int curl_sock_cb(CURL *curl, curl_socket_t fd, int action, + if (!socket) { + socket = g_new0(CURLSocket, 1); + socket->fd = fd; ++ socket->state = state; + QLIST_INSERT_HEAD(&state->sockets, socket, next); + } + socket = NULL; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-curl-Keep-socket-until-the-end-of-curl_sock_cb.patch b/SOURCES/kvm-curl-Keep-socket-until-the-end-of-curl_sock_cb.patch new file mode 100644 index 0000000..1ed321a --- /dev/null +++ b/SOURCES/kvm-curl-Keep-socket-until-the-end-of-curl_sock_cb.patch @@ -0,0 +1,72 @@ +From 46598620c18de69d9565e662a47d2615984cc49b Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Tue, 19 Nov 2019 15:29:55 +0000 +Subject: [PATCH 3/8] curl: Keep *socket until the end of curl_sock_cb() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Max Reitz +Message-id: <20191119153000.101646-3-mreitz@redhat.com> +Patchwork-id: 92517 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH 2/7] curl: Keep *socket until the end of curl_sock_cb() +Bugzilla: 1744602 +RH-Acked-by: Maxim Levitsky +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Stefano Garzarella + +This does not really change anything, but it makes the code a bit easier +to follow once we use @socket as the opaque pointer for +aio_set_fd_handler(). + +Cc: qemu-stable@nongnu.org +Signed-off-by: Max Reitz +Message-id: 20190910124136.10565-3-mreitz@redhat.com +Reviewed-by: Maxim Levitsky +Reviewed-by: John Snow +Signed-off-by: Max Reitz +(cherry picked from commit 007f339b1099af46a008dac438ca0943e31dba72) +Signed-off-by: Max Reitz +Signed-off-by: Danilo C. L. de Paula +--- + block/curl.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/block/curl.c b/block/curl.c +index fa602d1..b3fe09f 100644 +--- a/block/curl.c ++++ b/block/curl.c +@@ -181,10 +181,6 @@ static int curl_sock_cb(CURL *curl, curl_socket_t fd, int action, + + QLIST_FOREACH(socket, &state->sockets, next) { + if (socket->fd == fd) { +- if (action == CURL_POLL_REMOVE) { +- QLIST_REMOVE(socket, next); +- g_free(socket); +- } + break; + } + } +@@ -194,7 +190,6 @@ static int curl_sock_cb(CURL *curl, curl_socket_t fd, int action, + socket->state = state; + QLIST_INSERT_HEAD(&state->sockets, socket, next); + } +- socket = NULL; + + DPRINTF("CURL (AIO): Sock action %d on fd %d\n", action, (int)fd); + switch (action) { +@@ -216,6 +211,11 @@ static int curl_sock_cb(CURL *curl, curl_socket_t fd, int action, + break; + } + ++ if (action == CURL_POLL_REMOVE) { ++ QLIST_REMOVE(socket, next); ++ g_free(socket); ++ } ++ + return 0; + } + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-curl-Pass-CURLSocket-to-curl_multi_do.patch b/SOURCES/kvm-curl-Pass-CURLSocket-to-curl_multi_do.patch new file mode 100644 index 0000000..6879fb2 --- /dev/null +++ b/SOURCES/kvm-curl-Pass-CURLSocket-to-curl_multi_do.patch @@ -0,0 +1,93 @@ +From 37acfe84ccbc4cc050e7be0ba9c8c4134a7b004e Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Tue, 19 Nov 2019 15:29:57 +0000 +Subject: [PATCH 5/8] curl: Pass CURLSocket to curl_multi_do() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Max Reitz +Message-id: <20191119153000.101646-5-mreitz@redhat.com> +Patchwork-id: 92518 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH 4/7] curl: Pass CURLSocket to curl_multi_do() +Bugzilla: 1744602 +RH-Acked-by: Maxim Levitsky +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Stefano Garzarella + +curl_multi_do_locked() currently marks all sockets as ready. That is +not only inefficient, but in fact unsafe (the loop is). A follow-up +patch will change that, but to do so, curl_multi_do_locked() needs to +know exactly which socket is ready; and that is accomplished by this +patch here. + +Cc: qemu-stable@nongnu.org +Signed-off-by: Max Reitz +Message-id: 20190910124136.10565-5-mreitz@redhat.com +Reviewed-by: Maxim Levitsky +Reviewed-by: John Snow +Signed-off-by: Max Reitz +(cherry picked from commit 9dbad87d25587ff640ef878f7b6159fc368ff541) +Signed-off-by: Max Reitz +Signed-off-by: Danilo C. L. de Paula +--- + block/curl.c | 20 +++++++++++--------- + 1 file changed, 11 insertions(+), 9 deletions(-) + +diff --git a/block/curl.c b/block/curl.c +index 8f31594..de00ec8 100644 +--- a/block/curl.c ++++ b/block/curl.c +@@ -194,15 +194,15 @@ static int curl_sock_cb(CURL *curl, curl_socket_t fd, int action, + switch (action) { + case CURL_POLL_IN: + aio_set_fd_handler(s->aio_context, fd, false, +- curl_multi_do, NULL, NULL, state); ++ curl_multi_do, NULL, NULL, socket); + break; + case CURL_POLL_OUT: + aio_set_fd_handler(s->aio_context, fd, false, +- NULL, curl_multi_do, NULL, state); ++ NULL, curl_multi_do, NULL, socket); + break; + case CURL_POLL_INOUT: + aio_set_fd_handler(s->aio_context, fd, false, +- curl_multi_do, curl_multi_do, NULL, state); ++ curl_multi_do, curl_multi_do, NULL, socket); + break; + case CURL_POLL_REMOVE: + aio_set_fd_handler(s->aio_context, fd, false, +@@ -401,9 +401,10 @@ static void curl_multi_check_completion(BDRVCURLState *s) + } + + /* Called with s->mutex held. */ +-static void curl_multi_do_locked(CURLState *s) ++static void curl_multi_do_locked(CURLSocket *ready_socket) + { + CURLSocket *socket, *next_socket; ++ CURLState *s = ready_socket->state; + int running; + int r; + +@@ -422,12 +423,13 @@ static void curl_multi_do_locked(CURLState *s) + + static void curl_multi_do(void *arg) + { +- CURLState *s = (CURLState *)arg; ++ CURLSocket *socket = arg; ++ BDRVCURLState *s = socket->state->s; + +- qemu_mutex_lock(&s->s->mutex); +- curl_multi_do_locked(s); +- curl_multi_check_completion(s->s); +- qemu_mutex_unlock(&s->s->mutex); ++ qemu_mutex_lock(&s->mutex); ++ curl_multi_do_locked(socket); ++ curl_multi_check_completion(s); ++ qemu_mutex_unlock(&s->mutex); + } + + static void curl_multi_timeout_do(void *arg) +-- +1.8.3.1 + diff --git a/SOURCES/kvm-curl-Report-only-ready-sockets.patch b/SOURCES/kvm-curl-Report-only-ready-sockets.patch new file mode 100644 index 0000000..06db6e3 --- /dev/null +++ b/SOURCES/kvm-curl-Report-only-ready-sockets.patch @@ -0,0 +1,77 @@ +From 70c7a568e3c1384704228622990d6aaa2350e44e Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Tue, 19 Nov 2019 15:29:58 +0000 +Subject: [PATCH 6/8] curl: Report only ready sockets +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Max Reitz +Message-id: <20191119153000.101646-6-mreitz@redhat.com> +Patchwork-id: 92519 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH 5/7] curl: Report only ready sockets +Bugzilla: 1744602 +RH-Acked-by: Maxim Levitsky +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Stefano Garzarella + +Instead of reporting all sockets to cURL, only report the one that has +caused curl_multi_do_locked() to be called. This lets us get rid of the +QLIST_FOREACH_SAFE() list, which was actually wrong: SAFE foreaches are +only safe when the current element is removed in each iteration. If it +possible for the list to be concurrently modified, we cannot guarantee +that only the current element will be removed. Therefore, we must not +use QLIST_FOREACH_SAFE() here. + +Fixes: ff5ca1664af85b24a4180d595ea6873fd3deac57 +Cc: qemu-stable@nongnu.org +Signed-off-by: Max Reitz +Message-id: 20190910124136.10565-6-mreitz@redhat.com +Reviewed-by: Maxim Levitsky +Reviewed-by: John Snow +Signed-off-by: Max Reitz +(cherry picked from commit 9abaf9fc474c3dd53e8e119326abc774c977c331) +Signed-off-by: Max Reitz +Signed-off-by: Danilo C. L. de Paula +--- + block/curl.c | 17 ++++++----------- + 1 file changed, 6 insertions(+), 11 deletions(-) + +diff --git a/block/curl.c b/block/curl.c +index de00ec8..f776615 100644 +--- a/block/curl.c ++++ b/block/curl.c +@@ -401,24 +401,19 @@ static void curl_multi_check_completion(BDRVCURLState *s) + } + + /* Called with s->mutex held. */ +-static void curl_multi_do_locked(CURLSocket *ready_socket) ++static void curl_multi_do_locked(CURLSocket *socket) + { +- CURLSocket *socket, *next_socket; +- CURLState *s = ready_socket->state; ++ BDRVCURLState *s = socket->state->s; + int running; + int r; + +- if (!s->s->multi) { ++ if (!s->multi) { + return; + } + +- /* Need to use _SAFE because curl_multi_socket_action() may trigger +- * curl_sock_cb() which might modify this list */ +- QLIST_FOREACH_SAFE(socket, &s->sockets, next, next_socket) { +- do { +- r = curl_multi_socket_action(s->s->multi, socket->fd, 0, &running); +- } while (r == CURLM_CALL_MULTI_PERFORM); +- } ++ do { ++ r = curl_multi_socket_action(s->multi, socket->fd, 0, &running); ++ } while (r == CURLM_CALL_MULTI_PERFORM); + } + + static void curl_multi_do(void *arg) +-- +1.8.3.1 + diff --git a/SOURCES/kvm-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-exec-Fix-MAP_RAM-for-cached-access.patch b/SOURCES/kvm-exec-Fix-MAP_RAM-for-cached-access.patch new file mode 100644 index 0000000..2e0849b --- /dev/null +++ b/SOURCES/kvm-exec-Fix-MAP_RAM-for-cached-access.patch @@ -0,0 +1,271 @@ +From 064565e76b986a42d9cdcba72965887528cea90a Mon Sep 17 00:00:00 2001 +From: Maxim Levitsky +Date: Sun, 22 Dec 2019 11:02:06 +0100 +Subject: [PATCH 1/7] exec: Fix MAP_RAM for cached access + +RH-Author: Maxim Levitsky +Message-id: <20191222110207.21384-2-mlevitsk@redhat.com> +Patchwork-id: 93207 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH 1/2] exec: Fix MAP_RAM for cached access +Bugzilla: 1769613 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Cornelia Huck +RH-Acked-by: Peter Xu + +From: Eric Auger + +When an IOMMUMemoryRegion is in front of a virtio device, +address_space_cache_init does not set cache->ptr as the memory +region is not RAM. However when the device performs an access, +we end up in glue() which performs the translation and then uses +MAP_RAM. This latter uses the unset ptr and returns a wrong value +which leads to a SIGSEV in address_space_lduw_internal_cached_slow, +for instance. + +In slow path cache->ptr is NULL and MAP_RAM must redirect to +qemu_map_ram_ptr((mr)->ram_block, ofs). + +As MAP_RAM, IS_DIRECT and INVALIDATE are the same in _cached_slow +and non cached mode, let's remove those macros. + +This fixes the use cases featuring vIOMMU (Intel and ARM SMMU) +which lead to a SIGSEV. + +Fixes: 48564041a73a (exec: reintroduce MemoryRegion caching) +Signed-off-by: Eric Auger + +Message-Id: <1528895946-28677-1-git-send-email-eric.auger@redhat.com> +Signed-off-by: Paolo Bonzini +(cherry picked from commit a99761d3c85679da380c0f597468acd3dc1b53b3) +Signed-off-by: Maxim Levitsky +Signed-off-by: Miroslav Rezanina +--- + exec.c | 6 ------ + memory_ldst.inc.c | 47 ++++++++++++++++++++++------------------------- + 2 files changed, 22 insertions(+), 31 deletions(-) + +diff --git a/exec.c b/exec.c +index 9112d8b..86218ef 100644 +--- a/exec.c ++++ b/exec.c +@@ -3608,9 +3608,6 @@ void cpu_physical_memory_unmap(void *buffer, hwaddr len, + #define ARG1 as + #define SUFFIX + #define TRANSLATE(...) address_space_translate(as, __VA_ARGS__) +-#define IS_DIRECT(mr, is_write) memory_access_is_direct(mr, is_write) +-#define MAP_RAM(mr, ofs) qemu_map_ram_ptr((mr)->ram_block, ofs) +-#define INVALIDATE(mr, ofs, len) invalidate_and_set_dirty(mr, ofs, len) + #define RCU_READ_LOCK(...) rcu_read_lock() + #define RCU_READ_UNLOCK(...) rcu_read_unlock() + #include "memory_ldst.inc.c" +@@ -3643,9 +3640,6 @@ void address_space_cache_destroy(MemoryRegionCache *cache) + #define SUFFIX _cached + #define TRANSLATE(addr, ...) \ + address_space_translate(cache->as, cache->xlat + (addr), __VA_ARGS__) +-#define IS_DIRECT(mr, is_write) true +-#define MAP_RAM(mr, ofs) qemu_map_ram_ptr((mr)->ram_block, ofs) +-#define INVALIDATE(mr, ofs, len) invalidate_and_set_dirty(mr, ofs, len) + #define RCU_READ_LOCK() rcu_read_lock() + #define RCU_READ_UNLOCK() rcu_read_unlock() + #include "memory_ldst.inc.c" +diff --git a/memory_ldst.inc.c b/memory_ldst.inc.c +index 5dbff9c..a30060c 100644 +--- a/memory_ldst.inc.c ++++ b/memory_ldst.inc.c +@@ -34,7 +34,7 @@ static inline uint32_t glue(address_space_ldl_internal, SUFFIX)(ARG1_DECL, + + RCU_READ_LOCK(); + mr = TRANSLATE(addr, &addr1, &l, false); +- if (l < 4 || !IS_DIRECT(mr, false)) { ++ if (l < 4 || !memory_access_is_direct(mr, false)) { + release_lock |= prepare_mmio_access(mr); + + /* I/O case */ +@@ -50,7 +50,7 @@ static inline uint32_t glue(address_space_ldl_internal, SUFFIX)(ARG1_DECL, + #endif + } else { + /* RAM case */ +- ptr = MAP_RAM(mr, addr1); ++ ptr = qemu_map_ram_ptr(mr->ram_block, addr1); + switch (endian) { + case DEVICE_LITTLE_ENDIAN: + val = ldl_le_p(ptr); +@@ -128,7 +128,7 @@ static inline uint64_t glue(address_space_ldq_internal, SUFFIX)(ARG1_DECL, + + RCU_READ_LOCK(); + mr = TRANSLATE(addr, &addr1, &l, false); +- if (l < 8 || !IS_DIRECT(mr, false)) { ++ if (l < 8 || !memory_access_is_direct(mr, false)) { + release_lock |= prepare_mmio_access(mr); + + /* I/O case */ +@@ -144,7 +144,7 @@ static inline uint64_t glue(address_space_ldq_internal, SUFFIX)(ARG1_DECL, + #endif + } else { + /* RAM case */ +- ptr = MAP_RAM(mr, addr1); ++ ptr = qemu_map_ram_ptr(mr->ram_block, addr1); + switch (endian) { + case DEVICE_LITTLE_ENDIAN: + val = ldq_le_p(ptr); +@@ -220,14 +220,14 @@ uint32_t glue(address_space_ldub, SUFFIX)(ARG1_DECL, + + RCU_READ_LOCK(); + mr = TRANSLATE(addr, &addr1, &l, false); +- if (!IS_DIRECT(mr, false)) { ++ if (!memory_access_is_direct(mr, false)) { + release_lock |= prepare_mmio_access(mr); + + /* I/O case */ + r = memory_region_dispatch_read(mr, addr1, &val, 1, attrs); + } else { + /* RAM case */ +- ptr = MAP_RAM(mr, addr1); ++ ptr = qemu_map_ram_ptr(mr->ram_block, addr1); + val = ldub_p(ptr); + r = MEMTX_OK; + } +@@ -262,7 +262,7 @@ static inline uint32_t glue(address_space_lduw_internal, SUFFIX)(ARG1_DECL, + + RCU_READ_LOCK(); + mr = TRANSLATE(addr, &addr1, &l, false); +- if (l < 2 || !IS_DIRECT(mr, false)) { ++ if (l < 2 || !memory_access_is_direct(mr, false)) { + release_lock |= prepare_mmio_access(mr); + + /* I/O case */ +@@ -278,7 +278,7 @@ static inline uint32_t glue(address_space_lduw_internal, SUFFIX)(ARG1_DECL, + #endif + } else { + /* RAM case */ +- ptr = MAP_RAM(mr, addr1); ++ ptr = qemu_map_ram_ptr(mr->ram_block, addr1); + switch (endian) { + case DEVICE_LITTLE_ENDIAN: + val = lduw_le_p(ptr); +@@ -357,12 +357,12 @@ void glue(address_space_stl_notdirty, SUFFIX)(ARG1_DECL, + + RCU_READ_LOCK(); + mr = TRANSLATE(addr, &addr1, &l, true); +- if (l < 4 || !IS_DIRECT(mr, true)) { ++ if (l < 4 || !memory_access_is_direct(mr, true)) { + release_lock |= prepare_mmio_access(mr); + + r = memory_region_dispatch_write(mr, addr1, val, 4, attrs); + } else { +- ptr = MAP_RAM(mr, addr1); ++ ptr = qemu_map_ram_ptr(mr->ram_block, addr1); + stl_p(ptr, val); + + dirty_log_mask = memory_region_get_dirty_log_mask(mr); +@@ -400,7 +400,7 @@ static inline void glue(address_space_stl_internal, SUFFIX)(ARG1_DECL, + + RCU_READ_LOCK(); + mr = TRANSLATE(addr, &addr1, &l, true); +- if (l < 4 || !IS_DIRECT(mr, true)) { ++ if (l < 4 || !memory_access_is_direct(mr, true)) { + release_lock |= prepare_mmio_access(mr); + + #if defined(TARGET_WORDS_BIGENDIAN) +@@ -415,7 +415,7 @@ static inline void glue(address_space_stl_internal, SUFFIX)(ARG1_DECL, + r = memory_region_dispatch_write(mr, addr1, val, 4, attrs); + } else { + /* RAM case */ +- ptr = MAP_RAM(mr, addr1); ++ ptr = qemu_map_ram_ptr(mr->ram_block, addr1); + switch (endian) { + case DEVICE_LITTLE_ENDIAN: + stl_le_p(ptr, val); +@@ -427,7 +427,7 @@ static inline void glue(address_space_stl_internal, SUFFIX)(ARG1_DECL, + stl_p(ptr, val); + break; + } +- INVALIDATE(mr, addr1, 4); ++ invalidate_and_set_dirty(mr, addr1, 4); + r = MEMTX_OK; + } + if (result) { +@@ -490,14 +490,14 @@ void glue(address_space_stb, SUFFIX)(ARG1_DECL, + + RCU_READ_LOCK(); + mr = TRANSLATE(addr, &addr1, &l, true); +- if (!IS_DIRECT(mr, true)) { ++ if (!memory_access_is_direct(mr, true)) { + release_lock |= prepare_mmio_access(mr); + r = memory_region_dispatch_write(mr, addr1, val, 1, attrs); + } else { + /* RAM case */ +- ptr = MAP_RAM(mr, addr1); ++ ptr = qemu_map_ram_ptr(mr->ram_block, addr1); + stb_p(ptr, val); +- INVALIDATE(mr, addr1, 1); ++ invalidate_and_set_dirty(mr, addr1, 1); + r = MEMTX_OK; + } + if (result) { +@@ -529,7 +529,7 @@ static inline void glue(address_space_stw_internal, SUFFIX)(ARG1_DECL, + + RCU_READ_LOCK(); + mr = TRANSLATE(addr, &addr1, &l, true); +- if (l < 2 || !IS_DIRECT(mr, true)) { ++ if (l < 2 || !memory_access_is_direct(mr, true)) { + release_lock |= prepare_mmio_access(mr); + + #if defined(TARGET_WORDS_BIGENDIAN) +@@ -544,7 +544,7 @@ static inline void glue(address_space_stw_internal, SUFFIX)(ARG1_DECL, + r = memory_region_dispatch_write(mr, addr1, val, 2, attrs); + } else { + /* RAM case */ +- ptr = MAP_RAM(mr, addr1); ++ ptr = qemu_map_ram_ptr(mr->ram_block, addr1); + switch (endian) { + case DEVICE_LITTLE_ENDIAN: + stw_le_p(ptr, val); +@@ -556,7 +556,7 @@ static inline void glue(address_space_stw_internal, SUFFIX)(ARG1_DECL, + stw_p(ptr, val); + break; + } +- INVALIDATE(mr, addr1, 2); ++ invalidate_and_set_dirty(mr, addr1, 2); + r = MEMTX_OK; + } + if (result) { +@@ -620,7 +620,7 @@ static void glue(address_space_stq_internal, SUFFIX)(ARG1_DECL, + + RCU_READ_LOCK(); + mr = TRANSLATE(addr, &addr1, &l, true); +- if (l < 8 || !IS_DIRECT(mr, true)) { ++ if (l < 8 || !memory_access_is_direct(mr, true)) { + release_lock |= prepare_mmio_access(mr); + + #if defined(TARGET_WORDS_BIGENDIAN) +@@ -635,7 +635,7 @@ static void glue(address_space_stq_internal, SUFFIX)(ARG1_DECL, + r = memory_region_dispatch_write(mr, addr1, val, 8, attrs); + } else { + /* RAM case */ +- ptr = MAP_RAM(mr, addr1); ++ ptr = qemu_map_ram_ptr(mr->ram_block, addr1); + switch (endian) { + case DEVICE_LITTLE_ENDIAN: + stq_le_p(ptr, val); +@@ -647,7 +647,7 @@ static void glue(address_space_stq_internal, SUFFIX)(ARG1_DECL, + stq_p(ptr, val); + break; + } +- INVALIDATE(mr, addr1, 8); ++ invalidate_and_set_dirty(mr, addr1, 8); + r = MEMTX_OK; + } + if (result) { +@@ -702,8 +702,5 @@ void glue(stq_be_phys, SUFFIX)(ARG1_DECL, hwaddr addr, uint64_t val) + #undef ARG1 + #undef SUFFIX + #undef TRANSLATE +-#undef IS_DIRECT +-#undef MAP_RAM +-#undef INVALIDATE + #undef RCU_READ_LOCK + #undef RCU_READ_UNLOCK +-- +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-fw_cfg-Fix-boot-bootsplash-error-checking.patch b/SOURCES/kvm-fw_cfg-Fix-boot-bootsplash-error-checking.patch new file mode 100644 index 0000000..c838f38 --- /dev/null +++ b/SOURCES/kvm-fw_cfg-Fix-boot-bootsplash-error-checking.patch @@ -0,0 +1,122 @@ +From f798645d16957453ee49a5a2945ed80eeb87cd15 Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Mon, 7 Oct 2019 07:35:07 +0100 +Subject: [PATCH 14/22] fw_cfg: Fix -boot bootsplash error checking +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Markus Armbruster +Message-id: <20191007073509.5887-3-armbru@redhat.com> +Patchwork-id: 90980 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH v2 2/4] fw_cfg: Fix -boot bootsplash error checking +Bugzilla: 1607367 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Laszlo Ersek + +From: Li Qiang + +fw_cfg_bootsplash() gets option parameter "splash-time" +with qemu_opt_get(), then converts it to an integer by hand. +It neglects to check that conversion for errors. This is +needlessly complicated and error-prone. But as "splash-time +not specified" is not the same as "splash-time=T" for any T, +we need use qemu_opt_get() to check if splash time exists. +This patch also make the qemu exit when finding or loading +splash file failed. + +Signed-off-by: Li Qiang +Reviewed-by: Markus Armbruster +Reviewed-by: Gerd Hoffmann +Reviewed-by: Philippe Mathieu-Daudé +Message-Id: <1542777026-2788-2-git-send-email-liq3ea@gmail.com> +Signed-off-by: Philippe Mathieu-Daudé +(cherry picked from commit 6912bb0b3d3b140c70d8cdfd2dff77f9890d7f12) +Signed-off-by: Danilo C. L. de Paula +--- + hw/nvram/fw_cfg.c | 35 +++++++++++++---------------------- + vl.c | 2 +- + 2 files changed, 14 insertions(+), 23 deletions(-) + +diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c +index d35ac7b..d7185ea 100644 +--- a/hw/nvram/fw_cfg.c ++++ b/hw/nvram/fw_cfg.c +@@ -117,47 +117,38 @@ error: + + static void fw_cfg_bootsplash(FWCfgState *s) + { +- int boot_splash_time = -1; + const char *boot_splash_filename = NULL; +- char *p; ++ const char *boot_splash_time = NULL; + char *filename, *file_data; + gsize file_size; + int file_type; +- const char *temp; + + /* get user configuration */ + QemuOptsList *plist = qemu_find_opts("boot-opts"); + QemuOpts *opts = QTAILQ_FIRST(&plist->head); +- if (opts != NULL) { +- temp = qemu_opt_get(opts, "splash"); +- if (temp != NULL) { +- boot_splash_filename = temp; +- } +- temp = qemu_opt_get(opts, "splash-time"); +- if (temp != NULL) { +- p = (char *)temp; +- boot_splash_time = strtol(p, &p, 10); +- } +- } ++ boot_splash_filename = qemu_opt_get(opts, "splash"); ++ boot_splash_time = qemu_opt_get(opts, "splash-time"); + + /* insert splash time if user configurated */ +- if (boot_splash_time >= 0) { ++ if (boot_splash_time) { ++ int64_t bst_val = qemu_opt_get_number(opts, "splash-time", -1); + /* validate the input */ +- if (boot_splash_time > 0xffff) { +- error_report("splash time is big than 65535, force it to 65535."); +- boot_splash_time = 0xffff; ++ if (bst_val < 0 || bst_val > 0xffff) { ++ error_report("splash-time is invalid," ++ "it should be a value between 0 and 65535"); ++ exit(1); + } + /* use little endian format */ +- qemu_extra_params_fw[0] = (uint8_t)(boot_splash_time & 0xff); +- qemu_extra_params_fw[1] = (uint8_t)((boot_splash_time >> 8) & 0xff); ++ qemu_extra_params_fw[0] = (uint8_t)(bst_val & 0xff); ++ qemu_extra_params_fw[1] = (uint8_t)((bst_val >> 8) & 0xff); + fw_cfg_add_file(s, "etc/boot-menu-wait", qemu_extra_params_fw, 2); + } + + /* insert splash file if user configurated */ +- if (boot_splash_filename != NULL) { ++ if (boot_splash_filename) { + filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, boot_splash_filename); + if (filename == NULL) { +- error_report("failed to find file '%s'.", boot_splash_filename); ++ error_report("failed to find file '%s'", boot_splash_filename); + return; + } + +diff --git a/vl.c b/vl.c +index c778594..e2212f5 100644 +--- a/vl.c ++++ b/vl.c +@@ -364,7 +364,7 @@ static QemuOptsList qemu_boot_opts = { + .type = QEMU_OPT_STRING, + }, { + .name = "splash-time", +- .type = QEMU_OPT_STRING, ++ .type = QEMU_OPT_NUMBER, + }, { + .name = "reboot-timeout", + .type = QEMU_OPT_STRING, +-- +1.8.3.1 + diff --git a/SOURCES/kvm-fw_cfg-Fix-boot-reboot-timeout-error-checking.patch b/SOURCES/kvm-fw_cfg-Fix-boot-reboot-timeout-error-checking.patch new file mode 100644 index 0000000..188ceb4 --- /dev/null +++ b/SOURCES/kvm-fw_cfg-Fix-boot-reboot-timeout-error-checking.patch @@ -0,0 +1,99 @@ +From 07c499baed0c800e43cd6ec867fc465dea43567d Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Mon, 7 Oct 2019 07:35:08 +0100 +Subject: [PATCH 15/22] fw_cfg: Fix -boot reboot-timeout error checking +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Markus Armbruster +Message-id: <20191007073509.5887-4-armbru@redhat.com> +Patchwork-id: 90979 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH v2 3/4] fw_cfg: Fix -boot reboot-timeout error checking +Bugzilla: 1607367 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Laszlo Ersek + +From: Li Qiang + +fw_cfg_reboot() gets option parameter "reboot-timeout" with +qemu_opt_get(), then converts it to an integer by hand. It neglects to +check that conversion for errors, and fails to reject negative values. +Positive values above the limit get reported and replaced by the limit. +This patch checks for conversion errors properly, and reject all values +outside 0...0xffff. + +Signed-off-by: Li Qiang +Reviewed-by: Markus Armbruster +Reviewed-by: Gerd Hoffmann +Reviewed-by: Philippe Mathieu-Daudé +Message-Id: <1542777026-2788-3-git-send-email-liq3ea@gmail.com> +Signed-off-by: Philippe Mathieu-Daudé +(cherry picked from commit ee5d0f89de3e53cdb0dcf51acc1502b310ed3bd2) +Signed-off-by: Danilo C. L. de Paula +--- + hw/nvram/fw_cfg.c | 27 +++++++++++++-------------- + vl.c | 2 +- + 2 files changed, 14 insertions(+), 15 deletions(-) + +diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c +index d7185ea..02ab458 100644 +--- a/hw/nvram/fw_cfg.c ++++ b/hw/nvram/fw_cfg.c +@@ -176,26 +176,25 @@ static void fw_cfg_bootsplash(FWCfgState *s) + + static void fw_cfg_reboot(FWCfgState *s) + { +- int reboot_timeout = -1; +- char *p; +- const char *temp; ++ const char *reboot_timeout = NULL; ++ int64_t rt_val = -1; + + /* get user configuration */ + QemuOptsList *plist = qemu_find_opts("boot-opts"); + QemuOpts *opts = QTAILQ_FIRST(&plist->head); +- if (opts != NULL) { +- temp = qemu_opt_get(opts, "reboot-timeout"); +- if (temp != NULL) { +- p = (char *)temp; +- reboot_timeout = strtol(p, &p, 10); ++ reboot_timeout = qemu_opt_get(opts, "reboot-timeout"); ++ ++ if (reboot_timeout) { ++ rt_val = qemu_opt_get_number(opts, "reboot-timeout", -1); ++ /* validate the input */ ++ if (rt_val < 0 || rt_val > 0xffff) { ++ error_report("reboot timeout is invalid," ++ "it should be a value between 0 and 65535"); ++ exit(1); + } + } +- /* validate the input */ +- if (reboot_timeout > 0xffff) { +- error_report("reboot timeout is larger than 65535, force it to 65535."); +- reboot_timeout = 0xffff; +- } +- fw_cfg_add_file(s, "etc/boot-fail-wait", g_memdup(&reboot_timeout, 4), 4); ++ ++ fw_cfg_add_file(s, "etc/boot-fail-wait", g_memdup(&rt_val, 4), 4); + } + + static void fw_cfg_write(FWCfgState *s, uint8_t value) +diff --git a/vl.c b/vl.c +index e2212f5..3cee95f 100644 +--- a/vl.c ++++ b/vl.c +@@ -367,7 +367,7 @@ static QemuOptsList qemu_boot_opts = { + .type = QEMU_OPT_NUMBER, + }, { + .name = "reboot-timeout", +- .type = QEMU_OPT_STRING, ++ .type = QEMU_OPT_NUMBER, + }, { + .name = "strict", + .type = QEMU_OPT_BOOL, +-- +1.8.3.1 + diff --git a/SOURCES/kvm-fw_cfg-Improve-error-message-when-can-t-load-splash-.patch b/SOURCES/kvm-fw_cfg-Improve-error-message-when-can-t-load-splash-.patch new file mode 100644 index 0000000..f9ca4b2 --- /dev/null +++ b/SOURCES/kvm-fw_cfg-Improve-error-message-when-can-t-load-splash-.patch @@ -0,0 +1,62 @@ +From f11136998ed22e121b0a9df26f83e252bd5918fa Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Mon, 7 Oct 2019 07:35:06 +0100 +Subject: [PATCH 13/22] fw_cfg: Improve error message when can't load splash + file +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Markus Armbruster +Message-id: <20191007073509.5887-2-armbru@redhat.com> +Patchwork-id: 90978 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH v2 1/4] fw_cfg: Improve error message when can't load splash file +Bugzilla: 1607367 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Laszlo Ersek + +From: Li Qiang + +read_splashfile() reports "failed to read splash file" without +further details. Get the details from g_file_get_contents(), and +include them in the error message. Also remove unnecessary 'res' +variable. + +Signed-off-by: Li Qiang +Reviewed-by: Markus Armbruster +Reviewed-by: Philippe Mathieu-Daudé +Message-Id: <1541052148-28752-1-git-send-email-liq3ea@gmail.com> +Signed-off-by: Philippe Mathieu-Daudé +(cherry picked from commit bed66336771ecdcb788d394bdd081a78b843e509) +Signed-off-by: Danilo C. L. de Paula +--- + hw/nvram/fw_cfg.c | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c +index 2a0739d..d35ac7b 100644 +--- a/hw/nvram/fw_cfg.c ++++ b/hw/nvram/fw_cfg.c +@@ -68,15 +68,14 @@ static char *read_splashfile(char *filename, gsize *file_sizep, + int *file_typep) + { + GError *err = NULL; +- gboolean res; + gchar *content; + int file_type; + unsigned int filehead; + int bmp_bpp; + +- res = g_file_get_contents(filename, &content, file_sizep, &err); +- if (res == FALSE) { +- error_report("failed to read splash file '%s'", filename); ++ if (!g_file_get_contents(filename, &content, file_sizep, &err)) { ++ error_report("failed to read splash file '%s': %s", ++ filename, err->message); + g_error_free(err); + return NULL; + } +-- +1.8.3.1 + diff --git a/SOURCES/kvm-gluster-Handle-changed-glfs_ftruncate-signature.patch b/SOURCES/kvm-gluster-Handle-changed-glfs_ftruncate-signature.patch new file mode 100644 index 0000000..711e67c --- /dev/null +++ b/SOURCES/kvm-gluster-Handle-changed-glfs_ftruncate-signature.patch @@ -0,0 +1,97 @@ +From a30344defca0e948400587280f67d4e6bcc5834f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Wed, 19 Jun 2019 17:15:07 +0200 +Subject: [PATCH 1/2] gluster: Handle changed glfs_ftruncate signature +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Philippe Mathieu-Daudé +Message-id: <20190619171508.31981-2-philmd@redhat.com> +Patchwork-id: 88737 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 1/2] gluster: Handle changed glfs_ftruncate signature +Bugzilla: 1721983 +RH-Acked-by: Max Reitz +RH-Acked-by: Niels de Vos +RH-Acked-by: Miroslav Rezanina + +From: Prasanna Kumar Kalever + +New versions of Glusters libgfapi.so have an updated glfs_ftruncate() +function that returns additional 'struct stat' structures to enable +advanced caching of attributes. This is useful for file servers, not so +much for QEMU. Nevertheless, the API has changed and needs to be +adopted. + +Signed-off-by: Prasanna Kumar Kalever +Signed-off-by: Niels de Vos +Signed-off-by: Kevin Wolf +(cherry picked from commit e014dbe74e0484188164c61ff6843f8a04a8cb9d) +Signed-off-by: Philippe Mathieu-Daudé +Signed-off-by: Miroslav Rezanina +--- + block/gluster.c | 4 ++++ + configure | 18 ++++++++++++++++++ + 2 files changed, 22 insertions(+) + +diff --git a/block/gluster.c b/block/gluster.c +index 8c13002..e3ffa61 100644 +--- a/block/gluster.c ++++ b/block/gluster.c +@@ -20,6 +20,10 @@ + #include "qemu/option.h" + #include "qemu/cutils.h" + ++#ifdef CONFIG_GLUSTERFS_FTRUNCATE_HAS_STAT ++# define glfs_ftruncate(fd, offset) glfs_ftruncate(fd, offset, NULL, NULL) ++#endif ++ + #define GLUSTER_OPT_FILENAME "filename" + #define GLUSTER_OPT_VOLUME "volume" + #define GLUSTER_OPT_PATH "path" +diff --git a/configure b/configure +index 6d61b14..b3d337b 100755 +--- a/configure ++++ b/configure +@@ -429,6 +429,7 @@ glusterfs_xlator_opt="no" + glusterfs_discard="no" + glusterfs_fallocate="no" + glusterfs_zerofill="no" ++glusterfs_ftruncate_has_stat="no" + gtk="" + gtkabi="" + gtk_gl="no" +@@ -3919,6 +3920,19 @@ if test "$glusterfs" != "no" ; then + glusterfs_fallocate="yes" + glusterfs_zerofill="yes" + fi ++ cat > $TMPC << EOF ++#include ++ ++int ++main(void) ++{ ++ /* new glfs_ftruncate() passes two additional args */ ++ return glfs_ftruncate(NULL, 0, NULL, NULL); ++} ++EOF ++ if compile_prog "$glusterfs_cflags" "$glusterfs_libs" ; then ++ glusterfs_ftruncate_has_stat="yes" ++ fi + else + if test "$glusterfs" = "yes" ; then + feature_not_found "GlusterFS backend support" \ +@@ -6622,6 +6636,10 @@ if test "$glusterfs_zerofill" = "yes" ; then + echo "CONFIG_GLUSTERFS_ZEROFILL=y" >> $config_host_mak + fi + ++if test "$glusterfs_ftruncate_has_stat" = "yes" ; then ++ echo "CONFIG_GLUSTERFS_FTRUNCATE_HAS_STAT=y" >> $config_host_mak ++fi ++ + if test "$libssh2" = "yes" ; then + echo "CONFIG_LIBSSH2=m" >> $config_host_mak + echo "LIBSSH2_CFLAGS=$libssh2_cflags" >> $config_host_mak +-- +1.8.3.1 + diff --git a/SOURCES/kvm-gluster-the-glfs_io_cbk-callback-function-pointer-ad.patch b/SOURCES/kvm-gluster-the-glfs_io_cbk-callback-function-pointer-ad.patch new file mode 100644 index 0000000..c822f7c --- /dev/null +++ b/SOURCES/kvm-gluster-the-glfs_io_cbk-callback-function-pointer-ad.patch @@ -0,0 +1,108 @@ +From 41e53f27ba80b6479c5b7fdb34eb67ceb801c65b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Wed, 19 Jun 2019 17:15:08 +0200 +Subject: [PATCH 2/2] gluster: the glfs_io_cbk callback function pointer adds + pre/post stat args +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Philippe Mathieu-Daudé +Message-id: <20190619171508.31981-3-philmd@redhat.com> +Patchwork-id: 88738 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 2/2] gluster: the glfs_io_cbk callback function pointer adds pre/post stat args +Bugzilla: 1721983 +RH-Acked-by: Max Reitz +RH-Acked-by: Niels de Vos +RH-Acked-by: Miroslav Rezanina + +From: Niels de Vos + +The glfs_*_async() functions do a callback once finished. This callback +has changed its arguments, pre- and post-stat structures have been +added. This makes it possible to improve caching, which is useful for +Samba and NFS-Ganesha, but not so much for QEMU. Gluster 6 is the first +release that includes these new arguments. + +With an additional detection in ./configure, the new arguments can +conditionally get included in the glfs_io_cbk handler. + +Signed-off-by: Niels de Vos +Signed-off-by: Kevin Wolf +(cherry picked from commit 0e3b891fefacc0e49f3c8ffa3a753b69eb7214d2) +Signed-off-by: Philippe Mathieu-Daudé +Signed-off-by: Miroslav Rezanina +--- + block/gluster.c | 6 +++++- + configure | 24 ++++++++++++++++++++++++ + 2 files changed, 29 insertions(+), 1 deletion(-) + +diff --git a/block/gluster.c b/block/gluster.c +index e3ffa61..a6ac2b1 100644 +--- a/block/gluster.c ++++ b/block/gluster.c +@@ -729,7 +729,11 @@ static struct glfs *qemu_gluster_init(BlockdevOptionsGluster *gconf, + /* + * AIO callback routine called from GlusterFS thread. + */ +-static void gluster_finish_aiocb(struct glfs_fd *fd, ssize_t ret, void *arg) ++static void gluster_finish_aiocb(struct glfs_fd *fd, ssize_t ret, ++#ifdef CONFIG_GLUSTERFS_IOCB_HAS_STAT ++ struct glfs_stat *pre, struct glfs_stat *post, ++#endif ++ void *arg) + { + GlusterAIOCB *acb = (GlusterAIOCB *)arg; + +diff --git a/configure b/configure +index b3d337b..c9a1034 100755 +--- a/configure ++++ b/configure +@@ -430,6 +430,7 @@ glusterfs_discard="no" + glusterfs_fallocate="no" + glusterfs_zerofill="no" + glusterfs_ftruncate_has_stat="no" ++glusterfs_iocb_has_stat="no" + gtk="" + gtkabi="" + gtk_gl="no" +@@ -3933,6 +3934,25 @@ EOF + if compile_prog "$glusterfs_cflags" "$glusterfs_libs" ; then + glusterfs_ftruncate_has_stat="yes" + fi ++ cat > $TMPC << EOF ++#include ++ ++/* new glfs_io_cbk() passes two additional glfs_stat structs */ ++static void ++glusterfs_iocb(glfs_fd_t *fd, ssize_t ret, struct glfs_stat *prestat, struct glfs_stat *poststat, void *data) ++{} ++ ++int ++main(void) ++{ ++ glfs_io_cbk iocb = &glusterfs_iocb; ++ iocb(NULL, 0 , NULL, NULL, NULL); ++ return 0; ++} ++EOF ++ if compile_prog "$glusterfs_cflags" "$glusterfs_libs" ; then ++ glusterfs_iocb_has_stat="yes" ++ fi + else + if test "$glusterfs" = "yes" ; then + feature_not_found "GlusterFS backend support" \ +@@ -6640,6 +6660,10 @@ if test "$glusterfs_ftruncate_has_stat" = "yes" ; then + echo "CONFIG_GLUSTERFS_FTRUNCATE_HAS_STAT=y" >> $config_host_mak + fi + ++if test "$glusterfs_iocb_has_stat" = "yes" ; then ++ echo "CONFIG_GLUSTERFS_IOCB_HAS_STAT=y" >> $config_host_mak ++fi ++ + if test "$libssh2" = "yes" ; then + echo "CONFIG_LIBSSH2=m" >> $config_host_mak + echo "LIBSSH2_CFLAGS=$libssh2_cflags" >> $config_host_mak +-- +1.8.3.1 + diff --git a/SOURCES/kvm-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-nvram-fw_cfg-Store-reboot-timeout-as-little-endia.patch b/SOURCES/kvm-hw-nvram-fw_cfg-Store-reboot-timeout-as-little-endia.patch new file mode 100644 index 0000000..058f595 --- /dev/null +++ b/SOURCES/kvm-hw-nvram-fw_cfg-Store-reboot-timeout-as-little-endia.patch @@ -0,0 +1,80 @@ +From 5bb1365ea92b83615937e3082a9c250728384989 Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Mon, 7 Oct 2019 07:35:09 +0100 +Subject: [PATCH 16/22] hw/nvram/fw_cfg: Store 'reboot-timeout' as little + endian +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Markus Armbruster +Message-id: <20191007073509.5887-5-armbru@redhat.com> +Patchwork-id: 90976 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH v2 4/4] hw/nvram/fw_cfg: Store 'reboot-timeout' as little endian +Bugzilla: 1607367 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Laszlo Ersek + +From: Li Qiang + +The current codebase is not specific about the endianess of the +fw_cfg 'file' entry 'reboot-timeout'. + +Per docs/specs/fw_cfg.txt: + + === All Other Data Items === + + Please consult the QEMU source for the most up-to-date + and authoritative list of selector keys and their respective + items' purpose, format and writeability. + +Checking the git history, this code was introduced in commit +ac05f3492421, very similar to commit 3d3b8303c6f8 for the +'boot-menu-wait' entry, which explicitely use little-endian. + +OVMF consumes 'boot-menu-wait' as little-endian, however it does +not consume 'reboot-timeout'. + +Regarding the git history and OVMF use, we choose to explicit +'reboot-timeout' endianess as little-endian. + +Signed-off-by: Li Qiang +Tested-by: Thomas Huth +Reviewed-by: Philippe Mathieu-Daudé +Tested-by: Philippe Mathieu-Daudé +Message-Id: <20190424140643.62457-4-liq3ea@163.com> +[PMD: Reword commit description based on review comments] +Signed-off-by: Philippe Mathieu-Daudé +(cherry picked from commit 04da973501b591525ce68c2925c61c8886badd4d) + +Signed-off-by: Danilo C. L. de Paula +--- + hw/nvram/fw_cfg.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/hw/nvram/fw_cfg.c b/hw/nvram/fw_cfg.c +index 02ab458..954de33 100644 +--- a/hw/nvram/fw_cfg.c ++++ b/hw/nvram/fw_cfg.c +@@ -178,6 +178,7 @@ static void fw_cfg_reboot(FWCfgState *s) + { + const char *reboot_timeout = NULL; + int64_t rt_val = -1; ++ uint32_t rt_le32; + + /* get user configuration */ + QemuOptsList *plist = qemu_find_opts("boot-opts"); +@@ -194,7 +195,8 @@ static void fw_cfg_reboot(FWCfgState *s) + } + } + +- fw_cfg_add_file(s, "etc/boot-fail-wait", g_memdup(&rt_val, 4), 4); ++ rt_le32 = cpu_to_le32(rt_val); ++ fw_cfg_add_file(s, "etc/boot-fail-wait", g_memdup(&rt_le32, 4), 4); + } + + static void fw_cfg_write(FWCfgState *s, uint8_t value) +-- +1.8.3.1 + diff --git a/SOURCES/kvm-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 new file mode 100644 index 0000000..6a7fe3c --- /dev/null +++ b/SOURCES/kvm-i386-Add-CPUID-bit-and-feature-words-for-IA32_ARCH_C.patch @@ -0,0 +1,72 @@ +From 5765ff204771d519ec6c109a8f6b15871251dff0 Mon Sep 17 00:00:00 2001 +From: "plai@redhat.com" +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: <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: Igor Mammedov +RH-Acked-by: Michael S. Tsirkin + +From: Robert Hoo + +Support of IA32_PRED_CMD MSR already be enumerated by same CPUID bit as +SPEC_CTRL. + +At present, mark CPUID_7_0_EDX_ARCH_CAPABILITIES unmigratable, per Paolo's +comment. + +Signed-off-by: Robert Hoo +Message-Id: <1530781798-183214-3-git-send-email-robert.hu@linux.intel.com> +Signed-off-by: Eduardo Habkost +(cherry picked from commit 3fc7c73139d2d38ae80c3b0bc963b1ac1555924c) +Signed-off-by: Paul Lai + +Resolved Conflicts: + target/i386/cpu.c + +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.c | 3 ++- + target/i386/cpu.h | 1 + + 2 files changed, 3 insertions(+), 1 deletion(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index c979feb..6d38ac0 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -1008,12 +1008,13 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, "spec-ctrl", "stibp", +- NULL, NULL, NULL, "ssbd", ++ NULL, "arch-capabilities", NULL, "ssbd", + }, + .cpuid_eax = 7, + .cpuid_needs_ecx = true, .cpuid_ecx = 0, + .cpuid_reg = R_EDX, + .tcg_features = TCG_7_0_EDX_FEATURES, ++ .unmigratable_flags = CPUID_7_0_EDX_ARCH_CAPABILITIES, + }, + [FEAT_8000_0007_EDX] = { + .feat_names = { +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index 1dc565c..e5e5169 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -687,6 +687,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_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 */ + + #define KVM_HINTS_DEDICATED (1U << 0) +-- +1.8.3.1 + 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 new file mode 100644 index 0000000..1c77fc2 --- /dev/null +++ b/SOURCES/kvm-i386-Add-new-MSR-indices-for-IA32_PRED_CMD-and-IA32_.patch @@ -0,0 +1,50 @@ +From a0a63864906cd578c7bc73ea5318282fb393c147 Mon Sep 17 00:00:00 2001 +From: "plai@redhat.com" +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: <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: Igor Mammedov +RH-Acked-by: Michael S. Tsirkin + +From: Robert Hoo + +IA32_PRED_CMD MSR gives software a way to issue commands that affect the state +of indirect branch predictors. Enumerated by CPUID.(EAX=7H,ECX=0):EDX[26]. +IA32_ARCH_CAPABILITIES MSR enumerates architectural features of RDCL_NO and +IBRS_ALL. Enumerated by CPUID.(EAX=07H, ECX=0):EDX[29]. + +https://software.intel.com/sites/default/files/managed/c5/63/336996-Speculative-Execution-Side-Channel-Mitigations.pdf + +Signed-off-by: Robert Hoo +Message-Id: <1530781798-183214-2-git-send-email-robert.hu@linux.intel.com> +Signed-off-by: Eduardo Habkost +(cherry picked from commit 8c80c99fcceabd0708a5a83f08577e778c9419f5) +Signed-off-by: Paul Lai +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.h | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index fb6caf4..1dc565c 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -352,6 +352,8 @@ typedef enum X86Seg { + #define MSR_TSC_ADJUST 0x0000003b + #define MSR_IA32_SPEC_CTRL 0x48 + #define MSR_VIRT_SSBD 0xc001011f ++#define MSR_IA32_PRED_CMD 0x49 ++#define MSR_IA32_ARCH_CAPABILITIES 0x10a + #define MSR_IA32_TSCDEADLINE 0x6e0 + + #define FEATURE_CONTROL_LOCKED (1<<0) +-- +1.8.3.1 + diff --git a/SOURCES/kvm-i386-Add-new-model-of-Cascadelake-Server.patch b/SOURCES/kvm-i386-Add-new-model-of-Cascadelake-Server.patch new file mode 100644 index 0000000..8b96ddd --- /dev/null +++ b/SOURCES/kvm-i386-Add-new-model-of-Cascadelake-Server.patch @@ -0,0 +1,107 @@ +From 2d44f02611fcb0eddad08d2c5d4361d568fcfd67 Mon Sep 17 00:00:00 2001 +From: "plai@redhat.com" +Date: Mon, 1 Jul 2019 16:17:30 +0100 +Subject: [PATCH 01/39] i386: Add new model of Cascadelake-Server + +RH-Author: plai@redhat.com +Message-id: <1561997854-9646-2-git-send-email-plai@redhat.com> +Patchwork-id: 89331 +O-Subject: [RHEL8.1 qemu-kvm PATCH v6 1/5] i386: Add new model of Cascadelake-Server +Bugzilla: 1629906 +RH-Acked-by: Eduardo Habkost +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Bandan Das + +From: Tao Xu + +New CPU models mostly inherit features from ancestor Skylake-Server, +while addin new features: AVX512_VNNI, Intel PT. +SSBD support for speculative execution +side channel mitigations. + +Note: + +On Cascadelake, some capabilities (RDCL_NO, IBRS_ALL, RSBA, +SKIP_L1DFL_VMENTRY and SSB_NO) are enumerated by MSR. +These features rely on MSR based feature support patch. +Will be added later after that patch's in. +http://lists.nongnu.org/archive/html/qemu-devel/2018-09/msg00074.html + +Signed-off-by: Tao Xu +Message-Id: <20180919031122.28487-2-tao3.xu@intel.com> +Signed-off-by: Eduardo Habkost +(cherry picked from commit c7a88b52f62b30c04158eeb07f73e3f72221b6a8) +Signed-off-by: Paul Lai +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 54 insertions(+) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index 5c10093..9ba5288 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -2483,6 +2483,60 @@ static X86CPUDefinition builtin_x86_defs[] = { + .model_id = "Intel Xeon Processor (Skylake, IBRS)", + }, + { ++ .name = "Cascadelake-Server", ++ .level = 0xd, ++ .vendor = CPUID_VENDOR_INTEL, ++ .family = 6, ++ .model = 85, ++ .stepping = 5, ++ .features[FEAT_1_EDX] = ++ CPUID_VME | CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | ++ CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA | ++ CPUID_PGE | CPUID_MTRR | CPUID_SEP | CPUID_APIC | CPUID_CX8 | ++ CPUID_MCE | CPUID_PAE | CPUID_MSR | CPUID_TSC | CPUID_PSE | ++ CPUID_DE | CPUID_FP87, ++ .features[FEAT_1_ECX] = ++ CPUID_EXT_AVX | CPUID_EXT_XSAVE | CPUID_EXT_AES | ++ CPUID_EXT_POPCNT | CPUID_EXT_X2APIC | CPUID_EXT_SSE42 | ++ CPUID_EXT_SSE41 | CPUID_EXT_CX16 | CPUID_EXT_SSSE3 | ++ CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSE3 | ++ CPUID_EXT_TSC_DEADLINE_TIMER | CPUID_EXT_FMA | CPUID_EXT_MOVBE | ++ CPUID_EXT_PCID | CPUID_EXT_F16C | CPUID_EXT_RDRAND, ++ .features[FEAT_8000_0001_EDX] = ++ CPUID_EXT2_LM | CPUID_EXT2_PDPE1GB | CPUID_EXT2_RDTSCP | ++ CPUID_EXT2_NX | CPUID_EXT2_SYSCALL, ++ .features[FEAT_8000_0001_ECX] = ++ CPUID_EXT3_ABM | CPUID_EXT3_LAHF_LM | CPUID_EXT3_3DNOWPREFETCH, ++ .features[FEAT_7_0_EBX] = ++ CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_BMI1 | ++ CPUID_7_0_EBX_HLE | CPUID_7_0_EBX_AVX2 | CPUID_7_0_EBX_SMEP | ++ CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ERMS | CPUID_7_0_EBX_INVPCID | ++ CPUID_7_0_EBX_RTM | CPUID_7_0_EBX_RDSEED | CPUID_7_0_EBX_ADX | ++ CPUID_7_0_EBX_SMAP | CPUID_7_0_EBX_MPX | CPUID_7_0_EBX_CLWB | ++ CPUID_7_0_EBX_AVX512F | CPUID_7_0_EBX_AVX512DQ | ++ CPUID_7_0_EBX_AVX512BW | CPUID_7_0_EBX_AVX512CD | ++ CPUID_7_0_EBX_AVX512VL | CPUID_7_0_EBX_CLFLUSHOPT | ++ CPUID_7_0_EBX_INTEL_PT, ++ .features[FEAT_7_0_ECX] = ++ CPUID_7_0_ECX_PKU | CPUID_7_0_ECX_OSPKE | ++ CPUID_7_0_ECX_AVX512VNNI, ++ .features[FEAT_7_0_EDX] = ++ CPUID_7_0_EDX_SPEC_CTRL | CPUID_7_0_EDX_SPEC_CTRL_SSBD, ++ /* Missing: XSAVES (not supported by some Linux versions, ++ * including v4.1 to v4.12). ++ * KVM doesn't yet expose any XSAVES state save component, ++ * and the only one defined in Skylake (processor tracing) ++ * probably will block migration anyway. ++ */ ++ .features[FEAT_XSAVE] = ++ CPUID_XSAVE_XSAVEOPT | CPUID_XSAVE_XSAVEC | ++ CPUID_XSAVE_XGETBV1, ++ .features[FEAT_6_EAX] = ++ CPUID_6_EAX_ARAT, ++ .xlevel = 0x80000008, ++ .model_id = "Intel Xeon Processor (Cascadelake)", ++ }, ++ { + .name = "Icelake-Client", + .level = 0xd, + .vendor = CPUID_VENDOR_INTEL, +-- +1.8.3.1 + diff --git a/SOURCES/kvm-i386-Add-x-force-features-option-for-testing.patch b/SOURCES/kvm-i386-Add-x-force-features-option-for-testing.patch new file mode 100644 index 0000000..3281581 --- /dev/null +++ b/SOURCES/kvm-i386-Add-x-force-features-option-for-testing.patch @@ -0,0 +1,80 @@ +From d5526e43ccf3532aa3a0f592e6df5740983a94e2 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Fri, 22 Nov 2019 11:53:35 +0000 +Subject: [PATCH 02/16] i386: Add x-force-features option for testing +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Paolo Bonzini +Message-id: <20191122115348.25000-3-pbonzini@redhat.com> +Patchwork-id: 92602 +O-Subject: [RHEL8.2/rhel qemu-kvm PATCH 02/15] i386: Add x-force-features option for testing +Bugzilla: 1689270 +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Eduardo Habkost +RH-Acked-by: Maxim Levitsky + +From: Eduardo Habkost + +Add a new option that can be used to disable feature flag +filtering. This will allow CPU model compatibility test cases to +work without host hardware dependencies. + +Signed-off-by: Eduardo Habkost +Message-Id: <20190628002844.24894-3-ehabkost@redhat.com> +Reviewed-by: Daniel P. Berrangé +Signed-off-by: Eduardo Habkost +(cherry picked from commit dac1deae658539e39966e12b12378a28e3dc8441) +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.c | 8 ++++++-- + target/i386/cpu.h | 6 ++++++ + 2 files changed, 12 insertions(+), 2 deletions(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index c69116c..8c1338f 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -5019,8 +5019,11 @@ static int x86_cpu_filter_features(X86CPU *cpu) + uint32_t host_feat = + x86_cpu_get_supported_feature_word(w, false); + uint32_t requested_features = env->features[w]; +- env->features[w] &= host_feat; +- cpu->filtered_features[w] = requested_features & ~env->features[w]; ++ uint32_t available_features = requested_features & host_feat; ++ if (!cpu->force_features) { ++ env->features[w] = available_features; ++ } ++ cpu->filtered_features[w] = requested_features & ~available_features; + if (cpu->filtered_features[w]) { + rv = 1; + } +@@ -5680,6 +5683,7 @@ static Property x86_cpu_properties[] = { + DEFINE_PROP_BOOL("hv-frequencies", X86CPU, hyperv_frequencies, false), + DEFINE_PROP_BOOL("check", X86CPU, check_cpuid, true), + DEFINE_PROP_BOOL("enforce", X86CPU, enforce_cpuid, false), ++ DEFINE_PROP_BOOL("x-force-features", X86CPU, force_features, false), + DEFINE_PROP_BOOL("kvm", X86CPU, expose_kvm, true), + DEFINE_PROP_UINT32("phys-bits", X86CPU, phys_bits, 0), + DEFINE_PROP_BOOL("host-phys-bits", X86CPU, host_phys_bits, false), +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index add8b60..1ad54bd 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -1394,6 +1394,12 @@ struct X86CPU { + bool hyperv_frequencies; + bool check_cpuid; + bool enforce_cpuid; ++ /* ++ * Force features to be enabled even if the host doesn't support them. ++ * This is dangerous and should be done only for testing CPUID ++ * compatibility. ++ */ ++ bool force_features; + bool expose_kvm; + bool expose_tcg; + bool migratable; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-i386-Disable-OSPKE-on-CPU-model-definitions-NEW.patch b/SOURCES/kvm-i386-Disable-OSPKE-on-CPU-model-definitions-NEW.patch new file mode 100644 index 0000000..c78b32a --- /dev/null +++ b/SOURCES/kvm-i386-Disable-OSPKE-on-CPU-model-definitions-NEW.patch @@ -0,0 +1,72 @@ +From 04f34e7c0b0fada186ca7012f5f4168f46483c5f Mon Sep 17 00:00:00 2001 +From: "plai@redhat.com" +Date: Mon, 1 Jul 2019 16:17:34 +0100 +Subject: [PATCH 05/39] i386: Disable OSPKE on CPU model definitions + +RH-Author: plai@redhat.com +Message-id: <1561997854-9646-6-git-send-email-plai@redhat.com> +Patchwork-id: 89334 +O-Subject: [RHEL8.1 qemu-kvm PATCH v6 5/5] i386: Disable OSPKE on CPU model definitions +Bugzilla: 1629906 +RH-Acked-by: Eduardo Habkost +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Bandan Das + +From: Eduardo Habkost + +Currently, the Cascadelake-Server, Icelake-Client, and +Icelake-Server are always generating the following warning: + + qemu-system-x86_64: warning: \ + host doesn't support requested feature: CPUID.07H:ECX [bit 4] + +This happens because OSPKE was never returned by +GET_SUPPORTED_CPUID or x86_cpu_get_supported_feature_word(). +OSPKE is a runtime flag automatically set by the KVM module or by +TCG code, was always cleared by x86_cpu_filter_features(), and +was not supposed to appear on the CPU model table. + +Remove the OSPKE flag from the CPU model table entries, to avoid +the bogus warning and avoid returning invalid feature data on +query-cpu-* QMP commands. As OSPKE was always cleared by +x86_cpu_filter_features(), this won't have any guest-visible +impact. + +Include a test case that should detect the problem if we introduce +a similar bug again. + +Fixes: c7a88b52f62b ("i386: Add new model of Cascadelake-Server") +Fixes: 8a11c62da914 ("i386: Add new CPU model Icelake-{Server,Client}") +Cc: Tao Xu +Cc: Robert Hoo +Signed-off-by: Eduardo Habkost +Message-Id: <20190319200515.14999-1-ehabkost@redhat.com> +Signed-off-by: Eduardo Habkost +(cherry picked from commit bb4928c7cafe50ab2137a0034e350ef1bfa044d9) +Signed-off-by: Paul Lai +Signed-off-by: Danilo C. L. de Paula + +Conflicts: + target/i386/cpu.c + +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index 2538d82..af62281 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -2517,7 +2517,7 @@ static X86CPUDefinition builtin_x86_defs[] = { + CPUID_7_0_EBX_AVX512BW | CPUID_7_0_EBX_AVX512CD | + CPUID_7_0_EBX_AVX512VL | CPUID_7_0_EBX_CLFLUSHOPT, + .features[FEAT_7_0_ECX] = +- CPUID_7_0_ECX_PKU | CPUID_7_0_ECX_OSPKE | ++ CPUID_7_0_ECX_PKU | + CPUID_7_0_ECX_AVX512VNNI, + .features[FEAT_7_0_EDX] = + CPUID_7_0_EDX_SPEC_CTRL | CPUID_7_0_EDX_SPEC_CTRL_SSBD, +-- +1.8.3.1 + diff --git a/SOURCES/kvm-i386-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-Don-t-print-warning-if-phys-bits-was-set-automa.patch b/SOURCES/kvm-i386-Don-t-print-warning-if-phys-bits-was-set-automa.patch new file mode 100644 index 0000000..d64dbc9 --- /dev/null +++ b/SOURCES/kvm-i386-Don-t-print-warning-if-phys-bits-was-set-automa.patch @@ -0,0 +1,79 @@ +From 7e78c8e8b5a9cab9ef4604dc29eab4b4323e9b9b Mon Sep 17 00:00:00 2001 +From: Eduardo Habkost +Date: Tue, 13 Aug 2019 01:53:55 +0100 +Subject: [PATCH 01/21] i386: Don't print warning if phys-bits was set + automatically + +RH-Author: Eduardo Habkost +Message-id: <20190813015355.17556-1-ehabkost@redhat.com> +Patchwork-id: 89946 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH] i386: Don't print warning if phys-bits was set automatically +Bugzilla: 1719127 +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Igor Mammedov +RH-Acked-by: John Snow + +BZ: https://bugzilla.redhat.com/show_bug.cgi?id=1719127 +BRANCH: rhel-8.1.0 +UPSTREAM: fea306520ea4b2f189dd23c70a6afd2fc4ffafdc +BREW: https://brewweb.engineering.redhat.com/brew/taskinfo?taskID=23026463 + +If cpu->host_phys_bits_limit is set, QEMU will make +cpu->phys_bits be lower than host_phys_bits on some cases. This +triggers a warning that was supposed to be printed only if +phys-bits was explicitly set in the command-line. + +Reorder the code so the value of cpu->phys_bits is validated +before the cpu->host_phys_bits handling. This will avoid +unexpected warnings when cpu->host_phys_bits_limit is set. + +Signed-off-by: Eduardo Habkost +Message-Id: <20190611205420.20286-1-ehabkost@redhat.com> +Reviewed-by: Dr. David Alan Gilbert +Signed-off-by: Eduardo Habkost +(cherry picked from commit fea306520ea4b2f189dd23c70a6afd2fc4ffafdc) +Signed-off-by: Eduardo Habkost +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.c | 18 +++++++++--------- + 1 file changed, 9 insertions(+), 9 deletions(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index c8f50a7..c69116c 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -5116,15 +5116,6 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp) + uint32_t host_phys_bits = x86_host_phys_bits(); + static bool warned; + +- if (cpu->host_phys_bits) { +- /* The user asked for us to use the host physical bits */ +- cpu->phys_bits = host_phys_bits; +- if (cpu->host_phys_bits_limit && +- cpu->phys_bits > cpu->host_phys_bits_limit) { +- cpu->phys_bits = cpu->host_phys_bits_limit; +- } +- } +- + /* Print a warning if the user set it to a value that's not the + * host value. + */ +@@ -5136,6 +5127,15 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp) + warned = true; + } + ++ if (cpu->host_phys_bits) { ++ /* The user asked for us to use the host physical bits */ ++ cpu->phys_bits = host_phys_bits; ++ if (cpu->host_phys_bits_limit && ++ cpu->phys_bits > cpu->host_phys_bits_limit) { ++ cpu->phys_bits = cpu->host_phys_bits_limit; ++ } ++ } ++ + if (cpu->phys_bits && + (cpu->phys_bits > TARGET_PHYS_ADDR_SPACE_BITS || + cpu->phys_bits < 32)) { +-- +1.8.3.1 + diff --git a/SOURCES/kvm-i386-Make-arch_capabilities-migratable.patch b/SOURCES/kvm-i386-Make-arch_capabilities-migratable.patch new file mode 100644 index 0000000..09b869d --- /dev/null +++ b/SOURCES/kvm-i386-Make-arch_capabilities-migratable.patch @@ -0,0 +1,54 @@ +From 31194033bdc6f379edebe9fa818536d478a629f0 Mon Sep 17 00:00:00 2001 +From: "plai@redhat.com" +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: <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: 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. + +Signed-off-by: Eduardo Habkost +Message-Id: <20190125220606.4864-3-ehabkost@redhat.com> +Signed-off-by: Eduardo Habkost +(cherry picked from commit 014018e19b3c54dd1bf5072bc912ceffea40abe8) +Signed-off-by: Paul Lai +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +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] = { + .reg = R_EDX, + }, + .tcg_features = TCG_7_0_EDX_FEATURES, +- .unmigratable_flags = CPUID_7_0_EDX_ARCH_CAPABILITIES, + }, + [FEAT_8000_0007_EDX] = { + .type = CPUID_FEATURE_WORD, +-- +1.8.3.1 + diff --git a/SOURCES/kvm-i386-Remove-cpu64-rhel6-CPU-model.patch b/SOURCES/kvm-i386-Remove-cpu64-rhel6-CPU-model.patch new file mode 100644 index 0000000..9358f45 --- /dev/null +++ b/SOURCES/kvm-i386-Remove-cpu64-rhel6-CPU-model.patch @@ -0,0 +1,77 @@ +From d52cded7f0cab801cfd59c4c97f70f48f332c1bb Mon Sep 17 00:00:00 2001 +From: Eduardo Habkost +Date: Mon, 23 Dec 2019 21:17:05 +0000 +Subject: [PATCH] i386: Remove cpu64-rhel6 CPU model + +RH-Author: Eduardo Habkost +Message-id: <20191223211705.34325-1-ehabkost@redhat.com> +Patchwork-id: 93214 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH] i386: Remove cpu64-rhel6 CPU model +Bugzilla: 1741346 +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Thomas Huth + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1741346 +BRANCH: rhel-8.2.0 +Upstream: not applicable +Brew: https://brewweb.engineering.redhat.com/brew/taskinfo?taskID=25526009 + +We don't provide rhel6 machine types anymore, so we don't need to +provide compatibility with RHEl6. cpu64-rhel6 was documented as +deprecated and scheduled for removal in 8.2, so now it's time to +remove it. + +Signed-off-by: Eduardo Habkost +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.c | 26 +------------------------- + 1 file changed, 1 insertion(+), 25 deletions(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index 0717c66..33abc24 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -1739,12 +1739,7 @@ static CPUCaches epyc_cache_info = { + + static X86CPUDefinition builtin_x86_defs[] = { + { +- /* qemu64 is the default CPU model for all *-rhel7.* machine-types. +- * The default on RHEL-6 was cpu64-rhel6. +- * libvirt assumes that qemu64 is the default for _all_ machine-types, +- * so we should try to keep qemu64 and cpu64-rhel6 as similar as +- * possible. +- */ ++ /* qemu64 is the default CPU model for all machine-types */ + .name = "qemu64", + .level = 0xd, + .vendor = CPUID_VENDOR_AMD, +@@ -2045,25 +2040,6 @@ static X86CPUDefinition builtin_x86_defs[] = { + .model_id = "Intel(R) Atom(TM) CPU N270 @ 1.60GHz", + }, + { +- .name = "cpu64-rhel6", +- .level = 4, +- .vendor = CPUID_VENDOR_AMD, +- .family = 6, +- .model = 13, +- .stepping = 3, +- .features[FEAT_1_EDX] = 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_CX16 | CPUID_EXT_SSE3, +- .features[FEAT_8000_0001_EDX] = CPUID_EXT2_LM | CPUID_EXT2_NX | CPUID_EXT2_SYSCALL, +- .features[FEAT_8000_0001_ECX] = CPUID_EXT3_SSE4A | CPUID_EXT3_ABM | +- CPUID_EXT3_SVM | CPUID_EXT3_LAHF_LM, +- .xlevel = 0x8000000A, +- .model_id = "QEMU Virtual CPU version (cpu64-rhel6)", +- }, +- { + .name = "Conroe", + .level = 10, + .vendor = CPUID_VENDOR_INTEL, +-- +1.8.3.1 + diff --git a/SOURCES/kvm-i386-Save-EFER-for-32-bit-targets.patch b/SOURCES/kvm-i386-Save-EFER-for-32-bit-targets.patch new file mode 100644 index 0000000..fe1a7b3 --- /dev/null +++ b/SOURCES/kvm-i386-Save-EFER-for-32-bit-targets.patch @@ -0,0 +1,80 @@ +From 1e8e3c4fe380a2a0ed88f7a92f5bcb8600ab1258 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Mon, 22 Jul 2019 18:22:03 +0100 +Subject: [PATCH 22/39] i386: Save EFER for 32-bit targets + +RH-Author: Paolo Bonzini +Message-id: <20190722182220.19374-2-pbonzini@redhat.com> +Patchwork-id: 89619 +O-Subject: [RHEL-8.1.0 PATCH qemu-kvm v3 01/18] i386: Save EFER for 32-bit targets +Bugzilla: 1689269 +RH-Acked-by: Peter Xu +RH-Acked-by: Laurent Vivier +RH-Acked-by: Dr. David Alan Gilbert + +From: Pavel Dovgalyuk + +i386 (32 bit) emulation uses EFER in wrmsr and in MMU fault +processing. +But it does not included in VMState, because "efer" field is disabled with + +This patch adds a section for 32-bit targets which saves EFER when +it's value is non-zero. + +Signed-off-by: Pavel Dovgalyuk +Message-Id: <155913371654.8429.1659082639780315242.stgit@pasha-Precision-3630-Tower> +Reviewed-by: Peter Xu +[ehabkost: indentation fix] +Signed-off-by: Eduardo Habkost +(cherry picked from commit 89a44a103315267122119b4311218d00d2561ebe) + +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/machine.c | 24 ++++++++++++++++++++++++ + 1 file changed, 24 insertions(+) + +diff --git a/target/i386/machine.c b/target/i386/machine.c +index 2a85c91..561d4a5 100644 +--- a/target/i386/machine.c ++++ b/target/i386/machine.c +@@ -932,6 +932,27 @@ static const VMStateDescription vmstate_msr_virt_ssbd = { + } + }; + ++#ifndef TARGET_X86_64 ++static bool intel_efer32_needed(void *opaque) ++{ ++ X86CPU *cpu = opaque; ++ CPUX86State *env = &cpu->env; ++ ++ return env->efer != 0; ++} ++ ++static const VMStateDescription vmstate_efer32 = { ++ .name = "cpu/efer32", ++ .version_id = 1, ++ .minimum_version_id = 1, ++ .needed = intel_efer32_needed, ++ .fields = (VMStateField[]) { ++ VMSTATE_UINT64(env.efer, X86CPU), ++ VMSTATE_END_OF_LIST() ++ } ++}; ++#endif ++ + VMStateDescription vmstate_x86_cpu = { + .name = "cpu", + .version_id = 12, +@@ -1056,6 +1077,9 @@ VMStateDescription vmstate_x86_cpu = { + &vmstate_msr_intel_pt, + &vmstate_xsave, + &vmstate_msr_virt_ssbd, ++#ifndef TARGET_X86_64 ++ &vmstate_efer32, ++#endif + NULL + } + }; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-i386-Update-stepping-of-Cascadelake-Server.patch b/SOURCES/kvm-i386-Update-stepping-of-Cascadelake-Server.patch new file mode 100644 index 0000000..328d271 --- /dev/null +++ b/SOURCES/kvm-i386-Update-stepping-of-Cascadelake-Server.patch @@ -0,0 +1,66 @@ +From 839e9376bc82933ccacb26b660f1d3adf62aaf05 Mon Sep 17 00:00:00 2001 +From: "plai@redhat.com" +Date: Mon, 1 Jul 2019 16:17:31 +0100 +Subject: [PATCH 02/39] i386: Update stepping of Cascadelake-Server + +RH-Author: plai@redhat.com +Message-id: <1561997854-9646-3-git-send-email-plai@redhat.com> +Patchwork-id: 89329 +O-Subject: [RHEL8.1 qemu-kvm PATCH v6 2/5] i386: Update stepping of Cascadelake-Server +Bugzilla: 1629906 +RH-Acked-by: Eduardo Habkost +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Bandan Das + +From: Tao Xu + +Update the stepping from 5 to 6, in order that +the Cascadelake-Server CPU model can support AVX512VNNI +and MSR based features exposed by ARCH_CAPABILITIES. + +Signed-off-by: Tao Xu +Message-Id: <20181227024304.12182-2-tao3.xu@intel.com> +Signed-off-by: Eduardo Habkost +(cherry picked from commit b0a1980384fc265d91de7e09aa5fe531a69e6288) +Signed-off-by: Paul Lai + +Resolved Conflicts: + hw/i386/pc.c changes to include/hw/i386/pc.h + +Signed-off-by: Danilo C. L. de Paula +--- + include/hw/i386/pc.h | 4 ++++ + target/i386/cpu.c | 2 +- + 2 files changed, 5 insertions(+), 1 deletion(-) + +diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h +index 244d7b5..88ffd40 100644 +--- a/include/hw/i386/pc.h ++++ b/include/hw/i386/pc.h +@@ -318,6 +318,10 @@ bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *); + .driver = "Skylake-Server" "-" TYPE_X86_CPU,\ + .property = "clflushopt",\ + .value = "off",\ ++ },{\ ++ .driver = "Cascadelake-Server" "-" TYPE_X86_CPU,\ ++ .property = "stepping",\ ++ .value = "5",\ + }, + + #define PC_COMPAT_2_10 \ +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index 9ba5288..c4b31eb 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -2488,7 +2488,7 @@ static X86CPUDefinition builtin_x86_defs[] = { + .vendor = CPUID_VENDOR_INTEL, + .family = 6, + .model = 85, +- .stepping = 5, ++ .stepping = 6, + .features[FEAT_1_EDX] = + CPUID_VME | CPUID_SSE2 | CPUID_SSE | CPUID_FXSR | CPUID_MMX | + CPUID_CLFLUSH | CPUID_PSE36 | CPUID_PAT | CPUID_CMOV | CPUID_MCA | +-- +1.8.3.1 + diff --git a/SOURCES/kvm-i386-cpu-make-cpu-host-support-monitor-mwait.patch b/SOURCES/kvm-i386-cpu-make-cpu-host-support-monitor-mwait.patch new file mode 100644 index 0000000..19f6d86 --- /dev/null +++ b/SOURCES/kvm-i386-cpu-make-cpu-host-support-monitor-mwait.patch @@ -0,0 +1,132 @@ +From 91ac1f511b0414292d07688c3cb3012bed6e3649 Mon Sep 17 00:00:00 2001 +From: "Michael S. Tsirkin" +Date: Fri, 22 Jun 2018 22:22:05 +0300 +Subject: [PATCH 09/11] i386/cpu: make -cpu host support monitor/mwait + +When guest CPU PM is enabled, and with -cpu host, expose the host CPU +MWAIT leaf in the CPUID so guest can make good PM decisions. + +Note: the result is 100% CPU utilization reported by host as host +no longer knows that the CPU is halted. + +Signed-off-by: Michael S. Tsirkin +Reviewed-by: Eduardo Habkost +Message-Id: <20180622192148.178309-3-mst@redhat.com> +Signed-off-by: Paolo Bonzini +Signed-off-by: Danilo C. L. de Paula +--- + accel/tcg/user-exec-stub.c | 3 +++ + target/i386/cpu.c | 32 ++++++++++++++++++++++---------- + target/i386/cpu.h | 9 +++++++++ + target/i386/kvm.c | 9 +++++++++ + 4 files changed, 43 insertions(+), 10 deletions(-) + +diff --git a/accel/tcg/user-exec-stub.c b/accel/tcg/user-exec-stub.c +index dbcf1ad..a32b449 100644 +--- a/accel/tcg/user-exec-stub.c ++++ b/accel/tcg/user-exec-stub.c +@@ -2,6 +2,9 @@ + #include "qemu-common.h" + #include "qom/cpu.h" + #include "sysemu/replay.h" ++#include "sysemu/sysemu.h" ++ ++bool enable_cpu_pm = false; + + void cpu_resume(CPUState *cpu) + { +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index 307b629..87b0502 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -5662,11 +5662,11 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, + } + break; + case 5: +- /* mwait info: needed for Core compatibility */ +- *eax = 0; /* Smallest monitor-line size in bytes */ +- *ebx = 0; /* Largest monitor-line size in bytes */ +- *ecx = CPUID_MWAIT_EMX | CPUID_MWAIT_IBE; +- *edx = 0; ++ /* MONITOR/MWAIT Leaf */ ++ *eax = cpu->mwait.eax; /* Smallest monitor-line size in bytes */ ++ *ebx = cpu->mwait.ebx; /* Largest monitor-line size in bytes */ ++ *ecx = cpu->mwait.ecx; /* flags */ ++ *edx = cpu->mwait.edx; /* mwait substates */ + break; + case 6: + /* Thermal and Power Leaf */ +@@ -6521,13 +6521,25 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp) + Error *local_err = NULL; + static bool ht_warned; + +- if (xcc->host_cpuid_required && !accel_uses_host_cpuid()) { +- char *name = x86_cpu_class_get_model_name(xcc); +- error_setg(&local_err, "CPU model '%s' requires KVM", name); +- g_free(name); +- goto out; ++ if (xcc->host_cpuid_required) { ++ if (!accel_uses_host_cpuid()) { ++ char *name = x86_cpu_class_get_model_name(xcc); ++ error_setg(&local_err, "CPU model '%s' requires KVM", name); ++ g_free(name); ++ goto out; ++ } ++ ++ if (enable_cpu_pm) { ++ host_cpuid(5, 0, &cpu->mwait.eax, &cpu->mwait.ebx, ++ &cpu->mwait.ecx, &cpu->mwait.edx); ++ env->features[FEAT_1_ECX] |= CPUID_EXT_MONITOR; ++ } + } + ++ /* mwait extended info: needed for Core compatibility */ ++ /* We always wake on interrupt even if host does not have the capability */ ++ cpu->mwait.ecx |= CPUID_MWAIT_EMX | CPUID_MWAIT_IBE; ++ + if (cpu->apic_id == UNASSIGNED_APIC_ID) { + error_setg(errp, "apic-id property was not initialized properly"); + return; +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index d33fa8d..7ab8ee9 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -1564,6 +1564,15 @@ struct X86CPU { + /* if true the CPUID code directly forward host cache leaves to the guest */ + bool cache_info_passthrough; + ++ /* if true the CPUID code directly forwards ++ * host monitor/mwait leaves to the guest */ ++ struct { ++ uint32_t eax; ++ uint32_t ebx; ++ uint32_t ecx; ++ uint32_t edx; ++ } mwait; ++ + /* Features that were filtered out because of missing host capabilities */ + FeatureWordArray filtered_features; + +diff --git a/target/i386/kvm.c b/target/i386/kvm.c +index 879c3e0..ffd01f0 100644 +--- a/target/i386/kvm.c ++++ b/target/i386/kvm.c +@@ -377,6 +377,15 @@ uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function, + if (!kvm_irqchip_in_kernel()) { + ret &= ~CPUID_EXT_X2APIC; + } ++ ++ if (enable_cpu_pm) { ++ int disable_exits = kvm_check_extension(s, ++ KVM_CAP_X86_DISABLE_EXITS); ++ ++ if (disable_exits & KVM_X86_DISABLE_EXITS_MWAIT) { ++ ret |= CPUID_EXT_MONITOR; ++ } ++ } + } else if (function == 6 && reg == R_EAX) { + ret |= CPUID_6_EAX_ARAT; /* safe to allow because of emulated APIC */ + } else if (function == 7 && index == 0 && reg == R_EBX) { +-- +1.8.3.1 + diff --git a/SOURCES/kvm-i386-display-known-CPUID-features-linewrapped-in-alp.patch b/SOURCES/kvm-i386-display-known-CPUID-features-linewrapped-in-alp.patch new file mode 100644 index 0000000..50e63b4 --- /dev/null +++ b/SOURCES/kvm-i386-display-known-CPUID-features-linewrapped-in-alp.patch @@ -0,0 +1,119 @@ +From e7f11d39d1ef78f47ed6d45ecd278d51c502f131 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Fri, 22 Nov 2019 11:53:37 +0000 +Subject: [PATCH 04/16] i386: display known CPUID features linewrapped, in + alphabetical order +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Paolo Bonzini +Message-id: <20191122115348.25000-5-pbonzini@redhat.com> +Patchwork-id: 92605 +O-Subject: [RHEL8.2/rhel qemu-kvm PATCH 04/15] i386: display known CPUID features linewrapped, in alphabetical order +Bugzilla: 1689270 +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Eduardo Habkost +RH-Acked-by: Maxim Levitsky + +From: Daniel P. Berrangé + +When using '-cpu help' the list of CPUID features is grouped according +to the internal low level CPUID grouping. The data printed results in +very long lines too. + +This combines to make it hard for users to read the output and identify +if QEMU knows about the feature they wish to use. + +This change gets rid of the grouping of features and treats all flags as +single list. The list is sorted into alphabetical order and the printing +with line wrapping at the 77th column. + +Signed-off-by: Daniel P. Berrangé +Message-Id: <20180606165527.17365-4-berrange@redhat.com> +Signed-off-by: Eduardo Habkost +(cherry picked from commit cc643b1e7898414b56f551bbd42d4ed8c2ae127a) +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.c | 41 +++++++++++++++++++++++++++-------------- + 1 file changed, 27 insertions(+), 14 deletions(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index 52f1f33..d0c48c2 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -3651,17 +3651,21 @@ static void x86_cpu_class_check_missing_features(X86CPUClass *xcc, + + /* Print all cpuid feature names in featureset + */ +-static void listflags(FILE *f, fprintf_function print, const char **featureset) ++static void listflags(FILE *f, fprintf_function print, GList *features) + { +- int bit; +- bool first = true; +- +- for (bit = 0; bit < 32; bit++) { +- if (featureset[bit]) { +- print(f, "%s%s", first ? "" : " ", featureset[bit]); +- first = false; ++ size_t len = 0; ++ GList *tmp; ++ ++ for (tmp = features; tmp; tmp = tmp->next) { ++ const char *name = tmp->data; ++ if ((len + strlen(name) + 1) >= 75) { ++ print(f, "\n"); ++ len = 0; + } ++ print(f, "%s%s", len == 0 ? " " : " ", name); ++ len += strlen(name) + 1; + } ++ print(f, "\n"); + } + + /* Sort alphabetically by type name, respecting X86CPUClass::ordering. */ +@@ -3708,26 +3712,35 @@ static void x86_cpu_list_entry(gpointer data, gpointer user_data) + /* list available CPU models and flags */ + void x86_cpu_list(FILE *f, fprintf_function cpu_fprintf) + { +- int i; ++ int i, j; + CPUListState s = { + .file = f, + .cpu_fprintf = cpu_fprintf, + }; + GSList *list; ++ GList *names = NULL; + + (*cpu_fprintf)(f, "Available CPUs:\n"); + list = get_sorted_cpu_model_list(); + g_slist_foreach(list, x86_cpu_list_entry, &s); + g_slist_free(list); + +- (*cpu_fprintf)(f, "\nRecognized CPUID flags:\n"); ++ names = NULL; + for (i = 0; i < ARRAY_SIZE(feature_word_info); i++) { + FeatureWordInfo *fw = &feature_word_info[i]; +- +- (*cpu_fprintf)(f, " "); +- listflags(f, cpu_fprintf, fw->feat_names); +- (*cpu_fprintf)(f, "\n"); ++ for (j = 0; j < 32; j++) { ++ if (fw->feat_names[j]) { ++ names = g_list_append(names, (gpointer)fw->feat_names[j]); ++ } ++ } + } ++ ++ names = g_list_sort(names, (GCompareFunc)strcmp); ++ ++ (*cpu_fprintf)(f, "\nRecognized CPUID flags:\n"); ++ listflags(f, cpu_fprintf, names); ++ (*cpu_fprintf)(f, "\n"); ++ g_list_free(names); + } + + static void x86_cpu_definition_entry(gpointer data, gpointer user_data) +-- +1.8.3.1 + diff --git a/SOURCES/kvm-i386-fix-regression-parsing-multiboot-initrd-modules.patch b/SOURCES/kvm-i386-fix-regression-parsing-multiboot-initrd-modules.patch new file mode 100644 index 0000000..0f80206 --- /dev/null +++ b/SOURCES/kvm-i386-fix-regression-parsing-multiboot-initrd-modules.patch @@ -0,0 +1,83 @@ +From dc98e8dd5c4aad2f3c480a9513ffba89540dcf3f Mon Sep 17 00:00:00 2001 +From: Laszlo Ersek +Date: Thu, 12 Sep 2019 13:05:01 +0100 +Subject: [PATCH 04/22] i386: fix regression parsing multiboot initrd modules +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Laszlo Ersek +Message-id: <20190912130503.14094-5-lersek@redhat.com> +Patchwork-id: 90434 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH 4/6] i386: fix regression parsing multiboot initrd modules +Bugzilla: 1749022 +RH-Acked-by: Stefano Garzarella +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Eduardo Habkost + +From: Daniel P. Berrangé + +The logic for parsing the multiboot initrd modules was messed up in + + commit 950c4e6c94b15cd0d8b63891dddd7a8dbf458e6a + Author: Daniel P. Berrangé + Date: Mon Apr 16 12:17:43 2018 +0100 + + opts: don't silently truncate long option values + +Causing the length to be undercounter, and the number of modules over +counted. It also passes NULL to get_opt_value() which was not robust +at accepting a NULL value. + +RHEL8 notes: + +- Context difference in "util/qemu-option.c", function get_opt_value(); + upstream has commit 5c99fa375da1 ("cutils: Provide strchrnul", + 2018-06-29), part of v3.0.0, but downstream lacks it. Harmless, because + said upstream commit only refactors get_opt_value(). + +Signed-off-by: Daniel P. Berrangé +Message-Id: <20180514171913.17664-2-berrange@redhat.com> +Reviewed-by: Eduardo Habkost +Tested-by: Roman Kagan +Signed-off-by: Paolo Bonzini +(cherry picked from commit 6e3ad3f0e31b8e31c6c0769d0f474bcd9673e0e5) +Signed-off-by: Laszlo Ersek +Signed-off-by: Danilo C. L. de Paula +--- + hw/i386/multiboot.c | 3 +-- + util/qemu-option.c | 4 +++- + 2 files changed, 4 insertions(+), 3 deletions(-) + +diff --git a/hw/i386/multiboot.c b/hw/i386/multiboot.c +index 7a2953e..8e26545 100644 +--- a/hw/i386/multiboot.c ++++ b/hw/i386/multiboot.c +@@ -292,8 +292,7 @@ int load_multiboot(FWCfgState *fw_cfg, + cmdline_len += strlen(kernel_cmdline) + 1; + if (initrd_filename) { + const char *r = get_opt_value(initrd_filename, NULL); +- cmdline_len += strlen(r) + 1; +- mbs.mb_mods_avail = 1; ++ cmdline_len += strlen(initrd_filename) + 1; + while (1) { + mbs.mb_mods_avail++; + r = get_opt_value(r, NULL); +diff --git a/util/qemu-option.c b/util/qemu-option.c +index ba44a08..a396d60 100644 +--- a/util/qemu-option.c ++++ b/util/qemu-option.c +@@ -75,7 +75,9 @@ const char *get_opt_value(const char *p, char **value) + size_t capacity = 0, length; + const char *offset; + +- *value = NULL; ++ if (value) { ++ *value = NULL; ++ } + while (1) { + offset = strchr(p, ','); + if (!offset) { +-- +1.8.3.1 + diff --git a/SOURCES/kvm-i386-kvm-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 new file mode 100644 index 0000000..b096d40 --- /dev/null +++ b/SOURCES/kvm-i386-kvm-Disable-arch_capabilities-if-MSR-can-t-be-s.patch @@ -0,0 +1,69 @@ +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: 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 +RH-Acked-by: Bandan Das + +KVM has two bugs in the handling of MSR_IA32_ARCH_CAPABILITIES: + +1) Linux commit commit 1eaafe91a0df ("kvm: x86: IA32_ARCH_CAPABILITIES + is always supported") makes GET_SUPPORTED_CPUID return + arch_capabilities even if running on SVM. This makes "-cpu + host,migratable=off" incorrectly expose arch_capabilities on CPUID on + AMD hosts (where the MSR is not emulated by KVM). + +2) KVM_GET_MSR_INDEX_LIST does not return MSR_IA32_ARCH_CAPABILITIES if + the MSR is not supported by the host CPU. This makes QEMU not + initialize the MSR properly at kvm_put_msrs() on those hosts. + +Work around both bugs on the QEMU side, by checking if the MSR +was returned by KVM_GET_MSR_INDEX_LIST before returning the +feature flag on kvm_arch_get_supported_cpuid(). + +This has the unfortunate side effect of making arch_capabilities +unavailable on hosts without hardware support for the MSR until bug #2 +is fixed on KVM, but I can't see another way to work around bug #1 +without that side effect. + +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: 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 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, + if (host_tsx_blacklisted()) { + ret &= ~(CPUID_7_0_EBX_RTM | CPUID_7_0_EBX_HLE); + } ++ } else if (function == 7 && index == 0 && reg == R_EDX) { ++ /* ++ * Linux v4.17-v4.20 incorrectly return ARCH_CAPABILITIES on SVM hosts. ++ * We can detect the bug by checking if MSR_IA32_ARCH_CAPABILITIES is ++ * returned by KVM_GET_MSR_INDEX_LIST. ++ */ ++ if (!has_msr_arch_capabs) { ++ ret &= ~CPUID_7_0_EDX_ARCH_CAPABILITIES; ++ } + } else if (function == 0x80000001 && reg == R_ECX) { + /* + * It's safe to enable TOPOEXT even if it's not returned by +-- +1.8.3.1 + diff --git a/SOURCES/kvm-i386-kvm-Do-not-sync-nested-state-during-runtime.patch b/SOURCES/kvm-i386-kvm-Do-not-sync-nested-state-during-runtime.patch new file mode 100644 index 0000000..f0d83c7 --- /dev/null +++ b/SOURCES/kvm-i386-kvm-Do-not-sync-nested-state-during-runtime.patch @@ -0,0 +1,55 @@ +From aaf60450da6b0bc4723028aeab9ced75ee03111b Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Mon, 22 Jul 2019 18:22:20 +0100 +Subject: [PATCH 39/39] i386/kvm: Do not sync nested state during runtime + +RH-Author: Paolo Bonzini +Message-id: <20190722182220.19374-19-pbonzini@redhat.com> +Patchwork-id: 89635 +O-Subject: [RHEL-8.1.0 PATCH qemu-kvm v3 18/18] i386/kvm: Do not sync nested state during runtime +Bugzilla: 1689269 +RH-Acked-by: Peter Xu +RH-Acked-by: Laurent Vivier +RH-Acked-by: Dr. David Alan Gilbert + +From: Jan Kiszka + +Writing the nested state e.g. after a vmport access can invalidate +important parts of the kernel-internal state, and it is not needed as +well. So leave this out from KVM_PUT_RUNTIME_STATE. + +Suggested-by: Paolo Bonzini +Signed-off-by: Jan Kiszka +Message-Id: +Signed-off-by: Paolo Bonzini +(cherry picked from commit 20b25d239ab7a94bb8bff3d0f13a9527ee75cf10) +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/kvm.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/target/i386/kvm.c b/target/i386/kvm.c +index 8648f1f..da5f07e 100644 +--- a/target/i386/kvm.c ++++ b/target/i386/kvm.c +@@ -3014,12 +3014,12 @@ int kvm_arch_put_registers(CPUState *cpu, int level) + + assert(cpu_is_stopped(cpu) || qemu_cpu_is_self(cpu)); + +- ret = kvm_put_nested_state(x86_cpu); +- if (ret < 0) { +- return ret; +- } +- + if (level >= KVM_PUT_RESET_STATE) { ++ ret = kvm_put_nested_state(x86_cpu); ++ if (ret < 0) { ++ return ret; ++ } ++ + ret = kvm_put_msr_feature_control(x86_cpu); + if (ret < 0) { + return ret; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-i386-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-only-parse-the-initrd_filename-once-for-multibo.patch b/SOURCES/kvm-i386-only-parse-the-initrd_filename-once-for-multibo.patch new file mode 100644 index 0000000..204cb8d --- /dev/null +++ b/SOURCES/kvm-i386-only-parse-the-initrd_filename-once-for-multibo.patch @@ -0,0 +1,115 @@ +From b9d1e72a0910c3a0d11cb0a3c863938de344e0f5 Mon Sep 17 00:00:00 2001 +From: Laszlo Ersek +Date: Thu, 12 Sep 2019 13:05:02 +0100 +Subject: [PATCH 05/22] i386: only parse the initrd_filename once for multiboot + modules +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Laszlo Ersek +Message-id: <20190912130503.14094-6-lersek@redhat.com> +Patchwork-id: 90438 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH 5/6] i386: only parse the initrd_filename once for multiboot modules +Bugzilla: 1749022 +RH-Acked-by: Stefano Garzarella +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Eduardo Habkost + +From: Daniel P. Berrangé + +The multiboot code parses the initrd_filename twice, first to count how +many entries there are, and second to process each entry. This changes +the first loop to store the parse module names in a list, and the second +loop can now use these names. This avoids having to pass NULL to the +get_opt_value() method which means it can safely assume a non-NULL param. + +Signed-off-by: Daniel P. Berrangé +Message-Id: <20180514171913.17664-3-berrange@redhat.com> +Reviewed-by: Eduardo Habkost +Tested-by: Roman Kagan +Signed-off-by: Paolo Bonzini +(cherry picked from commit f8da93a0ffa09268815c1942732cbc616a7db847) +Signed-off-by: Laszlo Ersek +Signed-off-by: Danilo C. L. de Paula +--- + hw/i386/multiboot.c | 32 +++++++++++++++----------------- + 1 file changed, 15 insertions(+), 17 deletions(-) + +diff --git a/hw/i386/multiboot.c b/hw/i386/multiboot.c +index 8e26545..d519e20 100644 +--- a/hw/i386/multiboot.c ++++ b/hw/i386/multiboot.c +@@ -161,6 +161,7 @@ int load_multiboot(FWCfgState *fw_cfg, + uint8_t bootinfo[MBI_SIZE]; + uint8_t *mb_bootinfo_data; + uint32_t cmdline_len; ++ GList *mods = NULL; + + /* Ok, let's see if it is a multiboot image. + The header is 12x32bit long, so the latest entry may be 8192 - 48. */ +@@ -291,15 +292,16 @@ int load_multiboot(FWCfgState *fw_cfg, + cmdline_len = strlen(kernel_filename) + 1; + cmdline_len += strlen(kernel_cmdline) + 1; + if (initrd_filename) { +- const char *r = get_opt_value(initrd_filename, NULL); ++ const char *r = initrd_filename; + cmdline_len += strlen(initrd_filename) + 1; +- while (1) { ++ while (*r) { ++ char *value; ++ r = get_opt_value(r, &value); + mbs.mb_mods_avail++; +- r = get_opt_value(r, NULL); +- if (!*r) { +- break; ++ mods = g_list_append(mods, value); ++ if (*r) { ++ r++; + } +- r++; + } + } + +@@ -314,20 +316,16 @@ int load_multiboot(FWCfgState *fw_cfg, + mbs.offset_cmdlines = mbs.offset_mbinfo + mbs.mb_mods_avail * MB_MOD_SIZE; + mbs.offset_bootloader = mbs.offset_cmdlines + cmdline_len; + +- if (initrd_filename) { +- const char *next_initrd; +- char not_last; +- char *one_file = NULL; +- ++ if (mods) { ++ GList *tmpl = mods; + mbs.offset_mods = mbs.mb_buf_size; + +- do { ++ while (tmpl) { + char *next_space; + int mb_mod_length; + uint32_t offs = mbs.mb_buf_size; ++ char *one_file = tmpl->data; + +- next_initrd = get_opt_value(initrd_filename, &one_file); +- not_last = *next_initrd; + /* if a space comes after the module filename, treat everything + after that as parameters */ + hwaddr c = mb_add_cmdline(&mbs, one_file); +@@ -352,10 +350,10 @@ int load_multiboot(FWCfgState *fw_cfg, + mb_debug("mod_start: %p\nmod_end: %p\n cmdline: "TARGET_FMT_plx, + (char *)mbs.mb_buf + offs, + (char *)mbs.mb_buf + offs + mb_mod_length, c); +- initrd_filename = next_initrd+1; + g_free(one_file); +- one_file = NULL; +- } while (not_last); ++ tmpl = tmpl->next; ++ } ++ g_list_free(mods); + } + + /* Commandline support */ +-- +1.8.3.1 + diff --git a/SOURCES/kvm-i386-remove-the-INTEL_PT-CPUID-bit-from-named-CPU-NEW.patch b/SOURCES/kvm-i386-remove-the-INTEL_PT-CPUID-bit-from-named-CPU-NEW.patch new file mode 100644 index 0000000..9e36c94 --- /dev/null +++ b/SOURCES/kvm-i386-remove-the-INTEL_PT-CPUID-bit-from-named-CPU-NEW.patch @@ -0,0 +1,52 @@ +From 6131491c7a5494c1c034973ae23fc842b1ee733e Mon Sep 17 00:00:00 2001 +From: "plai@redhat.com" +Date: Mon, 1 Jul 2019 16:17:33 +0100 +Subject: [PATCH 04/39] i386: remove the 'INTEL_PT' CPUID bit from named CPU + models + +RH-Author: plai@redhat.com +Message-id: <1561997854-9646-5-git-send-email-plai@redhat.com> +Patchwork-id: 89332 +O-Subject: [RHEL8.1 qemu-kvm PATCH v6 4/5] i386: remove the 'INTEL_PT' CPUID bit from named CPU models +Bugzilla: 1629906 +RH-Acked-by: Eduardo Habkost +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Bandan Das + +From: Paolo Bonzini + +Processor tracing is not yet implemented for KVM and it will be an +opt in feature requiring a special module parameter. +Disable it, because it is wrong to enable it by default and +it is impossible that no one has ever used it. + +Cc: qemu-stable@nongnu.org +Signed-off-by: Paolo Bonzini +(cherry picked from commit 4c257911dcc7c4189768e9651755c849ce9db4e8) +Signed-off-by: Paul Lai + +Resolved Conflicts: + target/i386/cpu.c + +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index 094f8a1..2538d82 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -2515,8 +2515,7 @@ static X86CPUDefinition builtin_x86_defs[] = { + CPUID_7_0_EBX_SMAP | CPUID_7_0_EBX_CLWB | + CPUID_7_0_EBX_AVX512F | CPUID_7_0_EBX_AVX512DQ | + CPUID_7_0_EBX_AVX512BW | CPUID_7_0_EBX_AVX512CD | +- CPUID_7_0_EBX_AVX512VL | CPUID_7_0_EBX_CLFLUSHOPT | +- CPUID_7_0_EBX_INTEL_PT, ++ CPUID_7_0_EBX_AVX512VL | CPUID_7_0_EBX_CLFLUSHOPT, + .features[FEAT_7_0_ECX] = + CPUID_7_0_ECX_PKU | CPUID_7_0_ECX_OSPKE | + CPUID_7_0_ECX_AVX512VNNI, +-- +1.8.3.1 + diff --git a/SOURCES/kvm-i386-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-Correct-caching-mode-error-message.patch b/SOURCES/kvm-intel_iommu-Correct-caching-mode-error-message.patch new file mode 100644 index 0000000..02b5255 --- /dev/null +++ b/SOURCES/kvm-intel_iommu-Correct-caching-mode-error-message.patch @@ -0,0 +1,59 @@ +From 8954b0306e2179987cd097d203057e780808b0ba Mon Sep 17 00:00:00 2001 +From: Peter Xu +Date: Wed, 9 Oct 2019 12:39:43 +0100 +Subject: [PATCH 17/22] intel_iommu: Correct caching-mode error message +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Peter Xu +Message-id: <20191009123947.21505-2-peterx@redhat.com> +Patchwork-id: 91350 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH 1/5] intel_iommu: Correct caching-mode error message +Bugzilla: 1738440 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Auger Eric +RH-Acked-by: Alex Williamson + +From: Alex Williamson + +If we try to use the intel-iommu device with vfio-pci devices without +caching mode enabled, we're told: + + qemu-system-x86_64: We need to set caching-mode=1 for intel-iommu to enable + device assignment with IOMMU protection. + +But to enable caching mode, the option is actually "caching-mode=on". + +Signed-off-by: Alex Williamson +Message-Id: <155364147432.16467.15898335025013220939.stgit@gimli.home> +Reviewed-by: Peter Xu +Reviewed-by: Laurent Vivier +Reviewed-by: Philippe Mathieu-Daudé +Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
+Reviewed-by: Eric Auger +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +(cherry picked from commit 75c5626c88a9675010018849ca9abc8d56045425) +Signed-off-by: Peter Xu +Signed-off-by: Danilo C. L. de Paula +--- + hw/i386/intel_iommu.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c +index e827c5a..22d2e52 100644 +--- a/hw/i386/intel_iommu.c ++++ b/hw/i386/intel_iommu.c +@@ -2554,7 +2554,7 @@ static void vtd_iommu_notify_flag_changed(IOMMUMemoryRegion *iommu, + IntelIOMMUState *s = vtd_as->iommu_state; + + if (!s->caching_mode && new & IOMMU_NOTIFIER_MAP) { +- error_report("We need to set caching-mode=1 for intel-iommu to enable " ++ error_report("We need to set caching-mode=on for intel-iommu to enable " + "device assignment with IOMMU protection."); + exit(1); + } +-- +1.8.3.1 + diff --git a/SOURCES/kvm-intel_iommu-Remove-the-caching-mode-check-during-fla.patch b/SOURCES/kvm-intel_iommu-Remove-the-caching-mode-check-during-fla.patch new file mode 100644 index 0000000..1f45fc0 --- /dev/null +++ b/SOURCES/kvm-intel_iommu-Remove-the-caching-mode-check-during-fla.patch @@ -0,0 +1,49 @@ +From 01ab894f9d19a03aee876b0d1b468f7314765539 Mon Sep 17 00:00:00 2001 +From: Peter Xu +Date: Wed, 9 Oct 2019 12:39:47 +0100 +Subject: [PATCH 21/22] intel_iommu: Remove the caching-mode check during flag + change + +RH-Author: Peter Xu +Message-id: <20191009123947.21505-6-peterx@redhat.com> +Patchwork-id: 91349 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH 5/5] intel_iommu: Remove the caching-mode check during flag change +Bugzilla: 1738440 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Auger Eric +RH-Acked-by: Alex Williamson + +That's never a good place to stop QEMU process... Since now we have +both the machine done sanity check and also the hotplug handler, we +can safely remove this to avoid that. + +Reviewed-by: Eric Auger +Signed-off-by: Peter Xu +Message-Id: <20190916080718.3299-5-peterx@redhat.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +(cherry picked from commit e7df189e19e86bf9f4d7aea4c6cf50ac0ebfce46) +Signed-off-by: Peter Xu +Signed-off-by: Danilo C. L. de Paula +--- + hw/i386/intel_iommu.c | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c +index 44d19cc..a4190bf 100644 +--- a/hw/i386/intel_iommu.c ++++ b/hw/i386/intel_iommu.c +@@ -2561,10 +2561,6 @@ static void vtd_iommu_notify_flag_changed(IOMMUMemoryRegion *iommu, + VTDAddressSpace *vtd_as = container_of(iommu, VTDAddressSpace, iommu); + IntelIOMMUState *s = vtd_as->iommu_state; + +- if (!s->caching_mode && new & IOMMU_NOTIFIER_MAP) { +- vtd_panic_require_caching_mode(); +- } +- + /* Update per-address-space notifier flags */ + vtd_as->notifier_flags = new; + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-intel_iommu-Sanity-check-vfio-pci-config-on-machine-.patch b/SOURCES/kvm-intel_iommu-Sanity-check-vfio-pci-config-on-machine-.patch new file mode 100644 index 0000000..ed7753f --- /dev/null +++ b/SOURCES/kvm-intel_iommu-Sanity-check-vfio-pci-config-on-machine-.patch @@ -0,0 +1,131 @@ +From 3a528a458d4a2ba4236e98ef3f4efe5482323972 Mon Sep 17 00:00:00 2001 +From: Peter Xu +Date: Wed, 9 Oct 2019 12:39:44 +0100 +Subject: [PATCH 18/22] intel_iommu: Sanity check vfio-pci config on machine + init done + +RH-Author: Peter Xu +Message-id: <20191009123947.21505-3-peterx@redhat.com> +Patchwork-id: 91347 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH 2/5] intel_iommu: Sanity check vfio-pci config on machine init done +Bugzilla: 1738440 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Auger Eric +RH-Acked-by: Alex Williamson + +This check was previously only happened when the IOMMU is enabled in +the guest. It was always too late because the enabling of IOMMU +normally only happens during the boot of guest OS. It means that we +can bail out and exit directly during the guest OS boots if the +configuration of devices are not supported. Or, if the guest didn't +enable vIOMMU at all, then the user can use the guest normally but as +long as it reconfigure the guest OS to enable the vIOMMU then reboot, +the user will see the panic right after the reset when the next boot +starts. + +Let's make this failure even earlier so that we force the user to use +caching-mode for vfio-pci devices when with the vIOMMU. So the user +won't get surprise at least during execution of the guest, which seems +a bit nicer. + +This will affect some user who didn't enable vIOMMU in the guest OS +but was using vfio-pci and the vtd device in the past. However I hope +it's not a majority because not enabling vIOMMU with the device +attached is actually meaningless. + +We still keep the old assertion for safety so far because the hotplug +path could still reach it, so far. + +Reviewed-by: Eric Auger +Signed-off-by: Peter Xu +Message-Id: <20190916080718.3299-2-peterx@redhat.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +(cherry picked from commit 28cf553afeb29b0c4f339c600171552a72a68cb7) +Signed-off-by: Peter Xu +Signed-off-by: Danilo C. L. de Paula +--- + hw/i386/intel_iommu.c | 39 ++++++++++++++++++++++++++++++++++++--- + 1 file changed, 36 insertions(+), 3 deletions(-) + +diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c +index 22d2e52..44d19cc 100644 +--- a/hw/i386/intel_iommu.c ++++ b/hw/i386/intel_iommu.c +@@ -33,6 +33,7 @@ + #include "hw/i386/x86-iommu.h" + #include "hw/pci-host/q35.h" + #include "sysemu/kvm.h" ++#include "sysemu/sysemu.h" + #include "hw/i386/apic_internal.h" + #include "kvm_i386.h" + #include "trace.h" +@@ -40,6 +41,13 @@ + static void vtd_address_space_refresh_all(IntelIOMMUState *s); + static void vtd_address_space_unmap(VTDAddressSpace *as, IOMMUNotifier *n); + ++static void vtd_panic_require_caching_mode(void) ++{ ++ error_report("We need to set caching-mode=on for intel-iommu to enable " ++ "device assignment with IOMMU protection."); ++ exit(1); ++} ++ + static void vtd_define_quad(IntelIOMMUState *s, hwaddr addr, uint64_t val, + uint64_t wmask, uint64_t w1cmask) + { +@@ -2554,9 +2562,7 @@ static void vtd_iommu_notify_flag_changed(IOMMUMemoryRegion *iommu, + IntelIOMMUState *s = vtd_as->iommu_state; + + if (!s->caching_mode && new & IOMMU_NOTIFIER_MAP) { +- error_report("We need to set caching-mode=on for intel-iommu to enable " +- "device assignment with IOMMU protection."); +- exit(1); ++ vtd_panic_require_caching_mode(); + } + + /* Update per-address-space notifier flags */ +@@ -3303,6 +3309,32 @@ static bool vtd_decide_config(IntelIOMMUState *s, Error **errp) + return true; + } + ++static int vtd_machine_done_notify_one(Object *child, void *unused) ++{ ++ IntelIOMMUState *iommu = INTEL_IOMMU_DEVICE(x86_iommu_get_default()); ++ ++ /* ++ * We hard-coded here because vfio-pci is the only special case ++ * here. Let's be more elegant in the future when we can, but so ++ * far there seems to be no better way. ++ */ ++ if (object_dynamic_cast(child, "vfio-pci") && !iommu->caching_mode) { ++ vtd_panic_require_caching_mode(); ++ } ++ ++ return 0; ++} ++ ++static void vtd_machine_done_hook(Notifier *notifier, void *unused) ++{ ++ object_child_foreach_recursive(object_get_root(), ++ vtd_machine_done_notify_one, NULL); ++} ++ ++static Notifier vtd_machine_done_notify = { ++ .notify = vtd_machine_done_hook, ++}; ++ + static void vtd_realize(DeviceState *dev, Error **errp) + { + MachineState *ms = MACHINE(qdev_get_machine()); +@@ -3333,6 +3365,7 @@ static void vtd_realize(DeviceState *dev, Error **errp) + pci_setup_iommu(bus, vtd_host_dma_iommu, dev); + /* Pseudo address space under root PCI bus. */ + pcms->ioapic_as = vtd_host_dma_iommu(bus, s, Q35_PSEUDO_DEVFN_IOAPIC); ++ qemu_add_machine_init_done_notifier(&vtd_machine_done_notify); + } + + static void vtd_class_init(ObjectClass *klass, void *data) +-- +1.8.3.1 + diff --git a/SOURCES/kvm-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-iscsi-Avoid-potential-for-get_status-overflow.patch b/SOURCES/kvm-iscsi-Avoid-potential-for-get_status-overflow.patch new file mode 100644 index 0000000..a4eddb2 --- /dev/null +++ b/SOURCES/kvm-iscsi-Avoid-potential-for-get_status-overflow.patch @@ -0,0 +1,61 @@ +From 242abde4b0152142787bd3200de5cc35863da59a Mon Sep 17 00:00:00 2001 +From: jmaloy +Date: Wed, 29 Jan 2020 21:41:14 +0000 +Subject: [PATCH 1/6] iscsi: Avoid potential for get_status overflow +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: jmaloy +Message-id: <20200129214115.19979-2-jmaloy@redhat.com> +Patchwork-id: 93587 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH 1/2] iscsi: Avoid potential for get_status overflow +Bugzilla: 1794501 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Kevin Wolf +RH-Acked-by: Philippe Mathieu-Daudé + +From: Eric Blake + +Detected by Coverity: Multiplying two 32-bit int and assigning +the result to a 64-bit number is a risk of overflow. Prior to +the conversion to byte-based interfaces, the block layer took +care of ensuring that a status request never exceeded 2G in +the driver; but after that conversion, the block layer expects +drivers to deal with any size request (the driver can always +truncate the request size back down, as long as it makes +progress). So, in the off-chance that someone makes a large +request, we are at the mercy of whether iscsi_get_lba_status_task() +will cap things to at most INT_MAX / iscsilun->block_size when +it populates lbasd->num_blocks; since I could not easily audit +that, it's better to be safe than sorry by just forcing a 64-bit +multiply. + +Fixes: 92809c36 +CC: qemu-stable@nongnu.org +Signed-off-by: Eric Blake +Message-Id: <20180508212718.1482663-1-eblake@redhat.com> +Reviewed-by: Philippe Mathieu-Daudé +(cherry picked from commit 8ee1cef4593a7bda076891470c0620e79333c0d0) +Signed-off-by: Jon Maloy +Signed-off-by: Danilo C. L. de Paula +--- + block/iscsi.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/block/iscsi.c b/block/iscsi.c +index c412b12..336ce49 100644 +--- a/block/iscsi.c ++++ b/block/iscsi.c +@@ -734,7 +734,7 @@ retry: + goto out_unlock; + } + +- *pnum = lbasd->num_blocks * iscsilun->block_size; ++ *pnum = (int64_t) lbasd->num_blocks * iscsilun->block_size; + + if (lbasd->provisioning == SCSI_PROVISIONING_TYPE_DEALLOCATED || + lbasd->provisioning == SCSI_PROVISIONING_TYPE_ANCHORED) { +-- +1.8.3.1 + diff --git a/SOURCES/kvm-iscsi-Cap-block-count-from-GET-LBA-STATUS-CVE-2020-1.patch b/SOURCES/kvm-iscsi-Cap-block-count-from-GET-LBA-STATUS-CVE-2020-1.patch new file mode 100644 index 0000000..ae34541 --- /dev/null +++ b/SOURCES/kvm-iscsi-Cap-block-count-from-GET-LBA-STATUS-CVE-2020-1.patch @@ -0,0 +1,79 @@ +From 7dd9696a1b288746bac6fa0fe4f1d212be4f8f82 Mon Sep 17 00:00:00 2001 +From: jmaloy +Date: Wed, 29 Jan 2020 21:41:15 +0000 +Subject: [PATCH 2/6] iscsi: Cap block count from GET LBA STATUS + (CVE-2020-1711) +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: jmaloy +Message-id: <20200129214115.19979-3-jmaloy@redhat.com> +Patchwork-id: 93585 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH 2/2] iscsi: Cap block count from GET LBA STATUS (CVE-2020-1711) +Bugzilla: 1794501 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Kevin Wolf +RH-Acked-by: Philippe Mathieu-Daudé + +From: Felipe Franciosi + +When querying an iSCSI server for the provisioning status of blocks (via +GET LBA STATUS), Qemu only validates that the response descriptor zero's +LBA matches the one requested. Given the SCSI spec allows servers to +respond with the status of blocks beyond the end of the LUN, Qemu may +have its heap corrupted by clearing/setting too many bits at the end of +its allocmap for the LUN. + +A malicious guest in control of the iSCSI server could carefully program +Qemu's heap (by selectively setting the bitmap) and then smash it. + +This limits the number of bits that iscsi_co_block_status() will try to +update in the allocmap so it can't overflow the bitmap. + +Fixes: CVE-2020-1711 +Cc: qemu-stable@nongnu.org +Signed-off-by: Felipe Franciosi +Signed-off-by: Peter Turschmid +Signed-off-by: Raphael Norwitz +Signed-off-by: Kevin Wolf +(cherry picked from commit 693fd2acdf14dd86c0bf852610f1c2cca80a74dc) +Signed-off-by: Jon Maloy +Signed-off-by: Danilo C. L. de Paula +--- + block/iscsi.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/block/iscsi.c b/block/iscsi.c +index 336ce49..8ec97ab 100644 +--- a/block/iscsi.c ++++ b/block/iscsi.c +@@ -671,7 +671,7 @@ static int coroutine_fn iscsi_co_block_status(BlockDriverState *bs, + struct scsi_get_lba_status *lbas = NULL; + struct scsi_lba_status_descriptor *lbasd = NULL; + struct IscsiTask iTask; +- uint64_t lba; ++ uint64_t lba, max_bytes; + int ret; + + iscsi_co_init_iscsitask(iscsilun, &iTask); +@@ -691,6 +691,7 @@ static int coroutine_fn iscsi_co_block_status(BlockDriverState *bs, + } + + lba = offset / iscsilun->block_size; ++ max_bytes = (iscsilun->num_blocks - lba) * iscsilun->block_size; + + qemu_mutex_lock(&iscsilun->mutex); + retry: +@@ -734,7 +735,7 @@ retry: + goto out_unlock; + } + +- *pnum = (int64_t) lbasd->num_blocks * iscsilun->block_size; ++ *pnum = MIN((int64_t) lbasd->num_blocks * iscsilun->block_size, max_bytes); + + if (lbasd->provisioning == SCSI_PROVISIONING_TYPE_DEALLOCATED || + lbasd->provisioning == SCSI_PROVISIONING_TYPE_ANCHORED) { +-- +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-mmap-alloc-fix-hugetlbfs-misaligned-length-in-ppc64.patch b/SOURCES/kvm-mmap-alloc-fix-hugetlbfs-misaligned-length-in-ppc64.patch new file mode 100644 index 0000000..c3f4fa9 --- /dev/null +++ b/SOURCES/kvm-mmap-alloc-fix-hugetlbfs-misaligned-length-in-ppc64.patch @@ -0,0 +1,174 @@ +From e69f257e657473ba59f48692d387e292a24892bb Mon Sep 17 00:00:00 2001 +From: "plai@redhat.com" +Date: Tue, 20 Aug 2019 16:12:50 +0100 +Subject: [PATCH 03/11] mmap-alloc: fix hugetlbfs misaligned length in ppc64 + +RH-Author: plai@redhat.com +Message-id: <1566317571-5697-4-git-send-email-plai@redhat.com> +Patchwork-id: 90082 +O-Subject: [RHEL8.2 qemu-kvm PATCH 3/4] mmap-alloc: fix hugetlbfs misaligned length in ppc64 +Bugzilla: 1539282 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Pankaj Gupta +RH-Acked-by: Eduardo Habkost + +From: Murilo Opsfelder Araujo + +The commit 7197fb4058bcb68986bae2bb2c04d6370f3e7218 ("util/mmap-alloc: +fix hugetlb support on ppc64") fixed Huge TLB mappings on ppc64. + +However, we still need to consider the underlying huge page size +during munmap() because it requires that both address and length be a +multiple of the underlying huge page size for Huge TLB mappings. +Quote from "Huge page (Huge TLB) mappings" paragraph under NOTES +section of the munmap(2) manual: + + "For munmap(), addr and length must both be a multiple of the + underlying huge page size." + +On ppc64, the munmap() in qemu_ram_munmap() does not work for Huge TLB +mappings because the mapped segment can be aligned with the underlying +huge page size, not aligned with the native system page size, as +returned by getpagesize(). + +This has the side effect of not releasing huge pages back to the pool +after a hugetlbfs file-backed memory device is hot-unplugged. + +This patch fixes the situation in qemu_ram_mmap() and +qemu_ram_munmap() by considering the underlying page size on ppc64. + +After this patch, memory hot-unplug releases huge pages back to the +pool. + +Fixes: 7197fb4058bcb68986bae2bb2c04d6370f3e7218 +Signed-off-by: Murilo Opsfelder Araujo +Reviewed-by: Greg Kurz +Signed-off-by: David Gibson +(cherry picked from commit 53adb9d43e1abba187387a51f238e878e934c647) +Signed-off-by: Paul Lai +Signed-off-by: Danilo C. L. de Paula +--- + exec.c | 4 ++-- + include/qemu/mmap-alloc.h | 2 +- + util/mmap-alloc.c | 22 ++++++++++++++++------ + util/oslib-posix.c | 2 +- + 4 files changed, 20 insertions(+), 10 deletions(-) + +diff --git a/exec.c b/exec.c +index a79eaa3..9112d8b 100644 +--- a/exec.c ++++ b/exec.c +@@ -1679,7 +1679,7 @@ static void *file_ram_alloc(RAMBlock *block, + if (mem_prealloc) { + os_mem_prealloc(fd, area, memory, smp_cpus, errp); + if (errp && *errp) { +- qemu_ram_munmap(area, memory); ++ qemu_ram_munmap(fd, area, memory); + return NULL; + } + } +@@ -2200,7 +2200,7 @@ static void reclaim_ramblock(RAMBlock *block) + xen_invalidate_map_cache_entry(block->host); + #ifndef _WIN32 + } else if (block->fd >= 0) { +- qemu_ram_munmap(block->host, block->max_length); ++ qemu_ram_munmap(block->fd, block->host, block->max_length); + close(block->fd); + #endif + } else { +diff --git a/include/qemu/mmap-alloc.h b/include/qemu/mmap-alloc.h +index 190688a..eec98d8 100644 +--- a/include/qemu/mmap-alloc.h ++++ b/include/qemu/mmap-alloc.h +@@ -28,6 +28,6 @@ void *qemu_ram_mmap(int fd, + bool shared, + bool is_pmem); + +-void qemu_ram_munmap(void *ptr, size_t size); ++void qemu_ram_munmap(int fd, void *ptr, size_t size); + + #endif +diff --git a/util/mmap-alloc.c b/util/mmap-alloc.c +index b29fcee..bbd9077 100644 +--- a/util/mmap-alloc.c ++++ b/util/mmap-alloc.c +@@ -82,6 +82,7 @@ void *qemu_ram_mmap(int fd, + int flags; + int guardfd; + size_t offset; ++ size_t pagesize; + size_t total; + void *guardptr; + void *ptr; +@@ -102,7 +103,8 @@ void *qemu_ram_mmap(int fd, + * anonymous memory is OK. + */ + flags = MAP_PRIVATE; +- if (fd == -1 || qemu_fd_getpagesize(fd) == getpagesize()) { ++ pagesize = qemu_fd_getpagesize(fd); ++ if (fd == -1 || pagesize == getpagesize()) { + guardfd = -1; + flags |= MAP_ANONYMOUS; + } else { +@@ -111,6 +113,7 @@ void *qemu_ram_mmap(int fd, + } + #else + guardfd = -1; ++ pagesize = getpagesize(); + flags = MAP_PRIVATE | MAP_ANONYMOUS; + #endif + +@@ -122,7 +125,7 @@ void *qemu_ram_mmap(int fd, + + assert(is_power_of_2(align)); + /* Always align to host page size */ +- assert(align >= getpagesize()); ++ assert(align >= pagesize); + + flags = MAP_FIXED; + flags |= fd == -1 ? MAP_ANONYMOUS : 0; +@@ -145,17 +148,24 @@ void *qemu_ram_mmap(int fd, + * a guard page guarding against potential buffer overflows. + */ + total -= offset; +- if (total > size + getpagesize()) { +- munmap(ptr + size + getpagesize(), total - size - getpagesize()); ++ if (total > size + pagesize) { ++ munmap(ptr + size + pagesize, total - size - pagesize); + } + + return ptr; + } + +-void qemu_ram_munmap(void *ptr, size_t size) ++void qemu_ram_munmap(int fd, void *ptr, size_t size) + { ++ size_t pagesize; ++ + if (ptr) { + /* Unmap both the RAM block and the guard page */ +- munmap(ptr, size + getpagesize()); ++#if defined(__powerpc64__) && defined(__linux__) ++ pagesize = qemu_fd_getpagesize(fd); ++#else ++ pagesize = getpagesize(); ++#endif ++ munmap(ptr, size + pagesize); + } + } +diff --git a/util/oslib-posix.c b/util/oslib-posix.c +index c36b2bb..7b6db04 100644 +--- a/util/oslib-posix.c ++++ b/util/oslib-posix.c +@@ -153,7 +153,7 @@ void qemu_vfree(void *ptr) + void qemu_anon_ram_free(void *ptr, size_t size) + { + trace_qemu_anon_ram_free(ptr, size); +- qemu_ram_munmap(ptr, size); ++ qemu_ram_munmap(-1, ptr, size); + } + + void qemu_set_block(int fd) +-- +1.8.3.1 + diff --git a/SOURCES/kvm-mmap-alloc-unfold-qemu_ram_mmap.patch b/SOURCES/kvm-mmap-alloc-unfold-qemu_ram_mmap.patch new file mode 100644 index 0000000..fdc21ec --- /dev/null +++ b/SOURCES/kvm-mmap-alloc-unfold-qemu_ram_mmap.patch @@ -0,0 +1,139 @@ +From 6b3478bb8b5718d86cb04f41043a8e0cce4df24c Mon Sep 17 00:00:00 2001 +From: "plai@redhat.com" +Date: Tue, 20 Aug 2019 16:12:49 +0100 +Subject: [PATCH 02/11] mmap-alloc: unfold qemu_ram_mmap() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: plai@redhat.com +Message-id: <1566317571-5697-3-git-send-email-plai@redhat.com> +Patchwork-id: 90083 +O-Subject: [RHEL8.2 qemu-kvm PATCH 2/4] mmap-alloc: unfold qemu_ram_mmap() +Bugzilla: 1539282 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Pankaj Gupta +RH-Acked-by: Eduardo Habkost + +From: Murilo Opsfelder Araujo + +Unfold parts of qemu_ram_mmap() for the sake of understanding, moving +declarations to the top, and keeping architecture-specifics in the +ifdef-else blocks. No changes in the function behaviour. + +Give ptr and ptr1 meaningful names: + ptr -> guardptr : pointer to the PROT_NONE guard region + ptr1 -> ptr : pointer to the mapped memory returned to caller + +Signed-off-by: Murilo Opsfelder Araujo +Reviewed-by: Greg Kurz +Signed-off-by: David Gibson +(cherry picked from commit 2044c3e7116eeac0449dcb4a4130cc8f8b9310da) +Signed-off-by: Paul Lai +Signed-off-by: Danilo C. L. de Paula +--- + util/mmap-alloc.c | 53 ++++++++++++++++++++++++++++++++++------------------- + 1 file changed, 34 insertions(+), 19 deletions(-) + +diff --git a/util/mmap-alloc.c b/util/mmap-alloc.c +index 55d1890..b29fcee 100644 +--- a/util/mmap-alloc.c ++++ b/util/mmap-alloc.c +@@ -79,11 +79,19 @@ void *qemu_ram_mmap(int fd, + bool shared, + bool is_pmem) + { ++ int flags; ++ int guardfd; ++ size_t offset; ++ size_t total; ++ void *guardptr; ++ void *ptr; ++ + /* + * Note: this always allocates at least one extra page of virtual address + * space, even if size is already aligned. + */ +- size_t total = size + align; ++ total = size + align; ++ + #if defined(__powerpc64__) && defined(__linux__) + /* On ppc64 mappings in the same segment (aka slice) must share the same + * page size. Since we will be re-allocating part of this segment +@@ -93,16 +101,22 @@ void *qemu_ram_mmap(int fd, + * We do this unless we are using the system page size, in which case + * anonymous memory is OK. + */ +- int anonfd = fd == -1 || qemu_fd_getpagesize(fd) == getpagesize() ? -1 : fd; +- int flags = anonfd == -1 ? MAP_ANONYMOUS : MAP_NORESERVE; +- void *ptr = mmap(0, total, PROT_NONE, flags | MAP_PRIVATE, anonfd, 0); ++ flags = MAP_PRIVATE; ++ if (fd == -1 || qemu_fd_getpagesize(fd) == getpagesize()) { ++ guardfd = -1; ++ flags |= MAP_ANONYMOUS; ++ } else { ++ guardfd = fd; ++ flags |= MAP_NORESERVE; ++ } + #else +- void *ptr = mmap(0, total, PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); ++ guardfd = -1; ++ flags = MAP_PRIVATE | MAP_ANONYMOUS; + #endif +- size_t offset; +- void *ptr1; + +- if (ptr == MAP_FAILED) { ++ guardptr = mmap(0, total, PROT_NONE, flags, guardfd, 0); ++ ++ if (guardptr == MAP_FAILED) { + return MAP_FAILED; + } + +@@ -110,19 +124,20 @@ void *qemu_ram_mmap(int fd, + /* Always align to host page size */ + assert(align >= getpagesize()); + +- offset = QEMU_ALIGN_UP((uintptr_t)ptr, align) - (uintptr_t)ptr; +- ptr1 = mmap(ptr + offset, size, PROT_READ | PROT_WRITE, +- MAP_FIXED | +- (fd == -1 ? MAP_ANONYMOUS : 0) | +- (shared ? MAP_SHARED : MAP_PRIVATE), +- fd, 0); +- if (ptr1 == MAP_FAILED) { +- munmap(ptr, total); ++ flags = MAP_FIXED; ++ flags |= fd == -1 ? MAP_ANONYMOUS : 0; ++ flags |= shared ? MAP_SHARED : MAP_PRIVATE; ++ offset = QEMU_ALIGN_UP((uintptr_t)guardptr, align) - (uintptr_t)guardptr; ++ ++ ptr = mmap(guardptr + offset, size, PROT_READ | PROT_WRITE, flags, fd, 0); ++ ++ if (ptr == MAP_FAILED) { ++ munmap(guardptr, total); + return MAP_FAILED; + } + + if (offset > 0) { +- munmap(ptr, offset); ++ munmap(guardptr, offset); + } + + /* +@@ -131,10 +146,10 @@ void *qemu_ram_mmap(int fd, + */ + total -= offset; + if (total > size + getpagesize()) { +- munmap(ptr1 + size + getpagesize(), total - size - getpagesize()); ++ munmap(ptr + size + getpagesize(), total - size - getpagesize()); + } + +- return ptr1; ++ return ptr; + } + + void qemu_ram_munmap(void *ptr, size_t size) +-- +1.8.3.1 + diff --git a/SOURCES/kvm-nbd-client-Lower-min_block-for-block-status-unaligne.patch b/SOURCES/kvm-nbd-client-Lower-min_block-for-block-status-unaligne.patch new file mode 100644 index 0000000..1573c0f --- /dev/null +++ b/SOURCES/kvm-nbd-client-Lower-min_block-for-block-status-unaligne.patch @@ -0,0 +1,119 @@ +From 569674a3b855f516a8bec22ca365fc7614639ce6 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Tue, 23 Jul 2019 14:45:42 +0100 +Subject: [PATCH 04/14] nbd/client: Lower min_block for block-status, unaligned + size + +RH-Author: Max Reitz +Message-id: <20190723144546.23701-4-mreitz@redhat.com> +Patchwork-id: 89650 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 3/7] nbd/client: Lower min_block for block-status, unaligned size +Bugzilla: 1678979 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Stefano Garzarella +RH-Acked-by: John Snow + +From: Eric Blake + +We have a latent bug in our NBD client code, tickled by the brand new +nbdkit 1.11.10 block status support: + +$ nbdkit --filter=log --filter=truncate -U - \ + data data="1" size=511 truncate=64K logfile=/dev/stdout \ + --run 'qemu-img convert $nbd /var/tmp/out' +... +qemu-img: block/io.c:2122: bdrv_co_block_status: Assertion `*pnum && QEMU_IS_ALIGNED(*pnum, align) && align > offset - aligned_offset' failed. + +The culprit? Our implementation of .bdrv_co_block_status can return +unaligned block status for any server that operates with a lower +actual alignment than what we tell the block layer in +request_alignment, in violation of the block layer's constraints. To +date, we've been unable to trip the bug, because qemu as NBD server +always advertises block sizing (at which point it is a server bug if +the server sends unaligned status - although qemu 3.1 is such a server +and I've sent separate patches for 4.0 both to get the server to obey +the spec, and to let the client to tolerate server oddities at EOF). + +But nbdkit does not (yet) advertise block sizing, and therefore is not +in violation of the spec for returning block status at whatever +boundaries it wants, and those unaligned results can occur anywhere +rather than just at EOF. While we are still wise to avoid sending +sub-sector read/write requests to a server of unknown origin, we MUST +consider that a server telling us block status without an advertised +block size is correct. So, we either have to munge unaligned answers +from the server into aligned ones that we hand back to the block +layer, or we have to tell the block layer about a smaller alignment. + +Similarly, if the server advertises an image size that is not +sector-aligned, we might as well assume that the server intends to let +us access those tail bytes, and therefore supports a minimum block +size of 1, regardless of whether the server supports block status +(although we still need more patches to fix the problem that with an +unaligned image, we can send read or block status requests that exceed +EOF to the server). Again, qemu as server cannot trip this problem +(because it rounds images to sector alignment), but nbdkit advertised +unaligned size even before it gained block status support. + +Solve both alignment problems at once by using better heuristics on +what alignment to report to the block layer when the server did not +give us something to work with. Note that very few NBD servers +implement block status (to date, only qemu and nbdkit are known to do +so); and as the NBD spec mentioned block sizing constraints prior to +documenting block status, it can be assumed that any future +implementations of block status are aware that they must advertise +block size if they want a minimum size other than 1. + +We've had a long history of struggles with picking the right alignment +to use in the block layer, as evidenced by the commit message of +fd8d372d (v2.12) that introduced the current choice of forced 512-byte +alignment. + +There is no iotest coverage for this fix, because qemu can't provoke +it, and I didn't want to make test 241 dependent on nbdkit. + +Fixes: fd8d372d +Reported-by: Richard W.M. Jones +Signed-off-by: Eric Blake +Message-Id: <20190329042750.14704-3-eblake@redhat.com> +Reviewed-by: Vladimir Sementsov-Ogievskiy +Tested-by: Richard W.M. Jones +(cherry picked from commit 7da537f70d929800ba9c657b8a47a7b827695ccc) +Signed-off-by: Max Reitz +Signed-off-by: Danilo C. L. de Paula +--- + block/nbd.c | 19 ++++++++++++++++++- + 1 file changed, 18 insertions(+), 1 deletion(-) + +diff --git a/block/nbd.c b/block/nbd.c +index f29c10f..3d642cd 100644 +--- a/block/nbd.c ++++ b/block/nbd.c +@@ -473,7 +473,24 @@ static void nbd_refresh_limits(BlockDriverState *bs, Error **errp) + uint32_t min = s->info.min_block; + uint32_t max = MIN_NON_ZERO(NBD_MAX_BUFFER_SIZE, s->info.max_block); + +- bs->bl.request_alignment = min ? min : BDRV_SECTOR_SIZE; ++ /* ++ * If the server did not advertise an alignment: ++ * - a size that is not sector-aligned implies that an alignment ++ * of 1 can be used to access those tail bytes ++ * - advertisement of block status requires an alignment of 1, so ++ * that we don't violate block layer constraints that block ++ * status is always aligned (as we can't control whether the ++ * server will report sub-sector extents, such as a hole at EOF ++ * on an unaligned POSIX file) ++ * - otherwise, assume the server is so old that we are safer avoiding ++ * sub-sector requests ++ */ ++ if (!min) { ++ min = (!QEMU_IS_ALIGNED(s->info.size, BDRV_SECTOR_SIZE) || ++ s->info.base_allocation) ? 1 : BDRV_SECTOR_SIZE; ++ } ++ ++ bs->bl.request_alignment = min; + bs->bl.max_pdiscard = max; + bs->bl.max_pwrite_zeroes = max; + bs->bl.max_transfer = max; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-nbd-client-Reject-inaccessible-tail-of-inconsistent-.patch b/SOURCES/kvm-nbd-client-Reject-inaccessible-tail-of-inconsistent-.patch new file mode 100644 index 0000000..9061a46 --- /dev/null +++ b/SOURCES/kvm-nbd-client-Reject-inaccessible-tail-of-inconsistent-.patch @@ -0,0 +1,64 @@ +From e49b010d5f866b3ee7efbf40398f0a0832ce8801 Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Tue, 23 Jul 2019 14:45:43 +0100 +Subject: [PATCH 05/14] nbd/client: Reject inaccessible tail of inconsistent + server + +RH-Author: Max Reitz +Message-id: <20190723144546.23701-5-mreitz@redhat.com> +Patchwork-id: 89649 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 4/7] nbd/client: Reject inaccessible tail of inconsistent server +Bugzilla: 1678979 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Stefano Garzarella +RH-Acked-by: John Snow + +From: Eric Blake + +The NBD spec suggests that a server should never advertise a size +inconsistent with its minimum block alignment, as that tail is +effectively inaccessible to a compliant client obeying those block +constraints. Since we have a habit of rounding up rather than +truncating, to avoid losing the last few bytes of user input, and we +cannot access the tail when the server advertises bogus block sizing, +abort the connection to alert the server to fix their bug. And +rejecting such servers matches what we already did for a min_block +that was not a power of 2 or which was larger than max_block. + +Does not impact either qemu (which always sends properly aligned +sizes) or nbdkit (which does not send minimum block requirements yet); +so this is mostly aimed at new NBD server implementations, and ensures +that the rest of our code can assume the size is aligned. + +Signed-off-by: Eric Blake +Message-Id: <20190330155704.24191-1-eblake@redhat.com> +Reviewed-by: Vladimir Sementsov-Ogievskiy +(cherry picked from commit 3add3ab78247fd347fd6f377a4b951022ac35d35) +Signed-off-by: Max Reitz +Signed-off-by: Danilo C. L. de Paula +--- + nbd/client.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/nbd/client.c b/nbd/client.c +index 25603f2..c828faf 100644 +--- a/nbd/client.c ++++ b/nbd/client.c +@@ -416,6 +416,14 @@ static int nbd_opt_go(QIOChannel *ioc, const char *wantname, + nbd_send_opt_abort(ioc); + return -1; + } ++ if (info->min_block && ++ !QEMU_IS_ALIGNED(info->size, info->min_block)) { ++ error_setg(errp, "export size %" PRIu64 "is not multiple of " ++ "minimum block size %" PRIu32, info->size, ++ info->min_block); ++ nbd_send_opt_abort(ioc); ++ return -1; ++ } + be16_to_cpus(&info->flags); + trace_nbd_receive_negotiate_size_flags(info->size, info->flags); + break; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-nbd-client-Support-qemu-img-convert-from-unaligned-s.patch b/SOURCES/kvm-nbd-client-Support-qemu-img-convert-from-unaligned-s.patch new file mode 100644 index 0000000..fe47c31 --- /dev/null +++ b/SOURCES/kvm-nbd-client-Support-qemu-img-convert-from-unaligned-s.patch @@ -0,0 +1,132 @@ +From 25bfe4a95b02b6fefafdfa1651c50a4d0c5bc87b Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Tue, 23 Jul 2019 14:45:44 +0100 +Subject: [PATCH 06/14] nbd/client: Support qemu-img convert from unaligned + size + +RH-Author: Max Reitz +Message-id: <20190723144546.23701-6-mreitz@redhat.com> +Patchwork-id: 89651 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 5/7] nbd/client: Support qemu-img convert from unaligned size +Bugzilla: 1678979 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Stefano Garzarella +RH-Acked-by: John Snow + +From: Eric Blake + +If an NBD server advertises a size that is not a multiple of a sector, +the block layer rounds up that size, even though we set info.size to +the exact byte value sent by the server. The block layer then proceeds +to let us read or query block status on the hole that it added past +EOF, which the NBD server is unlikely to be happy with. Fortunately, +qemu as a server never advertizes an unaligned size, so we generally +don't run into this problem; but the nbdkit server makes it easy to +test: + +$ printf %1000d 1 > f1 +$ ~/nbdkit/nbdkit -fv file f1 & pid=$! +$ qemu-img convert -f raw nbd://localhost:10809 f2 +$ kill $pid +$ qemu-img compare f1 f2 + +Pre-patch, the server attempts a 1024-byte read, which nbdkit +rightfully rejects as going beyond its advertised 1000 byte size; the +conversion fails and the output files differ (not even the first +sector is copied, because qemu-img does not follow ddrescue's habit of +trying smaller reads to get as much information as possible in spite +of errors). Post-patch, the client's attempts to read (and query block +status, for new enough nbdkit) are properly truncated to the server's +length, with sane handling of the hole the block layer forced on +us. Although f2 ends up as a larger file (1024 bytes instead of 1000), +qemu-img compare shows the two images to have identical contents for +display to the guest. + +I didn't add iotests coverage since I didn't want to add a dependency +on nbdkit in iotests. I also did NOT patch write, trim, or write +zeroes - these commands continue to fail (usually with ENOSPC, but +whatever the server chose), because we really can't write to the end +of the file, and because 'qemu-img convert' is the most common case +where we care about being tolerant (which is read-only). Perhaps we +could truncate the request if the client is writing zeros to the tail, +but that seems like more work, especially if the block layer is fixed +in 4.1 to track byte-accurate sizing (in which case this patch would +be reverted as unnecessary). + +Signed-off-by: Eric Blake +Message-Id: <20190329042750.14704-5-eblake@redhat.com> +Tested-by: Richard W.M. Jones +(cherry picked from commit 9cf638508c0090b33ada4155c7cbb684e08e5ee9) +Signed-off-by: Max Reitz +Signed-off-by: Danilo C. L. de Paula +--- + block/nbd-client.c | 39 ++++++++++++++++++++++++++++++++++++++- + 1 file changed, 38 insertions(+), 1 deletion(-) + +diff --git a/block/nbd-client.c b/block/nbd-client.c +index 80d3625..6b33fe3 100644 +--- a/block/nbd-client.c ++++ b/block/nbd-client.c +@@ -790,6 +790,25 @@ int nbd_client_co_preadv(BlockDriverState *bs, uint64_t offset, + if (!bytes) { + return 0; + } ++ /* ++ * Work around the fact that the block layer doesn't do ++ * byte-accurate sizing yet - if the read exceeds the server's ++ * advertised size because the block layer rounded size up, then ++ * truncate the request to the server and tail-pad with zero. ++ */ ++ if (offset >= client->info.size) { ++ assert(bytes < BDRV_SECTOR_SIZE); ++ qemu_iovec_memset(qiov, 0, 0, bytes); ++ return 0; ++ } ++ if (offset + bytes > client->info.size) { ++ uint64_t slop = offset + bytes - client->info.size; ++ ++ assert(slop < BDRV_SECTOR_SIZE); ++ qemu_iovec_memset(qiov, bytes - slop, 0, slop); ++ request.len -= slop; ++ } ++ + ret = nbd_co_send_request(bs, &request, NULL); + if (ret < 0) { + return ret; +@@ -904,7 +923,8 @@ int coroutine_fn nbd_client_co_block_status(BlockDriverState *bs, + .from = offset, + .len = MIN(MIN_NON_ZERO(QEMU_ALIGN_DOWN(INT_MAX, + bs->bl.request_alignment), +- client->info.max_block), bytes), ++ client->info.max_block), ++ MIN(bytes, client->info.size - offset)), + .flags = NBD_CMD_FLAG_REQ_ONE, + }; + +@@ -913,6 +933,23 @@ int coroutine_fn nbd_client_co_block_status(BlockDriverState *bs, + return BDRV_BLOCK_DATA; + } + ++ /* ++ * Work around the fact that the block layer doesn't do ++ * byte-accurate sizing yet - if the status request exceeds the ++ * server's advertised size because the block layer rounded size ++ * up, we truncated the request to the server (above), or are ++ * called on just the hole. ++ */ ++ if (offset >= client->info.size) { ++ *pnum = bytes; ++ assert(bytes < BDRV_SECTOR_SIZE); ++ /* Intentionally don't report offset_valid for the hole */ ++ return BDRV_BLOCK_ZERO; ++ } ++ ++ if (client->info.min_block) { ++ assert(QEMU_IS_ALIGNED(request.len, client->info.min_block)); ++ } + ret = nbd_co_send_request(bs, &request, NULL); + if (ret < 0) { + return ret; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-nbd-server-Advertise-actual-minimum-block-size.patch b/SOURCES/kvm-nbd-server-Advertise-actual-minimum-block-size.patch new file mode 100644 index 0000000..b9312c3 --- /dev/null +++ b/SOURCES/kvm-nbd-server-Advertise-actual-minimum-block-size.patch @@ -0,0 +1,120 @@ +From 1832a90928232cb91a8542613b754079fd1f0f0e Mon Sep 17 00:00:00 2001 +From: Max Reitz +Date: Tue, 23 Jul 2019 14:45:46 +0100 +Subject: [PATCH 08/14] nbd/server: Advertise actual minimum block size + +RH-Author: Max Reitz +Message-id: <20190723144546.23701-8-mreitz@redhat.com> +Patchwork-id: 89652 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 7/7] nbd/server: Advertise actual minimum block size +Bugzilla: 1678979 +RH-Acked-by: Kevin Wolf +RH-Acked-by: Stefano Garzarella +RH-Acked-by: John Snow + +From: Eric Blake + +Both NBD_CMD_BLOCK_STATUS and structured NBD_CMD_READ will split their +reply according to bdrv_block_status() boundaries. If the block device +has a request_alignment smaller than 512, but we advertise a block +alignment of 512 to the client, then this can result in the server +reply violating client expectations by reporting a smaller region of +the export than what the client is permitted to address (although this +is less of an issue for qemu 4.0 clients, given recent client patches +to overlook our non-compliance at EOF). Since it's always better to +be strict in what we send, it is worth advertising the actual minimum +block limit rather than blindly rounding it up to 512. + +Note that this patch is not foolproof - it is still possible to +provoke non-compliant server behavior using: + +$ qemu-nbd --image-opts driver=blkdebug,align=512,image.driver=file,image.filename=/path/to/non-aligned-file + +That is arguably a bug in the blkdebug driver (it should never pass +back block status smaller than its alignment, even if it has to make +multiple bdrv_get_status calls and determine the +least-common-denominator status among the group to return). It may +also be possible to observe issues with a backing layer with smaller +alignment than the active layer, although so far I have been unable to +write a reliable iotest for that scenario (but again, an issue like +that could be argued to be a bug in the block layer, or something +where we need a flag to bdrv_block_status() to state whether the +result must be aligned to the current layer's limits or can be +subdivided for accuracy when chasing backing files). + +Anyways, as blkdebug is not normally used, and as this patch makes our +server more interoperable with qemu 3.1 clients, it is worth applying +now, even while we still work on a larger patch series for the 4.1 +timeframe to have byte-accurate file lengths. + +Note that the iotests output changes - for 223 and 233, we can see the +server's better granularity advertisement; and for 241, the three test +cases have the following effects: +- natural alignment: the server's smaller alignment is now advertised, +and the hole reported at EOF is now the right result; we've gotten rid +of the server's non-compliance +- forced server alignment: the server still advertises 512 bytes, but +still sends a mid-sector hole. This is still a server compliance bug, +which needs to be fixed in the block layer in a later patch; output +does not change because the client is already being tolerant of the +non-compliance +- forced client alignment: the server's smaller alignment means that +the client now sees the server's status change mid-sector without any +protocol violations, but the fact that the map shows an unaligned +mid-sector hole is evidence of the block layer problems with aligned +block status, to be fixed in a later patch + +Signed-off-by: Eric Blake +Message-Id: <20190329042750.14704-7-eblake@redhat.com> +Reviewed-by: Vladimir Sementsov-Ogievskiy +[eblake: rebase to enhanced iotest 241 coverage] +(cherry picked from commit b0245d6478ea5906e3d7a542244d5c015fd47bc7) + +Signed-off-by: Danilo C. L. de Paula + +Conflicts: +- tests/qemu-iotests/223.out: We are missing + ddd09448fd833d646952c769ae9ce3d39bee989f downstream, which adds + qemu-nbd --list tests to 223. (qemu-nbd --list does not exist + downstream.) + +- tests/qemu-iotests/233.out: Does not exist downstream. + +- tests/qemu-iotests/241.out: Does not exist downstream, because it + would require qemu-nbd --list. + +Signed-off-by: Max Reitz +Signed-off-by: Danilo C. L. de Paula +--- + nbd/server.c | 13 ++++++++----- + 1 file changed, 8 insertions(+), 5 deletions(-) + +diff --git a/nbd/server.c b/nbd/server.c +index e094300..96b6631 100644 +--- a/nbd/server.c ++++ b/nbd/server.c +@@ -608,13 +608,16 @@ static int nbd_negotiate_handle_info(NBDClient *client, uint16_t myflags, + /* Send NBD_INFO_BLOCK_SIZE always, but tweak the minimum size + * according to whether the client requested it, and according to + * whether this is OPT_INFO or OPT_GO. */ +- /* minimum - 1 for back-compat, or 512 if client is new enough. +- * TODO: consult blk_bs(blk)->bl.request_alignment? */ +- sizes[0] = +- (client->opt == NBD_OPT_INFO || blocksize) ? BDRV_SECTOR_SIZE : 1; ++ /* minimum - 1 for back-compat, or actual if client will obey it. */ ++ if (client->opt == NBD_OPT_INFO || blocksize) { ++ sizes[0] = blk_get_request_alignment(exp->blk); ++ } else { ++ sizes[0] = 1; ++ } ++ assert(sizes[0] <= NBD_MAX_BUFFER_SIZE); + /* preferred - Hard-code to 4096 for now. + * TODO: is blk_bs(blk)->bl.opt_transfer appropriate? */ +- sizes[1] = 4096; ++ sizes[1] = MAX(4096, sizes[0]); + /* maximum - At most 32M, but smaller as appropriate. */ + sizes[2] = MIN(blk_get_max_transfer(exp->blk), NBD_MAX_BUFFER_SIZE); + trace_nbd_negotiate_handle_info_block_size(sizes[0], sizes[1], sizes[2]); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-opts-don-t-silently-truncate-long-option-values.patch b/SOURCES/kvm-opts-don-t-silently-truncate-long-option-values.patch new file mode 100644 index 0000000..f338282 --- /dev/null +++ b/SOURCES/kvm-opts-don-t-silently-truncate-long-option-values.patch @@ -0,0 +1,398 @@ +From 6abc65aaa666bf41070fa772293982cb0d1ae835 Mon Sep 17 00:00:00 2001 +From: Laszlo Ersek +Date: Thu, 12 Sep 2019 13:05:00 +0100 +Subject: [PATCH 03/22] opts: don't silently truncate long option values +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Laszlo Ersek +Message-id: <20190912130503.14094-4-lersek@redhat.com> +Patchwork-id: 90436 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH 3/6] opts: don't silently truncate long option values +Bugzilla: 1749022 +RH-Acked-by: Stefano Garzarella +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Eduardo Habkost + +From: Daniel P. Berrangé + +The existing QemuOpts parsing code uses a fixed size 1024 byte buffer +for storing the option values. If a value exceeded this size it was +silently truncated and no error reported to the user. Long option values +is not a common scenario, but it is conceivable that they will happen. +eg if the user has a very deeply nested filesystem it would be possible +to come up with a disk path that was > 1024 bytes. Most of the time if +such data was silently truncated, the user would get an error about +opening a non-existant disk. If they're unlucky though, QEMU might use a +completely different disk image from another VM, which could be +considered a security issue. Another example program was in using the +-smbios command line arg with very large data blobs. In this case the +silent truncation will be providing semantically incorrect data to the +guest OS for SMBIOS tables. + +If the operating system didn't limit the user's argv when spawning QEMU, +the code should honour whatever length arguments were given without +imposing its own length restrictions. This patch thus changes the code +to use a heap allocated buffer for storing the values during parsing, +lifting the arbitrary length restriction. + +RHEL8 notes: + +- Fix up upstream's obviously garbled UTF8 sequences in Dan's name (Author + meta-datum, Signed-off-by tags). + +Signed-off-by: Daniel P. Berrangé +Message-Id: <20180416111743.8473-4-berrange@redhat.com> +Signed-off-by: Paolo Bonzini +Signed-off-by: Daniel P. Berrangé +(cherry picked from commit 950c4e6c94b15cd0d8b63891dddd7a8dbf458e6a) +Signed-off-by: Laszlo Ersek +Signed-off-by: Danilo C. L. de Paula +--- + hw/i386/multiboot.c | 33 +++++++++------ + include/qemu/option.h | 2 +- + util/qemu-option.c | 111 +++++++++++++++++++++++++++----------------------- + 3 files changed, 81 insertions(+), 65 deletions(-) + +diff --git a/hw/i386/multiboot.c b/hw/i386/multiboot.c +index 5bc0a2c..7a2953e 100644 +--- a/hw/i386/multiboot.c ++++ b/hw/i386/multiboot.c +@@ -291,12 +291,16 @@ int load_multiboot(FWCfgState *fw_cfg, + cmdline_len = strlen(kernel_filename) + 1; + cmdline_len += strlen(kernel_cmdline) + 1; + if (initrd_filename) { +- const char *r = initrd_filename; ++ const char *r = get_opt_value(initrd_filename, NULL); + cmdline_len += strlen(r) + 1; + mbs.mb_mods_avail = 1; +- while (*(r = get_opt_value(NULL, 0, r))) { +- mbs.mb_mods_avail++; +- r++; ++ while (1) { ++ mbs.mb_mods_avail++; ++ r = get_opt_value(r, NULL); ++ if (!*r) { ++ break; ++ } ++ r++; + } + } + +@@ -313,7 +317,8 @@ int load_multiboot(FWCfgState *fw_cfg, + + if (initrd_filename) { + const char *next_initrd; +- char not_last, tmpbuf[strlen(initrd_filename) + 1]; ++ char not_last; ++ char *one_file = NULL; + + mbs.offset_mods = mbs.mb_buf_size; + +@@ -322,24 +327,26 @@ int load_multiboot(FWCfgState *fw_cfg, + int mb_mod_length; + uint32_t offs = mbs.mb_buf_size; + +- next_initrd = get_opt_value(tmpbuf, sizeof(tmpbuf), initrd_filename); ++ next_initrd = get_opt_value(initrd_filename, &one_file); + not_last = *next_initrd; + /* if a space comes after the module filename, treat everything + after that as parameters */ +- hwaddr c = mb_add_cmdline(&mbs, tmpbuf); +- if ((next_space = strchr(tmpbuf, ' '))) ++ hwaddr c = mb_add_cmdline(&mbs, one_file); ++ next_space = strchr(one_file, ' '); ++ if (next_space) { + *next_space = '\0'; +- mb_debug("multiboot loading module: %s", tmpbuf); +- mb_mod_length = get_image_size(tmpbuf); ++ } ++ mb_debug("multiboot loading module: %s", one_file); ++ mb_mod_length = get_image_size(one_file); + if (mb_mod_length < 0) { +- error_report("Failed to open file '%s'", tmpbuf); ++ error_report("Failed to open file '%s'", one_file); + exit(1); + } + + mbs.mb_buf_size = TARGET_PAGE_ALIGN(mb_mod_length + mbs.mb_buf_size); + mbs.mb_buf = g_realloc(mbs.mb_buf, mbs.mb_buf_size); + +- load_image(tmpbuf, (unsigned char *)mbs.mb_buf + offs); ++ load_image(one_file, (unsigned char *)mbs.mb_buf + offs); + mb_add_mod(&mbs, mbs.mb_buf_phys + offs, + mbs.mb_buf_phys + offs + mb_mod_length, c); + +@@ -347,6 +354,8 @@ int load_multiboot(FWCfgState *fw_cfg, + (char *)mbs.mb_buf + offs, + (char *)mbs.mb_buf + offs + mb_mod_length, c); + initrd_filename = next_initrd+1; ++ g_free(one_file); ++ one_file = NULL; + } while (not_last); + } + +diff --git a/include/qemu/option.h b/include/qemu/option.h +index 1cfe5cb..3dfb449 100644 +--- a/include/qemu/option.h ++++ b/include/qemu/option.h +@@ -28,7 +28,7 @@ + + #include "qemu/queue.h" + +-const char *get_opt_value(char *buf, int buf_size, const char *p); ++const char *get_opt_value(const char *p, char **value); + + void parse_option_size(const char *name, const char *value, + uint64_t *ret, Error **errp); +diff --git a/util/qemu-option.c b/util/qemu-option.c +index b99568f..ba44a08 100644 +--- a/util/qemu-option.c ++++ b/util/qemu-option.c +@@ -70,25 +70,37 @@ static const char *get_opt_name(const char *p, char **option, char delim) + * delimiter is fixed to be comma which starts a new option. To specify an + * option value that contains commas, double each comma. + */ +-const char *get_opt_value(char *buf, int buf_size, const char *p) ++const char *get_opt_value(const char *p, char **value) + { +- char *q; ++ size_t capacity = 0, length; ++ const char *offset; ++ ++ *value = NULL; ++ while (1) { ++ offset = strchr(p, ','); ++ if (!offset) { ++ offset = p + strlen(p); ++ } + +- q = buf; +- while (*p != '\0') { +- if (*p == ',') { +- if (*(p + 1) != ',') +- break; +- p++; ++ length = offset - p; ++ if (*offset != '\0' && *(offset + 1) == ',') { ++ length++; ++ } ++ if (value) { ++ *value = g_renew(char, *value, capacity + length + 1); ++ strncpy(*value + capacity, p, length); ++ (*value)[capacity + length] = '\0'; ++ } ++ capacity += length; ++ if (*offset == '\0' || ++ *(offset + 1) != ',') { ++ break; + } +- if (q && (q - buf) < buf_size - 1) +- *q++ = *p; +- p++; ++ ++ p += (offset - p) + 2; + } +- if (q) +- *q = '\0'; + +- return p; ++ return offset; + } + + static void parse_option_bool(const char *name, const char *value, bool *ret, +@@ -162,50 +174,43 @@ void parse_option_size(const char *name, const char *value, + + bool has_help_option(const char *param) + { +- size_t buflen = strlen(param) + 1; +- char *buf = g_malloc(buflen); + const char *p = param; + bool result = false; + +- while (*p) { +- p = get_opt_value(buf, buflen, p); ++ while (*p && !result) { ++ char *value; ++ ++ p = get_opt_value(p, &value); + if (*p) { + p++; + } + +- if (is_help_option(buf)) { +- result = true; +- goto out; +- } ++ result = is_help_option(value); ++ g_free(value); + } + +-out: +- g_free(buf); + return result; + } + +-bool is_valid_option_list(const char *param) ++bool is_valid_option_list(const char *p) + { +- size_t buflen = strlen(param) + 1; +- char *buf = g_malloc(buflen); +- const char *p = param; +- bool result = true; ++ char *value = NULL; ++ bool result = false; + + while (*p) { +- p = get_opt_value(buf, buflen, p); +- if (*p && !*++p) { +- result = false; ++ p = get_opt_value(p, &value); ++ if ((*p && !*++p) || ++ (!*value || *value == ',')) { + goto out; + } + +- if (!*buf || *buf == ',') { +- result = false; +- goto out; +- } ++ g_free(value); ++ value = NULL; + } + ++ result = true; + out: +- g_free(buf); ++ g_free(value); + return result; + } + +@@ -486,7 +491,7 @@ int qemu_opt_unset(QemuOpts *opts, const char *name) + } + } + +-static void opt_set(QemuOpts *opts, const char *name, const char *value, ++static void opt_set(QemuOpts *opts, const char *name, char *value, + bool prepend, Error **errp) + { + QemuOpt *opt; +@@ -495,6 +500,7 @@ static void opt_set(QemuOpts *opts, const char *name, const char *value, + + desc = find_desc_by_name(opts->list->desc, name); + if (!desc && !opts_accepts_any(opts)) { ++ g_free(value); + error_setg(errp, QERR_INVALID_PARAMETER, name); + return; + } +@@ -508,8 +514,7 @@ static void opt_set(QemuOpts *opts, const char *name, const char *value, + QTAILQ_INSERT_TAIL(&opts->head, opt, next); + } + opt->desc = desc; +- opt->str = g_strdup(value); +- assert(opt->str); ++ opt->str = value; + qemu_opt_parse(opt, &local_err); + if (local_err) { + error_propagate(errp, local_err); +@@ -520,7 +525,7 @@ static void opt_set(QemuOpts *opts, const char *name, const char *value, + void qemu_opt_set(QemuOpts *opts, const char *name, const char *value, + Error **errp) + { +- opt_set(opts, name, value, false, errp); ++ opt_set(opts, name, g_strdup(value), false, errp); + } + + void qemu_opt_set_bool(QemuOpts *opts, const char *name, bool val, +@@ -754,7 +759,7 @@ static void opts_do_parse(QemuOpts *opts, const char *params, + const char *firstname, bool prepend, Error **errp) + { + char *option = NULL; +- char value[1024]; ++ char *value = NULL; + const char *p,*pe,*pc; + Error *local_err = NULL; + +@@ -766,15 +771,15 @@ static void opts_do_parse(QemuOpts *opts, const char *params, + if (p == params && firstname) { + /* implicitly named first option */ + option = g_strdup(firstname); +- p = get_opt_value(value, sizeof(value), p); ++ p = get_opt_value(p, &value); + } else { + /* option without value, probably a flag */ + p = get_opt_name(p, &option, ','); + if (strncmp(option, "no", 2) == 0) { + memmove(option, option+2, strlen(option+2)+1); +- pstrcpy(value, sizeof(value), "off"); ++ value = g_strdup("off"); + } else { +- pstrcpy(value, sizeof(value), "on"); ++ value = g_strdup("on"); + } + } + } else { +@@ -782,11 +787,12 @@ static void opts_do_parse(QemuOpts *opts, const char *params, + p = get_opt_name(p, &option, '='); + assert(*p == '='); + p++; +- p = get_opt_value(value, sizeof(value), p); ++ p = get_opt_value(p, &value); + } + if (strcmp(option, "id") != 0) { + /* store and parse */ + opt_set(opts, option, value, prepend, &local_err); ++ value = NULL; + if (local_err) { + error_propagate(errp, local_err); + goto cleanup; +@@ -796,11 +802,13 @@ static void opts_do_parse(QemuOpts *opts, const char *params, + break; + } + g_free(option); +- option = NULL; ++ g_free(value); ++ option = value = NULL; + } + + cleanup: + g_free(option); ++ g_free(value); + } + + /** +@@ -819,7 +827,7 @@ static QemuOpts *opts_parse(QemuOptsList *list, const char *params, + bool permit_abbrev, bool defaults, Error **errp) + { + const char *firstname; +- char value[1024], *id = NULL; ++ char *id = NULL; + const char *p; + QemuOpts *opts; + Error *local_err = NULL; +@@ -828,11 +836,9 @@ static QemuOpts *opts_parse(QemuOptsList *list, const char *params, + firstname = permit_abbrev ? list->implied_opt_name : NULL; + + if (strncmp(params, "id=", 3) == 0) { +- get_opt_value(value, sizeof(value), params+3); +- id = value; ++ get_opt_value(params + 3, &id); + } else if ((p = strstr(params, ",id=")) != NULL) { +- get_opt_value(value, sizeof(value), p+4); +- id = value; ++ get_opt_value(p + 4, &id); + } + + /* +@@ -844,6 +850,7 @@ static QemuOpts *opts_parse(QemuOptsList *list, const char *params, + */ + assert(!defaults || list->merge_lists); + opts = qemu_opts_create(list, id, !defaults, &local_err); ++ g_free(id); + if (opts == NULL) { + error_propagate(errp, local_err); + return NULL; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-opts-don-t-silently-truncate-long-parameter-keys.patch b/SOURCES/kvm-opts-don-t-silently-truncate-long-parameter-keys.patch new file mode 100644 index 0000000..00cd2ae --- /dev/null +++ b/SOURCES/kvm-opts-don-t-silently-truncate-long-parameter-keys.patch @@ -0,0 +1,198 @@ +From 5fe3c58c3a57a04254b3083b070fdf99fba82c93 Mon Sep 17 00:00:00 2001 +From: Laszlo Ersek +Date: Thu, 12 Sep 2019 13:04:59 +0100 +Subject: [PATCH 02/22] opts: don't silently truncate long parameter keys +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Laszlo Ersek +Message-id: <20190912130503.14094-3-lersek@redhat.com> +Patchwork-id: 90435 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH 2/6] opts: don't silently truncate long parameter keys +Bugzilla: 1749022 +RH-Acked-by: Stefano Garzarella +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Eduardo Habkost + +From: Daniel P. Berrangé + +The existing QemuOpts parsing code uses a fixed size 128 byte buffer +for storing the parameter keys. If a key exceeded this size it was +silently truncate and no error reported to the user. This behaviour was +reasonable & harmless because traditionally the key names are all +statically declared, and it was known that no code was declaring a key +longer than 127 bytes. This assumption, however, ceased to be valid once +the block layer added support for dot-separate compound keys. This +syntax allows for keys that can be arbitrarily long, limited only by the +number of block drivers you can stack up. With this usage, silently +truncating the key name can never lead to correct behaviour. + +Hopefully such truncation would turn into an error, when the block code +then tried to extract options later, but there's no guarantee that will +happen. It is conceivable that an option specified by the user may be +truncated and then ignored. This could have serious consequences, +possibly even leading to security problems if the ignored option set a +security relevant parameter. + +If the operating system didn't limit the user's argv when spawning QEMU, +the code should honour whatever length arguments were given without +imposing its own length restrictions. This patch thus changes the code +to use a heap allocated buffer for storing the keys during parsing, +lifting the arbitrary length restriction. + +RHEL8 notes: + +- Fix up upstream's obviously garbled UTF8 sequences in Dan's name (Author + meta-datum, Signed-off-by tags). + +Signed-off-by: Daniel P. Berrangé +Message-Id: <20180416111743.8473-3-berrange@redhat.com> +Signed-off-by: Paolo Bonzini +Signed-off-by: Daniel P. Berrangé +(cherry picked from commit e652714f98f22e8882e88e3d563b025c5b00feec) +Signed-off-by: Laszlo Ersek +Signed-off-by: Danilo C. L. de Paula +--- + tests/test-qemu-opts.c | 18 ------------------ + util/qemu-option.c | 44 ++++++++++++++++++++++---------------------- + 2 files changed, 22 insertions(+), 40 deletions(-) + +diff --git a/tests/test-qemu-opts.c b/tests/test-qemu-opts.c +index 77dd72b..7092e21 100644 +--- a/tests/test-qemu-opts.c ++++ b/tests/test-qemu-opts.c +@@ -459,8 +459,6 @@ static void test_opts_parse(void) + { + Error *err = NULL; + QemuOpts *opts; +- char long_key[129]; +- char *params; + + /* Nothing */ + opts = qemu_opts_parse(&opts_list_03, "", false, &error_abort); +@@ -471,22 +469,6 @@ static void test_opts_parse(void) + g_assert_cmpuint(opts_count(opts), ==, 1); + g_assert_cmpstr(qemu_opt_get(opts, ""), ==, "val"); + +- /* Long key */ +- memset(long_key, 'a', 127); +- long_key[127] = 'z'; +- long_key[128] = 0; +- params = g_strdup_printf("%s=v", long_key); +- opts = qemu_opts_parse(&opts_list_03, params + 1, NULL, &error_abort); +- g_assert_cmpuint(opts_count(opts), ==, 1); +- g_assert_cmpstr(qemu_opt_get(opts, long_key + 1), ==, "v"); +- +- /* Overlong key gets truncated */ +- opts = qemu_opts_parse(&opts_list_03, params, NULL, &error_abort); +- g_assert(opts_count(opts) == 1); +- long_key[127] = 0; +- g_assert_cmpstr(qemu_opt_get(opts, long_key), ==, "v"); +- g_free(params); +- + /* Multiple keys, last one wins */ + opts = qemu_opts_parse(&opts_list_03, "a=1,b=2,,x,a=3", + false, &error_abort); +diff --git a/util/qemu-option.c b/util/qemu-option.c +index a8db173..b99568f 100644 +--- a/util/qemu-option.c ++++ b/util/qemu-option.c +@@ -43,27 +43,23 @@ + * first byte of the option name) + * + * The option name is delimited by delim (usually , or =) or the string end +- * and is copied into buf. If the option name is longer than buf_size, it is +- * truncated. buf is always zero terminated. ++ * and is copied into option. The caller is responsible for free'ing option ++ * when no longer required. + * + * The return value is the position of the delimiter/zero byte after the option + * name in p. + */ +-static const char *get_opt_name(char *buf, int buf_size, const char *p, +- char delim) ++static const char *get_opt_name(const char *p, char **option, char delim) + { +- char *q; ++ char *offset = strchr(p, delim); + +- q = buf; +- while (*p != '\0' && *p != delim) { +- if (q && (q - buf) < buf_size - 1) +- *q++ = *p; +- p++; ++ if (offset) { ++ *option = g_strndup(p, offset - p); ++ return offset; ++ } else { ++ *option = g_strdup(p); ++ return p + strlen(p); + } +- if (q) +- *q = '\0'; +- +- return p; + } + + /* +@@ -757,7 +753,8 @@ void qemu_opts_print(QemuOpts *opts, const char *separator) + static void opts_do_parse(QemuOpts *opts, const char *params, + const char *firstname, bool prepend, Error **errp) + { +- char option[128], value[1024]; ++ char *option = NULL; ++ char value[1024]; + const char *p,*pe,*pc; + Error *local_err = NULL; + +@@ -768,11 +765,11 @@ static void opts_do_parse(QemuOpts *opts, const char *params, + /* found "foo,more" */ + if (p == params && firstname) { + /* implicitly named first option */ +- pstrcpy(option, sizeof(option), firstname); ++ option = g_strdup(firstname); + p = get_opt_value(value, sizeof(value), p); + } else { + /* option without value, probably a flag */ +- p = get_opt_name(option, sizeof(option), p, ','); ++ p = get_opt_name(p, &option, ','); + if (strncmp(option, "no", 2) == 0) { + memmove(option, option+2, strlen(option+2)+1); + pstrcpy(value, sizeof(value), "off"); +@@ -782,10 +779,8 @@ static void opts_do_parse(QemuOpts *opts, const char *params, + } + } else { + /* found "foo=bar,more" */ +- p = get_opt_name(option, sizeof(option), p, '='); +- if (*p != '=') { +- break; +- } ++ p = get_opt_name(p, &option, '='); ++ assert(*p == '='); + p++; + p = get_opt_value(value, sizeof(value), p); + } +@@ -794,13 +789,18 @@ static void opts_do_parse(QemuOpts *opts, const char *params, + opt_set(opts, option, value, prepend, &local_err); + if (local_err) { + error_propagate(errp, local_err); +- return; ++ goto cleanup; + } + } + if (*p != ',') { + break; + } ++ g_free(option); ++ option = NULL; + } ++ ++ cleanup: ++ g_free(option); + } + + /** +-- +1.8.3.1 + diff --git a/SOURCES/kvm-opts-remove-redundant-check-for-NULL-parameter.patch b/SOURCES/kvm-opts-remove-redundant-check-for-NULL-parameter.patch new file mode 100644 index 0000000..7130abe --- /dev/null +++ b/SOURCES/kvm-opts-remove-redundant-check-for-NULL-parameter.patch @@ -0,0 +1,74 @@ +From 1906ff6940bb9f84f0f6a66980354e66b5124558 Mon Sep 17 00:00:00 2001 +From: Laszlo Ersek +Date: Thu, 12 Sep 2019 13:05:03 +0100 +Subject: [PATCH 06/22] opts: remove redundant check for NULL parameter +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Laszlo Ersek +Message-id: <20190912130503.14094-7-lersek@redhat.com> +Patchwork-id: 90432 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH 6/6] opts: remove redundant check for NULL parameter +Bugzilla: 1749022 +RH-Acked-by: Stefano Garzarella +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Eduardo Habkost + +From: Daniel P. Berrangé + +No callers of get_opt_value() pass in a NULL for the "value" parameter, +so the check is redundant. + +RHEL8 notes: + +- Context difference in "util/qemu-option.c", function get_opt_value(); + upstream has commit 5c99fa375da1 ("cutils: Provide strchrnul", + 2018-06-29), part of v3.0.0, but downstream lacks it. Harmless, because + said upstream commit only refactors get_opt_value(). + +Signed-off-by: Daniel P. Berrangé +Message-Id: <20180514171913.17664-4-berrange@redhat.com> +Reviewed-by: Eduardo Habkost +Tested-by: Roman Kagan +Signed-off-by: Paolo Bonzini +(cherry picked from commit 0c2f6e7ee99517449b4ed6cf333c2d9456d8fe35) +Signed-off-by: Laszlo Ersek +Signed-off-by: Danilo C. L. de Paula +--- + util/qemu-option.c | 12 ++++-------- + 1 file changed, 4 insertions(+), 8 deletions(-) + +diff --git a/util/qemu-option.c b/util/qemu-option.c +index a396d60..940f7a3 100644 +--- a/util/qemu-option.c ++++ b/util/qemu-option.c +@@ -75,9 +75,7 @@ const char *get_opt_value(const char *p, char **value) + size_t capacity = 0, length; + const char *offset; + +- if (value) { +- *value = NULL; +- } ++ *value = NULL; + while (1) { + offset = strchr(p, ','); + if (!offset) { +@@ -88,11 +86,9 @@ const char *get_opt_value(const char *p, char **value) + if (*offset != '\0' && *(offset + 1) == ',') { + length++; + } +- if (value) { +- *value = g_renew(char, *value, capacity + length + 1); +- strncpy(*value + capacity, p, length); +- (*value)[capacity + length] = '\0'; +- } ++ *value = g_renew(char, *value, capacity + length + 1); ++ strncpy(*value + capacity, p, length); ++ (*value)[capacity + length] = '\0'; + capacity += length; + if (*offset == '\0' || + *(offset + 1) != ',') { +-- +1.8.3.1 + diff --git a/SOURCES/kvm-pc-bios-s390-ccw-define-loadparm-length.patch b/SOURCES/kvm-pc-bios-s390-ccw-define-loadparm-length.patch new file mode 100644 index 0000000..3f12d5a --- /dev/null +++ b/SOURCES/kvm-pc-bios-s390-ccw-define-loadparm-length.patch @@ -0,0 +1,122 @@ +From ad3b92699ba5e2280950fa9866f79673cecdb695 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Mon, 14 Oct 2019 10:06:29 +0100 +Subject: [PATCH 04/21] pc-bios/s390-ccw: define loadparm length + +RH-Author: Thomas Huth +Message-id: <20191014100645.22862-2-thuth@redhat.com> +Patchwork-id: 91780 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH v2 01/17] pc-bios/s390-ccw: define loadparm length +Bugzilla: 1664376 +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand +RH-Acked-by: Jens Freimann + +From: Collin Walling + +Loadparm is defined by the s390 architecture to be 8 bytes +in length. Let's define this size in the s390-ccw bios. + +Suggested-by: Laszlo Ersek +Signed-off-by: Collin Walling +Reviewed-by: Laszlo Ersek +Reviewed-by: Thomas Huth +Signed-off-by: Thomas Huth +(cherry picked from commit a0e11b617b9ef41cefe8739dff4d6a7b01ca967f) +Signed-off-by: Danilo C. L. de Paula +--- + pc-bios/s390-ccw/iplb.h | 4 +++- + pc-bios/s390-ccw/main.c | 8 ++++---- + pc-bios/s390-ccw/sclp.c | 2 +- + pc-bios/s390-ccw/sclp.h | 2 +- + 4 files changed, 9 insertions(+), 7 deletions(-) + +diff --git a/pc-bios/s390-ccw/iplb.h b/pc-bios/s390-ccw/iplb.h +index ded20c8..772d5c5 100644 +--- a/pc-bios/s390-ccw/iplb.h ++++ b/pc-bios/s390-ccw/iplb.h +@@ -12,6 +12,8 @@ + #ifndef IPLB_H + #define IPLB_H + ++#define LOADPARM_LEN 8 ++ + struct IplBlockCcw { + uint8_t reserved0[85]; + uint8_t ssid; +@@ -61,7 +63,7 @@ struct IplParameterBlock { + uint8_t pbt; + uint8_t flags; + uint16_t reserved01; +- uint8_t loadparm[8]; ++ uint8_t loadparm[LOADPARM_LEN]; + union { + IplBlockCcw ccw; + IplBlockFcp fcp; +diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c +index 26f9adf..544851d 100644 +--- a/pc-bios/s390-ccw/main.c ++++ b/pc-bios/s390-ccw/main.c +@@ -15,7 +15,7 @@ + char stack[PAGE_SIZE * 8] __attribute__((__aligned__(PAGE_SIZE))); + static SubChannelId blk_schid = { .one = 1 }; + IplParameterBlock iplb __attribute__((__aligned__(PAGE_SIZE))); +-static char loadparm_str[9] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; ++static char loadparm_str[LOADPARM_LEN + 1] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + QemuIplParameters qipl; + + #define LOADPARM_PROMPT "PROMPT " +@@ -80,13 +80,13 @@ static bool find_dev(Schib *schib, int dev_no) + + static void menu_setup(void) + { +- if (memcmp(loadparm_str, LOADPARM_PROMPT, 8) == 0) { ++ if (memcmp(loadparm_str, LOADPARM_PROMPT, LOADPARM_LEN) == 0) { + menu_set_parms(QIPL_FLAG_BM_OPTS_CMD, 0); + return; + } + + /* If loadparm was set to any other value, then do not enable menu */ +- if (memcmp(loadparm_str, LOADPARM_EMPTY, 8) != 0) { ++ if (memcmp(loadparm_str, LOADPARM_EMPTY, LOADPARM_LEN) != 0) { + return; + } + +@@ -117,7 +117,7 @@ static void virtio_setup(void) + enable_mss_facility(); + + sclp_get_loadparm_ascii(loadparm_str); +- memcpy(ldp + 10, loadparm_str, 8); ++ memcpy(ldp + 10, loadparm_str, LOADPARM_LEN); + sclp_print(ldp); + + memcpy(&qipl, early_qipl, sizeof(QemuIplParameters)); +diff --git a/pc-bios/s390-ccw/sclp.c b/pc-bios/s390-ccw/sclp.c +index 3836cb4..c0223fa 100644 +--- a/pc-bios/s390-ccw/sclp.c ++++ b/pc-bios/s390-ccw/sclp.c +@@ -114,7 +114,7 @@ void sclp_get_loadparm_ascii(char *loadparm) + memset((char *)_sccb, 0, sizeof(ReadInfo)); + sccb->h.length = sizeof(ReadInfo); + if (!sclp_service_call(SCLP_CMDW_READ_SCP_INFO, sccb)) { +- ebcdic_to_ascii((char *) sccb->loadparm, loadparm, 8); ++ ebcdic_to_ascii((char *) sccb->loadparm, loadparm, LOADPARM_LEN); + } + } + +diff --git a/pc-bios/s390-ccw/sclp.h b/pc-bios/s390-ccw/sclp.h +index 0dd987f..8450161 100644 +--- a/pc-bios/s390-ccw/sclp.h ++++ b/pc-bios/s390-ccw/sclp.h +@@ -56,7 +56,7 @@ typedef struct ReadInfo { + uint16_t rnmax; + uint8_t rnsize; + uint8_t reserved[13]; +- uint8_t loadparm[8]; ++ uint8_t loadparm[LOADPARM_LEN]; + } __attribute__((packed)) ReadInfo; + + typedef struct SCCB { +-- +1.8.3.1 + diff --git a/SOURCES/kvm-pc-bios-s390-ccw-net-Use-diag308-to-reset-machine-be.patch b/SOURCES/kvm-pc-bios-s390-ccw-net-Use-diag308-to-reset-machine-be.patch new file mode 100644 index 0000000..54d102d --- /dev/null +++ b/SOURCES/kvm-pc-bios-s390-ccw-net-Use-diag308-to-reset-machine-be.patch @@ -0,0 +1,328 @@ +From 2f0454ccd0dd12429e8c204933cafe71a248d4eb Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Mon, 14 Oct 2019 10:06:30 +0100 +Subject: [PATCH 05/21] pc-bios/s390-ccw/net: Use diag308 to reset machine + before jumping to the OS + +RH-Author: Thomas Huth +Message-id: <20191014100645.22862-3-thuth@redhat.com> +Patchwork-id: 91777 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH v2 02/17] pc-bios/s390-ccw/net: Use diag308 to reset machine before jumping to the OS +Bugzilla: 1664376 +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand +RH-Acked-by: Jens Freimann + +The netboot firmware so far simply jumped directly into the OS kernel +after the download has been completed. This, however, bears the risk +that the virtio-net device still might be active in the background and +incoming packets are still placed into the buffers - which could destroy +memory of the now-running Linux kernel in case it did not take over the +device fast enough. Also the SCLP console is not put into a well-defined +state here. We should hand over the system in a clean state when jumping +into the kernel, so let's use the same mechanism as it's done in the +main s390-ccw firmware and reset the machine with diag308 into a clean +state before jumping into the OS kernel code. To be able to share the +code with the main s390-ccw firmware, the related functions are now +extracted from bootmap.c into a new file called jump2ipl.c. + +Since we now also set the boot device schid at address 184 for the network +boot device, this patch also slightly changes the way how we detect the +entry points for non-ELF binary images: The code now looks for the "S390EP" +magic first and then jumps to 0x10000 in case it has been found. This is +necessary for booting from network devices, since the normal kernel code +(where the PSW at ddress 0 points to) tries to do a block load from the +boot device. This of course fails for a virtio-net device and causes the +kernel to abort with a panic-PSW silently. + +Acked-by: Christian Borntraeger +Signed-off-by: Thomas Huth +(cherry picked from commit 9a848adf45d6732e62551decb3c0255173090767) +Signed-off-by: Danilo C. L. de Paula +--- + pc-bios/s390-ccw/Makefile | 4 +- + pc-bios/s390-ccw/bootmap.c | 63 +----------------------------- + pc-bios/s390-ccw/bootmap.h | 4 -- + pc-bios/s390-ccw/jump2ipl.c | 91 ++++++++++++++++++++++++++++++++++++++++++++ + pc-bios/s390-ccw/netboot.mak | 3 +- + pc-bios/s390-ccw/netmain.c | 11 +++++- + pc-bios/s390-ccw/s390-ccw.h | 4 ++ + 7 files changed, 111 insertions(+), 69 deletions(-) + create mode 100644 pc-bios/s390-ccw/jump2ipl.c + +diff --git a/pc-bios/s390-ccw/Makefile b/pc-bios/s390-ccw/Makefile +index 1712c2d..439e3cc 100644 +--- a/pc-bios/s390-ccw/Makefile ++++ b/pc-bios/s390-ccw/Makefile +@@ -9,7 +9,9 @@ $(call set-vpath, $(SRC_PATH)/pc-bios/s390-ccw) + + .PHONY : all clean build-all + +-OBJECTS = start.o main.o bootmap.o sclp.o virtio.o virtio-scsi.o virtio-blkdev.o libc.o menu.o ++OBJECTS = start.o main.o bootmap.o jump2ipl.o sclp.o menu.o \ ++ virtio.o virtio-scsi.o virtio-blkdev.o libc.o ++ + QEMU_CFLAGS := $(filter -W%, $(QEMU_CFLAGS)) + QEMU_CFLAGS += -ffreestanding -fno-delete-null-pointer-checks -msoft-float + QEMU_CFLAGS += -march=z900 -fPIE -fno-strict-aliasing +diff --git a/pc-bios/s390-ccw/bootmap.c b/pc-bios/s390-ccw/bootmap.c +index ffbf671..d13b7cb 100644 +--- a/pc-bios/s390-ccw/bootmap.c ++++ b/pc-bios/s390-ccw/bootmap.c +@@ -29,14 +29,6 @@ + /* Scratch space */ + static uint8_t sec[MAX_SECTOR_SIZE*4] __attribute__((__aligned__(PAGE_SIZE))); + +-typedef struct ResetInfo { +- uint32_t ipl_mask; +- uint32_t ipl_addr; +- uint32_t ipl_continue; +-} ResetInfo; +- +-static ResetInfo save; +- + const uint8_t el_torito_magic[] = "EL TORITO SPECIFICATION" + "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; + +@@ -57,53 +49,6 @@ static inline bool is_iso_vd_valid(IsoVolDesc *vd) + vd->type <= VOL_DESC_TYPE_PARTITION; + } + +-static void jump_to_IPL_2(void) +-{ +- ResetInfo *current = 0; +- +- void (*ipl)(void) = (void *) (uint64_t) current->ipl_continue; +- *current = save; +- ipl(); /* should not return */ +-} +- +-static void jump_to_IPL_code(uint64_t address) +-{ +- /* store the subsystem information _after_ the bootmap was loaded */ +- write_subsystem_identification(); +- +- /* prevent unknown IPL types in the guest */ +- if (iplb.pbt == S390_IPL_TYPE_QEMU_SCSI) { +- iplb.pbt = S390_IPL_TYPE_CCW; +- set_iplb(&iplb); +- } +- +- /* +- * The IPL PSW is at address 0. We also must not overwrite the +- * content of non-BIOS memory after we loaded the guest, so we +- * save the original content and restore it in jump_to_IPL_2. +- */ +- ResetInfo *current = 0; +- +- save = *current; +- current->ipl_addr = (uint32_t) (uint64_t) &jump_to_IPL_2; +- current->ipl_continue = address & 0x7fffffff; +- +- debug_print_int("set IPL addr to", current->ipl_continue); +- +- /* Ensure the guest output starts fresh */ +- sclp_print("\n"); +- +- /* +- * HACK ALERT. +- * We use the load normal reset to keep r15 unchanged. jump_to_IPL_2 +- * can then use r15 as its stack pointer. +- */ +- asm volatile("lghi 1,1\n\t" +- "diag 1,1,0x308\n\t" +- : : : "1", "memory"); +- panic("\n! IPL returns !\n"); +-} +- + /*********************************************************************** + * IPL an ECKD DASD (CDL or LDL/CMS format) + */ +@@ -744,13 +689,7 @@ static void load_iso_bc_entry(IsoBcSection *load) + (void *)((uint64_t)bswap16(s.load_segment)), + blks_to_load); + +- /* Trying to get PSW at zero address */ +- if (*((uint64_t *)0) & IPL_PSW_MASK) { +- jump_to_IPL_code((*((uint64_t *)0)) & 0x7fffffff); +- } +- +- /* Try default linux start address */ +- jump_to_IPL_code(KERN_IMAGE_START); ++ jump_to_low_kernel(); + } + + static uint32_t find_iso_bc(void) +diff --git a/pc-bios/s390-ccw/bootmap.h b/pc-bios/s390-ccw/bootmap.h +index f1ce423..94f53a5 100644 +--- a/pc-bios/s390-ccw/bootmap.h ++++ b/pc-bios/s390-ccw/bootmap.h +@@ -355,10 +355,6 @@ static inline uint32_t iso_733_to_u32(uint64_t x) + #define ISO_SECTOR_SIZE 2048 + /* El Torito specifies boot image size in 512 byte blocks */ + #define ET_SECTOR_SHIFT 2 +-#define KERN_IMAGE_START 0x010000UL +-#define PSW_MASK_64 0x0000000100000000ULL +-#define PSW_MASK_32 0x0000000080000000ULL +-#define IPL_PSW_MASK (PSW_MASK_32 | PSW_MASK_64) + + #define ISO_PRIMARY_VD_SECTOR 16 + +diff --git a/pc-bios/s390-ccw/jump2ipl.c b/pc-bios/s390-ccw/jump2ipl.c +new file mode 100644 +index 0000000..266f150 +--- /dev/null ++++ b/pc-bios/s390-ccw/jump2ipl.c +@@ -0,0 +1,91 @@ ++/* ++ * QEMU s390-ccw firmware - jump to IPL code ++ * ++ * This work is licensed under the terms of the GNU GPL, version 2 or (at ++ * your option) any later version. See the COPYING file in the top-level ++ * directory. ++ */ ++ ++#include "libc.h" ++#include "s390-ccw.h" ++ ++#define KERN_IMAGE_START 0x010000UL ++#define PSW_MASK_64 0x0000000100000000ULL ++#define PSW_MASK_32 0x0000000080000000ULL ++#define IPL_PSW_MASK (PSW_MASK_32 | PSW_MASK_64) ++ ++typedef struct ResetInfo { ++ uint32_t ipl_mask; ++ uint32_t ipl_addr; ++ uint32_t ipl_continue; ++} ResetInfo; ++ ++static ResetInfo save; ++ ++static void jump_to_IPL_2(void) ++{ ++ ResetInfo *current = 0; ++ ++ void (*ipl)(void) = (void *) (uint64_t) current->ipl_continue; ++ *current = save; ++ ipl(); /* should not return */ ++} ++ ++void jump_to_IPL_code(uint64_t address) ++{ ++ /* store the subsystem information _after_ the bootmap was loaded */ ++ write_subsystem_identification(); ++ ++ /* prevent unknown IPL types in the guest */ ++ if (iplb.pbt == S390_IPL_TYPE_QEMU_SCSI) { ++ iplb.pbt = S390_IPL_TYPE_CCW; ++ set_iplb(&iplb); ++ } ++ ++ /* ++ * The IPL PSW is at address 0. We also must not overwrite the ++ * content of non-BIOS memory after we loaded the guest, so we ++ * save the original content and restore it in jump_to_IPL_2. ++ */ ++ ResetInfo *current = 0; ++ ++ save = *current; ++ current->ipl_addr = (uint32_t) (uint64_t) &jump_to_IPL_2; ++ current->ipl_continue = address & 0x7fffffff; ++ ++ debug_print_int("set IPL addr to", current->ipl_continue); ++ ++ /* Ensure the guest output starts fresh */ ++ sclp_print("\n"); ++ ++ /* ++ * HACK ALERT. ++ * We use the load normal reset to keep r15 unchanged. jump_to_IPL_2 ++ * can then use r15 as its stack pointer. ++ */ ++ asm volatile("lghi 1,1\n\t" ++ "diag 1,1,0x308\n\t" ++ : : : "1", "memory"); ++ panic("\n! IPL returns !\n"); ++} ++ ++void jump_to_low_kernel(void) ++{ ++ /* ++ * If it looks like a Linux binary, i.e. there is the "S390EP" magic from ++ * arch/s390/kernel/head.S here, then let's jump to the well-known Linux ++ * kernel start address (when jumping to the PSW-at-zero address instead, ++ * the kernel startup code fails when we booted from a network device). ++ */ ++ if (!memcmp((char *)0x10008, "S390EP", 6)) { ++ jump_to_IPL_code(KERN_IMAGE_START); ++ } ++ ++ /* Trying to get PSW at zero address */ ++ if (*((uint64_t *)0) & IPL_PSW_MASK) { ++ jump_to_IPL_code((*((uint64_t *)0)) & 0x7fffffff); ++ } ++ ++ /* No other option left, so use the Linux kernel start address */ ++ jump_to_IPL_code(KERN_IMAGE_START); ++} +diff --git a/pc-bios/s390-ccw/netboot.mak b/pc-bios/s390-ccw/netboot.mak +index a25d238..4f64128 100644 +--- a/pc-bios/s390-ccw/netboot.mak ++++ b/pc-bios/s390-ccw/netboot.mak +@@ -1,7 +1,8 @@ + + SLOF_DIR := $(SRC_PATH)/roms/SLOF + +-NETOBJS := start.o sclp.o virtio.o virtio-net.o netmain.o libnet.a libc.a ++NETOBJS := start.o sclp.o virtio.o virtio-net.o jump2ipl.o netmain.o \ ++ libnet.a libc.a + + LIBC_INC := -nostdinc -I$(SLOF_DIR)/lib/libc/include + LIBNET_INC := -I$(SLOF_DIR)/lib/libnet +diff --git a/pc-bios/s390-ccw/netmain.c b/pc-bios/s390-ccw/netmain.c +index d86d46b..d60e84f 100644 +--- a/pc-bios/s390-ccw/netmain.c ++++ b/pc-bios/s390-ccw/netmain.c +@@ -281,6 +281,15 @@ void panic(const char *string) + } + } + ++void write_subsystem_identification(void) ++{ ++ SubChannelId *schid = (SubChannelId *) 184; ++ uint32_t *zeroes = (uint32_t *) 188; ++ ++ *schid = net_schid; ++ *zeroes = 0; ++} ++ + static bool find_net_dev(Schib *schib, int dev_no) + { + int i, r; +@@ -354,7 +363,7 @@ void main(void) + rc = net_load(NULL, (long)_start); + if (rc > 0) { + sclp_print("Network loading done, starting kernel...\n"); +- asm volatile (" lpsw 0(%0) " : : "r"(0) : "memory"); ++ jump_to_low_kernel(); + } + + panic("Failed to load OS from network\n"); +diff --git a/pc-bios/s390-ccw/s390-ccw.h b/pc-bios/s390-ccw/s390-ccw.h +index a1bdb4c..9828aa2 100644 +--- a/pc-bios/s390-ccw/s390-ccw.h ++++ b/pc-bios/s390-ccw/s390-ccw.h +@@ -87,6 +87,10 @@ ulong get_second(void); + /* bootmap.c */ + void zipl_load(void); + ++/* jump2ipl.c */ ++void jump_to_IPL_code(uint64_t address); ++void jump_to_low_kernel(void); ++ + /* menu.c */ + void menu_set_parms(uint8_t boot_menu_flag, uint32_t boot_menu_timeout); + int menu_get_zipl_boot_index(const char *menu_data); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-pc-q35-Disallow-vfio-pci-hotplug-without-VT-d-cachin.patch b/SOURCES/kvm-pc-q35-Disallow-vfio-pci-hotplug-without-VT-d-cachin.patch new file mode 100644 index 0000000..adcf327 --- /dev/null +++ b/SOURCES/kvm-pc-q35-Disallow-vfio-pci-hotplug-without-VT-d-cachin.patch @@ -0,0 +1,87 @@ +From f117f5fb216e45796a32579c03673c1d79164037 Mon Sep 17 00:00:00 2001 +From: Peter Xu +Date: Wed, 9 Oct 2019 12:39:46 +0100 +Subject: [PATCH 20/22] pc/q35: Disallow vfio-pci hotplug without VT-d caching + mode + +RH-Author: Peter Xu +Message-id: <20191009123947.21505-5-peterx@redhat.com> +Patchwork-id: 91352 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH 4/5] pc/q35: Disallow vfio-pci hotplug without VT-d caching mode +Bugzilla: 1738440 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Auger Eric +RH-Acked-by: Alex Williamson +Signed-off-by: Danilo C. L. de Paula + +Conflicts: + + hw/i386/pc.c: context differs on quite a few places in + pc_machine_class_init(), but none of them is really relevant to + current change. + +Instead of bailing out when trying to hotplug a vfio-pci device with +below configuration: + + -device intel-iommu,caching-mode=off + +With this we can return a warning message to the user via QMP/HMP and +the VM will continue to work after failing the hotplug: + + (qemu) device_add vfio-pci,bus=root.3,host=05:00.0,id=vfio1 + Error: Device assignment is not allowed without enabling caching-mode=on for Intel IOMMU. + +Reviewed-by: Eric Auger +Signed-off-by: Peter Xu +Message-Id: <20190916080718.3299-4-peterx@redhat.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +(cherry picked from commit c6cbc29d36fe8df078776ed715c37cebac582238) +Signed-off-by: Peter Xu +Signed-off-by: Danilo C. L. de Paula +--- + hw/i386/pc.c | 21 +++++++++++++++++++++ + 1 file changed, 21 insertions(+) + +diff --git a/hw/i386/pc.c b/hw/i386/pc.c +index 9e1e6ae..d6c4050 100644 +--- a/hw/i386/pc.c ++++ b/hw/i386/pc.c +@@ -2340,6 +2340,26 @@ static void x86_nmi(NMIState *n, int cpu_index, Error **errp) + } + } + ++ ++static bool pc_hotplug_allowed(MachineState *ms, DeviceState *dev, Error **errp) ++{ ++ X86IOMMUState *iommu = x86_iommu_get_default(); ++ IntelIOMMUState *intel_iommu; ++ ++ if (iommu && ++ object_dynamic_cast((Object *)iommu, TYPE_INTEL_IOMMU_DEVICE) && ++ object_dynamic_cast((Object *)dev, "vfio-pci")) { ++ intel_iommu = INTEL_IOMMU_DEVICE(iommu); ++ if (!intel_iommu->caching_mode) { ++ error_setg(errp, "Device assignment is not allowed without " ++ "enabling caching-mode=on for Intel IOMMU."); ++ return false; ++ } ++ } ++ ++ return true; ++} ++ + static void pc_machine_class_init(ObjectClass *oc, void *data) + { + MachineClass *mc = MACHINE_CLASS(oc); +@@ -2369,6 +2389,7 @@ static void pc_machine_class_init(ObjectClass *oc, void *data) + */ + mc->async_pf_vmexit_disable = true; + mc->get_hotplug_handler = pc_get_hotpug_handler; ++ mc->hotplug_allowed = pc_hotplug_allowed; + mc->cpu_index_to_instance_props = pc_cpu_index_to_props; + mc->get_default_cpu_node_id = pc_get_default_cpu_node_id; + mc->possible_cpu_arch_ids = pc_possible_cpu_arch_ids; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-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-pseries-do-not-allow-memory-less-cpu-less-NUMA-node.patch b/SOURCES/kvm-pseries-do-not-allow-memory-less-cpu-less-NUMA-node.patch new file mode 100644 index 0000000..93fa9f7 --- /dev/null +++ b/SOURCES/kvm-pseries-do-not-allow-memory-less-cpu-less-NUMA-node.patch @@ -0,0 +1,108 @@ +From 7ab2261eebf90ea8a3cf5701fa177d181fe665d1 Mon Sep 17 00:00:00 2001 +From: Laurent Vivier +Date: Thu, 10 Oct 2019 07:34:38 +0100 +Subject: [PATCH 22/22] pseries: do not allow memory-less/cpu-less NUMA node +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Laurent Vivier +Message-id: <20191010073438.16478-1-lvivier@redhat.com> +Patchwork-id: 91379 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH] pseries: do not allow memory-less/cpu-less NUMA node +Bugzilla: 1651474 +RH-Acked-by: David Gibson +RH-Acked-by: Thomas Huth +RH-Acked-by: Philippe Mathieu-Daudé + +When we hotplug a CPU on memory-less/cpu-less node, the linux kernel +crashes. + +This happens because linux kernel needs to know the NUMA topology at +start to be able to initialize the distance lookup table. + +On pseries, the topology is provided by the firmware via the existing +CPUs and memory information. Thus a node without memory and CPU cannot be +discovered by the kernel. + +To avoid the kernel crash, do not allow to start pseries with empty +nodes. + +Signed-off-by: Laurent Vivier +Message-Id: <20190830161345.22436-1-lvivier@redhat.com> +[dwg: Rework to cope with movement of numa state from globals to MachineState] +Signed-off-by: David Gibson +(cherry picked from commit 58c46efa451caa3935224223f950216872e2eee3) +Signed-off-by: Laurent Vivier + +Conflicts in the context: + hw/ppc/spapr.c +because of missing downstream commits: + 0550b1206a91 ("spapr: don't advertise radix GTSE if max-compat-cpu < power9") + ad99d04c76de ("target/ppc: Allow cpu compatiblity checks based on type, not instance") + +because of missing donwtream commit: + + 7e721e7b10e1 ("numa: move numa global variable numa_info into MachineState") + +replaced numa_state by numa_info (revert dwg rework), back to original +patch I sent: + + https://patchew.org/QEMU/20190830161345.22436-1-lvivier@redhat.com/ + +BZ: https://bugzilla.redhat.com/show_bug.cgi?id=1651474 +BRANCH: rhel-8.2.0 +UPSTREAM: merged +BREW: https://brewweb.engineering.redhat.com/brew/taskinfo?taskID=23924908 +Signed-off-by: Danilo C. L. de Paula +--- + hw/ppc/spapr.c | 33 +++++++++++++++++++++++++++++++++ + 1 file changed, 33 insertions(+) + +diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c +index 1a2f0d9..b4c9993 100644 +--- a/hw/ppc/spapr.c ++++ b/hw/ppc/spapr.c +@@ -2527,6 +2527,39 @@ static void spapr_machine_init(MachineState *machine) + /* init CPUs */ + spapr_init_cpus(spapr); + ++ /* ++ * check we don't have a memory-less/cpu-less NUMA node ++ * Firmware relies on the existing memory/cpu topology to provide the ++ * NUMA topology to the kernel. ++ * And the linux kernel needs to know the NUMA topology at start ++ * to be able to hotplug CPUs later. ++ */ ++ if (nb_numa_nodes) { ++ for (i = 0; i < nb_numa_nodes; ++i) { ++ /* check for memory-less node */ ++ if (numa_info[i].node_mem == 0) { ++ CPUState *cs; ++ int found = 0; ++ /* check for cpu-less node */ ++ CPU_FOREACH(cs) { ++ PowerPCCPU *cpu = POWERPC_CPU(cs); ++ if (cpu->node_id == i) { ++ found = 1; ++ break; ++ } ++ } ++ /* memory-less and cpu-less node */ ++ if (!found) { ++ error_report( ++ "Memory-less/cpu-less nodes are not supported (node %d)", ++ i); ++ exit(1); ++ } ++ } ++ } ++ ++ } ++ + if (kvm_enabled()) { + /* Enable H_LOGICAL_CI_* so SLOF can talk to in-kernel devices */ + kvmppc_enable_logical_ci_hcalls(); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-qapi-fill-in-CpuInfoFast.arch-in-query-cpus-fast.patch b/SOURCES/kvm-qapi-fill-in-CpuInfoFast.arch-in-query-cpus-fast.patch new file mode 100644 index 0000000..b506221 --- /dev/null +++ b/SOURCES/kvm-qapi-fill-in-CpuInfoFast.arch-in-query-cpus-fast.patch @@ -0,0 +1,116 @@ +From 9000286ea20abb4e03c76ab8f873a6e9eb708377 Mon Sep 17 00:00:00 2001 +From: Maxim Levitsky +Date: Thu, 14 Nov 2019 08:20:41 +0000 +Subject: [PATCH 1/8] qapi: fill in CpuInfoFast.arch in query-cpus-fast + +RH-Author: Maxim Levitsky +Message-id: <20191114082041.20840-2-mlevitsk@redhat.com> +Patchwork-id: 92245 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH v2 1/1] qapi: fill in CpuInfoFast.arch in query-cpus-fast +Bugzilla: 1730969 +RH-Acked-by: Cornelia Huck +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Markus Armbruster + +From: Laszlo Ersek + +* Commit ca230ff33f89 added the @arch field to @CpuInfoFast, but it failed + to set the new field in qmp_query_cpus_fast(), when TARGET_S390X was not + defined. The updated @query-cpus-fast example in "qapi-schema.json" + showed "arch":"x86" only because qmp_query_cpus_fast() calls g_malloc0() + to allocate @CpuInfoFast, and the CPU_INFO_ARCH_X86 enum constant is + generated with value 0. + + All @arch values other than @s390 implied the @CpuInfoOther sub-struct + for @CpuInfoFast -- at the time of writing the patch --, thus no fields + other than @arch needed to be set when TARGET_S390X was not defined. Set + @arch now, by copying the corresponding assignments from + qmp_query_cpus(). + +* Commit 25fa194b7b11 added the @riscv enum constant to @CpuInfoArch (used + in both @CpuInfo and @CpuInfoFast -- the return types of the @query-cpus + and @query-cpus-fast commands, respectively), and assigned, in both + return structures, the @CpuInfoRISCV sub-structure to the new enum + value. + + However, qmp_query_cpus_fast() would not populate either the @arch field + or the @CpuInfoRISCV sub-structure, when TARGET_RISCV was defined; only + qmp_query_cpus() would. + + Assign @CpuInfoOther to the @riscv enum constant in @CpuInfoFast, and + populate only the @arch field in qmp_query_cpus_fast(). Getting CPU + state without interrupting KVM is an exceptional thing that only S390X + does currently. Quoting Cornelia Huck , "s390x is + exceptional in that it has state in QEMU that is actually interesting + for upper layers and can be retrieved without performance penalty". See + also + . + +Cc: Cornelia Huck +Cc: Eric Blake +Cc: Markus Armbruster +Cc: Viktor VM Mihajlovski +Cc: qemu-stable@nongnu.org +Fixes: ca230ff33f89bf7102cbfbc2328716da6750aaed +Fixes: 25fa194b7b11901561532e435beb83d046899f7a +Signed-off-by: Laszlo Ersek +Reviewed-by: Eric Blake +Reviewed-by: Cornelia Huck +Reviewed-by: Markus Armbruster +Message-Id: <20180427192852.15013-2-lersek@redhat.com> +Signed-off-by: Markus Armbruster +(cherry picked from commit 96054f56396eaa0b9b5c681fc3e42a0004b17ade) +Signed-off-by: Maxim Levitsky +Signed-off-by: Danilo C. L. de Paula +--- + cpus.c | 16 +++++++++++++++- + qapi/misc.json | 2 +- + 2 files changed, 16 insertions(+), 2 deletions(-) + +diff --git a/cpus.c b/cpus.c +index 6100089..cea42f9 100644 +--- a/cpus.c ++++ b/cpus.c +@@ -2218,11 +2218,25 @@ CpuInfoFastList *qmp_query_cpus_fast(Error **errp) + info->value->props = props; + } + +-#if defined(TARGET_S390X) ++#if defined(TARGET_I386) ++ info->value->arch = CPU_INFO_ARCH_X86; ++#elif defined(TARGET_PPC) ++ info->value->arch = CPU_INFO_ARCH_PPC; ++#elif defined(TARGET_SPARC) ++ info->value->arch = CPU_INFO_ARCH_SPARC; ++#elif defined(TARGET_MIPS) ++ info->value->arch = CPU_INFO_ARCH_MIPS; ++#elif defined(TARGET_TRICORE) ++ info->value->arch = CPU_INFO_ARCH_TRICORE; ++#elif defined(TARGET_S390X) + s390_cpu = S390_CPU(cpu); + env = &s390_cpu->env; + info->value->arch = CPU_INFO_ARCH_S390; + info->value->u.s390.cpu_state = env->cpu_state; ++#elif defined(TARGET_RISCV) ++ info->value->arch = CPU_INFO_ARCH_RISCV; ++#else ++ info->value->arch = CPU_INFO_ARCH_OTHER; + #endif + if (!cur_item) { + head = cur_item = info; +diff --git a/qapi/misc.json b/qapi/misc.json +index 5636f4a..104d013 100644 +--- a/qapi/misc.json ++++ b/qapi/misc.json +@@ -573,7 +573,7 @@ + 'mips': 'CpuInfoOther', + 'tricore': 'CpuInfoOther', + 's390': 'CpuInfoS390', +- 'riscv': 'CpuInfoRISCV', ++ 'riscv': 'CpuInfoOther', + 'other': 'CpuInfoOther' } } + + ## +-- +1.8.3.1 + diff --git a/SOURCES/kvm-qdev-machine-Introduce-hotplug_allowed-hook.patch b/SOURCES/kvm-qdev-machine-Introduce-hotplug_allowed-hook.patch new file mode 100644 index 0000000..22575fe --- /dev/null +++ b/SOURCES/kvm-qdev-machine-Introduce-hotplug_allowed-hook.patch @@ -0,0 +1,135 @@ +From 6a2ee1fd8d36ed8407b403a7307de1633462759c Mon Sep 17 00:00:00 2001 +From: Peter Xu +Date: Wed, 9 Oct 2019 12:39:45 +0100 +Subject: [PATCH 19/22] qdev/machine: Introduce hotplug_allowed hook + +RH-Author: Peter Xu +Message-id: <20191009123947.21505-4-peterx@redhat.com> +Patchwork-id: 91351 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH 3/5] qdev/machine: Introduce hotplug_allowed hook +Bugzilla: 1738440 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Auger Eric +RH-Acked-by: Alex Williamson +Signed-off-by: Danilo C. L. de Paula + +Conflicts: + + hw/core/qdev.c: don't have 14405c274e86e ("qdev: Provide + qdev_get_bus_hotplug_handler()") + + include/hw/boards: plenty of new things missing in + MachineClass (kvm_type, numa_mem_supported, smp_parse) + + include/hw/qdev-core.h: don't have 17cc0128da3 ("qdev: Let machine + hotplug handler to override bus hotplug handler") + +Introduce this new per-machine hook to give any machine class a chance +to do a sanity check on the to-be-hotplugged device as a sanity test. +This will be used for x86 to try to detect some illegal configuration +of devices, e.g., possible conflictions between vfio-pci and x86 +vIOMMU. + +Reviewed-by: Eric Auger +Signed-off-by: Peter Xu +Message-Id: <20190916080718.3299-3-peterx@redhat.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +(cherry picked from commit d2321d31ff98b75b652c2b1594f00a4cfd48102a) +Signed-off-by: Peter Xu +Signed-off-by: Danilo C. L. de Paula +--- + hw/core/qdev.c | 17 +++++++++++++++++ + include/hw/boards.h | 9 +++++++++ + include/hw/qdev-core.h | 1 + + qdev-monitor.c | 7 +++++++ + 4 files changed, 34 insertions(+) + +diff --git a/hw/core/qdev.c b/hw/core/qdev.c +index 24f1ae7..5971242 100644 +--- a/hw/core/qdev.c ++++ b/hw/core/qdev.c +@@ -259,6 +259,23 @@ HotplugHandler *qdev_get_machine_hotplug_handler(DeviceState *dev) + return NULL; + } + ++bool qdev_hotplug_allowed(DeviceState *dev, Error **errp) ++{ ++ MachineState *machine; ++ MachineClass *mc; ++ Object *m_obj = qdev_get_machine(); ++ ++ if (object_dynamic_cast(m_obj, TYPE_MACHINE)) { ++ machine = MACHINE(m_obj); ++ mc = MACHINE_GET_CLASS(machine); ++ if (mc->hotplug_allowed) { ++ return mc->hotplug_allowed(machine, dev, errp); ++ } ++ } ++ ++ return true; ++} ++ + HotplugHandler *qdev_get_hotplug_handler(DeviceState *dev) + { + HotplugHandler *hotplug_ctrl; +diff --git a/include/hw/boards.h b/include/hw/boards.h +index 9b4a69b..e568a3c 100644 +--- a/include/hw/boards.h ++++ b/include/hw/boards.h +@@ -156,6 +156,13 @@ typedef struct { + * should instead use "unimplemented-device" for all memory ranges where + * the guest will attempt to probe for a device that QEMU doesn't + * implement and a stub device is required. ++ * @hotplug_allowed: ++ * If the hook is provided, then it'll be called for each device ++ * hotplug to check whether the device hotplug is allowed. Return ++ * true to grant allowance or false to reject the hotplug. When ++ * false is returned, an error must be set to show the reason of ++ * the rejection. If the hook is not provided, all hotplug will be ++ * allowed. + */ + struct MachineClass { + /*< private >*/ +@@ -210,6 +217,8 @@ struct MachineClass { + + HotplugHandler *(*get_hotplug_handler)(MachineState *machine, + DeviceState *dev); ++ bool (*hotplug_allowed)(MachineState *state, DeviceState *dev, ++ Error **errp); + CpuInstanceProperties (*cpu_index_to_instance_props)(MachineState *machine, + unsigned cpu_index); + const CPUArchIdList *(*possible_cpu_arch_ids)(MachineState *machine); +diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h +index 9453588..b8d1cac 100644 +--- a/include/hw/qdev-core.h ++++ b/include/hw/qdev-core.h +@@ -286,6 +286,7 @@ void qdev_init_nofail(DeviceState *dev); + void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id, + int required_for_version); + HotplugHandler *qdev_get_machine_hotplug_handler(DeviceState *dev); ++bool qdev_hotplug_allowed(DeviceState *dev, Error **errp); + HotplugHandler *qdev_get_hotplug_handler(DeviceState *dev); + void qdev_unplug(DeviceState *dev, Error **errp); + void qdev_simple_device_unplug_cb(HotplugHandler *hotplug_dev, +diff --git a/qdev-monitor.c b/qdev-monitor.c +index f439b83..70bce8f 100644 +--- a/qdev-monitor.c ++++ b/qdev-monitor.c +@@ -606,6 +606,13 @@ DeviceState *qdev_device_add(QemuOpts *opts, Error **errp) + /* create device */ + dev = DEVICE(object_new(driver)); + ++ /* Check whether the hotplug is allowed by the machine */ ++ if (qdev_hotplug && !qdev_hotplug_allowed(dev, &err)) { ++ /* Error must be set in the machine hook */ ++ assert(err); ++ goto err_del_dev; ++ } ++ + if (bus) { + qdev_set_parent_bus(dev, bus); + } else if (qdev_hotplug && !qdev_get_machine_hotplug_handler(dev)) { +-- +1.8.3.1 + diff --git a/SOURCES/kvm-qemu-img-fix-regression-copying-secrets-during-conve.patch b/SOURCES/kvm-qemu-img-fix-regression-copying-secrets-during-conve.patch new file mode 100644 index 0000000..ead5090 --- /dev/null +++ b/SOURCES/kvm-qemu-img-fix-regression-copying-secrets-during-conve.patch @@ -0,0 +1,124 @@ +From 14768fe9b44d6c89c066ebf597b9be79f7d43f30 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Wed, 14 Aug 2019 11:28:11 +0100 +Subject: [PATCH 3/3] qemu-img: fix regression copying secrets during convert +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Kevin Wolf +Message-id: <20190814112811.28642-2-kwolf@redhat.com> +Patchwork-id: 89987 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 1/1] qemu-img: fix regression copying secrets during convert +Bugzilla: 1727821 +RH-Acked-by: Max Reitz +RH-Acked-by: John Snow +RH-Acked-by: Thomas Huth + +From: Daniel P. Berrangé + +When the convert command is creating an output file that needs +secrets, we need to ensure those secrets are passed to both the +blk_new_open and bdrv_create API calls. + +This is done by qemu-img extracting all opts matching the name +suffix "key-secret". Unfortunately the code doing this was run after the +call to bdrv_create(), which meant the QemuOpts it was extracting +secrets from was now empty. + +Previously this worked by luks as a bug meant the "key-secret" +parameters were not purged from the QemuOpts. This bug was fixed in + + commit b76b4f604521e59f857d6177bc55f6f2e41fd392 + Author: Kevin Wolf + Date: Thu Jan 11 16:18:08 2018 +0100 + + qcow2: Use visitor for options in qcow2_create() + +Exposing the latent bug in qemu-img. This fix simply moves the copying +of secrets to before the bdrv_create() call. + +Cc: qemu-stable@nongnu.org +Signed-off-by: Daniel P. Berrangé +Signed-off-by: Kevin Wolf +(cherry picked from commit 8d65a3ccfd5db7f0436e095cd952f5d0c3a873ba) +Signed-off-by: Kevin Wolf +Signed-off-by: Danilo C. L. de Paula +--- + qemu-img.c | 32 +++++++++++++++----------------- + 1 file changed, 15 insertions(+), 17 deletions(-) + +diff --git a/qemu-img.c b/qemu-img.c +index f42750a..fa0cbd7 100644 +--- a/qemu-img.c ++++ b/qemu-img.c +@@ -348,21 +348,6 @@ static int img_add_key_secrets(void *opaque, + return 0; + } + +-static BlockBackend *img_open_new_file(const char *filename, +- QemuOpts *create_opts, +- const char *fmt, int flags, +- bool writethrough, bool quiet, +- bool force_share) +-{ +- QDict *options = NULL; +- +- options = qdict_new(); +- qemu_opt_foreach(create_opts, img_add_key_secrets, options, &error_abort); +- +- return img_open_file(filename, options, fmt, flags, writethrough, quiet, +- force_share); +-} +- + + static BlockBackend *img_open(bool image_opts, + const char *filename, +@@ -1994,6 +1979,7 @@ static int img_convert(int argc, char **argv) + BlockDriverState *out_bs; + QemuOpts *opts = NULL, *sn_opts = NULL; + QemuOptsList *create_opts = NULL; ++ QDict *open_opts = NULL; + char *options = NULL; + Error *local_err = NULL; + bool writethrough, src_writethrough, quiet = false, image_opts = false, +@@ -2342,6 +2328,16 @@ static int img_convert(int argc, char **argv) + } + } + ++ /* ++ * The later open call will need any decryption secrets, and ++ * bdrv_create() will purge "opts", so extract them now before ++ * they are lost. ++ */ ++ if (!skip_create) { ++ open_opts = qdict_new(); ++ qemu_opt_foreach(opts, img_add_key_secrets, open_opts, &error_abort); ++ } ++ + if (!skip_create) { + /* Create the new image */ + ret = bdrv_create(drv, out_filename, opts, &local_err); +@@ -2368,8 +2364,9 @@ static int img_convert(int argc, char **argv) + * That has to wait for bdrv_create to be improved + * to allow filenames in option syntax + */ +- s.target = img_open_new_file(out_filename, opts, out_fmt, +- flags, writethrough, quiet, false); ++ s.target = img_open_file(out_filename, open_opts, out_fmt, ++ flags, writethrough, quiet, false); ++ open_opts = NULL; /* blk_new_open will have freed it */ + } + if (!s.target) { + ret = -1; +@@ -2437,6 +2434,7 @@ out: + qemu_opts_del(opts); + qemu_opts_free(create_opts); + qemu_opts_del(sn_opts); ++ qobject_unref(open_opts); + blk_unref(s.target); + if (s.src) { + for (bs_i = 0; bs_i < s.src_num; bs_i++) { +-- +1.8.3.1 + diff --git a/SOURCES/kvm-qemu-iotests-Filter-NFS-paths.patch b/SOURCES/kvm-qemu-iotests-Filter-NFS-paths.patch new file mode 100644 index 0000000..a891d98 --- /dev/null +++ b/SOURCES/kvm-qemu-iotests-Filter-NFS-paths.patch @@ -0,0 +1,110 @@ +From 065df0fad17065597ffb3baf5b697c82c95c2ed0 Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Mon, 8 Jul 2019 15:25:55 +0100 +Subject: [PATCH 09/39] qemu-iotests: Filter NFS paths +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Pino Toscano +Message-id: <20190708152601.21123-5-ptoscano@redhat.com> +Patchwork-id: 89419 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v3 04/10] qemu-iotests: Filter NFS paths +Bugzilla: 1513367 +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Max Reitz +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Markus Armbruster + +From: Kevin Wolf + +NFS paths were only partially filtered in _filter_img_create, _img_info +and _filter_img_info, resulting in "nfs://127.0.0.1TEST_DIR/t.IMGFMT". +This adds another replacement to the sed calls that matches the test +directory not as a host path, but as an NFS URL (the prefix as used for +$TEST_IMG). + +Signed-off-by: Kevin Wolf +Reviewed-by: Fam Zheng +(cherry picked from commit 8908b253c4ad5f8874c8d13abec169c696a5cd32) +Signed-off-by: Pino Toscano +Signed-off-by: Danilo C. L. de Paula +--- + tests/qemu-iotests/126.out | 2 +- + tests/qemu-iotests/common.filter | 6 ++++-- + tests/qemu-iotests/common.rc | 8 +++++++- + 3 files changed, 12 insertions(+), 4 deletions(-) + +diff --git a/tests/qemu-iotests/126.out b/tests/qemu-iotests/126.out +index 50d7308..17d03d5 100644 +--- a/tests/qemu-iotests/126.out ++++ b/tests/qemu-iotests/126.out +@@ -3,7 +3,7 @@ QA output created by 126 + === Testing plain files === + + Formatting 'TEST_DIR/a:b.IMGFMT', fmt=IMGFMT size=67108864 +-Formatting 'TEST_DIR/a:b.IMGFMT', fmt=IMGFMT size=67108864 ++Formatting 'file:TEST_DIR/a:b.IMGFMT', fmt=IMGFMT size=67108864 + + === Testing relative backing filename resolution === + +diff --git a/tests/qemu-iotests/common.filter b/tests/qemu-iotests/common.filter +index 7acb454..2031e35 100644 +--- a/tests/qemu-iotests/common.filter ++++ b/tests/qemu-iotests/common.filter +@@ -118,7 +118,8 @@ _filter_actual_image_size() + # replace driver-specific options in the "Formatting..." line + _filter_img_create() + { +- sed -e "s#$IMGPROTO:$TEST_DIR#TEST_DIR#g" \ ++ sed -e "s#$REMOTE_TEST_DIR#TEST_DIR#g" \ ++ -e "s#$IMGPROTO:$TEST_DIR#TEST_DIR#g" \ + -e "s#$TEST_DIR#TEST_DIR#g" \ + -e "s#$IMGFMT#IMGFMT#g" \ + -e 's#nbd:127.0.0.1:10810#TEST_DIR/t.IMGFMT#g' \ +@@ -153,7 +154,8 @@ _filter_img_info() + + discard=0 + regex_json_spec_start='^ *"format-specific": \{' +- sed -e "s#$IMGPROTO:$TEST_DIR#TEST_DIR#g" \ ++ sed -e "s#$REMOTE_TEST_DIR#TEST_DIR#g" \ ++ -e "s#$IMGPROTO:$TEST_DIR#TEST_DIR#g" \ + -e "s#$TEST_DIR#TEST_DIR#g" \ + -e "s#$IMGFMT#IMGFMT#g" \ + -e 's#nbd://127.0.0.1:10810$#TEST_DIR/t.IMGFMT#g' \ +diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc +index cb5fa14..d054cb9 100644 +--- a/tests/qemu-iotests/common.rc ++++ b/tests/qemu-iotests/common.rc +@@ -148,6 +148,7 @@ else + TEST_IMG="ssh://127.0.0.1$TEST_IMG_FILE" + elif [ "$IMGPROTO" = "nfs" ]; then + TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT ++ REMOTE_TEST_DIR="nfs://127.0.0.1$TEST_DIR" + TEST_IMG="nfs://127.0.0.1$TEST_IMG_FILE" + elif [ "$IMGPROTO" = "vxhs" ]; then + TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT +@@ -173,6 +174,10 @@ if [ ! -d "$TEST_DIR" ]; then + exit 1 + fi + ++if [ -z "$REMOTE_TEST_DIR" ]; then ++ REMOTE_TEST_DIR="$TEST_DIR" ++fi ++ + if [ ! -d "$SAMPLE_IMG_DIR" ]; then + echo "common.config: Error: \$SAMPLE_IMG_DIR ($SAMPLE_IMG_DIR) is not a directory" + exit 1 +@@ -333,7 +338,8 @@ _img_info() + discard=0 + regex_json_spec_start='^ *"format-specific": \{' + $QEMU_IMG info $QEMU_IMG_EXTRA_ARGS "$@" "$TEST_IMG" 2>&1 | \ +- sed -e "s#$IMGPROTO:$TEST_DIR#TEST_DIR#g" \ ++ sed -e "s#$REMOTE_TEST_DIR#TEST_DIR#g" \ ++ -e "s#$IMGPROTO:$TEST_DIR#TEST_DIR#g" \ + -e "s#$TEST_DIR#TEST_DIR#g" \ + -e "s#$IMGFMT#IMGFMT#g" \ + -e "/^disk size:/ D" \ +-- +1.8.3.1 + diff --git a/SOURCES/kvm-qemu-iotests-Fix-paths-for-NFS.patch b/SOURCES/kvm-qemu-iotests-Fix-paths-for-NFS.patch new file mode 100644 index 0000000..c475e51 --- /dev/null +++ b/SOURCES/kvm-qemu-iotests-Fix-paths-for-NFS.patch @@ -0,0 +1,51 @@ +From 5e41ecd75bc95d1390328218676c72ac1cf4562b Mon Sep 17 00:00:00 2001 +From: Pino Toscano +Date: Mon, 8 Jul 2019 15:25:54 +0100 +Subject: [PATCH 08/39] qemu-iotests: Fix paths for NFS +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Pino Toscano +Message-id: <20190708152601.21123-4-ptoscano@redhat.com> +Patchwork-id: 89423 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v3 03/10] qemu-iotests: Fix paths for NFS +Bugzilla: 1513367 +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Max Reitz +RH-Acked-by: Miroslav Rezanina +RH-Acked-by: Markus Armbruster + +From: Kevin Wolf + +Test cases were trying to use nfs:// URLs as local filenames, which made +every test fail for NFS. With TEST_IMG and TEST_IMG_FILE set like for +the other protocols, NFS tests can pass again. + +Signed-off-by: Kevin Wolf +Reviewed-by: Fam Zheng +(cherry picked from commit 655ae6bb91998a01964759406cb38ef215a6ba5b) +Signed-off-by: Pino Toscano +Signed-off-by: Danilo C. L. de Paula +--- + tests/qemu-iotests/common.rc | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/tests/qemu-iotests/common.rc b/tests/qemu-iotests/common.rc +index 9a65a11..cb5fa14 100644 +--- a/tests/qemu-iotests/common.rc ++++ b/tests/qemu-iotests/common.rc +@@ -147,8 +147,8 @@ else + TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT + TEST_IMG="ssh://127.0.0.1$TEST_IMG_FILE" + elif [ "$IMGPROTO" = "nfs" ]; then +- TEST_DIR="nfs://127.0.0.1/$TEST_DIR" +- TEST_IMG=$TEST_DIR/t.$IMGFMT ++ TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT ++ TEST_IMG="nfs://127.0.0.1$TEST_IMG_FILE" + elif [ "$IMGPROTO" = "vxhs" ]; then + TEST_IMG_FILE=$TEST_DIR/t.$IMGFMT + TEST_IMG="vxhs://127.0.0.1:9999/t.$IMGFMT" +-- +1.8.3.1 + diff --git a/SOURCES/kvm-qxl-check-release-info-object.patch b/SOURCES/kvm-qxl-check-release-info-object.patch new file mode 100644 index 0000000..5f14dc6 --- /dev/null +++ b/SOURCES/kvm-qxl-check-release-info-object.patch @@ -0,0 +1,50 @@ +From 56a21c3a967a6cbf99e2ecb2dff30d4dca759532 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Thu, 20 Jun 2019 13:07:31 +0100 +Subject: [PATCH 1/2] qxl: check release info object +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Philippe Mathieu-Daudé +Message-id: <20190620130731.18034-2-philmd@redhat.com> +Patchwork-id: 88745 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 1/1] qxl: check release info object +Bugzilla: 1712705 +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Stefan Hajnoczi + +From: Prasad J Pandit + +When releasing spice resources in release_resource() routine, +if release info object 'ext.info' is null, it leads to null +pointer dereference. Add check to avoid it. + +Reported-by: Bugs SysSec +Signed-off-by: Prasad J Pandit +Message-id: 20190425063534.32747-1-ppandit@redhat.com +Signed-off-by: Gerd Hoffmann +(cherry picked from commit d52680fc932efb8a2f334cc6993e705ed1e31e99) +Signed-off-by: Danilo C. L. de Paula +--- + hw/display/qxl.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/hw/display/qxl.c b/hw/display/qxl.c +index b373c50..a8c953b 100644 +--- a/hw/display/qxl.c ++++ b/hw/display/qxl.c +@@ -776,6 +776,9 @@ static void interface_release_resource(QXLInstance *sin, + QXLReleaseRing *ring; + uint64_t *item, id; + ++ if (!ext.info) { ++ return; ++ } + if (ext.group_id == MEMSLOT_GROUP_HOST) { + /* host group -> vga mode update request */ + QXLCommandExt *cmdext = (void *)(intptr_t)(ext.info->id); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-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-PCI-fix-IOMMU-region-init.patch b/SOURCES/kvm-s390-PCI-fix-IOMMU-region-init.patch new file mode 100644 index 0000000..d6822b8 --- /dev/null +++ b/SOURCES/kvm-s390-PCI-fix-IOMMU-region-init.patch @@ -0,0 +1,61 @@ +From 324a0ffc5140c4ece5b720708da2c673a8d1b9cc Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Tue, 1 Oct 2019 06:02:58 +0100 +Subject: [PATCH 12/22] s390: PCI: fix IOMMU region init + +RH-Author: Thomas Huth +Message-id: <20191001060258.28206-2-thuth@redhat.com> +Patchwork-id: 90929 +O-Subject: [RHEL-8.2.0/RHEL-8.1.z qemu-kvm PATCH 1/1] s390: PCI: fix IOMMU region init +Bugzilla: 1754643 +RH-Acked-by: Jens Freimann +RH-Acked-by: David Hildenbrand +RH-Acked-by: Maxim Levitsky + +From: Matthew Rosato + +The fix in dbe9cf606c shrinks the IOMMU memory region to a size +that seems reasonable on the surface, however is actually too +small as it is based against a 0-mapped address space. This +causes breakage with small guests as they can overrun the IOMMU window. + +Let's go back to the prior method of initializing iommu for now. + +Fixes: dbe9cf606c ("s390x/pci: Set the iommu region size mpcifc request") +Reviewed-by: Pierre Morel +Reported-by: Boris Fiuczynski +Tested-by: Boris Fiuczynski +Reported-by: Stefan Zimmerman +Signed-off-by: Matthew Rosato +Message-Id: <1569507036-15314-1-git-send-email-mjrosato@linux.ibm.com> +Signed-off-by: Christian Borntraeger +(cherry picked from commit 7df1dac5f1c85312474df9cb3a8fcae72303da62) +Signed-off-by: Danilo C. L. de Paula +--- + hw/s390x/s390-pci-bus.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/hw/s390x/s390-pci-bus.c b/hw/s390x/s390-pci-bus.c +index 383b3e7..069e152 100644 +--- a/hw/s390x/s390-pci-bus.c ++++ b/hw/s390x/s390-pci-bus.c +@@ -691,10 +691,15 @@ static const MemoryRegionOps s390_msi_ctrl_ops = { + + void s390_pci_iommu_enable(S390PCIIOMMU *iommu) + { ++ /* ++ * The iommu region is initialized against a 0-mapped address space, ++ * so the smallest IOMMU region we can define runs from 0 to the end ++ * of the PCI address space. ++ */ + char *name = g_strdup_printf("iommu-s390-%04x", iommu->pbdev->uid); + memory_region_init_iommu(&iommu->iommu_mr, sizeof(iommu->iommu_mr), + TYPE_S390_IOMMU_MEMORY_REGION, OBJECT(&iommu->mr), +- name, iommu->pal - iommu->pba + 1); ++ name, iommu->pal + 1); + iommu->enabled = true; + memory_region_add_subregion(&iommu->mr, 0, MEMORY_REGION(&iommu->iommu_mr)); + g_free(name); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390-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-Add-channel-command-codes-structs-needed-f.patch b/SOURCES/kvm-s390-bios-Add-channel-command-codes-structs-needed-f.patch new file mode 100644 index 0000000..9c02f2d --- /dev/null +++ b/SOURCES/kvm-s390-bios-Add-channel-command-codes-structs-needed-f.patch @@ -0,0 +1,88 @@ +From 81d722eaf6284d55e2da0ba6cc4874bfd262a7e2 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Mon, 14 Oct 2019 10:06:43 +0100 +Subject: [PATCH 18/21] s390-bios: Add channel command codes/structs needed for + dasd-ipl + +RH-Author: Thomas Huth +Message-id: <20191014100645.22862-16-thuth@redhat.com> +Patchwork-id: 91792 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH v2 15/17] s390-bios: Add channel command codes/structs needed for dasd-ipl +Bugzilla: 1664376 +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand +RH-Acked-by: Jens Freimann + +From: "Jason J. Herne" + +The dasd IPL procedure needs to execute a few previously unused +channel commands. Let's define them and their associated data +structures. + +Signed-off-by: Jason J. Herne +Acked-by: Cornelia Huck +Acked-by: Thomas Huth +Message-Id: <1554388475-18329-15-git-send-email-jjherne@linux.ibm.com> +Signed-off-by: Thomas Huth +(cherry picked from commit 69333c36dc85b84b021766747cffc2b53df93ae8) +Signed-off-by: Danilo C. L. de Paula +--- + pc-bios/s390-ccw/cio.h | 23 +++++++++++++++++++++++ + 1 file changed, 23 insertions(+) + +diff --git a/pc-bios/s390-ccw/cio.h b/pc-bios/s390-ccw/cio.h +index 1637e32..aaa432d 100644 +--- a/pc-bios/s390-ccw/cio.h ++++ b/pc-bios/s390-ccw/cio.h +@@ -200,11 +200,14 @@ typedef struct ccw1 { + #define CCW_FLAG_IDA 0x04 + #define CCW_FLAG_SUSPEND 0x02 + ++/* Common CCW commands */ ++#define CCW_CMD_READ_IPL 0x02 + #define CCW_CMD_NOOP 0x03 + #define CCW_CMD_BASIC_SENSE 0x04 + #define CCW_CMD_TIC 0x08 + #define CCW_CMD_SENSE_ID 0xe4 + ++/* Virtio CCW commands */ + #define CCW_CMD_SET_VQ 0x13 + #define CCW_CMD_VDEV_RESET 0x33 + #define CCW_CMD_READ_FEAT 0x12 +@@ -216,6 +219,12 @@ typedef struct ccw1 { + #define CCW_CMD_SET_CONF_IND 0x53 + #define CCW_CMD_READ_VQ_CONF 0x32 + ++/* DASD CCW commands */ ++#define CCW_CMD_DASD_READ 0x06 ++#define CCW_CMD_DASD_SEEK 0x07 ++#define CCW_CMD_DASD_SEARCH_ID_EQ 0x31 ++#define CCW_CMD_DASD_READ_MT 0x86 ++ + /* + * Command-mode operation request block + */ +@@ -333,6 +342,20 @@ typedef struct irb { + __u32 emw[8]; + } __attribute__ ((packed, aligned(4))) Irb; + ++/* Used for SEEK ccw commands */ ++typedef struct CcwSeekData { ++ uint16_t reserved; ++ uint16_t cyl; ++ uint16_t head; ++} __attribute__((packed)) CcwSeekData; ++ ++/* Used for SEARCH ID ccw commands */ ++typedef struct CcwSearchIdData { ++ uint16_t cyl; ++ uint16_t head; ++ uint8_t record; ++} __attribute__((packed)) CcwSearchIdData; ++ + int enable_mss_facility(void); + void enable_subchannel(SubChannelId schid); + uint16_t cu_type(SubChannelId schid); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390-bios-Clean-up-cio.h.patch b/SOURCES/kvm-s390-bios-Clean-up-cio.h.patch new file mode 100644 index 0000000..7dd990a --- /dev/null +++ b/SOURCES/kvm-s390-bios-Clean-up-cio.h.patch @@ -0,0 +1,251 @@ +From fc07c126ddd0796c1996b2e527e69486c9c848b9 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Mon, 14 Oct 2019 10:06:33 +0100 +Subject: [PATCH 08/21] s390-bios: Clean up cio.h + +RH-Author: Thomas Huth +Message-id: <20191014100645.22862-6-thuth@redhat.com> +Patchwork-id: 91782 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH v2 05/17] s390-bios: Clean up cio.h +Bugzilla: 1664376 +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand +RH-Acked-by: Jens Freimann + +From: "Jason J. Herne" + +Add proper typedefs to all structs and modify all bit fields to use consistent +formatting. + +Signed-off-by: Jason J. Herne +Reviewed-by: Collin Walling +Reviewed-by: Farhan Ali +Acked-by: Cornelia Huck +Reviewed-by: Thomas Huth +Message-Id: <1554388475-18329-5-git-send-email-jjherne@linux.ibm.com> +Signed-off-by: Thomas Huth +(cherry picked from commit d96c5db77f1058ee9509554f43b945c66b3aa7c9) +Signed-off-by: Danilo C. L. de Paula +--- + pc-bios/s390-ccw/cio.h | 114 ++++++++++++++++++++++---------------------- + pc-bios/s390-ccw/s390-ccw.h | 8 ---- + 2 files changed, 57 insertions(+), 65 deletions(-) + +diff --git a/pc-bios/s390-ccw/cio.h b/pc-bios/s390-ccw/cio.h +index 1a0795f..ed5b2cb 100644 +--- a/pc-bios/s390-ccw/cio.h ++++ b/pc-bios/s390-ccw/cio.h +@@ -17,35 +17,35 @@ + * path management control word + */ + struct pmcw { +- __u32 intparm; /* interruption parameter */ +- __u32 qf : 1; /* qdio facility */ +- __u32 w : 1; +- __u32 isc : 3; /* interruption sublass */ +- __u32 res5 : 3; /* reserved zeros */ +- __u32 ena : 1; /* enabled */ +- __u32 lm : 2; /* limit mode */ +- __u32 mme : 2; /* measurement-mode enable */ +- __u32 mp : 1; /* multipath mode */ +- __u32 tf : 1; /* timing facility */ +- __u32 dnv : 1; /* device number valid */ +- __u32 dev : 16; /* device number */ +- __u8 lpm; /* logical path mask */ +- __u8 pnom; /* path not operational mask */ +- __u8 lpum; /* last path used mask */ +- __u8 pim; /* path installed mask */ +- __u16 mbi; /* measurement-block index */ +- __u8 pom; /* path operational mask */ +- __u8 pam; /* path available mask */ +- __u8 chpid[8]; /* CHPID 0-7 (if available) */ +- __u32 unused1 : 8; /* reserved zeros */ +- __u32 st : 3; /* subchannel type */ +- __u32 unused2 : 18; /* reserved zeros */ +- __u32 mbfc : 1; /* measurement block format control */ +- __u32 xmwme : 1; /* extended measurement word mode enable */ +- __u32 csense : 1; /* concurrent sense; can be enabled ...*/ +- /* ... per MSCH, however, if facility */ +- /* ... is not installed, this results */ +- /* ... in an operand exception. */ ++ __u32 intparm; /* interruption parameter */ ++ __u32 qf:1; /* qdio facility */ ++ __u32 w:1; ++ __u32 isc:3; /* interruption sublass */ ++ __u32 res5:3; /* reserved zeros */ ++ __u32 ena:1; /* enabled */ ++ __u32 lm:2; /* limit mode */ ++ __u32 mme:2; /* measurement-mode enable */ ++ __u32 mp:1; /* multipath mode */ ++ __u32 tf:1; /* timing facility */ ++ __u32 dnv:1; /* device number valid */ ++ __u32 dev:16; /* device number */ ++ __u8 lpm; /* logical path mask */ ++ __u8 pnom; /* path not operational mask */ ++ __u8 lpum; /* last path used mask */ ++ __u8 pim; /* path installed mask */ ++ __u16 mbi; /* measurement-block index */ ++ __u8 pom; /* path operational mask */ ++ __u8 pam; /* path available mask */ ++ __u8 chpid[8]; /* CHPID 0-7 (if available) */ ++ __u32 unused1:8; /* reserved zeros */ ++ __u32 st:3; /* subchannel type */ ++ __u32 unused2:18; /* reserved zeros */ ++ __u32 mbfc:1; /* measurement block format control */ ++ __u32 xmwme:1; /* extended measurement word mode enable */ ++ __u32 csense:1; /* concurrent sense; can be enabled ...*/ ++ /* ... per MSCH, however, if facility */ ++ /* ... is not installed, this results */ ++ /* ... in an operand exception. */ + } __attribute__ ((packed)); + + /* Target SCHIB configuration. */ +@@ -77,28 +77,28 @@ struct scsw { + /* + * subchannel information block + */ +-struct schib { ++typedef struct schib { + struct pmcw pmcw; /* path management control word */ + struct scsw scsw; /* subchannel status word */ + __u64 mba; /* measurement block address */ + __u8 mda[4]; /* model dependent area */ +-} __attribute__ ((packed,aligned(4))); +- +-struct subchannel_id { +- __u32 cssid : 8; +- __u32 : 4; +- __u32 m : 1; +- __u32 ssid : 2; +- __u32 one : 1; +- __u32 sch_no : 16; +-} __attribute__ ((packed, aligned(4))); ++} __attribute__ ((packed, aligned(4))) Schib; ++ ++typedef struct subchannel_id { ++ __u32 cssid:8; ++ __u32:4; ++ __u32 m:1; ++ __u32 ssid:2; ++ __u32 one:1; ++ __u32 sch_no:16; ++} __attribute__ ((packed, aligned(4))) SubChannelId; + + struct chsc_header { + __u16 length; + __u16 code; + } __attribute__((packed)); + +-struct chsc_area_sda { ++typedef struct chsc_area_sda { + struct chsc_header request; + __u8 reserved1:4; + __u8 format:4; +@@ -111,29 +111,29 @@ struct chsc_area_sda { + __u32 reserved5:4; + __u32 format2:4; + __u32 reserved6:24; +-} __attribute__((packed)); ++} __attribute__((packed)) ChscAreaSda; + + /* + * TPI info structure + */ + struct tpi_info { + struct subchannel_id schid; +- __u32 intparm; /* interruption parameter */ +- __u32 adapter_IO : 1; +- __u32 reserved2 : 1; +- __u32 isc : 3; +- __u32 reserved3 : 12; +- __u32 int_type : 3; +- __u32 reserved4 : 12; ++ __u32 intparm; /* interruption parameter */ ++ __u32 adapter_IO:1; ++ __u32 reserved2:1; ++ __u32 isc:3; ++ __u32 reserved3:12; ++ __u32 int_type:3; ++ __u32 reserved4:12; + } __attribute__ ((packed, aligned(4))); + + /* channel command word (type 1) */ +-struct ccw1 { ++typedef struct ccw1 { + __u8 cmd_code; + __u8 flags; + __u16 count; + __u32 cda; +-} __attribute__ ((packed, aligned(8))); ++} __attribute__ ((packed, aligned(8))) Ccw1; + + #define CCW_FLAG_DC 0x80 + #define CCW_FLAG_CC 0x40 +@@ -162,7 +162,7 @@ struct ccw1 { + /* + * Command-mode operation request block + */ +-struct cmd_orb { ++typedef struct cmd_orb { + __u32 intparm; /* interruption parameter */ + __u32 key:4; /* flags, like key, suspend control, etc. */ + __u32 spnd:1; /* suspend control */ +@@ -182,7 +182,7 @@ struct cmd_orb { + __u32 zero:6; /* reserved zeros */ + __u32 orbx:1; /* ORB extension control */ + __u32 cpa; /* channel program address */ +-} __attribute__ ((packed, aligned(4))); ++} __attribute__ ((packed, aligned(4))) CmdOrb; + + struct ciw { + __u8 type; +@@ -193,7 +193,7 @@ struct ciw { + /* + * sense-id response buffer layout + */ +-struct senseid { ++typedef struct senseid { + /* common part */ + __u8 reserved; /* always 0x'FF' */ + __u16 cu_type; /* control unit type */ +@@ -203,15 +203,15 @@ struct senseid { + __u8 unused; /* padding byte */ + /* extended part */ + struct ciw ciw[62]; +-} __attribute__ ((packed, aligned(4))); ++} __attribute__ ((packed, aligned(4))) SenseId; + + /* interruption response block */ +-struct irb { ++typedef struct irb { + struct scsw scsw; + __u32 esw[5]; + __u32 ecw[8]; + __u32 emw[8]; +-} __attribute__ ((packed, aligned(4))); ++} __attribute__ ((packed, aligned(4))) Irb; + + /* + * Some S390 specific IO instructions as inline +diff --git a/pc-bios/s390-ccw/s390-ccw.h b/pc-bios/s390-ccw/s390-ccw.h +index 9828aa2..241c6d0 100644 +--- a/pc-bios/s390-ccw/s390-ccw.h ++++ b/pc-bios/s390-ccw/s390-ccw.h +@@ -49,14 +49,6 @@ typedef unsigned long long __u64; + #include "cio.h" + #include "iplb.h" + +-typedef struct irb Irb; +-typedef struct ccw1 Ccw1; +-typedef struct cmd_orb CmdOrb; +-typedef struct schib Schib; +-typedef struct chsc_area_sda ChscAreaSda; +-typedef struct senseid SenseId; +-typedef struct subchannel_id SubChannelId; +- + /* start.s */ + void disabled_wait(void); + void consume_sclp_int(void); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390-bios-Decouple-channel-i-o-logic-from-virtio.patch b/SOURCES/kvm-s390-bios-Decouple-channel-i-o-logic-from-virtio.patch new file mode 100644 index 0000000..4e8b917 --- /dev/null +++ b/SOURCES/kvm-s390-bios-Decouple-channel-i-o-logic-from-virtio.patch @@ -0,0 +1,226 @@ +From 9fa5a139c303dd7cedabafda03bcd79807b01086 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Mon, 14 Oct 2019 10:06:34 +0100 +Subject: [PATCH 09/21] s390-bios: Decouple channel i/o logic from virtio + +RH-Author: Thomas Huth +Message-id: <20191014100645.22862-7-thuth@redhat.com> +Patchwork-id: 91779 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH v2 06/17] s390-bios: Decouple channel i/o logic from virtio +Bugzilla: 1664376 +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand +RH-Acked-by: Jens Freimann + +From: "Jason J. Herne" + +Create a separate library for channel i/o related code. This decouples +channel i/o operations from virtio and allows us to make use of them for +the real dasd boot path. + +Signed-off-by: Jason J. Herne +Reviewed-by: Cornelia Huck +Reviewed-by: Thomas Huth +Message-Id: <1554388475-18329-6-git-send-email-jjherne@linux.ibm.com> +Signed-off-by: Thomas Huth +(cherry picked from commit 120d04103e3f870d0fcd2a23c2ada0a4a4f036cc) +Signed-off-by: Danilo C. L. de Paula +--- + pc-bios/s390-ccw/Makefile | 2 +- + pc-bios/s390-ccw/cio.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ + pc-bios/s390-ccw/cio.h | 3 +++ + pc-bios/s390-ccw/main.c | 1 + + pc-bios/s390-ccw/netboot.mak | 2 +- + pc-bios/s390-ccw/netmain.c | 1 + + pc-bios/s390-ccw/s390-ccw.h | 1 - + pc-bios/s390-ccw/virtio.c | 27 ++------------------------- + 8 files changed, 53 insertions(+), 28 deletions(-) + create mode 100644 pc-bios/s390-ccw/cio.c + +diff --git a/pc-bios/s390-ccw/Makefile b/pc-bios/s390-ccw/Makefile +index 439e3cc..acca961 100644 +--- a/pc-bios/s390-ccw/Makefile ++++ b/pc-bios/s390-ccw/Makefile +@@ -10,7 +10,7 @@ $(call set-vpath, $(SRC_PATH)/pc-bios/s390-ccw) + .PHONY : all clean build-all + + OBJECTS = start.o main.o bootmap.o jump2ipl.o sclp.o menu.o \ +- virtio.o virtio-scsi.o virtio-blkdev.o libc.o ++ virtio.o virtio-scsi.o virtio-blkdev.o libc.o cio.o + + QEMU_CFLAGS := $(filter -W%, $(QEMU_CFLAGS)) + QEMU_CFLAGS += -ffreestanding -fno-delete-null-pointer-checks -msoft-float +diff --git a/pc-bios/s390-ccw/cio.c b/pc-bios/s390-ccw/cio.c +new file mode 100644 +index 0000000..87c6b34 +--- /dev/null ++++ b/pc-bios/s390-ccw/cio.c +@@ -0,0 +1,44 @@ ++/* ++ * S390 Channel I/O ++ * ++ * Copyright (c) 2013 Alexander Graf ++ * Copyright (c) 2019 IBM Corp. ++ * ++ * Author(s): Jason J. Herne ++ * ++ * This work is licensed under the terms of the GNU GPL, version 2 or (at ++ * your option) any later version. See the COPYING file in the top-level ++ * directory. ++ */ ++ ++#include "libc.h" ++#include "s390-ccw.h" ++#include "cio.h" ++ ++static char chsc_page[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE))); ++ ++int enable_mss_facility(void) ++{ ++ int ret; ++ ChscAreaSda *sda_area = (ChscAreaSda *) chsc_page; ++ ++ memset(sda_area, 0, PAGE_SIZE); ++ sda_area->request.length = 0x0400; ++ sda_area->request.code = 0x0031; ++ sda_area->operation_code = 0x2; ++ ++ ret = chsc(sda_area); ++ if ((ret == 0) && (sda_area->response.code == 0x0001)) { ++ return 0; ++ } ++ return -EIO; ++} ++ ++void enable_subchannel(SubChannelId schid) ++{ ++ Schib schib; ++ ++ stsch_err(schid, &schib); ++ schib.pmcw.ena = 1; ++ msch(schid, &schib); ++} +diff --git a/pc-bios/s390-ccw/cio.h b/pc-bios/s390-ccw/cio.h +index ed5b2cb..218fd96 100644 +--- a/pc-bios/s390-ccw/cio.h ++++ b/pc-bios/s390-ccw/cio.h +@@ -213,6 +213,9 @@ typedef struct irb { + __u32 emw[8]; + } __attribute__ ((packed, aligned(4))) Irb; + ++int enable_mss_facility(void); ++void enable_subchannel(SubChannelId schid); ++ + /* + * Some S390 specific IO instructions as inline + */ +diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c +index 67df421..10f04c6 100644 +--- a/pc-bios/s390-ccw/main.c ++++ b/pc-bios/s390-ccw/main.c +@@ -10,6 +10,7 @@ + + #include "libc.h" + #include "s390-ccw.h" ++#include "cio.h" + #include "virtio.h" + + char stack[PAGE_SIZE * 8] __attribute__((__aligned__(PAGE_SIZE))); +diff --git a/pc-bios/s390-ccw/netboot.mak b/pc-bios/s390-ccw/netboot.mak +index 4f64128..d17b424 100644 +--- a/pc-bios/s390-ccw/netboot.mak ++++ b/pc-bios/s390-ccw/netboot.mak +@@ -1,7 +1,7 @@ + + SLOF_DIR := $(SRC_PATH)/roms/SLOF + +-NETOBJS := start.o sclp.o virtio.o virtio-net.o jump2ipl.o netmain.o \ ++NETOBJS := start.o sclp.o cio.o virtio.o virtio-net.o jump2ipl.o netmain.o \ + libnet.a libc.a + + LIBC_INC := -nostdinc -I$(SLOF_DIR)/lib/libc/include +diff --git a/pc-bios/s390-ccw/netmain.c b/pc-bios/s390-ccw/netmain.c +index d60e84f..4e1b8cf 100644 +--- a/pc-bios/s390-ccw/netmain.c ++++ b/pc-bios/s390-ccw/netmain.c +@@ -32,6 +32,7 @@ + #include + + #include "s390-ccw.h" ++#include "cio.h" + #include "virtio.h" + + #define DEFAULT_BOOT_RETRIES 10 +diff --git a/pc-bios/s390-ccw/s390-ccw.h b/pc-bios/s390-ccw/s390-ccw.h +index 241c6d0..b39ee5d 100644 +--- a/pc-bios/s390-ccw/s390-ccw.h ++++ b/pc-bios/s390-ccw/s390-ccw.h +@@ -72,7 +72,6 @@ unsigned long virtio_load_direct(ulong rec_list1, ulong rec_list2, + bool virtio_is_supported(SubChannelId schid); + void virtio_blk_setup_device(SubChannelId schid); + int virtio_read(ulong sector, void *load_addr); +-int enable_mss_facility(void); + u64 get_clock(void); + ulong get_second(void); + +diff --git a/pc-bios/s390-ccw/virtio.c b/pc-bios/s390-ccw/virtio.c +index cdb66f4..aa9da72 100644 +--- a/pc-bios/s390-ccw/virtio.c ++++ b/pc-bios/s390-ccw/virtio.c +@@ -10,6 +10,7 @@ + + #include "libc.h" + #include "s390-ccw.h" ++#include "cio.h" + #include "virtio.h" + #include "virtio-scsi.h" + #include "bswap.h" +@@ -20,8 +21,6 @@ static VRing block[VIRTIO_MAX_VQS]; + static char ring_area[VIRTIO_RING_SIZE * VIRTIO_MAX_VQS] + __attribute__((__aligned__(PAGE_SIZE))); + +-static char chsc_page[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE))); +- + static VDev vdev = { + .nr_vqs = 1, + .vrings = block, +@@ -94,14 +93,9 @@ static int run_ccw(VDev *vdev, int cmd, void *ptr, int len) + { + Ccw1 ccw = {}; + CmdOrb orb = {}; +- Schib schib; + int r; + +- /* start command processing */ +- stsch_err(vdev->schid, &schib); +- /* enable the subchannel for IPL device */ +- schib.pmcw.ena = 1; +- msch(vdev->schid, &schib); ++ enable_subchannel(vdev->schid); + + /* start subchannel command */ + orb.fmt = 1; +@@ -343,20 +337,3 @@ bool virtio_is_supported(SubChannelId schid) + } + return false; + } +- +-int enable_mss_facility(void) +-{ +- int ret; +- ChscAreaSda *sda_area = (ChscAreaSda *) chsc_page; +- +- memset(sda_area, 0, PAGE_SIZE); +- sda_area->request.length = 0x0400; +- sda_area->request.code = 0x0031; +- sda_area->operation_code = 0x2; +- +- ret = chsc(sda_area); +- if ((ret == 0) && (sda_area->response.code == 0x0001)) { +- return 0; +- } +- return -EIO; +-} +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390-bios-Extend-find_dev-for-non-virtio-devices.patch b/SOURCES/kvm-s390-bios-Extend-find_dev-for-non-virtio-devices.patch new file mode 100644 index 0000000..eb8c504 --- /dev/null +++ b/SOURCES/kvm-s390-bios-Extend-find_dev-for-non-virtio-devices.patch @@ -0,0 +1,72 @@ +From edf2dd4c4eda49957b845ea90a084dde0951f92a Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Mon, 14 Oct 2019 10:06:39 +0100 +Subject: [PATCH 14/21] s390-bios: Extend find_dev() for non-virtio devices + +RH-Author: Thomas Huth +Message-id: <20191014100645.22862-12-thuth@redhat.com> +Patchwork-id: 91784 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH v2 11/17] s390-bios: Extend find_dev() for non-virtio devices +Bugzilla: 1664376 +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand +RH-Acked-by: Jens Freimann + +From: "Jason J. Herne" + +We need a method for finding the subchannel of a dasd device. Let's +modify find_dev to handle this since it mostly does what we need. Up to +this point find_dev has been specific to only virtio devices. + +Signed-off-by: Jason J. Herne +Acked-by: Halil Pasic +Reviewed-by: Cornelia Huck +Message-Id: <1554388475-18329-11-git-send-email-jjherne@linux.ibm.com> +Signed-off-by: Thomas Huth +(cherry picked from commit 930072d2bf30986e57dac5c5945a32492f288944) +Signed-off-by: Danilo C. L. de Paula +--- + pc-bios/s390-ccw/main.c | 16 +++++++++++----- + 1 file changed, 11 insertions(+), 5 deletions(-) + +diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c +index e403b5f..d04ea89 100644 +--- a/pc-bios/s390-ccw/main.c ++++ b/pc-bios/s390-ccw/main.c +@@ -52,6 +52,12 @@ unsigned int get_loadparm_index(void) + return atoui(loadparm_str); + } + ++/* ++ * Find the subchannel connected to the given device (dev_no) and fill in the ++ * subchannel information block (schib) with the connected subchannel's info. ++ * NOTE: The global variable blk_schid is updated to contain the subchannel ++ * information. ++ */ + static bool find_dev(Schib *schib, int dev_no) + { + int i, r; +@@ -65,15 +71,15 @@ static bool find_dev(Schib *schib, int dev_no) + if (!schib->pmcw.dnv) { + continue; + } +- if (!virtio_is_supported(blk_schid)) { +- continue; +- } ++ + /* Skip net devices since no IPLB is created and therefore no +- * no network bootloader has been loaded ++ * network bootloader has been loaded + */ +- if (virtio_get_device_type() == VIRTIO_ID_NET && dev_no < 0) { ++ if (virtio_is_supported(blk_schid) && ++ virtio_get_device_type() == VIRTIO_ID_NET && dev_no < 0) { + continue; + } ++ + if ((dev_no < 0) || (schib->pmcw.dev == dev_no)) { + return true; + } +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390-bios-Factor-finding-boot-device-out-of-virtio-c.patch b/SOURCES/kvm-s390-bios-Factor-finding-boot-device-out-of-virtio-c.patch new file mode 100644 index 0000000..3d82337 --- /dev/null +++ b/SOURCES/kvm-s390-bios-Factor-finding-boot-device-out-of-virtio-c.patch @@ -0,0 +1,201 @@ +From e9b154b1297ac5aff8737dde61b6793fcd7c0a69 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Mon, 14 Oct 2019 10:06:40 +0100 +Subject: [PATCH 15/21] s390-bios: Factor finding boot device out of virtio + code path + +RH-Author: Thomas Huth +Message-id: <20191014100645.22862-13-thuth@redhat.com> +Patchwork-id: 91789 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH v2 12/17] s390-bios: Factor finding boot device out of virtio code path +Bugzilla: 1664376 +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand +RH-Acked-by: Jens Freimann + +From: "Jason J. Herne" + +Make a new routine find_boot_device to locate the boot device for all +cases, not just virtio. + +The error message for the case where no boot device has been specified +and a suitable boot device cannot be auto detected was specific to +virtio devices. We update this message to remove virtio specific wording. + +Signed-off-by: Jason J. Herne +Reviewed-by: Farhan Ali +Reviewed-by: Cornelia Huck +Message-Id: <1554388475-18329-12-git-send-email-jjherne@linux.ibm.com> +Signed-off-by: Thomas Huth +(cherry picked from commit 7b361db37b18a75860decc0a85e0194936401d66) +Signed-off-by: Danilo C. L. de Paula + +Conflicts: + tests/boot-serial-test.c + (we're missing commit 052888f043ba in downstream) +Signed-off-by: Thomas Huth + +Signed-off-by: Danilo C. L. de Paula +--- + pc-bios/s390-ccw/main.c | 85 ++++++++++++++++++++++++++---------------------- + tests/boot-serial-test.c | 2 +- + 2 files changed, 47 insertions(+), 40 deletions(-) + +diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c +index d04ea89..d3a161c 100644 +--- a/pc-bios/s390-ccw/main.c ++++ b/pc-bios/s390-ccw/main.c +@@ -58,17 +58,18 @@ unsigned int get_loadparm_index(void) + * NOTE: The global variable blk_schid is updated to contain the subchannel + * information. + */ +-static bool find_dev(Schib *schib, int dev_no) ++static bool find_subch(int dev_no) + { ++ Schib schib; + int i, r; + + for (i = 0; i < 0x10000; i++) { + blk_schid.sch_no = i; +- r = stsch_err(blk_schid, schib); ++ r = stsch_err(blk_schid, &schib); + if ((r == 3) || (r == -EIO)) { + break; + } +- if (!schib->pmcw.dnv) { ++ if (!schib.pmcw.dnv) { + continue; + } + +@@ -80,7 +81,7 @@ static bool find_dev(Schib *schib, int dev_no) + continue; + } + +- if ((dev_no < 0) || (schib->pmcw.dev == dev_no)) { ++ if ((dev_no < 0) || (schib.pmcw.dev == dev_no)) { + return true; + } + } +@@ -136,56 +137,61 @@ static void boot_setup(void) + have_iplb = store_iplb(&iplb); + } + +-static void virtio_setup(void) ++static void find_boot_device(void) + { +- Schib schib; +- int ssid; +- bool found = false; +- uint16_t dev_no; + VDev *vdev = virtio_get_device(); +- QemuIplParameters *early_qipl = (QemuIplParameters *)QIPL_ADDRESS; +- +- memcpy(&qipl, early_qipl, sizeof(QemuIplParameters)); ++ int ssid; ++ bool found; + +- if (have_iplb) { +- switch (iplb.pbt) { +- case S390_IPL_TYPE_CCW: +- dev_no = iplb.ccw.devno; +- debug_print_int("device no. ", dev_no); +- blk_schid.ssid = iplb.ccw.ssid & 0x3; +- debug_print_int("ssid ", blk_schid.ssid); +- found = find_dev(&schib, dev_no); +- break; +- case S390_IPL_TYPE_QEMU_SCSI: +- vdev->scsi_device_selected = true; +- vdev->selected_scsi_device.channel = iplb.scsi.channel; +- vdev->selected_scsi_device.target = iplb.scsi.target; +- vdev->selected_scsi_device.lun = iplb.scsi.lun; +- blk_schid.ssid = iplb.scsi.ssid & 0x3; +- found = find_dev(&schib, iplb.scsi.devno); +- break; +- default: +- panic("List-directed IPL not supported yet!\n"); +- } +- menu_setup(); +- } else { ++ if (!have_iplb) { + for (ssid = 0; ssid < 0x3; ssid++) { + blk_schid.ssid = ssid; +- found = find_dev(&schib, -1); ++ found = find_subch(-1); + if (found) { +- break; ++ return; + } + } ++ panic("Could not find a suitable boot device (none specified)\n"); ++ } ++ ++ switch (iplb.pbt) { ++ case S390_IPL_TYPE_CCW: ++ debug_print_int("device no. ", iplb.ccw.devno); ++ blk_schid.ssid = iplb.ccw.ssid & 0x3; ++ debug_print_int("ssid ", blk_schid.ssid); ++ found = find_subch(iplb.ccw.devno); ++ break; ++ case S390_IPL_TYPE_QEMU_SCSI: ++ vdev->scsi_device_selected = true; ++ vdev->selected_scsi_device.channel = iplb.scsi.channel; ++ vdev->selected_scsi_device.target = iplb.scsi.target; ++ vdev->selected_scsi_device.lun = iplb.scsi.lun; ++ blk_schid.ssid = iplb.scsi.ssid & 0x3; ++ found = find_subch(iplb.scsi.devno); ++ break; ++ default: ++ panic("List-directed IPL not supported yet!\n"); + } + +- IPL_assert(found, "No virtio device found"); ++ IPL_assert(found, "Boot device not found\n"); ++} ++ ++static void virtio_setup(void) ++{ ++ VDev *vdev = virtio_get_device(); ++ QemuIplParameters *early_qipl = (QemuIplParameters *)QIPL_ADDRESS; ++ ++ memcpy(&qipl, early_qipl, sizeof(QemuIplParameters)); ++ ++ if (have_iplb) { ++ menu_setup(); ++ } + + if (virtio_get_device_type() == VIRTIO_ID_NET) { + sclp_print("Network boot device detected\n"); + vdev->netboot_start_addr = qipl.netboot_start_addr; + } else { + virtio_blk_setup_device(blk_schid); +- + IPL_assert(virtio_ipl_disk_is_valid(), "No valid IPL device detected"); + } + } +@@ -195,8 +201,9 @@ int main(void) + sclp_setup(); + css_setup(); + boot_setup(); +- virtio_setup(); ++ find_boot_device(); + ++ virtio_setup(); + zipl_load(); /* no return */ + + panic("Failed to load OS from hard disk\n"); +diff --git a/tests/boot-serial-test.c b/tests/boot-serial-test.c +index dc682c1..fe52668 100644 +--- a/tests/boot-serial-test.c ++++ b/tests/boot-serial-test.c +@@ -97,7 +97,7 @@ static testdef_t tests[] = { + { "sparc", "SS-600MP", "", "TMS390Z55" }, + { "sparc64", "sun4u", "", "UltraSPARC" }, + { "s390x", "s390-ccw-virtio", +- "-nodefaults -device sclpconsole,chardev=serial0", "virtio device" }, ++ "-nodefaults -device sclpconsole,chardev=serial0", "device" }, + { "m68k", "mcf5208evb", "", "TT", sizeof(kernel_mcf5208), kernel_mcf5208 }, + { "microblaze", "petalogix-s3adsp1800", "", "TT", + sizeof(kernel_pls3adsp1800), kernel_pls3adsp1800 }, +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390-bios-Map-low-core-memory.patch b/SOURCES/kvm-s390-bios-Map-low-core-memory.patch new file mode 100644 index 0000000..51cf633 --- /dev/null +++ b/SOURCES/kvm-s390-bios-Map-low-core-memory.patch @@ -0,0 +1,152 @@ +From 256d99ee0acedd9ca8f21c9ebec83eee5e905c9d Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Mon, 14 Oct 2019 10:06:35 +0100 +Subject: [PATCH 10/21] s390-bios: Map low core memory + +RH-Author: Thomas Huth +Message-id: <20191014100645.22862-8-thuth@redhat.com> +Patchwork-id: 91786 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH v2 07/17] s390-bios: Map low core memory +Bugzilla: 1664376 +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand +RH-Acked-by: Jens Freimann + +From: "Jason J. Herne" + +Create a new header for basic architecture specific definitions and add a +mapping of low core memory. This mapping will be used by the real dasd boot +process. + +Signed-off-by: Jason J. Herne +Acked-by: Cornelia Huck +Reviewed-by: Thomas Huth +Message-Id: <1554388475-18329-7-git-send-email-jjherne@linux.ibm.com> +Signed-off-by: Thomas Huth +(cherry picked from commit c95df3d108028ff5a709ee3aefdb14401b07cb39) +Signed-off-by: Danilo C. L. de Paula +--- + pc-bios/s390-ccw/main.c | 2 + + pc-bios/s390-ccw/s390-arch.h | 90 ++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 92 insertions(+) + create mode 100644 pc-bios/s390-ccw/s390-arch.h + +diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c +index 10f04c6..e403b5f 100644 +--- a/pc-bios/s390-ccw/main.c ++++ b/pc-bios/s390-ccw/main.c +@@ -9,6 +9,7 @@ + */ + + #include "libc.h" ++#include "s390-arch.h" + #include "s390-ccw.h" + #include "cio.h" + #include "virtio.h" +@@ -19,6 +20,7 @@ static char loadparm_str[LOADPARM_LEN + 1] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + QemuIplParameters qipl; + IplParameterBlock iplb __attribute__((__aligned__(PAGE_SIZE))); + static bool have_iplb; ++LowCore const *lowcore; /* Yes, this *is* a pointer to address 0 */ + + #define LOADPARM_PROMPT "PROMPT " + #define LOADPARM_EMPTY " " +diff --git a/pc-bios/s390-ccw/s390-arch.h b/pc-bios/s390-ccw/s390-arch.h +new file mode 100644 +index 0000000..5e92c7a +--- /dev/null ++++ b/pc-bios/s390-ccw/s390-arch.h +@@ -0,0 +1,90 @@ ++/* ++ * S390 Basic Architecture ++ * ++ * Copyright (c) 2019 Jason J. Herne ++ * ++ * This work is licensed under the terms of the GNU GPL, version 2 or (at ++ * your option) any later version. See the COPYING file in the top-level ++ * directory. ++ */ ++ ++#ifndef S390_ARCH_H ++#define S390_ARCH_H ++ ++typedef struct PSW { ++ uint64_t mask; ++ uint64_t addr; ++} __attribute__ ((aligned(8))) PSW; ++_Static_assert(sizeof(struct PSW) == 16, "PSW size incorrect"); ++ ++/* Older PSW format used by LPSW instruction */ ++typedef struct PSWLegacy { ++ uint32_t mask; ++ uint32_t addr; ++} __attribute__ ((aligned(8))) PSWLegacy; ++_Static_assert(sizeof(struct PSWLegacy) == 8, "PSWLegacy size incorrect"); ++ ++/* s390 psw bit masks */ ++#define PSW_MASK_IOINT 0x0200000000000000ULL ++#define PSW_MASK_WAIT 0x0002000000000000ULL ++#define PSW_MASK_EAMODE 0x0000000100000000ULL ++#define PSW_MASK_BAMODE 0x0000000080000000ULL ++#define PSW_MASK_ZMODE (PSW_MASK_EAMODE | PSW_MASK_BAMODE) ++ ++/* Low core mapping */ ++typedef struct LowCore { ++ /* prefix area: defined by architecture */ ++ PSWLegacy ipl_psw; /* 0x000 */ ++ uint32_t ccw1[2]; /* 0x008 */ ++ uint32_t ccw2[2]; /* 0x010 */ ++ uint8_t pad1[0x80 - 0x18]; /* 0x018 */ ++ uint32_t ext_params; /* 0x080 */ ++ uint16_t cpu_addr; /* 0x084 */ ++ uint16_t ext_int_code; /* 0x086 */ ++ uint16_t svc_ilen; /* 0x088 */ ++ uint16_t svc_code; /* 0x08a */ ++ uint16_t pgm_ilen; /* 0x08c */ ++ uint16_t pgm_code; /* 0x08e */ ++ uint32_t data_exc_code; /* 0x090 */ ++ uint16_t mon_class_num; /* 0x094 */ ++ uint16_t per_perc_atmid; /* 0x096 */ ++ uint64_t per_address; /* 0x098 */ ++ uint8_t exc_access_id; /* 0x0a0 */ ++ uint8_t per_access_id; /* 0x0a1 */ ++ uint8_t op_access_id; /* 0x0a2 */ ++ uint8_t ar_access_id; /* 0x0a3 */ ++ uint8_t pad2[0xA8 - 0xA4]; /* 0x0a4 */ ++ uint64_t trans_exc_code; /* 0x0a8 */ ++ uint64_t monitor_code; /* 0x0b0 */ ++ uint16_t subchannel_id; /* 0x0b8 */ ++ uint16_t subchannel_nr; /* 0x0ba */ ++ uint32_t io_int_parm; /* 0x0bc */ ++ uint32_t io_int_word; /* 0x0c0 */ ++ uint8_t pad3[0xc8 - 0xc4]; /* 0x0c4 */ ++ uint32_t stfl_fac_list; /* 0x0c8 */ ++ uint8_t pad4[0xe8 - 0xcc]; /* 0x0cc */ ++ uint64_t mcic; /* 0x0e8 */ ++ uint8_t pad5[0xf4 - 0xf0]; /* 0x0f0 */ ++ uint32_t external_damage_code; /* 0x0f4 */ ++ uint64_t failing_storage_address; /* 0x0f8 */ ++ uint8_t pad6[0x110 - 0x100]; /* 0x100 */ ++ uint64_t per_breaking_event_addr; /* 0x110 */ ++ uint8_t pad7[0x120 - 0x118]; /* 0x118 */ ++ PSW restart_old_psw; /* 0x120 */ ++ PSW external_old_psw; /* 0x130 */ ++ PSW svc_old_psw; /* 0x140 */ ++ PSW program_old_psw; /* 0x150 */ ++ PSW mcck_old_psw; /* 0x160 */ ++ PSW io_old_psw; /* 0x170 */ ++ uint8_t pad8[0x1a0 - 0x180]; /* 0x180 */ ++ PSW restart_new_psw; /* 0x1a0 */ ++ PSW external_new_psw; /* 0x1b0 */ ++ PSW svc_new_psw; /* 0x1c0 */ ++ PSW program_new_psw; /* 0x1d0 */ ++ PSW mcck_new_psw; /* 0x1e0 */ ++ PSW io_new_psw; /* 0x1f0 */ ++} __attribute__((packed, aligned(8192))) LowCore; ++ ++extern LowCore const *lowcore; ++ ++#endif +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390-bios-Refactor-virtio-to-run-channel-programs-vi.patch b/SOURCES/kvm-s390-bios-Refactor-virtio-to-run-channel-programs-vi.patch new file mode 100644 index 0000000..ba8e222 --- /dev/null +++ b/SOURCES/kvm-s390-bios-Refactor-virtio-to-run-channel-programs-vi.patch @@ -0,0 +1,159 @@ +From 776fe22777dd348073449622797cfd9d12058f38 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Mon, 14 Oct 2019 10:06:41 +0100 +Subject: [PATCH 16/21] s390-bios: Refactor virtio to run channel programs via + cio + +RH-Author: Thomas Huth +Message-id: <20191014100645.22862-14-thuth@redhat.com> +Patchwork-id: 91793 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH v2 13/17] s390-bios: Refactor virtio to run channel programs via cio +Bugzilla: 1664376 +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand +RH-Acked-by: Jens Freimann + +From: "Jason J. Herne" + +Now that we have a Channel I/O library let's modify virtio boot code to +make use of it for running channel programs. + +Signed-off-by: Jason J. Herne +Reviewed-by: Cornelia Huck +Acked-by: Thomas Huth +Message-Id: <1554388475-18329-13-git-send-email-jjherne@linux.ibm.com> +Signed-off-by: Thomas Huth +(cherry picked from commit 9de6cbb152bee3917e58ad00633eddafb40d6678) +Signed-off-by: Danilo C. L. de Paula +--- + pc-bios/s390-ccw/virtio.c | 57 ++++++++++++++++++++++------------------------- + 1 file changed, 27 insertions(+), 30 deletions(-) + +diff --git a/pc-bios/s390-ccw/virtio.c b/pc-bios/s390-ccw/virtio.c +index aa9da72..35278eae 100644 +--- a/pc-bios/s390-ccw/virtio.c ++++ b/pc-bios/s390-ccw/virtio.c +@@ -14,6 +14,7 @@ + #include "virtio.h" + #include "virtio-scsi.h" + #include "bswap.h" ++#include "helper.h" + + #define VRING_WAIT_REPLY_TIMEOUT 30 + +@@ -89,33 +90,20 @@ int drain_irqs(SubChannelId schid) + } + } + +-static int run_ccw(VDev *vdev, int cmd, void *ptr, int len) ++static int run_ccw(VDev *vdev, int cmd, void *ptr, int len, bool sli) + { + Ccw1 ccw = {}; +- CmdOrb orb = {}; +- int r; +- +- enable_subchannel(vdev->schid); +- +- /* start subchannel command */ +- orb.fmt = 1; +- orb.cpa = (u32)(long)&ccw; +- orb.lpm = 0x80; + + ccw.cmd_code = cmd; + ccw.cda = (long)ptr; + ccw.count = len; + +- r = ssch(vdev->schid, &orb); +- /* +- * XXX Wait until device is done processing the CCW. For now we can +- * assume that a simple tsch will have finished the CCW processing, +- * but the architecture allows for asynchronous operation +- */ +- if (!r) { +- r = drain_irqs(vdev->schid); ++ if (sli) { ++ ccw.flags |= CCW_FLAG_SLI; + } +- return r; ++ ++ enable_subchannel(vdev->schid); ++ return do_cio(vdev->schid, vdev->senseid.cu_type, ptr2u32(&ccw), CCW_FMT1); + } + + static void vring_init(VRing *vr, VqInfo *info) +@@ -257,7 +245,7 @@ void virtio_setup_ccw(VDev *vdev) + vdev->config.blk.blk_size = 0; /* mark "illegal" - setup started... */ + vdev->guessed_disk_nature = VIRTIO_GDN_NONE; + +- run_ccw(vdev, CCW_CMD_VDEV_RESET, NULL, 0); ++ run_ccw(vdev, CCW_CMD_VDEV_RESET, NULL, 0, false); + + switch (vdev->senseid.cu_model) { + case VIRTIO_ID_NET: +@@ -278,18 +266,19 @@ void virtio_setup_ccw(VDev *vdev) + default: + panic("Unsupported virtio device\n"); + } +- IPL_assert(run_ccw(vdev, CCW_CMD_READ_CONF, &vdev->config, cfg_size) == 0, +- "Could not get block device configuration"); ++ IPL_assert( ++ run_ccw(vdev, CCW_CMD_READ_CONF, &vdev->config, cfg_size, false) == 0, ++ "Could not get block device configuration"); + + /* Feature negotiation */ + for (i = 0; i < ARRAY_SIZE(vdev->guest_features); i++) { + feats.features = 0; + feats.index = i; +- rc = run_ccw(vdev, CCW_CMD_READ_FEAT, &feats, sizeof(feats)); ++ rc = run_ccw(vdev, CCW_CMD_READ_FEAT, &feats, sizeof(feats), false); + IPL_assert(rc == 0, "Could not get features bits"); + vdev->guest_features[i] &= bswap32(feats.features); + feats.features = bswap32(vdev->guest_features[i]); +- rc = run_ccw(vdev, CCW_CMD_WRITE_FEAT, &feats, sizeof(feats)); ++ rc = run_ccw(vdev, CCW_CMD_WRITE_FEAT, &feats, sizeof(feats), false); + IPL_assert(rc == 0, "Could not set features bits"); + } + +@@ -306,16 +295,17 @@ void virtio_setup_ccw(VDev *vdev) + }; + + IPL_assert( +- run_ccw(vdev, CCW_CMD_READ_VQ_CONF, &config, sizeof(config)) == 0, ++ run_ccw(vdev, CCW_CMD_READ_VQ_CONF, &config, sizeof(config), false) == 0, + "Could not get block device VQ configuration"); + info.num = config.num; + vring_init(&vdev->vrings[i], &info); + vdev->vrings[i].schid = vdev->schid; +- IPL_assert(run_ccw(vdev, CCW_CMD_SET_VQ, &info, sizeof(info)) == 0, +- "Cannot set VQ info"); ++ IPL_assert( ++ run_ccw(vdev, CCW_CMD_SET_VQ, &info, sizeof(info), false) == 0, ++ "Cannot set VQ info"); + } + IPL_assert( +- run_ccw(vdev, CCW_CMD_WRITE_STATUS, &status, sizeof(status)) == 0, ++ run_ccw(vdev, CCW_CMD_WRITE_STATUS, &status, sizeof(status), false) == 0, + "Could not write status to host"); + } + +@@ -323,8 +313,15 @@ bool virtio_is_supported(SubChannelId schid) + { + vdev.schid = schid; + memset(&vdev.senseid, 0, sizeof(vdev.senseid)); +- /* run sense id command */ +- if (run_ccw(&vdev, CCW_CMD_SENSE_ID, &vdev.senseid, sizeof(vdev.senseid))) { ++ ++ /* ++ * Run sense id command. ++ * The size of the senseid data differs between devices (notably, ++ * between virtio devices and dasds), so specify the largest possible ++ * size and suppress the incorrect length indication for smaller sizes. ++ */ ++ if (run_ccw(&vdev, CCW_CMD_SENSE_ID, &vdev.senseid, sizeof(vdev.senseid), ++ true)) { + return false; + } + if (vdev.senseid.cu_type == 0x3832) { +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390-bios-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-bios-Support-booting-from-real-dasd-device.patch b/SOURCES/kvm-s390-bios-Support-booting-from-real-dasd-device.patch new file mode 100644 index 0000000..86522dc --- /dev/null +++ b/SOURCES/kvm-s390-bios-Support-booting-from-real-dasd-device.patch @@ -0,0 +1,520 @@ +From 2267eadd85126ea711cc8314c7df45a70486651c Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Mon, 14 Oct 2019 10:06:44 +0100 +Subject: [PATCH 19/21] s390-bios: Support booting from real dasd device + +RH-Author: Thomas Huth +Message-id: <20191014100645.22862-17-thuth@redhat.com> +Patchwork-id: 91791 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH v2 16/17] s390-bios: Support booting from real dasd device +Bugzilla: 1664376 +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand +RH-Acked-by: Jens Freimann + +From: "Jason J. Herne" + +Allows guest to boot from a vfio configured real dasd device. + +Signed-off-by: Jason J. Herne +Reviewed-by: Cornelia Huck +Message-Id: <1554388475-18329-16-git-send-email-jjherne@linux.ibm.com> +Signed-off-by: Thomas Huth +(cherry picked from commit efa47d36da89f4b23c315a7cc085fab0d15eb47c) +Signed-off-by: Danilo C. L. de Paula + +Conflicts: + MAINTAINERS + (simple contextual conflict due to missing downstream commits) + +Signed-off-by: Danilo C. L. de Paula +--- + MAINTAINERS | 3 +- + docs/devel/s390-dasd-ipl.txt | 133 ++++++++++++++++++++++++ + pc-bios/s390-ccw/Makefile | 2 +- + pc-bios/s390-ccw/dasd-ipl.c | 235 +++++++++++++++++++++++++++++++++++++++++++ + pc-bios/s390-ccw/dasd-ipl.h | 16 +++ + pc-bios/s390-ccw/main.c | 5 + + pc-bios/s390-ccw/s390-arch.h | 13 +++ + 7 files changed, 405 insertions(+), 2 deletions(-) + create mode 100644 docs/devel/s390-dasd-ipl.txt + create mode 100644 pc-bios/s390-ccw/dasd-ipl.c + create mode 100644 pc-bios/s390-ccw/dasd-ipl.h + +diff --git a/MAINTAINERS b/MAINTAINERS +index 9b74756..770885a 100644 +--- a/MAINTAINERS ++++ b/MAINTAINERS +@@ -896,7 +896,8 @@ M: Thomas Huth + S: Supported + F: pc-bios/s390-ccw/ + F: pc-bios/s390-ccw.img +-T: git git://github.com/borntraeger/qemu.git s390-next ++F: docs/devel/s390-dasd-ipl.txt ++T: git https://github.com/borntraeger/qemu.git s390-next + L: qemu-s390x@nongnu.org + + UniCore32 Machines +diff --git a/docs/devel/s390-dasd-ipl.txt b/docs/devel/s390-dasd-ipl.txt +new file mode 100644 +index 0000000..9107e04 +--- /dev/null ++++ b/docs/devel/s390-dasd-ipl.txt +@@ -0,0 +1,133 @@ ++***************************** ++***** s390 hardware IPL ***** ++***************************** ++ ++The s390 hardware IPL process consists of the following steps. ++ ++1. A READ IPL ccw is constructed in memory location 0x0. ++ This ccw, by definition, reads the IPL1 record which is located on the disk ++ at cylinder 0 track 0 record 1. Note that the chain flag is on in this ccw ++ so when it is complete another ccw will be fetched and executed from memory ++ location 0x08. ++ ++2. Execute the Read IPL ccw at 0x00, thereby reading IPL1 data into 0x00. ++ IPL1 data is 24 bytes in length and consists of the following pieces of ++ information: [psw][read ccw][tic ccw]. When the machine executes the Read ++ IPL ccw it read the 24-bytes of IPL1 to be read into memory starting at ++ location 0x0. Then the ccw program at 0x08 which consists of a read ++ ccw and a tic ccw is automatically executed because of the chain flag from ++ the original READ IPL ccw. The read ccw will read the IPL2 data into memory ++ and the TIC (Transfer In Channel) will transfer control to the channel ++ program contained in the IPL2 data. The TIC channel command is the ++ equivalent of a branch/jump/goto instruction for channel programs. ++ NOTE: The ccws in IPL1 are defined by the architecture to be format 0. ++ ++3. Execute IPL2. ++ The TIC ccw instruction at the end of the IPL1 channel program will begin ++ the execution of the IPL2 channel program. IPL2 is stage-2 of the boot ++ process and will contain a larger channel program than IPL1. The point of ++ IPL2 is to find and load either the operating system or a small program that ++ loads the operating system from disk. At the end of this step all or some of ++ the real operating system is loaded into memory and we are ready to hand ++ control over to the guest operating system. At this point the guest ++ operating system is entirely responsible for loading any more data it might ++ need to function. NOTE: The IPL2 channel program might read data into memory ++ location 0 thereby overwriting the IPL1 psw and channel program. This is ok ++ as long as the data placed in location 0 contains a psw whose instruction ++ address points to the guest operating system code to execute at the end of ++ the IPL/boot process. ++ NOTE: The ccws in IPL2 are defined by the architecture to be format 0. ++ ++4. Start executing the guest operating system. ++ The psw that was loaded into memory location 0 as part of the ipl process ++ should contain the needed flags for the operating system we have loaded. The ++ psw's instruction address will point to the location in memory where we want ++ to start executing the operating system. This psw is loaded (via LPSW ++ instruction) causing control to be passed to the operating system code. ++ ++In a non-virtualized environment this process, handled entirely by the hardware, ++is kicked off by the user initiating a "Load" procedure from the hardware ++management console. This "Load" procedure crafts a special "Read IPL" ccw in ++memory location 0x0 that reads IPL1. It then executes this ccw thereby kicking ++off the reading of IPL1 data. Since the channel program from IPL1 will be ++written immediately after the special "Read IPL" ccw, the IPL1 channel program ++will be executed immediately (the special read ccw has the chaining bit turned ++on). The TIC at the end of the IPL1 channel program will cause the IPL2 channel ++program to be executed automatically. After this sequence completes the "Load" ++procedure then loads the psw from 0x0. ++ ++********************************************************** ++***** How this all pertains to QEMU (and the kernel) ***** ++********************************************************** ++ ++In theory we should merely have to do the following to IPL/boot a guest ++operating system from a DASD device: ++ ++1. Place a "Read IPL" ccw into memory location 0x0 with chaining bit on. ++2. Execute channel program at 0x0. ++3. LPSW 0x0. ++ ++However, our emulation of the machine's channel program logic within the kernel ++is missing one key feature that is required for this process to work: ++non-prefetch of ccw data. ++ ++When we start a channel program we pass the channel subsystem parameters via an ++ORB (Operation Request Block). One of those parameters is a prefetch bit. If the ++bit is on then the vfio-ccw kernel driver is allowed to read the entire channel ++program from guest memory before it starts executing it. This means that any ++channel commands that read additional channel commands will not work as expected ++because the newly read commands will only exist in guest memory and NOT within ++the kernel's channel subsystem memory. The kernel vfio-ccw driver currently ++requires this bit to be on for all channel programs. This is a problem because ++the IPL process consists of transferring control from the "Read IPL" ccw ++immediately to the IPL1 channel program that was read by "Read IPL". ++ ++Not being able to turn off prefetch will also prevent the TIC at the end of the ++IPL1 channel program from transferring control to the IPL2 channel program. ++ ++Lastly, in some cases (the zipl bootloader for example) the IPL2 program also ++transfers control to another channel program segment immediately after reading ++it from the disk. So we need to be able to handle this case. ++ ++************************** ++***** What QEMU does ***** ++************************** ++ ++Since we are forced to live with prefetch we cannot use the very simple IPL ++procedure we defined in the preceding section. So we compensate by doing the ++following. ++ ++1. Place "Read IPL" ccw into memory location 0x0, but turn off chaining bit. ++2. Execute "Read IPL" at 0x0. ++ ++ So now IPL1's psw is at 0x0 and IPL1's channel program is at 0x08. ++ ++4. Write a custom channel program that will seek to the IPL2 record and then ++ execute the READ and TIC ccws from IPL1. Normally the seek is not required ++ because after reading the IPL1 record the disk is automatically positioned ++ to read the very next record which will be IPL2. But since we are not reading ++ both IPL1 and IPL2 as part of the same channel program we must manually set ++ the position. ++ ++5. Grab the target address of the TIC instruction from the IPL1 channel program. ++ This address is where the IPL2 channel program starts. ++ ++ Now IPL2 is loaded into memory somewhere, and we know the address. ++ ++6. Execute the IPL2 channel program at the address obtained in step #5. ++ ++ Because this channel program can be dynamic, we must use a special algorithm ++ that detects a READ immediately followed by a TIC and breaks the ccw chain ++ by turning off the chain bit in the READ ccw. When control is returned from ++ the kernel/hardware to the QEMU bios code we immediately issue another start ++ subchannel to execute the remaining TIC instruction. This causes the entire ++ channel program (starting from the TIC) and all needed data to be refetched ++ thereby stepping around the limitation that would otherwise prevent this ++ channel program from executing properly. ++ ++ Now the operating system code is loaded somewhere in guest memory and the psw ++ in memory location 0x0 will point to entry code for the guest operating ++ system. ++ ++7. LPSW 0x0. ++ LPSW transfers control to the guest operating system and we're done. +diff --git a/pc-bios/s390-ccw/Makefile b/pc-bios/s390-ccw/Makefile +index acca961..d6a6e18 100644 +--- a/pc-bios/s390-ccw/Makefile ++++ b/pc-bios/s390-ccw/Makefile +@@ -10,7 +10,7 @@ $(call set-vpath, $(SRC_PATH)/pc-bios/s390-ccw) + .PHONY : all clean build-all + + OBJECTS = start.o main.o bootmap.o jump2ipl.o sclp.o menu.o \ +- virtio.o virtio-scsi.o virtio-blkdev.o libc.o cio.o ++ virtio.o virtio-scsi.o virtio-blkdev.o libc.o cio.o dasd-ipl.o + + QEMU_CFLAGS := $(filter -W%, $(QEMU_CFLAGS)) + QEMU_CFLAGS += -ffreestanding -fno-delete-null-pointer-checks -msoft-float +diff --git a/pc-bios/s390-ccw/dasd-ipl.c b/pc-bios/s390-ccw/dasd-ipl.c +new file mode 100644 +index 0000000..0fc879b +--- /dev/null ++++ b/pc-bios/s390-ccw/dasd-ipl.c +@@ -0,0 +1,235 @@ ++/* ++ * S390 IPL (boot) from a real DASD device via vfio framework. ++ * ++ * Copyright (c) 2019 Jason J. Herne ++ * ++ * This work is licensed under the terms of the GNU GPL, version 2 or (at ++ * your option) any later version. See the COPYING file in the top-level ++ * directory. ++ */ ++ ++#include "libc.h" ++#include "s390-ccw.h" ++#include "s390-arch.h" ++#include "dasd-ipl.h" ++#include "helper.h" ++ ++static char prefix_page[PAGE_SIZE * 2] ++ __attribute__((__aligned__(PAGE_SIZE * 2))); ++ ++static void enable_prefixing(void) ++{ ++ memcpy(&prefix_page, lowcore, 4096); ++ set_prefix(ptr2u32(&prefix_page)); ++} ++ ++static void disable_prefixing(void) ++{ ++ set_prefix(0); ++ /* Copy io interrupt info back to low core */ ++ memcpy((void *)&lowcore->subchannel_id, prefix_page + 0xB8, 12); ++} ++ ++static bool is_read_tic_ccw_chain(Ccw0 *ccw) ++{ ++ Ccw0 *next_ccw = ccw + 1; ++ ++ return ((ccw->cmd_code == CCW_CMD_DASD_READ || ++ ccw->cmd_code == CCW_CMD_DASD_READ_MT) && ++ ccw->chain && next_ccw->cmd_code == CCW_CMD_TIC); ++} ++ ++static bool dynamic_cp_fixup(uint32_t ccw_addr, uint32_t *next_cpa) ++{ ++ Ccw0 *cur_ccw = (Ccw0 *)(uint64_t)ccw_addr; ++ Ccw0 *tic_ccw; ++ ++ while (true) { ++ /* Skip over inline TIC (it might not have the chain bit on) */ ++ if (cur_ccw->cmd_code == CCW_CMD_TIC && ++ cur_ccw->cda == ptr2u32(cur_ccw) - 8) { ++ cur_ccw += 1; ++ continue; ++ } ++ ++ if (!cur_ccw->chain) { ++ break; ++ } ++ if (is_read_tic_ccw_chain(cur_ccw)) { ++ /* ++ * Breaking a chain of CCWs may alter the semantics or even the ++ * validity of a channel program. The heuristic implemented below ++ * seems to work well in practice for the channel programs ++ * generated by zipl. ++ */ ++ tic_ccw = cur_ccw + 1; ++ *next_cpa = tic_ccw->cda; ++ cur_ccw->chain = 0; ++ return true; ++ } ++ cur_ccw += 1; ++ } ++ return false; ++} ++ ++static int run_dynamic_ccw_program(SubChannelId schid, uint16_t cutype, ++ uint32_t cpa) ++{ ++ bool has_next; ++ uint32_t next_cpa = 0; ++ int rc; ++ ++ do { ++ has_next = dynamic_cp_fixup(cpa, &next_cpa); ++ ++ print_int("executing ccw chain at ", cpa); ++ enable_prefixing(); ++ rc = do_cio(schid, cutype, cpa, CCW_FMT0); ++ disable_prefixing(); ++ ++ if (rc) { ++ break; ++ } ++ cpa = next_cpa; ++ } while (has_next); ++ ++ return rc; ++} ++ ++static void make_readipl(void) ++{ ++ Ccw0 *ccwIplRead = (Ccw0 *)0x00; ++ ++ /* Create Read IPL ccw at address 0 */ ++ ccwIplRead->cmd_code = CCW_CMD_READ_IPL; ++ ccwIplRead->cda = 0x00; /* Read into address 0x00 in main memory */ ++ ccwIplRead->chain = 0; /* Chain flag */ ++ ccwIplRead->count = 0x18; /* Read 0x18 bytes of data */ ++} ++ ++static void run_readipl(SubChannelId schid, uint16_t cutype) ++{ ++ if (do_cio(schid, cutype, 0x00, CCW_FMT0)) { ++ panic("dasd-ipl: Failed to run Read IPL channel program\n"); ++ } ++} ++ ++/* ++ * The architecture states that IPL1 data should consist of a psw followed by ++ * format-0 READ and TIC CCWs. Let's sanity check. ++ */ ++static void check_ipl1(void) ++{ ++ Ccw0 *ccwread = (Ccw0 *)0x08; ++ Ccw0 *ccwtic = (Ccw0 *)0x10; ++ ++ if (ccwread->cmd_code != CCW_CMD_DASD_READ || ++ ccwtic->cmd_code != CCW_CMD_TIC) { ++ panic("dasd-ipl: IPL1 data invalid. Is this disk really bootable?\n"); ++ } ++} ++ ++static void check_ipl2(uint32_t ipl2_addr) ++{ ++ Ccw0 *ccw = u32toptr(ipl2_addr); ++ ++ if (ipl2_addr == 0x00) { ++ panic("IPL2 address invalid. Is this disk really bootable?\n"); ++ } ++ if (ccw->cmd_code == 0x00) { ++ panic("IPL2 ccw data invalid. Is this disk really bootable?\n"); ++ } ++} ++ ++static uint32_t read_ipl2_addr(void) ++{ ++ Ccw0 *ccwtic = (Ccw0 *)0x10; ++ ++ return ccwtic->cda; ++} ++ ++static void ipl1_fixup(void) ++{ ++ Ccw0 *ccwSeek = (Ccw0 *) 0x08; ++ Ccw0 *ccwSearchID = (Ccw0 *) 0x10; ++ Ccw0 *ccwSearchTic = (Ccw0 *) 0x18; ++ Ccw0 *ccwRead = (Ccw0 *) 0x20; ++ CcwSeekData *seekData = (CcwSeekData *) 0x30; ++ CcwSearchIdData *searchData = (CcwSearchIdData *) 0x38; ++ ++ /* move IPL1 CCWs to make room for CCWs needed to locate record 2 */ ++ memcpy(ccwRead, (void *)0x08, 16); ++ ++ /* Disable chaining so we don't TIC to IPL2 channel program */ ++ ccwRead->chain = 0x00; ++ ++ ccwSeek->cmd_code = CCW_CMD_DASD_SEEK; ++ ccwSeek->cda = ptr2u32(seekData); ++ ccwSeek->chain = 1; ++ ccwSeek->count = sizeof(*seekData); ++ seekData->reserved = 0x00; ++ seekData->cyl = 0x00; ++ seekData->head = 0x00; ++ ++ ccwSearchID->cmd_code = CCW_CMD_DASD_SEARCH_ID_EQ; ++ ccwSearchID->cda = ptr2u32(searchData); ++ ccwSearchID->chain = 1; ++ ccwSearchID->count = sizeof(*searchData); ++ searchData->cyl = 0; ++ searchData->head = 0; ++ searchData->record = 2; ++ ++ /* Go back to Search CCW if correct record not yet found */ ++ ccwSearchTic->cmd_code = CCW_CMD_TIC; ++ ccwSearchTic->cda = ptr2u32(ccwSearchID); ++} ++ ++static void run_ipl1(SubChannelId schid, uint16_t cutype) ++ { ++ uint32_t startAddr = 0x08; ++ ++ if (do_cio(schid, cutype, startAddr, CCW_FMT0)) { ++ panic("dasd-ipl: Failed to run IPL1 channel program\n"); ++ } ++} ++ ++static void run_ipl2(SubChannelId schid, uint16_t cutype, uint32_t addr) ++{ ++ if (run_dynamic_ccw_program(schid, cutype, addr)) { ++ panic("dasd-ipl: Failed to run IPL2 channel program\n"); ++ } ++} ++ ++/* ++ * Limitations in vfio-ccw support complicate the IPL process. Details can ++ * be found in docs/devel/s390-dasd-ipl.txt ++ */ ++void dasd_ipl(SubChannelId schid, uint16_t cutype) ++{ ++ PSWLegacy *pswl = (PSWLegacy *) 0x00; ++ uint32_t ipl2_addr; ++ ++ /* Construct Read IPL CCW and run it to read IPL1 from boot disk */ ++ make_readipl(); ++ run_readipl(schid, cutype); ++ ipl2_addr = read_ipl2_addr(); ++ check_ipl1(); ++ ++ /* ++ * Fixup IPL1 channel program to account for vfio-ccw limitations, then run ++ * it to read IPL2 channel program from boot disk. ++ */ ++ ipl1_fixup(); ++ run_ipl1(schid, cutype); ++ check_ipl2(ipl2_addr); ++ ++ /* ++ * Run IPL2 channel program to read operating system code from boot disk ++ */ ++ run_ipl2(schid, cutype, ipl2_addr); ++ ++ /* Transfer control to the guest operating system */ ++ pswl->mask |= PSW_MASK_EAMODE; /* Force z-mode */ ++ pswl->addr |= PSW_MASK_BAMODE; /* ... */ ++ jump_to_low_kernel(); ++} +diff --git a/pc-bios/s390-ccw/dasd-ipl.h b/pc-bios/s390-ccw/dasd-ipl.h +new file mode 100644 +index 0000000..c394828 +--- /dev/null ++++ b/pc-bios/s390-ccw/dasd-ipl.h +@@ -0,0 +1,16 @@ ++/* ++ * S390 IPL (boot) from a real DASD device via vfio framework. ++ * ++ * Copyright (c) 2019 Jason J. Herne ++ * ++ * This work is licensed under the terms of the GNU GPL, version 2 or (at ++ * your option) any later version. See the COPYING file in the top-level ++ * directory. ++ */ ++ ++#ifndef DASD_IPL_H ++#define DASD_IPL_H ++ ++void dasd_ipl(SubChannelId schid, uint16_t cutype); ++ ++#endif /* DASD_IPL_H */ +diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c +index 57a1013..3c449ad 100644 +--- a/pc-bios/s390-ccw/main.c ++++ b/pc-bios/s390-ccw/main.c +@@ -13,6 +13,7 @@ + #include "s390-ccw.h" + #include "cio.h" + #include "virtio.h" ++#include "dasd-ipl.h" + + char stack[PAGE_SIZE * 8] __attribute__((__aligned__(PAGE_SIZE))); + static SubChannelId blk_schid = { .one = 1 }; +@@ -209,6 +210,10 @@ int main(void) + + cutype = cu_type(blk_schid); + switch (cutype) { ++ case CU_TYPE_DASD_3990: ++ case CU_TYPE_DASD_2107: ++ dasd_ipl(blk_schid, cutype); /* no return */ ++ break; + case CU_TYPE_VIRTIO: + virtio_setup(); + zipl_load(); /* no return */ +diff --git a/pc-bios/s390-ccw/s390-arch.h b/pc-bios/s390-ccw/s390-arch.h +index 5e92c7a..504fc7c 100644 +--- a/pc-bios/s390-ccw/s390-arch.h ++++ b/pc-bios/s390-ccw/s390-arch.h +@@ -87,4 +87,17 @@ typedef struct LowCore { + + extern LowCore const *lowcore; + ++static inline void set_prefix(uint32_t address) ++{ ++ asm volatile("spx %0" : : "m" (address) : "memory"); ++} ++ ++static inline uint32_t store_prefix(void) ++{ ++ uint32_t address; ++ ++ asm volatile("stpx %0" : "=m" (address)); ++ return address; ++} ++ + #endif +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390-bios-Support-for-running-format-0-1-channel-pro.patch b/SOURCES/kvm-s390-bios-Support-for-running-format-0-1-channel-pro.patch new file mode 100644 index 0000000..eb6a65d --- /dev/null +++ b/SOURCES/kvm-s390-bios-Support-for-running-format-0-1-channel-pro.patch @@ -0,0 +1,445 @@ +From 363d844cccb965c9eb0e0e6b5ca100e9532a2f0a Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Mon, 14 Oct 2019 10:06:37 +0100 +Subject: [PATCH 12/21] s390-bios: Support for running format-0/1 channel + programs + +RH-Author: Thomas Huth +Message-id: <20191014100645.22862-10-thuth@redhat.com> +Patchwork-id: 91783 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH v2 09/17] s390-bios: Support for running format-0/1 channel programs +Bugzilla: 1664376 +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand +RH-Acked-by: Jens Freimann + +From: "Jason J. Herne" + +Introduce a library function for executing format-0 and format-1 +channel programs and waiting for their completion before continuing +execution. + +Add cu_type() to channel io library. This will be used to query control +unit type which is used to determine if we are booting a virtio device or a +real dasd device. + +Signed-off-by: Jason J. Herne +Reviewed-by: Cornelia Huck +Reviewed-by: Farhan Ali +Message-Id: <1554388475-18329-9-git-send-email-jjherne@linux.ibm.com> +Signed-off-by: Thomas Huth +(cherry picked from commit 3083a1bbb8716e9052fe375f68f330107ee13127) +Signed-off-by: Danilo C. L. de Paula +--- + pc-bios/s390-ccw/cio.c | 144 ++++++++++++++++++++++++++++++++++++++++++++ + pc-bios/s390-ccw/cio.h | 130 ++++++++++++++++++++++++++++++++++++++- + pc-bios/s390-ccw/s390-ccw.h | 1 + + pc-bios/s390-ccw/start.S | 29 +++++++++ + 4 files changed, 301 insertions(+), 3 deletions(-) + +diff --git a/pc-bios/s390-ccw/cio.c b/pc-bios/s390-ccw/cio.c +index 87c6b34..c43e50b 100644 +--- a/pc-bios/s390-ccw/cio.c ++++ b/pc-bios/s390-ccw/cio.c +@@ -13,10 +13,14 @@ + + #include "libc.h" + #include "s390-ccw.h" ++#include "s390-arch.h" ++#include "helper.h" + #include "cio.h" + + static char chsc_page[PAGE_SIZE] __attribute__((__aligned__(PAGE_SIZE))); + ++static int __do_cio(SubChannelId schid, uint32_t ccw_addr, int fmt, Irb *irb); ++ + int enable_mss_facility(void) + { + int ret; +@@ -42,3 +46,143 @@ void enable_subchannel(SubChannelId schid) + schib.pmcw.ena = 1; + msch(schid, &schib); + } ++ ++uint16_t cu_type(SubChannelId schid) ++{ ++ Ccw1 sense_id_ccw; ++ SenseId sense_data; ++ ++ sense_id_ccw.cmd_code = CCW_CMD_SENSE_ID; ++ sense_id_ccw.cda = ptr2u32(&sense_data); ++ sense_id_ccw.count = sizeof(sense_data); ++ sense_id_ccw.flags |= CCW_FLAG_SLI; ++ ++ if (do_cio(schid, CU_TYPE_UNKNOWN, ptr2u32(&sense_id_ccw), CCW_FMT1)) { ++ panic("Failed to run SenseID CCw\n"); ++ } ++ ++ return sense_data.cu_type; ++} ++ ++int basic_sense(SubChannelId schid, uint16_t cutype, void *sense_data, ++ uint16_t data_size) ++{ ++ Ccw1 senseCcw; ++ Irb irb; ++ ++ senseCcw.cmd_code = CCW_CMD_BASIC_SENSE; ++ senseCcw.cda = ptr2u32(sense_data); ++ senseCcw.count = data_size; ++ ++ return __do_cio(schid, ptr2u32(&senseCcw), CCW_FMT1, &irb); ++} ++ ++static bool irb_error(Irb *irb) ++{ ++ if (irb->scsw.cstat) { ++ return true; ++ } ++ return irb->scsw.dstat != (SCSW_DSTAT_DEVEND | SCSW_DSTAT_CHEND); ++} ++ ++/* ++ * Handles executing ssch, tsch and returns the irb obtained from tsch. ++ * Returns 0 on success, -1 if unexpected status pending and we need to retry, ++ * otherwise returns condition code from ssch/tsch for error cases. ++ */ ++static int __do_cio(SubChannelId schid, uint32_t ccw_addr, int fmt, Irb *irb) ++{ ++ CmdOrb orb = {}; ++ int rc; ++ ++ IPL_assert(fmt == 0 || fmt == 1, "Invalid ccw format"); ++ ++ /* ccw_addr must be <= 24 bits and point to at least one whole ccw. */ ++ if (fmt == 0) { ++ IPL_assert(ccw_addr <= 0xFFFFFF - 8, "Invalid ccw address"); ++ } ++ ++ orb.fmt = fmt; ++ orb.pfch = 1; /* QEMU's cio implementation requires prefetch */ ++ orb.c64 = 1; /* QEMU's cio implementation requires 64-bit idaws */ ++ orb.lpm = 0xFF; /* All paths allowed */ ++ orb.cpa = ccw_addr; ++ ++ rc = ssch(schid, &orb); ++ if (rc == 1 || rc == 2) { ++ /* Subchannel status pending or busy. Eat status and ask for retry. */ ++ tsch(schid, irb); ++ return -1; ++ } ++ if (rc) { ++ print_int("ssch failed with cc=", rc); ++ return rc; ++ } ++ ++ consume_io_int(); ++ ++ /* collect status */ ++ rc = tsch(schid, irb); ++ if (rc) { ++ print_int("tsch failed with cc=", rc); ++ } ++ ++ return rc; ++} ++ ++/* ++ * Executes a channel program at a given subchannel. The request to run the ++ * channel program is sent to the subchannel, we then wait for the interrupt ++ * signaling completion of the I/O operation(s) performed by the channel ++ * program. Lastly we verify that the i/o operation completed without error and ++ * that the interrupt we received was for the subchannel used to run the ++ * channel program. ++ * ++ * Note: This function assumes it is running in an environment where no other ++ * cpus are generating or receiving I/O interrupts. So either run it in a ++ * single-cpu environment or make sure all other cpus are not doing I/O and ++ * have I/O interrupts masked off. We also assume that only one device is ++ * active (generating i/o interrupts). ++ * ++ * Returns non-zero on error. ++ */ ++int do_cio(SubChannelId schid, uint16_t cutype, uint32_t ccw_addr, int fmt) ++{ ++ Irb irb = {}; ++ SenseDataEckdDasd sd; ++ int rc, retries = 0; ++ ++ while (true) { ++ rc = __do_cio(schid, ccw_addr, fmt, &irb); ++ ++ if (rc == -1) { ++ retries++; ++ continue; ++ } ++ if (rc) { ++ /* ssch/tsch error. Message already reported by __do_cio */ ++ break; ++ } ++ ++ if (!irb_error(&irb)) { ++ break; ++ } ++ ++ /* ++ * Unexpected unit check, or interface-control-check. Use sense to ++ * clear (unit check only) then retry. ++ */ ++ if ((unit_check(&irb) || iface_ctrl_check(&irb)) && retries <= 2) { ++ if (unit_check(&irb)) { ++ basic_sense(schid, cutype, &sd, sizeof(sd)); ++ } ++ retries++; ++ continue; ++ } ++ ++ rc = -1; ++ break; ++ } ++ ++ return rc; ++} +diff --git a/pc-bios/s390-ccw/cio.h b/pc-bios/s390-ccw/cio.h +index 218fd96..1637e32 100644 +--- a/pc-bios/s390-ccw/cio.h ++++ b/pc-bios/s390-ccw/cio.h +@@ -70,9 +70,46 @@ struct scsw { + __u16 count; + } __attribute__ ((packed)); + +-#define SCSW_FCTL_CLEAR_FUNC 0x1000 +-#define SCSW_FCTL_HALT_FUNC 0x2000 ++/* Function Control */ + #define SCSW_FCTL_START_FUNC 0x4000 ++#define SCSW_FCTL_HALT_FUNC 0x2000 ++#define SCSW_FCTL_CLEAR_FUNC 0x1000 ++ ++/* Activity Control */ ++#define SCSW_ACTL_RESUME_PEND 0x0800 ++#define SCSW_ACTL_START_PEND 0x0400 ++#define SCSW_ACTL_HALT_PEND 0x0200 ++#define SCSW_ACTL_CLEAR_PEND 0x0100 ++#define SCSW_ACTL_CH_ACTIVE 0x0080 ++#define SCSW_ACTL_DEV_ACTIVE 0x0040 ++#define SCSW_ACTL_SUSPENDED 0x0020 ++ ++/* Status Control */ ++#define SCSW_SCTL_ALERT 0x0010 ++#define SCSW_SCTL_INTERMED 0x0008 ++#define SCSW_SCTL_PRIMARY 0x0004 ++#define SCSW_SCTL_SECONDARY 0x0002 ++#define SCSW_SCTL_STATUS_PEND 0x0001 ++ ++/* SCSW Device Status Flags */ ++#define SCSW_DSTAT_ATTN 0x80 ++#define SCSW_DSTAT_STATMOD 0x40 ++#define SCSW_DSTAT_CUEND 0x20 ++#define SCSW_DSTAT_BUSY 0x10 ++#define SCSW_DSTAT_CHEND 0x08 ++#define SCSW_DSTAT_DEVEND 0x04 ++#define SCSW_DSTAT_UCHK 0x02 ++#define SCSW_DSTAT_UEXCP 0x01 ++ ++/* SCSW Subchannel Status Flags */ ++#define SCSW_CSTAT_PCINT 0x80 ++#define SCSW_CSTAT_BADLEN 0x40 ++#define SCSW_CSTAT_PROGCHK 0x20 ++#define SCSW_CSTAT_PROTCHK 0x10 ++#define SCSW_CSTAT_CHDCHK 0x08 ++#define SCSW_CSTAT_CHCCHK 0x04 ++#define SCSW_CSTAT_ICCHK 0x02 ++#define SCSW_CSTAT_CHAINCHK 0x01 + + /* + * subchannel information block +@@ -127,7 +164,23 @@ struct tpi_info { + __u32 reserved4:12; + } __attribute__ ((packed, aligned(4))); + +-/* channel command word (type 1) */ ++/* channel command word (format 0) */ ++typedef struct ccw0 { ++ __u8 cmd_code; ++ __u32 cda:24; ++ __u32 chainData:1; ++ __u32 chain:1; ++ __u32 sli:1; ++ __u32 skip:1; ++ __u32 pci:1; ++ __u32 ida:1; ++ __u32 suspend:1; ++ __u32 mida:1; ++ __u8 reserved; ++ __u16 count; ++} __attribute__ ((packed, aligned(8))) Ccw0; ++ ++/* channel command word (format 1) */ + typedef struct ccw1 { + __u8 cmd_code; + __u8 flags; +@@ -135,6 +188,10 @@ typedef struct ccw1 { + __u32 cda; + } __attribute__ ((packed, aligned(8))) Ccw1; + ++/* do_cio() CCW formats */ ++#define CCW_FMT0 0x00 ++#define CCW_FMT1 0x01 ++ + #define CCW_FLAG_DC 0x80 + #define CCW_FLAG_CC 0x40 + #define CCW_FLAG_SLI 0x20 +@@ -190,6 +247,11 @@ struct ciw { + __u16 count; + }; + ++#define CU_TYPE_UNKNOWN 0x0000 ++#define CU_TYPE_DASD_2107 0x2107 ++#define CU_TYPE_VIRTIO 0x3832 ++#define CU_TYPE_DASD_3990 0x3990 ++ + /* + * sense-id response buffer layout + */ +@@ -205,6 +267,64 @@ typedef struct senseid { + struct ciw ciw[62]; + } __attribute__ ((packed, aligned(4))) SenseId; + ++/* ++ * architected values for first sense byte - common_status. Bits 0-5 of this ++ * field are common to all device types. ++ */ ++#define SNS_STAT0_CMD_REJECT 0x80 ++#define SNS_STAT0_INTERVENTION_REQ 0x40 ++#define SNS_STAT0_BUS_OUT_CHECK 0x20 ++#define SNS_STAT0_EQUIPMENT_CHECK 0x10 ++#define SNS_STAT0_DATA_CHECK 0x08 ++#define SNS_STAT0_OVERRUN 0x04 ++#define SNS_STAT0_INCOMPL_DOMAIN 0x01 ++ ++/* ECKD DASD status[0] byte */ ++#define SNS_STAT1_PERM_ERR 0x80 ++#define SNS_STAT1_INV_TRACK_FORMAT 0x40 ++#define SNS_STAT1_EOC 0x20 ++#define SNS_STAT1_MESSAGE_TO_OPER 0x10 ++#define SNS_STAT1_NO_REC_FOUND 0x08 ++#define SNS_STAT1_FILE_PROTECTED 0x04 ++#define SNS_STAT1_WRITE_INHIBITED 0x02 ++#define SNS_STAT1_IMPRECISE_END 0x01 ++ ++/* ECKD DASD status[1] byte */ ++#define SNS_STAT2_REQ_INH_WRITE 0x80 ++#define SNS_STAT2_CORRECTABLE 0x40 ++#define SNS_STAT2_FIRST_LOG_ERR 0x20 ++#define SNS_STAT2_ENV_DATA_PRESENT 0x10 ++#define SNS_STAT2_IMPRECISE_END 0x04 ++ ++/* ECKD DASD 24-byte Sense fmt_msg codes */ ++#define SENSE24_FMT_PROG_SYS 0x0 ++#define SENSE24_FMT_EQUIPMENT 0x2 ++#define SENSE24_FMT_CONTROLLER 0x3 ++#define SENSE24_FMT_MISC 0xF ++ ++/* basic sense response buffer layout */ ++typedef struct SenseDataEckdDasd { ++ uint8_t common_status; ++ uint8_t status[2]; ++ uint8_t res_count; ++ uint8_t phys_drive_id; ++ uint8_t low_cyl_addr; ++ uint8_t head_high_cyl_addr; ++ uint8_t fmt_msg; ++ uint64_t fmt_dependent_info[2]; ++ uint8_t reserved; ++ uint8_t program_action_code; ++ uint16_t config_info; ++ uint8_t mcode_hicyl; ++ uint8_t cyl_head_addr[3]; ++} __attribute__ ((packed, aligned(4))) SenseDataEckdDasd; ++ ++#define ECKD_SENSE24_GET_FMT(sd) (sd->fmt_msg & 0xF0 >> 4) ++#define ECKD_SENSE24_GET_MSG(sd) (sd->fmt_msg & 0x0F) ++ ++#define unit_check(irb) ((irb)->scsw.dstat & SCSW_DSTAT_UCHK) ++#define iface_ctrl_check(irb) ((irb)->scsw.cstat & SCSW_CSTAT_ICCHK) ++ + /* interruption response block */ + typedef struct irb { + struct scsw scsw; +@@ -215,6 +335,10 @@ typedef struct irb { + + int enable_mss_facility(void); + void enable_subchannel(SubChannelId schid); ++uint16_t cu_type(SubChannelId schid); ++int basic_sense(SubChannelId schid, uint16_t cutype, void *sense_data, ++ uint16_t data_size); ++int do_cio(SubChannelId schid, uint16_t cutype, uint32_t ccw_addr, int fmt); + + /* + * Some S390 specific IO instructions as inline +diff --git a/pc-bios/s390-ccw/s390-ccw.h b/pc-bios/s390-ccw/s390-ccw.h +index b39ee5d..11bce7d 100644 +--- a/pc-bios/s390-ccw/s390-ccw.h ++++ b/pc-bios/s390-ccw/s390-ccw.h +@@ -52,6 +52,7 @@ typedef unsigned long long __u64; + /* start.s */ + void disabled_wait(void); + void consume_sclp_int(void); ++void consume_io_int(void); + + /* main.c */ + void panic(const char *string); +diff --git a/pc-bios/s390-ccw/start.S b/pc-bios/s390-ccw/start.S +index eb8d024..fe2a4c3 100644 +--- a/pc-bios/s390-ccw/start.S ++++ b/pc-bios/s390-ccw/start.S +@@ -71,6 +71,26 @@ consume_sclp_int: + larl %r1, enabled_wait_psw + lpswe 0(%r1) + ++/* ++ * void consume_io_int(void) ++ * ++ * eats one I/O interrupt ++ */ ++ .globl consume_io_int ++consume_io_int: ++ /* enable I/O interrupts in cr6 */ ++ stctg %c6,%c6,0(%r15) ++ oi 4(%r15), 0xff ++ lctlg %c6,%c6,0(%r15) ++ /* prepare i/o call handler */ ++ larl %r1, io_new_code ++ stg %r1, 0x1f8 ++ larl %r1, io_new_mask ++ mvc 0x1f0(8),0(%r1) ++ /* load enabled wait PSW */ ++ larl %r1, enabled_wait_psw ++ lpswe 0(%r1) ++ + external_new_code: + /* disable service interrupts in cr0 */ + stctg 0,0,0(15) +@@ -78,6 +98,13 @@ external_new_code: + lctlg 0,0,0(15) + br 14 + ++io_new_code: ++ /* disable I/O interrupts in cr6 */ ++ stctg %c6,%c6,0(%r15) ++ ni 4(%r15), 0x00 ++ lctlg %c6,%c6,0(%r15) ++ br %r14 ++ + .align 8 + disabled_wait_psw: + .quad 0x0002000180000000,0x0000000000000000 +@@ -85,3 +112,5 @@ enabled_wait_psw: + .quad 0x0302000180000000,0x0000000000000000 + external_new_mask: + .quad 0x0000000180000000 ++io_new_mask: ++ .quad 0x0000000180000000 +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390-bios-Use-control-unit-type-to-determine-boot-me.patch b/SOURCES/kvm-s390-bios-Use-control-unit-type-to-determine-boot-me.patch new file mode 100644 index 0000000..d9daa9c --- /dev/null +++ b/SOURCES/kvm-s390-bios-Use-control-unit-type-to-determine-boot-me.patch @@ -0,0 +1,106 @@ +From 4b0f36b50e79fe6d345c85f60f12508c17c44f1d Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Mon, 14 Oct 2019 10:06:42 +0100 +Subject: [PATCH 17/21] s390-bios: Use control unit type to determine boot + method + +RH-Author: Thomas Huth +Message-id: <20191014100645.22862-15-thuth@redhat.com> +Patchwork-id: 91785 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH v2 14/17] s390-bios: Use control unit type to determine boot method +Bugzilla: 1664376 +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand +RH-Acked-by: Jens Freimann + +From: "Jason J. Herne" + +The boot method is different depending on which device type we are +booting from. Let's examine the control unit type to determine if we're +a virtio device. We'll eventually add a case to check for a real dasd device +here as well. + +Since we have to call enable_subchannel() in main now, might as well +remove that call from virtio.c : run_ccw(). This requires adding some +additional enable_subchannel calls to not break calls to +virtio_is_supported(). + +Signed-off-by: Jason J. Herne +Reviewed-by: Cornelia Huck +Reviewed-by: Thomas Huth +Message-Id: <1554388475-18329-14-git-send-email-jjherne@linux.ibm.com> +Signed-off-by: Thomas Huth +(cherry picked from commit 3668cb7ce864ee9351d5d20a1ec6b427cd0b3be4) +Signed-off-by: Danilo C. L. de Paula +--- + pc-bios/s390-ccw/main.c | 16 ++++++++++++++-- + pc-bios/s390-ccw/netmain.c | 1 + + pc-bios/s390-ccw/virtio.c | 1 - + 3 files changed, 15 insertions(+), 3 deletions(-) + +diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c +index d3a161c..57a1013 100644 +--- a/pc-bios/s390-ccw/main.c ++++ b/pc-bios/s390-ccw/main.c +@@ -76,6 +76,7 @@ static bool find_subch(int dev_no) + /* Skip net devices since no IPLB is created and therefore no + * network bootloader has been loaded + */ ++ enable_subchannel(blk_schid); + if (virtio_is_supported(blk_schid) && + virtio_get_device_type() == VIRTIO_ID_NET && dev_no < 0) { + continue; +@@ -198,13 +199,24 @@ static void virtio_setup(void) + + int main(void) + { ++ uint16_t cutype; ++ + sclp_setup(); + css_setup(); + boot_setup(); + find_boot_device(); ++ enable_subchannel(blk_schid); + +- virtio_setup(); +- zipl_load(); /* no return */ ++ cutype = cu_type(blk_schid); ++ switch (cutype) { ++ case CU_TYPE_VIRTIO: ++ virtio_setup(); ++ zipl_load(); /* no return */ ++ break; ++ default: ++ print_int("Attempting to boot from unexpected device type", cutype); ++ panic(""); ++ } + + panic("Failed to load OS from hard disk\n"); + return 0; /* make compiler happy */ +diff --git a/pc-bios/s390-ccw/netmain.c b/pc-bios/s390-ccw/netmain.c +index 4e1b8cf..69cf59d 100644 +--- a/pc-bios/s390-ccw/netmain.c ++++ b/pc-bios/s390-ccw/netmain.c +@@ -304,6 +304,7 @@ static bool find_net_dev(Schib *schib, int dev_no) + if (!schib->pmcw.dnv) { + continue; + } ++ enable_subchannel(net_schid); + if (!virtio_is_supported(net_schid)) { + continue; + } +diff --git a/pc-bios/s390-ccw/virtio.c b/pc-bios/s390-ccw/virtio.c +index 35278eae..fb40ca9 100644 +--- a/pc-bios/s390-ccw/virtio.c ++++ b/pc-bios/s390-ccw/virtio.c +@@ -102,7 +102,6 @@ static int run_ccw(VDev *vdev, int cmd, void *ptr, int len, bool sli) + ccw.flags |= CCW_FLAG_SLI; + } + +- enable_subchannel(vdev->schid); + return do_cio(vdev->schid, vdev->senseid.cu_type, ptr2u32(&ccw), CCW_FMT1); + } + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390-bios-Use-control-unit-type-to-find-bootable-dev.patch b/SOURCES/kvm-s390-bios-Use-control-unit-type-to-find-bootable-dev.patch new file mode 100644 index 0000000..296f273 --- /dev/null +++ b/SOURCES/kvm-s390-bios-Use-control-unit-type-to-find-bootable-dev.patch @@ -0,0 +1,127 @@ +From cdc1df196d9e1cf5e6f6fe2900637b78d606ee85 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Mon, 14 Oct 2019 10:06:45 +0100 +Subject: [PATCH 20/21] s390-bios: Use control unit type to find bootable + devices + +RH-Author: Thomas Huth +Message-id: <20191014100645.22862-18-thuth@redhat.com> +Patchwork-id: 91790 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH v2 17/17] s390-bios: Use control unit type to find bootable devices +Bugzilla: 1664376 +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand +RH-Acked-by: Jens Freimann + +From: "Jason J. Herne" + +When the user does not specify which device to boot from then we end +up guessing. Instead of simply grabbing the first available device let's +be a little bit smarter and only choose devices that might be bootable +like disk, and not console devices. + +Signed-off-by: Jason J. Herne +Message-Id: <1554388475-18329-17-git-send-email-jjherne@linux.ibm.com> +[thuth: Added fix for virtio_is_supported() not being called anymore] +Signed-off-by: Thomas Huth +(cherry picked from commit 2880469c95e42f8a5b0acbe8c4808255cc6c9e5b) + +Signed-off-by: Danilo C. L. de Paula +--- + pc-bios/s390-ccw/main.c | 45 +++++++++++++++++++++++++++++++++++---------- + 1 file changed, 35 insertions(+), 10 deletions(-) + +diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c +index 3c449ad..a69c733 100644 +--- a/pc-bios/s390-ccw/main.c ++++ b/pc-bios/s390-ccw/main.c +@@ -21,6 +21,7 @@ static char loadparm_str[LOADPARM_LEN + 1] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + QemuIplParameters qipl; + IplParameterBlock iplb __attribute__((__aligned__(PAGE_SIZE))); + static bool have_iplb; ++static uint16_t cutype; + LowCore const *lowcore; /* Yes, this *is* a pointer to address 0 */ + + #define LOADPARM_PROMPT "PROMPT " +@@ -58,11 +59,15 @@ unsigned int get_loadparm_index(void) + * subchannel information block (schib) with the connected subchannel's info. + * NOTE: The global variable blk_schid is updated to contain the subchannel + * information. ++ * ++ * If the caller gives dev_no=-1 then the user did not specify a boot device. ++ * In this case we'll just use the first potentially bootable device we find. + */ + static bool find_subch(int dev_no) + { + Schib schib; + int i, r; ++ bool is_virtio; + + for (i = 0; i < 0x10000; i++) { + blk_schid.sch_no = i; +@@ -74,16 +79,39 @@ static bool find_subch(int dev_no) + continue; + } + +- /* Skip net devices since no IPLB is created and therefore no +- * network bootloader has been loaded +- */ + enable_subchannel(blk_schid); +- if (virtio_is_supported(blk_schid) && +- virtio_get_device_type() == VIRTIO_ID_NET && dev_no < 0) { +- continue; ++ cutype = cu_type(blk_schid); ++ ++ /* ++ * Note: we always have to run virtio_is_supported() here to make ++ * sure that the vdev.senseid data gets pre-initialized correctly ++ */ ++ is_virtio = virtio_is_supported(blk_schid); ++ ++ /* No specific devno given, just return 1st possibly bootable device */ ++ if (dev_no < 0) { ++ switch (cutype) { ++ case CU_TYPE_VIRTIO: ++ if (is_virtio) { ++ /* ++ * Skip net devices since no IPLB is created and therefore ++ * no network bootloader has been loaded ++ */ ++ if (virtio_get_device_type() != VIRTIO_ID_NET) { ++ return true; ++ } ++ } ++ continue; ++ case CU_TYPE_DASD_3990: ++ case CU_TYPE_DASD_2107: ++ return true; ++ default: ++ continue; ++ } + } + +- if ((dev_no < 0) || (schib.pmcw.dev == dev_no)) { ++ /* Caller asked for a specific devno */ ++ if (schib.pmcw.dev == dev_no) { + return true; + } + } +@@ -200,15 +228,12 @@ static void virtio_setup(void) + + int main(void) + { +- uint16_t cutype; +- + sclp_setup(); + css_setup(); + boot_setup(); + find_boot_device(); + enable_subchannel(blk_schid); + +- cutype = cu_type(blk_schid); + switch (cutype) { + case CU_TYPE_DASD_3990: + case CU_TYPE_DASD_2107: +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390-bios-cio-error-handling.patch b/SOURCES/kvm-s390-bios-cio-error-handling.patch new file mode 100644 index 0000000..f7bf350 --- /dev/null +++ b/SOURCES/kvm-s390-bios-cio-error-handling.patch @@ -0,0 +1,341 @@ +From f7d509d82aeb0af595c6dcfade7904b248ed180b Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Mon, 14 Oct 2019 10:06:38 +0100 +Subject: [PATCH 13/21] s390-bios: cio error handling + +RH-Author: Thomas Huth +Message-id: <20191014100645.22862-11-thuth@redhat.com> +Patchwork-id: 91787 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH v2 10/17] s390-bios: cio error handling +Bugzilla: 1664376 +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand +RH-Acked-by: Jens Freimann + +From: "Jason J. Herne" + +Add verbose error output for when unexpected i/o errors happen. This eases the +burden of debugging and reporting i/o errors. No error information is printed +in the success case, here is an example of what is output on error: + +cio device error + ssid : 0x0000000000000000 + cssid : 0x0000000000000000 + sch_no: 0x0000000000000000 + +Interrupt Response Block Data: + Function Ctrl : [Start] + Activity Ctrl : [Start-Pending] + Status Ctrl : [Alert] [Primary] [Secondary] [Status-Pending] + Device Status : [Unit-Check] + Channel Status : + cpa=: 0x000000007f8d6038 + prev_ccw=: 0x0000000000000000 + this_ccw=: 0x0000000000000000 +Eckd Dasd Sense Data (fmt 32-bytes): + Sense Condition Flags : + Residual Count =: 0x0000000000000000 + Phys Drive ID =: 0x000000000000009e + low cyl address =: 0x0000000000000000 + head addr & hi cyl =: 0x0000000000000000 + format/message =: 0x0000000000000008 + fmt-dependent[0-7] =: 0x0000000000000004 + fmt-dependent[8-15]=: 0xe561282305082fff + prog action code =: 0x0000000000000016 + Configuration info =: 0x00000000000040e0 + mcode / hi-cyl =: 0x0000000000000000 + cyl & head addr [0]=: 0x0000000000000000 + cyl & head addr [1]=: 0x0000000000000000 + cyl & head addr [2]=: 0x0000000000000000 + +The Sense Data section is currently only printed for ECKD DASD. + +Signed-off-by: Jason J. Herne +Reviewed-by: Cornelia Huck +Message-Id: <1554388475-18329-10-git-send-email-jjherne@linux.ibm.com> +Signed-off-by: Thomas Huth +(cherry picked from commit 86c58705bb186cfa73a03851047da2c2c37b9418) +Signed-off-by: Danilo C. L. de Paula +--- + pc-bios/s390-ccw/cio.c | 235 ++++++++++++++++++++++++++++++++++++++++++++++++ + pc-bios/s390-ccw/libc.h | 11 +++ + 2 files changed, 246 insertions(+) + +diff --git a/pc-bios/s390-ccw/cio.c b/pc-bios/s390-ccw/cio.c +index c43e50b..339ec5f 100644 +--- a/pc-bios/s390-ccw/cio.c ++++ b/pc-bios/s390-ccw/cio.c +@@ -85,6 +85,228 @@ static bool irb_error(Irb *irb) + return irb->scsw.dstat != (SCSW_DSTAT_DEVEND | SCSW_DSTAT_CHEND); + } + ++static void print_eckd_dasd_sense_data(SenseDataEckdDasd *sd) ++{ ++ char msgline[512]; ++ ++ if (sd->config_info & 0x8000) { ++ sclp_print("Eckd Dasd Sense Data (fmt 24-bytes):\n"); ++ } else { ++ sclp_print("Eckd Dasd Sense Data (fmt 32-bytes):\n"); ++ } ++ ++ strcat(msgline, " Sense Condition Flags :"); ++ if (sd->common_status & SNS_STAT0_CMD_REJECT) { ++ strcat(msgline, " [Cmd-Reject]"); ++ } ++ if (sd->common_status & SNS_STAT0_INTERVENTION_REQ) { ++ strcat(msgline, " [Intervention-Required]"); ++ } ++ if (sd->common_status & SNS_STAT0_BUS_OUT_CHECK) { ++ strcat(msgline, " [Bus-Out-Parity-Check]"); ++ } ++ if (sd->common_status & SNS_STAT0_EQUIPMENT_CHECK) { ++ strcat(msgline, " [Equipment-Check]"); ++ } ++ if (sd->common_status & SNS_STAT0_DATA_CHECK) { ++ strcat(msgline, " [Data-Check]"); ++ } ++ if (sd->common_status & SNS_STAT0_OVERRUN) { ++ strcat(msgline, " [Overrun]"); ++ } ++ if (sd->common_status & SNS_STAT0_INCOMPL_DOMAIN) { ++ strcat(msgline, " [Incomplete-Domain]"); ++ } ++ ++ if (sd->status[0] & SNS_STAT1_PERM_ERR) { ++ strcat(msgline, " [Permanent-Error]"); ++ } ++ if (sd->status[0] & SNS_STAT1_INV_TRACK_FORMAT) { ++ strcat(msgline, " [Invalid-Track-Fmt]"); ++ } ++ if (sd->status[0] & SNS_STAT1_EOC) { ++ strcat(msgline, " [End-of-Cyl]"); ++ } ++ if (sd->status[0] & SNS_STAT1_MESSAGE_TO_OPER) { ++ strcat(msgline, " [Operator-Msg]"); ++ } ++ if (sd->status[0] & SNS_STAT1_NO_REC_FOUND) { ++ strcat(msgline, " [No-Record-Found]"); ++ } ++ if (sd->status[0] & SNS_STAT1_FILE_PROTECTED) { ++ strcat(msgline, " [File-Protected]"); ++ } ++ if (sd->status[0] & SNS_STAT1_WRITE_INHIBITED) { ++ strcat(msgline, " [Write-Inhibited]"); ++ } ++ if (sd->status[0] & SNS_STAT1_IMPRECISE_END) { ++ strcat(msgline, " [Imprecise-Ending]"); ++ } ++ ++ if (sd->status[1] & SNS_STAT2_REQ_INH_WRITE) { ++ strcat(msgline, " [Req-Inhibit-Write]"); ++ } ++ if (sd->status[1] & SNS_STAT2_CORRECTABLE) { ++ strcat(msgline, " [Correctable-Data-Check]"); ++ } ++ if (sd->status[1] & SNS_STAT2_FIRST_LOG_ERR) { ++ strcat(msgline, " [First-Error-Log]"); ++ } ++ if (sd->status[1] & SNS_STAT2_ENV_DATA_PRESENT) { ++ strcat(msgline, " [Env-Data-Present]"); ++ } ++ if (sd->status[1] & SNS_STAT2_IMPRECISE_END) { ++ strcat(msgline, " [Imprecise-End]"); ++ } ++ strcat(msgline, "\n"); ++ sclp_print(msgline); ++ ++ print_int(" Residual Count =", sd->res_count); ++ print_int(" Phys Drive ID =", sd->phys_drive_id); ++ print_int(" low cyl address =", sd->low_cyl_addr); ++ print_int(" head addr & hi cyl =", sd->head_high_cyl_addr); ++ print_int(" format/message =", sd->fmt_msg); ++ print_int(" fmt-dependent[0-7] =", sd->fmt_dependent_info[0]); ++ print_int(" fmt-dependent[8-15]=", sd->fmt_dependent_info[1]); ++ print_int(" prog action code =", sd->program_action_code); ++ print_int(" Configuration info =", sd->config_info); ++ print_int(" mcode / hi-cyl =", sd->mcode_hicyl); ++ print_int(" cyl & head addr [0]=", sd->cyl_head_addr[0]); ++ print_int(" cyl & head addr [1]=", sd->cyl_head_addr[1]); ++ print_int(" cyl & head addr [2]=", sd->cyl_head_addr[2]); ++} ++ ++static void print_irb_err(Irb *irb) ++{ ++ uint64_t this_ccw = *(uint64_t *)u32toptr(irb->scsw.cpa); ++ uint64_t prev_ccw = *(uint64_t *)u32toptr(irb->scsw.cpa - 8); ++ char msgline[256]; ++ ++ sclp_print("Interrupt Response Block Data:\n"); ++ ++ strcat(msgline, " Function Ctrl :"); ++ if (irb->scsw.ctrl & SCSW_FCTL_START_FUNC) { ++ strcat(msgline, " [Start]"); ++ } ++ if (irb->scsw.ctrl & SCSW_FCTL_HALT_FUNC) { ++ strcat(msgline, " [Halt]"); ++ } ++ if (irb->scsw.ctrl & SCSW_FCTL_CLEAR_FUNC) { ++ strcat(msgline, " [Clear]"); ++ } ++ strcat(msgline, "\n"); ++ sclp_print(msgline); ++ ++ msgline[0] = '\0'; ++ strcat(msgline, " Activity Ctrl :"); ++ if (irb->scsw.ctrl & SCSW_ACTL_RESUME_PEND) { ++ strcat(msgline, " [Resume-Pending]"); ++ } ++ if (irb->scsw.ctrl & SCSW_ACTL_START_PEND) { ++ strcat(msgline, " [Start-Pending]"); ++ } ++ if (irb->scsw.ctrl & SCSW_ACTL_HALT_PEND) { ++ strcat(msgline, " [Halt-Pending]"); ++ } ++ if (irb->scsw.ctrl & SCSW_ACTL_CLEAR_PEND) { ++ strcat(msgline, " [Clear-Pending]"); ++ } ++ if (irb->scsw.ctrl & SCSW_ACTL_CH_ACTIVE) { ++ strcat(msgline, " [Channel-Active]"); ++ } ++ if (irb->scsw.ctrl & SCSW_ACTL_DEV_ACTIVE) { ++ strcat(msgline, " [Device-Active]"); ++ } ++ if (irb->scsw.ctrl & SCSW_ACTL_SUSPENDED) { ++ strcat(msgline, " [Suspended]"); ++ } ++ strcat(msgline, "\n"); ++ sclp_print(msgline); ++ ++ msgline[0] = '\0'; ++ strcat(msgline, " Status Ctrl :"); ++ if (irb->scsw.ctrl & SCSW_SCTL_ALERT) { ++ strcat(msgline, " [Alert]"); ++ } ++ if (irb->scsw.ctrl & SCSW_SCTL_INTERMED) { ++ strcat(msgline, " [Intermediate]"); ++ } ++ if (irb->scsw.ctrl & SCSW_SCTL_PRIMARY) { ++ strcat(msgline, " [Primary]"); ++ } ++ if (irb->scsw.ctrl & SCSW_SCTL_SECONDARY) { ++ strcat(msgline, " [Secondary]"); ++ } ++ if (irb->scsw.ctrl & SCSW_SCTL_STATUS_PEND) { ++ strcat(msgline, " [Status-Pending]"); ++ } ++ ++ strcat(msgline, "\n"); ++ sclp_print(msgline); ++ ++ msgline[0] = '\0'; ++ strcat(msgline, " Device Status :"); ++ if (irb->scsw.dstat & SCSW_DSTAT_ATTN) { ++ strcat(msgline, " [Attention]"); ++ } ++ if (irb->scsw.dstat & SCSW_DSTAT_STATMOD) { ++ strcat(msgline, " [Status-Modifier]"); ++ } ++ if (irb->scsw.dstat & SCSW_DSTAT_CUEND) { ++ strcat(msgline, " [Ctrl-Unit-End]"); ++ } ++ if (irb->scsw.dstat & SCSW_DSTAT_BUSY) { ++ strcat(msgline, " [Busy]"); ++ } ++ if (irb->scsw.dstat & SCSW_DSTAT_CHEND) { ++ strcat(msgline, " [Channel-End]"); ++ } ++ if (irb->scsw.dstat & SCSW_DSTAT_DEVEND) { ++ strcat(msgline, " [Device-End]"); ++ } ++ if (irb->scsw.dstat & SCSW_DSTAT_UCHK) { ++ strcat(msgline, " [Unit-Check]"); ++ } ++ if (irb->scsw.dstat & SCSW_DSTAT_UEXCP) { ++ strcat(msgline, " [Unit-Exception]"); ++ } ++ strcat(msgline, "\n"); ++ sclp_print(msgline); ++ ++ msgline[0] = '\0'; ++ strcat(msgline, " Channel Status :"); ++ if (irb->scsw.cstat & SCSW_CSTAT_PCINT) { ++ strcat(msgline, " [Program-Ctrl-Interruption]"); ++ } ++ if (irb->scsw.cstat & SCSW_CSTAT_BADLEN) { ++ strcat(msgline, " [Incorrect-Length]"); ++ } ++ if (irb->scsw.cstat & SCSW_CSTAT_PROGCHK) { ++ strcat(msgline, " [Program-Check]"); ++ } ++ if (irb->scsw.cstat & SCSW_CSTAT_PROTCHK) { ++ strcat(msgline, " [Protection-Check]"); ++ } ++ if (irb->scsw.cstat & SCSW_CSTAT_CHDCHK) { ++ strcat(msgline, " [Channel-Data-Check]"); ++ } ++ if (irb->scsw.cstat & SCSW_CSTAT_CHCCHK) { ++ strcat(msgline, " [Channel-Ctrl-Check]"); ++ } ++ if (irb->scsw.cstat & SCSW_CSTAT_ICCHK) { ++ strcat(msgline, " [Interface-Ctrl-Check]"); ++ } ++ if (irb->scsw.cstat & SCSW_CSTAT_CHAINCHK) { ++ strcat(msgline, " [Chaining-Check]"); ++ } ++ strcat(msgline, "\n"); ++ sclp_print(msgline); ++ ++ print_int(" cpa=", irb->scsw.cpa); ++ print_int(" prev_ccw=", prev_ccw); ++ print_int(" this_ccw=", this_ccw); ++} ++ + /* + * Handles executing ssch, tsch and returns the irb obtained from tsch. + * Returns 0 on success, -1 if unexpected status pending and we need to retry, +@@ -180,6 +402,19 @@ int do_cio(SubChannelId schid, uint16_t cutype, uint32_t ccw_addr, int fmt) + continue; + } + ++ sclp_print("cio device error\n"); ++ print_int(" ssid ", schid.ssid); ++ print_int(" cssid ", schid.cssid); ++ print_int(" sch_no", schid.sch_no); ++ print_int(" ctrl-unit type", cutype); ++ sclp_print("\n"); ++ print_irb_err(&irb); ++ if (cutype == CU_TYPE_DASD_3990 || cutype == CU_TYPE_DASD_2107 || ++ cutype == CU_TYPE_UNKNOWN) { ++ if (!basic_sense(schid, cutype, &sd, sizeof(sd))) { ++ print_eckd_dasd_sense_data(&sd); ++ } ++ } + rc = -1; + break; + } +diff --git a/pc-bios/s390-ccw/libc.h b/pc-bios/s390-ccw/libc.h +index 818517f..bcdc457 100644 +--- a/pc-bios/s390-ccw/libc.h ++++ b/pc-bios/s390-ccw/libc.h +@@ -67,6 +67,17 @@ static inline size_t strlen(const char *str) + return i; + } + ++static inline char *strcat(char *dest, const char *src) ++{ ++ int i; ++ char *dest_end = dest + strlen(dest); ++ ++ for (i = 0; i <= strlen(src); i++) { ++ dest_end[i] = src[i]; ++ } ++ return dest; ++} ++ + static inline int isdigit(int c) + { + return (c >= '0') && (c <= '9'); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390-bios-decouple-cio-setup-from-virtio.patch b/SOURCES/kvm-s390-bios-decouple-cio-setup-from-virtio.patch new file mode 100644 index 0000000..f51a3a0 --- /dev/null +++ b/SOURCES/kvm-s390-bios-decouple-cio-setup-from-virtio.patch @@ -0,0 +1,82 @@ +From 19b96c7f412b9b8d893ec9ebd2603565d6afa178 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Mon, 14 Oct 2019 10:06:31 +0100 +Subject: [PATCH 06/21] s390-bios: decouple cio setup from virtio + +RH-Author: Thomas Huth +Message-id: <20191014100645.22862-4-thuth@redhat.com> +Patchwork-id: 91776 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH v2 03/17] s390-bios: decouple cio setup from virtio +Bugzilla: 1664376 +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand +RH-Acked-by: Jens Freimann + +From: "Jason J. Herne" + +Move channel i/o setup code out to a separate function. This decouples cio +setup from the virtio code path and allows us to make use of it for booting +dasd devices. + +Signed-off-by: Jason J. Herne +Acked-by: Halil Pasic +Reviewed-by: Collin Walling +Reviewed-by: Farhan Ali +Reviewed-by: Thomas Huth +Reviewed-by: Cornelia Huck +Message-Id: <1554388475-18329-3-git-send-email-jjherne@linux.ibm.com> +Signed-off-by: Thomas Huth +(cherry picked from commit 87f910c142d5589ef937ac216f92c6dcddae955e) +Signed-off-by: Danilo C. L. de Paula +--- + pc-bios/s390-ccw/main.c | 20 +++++++++++++------- + 1 file changed, 13 insertions(+), 7 deletions(-) + +diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c +index 544851d..e82fe2c 100644 +--- a/pc-bios/s390-ccw/main.c ++++ b/pc-bios/s390-ccw/main.c +@@ -99,6 +99,18 @@ static void menu_setup(void) + } + } + ++/* ++ * Initialize the channel I/O subsystem so we can talk to our ipl/boot device. ++ */ ++static void css_setup(void) ++{ ++ /* ++ * Unconditionally enable mss support. In every sane configuration this ++ * will succeed; and even if it doesn't, stsch_err() can handle it. ++ */ ++ enable_mss_facility(); ++} ++ + static void virtio_setup(void) + { + Schib schib; +@@ -109,13 +121,6 @@ static void virtio_setup(void) + VDev *vdev = virtio_get_device(); + QemuIplParameters *early_qipl = (QemuIplParameters *)QIPL_ADDRESS; + +- /* +- * We unconditionally enable mss support. In every sane configuration, +- * this will succeed; and even if it doesn't, stsch_err() can deal +- * with the consequences. +- */ +- enable_mss_facility(); +- + sclp_get_loadparm_ascii(loadparm_str); + memcpy(ldp + 10, loadparm_str, LOADPARM_LEN); + sclp_print(ldp); +@@ -168,6 +173,7 @@ static void virtio_setup(void) + int main(void) + { + sclp_setup(); ++ css_setup(); + virtio_setup(); + + zipl_load(); /* no return */ +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390-bios-decouple-common-boot-logic-from-virtio.patch b/SOURCES/kvm-s390-bios-decouple-common-boot-logic-from-virtio.patch new file mode 100644 index 0000000..cf40956 --- /dev/null +++ b/SOURCES/kvm-s390-bios-decouple-common-boot-logic-from-virtio.patch @@ -0,0 +1,110 @@ +From 59ef4d9a3358627fbd7001028903cd89e061a216 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Mon, 14 Oct 2019 10:06:32 +0100 +Subject: [PATCH 07/21] s390-bios: decouple common boot logic from virtio + +RH-Author: Thomas Huth +Message-id: <20191014100645.22862-5-thuth@redhat.com> +Patchwork-id: 91778 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH v2 04/17] s390-bios: decouple common boot logic from virtio +Bugzilla: 1664376 +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand +RH-Acked-by: Jens Freimann + +From: "Jason J. Herne" + +Create a boot_setup function to handle getting boot information from +the machine/hypervisor. This decouples common boot logic from the +virtio code path and allows us to make use of it for the real dasd boot +scenario. + +Signed-off-by: Jason J. Herne +Acked-by: Halil Pasic +Reviewed-by: Collin Walling +Reviewed-by: Farhan Ali +Reviewed-by: Cornelia Huck +Message-Id: <1554388475-18329-4-git-send-email-jjherne@linux.ibm.com> +Signed-off-by: Thomas Huth +(cherry picked from commit a5f6e0975b1f1b79f446c8323e62fd0534408da6) +Signed-off-by: Danilo C. L. de Paula +--- + pc-bios/s390-ccw/main.c | 28 ++++++++++++++++++++-------- + 1 file changed, 20 insertions(+), 8 deletions(-) + +diff --git a/pc-bios/s390-ccw/main.c b/pc-bios/s390-ccw/main.c +index e82fe2c..67df421 100644 +--- a/pc-bios/s390-ccw/main.c ++++ b/pc-bios/s390-ccw/main.c +@@ -14,16 +14,17 @@ + + char stack[PAGE_SIZE * 8] __attribute__((__aligned__(PAGE_SIZE))); + static SubChannelId blk_schid = { .one = 1 }; +-IplParameterBlock iplb __attribute__((__aligned__(PAGE_SIZE))); + static char loadparm_str[LOADPARM_LEN + 1] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + QemuIplParameters qipl; ++IplParameterBlock iplb __attribute__((__aligned__(PAGE_SIZE))); ++static bool have_iplb; + + #define LOADPARM_PROMPT "PROMPT " + #define LOADPARM_EMPTY " " + #define BOOT_MENU_FLAG_MASK (QIPL_FLAG_BM_OPTS_CMD | QIPL_FLAG_BM_OPTS_ZIPL) + + /* +- * Priniciples of Operations (SA22-7832-09) chapter 17 requires that ++ * Principles of Operations (SA22-7832-09) chapter 17 requires that + * a subsystem-identification is at 184-187 and bytes 188-191 are zero + * after list-directed-IPL and ccw-IPL. + */ +@@ -111,23 +112,33 @@ static void css_setup(void) + enable_mss_facility(); + } + ++/* ++ * Collect various pieces of information from the hypervisor/hardware that ++ * we'll use to determine exactly how we'll boot. ++ */ ++static void boot_setup(void) ++{ ++ char lpmsg[] = "LOADPARM=[________]\n"; ++ ++ sclp_get_loadparm_ascii(loadparm_str); ++ memcpy(lpmsg + 10, loadparm_str, 8); ++ sclp_print(lpmsg); ++ ++ have_iplb = store_iplb(&iplb); ++} ++ + static void virtio_setup(void) + { + Schib schib; + int ssid; + bool found = false; + uint16_t dev_no; +- char ldp[] = "LOADPARM=[________]\n"; + VDev *vdev = virtio_get_device(); + QemuIplParameters *early_qipl = (QemuIplParameters *)QIPL_ADDRESS; + +- sclp_get_loadparm_ascii(loadparm_str); +- memcpy(ldp + 10, loadparm_str, LOADPARM_LEN); +- sclp_print(ldp); +- + memcpy(&qipl, early_qipl, sizeof(QemuIplParameters)); + +- if (store_iplb(&iplb)) { ++ if (have_iplb) { + switch (iplb.pbt) { + case S390_IPL_TYPE_CCW: + dev_no = iplb.ccw.devno; +@@ -174,6 +185,7 @@ int main(void) + { + sclp_setup(); + css_setup(); ++ boot_setup(); + virtio_setup(); + + zipl_load(); /* no return */ +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390-bios-ptr2u32-and-u32toptr.patch b/SOURCES/kvm-s390-bios-ptr2u32-and-u32toptr.patch new file mode 100644 index 0000000..b34c971 --- /dev/null +++ b/SOURCES/kvm-s390-bios-ptr2u32-and-u32toptr.patch @@ -0,0 +1,72 @@ +From d032dae613dc006c91ad8581f203af1bd4bdbf9c Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Mon, 14 Oct 2019 10:06:36 +0100 +Subject: [PATCH 11/21] s390-bios: ptr2u32 and u32toptr + +RH-Author: Thomas Huth +Message-id: <20191014100645.22862-9-thuth@redhat.com> +Patchwork-id: 91788 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH v2 08/17] s390-bios: ptr2u32 and u32toptr +Bugzilla: 1664376 +RH-Acked-by: Cornelia Huck +RH-Acked-by: David Hildenbrand +RH-Acked-by: Jens Freimann + +From: "Jason J. Herne" + +Introduce inline functions to convert between pointers and unsigned 32-bit +ints. These are used to hide the ugliness required to avoid compiler +warnings. + +Signed-off-by: Jason J. Herne +Acked-by: Cornelia Huck +Reviewed-by: Thomas Huth +Message-Id: <1554388475-18329-8-git-send-email-jjherne@linux.ibm.com> +Signed-off-by: Thomas Huth +(cherry picked from commit 1fb3e5cde8dcd9b5917aea9a0b2918e16be8be1e) +Signed-off-by: Danilo C. L. de Paula +--- + pc-bios/s390-ccw/helper.h | 31 +++++++++++++++++++++++++++++++ + 1 file changed, 31 insertions(+) + create mode 100644 pc-bios/s390-ccw/helper.h + +diff --git a/pc-bios/s390-ccw/helper.h b/pc-bios/s390-ccw/helper.h +new file mode 100644 +index 0000000..78d5bc7 +--- /dev/null ++++ b/pc-bios/s390-ccw/helper.h +@@ -0,0 +1,31 @@ ++/* ++ * Helper Functions ++ * ++ * Copyright (c) 2019 IBM Corp. ++ * ++ * Author(s): Jason J. Herne ++ * ++ * This work is licensed under the terms of the GNU GPL, version 2 or (at ++ * your option) any later version. See the COPYING file in the top-level ++ * directory. ++ */ ++ ++#ifndef S390_CCW_HELPER_H ++#define S390_CCW_HELPER_H ++ ++#include "s390-ccw.h" ++ ++/* Avoids compiler warnings when casting a pointer to a u32 */ ++static inline uint32_t ptr2u32(void *ptr) ++{ ++ IPL_assert((uint64_t)ptr <= 0xffffffff, "ptr2u32: ptr too large"); ++ return (uint32_t)(uint64_t)ptr; ++} ++ ++/* Avoids compiler warnings when casting a u32 to a pointer */ ++static inline void *u32toptr(uint32_t n) ++{ ++ return (void *)(uint64_t)n; ++} ++ ++#endif +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390-cpumodel-fix-description-for-the-new-vector-fac.patch b/SOURCES/kvm-s390-cpumodel-fix-description-for-the-new-vector-fac.patch new file mode 100644 index 0000000..9ad4f46 --- /dev/null +++ b/SOURCES/kvm-s390-cpumodel-fix-description-for-the-new-vector-fac.patch @@ -0,0 +1,48 @@ +From bd0e218dc19724fb4c61d259601d116113f114a5 Mon Sep 17 00:00:00 2001 +From: David Hildenbrand +Date: Tue, 16 Jul 2019 20:44:19 +0100 +Subject: [PATCH 17/39] s390: cpumodel: fix description for the new vector + facility + +RH-Author: David Hildenbrand +Message-id: <20190716204422.9350-2-david@redhat.com> +Patchwork-id: 89547 +O-Subject: [RHEL8.1 qemu-kvm PATCH 1/4] s390: cpumodel: fix description for the new vector facility +Bugzilla: 1729975 +RH-Acked-by: Thomas Huth +RH-Acked-by: Cornelia Huck +RH-Acked-by: Jens Freimann + +Conflicts: upstream moved the definitions + +The new facility is called "Vector-Packed-Decimal-Enhancement Facility" +and not "Vector BCD enhancements facility 1". As the shortname might +have already found its way into some backports, let's keep vxbeh. + +Fixes: 54d65de0b525 ("s390x/cpumodel: vector enhancements") +Signed-off-by: Christian Borntraeger +Message-Id: <20190708150931.93448-1-borntraeger@de.ibm.com> +Signed-off-by: Cornelia Huck +(cherry picked from commit d05be57ddc2e1722f527aa4c20d84dfd15c840ec) +Signed-off-by: David Hildenbrand +Signed-off-by: Danilo C. L. de Paula +--- + target/s390x/cpu_features.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/target/s390x/cpu_features.c b/target/s390x/cpu_features.c +index f64f581..5be6f59 100644 +--- a/target/s390x/cpu_features.c ++++ b/target/s390x/cpu_features.c +@@ -111,7 +111,7 @@ static const S390FeatDef s390_features[] = { + FEAT_INIT("vxeh2", S390_FEAT_TYPE_STFL, 148, "Vector Enhancements facility 2"), + FEAT_INIT("esort-base", S390_FEAT_TYPE_STFL, 150, "Enhanced-sort facility (excluding subfunctions)"), + FEAT_INIT("deflate-base", S390_FEAT_TYPE_STFL, 151, "Deflate-conversion facility (excluding subfunctions)"), +- FEAT_INIT("vxbeh", S390_FEAT_TYPE_STFL, 152, "Vector BCD enhancements facility 1"), ++ FEAT_INIT("vxbeh", S390_FEAT_TYPE_STFL, 152, "Vector-Packed-Decimal-Enhancement Facility"), + FEAT_INIT("msa9-base", S390_FEAT_TYPE_STFL, 155, "Message-security-assist-extension-9 facility (excluding subfunctions)"), + FEAT_INIT("etoken", S390_FEAT_TYPE_STFL, 156, "Etoken facility"), + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-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-Rework-CPU-feature-definition.patch b/SOURCES/kvm-s390x-cpumodel-Rework-CPU-feature-definition.patch new file mode 100644 index 0000000..f1fbf6f --- /dev/null +++ b/SOURCES/kvm-s390x-cpumodel-Rework-CPU-feature-definition.patch @@ -0,0 +1,1168 @@ +From 7d9350b6ad9f0b5dcdd098092eb3760bdbcf9d54 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Wed, 18 Sep 2019 14:35:48 +0100 +Subject: [PATCH 09/22] s390x/cpumodel: Rework CPU feature definition + +RH-Author: Thomas Huth +Message-id: <20190918143549.16340-2-thuth@redhat.com> +Patchwork-id: 90759 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH 1/2] s390x/cpumodel: Rework CPU feature definition +Bugzilla: 1660909 +RH-Acked-by: David Hildenbrand +RH-Acked-by: Cornelia Huck +RH-Acked-by: Jens Freimann + +Let's define features at a single spot and make it less error prone to +define new features. + +Acked-by: Janosch Frank +Acked-by: Cornelia Huck +Signed-off-by: David Hildenbrand +(cherry picked from commit 220ae9002f33480fa30050140c852847677b3c06) +Signed-off-by: Danilo C. L. de Paula + +Conflicts: + The "vxpdeh" line needed adaption due to out-of-order backported commits: + + d05be57ddc2e1722f527aa4c20d84dfd15c840ec + s390: cpumodel: fix description for the new vector facility + + 0d4cb295db7503fbac2f5bb3e878a56630231fed + s390x/cpumodel: also change name of vxbeh + + 5d8866c89817998a3d9c3055d5dc2b5a8e78658a + s390x/cpumodel: change internal name of vxpdeh to match description + +Signed-off-by: Thomas Huth +Signed-off-by: Danilo C. L. de Paula +--- + target/s390x/cpu_features.c | 352 ++-------------------------------- + target/s390x/cpu_features_def.h | 352 +--------------------------------- + target/s390x/cpu_features_def.inc.h | 369 ++++++++++++++++++++++++++++++++++++ + 3 files changed, 386 insertions(+), 687 deletions(-) + create mode 100644 target/s390x/cpu_features_def.inc.h + +diff --git a/target/s390x/cpu_features.c b/target/s390x/cpu_features.c +index 065db76..9f817e3 100644 +--- a/target/s390x/cpu_features.c ++++ b/target/s390x/cpu_features.c +@@ -2,8 +2,9 @@ + * CPU features/facilities for s390x + * + * Copyright IBM Corp. 2016, 2018 ++ * Copyright Red Hat, Inc. 2019 + * +- * Author(s): David Hildenbrand ++ * Author(s): David Hildenbrand + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at + * your option) any later version. See the COPYING file in the top-level +@@ -14,346 +15,17 @@ + #include "qemu/module.h" + #include "cpu_features.h" + +-#define FEAT_INIT(_name, _type, _bit, _desc) \ +- { \ +- .name = _name, \ +- .type = _type, \ +- .bit = _bit, \ +- .desc = _desc, \ +- } +- +-/* S390FeatDef.bit is not applicable as there is no feature block. */ +-#define FEAT_INIT_MISC(_name, _desc) \ +- FEAT_INIT(_name, S390_FEAT_TYPE_MISC, 0, _desc) +- +-/* indexed by feature number for easy lookup */ +-static const S390FeatDef s390_features[] = { +- FEAT_INIT("esan3", S390_FEAT_TYPE_STFL, 0, "Instructions marked as n3"), +- FEAT_INIT("zarch", S390_FEAT_TYPE_STFL, 1, "z/Architecture architectural mode"), +- FEAT_INIT("dateh", S390_FEAT_TYPE_STFL, 3, "DAT-enhancement facility"), +- FEAT_INIT("idtes", S390_FEAT_TYPE_STFL, 4, "IDTE selective TLB segment-table clearing"), +- FEAT_INIT("idter", S390_FEAT_TYPE_STFL, 5, "IDTE selective TLB region-table clearing"), +- FEAT_INIT("asnlxr", S390_FEAT_TYPE_STFL, 6, "ASN-and-LX reuse facility"), +- FEAT_INIT("stfle", S390_FEAT_TYPE_STFL, 7, "Store-facility-list-extended facility"), +- FEAT_INIT("edat", S390_FEAT_TYPE_STFL, 8, "Enhanced-DAT facility"), +- FEAT_INIT("srs", S390_FEAT_TYPE_STFL, 9, "Sense-running-status facility"), +- FEAT_INIT("csske", S390_FEAT_TYPE_STFL, 10, "Conditional-SSKE facility"), +- FEAT_INIT("ctop", S390_FEAT_TYPE_STFL, 11, "Configuration-topology facility"), +- FEAT_INIT("apqci", S390_FEAT_TYPE_STFL, 12, "Query AP Configuration Information facility"), +- FEAT_INIT("ipter", S390_FEAT_TYPE_STFL, 13, "IPTE-range facility"), +- FEAT_INIT("nonqks", S390_FEAT_TYPE_STFL, 14, "Nonquiescing key-setting facility"), +- FEAT_INIT("apft", S390_FEAT_TYPE_STFL, 15, "AP Facilities Test facility"), +- FEAT_INIT("etf2", S390_FEAT_TYPE_STFL, 16, "Extended-translation facility 2"), +- FEAT_INIT("msa-base", S390_FEAT_TYPE_STFL, 17, "Message-security-assist facility (excluding subfunctions)"), +- FEAT_INIT("ldisp", S390_FEAT_TYPE_STFL, 18, "Long-displacement facility"), +- FEAT_INIT("ldisphp", S390_FEAT_TYPE_STFL, 19, "Long-displacement facility has high performance"), +- FEAT_INIT("hfpm", S390_FEAT_TYPE_STFL, 20, "HFP-multiply-add/subtract facility"), +- FEAT_INIT("eimm", S390_FEAT_TYPE_STFL, 21, "Extended-immediate facility"), +- FEAT_INIT("etf3", S390_FEAT_TYPE_STFL, 22, "Extended-translation facility 3"), +- FEAT_INIT("hfpue", S390_FEAT_TYPE_STFL, 23, "HFP-unnormalized-extension facility"), +- FEAT_INIT("etf2eh", S390_FEAT_TYPE_STFL, 24, "ETF2-enhancement facility"), +- FEAT_INIT("stckf", S390_FEAT_TYPE_STFL, 25, "Store-clock-fast facility"), +- FEAT_INIT("parseh", S390_FEAT_TYPE_STFL, 26, "Parsing-enhancement facility"), +- FEAT_INIT("mvcos", S390_FEAT_TYPE_STFL, 27, "Move-with-optional-specification facility"), +- FEAT_INIT("tods-base", S390_FEAT_TYPE_STFL, 28, "TOD-clock-steering facility (excluding subfunctions)"), +- FEAT_INIT("etf3eh", S390_FEAT_TYPE_STFL, 30, "ETF3-enhancement facility"), +- FEAT_INIT("ectg", S390_FEAT_TYPE_STFL, 31, "Extract-CPU-time facility"), +- FEAT_INIT("csst", S390_FEAT_TYPE_STFL, 32, "Compare-and-swap-and-store facility"), +- FEAT_INIT("csst2", S390_FEAT_TYPE_STFL, 33, "Compare-and-swap-and-store facility 2"), +- FEAT_INIT("ginste", S390_FEAT_TYPE_STFL, 34, "General-instructions-extension facility"), +- FEAT_INIT("exrl", S390_FEAT_TYPE_STFL, 35, "Execute-extensions facility"), +- FEAT_INIT("emon", S390_FEAT_TYPE_STFL, 36, "Enhanced-monitor facility"), +- FEAT_INIT("fpe", S390_FEAT_TYPE_STFL, 37, "Floating-point extension facility"), +- FEAT_INIT("opc", S390_FEAT_TYPE_STFL, 38, "Order Preserving Compression facility"), +- FEAT_INIT("sprogp", S390_FEAT_TYPE_STFL, 40, "Set-program-parameters facility"), +- FEAT_INIT("fpseh", S390_FEAT_TYPE_STFL, 41, "Floating-point-support-enhancement facilities"), +- FEAT_INIT("dfp", S390_FEAT_TYPE_STFL, 42, "DFP (decimal-floating-point) facility"), +- FEAT_INIT("dfphp", S390_FEAT_TYPE_STFL, 43, "DFP (decimal-floating-point) facility has high performance"), +- FEAT_INIT("pfpo", S390_FEAT_TYPE_STFL, 44, "PFPO instruction"), +- FEAT_INIT("stfle45", S390_FEAT_TYPE_STFL, 45, "Various facilities introduced with z196"), +- FEAT_INIT("cmpsceh", S390_FEAT_TYPE_STFL, 47, "CMPSC-enhancement facility"), +- FEAT_INIT("dfpzc", S390_FEAT_TYPE_STFL, 48, "Decimal-floating-point zoned-conversion facility"), +- FEAT_INIT("stfle49", S390_FEAT_TYPE_STFL, 49, "Various facilities introduced with zEC12"), +- FEAT_INIT("cte", S390_FEAT_TYPE_STFL, 50, "Constrained transactional-execution facility"), +- FEAT_INIT("ltlbc", S390_FEAT_TYPE_STFL, 51, "Local-TLB-clearing facility"), +- FEAT_INIT("iacc2", S390_FEAT_TYPE_STFL, 52, "Interlocked-access facility 2"), +- FEAT_INIT("stfle53", S390_FEAT_TYPE_STFL, 53, "Various facilities introduced with z13"), +- FEAT_INIT("eec", S390_FEAT_TYPE_STFL, 54, "Entropy encoding compression facility"), +- FEAT_INIT("msa5-base", S390_FEAT_TYPE_STFL, 57, "Message-security-assist-extension-5 facility (excluding subfunctions)"), +- FEAT_INIT("minste2", S390_FEAT_TYPE_STFL, 58, "Miscellaneous-instruction-extensions facility 2"), +- FEAT_INIT("sema", S390_FEAT_TYPE_STFL, 59, "Semaphore-assist facility"), +- FEAT_INIT("tsi", S390_FEAT_TYPE_STFL, 60, "Time-slice Instrumentation facility"), +- FEAT_INIT("minste3", S390_FEAT_TYPE_STFL, 61, "Miscellaneous-Instruction-Extensions Facility 3"), +- FEAT_INIT("ri", S390_FEAT_TYPE_STFL, 64, "CPU runtime-instrumentation facility"), +- FEAT_INIT("zpci", S390_FEAT_TYPE_STFL, 69, "z/PCI facility"), +- FEAT_INIT("aen", S390_FEAT_TYPE_STFL, 71, "General-purpose-adapter-event-notification facility"), +- FEAT_INIT("ais", S390_FEAT_TYPE_STFL, 72, "General-purpose-adapter-interruption-suppression facility"), +- FEAT_INIT("te", S390_FEAT_TYPE_STFL, 73, "Transactional-execution facility"), +- FEAT_INIT("sthyi", S390_FEAT_TYPE_STFL, 74, "Store-hypervisor-information facility"), +- FEAT_INIT("aefsi", S390_FEAT_TYPE_STFL, 75, "Access-exception-fetch/store-indication facility"), +- FEAT_INIT("msa3-base", S390_FEAT_TYPE_STFL, 76, "Message-security-assist-extension-3 facility (excluding subfunctions)"), +- FEAT_INIT("msa4-base", S390_FEAT_TYPE_STFL, 77, "Message-security-assist-extension-4 facility (excluding subfunctions)"), +- FEAT_INIT("edat2", S390_FEAT_TYPE_STFL, 78, "Enhanced-DAT facility 2"), +- FEAT_INIT("dfppc", S390_FEAT_TYPE_STFL, 80, "Decimal-floating-point packed-conversion facility"), +- FEAT_INIT("ppa15", S390_FEAT_TYPE_STFL, 81, "PPA15 is installed"), +- FEAT_INIT("bpb", S390_FEAT_TYPE_STFL, 82, "Branch prediction blocking"), +- FEAT_INIT("vx", S390_FEAT_TYPE_STFL, 129, "Vector facility"), +- FEAT_INIT("iep", S390_FEAT_TYPE_STFL, 130, "Instruction-execution-protection facility"), +- FEAT_INIT("sea_esop2", S390_FEAT_TYPE_STFL, 131, "Side-effect-access facility and Enhanced-suppression-on-protection facility 2"), +- FEAT_INIT("gs", S390_FEAT_TYPE_STFL, 133, "Guarded-storage facility"), +- FEAT_INIT("vxpd", S390_FEAT_TYPE_STFL, 134, "Vector packed decimal facility"), +- FEAT_INIT("vxeh", S390_FEAT_TYPE_STFL, 135, "Vector enhancements facility"), +- FEAT_INIT("mepoch", S390_FEAT_TYPE_STFL, 139, "Multiple-epoch facility"), +- FEAT_INIT("tpei", S390_FEAT_TYPE_STFL, 144, "Test-pending-external-interruption facility"), +- FEAT_INIT("irbm", S390_FEAT_TYPE_STFL, 145, "Insert-reference-bits-multiple facility"), +- FEAT_INIT("msa8-base", S390_FEAT_TYPE_STFL, 146, "Message-security-assist-extension-8 facility (excluding subfunctions)"), +- FEAT_INIT("cmmnt", S390_FEAT_TYPE_STFL, 147, "CMM: ESSA-enhancement (no translate) facility"), +- FEAT_INIT("vxeh2", S390_FEAT_TYPE_STFL, 148, "Vector Enhancements facility 2"), +- FEAT_INIT("esort-base", S390_FEAT_TYPE_STFL, 150, "Enhanced-sort facility (excluding subfunctions)"), +- FEAT_INIT("deflate-base", S390_FEAT_TYPE_STFL, 151, "Deflate-conversion facility (excluding subfunctions)"), +- FEAT_INIT("vxpdeh", S390_FEAT_TYPE_STFL, 152, "Vector-Packed-Decimal-Enhancement Facility"), +- FEAT_INIT("msa9-base", S390_FEAT_TYPE_STFL, 155, "Message-security-assist-extension-9 facility (excluding subfunctions)"), +- FEAT_INIT("etoken", S390_FEAT_TYPE_STFL, 156, "Etoken facility"), +- +- /* SCLP SCCB Byte 80 - 98 (bit numbers relative to byte-80) */ +- FEAT_INIT("gsls", S390_FEAT_TYPE_SCLP_CONF_CHAR, 40, "SIE: Guest-storage-limit-suppression facility"), +- FEAT_INIT("esop", S390_FEAT_TYPE_SCLP_CONF_CHAR, 46, "Enhanced-suppression-on-protection facility"), +- FEAT_INIT("hpma2", S390_FEAT_TYPE_SCLP_CONF_CHAR, 90, "Host page management assist 2 Facility"), /* 91-2 */ +- FEAT_INIT("kss", S390_FEAT_TYPE_SCLP_CONF_CHAR, 151, "SIE: Keyless-subset facility"), /* 98-7 */ +- +- /* SCLP SCCB Byte 116 - 119 (bit numbers relative to byte-116) */ +- FEAT_INIT("64bscao", S390_FEAT_TYPE_SCLP_CONF_CHAR_EXT, 0, "SIE: 64-bit-SCAO facility"), +- FEAT_INIT("cmma", S390_FEAT_TYPE_SCLP_CONF_CHAR_EXT, 1, "SIE: Collaborative-memory-management assist"), +- FEAT_INIT("pfmfi", S390_FEAT_TYPE_SCLP_CONF_CHAR_EXT, 9, "SIE: PFMF interpretation facility"), +- FEAT_INIT("ibs", S390_FEAT_TYPE_SCLP_CONF_CHAR_EXT, 10, "SIE: Interlock-and-broadcast-suppression facility"), +- +- FEAT_INIT("sief2", S390_FEAT_TYPE_SCLP_CPU, 4, "SIE: interception format 2 (Virtual SIE)"), +- FEAT_INIT("skey", S390_FEAT_TYPE_SCLP_CPU, 5, "SIE: Storage-key facility"), +- FEAT_INIT("gpereh", S390_FEAT_TYPE_SCLP_CPU, 10, "SIE: Guest-PER enhancement facility"), +- FEAT_INIT("siif", S390_FEAT_TYPE_SCLP_CPU, 11, "SIE: Shared IPTE-interlock facility"), +- FEAT_INIT("sigpif", S390_FEAT_TYPE_SCLP_CPU, 12, "SIE: SIGP interpretation facility"), +- FEAT_INIT("ib", S390_FEAT_TYPE_SCLP_CPU, 42, "SIE: Intervention bypass facility"), +- FEAT_INIT("cei", S390_FEAT_TYPE_SCLP_CPU, 43, "SIE: Conditional-external-interception facility"), +- +- FEAT_INIT_MISC("dateh2", "DAT-enhancement facility 2"), +- FEAT_INIT_MISC("cmm", "Collaborative-memory-management facility"), +- FEAT_INIT_MISC("ap", "AP instructions installed"), +- +- FEAT_INIT("plo-cl", S390_FEAT_TYPE_PLO, 0, "PLO Compare and load (32 bit in general registers)"), +- FEAT_INIT("plo-clg", S390_FEAT_TYPE_PLO, 1, "PLO Compare and load (64 bit in parameter list)"), +- FEAT_INIT("plo-clgr", S390_FEAT_TYPE_PLO, 2, "PLO Compare and load (32 bit in general registers)"), +- FEAT_INIT("plo-clx", S390_FEAT_TYPE_PLO, 3, "PLO Compare and load (128 bit in parameter list)"), +- FEAT_INIT("plo-cs", S390_FEAT_TYPE_PLO, 4, "PLO Compare and swap (32 bit in general registers)"), +- FEAT_INIT("plo-csg", S390_FEAT_TYPE_PLO, 5, "PLO Compare and swap (64 bit in parameter list)"), +- FEAT_INIT("plo-csgr", S390_FEAT_TYPE_PLO, 6, "PLO Compare and swap (32 bit in general registers)"), +- FEAT_INIT("plo-csx", S390_FEAT_TYPE_PLO, 7, "PLO Compare and swap (128 bit in parameter list)"), +- FEAT_INIT("plo-dcs", S390_FEAT_TYPE_PLO, 8, "PLO Double compare and swap (32 bit in general registers)"), +- FEAT_INIT("plo-dcsg", S390_FEAT_TYPE_PLO, 9, "PLO Double compare and swap (64 bit in parameter list)"), +- FEAT_INIT("plo-dcsgr", S390_FEAT_TYPE_PLO, 10, "PLO Double compare and swap (32 bit in general registers)"), +- FEAT_INIT("plo-dcsx", S390_FEAT_TYPE_PLO, 11, "PLO Double compare and swap (128 bit in parameter list)"), +- FEAT_INIT("plo-csst", S390_FEAT_TYPE_PLO, 12, "PLO Compare and swap and store (32 bit in general registers)"), +- FEAT_INIT("plo-csstg", S390_FEAT_TYPE_PLO, 13, "PLO Compare and swap and store (64 bit in parameter list)"), +- FEAT_INIT("plo-csstgr", S390_FEAT_TYPE_PLO, 14, "PLO Compare and swap and store (32 bit in general registers)"), +- FEAT_INIT("plo-csstx", S390_FEAT_TYPE_PLO, 15, "PLO Compare and swap and store (128 bit in parameter list)"), +- FEAT_INIT("plo-csdst", S390_FEAT_TYPE_PLO, 16, "PLO Compare and swap and double store (32 bit in general registers)"), +- FEAT_INIT("plo-csdstg", S390_FEAT_TYPE_PLO, 17, "PLO Compare and swap and double store (64 bit in parameter list)"), +- FEAT_INIT("plo-csdstgr", S390_FEAT_TYPE_PLO, 18, "PLO Compare and swap and double store (32 bit in general registers)"), +- FEAT_INIT("plo-csdstx", S390_FEAT_TYPE_PLO, 19, "PLO Compare and swap and double store (128 bit in parameter list)"), +- FEAT_INIT("plo-cstst", S390_FEAT_TYPE_PLO, 20, "PLO Compare and swap and triple store (32 bit in general registers)"), +- FEAT_INIT("plo-cststg", S390_FEAT_TYPE_PLO, 21, "PLO Compare and swap and triple store (64 bit in parameter list)"), +- FEAT_INIT("plo-cststgr", S390_FEAT_TYPE_PLO, 22, "PLO Compare and swap and triple store (32 bit in general registers)"), +- FEAT_INIT("plo-cststx", S390_FEAT_TYPE_PLO, 23, "PLO Compare and swap and triple store (128 bit in parameter list)"), +- +- FEAT_INIT("ptff-qto", S390_FEAT_TYPE_PTFF, 1, "PTFF Query TOD Offset"), +- FEAT_INIT("ptff-qsi", S390_FEAT_TYPE_PTFF, 2, "PTFF Query Steering Information"), +- FEAT_INIT("ptff-qpc", S390_FEAT_TYPE_PTFF, 3, "PTFF Query Physical Clock"), +- FEAT_INIT("ptff-qui", S390_FEAT_TYPE_PTFF, 4, "PTFF Query UTC Information"), +- FEAT_INIT("ptff-qtou", S390_FEAT_TYPE_PTFF, 5, "PTFF Query TOD Offset User"), +- FEAT_INIT("ptff-qsie", S390_FEAT_TYPE_PTFF, 10, "PTFF Query Steering Information Extended"), +- FEAT_INIT("ptff-qtoue", S390_FEAT_TYPE_PTFF, 13, "PTFF Query TOD Offset User Extended"), +- FEAT_INIT("ptff-sto", S390_FEAT_TYPE_PTFF, 65, "PTFF Set TOD Offset"), +- FEAT_INIT("ptff-stou", S390_FEAT_TYPE_PTFF, 69, "PTFF Set TOD Offset User"), +- FEAT_INIT("ptff-stoe", S390_FEAT_TYPE_PTFF, 73, "PTFF Set TOD Offset Extended"), +- FEAT_INIT("ptff-stoue", S390_FEAT_TYPE_PTFF, 77, "PTFF Set TOD Offset User Extended"), +- +- FEAT_INIT("kmac-dea", S390_FEAT_TYPE_KMAC, 1, "KMAC DEA"), +- FEAT_INIT("kmac-tdea-128", S390_FEAT_TYPE_KMAC, 2, "KMAC TDEA-128"), +- FEAT_INIT("kmac-tdea-192", S390_FEAT_TYPE_KMAC, 3, "KMAC TDEA-192"), +- FEAT_INIT("kmac-edea", S390_FEAT_TYPE_KMAC, 9, "KMAC Encrypted-DEA"), +- FEAT_INIT("kmac-etdea-128", S390_FEAT_TYPE_KMAC, 10, "KMAC Encrypted-TDEA-128"), +- FEAT_INIT("kmac-etdea-192", S390_FEAT_TYPE_KMAC, 11, "KMAC Encrypted-TDEA-192"), +- FEAT_INIT("kmac-aes-128", S390_FEAT_TYPE_KMAC, 18, "KMAC AES-128"), +- FEAT_INIT("kmac-aes-192", S390_FEAT_TYPE_KMAC, 19, "KMAC AES-192"), +- FEAT_INIT("kmac-aes-256", S390_FEAT_TYPE_KMAC, 20, "KMAC AES-256"), +- FEAT_INIT("kmac-eaes-128", S390_FEAT_TYPE_KMAC, 26, "KMAC Encrypted-AES-128"), +- FEAT_INIT("kmac-eaes-192", S390_FEAT_TYPE_KMAC, 27, "KMAC Encrypted-AES-192"), +- FEAT_INIT("kmac-eaes-256", S390_FEAT_TYPE_KMAC, 28, "KMAC Encrypted-AES-256"), +- +- FEAT_INIT("kmc-dea", S390_FEAT_TYPE_KMC, 1, "KMC DEA"), +- FEAT_INIT("kmc-tdea-128", S390_FEAT_TYPE_KMC, 2, "KMC TDEA-128"), +- FEAT_INIT("kmc-tdea-192", S390_FEAT_TYPE_KMC, 3, "KMC TDEA-192"), +- FEAT_INIT("kmc-edea", S390_FEAT_TYPE_KMC, 9, "KMC Encrypted-DEA"), +- FEAT_INIT("kmc-etdea-128", S390_FEAT_TYPE_KMC, 10, "KMC Encrypted-TDEA-128"), +- FEAT_INIT("kmc-etdea-192", S390_FEAT_TYPE_KMC, 11, "KMC Encrypted-TDEA-192"), +- FEAT_INIT("kmc-aes-128", S390_FEAT_TYPE_KMC, 18, "KMC AES-128"), +- FEAT_INIT("kmc-aes-192", S390_FEAT_TYPE_KMC, 19, "KMC AES-192"), +- FEAT_INIT("kmc-aes-256", S390_FEAT_TYPE_KMC, 20, "KMC AES-256"), +- FEAT_INIT("kmc-eaes-128", S390_FEAT_TYPE_KMC, 26, "KMC Encrypted-AES-128"), +- FEAT_INIT("kmc-eaes-192", S390_FEAT_TYPE_KMC, 27, "KMC Encrypted-AES-192"), +- FEAT_INIT("kmc-eaes-256", S390_FEAT_TYPE_KMC, 28, "KMC Encrypted-AES-256"), +- FEAT_INIT("kmc-prng", S390_FEAT_TYPE_KMC, 67, "KMC PRNG"), +- +- FEAT_INIT("km-dea", S390_FEAT_TYPE_KM, 1, "KM DEA"), +- FEAT_INIT("km-tdea-128", S390_FEAT_TYPE_KM, 2, "KM TDEA-128"), +- FEAT_INIT("km-tdea-192", S390_FEAT_TYPE_KM, 3, "KM TDEA-192"), +- FEAT_INIT("km-edea", S390_FEAT_TYPE_KM, 9, "KM Encrypted-DEA"), +- FEAT_INIT("km-etdea-128", S390_FEAT_TYPE_KM, 10, "KM Encrypted-TDEA-128"), +- FEAT_INIT("km-etdea-192", S390_FEAT_TYPE_KM, 11, "KM Encrypted-TDEA-192"), +- FEAT_INIT("km-aes-128", S390_FEAT_TYPE_KM, 18, "KM AES-128"), +- FEAT_INIT("km-aes-192", S390_FEAT_TYPE_KM, 19, "KM AES-192"), +- FEAT_INIT("km-aes-256", S390_FEAT_TYPE_KM, 20, "KM AES-256"), +- FEAT_INIT("km-eaes-128", S390_FEAT_TYPE_KM, 26, "KM Encrypted-AES-128"), +- FEAT_INIT("km-eaes-192", S390_FEAT_TYPE_KM, 27, "KM Encrypted-AES-192"), +- FEAT_INIT("km-eaes-256", S390_FEAT_TYPE_KM, 28, "KM Encrypted-AES-256"), +- FEAT_INIT("km-xts-aes-128", S390_FEAT_TYPE_KM, 50, "KM XTS-AES-128"), +- FEAT_INIT("km-xts-aes-256", S390_FEAT_TYPE_KM, 52, "KM XTS-AES-256"), +- FEAT_INIT("km-xts-eaes-128", S390_FEAT_TYPE_KM, 58, "KM XTS-Encrypted-AES-128"), +- FEAT_INIT("km-xts-eaes-256", S390_FEAT_TYPE_KM, 60, "KM XTS-Encrypted-AES-256"), +- +- FEAT_INIT("kimd-sha-1", S390_FEAT_TYPE_KIMD, 1, "KIMD SHA-1"), +- FEAT_INIT("kimd-sha-256", S390_FEAT_TYPE_KIMD, 2, "KIMD SHA-256"), +- FEAT_INIT("kimd-sha-512", S390_FEAT_TYPE_KIMD, 3, "KIMD SHA-512"), +- FEAT_INIT("kimd-sha3-224", S390_FEAT_TYPE_KIMD, 32, "KIMD SHA3-224"), +- FEAT_INIT("kimd-sha3-256", S390_FEAT_TYPE_KIMD, 33, "KIMD SHA3-256"), +- FEAT_INIT("kimd-sha3-384", S390_FEAT_TYPE_KIMD, 34, "KIMD SHA3-384"), +- FEAT_INIT("kimd-sha3-512", S390_FEAT_TYPE_KIMD, 35, "KIMD SHA3-512"), +- FEAT_INIT("kimd-shake-128", S390_FEAT_TYPE_KIMD, 36, "KIMD SHAKE-128"), +- FEAT_INIT("kimd-shake-256", S390_FEAT_TYPE_KIMD, 37, "KIMD SHAKE-256"), +- FEAT_INIT("kimd-ghash", S390_FEAT_TYPE_KIMD, 65, "KIMD GHASH"), +- +- FEAT_INIT("klmd-sha-1", S390_FEAT_TYPE_KLMD, 1, "KLMD SHA-1"), +- FEAT_INIT("klmd-sha-256", S390_FEAT_TYPE_KLMD, 2, "KLMD SHA-256"), +- FEAT_INIT("klmd-sha-512", S390_FEAT_TYPE_KLMD, 3, "KLMD SHA-512"), +- FEAT_INIT("klmd-sha3-224", S390_FEAT_TYPE_KLMD, 32, "KLMD SHA3-224"), +- FEAT_INIT("klmd-sha3-256", S390_FEAT_TYPE_KLMD, 33, "KLMD SHA3-256"), +- FEAT_INIT("klmd-sha3-384", S390_FEAT_TYPE_KLMD, 34, "KLMD SHA3-384"), +- FEAT_INIT("klmd-sha3-512", S390_FEAT_TYPE_KLMD, 35, "KLMD SHA3-512"), +- FEAT_INIT("klmd-shake-128", S390_FEAT_TYPE_KLMD, 36, "KLMD SHAKE-128"), +- FEAT_INIT("klmd-shake-256", S390_FEAT_TYPE_KLMD, 37, "KLMD SHAKE-256"), +- +- FEAT_INIT("pckmo-edea", S390_FEAT_TYPE_PCKMO, 1, "PCKMO Encrypted-DEA-Key"), +- FEAT_INIT("pckmo-etdea-128", S390_FEAT_TYPE_PCKMO, 2, "PCKMO Encrypted-TDEA-128-Key"), +- FEAT_INIT("pckmo-etdea-192", S390_FEAT_TYPE_PCKMO, 3, "PCKMO Encrypted-TDEA-192-Key"), +- FEAT_INIT("pckmo-aes-128", S390_FEAT_TYPE_PCKMO, 18, "PCKMO Encrypted-AES-128-Key"), +- FEAT_INIT("pckmo-aes-192", S390_FEAT_TYPE_PCKMO, 19, "PCKMO Encrypted-AES-192-Key"), +- FEAT_INIT("pckmo-aes-256", S390_FEAT_TYPE_PCKMO, 20, "PCKMO Encrypted-AES-256-Key"), +- FEAT_INIT("pckmo-ecc-p256", S390_FEAT_TYPE_PCKMO, 32, "PCKMO Encrypt-ECC-P256-Key"), +- FEAT_INIT("pckmo-ecc-p384", S390_FEAT_TYPE_PCKMO, 33, "PCKMO Encrypt-ECC-P384-Key"), +- FEAT_INIT("pckmo-ecc-p521", S390_FEAT_TYPE_PCKMO, 34, "PCKMO Encrypt-ECC-P521-Key"), +- FEAT_INIT("pckmo-ecc-ed25519", S390_FEAT_TYPE_PCKMO, 40 , "PCKMO Encrypt-ECC-Ed25519-Key"), +- FEAT_INIT("pckmo-ecc-ed448", S390_FEAT_TYPE_PCKMO, 41 , "PCKMO Encrypt-ECC-Ed448-Key"), +- +- FEAT_INIT("kmctr-dea", S390_FEAT_TYPE_KMCTR, 1, "KMCTR DEA"), +- FEAT_INIT("kmctr-tdea-128", S390_FEAT_TYPE_KMCTR, 2, "KMCTR TDEA-128"), +- FEAT_INIT("kmctr-tdea-192", S390_FEAT_TYPE_KMCTR, 3, "KMCTR TDEA-192"), +- FEAT_INIT("kmctr-edea", S390_FEAT_TYPE_KMCTR, 9, "KMCTR Encrypted-DEA"), +- FEAT_INIT("kmctr-etdea-128", S390_FEAT_TYPE_KMCTR, 10, "KMCTR Encrypted-TDEA-128"), +- FEAT_INIT("kmctr-etdea-192", S390_FEAT_TYPE_KMCTR, 11, "KMCTR Encrypted-TDEA-192"), +- FEAT_INIT("kmctr-aes-128", S390_FEAT_TYPE_KMCTR, 18, "KMCTR AES-128"), +- FEAT_INIT("kmctr-aes-192", S390_FEAT_TYPE_KMCTR, 19, "KMCTR AES-192"), +- FEAT_INIT("kmctr-aes-256", S390_FEAT_TYPE_KMCTR, 20, "KMCTR AES-256"), +- FEAT_INIT("kmctr-eaes-128", S390_FEAT_TYPE_KMCTR, 26, "KMCTR Encrypted-AES-128"), +- FEAT_INIT("kmctr-eaes-192", S390_FEAT_TYPE_KMCTR, 27, "KMCTR Encrypted-AES-192"), +- FEAT_INIT("kmctr-eaes-256", S390_FEAT_TYPE_KMCTR, 28, "KMCTR Encrypted-AES-256"), +- +- FEAT_INIT("kmf-dea", S390_FEAT_TYPE_KMF, 1, "KMF DEA"), +- FEAT_INIT("kmf-tdea-128", S390_FEAT_TYPE_KMF, 2, "KMF TDEA-128"), +- FEAT_INIT("kmf-tdea-192", S390_FEAT_TYPE_KMF, 3, "KMF TDEA-192"), +- FEAT_INIT("kmf-edea", S390_FEAT_TYPE_KMF, 9, "KMF Encrypted-DEA"), +- FEAT_INIT("kmf-etdea-128", S390_FEAT_TYPE_KMF, 10, "KMF Encrypted-TDEA-128"), +- FEAT_INIT("kmf-etdea-192", S390_FEAT_TYPE_KMF, 11, "KMF Encrypted-TDEA-192"), +- FEAT_INIT("kmf-aes-128", S390_FEAT_TYPE_KMF, 18, "KMF AES-128"), +- FEAT_INIT("kmf-aes-192", S390_FEAT_TYPE_KMF, 19, "KMF AES-192"), +- FEAT_INIT("kmf-aes-256", S390_FEAT_TYPE_KMF, 20, "KMF AES-256"), +- FEAT_INIT("kmf-eaes-128", S390_FEAT_TYPE_KMF, 26, "KMF Encrypted-AES-128"), +- FEAT_INIT("kmf-eaes-192", S390_FEAT_TYPE_KMF, 27, "KMF Encrypted-AES-192"), +- FEAT_INIT("kmf-eaes-256", S390_FEAT_TYPE_KMF, 28, "KMF Encrypted-AES-256"), +- +- FEAT_INIT("kmo-dea", S390_FEAT_TYPE_KMO, 1, "KMO DEA"), +- FEAT_INIT("kmo-tdea-128", S390_FEAT_TYPE_KMO, 2, "KMO TDEA-128"), +- FEAT_INIT("kmo-tdea-192", S390_FEAT_TYPE_KMO, 3, "KMO TDEA-192"), +- FEAT_INIT("kmo-edea", S390_FEAT_TYPE_KMO, 9, "KMO Encrypted-DEA"), +- FEAT_INIT("kmo-etdea-128", S390_FEAT_TYPE_KMO, 10, "KMO Encrypted-TDEA-128"), +- FEAT_INIT("kmo-etdea-192", S390_FEAT_TYPE_KMO, 11, "KMO Encrypted-TDEA-192"), +- FEAT_INIT("kmo-aes-128", S390_FEAT_TYPE_KMO, 18, "KMO AES-128"), +- FEAT_INIT("kmo-aes-192", S390_FEAT_TYPE_KMO, 19, "KMO AES-192"), +- FEAT_INIT("kmo-aes-256", S390_FEAT_TYPE_KMO, 20, "KMO AES-256"), +- FEAT_INIT("kmo-eaes-128", S390_FEAT_TYPE_KMO, 26, "KMO Encrypted-AES-128"), +- FEAT_INIT("kmo-eaes-192", S390_FEAT_TYPE_KMO, 27, "KMO Encrypted-AES-192"), +- FEAT_INIT("kmo-eaes-256", S390_FEAT_TYPE_KMO, 28, "KMO Encrypted-AES-256"), +- +- FEAT_INIT("pcc-cmac-dea", S390_FEAT_TYPE_PCC, 1, "PCC Compute-Last-Block-CMAC-Using-DEA"), +- FEAT_INIT("pcc-cmac-tdea-128", S390_FEAT_TYPE_PCC, 2, "PCC Compute-Last-Block-CMAC-Using-TDEA-128"), +- FEAT_INIT("pcc-cmac-tdea-192", S390_FEAT_TYPE_PCC, 3, "PCC Compute-Last-Block-CMAC-Using-TDEA-192"), +- FEAT_INIT("pcc-cmac-edea", S390_FEAT_TYPE_PCC, 9, "PCC Compute-Last-Block-CMAC-Using-Encrypted-DEA"), +- FEAT_INIT("pcc-cmac-etdea-128", S390_FEAT_TYPE_PCC, 10, "PCC Compute-Last-Block-CMAC-Using-Encrypted-TDEA-128"), +- FEAT_INIT("pcc-cmac-etdea-192", S390_FEAT_TYPE_PCC, 11, "PCC Compute-Last-Block-CMAC-Using-EncryptedTDEA-192"), +- FEAT_INIT("pcc-cmac-aes-128", S390_FEAT_TYPE_PCC, 18, "PCC Compute-Last-Block-CMAC-Using-AES-128"), +- FEAT_INIT("pcc-cmac-aes-192", S390_FEAT_TYPE_PCC, 19, "PCC Compute-Last-Block-CMAC-Using-AES-192"), +- FEAT_INIT("pcc-cmac-eaes-256", S390_FEAT_TYPE_PCC, 20, "PCC Compute-Last-Block-CMAC-Using-AES-256"), +- FEAT_INIT("pcc-cmac-eaes-128", S390_FEAT_TYPE_PCC, 26, "PCC Compute-Last-Block-CMAC-Using-Encrypted-AES-128"), +- FEAT_INIT("pcc-cmac-eaes-192", S390_FEAT_TYPE_PCC, 27, "PCC Compute-Last-Block-CMAC-Using-Encrypted-AES-192"), +- FEAT_INIT("pcc-cmac-eaes-256", S390_FEAT_TYPE_PCC, 28, "PCC Compute-Last-Block-CMAC-Using-Encrypted-AES-256"), +- FEAT_INIT("pcc-xts-aes-128", S390_FEAT_TYPE_PCC, 50, "PCC Compute-XTS-Parameter-Using-AES-128"), +- FEAT_INIT("pcc-xts-aes-256", S390_FEAT_TYPE_PCC, 52, "PCC Compute-XTS-Parameter-Using-AES-256"), +- FEAT_INIT("pcc-xts-eaes-128", S390_FEAT_TYPE_PCC, 58, "PCC Compute-XTS-Parameter-Using-Encrypted-AES-128"), +- FEAT_INIT("pcc-xts-eaes-256", S390_FEAT_TYPE_PCC, 60, "PCC Compute-XTS-Parameter-Using-Encrypted-AES-256"), +- FEAT_INIT("pcc-scalar-mult-p256", S390_FEAT_TYPE_PCC, 64, "PCC Scalar-Multiply-P256"), +- FEAT_INIT("pcc-scalar-mult-p384", S390_FEAT_TYPE_PCC, 65, "PCC Scalar-Multiply-P384"), +- FEAT_INIT("pcc-scalar-mult-p521", S390_FEAT_TYPE_PCC, 66, "PCC Scalar-Multiply-P521"), +- FEAT_INIT("pcc-scalar-mult-ed25519", S390_FEAT_TYPE_PCC, 72, "PCC Scalar-Multiply-Ed25519"), +- FEAT_INIT("pcc-scalar-mult-ed448", S390_FEAT_TYPE_PCC, 73, "PCC Scalar-Multiply-Ed448"), +- FEAT_INIT("pcc-scalar-mult-x25519", S390_FEAT_TYPE_PCC, 80, "PCC Scalar-Multiply-X25519"), +- FEAT_INIT("pcc-scalar-mult-x448", S390_FEAT_TYPE_PCC, 81, "PCC Scalar-Multiply-X448"), +- +- FEAT_INIT("ppno-sha-512-drng", S390_FEAT_TYPE_PPNO, 3, "PPNO SHA-512-DRNG"), +- FEAT_INIT("prno-trng-qrtcr", S390_FEAT_TYPE_PPNO, 112, "PRNO TRNG-Query-Raw-to-Conditioned-Ratio"), +- FEAT_INIT("prno-trng", S390_FEAT_TYPE_PPNO, 114, "PRNO TRNG"), +- +- FEAT_INIT("kma-gcm-aes-128", S390_FEAT_TYPE_KMA, 18, "KMA GCM-AES-128"), +- FEAT_INIT("kma-gcm-aes-192", S390_FEAT_TYPE_KMA, 19, "KMA GCM-AES-192"), +- FEAT_INIT("kma-gcm-aes-256", S390_FEAT_TYPE_KMA, 20, "KMA GCM-AES-256"), +- FEAT_INIT("kma-gcm-eaes-128", S390_FEAT_TYPE_KMA, 26, "KMA GCM-Encrypted-AES-128"), +- FEAT_INIT("kma-gcm-eaes-192", S390_FEAT_TYPE_KMA, 27, "KMA GCM-Encrypted-AES-192"), +- FEAT_INIT("kma-gcm-eaes-256", S390_FEAT_TYPE_KMA, 28, "KMA GCM-Encrypted-AES-256"), +- +- FEAT_INIT("kdsa-ecdsa-verify-p256", S390_FEAT_TYPE_KDSA, 1, "KDSA ECDSA-Verify-P256"), +- FEAT_INIT("kdsa-ecdsa-verify-p384", S390_FEAT_TYPE_KDSA, 2, "KDSA ECDSA-Verify-P384"), +- FEAT_INIT("kdsa-ecdsa-verify-p521", S390_FEAT_TYPE_KDSA, 3, "KDSA ECDSA-Verify-P521"), +- FEAT_INIT("kdsa-ecdsa-sign-p256", S390_FEAT_TYPE_KDSA, 9, "KDSA ECDSA-Sign-P256"), +- FEAT_INIT("kdsa-ecdsa-sign-p384", S390_FEAT_TYPE_KDSA, 10, "KDSA ECDSA-Sign-P384"), +- FEAT_INIT("kdsa-ecdsa-sign-p521", S390_FEAT_TYPE_KDSA, 11, "KDSA ECDSA-Sign-P521"), +- FEAT_INIT("kdsa-eecdsa-sign-p256", S390_FEAT_TYPE_KDSA, 17, "KDSA Encrypted-ECDSA-Sign-P256"), +- FEAT_INIT("kdsa-eecdsa-sign-p384", S390_FEAT_TYPE_KDSA, 18, "KDSA Encrypted-ECDSA-Sign-P384"), +- FEAT_INIT("kdsa-eecdsa-sign-p521", S390_FEAT_TYPE_KDSA, 19, "KDSA Encrypted-ECDSA-Sign-P521"), +- FEAT_INIT("kdsa-eddsa-verify-ed25519", S390_FEAT_TYPE_KDSA, 32, "KDSA EdDSA-Verify-Ed25519"), +- FEAT_INIT("kdsa-eddsa-verify-ed448", S390_FEAT_TYPE_KDSA, 36, "KDSA EdDSA-Verify-Ed448"), +- FEAT_INIT("kdsa-eddsa-sign-ed25519", S390_FEAT_TYPE_KDSA, 40, "KDSA EdDSA-Sign-Ed25519"), +- FEAT_INIT("kdsa-eddsa-sign-ed448", S390_FEAT_TYPE_KDSA, 44, "KDSA EdDSA-Sign-Ed448"), +- FEAT_INIT("kdsa-eeddsa-sign-ed25519", S390_FEAT_TYPE_KDSA, 48, "KDSA Encrypted-EdDSA-Sign-Ed25519"), +- FEAT_INIT("kdsa-eeddsa-sign-ed448", S390_FEAT_TYPE_KDSA, 52, "KDSA Encrypted-EdDSA-Sign-Ed448"), +- +- FEAT_INIT("sortl-sflr", S390_FEAT_TYPE_SORTL, 1, "SORTL SFLR"), +- FEAT_INIT("sortl-svlr", S390_FEAT_TYPE_SORTL, 2, "SORTL SVLR"), +- FEAT_INIT("sortl-32", S390_FEAT_TYPE_SORTL, 130, "SORTL 32 input lists"), +- FEAT_INIT("sortl-128", S390_FEAT_TYPE_SORTL, 132, "SORTL 128 input lists"), +- FEAT_INIT("sortl-f0", S390_FEAT_TYPE_SORTL, 192, "SORTL format 0 parameter-block"), +- +- FEAT_INIT("dfltcc-gdht", S390_FEAT_TYPE_DFLTCC, 1, "DFLTCC GDHT"), +- FEAT_INIT("dfltcc-cmpr", S390_FEAT_TYPE_DFLTCC, 2, "DFLTCC CMPR"), +- FEAT_INIT("dfltcc-xpnd", S390_FEAT_TYPE_DFLTCC, 4, "DFLTCC XPND"), +- FEAT_INIT("dfltcc-f0", S390_FEAT_TYPE_DFLTCC, 192, "DFLTCC format 0 parameter-block"), ++#define DEF_FEAT(_FEAT, _NAME, _TYPE, _BIT, _DESC) \ ++ [S390_FEAT_##_FEAT] = { \ ++ .name = _NAME, \ ++ .type = S390_FEAT_TYPE_##_TYPE, \ ++ .bit = _BIT, \ ++ .desc = _DESC, \ ++ }, ++static const S390FeatDef s390_features[S390_FEAT_MAX] = { ++ #include "cpu_features_def.inc.h" + }; ++#undef DEF_FEAT + + const S390FeatDef *s390_feat_def(S390Feat feat) + { +diff --git a/target/s390x/cpu_features_def.h b/target/s390x/cpu_features_def.h +index a7abe4d..412d356 100644 +--- a/target/s390x/cpu_features_def.h ++++ b/target/s390x/cpu_features_def.h +@@ -2,9 +2,10 @@ + * CPU features/facilities for s390 + * + * Copyright IBM Corp. 2016, 2018 ++ * Copyright Red Hat, Inc. 2019 + * + * Author(s): Michael Mueller +- * David Hildenbrand ++ * David Hildenbrand + * + * This work is licensed under the terms of the GNU GPL, version 2 or (at + * your option) any later version. See the COPYING file in the top-level +@@ -14,354 +15,11 @@ + #ifndef TARGET_S390X_CPU_FEATURES_DEF_H + #define TARGET_S390X_CPU_FEATURES_DEF_H + ++#define DEF_FEAT(_FEAT, ...) S390_FEAT_##_FEAT, + typedef enum { +- /* Stfle */ +- S390_FEAT_ESAN3 = 0, +- S390_FEAT_ZARCH, +- S390_FEAT_DAT_ENH, +- S390_FEAT_IDTE_SEGMENT, +- S390_FEAT_IDTE_REGION, +- S390_FEAT_ASN_LX_REUSE, +- S390_FEAT_STFLE, +- S390_FEAT_EDAT, +- S390_FEAT_SENSE_RUNNING_STATUS, +- S390_FEAT_CONDITIONAL_SSKE, +- S390_FEAT_CONFIGURATION_TOPOLOGY, +- S390_FEAT_AP_QUERY_CONFIG_INFO, +- S390_FEAT_IPTE_RANGE, +- S390_FEAT_NONQ_KEY_SETTING, +- S390_FEAT_AP_FACILITIES_TEST, +- S390_FEAT_EXTENDED_TRANSLATION_2, +- S390_FEAT_MSA, +- S390_FEAT_LONG_DISPLACEMENT, +- S390_FEAT_LONG_DISPLACEMENT_FAST, +- S390_FEAT_HFP_MADDSUB, +- S390_FEAT_EXTENDED_IMMEDIATE, +- S390_FEAT_EXTENDED_TRANSLATION_3, +- S390_FEAT_HFP_UNNORMALIZED_EXT, +- S390_FEAT_ETF2_ENH, +- S390_FEAT_STORE_CLOCK_FAST, +- S390_FEAT_PARSING_ENH, +- S390_FEAT_MOVE_WITH_OPTIONAL_SPEC, +- S390_FEAT_TOD_CLOCK_STEERING, +- S390_FEAT_ETF3_ENH, +- S390_FEAT_EXTRACT_CPU_TIME, +- S390_FEAT_COMPARE_AND_SWAP_AND_STORE, +- S390_FEAT_COMPARE_AND_SWAP_AND_STORE_2, +- S390_FEAT_GENERAL_INSTRUCTIONS_EXT, +- S390_FEAT_EXECUTE_EXT, +- S390_FEAT_ENHANCED_MONITOR, +- S390_FEAT_FLOATING_POINT_EXT, +- S390_FEAT_ORDER_PRESERVING_COMPRESSION, +- S390_FEAT_SET_PROGRAM_PARAMETERS, +- S390_FEAT_FLOATING_POINT_SUPPPORT_ENH, +- S390_FEAT_DFP, +- S390_FEAT_DFP_FAST, +- S390_FEAT_PFPO, +- S390_FEAT_STFLE_45, +- S390_FEAT_CMPSC_ENH, +- S390_FEAT_DFP_ZONED_CONVERSION, +- S390_FEAT_STFLE_49, +- S390_FEAT_CONSTRAINT_TRANSACTIONAL_EXE, +- S390_FEAT_LOCAL_TLB_CLEARING, +- S390_FEAT_INTERLOCKED_ACCESS_2, +- S390_FEAT_STFLE_53, +- S390_FEAT_ENTROPY_ENC_COMP, +- S390_FEAT_MSA_EXT_5, +- S390_FEAT_MISC_INSTRUCTION_EXT, +- S390_FEAT_SEMAPHORE_ASSIST, +- S390_FEAT_TIME_SLICE_INSTRUMENTATION, +- S390_FEAT_MISC_INSTRUCTION_EXT3, +- S390_FEAT_RUNTIME_INSTRUMENTATION, +- S390_FEAT_ZPCI, +- S390_FEAT_ADAPTER_EVENT_NOTIFICATION, +- S390_FEAT_ADAPTER_INT_SUPPRESSION, +- S390_FEAT_TRANSACTIONAL_EXE, +- S390_FEAT_STORE_HYPERVISOR_INFO, +- S390_FEAT_ACCESS_EXCEPTION_FS_INDICATION, +- S390_FEAT_MSA_EXT_3, +- S390_FEAT_MSA_EXT_4, +- S390_FEAT_EDAT_2, +- S390_FEAT_DFP_PACKED_CONVERSION, +- S390_FEAT_PPA15, +- S390_FEAT_BPB, +- S390_FEAT_VECTOR, +- S390_FEAT_INSTRUCTION_EXEC_PROT, +- S390_FEAT_SIDE_EFFECT_ACCESS_ESOP2, +- S390_FEAT_GUARDED_STORAGE, +- S390_FEAT_VECTOR_PACKED_DECIMAL, +- S390_FEAT_VECTOR_ENH, +- S390_FEAT_MULTIPLE_EPOCH, +- S390_FEAT_TEST_PENDING_EXT_INTERRUPTION, +- S390_FEAT_INSERT_REFERENCE_BITS_MULT, +- S390_FEAT_MSA_EXT_8, +- S390_FEAT_CMM_NT, +- S390_FEAT_VECTOR_ENH2, +- S390_FEAT_ESORT_BASE, +- S390_FEAT_DEFLATE_BASE, +- S390_FEAT_VECTOR_PACKED_DECIMAL_ENH, +- S390_FEAT_MSA_EXT_9, +- S390_FEAT_ETOKEN, +- +- /* Sclp Conf Char */ +- S390_FEAT_SIE_GSLS, +- S390_FEAT_ESOP, +- S390_FEAT_HPMA2, +- S390_FEAT_SIE_KSS, +- +- /* Sclp Conf Char Ext */ +- S390_FEAT_SIE_64BSCAO, +- S390_FEAT_SIE_CMMA, +- S390_FEAT_SIE_PFMFI, +- S390_FEAT_SIE_IBS, +- +- /* Sclp Cpu */ +- S390_FEAT_SIE_F2, +- S390_FEAT_SIE_SKEY, +- S390_FEAT_SIE_GPERE, +- S390_FEAT_SIE_SIIF, +- S390_FEAT_SIE_SIGPIF, +- S390_FEAT_SIE_IB, +- S390_FEAT_SIE_CEI, +- +- /* Misc */ +- S390_FEAT_DAT_ENH_2, +- S390_FEAT_CMM, +- S390_FEAT_AP, +- +- /* PLO */ +- S390_FEAT_PLO_CL, +- S390_FEAT_PLO_CLG, +- S390_FEAT_PLO_CLGR, +- S390_FEAT_PLO_CLX, +- S390_FEAT_PLO_CS, +- S390_FEAT_PLO_CSG, +- S390_FEAT_PLO_CSGR, +- S390_FEAT_PLO_CSX, +- S390_FEAT_PLO_DCS, +- S390_FEAT_PLO_DCSG, +- S390_FEAT_PLO_DCSGR, +- S390_FEAT_PLO_DCSX, +- S390_FEAT_PLO_CSST, +- S390_FEAT_PLO_CSSTG, +- S390_FEAT_PLO_CSSTGR, +- S390_FEAT_PLO_CSSTX, +- S390_FEAT_PLO_CSDST, +- S390_FEAT_PLO_CSDSTG, +- S390_FEAT_PLO_CSDSTGR, +- S390_FEAT_PLO_CSDSTX, +- S390_FEAT_PLO_CSTST, +- S390_FEAT_PLO_CSTSTG, +- S390_FEAT_PLO_CSTSTGR, +- S390_FEAT_PLO_CSTSTX, +- +- /* PTFF */ +- S390_FEAT_PTFF_QTO, +- S390_FEAT_PTFF_QSI, +- S390_FEAT_PTFF_QPT, +- S390_FEAT_PTFF_QUI, +- S390_FEAT_PTFF_QTOU, +- S390_FEAT_PTFF_QSIE, +- S390_FEAT_PTFF_QTOUE, +- S390_FEAT_PTFF_STO, +- S390_FEAT_PTFF_STOU, +- S390_FEAT_PTFF_STOE, +- S390_FEAT_PTFF_STOUE, +- +- /* KMAC */ +- S390_FEAT_KMAC_DEA, +- S390_FEAT_KMAC_TDEA_128, +- S390_FEAT_KMAC_TDEA_192, +- S390_FEAT_KMAC_EDEA, +- S390_FEAT_KMAC_ETDEA_128, +- S390_FEAT_KMAC_ETDEA_192, +- S390_FEAT_KMAC_AES_128, +- S390_FEAT_KMAC_AES_192, +- S390_FEAT_KMAC_AES_256, +- S390_FEAT_KMAC_EAES_128, +- S390_FEAT_KMAC_EAES_192, +- S390_FEAT_KMAC_EAES_256, +- +- /* KMC */ +- S390_FEAT_KMC_DEA, +- S390_FEAT_KMC_TDEA_128, +- S390_FEAT_KMC_TDEA_192, +- S390_FEAT_KMC_EDEA, +- S390_FEAT_KMC_ETDEA_128, +- S390_FEAT_KMC_ETDEA_192, +- S390_FEAT_KMC_AES_128, +- S390_FEAT_KMC_AES_192, +- S390_FEAT_KMC_AES_256, +- S390_FEAT_KMC_EAES_128, +- S390_FEAT_KMC_EAES_192, +- S390_FEAT_KMC_EAES_256, +- S390_FEAT_KMC_PRNG, +- +- /* KM */ +- S390_FEAT_KM_DEA, +- S390_FEAT_KM_TDEA_128, +- S390_FEAT_KM_TDEA_192, +- S390_FEAT_KM_EDEA, +- S390_FEAT_KM_ETDEA_128, +- S390_FEAT_KM_ETDEA_192, +- S390_FEAT_KM_AES_128, +- S390_FEAT_KM_AES_192, +- S390_FEAT_KM_AES_256, +- S390_FEAT_KM_EAES_128, +- S390_FEAT_KM_EAES_192, +- S390_FEAT_KM_EAES_256, +- S390_FEAT_KM_XTS_AES_128, +- S390_FEAT_KM_XTS_AES_256, +- S390_FEAT_KM_XTS_EAES_128, +- S390_FEAT_KM_XTS_EAES_256, +- +- /* KIMD */ +- S390_FEAT_KIMD_SHA_1, +- S390_FEAT_KIMD_SHA_256, +- S390_FEAT_KIMD_SHA_512, +- S390_FEAT_KIMD_SHA3_224, +- S390_FEAT_KIMD_SHA3_256, +- S390_FEAT_KIMD_SHA3_384, +- S390_FEAT_KIMD_SHA3_512, +- S390_FEAT_KIMD_SHAKE_128, +- S390_FEAT_KIMD_SHAKE_256, +- S390_FEAT_KIMD_GHASH, +- +- /* KLMD */ +- S390_FEAT_KLMD_SHA_1, +- S390_FEAT_KLMD_SHA_256, +- S390_FEAT_KLMD_SHA_512, +- S390_FEAT_KLMD_SHA3_224, +- S390_FEAT_KLMD_SHA3_256, +- S390_FEAT_KLMD_SHA3_384, +- S390_FEAT_KLMD_SHA3_512, +- S390_FEAT_KLMD_SHAKE_128, +- S390_FEAT_KLMD_SHAKE_256, +- +- /* PCKMO */ +- S390_FEAT_PCKMO_EDEA, +- S390_FEAT_PCKMO_ETDEA_128, +- S390_FEAT_PCKMO_ETDEA_256, +- S390_FEAT_PCKMO_AES_128, +- S390_FEAT_PCKMO_AES_192, +- S390_FEAT_PCKMO_AES_256, +- S390_FEAT_PCKMO_ECC_P256, +- S390_FEAT_PCKMO_ECC_P384, +- S390_FEAT_PCKMO_ECC_P521, +- S390_FEAT_PCKMO_ECC_ED25519, +- S390_FEAT_PCKMO_ECC_ED448, +- +- /* KMCTR */ +- S390_FEAT_KMCTR_DEA, +- S390_FEAT_KMCTR_TDEA_128, +- S390_FEAT_KMCTR_TDEA_192, +- S390_FEAT_KMCTR_EDEA, +- S390_FEAT_KMCTR_ETDEA_128, +- S390_FEAT_KMCTR_ETDEA_192, +- S390_FEAT_KMCTR_AES_128, +- S390_FEAT_KMCTR_AES_192, +- S390_FEAT_KMCTR_AES_256, +- S390_FEAT_KMCTR_EAES_128, +- S390_FEAT_KMCTR_EAES_192, +- S390_FEAT_KMCTR_EAES_256, +- +- /* KMF */ +- S390_FEAT_KMF_DEA, +- S390_FEAT_KMF_TDEA_128, +- S390_FEAT_KMF_TDEA_192, +- S390_FEAT_KMF_EDEA, +- S390_FEAT_KMF_ETDEA_128, +- S390_FEAT_KMF_ETDEA_192, +- S390_FEAT_KMF_AES_128, +- S390_FEAT_KMF_AES_192, +- S390_FEAT_KMF_AES_256, +- S390_FEAT_KMF_EAES_128, +- S390_FEAT_KMF_EAES_192, +- S390_FEAT_KMF_EAES_256, +- +- /* KMO */ +- S390_FEAT_KMO_DEA, +- S390_FEAT_KMO_TDEA_128, +- S390_FEAT_KMO_TDEA_192, +- S390_FEAT_KMO_EDEA, +- S390_FEAT_KMO_ETDEA_128, +- S390_FEAT_KMO_ETDEA_192, +- S390_FEAT_KMO_AES_128, +- S390_FEAT_KMO_AES_192, +- S390_FEAT_KMO_AES_256, +- S390_FEAT_KMO_EAES_128, +- S390_FEAT_KMO_EAES_192, +- S390_FEAT_KMO_EAES_256, +- +- /* PCC */ +- S390_FEAT_PCC_CMAC_DEA, +- S390_FEAT_PCC_CMAC_TDEA_128, +- S390_FEAT_PCC_CMAC_TDEA_192, +- S390_FEAT_PCC_CMAC_ETDEA_128, +- S390_FEAT_PCC_CMAC_ETDEA_192, +- S390_FEAT_PCC_CMAC_TDEA, +- S390_FEAT_PCC_CMAC_AES_128, +- S390_FEAT_PCC_CMAC_AES_192, +- S390_FEAT_PCC_CMAC_AES_256, +- S390_FEAT_PCC_CMAC_EAES_128, +- S390_FEAT_PCC_CMAC_EAES_192, +- S390_FEAT_PCC_CMAC_EAES_256, +- S390_FEAT_PCC_XTS_AES_128, +- S390_FEAT_PCC_XTS_AES_256, +- S390_FEAT_PCC_XTS_EAES_128, +- S390_FEAT_PCC_XTS_EAES_256, +- S390_FEAT_PCC_SCALAR_MULT_P256, +- S390_FEAT_PCC_SCALAR_MULT_P384, +- S390_FEAT_PCC_SCALAR_MULT_P512, +- S390_FEAT_PCC_SCALAR_MULT_ED25519, +- S390_FEAT_PCC_SCALAR_MULT_ED448, +- S390_FEAT_PCC_SCALAR_MULT_X25519, +- S390_FEAT_PCC_SCALAR_MULT_X448, +- +- /* PPNO/PRNO */ +- S390_FEAT_PPNO_SHA_512_DRNG, +- S390_FEAT_PRNO_TRNG_QRTCR, +- S390_FEAT_PRNO_TRNG, +- +- /* KMA */ +- S390_FEAT_KMA_GCM_AES_128, +- S390_FEAT_KMA_GCM_AES_192, +- S390_FEAT_KMA_GCM_AES_256 , +- S390_FEAT_KMA_GCM_EAES_128, +- S390_FEAT_KMA_GCM_EAES_192, +- S390_FEAT_KMA_GCM_EAES_256, +- +- /* KDSA */ +- S390_FEAT_ECDSA_VERIFY_P256, +- S390_FEAT_ECDSA_VERIFY_P384, +- S390_FEAT_ECDSA_VERIFY_P512, +- S390_FEAT_ECDSA_SIGN_P256, +- S390_FEAT_ECDSA_SIGN_P384, +- S390_FEAT_ECDSA_SIGN_P512, +- S390_FEAT_EECDSA_SIGN_P256, +- S390_FEAT_EECDSA_SIGN_P384, +- S390_FEAT_EECDSA_SIGN_P512, +- S390_FEAT_EDDSA_VERIFY_ED25519, +- S390_FEAT_EDDSA_VERIFY_ED448, +- S390_FEAT_EDDSA_SIGN_ED25519, +- S390_FEAT_EDDSA_SIGN_ED448, +- S390_FEAT_EEDDSA_SIGN_ED25519, +- S390_FEAT_EEDDSA_SIGN_ED448, +- +- /* SORTL */ +- S390_FEAT_SORTL_SFLR, +- S390_FEAT_SORTL_SVLR, +- S390_FEAT_SORTL_32, +- S390_FEAT_SORTL_128, +- S390_FEAT_SORTL_F0, +- +- /* DEFLATE */ +- S390_FEAT_DEFLATE_GHDT, +- S390_FEAT_DEFLATE_CMPR, +- S390_FEAT_DEFLATE_XPND, +- S390_FEAT_DEFLATE_F0, +- ++ #include "cpu_features_def.inc.h" + S390_FEAT_MAX, + } S390Feat; ++#undef DEF_FEAT + + #endif /* TARGET_S390X_CPU_FEATURES_DEF_H */ +diff --git a/target/s390x/cpu_features_def.inc.h b/target/s390x/cpu_features_def.inc.h +new file mode 100644 +index 0000000..011ce4d +--- /dev/null ++++ b/target/s390x/cpu_features_def.inc.h +@@ -0,0 +1,369 @@ ++/* ++ * RAW s390x CPU feature definitions: ++ * ++ * DEF_FEAT(_FEAT, _NAME, _TYPE, _BIT, _DESC): ++ * - _FEAT: Feature (enum) name used internally (S390_FEAT_##_FEAT) ++ * - _NAME: Feature name exposed to the user. ++ * - _TYPE: Feature type (S390_FEAT_TYPE_##_TYPE). ++ * - _BIT: Feature bit number within feature type block (unused for MISC). ++ * - _DESC: Feature description, exposed to the user. ++ * ++ * Copyright IBM Corp. 2016, 2018 ++ * Copyright Red Hat, Inc. 2019 ++ * ++ * Author(s): Michael Mueller ++ * David Hildenbrand ++ * ++ * This work is licensed under the terms of the GNU GPL, version 2 or (at ++ * your option) any later version. See the COPYING file in the top-level ++ * directory. ++ */ ++ ++/* Features exposed via the STFL(E) instruction. */ ++DEF_FEAT(ESAN3, "esan3", STFL, 0, "Instructions marked as n3") ++DEF_FEAT(ZARCH, "zarch", STFL, 1, "z/Architecture architectural mode") ++DEF_FEAT(DAT_ENH, "dateh", STFL, 3, "DAT-enhancement facility") ++DEF_FEAT(IDTE_SEGMENT, "idtes", STFL, 4, "IDTE selective TLB segment-table clearing") ++DEF_FEAT(IDTE_REGION, "idter", STFL, 5, "IDTE selective TLB region-table clearing") ++DEF_FEAT(ASN_LX_REUSE, "asnlxr", STFL, 6, "ASN-and-LX reuse facility") ++DEF_FEAT(STFLE, "stfle", STFL, 7, "Store-facility-list-extended facility") ++DEF_FEAT(EDAT, "edat", STFL, 8, "Enhanced-DAT facility") ++DEF_FEAT(SENSE_RUNNING_STATUS, "srs", STFL, 9, "Sense-running-status facility") ++DEF_FEAT(CONDITIONAL_SSKE, "csske", STFL, 10, "Conditional-SSKE facility") ++DEF_FEAT(CONFIGURATION_TOPOLOGY, "ctop", STFL, 11, "Configuration-topology facility") ++DEF_FEAT(AP_QUERY_CONFIG_INFO, "apqci", STFL, 12, "Query AP Configuration Information facility") ++DEF_FEAT(IPTE_RANGE, "ipter", STFL, 13, "IPTE-range facility") ++DEF_FEAT(NONQ_KEY_SETTING, "nonqks", STFL, 14, "Nonquiescing key-setting facility") ++DEF_FEAT(AP_FACILITIES_TEST, "apft", STFL, 15, "AP Facilities Test facility") ++DEF_FEAT(EXTENDED_TRANSLATION_2, "etf2", STFL, 16, "Extended-translation facility 2") ++DEF_FEAT(MSA, "msa-base", STFL, 17, "Message-security-assist facility (excluding subfunctions)") ++DEF_FEAT(LONG_DISPLACEMENT, "ldisp", STFL, 18, "Long-displacement facility") ++DEF_FEAT(LONG_DISPLACEMENT_FAST, "ldisphp", STFL, 19, "Long-displacement facility has high performance") ++DEF_FEAT(HFP_MADDSUB, "hfpm", STFL, 20, "HFP-multiply-add/subtract facility") ++DEF_FEAT(EXTENDED_IMMEDIATE, "eimm", STFL, 21, "Extended-immediate facility") ++DEF_FEAT(EXTENDED_TRANSLATION_3, "etf3", STFL, 22, "Extended-translation facility 3") ++DEF_FEAT(HFP_UNNORMALIZED_EXT, "hfpue", STFL, 23, "HFP-unnormalized-extension facility") ++DEF_FEAT(ETF2_ENH, "etf2eh", STFL, 24, "ETF2-enhancement facility") ++DEF_FEAT(STORE_CLOCK_FAST, "stckf", STFL, 25, "Store-clock-fast facility") ++DEF_FEAT(PARSING_ENH, "parseh", STFL, 26, "Parsing-enhancement facility") ++DEF_FEAT(MOVE_WITH_OPTIONAL_SPEC, "mvcos", STFL, 27, "Move-with-optional-specification facility") ++DEF_FEAT(TOD_CLOCK_STEERING, "tods-base", STFL, 28, "TOD-clock-steering facility (excluding subfunctions)") ++DEF_FEAT(ETF3_ENH, "etf3eh", STFL, 30, "ETF3-enhancement facility") ++DEF_FEAT(EXTRACT_CPU_TIME, "ectg", STFL, 31, "Extract-CPU-time facility") ++DEF_FEAT(COMPARE_AND_SWAP_AND_STORE, "csst", STFL, 32, "Compare-and-swap-and-store facility") ++DEF_FEAT(COMPARE_AND_SWAP_AND_STORE_2, "csst2", STFL, 33, "Compare-and-swap-and-store facility 2") ++DEF_FEAT(GENERAL_INSTRUCTIONS_EXT, "ginste", STFL, 34, "General-instructions-extension facility") ++DEF_FEAT(EXECUTE_EXT, "exrl", STFL, 35, "Execute-extensions facility") ++DEF_FEAT(ENHANCED_MONITOR, "emon", STFL, 36, "Enhanced-monitor facility") ++DEF_FEAT(FLOATING_POINT_EXT, "fpe", STFL, 37, "Floating-point extension facility") ++DEF_FEAT(ORDER_PRESERVING_COMPRESSION, "opc", STFL, 38, "Order Preserving Compression facility") ++DEF_FEAT(SET_PROGRAM_PARAMETERS, "sprogp", STFL, 40, "Set-program-parameters facility") ++DEF_FEAT(FLOATING_POINT_SUPPPORT_ENH, "fpseh", STFL, 41, "Floating-point-support-enhancement facilities") ++DEF_FEAT(DFP, "dfp", STFL, 42, "DFP (decimal-floating-point) facility") ++DEF_FEAT(DFP_FAST, "dfphp", STFL, 43, "DFP (decimal-floating-point) facility has high performance") ++DEF_FEAT(PFPO, "pfpo", STFL, 44, "PFPO instruction") ++DEF_FEAT(STFLE_45, "stfle45", STFL, 45, "Various facilities introduced with z196") ++DEF_FEAT(CMPSC_ENH, "cmpsceh", STFL, 47, "CMPSC-enhancement facility") ++DEF_FEAT(DFP_ZONED_CONVERSION, "dfpzc", STFL, 48, "Decimal-floating-point zoned-conversion facility") ++DEF_FEAT(STFLE_49, "stfle49", STFL, 49, "Various facilities introduced with zEC12") ++DEF_FEAT(CONSTRAINT_TRANSACTIONAL_EXE, "cte", STFL, 50, "Constrained transactional-execution facility") ++DEF_FEAT(LOCAL_TLB_CLEARING, "ltlbc", STFL, 51, "Local-TLB-clearing facility") ++DEF_FEAT(INTERLOCKED_ACCESS_2, "iacc2", STFL, 52, "Interlocked-access facility 2") ++DEF_FEAT(STFLE_53, "stfle53", STFL, 53, "Various facilities introduced with z13") ++DEF_FEAT(ENTROPY_ENC_COMP, "eec", STFL, 54, "Entropy encoding compression facility") ++DEF_FEAT(MSA_EXT_5, "msa5-base", STFL, 57, "Message-security-assist-extension-5 facility (excluding subfunctions)") ++DEF_FEAT(MISC_INSTRUCTION_EXT, "minste2", STFL, 58, "Miscellaneous-instruction-extensions facility 2") ++DEF_FEAT(SEMAPHORE_ASSIST, "sema", STFL, 59, "Semaphore-assist facility") ++DEF_FEAT(TIME_SLICE_INSTRUMENTATION, "tsi", STFL, 60, "Time-slice Instrumentation facility") ++DEF_FEAT(MISC_INSTRUCTION_EXT3, "minste3", STFL, 61, "Miscellaneous-Instruction-Extensions Facility 3") ++DEF_FEAT(RUNTIME_INSTRUMENTATION, "ri", STFL, 64, "CPU runtime-instrumentation facility") ++DEF_FEAT(ZPCI, "zpci", STFL, 69, "z/PCI facility") ++DEF_FEAT(ADAPTER_EVENT_NOTIFICATION, "aen", STFL, 71, "General-purpose-adapter-event-notification facility") ++DEF_FEAT(ADAPTER_INT_SUPPRESSION, "ais", STFL, 72, "General-purpose-adapter-interruption-suppression facility") ++DEF_FEAT(TRANSACTIONAL_EXE, "te", STFL, 73, "Transactional-execution facility") ++DEF_FEAT(STORE_HYPERVISOR_INFO, "sthyi", STFL, 74, "Store-hypervisor-information facility") ++DEF_FEAT(ACCESS_EXCEPTION_FS_INDICATION, "aefsi", STFL, 75, "Access-exception-fetch/store-indication facility") ++DEF_FEAT(MSA_EXT_3, "msa3-base", STFL, 76, "Message-security-assist-extension-3 facility (excluding subfunctions)") ++DEF_FEAT(MSA_EXT_4, "msa4-base", STFL, 77, "Message-security-assist-extension-4 facility (excluding subfunctions)") ++DEF_FEAT(EDAT_2, "edat2", STFL, 78, "Enhanced-DAT facility 2") ++DEF_FEAT(DFP_PACKED_CONVERSION, "dfppc", STFL, 80, "Decimal-floating-point packed-conversion facility") ++DEF_FEAT(PPA15, "ppa15", STFL, 81, "PPA15 is installed") ++DEF_FEAT(BPB, "bpb", STFL, 82, "Branch prediction blocking") ++DEF_FEAT(VECTOR, "vx", STFL, 129, "Vector facility") ++DEF_FEAT(INSTRUCTION_EXEC_PROT, "iep", STFL, 130, "Instruction-execution-protection facility") ++DEF_FEAT(SIDE_EFFECT_ACCESS_ESOP2, "sea_esop2", STFL, 131, "Side-effect-access facility and Enhanced-suppression-on-protection facility 2") ++DEF_FEAT(GUARDED_STORAGE, "gs", STFL, 133, "Guarded-storage facility") ++DEF_FEAT(VECTOR_PACKED_DECIMAL, "vxpd", STFL, 134, "Vector packed decimal facility") ++DEF_FEAT(VECTOR_ENH, "vxeh", STFL, 135, "Vector enhancements facility") ++DEF_FEAT(MULTIPLE_EPOCH, "mepoch", STFL, 139, "Multiple-epoch facility") ++DEF_FEAT(TEST_PENDING_EXT_INTERRUPTION, "tpei", STFL, 144, "Test-pending-external-interruption facility") ++DEF_FEAT(INSERT_REFERENCE_BITS_MULT, "irbm", STFL, 145, "Insert-reference-bits-multiple facility") ++DEF_FEAT(MSA_EXT_8, "msa8-base", STFL, 146, "Message-security-assist-extension-8 facility (excluding subfunctions)") ++DEF_FEAT(CMM_NT, "cmmnt", STFL, 147, "CMM: ESSA-enhancement (no translate) facility") ++DEF_FEAT(VECTOR_ENH2, "vxeh2", STFL, 148, "Vector Enhancements facility 2") ++DEF_FEAT(ESORT_BASE, "esort-base", STFL, 150, "Enhanced-sort facility (excluding subfunctions)") ++DEF_FEAT(DEFLATE_BASE, "deflate-base", STFL, 151, "Deflate-conversion facility (excluding subfunctions)") ++DEF_FEAT(VECTOR_PACKED_DECIMAL_ENH, "vxpdeh", STFL, 152, "Vector-Packed-Decimal-Enhancement Facility") ++DEF_FEAT(MSA_EXT_9, "msa9-base", STFL, 155, "Message-security-assist-extension-9 facility (excluding subfunctions)") ++DEF_FEAT(ETOKEN, "etoken", STFL, 156, "Etoken facility") ++ ++/* Features exposed via SCLP SCCB Byte 80 - 98 (bit numbers relative to byte-80) */ ++DEF_FEAT(SIE_GSLS, "gsls", SCLP_CONF_CHAR, 40, "SIE: Guest-storage-limit-suppression facility") ++DEF_FEAT(ESOP, "esop", SCLP_CONF_CHAR, 46, "Enhanced-suppression-on-protection facility") ++DEF_FEAT(HPMA2, "hpma2", SCLP_CONF_CHAR, 90, "Host page management assist 2 Facility") /* 91-2 */ ++DEF_FEAT(SIE_KSS, "kss", SCLP_CONF_CHAR, 151, "SIE: Keyless-subset facility") /* 98-7 */ ++ ++/* Features exposed via SCLP SCCB Byte 116 - 119 (bit numbers relative to byte-116) */ ++DEF_FEAT(SIE_64BSCAO, "64bscao", SCLP_CONF_CHAR_EXT, 0, "SIE: 64-bit-SCAO facility") ++DEF_FEAT(SIE_CMMA, "cmma", SCLP_CONF_CHAR_EXT, 1, "SIE: Collaborative-memory-management assist") ++DEF_FEAT(SIE_PFMFI, "pfmfi", SCLP_CONF_CHAR_EXT, 9, "SIE: PFMF interpretation facility") ++DEF_FEAT(SIE_IBS, "ibs", SCLP_CONF_CHAR_EXT, 10, "SIE: Interlock-and-broadcast-suppression facility") ++ ++/* Features exposed via SCLP CPU info. */ ++DEF_FEAT(SIE_F2, "sief2", SCLP_CPU, 4, "SIE: interception format 2 (Virtual SIE)") ++DEF_FEAT(SIE_SKEY, "skey", SCLP_CPU, 5, "SIE: Storage-key facility") ++DEF_FEAT(SIE_GPERE, "gpereh", SCLP_CPU, 10, "SIE: Guest-PER enhancement facility") ++DEF_FEAT(SIE_SIIF, "siif", SCLP_CPU, 11, "SIE: Shared IPTE-interlock facility") ++DEF_FEAT(SIE_SIGPIF, "sigpif", SCLP_CPU, 12, "SIE: SIGP interpretation facility") ++DEF_FEAT(SIE_IB, "ib", SCLP_CPU, 42, "SIE: Intervention bypass facility") ++DEF_FEAT(SIE_CEI, "cei", SCLP_CPU, 43, "SIE: Conditional-external-interception facility") ++ ++/* ++ * Features exposed via no feature bit (but e.g., instruction sensing) ++ * -> the feature bit number is irrelavant ++ */ ++DEF_FEAT(DAT_ENH_2, "dateh2", MISC, 0, "DAT-enhancement facility 2") ++DEF_FEAT(CMM, "cmm", MISC, 0, "Collaborative-memory-management facility") ++DEF_FEAT(AP, "ap", MISC, 0, "AP instructions installed") ++ ++/* Features exposed via the PLO instruction. */ ++DEF_FEAT(PLO_CL, "plo-cl", PLO, 0, "PLO Compare and load (32 bit in general registers)") ++DEF_FEAT(PLO_CLG, "plo-clg", PLO, 1, "PLO Compare and load (64 bit in parameter list)") ++DEF_FEAT(PLO_CLGR, "plo-clgr", PLO, 2, "PLO Compare and load (32 bit in general registers)") ++DEF_FEAT(PLO_CLX, "plo-clx", PLO, 3, "PLO Compare and load (128 bit in parameter list)") ++DEF_FEAT(PLO_CS, "plo-cs", PLO, 4, "PLO Compare and swap (32 bit in general registers)") ++DEF_FEAT(PLO_CSG, "plo-csg", PLO, 5, "PLO Compare and swap (64 bit in parameter list)") ++DEF_FEAT(PLO_CSGR, "plo-csgr", PLO, 6, "PLO Compare and swap (32 bit in general registers)") ++DEF_FEAT(PLO_CSX, "plo-csx", PLO, 7, "PLO Compare and swap (128 bit in parameter list)") ++DEF_FEAT(PLO_DCS, "plo-dcs", PLO, 8, "PLO Double compare and swap (32 bit in general registers)") ++DEF_FEAT(PLO_DCSG, "plo-dcsg", PLO, 9, "PLO Double compare and swap (64 bit in parameter list)") ++DEF_FEAT(PLO_DCSGR, "plo-dcsgr", PLO, 10, "PLO Double compare and swap (32 bit in general registers)") ++DEF_FEAT(PLO_DCSX, "plo-dcsx", PLO, 11, "PLO Double compare and swap (128 bit in parameter list)") ++DEF_FEAT(PLO_CSST, "plo-csst", PLO, 12, "PLO Compare and swap and store (32 bit in general registers)") ++DEF_FEAT(PLO_CSSTG, "plo-csstg", PLO, 13, "PLO Compare and swap and store (64 bit in parameter list)") ++DEF_FEAT(PLO_CSSTGR, "plo-csstgr", PLO, 14, "PLO Compare and swap and store (32 bit in general registers)") ++DEF_FEAT(PLO_CSSTX, "plo-csstx", PLO, 15, "PLO Compare and swap and store (128 bit in parameter list)") ++DEF_FEAT(PLO_CSDST, "plo-csdst", PLO, 16, "PLO Compare and swap and double store (32 bit in general registers)") ++DEF_FEAT(PLO_CSDSTG, "plo-csdstg", PLO, 17, "PLO Compare and swap and double store (64 bit in parameter list)") ++DEF_FEAT(PLO_CSDSTGR, "plo-csdstgr", PLO, 18, "PLO Compare and swap and double store (32 bit in general registers)") ++DEF_FEAT(PLO_CSDSTX, "plo-csdstx", PLO, 19, "PLO Compare and swap and double store (128 bit in parameter list)") ++DEF_FEAT(PLO_CSTST, "plo-cstst", PLO, 20, "PLO Compare and swap and triple store (32 bit in general registers)") ++DEF_FEAT(PLO_CSTSTG, "plo-cststg", PLO, 21, "PLO Compare and swap and triple store (64 bit in parameter list)") ++DEF_FEAT(PLO_CSTSTGR, "plo-cststgr", PLO, 22, "PLO Compare and swap and triple store (32 bit in general registers)") ++DEF_FEAT(PLO_CSTSTX, "plo-cststx", PLO, 23, "PLO Compare and swap and triple store (128 bit in parameter list)") ++ ++/* Features exposed via the PTFF instruction. */ ++DEF_FEAT(PTFF_QTO, "ptff-qto", PTFF, 1, "PTFF Query TOD Offset") ++DEF_FEAT(PTFF_QSI, "ptff-qsi", PTFF, 2, "PTFF Query Steering Information") ++DEF_FEAT(PTFF_QPT, "ptff-qpc", PTFF, 3, "PTFF Query Physical Clock") ++DEF_FEAT(PTFF_QUI, "ptff-qui", PTFF, 4, "PTFF Query UTC Information") ++DEF_FEAT(PTFF_QTOU, "ptff-qtou", PTFF, 5, "PTFF Query TOD Offset User") ++DEF_FEAT(PTFF_QSIE, "ptff-qsie", PTFF, 10, "PTFF Query Steering Information Extended") ++DEF_FEAT(PTFF_QTOUE, "ptff-qtoue", PTFF, 13, "PTFF Query TOD Offset User Extended") ++DEF_FEAT(PTFF_STO, "ptff-sto", PTFF, 65, "PTFF Set TOD Offset") ++DEF_FEAT(PTFF_STOU, "ptff-stou", PTFF, 69, "PTFF Set TOD Offset User") ++DEF_FEAT(PTFF_STOE, "ptff-stoe", PTFF, 73, "PTFF Set TOD Offset Extended") ++DEF_FEAT(PTFF_STOUE, "ptff-stoue", PTFF, 77, "PTFF Set TOD Offset User Extended") ++ ++/* Features exposed via the KMAC instruction. */ ++DEF_FEAT(KMAC_DEA, "kmac-dea", KMAC, 1, "KMAC DEA") ++DEF_FEAT(KMAC_TDEA_128, "kmac-tdea-128", KMAC, 2, "KMAC TDEA-128") ++DEF_FEAT(KMAC_TDEA_192, "kmac-tdea-192", KMAC, 3, "KMAC TDEA-192") ++DEF_FEAT(KMAC_EDEA, "kmac-edea", KMAC, 9, "KMAC Encrypted-DEA") ++DEF_FEAT(KMAC_ETDEA_128, "kmac-etdea-128", KMAC, 10, "KMAC Encrypted-TDEA-128") ++DEF_FEAT(KMAC_ETDEA_192, "kmac-etdea-192", KMAC, 11, "KMAC Encrypted-TDEA-192") ++DEF_FEAT(KMAC_AES_128, "kmac-aes-128", KMAC, 18, "KMAC AES-128") ++DEF_FEAT(KMAC_AES_192, "kmac-aes-192", KMAC, 19, "KMAC AES-192") ++DEF_FEAT(KMAC_AES_256, "kmac-aes-256", KMAC, 20, "KMAC AES-256") ++DEF_FEAT(KMAC_EAES_128, "kmac-eaes-128", KMAC, 26, "KMAC Encrypted-AES-128") ++DEF_FEAT(KMAC_EAES_192, "kmac-eaes-192", KMAC, 27, "KMAC Encrypted-AES-192") ++DEF_FEAT(KMAC_EAES_256, "kmac-eaes-256", KMAC, 28, "KMAC Encrypted-AES-256") ++ ++/* Features exposed via the KMC instruction. */ ++DEF_FEAT(KMC_DEA, "kmc-dea", KMC, 1, "KMC DEA") ++DEF_FEAT(KMC_TDEA_128, "kmc-tdea-128", KMC, 2, "KMC TDEA-128") ++DEF_FEAT(KMC_TDEA_192, "kmc-tdea-192", KMC, 3, "KMC TDEA-192") ++DEF_FEAT(KMC_EDEA, "kmc-edea", KMC, 9, "KMC Encrypted-DEA") ++DEF_FEAT(KMC_ETDEA_128, "kmc-etdea-128", KMC, 10, "KMC Encrypted-TDEA-128") ++DEF_FEAT(KMC_ETDEA_192, "kmc-etdea-192", KMC, 11, "KMC Encrypted-TDEA-192") ++DEF_FEAT(KMC_AES_128, "kmc-aes-128", KMC, 18, "KMC AES-128") ++DEF_FEAT(KMC_AES_192, "kmc-aes-192", KMC, 19, "KMC AES-192") ++DEF_FEAT(KMC_AES_256, "kmc-aes-256", KMC, 20, "KMC AES-256") ++DEF_FEAT(KMC_EAES_128, "kmc-eaes-128", KMC, 26, "KMC Encrypted-AES-128") ++DEF_FEAT(KMC_EAES_192, "kmc-eaes-192", KMC, 27, "KMC Encrypted-AES-192") ++DEF_FEAT(KMC_EAES_256, "kmc-eaes-256", KMC, 28, "KMC Encrypted-AES-256") ++DEF_FEAT(KMC_PRNG, "kmc-prng", KMC, 67, "KMC PRNG") ++ ++/* Features exposed via the KM instruction. */ ++DEF_FEAT(KM_DEA, "km-dea", KM, 1, "KM DEA") ++DEF_FEAT(KM_TDEA_128, "km-tdea-128", KM, 2, "KM TDEA-128") ++DEF_FEAT(KM_TDEA_192, "km-tdea-192", KM, 3, "KM TDEA-192") ++DEF_FEAT(KM_EDEA, "km-edea", KM, 9, "KM Encrypted-DEA") ++DEF_FEAT(KM_ETDEA_128, "km-etdea-128", KM, 10, "KM Encrypted-TDEA-128") ++DEF_FEAT(KM_ETDEA_192, "km-etdea-192", KM, 11, "KM Encrypted-TDEA-192") ++DEF_FEAT(KM_AES_128, "km-aes-128", KM, 18, "KM AES-128") ++DEF_FEAT(KM_AES_192, "km-aes-192", KM, 19, "KM AES-192") ++DEF_FEAT(KM_AES_256, "km-aes-256", KM, 20, "KM AES-256") ++DEF_FEAT(KM_EAES_128, "km-eaes-128", KM, 26, "KM Encrypted-AES-128") ++DEF_FEAT(KM_EAES_192, "km-eaes-192", KM, 27, "KM Encrypted-AES-192") ++DEF_FEAT(KM_EAES_256, "km-eaes-256", KM, 28, "KM Encrypted-AES-256") ++DEF_FEAT(KM_XTS_AES_128, "km-xts-aes-128", KM, 50, "KM XTS-AES-128") ++DEF_FEAT(KM_XTS_AES_256, "km-xts-aes-256", KM, 52, "KM XTS-AES-256") ++DEF_FEAT(KM_XTS_EAES_128, "km-xts-eaes-128", KM, 58, "KM XTS-Encrypted-AES-128") ++DEF_FEAT(KM_XTS_EAES_256, "km-xts-eaes-256", KM, 60, "KM XTS-Encrypted-AES-256") ++ ++/* Features exposed via the KIMD instruction. */ ++DEF_FEAT(KIMD_SHA_1, "kimd-sha-1", KIMD, 1, "KIMD SHA-1") ++DEF_FEAT(KIMD_SHA_256, "kimd-sha-256", KIMD, 2, "KIMD SHA-256") ++DEF_FEAT(KIMD_SHA_512, "kimd-sha-512", KIMD, 3, "KIMD SHA-512") ++DEF_FEAT(KIMD_SHA3_224, "kimd-sha3-224", KIMD, 32, "KIMD SHA3-224") ++DEF_FEAT(KIMD_SHA3_256, "kimd-sha3-256", KIMD, 33, "KIMD SHA3-256") ++DEF_FEAT(KIMD_SHA3_384, "kimd-sha3-384", KIMD, 34, "KIMD SHA3-384") ++DEF_FEAT(KIMD_SHA3_512, "kimd-sha3-512", KIMD, 35, "KIMD SHA3-512") ++DEF_FEAT(KIMD_SHAKE_128, "kimd-shake-128", KIMD, 36, "KIMD SHAKE-128") ++DEF_FEAT(KIMD_SHAKE_256, "kimd-shake-256", KIMD, 37, "KIMD SHAKE-256") ++DEF_FEAT(KIMD_GHASH, "kimd-ghash", KIMD, 65, "KIMD GHASH") ++ ++/* Features exposed via the KLMD instruction. */ ++DEF_FEAT(KLMD_SHA_1, "klmd-sha-1", KLMD, 1, "KLMD SHA-1") ++DEF_FEAT(KLMD_SHA_256, "klmd-sha-256", KLMD, 2, "KLMD SHA-256") ++DEF_FEAT(KLMD_SHA_512, "klmd-sha-512", KLMD, 3, "KLMD SHA-512") ++DEF_FEAT(KLMD_SHA3_224, "klmd-sha3-224", KLMD, 32, "KLMD SHA3-224") ++DEF_FEAT(KLMD_SHA3_256, "klmd-sha3-256", KLMD, 33, "KLMD SHA3-256") ++DEF_FEAT(KLMD_SHA3_384, "klmd-sha3-384", KLMD, 34, "KLMD SHA3-384") ++DEF_FEAT(KLMD_SHA3_512, "klmd-sha3-512", KLMD, 35, "KLMD SHA3-512") ++DEF_FEAT(KLMD_SHAKE_128, "klmd-shake-128", KLMD, 36, "KLMD SHAKE-128") ++DEF_FEAT(KLMD_SHAKE_256, "klmd-shake-256", KLMD, 37, "KLMD SHAKE-256") ++ ++/* Features exposed via the PCKMO instruction. */ ++DEF_FEAT(PCKMO_EDEA, "pckmo-edea", PCKMO, 1, "PCKMO Encrypted-DEA-Key") ++DEF_FEAT(PCKMO_ETDEA_128, "pckmo-etdea-128", PCKMO, 2, "PCKMO Encrypted-TDEA-128-Key") ++DEF_FEAT(PCKMO_ETDEA_256, "pckmo-etdea-192", PCKMO, 3, "PCKMO Encrypted-TDEA-192-Key") ++DEF_FEAT(PCKMO_AES_128, "pckmo-aes-128", PCKMO, 18, "PCKMO Encrypted-AES-128-Key") ++DEF_FEAT(PCKMO_AES_192, "pckmo-aes-192", PCKMO, 19, "PCKMO Encrypted-AES-192-Key") ++DEF_FEAT(PCKMO_AES_256, "pckmo-aes-256", PCKMO, 20, "PCKMO Encrypted-AES-256-Key") ++DEF_FEAT(PCKMO_ECC_P256, "pckmo-ecc-p256", PCKMO, 32, "PCKMO Encrypt-ECC-P256-Key") ++DEF_FEAT(PCKMO_ECC_P384, "pckmo-ecc-p384", PCKMO, 33, "PCKMO Encrypt-ECC-P384-Key") ++DEF_FEAT(PCKMO_ECC_P521, "pckmo-ecc-p521", PCKMO, 34, "PCKMO Encrypt-ECC-P521-Key") ++DEF_FEAT(PCKMO_ECC_ED25519, "pckmo-ecc-ed25519", PCKMO, 40 , "PCKMO Encrypt-ECC-Ed25519-Key") ++DEF_FEAT(PCKMO_ECC_ED448, "pckmo-ecc-ed448", PCKMO, 41 , "PCKMO Encrypt-ECC-Ed448-Key") ++ ++/* Features exposed via the KMCTR instruction. */ ++DEF_FEAT(KMCTR_DEA, "kmctr-dea", KMCTR, 1, "KMCTR DEA") ++DEF_FEAT(KMCTR_TDEA_128, "kmctr-tdea-128", KMCTR, 2, "KMCTR TDEA-128") ++DEF_FEAT(KMCTR_TDEA_192, "kmctr-tdea-192", KMCTR, 3, "KMCTR TDEA-192") ++DEF_FEAT(KMCTR_EDEA, "kmctr-edea", KMCTR, 9, "KMCTR Encrypted-DEA") ++DEF_FEAT(KMCTR_ETDEA_128, "kmctr-etdea-128", KMCTR, 10, "KMCTR Encrypted-TDEA-128") ++DEF_FEAT(KMCTR_ETDEA_192, "kmctr-etdea-192", KMCTR, 11, "KMCTR Encrypted-TDEA-192") ++DEF_FEAT(KMCTR_AES_128, "kmctr-aes-128", KMCTR, 18, "KMCTR AES-128") ++DEF_FEAT(KMCTR_AES_192, "kmctr-aes-192", KMCTR, 19, "KMCTR AES-192") ++DEF_FEAT(KMCTR_AES_256, "kmctr-aes-256", KMCTR, 20, "KMCTR AES-256") ++DEF_FEAT(KMCTR_EAES_128, "kmctr-eaes-128", KMCTR, 26, "KMCTR Encrypted-AES-128") ++DEF_FEAT(KMCTR_EAES_192, "kmctr-eaes-192", KMCTR, 27, "KMCTR Encrypted-AES-192") ++DEF_FEAT(KMCTR_EAES_256, "kmctr-eaes-256", KMCTR, 28, "KMCTR Encrypted-AES-256") ++ ++/* Features exposed via the KMF instruction. */ ++DEF_FEAT(KMF_DEA, "kmf-dea", KMF, 1, "KMF DEA") ++DEF_FEAT(KMF_TDEA_128, "kmf-tdea-128", KMF, 2, "KMF TDEA-128") ++DEF_FEAT(KMF_TDEA_192, "kmf-tdea-192", KMF, 3, "KMF TDEA-192") ++DEF_FEAT(KMF_EDEA, "kmf-edea", KMF, 9, "KMF Encrypted-DEA") ++DEF_FEAT(KMF_ETDEA_128, "kmf-etdea-128", KMF, 10, "KMF Encrypted-TDEA-128") ++DEF_FEAT(KMF_ETDEA_192, "kmf-etdea-192", KMF, 11, "KMF Encrypted-TDEA-192") ++DEF_FEAT(KMF_AES_128, "kmf-aes-128", KMF, 18, "KMF AES-128") ++DEF_FEAT(KMF_AES_192, "kmf-aes-192", KMF, 19, "KMF AES-192") ++DEF_FEAT(KMF_AES_256, "kmf-aes-256", KMF, 20, "KMF AES-256") ++DEF_FEAT(KMF_EAES_128, "kmf-eaes-128", KMF, 26, "KMF Encrypted-AES-128") ++DEF_FEAT(KMF_EAES_192, "kmf-eaes-192", KMF, 27, "KMF Encrypted-AES-192") ++DEF_FEAT(KMF_EAES_256, "kmf-eaes-256", KMF, 28, "KMF Encrypted-AES-256") ++ ++/* Features exposed via the KMO instruction. */ ++DEF_FEAT(KMO_DEA, "kmo-dea", KMO, 1, "KMO DEA") ++DEF_FEAT(KMO_TDEA_128, "kmo-tdea-128", KMO, 2, "KMO TDEA-128") ++DEF_FEAT(KMO_TDEA_192, "kmo-tdea-192", KMO, 3, "KMO TDEA-192") ++DEF_FEAT(KMO_EDEA, "kmo-edea", KMO, 9, "KMO Encrypted-DEA") ++DEF_FEAT(KMO_ETDEA_128, "kmo-etdea-128", KMO, 10, "KMO Encrypted-TDEA-128") ++DEF_FEAT(KMO_ETDEA_192, "kmo-etdea-192", KMO, 11, "KMO Encrypted-TDEA-192") ++DEF_FEAT(KMO_AES_128, "kmo-aes-128", KMO, 18, "KMO AES-128") ++DEF_FEAT(KMO_AES_192, "kmo-aes-192", KMO, 19, "KMO AES-192") ++DEF_FEAT(KMO_AES_256, "kmo-aes-256", KMO, 20, "KMO AES-256") ++DEF_FEAT(KMO_EAES_128, "kmo-eaes-128", KMO, 26, "KMO Encrypted-AES-128") ++DEF_FEAT(KMO_EAES_192, "kmo-eaes-192", KMO, 27, "KMO Encrypted-AES-192") ++DEF_FEAT(KMO_EAES_256, "kmo-eaes-256", KMO, 28, "KMO Encrypted-AES-256") ++ ++/* Features exposed via the PCC instruction. */ ++DEF_FEAT(PCC_CMAC_DEA, "pcc-cmac-dea", PCC, 1, "PCC Compute-Last-Block-CMAC-Using-DEA") ++DEF_FEAT(PCC_CMAC_TDEA_128, "pcc-cmac-tdea-128", PCC, 2, "PCC Compute-Last-Block-CMAC-Using-TDEA-128") ++DEF_FEAT(PCC_CMAC_TDEA_192, "pcc-cmac-tdea-192", PCC, 3, "PCC Compute-Last-Block-CMAC-Using-TDEA-192") ++DEF_FEAT(PCC_CMAC_ETDEA_128, "pcc-cmac-edea", PCC, 9, "PCC Compute-Last-Block-CMAC-Using-Encrypted-DEA") ++DEF_FEAT(PCC_CMAC_ETDEA_192, "pcc-cmac-etdea-128", PCC, 10, "PCC Compute-Last-Block-CMAC-Using-Encrypted-TDEA-128") ++DEF_FEAT(PCC_CMAC_TDEA, "pcc-cmac-etdea-192", PCC, 11, "PCC Compute-Last-Block-CMAC-Using-EncryptedTDEA-192") ++DEF_FEAT(PCC_CMAC_AES_128, "pcc-cmac-aes-128", PCC, 18, "PCC Compute-Last-Block-CMAC-Using-AES-128") ++DEF_FEAT(PCC_CMAC_AES_192, "pcc-cmac-aes-192", PCC, 19, "PCC Compute-Last-Block-CMAC-Using-AES-192") ++DEF_FEAT(PCC_CMAC_AES_256, "pcc-cmac-eaes-256", PCC, 20, "PCC Compute-Last-Block-CMAC-Using-AES-256") ++DEF_FEAT(PCC_CMAC_EAES_128, "pcc-cmac-eaes-128", PCC, 26, "PCC Compute-Last-Block-CMAC-Using-Encrypted-AES-128") ++DEF_FEAT(PCC_CMAC_EAES_192, "pcc-cmac-eaes-192", PCC, 27, "PCC Compute-Last-Block-CMAC-Using-Encrypted-AES-192") ++DEF_FEAT(PCC_CMAC_EAES_256, "pcc-cmac-eaes-256", PCC, 28, "PCC Compute-Last-Block-CMAC-Using-Encrypted-AES-256") ++DEF_FEAT(PCC_XTS_AES_128, "pcc-xts-aes-128", PCC, 50, "PCC Compute-XTS-Parameter-Using-AES-128") ++DEF_FEAT(PCC_XTS_AES_256, "pcc-xts-aes-256", PCC, 52, "PCC Compute-XTS-Parameter-Using-AES-256") ++DEF_FEAT(PCC_XTS_EAES_128, "pcc-xts-eaes-128", PCC, 58, "PCC Compute-XTS-Parameter-Using-Encrypted-AES-128") ++DEF_FEAT(PCC_XTS_EAES_256, "pcc-xts-eaes-256", PCC, 60, "PCC Compute-XTS-Parameter-Using-Encrypted-AES-256") ++DEF_FEAT(PCC_SCALAR_MULT_P256, "pcc-scalar-mult-p256", PCC, 64, "PCC Scalar-Multiply-P256") ++DEF_FEAT(PCC_SCALAR_MULT_P384, "pcc-scalar-mult-p384", PCC, 65, "PCC Scalar-Multiply-P384") ++DEF_FEAT(PCC_SCALAR_MULT_P512, "pcc-scalar-mult-p521", PCC, 66, "PCC Scalar-Multiply-P521") ++DEF_FEAT(PCC_SCALAR_MULT_ED25519, "pcc-scalar-mult-ed25519", PCC, 72, "PCC Scalar-Multiply-Ed25519") ++DEF_FEAT(PCC_SCALAR_MULT_ED448, "pcc-scalar-mult-ed448", PCC, 73, "PCC Scalar-Multiply-Ed448") ++DEF_FEAT(PCC_SCALAR_MULT_X25519, "pcc-scalar-mult-x25519", PCC, 80, "PCC Scalar-Multiply-X25519") ++DEF_FEAT(PCC_SCALAR_MULT_X448, "pcc-scalar-mult-x448", PCC, 81, "PCC Scalar-Multiply-X448") ++ ++/* Features exposed via the PPNO/PRNO instruction. */ ++DEF_FEAT(PPNO_SHA_512_DRNG, "ppno-sha-512-drng", PPNO, 3, "PPNO SHA-512-DRNG") ++DEF_FEAT(PRNO_TRNG_QRTCR, "prno-trng-qrtcr", PPNO, 112, "PRNO TRNG-Query-Raw-to-Conditioned-Ratio") ++DEF_FEAT(PRNO_TRNG, "prno-trng", PPNO, 114, "PRNO TRNG") ++ ++/* Features exposed via the KMA instruction. */ ++DEF_FEAT(KMA_GCM_AES_128, "kma-gcm-aes-128", KMA, 18, "KMA GCM-AES-128") ++DEF_FEAT(KMA_GCM_AES_192, "kma-gcm-aes-192", KMA, 19, "KMA GCM-AES-192") ++DEF_FEAT(KMA_GCM_AES_256, "kma-gcm-aes-256", KMA, 20, "KMA GCM-AES-256") ++DEF_FEAT(KMA_GCM_EAES_128, "kma-gcm-eaes-128", KMA, 26, "KMA GCM-Encrypted-AES-128") ++DEF_FEAT(KMA_GCM_EAES_192, "kma-gcm-eaes-192", KMA, 27, "KMA GCM-Encrypted-AES-192") ++DEF_FEAT(KMA_GCM_EAES_256, "kma-gcm-eaes-256", KMA, 28, "KMA GCM-Encrypted-AES-256") ++ ++/* Features exposed via the KDSA instruction. */ ++DEF_FEAT(ECDSA_VERIFY_P256, "kdsa-ecdsa-verify-p256", KDSA, 1, "KDSA ECDSA-Verify-P256") ++DEF_FEAT(ECDSA_VERIFY_P384, "kdsa-ecdsa-verify-p384", KDSA, 2, "KDSA ECDSA-Verify-P384") ++DEF_FEAT(ECDSA_VERIFY_P512, "kdsa-ecdsa-verify-p521", KDSA, 3, "KDSA ECDSA-Verify-P521") ++DEF_FEAT(ECDSA_SIGN_P256, "kdsa-ecdsa-sign-p256", KDSA, 9, "KDSA ECDSA-Sign-P256") ++DEF_FEAT(ECDSA_SIGN_P384, "kdsa-ecdsa-sign-p384", KDSA, 10, "KDSA ECDSA-Sign-P384") ++DEF_FEAT(ECDSA_SIGN_P512, "kdsa-ecdsa-sign-p521", KDSA, 11, "KDSA ECDSA-Sign-P521") ++DEF_FEAT(EECDSA_SIGN_P256, "kdsa-eecdsa-sign-p256", KDSA, 17, "KDSA Encrypted-ECDSA-Sign-P256") ++DEF_FEAT(EECDSA_SIGN_P384, "kdsa-eecdsa-sign-p384", KDSA, 18, "KDSA Encrypted-ECDSA-Sign-P384") ++DEF_FEAT(EECDSA_SIGN_P512, "kdsa-eecdsa-sign-p521", KDSA, 19, "KDSA Encrypted-ECDSA-Sign-P521") ++DEF_FEAT(EDDSA_VERIFY_ED25519, "kdsa-eddsa-verify-ed25519", KDSA, 32, "KDSA EdDSA-Verify-Ed25519") ++DEF_FEAT(EDDSA_VERIFY_ED448, "kdsa-eddsa-verify-ed448", KDSA, 36, "KDSA EdDSA-Verify-Ed448") ++DEF_FEAT(EDDSA_SIGN_ED25519, "kdsa-eddsa-sign-ed25519", KDSA, 40, "KDSA EdDSA-Sign-Ed25519") ++DEF_FEAT(EDDSA_SIGN_ED448, "kdsa-eddsa-sign-ed448", KDSA, 44, "KDSA EdDSA-Sign-Ed448") ++DEF_FEAT(EEDDSA_SIGN_ED25519, "kdsa-eeddsa-sign-ed25519", KDSA, 48, "KDSA Encrypted-EdDSA-Sign-Ed25519") ++DEF_FEAT(EEDDSA_SIGN_ED448, "kdsa-eeddsa-sign-ed448", KDSA, 52, "KDSA Encrypted-EdDSA-Sign-Ed448") ++ ++/* Features exposed via the SORTL instruction. */ ++DEF_FEAT(SORTL_SFLR, "sortl-sflr", SORTL, 1, "SORTL SFLR") ++DEF_FEAT(SORTL_SVLR, "sortl-svlr", SORTL, 2, "SORTL SVLR") ++DEF_FEAT(SORTL_32, "sortl-32", SORTL, 130, "SORTL 32 input lists") ++DEF_FEAT(SORTL_128, "sortl-128", SORTL, 132, "SORTL 128 input lists") ++DEF_FEAT(SORTL_F0, "sortl-f0", SORTL, 192, "SORTL format 0 parameter-block") ++ ++/* Features exposed via the DEFLATE instruction. */ ++DEF_FEAT(DEFLATE_GHDT, "dfltcc-gdht", DFLTCC, 1, "DFLTCC GDHT") ++DEF_FEAT(DEFLATE_CMPR, "dfltcc-cmpr", DFLTCC, 2, "DFLTCC CMPR") ++DEF_FEAT(DEFLATE_XPND, "dfltcc-xpnd", DFLTCC, 4, "DFLTCC XPND") ++DEF_FEAT(DEFLATE_F0, "dfltcc-f0", DFLTCC, 192, "DFLTCC format 0 parameter-block") +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390x-cpumodel-Set-up-CPU-model-for-AQIC-interceptio.patch b/SOURCES/kvm-s390x-cpumodel-Set-up-CPU-model-for-AQIC-interceptio.patch new file mode 100644 index 0000000..7ef39c4 --- /dev/null +++ b/SOURCES/kvm-s390x-cpumodel-Set-up-CPU-model-for-AQIC-interceptio.patch @@ -0,0 +1,96 @@ +From ad53e96559cfe9d5f1b5518c3c925618e7e1bcc7 Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Wed, 18 Sep 2019 14:35:49 +0100 +Subject: [PATCH 10/22] s390x/cpumodel: Set up CPU model for AQIC interception + +RH-Author: Thomas Huth +Message-id: <20190918143549.16340-3-thuth@redhat.com> +Patchwork-id: 90760 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH 2/2] s390x/cpumodel: Set up CPU model for AQIC interception +Bugzilla: 1660909 +RH-Acked-by: David Hildenbrand +RH-Acked-by: Cornelia Huck +RH-Acked-by: Jens Freimann + +From: Pierre Morel + +Let's add support for the AP-Queue interruption facility to the CPU +model. + +The S390_FEAT_AP_QUEUE_INTERRUPT_CONTROL, CPU facility indicates +whether the PQAP instruction with the AQIC command is available +to the guest. +This feature will be enabled only if the AP instructions are +available on the linux host and AQIC facility is installed on +the host. + +This feature must be turned on from userspace to intercept AP +instructions on the KVM guest. The QEMU command line to turn +this feature on looks something like this: + + qemu-system-s390x ... -cpu xxx,apqi=on ... +or + ... -cpu host + +Right now AP pass-through devices do not support migration, +which means that we do not have to take care of migrating +the interrupt data: +virsh migrate apguest --live qemu+ssh://root@target.lan/system +error: Requested operation is not valid: domain has assigned non-USB host devices + +Signed-off-by: Pierre Morel +Reviewed-by: Tony Krowiak +Reviewed-by: Christian Borntraeger +Reviewed-by: Halil Pasic +Signed-off-by: Christian Borntraeger +[rebase to newest qemu and fixup description] +Message-Id: <20190705153249.12525-1-borntraeger@de.ibm.com> +Signed-off-by: Cornelia Huck +(cherry picked from commit 9ef2d19e5f5dfdebc9877c77951c28f25c74e000) + +Signed-off-by: Danilo C. L. de Paula +--- + target/s390x/cpu_features_def.inc.h | 1 + + target/s390x/cpu_models.c | 1 + + target/s390x/gen-features.c | 1 + + 3 files changed, 3 insertions(+) + +diff --git a/target/s390x/cpu_features_def.inc.h b/target/s390x/cpu_features_def.inc.h +index 011ce4d..dead061 100644 +--- a/target/s390x/cpu_features_def.inc.h ++++ b/target/s390x/cpu_features_def.inc.h +@@ -77,6 +77,7 @@ DEF_FEAT(SEMAPHORE_ASSIST, "sema", STFL, 59, "Semaphore-assist facility") + DEF_FEAT(TIME_SLICE_INSTRUMENTATION, "tsi", STFL, 60, "Time-slice Instrumentation facility") + DEF_FEAT(MISC_INSTRUCTION_EXT3, "minste3", STFL, 61, "Miscellaneous-Instruction-Extensions Facility 3") + DEF_FEAT(RUNTIME_INSTRUMENTATION, "ri", STFL, 64, "CPU runtime-instrumentation facility") ++DEF_FEAT(AP_QUEUE_INTERRUPT_CONTROL, "apqi", STFL, 65, "AP-Queue interruption facility") + DEF_FEAT(ZPCI, "zpci", STFL, 69, "z/PCI facility") + DEF_FEAT(ADAPTER_EVENT_NOTIFICATION, "aen", STFL, 71, "General-purpose-adapter-event-notification facility") + DEF_FEAT(ADAPTER_INT_SUPPRESSION, "ais", STFL, 72, "General-purpose-adapter-interruption-suppression facility") +diff --git a/target/s390x/cpu_models.c b/target/s390x/cpu_models.c +index 91afc6b..f16ef64 100644 +--- a/target/s390x/cpu_models.c ++++ b/target/s390x/cpu_models.c +@@ -792,6 +792,7 @@ static void check_consistency(const S390CPUModel *model) + { S390_FEAT_PTFF_QTOUE, S390_FEAT_MULTIPLE_EPOCH }, + { S390_FEAT_PTFF_STOE, S390_FEAT_MULTIPLE_EPOCH }, + { S390_FEAT_PTFF_STOUE, S390_FEAT_MULTIPLE_EPOCH }, ++ { S390_FEAT_AP_QUEUE_INTERRUPT_CONTROL, S390_FEAT_AP }, + }; + int i; + +diff --git a/target/s390x/gen-features.c b/target/s390x/gen-features.c +index 24d78e9..17bb04e 100644 +--- a/target/s390x/gen-features.c ++++ b/target/s390x/gen-features.c +@@ -519,6 +519,7 @@ static uint16_t full_GEN12_GA1[] = { + S390_FEAT_EDAT_2, + S390_FEAT_SIDE_EFFECT_ACCESS_ESOP2, + S390_FEAT_AP_QUERY_CONFIG_INFO, ++ S390_FEAT_AP_QUEUE_INTERRUPT_CONTROL, + S390_FEAT_AP_FACILITIES_TEST, + S390_FEAT_AP, + }; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-s390x-cpumodel-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-s390x-vfio-ap-Implement-hot-plug-unplug-of-vfio-ap-d.patch b/SOURCES/kvm-s390x-vfio-ap-Implement-hot-plug-unplug-of-vfio-ap-d.patch new file mode 100644 index 0000000..af41a46 --- /dev/null +++ b/SOURCES/kvm-s390x-vfio-ap-Implement-hot-plug-unplug-of-vfio-ap-d.patch @@ -0,0 +1,153 @@ +From e855a53f491f73e05e2b6542fb556ad80d45f89e Mon Sep 17 00:00:00 2001 +From: Thomas Huth +Date: Thu, 17 Oct 2019 08:43:01 +0100 +Subject: [PATCH 21/21] s390x/vfio-ap: Implement hot plug/unplug of vfio-ap + device + +RH-Author: Thomas Huth +Message-id: <20191017084301.8658-2-thuth@redhat.com> +Patchwork-id: 91819 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH 1/1] s390x/vfio-ap: Implement hot plug/unplug of vfio-ap device +Bugzilla: 1660906 +RH-Acked-by: David Hildenbrand +RH-Acked-by: Cornelia Huck +RH-Acked-by: John Snow + +From: Tony Krowiak + +Introduces hot plug/unplug support for the vfio-ap device. + +To hot plug a vfio-ap device using the QEMU device_add command: + + (qemu) device_add vfio-ap,sysfsdev=$path-to-mdev + + Where $path-to-mdev is the absolute path to the mediated matrix device + to which AP resources to be used by the guest have been assigned. + +A vfio-ap device can be hot plugged only if: + +1. A vfio-ap device has not been attached to the virtual machine's ap-bus + via the QEMU command line or a prior hot plug action. + +2. The guest was started with the CPU model feature for AP enabled + (e.g., -cpu host,ap=on) + +To hot unplug a vfio-ap device using the QEMU device_del command: + + (qemu) device_del vfio-ap,sysfsdev=$path-to-mdev + + Where $path-to-mdev is the absolute path to the mediated matrix device + specified when the vfio-ap device was attached to the virtual machine's + ap-bus. + +A vfio-ap device can be hot unplugged only if: + +1. A vfio-ap device has been attached to the virtual machine's ap-bus + via the QEMU command line or a prior hot plug action. + +2. The guest was started with the CPU model feature for AP enabled + (e.g., -cpu host,ap=on) + +Please note that a hot plug handler is not necessary for the vfio-ap device +because the AP matrix configuration for the guest is performed by the +kernel device driver when the vfio-ap device is realized. The vfio-ap device +represents a VFIO mediated device created in the host sysfs for use by a guest. +The mdev device is configured with an AP matrix (i.e., adapters and domains) via +its sysfs attribute interfaces prior to starting the guest or plugging a vfio-ap +device in. When the device is realized, a file descriptor is opened on the mdev +device which results in a callback to the vfio_ap kernel device driver. The +device driver then configures the AP matrix in the guest's SIE state description +from the AP matrix assigned via the mdev device's sysfs interfaces. The AP +devices will be created for the guest when the AP bus running on the guest +subsequently performs its periodic scan for AP devices. + +The qdev_simple_device_unplug_cb() callback function is used for the same +reaons; namely, the vfio_ap kernel device driver will perform the AP resource +de-configuration for the guest when the vfio-ap device is unplugged. When the +vfio-ap device is unrealized, the mdev device file descriptor is closed which +results in a callback to the vfio_ap kernel device driver. The device driver +then clears the AP matrix configuration in the guest's SIE state description +and resets all of the affected queues. The AP devices created for the guest +will be removed when the AP bus running on the guest subsequently performs +its periodic scan and finds there are no longer any AP resources assigned to the +guest. + +Signed-off-by: Tony Krowiak +Reviewed-by: Pierre Morel +Reviewed-by: David Hildenbrand +Reviewed-by: Halil Pasic +Tested-by: Pierre Morel +Message-Id: <1550519397-25359-2-git-send-email-akrowiak@linux.ibm.com> +[CH: adapt to changed qbus_set_hotplug_handler() signature] +Signed-off-by: Cornelia Huck +(cherry picked from commit 374b78e37029b05f7ee2f40d0d0aabf5b5b03ce0) + +Changed the qbus_set_hotplug_handler() line for RHEL: We do no have +commit 94d1cc5f03a in downstream, so no need for the OBJECT() cast here. + +Signed-off-by: Thomas Huth +Signed-off-by: Danilo C. L. de Paula +--- + hw/s390x/ap-bridge.c | 12 +++++++++++- + hw/vfio/ap.c | 2 +- + 2 files changed, 12 insertions(+), 2 deletions(-) + +diff --git a/hw/s390x/ap-bridge.c b/hw/s390x/ap-bridge.c +index 3795d30..25a0341 100644 +--- a/hw/s390x/ap-bridge.c ++++ b/hw/s390x/ap-bridge.c +@@ -39,6 +39,7 @@ static const TypeInfo ap_bus_info = { + void s390_init_ap(void) + { + DeviceState *dev; ++ BusState *bus; + + /* If no AP instructions then no need for AP bridge */ + if (!s390_has_feat(S390_FEAT_AP)) { +@@ -52,13 +53,18 @@ void s390_init_ap(void) + qdev_init_nofail(dev); + + /* Create bus on bridge device */ +- qbus_create(TYPE_AP_BUS, dev, TYPE_AP_BUS); ++ bus = qbus_create(TYPE_AP_BUS, dev, TYPE_AP_BUS); ++ ++ /* Enable hotplugging */ ++ qbus_set_hotplug_handler(bus, dev, &error_abort); + } + + static void ap_bridge_class_init(ObjectClass *oc, void *data) + { + DeviceClass *dc = DEVICE_CLASS(oc); ++ HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc); + ++ hc->unplug = qdev_simple_device_unplug_cb; + set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); + } + +@@ -67,6 +73,10 @@ static const TypeInfo ap_bridge_info = { + .parent = TYPE_SYS_BUS_DEVICE, + .instance_size = 0, + .class_init = ap_bridge_class_init, ++ .interfaces = (InterfaceInfo[]) { ++ { TYPE_HOTPLUG_HANDLER }, ++ { } ++ } + }; + + static void ap_register(void) +diff --git a/hw/vfio/ap.c b/hw/vfio/ap.c +index 3962bb7..a899f8e 100644 +--- a/hw/vfio/ap.c ++++ b/hw/vfio/ap.c +@@ -161,7 +161,7 @@ static void vfio_ap_class_init(ObjectClass *klass, void *data) + set_bit(DEVICE_CATEGORY_MISC, dc->categories); + dc->realize = vfio_ap_realize; + dc->unrealize = vfio_ap_unrealize; +- dc->hotpluggable = false; ++ dc->hotpluggable = true; + dc->reset = vfio_ap_reset; + dc->bus_type = TYPE_AP_BUS; + } +-- +1.8.3.1 + diff --git a/SOURCES/kvm-scsi-disk-Acquire-the-AioContext-in-scsi_-_realize.patch b/SOURCES/kvm-scsi-disk-Acquire-the-AioContext-in-scsi_-_realize.patch new file mode 100644 index 0000000..0168154 --- /dev/null +++ b/SOURCES/kvm-scsi-disk-Acquire-the-AioContext-in-scsi_-_realize.patch @@ -0,0 +1,191 @@ +From f211540f531d850eb336154469d936b87398d877 Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Thu, 6 Jun 2019 19:15:23 +0100 +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: 1673396 1673401 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Kevin Wolf + +From: Alberto Garcia + +This fixes a crash when attaching two disks with the same blockdev to +a SCSI device that is using iothreads. Test case included. + +Signed-off-by: Alberto Garcia +Signed-off-by: Kevin Wolf +(cherry picked from commit 3ff35ba391134e4e43ab96152deb38a62e62f858) +[Trivial conflict in hw/scsi/scsi-disk.c due to lack of commit +51f43d5792e resolved] +Signed-off-by: Markus Armbruster + +Signed-off-by: Danilo C. L. de Paula +--- + hw/scsi/scsi-disk.c | 23 ++++++++++++++++++++--- + tests/qemu-iotests/240 | 18 ++++++++++++++++++ + tests/qemu-iotests/240.out | 16 ++++++++++++++++ + 3 files changed, 54 insertions(+), 3 deletions(-) + +diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c +index a20ef91..08da23d 100644 +--- a/hw/scsi/scsi-disk.c ++++ b/hw/scsi/scsi-disk.c +@@ -2378,10 +2378,13 @@ static void scsi_realize(SCSIDevice *dev, Error **errp) + static void scsi_hd_realize(SCSIDevice *dev, Error **errp) + { + SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev); ++ AioContext *ctx = NULL; + /* can happen for devices without drive. The error message for missing + * backend will be issued in scsi_realize + */ + if (s->qdev.conf.blk) { ++ ctx = blk_get_aio_context(s->qdev.conf.blk); ++ aio_context_acquire(ctx); + blkconf_blocksizes(&s->qdev.conf); + } + s->qdev.blocksize = s->qdev.conf.logical_block_size; +@@ -2390,11 +2393,15 @@ static void scsi_hd_realize(SCSIDevice *dev, Error **errp) + s->product = g_strdup("QEMU HARDDISK"); + } + scsi_realize(&s->qdev, errp); ++ if (ctx) { ++ aio_context_release(ctx); ++ } + } + + static void scsi_cd_realize(SCSIDevice *dev, Error **errp) + { + SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev); ++ AioContext *ctx; + int ret; + + if (!dev->conf.blk) { +@@ -2405,6 +2412,8 @@ static void scsi_cd_realize(SCSIDevice *dev, Error **errp) + assert(ret == 0); + } + ++ ctx = blk_get_aio_context(dev->conf.blk); ++ aio_context_acquire(ctx); + s->qdev.blocksize = 2048; + s->qdev.type = TYPE_ROM; + s->features |= 1 << SCSI_DISK_F_REMOVABLE; +@@ -2412,6 +2421,7 @@ static void scsi_cd_realize(SCSIDevice *dev, Error **errp) + s->product = g_strdup("QEMU CD-ROM"); + } + scsi_realize(&s->qdev, errp); ++ aio_context_release(ctx); + } + + static void scsi_disk_realize(SCSIDevice *dev, Error **errp) +@@ -2550,6 +2560,7 @@ static int get_device_type(SCSIDiskState *s) + static void scsi_block_realize(SCSIDevice *dev, Error **errp) + { + SCSIDiskState *s = DO_UPCAST(SCSIDiskState, qdev, dev); ++ AioContext *ctx; + int sg_version; + int rc; + +@@ -2558,6 +2569,9 @@ static void scsi_block_realize(SCSIDevice *dev, Error **errp) + return; + } + ++ ctx = blk_get_aio_context(s->qdev.conf.blk); ++ aio_context_acquire(ctx); ++ + /* check we are using a driver managing SG_IO (version 3 and after) */ + rc = blk_ioctl(s->qdev.conf.blk, SG_GET_VERSION_NUM, &sg_version); + if (rc < 0) { +@@ -2565,18 +2579,18 @@ static void scsi_block_realize(SCSIDevice *dev, Error **errp) + if (rc != -EPERM) { + error_append_hint(errp, "Is this a SCSI device?\n"); + } +- return; ++ goto out; + } + if (sg_version < 30000) { + error_setg(errp, "scsi generic interface too old"); +- return; ++ goto out; + } + + /* get device type from INQUIRY data */ + rc = get_device_type(s); + if (rc < 0) { + error_setg(errp, "INQUIRY failed"); +- return; ++ goto out; + } + + /* Make a guess for the block size, we'll fix it when the guest sends. +@@ -2596,6 +2610,9 @@ static void scsi_block_realize(SCSIDevice *dev, Error **errp) + + scsi_realize(&s->qdev, errp); + scsi_generic_read_device_inquiry(&s->qdev); ++ ++out: ++ aio_context_release(ctx); + } + + typedef struct SCSIBlockReq { +diff --git a/tests/qemu-iotests/240 b/tests/qemu-iotests/240 +index ead7ee0..5d499c9 100755 +--- a/tests/qemu-iotests/240 ++++ b/tests/qemu-iotests/240 +@@ -83,6 +83,24 @@ run_qemu < +Date: Wed, 24 Jul 2019 15:53:34 +0100 +Subject: [PATCH 09/14] slirp: check sscanf result when emulating ident +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Philippe Mathieu-Daudé +Message-id: <20190724155337.25303-2-philmd@redhat.com> +Patchwork-id: 89675 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v2 1/4] slirp: check sscanf result when emulating ident +Bugzilla: 1727642 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Marc-André Lureau +RH-Acked-by: Thomas Huth + +From: William Bowling + +When emulating ident in tcp_emu, if the strchr checks passed but the +sscanf check failed, two uninitialized variables would be copied and +sent in the reply, so move this code inside the if(sscanf()) clause. + +Signed-off-by: William Bowling +Cc: qemu-stable@nongnu.org +Cc: secalert@redhat.com +Message-Id: <1551476756-25749-1-git-send-email-will@wbowling.info> +Signed-off-by: Samuel Thibault +Reviewed-by: Philippe Mathieu-Daudé +(cherry picked from commit d3222975c7d6cda9e25809dea05241188457b113) +Fixes: CVE-2019-9824 +Signed-off-by: Philippe Mathieu-Daudé +Signed-off-by: Danilo C. L. de Paula +--- + slirp/tcp_subr.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/slirp/tcp_subr.c b/slirp/tcp_subr.c +index 1c7eb28..af1b3eb 100644 +--- a/slirp/tcp_subr.c ++++ b/slirp/tcp_subr.c +@@ -665,12 +665,12 @@ tcp_emu(struct socket *so, struct mbuf *m) + break; + } + } ++ so_rcv->sb_cc = snprintf(so_rcv->sb_data, ++ so_rcv->sb_datalen, ++ "%d,%d\r\n", n1, n2); ++ so_rcv->sb_rptr = so_rcv->sb_data; ++ so_rcv->sb_wptr = so_rcv->sb_data + so_rcv->sb_cc; + } +- so_rcv->sb_cc = snprintf(so_rcv->sb_data, +- so_rcv->sb_datalen, +- "%d,%d\r\n", n1, n2); +- so_rcv->sb_rptr = so_rcv->sb_data; +- so_rcv->sb_wptr = so_rcv->sb_data + so_rcv->sb_cc; + } + m_free(m); + return 0; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-slirp-disable-tcp_emu.patch b/SOURCES/kvm-slirp-disable-tcp_emu.patch new file mode 100644 index 0000000..aa807b1 --- /dev/null +++ b/SOURCES/kvm-slirp-disable-tcp_emu.patch @@ -0,0 +1,70 @@ +From 3bb5804776e5141690ff6fbb5b07b2a0307391ee Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= +Date: Tue, 28 Jan 2020 13:32:53 +0000 +Subject: [PATCH 1/2] slirp: disable tcp_emu() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Marc-André Lureau +Message-id: <20200128133253.794107-2-marcandre.lureau@redhat.com> +Patchwork-id: 93569 +O-Subject: [RHEL-8.2.0 qemu-kvm + RHEL-7.7 qemu-kvm + RHEL-6.11 qemu-kvm PATCH 1/1] slirp: disable tcp_emu() +Bugzilla: 1791677 +RH-Acked-by: Danilo de Paula +RH-Acked-by: Eduardo Habkost +RH-Acked-by: Stefan Hajnoczi + +Since libslirp 4.1, tcp_emu() is disabled by default because it is +known to cause several CVEs and is not useful today in most +cases. Qemu upstream doesn't have an option to enable it back at this +point, it's not clear if we ever want to expose that option anyway. + +See also upstream commit 07c2a44b67e ("emu: disable by default") + +Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1791677 +Signed-off-by: Marc-André Lureau +Signed-off-by: Danilo C. L. de Paula +--- + slirp/tcp_subr.c | 4 ++-- + slirp/udp.c | 2 +- + 2 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/slirp/tcp_subr.c b/slirp/tcp_subr.c +index b95ba23..ac14366 100644 +--- a/slirp/tcp_subr.c ++++ b/slirp/tcp_subr.c +@@ -568,7 +568,7 @@ tcp_tos(struct socket *so) + while(tcptos[i].tos) { + if ((tcptos[i].fport && (ntohs(so->so_fport) == tcptos[i].fport)) || + (tcptos[i].lport && (ntohs(so->so_lport) == tcptos[i].lport))) { +- so->so_emu = tcptos[i].emu; ++ so->so_emu = 0; /* disabled */ + return tcptos[i].tos; + } + i++; +@@ -578,7 +578,7 @@ tcp_tos(struct socket *so) + for (emup = tcpemu; emup; emup = emup->next) { + if ((emup->fport && (ntohs(so->so_fport) == emup->fport)) || + (emup->lport && (ntohs(so->so_lport) == emup->lport))) { +- so->so_emu = emup->emu; ++ so->so_emu = 0; /* disabled */ + return emup->tos; + } + } +diff --git a/slirp/udp.c b/slirp/udp.c +index 227d779..f5f5548 100644 +--- a/slirp/udp.c ++++ b/slirp/udp.c +@@ -313,7 +313,7 @@ udp_tos(struct socket *so) + while(udptos[i].tos) { + if ((udptos[i].fport && ntohs(so->so_fport) == udptos[i].fport) || + (udptos[i].lport && ntohs(so->so_lport) == udptos[i].lport)) { +- so->so_emu = udptos[i].emu; ++ so->so_emu = 0; /* disabled */ + return udptos[i].tos; + } + i++; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-slirp-don-t-manipulate-so_rcv-in-tcp_emu.patch b/SOURCES/kvm-slirp-don-t-manipulate-so_rcv-in-tcp_emu.patch new file mode 100644 index 0000000..0ae23ce --- /dev/null +++ b/SOURCES/kvm-slirp-don-t-manipulate-so_rcv-in-tcp_emu.patch @@ -0,0 +1,131 @@ +From e63645b8e4335e71721defc01db16db7cebe09b8 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Wed, 24 Jul 2019 15:53:37 +0100 +Subject: [PATCH 12/14] slirp: don't manipulate so_rcv in tcp_emu() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Philippe Mathieu-Daudé +Message-id: <20190724155337.25303-5-philmd@redhat.com> +Patchwork-id: 89676 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v2 4/4] slirp: don't manipulate so_rcv in tcp_emu() +Bugzilla: 1727642 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Marc-André Lureau +RH-Acked-by: Thomas Huth + +From: Marc-André Lureau + +For some reason, EMU_IDENT is not like other "emulated" protocols and +tries to reconstitute the original buffer, if it came in multiple +packets. Unfortunately, it does so wrongly, as it doesn't respect the +sbuf circular buffer appending rules, nor does it maintain some of the +invariants (rptr is incremented without bounds, etc): this leads to +further memory corruption revealed by ASAN or various malloc +errors. Furthermore, the so_rcv buffer is regularly flushed, so there +is no guarantee that buffer reconstruction will do what is expected. + +Instead, do what the function comment says: "XXX Assumes the whole +command came in one packet", and don't touch so_rcv. + +Related to: https://bugzilla.redhat.com/show_bug.cgi?id=1664205 + +Cc: Prasad J Pandit +Signed-off-by: Marc-André Lureau + +(cherry picked from libslirp commit +9da0da837780f825b5db31db6620492f8b7cd5d6) +[ MA - backported with style conflicts, and without qemu commit +a7104eda7dab99d0cdbd3595c211864cba415905 which is unnecessary with +this patch ] +Signed-off-by: Marc-André Lureau +Signed-off-by: Philippe Mathieu-Daudé + +Signed-off-by: Danilo C. L. de Paula +--- + slirp/tcp_subr.c | 62 ++++++++++++++++++++++++-------------------------------- + 1 file changed, 27 insertions(+), 35 deletions(-) + +diff --git a/slirp/tcp_subr.c b/slirp/tcp_subr.c +index e245e0d..0152f72 100644 +--- a/slirp/tcp_subr.c ++++ b/slirp/tcp_subr.c +@@ -636,47 +636,39 @@ tcp_emu(struct socket *so, struct mbuf *m) + struct socket *tmpso; + struct sockaddr_in addr; + socklen_t addrlen = sizeof(struct sockaddr_in); +- struct sbuf *so_rcv = &so->so_rcv; ++ char *eol = g_strstr_len(m->m_data, m->m_len, "\r\n"); + +- if (m->m_len > so_rcv->sb_datalen +- - (so_rcv->sb_wptr - so_rcv->sb_data)) { +- return 1; ++ if (!eol) { ++ return 1; + } + +- memcpy(so_rcv->sb_wptr, m->m_data, m->m_len); +- so_rcv->sb_wptr += m->m_len; +- so_rcv->sb_rptr += m->m_len; +- m_inc(m, m->m_len + 1); +- m->m_data[m->m_len] = 0; /* NULL terminate */ +- if (strchr(m->m_data, '\r') || strchr(m->m_data, '\n')) { +- if (sscanf(so_rcv->sb_data, "%u%*[ ,]%u", &n1, &n2) == 2) { +- HTONS(n1); +- HTONS(n2); +- /* n2 is the one on our host */ +- for (tmpso = slirp->tcb.so_next; +- tmpso != &slirp->tcb; +- tmpso = tmpso->so_next) { +- if (tmpso->so_laddr.s_addr == so->so_laddr.s_addr && +- tmpso->so_lport == n2 && +- tmpso->so_faddr.s_addr == so->so_faddr.s_addr && +- tmpso->so_fport == n1) { +- if (getsockname(tmpso->s, +- (struct sockaddr *)&addr, &addrlen) == 0) +- n2 = addr.sin_port; +- break; +- } ++ *eol = '\0'; ++ if (sscanf(m->m_data, "%u%*[ ,]%u", &n1, &n2) == 2) { ++ HTONS(n1); ++ HTONS(n2); ++ /* n2 is the one on our host */ ++ for (tmpso = slirp->tcb.so_next; tmpso != &slirp->tcb; ++ tmpso = tmpso->so_next) { ++ if (tmpso->so_laddr.s_addr == so->so_laddr.s_addr && ++ tmpso->so_lport == n2 && ++ tmpso->so_faddr.s_addr == so->so_faddr.s_addr && ++ tmpso->so_fport == n1) { ++ if (getsockname(tmpso->s, (struct sockaddr *)&addr, ++ &addrlen) == 0) ++ n2 = addr.sin_port; ++ break; + } +- NTOHS(n1); +- NTOHS(n2); +- so_rcv->sb_cc = snprintf(so_rcv->sb_data, +- so_rcv->sb_datalen, +- "%d,%d\r\n", n1, n2); +- so_rcv->sb_rptr = so_rcv->sb_data; +- so_rcv->sb_wptr = so_rcv->sb_data + so_rcv->sb_cc; + } ++ NTOHS(n1); ++ NTOHS(n2); ++ m_inc(m, snprintf(NULL, 0, "%d,%d\r\n", n1, n2) + 1); ++ m->m_len = snprintf(m->m_data, M_ROOM(m), "%d,%d\r\n", n1, n2); ++ assert(m->m_len < M_ROOM(m)); ++ } else { ++ *eol = '\r'; + } +- m_free(m); +- return 0; ++ ++ return 1; + } + + case EMU_FTP: /* ftp */ +-- +1.8.3.1 + diff --git a/SOURCES/kvm-slirp-ensure-there-is-enough-space-in-mbuf-to-null-t.patch b/SOURCES/kvm-slirp-ensure-there-is-enough-space-in-mbuf-to-null-t.patch new file mode 100644 index 0000000..96e39d3 --- /dev/null +++ b/SOURCES/kvm-slirp-ensure-there-is-enough-space-in-mbuf-to-null-t.patch @@ -0,0 +1,71 @@ +From ad30988fde29143951447e7f973918eaa09c448c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Wed, 24 Jul 2019 15:53:36 +0100 +Subject: [PATCH 11/14] slirp: ensure there is enough space in mbuf to + null-terminate +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Philippe Mathieu-Daudé +Message-id: <20190724155337.25303-4-philmd@redhat.com> +Patchwork-id: 89678 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v2 3/4] slirp: ensure there is enough space in mbuf to null-terminate +Bugzilla: 1727642 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Marc-André Lureau +RH-Acked-by: Thomas Huth + +From: Marc-André Lureau + +Prevents from buffer overflows. +Related to: https://bugzilla.redhat.com/show_bug.cgi?id=1664205 + +Cc: Prasad J Pandit +Signed-off-by: Marc-André Lureau + +(cherry picked from libslirp commit +306fef58b54d793ba4b259728c21322765bda917) + +[ MA - backported with style conflicts fixes ] +Signed-off-by: Marc-André Lureau +Signed-off-by: Miroslav Rezanina +(cherry picked from commit e80c12dfdbde349dcd225771a4801b47be0b3b5f) +Signed-off-by: Philippe Mathieu-Daudé + +Signed-off-by: Danilo C. L. de Paula +--- + slirp/tcp_subr.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/slirp/tcp_subr.c b/slirp/tcp_subr.c +index 393447d..e245e0d 100644 +--- a/slirp/tcp_subr.c ++++ b/slirp/tcp_subr.c +@@ -646,6 +646,7 @@ tcp_emu(struct socket *so, struct mbuf *m) + memcpy(so_rcv->sb_wptr, m->m_data, m->m_len); + so_rcv->sb_wptr += m->m_len; + so_rcv->sb_rptr += m->m_len; ++ m_inc(m, m->m_len + 1); + m->m_data[m->m_len] = 0; /* NULL terminate */ + if (strchr(m->m_data, '\r') || strchr(m->m_data, '\n')) { + if (sscanf(so_rcv->sb_data, "%u%*[ ,]%u", &n1, &n2) == 2) { +@@ -679,6 +680,7 @@ tcp_emu(struct socket *so, struct mbuf *m) + } + + case EMU_FTP: /* ftp */ ++ m_inc(m, m->m_len + 1); + *(m->m_data+m->m_len) = 0; /* NUL terminate for strstr */ + if ((bptr = (char *)strstr(m->m_data, "ORT")) != NULL) { + /* +@@ -776,6 +778,7 @@ tcp_emu(struct socket *so, struct mbuf *m) + /* + * Need to emulate DCC CHAT, DCC SEND and DCC MOVE + */ ++ m_inc(m, m->m_len + 1); + *(m->m_data+m->m_len) = 0; /* NULL terminate the string for strstr */ + if ((bptr = (char *)strstr(m->m_data, "DCC")) == NULL) + return 1; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-slirp-fix-big-little-endian-conversion-in-ident-prot.patch b/SOURCES/kvm-slirp-fix-big-little-endian-conversion-in-ident-prot.patch new file mode 100644 index 0000000..38c4c71 --- /dev/null +++ b/SOURCES/kvm-slirp-fix-big-little-endian-conversion-in-ident-prot.patch @@ -0,0 +1,50 @@ +From f4157e1c90e8986d95a57bf00cc8c0e297869c35 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Wed, 24 Jul 2019 15:53:35 +0100 +Subject: [PATCH 10/14] slirp: fix big/little endian conversion in ident + protocol +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Philippe Mathieu-Daudé +Message-id: <20190724155337.25303-3-philmd@redhat.com> +Patchwork-id: 89674 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v2 2/4] slirp: fix big/little endian conversion in ident protocol +Bugzilla: 1727642 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Marc-André Lureau +RH-Acked-by: Thomas Huth + +From: Samuel Thibault + +Signed-off-by: Samuel Thibault +Reviewed-by: Philippe Mathieu-Daudé +(cherry picked from commit 1fd71067dae501f1c78618e9583c6cc72db0cfa6) +Signed-off-by: Philippe Mathieu-Daudé +Signed-off-by: Danilo C. L. de Paula +--- + slirp/tcp_subr.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/slirp/tcp_subr.c b/slirp/tcp_subr.c +index af1b3eb..393447d 100644 +--- a/slirp/tcp_subr.c ++++ b/slirp/tcp_subr.c +@@ -661,10 +661,12 @@ tcp_emu(struct socket *so, struct mbuf *m) + tmpso->so_fport == n1) { + if (getsockname(tmpso->s, + (struct sockaddr *)&addr, &addrlen) == 0) +- n2 = ntohs(addr.sin_port); ++ n2 = addr.sin_port; + break; + } + } ++ NTOHS(n1); ++ NTOHS(n2); + so_rcv->sb_cc = snprintf(so_rcv->sb_data, + so_rcv->sb_datalen, + "%d,%d\r\n", n1, n2); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-slirp-use-correct-size-while-emulating-IRC-commands.patch b/SOURCES/kvm-slirp-use-correct-size-while-emulating-IRC-commands.patch new file mode 100644 index 0000000..01a32e2 --- /dev/null +++ b/SOURCES/kvm-slirp-use-correct-size-while-emulating-IRC-commands.patch @@ -0,0 +1,71 @@ +From 64f43842f5685d5b1290d4a1bf4eba8e1e738a8d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Fri, 17 Jan 2020 11:49:41 +0100 +Subject: [PATCH 6/7] slirp: use correct size while emulating IRC commands +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Philippe Mathieu-Daudé +Message-id: <20200117114942.12236-3-philmd@redhat.com> +Patchwork-id: 93392 +O-Subject: [RHEL-7.7.z qemu-kvm-rhev + RHEL-7.8 qemu-kvm-rhev + RHEL-7.9 qemu-kvm-rhev + RHEL-8.1.0 qemu-kvm + RHEL-8.2.0 qemu-kvm + RHEL-7.7.z qemu-kvm-ma + RHEL-7.8 qemu-kvm-ma + RHEL-7.9 qemu-kvm-ma PATCH 2/3] slirp: use correct size while emulating IRC commands +Bugzilla: 1791566 +RH-Acked-by: Stefano Garzarella +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Thomas Huth + +From: Prasad J Pandit + +While emulating IRC DCC commands, tcp_emu() uses 'mbuf' size +'m->m_size' to write DCC commands via snprintf(3). This may +lead to OOB write access, because 'bptr' points somewhere in +the middle of 'mbuf' buffer, not at the start. Use M_FREEROOM(m) +size to avoid OOB access. + +Reported-by: Vishnu Dev TJ +Signed-off-by: Prasad J Pandit +Reviewed-by: Samuel Thibault +Message-Id: <20200109094228.79764-2-ppandit@redhat.com> +(cherry picked from libslirp commit ce131029d6d4a405cb7d3ac6716d03e58fb4a5d9) +Signed-off-by: Philippe Mathieu-Daudé + +Signed-off-by: Miroslav Rezanina +--- + slirp/tcp_subr.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/slirp/tcp_subr.c b/slirp/tcp_subr.c +index decfd9b..b60310d 100644 +--- a/slirp/tcp_subr.c ++++ b/slirp/tcp_subr.c +@@ -783,7 +783,7 @@ tcp_emu(struct socket *so, struct mbuf *m) + return 1; + } + m->m_len = bptr - m->m_data; /* Adjust length */ +- m->m_len += snprintf(bptr, m->m_size, ++ m->m_len += snprintf(bptr, M_FREEROOM(m), + "DCC CHAT chat %lu %u%c\n", + (unsigned long)ntohl(so->so_faddr.s_addr), + ntohs(so->so_fport), 1); +@@ -794,7 +794,7 @@ tcp_emu(struct socket *so, struct mbuf *m) + return 1; + } + m->m_len = bptr - m->m_data; /* Adjust length */ +- m->m_len += snprintf(bptr, m->m_size, ++ m->m_len += snprintf(bptr, M_FREEROOM(m), + "DCC SEND %s %lu %u %u%c\n", buff, + (unsigned long)ntohl(so->so_faddr.s_addr), + ntohs(so->so_fport), n1, 1); +@@ -805,7 +805,7 @@ tcp_emu(struct socket *so, struct mbuf *m) + return 1; + } + m->m_len = bptr - m->m_data; /* Adjust length */ +- m->m_len += snprintf(bptr, m->m_size, ++ m->m_len += snprintf(bptr, M_FREEROOM(m), + "DCC MOVE %s %lu %u %u%c\n", buff, + (unsigned long)ntohl(so->so_faddr.s_addr), + ntohs(so->so_fport), n1, 1); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-slirp-use-correct-size-while-emulating-commands.patch b/SOURCES/kvm-slirp-use-correct-size-while-emulating-commands.patch new file mode 100644 index 0000000..58aba08 --- /dev/null +++ b/SOURCES/kvm-slirp-use-correct-size-while-emulating-commands.patch @@ -0,0 +1,70 @@ +From cfba2381aaea94b4be5f36ea7b95d42f1c283982 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Fri, 17 Jan 2020 11:49:42 +0100 +Subject: [PATCH 7/7] slirp: use correct size while emulating commands +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Philippe Mathieu-Daudé +Message-id: <20200117114942.12236-4-philmd@redhat.com> +Patchwork-id: 93391 +O-Subject: [RHEL-7.7.z qemu-kvm-rhev + RHEL-7.8 qemu-kvm-rhev + RHEL-7.9 qemu-kvm-rhev + RHEL-8.1.0 qemu-kvm + RHEL-8.2.0 qemu-kvm + RHEL-7.7.z qemu-kvm-ma + RHEL-7.8 qemu-kvm-ma + RHEL-7.9 qemu-kvm-ma PATCH 3/3] slirp: use correct size while emulating commands +Bugzilla: 1791566 +RH-Acked-by: Stefano Garzarella +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Thomas Huth + +From: Prasad J Pandit + +While emulating services in tcp_emu(), it uses 'mbuf' size +'m->m_size' to write commands via snprintf(3). Use M_FREEROOM(m) +size to avoid possible OOB access. + +Signed-off-by: Prasad J Pandit +Signed-off-by: Samuel Thibault +Message-Id: <20200109094228.79764-3-ppandit@redhat.com> +(cherry picked from libslirp commit 82ebe9c370a0e2970fb5695aa19aa5214a6a1c80) +Signed-off-by: Philippe Mathieu-Daudé + +Signed-off-by: Miroslav Rezanina +--- + slirp/tcp_subr.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/slirp/tcp_subr.c b/slirp/tcp_subr.c +index b60310d..b95ba23 100644 +--- a/slirp/tcp_subr.c ++++ b/slirp/tcp_subr.c +@@ -703,7 +703,7 @@ tcp_emu(struct socket *so, struct mbuf *m) + n4 = (laddr & 0xff); + + m->m_len = bptr - m->m_data; /* Adjust length */ +- m->m_len += snprintf(bptr, m->m_size - m->m_len, ++ m->m_len += snprintf(bptr, M_FREEROOM(m), + "ORT %d,%d,%d,%d,%d,%d\r\n%s", + n1, n2, n3, n4, n5, n6, x==7?buff:""); + return 1; +@@ -736,7 +736,7 @@ tcp_emu(struct socket *so, struct mbuf *m) + n4 = (laddr & 0xff); + + m->m_len = bptr - m->m_data; /* Adjust length */ +- m->m_len += snprintf(bptr, m->m_size - m->m_len, ++ m->m_len += snprintf(bptr, M_FREEROOM(m), + "27 Entering Passive Mode (%d,%d,%d,%d,%d,%d)\r\n%s", + n1, n2, n3, n4, n5, n6, x==7?buff:""); + +@@ -762,8 +762,8 @@ tcp_emu(struct socket *so, struct mbuf *m) + if (m->m_data[m->m_len-1] == '\0' && lport != 0 && + (so = tcp_listen(slirp, INADDR_ANY, 0, so->so_laddr.s_addr, + htons(lport), SS_FACCEPTONCE)) != NULL) +- m->m_len = snprintf(m->m_data, m->m_size, "%d", +- ntohs(so->so_fport)) + 1; ++ m->m_len = snprintf(m->m_data, M_ROOM(m), ++ "%d", ntohs(so->so_fport)) + 1; + return 1; + + case EMU_IRC: +-- +1.8.3.1 + 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-support-overcommit-cpu-pm-on-off.patch b/SOURCES/kvm-support-overcommit-cpu-pm-on-off.patch new file mode 100644 index 0000000..3da6e68 --- /dev/null +++ b/SOURCES/kvm-support-overcommit-cpu-pm-on-off.patch @@ -0,0 +1,181 @@ +From 1cfbcbeebc6d9ca1f1f7656fff572bf6ac50de76 Mon Sep 17 00:00:00 2001 +From: "plai@redhat.com" +Date: Tue, 26 Nov 2019 19:36:52 +0000 +Subject: [PATCH 08/11] kvm: support -overcommit cpu-pm=on|off + +RH-Author: plai@redhat.com +Message-id: <1574797015-32564-5-git-send-email-plai@redhat.com> +Patchwork-id: 92697 +O-Subject: [RHEL8.2 qemu-kvm PATCH 4/7] kvm: support -overcommit cpu-pm=on|off +Bugzilla: 1634827 +RH-Acked-by: Eduardo Habkost +RH-Acked-by: Michael S. Tsirkin +RH-Acked-by: Igor Mammedov + +From: "Michael S. Tsirkin" + +With this flag, kvm allows guest to control host CPU power state. This +increases latency for other processes using same host CPU in an +unpredictable way, but if decreases idle entry/exit times for the +running VCPU, so to use it QEMU needs a hint about whether host CPU is +overcommitted, hence the flag name. + +Follow-up patches will expose this capability to guest +(using mwait leaf). + +Based on a patch by Wanpeng Li . + +Signed-off-by: Michael S. Tsirkin +Message-Id: <20180622192148.178309-2-mst@redhat.com> +Signed-off-by: Paolo Bonzini +(cherry picked from commit 6f131f13e68d648a8e4f083c667ab1acd88ce4cd) +Signed-off-by: Paul Lai +Signed-off-by: Danilo C. L. de Paula +--- + include/sysemu/sysemu.h | 1 + + qemu-options.hx | 24 ++++++++++++++++++++++++ + target/i386/kvm.c | 23 +++++++++++++++++++++++ + vl.c | 32 +++++++++++++++++++++++++++++++- + 4 files changed, 79 insertions(+), 1 deletion(-) + +diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h +index f20e4f5..f38fad0 100644 +--- a/include/sysemu/sysemu.h ++++ b/include/sysemu/sysemu.h +@@ -131,6 +131,7 @@ extern bool boot_strict; + extern uint8_t *boot_splash_filedata; + extern size_t boot_splash_filedata_size; + extern bool enable_mlock; ++extern bool enable_cpu_pm; + extern uint8_t qemu_extra_params_fw[2]; + extern QEMUClockType rtc_clock; + extern const char *mem_path; +diff --git a/qemu-options.hx b/qemu-options.hx +index 1243057..99933a0 100644 +--- a/qemu-options.hx ++++ b/qemu-options.hx +@@ -3331,6 +3331,30 @@ mlocking qemu-kvm and guest memory can be enabled via @option{mlock=on} + (enabled by default). + ETEXI + ++DEF("overcommit", HAS_ARG, QEMU_OPTION_overcommit, ++ "--overcommit [mem-lock=on|off][cpu-pm=on|off]\n" ++ " run qemu with overcommit hints\n" ++ " mem-lock=on|off controls memory lock support (default: off)\n" ++ " cpu-pm=on|off controls cpu power management (default: off)\n", ++ QEMU_ARCH_ALL) ++STEXI ++@item -overcommit mem-lock=on|off ++@item -overcommit cpu-pm=on|off ++@findex -overcommit ++Run qemu with hints about host resource overcommit. The default is ++to assume that host overcommits all resources. ++ ++Locking qemu and guest memory can be enabled via @option{mem-lock=on} (disabled ++by default). This works when host memory is not overcommitted and reduces the ++worst-case latency for guest. This is equivalent to @option{realtime}. ++ ++Guest ability to manage power state of host cpus (increasing latency for other ++processes on the same host cpu, but decreasing latency for guest) can be ++enabled via @option{cpu-pm=on} (disabled by default). This works best when ++host CPU is not overcommitted. When used, host estimates of CPU cycle and power ++utilization will be incorrect, not taking into account guest idle time. ++ETEXI ++ + DEF("gdb", HAS_ARG, QEMU_OPTION_gdb, \ + "-gdb dev wait for gdb connection on 'dev'\n", QEMU_ARCH_ALL) + STEXI +diff --git a/target/i386/kvm.c b/target/i386/kvm.c +index 107c53b..879c3e0 100644 +--- a/target/i386/kvm.c ++++ b/target/i386/kvm.c +@@ -1606,6 +1606,29 @@ int kvm_arch_init(MachineState *ms, KVMState *s) + smram_machine_done.notify = register_smram_listener; + qemu_add_machine_init_done_notifier(&smram_machine_done); + } ++ ++ if (enable_cpu_pm) { ++ int disable_exits = kvm_check_extension(s, KVM_CAP_X86_DISABLE_EXITS); ++ int ret; ++ ++/* Work around for kernel header with a typo. TODO: fix header and drop. */ ++#if defined(KVM_X86_DISABLE_EXITS_HTL) && !defined(KVM_X86_DISABLE_EXITS_HLT) ++#define KVM_X86_DISABLE_EXITS_HLT KVM_X86_DISABLE_EXITS_HTL ++#endif ++ if (disable_exits) { ++ disable_exits &= (KVM_X86_DISABLE_EXITS_MWAIT | ++ KVM_X86_DISABLE_EXITS_HLT | ++ KVM_X86_DISABLE_EXITS_PAUSE); ++ } ++ ++ ret = kvm_vm_enable_cap(s, KVM_CAP_X86_DISABLE_EXITS, 0, ++ disable_exits); ++ if (ret < 0) { ++ error_report("kvm: guest stopping CPU not supported: %s", ++ strerror(-ret)); ++ } ++ } ++ + return 0; + } + +diff --git a/vl.c b/vl.c +index 932c1cf..aa08ab5 100644 +--- a/vl.c ++++ b/vl.c +@@ -150,6 +150,7 @@ ram_addr_t ram_size; + const char *mem_path = NULL; + int mem_prealloc = 0; /* force preallocation of physical target memory */ + bool enable_mlock = false; ++bool enable_cpu_pm = false; + int nb_nics; + NICInfo nd_table[MAX_NICS]; + int autostart; +@@ -428,6 +429,22 @@ static QemuOptsList qemu_realtime_opts = { + }, + }; + ++static QemuOptsList qemu_overcommit_opts = { ++ .name = "overcommit", ++ .head = QTAILQ_HEAD_INITIALIZER(qemu_overcommit_opts.head), ++ .desc = { ++ { ++ .name = "mem-lock", ++ .type = QEMU_OPT_BOOL, ++ }, ++ { ++ .name = "cpu-pm", ++ .type = QEMU_OPT_BOOL, ++ }, ++ { /* end of list */ } ++ }, ++}; ++ + static QemuOptsList qemu_msg_opts = { + .name = "msg", + .head = QTAILQ_HEAD_INITIALIZER(qemu_msg_opts.head), +@@ -4089,7 +4106,20 @@ int main(int argc, char **argv, char **envp) + if (!opts) { + exit(1); + } +- enable_mlock = qemu_opt_get_bool(opts, "mlock", true); ++ /* Don't override the -overcommit option if set */ ++ enable_mlock = enable_mlock || ++ qemu_opt_get_bool(opts, "mlock", true); ++ break; ++ case QEMU_OPTION_overcommit: ++ opts = qemu_opts_parse_noisily(qemu_find_opts("overcommit"), ++ optarg, false); ++ if (!opts) { ++ exit(1); ++ } ++ /* Don't override the -realtime option if set */ ++ enable_mlock = enable_mlock || ++ qemu_opt_get_bool(opts, "mem-lock", false); ++ enable_cpu_pm = qemu_opt_get_bool(opts, "cpu-pm", false); + break; + case QEMU_OPTION_msg: + opts = qemu_opts_parse_noisily(qemu_find_opts("msg"), optarg, +-- +1.8.3.1 + diff --git a/SOURCES/kvm-tap-set-vhostfd-passed-from-qemu-cli-to-non-blocking.patch b/SOURCES/kvm-tap-set-vhostfd-passed-from-qemu-cli-to-non-blocking.patch new file mode 100644 index 0000000..1bf8142 --- /dev/null +++ b/SOURCES/kvm-tap-set-vhostfd-passed-from-qemu-cli-to-non-blocking.patch @@ -0,0 +1,66 @@ +From 689a30f211939282ce6de9d3597c0fc6ad674a6e Mon Sep 17 00:00:00 2001 +From: Laszlo Ersek +Date: Fri, 26 Jul 2019 11:29:51 +0100 +Subject: [PATCH 13/14] tap: set vhostfd passed from qemu cli to non-blocking + +RH-Author: Laszlo Ersek +Message-id: <20190726112951.11834-2-lersek@redhat.com> +Patchwork-id: 89734 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 1/1] tap: set vhostfd passed from qemu cli to non-blocking +Bugzilla: 1732642 +RH-Acked-by: Xiao Wang +RH-Acked-by: Stefano Garzarella +RH-Acked-by: John Snow + +From: Brijesh Singh + +A guest boot hangs while probing the network interface when +iommu_platform=on is used. + +The following qemu cli hangs without this patch: + +# $QEMU \ + -netdev tap,fd=3,id=hostnet0,vhost=on,vhostfd=4 3<>/dev/tap67 4<>/dev/host-net \ + -device virtio-net-pci,netdev=hostnet0,id=net0,iommu_platform=on,disable-legacy=on \ + ... + +Commit: c471ad0e9bd46 (vhost_net: device IOTLB support) took care of +setting vhostfd to non-blocking when QEMU opens /dev/host-net but if +the fd is passed from qemu cli then we need to ensure that fd is set +to non-blocking. + +Fixes: c471ad0e9bd46 ("vhost_net: device IOTLB support") +Cc: qemu-stable@nongnu.org +Cc: Michael S. Tsirkin +Cc: Jason Wang +Signed-off-by: Brijesh Singh +Signed-off-by: Jason Wang +(cherry picked from commit d542800d1edc62f63f8a29cfa6bdd1a9536ae11c) +Signed-off-by: Danilo C. L. de Paula +--- + net/tap.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/tap.c b/net/tap.c +index 2b3a36f..89c4e19 100644 +--- a/net/tap.c ++++ b/net/tap.c +@@ -40,6 +40,7 @@ + #include "qemu-common.h" + #include "qemu/cutils.h" + #include "qemu/error-report.h" ++#include "qemu/sockets.h" + + #include "net/tap.h" + +@@ -693,6 +694,7 @@ static void net_init_tap_one(const NetdevTapOptions *tap, NetClientState *peer, + } + return; + } ++ qemu_set_nonblock(vhostfd); + } else { + vhostfd = open("/dev/vhost-net", O_RDWR); + if (vhostfd < 0) { +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-Add-support-for-save-load-IA32_UMWAIT_CO.patch b/SOURCES/kvm-target-i386-Add-support-for-save-load-IA32_UMWAIT_CO.patch new file mode 100644 index 0000000..da6cbe9 --- /dev/null +++ b/SOURCES/kvm-target-i386-Add-support-for-save-load-IA32_UMWAIT_CO.patch @@ -0,0 +1,147 @@ +From 9c3757a2d7302918456da459a8d188bb41299891 Mon Sep 17 00:00:00 2001 +From: Tao Xu +Date: Fri, 11 Oct 2019 15:41:03 +0800 +Subject: [PATCH 11/11] target/i386: Add support for save/load + IA32_UMWAIT_CONTROL MSR + +RH-Author: plai@redhat.com +Message-id: <1574797015-32564-8-git-send-email-plai@redhat.com> +Patchwork-id: 92693 +O-Subject: [RHEL8.2 qemu-kvm PATCH 7/7] target/i386: Add support for save/load IA32_UMWAIT_CONTROL MSR +Bugzilla: 1634827 +RH-Acked-by: Eduardo Habkost +RH-Acked-by: Michael S. Tsirkin +RH-Acked-by: Igor Mammedov + +UMWAIT and TPAUSE instructions use 32bits IA32_UMWAIT_CONTROL at MSR +index E1H to determines the maximum time in TSC-quanta that the processor +can reside in either C0.1 or C0.2. + +This patch is to Add support for save/load IA32_UMWAIT_CONTROL MSR in +guest. + +Co-developed-by: Jingqi Liu +Signed-off-by: Jingqi Liu +Signed-off-by: Tao Xu +Message-Id: <20191011074103.30393-3-tao3.xu@intel.com> +Signed-off-by: Paolo Bonzini +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.h | 2 ++ + target/i386/kvm.c | 13 +++++++++++++ + target/i386/machine.c | 20 ++++++++++++++++++++ + 3 files changed, 35 insertions(+) + +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index fac98aa..ecbe4f0 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -461,6 +461,7 @@ typedef enum X86Seg { + + #define MSR_IA32_BNDCFGS 0x00000d90 + #define MSR_IA32_XSS 0x00000da0 ++#define MSR_IA32_UMWAIT_CONTROL 0xe1 + + #define MSR_IA32_VMX_BASIC 0x00000480 + #define MSR_IA32_VMX_PINBASED_CTLS 0x00000481 +@@ -1510,6 +1511,7 @@ typedef struct CPUX86State { + uint16_t fpregs_format_vmstate; + + uint64_t xss; ++ uint32_t umwait; + + TPRAccess tpr_access_type; + } CPUX86State; +diff --git a/target/i386/kvm.c b/target/i386/kvm.c +index 0fd5650..ad58bfb 100644 +--- a/target/i386/kvm.c ++++ b/target/i386/kvm.c +@@ -91,6 +91,7 @@ static bool has_msr_hv_synic; + static bool has_msr_hv_stimer; + static bool has_msr_hv_frequencies; + static bool has_msr_xss; ++static bool has_msr_umwait; + static bool has_msr_spec_ctrl; + static bool has_msr_tsx_ctrl; + static bool has_msr_virt_ssbd; +@@ -1450,6 +1451,9 @@ static int kvm_get_supported_msrs(KVMState *s) + case MSR_IA32_XSS: + has_msr_xss = true; + break; ++ case MSR_IA32_UMWAIT_CONTROL: ++ has_msr_umwait = true; ++ break; + case HV_X64_MSR_CRASH_CTL: + has_msr_hv_crash = true; + break; +@@ -2134,6 +2138,9 @@ static int kvm_put_msrs(X86CPU *cpu, int level) + if (has_msr_xss) { + kvm_msr_entry_add(cpu, MSR_IA32_XSS, env->xss); + } ++ if (has_msr_umwait) { ++ kvm_msr_entry_add(cpu, MSR_IA32_UMWAIT_CONTROL, env->umwait); ++ } + if (has_msr_spec_ctrl) { + kvm_msr_entry_add(cpu, MSR_IA32_SPEC_CTRL, env->spec_ctrl); + } +@@ -2533,6 +2540,9 @@ static int kvm_get_msrs(X86CPU *cpu) + if (has_msr_xss) { + kvm_msr_entry_add(cpu, MSR_IA32_XSS, 0); + } ++ if (has_msr_umwait) { ++ kvm_msr_entry_add(cpu, MSR_IA32_UMWAIT_CONTROL, 0); ++ } + if (has_msr_spec_ctrl) { + kvm_msr_entry_add(cpu, MSR_IA32_SPEC_CTRL, 0); + } +@@ -2780,6 +2790,9 @@ static int kvm_get_msrs(X86CPU *cpu) + case MSR_IA32_XSS: + env->xss = msrs[i].data; + break; ++ case MSR_IA32_UMWAIT_CONTROL: ++ env->umwait = msrs[i].data; ++ break; + default: + if (msrs[i].index >= MSR_MC0_CTL && + msrs[i].index < MSR_MC0_CTL + (env->mcg_cap & 0xff) * 4) { +diff --git a/target/i386/machine.c b/target/i386/machine.c +index 76b173c..960cb51 100644 +--- a/target/i386/machine.c ++++ b/target/i386/machine.c +@@ -894,6 +894,25 @@ static const VMStateDescription vmstate_xss = { + } + }; + ++static bool umwait_needed(void *opaque) ++{ ++ X86CPU *cpu = opaque; ++ CPUX86State *env = &cpu->env; ++ ++ return env->umwait != 0; ++} ++ ++static const VMStateDescription vmstate_umwait = { ++ .name = "cpu/umwait", ++ .version_id = 1, ++ .minimum_version_id = 1, ++ .needed = umwait_needed, ++ .fields = (VMStateField[]) { ++ VMSTATE_UINT32(env.umwait, X86CPU), ++ VMSTATE_END_OF_LIST() ++ } ++}; ++ + #ifdef TARGET_X86_64 + static bool pkru_needed(void *opaque) + { +@@ -1360,6 +1379,7 @@ VMStateDescription vmstate_x86_cpu = { + &vmstate_msr_hyperv_stimer, + &vmstate_avx512, + &vmstate_xss, ++ &vmstate_umwait, + &vmstate_tsc_khz, + &vmstate_msr_smi_count, + #ifdef TARGET_X86_64 +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-Disable-MPX-support-on-named-CPU-models.patch b/SOURCES/kvm-target-i386-Disable-MPX-support-on-named-CPU-models.patch new file mode 100644 index 0000000..a8dfc93 --- /dev/null +++ b/SOURCES/kvm-target-i386-Disable-MPX-support-on-named-CPU-models.patch @@ -0,0 +1,59 @@ +From defbb3b33db7fcbc9da20c1350ce90a6b5e279bb Mon Sep 17 00:00:00 2001 +From: "plai@redhat.com" +Date: Mon, 1 Jul 2019 16:17:32 +0100 +Subject: [PATCH 03/39] target/i386: Disable MPX support on named CPU models +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: plai@redhat.com +Message-id: <1561997854-9646-4-git-send-email-plai@redhat.com> +Patchwork-id: 89333 +O-Subject: [RHEL8.1 qemu-kvm PATCH v6 3/5] target/i386: Disable MPX support on named CPU models +Bugzilla: 1629906 +RH-Acked-by: Eduardo Habkost +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Bandan Das + +From: Paolo Bonzini + +MPX support is being phased out by Intel; GCC has dropped it, Linux +is also going to do that. Even though KVM will have special code +to support MPX after the kernel proper stops enabling it in XCR0, +we probably also want to deprecate that in a few years. As a start, +do not enable it by default for any named CPU model starting with +the 4.0 machine types; this include Skylake, Icelake and Cascadelake. + +Signed-off-by: Paolo Bonzini +Message-Id: <20181220121100.21554-1-pbonzini@redhat.com> +Reviewed-by:   Wainer dos Santos Moschetta +Signed-off-by: Eduardo Habkost +(cherry picked from commit ecb85fe48cacb2f8740186e81f2f38a2e02bd963) +Signed-off-by: Paul Lai +Signed-off-by: Danilo C. L. de Paula + +Conflicts: + hw/i386/pc.c changes to include/hw/i386/pc.h + target/i386/cpu.c + +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index c4b31eb..094f8a1 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -2512,7 +2512,7 @@ static X86CPUDefinition builtin_x86_defs[] = { + CPUID_7_0_EBX_HLE | CPUID_7_0_EBX_AVX2 | CPUID_7_0_EBX_SMEP | + CPUID_7_0_EBX_BMI2 | CPUID_7_0_EBX_ERMS | CPUID_7_0_EBX_INVPCID | + CPUID_7_0_EBX_RTM | CPUID_7_0_EBX_RDSEED | CPUID_7_0_EBX_ADX | +- CPUID_7_0_EBX_SMAP | CPUID_7_0_EBX_MPX | CPUID_7_0_EBX_CLWB | ++ CPUID_7_0_EBX_SMAP | CPUID_7_0_EBX_CLWB | + CPUID_7_0_EBX_AVX512F | CPUID_7_0_EBX_AVX512DQ | + CPUID_7_0_EBX_AVX512BW | CPUID_7_0_EBX_AVX512CD | + CPUID_7_0_EBX_AVX512VL | CPUID_7_0_EBX_CLFLUSHOPT | +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-Export-TAA_NO-bit-to-guests.patch b/SOURCES/kvm-target-i386-Export-TAA_NO-bit-to-guests.patch new file mode 100644 index 0000000..e3eaa99 --- /dev/null +++ b/SOURCES/kvm-target-i386-Export-TAA_NO-bit-to-guests.patch @@ -0,0 +1,48 @@ +From 3048f38859988e7b6d63099350769ecb9ac0e76f Mon Sep 17 00:00:00 2001 +From: Eduardo Habkost +Date: Tue, 3 Dec 2019 23:53:07 +0000 +Subject: [PATCH 1/2] target/i386: Export TAA_NO bit to guests + +RH-Author: Eduardo Habkost +Message-id: <20191203235308.590845-2-ehabkost@redhat.com> +Patchwork-id: 92851 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH 1/2] target/i386: Export TAA_NO bit to guests +Bugzilla: 1771971 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Igor Mammedov + +From: Pawan Gupta + +TSX Async Abort (TAA) is a side channel attack on internal buffers in +some Intel processors similar to Microachitectural Data Sampling (MDS). + +Some future Intel processors will use the ARCH_CAP_TAA_NO bit in the +IA32_ARCH_CAPABILITIES MSR to report that they are not vulnerable to +TAA. Make this bit available to guests. + +Signed-off-by: Pawan Gupta +Signed-off-by: Paolo Bonzini +(cherry picked from commit 7fac38635e1cc5ebae34eb6530da1009bd5808e4) +Signed-off-by: Eduardo Habkost +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index 3effcf3..68fe865 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -1144,7 +1144,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { + .feat_names = { + "rdctl-no", "ibrs-all", "rsba", "skip-l1dfl-vmentry", + "ssb-no", "mds-no", NULL, NULL, +- NULL, NULL, NULL, NULL, ++ "taa-no", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-add-MDS-NO-feature.patch b/SOURCES/kvm-target-i386-add-MDS-NO-feature.patch new file mode 100644 index 0000000..e465737 --- /dev/null +++ b/SOURCES/kvm-target-i386-add-MDS-NO-feature.patch @@ -0,0 +1,51 @@ +From 354818b02978df635ea030462223283529711970 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Sun, 23 Jun 2019 15:19:12 +0200 +Subject: [PATCH 1/4] target/i386: add MDS-NO feature + +RH-Author: Paolo Bonzini +Message-id: <20190623151912.7829-1-pbonzini@redhat.com> +Patchwork-id: 88872 +O-Subject: [RHEL-8.1.0 PATCH qemu-kvm] target/i386: add MDS-NO feature +Bugzilla: 1714792 +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Stefano Garzarella +RH-Acked-by: Miroslav Rezanina + +Bugzilla: 1714792 + +Brew build: 22307357 + +Microarchitectural Data Sampling is a hardware vulnerability which allows +unprivileged speculative access to data which is available in various CPU +internal buffers. + +Some Intel processors use the ARCH_CAP_MDS_NO bit in the +IA32_ARCH_CAPABILITIES +MSR to report that they are not vulnerable, make it available to guests. + +Signed-off-by: Paolo Bonzini +Message-Id: <20190516185320.28340-1-pbonzini@redhat.com> +Signed-off-by: Eduardo Habkost +(cherry picked from commit 20140a82c67467f53814ca197403d5e1b561a5e5) +Signed-off-by: Miroslav Rezanina +--- + target/i386/cpu.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index 4411012..5c10093 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -1147,7 +1147,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { + .type = MSR_FEATURE_WORD, + .feat_names = { + "rdctl-no", "ibrs-all", "rsba", "skip-l1dfl-vmentry", +- "ssb-no", NULL, NULL, NULL, ++ "ssb-no", "mds-no", NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-add-VMX-definitions.patch b/SOURCES/kvm-target-i386-add-VMX-definitions.patch new file mode 100644 index 0000000..3d70b4d --- /dev/null +++ b/SOURCES/kvm-target-i386-add-VMX-definitions.patch @@ -0,0 +1,177 @@ +From 968d0586936c356ca19f6f3b659ab094a2825374 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Fri, 22 Nov 2019 11:53:42 +0000 +Subject: [PATCH 09/16] target/i386: add VMX definitions + +RH-Author: Paolo Bonzini +Message-id: <20191122115348.25000-10-pbonzini@redhat.com> +Patchwork-id: 92604 +O-Subject: [RHEL8.2/rhel qemu-kvm PATCH 09/15] target/i386: add VMX definitions +Bugzilla: 1689270 +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Eduardo Habkost +RH-Acked-by: Maxim Levitsky + +These will be used to compile the list of VMX features for named +CPU models, and/or by the code that sets up the VMX MSRs. + +Signed-off-by: Paolo Bonzini +(cherry picked from commit 704798add83be4ac868ffcb495480065fb665794) + +RHEL: context +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.h | 130 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 130 insertions(+) + +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index edba84e..2d1f247 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -459,6 +459,25 @@ typedef enum X86Seg { + #define MSR_IA32_BNDCFGS 0x00000d90 + #define MSR_IA32_XSS 0x00000da0 + ++#define MSR_IA32_VMX_BASIC 0x00000480 ++#define MSR_IA32_VMX_PINBASED_CTLS 0x00000481 ++#define MSR_IA32_VMX_PROCBASED_CTLS 0x00000482 ++#define MSR_IA32_VMX_EXIT_CTLS 0x00000483 ++#define MSR_IA32_VMX_ENTRY_CTLS 0x00000484 ++#define MSR_IA32_VMX_MISC 0x00000485 ++#define MSR_IA32_VMX_CR0_FIXED0 0x00000486 ++#define MSR_IA32_VMX_CR0_FIXED1 0x00000487 ++#define MSR_IA32_VMX_CR4_FIXED0 0x00000488 ++#define MSR_IA32_VMX_CR4_FIXED1 0x00000489 ++#define MSR_IA32_VMX_VMCS_ENUM 0x0000048a ++#define MSR_IA32_VMX_PROCBASED_CTLS2 0x0000048b ++#define MSR_IA32_VMX_EPT_VPID_CAP 0x0000048c ++#define MSR_IA32_VMX_TRUE_PINBASED_CTLS 0x0000048d ++#define MSR_IA32_VMX_TRUE_PROCBASED_CTLS 0x0000048e ++#define MSR_IA32_VMX_TRUE_EXIT_CTLS 0x0000048f ++#define MSR_IA32_VMX_TRUE_ENTRY_CTLS 0x00000490 ++#define MSR_IA32_VMX_VMFUNC 0x00000491 ++ + #define XSTATE_FP_BIT 0 + #define XSTATE_SSE_BIT 1 + #define XSTATE_YMM_BIT 2 +@@ -749,6 +768,117 @@ typedef uint64_t FeatureWordArray[FEATURE_WORDS]; + + #define MSR_CORE_CAP_SPLIT_LOCK_DETECT (1U << 5) + ++/* VMX MSR features */ ++#define MSR_VMX_BASIC_VMCS_REVISION_MASK 0x7FFFFFFFull ++#define MSR_VMX_BASIC_VMXON_REGION_SIZE_MASK (0x00001FFFull << 32) ++#define MSR_VMX_BASIC_VMCS_MEM_TYPE_MASK (0x003C0000ull << 32) ++#define MSR_VMX_BASIC_DUAL_MONITOR (1ULL << 49) ++#define MSR_VMX_BASIC_INS_OUTS (1ULL << 54) ++#define MSR_VMX_BASIC_TRUE_CTLS (1ULL << 55) ++ ++#define MSR_VMX_MISC_PREEMPTION_TIMER_SHIFT_MASK 0x1Full ++#define MSR_VMX_MISC_STORE_LMA (1ULL << 5) ++#define MSR_VMX_MISC_ACTIVITY_HLT (1ULL << 6) ++#define MSR_VMX_MISC_ACTIVITY_SHUTDOWN (1ULL << 7) ++#define MSR_VMX_MISC_ACTIVITY_WAIT_SIPI (1ULL << 8) ++#define MSR_VMX_MISC_MAX_MSR_LIST_SIZE_MASK 0x0E000000ull ++#define MSR_VMX_MISC_VMWRITE_VMEXIT (1ULL << 29) ++#define MSR_VMX_MISC_ZERO_LEN_INJECT (1ULL << 30) ++ ++#define MSR_VMX_EPT_EXECONLY (1ULL << 0) ++#define MSR_VMX_EPT_PAGE_WALK_LENGTH_4 (1ULL << 6) ++#define MSR_VMX_EPT_PAGE_WALK_LENGTH_5 (1ULL << 7) ++#define MSR_VMX_EPT_UC (1ULL << 8) ++#define MSR_VMX_EPT_WB (1ULL << 14) ++#define MSR_VMX_EPT_2MB (1ULL << 16) ++#define MSR_VMX_EPT_1GB (1ULL << 17) ++#define MSR_VMX_EPT_INVEPT (1ULL << 20) ++#define MSR_VMX_EPT_AD_BITS (1ULL << 21) ++#define MSR_VMX_EPT_ADVANCED_VMEXIT_INFO (1ULL << 22) ++#define MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT (1ULL << 25) ++#define MSR_VMX_EPT_INVEPT_ALL_CONTEXT (1ULL << 26) ++#define MSR_VMX_EPT_INVVPID (1ULL << 32) ++#define MSR_VMX_EPT_INVVPID_SINGLE_ADDR (1ULL << 40) ++#define MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT (1ULL << 41) ++#define MSR_VMX_EPT_INVVPID_ALL_CONTEXT (1ULL << 42) ++#define MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS (1ULL << 43) ++ ++#define MSR_VMX_VMFUNC_EPT_SWITCHING (1ULL << 0) ++ ++ ++/* VMX controls */ ++#define VMX_CPU_BASED_VIRTUAL_INTR_PENDING 0x00000004 ++#define VMX_CPU_BASED_USE_TSC_OFFSETING 0x00000008 ++#define VMX_CPU_BASED_HLT_EXITING 0x00000080 ++#define VMX_CPU_BASED_INVLPG_EXITING 0x00000200 ++#define VMX_CPU_BASED_MWAIT_EXITING 0x00000400 ++#define VMX_CPU_BASED_RDPMC_EXITING 0x00000800 ++#define VMX_CPU_BASED_RDTSC_EXITING 0x00001000 ++#define VMX_CPU_BASED_CR3_LOAD_EXITING 0x00008000 ++#define VMX_CPU_BASED_CR3_STORE_EXITING 0x00010000 ++#define VMX_CPU_BASED_CR8_LOAD_EXITING 0x00080000 ++#define VMX_CPU_BASED_CR8_STORE_EXITING 0x00100000 ++#define VMX_CPU_BASED_TPR_SHADOW 0x00200000 ++#define VMX_CPU_BASED_VIRTUAL_NMI_PENDING 0x00400000 ++#define VMX_CPU_BASED_MOV_DR_EXITING 0x00800000 ++#define VMX_CPU_BASED_UNCOND_IO_EXITING 0x01000000 ++#define VMX_CPU_BASED_USE_IO_BITMAPS 0x02000000 ++#define VMX_CPU_BASED_MONITOR_TRAP_FLAG 0x08000000 ++#define VMX_CPU_BASED_USE_MSR_BITMAPS 0x10000000 ++#define VMX_CPU_BASED_MONITOR_EXITING 0x20000000 ++#define VMX_CPU_BASED_PAUSE_EXITING 0x40000000 ++#define VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS 0x80000000 ++ ++#define VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES 0x00000001 ++#define VMX_SECONDARY_EXEC_ENABLE_EPT 0x00000002 ++#define VMX_SECONDARY_EXEC_DESC 0x00000004 ++#define VMX_SECONDARY_EXEC_RDTSCP 0x00000008 ++#define VMX_SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE 0x00000010 ++#define VMX_SECONDARY_EXEC_ENABLE_VPID 0x00000020 ++#define VMX_SECONDARY_EXEC_WBINVD_EXITING 0x00000040 ++#define VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST 0x00000080 ++#define VMX_SECONDARY_EXEC_APIC_REGISTER_VIRT 0x00000100 ++#define VMX_SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY 0x00000200 ++#define VMX_SECONDARY_EXEC_PAUSE_LOOP_EXITING 0x00000400 ++#define VMX_SECONDARY_EXEC_RDRAND_EXITING 0x00000800 ++#define VMX_SECONDARY_EXEC_ENABLE_INVPCID 0x00001000 ++#define VMX_SECONDARY_EXEC_ENABLE_VMFUNC 0x00002000 ++#define VMX_SECONDARY_EXEC_SHADOW_VMCS 0x00004000 ++#define VMX_SECONDARY_EXEC_ENCLS_EXITING 0x00008000 ++#define VMX_SECONDARY_EXEC_RDSEED_EXITING 0x00010000 ++#define VMX_SECONDARY_EXEC_ENABLE_PML 0x00020000 ++#define VMX_SECONDARY_EXEC_XSAVES 0x00100000 ++ ++#define VMX_PIN_BASED_EXT_INTR_MASK 0x00000001 ++#define VMX_PIN_BASED_NMI_EXITING 0x00000008 ++#define VMX_PIN_BASED_VIRTUAL_NMIS 0x00000020 ++#define VMX_PIN_BASED_VMX_PREEMPTION_TIMER 0x00000040 ++#define VMX_PIN_BASED_POSTED_INTR 0x00000080 ++ ++#define VMX_VM_EXIT_SAVE_DEBUG_CONTROLS 0x00000004 ++#define VMX_VM_EXIT_HOST_ADDR_SPACE_SIZE 0x00000200 ++#define VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL 0x00001000 ++#define VMX_VM_EXIT_ACK_INTR_ON_EXIT 0x00008000 ++#define VMX_VM_EXIT_SAVE_IA32_PAT 0x00040000 ++#define VMX_VM_EXIT_LOAD_IA32_PAT 0x00080000 ++#define VMX_VM_EXIT_SAVE_IA32_EFER 0x00100000 ++#define VMX_VM_EXIT_LOAD_IA32_EFER 0x00200000 ++#define VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER 0x00400000 ++#define VMX_VM_EXIT_CLEAR_BNDCFGS 0x00800000 ++#define VMX_VM_EXIT_PT_CONCEAL_PIP 0x01000000 ++#define VMX_VM_EXIT_CLEAR_IA32_RTIT_CTL 0x02000000 ++ ++#define VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS 0x00000004 ++#define VMX_VM_ENTRY_IA32E_MODE 0x00000200 ++#define VMX_VM_ENTRY_SMM 0x00000400 ++#define VMX_VM_ENTRY_DEACT_DUAL_MONITOR 0x00000800 ++#define VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL 0x00002000 ++#define VMX_VM_ENTRY_LOAD_IA32_PAT 0x00004000 ++#define VMX_VM_ENTRY_LOAD_IA32_EFER 0x00008000 ++#define VMX_VM_ENTRY_LOAD_BNDCFGS 0x00010000 ++#define VMX_VM_ENTRY_PT_CONCEAL_PIP 0x00020000 ++#define VMX_VM_ENTRY_LOAD_IA32_RTIT_CTL 0x00040000 ++ + #ifndef HYPERV_SPINLOCK_NEVER_RETRY + #define HYPERV_SPINLOCK_NEVER_RETRY 0xFFFFFFFF + #endif +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-add-VMX-features-to-named-CPU-models-RHE.patch b/SOURCES/kvm-target-i386-add-VMX-features-to-named-CPU-models-RHE.patch new file mode 100644 index 0000000..3d1cb0c --- /dev/null +++ b/SOURCES/kvm-target-i386-add-VMX-features-to-named-CPU-models-RHE.patch @@ -0,0 +1,654 @@ +From 1163b93bcdbef8e11c276722014d39c3619dbd1b Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Fri, 22 Nov 2019 11:53:48 +0000 +Subject: [PATCH 15/16] target/i386: add VMX features to named CPU models (RHEL + only) + +RH-Author: Paolo Bonzini +Message-id: <20191122115348.25000-16-pbonzini@redhat.com> +Patchwork-id: 92614 +O-Subject: [RHEL8.2/rhel qemu-kvm PATCH 15/15] target/i386: add VMX features to named CPU models (RHEL only) +Bugzilla: 1689270 +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Eduardo Habkost +RH-Acked-by: Maxim Levitsky + +Upstream has switched to versioned CPU models in order to provide the +noTSX and IBRS variants. In 2.12, VMX features have to be duplicated by +hand. + +Signed-off-by: Paolo Bonzini +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.c | 538 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 538 insertions(+) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index 36c9252..3effcf3 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -2212,6 +2212,46 @@ static X86CPUDefinition builtin_x86_defs[] = { + CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX, + .features[FEAT_8000_0001_ECX] = + CPUID_EXT3_LAHF_LM, ++ .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS | ++ MSR_VMX_BASIC_TRUE_CTLS, ++ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE | ++ VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | VMX_VM_ENTRY_LOAD_IA32_PAT | ++ VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS | VMX_VM_ENTRY_LOAD_IA32_EFER, ++ .features[FEAT_VMX_EPT_VPID_CAPS] = MSR_VMX_EPT_EXECONLY | ++ MSR_VMX_EPT_PAGE_WALK_LENGTH_4 | MSR_VMX_EPT_WB | MSR_VMX_EPT_2MB | ++ MSR_VMX_EPT_1GB | MSR_VMX_EPT_INVEPT | ++ MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT | MSR_VMX_EPT_INVEPT_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID | MSR_VMX_EPT_INVVPID_SINGLE_ADDR | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT | MSR_VMX_EPT_INVVPID_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS, ++ .features[FEAT_VMX_EXIT_CTLS] = ++ VMX_VM_EXIT_ACK_INTR_ON_EXIT | VMX_VM_EXIT_SAVE_DEBUG_CONTROLS | ++ VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | ++ VMX_VM_EXIT_LOAD_IA32_PAT | VMX_VM_EXIT_LOAD_IA32_EFER | ++ VMX_VM_EXIT_SAVE_IA32_PAT | VMX_VM_EXIT_SAVE_IA32_EFER | ++ VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER, ++ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT, ++ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | ++ VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS | ++ VMX_PIN_BASED_VMX_PREEMPTION_TIMER, ++ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | ++ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | ++ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | ++ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | ++ VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | ++ VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | ++ VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | ++ VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | ++ VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | ++ VMX_CPU_BASED_CR3_LOAD_EXITING | VMX_CPU_BASED_CR3_STORE_EXITING | ++ VMX_CPU_BASED_MONITOR_TRAP_FLAG | ++ VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, ++ .features[FEAT_VMX_SECONDARY_CTLS] = ++ VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | ++ VMX_SECONDARY_EXEC_WBINVD_EXITING | VMX_SECONDARY_EXEC_ENABLE_EPT | ++ VMX_SECONDARY_EXEC_DESC | VMX_SECONDARY_EXEC_RDTSCP | ++ VMX_SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE | ++ VMX_SECONDARY_EXEC_ENABLE_VPID, + .xlevel = 0x80000008, + .model_id = "Intel Core i7 9xx (Nehalem Core i7, IBRS update)", + }, +@@ -2307,6 +2347,47 @@ static X86CPUDefinition builtin_x86_defs[] = { + CPUID_7_0_EDX_SPEC_CTRL, + .features[FEAT_6_EAX] = + CPUID_6_EAX_ARAT, ++ .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS | ++ MSR_VMX_BASIC_TRUE_CTLS, ++ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE | ++ VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | VMX_VM_ENTRY_LOAD_IA32_PAT | ++ VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS | VMX_VM_ENTRY_LOAD_IA32_EFER, ++ .features[FEAT_VMX_EPT_VPID_CAPS] = MSR_VMX_EPT_EXECONLY | ++ MSR_VMX_EPT_PAGE_WALK_LENGTH_4 | MSR_VMX_EPT_WB | MSR_VMX_EPT_2MB | ++ MSR_VMX_EPT_1GB | MSR_VMX_EPT_INVEPT | ++ MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT | MSR_VMX_EPT_INVEPT_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID | MSR_VMX_EPT_INVVPID_SINGLE_ADDR | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT | MSR_VMX_EPT_INVVPID_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS, ++ .features[FEAT_VMX_EXIT_CTLS] = ++ VMX_VM_EXIT_ACK_INTR_ON_EXIT | VMX_VM_EXIT_SAVE_DEBUG_CONTROLS | ++ VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | ++ VMX_VM_EXIT_LOAD_IA32_PAT | VMX_VM_EXIT_LOAD_IA32_EFER | ++ VMX_VM_EXIT_SAVE_IA32_PAT | VMX_VM_EXIT_SAVE_IA32_EFER | ++ VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER, ++ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT | ++ MSR_VMX_MISC_STORE_LMA, ++ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | ++ VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS | ++ VMX_PIN_BASED_VMX_PREEMPTION_TIMER, ++ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | ++ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | ++ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | ++ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | ++ VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | ++ VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | ++ VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | ++ VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | ++ VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | ++ VMX_CPU_BASED_CR3_LOAD_EXITING | VMX_CPU_BASED_CR3_STORE_EXITING | ++ VMX_CPU_BASED_MONITOR_TRAP_FLAG | ++ VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, ++ .features[FEAT_VMX_SECONDARY_CTLS] = ++ VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | ++ VMX_SECONDARY_EXEC_WBINVD_EXITING | VMX_SECONDARY_EXEC_ENABLE_EPT | ++ VMX_SECONDARY_EXEC_DESC | VMX_SECONDARY_EXEC_RDTSCP | ++ VMX_SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE | ++ VMX_SECONDARY_EXEC_ENABLE_VPID | VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST, + .xlevel = 0x80000008, + .model_id = "Westmere E56xx/L56xx/X56xx (IBRS update)", + }, +@@ -2412,6 +2493,47 @@ static X86CPUDefinition builtin_x86_defs[] = { + CPUID_XSAVE_XSAVEOPT, + .features[FEAT_6_EAX] = + CPUID_6_EAX_ARAT, ++ .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS | ++ MSR_VMX_BASIC_TRUE_CTLS, ++ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE | ++ VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | VMX_VM_ENTRY_LOAD_IA32_PAT | ++ VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS | VMX_VM_ENTRY_LOAD_IA32_EFER, ++ .features[FEAT_VMX_EPT_VPID_CAPS] = MSR_VMX_EPT_EXECONLY | ++ MSR_VMX_EPT_PAGE_WALK_LENGTH_4 | MSR_VMX_EPT_WB | MSR_VMX_EPT_2MB | ++ MSR_VMX_EPT_1GB | MSR_VMX_EPT_INVEPT | ++ MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT | MSR_VMX_EPT_INVEPT_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID | MSR_VMX_EPT_INVVPID_SINGLE_ADDR | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT | MSR_VMX_EPT_INVVPID_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS, ++ .features[FEAT_VMX_EXIT_CTLS] = ++ VMX_VM_EXIT_ACK_INTR_ON_EXIT | VMX_VM_EXIT_SAVE_DEBUG_CONTROLS | ++ VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | ++ VMX_VM_EXIT_LOAD_IA32_PAT | VMX_VM_EXIT_LOAD_IA32_EFER | ++ VMX_VM_EXIT_SAVE_IA32_PAT | VMX_VM_EXIT_SAVE_IA32_EFER | ++ VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER, ++ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT | ++ MSR_VMX_MISC_STORE_LMA, ++ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | ++ VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS | ++ VMX_PIN_BASED_VMX_PREEMPTION_TIMER, ++ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | ++ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | ++ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | ++ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | ++ VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | ++ VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | ++ VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | ++ VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | ++ VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | ++ VMX_CPU_BASED_CR3_LOAD_EXITING | VMX_CPU_BASED_CR3_STORE_EXITING | ++ VMX_CPU_BASED_MONITOR_TRAP_FLAG | ++ VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, ++ .features[FEAT_VMX_SECONDARY_CTLS] = ++ VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | ++ VMX_SECONDARY_EXEC_WBINVD_EXITING | VMX_SECONDARY_EXEC_ENABLE_EPT | ++ VMX_SECONDARY_EXEC_DESC | VMX_SECONDARY_EXEC_RDTSCP | ++ VMX_SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE | ++ VMX_SECONDARY_EXEC_ENABLE_VPID | VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST, + .xlevel = 0x80000008, + .model_id = "Intel Xeon E312xx (Sandy Bridge, IBRS update)", + }, +@@ -2526,6 +2648,50 @@ static X86CPUDefinition builtin_x86_defs[] = { + CPUID_XSAVE_XSAVEOPT, + .features[FEAT_6_EAX] = + CPUID_6_EAX_ARAT, ++ .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS | ++ MSR_VMX_BASIC_TRUE_CTLS, ++ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE | ++ VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | VMX_VM_ENTRY_LOAD_IA32_PAT | ++ VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS | VMX_VM_ENTRY_LOAD_IA32_EFER, ++ .features[FEAT_VMX_EPT_VPID_CAPS] = MSR_VMX_EPT_EXECONLY | ++ MSR_VMX_EPT_PAGE_WALK_LENGTH_4 | MSR_VMX_EPT_WB | MSR_VMX_EPT_2MB | ++ MSR_VMX_EPT_1GB | MSR_VMX_EPT_INVEPT | ++ MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT | MSR_VMX_EPT_INVEPT_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID | MSR_VMX_EPT_INVVPID_SINGLE_ADDR | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT | MSR_VMX_EPT_INVVPID_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS, ++ .features[FEAT_VMX_EXIT_CTLS] = ++ VMX_VM_EXIT_ACK_INTR_ON_EXIT | VMX_VM_EXIT_SAVE_DEBUG_CONTROLS | ++ VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | ++ VMX_VM_EXIT_LOAD_IA32_PAT | VMX_VM_EXIT_LOAD_IA32_EFER | ++ VMX_VM_EXIT_SAVE_IA32_PAT | VMX_VM_EXIT_SAVE_IA32_EFER | ++ VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER, ++ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT | ++ MSR_VMX_MISC_STORE_LMA, ++ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | ++ VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS | ++ VMX_PIN_BASED_VMX_PREEMPTION_TIMER | VMX_PIN_BASED_POSTED_INTR, ++ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | ++ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | ++ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | ++ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | ++ VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | ++ VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | ++ VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | ++ VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | ++ VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | ++ VMX_CPU_BASED_CR3_LOAD_EXITING | VMX_CPU_BASED_CR3_STORE_EXITING | ++ VMX_CPU_BASED_MONITOR_TRAP_FLAG | ++ VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, ++ .features[FEAT_VMX_SECONDARY_CTLS] = ++ VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | ++ VMX_SECONDARY_EXEC_WBINVD_EXITING | VMX_SECONDARY_EXEC_ENABLE_EPT | ++ VMX_SECONDARY_EXEC_DESC | VMX_SECONDARY_EXEC_RDTSCP | ++ VMX_SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE | ++ VMX_SECONDARY_EXEC_ENABLE_VPID | VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST | ++ VMX_SECONDARY_EXEC_APIC_REGISTER_VIRT | ++ VMX_SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY | ++ VMX_SECONDARY_EXEC_RDRAND_EXITING, + .xlevel = 0x80000008, + .model_id = "Intel Xeon E3-12xx v2 (Ivy Bridge, IBRS)", + }, +@@ -2562,6 +2728,52 @@ static X86CPUDefinition builtin_x86_defs[] = { + CPUID_XSAVE_XSAVEOPT, + .features[FEAT_6_EAX] = + CPUID_6_EAX_ARAT, ++ .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS | ++ MSR_VMX_BASIC_TRUE_CTLS, ++ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE | ++ VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | VMX_VM_ENTRY_LOAD_IA32_PAT | ++ VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS | VMX_VM_ENTRY_LOAD_IA32_EFER, ++ .features[FEAT_VMX_EPT_VPID_CAPS] = MSR_VMX_EPT_EXECONLY | ++ MSR_VMX_EPT_PAGE_WALK_LENGTH_4 | MSR_VMX_EPT_WB | MSR_VMX_EPT_2MB | ++ MSR_VMX_EPT_1GB | MSR_VMX_EPT_INVEPT | ++ MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT | MSR_VMX_EPT_INVEPT_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID | MSR_VMX_EPT_INVVPID_SINGLE_ADDR | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT | MSR_VMX_EPT_INVVPID_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS | MSR_VMX_EPT_AD_BITS, ++ .features[FEAT_VMX_EXIT_CTLS] = ++ VMX_VM_EXIT_ACK_INTR_ON_EXIT | VMX_VM_EXIT_SAVE_DEBUG_CONTROLS | ++ VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | ++ VMX_VM_EXIT_LOAD_IA32_PAT | VMX_VM_EXIT_LOAD_IA32_EFER | ++ VMX_VM_EXIT_SAVE_IA32_PAT | VMX_VM_EXIT_SAVE_IA32_EFER | ++ VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER, ++ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT | ++ MSR_VMX_MISC_STORE_LMA | MSR_VMX_MISC_VMWRITE_VMEXIT, ++ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | ++ VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS | ++ VMX_PIN_BASED_VMX_PREEMPTION_TIMER | VMX_PIN_BASED_POSTED_INTR, ++ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | ++ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | ++ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | ++ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | ++ VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | ++ VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | ++ VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | ++ VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | ++ VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | ++ VMX_CPU_BASED_CR3_LOAD_EXITING | VMX_CPU_BASED_CR3_STORE_EXITING | ++ VMX_CPU_BASED_MONITOR_TRAP_FLAG | ++ VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, ++ .features[FEAT_VMX_SECONDARY_CTLS] = ++ VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | ++ VMX_SECONDARY_EXEC_WBINVD_EXITING | VMX_SECONDARY_EXEC_ENABLE_EPT | ++ VMX_SECONDARY_EXEC_DESC | VMX_SECONDARY_EXEC_RDTSCP | ++ VMX_SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE | ++ VMX_SECONDARY_EXEC_ENABLE_VPID | VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST | ++ VMX_SECONDARY_EXEC_APIC_REGISTER_VIRT | ++ VMX_SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY | ++ VMX_SECONDARY_EXEC_RDRAND_EXITING | VMX_SECONDARY_EXEC_ENABLE_INVPCID | ++ VMX_SECONDARY_EXEC_ENABLE_VMFUNC | VMX_SECONDARY_EXEC_SHADOW_VMCS, ++ .features[FEAT_VMX_VMFUNC] = MSR_VMX_VMFUNC_EPT_SWITCHING, + .xlevel = 0x80000008, + .model_id = "Intel Core Processor (Haswell, no TSX)", + }, +@@ -2600,6 +2812,52 @@ static X86CPUDefinition builtin_x86_defs[] = { + CPUID_XSAVE_XSAVEOPT, + .features[FEAT_6_EAX] = + CPUID_6_EAX_ARAT, ++ .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS | ++ MSR_VMX_BASIC_TRUE_CTLS, ++ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE | ++ VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | VMX_VM_ENTRY_LOAD_IA32_PAT | ++ VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS | VMX_VM_ENTRY_LOAD_IA32_EFER, ++ .features[FEAT_VMX_EPT_VPID_CAPS] = MSR_VMX_EPT_EXECONLY | ++ MSR_VMX_EPT_PAGE_WALK_LENGTH_4 | MSR_VMX_EPT_WB | MSR_VMX_EPT_2MB | ++ MSR_VMX_EPT_1GB | MSR_VMX_EPT_INVEPT | ++ MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT | MSR_VMX_EPT_INVEPT_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID | MSR_VMX_EPT_INVVPID_SINGLE_ADDR | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT | MSR_VMX_EPT_INVVPID_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS | MSR_VMX_EPT_AD_BITS, ++ .features[FEAT_VMX_EXIT_CTLS] = ++ VMX_VM_EXIT_ACK_INTR_ON_EXIT | VMX_VM_EXIT_SAVE_DEBUG_CONTROLS | ++ VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | ++ VMX_VM_EXIT_LOAD_IA32_PAT | VMX_VM_EXIT_LOAD_IA32_EFER | ++ VMX_VM_EXIT_SAVE_IA32_PAT | VMX_VM_EXIT_SAVE_IA32_EFER | ++ VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER, ++ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT | ++ MSR_VMX_MISC_STORE_LMA | MSR_VMX_MISC_VMWRITE_VMEXIT, ++ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | ++ VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS | ++ VMX_PIN_BASED_VMX_PREEMPTION_TIMER | VMX_PIN_BASED_POSTED_INTR, ++ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | ++ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | ++ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | ++ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | ++ VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | ++ VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | ++ VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | ++ VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | ++ VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | ++ VMX_CPU_BASED_CR3_LOAD_EXITING | VMX_CPU_BASED_CR3_STORE_EXITING | ++ VMX_CPU_BASED_MONITOR_TRAP_FLAG | ++ VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, ++ .features[FEAT_VMX_SECONDARY_CTLS] = ++ VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | ++ VMX_SECONDARY_EXEC_WBINVD_EXITING | VMX_SECONDARY_EXEC_ENABLE_EPT | ++ VMX_SECONDARY_EXEC_DESC | VMX_SECONDARY_EXEC_RDTSCP | ++ VMX_SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE | ++ VMX_SECONDARY_EXEC_ENABLE_VPID | VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST | ++ VMX_SECONDARY_EXEC_APIC_REGISTER_VIRT | ++ VMX_SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY | ++ VMX_SECONDARY_EXEC_RDRAND_EXITING | VMX_SECONDARY_EXEC_ENABLE_INVPCID | ++ VMX_SECONDARY_EXEC_ENABLE_VMFUNC | VMX_SECONDARY_EXEC_SHADOW_VMCS, ++ .features[FEAT_VMX_VMFUNC] = MSR_VMX_VMFUNC_EPT_SWITCHING, + .xlevel = 0x80000008, + .model_id = "Intel Core Processor (Haswell, no TSX, IBRS)", + }, +@@ -2722,6 +2980,52 @@ static X86CPUDefinition builtin_x86_defs[] = { + CPUID_XSAVE_XSAVEOPT, + .features[FEAT_6_EAX] = + CPUID_6_EAX_ARAT, ++ .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS | ++ MSR_VMX_BASIC_TRUE_CTLS, ++ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE | ++ VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | VMX_VM_ENTRY_LOAD_IA32_PAT | ++ VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS | VMX_VM_ENTRY_LOAD_IA32_EFER, ++ .features[FEAT_VMX_EPT_VPID_CAPS] = MSR_VMX_EPT_EXECONLY | ++ MSR_VMX_EPT_PAGE_WALK_LENGTH_4 | MSR_VMX_EPT_WB | MSR_VMX_EPT_2MB | ++ MSR_VMX_EPT_1GB | MSR_VMX_EPT_INVEPT | ++ MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT | MSR_VMX_EPT_INVEPT_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID | MSR_VMX_EPT_INVVPID_SINGLE_ADDR | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT | MSR_VMX_EPT_INVVPID_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS | MSR_VMX_EPT_AD_BITS, ++ .features[FEAT_VMX_EXIT_CTLS] = ++ VMX_VM_EXIT_ACK_INTR_ON_EXIT | VMX_VM_EXIT_SAVE_DEBUG_CONTROLS | ++ VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | ++ VMX_VM_EXIT_LOAD_IA32_PAT | VMX_VM_EXIT_LOAD_IA32_EFER | ++ VMX_VM_EXIT_SAVE_IA32_PAT | VMX_VM_EXIT_SAVE_IA32_EFER | ++ VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER, ++ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT | ++ MSR_VMX_MISC_STORE_LMA | MSR_VMX_MISC_VMWRITE_VMEXIT, ++ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | ++ VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS | ++ VMX_PIN_BASED_VMX_PREEMPTION_TIMER | VMX_PIN_BASED_POSTED_INTR, ++ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | ++ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | ++ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | ++ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | ++ VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | ++ VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | ++ VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | ++ VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | ++ VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | ++ VMX_CPU_BASED_CR3_LOAD_EXITING | VMX_CPU_BASED_CR3_STORE_EXITING | ++ VMX_CPU_BASED_MONITOR_TRAP_FLAG | ++ VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, ++ .features[FEAT_VMX_SECONDARY_CTLS] = ++ VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | ++ VMX_SECONDARY_EXEC_WBINVD_EXITING | VMX_SECONDARY_EXEC_ENABLE_EPT | ++ VMX_SECONDARY_EXEC_DESC | VMX_SECONDARY_EXEC_RDTSCP | ++ VMX_SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE | ++ VMX_SECONDARY_EXEC_ENABLE_VPID | VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST | ++ VMX_SECONDARY_EXEC_APIC_REGISTER_VIRT | ++ VMX_SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY | ++ VMX_SECONDARY_EXEC_RDRAND_EXITING | VMX_SECONDARY_EXEC_ENABLE_INVPCID | ++ VMX_SECONDARY_EXEC_ENABLE_VMFUNC | VMX_SECONDARY_EXEC_SHADOW_VMCS, ++ .features[FEAT_VMX_VMFUNC] = MSR_VMX_VMFUNC_EPT_SWITCHING, + .xlevel = 0x80000008, + .model_id = "Intel Core Processor (Haswell, IBRS)", + }, +@@ -2760,6 +3064,53 @@ static X86CPUDefinition builtin_x86_defs[] = { + CPUID_XSAVE_XSAVEOPT, + .features[FEAT_6_EAX] = + CPUID_6_EAX_ARAT, ++ .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS | ++ MSR_VMX_BASIC_TRUE_CTLS, ++ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE | ++ VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | VMX_VM_ENTRY_LOAD_IA32_PAT | ++ VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS | VMX_VM_ENTRY_LOAD_IA32_EFER, ++ .features[FEAT_VMX_EPT_VPID_CAPS] = MSR_VMX_EPT_EXECONLY | ++ MSR_VMX_EPT_PAGE_WALK_LENGTH_4 | MSR_VMX_EPT_WB | MSR_VMX_EPT_2MB | ++ MSR_VMX_EPT_1GB | MSR_VMX_EPT_INVEPT | ++ MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT | MSR_VMX_EPT_INVEPT_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID | MSR_VMX_EPT_INVVPID_SINGLE_ADDR | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT | MSR_VMX_EPT_INVVPID_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS | MSR_VMX_EPT_AD_BITS, ++ .features[FEAT_VMX_EXIT_CTLS] = ++ VMX_VM_EXIT_ACK_INTR_ON_EXIT | VMX_VM_EXIT_SAVE_DEBUG_CONTROLS | ++ VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | ++ VMX_VM_EXIT_LOAD_IA32_PAT | VMX_VM_EXIT_LOAD_IA32_EFER | ++ VMX_VM_EXIT_SAVE_IA32_PAT | VMX_VM_EXIT_SAVE_IA32_EFER | ++ VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER, ++ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT | ++ MSR_VMX_MISC_STORE_LMA | MSR_VMX_MISC_VMWRITE_VMEXIT, ++ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | ++ VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS | ++ VMX_PIN_BASED_VMX_PREEMPTION_TIMER | VMX_PIN_BASED_POSTED_INTR, ++ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | ++ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | ++ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | ++ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | ++ VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | ++ VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | ++ VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | ++ VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | ++ VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | ++ VMX_CPU_BASED_CR3_LOAD_EXITING | VMX_CPU_BASED_CR3_STORE_EXITING | ++ VMX_CPU_BASED_MONITOR_TRAP_FLAG | ++ VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, ++ .features[FEAT_VMX_SECONDARY_CTLS] = ++ VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | ++ VMX_SECONDARY_EXEC_WBINVD_EXITING | VMX_SECONDARY_EXEC_ENABLE_EPT | ++ VMX_SECONDARY_EXEC_DESC | VMX_SECONDARY_EXEC_RDTSCP | ++ VMX_SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE | ++ VMX_SECONDARY_EXEC_ENABLE_VPID | VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST | ++ VMX_SECONDARY_EXEC_APIC_REGISTER_VIRT | ++ VMX_SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY | ++ VMX_SECONDARY_EXEC_RDRAND_EXITING | VMX_SECONDARY_EXEC_ENABLE_INVPCID | ++ VMX_SECONDARY_EXEC_ENABLE_VMFUNC | VMX_SECONDARY_EXEC_SHADOW_VMCS | ++ VMX_SECONDARY_EXEC_RDSEED_EXITING | VMX_SECONDARY_EXEC_ENABLE_PML, ++ .features[FEAT_VMX_VMFUNC] = MSR_VMX_VMFUNC_EPT_SWITCHING, + .xlevel = 0x80000008, + .model_id = "Intel Core Processor (Broadwell, no TSX)", + }, +@@ -2800,6 +3151,53 @@ static X86CPUDefinition builtin_x86_defs[] = { + CPUID_XSAVE_XSAVEOPT, + .features[FEAT_6_EAX] = + CPUID_6_EAX_ARAT, ++ .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS | ++ MSR_VMX_BASIC_TRUE_CTLS, ++ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE | ++ VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | VMX_VM_ENTRY_LOAD_IA32_PAT | ++ VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS | VMX_VM_ENTRY_LOAD_IA32_EFER, ++ .features[FEAT_VMX_EPT_VPID_CAPS] = MSR_VMX_EPT_EXECONLY | ++ MSR_VMX_EPT_PAGE_WALK_LENGTH_4 | MSR_VMX_EPT_WB | MSR_VMX_EPT_2MB | ++ MSR_VMX_EPT_1GB | MSR_VMX_EPT_INVEPT | ++ MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT | MSR_VMX_EPT_INVEPT_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID | MSR_VMX_EPT_INVVPID_SINGLE_ADDR | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT | MSR_VMX_EPT_INVVPID_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS | MSR_VMX_EPT_AD_BITS, ++ .features[FEAT_VMX_EXIT_CTLS] = ++ VMX_VM_EXIT_ACK_INTR_ON_EXIT | VMX_VM_EXIT_SAVE_DEBUG_CONTROLS | ++ VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | ++ VMX_VM_EXIT_LOAD_IA32_PAT | VMX_VM_EXIT_LOAD_IA32_EFER | ++ VMX_VM_EXIT_SAVE_IA32_PAT | VMX_VM_EXIT_SAVE_IA32_EFER | ++ VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER, ++ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT | ++ MSR_VMX_MISC_STORE_LMA | MSR_VMX_MISC_VMWRITE_VMEXIT, ++ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | ++ VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS | ++ VMX_PIN_BASED_VMX_PREEMPTION_TIMER | VMX_PIN_BASED_POSTED_INTR, ++ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | ++ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | ++ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | ++ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | ++ VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | ++ VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | ++ VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | ++ VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | ++ VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | ++ VMX_CPU_BASED_CR3_LOAD_EXITING | VMX_CPU_BASED_CR3_STORE_EXITING | ++ VMX_CPU_BASED_MONITOR_TRAP_FLAG | ++ VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, ++ .features[FEAT_VMX_SECONDARY_CTLS] = ++ VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | ++ VMX_SECONDARY_EXEC_WBINVD_EXITING | VMX_SECONDARY_EXEC_ENABLE_EPT | ++ VMX_SECONDARY_EXEC_DESC | VMX_SECONDARY_EXEC_RDTSCP | ++ VMX_SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE | ++ VMX_SECONDARY_EXEC_ENABLE_VPID | VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST | ++ VMX_SECONDARY_EXEC_APIC_REGISTER_VIRT | ++ VMX_SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY | ++ VMX_SECONDARY_EXEC_RDRAND_EXITING | VMX_SECONDARY_EXEC_ENABLE_INVPCID | ++ VMX_SECONDARY_EXEC_ENABLE_VMFUNC | VMX_SECONDARY_EXEC_SHADOW_VMCS | ++ VMX_SECONDARY_EXEC_RDSEED_EXITING | VMX_SECONDARY_EXEC_ENABLE_PML, ++ .features[FEAT_VMX_VMFUNC] = MSR_VMX_VMFUNC_EPT_SWITCHING, + .xlevel = 0x80000008, + .model_id = "Intel Core Processor (Broadwell, no TSX, IBRS)", + }, +@@ -2925,6 +3323,53 @@ static X86CPUDefinition builtin_x86_defs[] = { + CPUID_XSAVE_XSAVEOPT, + .features[FEAT_6_EAX] = + CPUID_6_EAX_ARAT, ++ .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS | ++ MSR_VMX_BASIC_TRUE_CTLS, ++ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE | ++ VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | VMX_VM_ENTRY_LOAD_IA32_PAT | ++ VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS | VMX_VM_ENTRY_LOAD_IA32_EFER, ++ .features[FEAT_VMX_EPT_VPID_CAPS] = MSR_VMX_EPT_EXECONLY | ++ MSR_VMX_EPT_PAGE_WALK_LENGTH_4 | MSR_VMX_EPT_WB | MSR_VMX_EPT_2MB | ++ MSR_VMX_EPT_1GB | MSR_VMX_EPT_INVEPT | ++ MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT | MSR_VMX_EPT_INVEPT_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID | MSR_VMX_EPT_INVVPID_SINGLE_ADDR | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT | MSR_VMX_EPT_INVVPID_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS | MSR_VMX_EPT_AD_BITS, ++ .features[FEAT_VMX_EXIT_CTLS] = ++ VMX_VM_EXIT_ACK_INTR_ON_EXIT | VMX_VM_EXIT_SAVE_DEBUG_CONTROLS | ++ VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | ++ VMX_VM_EXIT_LOAD_IA32_PAT | VMX_VM_EXIT_LOAD_IA32_EFER | ++ VMX_VM_EXIT_SAVE_IA32_PAT | VMX_VM_EXIT_SAVE_IA32_EFER | ++ VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER, ++ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT | ++ MSR_VMX_MISC_STORE_LMA | MSR_VMX_MISC_VMWRITE_VMEXIT, ++ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | ++ VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS | ++ VMX_PIN_BASED_VMX_PREEMPTION_TIMER | VMX_PIN_BASED_POSTED_INTR, ++ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | ++ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | ++ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | ++ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | ++ VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | ++ VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | ++ VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | ++ VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | ++ VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | ++ VMX_CPU_BASED_CR3_LOAD_EXITING | VMX_CPU_BASED_CR3_STORE_EXITING | ++ VMX_CPU_BASED_MONITOR_TRAP_FLAG | ++ VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, ++ .features[FEAT_VMX_SECONDARY_CTLS] = ++ VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | ++ VMX_SECONDARY_EXEC_WBINVD_EXITING | VMX_SECONDARY_EXEC_ENABLE_EPT | ++ VMX_SECONDARY_EXEC_DESC | VMX_SECONDARY_EXEC_RDTSCP | ++ VMX_SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE | ++ VMX_SECONDARY_EXEC_ENABLE_VPID | VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST | ++ VMX_SECONDARY_EXEC_APIC_REGISTER_VIRT | ++ VMX_SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY | ++ VMX_SECONDARY_EXEC_RDRAND_EXITING | VMX_SECONDARY_EXEC_ENABLE_INVPCID | ++ VMX_SECONDARY_EXEC_ENABLE_VMFUNC | VMX_SECONDARY_EXEC_SHADOW_VMCS | ++ VMX_SECONDARY_EXEC_RDSEED_EXITING | VMX_SECONDARY_EXEC_ENABLE_PML, ++ .features[FEAT_VMX_VMFUNC] = MSR_VMX_VMFUNC_EPT_SWITCHING, + .xlevel = 0x80000008, + .model_id = "Intel Core Processor (Broadwell, IBRS)", + }, +@@ -3062,6 +3507,51 @@ static X86CPUDefinition builtin_x86_defs[] = { + CPUID_XSAVE_XGETBV1, + .features[FEAT_6_EAX] = + CPUID_6_EAX_ARAT, ++ /* Missing: Mode-based execute control (XS/XU), processor tracing, TSC scaling */ ++ .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS | ++ MSR_VMX_BASIC_TRUE_CTLS, ++ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE | ++ VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | VMX_VM_ENTRY_LOAD_IA32_PAT | ++ VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS | VMX_VM_ENTRY_LOAD_IA32_EFER, ++ .features[FEAT_VMX_EPT_VPID_CAPS] = MSR_VMX_EPT_EXECONLY | ++ MSR_VMX_EPT_PAGE_WALK_LENGTH_4 | MSR_VMX_EPT_WB | MSR_VMX_EPT_2MB | ++ MSR_VMX_EPT_1GB | MSR_VMX_EPT_INVEPT | ++ MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT | MSR_VMX_EPT_INVEPT_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID | MSR_VMX_EPT_INVVPID_SINGLE_ADDR | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT | MSR_VMX_EPT_INVVPID_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS | MSR_VMX_EPT_AD_BITS, ++ .features[FEAT_VMX_EXIT_CTLS] = ++ VMX_VM_EXIT_ACK_INTR_ON_EXIT | VMX_VM_EXIT_SAVE_DEBUG_CONTROLS | ++ VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | ++ VMX_VM_EXIT_LOAD_IA32_PAT | VMX_VM_EXIT_LOAD_IA32_EFER | ++ VMX_VM_EXIT_SAVE_IA32_PAT | VMX_VM_EXIT_SAVE_IA32_EFER | ++ VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER, ++ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT | ++ MSR_VMX_MISC_STORE_LMA | MSR_VMX_MISC_VMWRITE_VMEXIT, ++ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | ++ VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS | ++ VMX_PIN_BASED_VMX_PREEMPTION_TIMER, ++ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | ++ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | ++ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | ++ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | ++ VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | ++ VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | ++ VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | ++ VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | ++ VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | ++ VMX_CPU_BASED_CR3_LOAD_EXITING | VMX_CPU_BASED_CR3_STORE_EXITING | ++ VMX_CPU_BASED_MONITOR_TRAP_FLAG | ++ VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, ++ .features[FEAT_VMX_SECONDARY_CTLS] = ++ VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | ++ VMX_SECONDARY_EXEC_WBINVD_EXITING | VMX_SECONDARY_EXEC_ENABLE_EPT | ++ VMX_SECONDARY_EXEC_DESC | VMX_SECONDARY_EXEC_RDTSCP | ++ VMX_SECONDARY_EXEC_ENABLE_VPID | VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST | ++ VMX_SECONDARY_EXEC_RDRAND_EXITING | VMX_SECONDARY_EXEC_ENABLE_INVPCID | ++ VMX_SECONDARY_EXEC_ENABLE_VMFUNC | VMX_SECONDARY_EXEC_SHADOW_VMCS | ++ VMX_SECONDARY_EXEC_RDSEED_EXITING | VMX_SECONDARY_EXEC_ENABLE_PML, ++ .features[FEAT_VMX_VMFUNC] = MSR_VMX_VMFUNC_EPT_SWITCHING, + .xlevel = 0x80000008, + .model_id = "Intel Core Processor (Skylake, IBRS)", + }, +@@ -3208,6 +3698,54 @@ static X86CPUDefinition builtin_x86_defs[] = { + CPUID_XSAVE_XGETBV1, + .features[FEAT_6_EAX] = + CPUID_6_EAX_ARAT, ++ /* Missing: Mode-based execute control (XS/XU), processor tracing, TSC scaling */ ++ .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS | ++ MSR_VMX_BASIC_TRUE_CTLS, ++ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE | ++ VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | VMX_VM_ENTRY_LOAD_IA32_PAT | ++ VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS | VMX_VM_ENTRY_LOAD_IA32_EFER, ++ .features[FEAT_VMX_EPT_VPID_CAPS] = MSR_VMX_EPT_EXECONLY | ++ MSR_VMX_EPT_PAGE_WALK_LENGTH_4 | MSR_VMX_EPT_WB | MSR_VMX_EPT_2MB | ++ MSR_VMX_EPT_1GB | MSR_VMX_EPT_INVEPT | ++ MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT | MSR_VMX_EPT_INVEPT_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID | MSR_VMX_EPT_INVVPID_SINGLE_ADDR | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT | MSR_VMX_EPT_INVVPID_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS | MSR_VMX_EPT_AD_BITS, ++ .features[FEAT_VMX_EXIT_CTLS] = ++ VMX_VM_EXIT_ACK_INTR_ON_EXIT | VMX_VM_EXIT_SAVE_DEBUG_CONTROLS | ++ VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | ++ VMX_VM_EXIT_LOAD_IA32_PAT | VMX_VM_EXIT_LOAD_IA32_EFER | ++ VMX_VM_EXIT_SAVE_IA32_PAT | VMX_VM_EXIT_SAVE_IA32_EFER | ++ VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER, ++ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT | ++ MSR_VMX_MISC_STORE_LMA | MSR_VMX_MISC_VMWRITE_VMEXIT, ++ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | ++ VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS | ++ VMX_PIN_BASED_VMX_PREEMPTION_TIMER | VMX_PIN_BASED_POSTED_INTR, ++ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | ++ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | ++ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | ++ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | ++ VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | ++ VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | ++ VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | ++ VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | ++ VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | ++ VMX_CPU_BASED_CR3_LOAD_EXITING | VMX_CPU_BASED_CR3_STORE_EXITING | ++ VMX_CPU_BASED_MONITOR_TRAP_FLAG | ++ VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, ++ .features[FEAT_VMX_SECONDARY_CTLS] = ++ VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | ++ VMX_SECONDARY_EXEC_WBINVD_EXITING | VMX_SECONDARY_EXEC_ENABLE_EPT | ++ VMX_SECONDARY_EXEC_DESC | VMX_SECONDARY_EXEC_RDTSCP | ++ VMX_SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE | ++ VMX_SECONDARY_EXEC_ENABLE_VPID | VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST | ++ VMX_SECONDARY_EXEC_APIC_REGISTER_VIRT | ++ VMX_SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY | ++ VMX_SECONDARY_EXEC_RDRAND_EXITING | VMX_SECONDARY_EXEC_ENABLE_INVPCID | ++ VMX_SECONDARY_EXEC_ENABLE_VMFUNC | VMX_SECONDARY_EXEC_SHADOW_VMCS | ++ VMX_SECONDARY_EXEC_RDSEED_EXITING | VMX_SECONDARY_EXEC_ENABLE_PML, ++ .features[FEAT_VMX_VMFUNC] = MSR_VMX_VMFUNC_EPT_SWITCHING, + .xlevel = 0x80000008, + .model_id = "Intel Xeon Processor (Skylake, IBRS)", + }, +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-add-VMX-features-to-named-CPU-models.patch b/SOURCES/kvm-target-i386-add-VMX-features-to-named-CPU-models.patch new file mode 100644 index 0000000..3ca0136 --- /dev/null +++ b/SOURCES/kvm-target-i386-add-VMX-features-to-named-CPU-models.patch @@ -0,0 +1,891 @@ +From a958a54a1072e201d209fd54e3fd0b55a331c5da Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Fri, 22 Nov 2019 11:53:47 +0000 +Subject: [PATCH 14/16] target/i386: add VMX features to named CPU models + +RH-Author: Paolo Bonzini +Message-id: <20191122115348.25000-15-pbonzini@redhat.com> +Patchwork-id: 92613 +O-Subject: [RHEL8.2/rhel qemu-kvm PATCH 14/15] target/i386: add VMX features to named CPU models +Bugzilla: 1689270 +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Eduardo Habkost +RH-Acked-by: Maxim Levitsky + +This allows using "-cpu Haswell,+vmx", which we did not really want to +support in QEMU but was produced by Libvirt when using the "host-model" +CPU model. Without this patch, no VMX feature is _actually_ supported +(only the basic instruction set extensions are) and KVM fails to load +in the guest. + +This was produced from the output of scripts/kvm/vmxcap using the following +very ugly Python script: + + bits = { + 'INS/OUTS instruction information': ['FEAT_VMX_BASIC', 'MSR_VMX_BASIC_INS_OUTS'], + 'IA32_VMX_TRUE_*_CTLS support': ['FEAT_VMX_BASIC', 'MSR_VMX_BASIC_TRUE_CTLS'], + 'External interrupt exiting': ['FEAT_VMX_PINBASED_CTLS', 'VMX_PIN_BASED_EXT_INTR_MASK'], + 'NMI exiting': ['FEAT_VMX_PINBASED_CTLS', 'VMX_PIN_BASED_NMI_EXITING'], + 'Virtual NMIs': ['FEAT_VMX_PINBASED_CTLS', 'VMX_PIN_BASED_VIRTUAL_NMIS'], + 'Activate VMX-preemption timer': ['FEAT_VMX_PINBASED_CTLS', 'VMX_PIN_BASED_VMX_PREEMPTION_TIMER'], + 'Process posted interrupts': ['FEAT_VMX_PINBASED_CTLS', 'VMX_PIN_BASED_POSTED_INTR'], + 'Interrupt window exiting': ['FEAT_VMX_PROCBASED_CTLS', 'VMX_CPU_BASED_VIRTUAL_INTR_PENDING'], + 'Use TSC offsetting': ['FEAT_VMX_PROCBASED_CTLS', 'VMX_CPU_BASED_USE_TSC_OFFSETING'], + 'HLT exiting': ['FEAT_VMX_PROCBASED_CTLS', 'VMX_CPU_BASED_HLT_EXITING'], + 'INVLPG exiting': ['FEAT_VMX_PROCBASED_CTLS', 'VMX_CPU_BASED_INVLPG_EXITING'], + 'MWAIT exiting': ['FEAT_VMX_PROCBASED_CTLS', 'VMX_CPU_BASED_MWAIT_EXITING'], + 'RDPMC exiting': ['FEAT_VMX_PROCBASED_CTLS', 'VMX_CPU_BASED_RDPMC_EXITING'], + 'RDTSC exiting': ['FEAT_VMX_PROCBASED_CTLS', 'VMX_CPU_BASED_RDTSC_EXITING'], + 'CR3-load exiting': ['FEAT_VMX_PROCBASED_CTLS', 'VMX_CPU_BASED_CR3_LOAD_EXITING'], + 'CR3-store exiting': ['FEAT_VMX_PROCBASED_CTLS', 'VMX_CPU_BASED_CR3_STORE_EXITING'], + 'CR8-load exiting': ['FEAT_VMX_PROCBASED_CTLS', 'VMX_CPU_BASED_CR8_LOAD_EXITING'], + 'CR8-store exiting': ['FEAT_VMX_PROCBASED_CTLS', 'VMX_CPU_BASED_CR8_STORE_EXITING'], + 'Use TPR shadow': ['FEAT_VMX_PROCBASED_CTLS', 'VMX_CPU_BASED_TPR_SHADOW'], + 'NMI-window exiting': ['FEAT_VMX_PROCBASED_CTLS', 'VMX_CPU_BASED_VIRTUAL_NMI_PENDING'], + 'MOV-DR exiting': ['FEAT_VMX_PROCBASED_CTLS', 'VMX_CPU_BASED_MOV_DR_EXITING'], + 'Unconditional I/O exiting': ['FEAT_VMX_PROCBASED_CTLS', 'VMX_CPU_BASED_UNCOND_IO_EXITING'], + 'Use I/O bitmaps': ['FEAT_VMX_PROCBASED_CTLS', 'VMX_CPU_BASED_USE_IO_BITMAPS'], + 'Monitor trap flag': ['FEAT_VMX_PROCBASED_CTLS', 'VMX_CPU_BASED_MONITOR_TRAP_FLAG'], + 'Use MSR bitmaps': ['FEAT_VMX_PROCBASED_CTLS', 'VMX_CPU_BASED_USE_MSR_BITMAPS'], + 'MONITOR exiting': ['FEAT_VMX_PROCBASED_CTLS', 'VMX_CPU_BASED_MONITOR_EXITING'], + 'PAUSE exiting': ['FEAT_VMX_PROCBASED_CTLS', 'VMX_CPU_BASED_PAUSE_EXITING'], + 'Activate secondary control': ['FEAT_VMX_PROCBASED_CTLS', 'VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS'], + 'Virtualize APIC accesses': ['FEAT_VMX_SECONDARY_CTLS', 'VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES'], + 'Enable EPT': ['FEAT_VMX_SECONDARY_CTLS', 'VMX_SECONDARY_EXEC_ENABLE_EPT'], + 'Descriptor-table exiting': ['FEAT_VMX_SECONDARY_CTLS', 'VMX_SECONDARY_EXEC_DESC'], + 'Enable RDTSCP': ['FEAT_VMX_SECONDARY_CTLS', 'VMX_SECONDARY_EXEC_RDTSCP'], + 'Virtualize x2APIC mode': ['FEAT_VMX_SECONDARY_CTLS', 'VMX_SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE'], + 'Enable VPID': ['FEAT_VMX_SECONDARY_CTLS', 'VMX_SECONDARY_EXEC_ENABLE_VPID'], + 'WBINVD exiting': ['FEAT_VMX_SECONDARY_CTLS', 'VMX_SECONDARY_EXEC_WBINVD_EXITING'], + 'Unrestricted guest': ['FEAT_VMX_SECONDARY_CTLS', 'VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST'], + 'APIC register emulation': ['FEAT_VMX_SECONDARY_CTLS', 'VMX_SECONDARY_EXEC_APIC_REGISTER_VIRT'], + 'Virtual interrupt delivery': ['FEAT_VMX_SECONDARY_CTLS', 'VMX_SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY'], + 'PAUSE-loop exiting': ['FEAT_VMX_SECONDARY_CTLS', 'VMX_SECONDARY_EXEC_PAUSE_LOOP_EXITING'], + 'RDRAND exiting': ['FEAT_VMX_SECONDARY_CTLS', 'VMX_SECONDARY_EXEC_RDRAND_EXITING'], + 'Enable INVPCID': ['FEAT_VMX_SECONDARY_CTLS', 'VMX_SECONDARY_EXEC_ENABLE_INVPCID'], + 'Enable VM functions': ['FEAT_VMX_SECONDARY_CTLS', 'VMX_SECONDARY_EXEC_ENABLE_VMFUNC'], + 'VMCS shadowing': ['FEAT_VMX_SECONDARY_CTLS', 'VMX_SECONDARY_EXEC_SHADOW_VMCS'], + 'RDSEED exiting': ['FEAT_VMX_SECONDARY_CTLS', 'VMX_SECONDARY_EXEC_RDSEED_EXITING'], + 'Enable PML': ['FEAT_VMX_SECONDARY_CTLS', 'VMX_SECONDARY_EXEC_ENABLE_PML'], + 'Enable XSAVES/XRSTORS': ['FEAT_VMX_SECONDARY_CTLS', 'VMX_SECONDARY_EXEC_XSAVES'], + 'Save debug controls': ['FEAT_VMX_EXIT_CTLS', 'VMX_VM_EXIT_SAVE_DEBUG_CONTROLS'], + 'Load IA32_PERF_GLOBAL_CTRL': ['FEAT_VMX_EXIT_CTLS', 'VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL'], + 'Acknowledge interrupt on exit': ['FEAT_VMX_EXIT_CTLS', 'VMX_VM_EXIT_ACK_INTR_ON_EXIT'], + 'Save IA32_PAT': ['FEAT_VMX_EXIT_CTLS', 'VMX_VM_EXIT_SAVE_IA32_PAT'], + 'Load IA32_PAT': ['FEAT_VMX_EXIT_CTLS', 'VMX_VM_EXIT_LOAD_IA32_PAT'], + 'Save IA32_EFER': ['FEAT_VMX_EXIT_CTLS', 'VMX_VM_EXIT_SAVE_IA32_EFER'], + 'Load IA32_EFER': ['FEAT_VMX_EXIT_CTLS', 'VMX_VM_EXIT_LOAD_IA32_EFER'], + 'Save VMX-preemption timer value': ['FEAT_VMX_EXIT_CTLS', 'VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER'], + 'Clear IA32_BNDCFGS': ['FEAT_VMX_EXIT_CTLS', 'VMX_VM_EXIT_CLEAR_BNDCFGS'], + 'Load debug controls': ['FEAT_VMX_ENTRY_CTLS', 'VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS'], + 'IA-32e mode guest': ['FEAT_VMX_ENTRY_CTLS', 'VMX_VM_ENTRY_IA32E_MODE'], + 'Load IA32_PERF_GLOBAL_CTRL': ['FEAT_VMX_ENTRY_CTLS', 'VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL'], + 'Load IA32_PAT': ['FEAT_VMX_ENTRY_CTLS', 'VMX_VM_ENTRY_LOAD_IA32_PAT'], + 'Load IA32_EFER': ['FEAT_VMX_ENTRY_CTLS', 'VMX_VM_ENTRY_LOAD_IA32_EFER'], + 'Load IA32_BNDCFGS': ['FEAT_VMX_ENTRY_CTLS', 'VMX_VM_ENTRY_LOAD_BNDCFGS'], + 'Store EFER.LMA into IA-32e mode guest control': ['FEAT_VMX_MISC', 'MSR_VMX_MISC_STORE_LMA'], + 'HLT activity state': ['FEAT_VMX_MISC', 'MSR_VMX_MISC_ACTIVITY_HLT'], + 'VMWRITE to VM-exit information fields': ['FEAT_VMX_MISC', 'MSR_VMX_MISC_VMWRITE_VMEXIT'], + 'Inject event with insn length=0': ['FEAT_VMX_MISC', 'MSR_VMX_MISC_ZERO_LEN_INJECT'], + 'Execute-only EPT translations': ['FEAT_VMX_EPT_VPID_CAPS', 'MSR_VMX_EPT_EXECONLY'], + 'Page-walk length 4': ['FEAT_VMX_EPT_VPID_CAPS', 'MSR_VMX_EPT_PAGE_WALK_LENGTH_4'], + 'Paging-structure memory type WB': ['FEAT_VMX_EPT_VPID_CAPS', 'MSR_VMX_EPT_WB'], + '2MB EPT pages': ['FEAT_VMX_EPT_VPID_CAPS', 'MSR_VMX_EPT_2MB | MSR_VMX_EPT_1GB'], + 'INVEPT supported': ['FEAT_VMX_EPT_VPID_CAPS', 'MSR_VMX_EPT_INVEPT'], + 'EPT accessed and dirty flags': ['FEAT_VMX_EPT_VPID_CAPS', 'MSR_VMX_EPT_AD_BITS'], + 'Single-context INVEPT': ['FEAT_VMX_EPT_VPID_CAPS', 'MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT'], + 'All-context INVEPT': ['FEAT_VMX_EPT_VPID_CAPS', 'MSR_VMX_EPT_INVEPT_ALL_CONTEXT'], + 'INVVPID supported': ['FEAT_VMX_EPT_VPID_CAPS', 'MSR_VMX_EPT_INVVPID'], + 'Individual-address INVVPID': ['FEAT_VMX_EPT_VPID_CAPS', 'MSR_VMX_EPT_INVVPID_SINGLE_ADDR'], + 'Single-context INVVPID': ['FEAT_VMX_EPT_VPID_CAPS', 'MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT'], + 'All-context INVVPID': ['FEAT_VMX_EPT_VPID_CAPS', 'MSR_VMX_EPT_INVVPID_ALL_CONTEXT'], + 'Single-context-retaining-globals INVVPID': ['FEAT_VMX_EPT_VPID_CAPS', 'MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS'], + 'EPTP Switching': ['FEAT_VMX_VMFUNC', 'MSR_VMX_VMFUNC_EPT_SWITCHING'] + } + + import sys + import textwrap + + out = {} + for l in sys.stdin.readlines(): + l = l.rstrip() + if l.endswith('!!'): + l = l[:-2].rstrip() + if l.startswith(' ') and (l.endswith('default') or l.endswith('yes')): + l = l[4:] + for key, value in bits.items(): + if l.startswith(key): + ctl, bit = value + if ctl in out: + out[ctl] = out[ctl] + ' | ' + else: + out[ctl] = ' [%s] = ' % ctl + out[ctl] = out[ctl] + bit + + for x in sorted(out.keys()): + print("\n ".join(textwrap.wrap(out[x] + ","))) + +Note that the script has a bug in that some keys apply to both VM entry +and VM exit controls ("load IA32_PERF_GLOBAL_CTRL", "load IA32_EFER", +"load IA32_PAT". Those have to be fixed by hand. + +Reviewed-by: Eduardo Habkost +Signed-off-by: Paolo Bonzini +(cherry picked from commit 0723cc8a5558c94388db75ae1f4991314914edd3) + +RHEL: no Denverton and Snowridge +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.c | 617 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 617 insertions(+) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index 9074a2e..36c9252 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -1689,6 +1689,34 @@ static CPUCaches epyc_cache_info = { + }, + }; + ++/* The following VMX features are not supported by KVM and are left out in the ++ * CPU definitions: ++ * ++ * Dual-monitor support (all processors) ++ * Entry to SMM ++ * Deactivate dual-monitor treatment ++ * Number of CR3-target values ++ * Shutdown activity state ++ * Wait-for-SIPI activity state ++ * PAUSE-loop exiting (Westmere and newer) ++ * EPT-violation #VE (Broadwell and newer) ++ * Inject event with insn length=0 (Skylake and newer) ++ * Conceal non-root operation from PT ++ * Conceal VM exits from PT ++ * Conceal VM entries from PT ++ * Enable ENCLS exiting ++ * Mode-based execute control (XS/XU) ++ s TSC scaling (Skylake Server and newer) ++ * GPA translation for PT (IceLake and newer) ++ * User wait and pause ++ * ENCLV exiting ++ * Load IA32_RTIT_CTL ++ * Clear IA32_RTIT_CTL ++ * Advanced VM-exit information for EPT violations ++ * Sub-page write permissions ++ * PT in VMX operation ++ */ ++ + static X86CPUDefinition builtin_x86_defs[] = { + { + /* qemu64 is the default CPU model for all *-rhel7.* machine-types. +@@ -1769,6 +1797,24 @@ static X86CPUDefinition builtin_x86_defs[] = { + CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX, + .features[FEAT_8000_0001_ECX] = + CPUID_EXT3_LAHF_LM, ++ .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS, ++ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE, ++ .features[FEAT_VMX_EXIT_CTLS] = VMX_VM_EXIT_ACK_INTR_ON_EXIT, ++ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT, ++ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | ++ VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS, ++ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | ++ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | ++ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | ++ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | ++ VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | ++ VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | ++ VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | ++ VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | ++ VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | ++ VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, ++ .features[FEAT_VMX_SECONDARY_CTLS] = ++ VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES, + .xlevel = 0x80000008, + .model_id = "Intel(R) Core(TM)2 Duo CPU T7700 @ 2.40GHz", + }, +@@ -1796,6 +1842,20 @@ static X86CPUDefinition builtin_x86_defs[] = { + CPUID_EXT3_OSVW, CPUID_EXT3_IBS, CPUID_EXT3_SVM */ + .features[FEAT_8000_0001_ECX] = + 0, ++ /* VMX features from Cedar Mill/Prescott */ ++ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE, ++ .features[FEAT_VMX_EXIT_CTLS] = VMX_VM_EXIT_ACK_INTR_ON_EXIT, ++ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT, ++ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | ++ VMX_PIN_BASED_NMI_EXITING, ++ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | ++ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | ++ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | ++ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | ++ VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | ++ VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | ++ VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | ++ VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING, + .xlevel = 0x80000008, + .model_id = "Common KVM processor" + }, +@@ -1827,6 +1887,19 @@ static X86CPUDefinition builtin_x86_defs[] = { + CPUID_EXT_SSE3, + .features[FEAT_8000_0001_ECX] = + 0, ++ /* VMX features from Yonah */ ++ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE, ++ .features[FEAT_VMX_EXIT_CTLS] = VMX_VM_EXIT_ACK_INTR_ON_EXIT, ++ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT, ++ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | ++ VMX_PIN_BASED_NMI_EXITING, ++ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | ++ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | ++ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | ++ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | ++ VMX_CPU_BASED_MOV_DR_EXITING | VMX_CPU_BASED_UNCOND_IO_EXITING | ++ VMX_CPU_BASED_USE_IO_BITMAPS | VMX_CPU_BASED_MONITOR_EXITING | ++ VMX_CPU_BASED_PAUSE_EXITING | VMX_CPU_BASED_USE_MSR_BITMAPS, + .xlevel = 0x80000008, + .model_id = "Common 32-bit KVM processor" + }, +@@ -1848,6 +1921,18 @@ static X86CPUDefinition builtin_x86_defs[] = { + CPUID_EXT_SSE3 | CPUID_EXT_MONITOR, + .features[FEAT_8000_0001_EDX] = + CPUID_EXT2_NX, ++ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE, ++ .features[FEAT_VMX_EXIT_CTLS] = VMX_VM_EXIT_ACK_INTR_ON_EXIT, ++ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT, ++ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | ++ VMX_PIN_BASED_NMI_EXITING, ++ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | ++ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | ++ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | ++ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | ++ VMX_CPU_BASED_MOV_DR_EXITING | VMX_CPU_BASED_UNCOND_IO_EXITING | ++ VMX_CPU_BASED_USE_IO_BITMAPS | VMX_CPU_BASED_MONITOR_EXITING | ++ VMX_CPU_BASED_PAUSE_EXITING | VMX_CPU_BASED_USE_MSR_BITMAPS, + .xlevel = 0x80000008, + .model_id = "Genuine Intel(R) CPU T2600 @ 2.16GHz", + }, +@@ -1977,6 +2062,24 @@ static X86CPUDefinition builtin_x86_defs[] = { + CPUID_EXT2_LM | CPUID_EXT2_NX | CPUID_EXT2_SYSCALL, + .features[FEAT_8000_0001_ECX] = + CPUID_EXT3_LAHF_LM, ++ .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS, ++ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE, ++ .features[FEAT_VMX_EXIT_CTLS] = VMX_VM_EXIT_ACK_INTR_ON_EXIT, ++ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT, ++ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | ++ VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS, ++ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | ++ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | ++ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | ++ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | ++ VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | ++ VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | ++ VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | ++ VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | ++ VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | ++ VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, ++ .features[FEAT_VMX_SECONDARY_CTLS] = ++ VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES, + .xlevel = 0x80000008, + .model_id = "Intel Celeron_4x0 (Conroe/Merom Class Core 2)", + }, +@@ -2000,6 +2103,27 @@ static X86CPUDefinition builtin_x86_defs[] = { + CPUID_EXT2_LM | CPUID_EXT2_NX | CPUID_EXT2_SYSCALL, + .features[FEAT_8000_0001_ECX] = + CPUID_EXT3_LAHF_LM, ++ .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS, ++ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE | ++ VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL, ++ .features[FEAT_VMX_EXIT_CTLS] = VMX_VM_EXIT_ACK_INTR_ON_EXIT | ++ VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL, ++ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT, ++ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | ++ VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS, ++ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | ++ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | ++ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | ++ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | ++ VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | ++ VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | ++ VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | ++ VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | ++ VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | ++ VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, ++ .features[FEAT_VMX_SECONDARY_CTLS] = ++ VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | ++ VMX_SECONDARY_EXEC_WBINVD_EXITING, + .xlevel = 0x80000008, + .model_id = "Intel Core 2 Duo P9xxx (Penryn Class Core 2)", + }, +@@ -2023,6 +2147,46 @@ static X86CPUDefinition builtin_x86_defs[] = { + CPUID_EXT2_LM | CPUID_EXT2_SYSCALL | CPUID_EXT2_NX, + .features[FEAT_8000_0001_ECX] = + CPUID_EXT3_LAHF_LM, ++ .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS | ++ MSR_VMX_BASIC_TRUE_CTLS, ++ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE | ++ VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | VMX_VM_ENTRY_LOAD_IA32_PAT | ++ VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS | VMX_VM_ENTRY_LOAD_IA32_EFER, ++ .features[FEAT_VMX_EPT_VPID_CAPS] = MSR_VMX_EPT_EXECONLY | ++ MSR_VMX_EPT_PAGE_WALK_LENGTH_4 | MSR_VMX_EPT_WB | MSR_VMX_EPT_2MB | ++ MSR_VMX_EPT_1GB | MSR_VMX_EPT_INVEPT | ++ MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT | MSR_VMX_EPT_INVEPT_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID | MSR_VMX_EPT_INVVPID_SINGLE_ADDR | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT | MSR_VMX_EPT_INVVPID_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS, ++ .features[FEAT_VMX_EXIT_CTLS] = ++ VMX_VM_EXIT_ACK_INTR_ON_EXIT | VMX_VM_EXIT_SAVE_DEBUG_CONTROLS | ++ VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | ++ VMX_VM_EXIT_LOAD_IA32_PAT | VMX_VM_EXIT_LOAD_IA32_EFER | ++ VMX_VM_EXIT_SAVE_IA32_PAT | VMX_VM_EXIT_SAVE_IA32_EFER | ++ VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER, ++ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT, ++ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | ++ VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS | ++ VMX_PIN_BASED_VMX_PREEMPTION_TIMER, ++ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | ++ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | ++ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | ++ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | ++ VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | ++ VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | ++ VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | ++ VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | ++ VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | ++ VMX_CPU_BASED_CR3_LOAD_EXITING | VMX_CPU_BASED_CR3_STORE_EXITING | ++ VMX_CPU_BASED_MONITOR_TRAP_FLAG | ++ VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, ++ .features[FEAT_VMX_SECONDARY_CTLS] = ++ VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | ++ VMX_SECONDARY_EXEC_WBINVD_EXITING | VMX_SECONDARY_EXEC_ENABLE_EPT | ++ VMX_SECONDARY_EXEC_DESC | VMX_SECONDARY_EXEC_RDTSCP | ++ VMX_SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE | ++ VMX_SECONDARY_EXEC_ENABLE_VPID, + .xlevel = 0x80000008, + .model_id = "Intel Core i7 9xx (Nehalem Class Core i7)", + }, +@@ -2074,6 +2238,47 @@ static X86CPUDefinition builtin_x86_defs[] = { + CPUID_EXT3_LAHF_LM, + .features[FEAT_6_EAX] = + CPUID_6_EAX_ARAT, ++ .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS | ++ MSR_VMX_BASIC_TRUE_CTLS, ++ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE | ++ VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | VMX_VM_ENTRY_LOAD_IA32_PAT | ++ VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS | VMX_VM_ENTRY_LOAD_IA32_EFER, ++ .features[FEAT_VMX_EPT_VPID_CAPS] = MSR_VMX_EPT_EXECONLY | ++ MSR_VMX_EPT_PAGE_WALK_LENGTH_4 | MSR_VMX_EPT_WB | MSR_VMX_EPT_2MB | ++ MSR_VMX_EPT_1GB | MSR_VMX_EPT_INVEPT | ++ MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT | MSR_VMX_EPT_INVEPT_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID | MSR_VMX_EPT_INVVPID_SINGLE_ADDR | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT | MSR_VMX_EPT_INVVPID_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS, ++ .features[FEAT_VMX_EXIT_CTLS] = ++ VMX_VM_EXIT_ACK_INTR_ON_EXIT | VMX_VM_EXIT_SAVE_DEBUG_CONTROLS | ++ VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | ++ VMX_VM_EXIT_LOAD_IA32_PAT | VMX_VM_EXIT_LOAD_IA32_EFER | ++ VMX_VM_EXIT_SAVE_IA32_PAT | VMX_VM_EXIT_SAVE_IA32_EFER | ++ VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER, ++ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT | ++ MSR_VMX_MISC_STORE_LMA, ++ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | ++ VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS | ++ VMX_PIN_BASED_VMX_PREEMPTION_TIMER, ++ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | ++ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | ++ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | ++ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | ++ VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | ++ VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | ++ VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | ++ VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | ++ VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | ++ VMX_CPU_BASED_CR3_LOAD_EXITING | VMX_CPU_BASED_CR3_STORE_EXITING | ++ VMX_CPU_BASED_MONITOR_TRAP_FLAG | ++ VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, ++ .features[FEAT_VMX_SECONDARY_CTLS] = ++ VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | ++ VMX_SECONDARY_EXEC_WBINVD_EXITING | VMX_SECONDARY_EXEC_ENABLE_EPT | ++ VMX_SECONDARY_EXEC_DESC | VMX_SECONDARY_EXEC_RDTSCP | ++ VMX_SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE | ++ VMX_SECONDARY_EXEC_ENABLE_VPID | VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST, + .xlevel = 0x80000008, + .model_id = "Westmere E56xx/L56xx/X56xx (Nehalem-C)", + }, +@@ -2133,6 +2338,47 @@ static X86CPUDefinition builtin_x86_defs[] = { + CPUID_XSAVE_XSAVEOPT, + .features[FEAT_6_EAX] = + CPUID_6_EAX_ARAT, ++ .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS | ++ MSR_VMX_BASIC_TRUE_CTLS, ++ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE | ++ VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | VMX_VM_ENTRY_LOAD_IA32_PAT | ++ VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS | VMX_VM_ENTRY_LOAD_IA32_EFER, ++ .features[FEAT_VMX_EPT_VPID_CAPS] = MSR_VMX_EPT_EXECONLY | ++ MSR_VMX_EPT_PAGE_WALK_LENGTH_4 | MSR_VMX_EPT_WB | MSR_VMX_EPT_2MB | ++ MSR_VMX_EPT_1GB | MSR_VMX_EPT_INVEPT | ++ MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT | MSR_VMX_EPT_INVEPT_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID | MSR_VMX_EPT_INVVPID_SINGLE_ADDR | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT | MSR_VMX_EPT_INVVPID_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS, ++ .features[FEAT_VMX_EXIT_CTLS] = ++ VMX_VM_EXIT_ACK_INTR_ON_EXIT | VMX_VM_EXIT_SAVE_DEBUG_CONTROLS | ++ VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | ++ VMX_VM_EXIT_LOAD_IA32_PAT | VMX_VM_EXIT_LOAD_IA32_EFER | ++ VMX_VM_EXIT_SAVE_IA32_PAT | VMX_VM_EXIT_SAVE_IA32_EFER | ++ VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER, ++ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT | ++ MSR_VMX_MISC_STORE_LMA, ++ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | ++ VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS | ++ VMX_PIN_BASED_VMX_PREEMPTION_TIMER, ++ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | ++ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | ++ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | ++ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | ++ VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | ++ VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | ++ VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | ++ VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | ++ VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | ++ VMX_CPU_BASED_CR3_LOAD_EXITING | VMX_CPU_BASED_CR3_STORE_EXITING | ++ VMX_CPU_BASED_MONITOR_TRAP_FLAG | ++ VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, ++ .features[FEAT_VMX_SECONDARY_CTLS] = ++ VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | ++ VMX_SECONDARY_EXEC_WBINVD_EXITING | VMX_SECONDARY_EXEC_ENABLE_EPT | ++ VMX_SECONDARY_EXEC_DESC | VMX_SECONDARY_EXEC_RDTSCP | ++ VMX_SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE | ++ VMX_SECONDARY_EXEC_ENABLE_VPID | VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST, + .xlevel = 0x80000008, + .model_id = "Intel Xeon E312xx (Sandy Bridge)", + }, +@@ -2200,6 +2446,50 @@ static X86CPUDefinition builtin_x86_defs[] = { + CPUID_XSAVE_XSAVEOPT, + .features[FEAT_6_EAX] = + CPUID_6_EAX_ARAT, ++ .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS | ++ MSR_VMX_BASIC_TRUE_CTLS, ++ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE | ++ VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | VMX_VM_ENTRY_LOAD_IA32_PAT | ++ VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS | VMX_VM_ENTRY_LOAD_IA32_EFER, ++ .features[FEAT_VMX_EPT_VPID_CAPS] = MSR_VMX_EPT_EXECONLY | ++ MSR_VMX_EPT_PAGE_WALK_LENGTH_4 | MSR_VMX_EPT_WB | MSR_VMX_EPT_2MB | ++ MSR_VMX_EPT_1GB | MSR_VMX_EPT_INVEPT | ++ MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT | MSR_VMX_EPT_INVEPT_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID | MSR_VMX_EPT_INVVPID_SINGLE_ADDR | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT | MSR_VMX_EPT_INVVPID_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS, ++ .features[FEAT_VMX_EXIT_CTLS] = ++ VMX_VM_EXIT_ACK_INTR_ON_EXIT | VMX_VM_EXIT_SAVE_DEBUG_CONTROLS | ++ VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | ++ VMX_VM_EXIT_LOAD_IA32_PAT | VMX_VM_EXIT_LOAD_IA32_EFER | ++ VMX_VM_EXIT_SAVE_IA32_PAT | VMX_VM_EXIT_SAVE_IA32_EFER | ++ VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER, ++ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT | ++ MSR_VMX_MISC_STORE_LMA, ++ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | ++ VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS | ++ VMX_PIN_BASED_VMX_PREEMPTION_TIMER | VMX_PIN_BASED_POSTED_INTR, ++ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | ++ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | ++ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | ++ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | ++ VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | ++ VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | ++ VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | ++ VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | ++ VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | ++ VMX_CPU_BASED_CR3_LOAD_EXITING | VMX_CPU_BASED_CR3_STORE_EXITING | ++ VMX_CPU_BASED_MONITOR_TRAP_FLAG | ++ VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, ++ .features[FEAT_VMX_SECONDARY_CTLS] = ++ VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | ++ VMX_SECONDARY_EXEC_WBINVD_EXITING | VMX_SECONDARY_EXEC_ENABLE_EPT | ++ VMX_SECONDARY_EXEC_DESC | VMX_SECONDARY_EXEC_RDTSCP | ++ VMX_SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE | ++ VMX_SECONDARY_EXEC_ENABLE_VPID | VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST | ++ VMX_SECONDARY_EXEC_APIC_REGISTER_VIRT | ++ VMX_SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY | ++ VMX_SECONDARY_EXEC_RDRAND_EXITING, + .xlevel = 0x80000008, + .model_id = "Intel Xeon E3-12xx v2 (Ivy Bridge)", + }, +@@ -2347,6 +2637,52 @@ static X86CPUDefinition builtin_x86_defs[] = { + CPUID_XSAVE_XSAVEOPT, + .features[FEAT_6_EAX] = + CPUID_6_EAX_ARAT, ++ .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS | ++ MSR_VMX_BASIC_TRUE_CTLS, ++ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE | ++ VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | VMX_VM_ENTRY_LOAD_IA32_PAT | ++ VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS | VMX_VM_ENTRY_LOAD_IA32_EFER, ++ .features[FEAT_VMX_EPT_VPID_CAPS] = MSR_VMX_EPT_EXECONLY | ++ MSR_VMX_EPT_PAGE_WALK_LENGTH_4 | MSR_VMX_EPT_WB | MSR_VMX_EPT_2MB | ++ MSR_VMX_EPT_1GB | MSR_VMX_EPT_INVEPT | ++ MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT | MSR_VMX_EPT_INVEPT_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID | MSR_VMX_EPT_INVVPID_SINGLE_ADDR | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT | MSR_VMX_EPT_INVVPID_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS | MSR_VMX_EPT_AD_BITS, ++ .features[FEAT_VMX_EXIT_CTLS] = ++ VMX_VM_EXIT_ACK_INTR_ON_EXIT | VMX_VM_EXIT_SAVE_DEBUG_CONTROLS | ++ VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | ++ VMX_VM_EXIT_LOAD_IA32_PAT | VMX_VM_EXIT_LOAD_IA32_EFER | ++ VMX_VM_EXIT_SAVE_IA32_PAT | VMX_VM_EXIT_SAVE_IA32_EFER | ++ VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER, ++ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT | ++ MSR_VMX_MISC_STORE_LMA | MSR_VMX_MISC_VMWRITE_VMEXIT, ++ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | ++ VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS | ++ VMX_PIN_BASED_VMX_PREEMPTION_TIMER | VMX_PIN_BASED_POSTED_INTR, ++ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | ++ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | ++ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | ++ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | ++ VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | ++ VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | ++ VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | ++ VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | ++ VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | ++ VMX_CPU_BASED_CR3_LOAD_EXITING | VMX_CPU_BASED_CR3_STORE_EXITING | ++ VMX_CPU_BASED_MONITOR_TRAP_FLAG | ++ VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, ++ .features[FEAT_VMX_SECONDARY_CTLS] = ++ VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | ++ VMX_SECONDARY_EXEC_WBINVD_EXITING | VMX_SECONDARY_EXEC_ENABLE_EPT | ++ VMX_SECONDARY_EXEC_DESC | VMX_SECONDARY_EXEC_RDTSCP | ++ VMX_SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE | ++ VMX_SECONDARY_EXEC_ENABLE_VPID | VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST | ++ VMX_SECONDARY_EXEC_APIC_REGISTER_VIRT | ++ VMX_SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY | ++ VMX_SECONDARY_EXEC_RDRAND_EXITING | VMX_SECONDARY_EXEC_ENABLE_INVPCID | ++ VMX_SECONDARY_EXEC_ENABLE_VMFUNC | VMX_SECONDARY_EXEC_SHADOW_VMCS, ++ .features[FEAT_VMX_VMFUNC] = MSR_VMX_VMFUNC_EPT_SWITCHING, + .xlevel = 0x80000008, + .model_id = "Intel Core Processor (Haswell)", + }, +@@ -2502,6 +2838,53 @@ static X86CPUDefinition builtin_x86_defs[] = { + CPUID_XSAVE_XSAVEOPT, + .features[FEAT_6_EAX] = + CPUID_6_EAX_ARAT, ++ .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS | ++ MSR_VMX_BASIC_TRUE_CTLS, ++ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE | ++ VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | VMX_VM_ENTRY_LOAD_IA32_PAT | ++ VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS | VMX_VM_ENTRY_LOAD_IA32_EFER, ++ .features[FEAT_VMX_EPT_VPID_CAPS] = MSR_VMX_EPT_EXECONLY | ++ MSR_VMX_EPT_PAGE_WALK_LENGTH_4 | MSR_VMX_EPT_WB | MSR_VMX_EPT_2MB | ++ MSR_VMX_EPT_1GB | MSR_VMX_EPT_INVEPT | ++ MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT | MSR_VMX_EPT_INVEPT_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID | MSR_VMX_EPT_INVVPID_SINGLE_ADDR | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT | MSR_VMX_EPT_INVVPID_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS | MSR_VMX_EPT_AD_BITS, ++ .features[FEAT_VMX_EXIT_CTLS] = ++ VMX_VM_EXIT_ACK_INTR_ON_EXIT | VMX_VM_EXIT_SAVE_DEBUG_CONTROLS | ++ VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | ++ VMX_VM_EXIT_LOAD_IA32_PAT | VMX_VM_EXIT_LOAD_IA32_EFER | ++ VMX_VM_EXIT_SAVE_IA32_PAT | VMX_VM_EXIT_SAVE_IA32_EFER | ++ VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER, ++ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT | ++ MSR_VMX_MISC_STORE_LMA | MSR_VMX_MISC_VMWRITE_VMEXIT, ++ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | ++ VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS | ++ VMX_PIN_BASED_VMX_PREEMPTION_TIMER | VMX_PIN_BASED_POSTED_INTR, ++ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | ++ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | ++ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | ++ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | ++ VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | ++ VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | ++ VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | ++ VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | ++ VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | ++ VMX_CPU_BASED_CR3_LOAD_EXITING | VMX_CPU_BASED_CR3_STORE_EXITING | ++ VMX_CPU_BASED_MONITOR_TRAP_FLAG | ++ VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, ++ .features[FEAT_VMX_SECONDARY_CTLS] = ++ VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | ++ VMX_SECONDARY_EXEC_WBINVD_EXITING | VMX_SECONDARY_EXEC_ENABLE_EPT | ++ VMX_SECONDARY_EXEC_DESC | VMX_SECONDARY_EXEC_RDTSCP | ++ VMX_SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE | ++ VMX_SECONDARY_EXEC_ENABLE_VPID | VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST | ++ VMX_SECONDARY_EXEC_APIC_REGISTER_VIRT | ++ VMX_SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY | ++ VMX_SECONDARY_EXEC_RDRAND_EXITING | VMX_SECONDARY_EXEC_ENABLE_INVPCID | ++ VMX_SECONDARY_EXEC_ENABLE_VMFUNC | VMX_SECONDARY_EXEC_SHADOW_VMCS | ++ VMX_SECONDARY_EXEC_RDSEED_EXITING | VMX_SECONDARY_EXEC_ENABLE_PML, ++ .features[FEAT_VMX_VMFUNC] = MSR_VMX_VMFUNC_EPT_SWITCHING, + .xlevel = 0x80000008, + .model_id = "Intel Core Processor (Broadwell)", + }, +@@ -2587,6 +2970,51 @@ static X86CPUDefinition builtin_x86_defs[] = { + CPUID_XSAVE_XGETBV1, + .features[FEAT_6_EAX] = + CPUID_6_EAX_ARAT, ++ /* Missing: Mode-based execute control (XS/XU), processor tracing, TSC scaling */ ++ .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS | ++ MSR_VMX_BASIC_TRUE_CTLS, ++ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE | ++ VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | VMX_VM_ENTRY_LOAD_IA32_PAT | ++ VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS | VMX_VM_ENTRY_LOAD_IA32_EFER, ++ .features[FEAT_VMX_EPT_VPID_CAPS] = MSR_VMX_EPT_EXECONLY | ++ MSR_VMX_EPT_PAGE_WALK_LENGTH_4 | MSR_VMX_EPT_WB | MSR_VMX_EPT_2MB | ++ MSR_VMX_EPT_1GB | MSR_VMX_EPT_INVEPT | ++ MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT | MSR_VMX_EPT_INVEPT_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID | MSR_VMX_EPT_INVVPID_SINGLE_ADDR | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT | MSR_VMX_EPT_INVVPID_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS | MSR_VMX_EPT_AD_BITS, ++ .features[FEAT_VMX_EXIT_CTLS] = ++ VMX_VM_EXIT_ACK_INTR_ON_EXIT | VMX_VM_EXIT_SAVE_DEBUG_CONTROLS | ++ VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | ++ VMX_VM_EXIT_LOAD_IA32_PAT | VMX_VM_EXIT_LOAD_IA32_EFER | ++ VMX_VM_EXIT_SAVE_IA32_PAT | VMX_VM_EXIT_SAVE_IA32_EFER | ++ VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER, ++ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT | ++ MSR_VMX_MISC_STORE_LMA | MSR_VMX_MISC_VMWRITE_VMEXIT, ++ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | ++ VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS | ++ VMX_PIN_BASED_VMX_PREEMPTION_TIMER, ++ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | ++ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | ++ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | ++ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | ++ VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | ++ VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | ++ VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | ++ VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | ++ VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | ++ VMX_CPU_BASED_CR3_LOAD_EXITING | VMX_CPU_BASED_CR3_STORE_EXITING | ++ VMX_CPU_BASED_MONITOR_TRAP_FLAG | ++ VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, ++ .features[FEAT_VMX_SECONDARY_CTLS] = ++ VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | ++ VMX_SECONDARY_EXEC_WBINVD_EXITING | VMX_SECONDARY_EXEC_ENABLE_EPT | ++ VMX_SECONDARY_EXEC_DESC | VMX_SECONDARY_EXEC_RDTSCP | ++ VMX_SECONDARY_EXEC_ENABLE_VPID | VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST | ++ VMX_SECONDARY_EXEC_RDRAND_EXITING | VMX_SECONDARY_EXEC_ENABLE_INVPCID | ++ VMX_SECONDARY_EXEC_ENABLE_VMFUNC | VMX_SECONDARY_EXEC_SHADOW_VMCS | ++ VMX_SECONDARY_EXEC_RDSEED_EXITING | VMX_SECONDARY_EXEC_ENABLE_PML, ++ .features[FEAT_VMX_VMFUNC] = MSR_VMX_VMFUNC_EPT_SWITCHING, + .xlevel = 0x80000008, + .model_id = "Intel Core Processor (Skylake)", + }, +@@ -2682,6 +3110,54 @@ static X86CPUDefinition builtin_x86_defs[] = { + CPUID_XSAVE_XGETBV1, + .features[FEAT_6_EAX] = + CPUID_6_EAX_ARAT, ++ /* Missing: Mode-based execute control (XS/XU), processor tracing, TSC scaling */ ++ .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS | ++ MSR_VMX_BASIC_TRUE_CTLS, ++ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE | ++ VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | VMX_VM_ENTRY_LOAD_IA32_PAT | ++ VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS | VMX_VM_ENTRY_LOAD_IA32_EFER, ++ .features[FEAT_VMX_EPT_VPID_CAPS] = MSR_VMX_EPT_EXECONLY | ++ MSR_VMX_EPT_PAGE_WALK_LENGTH_4 | MSR_VMX_EPT_WB | MSR_VMX_EPT_2MB | ++ MSR_VMX_EPT_1GB | MSR_VMX_EPT_INVEPT | ++ MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT | MSR_VMX_EPT_INVEPT_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID | MSR_VMX_EPT_INVVPID_SINGLE_ADDR | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT | MSR_VMX_EPT_INVVPID_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS | MSR_VMX_EPT_AD_BITS, ++ .features[FEAT_VMX_EXIT_CTLS] = ++ VMX_VM_EXIT_ACK_INTR_ON_EXIT | VMX_VM_EXIT_SAVE_DEBUG_CONTROLS | ++ VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | ++ VMX_VM_EXIT_LOAD_IA32_PAT | VMX_VM_EXIT_LOAD_IA32_EFER | ++ VMX_VM_EXIT_SAVE_IA32_PAT | VMX_VM_EXIT_SAVE_IA32_EFER | ++ VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER, ++ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT | ++ MSR_VMX_MISC_STORE_LMA | MSR_VMX_MISC_VMWRITE_VMEXIT, ++ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | ++ VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS | ++ VMX_PIN_BASED_VMX_PREEMPTION_TIMER | VMX_PIN_BASED_POSTED_INTR, ++ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | ++ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | ++ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | ++ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | ++ VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | ++ VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | ++ VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | ++ VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | ++ VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | ++ VMX_CPU_BASED_CR3_LOAD_EXITING | VMX_CPU_BASED_CR3_STORE_EXITING | ++ VMX_CPU_BASED_MONITOR_TRAP_FLAG | ++ VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, ++ .features[FEAT_VMX_SECONDARY_CTLS] = ++ VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | ++ VMX_SECONDARY_EXEC_WBINVD_EXITING | VMX_SECONDARY_EXEC_ENABLE_EPT | ++ VMX_SECONDARY_EXEC_DESC | VMX_SECONDARY_EXEC_RDTSCP | ++ VMX_SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE | ++ VMX_SECONDARY_EXEC_ENABLE_VPID | VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST | ++ VMX_SECONDARY_EXEC_APIC_REGISTER_VIRT | ++ VMX_SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY | ++ VMX_SECONDARY_EXEC_RDRAND_EXITING | VMX_SECONDARY_EXEC_ENABLE_INVPCID | ++ VMX_SECONDARY_EXEC_ENABLE_VMFUNC | VMX_SECONDARY_EXEC_SHADOW_VMCS | ++ VMX_SECONDARY_EXEC_RDSEED_EXITING | VMX_SECONDARY_EXEC_ENABLE_PML, ++ .features[FEAT_VMX_VMFUNC] = MSR_VMX_VMFUNC_EPT_SWITCHING, + .xlevel = 0x80000008, + .model_id = "Intel Xeon Processor (Skylake)", + }, +@@ -2785,6 +3261,54 @@ static X86CPUDefinition builtin_x86_defs[] = { + CPUID_XSAVE_XGETBV1, + .features[FEAT_6_EAX] = + CPUID_6_EAX_ARAT, ++ /* Missing: Mode-based execute control (XS/XU), processor tracing, TSC scaling */ ++ .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS | ++ MSR_VMX_BASIC_TRUE_CTLS, ++ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE | ++ VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | VMX_VM_ENTRY_LOAD_IA32_PAT | ++ VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS | VMX_VM_ENTRY_LOAD_IA32_EFER, ++ .features[FEAT_VMX_EPT_VPID_CAPS] = MSR_VMX_EPT_EXECONLY | ++ MSR_VMX_EPT_PAGE_WALK_LENGTH_4 | MSR_VMX_EPT_WB | MSR_VMX_EPT_2MB | ++ MSR_VMX_EPT_1GB | MSR_VMX_EPT_INVEPT | ++ MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT | MSR_VMX_EPT_INVEPT_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID | MSR_VMX_EPT_INVVPID_SINGLE_ADDR | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT | MSR_VMX_EPT_INVVPID_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS | MSR_VMX_EPT_AD_BITS, ++ .features[FEAT_VMX_EXIT_CTLS] = ++ VMX_VM_EXIT_ACK_INTR_ON_EXIT | VMX_VM_EXIT_SAVE_DEBUG_CONTROLS | ++ VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | ++ VMX_VM_EXIT_LOAD_IA32_PAT | VMX_VM_EXIT_LOAD_IA32_EFER | ++ VMX_VM_EXIT_SAVE_IA32_PAT | VMX_VM_EXIT_SAVE_IA32_EFER | ++ VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER, ++ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT | ++ MSR_VMX_MISC_STORE_LMA | MSR_VMX_MISC_VMWRITE_VMEXIT, ++ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | ++ VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS | ++ VMX_PIN_BASED_VMX_PREEMPTION_TIMER | VMX_PIN_BASED_POSTED_INTR, ++ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | ++ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | ++ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | ++ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | ++ VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | ++ VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | ++ VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | ++ VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | ++ VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | ++ VMX_CPU_BASED_CR3_LOAD_EXITING | VMX_CPU_BASED_CR3_STORE_EXITING | ++ VMX_CPU_BASED_MONITOR_TRAP_FLAG | ++ VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, ++ .features[FEAT_VMX_SECONDARY_CTLS] = ++ VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | ++ VMX_SECONDARY_EXEC_WBINVD_EXITING | VMX_SECONDARY_EXEC_ENABLE_EPT | ++ VMX_SECONDARY_EXEC_DESC | VMX_SECONDARY_EXEC_RDTSCP | ++ VMX_SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE | ++ VMX_SECONDARY_EXEC_ENABLE_VPID | VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST | ++ VMX_SECONDARY_EXEC_APIC_REGISTER_VIRT | ++ VMX_SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY | ++ VMX_SECONDARY_EXEC_RDRAND_EXITING | VMX_SECONDARY_EXEC_ENABLE_INVPCID | ++ VMX_SECONDARY_EXEC_ENABLE_VMFUNC | VMX_SECONDARY_EXEC_SHADOW_VMCS | ++ VMX_SECONDARY_EXEC_RDSEED_EXITING | VMX_SECONDARY_EXEC_ENABLE_PML, ++ .features[FEAT_VMX_VMFUNC] = MSR_VMX_VMFUNC_EPT_SWITCHING, + .xlevel = 0x80000008, + .model_id = "Intel Xeon Processor (Cascadelake)", + }, +@@ -2840,6 +3364,51 @@ static X86CPUDefinition builtin_x86_defs[] = { + CPUID_XSAVE_XGETBV1, + .features[FEAT_6_EAX] = + CPUID_6_EAX_ARAT, ++ /* Missing: Mode-based execute control (XS/XU), processor tracing, TSC scaling */ ++ .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS | ++ MSR_VMX_BASIC_TRUE_CTLS, ++ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE | ++ VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | VMX_VM_ENTRY_LOAD_IA32_PAT | ++ VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS | VMX_VM_ENTRY_LOAD_IA32_EFER, ++ .features[FEAT_VMX_EPT_VPID_CAPS] = MSR_VMX_EPT_EXECONLY | ++ MSR_VMX_EPT_PAGE_WALK_LENGTH_4 | MSR_VMX_EPT_WB | MSR_VMX_EPT_2MB | ++ MSR_VMX_EPT_1GB | MSR_VMX_EPT_INVEPT | ++ MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT | MSR_VMX_EPT_INVEPT_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID | MSR_VMX_EPT_INVVPID_SINGLE_ADDR | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT | MSR_VMX_EPT_INVVPID_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS | MSR_VMX_EPT_AD_BITS, ++ .features[FEAT_VMX_EXIT_CTLS] = ++ VMX_VM_EXIT_ACK_INTR_ON_EXIT | VMX_VM_EXIT_SAVE_DEBUG_CONTROLS | ++ VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | ++ VMX_VM_EXIT_LOAD_IA32_PAT | VMX_VM_EXIT_LOAD_IA32_EFER | ++ VMX_VM_EXIT_SAVE_IA32_PAT | VMX_VM_EXIT_SAVE_IA32_EFER | ++ VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER, ++ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT | ++ MSR_VMX_MISC_STORE_LMA | MSR_VMX_MISC_VMWRITE_VMEXIT, ++ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | ++ VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS | ++ VMX_PIN_BASED_VMX_PREEMPTION_TIMER, ++ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | ++ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | ++ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | ++ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | ++ VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | ++ VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | ++ VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | ++ VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | ++ VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | ++ VMX_CPU_BASED_CR3_LOAD_EXITING | VMX_CPU_BASED_CR3_STORE_EXITING | ++ VMX_CPU_BASED_MONITOR_TRAP_FLAG | ++ VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, ++ .features[FEAT_VMX_SECONDARY_CTLS] = ++ VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | ++ VMX_SECONDARY_EXEC_WBINVD_EXITING | VMX_SECONDARY_EXEC_ENABLE_EPT | ++ VMX_SECONDARY_EXEC_DESC | VMX_SECONDARY_EXEC_RDTSCP | ++ VMX_SECONDARY_EXEC_ENABLE_VPID | VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST | ++ VMX_SECONDARY_EXEC_RDRAND_EXITING | VMX_SECONDARY_EXEC_ENABLE_INVPCID | ++ VMX_SECONDARY_EXEC_ENABLE_VMFUNC | VMX_SECONDARY_EXEC_SHADOW_VMCS | ++ VMX_SECONDARY_EXEC_RDSEED_EXITING | VMX_SECONDARY_EXEC_ENABLE_PML, ++ .features[FEAT_VMX_VMFUNC] = MSR_VMX_VMFUNC_EPT_SWITCHING, + .xlevel = 0x80000008, + .model_id = "Intel Core Processor (Icelake)", + }, +@@ -2898,6 +3467,54 @@ static X86CPUDefinition builtin_x86_defs[] = { + CPUID_XSAVE_XGETBV1, + .features[FEAT_6_EAX] = + CPUID_6_EAX_ARAT, ++ /* Missing: Mode-based execute control (XS/XU), processor tracing, TSC scaling */ ++ .features[FEAT_VMX_BASIC] = MSR_VMX_BASIC_INS_OUTS | ++ MSR_VMX_BASIC_TRUE_CTLS, ++ .features[FEAT_VMX_ENTRY_CTLS] = VMX_VM_ENTRY_IA32E_MODE | ++ VMX_VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL | VMX_VM_ENTRY_LOAD_IA32_PAT | ++ VMX_VM_ENTRY_LOAD_DEBUG_CONTROLS | VMX_VM_ENTRY_LOAD_IA32_EFER, ++ .features[FEAT_VMX_EPT_VPID_CAPS] = MSR_VMX_EPT_EXECONLY | ++ MSR_VMX_EPT_PAGE_WALK_LENGTH_4 | MSR_VMX_EPT_WB | MSR_VMX_EPT_2MB | ++ MSR_VMX_EPT_1GB | MSR_VMX_EPT_INVEPT | ++ MSR_VMX_EPT_INVEPT_SINGLE_CONTEXT | MSR_VMX_EPT_INVEPT_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID | MSR_VMX_EPT_INVVPID_SINGLE_ADDR | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT | MSR_VMX_EPT_INVVPID_ALL_CONTEXT | ++ MSR_VMX_EPT_INVVPID_SINGLE_CONTEXT_NOGLOBALS | MSR_VMX_EPT_AD_BITS, ++ .features[FEAT_VMX_EXIT_CTLS] = ++ VMX_VM_EXIT_ACK_INTR_ON_EXIT | VMX_VM_EXIT_SAVE_DEBUG_CONTROLS | ++ VMX_VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | ++ VMX_VM_EXIT_LOAD_IA32_PAT | VMX_VM_EXIT_LOAD_IA32_EFER | ++ VMX_VM_EXIT_SAVE_IA32_PAT | VMX_VM_EXIT_SAVE_IA32_EFER | ++ VMX_VM_EXIT_SAVE_VMX_PREEMPTION_TIMER, ++ .features[FEAT_VMX_MISC] = MSR_VMX_MISC_ACTIVITY_HLT | ++ MSR_VMX_MISC_STORE_LMA | MSR_VMX_MISC_VMWRITE_VMEXIT, ++ .features[FEAT_VMX_PINBASED_CTLS] = VMX_PIN_BASED_EXT_INTR_MASK | ++ VMX_PIN_BASED_NMI_EXITING | VMX_PIN_BASED_VIRTUAL_NMIS | ++ VMX_PIN_BASED_VMX_PREEMPTION_TIMER | VMX_PIN_BASED_POSTED_INTR, ++ .features[FEAT_VMX_PROCBASED_CTLS] = VMX_CPU_BASED_VIRTUAL_INTR_PENDING | ++ VMX_CPU_BASED_USE_TSC_OFFSETING | VMX_CPU_BASED_HLT_EXITING | ++ VMX_CPU_BASED_INVLPG_EXITING | VMX_CPU_BASED_MWAIT_EXITING | ++ VMX_CPU_BASED_RDPMC_EXITING | VMX_CPU_BASED_RDTSC_EXITING | ++ VMX_CPU_BASED_CR8_LOAD_EXITING | VMX_CPU_BASED_CR8_STORE_EXITING | ++ VMX_CPU_BASED_TPR_SHADOW | VMX_CPU_BASED_MOV_DR_EXITING | ++ VMX_CPU_BASED_UNCOND_IO_EXITING | VMX_CPU_BASED_USE_IO_BITMAPS | ++ VMX_CPU_BASED_MONITOR_EXITING | VMX_CPU_BASED_PAUSE_EXITING | ++ VMX_CPU_BASED_VIRTUAL_NMI_PENDING | VMX_CPU_BASED_USE_MSR_BITMAPS | ++ VMX_CPU_BASED_CR3_LOAD_EXITING | VMX_CPU_BASED_CR3_STORE_EXITING | ++ VMX_CPU_BASED_MONITOR_TRAP_FLAG | ++ VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS, ++ .features[FEAT_VMX_SECONDARY_CTLS] = ++ VMX_SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | ++ VMX_SECONDARY_EXEC_WBINVD_EXITING | VMX_SECONDARY_EXEC_ENABLE_EPT | ++ VMX_SECONDARY_EXEC_DESC | VMX_SECONDARY_EXEC_RDTSCP | ++ VMX_SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE | ++ VMX_SECONDARY_EXEC_ENABLE_VPID | VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST | ++ VMX_SECONDARY_EXEC_APIC_REGISTER_VIRT | ++ VMX_SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY | ++ VMX_SECONDARY_EXEC_RDRAND_EXITING | VMX_SECONDARY_EXEC_ENABLE_INVPCID | ++ VMX_SECONDARY_EXEC_ENABLE_VMFUNC | VMX_SECONDARY_EXEC_SHADOW_VMCS | ++ VMX_SECONDARY_EXEC_RDSEED_EXITING | VMX_SECONDARY_EXEC_ENABLE_PML, ++ .features[FEAT_VMX_VMFUNC] = MSR_VMX_VMFUNC_EPT_SWITCHING, + .xlevel = 0x80000008, + .model_id = "Intel Xeon Processor (Icelake)", + }, +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-add-VMX-features.patch b/SOURCES/kvm-target-i386-add-VMX-features.patch new file mode 100644 index 0000000..7bbb35a --- /dev/null +++ b/SOURCES/kvm-target-i386-add-VMX-features.patch @@ -0,0 +1,503 @@ +From 88ab13cec526a16cb02bf1af51bdd33230308d36 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Fri, 22 Nov 2019 11:53:44 +0000 +Subject: [PATCH 11/16] target/i386: add VMX features + +RH-Author: Paolo Bonzini +Message-id: <20191122115348.25000-12-pbonzini@redhat.com> +Patchwork-id: 92608 +O-Subject: [RHEL8.2/rhel qemu-kvm PATCH 11/15] target/i386: add VMX features +Bugzilla: 1689270 +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Eduardo Habkost +RH-Acked-by: Maxim Levitsky + +Add code to convert the VMX feature words back into MSR values, +allowing the user to enable/disable VMX features as they wish. The same +infrastructure enables support for limiting VMX features in named +CPU models. + +Signed-off-by: Paolo Bonzini +(cherry picked from commit 20a78b02d31534ae478779c2f2816c273601e869) +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.c | 225 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ + target/i386/cpu.h | 9 +++ + target/i386/kvm.c | 162 ++++++++++++++++++++++++++++++++++++++- + 3 files changed, 394 insertions(+), 2 deletions(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index 3e77830..9074a2e 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -1171,6 +1171,163 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { + .index = MSR_IA32_CORE_CAPABILITY, + }, + }, ++ ++ [FEAT_VMX_PROCBASED_CTLS] = { ++ .type = MSR_FEATURE_WORD, ++ .feat_names = { ++ NULL, NULL, "vmx-vintr-pending", "vmx-tsc-offset", ++ NULL, NULL, NULL, "vmx-hlt-exit", ++ NULL, "vmx-invlpg-exit", "vmx-mwait-exit", "vmx-rdpmc-exit", ++ "vmx-rdtsc-exit", NULL, NULL, "vmx-cr3-load-noexit", ++ "vmx-cr3-store-noexit", NULL, NULL, "vmx-cr8-load-exit", ++ "vmx-cr8-store-exit", "vmx-flexpriority", "vmx-vnmi-pending", "vmx-movdr-exit", ++ "vmx-io-exit", "vmx-io-bitmap", NULL, "vmx-mtf", ++ "vmx-msr-bitmap", "vmx-monitor-exit", "vmx-pause-exit", "vmx-secondary-ctls", ++ }, ++ .msr = { ++ .index = MSR_IA32_VMX_TRUE_PROCBASED_CTLS, ++ } ++ }, ++ ++ [FEAT_VMX_SECONDARY_CTLS] = { ++ .type = MSR_FEATURE_WORD, ++ .feat_names = { ++ "vmx-apicv-xapic", "vmx-ept", "vmx-desc-exit", "vmx-rdtscp-exit", ++ "vmx-apicv-x2apic", "vmx-vpid", "vmx-wbinvd-exit", "vmx-unrestricted-guest", ++ "vmx-apicv-register", "vmx-apicv-vid", "vmx-ple", "vmx-rdrand-exit", ++ "vmx-invpcid-exit", "vmx-vmfunc", "vmx-shadow-vmcs", "vmx-encls-exit", ++ "vmx-rdseed-exit", "vmx-pml", NULL, NULL, ++ "vmx-xsaves", NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ }, ++ .msr = { ++ .index = MSR_IA32_VMX_PROCBASED_CTLS2, ++ } ++ }, ++ ++ [FEAT_VMX_PINBASED_CTLS] = { ++ .type = MSR_FEATURE_WORD, ++ .feat_names = { ++ "vmx-intr-exit", NULL, NULL, "vmx-nmi-exit", ++ NULL, "vmx-vnmi", "vmx-preemption-timer", "vmx-posted-intr", ++ NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ }, ++ .msr = { ++ .index = MSR_IA32_VMX_TRUE_PINBASED_CTLS, ++ } ++ }, ++ ++ [FEAT_VMX_EXIT_CTLS] = { ++ .type = MSR_FEATURE_WORD, ++ /* ++ * VMX_VM_EXIT_HOST_ADDR_SPACE_SIZE is copied from ++ * the LM CPUID bit. ++ */ ++ .feat_names = { ++ NULL, NULL, "vmx-exit-nosave-debugctl", NULL, ++ NULL, NULL, NULL, NULL, ++ NULL, NULL /* vmx-exit-host-addr-space-size */, NULL, NULL, ++ "vmx-exit-load-perf-global-ctrl", NULL, NULL, "vmx-exit-ack-intr", ++ NULL, NULL, "vmx-exit-save-pat", "vmx-exit-load-pat", ++ "vmx-exit-save-efer", "vmx-exit-load-efer", ++ "vmx-exit-save-preemption-timer", "vmx-exit-clear-bndcfgs", ++ NULL, "vmx-exit-clear-rtit-ctl", NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ }, ++ .msr = { ++ .index = MSR_IA32_VMX_TRUE_EXIT_CTLS, ++ } ++ }, ++ ++ [FEAT_VMX_ENTRY_CTLS] = { ++ .type = MSR_FEATURE_WORD, ++ .feat_names = { ++ NULL, NULL, "vmx-entry-noload-debugctl", NULL, ++ NULL, NULL, NULL, NULL, ++ NULL, "vmx-entry-ia32e-mode", NULL, NULL, ++ NULL, "vmx-entry-load-perf-global-ctrl", "vmx-entry-load-pat", "vmx-entry-load-efer", ++ "vmx-entry-load-bndcfgs", NULL, "vmx-entry-load-rtit-ctl", NULL, ++ NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ }, ++ .msr = { ++ .index = MSR_IA32_VMX_TRUE_ENTRY_CTLS, ++ } ++ }, ++ ++ [FEAT_VMX_MISC] = { ++ .type = MSR_FEATURE_WORD, ++ .feat_names = { ++ NULL, NULL, NULL, NULL, ++ NULL, "vmx-store-lma", "vmx-activity-hlt", "vmx-activity-shutdown", ++ "vmx-activity-wait-sipi", NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ NULL, "vmx-vmwrite-vmexit-fields", "vmx-zero-len-inject", NULL, ++ }, ++ .msr = { ++ .index = MSR_IA32_VMX_MISC, ++ } ++ }, ++ ++ [FEAT_VMX_EPT_VPID_CAPS] = { ++ .type = MSR_FEATURE_WORD, ++ .feat_names = { ++ "vmx-ept-execonly", NULL, NULL, NULL, ++ NULL, NULL, "vmx-page-walk-4", "vmx-page-walk-5", ++ NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ "vmx-ept-2mb", "vmx-ept-1gb", NULL, NULL, ++ "vmx-invept", "vmx-eptad", "vmx-ept-advanced-exitinfo", NULL, ++ NULL, "vmx-invept-single-context", "vmx-invept-all-context", NULL, ++ NULL, NULL, NULL, NULL, ++ "vmx-invvpid", NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ "vmx-invvpid-single-addr", "vmx-invept-single-context", ++ "vmx-invvpid-all-context", "vmx-invept-single-context-noglobals", ++ NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ }, ++ .msr = { ++ .index = MSR_IA32_VMX_EPT_VPID_CAP, ++ } ++ }, ++ ++ [FEAT_VMX_BASIC] = { ++ .type = MSR_FEATURE_WORD, ++ .feat_names = { ++ [54] = "vmx-ins-outs", ++ [55] = "vmx-true-ctls", ++ }, ++ .msr = { ++ .index = MSR_IA32_VMX_BASIC, ++ }, ++ /* Just to be safe - we don't support setting the MSEG version field. */ ++ .no_autoenable_flags = MSR_VMX_BASIC_DUAL_MONITOR, ++ }, ++ ++ [FEAT_VMX_VMFUNC] = { ++ .type = MSR_FEATURE_WORD, ++ .feat_names = { ++ [0] = "vmx-eptp-switching", ++ }, ++ .msr = { ++ .index = MSR_IA32_VMX_VMFUNC, ++ } ++ }, ++ + }; + + typedef struct FeatureMask { +@@ -1191,6 +1348,74 @@ static FeatureDep feature_dependencies[] = { + .from = { FEAT_7_0_EDX, CPUID_7_0_EDX_CORE_CAPABILITY }, + .to = { FEAT_CORE_CAPABILITY, ~0ull }, + }, ++ { ++ .from = { FEAT_1_ECX, CPUID_EXT_VMX }, ++ .to = { FEAT_VMX_PROCBASED_CTLS, ~0ull }, ++ }, ++ { ++ .from = { FEAT_1_ECX, CPUID_EXT_VMX }, ++ .to = { FEAT_VMX_PINBASED_CTLS, ~0ull }, ++ }, ++ { ++ .from = { FEAT_1_ECX, CPUID_EXT_VMX }, ++ .to = { FEAT_VMX_EXIT_CTLS, ~0ull }, ++ }, ++ { ++ .from = { FEAT_1_ECX, CPUID_EXT_VMX }, ++ .to = { FEAT_VMX_ENTRY_CTLS, ~0ull }, ++ }, ++ { ++ .from = { FEAT_1_ECX, CPUID_EXT_VMX }, ++ .to = { FEAT_VMX_MISC, ~0ull }, ++ }, ++ { ++ .from = { FEAT_1_ECX, CPUID_EXT_VMX }, ++ .to = { FEAT_VMX_BASIC, ~0ull }, ++ }, ++ { ++ .from = { FEAT_8000_0001_EDX, CPUID_EXT2_LM }, ++ .to = { FEAT_VMX_ENTRY_CTLS, VMX_VM_ENTRY_IA32E_MODE }, ++ }, ++ { ++ .from = { FEAT_VMX_PROCBASED_CTLS, VMX_CPU_BASED_ACTIVATE_SECONDARY_CONTROLS }, ++ .to = { FEAT_VMX_SECONDARY_CTLS, ~0ull }, ++ }, ++ { ++ .from = { FEAT_XSAVE, CPUID_XSAVE_XSAVES }, ++ .to = { FEAT_VMX_SECONDARY_CTLS, VMX_SECONDARY_EXEC_XSAVES }, ++ }, ++ { ++ .from = { FEAT_1_ECX, CPUID_EXT_RDRAND }, ++ .to = { FEAT_VMX_SECONDARY_CTLS, VMX_SECONDARY_EXEC_RDRAND_EXITING }, ++ }, ++ { ++ .from = { FEAT_7_0_EBX, CPUID_7_0_EBX_INVPCID }, ++ .to = { FEAT_VMX_SECONDARY_CTLS, VMX_SECONDARY_EXEC_ENABLE_INVPCID }, ++ }, ++ { ++ .from = { FEAT_7_0_EBX, CPUID_7_0_EBX_RDSEED }, ++ .to = { FEAT_VMX_SECONDARY_CTLS, VMX_SECONDARY_EXEC_RDSEED_EXITING }, ++ }, ++ { ++ .from = { FEAT_8000_0001_EDX, CPUID_EXT2_RDTSCP }, ++ .to = { FEAT_VMX_SECONDARY_CTLS, VMX_SECONDARY_EXEC_RDTSCP }, ++ }, ++ { ++ .from = { FEAT_VMX_SECONDARY_CTLS, VMX_SECONDARY_EXEC_ENABLE_EPT }, ++ .to = { FEAT_VMX_EPT_VPID_CAPS, 0xffffffffull }, ++ }, ++ { ++ .from = { FEAT_VMX_SECONDARY_CTLS, VMX_SECONDARY_EXEC_ENABLE_EPT }, ++ .to = { FEAT_VMX_SECONDARY_CTLS, VMX_SECONDARY_EXEC_UNRESTRICTED_GUEST }, ++ }, ++ { ++ .from = { FEAT_VMX_SECONDARY_CTLS, VMX_SECONDARY_EXEC_ENABLE_VPID }, ++ .to = { FEAT_VMX_EPT_VPID_CAPS, 0xffffffffull << 32 }, ++ }, ++ { ++ .from = { FEAT_VMX_SECONDARY_CTLS, VMX_SECONDARY_EXEC_ENABLE_VMFUNC }, ++ .to = { FEAT_VMX_VMFUNC, ~0ull }, ++ }, + }; + + typedef struct X86RegisterInfo32 { +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index 2d1f247..386e821 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -522,6 +522,15 @@ typedef enum FeatureWord { + FEAT_XSAVE_COMP_HI, /* CPUID[EAX=0xd,ECX=0].EDX */ + FEAT_ARCH_CAPABILITIES, + FEAT_CORE_CAPABILITY, ++ FEAT_VMX_PROCBASED_CTLS, ++ FEAT_VMX_SECONDARY_CTLS, ++ FEAT_VMX_PINBASED_CTLS, ++ FEAT_VMX_EXIT_CTLS, ++ FEAT_VMX_ENTRY_CTLS, ++ FEAT_VMX_MISC, ++ FEAT_VMX_EPT_VPID_CAPS, ++ FEAT_VMX_BASIC, ++ FEAT_VMX_VMFUNC, + FEATURE_WORDS, + } FeatureWord; + +diff --git a/target/i386/kvm.c b/target/i386/kvm.c +index 85abd37..512d7d5 100644 +--- a/target/i386/kvm.c ++++ b/target/i386/kvm.c +@@ -96,6 +96,7 @@ static bool has_msr_virt_ssbd; + static bool has_msr_smi_count; + static bool has_msr_arch_capabs; + static bool has_msr_core_capabs; ++static bool has_msr_vmx_vmfunc; + + static uint32_t has_architectural_pmu_version; + static uint32_t num_architectural_pmu_gp_counters; +@@ -429,7 +430,8 @@ uint64_t kvm_arch_get_supported_msr_feature(KVMState *s, uint32_t index) + struct kvm_msrs info; + struct kvm_msr_entry entries[1]; + } msr_data; +- uint32_t ret; ++ uint64_t value; ++ uint32_t ret, can_be_one, must_be_one; + + if (kvm_feature_msrs == NULL) { /* Host doesn't support feature MSRs */ + return 0; +@@ -455,7 +457,25 @@ uint64_t kvm_arch_get_supported_msr_feature(KVMState *s, uint32_t index) + exit(1); + } + +- return msr_data.entries[0].data; ++ value = msr_data.entries[0].data; ++ switch (index) { ++ case MSR_IA32_VMX_PROCBASED_CTLS2: ++ case MSR_IA32_VMX_TRUE_PINBASED_CTLS: ++ case MSR_IA32_VMX_TRUE_PROCBASED_CTLS: ++ case MSR_IA32_VMX_TRUE_ENTRY_CTLS: ++ case MSR_IA32_VMX_TRUE_EXIT_CTLS: ++ /* ++ * Return true for bits that can be one, but do not have to be one. ++ * The SDM tells us which bits could have a "must be one" setting, ++ * so we can do the opposite transformation in make_vmx_msr_value. ++ */ ++ must_be_one = (uint32_t)value; ++ can_be_one = (uint32_t)(value >> 32); ++ return can_be_one & ~must_be_one; ++ ++ default: ++ return value; ++ } + } + + +@@ -1430,6 +1450,9 @@ static int kvm_get_supported_msrs(KVMState *s) + case MSR_IA32_CORE_CAPABILITY: + has_msr_core_capabs = true; + break; ++ case MSR_IA32_VMX_VMFUNC: ++ has_msr_vmx_vmfunc = true; ++ break; + } + } + } +@@ -1886,6 +1909,132 @@ static int kvm_put_msr_feature_control(X86CPU *cpu) + return 0; + } + ++static uint64_t make_vmx_msr_value(uint32_t index, uint32_t features) ++{ ++ uint32_t default1, can_be_one, can_be_zero; ++ uint32_t must_be_one; ++ ++ switch (index) { ++ case MSR_IA32_VMX_TRUE_PINBASED_CTLS: ++ default1 = 0x00000016; ++ break; ++ case MSR_IA32_VMX_TRUE_PROCBASED_CTLS: ++ default1 = 0x0401e172; ++ break; ++ case MSR_IA32_VMX_TRUE_ENTRY_CTLS: ++ default1 = 0x000011ff; ++ break; ++ case MSR_IA32_VMX_TRUE_EXIT_CTLS: ++ default1 = 0x00036dff; ++ break; ++ case MSR_IA32_VMX_PROCBASED_CTLS2: ++ default1 = 0; ++ break; ++ default: ++ abort(); ++ } ++ ++ /* If a feature bit is set, the control can be either set or clear. ++ * Otherwise the value is limited to either 0 or 1 by default1. ++ */ ++ can_be_one = features | default1; ++ can_be_zero = features | ~default1; ++ must_be_one = ~can_be_zero; ++ ++ /* ++ * Bit 0:31 -> 0 if the control bit can be zero (i.e. 1 if it must be one). ++ * Bit 32:63 -> 1 if the control bit can be one. ++ */ ++ return must_be_one | (((uint64_t)can_be_one) << 32); ++} ++ ++#define VMCS12_MAX_FIELD_INDEX (0x17) ++ ++static void kvm_msr_entry_add_vmx(X86CPU *cpu, FeatureWordArray f) ++{ ++ uint64_t kvm_vmx_basic = ++ kvm_arch_get_supported_msr_feature(kvm_state, ++ MSR_IA32_VMX_BASIC); ++ uint64_t kvm_vmx_misc = ++ kvm_arch_get_supported_msr_feature(kvm_state, ++ MSR_IA32_VMX_MISC); ++ uint64_t kvm_vmx_ept_vpid = ++ kvm_arch_get_supported_msr_feature(kvm_state, ++ MSR_IA32_VMX_EPT_VPID_CAP); ++ ++ /* ++ * If the guest is 64-bit, a value of 1 is allowed for the host address ++ * space size vmexit control. ++ */ ++ uint64_t fixed_vmx_exit = f[FEAT_8000_0001_EDX] & CPUID_EXT2_LM ++ ? (uint64_t)VMX_VM_EXIT_HOST_ADDR_SPACE_SIZE << 32 : 0; ++ ++ /* ++ * Bits 0-30, 32-44 and 50-53 come from the host. KVM should ++ * not change them for backwards compatibility. ++ */ ++ uint64_t fixed_vmx_basic = kvm_vmx_basic & ++ (MSR_VMX_BASIC_VMCS_REVISION_MASK | ++ MSR_VMX_BASIC_VMXON_REGION_SIZE_MASK | ++ MSR_VMX_BASIC_VMCS_MEM_TYPE_MASK); ++ ++ /* ++ * Same for bits 0-4 and 25-27. Bits 16-24 (CR3 target count) can ++ * change in the future but are always zero for now, clear them to be ++ * future proof. Bits 32-63 in theory could change, though KVM does ++ * not support dual-monitor treatment and probably never will; mask ++ * them out as well. ++ */ ++ uint64_t fixed_vmx_misc = kvm_vmx_misc & ++ (MSR_VMX_MISC_PREEMPTION_TIMER_SHIFT_MASK | ++ MSR_VMX_MISC_MAX_MSR_LIST_SIZE_MASK); ++ ++ /* ++ * EPT memory types should not change either, so we do not bother ++ * adding features for them. ++ */ ++ uint64_t fixed_vmx_ept_mask = ++ (f[FEAT_VMX_SECONDARY_CTLS] & VMX_SECONDARY_EXEC_ENABLE_EPT ? ++ MSR_VMX_EPT_UC | MSR_VMX_EPT_WB : 0); ++ uint64_t fixed_vmx_ept_vpid = kvm_vmx_ept_vpid & fixed_vmx_ept_mask; ++ ++ kvm_msr_entry_add(cpu, MSR_IA32_VMX_TRUE_PROCBASED_CTLS, ++ make_vmx_msr_value(MSR_IA32_VMX_TRUE_PROCBASED_CTLS, ++ f[FEAT_VMX_PROCBASED_CTLS])); ++ kvm_msr_entry_add(cpu, MSR_IA32_VMX_TRUE_PINBASED_CTLS, ++ make_vmx_msr_value(MSR_IA32_VMX_TRUE_PINBASED_CTLS, ++ f[FEAT_VMX_PINBASED_CTLS])); ++ kvm_msr_entry_add(cpu, MSR_IA32_VMX_TRUE_EXIT_CTLS, ++ make_vmx_msr_value(MSR_IA32_VMX_TRUE_EXIT_CTLS, ++ f[FEAT_VMX_EXIT_CTLS]) | fixed_vmx_exit); ++ kvm_msr_entry_add(cpu, MSR_IA32_VMX_TRUE_ENTRY_CTLS, ++ make_vmx_msr_value(MSR_IA32_VMX_TRUE_ENTRY_CTLS, ++ f[FEAT_VMX_ENTRY_CTLS])); ++ kvm_msr_entry_add(cpu, MSR_IA32_VMX_PROCBASED_CTLS2, ++ make_vmx_msr_value(MSR_IA32_VMX_PROCBASED_CTLS2, ++ f[FEAT_VMX_SECONDARY_CTLS])); ++ kvm_msr_entry_add(cpu, MSR_IA32_VMX_EPT_VPID_CAP, ++ f[FEAT_VMX_EPT_VPID_CAPS] | fixed_vmx_ept_vpid); ++ kvm_msr_entry_add(cpu, MSR_IA32_VMX_BASIC, ++ f[FEAT_VMX_BASIC] | fixed_vmx_basic); ++ kvm_msr_entry_add(cpu, MSR_IA32_VMX_MISC, ++ f[FEAT_VMX_MISC] | fixed_vmx_misc); ++ if (has_msr_vmx_vmfunc) { ++ kvm_msr_entry_add(cpu, MSR_IA32_VMX_VMFUNC, f[FEAT_VMX_VMFUNC]); ++ } ++ ++ /* ++ * Just to be safe, write these with constant values. The CRn_FIXED1 ++ * MSRs are generated by KVM based on the vCPU's CPUID. ++ */ ++ kvm_msr_entry_add(cpu, MSR_IA32_VMX_CR0_FIXED0, ++ CR0_PE_MASK | CR0_PG_MASK | CR0_NE_MASK); ++ kvm_msr_entry_add(cpu, MSR_IA32_VMX_CR4_FIXED0, ++ CR4_VMXE_MASK); ++ kvm_msr_entry_add(cpu, MSR_IA32_VMX_VMCS_ENUM, ++ VMCS12_MAX_FIELD_INDEX << 1); ++} ++ + static int kvm_put_msrs(X86CPU *cpu, int level) + { + CPUX86State *env = &cpu->env; +@@ -2112,7 +2261,16 @@ static int kvm_put_msrs(X86CPU *cpu, int level) + + /* Note: MSR_IA32_FEATURE_CONTROL is written separately, see + * kvm_put_msr_feature_control. */ ++ ++ /* ++ * Older kernels do not include VMX MSRs in KVM_GET_MSR_INDEX_LIST, but ++ * all kernels with MSR features should have them. ++ */ ++ if (kvm_feature_msrs && cpu_has_vmx(env)) { ++ kvm_msr_entry_add_vmx(cpu, env->features); ++ } + } ++ + if (env->mcg_cap) { + int i; + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-add-support-for-MSR_IA32_TSX_CTRL.patch b/SOURCES/kvm-target-i386-add-support-for-MSR_IA32_TSX_CTRL.patch new file mode 100644 index 0000000..fab9b64 --- /dev/null +++ b/SOURCES/kvm-target-i386-add-support-for-MSR_IA32_TSX_CTRL.patch @@ -0,0 +1,161 @@ +From 39c3a18b4b956d0533e07de2640be064e07e3c97 Mon Sep 17 00:00:00 2001 +From: Eduardo Habkost +Date: Tue, 3 Dec 2019 23:53:08 +0000 +Subject: [PATCH 2/2] target/i386: add support for MSR_IA32_TSX_CTRL + +RH-Author: Eduardo Habkost +Message-id: <20191203235308.590845-3-ehabkost@redhat.com> +Patchwork-id: 92850 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH 2/2] target/i386: add support for MSR_IA32_TSX_CTRL +Bugzilla: 1771971 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Igor Mammedov + +From: Paolo Bonzini + +The MSR_IA32_TSX_CTRL MSR can be used to hide TSX (also known as the +Trusty Side-channel Extension). By virtualizing the MSR, KVM guests +can disable TSX and avoid paying the price of mitigating TSX-based +attacks on microarchitectural side channels. + +Reviewed-by: Eduardo Habkost +Signed-off-by: Paolo Bonzini +(cherry picked from commit 2a9758c51e2c2d13fc3845c3d603c11df98b8823) +Signed-off-by: Eduardo Habkost +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.c | 2 +- + target/i386/cpu.h | 4 ++++ + target/i386/kvm.c | 13 +++++++++++++ + target/i386/machine.c | 20 ++++++++++++++++++++ + 4 files changed, 38 insertions(+), 1 deletion(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index 68fe865..ef6b958 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -1143,7 +1143,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { + .type = MSR_FEATURE_WORD, + .feat_names = { + "rdctl-no", "ibrs-all", "rsba", "skip-l1dfl-vmentry", +- "ssb-no", "mds-no", NULL, NULL, ++ "ssb-no", "mds-no", NULL, "tsx-ctrl", + "taa-no", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index 386e821..8d8814e 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -355,6 +355,9 @@ typedef enum X86Seg { + #define MSR_IA32_PRED_CMD 0x49 + #define MSR_IA32_CORE_CAPABILITY 0xcf + #define MSR_IA32_ARCH_CAPABILITIES 0x10a ++#define ARCH_CAP_TSX_CTRL_MSR (1<<7) ++ ++#define MSR_IA32_TSX_CTRL 0x122 + #define MSR_IA32_TSCDEADLINE 0x6e0 + + #define FEATURE_CONTROL_LOCKED (1<<0) +@@ -1373,6 +1376,7 @@ typedef struct CPUX86State { + uint64_t msr_smi_count; + + uint32_t pkru; ++ uint32_t tsx_ctrl; + + uint64_t spec_ctrl; + uint64_t virt_ssbd; +diff --git a/target/i386/kvm.c b/target/i386/kvm.c +index 6366172..107c53b 100644 +--- a/target/i386/kvm.c ++++ b/target/i386/kvm.c +@@ -92,6 +92,7 @@ static bool has_msr_hv_stimer; + static bool has_msr_hv_frequencies; + static bool has_msr_xss; + static bool has_msr_spec_ctrl; ++static bool has_msr_tsx_ctrl; + static bool has_msr_virt_ssbd; + static bool has_msr_smi_count; + static bool has_msr_arch_capabs; +@@ -1458,6 +1459,9 @@ static int kvm_get_supported_msrs(KVMState *s) + case MSR_IA32_SPEC_CTRL: + has_msr_spec_ctrl = true; + break; ++ case MSR_IA32_TSX_CTRL: ++ has_msr_tsx_ctrl = true; ++ break; + case MSR_VIRT_SSBD: + has_msr_virt_ssbd = true; + break; +@@ -2095,6 +2099,9 @@ static int kvm_put_msrs(X86CPU *cpu, int level) + if (has_msr_spec_ctrl) { + kvm_msr_entry_add(cpu, MSR_IA32_SPEC_CTRL, env->spec_ctrl); + } ++ if (has_msr_tsx_ctrl) { ++ kvm_msr_entry_add(cpu, MSR_IA32_TSX_CTRL, env->tsx_ctrl); ++ } + if (has_msr_virt_ssbd) { + kvm_msr_entry_add(cpu, MSR_VIRT_SSBD, env->virt_ssbd); + } +@@ -2491,6 +2498,9 @@ static int kvm_get_msrs(X86CPU *cpu) + if (has_msr_spec_ctrl) { + kvm_msr_entry_add(cpu, MSR_IA32_SPEC_CTRL, 0); + } ++ if (has_msr_tsx_ctrl) { ++ kvm_msr_entry_add(cpu, MSR_IA32_TSX_CTRL, 0); ++ } + if (has_msr_virt_ssbd) { + kvm_msr_entry_add(cpu, MSR_VIRT_SSBD, 0); + } +@@ -2862,6 +2872,9 @@ static int kvm_get_msrs(X86CPU *cpu) + case MSR_IA32_SPEC_CTRL: + env->spec_ctrl = msrs[i].data; + break; ++ case MSR_IA32_TSX_CTRL: ++ env->tsx_ctrl = msrs[i].data; ++ break; + case MSR_VIRT_SSBD: + env->virt_ssbd = msrs[i].data; + break; +diff --git a/target/i386/machine.c b/target/i386/machine.c +index fa8d1cc..76b173c 100644 +--- a/target/i386/machine.c ++++ b/target/i386/machine.c +@@ -1226,6 +1226,25 @@ static const VMStateDescription vmstate_efer32 = { + }; + #endif + ++static bool msr_tsx_ctrl_needed(void *opaque) ++{ ++ X86CPU *cpu = opaque; ++ CPUX86State *env = &cpu->env; ++ ++ return env->features[FEAT_ARCH_CAPABILITIES] & ARCH_CAP_TSX_CTRL_MSR; ++} ++ ++static const VMStateDescription vmstate_msr_tsx_ctrl = { ++ .name = "cpu/msr_tsx_ctrl", ++ .version_id = 1, ++ .minimum_version_id = 1, ++ .needed = msr_tsx_ctrl_needed, ++ .fields = (VMStateField[]) { ++ VMSTATE_UINT32(env.tsx_ctrl, X86CPU), ++ VMSTATE_END_OF_LIST() ++ } ++}; ++ + VMStateDescription vmstate_x86_cpu = { + .name = "cpu", + .version_id = 12, +@@ -1357,6 +1376,7 @@ VMStateDescription vmstate_x86_cpu = { + #ifdef CONFIG_KVM + &vmstate_nested_state, + #endif ++ &vmstate_msr_tsx_ctrl, + NULL + } + }; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-adjust-for-missing-VMX-features.patch b/SOURCES/kvm-target-i386-adjust-for-missing-VMX-features.patch new file mode 100644 index 0000000..c193e7f --- /dev/null +++ b/SOURCES/kvm-target-i386-adjust-for-missing-VMX-features.patch @@ -0,0 +1,49 @@ +From 76abda27a42dfe08598b38582210f7aeb31e6685 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Fri, 22 Nov 2019 11:53:46 +0000 +Subject: [PATCH 13/16] target/i386: adjust for missing VMX features + +RH-Author: Paolo Bonzini +Message-id: <20191122115348.25000-14-pbonzini@redhat.com> +Patchwork-id: 92611 +O-Subject: [RHEL8.2/rhel qemu-kvm PATCH 13/15] target/i386: adjust for missing VMX features +Bugzilla: 1689270 +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Eduardo Habkost +RH-Acked-by: Maxim Levitsky + +vmx-exit-load-perf-global-ctrl and vmx-entry-load-perf-global-ctrl +have only been added to kernel 5.4, so disable them in RHEL until +we add them to the kernel. At that point, they could be added back +to a new machine type. + +Signed-off-by: Paolo Bonzini +Signed-off-by: Danilo C. L. de Paula +--- + include/hw/i386/pc.h | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h +index 88ffd40..b546aed 100644 +--- a/include/hw/i386/pc.h ++++ b/include/hw/i386/pc.h +@@ -968,6 +968,16 @@ extern void igd_passthrough_isa_bridge_create(PCIBus *bus, uint16_t gpu_dev_id); + #define PC_RHEL_COMPAT \ + { /* PC_RHEL_COMPAT */ \ + .driver = TYPE_X86_CPU,\ ++ .property = "vmx-exit-load-perf-global-ctrl",\ ++ .value = "off",\ ++ },\ ++ { /* PC_RHEL_COMPAT */ \ ++ .driver = TYPE_X86_CPU,\ ++ .property = "vmx-entry-load-perf-global-ctrl",\ ++ .value = "off",\ ++ },\ ++ { /* PC_RHEL_COMPAT */ \ ++ .driver = TYPE_X86_CPU,\ + .property = "host-phys-bits",\ + .value = "on",\ + },\ +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-define-a-new-MSR-based-feature-word-FEAT.patch b/SOURCES/kvm-target-i386-define-a-new-MSR-based-feature-word-FEAT.patch new file mode 100644 index 0000000..5654ec6 --- /dev/null +++ b/SOURCES/kvm-target-i386-define-a-new-MSR-based-feature-word-FEAT.patch @@ -0,0 +1,152 @@ +From 127410386296459cf3eec4b12d7451afc50d2503 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Fri, 22 Nov 2019 11:53:36 +0000 +Subject: [PATCH 03/16] target/i386: define a new MSR based feature word - + FEAT_CORE_CAPABILITY + +RH-Author: Paolo Bonzini +Message-id: <20191122115348.25000-4-pbonzini@redhat.com> +Patchwork-id: 92603 +O-Subject: [RHEL8.2/rhel qemu-kvm PATCH 03/15] target/i386: define a new MSR based feature word - FEAT_CORE_CAPABILITY +Bugzilla: 1689270 +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Eduardo Habkost +RH-Acked-by: Maxim Levitsky + +From: Xiaoyao Li + +MSR IA32_CORE_CAPABILITY is a feature-enumerating MSR, which only +enumerates the feature split lock detection (via bit 5) by now. + +The existence of MSR IA32_CORE_CAPABILITY is enumerated by CPUID.7_0:EDX[30]. + +The latest kernel patches about them can be found here: +https://lkml.org/lkml/2019/4/24/1909 + +Signed-off-by: Xiaoyao Li +Message-Id: <20190617153654.916-1-xiaoyao.li@linux.intel.com> +Signed-off-by: Paolo Bonzini +(cherry picked from commit 597360c0d8ebda9ca6f239db724a25bddec62b2f) + +RHEL: context +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.c | 22 +++++++++++++++++++++- + target/i386/cpu.h | 5 +++++ + target/i386/kvm.c | 9 +++++++++ + 3 files changed, 35 insertions(+), 1 deletion(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index 8c1338f..52f1f33 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -1045,7 +1045,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + NULL, NULL, "spec-ctrl", "stibp", +- NULL, "arch-capabilities", NULL, "ssbd", ++ NULL, "arch-capabilities", "core-capability", "ssbd", + }, + .cpuid = { + .eax = 7, +@@ -1163,6 +1163,26 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { + } + }, + }, ++ [FEAT_CORE_CAPABILITY] = { ++ .type = MSR_FEATURE_WORD, ++ .feat_names = { ++ NULL, NULL, NULL, NULL, ++ NULL, "split-lock-detect", NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ }, ++ .msr = { ++ .index = MSR_IA32_CORE_CAPABILITY, ++ .cpuid_dep = { ++ FEAT_7_0_EDX, ++ CPUID_7_0_EDX_CORE_CAPABILITY, ++ }, ++ }, ++ }, + }; + + typedef struct X86RegisterInfo32 { +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index 1ad54bd..f9b93be 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -353,6 +353,7 @@ typedef enum X86Seg { + #define MSR_IA32_SPEC_CTRL 0x48 + #define MSR_VIRT_SSBD 0xc001011f + #define MSR_IA32_PRED_CMD 0x49 ++#define MSR_IA32_CORE_CAPABILITY 0xcf + #define MSR_IA32_ARCH_CAPABILITIES 0x10a + #define MSR_IA32_TSCDEADLINE 0x6e0 + +@@ -501,6 +502,7 @@ typedef enum FeatureWord { + FEAT_XSAVE_COMP_LO, /* CPUID[EAX=0xd,ECX=0].EAX */ + FEAT_XSAVE_COMP_HI, /* CPUID[EAX=0xd,ECX=0].EDX */ + FEAT_ARCH_CAPABILITIES, ++ FEAT_CORE_CAPABILITY, + FEATURE_WORDS, + } FeatureWord; + +@@ -690,6 +692,7 @@ typedef uint32_t FeatureWordArray[FEATURE_WORDS]; + #define CPUID_7_0_EDX_AVX512_4FMAPS (1U << 3) /* AVX512 Multiply Accumulation Single Precision */ + #define CPUID_7_0_EDX_SPEC_CTRL (1U << 26) /* Speculation Control */ + #define CPUID_7_0_EDX_ARCH_CAPABILITIES (1U << 29) /*Arch Capabilities*/ ++#define CPUID_7_0_EDX_CORE_CAPABILITY (1U << 30) /*Core Capability*/ + #define CPUID_7_0_EDX_SPEC_CTRL_SSBD (1U << 31) /* Speculative Store Bypass Disable */ + + #define KVM_HINTS_DEDICATED (1U << 0) +@@ -744,6 +747,8 @@ typedef uint32_t FeatureWordArray[FEATURE_WORDS]; + #define MSR_ARCH_CAP_SKIP_L1DFL_VMENTRY (1U << 3) + #define MSR_ARCH_CAP_SSB_NO (1U << 4) + ++#define MSR_CORE_CAP_SPLIT_LOCK_DETECT (1U << 5) ++ + #ifndef HYPERV_SPINLOCK_NEVER_RETRY + #define HYPERV_SPINLOCK_NEVER_RETRY 0xFFFFFFFF + #endif +diff --git a/target/i386/kvm.c b/target/i386/kvm.c +index da5f07e..849a11a 100644 +--- a/target/i386/kvm.c ++++ b/target/i386/kvm.c +@@ -95,6 +95,7 @@ static bool has_msr_spec_ctrl; + static bool has_msr_virt_ssbd; + static bool has_msr_smi_count; + static bool has_msr_arch_capabs; ++static bool has_msr_core_capabs; + + static uint32_t has_architectural_pmu_version; + static uint32_t num_architectural_pmu_gp_counters; +@@ -1428,6 +1429,9 @@ static int kvm_get_supported_msrs(KVMState *s) + case MSR_IA32_ARCH_CAPABILITIES: + has_msr_arch_capabs = true; + break; ++ case MSR_IA32_CORE_CAPABILITY: ++ has_msr_core_capabs = true; ++ break; + } + } + } +@@ -1947,6 +1951,11 @@ static int kvm_put_msrs(X86CPU *cpu, int level) + env->features[FEAT_ARCH_CAPABILITIES]); + } + ++ if (has_msr_core_capabs) { ++ kvm_msr_entry_add(cpu, MSR_IA32_CORE_CAPABILITY, ++ env->features[FEAT_CORE_CAPABILITY]); ++ } ++ + /* + * The following MSRs have side effects on the guest or are too heavy + * for normal writeback. Limit them to reset or full state updates. +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-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-expand-feature-words-to-64-bits.patch b/SOURCES/kvm-target-i386-expand-feature-words-to-64-bits.patch new file mode 100644 index 0000000..11e064e --- /dev/null +++ b/SOURCES/kvm-target-i386-expand-feature-words-to-64-bits.patch @@ -0,0 +1,306 @@ +From a31ce6a9fa171f677bf52dd0b0076e7b92d9ae33 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Fri, 22 Nov 2019 11:53:41 +0000 +Subject: [PATCH 08/16] target/i386: expand feature words to 64 bits + +RH-Author: Paolo Bonzini +Message-id: <20191122115348.25000-9-pbonzini@redhat.com> +Patchwork-id: 92612 +O-Subject: [RHEL8.2/rhel qemu-kvm PATCH 08/15] target/i386: expand feature words to 64 bits +Bugzilla: 1689270 +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Eduardo Habkost +RH-Acked-by: Maxim Levitsky + +VMX requires 64-bit feature words for the IA32_VMX_EPT_VPID_CAP +and IA32_VMX_BASIC MSRs. (The VMX control MSRs are 64-bit wide but +actually have only 32 bits of information). + +Signed-off-by: Paolo Bonzini +(cherry picked from commit ede146c2e720b670350c7ef5e9af44e80a73fe97) +Signed-off-by: Danilo C. L. de Paula +--- + include/sysemu/kvm.h | 2 +- + target/i386/cpu.c | 71 +++++++++++++++++++++++++++------------------------- + target/i386/cpu.h | 2 +- + target/i386/kvm.c | 2 +- + 4 files changed, 40 insertions(+), 37 deletions(-) + +diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h +index 3cf04cf..2c7f841 100644 +--- a/include/sysemu/kvm.h ++++ b/include/sysemu/kvm.h +@@ -466,7 +466,7 @@ int kvm_vm_check_extension(KVMState *s, unsigned int extension); + + uint32_t kvm_arch_get_supported_cpuid(KVMState *env, uint32_t function, + uint32_t index, int reg); +-uint32_t kvm_arch_get_supported_msr_feature(KVMState *s, uint32_t index); ++uint64_t kvm_arch_get_supported_msr_feature(KVMState *s, uint32_t index); + + + void kvm_set_sigmask_len(KVMState *s, unsigned int sigmask_len); +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index a7360b3..3e77830 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -785,7 +785,7 @@ typedef struct FeatureWordInfo { + * In cases of disagreement between feature naming conventions, + * aliases may be added. + */ +- const char *feat_names[32]; ++ const char *feat_names[64]; + union { + /* If type==CPUID_FEATURE_WORD */ + struct { +@@ -799,11 +799,11 @@ typedef struct FeatureWordInfo { + uint32_t index; + } msr; + }; +- uint32_t tcg_features; /* Feature flags supported by TCG */ +- uint32_t unmigratable_flags; /* Feature flags known to be unmigratable */ +- uint32_t migratable_flags; /* Feature flags known to be migratable */ ++ uint64_t tcg_features; /* Feature flags supported by TCG */ ++ uint64_t unmigratable_flags; /* Feature flags known to be unmigratable */ ++ uint64_t migratable_flags; /* Feature flags known to be migratable */ + /* Features that shouldn't be auto-enabled by "-cpu host" */ +- uint32_t no_autoenable_flags; ++ uint64_t no_autoenable_flags; + } FeatureWordInfo; + + static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { +@@ -1175,7 +1175,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { + + typedef struct FeatureMask { + FeatureWord index; +- uint32_t mask; ++ uint64_t mask; + } FeatureMask; + + typedef struct FeatureDep { +@@ -1185,11 +1185,11 @@ typedef struct FeatureDep { + static FeatureDep feature_dependencies[] = { + { + .from = { FEAT_7_0_EDX, CPUID_7_0_EDX_ARCH_CAPABILITIES }, +- .to = { FEAT_ARCH_CAPABILITIES, ~0u }, ++ .to = { FEAT_ARCH_CAPABILITIES, ~0ull }, + }, + { + .from = { FEAT_7_0_EDX, CPUID_7_0_EDX_CORE_CAPABILITY }, +- .to = { FEAT_CORE_CAPABILITY, ~0u }, ++ .to = { FEAT_CORE_CAPABILITY, ~0ull }, + }, + }; + +@@ -1301,14 +1301,14 @@ const char *get_register_name_32(unsigned int reg) + * Returns the set of feature flags that are supported and migratable by + * QEMU, for a given FeatureWord. + */ +-static uint32_t x86_cpu_get_migratable_flags(FeatureWord w) ++static uint64_t x86_cpu_get_migratable_flags(FeatureWord w) + { + FeatureWordInfo *wi = &feature_word_info[w]; +- uint32_t r = 0; ++ uint64_t r = 0; + int i; + +- for (i = 0; i < 32; i++) { +- uint32_t f = 1U << i; ++ for (i = 0; i < 64; i++) { ++ uint64_t f = 1ULL << i; + + /* If the feature name is known, it is implicitly considered migratable, + * unless it is explicitly set in unmigratable_flags */ +@@ -2948,7 +2948,7 @@ void x86_cpu_change_kvm_default(const char *prop, const char *value) + assert(pv->prop); + } + +-static uint32_t x86_cpu_get_supported_feature_word(FeatureWord w, ++static uint64_t x86_cpu_get_supported_feature_word(FeatureWord w, + bool migratable_only); + + static bool lmce_supported(void) +@@ -3142,7 +3142,7 @@ static bool x86_cpu_have_filtered_features(X86CPU *cpu) + return false; + } + +-static void mark_unavailable_features(X86CPU *cpu, FeatureWord w, uint32_t mask, ++static void mark_unavailable_features(X86CPU *cpu, FeatureWord w, uint64_t mask, + const char *verbose_prefix) + { + CPUX86State *env = &cpu->env; +@@ -3159,8 +3159,8 @@ static void mark_unavailable_features(X86CPU *cpu, FeatureWord w, uint32_t mask, + return; + } + +- for (i = 0; i < 32; ++i) { +- if ((1UL << i) & mask) { ++ for (i = 0; i < 64; ++i) { ++ if ((1ULL << i) & mask) { + feat_word_str = feature_word_description(f, i); + warn_report("%s: %s%s%s [bit %d]", + verbose_prefix, +@@ -3403,7 +3403,7 @@ static void x86_cpu_get_feature_words(Object *obj, Visitor *v, + const char *name, void *opaque, + Error **errp) + { +- uint32_t *array = (uint32_t *)opaque; ++ uint64_t *array = (uint64_t *)opaque; + FeatureWord w; + X86CPUFeatureWordInfo word_infos[FEATURE_WORDS] = { }; + X86CPUFeatureWordInfoList list_entries[FEATURE_WORDS] = { }; +@@ -3487,6 +3487,7 @@ static inline void feat2prop(char *s) + /* Return the feature property name for a feature flag bit */ + static const char *x86_cpu_feature_name(FeatureWord w, int bitnr) + { ++ const char *name; + /* XSAVE components are automatically enabled by other features, + * so return the original feature name instead + */ +@@ -3500,9 +3501,11 @@ static const char *x86_cpu_feature_name(FeatureWord w, int bitnr) + } + } + +- assert(bitnr < 32); ++ assert(bitnr < 64); + assert(w < FEATURE_WORDS); +- return feature_word_info[w].feat_names[bitnr]; ++ name = feature_word_info[w].feat_names[bitnr]; ++ assert(bitnr < 32 || !(name && feature_word_info[w].type == CPUID_FEATURE_WORD)); ++ return name; + } + + /* Compatibily hack to maintain legacy +-feat semantic, +@@ -3619,10 +3622,10 @@ static void x86_cpu_list_feature_names(FeatureWordArray features, + strList **next = feat_names; + + for (w = 0; w < FEATURE_WORDS; w++) { +- uint32_t filtered = features[w]; ++ uint64_t filtered = features[w]; + int i; +- for (i = 0; i < 32; i++) { +- if (filtered & (1UL << i)) { ++ for (i = 0; i < 64; i++) { ++ if (filtered & (1ULL << i)) { + strList *new = g_new0(strList, 1); + new->value = g_strdup(x86_cpu_feature_name(w, i)); + *next = new; +@@ -3760,7 +3763,7 @@ void x86_cpu_list(FILE *f, fprintf_function cpu_fprintf) + names = NULL; + for (i = 0; i < ARRAY_SIZE(feature_word_info); i++) { + FeatureWordInfo *fw = &feature_word_info[i]; +- for (j = 0; j < 32; j++) { ++ for (j = 0; j < 64; j++) { + if (fw->feat_names[j]) { + names = g_list_append(names, (gpointer)fw->feat_names[j]); + } +@@ -3807,11 +3810,11 @@ CpuDefinitionInfoList *arch_query_cpu_definitions(Error **errp) + return cpu_list; + } + +-static uint32_t x86_cpu_get_supported_feature_word(FeatureWord w, ++static uint64_t x86_cpu_get_supported_feature_word(FeatureWord w, + bool migratable_only) + { + FeatureWordInfo *wi = &feature_word_info[w]; +- uint32_t r = 0; ++ uint64_t r = 0; + + if (kvm_enabled()) { + switch (wi->type) { +@@ -3950,7 +3953,7 @@ static QDict *x86_cpu_static_props(void) + for (w = 0; w < FEATURE_WORDS; w++) { + FeatureWordInfo *fi = &feature_word_info[w]; + int bit; +- for (bit = 0; bit < 32; bit++) { ++ for (bit = 0; bit < 64; bit++) { + if (!fi->feat_names[bit]) { + continue; + } +@@ -5015,7 +5018,7 @@ static void x86_cpu_expand_features(X86CPU *cpu, Error **errp) + for (i = 0; i < ARRAY_SIZE(feature_dependencies); i++) { + FeatureDep *d = &feature_dependencies[i]; + if (!(env->features[d->from.index] & d->from.mask)) { +- uint32_t unavailable_features = env->features[d->to.index] & d->to.mask; ++ uint64_t unavailable_features = env->features[d->to.index] & d->to.mask; + + /* Not an error unless the dependent feature was added explicitly. */ + mark_unavailable_features(cpu, d->to.index, +@@ -5094,10 +5097,10 @@ static void x86_cpu_filter_features(X86CPU *cpu, bool verbose) + } + + for (w = 0; w < FEATURE_WORDS; w++) { +- uint32_t host_feat = ++ uint64_t host_feat = + x86_cpu_get_supported_feature_word(w, false); +- uint32_t requested_features = env->features[w]; +- uint32_t unavailable_features = requested_features & ~host_feat; ++ uint64_t requested_features = env->features[w]; ++ uint64_t unavailable_features = requested_features & ~host_feat; + mark_unavailable_features(cpu, w, unavailable_features, prefix); + } + +@@ -5380,7 +5383,7 @@ static void x86_cpu_unrealizefn(DeviceState *dev, Error **errp) + + typedef struct BitProperty { + FeatureWord w; +- uint32_t mask; ++ uint64_t mask; + } BitProperty; + + static void x86_cpu_get_bit_prop(Object *obj, Visitor *v, const char *name, +@@ -5388,7 +5391,7 @@ static void x86_cpu_get_bit_prop(Object *obj, Visitor *v, const char *name, + { + X86CPU *cpu = X86_CPU(obj); + BitProperty *fp = opaque; +- uint32_t f = cpu->env.features[fp->w]; ++ uint64_t f = cpu->env.features[fp->w]; + bool value = (f & fp->mask) == fp->mask; + visit_type_bool(v, name, &value, errp); + } +@@ -5441,7 +5444,7 @@ static void x86_cpu_register_bit_prop(X86CPU *cpu, + { + BitProperty *fp; + ObjectProperty *op; +- uint32_t mask = (1UL << bitnr); ++ uint64_t mask = (1ULL << bitnr); + + op = object_property_find(OBJECT(cpu), prop_name, NULL); + if (op) { +@@ -5577,7 +5580,7 @@ static void x86_cpu_initfn(Object *obj) + for (w = 0; w < FEATURE_WORDS; w++) { + int bitnr; + +- for (bitnr = 0; bitnr < 32; bitnr++) { ++ for (bitnr = 0; bitnr < 64; bitnr++) { + x86_cpu_register_feature_bit_props(cpu, w, bitnr); + } + } +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index f9b93be..edba84e 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -506,7 +506,7 @@ typedef enum FeatureWord { + FEATURE_WORDS, + } FeatureWord; + +-typedef uint32_t FeatureWordArray[FEATURE_WORDS]; ++typedef uint64_t FeatureWordArray[FEATURE_WORDS]; + + /* cpuid_features bits */ + #define CPUID_FP87 (1U << 0) +diff --git a/target/i386/kvm.c b/target/i386/kvm.c +index 2290c5d..85abd37 100644 +--- a/target/i386/kvm.c ++++ b/target/i386/kvm.c +@@ -423,7 +423,7 @@ uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function, + return ret; + } + +-uint32_t kvm_arch_get_supported_msr_feature(KVMState *s, uint32_t index) ++uint64_t kvm_arch_get_supported_msr_feature(KVMState *s, uint32_t index) + { + struct { + struct kvm_msrs info; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-handle-filtered_features-in-a-new-functi.patch b/SOURCES/kvm-target-i386-handle-filtered_features-in-a-new-functi.patch new file mode 100644 index 0000000..f48b1d1 --- /dev/null +++ b/SOURCES/kvm-target-i386-handle-filtered_features-in-a-new-functi.patch @@ -0,0 +1,187 @@ +From d7362c761ef55b7f665c4dff61d9e58b153ff11c Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Fri, 22 Nov 2019 11:53:39 +0000 +Subject: [PATCH 06/16] target/i386: handle filtered_features in a new function + mark_unavailable_features + +RH-Author: Paolo Bonzini +Message-id: <20191122115348.25000-7-pbonzini@redhat.com> +Patchwork-id: 92600 +O-Subject: [RHEL8.2/rhel qemu-kvm PATCH 06/15] target/i386: handle filtered_features in a new function mark_unavailable_features +Bugzilla: 1689270 +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Eduardo Habkost +RH-Acked-by: Maxim Levitsky + +The next patch will add a different reason for filtering features, unrelated +to host feature support. Extract a new function that takes care of disabling +the features and optionally reporting them. + +Signed-off-by: Paolo Bonzini +(cherry picked from commit 245edd0cfb1481b7a0398cce45df23db50f00034) +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.c | 87 ++++++++++++++++++++++++++++++------------------------- + 1 file changed, 48 insertions(+), 39 deletions(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index d0c48c2..b06ce9d 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -3121,17 +3121,41 @@ static char *feature_word_description(FeatureWordInfo *f, uint32_t bit) + return NULL; + } + +-static void report_unavailable_features(FeatureWord w, uint32_t mask) ++static bool x86_cpu_have_filtered_features(X86CPU *cpu) + { ++ FeatureWord w; ++ ++ for (w = 0; w < FEATURE_WORDS; w++) { ++ if (cpu->filtered_features[w]) { ++ return true; ++ } ++ } ++ ++ return false; ++} ++ ++static void mark_unavailable_features(X86CPU *cpu, FeatureWord w, uint32_t mask, ++ const char *verbose_prefix) ++{ ++ CPUX86State *env = &cpu->env; + FeatureWordInfo *f = &feature_word_info[w]; + int i; + char *feat_word_str; + ++ if (!cpu->force_features) { ++ env->features[w] &= ~mask; ++ } ++ cpu->filtered_features[w] |= mask; ++ ++ if (!verbose_prefix) { ++ return; ++ } ++ + for (i = 0; i < 32; ++i) { + if ((1UL << i) & mask) { + feat_word_str = feature_word_description(f, i); +- warn_report("%s doesn't support requested feature: %s%s%s [bit %d]", +- accel_uses_host_cpuid() ? "host" : "TCG", ++ warn_report("%s: %s%s%s [bit %d]", ++ verbose_prefix, + feat_word_str, + f->feat_names[i] ? "." : "", + f->feat_names[i] ? f->feat_names[i] : "", i); +@@ -3577,7 +3601,7 @@ static void x86_cpu_parse_featurestr(const char *typename, char *features, + } + + static void x86_cpu_expand_features(X86CPU *cpu, Error **errp); +-static int x86_cpu_filter_features(X86CPU *cpu); ++static void x86_cpu_filter_features(X86CPU *cpu, bool verbose); + + /* Build a list with the name of all features on a feature word array */ + static void x86_cpu_list_feature_names(FeatureWordArray features, +@@ -3642,7 +3666,7 @@ static void x86_cpu_class_check_missing_features(X86CPUClass *xcc, + next = &new->next; + } + +- x86_cpu_filter_features(xc); ++ x86_cpu_filter_features(xc, false); + + x86_cpu_list_feature_names(xc->filtered_features, next); + +@@ -3811,15 +3835,6 @@ static uint32_t x86_cpu_get_supported_feature_word(FeatureWord w, + return r; + } + +-static void x86_cpu_report_filtered_features(X86CPU *cpu) +-{ +- FeatureWord w; +- +- for (w = 0; w < FEATURE_WORDS; w++) { +- report_unavailable_features(w, cpu->filtered_features[w]); +- } +-} +- + static void x86_cpu_apply_props(X86CPU *cpu, PropValue *props) + { + PropValue *pv; +@@ -5042,24 +5057,24 @@ out: + * + * Returns: 0 if all flags are supported by the host, non-zero otherwise. + */ +-static int x86_cpu_filter_features(X86CPU *cpu) ++static void x86_cpu_filter_features(X86CPU *cpu, bool verbose) + { + CPUX86State *env = &cpu->env; + FeatureWord w; +- int rv = 0; ++ const char *prefix = NULL; ++ ++ if (verbose) { ++ prefix = accel_uses_host_cpuid() ++ ? "host doesn't support requested feature" ++ : "TCG doesn't support requested feature"; ++ } + + for (w = 0; w < FEATURE_WORDS; w++) { + uint32_t host_feat = + x86_cpu_get_supported_feature_word(w, false); + uint32_t requested_features = env->features[w]; +- uint32_t available_features = requested_features & host_feat; +- if (!cpu->force_features) { +- env->features[w] = available_features; +- } +- cpu->filtered_features[w] = requested_features & ~available_features; +- if (cpu->filtered_features[w]) { +- rv = 1; +- } ++ uint32_t unavailable_features = requested_features & ~host_feat; ++ mark_unavailable_features(cpu, w, unavailable_features, prefix); + } + + if ((env->features[FEAT_7_0_EBX] & CPUID_7_0_EBX_INTEL_PT) && +@@ -5085,13 +5100,9 @@ static int x86_cpu_filter_features(X86CPU *cpu) + * host can't emulate the capabilities we report on + * cpu_x86_cpuid(), intel-pt can't be enabled on the current host. + */ +- env->features[FEAT_7_0_EBX] &= ~CPUID_7_0_EBX_INTEL_PT; +- cpu->filtered_features[FEAT_7_0_EBX] |= CPUID_7_0_EBX_INTEL_PT; +- rv = 1; ++ mark_unavailable_features(cpu, FEAT_7_0_EBX, CPUID_7_0_EBX_INTEL_PT, prefix); + } + } +- +- return rv; + } + + static void x86_cpu_realizefn(DeviceState *dev, Error **errp) +@@ -5120,16 +5131,14 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp) + goto out; + } + +- if (x86_cpu_filter_features(cpu) && +- (cpu->check_cpuid || cpu->enforce_cpuid)) { +- x86_cpu_report_filtered_features(cpu); +- if (cpu->enforce_cpuid) { +- error_setg(&local_err, +- accel_uses_host_cpuid() ? +- "Host doesn't support requested features" : +- "TCG doesn't support requested features"); +- goto out; +- } ++ x86_cpu_filter_features(cpu, cpu->check_cpuid || cpu->enforce_cpuid); ++ ++ if (cpu->enforce_cpuid && x86_cpu_have_filtered_features(cpu)) { ++ error_setg(&local_err, ++ accel_uses_host_cpuid() ? ++ "Host doesn't support requested features" : ++ "TCG doesn't support requested features"); ++ goto out; + } + + /* On AMD CPUs, some CPUID[8000_0001].EDX bits must match the bits on +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-introduce-generic-feature-dependency-mec.patch b/SOURCES/kvm-target-i386-introduce-generic-feature-dependency-mec.patch new file mode 100644 index 0000000..e3bf334 --- /dev/null +++ b/SOURCES/kvm-target-i386-introduce-generic-feature-dependency-mec.patch @@ -0,0 +1,158 @@ +From 98145bfcdcee809e370d65eb3a97a9529670ec06 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Fri, 22 Nov 2019 11:53:40 +0000 +Subject: [PATCH 07/16] target/i386: introduce generic feature dependency + mechanism + +RH-Author: Paolo Bonzini +Message-id: <20191122115348.25000-8-pbonzini@redhat.com> +Patchwork-id: 92610 +O-Subject: [RHEL8.2/rhel qemu-kvm PATCH 07/15] target/i386: introduce generic feature dependency mechanism +Bugzilla: 1689270 +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Eduardo Habkost +RH-Acked-by: Maxim Levitsky + +Sometimes a CPU feature does not make sense unless another is +present. In the case of VMX features, KVM does not even allow +setting the VMX controls to some invalid combinations. + +Therefore, this patch adds a generic mechanism that looks for bits +that the user explicitly cleared, and uses them to remove other bits +from the expanded CPU definition. If these dependent bits were also +explicitly *set* by the user, this will be a warning for "-cpu check" +and an error for "-cpu enforce". If not, then the dependent bits are +cleared silently, for convenience. + +With VMX features, this will be used so that for example +"-cpu host,-rdrand" will also hide support for RDRAND exiting. + +Signed-off-by: Paolo Bonzini +(cherry picked from commit 99e24dbdaa682c7b9d0bb5b463638c585bcee1c3) +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.c | 72 ++++++++++++++++++++++++++++++++++++------------------- + 1 file changed, 48 insertions(+), 24 deletions(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index b06ce9d..a7360b3 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -797,10 +797,6 @@ typedef struct FeatureWordInfo { + /* If type==MSR_FEATURE_WORD */ + struct { + uint32_t index; +- struct { /*CPUID that enumerate this MSR*/ +- FeatureWord cpuid_class; +- uint32_t cpuid_flag; +- } cpuid_dep; + } msr; + }; + uint32_t tcg_features; /* Feature flags supported by TCG */ +@@ -1157,10 +1153,6 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { + }, + .msr = { + .index = MSR_IA32_ARCH_CAPABILITIES, +- .cpuid_dep = { +- FEAT_7_0_EDX, +- CPUID_7_0_EDX_ARCH_CAPABILITIES +- } + }, + }, + [FEAT_CORE_CAPABILITY] = { +@@ -1177,14 +1169,30 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { + }, + .msr = { + .index = MSR_IA32_CORE_CAPABILITY, +- .cpuid_dep = { +- FEAT_7_0_EDX, +- CPUID_7_0_EDX_CORE_CAPABILITY, +- }, + }, + }, + }; + ++typedef struct FeatureMask { ++ FeatureWord index; ++ uint32_t mask; ++} FeatureMask; ++ ++typedef struct FeatureDep { ++ FeatureMask from, to; ++} FeatureDep; ++ ++static FeatureDep feature_dependencies[] = { ++ { ++ .from = { FEAT_7_0_EDX, CPUID_7_0_EDX_ARCH_CAPABILITIES }, ++ .to = { FEAT_ARCH_CAPABILITIES, ~0u }, ++ }, ++ { ++ .from = { FEAT_7_0_EDX, CPUID_7_0_EDX_CORE_CAPABILITY }, ++ .to = { FEAT_CORE_CAPABILITY, ~0u }, ++ }, ++}; ++ + typedef struct X86RegisterInfo32 { + /* Name of register */ + const char *name; +@@ -4967,9 +4975,26 @@ static void x86_cpu_expand_features(X86CPU *cpu, Error **errp) + { + CPUX86State *env = &cpu->env; + FeatureWord w; ++ int i; + GList *l; + Error *local_err = NULL; + ++ for (l = plus_features; l; l = l->next) { ++ const char *prop = l->data; ++ object_property_set_bool(OBJECT(cpu), true, prop, &local_err); ++ if (local_err) { ++ goto out; ++ } ++ } ++ ++ for (l = minus_features; l; l = l->next) { ++ const char *prop = l->data; ++ object_property_set_bool(OBJECT(cpu), false, prop, &local_err); ++ if (local_err) { ++ goto out; ++ } ++ } ++ + /*TODO: Now cpu->max_features doesn't overwrite features + * set using QOM properties, and we can convert + * plus_features & minus_features to global properties +@@ -4987,19 +5012,18 @@ static void x86_cpu_expand_features(X86CPU *cpu, Error **errp) + } + } + +- for (l = plus_features; l; l = l->next) { +- const char *prop = l->data; +- object_property_set_bool(OBJECT(cpu), true, prop, &local_err); +- if (local_err) { +- goto out; +- } +- } ++ for (i = 0; i < ARRAY_SIZE(feature_dependencies); i++) { ++ FeatureDep *d = &feature_dependencies[i]; ++ if (!(env->features[d->from.index] & d->from.mask)) { ++ uint32_t unavailable_features = env->features[d->to.index] & d->to.mask; + +- for (l = minus_features; l; l = l->next) { +- const char *prop = l->data; +- object_property_set_bool(OBJECT(cpu), false, prop, &local_err); +- if (local_err) { +- goto out; ++ /* Not an error unless the dependent feature was added explicitly. */ ++ mark_unavailable_features(cpu, d->to.index, ++ unavailable_features & env->user_features[d->to.index], ++ "This feature depends on other features that were not requested"); ++ ++ env->user_features[d->to.index] |= unavailable_features; ++ env->features[d->to.index] &= ~unavailable_features; + } + } + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-kvm-Add-nested-migration-blocker-only-wh.patch b/SOURCES/kvm-target-i386-kvm-Add-nested-migration-blocker-only-wh.patch new file mode 100644 index 0000000..b50ba57 --- /dev/null +++ b/SOURCES/kvm-target-i386-kvm-Add-nested-migration-blocker-only-wh.patch @@ -0,0 +1,60 @@ +From a99cae3466f0fae8a46c58f4e07ed6b6a481a0a5 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Mon, 22 Jul 2019 18:22:17 +0100 +Subject: [PATCH 36/39] target/i386: kvm: Add nested migration blocker only + when kernel lacks required capabilities + +RH-Author: Paolo Bonzini +Message-id: <20190722182220.19374-16-pbonzini@redhat.com> +Patchwork-id: 89632 +O-Subject: [RHEL-8.1.0 PATCH qemu-kvm v3 15/18] target/i386: kvm: Add nested migration blocker only when kernel lacks required capabilities +Bugzilla: 1689269 +RH-Acked-by: Peter Xu +RH-Acked-by: Laurent Vivier +RH-Acked-by: Dr. David Alan Gilbert + +From: Liran Alon + +Previous commits have added support for migration of nested virtualization +workloads. This was done by utilising two new KVM capabilities: +KVM_CAP_NESTED_STATE and KVM_CAP_EXCEPTION_PAYLOAD. Both which are +required in order to correctly migrate such workloads. + +Therefore, change code to add a migration blocker for vCPUs exposed with +Intel VMX or AMD SVM in case one of these kernel capabilities is +missing. + +Signed-off-by: Liran Alon +Reviewed-by: Maran Wilson +Message-Id: <20190619162140.133674-11-liran.alon@oracle.com> +Signed-off-by: Paolo Bonzini +(cherry picked from commit 12604092e26cdace44c901bc429e7e4c7c3e0cab) +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/kvm.c | 9 +++++++-- + 1 file changed, 7 insertions(+), 2 deletions(-) + +diff --git a/target/i386/kvm.c b/target/i386/kvm.c +index aa2d589..0619aba 100644 +--- a/target/i386/kvm.c ++++ b/target/i386/kvm.c +@@ -1159,9 +1159,14 @@ int kvm_arch_init_vcpu(CPUState *cs) + !!(c->ecx & CPUID_EXT_SMX); + } + +- if (cpu_has_vmx(env) && !nested_virt_mig_blocker) { ++ if (cpu_has_vmx(env) && !nested_virt_mig_blocker && ++ ((kvm_max_nested_state_length() <= 0) || !has_exception_payload)) { + error_setg(&nested_virt_mig_blocker, +- "Nested virtualization does not support live migration yet"); ++ "Kernel do not provide required capabilities for " ++ "nested virtualization migration. " ++ "(CAP_NESTED_STATE=%d, CAP_EXCEPTION_PAYLOAD=%d)", ++ kvm_max_nested_state_length() > 0, ++ has_exception_payload); + r = migrate_add_blocker(nested_virt_mig_blocker, &local_err); + if (local_err) { + error_report_err(local_err); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-kvm-Add-support-for-KVM_CAP_EXCEPTION_PA.patch b/SOURCES/kvm-target-i386-kvm-Add-support-for-KVM_CAP_EXCEPTION_PA.patch new file mode 100644 index 0000000..53e4621 --- /dev/null +++ b/SOURCES/kvm-target-i386-kvm-Add-support-for-KVM_CAP_EXCEPTION_PA.patch @@ -0,0 +1,451 @@ +From 05a54f3fc44598f917d72a1f2570c43ec042cdb8 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Mon, 22 Jul 2019 18:22:16 +0100 +Subject: [PATCH 35/39] target/i386: kvm: Add support for + KVM_CAP_EXCEPTION_PAYLOAD + +RH-Author: Paolo Bonzini +Message-id: <20190722182220.19374-15-pbonzini@redhat.com> +Patchwork-id: 89631 +O-Subject: [RHEL-8.1.0 PATCH qemu-kvm v3 14/18] target/i386: kvm: Add support for KVM_CAP_EXCEPTION_PAYLOAD +Bugzilla: 1689269 +RH-Acked-by: Peter Xu +RH-Acked-by: Laurent Vivier +RH-Acked-by: Dr. David Alan Gilbert + +From: Liran Alon + +Kernel commit c4f55198c7c2 ("kvm: x86: Introduce KVM_CAP_EXCEPTION_PAYLOAD") +introduced a new KVM capability which allows userspace to correctly +distinguish between pending and injected exceptions. + +This distinguish is important in case of nested virtualization scenarios +because a L2 pending exception can still be intercepted by the L1 hypervisor +while a L2 injected exception cannot. + +Furthermore, when an exception is attempted to be injected by QEMU, +QEMU should specify the exception payload (CR2 in case of #PF or +DR6 in case of #DB) instead of having the payload already delivered in +the respective vCPU register. Because in case exception is injected to +L2 guest and is intercepted by L1 hypervisor, then payload needs to be +reported to L1 intercept (VMExit handler) while still preserving +respective vCPU register unchanged. + +This commit adds support for QEMU to properly utilise this new KVM +capability (KVM_CAP_EXCEPTION_PAYLOAD). + +Reviewed-by: Nikita Leshenko +Signed-off-by: Liran Alon +Message-Id: <20190619162140.133674-10-liran.alon@oracle.com> +Signed-off-by: Paolo Bonzini +(cherry picked from commit fd13f23b8c95311eff74426921557eee592b0ed3) +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.c | 6 ++- + target/i386/cpu.h | 6 ++- + target/i386/hvf/hvf.c | 10 +++-- + target/i386/hvf/x86hvf.c | 4 +- + target/i386/kvm.c | 101 +++++++++++++++++++++++++++++++++++++++-------- + target/i386/machine.c | 84 ++++++++++++++++++++++++++++++++++++++- + 6 files changed, 187 insertions(+), 24 deletions(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index bd0b784..f71b044 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -4645,7 +4645,11 @@ static void x86_cpu_reset(CPUState *s) + memset(env->mtrr_fixed, 0, sizeof(env->mtrr_fixed)); + + env->interrupt_injected = -1; +- env->exception_injected = -1; ++ env->exception_nr = -1; ++ env->exception_pending = 0; ++ env->exception_injected = 0; ++ env->exception_has_payload = false; ++ env->exception_payload = 0; + env->nmi_injected = false; + #if !defined(CONFIG_USER_ONLY) + /* We hard-wire the BSP to the first CPU. */ +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index 86f3d98..d120f62 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -1325,10 +1325,14 @@ typedef struct CPUX86State { + + /* For KVM */ + uint32_t mp_state; +- int32_t exception_injected; ++ int32_t exception_nr; + int32_t interrupt_injected; + uint8_t soft_interrupt; ++ uint8_t exception_pending; ++ uint8_t exception_injected; + uint8_t has_error_code; ++ uint8_t exception_has_payload; ++ uint64_t exception_payload; + uint32_t ins_len; + uint32_t sipi_vector; + bool tsc_valid; +diff --git a/target/i386/hvf/hvf.c b/target/i386/hvf/hvf.c +index c367539..acc0bb9 100644 +--- a/target/i386/hvf/hvf.c ++++ b/target/i386/hvf/hvf.c +@@ -617,7 +617,9 @@ static void hvf_store_events(CPUState *cpu, uint32_t ins_len, uint64_t idtvec_in + X86CPU *x86_cpu = X86_CPU(cpu); + CPUX86State *env = &x86_cpu->env; + +- env->exception_injected = -1; ++ env->exception_nr = -1; ++ env->exception_pending = 0; ++ env->exception_injected = 0; + env->interrupt_injected = -1; + env->nmi_injected = false; + if (idtvec_info & VMCS_IDT_VEC_VALID) { +@@ -631,7 +633,8 @@ static void hvf_store_events(CPUState *cpu, uint32_t ins_len, uint64_t idtvec_in + break; + case VMCS_IDT_VEC_HWEXCEPTION: + case VMCS_IDT_VEC_SWEXCEPTION: +- env->exception_injected = idtvec_info & VMCS_IDT_VEC_VECNUM; ++ env->exception_nr = idtvec_info & VMCS_IDT_VEC_VECNUM; ++ env->exception_injected = 1; + break; + case VMCS_IDT_VEC_PRIV_SWEXCEPTION: + default: +@@ -925,7 +928,8 @@ int hvf_vcpu_exec(CPUState *cpu) + macvm_set_rip(cpu, rip + ins_len); + break; + case VMX_REASON_VMCALL: +- env->exception_injected = EXCP0D_GPF; ++ env->exception_nr = EXCP0D_GPF; ++ env->exception_injected = 1; + env->has_error_code = true; + env->error_code = 0; + break; +diff --git a/target/i386/hvf/x86hvf.c b/target/i386/hvf/x86hvf.c +index 6c88939..f0e58a8 100644 +--- a/target/i386/hvf/x86hvf.c ++++ b/target/i386/hvf/x86hvf.c +@@ -362,8 +362,8 @@ bool hvf_inject_interrupts(CPUState *cpu_state) + if (env->interrupt_injected != -1) { + vector = env->interrupt_injected; + intr_type = VMCS_INTR_T_SWINTR; +- } else if (env->exception_injected != -1) { +- vector = env->exception_injected; ++ } else if (env->exception_nr != -1) { ++ vector = env->exception_nr; + if (vector == EXCP03_INT3 || vector == EXCP04_INTO) { + intr_type = VMCS_INTR_T_SWEXCEPTION; + } else { +diff --git a/target/i386/kvm.c b/target/i386/kvm.c +index ddceb7d..aa2d589 100644 +--- a/target/i386/kvm.c ++++ b/target/i386/kvm.c +@@ -103,6 +103,7 @@ static uint32_t num_architectural_pmu_fixed_counters; + static int has_xsave; + static int has_xcrs; + static int has_pit_state2; ++static int has_exception_payload; + + static bool has_msr_mcg_ext_ctl; + +@@ -569,15 +570,56 @@ void kvm_arch_on_sigbus_vcpu(CPUState *c, int code, void *addr) + /* Hope we are lucky for AO MCE */ + } + ++static void kvm_reset_exception(CPUX86State *env) ++{ ++ env->exception_nr = -1; ++ env->exception_pending = 0; ++ env->exception_injected = 0; ++ env->exception_has_payload = false; ++ env->exception_payload = 0; ++} ++ ++static void kvm_queue_exception(CPUX86State *env, ++ int32_t exception_nr, ++ uint8_t exception_has_payload, ++ uint64_t exception_payload) ++{ ++ assert(env->exception_nr == -1); ++ assert(!env->exception_pending); ++ assert(!env->exception_injected); ++ assert(!env->exception_has_payload); ++ ++ env->exception_nr = exception_nr; ++ ++ if (has_exception_payload) { ++ env->exception_pending = 1; ++ ++ env->exception_has_payload = exception_has_payload; ++ env->exception_payload = exception_payload; ++ } else { ++ env->exception_injected = 1; ++ ++ if (exception_nr == EXCP01_DB) { ++ assert(exception_has_payload); ++ env->dr[6] = exception_payload; ++ } else if (exception_nr == EXCP0E_PAGE) { ++ assert(exception_has_payload); ++ env->cr[2] = exception_payload; ++ } else { ++ assert(!exception_has_payload); ++ } ++ } ++} ++ + static int kvm_inject_mce_oldstyle(X86CPU *cpu) + { + CPUX86State *env = &cpu->env; + +- if (!kvm_has_vcpu_events() && env->exception_injected == EXCP12_MCHK) { ++ if (!kvm_has_vcpu_events() && env->exception_nr == EXCP12_MCHK) { + unsigned int bank, bank_num = env->mcg_cap & 0xff; + struct kvm_x86_mce mce; + +- env->exception_injected = -1; ++ kvm_reset_exception(env); + + /* + * There must be at least one bank in use if an MCE is pending. +@@ -1458,6 +1500,16 @@ int kvm_arch_init(MachineState *ms, KVMState *s) + has_pit_state2 = kvm_check_extension(s, KVM_CAP_PIT_STATE2); + #endif + ++ has_exception_payload = kvm_check_extension(s, KVM_CAP_EXCEPTION_PAYLOAD); ++ if (has_exception_payload) { ++ ret = kvm_vm_enable_cap(s, KVM_CAP_EXCEPTION_PAYLOAD, 0, true); ++ if (ret < 0) { ++ error_report("kvm: Failed to enable exception payload cap: %s", ++ strerror(-ret)); ++ return ret; ++ } ++ } ++ + ret = kvm_get_supported_msrs(s); + if (ret < 0) { + return ret; +@@ -2717,8 +2769,16 @@ static int kvm_put_vcpu_events(X86CPU *cpu, int level) + return 0; + } + +- events.exception.injected = (env->exception_injected >= 0); +- events.exception.nr = env->exception_injected; ++ events.flags = 0; ++ ++ if (has_exception_payload) { ++ events.flags |= KVM_VCPUEVENT_VALID_PAYLOAD; ++ events.exception.pending = env->exception_pending; ++ events.exception_has_payload = env->exception_has_payload; ++ events.exception_payload = env->exception_payload; ++ } ++ events.exception.nr = env->exception_nr; ++ events.exception.injected = env->exception_injected; + events.exception.has_error_code = env->has_error_code; + events.exception.error_code = env->error_code; + +@@ -2731,7 +2791,6 @@ static int kvm_put_vcpu_events(X86CPU *cpu, int level) + events.nmi.masked = !!(env->hflags2 & HF2_NMI_MASK); + + events.sipi_vector = env->sipi_vector; +- events.flags = 0; + + if (has_msr_smbase) { + events.smi.smm = !!(env->hflags & HF_SMM_MASK); +@@ -2781,8 +2840,19 @@ static int kvm_get_vcpu_events(X86CPU *cpu) + if (ret < 0) { + return ret; + } +- env->exception_injected = +- events.exception.injected ? events.exception.nr : -1; ++ ++ if (events.flags & KVM_VCPUEVENT_VALID_PAYLOAD) { ++ env->exception_pending = events.exception.pending; ++ env->exception_has_payload = events.exception_has_payload; ++ env->exception_payload = events.exception_payload; ++ } else { ++ env->exception_pending = 0; ++ env->exception_has_payload = false; ++ } ++ env->exception_injected = events.exception.injected; ++ env->exception_nr = ++ (env->exception_pending || env->exception_injected) ? ++ events.exception.nr : -1; + env->has_error_code = events.exception.has_error_code; + env->error_code = events.exception.error_code; + +@@ -2834,12 +2904,12 @@ static int kvm_guest_debug_workarounds(X86CPU *cpu) + unsigned long reinject_trap = 0; + + if (!kvm_has_vcpu_events()) { +- if (env->exception_injected == EXCP01_DB) { ++ if (env->exception_nr == EXCP01_DB) { + reinject_trap = KVM_GUESTDBG_INJECT_DB; + } else if (env->exception_injected == EXCP03_INT3) { + reinject_trap = KVM_GUESTDBG_INJECT_BP; + } +- env->exception_injected = -1; ++ kvm_reset_exception(env); + } + + /* +@@ -3215,13 +3285,13 @@ int kvm_arch_process_async_events(CPUState *cs) + + kvm_cpu_synchronize_state(cs); + +- if (env->exception_injected == EXCP08_DBLE) { ++ if (env->exception_nr == EXCP08_DBLE) { + /* this means triple fault */ + qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); + cs->exit_request = 1; + return 0; + } +- env->exception_injected = EXCP12_MCHK; ++ kvm_queue_exception(env, EXCP12_MCHK, 0, 0); + env->has_error_code = 0; + + cs->halted = 0; +@@ -3436,14 +3506,13 @@ static int kvm_handle_debug(X86CPU *cpu, + } + if (ret == 0) { + cpu_synchronize_state(cs); +- assert(env->exception_injected == -1); ++ assert(env->exception_nr == -1); + + /* pass to guest */ +- env->exception_injected = arch_info->exception; ++ kvm_queue_exception(env, arch_info->exception, ++ arch_info->exception == EXCP01_DB, ++ arch_info->dr6); + env->has_error_code = 0; +- if (arch_info->exception == EXCP01_DB) { +- env->dr[6] = arch_info->dr6; +- } + } + + return ret; +diff --git a/target/i386/machine.c b/target/i386/machine.c +index a2ddbba..5ffee8f 100644 +--- a/target/i386/machine.c ++++ b/target/i386/machine.c +@@ -239,6 +239,41 @@ static int cpu_pre_save(void *opaque) + } + #endif + ++ /* ++ * When vCPU is running L2 and exception is still pending, ++ * it can potentially be intercepted by L1 hypervisor. ++ * In contrast to an injected exception which cannot be ++ * intercepted anymore. ++ * ++ * Furthermore, when a L2 exception is intercepted by L1 ++ * hypervisor, it's exception payload (CR2/DR6 on #PF/#DB) ++ * should not be set yet in the respective vCPU register. ++ * Thus, in case an exception is pending, it is ++ * important to save the exception payload seperately. ++ * ++ * Therefore, if an exception is not in a pending state ++ * or vCPU is not in guest-mode, it is not important to ++ * distinguish between a pending and injected exception ++ * and we don't need to store seperately the exception payload. ++ * ++ * In order to preserve better backwards-compatabile migration, ++ * convert a pending exception to an injected exception in ++ * case it is not important to distingiush between them ++ * as described above. ++ */ ++ if (env->exception_pending && !(env->hflags & HF_GUEST_MASK)) { ++ env->exception_pending = 0; ++ env->exception_injected = 1; ++ ++ if (env->exception_has_payload) { ++ if (env->exception_nr == EXCP01_DB) { ++ env->dr[6] = env->exception_payload; ++ } else if (env->exception_nr == EXCP0E_PAGE) { ++ env->cr[2] = env->exception_payload; ++ } ++ } ++ } ++ + return 0; + } + +@@ -296,6 +331,23 @@ static int cpu_post_load(void *opaque, int version_id) + } + #endif + ++ /* ++ * There are cases that we can get valid exception_nr with both ++ * exception_pending and exception_injected being cleared. ++ * This can happen in one of the following scenarios: ++ * 1) Source is older QEMU without KVM_CAP_EXCEPTION_PAYLOAD support. ++ * 2) Source is running on kernel without KVM_CAP_EXCEPTION_PAYLOAD support. ++ * 3) "cpu/exception_info" subsection not sent because there is no exception ++ * pending or guest wasn't running L2 (See comment in cpu_pre_save()). ++ * ++ * In those cases, we can just deduce that a valid exception_nr means ++ * we can treat the exception as already injected. ++ */ ++ if ((env->exception_nr != -1) && ++ !env->exception_pending && !env->exception_injected) { ++ env->exception_injected = 1; ++ } ++ + env->fpstt = (env->fpus_vmstate >> 11) & 7; + env->fpus = env->fpus_vmstate & ~0x3800; + env->fptag_vmstate ^= 0xff; +@@ -341,6 +393,35 @@ static bool steal_time_msr_needed(void *opaque) + return cpu->env.steal_time_msr != 0; + } + ++static bool exception_info_needed(void *opaque) ++{ ++ X86CPU *cpu = opaque; ++ CPUX86State *env = &cpu->env; ++ ++ /* ++ * It is important to save exception-info only in case ++ * we need to distingiush between a pending and injected ++ * exception. Which is only required in case there is a ++ * pending exception and vCPU is running L2. ++ * For more info, refer to comment in cpu_pre_save(). ++ */ ++ return env->exception_pending && (env->hflags & HF_GUEST_MASK); ++} ++ ++static const VMStateDescription vmstate_exception_info = { ++ .name = "cpu/exception_info", ++ .version_id = 1, ++ .minimum_version_id = 1, ++ .needed = exception_info_needed, ++ .fields = (VMStateField[]) { ++ VMSTATE_UINT8(env.exception_pending, X86CPU), ++ VMSTATE_UINT8(env.exception_injected, X86CPU), ++ VMSTATE_UINT8(env.exception_has_payload, X86CPU), ++ VMSTATE_UINT64(env.exception_payload, X86CPU), ++ VMSTATE_END_OF_LIST() ++ } ++}; ++ + static const VMStateDescription vmstate_steal_time_msr = { + .name = "cpu/steal_time_msr", + .version_id = 1, +@@ -1219,7 +1300,7 @@ VMStateDescription vmstate_x86_cpu = { + VMSTATE_INT32(env.interrupt_injected, X86CPU), + VMSTATE_UINT32(env.mp_state, X86CPU), + VMSTATE_UINT64(env.tsc, X86CPU), +- VMSTATE_INT32(env.exception_injected, X86CPU), ++ VMSTATE_INT32(env.exception_nr, X86CPU), + VMSTATE_UINT8(env.soft_interrupt, X86CPU), + VMSTATE_UINT8(env.nmi_injected, X86CPU), + VMSTATE_UINT8(env.nmi_pending, X86CPU), +@@ -1243,6 +1324,7 @@ VMStateDescription vmstate_x86_cpu = { + /* The above list is not sorted /wrt version numbers, watch out! */ + }, + .subsections = (const VMStateDescription*[]) { ++ &vmstate_exception_info, + &vmstate_async_pf_msr, + &vmstate_pv_eoi_msr, + &vmstate_steal_time_msr, +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-kvm-Add-support-for-save-and-restore-nes.patch b/SOURCES/kvm-target-i386-kvm-Add-support-for-save-and-restore-nes.patch new file mode 100644 index 0000000..176b679 --- /dev/null +++ b/SOURCES/kvm-target-i386-kvm-Add-support-for-save-and-restore-nes.patch @@ -0,0 +1,464 @@ +From 0a1fd178d9b7c054d229b60540b7d12d87eb8070 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Mon, 22 Jul 2019 18:22:15 +0100 +Subject: [PATCH 34/39] target/i386: kvm: Add support for save and restore + nested state + +RH-Author: Paolo Bonzini +Message-id: <20190722182220.19374-14-pbonzini@redhat.com> +Patchwork-id: 89629 +O-Subject: [RHEL-8.1.0 PATCH qemu-kvm v3 13/18] target/i386: kvm: Add support for save and restore nested state +Bugzilla: 1689269 +RH-Acked-by: Peter Xu +RH-Acked-by: Laurent Vivier +RH-Acked-by: Dr. David Alan Gilbert + +From: Liran Alon + +Kernel commit 8fcc4b5923af ("kvm: nVMX: Introduce KVM_CAP_NESTED_STATE") +introduced new IOCTLs to extract and restore vCPU state related to +Intel VMX & AMD SVM. + +Utilize these IOCTLs to add support for migration of VMs which are +running nested hypervisors. + +Reviewed-by: Nikita Leshenko +Reviewed-by: Maran Wilson +Tested-by: Maran Wilson +Signed-off-by: Liran Alon +Message-Id: <20190619162140.133674-9-liran.alon@oracle.com> +Signed-off-by: Paolo Bonzini +(cherry picked from commit ebbfef2f34cfc749c045a4569dedb4f748ec024a) +Signed-off-by: Danilo C. L. de Paula +--- + accel/kvm/kvm-all.c | 8 ++ + include/sysemu/kvm.h | 1 + + target/i386/cpu.h | 3 + + target/i386/kvm.c | 80 ++++++++++++++++++++ + target/i386/machine.c | 198 ++++++++++++++++++++++++++++++++++++++++++++++++++ + 5 files changed, 290 insertions(+) + +diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c +index a939b26..2130fcb 100644 +--- a/accel/kvm/kvm-all.c ++++ b/accel/kvm/kvm-all.c +@@ -87,6 +87,7 @@ struct KVMState + #ifdef KVM_CAP_SET_GUEST_DEBUG + struct kvm_sw_breakpoint_head kvm_sw_breakpoints; + #endif ++ int max_nested_state_len; + int many_ioeventfds; + int intx_set_mask; + bool sync_mmu; +@@ -1646,6 +1647,8 @@ static int kvm_init(MachineState *ms) + s->debugregs = kvm_check_extension(s, KVM_CAP_DEBUGREGS); + #endif + ++ s->max_nested_state_len = kvm_check_extension(s, KVM_CAP_NESTED_STATE); ++ + #ifdef KVM_CAP_IRQ_ROUTING + kvm_direct_msi_allowed = (kvm_check_extension(s, KVM_CAP_SIGNAL_MSI) > 0); + #endif +@@ -2207,6 +2210,11 @@ int kvm_has_debugregs(void) + return kvm_state->debugregs; + } + ++int kvm_max_nested_state_length(void) ++{ ++ return kvm_state->max_nested_state_len; ++} ++ + int kvm_has_many_ioeventfds(void) + { + if (!kvm_enabled()) { +diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h +index a5a6dff..3cf04cf 100644 +--- a/include/sysemu/kvm.h ++++ b/include/sysemu/kvm.h +@@ -211,6 +211,7 @@ bool kvm_has_sync_mmu(void); + int kvm_has_vcpu_events(void); + int kvm_has_robust_singlestep(void); + int kvm_has_debugregs(void); ++int kvm_max_nested_state_length(void); + int kvm_has_pit_state2(void); + int kvm_has_many_ioeventfds(void); + int kvm_has_gsi_routing(void); +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index f595fc3..86f3d98 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -1335,6 +1335,9 @@ typedef struct CPUX86State { + int64_t tsc_khz; + int64_t user_tsc_khz; /* for sanity check only */ + void *kvm_xsave_buf; ++#if defined(CONFIG_KVM) ++ struct kvm_nested_state *nested_state; ++#endif + #if defined(CONFIG_HVF) + HVFX86EmulatorState *hvf_emul; + #endif +diff --git a/target/i386/kvm.c b/target/i386/kvm.c +index 8a6da90..ddceb7d 100644 +--- a/target/i386/kvm.c ++++ b/target/i386/kvm.c +@@ -789,6 +789,7 @@ int kvm_arch_init_vcpu(CPUState *cs) + struct kvm_cpuid_entry2 *c; + uint32_t signature[3]; + int kvm_base = KVM_CPUID_SIGNATURE; ++ int max_nested_state_len; + int r; + Error *local_err = NULL; + +@@ -1180,6 +1181,24 @@ int kvm_arch_init_vcpu(CPUState *cs) + if (has_xsave) { + env->kvm_xsave_buf = qemu_memalign(4096, sizeof(struct kvm_xsave)); + } ++ ++ max_nested_state_len = kvm_max_nested_state_length(); ++ if (max_nested_state_len > 0) { ++ assert(max_nested_state_len >= offsetof(struct kvm_nested_state, data)); ++ env->nested_state = g_malloc0(max_nested_state_len); ++ ++ env->nested_state->size = max_nested_state_len; ++ ++ if (IS_INTEL_CPU(env)) { ++ struct kvm_vmx_nested_state_hdr *vmx_hdr = ++ &env->nested_state->hdr.vmx; ++ ++ env->nested_state->format = KVM_STATE_NESTED_FORMAT_VMX; ++ vmx_hdr->vmxon_pa = -1ull; ++ vmx_hdr->vmcs12_pa = -1ull; ++ } ++ } ++ + cpu->kvm_msr_buf = g_malloc0(MSR_BUF_SIZE); + + if (!(env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_RDTSCP)) { +@@ -1199,12 +1218,18 @@ int kvm_arch_init_vcpu(CPUState *cs) + int kvm_arch_destroy_vcpu(CPUState *cs) + { + X86CPU *cpu = X86_CPU(cs); ++ CPUX86State *env = &cpu->env; + + if (cpu->kvm_msr_buf) { + g_free(cpu->kvm_msr_buf); + cpu->kvm_msr_buf = NULL; + } + ++ if (env->nested_state) { ++ g_free(env->nested_state); ++ env->nested_state = NULL; ++ } ++ + return 0; + } + +@@ -2875,6 +2900,52 @@ static int kvm_get_debugregs(X86CPU *cpu) + return 0; + } + ++static int kvm_put_nested_state(X86CPU *cpu) ++{ ++ CPUX86State *env = &cpu->env; ++ int max_nested_state_len = kvm_max_nested_state_length(); ++ ++ if (max_nested_state_len <= 0) { ++ return 0; ++ } ++ ++ assert(env->nested_state->size <= max_nested_state_len); ++ return kvm_vcpu_ioctl(CPU(cpu), KVM_SET_NESTED_STATE, env->nested_state); ++} ++ ++static int kvm_get_nested_state(X86CPU *cpu) ++{ ++ CPUX86State *env = &cpu->env; ++ int max_nested_state_len = kvm_max_nested_state_length(); ++ int ret; ++ ++ if (max_nested_state_len <= 0) { ++ return 0; ++ } ++ ++ /* ++ * It is possible that migration restored a smaller size into ++ * nested_state->hdr.size than what our kernel support. ++ * We preserve migration origin nested_state->hdr.size for ++ * call to KVM_SET_NESTED_STATE but wish that our next call ++ * to KVM_GET_NESTED_STATE will use max size our kernel support. ++ */ ++ env->nested_state->size = max_nested_state_len; ++ ++ ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_NESTED_STATE, env->nested_state); ++ if (ret < 0) { ++ return ret; ++ } ++ ++ if (env->nested_state->flags & KVM_STATE_NESTED_GUEST_MODE) { ++ env->hflags |= HF_GUEST_MASK; ++ } else { ++ env->hflags &= ~HF_GUEST_MASK; ++ } ++ ++ return ret; ++} ++ + int kvm_arch_put_registers(CPUState *cpu, int level) + { + X86CPU *x86_cpu = X86_CPU(cpu); +@@ -2882,6 +2953,11 @@ int kvm_arch_put_registers(CPUState *cpu, int level) + + assert(cpu_is_stopped(cpu) || qemu_cpu_is_self(cpu)); + ++ ret = kvm_put_nested_state(x86_cpu); ++ if (ret < 0) { ++ return ret; ++ } ++ + if (level >= KVM_PUT_RESET_STATE) { + ret = kvm_put_msr_feature_control(x86_cpu); + if (ret < 0) { +@@ -2997,6 +3073,10 @@ int kvm_arch_get_registers(CPUState *cs) + if (ret < 0) { + goto out; + } ++ ret = kvm_get_nested_state(cpu); ++ if (ret < 0) { ++ goto out; ++ } + ret = 0; + out: + cpu_sync_bndcs_hflags(&cpu->env); +diff --git a/target/i386/machine.c b/target/i386/machine.c +index 561d4a5..a2ddbba 100644 +--- a/target/i386/machine.c ++++ b/target/i386/machine.c +@@ -230,6 +230,15 @@ static int cpu_pre_save(void *opaque) + env->segs[R_SS].flags &= ~(env->segs[R_SS].flags & DESC_DPL_MASK); + } + ++#ifdef CONFIG_KVM ++ /* Verify we have nested virtualization state from kernel if required */ ++ if (kvm_enabled() && cpu_has_vmx(env) && !env->nested_state) { ++ error_report("Guest enabled nested virtualization but kernel " ++ "does not support saving of nested state"); ++ return -EINVAL; ++ } ++#endif ++ + return 0; + } + +@@ -277,6 +286,16 @@ static int cpu_post_load(void *opaque, int version_id) + env->hflags &= ~HF_CPL_MASK; + env->hflags |= (env->segs[R_SS].flags >> DESC_DPL_SHIFT) & HF_CPL_MASK; + ++#ifdef CONFIG_KVM ++ if ((env->hflags & HF_GUEST_MASK) && ++ (!env->nested_state || ++ !(env->nested_state->flags & KVM_STATE_NESTED_GUEST_MODE))) { ++ error_report("vCPU set in guest-mode inconsistent with " ++ "migrated kernel nested state"); ++ return -EINVAL; ++ } ++#endif ++ + env->fpstt = (env->fpus_vmstate >> 11) & 7; + env->fpus = env->fpus_vmstate & ~0x3800; + env->fptag_vmstate ^= 0xff; +@@ -819,6 +838,182 @@ static const VMStateDescription vmstate_tsc_khz = { + } + }; + ++#ifdef CONFIG_KVM ++ ++static bool vmx_vmcs12_needed(void *opaque) ++{ ++ struct kvm_nested_state *nested_state = opaque; ++ return (nested_state->size > ++ offsetof(struct kvm_nested_state, data.vmx[0].vmcs12)); ++} ++ ++static const VMStateDescription vmstate_vmx_vmcs12 = { ++ .name = "cpu/kvm_nested_state/vmx/vmcs12", ++ .version_id = 1, ++ .minimum_version_id = 1, ++ .needed = vmx_vmcs12_needed, ++ .fields = (VMStateField[]) { ++ VMSTATE_UINT8_ARRAY(data.vmx[0].vmcs12, ++ struct kvm_nested_state, ++ KVM_STATE_NESTED_VMX_VMCS_SIZE), ++ VMSTATE_END_OF_LIST() ++ } ++}; ++ ++static bool vmx_shadow_vmcs12_needed(void *opaque) ++{ ++ struct kvm_nested_state *nested_state = opaque; ++ return (nested_state->size > ++ offsetof(struct kvm_nested_state, data.vmx[0].shadow_vmcs12)); ++} ++ ++static const VMStateDescription vmstate_vmx_shadow_vmcs12 = { ++ .name = "cpu/kvm_nested_state/vmx/shadow_vmcs12", ++ .version_id = 1, ++ .minimum_version_id = 1, ++ .needed = vmx_shadow_vmcs12_needed, ++ .fields = (VMStateField[]) { ++ VMSTATE_UINT8_ARRAY(data.vmx[0].shadow_vmcs12, ++ struct kvm_nested_state, ++ KVM_STATE_NESTED_VMX_VMCS_SIZE), ++ VMSTATE_END_OF_LIST() ++ } ++}; ++ ++static bool vmx_nested_state_needed(void *opaque) ++{ ++ struct kvm_nested_state *nested_state = opaque; ++ ++ return ((nested_state->format == KVM_STATE_NESTED_FORMAT_VMX) && ++ ((nested_state->hdr.vmx.vmxon_pa != -1ull) || ++ (nested_state->hdr.vmx.smm.flags & KVM_STATE_NESTED_SMM_VMXON))); ++} ++ ++static const VMStateDescription vmstate_vmx_nested_state = { ++ .name = "cpu/kvm_nested_state/vmx", ++ .version_id = 1, ++ .minimum_version_id = 1, ++ .needed = vmx_nested_state_needed, ++ .fields = (VMStateField[]) { ++ VMSTATE_U64(hdr.vmx.vmxon_pa, struct kvm_nested_state), ++ VMSTATE_U64(hdr.vmx.vmcs12_pa, struct kvm_nested_state), ++ VMSTATE_U16(hdr.vmx.smm.flags, struct kvm_nested_state), ++ VMSTATE_END_OF_LIST() ++ }, ++ .subsections = (const VMStateDescription*[]) { ++ &vmstate_vmx_vmcs12, ++ &vmstate_vmx_shadow_vmcs12, ++ NULL, ++ } ++}; ++ ++static bool svm_nested_state_needed(void *opaque) ++{ ++ struct kvm_nested_state *nested_state = opaque; ++ ++ return (nested_state->format == KVM_STATE_NESTED_FORMAT_SVM); ++} ++ ++static const VMStateDescription vmstate_svm_nested_state = { ++ .name = "cpu/kvm_nested_state/svm", ++ .version_id = 1, ++ .minimum_version_id = 1, ++ .needed = svm_nested_state_needed, ++ .fields = (VMStateField[]) { ++ VMSTATE_END_OF_LIST() ++ } ++}; ++ ++static bool nested_state_needed(void *opaque) ++{ ++ X86CPU *cpu = opaque; ++ CPUX86State *env = &cpu->env; ++ ++ return (env->nested_state && ++ (vmx_nested_state_needed(env->nested_state) || ++ svm_nested_state_needed(env->nested_state))); ++} ++ ++static int nested_state_post_load(void *opaque, int version_id) ++{ ++ X86CPU *cpu = opaque; ++ CPUX86State *env = &cpu->env; ++ struct kvm_nested_state *nested_state = env->nested_state; ++ int min_nested_state_len = offsetof(struct kvm_nested_state, data); ++ int max_nested_state_len = kvm_max_nested_state_length(); ++ ++ /* ++ * If our kernel don't support setting nested state ++ * and we have received nested state from migration stream, ++ * we need to fail migration ++ */ ++ if (max_nested_state_len <= 0) { ++ error_report("Received nested state when kernel cannot restore it"); ++ return -EINVAL; ++ } ++ ++ /* ++ * Verify that the size of received nested_state struct ++ * at least cover required header and is not larger ++ * than the max size that our kernel support ++ */ ++ if (nested_state->size < min_nested_state_len) { ++ error_report("Received nested state size less than min: " ++ "len=%d, min=%d", ++ nested_state->size, min_nested_state_len); ++ return -EINVAL; ++ } ++ if (nested_state->size > max_nested_state_len) { ++ error_report("Recieved unsupported nested state size: " ++ "nested_state->size=%d, max=%d", ++ nested_state->size, max_nested_state_len); ++ return -EINVAL; ++ } ++ ++ /* Verify format is valid */ ++ if ((nested_state->format != KVM_STATE_NESTED_FORMAT_VMX) && ++ (nested_state->format != KVM_STATE_NESTED_FORMAT_SVM)) { ++ error_report("Received invalid nested state format: %d", ++ nested_state->format); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ ++static const VMStateDescription vmstate_kvm_nested_state = { ++ .name = "cpu/kvm_nested_state", ++ .version_id = 1, ++ .minimum_version_id = 1, ++ .fields = (VMStateField[]) { ++ VMSTATE_U16(flags, struct kvm_nested_state), ++ VMSTATE_U16(format, struct kvm_nested_state), ++ VMSTATE_U32(size, struct kvm_nested_state), ++ VMSTATE_END_OF_LIST() ++ }, ++ .subsections = (const VMStateDescription*[]) { ++ &vmstate_vmx_nested_state, ++ &vmstate_svm_nested_state, ++ NULL ++ } ++}; ++ ++static const VMStateDescription vmstate_nested_state = { ++ .name = "cpu/nested_state", ++ .version_id = 1, ++ .minimum_version_id = 1, ++ .needed = nested_state_needed, ++ .post_load = nested_state_post_load, ++ .fields = (VMStateField[]) { ++ VMSTATE_STRUCT_POINTER(env.nested_state, X86CPU, ++ vmstate_kvm_nested_state, ++ struct kvm_nested_state), ++ VMSTATE_END_OF_LIST() ++ } ++}; ++ ++#endif ++ + static bool mcg_ext_ctl_needed(void *opaque) + { + X86CPU *cpu = opaque; +@@ -1080,6 +1275,9 @@ VMStateDescription vmstate_x86_cpu = { + #ifndef TARGET_X86_64 + &vmstate_efer32, + #endif ++#ifdef CONFIG_KVM ++ &vmstate_nested_state, ++#endif + NULL + } + }; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-kvm-Block-migration-for-vCPUs-exposed-wi.patch b/SOURCES/kvm-target-i386-kvm-Block-migration-for-vCPUs-exposed-wi.patch new file mode 100644 index 0000000..c4e9269 --- /dev/null +++ b/SOURCES/kvm-target-i386-kvm-Block-migration-for-vCPUs-exposed-wi.patch @@ -0,0 +1,130 @@ +From 0d5048785d6edd2fee3b22aa6901e55539e07525 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Mon, 22 Jul 2019 18:22:11 +0100 +Subject: [PATCH 30/39] target/i386: kvm: Block migration for vCPUs exposed + with nested virtualization + +RH-Author: Paolo Bonzini +Message-id: <20190722182220.19374-10-pbonzini@redhat.com> +Patchwork-id: 89633 +O-Subject: [RHEL-8.1.0 PATCH qemu-kvm v3 09/18] target/i386: kvm: Block migration for vCPUs exposed with nested virtualization +Bugzilla: 1689269 +RH-Acked-by: Peter Xu +RH-Acked-by: Laurent Vivier +RH-Acked-by: Dr. David Alan Gilbert + +From: Liran Alon + +Commit d98f26073beb ("target/i386: kvm: add VMX migration blocker") +added a migration blocker for vCPU exposed with Intel VMX. +However, migration should also be blocked for vCPU exposed with +AMD SVM. + +Both cases should be blocked because QEMU should extract additional +vCPU state from KVM that should be migrated as part of vCPU VMState. +E.g. Whether vCPU is running in guest-mode or host-mode. + +Fixes: d98f26073beb ("target/i386: kvm: add VMX migration blocker") +Reviewed-by: Maran Wilson +Signed-off-by: Liran Alon +Message-Id: <20190619162140.133674-6-liran.alon@oracle.com> +Signed-off-by: Paolo Bonzini +(cherry picked from commit 18ab37ba1cee290923240744288dbee8be9355fb) +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.c | 6 ------ + target/i386/cpu.h | 12 ++++++++++++ + target/i386/kvm.c | 14 +++++++------- + 3 files changed, 19 insertions(+), 13 deletions(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index af62281..bd0b784 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -5034,12 +5034,6 @@ static int x86_cpu_filter_features(X86CPU *cpu) + return rv; + } + +-#define IS_INTEL_CPU(env) ((env)->cpuid_vendor1 == CPUID_VENDOR_INTEL_1 && \ +- (env)->cpuid_vendor2 == CPUID_VENDOR_INTEL_2 && \ +- (env)->cpuid_vendor3 == CPUID_VENDOR_INTEL_3) +-#define IS_AMD_CPU(env) ((env)->cpuid_vendor1 == CPUID_VENDOR_AMD_1 && \ +- (env)->cpuid_vendor2 == CPUID_VENDOR_AMD_2 && \ +- (env)->cpuid_vendor3 == CPUID_VENDOR_AMD_3) + static void x86_cpu_realizefn(DeviceState *dev, Error **errp) + { + CPUState *cs = CPU(dev); +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index 923dfcd..f595fc3 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -722,6 +722,13 @@ typedef uint32_t FeatureWordArray[FEATURE_WORDS]; + + #define CPUID_VENDOR_VIA "CentaurHauls" + ++#define IS_INTEL_CPU(env) ((env)->cpuid_vendor1 == CPUID_VENDOR_INTEL_1 && \ ++ (env)->cpuid_vendor2 == CPUID_VENDOR_INTEL_2 && \ ++ (env)->cpuid_vendor3 == CPUID_VENDOR_INTEL_3) ++#define IS_AMD_CPU(env) ((env)->cpuid_vendor1 == CPUID_VENDOR_AMD_1 && \ ++ (env)->cpuid_vendor2 == CPUID_VENDOR_AMD_2 && \ ++ (env)->cpuid_vendor3 == CPUID_VENDOR_AMD_3) ++ + #define CPUID_MWAIT_IBE (1U << 1) /* Interrupts can exit capability */ + #define CPUID_MWAIT_EMX (1U << 0) /* enumeration supported */ + +@@ -1829,6 +1836,11 @@ static inline int32_t x86_get_a20_mask(CPUX86State *env) + } + } + ++static inline bool cpu_has_vmx(CPUX86State *env) ++{ ++ return env->features[FEAT_1_ECX] & CPUID_EXT_VMX; ++} ++ + /* fpu_helper.c */ + void update_fp_status(CPUX86State *env); + void update_mxcsr_status(CPUX86State *env); +diff --git a/target/i386/kvm.c b/target/i386/kvm.c +index 1a4ff3c..f741e8b 100644 +--- a/target/i386/kvm.c ++++ b/target/i386/kvm.c +@@ -772,7 +772,7 @@ static int hyperv_handle_properties(CPUState *cs) + } + + static Error *invtsc_mig_blocker; +-static Error *vmx_mig_blocker; ++static Error *nested_virt_mig_blocker; + + #define KVM_MAX_CPUID_ENTRIES 100 + +@@ -1116,13 +1116,13 @@ int kvm_arch_init_vcpu(CPUState *cs) + !!(c->ecx & CPUID_EXT_SMX); + } + +- if ((env->features[FEAT_1_ECX] & CPUID_EXT_VMX) && !vmx_mig_blocker) { +- error_setg(&vmx_mig_blocker, +- "Nested VMX virtualization does not support live migration yet"); +- r = migrate_add_blocker(vmx_mig_blocker, &local_err); ++ if (cpu_has_vmx(env) && !nested_virt_mig_blocker) { ++ error_setg(&nested_virt_mig_blocker, ++ "Nested virtualization does not support live migration yet"); ++ r = migrate_add_blocker(nested_virt_mig_blocker, &local_err); + if (local_err) { + error_report_err(local_err); +- error_free(vmx_mig_blocker); ++ error_free(nested_virt_mig_blocker); + return r; + } + } +@@ -1191,7 +1191,7 @@ int kvm_arch_init_vcpu(CPUState *cs) + fail: + migrate_del_blocker(invtsc_mig_blocker); + fail2: +- migrate_del_blocker(vmx_mig_blocker); ++ migrate_del_blocker(nested_virt_mig_blocker); + + return r; + } +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-kvm-Delete-VMX-migration-blocker-on-vCPU.patch b/SOURCES/kvm-target-i386-kvm-Delete-VMX-migration-blocker-on-vCPU.patch new file mode 100644 index 0000000..215a425 --- /dev/null +++ b/SOURCES/kvm-target-i386-kvm-Delete-VMX-migration-blocker-on-vCPU.patch @@ -0,0 +1,72 @@ +From 9cf495aabeeaf4fdccae83d748a70936e3bf26ab Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Mon, 22 Jul 2019 18:22:07 +0100 +Subject: [PATCH 26/39] target/i386: kvm: Delete VMX migration blocker on vCPU + init failure + +RH-Author: Paolo Bonzini +Message-id: <20190722182220.19374-6-pbonzini@redhat.com> +Patchwork-id: 89624 +O-Subject: [RHEL-8.1.0 PATCH qemu-kvm v3 05/18] target/i386: kvm: Delete VMX migration blocker on vCPU init failure +Bugzilla: 1689269 +RH-Acked-by: Peter Xu +RH-Acked-by: Laurent Vivier +RH-Acked-by: Dr. David Alan Gilbert + +From: Liran Alon + +Commit d98f26073beb ("target/i386: kvm: add VMX migration blocker") +added migration blocker for vCPU exposed with Intel VMX because QEMU +doesn't yet contain code to support migration of nested virtualization +workloads. + +However, that commit missed adding deletion of the migration blocker in +case init of vCPU failed. Similar to invtsc_mig_blocker. This commit fix +that issue. + +Fixes: d98f26073beb ("target/i386: kvm: add VMX migration blocker") +Signed-off-by: Liran Alon +Reviewed-by: Maran Wilson +Message-Id: <20190619162140.133674-2-liran.alon@oracle.com> +Signed-off-by: Paolo Bonzini +(cherry picked from commit 6b2341eeea43c00b8e266026cec84d57af1484dc) +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/kvm.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/target/i386/kvm.c b/target/i386/kvm.c +index 875412c..8e861a1 100644 +--- a/target/i386/kvm.c ++++ b/target/i386/kvm.c +@@ -798,7 +798,7 @@ int kvm_arch_init_vcpu(CPUState *cs) + + r = kvm_arch_set_tsc_khz(cs); + if (r < 0) { +- goto fail; ++ return r; + } + + /* vcpu's TSC frequency is either specified by user, or following +@@ -1142,7 +1142,7 @@ int kvm_arch_init_vcpu(CPUState *cs) + if (local_err) { + error_report_err(local_err); + error_free(invtsc_mig_blocker); +- return r; ++ goto fail2; + } + /* for savevm */ + vmstate_x86_cpu.unmigratable = 1; +@@ -1190,6 +1190,9 @@ int kvm_arch_init_vcpu(CPUState *cs) + + fail: + migrate_del_blocker(invtsc_mig_blocker); ++ fail2: ++ migrate_del_blocker(vmx_mig_blocker); ++ + return r; + } + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-kvm-Demand-nested-migration-kernel-capab.patch b/SOURCES/kvm-target-i386-kvm-Demand-nested-migration-kernel-capab.patch new file mode 100644 index 0000000..07ddbfd --- /dev/null +++ b/SOURCES/kvm-target-i386-kvm-Demand-nested-migration-kernel-capab.patch @@ -0,0 +1,217 @@ +From 2427e21de274cf7b56ef79e4a7ba78a08def7a58 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Mon, 22 Jul 2019 18:22:18 +0100 +Subject: [PATCH 37/39] target/i386: kvm: Demand nested migration kernel + capabilities only when vCPU may have enabled VMX + +RH-Author: Paolo Bonzini +Message-id: <20190722182220.19374-17-pbonzini@redhat.com> +Patchwork-id: 89634 +O-Subject: [RHEL-8.1.0 PATCH qemu-kvm v3 16/18] target/i386: kvm: Demand nested migration kernel capabilities only when vCPU may have enabled VMX +Bugzilla: 1689269 +RH-Acked-by: Peter Xu +RH-Acked-by: Laurent Vivier +RH-Acked-by: Dr. David Alan Gilbert + +From: Liran Alon + +Previous to this change, a vCPU exposed with VMX running on a kernel +without KVM_CAP_NESTED_STATE or KVM_CAP_EXCEPTION_PAYLOAD resulted in +adding a migration blocker. This was because when the code was written +it was thought there is no way to reliably know if a vCPU is utilising +VMX or not at runtime. However, it turns out that this can be known to +some extent: + +In order for a vCPU to enter VMX operation it must have CR4.VMXE set. +Since it was set, CR4.VMXE must remain set as long as the vCPU is in +VMX operation. This is because CR4.VMXE is one of the bits set +in MSR_IA32_VMX_CR4_FIXED1. +There is one exception to the above statement when vCPU enters SMM mode. +When a vCPU enters SMM mode, it temporarily exits VMX operation and +may also reset CR4.VMXE during execution in SMM mode. +When the vCPU exits SMM mode, vCPU state is restored to be in VMX operation +and CR4.VMXE is restored to its original state of being set. +Therefore, when the vCPU is not in SMM mode, we can infer whether +VMX is being used by examining CR4.VMXE. Otherwise, we cannot +know for certain but assume the worse that vCPU may utilise VMX. + +Summaring all the above, a vCPU may have enabled VMX in case +CR4.VMXE is set or vCPU is in SMM mode. + +Therefore, remove migration blocker and check before migration +(cpu_pre_save()) if the vCPU may have enabled VMX. If true, only then +require relevant kernel capabilities. + +While at it, demand KVM_CAP_EXCEPTION_PAYLOAD only when the vCPU is in +guest-mode and there is a pending/injected exception. Otherwise, this +kernel capability is not required for proper migration. + +Reviewed-by: Joao Martins +Signed-off-by: Liran Alon +Reviewed-by: Maran Wilson +Tested-by: Maran Wilson +Signed-off-by: Paolo Bonzini +(cherry picked from commit 79a197ab180e75838523c58973b1221ad7bf51eb) +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.h | 22 ++++++++++++++++++++++ + target/i386/kvm.c | 26 ++++++-------------------- + target/i386/kvm_i386.h | 1 + + target/i386/machine.c | 24 ++++++++++++++++++++---- + 4 files changed, 49 insertions(+), 24 deletions(-) + +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index d120f62..273c90b 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -1848,6 +1848,28 @@ static inline bool cpu_has_vmx(CPUX86State *env) + return env->features[FEAT_1_ECX] & CPUID_EXT_VMX; + } + ++/* ++ * In order for a vCPU to enter VMX operation it must have CR4.VMXE set. ++ * Since it was set, CR4.VMXE must remain set as long as vCPU is in ++ * VMX operation. This is because CR4.VMXE is one of the bits set ++ * in MSR_IA32_VMX_CR4_FIXED1. ++ * ++ * There is one exception to above statement when vCPU enters SMM mode. ++ * When a vCPU enters SMM mode, it temporarily exit VMX operation and ++ * may also reset CR4.VMXE during execution in SMM mode. ++ * When vCPU exits SMM mode, vCPU state is restored to be in VMX operation ++ * and CR4.VMXE is restored to it's original value of being set. ++ * ++ * Therefore, when vCPU is not in SMM mode, we can infer whether ++ * VMX is being used by examining CR4.VMXE. Otherwise, we cannot ++ * know for certain. ++ */ ++static inline bool cpu_vmx_maybe_enabled(CPUX86State *env) ++{ ++ return cpu_has_vmx(env) && ++ ((env->cr[4] & CR4_VMXE_MASK) || (env->hflags & HF_SMM_MASK)); ++} ++ + /* fpu_helper.c */ + void update_fp_status(CPUX86State *env); + void update_mxcsr_status(CPUX86State *env); +diff --git a/target/i386/kvm.c b/target/i386/kvm.c +index 0619aba..0bd286e 100644 +--- a/target/i386/kvm.c ++++ b/target/i386/kvm.c +@@ -127,6 +127,11 @@ bool kvm_has_adjust_clock_stable(void) + return (ret == KVM_CLOCK_TSC_STABLE); + } + ++bool kvm_has_exception_payload(void) ++{ ++ return has_exception_payload; ++} ++ + bool kvm_allows_irq0_override(void) + { + return !kvm_irqchip_in_kernel() || kvm_has_gsi_routing(); +@@ -814,7 +819,6 @@ static int hyperv_handle_properties(CPUState *cs) + } + + static Error *invtsc_mig_blocker; +-static Error *nested_virt_mig_blocker; + + #define KVM_MAX_CPUID_ENTRIES 100 + +@@ -1159,22 +1163,6 @@ int kvm_arch_init_vcpu(CPUState *cs) + !!(c->ecx & CPUID_EXT_SMX); + } + +- if (cpu_has_vmx(env) && !nested_virt_mig_blocker && +- ((kvm_max_nested_state_length() <= 0) || !has_exception_payload)) { +- error_setg(&nested_virt_mig_blocker, +- "Kernel do not provide required capabilities for " +- "nested virtualization migration. " +- "(CAP_NESTED_STATE=%d, CAP_EXCEPTION_PAYLOAD=%d)", +- kvm_max_nested_state_length() > 0, +- has_exception_payload); +- r = migrate_add_blocker(nested_virt_mig_blocker, &local_err); +- if (local_err) { +- error_report_err(local_err); +- error_free(nested_virt_mig_blocker); +- return r; +- } +- } +- + if (env->mcg_cap & MCG_LMCE_P) { + has_msr_mcg_ext_ctl = has_msr_feature_control = true; + } +@@ -1190,7 +1178,7 @@ int kvm_arch_init_vcpu(CPUState *cs) + if (local_err) { + error_report_err(local_err); + error_free(invtsc_mig_blocker); +- goto fail2; ++ return r; + } + /* for savevm */ + vmstate_x86_cpu.unmigratable = 1; +@@ -1256,8 +1244,6 @@ int kvm_arch_init_vcpu(CPUState *cs) + + fail: + migrate_del_blocker(invtsc_mig_blocker); +- fail2: +- migrate_del_blocker(nested_virt_mig_blocker); + + return r; + } +diff --git a/target/i386/kvm_i386.h b/target/i386/kvm_i386.h +index 1de9876..df9bbf3 100644 +--- a/target/i386/kvm_i386.h ++++ b/target/i386/kvm_i386.h +@@ -41,6 +41,7 @@ + bool kvm_allows_irq0_override(void); + bool kvm_has_smm(void); + bool kvm_has_adjust_clock_stable(void); ++bool kvm_has_exception_payload(void); + void kvm_synchronize_all_tsc(void); + void kvm_arch_reset_vcpu(X86CPU *cs); + void kvm_arch_do_init_vcpu(X86CPU *cs); +diff --git a/target/i386/machine.c b/target/i386/machine.c +index 5ffee8f..8d90d98 100644 +--- a/target/i386/machine.c ++++ b/target/i386/machine.c +@@ -7,6 +7,7 @@ + #include "hw/i386/pc.h" + #include "hw/isa/isa.h" + #include "migration/cpu.h" ++#include "kvm_i386.h" + + #include "sysemu/kvm.h" + +@@ -231,10 +232,25 @@ static int cpu_pre_save(void *opaque) + } + + #ifdef CONFIG_KVM +- /* Verify we have nested virtualization state from kernel if required */ +- if (kvm_enabled() && cpu_has_vmx(env) && !env->nested_state) { +- error_report("Guest enabled nested virtualization but kernel " +- "does not support saving of nested state"); ++ /* ++ * In case vCPU may have enabled VMX, we need to make sure kernel have ++ * required capabilities in order to perform migration correctly: ++ * ++ * 1) We must be able to extract vCPU nested-state from KVM. ++ * ++ * 2) In case vCPU is running in guest-mode and it has a pending exception, ++ * we must be able to determine if it's in a pending or injected state. ++ * Note that in case KVM don't have required capability to do so, ++ * a pending/injected exception will always appear as an ++ * injected exception. ++ */ ++ if (kvm_enabled() && cpu_vmx_maybe_enabled(env) && ++ (!env->nested_state || ++ (!kvm_has_exception_payload() && (env->hflags & HF_GUEST_MASK) && ++ env->exception_injected))) { ++ error_report("Guest maybe enabled nested virtualization but kernel " ++ "does not support required capabilities to save vCPU " ++ "nested state"); + return -EINVAL; + } + #endif +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-kvm-Re-inject-DB-to-guest-with-updated-D.patch b/SOURCES/kvm-target-i386-kvm-Re-inject-DB-to-guest-with-updated-D.patch new file mode 100644 index 0000000..adb30cb --- /dev/null +++ b/SOURCES/kvm-target-i386-kvm-Re-inject-DB-to-guest-with-updated-D.patch @@ -0,0 +1,66 @@ +From c31315e765df0137cb7dfedb3869db72d6d2ca57 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Mon, 22 Jul 2019 18:22:10 +0100 +Subject: [PATCH 29/39] target/i386: kvm: Re-inject #DB to guest with updated + DR6 + +RH-Author: Paolo Bonzini +Message-id: <20190722182220.19374-9-pbonzini@redhat.com> +Patchwork-id: 89626 +O-Subject: [RHEL-8.1.0 PATCH qemu-kvm v3 08/18] target/i386: kvm: Re-inject #DB to guest with updated DR6 +Bugzilla: 1689269 +RH-Acked-by: Peter Xu +RH-Acked-by: Laurent Vivier +RH-Acked-by: Dr. David Alan Gilbert + +From: Liran Alon + +If userspace (QEMU) debug guest, when #DB is raised in guest and +intercepted by KVM, KVM forwards information on #DB to userspace +instead of injecting #DB to guest. +While doing so, KVM don't update vCPU DR6 but instead report the #DB DR6 +value to userspace for further handling. +See KVM's handle_exception() DB_VECTOR handler. + +QEMU handler for this case is kvm_handle_debug(). This handler basically +checks if #DB is related to one of user set hardware breakpoints and if +not, it re-inject #DB into guest. +The re-injection is done by setting env->exception_injected to #DB which +will later be passed as events.exception.nr to KVM_SET_VCPU_EVENTS ioctl +by kvm_put_vcpu_events(). + +However, in case userspace re-injects #DB, KVM expects userspace to set +vCPU DR6 as reported to userspace when #DB was intercepted! Otherwise, +KVM_REQ_EVENT handler will inject #DB with wrong DR6 to guest. + +Fix this issue by updating vCPU DR6 appropriately when re-inject #DB to +guest. + +Reviewed-by: Nikita Leshenko +Reviewed-by: Krish Sadhukhan +Signed-off-by: Liran Alon +Message-Id: <20190619162140.133674-5-liran.alon@oracle.com> +Signed-off-by: Paolo Bonzini +(cherry picked from commit bceeeef9e7544057659118688243260c390eceb9) +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/kvm.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/target/i386/kvm.c b/target/i386/kvm.c +index 4138fe9..1a4ff3c 100644 +--- a/target/i386/kvm.c ++++ b/target/i386/kvm.c +@@ -3363,6 +3363,9 @@ static int kvm_handle_debug(X86CPU *cpu, + /* pass to guest */ + env->exception_injected = arch_info->exception; + env->has_error_code = 0; ++ if (arch_info->exception == EXCP01_DB) { ++ env->dr[6] = arch_info->dr6; ++ } + } + + return ret; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-kvm-Use-symbolic-constant-for-DB-BP-exce.patch b/SOURCES/kvm-target-i386-kvm-Use-symbolic-constant-for-DB-BP-exce.patch new file mode 100644 index 0000000..b551bc8 --- /dev/null +++ b/SOURCES/kvm-target-i386-kvm-Use-symbolic-constant-for-DB-BP-exce.patch @@ -0,0 +1,58 @@ +From 0168573b58d5e70a60c9fef319ba510aa9648f2d Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Mon, 22 Jul 2019 18:22:09 +0100 +Subject: [PATCH 28/39] target/i386: kvm: Use symbolic constant for #DB/#BP + exception constants + +RH-Author: Paolo Bonzini +Message-id: <20190722182220.19374-8-pbonzini@redhat.com> +Patchwork-id: 89625 +O-Subject: [RHEL-8.1.0 PATCH qemu-kvm v3 07/18] target/i386: kvm: Use symbolic constant for #DB/#BP exception constants +Bugzilla: 1689269 +RH-Acked-by: Peter Xu +RH-Acked-by: Laurent Vivier +RH-Acked-by: Dr. David Alan Gilbert + +From: Liran Alon + +Reviewed-by: Nikita Leshenko +Reviewed-by: Krish Sadhukhan +Signed-off-by: Liran Alon +Message-Id: <20190619162140.133674-4-liran.alon@oracle.com> +Signed-off-by: Paolo Bonzini +(cherry picked from commit 37936ac70f6c20aec6f537349eb797fb98f9a99d) +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/kvm.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/target/i386/kvm.c b/target/i386/kvm.c +index 305809f..4138fe9 100644 +--- a/target/i386/kvm.c ++++ b/target/i386/kvm.c +@@ -2811,9 +2811,9 @@ static int kvm_guest_debug_workarounds(X86CPU *cpu) + unsigned long reinject_trap = 0; + + if (!kvm_has_vcpu_events()) { +- if (env->exception_injected == 1) { ++ if (env->exception_injected == EXCP01_DB) { + reinject_trap = KVM_GUESTDBG_INJECT_DB; +- } else if (env->exception_injected == 3) { ++ } else if (env->exception_injected == EXCP03_INT3) { + reinject_trap = KVM_GUESTDBG_INJECT_BP; + } + env->exception_injected = -1; +@@ -3325,8 +3325,8 @@ static int kvm_handle_debug(X86CPU *cpu, + int ret = 0; + int n; + +- if (arch_info->exception == 1) { +- if (arch_info->dr6 & (1 << 14)) { ++ if (arch_info->exception == EXCP01_DB) { ++ if (arch_info->dr6 & DR6_BS) { + if (cs->singlestep_enabled) { + ret = EXCP_DEBUG; + } +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-kvm-add-VMX-migration-blocker.patch b/SOURCES/kvm-target-i386-kvm-add-VMX-migration-blocker.patch new file mode 100644 index 0000000..2adbaea --- /dev/null +++ b/SOURCES/kvm-target-i386-kvm-add-VMX-migration-blocker.patch @@ -0,0 +1,60 @@ +From 9a920701b3d2d78612bc454c407cf7b0d01f51c6 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Mon, 22 Jul 2019 18:22:05 +0100 +Subject: [PATCH 24/39] target/i386: kvm: add VMX migration blocker + +RH-Author: Paolo Bonzini +Message-id: <20190722182220.19374-4-pbonzini@redhat.com> +Patchwork-id: 89621 +O-Subject: [RHEL-8.1.0 PATCH qemu-kvm v3 03/18] target/i386: kvm: add VMX migration blocker +Bugzilla: 1689269 +RH-Acked-by: Peter Xu +RH-Acked-by: Laurent Vivier +RH-Acked-by: Dr. David Alan Gilbert + +Nested VMX does not support live migration yet. Add a blocker +until that is worked out. + +Nested SVM only does not support it, but unfortunately it is +enabled by default for -cpu host so we cannot really disable it. + +Signed-off-by: Paolo Bonzini +(cherry picked from commit d98f26073bebddcd3da0ba1b86c3a34e840c0fb8) +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/kvm.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/target/i386/kvm.c b/target/i386/kvm.c +index 8a4d31d..d414187 100644 +--- a/target/i386/kvm.c ++++ b/target/i386/kvm.c +@@ -772,6 +772,7 @@ static int hyperv_handle_properties(CPUState *cs) + } + + static Error *invtsc_mig_blocker; ++static Error *vmx_mig_blocker; + + #define KVM_MAX_CPUID_ENTRIES 100 + +@@ -1115,6 +1116,17 @@ int kvm_arch_init_vcpu(CPUState *cs) + !!(c->ecx & CPUID_EXT_SMX); + } + ++ if ((env->features[FEAT_1_ECX] & CPUID_EXT_VMX) && !vmx_mig_blocker) { ++ error_setg(&vmx_mig_blocker, ++ "Nested VMX virtualization does not support live migration yet"); ++ r = migrate_add_blocker(vmx_mig_blocker, &local_err); ++ if (local_err) { ++ error_report_err(local_err); ++ error_free(vmx_mig_blocker); ++ return r; ++ } ++ } ++ + if (env->mcg_cap & MCG_LMCE_P) { + has_msr_mcg_ext_ctl = has_msr_feature_control = true; + } +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-kvm-do-not-initialize-padding-fields.patch b/SOURCES/kvm-target-i386-kvm-do-not-initialize-padding-fields.patch new file mode 100644 index 0000000..8f32cad --- /dev/null +++ b/SOURCES/kvm-target-i386-kvm-do-not-initialize-padding-fields.patch @@ -0,0 +1,52 @@ +From 61f0e94fd78c21f2d7e1b2893dc11103399a0efe Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Mon, 22 Jul 2019 18:22:12 +0100 +Subject: [PATCH 31/39] target-i386: kvm: do not initialize padding fields + +RH-Author: Paolo Bonzini +Message-id: <20190722182220.19374-11-pbonzini@redhat.com> +Patchwork-id: 89627 +O-Subject: [RHEL-8.1.0 PATCH qemu-kvm v3 10/18] target-i386: kvm: do not initialize padding fields +Bugzilla: 1689269 +RH-Acked-by: Peter Xu +RH-Acked-by: Laurent Vivier +RH-Acked-by: Dr. David Alan Gilbert + +The exception.pad field is going to be renamed to pending in an upcoming +header file update. Remove the unnecessary initialization; it was +introduced to please valgrind (commit 7e680753cfa2) but they were later +rendered unnecessary by commit 076796f8fd27f4d, which added the "= {}" +initializer to the declaration of "events". Therefore the patch does +not change behavior in any way. + +Reviewed-by: Peter Maydell +Signed-off-by: Paolo Bonzini +(cherry picked from commit b31c003895b030bea1319037d6bec976d47d9020) +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/kvm.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/target/i386/kvm.c b/target/i386/kvm.c +index f741e8b..8a6da90 100644 +--- a/target/i386/kvm.c ++++ b/target/i386/kvm.c +@@ -2696,7 +2696,6 @@ static int kvm_put_vcpu_events(X86CPU *cpu, int level) + events.exception.nr = env->exception_injected; + events.exception.has_error_code = env->has_error_code; + events.exception.error_code = env->error_code; +- events.exception.pad = 0; + + events.interrupt.injected = (env->interrupt_injected >= 0); + events.interrupt.nr = env->interrupt_injected; +@@ -2705,7 +2704,6 @@ static int kvm_put_vcpu_events(X86CPU *cpu, int level) + events.nmi.injected = env->nmi_injected; + events.nmi.pending = env->nmi_pending; + events.nmi.masked = !!(env->hflags2 & HF2_NMI_MASK); +- events.nmi.pad = 0; + + events.sipi_vector = env->sipi_vector; + events.flags = 0; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-kvm-initialize-feature-MSRs-very-early.patch b/SOURCES/kvm-target-i386-kvm-initialize-feature-MSRs-very-early.patch new file mode 100644 index 0000000..d715457 --- /dev/null +++ b/SOURCES/kvm-target-i386-kvm-initialize-feature-MSRs-very-early.patch @@ -0,0 +1,176 @@ +From c4660f9a4e2ffde711294ee7c5959f17735fd863 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Thu, 6 Feb 2020 23:51:16 +0000 +Subject: [PATCH 2/2] target/i386: kvm: initialize feature MSRs very early + +RH-Author: Paolo Bonzini +Message-id: <20200206235116.19421-2-pbonzini@redhat.com> +Patchwork-id: 93733 +O-Subject: [PATCH 1/1] target/i386: kvm: initialize feature MSRs very early +Bugzilla: 1790308 +RH-Acked-by: Vitaly Kuznetsov +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Eduardo Habkost + +Some read-only MSRs affect the behavior of ioctls such as +KVM_SET_NESTED_STATE. We can initialize them once and for all +right after the CPU is realized, since they will never be modified +by the guest. + +Reported-by: Qingua Cheng +Cc: qemu-stable@nongnu.org +Signed-off-by: Paolo Bonzini +Message-Id: <1579544504-3616-2-git-send-email-pbonzini@redhat.com> +Signed-off-by: Paolo Bonzini +(cherry picked from commit 420ae1fc51c99abfd03b1c590f55617edd2a2bed) +Signed-off-by: Paolo Bonzini +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/kvm.c | 81 ++++++++++++++++++++++++++++++-------------------- + target/i386/kvm_i386.h | 1 + + 2 files changed, 49 insertions(+), 33 deletions(-) + +diff --git a/target/i386/kvm.c b/target/i386/kvm.c +index 92eda8d..e43bcd3 100644 +--- a/target/i386/kvm.c ++++ b/target/i386/kvm.c +@@ -65,6 +65,8 @@ + * 255 kvm_msr_entry structs */ + #define MSR_BUF_SIZE 4096 + ++static void kvm_init_msrs(X86CPU *cpu); ++ + const KVMCapabilityInfo kvm_arch_required_capabilities[] = { + KVM_CAP_INFO(SET_TSS_ADDR), + KVM_CAP_INFO(EXT_CPUID), +@@ -1296,6 +1298,8 @@ int kvm_arch_init_vcpu(CPUState *cs) + has_msr_tsc_aux = false; + } + ++ kvm_init_msrs(cpu); ++ + return 0; + + fail: +@@ -2099,11 +2103,53 @@ static void kvm_msr_entry_add_vmx(X86CPU *cpu, FeatureWordArray f) + VMCS12_MAX_FIELD_INDEX << 1); + } + ++static int kvm_buf_set_msrs(X86CPU *cpu) ++{ ++ int ret = kvm_vcpu_ioctl(CPU(cpu), KVM_SET_MSRS, cpu->kvm_msr_buf); ++ if (ret < 0) { ++ return ret; ++ } ++ ++ if (ret < cpu->kvm_msr_buf->nmsrs) { ++ struct kvm_msr_entry *e = &cpu->kvm_msr_buf->entries[ret]; ++ error_report("error: failed to set MSR 0x%" PRIx32 " to 0x%" PRIx64, ++ (uint32_t)e->index, (uint64_t)e->data); ++ } ++ ++ assert(ret == cpu->kvm_msr_buf->nmsrs); ++ return 0; ++} ++ ++static void kvm_init_msrs(X86CPU *cpu) ++{ ++ CPUX86State *env = &cpu->env; ++ ++ kvm_msr_buf_reset(cpu); ++ if (has_msr_arch_capabs) { ++ kvm_msr_entry_add(cpu, MSR_IA32_ARCH_CAPABILITIES, ++ env->features[FEAT_ARCH_CAPABILITIES]); ++ } ++ ++ if (has_msr_core_capabs) { ++ kvm_msr_entry_add(cpu, MSR_IA32_CORE_CAPABILITY, ++ env->features[FEAT_CORE_CAPABILITY]); ++ } ++ ++ /* ++ * Older kernels do not include VMX MSRs in KVM_GET_MSR_INDEX_LIST, but ++ * all kernels with MSR features should have them. ++ */ ++ if (kvm_feature_msrs && cpu_has_vmx(env)) { ++ kvm_msr_entry_add_vmx(cpu, env->features); ++ } ++ ++ assert(kvm_buf_set_msrs(cpu) == 0); ++} ++ + static int kvm_put_msrs(X86CPU *cpu, int level) + { + CPUX86State *env = &cpu->env; + int i; +- int ret; + + kvm_msr_buf_reset(cpu); + +@@ -2161,17 +2207,6 @@ static int kvm_put_msrs(X86CPU *cpu, int level) + } + #endif + +- /* If host supports feature MSR, write down. */ +- if (has_msr_arch_capabs) { +- kvm_msr_entry_add(cpu, MSR_IA32_ARCH_CAPABILITIES, +- env->features[FEAT_ARCH_CAPABILITIES]); +- } +- +- if (has_msr_core_capabs) { +- kvm_msr_entry_add(cpu, MSR_IA32_CORE_CAPABILITY, +- env->features[FEAT_CORE_CAPABILITY]); +- } +- + /* + * The following MSRs have side effects on the guest or are too heavy + * for normal writeback. Limit them to reset or full state updates. +@@ -2331,14 +2366,6 @@ static int kvm_put_msrs(X86CPU *cpu, int level) + + /* Note: MSR_IA32_FEATURE_CONTROL is written separately, see + * kvm_put_msr_feature_control. */ +- +- /* +- * Older kernels do not include VMX MSRs in KVM_GET_MSR_INDEX_LIST, but +- * all kernels with MSR features should have them. +- */ +- if (kvm_feature_msrs && cpu_has_vmx(env)) { +- kvm_msr_entry_add_vmx(cpu, env->features); +- } + } + + if (env->mcg_cap) { +@@ -2354,19 +2381,7 @@ static int kvm_put_msrs(X86CPU *cpu, int level) + } + } + +- ret = kvm_vcpu_ioctl(CPU(cpu), KVM_SET_MSRS, cpu->kvm_msr_buf); +- if (ret < 0) { +- return ret; +- } +- +- if (ret < cpu->kvm_msr_buf->nmsrs) { +- struct kvm_msr_entry *e = &cpu->kvm_msr_buf->entries[ret]; +- error_report("error: failed to set MSR 0x%" PRIx32 " to 0x%" PRIx64, +- (uint32_t)e->index, (uint64_t)e->data); +- } +- +- assert(ret == cpu->kvm_msr_buf->nmsrs); +- return 0; ++ return kvm_buf_set_msrs(cpu); + } + + +diff --git a/target/i386/kvm_i386.h b/target/i386/kvm_i386.h +index df9bbf3..5748337 100644 +--- a/target/i386/kvm_i386.h ++++ b/target/i386/kvm_i386.h +@@ -70,4 +70,5 @@ void kvm_put_apicbase(X86CPU *cpu, uint64_t value); + + bool kvm_enable_x2apic(void); + bool kvm_has_x2apic_api(void); ++ + #endif +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-kvm-just-return-after-migrate_add_blocke.patch b/SOURCES/kvm-target-i386-kvm-just-return-after-migrate_add_blocke.patch new file mode 100644 index 0000000..2a3cbc8 --- /dev/null +++ b/SOURCES/kvm-target-i386-kvm-just-return-after-migrate_add_blocke.patch @@ -0,0 +1,45 @@ +From 28e39ed55e3b01d883e0fa7d2d65937769fa5f72 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Mon, 22 Jul 2019 18:22:06 +0100 +Subject: [PATCH 25/39] target/i386: kvm: just return after migrate_add_blocker + failed + +RH-Author: Paolo Bonzini +Message-id: <20190722182220.19374-5-pbonzini@redhat.com> +Patchwork-id: 89622 +O-Subject: [RHEL-8.1.0 PATCH qemu-kvm v3 04/18] target/i386: kvm: just return after migrate_add_blocker failed +Bugzilla: 1689269 +RH-Acked-by: Peter Xu +RH-Acked-by: Laurent Vivier +RH-Acked-by: Dr. David Alan Gilbert + +From: Li Qiang + +When migrate_add_blocker failed, the invtsc_mig_blocker is not +appended so no need to remove. This can save several instructions. + +Signed-off-by: Li Qiang +Message-Id: <20181006091816.7659-1-liq3ea@163.com> +Signed-off-by: Paolo Bonzini +(cherry picked from commit 0c2ed83fa45aa5d80ecc7d3fff0ab38db2db5972) +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/kvm.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/target/i386/kvm.c b/target/i386/kvm.c +index d414187..875412c 100644 +--- a/target/i386/kvm.c ++++ b/target/i386/kvm.c +@@ -1142,7 +1142,7 @@ int kvm_arch_init_vcpu(CPUState *cs) + if (local_err) { + error_report_err(local_err); + error_free(invtsc_mig_blocker); +- goto fail; ++ return r; + } + /* for savevm */ + vmstate_x86_cpu.unmigratable = 1; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-kvm-kvm_get_supported_msrs-cleanup.patch b/SOURCES/kvm-target-i386-kvm-kvm_get_supported_msrs-cleanup.patch new file mode 100644 index 0000000..3fffb50 --- /dev/null +++ b/SOURCES/kvm-target-i386-kvm-kvm_get_supported_msrs-cleanup.patch @@ -0,0 +1,231 @@ +From 07cb338d84e4f439b0a62fbdcbe2162936e3728a Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Fri, 22 Nov 2019 11:53:38 +0000 +Subject: [PATCH 05/16] target-i386: kvm: 'kvm_get_supported_msrs' cleanup + +RH-Author: Paolo Bonzini +Message-id: <20191122115348.25000-6-pbonzini@redhat.com> +Patchwork-id: 92606 +O-Subject: [RHEL8.2/rhel qemu-kvm PATCH 05/15] target-i386: kvm: 'kvm_get_supported_msrs' cleanup +Bugzilla: 1689270 +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Eduardo Habkost +RH-Acked-by: Maxim Levitsky + +From: Li Qiang + +Function 'kvm_get_supported_msrs' is only called once +now, get rid of the static variable 'kvm_supported_msrs'. + +Signed-off-by: Li Qiang +Message-Id: <20190725151639.21693-1-liq3ea@163.com> +Signed-off-by: Paolo Bonzini +(cherry picked from commit de428cead63a958137ee63efcc3cceaf75f6c125) + +RHEL: no HV_X64_MSR_REENLIGHTENMENT_CONTROL +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/kvm.c | 179 +++++++++++++++++++++++++++--------------------------- + 1 file changed, 88 insertions(+), 91 deletions(-) + +diff --git a/target/i386/kvm.c b/target/i386/kvm.c +index 849a11a..2290c5d 100644 +--- a/target/i386/kvm.c ++++ b/target/i386/kvm.c +@@ -1340,105 +1340,102 @@ static int kvm_get_supported_feature_msrs(KVMState *s) + + static int kvm_get_supported_msrs(KVMState *s) + { +- static int kvm_supported_msrs; + int ret = 0; ++ struct kvm_msr_list msr_list, *kvm_msr_list; + +- /* first time */ +- if (kvm_supported_msrs == 0) { +- struct kvm_msr_list msr_list, *kvm_msr_list; ++ /* ++ * Obtain MSR list from KVM. These are the MSRs that we must ++ * save/restore. ++ */ ++ msr_list.nmsrs = 0; ++ ret = kvm_ioctl(s, KVM_GET_MSR_INDEX_LIST, &msr_list); ++ if (ret < 0 && ret != -E2BIG) { ++ return ret; ++ } ++ /* ++ * Old kernel modules had a bug and could write beyond the provided ++ * memory. Allocate at least a safe amount of 1K. ++ */ ++ kvm_msr_list = g_malloc0(MAX(1024, sizeof(msr_list) + ++ msr_list.nmsrs * ++ sizeof(msr_list.indices[0]))); + +- kvm_supported_msrs = -1; ++ kvm_msr_list->nmsrs = msr_list.nmsrs; ++ ret = kvm_ioctl(s, KVM_GET_MSR_INDEX_LIST, kvm_msr_list); ++ if (ret >= 0) { ++ int i; + +- /* Obtain MSR list from KVM. These are the MSRs that we must +- * save/restore */ +- msr_list.nmsrs = 0; +- ret = kvm_ioctl(s, KVM_GET_MSR_INDEX_LIST, &msr_list); +- if (ret < 0 && ret != -E2BIG) { +- return ret; +- } +- /* Old kernel modules had a bug and could write beyond the provided +- memory. Allocate at least a safe amount of 1K. */ +- kvm_msr_list = g_malloc0(MAX(1024, sizeof(msr_list) + +- msr_list.nmsrs * +- sizeof(msr_list.indices[0]))); +- +- kvm_msr_list->nmsrs = msr_list.nmsrs; +- ret = kvm_ioctl(s, KVM_GET_MSR_INDEX_LIST, kvm_msr_list); +- if (ret >= 0) { +- int i; +- +- for (i = 0; i < kvm_msr_list->nmsrs; i++) { +- switch (kvm_msr_list->indices[i]) { +- case MSR_STAR: +- has_msr_star = true; +- break; +- case MSR_VM_HSAVE_PA: +- has_msr_hsave_pa = true; +- break; +- case MSR_TSC_AUX: +- has_msr_tsc_aux = true; +- break; +- case MSR_TSC_ADJUST: +- has_msr_tsc_adjust = true; +- break; +- case MSR_IA32_TSCDEADLINE: +- has_msr_tsc_deadline = true; +- break; +- case MSR_IA32_SMBASE: +- has_msr_smbase = true; +- break; +- case MSR_SMI_COUNT: +- has_msr_smi_count = true; +- break; +- case MSR_IA32_MISC_ENABLE: +- has_msr_misc_enable = true; +- break; +- case MSR_IA32_BNDCFGS: +- has_msr_bndcfgs = true; +- break; +- case MSR_IA32_XSS: +- has_msr_xss = true; +- break; +- case HV_X64_MSR_CRASH_CTL: +- has_msr_hv_crash = true; +- break; +- case HV_X64_MSR_RESET: +- has_msr_hv_reset = true; +- break; +- case HV_X64_MSR_VP_INDEX: +- has_msr_hv_vpindex = true; +- break; +- case HV_X64_MSR_VP_RUNTIME: +- has_msr_hv_runtime = true; +- break; +- case HV_X64_MSR_SCONTROL: +- has_msr_hv_synic = true; +- break; +- case HV_X64_MSR_STIMER0_CONFIG: +- has_msr_hv_stimer = true; +- break; +- case HV_X64_MSR_TSC_FREQUENCY: +- has_msr_hv_frequencies = true; +- break; +- case MSR_IA32_SPEC_CTRL: +- has_msr_spec_ctrl = true; +- break; +- case MSR_VIRT_SSBD: +- has_msr_virt_ssbd = true; +- break; +- case MSR_IA32_ARCH_CAPABILITIES: +- has_msr_arch_capabs = true; +- break; +- case MSR_IA32_CORE_CAPABILITY: +- has_msr_core_capabs = true; +- break; +- } ++ for (i = 0; i < kvm_msr_list->nmsrs; i++) { ++ switch (kvm_msr_list->indices[i]) { ++ case MSR_STAR: ++ has_msr_star = true; ++ break; ++ case MSR_VM_HSAVE_PA: ++ has_msr_hsave_pa = true; ++ break; ++ case MSR_TSC_AUX: ++ has_msr_tsc_aux = true; ++ break; ++ case MSR_TSC_ADJUST: ++ has_msr_tsc_adjust = true; ++ break; ++ case MSR_IA32_TSCDEADLINE: ++ has_msr_tsc_deadline = true; ++ break; ++ case MSR_IA32_SMBASE: ++ has_msr_smbase = true; ++ break; ++ case MSR_SMI_COUNT: ++ has_msr_smi_count = true; ++ break; ++ case MSR_IA32_MISC_ENABLE: ++ has_msr_misc_enable = true; ++ break; ++ case MSR_IA32_BNDCFGS: ++ has_msr_bndcfgs = true; ++ break; ++ case MSR_IA32_XSS: ++ has_msr_xss = true; ++ break; ++ case HV_X64_MSR_CRASH_CTL: ++ has_msr_hv_crash = true; ++ break; ++ case HV_X64_MSR_RESET: ++ has_msr_hv_reset = true; ++ break; ++ case HV_X64_MSR_VP_INDEX: ++ has_msr_hv_vpindex = true; ++ break; ++ case HV_X64_MSR_VP_RUNTIME: ++ has_msr_hv_runtime = true; ++ break; ++ case HV_X64_MSR_SCONTROL: ++ has_msr_hv_synic = true; ++ break; ++ case HV_X64_MSR_STIMER0_CONFIG: ++ has_msr_hv_stimer = true; ++ break; ++ case HV_X64_MSR_TSC_FREQUENCY: ++ has_msr_hv_frequencies = true; ++ break; ++ case MSR_IA32_SPEC_CTRL: ++ has_msr_spec_ctrl = true; ++ break; ++ case MSR_VIRT_SSBD: ++ has_msr_virt_ssbd = true; ++ break; ++ case MSR_IA32_ARCH_CAPABILITIES: ++ has_msr_arch_capabs = true; ++ break; ++ case MSR_IA32_CORE_CAPABILITY: ++ has_msr_core_capabs = true; ++ break; + } + } +- +- g_free(kvm_msr_list); + } + ++ g_free(kvm_msr_list); ++ + return ret; + } + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-rename-HF_SVMI_MASK-to-HF_GUEST_MASK.patch b/SOURCES/kvm-target-i386-rename-HF_SVMI_MASK-to-HF_GUEST_MASK.patch new file mode 100644 index 0000000..63d5112 --- /dev/null +++ b/SOURCES/kvm-target-i386-rename-HF_SVMI_MASK-to-HF_GUEST_MASK.patch @@ -0,0 +1,150 @@ +From 9d1e37615a8285d852b7d8f829b9f9aeed703f14 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Mon, 22 Jul 2019 18:22:04 +0100 +Subject: [PATCH 23/39] target/i386: rename HF_SVMI_MASK to HF_GUEST_MASK + +RH-Author: Paolo Bonzini +Message-id: <20190722182220.19374-3-pbonzini@redhat.com> +Patchwork-id: 89620 +O-Subject: [RHEL-8.1.0 PATCH qemu-kvm v3 02/18] target/i386: rename HF_SVMI_MASK to HF_GUEST_MASK +Bugzilla: 1689269 +RH-Acked-by: Peter Xu +RH-Acked-by: Laurent Vivier +RH-Acked-by: Dr. David Alan Gilbert + +This flag will be used for KVM's nested VMX migration; the HF_GUEST_MASK name +is already used in KVM, adopt it in QEMU as well. + +Signed-off-by: Paolo Bonzini +(cherry picked from commit f8dc4c645ec2956a6cd97e0ca0fdd4753181f735) +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.h | 4 ++-- + target/i386/excp_helper.c | 2 +- + target/i386/seg_helper.c | 6 +++--- + target/i386/svm_helper.c | 6 +++--- + target/i386/translate.c | 4 ++-- + 5 files changed, 11 insertions(+), 11 deletions(-) + +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index 4f9df6e..923dfcd 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -171,7 +171,7 @@ typedef enum X86Seg { + #define HF_AC_SHIFT 18 /* must be same as eflags */ + #define HF_SMM_SHIFT 19 /* CPU in SMM mode */ + #define HF_SVME_SHIFT 20 /* SVME enabled (copy of EFER.SVME) */ +-#define HF_SVMI_SHIFT 21 /* SVM intercepts are active */ ++#define HF_GUEST_SHIFT 21 /* SVM intercepts are active */ + #define HF_OSFXSR_SHIFT 22 /* CR4.OSFXSR */ + #define HF_SMAP_SHIFT 23 /* CR4.SMAP */ + #define HF_IOBPT_SHIFT 24 /* an io breakpoint enabled */ +@@ -196,7 +196,7 @@ typedef enum X86Seg { + #define HF_AC_MASK (1 << HF_AC_SHIFT) + #define HF_SMM_MASK (1 << HF_SMM_SHIFT) + #define HF_SVME_MASK (1 << HF_SVME_SHIFT) +-#define HF_SVMI_MASK (1 << HF_SVMI_SHIFT) ++#define HF_GUEST_MASK (1 << HF_GUEST_SHIFT) + #define HF_OSFXSR_MASK (1 << HF_OSFXSR_SHIFT) + #define HF_SMAP_MASK (1 << HF_SMAP_SHIFT) + #define HF_IOBPT_MASK (1 << HF_IOBPT_SHIFT) +diff --git a/target/i386/excp_helper.c b/target/i386/excp_helper.c +index cb4d1b7..7153837 100644 +--- a/target/i386/excp_helper.c ++++ b/target/i386/excp_helper.c +@@ -53,7 +53,7 @@ static int check_exception(CPUX86State *env, int intno, int *error_code, + + #if !defined(CONFIG_USER_ONLY) + if (env->old_exception == EXCP08_DBLE) { +- if (env->hflags & HF_SVMI_MASK) { ++ if (env->hflags & HF_GUEST_MASK) { + cpu_vmexit(env, SVM_EXIT_SHUTDOWN, 0, retaddr); /* does not return */ + } + +diff --git a/target/i386/seg_helper.c b/target/i386/seg_helper.c +index 600a4d7..f028045 100644 +--- a/target/i386/seg_helper.c ++++ b/target/i386/seg_helper.c +@@ -1239,7 +1239,7 @@ static void do_interrupt_all(X86CPU *cpu, int intno, int is_int, + } + if (env->cr[0] & CR0_PE_MASK) { + #if !defined(CONFIG_USER_ONLY) +- if (env->hflags & HF_SVMI_MASK) { ++ if (env->hflags & HF_GUEST_MASK) { + handle_even_inj(env, intno, is_int, error_code, is_hw, 0); + } + #endif +@@ -1254,7 +1254,7 @@ static void do_interrupt_all(X86CPU *cpu, int intno, int is_int, + } + } else { + #if !defined(CONFIG_USER_ONLY) +- if (env->hflags & HF_SVMI_MASK) { ++ if (env->hflags & HF_GUEST_MASK) { + handle_even_inj(env, intno, is_int, error_code, is_hw, 1); + } + #endif +@@ -1262,7 +1262,7 @@ static void do_interrupt_all(X86CPU *cpu, int intno, int is_int, + } + + #if !defined(CONFIG_USER_ONLY) +- if (env->hflags & HF_SVMI_MASK) { ++ if (env->hflags & HF_GUEST_MASK) { + CPUState *cs = CPU(cpu); + uint32_t event_inj = x86_ldl_phys(cs, env->vm_vmcb + + offsetof(struct vmcb, +diff --git a/target/i386/svm_helper.c b/target/i386/svm_helper.c +index 3504923..5b8458d 100644 +--- a/target/i386/svm_helper.c ++++ b/target/i386/svm_helper.c +@@ -206,7 +206,7 @@ void helper_vmrun(CPUX86State *env, int aflag, int next_eip_addend) + )); + + /* enable intercepts */ +- env->hflags |= HF_SVMI_MASK; ++ env->hflags |= HF_GUEST_MASK; + + env->tsc_offset = x86_ldq_phys(cs, env->vm_vmcb + + offsetof(struct vmcb, control.tsc_offset)); +@@ -481,7 +481,7 @@ void cpu_svm_check_intercept_param(CPUX86State *env, uint32_t type, + { + CPUState *cs = CPU(x86_env_get_cpu(env)); + +- if (likely(!(env->hflags & HF_SVMI_MASK))) { ++ if (likely(!(env->hflags & HF_GUEST_MASK))) { + return; + } + switch (type) { +@@ -674,7 +674,7 @@ void do_vmexit(CPUX86State *env, uint32_t exit_code, uint64_t exit_info_1) + + /* Reload the host state from vm_hsave */ + env->hflags2 &= ~(HF2_HIF_MASK | HF2_VINTR_MASK); +- env->hflags &= ~HF_SVMI_MASK; ++ env->hflags &= ~HF_GUEST_MASK; + env->intercept = 0; + env->intercept_exceptions = 0; + cs->interrupt_request &= ~CPU_INTERRUPT_VIRQ; +diff --git a/target/i386/translate.c b/target/i386/translate.c +index c9ed8dc..2a1b39e 100644 +--- a/target/i386/translate.c ++++ b/target/i386/translate.c +@@ -621,7 +621,7 @@ static void gen_check_io(DisasContext *s, TCGMemOp ot, target_ulong cur_eip, + tcg_abort(); + } + } +- if(s->flags & HF_SVMI_MASK) { ++ if(s->flags & HF_GUEST_MASK) { + gen_update_cc_op(s); + gen_jmp_im(cur_eip); + svm_flags |= (1 << (4 + ot)); +@@ -2305,7 +2305,7 @@ gen_svm_check_intercept_param(DisasContext *s, target_ulong pc_start, + uint32_t type, uint64_t param) + { + /* no SVM activated; fast case */ +- if (likely(!(s->flags & HF_SVMI_MASK))) ++ if (likely(!(s->flags & HF_GUEST_MASK))) + return; + gen_update_cc_op(s); + gen_jmp_im(pc_start - s->cs_base); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-i386-sev-Do-not-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-i386-work-around-KVM_GET_MSRS-bug-for-seconda.patch b/SOURCES/kvm-target-i386-work-around-KVM_GET_MSRS-bug-for-seconda.patch new file mode 100644 index 0000000..94e6eb6 --- /dev/null +++ b/SOURCES/kvm-target-i386-work-around-KVM_GET_MSRS-bug-for-seconda.patch @@ -0,0 +1,60 @@ +From 92fad7ff756d40b231399a1eeedb7caca9ab321e Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Fri, 22 Nov 2019 11:53:45 +0000 +Subject: [PATCH 12/16] target/i386: work around KVM_GET_MSRS bug for secondary + execution controls + +RH-Author: Paolo Bonzini +Message-id: <20191122115348.25000-13-pbonzini@redhat.com> +Patchwork-id: 92609 +O-Subject: [RHEL8.2/rhel qemu-kvm PATCH 12/15] target/i386: work around KVM_GET_MSRS bug for secondary execution controls +Bugzilla: 1689270 +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Eduardo Habkost +RH-Acked-by: Maxim Levitsky + +Some secondary controls are automatically enabled/disabled based on the CPUID +values that are set for the guest. However, they are still available at a +global level and therefore should be present when KVM_GET_MSRS is sent to +/dev/kvm. + +Unfortunately KVM forgot to include those, so fix that. + +Signed-off-by: Paolo Bonzini +(cherry picked from commit 048c95163b472ed737a2f0dca4f4e23a82ac2f8a) +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/kvm.c | 17 +++++++++++++++++ + 1 file changed, 17 insertions(+) + +diff --git a/target/i386/kvm.c b/target/i386/kvm.c +index 512d7d5..6366172 100644 +--- a/target/i386/kvm.c ++++ b/target/i386/kvm.c +@@ -460,6 +460,23 @@ uint64_t kvm_arch_get_supported_msr_feature(KVMState *s, uint32_t index) + value = msr_data.entries[0].data; + switch (index) { + case MSR_IA32_VMX_PROCBASED_CTLS2: ++ /* KVM forgot to add these bits for some time, do this ourselves. */ ++ if (kvm_arch_get_supported_cpuid(s, 0xD, 1, R_ECX) & CPUID_XSAVE_XSAVES) { ++ value |= (uint64_t)VMX_SECONDARY_EXEC_XSAVES << 32; ++ } ++ if (kvm_arch_get_supported_cpuid(s, 1, 0, R_ECX) & CPUID_EXT_RDRAND) { ++ value |= (uint64_t)VMX_SECONDARY_EXEC_RDRAND_EXITING << 32; ++ } ++ if (kvm_arch_get_supported_cpuid(s, 7, 0, R_EBX) & CPUID_7_0_EBX_INVPCID) { ++ value |= (uint64_t)VMX_SECONDARY_EXEC_ENABLE_INVPCID << 32; ++ } ++ if (kvm_arch_get_supported_cpuid(s, 7, 0, R_EBX) & CPUID_7_0_EBX_RDSEED) { ++ value |= (uint64_t)VMX_SECONDARY_EXEC_RDSEED_EXITING << 32; ++ } ++ if (kvm_arch_get_supported_cpuid(s, 0x80000001, 0, R_EDX) & CPUID_EXT2_RDTSCP) { ++ value |= (uint64_t)VMX_SECONDARY_EXEC_RDTSCP << 32; ++ } ++ /* fall through */ + case MSR_IA32_VMX_TRUE_PINBASED_CTLS: + case MSR_IA32_VMX_TRUE_PROCBASED_CTLS: + case MSR_IA32_VMX_TRUE_ENTRY_CTLS: +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-ppc-spapr-Add-SPAPR_CAP_CCF_ASSIST.patch b/SOURCES/kvm-target-ppc-spapr-Add-SPAPR_CAP_CCF_ASSIST.patch new file mode 100644 index 0000000..a87ebe8 --- /dev/null +++ b/SOURCES/kvm-target-ppc-spapr-Add-SPAPR_CAP_CCF_ASSIST.patch @@ -0,0 +1,244 @@ +From d63d52e74a9af9d7d45f5734c4a6e127c3ecc0b4 Mon Sep 17 00:00:00 2001 +From: Sam Bobroff +Date: Thu, 29 Aug 2019 05:53:36 +0100 +Subject: [PATCH 03/10] target/ppc/spapr: Add SPAPR_CAP_CCF_ASSIST + +RH-Author: Sam Bobroff +Message-id: <80714b6e8fc19054881e9c1eaf1b8a332f8e104f.1567057498.git.sbobroff@redhat.com> +Patchwork-id: 90189 +O-Subject: [RHEL8.1 qemu-kvm BZ1744415 PATCH 2/2] target/ppc/spapr: Add SPAPR_CAP_CCF_ASSIST +Bugzilla: 1744415 +RH-Acked-by: David Gibson +RH-Acked-by: Laurent Vivier +RH-Acked-by: Thomas Huth + +From: Suraj Jitindar Singh + +Introduce a new spapr_cap SPAPR_CAP_CCF_ASSIST to be used to indicate +the requirement for a hw-assisted version of the count cache flush +workaround. + +The count cache flush workaround is a software workaround which can be +used to flush the count cache on context switch. Some revisions of +hardware may have a hardware accelerated flush, in which case the +software flush can be shortened. This cap is used to set the +availability of such hardware acceleration for the count cache flush +routine. + +The availability of such hardware acceleration is indicated by the +H_CPU_CHAR_BCCTR_FLUSH_ASSIST flag being set in the characteristics +returned from the KVM_PPC_GET_CPU_CHAR ioctl. + +Signed-off-by: Suraj Jitindar Singh +Message-Id: <20190301031912.28809-2-sjitindarsingh@gmail.com> +[dwg: Small style fixes] +Signed-off-by: David Gibson +(cherry picked from commit 8ff43ee404d3e295839d1fd4e9e6571ca7a62a66) +[SB: Minor fixup for context change.] + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1744415 +Brew: https://brewweb.engineering.redhat.com/brew/taskinfo?taskID=23229146 +Signed-off-by: Sam Bobroff +Testing: QEMU -M cap-ibs=workaround,cap-ccf-assist=on, check guest dmesg +Signed-off-by: Danilo C. L. de Paula +--- + hw/ppc/spapr.c | 2 ++ + hw/ppc/spapr_caps.c | 25 +++++++++++++++++++++++++ + hw/ppc/spapr_hcall.c | 5 +++++ + include/hw/ppc/spapr.h | 5 ++++- + target/ppc/kvm.c | 16 ++++++++++++++++ + target/ppc/kvm_ppc.h | 6 ++++++ + 6 files changed, 58 insertions(+), 1 deletion(-) + +diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c +index c72aad1..1a2f0d9 100644 +--- a/hw/ppc/spapr.c ++++ b/hw/ppc/spapr.c +@@ -1828,6 +1828,7 @@ static const VMStateDescription vmstate_spapr = { + &vmstate_spapr_cap_sbbc, + &vmstate_spapr_cap_ibs, + &vmstate_spapr_cap_nested_kvm_hv, ++ &vmstate_spapr_cap_ccf_assist, + NULL + } + }; +@@ -3939,6 +3940,7 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data) + smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_BROKEN; + smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_BROKEN; + smc->default_caps.caps[SPAPR_CAP_NESTED_KVM_HV] = SPAPR_CAP_OFF; ++ smc->default_caps.caps[SPAPR_CAP_CCF_ASSIST] = SPAPR_CAP_OFF; + spapr_caps_add_properties(smc, &error_abort); + smc->has_power9_support = true; + } +diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c +index dfc8cce..5353255 100644 +--- a/hw/ppc/spapr_caps.c ++++ b/hw/ppc/spapr_caps.c +@@ -285,6 +285,21 @@ static void cap_nested_kvm_hv_apply(sPAPRMachineState *spapr, + } + } + ++static void cap_ccf_assist_apply(sPAPRMachineState *spapr, uint8_t val, ++ Error **errp) ++{ ++ uint8_t kvm_val = kvmppc_get_cap_count_cache_flush_assist(); ++ ++ if (tcg_enabled() && val) { ++ /* TODO - for now only allow broken for TCG */ ++ error_setg(errp, ++"Requested count cache flush assist capability level not supported by tcg, try cap-ccf-assist=off"); ++ } else if (kvm_enabled() && (val > kvm_val)) { ++ error_setg(errp, ++"Requested count cache flush assist capability level not supported by kvm, try cap-ccf-assist=off"); ++ } ++} ++ + sPAPRCapabilityInfo capability_table[SPAPR_CAP_NUM] = { + [SPAPR_CAP_HTM] = { + .name = "htm", +@@ -354,6 +369,15 @@ sPAPRCapabilityInfo capability_table[SPAPR_CAP_NUM] = { + .type = "bool", + .apply = cap_nested_kvm_hv_apply, + }, ++ [SPAPR_CAP_CCF_ASSIST] = { ++ .name = "ccf-assist", ++ .description = "Count Cache Flush Assist via HW Instruction", ++ .index = SPAPR_CAP_CCF_ASSIST, ++ .get = spapr_cap_get_bool, ++ .set = spapr_cap_set_bool, ++ .type = "bool", ++ .apply = cap_ccf_assist_apply, ++ }, + }; + + static sPAPRCapabilities default_caps_with_cpu(sPAPRMachineState *spapr, +@@ -470,6 +494,7 @@ SPAPR_CAP_MIG_STATE(cfpc, SPAPR_CAP_CFPC); + SPAPR_CAP_MIG_STATE(sbbc, SPAPR_CAP_SBBC); + SPAPR_CAP_MIG_STATE(ibs, SPAPR_CAP_IBS); + SPAPR_CAP_MIG_STATE(nested_kvm_hv, SPAPR_CAP_NESTED_KVM_HV); ++SPAPR_CAP_MIG_STATE(ccf_assist, SPAPR_CAP_CCF_ASSIST); + + void spapr_caps_reset(sPAPRMachineState *spapr) + { +diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c +index 01c4215..141d1f4 100644 +--- a/hw/ppc/spapr_hcall.c ++++ b/hw/ppc/spapr_hcall.c +@@ -1675,6 +1675,8 @@ static target_ulong h_get_cpu_characteristics(PowerPCCPU *cpu, + uint8_t safe_cache = spapr_get_cap(spapr, SPAPR_CAP_CFPC); + uint8_t safe_bounds_check = spapr_get_cap(spapr, SPAPR_CAP_SBBC); + uint8_t safe_indirect_branch = spapr_get_cap(spapr, SPAPR_CAP_IBS); ++ uint8_t count_cache_flush_assist = spapr_get_cap(spapr, ++ SPAPR_CAP_CCF_ASSIST); + + switch (safe_cache) { + case SPAPR_CAP_WORKAROUND: +@@ -1715,6 +1717,9 @@ static target_ulong h_get_cpu_characteristics(PowerPCCPU *cpu, + break; + case SPAPR_CAP_WORKAROUND: + behaviour |= H_CPU_BEHAV_FLUSH_COUNT_CACHE; ++ if (count_cache_flush_assist) { ++ characteristics |= H_CPU_CHAR_BCCTR_FLUSH_ASSIST; ++ } + break; + default: /* broken */ + assert(safe_indirect_branch == SPAPR_CAP_BROKEN); +diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h +index 8bb95bb..4aff3b6 100644 +--- a/include/hw/ppc/spapr.h ++++ b/include/hw/ppc/spapr.h +@@ -68,8 +68,10 @@ typedef enum { + #define SPAPR_CAP_IBS 0x05 + /* Nested KVM-HV */ + #define SPAPR_CAP_NESTED_KVM_HV 0x06 ++/* Count Cache Flush Assist HW Instruction */ ++#define SPAPR_CAP_CCF_ASSIST 0x07 + /* Num Caps */ +-#define SPAPR_CAP_NUM (SPAPR_CAP_NESTED_KVM_HV + 1) ++#define SPAPR_CAP_NUM (SPAPR_CAP_CCF_ASSIST + 1) + + /* + * Capability Values +@@ -807,6 +809,7 @@ extern const VMStateDescription vmstate_spapr_cap_cfpc; + extern const VMStateDescription vmstate_spapr_cap_sbbc; + extern const VMStateDescription vmstate_spapr_cap_ibs; + extern const VMStateDescription vmstate_spapr_cap_nested_kvm_hv; ++extern const VMStateDescription vmstate_spapr_cap_ccf_assist; + + static inline uint8_t spapr_get_cap(sPAPRMachineState *spapr, int cap) + { +diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c +index 0e94cfc..8f90ee5 100644 +--- a/target/ppc/kvm.c ++++ b/target/ppc/kvm.c +@@ -92,6 +92,7 @@ static int cap_ppc_pvr_compat; + static int cap_ppc_safe_cache; + static int cap_ppc_safe_bounds_check; + static int cap_ppc_safe_indirect_branch; ++static int cap_ppc_count_cache_flush_assist; + static int cap_ppc_nested_kvm_hv; + + static uint32_t debug_inst_opcode; +@@ -2526,6 +2527,14 @@ static int parse_cap_ppc_safe_indirect_branch(struct kvm_ppc_cpu_char c) + return 0; + } + ++static int parse_cap_ppc_count_cache_flush_assist(struct kvm_ppc_cpu_char c) ++{ ++ if (c.character & c.character_mask & H_CPU_CHAR_BCCTR_FLUSH_ASSIST) { ++ return 1; ++ } ++ return 0; ++} ++ + static void kvmppc_get_cpu_characteristics(KVMState *s) + { + struct kvm_ppc_cpu_char c; +@@ -2548,6 +2557,8 @@ static void kvmppc_get_cpu_characteristics(KVMState *s) + cap_ppc_safe_cache = parse_cap_ppc_safe_cache(c); + cap_ppc_safe_bounds_check = parse_cap_ppc_safe_bounds_check(c); + cap_ppc_safe_indirect_branch = parse_cap_ppc_safe_indirect_branch(c); ++ cap_ppc_count_cache_flush_assist = ++ parse_cap_ppc_count_cache_flush_assist(c); + } + + int kvmppc_get_cap_safe_cache(void) +@@ -2565,6 +2576,11 @@ int kvmppc_get_cap_safe_indirect_branch(void) + return cap_ppc_safe_indirect_branch; + } + ++int kvmppc_get_cap_count_cache_flush_assist(void) ++{ ++ return cap_ppc_count_cache_flush_assist; ++} ++ + bool kvmppc_has_cap_nested_kvm_hv(void) + { + return !!cap_ppc_nested_kvm_hv; +diff --git a/target/ppc/kvm_ppc.h b/target/ppc/kvm_ppc.h +index dc86eff..e440c75 100644 +--- a/target/ppc/kvm_ppc.h ++++ b/target/ppc/kvm_ppc.h +@@ -63,6 +63,7 @@ bool kvmppc_has_cap_mmu_hash_v3(void); + int kvmppc_get_cap_safe_cache(void); + int kvmppc_get_cap_safe_bounds_check(void); + int kvmppc_get_cap_safe_indirect_branch(void); ++int kvmppc_get_cap_count_cache_flush_assist(void); + bool kvmppc_has_cap_nested_kvm_hv(void); + int kvmppc_set_cap_nested_kvm_hv(int enable); + int kvmppc_enable_hwrng(void); +@@ -316,6 +317,11 @@ static inline int kvmppc_get_cap_safe_indirect_branch(void) + return 0; + } + ++static inline int kvmppc_get_cap_count_cache_flush_assist(void) ++{ ++ return 0; ++} ++ + static inline bool kvmppc_has_cap_nested_kvm_hv(void) + { + return false; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-target-ppc-spapr-Add-workaround-option-to-SPAPR_CAP_.patch b/SOURCES/kvm-target-ppc-spapr-Add-workaround-option-to-SPAPR_CAP_.patch new file mode 100644 index 0000000..456c37e --- /dev/null +++ b/SOURCES/kvm-target-ppc-spapr-Add-workaround-option-to-SPAPR_CAP_.patch @@ -0,0 +1,173 @@ +From c1bd7825b1cbe0ff34be196effc7a18992cce269 Mon Sep 17 00:00:00 2001 +From: Sam Bobroff +Date: Thu, 29 Aug 2019 05:53:35 +0100 +Subject: [PATCH 02/10] target/ppc/spapr: Add workaround option to + SPAPR_CAP_IBS + +RH-Author: Sam Bobroff +Message-id: <67946d77e95afc19f2afc5f8dfa4e89335dbb58d.1567057498.git.sbobroff@redhat.com> +Patchwork-id: 90188 +O-Subject: [RHEL8.1 qemu-kvm BZ1744415 PATCH 1/2] target/ppc/spapr: Add workaround option to SPAPR_CAP_IBS +Bugzilla: 1744415 +RH-Acked-by: David Gibson +RH-Acked-by: Laurent Vivier +RH-Acked-by: Thomas Huth + +From: Suraj Jitindar Singh + +The spapr_cap SPAPR_CAP_IBS is used to indicate the level of capability +for mitigations for indirect branch speculation. Currently the available +values are broken (default), fixed-ibs (fixed by serialising indirect +branches) and fixed-ccd (fixed by diabling the count cache). + +Introduce a new value for this capability denoted workaround, meaning that +software can work around the issue by flushing the count cache on +context switch. This option is available if the hypervisor sets the +H_CPU_BEHAV_FLUSH_COUNT_CACHE flag in the cpu behaviours returned from +the KVM_PPC_GET_CPU_CHAR ioctl. + +Signed-off-by: Suraj Jitindar Singh +Message-Id: <20190301031912.28809-1-sjitindarsingh@gmail.com> +Signed-off-by: David Gibson +(cherry picked from commit 399b2896d4948a1ec0278d896ea3a561df768d64) + +Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1744415 +Brew: https://brewweb.engineering.redhat.com/brew/taskinfo?taskID=23229146 +Signed-off-by: Sam Bobroff +Testing: Start QEMU with -M cap-ibs=workaround, check guest dmesg +Signed-off-by: Danilo C. L. de Paula +--- + hw/ppc/spapr_caps.c | 21 ++++++++++----------- + hw/ppc/spapr_hcall.c | 5 +++++ + include/hw/ppc/spapr.h | 7 +++++++ + target/ppc/kvm.c | 8 +++++++- + 4 files changed, 29 insertions(+), 12 deletions(-) + +diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c +index 86a7947..dfc8cce 100644 +--- a/hw/ppc/spapr_caps.c ++++ b/hw/ppc/spapr_caps.c +@@ -236,11 +236,13 @@ static void cap_safe_bounds_check_apply(sPAPRMachineState *spapr, uint8_t val, + } + + sPAPRCapPossible cap_ibs_possible = { +- .num = 4, ++ .num = 5, + /* Note workaround only maintained for compatibility */ +- .vals = {"broken", "workaround", "fixed-ibs", "fixed-ccd"}, +- .help = "broken - no protection, fixed-ibs - indirect branch serialisation," +- " fixed-ccd - cache count disabled", ++ .vals = {"broken", "workaround", "fixed-ibs", "fixed-ccd", "fixed-na"}, ++ .help = "broken - no protection, workaround - count cache flush" ++ ", fixed-ibs - indirect branch serialisation," ++ " fixed-ccd - cache count disabled," ++ " fixed-na - fixed in hardware (no longer applicable)", + }; + + static void cap_safe_indirect_branch_apply(sPAPRMachineState *spapr, +@@ -248,15 +250,11 @@ static void cap_safe_indirect_branch_apply(sPAPRMachineState *spapr, + { + uint8_t kvm_val = kvmppc_get_cap_safe_indirect_branch(); + +- if (val == SPAPR_CAP_WORKAROUND) { /* Can only be Broken or Fixed */ +- error_setg(errp, +-"Requested safe indirect branch capability level \"workaround\" not valid, try cap-ibs=%s", +- cap_ibs_possible.vals[kvm_val]); +- } else if (tcg_enabled() && val) { ++ if (tcg_enabled() && val) { + /* TODO - for now only allow broken for TCG */ + error_setg(errp, + "Requested safe indirect branch capability level not supported by tcg, try a different value for cap-ibs"); +- } else if (kvm_enabled() && val && (val != kvm_val)) { ++ } else if (kvm_enabled() && (val > kvm_val)) { + error_setg(errp, + "Requested safe indirect branch capability level not supported by kvm, try cap-ibs=%s", + cap_ibs_possible.vals[kvm_val]); +@@ -338,7 +336,8 @@ sPAPRCapabilityInfo capability_table[SPAPR_CAP_NUM] = { + [SPAPR_CAP_IBS] = { + .name = "ibs", + .description = +- "Indirect Branch Speculation (broken, fixed-ibs, fixed-ccd)", ++ "Indirect Branch Speculation (broken, workaround, fixed-ibs," ++ "fixed-ccd, fixed-na)", + .index = SPAPR_CAP_IBS, + .get = spapr_cap_get_string, + .set = spapr_cap_set_string, +diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c +index 16bccdd..01c4215 100644 +--- a/hw/ppc/spapr_hcall.c ++++ b/hw/ppc/spapr_hcall.c +@@ -1705,12 +1705,17 @@ static target_ulong h_get_cpu_characteristics(PowerPCCPU *cpu, + } + + switch (safe_indirect_branch) { ++ case SPAPR_CAP_FIXED_NA: ++ break; + case SPAPR_CAP_FIXED_CCD: + characteristics |= H_CPU_CHAR_CACHE_COUNT_DIS; + break; + case SPAPR_CAP_FIXED_IBS: + characteristics |= H_CPU_CHAR_BCCTRL_SERIALISED; + break; ++ case SPAPR_CAP_WORKAROUND: ++ behaviour |= H_CPU_BEHAV_FLUSH_COUNT_CACHE; ++ break; + default: /* broken */ + assert(safe_indirect_branch == SPAPR_CAP_BROKEN); + break; +diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h +index 72cfa49..8bb95bb 100644 +--- a/include/hw/ppc/spapr.h ++++ b/include/hw/ppc/spapr.h +@@ -77,12 +77,17 @@ typedef enum { + /* Bool Caps */ + #define SPAPR_CAP_OFF 0x00 + #define SPAPR_CAP_ON 0x01 ++ + /* Custom Caps */ ++ ++/* Generic */ + #define SPAPR_CAP_BROKEN 0x00 + #define SPAPR_CAP_WORKAROUND 0x01 + #define SPAPR_CAP_FIXED 0x02 ++/* SPAPR_CAP_IBS (cap-ibs) */ + #define SPAPR_CAP_FIXED_IBS 0x02 + #define SPAPR_CAP_FIXED_CCD 0x03 ++#define SPAPR_CAP_FIXED_NA 0x10 /* Lets leave a bit of a gap... */ + + typedef struct sPAPRCapabilities sPAPRCapabilities; + struct sPAPRCapabilities { +@@ -322,9 +327,11 @@ struct sPAPRMachineState { + #define H_CPU_CHAR_HON_BRANCH_HINTS PPC_BIT(5) + #define H_CPU_CHAR_THR_RECONF_TRIG PPC_BIT(6) + #define H_CPU_CHAR_CACHE_COUNT_DIS PPC_BIT(7) ++#define H_CPU_CHAR_BCCTR_FLUSH_ASSIST PPC_BIT(9) + #define H_CPU_BEHAV_FAVOUR_SECURITY PPC_BIT(0) + #define H_CPU_BEHAV_L1D_FLUSH_PR PPC_BIT(1) + #define H_CPU_BEHAV_BNDS_CHK_SPEC_BAR PPC_BIT(2) ++#define H_CPU_BEHAV_FLUSH_COUNT_CACHE PPC_BIT(5) + + /* Each control block has to be on a 4K boundary */ + #define H_CB_ALIGNMENT 4096 +diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c +index b9858fa..0e94cfc 100644 +--- a/target/ppc/kvm.c ++++ b/target/ppc/kvm.c +@@ -2511,7 +2511,13 @@ static int parse_cap_ppc_safe_bounds_check(struct kvm_ppc_cpu_char c) + + static int parse_cap_ppc_safe_indirect_branch(struct kvm_ppc_cpu_char c) + { +- if (c.character & c.character_mask & H_CPU_CHAR_CACHE_COUNT_DIS) { ++ if ((~c.behaviour & c.behaviour_mask & H_CPU_BEHAV_FLUSH_COUNT_CACHE) && ++ (~c.character & c.character_mask & H_CPU_CHAR_CACHE_COUNT_DIS) && ++ (~c.character & c.character_mask & H_CPU_CHAR_BCCTRL_SERIALISED)) { ++ return SPAPR_CAP_FIXED_NA; ++ } else if (c.behaviour & c.behaviour_mask & H_CPU_BEHAV_FLUSH_COUNT_CACHE) { ++ return SPAPR_CAP_WORKAROUND; ++ } else if (c.character & c.character_mask & H_CPU_CHAR_CACHE_COUNT_DIS) { + return SPAPR_CAP_FIXED_CCD; + } else if (c.character & c.character_mask & H_CPU_CHAR_BCCTRL_SERIALISED) { + return SPAPR_CAP_FIXED_IBS; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-tcp_emu-Fix-oob-access.patch b/SOURCES/kvm-tcp_emu-Fix-oob-access.patch new file mode 100644 index 0000000..2c947c0 --- /dev/null +++ b/SOURCES/kvm-tcp_emu-Fix-oob-access.patch @@ -0,0 +1,60 @@ +From a0b2e40bae795bfcf58492e0081665a29a2cc9e2 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Fri, 17 Jan 2020 11:49:40 +0100 +Subject: [PATCH 5/7] tcp_emu: Fix oob access +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Philippe Mathieu-Daudé +Message-id: <20200117114942.12236-2-philmd@redhat.com> +Patchwork-id: 93393 +O-Subject: [RHEL-7.7.z qemu-kvm-rhev + RHEL-7.8 qemu-kvm-rhev + RHEL-7.9 qemu-kvm-rhev + RHEL-8.1.0 qemu-kvm + RHEL-8.2.0 qemu-kvm + RHEL-7.7.z qemu-kvm-ma + RHEL-7.8 qemu-kvm-ma + RHEL-7.9 qemu-kvm-ma PATCH 1/3] tcp_emu: Fix oob access +Bugzilla: 1791566 +RH-Acked-by: Stefano Garzarella +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Thomas Huth + +From: Samuel Thibault + +The main loop only checks for one available byte, while we sometimes +need two bytes. + +(cherry picked from libslirp commit 2655fffed7a9e765bcb4701dd876e9dab975f289) +[PMD: backported with style conflicts, + CHANGELOG.md absent in downstream] +Signed-off-by: Philippe Mathieu-Daudé + +Signed-off-by: Miroslav Rezanina +--- + slirp/tcp_subr.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/slirp/tcp_subr.c b/slirp/tcp_subr.c +index 0152f72..decfd9b 100644 +--- a/slirp/tcp_subr.c ++++ b/slirp/tcp_subr.c +@@ -892,6 +892,9 @@ tcp_emu(struct socket *so, struct mbuf *m) + break; + + case 5: ++ if (bptr == m->m_data + m->m_len - 1) ++ return 1; /* We need two bytes */ ++ + /* + * The difference between versions 1.0 and + * 2.0 is here. For future versions of +@@ -907,6 +910,10 @@ tcp_emu(struct socket *so, struct mbuf *m) + /* This is the field containing the port + * number that RA-player is listening to. + */ ++ ++ if (bptr == m->m_data + m->m_len - 1) ++ return 1; /* We need two bytes */ ++ + lport = (((u_char*)bptr)[0] << 8) + + ((u_char *)bptr)[1]; + if (lport < 6970) +-- +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 new file mode 100644 index 0000000..1048151 --- /dev/null +++ b/SOURCES/kvm-usb-call-reset-handler-before-updating-state.patch @@ -0,0 +1,47 @@ +From 99588fb3673a3315a66f7890b25bdca9b829925e Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Tue, 4 Jun 2019 05:12:44 +0100 +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 + +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: 1713677 +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Max Reitz + +That way the device reset handler can see what +the before-reset state of the device is. + +Signed-off-by: Gerd Hoffmann +Message-id: 20190522094702.17619-2-kraxel@redhat.com +(cherry picked from commit 7ed4657396add28382081a15557c78cd480c1cf1) +Signed-off-by: Danilo C. L. de Paula +--- + hw/usb/core.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/usb/core.c b/hw/usb/core.c +index 241ae66..07b67fb 100644 +--- a/hw/usb/core.c ++++ b/hw/usb/core.c +@@ -87,10 +87,10 @@ void usb_device_reset(USBDevice *dev) + if (dev == NULL || !dev->attached) { + return; + } ++ usb_device_handle_reset(dev); + dev->remote_wakeup = 0; + dev->addr = 0; + dev->state = USB_STATE_DEFAULT; +- usb_device_handle_reset(dev); + } + + void usb_wakeup(USBEndpoint *ep, unsigned int stream) +-- +1.8.3.1 + diff --git a/SOURCES/kvm-usb-drop-unnecessary-usb_device_post_load-checks.patch b/SOURCES/kvm-usb-drop-unnecessary-usb_device_post_load-checks.patch new file mode 100644 index 0000000..60e2d2e --- /dev/null +++ b/SOURCES/kvm-usb-drop-unnecessary-usb_device_post_load-checks.patch @@ -0,0 +1,127 @@ +From 24ca1010222cadbfc3c734406b665e6a9775d9d9 Mon Sep 17 00:00:00 2001 +From: "Dr. David Alan Gilbert" +Date: Tue, 1 Oct 2019 18:49:25 +0100 +Subject: [PATCH 03/21] usb: drop unnecessary usb_device_post_load checks + +RH-Author: Dr. David Alan Gilbert +Message-id: <20191001184925.29912-2-dgilbert@redhat.com> +Patchwork-id: 90933 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH 1/1] usb: drop unnecessary usb_device_post_load checks +Bugzilla: 1757482 +RH-Acked-by: Maxim Levitsky +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Igor Mammedov + +From: Jonathan Davies + +In usb_device_post_load, certain values of dev->setup_len or +dev->setup_index can cause -EINVAL to be returned. One example is when +setup_len exceeds 4096, the hard-coded value of sizeof(dev->data_buf). +This can happen through legitimate guest activity and will cause all +subsequent attempts to migrate the guest to fail in vmstate_load_state. + +The values of these variables can be set by USB packets originating in +the guest. There are two ways in which they can be set: in +do_token_setup and in do_parameter in hw/usb/core.c. + +It is easy to craft a USB packet in a guest that causes do_token_setup +to set setup_len to a value larger than 4096. When this has been done +once, all subsequent attempts to migrate the VM will fail in +usb_device_post_load until the VM is next power-cycled or a +smaller-sized USB packet is sent to the device. + +Sample code for achieving this in a VM started with "-device usb-tablet" +running Linux with CONFIG_HIDRAW=y and HID_MAX_BUFFER_SIZE > 4096: + + #include + #include + #include + #include + + int main() { + char buf[4097]; + int fd = open("/dev/hidraw0", O_RDWR|O_NONBLOCK); + + buf[0] = 0x1; + write(fd, buf, 4097); + + return 0; + } + +When this code is run in the VM, qemu will output: + + usb_generic_handle_packet: ctrl buffer too small (4097 > 4096) + +A subsequent attempt to migrate the VM will fail and output the +following on the destination host: + + qemu-kvm: error while loading state for instance 0x0 of device '0000:00:06.7/1/usb-ptr' + qemu-kvm: load of migration failed: Invalid argument + +The idea behind checking the values of setup_len and setup_index before +they are used is correct, but doing it in usb_device_post_load feels +arbitrary, and will cause unnecessary migration failures. Indeed, none +of the commit messages for c60174e8, 9f8e9895 and 719ffe1f justify why +post_load is the right place to do these checks. They correctly point +out that the important thing to protect is the usb_packet_copy. + +Instead, the right place to do the checks is in do_token_setup and +do_parameter. Indeed, there are already some checks here. We can examine +each of the disjuncts currently tested in usb_device_post_load to see +whether any need adding to do_token_setup or do_parameter to improve +safety there: + + * dev->setup_index < 0 + - This test is not needed because setup_index is explicitly set to +0 in do_token_setup and do_parameter. + + * dev->setup_len < 0 + - In both do_token_setup and do_parameter, the value of setup_len +is computed by (s->setup_buf[7] << 8) | s->setup_buf[6]. Since +s->setup_buf is a byte array and setup_len is an int32_t, it's +impossible for this arithmetic to set setup_len's top bit, so it can +never be negative. + + * dev->setup_index > dev->setup_len + - Since setup_index is 0, this is equivalent to the previous test, +so is redundant. + + * dev->setup_len > sizeof(dev->data_buf) + - This condition is already explicitly checked in both +do_token_setup and do_parameter. + +Hence there is no need to bolster the existing checks in do_token_setup +or do_parameter, and we can safely remove these checks from +usb_device_post_load without reducing safety but allowing migrations to +proceed regardless of what USB packets have been generated by the guest. + +Signed-off-by: Jonathan Davies +Message-Id: <20190107175117.23769-1-jonathan.davies@nutanix.com> +Signed-off-by: Gerd Hoffmann +Signed-off-by: Dr. David Alan Gilbert +(cherry picked from commit f30815390adb1ec153327c3832ab378e8bce9808) +Signed-off-by: Danilo C. L. de Paula +--- + hw/usb/bus.c | 6 ------ + 1 file changed, 6 deletions(-) + +diff --git a/hw/usb/bus.c b/hw/usb/bus.c +index 11f7720..5499810 100644 +--- a/hw/usb/bus.c ++++ b/hw/usb/bus.c +@@ -59,12 +59,6 @@ static int usb_device_post_load(void *opaque, int version_id) + } else { + dev->attached = true; + } +- if (dev->setup_index < 0 || +- dev->setup_len < 0 || +- dev->setup_index > dev->setup_len || +- dev->setup_len > sizeof(dev->data_buf)) { +- return -EINVAL; +- } + return 0; + } + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-usb-host-avoid-libusb_set_configuration-calls.patch b/SOURCES/kvm-usb-host-avoid-libusb_set_configuration-calls.patch new file mode 100644 index 0000000..21a84d3 --- /dev/null +++ b/SOURCES/kvm-usb-host-avoid-libusb_set_configuration-calls.patch @@ -0,0 +1,68 @@ +From c7150963b7db0123299f2430eea956c6a83f69d4 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Tue, 4 Jun 2019 05:12:46 +0100 +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 + +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: 1713677 +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Max Reitz + +Seems some devices become confused when we call +libusb_set_configuration(). So before calling the function check +whenever the device has multiple configurations in the first place, and +in case it hasn't (which is the case for the majority of devices) simply +skip the call as it will have no effect anyway. + +Signed-off-by: Gerd Hoffmann +Message-id: 20190522094702.17619-4-kraxel@redhat.com +(cherry picked from commit bfe44898848614cfcb3a269bc965afbe1f0f331c) +Signed-off-by: Danilo C. L. de Paula +--- + hw/usb/host-libusb.c | 18 ++++++++++-------- + 1 file changed, 10 insertions(+), 8 deletions(-) + +diff --git a/hw/usb/host-libusb.c b/hw/usb/host-libusb.c +index dd3ed02..587ff70 100644 +--- a/hw/usb/host-libusb.c ++++ b/hw/usb/host-libusb.c +@@ -1220,19 +1220,21 @@ static void usb_host_set_address(USBHostDevice *s, int addr) + + static void usb_host_set_config(USBHostDevice *s, int config, USBPacket *p) + { +- int rc; ++ int rc = 0; + + trace_usb_host_set_config(s->bus_num, s->addr, config); + + usb_host_release_interfaces(s); +- rc = libusb_set_configuration(s->dh, config); +- if (rc != 0) { +- usb_host_libusb_error("libusb_set_configuration", rc); +- p->status = USB_RET_STALL; +- if (rc == LIBUSB_ERROR_NO_DEVICE) { +- usb_host_nodev(s); ++ if (s->ddesc.bNumConfigurations != 1) { ++ rc = libusb_set_configuration(s->dh, config); ++ if (rc != 0) { ++ usb_host_libusb_error("libusb_set_configuration", rc); ++ p->status = USB_RET_STALL; ++ if (rc == LIBUSB_ERROR_NO_DEVICE) { ++ usb_host_nodev(s); ++ } ++ return; + } +- return; + } + p->status = usb_host_claim_interfaces(s, config); + if (p->status != USB_RET_SUCCESS) { +-- +1.8.3.1 + diff --git a/SOURCES/kvm-usb-host-skip-reset-for-untouched-devices.patch b/SOURCES/kvm-usb-host-skip-reset-for-untouched-devices.patch new file mode 100644 index 0000000..b0646c8 --- /dev/null +++ b/SOURCES/kvm-usb-host-skip-reset-for-untouched-devices.patch @@ -0,0 +1,46 @@ +From 874e4b3556ad42ff5b93b44305186be68fefce99 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Tue, 4 Jun 2019 05:12:45 +0100 +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 + +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: 1713677 +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Max Reitz + +If the guest didn't talk to the device yet, skip the reset. +Without this usb-host devices get resetted a number of times +at boot time for no good reason. + +Signed-off-by: Gerd Hoffmann +Message-id: 20190522094702.17619-3-kraxel@redhat.com +(cherry picked from commit 65f14ab98da1da920f98ee8734dc1588b01d6b2b) +Signed-off-by: Danilo C. L. de Paula +--- + hw/usb/host-libusb.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/hw/usb/host-libusb.c b/hw/usb/host-libusb.c +index d82a10a..dd3ed02 100644 +--- a/hw/usb/host-libusb.c ++++ b/hw/usb/host-libusb.c +@@ -1454,6 +1454,9 @@ static void usb_host_handle_reset(USBDevice *udev) + if (!s->allow_guest_reset) { + return; + } ++ if (udev->addr == 0) { ++ return; ++ } + + trace_usb_host_reset(s->bus_num, s->addr); + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-usb-hub-clear-suspend-on-detach.patch b/SOURCES/kvm-usb-hub-clear-suspend-on-detach.patch new file mode 100644 index 0000000..52f82f5 --- /dev/null +++ b/SOURCES/kvm-usb-hub-clear-suspend-on-detach.patch @@ -0,0 +1,43 @@ +From 24300291c98529f7d5a00ebdf6fdea68f8af97f5 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Wed, 14 Aug 2019 09:47:34 +0100 +Subject: [PATCH 2/3] usb-hub: clear suspend on detach +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Gerd Hoffmann +Message-id: <20190814094734.18110-2-kraxel@redhat.com> +Patchwork-id: 89977 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 1/1] usb-hub: clear suspend on detach +Bugzilla: 1619661 +RH-Acked-by: John Snow +RH-Acked-by: Markus Armbruster +RH-Acked-by: Philippe Mathieu-Daudé + +Signed-off-by: Gerd Hoffmann +Message-id: 20180912114012.6034-1-kraxel@redhat.com +(cherry picked from commit 3e9191acb797e4298adb853bf6c75cd31af47ef9) +Signed-off-by: Danilo C. L. de Paula +--- + hw/usb/dev-hub.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/hw/usb/dev-hub.c b/hw/usb/dev-hub.c +index 752e30c..2452e88 100644 +--- a/hw/usb/dev-hub.c ++++ b/hw/usb/dev-hub.c +@@ -191,6 +191,10 @@ static void usb_hub_detach(USBPort *port1) + port->wPortStatus &= ~PORT_STAT_ENABLE; + port->wPortChange |= PORT_STAT_C_ENABLE; + } ++ if (port->wPortStatus & PORT_STAT_SUSPEND) { ++ port->wPortStatus &= ~PORT_STAT_SUSPEND; ++ port->wPortChange |= PORT_STAT_C_SUSPEND; ++ } + usb_wakeup(s->intr, 0); + } + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-usbredir-Prevent-recursion-in-usbredir_write.patch b/SOURCES/kvm-usbredir-Prevent-recursion-in-usbredir_write.patch new file mode 100644 index 0000000..b919808 --- /dev/null +++ b/SOURCES/kvm-usbredir-Prevent-recursion-in-usbredir_write.patch @@ -0,0 +1,106 @@ +From 155e3ab0c8a7886781755ba44849c77048815025 Mon Sep 17 00:00:00 2001 +From: "Dr. David Alan Gilbert" +Date: Wed, 15 Jan 2020 12:07:41 +0100 +Subject: [PATCH 3/7] usbredir: Prevent recursion in usbredir_write +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Dr. David Alan Gilbert +Message-id: <20200115120742.19583-2-dgilbert@redhat.com> +Patchwork-id: 93352 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH 1/2] usbredir: Prevent recursion in usbredir_write +Bugzilla: 1752320 +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Peter Xu + +From: "Dr. David Alan Gilbert" + +I've got a case where usbredir_write manages to call back into itself +via spice; this patch causes the recursion to fail (0 bytes) the write; +this seems to avoid the deadlock I was previously seeing. + +I can't say I fully understand the interaction of usbredir and spice; +but there are a few similar guards in spice and usbredir +to catch other cases especially onces also related to spice_server_char_device_wakeup + +This case seems to be triggered by repeated migration+repeated +reconnection of the viewer; but my debugging suggests the migration +finished before this hits. + +The backtrace of the hang looks like: + reds_handle_ticket + reds_handle_other_links + reds_channel_do_link + red_channel_connect + spicevmc_connect + usbredir_create_parser + usbredirparser_do_write + usbredir_write + qemu_chr_fe_write + qemu_chr_write + qemu_chr_write_buffer + spice_chr_write + spice_server_char_device_wakeup + red_char_device_wakeup + red_char_device_write_to_device + vmc_write + usbredirparser_do_write + usbredir_write + qemu_chr_fe_write + qemu_chr_write + qemu_chr_write_buffer + qemu_mutex_lock_impl + +and we fail as we land through qemu_chr_write_buffer's lock +twice. + +Bug: https://bugzilla.redhat.com/show_bug.cgi?id=1752320 + +Signed-off-by: Dr. David Alan Gilbert +Message-Id: <20191218113012.13331-1-dgilbert@redhat.com> +Signed-off-by: Gerd Hoffmann +(cherry picked from commit 394642a8d3742c885e397d5bb5ee0ec40743cdc6) +Signed-off-by: Miroslav Rezanina +--- + hw/usb/redirect.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c +index 65a9196..3dcf76e 100644 +--- a/hw/usb/redirect.c ++++ b/hw/usb/redirect.c +@@ -107,6 +107,7 @@ struct USBRedirDevice { + /* Properties */ + CharBackend cs; + bool enable_streams; ++ bool in_write; + uint8_t debug; + int32_t bootindex; + char *filter_str; +@@ -284,6 +285,13 @@ static int usbredir_write(void *priv, uint8_t *data, int count) + return 0; + } + ++ /* Recursion check */ ++ if (dev->in_write) { ++ DPRINTF("usbredir_write recursion\n"); ++ return 0; ++ } ++ dev->in_write = true; ++ + r = qemu_chr_fe_write(&dev->cs, data, count); + if (r < count) { + if (!dev->watch) { +@@ -294,6 +302,7 @@ static int usbredir_write(void *priv, uint8_t *data, int count) + r = 0; + } + } ++ dev->in_write = false; + return r; + } + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-util-mmap-alloc-Add-a-is_pmem-parameter-to-qemu_ram_.patch b/SOURCES/kvm-util-mmap-alloc-Add-a-is_pmem-parameter-to-qemu_ram_.patch new file mode 100644 index 0000000..ec01556 --- /dev/null +++ b/SOURCES/kvm-util-mmap-alloc-Add-a-is_pmem-parameter-to-qemu_ram_.patch @@ -0,0 +1,120 @@ +From 5e258b59991284cf2e6bfcac04ff2de01dc83005 Mon Sep 17 00:00:00 2001 +From: "plai@redhat.com" +Date: Tue, 20 Aug 2019 16:12:48 +0100 +Subject: [PATCH 01/11] util/mmap-alloc: Add a 'is_pmem' parameter to + qemu_ram_mmap +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: plai@redhat.com +Message-id: <1566317571-5697-2-git-send-email-plai@redhat.com> +Patchwork-id: 90084 +O-Subject: [RHEL8.2 qemu-kvm PATCH 1/4] util/mmap-alloc: Add a 'is_pmem' parameter to qemu_ram_mmap +Bugzilla: 1539282 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Pankaj Gupta +RH-Acked-by: Eduardo Habkost + +From: Zhang Yi + +besides the existing 'shared' flags, we are going to add +'is_pmem' to qemu_ram_mmap(), which indicated the memory backend +file is a persist memory. + +Signed-off-by: Haozhong Zhang +Signed-off-by: Zhang Yi +Reviewed-by: Pankaj Gupta +Message-Id: <786c46862cfeb253ee0ea2f44d62ffe76edb7fa4.1549555521.git.yi.z.zhang@linux.intel.com> +Reviewed-by: Michael S. Tsirkin +Reviewed-by: Pankaj Gupta +Signed-off-by: Eduardo Habkost +(cherry picked from commit 2ac0f1621c9be59eebc844fa10361a84fd726185) +Signed-off-by: Paul Lai +Signed-off-by: Danilo C. L. de Paula +--- + exec.c | 2 +- + include/qemu/mmap-alloc.h | 21 ++++++++++++++++++++- + util/mmap-alloc.c | 6 +++++- + util/oslib-posix.c | 2 +- + 4 files changed, 27 insertions(+), 4 deletions(-) + +diff --git a/exec.c b/exec.c +index 9028700..a79eaa3 100644 +--- a/exec.c ++++ b/exec.c +@@ -1669,7 +1669,7 @@ static void *file_ram_alloc(RAMBlock *block, + } + + area = qemu_ram_mmap(fd, memory, block->mr->align, +- block->flags & RAM_SHARED); ++ block->flags & RAM_SHARED, block->flags & RAM_PMEM); + if (area == MAP_FAILED) { + error_setg_errno(errp, errno, + "unable to map backing store for guest RAM"); +diff --git a/include/qemu/mmap-alloc.h b/include/qemu/mmap-alloc.h +index 50385e3..190688a 100644 +--- a/include/qemu/mmap-alloc.h ++++ b/include/qemu/mmap-alloc.h +@@ -7,7 +7,26 @@ size_t qemu_fd_getpagesize(int fd); + + size_t qemu_mempath_getpagesize(const char *mem_path); + +-void *qemu_ram_mmap(int fd, size_t size, size_t align, bool shared); ++/** ++ * qemu_ram_mmap: mmap the specified file or device. ++ * ++ * Parameters: ++ * @fd: the file or the device to mmap ++ * @size: the number of bytes to be mmaped ++ * @align: if not zero, specify the alignment of the starting mapping address; ++ * otherwise, the alignment in use will be determined by QEMU. ++ * @shared: map has RAM_SHARED flag. ++ * @is_pmem: map has RAM_PMEM flag. ++ * ++ * Return: ++ * On success, return a pointer to the mapped area. ++ * On failure, return MAP_FAILED. ++ */ ++void *qemu_ram_mmap(int fd, ++ size_t size, ++ size_t align, ++ bool shared, ++ bool is_pmem); + + void qemu_ram_munmap(void *ptr, size_t size); + +diff --git a/util/mmap-alloc.c b/util/mmap-alloc.c +index 2fd8cbc..55d1890 100644 +--- a/util/mmap-alloc.c ++++ b/util/mmap-alloc.c +@@ -73,7 +73,11 @@ size_t qemu_mempath_getpagesize(const char *mem_path) + return getpagesize(); + } + +-void *qemu_ram_mmap(int fd, size_t size, size_t align, bool shared) ++void *qemu_ram_mmap(int fd, ++ size_t size, ++ size_t align, ++ bool shared, ++ bool is_pmem) + { + /* + * Note: this always allocates at least one extra page of virtual address +diff --git a/util/oslib-posix.c b/util/oslib-posix.c +index 13b6f8d..c36b2bb 100644 +--- a/util/oslib-posix.c ++++ b/util/oslib-posix.c +@@ -130,7 +130,7 @@ void *qemu_memalign(size_t alignment, size_t size) + void *qemu_anon_ram_alloc(size_t size, uint64_t *alignment, bool shared) + { + size_t align = QEMU_VMALLOC_ALIGN; +- void *ptr = qemu_ram_mmap(-1, size, align, shared); ++ void *ptr = qemu_ram_mmap(-1, size, align, shared, false); + + if (ptr == MAP_FAILED) { + return NULL; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-util-mmap-alloc-support-MAP_SYNC-in-qemu_ram_mmap.patch b/SOURCES/kvm-util-mmap-alloc-support-MAP_SYNC-in-qemu_ram_mmap.patch new file mode 100644 index 0000000..dbbcec5 --- /dev/null +++ b/SOURCES/kvm-util-mmap-alloc-support-MAP_SYNC-in-qemu_ram_mmap.patch @@ -0,0 +1,176 @@ +From 4438710f7aa42f55d189d1b6adb09b1c0471495e Mon Sep 17 00:00:00 2001 +From: "plai@redhat.com" +Date: Tue, 20 Aug 2019 16:12:51 +0100 +Subject: [PATCH 04/11] util/mmap-alloc: support MAP_SYNC in qemu_ram_mmap() + +RH-Author: plai@redhat.com +Message-id: <1566317571-5697-5-git-send-email-plai@redhat.com> +Patchwork-id: 90085 +O-Subject: [RHEL8.2 qemu-kvm PATCH 4/4] util/mmap-alloc: support MAP_SYNC in qemu_ram_mmap() +Bugzilla: 1539282 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Pankaj Gupta +RH-Acked-by: Eduardo Habkost + +From: Zhang Yi + +When a file supporting DAX is used as vNVDIMM backend, mmap it with +MAP_SYNC flag in addition which can ensure file system metadata +synced in each guest writes to the backend file, without other QEMU +actions (e.g., periodic fsync() by QEMU). + +Current, We have below different possible use cases: + +1. pmem=on is set, shared=on is set, MAP_SYNC supported: + a: backend is a dax supporting file. + - MAP_SYNC will active. + b: backend is not a dax supporting file. + - mmap will trigger a warning. then MAP_SYNC flag will be ignored + +2. The rest of cases: + - we will never pass the MAP_SYNC to mmap2 + +Signed-off-by: Haozhong Zhang +Signed-off-by: Zhang Yi +[ehabkost: Rebased patch to latest code on master] +Signed-off-by: Eduardo Habkost +Signed-off-by: Wei Yang +Tested-by: Wei Yang +Message-Id: <20190422004849.26463-2-richardw.yang@linux.intel.com> +[ehabkost: squashed documentation patch] +Message-Id: <20190422004849.26463-3-richardw.yang@linux.intel.com> +[ehabkost: documentation fixup] +Reviewed-by: Michael S. Tsirkin +Reviewed-by: Pankaj Gupta +Reviewed-by: Stefan Hajnoczi +Signed-off-by: Eduardo Habkost + +(cherry picked from commit 119906afa5ca610adb87c55ab0d8e53c9104bfc3) +Signed-off-by: Paul Lai +Signed-off-by: Danilo C. L. de Paula +--- + docs/nvdimm.txt | 22 +++++++++++++++++++--- + qemu-options.hx | 5 +++++ + util/mmap-alloc.c | 41 ++++++++++++++++++++++++++++++++++++++++- + 3 files changed, 64 insertions(+), 4 deletions(-) + +diff --git a/docs/nvdimm.txt b/docs/nvdimm.txt +index 5f158a6..33ce9aa 100644 +--- a/docs/nvdimm.txt ++++ b/docs/nvdimm.txt +@@ -143,9 +143,25 @@ Guest Data Persistence + ---------------------- + + Though QEMU supports multiple types of vNVDIMM backends on Linux, +-currently the only one that can guarantee the guest write persistence +-is the device DAX on the real NVDIMM device (e.g., /dev/dax0.0), to +-which all guest access do not involve any host-side kernel cache. ++the only backend that can guarantee the guest write persistence is: ++ ++A. DAX device (e.g., /dev/dax0.0, ) or ++B. DAX file(mounted with dax option) ++ ++When using B (A file supporting direct mapping of persistent memory) ++as a backend, write persistence is guaranteed if the host kernel has ++support for the MAP_SYNC flag in the mmap system call (available ++since Linux 4.15 and on certain distro kernels) and additionally ++both 'pmem' and 'share' flags are set to 'on' on the backend. ++ ++If these conditions are not satisfied i.e. if either 'pmem' or 'share' ++are not set, if the backend file does not support DAX or if MAP_SYNC ++is not supported by the host kernel, write persistence is not ++guaranteed after a system crash. For compatibility reasons, these ++conditions are ignored if not satisfied. Currently, no way is ++provided to test for them. ++For more details, please reference mmap(2) man page: ++http://man7.org/linux/man-pages/man2/mmap.2.html. + + When using other types of backends, it's suggested to set 'unarmed' + option of '-device nvdimm' to 'on', which sets the unarmed flag of the +diff --git a/qemu-options.hx b/qemu-options.hx +index 1b6786b..1243057 100644 +--- a/qemu-options.hx ++++ b/qemu-options.hx +@@ -4057,6 +4057,11 @@ using the SNIA NVM programming model (e.g. Intel NVDIMM). + If @option{pmem} is set to 'on', QEMU will take necessary operations to + guarantee the persistence of its own writes to @option{mem-path} + (e.g. in vNVDIMM label emulation and live migration). ++Also, we will map the backend-file with MAP_SYNC flag, which ensures the ++file metadata is in sync for @option{mem-path} in case of host crash ++or a power failure. MAP_SYNC requires support from both the host kernel ++(since Linux kernel 4.15) and the filesystem of @option{mem-path} mounted ++with DAX option. + + @item -object memory-backend-ram,id=@var{id},merge=@var{on|off},dump=@var{on|off},share=@var{on|off},prealloc=@var{on|off},size=@var{size},host-nodes=@var{host-nodes},policy=@var{default|preferred|bind|interleave} + +diff --git a/util/mmap-alloc.c b/util/mmap-alloc.c +index bbd9077..4873984 100644 +--- a/util/mmap-alloc.c ++++ b/util/mmap-alloc.c +@@ -10,6 +10,13 @@ + * later. See the COPYING file in the top-level directory. + */ + ++#ifdef CONFIG_LINUX ++#include ++#else /* !CONFIG_LINUX */ ++#define MAP_SYNC 0x0 ++#define MAP_SHARED_VALIDATE 0x0 ++#endif /* CONFIG_LINUX */ ++ + #include "qemu/osdep.h" + #include "qemu/mmap-alloc.h" + #include "qemu/host-utils.h" +@@ -80,6 +87,7 @@ void *qemu_ram_mmap(int fd, + bool is_pmem) + { + int flags; ++ int map_sync_flags = 0; + int guardfd; + size_t offset; + size_t pagesize; +@@ -130,9 +138,40 @@ void *qemu_ram_mmap(int fd, + flags = MAP_FIXED; + flags |= fd == -1 ? MAP_ANONYMOUS : 0; + flags |= shared ? MAP_SHARED : MAP_PRIVATE; ++ if (shared && is_pmem) { ++ map_sync_flags = MAP_SYNC | MAP_SHARED_VALIDATE; ++ } ++ + offset = QEMU_ALIGN_UP((uintptr_t)guardptr, align) - (uintptr_t)guardptr; + +- ptr = mmap(guardptr + offset, size, PROT_READ | PROT_WRITE, flags, fd, 0); ++ ptr = mmap(guardptr + offset, size, PROT_READ | PROT_WRITE, ++ flags | map_sync_flags, fd, 0); ++ ++ if (ptr == MAP_FAILED && map_sync_flags) { ++ if (errno == ENOTSUP) { ++ char *proc_link, *file_name; ++ int len; ++ proc_link = g_strdup_printf("/proc/self/fd/%d", fd); ++ file_name = g_malloc0(PATH_MAX); ++ len = readlink(proc_link, file_name, PATH_MAX - 1); ++ if (len < 0) { ++ len = 0; ++ } ++ file_name[len] = '\0'; ++ fprintf(stderr, "Warning: requesting persistence across crashes " ++ "for backend file %s failed. Proceeding without " ++ "persistence, data might become corrupted in case of host " ++ "crash.\n", file_name); ++ g_free(proc_link); ++ g_free(file_name); ++ } ++ /* ++ * if map failed with MAP_SHARED_VALIDATE | MAP_SYNC, ++ * we will remove these flags to handle compatibility. ++ */ ++ ptr = mmap(guardptr + offset, size, PROT_READ | PROT_WRITE, ++ flags, fd, 0); ++ } + + if (ptr == MAP_FAILED) { + munmap(guardptr, total); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-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-vhost-fix-vhost_log-size-overflow-during-migration.patch b/SOURCES/kvm-vhost-fix-vhost_log-size-overflow-during-migration.patch new file mode 100644 index 0000000..b18a29e --- /dev/null +++ b/SOURCES/kvm-vhost-fix-vhost_log-size-overflow-during-migration.patch @@ -0,0 +1,81 @@ +From 8c80943cfe6e8e50f0a18cc2b4f09f9eefed47dc Mon Sep 17 00:00:00 2001 +From: "Dr. David Alan Gilbert" +Date: Tue, 26 Nov 2019 16:29:02 +0000 +Subject: [PATCH 16/16] vhost: fix vhost_log size overflow during migration + +RH-Author: Dr. David Alan Gilbert +Message-id: <20191126162902.46145-2-dgilbert@redhat.com> +Patchwork-id: 92689 +O-Subject: [RHEL-AV-8.2.0 qemu-kvm PATCH 1/1] vhost: fix vhost_log size overflow during migration +Bugzilla: 1776808 +RH-Acked-by: Peter Xu +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Michael S. Tsirkin + +From: Li Hangjing + +When a guest which doesn't support multiqueue is migrated with a multi queues +vhost-user-blk deivce, a crash will occur like: + +0 qemu_memfd_alloc (name=, size=562949953421312, seals=, fd=0x7f87171fe8b4, errp=0x7f87171fe8a8) at util/memfd.c:153 +1 0x00007f883559d7cf in vhost_log_alloc (size=70368744177664, share=true) at hw/virtio/vhost.c:186 +2 0x00007f88355a0758 in vhost_log_get (listener=0x7f8838bd7940, enable=1) at qemu-2-12/hw/virtio/vhost.c:211 +3 vhost_dev_log_resize (listener=0x7f8838bd7940, enable=1) at hw/virtio/vhost.c:263 +4 vhost_migration_log (listener=0x7f8838bd7940, enable=1) at hw/virtio/vhost.c:787 +5 0x00007f88355463d6 in memory_global_dirty_log_start () at memory.c:2503 +6 0x00007f8835550577 in ram_init_bitmaps (f=0x7f88384ce600, opaque=0x7f8836024098) at migration/ram.c:2173 +7 ram_init_all (f=0x7f88384ce600, opaque=0x7f8836024098) at migration/ram.c:2192 +8 ram_save_setup (f=0x7f88384ce600, opaque=0x7f8836024098) at migration/ram.c:2219 +9 0x00007f88357a419d in qemu_savevm_state_setup (f=0x7f88384ce600) at migration/savevm.c:1002 +10 0x00007f883579fc3e in migration_thread (opaque=0x7f8837530400) at migration/migration.c:2382 +11 0x00007f8832447893 in start_thread () from /lib64/libpthread.so.0 +12 0x00007f8832178bfd in clone () from /lib64/libc.so.6 + +This is because vhost_get_log_size() returns a overflowed vhost-log size. +In this function, it uses the uninitialized variable vqs->used_phys and +vqs->used_size to get the vhost-log size. + +Signed-off-by: Li Hangjing +Reviewed-by: Xie Yongji +Reviewed-by: Chai Wen +Message-Id: <20190603061524.24076-1-lihangjing@baidu.com> +Cc: qemu-stable@nongnu.org +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +(cherry picked from commit 240e647a14df9677b3a501f7b8b870e40aac3fd5) +Signed-off-by: Danilo C. L. de Paula +--- + hw/virtio/vhost.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c +index 1ae68ff..7bdc9c4 100644 +--- a/hw/virtio/vhost.c ++++ b/hw/virtio/vhost.c +@@ -131,6 +131,11 @@ static int vhost_sync_dirty_bitmap(struct vhost_dev *dev, + } + for (i = 0; i < dev->nvqs; ++i) { + struct vhost_virtqueue *vq = dev->vqs + i; ++ ++ if (!vq->used_phys && !vq->used_size) { ++ continue; ++ } ++ + vhost_dev_sync_region(dev, section, start_addr, end_addr, vq->used_phys, + range_get_last(vq->used_phys, vq->used_size)); + } +@@ -168,6 +173,11 @@ static uint64_t vhost_get_log_size(struct vhost_dev *dev) + } + for (i = 0; i < dev->nvqs; ++i) { + struct vhost_virtqueue *vq = dev->vqs + i; ++ ++ if (!vq->used_phys && !vq->used_size) { ++ continue; ++ } ++ + uint64_t last = vq->used_phys + vq->used_size - 1; + log_size = MAX(log_size, last / VHOST_LOG_CHUNK + 1); + } +-- +1.8.3.1 + diff --git a/SOURCES/kvm-virtio-Return-true-from-virtio_queue_empty-if-broken.patch b/SOURCES/kvm-virtio-Return-true-from-virtio_queue_empty-if-broken.patch new file mode 100644 index 0000000..675af20 --- /dev/null +++ b/SOURCES/kvm-virtio-Return-true-from-virtio_queue_empty-if-broken.patch @@ -0,0 +1,104 @@ +From 5bcbdfefff3209a194168dbe772c7e2f45d248f7 Mon Sep 17 00:00:00 2001 +From: Maxim Levitsky +Date: Sun, 22 Dec 2019 11:02:07 +0100 +Subject: [PATCH 2/7] virtio: Return true from virtio_queue_empty if broken + +RH-Author: Maxim Levitsky +Message-id: <20191222110207.21384-3-mlevitsk@redhat.com> +Patchwork-id: 93208 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH 2/2] virtio: Return true from virtio_queue_empty if broken +Bugzilla: 1769613 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Cornelia Huck +RH-Acked-by: Peter Xu + +From: Fam Zheng + +Both virtio-blk and virtio-scsi use virtio_queue_empty() as the +loop condition in VQ handlers (virtio_blk_handle_vq, +virtio_scsi_handle_cmd_vq). When a device is marked broken in +virtqueue_pop, for example if a vIOMMU address translation failed, we +want to break out of the loop. + +This fixes a hanging problem when booting a CentOS 3.10.0-862.el7.x86_64 +kernel with ATS enabled: + + $ qemu-system-x86_64 \ + ... \ + -device intel-iommu,intremap=on,caching-mode=on,eim=on,device-iotlb=on \ + -device virtio-scsi-pci,iommu_platform=on,ats=on,id=scsi0,bus=pci.4,addr=0x0 + +The dead loop happens immediately when the kernel boots and initializes +the device, where virtio_scsi_data_plane_handle_cmd will not return: + + > ... + > #13 0x00005586602b7793 in virtio_scsi_handle_cmd_vq + > #14 0x00005586602b8d66 in virtio_scsi_data_plane_handle_cmd + > #15 0x00005586602ddab7 in virtio_queue_notify_aio_vq + > #16 0x00005586602dfc9f in virtio_queue_host_notifier_aio_poll + > #17 0x00005586607885da in run_poll_handlers_once + > #18 0x000055866078880e in try_poll_mode + > #19 0x00005586607888eb in aio_poll + > #20 0x0000558660784561 in aio_wait_bh_oneshot + > #21 0x00005586602b9582 in virtio_scsi_dataplane_stop + > #22 0x00005586605a7110 in virtio_bus_stop_ioeventfd + > #23 0x00005586605a9426 in virtio_pci_stop_ioeventfd + > #24 0x00005586605ab808 in virtio_pci_common_write + > #25 0x0000558660242396 in memory_region_write_accessor + > #26 0x00005586602425ab in access_with_adjusted_size + > #27 0x0000558660245281 in memory_region_dispatch_write + > #28 0x00005586601e008e in flatview_write_continue + > #29 0x00005586601e01d8 in flatview_write + > #30 0x00005586601e04de in address_space_write + > #31 0x00005586601e052f in address_space_rw + > #32 0x00005586602607f2 in kvm_cpu_exec + > #33 0x0000558660227148 in qemu_kvm_cpu_thread_fn + > #34 0x000055866078bde7 in qemu_thread_start + > #35 0x00007f5784906594 in start_thread + > #36 0x00007f5784639e6f in clone + +With this patch, virtio_queue_empty will now return 1 as soon as the +vdev is marked as broken, after a "virtio: zero sized buffers are not +allowed" error. + +To be consistent, update virtio_queue_empty_rcu as well. + +Signed-off-by: Fam Zheng +Message-Id: <20180910145616.8598-2-famz@redhat.com> +Signed-off-by: Paolo Bonzini +(cherry picked from commit 2d1df8591022737b8ef19d681ff74eda389f5198) +Signed-off-by: Maxim Levitsky +Signed-off-by: Miroslav Rezanina +--- + hw/virtio/virtio.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c +index 1debb01..fce199e 100644 +--- a/hw/virtio/virtio.c ++++ b/hw/virtio/virtio.c +@@ -344,6 +344,10 @@ int virtio_queue_ready(VirtQueue *vq) + * Called within rcu_read_lock(). */ + static int virtio_queue_empty_rcu(VirtQueue *vq) + { ++ if (unlikely(vq->vdev->broken)) { ++ return 1; ++ } ++ + if (unlikely(!vq->vring.avail)) { + return 1; + } +@@ -359,6 +363,10 @@ int virtio_queue_empty(VirtQueue *vq) + { + bool empty; + ++ if (unlikely(vq->vdev->broken)) { ++ return 1; ++ } ++ + if (unlikely(!vq->vring.avail)) { + return 1; + } +-- +1.8.3.1 + diff --git a/SOURCES/kvm-virtio-add-ability-to-delete-vq-through-a-pointer.patch b/SOURCES/kvm-virtio-add-ability-to-delete-vq-through-a-pointer.patch new file mode 100644 index 0000000..64b13b2 --- /dev/null +++ b/SOURCES/kvm-virtio-add-ability-to-delete-vq-through-a-pointer.patch @@ -0,0 +1,74 @@ +From 0f56ff85e38a3925ba8c63af9fcf6a0708f0d10f Mon Sep 17 00:00:00 2001 +From: Julia Suvorova +Date: Tue, 4 Feb 2020 18:20:05 +0000 +Subject: [PATCH 4/6] virtio: add ability to delete vq through a pointer + +RH-Author: Julia Suvorova +Message-id: <20200204182007.183537-3-jusual@redhat.com> +Patchwork-id: 93705 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH 2/4] virtio: add ability to delete vq through a pointer +Bugzilla: 1708480 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Cornelia Huck +RH-Acked-by: Michael S. Tsirkin + +From: "Michael S. Tsirkin" + +Devices tend to maintain vq pointers, allow deleting them trough a vq pointer. + +Signed-off-by: Michael S. Tsirkin +Reviewed-by: David Hildenbrand +Reviewed-by: David Hildenbrand +(cherry picked from commit 722f8c51d8af223751dfb1d02de40043e8ba067e) +Signed-off-by: Danilo C. L. de Paula +--- + hw/virtio/virtio.c | 13 +++++++++---- + include/hw/virtio/virtio.h | 2 ++ + 2 files changed, 11 insertions(+), 4 deletions(-) + +diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c +index 6356bf3..624f6e2 100644 +--- a/hw/virtio/virtio.c ++++ b/hw/virtio/virtio.c +@@ -1601,16 +1601,21 @@ VirtQueue *virtio_add_queue(VirtIODevice *vdev, int queue_size, + return &vdev->vq[i]; + } + ++void virtio_delete_queue(VirtQueue *vq) ++{ ++ vq->vring.num = 0; ++ vq->vring.num_default = 0; ++ vq->handle_output = NULL; ++ vq->handle_aio_output = NULL; ++} ++ + void virtio_del_queue(VirtIODevice *vdev, int n) + { + if (n < 0 || n >= VIRTIO_QUEUE_MAX) { + abort(); + } + +- vdev->vq[n].vring.num = 0; +- vdev->vq[n].vring.num_default = 0; +- vdev->vq[n].handle_output = NULL; +- vdev->vq[n].handle_aio_output = NULL; ++ virtio_delete_queue(&vdev->vq[n]); + } + + static void virtio_set_isr(VirtIODevice *vdev, int value) +diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h +index 9c1fa07..90471a1 100644 +--- a/include/hw/virtio/virtio.h ++++ b/include/hw/virtio/virtio.h +@@ -163,6 +163,8 @@ VirtQueue *virtio_add_queue(VirtIODevice *vdev, int queue_size, + + void virtio_del_queue(VirtIODevice *vdev, int n); + ++void virtio_delete_queue(VirtQueue *vq); ++ + void virtqueue_push(VirtQueue *vq, const VirtQueueElement *elem, + unsigned int len); + void virtqueue_flush(VirtQueue *vq, unsigned int count); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-virtio-blk-Cancel-the-pending-BH-when-the-dataplane-.patch b/SOURCES/kvm-virtio-blk-Cancel-the-pending-BH-when-the-dataplane-.patch new file mode 100644 index 0000000..4f86110 --- /dev/null +++ b/SOURCES/kvm-virtio-blk-Cancel-the-pending-BH-when-the-dataplane-.patch @@ -0,0 +1,92 @@ +From 93a7832d5dfd83f170119e7130f3968fe37fa8e6 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= +Date: Fri, 13 Sep 2019 14:16:25 +0100 +Subject: [PATCH 08/22] virtio-blk: Cancel the pending BH when the dataplane is + reset +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Philippe Mathieu-Daudé +Message-id: <20190913141625.12521-2-philmd@redhat.com> +Patchwork-id: 90453 +O-Subject: [RHEL-7.7.z qemu-kvm-rhev + RHEL-8.1.0 qemu-kvm + RHEL-AV-8.1.0 qemu-kvm PATCH v2 1/1] virtio-blk: Cancel the pending BH when the dataplane is reset +Bugzilla: 1708459 +RH-Acked-by: John Snow +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Danilo de Paula + +When 'system_reset' is called, the main loop clear the memory +region cache before the BH has a chance to execute. Later when +the deferred function is called, some assumptions that were +made when scheduling them are no longer true when they actually +execute. + +This is what happens using a virtio-blk device (fresh RHEL7.8 install): + + $ (sleep 12.3; echo system_reset; sleep 12.3; echo system_reset; sleep 1; echo q) \ + | qemu-system-x86_64 -m 4G -smp 8 -boot menu=on \ + -device virtio-blk-pci,id=image1,drive=drive_image1 \ + -drive file=/var/lib/libvirt/images/rhel78.qcow2,if=none,id=drive_image1,format=qcow2,cache=none \ + -device virtio-net-pci,netdev=net0,id=nic0,mac=52:54:00:c4:e7:84 \ + -netdev tap,id=net0,script=/bin/true,downscript=/bin/true,vhost=on \ + -monitor stdio -serial null -nographic + (qemu) system_reset + (qemu) system_reset + (qemu) qemu-system-x86_64: hw/virtio/virtio.c:225: vring_get_region_caches: Assertion `caches != NULL' failed. + Aborted + + (gdb) bt + Thread 1 (Thread 0x7f109c17b680 (LWP 10939)): + #0 0x00005604083296d1 in vring_get_region_caches (vq=0x56040a24bdd0) at hw/virtio/virtio.c:227 + #1 0x000056040832972b in vring_avail_flags (vq=0x56040a24bdd0) at hw/virtio/virtio.c:235 + #2 0x000056040832d13d in virtio_should_notify (vdev=0x56040a240630, vq=0x56040a24bdd0) at hw/virtio/virtio.c:1648 + #3 0x000056040832d1f8 in virtio_notify_irqfd (vdev=0x56040a240630, vq=0x56040a24bdd0) at hw/virtio/virtio.c:1662 + #4 0x00005604082d213d in notify_guest_bh (opaque=0x56040a243ec0) at hw/block/dataplane/virtio-blk.c:75 + #5 0x000056040883dc35 in aio_bh_call (bh=0x56040a243f10) at util/async.c:90 + #6 0x000056040883dccd in aio_bh_poll (ctx=0x560409161980) at util/async.c:118 + #7 0x0000560408842af7 in aio_dispatch (ctx=0x560409161980) at util/aio-posix.c:460 + #8 0x000056040883e068 in aio_ctx_dispatch (source=0x560409161980, callback=0x0, user_data=0x0) at util/async.c:261 + #9 0x00007f10a8fca06d in g_main_context_dispatch () at /lib64/libglib-2.0.so.0 + #10 0x0000560408841445 in glib_pollfds_poll () at util/main-loop.c:215 + #11 0x00005604088414bf in os_host_main_loop_wait (timeout=0) at util/main-loop.c:238 + #12 0x00005604088415c4 in main_loop_wait (nonblocking=0) at util/main-loop.c:514 + #13 0x0000560408416b1e in main_loop () at vl.c:1923 + #14 0x000056040841e0e8 in main (argc=20, argv=0x7ffc2c3f9c58, envp=0x7ffc2c3f9d00) at vl.c:4578 + +Fix this by cancelling the BH when the virtio dataplane is stopped. + +[This is version of the patch was modified as discussed with Philippe on +the mailing list thread. +--Stefan] + +Reported-by: Yihuang Yu +Suggested-by: Stefan Hajnoczi +Fixes: https://bugs.launchpad.net/qemu/+bug/1839428 +Signed-off-by: Philippe Mathieu-Daudé +Message-Id: <20190816171503.24761-1-philmd@redhat.com> +Signed-off-by: Stefan Hajnoczi +(cherry picked from commit ebb6ff25cd888a52a64a9adc3692541c6d1d9a42) +Signed-off-by: Philippe Mathieu-Daudé +Signed-off-by: Danilo C. L. de Paula +--- + hw/block/dataplane/virtio-blk.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c +index 101f32c..23e4022 100644 +--- a/hw/block/dataplane/virtio-blk.c ++++ b/hw/block/dataplane/virtio-blk.c +@@ -292,6 +292,9 @@ void virtio_blk_data_plane_stop(VirtIODevice *vdev) + virtio_bus_cleanup_host_notifier(VIRTIO_BUS(qbus), i); + } + ++ qemu_bh_cancel(s->bh); ++ notify_guest_bh(s); /* final chance to notify guest */ ++ + /* Clean up guest notifier (irq) */ + k->set_guest_notifiers(qbus->parent, nvqs, false); + +-- +1.8.3.1 + diff --git a/SOURCES/kvm-virtio-blk-Increase-in_flight-for-request-restart-BH.patch b/SOURCES/kvm-virtio-blk-Increase-in_flight-for-request-restart-BH.patch new file mode 100644 index 0000000..27c6935 --- /dev/null +++ b/SOURCES/kvm-virtio-blk-Increase-in_flight-for-request-restart-BH.patch @@ -0,0 +1,62 @@ +From 2f11a1952881d9e2dcc8acb3549441dbd9ade1e3 Mon Sep 17 00:00:00 2001 +From: Kevin Wolf +Date: Wed, 14 Aug 2019 08:42:26 +0100 +Subject: [PATCH 03/10] virtio-blk: Increase in_flight for request restart BH + +RH-Author: Kevin Wolf +Message-id: <20190814084229.6458-3-kwolf@redhat.com> +Patchwork-id: 89967 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 2/5] virtio-blk: Increase in_flight for request restart BH +Bugzilla: 1716349 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Max Reitz +RH-Acked-by: Paolo Bonzini + +virtio_blk_dma_restart_bh() submits new requests, so in order to make +sure that these requests are not started inside a drained section of the +attached BlockBackend, we need to make sure that draining the +BlockBackend waits for the BH to be executed. + +This BH is still questionable because its scheduled in the main thread +instead of the configured iothread. Leave a FIXME comment for this. + +But with this fix, enabling the data plane at least waits for these +requests (in bdrv_set_aio_context()) instead of changing the AioContext +under their feet and making them run in the wrong thread, causing +crashes and failures (e.g. due to missing locking). + +Signed-off-by: Kevin Wolf +(cherry picked from commit 680f200217748e0920b79ec1d524717c2f50935b) +Signed-off-by: Kevin Wolf +Signed-off-by: Danilo C. L. de Paula +--- + hw/block/virtio-blk.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/hw/block/virtio-blk.c b/hw/block/virtio-blk.c +index b1532e4..691ade4 100644 +--- a/hw/block/virtio-blk.c ++++ b/hw/block/virtio-blk.c +@@ -678,6 +678,7 @@ static void virtio_blk_dma_restart_bh(void *opaque) + if (mrb.num_reqs) { + virtio_blk_submit_multireq(s->blk, &mrb); + } ++ blk_dec_in_flight(s->conf.conf.blk); + aio_context_release(blk_get_aio_context(s->conf.conf.blk)); + } + +@@ -691,8 +692,11 @@ static void virtio_blk_dma_restart_cb(void *opaque, int running, + } + + if (!s->bh) { ++ /* FIXME The data plane is not started yet, so these requests are ++ * processed in the main thread. */ + s->bh = aio_bh_new(blk_get_aio_context(s->conf.conf.blk), + virtio_blk_dma_restart_bh, s); ++ blk_inc_in_flight(s->conf.conf.blk); + qemu_bh_schedule(s->bh); + } + } +-- +1.8.3.1 + diff --git a/SOURCES/kvm-virtio-gpu-add-iommu-support.patch b/SOURCES/kvm-virtio-gpu-add-iommu-support.patch new file mode 100644 index 0000000..d66a172 --- /dev/null +++ b/SOURCES/kvm-virtio-gpu-add-iommu-support.patch @@ -0,0 +1,99 @@ +From c6874c974165bd783649ae9e0fb4390881c5e79c Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Thu, 4 Jul 2019 10:32:06 +0200 +Subject: [PATCH 3/4] virtio-gpu: add iommu support +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Gerd Hoffmann +Message-id: <20190704103207.29158-3-kraxel@redhat.com> +Patchwork-id: 89371 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH v2 2/3] virtio-gpu: add iommu support +Bugzilla: 1531543 +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Laszlo Ersek +RH-Acked-by: Stefan Hajnoczi + +Switch from cpu_physical_memory_map to dma_memory_map, +so iommu mappings for virtio-gpu objects work properly. + +Signed-off-by: Gerd Hoffmann +Message-Id: <20180829122101.29852-3-kraxel@redhat.com> +(cherry picked from commit 8da132a56f7ebaabc5b674b5a3a2e6fa8934be45) +Signed-off-by: Miroslav Rezanina +--- + hw/display/virtio-gpu.c | 25 ++++++++++++++----------- + 1 file changed, 14 insertions(+), 11 deletions(-) + +diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c +index cb77ece..327c2be 100644 +--- a/hw/display/virtio-gpu.c ++++ b/hw/display/virtio-gpu.c +@@ -16,6 +16,7 @@ + #include "qemu/iov.h" + #include "ui/console.h" + #include "trace.h" ++#include "sysemu/dma.h" + #include "hw/virtio/virtio.h" + #include "hw/virtio/virtio-gpu.h" + #include "hw/virtio/virtio-bus.h" +@@ -725,7 +726,8 @@ int virtio_gpu_create_mapping_iov(VirtIOGPU *g, + uint32_t l = le32_to_cpu(ents[i].length); + hwaddr len = l; + (*iov)[i].iov_len = l; +- (*iov)[i].iov_base = cpu_physical_memory_map(a, &len, 1); ++ (*iov)[i].iov_base = dma_memory_map(VIRTIO_DEVICE(g)->dma_as, ++ a, &len, DMA_DIRECTION_TO_DEVICE); + if (addr) { + (*addr)[i] = a; + } +@@ -753,8 +755,10 @@ void virtio_gpu_cleanup_mapping_iov(VirtIOGPU *g, + int i; + + for (i = 0; i < count; i++) { +- cpu_physical_memory_unmap(iov[i].iov_base, iov[i].iov_len, 1, +- iov[i].iov_len); ++ dma_memory_unmap(VIRTIO_DEVICE(g)->dma_as, ++ iov[i].iov_base, iov[i].iov_len, ++ DMA_DIRECTION_TO_DEVICE, ++ iov[i].iov_len); + } + g_free(iov); + } +@@ -1146,13 +1150,17 @@ static int virtio_gpu_load(QEMUFile *f, void *opaque, size_t size, + for (i = 0; i < res->iov_cnt; i++) { + hwaddr len = res->iov[i].iov_len; + res->iov[i].iov_base = +- cpu_physical_memory_map(res->addrs[i], &len, 1); ++ dma_memory_map(VIRTIO_DEVICE(g)->dma_as, ++ res->addrs[i], &len, DMA_DIRECTION_TO_DEVICE); + + if (!res->iov[i].iov_base || len != res->iov[i].iov_len) { + /* Clean up the half-a-mapping we just created... */ + if (res->iov[i].iov_base) { +- cpu_physical_memory_unmap(res->iov[i].iov_base, +- len, 0, 0); ++ dma_memory_unmap(VIRTIO_DEVICE(g)->dma_as, ++ res->iov[i].iov_base, ++ res->iov[i].iov_len, ++ DMA_DIRECTION_TO_DEVICE, ++ res->iov[i].iov_len); + } + /* ...and the mappings for previous loop iterations */ + res->iov_cnt = i; +@@ -1204,11 +1212,6 @@ static void virtio_gpu_device_realize(DeviceState *qdev, Error **errp) + Error *local_err = NULL; + int i; + +- if (virtio_host_has_feature(vdev, VIRTIO_F_IOMMU_PLATFORM)) { +- error_setg(errp, "virtio-gpu does not support vIOMMU yet"); +- return; +- } +- + if (g->conf.max_outputs > VIRTIO_GPU_MAX_SCANOUTS) { + error_setg(errp, "invalid max_outputs > %d", VIRTIO_GPU_MAX_SCANOUTS); + return; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-virtio-gpu-block-both-2d-and-3d-rendering.patch b/SOURCES/kvm-virtio-gpu-block-both-2d-and-3d-rendering.patch new file mode 100644 index 0000000..3a7861a --- /dev/null +++ b/SOURCES/kvm-virtio-gpu-block-both-2d-and-3d-rendering.patch @@ -0,0 +1,152 @@ +From 6bf01418f12a88167ec2a3244ca7b245a53c60ae Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= +Date: Wed, 16 Oct 2019 13:53:27 +0100 +Subject: [PATCH 1/2] virtio-gpu: block both 2d and 3d rendering +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Marc-André Lureau +Message-id: <20191016135327.23601-1-marcandre.lureau@redhat.com> +Patchwork-id: 91814 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH] virtio-gpu: block both 2d and 3d rendering +Bugzilla: 1674324 +RH-Acked-by: John Snow +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Danilo de Paula + +BZ: https://bugzilla.redhat.com/show_bug.cgi?id=1674324 +BRANCH: rhel-8.2.0 +UPSTREAM: ad341aacbf4b119a88e0f9d5a1f753d6ed0fdd86 +BREW: http://brewweb.devel.redhat.com/brew/taskinfo?taskID=24095898 + +Now that 2d commands are translated to 3d rendering, qemu must stop +sending 3d updates (from 2d) to Spice as well. + +Fixes: +https://bugzilla.redhat.com/show_bug.cgi?id=1674324 + +Cc: cfergeau@redhat.com +Signed-off-by: Marc-André Lureau +Reviewed-by: Christophe Fergeau +Tested-by: Christophe Fergeau +Message-id: 20190221114330.17968-4-marcandre.lureau@redhat.com +Signed-off-by: Gerd Hoffmann + +(cherry picked from commit ad341aacbf4b119a88e0f9d5a1f753d6ed0fdd86) +Signed-off-by: Marc-André Lureau +Signed-off-by: Danilo C. L. de Paula +--- + hw/display/virtio-gpu-3d.c | 21 --------------------- + hw/display/virtio-gpu.c | 27 ++++++++++++++++++++++----- + include/hw/virtio/virtio-gpu.h | 1 - + 3 files changed, 22 insertions(+), 27 deletions(-) + +diff --git a/hw/display/virtio-gpu-3d.c b/hw/display/virtio-gpu-3d.c +index 55d7640..9654c04 100644 +--- a/hw/display/virtio-gpu-3d.c ++++ b/hw/display/virtio-gpu-3d.c +@@ -404,11 +404,6 @@ void virtio_gpu_virgl_process_cmd(VirtIOGPU *g, + { + VIRTIO_GPU_FILL_CMD(cmd->cmd_hdr); + +- cmd->waiting = g->renderer_blocked; +- if (cmd->waiting) { +- return; +- } +- + virgl_renderer_force_ctx_0(); + switch (cmd->cmd_hdr.type) { + case VIRTIO_GPU_CMD_CTX_CREATE: +@@ -604,22 +599,6 @@ void virtio_gpu_virgl_reset(VirtIOGPU *g) + } + } + +-void virtio_gpu_gl_block(void *opaque, bool block) +-{ +- VirtIOGPU *g = opaque; +- +- if (block) { +- g->renderer_blocked++; +- } else { +- g->renderer_blocked--; +- } +- assert(g->renderer_blocked >= 0); +- +- if (g->renderer_blocked == 0) { +- virtio_gpu_process_cmdq(g); +- } +-} +- + int virtio_gpu_virgl_init(VirtIOGPU *g) + { + int ret; +diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c +index 07712d0..416ef80 100644 +--- a/hw/display/virtio-gpu.c ++++ b/hw/display/virtio-gpu.c +@@ -888,12 +888,15 @@ void virtio_gpu_process_cmdq(VirtIOGPU *g) + while (!QTAILQ_EMPTY(&g->cmdq)) { + cmd = QTAILQ_FIRST(&g->cmdq); + +- /* process command */ +- VIRGL(g, virtio_gpu_virgl_process_cmd, virtio_gpu_simple_process_cmd, +- g, cmd); ++ cmd->waiting = g->renderer_blocked; + if (cmd->waiting) { + break; + } ++ ++ /* process command */ ++ VIRGL(g, virtio_gpu_virgl_process_cmd, virtio_gpu_simple_process_cmd, ++ g, cmd); ++ + QTAILQ_REMOVE(&g->cmdq, cmd, next); + if (virtio_gpu_stats_enabled(g->conf)) { + g->stats.requests++; +@@ -1029,14 +1032,28 @@ static int virtio_gpu_ui_info(void *opaque, uint32_t idx, QemuUIInfo *info) + return 0; + } + ++static void virtio_gpu_gl_block(void *opaque, bool block) ++{ ++ VirtIOGPU *g = opaque; ++ ++ if (block) { ++ g->renderer_blocked++; ++ } else { ++ g->renderer_blocked--; ++ } ++ assert(g->renderer_blocked >= 0); ++ ++ if (g->renderer_blocked == 0) { ++ virtio_gpu_process_cmdq(g); ++ } ++} ++ + const GraphicHwOps virtio_gpu_ops = { + .invalidate = virtio_gpu_invalidate_display, + .gfx_update = virtio_gpu_update_display, + .text_update = virtio_gpu_text_update, + .ui_info = virtio_gpu_ui_info, +-#ifdef CONFIG_VIRGL + .gl_block = virtio_gpu_gl_block, +-#endif + }; + + static const VMStateDescription vmstate_virtio_gpu_scanout = { +diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h +index f95f8ce..bbeddd7 100644 +--- a/include/hw/virtio/virtio-gpu.h ++++ b/include/hw/virtio/virtio-gpu.h +@@ -171,7 +171,6 @@ void virtio_gpu_virgl_process_cmd(VirtIOGPU *g, + struct virtio_gpu_ctrl_command *cmd); + void virtio_gpu_virgl_fence_poll(VirtIOGPU *g); + void virtio_gpu_virgl_reset(VirtIOGPU *g); +-void virtio_gpu_gl_block(void *opaque, bool block); + int virtio_gpu_virgl_init(VirtIOGPU *g); + int virtio_gpu_virgl_get_num_capsets(VirtIOGPU *g); + #endif +-- +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-net-delete-also-control-queue-when-TX-RX-dele.patch b/SOURCES/kvm-virtio-net-delete-also-control-queue-when-TX-RX-dele.patch new file mode 100644 index 0000000..4483a5c --- /dev/null +++ b/SOURCES/kvm-virtio-net-delete-also-control-queue-when-TX-RX-dele.patch @@ -0,0 +1,52 @@ +From bbfbeacbeb992bd85c4aeab2566782f551097d18 Mon Sep 17 00:00:00 2001 +From: Julia Suvorova +Date: Tue, 4 Feb 2020 18:20:07 +0000 +Subject: [PATCH 6/6] virtio-net: delete also control queue when TX/RX deleted + +RH-Author: Julia Suvorova +Message-id: <20200204182007.183537-5-jusual@redhat.com> +Patchwork-id: 93702 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH 4/4] virtio-net: delete also control queue when TX/RX deleted +Bugzilla: 1708480 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Cornelia Huck +RH-Acked-by: Michael S. Tsirkin + +From: Yuri Benditovich + +https://bugzilla.redhat.com/show_bug.cgi?id=1708480 +If the control queue is not deleted together with TX/RX, it +later will be ignored in freeing cache resources and hot +unplug will not be completed. + +Cc: qemu-stable@nongnu.org +Signed-off-by: Yuri Benditovich +Message-Id: <20191226043649.14481-3-yuri.benditovich@daynix.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +(cherry picked from commit d945d9f1731244ef341f74ede93120fc9de35913) +Signed-off-by: Danilo C. L. de Paula +--- + hw/net/virtio-net.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c +index 90502fc..c489618 100644 +--- a/hw/net/virtio-net.c ++++ b/hw/net/virtio-net.c +@@ -2100,8 +2100,12 @@ static void virtio_net_device_unrealize(DeviceState *dev, Error **errp) + virtio_net_del_queue(n, i); + } + ++ /* delete also control vq */ ++ virtio_del_queue(vdev, max_queues * 2); ++ + timer_del(n->announce_timer); + timer_free(n->announce_timer); ++ + g_free(n->vqs); + qemu_del_nic(n->nic); + virtio_cleanup(vdev); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-virtio-reset-region-cache-when-on-queue-deletion.patch b/SOURCES/kvm-virtio-reset-region-cache-when-on-queue-deletion.patch new file mode 100644 index 0000000..a2d1ff2 --- /dev/null +++ b/SOURCES/kvm-virtio-reset-region-cache-when-on-queue-deletion.patch @@ -0,0 +1,46 @@ +From 83da09b513ecdc9225188de859f4d35184094522 Mon Sep 17 00:00:00 2001 +From: Julia Suvorova +Date: Tue, 4 Feb 2020 18:20:06 +0000 +Subject: [PATCH 5/6] virtio: reset region cache when on queue deletion + +RH-Author: Julia Suvorova +Message-id: <20200204182007.183537-4-jusual@redhat.com> +Patchwork-id: 93704 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH 3/4] virtio: reset region cache when on queue deletion +Bugzilla: 1708480 +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Cornelia Huck +RH-Acked-by: Michael S. Tsirkin + +From: Yuri Benditovich + +https://bugzilla.redhat.com/show_bug.cgi?id=1708480 +Fix leak of region reference that prevents complete +device deletion on hot unplug. + +Cc: qemu-stable@nongnu.org +Signed-off-by: Yuri Benditovich +Message-Id: <20191226043649.14481-2-yuri.benditovich@daynix.com> +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Michael S. Tsirkin +(cherry picked from commit 421afd2fe8dd4603216cbf36081877c391f5a2a4) +Signed-off-by: Danilo C. L. de Paula +--- + hw/virtio/virtio.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c +index 624f6e2..c105873 100644 +--- a/hw/virtio/virtio.c ++++ b/hw/virtio/virtio.c +@@ -1607,6 +1607,7 @@ void virtio_delete_queue(VirtQueue *vq) + vq->vring.num_default = 0; + vq->handle_output = NULL; + vq->handle_aio_output = NULL; ++ virtio_virtqueue_reset_region_cache(vq); + } + + void virtio_del_queue(VirtIODevice *vdev, int n) +-- +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 new file mode 100644 index 0000000..70527ee --- /dev/null +++ b/SOURCES/kvm-virtio-scsi-Forbid-devices-with-different-iothreads-.patch @@ -0,0 +1,117 @@ +From aff6f71a4e88ccec03f8451d9d9605589dddc6a2 Mon Sep 17 00:00:00 2001 +From: Markus Armbruster +Date: Thu, 6 Jun 2019 19:15:24 +0100 +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: 1673396 1673401 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Kevin Wolf + +From: Alberto Garcia + +This patch forbids attaching a disk to a SCSI device if its using a +different AioContext. Test case included. + +Signed-off-by: Alberto Garcia +Signed-off-by: Kevin Wolf +(cherry picked from commit eb97813ff5fd5bdffc8ed9f5be5a3a50eae70a2c) +Signed-off-by: Markus Armbruster +Signed-off-by: Danilo C. L. de Paula +--- + hw/scsi/virtio-scsi.c | 7 +++++++ + tests/qemu-iotests/240 | 22 ++++++++++++++++++++++ + tests/qemu-iotests/240.out | 20 ++++++++++++++++++++ + 3 files changed, 49 insertions(+) + +diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c +index 85073f6..391500b 100644 +--- a/hw/scsi/virtio-scsi.c ++++ b/hw/scsi/virtio-scsi.c +@@ -800,9 +800,16 @@ static void virtio_scsi_hotplug(HotplugHandler *hotplug_dev, DeviceState *dev, + return; + } + if (s->ctx && !s->dataplane_fenced) { ++ AioContext *ctx; + if (blk_op_is_blocked(sd->conf.blk, BLOCK_OP_TYPE_DATAPLANE, errp)) { + return; + } ++ ctx = blk_get_aio_context(sd->conf.blk); ++ if (ctx != s->ctx && ctx != qemu_get_aio_context()) { ++ error_setg(errp, "Cannot attach a blockdev that is using " ++ "a different iothread"); ++ return; ++ } + virtio_scsi_acquire(s); + blk_set_aio_context(sd->conf.blk, s->ctx); + virtio_scsi_release(s); +diff --git a/tests/qemu-iotests/240 b/tests/qemu-iotests/240 +index 5d499c9..65cc3b3 100755 +--- a/tests/qemu-iotests/240 ++++ b/tests/qemu-iotests/240 +@@ -101,6 +101,28 @@ run_qemu < +Date: Thu, 6 Jun 2019 19:15:22 +0100 +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: 1673396 1673401 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Kevin Wolf + +From: Alberto Garcia + +This fixes a crash when attaching a disk to a SCSI device using +iothreads, then detaching it and reattaching it again. Test case +included. + +Signed-off-by: Alberto Garcia +Signed-off-by: Kevin Wolf +(cherry picked from commit a6f230c8d13a7ff3a0c7f1097412f44bfd9eff0b) +[Trivial conflict in tests/qemu-iotests/group resolved] +Signed-off-by: Markus Armbruster + +Signed-off-by: Danilo C. L. de Paula +--- + hw/scsi/virtio-scsi.c | 6 ++++ + tests/qemu-iotests/240 | 89 ++++++++++++++++++++++++++++++++++++++++++++++ + tests/qemu-iotests/240.out | 18 ++++++++++ + tests/qemu-iotests/group | 1 + + 4 files changed, 114 insertions(+) + create mode 100755 tests/qemu-iotests/240 + create mode 100644 tests/qemu-iotests/240.out + +diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c +index 52a3c1d..85073f6 100644 +--- a/hw/scsi/virtio-scsi.c ++++ b/hw/scsi/virtio-scsi.c +@@ -841,6 +841,12 @@ static void virtio_scsi_hotunplug(HotplugHandler *hotplug_dev, DeviceState *dev, + virtio_scsi_release(s); + } + ++ if (s->ctx) { ++ virtio_scsi_acquire(s); ++ blk_set_aio_context(sd->conf.blk, qemu_get_aio_context()); ++ virtio_scsi_release(s); ++ } ++ + qdev_simple_device_unplug_cb(hotplug_dev, dev, errp); + } + +diff --git a/tests/qemu-iotests/240 b/tests/qemu-iotests/240 +new file mode 100755 +index 0000000..ead7ee0 +--- /dev/null ++++ b/tests/qemu-iotests/240 +@@ -0,0 +1,89 @@ ++#!/bin/bash ++# ++# Test hot plugging and unplugging with iothreads ++# ++# Copyright (C) 2019 Igalia, S.L. ++# Author: Alberto Garcia ++# ++# This program is free software; you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation; either version 2 of the License, or ++# (at your option) any later version. ++# ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++# ++# You should have received a copy of the GNU General Public License ++# along with this program. If not, see . ++# ++ ++# creator ++owner=berto@igalia.com ++ ++seq=`basename $0` ++echo "QA output created by $seq" ++ ++status=1 # failure is the default! ++ ++# get standard environment, filters and checks ++. ./common.rc ++. ./common.filter ++ ++_supported_fmt generic ++_supported_proto generic ++_supported_os Linux ++ ++do_run_qemu() ++{ ++ echo Testing: "$@" ++ $QEMU -nographic -qmp stdio -serial none "$@" ++ echo ++} ++ ++# Remove QMP events from (pretty-printed) output. Doesn't handle ++# nested dicts correctly, but we don't get any of those in this test. ++_filter_qmp_events() ++{ ++ tr '\n' '\t' | sed -e \ ++ 's/{\s*"timestamp":\s*{[^}]*},\s*"event":[^,}]*\(,\s*"data":\s*{[^}]*}\)\?\s*}\s*//g' \ ++ | tr '\t' '\n' ++} ++ ++run_qemu() ++{ ++ do_run_qemu "$@" 2>&1 | _filter_qmp | _filter_qmp_events ++} ++ ++case "$QEMU_DEFAULT_MACHINE" in ++ s390-ccw-virtio) ++ virtio_scsi=virtio-scsi-ccw ++ ;; ++ *) ++ virtio_scsi=virtio-scsi-pci ++ ;; ++esac ++ ++echo ++echo === Unplug a SCSI disk and then plug it again === ++echo ++ ++run_qemu < +Date: Mon, 22 Jul 2019 18:22:14 +0100 +Subject: [PATCH 33/39] vmstate: Add support for kernel integer types + +RH-Author: Paolo Bonzini +Message-id: <20190722182220.19374-13-pbonzini@redhat.com> +Patchwork-id: 89630 +O-Subject: [RHEL-8.1.0 PATCH qemu-kvm v3 12/18] vmstate: Add support for kernel integer types +Bugzilla: 1689269 +RH-Acked-by: Peter Xu +RH-Acked-by: Laurent Vivier +RH-Acked-by: Dr. David Alan Gilbert + +From: Liran Alon + +Reviewed-by: Nikita Leshenko +Reviewed-by: Maran Wilson +Signed-off-by: Liran Alon +Reviewed-by: Dr. David Alan Gilbert +Message-Id: <20190619162140.133674-8-liran.alon@oracle.com> +Signed-off-by: Paolo Bonzini +(cherry picked from commit 6cfd7639329062797c04ec79adb1023a8ba2fcb4) +Signed-off-by: Danilo C. L. de Paula +--- + include/migration/vmstate.h | 26 ++++++++++++++++++++++++++ + 1 file changed, 26 insertions(+) + +diff --git a/include/migration/vmstate.h b/include/migration/vmstate.h +index df463fd..380a0fd 100644 +--- a/include/migration/vmstate.h ++++ b/include/migration/vmstate.h +@@ -755,6 +755,19 @@ extern const VMStateInfo vmstate_info_qtailq; + #define VMSTATE_UINT64_V(_f, _s, _v) \ + VMSTATE_SINGLE(_f, _s, _v, vmstate_info_uint64, uint64_t) + ++#ifdef CONFIG_LINUX ++ ++#define VMSTATE_U8_V(_f, _s, _v) \ ++ VMSTATE_SINGLE(_f, _s, _v, vmstate_info_uint8, __u8) ++#define VMSTATE_U16_V(_f, _s, _v) \ ++ VMSTATE_SINGLE(_f, _s, _v, vmstate_info_uint16, __u16) ++#define VMSTATE_U32_V(_f, _s, _v) \ ++ VMSTATE_SINGLE(_f, _s, _v, vmstate_info_uint32, __u32) ++#define VMSTATE_U64_V(_f, _s, _v) \ ++ VMSTATE_SINGLE(_f, _s, _v, vmstate_info_uint64, __u64) ++ ++#endif ++ + #define VMSTATE_BOOL(_f, _s) \ + VMSTATE_BOOL_V(_f, _s, 0) + +@@ -776,6 +789,19 @@ extern const VMStateInfo vmstate_info_qtailq; + #define VMSTATE_UINT64(_f, _s) \ + VMSTATE_UINT64_V(_f, _s, 0) + ++#ifdef CONFIG_LINUX ++ ++#define VMSTATE_U8(_f, _s) \ ++ VMSTATE_U8_V(_f, _s, 0) ++#define VMSTATE_U16(_f, _s) \ ++ VMSTATE_U16_V(_f, _s, 0) ++#define VMSTATE_U32(_f, _s) \ ++ VMSTATE_U32_V(_f, _s, 0) ++#define VMSTATE_U64(_f, _s) \ ++ VMSTATE_U64_V(_f, _s, 0) ++ ++#endif ++ + #define VMSTATE_UINT8_EQUAL(_f, _s, _err_hint) \ + VMSTATE_SINGLE_FULL(_f, _s, 0, 0, \ + vmstate_info_uint8_equal, uint8_t, _err_hint) +-- +1.8.3.1 + diff --git a/SOURCES/kvm-vmxcap-correct-the-name-of-the-variables.patch b/SOURCES/kvm-vmxcap-correct-the-name-of-the-variables.patch new file mode 100644 index 0000000..074f148 --- /dev/null +++ b/SOURCES/kvm-vmxcap-correct-the-name-of-the-variables.patch @@ -0,0 +1,55 @@ +From 0d087d9d5276866b7a7c17cdb23e71b5636dc529 Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Fri, 22 Nov 2019 11:53:43 +0000 +Subject: [PATCH 10/16] vmxcap: correct the name of the variables + +RH-Author: Paolo Bonzini +Message-id: <20191122115348.25000-11-pbonzini@redhat.com> +Patchwork-id: 92607 +O-Subject: [RHEL8.2/rhel qemu-kvm PATCH 10/15] vmxcap: correct the name of the variables +Bugzilla: 1689270 +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Eduardo Habkost +RH-Acked-by: Maxim Levitsky + +The low bits are 1 if the control must be one, the high bits +are 1 if the control can be one. Correct the variable names +as they are very confusing. + +Signed-off-by: Paolo Bonzini +(cherry picked from commit 49d51b8927a9ea7267f4677a2e92f5046ce74025) +Signed-off-by: Danilo C. L. de Paula +--- + scripts/kvm/vmxcap | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +diff --git a/scripts/kvm/vmxcap b/scripts/kvm/vmxcap +index 99a8146..2db6832 100755 +--- a/scripts/kvm/vmxcap ++++ b/scripts/kvm/vmxcap +@@ -51,15 +51,15 @@ class Control(object): + return (val & 0xffffffff, val >> 32) + def show(self): + print(self.name) +- mbz, mb1 = self.read2(self.cap_msr) +- tmbz, tmb1 = 0, 0 ++ mb1, cb1 = self.read2(self.cap_msr) ++ tmb1, tcb1 = 0, 0 + if self.true_cap_msr: +- tmbz, tmb1 = self.read2(self.true_cap_msr) ++ tmb1, tcb1 = self.read2(self.true_cap_msr) + for bit in sorted(self.bits.keys()): +- zero = not (mbz & (1 << bit)) +- one = mb1 & (1 << bit) +- true_zero = not (tmbz & (1 << bit)) +- true_one = tmb1 & (1 << bit) ++ zero = not (mb1 & (1 << bit)) ++ one = cb1 & (1 << bit) ++ true_zero = not (tmb1 & (1 << bit)) ++ true_one = tcb1 & (1 << bit) + s= '?' + if (self.true_cap_msr and true_zero and true_one + and one and not zero): +-- +1.8.3.1 + diff --git a/SOURCES/kvm-vnc-detect-and-optimize-pageflips.patch b/SOURCES/kvm-vnc-detect-and-optimize-pageflips.patch new file mode 100644 index 0000000..eb67e2b --- /dev/null +++ b/SOURCES/kvm-vnc-detect-and-optimize-pageflips.patch @@ -0,0 +1,95 @@ +From 1b209dbf4eba1f7cdd456a809a2a8576e66a1464 Mon Sep 17 00:00:00 2001 +From: Gerd Hoffmann +Date: Tue, 13 Aug 2019 11:20:45 +0100 +Subject: [PATCH 01/10] vnc: detect and optimize pageflips +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Gerd Hoffmann +Message-id: <20190813112045.3887-2-kraxel@redhat.com> +Patchwork-id: 89956 +O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 1/1] vnc: detect and optimize pageflips +Bugzilla: 1727033 +RH-Acked-by: John Snow +RH-Acked-by: Stefan Hajnoczi +RH-Acked-by: Thomas Huth + +When size and format of the display surface stays the same we can just +tag the guest display as dirty and be done with it. + +There is no need need to resize the vnc server display or to touch the +vnc client dirty bits. On the next refresh cycle +vnc_refresh_server_surface() will check for actual display content +changes and update the client dirty bits as needed. + +The desktop resize and framebuffer format notifications to the vnc +client will be skipped too. + +Signed-off-by: Gerd Hoffmann +Reviewed-by: Daniel P. Berrangé +Message-id: 20190116101049.8929-1-kraxel@redhat.com +(cherry picked from commit 61e77a5f0c788495566aecb437bcf6b2cf9cda97) +Signed-off-by: Danilo C. L. de Paula +--- + ui/vnc.c | 25 ++++++++++++++++++++++--- + 1 file changed, 22 insertions(+), 3 deletions(-) + +diff --git a/ui/vnc.c b/ui/vnc.c +index 86c6762..0bd44f1 100644 +--- a/ui/vnc.c ++++ b/ui/vnc.c +@@ -743,6 +743,17 @@ static void vnc_update_server_surface(VncDisplay *vd) + width, height); + } + ++static bool vnc_check_pageflip(DisplaySurface *s1, ++ DisplaySurface *s2) ++{ ++ return (s1 != NULL && ++ s2 != NULL && ++ surface_width(s1) == surface_width(s2) && ++ surface_height(s1) == surface_height(s2) && ++ surface_format(s1) == surface_format(s2)); ++ ++} ++ + static void vnc_dpy_switch(DisplayChangeListener *dcl, + DisplaySurface *surface) + { +@@ -750,6 +761,7 @@ static void vnc_dpy_switch(DisplayChangeListener *dcl, + "Display output is not active."; + static DisplaySurface *placeholder; + VncDisplay *vd = container_of(dcl, VncDisplay, dcl); ++ bool pageflip = vnc_check_pageflip(vd->ds, surface); + VncState *vs; + + if (surface == NULL) { +@@ -762,14 +774,21 @@ static void vnc_dpy_switch(DisplayChangeListener *dcl, + vnc_abort_display_jobs(vd); + vd->ds = surface; + +- /* server surface */ +- vnc_update_server_surface(vd); +- + /* guest surface */ + qemu_pixman_image_unref(vd->guest.fb); + vd->guest.fb = pixman_image_ref(surface->image); + vd->guest.format = surface->format; + ++ if (pageflip) { ++ vnc_set_area_dirty(vd->guest.dirty, vd, 0, 0, ++ surface_width(surface), ++ surface_height(surface)); ++ return; ++ } ++ ++ /* server surface */ ++ vnc_update_server_surface(vd); ++ + QTAILQ_FOREACH(vs, &vd->clients, next) { + vnc_colordepth(vs); + vnc_desktop_resize(vs); +-- +1.8.3.1 + diff --git a/SOURCES/kvm-x86-Data-structure-changes-to-support-MSR-based-feat.patch b/SOURCES/kvm-x86-Data-structure-changes-to-support-MSR-based-feat.patch new file mode 100644 index 0000000..ac0bad3 --- /dev/null +++ b/SOURCES/kvm-x86-Data-structure-changes-to-support-MSR-based-feat.patch @@ -0,0 +1,501 @@ +From 1f97a7e017e09c60ca5b81062308cb951c5972a1 Mon Sep 17 00:00:00 2001 +From: "plai@redhat.com" +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: <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: Igor Mammedov +RH-Acked-by: Michael S. Tsirkin + +From: Robert Hoo + +Add FeatureWordType indicator in struct FeatureWordInfo. +Change feature_word_info[] accordingly. +Change existing functions that refer to feature_word_info[] accordingly. + +Signed-off-by: Robert Hoo +Message-Id: <1539578845-37944-3-git-send-email-robert.hu@linux.intel.com> +[ehabkost: fixed hvf_enabled() case] +Signed-off-by: Eduardo Habkost + +(cherry picked from commit 07585923485952bf4cb7da563c9f91fecc85d09c) +Signed-off-by: Paul Lai +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.c | 197 +++++++++++++++++++++++++++++++++++++++--------------- + 1 file changed, 142 insertions(+), 55 deletions(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +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, + /* missing: + CPUID_XSAVE_XSAVEC, CPUID_XSAVE_XSAVES */ + ++typedef enum FeatureWordType { ++ CPUID_FEATURE_WORD, ++ MSR_FEATURE_WORD, ++} FeatureWordType; ++ + typedef struct FeatureWordInfo { ++ FeatureWordType type; + /* feature flags names are taken from "Intel Processor Identification and + * the CPUID Instruction" and AMD's "CPUID Specification". + * In cases of disagreement between feature naming conventions, + * aliases may be added. + */ + const char *feat_names[32]; +- uint32_t cpuid_eax; /* Input EAX for CPUID */ +- bool cpuid_needs_ecx; /* CPUID instruction uses ECX as input */ +- uint32_t cpuid_ecx; /* Input ECX value for CPUID */ +- int cpuid_reg; /* output register (R_* constant) */ ++ union { ++ /* If type==CPUID_FEATURE_WORD */ ++ struct { ++ uint32_t eax; /* Input EAX for CPUID */ ++ bool needs_ecx; /* CPUID instruction uses ECX as input */ ++ uint32_t ecx; /* Input ECX value for CPUID */ ++ int reg; /* output register (R_* constant) */ ++ } cpuid; ++ /* If type==MSR_FEATURE_WORD */ ++ struct { ++ uint32_t index; ++ struct { /*CPUID that enumerate this MSR*/ ++ FeatureWord cpuid_class; ++ uint32_t cpuid_flag; ++ } cpuid_dep; ++ } msr; ++ }; + uint32_t tcg_features; /* Feature flags supported by TCG */ + uint32_t unmigratable_flags; /* Feature flags known to be unmigratable */ + uint32_t migratable_flags; /* Feature flags known to be migratable */ +@@ -793,6 +812,7 @@ typedef struct FeatureWordInfo { + + static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { + [FEAT_1_EDX] = { ++ .type = CPUID_FEATURE_WORD, + .feat_names = { + "fpu", "vme", "de", "pse", + "tsc", "msr", "pae", "mce", +@@ -803,10 +823,11 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { + "fxsr", "sse", "sse2", "ss", + "ht" /* Intel htt */, "tm", "ia64", "pbe", + }, +- .cpuid_eax = 1, .cpuid_reg = R_EDX, ++ .cpuid = {.eax = 1, .reg = R_EDX, }, + .tcg_features = TCG_FEATURES, + }, + [FEAT_1_ECX] = { ++ .type = CPUID_FEATURE_WORD, + .feat_names = { + "pni" /* Intel,AMD sse3 */, "pclmulqdq", "dtes64", "monitor", + "ds-cpl", "vmx", "smx", "est", +@@ -817,7 +838,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { + "tsc-deadline", "aes", "xsave", "osxsave", + "avx", "f16c", "rdrand", "hypervisor", + }, +- .cpuid_eax = 1, .cpuid_reg = R_ECX, ++ .cpuid = { .eax = 1, .reg = R_ECX, }, + .tcg_features = TCG_EXT_FEATURES, + }, + /* Feature names that are already defined on feature_name[] but +@@ -826,6 +847,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { + * to features[FEAT_8000_0001_EDX] if and only if CPU vendor is AMD. + */ + [FEAT_8000_0001_EDX] = { ++ .type = CPUID_FEATURE_WORD, + .feat_names = { + NULL /* fpu */, NULL /* vme */, NULL /* de */, NULL /* pse */, + NULL /* tsc */, NULL /* msr */, NULL /* pae */, NULL /* mce */, +@@ -836,10 +858,11 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { + NULL /* fxsr */, "fxsr-opt", "pdpe1gb", "rdtscp", + NULL, "lm", "3dnowext", "3dnow", + }, +- .cpuid_eax = 0x80000001, .cpuid_reg = R_EDX, ++ .cpuid = { .eax = 0x80000001, .reg = R_EDX, }, + .tcg_features = TCG_EXT2_FEATURES, + }, + [FEAT_8000_0001_ECX] = { ++ .type = CPUID_FEATURE_WORD, + .feat_names = { + "lahf-lm", "cmp-legacy", "svm", "extapic", + "cr8legacy", "abm", "sse4a", "misalignsse", +@@ -850,7 +873,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { + "perfctr-nb", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + }, +- .cpuid_eax = 0x80000001, .cpuid_reg = R_ECX, ++ .cpuid = { .eax = 0x80000001, .reg = R_ECX, }, + .tcg_features = TCG_EXT3_FEATURES, + /* + * TOPOEXT is always allowed but can't be enabled blindly by +@@ -860,6 +883,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { + .no_autoenable_flags = CPUID_EXT3_TOPOEXT, + }, + [FEAT_C000_0001_EDX] = { ++ .type = CPUID_FEATURE_WORD, + .feat_names = { + NULL, NULL, "xstore", "xstore-en", + NULL, NULL, "xcrypt", "xcrypt-en", +@@ -870,10 +894,11 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + }, +- .cpuid_eax = 0xC0000001, .cpuid_reg = R_EDX, ++ .cpuid = { .eax = 0xC0000001, .reg = R_EDX, }, + .tcg_features = TCG_EXT4_FEATURES, + }, + [FEAT_KVM] = { ++ .type = CPUID_FEATURE_WORD, + .feat_names = { + "kvmclock", "kvm-nopiodelay", "kvm-mmu", "kvmclock", + "kvm-asyncpf", "kvm-steal-time", "kvm-pv-eoi", "kvm-pv-unhalt", +@@ -884,10 +909,11 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { + "kvmclock-stable-bit", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + }, +- .cpuid_eax = KVM_CPUID_FEATURES, .cpuid_reg = R_EAX, ++ .cpuid = { .eax = KVM_CPUID_FEATURES, .reg = R_EAX, }, + .tcg_features = TCG_KVM_FEATURES, + }, + [FEAT_KVM_HINTS] = { ++ .type = CPUID_FEATURE_WORD, + .feat_names = { + "kvm-hint-dedicated", NULL, NULL, NULL, + NULL, NULL, NULL, NULL, +@@ -898,7 +924,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + }, +- .cpuid_eax = KVM_CPUID_FEATURES, .cpuid_reg = R_EDX, ++ .cpuid = { .eax = KVM_CPUID_FEATURES, .reg = R_EDX, }, + .tcg_features = TCG_KVM_FEATURES, + /* + * KVM hints aren't auto-enabled by -cpu host, they need to be +@@ -907,6 +933,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { + .no_autoenable_flags = ~0U, + }, + [FEAT_HYPERV_EAX] = { ++ .type = CPUID_FEATURE_WORD, + .feat_names = { + NULL /* hv_msr_vp_runtime_access */, NULL /* hv_msr_time_refcount_access */, + NULL /* hv_msr_synic_access */, NULL /* hv_msr_stimer_access */, +@@ -920,9 +947,10 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + }, +- .cpuid_eax = 0x40000003, .cpuid_reg = R_EAX, ++ .cpuid = { .eax = 0x40000003, .reg = R_EAX, }, + }, + [FEAT_HYPERV_EBX] = { ++ .type = CPUID_FEATURE_WORD, + .feat_names = { + NULL /* hv_create_partitions */, NULL /* hv_access_partition_id */, + NULL /* hv_access_memory_pool */, NULL /* hv_adjust_message_buffers */, +@@ -936,9 +964,10 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + }, +- .cpuid_eax = 0x40000003, .cpuid_reg = R_EBX, ++ .cpuid = { .eax = 0x40000003, .reg = R_EBX, }, + }, + [FEAT_HYPERV_EDX] = { ++ .type = CPUID_FEATURE_WORD, + .feat_names = { + NULL /* hv_mwait */, NULL /* hv_guest_debugging */, + NULL /* hv_perf_monitor */, NULL /* hv_cpu_dynamic_part */, +@@ -951,9 +980,10 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + }, +- .cpuid_eax = 0x40000003, .cpuid_reg = R_EDX, ++ .cpuid = { .eax = 0x40000003, .reg = R_EDX, }, + }, + [FEAT_SVM] = { ++ .type = CPUID_FEATURE_WORD, + .feat_names = { + "npt", "lbrv", "svm-lock", "nrip-save", + "tsc-scale", "vmcb-clean", "flushbyasid", "decodeassists", +@@ -964,10 +994,11 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + }, +- .cpuid_eax = 0x8000000A, .cpuid_reg = R_EDX, ++ .cpuid = { .eax = 0x8000000A, .reg = R_EDX, }, + .tcg_features = TCG_SVM_FEATURES, + }, + [FEAT_7_0_EBX] = { ++ .type = CPUID_FEATURE_WORD, + .feat_names = { + "fsgsbase", "tsc-adjust", NULL, "bmi1", + "hle", "avx2", NULL, "smep", +@@ -978,12 +1009,15 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { + "clwb", "intel-pt", "avx512pf", "avx512er", + "avx512cd", "sha-ni", "avx512bw", "avx512vl", + }, +- .cpuid_eax = 7, +- .cpuid_needs_ecx = true, .cpuid_ecx = 0, +- .cpuid_reg = R_EBX, ++ .cpuid = { ++ .eax = 7, ++ .needs_ecx = true, .ecx = 0, ++ .reg = R_EBX, ++ }, + .tcg_features = TCG_7_0_EBX_FEATURES, + }, + [FEAT_7_0_ECX] = { ++ .type = CPUID_FEATURE_WORD, + .feat_names = { + NULL, "avx512vbmi", "umip", "pku", + "ospke", NULL, "avx512vbmi2", NULL, +@@ -994,12 +1028,15 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + }, +- .cpuid_eax = 7, +- .cpuid_needs_ecx = true, .cpuid_ecx = 0, +- .cpuid_reg = R_ECX, ++ .cpuid = { ++ .eax = 7, ++ .needs_ecx = true, .ecx = 0, ++ .reg = R_ECX, ++ }, + .tcg_features = TCG_7_0_ECX_FEATURES, + }, + [FEAT_7_0_EDX] = { ++ .type = CPUID_FEATURE_WORD, + .feat_names = { + NULL, NULL, "avx512-4vnniw", "avx512-4fmaps", + NULL, NULL, NULL, NULL, +@@ -1010,13 +1047,16 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { + NULL, NULL, "spec-ctrl", "stibp", + NULL, "arch-capabilities", NULL, "ssbd", + }, +- .cpuid_eax = 7, +- .cpuid_needs_ecx = true, .cpuid_ecx = 0, +- .cpuid_reg = R_EDX, ++ .cpuid = { ++ .eax = 7, ++ .needs_ecx = true, .ecx = 0, ++ .reg = R_EDX, ++ }, + .tcg_features = TCG_7_0_EDX_FEATURES, + .unmigratable_flags = CPUID_7_0_EDX_ARCH_CAPABILITIES, + }, + [FEAT_8000_0007_EDX] = { ++ .type = CPUID_FEATURE_WORD, + .feat_names = { + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, +@@ -1027,12 +1067,12 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + }, +- .cpuid_eax = 0x80000007, +- .cpuid_reg = R_EDX, ++ .cpuid = { .eax = 0x80000007, .reg = R_EDX, }, + .tcg_features = TCG_APM_FEATURES, + .unmigratable_flags = CPUID_APM_INVTSC, + }, + [FEAT_8000_0008_EBX] = { ++ .type = CPUID_FEATURE_WORD, + .feat_names = { + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, +@@ -1043,12 +1083,12 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { + NULL, "virt-ssbd", NULL, NULL, + NULL, NULL, NULL, NULL, + }, +- .cpuid_eax = 0x80000008, +- .cpuid_reg = R_EBX, ++ .cpuid = { .eax = 0x80000008, .reg = R_EBX, }, + .tcg_features = 0, + .unmigratable_flags = 0, + }, + [FEAT_XSAVE] = { ++ .type = CPUID_FEATURE_WORD, + .feat_names = { + "xsaveopt", "xsavec", "xgetbv1", "xsaves", + NULL, NULL, NULL, NULL, +@@ -1059,12 +1099,15 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + }, +- .cpuid_eax = 0xd, +- .cpuid_needs_ecx = true, .cpuid_ecx = 1, +- .cpuid_reg = R_EAX, ++ .cpuid = { ++ .eax = 0xd, ++ .needs_ecx = true, .ecx = 1, ++ .reg = R_EAX, ++ }, + .tcg_features = TCG_XSAVE_FEATURES, + }, + [FEAT_6_EAX] = { ++ .type = CPUID_FEATURE_WORD, + .feat_names = { + NULL, NULL, "arat", NULL, + NULL, NULL, NULL, NULL, +@@ -1075,13 +1118,16 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { + NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, + }, +- .cpuid_eax = 6, .cpuid_reg = R_EAX, ++ .cpuid = { .eax = 6, .reg = R_EAX, }, + .tcg_features = TCG_6_EAX_FEATURES, + }, + [FEAT_XSAVE_COMP_LO] = { +- .cpuid_eax = 0xD, +- .cpuid_needs_ecx = true, .cpuid_ecx = 0, +- .cpuid_reg = R_EAX, ++ .type = CPUID_FEATURE_WORD, ++ .cpuid = { ++ .eax = 0xD, ++ .needs_ecx = true, .ecx = 0, ++ .reg = R_EAX, ++ }, + .tcg_features = ~0U, + .migratable_flags = XSTATE_FP_MASK | XSTATE_SSE_MASK | + XSTATE_YMM_MASK | XSTATE_BNDREGS_MASK | XSTATE_BNDCSR_MASK | +@@ -1089,9 +1135,12 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { + XSTATE_PKRU_MASK, + }, + [FEAT_XSAVE_COMP_HI] = { +- .cpuid_eax = 0xD, +- .cpuid_needs_ecx = true, .cpuid_ecx = 0, +- .cpuid_reg = R_EDX, ++ .type = CPUID_FEATURE_WORD, ++ .cpuid = { ++ .eax = 0xD, ++ .needs_ecx = true, .ecx = 0, ++ .reg = R_EDX, ++ }, + .tcg_features = ~0U, + }, + }; +@@ -2961,21 +3010,41 @@ static const TypeInfo host_x86_cpu_type_info = { + + #endif + ++static char *feature_word_description(FeatureWordInfo *f, uint32_t bit) ++{ ++ assert(f->type == CPUID_FEATURE_WORD || f->type == MSR_FEATURE_WORD); ++ ++ switch (f->type) { ++ case CPUID_FEATURE_WORD: ++ { ++ const char *reg = get_register_name_32(f->cpuid.reg); ++ assert(reg); ++ return g_strdup_printf("CPUID.%02XH:%s", ++ f->cpuid.eax, reg); ++ } ++ case MSR_FEATURE_WORD: ++ return g_strdup_printf("MSR(%02XH)", ++ f->msr.index); ++ } ++ ++ return NULL; ++} ++ + static void report_unavailable_features(FeatureWord w, uint32_t mask) + { + FeatureWordInfo *f = &feature_word_info[w]; + int i; ++ char *feat_word_str; + + for (i = 0; i < 32; ++i) { + if ((1UL << i) & mask) { +- const char *reg = get_register_name_32(f->cpuid_reg); +- assert(reg); +- warn_report("%s doesn't support requested feature: " +- "CPUID.%02XH:%s%s%s [bit %d]", ++ feat_word_str = feature_word_description(f, i); ++ warn_report("%s doesn't support requested feature: %s%s%s [bit %d]", + accel_uses_host_cpuid() ? "host" : "TCG", +- f->cpuid_eax, reg, ++ feat_word_str, + f->feat_names[i] ? "." : "", + f->feat_names[i] ? f->feat_names[i] : "", i); ++ g_free(feat_word_str); + } + } + } +@@ -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]; ++ /* ++ * We didn't have MSR features when "feature-words" was ++ * introduced. Therefore skipped other type entries. ++ */ ++ if (wi->type != CPUID_FEATURE_WORD) { ++ continue; ++ } + X86CPUFeatureWordInfo *qwi = &word_infos[w]; +- qwi->cpuid_input_eax = wi->cpuid_eax; +- qwi->has_cpuid_input_ecx = wi->cpuid_needs_ecx; +- qwi->cpuid_input_ecx = wi->cpuid_ecx; +- qwi->cpuid_register = x86_reg_info_32[wi->cpuid_reg].qapi_enum; ++ qwi->cpuid_input_eax = wi->cpuid.eax; ++ qwi->has_cpuid_input_ecx = wi->cpuid.needs_ecx; ++ qwi->cpuid_input_ecx = wi->cpuid.ecx; ++ qwi->cpuid_register = x86_reg_info_32[wi->cpuid.reg].qapi_enum; + qwi->features = array[w]; + + /* List will be in reverse order, but order shouldn't matter */ +@@ -3579,16 +3655,26 @@ static uint32_t x86_cpu_get_supported_feature_word(FeatureWord w, + bool migratable_only) + { + FeatureWordInfo *wi = &feature_word_info[w]; +- uint32_t r; ++ uint32_t r = 0; + + if (kvm_enabled()) { +- r = kvm_arch_get_supported_cpuid(kvm_state, wi->cpuid_eax, +- wi->cpuid_ecx, +- wi->cpuid_reg); ++ switch (wi->type) { ++ case CPUID_FEATURE_WORD: ++ r = kvm_arch_get_supported_cpuid(kvm_state, wi->cpuid.eax, ++ wi->cpuid.ecx, ++ wi->cpuid.reg); ++ break; ++ case MSR_FEATURE_WORD: ++ r = kvm_arch_get_supported_msr_feature(kvm_state, wi->msr.index); ++ break; ++ } + } else if (hvf_enabled()) { +- r = hvf_get_supported_cpuid(wi->cpuid_eax, +- wi->cpuid_ecx, +- wi->cpuid_reg); ++ if (wi->type != CPUID_FEATURE_WORD) { ++ return 0; ++ } ++ r = hvf_get_supported_cpuid(wi->cpuid.eax, ++ wi->cpuid.ecx, ++ wi->cpuid.reg); + } else if (tcg_enabled()) { + r = wi->tcg_features; + } else { +@@ -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]; +- uint32_t eax = fi->cpuid_eax; ++ uint32_t eax = fi->cpuid.eax; + uint32_t region = eax & 0xF0000000; + ++ assert(feature_word_info[w].type == CPUID_FEATURE_WORD); + if (!env->features[w]) { + return; + } +-- +1.8.3.1 + diff --git a/SOURCES/kvm-x86-Intel-AVX512_BF16-feature-enabling.patch b/SOURCES/kvm-x86-Intel-AVX512_BF16-feature-enabling.patch new file mode 100644 index 0000000..ec27c93 --- /dev/null +++ b/SOURCES/kvm-x86-Intel-AVX512_BF16-feature-enabling.patch @@ -0,0 +1,201 @@ +From b6b9ed9623f87d1a2b574c8010685e68ac4cd669 Mon Sep 17 00:00:00 2001 +From: "plai@redhat.com" +Date: Mon, 4 Nov 2019 17:35:19 +0000 +Subject: [PATCH 2/2] x86: Intel AVX512_BF16 feature enabling + +RH-Author: plai@redhat.com +Message-id: <1572888919-16839-1-git-send-email-plai@redhat.com> +Patchwork-id: 92026 +O-Subject: [RHEL8.2 qemu-kvm PATCH] x86: Intel AVX512_BF16 feature enabling +Bugzilla: 1642541 +RH-Acked-by: Paolo Bonzini +RH-Acked-by: Eduardo Habkost +RH-Acked-by: Igor Mammedov +RH-Acked-by: Michael S. Tsirkin + +From: Jing Liu + +BZ: https://bugzilla.redhat.com/show_bug.cgi?id=1642541 +Brew: http://brewweb.devel.redhat.com/brew/taskinfo?taskID=23221805 +Branch: rhel-8.2.0 + +--- + +Intel CooperLake cpu adds AVX512_BF16 instruction, defining as +CPUID.(EAX=7,ECX=1):EAX[bit 05]. + +The patch adds a property for setting the subleaf of CPUID leaf 7 in +case that people would like to specify it. + +The release spec link as follows, +https://software.intel.com/sites/default/files/managed/c5/15/\ +architecture-instruction-set-extensions-programming-reference.pdf + +Signed-off-by: Jing Liu +Signed-off-by: Paolo Bonzini +(cherry picked from commit 80db491da4ce8b199e0e8d1e23943b20aab82f69) +Signed-off-by: Paul Lai + +Resovled Conflicts: + target/i386/cpu.h + +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.c | 39 ++++++++++++++++++++++++++++++++++++++- + target/i386/cpu.h | 6 ++++++ + target/i386/kvm.c | 3 ++- + 3 files changed, 46 insertions(+), 2 deletions(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index 7d2afc7..0717c66 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -767,6 +767,7 @@ static void x86_cpu_vendor_words2str(char *dst, uint32_t vendor1, + #define TCG_7_0_ECX_FEATURES (CPUID_7_0_ECX_PKU | CPUID_7_0_ECX_OSPKE | \ + CPUID_7_0_ECX_LA57) + #define TCG_7_0_EDX_FEATURES 0 ++#define TCG_7_1_EAX_FEATURES 0 + #define TCG_APM_FEATURES 0 + #define TCG_6_EAX_FEATURES CPUID_6_EAX_ARAT + #define TCG_XSAVE_FEATURES (CPUID_XSAVE_XSAVEOPT | CPUID_XSAVE_XGETBV1) +@@ -1050,6 +1051,25 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { + }, + .tcg_features = TCG_7_0_EDX_FEATURES, + }, ++ [FEAT_7_1_EAX] = { ++ .type = CPUID_FEATURE_WORD, ++ .feat_names = { ++ NULL, NULL, NULL, NULL, ++ NULL, "avx512-bf16", NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ }, ++ .cpuid = { ++ .eax = 7, ++ .needs_ecx = true, .ecx = 1, ++ .reg = R_EAX, ++ }, ++ .tcg_features = TCG_7_1_EAX_FEATURES, ++ }, + [FEAT_8000_0007_EDX] = { + .type = CPUID_FEATURE_WORD, + .feat_names = { +@@ -5678,13 +5698,19 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count, + case 7: + /* Structured Extended Feature Flags Enumeration Leaf */ + if (count == 0) { +- *eax = 0; /* Maximum ECX value for sub-leaves */ ++ /* Maximum ECX value for sub-leaves */ ++ *eax = env->cpuid_level_func7; + *ebx = env->features[FEAT_7_0_EBX]; /* Feature flags */ + *ecx = env->features[FEAT_7_0_ECX]; /* Feature flags */ + if ((*ecx & CPUID_7_0_ECX_PKU) && env->cr[4] & CR4_PKE_MASK) { + *ecx |= CPUID_7_0_ECX_OSPKE; + } + *edx = env->features[FEAT_7_0_EDX]; /* Feature flags */ ++ } else if (count == 1) { ++ *eax = env->features[FEAT_7_1_EAX]; ++ *ebx = 0; ++ *ecx = 0; ++ *edx = 0; + } else { + *eax = 0; + *ebx = 0; +@@ -6289,6 +6315,11 @@ static void x86_cpu_adjust_feat_level(X86CPU *cpu, FeatureWord w) + x86_cpu_adjust_level(cpu, &env->cpuid_min_xlevel2, eax); + break; + } ++ ++ if (eax == 7) { ++ x86_cpu_adjust_level(cpu, &env->cpuid_min_level_func7, ++ fi->cpuid.ecx); ++ } + } + + /* Calculate XSAVE components based on the configured CPU feature flags */ +@@ -6423,6 +6454,7 @@ static void x86_cpu_expand_features(X86CPU *cpu, Error **errp) + x86_cpu_adjust_feat_level(cpu, FEAT_1_ECX); + x86_cpu_adjust_feat_level(cpu, FEAT_6_EAX); + x86_cpu_adjust_feat_level(cpu, FEAT_7_0_ECX); ++ x86_cpu_adjust_feat_level(cpu, FEAT_7_1_EAX); + x86_cpu_adjust_feat_level(cpu, FEAT_8000_0001_EDX); + x86_cpu_adjust_feat_level(cpu, FEAT_8000_0001_ECX); + x86_cpu_adjust_feat_level(cpu, FEAT_8000_0007_EDX); +@@ -6442,6 +6474,9 @@ static void x86_cpu_expand_features(X86CPU *cpu, Error **errp) + } + + /* Set cpuid_*level* based on cpuid_min_*level, if not explicitly set */ ++ if (env->cpuid_level_func7 == UINT32_MAX) { ++ env->cpuid_level_func7 = env->cpuid_min_level_func7; ++ } + if (env->cpuid_level == UINT32_MAX) { + env->cpuid_level = env->cpuid_min_level; + } +@@ -7150,6 +7185,8 @@ static Property x86_cpu_properties[] = { + DEFINE_PROP_BOOL("host-phys-bits", X86CPU, host_phys_bits, false), + DEFINE_PROP_UINT8("host-phys-bits-limit", X86CPU, host_phys_bits_limit, 0), + DEFINE_PROP_BOOL("fill-mtrr-mask", X86CPU, fill_mtrr_mask, true), ++ DEFINE_PROP_UINT32("level-func7", X86CPU, env.cpuid_level_func7, ++ UINT32_MAX), + DEFINE_PROP_UINT32("level", X86CPU, env.cpuid_level, UINT32_MAX), + DEFINE_PROP_UINT32("xlevel", X86CPU, env.cpuid_xlevel, UINT32_MAX), + DEFINE_PROP_UINT32("xlevel2", X86CPU, env.cpuid_xlevel2, UINT32_MAX), +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index ecbe4f0..43a5ae0 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -509,6 +509,7 @@ typedef enum FeatureWord { + FEAT_7_0_EBX, /* CPUID[EAX=7,ECX=0].EBX */ + FEAT_7_0_ECX, /* CPUID[EAX=7,ECX=0].ECX */ + FEAT_7_0_EDX, /* CPUID[EAX=7,ECX=0].EDX */ ++ FEAT_7_1_EAX, /* CPUID[EAX=7,ECX=1].EAX */ + FEAT_8000_0001_EDX, /* CPUID[8000_0001].EDX */ + FEAT_8000_0001_ECX, /* CPUID[8000_0001].ECX */ + FEAT_8000_0007_EDX, /* CPUID[8000_0007].EDX */ +@@ -732,6 +733,7 @@ typedef uint64_t FeatureWordArray[FEATURE_WORDS]; + #define CPUID_7_0_EDX_SPEC_CTRL_SSBD (1U << 31) /* Speculative Store Bypass Disable */ + + #define KVM_HINTS_DEDICATED (1U << 0) ++#define CPUID_7_1_EAX_AVX512_BF16 (1U << 5) /* AVX512 BFloat16 Instruction */ + + #define CPUID_8000_0008_EBX_WBNOINVD (1U << 9) /* Write back and + do not invalidate cache */ +@@ -1451,6 +1453,10 @@ typedef struct CPUX86State { + /* Fields after CPU_COMMON are preserved across CPU reset. */ + + /* processor features (e.g. for CPUID insn) */ ++ /* Minimum cpuid leaf 7 value */ ++ uint32_t cpuid_level_func7; ++ /* Actual cpuid leaf 7 value */ ++ uint32_t cpuid_min_level_func7; + /* Minimum level/xlevel/xlevel2, based on CPU model + features */ + uint32_t cpuid_min_level, cpuid_min_xlevel, cpuid_min_xlevel2; + /* Maximum level/xlevel/xlevel2 value for auto-assignment: */ +diff --git a/target/i386/kvm.c b/target/i386/kvm.c +index ad58bfb..92eda8d 100644 +--- a/target/i386/kvm.c ++++ b/target/i386/kvm.c +@@ -1058,6 +1058,7 @@ int kvm_arch_init_vcpu(CPUState *cs) + c = &cpuid_data.entries[cpuid_i++]; + } + break; ++ case 0x7: + case 0x14: { + uint32_t times; + +@@ -1070,7 +1071,7 @@ int kvm_arch_init_vcpu(CPUState *cs) + for (j = 1; j <= times; ++j) { + if (cpuid_i == KVM_MAX_CPUID_ENTRIES) { + fprintf(stderr, "cpuid_data is full, no space for " +- "cpuid(eax:0x14,ecx:0x%x)\n", j); ++ "cpuid(eax:0x%x,ecx:0x%x)\n", i, j); + abort(); + } + c = &cpuid_data.entries[cpuid_i++]; +-- +1.8.3.1 + diff --git a/SOURCES/kvm-x86-cpu-Add-support-for-UMONITOR-UMWAIT-TPAUSE.patch b/SOURCES/kvm-x86-cpu-Add-support-for-UMONITOR-UMWAIT-TPAUSE.patch new file mode 100644 index 0000000..b8d255a --- /dev/null +++ b/SOURCES/kvm-x86-cpu-Add-support-for-UMONITOR-UMWAIT-TPAUSE.patch @@ -0,0 +1,108 @@ +From 7e7c5dab29ed99bda0fb5d810db6f12ae4aa2608 Mon Sep 17 00:00:00 2001 +From: "plai@redhat.com" +Date: Tue, 26 Nov 2019 18:36:54 +0000 +Subject: [PATCH 10/11] x86/cpu: Add support for UMONITOR/UMWAIT/TPAUSE +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +x86/cpu: Add support for UMONITOR/UMWAIT/TPAUSE + +RH-Author: plai@redhat.com +Message-id: <1574797015-32564-7-git-send-email-plai@redhat.com> +Patchwork-id: 92695 +O-Subject: [RHEL8.2 qemu-kvm PATCH 6/7] x86/cpu: Add support for UMONITOR/UMWAIT/TPAUSE +Bugzilla: 1634827 +RH-Acked-by: Eduardo Habkost +RH-Acked-by: Michael S. Tsirkin +RH-Acked-by: Igor Mammedov + +From: Tao Xu + +UMONITOR, UMWAIT and TPAUSE are a set of user wait instructions. +This patch adds support for user wait instructions in KVM. Availability +of the user wait instructions is indicated by the presence of the CPUID +feature flag WAITPKG CPUID.0x07.0x0:ECX[5]. User wait instructions may +be executed at any privilege level, and use IA32_UMWAIT_CONTROL MSR to +set the maximum time. + +The patch enable the umonitor, umwait and tpause features in KVM. +Because umwait and tpause can put a (psysical) CPU into a power saving +state, by default we dont't expose it to kvm and enable it only when +guest CPUID has it. And use QEMU command-line "-overcommit cpu-pm=on" +(enable_cpu_pm is enabled), a VM can use UMONITOR, UMWAIT and TPAUSE +instructions. If the instruction causes a delay, the amount of time +delayed is called here the physical delay. The physical delay is first +computed by determining the virtual delay (the time to delay relative to +the VM’s timestamp counter). Otherwise, UMONITOR, UMWAIT and TPAUSE cause +an invalid-opcode exception(#UD). + +The release document ref below link: +https://software.intel.com/sites/default/files/\ +managed/39/c5/325462-sdm-vol-1-2abcd-3abcd.pdf + +Co-developed-by: Jingqi Liu +Signed-off-by: Jingqi Liu +Signed-off-by: Tao Xu +Message-Id: <20191011074103.30393-2-tao3.xu@intel.com> +Signed-off-by: Paolo Bonzini +(cherry picked from commit 67192a298f5bf98f96e5516c3b6474c49e4853cd) +Signed-off-by: Paul Lai + +Resolved Conflicts: + target/i386/cpu.c + target/i386/cpu.h + +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.c | 2 +- + target/i386/cpu.h | 2 ++ + target/i386/kvm.c | 6 ++++++ + 3 files changed, 9 insertions(+), 1 deletion(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index 87b0502..7d2afc7 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -1016,7 +1016,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { + .type = CPUID_FEATURE_WORD, + .feat_names = { + NULL, "avx512vbmi", "umip", "pku", +- "ospke", NULL, "avx512vbmi2", NULL, ++ "ospke", "waitpkg", "avx512vbmi2", NULL, + "gfni", "vaes", "vpclmulqdq", "avx512vnni", + "avx512bitalg", NULL, "avx512-vpopcntdq", NULL, + "la57", NULL, NULL, NULL, +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index 7ab8ee9..fac98aa 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -708,6 +708,8 @@ typedef uint64_t FeatureWordArray[FEATURE_WORDS]; + #define CPUID_7_0_ECX_UMIP (1U << 2) + #define CPUID_7_0_ECX_PKU (1U << 3) + #define CPUID_7_0_ECX_OSPKE (1U << 4) ++/* UMONITOR/UMWAIT/TPAUSE Instructions */ ++#define CPUID_7_0_ECX_WAITPKG (1U << 5) + #define CPUID_7_0_ECX_VBMI2 (1U << 6) /* Additional VBMI Instrs */ + #define CPUID_7_0_ECX_GFNI (1U << 8) + #define CPUID_7_0_ECX_VAES (1U << 9) +diff --git a/target/i386/kvm.c b/target/i386/kvm.c +index ffd01f0..0fd5650 100644 +--- a/target/i386/kvm.c ++++ b/target/i386/kvm.c +@@ -392,6 +392,12 @@ uint32_t kvm_arch_get_supported_cpuid(KVMState *s, uint32_t function, + if (host_tsx_blacklisted()) { + ret &= ~(CPUID_7_0_EBX_RTM | CPUID_7_0_EBX_HLE); + } ++ } else if (function == 7 && index == 0 && reg == R_ECX) { ++ if (enable_cpu_pm) { ++ ret |= CPUID_7_0_ECX_WAITPKG; ++ } else { ++ ret &= ~CPUID_7_0_ECX_WAITPKG; ++ } + } else if (function == 7 && index == 0 && reg == R_EDX) { + /* + * Linux v4.17-v4.20 incorrectly return ARCH_CAPABILITIES on SVM hosts. +-- +1.8.3.1 + diff --git a/SOURCES/kvm-x86-cpu-Enable-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-cpu-Enable-MOVDIR64B-cpu-feature.patch b/SOURCES/kvm-x86-cpu-Enable-MOVDIR64B-cpu-feature.patch new file mode 100644 index 0000000..005f5df --- /dev/null +++ b/SOURCES/kvm-x86-cpu-Enable-MOVDIR64B-cpu-feature.patch @@ -0,0 +1,71 @@ +From 04387fbe913b26a3819d711ea91b99be6faa8616 Mon Sep 17 00:00:00 2001 +From: "plai@redhat.com" +Date: Tue, 26 Nov 2019 19:36:50 +0000 +Subject: [PATCH 06/11] x86/cpu: Enable MOVDIR64B cpu feature + +RH-Author: plai@redhat.com +Message-id: <1574797015-32564-3-git-send-email-plai@redhat.com> +Patchwork-id: 92691 +O-Subject: [RHEL8.2 qemu-kvm PATCH 2/7] x86/cpu: Enable MOVDIR64B cpu feature +Bugzilla: 1634827 +RH-Acked-by: Eduardo Habkost +RH-Acked-by: Michael S. Tsirkin +RH-Acked-by: Igor Mammedov + +From: Liu Jingqi + +MOVDIR64B moves 64-bytes as direct-store with 64-bytes write atomicity. +Direct store is implemented by using write combining (WC) for writing +data directly into memory without caching the data. + +The bit definition: +CPUID.(EAX=7,ECX=0):ECX[bit 28] MOVDIR64B + +The release document ref below link: +https://software.intel.com/sites/default/files/managed/c5/15/\ +architecture-instruction-set-extensions-programming-reference.pdf + +Cc: Xu Tao +Signed-off-by: Liu Jingqi +Message-Id: <1541488407-17045-3-git-send-email-jingqi.liu@intel.com> +Signed-off-by: Eduardo Habkost +(cherry picked from commit 1c65775ffc2dbd276a8bffe592feba0e186a151c) +Signed-off-by: Paul Lai + +Resolved Conflicts: + target/i386/cpu.c + +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.c | 2 +- + target/i386/cpu.h | 1 + + 2 files changed, 2 insertions(+), 1 deletion(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index f2ab558..307b629 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -1022,7 +1022,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { + "la57", NULL, NULL, NULL, + NULL, NULL, "rdpid", NULL, + NULL, "cldemote", NULL, "movdiri", +- NULL, NULL, NULL, NULL, ++ "movdir64b", NULL, NULL, NULL, + }, + .cpuid = { + .eax = 7, +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index 6ba0b1e..d33fa8d 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -719,6 +719,7 @@ typedef uint64_t FeatureWordArray[FEATURE_WORDS]; + #define CPUID_7_0_ECX_RDPID (1U << 22) + #define CPUID_7_0_ECX_CLDEMOTE (1U << 25) /* CLDEMOTE Instruction */ + #define CPUID_7_0_ECX_MOVDIRI (1U << 27) /* MOVDIRI Instruction */ ++#define CPUID_7_0_ECX_MOVDIR64B (1U << 28) /* MOVDIR64B Instruction */ + + #define CPUID_7_0_EDX_AVX512_4VNNIW (1U << 2) /* AVX512 Neural Network Instructions */ + #define CPUID_7_0_EDX_AVX512_4FMAPS (1U << 3) /* AVX512 Multiply Accumulation Single Precision */ +-- +1.8.3.1 + diff --git a/SOURCES/kvm-x86-cpu-Enable-MOVDIRI-cpu-feature.patch b/SOURCES/kvm-x86-cpu-Enable-MOVDIRI-cpu-feature.patch new file mode 100644 index 0000000..da10be4 --- /dev/null +++ b/SOURCES/kvm-x86-cpu-Enable-MOVDIRI-cpu-feature.patch @@ -0,0 +1,72 @@ +From a2765b13bbe4a4d5978cd25f451b35dbb137ab6e Mon Sep 17 00:00:00 2001 +From: "plai@redhat.com" +Date: Tue, 26 Nov 2019 19:36:49 +0000 +Subject: [PATCH 05/11] x86/cpu: Enable MOVDIRI cpu feature + +RH-Author: plai@redhat.com +Message-id: <1574797015-32564-2-git-send-email-plai@redhat.com> +Patchwork-id: 92696 +O-Subject: [RHEL8.2 qemu-kvm PATCH 1/7] x86/cpu: Enable MOVDIRI cpu feature +Bugzilla: 1634827 +RH-Acked-by: Eduardo Habkost +RH-Acked-by: Michael S. Tsirkin +RH-Acked-by: Igor Mammedov + +From: Liu Jingqi + +MOVDIRI moves doubleword or quadword from register to memory through +direct store which is implemented by using write combining (WC) for +writing data directly into memory without caching the data. + +The bit definition: +CPUID.(EAX=7,ECX=0):ECX[bit 27] MOVDIRI + +The release document ref below link: +https://software.intel.com/sites/default/files/managed/c5/15/\ +architecture-instruction-set-extensions-programming-reference.pdf + +Cc: Xu Tao +Signed-off-by: Liu Jingqi +Message-Id: <1541488407-17045-2-git-send-email-jingqi.liu@intel.com> +Signed-off-by: Eduardo Habkost +(cherry picked from commit 24261de4916596d8ab5f5fee67e9e7a19e8325a5) +Signed-off-by: Paul Lai + +Resolved Conflicts: + target/i386/cpu.c + target/i386/cpu.h + +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.c | 2 +- + target/i386/cpu.h | 1 + + 2 files changed, 2 insertions(+), 1 deletion(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +index ef6b958..f2ab558 100644 +--- a/target/i386/cpu.c ++++ b/target/i386/cpu.c +@@ -1021,7 +1021,7 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = { + "avx512bitalg", NULL, "avx512-vpopcntdq", NULL, + "la57", NULL, NULL, NULL, + NULL, NULL, "rdpid", NULL, +- NULL, "cldemote", NULL, NULL, ++ NULL, "cldemote", NULL, "movdiri", + NULL, NULL, NULL, NULL, + }, + .cpuid = { +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index 8d8814e..6ba0b1e 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -718,6 +718,7 @@ typedef uint64_t FeatureWordArray[FEATURE_WORDS]; + #define CPUID_7_0_ECX_LA57 (1U << 16) + #define CPUID_7_0_ECX_RDPID (1U << 22) + #define CPUID_7_0_ECX_CLDEMOTE (1U << 25) /* CLDEMOTE Instruction */ ++#define CPUID_7_0_ECX_MOVDIRI (1U << 27) /* MOVDIRI Instruction */ + + #define CPUID_7_0_EDX_AVX512_4VNNIW (1U << 2) /* AVX512 Neural Network Instructions */ + #define CPUID_7_0_EDX_AVX512_4FMAPS (1U << 3) /* AVX512 Multiply Accumulation Single Precision */ +-- +1.8.3.1 + diff --git a/SOURCES/kvm-x86-cpu-use-FeatureWordArray-to-define-filtered_feat.patch b/SOURCES/kvm-x86-cpu-use-FeatureWordArray-to-define-filtered_feat.patch new file mode 100644 index 0000000..65cceca --- /dev/null +++ b/SOURCES/kvm-x86-cpu-use-FeatureWordArray-to-define-filtered_feat.patch @@ -0,0 +1,44 @@ +From 8caf8808acc4b95a0bde03430b214a298da3a71a Mon Sep 17 00:00:00 2001 +From: Paolo Bonzini +Date: Fri, 22 Nov 2019 11:53:34 +0000 +Subject: [PATCH 01/16] x86/cpu: use FeatureWordArray to define + filtered_features + +RH-Author: Paolo Bonzini +Message-id: <20191122115348.25000-2-pbonzini@redhat.com> +Patchwork-id: 92599 +O-Subject: [RHEL8.2/rhel qemu-kvm PATCH 01/15] x86/cpu: use FeatureWordArray to define filtered_features +Bugzilla: 1689270 +RH-Acked-by: Dr. David Alan Gilbert +RH-Acked-by: Eduardo Habkost +RH-Acked-by: Maxim Levitsky + +From: Wei Yang + +Use the same definition as features/user_features in CPUX86State. + +Signed-off-by: Wei Yang +Message-Id: <20190620023746.9869-1-richardw.yang@linux.intel.com> +Signed-off-by: Eduardo Habkost +(cherry picked from commit f69ecddb4a02b5071297427b4ebb3d8f0cea7323) +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index 273c90b..add8b60 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -1409,7 +1409,7 @@ struct X86CPU { + bool cache_info_passthrough; + + /* Features that were filtered out because of missing host capabilities */ +- uint32_t filtered_features[FEATURE_WORDS]; ++ FeatureWordArray filtered_features; + + /* Enable PMU CPUID bits. This can't be enabled by default yet because + * it doesn't have ABI stability guarantees, as it passes all PMU CPUID +-- +1.8.3.1 + diff --git a/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 new file mode 100644 index 0000000..a9c2bcd --- /dev/null +++ b/SOURCES/kvm-x86-define-a-new-MSR-based-feature-word-FEATURE_WORD.patch @@ -0,0 +1,128 @@ +From 8b64571f3ce90fc14c571ea588f608bce4328d34 Mon Sep 17 00:00:00 2001 +From: "plai@redhat.com" +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: <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: Igor Mammedov +RH-Acked-by: Michael S. Tsirkin + +From: Robert Hoo + +Note RSBA is specially treated -- no matter host support it or not, qemu +pretends it is supported. + +Signed-off-by: Robert Hoo +Message-Id: <1539578845-37944-4-git-send-email-robert.hu@linux.intel.com> +[ehabkost: removed automatic enabling of RSBA] +Reviewed-by: Eduardo Habkost +Signed-off-by: Eduardo Habkost + +(cherry picked from commit d86f963694df27f11b3681ffd225c9362de1b634) +Signed-off-by: Paul Lai +Signed-off-by: Danilo C. L. de Paula +--- + target/i386/cpu.c | 24 +++++++++++++++++++++++- + target/i386/cpu.h | 8 ++++++++ + target/i386/kvm.c | 11 +++++++++++ + 3 files changed, 42 insertions(+), 1 deletion(-) + +diff --git a/target/i386/cpu.c b/target/i386/cpu.c +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] = { + }, + .tcg_features = ~0U, + }, ++ /*Below are MSR exposed features*/ ++ [FEAT_ARCH_CAPABILITIES] = { ++ .type = MSR_FEATURE_WORD, ++ .feat_names = { ++ "rdctl-no", "ibrs-all", "rsba", "skip-l1dfl-vmentry", ++ "ssb-no", NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ NULL, NULL, NULL, NULL, ++ }, ++ .msr = { ++ .index = MSR_IA32_ARCH_CAPABILITIES, ++ .cpuid_dep = { ++ FEAT_7_0_EDX, ++ CPUID_7_0_EDX_ARCH_CAPABILITIES ++ } ++ }, ++ }, + }; + + typedef struct X86RegisterInfo32 { +@@ -3665,7 +3686,8 @@ static uint32_t x86_cpu_get_supported_feature_word(FeatureWord w, + wi->cpuid.reg); + break; + case MSR_FEATURE_WORD: +- r = kvm_arch_get_supported_msr_feature(kvm_state, wi->msr.index); ++ r = kvm_arch_get_supported_msr_feature(kvm_state, ++ wi->msr.index); + break; + } + } else if (hvf_enabled()) { +diff --git a/target/i386/cpu.h b/target/i386/cpu.h +index dd4493e..63f692f 100644 +--- a/target/i386/cpu.h ++++ b/target/i386/cpu.h +@@ -500,6 +500,7 @@ typedef enum FeatureWord { + FEAT_6_EAX, /* CPUID[6].EAX */ + FEAT_XSAVE_COMP_LO, /* CPUID[EAX=0xd,ECX=0].EAX */ + FEAT_XSAVE_COMP_HI, /* CPUID[EAX=0xd,ECX=0].EDX */ ++ FEAT_ARCH_CAPABILITIES, + FEATURE_WORDS, + } FeatureWord; + +@@ -729,6 +730,13 @@ typedef uint32_t FeatureWordArray[FEATURE_WORDS]; + #define CPUID_TOPOLOGY_LEVEL_SMT (1U << 8) + #define CPUID_TOPOLOGY_LEVEL_CORE (2U << 8) + ++/* MSR Feature Bits */ ++#define MSR_ARCH_CAP_RDCL_NO (1U << 0) ++#define MSR_ARCH_CAP_IBRS_ALL (1U << 1) ++#define MSR_ARCH_CAP_RSBA (1U << 2) ++#define MSR_ARCH_CAP_SKIP_L1DFL_VMENTRY (1U << 3) ++#define MSR_ARCH_CAP_SSB_NO (1U << 4) ++ + #ifndef HYPERV_SPINLOCK_NEVER_RETRY + #define HYPERV_SPINLOCK_NEVER_RETRY 0xFFFFFFFF + #endif +diff --git a/target/i386/kvm.c b/target/i386/kvm.c +index 096ed24..f1626a4 100644 +--- a/target/i386/kvm.c ++++ b/target/i386/kvm.c +@@ -1833,6 +1833,17 @@ static int kvm_put_msrs(X86CPU *cpu, int level) + } + #endif + ++ /* If host supports feature MSR, write down. */ ++ if (kvm_feature_msrs) { ++ int i; ++ for (i = 0; i < kvm_feature_msrs->nmsrs; i++) ++ if (kvm_feature_msrs->indices[i] == MSR_IA32_ARCH_CAPABILITIES) { ++ kvm_msr_entry_add(cpu, MSR_IA32_ARCH_CAPABILITIES, ++ env->features[FEAT_ARCH_CAPABILITIES]); ++ break; ++ } ++ } ++ + /* + * The following MSRs have side effects on the guest or are too heavy + * for normal writeback. Limit them to reset or full state updates. +-- +1.8.3.1 + diff --git a/SOURCES/kvm-xhci-recheck-slot-status.patch b/SOURCES/kvm-xhci-recheck-slot-status.patch new file mode 100644 index 0000000..0fa6716 --- /dev/null +++ b/SOURCES/kvm-xhci-recheck-slot-status.patch @@ -0,0 +1,77 @@ +From 1406157e5944e023b07a644d5a8377db708134e8 Mon Sep 17 00:00:00 2001 +From: "Dr. David Alan Gilbert" +Date: Wed, 15 Jan 2020 12:07:42 +0100 +Subject: [PATCH 4/7] xhci: recheck slot status +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +RH-Author: Dr. David Alan Gilbert +Message-id: <20200115120742.19583-3-dgilbert@redhat.com> +Patchwork-id: 93353 +O-Subject: [RHEL-8.2.0 qemu-kvm PATCH 2/2] xhci: recheck slot status +Bugzilla: 1752320 +RH-Acked-by: Gerd Hoffmann +RH-Acked-by: Philippe Mathieu-Daudé +RH-Acked-by: Peter Xu + +From: Gerd Hoffmann + +Factor out slot status check into a helper function. Add an additional +check after completing transfers. This is needed in case a guest +queues multiple transfers in a row and a device unplug happens while +qemu processes them. + +Buglink: https://bugzilla.redhat.com/show_bug.cgi?id=1786413 +Signed-off-by: Gerd Hoffmann +Reviewed-by: Philippe Mathieu-Daudé +Message-id: 20200107083606.12393-1-kraxel@redhat.com +(cherry picked from commit 236846a019c4f7aa3111026fc9a1fe09684c8978) +Signed-off-by: Miroslav Rezanina +--- + hw/usb/hcd-xhci.c | 15 ++++++++++++--- + 1 file changed, 12 insertions(+), 3 deletions(-) + +diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c +index 45fcce3..e63a603 100644 +--- a/hw/usb/hcd-xhci.c ++++ b/hw/usb/hcd-xhci.c +@@ -1853,6 +1853,13 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, + xhci_kick_epctx(epctx, streamid); + } + ++static bool xhci_slot_ok(XHCIState *xhci, int slotid) ++{ ++ return (xhci->slots[slotid - 1].uport && ++ xhci->slots[slotid - 1].uport->dev && ++ xhci->slots[slotid - 1].uport->dev->attached); ++} ++ + static void xhci_kick_epctx(XHCIEPContext *epctx, unsigned int streamid) + { + XHCIState *xhci = epctx->xhci; +@@ -1870,9 +1877,7 @@ static void xhci_kick_epctx(XHCIEPContext *epctx, unsigned int streamid) + + /* If the device has been detached, but the guest has not noticed this + yet the 2 above checks will succeed, but we must NOT continue */ +- if (!xhci->slots[epctx->slotid - 1].uport || +- !xhci->slots[epctx->slotid - 1].uport->dev || +- !xhci->slots[epctx->slotid - 1].uport->dev->attached) { ++ if (!xhci_slot_ok(xhci, epctx->slotid)) { + return; + } + +@@ -1968,6 +1973,10 @@ static void xhci_kick_epctx(XHCIEPContext *epctx, unsigned int streamid) + } else { + xhci_fire_transfer(xhci, xfer, epctx); + } ++ if (!xhci_slot_ok(xhci, epctx->slotid)) { ++ /* surprise removal -> stop processing */ ++ break; ++ } + if (xfer->complete) { + /* update ring dequeue ptr */ + xhci_set_ep_state(xhci, epctx, stctx, epctx->state); +-- +1.8.3.1 + diff --git a/SPECS/qemu-kvm.spec b/SPECS/qemu-kvm.spec index d971ee7..90638d7 100644 --- a/SPECS/qemu-kvm.spec +++ b/SPECS/qemu-kvm.spec @@ -8,13 +8,12 @@ %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 %endif -%ifnarch s390x %{arm} +%ifnarch s390x %global have_librdma 1 %else %global have_librdma 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 @@ -48,10 +47,6 @@ %global kvm_target aarch64 %global have_fdt 1 %endif -%ifarch %{arm} - %global kvm_target arm - %global have_fdt 1 -%endif #Versions of various parts: @@ -72,13 +67,13 @@ Obsoletes: %1-rhev Summary: QEMU is a machine emulator and virtualizer Name: qemu-kvm Version: 2.12.0 -Release: 64%{?dist}.2 +Release: 99%{?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 Group: Development/Tools URL: http://www.qemu.org/ -ExclusiveArch: x86_64 %{power64} aarch64 s390x %{arm} +ExclusiveArch: x86_64 %{power64} aarch64 s390x Source0: http://wiki.qemu.org/download/qemu-2.12.0.tar.xz @@ -109,7 +104,6 @@ Source35: udev-kvm-check.c Source36: README.tests -Source9999: kvm-arm-fixes.patch Patch0001: 0001-Initial-redhat-build.patch Patch0002: 0002-Enable-disable-devices-for-RHEL-7.patch @@ -1323,10 +1317,565 @@ 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 +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 +# For bz#1749022 - Please backport 950c4e6c94b1 ("opts: don't silently truncate long option values", 2018-05-09) +Patch823: kvm-accel-use-g_strsplit-for-parsing-accelerator-names.patch +# For bz#1749022 - Please backport 950c4e6c94b1 ("opts: don't silently truncate long option values", 2018-05-09) +Patch824: kvm-opts-don-t-silently-truncate-long-parameter-keys.patch +# For bz#1749022 - Please backport 950c4e6c94b1 ("opts: don't silently truncate long option values", 2018-05-09) +Patch825: kvm-opts-don-t-silently-truncate-long-option-values.patch +# For bz#1749022 - Please backport 950c4e6c94b1 ("opts: don't silently truncate long option values", 2018-05-09) +Patch826: kvm-i386-fix-regression-parsing-multiboot-initrd-modules.patch +# For bz#1749022 - Please backport 950c4e6c94b1 ("opts: don't silently truncate long option values", 2018-05-09) +Patch827: kvm-i386-only-parse-the-initrd_filename-once-for-multibo.patch +# For bz#1749022 - Please backport 950c4e6c94b1 ("opts: don't silently truncate long option values", 2018-05-09) +Patch828: kvm-opts-remove-redundant-check-for-NULL-parameter.patch +# For bz#1749724 - CVE-2019-15890 qemu-kvm: QEMU: Slirp: use-after-free during packet reassembly [rhel-8] +Patch829: kvm-Using-ip_deq-after-m_free-might-read-pointers-from-a.patch +# For bz#1708459 - qemu-kvm core dumped when repeat "system_reset" multiple times during guest boot +Patch830: kvm-virtio-blk-Cancel-the-pending-BH-when-the-dataplane-.patch +# For bz#1660909 - [IBM 8.2 FEAT] KVM s390x: Crypto Passthrough Interrupt Support - qemu part +Patch831: kvm-s390x-cpumodel-Rework-CPU-feature-definition.patch +# For bz#1660909 - [IBM 8.2 FEAT] KVM s390x: Crypto Passthrough Interrupt Support - qemu part +Patch832: kvm-s390x-cpumodel-Set-up-CPU-model-for-AQIC-interceptio.patch +# For bz#1746361 - ccid: Fix incorrect dwProtocol advertisement of T=0 +Patch833: kvm-ccid-Fix-dwProtocols-advertisement-of-T-0.patch +# For bz#1754643 - RHEL8.1 Snapshot3 - Passthrough PCI card goes into error state if used in domain (kvm) +Patch834: kvm-s390-PCI-fix-IOMMU-region-init.patch +# For bz#1607367 - After boot failed, guest should not reboot when set reboot-timeout < -1 +Patch835: kvm-fw_cfg-Improve-error-message-when-can-t-load-splash-.patch +# For bz#1607367 - After boot failed, guest should not reboot when set reboot-timeout < -1 +Patch836: kvm-fw_cfg-Fix-boot-bootsplash-error-checking.patch +# For bz#1607367 - After boot failed, guest should not reboot when set reboot-timeout < -1 +Patch837: kvm-fw_cfg-Fix-boot-reboot-timeout-error-checking.patch +# For bz#1607367 - After boot failed, guest should not reboot when set reboot-timeout < -1 +Patch838: kvm-hw-nvram-fw_cfg-Store-reboot-timeout-as-little-endia.patch +# For bz#1738440 - For intel-iommu, qemu shows conflict behaviors between booting a guest with vfio and hot plugging vfio device +Patch839: kvm-intel_iommu-Correct-caching-mode-error-message.patch +# For bz#1738440 - For intel-iommu, qemu shows conflict behaviors between booting a guest with vfio and hot plugging vfio device +Patch840: kvm-intel_iommu-Sanity-check-vfio-pci-config-on-machine-.patch +# For bz#1738440 - For intel-iommu, qemu shows conflict behaviors between booting a guest with vfio and hot plugging vfio device +Patch841: kvm-qdev-machine-Introduce-hotplug_allowed-hook.patch +# For bz#1738440 - For intel-iommu, qemu shows conflict behaviors between booting a guest with vfio and hot plugging vfio device +Patch842: kvm-pc-q35-Disallow-vfio-pci-hotplug-without-VT-d-cachin.patch +# For bz#1738440 - For intel-iommu, qemu shows conflict behaviors between booting a guest with vfio and hot plugging vfio device +Patch843: kvm-intel_iommu-Remove-the-caching-mode-check-during-fla.patch +# For bz#1651474 - RHEL8.0 Beta - [4.18.0-32.el8.ppc64le] Guest VM crashes during vcpu hotplug with specific numa configuration (kvm) +Patch844: kvm-pseries-do-not-allow-memory-less-cpu-less-NUMA-node.patch +# For bz#1719127 - [Intel 8.2 Bug] warning shown when boot VM with “–cpu host” or “–cpu other mode” on ICX platform (physical) +Patch845: kvm-i386-Don-t-print-warning-if-phys-bits-was-set-automa.patch +# For bz#1693140 - aarch64: qemu: remove smbus_eeprom and i2c from config +Patch846: kvm-Disable-CONFIG_I2C-and-CONFIG_IOH3420.patch +# For bz#1757482 - Fail to migrate a rhel6.10-mt7.6 guest with dimm device +Patch847: kvm-usb-drop-unnecessary-usb_device_post_load-checks.patch +# For bz#1664376 - [IBM 8.2 FEAT] CCW IPL Support (kvm) - qemu part +Patch848: kvm-pc-bios-s390-ccw-define-loadparm-length.patch +# For bz#1664376 - [IBM 8.2 FEAT] CCW IPL Support (kvm) - qemu part +Patch849: kvm-pc-bios-s390-ccw-net-Use-diag308-to-reset-machine-be.patch +# For bz#1664376 - [IBM 8.2 FEAT] CCW IPL Support (kvm) - qemu part +Patch850: kvm-s390-bios-decouple-cio-setup-from-virtio.patch +# For bz#1664376 - [IBM 8.2 FEAT] CCW IPL Support (kvm) - qemu part +Patch851: kvm-s390-bios-decouple-common-boot-logic-from-virtio.patch +# For bz#1664376 - [IBM 8.2 FEAT] CCW IPL Support (kvm) - qemu part +Patch852: kvm-s390-bios-Clean-up-cio.h.patch +# For bz#1664376 - [IBM 8.2 FEAT] CCW IPL Support (kvm) - qemu part +Patch853: kvm-s390-bios-Decouple-channel-i-o-logic-from-virtio.patch +# For bz#1664376 - [IBM 8.2 FEAT] CCW IPL Support (kvm) - qemu part +Patch854: kvm-s390-bios-Map-low-core-memory.patch +# For bz#1664376 - [IBM 8.2 FEAT] CCW IPL Support (kvm) - qemu part +Patch855: kvm-s390-bios-ptr2u32-and-u32toptr.patch +# For bz#1664376 - [IBM 8.2 FEAT] CCW IPL Support (kvm) - qemu part +Patch856: kvm-s390-bios-Support-for-running-format-0-1-channel-pro.patch +# For bz#1664376 - [IBM 8.2 FEAT] CCW IPL Support (kvm) - qemu part +Patch857: kvm-s390-bios-cio-error-handling.patch +# For bz#1664376 - [IBM 8.2 FEAT] CCW IPL Support (kvm) - qemu part +Patch858: kvm-s390-bios-Extend-find_dev-for-non-virtio-devices.patch +# For bz#1664376 - [IBM 8.2 FEAT] CCW IPL Support (kvm) - qemu part +Patch859: kvm-s390-bios-Factor-finding-boot-device-out-of-virtio-c.patch +# For bz#1664376 - [IBM 8.2 FEAT] CCW IPL Support (kvm) - qemu part +Patch860: kvm-s390-bios-Refactor-virtio-to-run-channel-programs-vi.patch +# For bz#1664376 - [IBM 8.2 FEAT] CCW IPL Support (kvm) - qemu part +Patch861: kvm-s390-bios-Use-control-unit-type-to-determine-boot-me.patch +# For bz#1664376 - [IBM 8.2 FEAT] CCW IPL Support (kvm) - qemu part +Patch862: kvm-s390-bios-Add-channel-command-codes-structs-needed-f.patch +# For bz#1664376 - [IBM 8.2 FEAT] CCW IPL Support (kvm) - qemu part +Patch863: kvm-s390-bios-Support-booting-from-real-dasd-device.patch +# For bz#1664376 - [IBM 8.2 FEAT] CCW IPL Support (kvm) - qemu part +Patch864: kvm-s390-bios-Use-control-unit-type-to-find-bootable-dev.patch +# For bz#1660906 - [IBM 8.2 FEAT] KVM s390x: Crypto Passthrough Hotplug - qemu part +Patch865: kvm-s390x-vfio-ap-Implement-hot-plug-unplug-of-vfio-ap-d.patch +# For bz#1730969 - [ppc] qmp: The 'arch' value returned by the command 'query-cpus-fast' does not match +Patch866: kvm-qapi-fill-in-CpuInfoFast.arch-in-query-cpus-fast.patch +# For bz#1744602 - qemu-img gets stuck when stream-converting from http +Patch867: kvm-curl-Keep-pointer-to-the-CURLState-in-CURLSocket.patch +# For bz#1744602 - qemu-img gets stuck when stream-converting from http +Patch868: kvm-curl-Keep-socket-until-the-end-of-curl_sock_cb.patch +# For bz#1744602 - qemu-img gets stuck when stream-converting from http +Patch869: kvm-curl-Check-completion-in-curl_multi_do.patch +# For bz#1744602 - qemu-img gets stuck when stream-converting from http +Patch870: kvm-curl-Pass-CURLSocket-to-curl_multi_do.patch +# For bz#1744602 - qemu-img gets stuck when stream-converting from http +Patch871: kvm-curl-Report-only-ready-sockets.patch +# For bz#1744602 - qemu-img gets stuck when stream-converting from http +Patch872: kvm-curl-Handle-success-in-multi_check_completion.patch +# For bz#1744602 - qemu-img gets stuck when stream-converting from http +Patch873: kvm-curl-Check-curl_multi_add_handle-s-return-code.patch +# For bz#1689270 - Nested KVM: limit VMX features according to CPU models - Slow Train +Patch874: kvm-x86-cpu-use-FeatureWordArray-to-define-filtered_feat.patch +# For bz#1689270 - Nested KVM: limit VMX features according to CPU models - Slow Train +Patch875: kvm-i386-Add-x-force-features-option-for-testing.patch +# For bz#1689270 - Nested KVM: limit VMX features according to CPU models - Slow Train +Patch876: kvm-target-i386-define-a-new-MSR-based-feature-word-FEAT.patch +# For bz#1689270 - Nested KVM: limit VMX features according to CPU models - Slow Train +Patch877: kvm-i386-display-known-CPUID-features-linewrapped-in-alp.patch +# For bz#1689270 - Nested KVM: limit VMX features according to CPU models - Slow Train +Patch878: kvm-target-i386-kvm-kvm_get_supported_msrs-cleanup.patch +# For bz#1689270 - Nested KVM: limit VMX features according to CPU models - Slow Train +Patch879: kvm-target-i386-handle-filtered_features-in-a-new-functi.patch +# For bz#1689270 - Nested KVM: limit VMX features according to CPU models - Slow Train +Patch880: kvm-target-i386-introduce-generic-feature-dependency-mec.patch +# For bz#1689270 - Nested KVM: limit VMX features according to CPU models - Slow Train +Patch881: kvm-target-i386-expand-feature-words-to-64-bits.patch +# For bz#1689270 - Nested KVM: limit VMX features according to CPU models - Slow Train +Patch882: kvm-target-i386-add-VMX-definitions.patch +# For bz#1689270 - Nested KVM: limit VMX features according to CPU models - Slow Train +Patch883: kvm-vmxcap-correct-the-name-of-the-variables.patch +# For bz#1689270 - Nested KVM: limit VMX features according to CPU models - Slow Train +Patch884: kvm-target-i386-add-VMX-features.patch +# For bz#1689270 - Nested KVM: limit VMX features according to CPU models - Slow Train +Patch885: kvm-target-i386-work-around-KVM_GET_MSRS-bug-for-seconda.patch +# For bz#1689270 - Nested KVM: limit VMX features according to CPU models - Slow Train +Patch886: kvm-target-i386-adjust-for-missing-VMX-features.patch +# For bz#1689270 - Nested KVM: limit VMX features according to CPU models - Slow Train +Patch887: kvm-target-i386-add-VMX-features-to-named-CPU-models.patch +# For bz#1689270 - Nested KVM: limit VMX features according to CPU models - Slow Train +Patch888: kvm-target-i386-add-VMX-features-to-named-CPU-models-RHE.patch +# For bz#1776808 - qemu-kvm crashes when Windows VM is migrated with multiqueue +Patch889: kvm-vhost-fix-vhost_log-size-overflow-during-migration.patch +# For bz#1771971 - CVE-2019-11135 virt:rhel/qemu-kvm: hw: TSX Transaction Asynchronous Abort (TAA) [rhel-8.2.0] +Patch890: kvm-target-i386-Export-TAA_NO-bit-to-guests.patch +# For bz#1771971 - CVE-2019-11135 virt:rhel/qemu-kvm: hw: TSX Transaction Asynchronous Abort (TAA) [rhel-8.2.0] +Patch891: kvm-target-i386-add-support-for-MSR_IA32_TSX_CTRL.patch +# For bz#1539282 - [Intel 8.2 Feature][Crystal Ridge] Support MAP_SYNC - qemu-kvm +Patch892: kvm-util-mmap-alloc-Add-a-is_pmem-parameter-to-qemu_ram_.patch +# For bz#1539282 - [Intel 8.2 Feature][Crystal Ridge] Support MAP_SYNC - qemu-kvm +Patch893: kvm-mmap-alloc-unfold-qemu_ram_mmap.patch +# For bz#1539282 - [Intel 8.2 Feature][Crystal Ridge] Support MAP_SYNC - qemu-kvm +Patch894: kvm-mmap-alloc-fix-hugetlbfs-misaligned-length-in-ppc64.patch +# For bz#1539282 - [Intel 8.2 Feature][Crystal Ridge] Support MAP_SYNC - qemu-kvm +Patch895: kvm-util-mmap-alloc-support-MAP_SYNC-in-qemu_ram_mmap.patch +# For bz#1634827 - [Intel 8.2 Feat] KVM Enable SnowRidge Accelerator Interface Architecture (AIA) - qemu +Patch896: kvm-x86-cpu-Enable-MOVDIRI-cpu-feature.patch +# For bz#1634827 - [Intel 8.2 Feat] KVM Enable SnowRidge Accelerator Interface Architecture (AIA) - qemu +Patch897: kvm-x86-cpu-Enable-MOVDIR64B-cpu-feature.patch +# For bz#1634827 - [Intel 8.2 Feat] KVM Enable SnowRidge Accelerator Interface Architecture (AIA) - qemu +Patch898: kvm-add-call-to-qemu_add_opts-for-overcommit-option.patch +# For bz#1634827 - [Intel 8.2 Feat] KVM Enable SnowRidge Accelerator Interface Architecture (AIA) - qemu +Patch899: kvm-support-overcommit-cpu-pm-on-off.patch +Patch900: kvm-i386-cpu-make-cpu-host-support-monitor-mwait.patch +# For bz#1634827 - [Intel 8.2 Feat] KVM Enable SnowRidge Accelerator Interface Architecture (AIA) - qemu +Patch901: kvm-x86-cpu-Add-support-for-UMONITOR-UMWAIT-TPAUSE.patch +# For bz#1634827 - [Intel 8.2 Feat] KVM Enable SnowRidge Accelerator Interface Architecture (AIA) - qemu +Patch902: kvm-target-i386-Add-support-for-save-load-IA32_UMWAIT_CO.patch +# For bz#1674324 - With , qemu either refuses to start completely or spice-server crashes afterwards +Patch903: kvm-virtio-gpu-block-both-2d-and-3d-rendering.patch +# For bz#1642541 - [Intel 8.2 Feature] qemu-kvm Enable BFloat16 data type support +Patch904: kvm-x86-Intel-AVX512_BF16-feature-enabling.patch +# For bz#1741346 - Remove the "cpu64-rhel6" CPU from qemu-kvm +Patch905: kvm-i386-Remove-cpu64-rhel6-CPU-model.patch +# For bz#1769613 - [SEV] kexec mays hang at "[sda] Synchronizing SCSI cache " before switching to new kernel +Patch906: kvm-exec-Fix-MAP_RAM-for-cached-access.patch +# For bz#1769613 - [SEV] kexec mays hang at "[sda] Synchronizing SCSI cache " before switching to new kernel +Patch907: kvm-virtio-Return-true-from-virtio_queue_empty-if-broken.patch +# For bz#1752320 - vm gets stuck when migrate vm back and forth with remote-viewer trying to connect +Patch908: kvm-usbredir-Prevent-recursion-in-usbredir_write.patch +# For bz#1752320 - vm gets stuck when migrate vm back and forth with remote-viewer trying to connect +Patch909: kvm-xhci-recheck-slot-status.patch +# For bz#1791566 - CVE-2020-7039 virt:rhel/qemu-kvm: QEMU: slirp: OOB buffer access while emulating tcp protocols in tcp_emu() [rhel-8.2.0] +Patch910: kvm-tcp_emu-Fix-oob-access.patch +# For bz#1791566 - CVE-2020-7039 virt:rhel/qemu-kvm: QEMU: slirp: OOB buffer access while emulating tcp protocols in tcp_emu() [rhel-8.2.0] +Patch911: kvm-slirp-use-correct-size-while-emulating-IRC-commands.patch +# For bz#1791566 - CVE-2020-7039 virt:rhel/qemu-kvm: QEMU: slirp: OOB buffer access while emulating tcp protocols in tcp_emu() [rhel-8.2.0] +Patch912: kvm-slirp-use-correct-size-while-emulating-commands.patch +# For bz#1794501 - CVE-2020-1711 qemu-kvm: QEMU: block: iscsi: OOB heap access via an unexpected response of iSCSI Server [rhel-8.2.0] +Patch913: kvm-iscsi-Avoid-potential-for-get_status-overflow.patch +# For bz#1794501 - CVE-2020-1711 qemu-kvm: QEMU: block: iscsi: OOB heap access via an unexpected response of iSCSI Server [rhel-8.2.0] +Patch914: kvm-iscsi-Cap-block-count-from-GET-LBA-STATUS-CVE-2020-1.patch +# For bz#1708480 - [Q35] No "DEVICE_DELETED" event in qmp after unplug virtio-net-pci device +Patch915: kvm-clean-up-callback-when-del-virtqueue.patch +# For bz#1708480 - [Q35] No "DEVICE_DELETED" event in qmp after unplug virtio-net-pci device +Patch916: kvm-virtio-add-ability-to-delete-vq-through-a-pointer.patch +# For bz#1708480 - [Q35] No "DEVICE_DELETED" event in qmp after unplug virtio-net-pci device +Patch917: kvm-virtio-reset-region-cache-when-on-queue-deletion.patch +# For bz#1708480 - [Q35] No "DEVICE_DELETED" event in qmp after unplug virtio-net-pci device +Patch918: kvm-virtio-net-delete-also-control-queue-when-TX-RX-dele.patch +# For bz#1791677 - QEMU: Slirp: disable emulation of tcp programs like ftp IRC etc. [rhel-8] +Patch919: kvm-slirp-disable-tcp_emu.patch +# For bz#1790308 - qemu-kvm core dump when do L1 guest live migration with L2 guest running +Patch920: kvm-target-i386-kvm-initialize-feature-MSRs-very-early.patch BuildRequires: zlib-devel BuildRequires: glib2-devel @@ -1353,10 +1902,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} @@ -1400,7 +1949,7 @@ BuildRequires: cpp # For compressed guest memory dumps BuildRequires: lzo-devel snappy-devel # For NUMA memory binding -%ifnarch s390x %{arm} +%ifnarch s390x BuildRequires: numactl-devel %endif BuildRequires: libgcrypt-devel @@ -1459,7 +2008,7 @@ Requires: edk2-ovmf Requires: edk2-aarch64 %endif -%ifnarch aarch64 s390x %{arm} +%ifnarch aarch64 s390x Requires: seavgabios-bin >= 1.10.2-1 Requires: ipxe-roms-qemu >= 20170123-1 %endif @@ -1467,7 +2016,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} @@ -1475,6 +2024,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 @@ -1607,10 +2157,6 @@ the Secure Shell (SSH) protocol. %setup -q -n qemu-%{version} %autopatch -p1 -%ifarch %{arm} -patch -p1 < %{SOURCE9999} -%endif - %build %global buildarch %{kvm_target}-softmmu @@ -1619,9 +2165,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 @@ -1650,7 +2193,7 @@ buildldflags="VL_LDFLAGS=-Wl,--build-id" --disable-glusterfs \ %endif --enable-guest-agent \ -%ifnarch s390x %{arm} +%ifnarch s390x --enable-numa \ %else --disable-numa \ @@ -1680,11 +2223,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 @@ -1710,7 +2249,7 @@ buildldflags="VL_LDFLAGS=-Wl,--build-id" --enable-kvm \ --enable-libiscsi \ --disable-libnfs \ - --enable-libssh2 \ + --enable-libssh \ --enable-libusb \ --disable-bzip2 \ --enable-linux-aio \ @@ -1853,8 +2392,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 @@ -1986,7 +2526,7 @@ pxe_link() { ln -s ../ipxe.efi/$2.rom %{buildroot}%{_datadir}/%{name}/efi-$1.rom } -%ifnarch aarch64 s390x %{arm} +%ifnarch aarch64 s390x pxe_link e1000 8086100e pxe_link ne2k_pci 10ec8029 pxe_link pcnet 10222000 @@ -1999,7 +2539,7 @@ rom_link() { ln -s $1 %{buildroot}%{_datadir}/%{name}/$2 } -%ifnarch aarch64 s390x %{arm} +%ifnarch aarch64 s390x rom_link ../seavgabios/vgabios-isavga.bin vgabios.bin rom_link ../seavgabios/vgabios-cirrus.bin vgabios-cirrus.bin rom_link ../seavgabios/vgabios-qxl.bin vgabios-qxl.bin @@ -2037,13 +2577,7 @@ find $RPM_BUILD_ROOT -name '*.la' -or -name '*.a' | xargs rm -f chmod +x $RPM_BUILD_ROOT%{_libdir}/qemu-kvm/block-*.so %check -%ifnarch %{arm} 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 -%endif %post -n qemu-kvm-core # load kvm modules now, so we can make sure no reboot is needed. @@ -2059,6 +2593,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 @@ -2150,7 +2689,7 @@ useradd -r -u 107 -g qemu -G kvm -d / -s /sbin/nologin \ %{_datadir}/%{name}/s390-ccw.img %{_datadir}/%{name}/s390-netboot.img %endif -%ifnarch aarch64 s390x %{arm} +%ifnarch aarch64 s390x %{_datadir}/%{name}/vgabios.bin %{_datadir}/%{name}/vgabios-cirrus.bin %{_datadir}/%{name}/vgabios-qxl.bin @@ -2223,21 +2762,543 @@ useradd -r -u 107 -g qemu -G kvm -d / -s /sbin/nologin \ %changelog -* 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 +* Fri Feb 21 2020 Danilo Cesar Lemes de Paula - 2.12.0-99.el8 +- kvm-slirp-disable-tcp_emu.patch [bz#1791677] +- kvm-target-i386-kvm-initialize-feature-MSRs-very-early.patch [bz#1790308] +- Resolves: bz#1790308 + (qemu-kvm core dump when do L1 guest live migration with L2 guest running) +- Resolves: bz#1791677 + (QEMU: Slirp: disable emulation of tcp programs like ftp IRC etc. [rhel-8]) + +* Mon Feb 10 2020 Danilo Cesar Lemes de Paula - 2.12.0-98.el8 +- kvm-iscsi-Avoid-potential-for-get_status-overflow.patch [bz#1794501] +- kvm-iscsi-Cap-block-count-from-GET-LBA-STATUS-CVE-2020-1.patch [bz#1794501] +- kvm-clean-up-callback-when-del-virtqueue.patch [bz#1708480] +- kvm-virtio-add-ability-to-delete-vq-through-a-pointer.patch [bz#1708480] +- kvm-virtio-reset-region-cache-when-on-queue-deletion.patch [bz#1708480] +- kvm-virtio-net-delete-also-control-queue-when-TX-RX-dele.patch [bz#1708480] +- Resolves: bz#1708480 + ([Q35] No "DEVICE_DELETED" event in qmp after unplug virtio-net-pci device) +- Resolves: bz#1794501 + (CVE-2020-1711 qemu-kvm: QEMU: block: iscsi: OOB heap access via an unexpected response of iSCSI Server [rhel-8.2.0]) + +* Fri Jan 24 2020 Miroslav Rezanina - 2.12.0-97.el8 +- kvm-exec-Fix-MAP_RAM-for-cached-access.patch [bz#1769613] +- kvm-virtio-Return-true-from-virtio_queue_empty-if-broken.patch [bz#1769613] +- kvm-usbredir-Prevent-recursion-in-usbredir_write.patch [bz#1752320] +- kvm-xhci-recheck-slot-status.patch [bz#1752320] +- kvm-tcp_emu-Fix-oob-access.patch [bz#1791566] +- kvm-slirp-use-correct-size-while-emulating-IRC-commands.patch [bz#1791566] +- kvm-slirp-use-correct-size-while-emulating-commands.patch [bz#1791566] +- Resolves: bz#1752320 + (vm gets stuck when migrate vm back and forth with remote-viewer trying to connect) +- Resolves: bz#1769613 + ([SEV] kexec mays hang at "[sda] Synchronizing SCSI cache " before switching to new kernel) +- Resolves: bz#1791566 + (CVE-2020-7039 virt:rhel/qemu-kvm: QEMU: slirp: OOB buffer access while emulating tcp protocols in tcp_emu() [rhel-8.2.0]) + +* Tue Jan 07 2020 Danilo Cesar Lemes de Paula - 2.12.0-96.el8 +- kvm-i386-Remove-cpu64-rhel6-CPU-model.patch [bz#1741346] +- Resolves: bz#1741346 + (Remove the "cpu64-rhel6" CPU from qemu-kvm) + +* Thu Jan 02 2020 Danilo Cesar Lemes de Paula - 2.12.0-95.el8 +- kvm-virtio-gpu-block-both-2d-and-3d-rendering.patch [bz#1674324] +- kvm-x86-Intel-AVX512_BF16-feature-enabling.patch [bz#1642541] +- Resolves: bz#1642541 + ([Intel 8.2 Feature] qemu-kvm Enable BFloat16 data type support) +- Resolves: bz#1674324 + (With , qemu either refuses to start completely or spice-server crashes afterwards) + +* Wed Dec 18 2019 Danilo Cesar Lemes de Paula - 2.12.0-94.el8 +- kvm-util-mmap-alloc-Add-a-is_pmem-parameter-to-qemu_ram_.patch [bz#1539282] +- kvm-mmap-alloc-unfold-qemu_ram_mmap.patch [bz#1539282] +- kvm-mmap-alloc-fix-hugetlbfs-misaligned-length-in-ppc64.patch [bz#1539282] +- kvm-util-mmap-alloc-support-MAP_SYNC-in-qemu_ram_mmap.patch [bz#1539282] +- kvm-x86-cpu-Enable-MOVDIRI-cpu-feature.patch [bz#1634827] +- kvm-x86-cpu-Enable-MOVDIR64B-cpu-feature.patch [bz#1634827] +- kvm-add-call-to-qemu_add_opts-for-overcommit-option.patch [bz#1634827] +- kvm-support-overcommit-cpu-pm-on-off.patch [bz#1634827] +- kvm-i386-cpu-make-cpu-host-support-monitor-mwait.patch [] +- kvm-x86-cpu-Add-support-for-UMONITOR-UMWAIT-TPAUSE.patch [bz#1634827] +- kvm-target-i386-Add-support-for-save-load-IA32_UMWAIT_CO.patch [bz#1634827] +- Resolves: bz#1539282 + ([Intel 8.2 Feature][Crystal Ridge] Support MAP_SYNC - qemu-kvm) +- Resolves: bz#1634827 + ([Intel 8.2 Feat] KVM Enable SnowRidge Accelerator Interface Architecture (AIA) - qemu) + +* Wed Dec 11 2019 Danilo Cesar Lemes de Paula - 2.12.0-93.el8 +- kvm-target-i386-Export-TAA_NO-bit-to-guests.patch [bz#1771971] +- kvm-target-i386-add-support-for-MSR_IA32_TSX_CTRL.patch [bz#1771971] +- Resolves: bz#1771971 + (CVE-2019-11135 virt:rhel/qemu-kvm: hw: TSX Transaction Asynchronous Abort (TAA) [rhel-8.2.0]) + +* Mon Dec 02 2019 Danilo Cesar Lemes de Paula - 2.12.0-92.el8 +- kvm-x86-cpu-use-FeatureWordArray-to-define-filtered_feat.patch [bz#1689270] +- kvm-i386-Add-x-force-features-option-for-testing.patch [bz#1689270] +- kvm-target-i386-define-a-new-MSR-based-feature-word-FEAT.patch [bz#1689270] +- kvm-i386-display-known-CPUID-features-linewrapped-in-alp.patch [bz#1689270] +- kvm-target-i386-kvm-kvm_get_supported_msrs-cleanup.patch [bz#1689270] +- kvm-target-i386-handle-filtered_features-in-a-new-functi.patch [bz#1689270] +- kvm-target-i386-introduce-generic-feature-dependency-mec.patch [bz#1689270] +- kvm-target-i386-expand-feature-words-to-64-bits.patch [bz#1689270] +- kvm-target-i386-add-VMX-definitions.patch [bz#1689270] +- kvm-vmxcap-correct-the-name-of-the-variables.patch [bz#1689270] +- kvm-target-i386-add-VMX-features.patch [bz#1689270] +- kvm-target-i386-work-around-KVM_GET_MSRS-bug-for-seconda.patch [bz#1689270] +- kvm-target-i386-adjust-for-missing-VMX-features.patch [bz#1689270] +- kvm-target-i386-add-VMX-features-to-named-CPU-models.patch [bz#1689270] +- kvm-target-i386-add-VMX-features-to-named-CPU-models-RHE.patch [bz#1689270] +- kvm-vhost-fix-vhost_log-size-overflow-during-migration.patch [bz#1776808] +- Resolves: bz#1689270 + (Nested KVM: limit VMX features according to CPU models - Slow Train) +- Resolves: bz#1776808 + (qemu-kvm crashes when Windows VM is migrated with multiqueue) + +* Wed Nov 27 2019 Danilo Cesar Lemes de Paula - 2.12.0-91.el8 +- kvm-qapi-fill-in-CpuInfoFast.arch-in-query-cpus-fast.patch [bz#1730969] +- kvm-curl-Keep-pointer-to-the-CURLState-in-CURLSocket.patch [bz#1744602] +- kvm-curl-Keep-socket-until-the-end-of-curl_sock_cb.patch [bz#1744602] +- kvm-curl-Check-completion-in-curl_multi_do.patch [bz#1744602] +- kvm-curl-Pass-CURLSocket-to-curl_multi_do.patch [bz#1744602] +- kvm-curl-Report-only-ready-sockets.patch [bz#1744602] +- kvm-curl-Handle-success-in-multi_check_completion.patch [bz#1744602] +- kvm-curl-Check-curl_multi_add_handle-s-return-code.patch [bz#1744602] +- Resolves: bz#1730969 + ([ppc] qmp: The 'arch' value returned by the command 'query-cpus-fast' does not match) +- Resolves: bz#1744602 + (qemu-img gets stuck when stream-converting from http) + +* Tue Nov 12 2019 Danilo Cesar Lemes de Paula - 2.12.0-90.el8 +- kvm-i386-Don-t-print-warning-if-phys-bits-was-set-automa.patch [bz#1719127] +- kvm-Disable-CONFIG_I2C-and-CONFIG_IOH3420.patch [bz#1693140] +- kvm-usb-drop-unnecessary-usb_device_post_load-checks.patch [bz#1757482] +- kvm-pc-bios-s390-ccw-define-loadparm-length.patch [bz#1664376] +- kvm-pc-bios-s390-ccw-net-Use-diag308-to-reset-machine-be.patch [bz#1664376] +- kvm-s390-bios-decouple-cio-setup-from-virtio.patch [bz#1664376] +- kvm-s390-bios-decouple-common-boot-logic-from-virtio.patch [bz#1664376] +- kvm-s390-bios-Clean-up-cio.h.patch [bz#1664376] +- kvm-s390-bios-Decouple-channel-i-o-logic-from-virtio.patch [bz#1664376] +- kvm-s390-bios-Map-low-core-memory.patch [bz#1664376] +- kvm-s390-bios-ptr2u32-and-u32toptr.patch [bz#1664376] +- kvm-s390-bios-Support-for-running-format-0-1-channel-pro.patch [bz#1664376] +- kvm-s390-bios-cio-error-handling.patch [bz#1664376] +- kvm-s390-bios-Extend-find_dev-for-non-virtio-devices.patch [bz#1664376] +- kvm-s390-bios-Factor-finding-boot-device-out-of-virtio-c.patch [bz#1664376] +- kvm-s390-bios-Refactor-virtio-to-run-channel-programs-vi.patch [bz#1664376] +- kvm-s390-bios-Use-control-unit-type-to-determine-boot-me.patch [bz#1664376] +- kvm-s390-bios-Add-channel-command-codes-structs-needed-f.patch [bz#1664376] +- kvm-s390-bios-Support-booting-from-real-dasd-device.patch [bz#1664376] +- kvm-s390-bios-Use-control-unit-type-to-find-bootable-dev.patch [bz#1664376] +- kvm-s390x-vfio-ap-Implement-hot-plug-unplug-of-vfio-ap-d.patch [bz#1660906] +- Resolves: bz#1660906 + ([IBM 8.2 FEAT] KVM s390x: Crypto Passthrough Hotplug - qemu part) +- Resolves: bz#1664376 + ([IBM 8.2 FEAT] CCW IPL Support (kvm) - qemu part) +- Resolves: bz#1693140 + (aarch64: qemu: remove smbus_eeprom and i2c from config) +- Resolves: bz#1719127 + ([Intel 8.2 Bug] warning shown when boot VM with “–cpu host” or “–cpu other mode” on ICX platform (physical)) +- Resolves: bz#1757482 + (Fail to migrate a rhel6.10-mt7.6 guest with dimm device) + +* Mon Oct 14 2019 Danilo Cesar Lemes de Paula - 2.12.0-89.el8 +- kvm-accel-use-g_strsplit-for-parsing-accelerator-names.patch [bz#1749022] +- kvm-opts-don-t-silently-truncate-long-parameter-keys.patch [bz#1749022] +- kvm-opts-don-t-silently-truncate-long-option-values.patch [bz#1749022] +- kvm-i386-fix-regression-parsing-multiboot-initrd-modules.patch [bz#1749022] +- kvm-i386-only-parse-the-initrd_filename-once-for-multibo.patch [bz#1749022] +- kvm-opts-remove-redundant-check-for-NULL-parameter.patch [bz#1749022] +- kvm-Using-ip_deq-after-m_free-might-read-pointers-from-a.patch [bz#1749724] +- kvm-virtio-blk-Cancel-the-pending-BH-when-the-dataplane-.patch [bz#1708459] +- kvm-s390x-cpumodel-Rework-CPU-feature-definition.patch [bz#1660909] +- kvm-s390x-cpumodel-Set-up-CPU-model-for-AQIC-interceptio.patch [bz#1660909] +- kvm-ccid-Fix-dwProtocols-advertisement-of-T-0.patch [bz#1746361] +- kvm-s390-PCI-fix-IOMMU-region-init.patch [bz#1754643] +- kvm-fw_cfg-Improve-error-message-when-can-t-load-splash-.patch [bz#1607367] +- kvm-fw_cfg-Fix-boot-bootsplash-error-checking.patch [bz#1607367] +- kvm-fw_cfg-Fix-boot-reboot-timeout-error-checking.patch [bz#1607367] +- kvm-hw-nvram-fw_cfg-Store-reboot-timeout-as-little-endia.patch [bz#1607367] +- kvm-intel_iommu-Correct-caching-mode-error-message.patch [bz#1738440] +- kvm-intel_iommu-Sanity-check-vfio-pci-config-on-machine-.patch [bz#1738440] +- kvm-qdev-machine-Introduce-hotplug_allowed-hook.patch [bz#1738440] +- kvm-pc-q35-Disallow-vfio-pci-hotplug-without-VT-d-cachin.patch [bz#1738440] +- kvm-intel_iommu-Remove-the-caching-mode-check-during-fla.patch [bz#1738440] +- kvm-pseries-do-not-allow-memory-less-cpu-less-NUMA-node.patch [bz#1651474] +- Resolves: bz#1607367 + (After boot failed, guest should not reboot when set reboot-timeout < -1) +- Resolves: bz#1651474 + (RHEL8.0 Beta - [4.18.0-32.el8.ppc64le] Guest VM crashes during vcpu hotplug with specific numa configuration (kvm)) +- Resolves: bz#1660909 + ([IBM 8.2 FEAT] KVM s390x: Crypto Passthrough Interrupt Support - qemu part) +- Resolves: bz#1708459 + (qemu-kvm core dumped when repeat "system_reset" multiple times during guest boot) +- Resolves: bz#1738440 + (For intel-iommu, qemu shows conflict behaviors between booting a guest with vfio and hot plugging vfio device) +- Resolves: bz#1746361 + (ccid: Fix incorrect dwProtocol advertisement of T=0) +- Resolves: bz#1749022 + (Please backport 950c4e6c94b1 ("opts: don't silently truncate long option values", 2018-05-09)) +- Resolves: bz#1749724 + (CVE-2019-15890 qemu-kvm: QEMU: Slirp: use-after-free during packet reassembly [rhel-8]) +- Resolves: bz#1754643 + (RHEL8.1 Snapshot3 - Passthrough PCI card goes into error state if used in domain (kvm)) + +* Fri Sep 13 2019 Danilo Cesar Lemes de Paula - 2.12.0-88.el8 +- Revert fix for bz#1749724 - this got delayed to 8.2 + (CVE-2019-15890 qemu-kvm: QEMU: Slirp: use-after-free during packet reassembly [rhel-8]) + +* Tue Sep 03 2019 Danilo Cesar Lemes de Paula - 2.12.0-86.el8 +- kvm-Do-not-run-iotests-on-brew-build.patch [bz#1742819] +- kvm-target-ppc-spapr-Add-workaround-option-to-SPAPR_CAP_.patch [bz#1744415] +- kvm-target-ppc-spapr-Add-SPAPR_CAP_CCF_ASSIST.patch [bz#1744415] +- kvm-i386-x86_cpu_list_feature_names-function.patch [bz#1747185] +- kvm-i386-unavailable-features-QOM-property.patch [bz#1747185] +- kvm-file-posix-Handle-undetectable-alignment.patch [bz#1738839] +- kvm-iotests-Tweak-221-sizing-for-different-hole-granular.patch [bz#1738839] +- kvm-iotests-Filter-175-s-allocation-information.patch [bz#1738839] +- kvm-block-posix-Always-allocate-the-first-block.patch [bz#1738839] +- kvm-iotests-Test-allocate_first_block-with-O_DIRECT.patch [bz#1738839] +- Resolves: bz#1738839 + (I/O error when virtio-blk disk is backed by a raw image on 4k disk) +- Resolves: bz#1742819 + (Remove iotests from qemu-kvm builds [RHEL 8.1.0]) +- Resolves: bz#1744415 + (Backport support for count cache flush Spectre v2 mitigation [slow train]) +- Resolves: bz#1747185 + ("filtered-features" QOM property is not available) + +* Mon Aug 19 2019 Danilo Cesar Lemes de Paula - 2.12.0-85.el8 +- kvm-console-Avoid-segfault-in-screendump.patch [bz#1684383] +- kvm-usb-hub-clear-suspend-on-detach.patch [bz#1619661] +- kvm-qemu-img-fix-regression-copying-secrets-during-conve.patch [bz#1727821] +- Resolves: bz#1619661 + (the attach hub on one hub still exits in device manager after unhotplug) +- Resolves: bz#1684383 + (qemu crashed when take screenshot for 2nd head of virtio video device if the display not opened by virt-viewer) +- Resolves: bz#1727821 + (Failed to convert a source image to the qcow2 image encrypted by luks) + +* Fri Aug 16 2019 Danilo Cesar Lemes de Paula - 2.12.0-84.el8 +- kvm-vnc-detect-and-optimize-pageflips.patch [bz#1727033] +- kvm-block-backend-Make-blk_inc-dec_in_flight-public.patch [bz#1716349] +- kvm-virtio-blk-Increase-in_flight-for-request-restart-BH.patch [bz#1716349] +- kvm-block-Fix-AioContext-switch-for-drained-node.patch [bz#1716349] +- kvm-test-bdrv-drain-AioContext-switch-in-drained-section.patch [bz#1716349] +- kvm-block-Use-normal-drain-for-bdrv_set_aio_context.patch [bz#1716349] +- kvm-block-Fix-AioContext-switch-for-bs-drv-NULL.patch [bz#1716347] +- kvm-iothread-fix-crash-with-invalid-properties.patch [bz#1687541] +- kvm-iothread-replace-init_done_cond-with-a-semaphore.patch [bz#1687541] +- kvm-RHEL-disable-hostmem-memfd.patch [bz#1740797] +- Resolves: bz#1687541 + (qemu aborted when start guest with a big iothreads) +- Resolves: bz#1716347 + (Qemu Core dump when quit vm that's in status "paused(io-error)" with data plane enabled) +- Resolves: bz#1716349 + (qemu with iothreads enabled crashes on resume after enospc pause for disk extension) +- Resolves: bz#1727033 + (vnc server should detect page-flips and avoid sending fullscreen updates then.) +- Resolves: bz#1740797 + (Disable memfd in QEMU) + +* Thu Aug 01 2019 Danilo Cesar Lemes de Paula - 2.12.0-83.el8 +- kvm-hw-block-pflash_cfi01-Add-missing-DeviceReset-handle.patch [bz#1707192] +- kvm-block-file-posix-Unaligned-O_DIRECT-block-status.patch [bz#1678979] +- kvm-iotests-Test-unaligned-raw-images-with-O_DIRECT.patch [bz#1678979] +- kvm-nbd-client-Lower-min_block-for-block-status-unaligne.patch [bz#1678979] +- kvm-nbd-client-Reject-inaccessible-tail-of-inconsistent-.patch [bz#1678979] +- kvm-nbd-client-Support-qemu-img-convert-from-unaligned-s.patch [bz#1678979] +- kvm-block-Add-bdrv_get_request_alignment.patch [bz#1678979] +- kvm-nbd-server-Advertise-actual-minimum-block-size.patch [bz#1678979] +- kvm-slirp-check-sscanf-result-when-emulating-ident.patch [bz#1727642] +- kvm-slirp-fix-big-little-endian-conversion-in-ident-prot.patch [bz#1727642] +- kvm-slirp-ensure-there-is-enough-space-in-mbuf-to-null-t.patch [bz#1727642] +- kvm-slirp-don-t-manipulate-so_rcv-in-tcp_emu.patch [bz#1727642] +- kvm-tap-set-vhostfd-passed-from-qemu-cli-to-non-blocking.patch [bz#1732642] +- kvm-Fix-heap-overflow-in-ip_reass-on-big-packet-input.patch [bz#1734751] +- Resolves: bz#1678979 + (qemu-img convert abort when converting image with unaligned size (qemu-img: block/io.c:2134: bdrv_co_block_status: Assertion `*pnum && (((*pnum) % (align)) == 0) && align > offset - aligned_offset\' failed)) +- Resolves: bz#1707192 + (implement missing reset handler for cfi.pflash01 - slow train) +- Resolves: bz#1727642 + (CVE-2019-6778 qemu-kvm: QEMU: slirp: heap buffer overflow in tcp_emu()) +- Resolves: bz#1732642 + (enable the virtio-net frontend to work with the vhost-net backend in SEV guests) +- Resolves: bz#1734751 + (CVE-2019-14378 qemu-kvm: QEMU: slirp: heap buffer overflow during packet reassembly [rhel-8.1.0]) + +* Tue Jul 23 2019 Danilo Cesar Lemes de Paula - 2.12.0-82.el8 +- kvm-i386-Add-new-model-of-Cascadelake-Server.patch [bz#1629906] +- kvm-i386-Update-stepping-of-Cascadelake-Server.patch [bz#1629906] +- kvm-target-i386-Disable-MPX-support-on-named-CPU-models.patch [bz#1629906] +- kvm-i386-remove-the-INTEL_PT-CPUID-bit-from-named-CPU-NEW.patch [bz#1629906] +- kvm-i386-Disable-OSPKE-on-CPU-model-definitions-NEW.patch [bz#1629906] +- kvm-block-ssh-Convert-from-DPRINTF-macro-to-trace-events.patch [bz#1513367] +- kvm-block-ssh-Do-not-report-read-write-flush-errors-to-t.patch [bz#1513367] +- kvm-qemu-iotests-Fix-paths-for-NFS.patch [bz#1513367] +- kvm-qemu-iotests-Filter-NFS-paths.patch [bz#1513367] +- kvm-iotests-Filter-SSH-paths.patch [bz#1513367] +- kvm-block-ssh-Implement-.bdrv_refresh_filename.patch [bz#1513367] +- kvm-iotests-Use-Python-byte-strings-where-appropriate.patch [bz#1513367] +- kvm-iotests-Unify-log-outputs-between-Python-2-and-3.patch [bz#1513367] +- kvm-ssh-switch-from-libssh2-to-libssh.patch [bz#1513367] +- kvm-redhat-switch-from-libssh2-to-libssh.patch [bz#1513367] +- kvm-block-gluster-limit-the-transfer-size-to-512-MiB.patch [bz#1728657] +- kvm-s390-cpumodel-fix-description-for-the-new-vector-fac.patch [bz#1729975] +- kvm-s390x-cpumodel-remove-esort-from-the-default-model.patch [bz#1729975] +- kvm-s390x-cpumodel-also-change-name-of-vxbeh.patch [bz#1729975] +- kvm-s390x-cpumodel-change-internal-name-of-vxpdeh-to-mat.patch [bz#1729975] +- kvm-target-i386-sev-Do-not-unpin-ram-device-memory-regio.patch [bz#1728958] +- kvm-i386-Save-EFER-for-32-bit-targets.patch [bz#1689269] +- kvm-target-i386-rename-HF_SVMI_MASK-to-HF_GUEST_MASK.patch [bz#1689269] +- kvm-target-i386-kvm-add-VMX-migration-blocker.patch [bz#1689269] +- kvm-target-i386-kvm-just-return-after-migrate_add_blocke.patch [bz#1689269] +- kvm-target-i386-kvm-Delete-VMX-migration-blocker-on-vCPU.patch [bz#1689269] +- kvm-Introduce-kvm_arch_destroy_vcpu.patch [bz#1689269] +- kvm-target-i386-kvm-Use-symbolic-constant-for-DB-BP-exce.patch [bz#1689269] +- kvm-target-i386-kvm-Re-inject-DB-to-guest-with-updated-D.patch [bz#1689269] +- kvm-target-i386-kvm-Block-migration-for-vCPUs-exposed-wi.patch [bz#1689269] +- kvm-target-i386-kvm-do-not-initialize-padding-fields.patch [bz#1689269] +- kvm-linux-headers-synchronize-generic-and-x86-KVM-header.patch [bz#1689269] +- kvm-vmstate-Add-support-for-kernel-integer-types.patch [bz#1689269] +- kvm-target-i386-kvm-Add-support-for-save-and-restore-nes.patch [bz#1689269] +- kvm-target-i386-kvm-Add-support-for-KVM_CAP_EXCEPTION_PA.patch [bz#1689269] +- kvm-target-i386-kvm-Add-nested-migration-blocker-only-wh.patch [bz#1689269] +- kvm-target-i386-kvm-Demand-nested-migration-kernel-capab.patch [bz#1689269] +- kvm-target-i386-skip-KVM_GET-SET_NESTED_STATE-if-VMX-dis.patch [bz#1689269] +- kvm-i386-kvm-Do-not-sync-nested-state-during-runtime.patch [bz#1689269] +- Resolves: bz#1513367 + (qemu with libssh) +- Resolves: bz#1629906 + ([Intel 8.1 Feat] qemu-kvm Introduce Cascade Lake (CLX) cpu model) +- Resolves: bz#1689269 + (Nested KVM: support for migration of nested hypervisors - Slow Train) +- Resolves: bz#1728657 + ('qemu-io write' to a raw image over libgfapi fails) +- Resolves: bz#1728958 + (Hot unplug vfio-pci NIC devices from sev guest will cause qemu-kvm: sev_ram_block_removed: failed to unregister region) +- Resolves: bz#1729975 + (RHEL 8.1 Pre-Beta - Fix for hardware CPU Model) + +* Mon Jul 08 2019 Miroslav Rezanina - 2.12.0-81.el8 +- kvm-target-i386-add-MDS-NO-feature.patch [bz#1714792] +- kvm-virtio-gpu-pass-down-VirtIOGPU-pointer-to-a-bunch-of.patch [bz#1531543] +- kvm-virtio-gpu-add-iommu-support.patch [bz#1531543] +- kvm-virtio-gpu-fix-unmap-in-error-path.patch [bz#1531543] +- Resolves: bz#1531543 + ([RFE] add iommu support to virtio-gpu) +- Resolves: bz#1714792 + ([Intel 8.1 FEAT] MDS_NO exposure to guest) + +* Tue Jul 02 2019 Danilo Cesar Lemes de Paula - 2.12.0-80.el8 +- kvm-qxl-check-release-info-object.patch [bz#1712705] +- kvm-iotests-Make-182-do-without-device_add.patch [bz#1707598] +- Resolves: bz#1707598 + (qemu-iotest 182 fails without device hotplugging support) +- Resolves: bz#1712705 + (CVE-2019-12155 qemu-kvm: QEMU: qxl: null pointer dereference while releasing spice resources [rhel-8]) + +* Fri Jun 28 2019 Danilo de Paula - 15:2.12.0-79 +- Rebuild all virt packages to fix RHEL's upgrade path +- Resolves: rhbz#1695587 + (Ensure modular RPM upgrade path) + +* Thu Jun 20 2019 Miroslav Rezanina - 2.12.0-78.el8 +- kvm-gluster-Handle-changed-glfs_ftruncate-signature.patch [bz#1721983] +- kvm-gluster-the-glfs_io_cbk-callback-function-pointer-ad.patch [bz#1721983] +- Resolves: bz#1721983 + (qemu-kvm can't be build with new gluster version (6.0.6)) + +* Thu Jun 13 2019 Danilo Cesar Lemes de Paula - 2.12.0-77.el8 +- kvm-i386-Make-arch_capabilities-migratable.patch [bz#1709970] +- kvm-spapr-Fix-ibm-max-associativity-domains-property-num.patch [bz#1710662] +- 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