diff --git a/SOURCES/libvirt-Handle-copying-bitmaps-to-larger-data-buffers.patch b/SOURCES/libvirt-Handle-copying-bitmaps-to-larger-data-buffers.patch
new file mode 100644
index 0000000..4f8ba04
--- /dev/null
+++ b/SOURCES/libvirt-Handle-copying-bitmaps-to-larger-data-buffers.patch
@@ -0,0 +1,56 @@
+From e75abae126f9fcaf1e8478f0780ecae736f7d3e1 Mon Sep 17 00:00:00 2001
+Message-Id: <e75abae126f9fcaf1e8478f0780ecae736f7d3e1@dist-git>
+From: "Allen, John" <John.Allen@amd.com>
+Date: Tue, 2 Jul 2019 17:05:34 +0200
+Subject: [PATCH] Handle copying bitmaps to larger data buffers
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+If a bitmap of a shorter length than the data buffer is passed to
+virBitmapToDataBuf, it will read off the end of the bitmap and copy junk
+into the returned buffer. Add a check to only copy the length of the
+bitmap to the buffer.
+
+The problem can be observed after setting a vcpu affinity using the vcpupin
+command on a system with a large number of cores:
+  # virsh vcpupin example_domain 0 0
+  # virsh vcpupin example_domain 0
+     VCPU   CPU Affinity
+    ---------------------------
+     0      0,192,197-198,202
+
+Signed-off-by: John Allen <john.allen@amd.com>
+(cherry picked from commit 51f9f80d350e633adf479c6a9b3c55f82ca9cbd4)
+
+https: //bugzilla.redhat.com/show_bug.cgi?id=1703160
+Signed-off-by: Erik Skultety <eskultet@redhat.com>
+Message-Id: <1a487c4f1ba9725eb7325debeeff2861d7047890.1562079635.git.eskultet@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/virbitmap.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/src/util/virbitmap.c b/src/util/virbitmap.c
+index 49e542a4e6..7df0a2d4f3 100644
+--- a/src/util/virbitmap.c
++++ b/src/util/virbitmap.c
+@@ -831,11 +831,15 @@ virBitmapToDataBuf(virBitmapPtr bitmap,
+                    unsigned char *bytes,
+                    size_t len)
+ {
++    size_t nbytes = bitmap->map_len * (VIR_BITMAP_BITS_PER_UNIT / CHAR_BIT);
+     unsigned long *l;
+     size_t i, j;
+ 
+     memset(bytes, 0, len);
+ 
++    /* If bitmap and buffer differ in size, only fill to the smaller length */
++    len = MIN(len, nbytes);
++
+     /* htole64 is not provided by gnulib, so we do the conversion by hand */
+     l = bitmap->map;
+     for (i = j = 0; i < len; i++, j++) {
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-PPC64-support-for-NVIDIA-V100-GPU-with-NVLink2-passthrough.patch b/SOURCES/libvirt-PPC64-support-for-NVIDIA-V100-GPU-with-NVLink2-passthrough.patch
new file mode 100644
index 0000000..d29a9cf
--- /dev/null
+++ b/SOURCES/libvirt-PPC64-support-for-NVIDIA-V100-GPU-with-NVLink2-passthrough.patch
@@ -0,0 +1,183 @@
+From 5347b12008842b5c86f766e391c6f3756afbff7d Mon Sep 17 00:00:00 2001
+Message-Id: <5347b12008842b5c86f766e391c6f3756afbff7d@dist-git>
+From: Daniel Henrique Barboza <danielhb413@gmail.com>
+Date: Fri, 3 May 2019 13:54:53 +0200
+Subject: [PATCH] PPC64 support for NVIDIA V100 GPU with NVLink2 passthrough
+
+The NVIDIA V100 GPU has an onboard RAM that is mapped into the
+host memory and accessible as normal RAM via an NVLink2 bridge. When
+passed through in a guest, QEMU puts the NVIDIA RAM window in a
+non-contiguous area, above the PCI MMIO area that starts at 32TiB.
+This means that the NVIDIA RAM window starts at 64TiB and go all the
+way to 128TiB.
+
+This means that the guest might request a 64-bit window, for each PCI
+Host Bridge, that goes all the way to 128TiB. However, the NVIDIA RAM
+window isn't counted as regular RAM, thus this window is considered
+only for the allocation of the Translation and Control Entry (TCE).
+For more information about how NVLink2 support works in QEMU,
+refer to the accepted implementation [1].
+
+This memory layout differs from the existing VFIO case, requiring its
+own formula. This patch changes the PPC64 code of
+@qemuDomainGetMemLockLimitBytes to:
+
+- detect if we have a NVLink2 bridge being passed through to the
+guest. This is done by using the @ppc64VFIODeviceIsNV2Bridge function
+added in the previous patch. The existence of the NVLink2 bridge in
+the guest means that we are dealing with the NVLink2 memory layout;
+
+- if an IBM NVLink2 bridge exists, passthroughLimit is calculated in a
+different way to account for the extra memory the TCE table can alloc.
+The 64TiB..128TiB window is more than enough to fit all possible
+GPUs, thus the memLimit is the same regardless of passing through 1 or
+multiple V100 GPUs.
+
+Further reading explaining the background
+[1] https://lists.gnu.org/archive/html/qemu-devel/2019-03/msg03700.html
+[2] https://www.redhat.com/archives/libvir-list/2019-March/msg00660.html
+[3] https://www.redhat.com/archives/libvir-list/2019-April/msg00527.html
+
+Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com>
+Reviewed-by: Erik Skultety <eskultet@redhat.com>
+(cherry picked from commit 1a922648f67f56c4374d647feebf2adb9a642f96)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1505998
+
+Conflicts:
+    The upstream commit relied on:
+        - v4.7.0-37-gb72183223f
+        - v4.7.0-38-ga14f597266
+    which were not backported so virPCIDeviceAddressAsString had to
+    swapped for the former virDomainPCIAddressAsString in order to
+    compile.
+
+Signed-off-by: Erik Skultety <eskultet@redhat.com>
+Message-Id: <03c00ebf46d85b0615134ef8655e67a4c909b7da.1556884443.git.eskultet@redhat.com>
+Reviewed-by: Andrea Bolognani <abologna@redhat.com>
+---
+ src/qemu/qemu_domain.c | 80 ++++++++++++++++++++++++++++++++----------
+ 1 file changed, 61 insertions(+), 19 deletions(-)
+
+diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
+index a8bc618389..21f0722495 100644
+--- a/src/qemu/qemu_domain.c
++++ b/src/qemu/qemu_domain.c
+@@ -9813,7 +9813,7 @@ qemuDomainUpdateCurrentMemorySize(virQEMUDriverPtr driver,
+  * such as '0004:04:00.0', and tells if the device is a NVLink2
+  * bridge.
+  */
+-static ATTRIBUTE_UNUSED bool
++static bool
+ ppc64VFIODeviceIsNV2Bridge(const char *device)
+ {
+     const char *nvlink2Files[] = {"ibm,gpu", "ibm,nvlink",
+@@ -9851,7 +9851,9 @@ getPPC64MemLockLimitBytes(virDomainDefPtr def)
+     unsigned long long maxMemory = 0;
+     unsigned long long passthroughLimit = 0;
+     size_t i, nPCIHostBridges = 0;
++    virPCIDeviceAddressPtr pciAddr;
+     bool usesVFIO = false;
++    bool nvlink2Capable = false;
+ 
+     for (i = 0; i < def->ncontrollers; i++) {
+         virDomainControllerDefPtr cont = def->controllers[i];
+@@ -9869,7 +9871,17 @@ getPPC64MemLockLimitBytes(virDomainDefPtr def)
+             dev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI &&
+             dev->source.subsys.u.pci.backend == VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO) {
+             usesVFIO = true;
+-            break;
++
++            pciAddr = &dev->source.subsys.u.pci.addr;
++            if (virPCIDeviceAddressIsValid(pciAddr, false)) {
++                VIR_AUTOFREE(char *) pciAddrStr = NULL;
++
++                pciAddrStr = virDomainPCIAddressAsString(pciAddr);
++                if (ppc64VFIODeviceIsNV2Bridge(pciAddrStr)) {
++                    nvlink2Capable = true;
++                    break;
++                }
++            }
+         }
+     }
+ 
+@@ -9896,29 +9908,59 @@ getPPC64MemLockLimitBytes(virDomainDefPtr def)
+                 4096 * nPCIHostBridges +
+                 8192;
+ 
+-    /* passthroughLimit := max( 2 GiB * #PHBs,                       (c)
+-     *                          memory                               (d)
+-     *                          + memory * 1/512 * #PHBs + 8 MiB )   (e)
++    /* NVLink2 support in QEMU is a special case of the passthrough
++     * mechanics explained in the usesVFIO case below. The GPU RAM
++     * is placed with a gap after maxMemory. The current QEMU
++     * implementation puts the NVIDIA RAM above the PCI MMIO, which
++     * starts at 32TiB and is the MMIO reserved for the guest main RAM.
+      *
+-     * (c) is the pre-DDW VFIO DMA window accounting. We're allowing 2 GiB
+-     * rather than 1 GiB
++     * This window ends at 64TiB, and this is where the GPUs are being
++     * placed. The next available window size is at 128TiB, and
++     * 64TiB..128TiB will fit all possible NVIDIA GPUs.
+      *
+-     * (d) is the with-DDW (and memory pre-registration and related
+-     * features) DMA window accounting - assuming that we only account RAM
+-     * once, even if mapped to multiple PHBs
++     * The same assumption as the most common case applies here:
++     * the guest will request a 64-bit DMA window, per PHB, that is
++     * big enough to map all its RAM, which is now at 128TiB due
++     * to the GPUs.
+      *
+-     * (e) is the with-DDW userspace view and overhead for the 64-bit DMA
+-     * window. This is based a bit on expected guest behaviour, but there
+-     * really isn't a way to completely avoid that. We assume the guest
+-     * requests a 64-bit DMA window (per PHB) just big enough to map all
+-     * its RAM. 4 kiB page size gives the 1/512; it will be less with 64
+-     * kiB pages, less still if the guest is mapped with hugepages (unlike
+-     * the default 32-bit DMA window, DDW windows can use large IOMMU
+-     * pages). 8 MiB is for second and further level overheads, like (b) */
+-    if (usesVFIO)
++     * Note that the NVIDIA RAM window must be accounted for the TCE
++     * table size, but *not* for the main RAM (maxMemory). This gives
++     * us the following passthroughLimit for the NVLink2 case:
++     *
++     * passthroughLimit = maxMemory +
++     *                    128TiB/512KiB * #PHBs + 8 MiB */
++    if (nvlink2Capable) {
++        passthroughLimit = maxMemory +
++                           128 * (1ULL<<30) / 512 * nPCIHostBridges +
++                           8192;
++    } else if (usesVFIO) {
++        /* For regular (non-NVLink2 present) VFIO passthrough, the value
++         * of passthroughLimit is:
++         *
++         * passthroughLimit := max( 2 GiB * #PHBs,                       (c)
++         *                          memory                               (d)
++         *                          + memory * 1/512 * #PHBs + 8 MiB )   (e)
++         *
++         * (c) is the pre-DDW VFIO DMA window accounting. We're allowing 2
++         * GiB rather than 1 GiB
++         *
++         * (d) is the with-DDW (and memory pre-registration and related
++         * features) DMA window accounting - assuming that we only account
++         * RAM once, even if mapped to multiple PHBs
++         *
++         * (e) is the with-DDW userspace view and overhead for the 64-bit
++         * DMA window. This is based a bit on expected guest behaviour, but
++         * there really isn't a way to completely avoid that. We assume the
++         * guest requests a 64-bit DMA window (per PHB) just big enough to
++         * map all its RAM. 4 kiB page size gives the 1/512; it will be
++         * less with 64 kiB pages, less still if the guest is mapped with
++         * hugepages (unlike the default 32-bit DMA window, DDW windows
++         * can use large IOMMU pages). 8 MiB is for second and further level
++         * overheads, like (b) */
+         passthroughLimit = MAX(2 * 1024 * 1024 * nPCIHostBridges,
+                                memory +
+                                memory / 512 * nPCIHostBridges + 8192);
++    }
+ 
+     memKB = baseLimit + passthroughLimit;
+ 
+-- 
+2.21.0
+
diff --git a/SOURCES/libvirt-Revert-Separate-out-StateAutoStart-from-StateInitialize.patch b/SOURCES/libvirt-Revert-Separate-out-StateAutoStart-from-StateInitialize.patch
new file mode 100644
index 0000000..abec5aa
--- /dev/null
+++ b/SOURCES/libvirt-Revert-Separate-out-StateAutoStart-from-StateInitialize.patch
@@ -0,0 +1,93 @@
+From 8069bb50b2548acd3f2176499ede205e6099c067 Mon Sep 17 00:00:00 2001
+Message-Id: <8069bb50b2548acd3f2176499ede205e6099c067@dist-git>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Thu, 27 Jun 2019 15:18:17 +0200
+Subject: [PATCH] Revert "Separate out StateAutoStart from StateInitialize"
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This reverts commit e4a969092bda5b3b952963fdf6658895165040b7.
+
+Now that drivers may call virConnectOpen() on secondary drivers, it
+doesn't make much sense to have autostart separated from driver
+initialization callback. In fact, it creates a problem because one
+driver during its initialization might try to fetch an object from
+another driver but since the object is yet to be autostarted the fetch
+fails. This has been observed in reality: qemu driver performs
+qemuProcessReconnect() during qemu's stateInitialize phase which may
+call virDomainDiskTranslateSourcePool() which connects to the storage
+driver to look up the volume. But the storage driver did not autostart
+its pools yet therefore volume lookup fails and the domain is killed.
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit 07a9c8bae8b80ef1650e6d05869cbf55c6aea837)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1685151
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Message-Id: <4ed5f8f4edd0053cc14f4bb579a945b606b36f5a.1561641375.git.mprivozn@redhat.com>
+Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/driver-state.h |  4 ----
+ src/libvirt.c      | 14 +-------------
+ 2 files changed, 1 insertion(+), 17 deletions(-)
+
+diff --git a/src/driver-state.h b/src/driver-state.h
+index 1cb3e4faf3..e1e060bcc5 100644
+--- a/src/driver-state.h
++++ b/src/driver-state.h
+@@ -30,9 +30,6 @@ typedef int
+                          virStateInhibitCallback callback,
+                          void *opaque);
+ 
+-typedef void
+-(*virDrvStateAutoStart)(void);
+-
+ typedef int
+ (*virDrvStateCleanup)(void);
+ 
+@@ -48,7 +45,6 @@ typedef virStateDriver *virStateDriverPtr;
+ struct _virStateDriver {
+     const char *name;
+     virDrvStateInitialize stateInitialize;
+-    virDrvStateAutoStart stateAutoStart;
+     virDrvStateCleanup stateCleanup;
+     virDrvStateReload stateReload;
+     virDrvStateStop stateStop;
+diff --git a/src/libvirt.c b/src/libvirt.c
+index 52f4dd2808..c9e5f47fd4 100644
+--- a/src/libvirt.c
++++ b/src/libvirt.c
+@@ -637,11 +637,7 @@ virRegisterStateDriver(virStateDriverPtr driver)
+  * @callback: callback to invoke to inhibit shutdown of the daemon
+  * @opaque: data to pass to @callback
+  *
+- * Initialize all virtualization drivers. Accomplished in two phases,
+- * the first being state and structure initialization followed by any
+- * auto start supported by the driver.  This is done to ensure dependencies
+- * that some drivers may have on another driver having been initialized
+- * will exist, such as the storage driver's need to use the secret driver.
++ * Initialize all virtualization drivers.
+  *
+  * Returns 0 if all succeed, -1 upon any failure.
+  */
+@@ -669,14 +665,6 @@ virStateInitialize(bool privileged,
+             }
+         }
+     }
+-
+-    for (i = 0; i < virStateDriverTabCount; i++) {
+-        if (virStateDriverTab[i]->stateAutoStart) {
+-            VIR_DEBUG("Running global auto start for %s state driver",
+-                      virStateDriverTab[i]->name);
+-            virStateDriverTab[i]->stateAutoStart();
+-        }
+-    }
+     return 0;
+ }
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-Revert-util-vircgroup-pass-parent-cgroup-into-virCgroupDetectControllersCB.patch b/SOURCES/libvirt-Revert-util-vircgroup-pass-parent-cgroup-into-virCgroupDetectControllersCB.patch
new file mode 100644
index 0000000..796cc2e
--- /dev/null
+++ b/SOURCES/libvirt-Revert-util-vircgroup-pass-parent-cgroup-into-virCgroupDetectControllersCB.patch
@@ -0,0 +1,108 @@
+From 2395bf301cf76ffa863a3c2e125d52345cfbf6b5 Mon Sep 17 00:00:00 2001
+Message-Id: <2395bf301cf76ffa863a3c2e125d52345cfbf6b5@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:08:23 +0200
+Subject: [PATCH] Revert "util: vircgroup: pass parent cgroup into
+ virCgroupDetectControllersCB"
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This reverts commit 7bca1c9bdc85247446129f856e27c80a32819e17.
+
+As it turns out it's not a good idea on systemd hosts.  The root
+cgroup can have all controllers enabled but they don't have to be
+enabled for sub-cgroups.
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit d117431143d5b6dcfc8fae4a6b3fae23881d0937)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <754b0ac5a0f1bd21e79eaeb71f6d2ab811446168.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c        |  2 +-
+ src/util/vircgroupbackend.h |  3 +--
+ src/util/vircgroupv1.c      |  3 +--
+ src/util/vircgroupv2.c      | 17 ++++++-----------
+ 4 files changed, 9 insertions(+), 16 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index ff2a0b75b5..a7fb595bce 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -412,7 +412,7 @@ virCgroupDetect(virCgroupPtr group,
+ 
+     for (i = 0; i < VIR_CGROUP_BACKEND_TYPE_LAST; i++) {
+         if (group->backends[i]) {
+-            int rc = group->backends[i]->detectControllers(group, controllers, parent);
++            int rc = group->backends[i]->detectControllers(group, controllers);
+             if (rc < 0)
+                 return -1;
+             controllersAvailable |= rc;
+diff --git a/src/util/vircgroupbackend.h b/src/util/vircgroupbackend.h
+index 05af118ec1..a825dc4be7 100644
+--- a/src/util/vircgroupbackend.h
++++ b/src/util/vircgroupbackend.h
+@@ -96,8 +96,7 @@ typedef char *
+ 
+ typedef int
+ (*virCgroupDetectControllersCB)(virCgroupPtr group,
+-                                int controllers,
+-                                virCgroupPtr parent);
++                                int controllers);
+ 
+ typedef bool
+ (*virCgroupHasControllerCB)(virCgroupPtr cgroup,
+diff --git a/src/util/vircgroupv1.c b/src/util/vircgroupv1.c
+index 5b218c7f78..58bd20d636 100644
+--- a/src/util/vircgroupv1.c
++++ b/src/util/vircgroupv1.c
+@@ -419,8 +419,7 @@ virCgroupV1StealPlacement(virCgroupPtr group)
+ 
+ static int
+ virCgroupV1DetectControllers(virCgroupPtr group,
+-                             int controllers,
+-                             virCgroupPtr parent ATTRIBUTE_UNUSED)
++                             int controllers)
+ {
+     size_t i;
+     size_t j;
+diff --git a/src/util/vircgroupv2.c b/src/util/vircgroupv2.c
+index bdeab397a3..b0ed889cc8 100644
+--- a/src/util/vircgroupv2.c
++++ b/src/util/vircgroupv2.c
+@@ -285,21 +285,16 @@ virCgroupV2ParseControllersFile(virCgroupPtr group)
+ 
+ static int
+ virCgroupV2DetectControllers(virCgroupPtr group,
+-                             int controllers,
+-                             virCgroupPtr parent)
++                             int controllers)
+ {
+     size_t i;
+ 
+-    if (parent) {
+-        group->unified.controllers = parent->unified.controllers;
+-    } else {
+-        if (virCgroupV2ParseControllersFile(group) < 0)
+-            return -1;
++    if (virCgroupV2ParseControllersFile(group) < 0)
++        return -1;
+ 
+-        /* In cgroup v2 there is no cpuacct controller, the cpu.stat file always
+-         * exists with usage stats. */
+-        group->unified.controllers |= 1 << VIR_CGROUP_CONTROLLER_CPUACCT;
+-    }
++    /* In cgroup v2 there is no cpuacct controller, the cpu.stat file always
++     * exists with usage stats. */
++    group->unified.controllers |= 1 << VIR_CGROUP_CONTROLLER_CPUACCT;
+ 
+     if (controllers >= 0)
+         group->unified.controllers &= controllers;
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-Revert-virStateDriver-Separate-AutoStart-from-Initialize.patch b/SOURCES/libvirt-Revert-virStateDriver-Separate-AutoStart-from-Initialize.patch
new file mode 100644
index 0000000..45fdd94
--- /dev/null
+++ b/SOURCES/libvirt-Revert-virStateDriver-Separate-AutoStart-from-Initialize.patch
@@ -0,0 +1,295 @@
+From 799c9dd37390878a54be303b3e3e27445049bf2b Mon Sep 17 00:00:00 2001
+Message-Id: <799c9dd37390878a54be303b3e3e27445049bf2b@dist-git>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Thu, 27 Jun 2019 15:18:16 +0200
+Subject: [PATCH] Revert "virStateDriver - Separate AutoStart from Initialize"
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This reverts commit cefb97fb815c81fc882da752f45effd23bcb9b4b.
+
+The stateAutoStart callback will be removed in the next commit.
+Therefore move autostarting of domains, networks and storage
+pools back into stateInitialize callbacks.
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit fc380c2e018ae15347d4c281a7e74896c48cac4a)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1685151
+
+The difference to the upstream commit is uml driver change. In
+upstream, the uml driver was dropped, but it's still kept around
+in downstream.
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Message-Id: <a8e69f65b397c81c2a68597cca6c8ac04df24153.1561641375.git.mprivozn@redhat.com>
+Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/libxl/libxl_driver.c     | 14 +++-----------
+ src/lxc/lxc_driver.c         | 16 ++--------------
+ src/network/bridge_driver.c  | 22 ++++------------------
+ src/qemu/qemu_driver.c       | 17 ++---------------
+ src/storage/storage_driver.c | 19 ++-----------------
+ src/uml/uml_driver.c         | 17 ++---------------
+ 6 files changed, 15 insertions(+), 90 deletions(-)
+
+diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c
+index 5a5e792957..99bb010af4 100644
+--- a/src/libxl/libxl_driver.c
++++ b/src/libxl/libxl_driver.c
+@@ -773,6 +773,9 @@ libxlStateInitialize(bool privileged,
+                                        NULL, NULL) < 0)
+         goto error;
+ 
++    virDomainObjListForEach(libxl_driver->domains, libxlAutostartDomain,
++                            libxl_driver);
++
+     virDomainObjListForEach(libxl_driver->domains, libxlDomainManagedSaveLoad,
+                             libxl_driver);
+ 
+@@ -784,16 +787,6 @@ libxlStateInitialize(bool privileged,
+     return -1;
+ }
+ 
+-static void
+-libxlStateAutoStart(void)
+-{
+-    if (!libxl_driver)
+-        return;
+-
+-    virDomainObjListForEach(libxl_driver->domains, libxlAutostartDomain,
+-                            libxl_driver);
+-}
+-
+ static int
+ libxlStateReload(void)
+ {
+@@ -6479,7 +6472,6 @@ static virConnectDriver libxlConnectDriver = {
+ static virStateDriver libxlStateDriver = {
+     .name = "LIBXL",
+     .stateInitialize = libxlStateInitialize,
+-    .stateAutoStart = libxlStateAutoStart,
+     .stateCleanup = libxlStateCleanup,
+     .stateReload = libxlStateReload,
+ };
+diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c
+index f9794e0655..527fa72083 100644
+--- a/src/lxc/lxc_driver.c
++++ b/src/lxc/lxc_driver.c
+@@ -1646,6 +1646,8 @@ static int lxcStateInitialize(bool privileged,
+                                        NULL, NULL) < 0)
+         goto cleanup;
+ 
++    virLXCProcessAutostartAll(lxc_driver);
++
+     virObjectUnref(caps);
+     return 0;
+ 
+@@ -1655,19 +1657,6 @@ static int lxcStateInitialize(bool privileged,
+     return -1;
+ }
+ 
+-/**
+- * lxcStateAutoStart:
+- *
+- * Function to autostart the LXC daemons
+- */
+-static void lxcStateAutoStart(void)
+-{
+-    if (!lxc_driver)
+-        return;
+-
+-    virLXCProcessAutostartAll(lxc_driver);
+-}
+-
+ static void lxcNotifyLoadDomain(virDomainObjPtr vm, int newVM, void *opaque)
+ {
+     virLXCDriverPtr driver = opaque;
+@@ -5550,7 +5539,6 @@ static virConnectDriver lxcConnectDriver = {
+ static virStateDriver lxcStateDriver = {
+     .name = LXC_DRIVER_NAME,
+     .stateInitialize = lxcStateInitialize,
+-    .stateAutoStart = lxcStateAutoStart,
+     .stateCleanup = lxcStateCleanup,
+     .stateReload = lxcStateReload,
+ };
+diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c
+index d153a8cdb6..a60d7db685 100644
+--- a/src/network/bridge_driver.c
++++ b/src/network/bridge_driver.c
+@@ -755,6 +755,10 @@ networkStateInitialize(bool privileged,
+     networkReloadFirewallRules(network_driver);
+     networkRefreshDaemons(network_driver);
+ 
++    virNetworkObjListForEach(network_driver->networks,
++                             networkAutostartConfig,
++                             network_driver);
++
+     network_driver->networkEventState = virObjectEventStateNew();
+ 
+ #ifdef WITH_FIREWALLD
+@@ -794,23 +798,6 @@ networkStateInitialize(bool privileged,
+ }
+ 
+ 
+-/**
+- * networkStateAutoStart:
+- *
+- * Function to AutoStart the bridge configs
+- */
+-static void
+-networkStateAutoStart(void)
+-{
+-    if (!network_driver)
+-        return;
+-
+-    virNetworkObjListForEach(network_driver->networks,
+-                             networkAutostartConfig,
+-                             network_driver);
+-}
+-
+-
+ /**
+  * networkStateReload:
+  *
+@@ -5616,7 +5603,6 @@ static virConnectDriver networkConnectDriver = {
+ static virStateDriver networkStateDriver = {
+     .name = "bridge",
+     .stateInitialize  = networkStateInitialize,
+-    .stateAutoStart  = networkStateAutoStart,
+     .stateCleanup = networkStateCleanup,
+     .stateReload = networkStateReload,
+ };
+diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
+index 2da87992fd..056d324a62 100644
+--- a/src/qemu/qemu_driver.c
++++ b/src/qemu/qemu_driver.c
+@@ -911,6 +911,8 @@ qemuStateInitialize(bool privileged,
+ 
+     qemuProcessReconnectAll(qemu_driver);
+ 
++    qemuAutostartDomains(qemu_driver);
++
+     return 0;
+ 
+  error:
+@@ -921,20 +923,6 @@ qemuStateInitialize(bool privileged,
+     return -1;
+ }
+ 
+-/**
+- * qemuStateAutoStart:
+- *
+- * Function to auto start the QEMU daemons
+- */
+-static void
+-qemuStateAutoStart(void)
+-{
+-    if (!qemu_driver)
+-        return;
+-
+-    qemuAutostartDomains(qemu_driver);
+-}
+-
+ static void qemuNotifyLoadDomain(virDomainObjPtr vm, int newVM, void *opaque)
+ {
+     virQEMUDriverPtr driver = opaque;
+@@ -21846,7 +21834,6 @@ static virConnectDriver qemuConnectDriver = {
+ static virStateDriver qemuStateDriver = {
+     .name = QEMU_DRIVER_NAME,
+     .stateInitialize = qemuStateInitialize,
+-    .stateAutoStart = qemuStateAutoStart,
+     .stateCleanup = qemuStateCleanup,
+     .stateReload = qemuStateReload,
+     .stateStop = qemuStateStop,
+diff --git a/src/storage/storage_driver.c b/src/storage/storage_driver.c
+index 254818e308..f61fb074e6 100644
+--- a/src/storage/storage_driver.c
++++ b/src/storage/storage_driver.c
+@@ -291,6 +291,8 @@ storageStateInitialize(bool privileged,
+ 
+     storagePoolUpdateAllState();
+ 
++    storageDriverAutostart();
++
+     driver->storageEventState = virObjectEventStateNew();
+ 
+     storageDriverUnlock();
+@@ -307,22 +309,6 @@ storageStateInitialize(bool privileged,
+     goto cleanup;
+ }
+ 
+-/**
+- * storageStateAutoStart:
+- *
+- * Function to auto start the storage driver
+- */
+-static void
+-storageStateAutoStart(void)
+-{
+-    if (!driver)
+-        return;
+-
+-    storageDriverLock();
+-    storageDriverAutostart();
+-    storageDriverUnlock();
+-}
+-
+ /**
+  * storageStateReload:
+  *
+@@ -2843,7 +2829,6 @@ static virConnectDriver storageConnectDriver = {
+ static virStateDriver stateDriver = {
+     .name = "storage",
+     .stateInitialize = storageStateInitialize,
+-    .stateAutoStart = storageStateAutoStart,
+     .stateCleanup = storageStateCleanup,
+     .stateReload = storageStateReload,
+ };
+diff --git a/src/uml/uml_driver.c b/src/uml/uml_driver.c
+index c77988f01e..296adf55d1 100644
+--- a/src/uml/uml_driver.c
++++ b/src/uml/uml_driver.c
+@@ -575,6 +575,8 @@ umlStateInitialize(bool privileged,
+ 
+     umlDriverUnlock(uml_driver);
+ 
++    umlAutostartConfigs(uml_driver);
++
+     VIR_FREE(userdir);
+ 
+     return 0;
+@@ -590,20 +592,6 @@ umlStateInitialize(bool privileged,
+     return -1;
+ }
+ 
+-/**
+- * umlStateAutoStart:
+- *
+- * Function to autostart the Uml daemons
+- */
+-static void
+-umlStateAutoStart(void)
+-{
+-    if (!uml_driver)
+-        return;
+-
+-    umlAutostartConfigs(uml_driver);
+-}
+-
+ static void umlNotifyLoadDomain(virDomainObjPtr vm, int newVM, void *opaque)
+ {
+     struct uml_driver *driver = opaque;
+@@ -2826,7 +2814,6 @@ static virConnectDriver umlConnectDriver = {
+ static virStateDriver umlStateDriver = {
+     .name = "UML",
+     .stateInitialize = umlStateInitialize,
+-    .stateAutoStart = umlStateAutoStart,
+     .stateCleanup = umlStateCleanup,
+     .stateReload = umlStateReload,
+ };
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-Revert-vircgroup-cleanup-controllers-not-managed-by-systemd-on-error.patch b/SOURCES/libvirt-Revert-vircgroup-cleanup-controllers-not-managed-by-systemd-on-error.patch
new file mode 100644
index 0000000..44f72a9
--- /dev/null
+++ b/SOURCES/libvirt-Revert-vircgroup-cleanup-controllers-not-managed-by-systemd-on-error.patch
@@ -0,0 +1,83 @@
+From ddea95c1c2e32c6454c89aa83d78b26a83564cd4 Mon Sep 17 00:00:00 2001
+Message-Id: <ddea95c1c2e32c6454c89aa83d78b26a83564cd4@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:07:11 +0200
+Subject: [PATCH] Revert "vircgroup: cleanup controllers not managed by systemd
+ on error"
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This reverts commit 1602aa28f820ada66f707cef3e536e8572fbda1e.
+
+There is no need to call virCgroupRemove() nor virCgroupFree() if
+virCgroupEnableMissingControllers() fails because it will not modify
+'group' at all.
+
+The cleanup of directories is done in virCgroupMakeGroup().
+
+Reviewed-by: John Ferlan <jferlan@redhat.com>
+Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
+Reviewed-by: Marc Hartmayer <mhartmay@linux.ibm.com>
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 199eee6aae7af3d813fbe98660c7e0fa1a8ae7b7)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <53288dd310e0305ac3179693e64684eb8b3a31ab.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c | 25 ++++++++++---------------
+ 1 file changed, 10 insertions(+), 15 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index a376b9b89a..7ec1399bc6 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -1059,7 +1059,6 @@ virCgroupNewMachineSystemd(const char *name,
+     int rv;
+     virCgroupPtr init;
+     VIR_AUTOFREE(char *) path = NULL;
+-    virErrorPtr saved = NULL;
+ 
+     VIR_DEBUG("Trying to setup machine '%s' via systemd", name);
+     if ((rv = virSystemdCreateMachine(name,
+@@ -1092,24 +1091,20 @@ virCgroupNewMachineSystemd(const char *name,
+ 
+     if (virCgroupEnableMissingControllers(path, pidleader,
+                                           controllers, group) < 0) {
+-        goto error;
++        return -1;
+     }
+ 
+-    if (virCgroupAddProcess(*group, pidleader) < 0)
+-        goto error;
++    if (virCgroupAddProcess(*group, pidleader) < 0) {
++        virErrorPtr saved = virSaveLastError();
++        virCgroupRemove(*group);
++        virCgroupFree(group);
++        if (saved) {
++            virSetError(saved);
++            virFreeError(saved);
++        }
++    }
+ 
+     return 0;
+-
+- error:
+-    saved = virSaveLastError();
+-    virCgroupRemove(*group);
+-    virCgroupFree(group);
+-    if (saved) {
+-        virSetError(saved);
+-        virFreeError(saved);
+-    }
+-
+-    return -1;
+ }
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-admin-reject-clients-unless-their-UID-matches-the-current-UID.patch b/SOURCES/libvirt-admin-reject-clients-unless-their-UID-matches-the-current-UID.patch
index 936e3ce..a6c1113 100644
--- a/SOURCES/libvirt-admin-reject-clients-unless-their-UID-matches-the-current-UID.patch
+++ b/SOURCES/libvirt-admin-reject-clients-unless-their-UID-matches-the-current-UID.patch
@@ -1,5 +1,5 @@
-From 5ed86f689f011c36e8008c30dc3dfe89bfbf280a Mon Sep 17 00:00:00 2001
-Message-Id: <5ed86f689f011c36e8008c30dc3dfe89bfbf280a@dist-git>
+From 3eaa16967f0546c5d1596bb6c36767cbe01040b9 Mon Sep 17 00:00:00 2001
+Message-Id: <3eaa16967f0546c5d1596bb6c36767cbe01040b9@dist-git>
 From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= <berrange@redhat.com>
 Date: Wed, 15 May 2019 21:40:56 +0100
 Subject: [PATCH] admin: reject clients unless their UID matches the current
@@ -16,7 +16,7 @@ Fixes CVE-2019-10132
 
 Reviewed-by: Ján Tomko <jtomko@redhat.com>
 Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
-(cherry picked from a private commit)
+(cherry picked from commit 96f41cd765c9e525fe28ee5abbfbf4a79b3720c7)
 Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
 Message-Id: <20190515204058.28077-2-berrange@redhat.com>
 ---
@@ -57,5 +57,5 @@ index b78ff902c0..9f25813ae3 100644
      if (VIR_ALLOC(priv) < 0)
          return NULL;
 -- 
-2.21.0
+2.22.0
 
diff --git a/SOURCES/libvirt-api-disallow-virConnect-HypervisorCPU-on-read-only-connections.patch b/SOURCES/libvirt-api-disallow-virConnect-HypervisorCPU-on-read-only-connections.patch
index 0f182be..70eecbc 100644
--- a/SOURCES/libvirt-api-disallow-virConnect-HypervisorCPU-on-read-only-connections.patch
+++ b/SOURCES/libvirt-api-disallow-virConnect-HypervisorCPU-on-read-only-connections.patch
@@ -1,5 +1,5 @@
-From 80850486e791a69a4cd58851617f321b84f7c178 Mon Sep 17 00:00:00 2001
-Message-Id: <80850486e791a69a4cd58851617f321b84f7c178@dist-git>
+From bab30af2d83e27d9141545cb9dcff51924e52b4d Mon Sep 17 00:00:00 2001
+Message-Id: <bab30af2d83e27d9141545cb9dcff51924e52b4d@dist-git>
 From: =?UTF-8?q?J=C3=A1n=20Tomko?= <jtomko@redhat.com>
 Date: Tue, 18 Jun 2019 13:30:02 +0200
 Subject: [PATCH] api: disallow virConnect*HypervisorCPU on read-only
diff --git a/SOURCES/libvirt-api-disallow-virConnectGetDomainCapabilities-on-read-only-connections.patch b/SOURCES/libvirt-api-disallow-virConnectGetDomainCapabilities-on-read-only-connections.patch
index b04e5f4..6815a55 100644
--- a/SOURCES/libvirt-api-disallow-virConnectGetDomainCapabilities-on-read-only-connections.patch
+++ b/SOURCES/libvirt-api-disallow-virConnectGetDomainCapabilities-on-read-only-connections.patch
@@ -1,5 +1,5 @@
-From b77317482326f31c796e16bda24c1eb344be2d21 Mon Sep 17 00:00:00 2001
-Message-Id: <b77317482326f31c796e16bda24c1eb344be2d21@dist-git>
+From 2b0e20b240848c84932aa549e8ec2b6e0a5646fa Mon Sep 17 00:00:00 2001
+Message-Id: <2b0e20b240848c84932aa549e8ec2b6e0a5646fa@dist-git>
 From: =?UTF-8?q?J=C3=A1n=20Tomko?= <jtomko@redhat.com>
 Date: Tue, 18 Jun 2019 13:30:01 +0200
 Subject: [PATCH] api: disallow virConnectGetDomainCapabilities on read-only
diff --git a/SOURCES/libvirt-api-disallow-virDomainManagedSaveDefineXML-on-read-only-connections.patch b/SOURCES/libvirt-api-disallow-virDomainManagedSaveDefineXML-on-read-only-connections.patch
index 461c8f6..c02b5b9 100644
--- a/SOURCES/libvirt-api-disallow-virDomainManagedSaveDefineXML-on-read-only-connections.patch
+++ b/SOURCES/libvirt-api-disallow-virDomainManagedSaveDefineXML-on-read-only-connections.patch
@@ -1,5 +1,5 @@
-From 2f8042cc71d65391e702c48f4e5e9dd38811cf4a Mon Sep 17 00:00:00 2001
-Message-Id: <2f8042cc71d65391e702c48f4e5e9dd38811cf4a@dist-git>
+From 0673d5b707d68562732b78c89fe339e8558f8496 Mon Sep 17 00:00:00 2001
+Message-Id: <0673d5b707d68562732b78c89fe339e8558f8496@dist-git>
 From: =?UTF-8?q?J=C3=A1n=20Tomko?= <jtomko@redhat.com>
 Date: Tue, 18 Jun 2019 13:30:00 +0200
 Subject: [PATCH] api: disallow virDomainManagedSaveDefineXML on read-only
diff --git a/SOURCES/libvirt-api-disallow-virDomainSaveImageGetXMLDesc-on-read-only-connections.patch b/SOURCES/libvirt-api-disallow-virDomainSaveImageGetXMLDesc-on-read-only-connections.patch
index f0ee792..f2ec040 100644
--- a/SOURCES/libvirt-api-disallow-virDomainSaveImageGetXMLDesc-on-read-only-connections.patch
+++ b/SOURCES/libvirt-api-disallow-virDomainSaveImageGetXMLDesc-on-read-only-connections.patch
@@ -1,5 +1,5 @@
-From d5b7ada5278e175d3174a6bcdc4338684ae4376e Mon Sep 17 00:00:00 2001
-Message-Id: <d5b7ada5278e175d3174a6bcdc4338684ae4376e@dist-git>
+From 8533d820c378ae31176922703b7368f586a59bc0 Mon Sep 17 00:00:00 2001
+Message-Id: <8533d820c378ae31176922703b7368f586a59bc0@dist-git>
 From: =?UTF-8?q?J=C3=A1n=20Tomko?= <jtomko@redhat.com>
 Date: Tue, 18 Jun 2019 13:29:59 +0200
 Subject: [PATCH] api: disallow virDomainSaveImageGetXMLDesc on read-only
diff --git a/SOURCES/libvirt-bhyve-Move-autostarting-of-domains-into-bhyveStateInitialize.patch b/SOURCES/libvirt-bhyve-Move-autostarting-of-domains-into-bhyveStateInitialize.patch
new file mode 100644
index 0000000..2f0f16b
--- /dev/null
+++ b/SOURCES/libvirt-bhyve-Move-autostarting-of-domains-into-bhyveStateInitialize.patch
@@ -0,0 +1,65 @@
+From a26ad1b57617abc4de8a0d13716b898d311ee01e Mon Sep 17 00:00:00 2001
+Message-Id: <a26ad1b57617abc4de8a0d13716b898d311ee01e@dist-git>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Thu, 27 Jun 2019 15:18:15 +0200
+Subject: [PATCH] bhyve: Move autostarting of domains into bhyveStateInitialize
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The stateAutoStart callback will go away shortly. Therefore, move
+the autostart call into state initialize callback.
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit 31c3c35c940010a793fea8351751bb04fab1a6d4)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1685151
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Message-Id: <1a93e2bef531c11190c652fcfb73b568ee73e487.1561641375.git.mprivozn@redhat.com>
+Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/bhyve/bhyve_driver.c | 12 ++----------
+ 1 file changed, 2 insertions(+), 10 deletions(-)
+
+diff --git a/src/bhyve/bhyve_driver.c b/src/bhyve/bhyve_driver.c
+index 9284b51783..ec016ecc0c 100644
+--- a/src/bhyve/bhyve_driver.c
++++ b/src/bhyve/bhyve_driver.c
+@@ -1270,6 +1270,8 @@ bhyveStateInitialize(bool privileged,
+ 
+     virBhyveProcessReconnectAll(bhyve_driver);
+ 
++    bhyveAutostartDomains(bhyve_driver);
++
+     return 0;
+ 
+  cleanup:
+@@ -1297,15 +1299,6 @@ bhyveDriverGetGrubCaps(virConnectPtr conn)
+     return 0;
+ }
+ 
+-static void
+-bhyveStateAutoStart(void)
+-{
+-    if (!bhyve_driver)
+-        return;
+-
+-    bhyveAutostartDomains(bhyve_driver);
+-}
+-
+ static int
+ bhyveConnectGetMaxVcpus(virConnectPtr conn,
+                         const char *type)
+@@ -1713,7 +1706,6 @@ static virConnectDriver bhyveConnectDriver = {
+ static virStateDriver bhyveStateDriver = {
+     .name = "bhyve",
+     .stateInitialize = bhyveStateInitialize,
+-    .stateAutoStart = bhyveStateAutoStart,
+     .stateCleanup = bhyveStateCleanup,
+ };
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-conf-Add-definitions-for-uid-and-fid-PCI-address-attributes.patch b/SOURCES/libvirt-conf-Add-definitions-for-uid-and-fid-PCI-address-attributes.patch
new file mode 100644
index 0000000..17eb235
--- /dev/null
+++ b/SOURCES/libvirt-conf-Add-definitions-for-uid-and-fid-PCI-address-attributes.patch
@@ -0,0 +1,67 @@
+From dd083516c7057ee50e59290643634156daf0773b Mon Sep 17 00:00:00 2001
+Message-Id: <dd083516c7057ee50e59290643634156daf0773b@dist-git>
+From: Yi Min Zhao <zyimin@linux.ibm.com>
+Date: Mon, 8 Apr 2019 10:57:18 +0200
+Subject: [PATCH] conf: Add definitions for 'uid' and 'fid' PCI address
+ attributes
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Add zPCI definitions in preparation of extending the PCI address
+with parameters uid (user-defined identifier) and fid (PCI function
+identifier).
+
+Signed-off-by: Yi Min Zhao <zyimin@linux.ibm.com>
+Reviewed-by: Boris Fiuczynski <fiuczy@linux.ibm.com>
+Reviewed-by: Stefan Zimmermann <stzi@linux.ibm.com>
+Reviewed-by: Bjoern Walk <bwalk@linux.ibm.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Reviewed-by: Andrea Bolognani <abologna@redhat.com>
+
+(cherry-picked from commit 30522c78c11d9ff6c6c177dfca4a0da8057095fe)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1508149
+
+Signed-off-by: Andrea Bolognani <abologna@redhat.com>
+Message-Id: <20190408085732.28684-2-abologna@redhat.com>
+Reviewed-by: Laine Stump <laine@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ cfg.mk            | 1 +
+ src/util/virpci.h | 7 +++++++
+ 2 files changed, 8 insertions(+)
+
+diff --git a/cfg.mk b/cfg.mk
+index e3e94bf6f0..7fd2b1dcb6 100644
+--- a/cfg.mk
++++ b/cfg.mk
+@@ -472,6 +472,7 @@ sc_prohibit_canonicalize_file_name:
+ # Insist on correct types for [pug]id.
+ sc_correct_id_types:
+ 	@prohibit='\<(int|long) *[pug]id\>' \
++	exclude='exempt from syntax-check' \
+ 	halt='use pid_t for pid, uid_t for uid, gid_t for gid' \
+ 	  $(_sc_search_regexp)
+ 
+diff --git a/src/util/virpci.h b/src/util/virpci.h
+index 794b7e59db..01df652b86 100644
+--- a/src/util/virpci.h
++++ b/src/util/virpci.h
+@@ -36,6 +36,13 @@ typedef virPCIDeviceAddress *virPCIDeviceAddressPtr;
+ typedef struct _virPCIDeviceList virPCIDeviceList;
+ typedef virPCIDeviceList *virPCIDeviceListPtr;
+ 
++typedef struct _virZPCIDeviceAddress virZPCIDeviceAddress;
++typedef virZPCIDeviceAddress *virZPCIDeviceAddressPtr;
++struct _virZPCIDeviceAddress {
++    unsigned int uid; /* exempt from syntax-check */
++    unsigned int fid;
++};
++
+ struct _virPCIDeviceAddress {
+     unsigned int domain;
+     unsigned int bus;
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-conf-Allocate-release-uid-and-fid-in-PCI-address.patch b/SOURCES/libvirt-conf-Allocate-release-uid-and-fid-in-PCI-address.patch
new file mode 100644
index 0000000..d99def9
--- /dev/null
+++ b/SOURCES/libvirt-conf-Allocate-release-uid-and-fid-in-PCI-address.patch
@@ -0,0 +1,527 @@
+From 87e3a5f2f797c79516a560ddc224074c834ef528 Mon Sep 17 00:00:00 2001
+Message-Id: <87e3a5f2f797c79516a560ddc224074c834ef528@dist-git>
+From: Yi Min Zhao <zyimin@linux.ibm.com>
+Date: Mon, 8 Apr 2019 10:57:27 +0200
+Subject: [PATCH] conf: Allocate/release 'uid' and 'fid' in PCI address
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This patch adds new functions for reservation, assignment and release
+to handle the uid/fid. If the uid/fid is defined in the domain XML,
+they will be reserved directly in the collecting phase. If any of them
+is not defined, we will find out an available value for them from the
+zPCI address hashtable, and reserve them. For the hotplug case there
+might not be a zPCI definition. So allocate and reserve uid/fid the
+case. Assign if needed and reserve uid/fid for the defined case.
+
+Signed-off-by: Yi Min Zhao <zyimin@linux.ibm.com>
+Reviewed-by: Bjoern Walk <bwalk@linux.ibm.com>
+Reviewed-by: Boris Fiuczynski <fiuczy@linux.ibm.com>
+Reviewed-by: Andrea Bolognani <abologna@redhat.com>
+
+(cherry picked from commit f183b87fc1dbcc6446ac3c1cef9cdd345b9725fb)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1508149
+
+Conflicts:
+
+  * src/libvirt_private.syms
+    + several symbols are not present in the list
+      - missing 9ad119f4db5, ab3f781a10c, edeef779585, b899726faa5
+
+  * src/qemu/qemu_domain_address.c
+    + the old name for virDeviceInfoPCIAddressIsPresent() is used
+      - missing 76151a53a100
+
+Signed-off-by: Andrea Bolognani <abologna@redhat.com>
+Message-Id: <20190408085732.28684-11-abologna@redhat.com>
+Reviewed-by: Laine Stump <laine@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/conf/device_conf.c         |  16 +++
+ src/conf/device_conf.h         |   3 +
+ src/conf/domain_addr.c         | 244 +++++++++++++++++++++++++++++++++
+ src/conf/domain_addr.h         |  12 ++
+ src/libvirt_private.syms       |   5 +
+ src/qemu/qemu_domain_address.c |  59 +++++++-
+ 6 files changed, 338 insertions(+), 1 deletion(-)
+
+diff --git a/src/conf/device_conf.c b/src/conf/device_conf.c
+index cadac32603..76370d30a2 100644
+--- a/src/conf/device_conf.c
++++ b/src/conf/device_conf.c
+@@ -28,6 +28,7 @@
+ #include "viruuid.h"
+ #include "virbuffer.h"
+ #include "device_conf.h"
++#include "domain_addr.h"
+ #include "virstring.h"
+ 
+ #define VIR_FROM_THIS VIR_FROM_DEVICE
+@@ -230,6 +231,21 @@ int virPCIDeviceAddressIsValid(virPCIDeviceAddressPtr addr,
+ }
+ 
+ 
++bool
++virDeviceInfoPCIAddressExtensionIsWanted(const virDomainDeviceInfo *info)
++{
++    return (info->addr.pci.extFlags & VIR_PCI_ADDRESS_EXTENSION_ZPCI) &&
++           virZPCIDeviceAddressIsEmpty(&info->addr.pci.zpci);
++}
++
++bool
++virDeviceInfoPCIAddressExtensionIsPresent(const virDomainDeviceInfo *info)
++{
++    return (info->addr.pci.extFlags & VIR_PCI_ADDRESS_EXTENSION_ZPCI) &&
++           !virZPCIDeviceAddressIsEmpty(&info->addr.pci.zpci);
++}
++
++
+ int
+ virPCIDeviceAddressParseXML(xmlNodePtr node,
+                             virPCIDeviceAddressPtr addr)
+diff --git a/src/conf/device_conf.h b/src/conf/device_conf.h
+index c79066ec02..6bef2f093a 100644
+--- a/src/conf/device_conf.h
++++ b/src/conf/device_conf.h
+@@ -214,6 +214,9 @@ virDeviceInfoPCIAddressPresent(const virDomainDeviceInfo *info)
+        !virPCIDeviceAddressIsEmpty(&info->addr.pci);
+ }
+ 
++bool virDeviceInfoPCIAddressExtensionIsWanted(const virDomainDeviceInfo *info);
++bool virDeviceInfoPCIAddressExtensionIsPresent(const virDomainDeviceInfo *info);
++
+ int virPCIDeviceAddressParseXML(xmlNodePtr node,
+                                 virPCIDeviceAddressPtr addr);
+ 
+diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c
+index 9e0a0fdf95..a58910c394 100644
+--- a/src/conf/domain_addr.c
++++ b/src/conf/domain_addr.c
+@@ -33,6 +33,238 @@
+ 
+ VIR_LOG_INIT("conf.domain_addr");
+ 
++static int
++virDomainZPCIAddressReserveId(virHashTablePtr set,
++                              unsigned int id,
++                              const char *name)
++{
++    if (virHashLookup(set, &id)) {
++        virReportError(VIR_ERR_INTERNAL_ERROR,
++                       _("zPCI %s %o is already reserved"),
++                       name, id);
++        return -1;
++    }
++
++    if (virHashAddEntry(set, &id, (void*)1) < 0) {
++        virReportError(VIR_ERR_INTERNAL_ERROR,
++                       _("Failed to reserve %s %o"),
++                       name, id);
++        return -1;
++    }
++
++    return 0;
++}
++
++
++static int
++virDomainZPCIAddressReserveUid(virHashTablePtr set,
++                               virZPCIDeviceAddressPtr addr)
++{
++    return virDomainZPCIAddressReserveId(set, addr->uid, "uid");
++}
++
++
++static int
++virDomainZPCIAddressReserveFid(virHashTablePtr set,
++                               virZPCIDeviceAddressPtr addr)
++{
++    return virDomainZPCIAddressReserveId(set, addr->fid, "fid");
++}
++
++
++static int
++virDomainZPCIAddressAssignId(virHashTablePtr set,
++                             unsigned int *id,
++                             unsigned int min,
++                             unsigned int max,
++                             const char *name)
++{
++    while (virHashLookup(set, &min)) {
++        if (min == max) {
++            virReportError(VIR_ERR_INTERNAL_ERROR,
++                           _("There is no more free %s."),
++                           name);
++            return -1;
++        }
++        ++min;
++    }
++    *id = min;
++
++    return 0;
++}
++
++
++static int
++virDomainZPCIAddressAssignUid(virHashTablePtr set,
++                              virZPCIDeviceAddressPtr addr)
++{
++    return virDomainZPCIAddressAssignId(set, &addr->uid, 1,
++                                        VIR_DOMAIN_DEVICE_ZPCI_MAX_UID, "uid");
++}
++
++
++static int
++virDomainZPCIAddressAssignFid(virHashTablePtr set,
++                              virZPCIDeviceAddressPtr addr)
++{
++    return virDomainZPCIAddressAssignId(set, &addr->fid, 0,
++                                        VIR_DOMAIN_DEVICE_ZPCI_MAX_FID, "fid");
++}
++
++
++static void
++virDomainZPCIAddressReleaseId(virHashTablePtr set,
++                              unsigned int *id,
++                              const char *name)
++{
++    if (virHashRemoveEntry(set, id) < 0) {
++        virReportError(VIR_ERR_INTERNAL_ERROR,
++                       _("Release %s %o failed"),
++                       name, *id);
++    }
++
++    *id = 0;
++}
++
++
++static void
++virDomainZPCIAddressReleaseUid(virHashTablePtr set,
++                               virZPCIDeviceAddressPtr addr)
++{
++    virDomainZPCIAddressReleaseId(set, &addr->uid, "uid");
++}
++
++
++static void
++virDomainZPCIAddressReleaseFid(virHashTablePtr set,
++                               virZPCIDeviceAddressPtr addr)
++{
++    virDomainZPCIAddressReleaseId(set, &addr->fid, "fid");
++}
++
++
++static void
++virDomainZPCIAddressReleaseIds(virDomainZPCIAddressIdsPtr zpciIds,
++                               virZPCIDeviceAddressPtr addr)
++{
++    if (!zpciIds || virZPCIDeviceAddressIsEmpty(addr))
++        return;
++
++    virDomainZPCIAddressReleaseUid(zpciIds->uids, addr);
++
++    virDomainZPCIAddressReleaseFid(zpciIds->fids, addr);
++}
++
++
++static int
++virDomainZPCIAddressReserveNextUid(virHashTablePtr uids,
++                                   virZPCIDeviceAddressPtr zpci)
++{
++    if (virDomainZPCIAddressAssignUid(uids, zpci) < 0)
++        return -1;
++
++    if (virDomainZPCIAddressReserveUid(uids, zpci) < 0)
++        return -1;
++
++    return 0;
++}
++
++
++static int
++virDomainZPCIAddressReserveNextFid(virHashTablePtr fids,
++                                   virZPCIDeviceAddressPtr zpci)
++{
++    if (virDomainZPCIAddressAssignFid(fids, zpci) < 0)
++        return -1;
++
++    if (virDomainZPCIAddressReserveFid(fids, zpci) < 0)
++        return -1;
++
++    return 0;
++}
++
++
++static int
++virDomainZPCIAddressReserveAddr(virDomainZPCIAddressIdsPtr zpciIds,
++                                virZPCIDeviceAddressPtr addr)
++{
++    if (virDomainZPCIAddressReserveUid(zpciIds->uids, addr) < 0)
++        return -1;
++
++    if (virDomainZPCIAddressReserveFid(zpciIds->fids, addr) < 0) {
++        virDomainZPCIAddressReleaseUid(zpciIds->uids, addr);
++        return -1;
++    }
++
++    return 0;
++}
++
++
++static int
++virDomainZPCIAddressReserveNextAddr(virDomainZPCIAddressIdsPtr zpciIds,
++                                    virZPCIDeviceAddressPtr addr)
++{
++    if (virDomainZPCIAddressReserveNextUid(zpciIds->uids, addr) < 0)
++        return -1;
++
++    if (virDomainZPCIAddressReserveNextFid(zpciIds->fids, addr) < 0) {
++        virDomainZPCIAddressReleaseUid(zpciIds->uids, addr);
++        return -1;
++    }
++
++    return 0;
++}
++
++
++int
++virDomainPCIAddressExtensionReserveAddr(virDomainPCIAddressSetPtr addrs,
++                                        virPCIDeviceAddressPtr addr)
++{
++    if (addr->extFlags & VIR_PCI_ADDRESS_EXTENSION_ZPCI) {
++        /* Reserve uid/fid to ZPCI device which has defined uid/fid
++         * in the domain.
++         */
++        return virDomainZPCIAddressReserveAddr(addrs->zpciIds, &addr->zpci);
++    }
++
++    return 0;
++}
++
++
++int
++virDomainPCIAddressExtensionReserveNextAddr(virDomainPCIAddressSetPtr addrs,
++                                            virPCIDeviceAddressPtr addr)
++{
++    if (addr->extFlags & VIR_PCI_ADDRESS_EXTENSION_ZPCI) {
++        virZPCIDeviceAddress zpci = { 0 };
++
++        if (virDomainZPCIAddressReserveNextAddr(addrs->zpciIds, &zpci) < 0)
++            return -1;
++
++        if (!addrs->dryRun)
++            addr->zpci = zpci;
++    }
++
++    return 0;
++}
++
++static int
++virDomainPCIAddressExtensionEnsureAddr(virDomainPCIAddressSetPtr addrs,
++                                       virPCIDeviceAddressPtr addr)
++{
++    if (addr->extFlags & VIR_PCI_ADDRESS_EXTENSION_ZPCI) {
++        virZPCIDeviceAddressPtr zpci = &addr->zpci;
++
++        if (virZPCIDeviceAddressIsEmpty(zpci))
++            return virDomainZPCIAddressReserveNextAddr(addrs->zpciIds, zpci);
++        else
++            return virDomainZPCIAddressReserveAddr(addrs->zpciIds, zpci);
++    }
++
++    return 0;
++}
++
++
+ virDomainPCIConnectFlags
+ virDomainPCIControllerModelToConnectType(virDomainControllerModelPCI model)
+ {
+@@ -729,12 +961,24 @@ virDomainPCIAddressEnsureAddr(virDomainPCIAddressSetPtr addrs,
+         ret = virDomainPCIAddressReserveNextAddr(addrs, dev, flags, -1);
+     }
+ 
++    dev->addr.pci.extFlags = dev->pciAddrExtFlags;
++    ret = virDomainPCIAddressExtensionEnsureAddr(addrs, &dev->addr.pci);
++
+  cleanup:
+     VIR_FREE(addrStr);
+     return ret;
+ }
+ 
+ 
++void
++virDomainPCIAddressExtensionReleaseAddr(virDomainPCIAddressSetPtr addrs,
++                                        virPCIDeviceAddressPtr addr)
++{
++    if (addr->extFlags & VIR_PCI_ADDRESS_EXTENSION_ZPCI)
++        virDomainZPCIAddressReleaseIds(addrs->zpciIds, &addr->zpci);
++}
++
++
+ void
+ virDomainPCIAddressReleaseAddr(virDomainPCIAddressSetPtr addrs,
+                                virPCIDeviceAddressPtr addr)
+diff --git a/src/conf/domain_addr.h b/src/conf/domain_addr.h
+index b01e6b9d20..e5ce4868d5 100644
+--- a/src/conf/domain_addr.h
++++ b/src/conf/domain_addr.h
+@@ -166,6 +166,14 @@ bool virDomainPCIAddressSlotInUse(virDomainPCIAddressSetPtr addrs,
+                                   virPCIDeviceAddressPtr addr)
+     ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
+ 
++int virDomainPCIAddressExtensionReserveAddr(virDomainPCIAddressSetPtr addrs,
++                                            virPCIDeviceAddressPtr addr)
++    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
++
++int virDomainPCIAddressExtensionReserveNextAddr(virDomainPCIAddressSetPtr addrs,
++                                                virPCIDeviceAddressPtr addr)
++    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
++
+ int virDomainPCIAddressReserveAddr(virDomainPCIAddressSetPtr addrs,
+                                    virPCIDeviceAddressPtr addr,
+                                    virDomainPCIConnectFlags flags,
+@@ -187,6 +195,10 @@ void virDomainPCIAddressReleaseAddr(virDomainPCIAddressSetPtr addrs,
+                                     virPCIDeviceAddressPtr addr)
+     ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
+ 
++void virDomainPCIAddressExtensionReleaseAddr(virDomainPCIAddressSetPtr addrs,
++                                             virPCIDeviceAddressPtr addr)
++    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
++
+ void virDomainPCIAddressSetAllMulti(virDomainDefPtr def)
+     ATTRIBUTE_NONNULL(1);
+ 
+diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
+index b2a2a1f265..ee7625b0f3 100644
+--- a/src/libvirt_private.syms
++++ b/src/libvirt_private.syms
+@@ -93,6 +93,8 @@ virCPUModeTypeToString;
+ 
+ 
+ # conf/device_conf.h
++virDeviceInfoPCIAddressExtensionIsPresent;
++virDeviceInfoPCIAddressExtensionIsWanted;
+ virDomainDeviceInfoAddressIsEqual;
+ virDomainDeviceInfoCopy;
+ virInterfaceLinkFormat;
+@@ -114,6 +116,9 @@ virDomainPCIAddressAsString;
+ virDomainPCIAddressBusIsFullyReserved;
+ virDomainPCIAddressBusSetModel;
+ virDomainPCIAddressEnsureAddr;
++virDomainPCIAddressExtensionReleaseAddr;
++virDomainPCIAddressExtensionReserveAddr;
++virDomainPCIAddressExtensionReserveNextAddr;
+ virDomainPCIAddressReleaseAddr;
+ virDomainPCIAddressReserveAddr;
+ virDomainPCIAddressReserveNextAddr;
+diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c
+index ba870d56b1..8338241cba 100644
+--- a/src/qemu/qemu_domain_address.c
++++ b/src/qemu/qemu_domain_address.c
+@@ -1405,6 +1405,24 @@ qemuDomainPCIAddressReserveNextAddr(virDomainPCIAddressSetPtr addrs,
+ }
+ 
+ 
++static int
++qemuDomainAssignPCIAddressExtension(virDomainDefPtr def ATTRIBUTE_UNUSED,
++                                    virDomainDeviceDefPtr device ATTRIBUTE_UNUSED,
++                                    virDomainDeviceInfoPtr info,
++                                    void *opaque)
++{
++    virDomainPCIAddressSetPtr addrs = opaque;
++    virPCIDeviceAddressPtr addr = &info->addr.pci;
++
++    if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI)
++        addr->extFlags = info->pciAddrExtFlags;
++
++    if (virDeviceInfoPCIAddressExtensionIsWanted(info))
++        return virDomainPCIAddressExtensionReserveNextAddr(addrs, addr);
++
++    return 0;
++}
++
+ static int
+ qemuDomainCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED,
+                             virDomainDeviceDefPtr device,
+@@ -1498,6 +1516,31 @@ qemuDomainCollectPCIAddress(virDomainDefPtr def ATTRIBUTE_UNUSED,
+     return ret;
+ }
+ 
++static int
++qemuDomainCollectPCIAddressExtension(virDomainDefPtr def ATTRIBUTE_UNUSED,
++                                     virDomainDeviceDefPtr device,
++                                     virDomainDeviceInfoPtr info,
++                                     void *opaque)
++{
++    virDomainPCIAddressSetPtr addrs = opaque;
++    virPCIDeviceAddressPtr addr = &info->addr.pci;
++
++    if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI)
++        addr->extFlags = info->pciAddrExtFlags;
++
++    if (!virDeviceInfoPCIAddressExtensionIsPresent(info) ||
++        ((device->type == VIR_DOMAIN_DEVICE_HOSTDEV) &&
++         (device->data.hostdev->parent.type != VIR_DOMAIN_DEVICE_NONE))) {
++        /* If a hostdev has a parent, its info will be a part of the
++         * parent, and will have its address collected during the scan
++         * of the parent's device type.
++        */
++        return 0;
++    }
++
++    return virDomainPCIAddressExtensionReserveAddr(addrs, addr);
++}
++
+ static virDomainPCIAddressSetPtr
+ qemuDomainPCIAddressSetCreate(virDomainDefPtr def,
+                               virQEMUCapsPtr qemuCaps,
+@@ -1589,6 +1632,12 @@ qemuDomainPCIAddressSetCreate(virDomainDefPtr def,
+     if (virDomainDeviceInfoIterate(def, qemuDomainCollectPCIAddress, addrs) < 0)
+         goto error;
+ 
++    if (virDomainDeviceInfoIterate(def,
++                                   qemuDomainCollectPCIAddressExtension,
++                                   addrs) < 0) {
++        goto error;
++    }
++
+     return addrs;
+ 
+  error:
+@@ -2590,6 +2639,9 @@ qemuDomainAssignPCIAddresses(virDomainDefPtr def,
+         if (qemuDomainAssignDevicePCISlots(def, qemuCaps, addrs) < 0)
+             goto cleanup;
+ 
++        if (virDomainDeviceInfoIterate(def, qemuDomainAssignPCIAddressExtension, addrs) < 0)
++            goto cleanup;
++
+         /* Only for *new* domains with pcie-root (and no other
+          * manually specified PCI controllers in the definition): If,
+          * after assigning addresses/reserving slots for all devices,
+@@ -2684,6 +2736,9 @@ qemuDomainAssignPCIAddresses(virDomainDefPtr def,
+         if (qemuDomainAssignDevicePCISlots(def, qemuCaps, addrs) < 0)
+             goto cleanup;
+ 
++        if (virDomainDeviceInfoIterate(def, qemuDomainAssignPCIAddressExtension, addrs) < 0)
++            goto cleanup;
++
+         /* set multi attribute for devices at function 0 of
+          * any slot that has multiple functions in use
+          */
+@@ -3143,8 +3198,10 @@ qemuDomainReleaseDeviceAddress(virDomainObjPtr vm,
+     if (!devstr)
+         devstr = info->alias;
+ 
+-    if (virDeviceInfoPCIAddressPresent(info))
++    if (virDeviceInfoPCIAddressPresent(info)) {
+         virDomainPCIAddressReleaseAddr(priv->pciaddrs, &info->addr.pci);
++        virDomainPCIAddressExtensionReleaseAddr(priv->pciaddrs, &info->addr.pci);
++    }
+ 
+     if (virDomainUSBAddressRelease(priv->usbaddrs, info) < 0)
+         VIR_WARN("Unable to release USB address on %s", NULLSTR(devstr));
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-conf-Expose-virDomainSCSIDriveAddressIsUsed.patch b/SOURCES/libvirt-conf-Expose-virDomainSCSIDriveAddressIsUsed.patch
new file mode 100644
index 0000000..9d79b6a
--- /dev/null
+++ b/SOURCES/libvirt-conf-Expose-virDomainSCSIDriveAddressIsUsed.patch
@@ -0,0 +1,69 @@
+From 2e3774564235a185a2cc4b7a22c17de17498db68 Mon Sep 17 00:00:00 2001
+Message-Id: <2e3774564235a185a2cc4b7a22c17de17498db68@dist-git>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Thu, 18 Apr 2019 19:36:31 +0200
+Subject: [PATCH] conf: Expose virDomainSCSIDriveAddressIsUsed
+
+RHEl-7.7: https://bugzilla.redhat.com/show_bug.cgi?id=1692296
+RHEL-8.1.0: https://bugzilla.redhat.com/show_bug.cgi?id=1692354
+
+This function checks if given drive address is already present in
+passed domain definition. Expose the function as it will be used
+shortly.
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Tested-by: Daniel Henrique Barboza <danielhb413@gmail.com>
+Reviewed-by: Jim Fehlig <jfehlig@suse.com>
+(cherry picked from commit 89237d534f0fe950d06a2081089154160c6c2224)
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Message-Id: <ef6c1d914a1f6bf0cdb44006b9adf6edf7bb4d41.1555608962.git.mprivozn@redhat.com>
+Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/conf/domain_conf.c   | 2 +-
+ src/conf/domain_conf.h   | 4 ++++
+ src/libvirt_private.syms | 1 +
+ 3 files changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
+index d431441f62..e62f78471c 100644
+--- a/src/conf/domain_conf.c
++++ b/src/conf/domain_conf.c
+@@ -4404,7 +4404,7 @@ virDomainDriveAddressIsUsedByHostdev(const virDomainDef *def,
+  * Return true if the SCSI drive address is already in use, false
+  * otherwise.
+  */
+-static bool
++bool
+ virDomainSCSIDriveAddressIsUsed(const virDomainDef *def,
+                                 const virDomainDeviceDriveAddress *addr)
+ {
+diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
+index f05fca284f..dbccf2cf24 100644
+--- a/src/conf/domain_conf.h
++++ b/src/conf/domain_conf.h
+@@ -2789,6 +2789,10 @@ virDomainXMLNamespacePtr
+ virDomainXMLOptionGetNamespace(virDomainXMLOptionPtr xmlopt)
+     ATTRIBUTE_NONNULL(1);
+ 
++bool
++virDomainSCSIDriveAddressIsUsed(const virDomainDef *def,
++                                const virDomainDeviceDriveAddress *addr);
++
+ int virDomainDefPostParse(virDomainDefPtr def,
+                           virCapsPtr caps,
+                           unsigned int parseFlags,
+diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
+index 624151056a..df27ac4b3a 100644
+--- a/src/libvirt_private.syms
++++ b/src/libvirt_private.syms
+@@ -520,6 +520,7 @@ virDomainRunningReasonTypeToString;
+ virDomainSaveConfig;
+ virDomainSaveStatus;
+ virDomainSaveXML;
++virDomainSCSIDriveAddressIsUsed;
+ virDomainSeclabelTypeFromString;
+ virDomainSeclabelTypeToString;
+ virDomainShmemDefEquals;
+-- 
+2.21.0
+
diff --git a/SOURCES/libvirt-conf-Introduce-address-caching-for-PCI-extensions.patch b/SOURCES/libvirt-conf-Introduce-address-caching-for-PCI-extensions.patch
new file mode 100644
index 0000000..a186a21
--- /dev/null
+++ b/SOURCES/libvirt-conf-Introduce-address-caching-for-PCI-extensions.patch
@@ -0,0 +1,241 @@
+From 7888472ef1d57d992995a16dc7c9ba0fe18562a8 Mon Sep 17 00:00:00 2001
+Message-Id: <7888472ef1d57d992995a16dc7c9ba0fe18562a8@dist-git>
+From: Yi Min Zhao <zyimin@linux.ibm.com>
+Date: Mon, 8 Apr 2019 10:57:22 +0200
+Subject: [PATCH] conf: Introduce address caching for PCI extensions
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This patch provides a caching mechanism for the device address
+extensions uid and fid on S390. For efficient sparse address allocation,
+we introduce two hash tables for uid/fid which hold the address set
+information per domain. Also in order to improve performance of
+searching available value, we introduce our own callbacks for the two
+hashtables. In this way, uid/fid is saved in hash key and hash value
+could be any non-NULL pointer due to no operation on hash value. That is
+also the reason why we don't introduce hash value free callback.
+
+Signed-off-by: Yi Min Zhao <zyimin@linux.ibm.com>
+Reviewed-by: Boris Fiuczynski <fiuczy@linux.ibm.com>
+Reviewed-by: Bjoern Walk <bwalk@linux.ibm.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Reviewed-by: Andrea Bolognani <abologna@redhat.com>
+
+(cherry picked from commit 28831e1f1ec001882e907f03f7618f7c00ebc98d)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1508149
+
+Conflicts:
+
+  * src/conf/domain_addr.h
+    + context
+      - missing b72183223f3b
+
+Signed-off-by: Andrea Bolognani <abologna@redhat.com>
+Message-Id: <20190408085732.28684-6-abologna@redhat.com>
+Reviewed-by: Laine Stump <laine@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/bhyve/bhyve_device.c       |  3 +-
+ src/conf/domain_addr.c         | 93 +++++++++++++++++++++++++++++++++-
+ src/conf/domain_addr.h         | 10 +++-
+ src/qemu/qemu_domain_address.c |  6 ++-
+ 4 files changed, 108 insertions(+), 4 deletions(-)
+
+diff --git a/src/bhyve/bhyve_device.c b/src/bhyve/bhyve_device.c
+index 03aa6c93bd..8f0862b0b6 100644
+--- a/src/bhyve/bhyve_device.c
++++ b/src/bhyve/bhyve_device.c
+@@ -71,7 +71,8 @@ bhyveDomainPCIAddressSetCreate(virDomainDefPtr def, unsigned int nbuses)
+ {
+     virDomainPCIAddressSetPtr addrs;
+ 
+-    if ((addrs = virDomainPCIAddressSetAlloc(nbuses)) == NULL)
++    if ((addrs = virDomainPCIAddressSetAlloc(nbuses,
++                                             VIR_PCI_ADDRESS_EXTENSION_NONE)) == NULL)
+         return NULL;
+ 
+     if (virDomainPCIAddressBusSetModel(&addrs->buses[0],
+diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c
+index 39f22b82eb..3e33549c3d 100644
+--- a/src/conf/domain_addr.c
++++ b/src/conf/domain_addr.c
+@@ -27,6 +27,7 @@
+ #include "virlog.h"
+ #include "virstring.h"
+ #include "domain_addr.h"
++#include "virhashcode.h"
+ 
+ #define VIR_FROM_THIS VIR_FROM_DOMAIN
+ 
+@@ -741,8 +742,93 @@ virDomainPCIAddressReleaseAddr(virDomainPCIAddressSetPtr addrs,
+     addrs->buses[addr->bus].slot[addr->slot].functions &= ~(1 << addr->function);
+ }
+ 
++
++static uint32_t
++virZPCIAddrKeyCode(const void *name,
++                   uint32_t seed)
++{
++    unsigned int value = *((unsigned int *)name);
++    return virHashCodeGen(&value, sizeof(value), seed);
++}
++
++
++static bool
++virZPCIAddrKeyEqual(const void *namea,
++                    const void *nameb)
++{
++    return *((unsigned int *)namea) == *((unsigned int *)nameb);
++}
++
++
++static void *
++virZPCIAddrKeyCopy(const void *name)
++{
++    unsigned int *copy;
++
++    if (VIR_ALLOC(copy) < 0)
++        return NULL;
++
++    *copy = *((unsigned int *)name);
++    return (void *)copy;
++}
++
++
++static void
++virZPCIAddrKeyFree(void *name)
++{
++    VIR_FREE(name);
++}
++
++
++static void
++virDomainPCIAddressSetExtensionFree(virDomainPCIAddressSetPtr addrs)
++{
++    if (!addrs || !addrs->zpciIds)
++        return;
++
++    virHashFree(addrs->zpciIds->uids);
++    virHashFree(addrs->zpciIds->fids);
++    VIR_FREE(addrs->zpciIds);
++}
++
++
++static int
++virDomainPCIAddressSetExtensionAlloc(virDomainPCIAddressSetPtr addrs,
++                                     virPCIDeviceAddressExtensionFlags extFlags)
++{
++    if (extFlags & VIR_PCI_ADDRESS_EXTENSION_ZPCI) {
++        if (addrs->zpciIds)
++            return 0;
++
++        if (VIR_ALLOC(addrs->zpciIds) < 0)
++            return -1;
++
++        if (!(addrs->zpciIds->uids = virHashCreateFull(10, NULL,
++                                                       virZPCIAddrKeyCode,
++                                                       virZPCIAddrKeyEqual,
++                                                       virZPCIAddrKeyCopy,
++                                                       virZPCIAddrKeyFree)))
++            goto error;
++
++        if (!(addrs->zpciIds->fids = virHashCreateFull(10, NULL,
++                                                       virZPCIAddrKeyCode,
++                                                       virZPCIAddrKeyEqual,
++                                                       virZPCIAddrKeyCopy,
++                                                       virZPCIAddrKeyFree)))
++            goto error;
++    }
++
++    return 0;
++
++ error:
++    virDomainPCIAddressSetExtensionFree(addrs);
++    return -1;
++}
++
++
+ virDomainPCIAddressSetPtr
+-virDomainPCIAddressSetAlloc(unsigned int nbuses)
++virDomainPCIAddressSetAlloc(unsigned int nbuses,
++                            virPCIDeviceAddressExtensionFlags extFlags)
+ {
+     virDomainPCIAddressSetPtr addrs;
+ 
+@@ -753,6 +839,10 @@ virDomainPCIAddressSetAlloc(unsigned int nbuses)
+         goto error;
+ 
+     addrs->nbuses = nbuses;
++
++    if (virDomainPCIAddressSetExtensionAlloc(addrs, extFlags) < 0)
++        goto error;
++
+     return addrs;
+ 
+  error:
+@@ -767,6 +857,7 @@ virDomainPCIAddressSetFree(virDomainPCIAddressSetPtr addrs)
+     if (!addrs)
+         return;
+ 
++    virDomainPCIAddressSetExtensionFree(addrs);
+     VIR_FREE(addrs->buses);
+     VIR_FREE(addrs);
+ }
+diff --git a/src/conf/domain_addr.h b/src/conf/domain_addr.h
+index fd06008e26..b01e6b9d20 100644
+--- a/src/conf/domain_addr.h
++++ b/src/conf/domain_addr.h
+@@ -116,6 +116,12 @@ typedef struct {
+ } virDomainPCIAddressBus;
+ typedef virDomainPCIAddressBus *virDomainPCIAddressBusPtr;
+ 
++typedef struct {
++    virHashTablePtr uids;
++    virHashTablePtr fids;
++} virDomainZPCIAddressIds;
++typedef virDomainZPCIAddressIds *virDomainZPCIAddressIdsPtr;
++
+ struct _virDomainPCIAddressSet {
+     virDomainPCIAddressBus *buses;
+     size_t nbuses;
+@@ -125,6 +131,7 @@ struct _virDomainPCIAddressSet {
+     bool areMultipleRootsSupported;
+     /* If true, the guest can use the pcie-to-pci-bridge controller */
+     bool isPCIeToPCIBridgeSupported;
++    virDomainZPCIAddressIdsPtr zpciIds;
+ };
+ typedef struct _virDomainPCIAddressSet virDomainPCIAddressSet;
+ typedef virDomainPCIAddressSet *virDomainPCIAddressSetPtr;
+@@ -132,7 +139,8 @@ typedef virDomainPCIAddressSet *virDomainPCIAddressSetPtr;
+ char *virDomainPCIAddressAsString(virPCIDeviceAddressPtr addr)
+       ATTRIBUTE_NONNULL(1);
+ 
+-virDomainPCIAddressSetPtr virDomainPCIAddressSetAlloc(unsigned int nbuses);
++virDomainPCIAddressSetPtr virDomainPCIAddressSetAlloc(unsigned int nbuses,
++                                                      virPCIDeviceAddressExtensionFlags extFlags);
+ 
+ void virDomainPCIAddressSetFree(virDomainPCIAddressSetPtr addrs);
+ 
+diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c
+index 3d01d14b46..ba870d56b1 100644
+--- a/src/qemu/qemu_domain_address.c
++++ b/src/qemu/qemu_domain_address.c
+@@ -1508,8 +1508,12 @@ qemuDomainPCIAddressSetCreate(virDomainDefPtr def,
+     size_t i;
+     bool hasPCIeRoot = false;
+     virDomainControllerModelPCI defaultModel;
++    virPCIDeviceAddressExtensionFlags extFlags = VIR_PCI_ADDRESS_EXTENSION_NONE;
+ 
+-    if ((addrs = virDomainPCIAddressSetAlloc(nbuses)) == NULL)
++    if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_ZPCI))
++        extFlags |= VIR_PCI_ADDRESS_EXTENSION_ZPCI;
++
++    if ((addrs = virDomainPCIAddressSetAlloc(nbuses, extFlags)) == NULL)
+         return NULL;
+ 
+     addrs->dryRun = dryRun;
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-conf-Introduce-extension-flag-and-zPCI-member-for-PCI-address.patch b/SOURCES/libvirt-conf-Introduce-extension-flag-and-zPCI-member-for-PCI-address.patch
new file mode 100644
index 0000000..3093f57
--- /dev/null
+++ b/SOURCES/libvirt-conf-Introduce-extension-flag-and-zPCI-member-for-PCI-address.patch
@@ -0,0 +1,283 @@
+From 050eb598af9291f385998cb1127d5bdf83305501 Mon Sep 17 00:00:00 2001
+Message-Id: <050eb598af9291f385998cb1127d5bdf83305501@dist-git>
+From: Yi Min Zhao <zyimin@linux.ibm.com>
+Date: Mon, 8 Apr 2019 10:57:21 +0200
+Subject: [PATCH] conf: Introduce extension flag and zPCI member for PCI
+ address
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This patch introduces PCI address extension flag for virDomainDeviceInfo
+and virPCIDeviceAddress. The extension flag in virDomainDeviceInfo is
+used internally during calculating PCI extension flag. The one in
+virPCIDeviceAddress is the duplicate to indicate extension address is
+being used. Currently only zPCI extension address is introduced to deal
+with 'uid' and 'fid' on the S390 platform.
+
+Signed-off-by: Yi Min Zhao <zyimin@linux.ibm.com>
+Reviewed-by: Boris Fiuczynski <fiuczy@linux.ibm.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Reviewed-by: Andrea Bolognani <abologna@redhat.com>
+
+(cherry picked from commit 478e5f90fd4c0c0a8c1b3a8e19b9cae93ed78a4e)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1508149
+
+Conflicts:
+
+  * src/qemu/qemu_domain_address.c
+    + context
+      - missing db98a426a640
+
+Signed-off-by: Andrea Bolognani <abologna@redhat.com>
+Message-Id: <20190408085732.28684-5-abologna@redhat.com>
+Reviewed-by: Laine Stump <laine@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/conf/device_conf.h         |   4 +
+ src/conf/domain_addr.h         |   5 ++
+ src/qemu/qemu_domain_address.c | 140 ++++++++++++++++++++++++++++++++-
+ src/util/virpci.h              |   2 +
+ 4 files changed, 149 insertions(+), 2 deletions(-)
+
+diff --git a/src/conf/device_conf.h b/src/conf/device_conf.h
+index a31ce9c376..c79066ec02 100644
+--- a/src/conf/device_conf.h
++++ b/src/conf/device_conf.h
+@@ -164,6 +164,10 @@ struct _virDomainDeviceInfo {
+      * assignment, never saved and never reported.
+      */
+     int pciConnectFlags; /* enum virDomainPCIConnectFlags */
++    /* pciAddrExtFlags is only used internally to calculate PCI
++     * address extension flags during address assignment.
++     */
++    int pciAddrExtFlags; /* enum virDomainPCIAddressExtensionFlags */
+     char *loadparm;
+ 
+     /* PCI devices will only be automatically placed on a PCI bus
+diff --git a/src/conf/domain_addr.h b/src/conf/domain_addr.h
+index 3236b7d6de..fd06008e26 100644
+--- a/src/conf/domain_addr.h
++++ b/src/conf/domain_addr.h
+@@ -29,6 +29,11 @@
+ # define VIR_PCI_ADDRESS_SLOT_LAST 31
+ # define VIR_PCI_ADDRESS_FUNCTION_LAST 7
+ 
++typedef enum {
++    VIR_PCI_ADDRESS_EXTENSION_NONE = 0, /* no extension */
++    VIR_PCI_ADDRESS_EXTENSION_ZPCI = 1 << 0, /* zPCI support */
++} virPCIDeviceAddressExtensionFlags;
++
+ typedef enum {
+    VIR_PCI_CONNECT_HOTPLUGGABLE = 1 << 0, /* is hotplug needed/supported */
+ 
+diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c
+index 79d2b9f9c4..3d01d14b46 100644
+--- a/src/qemu/qemu_domain_address.c
++++ b/src/qemu/qemu_domain_address.c
+@@ -511,6 +511,64 @@ qemuDomainAssignARMVirtioMMIOAddresses(virDomainDefPtr def,
+ }
+ 
+ 
++static bool
++qemuDomainDeviceSupportZPCI(virDomainDeviceDefPtr device)
++{
++    switch ((virDomainDeviceType)device->type) {
++    case VIR_DOMAIN_DEVICE_CHR:
++        return false;
++
++    case VIR_DOMAIN_DEVICE_CONTROLLER:
++    case VIR_DOMAIN_DEVICE_DISK:
++    case VIR_DOMAIN_DEVICE_LEASE:
++    case VIR_DOMAIN_DEVICE_FS:
++    case VIR_DOMAIN_DEVICE_NET:
++    case VIR_DOMAIN_DEVICE_INPUT:
++    case VIR_DOMAIN_DEVICE_SOUND:
++    case VIR_DOMAIN_DEVICE_VIDEO:
++    case VIR_DOMAIN_DEVICE_HOSTDEV:
++    case VIR_DOMAIN_DEVICE_WATCHDOG:
++    case VIR_DOMAIN_DEVICE_GRAPHICS:
++    case VIR_DOMAIN_DEVICE_HUB:
++    case VIR_DOMAIN_DEVICE_REDIRDEV:
++    case VIR_DOMAIN_DEVICE_SMARTCARD:
++    case VIR_DOMAIN_DEVICE_MEMBALLOON:
++    case VIR_DOMAIN_DEVICE_NVRAM:
++    case VIR_DOMAIN_DEVICE_RNG:
++    case VIR_DOMAIN_DEVICE_SHMEM:
++    case VIR_DOMAIN_DEVICE_TPM:
++    case VIR_DOMAIN_DEVICE_PANIC:
++    case VIR_DOMAIN_DEVICE_MEMORY:
++    case VIR_DOMAIN_DEVICE_IOMMU:
++    case VIR_DOMAIN_DEVICE_VSOCK:
++        break;
++
++    case VIR_DOMAIN_DEVICE_NONE:
++    case VIR_DOMAIN_DEVICE_LAST:
++    default:
++        virReportEnumRangeError(virDomainDeviceType, device->type);
++        return false;
++    }
++
++    return true;
++}
++
++
++static virPCIDeviceAddressExtensionFlags
++qemuDomainDeviceCalculatePCIAddressExtensionFlags(virQEMUCapsPtr qemuCaps,
++                                                  virDomainDeviceDefPtr dev)
++{
++    virPCIDeviceAddressExtensionFlags extFlags = 0;
++
++    if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_ZPCI) &&
++        qemuDomainDeviceSupportZPCI(dev)) {
++        extFlags |= VIR_PCI_ADDRESS_EXTENSION_ZPCI;
++    }
++
++    return extFlags;
++}
++
++
+ /**
+  * qemuDomainDeviceCalculatePCIConnectFlags:
+  *
+@@ -993,6 +1051,56 @@ qemuDomainFillAllPCIConnectFlags(virDomainDefPtr def,
+ }
+ 
+ 
++/**
++ * qemuDomainFillDevicePCIExtensionFlagsIter:
++ *
++ * @def: the entire DomainDef
++ * @dev: The device to be checked
++ * @info: virDomainDeviceInfo within the device
++ * @opaque: qemu capabilities
++ *
++ * Sets the pciAddressExtFlags for a single device's info. Has properly
++ * formatted arguments to be called by virDomainDeviceInfoIterate().
++ *
++ * Always returns 0 - there is no failure.
++ */
++static int
++qemuDomainFillDevicePCIExtensionFlagsIter(virDomainDefPtr def ATTRIBUTE_UNUSED,
++                                          virDomainDeviceDefPtr dev,
++                                          virDomainDeviceInfoPtr info,
++                                          void *opaque)
++{
++    virQEMUCapsPtr qemuCaps = opaque;
++
++    info->pciAddrExtFlags =
++        qemuDomainDeviceCalculatePCIAddressExtensionFlags(qemuCaps, dev);
++
++    return 0;
++}
++
++
++/**
++ * qemuDomainFillAllPCIExtensionFlags:
++ *
++ * @def: the entire DomainDef
++ * @qemuCaps: as you'd expect
++ *
++ * Set the info->pciAddressExtFlags for all devices in the domain.
++ *
++ * Returns 0 on success or -1 on failure (the only possibility of
++ * failure would be some internal problem with
++ * virDomainDeviceInfoIterate())
++ */
++static int
++qemuDomainFillAllPCIExtensionFlags(virDomainDefPtr def,
++                                   virQEMUCapsPtr qemuCaps)
++{
++    return virDomainDeviceInfoIterate(def,
++                                      qemuDomainFillDevicePCIExtensionFlagsIter,
++                                      qemuCaps);
++}
++
++
+ /**
+  * qemuDomainFindUnusedIsolationGroupIter:
+  * @def: domain definition
+@@ -1267,6 +1375,27 @@ qemuDomainFillDevicePCIConnectFlags(virDomainDefPtr def,
+ }
+ 
+ 
++/**
++ * qemuDomainFillDevicePCIExtensionFlags:
++ *
++ * @dev: The device to be checked
++ * @info: virDomainDeviceInfo within the device
++ * @qemuCaps: as you'd expect
++ *
++ * Set the info->pciAddressExtFlags for a single device.
++ *
++ * No return value.
++ */
++static void
++qemuDomainFillDevicePCIExtensionFlags(virDomainDeviceDefPtr dev,
++                                      virDomainDeviceInfoPtr info,
++                                      virQEMUCapsPtr qemuCaps)
++{
++    info->pciAddrExtFlags =
++        qemuDomainDeviceCalculatePCIAddressExtensionFlags(qemuCaps, dev);
++}
++
++
+ static int
+ qemuDomainPCIAddressReserveNextAddr(virDomainPCIAddressSetPtr addrs,
+                                     virDomainDeviceInfoPtr dev)
+@@ -2400,6 +2529,9 @@ qemuDomainAssignPCIAddresses(virDomainDefPtr def,
+     if (qemuDomainFillAllPCIConnectFlags(def, qemuCaps, driver) < 0)
+         goto cleanup;
+ 
++    if (qemuDomainFillAllPCIExtensionFlags(def, qemuCaps) < 0)
++        goto cleanup;
++
+     if (qemuDomainSetupIsolationGroups(def) < 0)
+         goto cleanup;
+ 
+@@ -2435,7 +2567,8 @@ qemuDomainAssignPCIAddresses(virDomainDefPtr def,
+              */
+             virDomainDeviceInfo info = {
+                 .pciConnectFlags = (VIR_PCI_CONNECT_HOTPLUGGABLE |
+-                                    VIR_PCI_CONNECT_TYPE_PCI_DEVICE)
++                                    VIR_PCI_CONNECT_TYPE_PCI_DEVICE),
++                .pciAddrExtFlags = VIR_PCI_ADDRESS_EXTENSION_NONE
+             };
+             bool buses_reserved = true;
+ 
+@@ -2472,7 +2605,8 @@ qemuDomainAssignPCIAddresses(virDomainDefPtr def,
+             qemuDomainHasPCIeRoot(def)) {
+             virDomainDeviceInfo info = {
+                 .pciConnectFlags = (VIR_PCI_CONNECT_HOTPLUGGABLE |
+-                                    VIR_PCI_CONNECT_TYPE_PCIE_DEVICE)
++                                    VIR_PCI_CONNECT_TYPE_PCIE_DEVICE),
++                .pciAddrExtFlags = VIR_PCI_ADDRESS_EXTENSION_NONE
+             };
+ 
+             /* if there isn't an empty pcie-root-port, this will
+@@ -2989,6 +3123,8 @@ qemuDomainEnsurePCIAddress(virDomainObjPtr obj,
+ 
+     qemuDomainFillDevicePCIConnectFlags(obj->def, dev, priv->qemuCaps, driver);
+ 
++    qemuDomainFillDevicePCIExtensionFlags(dev, info, priv->qemuCaps);
++
+     return virDomainPCIAddressEnsureAddr(priv->pciaddrs, info,
+                                          info->pciConnectFlags);
+ }
+diff --git a/src/util/virpci.h b/src/util/virpci.h
+index 01df652b86..b366d7d9c3 100644
+--- a/src/util/virpci.h
++++ b/src/util/virpci.h
+@@ -49,6 +49,8 @@ struct _virPCIDeviceAddress {
+     unsigned int slot;
+     unsigned int function;
+     int multi; /* virTristateSwitch */
++    int extFlags; /* enum virPCIDeviceAddressExtensionFlags */
++    virZPCIDeviceAddress zpci;
+ };
+ 
+ typedef enum {
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-conf-Introduce-parser-formatter-for-uid-and-fid.patch b/SOURCES/libvirt-conf-Introduce-parser-formatter-for-uid-and-fid.patch
new file mode 100644
index 0000000..3bd46dd
--- /dev/null
+++ b/SOURCES/libvirt-conf-Introduce-parser-formatter-for-uid-and-fid.patch
@@ -0,0 +1,574 @@
+From fddd43e717869d56e481c3fde2d5ee6b5513a1f5 Mon Sep 17 00:00:00 2001
+Message-Id: <fddd43e717869d56e481c3fde2d5ee6b5513a1f5@dist-git>
+From: Yi Min Zhao <zyimin@linux.ibm.com>
+Date: Mon, 8 Apr 2019 10:57:25 +0200
+Subject: [PATCH] conf: Introduce parser, formatter for uid and fid
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This patch introduces new XML parser/formatter functions. Uid is
+16-bit and non-zero. Fid is 32-bit. They are the two attributes of zpci
+which is introduced as PCI address element. Zpci element is parsed and
+formatted along with PCI address. And add the related test cases.
+
+Signed-off-by: Yi Min Zhao <zyimin@linux.ibm.com>
+Reviewed-by: Boris Fiuczynski <fiuczy@linux.ibm.com>
+Reviewed-by: Stefan Zimmermann <stzi@linux.ibm.com>
+Reviewed-by: Bjoern Walk <bwalk@linux.ibm.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Reviewed-by: Andrea Bolognani <abologna@redhat.com>
+
+(cherry picked from commit b4833b2c2f7be8a68eb6495ed57ed61918e3ecd8)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1508149
+
+Conflicts:
+
+  * src/conf/device_conf.c
+    + context
+      - missing edeef779585
+
+  * tests/qemuxml2argvtest.c
+    + context
+      - missing a0ff9fbe5cad, 0bdb704383f7
+
+Changed:
+
+  * tests/qemuxml2argvdata/disk-virtio-s390-zpci.args
+    tests/qemuxml2argvdata/hostdev-vfio-zpci.args
+    + no -boot in output
+      - missing caccbba64aa9
+
+Signed-off-by: Andrea Bolognani <abologna@redhat.com>
+Message-Id: <20190408085732.28684-9-abologna@redhat.com>
+Reviewed-by: Laine Stump <laine@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ docs/schemas/basictypes.rng                   | 27 ++++++++++
+ docs/schemas/domaincommon.rng                 |  1 +
+ src/conf/device_conf.c                        | 53 +++++++++++++++++++
+ src/conf/domain_addr.c                        |  3 ++
+ src/conf/domain_conf.c                        | 12 ++++-
+ src/libvirt_private.syms                      |  2 +
+ src/util/virpci.c                             | 26 +++++++++
+ src/util/virpci.h                             |  6 +++
+ .../disk-virtio-s390-zpci.args                | 26 +++++++++
+ .../disk-virtio-s390-zpci.xml                 | 19 +++++++
+ tests/qemuxml2argvdata/hostdev-vfio-zpci.args | 24 +++++++++
+ tests/qemuxml2argvdata/hostdev-vfio-zpci.xml  | 21 ++++++++
+ tests/qemuxml2argvtest.c                      |  7 +++
+ .../disk-virtio-s390-zpci.xml                 | 31 +++++++++++
+ .../qemuxml2xmloutdata/hostdev-vfio-zpci.xml  | 32 +++++++++++
+ tests/qemuxml2xmltest.c                       |  6 +++
+ 16 files changed, 295 insertions(+), 1 deletion(-)
+ create mode 100644 tests/qemuxml2argvdata/disk-virtio-s390-zpci.args
+ create mode 100644 tests/qemuxml2argvdata/disk-virtio-s390-zpci.xml
+ create mode 100644 tests/qemuxml2argvdata/hostdev-vfio-zpci.args
+ create mode 100644 tests/qemuxml2argvdata/hostdev-vfio-zpci.xml
+ create mode 100644 tests/qemuxml2xmloutdata/disk-virtio-s390-zpci.xml
+ create mode 100644 tests/qemuxml2xmloutdata/hostdev-vfio-zpci.xml
+
+diff --git a/docs/schemas/basictypes.rng b/docs/schemas/basictypes.rng
+index b45a7fcdc8..97e14d7ca8 100644
+--- a/docs/schemas/basictypes.rng
++++ b/docs/schemas/basictypes.rng
+@@ -65,6 +65,17 @@
+       </data>
+     </choice>
+   </define>
++  <define name="uint32">
++    <choice>
++      <data type="string">
++        <param name="pattern">(0x)?[0-9a-fA-F]{1,8}</param>
++      </data>
++      <data type="unsignedInt">
++        <param name="minInclusive">0</param>
++        <param name="maxInclusive">4294967295</param>
++      </data>
++    </choice>
++  </define>
+ 
+   <define name="UUID">
+     <choice>
+@@ -111,6 +122,22 @@
+       </attribute>
+     </optional>
+   </define>
++  <define name="zpciaddress">
++    <optional>
++      <element name="zpci">
++        <optional>
++          <attribute name="uid">
++            <ref name="uint16"/>
++          </attribute>
++        </optional>
++        <optional>
++          <attribute name="fid">
++            <ref name="uint32"/>
++          </attribute>
++        </optional>
++      </element>
++    </optional>
++  </define>
+ 
+   <!-- a 6 byte MAC address in ASCII-hex format, eg "12:34:56:78:9A:BC" -->
+   <!-- The lowest bit of the 1st byte is the "multicast" bit. a         -->
+diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
+index 70a7767d9c..2b6d4dced6 100644
+--- a/docs/schemas/domaincommon.rng
++++ b/docs/schemas/domaincommon.rng
+@@ -5186,6 +5186,7 @@
+             <value>pci</value>
+           </attribute>
+           <ref name="pciaddress"/>
++          <ref name="zpciaddress"/>
+         </group>
+         <group>
+           <attribute name="type">
+diff --git a/src/conf/device_conf.c b/src/conf/device_conf.c
+index d69f94fadf..cadac32603 100644
+--- a/src/conf/device_conf.c
++++ b/src/conf/device_conf.c
+@@ -32,6 +32,45 @@
+ 
+ #define VIR_FROM_THIS VIR_FROM_DEVICE
+ 
++static int
++virZPCIDeviceAddressParseXML(xmlNodePtr node,
++                             virPCIDeviceAddressPtr addr)
++{
++    virZPCIDeviceAddress def = { 0 };
++    char *uid;
++    char *fid;
++    int ret = -1;
++
++    uid = virXMLPropString(node, "uid");
++    fid = virXMLPropString(node, "fid");
++
++    if (uid &&
++        virStrToLong_uip(uid, NULL, 0, &def.uid) < 0) {
++        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
++                       _("Cannot parse <address> 'uid' attribute"));
++        goto cleanup;
++    }
++
++    if (fid &&
++        virStrToLong_uip(fid, NULL, 0, &def.fid) < 0) {
++        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
++                       _("Cannot parse <address> 'fid' attribute"));
++        goto cleanup;
++    }
++
++    if (!virZPCIDeviceAddressIsEmpty(&def) &&
++        !virZPCIDeviceAddressIsValid(&def))
++        goto cleanup;
++
++    addr->zpci = def;
++    ret = 0;
++
++ cleanup:
++    VIR_FREE(uid);
++    VIR_FREE(fid);
++    return ret;
++}
++
+ int
+ virDomainDeviceInfoCopy(virDomainDeviceInfoPtr dst,
+                         virDomainDeviceInfoPtr src)
+@@ -196,6 +235,8 @@ virPCIDeviceAddressParseXML(xmlNodePtr node,
+                             virPCIDeviceAddressPtr addr)
+ {
+     char *domain, *slot, *bus, *function, *multi;
++    xmlNodePtr cur;
++    xmlNodePtr zpci = NULL;
+     int ret = -1;
+ 
+     memset(addr, 0, sizeof(*addr));
+@@ -245,6 +286,18 @@ virPCIDeviceAddressParseXML(xmlNodePtr node,
+     if (!virPCIDeviceAddressIsEmpty(addr) && !virPCIDeviceAddressIsValid(addr, true))
+         goto cleanup;
+ 
++    cur = node->children;
++    while (cur) {
++        if (cur->type == XML_ELEMENT_NODE &&
++            virXMLNodeNameEqual(cur, "zpci")) {
++            zpci = cur;
++        }
++        cur = cur->next;
++    }
++
++    if (zpci && virZPCIDeviceAddressParseXML(zpci, addr) < 0)
++        goto cleanup;
++
+     ret = 0;
+ 
+  cleanup:
+diff --git a/src/conf/domain_addr.c b/src/conf/domain_addr.c
+index 3e33549c3d..9e0a0fdf95 100644
+--- a/src/conf/domain_addr.c
++++ b/src/conf/domain_addr.c
+@@ -1054,6 +1054,9 @@ virDomainPCIAddressReserveNextAddr(virDomainPCIAddressSetPtr addrs,
+                                                dev->isolationGroup, false) < 0)
+         return -1;
+ 
++    addr.extFlags = dev->addr.pci.extFlags;
++    addr.zpci = dev->addr.pci.zpci;
++
+     if (!addrs->dryRun) {
+         dev->type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI;
+         dev->addr.pci = addr;
+diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
+index bcb0558bc3..29ebf0a930 100644
+--- a/src/conf/domain_conf.c
++++ b/src/conf/domain_conf.c
+@@ -6448,6 +6448,7 @@ virDomainDeviceInfoFormat(virBufferPtr buf,
+                           unsigned int flags)
+ {
+     virBuffer attrBuf = VIR_BUFFER_INITIALIZER;
++    virBuffer childBuf = VIR_BUFFER_INITIALIZER;
+ 
+     if ((flags & VIR_DOMAIN_DEF_FORMAT_ALLOW_BOOT) && info->bootIndex) {
+         virBufferAsprintf(buf, "<boot order='%u'", info->bootIndex);
+@@ -6510,6 +6511,14 @@ virDomainDeviceInfoFormat(virBufferPtr buf,
+             virBufferAsprintf(&attrBuf, " multifunction='%s'",
+                               virTristateSwitchTypeToString(info->addr.pci.multi));
+         }
++
++        if (!virZPCIDeviceAddressIsEmpty(&info->addr.pci.zpci)) {
++            virBufferSetChildIndent(&childBuf, buf);
++            virBufferAsprintf(&childBuf,
++                              "<zpci uid='0x%.4x' fid='0x%.8x'/>\n",
++                              info->addr.pci.zpci.uid,
++                              info->addr.pci.zpci.fid);
++        }
+         break;
+ 
+     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE:
+@@ -6577,9 +6586,10 @@ virDomainDeviceInfoFormat(virBufferPtr buf,
+         break;
+     }
+ 
+-    virXMLFormatElement(buf, "address", &attrBuf, NULL);
++    virXMLFormatElement(buf, "address", &attrBuf, &childBuf);
+ 
+     virBufferFreeAndReset(&attrBuf);
++    virBufferFreeAndReset(&childBuf);
+ }
+ 
+ static int
+diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
+index df27ac4b3a..b2a2a1f265 100644
+--- a/src/libvirt_private.syms
++++ b/src/libvirt_private.syms
+@@ -2569,6 +2569,8 @@ virPCIHeaderTypeToString;
+ virPCIIsVirtualFunction;
+ virPCIStubDriverTypeFromString;
+ virPCIStubDriverTypeToString;
++virZPCIDeviceAddressIsEmpty;
++virZPCIDeviceAddressIsValid;
+ 
+ 
+ # util/virperf.h
+diff --git a/src/util/virpci.c b/src/util/virpci.c
+index 8d02366664..3a1e49a7a7 100644
+--- a/src/util/virpci.c
++++ b/src/util/virpci.c
+@@ -2597,6 +2597,32 @@ virPCIDeviceAddressParse(char *address,
+ 
+ #ifdef __linux__
+ 
++bool
++virZPCIDeviceAddressIsValid(virZPCIDeviceAddressPtr zpci)
++{
++    /* We don't need to check fid because fid covers
++     * all range of uint32 type.
++     */
++    if (zpci->uid > VIR_DOMAIN_DEVICE_ZPCI_MAX_UID ||
++        zpci->uid == 0) {
++        virReportError(VIR_ERR_XML_ERROR,
++                       _("Invalid PCI address uid='0x%.4x', "
++                         "must be > 0x0000 and <= 0x%.4x"),
++                       zpci->uid,
++                       VIR_DOMAIN_DEVICE_ZPCI_MAX_UID);
++        return false;
++    }
++
++    return true;
++}
++
++bool
++virZPCIDeviceAddressIsEmpty(const virZPCIDeviceAddress *addr)
++{
++    return !(addr->uid || addr->fid);
++}
++
++
+ /*
+  * returns true if equal
+  */
+diff --git a/src/util/virpci.h b/src/util/virpci.h
+index b366d7d9c3..1ed9e2381e 100644
+--- a/src/util/virpci.h
++++ b/src/util/virpci.h
+@@ -36,6 +36,9 @@ typedef virPCIDeviceAddress *virPCIDeviceAddressPtr;
+ typedef struct _virPCIDeviceList virPCIDeviceList;
+ typedef virPCIDeviceList *virPCIDeviceListPtr;
+ 
++# define VIR_DOMAIN_DEVICE_ZPCI_MAX_UID UINT16_MAX
++# define VIR_DOMAIN_DEVICE_ZPCI_MAX_FID UINT32_MAX
++
+ typedef struct _virZPCIDeviceAddress virZPCIDeviceAddress;
+ typedef virZPCIDeviceAddress *virZPCIDeviceAddressPtr;
+ struct _virZPCIDeviceAddress {
+@@ -235,6 +238,9 @@ int virPCIGetAddrString(unsigned int domain,
+ 
+ int virPCIDeviceAddressParse(char *address, virPCIDeviceAddressPtr bdf);
+ 
++bool virZPCIDeviceAddressIsValid(virZPCIDeviceAddressPtr zpci);
++bool virZPCIDeviceAddressIsEmpty(const virZPCIDeviceAddress *addr);
++
+ int virPCIGetVirtualFunctionInfo(const char *vf_sysfs_device_path,
+                                  int pfNetDevIdx,
+                                  char **pfname,
+diff --git a/tests/qemuxml2argvdata/disk-virtio-s390-zpci.args b/tests/qemuxml2argvdata/disk-virtio-s390-zpci.args
+new file mode 100644
+index 0000000000..20e63a15b5
+--- /dev/null
++++ b/tests/qemuxml2argvdata/disk-virtio-s390-zpci.args
+@@ -0,0 +1,26 @@
++LC_ALL=C \
++PATH=/bin \
++HOME=/home/test \
++USER=test \
++LOGNAME=test \
++QEMU_AUDIO_DRV=none \
++/usr/bin/qemu-system-s390x \
++-name QEMUGuest1 \
++-S \
++-machine s390-ccw-virtio,accel=tcg,usb=off,dump-guest-core=off \
++-m 214 \
++-smp 1,sockets=1,cores=1,threads=1 \
++-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \
++-display none \
++-no-user-config \
++-nodefaults \
++-chardev socket,id=charmonitor,path=/tmp/lib/domain--1-QEMUGuest1/monitor.sock,\
++server,nowait \
++-mon chardev=charmonitor,id=monitor,mode=control \
++-rtc base=utc \
++-no-shutdown \
++-boot c \
++-drive file=/dev/HostVG/QEMUGuest1,format=raw,if=none,id=drive-virtio-disk0 \
++-device virtio-blk-pci,bus=pci.0,addr=0x8,drive=drive-virtio-disk0,\
++id=virtio-disk0 \
++-device virtio-balloon-ccw,id=balloon0,devno=fe.0.0000
+diff --git a/tests/qemuxml2argvdata/disk-virtio-s390-zpci.xml b/tests/qemuxml2argvdata/disk-virtio-s390-zpci.xml
+new file mode 100644
+index 0000000000..8bf4a23670
+--- /dev/null
++++ b/tests/qemuxml2argvdata/disk-virtio-s390-zpci.xml
+@@ -0,0 +1,19 @@
++<domain type='qemu'>
++  <name>QEMUGuest1</name>
++  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
++  <memory>219136</memory>
++  <vcpu>1</vcpu>
++  <os>
++    <type arch='s390x' machine='s390-ccw-virtio'>hvm</type>
++  </os>
++  <devices>
++    <emulator>/usr/bin/qemu-system-s390x</emulator>
++    <disk type='block' device='disk'>
++      <source dev='/dev/HostVG/QEMUGuest1'/>
++      <target dev='hda' bus='virtio'/>
++      <address type='pci' domain='0x0000' bus='0x00' slot='0x08' function='0x0'>
++        <zpci uid='0x0019' fid='0x0000001f'/>
++      </address>
++    </disk>
++  </devices>
++</domain>
+diff --git a/tests/qemuxml2argvdata/hostdev-vfio-zpci.args b/tests/qemuxml2argvdata/hostdev-vfio-zpci.args
+new file mode 100644
+index 0000000000..622c504da0
+--- /dev/null
++++ b/tests/qemuxml2argvdata/hostdev-vfio-zpci.args
+@@ -0,0 +1,24 @@
++LC_ALL=C \
++PATH=/bin \
++HOME=/home/test \
++USER=test \
++LOGNAME=test \
++QEMU_AUDIO_DRV=none \
++/usr/bin/qemu-system-s390x \
++-name QEMUGuest1 \
++-S \
++-machine s390-ccw-virtio,accel=tcg,usb=off,dump-guest-core=off \
++-m 214 \
++-smp 1,sockets=1,cores=1,threads=1 \
++-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \
++-display none \
++-no-user-config \
++-nodefaults \
++-chardev socket,id=charmonitor,path=/tmp/lib/domain--1-QEMUGuest1/monitor.sock,\
++server,nowait \
++-mon chardev=charmonitor,id=monitor,mode=control \
++-rtc base=utc \
++-no-shutdown \
++-boot c \
++-device vfio-pci,host=00:00.0,id=hostdev0,bus=pci.0,addr=0x8 \
++-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x1
+diff --git a/tests/qemuxml2argvdata/hostdev-vfio-zpci.xml b/tests/qemuxml2argvdata/hostdev-vfio-zpci.xml
+new file mode 100644
+index 0000000000..002b99c52d
+--- /dev/null
++++ b/tests/qemuxml2argvdata/hostdev-vfio-zpci.xml
+@@ -0,0 +1,21 @@
++<domain type='qemu'>
++  <name>QEMUGuest1</name>
++  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
++  <memory>219100</memory>
++  <os>
++    <type arch='s390x' machine='s390-ccw-virtio'>hvm</type>
++  </os>
++  <devices>
++    <emulator>/usr/bin/qemu-system-s390x</emulator>
++    <controller type='pci' index='0' model='pci-root'/>
++    <hostdev mode='subsystem' type='pci' managed='no'>
++      <driver name='vfio'/>
++      <source>
++        <address domain='0x0000' bus='0x00' slot='0x00' function='0x0'/>
++      </source>
++      <address type='pci' domain='0x0000' bus='0x00' slot='0x08' function='0x0'>
++        <zpci uid='0x0019' fid='0x0000001f'/>
++      </address>
++    </hostdev>
++  </devices>
++</domain>
+diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
+index 7f25cccf9d..2eb2505971 100644
+--- a/tests/qemuxml2argvtest.c
++++ b/tests/qemuxml2argvtest.c
+@@ -1038,6 +1038,10 @@ mymain(void)
+             QEMU_CAPS_CCW, QEMU_CAPS_VIRTIO_S390);
+     DO_TEST("disk-virtio-scsi-ccw", QEMU_CAPS_VIRTIO_SCSI,
+             QEMU_CAPS_CCW, QEMU_CAPS_VIRTIO_S390);
++    DO_TEST("disk-virtio-s390-zpci",
++            QEMU_CAPS_DEVICE_ZPCI,
++            QEMU_CAPS_CCW,
++            QEMU_CAPS_VIRTIO_S390);
+     DO_TEST("disk-order",
+             QEMU_CAPS_DRIVE_BOOT, QEMU_CAPS_VIRTIO_BLK_SCSI);
+     DO_TEST("disk-virtio-drive-queues",
+@@ -1628,6 +1632,9 @@ mymain(void)
+     DO_TEST_PARSE_ERROR("hostdev-mdev-display-missing-graphics",
+             QEMU_CAPS_DEVICE_VFIO_PCI,
+             QEMU_CAPS_VFIO_PCI_DISPLAY);
++    DO_TEST("hostdev-vfio-zpci",
++            QEMU_CAPS_DEVICE_VFIO_PCI,
++            QEMU_CAPS_DEVICE_ZPCI);
+     DO_TEST("pci-rom", NONE);
+     DO_TEST("pci-rom-disabled", NONE);
+     DO_TEST("pci-rom-disabled-invalid", NONE);
+diff --git a/tests/qemuxml2xmloutdata/disk-virtio-s390-zpci.xml b/tests/qemuxml2xmloutdata/disk-virtio-s390-zpci.xml
+new file mode 100644
+index 0000000000..37684c82b1
+--- /dev/null
++++ b/tests/qemuxml2xmloutdata/disk-virtio-s390-zpci.xml
+@@ -0,0 +1,31 @@
++<domain type='qemu'>
++  <name>QEMUGuest1</name>
++  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
++  <memory unit='KiB'>219136</memory>
++  <currentMemory unit='KiB'>219136</currentMemory>
++  <vcpu placement='static'>1</vcpu>
++  <os>
++    <type arch='s390x' machine='s390-ccw-virtio'>hvm</type>
++    <boot dev='hd'/>
++  </os>
++  <clock offset='utc'/>
++  <on_poweroff>destroy</on_poweroff>
++  <on_reboot>restart</on_reboot>
++  <on_crash>destroy</on_crash>
++  <devices>
++    <emulator>/usr/bin/qemu-system-s390x</emulator>
++    <disk type='block' device='disk'>
++      <driver name='qemu' type='raw'/>
++      <source dev='/dev/HostVG/QEMUGuest1'/>
++      <target dev='hda' bus='virtio'/>
++      <address type='pci' domain='0x0000' bus='0x00' slot='0x08' function='0x0'>
++        <zpci uid='0x0019' fid='0x0000001f'/>
++      </address>
++    </disk>
++    <controller type='pci' index='0' model='pci-root'/>
++    <memballoon model='virtio'>
++      <address type='ccw' cssid='0xfe' ssid='0x0' devno='0x0000'/>
++    </memballoon>
++    <panic model='s390'/>
++  </devices>
++</domain>
+diff --git a/tests/qemuxml2xmloutdata/hostdev-vfio-zpci.xml b/tests/qemuxml2xmloutdata/hostdev-vfio-zpci.xml
+new file mode 100644
+index 0000000000..fc8c38ab66
+--- /dev/null
++++ b/tests/qemuxml2xmloutdata/hostdev-vfio-zpci.xml
+@@ -0,0 +1,32 @@
++<domain type='qemu'>
++  <name>QEMUGuest1</name>
++  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
++  <memory unit='KiB'>219100</memory>
++  <currentMemory unit='KiB'>219100</currentMemory>
++  <vcpu placement='static'>1</vcpu>
++  <os>
++    <type arch='s390x' machine='s390-ccw-virtio'>hvm</type>
++    <boot dev='hd'/>
++  </os>
++  <clock offset='utc'/>
++  <on_poweroff>destroy</on_poweroff>
++  <on_reboot>restart</on_reboot>
++  <on_crash>destroy</on_crash>
++  <devices>
++    <emulator>/usr/bin/qemu-system-s390x</emulator>
++    <controller type='pci' index='0' model='pci-root'/>
++    <hostdev mode='subsystem' type='pci' managed='no'>
++      <driver name='vfio'/>
++      <source>
++        <address domain='0x0000' bus='0x00' slot='0x00' function='0x0'/>
++      </source>
++      <address type='pci' domain='0x0000' bus='0x00' slot='0x08' function='0x0'>
++        <zpci uid='0x0019' fid='0x0000001f'/>
++      </address>
++    </hostdev>
++    <memballoon model='virtio'>
++      <address type='ccw' cssid='0xfe' ssid='0x0' devno='0x0000'/>
++    </memballoon>
++    <panic model='s390'/>
++  </devices>
++</domain>
+diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
+index 2a2bf01ffa..a787f4f4a3 100644
+--- a/tests/qemuxml2xmltest.c
++++ b/tests/qemuxml2xmltest.c
+@@ -400,6 +400,9 @@ mymain(void)
+             QEMU_CAPS_VIRTIO_SCSI);
+     DO_TEST("disk-virtio-scsi-ioeventfd",
+             QEMU_CAPS_VIRTIO_SCSI);
++    DO_TEST("disk-virtio-s390-zpci",
++            QEMU_CAPS_DEVICE_ZPCI,
++            QEMU_CAPS_CCW);
+     DO_TEST("disk-scsi-megasas",
+             QEMU_CAPS_SCSI_MEGASAS);
+     DO_TEST("disk-scsi-mptsas1068",
+@@ -482,6 +485,9 @@ mymain(void)
+     DO_TEST("hostdev-usb-address", NONE);
+     DO_TEST("hostdev-pci-address", NONE);
+     DO_TEST("hostdev-vfio", NONE);
++    DO_TEST("hostdev-vfio-zpci",
++            QEMU_CAPS_DEVICE_ZPCI,
++            QEMU_CAPS_CCW);
+     DO_TEST("hostdev-mdev-precreated", NONE);
+     DO_TEST("hostdev-mdev-display", QEMU_CAPS_VFIO_PCI_DISPLAY);
+     DO_TEST("pci-rom", NONE);
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-conf-Introduce-virCPUDefCheckFeatures.patch b/SOURCES/libvirt-conf-Introduce-virCPUDefCheckFeatures.patch
new file mode 100644
index 0000000..509c5cf
--- /dev/null
+++ b/SOURCES/libvirt-conf-Introduce-virCPUDefCheckFeatures.patch
@@ -0,0 +1,103 @@
+From 0bed2e17ea6469ccabb374c0520a97706b281911 Mon Sep 17 00:00:00 2001
+Message-Id: <0bed2e17ea6469ccabb374c0520a97706b281911@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:26:06 +0200
+Subject: [PATCH] conf: Introduce virCPUDefCheckFeatures
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This API can be used to check whether a CPU definition contains features
+matching a given filter.
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit 4e6f58b8d55d44fa9f80736b2745b44710f6e25a)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1697627
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <ea489f203e2d52250acb1b9656de6aba8355f3a6.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/conf/cpu_conf.c      | 33 +++++++++++++++++++++++++++++++++
+ src/conf/cpu_conf.h      |  6 ++++++
+ src/libvirt_private.syms |  1 +
+ 3 files changed, 40 insertions(+)
+
+diff --git a/src/conf/cpu_conf.c b/src/conf/cpu_conf.c
+index 51e2a83eae..4cccea9981 100644
+--- a/src/conf/cpu_conf.c
++++ b/src/conf/cpu_conf.c
+@@ -872,6 +872,39 @@ virCPUDefFilterFeatures(virCPUDefPtr cpu,
+ }
+ 
+ 
++/**
++ * virCPUDefCheckFeatures:
++ *
++ * Check CPU features for which @filter reports true and store them in a NULL
++ * terminated list returned via @features.
++ *
++ * Returns the number of features matching @filter or -1 on error.
++ */
++int
++virCPUDefCheckFeatures(virCPUDefPtr cpu,
++                       virCPUDefFeatureFilter filter,
++                       void *opaque,
++                       char ***features)
++{
++    VIR_AUTOSTRINGLIST list = NULL;
++    size_t n = 0;
++    size_t i;
++
++    *features = NULL;
++
++    for (i = 0; i < cpu->nfeatures; i++) {
++        if (filter(cpu->features[i].name, opaque)) {
++            if (virStringListAdd(&list, cpu->features[i].name) < 0)
++                return -1;
++            n++;
++        }
++    }
++
++    VIR_STEAL_PTR(*features, list);
++    return n;
++}
++
++
+ bool
+ virCPUDefIsEqual(virCPUDefPtr src,
+                  virCPUDefPtr dst,
+diff --git a/src/conf/cpu_conf.h b/src/conf/cpu_conf.h
+index ad25932b9b..cba0ec7c81 100644
+--- a/src/conf/cpu_conf.h
++++ b/src/conf/cpu_conf.h
+@@ -225,6 +225,12 @@ virCPUDefFilterFeatures(virCPUDefPtr cpu,
+                         virCPUDefFeatureFilter filter,
+                         void *opaque);
+ 
++int
++virCPUDefCheckFeatures(virCPUDefPtr cpu,
++                       virCPUDefFeatureFilter filter,
++                       void *opaque,
++                       char ***features);
++
+ virCPUDefPtr *
+ virCPUDefListParse(const char **xmlCPUs,
+                    unsigned int ncpus,
+diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
+index 06374deaae..0290f960a0 100644
+--- a/src/libvirt_private.syms
++++ b/src/libvirt_private.syms
+@@ -72,6 +72,7 @@ virCapabilitiesSetNetPrefix;
+ virCPUCacheModeTypeFromString;
+ virCPUCacheModeTypeToString;
+ virCPUDefAddFeature;
++virCPUDefCheckFeatures;
+ virCPUDefCopy;
+ virCPUDefCopyModel;
+ virCPUDefCopyModelFilter;
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-conf-use-virXMLFormatElement-in-virDomainDeviceInfoFormat.patch b/SOURCES/libvirt-conf-use-virXMLFormatElement-in-virDomainDeviceInfoFormat.patch
new file mode 100644
index 0000000..1747e21
--- /dev/null
+++ b/SOURCES/libvirt-conf-use-virXMLFormatElement-in-virDomainDeviceInfoFormat.patch
@@ -0,0 +1,154 @@
+From 2566a32fae64fa5cc8a3d3c30778d0ea7d8c4faa Mon Sep 17 00:00:00 2001
+Message-Id: <2566a32fae64fa5cc8a3d3c30778d0ea7d8c4faa@dist-git>
+From: Yi Min Zhao <zyimin@linux.ibm.com>
+Date: Mon, 8 Apr 2019 10:57:24 +0200
+Subject: [PATCH] conf: use virXMLFormatElement() in
+ virDomainDeviceInfoFormat()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+In order to add zPCI child element for PCI address, we update
+virDomainDeviceInfoFormat() to format device info by helper function
+virXMLFormatElement(). Then we could simply format zPCI address into
+child buffer later.
+
+Signed-off-by: Yi Min Zhao <zyimin@linux.ibm.com>
+Reviewed-by: Boris Fiuczynski <fiuczy@linux.ibm.com>
+Reviewed-by: Andrea Bolognani <abologna@redhat.com>
+
+(cherry picked from commit 0d6b87335c00451b0923ecc91d617f71e4135bf8)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1508149
+
+Signed-off-by: Andrea Bolognani <abologna@redhat.com>
+Message-Id: <20190408085732.28684-8-abologna@redhat.com>
+Reviewed-by: Laine Stump <laine@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/conf/domain_conf.c | 40 ++++++++++++++++++++++------------------
+ 1 file changed, 22 insertions(+), 18 deletions(-)
+
+diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
+index e62f78471c..bcb0558bc3 100644
+--- a/src/conf/domain_conf.c
++++ b/src/conf/domain_conf.c
+@@ -6447,6 +6447,8 @@ virDomainDeviceInfoFormat(virBufferPtr buf,
+                           virDomainDeviceInfoPtr info,
+                           unsigned int flags)
+ {
++    virBuffer attrBuf = VIR_BUFFER_INITIALIZER;
++
+     if ((flags & VIR_DOMAIN_DEF_FORMAT_ALLOW_BOOT) && info->bootIndex) {
+         virBufferAsprintf(buf, "<boot order='%u'", info->bootIndex);
+ 
+@@ -6491,13 +6493,13 @@ virDomainDeviceInfoFormat(virBufferPtr buf,
+         info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390)
+         return;
+ 
+-    virBufferAsprintf(buf, "<address type='%s'",
++    virBufferAsprintf(&attrBuf, " type='%s'",
+                       virDomainDeviceAddressTypeToString(info->type));
+ 
+     switch ((virDomainDeviceAddressType) info->type) {
+     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI:
+         if (!virPCIDeviceAddressIsEmpty(&info->addr.pci)) {
+-            virBufferAsprintf(buf, " domain='0x%.4x' bus='0x%.2x' "
++            virBufferAsprintf(&attrBuf, " domain='0x%.4x' bus='0x%.2x' "
+                               "slot='0x%.2x' function='0x%.1x'",
+                               info->addr.pci.domain,
+                               info->addr.pci.bus,
+@@ -6505,13 +6507,13 @@ virDomainDeviceInfoFormat(virBufferPtr buf,
+                               info->addr.pci.function);
+         }
+         if (info->addr.pci.multi) {
+-           virBufferAsprintf(buf, " multifunction='%s'",
+-                             virTristateSwitchTypeToString(info->addr.pci.multi));
++            virBufferAsprintf(&attrBuf, " multifunction='%s'",
++                              virTristateSwitchTypeToString(info->addr.pci.multi));
+         }
+         break;
+ 
+     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DRIVE:
+-        virBufferAsprintf(buf, " controller='%d' bus='%d' target='%d' unit='%d'",
++        virBufferAsprintf(&attrBuf, " controller='%d' bus='%d' target='%d' unit='%d'",
+                           info->addr.drive.controller,
+                           info->addr.drive.bus,
+                           info->addr.drive.target,
+@@ -6519,34 +6521,34 @@ virDomainDeviceInfoFormat(virBufferPtr buf,
+         break;
+ 
+     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_SERIAL:
+-        virBufferAsprintf(buf, " controller='%d' bus='%d' port='%d'",
++        virBufferAsprintf(&attrBuf, " controller='%d' bus='%d' port='%d'",
+                           info->addr.vioserial.controller,
+                           info->addr.vioserial.bus,
+                           info->addr.vioserial.port);
+         break;
+ 
+     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCID:
+-        virBufferAsprintf(buf, " controller='%d' slot='%d'",
++        virBufferAsprintf(&attrBuf, " controller='%d' slot='%d'",
+                           info->addr.ccid.controller,
+                           info->addr.ccid.slot);
+         break;
+ 
+     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_USB:
+-        virBufferAsprintf(buf, " bus='%d'", info->addr.usb.bus);
++        virBufferAsprintf(&attrBuf, " bus='%d'", info->addr.usb.bus);
+         if (virDomainUSBAddressPortIsValid(info->addr.usb.port)) {
+-            virBufferAddLit(buf, " port='");
+-            virDomainUSBAddressPortFormatBuf(buf, info->addr.usb.port);
+-            virBufferAddLit(buf, "'");
++            virBufferAddLit(&attrBuf, " port='");
++            virDomainUSBAddressPortFormatBuf(&attrBuf, info->addr.usb.port);
++            virBufferAddLit(&attrBuf, "'");
+         }
+         break;
+ 
+     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_SPAPRVIO:
+         if (info->addr.spaprvio.has_reg)
+-            virBufferAsprintf(buf, " reg='0x%llx'", info->addr.spaprvio.reg);
++            virBufferAsprintf(&attrBuf, " reg='0x%llx'", info->addr.spaprvio.reg);
+         break;
+ 
+     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW:
+-        virBufferAsprintf(buf, " cssid='0x%x' ssid='0x%x' devno='0x%04x'",
++        virBufferAsprintf(&attrBuf, " cssid='0x%x' ssid='0x%x' devno='0x%04x'",
+                           info->addr.ccw.cssid,
+                           info->addr.ccw.ssid,
+                           info->addr.ccw.devno);
+@@ -6557,15 +6559,15 @@ virDomainDeviceInfoFormat(virBufferPtr buf,
+ 
+     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_ISA:
+         if (info->addr.isa.iobase > 0)
+-            virBufferAsprintf(buf, " iobase='0x%x'", info->addr.isa.iobase);
++            virBufferAsprintf(&attrBuf, " iobase='0x%x'", info->addr.isa.iobase);
+         if (info->addr.isa.irq > 0)
+-            virBufferAsprintf(buf, " irq='0x%x'", info->addr.isa.irq);
++            virBufferAsprintf(&attrBuf, " irq='0x%x'", info->addr.isa.irq);
+         break;
+ 
+     case VIR_DOMAIN_DEVICE_ADDRESS_TYPE_DIMM:
+-        virBufferAsprintf(buf, " slot='%u'", info->addr.dimm.slot);
++        virBufferAsprintf(&attrBuf, " slot='%u'", info->addr.dimm.slot);
+         if (info->addr.dimm.base)
+-            virBufferAsprintf(buf, " base='0x%llx'", info->addr.dimm.base);
++            virBufferAsprintf(&attrBuf, " base='0x%llx'", info->addr.dimm.base);
+ 
+         break;
+ 
+@@ -6575,7 +6577,9 @@ virDomainDeviceInfoFormat(virBufferPtr buf,
+         break;
+     }
+ 
+-    virBufferAddLit(buf, "/>\n");
++    virXMLFormatElement(buf, "address", &attrBuf, NULL);
++
++    virBufferFreeAndReset(&attrBuf);
+ }
+ 
+ static int
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-cpu-Don-t-access-invalid-memory-in-virCPUx86Translate.patch b/SOURCES/libvirt-cpu-Don-t-access-invalid-memory-in-virCPUx86Translate.patch
new file mode 100644
index 0000000..d8224ba
--- /dev/null
+++ b/SOURCES/libvirt-cpu-Don-t-access-invalid-memory-in-virCPUx86Translate.patch
@@ -0,0 +1,59 @@
+From b339a54e493d97a5616be8883d1a0b4ebcd149d3 Mon Sep 17 00:00:00 2001
+Message-Id: <b339a54e493d97a5616be8883d1a0b4ebcd149d3@dist-git>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Fri, 21 Jun 2019 09:25:18 +0200
+Subject: [PATCH] cpu: Don't access invalid memory in virCPUx86Translate
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Problem is that if there are no signatures for a CPU, then we
+still allocate cpu->signatures (even though with size 0). Later,
+we access cpu->signatures[0] if cpu->signatures is not NULL.
+
+ Invalid read of size 4
+    at 0x5F439D7: virCPUx86Translate (cpu_x86.c:2930)
+    by 0x5F3C239: virCPUTranslate (cpu.c:927)
+    by 0x57CE7A1: qemuProcessUpdateGuestCPU (qemu_process.c:5870)
+    ...
+  Address 0xf752d40 is 0 bytes after a block of size 0 alloc'd
+    at 0x4C30EC6: calloc (vg_replace_malloc.c:711)
+    by 0x5DBDE4E: virAllocN (viralloc.c:190)
+    by 0x5F3E4FA: x86ModelCopySignatures (cpu_x86.c:990)
+    by 0x5F3E60F: x86ModelCopy (cpu_x86.c:1008)
+    by 0x5F3E7CB: x86ModelFromCPU (cpu_x86.c:1068)
+    by 0x5F4397E: virCPUx86Translate (cpu_x86.c:2922)
+    by 0x5F3C239: virCPUTranslate (cpu.c:927)
+    by 0x57CE7A1: qemuProcessUpdateGuestCPU (qemu_process.c:5870)
+    ...
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
+(cherry picked from commit 62cb9c335c43a722e81ac0a1ed6e1111ba1d428b)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1686895
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <b36b22d237a7044a473e9b72de9763b2c603198c.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/cpu/cpu_x86.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
+index 24569a90f3..66aa5a612c 100644
+--- a/src/cpu/cpu_x86.c
++++ b/src/cpu/cpu_x86.c
+@@ -985,6 +985,9 @@ x86ModelCopySignatures(virCPUx86ModelPtr dst,
+ {
+     size_t i;
+ 
++    if (src->nsignatures == 0)
++        return 0;
++
+     if (VIR_ALLOC_N(dst->signatures, src->nsignatures) < 0)
+         return -1;
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-cpu-Introduce-virCPUDataAddFeature.patch b/SOURCES/libvirt-cpu-Introduce-virCPUDataAddFeature.patch
new file mode 100644
index 0000000..89765cf
--- /dev/null
+++ b/SOURCES/libvirt-cpu-Introduce-virCPUDataAddFeature.patch
@@ -0,0 +1,176 @@
+From 992af2f6564b899142a2be5f342e0cdbdd13eadc Mon Sep 17 00:00:00 2001
+Message-Id: <992af2f6564b899142a2be5f342e0cdbdd13eadc@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:25:59 +0200
+Subject: [PATCH] cpu: Introduce virCPUDataAddFeature
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This is a generic replacement for the former virCPUx86DataAddFeature,
+which worked on the generic virCPUDataPtr anyway.
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit df73078c612a70e48aa76e889a7026e2daa47b16)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1697627
+
+Conflicts:
+	src/cpu/cpu_x86.h
+            - downstream did not switch to #pragma once
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <4e946f702092fe5eb4c8235dbb98402b30876a5f.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/cpu/cpu.c                | 33 +++++++++++++++++++++++++++++++++
+ src/cpu/cpu.h                |  9 +++++++++
+ src/cpu/cpu_x86.c            |  3 ++-
+ src/cpu/cpu_x86.h            |  3 ---
+ src/libvirt_private.syms     |  2 +-
+ src/qemu/qemu_capabilities.c |  2 +-
+ 6 files changed, 46 insertions(+), 6 deletions(-)
+
+diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c
+index cc93c49418..a2d143c94a 100644
+--- a/src/cpu/cpu.c
++++ b/src/cpu/cpu.c
+@@ -1078,3 +1078,36 @@ virCPUValidateFeatures(virArch arch,
+     else
+         return 0;
+ }
++
++
++/**
++ * virCPUDataAddFeature:
++ *
++ * @cpuData: CPU data
++ * @name: feature to be added to @cpuData
++ *
++ * Adds a feature called @name to @cpuData.
++ *
++ * Returns 0 on success, -1 on error.
++ */
++int
++virCPUDataAddFeature(virCPUDataPtr cpuData,
++                     const char *name)
++{
++    struct cpuArchDriver *driver;
++
++    VIR_DEBUG("arch=%s, cpuData=%p, name=%s",
++              virArchToString(cpuData->arch), cpuData, name);
++
++    if (!(driver = cpuGetSubDriver(cpuData->arch)))
++        return -1;
++
++    if (!driver->dataAddFeature) {
++        virReportError(VIR_ERR_NO_SUPPORT,
++                       _("cannot add guest CPU feature for %s architecture"),
++                       virArchToString(cpuData->arch));
++        return -1;
++    }
++
++    return driver->dataAddFeature(cpuData, name);
++}
+diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h
+index 81119b6aeb..e5fae31e30 100644
+--- a/src/cpu/cpu.h
++++ b/src/cpu/cpu.h
+@@ -121,6 +121,10 @@ typedef virCPUDefPtr
+ typedef int
+ (*virCPUArchValidateFeatures)(virCPUDefPtr cpu);
+ 
++typedef int
++(*virCPUArchDataAddFeature)(virCPUDataPtr cpuData,
++                            const char *name);
++
+ struct cpuArchDriver {
+     const char *name;
+     const virArch *arch;
+@@ -143,6 +147,7 @@ struct cpuArchDriver {
+     virCPUArchExpandFeatures expandFeatures;
+     virCPUArchCopyMigratable copyMigratable;
+     virCPUArchValidateFeatures validateFeatures;
++    virCPUArchDataAddFeature dataAddFeature;
+ };
+ 
+ 
+@@ -260,6 +265,10 @@ virCPUValidateFeatures(virArch arch,
+                        virCPUDefPtr cpu)
+     ATTRIBUTE_NONNULL(2);
+ 
++int
++virCPUDataAddFeature(virCPUDataPtr cpuData,
++                     const char *name);
++
+ /* virCPUDataFormat and virCPUDataParse are implemented for unit tests only and
+  * have no real-life usage
+  */
+diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
+index 3c1bd623db..ead962ae06 100644
+--- a/src/cpu/cpu_x86.c
++++ b/src/cpu/cpu_x86.c
+@@ -3316,7 +3316,7 @@ virCPUx86DataSetVendor(virCPUDataPtr cpuData,
+ }
+ 
+ 
+-int
++static int
+ virCPUx86DataAddFeature(virCPUDataPtr cpuData,
+                         const char *name)
+ {
+@@ -3361,4 +3361,5 @@ struct cpuArchDriver cpuDriverX86 = {
+     .expandFeatures = virCPUx86ExpandFeatures,
+     .copyMigratable = virCPUx86CopyMigratable,
+     .validateFeatures = virCPUx86ValidateFeatures,
++    .dataAddFeature = virCPUx86DataAddFeature,
+ };
+diff --git a/src/cpu/cpu_x86.h b/src/cpu/cpu_x86.h
+index 8b51cef9c1..519024b7c0 100644
+--- a/src/cpu/cpu_x86.h
++++ b/src/cpu/cpu_x86.h
+@@ -45,7 +45,4 @@ uint32_t virCPUx86DataGetSignature(virCPUDataPtr cpuData,
+ int virCPUx86DataSetVendor(virCPUDataPtr cpuData,
+                            const char *vendor);
+ 
+-int virCPUx86DataAddFeature(virCPUDataPtr cpuData,
+-                            const char *name);
+-
+ #endif /* __VIR_CPU_X86_H__ */
+diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
+index 57508de0c1..a20e0593f0 100644
+--- a/src/libvirt_private.syms
++++ b/src/libvirt_private.syms
+@@ -1187,6 +1187,7 @@ virCPUCompare;
+ virCPUCompareXML;
+ virCPUConvertLegacy;
+ virCPUCopyMigratable;
++virCPUDataAddFeature;
+ virCPUDataCheckFeature;
+ virCPUDataFormat;
+ virCPUDataFree;
+@@ -1205,7 +1206,6 @@ virCPUValidateFeatures;
+ 
+ # cpu/cpu_x86.h
+ virCPUx86DataAdd;
+-virCPUx86DataAddFeature;
+ virCPUx86DataGetSignature;
+ virCPUx86DataSetSignature;
+ virCPUx86DataSetVendor;
+diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
+index 78be2d35f4..4be0ec305f 100644
+--- a/src/qemu/qemu_capabilities.c
++++ b/src/qemu/qemu_capabilities.c
+@@ -2916,7 +2916,7 @@ virQEMUCapsGetCPUModelX86Data(virQEMUCapsPtr qemuCaps,
+                 (migratable && prop->migratable == VIR_TRISTATE_BOOL_NO))
+                 continue;
+ 
+-            if (virCPUx86DataAddFeature(data, name) < 0)
++            if (virCPUDataAddFeature(data, name) < 0)
+                 goto cleanup;
+ 
+             break;
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-cpu-allow-include-files-for-CPU-definition.patch b/SOURCES/libvirt-cpu-allow-include-files-for-CPU-definition.patch
new file mode 100644
index 0000000..84abe17
--- /dev/null
+++ b/SOURCES/libvirt-cpu-allow-include-files-for-CPU-definition.patch
@@ -0,0 +1,159 @@
+From 6438640b53fef3e889c21a2ed016638b91c5ac80 Mon Sep 17 00:00:00 2001
+Message-Id: <6438640b53fef3e889c21a2ed016638b91c5ac80@dist-git>
+From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= <berrange@redhat.com>
+Date: Fri, 21 Jun 2019 09:24:44 +0200
+Subject: [PATCH] cpu: allow include files for CPU definition
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Allow for syntax
+
+    <include filename="subdir/fooo.xml"/>
+
+to reference other files in the CPU database directory
+
+Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
+Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
+(cherry picked from commit eda5f575f2a7530fc7f6471f88496778a9bc9fcb)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1686895
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <800e5ebbc30502fd780a3ef84fe524f1dc0ffd67.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/cpu/cpu_map.c | 92 +++++++++++++++++++++++++++++++++++++++++++++--
+ 1 file changed, 89 insertions(+), 3 deletions(-)
+
+diff --git a/src/cpu/cpu_map.c b/src/cpu/cpu_map.c
+index d263eb8cdd..333c7ef24f 100644
+--- a/src/cpu/cpu_map.c
++++ b/src/cpu/cpu_map.c
+@@ -1,7 +1,7 @@
+ /*
+  * cpu_map.c: internal functions for handling CPU mapping configuration
+  *
+- * Copyright (C) 2009-2010 Red Hat, Inc.
++ * Copyright (C) 2009-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
+@@ -70,6 +70,89 @@ static int load(xmlXPathContextPtr ctxt,
+     return ret;
+ }
+ 
++static int
++cpuMapLoadInclude(const char *filename,
++                  cpuMapLoadCallback cb,
++                  void *data)
++{
++    xmlDocPtr xml = NULL;
++    xmlXPathContextPtr ctxt = NULL;
++    int ret = -1;
++    int element;
++    char *mapfile;
++
++    if (!(mapfile = virFileFindResource(filename,
++                                        abs_topsrcdir "/src/cpu",
++                                        PKGDATADIR)))
++        return -1;
++
++    VIR_DEBUG("Loading CPU map include from %s", mapfile);
++
++    if (!(xml = virXMLParseFileCtxt(mapfile, &ctxt)))
++        goto cleanup;
++
++    ctxt->node = xmlDocGetRootElement(xml);
++
++    for (element = 0; element < CPU_MAP_ELEMENT_LAST; element++) {
++        if (load(ctxt, element, cb, data) < 0) {
++            virReportError(VIR_ERR_INTERNAL_ERROR,
++                           _("cannot parse CPU map '%s'"), mapfile);
++            goto cleanup;
++        }
++    }
++
++    ret = 0;
++
++ cleanup:
++    xmlXPathFreeContext(ctxt);
++    xmlFreeDoc(xml);
++    VIR_FREE(mapfile);
++
++    return ret;
++}
++
++
++static int
++loadIncludes(xmlXPathContextPtr ctxt,
++             cpuMapLoadCallback callback,
++             void *data)
++{
++    int ret = -1;
++    xmlNodePtr ctxt_node;
++    xmlNodePtr *nodes = NULL;
++    int n;
++    size_t i;
++
++    ctxt_node = ctxt->node;
++
++    n = virXPathNodeSet("include", ctxt, &nodes);
++    if (n < 0)
++        goto cleanup;
++
++    for (i = 0; i < n; i++) {
++        char *filename = virXMLPropString(nodes[i], "filename");
++        if (!filename) {
++            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
++                           _("Missing 'filename' in CPU map include"));
++            goto cleanup;
++        }
++        VIR_DEBUG("Finding CPU map include '%s'", filename);
++        if (cpuMapLoadInclude(filename, callback, data) < 0) {
++            VIR_FREE(filename);
++            goto cleanup;
++        }
++        VIR_FREE(filename);
++    }
++
++    ret = 0;
++
++ cleanup:
++    ctxt->node = ctxt_node;
++    VIR_FREE(nodes);
++
++    return ret;
++}
++
+ 
+ int cpuMapLoad(const char *arch,
+                cpuMapLoadCallback cb,
+@@ -88,7 +171,7 @@ int cpuMapLoad(const char *arch,
+                                         PKGDATADIR)))
+         return -1;
+ 
+-    VIR_DEBUG("Loading CPU map from %s", mapfile);
++    VIR_DEBUG("Loading '%s' CPU map from %s", NULLSTR(arch), mapfile);
+ 
+     if (arch == NULL) {
+         virReportError(VIR_ERR_INTERNAL_ERROR,
+@@ -122,11 +205,14 @@ int cpuMapLoad(const char *arch,
+     for (element = 0; element < CPU_MAP_ELEMENT_LAST; element++) {
+         if (load(ctxt, element, cb, data) < 0) {
+             virReportError(VIR_ERR_INTERNAL_ERROR,
+-                           _("cannot parse CPU map for %s architecture"), arch);
++                           _("cannot parse CPU map '%s'"), mapfile);
+             goto cleanup;
+         }
+     }
+ 
++    if (loadIncludes(ctxt, cb, data) < 0)
++        goto cleanup;
++
+     ret = 0;
+ 
+  cleanup:
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-cpu-fix-cleanup-when-signature-parsing-fails.patch b/SOURCES/libvirt-cpu-fix-cleanup-when-signature-parsing-fails.patch
new file mode 100644
index 0000000..1b253a4
--- /dev/null
+++ b/SOURCES/libvirt-cpu-fix-cleanup-when-signature-parsing-fails.patch
@@ -0,0 +1,51 @@
+From 612913a764992dc1a9ae63762749ecee447427d7 Mon Sep 17 00:00:00 2001
+Message-Id: <612913a764992dc1a9ae63762749ecee447427d7@dist-git>
+From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= <berrange@redhat.com>
+Date: Fri, 21 Jun 2019 09:24:45 +0200
+Subject: [PATCH] cpu: fix cleanup when signature parsing fails
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Two pieces of code accidentally jumped to the wrong label when they
+failed causing incorrect cleanup, returning a partially initialized
+CPU model struct.
+
+Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
+Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
+(cherry picked from commit 118fcdd480ad38a3e8477f466f6a876dce7e9fa6)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1686895
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <5e9aedc6fd4f4570322a7d13626863bec0449283.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/cpu/cpu_x86.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
+index 89baf94d7d..124aa5fd5e 100644
+--- a/src/cpu/cpu_x86.c
++++ b/src/cpu/cpu_x86.c
+@@ -1250,7 +1250,7 @@ x86ModelParse(xmlXPathContextPtr ctxt,
+             virReportError(VIR_ERR_INTERNAL_ERROR,
+                            _("Invalid CPU signature family in model %s"),
+                            model->name);
+-            goto cleanup;
++            goto error;
+         }
+ 
+         rc = virXPathUInt("string(./signature/@model)", ctxt, &sigModel);
+@@ -1258,7 +1258,7 @@ x86ModelParse(xmlXPathContextPtr ctxt,
+             virReportError(VIR_ERR_INTERNAL_ERROR,
+                            _("Invalid CPU signature model in model %s"),
+                            model->name);
+-            goto cleanup;
++            goto error;
+         }
+ 
+         model->signature = x86MakeSignature(sigFamily, sigModel, 0);
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-cpu-push-more-parsing-logic-into-common-code.patch b/SOURCES/libvirt-cpu-push-more-parsing-logic-into-common-code.patch
new file mode 100644
index 0000000..357b983
--- /dev/null
+++ b/SOURCES/libvirt-cpu-push-more-parsing-logic-into-common-code.patch
@@ -0,0 +1,782 @@
+From 728231dcbbf2a4ab8a4bfe03fdf43d78bdeccbb0 Mon Sep 17 00:00:00 2001
+Message-Id: <728231dcbbf2a4ab8a4bfe03fdf43d78bdeccbb0@dist-git>
+From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= <berrange@redhat.com>
+Date: Fri, 21 Jun 2019 09:24:46 +0200
+Subject: [PATCH] cpu: push more parsing logic into common code
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The x86 and ppc impls both duplicate some logic when parsing CPU
+features. Change the callback signature so that this duplication can be
+pushed up a level to common code.
+
+Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
+Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
+(cherry picked from commit 0815f519784a7c565c543498777dc25f129620f9)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1686895
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <c770b678131dc5e207cbe84d276a2774e0c807c7.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/cpu/cpu_map.c   |  98 +++++++++++++---------
+ src/cpu/cpu_map.h   |  22 ++---
+ src/cpu/cpu_ppc64.c | 112 ++++++-------------------
+ src/cpu/cpu_x86.c   | 196 +++++++++++++-------------------------------
+ 4 files changed, 143 insertions(+), 285 deletions(-)
+
+diff --git a/src/cpu/cpu_map.c b/src/cpu/cpu_map.c
+index 333c7ef24f..ac7e58037a 100644
+--- a/src/cpu/cpu_map.c
++++ b/src/cpu/cpu_map.c
+@@ -35,31 +35,47 @@
+ 
+ VIR_LOG_INIT("cpu.cpu_map");
+ 
+-VIR_ENUM_IMPL(cpuMapElement, CPU_MAP_ELEMENT_LAST,
+-    "vendor",
+-    "feature",
+-    "model")
+-
+-
+-static int load(xmlXPathContextPtr ctxt,
+-                cpuMapElement element,
+-                cpuMapLoadCallback callback,
+-                void *data)
++static int
++loadData(const char *mapfile,
++         xmlXPathContextPtr ctxt,
++         const char *element,
++         cpuMapLoadCallback callback,
++         void *data)
+ {
+     int ret = -1;
+     xmlNodePtr ctxt_node;
+     xmlNodePtr *nodes = NULL;
+     int n;
++    size_t i;
++    int rv;
+ 
+     ctxt_node = ctxt->node;
+ 
+-    n = virXPathNodeSet(cpuMapElementTypeToString(element), ctxt, &nodes);
+-    if (n < 0)
++    if ((n = virXPathNodeSet(element, ctxt, &nodes)) < 0)
+         goto cleanup;
+ 
+-    if (n > 0 &&
+-        callback(element, ctxt, nodes, n, data) < 0)
++    if (n > 0 && !callback) {
++        virReportError(VIR_ERR_INTERNAL_ERROR,
++                       _("Unexpected element '%s' in CPU map '%s'"), element, mapfile);
+         goto cleanup;
++    }
++
++    for (i = 0; i < n; i++) {
++        xmlNodePtr old = ctxt->node;
++        char *name = virXMLPropString(nodes[i], "name");
++        if (!name) {
++            virReportError(VIR_ERR_INTERNAL_ERROR,
++                           _("cannot find %s name in CPU map '%s'"), element, mapfile);
++            goto cleanup;
++        }
++        VIR_DEBUG("Load %s name %s", element, name);
++        ctxt->node = nodes[i];
++        rv = callback(ctxt, name, data);
++        ctxt->node = old;
++        VIR_FREE(name);
++        if (rv < 0)
++            goto cleanup;
++    }
+ 
+     ret = 0;
+ 
+@@ -72,13 +88,14 @@ static int load(xmlXPathContextPtr ctxt,
+ 
+ static int
+ cpuMapLoadInclude(const char *filename,
+-                  cpuMapLoadCallback cb,
++                  cpuMapLoadCallback vendorCB,
++                  cpuMapLoadCallback featureCB,
++                  cpuMapLoadCallback modelCB,
+                   void *data)
+ {
+     xmlDocPtr xml = NULL;
+     xmlXPathContextPtr ctxt = NULL;
+     int ret = -1;
+-    int element;
+     char *mapfile;
+ 
+     if (!(mapfile = virFileFindResource(filename,
+@@ -93,13 +110,14 @@ cpuMapLoadInclude(const char *filename,
+ 
+     ctxt->node = xmlDocGetRootElement(xml);
+ 
+-    for (element = 0; element < CPU_MAP_ELEMENT_LAST; element++) {
+-        if (load(ctxt, element, cb, data) < 0) {
+-            virReportError(VIR_ERR_INTERNAL_ERROR,
+-                           _("cannot parse CPU map '%s'"), mapfile);
+-            goto cleanup;
+-        }
+-    }
++    if (loadData(mapfile, ctxt, "vendor", vendorCB, data) < 0)
++        goto cleanup;
++
++    if (loadData(mapfile, ctxt, "feature", featureCB, data) < 0)
++        goto cleanup;
++
++    if (loadData(mapfile, ctxt, "model", modelCB, data) < 0)
++        goto cleanup;
+ 
+     ret = 0;
+ 
+@@ -114,7 +132,9 @@ cpuMapLoadInclude(const char *filename,
+ 
+ static int
+ loadIncludes(xmlXPathContextPtr ctxt,
+-             cpuMapLoadCallback callback,
++             cpuMapLoadCallback vendorCB,
++             cpuMapLoadCallback featureCB,
++             cpuMapLoadCallback modelCB,
+              void *data)
+ {
+     int ret = -1;
+@@ -137,7 +157,7 @@ loadIncludes(xmlXPathContextPtr ctxt,
+             goto cleanup;
+         }
+         VIR_DEBUG("Finding CPU map include '%s'", filename);
+-        if (cpuMapLoadInclude(filename, callback, data) < 0) {
++        if (cpuMapLoadInclude(filename, vendorCB, featureCB, modelCB, data) < 0) {
+             VIR_FREE(filename);
+             goto cleanup;
+         }
+@@ -155,7 +175,9 @@ loadIncludes(xmlXPathContextPtr ctxt,
+ 
+ 
+ int cpuMapLoad(const char *arch,
+-               cpuMapLoadCallback cb,
++               cpuMapLoadCallback vendorCB,
++               cpuMapLoadCallback featureCB,
++               cpuMapLoadCallback modelCB,
+                void *data)
+ {
+     xmlDocPtr xml = NULL;
+@@ -163,7 +185,6 @@ int cpuMapLoad(const char *arch,
+     virBuffer buf = VIR_BUFFER_INITIALIZER;
+     char *xpath = NULL;
+     int ret = -1;
+-    int element;
+     char *mapfile;
+ 
+     if (!(mapfile = virFileFindResource("cpu_map.xml",
+@@ -179,12 +200,6 @@ int cpuMapLoad(const char *arch,
+         goto cleanup;
+     }
+ 
+-    if (cb == NULL) {
+-        virReportError(VIR_ERR_INTERNAL_ERROR,
+-                       "%s", _("no callback provided"));
+-        goto cleanup;
+-    }
+-
+     if (!(xml = virXMLParseFileCtxt(mapfile, &ctxt)))
+         goto cleanup;
+ 
+@@ -202,15 +217,16 @@ int cpuMapLoad(const char *arch,
+         goto cleanup;
+     }
+ 
+-    for (element = 0; element < CPU_MAP_ELEMENT_LAST; element++) {
+-        if (load(ctxt, element, cb, data) < 0) {
+-            virReportError(VIR_ERR_INTERNAL_ERROR,
+-                           _("cannot parse CPU map '%s'"), mapfile);
+-            goto cleanup;
+-        }
+-    }
++    if (loadData(mapfile, ctxt, "vendor", vendorCB, data) < 0)
++        goto cleanup;
+ 
+-    if (loadIncludes(ctxt, cb, data) < 0)
++    if (loadData(mapfile, ctxt, "feature", featureCB, data) < 0)
++        goto cleanup;
++
++    if (loadData(mapfile, ctxt, "model", modelCB, data) < 0)
++        goto cleanup;
++
++    if (loadIncludes(ctxt, vendorCB, featureCB, modelCB, data) < 0)
+         goto cleanup;
+ 
+     ret = 0;
+diff --git a/src/cpu/cpu_map.h b/src/cpu/cpu_map.h
+index 0c7507e98f..4596987150 100644
+--- a/src/cpu/cpu_map.h
++++ b/src/cpu/cpu_map.h
+@@ -26,28 +26,16 @@
+ 
+ # include "virxml.h"
+ 
+-
+-typedef enum {
+-    CPU_MAP_ELEMENT_VENDOR,
+-    CPU_MAP_ELEMENT_FEATURE,
+-    CPU_MAP_ELEMENT_MODEL,
+-
+-    CPU_MAP_ELEMENT_LAST
+-} cpuMapElement;
+-
+-VIR_ENUM_DECL(cpuMapElement)
+-
+-
+ typedef int
+-(*cpuMapLoadCallback)  (cpuMapElement element,
+-                        xmlXPathContextPtr ctxt,
+-                        xmlNodePtr *nodes,
+-                        int n,
++(*cpuMapLoadCallback)  (xmlXPathContextPtr ctxt,
++                        const char *name,
+                         void *data);
+ 
+ int
+ cpuMapLoad(const char *arch,
+-           cpuMapLoadCallback cb,
++           cpuMapLoadCallback vendorCB,
++           cpuMapLoadCallback featureCB,
++           cpuMapLoadCallback modelCB,
+            void *data);
+ 
+ #endif /* __VIR_CPU_MAP_H__ */
+diff --git a/src/cpu/cpu_ppc64.c b/src/cpu/cpu_ppc64.c
+index d562677fa3..75da5b77d8 100644
+--- a/src/cpu/cpu_ppc64.c
++++ b/src/cpu/cpu_ppc64.c
+@@ -281,21 +281,19 @@ ppc64MapFree(struct ppc64_map *map)
+     VIR_FREE(map);
+ }
+ 
+-static struct ppc64_vendor *
+-ppc64VendorParse(xmlXPathContextPtr ctxt,
+-                 struct ppc64_map *map)
++static int
++ppc64VendorParse(xmlXPathContextPtr ctxt ATTRIBUTE_UNUSED,
++                 const char *name,
++                 void *data)
+ {
++    struct ppc64_map *map = data;
+     struct ppc64_vendor *vendor;
+ 
+     if (VIR_ALLOC(vendor) < 0)
+-        return NULL;
++        return -1;
+ 
+-    vendor->name = virXPathString("string(@name)", ctxt);
+-    if (!vendor->name) {
+-        virReportError(VIR_ERR_INTERNAL_ERROR,
+-                       "%s", _("Missing CPU vendor name"));
++    if (VIR_STRDUP(vendor->name, name) < 0)
+         goto error;
+-    }
+ 
+     if (ppc64VendorFind(map, vendor->name)) {
+         virReportError(VIR_ERR_INTERNAL_ERROR,
+@@ -303,57 +301,36 @@ ppc64VendorParse(xmlXPathContextPtr ctxt,
+         goto error;
+     }
+ 
+-    return vendor;
++    if (VIR_APPEND_ELEMENT(map->vendors, map->nvendors, vendor) < 0)
++        goto error;
++
++    return 0;
+ 
+  error:
+     ppc64VendorFree(vendor);
+-    return NULL;
++    return -1;
+ }
+ 
+ 
+ static int
+-ppc64VendorsLoad(struct ppc64_map *map,
+-                 xmlXPathContextPtr ctxt,
+-                 xmlNodePtr *nodes,
+-                 int n)
+-{
+-    struct ppc64_vendor *vendor;
+-    size_t i;
+-
+-    if (VIR_ALLOC_N(map->vendors, n) < 0)
+-        return -1;
+-
+-    for (i = 0; i < n; i++) {
+-        ctxt->node = nodes[i];
+-        if (!(vendor = ppc64VendorParse(ctxt, map)))
+-            return -1;
+-        map->vendors[map->nvendors++] = vendor;
+-    }
+-
+-    return 0;
+-}
+-
+-
+-static struct ppc64_model *
+ ppc64ModelParse(xmlXPathContextPtr ctxt,
+-                struct ppc64_map *map)
++                const char *name,
++                void *data)
+ {
++    struct ppc64_map *map = data;
+     struct ppc64_model *model;
+     xmlNodePtr *nodes = NULL;
+     char *vendor = NULL;
+     unsigned long pvr;
+     size_t i;
+     int n;
++    int ret = -1;
+ 
+     if (VIR_ALLOC(model) < 0)
+         goto error;
+ 
+-    model->name = virXPathString("string(@name)", ctxt);
+-    if (!model->name) {
+-        virReportError(VIR_ERR_INTERNAL_ERROR,
+-                       "%s", _("Missing CPU model name"));
++    if (VIR_STRDUP(model->name, name) < 0)
+         goto error;
+-    }
+ 
+     if (ppc64ModelFind(map, model->name)) {
+         virReportError(VIR_ERR_INTERNAL_ERROR,
+@@ -410,63 +387,22 @@ ppc64ModelParse(xmlXPathContextPtr ctxt,
+         model->data.pvr[i].mask = pvr;
+     }
+ 
++    if (VIR_APPEND_ELEMENT(map->models, map->nmodels, model) < 0)
++        goto error;
++
++    ret = 0;
++
+  cleanup:
+     VIR_FREE(vendor);
+     VIR_FREE(nodes);
+-    return model;
++    return ret;
+ 
+  error:
+     ppc64ModelFree(model);
+-    model = NULL;
+     goto cleanup;
+ }
+ 
+ 
+-static int
+-ppc64ModelsLoad(struct ppc64_map *map,
+-                xmlXPathContextPtr ctxt,
+-                xmlNodePtr *nodes,
+-                int n)
+-{
+-    struct ppc64_model *model;
+-    size_t i;
+-
+-    if (VIR_ALLOC_N(map->models, n) < 0)
+-        return -1;
+-
+-    for (i = 0; i < n; i++) {
+-        ctxt->node = nodes[i];
+-        if (!(model = ppc64ModelParse(ctxt, map)))
+-            return -1;
+-        map->models[map->nmodels++] = model;
+-    }
+-
+-    return 0;
+-}
+-
+-
+-static int
+-ppc64MapLoadCallback(cpuMapElement element,
+-                     xmlXPathContextPtr ctxt,
+-                     xmlNodePtr *nodes,
+-                     int n,
+-                     void *data)
+-{
+-    struct ppc64_map *map = data;
+-
+-    switch (element) {
+-    case CPU_MAP_ELEMENT_VENDOR:
+-        return ppc64VendorsLoad(map, ctxt, nodes, n);
+-    case CPU_MAP_ELEMENT_MODEL:
+-        return ppc64ModelsLoad(map, ctxt, nodes, n);
+-    case CPU_MAP_ELEMENT_FEATURE:
+-    case CPU_MAP_ELEMENT_LAST:
+-        break;
+-    }
+-
+-    return 0;
+-}
+-
+ static struct ppc64_map *
+ ppc64LoadMap(void)
+ {
+@@ -475,7 +411,7 @@ ppc64LoadMap(void)
+     if (VIR_ALLOC(map) < 0)
+         goto error;
+ 
+-    if (cpuMapLoad("ppc64", ppc64MapLoadCallback, map) < 0)
++    if (cpuMapLoad("ppc64", ppc64VendorParse, NULL, ppc64ModelParse, map) < 0)
+         goto error;
+ 
+     return map;
+diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
+index 124aa5fd5e..11dbd1e757 100644
+--- a/src/cpu/cpu_x86.c
++++ b/src/cpu/cpu_x86.c
+@@ -720,22 +720,21 @@ x86VendorFind(virCPUx86MapPtr map,
+ }
+ 
+ 
+-static virCPUx86VendorPtr
++static int
+ x86VendorParse(xmlXPathContextPtr ctxt,
+-               virCPUx86MapPtr map)
++               const char *name,
++               void *data)
+ {
++    virCPUx86MapPtr map = data;
+     virCPUx86VendorPtr vendor = NULL;
+     char *string = NULL;
++    int ret = -1;
+ 
+     if (VIR_ALLOC(vendor) < 0)
+         goto error;
+ 
+-    vendor->name = virXPathString("string(@name)", ctxt);
+-    if (!vendor->name) {
+-        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+-                       _("Missing CPU vendor name"));
++    if (VIR_STRDUP(vendor->name, name) < 0)
+         goto error;
+-    }
+ 
+     if (x86VendorFind(map, vendor->name)) {
+         virReportError(VIR_ERR_INTERNAL_ERROR,
+@@ -754,40 +753,21 @@ x86VendorParse(xmlXPathContextPtr ctxt,
+     if (virCPUx86VendorToCPUID(string, &vendor->cpuid) < 0)
+         goto error;
+ 
++    if (VIR_APPEND_ELEMENT(map->vendors, map->nvendors, vendor) < 0)
++        goto error;
++
++    ret = 0;
++
+  cleanup:
+     VIR_FREE(string);
+-    return vendor;
++    return ret;
+ 
+  error:
+     x86VendorFree(vendor);
+-    vendor = NULL;
+     goto cleanup;
+ }
+ 
+ 
+-static int
+-x86VendorsLoad(virCPUx86MapPtr map,
+-               xmlXPathContextPtr ctxt,
+-               xmlNodePtr *nodes,
+-               int n)
+-{
+-    virCPUx86VendorPtr vendor;
+-    size_t i;
+-
+-    if (VIR_ALLOC_N(map->vendors, n) < 0)
+-        return -1;
+-
+-    for (i = 0; i < n; i++) {
+-        ctxt->node = nodes[i];
+-        if (!(vendor = x86VendorParse(ctxt, map)))
+-            return -1;
+-        map->vendors[map->nvendors++] = vendor;
+-    }
+-
+-    return 0;
+-}
+-
+-
+ static virCPUx86FeaturePtr
+ x86FeatureNew(void)
+ {
+@@ -909,27 +889,27 @@ x86ParseCPUID(xmlXPathContextPtr ctxt,
+ }
+ 
+ 
+-static virCPUx86FeaturePtr
++static int
+ x86FeatureParse(xmlXPathContextPtr ctxt,
+-                virCPUx86MapPtr map)
++                const char *name,
++                void *data)
+ {
++    virCPUx86MapPtr map = data;
+     xmlNodePtr *nodes = NULL;
+     virCPUx86FeaturePtr feature;
+     virCPUx86CPUID cpuid;
+     size_t i;
+     int n;
+     char *str = NULL;
++    int ret = -1;
+ 
+     if (!(feature = x86FeatureNew()))
+         goto error;
+ 
+     feature->migratable = true;
+-    feature->name = virXPathString("string(@name)", ctxt);
+-    if (!feature->name) {
+-        virReportError(VIR_ERR_INTERNAL_ERROR,
+-                       "%s", _("Missing CPU feature name"));
++
++    if (VIR_STRDUP(feature->name, name) < 0)
+         goto error;
+-    }
+ 
+     if (x86FeatureFind(map, feature->name)) {
+         virReportError(VIR_ERR_INTERNAL_ERROR,
+@@ -957,46 +937,28 @@ x86FeatureParse(xmlXPathContextPtr ctxt,
+             goto error;
+     }
+ 
++    if (!feature->migratable &&
++        VIR_APPEND_ELEMENT_COPY(map->migrate_blockers,
++                                map->nblockers,
++                                feature) < 0)
++        goto error;
++
++    if (VIR_APPEND_ELEMENT(map->features, map->nfeatures, feature) < 0)
++        goto error;
++
++    ret = 0;
++
+  cleanup:
+     VIR_FREE(nodes);
+     VIR_FREE(str);
+-    return feature;
++    return ret;
+ 
+  error:
+     x86FeatureFree(feature);
+-    feature = NULL;
+     goto cleanup;
+ }
+ 
+ 
+-static int
+-x86FeaturesLoad(virCPUx86MapPtr map,
+-                xmlXPathContextPtr ctxt,
+-                xmlNodePtr *nodes,
+-                int n)
+-{
+-    virCPUx86FeaturePtr feature;
+-    size_t i;
+-
+-    if (VIR_ALLOC_N(map->features, n) < 0)
+-        return -1;
+-
+-    for (i = 0; i < n; i++) {
+-        ctxt->node = nodes[i];
+-        if (!(feature = x86FeatureParse(ctxt, map)))
+-            return -1;
+-        map->features[map->nfeatures++] = feature;
+-        if (!feature->migratable &&
+-            VIR_APPEND_ELEMENT(map->migrate_blockers,
+-                               map->nblockers,
+-                               feature) < 0)
+-            return -1;
+-    }
+-
+-    return 0;
+-}
+-
+-
+ static virCPUx86ModelPtr
+ x86ModelNew(void)
+ {
+@@ -1192,47 +1154,46 @@ x86ModelCompare(virCPUx86ModelPtr model1,
+ }
+ 
+ 
+-static virCPUx86ModelPtr
++static int
+ x86ModelParse(xmlXPathContextPtr ctxt,
+-              virCPUx86MapPtr map)
++              const char *name,
++              void *data)
+ {
++    virCPUx86MapPtr map = data;
+     xmlNodePtr *nodes = NULL;
+     virCPUx86ModelPtr model;
+     char *vendor = NULL;
+     size_t i;
+     int n;
++    int ret = -1;
+ 
+     if (!(model = x86ModelNew()))
+         goto error;
+ 
+-    model->name = virXPathString("string(@name)", ctxt);
+-    if (!model->name) {
+-        virReportError(VIR_ERR_INTERNAL_ERROR,
+-                       "%s", _("Missing CPU model name"));
++    if (VIR_STRDUP(model->name, name) < 0)
+         goto error;
+-    }
+ 
+     if (virXPathNode("./model", ctxt)) {
+         virCPUx86ModelPtr ancestor;
+-        char *name;
++        char *anname;
+ 
+-        name = virXPathString("string(./model/@name)", ctxt);
+-        if (!name) {
++        anname = virXPathString("string(./model/@name)", ctxt);
++        if (!anname) {
+             virReportError(VIR_ERR_INTERNAL_ERROR,
+                            _("Missing ancestor's name in CPU model %s"),
+                            model->name);
+             goto error;
+         }
+ 
+-        if (!(ancestor = x86ModelFind(map, name))) {
++        if (!(ancestor = x86ModelFind(map, anname))) {
+             virReportError(VIR_ERR_INTERNAL_ERROR,
+                            _("Ancestor model %s not found for CPU model %s"),
+-                           name, model->name);
+-            VIR_FREE(name);
++                           anname, model->name);
++            VIR_FREE(anname);
+             goto error;
+         }
+ 
+-        VIR_FREE(name);
++        VIR_FREE(anname);
+ 
+         model->vendor = ancestor->vendor;
+         model->signature = ancestor->signature;
+@@ -1287,62 +1248,43 @@ x86ModelParse(xmlXPathContextPtr ctxt,
+ 
+     for (i = 0; i < n; i++) {
+         virCPUx86FeaturePtr feature;
+-        char *name;
++        char *ftname;
+ 
+-        if (!(name = virXMLPropString(nodes[i], "name"))) {
++        if (!(ftname = virXMLPropString(nodes[i], "name"))) {
+             virReportError(VIR_ERR_INTERNAL_ERROR,
+                            _("Missing feature name for CPU model %s"), model->name);
+             goto error;
+         }
+ 
+-        if (!(feature = x86FeatureFind(map, name))) {
++        if (!(feature = x86FeatureFind(map, ftname))) {
+             virReportError(VIR_ERR_INTERNAL_ERROR,
+                            _("Feature %s required by CPU model %s not found"),
+-                           name, model->name);
+-            VIR_FREE(name);
++                           ftname, model->name);
++            VIR_FREE(ftname);
+             goto error;
+         }
+-        VIR_FREE(name);
++        VIR_FREE(ftname);
+ 
+         if (x86DataAdd(&model->data, &feature->data))
+             goto error;
+     }
+ 
++    if (VIR_APPEND_ELEMENT(map->models, map->nmodels, model) < 0)
++        goto error;
++
++    ret = 0;
++
+  cleanup:
+     VIR_FREE(vendor);
+     VIR_FREE(nodes);
+-    return model;
++    return ret;
+ 
+  error:
+     x86ModelFree(model);
+-    model = NULL;
+     goto cleanup;
+ }
+ 
+ 
+-static int
+-x86ModelsLoad(virCPUx86MapPtr map,
+-              xmlXPathContextPtr ctxt,
+-              xmlNodePtr *nodes,
+-              int n)
+-{
+-    virCPUx86ModelPtr model;
+-    size_t i;
+-
+-    if (VIR_ALLOC_N(map->models, n) < 0)
+-        return -1;
+-
+-    for (i = 0; i < n; i++) {
+-        ctxt->node = nodes[i];
+-        if (!(model = x86ModelParse(ctxt, map)))
+-            return -1;
+-        map->models[map->nmodels++] = model;
+-    }
+-
+-    return 0;
+-}
+-
+-
+ static void
+ x86MapFree(virCPUx86MapPtr map)
+ {
+@@ -1372,30 +1314,6 @@ x86MapFree(virCPUx86MapPtr map)
+ }
+ 
+ 
+-static int
+-x86MapLoadCallback(cpuMapElement element,
+-                   xmlXPathContextPtr ctxt,
+-                   xmlNodePtr *nodes,
+-                   int n,
+-                   void *data)
+-{
+-    virCPUx86MapPtr map = data;
+-
+-    switch (element) {
+-    case CPU_MAP_ELEMENT_VENDOR:
+-        return x86VendorsLoad(map, ctxt, nodes, n);
+-    case CPU_MAP_ELEMENT_FEATURE:
+-        return x86FeaturesLoad(map, ctxt, nodes, n);
+-    case CPU_MAP_ELEMENT_MODEL:
+-        return x86ModelsLoad(map, ctxt, nodes, n);
+-    case CPU_MAP_ELEMENT_LAST:
+-        break;
+-    }
+-
+-    return 0;
+-}
+-
+-
+ static virCPUx86MapPtr
+ virCPUx86LoadMap(void)
+ {
+@@ -1404,7 +1322,7 @@ virCPUx86LoadMap(void)
+     if (VIR_ALLOC(map) < 0)
+         return NULL;
+ 
+-    if (cpuMapLoad("x86", x86MapLoadCallback, map) < 0)
++    if (cpuMapLoad("x86", x86VendorParse, x86FeatureParse, x86ModelParse, map) < 0)
+         goto error;
+ 
+     return map;
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-cpu-simplify-failure-cleanup-paths.patch b/SOURCES/libvirt-cpu-simplify-failure-cleanup-paths.patch
new file mode 100644
index 0000000..74ad548
--- /dev/null
+++ b/SOURCES/libvirt-cpu-simplify-failure-cleanup-paths.patch
@@ -0,0 +1,397 @@
+From 85d367abe6063225117cc27c85e01e36a7b70409 Mon Sep 17 00:00:00 2001
+Message-Id: <85d367abe6063225117cc27c85e01e36a7b70409@dist-git>
+From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= <berrange@redhat.com>
+Date: Fri, 21 Jun 2019 09:24:47 +0200
+Subject: [PATCH] cpu: simplify failure cleanup paths
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Get rid of the separate 'error:' label, so all code paths jump straight
+to the 'cleanup:' label.
+
+Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
+Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
+(cherry picked from commit 18cab54c3a0bc72390f29300684396690a7ecf51)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1686895
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <40ff4abfea153cf8210286a84967c3ca7850b775.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/cpu/cpu_ppc64.c | 38 ++++++++++++------------
+ src/cpu/cpu_x86.c   | 71 ++++++++++++++++++++-------------------------
+ 2 files changed, 49 insertions(+), 60 deletions(-)
+
+diff --git a/src/cpu/cpu_ppc64.c b/src/cpu/cpu_ppc64.c
+index 75da5b77d8..fcba7e9b37 100644
+--- a/src/cpu/cpu_ppc64.c
++++ b/src/cpu/cpu_ppc64.c
+@@ -288,27 +288,28 @@ ppc64VendorParse(xmlXPathContextPtr ctxt ATTRIBUTE_UNUSED,
+ {
+     struct ppc64_map *map = data;
+     struct ppc64_vendor *vendor;
++    int ret = -1;
+ 
+     if (VIR_ALLOC(vendor) < 0)
+         return -1;
+ 
+     if (VIR_STRDUP(vendor->name, name) < 0)
+-        goto error;
++        goto cleanup;
+ 
+     if (ppc64VendorFind(map, vendor->name)) {
+         virReportError(VIR_ERR_INTERNAL_ERROR,
+                        _("CPU vendor %s already defined"), vendor->name);
+-        goto error;
++        goto cleanup;
+     }
+ 
+     if (VIR_APPEND_ELEMENT(map->vendors, map->nvendors, vendor) < 0)
+-        goto error;
++        goto cleanup;
+ 
+-    return 0;
++    ret = 0;
+ 
+- error:
++ cleanup:
+     ppc64VendorFree(vendor);
+-    return -1;
++    return ret;
+ }
+ 
+ 
+@@ -327,15 +328,15 @@ ppc64ModelParse(xmlXPathContextPtr ctxt,
+     int ret = -1;
+ 
+     if (VIR_ALLOC(model) < 0)
+-        goto error;
++        goto cleanup;
+ 
+     if (VIR_STRDUP(model->name, name) < 0)
+-        goto error;
++        goto cleanup;
+ 
+     if (ppc64ModelFind(map, model->name)) {
+         virReportError(VIR_ERR_INTERNAL_ERROR,
+                        _("CPU model %s already defined"), model->name);
+-        goto error;
++        goto cleanup;
+     }
+ 
+     if (virXPathBoolean("boolean(./vendor)", ctxt)) {
+@@ -344,14 +345,14 @@ ppc64ModelParse(xmlXPathContextPtr ctxt,
+             virReportError(VIR_ERR_INTERNAL_ERROR,
+                            _("Invalid vendor element in CPU model %s"),
+                            model->name);
+-            goto error;
++            goto cleanup;
+         }
+ 
+         if (!(model->vendor = ppc64VendorFind(map, vendor))) {
+             virReportError(VIR_ERR_INTERNAL_ERROR,
+                            _("Unknown vendor %s referenced by CPU model %s"),
+                            vendor, model->name);
+-            goto error;
++            goto cleanup;
+         }
+     }
+ 
+@@ -359,11 +360,11 @@ ppc64ModelParse(xmlXPathContextPtr ctxt,
+         virReportError(VIR_ERR_INTERNAL_ERROR,
+                        _("Missing PVR information for CPU model %s"),
+                        model->name);
+-        goto error;
++        goto cleanup;
+     }
+ 
+     if (VIR_ALLOC_N(model->data.pvr, n) < 0)
+-        goto error;
++        goto cleanup;
+ 
+     model->data.len = n;
+ 
+@@ -374,7 +375,7 @@ ppc64ModelParse(xmlXPathContextPtr ctxt,
+             virReportError(VIR_ERR_INTERNAL_ERROR,
+                            _("Missing or invalid PVR value in CPU model %s"),
+                            model->name);
+-            goto error;
++            goto cleanup;
+         }
+         model->data.pvr[i].value = pvr;
+ 
+@@ -382,24 +383,21 @@ ppc64ModelParse(xmlXPathContextPtr ctxt,
+             virReportError(VIR_ERR_INTERNAL_ERROR,
+                            _("Missing or invalid PVR mask in CPU model %s"),
+                            model->name);
+-            goto error;
++            goto cleanup;
+         }
+         model->data.pvr[i].mask = pvr;
+     }
+ 
+     if (VIR_APPEND_ELEMENT(map->models, map->nmodels, model) < 0)
+-        goto error;
++        goto cleanup;
+ 
+     ret = 0;
+ 
+  cleanup:
++    ppc64ModelFree(model);
+     VIR_FREE(vendor);
+     VIR_FREE(nodes);
+     return ret;
+-
+- error:
+-    ppc64ModelFree(model);
+-    goto cleanup;
+ }
+ 
+ 
+diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
+index 11dbd1e757..ce48ca6867 100644
+--- a/src/cpu/cpu_x86.c
++++ b/src/cpu/cpu_x86.c
+@@ -731,15 +731,15 @@ x86VendorParse(xmlXPathContextPtr ctxt,
+     int ret = -1;
+ 
+     if (VIR_ALLOC(vendor) < 0)
+-        goto error;
++        goto cleanup;
+ 
+     if (VIR_STRDUP(vendor->name, name) < 0)
+-        goto error;
++        goto cleanup;
+ 
+     if (x86VendorFind(map, vendor->name)) {
+         virReportError(VIR_ERR_INTERNAL_ERROR,
+                        _("CPU vendor %s already defined"), vendor->name);
+-        goto error;
++        goto cleanup;
+     }
+ 
+     string = virXPathString("string(@string)", ctxt);
+@@ -747,24 +747,21 @@ x86VendorParse(xmlXPathContextPtr ctxt,
+         virReportError(VIR_ERR_INTERNAL_ERROR,
+                        _("Missing vendor string for CPU vendor %s"),
+                        vendor->name);
+-        goto error;
++        goto cleanup;
+     }
+ 
+     if (virCPUx86VendorToCPUID(string, &vendor->cpuid) < 0)
+-        goto error;
++        goto cleanup;
+ 
+     if (VIR_APPEND_ELEMENT(map->vendors, map->nvendors, vendor) < 0)
+-        goto error;
++        goto cleanup;
+ 
+     ret = 0;
+ 
+  cleanup:
++    x86VendorFree(vendor);
+     VIR_FREE(string);
+     return ret;
+-
+- error:
+-    x86VendorFree(vendor);
+-    goto cleanup;
+ }
+ 
+ 
+@@ -904,17 +901,17 @@ x86FeatureParse(xmlXPathContextPtr ctxt,
+     int ret = -1;
+ 
+     if (!(feature = x86FeatureNew()))
+-        goto error;
++        goto cleanup;
+ 
+     feature->migratable = true;
+ 
+     if (VIR_STRDUP(feature->name, name) < 0)
+-        goto error;
++        goto cleanup;
+ 
+     if (x86FeatureFind(map, feature->name)) {
+         virReportError(VIR_ERR_INTERNAL_ERROR,
+                        _("CPU feature %s already defined"), feature->name);
+-        goto error;
++        goto cleanup;
+     }
+ 
+     str = virXPathString("string(@migratable)", ctxt);
+@@ -923,7 +920,7 @@ x86FeatureParse(xmlXPathContextPtr ctxt,
+ 
+     n = virXPathNodeSet("./cpuid", ctxt, &nodes);
+     if (n < 0)
+-        goto error;
++        goto cleanup;
+ 
+     for (i = 0; i < n; i++) {
+         ctxt->node = nodes[i];
+@@ -931,31 +928,28 @@ x86FeatureParse(xmlXPathContextPtr ctxt,
+             virReportError(VIR_ERR_INTERNAL_ERROR,
+                            _("Invalid cpuid[%zu] in %s feature"),
+                            i, feature->name);
+-            goto error;
++            goto cleanup;
+         }
+         if (virCPUx86DataAddCPUIDInt(&feature->data, &cpuid))
+-            goto error;
++            goto cleanup;
+     }
+ 
+     if (!feature->migratable &&
+         VIR_APPEND_ELEMENT_COPY(map->migrate_blockers,
+                                 map->nblockers,
+                                 feature) < 0)
+-        goto error;
++        goto cleanup;
+ 
+     if (VIR_APPEND_ELEMENT(map->features, map->nfeatures, feature) < 0)
+-        goto error;
++        goto cleanup;
+ 
+     ret = 0;
+ 
+  cleanup:
++    x86FeatureFree(feature);
+     VIR_FREE(nodes);
+     VIR_FREE(str);
+     return ret;
+-
+- error:
+-    x86FeatureFree(feature);
+-    goto cleanup;
+ }
+ 
+ 
+@@ -1168,10 +1162,10 @@ x86ModelParse(xmlXPathContextPtr ctxt,
+     int ret = -1;
+ 
+     if (!(model = x86ModelNew()))
+-        goto error;
++        goto cleanup;
+ 
+     if (VIR_STRDUP(model->name, name) < 0)
+-        goto error;
++        goto cleanup;
+ 
+     if (virXPathNode("./model", ctxt)) {
+         virCPUx86ModelPtr ancestor;
+@@ -1182,7 +1176,7 @@ x86ModelParse(xmlXPathContextPtr ctxt,
+             virReportError(VIR_ERR_INTERNAL_ERROR,
+                            _("Missing ancestor's name in CPU model %s"),
+                            model->name);
+-            goto error;
++            goto cleanup;
+         }
+ 
+         if (!(ancestor = x86ModelFind(map, anname))) {
+@@ -1190,7 +1184,7 @@ x86ModelParse(xmlXPathContextPtr ctxt,
+                            _("Ancestor model %s not found for CPU model %s"),
+                            anname, model->name);
+             VIR_FREE(anname);
+-            goto error;
++            goto cleanup;
+         }
+ 
+         VIR_FREE(anname);
+@@ -1198,7 +1192,7 @@ x86ModelParse(xmlXPathContextPtr ctxt,
+         model->vendor = ancestor->vendor;
+         model->signature = ancestor->signature;
+         if (x86DataCopy(&model->data, &ancestor->data) < 0)
+-            goto error;
++            goto cleanup;
+     }
+ 
+     if (virXPathBoolean("boolean(./signature)", ctxt)) {
+@@ -1211,7 +1205,7 @@ x86ModelParse(xmlXPathContextPtr ctxt,
+             virReportError(VIR_ERR_INTERNAL_ERROR,
+                            _("Invalid CPU signature family in model %s"),
+                            model->name);
+-            goto error;
++            goto cleanup;
+         }
+ 
+         rc = virXPathUInt("string(./signature/@model)", ctxt, &sigModel);
+@@ -1219,7 +1213,7 @@ x86ModelParse(xmlXPathContextPtr ctxt,
+             virReportError(VIR_ERR_INTERNAL_ERROR,
+                            _("Invalid CPU signature model in model %s"),
+                            model->name);
+-            goto error;
++            goto cleanup;
+         }
+ 
+         model->signature = x86MakeSignature(sigFamily, sigModel, 0);
+@@ -1231,20 +1225,20 @@ x86ModelParse(xmlXPathContextPtr ctxt,
+             virReportError(VIR_ERR_INTERNAL_ERROR,
+                            _("Invalid vendor element in CPU model %s"),
+                            model->name);
+-            goto error;
++            goto cleanup;
+         }
+ 
+         if (!(model->vendor = x86VendorFind(map, vendor))) {
+             virReportError(VIR_ERR_INTERNAL_ERROR,
+                            _("Unknown vendor %s referenced by CPU model %s"),
+                            vendor, model->name);
+-            goto error;
++            goto cleanup;
+         }
+     }
+ 
+     n = virXPathNodeSet("./feature", ctxt, &nodes);
+     if (n < 0)
+-        goto error;
++        goto cleanup;
+ 
+     for (i = 0; i < n; i++) {
+         virCPUx86FeaturePtr feature;
+@@ -1253,7 +1247,7 @@ x86ModelParse(xmlXPathContextPtr ctxt,
+         if (!(ftname = virXMLPropString(nodes[i], "name"))) {
+             virReportError(VIR_ERR_INTERNAL_ERROR,
+                            _("Missing feature name for CPU model %s"), model->name);
+-            goto error;
++            goto cleanup;
+         }
+ 
+         if (!(feature = x86FeatureFind(map, ftname))) {
+@@ -1261,27 +1255,24 @@ x86ModelParse(xmlXPathContextPtr ctxt,
+                            _("Feature %s required by CPU model %s not found"),
+                            ftname, model->name);
+             VIR_FREE(ftname);
+-            goto error;
++            goto cleanup;
+         }
+         VIR_FREE(ftname);
+ 
+         if (x86DataAdd(&model->data, &feature->data))
+-            goto error;
++            goto cleanup;
+     }
+ 
+     if (VIR_APPEND_ELEMENT(map->models, map->nmodels, model) < 0)
+-        goto error;
++        goto cleanup;
+ 
+     ret = 0;
+ 
+  cleanup:
++    x86ModelFree(model);
+     VIR_FREE(vendor);
+     VIR_FREE(nodes);
+     return ret;
+-
+- error:
+-    x86ModelFree(model);
+-    goto cleanup;
+ }
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-cpu_conf-Introduce-virCPUDefFilterFeatures.patch b/SOURCES/libvirt-cpu_conf-Introduce-virCPUDefFilterFeatures.patch
new file mode 100644
index 0000000..debce13
--- /dev/null
+++ b/SOURCES/libvirt-cpu_conf-Introduce-virCPUDefFilterFeatures.patch
@@ -0,0 +1,91 @@
+From 296ff8fbba31a8052bdf24e409b0bb9e3c041c8f Mon Sep 17 00:00:00 2001
+Message-Id: <296ff8fbba31a8052bdf24e409b0bb9e3c041c8f@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:25:46 +0200
+Subject: [PATCH] cpu_conf: Introduce virCPUDefFilterFeatures
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This new internal API can be used for in place filtering of CPU features
+in virCPUDef.
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit c145b660b8225f73db16660461077ef931730939)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1697627
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <b3bd18c6e9cdf5256a7369bd06e5f773e160d9f3.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/conf/cpu_conf.c      | 22 ++++++++++++++++++++++
+ src/conf/cpu_conf.h      |  5 +++++
+ src/libvirt_private.syms |  1 +
+ 3 files changed, 28 insertions(+)
+
+diff --git a/src/conf/cpu_conf.c b/src/conf/cpu_conf.c
+index 43a3ab5dcd..51e2a83eae 100644
+--- a/src/conf/cpu_conf.c
++++ b/src/conf/cpu_conf.c
+@@ -850,6 +850,28 @@ virCPUDefFindFeature(virCPUDefPtr def,
+ }
+ 
+ 
++int
++virCPUDefFilterFeatures(virCPUDefPtr cpu,
++                        virCPUDefFeatureFilter filter,
++                        void *opaque)
++{
++    size_t i = 0;
++
++    while (i < cpu->nfeatures) {
++        if (filter(cpu->features[i].name, opaque)) {
++            i++;
++            continue;
++        }
++
++        VIR_FREE(cpu->features[i].name);
++        if (VIR_DELETE_ELEMENT_INPLACE(cpu->features, i, cpu->nfeatures) < 0)
++            return -1;
++    }
++
++    return 0;
++}
++
++
+ bool
+ virCPUDefIsEqual(virCPUDefPtr src,
+                  virCPUDefPtr dst,
+diff --git a/src/conf/cpu_conf.h b/src/conf/cpu_conf.h
+index 9f2e7ee264..ad25932b9b 100644
+--- a/src/conf/cpu_conf.h
++++ b/src/conf/cpu_conf.h
+@@ -220,6 +220,11 @@ virCPUFeatureDefPtr
+ virCPUDefFindFeature(virCPUDefPtr def,
+                      const char *name);
+ 
++int
++virCPUDefFilterFeatures(virCPUDefPtr cpu,
++                        virCPUDefFeatureFilter filter,
++                        void *opaque);
++
+ virCPUDefPtr *
+ virCPUDefListParse(const char **xmlCPUs,
+                    unsigned int ncpus,
+diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
+index 9ebc5384fb..57508de0c1 100644
+--- a/src/libvirt_private.syms
++++ b/src/libvirt_private.syms
+@@ -76,6 +76,7 @@ virCPUDefCopy;
+ virCPUDefCopyModel;
+ virCPUDefCopyModelFilter;
+ virCPUDefCopyWithoutModel;
++virCPUDefFilterFeatures;
+ virCPUDefFindFeature;
+ virCPUDefFormat;
+ virCPUDefFormatBuf;
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-cpu_map-Add-Cascadelake-Server-CPU-model.patch b/SOURCES/libvirt-cpu_map-Add-Cascadelake-Server-CPU-model.patch
new file mode 100644
index 0000000..7febd6c
--- /dev/null
+++ b/SOURCES/libvirt-cpu_map-Add-Cascadelake-Server-CPU-model.patch
@@ -0,0 +1,211 @@
+From 6d31e77ae83bb2b29d3bff5bd08742ee4c611e25 Mon Sep 17 00:00:00 2001
+Message-Id: <6d31e77ae83bb2b29d3bff5bd08742ee4c611e25@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:25:21 +0200
+Subject: [PATCH] cpu_map: Add Cascadelake-Server CPU model
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Introduced in QEMU 3.1.0 by commit
+c7a88b52f62b30c04158eeb07f73e3f72221b6a8
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit 2878278c74cc450a7e28a3830ed0ceff3126f12f)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1693433
+
+Conflicts:
+	src/cpu_map/index.xml
+        src/cpu_map/x86_Cascadelake-Server.xml
+            - cpu_map split not backported
+
+	tests/domaincapsschemadata/qemu_3.1.0.x86_64.xml
+	tests/domaincapsschemadata/qemu_4.0.0.x86_64.xml
+            - test data missing
+
+	tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-guest.xml
+	tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-host.xml
+            - md-clear feature did not exist at the time of the original
+              patch, but downstream already has it
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <d99c9ab500eb9a482450ba87dec52f5f3cf03429.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/cpu/cpu_map.xml                           | 81 +++++++++++++++++++
+ .../x86_64-cpuid-Xeon-Platinum-8268-guest.xml |  5 +-
+ .../x86_64-cpuid-Xeon-Platinum-8268-host.xml  |  5 +-
+ .../x86_64-cpuid-Xeon-Platinum-8268-json.xml  |  5 +-
+ 4 files changed, 84 insertions(+), 12 deletions(-)
+
+diff --git a/src/cpu/cpu_map.xml b/src/cpu/cpu_map.xml
+index b2eb07b832..9b289556e8 100644
+--- a/src/cpu/cpu_map.xml
++++ b/src/cpu/cpu_map.xml
+@@ -2193,6 +2193,87 @@
+       <feature name='xsaveopt'/>
+     </model>
+ 
++    <model name='Cascadelake-Server'>
++      <signature family='6' model='85'/> <!-- 050654 -->
++      <vendor name='Intel'/>
++      <feature name='3dnowprefetch'/>
++      <feature name='abm'/>
++      <feature name='adx'/>
++      <feature name='aes'/>
++      <feature name='apic'/>
++      <feature name='arat'/>
++      <feature name='avx'/>
++      <feature name='avx2'/>
++      <feature name='avx512bw'/>
++      <feature name='avx512cd'/>
++      <feature name='avx512dq'/>
++      <feature name='avx512f'/>
++      <feature name='avx512vl'/>
++      <feature name='avx512vnni'/>
++      <feature name='bmi1'/>
++      <feature name='bmi2'/>
++      <feature name='clflush'/>
++      <feature name='clflushopt'/>
++      <feature name='clwb'/>
++      <feature name='cmov'/>
++      <feature name='cx16'/>
++      <feature name='cx8'/>
++      <feature name='de'/>
++      <feature name='erms'/>
++      <feature name='f16c'/>
++      <feature name='fma'/>
++      <feature name='fpu'/>
++      <feature name='fsgsbase'/>
++      <feature name='fxsr'/>
++      <feature name='hle'/>
++      <feature name='invpcid'/>
++      <feature name='lahf_lm'/>
++      <feature name='lm'/>
++      <feature name='mca'/>
++      <feature name='mce'/>
++      <feature name='mmx'/>
++      <feature name='movbe'/>
++      <feature name='mpx'/>
++      <feature name='msr'/>
++      <feature name='mtrr'/>
++      <feature name='nx'/>
++      <!-- 'ospke' is a dynamic feature and cannot be enabled manually
++           see QEMU's commit 9ccb9784b57 for more details -->
++      <feature name='pae'/>
++      <feature name='pat'/>
++      <feature name='pcid'/>
++      <feature name='pclmuldq'/>
++      <feature name='pdpe1gb'/>
++      <feature name='pge'/>
++      <feature name='pni'/>
++      <feature name='popcnt'/>
++      <feature name='pse'/>
++      <feature name='pse36'/>
++      <feature name='rdrand'/>
++      <feature name='rdseed'/>
++      <feature name='rdtscp'/>
++      <feature name='rtm'/>
++      <feature name='sep'/>
++      <feature name='smap'/>
++      <feature name='smep'/>
++      <feature name='spec-ctrl'/>
++      <feature name='ssbd'/>
++      <feature name='sse'/>
++      <feature name='sse2'/>
++      <feature name='sse4.1'/>
++      <feature name='sse4.2'/>
++      <feature name='ssse3'/>
++      <feature name='syscall'/>
++      <feature name='tsc'/>
++      <feature name='tsc-deadline'/>
++      <feature name='vme'/>
++      <feature name='x2apic'/>
++      <feature name='xgetbv1'/>
++      <feature name='xsave'/>
++      <feature name='xsavec'/>
++      <feature name='xsaveopt'/>
++    </model>
++
+     <!-- AMD CPUs -->
+     <model name='athlon'>
+       <vendor name='AMD'/>
+diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-guest.xml b/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-guest.xml
+index 2836481454..c7e8a1fccf 100644
+--- a/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-guest.xml
++++ b/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-guest.xml
+@@ -1,5 +1,5 @@
+ <cpu mode='custom' match='exact'>
+-  <model fallback='forbid'>Skylake-Server-IBRS</model>
++  <model fallback='forbid'>Cascadelake-Server</model>
+   <vendor>Intel</vendor>
+   <feature policy='require' name='ds'/>
+   <feature policy='require' name='acpi'/>
+@@ -20,15 +20,12 @@
+   <feature policy='require' name='osxsave'/>
+   <feature policy='require' name='tsc_adjust'/>
+   <feature policy='require' name='cmt'/>
+-  <feature policy='require' name='clflushopt'/>
+   <feature policy='require' name='intel-pt'/>
+   <feature policy='require' name='pku'/>
+   <feature policy='require' name='ospke'/>
+-  <feature policy='require' name='avx512vnni'/>
+   <feature policy='require' name='md-clear'/>
+   <feature policy='require' name='stibp'/>
+   <feature policy='require' name='arch-capabilities'/>
+-  <feature policy='require' name='ssbd'/>
+   <feature policy='require' name='xsaves'/>
+   <feature policy='require' name='mbm_total'/>
+   <feature policy='require' name='mbm_local'/>
+diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-host.xml b/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-host.xml
+index 032d8ffeca..d7482751b4 100644
+--- a/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-host.xml
++++ b/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-host.xml
+@@ -1,6 +1,6 @@
+ <cpu>
+   <arch>x86_64</arch>
+-  <model>Skylake-Server-IBRS</model>
++  <model>Cascadelake-Server</model>
+   <vendor>Intel</vendor>
+   <feature name='ds'/>
+   <feature name='acpi'/>
+@@ -21,15 +21,12 @@
+   <feature name='osxsave'/>
+   <feature name='tsc_adjust'/>
+   <feature name='cmt'/>
+-  <feature name='clflushopt'/>
+   <feature name='intel-pt'/>
+   <feature name='pku'/>
+   <feature name='ospke'/>
+-  <feature name='avx512vnni'/>
+   <feature name='md-clear'/>
+   <feature name='stibp'/>
+   <feature name='arch-capabilities'/>
+-  <feature name='ssbd'/>
+   <feature name='xsaves'/>
+   <feature name='mbm_total'/>
+   <feature name='mbm_local'/>
+diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-json.xml b/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-json.xml
+index 12431de213..b7d12dced7 100644
+--- a/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-json.xml
++++ b/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-json.xml
+@@ -1,13 +1,10 @@
+ <cpu mode='custom' match='exact'>
+-  <model fallback='forbid'>Skylake-Server-IBRS</model>
++  <model fallback='forbid'>Cascadelake-Server</model>
+   <vendor>Intel</vendor>
+   <feature policy='require' name='ss'/>
+   <feature policy='require' name='hypervisor'/>
+   <feature policy='require' name='tsc_adjust'/>
+-  <feature policy='require' name='clflushopt'/>
+   <feature policy='require' name='umip'/>
+   <feature policy='require' name='pku'/>
+-  <feature policy='require' name='avx512vnni'/>
+-  <feature policy='require' name='ssbd'/>
+   <feature policy='require' name='xsaves'/>
+ </cpu>
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-cpu_map-Add-hex-representation-of-signatures.patch b/SOURCES/libvirt-cpu_map-Add-hex-representation-of-signatures.patch
new file mode 100644
index 0000000..3319ca2
--- /dev/null
+++ b/SOURCES/libvirt-cpu_map-Add-hex-representation-of-signatures.patch
@@ -0,0 +1,318 @@
+From 83a1114820c95f9cd98789b14044a229dcc090a7 Mon Sep 17 00:00:00 2001
+Message-Id: <83a1114820c95f9cd98789b14044a229dcc090a7@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:25:07 +0200
+Subject: [PATCH] cpu_map: Add hex representation of signatures
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The family/model numbers are nice for humans or for comparing with
+/proc/cpuinfo, but sometimes there's a need to see the CPUID
+representation of the signature. Let's add it into a comment for each
+signature in out cpu_map XMLs as the conversion is not exactly
+straightforward.
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit 61be05a00fd383f11070761fac5ae28272b784dd)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1686895
+
+Conflicts:
+        src/cpu/cpu_map.xml
+            - the cpu_map split was not backported
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <e8e2e0bdf183bec170df5252cf927ff5fbe0ef47.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/cpu/cpu_map.xml | 62 ++++++++++++++++++++++-----------------------
+ 1 file changed, 31 insertions(+), 31 deletions(-)
+
+diff --git a/src/cpu/cpu_map.xml b/src/cpu/cpu_map.xml
+index a9f284fbbe..a5a5290a09 100644
+--- a/src/cpu/cpu_map.xml
++++ b/src/cpu/cpu_map.xml
+@@ -828,7 +828,7 @@
+ 
+     <!-- Intel CPU models -->
+     <model name='Conroe'>
+-      <signature family='6' model='15'/>
++      <signature family='6' model='15'/> <!-- 0006f0 -->
+       <vendor name='Intel'/>
+       <feature name='apic'/>
+       <feature name='clflush'/>
+@@ -860,7 +860,7 @@
+     </model>
+ 
+     <model name='Penryn'>
+-      <signature family='6' model='23'/>
++      <signature family='6' model='23'/> <!-- 010670 -->
+       <vendor name='Intel'/>
+       <feature name='apic'/>
+       <feature name='clflush'/>
+@@ -894,7 +894,7 @@
+     </model>
+ 
+     <model name='Nehalem'>
+-      <signature family='6' model='26'/>
++      <signature family='6' model='26'/> <!-- 0106a0 -->
+       <vendor name='Intel'/>
+       <feature name='apic'/>
+       <feature name='clflush'/>
+@@ -930,7 +930,7 @@
+     </model>
+ 
+     <model name='Nehalem-IBRS'>
+-      <signature family='6' model='26'/>
++      <signature family='6' model='26'/> <!-- 0106a0 -->
+       <vendor name='Intel'/>
+       <feature name='apic'/>
+       <feature name='clflush'/>
+@@ -967,7 +967,7 @@
+     </model>
+ 
+     <model name='Westmere'>
+-      <signature family='6' model='44'/>
++      <signature family='6' model='44'/> <!-- 0206c0 -->
+       <vendor name='Intel'/>
+       <feature name='aes'/>
+       <feature name='apic'/>
+@@ -1004,7 +1004,7 @@
+     </model>
+ 
+     <model name='Westmere-IBRS'>
+-      <signature family='6' model='44'/>
++      <signature family='6' model='44'/> <!-- 0206c0 -->
+       <vendor name='Intel'/>
+       <feature name='aes'/>
+       <feature name='apic'/>
+@@ -1042,7 +1042,7 @@
+     </model>
+ 
+     <model name='SandyBridge'>
+-      <signature family='6' model='42'/>
++      <signature family='6' model='42'/> <!-- 0206a0 -->
+       <vendor name='Intel'/>
+       <feature name='aes'/>
+       <feature name='apic'/>
+@@ -1085,7 +1085,7 @@
+     </model>
+ 
+     <model name='SandyBridge-IBRS'>
+-      <signature family='6' model='42'/>
++      <signature family='6' model='42'/> <!-- 0206a0 -->
+       <vendor name='Intel'/>
+       <feature name='aes'/>
+       <feature name='apic'/>
+@@ -1129,7 +1129,7 @@
+     </model>
+ 
+     <model name='IvyBridge'>
+-      <signature family='6' model='58'/>
++      <signature family='6' model='58'/> <!-- 0306a0 -->
+       <vendor name='Intel'/>
+       <feature name='aes'/>
+       <feature name='apic'/>
+@@ -1178,7 +1178,7 @@
+     </model>
+ 
+     <model name='IvyBridge-IBRS'>
+-      <signature family='6' model='58'/>
++      <signature family='6' model='58'/> <!-- 0306a0 -->
+       <vendor name='Intel'/>
+       <feature name='aes'/>
+       <feature name='apic'/>
+@@ -1228,7 +1228,7 @@
+     </model>
+ 
+     <model name='Haswell-noTSX'>
+-      <signature family='6' model='60'/>
++      <signature family='6' model='60'/> <!-- 0306c0 -->
+       <vendor name='Intel'/>
+       <feature name='aes'/>
+       <feature name='apic'/>
+@@ -1281,7 +1281,7 @@
+     </model>
+ 
+     <model name='Haswell-noTSX-IBRS'>
+-      <signature family='6' model='60'/>
++      <signature family='6' model='60'/> <!-- 0306c0 -->
+       <vendor name='Intel'/>
+       <feature name='aes'/>
+       <feature name='apic'/>
+@@ -1335,7 +1335,7 @@
+     </model>
+ 
+     <model name='Haswell'>
+-      <signature family='6' model='60'/>
++      <signature family='6' model='60'/> <!-- 0306c0 -->
+       <vendor name='Intel'/>
+       <feature name='aes'/>
+       <feature name='apic'/>
+@@ -1390,7 +1390,7 @@
+     </model>
+ 
+     <model name='Haswell-IBRS'>
+-      <signature family='6' model='60'/>
++      <signature family='6' model='60'/> <!-- 0306c0 -->
+       <vendor name='Intel'/>
+       <feature name='aes'/>
+       <feature name='apic'/>
+@@ -1446,7 +1446,7 @@
+     </model>
+ 
+     <model name='Broadwell-noTSX'>
+-      <signature family='6' model='61'/>
++      <signature family='6' model='61'/> <!-- 0306d0 -->
+       <vendor name='Intel'/>
+       <feature name='3dnowprefetch'/>
+       <feature name='adx'/>
+@@ -1503,7 +1503,7 @@
+     </model>
+ 
+     <model name='Broadwell-noTSX-IBRS'>
+-      <signature family='6' model='61'/>
++      <signature family='6' model='61'/> <!-- 0306d0 -->
+       <vendor name='Intel'/>
+       <feature name='3dnowprefetch'/>
+       <feature name='adx'/>
+@@ -1561,7 +1561,7 @@
+     </model>
+ 
+     <model name='Broadwell'>
+-      <signature family='6' model='61'/>
++      <signature family='6' model='61'/> <!-- 0306d0 -->
+       <vendor name='Intel'/>
+       <feature name='3dnowprefetch'/>
+       <feature name='adx'/>
+@@ -1620,7 +1620,7 @@
+     </model>
+ 
+     <model name='Broadwell-IBRS'>
+-      <signature family='6' model='61'/>
++      <signature family='6' model='61'/> <!-- 0306d0 -->
+       <vendor name='Intel'/>
+       <feature name='3dnowprefetch'/>
+       <feature name='adx'/>
+@@ -1680,7 +1680,7 @@
+     </model>
+ 
+     <model name='Skylake-Client'>
+-      <signature family='6' model='94'/>
++      <signature family='6' model='94'/> <!-- 0506e0 -->
+       <vendor name='Intel'/>
+       <feature name='3dnowprefetch'/>
+       <feature name='abm'/>
+@@ -1748,7 +1748,7 @@
+     </model>
+ 
+     <model name='Skylake-Client-IBRS'>
+-      <signature family='6' model='94'/>
++      <signature family='6' model='94'/> <!-- 0506e0 -->
+       <vendor name='Intel'/>
+       <feature name='3dnowprefetch'/>
+       <feature name='abm'/>
+@@ -1817,7 +1817,7 @@
+     </model>
+ 
+     <model name='Skylake-Server'>
+-      <signature family='6' model='85'/>
++      <signature family='6' model='85'/> <!-- 050654 -->
+       <vendor name='Intel'/>
+       <feature name='3dnowprefetch'/>
+       <feature name='abm'/>
+@@ -1892,7 +1892,7 @@
+     </model>
+ 
+     <model name='Skylake-Server-IBRS'>
+-      <signature family='6' model='85'/>
++      <signature family='6' model='85'/> <!-- 050654 -->
+       <vendor name='Intel'/>
+       <feature name='3dnowprefetch'/>
+       <feature name='abm'/>
+@@ -1968,7 +1968,7 @@
+     </model>
+ 
+     <model name='Icelake-Client'>
+-      <signature family='6' model='126'/>
++      <signature family='6' model='126'/> <!-- 0706e0 -->
+       <vendor name='Intel'/>
+       <feature name='3dnowprefetch'/>
+       <feature name='abm'/>
+@@ -2052,7 +2052,7 @@
+     </model>
+ 
+     <model name='Icelake-Server'>
+-      <signature family='6' model='134'/>
++      <signature family='6' model='134'/> <!-- 080660 -->
+       <vendor name='Intel'/>
+       <feature name='3dnowprefetch'/>
+       <feature name='abm'/>
+@@ -2209,7 +2209,7 @@
+     </model>
+ 
+     <model name='Opteron_G1'>
+-      <signature family='15' model='6'/>
++      <signature family='15' model='6'/> <!-- 100e60 -->
+       <vendor name='AMD'/>
+       <feature name='apic'/>
+       <feature name='clflush'/>
+@@ -2239,7 +2239,7 @@
+     </model>
+ 
+     <model name='Opteron_G2'>
+-      <signature family='15' model='6'/>
++      <signature family='15' model='6'/> <!-- 100e60 -->
+       <vendor name='AMD'/>
+       <feature name='apic'/>
+       <feature name='clflush'/>
+@@ -2273,7 +2273,7 @@
+     </model>
+ 
+     <model name='Opteron_G3'>
+-      <signature family='15' model='6'/>
++      <signature family='15' model='6'/> <!-- 100e60 -->
+       <vendor name='AMD'/>
+       <feature name='abm'/>
+       <feature name='apic'/>
+@@ -2312,7 +2312,7 @@
+     </model>
+ 
+     <model name='Opteron_G4'>
+-      <signature family='21' model='1'/>
++      <signature family='21' model='1'/> <!-- 600f10 -->
+       <vendor name='AMD'/>
+       <feature name='3dnowprefetch'/>
+       <feature name='abm'/>
+@@ -2361,7 +2361,7 @@
+     </model>
+ 
+     <model name='Opteron_G5'>
+-      <signature family='21' model='2'/>
++      <signature family='21' model='2'/> <!-- 600f20 -->
+       <vendor name='AMD'/>
+       <feature name='3dnowprefetch'/>
+       <feature name='abm'/>
+@@ -2413,7 +2413,7 @@
+     </model>
+ 
+     <model name='EPYC'>
+-      <signature family='23' model='1'/>
++      <signature family='23' model='1'/> <!-- 800f10 -->
+       <vendor name='AMD'/>
+       <feature name='3dnowprefetch'/>
+       <feature name='abm'/>
+@@ -2484,7 +2484,7 @@
+     </model>
+ 
+     <model name='EPYC-IBPB'>
+-      <signature family='23' model='1'/>
++      <signature family='23' model='1'/> <!-- 800f10 -->
+       <vendor name='AMD'/>
+       <feature name='3dnowprefetch'/>
+       <feature name='abm'/>
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-cpu_map-Add-more-signatures-for-Broadwell-CPU-models.patch b/SOURCES/libvirt-cpu_map-Add-more-signatures-for-Broadwell-CPU-models.patch
new file mode 100644
index 0000000..5a1e320
--- /dev/null
+++ b/SOURCES/libvirt-cpu_map-Add-more-signatures-for-Broadwell-CPU-models.patch
@@ -0,0 +1,254 @@
+From 77ad41e460c2e91f2c2e187c80581069654b741d Mon Sep 17 00:00:00 2001
+Message-Id: <77ad41e460c2e91f2c2e187c80581069654b741d@dist-git>
+From: Jiri Denemark <Jiri.Denemark@gmail.com>
+Date: Fri, 21 Jun 2019 09:25:16 +0200
+Subject: [PATCH] cpu_map: Add more signatures for Broadwell CPU models
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This fixes several CPUs which were incorrectly detected as
+Skylake-Client.
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit 4ff74a806ad42820eef3877c8ec146770914d8df)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1686895
+
+Conflicts:
+	src/cpu_map/x86_Broadwell-IBRS.xml
+	src/cpu_map/x86_Broadwell-noTSX-IBRS.xml
+	src/cpu_map/x86_Broadwell-noTSX.xml
+	src/cpu_map/x86_Broadwell.xml
+            - cpu_map split not backported
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <543534b544d2d09470c218aeb6c7d945facaf2c8.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/cpu/cpu_map.xml                                  | 12 ++++++++++++
+ .../x86_64-cpuid-Xeon-E5-2623-v4-guest.xml           | 11 +++++++----
+ .../x86_64-cpuid-Xeon-E5-2623-v4-json.xml            | 11 +++++++----
+ .../x86_64-cpuid-Xeon-E5-2630-v4-guest.xml           | 11 +++++++----
+ .../x86_64-cpuid-Xeon-E5-2630-v4-json.xml            | 11 +++++++----
+ .../x86_64-cpuid-Xeon-E5-2650-v4-guest.xml           | 11 +++++++----
+ .../x86_64-cpuid-Xeon-E5-2650-v4-json.xml            | 11 +++++++----
+ 7 files changed, 54 insertions(+), 24 deletions(-)
+
+diff --git a/src/cpu/cpu_map.xml b/src/cpu/cpu_map.xml
+index ed6006643b..04369d1eda 100644
+--- a/src/cpu/cpu_map.xml
++++ b/src/cpu/cpu_map.xml
+@@ -1473,6 +1473,9 @@
+ 
+     <model name='Broadwell-noTSX'>
+       <signature family='6' model='61'/> <!-- 0306d0 -->
++      <signature family='6' model='71'/> <!-- 040670 -->
++      <signature family='6' model='79'/> <!-- 0406f0 -->
++      <signature family='6' model='86'/> <!-- 050660 -->
+       <vendor name='Intel'/>
+       <feature name='3dnowprefetch'/>
+       <feature name='adx'/>
+@@ -1530,6 +1533,9 @@
+ 
+     <model name='Broadwell-noTSX-IBRS'>
+       <signature family='6' model='61'/> <!-- 0306d0 -->
++      <signature family='6' model='71'/> <!-- 040670 -->
++      <signature family='6' model='79'/> <!-- 0406f0 -->
++      <signature family='6' model='86'/> <!-- 050660 -->
+       <vendor name='Intel'/>
+       <feature name='3dnowprefetch'/>
+       <feature name='adx'/>
+@@ -1588,6 +1594,9 @@
+ 
+     <model name='Broadwell'>
+       <signature family='6' model='61'/> <!-- 0306d0 -->
++      <signature family='6' model='71'/> <!-- 040670 -->
++      <signature family='6' model='79'/> <!-- 0406f0 -->
++      <signature family='6' model='86'/> <!-- 050660 -->
+       <vendor name='Intel'/>
+       <feature name='3dnowprefetch'/>
+       <feature name='adx'/>
+@@ -1647,6 +1656,9 @@
+ 
+     <model name='Broadwell-IBRS'>
+       <signature family='6' model='61'/> <!-- 0306d0 -->
++      <signature family='6' model='71'/> <!-- 040670 -->
++      <signature family='6' model='79'/> <!-- 0406f0 -->
++      <signature family='6' model='86'/> <!-- 050660 -->
+       <vendor name='Intel'/>
+       <feature name='3dnowprefetch'/>
+       <feature name='adx'/>
+diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E5-2623-v4-guest.xml b/tests/cputestdata/x86_64-cpuid-Xeon-E5-2623-v4-guest.xml
+index 7718d7ca59..a5c6d9b471 100644
+--- a/tests/cputestdata/x86_64-cpuid-Xeon-E5-2623-v4-guest.xml
++++ b/tests/cputestdata/x86_64-cpuid-Xeon-E5-2623-v4-guest.xml
+@@ -1,6 +1,7 @@
+ <cpu mode='custom' match='exact'>
+-  <model fallback='forbid'>Skylake-Client-IBRS</model>
++  <model fallback='forbid'>Broadwell-IBRS</model>
+   <vendor>Intel</vendor>
++  <feature policy='require' name='vme'/>
+   <feature policy='require' name='ds'/>
+   <feature policy='require' name='acpi'/>
+   <feature policy='require' name='ss'/>
+@@ -18,15 +19,17 @@
+   <feature policy='require' name='pdcm'/>
+   <feature policy='require' name='dca'/>
+   <feature policy='require' name='osxsave'/>
++  <feature policy='require' name='f16c'/>
++  <feature policy='require' name='rdrand'/>
++  <feature policy='require' name='arat'/>
+   <feature policy='require' name='tsc_adjust'/>
+   <feature policy='require' name='cmt'/>
+   <feature policy='require' name='intel-pt'/>
+   <feature policy='require' name='stibp'/>
++  <feature policy='require' name='xsaveopt'/>
+   <feature policy='require' name='mbm_total'/>
+   <feature policy='require' name='mbm_local'/>
+   <feature policy='require' name='pdpe1gb'/>
++  <feature policy='require' name='abm'/>
+   <feature policy='require' name='invtsc'/>
+-  <feature policy='disable' name='mpx'/>
+-  <feature policy='disable' name='xsavec'/>
+-  <feature policy='disable' name='xgetbv1'/>
+ </cpu>
+diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E5-2623-v4-json.xml b/tests/cputestdata/x86_64-cpuid-Xeon-E5-2623-v4-json.xml
+index 167a9028ab..de082dbd93 100644
+--- a/tests/cputestdata/x86_64-cpuid-Xeon-E5-2623-v4-json.xml
++++ b/tests/cputestdata/x86_64-cpuid-Xeon-E5-2623-v4-json.xml
+@@ -1,11 +1,14 @@
+ <cpu mode='custom' match='exact'>
+-  <model fallback='forbid'>Skylake-Client-IBRS</model>
++  <model fallback='forbid'>Broadwell-IBRS</model>
+   <vendor>Intel</vendor>
++  <feature policy='require' name='vme'/>
+   <feature policy='require' name='ss'/>
++  <feature policy='require' name='f16c'/>
++  <feature policy='require' name='rdrand'/>
+   <feature policy='require' name='hypervisor'/>
++  <feature policy='require' name='arat'/>
+   <feature policy='require' name='tsc_adjust'/>
++  <feature policy='require' name='xsaveopt'/>
+   <feature policy='require' name='pdpe1gb'/>
+-  <feature policy='disable' name='mpx'/>
+-  <feature policy='disable' name='xsavec'/>
+-  <feature policy='disable' name='xgetbv1'/>
++  <feature policy='require' name='abm'/>
+ </cpu>
+diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E5-2630-v4-guest.xml b/tests/cputestdata/x86_64-cpuid-Xeon-E5-2630-v4-guest.xml
+index cd7e25b52a..e2999db8e9 100644
+--- a/tests/cputestdata/x86_64-cpuid-Xeon-E5-2630-v4-guest.xml
++++ b/tests/cputestdata/x86_64-cpuid-Xeon-E5-2630-v4-guest.xml
+@@ -1,6 +1,7 @@
+ <cpu mode='custom' match='exact'>
+-  <model fallback='forbid'>Skylake-Client</model>
++  <model fallback='forbid'>Broadwell</model>
+   <vendor>Intel</vendor>
++  <feature policy='require' name='vme'/>
+   <feature policy='require' name='ds'/>
+   <feature policy='require' name='acpi'/>
+   <feature policy='require' name='ss'/>
+@@ -18,14 +19,16 @@
+   <feature policy='require' name='pdcm'/>
+   <feature policy='require' name='dca'/>
+   <feature policy='require' name='osxsave'/>
++  <feature policy='require' name='f16c'/>
++  <feature policy='require' name='rdrand'/>
++  <feature policy='require' name='arat'/>
+   <feature policy='require' name='tsc_adjust'/>
+   <feature policy='require' name='cmt'/>
+   <feature policy='require' name='intel-pt'/>
++  <feature policy='require' name='xsaveopt'/>
+   <feature policy='require' name='mbm_total'/>
+   <feature policy='require' name='mbm_local'/>
+   <feature policy='require' name='pdpe1gb'/>
++  <feature policy='require' name='abm'/>
+   <feature policy='require' name='invtsc'/>
+-  <feature policy='disable' name='mpx'/>
+-  <feature policy='disable' name='xsavec'/>
+-  <feature policy='disable' name='xgetbv1'/>
+ </cpu>
+diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E5-2630-v4-json.xml b/tests/cputestdata/x86_64-cpuid-Xeon-E5-2630-v4-json.xml
+index 5dfce947b2..5b8891093a 100644
+--- a/tests/cputestdata/x86_64-cpuid-Xeon-E5-2630-v4-json.xml
++++ b/tests/cputestdata/x86_64-cpuid-Xeon-E5-2630-v4-json.xml
+@@ -1,11 +1,14 @@
+ <cpu mode='custom' match='exact'>
+-  <model fallback='forbid'>Skylake-Client</model>
++  <model fallback='forbid'>Broadwell</model>
+   <vendor>Intel</vendor>
++  <feature policy='require' name='vme'/>
+   <feature policy='require' name='ss'/>
++  <feature policy='require' name='f16c'/>
++  <feature policy='require' name='rdrand'/>
+   <feature policy='require' name='hypervisor'/>
++  <feature policy='require' name='arat'/>
+   <feature policy='require' name='tsc_adjust'/>
++  <feature policy='require' name='xsaveopt'/>
+   <feature policy='require' name='pdpe1gb'/>
+-  <feature policy='disable' name='mpx'/>
+-  <feature policy='disable' name='xsavec'/>
+-  <feature policy='disable' name='xgetbv1'/>
++  <feature policy='require' name='abm'/>
+ </cpu>
+diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E5-2650-v4-guest.xml b/tests/cputestdata/x86_64-cpuid-Xeon-E5-2650-v4-guest.xml
+index cd7e25b52a..e2999db8e9 100644
+--- a/tests/cputestdata/x86_64-cpuid-Xeon-E5-2650-v4-guest.xml
++++ b/tests/cputestdata/x86_64-cpuid-Xeon-E5-2650-v4-guest.xml
+@@ -1,6 +1,7 @@
+ <cpu mode='custom' match='exact'>
+-  <model fallback='forbid'>Skylake-Client</model>
++  <model fallback='forbid'>Broadwell</model>
+   <vendor>Intel</vendor>
++  <feature policy='require' name='vme'/>
+   <feature policy='require' name='ds'/>
+   <feature policy='require' name='acpi'/>
+   <feature policy='require' name='ss'/>
+@@ -18,14 +19,16 @@
+   <feature policy='require' name='pdcm'/>
+   <feature policy='require' name='dca'/>
+   <feature policy='require' name='osxsave'/>
++  <feature policy='require' name='f16c'/>
++  <feature policy='require' name='rdrand'/>
++  <feature policy='require' name='arat'/>
+   <feature policy='require' name='tsc_adjust'/>
+   <feature policy='require' name='cmt'/>
+   <feature policy='require' name='intel-pt'/>
++  <feature policy='require' name='xsaveopt'/>
+   <feature policy='require' name='mbm_total'/>
+   <feature policy='require' name='mbm_local'/>
+   <feature policy='require' name='pdpe1gb'/>
++  <feature policy='require' name='abm'/>
+   <feature policy='require' name='invtsc'/>
+-  <feature policy='disable' name='mpx'/>
+-  <feature policy='disable' name='xsavec'/>
+-  <feature policy='disable' name='xgetbv1'/>
+ </cpu>
+diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E5-2650-v4-json.xml b/tests/cputestdata/x86_64-cpuid-Xeon-E5-2650-v4-json.xml
+index 5dfce947b2..5b8891093a 100644
+--- a/tests/cputestdata/x86_64-cpuid-Xeon-E5-2650-v4-json.xml
++++ b/tests/cputestdata/x86_64-cpuid-Xeon-E5-2650-v4-json.xml
+@@ -1,11 +1,14 @@
+ <cpu mode='custom' match='exact'>
+-  <model fallback='forbid'>Skylake-Client</model>
++  <model fallback='forbid'>Broadwell</model>
+   <vendor>Intel</vendor>
++  <feature policy='require' name='vme'/>
+   <feature policy='require' name='ss'/>
++  <feature policy='require' name='f16c'/>
++  <feature policy='require' name='rdrand'/>
+   <feature policy='require' name='hypervisor'/>
++  <feature policy='require' name='arat'/>
+   <feature policy='require' name='tsc_adjust'/>
++  <feature policy='require' name='xsaveopt'/>
+   <feature policy='require' name='pdpe1gb'/>
+-  <feature policy='disable' name='mpx'/>
+-  <feature policy='disable' name='xsavec'/>
+-  <feature policy='disable' name='xgetbv1'/>
++  <feature policy='require' name='abm'/>
+ </cpu>
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-cpu_map-Add-more-signatures-for-Conroe-CPU-model.patch b/SOURCES/libvirt-cpu_map-Add-more-signatures-for-Conroe-CPU-model.patch
new file mode 100644
index 0000000..677455f
--- /dev/null
+++ b/SOURCES/libvirt-cpu_map-Add-more-signatures-for-Conroe-CPU-model.patch
@@ -0,0 +1,41 @@
+From 93520cb5f3b412c8cb4b5cf7098ff4a8c6c819ab Mon Sep 17 00:00:00 2001
+Message-Id: <93520cb5f3b412c8cb4b5cf7098ff4a8c6c819ab@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:25:09 +0200
+Subject: [PATCH] cpu_map: Add more signatures for Conroe CPU model
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit c1f6a3269c595e7d3d0c9cf31ef7e6cf88291056)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1686895
+
+Conflicts:
+	src/cpu_map/x86_Conroe.xml
+            - cpu_map split not backported
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <bdc4e7ff05e41cf66f69b61c0c622740f710d411.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/cpu/cpu_map.xml | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/src/cpu/cpu_map.xml b/src/cpu/cpu_map.xml
+index a5a5290a09..1699aec2cf 100644
+--- a/src/cpu/cpu_map.xml
++++ b/src/cpu/cpu_map.xml
+@@ -829,6 +829,7 @@
+     <!-- Intel CPU models -->
+     <model name='Conroe'>
+       <signature family='6' model='15'/> <!-- 0006f0 -->
++      <signature family='6' model='22'/> <!-- 010660 -->
+       <vendor name='Intel'/>
+       <feature name='apic'/>
+       <feature name='clflush'/>
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-cpu_map-Add-more-signatures-for-Haswell-CPU-models.patch b/SOURCES/libvirt-cpu_map-Add-more-signatures-for-Haswell-CPU-models.patch
new file mode 100644
index 0000000..a2782c6
--- /dev/null
+++ b/SOURCES/libvirt-cpu_map-Add-more-signatures-for-Haswell-CPU-models.patch
@@ -0,0 +1,76 @@
+From 41472ea4967eed29a41f619aca9c3d78504d0031 Mon Sep 17 00:00:00 2001
+Message-Id: <41472ea4967eed29a41f619aca9c3d78504d0031@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:25:15 +0200
+Subject: [PATCH] cpu_map: Add more signatures for Haswell CPU models
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit e58ca588cc0deee36c8ae44f2ad75bf9b1680fc5)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1686895
+
+Conflicts:
+	src/cpu_map/x86_Haswell-IBRS.xml
+	src/cpu_map/x86_Haswell-noTSX-IBRS.xml
+	src/cpu_map/x86_Haswell-noTSX.xml
+	src/cpu_map/x86_Haswell.xml
+            - cpu_map split not backported
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <f2154885afb3bb49b36ae3468b11251c7ebf896f.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/cpu/cpu_map.xml | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+diff --git a/src/cpu/cpu_map.xml b/src/cpu/cpu_map.xml
+index 9bd8bbbfbb..ed6006643b 100644
+--- a/src/cpu/cpu_map.xml
++++ b/src/cpu/cpu_map.xml
+@@ -1243,6 +1243,9 @@
+ 
+     <model name='Haswell-noTSX'>
+       <signature family='6' model='60'/> <!-- 0306c0 -->
++      <signature family='6' model='63'/> <!-- 0306f0 -->
++      <signature family='6' model='69'/> <!-- 040650 -->
++      <signature family='6' model='70'/> <!-- 040660 -->
+       <vendor name='Intel'/>
+       <feature name='aes'/>
+       <feature name='apic'/>
+@@ -1296,6 +1299,9 @@
+ 
+     <model name='Haswell-noTSX-IBRS'>
+       <signature family='6' model='60'/> <!-- 0306c0 -->
++      <signature family='6' model='63'/> <!-- 0306f0 -->
++      <signature family='6' model='69'/> <!-- 040650 -->
++      <signature family='6' model='70'/> <!-- 040660 -->
+       <vendor name='Intel'/>
+       <feature name='aes'/>
+       <feature name='apic'/>
+@@ -1350,6 +1356,9 @@
+ 
+     <model name='Haswell'>
+       <signature family='6' model='60'/> <!-- 0306c0 -->
++      <signature family='6' model='63'/> <!-- 0306f0 -->
++      <signature family='6' model='69'/> <!-- 040650 -->
++      <signature family='6' model='70'/> <!-- 040660 -->
+       <vendor name='Intel'/>
+       <feature name='aes'/>
+       <feature name='apic'/>
+@@ -1405,6 +1414,9 @@
+ 
+     <model name='Haswell-IBRS'>
+       <signature family='6' model='60'/> <!-- 0306c0 -->
++      <signature family='6' model='63'/> <!-- 0306f0 -->
++      <signature family='6' model='69'/> <!-- 040650 -->
++      <signature family='6' model='70'/> <!-- 040660 -->
+       <vendor name='Intel'/>
+       <feature name='aes'/>
+       <feature name='apic'/>
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-cpu_map-Add-more-signatures-for-IvyBridge-CPU-models.patch b/SOURCES/libvirt-cpu_map-Add-more-signatures-for-IvyBridge-CPU-models.patch
new file mode 100644
index 0000000..9f0f253
--- /dev/null
+++ b/SOURCES/libvirt-cpu_map-Add-more-signatures-for-IvyBridge-CPU-models.patch
@@ -0,0 +1,50 @@
+From 182faff133a2a21d6ce9fb2d2f2a59c10bded7a4 Mon Sep 17 00:00:00 2001
+Message-Id: <182faff133a2a21d6ce9fb2d2f2a59c10bded7a4@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:25:14 +0200
+Subject: [PATCH] cpu_map: Add more signatures for IvyBridge CPU models
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit 194105fef1a3a8645486df3323e460cc4a9b2d4c)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1686895
+
+Conflicts:
+	src/cpu_map/x86_IvyBridge-IBRS.xml
+	src/cpu_map/x86_IvyBridge.xml
+            - cpu_map split not backported
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <07778daea0841ab2e211311adc90fd04967b2fb3.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/cpu/cpu_map.xml | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/src/cpu/cpu_map.xml b/src/cpu/cpu_map.xml
+index 9eaba9572c..9bd8bbbfbb 100644
+--- a/src/cpu/cpu_map.xml
++++ b/src/cpu/cpu_map.xml
+@@ -1142,6 +1142,7 @@
+ 
+     <model name='IvyBridge'>
+       <signature family='6' model='58'/> <!-- 0306a0 -->
++      <signature family='6' model='62'/> <!-- 0306e0 -->
+       <vendor name='Intel'/>
+       <feature name='aes'/>
+       <feature name='apic'/>
+@@ -1191,6 +1192,7 @@
+ 
+     <model name='IvyBridge-IBRS'>
+       <signature family='6' model='58'/> <!-- 0306a0 -->
++      <signature family='6' model='62'/> <!-- 0306e0 -->
+       <vendor name='Intel'/>
+       <feature name='aes'/>
+       <feature name='apic'/>
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-cpu_map-Add-more-signatures-for-Nehalem-CPU-models.patch b/SOURCES/libvirt-cpu_map-Add-more-signatures-for-Nehalem-CPU-models.patch
new file mode 100644
index 0000000..ef1931e
--- /dev/null
+++ b/SOURCES/libvirt-cpu_map-Add-more-signatures-for-Nehalem-CPU-models.patch
@@ -0,0 +1,54 @@
+From 72bcfcf07c76288e943602995308d3e505aa1cff Mon Sep 17 00:00:00 2001
+Message-Id: <72bcfcf07c76288e943602995308d3e505aa1cff@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:25:11 +0200
+Subject: [PATCH] cpu_map: Add more signatures for Nehalem CPU models
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit f349f3c53f6427d9955ab7c57900c094f06dfd87)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1686895
+
+Conflicts:
+	src/cpu_map/x86_Nehalem-IBRS.xml
+	src/cpu_map/x86_Nehalem.xml
+            - cpu_map split not backported
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <6351ae62d5ea091e831968cd1fc50176d1552a86.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/cpu/cpu_map.xml | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/src/cpu/cpu_map.xml b/src/cpu/cpu_map.xml
+index f42b2e629c..4f9c247f3e 100644
+--- a/src/cpu/cpu_map.xml
++++ b/src/cpu/cpu_map.xml
+@@ -897,6 +897,9 @@
+ 
+     <model name='Nehalem'>
+       <signature family='6' model='26'/> <!-- 0106a0 -->
++      <signature family='6' model='30'/> <!-- 0106e0 -->
++      <signature family='6' model='31'/> <!-- 0106f0 -->
++      <signature family='6' model='46'/> <!-- 0206e0 -->
+       <vendor name='Intel'/>
+       <feature name='apic'/>
+       <feature name='clflush'/>
+@@ -933,6 +936,9 @@
+ 
+     <model name='Nehalem-IBRS'>
+       <signature family='6' model='26'/> <!-- 0106a0 -->
++      <signature family='6' model='30'/> <!-- 0106e0 -->
++      <signature family='6' model='31'/> <!-- 0106f0 -->
++      <signature family='6' model='46'/> <!-- 0206e0 -->
+       <vendor name='Intel'/>
+       <feature name='apic'/>
+       <feature name='clflush'/>
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-cpu_map-Add-more-signatures-for-Penryn-CPU-model.patch b/SOURCES/libvirt-cpu_map-Add-more-signatures-for-Penryn-CPU-model.patch
new file mode 100644
index 0000000..ff07b98
--- /dev/null
+++ b/SOURCES/libvirt-cpu_map-Add-more-signatures-for-Penryn-CPU-model.patch
@@ -0,0 +1,41 @@
+From 4042ef3cf2a0221d4c59a5adc9051ee9ae41aa7d Mon Sep 17 00:00:00 2001
+Message-Id: <4042ef3cf2a0221d4c59a5adc9051ee9ae41aa7d@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:25:10 +0200
+Subject: [PATCH] cpu_map: Add more signatures for Penryn CPU model
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit 0a09e59457f843b53c2702d1936bca6513868320)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1686895
+
+Conflicts:
+	src/cpu_map/x86_Penryn.xml
+            - cpu_map split not backported
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <1604252f9ef65cfb55161a0f8329ee6868926814.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/cpu/cpu_map.xml | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/src/cpu/cpu_map.xml b/src/cpu/cpu_map.xml
+index 1699aec2cf..f42b2e629c 100644
+--- a/src/cpu/cpu_map.xml
++++ b/src/cpu/cpu_map.xml
+@@ -862,6 +862,7 @@
+ 
+     <model name='Penryn'>
+       <signature family='6' model='23'/> <!-- 010670 -->
++      <signature family='6' model='29'/> <!-- 0106d0 -->
+       <vendor name='Intel'/>
+       <feature name='apic'/>
+       <feature name='clflush'/>
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-cpu_map-Add-more-signatures-for-SandyBridge-CPU-models.patch b/SOURCES/libvirt-cpu_map-Add-more-signatures-for-SandyBridge-CPU-models.patch
new file mode 100644
index 0000000..5685e1c
--- /dev/null
+++ b/SOURCES/libvirt-cpu_map-Add-more-signatures-for-SandyBridge-CPU-models.patch
@@ -0,0 +1,50 @@
+From 250d216f3f9f033ec39b2116b30c93b37967484c Mon Sep 17 00:00:00 2001
+Message-Id: <250d216f3f9f033ec39b2116b30c93b37967484c@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:25:13 +0200
+Subject: [PATCH] cpu_map: Add more signatures for SandyBridge CPU models
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit 4a3c3682f3da4ae1e1036c67db7ddba3dcc66d68)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1686895
+
+Conflicts:
+	src/cpu_map/x86_SandyBridge-IBRS.xml
+	src/cpu_map/x86_SandyBridge.xml
+            - cpu_map split not backported
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <521680181b58a762b0d6b3668e0d162fbc5d3cf9.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/cpu/cpu_map.xml | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/src/cpu/cpu_map.xml b/src/cpu/cpu_map.xml
+index fed0f51934..9eaba9572c 100644
+--- a/src/cpu/cpu_map.xml
++++ b/src/cpu/cpu_map.xml
+@@ -1053,6 +1053,7 @@
+ 
+     <model name='SandyBridge'>
+       <signature family='6' model='42'/> <!-- 0206a0 -->
++      <signature family='6' model='45'/> <!-- 0206d0 -->
+       <vendor name='Intel'/>
+       <feature name='aes'/>
+       <feature name='apic'/>
+@@ -1096,6 +1097,7 @@
+ 
+     <model name='SandyBridge-IBRS'>
+       <signature family='6' model='42'/> <!-- 0206a0 -->
++      <signature family='6' model='45'/> <!-- 0206d0 -->
+       <vendor name='Intel'/>
+       <feature name='aes'/>
+       <feature name='apic'/>
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-cpu_map-Add-more-signatures-for-Skylake-Client-CPU-models.patch b/SOURCES/libvirt-cpu_map-Add-more-signatures-for-Skylake-Client-CPU-models.patch
new file mode 100644
index 0000000..4672c57
--- /dev/null
+++ b/SOURCES/libvirt-cpu_map-Add-more-signatures-for-Skylake-Client-CPU-models.patch
@@ -0,0 +1,58 @@
+From f1a00c505aac83fe04f5385db5a9ed4768b0222b Mon Sep 17 00:00:00 2001
+Message-Id: <f1a00c505aac83fe04f5385db5a9ed4768b0222b@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:25:17 +0200
+Subject: [PATCH] cpu_map: Add more signatures for Skylake-Client CPU models
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit 367d96a5d6b04bf25d025ed59a7079d71f843c56)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1686895
+
+Conflicts:
+	src/cpu_map/x86_Skylake-Client-IBRS.xml
+	src/cpu_map/x86_Skylake-Client.xml
+            - cpu_map split not backported
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <d7ff83903e6d8ae1881afee54d3a248b9bb28678.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/cpu/cpu_map.xml | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/src/cpu/cpu_map.xml b/src/cpu/cpu_map.xml
+index 04369d1eda..b2eb07b832 100644
+--- a/src/cpu/cpu_map.xml
++++ b/src/cpu/cpu_map.xml
+@@ -1719,6 +1719,11 @@
+ 
+     <model name='Skylake-Client'>
+       <signature family='6' model='94'/> <!-- 0506e0 -->
++      <signature family='6' model='78'/> <!-- 0406e0 -->
++      <!-- These are Kaby Lake and Coffee Lake successors to Skylake,
++           but we don't have specific models for them. -->
++      <signature family='6' model='142'/> <!-- 0806e0 -->
++      <signature family='6' model='158'/> <!-- 0906e0 -->
+       <vendor name='Intel'/>
+       <feature name='3dnowprefetch'/>
+       <feature name='abm'/>
+@@ -1787,6 +1792,11 @@
+ 
+     <model name='Skylake-Client-IBRS'>
+       <signature family='6' model='94'/> <!-- 0506e0 -->
++      <signature family='6' model='78'/> <!-- 0406e0 -->
++      <!-- These are Kaby Lake and Coffee Lake successors to Skylake,
++           but we don't have specific models for them. -->
++      <signature family='6' model='142'/> <!-- 0806e0 -->
++      <signature family='6' model='158'/> <!-- 0906e0 -->
+       <vendor name='Intel'/>
+       <feature name='3dnowprefetch'/>
+       <feature name='abm'/>
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-cpu_map-Add-more-signatures-for-Westmere-CPU-model.patch b/SOURCES/libvirt-cpu_map-Add-more-signatures-for-Westmere-CPU-model.patch
new file mode 100644
index 0000000..ab8878e
--- /dev/null
+++ b/SOURCES/libvirt-cpu_map-Add-more-signatures-for-Westmere-CPU-model.patch
@@ -0,0 +1,184 @@
+From d31a3ba6c9396f8ede2966d49030e9b4011be636 Mon Sep 17 00:00:00 2001
+Message-Id: <d31a3ba6c9396f8ede2966d49030e9b4011be636@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:25:12 +0200
+Subject: [PATCH] cpu_map: Add more signatures for Westmere CPU model
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This fixes several CPUs which were incorrectly detected as a different
+CPU model.
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit e89f87721406f6ad6e811ff613a22dc804d69355)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1686895
+
+Conflicts:
+	src/cpu_map/x86_Westmere.xml
+            - cpu_map split not backported
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <facb5fd10ffe274e581e16db8362d0b8ee71424b.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/cpu/cpu_map.xml                                    |  2 ++
+ tests/cputestdata/x86_64-cpuid-Core-i5-650-json.xml    |  9 +++++----
+ tests/cputestdata/x86_64-cpuid-Pentium-P6100-guest.xml | 10 ++++++----
+ tests/cputestdata/x86_64-cpuid-Xeon-E7-4820-guest.xml  |  8 ++++----
+ tests/cputestdata/x86_64-cpuid-Xeon-E7-4820-json.xml   |  8 +++++---
+ tests/cputestdata/x86_64-cpuid-Xeon-E7-4830-json.xml   |  9 +++++----
+ 6 files changed, 27 insertions(+), 19 deletions(-)
+
+diff --git a/src/cpu/cpu_map.xml b/src/cpu/cpu_map.xml
+index 4f9c247f3e..fed0f51934 100644
+--- a/src/cpu/cpu_map.xml
++++ b/src/cpu/cpu_map.xml
+@@ -976,6 +976,8 @@
+ 
+     <model name='Westmere'>
+       <signature family='6' model='44'/> <!-- 0206c0 -->
++      <signature family='6' model='47'/> <!-- 0206f0 -->
++      <signature family='6' model='37'/> <!-- 020650 -->
+       <vendor name='Intel'/>
+       <feature name='aes'/>
+       <feature name='apic'/>
+diff --git a/tests/cputestdata/x86_64-cpuid-Core-i5-650-json.xml b/tests/cputestdata/x86_64-cpuid-Core-i5-650-json.xml
+index f5980f53e5..cb21e48a9f 100644
+--- a/tests/cputestdata/x86_64-cpuid-Core-i5-650-json.xml
++++ b/tests/cputestdata/x86_64-cpuid-Core-i5-650-json.xml
+@@ -1,12 +1,13 @@
+ <cpu mode='custom' match='exact'>
+-  <model fallback='forbid'>SandyBridge</model>
++  <model fallback='forbid'>Westmere</model>
+   <vendor>Intel</vendor>
+   <feature policy='require' name='vme'/>
+   <feature policy='require' name='ss'/>
++  <feature policy='require' name='pclmuldq'/>
++  <feature policy='require' name='x2apic'/>
++  <feature policy='require' name='tsc-deadline'/>
+   <feature policy='require' name='hypervisor'/>
+   <feature policy='require' name='arat'/>
+   <feature policy='require' name='tsc_adjust'/>
+-  <feature policy='disable' name='xsave'/>
+-  <feature policy='disable' name='avx'/>
+-  <feature policy='disable' name='xsaveopt'/>
++  <feature policy='require' name='rdtscp'/>
+ </cpu>
+diff --git a/tests/cputestdata/x86_64-cpuid-Pentium-P6100-guest.xml b/tests/cputestdata/x86_64-cpuid-Pentium-P6100-guest.xml
+index db5e0ae6af..20e2fa363a 100644
+--- a/tests/cputestdata/x86_64-cpuid-Pentium-P6100-guest.xml
++++ b/tests/cputestdata/x86_64-cpuid-Pentium-P6100-guest.xml
+@@ -1,6 +1,7 @@
+ <cpu mode='custom' match='exact'>
+-  <model fallback='forbid'>core2duo</model>
++  <model fallback='forbid'>Westmere</model>
+   <vendor>Intel</vendor>
++  <feature policy='require' name='vme'/>
+   <feature policy='require' name='ds'/>
+   <feature policy='require' name='acpi'/>
+   <feature policy='require' name='ss'/>
+@@ -8,16 +9,17 @@
+   <feature policy='require' name='tm'/>
+   <feature policy='require' name='pbe'/>
+   <feature policy='require' name='dtes64'/>
++  <feature policy='require' name='monitor'/>
+   <feature policy='require' name='ds_cpl'/>
+   <feature policy='require' name='est'/>
+   <feature policy='require' name='tm2'/>
+-  <feature policy='require' name='cx16'/>
+   <feature policy='require' name='xtpr'/>
+   <feature policy='require' name='pdcm'/>
+   <feature policy='require' name='pcid'/>
+-  <feature policy='require' name='popcnt'/>
+   <feature policy='require' name='arat'/>
+   <feature policy='require' name='rdtscp'/>
+-  <feature policy='require' name='lahf_lm'/>
+   <feature policy='require' name='invtsc'/>
++  <feature policy='disable' name='sse4.1'/>
++  <feature policy='disable' name='sse4.2'/>
++  <feature policy='disable' name='aes'/>
+ </cpu>
+diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E7-4820-guest.xml b/tests/cputestdata/x86_64-cpuid-Xeon-E7-4820-guest.xml
+index dbf8580a0e..659779687a 100644
+--- a/tests/cputestdata/x86_64-cpuid-Xeon-E7-4820-guest.xml
++++ b/tests/cputestdata/x86_64-cpuid-Xeon-E7-4820-guest.xml
+@@ -1,5 +1,5 @@
+ <cpu mode='custom' match='exact'>
+-  <model fallback='forbid'>SandyBridge</model>
++  <model fallback='forbid'>Westmere</model>
+   <vendor>Intel</vendor>
+   <feature policy='require' name='vme'/>
+   <feature policy='require' name='ds'/>
+@@ -8,6 +8,7 @@
+   <feature policy='require' name='ht'/>
+   <feature policy='require' name='tm'/>
+   <feature policy='require' name='pbe'/>
++  <feature policy='require' name='pclmuldq'/>
+   <feature policy='require' name='dtes64'/>
+   <feature policy='require' name='monitor'/>
+   <feature policy='require' name='ds_cpl'/>
+@@ -19,10 +20,9 @@
+   <feature policy='require' name='pdcm'/>
+   <feature policy='require' name='pcid'/>
+   <feature policy='require' name='dca'/>
++  <feature policy='require' name='x2apic'/>
+   <feature policy='require' name='arat'/>
+   <feature policy='require' name='pdpe1gb'/>
++  <feature policy='require' name='rdtscp'/>
+   <feature policy='require' name='invtsc'/>
+-  <feature policy='disable' name='tsc-deadline'/>
+-  <feature policy='disable' name='xsave'/>
+-  <feature policy='disable' name='avx'/>
+ </cpu>
+diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E7-4820-json.xml b/tests/cputestdata/x86_64-cpuid-Xeon-E7-4820-json.xml
+index d94a330f37..e8b74c5c30 100644
+--- a/tests/cputestdata/x86_64-cpuid-Xeon-E7-4820-json.xml
++++ b/tests/cputestdata/x86_64-cpuid-Xeon-E7-4820-json.xml
+@@ -1,12 +1,14 @@
+ <cpu mode='custom' match='exact'>
+-  <model fallback='forbid'>SandyBridge</model>
++  <model fallback='forbid'>Westmere</model>
+   <vendor>Intel</vendor>
+   <feature policy='require' name='vme'/>
+   <feature policy='require' name='ss'/>
++  <feature policy='require' name='pclmuldq'/>
+   <feature policy='require' name='pcid'/>
++  <feature policy='require' name='x2apic'/>
++  <feature policy='require' name='tsc-deadline'/>
+   <feature policy='require' name='hypervisor'/>
+   <feature policy='require' name='tsc_adjust'/>
+   <feature policy='require' name='pdpe1gb'/>
+-  <feature policy='disable' name='xsave'/>
+-  <feature policy='disable' name='avx'/>
++  <feature policy='require' name='rdtscp'/>
+ </cpu>
+diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E7-4830-json.xml b/tests/cputestdata/x86_64-cpuid-Xeon-E7-4830-json.xml
+index aae32bd7e2..da949ad25e 100644
+--- a/tests/cputestdata/x86_64-cpuid-Xeon-E7-4830-json.xml
++++ b/tests/cputestdata/x86_64-cpuid-Xeon-E7-4830-json.xml
+@@ -1,14 +1,15 @@
+ <cpu mode='custom' match='exact'>
+-  <model fallback='forbid'>SandyBridge</model>
++  <model fallback='forbid'>Westmere</model>
+   <vendor>Intel</vendor>
+   <feature policy='require' name='vme'/>
+   <feature policy='require' name='ss'/>
++  <feature policy='require' name='pclmuldq'/>
+   <feature policy='require' name='pcid'/>
++  <feature policy='require' name='x2apic'/>
++  <feature policy='require' name='tsc-deadline'/>
+   <feature policy='require' name='hypervisor'/>
+   <feature policy='require' name='arat'/>
+   <feature policy='require' name='tsc_adjust'/>
+   <feature policy='require' name='pdpe1gb'/>
+-  <feature policy='disable' name='xsave'/>
+-  <feature policy='disable' name='avx'/>
+-  <feature policy='disable' name='xsaveopt'/>
++  <feature policy='require' name='rdtscp'/>
+ </cpu>
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-cpu_map-Add-support-for-arch-capabilities-feature.patch b/SOURCES/libvirt-cpu_map-Add-support-for-arch-capabilities-feature.patch
new file mode 100644
index 0000000..e84978d
--- /dev/null
+++ b/SOURCES/libvirt-cpu_map-Add-support-for-arch-capabilities-feature.patch
@@ -0,0 +1,110 @@
+From bd665085c2cd890f2249042f135b7a1735932d1b Mon Sep 17 00:00:00 2001
+Message-Id: <bd665085c2cd890f2249042f135b7a1735932d1b@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:24:48 +0200
+Subject: [PATCH] cpu_map: Add support for arch-capabilities feature
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The feature was added to QEMU in 3.1.0 and it is currently blocking
+migration, which is expected to change in the future. Luckily 3.1.0 is
+new enough to give us migratability hints on each feature via
+query-cpu-model-expension, which means we don't need to use the
+"migratable" attribute on the CPU map XML.
+
+The kernel calls this feature arch_capabilities and RHEL/CentOS 7.* use
+arch-facilities. Apparently some CPU test files were gathered with the
+RHEL version of QEMU. Let's update the test files to avoid possible
+confusion about the correct naming.
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit 511df17aec36385320dbcc088ba85968537d1d42)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1693433
+
+Conflicts:
+	src/cpu_map/x86_features.xml
+            - cpu_map split was not backported
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <fc8d72f3a2191ef85b537943aa1cc844f50b038d.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/cpu/cpu_map.xml                                        | 3 +++
+ tests/cputestdata/x86_64-cpuid-EPYC-7601-32-Core-ibpb.json | 2 +-
+ tests/cputestdata/x86_64-cpuid-Xeon-E5-2609-v3.json        | 2 +-
+ tests/cputestdata/x86_64-cpuid-Xeon-E5-2623-v4.json        | 2 +-
+ tests/cputestdata/x86_64-cpuid-Xeon-Gold-5115.json         | 2 +-
+ 5 files changed, 7 insertions(+), 4 deletions(-)
+
+diff --git a/src/cpu/cpu_map.xml b/src/cpu/cpu_map.xml
+index ceee0ae489..a9f284fbbe 100644
+--- a/src/cpu/cpu_map.xml
++++ b/src/cpu/cpu_map.xml
+@@ -337,6 +337,9 @@
+     <feature name='stibp'>
+       <cpuid eax_in='0x07' ecx_in='0x00' edx='0x08000000'/>
+     </feature>
++    <feature name='arch-capabilities'> <!-- arch_capabilities, arch-facilities -->
++      <cpuid eax_in='0x07' ecx_in='0x00' edx='0x20000000'/>
++    </feature>
+     <feature name='ssbd'>
+       <cpuid eax_in='0x07' ecx_in='0x00' edx='0x80000000'/>
+     </feature>
+diff --git a/tests/cputestdata/x86_64-cpuid-EPYC-7601-32-Core-ibpb.json b/tests/cputestdata/x86_64-cpuid-EPYC-7601-32-Core-ibpb.json
+index 94a60fcc8f..1f53bb8bf3 100644
+--- a/tests/cputestdata/x86_64-cpuid-EPYC-7601-32-Core-ibpb.json
++++ b/tests/cputestdata/x86_64-cpuid-EPYC-7601-32-Core-ibpb.json
+@@ -232,7 +232,7 @@
+         "avx512vbmi": false,
+         "kvm-asyncpf": true,
+         "spec-ctrl": false,
+-        "arch-facilities": false,
++        "arch-capabilities": false,
+         "model": 1,
+         "node-id": -1
+       }
+diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E5-2609-v3.json b/tests/cputestdata/x86_64-cpuid-Xeon-E5-2609-v3.json
+index 10c5434263..6bdaf6e83a 100644
+--- a/tests/cputestdata/x86_64-cpuid-Xeon-E5-2609-v3.json
++++ b/tests/cputestdata/x86_64-cpuid-Xeon-E5-2609-v3.json
+@@ -232,7 +232,7 @@
+         "avx512vbmi": false,
+         "kvm-asyncpf": true,
+         "spec-ctrl": true,
+-        "arch-facilities": false,
++        "arch-capabilities": false,
+         "model": 63,
+         "node-id": -1
+       }
+diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E5-2623-v4.json b/tests/cputestdata/x86_64-cpuid-Xeon-E5-2623-v4.json
+index 0506dec0a7..2c6be20768 100644
+--- a/tests/cputestdata/x86_64-cpuid-Xeon-E5-2623-v4.json
++++ b/tests/cputestdata/x86_64-cpuid-Xeon-E5-2623-v4.json
+@@ -232,7 +232,7 @@
+         "avx512vbmi": false,
+         "kvm-asyncpf": true,
+         "spec-ctrl": true,
+-        "arch-facilities": false,
++        "arch-capabilities": false,
+         "model": 79,
+         "node-id": -1
+       }
+diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-Gold-5115.json b/tests/cputestdata/x86_64-cpuid-Xeon-Gold-5115.json
+index 79f3580219..79b47a56fb 100644
+--- a/tests/cputestdata/x86_64-cpuid-Xeon-Gold-5115.json
++++ b/tests/cputestdata/x86_64-cpuid-Xeon-Gold-5115.json
+@@ -232,7 +232,7 @@
+         "avx512vbmi": false,
+         "kvm-asyncpf": true,
+         "spec-ctrl": true,
+-        "arch-facilities": false,
++        "arch-capabilities": false,
+         "model": 85,
+         "node-id": -1
+       }
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-cpu_map-Add-support-for-cldemote-CPU-feature.patch b/SOURCES/libvirt-cpu_map-Add-support-for-cldemote-CPU-feature.patch
new file mode 100644
index 0000000..913e7e7
--- /dev/null
+++ b/SOURCES/libvirt-cpu_map-Add-support-for-cldemote-CPU-feature.patch
@@ -0,0 +1,46 @@
+From e7f71788bb7c3534b97fe50b05212e64aa9d1412 Mon Sep 17 00:00:00 2001
+Message-Id: <e7f71788bb7c3534b97fe50b05212e64aa9d1412@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Thu, 25 Apr 2019 16:36:43 +0200
+Subject: [PATCH] cpu_map: Add support for cldemote CPU feature
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Added in QEMU by v2.12.0-481-g0da0fb0628 (released in 3.0).
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit 8feeee9ee23f0500cc2585e1b11231c54de8e93d)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1537731
+https://bugzilla.redhat.com/show_bug.cgi?id=1537777
+
+Conflicts:
+	src/cpu_map/x86_features.xml
+            - features are defined in src/cpu/cpu_map.xml downstream
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <bb26b8e5c8323be651bae3d1c15aa04528f2c26d.1556202959.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/cpu/cpu_map.xml | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/src/cpu/cpu_map.xml b/src/cpu/cpu_map.xml
+index 095d49a69a..79c40cff34 100644
+--- a/src/cpu/cpu_map.xml
++++ b/src/cpu/cpu_map.xml
+@@ -315,6 +315,9 @@
+     <feature name='la57'>
+       <cpuid eax_in='0x07' ecx_in='0x00' ecx='0x00010000'/>
+     </feature>
++    <feature name='cldemote'>
++      <cpuid eax_in='0x07' ecx_in='0x00' ecx='0x02000000'/>
++    </feature>
+ 
+     <feature name='avx512-4vnniw'>
+       <cpuid eax_in='0x07' ecx_in='0x00' edx='0x00000004'/>
+-- 
+2.21.0
+
diff --git a/SOURCES/libvirt-cpu_map-Define-md-clear-CPUID-bit.patch b/SOURCES/libvirt-cpu_map-Define-md-clear-CPUID-bit.patch
index 856d764..61a7eec 100644
--- a/SOURCES/libvirt-cpu_map-Define-md-clear-CPUID-bit.patch
+++ b/SOURCES/libvirt-cpu_map-Define-md-clear-CPUID-bit.patch
@@ -1,5 +1,5 @@
-From 9ee392a5b6700c0aca597338106f2bd02ef9c4ec Mon Sep 17 00:00:00 2001
-Message-Id: <9ee392a5b6700c0aca597338106f2bd02ef9c4ec@dist-git>
+From 28c9a09d1f42513344c546ac344f90ae3280fd5b Mon Sep 17 00:00:00 2001
+Message-Id: <28c9a09d1f42513344c546ac344f90ae3280fd5b@dist-git>
 From: Jiri Denemark <jdenemar@redhat.com>
 Date: Fri, 5 Apr 2019 15:11:20 +0200
 Subject: [PATCH] cpu_map: Define md-clear CPUID bit
@@ -7,7 +7,7 @@ MIME-Version: 1.0
 Content-Type: text/plain; charset=UTF-8
 Content-Transfer-Encoding: 8bit
 
-CVE-2018-11091, CVE-2018-12126, CVE-2018-12127, CVE-2018-12130
+CVE-2018-12126, CVE-2018-12127, CVE-2018-12130, CVE-2019-11091
 
 The bit is set when microcode provides the mechanism to invoke a flush
 of various exploitable CPU buffers by invoking the VERW instruction.
@@ -15,7 +15,7 @@ of various exploitable CPU buffers by invoking the VERW instruction.
 Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
 Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
 Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
-(cherry picked from a private commit)
+(cherry picked from commit 538d873571d7a682852dc1d70e5f4478f4d64e85)
 
 Conflicts:
 	src/cpu_map/x86_features.xml
@@ -35,10 +35,10 @@ Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
  5 files changed, 7 insertions(+), 1 deletion(-)
 
 diff --git a/src/cpu/cpu_map.xml b/src/cpu/cpu_map.xml
-index 095d49a69a..2f77e5cc7f 100644
+index 79c40cff34..ceee0ae489 100644
 --- a/src/cpu/cpu_map.xml
 +++ b/src/cpu/cpu_map.xml
-@@ -322,6 +322,9 @@
+@@ -325,6 +325,9 @@
      <feature name='avx512-4fmaps'>
        <cpuid eax_in='0x07' ecx_in='0x00' edx='0x00000008'/>
      </feature>
diff --git a/SOURCES/libvirt-cpu_map-Introduce-IA32_ARCH_CAPABILITIES-MSR-features.patch b/SOURCES/libvirt-cpu_map-Introduce-IA32_ARCH_CAPABILITIES-MSR-features.patch
new file mode 100644
index 0000000..945e56f
--- /dev/null
+++ b/SOURCES/libvirt-cpu_map-Introduce-IA32_ARCH_CAPABILITIES-MSR-features.patch
@@ -0,0 +1,155 @@
+From 0c781b84fe81ca2d4865e92d6c22dafcea62261c Mon Sep 17 00:00:00 2001
+Message-Id: <0c781b84fe81ca2d4865e92d6c22dafcea62261c@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:26:10 +0200
+Subject: [PATCH] cpu_map: Introduce IA32_ARCH_CAPABILITIES MSR features
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit c8ec678fd9d97189667c0121f48a220dd26856b7)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1697627
+
+Conflicts:
+	src/cpu_map/x86_features.xml
+            - cpu_map XML is not split downstream
+
+	tests/domaincapsschemadata/qemu_3.1.0.x86_64.xml
+	tests/domaincapsschemadata/qemu_4.0.0.x86_64.xml
+            - missing
+
+	tests/domaincapsschemadata/qemu_4.1.0.x86_64.xml
+            - commit 4586b11bed9bc59ea749e28f522bf5e0b462c4c7 not
+              backported
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <acddba8b7464f063de46f04fc421319cc78ad86c.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/cpu/cpu_map.xml                           | 20 +++++++++++++++++++
+ .../x86_64-cpuid-Core-i7-7600U-enabled.xml    |  1 +
+ .../x86_64-cpuid-Core-i7-7600U-json.xml       |  1 +
+ ...86_64-cpuid-Xeon-Platinum-8268-enabled.xml |  1 +
+ .../x86_64-cpuid-Xeon-Platinum-8268-guest.xml |  4 ++++
+ .../x86_64-cpuid-Xeon-Platinum-8268-host.xml  |  4 ++++
+ .../x86_64-cpuid-Xeon-Platinum-8268-json.xml  |  3 +++
+ .../qemu_4.1.0.x86_64.xml                     |  1 +
+ 8 files changed, 35 insertions(+)
+
+diff --git a/src/cpu/cpu_map.xml b/src/cpu/cpu_map.xml
+index 9b289556e8..acd9dad7dc 100644
+--- a/src/cpu/cpu_map.xml
++++ b/src/cpu/cpu_map.xml
+@@ -482,6 +482,26 @@
+       <cpuid eax_in='0x80000008' ebx='0x02000000'/>
+     </feature>
+ 
++    <!-- IA32_ARCH_CAPABILITIES features -->
++    <feature name='rdctl-no'>
++      <msr index='0x10a' edx='0x00000000' eax='0x00000001'/>
++    </feature>
++    <feature name='ibrs-all'>
++      <msr index='0x10a' edx='0x00000000' eax='0x00000002'/>
++    </feature>
++    <feature name='rsba'>
++      <msr index='0x10a' edx='0x00000000' eax='0x00000004'/>
++    </feature>
++    <feature name='skip-l1dfl-vmentry'>
++      <msr index='0x10a' edx='0x00000000' eax='0x00000008'/>
++    </feature>
++    <feature name='ssb-no'>
++      <msr index='0x10a' edx='0x00000000' eax='0x00000010'/>
++    </feature>
++    <feature name='mds-no'>
++      <msr index='0x10a' edx='0x00000000' eax='0x00000020'/>
++    </feature>
++
+     <!-- models -->
+     <model name='486'>
+       <feature name='fpu'/>
+diff --git a/tests/cputestdata/x86_64-cpuid-Core-i7-7600U-enabled.xml b/tests/cputestdata/x86_64-cpuid-Core-i7-7600U-enabled.xml
+index b1cdaa802a..58bc84577c 100644
+--- a/tests/cputestdata/x86_64-cpuid-Core-i7-7600U-enabled.xml
++++ b/tests/cputestdata/x86_64-cpuid-Core-i7-7600U-enabled.xml
+@@ -5,4 +5,5 @@
+   <cpuid eax_in='0x00000007' ecx_in='0x00' eax='0x00000000' ebx='0x009c4fbb' ecx='0x00000004' edx='0x84000000'/>
+   <cpuid eax_in='0x0000000d' ecx_in='0x01' eax='0x0000000f' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
+   <cpuid eax_in='0x80000001' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000121' edx='0x2c100800'/>
++  <msr index='0x10a' edx='0x00000000' eax='0x00000008'/>
+ </cpudata>
+diff --git a/tests/cputestdata/x86_64-cpuid-Core-i7-7600U-json.xml b/tests/cputestdata/x86_64-cpuid-Core-i7-7600U-json.xml
+index 48089c6003..690081493b 100644
+--- a/tests/cputestdata/x86_64-cpuid-Core-i7-7600U-json.xml
++++ b/tests/cputestdata/x86_64-cpuid-Core-i7-7600U-json.xml
+@@ -10,4 +10,5 @@
+   <feature policy='require' name='ssbd'/>
+   <feature policy='require' name='xsaves'/>
+   <feature policy='require' name='pdpe1gb'/>
++  <feature policy='require' name='skip-l1dfl-vmentry'/>
+ </cpu>
+diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-enabled.xml b/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-enabled.xml
+index 434ac1956a..313009b156 100644
+--- a/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-enabled.xml
++++ b/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-enabled.xml
+@@ -5,4 +5,5 @@
+   <cpuid eax_in='0x00000007' ecx_in='0x00' eax='0x00000000' ebx='0xd19f4fbb' ecx='0x0000080c' edx='0x84000000'/>
+   <cpuid eax_in='0x0000000d' ecx_in='0x01' eax='0x0000000f' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
+   <cpuid eax_in='0x80000001' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000121' edx='0x2c100800'/>
++  <msr index='0x10a' edx='0x00000000' eax='0x0000000b'/>
+ </cpudata>
+diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-guest.xml b/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-guest.xml
+index c7e8a1fccf..988fb1dbdc 100644
+--- a/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-guest.xml
++++ b/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-guest.xml
+@@ -30,4 +30,8 @@
+   <feature policy='require' name='mbm_total'/>
+   <feature policy='require' name='mbm_local'/>
+   <feature policy='require' name='invtsc'/>
++  <feature policy='require' name='rdctl-no'/>
++  <feature policy='require' name='ibrs-all'/>
++  <feature policy='require' name='skip-l1dfl-vmentry'/>
++  <feature policy='require' name='mds-no'/>
+ </cpu>
+diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-host.xml b/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-host.xml
+index d7482751b4..fdeafc4870 100644
+--- a/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-host.xml
++++ b/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-host.xml
+@@ -31,4 +31,8 @@
+   <feature name='mbm_total'/>
+   <feature name='mbm_local'/>
+   <feature name='invtsc'/>
++  <feature name='rdctl-no'/>
++  <feature name='ibrs-all'/>
++  <feature name='skip-l1dfl-vmentry'/>
++  <feature name='mds-no'/>
+ </cpu>
+diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-json.xml b/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-json.xml
+index b7d12dced7..78863c61d1 100644
+--- a/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-json.xml
++++ b/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-json.xml
+@@ -7,4 +7,7 @@
+   <feature policy='require' name='umip'/>
+   <feature policy='require' name='pku'/>
+   <feature policy='require' name='xsaves'/>
++  <feature policy='require' name='rdctl-no'/>
++  <feature policy='require' name='ibrs-all'/>
++  <feature policy='require' name='skip-l1dfl-vmentry'/>
+ </cpu>
+diff --git a/tests/domaincapsschemadata/qemu_4.1.0.x86_64.xml b/tests/domaincapsschemadata/qemu_4.1.0.x86_64.xml
+index 47aed6a43a..63ae7957c4 100644
+--- a/tests/domaincapsschemadata/qemu_4.1.0.x86_64.xml
++++ b/tests/domaincapsschemadata/qemu_4.1.0.x86_64.xml
+@@ -34,6 +34,7 @@
+       <feature policy='require' name='arch-capabilities'/>
+       <feature policy='require' name='xsaves'/>
+       <feature policy='require' name='pdpe1gb'/>
++      <feature policy='require' name='skip-l1dfl-vmentry'/>
+     </mode>
+     <mode name='custom' supported='yes'>
+       <model usable='yes'>qemu64</model>
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-cpu_x86-Add-support-for-storing-MSR-features-in-CPU-map.patch b/SOURCES/libvirt-cpu_x86-Add-support-for-storing-MSR-features-in-CPU-map.patch
new file mode 100644
index 0000000..8f72765
--- /dev/null
+++ b/SOURCES/libvirt-cpu_x86-Add-support-for-storing-MSR-features-in-CPU-map.patch
@@ -0,0 +1,328 @@
+From 808b0c73134cd3c6a7fdd387fd9654dbd41356ac Mon Sep 17 00:00:00 2001
+Message-Id: <808b0c73134cd3c6a7fdd387fd9654dbd41356ac@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:25:39 +0200
+Subject: [PATCH] cpu_x86: Add support for storing MSR features in CPU map
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit fcf4846a6bb902a5cd2230fff2a1e7591dcb7456)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1697627
+
+Conflicts:
+	tests/cputestdata/cpu-cpuid.py
+            - no need to update this script downstream
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <0c37dabaaa6c2559b48918ca55e170750fe34ea0.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/cpu/cpu_x86.c      | 127 +++++++++++++++++++++++++++++++++++++----
+ src/cpu/cpu_x86_data.h |  10 ++++
+ 2 files changed, 125 insertions(+), 12 deletions(-)
+
+diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
+index e6da974b31..49562944c1 100644
+--- a/src/cpu/cpu_x86.c
++++ b/src/cpu/cpu_x86.c
+@@ -197,6 +197,8 @@ virCPUx86DataItemMatch(const virCPUx86DataItem *item1,
+ {
+     const virCPUx86CPUID *cpuid1;
+     const virCPUx86CPUID *cpuid2;
++    const virCPUx86MSR *msr1;
++    const virCPUx86MSR *msr2;
+ 
+     switch (item1->type) {
+     case VIR_CPU_X86_DATA_CPUID:
+@@ -207,6 +209,12 @@ virCPUx86DataItemMatch(const virCPUx86DataItem *item1,
+                 cpuid1->ecx == cpuid2->ecx &&
+                 cpuid1->edx == cpuid2->edx);
+ 
++    case VIR_CPU_X86_DATA_MSR:
++        msr1 = &item1->data.msr;
++        msr2 = &item2->data.msr;
++        return (msr1->eax == msr2->eax &&
++                msr1->edx == msr2->edx);
++
+     case VIR_CPU_X86_DATA_NONE:
+     default:
+         return false;
+@@ -220,6 +228,8 @@ virCPUx86DataItemMatchMasked(const virCPUx86DataItem *item,
+ {
+     const virCPUx86CPUID *cpuid;
+     const virCPUx86CPUID *cpuidMask;
++    const virCPUx86MSR *msr;
++    const virCPUx86MSR *msrMask;
+ 
+     switch (item->type) {
+     case VIR_CPU_X86_DATA_CPUID:
+@@ -230,6 +240,12 @@ virCPUx86DataItemMatchMasked(const virCPUx86DataItem *item,
+                 (cpuid->ecx & cpuidMask->ecx) == cpuidMask->ecx &&
+                 (cpuid->edx & cpuidMask->edx) == cpuidMask->edx);
+ 
++    case VIR_CPU_X86_DATA_MSR:
++        msr = &item->data.msr;
++        msrMask = &mask->data.msr;
++        return ((msr->eax & msrMask->eax) == msrMask->eax &&
++                (msr->edx & msrMask->edx) == msrMask->edx);
++
+     case VIR_CPU_X86_DATA_NONE:
+     default:
+         return false;
+@@ -243,6 +259,8 @@ virCPUx86DataItemSetBits(virCPUx86DataItemPtr item,
+ {
+     virCPUx86CPUIDPtr cpuid;
+     const virCPUx86CPUID *cpuidMask;
++    virCPUx86MSRPtr msr;
++    const virCPUx86MSR *msrMask;
+ 
+     if (!mask)
+         return;
+@@ -257,6 +275,13 @@ virCPUx86DataItemSetBits(virCPUx86DataItemPtr item,
+         cpuid->edx |= cpuidMask->edx;
+         break;
+ 
++    case VIR_CPU_X86_DATA_MSR:
++        msr = &item->data.msr;
++        msrMask = &mask->data.msr;
++        msr->eax |= msrMask->eax;
++        msr->edx |= msrMask->edx;
++        break;
++
+     case VIR_CPU_X86_DATA_NONE:
+     default:
+         break;
+@@ -270,6 +295,8 @@ virCPUx86DataItemClearBits(virCPUx86DataItemPtr item,
+ {
+     virCPUx86CPUIDPtr cpuid;
+     const virCPUx86CPUID *cpuidMask;
++    virCPUx86MSRPtr msr;
++    const virCPUx86MSR *msrMask;
+ 
+     if (!mask)
+         return;
+@@ -284,6 +311,13 @@ virCPUx86DataItemClearBits(virCPUx86DataItemPtr item,
+         cpuid->edx &= ~cpuidMask->edx;
+         break;
+ 
++    case VIR_CPU_X86_DATA_MSR:
++        msr = &item->data.msr;
++        msrMask = &mask->data.msr;
++        msr->eax &= ~msrMask->eax;
++        msr->edx &= ~msrMask->edx;
++        break;
++
+     case VIR_CPU_X86_DATA_NONE:
+     default:
+         break;
+@@ -297,6 +331,8 @@ virCPUx86DataItemAndBits(virCPUx86DataItemPtr item,
+ {
+     virCPUx86CPUIDPtr cpuid;
+     const virCPUx86CPUID *cpuidMask;
++    virCPUx86MSRPtr msr;
++    const virCPUx86MSR *msrMask;
+ 
+     if (!mask)
+         return;
+@@ -311,6 +347,13 @@ virCPUx86DataItemAndBits(virCPUx86DataItemPtr item,
+         cpuid->edx &= cpuidMask->edx;
+         break;
+ 
++    case VIR_CPU_X86_DATA_MSR:
++        msr = &item->data.msr;
++        msrMask = &mask->data.msr;
++        msr->eax &= msrMask->eax;
++        msr->edx &= msrMask->edx;
++        break;
++
+     case VIR_CPU_X86_DATA_NONE:
+     default:
+         break;
+@@ -373,6 +416,14 @@ virCPUx86DataSorter(const void *a, const void *b)
+ 
+         break;
+ 
++    case VIR_CPU_X86_DATA_MSR:
++        if (da->data.msr.index > db->data.msr.index)
++            return 1;
++        else if (da->data.msr.index < db->data.msr.index)
++            return -1;
++
++        break;
++
+     case VIR_CPU_X86_DATA_NONE:
+     default:
+         break;
+@@ -978,6 +1029,31 @@ x86ParseCPUID(xmlXPathContextPtr ctxt,
+ }
+ 
+ 
++static int
++x86ParseMSR(xmlXPathContextPtr ctxt,
++            virCPUx86DataItemPtr item)
++{
++    virCPUx86MSRPtr msr;
++    unsigned long index;
++    unsigned long eax;
++    unsigned long edx;
++
++    memset(item, 0, sizeof(*item));
++
++    if (virXPathULongHex("string(@index)", ctxt, &index) < 0 ||
++        virXPathULongHex("string(@eax)", ctxt, &eax) < 0 ||
++        virXPathULongHex("string(@edx)", ctxt, &edx) < 0)
++        return -1;
++
++    item->type = VIR_CPU_X86_DATA_MSR;
++    msr = &item->data.msr;
++    msr->index = index;
++    msr->eax = eax;
++    msr->edx = edx;
++    return 0;
++}
++
++
+ static int
+ x86FeatureParse(xmlXPathContextPtr ctxt,
+                 const char *name,
+@@ -1010,25 +1086,35 @@ x86FeatureParse(xmlXPathContextPtr ctxt,
+     if (STREQ_NULLABLE(str, "no"))
+         feature->migratable = false;
+ 
+-    n = virXPathNodeSet("./cpuid", ctxt, &nodes);
++    n = virXPathNodeSet("./cpuid|./msr", ctxt, &nodes);
+     if (n < 0)
+         goto cleanup;
+ 
+     if (n == 0) {
+         virReportError(VIR_ERR_INTERNAL_ERROR,
+-                       _("Missing cpuid for feature %s"),
++                       _("Missing cpuid or msr element in feature %s"),
+                        feature->name);
+         goto cleanup;
+     }
+ 
+     for (i = 0; i < n; i++) {
+         ctxt->node = nodes[i];
+-        if (x86ParseCPUID(ctxt, &item) < 0) {
+-            virReportError(VIR_ERR_INTERNAL_ERROR,
+-                           _("Invalid cpuid[%zu] in %s feature"),
+-                           i, feature->name);
+-            goto cleanup;
++        if (virXMLNodeNameEqual(nodes[i], "cpuid")) {
++            if (x86ParseCPUID(ctxt, &item) < 0) {
++                virReportError(VIR_ERR_INTERNAL_ERROR,
++                               _("Invalid cpuid[%zu] in %s feature"),
++                               i, feature->name);
++                goto cleanup;
++            }
++        } else {
++            if (x86ParseMSR(ctxt, &item) < 0) {
++                virReportError(VIR_ERR_INTERNAL_ERROR,
++                               _("Invalid msr[%zu] in %s feature"),
++                               i, feature->name);
++                goto cleanup;
++            }
+         }
++
+         if (virCPUx86DataAddItem(&feature->data, &item))
+             goto cleanup;
+     }
+@@ -1544,6 +1630,7 @@ virCPUx86DataFormat(const virCPUData *data)
+     virBufferAddLit(&buf, "<cpudata arch='x86'>\n");
+     while ((item = virCPUx86DataNext(&iter))) {
+         virCPUx86CPUIDPtr cpuid;
++        virCPUx86MSRPtr msr;
+ 
+         switch (item->type) {
+         case VIR_CPU_X86_DATA_CPUID:
+@@ -1556,6 +1643,13 @@ virCPUx86DataFormat(const virCPUData *data)
+                               cpuid->eax, cpuid->ebx, cpuid->ecx, cpuid->edx);
+             break;
+ 
++        case VIR_CPU_X86_DATA_MSR:
++            msr = &item->data.msr;
++            virBufferAsprintf(&buf,
++                              "  <msr index='0x%x' eax='0x%08x' edx='0x%08x'/>\n",
++                              msr->index, msr->eax, msr->edx);
++            break;
++
+         case VIR_CPU_X86_DATA_NONE:
+         default:
+             break;
+@@ -1579,7 +1673,7 @@ virCPUx86DataParse(xmlXPathContextPtr ctxt)
+     size_t i;
+     int n;
+ 
+-    n = virXPathNodeSet("/cpudata/cpuid", ctxt, &nodes);
++    n = virXPathNodeSet("/cpudata/cpuid|/cpudata/msr", ctxt, &nodes);
+     if (n <= 0) {
+         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                        _("no x86 CPU data found"));
+@@ -1591,11 +1685,20 @@ virCPUx86DataParse(xmlXPathContextPtr ctxt)
+ 
+     for (i = 0; i < n; i++) {
+         ctxt->node = nodes[i];
+-        if (x86ParseCPUID(ctxt, &item) < 0) {
+-            virReportError(VIR_ERR_INTERNAL_ERROR,
+-                           _("failed to parse cpuid[%zu]"), i);
+-            goto error;
++        if (virXMLNodeNameEqual(nodes[i], "cpuid")) {
++            if (x86ParseCPUID(ctxt, &item) < 0) {
++                virReportError(VIR_ERR_INTERNAL_ERROR,
++                               _("failed to parse cpuid[%zu]"), i);
++                goto error;
++            }
++        } else {
++            if (x86ParseMSR(ctxt, &item) < 0) {
++                virReportError(VIR_ERR_INTERNAL_ERROR,
++                               _("failed to parse msr[%zu]"), i);
++                goto error;
++            }
+         }
++
+         if (virCPUx86DataAdd(cpuData, &item) < 0)
+             goto error;
+     }
+diff --git a/src/cpu/cpu_x86_data.h b/src/cpu/cpu_x86_data.h
+index da8e91fe71..454345b688 100644
+--- a/src/cpu/cpu_x86_data.h
++++ b/src/cpu/cpu_x86_data.h
+@@ -37,6 +37,14 @@ struct _virCPUx86CPUID {
+     uint32_t edx;
+ };
+ 
++typedef struct _virCPUx86MSR virCPUx86MSR;
++typedef virCPUx86MSR *virCPUx86MSRPtr;
++struct _virCPUx86MSR {
++    uint32_t index;
++    uint32_t eax;
++    uint32_t edx;
++};
++
+ # define CPUX86_BASIC    0x0
+ # define CPUX86_KVM      0x40000000
+ # define CPUX86_EXTENDED 0x80000000
+@@ -74,6 +82,7 @@ struct _virCPUx86CPUID {
+ typedef enum {
+     VIR_CPU_X86_DATA_NONE = 0,
+     VIR_CPU_X86_DATA_CPUID,
++    VIR_CPU_X86_DATA_MSR,
+ } virCPUx86DataType;
+ 
+ typedef struct _virCPUx86DataItem virCPUx86DataItem;
+@@ -82,6 +91,7 @@ struct _virCPUx86DataItem {
+     virCPUx86DataType type;
+     union {
+         virCPUx86CPUID cpuid;
++        virCPUx86MSR msr;
+     } data;
+ };
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-cpu_x86-Add-virCPUx86DataGetSignature-for-tests.patch b/SOURCES/libvirt-cpu_x86-Add-virCPUx86DataGetSignature-for-tests.patch
new file mode 100644
index 0000000..034a778
--- /dev/null
+++ b/SOURCES/libvirt-cpu_x86-Add-virCPUx86DataGetSignature-for-tests.patch
@@ -0,0 +1,81 @@
+From 459e059de518794d909c77b6c24fd6962558d362 Mon Sep 17 00:00:00 2001
+Message-Id: <459e059de518794d909c77b6c24fd6962558d362@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:25:06 +0200
+Subject: [PATCH] cpu_x86: Add virCPUx86DataGetSignature for tests
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The function exports the functionality of x86DataToSignatureFull and
+x86MakeSignature to the test suite.
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit 661307b4b2e8597d889efddfac0ff5d324c9fa42)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1686895
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <7964c9cc9ea47fdce4c2b07fda8efa2cb9f9f384.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/cpu/cpu_x86.c        | 12 ++++++++++++
+ src/cpu/cpu_x86.h        |  5 +++++
+ src/libvirt_private.syms |  1 +
+ 3 files changed, 18 insertions(+)
+
+diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
+index ba14a6097d..24569a90f3 100644
+--- a/src/cpu/cpu_x86.c
++++ b/src/cpu/cpu_x86.c
+@@ -3066,6 +3066,18 @@ virCPUx86DataSetSignature(virCPUDataPtr cpuData,
+ }
+ 
+ 
++uint32_t
++virCPUx86DataGetSignature(virCPUDataPtr cpuData,
++                          unsigned int *family,
++                          unsigned int *model,
++                          unsigned int *stepping)
++{
++    x86DataToSignatureFull(&cpuData->data.x86, family, model, stepping);
++
++    return x86MakeSignature(*family, *model, *stepping);
++}
++
++
+ int
+ virCPUx86DataSetVendor(virCPUDataPtr cpuData,
+                        const char *vendor)
+diff --git a/src/cpu/cpu_x86.h b/src/cpu/cpu_x86.h
+index 5d14d83e1b..9d3c2b2cdd 100644
+--- a/src/cpu/cpu_x86.h
++++ b/src/cpu/cpu_x86.h
+@@ -37,6 +37,11 @@ int virCPUx86DataSetSignature(virCPUDataPtr cpuData,
+                               unsigned int model,
+                               unsigned int stepping);
+ 
++uint32_t virCPUx86DataGetSignature(virCPUDataPtr cpuData,
++                                   unsigned int *family,
++                                   unsigned int *model,
++                                   unsigned int *stepping);
++
+ int virCPUx86DataSetVendor(virCPUDataPtr cpuData,
+                            const char *vendor);
+ 
+diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
+index 7c48908a54..a275fa9aa1 100644
+--- a/src/libvirt_private.syms
++++ b/src/libvirt_private.syms
+@@ -1205,6 +1205,7 @@ virCPUValidateFeatures;
+ # cpu/cpu_x86.h
+ virCPUx86DataAddCPUID;
+ virCPUx86DataAddFeature;
++virCPUx86DataGetSignature;
+ virCPUx86DataSetSignature;
+ virCPUx86DataSetVendor;
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-cpu_x86-Add-x86ModelCopySignatures-helper.patch b/SOURCES/libvirt-cpu_x86-Add-x86ModelCopySignatures-helper.patch
new file mode 100644
index 0000000..9d389e8
--- /dev/null
+++ b/SOURCES/libvirt-cpu_x86-Add-x86ModelCopySignatures-helper.patch
@@ -0,0 +1,77 @@
+From 0b98a3d385f3d46949c5b2bc15c27c7c62739496 Mon Sep 17 00:00:00 2001
+Message-Id: <0b98a3d385f3d46949c5b2bc15c27c7c62739496@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:24:59 +0200
+Subject: [PATCH] cpu_x86: Add x86ModelCopySignatures helper
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Introduce a helper for copying CPU signature between two CPU models.
+
+It's not very useful until the way we store signatures is changed in the
+next patch.
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit 2254c1cfb854dfc52f3b4bfdfca2bd995b0a163c)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1686895
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <eb973566dab0f8d77ff536e4c56eb6bffd77928f.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/cpu/cpu_x86.c | 16 +++++++++++++---
+ 1 file changed, 13 insertions(+), 3 deletions(-)
+
+diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
+index 51cb9b7143..e25bc691ae 100644
+--- a/src/cpu/cpu_x86.c
++++ b/src/cpu/cpu_x86.c
+@@ -977,6 +977,16 @@ x86ModelFree(virCPUx86ModelPtr model)
+ }
+ 
+ 
++static int
++x86ModelCopySignatures(virCPUx86ModelPtr dst,
++                       virCPUx86ModelPtr src)
++{
++    dst->signature = src->signature;
++
++    return 0;
++}
++
++
+ static virCPUx86ModelPtr
+ x86ModelCopy(virCPUx86ModelPtr model)
+ {
+@@ -984,13 +994,13 @@ x86ModelCopy(virCPUx86ModelPtr model)
+ 
+     if (VIR_ALLOC(copy) < 0 ||
+         VIR_STRDUP(copy->name, model->name) < 0 ||
++        x86ModelCopySignatures(copy, model) < 0 ||
+         x86DataCopy(&copy->data, &model->data) < 0) {
+         x86ModelFree(copy);
+         return NULL;
+     }
+ 
+     copy->vendor = model->vendor;
+-    copy->signature = model->signature;
+ 
+     return copy;
+ }
+@@ -1176,8 +1186,8 @@ x86ModelParseAncestor(virCPUx86ModelPtr model,
+     }
+ 
+     model->vendor = ancestor->vendor;
+-    model->signature = ancestor->signature;
+-    if (x86DataCopy(&model->data, &ancestor->data) < 0)
++    if (x86ModelCopySignatures(model, ancestor) < 0 ||
++        x86DataCopy(&model->data, &ancestor->data) < 0)
+         return -1;
+ 
+     return 0;
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-cpu_x86-Allow-multiple-signatures-for-a-CPU-model.patch b/SOURCES/libvirt-cpu_x86-Allow-multiple-signatures-for-a-CPU-model.patch
new file mode 100644
index 0000000..faa8177
--- /dev/null
+++ b/SOURCES/libvirt-cpu_x86-Allow-multiple-signatures-for-a-CPU-model.patch
@@ -0,0 +1,114 @@
+From 5196a4b5fad475a8489faa9b5542536a941bd9da Mon Sep 17 00:00:00 2001
+Message-Id: <5196a4b5fad475a8489faa9b5542536a941bd9da@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:25:01 +0200
+Subject: [PATCH] cpu_x86: Allow multiple signatures for a CPU model
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+CPU signatures in the cpu_map serve as a hint for CPUID to CPU model
+matching algorithm. If the CPU signatures matches any CPU model in the
+cpu_map, this model will be the preferred one.
+
+This works out well and solved several mismatches, but in real world
+CPUs which should match a single CPU model may be produced with several
+different signatures. For example, low voltage Broadwell CPUs for
+laptops and Broadwell CPUs for servers differ in CPU model numbers while
+we should detect them all as Broadwell CPU model.
+
+This patch adds support for storing several signatures for a single CPU
+model to make this hint useful for more CPUs. Later commits will provide
+additional signatures for existing CPU models, which will correct some
+results in our CPU test suite.
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit dfeb3e598438a891a05487c34e6723d1d3ed9256)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1686895
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <393649e6301769c297f2d09bcb88d6200882eb9d.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/cpu/cpu_x86.c | 31 +++++++++++++++++++++----------
+ 1 file changed, 21 insertions(+), 10 deletions(-)
+
+diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
+index f8b8d8a96b..7bd8119c23 100644
+--- a/src/cpu/cpu_x86.c
++++ b/src/cpu/cpu_x86.c
+@@ -1204,22 +1204,32 @@ x86ModelParseAncestor(virCPUx86ModelPtr model,
+ 
+ 
+ static int
+-x86ModelParseSignature(virCPUx86ModelPtr model,
+-                       xmlXPathContextPtr ctxt)
++x86ModelParseSignatures(virCPUx86ModelPtr model,
++                        xmlXPathContextPtr ctxt)
+ {
++    VIR_AUTOFREE(xmlNodePtr *) nodes = NULL;
++    xmlNodePtr root = ctxt->node;
++    size_t i;
++    int n;
++
++    if ((n = virXPathNodeSet("./signature", ctxt, &nodes)) <= 0)
++        return n;
++
+     /* Remove inherited signatures. */
+     VIR_FREE(model->signatures);
+ 
+-    if (virXPathBoolean("boolean(./signature)", ctxt)) {
++    model->nsignatures = n;
++    if (VIR_ALLOC_N(model->signatures, n) < 0)
++       return -1;
++
++    for (i = 0; i < n; i++) {
+         unsigned int sigFamily = 0;
+         unsigned int sigModel = 0;
+         int rc;
+ 
+-        model->nsignatures = 1;
+-        if (VIR_ALLOC_N(model->signatures, 1) < 0)
+-            return -1;
++        ctxt->node = nodes[i];
+ 
+-        rc = virXPathUInt("string(./signature/@family)", ctxt, &sigFamily);
++        rc = virXPathUInt("string(@family)", ctxt, &sigFamily);
+         if (rc < 0 || sigFamily == 0) {
+             virReportError(VIR_ERR_INTERNAL_ERROR,
+                            _("Invalid CPU signature family in model %s"),
+@@ -1227,7 +1237,7 @@ x86ModelParseSignature(virCPUx86ModelPtr model,
+             return -1;
+         }
+ 
+-        rc = virXPathUInt("string(./signature/@model)", ctxt, &sigModel);
++        rc = virXPathUInt("string(@model)", ctxt, &sigModel);
+         if (rc < 0 || sigModel == 0) {
+             virReportError(VIR_ERR_INTERNAL_ERROR,
+                            _("Invalid CPU signature model in model %s"),
+@@ -1235,9 +1245,10 @@ x86ModelParseSignature(virCPUx86ModelPtr model,
+             return -1;
+         }
+ 
+-        model->signatures[0] = x86MakeSignature(sigFamily, sigModel, 0);
++        model->signatures[i] = x86MakeSignature(sigFamily, sigModel, 0);
+     }
+ 
++    ctxt->node = root;
+     return 0;
+ }
+ 
+@@ -1334,7 +1345,7 @@ x86ModelParse(xmlXPathContextPtr ctxt,
+     if (x86ModelParseAncestor(model, ctxt, map) < 0)
+         goto cleanup;
+ 
+-    if (x86ModelParseSignature(model, ctxt) < 0)
++    if (x86ModelParseSignatures(model, ctxt) < 0)
+         goto cleanup;
+ 
+     if (x86ModelParseVendor(model, ctxt, map) < 0)
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-cpu_x86-Do-not-cache-microcode-version.patch b/SOURCES/libvirt-cpu_x86-Do-not-cache-microcode-version.patch
index 38db4a7..d6ba3b3 100644
--- a/SOURCES/libvirt-cpu_x86-Do-not-cache-microcode-version.patch
+++ b/SOURCES/libvirt-cpu_x86-Do-not-cache-microcode-version.patch
@@ -1,5 +1,5 @@
-From eb1ac28530d9fe608ada1a3b44ac757c2b4ae020 Mon Sep 17 00:00:00 2001
-Message-Id: <eb1ac28530d9fe608ada1a3b44ac757c2b4ae020@dist-git>
+From f574d83a57b54248bc1f1c7fd3b25894d579c8e3 Mon Sep 17 00:00:00 2001
+Message-Id: <f574d83a57b54248bc1f1c7fd3b25894d579c8e3@dist-git>
 From: Jiri Denemark <jdenemar@redhat.com>
 Date: Fri, 5 Apr 2019 11:33:32 +0200
 Subject: [PATCH] cpu_x86: Do not cache microcode version
@@ -18,7 +18,7 @@ Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
 Reviewed-by: Ján Tomko <jtomko@redhat.com>
 (cherry picked from commit be46f613261d3b655a1f15afd635087e68a9c39b)
 
-CVE-2018-11091, CVE-2018-12126, CVE-2018-12127, CVE-2018-12130
+CVE-2018-12126, CVE-2018-12127, CVE-2018-12130, CVE-2019-11091
 
 Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
 ---
diff --git a/SOURCES/libvirt-cpu_x86-Fix-memory-leak-virCPUx86GetHost.patch b/SOURCES/libvirt-cpu_x86-Fix-memory-leak-virCPUx86GetHost.patch
new file mode 100644
index 0000000..c8111f6
--- /dev/null
+++ b/SOURCES/libvirt-cpu_x86-Fix-memory-leak-virCPUx86GetHost.patch
@@ -0,0 +1,43 @@
+From b63d4e603a3617bd0d68d8897afb5e1c13a75165 Mon Sep 17 00:00:00 2001
+Message-Id: <b63d4e603a3617bd0d68d8897afb5e1c13a75165@dist-git>
+From: John Ferlan <jferlan@redhat.com>
+Date: Tue, 2 Jul 2019 12:57:21 +0200
+Subject: [PATCH] cpu_x86: Fix memory leak - virCPUx86GetHost
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Commit 56b254dcc called virCPUx86DataAdd, but returned -1 directly
+without calling the virCPUx86DataFree.
+
+Found by Coverity.
+
+Signed-off-by: John Ferlan <jferlan@redhat.com>
+Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
+(cherry picked from commit 5acb4eede23bcd5bc75193ea21542e0fb04b6e45)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1697627
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <96135f1275b80b251c83ca947333b1969380ef7b.1562064911.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/cpu/cpu_x86.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
+index 0a520f07ff..9104bdbf1e 100644
+--- a/src/cpu/cpu_x86.c
++++ b/src/cpu/cpu_x86.c
+@@ -2789,7 +2789,7 @@ virCPUx86GetHost(virCPUDefPtr cpu,
+             };
+ 
+             if (virCPUx86DataAdd(cpuData, &item) < 0)
+-                return -1;
++                goto cleanup;
+         }
+     }
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-cpu_x86-Fix-placement-of-CheckFeature-functions.patch b/SOURCES/libvirt-cpu_x86-Fix-placement-of-CheckFeature-functions.patch
new file mode 100644
index 0000000..b99049d
--- /dev/null
+++ b/SOURCES/libvirt-cpu_x86-Fix-placement-of-CheckFeature-functions.patch
@@ -0,0 +1,119 @@
+From e0ea2a8c9fb17cbb0b48cb8a1548152e962b126b Mon Sep 17 00:00:00 2001
+Message-Id: <e0ea2a8c9fb17cbb0b48cb8a1548152e962b126b@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:25:45 +0200
+Subject: [PATCH] cpu_x86: Fix placement of *CheckFeature functions
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Commit 0a97486e09 moved them outside #ifdef, but after virCPUx86GetHost,
+which will start calling them in the following patch.
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+(cherry picked from commit 32f577ab10aefda6c4666abd07814c5c39f57788)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1697627
+
+Conflicts:
+	src/cpu/cpu_x86.c
+            - only the last patch moving these functions is backported
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <7bb25ee8ca5b743934fa2ae8249f5715a47aba06.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/cpu/cpu_x86.c | 70 +++++++++++++++++++++++------------------------
+ 1 file changed, 35 insertions(+), 35 deletions(-)
+
+diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
+index fdc2974a0d..3c1bd623db 100644
+--- a/src/cpu/cpu_x86.c
++++ b/src/cpu/cpu_x86.c
+@@ -2377,6 +2377,41 @@ x86Encode(virArch arch,
+ }
+ 
+ 
++static int
++virCPUx86CheckFeature(const virCPUDef *cpu,
++                      const char *name)
++{
++    int ret = -1;
++    virCPUx86MapPtr map;
++    virCPUx86ModelPtr model = NULL;
++
++    if (!(map = virCPUx86GetMap()))
++        return -1;
++
++    if (!(model = x86ModelFromCPU(cpu, map, -1)))
++        goto cleanup;
++
++    ret = x86FeatureInData(name, &model->data, map);
++
++ cleanup:
++    x86ModelFree(model);
++    return ret;
++}
++
++
++static int
++virCPUx86DataCheckFeature(const virCPUData *data,
++                          const char *name)
++{
++    virCPUx86MapPtr map;
++
++    if (!(map = virCPUx86GetMap()))
++        return -1;
++
++    return x86FeatureInData(name, &data->data.x86, map);
++}
++
++
+ #if defined(__i386__) || defined(__x86_64__)
+ static inline void
+ cpuidCall(virCPUx86CPUID *cpuid)
+@@ -2706,41 +2741,6 @@ cpuidSet(uint32_t base, virCPUDataPtr data)
+ }
+ 
+ 
+-static int
+-virCPUx86CheckFeature(const virCPUDef *cpu,
+-                      const char *name)
+-{
+-    int ret = -1;
+-    virCPUx86MapPtr map;
+-    virCPUx86ModelPtr model = NULL;
+-
+-    if (!(map = virCPUx86GetMap()))
+-        return -1;
+-
+-    if (!(model = x86ModelFromCPU(cpu, map, -1)))
+-        goto cleanup;
+-
+-    ret = x86FeatureInData(name, &model->data, map);
+-
+- cleanup:
+-    x86ModelFree(model);
+-    return ret;
+-}
+-
+-
+-static int
+-virCPUx86DataCheckFeature(const virCPUData *data,
+-                          const char *name)
+-{
+-    virCPUx86MapPtr map;
+-
+-    if (!(map = virCPUx86GetMap()))
+-        return -1;
+-
+-    return x86FeatureInData(name, &data->data.x86, map);
+-}
+-
+-
+ static int
+ virCPUx86GetHost(virCPUDefPtr cpu,
+                  virDomainCapsCPUModelsPtr models)
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-cpu_x86-Introduce-virCPUx86DataCmp.patch b/SOURCES/libvirt-cpu_x86-Introduce-virCPUx86DataCmp.patch
new file mode 100644
index 0000000..1138e87
--- /dev/null
+++ b/SOURCES/libvirt-cpu_x86-Introduce-virCPUx86DataCmp.patch
@@ -0,0 +1,60 @@
+From 5354c931f98f2d95d131bf4d490d0e5e057157fe Mon Sep 17 00:00:00 2001
+Message-Id: <5354c931f98f2d95d131bf4d490d0e5e057157fe@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:25:32 +0200
+Subject: [PATCH] cpu_x86: Introduce virCPUx86DataCmp
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+virCPUx86DataSorter already compares two virCPUx86DataItem structs.
+Let's add a tiny wrapper around it called virCPUx86DataCmp and use it
+instead of open coded comparisons.
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit 559ccd7815056af23de24b7a01e8f644d97b6a92)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1697627
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <9623fdd20059ec6abc7f09c5e7f1e13927c56944.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/cpu/cpu_x86.c | 13 ++++++++++---
+ 1 file changed, 10 insertions(+), 3 deletions(-)
+
+diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
+index 0582be63e2..5a09033d2a 100644
+--- a/src/cpu/cpu_x86.c
++++ b/src/cpu/cpu_x86.c
+@@ -304,6 +304,13 @@ virCPUx86DataSorter(const void *a, const void *b)
+     return 0;
+ }
+ 
++static int
++virCPUx86DataItemCmp(const virCPUx86DataItem *item1,
++                     const virCPUx86DataItem *item2)
++{
++    return virCPUx86DataSorter(item1, item2);
++}
++
+ 
+ /* skips all zero CPUID leaves */
+ static virCPUx86DataItemPtr
+@@ -332,9 +339,9 @@ virCPUx86DataGet(const virCPUx86Data *data,
+     size_t i;
+ 
+     for (i = 0; i < data->len; i++) {
+-        if (data->items[i].cpuid.eax_in == item->cpuid.eax_in &&
+-            data->items[i].cpuid.ecx_in == item->cpuid.ecx_in)
+-            return data->items + i;
++        virCPUx86DataItemPtr di = data->items + i;
++        if (virCPUx86DataItemCmp(di, item) == 0)
++            return di;
+     }
+ 
+     return NULL;
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-cpu_x86-Introduce-virCPUx86DataItem-container-struct.patch b/SOURCES/libvirt-cpu_x86-Introduce-virCPUx86DataItem-container-struct.patch
new file mode 100644
index 0000000..6bdf1ff
--- /dev/null
+++ b/SOURCES/libvirt-cpu_x86-Introduce-virCPUx86DataItem-container-struct.patch
@@ -0,0 +1,850 @@
+From 891f6c594088c787c92279af08ba0ab037492bdd Mon Sep 17 00:00:00 2001
+Message-Id: <891f6c594088c787c92279af08ba0ab037492bdd@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:25:22 +0200
+Subject: [PATCH] cpu_x86: Introduce virCPUx86DataItem container struct
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The following patches introduce CPU features read from MSR in addition
+to those queried via CPUID instruction. Let's introduce a container
+struct which will be able to describe either feature type.
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit 3673269e3aa22566f87e06a2b10dbc3b20110f84)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1697627
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <161419b9968304180f18b33e6dc29ba70d9174d0.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/cpu/cpu_x86.c              | 312 ++++++++++++++++++---------------
+ src/cpu/cpu_x86.h              |   2 +-
+ src/cpu/cpu_x86_data.h         |   9 +-
+ src/libxl/libxl_capabilities.c |   8 +-
+ src/qemu/qemu_monitor_json.c   |   6 +-
+ 5 files changed, 183 insertions(+), 154 deletions(-)
+
+diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
+index 98e8d608d6..2e953eaa12 100644
+--- a/src/cpu/cpu_x86.c
++++ b/src/cpu/cpu_x86.c
+@@ -49,7 +49,7 @@ typedef struct _virCPUx86Vendor virCPUx86Vendor;
+ typedef virCPUx86Vendor *virCPUx86VendorPtr;
+ struct _virCPUx86Vendor {
+     char *name;
+-    virCPUx86CPUID cpuid;
++    virCPUx86DataItem cpuid;
+ };
+ 
+ typedef struct _virCPUx86Feature virCPUx86Feature;
+@@ -61,17 +61,19 @@ struct _virCPUx86Feature {
+ };
+ 
+ 
++#define CPUID(...) { .cpuid = {__VA_ARGS__} }
++
+ #define KVM_FEATURE_DEF(Name, Eax_in, Eax) \
+-    static virCPUx86CPUID Name ## _cpuid[] = { \
+-        { .eax_in = Eax_in, .eax = Eax }, \
++    static virCPUx86DataItem Name ## _data[] = { \
++        CPUID(.eax_in = Eax_in, .eax = Eax), \
+     }
+ 
+ #define KVM_FEATURE(Name) \
+     { \
+         .name = (char *) Name, \
+         .data = { \
+-            .len = ARRAY_CARDINALITY(Name ## _cpuid), \
+-            .data = Name ## _cpuid \
++            .len = ARRAY_CARDINALITY(Name ## _data), \
++            .items = Name ## _data, \
+         } \
+     }
+ 
+@@ -286,17 +288,17 @@ x86FeatureFindInternal(const char *name)
+ static int
+ virCPUx86CPUIDSorter(const void *a, const void *b)
+ {
+-    virCPUx86CPUID *da = (virCPUx86CPUID *) a;
+-    virCPUx86CPUID *db = (virCPUx86CPUID *) b;
++    virCPUx86DataItemPtr da = (virCPUx86DataItemPtr) a;
++    virCPUx86DataItemPtr db = (virCPUx86DataItemPtr) b;
+ 
+-    if (da->eax_in > db->eax_in)
++    if (da->cpuid.eax_in > db->cpuid.eax_in)
+         return 1;
+-    else if (da->eax_in < db->eax_in)
++    else if (da->cpuid.eax_in < db->cpuid.eax_in)
+         return -1;
+ 
+-    if (da->ecx_in > db->ecx_in)
++    if (da->cpuid.ecx_in > db->cpuid.ecx_in)
+         return 1;
+-    else if (da->ecx_in < db->ecx_in)
++    else if (da->cpuid.ecx_in < db->cpuid.ecx_in)
+         return -1;
+ 
+     return 0;
+@@ -304,7 +306,7 @@ virCPUx86CPUIDSorter(const void *a, const void *b)
+ 
+ 
+ /* skips all zero CPUID leaves */
+-static virCPUx86CPUID *
++static virCPUx86DataItemPtr
+ x86DataCpuidNext(virCPUx86DataIteratorPtr iterator)
+ {
+     const virCPUx86Data *data = iterator->data;
+@@ -313,24 +315,26 @@ x86DataCpuidNext(virCPUx86DataIteratorPtr iterator)
+         return NULL;
+ 
+     while (++iterator->pos < data->len) {
+-        if (!x86cpuidMatch(data->data + iterator->pos, &cpuidNull))
+-            return data->data + iterator->pos;
++        virCPUx86DataItemPtr item = data->items + iterator->pos;
++
++        if (!x86cpuidMatch(&item->cpuid, &cpuidNull))
++            return item;
+     }
+ 
+     return NULL;
+ }
+ 
+ 
+-static virCPUx86CPUID *
++static virCPUx86DataItemPtr
+ x86DataCpuid(const virCPUx86Data *data,
+-             const virCPUx86CPUID *cpuid)
++             const virCPUx86DataItem *cpuid)
+ {
+     size_t i;
+ 
+     for (i = 0; i < data->len; i++) {
+-        if (data->data[i].eax_in == cpuid->eax_in &&
+-            data->data[i].ecx_in == cpuid->ecx_in)
+-            return data->data + i;
++        if (data->items[i].cpuid.eax_in == cpuid->cpuid.eax_in &&
++            data->items[i].cpuid.ecx_in == cpuid->cpuid.ecx_in)
++            return data->items + i;
+     }
+ 
+     return NULL;
+@@ -342,7 +346,7 @@ virCPUx86DataClear(virCPUx86Data *data)
+     if (!data)
+         return;
+ 
+-    VIR_FREE(data->data);
++    VIR_FREE(data->items);
+ }
+ 
+ 
+@@ -362,12 +366,12 @@ x86DataCopy(virCPUx86Data *dst, const virCPUx86Data *src)
+ {
+     size_t i;
+ 
+-    if (VIR_ALLOC_N(dst->data, src->len) < 0)
++    if (VIR_ALLOC_N(dst->items, src->len) < 0)
+         return -1;
+ 
+     dst->len = src->len;
+     for (i = 0; i < src->len; i++)
+-        dst->data[i] = src->data[i];
++        dst->items[i] = src->items[i];
+ 
+     return 0;
+ }
+@@ -375,19 +379,19 @@ x86DataCopy(virCPUx86Data *dst, const virCPUx86Data *src)
+ 
+ static int
+ virCPUx86DataAddCPUIDInt(virCPUx86Data *data,
+-                         const virCPUx86CPUID *cpuid)
++                         const virCPUx86DataItem *cpuid)
+ {
+-    virCPUx86CPUID *existing;
++    virCPUx86DataItemPtr existing;
+ 
+     if ((existing = x86DataCpuid(data, cpuid))) {
+-        x86cpuidSetBits(existing, cpuid);
++        x86cpuidSetBits(&existing->cpuid, &cpuid->cpuid);
+     } else {
+-        if (VIR_APPEND_ELEMENT_COPY(data->data, data->len,
+-                                    *((virCPUx86CPUID *)cpuid)) < 0)
++        if (VIR_APPEND_ELEMENT_COPY(data->items, data->len,
++                                    *((virCPUx86DataItemPtr)cpuid)) < 0)
+             return -1;
+ 
+-        qsort(data->data, data->len,
+-              sizeof(virCPUx86CPUID), virCPUx86CPUIDSorter);
++        qsort(data->items, data->len,
++              sizeof(virCPUx86DataItem), virCPUx86CPUIDSorter);
+     }
+ 
+     return 0;
+@@ -399,14 +403,14 @@ x86DataAdd(virCPUx86Data *data1,
+            const virCPUx86Data *data2)
+ {
+     virCPUx86DataIterator iter = virCPUx86DataIteratorInit(data2);
+-    virCPUx86CPUID *cpuid1;
+-    virCPUx86CPUID *cpuid2;
++    virCPUx86DataItemPtr cpuid1;
++    virCPUx86DataItemPtr cpuid2;
+ 
+     while ((cpuid2 = x86DataCpuidNext(&iter))) {
+         cpuid1 = x86DataCpuid(data1, cpuid2);
+ 
+         if (cpuid1) {
+-            x86cpuidSetBits(cpuid1, cpuid2);
++            x86cpuidSetBits(&cpuid1->cpuid, &cpuid2->cpuid);
+         } else {
+             if (virCPUx86DataAddCPUIDInt(data1, cpuid2) < 0)
+                 return -1;
+@@ -422,12 +426,12 @@ x86DataSubtract(virCPUx86Data *data1,
+                 const virCPUx86Data *data2)
+ {
+     virCPUx86DataIterator iter = virCPUx86DataIteratorInit(data1);
+-    virCPUx86CPUID *cpuid1;
+-    virCPUx86CPUID *cpuid2;
++    virCPUx86DataItemPtr cpuid1;
++    virCPUx86DataItemPtr cpuid2;
+ 
+     while ((cpuid1 = x86DataCpuidNext(&iter))) {
+-        cpuid2 = x86DataCpuid(data2, cpuid1);
+-        x86cpuidClearBits(cpuid1, cpuid2);
++        if ((cpuid2 = x86DataCpuid(data2, cpuid1)))
++            x86cpuidClearBits(&cpuid1->cpuid, &cpuid2->cpuid);
+     }
+ }
+ 
+@@ -437,15 +441,15 @@ x86DataIntersect(virCPUx86Data *data1,
+                  const virCPUx86Data *data2)
+ {
+     virCPUx86DataIterator iter = virCPUx86DataIteratorInit(data1);
+-    virCPUx86CPUID *cpuid1;
+-    virCPUx86CPUID *cpuid2;
++    virCPUx86DataItemPtr cpuid1;
++    virCPUx86DataItemPtr cpuid2;
+ 
+     while ((cpuid1 = x86DataCpuidNext(&iter))) {
+         cpuid2 = x86DataCpuid(data2, cpuid1);
+         if (cpuid2)
+-            x86cpuidAndBits(cpuid1, cpuid2);
++            x86cpuidAndBits(&cpuid1->cpuid, &cpuid2->cpuid);
+         else
+-            x86cpuidClearBits(cpuid1, cpuid1);
++            x86cpuidClearBits(&cpuid1->cpuid, &cpuid1->cpuid);
+     }
+ }
+ 
+@@ -465,12 +469,12 @@ x86DataIsSubset(const virCPUx86Data *data,
+ {
+ 
+     virCPUx86DataIterator iter = virCPUx86DataIteratorInit((virCPUx86Data *)subset);
+-    const virCPUx86CPUID *cpuid;
+-    const virCPUx86CPUID *cpuidSubset;
++    const virCPUx86DataItem *cpuid;
++    const virCPUx86DataItem *cpuidSubset;
+ 
+     while ((cpuidSubset = x86DataCpuidNext(&iter))) {
+         if (!(cpuid = x86DataCpuid(data, cpuidSubset)) ||
+-            !x86cpuidMatchMasked(cpuid, cpuidSubset))
++            !x86cpuidMatchMasked(&cpuid->cpuid, &cpuidSubset->cpuid))
+             return false;
+     }
+ 
+@@ -505,14 +509,14 @@ static virCPUx86VendorPtr
+ x86DataToVendor(const virCPUx86Data *data,
+                 virCPUx86MapPtr map)
+ {
+-    virCPUx86CPUID *cpuid;
++    virCPUx86DataItemPtr cpuid;
+     size_t i;
+ 
+     for (i = 0; i < map->nvendors; i++) {
+         virCPUx86VendorPtr vendor = map->vendors[i];
+         if ((cpuid = x86DataCpuid(data, &vendor->cpuid)) &&
+-            x86cpuidMatchMasked(cpuid, &vendor->cpuid)) {
+-            x86cpuidClearBits(cpuid, &vendor->cpuid);
++            x86cpuidMatchMasked(&cpuid->cpuid, &vendor->cpuid.cpuid)) {
++            x86cpuidClearBits(&cpuid->cpuid, &vendor->cpuid.cpuid);
+             return vendor;
+         }
+     }
+@@ -523,8 +527,10 @@ x86DataToVendor(const virCPUx86Data *data,
+ 
+ static int
+ virCPUx86VendorToCPUID(const char *vendor,
+-                       virCPUx86CPUID *cpuid)
++                       virCPUx86DataItemPtr data)
+ {
++    virCPUx86CPUIDPtr cpuid = &data->cpuid;
++
+     if (strlen(vendor) != VENDOR_STRING_LENGTH) {
+         virReportError(VIR_ERR_INTERNAL_ERROR,
+                        _("Invalid CPU vendor string '%s'"), vendor);
+@@ -597,14 +603,16 @@ x86DataToSignatureFull(const virCPUx86Data *data,
+                        unsigned int *model,
+                        unsigned int *stepping)
+ {
+-    virCPUx86CPUID leaf1 = { .eax_in = 0x1 };
+-    virCPUx86CPUID *cpuid;
++    virCPUx86DataItem leaf1 = CPUID(.eax_in = 0x1);
++    virCPUx86DataItemPtr item;
++    virCPUx86CPUIDPtr cpuid;
+ 
+     *family = *model = *stepping = 0;
+ 
+-    if (!(cpuid = x86DataCpuid(data, &leaf1)))
++    if (!(item = x86DataCpuid(data, &leaf1)))
+         return;
+ 
++    cpuid = &item->cpuid;
+     *family = ((cpuid->eax >> 20) & 0xff) + ((cpuid->eax >> 8) & 0xf);
+     *model = ((cpuid->eax >> 12) & 0xf0) + ((cpuid->eax >> 4) & 0xf);
+     *stepping = cpuid->eax & 0xf;
+@@ -617,13 +625,13 @@ x86DataToSignatureFull(const virCPUx86Data *data,
+ static uint32_t
+ x86DataToSignature(const virCPUx86Data *data)
+ {
+-    virCPUx86CPUID leaf1 = { .eax_in = 0x1 };
+-    virCPUx86CPUID *cpuid;
++    virCPUx86DataItem leaf1 = CPUID(.eax_in = 0x1);
++    virCPUx86DataItemPtr cpuid;
+ 
+     if (!(cpuid = x86DataCpuid(data, &leaf1)))
+         return 0;
+ 
+-    return cpuid->eax & SIGNATURE_MASK;
++    return cpuid->cpuid.eax & SIGNATURE_MASK;
+ }
+ 
+ 
+@@ -631,7 +639,7 @@ static int
+ x86DataAddSignature(virCPUx86Data *data,
+                     uint32_t signature)
+ {
+-    virCPUx86CPUID cpuid = { .eax_in = 0x1, .eax = signature };
++    virCPUx86DataItem cpuid = CPUID(.eax_in = 0x1, .eax = signature);
+ 
+     return virCPUx86DataAddCPUIDInt(data, &cpuid);
+ }
+@@ -856,13 +864,14 @@ x86FeatureNames(virCPUx86MapPtr map,
+ 
+ static int
+ x86ParseCPUID(xmlXPathContextPtr ctxt,
+-              virCPUx86CPUID *cpuid)
++              virCPUx86DataItemPtr item)
+ {
++    virCPUx86CPUIDPtr cpuid;
+     unsigned long eax_in, ecx_in;
+     unsigned long eax, ebx, ecx, edx;
+     int ret_eax_in, ret_ecx_in, ret_eax, ret_ebx, ret_ecx, ret_edx;
+ 
+-    memset(cpuid, 0, sizeof(*cpuid));
++    memset(item, 0, sizeof(*item));
+ 
+     eax_in = ecx_in = 0;
+     eax = ebx = ecx = edx = 0;
+@@ -877,6 +886,7 @@ x86ParseCPUID(xmlXPathContextPtr ctxt,
+         ret_eax == -2 || ret_ebx == -2 || ret_ecx == -2 || ret_edx == -2)
+         return -1;
+ 
++    cpuid = &item->cpuid;
+     cpuid->eax_in = eax_in;
+     cpuid->ecx_in = ecx_in;
+     cpuid->eax = eax;
+@@ -895,7 +905,7 @@ x86FeatureParse(xmlXPathContextPtr ctxt,
+     virCPUx86MapPtr map = data;
+     xmlNodePtr *nodes = NULL;
+     virCPUx86FeaturePtr feature;
+-    virCPUx86CPUID cpuid;
++    virCPUx86DataItem cpuid;
+     size_t i;
+     int n;
+     char *str = NULL;
+@@ -1138,16 +1148,16 @@ x86ModelCompare(virCPUx86ModelPtr model1,
+     virCPUx86CompareResult result = EQUAL;
+     virCPUx86DataIterator iter1 = virCPUx86DataIteratorInit(&model1->data);
+     virCPUx86DataIterator iter2 = virCPUx86DataIteratorInit(&model2->data);
+-    virCPUx86CPUID *cpuid1;
+-    virCPUx86CPUID *cpuid2;
++    virCPUx86DataItemPtr cpuid1;
++    virCPUx86DataItemPtr cpuid2;
+ 
+     while ((cpuid1 = x86DataCpuidNext(&iter1))) {
+         virCPUx86CompareResult match = SUPERSET;
+ 
+         if ((cpuid2 = x86DataCpuid(&model2->data, cpuid1))) {
+-            if (x86cpuidMatch(cpuid1, cpuid2))
++            if (x86cpuidMatch(&cpuid1->cpuid, &cpuid2->cpuid))
+                 continue;
+-            else if (!x86cpuidMatchMasked(cpuid1, cpuid2))
++            else if (!x86cpuidMatchMasked(&cpuid1->cpuid, &cpuid2->cpuid))
+                 match = SUBSET;
+         }
+ 
+@@ -1161,9 +1171,9 @@ x86ModelCompare(virCPUx86ModelPtr model1,
+         virCPUx86CompareResult match = SUBSET;
+ 
+         if ((cpuid1 = x86DataCpuid(&model1->data, cpuid2))) {
+-            if (x86cpuidMatch(cpuid2, cpuid1))
++            if (x86cpuidMatch(&cpuid2->cpuid, &cpuid1->cpuid))
+                 continue;
+-            else if (!x86cpuidMatchMasked(cpuid2, cpuid1))
++            else if (!x86cpuidMatchMasked(&cpuid2->cpuid, &cpuid1->cpuid))
+                 match = SUPERSET;
+         }
+ 
+@@ -1447,11 +1457,12 @@ static char *
+ virCPUx86DataFormat(const virCPUData *data)
+ {
+     virCPUx86DataIterator iter = virCPUx86DataIteratorInit(&data->data.x86);
+-    virCPUx86CPUID *cpuid;
++    virCPUx86DataItemPtr item;
+     virBuffer buf = VIR_BUFFER_INITIALIZER;
+ 
+     virBufferAddLit(&buf, "<cpudata arch='x86'>\n");
+-    while ((cpuid = x86DataCpuidNext(&iter))) {
++    while ((item = x86DataCpuidNext(&iter))) {
++        virCPUx86CPUIDPtr cpuid = &item->cpuid;
+         virBufferAsprintf(&buf,
+                           "  <cpuid eax_in='0x%08x' ecx_in='0x%08x'"
+                           " eax='0x%08x' ebx='0x%08x'"
+@@ -1473,7 +1484,7 @@ virCPUx86DataParse(xmlXPathContextPtr ctxt)
+ {
+     xmlNodePtr *nodes = NULL;
+     virCPUDataPtr cpuData = NULL;
+-    virCPUx86CPUID cpuid;
++    virCPUx86DataItem cpuid;
+     size_t i;
+     int n;
+ 
+@@ -2059,7 +2070,7 @@ x86EncodePolicy(virCPUx86Data *data,
+ 
+     *data = model->data;
+     model->data.len = 0;
+-    model->data.data = NULL;
++    model->data.items = NULL;
+     x86ModelFree(model);
+ 
+     return 0;
+@@ -2213,17 +2224,18 @@ cpuidCall(virCPUx86CPUID *cpuid)
+  */
+ static int
+ cpuidSetLeaf4(virCPUDataPtr data,
+-              virCPUx86CPUID *subLeaf0)
++              virCPUx86DataItemPtr subLeaf0)
+ {
+-    virCPUx86CPUID cpuid = *subLeaf0;
++    virCPUx86DataItem item = *subLeaf0;
++    virCPUx86CPUIDPtr cpuid = &item.cpuid;
+ 
+     if (virCPUx86DataAddCPUID(data, subLeaf0) < 0)
+         return -1;
+ 
+-    while (cpuid.eax & 0x1f) {
+-        cpuid.ecx_in++;
+-        cpuidCall(&cpuid);
+-        if (virCPUx86DataAddCPUID(data, &cpuid) < 0)
++    while (cpuid->eax & 0x1f) {
++        cpuid->ecx_in++;
++        cpuidCall(cpuid);
++        if (virCPUx86DataAddCPUID(data, &item) < 0)
+             return -1;
+     }
+     return 0;
+@@ -2236,18 +2248,19 @@ cpuidSetLeaf4(virCPUDataPtr data,
+  */
+ static int
+ cpuidSetLeaf7(virCPUDataPtr data,
+-              virCPUx86CPUID *subLeaf0)
++              virCPUx86DataItemPtr subLeaf0)
+ {
+-    virCPUx86CPUID cpuid = { .eax_in = 0x7 };
++    virCPUx86DataItem item = CPUID(.eax_in = 0x7);
++    virCPUx86CPUIDPtr cpuid = &item.cpuid;
+     uint32_t sub;
+ 
+     if (virCPUx86DataAddCPUID(data, subLeaf0) < 0)
+         return -1;
+ 
+-    for (sub = 1; sub <= subLeaf0->eax; sub++) {
+-        cpuid.ecx_in = sub;
+-        cpuidCall(&cpuid);
+-        if (virCPUx86DataAddCPUID(data, &cpuid) < 0)
++    for (sub = 1; sub <= subLeaf0->cpuid.eax; sub++) {
++        cpuid->ecx_in = sub;
++        cpuidCall(cpuid);
++        if (virCPUx86DataAddCPUID(data, &item) < 0)
+             return -1;
+     }
+     return 0;
+@@ -2263,15 +2276,16 @@ cpuidSetLeaf7(virCPUDataPtr data,
+  */
+ static int
+ cpuidSetLeafB(virCPUDataPtr data,
+-              virCPUx86CPUID *subLeaf0)
++              virCPUx86DataItemPtr subLeaf0)
+ {
+-    virCPUx86CPUID cpuid = *subLeaf0;
++    virCPUx86DataItem item = *subLeaf0;
++    virCPUx86CPUIDPtr cpuid = &item.cpuid;
+ 
+-    while (cpuid.ecx & 0xff00) {
+-        if (virCPUx86DataAddCPUID(data, &cpuid) < 0)
++    while (cpuid->ecx & 0xff00) {
++        if (virCPUx86DataAddCPUID(data, &item) < 0)
+             return -1;
+-        cpuid.ecx_in++;
+-        cpuidCall(&cpuid);
++        cpuid->ecx_in++;
++        cpuidCall(cpuid);
+     }
+     return 0;
+ }
+@@ -2287,9 +2301,10 @@ cpuidSetLeafB(virCPUDataPtr data,
+  */
+ static int
+ cpuidSetLeafD(virCPUDataPtr data,
+-              virCPUx86CPUID *subLeaf0)
++              virCPUx86DataItemPtr subLeaf0)
+ {
+-    virCPUx86CPUID cpuid = { .eax_in = 0xd };
++    virCPUx86DataItem item = CPUID(.eax_in = 0xd);
++    virCPUx86CPUIDPtr cpuid = &item.cpuid;
+     virCPUx86CPUID sub0;
+     virCPUx86CPUID sub1;
+     uint32_t sub;
+@@ -2297,13 +2312,13 @@ cpuidSetLeafD(virCPUDataPtr data,
+     if (virCPUx86DataAddCPUID(data, subLeaf0) < 0)
+         return -1;
+ 
+-    cpuid.ecx_in = 1;
+-    cpuidCall(&cpuid);
+-    if (virCPUx86DataAddCPUID(data, &cpuid) < 0)
++    cpuid->ecx_in = 1;
++    cpuidCall(cpuid);
++    if (virCPUx86DataAddCPUID(data, &item) < 0)
+         return -1;
+ 
+-    sub0 = *subLeaf0;
+-    sub1 = cpuid;
++    sub0 = subLeaf0->cpuid;
++    sub1 = *cpuid;
+     for (sub = 2; sub < 64; sub++) {
+         if (sub < 32 &&
+             !(sub0.eax & (1 << sub)) &&
+@@ -2314,9 +2329,9 @@ cpuidSetLeafD(virCPUDataPtr data,
+             !(sub1.edx & (1 << (sub - 32))))
+             continue;
+ 
+-        cpuid.ecx_in = sub;
+-        cpuidCall(&cpuid);
+-        if (virCPUx86DataAddCPUID(data, &cpuid) < 0)
++        cpuid->ecx_in = sub;
++        cpuidCall(cpuid);
++        if (virCPUx86DataAddCPUID(data, &item) < 0)
+             return -1;
+     }
+     return 0;
+@@ -2334,10 +2349,11 @@ cpuidSetLeafD(virCPUDataPtr data,
+  */
+ static int
+ cpuidSetLeafResID(virCPUDataPtr data,
+-                  virCPUx86CPUID *subLeaf0,
++                  virCPUx86DataItemPtr subLeaf0,
+                   uint32_t res)
+ {
+-    virCPUx86CPUID cpuid = { .eax_in = subLeaf0->eax_in };
++    virCPUx86DataItem item = CPUID(.eax_in = subLeaf0->cpuid.eax_in);
++    virCPUx86CPUIDPtr cpuid = &item.cpuid;
+     uint32_t sub;
+ 
+     if (virCPUx86DataAddCPUID(data, subLeaf0) < 0)
+@@ -2346,9 +2362,9 @@ cpuidSetLeafResID(virCPUDataPtr data,
+     for (sub = 1; sub < 32; sub++) {
+         if (!(res & (1 << sub)))
+             continue;
+-        cpuid.ecx_in = sub;
+-        cpuidCall(&cpuid);
+-        if (virCPUx86DataAddCPUID(data, &cpuid) < 0)
++        cpuid->ecx_in = sub;
++        cpuidCall(cpuid);
++        if (virCPUx86DataAddCPUID(data, &item) < 0)
+             return -1;
+     }
+     return 0;
+@@ -2362,31 +2378,32 @@ cpuidSetLeafResID(virCPUDataPtr data,
+  */
+ static int
+ cpuidSetLeaf12(virCPUDataPtr data,
+-               virCPUx86CPUID *subLeaf0)
++               virCPUx86DataItemPtr subLeaf0)
+ {
+-    virCPUx86CPUID cpuid = { .eax_in = 0x7 };
+-    virCPUx86CPUID *cpuid7;
++    virCPUx86DataItem item = CPUID(.eax_in = 0x7);
++    virCPUx86CPUIDPtr cpuid = &item.cpuid;
++    virCPUx86DataItemPtr cpuid7;
+ 
+-    if (!(cpuid7 = x86DataCpuid(&data->data.x86, &cpuid)) ||
+-        !(cpuid7->ebx & (1 << 2)))
++    if (!(cpuid7 = x86DataCpuid(&data->data.x86, &item)) ||
++        !(cpuid7->cpuid.ebx & (1 << 2)))
+         return 0;
+ 
+     if (virCPUx86DataAddCPUID(data, subLeaf0) < 0)
+         return -1;
+ 
+-    cpuid.eax_in = 0x12;
+-    cpuid.ecx_in = 1;
+-    cpuidCall(&cpuid);
+-    if (virCPUx86DataAddCPUID(data, &cpuid) < 0)
++    cpuid->eax_in = 0x12;
++    cpuid->ecx_in = 1;
++    cpuidCall(cpuid);
++    if (virCPUx86DataAddCPUID(data, &item) < 0)
+         return -1;
+ 
+-    cpuid.ecx_in = 2;
+-    cpuidCall(&cpuid);
+-    while (cpuid.eax & 0xf) {
+-        if (virCPUx86DataAddCPUID(data, &cpuid) < 0)
++    cpuid->ecx_in = 2;
++    cpuidCall(cpuid);
++    while (cpuid->eax & 0xf) {
++        if (virCPUx86DataAddCPUID(data, &item) < 0)
+             return -1;
+-        cpuid.ecx_in++;
+-        cpuidCall(&cpuid);
++        cpuid->ecx_in++;
++        cpuidCall(cpuid);
+     }
+     return 0;
+ }
+@@ -2398,18 +2415,19 @@ cpuidSetLeaf12(virCPUDataPtr data,
+  */
+ static int
+ cpuidSetLeaf14(virCPUDataPtr data,
+-               virCPUx86CPUID *subLeaf0)
++               virCPUx86DataItemPtr subLeaf0)
+ {
+-    virCPUx86CPUID cpuid = { .eax_in = 0x14 };
++    virCPUx86DataItem item = CPUID(.eax_in = 0x14);
++    virCPUx86CPUIDPtr cpuid = &item.cpuid;
+     uint32_t sub;
+ 
+     if (virCPUx86DataAddCPUID(data, subLeaf0) < 0)
+         return -1;
+ 
+-    for (sub = 1; sub <= subLeaf0->eax; sub++) {
+-        cpuid.ecx_in = sub;
+-        cpuidCall(&cpuid);
+-        if (virCPUx86DataAddCPUID(data, &cpuid) < 0)
++    for (sub = 1; sub <= subLeaf0->cpuid.eax; sub++) {
++        cpuid->ecx_in = sub;
++        cpuidCall(cpuid);
++        if (virCPUx86DataAddCPUID(data, &item) < 0)
+             return -1;
+     }
+     return 0;
+@@ -2423,21 +2441,22 @@ cpuidSetLeaf14(virCPUDataPtr data,
+  */
+ static int
+ cpuidSetLeaf17(virCPUDataPtr data,
+-               virCPUx86CPUID *subLeaf0)
++               virCPUx86DataItemPtr subLeaf0)
+ {
+-    virCPUx86CPUID cpuid = { .eax_in = 0x17 };
++    virCPUx86DataItem item = CPUID(.eax_in = 0x17);
++    virCPUx86CPUIDPtr cpuid = &item.cpuid;
+     uint32_t sub;
+ 
+-    if (subLeaf0->eax < 3)
++    if (subLeaf0->cpuid.eax < 3)
+         return 0;
+ 
+     if (virCPUx86DataAddCPUID(data, subLeaf0) < 0)
+         return -1;
+ 
+-    for (sub = 1; sub <= subLeaf0->eax; sub++) {
+-        cpuid.ecx_in = sub;
+-        cpuidCall(&cpuid);
+-        if (virCPUx86DataAddCPUID(data, &cpuid) < 0)
++    for (sub = 1; sub <= subLeaf0->cpuid.eax; sub++) {
++        cpuid->ecx_in = sub;
++        cpuidCall(cpuid);
++        if (virCPUx86DataAddCPUID(data, &item) < 0)
+             return -1;
+     }
+     return 0;
+@@ -2450,39 +2469,40 @@ cpuidSet(uint32_t base, virCPUDataPtr data)
+     int rc;
+     uint32_t max;
+     uint32_t leaf;
+-    virCPUx86CPUID cpuid = { .eax_in = base };
++    virCPUx86DataItem item = CPUID(.eax_in = base);
++    virCPUx86CPUIDPtr cpuid = &item.cpuid;
+ 
+-    cpuidCall(&cpuid);
+-    max = cpuid.eax;
++    cpuidCall(cpuid);
++    max = cpuid->eax;
+ 
+     for (leaf = base; leaf <= max; leaf++) {
+-        cpuid.eax_in = leaf;
+-        cpuid.ecx_in = 0;
+-        cpuidCall(&cpuid);
++        cpuid->eax_in = leaf;
++        cpuid->ecx_in = 0;
++        cpuidCall(cpuid);
+ 
+         /* Handle CPUID leaves that depend on previously queried bits or
+          * which provide additional sub leaves for ecx_in > 0
+          */
+         if (leaf == 0x4)
+-            rc = cpuidSetLeaf4(data, &cpuid);
++            rc = cpuidSetLeaf4(data, &item);
+         else if (leaf == 0x7)
+-            rc = cpuidSetLeaf7(data, &cpuid);
++            rc = cpuidSetLeaf7(data, &item);
+         else if (leaf == 0xb)
+-            rc = cpuidSetLeafB(data, &cpuid);
++            rc = cpuidSetLeafB(data, &item);
+         else if (leaf == 0xd)
+-            rc = cpuidSetLeafD(data, &cpuid);
++            rc = cpuidSetLeafD(data, &item);
+         else if (leaf == 0xf)
+-            rc = cpuidSetLeafResID(data, &cpuid, cpuid.edx);
++            rc = cpuidSetLeafResID(data, &item, cpuid->edx);
+         else if (leaf == 0x10)
+-            rc = cpuidSetLeafResID(data, &cpuid, cpuid.ebx);
++            rc = cpuidSetLeafResID(data, &item, cpuid->ebx);
+         else if (leaf == 0x12)
+-            rc = cpuidSetLeaf12(data, &cpuid);
++            rc = cpuidSetLeaf12(data, &item);
+         else if (leaf == 0x14)
+-            rc = cpuidSetLeaf14(data, &cpuid);
++            rc = cpuidSetLeaf14(data, &item);
+         else if (leaf == 0x17)
+-            rc = cpuidSetLeaf17(data, &cpuid);
++            rc = cpuidSetLeaf17(data, &item);
+         else
+-            rc = virCPUx86DataAddCPUID(data, &cpuid);
++            rc = virCPUx86DataAddCPUID(data, &item);
+ 
+         if (rc < 0)
+             return -1;
+@@ -3058,7 +3078,7 @@ virCPUx86ValidateFeatures(virCPUDefPtr cpu)
+ 
+ int
+ virCPUx86DataAddCPUID(virCPUDataPtr cpuData,
+-                      const virCPUx86CPUID *cpuid)
++                      const virCPUx86DataItem *cpuid)
+ {
+     return virCPUx86DataAddCPUIDInt(&cpuData->data.x86, cpuid);
+ }
+@@ -3092,7 +3112,7 @@ int
+ virCPUx86DataSetVendor(virCPUDataPtr cpuData,
+                        const char *vendor)
+ {
+-    virCPUx86CPUID cpuid = { 0 };
++    virCPUx86DataItem cpuid = CPUID(0);
+ 
+     if (virCPUx86VendorToCPUID(vendor, &cpuid) < 0)
+         return -1;
+diff --git a/src/cpu/cpu_x86.h b/src/cpu/cpu_x86.h
+index 9d3c2b2cdd..94655746c6 100644
+--- a/src/cpu/cpu_x86.h
++++ b/src/cpu/cpu_x86.h
+@@ -30,7 +30,7 @@
+ extern struct cpuArchDriver cpuDriverX86;
+ 
+ int virCPUx86DataAddCPUID(virCPUDataPtr cpuData,
+-                          const virCPUx86CPUID *cpuid);
++                          const virCPUx86DataItem *cpuid);
+ 
+ int virCPUx86DataSetSignature(virCPUDataPtr cpuData,
+                               unsigned int family,
+diff --git a/src/cpu/cpu_x86_data.h b/src/cpu/cpu_x86_data.h
+index 090a21156f..e93b355cf0 100644
+--- a/src/cpu/cpu_x86_data.h
++++ b/src/cpu/cpu_x86_data.h
+@@ -27,6 +27,7 @@
+ # include <stdint.h>
+ 
+ typedef struct _virCPUx86CPUID virCPUx86CPUID;
++typedef virCPUx86CPUID *virCPUx86CPUIDPtr;
+ struct _virCPUx86CPUID {
+     uint32_t eax_in;
+     uint32_t ecx_in;
+@@ -70,10 +71,16 @@ struct _virCPUx86CPUID {
+ 
+ # define VIR_CPU_X86_DATA_INIT { 0 }
+ 
++typedef struct _virCPUx86DataItem virCPUx86DataItem;
++typedef virCPUx86DataItem *virCPUx86DataItemPtr;
++struct _virCPUx86DataItem {
++    virCPUx86CPUID cpuid;
++};
++
+ typedef struct _virCPUx86Data virCPUx86Data;
+ struct _virCPUx86Data {
+     size_t len;
+-    virCPUx86CPUID *data;
++    virCPUx86DataItem *items;
+ };
+ 
+ #endif /* __VIR_CPU_X86_DATA_H__ */
+diff --git a/src/libxl/libxl_capabilities.c b/src/libxl/libxl_capabilities.c
+index 18596c7c72..231d72669f 100644
+--- a/src/libxl/libxl_capabilities.c
++++ b/src/libxl/libxl_capabilities.c
+@@ -67,13 +67,15 @@ struct guest_arch {
+ static int
+ libxlCapsAddCPUID(virCPUDataPtr data, virCPUx86CPUID *cpuid, ssize_t ncaps)
+ {
++    virCPUx86DataItem item = { 0 };
+     size_t i;
+ 
+     for (i = 0; i < ncaps; i++) {
+-        virCPUx86CPUID *c = &cpuid[i];
++        item.cpuid = cpuid[i];
+ 
+-        if (virCPUx86DataAddCPUID(data, c) < 0) {
+-            VIR_DEBUG("Failed to add CPUID(%x,%x)", c->eax_in, c->ecx_in);
++        if (virCPUx86DataAddCPUID(data, &item) < 0) {
++            VIR_DEBUG("Failed to add CPUID(%x,%x)",
++                      cpuid[i].eax_in, cpuid[i].ecx_in);
+             return -1;
+         }
+     }
+diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
+index d6c11666c5..0b4dfd70c0 100644
+--- a/src/qemu/qemu_monitor_json.c
++++ b/src/qemu/qemu_monitor_json.c
+@@ -7043,7 +7043,7 @@ static virCPUDataPtr
+ qemuMonitorJSONParseCPUx86Features(virJSONValuePtr data)
+ {
+     virCPUDataPtr cpudata = NULL;
+-    virCPUx86CPUID cpuid;
++    virCPUx86DataItem item = { 0 };
+     size_t i;
+ 
+     if (!(cpudata = virCPUDataNew(VIR_ARCH_X86_64)))
+@@ -7051,8 +7051,8 @@ qemuMonitorJSONParseCPUx86Features(virJSONValuePtr data)
+ 
+     for (i = 0; i < virJSONValueArraySize(data); i++) {
+         if (qemuMonitorJSONParseCPUx86FeatureWord(virJSONValueArrayGet(data, i),
+-                                                  &cpuid) < 0 ||
+-            virCPUx86DataAddCPUID(cpudata, &cpuid) < 0)
++                                                  &item.cpuid) < 0 ||
++            virCPUx86DataAddCPUID(cpudata, &item) < 0)
+             goto error;
+     }
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-cpu_x86-Introduce-virCPUx86FeatureFilter-MSR.patch b/SOURCES/libvirt-cpu_x86-Introduce-virCPUx86FeatureFilter-MSR.patch
new file mode 100644
index 0000000..33dd149
--- /dev/null
+++ b/SOURCES/libvirt-cpu_x86-Introduce-virCPUx86FeatureFilter-MSR.patch
@@ -0,0 +1,133 @@
+From 016b5348df8fc1007c08b0d0deec68d923be2e75 Mon Sep 17 00:00:00 2001
+Message-Id: <016b5348df8fc1007c08b0d0deec68d923be2e75@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:26:08 +0200
+Subject: [PATCH] cpu_x86: Introduce virCPUx86FeatureFilter*MSR
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This functions may be used as a virCPUDefFeatureFilter callbacks for
+virCPUDefCheckFeatures, virCPUDefFilerFeatures, and similar functions to
+select (virCPUx86FeatureFilterSelectMSR) or drop
+(virCPUx86FeatureFilterDropMSR) features reported via MSR.
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit bcfed7f1c84cbff21d129a79cbd675b0cd51613c)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1697627
+
+Conflicts:
+	src/cpu/cpu_x86.h
+            - downstream did not switch to #pragma once
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <1a0fd2733f3aaec22e4ad598086baac0f086bb47.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/cpu/cpu_x86.c        | 57 ++++++++++++++++++++++++++++++++++++++++
+ src/cpu/cpu_x86.h        |  6 +++++
+ src/libvirt_private.syms |  3 ++-
+ 3 files changed, 65 insertions(+), 1 deletion(-)
+
+diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
+index 75527fd28f..ec0e408f98 100644
+--- a/src/cpu/cpu_x86.c
++++ b/src/cpu/cpu_x86.c
+@@ -3351,6 +3351,63 @@ virCPUx86DataAddFeature(virCPUDataPtr cpuData,
+ }
+ 
+ 
++static bool
++virCPUx86FeatureIsMSR(const char *name)
++{
++    virCPUx86FeaturePtr feature;
++    virCPUx86DataIterator iter;
++    virCPUx86DataItemPtr item;
++    virCPUx86MapPtr map;
++
++    if (!(map = virCPUx86GetMap()))
++        return false;
++
++    if (!(feature = x86FeatureFind(map, name)) &&
++        !(feature = x86FeatureFindInternal(name)))
++        return false;
++
++    virCPUx86DataIteratorInit(&iter, &feature->data);
++    while ((item = virCPUx86DataNext(&iter))) {
++        if (item->type == VIR_CPU_X86_DATA_MSR)
++            return true;
++    }
++
++    return false;
++}
++
++
++/**
++ * virCPUx86FeatureFilterSelectMSR:
++ *
++ * This is a callback for functions filtering features in virCPUDef. The result
++ * will contain only MSR features.
++ *
++ * Returns true if @name is an MSR feature, false otherwise.
++ */
++bool
++virCPUx86FeatureFilterSelectMSR(const char *name,
++                                void *opaque ATTRIBUTE_UNUSED)
++{
++    return virCPUx86FeatureIsMSR(name);
++}
++
++
++/**
++ * virCPUx86FeatureFilterDropMSR:
++ *
++ * This is a callback for functions filtering features in virCPUDef. The result
++ * will not contain any MSR feature.
++ *
++ * Returns true if @name is not an MSR feature, false otherwise.
++ */
++bool
++virCPUx86FeatureFilterDropMSR(const char *name,
++                              void *opaque ATTRIBUTE_UNUSED)
++{
++    return !virCPUx86FeatureIsMSR(name);
++}
++
++
+ struct cpuArchDriver cpuDriverX86 = {
+     .name = "x86",
+     .arch = archs,
+diff --git a/src/cpu/cpu_x86.h b/src/cpu/cpu_x86.h
+index 519024b7c0..5126679985 100644
+--- a/src/cpu/cpu_x86.h
++++ b/src/cpu/cpu_x86.h
+@@ -45,4 +45,10 @@ uint32_t virCPUx86DataGetSignature(virCPUDataPtr cpuData,
+ int virCPUx86DataSetVendor(virCPUDataPtr cpuData,
+                            const char *vendor);
+ 
++bool virCPUx86FeatureFilterSelectMSR(const char *name,
++                                     void *opaque);
++
++bool virCPUx86FeatureFilterDropMSR(const char *name,
++                                   void *opaque);
++
+ #endif /* __VIR_CPU_X86_H__ */
+diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
+index 0290f960a0..f158a17b49 100644
+--- a/src/libvirt_private.syms
++++ b/src/libvirt_private.syms
+@@ -1210,7 +1210,8 @@ virCPUx86DataAdd;
+ virCPUx86DataGetSignature;
+ virCPUx86DataSetSignature;
+ virCPUx86DataSetVendor;
+-
++virCPUx86FeatureFilterDropMSR;
++virCPUx86FeatureFilterSelectMSR;
+ 
+ # datatypes.h
+ virConnectClass;
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-cpu_x86-Log-decoded-CPU-model-and-signatures.patch b/SOURCES/libvirt-cpu_x86-Log-decoded-CPU-model-and-signatures.patch
new file mode 100644
index 0000000..2b67e02
--- /dev/null
+++ b/SOURCES/libvirt-cpu_x86-Log-decoded-CPU-model-and-signatures.patch
@@ -0,0 +1,79 @@
+From 3335b5e0db21375053c5005be9f820f7ba945010 Mon Sep 17 00:00:00 2001
+Message-Id: <3335b5e0db21375053c5005be9f820f7ba945010@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:25:02 +0200
+Subject: [PATCH] cpu_x86: Log decoded CPU model and signatures
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The log message may be useful when debugging why a specific CPU model
+was selected for a given set of CPUID data.
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit 5ced12decea42f1d588f2cb28b10ca7a5772098e)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1686895
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <cae19825427465e352de05433920c96dc44552ff.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/cpu/cpu_x86.c | 26 ++++++++++++++++++++++++++
+ 1 file changed, 26 insertions(+)
+
+diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
+index 7bd8119c23..ba14a6097d 100644
+--- a/src/cpu/cpu_x86.c
++++ b/src/cpu/cpu_x86.c
+@@ -1769,6 +1769,26 @@ x86ModelHasSignature(virCPUx86ModelPtr model,
+ }
+ 
+ 
++static char *
++x86FormatSignatures(virCPUx86ModelPtr model)
++{
++    virBuffer buf = VIR_BUFFER_INITIALIZER;
++    size_t i;
++
++    for (i = 0; i < model->nsignatures; i++) {
++        virBufferAsprintf(&buf, "%06lx,",
++                          (unsigned long)model->signatures[i]);
++    }
++
++    virBufferTrim(&buf, ",", -1);
++
++    if (virBufferCheckError(&buf) < 0)
++        return NULL;
++
++    return virBufferContentAndReset(&buf);
++}
++
++
+ /*
+  * Checks whether a candidate model is a better fit for the CPU data than the
+  * current model.
+@@ -1892,6 +1912,7 @@ x86Decode(virCPUDefPtr cpu,
+     virCPUx86Data features = VIR_CPU_X86_DATA_INIT;
+     virCPUx86VendorPtr vendor;
+     virDomainCapsCPUModelPtr hvModel = NULL;
++    VIR_AUTOFREE(char *) sigs = NULL;
+     uint32_t signature;
+     ssize_t i;
+     int rc;
+@@ -1984,6 +2005,11 @@ x86Decode(virCPUDefPtr cpu,
+     if (vendor && VIR_STRDUP(cpu->vendor, vendor->name) < 0)
+         goto cleanup;
+ 
++    sigs = x86FormatSignatures(model);
++
++    VIR_DEBUG("Using CPU model %s (signatures %s) for CPU with signature %06lx",
++              model->name, NULLSTR(sigs), (unsigned long)signature);
++
+     VIR_STEAL_PTR(cpu->model, cpuModel->model);
+     VIR_STEAL_PTR(cpu->features, cpuModel->features);
+     cpu->nfeatures = cpuModel->nfeatures;
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-cpu_x86-Make-sure-CPU-model-names-are-unique-in-cpu_map.patch b/SOURCES/libvirt-cpu_x86-Make-sure-CPU-model-names-are-unique-in-cpu_map.patch
new file mode 100644
index 0000000..fa962ba
--- /dev/null
+++ b/SOURCES/libvirt-cpu_x86-Make-sure-CPU-model-names-are-unique-in-cpu_map.patch
@@ -0,0 +1,49 @@
+From 84ee95b9504d89236078952a44c1a8b7dba148ca Mon Sep 17 00:00:00 2001
+Message-Id: <84ee95b9504d89236078952a44c1a8b7dba148ca@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:24:58 +0200
+Subject: [PATCH] cpu_x86: Make sure CPU model names are unique in cpu_map
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Having multiple CPU model definitions with the same name could result in
+unexpected behavior.
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit 8d7245441a473bc1f73005fd378d4a925870cce6)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1686895
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <c5dcc42f39009e8a659acb56b89cc18da1c3b7b8.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/cpu/cpu_x86.c | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
+index 91362198ab..51cb9b7143 100644
+--- a/src/cpu/cpu_x86.c
++++ b/src/cpu/cpu_x86.c
+@@ -1291,9 +1291,15 @@ x86ModelParse(xmlXPathContextPtr ctxt,
+               void *data)
+ {
+     virCPUx86MapPtr map = data;
+-    virCPUx86ModelPtr model;
++    virCPUx86ModelPtr model = NULL;
+     int ret = -1;
+ 
++    if (x86ModelFind(map, name)) {
++        virReportError(VIR_ERR_INTERNAL_ERROR,
++                       _("Multiple definitions of CPU model '%s'"), name);
++        goto cleanup;
++    }
++
+     if (!(model = x86ModelNew()))
+         goto cleanup;
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-cpu_x86-Make-x86cpuidAndBits-more-general.patch b/SOURCES/libvirt-cpu_x86-Make-x86cpuidAndBits-more-general.patch
new file mode 100644
index 0000000..5065e64
--- /dev/null
+++ b/SOURCES/libvirt-cpu_x86-Make-x86cpuidAndBits-more-general.patch
@@ -0,0 +1,64 @@
+From be1b7ab3f5a634de17359376d559d5c312f5623f Mon Sep 17 00:00:00 2001
+Message-Id: <be1b7ab3f5a634de17359376d559d5c312f5623f@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:25:35 +0200
+Subject: [PATCH] cpu_x86: Make x86cpuidAndBits more general
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The function now works on virCPUx86DataItem and it's renamed as
+virCPUx86DataItemAndBits.
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit da1efddfa6606520fb5f16622bc522b231484b54)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1697627
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <c265f1fcb4ab52f884dd9481a426978efa60b8c8.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/cpu/cpu_x86.c | 14 +++++++-------
+ 1 file changed, 7 insertions(+), 7 deletions(-)
+
+diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
+index 5fbf0294bb..54da9a985c 100644
+--- a/src/cpu/cpu_x86.c
++++ b/src/cpu/cpu_x86.c
+@@ -242,16 +242,16 @@ virCPUx86DataItemClearBits(virCPUx86DataItemPtr item,
+ 
+ 
+ static void
+-x86cpuidAndBits(virCPUx86CPUID *cpuid,
+-                const virCPUx86CPUID *mask)
++virCPUx86DataItemAndBits(virCPUx86DataItemPtr item,
++                         const virCPUx86DataItem *mask)
+ {
+     if (!mask)
+         return;
+ 
+-    cpuid->eax &= mask->eax;
+-    cpuid->ebx &= mask->ebx;
+-    cpuid->ecx &= mask->ecx;
+-    cpuid->edx &= mask->edx;
++    item->cpuid.eax &= mask->cpuid.eax;
++    item->cpuid.ebx &= mask->cpuid.ebx;
++    item->cpuid.ecx &= mask->cpuid.ecx;
++    item->cpuid.edx &= mask->cpuid.edx;
+ }
+ 
+ 
+@@ -447,7 +447,7 @@ x86DataIntersect(virCPUx86Data *data1,
+     while ((item1 = virCPUx86DataNext(&iter))) {
+         item2 = virCPUx86DataGet(data2, item1);
+         if (item2)
+-            x86cpuidAndBits(&item1->cpuid, &item2->cpuid);
++            virCPUx86DataItemAndBits(item1, item2);
+         else
+             virCPUx86DataItemClearBits(item1, item1);
+     }
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-cpu_x86-Make-x86cpuidClearBits-more-general.patch b/SOURCES/libvirt-cpu_x86-Make-x86cpuidClearBits-more-general.patch
new file mode 100644
index 0000000..4103fd0
--- /dev/null
+++ b/SOURCES/libvirt-cpu_x86-Make-x86cpuidClearBits-more-general.patch
@@ -0,0 +1,84 @@
+From e9bc4fcd2c16a80cf564879d154f3083a6766ff9 Mon Sep 17 00:00:00 2001
+Message-Id: <e9bc4fcd2c16a80cf564879d154f3083a6766ff9@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:25:34 +0200
+Subject: [PATCH] cpu_x86: Make x86cpuidClearBits more general
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The parameters changed from virCPUx86CPUID to virCPUx86DataItem and the
+function is now called virCPUx86DataItemClearBits.
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit 4e3cab2d002d5f4cfdf81359467de8ffe4e18682)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1697627
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <bdc0f6c7da3674ba988c2fd83525a60df9108864.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/cpu/cpu_x86.c | 20 ++++++++++----------
+ 1 file changed, 10 insertions(+), 10 deletions(-)
+
+diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
+index e2951ed1b0..5fbf0294bb 100644
+--- a/src/cpu/cpu_x86.c
++++ b/src/cpu/cpu_x86.c
+@@ -228,16 +228,16 @@ virCPUx86DataItemSetBits(virCPUx86DataItemPtr item,
+ 
+ 
+ static void
+-x86cpuidClearBits(virCPUx86CPUID *cpuid,
+-                  const virCPUx86CPUID *mask)
++virCPUx86DataItemClearBits(virCPUx86DataItemPtr item,
++                           const virCPUx86DataItem *mask)
+ {
+     if (!mask)
+         return;
+ 
+-    cpuid->eax &= ~mask->eax;
+-    cpuid->ebx &= ~mask->ebx;
+-    cpuid->ecx &= ~mask->ecx;
+-    cpuid->edx &= ~mask->edx;
++    item->cpuid.eax &= ~mask->cpuid.eax;
++    item->cpuid.ebx &= ~mask->cpuid.ebx;
++    item->cpuid.ecx &= ~mask->cpuid.ecx;
++    item->cpuid.edx &= ~mask->cpuid.edx;
+ }
+ 
+ 
+@@ -430,8 +430,8 @@ x86DataSubtract(virCPUx86Data *data1,
+     virCPUx86DataItemPtr item2;
+ 
+     while ((item1 = virCPUx86DataNext(&iter))) {
+-        if ((item2 = virCPUx86DataGet(data2, item1)))
+-            x86cpuidClearBits(&item1->cpuid, &item2->cpuid);
++        item2 = virCPUx86DataGet(data2, item1);
++        virCPUx86DataItemClearBits(item1, item2);
+     }
+ }
+ 
+@@ -449,7 +449,7 @@ x86DataIntersect(virCPUx86Data *data1,
+         if (item2)
+             x86cpuidAndBits(&item1->cpuid, &item2->cpuid);
+         else
+-            x86cpuidClearBits(&item1->cpuid, &item1->cpuid);
++            virCPUx86DataItemClearBits(item1, item1);
+     }
+ }
+ 
+@@ -516,7 +516,7 @@ x86DataToVendor(const virCPUx86Data *data,
+         virCPUx86VendorPtr vendor = map->vendors[i];
+         if ((item = virCPUx86DataGet(data, &vendor->data)) &&
+             x86cpuidMatchMasked(&item->cpuid, &vendor->data.cpuid)) {
+-            x86cpuidClearBits(&item->cpuid, &vendor->data.cpuid);
++            virCPUx86DataItemClearBits(item, &vendor->data);
+             return vendor;
+         }
+     }
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-cpu_x86-Make-x86cpuidMatch-more-general.patch b/SOURCES/libvirt-cpu_x86-Make-x86cpuidMatch-more-general.patch
new file mode 100644
index 0000000..f6fd0fd
--- /dev/null
+++ b/SOURCES/libvirt-cpu_x86-Make-x86cpuidMatch-more-general.patch
@@ -0,0 +1,96 @@
+From 759fe35a1acdccf68577de62752c087aea4b8268 Mon Sep 17 00:00:00 2001
+Message-Id: <759fe35a1acdccf68577de62752c087aea4b8268@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:25:37 +0200
+Subject: [PATCH] cpu_x86: Make x86cpuidMatch more general
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The function now works on virCPUx86DataItem and it's called
+virCPUx86DataItemMatch.
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit 10b80165dba31f99306f39e348e3a6335feec5ef)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1697627
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <0b829eb945561e54c1fc4d333c59af53759edf19.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/cpu/cpu_x86.c | 21 ++++++++++-----------
+ 1 file changed, 10 insertions(+), 11 deletions(-)
+
+diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
+index 1bb35ec4e8..11c023ac31 100644
+--- a/src/cpu/cpu_x86.c
++++ b/src/cpu/cpu_x86.c
+@@ -41,8 +41,6 @@ VIR_LOG_INIT("cpu.cpu_x86");
+ 
+ #define VENDOR_STRING_LENGTH    12
+ 
+-static const virCPUx86CPUID cpuidNull = { 0 };
+-
+ static const virArch archs[] = { VIR_ARCH_I686, VIR_ARCH_X86_64 };
+ 
+ typedef struct _virCPUx86Vendor virCPUx86Vendor;
+@@ -192,13 +190,13 @@ struct _virCPUx86DataIterator {
+ 
+ 
+ static bool
+-x86cpuidMatch(const virCPUx86CPUID *cpuid1,
+-              const virCPUx86CPUID *cpuid2)
++virCPUx86DataItemMatch(const virCPUx86DataItem *item1,
++                       const virCPUx86DataItem *item2)
+ {
+-    return (cpuid1->eax == cpuid2->eax &&
+-            cpuid1->ebx == cpuid2->ebx &&
+-            cpuid1->ecx == cpuid2->ecx &&
+-            cpuid1->edx == cpuid2->edx);
++    return (item1->cpuid.eax == item2->cpuid.eax &&
++            item1->cpuid.ebx == item2->cpuid.ebx &&
++            item1->cpuid.ecx == item2->cpuid.ecx &&
++            item1->cpuid.edx == item2->cpuid.edx);
+ }
+ 
+ 
+@@ -317,6 +315,7 @@ static virCPUx86DataItemPtr
+ virCPUx86DataNext(virCPUx86DataIteratorPtr iterator)
+ {
+     const virCPUx86Data *data = iterator->data;
++    virCPUx86DataItem zero = { 0 };
+ 
+     if (!data)
+         return NULL;
+@@ -324,7 +323,7 @@ virCPUx86DataNext(virCPUx86DataIteratorPtr iterator)
+     while (++iterator->pos < data->len) {
+         virCPUx86DataItemPtr item = data->items + iterator->pos;
+ 
+-        if (!x86cpuidMatch(&item->cpuid, &cpuidNull))
++        if (!virCPUx86DataItemMatch(item, &zero))
+             return item;
+     }
+ 
+@@ -1155,7 +1154,7 @@ x86ModelCompare(virCPUx86ModelPtr model1,
+         virCPUx86CompareResult match = SUPERSET;
+ 
+         if ((item2 = virCPUx86DataGet(&model2->data, item1))) {
+-            if (x86cpuidMatch(&item1->cpuid, &item2->cpuid))
++            if (virCPUx86DataItemMatch(item1, item2))
+                 continue;
+             else if (!virCPUx86DataItemMatchMasked(item1, item2))
+                 match = SUBSET;
+@@ -1171,7 +1170,7 @@ x86ModelCompare(virCPUx86ModelPtr model1,
+         virCPUx86CompareResult match = SUBSET;
+ 
+         if ((item1 = virCPUx86DataGet(&model1->data, item2))) {
+-            if (x86cpuidMatch(&item2->cpuid, &item1->cpuid))
++            if (virCPUx86DataItemMatch(item2, item1))
+                 continue;
+             else if (!virCPUx86DataItemMatchMasked(item2, item1))
+                 match = SUPERSET;
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-cpu_x86-Make-x86cpuidMatchMasked-more-general.patch b/SOURCES/libvirt-cpu_x86-Make-x86cpuidMatchMasked-more-general.patch
new file mode 100644
index 0000000..e1c1925
--- /dev/null
+++ b/SOURCES/libvirt-cpu_x86-Make-x86cpuidMatchMasked-more-general.patch
@@ -0,0 +1,88 @@
+From 920ac610bc68ffd7de1ac14c401c7f8c37f3337e Mon Sep 17 00:00:00 2001
+Message-Id: <920ac610bc68ffd7de1ac14c401c7f8c37f3337e@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:25:36 +0200
+Subject: [PATCH] cpu_x86: Make x86cpuidMatchMasked more general
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The function is renamed as virCPUx86DataItemMatchMasked to reflect the
+change in parameter types.
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit 2eea67a98eab58b46dbf4275819c06c90bc4c5b6)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1697627
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <7c0a54c618d67d64663eb92d5eeb1d8a2270be16.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/cpu/cpu_x86.c | 20 ++++++++++----------
+ 1 file changed, 10 insertions(+), 10 deletions(-)
+
+diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
+index 54da9a985c..1bb35ec4e8 100644
+--- a/src/cpu/cpu_x86.c
++++ b/src/cpu/cpu_x86.c
+@@ -203,13 +203,13 @@ x86cpuidMatch(const virCPUx86CPUID *cpuid1,
+ 
+ 
+ static bool
+-x86cpuidMatchMasked(const virCPUx86CPUID *cpuid,
+-                    const virCPUx86CPUID *mask)
++virCPUx86DataItemMatchMasked(const virCPUx86DataItem *item,
++                             const virCPUx86DataItem *mask)
+ {
+-    return ((cpuid->eax & mask->eax) == mask->eax &&
+-            (cpuid->ebx & mask->ebx) == mask->ebx &&
+-            (cpuid->ecx & mask->ecx) == mask->ecx &&
+-            (cpuid->edx & mask->edx) == mask->edx);
++    return ((item->cpuid.eax & mask->cpuid.eax) == mask->cpuid.eax &&
++            (item->cpuid.ebx & mask->cpuid.ebx) == mask->cpuid.ebx &&
++            (item->cpuid.ecx & mask->cpuid.ecx) == mask->cpuid.ecx &&
++            (item->cpuid.edx & mask->cpuid.edx) == mask->cpuid.edx);
+ }
+ 
+ 
+@@ -474,7 +474,7 @@ x86DataIsSubset(const virCPUx86Data *data,
+ 
+     while ((itemSubset = virCPUx86DataNext(&iter))) {
+         if (!(item = virCPUx86DataGet(data, itemSubset)) ||
+-            !x86cpuidMatchMasked(&item->cpuid, &itemSubset->cpuid))
++            !virCPUx86DataItemMatchMasked(item, itemSubset))
+             return false;
+     }
+ 
+@@ -515,7 +515,7 @@ x86DataToVendor(const virCPUx86Data *data,
+     for (i = 0; i < map->nvendors; i++) {
+         virCPUx86VendorPtr vendor = map->vendors[i];
+         if ((item = virCPUx86DataGet(data, &vendor->data)) &&
+-            x86cpuidMatchMasked(&item->cpuid, &vendor->data.cpuid)) {
++            virCPUx86DataItemMatchMasked(item, &vendor->data)) {
+             virCPUx86DataItemClearBits(item, &vendor->data);
+             return vendor;
+         }
+@@ -1157,7 +1157,7 @@ x86ModelCompare(virCPUx86ModelPtr model1,
+         if ((item2 = virCPUx86DataGet(&model2->data, item1))) {
+             if (x86cpuidMatch(&item1->cpuid, &item2->cpuid))
+                 continue;
+-            else if (!x86cpuidMatchMasked(&item1->cpuid, &item2->cpuid))
++            else if (!virCPUx86DataItemMatchMasked(item1, item2))
+                 match = SUBSET;
+         }
+ 
+@@ -1173,7 +1173,7 @@ x86ModelCompare(virCPUx86ModelPtr model1,
+         if ((item1 = virCPUx86DataGet(&model1->data, item2))) {
+             if (x86cpuidMatch(&item2->cpuid, &item1->cpuid))
+                 continue;
+-            else if (!x86cpuidMatchMasked(&item2->cpuid, &item1->cpuid))
++            else if (!virCPUx86DataItemMatchMasked(item2, item1))
+                 match = SUPERSET;
+         }
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-cpu_x86-Make-x86cpuidSetBits-more-general.patch b/SOURCES/libvirt-cpu_x86-Make-x86cpuidSetBits-more-general.patch
new file mode 100644
index 0000000..642480d
--- /dev/null
+++ b/SOURCES/libvirt-cpu_x86-Make-x86cpuidSetBits-more-general.patch
@@ -0,0 +1,64 @@
+From d32fbe55ad3ee1bbbfe2adc9ab47034c7a5cb884 Mon Sep 17 00:00:00 2001
+Message-Id: <d32fbe55ad3ee1bbbfe2adc9ab47034c7a5cb884@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:25:33 +0200
+Subject: [PATCH] cpu_x86: Make x86cpuidSetBits more general
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The function is renamed as virCPUx86DataItemSetBits and it works on
+virCPUx86DataItem now.
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit 9c6f00fc3351800dc8b63472e71b398c180161d8)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1697627
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <f2e1e24cb2be24ee66911f75384436c5c4513d3e.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/cpu/cpu_x86.c | 14 +++++++-------
+ 1 file changed, 7 insertions(+), 7 deletions(-)
+
+diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
+index 5a09033d2a..e2951ed1b0 100644
+--- a/src/cpu/cpu_x86.c
++++ b/src/cpu/cpu_x86.c
+@@ -214,16 +214,16 @@ x86cpuidMatchMasked(const virCPUx86CPUID *cpuid,
+ 
+ 
+ static void
+-x86cpuidSetBits(virCPUx86CPUID *cpuid,
+-                const virCPUx86CPUID *mask)
++virCPUx86DataItemSetBits(virCPUx86DataItemPtr item,
++                         const virCPUx86DataItem *mask)
+ {
+     if (!mask)
+         return;
+ 
+-    cpuid->eax |= mask->eax;
+-    cpuid->ebx |= mask->ebx;
+-    cpuid->ecx |= mask->ecx;
+-    cpuid->edx |= mask->edx;
++    item->cpuid.eax |= mask->cpuid.eax;
++    item->cpuid.ebx |= mask->cpuid.ebx;
++    item->cpuid.ecx |= mask->cpuid.ecx;
++    item->cpuid.edx |= mask->cpuid.edx;
+ }
+ 
+ 
+@@ -391,7 +391,7 @@ virCPUx86DataAddItem(virCPUx86Data *data,
+     virCPUx86DataItemPtr existing;
+ 
+     if ((existing = virCPUx86DataGet(data, item))) {
+-        x86cpuidSetBits(&existing->cpuid, &item->cpuid);
++        virCPUx86DataItemSetBits(existing, item);
+     } else {
+         if (VIR_APPEND_ELEMENT_COPY(data->items, data->len,
+                                     *((virCPUx86DataItemPtr)item)) < 0)
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-cpu_x86-Move-CheckFeature-functions.patch b/SOURCES/libvirt-cpu_x86-Move-CheckFeature-functions.patch
new file mode 100644
index 0000000..e098b99
--- /dev/null
+++ b/SOURCES/libvirt-cpu_x86-Move-CheckFeature-functions.patch
@@ -0,0 +1,115 @@
+From dec2ce4345db0d13cff8c639c69afbf894ee593a Mon Sep 17 00:00:00 2001
+Message-Id: <dec2ce4345db0d13cff8c639c69afbf894ee593a@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:25:40 +0200
+Subject: [PATCH] cpu_x86: Move *CheckFeature functions
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+They are static and we will need to call them a little bit closer to the
+beginning of the file.
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit e17d10386bd9abcfb37c7d8b151bbd1071a87fc4)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1697627
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <41d2a36757ed83f70c9dc23e9b984e109e5a81ba.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/cpu/cpu_x86.c | 69 ++++++++++++++++++++++++-----------------------
+ 1 file changed, 35 insertions(+), 34 deletions(-)
+
+diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
+index 49562944c1..fdc2974a0d 100644
+--- a/src/cpu/cpu_x86.c
++++ b/src/cpu/cpu_x86.c
+@@ -2706,6 +2706,41 @@ cpuidSet(uint32_t base, virCPUDataPtr data)
+ }
+ 
+ 
++static int
++virCPUx86CheckFeature(const virCPUDef *cpu,
++                      const char *name)
++{
++    int ret = -1;
++    virCPUx86MapPtr map;
++    virCPUx86ModelPtr model = NULL;
++
++    if (!(map = virCPUx86GetMap()))
++        return -1;
++
++    if (!(model = x86ModelFromCPU(cpu, map, -1)))
++        goto cleanup;
++
++    ret = x86FeatureInData(name, &model->data, map);
++
++ cleanup:
++    x86ModelFree(model);
++    return ret;
++}
++
++
++static int
++virCPUx86DataCheckFeature(const virCPUData *data,
++                          const char *name)
++{
++    virCPUx86MapPtr map;
++
++    if (!(map = virCPUx86GetMap()))
++        return -1;
++
++    return x86FeatureInData(name, &data->data.x86, map);
++}
++
++
+ static int
+ virCPUx86GetHost(virCPUDefPtr cpu,
+                  virDomainCapsCPUModelsPtr models)
+@@ -3062,40 +3097,6 @@ virCPUx86UpdateLive(virCPUDefPtr cpu,
+ }
+ 
+ 
+-static int
+-virCPUx86CheckFeature(const virCPUDef *cpu,
+-                      const char *name)
+-{
+-    int ret = -1;
+-    virCPUx86MapPtr map;
+-    virCPUx86ModelPtr model = NULL;
+-
+-    if (!(map = virCPUx86GetMap()))
+-        return -1;
+-
+-    if (!(model = x86ModelFromCPU(cpu, map, -1)))
+-        goto cleanup;
+-
+-    ret = x86FeatureInData(name, &model->data, map);
+-
+- cleanup:
+-    x86ModelFree(model);
+-    return ret;
+-}
+-
+-
+-static int
+-virCPUx86DataCheckFeature(const virCPUData *data,
+-                          const char *name)
+-{
+-    virCPUx86MapPtr map;
+-
+-    if (!(map = virCPUx86GetMap()))
+-        return -1;
+-
+-    return x86FeatureInData(name, &data->data.x86, map);
+-}
+-
+ static int
+ virCPUx86GetModels(char ***models)
+ {
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-cpu_x86-Read-CPU-features-from-IA32_ARCH_CAPABILITIES-MSR.patch b/SOURCES/libvirt-cpu_x86-Read-CPU-features-from-IA32_ARCH_CAPABILITIES-MSR.patch
new file mode 100644
index 0000000..d583e77
--- /dev/null
+++ b/SOURCES/libvirt-cpu_x86-Read-CPU-features-from-IA32_ARCH_CAPABILITIES-MSR.patch
@@ -0,0 +1,61 @@
+From 0004d2f3b0c3b21336415a967d70b7e9c2d08f54 Mon Sep 17 00:00:00 2001
+Message-Id: <0004d2f3b0c3b21336415a967d70b7e9c2d08f54@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:26:09 +0200
+Subject: [PATCH] cpu_x86: Read CPU features from IA32_ARCH_CAPABILITIES MSR
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This is used by the host capabilities code to construct host CPU
+definition.
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit 56b254dccc96b7339494812c9df07ccf6af3da95)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1697627
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <58ad207c48e0f2a6c44ff097b0881b649826ecd4.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/cpu/cpu_x86.c | 22 ++++++++++++++++++++++
+ 1 file changed, 22 insertions(+)
+
+diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
+index ec0e408f98..0a520f07ff 100644
+--- a/src/cpu/cpu_x86.c
++++ b/src/cpu/cpu_x86.c
+@@ -2771,6 +2771,28 @@ virCPUx86GetHost(virCPUDefPtr cpu,
+         cpuidSet(CPUX86_EXTENDED, cpuData) < 0)
+         goto cleanup;
+ 
++    /* Read the IA32_ARCH_CAPABILITIES MSR (0x10a) if supported.
++     * This is best effort since there might be no way to read the MSR
++     * when we are not running as root. */
++    if (virCPUx86DataCheckFeature(cpuData, "arch-capabilities") == 1) {
++        uint64_t msr;
++        unsigned long index = 0x10a;
++
++        if (virHostCPUGetMSR(index, &msr) == 0) {
++            virCPUx86DataItem item = {
++                .type = VIR_CPU_X86_DATA_MSR,
++                .data.msr = {
++                    .index = index,
++                    .eax = msr & 0xffffffff,
++                    .edx = msr >> 32,
++                },
++            };
++
++            if (virCPUx86DataAdd(cpuData, &item) < 0)
++                return -1;
++        }
++    }
++
+     ret = x86DecodeCPUData(cpu, cpuData, models);
+     cpu->microcodeVersion = virHostCPUGetMicrocodeVersion();
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-cpu_x86-Rename-virCPUx86CPUIDSorter.patch b/SOURCES/libvirt-cpu_x86-Rename-virCPUx86CPUIDSorter.patch
new file mode 100644
index 0000000..c7e1099
--- /dev/null
+++ b/SOURCES/libvirt-cpu_x86-Rename-virCPUx86CPUIDSorter.patch
@@ -0,0 +1,50 @@
+From ea8bf8889659145cbf53306e3d16357f40679e4e Mon Sep 17 00:00:00 2001
+Message-Id: <ea8bf8889659145cbf53306e3d16357f40679e4e@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:25:27 +0200
+Subject: [PATCH] cpu_x86: Rename virCPUx86CPUIDSorter
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+It is called virCPUx86DataSorter since the function will work on any CPU
+data type.
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit 95accfa7fa15b21bf4824b55be666312d11c273a)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1697627
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <4661aa497f1b8d9b5ca1383a91affe24cd54caa9.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/cpu/cpu_x86.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
+index 52709f109e..efb2a3bb07 100644
+--- a/src/cpu/cpu_x86.c
++++ b/src/cpu/cpu_x86.c
+@@ -286,7 +286,7 @@ x86FeatureFindInternal(const char *name)
+ 
+ 
+ static int
+-virCPUx86CPUIDSorter(const void *a, const void *b)
++virCPUx86DataSorter(const void *a, const void *b)
+ {
+     virCPUx86DataItemPtr da = (virCPUx86DataItemPtr) a;
+     virCPUx86DataItemPtr db = (virCPUx86DataItemPtr) b;
+@@ -391,7 +391,7 @@ virCPUx86DataAddCPUIDInt(virCPUx86Data *data,
+             return -1;
+ 
+         qsort(data->items, data->len,
+-              sizeof(virCPUx86DataItem), virCPUx86CPUIDSorter);
++              sizeof(virCPUx86DataItem), virCPUx86DataSorter);
+     }
+ 
+     return 0;
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-cpu_x86-Rename-virCPUx86DataAddCPUID.patch b/SOURCES/libvirt-cpu_x86-Rename-virCPUx86DataAddCPUID.patch
new file mode 100644
index 0000000..8ad7f35
--- /dev/null
+++ b/SOURCES/libvirt-cpu_x86-Rename-virCPUx86DataAddCPUID.patch
@@ -0,0 +1,274 @@
+From d4df159ee1e489c9afc238f39e6bb52d4f71bce7 Mon Sep 17 00:00:00 2001
+Message-Id: <d4df159ee1e489c9afc238f39e6bb52d4f71bce7@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:25:29 +0200
+Subject: [PATCH] cpu_x86: Rename virCPUx86DataAddCPUID
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+It's called virCPUx86DataAdd now.
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit 8f1a8ce397d7514bee9f370a1531d668e01ec923)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1697627
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <1be869684ede8249c16fcab128fc6775edda08be.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/cpu/cpu_x86.c              | 46 +++++++++++++++++-----------------
+ src/cpu/cpu_x86.h              |  4 +--
+ src/libvirt_private.syms       |  2 +-
+ src/libxl/libxl_capabilities.c |  2 +-
+ src/qemu/qemu_monitor_json.c   |  2 +-
+ 5 files changed, 28 insertions(+), 28 deletions(-)
+
+diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
+index 7e077577d3..6d48c9264c 100644
+--- a/src/cpu/cpu_x86.c
++++ b/src/cpu/cpu_x86.c
+@@ -1505,7 +1505,7 @@ virCPUx86DataParse(xmlXPathContextPtr ctxt)
+                            _("failed to parse cpuid[%zu]"), i);
+             goto error;
+         }
+-        if (virCPUx86DataAddCPUID(cpuData, &item) < 0)
++        if (virCPUx86DataAdd(cpuData, &item) < 0)
+             goto error;
+     }
+ 
+@@ -2153,7 +2153,7 @@ x86Encode(virArch arch,
+         if (!(data_vendor = virCPUDataNew(arch)))
+             goto error;
+ 
+-        if (v && virCPUx86DataAddCPUID(data_vendor, &v->data) < 0)
++        if (v && virCPUx86DataAdd(data_vendor, &v->data) < 0)
+             goto error;
+     }
+ 
+@@ -2229,13 +2229,13 @@ cpuidSetLeaf4(virCPUDataPtr data,
+     virCPUx86DataItem item = *subLeaf0;
+     virCPUx86CPUIDPtr cpuid = &item.cpuid;
+ 
+-    if (virCPUx86DataAddCPUID(data, subLeaf0) < 0)
++    if (virCPUx86DataAdd(data, subLeaf0) < 0)
+         return -1;
+ 
+     while (cpuid->eax & 0x1f) {
+         cpuid->ecx_in++;
+         cpuidCall(cpuid);
+-        if (virCPUx86DataAddCPUID(data, &item) < 0)
++        if (virCPUx86DataAdd(data, &item) < 0)
+             return -1;
+     }
+     return 0;
+@@ -2254,13 +2254,13 @@ cpuidSetLeaf7(virCPUDataPtr data,
+     virCPUx86CPUIDPtr cpuid = &item.cpuid;
+     uint32_t sub;
+ 
+-    if (virCPUx86DataAddCPUID(data, subLeaf0) < 0)
++    if (virCPUx86DataAdd(data, subLeaf0) < 0)
+         return -1;
+ 
+     for (sub = 1; sub <= subLeaf0->cpuid.eax; sub++) {
+         cpuid->ecx_in = sub;
+         cpuidCall(cpuid);
+-        if (virCPUx86DataAddCPUID(data, &item) < 0)
++        if (virCPUx86DataAdd(data, &item) < 0)
+             return -1;
+     }
+     return 0;
+@@ -2282,7 +2282,7 @@ cpuidSetLeafB(virCPUDataPtr data,
+     virCPUx86CPUIDPtr cpuid = &item.cpuid;
+ 
+     while (cpuid->ecx & 0xff00) {
+-        if (virCPUx86DataAddCPUID(data, &item) < 0)
++        if (virCPUx86DataAdd(data, &item) < 0)
+             return -1;
+         cpuid->ecx_in++;
+         cpuidCall(cpuid);
+@@ -2309,12 +2309,12 @@ cpuidSetLeafD(virCPUDataPtr data,
+     virCPUx86CPUID sub1;
+     uint32_t sub;
+ 
+-    if (virCPUx86DataAddCPUID(data, subLeaf0) < 0)
++    if (virCPUx86DataAdd(data, subLeaf0) < 0)
+         return -1;
+ 
+     cpuid->ecx_in = 1;
+     cpuidCall(cpuid);
+-    if (virCPUx86DataAddCPUID(data, &item) < 0)
++    if (virCPUx86DataAdd(data, &item) < 0)
+         return -1;
+ 
+     sub0 = subLeaf0->cpuid;
+@@ -2331,7 +2331,7 @@ cpuidSetLeafD(virCPUDataPtr data,
+ 
+         cpuid->ecx_in = sub;
+         cpuidCall(cpuid);
+-        if (virCPUx86DataAddCPUID(data, &item) < 0)
++        if (virCPUx86DataAdd(data, &item) < 0)
+             return -1;
+     }
+     return 0;
+@@ -2356,7 +2356,7 @@ cpuidSetLeafResID(virCPUDataPtr data,
+     virCPUx86CPUIDPtr cpuid = &item.cpuid;
+     uint32_t sub;
+ 
+-    if (virCPUx86DataAddCPUID(data, subLeaf0) < 0)
++    if (virCPUx86DataAdd(data, subLeaf0) < 0)
+         return -1;
+ 
+     for (sub = 1; sub < 32; sub++) {
+@@ -2364,7 +2364,7 @@ cpuidSetLeafResID(virCPUDataPtr data,
+             continue;
+         cpuid->ecx_in = sub;
+         cpuidCall(cpuid);
+-        if (virCPUx86DataAddCPUID(data, &item) < 0)
++        if (virCPUx86DataAdd(data, &item) < 0)
+             return -1;
+     }
+     return 0;
+@@ -2388,19 +2388,19 @@ cpuidSetLeaf12(virCPUDataPtr data,
+         !(leaf7->cpuid.ebx & (1 << 2)))
+         return 0;
+ 
+-    if (virCPUx86DataAddCPUID(data, subLeaf0) < 0)
++    if (virCPUx86DataAdd(data, subLeaf0) < 0)
+         return -1;
+ 
+     cpuid->eax_in = 0x12;
+     cpuid->ecx_in = 1;
+     cpuidCall(cpuid);
+-    if (virCPUx86DataAddCPUID(data, &item) < 0)
++    if (virCPUx86DataAdd(data, &item) < 0)
+         return -1;
+ 
+     cpuid->ecx_in = 2;
+     cpuidCall(cpuid);
+     while (cpuid->eax & 0xf) {
+-        if (virCPUx86DataAddCPUID(data, &item) < 0)
++        if (virCPUx86DataAdd(data, &item) < 0)
+             return -1;
+         cpuid->ecx_in++;
+         cpuidCall(cpuid);
+@@ -2421,13 +2421,13 @@ cpuidSetLeaf14(virCPUDataPtr data,
+     virCPUx86CPUIDPtr cpuid = &item.cpuid;
+     uint32_t sub;
+ 
+-    if (virCPUx86DataAddCPUID(data, subLeaf0) < 0)
++    if (virCPUx86DataAdd(data, subLeaf0) < 0)
+         return -1;
+ 
+     for (sub = 1; sub <= subLeaf0->cpuid.eax; sub++) {
+         cpuid->ecx_in = sub;
+         cpuidCall(cpuid);
+-        if (virCPUx86DataAddCPUID(data, &item) < 0)
++        if (virCPUx86DataAdd(data, &item) < 0)
+             return -1;
+     }
+     return 0;
+@@ -2450,13 +2450,13 @@ cpuidSetLeaf17(virCPUDataPtr data,
+     if (subLeaf0->cpuid.eax < 3)
+         return 0;
+ 
+-    if (virCPUx86DataAddCPUID(data, subLeaf0) < 0)
++    if (virCPUx86DataAdd(data, subLeaf0) < 0)
+         return -1;
+ 
+     for (sub = 1; sub <= subLeaf0->cpuid.eax; sub++) {
+         cpuid->ecx_in = sub;
+         cpuidCall(cpuid);
+-        if (virCPUx86DataAddCPUID(data, &item) < 0)
++        if (virCPUx86DataAdd(data, &item) < 0)
+             return -1;
+     }
+     return 0;
+@@ -2502,7 +2502,7 @@ cpuidSet(uint32_t base, virCPUDataPtr data)
+         else if (leaf == 0x17)
+             rc = cpuidSetLeaf17(data, &item);
+         else
+-            rc = virCPUx86DataAddCPUID(data, &item);
++            rc = virCPUx86DataAdd(data, &item);
+ 
+         if (rc < 0)
+             return -1;
+@@ -3077,8 +3077,8 @@ virCPUx86ValidateFeatures(virCPUDefPtr cpu)
+ 
+ 
+ int
+-virCPUx86DataAddCPUID(virCPUDataPtr cpuData,
+-                      const virCPUx86DataItem *item)
++virCPUx86DataAdd(virCPUDataPtr cpuData,
++                 const virCPUx86DataItem *item)
+ {
+     return virCPUx86DataAddItem(&cpuData->data.x86, item);
+ }
+@@ -3117,7 +3117,7 @@ virCPUx86DataSetVendor(virCPUDataPtr cpuData,
+     if (virCPUx86VendorToCPUID(vendor, &item) < 0)
+         return -1;
+ 
+-    return virCPUx86DataAddCPUID(cpuData, &item);
++    return virCPUx86DataAdd(cpuData, &item);
+ }
+ 
+ 
+diff --git a/src/cpu/cpu_x86.h b/src/cpu/cpu_x86.h
+index 94655746c6..8b51cef9c1 100644
+--- a/src/cpu/cpu_x86.h
++++ b/src/cpu/cpu_x86.h
+@@ -29,8 +29,8 @@
+ 
+ extern struct cpuArchDriver cpuDriverX86;
+ 
+-int virCPUx86DataAddCPUID(virCPUDataPtr cpuData,
+-                          const virCPUx86DataItem *cpuid);
++int virCPUx86DataAdd(virCPUDataPtr cpuData,
++                     const virCPUx86DataItem *cpuid);
+ 
+ int virCPUx86DataSetSignature(virCPUDataPtr cpuData,
+                               unsigned int family,
+diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
+index a275fa9aa1..347667b17c 100644
+--- a/src/libvirt_private.syms
++++ b/src/libvirt_private.syms
+@@ -1203,7 +1203,7 @@ virCPUValidateFeatures;
+ 
+ 
+ # cpu/cpu_x86.h
+-virCPUx86DataAddCPUID;
++virCPUx86DataAdd;
+ virCPUx86DataAddFeature;
+ virCPUx86DataGetSignature;
+ virCPUx86DataSetSignature;
+diff --git a/src/libxl/libxl_capabilities.c b/src/libxl/libxl_capabilities.c
+index 231d72669f..2b351fbdde 100644
+--- a/src/libxl/libxl_capabilities.c
++++ b/src/libxl/libxl_capabilities.c
+@@ -73,7 +73,7 @@ libxlCapsAddCPUID(virCPUDataPtr data, virCPUx86CPUID *cpuid, ssize_t ncaps)
+     for (i = 0; i < ncaps; i++) {
+         item.cpuid = cpuid[i];
+ 
+-        if (virCPUx86DataAddCPUID(data, &item) < 0) {
++        if (virCPUx86DataAdd(data, &item) < 0) {
+             VIR_DEBUG("Failed to add CPUID(%x,%x)",
+                       cpuid[i].eax_in, cpuid[i].ecx_in);
+             return -1;
+diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
+index 0b4dfd70c0..abfaa6e68a 100644
+--- a/src/qemu/qemu_monitor_json.c
++++ b/src/qemu/qemu_monitor_json.c
+@@ -7052,7 +7052,7 @@ qemuMonitorJSONParseCPUx86Features(virJSONValuePtr data)
+     for (i = 0; i < virJSONValueArraySize(data); i++) {
+         if (qemuMonitorJSONParseCPUx86FeatureWord(virJSONValueArrayGet(data, i),
+                                                   &item.cpuid) < 0 ||
+-            virCPUx86DataAddCPUID(cpudata, &item) < 0)
++            virCPUx86DataAdd(cpudata, &item) < 0)
+             goto error;
+     }
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-cpu_x86-Rename-virCPUx86DataAddCPUIDInt.patch b/SOURCES/libvirt-cpu_x86-Rename-virCPUx86DataAddCPUIDInt.patch
new file mode 100644
index 0000000..fda0cf9
--- /dev/null
+++ b/SOURCES/libvirt-cpu_x86-Rename-virCPUx86DataAddCPUIDInt.patch
@@ -0,0 +1,107 @@
+From 39da1d7fe9d2bd12c10c40de62c36724556797be Mon Sep 17 00:00:00 2001
+Message-Id: <39da1d7fe9d2bd12c10c40de62c36724556797be@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:25:28 +0200
+Subject: [PATCH] cpu_x86: Rename virCPUx86DataAddCPUIDInt
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The new name is virCPUx86DataAddItem.
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit ce42042577ada2616a7b062f890677f9797c7bf9)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1697627
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <631af83ec447522318e8169b0b9ef607b764befa.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/cpu/cpu_x86.c | 20 ++++++++++----------
+ 1 file changed, 10 insertions(+), 10 deletions(-)
+
+diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
+index efb2a3bb07..7e077577d3 100644
+--- a/src/cpu/cpu_x86.c
++++ b/src/cpu/cpu_x86.c
+@@ -378,8 +378,8 @@ x86DataCopy(virCPUx86Data *dst, const virCPUx86Data *src)
+ 
+ 
+ static int
+-virCPUx86DataAddCPUIDInt(virCPUx86Data *data,
+-                         const virCPUx86DataItem *item)
++virCPUx86DataAddItem(virCPUx86Data *data,
++                     const virCPUx86DataItem *item)
+ {
+     virCPUx86DataItemPtr existing;
+ 
+@@ -412,7 +412,7 @@ x86DataAdd(virCPUx86Data *data1,
+         if (item1) {
+             x86cpuidSetBits(&item1->cpuid, &item2->cpuid);
+         } else {
+-            if (virCPUx86DataAddCPUIDInt(data1, item2) < 0)
++            if (virCPUx86DataAddItem(data1, item2) < 0)
+                 return -1;
+         }
+     }
+@@ -641,7 +641,7 @@ x86DataAddSignature(virCPUx86Data *data,
+ {
+     virCPUx86DataItem leaf1 = CPUID(.eax_in = 0x1, .eax = signature);
+ 
+-    return virCPUx86DataAddCPUIDInt(data, &leaf1);
++    return virCPUx86DataAddItem(data, &leaf1);
+ }
+ 
+ 
+@@ -948,7 +948,7 @@ x86FeatureParse(xmlXPathContextPtr ctxt,
+                            i, feature->name);
+             goto cleanup;
+         }
+-        if (virCPUx86DataAddCPUIDInt(&feature->data, &item))
++        if (virCPUx86DataAddItem(&feature->data, &item))
+             goto cleanup;
+     }
+ 
+@@ -1664,8 +1664,8 @@ x86Compute(virCPUDefPtr host,
+             goto error;
+ 
+         if (cpu->vendor && host_model->vendor &&
+-            virCPUx86DataAddCPUIDInt(&guest_model->data,
+-                                     &host_model->vendor->data) < 0)
++            virCPUx86DataAddItem(&guest_model->data,
++                                 &host_model->vendor->data) < 0)
+             goto error;
+ 
+         if (host_model->signatures &&
+@@ -2650,7 +2650,7 @@ virCPUx86Baseline(virCPUDefPtr *cpus,
+     }
+ 
+     if (vendor &&
+-        virCPUx86DataAddCPUIDInt(&base_model->data, &vendor->data) < 0)
++        virCPUx86DataAddItem(&base_model->data, &vendor->data) < 0)
+         goto error;
+ 
+     if (x86Decode(cpu, &base_model->data, models, modelName, migratable) < 0)
+@@ -2949,7 +2949,7 @@ virCPUx86Translate(virCPUDefPtr cpu,
+         goto cleanup;
+ 
+     if (model->vendor &&
+-        virCPUx86DataAddCPUIDInt(&model->data, &model->vendor->data) < 0)
++        virCPUx86DataAddItem(&model->data, &model->vendor->data) < 0)
+         goto cleanup;
+ 
+     if (model->signatures &&
+@@ -3080,7 +3080,7 @@ int
+ virCPUx86DataAddCPUID(virCPUDataPtr cpuData,
+                       const virCPUx86DataItem *item)
+ {
+-    return virCPUx86DataAddCPUIDInt(&cpuData->data.x86, item);
++    return virCPUx86DataAddItem(&cpuData->data.x86, item);
+ }
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-cpu_x86-Rename-virCPUx86DataItem-variables.patch b/SOURCES/libvirt-cpu_x86-Rename-virCPUx86DataItem-variables.patch
new file mode 100644
index 0000000..f2a826e
--- /dev/null
+++ b/SOURCES/libvirt-cpu_x86-Rename-virCPUx86DataItem-variables.patch
@@ -0,0 +1,328 @@
+From 74ecc2a0c728cf59279c61e1e9837423c72182e9 Mon Sep 17 00:00:00 2001
+Message-Id: <74ecc2a0c728cf59279c61e1e9837423c72182e9@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:25:24 +0200
+Subject: [PATCH] cpu_x86: Rename virCPUx86DataItem variables
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit 6c22b329d5bc592a390bd4d802c55a2a44af750e)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1697627
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <570635ac7fb5f7a6514072ee4b871eb4d08f65bc.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/cpu/cpu_x86.c | 128 +++++++++++++++++++++++-----------------------
+ 1 file changed, 64 insertions(+), 64 deletions(-)
+
+diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
+index 6e1fb37d20..74f4083aac 100644
+--- a/src/cpu/cpu_x86.c
++++ b/src/cpu/cpu_x86.c
+@@ -327,13 +327,13 @@ x86DataCpuidNext(virCPUx86DataIteratorPtr iterator)
+ 
+ static virCPUx86DataItemPtr
+ x86DataCpuid(const virCPUx86Data *data,
+-             const virCPUx86DataItem *cpuid)
++             const virCPUx86DataItem *item)
+ {
+     size_t i;
+ 
+     for (i = 0; i < data->len; i++) {
+-        if (data->items[i].cpuid.eax_in == cpuid->cpuid.eax_in &&
+-            data->items[i].cpuid.ecx_in == cpuid->cpuid.ecx_in)
++        if (data->items[i].cpuid.eax_in == item->cpuid.eax_in &&
++            data->items[i].cpuid.ecx_in == item->cpuid.ecx_in)
+             return data->items + i;
+     }
+ 
+@@ -379,15 +379,15 @@ x86DataCopy(virCPUx86Data *dst, const virCPUx86Data *src)
+ 
+ static int
+ virCPUx86DataAddCPUIDInt(virCPUx86Data *data,
+-                         const virCPUx86DataItem *cpuid)
++                         const virCPUx86DataItem *item)
+ {
+     virCPUx86DataItemPtr existing;
+ 
+-    if ((existing = x86DataCpuid(data, cpuid))) {
+-        x86cpuidSetBits(&existing->cpuid, &cpuid->cpuid);
++    if ((existing = x86DataCpuid(data, item))) {
++        x86cpuidSetBits(&existing->cpuid, &item->cpuid);
+     } else {
+         if (VIR_APPEND_ELEMENT_COPY(data->items, data->len,
+-                                    *((virCPUx86DataItemPtr)cpuid)) < 0)
++                                    *((virCPUx86DataItemPtr)item)) < 0)
+             return -1;
+ 
+         qsort(data->items, data->len,
+@@ -403,16 +403,16 @@ x86DataAdd(virCPUx86Data *data1,
+            const virCPUx86Data *data2)
+ {
+     virCPUx86DataIterator iter = virCPUx86DataIteratorInit(data2);
+-    virCPUx86DataItemPtr cpuid1;
+-    virCPUx86DataItemPtr cpuid2;
++    virCPUx86DataItemPtr item1;
++    virCPUx86DataItemPtr item2;
+ 
+-    while ((cpuid2 = x86DataCpuidNext(&iter))) {
+-        cpuid1 = x86DataCpuid(data1, cpuid2);
++    while ((item2 = x86DataCpuidNext(&iter))) {
++        item1 = x86DataCpuid(data1, item2);
+ 
+-        if (cpuid1) {
+-            x86cpuidSetBits(&cpuid1->cpuid, &cpuid2->cpuid);
++        if (item1) {
++            x86cpuidSetBits(&item1->cpuid, &item2->cpuid);
+         } else {
+-            if (virCPUx86DataAddCPUIDInt(data1, cpuid2) < 0)
++            if (virCPUx86DataAddCPUIDInt(data1, item2) < 0)
+                 return -1;
+         }
+     }
+@@ -426,12 +426,12 @@ x86DataSubtract(virCPUx86Data *data1,
+                 const virCPUx86Data *data2)
+ {
+     virCPUx86DataIterator iter = virCPUx86DataIteratorInit(data1);
+-    virCPUx86DataItemPtr cpuid1;
+-    virCPUx86DataItemPtr cpuid2;
++    virCPUx86DataItemPtr item1;
++    virCPUx86DataItemPtr item2;
+ 
+-    while ((cpuid1 = x86DataCpuidNext(&iter))) {
+-        if ((cpuid2 = x86DataCpuid(data2, cpuid1)))
+-            x86cpuidClearBits(&cpuid1->cpuid, &cpuid2->cpuid);
++    while ((item1 = x86DataCpuidNext(&iter))) {
++        if ((item2 = x86DataCpuid(data2, item1)))
++            x86cpuidClearBits(&item1->cpuid, &item2->cpuid);
+     }
+ }
+ 
+@@ -441,15 +441,15 @@ x86DataIntersect(virCPUx86Data *data1,
+                  const virCPUx86Data *data2)
+ {
+     virCPUx86DataIterator iter = virCPUx86DataIteratorInit(data1);
+-    virCPUx86DataItemPtr cpuid1;
+-    virCPUx86DataItemPtr cpuid2;
++    virCPUx86DataItemPtr item1;
++    virCPUx86DataItemPtr item2;
+ 
+-    while ((cpuid1 = x86DataCpuidNext(&iter))) {
+-        cpuid2 = x86DataCpuid(data2, cpuid1);
+-        if (cpuid2)
+-            x86cpuidAndBits(&cpuid1->cpuid, &cpuid2->cpuid);
++    while ((item1 = x86DataCpuidNext(&iter))) {
++        item2 = x86DataCpuid(data2, item1);
++        if (item2)
++            x86cpuidAndBits(&item1->cpuid, &item2->cpuid);
+         else
+-            x86cpuidClearBits(&cpuid1->cpuid, &cpuid1->cpuid);
++            x86cpuidClearBits(&item1->cpuid, &item1->cpuid);
+     }
+ }
+ 
+@@ -469,12 +469,12 @@ x86DataIsSubset(const virCPUx86Data *data,
+ {
+ 
+     virCPUx86DataIterator iter = virCPUx86DataIteratorInit((virCPUx86Data *)subset);
+-    const virCPUx86DataItem *cpuid;
+-    const virCPUx86DataItem *cpuidSubset;
++    const virCPUx86DataItem *item;
++    const virCPUx86DataItem *itemSubset;
+ 
+-    while ((cpuidSubset = x86DataCpuidNext(&iter))) {
+-        if (!(cpuid = x86DataCpuid(data, cpuidSubset)) ||
+-            !x86cpuidMatchMasked(&cpuid->cpuid, &cpuidSubset->cpuid))
++    while ((itemSubset = x86DataCpuidNext(&iter))) {
++        if (!(item = x86DataCpuid(data, itemSubset)) ||
++            !x86cpuidMatchMasked(&item->cpuid, &itemSubset->cpuid))
+             return false;
+     }
+ 
+@@ -509,14 +509,14 @@ static virCPUx86VendorPtr
+ x86DataToVendor(const virCPUx86Data *data,
+                 virCPUx86MapPtr map)
+ {
+-    virCPUx86DataItemPtr cpuid;
++    virCPUx86DataItemPtr item;
+     size_t i;
+ 
+     for (i = 0; i < map->nvendors; i++) {
+         virCPUx86VendorPtr vendor = map->vendors[i];
+-        if ((cpuid = x86DataCpuid(data, &vendor->data)) &&
+-            x86cpuidMatchMasked(&cpuid->cpuid, &vendor->data.cpuid)) {
+-            x86cpuidClearBits(&cpuid->cpuid, &vendor->data.cpuid);
++        if ((item = x86DataCpuid(data, &vendor->data)) &&
++            x86cpuidMatchMasked(&item->cpuid, &vendor->data.cpuid)) {
++            x86cpuidClearBits(&item->cpuid, &vendor->data.cpuid);
+             return vendor;
+         }
+     }
+@@ -626,12 +626,12 @@ static uint32_t
+ x86DataToSignature(const virCPUx86Data *data)
+ {
+     virCPUx86DataItem leaf1 = CPUID(.eax_in = 0x1);
+-    virCPUx86DataItemPtr cpuid;
++    virCPUx86DataItemPtr item;
+ 
+-    if (!(cpuid = x86DataCpuid(data, &leaf1)))
++    if (!(item = x86DataCpuid(data, &leaf1)))
+         return 0;
+ 
+-    return cpuid->cpuid.eax & SIGNATURE_MASK;
++    return item->cpuid.eax & SIGNATURE_MASK;
+ }
+ 
+ 
+@@ -639,9 +639,9 @@ static int
+ x86DataAddSignature(virCPUx86Data *data,
+                     uint32_t signature)
+ {
+-    virCPUx86DataItem cpuid = CPUID(.eax_in = 0x1, .eax = signature);
++    virCPUx86DataItem leaf1 = CPUID(.eax_in = 0x1, .eax = signature);
+ 
+-    return virCPUx86DataAddCPUIDInt(data, &cpuid);
++    return virCPUx86DataAddCPUIDInt(data, &leaf1);
+ }
+ 
+ 
+@@ -905,7 +905,7 @@ x86FeatureParse(xmlXPathContextPtr ctxt,
+     virCPUx86MapPtr map = data;
+     xmlNodePtr *nodes = NULL;
+     virCPUx86FeaturePtr feature;
+-    virCPUx86DataItem cpuid;
++    virCPUx86DataItem item;
+     size_t i;
+     int n;
+     char *str = NULL;
+@@ -942,13 +942,13 @@ x86FeatureParse(xmlXPathContextPtr ctxt,
+ 
+     for (i = 0; i < n; i++) {
+         ctxt->node = nodes[i];
+-        if (x86ParseCPUID(ctxt, &cpuid) < 0) {
++        if (x86ParseCPUID(ctxt, &item) < 0) {
+             virReportError(VIR_ERR_INTERNAL_ERROR,
+                            _("Invalid cpuid[%zu] in %s feature"),
+                            i, feature->name);
+             goto cleanup;
+         }
+-        if (virCPUx86DataAddCPUIDInt(&feature->data, &cpuid))
++        if (virCPUx86DataAddCPUIDInt(&feature->data, &item))
+             goto cleanup;
+     }
+ 
+@@ -1148,16 +1148,16 @@ x86ModelCompare(virCPUx86ModelPtr model1,
+     virCPUx86CompareResult result = EQUAL;
+     virCPUx86DataIterator iter1 = virCPUx86DataIteratorInit(&model1->data);
+     virCPUx86DataIterator iter2 = virCPUx86DataIteratorInit(&model2->data);
+-    virCPUx86DataItemPtr cpuid1;
+-    virCPUx86DataItemPtr cpuid2;
++    virCPUx86DataItemPtr item1;
++    virCPUx86DataItemPtr item2;
+ 
+-    while ((cpuid1 = x86DataCpuidNext(&iter1))) {
++    while ((item1 = x86DataCpuidNext(&iter1))) {
+         virCPUx86CompareResult match = SUPERSET;
+ 
+-        if ((cpuid2 = x86DataCpuid(&model2->data, cpuid1))) {
+-            if (x86cpuidMatch(&cpuid1->cpuid, &cpuid2->cpuid))
++        if ((item2 = x86DataCpuid(&model2->data, item1))) {
++            if (x86cpuidMatch(&item1->cpuid, &item2->cpuid))
+                 continue;
+-            else if (!x86cpuidMatchMasked(&cpuid1->cpuid, &cpuid2->cpuid))
++            else if (!x86cpuidMatchMasked(&item1->cpuid, &item2->cpuid))
+                 match = SUBSET;
+         }
+ 
+@@ -1167,13 +1167,13 @@ x86ModelCompare(virCPUx86ModelPtr model1,
+             return UNRELATED;
+     }
+ 
+-    while ((cpuid2 = x86DataCpuidNext(&iter2))) {
++    while ((item2 = x86DataCpuidNext(&iter2))) {
+         virCPUx86CompareResult match = SUBSET;
+ 
+-        if ((cpuid1 = x86DataCpuid(&model1->data, cpuid2))) {
+-            if (x86cpuidMatch(&cpuid2->cpuid, &cpuid1->cpuid))
++        if ((item1 = x86DataCpuid(&model1->data, item2))) {
++            if (x86cpuidMatch(&item2->cpuid, &item1->cpuid))
+                 continue;
+-            else if (!x86cpuidMatchMasked(&cpuid2->cpuid, &cpuid1->cpuid))
++            else if (!x86cpuidMatchMasked(&item2->cpuid, &item1->cpuid))
+                 match = SUPERSET;
+         }
+ 
+@@ -1484,7 +1484,7 @@ virCPUx86DataParse(xmlXPathContextPtr ctxt)
+ {
+     xmlNodePtr *nodes = NULL;
+     virCPUDataPtr cpuData = NULL;
+-    virCPUx86DataItem cpuid;
++    virCPUx86DataItem item;
+     size_t i;
+     int n;
+ 
+@@ -1500,12 +1500,12 @@ virCPUx86DataParse(xmlXPathContextPtr ctxt)
+ 
+     for (i = 0; i < n; i++) {
+         ctxt->node = nodes[i];
+-        if (x86ParseCPUID(ctxt, &cpuid) < 0) {
++        if (x86ParseCPUID(ctxt, &item) < 0) {
+             virReportError(VIR_ERR_INTERNAL_ERROR,
+                            _("failed to parse cpuid[%zu]"), i);
+             goto error;
+         }
+-        if (virCPUx86DataAddCPUID(cpuData, &cpuid) < 0)
++        if (virCPUx86DataAddCPUID(cpuData, &item) < 0)
+             goto error;
+     }
+ 
+@@ -2382,10 +2382,10 @@ cpuidSetLeaf12(virCPUDataPtr data,
+ {
+     virCPUx86DataItem item = CPUID(.eax_in = 0x7);
+     virCPUx86CPUIDPtr cpuid = &item.cpuid;
+-    virCPUx86DataItemPtr cpuid7;
++    virCPUx86DataItemPtr leaf7;
+ 
+-    if (!(cpuid7 = x86DataCpuid(&data->data.x86, &item)) ||
+-        !(cpuid7->cpuid.ebx & (1 << 2)))
++    if (!(leaf7 = x86DataCpuid(&data->data.x86, &item)) ||
++        !(leaf7->cpuid.ebx & (1 << 2)))
+         return 0;
+ 
+     if (virCPUx86DataAddCPUID(data, subLeaf0) < 0)
+@@ -3078,9 +3078,9 @@ virCPUx86ValidateFeatures(virCPUDefPtr cpu)
+ 
+ int
+ virCPUx86DataAddCPUID(virCPUDataPtr cpuData,
+-                      const virCPUx86DataItem *cpuid)
++                      const virCPUx86DataItem *item)
+ {
+-    return virCPUx86DataAddCPUIDInt(&cpuData->data.x86, cpuid);
++    return virCPUx86DataAddCPUIDInt(&cpuData->data.x86, item);
+ }
+ 
+ 
+@@ -3112,12 +3112,12 @@ int
+ virCPUx86DataSetVendor(virCPUDataPtr cpuData,
+                        const char *vendor)
+ {
+-    virCPUx86DataItem cpuid = CPUID(0);
++    virCPUx86DataItem item = CPUID(0);
+ 
+-    if (virCPUx86VendorToCPUID(vendor, &cpuid) < 0)
++    if (virCPUx86VendorToCPUID(vendor, &item) < 0)
+         return -1;
+ 
+-    return virCPUx86DataAddCPUID(cpuData, &cpuid);
++    return virCPUx86DataAddCPUID(cpuData, &item);
+ }
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-cpu_x86-Rename-virCPUx86Vendor.cpuid.patch b/SOURCES/libvirt-cpu_x86-Rename-virCPUx86Vendor.cpuid.patch
new file mode 100644
index 0000000..70186dc
--- /dev/null
+++ b/SOURCES/libvirt-cpu_x86-Rename-virCPUx86Vendor.cpuid.patch
@@ -0,0 +1,99 @@
+From 088d9da6e6c4f3edc0293f78ba7270941d2e7fd0 Mon Sep 17 00:00:00 2001
+Message-Id: <088d9da6e6c4f3edc0293f78ba7270941d2e7fd0@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:25:23 +0200
+Subject: [PATCH] cpu_x86: Rename virCPUx86Vendor.cpuid
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Although vendor string is always reported by CPUID, the container struct
+is used for consistency and thus "cpuid" name is not a good fit anymore.
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit c02d70d52efc4b7af09e68847ef72ad47a6bdcf1)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1697627
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <0b6fccb50f2ce2b5d926a75c90a8107a300c8d57.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/cpu/cpu_x86.c | 18 +++++++++---------
+ 1 file changed, 9 insertions(+), 9 deletions(-)
+
+diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
+index 2e953eaa12..6e1fb37d20 100644
+--- a/src/cpu/cpu_x86.c
++++ b/src/cpu/cpu_x86.c
+@@ -49,7 +49,7 @@ typedef struct _virCPUx86Vendor virCPUx86Vendor;
+ typedef virCPUx86Vendor *virCPUx86VendorPtr;
+ struct _virCPUx86Vendor {
+     char *name;
+-    virCPUx86DataItem cpuid;
++    virCPUx86DataItem data;
+ };
+ 
+ typedef struct _virCPUx86Feature virCPUx86Feature;
+@@ -514,9 +514,9 @@ x86DataToVendor(const virCPUx86Data *data,
+ 
+     for (i = 0; i < map->nvendors; i++) {
+         virCPUx86VendorPtr vendor = map->vendors[i];
+-        if ((cpuid = x86DataCpuid(data, &vendor->cpuid)) &&
+-            x86cpuidMatchMasked(&cpuid->cpuid, &vendor->cpuid.cpuid)) {
+-            x86cpuidClearBits(&cpuid->cpuid, &vendor->cpuid.cpuid);
++        if ((cpuid = x86DataCpuid(data, &vendor->data)) &&
++            x86cpuidMatchMasked(&cpuid->cpuid, &vendor->data.cpuid)) {
++            x86cpuidClearBits(&cpuid->cpuid, &vendor->data.cpuid);
+             return vendor;
+         }
+     }
+@@ -759,7 +759,7 @@ x86VendorParse(xmlXPathContextPtr ctxt,
+         goto cleanup;
+     }
+ 
+-    if (virCPUx86VendorToCPUID(string, &vendor->cpuid) < 0)
++    if (virCPUx86VendorToCPUID(string, &vendor->data) < 0)
+         goto cleanup;
+ 
+     if (VIR_APPEND_ELEMENT(map->vendors, map->nvendors, vendor) < 0)
+@@ -1665,7 +1665,7 @@ x86Compute(virCPUDefPtr host,
+ 
+         if (cpu->vendor && host_model->vendor &&
+             virCPUx86DataAddCPUIDInt(&guest_model->data,
+-                                     &host_model->vendor->cpuid) < 0)
++                                     &host_model->vendor->data) < 0)
+             goto error;
+ 
+         if (host_model->signatures &&
+@@ -2153,7 +2153,7 @@ x86Encode(virArch arch,
+         if (!(data_vendor = virCPUDataNew(arch)))
+             goto error;
+ 
+-        if (v && virCPUx86DataAddCPUID(data_vendor, &v->cpuid) < 0)
++        if (v && virCPUx86DataAddCPUID(data_vendor, &v->data) < 0)
+             goto error;
+     }
+ 
+@@ -2650,7 +2650,7 @@ virCPUx86Baseline(virCPUDefPtr *cpus,
+     }
+ 
+     if (vendor &&
+-        virCPUx86DataAddCPUIDInt(&base_model->data, &vendor->cpuid) < 0)
++        virCPUx86DataAddCPUIDInt(&base_model->data, &vendor->data) < 0)
+         goto error;
+ 
+     if (x86Decode(cpu, &base_model->data, models, modelName, migratable) < 0)
+@@ -2949,7 +2949,7 @@ virCPUx86Translate(virCPUDefPtr cpu,
+         goto cleanup;
+ 
+     if (model->vendor &&
+-        virCPUx86DataAddCPUIDInt(&model->data, &model->vendor->cpuid) < 0)
++        virCPUx86DataAddCPUIDInt(&model->data, &model->vendor->data) < 0)
+         goto cleanup;
+ 
+     if (model->signatures &&
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-cpu_x86-Rename-virCPUx86VendorToCPUID.patch b/SOURCES/libvirt-cpu_x86-Rename-virCPUx86VendorToCPUID.patch
new file mode 100644
index 0000000..59fdc0c
--- /dev/null
+++ b/SOURCES/libvirt-cpu_x86-Rename-virCPUx86VendorToCPUID.patch
@@ -0,0 +1,60 @@
+From c3573dbf60524401d06da6f6c5ce70a780494509 Mon Sep 17 00:00:00 2001
+Message-Id: <c3573dbf60524401d06da6f6c5ce70a780494509@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:25:30 +0200
+Subject: [PATCH] cpu_x86: Rename virCPUx86VendorToCPUID
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Renamed as virCPUx86VendorToData.
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit 3eff71a2d5048b30ded73bc6e542cbbd3e5b6193)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1697627
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <01af4e7922b394abeb1ea11856c188cb80ffb9a8.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/cpu/cpu_x86.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
+index 6d48c9264c..9c0f39e76d 100644
+--- a/src/cpu/cpu_x86.c
++++ b/src/cpu/cpu_x86.c
+@@ -526,8 +526,8 @@ x86DataToVendor(const virCPUx86Data *data,
+ 
+ 
+ static int
+-virCPUx86VendorToCPUID(const char *vendor,
+-                       virCPUx86DataItemPtr data)
++virCPUx86VendorToData(const char *vendor,
++                      virCPUx86DataItemPtr data)
+ {
+     virCPUx86CPUIDPtr cpuid = &data->cpuid;
+ 
+@@ -759,7 +759,7 @@ x86VendorParse(xmlXPathContextPtr ctxt,
+         goto cleanup;
+     }
+ 
+-    if (virCPUx86VendorToCPUID(string, &vendor->data) < 0)
++    if (virCPUx86VendorToData(string, &vendor->data) < 0)
+         goto cleanup;
+ 
+     if (VIR_APPEND_ELEMENT(map->vendors, map->nvendors, vendor) < 0)
+@@ -3114,7 +3114,7 @@ virCPUx86DataSetVendor(virCPUDataPtr cpuData,
+ {
+     virCPUx86DataItem item = CPUID(0);
+ 
+-    if (virCPUx86VendorToCPUID(vendor, &item) < 0)
++    if (virCPUx86VendorToData(vendor, &item) < 0)
+         return -1;
+ 
+     return virCPUx86DataAdd(cpuData, &item);
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-cpu_x86-Rename-x86DataCpuid.patch b/SOURCES/libvirt-cpu_x86-Rename-x86DataCpuid.patch
new file mode 100644
index 0000000..569167d
--- /dev/null
+++ b/SOURCES/libvirt-cpu_x86-Rename-x86DataCpuid.patch
@@ -0,0 +1,141 @@
+From 99431463aaf37298bc90f82bc6b20b44f4853246 Mon Sep 17 00:00:00 2001
+Message-Id: <99431463aaf37298bc90f82bc6b20b44f4853246@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:25:26 +0200
+Subject: [PATCH] cpu_x86: Rename x86DataCpuid
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+It is now called virCPUx86DataGet.
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit 609f467f1377da3418dad23fdd9f7136e462ba5b)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1697627
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <427e52b2993356d0170e2f756526e9d523686a42.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/cpu/cpu_x86.c | 26 +++++++++++++-------------
+ 1 file changed, 13 insertions(+), 13 deletions(-)
+
+diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
+index d9475e5b4a..52709f109e 100644
+--- a/src/cpu/cpu_x86.c
++++ b/src/cpu/cpu_x86.c
+@@ -326,8 +326,8 @@ virCPUx86DataNext(virCPUx86DataIteratorPtr iterator)
+ 
+ 
+ static virCPUx86DataItemPtr
+-x86DataCpuid(const virCPUx86Data *data,
+-             const virCPUx86DataItem *item)
++virCPUx86DataGet(const virCPUx86Data *data,
++                 const virCPUx86DataItem *item)
+ {
+     size_t i;
+ 
+@@ -383,7 +383,7 @@ virCPUx86DataAddCPUIDInt(virCPUx86Data *data,
+ {
+     virCPUx86DataItemPtr existing;
+ 
+-    if ((existing = x86DataCpuid(data, item))) {
++    if ((existing = virCPUx86DataGet(data, item))) {
+         x86cpuidSetBits(&existing->cpuid, &item->cpuid);
+     } else {
+         if (VIR_APPEND_ELEMENT_COPY(data->items, data->len,
+@@ -407,7 +407,7 @@ x86DataAdd(virCPUx86Data *data1,
+     virCPUx86DataItemPtr item2;
+ 
+     while ((item2 = virCPUx86DataNext(&iter))) {
+-        item1 = x86DataCpuid(data1, item2);
++        item1 = virCPUx86DataGet(data1, item2);
+ 
+         if (item1) {
+             x86cpuidSetBits(&item1->cpuid, &item2->cpuid);
+@@ -430,7 +430,7 @@ x86DataSubtract(virCPUx86Data *data1,
+     virCPUx86DataItemPtr item2;
+ 
+     while ((item1 = virCPUx86DataNext(&iter))) {
+-        if ((item2 = x86DataCpuid(data2, item1)))
++        if ((item2 = virCPUx86DataGet(data2, item1)))
+             x86cpuidClearBits(&item1->cpuid, &item2->cpuid);
+     }
+ }
+@@ -445,7 +445,7 @@ x86DataIntersect(virCPUx86Data *data1,
+     virCPUx86DataItemPtr item2;
+ 
+     while ((item1 = virCPUx86DataNext(&iter))) {
+-        item2 = x86DataCpuid(data2, item1);
++        item2 = virCPUx86DataGet(data2, item1);
+         if (item2)
+             x86cpuidAndBits(&item1->cpuid, &item2->cpuid);
+         else
+@@ -473,7 +473,7 @@ x86DataIsSubset(const virCPUx86Data *data,
+     const virCPUx86DataItem *itemSubset;
+ 
+     while ((itemSubset = virCPUx86DataNext(&iter))) {
+-        if (!(item = x86DataCpuid(data, itemSubset)) ||
++        if (!(item = virCPUx86DataGet(data, itemSubset)) ||
+             !x86cpuidMatchMasked(&item->cpuid, &itemSubset->cpuid))
+             return false;
+     }
+@@ -514,7 +514,7 @@ x86DataToVendor(const virCPUx86Data *data,
+ 
+     for (i = 0; i < map->nvendors; i++) {
+         virCPUx86VendorPtr vendor = map->vendors[i];
+-        if ((item = x86DataCpuid(data, &vendor->data)) &&
++        if ((item = virCPUx86DataGet(data, &vendor->data)) &&
+             x86cpuidMatchMasked(&item->cpuid, &vendor->data.cpuid)) {
+             x86cpuidClearBits(&item->cpuid, &vendor->data.cpuid);
+             return vendor;
+@@ -609,7 +609,7 @@ x86DataToSignatureFull(const virCPUx86Data *data,
+ 
+     *family = *model = *stepping = 0;
+ 
+-    if (!(item = x86DataCpuid(data, &leaf1)))
++    if (!(item = virCPUx86DataGet(data, &leaf1)))
+         return;
+ 
+     cpuid = &item->cpuid;
+@@ -628,7 +628,7 @@ x86DataToSignature(const virCPUx86Data *data)
+     virCPUx86DataItem leaf1 = CPUID(.eax_in = 0x1);
+     virCPUx86DataItemPtr item;
+ 
+-    if (!(item = x86DataCpuid(data, &leaf1)))
++    if (!(item = virCPUx86DataGet(data, &leaf1)))
+         return 0;
+ 
+     return item->cpuid.eax & SIGNATURE_MASK;
+@@ -1154,7 +1154,7 @@ x86ModelCompare(virCPUx86ModelPtr model1,
+     while ((item1 = virCPUx86DataNext(&iter1))) {
+         virCPUx86CompareResult match = SUPERSET;
+ 
+-        if ((item2 = x86DataCpuid(&model2->data, item1))) {
++        if ((item2 = virCPUx86DataGet(&model2->data, item1))) {
+             if (x86cpuidMatch(&item1->cpuid, &item2->cpuid))
+                 continue;
+             else if (!x86cpuidMatchMasked(&item1->cpuid, &item2->cpuid))
+@@ -1170,7 +1170,7 @@ x86ModelCompare(virCPUx86ModelPtr model1,
+     while ((item2 = virCPUx86DataNext(&iter2))) {
+         virCPUx86CompareResult match = SUBSET;
+ 
+-        if ((item1 = x86DataCpuid(&model1->data, item2))) {
++        if ((item1 = virCPUx86DataGet(&model1->data, item2))) {
+             if (x86cpuidMatch(&item2->cpuid, &item1->cpuid))
+                 continue;
+             else if (!x86cpuidMatchMasked(&item2->cpuid, &item1->cpuid))
+@@ -2384,7 +2384,7 @@ cpuidSetLeaf12(virCPUDataPtr data,
+     virCPUx86CPUIDPtr cpuid = &item.cpuid;
+     virCPUx86DataItemPtr leaf7;
+ 
+-    if (!(leaf7 = x86DataCpuid(&data->data.x86, &item)) ||
++    if (!(leaf7 = virCPUx86DataGet(&data->data.x86, &item)) ||
+         !(leaf7->cpuid.ebx & (1 << 2)))
+         return 0;
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-cpu_x86-Rename-x86DataCpuidNext-function.patch b/SOURCES/libvirt-cpu_x86-Rename-x86DataCpuidNext-function.patch
new file mode 100644
index 0000000..6dc883c
--- /dev/null
+++ b/SOURCES/libvirt-cpu_x86-Rename-x86DataCpuidNext-function.patch
@@ -0,0 +1,113 @@
+From ad4abf728510a5fed123d46a223f19f0b8178045 Mon Sep 17 00:00:00 2001
+Message-Id: <ad4abf728510a5fed123d46a223f19f0b8178045@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:25:25 +0200
+Subject: [PATCH] cpu_x86: Rename x86DataCpuidNext function
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The function is now called virCPUx86DataNext to reflect its purpose: it
+is an iterator over CPU data (both CPUID and MSR in the near future).
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit 5655b83139e47b6c52d48a7d10640bf3508865eb)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1697627
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <bcc496d392ff77d824f53460cacb0a7de0993785.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/cpu/cpu_x86.c | 18 +++++++++---------
+ 1 file changed, 9 insertions(+), 9 deletions(-)
+
+diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
+index 74f4083aac..d9475e5b4a 100644
+--- a/src/cpu/cpu_x86.c
++++ b/src/cpu/cpu_x86.c
+@@ -307,7 +307,7 @@ virCPUx86CPUIDSorter(const void *a, const void *b)
+ 
+ /* skips all zero CPUID leaves */
+ static virCPUx86DataItemPtr
+-x86DataCpuidNext(virCPUx86DataIteratorPtr iterator)
++virCPUx86DataNext(virCPUx86DataIteratorPtr iterator)
+ {
+     const virCPUx86Data *data = iterator->data;
+ 
+@@ -406,7 +406,7 @@ x86DataAdd(virCPUx86Data *data1,
+     virCPUx86DataItemPtr item1;
+     virCPUx86DataItemPtr item2;
+ 
+-    while ((item2 = x86DataCpuidNext(&iter))) {
++    while ((item2 = virCPUx86DataNext(&iter))) {
+         item1 = x86DataCpuid(data1, item2);
+ 
+         if (item1) {
+@@ -429,7 +429,7 @@ x86DataSubtract(virCPUx86Data *data1,
+     virCPUx86DataItemPtr item1;
+     virCPUx86DataItemPtr item2;
+ 
+-    while ((item1 = x86DataCpuidNext(&iter))) {
++    while ((item1 = virCPUx86DataNext(&iter))) {
+         if ((item2 = x86DataCpuid(data2, item1)))
+             x86cpuidClearBits(&item1->cpuid, &item2->cpuid);
+     }
+@@ -444,7 +444,7 @@ x86DataIntersect(virCPUx86Data *data1,
+     virCPUx86DataItemPtr item1;
+     virCPUx86DataItemPtr item2;
+ 
+-    while ((item1 = x86DataCpuidNext(&iter))) {
++    while ((item1 = virCPUx86DataNext(&iter))) {
+         item2 = x86DataCpuid(data2, item1);
+         if (item2)
+             x86cpuidAndBits(&item1->cpuid, &item2->cpuid);
+@@ -459,7 +459,7 @@ x86DataIsEmpty(virCPUx86Data *data)
+ {
+     virCPUx86DataIterator iter = virCPUx86DataIteratorInit(data);
+ 
+-    return !x86DataCpuidNext(&iter);
++    return !virCPUx86DataNext(&iter);
+ }
+ 
+ 
+@@ -472,7 +472,7 @@ x86DataIsSubset(const virCPUx86Data *data,
+     const virCPUx86DataItem *item;
+     const virCPUx86DataItem *itemSubset;
+ 
+-    while ((itemSubset = x86DataCpuidNext(&iter))) {
++    while ((itemSubset = virCPUx86DataNext(&iter))) {
+         if (!(item = x86DataCpuid(data, itemSubset)) ||
+             !x86cpuidMatchMasked(&item->cpuid, &itemSubset->cpuid))
+             return false;
+@@ -1151,7 +1151,7 @@ x86ModelCompare(virCPUx86ModelPtr model1,
+     virCPUx86DataItemPtr item1;
+     virCPUx86DataItemPtr item2;
+ 
+-    while ((item1 = x86DataCpuidNext(&iter1))) {
++    while ((item1 = virCPUx86DataNext(&iter1))) {
+         virCPUx86CompareResult match = SUPERSET;
+ 
+         if ((item2 = x86DataCpuid(&model2->data, item1))) {
+@@ -1167,7 +1167,7 @@ x86ModelCompare(virCPUx86ModelPtr model1,
+             return UNRELATED;
+     }
+ 
+-    while ((item2 = x86DataCpuidNext(&iter2))) {
++    while ((item2 = virCPUx86DataNext(&iter2))) {
+         virCPUx86CompareResult match = SUBSET;
+ 
+         if ((item1 = x86DataCpuid(&model1->data, item2))) {
+@@ -1461,7 +1461,7 @@ virCPUx86DataFormat(const virCPUData *data)
+     virBuffer buf = VIR_BUFFER_INITIALIZER;
+ 
+     virBufferAddLit(&buf, "<cpudata arch='x86'>\n");
+-    while ((item = x86DataCpuidNext(&iter))) {
++    while ((item = virCPUx86DataNext(&iter))) {
+         virCPUx86CPUIDPtr cpuid = &item->cpuid;
+         virBufferAsprintf(&buf,
+                           "  <cpuid eax_in='0x%08x' ecx_in='0x%08x'"
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-cpu_x86-Require-cpuid-within-feature-in-CPU-map.patch b/SOURCES/libvirt-cpu_x86-Require-cpuid-within-feature-in-CPU-map.patch
new file mode 100644
index 0000000..4986884
--- /dev/null
+++ b/SOURCES/libvirt-cpu_x86-Require-cpuid-within-feature-in-CPU-map.patch
@@ -0,0 +1,46 @@
+From c3148a408bd3c7ccf858bd5e0ac1139588847fc9 Mon Sep 17 00:00:00 2001
+Message-Id: <c3148a408bd3c7ccf858bd5e0ac1139588847fc9@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:25:19 +0200
+Subject: [PATCH] cpu_x86: Require <cpuid> within <feature> in CPU map
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+A feature with no cpuid element is invalid and it should not be silently
+treated as a feature with all CPUID bits set to zero.
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit dbc04114f3d14b53c999bd89db51276358b1aba3)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1697627
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <ea3bbf9cb28709fe52f43ce312c0171e2a62c1e8.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/cpu/cpu_x86.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
+index 66aa5a612c..98e8d608d6 100644
+--- a/src/cpu/cpu_x86.c
++++ b/src/cpu/cpu_x86.c
+@@ -923,6 +923,13 @@ x86FeatureParse(xmlXPathContextPtr ctxt,
+     if (n < 0)
+         goto cleanup;
+ 
++    if (n == 0) {
++        virReportError(VIR_ERR_INTERNAL_ERROR,
++                       _("Missing cpuid for feature %s"),
++                       feature->name);
++        goto cleanup;
++    }
++
+     for (i = 0; i < n; i++) {
+         ctxt->node = nodes[i];
+         if (x86ParseCPUID(ctxt, &cpuid) < 0) {
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-cpu_x86-Separate-ancestor-model-parsing-from-x86ModelParse.patch b/SOURCES/libvirt-cpu_x86-Separate-ancestor-model-parsing-from-x86ModelParse.patch
new file mode 100644
index 0000000..0571af1
--- /dev/null
+++ b/SOURCES/libvirt-cpu_x86-Separate-ancestor-model-parsing-from-x86ModelParse.patch
@@ -0,0 +1,110 @@
+From 4111804c77930ebcda4fa5fae751074f75da4f1c Mon Sep 17 00:00:00 2001
+Message-Id: <4111804c77930ebcda4fa5fae751074f75da4f1c@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:24:54 +0200
+Subject: [PATCH] cpu_x86: Separate ancestor model parsing from x86ModelParse
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The code is separated into a new x86ModelParseAncestor function.
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit 2e1e2b910c6a9d31f2fb6d388ed72dc8f561b845)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1686895
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <0e941dce0077eb7d7a31dffa60f7d647d66b95e6.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/cpu/cpu_x86.c | 65 +++++++++++++++++++++++++++--------------------
+ 1 file changed, 38 insertions(+), 27 deletions(-)
+
+diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
+index ce48ca6867..64788d60b3 100644
+--- a/src/cpu/cpu_x86.c
++++ b/src/cpu/cpu_x86.c
+@@ -1148,6 +1148,42 @@ x86ModelCompare(virCPUx86ModelPtr model1,
+ }
+ 
+ 
++static int
++x86ModelParseAncestor(virCPUx86ModelPtr model,
++                      xmlXPathContextPtr ctxt,
++                      virCPUx86MapPtr map)
++{
++    VIR_AUTOFREE(char *) name = NULL;
++    virCPUx86ModelPtr ancestor;
++    int rc;
++
++    if ((rc = virXPathBoolean("boolean(./model)", ctxt)) <= 0)
++        return rc;
++
++    name = virXPathString("string(./model/@name)", ctxt);
++    if (!name) {
++        virReportError(VIR_ERR_INTERNAL_ERROR,
++                       _("Missing ancestor's name in CPU model %s"),
++                       model->name);
++        return -1;
++    }
++
++    if (!(ancestor = x86ModelFind(map, name))) {
++        virReportError(VIR_ERR_INTERNAL_ERROR,
++                       _("Ancestor model %s not found for CPU model %s"),
++                       name, model->name);
++        return -1;
++    }
++
++    model->vendor = ancestor->vendor;
++    model->signature = ancestor->signature;
++    if (x86DataCopy(&model->data, &ancestor->data) < 0)
++        return -1;
++
++    return 0;
++}
++
++
+ static int
+ x86ModelParse(xmlXPathContextPtr ctxt,
+               const char *name,
+@@ -1167,33 +1203,8 @@ x86ModelParse(xmlXPathContextPtr ctxt,
+     if (VIR_STRDUP(model->name, name) < 0)
+         goto cleanup;
+ 
+-    if (virXPathNode("./model", ctxt)) {
+-        virCPUx86ModelPtr ancestor;
+-        char *anname;
+-
+-        anname = virXPathString("string(./model/@name)", ctxt);
+-        if (!anname) {
+-            virReportError(VIR_ERR_INTERNAL_ERROR,
+-                           _("Missing ancestor's name in CPU model %s"),
+-                           model->name);
+-            goto cleanup;
+-        }
+-
+-        if (!(ancestor = x86ModelFind(map, anname))) {
+-            virReportError(VIR_ERR_INTERNAL_ERROR,
+-                           _("Ancestor model %s not found for CPU model %s"),
+-                           anname, model->name);
+-            VIR_FREE(anname);
+-            goto cleanup;
+-        }
+-
+-        VIR_FREE(anname);
+-
+-        model->vendor = ancestor->vendor;
+-        model->signature = ancestor->signature;
+-        if (x86DataCopy(&model->data, &ancestor->data) < 0)
+-            goto cleanup;
+-    }
++    if (x86ModelParseAncestor(model, ctxt, map) < 0)
++        goto cleanup;
+ 
+     if (virXPathBoolean("boolean(./signature)", ctxt)) {
+         unsigned int sigFamily = 0;
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-cpu_x86-Separate-feature-list-parsing-from-x86ModelParse.patch b/SOURCES/libvirt-cpu_x86-Separate-feature-list-parsing-from-x86ModelParse.patch
new file mode 100644
index 0000000..9c70ab3
--- /dev/null
+++ b/SOURCES/libvirt-cpu_x86-Separate-feature-list-parsing-from-x86ModelParse.patch
@@ -0,0 +1,129 @@
+From 8d2f5155be8834db501930716e2cd2e1be14785c Mon Sep 17 00:00:00 2001
+Message-Id: <8d2f5155be8834db501930716e2cd2e1be14785c@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:24:57 +0200
+Subject: [PATCH] cpu_x86: Separate feature list parsing from x86ModelParse
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The code is separated into a new x86ModelParseFeatures function.
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit 8d249df9c917040d180202343e5cf7f70c3e4fe1)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1686895
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <5a741350b39394a93aee99a3b98142548936bc2d.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/cpu/cpu_x86.c | 68 +++++++++++++++++++++++++++--------------------
+ 1 file changed, 39 insertions(+), 29 deletions(-)
+
+diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
+index 62894cae9b..91362198ab 100644
+--- a/src/cpu/cpu_x86.c
++++ b/src/cpu/cpu_x86.c
+@@ -1247,16 +1247,51 @@ x86ModelParseVendor(virCPUx86ModelPtr model,
+ }
+ 
+ 
++static int
++x86ModelParseFeatures(virCPUx86ModelPtr model,
++                      xmlXPathContextPtr ctxt,
++                      virCPUx86MapPtr map)
++{
++    VIR_AUTOFREE(xmlNodePtr *) nodes = NULL;
++    size_t i;
++    int n;
++
++    if ((n = virXPathNodeSet("./feature", ctxt, &nodes)) <= 0)
++        return n;
++
++    for (i = 0; i < n; i++) {
++        VIR_AUTOFREE(char *) ftname = NULL;
++        virCPUx86FeaturePtr feature;
++
++        if (!(ftname = virXMLPropString(nodes[i], "name"))) {
++            virReportError(VIR_ERR_INTERNAL_ERROR,
++                           _("Missing feature name for CPU model %s"),
++                           model->name);
++            return -1;
++        }
++
++        if (!(feature = x86FeatureFind(map, ftname))) {
++            virReportError(VIR_ERR_INTERNAL_ERROR,
++                           _("Feature %s required by CPU model %s not found"),
++                           ftname, model->name);
++            return -1;
++        }
++
++        if (x86DataAdd(&model->data, &feature->data))
++            return -1;
++    }
++
++    return 0;
++}
++
++
+ static int
+ x86ModelParse(xmlXPathContextPtr ctxt,
+               const char *name,
+               void *data)
+ {
+     virCPUx86MapPtr map = data;
+-    xmlNodePtr *nodes = NULL;
+     virCPUx86ModelPtr model;
+-    size_t i;
+-    int n;
+     int ret = -1;
+ 
+     if (!(model = x86ModelNew()))
+@@ -1274,33 +1309,9 @@ x86ModelParse(xmlXPathContextPtr ctxt,
+     if (x86ModelParseVendor(model, ctxt, map) < 0)
+         goto cleanup;
+ 
+-    n = virXPathNodeSet("./feature", ctxt, &nodes);
+-    if (n < 0)
++    if (x86ModelParseFeatures(model, ctxt, map) < 0)
+         goto cleanup;
+ 
+-    for (i = 0; i < n; i++) {
+-        virCPUx86FeaturePtr feature;
+-        char *ftname;
+-
+-        if (!(ftname = virXMLPropString(nodes[i], "name"))) {
+-            virReportError(VIR_ERR_INTERNAL_ERROR,
+-                           _("Missing feature name for CPU model %s"), model->name);
+-            goto cleanup;
+-        }
+-
+-        if (!(feature = x86FeatureFind(map, ftname))) {
+-            virReportError(VIR_ERR_INTERNAL_ERROR,
+-                           _("Feature %s required by CPU model %s not found"),
+-                           ftname, model->name);
+-            VIR_FREE(ftname);
+-            goto cleanup;
+-        }
+-        VIR_FREE(ftname);
+-
+-        if (x86DataAdd(&model->data, &feature->data))
+-            goto cleanup;
+-    }
+-
+     if (VIR_APPEND_ELEMENT(map->models, map->nmodels, model) < 0)
+         goto cleanup;
+ 
+@@ -1308,7 +1319,6 @@ x86ModelParse(xmlXPathContextPtr ctxt,
+ 
+  cleanup:
+     x86ModelFree(model);
+-    VIR_FREE(nodes);
+     return ret;
+ }
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-cpu_x86-Separate-signature-parsing-from-x86ModelParse.patch b/SOURCES/libvirt-cpu_x86-Separate-signature-parsing-from-x86ModelParse.patch
new file mode 100644
index 0000000..e149723
--- /dev/null
+++ b/SOURCES/libvirt-cpu_x86-Separate-signature-parsing-from-x86ModelParse.patch
@@ -0,0 +1,103 @@
+From e7b8b38fe1fe7e7d8eb9fab6cb3ded16652f60f8 Mon Sep 17 00:00:00 2001
+Message-Id: <e7b8b38fe1fe7e7d8eb9fab6cb3ded16652f60f8@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:24:55 +0200
+Subject: [PATCH] cpu_x86: Separate signature parsing from x86ModelParse
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The code is separated into a new x86ModelParseSignature function.
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit fe78d2fda9f2dd67eb9daa98e48fbffa468d271e)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1686895
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <616b60991bfdaa735804b839e258f6f1fa409a7b.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/cpu/cpu_x86.c | 58 ++++++++++++++++++++++++++++-------------------
+ 1 file changed, 35 insertions(+), 23 deletions(-)
+
+diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
+index 64788d60b3..119ece4758 100644
+--- a/src/cpu/cpu_x86.c
++++ b/src/cpu/cpu_x86.c
+@@ -1184,6 +1184,39 @@ x86ModelParseAncestor(virCPUx86ModelPtr model,
+ }
+ 
+ 
++static int
++x86ModelParseSignature(virCPUx86ModelPtr model,
++                       xmlXPathContextPtr ctxt)
++{
++
++    if (virXPathBoolean("boolean(./signature)", ctxt)) {
++        unsigned int sigFamily = 0;
++        unsigned int sigModel = 0;
++        int rc;
++
++        rc = virXPathUInt("string(./signature/@family)", ctxt, &sigFamily);
++        if (rc < 0 || sigFamily == 0) {
++            virReportError(VIR_ERR_INTERNAL_ERROR,
++                           _("Invalid CPU signature family in model %s"),
++                           model->name);
++            return -1;
++        }
++
++        rc = virXPathUInt("string(./signature/@model)", ctxt, &sigModel);
++        if (rc < 0 || sigModel == 0) {
++            virReportError(VIR_ERR_INTERNAL_ERROR,
++                           _("Invalid CPU signature model in model %s"),
++                           model->name);
++            return -1;
++        }
++
++        model->signature = x86MakeSignature(sigFamily, sigModel, 0);
++    }
++
++    return 0;
++}
++
++
+ static int
+ x86ModelParse(xmlXPathContextPtr ctxt,
+               const char *name,
+@@ -1206,29 +1239,8 @@ x86ModelParse(xmlXPathContextPtr ctxt,
+     if (x86ModelParseAncestor(model, ctxt, map) < 0)
+         goto cleanup;
+ 
+-    if (virXPathBoolean("boolean(./signature)", ctxt)) {
+-        unsigned int sigFamily = 0;
+-        unsigned int sigModel = 0;
+-        int rc;
+-
+-        rc = virXPathUInt("string(./signature/@family)", ctxt, &sigFamily);
+-        if (rc < 0 || sigFamily == 0) {
+-            virReportError(VIR_ERR_INTERNAL_ERROR,
+-                           _("Invalid CPU signature family in model %s"),
+-                           model->name);
+-            goto cleanup;
+-        }
+-
+-        rc = virXPathUInt("string(./signature/@model)", ctxt, &sigModel);
+-        if (rc < 0 || sigModel == 0) {
+-            virReportError(VIR_ERR_INTERNAL_ERROR,
+-                           _("Invalid CPU signature model in model %s"),
+-                           model->name);
+-            goto cleanup;
+-        }
+-
+-        model->signature = x86MakeSignature(sigFamily, sigModel, 0);
+-    }
++    if (x86ModelParseSignature(model, ctxt) < 0)
++        goto cleanup;
+ 
+     if (virXPathBoolean("boolean(./vendor)", ctxt)) {
+         vendor = virXPathString("string(./vendor/@name)", ctxt);
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-cpu_x86-Separate-vendor-parsing-from-x86ModelParse.patch b/SOURCES/libvirt-cpu_x86-Separate-vendor-parsing-from-x86ModelParse.patch
new file mode 100644
index 0000000..5e06bc9
--- /dev/null
+++ b/SOURCES/libvirt-cpu_x86-Separate-vendor-parsing-from-x86ModelParse.patch
@@ -0,0 +1,109 @@
+From e1b42297bc41c8f356693f2756e806a8c7275f4f Mon Sep 17 00:00:00 2001
+Message-Id: <e1b42297bc41c8f356693f2756e806a8c7275f4f@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:24:56 +0200
+Subject: [PATCH] cpu_x86: Separate vendor parsing from x86ModelParse
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The code is separated into a new x86ModelParseVendor function.
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit 232266839c994dcf2958f1efdfe74cfb7973a749)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1686895
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <aaa0e5fac04ccd7b267e6912ceb3308249d9217e.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/cpu/cpu_x86.c | 50 ++++++++++++++++++++++++++++++-----------------
+ 1 file changed, 32 insertions(+), 18 deletions(-)
+
+diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
+index 119ece4758..62894cae9b 100644
+--- a/src/cpu/cpu_x86.c
++++ b/src/cpu/cpu_x86.c
+@@ -1217,6 +1217,36 @@ x86ModelParseSignature(virCPUx86ModelPtr model,
+ }
+ 
+ 
++static int
++x86ModelParseVendor(virCPUx86ModelPtr model,
++                    xmlXPathContextPtr ctxt,
++                    virCPUx86MapPtr map)
++{
++    VIR_AUTOFREE(char *) vendor = NULL;
++    int rc;
++
++    if ((rc = virXPathBoolean("boolean(./vendor)", ctxt)) <= 0)
++        return rc;
++
++    vendor = virXPathString("string(./vendor/@name)", ctxt);
++    if (!vendor) {
++        virReportError(VIR_ERR_INTERNAL_ERROR,
++                       _("Invalid vendor element in CPU model %s"),
++                       model->name);
++        return -1;
++    }
++
++    if (!(model->vendor = x86VendorFind(map, vendor))) {
++        virReportError(VIR_ERR_INTERNAL_ERROR,
++                       _("Unknown vendor %s referenced by CPU model %s"),
++                       vendor, model->name);
++        return -1;
++    }
++
++    return 0;
++}
++
++
+ static int
+ x86ModelParse(xmlXPathContextPtr ctxt,
+               const char *name,
+@@ -1225,7 +1255,6 @@ x86ModelParse(xmlXPathContextPtr ctxt,
+     virCPUx86MapPtr map = data;
+     xmlNodePtr *nodes = NULL;
+     virCPUx86ModelPtr model;
+-    char *vendor = NULL;
+     size_t i;
+     int n;
+     int ret = -1;
+@@ -1242,22 +1271,8 @@ x86ModelParse(xmlXPathContextPtr ctxt,
+     if (x86ModelParseSignature(model, ctxt) < 0)
+         goto cleanup;
+ 
+-    if (virXPathBoolean("boolean(./vendor)", ctxt)) {
+-        vendor = virXPathString("string(./vendor/@name)", ctxt);
+-        if (!vendor) {
+-            virReportError(VIR_ERR_INTERNAL_ERROR,
+-                           _("Invalid vendor element in CPU model %s"),
+-                           model->name);
+-            goto cleanup;
+-        }
+-
+-        if (!(model->vendor = x86VendorFind(map, vendor))) {
+-            virReportError(VIR_ERR_INTERNAL_ERROR,
+-                           _("Unknown vendor %s referenced by CPU model %s"),
+-                           vendor, model->name);
+-            goto cleanup;
+-        }
+-    }
++    if (x86ModelParseVendor(model, ctxt, map) < 0)
++        goto cleanup;
+ 
+     n = virXPathNodeSet("./feature", ctxt, &nodes);
+     if (n < 0)
+@@ -1293,7 +1308,6 @@ x86ModelParse(xmlXPathContextPtr ctxt,
+ 
+  cleanup:
+     x86ModelFree(model);
+-    VIR_FREE(vendor);
+     VIR_FREE(nodes);
+     return ret;
+ }
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-cpu_x86-Simplify-x86DataAdd.patch b/SOURCES/libvirt-cpu_x86-Simplify-x86DataAdd.patch
new file mode 100644
index 0000000..dea6e6d
--- /dev/null
+++ b/SOURCES/libvirt-cpu_x86-Simplify-x86DataAdd.patch
@@ -0,0 +1,54 @@
+From ed7c9cb6444ec9344ebb253eac417703c5371c2d Mon Sep 17 00:00:00 2001
+Message-Id: <ed7c9cb6444ec9344ebb253eac417703c5371c2d@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:25:31 +0200
+Subject: [PATCH] cpu_x86: Simplify x86DataAdd
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The while loop just copied half of virCPUx86DataAddItem.
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit 0fdc0ad84c7ea27480f6f4edb82389d414584ada)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1697627
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <8ffc18c0ee7c61e5e1ce1af023ee7e6c62726f5a.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/cpu/cpu_x86.c | 15 ++++-----------
+ 1 file changed, 4 insertions(+), 11 deletions(-)
+
+diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
+index 9c0f39e76d..0582be63e2 100644
+--- a/src/cpu/cpu_x86.c
++++ b/src/cpu/cpu_x86.c
+@@ -403,18 +403,11 @@ x86DataAdd(virCPUx86Data *data1,
+            const virCPUx86Data *data2)
+ {
+     virCPUx86DataIterator iter = virCPUx86DataIteratorInit(data2);
+-    virCPUx86DataItemPtr item1;
+-    virCPUx86DataItemPtr item2;
++    virCPUx86DataItemPtr item;
+ 
+-    while ((item2 = virCPUx86DataNext(&iter))) {
+-        item1 = virCPUx86DataGet(data1, item2);
+-
+-        if (item1) {
+-            x86cpuidSetBits(&item1->cpuid, &item2->cpuid);
+-        } else {
+-            if (virCPUx86DataAddItem(data1, item2) < 0)
+-                return -1;
+-        }
++    while ((item = virCPUx86DataNext(&iter))) {
++        if (virCPUx86DataAddItem(data1, item) < 0)
++            return -1;
+     }
+ 
+     return 0;
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-cpu_x86-Store-CPU-signature-in-an-array.patch b/SOURCES/libvirt-cpu_x86-Store-CPU-signature-in-an-array.patch
new file mode 100644
index 0000000..4b951ef
--- /dev/null
+++ b/SOURCES/libvirt-cpu_x86-Store-CPU-signature-in-an-array.patch
@@ -0,0 +1,161 @@
+From c7a8133cbe9d0612db2889038079d260c3a8334f Mon Sep 17 00:00:00 2001
+Message-Id: <c7a8133cbe9d0612db2889038079d260c3a8334f@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:25:00 +0200
+Subject: [PATCH] cpu_x86: Store CPU signature in an array
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+In preparation for storing several CPU signatures in a single CPU model,
+we need to turn virCPUx86Model's signature into an array of signatures.
+
+The parser still hardcodes the number of signatures to 1, but the
+following patch will drop this limit.
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit b07b8b7750c6a505d4b00bd272e79ea0305cb610)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1686895
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <1d24aad1c6b9aa8142a2e882511f52a41fbaff67.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/cpu/cpu_x86.c | 50 ++++++++++++++++++++++++++++++++++++++---------
+ 1 file changed, 41 insertions(+), 9 deletions(-)
+
+diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
+index e25bc691ae..f8b8d8a96b 100644
+--- a/src/cpu/cpu_x86.c
++++ b/src/cpu/cpu_x86.c
+@@ -145,7 +145,8 @@ typedef virCPUx86Model *virCPUx86ModelPtr;
+ struct _virCPUx86Model {
+     char *name;
+     virCPUx86VendorPtr vendor;
+-    uint32_t signature;
++    size_t nsignatures;
++    uint32_t *signatures;
+     virCPUx86Data data;
+ };
+ 
+@@ -972,6 +973,7 @@ x86ModelFree(virCPUx86ModelPtr model)
+         return;
+ 
+     VIR_FREE(model->name);
++    VIR_FREE(model->signatures);
+     virCPUx86DataClear(&model->data);
+     VIR_FREE(model);
+ }
+@@ -981,7 +983,14 @@ static int
+ x86ModelCopySignatures(virCPUx86ModelPtr dst,
+                        virCPUx86ModelPtr src)
+ {
+-    dst->signature = src->signature;
++    size_t i;
++
++    if (VIR_ALLOC_N(dst->signatures, src->nsignatures) < 0)
++        return -1;
++
++    dst->nsignatures = src->nsignatures;
++    for (i = 0; i < src->nsignatures; i++)
++        dst->signatures[i] = src->signatures[i];
+ 
+     return 0;
+ }
+@@ -1198,12 +1207,18 @@ static int
+ x86ModelParseSignature(virCPUx86ModelPtr model,
+                        xmlXPathContextPtr ctxt)
+ {
++    /* Remove inherited signatures. */
++    VIR_FREE(model->signatures);
+ 
+     if (virXPathBoolean("boolean(./signature)", ctxt)) {
+         unsigned int sigFamily = 0;
+         unsigned int sigModel = 0;
+         int rc;
+ 
++        model->nsignatures = 1;
++        if (VIR_ALLOC_N(model->signatures, 1) < 0)
++            return -1;
++
+         rc = virXPathUInt("string(./signature/@family)", ctxt, &sigFamily);
+         if (rc < 0 || sigFamily == 0) {
+             virReportError(VIR_ERR_INTERNAL_ERROR,
+@@ -1220,7 +1235,7 @@ x86ModelParseSignature(virCPUx86ModelPtr model,
+             return -1;
+         }
+ 
+-        model->signature = x86MakeSignature(sigFamily, sigModel, 0);
++        model->signatures[0] = x86MakeSignature(sigFamily, sigModel, 0);
+     }
+ 
+     return 0;
+@@ -1621,7 +1636,8 @@ x86Compute(virCPUDefPtr host,
+                                      &host_model->vendor->cpuid) < 0)
+             goto error;
+ 
+-        if (x86DataAddSignature(&guest_model->data, host_model->signature) < 0)
++        if (host_model->signatures &&
++            x86DataAddSignature(&guest_model->data, *host_model->signatures) < 0)
+             goto error;
+ 
+         if (cpu->type == VIR_CPU_TYPE_GUEST
+@@ -1727,6 +1743,21 @@ virCPUx86Compare(virCPUDefPtr host,
+ }
+ 
+ 
++static bool
++x86ModelHasSignature(virCPUx86ModelPtr model,
++                     uint32_t signature)
++{
++    size_t i;
++
++    for (i = 0; i < model->nsignatures; i++) {
++        if (model->signatures[i] == signature)
++            return true;
++    }
++
++    return false;
++}
++
++
+ /*
+  * Checks whether a candidate model is a better fit for the CPU data than the
+  * current model.
+@@ -1768,8 +1799,8 @@ x86DecodeUseCandidate(virCPUx86ModelPtr current,
+      * consider candidates with matching family/model.
+      */
+     if (signature &&
+-        current->signature == signature &&
+-        candidate->signature != signature) {
++        x86ModelHasSignature(current, signature) &&
++        !x86ModelHasSignature(candidate, signature)) {
+         VIR_DEBUG("%s differs in signature from matching %s",
+                   cpuCandidate->model, cpuCurrent->model);
+         return 0;
+@@ -1785,8 +1816,8 @@ x86DecodeUseCandidate(virCPUx86ModelPtr current,
+      * result in longer list of features.
+      */
+     if (signature &&
+-        candidate->signature == signature &&
+-        current->signature != signature) {
++        x86ModelHasSignature(candidate, signature) &&
++        !x86ModelHasSignature(current, signature)) {
+         VIR_DEBUG("%s provides matching signature", cpuCandidate->model);
+         return 1;
+     }
+@@ -2854,7 +2885,8 @@ virCPUx86Translate(virCPUDefPtr cpu,
+         virCPUx86DataAddCPUIDInt(&model->data, &model->vendor->cpuid) < 0)
+         goto cleanup;
+ 
+-    if (x86DataAddSignature(&model->data, model->signature) < 0)
++    if (model->signatures &&
++        x86DataAddSignature(&model->data, model->signatures[0]) < 0)
+         goto cleanup;
+ 
+     if (!(translated = virCPUDefCopyWithoutModel(cpu)))
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-cpu_x86-Store-virCPUx86DataItem-content-in-union.patch b/SOURCES/libvirt-cpu_x86-Store-virCPUx86DataItem-content-in-union.patch
new file mode 100644
index 0000000..e6a0f2f
--- /dev/null
+++ b/SOURCES/libvirt-cpu_x86-Store-virCPUx86DataItem-content-in-union.patch
@@ -0,0 +1,487 @@
+From c465e315637d0b2cf01d2957de3d816186e0fd0f Mon Sep 17 00:00:00 2001
+Message-Id: <c465e315637d0b2cf01d2957de3d816186e0fd0f@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:25:38 +0200
+Subject: [PATCH] cpu_x86: Store virCPUx86DataItem content in union
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The structure can only be used for CPUID data now. Adding a type
+indicator and moving the data into a union will let us store alternative
+data types.
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit 370177e2f6784319b2fc86d8fe7a271248a5982e)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1697627
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <00cf7daca0cde66e9a90f64435182ef430983b2e.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/cpu/cpu_x86.c              | 202 ++++++++++++++++++++++++---------
+ src/cpu/cpu_x86_data.h         |  10 +-
+ src/libxl/libxl_capabilities.c |   3 +-
+ src/qemu/qemu_monitor_json.c   |   3 +-
+ 4 files changed, 160 insertions(+), 58 deletions(-)
+
+diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
+index 11c023ac31..e6da974b31 100644
+--- a/src/cpu/cpu_x86.c
++++ b/src/cpu/cpu_x86.c
+@@ -59,7 +59,9 @@ struct _virCPUx86Feature {
+ };
+ 
+ 
+-#define CPUID(...) { .cpuid = {__VA_ARGS__} }
++#define CPUID(...) \
++    { .type = VIR_CPU_X86_DATA_CPUID, \
++      .data = { .cpuid = {__VA_ARGS__} } }
+ 
+ #define KVM_FEATURE_DEF(Name, Eax_in, Eax) \
+     static virCPUx86DataItem Name ## _data[] = { \
+@@ -193,10 +195,22 @@ static bool
+ virCPUx86DataItemMatch(const virCPUx86DataItem *item1,
+                        const virCPUx86DataItem *item2)
+ {
+-    return (item1->cpuid.eax == item2->cpuid.eax &&
+-            item1->cpuid.ebx == item2->cpuid.ebx &&
+-            item1->cpuid.ecx == item2->cpuid.ecx &&
+-            item1->cpuid.edx == item2->cpuid.edx);
++    const virCPUx86CPUID *cpuid1;
++    const virCPUx86CPUID *cpuid2;
++
++    switch (item1->type) {
++    case VIR_CPU_X86_DATA_CPUID:
++        cpuid1 = &item1->data.cpuid;
++        cpuid2 = &item2->data.cpuid;
++        return (cpuid1->eax == cpuid2->eax &&
++                cpuid1->ebx == cpuid2->ebx &&
++                cpuid1->ecx == cpuid2->ecx &&
++                cpuid1->edx == cpuid2->edx);
++
++    case VIR_CPU_X86_DATA_NONE:
++    default:
++        return false;
++    }
+ }
+ 
+ 
+@@ -204,10 +218,22 @@ static bool
+ virCPUx86DataItemMatchMasked(const virCPUx86DataItem *item,
+                              const virCPUx86DataItem *mask)
+ {
+-    return ((item->cpuid.eax & mask->cpuid.eax) == mask->cpuid.eax &&
+-            (item->cpuid.ebx & mask->cpuid.ebx) == mask->cpuid.ebx &&
+-            (item->cpuid.ecx & mask->cpuid.ecx) == mask->cpuid.ecx &&
+-            (item->cpuid.edx & mask->cpuid.edx) == mask->cpuid.edx);
++    const virCPUx86CPUID *cpuid;
++    const virCPUx86CPUID *cpuidMask;
++
++    switch (item->type) {
++    case VIR_CPU_X86_DATA_CPUID:
++        cpuid = &item->data.cpuid;
++        cpuidMask = &mask->data.cpuid;
++        return ((cpuid->eax & cpuidMask->eax) == cpuidMask->eax &&
++                (cpuid->ebx & cpuidMask->ebx) == cpuidMask->ebx &&
++                (cpuid->ecx & cpuidMask->ecx) == cpuidMask->ecx &&
++                (cpuid->edx & cpuidMask->edx) == cpuidMask->edx);
++
++    case VIR_CPU_X86_DATA_NONE:
++    default:
++        return false;
++    }
+ }
+ 
+ 
+@@ -215,13 +241,26 @@ static void
+ virCPUx86DataItemSetBits(virCPUx86DataItemPtr item,
+                          const virCPUx86DataItem *mask)
+ {
++    virCPUx86CPUIDPtr cpuid;
++    const virCPUx86CPUID *cpuidMask;
++
+     if (!mask)
+         return;
+ 
+-    item->cpuid.eax |= mask->cpuid.eax;
+-    item->cpuid.ebx |= mask->cpuid.ebx;
+-    item->cpuid.ecx |= mask->cpuid.ecx;
+-    item->cpuid.edx |= mask->cpuid.edx;
++    switch (item->type) {
++    case VIR_CPU_X86_DATA_CPUID:
++        cpuid = &item->data.cpuid;
++        cpuidMask = &mask->data.cpuid;
++        cpuid->eax |= cpuidMask->eax;
++        cpuid->ebx |= cpuidMask->ebx;
++        cpuid->ecx |= cpuidMask->ecx;
++        cpuid->edx |= cpuidMask->edx;
++        break;
++
++    case VIR_CPU_X86_DATA_NONE:
++    default:
++        break;
++    }
+ }
+ 
+ 
+@@ -229,13 +268,26 @@ static void
+ virCPUx86DataItemClearBits(virCPUx86DataItemPtr item,
+                            const virCPUx86DataItem *mask)
+ {
++    virCPUx86CPUIDPtr cpuid;
++    const virCPUx86CPUID *cpuidMask;
++
+     if (!mask)
+         return;
+ 
+-    item->cpuid.eax &= ~mask->cpuid.eax;
+-    item->cpuid.ebx &= ~mask->cpuid.ebx;
+-    item->cpuid.ecx &= ~mask->cpuid.ecx;
+-    item->cpuid.edx &= ~mask->cpuid.edx;
++    switch (item->type) {
++    case VIR_CPU_X86_DATA_CPUID:
++        cpuid = &item->data.cpuid;
++        cpuidMask = &mask->data.cpuid;
++        cpuid->eax &= ~cpuidMask->eax;
++        cpuid->ebx &= ~cpuidMask->ebx;
++        cpuid->ecx &= ~cpuidMask->ecx;
++        cpuid->edx &= ~cpuidMask->edx;
++        break;
++
++    case VIR_CPU_X86_DATA_NONE:
++    default:
++        break;
++    }
+ }
+ 
+ 
+@@ -243,13 +295,26 @@ static void
+ virCPUx86DataItemAndBits(virCPUx86DataItemPtr item,
+                          const virCPUx86DataItem *mask)
+ {
++    virCPUx86CPUIDPtr cpuid;
++    const virCPUx86CPUID *cpuidMask;
++
+     if (!mask)
+         return;
+ 
+-    item->cpuid.eax &= mask->cpuid.eax;
+-    item->cpuid.ebx &= mask->cpuid.ebx;
+-    item->cpuid.ecx &= mask->cpuid.ecx;
+-    item->cpuid.edx &= mask->cpuid.edx;
++    switch (item->type) {
++    case VIR_CPU_X86_DATA_CPUID:
++        cpuid = &item->data.cpuid;
++        cpuidMask = &mask->data.cpuid;
++        cpuid->eax &= cpuidMask->eax;
++        cpuid->ebx &= cpuidMask->ebx;
++        cpuid->ecx &= cpuidMask->ecx;
++        cpuid->edx &= cpuidMask->edx;
++        break;
++
++    case VIR_CPU_X86_DATA_NONE:
++    default:
++        break;
++    }
+ }
+ 
+ 
+@@ -289,15 +354,29 @@ virCPUx86DataSorter(const void *a, const void *b)
+     virCPUx86DataItemPtr da = (virCPUx86DataItemPtr) a;
+     virCPUx86DataItemPtr db = (virCPUx86DataItemPtr) b;
+ 
+-    if (da->cpuid.eax_in > db->cpuid.eax_in)
++    if (da->type > db->type)
+         return 1;
+-    else if (da->cpuid.eax_in < db->cpuid.eax_in)
++    else if (da->type < db->type)
+         return -1;
+ 
+-    if (da->cpuid.ecx_in > db->cpuid.ecx_in)
+-        return 1;
+-    else if (da->cpuid.ecx_in < db->cpuid.ecx_in)
+-        return -1;
++    switch (da->type) {
++    case VIR_CPU_X86_DATA_CPUID:
++        if (da->data.cpuid.eax_in > db->data.cpuid.eax_in)
++            return 1;
++        else if (da->data.cpuid.eax_in < db->data.cpuid.eax_in)
++            return -1;
++
++        if (da->data.cpuid.ecx_in > db->data.cpuid.ecx_in)
++            return 1;
++        else if (da->data.cpuid.ecx_in < db->data.cpuid.ecx_in)
++            return -1;
++
++        break;
++
++    case VIR_CPU_X86_DATA_NONE:
++    default:
++        break;
++    }
+ 
+     return 0;
+ }
+@@ -526,9 +605,9 @@ x86DataToVendor(const virCPUx86Data *data,
+ 
+ static int
+ virCPUx86VendorToData(const char *vendor,
+-                      virCPUx86DataItemPtr data)
++                      virCPUx86DataItemPtr item)
+ {
+-    virCPUx86CPUIDPtr cpuid = &data->cpuid;
++    virCPUx86CPUIDPtr cpuid;
+ 
+     if (strlen(vendor) != VENDOR_STRING_LENGTH) {
+         virReportError(VIR_ERR_INTERNAL_ERROR,
+@@ -536,6 +615,8 @@ virCPUx86VendorToData(const char *vendor,
+         return -1;
+     }
+ 
++    item->type = VIR_CPU_X86_DATA_CPUID;
++    cpuid = &item->data.cpuid;
+     cpuid->eax_in = 0;
+     cpuid->ecx_in = 0;
+     cpuid->ebx = virReadBufInt32LE(vendor);
+@@ -611,7 +692,7 @@ x86DataToSignatureFull(const virCPUx86Data *data,
+     if (!(item = virCPUx86DataGet(data, &leaf1)))
+         return;
+ 
+-    cpuid = &item->cpuid;
++    cpuid = &item->data.cpuid;
+     *family = ((cpuid->eax >> 20) & 0xff) + ((cpuid->eax >> 8) & 0xf);
+     *model = ((cpuid->eax >> 12) & 0xf0) + ((cpuid->eax >> 4) & 0xf);
+     *stepping = cpuid->eax & 0xf;
+@@ -630,7 +711,7 @@ x86DataToSignature(const virCPUx86Data *data)
+     if (!(item = virCPUx86DataGet(data, &leaf1)))
+         return 0;
+ 
+-    return item->cpuid.eax & SIGNATURE_MASK;
++    return item->data.cpuid.eax & SIGNATURE_MASK;
+ }
+ 
+ 
+@@ -885,7 +966,8 @@ x86ParseCPUID(xmlXPathContextPtr ctxt,
+         ret_eax == -2 || ret_ebx == -2 || ret_ecx == -2 || ret_edx == -2)
+         return -1;
+ 
+-    cpuid = &item->cpuid;
++    item->type = VIR_CPU_X86_DATA_CPUID;
++    cpuid = &item->data.cpuid;
+     cpuid->eax_in = eax_in;
+     cpuid->ecx_in = ecx_in;
+     cpuid->eax = eax;
+@@ -1461,13 +1543,23 @@ virCPUx86DataFormat(const virCPUData *data)
+ 
+     virBufferAddLit(&buf, "<cpudata arch='x86'>\n");
+     while ((item = virCPUx86DataNext(&iter))) {
+-        virCPUx86CPUIDPtr cpuid = &item->cpuid;
+-        virBufferAsprintf(&buf,
+-                          "  <cpuid eax_in='0x%08x' ecx_in='0x%08x'"
+-                          " eax='0x%08x' ebx='0x%08x'"
+-                          " ecx='0x%08x' edx='0x%08x'/>\n",
+-                          cpuid->eax_in, cpuid->ecx_in,
+-                          cpuid->eax, cpuid->ebx, cpuid->ecx, cpuid->edx);
++        virCPUx86CPUIDPtr cpuid;
++
++        switch (item->type) {
++        case VIR_CPU_X86_DATA_CPUID:
++            cpuid = &item->data.cpuid;
++            virBufferAsprintf(&buf,
++                              "  <cpuid eax_in='0x%08x' ecx_in='0x%08x'"
++                              " eax='0x%08x' ebx='0x%08x'"
++                              " ecx='0x%08x' edx='0x%08x'/>\n",
++                              cpuid->eax_in, cpuid->ecx_in,
++                              cpuid->eax, cpuid->ebx, cpuid->ecx, cpuid->edx);
++            break;
++
++        case VIR_CPU_X86_DATA_NONE:
++        default:
++            break;
++        }
+     }
+     virBufferAddLit(&buf, "</cpudata>\n");
+ 
+@@ -2226,7 +2318,7 @@ cpuidSetLeaf4(virCPUDataPtr data,
+               virCPUx86DataItemPtr subLeaf0)
+ {
+     virCPUx86DataItem item = *subLeaf0;
+-    virCPUx86CPUIDPtr cpuid = &item.cpuid;
++    virCPUx86CPUIDPtr cpuid = &item.data.cpuid;
+ 
+     if (virCPUx86DataAdd(data, subLeaf0) < 0)
+         return -1;
+@@ -2250,13 +2342,13 @@ cpuidSetLeaf7(virCPUDataPtr data,
+               virCPUx86DataItemPtr subLeaf0)
+ {
+     virCPUx86DataItem item = CPUID(.eax_in = 0x7);
+-    virCPUx86CPUIDPtr cpuid = &item.cpuid;
++    virCPUx86CPUIDPtr cpuid = &item.data.cpuid;
+     uint32_t sub;
+ 
+     if (virCPUx86DataAdd(data, subLeaf0) < 0)
+         return -1;
+ 
+-    for (sub = 1; sub <= subLeaf0->cpuid.eax; sub++) {
++    for (sub = 1; sub <= subLeaf0->data.cpuid.eax; sub++) {
+         cpuid->ecx_in = sub;
+         cpuidCall(cpuid);
+         if (virCPUx86DataAdd(data, &item) < 0)
+@@ -2278,7 +2370,7 @@ cpuidSetLeafB(virCPUDataPtr data,
+               virCPUx86DataItemPtr subLeaf0)
+ {
+     virCPUx86DataItem item = *subLeaf0;
+-    virCPUx86CPUIDPtr cpuid = &item.cpuid;
++    virCPUx86CPUIDPtr cpuid = &item.data.cpuid;
+ 
+     while (cpuid->ecx & 0xff00) {
+         if (virCPUx86DataAdd(data, &item) < 0)
+@@ -2303,7 +2395,7 @@ cpuidSetLeafD(virCPUDataPtr data,
+               virCPUx86DataItemPtr subLeaf0)
+ {
+     virCPUx86DataItem item = CPUID(.eax_in = 0xd);
+-    virCPUx86CPUIDPtr cpuid = &item.cpuid;
++    virCPUx86CPUIDPtr cpuid = &item.data.cpuid;
+     virCPUx86CPUID sub0;
+     virCPUx86CPUID sub1;
+     uint32_t sub;
+@@ -2316,7 +2408,7 @@ cpuidSetLeafD(virCPUDataPtr data,
+     if (virCPUx86DataAdd(data, &item) < 0)
+         return -1;
+ 
+-    sub0 = subLeaf0->cpuid;
++    sub0 = subLeaf0->data.cpuid;
+     sub1 = *cpuid;
+     for (sub = 2; sub < 64; sub++) {
+         if (sub < 32 &&
+@@ -2351,8 +2443,8 @@ cpuidSetLeafResID(virCPUDataPtr data,
+                   virCPUx86DataItemPtr subLeaf0,
+                   uint32_t res)
+ {
+-    virCPUx86DataItem item = CPUID(.eax_in = subLeaf0->cpuid.eax_in);
+-    virCPUx86CPUIDPtr cpuid = &item.cpuid;
++    virCPUx86DataItem item = CPUID(.eax_in = subLeaf0->data.cpuid.eax_in);
++    virCPUx86CPUIDPtr cpuid = &item.data.cpuid;
+     uint32_t sub;
+ 
+     if (virCPUx86DataAdd(data, subLeaf0) < 0)
+@@ -2380,11 +2472,11 @@ cpuidSetLeaf12(virCPUDataPtr data,
+                virCPUx86DataItemPtr subLeaf0)
+ {
+     virCPUx86DataItem item = CPUID(.eax_in = 0x7);
+-    virCPUx86CPUIDPtr cpuid = &item.cpuid;
++    virCPUx86CPUIDPtr cpuid = &item.data.cpuid;
+     virCPUx86DataItemPtr leaf7;
+ 
+     if (!(leaf7 = virCPUx86DataGet(&data->data.x86, &item)) ||
+-        !(leaf7->cpuid.ebx & (1 << 2)))
++        !(leaf7->data.cpuid.ebx & (1 << 2)))
+         return 0;
+ 
+     if (virCPUx86DataAdd(data, subLeaf0) < 0)
+@@ -2417,13 +2509,13 @@ cpuidSetLeaf14(virCPUDataPtr data,
+                virCPUx86DataItemPtr subLeaf0)
+ {
+     virCPUx86DataItem item = CPUID(.eax_in = 0x14);
+-    virCPUx86CPUIDPtr cpuid = &item.cpuid;
++    virCPUx86CPUIDPtr cpuid = &item.data.cpuid;
+     uint32_t sub;
+ 
+     if (virCPUx86DataAdd(data, subLeaf0) < 0)
+         return -1;
+ 
+-    for (sub = 1; sub <= subLeaf0->cpuid.eax; sub++) {
++    for (sub = 1; sub <= subLeaf0->data.cpuid.eax; sub++) {
+         cpuid->ecx_in = sub;
+         cpuidCall(cpuid);
+         if (virCPUx86DataAdd(data, &item) < 0)
+@@ -2443,16 +2535,16 @@ cpuidSetLeaf17(virCPUDataPtr data,
+                virCPUx86DataItemPtr subLeaf0)
+ {
+     virCPUx86DataItem item = CPUID(.eax_in = 0x17);
+-    virCPUx86CPUIDPtr cpuid = &item.cpuid;
++    virCPUx86CPUIDPtr cpuid = &item.data.cpuid;
+     uint32_t sub;
+ 
+-    if (subLeaf0->cpuid.eax < 3)
++    if (subLeaf0->data.cpuid.eax < 3)
+         return 0;
+ 
+     if (virCPUx86DataAdd(data, subLeaf0) < 0)
+         return -1;
+ 
+-    for (sub = 1; sub <= subLeaf0->cpuid.eax; sub++) {
++    for (sub = 1; sub <= subLeaf0->data.cpuid.eax; sub++) {
+         cpuid->ecx_in = sub;
+         cpuidCall(cpuid);
+         if (virCPUx86DataAdd(data, &item) < 0)
+@@ -2469,7 +2561,7 @@ cpuidSet(uint32_t base, virCPUDataPtr data)
+     uint32_t max;
+     uint32_t leaf;
+     virCPUx86DataItem item = CPUID(.eax_in = base);
+-    virCPUx86CPUIDPtr cpuid = &item.cpuid;
++    virCPUx86CPUIDPtr cpuid = &item.data.cpuid;
+ 
+     cpuidCall(cpuid);
+     max = cpuid->eax;
+diff --git a/src/cpu/cpu_x86_data.h b/src/cpu/cpu_x86_data.h
+index e93b355cf0..da8e91fe71 100644
+--- a/src/cpu/cpu_x86_data.h
++++ b/src/cpu/cpu_x86_data.h
+@@ -71,10 +71,18 @@ struct _virCPUx86CPUID {
+ 
+ # define VIR_CPU_X86_DATA_INIT { 0 }
+ 
++typedef enum {
++    VIR_CPU_X86_DATA_NONE = 0,
++    VIR_CPU_X86_DATA_CPUID,
++} virCPUx86DataType;
++
+ typedef struct _virCPUx86DataItem virCPUx86DataItem;
+ typedef virCPUx86DataItem *virCPUx86DataItemPtr;
+ struct _virCPUx86DataItem {
+-    virCPUx86CPUID cpuid;
++    virCPUx86DataType type;
++    union {
++        virCPUx86CPUID cpuid;
++    } data;
+ };
+ 
+ typedef struct _virCPUx86Data virCPUx86Data;
+diff --git a/src/libxl/libxl_capabilities.c b/src/libxl/libxl_capabilities.c
+index 2b351fbdde..6630aa2c0b 100644
+--- a/src/libxl/libxl_capabilities.c
++++ b/src/libxl/libxl_capabilities.c
+@@ -70,8 +70,9 @@ libxlCapsAddCPUID(virCPUDataPtr data, virCPUx86CPUID *cpuid, ssize_t ncaps)
+     virCPUx86DataItem item = { 0 };
+     size_t i;
+ 
++    item.type = VIR_CPU_X86_DATA_CPUID;
+     for (i = 0; i < ncaps; i++) {
+-        item.cpuid = cpuid[i];
++        item.data.cpuid = cpuid[i];
+ 
+         if (virCPUx86DataAdd(data, &item) < 0) {
+             VIR_DEBUG("Failed to add CPUID(%x,%x)",
+diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
+index abfaa6e68a..e6ac82e96b 100644
+--- a/src/qemu/qemu_monitor_json.c
++++ b/src/qemu/qemu_monitor_json.c
+@@ -7049,9 +7049,10 @@ qemuMonitorJSONParseCPUx86Features(virJSONValuePtr data)
+     if (!(cpudata = virCPUDataNew(VIR_ARCH_X86_64)))
+         goto error;
+ 
++    item.type = VIR_CPU_X86_DATA_CPUID;
+     for (i = 0; i < virJSONValueArraySize(data); i++) {
+         if (qemuMonitorJSONParseCPUx86FeatureWord(virJSONValueArrayGet(data, i),
+-                                                  &item.cpuid) < 0 ||
++                                                  &item.data.cpuid) < 0 ||
+             virCPUx86DataAdd(cpudata, &item) < 0)
+             goto error;
+     }
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-cpu_x86-Turn-virCPUx86DataIteratorInit-into-a-function.patch b/SOURCES/libvirt-cpu_x86-Turn-virCPUx86DataIteratorInit-into-a-function.patch
new file mode 100644
index 0000000..95ba70d
--- /dev/null
+++ b/SOURCES/libvirt-cpu_x86-Turn-virCPUx86DataIteratorInit-into-a-function.patch
@@ -0,0 +1,147 @@
+From 14c5258d4227930fdadcd0bc9de3cae547b56b70 Mon Sep 17 00:00:00 2001
+Message-Id: <14c5258d4227930fdadcd0bc9de3cae547b56b70@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:26:07 +0200
+Subject: [PATCH] cpu_x86: Turn virCPUx86DataIteratorInit into a function
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Until now, this was a macro usable for direct initialization when a
+variable is defined. Turning the macro into a function makes it more
+general.
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit b8e086a570b14b1f83fc07e25df6da758abe7706)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1697627
+
+Conflicts:
+	src/cpu/cpu_x86.c
+            - commit c9ed87a6103fd4f09e0714f3a2b94c4c975477cd was not
+              backported
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <eb52120d5047b6581f645dc334a327530261f5ed.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/cpu/cpu_x86.c | 35 ++++++++++++++++++++++++-----------
+ 1 file changed, 24 insertions(+), 11 deletions(-)
+
+diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
+index ead962ae06..75527fd28f 100644
+--- a/src/cpu/cpu_x86.c
++++ b/src/cpu/cpu_x86.c
+@@ -187,8 +187,13 @@ struct _virCPUx86DataIterator {
+ };
+ 
+ 
+-#define virCPUx86DataIteratorInit(data) \
+-    { data, -1 }
++static void
++virCPUx86DataIteratorInit(virCPUx86DataIteratorPtr iterator,
++                          const virCPUx86Data *data)
++{
++    virCPUx86DataIterator iter = { data, -1 };
++    *iterator = iter;
++}
+ 
+ 
+ static bool
+@@ -538,9 +543,10 @@ static int
+ x86DataAdd(virCPUx86Data *data1,
+            const virCPUx86Data *data2)
+ {
+-    virCPUx86DataIterator iter = virCPUx86DataIteratorInit(data2);
++    virCPUx86DataIterator iter;
+     virCPUx86DataItemPtr item;
+ 
++    virCPUx86DataIteratorInit(&iter, data2);
+     while ((item = virCPUx86DataNext(&iter))) {
+         if (virCPUx86DataAddItem(data1, item) < 0)
+             return -1;
+@@ -554,10 +560,11 @@ static void
+ x86DataSubtract(virCPUx86Data *data1,
+                 const virCPUx86Data *data2)
+ {
+-    virCPUx86DataIterator iter = virCPUx86DataIteratorInit(data1);
++    virCPUx86DataIterator iter;
+     virCPUx86DataItemPtr item1;
+     virCPUx86DataItemPtr item2;
+ 
++    virCPUx86DataIteratorInit(&iter, data1);
+     while ((item1 = virCPUx86DataNext(&iter))) {
+         item2 = virCPUx86DataGet(data2, item1);
+         virCPUx86DataItemClearBits(item1, item2);
+@@ -569,10 +576,11 @@ static void
+ x86DataIntersect(virCPUx86Data *data1,
+                  const virCPUx86Data *data2)
+ {
+-    virCPUx86DataIterator iter = virCPUx86DataIteratorInit(data1);
++    virCPUx86DataIterator iter;
+     virCPUx86DataItemPtr item1;
+     virCPUx86DataItemPtr item2;
+ 
++    virCPUx86DataIteratorInit(&iter, data1);
+     while ((item1 = virCPUx86DataNext(&iter))) {
+         item2 = virCPUx86DataGet(data2, item1);
+         if (item2)
+@@ -586,8 +594,9 @@ x86DataIntersect(virCPUx86Data *data1,
+ static bool
+ x86DataIsEmpty(virCPUx86Data *data)
+ {
+-    virCPUx86DataIterator iter = virCPUx86DataIteratorInit(data);
++    virCPUx86DataIterator iter;
+ 
++    virCPUx86DataIteratorInit(&iter, data);
+     return !virCPUx86DataNext(&iter);
+ }
+ 
+@@ -596,11 +605,11 @@ static bool
+ x86DataIsSubset(const virCPUx86Data *data,
+                 const virCPUx86Data *subset)
+ {
+-
+-    virCPUx86DataIterator iter = virCPUx86DataIteratorInit((virCPUx86Data *)subset);
++    virCPUx86DataIterator iter;
+     const virCPUx86DataItem *item;
+     const virCPUx86DataItem *itemSubset;
+ 
++    virCPUx86DataIteratorInit(&iter, subset);
+     while ((itemSubset = virCPUx86DataNext(&iter))) {
+         if (!(item = virCPUx86DataGet(data, itemSubset)) ||
+             !virCPUx86DataItemMatchMasked(item, itemSubset))
+@@ -1313,11 +1322,13 @@ x86ModelCompare(virCPUx86ModelPtr model1,
+                 virCPUx86ModelPtr model2)
+ {
+     virCPUx86CompareResult result = EQUAL;
+-    virCPUx86DataIterator iter1 = virCPUx86DataIteratorInit(&model1->data);
+-    virCPUx86DataIterator iter2 = virCPUx86DataIteratorInit(&model2->data);
++    virCPUx86DataIterator iter1;
++    virCPUx86DataIterator iter2;
+     virCPUx86DataItemPtr item1;
+     virCPUx86DataItemPtr item2;
+ 
++    virCPUx86DataIteratorInit(&iter1, &model1->data);
++    virCPUx86DataIteratorInit(&iter2, &model2->data);
+     while ((item1 = virCPUx86DataNext(&iter1))) {
+         virCPUx86CompareResult match = SUPERSET;
+ 
+@@ -1623,10 +1634,12 @@ virCPUx86GetMap(void)
+ static char *
+ virCPUx86DataFormat(const virCPUData *data)
+ {
+-    virCPUx86DataIterator iter = virCPUx86DataIteratorInit(&data->data.x86);
++    virCPUx86DataIterator iter;
+     virCPUx86DataItemPtr item;
+     virBuffer buf = VIR_BUFFER_INITIALIZER;
+ 
++    virCPUx86DataIteratorInit(&iter, &data->data.x86);
++
+     virBufferAddLit(&buf, "<cpudata arch='x86'>\n");
+     while ((item = virCPUx86DataNext(&iter))) {
+         virCPUx86CPUIDPtr cpuid;
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-cputest-Add-data-for-Intel-R-Core-TM-i7-7600U.patch b/SOURCES/libvirt-cputest-Add-data-for-Intel-R-Core-TM-i7-7600U.patch
new file mode 100644
index 0000000..fdfd363
--- /dev/null
+++ b/SOURCES/libvirt-cputest-Add-data-for-Intel-R-Core-TM-i7-7600U.patch
@@ -0,0 +1,979 @@
+From 7ea297f4cff68e0f5f44f91e1ba1283fce05de6f Mon Sep 17 00:00:00 2001
+Message-Id: <7ea297f4cff68e0f5f44f91e1ba1283fce05de6f@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:24:50 +0200
+Subject: [PATCH] cputest: Add data for Intel(R) Core(TM) i7-7600U
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit cd11ea73d01b256437e25bc635c51d08518c8c77)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1686895
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <6a76550993bbc3e13f59daeea8e03ab0a0891997.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ tests/cputest.c                               |   1 +
+ .../x86_64-cpuid-Core-i7-7600U-disabled.xml   |   6 +
+ .../x86_64-cpuid-Core-i7-7600U-enabled.xml    |   8 +
+ .../x86_64-cpuid-Core-i7-7600U-guest.xml      |  28 +
+ .../x86_64-cpuid-Core-i7-7600U-host.xml       |  29 +
+ .../x86_64-cpuid-Core-i7-7600U-json.xml       |  13 +
+ .../x86_64-cpuid-Core-i7-7600U.json           | 755 ++++++++++++++++++
+ .../x86_64-cpuid-Core-i7-7600U.xml            |  47 ++
+ 8 files changed, 887 insertions(+)
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Core-i7-7600U-disabled.xml
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Core-i7-7600U-enabled.xml
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Core-i7-7600U-guest.xml
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Core-i7-7600U-host.xml
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Core-i7-7600U-json.xml
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Core-i7-7600U.json
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Core-i7-7600U.xml
+
+diff --git a/tests/cputest.c b/tests/cputest.c
+index f43144edc9..28d575a784 100644
+--- a/tests/cputest.c
++++ b/tests/cputest.c
+@@ -1176,6 +1176,7 @@ mymain(void)
+     DO_TEST_CPUID(VIR_ARCH_X86_64, "Core-i7-5600U", JSON_HOST);
+     DO_TEST_CPUID(VIR_ARCH_X86_64, "Core-i7-5600U-arat", JSON_HOST);
+     DO_TEST_CPUID(VIR_ARCH_X86_64, "Core-i7-5600U-ibrs", JSON_HOST);
++    DO_TEST_CPUID(VIR_ARCH_X86_64, "Core-i7-7600U", JSON_MODELS);
+     DO_TEST_CPUID(VIR_ARCH_X86_64, "Core-i7-7700", JSON_MODELS);
+     DO_TEST_CPUID(VIR_ARCH_X86_64, "Core2-E6850", JSON_HOST);
+     DO_TEST_CPUID(VIR_ARCH_X86_64, "Core2-Q9500", JSON_NONE);
+diff --git a/tests/cputestdata/x86_64-cpuid-Core-i7-7600U-disabled.xml b/tests/cputestdata/x86_64-cpuid-Core-i7-7600U-disabled.xml
+new file mode 100644
+index 0000000000..0a567bbfae
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Core-i7-7600U-disabled.xml
+@@ -0,0 +1,6 @@
++<!-- Features disabled by QEMU -->
++<cpudata arch='x86'>
++  <cpuid eax_in='0x00000001' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x0800c1dc' edx='0xb0600000'/>
++  <cpuid eax_in='0x00000007' ecx_in='0x00' eax='0x00000000' ebx='0x02000000' ecx='0x00000000' edx='0x08000000'/>
++  <cpuid eax_in='0x80000007' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000100'/>
++</cpudata>
+diff --git a/tests/cputestdata/x86_64-cpuid-Core-i7-7600U-enabled.xml b/tests/cputestdata/x86_64-cpuid-Core-i7-7600U-enabled.xml
+new file mode 100644
+index 0000000000..b1cdaa802a
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Core-i7-7600U-enabled.xml
+@@ -0,0 +1,8 @@
++<!-- Features enabled by QEMU -->
++<cpudata arch='x86'>
++  <cpuid eax_in='0x00000001' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0xf7fa3223' edx='0x0f8bfbff'/>
++  <cpuid eax_in='0x00000006' ecx_in='0x00' eax='0x00000004' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x00000007' ecx_in='0x00' eax='0x00000000' ebx='0x009c4fbb' ecx='0x00000004' edx='0x84000000'/>
++  <cpuid eax_in='0x0000000d' ecx_in='0x01' eax='0x0000000f' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x80000001' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000121' edx='0x2c100800'/>
++</cpudata>
+diff --git a/tests/cputestdata/x86_64-cpuid-Core-i7-7600U-guest.xml b/tests/cputestdata/x86_64-cpuid-Core-i7-7600U-guest.xml
+new file mode 100644
+index 0000000000..70a0fc3286
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Core-i7-7600U-guest.xml
+@@ -0,0 +1,28 @@
++<cpu mode='custom' match='exact'>
++  <model fallback='forbid'>Skylake-Client-IBRS</model>
++  <vendor>Intel</vendor>
++  <feature policy='require' name='ds'/>
++  <feature policy='require' name='acpi'/>
++  <feature policy='require' name='ss'/>
++  <feature policy='require' name='ht'/>
++  <feature policy='require' name='tm'/>
++  <feature policy='require' name='pbe'/>
++  <feature policy='require' name='dtes64'/>
++  <feature policy='require' name='monitor'/>
++  <feature policy='require' name='ds_cpl'/>
++  <feature policy='require' name='vmx'/>
++  <feature policy='require' name='smx'/>
++  <feature policy='require' name='est'/>
++  <feature policy='require' name='tm2'/>
++  <feature policy='require' name='xtpr'/>
++  <feature policy='require' name='pdcm'/>
++  <feature policy='require' name='osxsave'/>
++  <feature policy='require' name='tsc_adjust'/>
++  <feature policy='require' name='clflushopt'/>
++  <feature policy='require' name='intel-pt'/>
++  <feature policy='require' name='stibp'/>
++  <feature policy='require' name='ssbd'/>
++  <feature policy='require' name='xsaves'/>
++  <feature policy='require' name='pdpe1gb'/>
++  <feature policy='require' name='invtsc'/>
++</cpu>
+diff --git a/tests/cputestdata/x86_64-cpuid-Core-i7-7600U-host.xml b/tests/cputestdata/x86_64-cpuid-Core-i7-7600U-host.xml
+new file mode 100644
+index 0000000000..bbdfb6aa61
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Core-i7-7600U-host.xml
+@@ -0,0 +1,29 @@
++<cpu>
++  <arch>x86_64</arch>
++  <model>Skylake-Client-IBRS</model>
++  <vendor>Intel</vendor>
++  <feature name='ds'/>
++  <feature name='acpi'/>
++  <feature name='ss'/>
++  <feature name='ht'/>
++  <feature name='tm'/>
++  <feature name='pbe'/>
++  <feature name='dtes64'/>
++  <feature name='monitor'/>
++  <feature name='ds_cpl'/>
++  <feature name='vmx'/>
++  <feature name='smx'/>
++  <feature name='est'/>
++  <feature name='tm2'/>
++  <feature name='xtpr'/>
++  <feature name='pdcm'/>
++  <feature name='osxsave'/>
++  <feature name='tsc_adjust'/>
++  <feature name='clflushopt'/>
++  <feature name='intel-pt'/>
++  <feature name='stibp'/>
++  <feature name='ssbd'/>
++  <feature name='xsaves'/>
++  <feature name='pdpe1gb'/>
++  <feature name='invtsc'/>
++</cpu>
+diff --git a/tests/cputestdata/x86_64-cpuid-Core-i7-7600U-json.xml b/tests/cputestdata/x86_64-cpuid-Core-i7-7600U-json.xml
+new file mode 100644
+index 0000000000..48089c6003
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Core-i7-7600U-json.xml
+@@ -0,0 +1,13 @@
++<cpu mode='custom' match='exact'>
++  <model fallback='forbid'>Skylake-Client-IBRS</model>
++  <vendor>Intel</vendor>
++  <feature policy='require' name='ss'/>
++  <feature policy='require' name='vmx'/>
++  <feature policy='require' name='hypervisor'/>
++  <feature policy='require' name='tsc_adjust'/>
++  <feature policy='require' name='clflushopt'/>
++  <feature policy='require' name='umip'/>
++  <feature policy='require' name='ssbd'/>
++  <feature policy='require' name='xsaves'/>
++  <feature policy='require' name='pdpe1gb'/>
++</cpu>
+diff --git a/tests/cputestdata/x86_64-cpuid-Core-i7-7600U.json b/tests/cputestdata/x86_64-cpuid-Core-i7-7600U.json
+new file mode 100644
+index 0000000000..9a258e6be3
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Core-i7-7600U.json
+@@ -0,0 +1,755 @@
++{
++  "return": {
++    "model": {
++      "name": "base",
++      "props": {
++        "phys-bits": 0,
++        "core-id": -1,
++        "xlevel": 2147483656,
++        "cmov": true,
++        "ia64": false,
++        "ssb-no": false,
++        "aes": true,
++        "mmx": true,
++        "rdpid": false,
++        "arat": true,
++        "gfni": false,
++        "ibrs-all": false,
++        "pause-filter": false,
++        "xsavec": true,
++        "intel-pt": false,
++        "hv-frequencies": false,
++        "tsc-frequency": 0,
++        "xd": true,
++        "hv-vendor-id": "",
++        "kvm-asyncpf": true,
++        "kvm_asyncpf": true,
++        "perfctr_core": false,
++        "perfctr-core": false,
++        "mpx": true,
++        "pbe": false,
++        "decodeassists": false,
++        "avx512cd": false,
++        "sse4_1": true,
++        "sse4.1": true,
++        "sse4-1": true,
++        "family": 6,
++        "legacy-cache": true,
++        "vmware-cpuid-freq": true,
++        "wbnoinvd": false,
++        "avx512f": false,
++        "msr": true,
++        "mce": true,
++        "mca": true,
++        "hv-runtime": false,
++        "xcrypt": false,
++        "thread-id": -1,
++        "min-level": 13,
++        "xgetbv1": true,
++        "cid": false,
++        "hv-relaxed": false,
++        "hv-crash": false,
++        "ds": false,
++        "fxsr": true,
++        "xsaveopt": true,
++        "xtpr": false,
++        "hv-evmcs": false,
++        "avx512vl": false,
++        "avx512-vpopcntdq": false,
++        "phe": false,
++        "extapic": false,
++        "3dnowprefetch": true,
++        "avx512vbmi2": false,
++        "cr8legacy": false,
++        "cpuid-0xb": true,
++        "xcrypt-en": false,
++        "kvm_pv_eoi": true,
++        "apic-id": 4294967295,
++        "rsba": false,
++        "pn": false,
++        "dca": false,
++        "vendor": "GenuineIntel",
++        "hv-ipi": false,
++        "pku": false,
++        "smx": false,
++        "cmp_legacy": false,
++        "cmp-legacy": false,
++        "node-id": -1,
++        "avx512-4fmaps": false,
++        "vmcb_clean": false,
++        "vmcb-clean": false,
++        "3dnowext": false,
++        "amd-no-ssb": false,
++        "hle": true,
++        "npt": false,
++        "rdctl-no": false,
++        "memory": "/machine/unattached/system[0]",
++        "clwb": false,
++        "lbrv": false,
++        "adx": true,
++        "ss": true,
++        "pni": true,
++        "svm_lock": false,
++        "svm-lock": false,
++        "pfthreshold": false,
++        "smep": true,
++        "smap": true,
++        "x2apic": true,
++        "avx512vbmi": false,
++        "avx512vnni": false,
++        "hv-stimer": false,
++        "x-hv-synic-kvm-only": false,
++        "i64": true,
++        "flushbyasid": false,
++        "f16c": true,
++        "ace2-en": false,
++        "pat": true,
++        "pae": true,
++        "sse": true,
++        "phe-en": false,
++        "kvm_nopiodelay": true,
++        "kvm-nopiodelay": true,
++        "tm": false,
++        "kvmclock-stable-bit": true,
++        "hypervisor": true,
++        "socket-id": -1,
++        "pcommit": false,
++        "syscall": true,
++        "level": 13,
++        "avx512dq": false,
++        "x-migrate-smi-count": true,
++        "svm": false,
++        "full-cpuid-auto-level": true,
++        "hv-reset": false,
++        "invtsc": false,
++        "sse3": true,
++        "sse2": true,
++        "ssbd": true,
++        "est": false,
++        "avx512ifma": false,
++        "tm2": false,
++        "kvm-pv-ipi": true,
++        "kvm-pv-eoi": true,
++        "cx8": true,
++        "cldemote": false,
++        "hv-reenlightenment": false,
++        "kvm_mmu": false,
++        "kvm-mmu": false,
++        "sse4_2": true,
++        "sse4.2": true,
++        "sse4-2": true,
++        "pge": true,
++        "fill-mtrr-mask": true,
++        "avx512bitalg": false,
++        "nodeid_msr": false,
++        "pdcm": false,
++        "movbe": true,
++        "model": 142,
++        "nrip_save": false,
++        "nrip-save": false,
++        "kvm_pv_unhalt": true,
++        "ssse3": true,
++        "sse4a": false,
++        "invpcid": true,
++        "pdpe1gb": true,
++        "tsc-deadline": true,
++        "skip-l1dfl-vmentry": true,
++        "fma": true,
++        "cx16": true,
++        "de": true,
++        "pconfig": false,
++        "enforce": false,
++        "stepping": 9,
++        "xsave": true,
++        "clflush": true,
++        "skinit": false,
++        "tsc": true,
++        "tce": false,
++        "fpu": true,
++        "ibs": false,
++        "ds_cpl": false,
++        "ds-cpl": false,
++        "host-phys-bits": false,
++        "fma4": false,
++        "la57": false,
++        "osvw": false,
++        "check": true,
++        "hv-spinlocks": -1,
++        "pmu": false,
++        "pmm": false,
++        "apic": true,
++        "spec-ctrl": true,
++        "min-xlevel2": 0,
++        "tsc-adjust": true,
++        "tsc_adjust": true,
++        "kvm-steal-time": true,
++        "kvm_steal_time": true,
++        "kvmclock": true,
++        "l3-cache": true,
++        "lwp": false,
++        "amd-ssbd": false,
++        "ibpb": false,
++        "xop": false,
++        "avx": true,
++        "ace2": false,
++        "avx512bw": false,
++        "acpi": false,
++        "hv-vapic": false,
++        "fsgsbase": true,
++        "ht": false,
++        "nx": true,
++        "pclmulqdq": true,
++        "mmxext": false,
++        "vaes": false,
++        "popcnt": true,
++        "xsaves": true,
++        "tcg-cpuid": true,
++        "lm": true,
++        "umip": true,
++        "pse": true,
++        "avx2": true,
++        "sep": true,
++        "pclmuldq": true,
++        "virt-ssbd": false,
++        "x-hv-max-vps": -1,
++        "nodeid-msr": false,
++        "kvm": true,
++        "misalignsse": false,
++        "min-xlevel": 2147483656,
++        "kvm-pv-unhalt": true,
++        "bmi2": true,
++        "bmi1": true,
++        "realized": false,
++        "tsc_scale": false,
++        "tsc-scale": false,
++        "topoext": false,
++        "hv-vpindex": false,
++        "xlevel2": 0,
++        "clflushopt": true,
++        "kvm-no-smi-migration": false,
++        "monitor": false,
++        "avx512er": false,
++        "pmm-en": false,
++        "pcid": true,
++        "arch-capabilities": false,
++        "3dnow": false,
++        "erms": true,
++        "lahf-lm": true,
++        "lahf_lm": true,
++        "vpclmulqdq": false,
++        "fxsr-opt": false,
++        "hv-synic": false,
++        "xstore": false,
++        "fxsr_opt": false,
++        "kvm-hint-dedicated": false,
++        "rtm": true,
++        "lmce": true,
++        "hv-time": false,
++        "perfctr-nb": false,
++        "perfctr_nb": false,
++        "ffxsr": false,
++        "hv-tlbflush": false,
++        "rdrand": true,
++        "rdseed": true,
++        "avx512-4vnniw": false,
++        "vmx": true,
++        "vme": true,
++        "dtes64": false,
++        "mtrr": true,
++        "rdtscp": true,
++        "pse36": true,
++        "kvm-pv-tlb-flush": true,
++        "tbm": false,
++        "wdt": false,
++        "pause_filter": false,
++        "sha-ni": false,
++        "model-id": "Intel(R) Core(TM) i7-7600U CPU @ 2.80GHz",
++        "abm": true,
++        "avx512pf": false,
++        "xstore-en": false
++      }
++    }
++  },
++  "id": "model-expansion"
++}
++
++
++{
++  "return": [
++    {
++      "name": "max",
++      "typename": "max-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": false
++    },
++    {
++      "name": "host",
++      "typename": "host-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": false
++    },
++    {
++      "name": "base",
++      "typename": "base-x86_64-cpu",
++      "unavailable-features": [],
++      "static": true,
++      "migration-safe": true
++    },
++    {
++      "name": "qemu64",
++      "typename": "qemu64-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "qemu32",
++      "typename": "qemu32-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "phenom",
++      "typename": "phenom-x86_64-cpu",
++      "unavailable-features": [
++        "mmxext",
++        "fxsr-opt",
++        "3dnowext",
++        "3dnow",
++        "sse4a",
++        "npt"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "pentium3",
++      "typename": "pentium3-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "pentium2",
++      "typename": "pentium2-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "pentium",
++      "typename": "pentium-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "n270",
++      "typename": "n270-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "kvm64",
++      "typename": "kvm64-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "kvm32",
++      "typename": "kvm32-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "coreduo",
++      "typename": "coreduo-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "core2duo",
++      "typename": "core2duo-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "athlon",
++      "typename": "athlon-x86_64-cpu",
++      "unavailable-features": [
++        "mmxext",
++        "3dnowext",
++        "3dnow"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Westmere-IBRS",
++      "typename": "Westmere-IBRS-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Westmere",
++      "typename": "Westmere-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Skylake-Server-IBRS",
++      "typename": "Skylake-Server-IBRS-x86_64-cpu",
++      "unavailable-features": [
++        "avx512f",
++        "avx512dq",
++        "clwb",
++        "avx512cd",
++        "avx512bw",
++        "avx512vl",
++        "pku",
++        "avx512f",
++        "avx512f",
++        "avx512f",
++        "pku"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Skylake-Server",
++      "typename": "Skylake-Server-x86_64-cpu",
++      "unavailable-features": [
++        "avx512f",
++        "avx512dq",
++        "clwb",
++        "avx512cd",
++        "avx512bw",
++        "avx512vl",
++        "pku",
++        "avx512f",
++        "avx512f",
++        "avx512f",
++        "pku"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Skylake-Client-IBRS",
++      "typename": "Skylake-Client-IBRS-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Skylake-Client",
++      "typename": "Skylake-Client-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "SandyBridge-IBRS",
++      "typename": "SandyBridge-IBRS-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "SandyBridge",
++      "typename": "SandyBridge-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Penryn",
++      "typename": "Penryn-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Opteron_G5",
++      "typename": "Opteron_G5-x86_64-cpu",
++      "unavailable-features": [
++        "sse4a",
++        "misalignsse",
++        "xop",
++        "fma4",
++        "tbm"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Opteron_G4",
++      "typename": "Opteron_G4-x86_64-cpu",
++      "unavailable-features": [
++        "sse4a",
++        "misalignsse",
++        "xop",
++        "fma4"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Opteron_G3",
++      "typename": "Opteron_G3-x86_64-cpu",
++      "unavailable-features": [
++        "sse4a",
++        "misalignsse"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Opteron_G2",
++      "typename": "Opteron_G2-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Opteron_G1",
++      "typename": "Opteron_G1-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Nehalem-IBRS",
++      "typename": "Nehalem-IBRS-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Nehalem",
++      "typename": "Nehalem-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "KnightsMill",
++      "typename": "KnightsMill-x86_64-cpu",
++      "unavailable-features": [
++        "avx512f",
++        "avx512pf",
++        "avx512er",
++        "avx512cd",
++        "avx512-vpopcntdq",
++        "avx512-4vnniw",
++        "avx512-4fmaps",
++        "avx512f",
++        "avx512f",
++        "avx512f"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "IvyBridge-IBRS",
++      "typename": "IvyBridge-IBRS-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "IvyBridge",
++      "typename": "IvyBridge-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Icelake-Server",
++      "typename": "Icelake-Server-x86_64-cpu",
++      "unavailable-features": [
++        "avx512f",
++        "avx512dq",
++        "clwb",
++        "intel-pt",
++        "avx512cd",
++        "avx512bw",
++        "avx512vl",
++        "avx512vbmi",
++        "pku",
++        "",
++        "avx512vbmi2",
++        "gfni",
++        "vaes",
++        "vpclmulqdq",
++        "avx512vnni",
++        "avx512bitalg",
++        "avx512-vpopcntdq",
++        "la57",
++        "pconfig",
++        "wbnoinvd",
++        "avx512f",
++        "avx512f",
++        "avx512f",
++        "pku"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Icelake-Client",
++      "typename": "Icelake-Client-x86_64-cpu",
++      "unavailable-features": [
++        "intel-pt",
++        "avx512vbmi",
++        "pku",
++        "",
++        "avx512vbmi2",
++        "gfni",
++        "vaes",
++        "vpclmulqdq",
++        "avx512vnni",
++        "avx512bitalg",
++        "avx512-vpopcntdq",
++        "wbnoinvd",
++        "pku"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Haswell-noTSX-IBRS",
++      "typename": "Haswell-noTSX-IBRS-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Haswell-noTSX",
++      "typename": "Haswell-noTSX-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Haswell-IBRS",
++      "typename": "Haswell-IBRS-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Haswell",
++      "typename": "Haswell-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "EPYC-IBPB",
++      "typename": "EPYC-IBPB-x86_64-cpu",
++      "unavailable-features": [
++        "sha-ni",
++        "mmxext",
++        "fxsr-opt",
++        "cr8legacy",
++        "sse4a",
++        "misalignsse",
++        "osvw",
++        "ibpb"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "EPYC",
++      "typename": "EPYC-x86_64-cpu",
++      "unavailable-features": [
++        "sha-ni",
++        "mmxext",
++        "fxsr-opt",
++        "cr8legacy",
++        "sse4a",
++        "misalignsse",
++        "osvw"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Conroe",
++      "typename": "Conroe-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Cascadelake-Server",
++      "typename": "Cascadelake-Server-x86_64-cpu",
++      "unavailable-features": [
++        "avx512f",
++        "avx512dq",
++        "clwb",
++        "intel-pt",
++        "avx512cd",
++        "avx512bw",
++        "avx512vl",
++        "pku",
++        "",
++        "avx512vnni",
++        "avx512f",
++        "avx512f",
++        "avx512f",
++        "pku"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Broadwell-noTSX-IBRS",
++      "typename": "Broadwell-noTSX-IBRS-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Broadwell-noTSX",
++      "typename": "Broadwell-noTSX-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Broadwell-IBRS",
++      "typename": "Broadwell-IBRS-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Broadwell",
++      "typename": "Broadwell-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "486",
++      "typename": "486-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    }
++  ],
++  "id": "definitions"
++}
+diff --git a/tests/cputestdata/x86_64-cpuid-Core-i7-7600U.xml b/tests/cputestdata/x86_64-cpuid-Core-i7-7600U.xml
+new file mode 100644
+index 0000000000..d46811e3d3
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Core-i7-7600U.xml
+@@ -0,0 +1,47 @@
++<!-- Intel(R) Core(TM) i7-7600U CPU @ 2.80GHz -->
++<cpudata arch='x86'>
++  <cpuid eax_in='0x00000000' ecx_in='0x00' eax='0x00000016' ebx='0x756e6547' ecx='0x6c65746e' edx='0x49656e69'/>
++  <cpuid eax_in='0x00000001' ecx_in='0x00' eax='0x000806e9' ebx='0x03100800' ecx='0x7ffafbff' edx='0xbfebfbff'/>
++  <cpuid eax_in='0x00000002' ecx_in='0x00' eax='0x76036301' ebx='0x00f0b5ff' ecx='0x00000000' edx='0x00c30000'/>
++  <cpuid eax_in='0x00000003' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x00000004' ecx_in='0x00' eax='0x1c004121' ebx='0x01c0003f' ecx='0x0000003f' edx='0x00000000'/>
++  <cpuid eax_in='0x00000004' ecx_in='0x01' eax='0x1c004122' ebx='0x01c0003f' ecx='0x0000003f' edx='0x00000000'/>
++  <cpuid eax_in='0x00000004' ecx_in='0x02' eax='0x1c004143' ebx='0x00c0003f' ecx='0x000003ff' edx='0x00000000'/>
++  <cpuid eax_in='0x00000004' ecx_in='0x03' eax='0x1c03c163' ebx='0x03c0003f' ecx='0x00000fff' edx='0x00000006'/>
++  <cpuid eax_in='0x00000005' ecx_in='0x00' eax='0x00000040' ebx='0x00000040' ecx='0x00000003' edx='0x11142120'/>
++  <cpuid eax_in='0x00000006' ecx_in='0x00' eax='0x000027f7' ebx='0x00000002' ecx='0x00000009' edx='0x00000000'/>
++  <cpuid eax_in='0x00000007' ecx_in='0x00' eax='0x00000000' ebx='0x029c6fbf' ecx='0x00000000' edx='0x9c000000'/>
++  <cpuid eax_in='0x00000008' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x00000009' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x0000000a' ecx_in='0x00' eax='0x07300404' ebx='0x00000000' ecx='0x00000000' edx='0x00000603'/>
++  <cpuid eax_in='0x0000000b' ecx_in='0x00' eax='0x00000001' ebx='0x00000002' ecx='0x00000100' edx='0x00000003'/>
++  <cpuid eax_in='0x0000000b' ecx_in='0x01' eax='0x00000004' ebx='0x00000004' ecx='0x00000201' edx='0x00000003'/>
++  <cpuid eax_in='0x0000000c' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x0000000d' ecx_in='0x00' eax='0x0000001f' ebx='0x00000440' ecx='0x00000440' edx='0x00000000'/>
++  <cpuid eax_in='0x0000000d' ecx_in='0x01' eax='0x0000000f' ebx='0x000003c0' ecx='0x00000100' edx='0x00000000'/>
++  <cpuid eax_in='0x0000000d' ecx_in='0x02' eax='0x00000100' ebx='0x00000240' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x0000000d' ecx_in='0x03' eax='0x00000040' ebx='0x000003c0' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x0000000d' ecx_in='0x04' eax='0x00000040' ebx='0x00000400' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x0000000d' ecx_in='0x08' eax='0x00000080' ebx='0x00000000' ecx='0x00000001' edx='0x00000000'/>
++  <cpuid eax_in='0x0000000e' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x0000000f' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x00000010' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x00000011' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x00000012' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x00000013' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x00000014' ecx_in='0x00' eax='0x00000001' ebx='0x0000000f' ecx='0x00000007' edx='0x00000000'/>
++  <cpuid eax_in='0x00000014' ecx_in='0x01' eax='0x02490002' ebx='0x003f3fff' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x00000015' ecx_in='0x00' eax='0x00000002' ebx='0x000000f2' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x00000016' ecx_in='0x00' eax='0x00000b54' ebx='0x00000f3c' ecx='0x00000064' edx='0x00000000'/>
++  <cpuid eax_in='0x80000000' ecx_in='0x00' eax='0x80000008' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x80000001' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000121' edx='0x2c100800'/>
++  <cpuid eax_in='0x80000002' ecx_in='0x00' eax='0x65746e49' ebx='0x2952286c' ecx='0x726f4320' edx='0x4d542865'/>
++  <cpuid eax_in='0x80000003' ecx_in='0x00' eax='0x37692029' ebx='0x3036372d' ecx='0x43205530' edx='0x40205550'/>
++  <cpuid eax_in='0x80000004' ecx_in='0x00' eax='0x382e3220' ebx='0x7a484730' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x80000005' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x80000006' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x01006040' edx='0x00000000'/>
++  <cpuid eax_in='0x80000007' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000100'/>
++  <cpuid eax_in='0x80000008' ecx_in='0x00' eax='0x00003027' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x80860000' ecx_in='0x00' eax='0x00000b54' ebx='0x00000f3c' ecx='0x00000064' edx='0x00000000'/>
++  <cpuid eax_in='0xc0000000' ecx_in='0x00' eax='0x00000b54' ebx='0x00000f3c' ecx='0x00000064' edx='0x00000000'/>
++</cpudata>
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-cputest-Add-data-for-Intel-R-Core-TM-i7-8700.patch b/SOURCES/libvirt-cputest-Add-data-for-Intel-R-Core-TM-i7-8700.patch
new file mode 100644
index 0000000..96b2ce2
--- /dev/null
+++ b/SOURCES/libvirt-cputest-Add-data-for-Intel-R-Core-TM-i7-8700.patch
@@ -0,0 +1,873 @@
+From 697bcb394816e4880cdbdb211527f057f4aea564 Mon Sep 17 00:00:00 2001
+Message-Id: <697bcb394816e4880cdbdb211527f057f4aea564@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:24:53 +0200
+Subject: [PATCH] cputest: Add data for Intel(R) Core(TM) i7-8700
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit 87a46f5d8f8b67b22eab8b25cd30a6b9901d6857)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1686895
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <2d5616ba4b88ef12435b52cfd7c90ce3360a83ef.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ tests/cputest.c                               |   1 +
+ .../x86_64-cpuid-Core-i7-8700-disabled.xml    |   6 +
+ .../x86_64-cpuid-Core-i7-8700-enabled.xml     |   8 +
+ .../x86_64-cpuid-Core-i7-8700-guest.xml       |  28 +
+ .../x86_64-cpuid-Core-i7-8700-host.xml        |  29 +
+ .../x86_64-cpuid-Core-i7-8700-json.xml        |  12 +
+ .../x86_64-cpuid-Core-i7-8700.json            | 650 ++++++++++++++++++
+ .../cputestdata/x86_64-cpuid-Core-i7-8700.xml |  47 ++
+ 8 files changed, 781 insertions(+)
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Core-i7-8700-disabled.xml
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Core-i7-8700-enabled.xml
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Core-i7-8700-guest.xml
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Core-i7-8700-host.xml
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Core-i7-8700-json.xml
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Core-i7-8700.json
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Core-i7-8700.xml
+
+diff --git a/tests/cputest.c b/tests/cputest.c
+index bcbfe2d08a..9e5f807823 100644
+--- a/tests/cputest.c
++++ b/tests/cputest.c
+@@ -1178,6 +1178,7 @@ mymain(void)
+     DO_TEST_CPUID(VIR_ARCH_X86_64, "Core-i7-5600U-ibrs", JSON_HOST);
+     DO_TEST_CPUID(VIR_ARCH_X86_64, "Core-i7-7600U", JSON_MODELS);
+     DO_TEST_CPUID(VIR_ARCH_X86_64, "Core-i7-7700", JSON_MODELS);
++    DO_TEST_CPUID(VIR_ARCH_X86_64, "Core-i7-8700", JSON_MODELS);
+     DO_TEST_CPUID(VIR_ARCH_X86_64, "Core2-E6850", JSON_HOST);
+     DO_TEST_CPUID(VIR_ARCH_X86_64, "Core2-Q9500", JSON_NONE);
+     DO_TEST_CPUID(VIR_ARCH_X86_64, "EPYC-7601-32-Core", JSON_HOST);
+diff --git a/tests/cputestdata/x86_64-cpuid-Core-i7-8700-disabled.xml b/tests/cputestdata/x86_64-cpuid-Core-i7-8700-disabled.xml
+new file mode 100644
+index 0000000000..6a7de576f1
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Core-i7-8700-disabled.xml
+@@ -0,0 +1,6 @@
++<!-- Features disabled by QEMU -->
++<cpudata arch='x86'>
++  <cpuid eax_in='0x00000001' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x0800c1fc' edx='0xb0600000'/>
++  <cpuid eax_in='0x00000007' ecx_in='0x00' eax='0x00000000' ebx='0x02000000' ecx='0x00000000' edx='0x08000000'/>
++  <cpuid eax_in='0x80000007' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000100'/>
++</cpudata>
+diff --git a/tests/cputestdata/x86_64-cpuid-Core-i7-8700-enabled.xml b/tests/cputestdata/x86_64-cpuid-Core-i7-8700-enabled.xml
+new file mode 100644
+index 0000000000..f0727d497b
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Core-i7-8700-enabled.xml
+@@ -0,0 +1,8 @@
++<!-- Features enabled by QEMU -->
++<cpudata arch='x86'>
++  <cpuid eax_in='0x00000001' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0xf7fa3203' edx='0x0f8bfbff'/>
++  <cpuid eax_in='0x00000006' ecx_in='0x00' eax='0x00000004' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x00000007' ecx_in='0x00' eax='0x00000000' ebx='0x009c4fbb' ecx='0x00000004' edx='0x84000000'/>
++  <cpuid eax_in='0x0000000d' ecx_in='0x01' eax='0x0000000f' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x80000001' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000121' edx='0x2c100800'/>
++</cpudata>
+diff --git a/tests/cputestdata/x86_64-cpuid-Core-i7-8700-guest.xml b/tests/cputestdata/x86_64-cpuid-Core-i7-8700-guest.xml
+new file mode 100644
+index 0000000000..70a0fc3286
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Core-i7-8700-guest.xml
+@@ -0,0 +1,28 @@
++<cpu mode='custom' match='exact'>
++  <model fallback='forbid'>Skylake-Client-IBRS</model>
++  <vendor>Intel</vendor>
++  <feature policy='require' name='ds'/>
++  <feature policy='require' name='acpi'/>
++  <feature policy='require' name='ss'/>
++  <feature policy='require' name='ht'/>
++  <feature policy='require' name='tm'/>
++  <feature policy='require' name='pbe'/>
++  <feature policy='require' name='dtes64'/>
++  <feature policy='require' name='monitor'/>
++  <feature policy='require' name='ds_cpl'/>
++  <feature policy='require' name='vmx'/>
++  <feature policy='require' name='smx'/>
++  <feature policy='require' name='est'/>
++  <feature policy='require' name='tm2'/>
++  <feature policy='require' name='xtpr'/>
++  <feature policy='require' name='pdcm'/>
++  <feature policy='require' name='osxsave'/>
++  <feature policy='require' name='tsc_adjust'/>
++  <feature policy='require' name='clflushopt'/>
++  <feature policy='require' name='intel-pt'/>
++  <feature policy='require' name='stibp'/>
++  <feature policy='require' name='ssbd'/>
++  <feature policy='require' name='xsaves'/>
++  <feature policy='require' name='pdpe1gb'/>
++  <feature policy='require' name='invtsc'/>
++</cpu>
+diff --git a/tests/cputestdata/x86_64-cpuid-Core-i7-8700-host.xml b/tests/cputestdata/x86_64-cpuid-Core-i7-8700-host.xml
+new file mode 100644
+index 0000000000..bbdfb6aa61
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Core-i7-8700-host.xml
+@@ -0,0 +1,29 @@
++<cpu>
++  <arch>x86_64</arch>
++  <model>Skylake-Client-IBRS</model>
++  <vendor>Intel</vendor>
++  <feature name='ds'/>
++  <feature name='acpi'/>
++  <feature name='ss'/>
++  <feature name='ht'/>
++  <feature name='tm'/>
++  <feature name='pbe'/>
++  <feature name='dtes64'/>
++  <feature name='monitor'/>
++  <feature name='ds_cpl'/>
++  <feature name='vmx'/>
++  <feature name='smx'/>
++  <feature name='est'/>
++  <feature name='tm2'/>
++  <feature name='xtpr'/>
++  <feature name='pdcm'/>
++  <feature name='osxsave'/>
++  <feature name='tsc_adjust'/>
++  <feature name='clflushopt'/>
++  <feature name='intel-pt'/>
++  <feature name='stibp'/>
++  <feature name='ssbd'/>
++  <feature name='xsaves'/>
++  <feature name='pdpe1gb'/>
++  <feature name='invtsc'/>
++</cpu>
+diff --git a/tests/cputestdata/x86_64-cpuid-Core-i7-8700-json.xml b/tests/cputestdata/x86_64-cpuid-Core-i7-8700-json.xml
+new file mode 100644
+index 0000000000..fd7539f7ce
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Core-i7-8700-json.xml
+@@ -0,0 +1,12 @@
++<cpu mode='custom' match='exact'>
++  <model fallback='forbid'>Skylake-Client-IBRS</model>
++  <vendor>Intel</vendor>
++  <feature policy='require' name='ss'/>
++  <feature policy='require' name='hypervisor'/>
++  <feature policy='require' name='tsc_adjust'/>
++  <feature policy='require' name='clflushopt'/>
++  <feature policy='require' name='umip'/>
++  <feature policy='require' name='ssbd'/>
++  <feature policy='require' name='xsaves'/>
++  <feature policy='require' name='pdpe1gb'/>
++</cpu>
+diff --git a/tests/cputestdata/x86_64-cpuid-Core-i7-8700.json b/tests/cputestdata/x86_64-cpuid-Core-i7-8700.json
+new file mode 100644
+index 0000000000..122a1b2985
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Core-i7-8700.json
+@@ -0,0 +1,650 @@
++{
++  "return": {
++    "model": {
++      "name": "base",
++      "props": {
++        "phys-bits": 0,
++        "core-id": -1,
++        "xlevel": 2147483656,
++        "cmov": true,
++        "ia64": false,
++        "aes": true,
++        "mmx": true,
++        "rdpid": false,
++        "arat": true,
++        "gfni": false,
++        "pause-filter": false,
++        "xsavec": true,
++        "intel-pt": false,
++        "osxsave": false,
++        "hv-frequencies": false,
++        "tsc-frequency": 0,
++        "xd": true,
++        "hv-vendor-id": "",
++        "kvm-asyncpf": true,
++        "kvm_asyncpf": true,
++        "perfctr_core": false,
++        "perfctr-core": false,
++        "mpx": true,
++        "pbe": false,
++        "decodeassists": false,
++        "avx512cd": false,
++        "sse4_1": true,
++        "sse4.1": true,
++        "sse4-1": true,
++        "family": 6,
++        "legacy-cache": true,
++        "vmware-cpuid-freq": true,
++        "avx512f": false,
++        "msr": true,
++        "mce": true,
++        "mca": true,
++        "hv-runtime": false,
++        "xcrypt": false,
++        "thread-id": -1,
++        "min-level": 13,
++        "xgetbv1": true,
++        "cid": false,
++        "hv-relaxed": false,
++        "hv-crash": false,
++        "ds": false,
++        "fxsr": true,
++        "xsaveopt": true,
++        "xtpr": false,
++        "avx512vl": false,
++        "avx512-vpopcntdq": false,
++        "phe": false,
++        "extapic": false,
++        "3dnowprefetch": true,
++        "avx512vbmi2": false,
++        "cr8legacy": false,
++        "cpuid-0xb": true,
++        "xcrypt-en": false,
++        "kvm_pv_eoi": true,
++        "apic-id": 4294967295,
++        "pn": false,
++        "dca": false,
++        "vendor": "GenuineIntel",
++        "pku": false,
++        "smx": false,
++        "cmp_legacy": false,
++        "cmp-legacy": false,
++        "node-id": -1,
++        "avx512-4fmaps": false,
++        "vmcb_clean": false,
++        "vmcb-clean": false,
++        "3dnowext": false,
++        "hle": true,
++        "npt": false,
++        "memory": "/machine/unattached/system[0]",
++        "clwb": false,
++        "lbrv": false,
++        "adx": true,
++        "ss": true,
++        "pni": true,
++        "svm_lock": false,
++        "svm-lock": false,
++        "pfthreshold": false,
++        "smep": true,
++        "smap": true,
++        "x2apic": true,
++        "avx512vbmi": false,
++        "avx512vnni": false,
++        "hv-stimer": false,
++        "i64": true,
++        "flushbyasid": false,
++        "f16c": true,
++        "ace2-en": false,
++        "pat": true,
++        "pae": true,
++        "sse": true,
++        "phe-en": false,
++        "kvm_nopiodelay": true,
++        "kvm-nopiodelay": true,
++        "tm": false,
++        "kvmclock-stable-bit": true,
++        "hypervisor": true,
++        "socket-id": -1,
++        "pcommit": false,
++        "syscall": true,
++        "level": 13,
++        "avx512dq": false,
++        "svm": false,
++        "full-cpuid-auto-level": true,
++        "hv-reset": false,
++        "invtsc": false,
++        "sse3": true,
++        "sse2": true,
++        "ssbd": true,
++        "est": false,
++        "avx512ifma": false,
++        "tm2": false,
++        "kvm-pv-eoi": true,
++        "cx8": true,
++        "kvm_mmu": false,
++        "kvm-mmu": false,
++        "sse4_2": true,
++        "sse4.2": true,
++        "sse4-2": true,
++        "pge": true,
++        "fill-mtrr-mask": true,
++        "avx512bitalg": false,
++        "nodeid_msr": false,
++        "pdcm": false,
++        "movbe": true,
++        "model": 158,
++        "nrip_save": false,
++        "nrip-save": false,
++        "kvm_pv_unhalt": true,
++        "ssse3": true,
++        "sse4a": false,
++        "invpcid": true,
++        "pdpe1gb": true,
++        "tsc-deadline": true,
++        "fma": true,
++        "cx16": true,
++        "de": true,
++        "enforce": false,
++        "stepping": 10,
++        "xsave": true,
++        "clflush": true,
++        "skinit": false,
++        "tsc": true,
++        "tce": false,
++        "fpu": true,
++        "ibs": false,
++        "ds_cpl": false,
++        "ds-cpl": false,
++        "host-phys-bits": true,
++        "fma4": false,
++        "la57": false,
++        "osvw": false,
++        "check": true,
++        "hv-spinlocks": -1,
++        "pmu": false,
++        "pmm": false,
++        "apic": true,
++        "spec-ctrl": true,
++        "min-xlevel2": 0,
++        "tsc-adjust": true,
++        "tsc_adjust": true,
++        "kvm-steal-time": true,
++        "kvm_steal_time": true,
++        "kvmclock": true,
++        "l3-cache": true,
++        "lwp": false,
++        "ibpb": false,
++        "xop": false,
++        "avx": true,
++        "ospke": false,
++        "ace2": false,
++        "avx512bw": false,
++        "acpi": false,
++        "hv-vapic": false,
++        "fsgsbase": true,
++        "ht": false,
++        "nx": true,
++        "pclmulqdq": true,
++        "mmxext": false,
++        "vaes": false,
++        "popcnt": true,
++        "xsaves": true,
++        "tcg-cpuid": true,
++        "lm": true,
++        "umip": true,
++        "pse": true,
++        "avx2": true,
++        "sep": true,
++        "pclmuldq": true,
++        "virt-ssbd": false,
++        "x-hv-max-vps": -1,
++        "nodeid-msr": false,
++        "kvm": true,
++        "misalignsse": false,
++        "min-xlevel": 2147483656,
++        "kvm-pv-unhalt": true,
++        "bmi2": true,
++        "bmi1": true,
++        "realized": false,
++        "tsc_scale": false,
++        "tsc-scale": false,
++        "topoext": false,
++        "hv-vpindex": false,
++        "xlevel2": 0,
++        "clflushopt": true,
++        "kvm-no-smi-migration": false,
++        "monitor": false,
++        "avx512er": false,
++        "pmm-en": false,
++        "pcid": true,
++        "3dnow": false,
++        "erms": true,
++        "lahf-lm": true,
++        "lahf_lm": true,
++        "vpclmulqdq": false,
++        "fxsr-opt": false,
++        "hv-synic": false,
++        "xstore": false,
++        "fxsr_opt": false,
++        "kvm-hint-dedicated": false,
++        "rtm": true,
++        "lmce": true,
++        "hv-time": false,
++        "perfctr-nb": false,
++        "perfctr_nb": false,
++        "ffxsr": false,
++        "rdrand": true,
++        "rdseed": true,
++        "avx512-4vnniw": false,
++        "vmx": false,
++        "vme": true,
++        "dtes64": false,
++        "mtrr": true,
++        "rdtscp": true,
++        "pse36": true,
++        "kvm-pv-tlb-flush": true,
++        "tbm": false,
++        "wdt": false,
++        "pause_filter": false,
++        "sha-ni": false,
++        "model-id": "Intel(R) Core(TM) i7-8700 CPU @ 3.20GHz",
++        "abm": true,
++        "avx512pf": false,
++        "xstore-en": false
++      }
++    }
++  },
++  "id": "model-expansion"
++}
++
++{
++  "return": [
++    {
++      "name": "max",
++      "typename": "max-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": false
++    },
++    {
++      "name": "host",
++      "typename": "host-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": false
++    },
++    {
++      "name": "base",
++      "typename": "base-x86_64-cpu",
++      "unavailable-features": [],
++      "static": true,
++      "migration-safe": true
++    },
++    {
++      "name": "qemu64",
++      "typename": "qemu64-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "qemu32",
++      "typename": "qemu32-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "phenom",
++      "typename": "phenom-x86_64-cpu",
++      "unavailable-features": [
++        "mmxext",
++        "fxsr-opt",
++        "3dnowext",
++        "3dnow",
++        "sse4a",
++        "npt"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "pentium3",
++      "typename": "pentium3-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "pentium2",
++      "typename": "pentium2-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "pentium",
++      "typename": "pentium-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "n270",
++      "typename": "n270-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "kvm64",
++      "typename": "kvm64-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "kvm32",
++      "typename": "kvm32-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "cpu64-rhel6",
++      "typename": "cpu64-rhel6-x86_64-cpu",
++      "unavailable-features": [
++        "sse4a"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "coreduo",
++      "typename": "coreduo-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "core2duo",
++      "typename": "core2duo-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "athlon",
++      "typename": "athlon-x86_64-cpu",
++      "unavailable-features": [
++        "mmxext",
++        "3dnowext",
++        "3dnow"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Westmere",
++      "typename": "Westmere-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Westmere-IBRS",
++      "typename": "Westmere-IBRS-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Skylake-Server",
++      "typename": "Skylake-Server-x86_64-cpu",
++      "unavailable-features": [
++        "avx512f",
++        "avx512dq",
++        "clwb",
++        "avx512cd",
++        "avx512bw",
++        "avx512vl",
++        "avx512f",
++        "avx512f",
++        "avx512f"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Skylake-Server-IBRS",
++      "typename": "Skylake-Server-IBRS-x86_64-cpu",
++      "unavailable-features": [
++        "avx512f",
++        "avx512dq",
++        "clwb",
++        "avx512cd",
++        "avx512bw",
++        "avx512vl",
++        "avx512f",
++        "avx512f",
++        "avx512f"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Skylake-Client",
++      "typename": "Skylake-Client-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Skylake-Client-IBRS",
++      "typename": "Skylake-Client-IBRS-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "SandyBridge",
++      "typename": "SandyBridge-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "SandyBridge-IBRS",
++      "typename": "SandyBridge-IBRS-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Penryn",
++      "typename": "Penryn-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Opteron_G5",
++      "typename": "Opteron_G5-x86_64-cpu",
++      "unavailable-features": [
++        "sse4a",
++        "misalignsse",
++        "xop",
++        "fma4",
++        "tbm"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Opteron_G4",
++      "typename": "Opteron_G4-x86_64-cpu",
++      "unavailable-features": [
++        "sse4a",
++        "misalignsse",
++        "xop",
++        "fma4"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Opteron_G3",
++      "typename": "Opteron_G3-x86_64-cpu",
++      "unavailable-features": [
++        "sse4a",
++        "misalignsse"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Opteron_G2",
++      "typename": "Opteron_G2-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Opteron_G1",
++      "typename": "Opteron_G1-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Nehalem",
++      "typename": "Nehalem-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Nehalem-IBRS",
++      "typename": "Nehalem-IBRS-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "IvyBridge",
++      "typename": "IvyBridge-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "IvyBridge-IBRS",
++      "typename": "IvyBridge-IBRS-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Haswell",
++      "typename": "Haswell-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Haswell-noTSX",
++      "typename": "Haswell-noTSX-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Haswell-noTSX-IBRS",
++      "typename": "Haswell-noTSX-IBRS-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Haswell-IBRS",
++      "typename": "Haswell-IBRS-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "EPYC",
++      "typename": "EPYC-x86_64-cpu",
++      "unavailable-features": [
++        "sha-ni",
++        "mmxext",
++        "fxsr-opt",
++        "cr8legacy",
++        "sse4a",
++        "misalignsse",
++        "osvw"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "EPYC-IBPB",
++      "typename": "EPYC-IBPB-x86_64-cpu",
++      "unavailable-features": [
++        "sha-ni",
++        "mmxext",
++        "fxsr-opt",
++        "cr8legacy",
++        "sse4a",
++        "misalignsse",
++        "osvw",
++        "ibpb"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Conroe",
++      "typename": "Conroe-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Broadwell",
++      "typename": "Broadwell-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Broadwell-noTSX",
++      "typename": "Broadwell-noTSX-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Broadwell-noTSX-IBRS",
++      "typename": "Broadwell-noTSX-IBRS-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Broadwell-IBRS",
++      "typename": "Broadwell-IBRS-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "486",
++      "typename": "486-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    }
++  ],
++  "id": "definitions"
++}
+diff --git a/tests/cputestdata/x86_64-cpuid-Core-i7-8700.xml b/tests/cputestdata/x86_64-cpuid-Core-i7-8700.xml
+new file mode 100644
+index 0000000000..03ba0a3925
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Core-i7-8700.xml
+@@ -0,0 +1,47 @@
++<!-- Intel(R) Core(TM) i7-8700 CPU @ 3.20GHz -->
++<cpudata arch='x86'>
++  <cpuid eax_in='0x00000000' ecx_in='0x00' eax='0x00000016' ebx='0x756e6547' ecx='0x6c65746e' edx='0x49656e69'/>
++  <cpuid eax_in='0x00000001' ecx_in='0x00' eax='0x000906ea' ebx='0x01100800' ecx='0x7ffafbff' edx='0xbfebfbff'/>
++  <cpuid eax_in='0x00000002' ecx_in='0x00' eax='0x76036301' ebx='0x00f0b5ff' ecx='0x00000000' edx='0x00c30000'/>
++  <cpuid eax_in='0x00000003' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x00000004' ecx_in='0x00' eax='0x1c004121' ebx='0x01c0003f' ecx='0x0000003f' edx='0x00000000'/>
++  <cpuid eax_in='0x00000004' ecx_in='0x01' eax='0x1c004122' ebx='0x01c0003f' ecx='0x0000003f' edx='0x00000000'/>
++  <cpuid eax_in='0x00000004' ecx_in='0x02' eax='0x1c004143' ebx='0x00c0003f' ecx='0x000003ff' edx='0x00000000'/>
++  <cpuid eax_in='0x00000004' ecx_in='0x03' eax='0x1c03c163' ebx='0x03c0003f' ecx='0x00002fff' edx='0x00000006'/>
++  <cpuid eax_in='0x00000005' ecx_in='0x00' eax='0x00000040' ebx='0x00000040' ecx='0x00000003' edx='0x11142120'/>
++  <cpuid eax_in='0x00000006' ecx_in='0x00' eax='0x000027f7' ebx='0x00000002' ecx='0x00000001' edx='0x00000000'/>
++  <cpuid eax_in='0x00000007' ecx_in='0x00' eax='0x00000000' ebx='0x029c6fbf' ecx='0x40000000' edx='0x9c000000'/>
++  <cpuid eax_in='0x00000008' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x00000009' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x0000000a' ecx_in='0x00' eax='0x07300404' ebx='0x00000000' ecx='0x00000000' edx='0x00000603'/>
++  <cpuid eax_in='0x0000000b' ecx_in='0x00' eax='0x00000001' ebx='0x00000002' ecx='0x00000100' edx='0x00000001'/>
++  <cpuid eax_in='0x0000000b' ecx_in='0x01' eax='0x00000004' ebx='0x0000000c' ecx='0x00000201' edx='0x00000001'/>
++  <cpuid eax_in='0x0000000c' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x0000000d' ecx_in='0x00' eax='0x0000001f' ebx='0x00000440' ecx='0x00000440' edx='0x00000000'/>
++  <cpuid eax_in='0x0000000d' ecx_in='0x01' eax='0x0000000f' ebx='0x000003c0' ecx='0x00000100' edx='0x00000000'/>
++  <cpuid eax_in='0x0000000d' ecx_in='0x02' eax='0x00000100' ebx='0x00000240' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x0000000d' ecx_in='0x03' eax='0x00000040' ebx='0x000003c0' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x0000000d' ecx_in='0x04' eax='0x00000040' ebx='0x00000400' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x0000000d' ecx_in='0x08' eax='0x00000080' ebx='0x00000000' ecx='0x00000001' edx='0x00000000'/>
++  <cpuid eax_in='0x0000000e' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x0000000f' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x00000010' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x00000011' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x00000012' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x00000013' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x00000014' ecx_in='0x00' eax='0x00000001' ebx='0x0000000f' ecx='0x00000007' edx='0x00000000'/>
++  <cpuid eax_in='0x00000014' ecx_in='0x01' eax='0x02490002' ebx='0x003f3fff' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x00000015' ecx_in='0x00' eax='0x00000002' ebx='0x0000010a' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x00000016' ecx_in='0x00' eax='0x00000c80' ebx='0x000011f8' ecx='0x00000064' edx='0x00000000'/>
++  <cpuid eax_in='0x80000000' ecx_in='0x00' eax='0x80000008' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x80000001' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000121' edx='0x2c100800'/>
++  <cpuid eax_in='0x80000002' ecx_in='0x00' eax='0x65746e49' ebx='0x2952286c' ecx='0x726f4320' edx='0x4d542865'/>
++  <cpuid eax_in='0x80000003' ecx_in='0x00' eax='0x37692029' ebx='0x3037382d' ecx='0x50432030' edx='0x20402055'/>
++  <cpuid eax_in='0x80000004' ecx_in='0x00' eax='0x30322e33' ebx='0x007a4847' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x80000005' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x80000006' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x01006040' edx='0x00000000'/>
++  <cpuid eax_in='0x80000007' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000100'/>
++  <cpuid eax_in='0x80000008' ecx_in='0x00' eax='0x00003027' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x80860000' ecx_in='0x00' eax='0x00000c80' ebx='0x000011f8' ecx='0x00000064' edx='0x00000000'/>
++  <cpuid eax_in='0xc0000000' ecx_in='0x00' eax='0x00000c80' ebx='0x000011f8' ecx='0x00000064' edx='0x00000000'/>
++</cpudata>
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-cputest-Add-data-for-Intel-R-Xeon-R-CPU-E3-1225-v5.patch b/SOURCES/libvirt-cputest-Add-data-for-Intel-R-Xeon-R-CPU-E3-1225-v5.patch
index b42496c..d0b011b 100644
--- a/SOURCES/libvirt-cputest-Add-data-for-Intel-R-Xeon-R-CPU-E3-1225-v5.patch
+++ b/SOURCES/libvirt-cputest-Add-data-for-Intel-R-Xeon-R-CPU-E3-1225-v5.patch
@@ -1,5 +1,5 @@
-From 7d229030e2ff3a2ca7664497205d3306c8ab6bb0 Mon Sep 17 00:00:00 2001
-Message-Id: <7d229030e2ff3a2ca7664497205d3306c8ab6bb0@dist-git>
+From cd7339269704e58b78c1033d46a336448256b4e7 Mon Sep 17 00:00:00 2001
+Message-Id: <cd7339269704e58b78c1033d46a336448256b4e7@dist-git>
 From: Jiri Denemark <jdenemar@redhat.com>
 Date: Fri, 5 Apr 2019 11:19:30 +0200
 Subject: [PATCH] cputest: Add data for Intel(R) Xeon(R) CPU E3-1225 v5
@@ -9,9 +9,9 @@ Content-Transfer-Encoding: 8bit
 
 Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
 Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
-(cherry picked from a private commit)
+(cherry picked from commit 5cd9db3ac11e88846cbcf95fad9f6fae9d880dee)
 
-CVE-2018-11091, CVE-2018-12126, CVE-2018-12127, CVE-2018-12130
+CVE-2018-12126, CVE-2018-12127, CVE-2018-12130, CVE-2019-11091
 
 Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
 ---
diff --git a/SOURCES/libvirt-cputest-Add-data-for-Intel-R-Xeon-R-CPU-E5-2630-v4.patch b/SOURCES/libvirt-cputest-Add-data-for-Intel-R-Xeon-R-CPU-E5-2630-v4.patch
new file mode 100644
index 0000000..63e259a
--- /dev/null
+++ b/SOURCES/libvirt-cputest-Add-data-for-Intel-R-Xeon-R-CPU-E5-2630-v4.patch
@@ -0,0 +1,824 @@
+From 4e22f6ec928e62811db06cd717fc286dd1dfba8e Mon Sep 17 00:00:00 2001
+Message-Id: <4e22f6ec928e62811db06cd717fc286dd1dfba8e@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:24:49 +0200
+Subject: [PATCH] cputest: Add data for Intel(R) Xeon(R) CPU E5-2630 v4
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit 8d068f360183ecd55e3213dbe9ba12f7d6470751)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1686895
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <5bc8830efc48a09ace38df33a83152ae0cf3a5fe.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ tests/cputest.c                               |   1 +
+ .../x86_64-cpuid-Xeon-E5-2630-v4-disabled.xml |   7 +
+ .../x86_64-cpuid-Xeon-E5-2630-v4-enabled.xml  |   8 +
+ .../x86_64-cpuid-Xeon-E5-2630-v4-guest.xml    |  31 +
+ .../x86_64-cpuid-Xeon-E5-2630-v4-host.xml     |  35 +
+ .../x86_64-cpuid-Xeon-E5-2630-v4-json.xml     |  11 +
+ .../x86_64-cpuid-Xeon-E5-2630-v4.json         | 596 ++++++++++++++++++
+ .../x86_64-cpuid-Xeon-E5-2630-v4.xml          |  43 ++
+ 8 files changed, 732 insertions(+)
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-E5-2630-v4-disabled.xml
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-E5-2630-v4-enabled.xml
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-E5-2630-v4-guest.xml
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-E5-2630-v4-host.xml
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-E5-2630-v4-json.xml
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-E5-2630-v4.json
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-E5-2630-v4.xml
+
+diff --git a/tests/cputest.c b/tests/cputest.c
+index fbb2a86af8..f43144edc9 100644
+--- a/tests/cputest.c
++++ b/tests/cputest.c
+@@ -1195,6 +1195,7 @@ mymain(void)
+     DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-E5-2609-v3", JSON_MODELS);
+     DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-E5-2623-v4", JSON_MODELS);
+     DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-E5-2630-v3", JSON_HOST);
++    DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-E5-2630-v4", JSON_MODELS);
+     DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-E5-2650-v3", JSON_HOST);
+     DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-E5-2650-v4", JSON_MODELS);
+     DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-E7-4820", JSON_HOST);
+diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E5-2630-v4-disabled.xml b/tests/cputestdata/x86_64-cpuid-Xeon-E5-2630-v4-disabled.xml
+new file mode 100644
+index 0000000000..3ffb246167
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Xeon-E5-2630-v4-disabled.xml
+@@ -0,0 +1,7 @@
++<!-- Features disabled by QEMU -->
++<cpudata arch='x86'>
++  <cpuid eax_in='0x00000001' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x0804c1fc' edx='0xb0600000'/>
++  <cpuid eax_in='0x00000007' ecx_in='0x00' eax='0x00000000' ebx='0x02001000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x0000000f' ecx_in='0x01' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000006'/>
++  <cpuid eax_in='0x80000007' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000100'/>
++</cpudata>
+diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E5-2630-v4-enabled.xml b/tests/cputestdata/x86_64-cpuid-Xeon-E5-2630-v4-enabled.xml
+new file mode 100644
+index 0000000000..f2d4f2826d
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Xeon-E5-2630-v4-enabled.xml
+@@ -0,0 +1,8 @@
++<!-- Features enabled by QEMU -->
++<cpudata arch='x86'>
++  <cpuid eax_in='0x00000001' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0xf7fa3203' edx='0x0f8bfbff'/>
++  <cpuid eax_in='0x00000006' ecx_in='0x00' eax='0x00000004' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x00000007' ecx_in='0x00' eax='0x00000000' ebx='0x001c0fbb' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x0000000d' ecx_in='0x01' eax='0x00000001' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x80000001' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000121' edx='0x2c100800'/>
++</cpudata>
+diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E5-2630-v4-guest.xml b/tests/cputestdata/x86_64-cpuid-Xeon-E5-2630-v4-guest.xml
+new file mode 100644
+index 0000000000..cd7e25b52a
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Xeon-E5-2630-v4-guest.xml
+@@ -0,0 +1,31 @@
++<cpu mode='custom' match='exact'>
++  <model fallback='forbid'>Skylake-Client</model>
++  <vendor>Intel</vendor>
++  <feature policy='require' name='ds'/>
++  <feature policy='require' name='acpi'/>
++  <feature policy='require' name='ss'/>
++  <feature policy='require' name='ht'/>
++  <feature policy='require' name='tm'/>
++  <feature policy='require' name='pbe'/>
++  <feature policy='require' name='dtes64'/>
++  <feature policy='require' name='monitor'/>
++  <feature policy='require' name='ds_cpl'/>
++  <feature policy='require' name='vmx'/>
++  <feature policy='require' name='smx'/>
++  <feature policy='require' name='est'/>
++  <feature policy='require' name='tm2'/>
++  <feature policy='require' name='xtpr'/>
++  <feature policy='require' name='pdcm'/>
++  <feature policy='require' name='dca'/>
++  <feature policy='require' name='osxsave'/>
++  <feature policy='require' name='tsc_adjust'/>
++  <feature policy='require' name='cmt'/>
++  <feature policy='require' name='intel-pt'/>
++  <feature policy='require' name='mbm_total'/>
++  <feature policy='require' name='mbm_local'/>
++  <feature policy='require' name='pdpe1gb'/>
++  <feature policy='require' name='invtsc'/>
++  <feature policy='disable' name='mpx'/>
++  <feature policy='disable' name='xsavec'/>
++  <feature policy='disable' name='xgetbv1'/>
++</cpu>
+diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E5-2630-v4-host.xml b/tests/cputestdata/x86_64-cpuid-Xeon-E5-2630-v4-host.xml
+new file mode 100644
+index 0000000000..5dd8d749de
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Xeon-E5-2630-v4-host.xml
+@@ -0,0 +1,35 @@
++<cpu>
++  <arch>x86_64</arch>
++  <model>Broadwell</model>
++  <vendor>Intel</vendor>
++  <feature name='vme'/>
++  <feature name='ds'/>
++  <feature name='acpi'/>
++  <feature name='ss'/>
++  <feature name='ht'/>
++  <feature name='tm'/>
++  <feature name='pbe'/>
++  <feature name='dtes64'/>
++  <feature name='monitor'/>
++  <feature name='ds_cpl'/>
++  <feature name='vmx'/>
++  <feature name='smx'/>
++  <feature name='est'/>
++  <feature name='tm2'/>
++  <feature name='xtpr'/>
++  <feature name='pdcm'/>
++  <feature name='dca'/>
++  <feature name='osxsave'/>
++  <feature name='f16c'/>
++  <feature name='rdrand'/>
++  <feature name='arat'/>
++  <feature name='tsc_adjust'/>
++  <feature name='cmt'/>
++  <feature name='intel-pt'/>
++  <feature name='xsaveopt'/>
++  <feature name='mbm_total'/>
++  <feature name='mbm_local'/>
++  <feature name='pdpe1gb'/>
++  <feature name='abm'/>
++  <feature name='invtsc'/>
++</cpu>
+diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E5-2630-v4-json.xml b/tests/cputestdata/x86_64-cpuid-Xeon-E5-2630-v4-json.xml
+new file mode 100644
+index 0000000000..5dfce947b2
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Xeon-E5-2630-v4-json.xml
+@@ -0,0 +1,11 @@
++<cpu mode='custom' match='exact'>
++  <model fallback='forbid'>Skylake-Client</model>
++  <vendor>Intel</vendor>
++  <feature policy='require' name='ss'/>
++  <feature policy='require' name='hypervisor'/>
++  <feature policy='require' name='tsc_adjust'/>
++  <feature policy='require' name='pdpe1gb'/>
++  <feature policy='disable' name='mpx'/>
++  <feature policy='disable' name='xsavec'/>
++  <feature policy='disable' name='xgetbv1'/>
++</cpu>
+diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E5-2630-v4.json b/tests/cputestdata/x86_64-cpuid-Xeon-E5-2630-v4.json
+new file mode 100644
+index 0000000000..ee09950fce
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Xeon-E5-2630-v4.json
+@@ -0,0 +1,596 @@
++{
++  "return": {
++    "model": {
++      "name": "base",
++      "props": {
++        "phys-bits": 0,
++        "core-id": -1,
++        "xlevel": 2147483656,
++        "cmov": true,
++        "ia64": false,
++        "aes": true,
++        "mmx": true,
++        "arat": true,
++        "rdpid": false,
++        "pause-filter": false,
++        "xsavec": false,
++        "osxsave": false,
++        "tsc-frequency": 0,
++        "xd": true,
++        "hv-vendor-id": "",
++        "kvm-asyncpf": true,
++        "kvm_asyncpf": true,
++        "perfctr_core": false,
++        "perfctr-core": false,
++        "mpx": false,
++        "decodeassists": false,
++        "avx512cd": false,
++        "pbe": false,
++        "sse4_1": true,
++        "sse4.1": true,
++        "sse4-1": true,
++        "family": 6,
++        "vmware-cpuid-freq": true,
++        "avx512f": false,
++        "xcrypt": false,
++        "msr": true,
++        "mce": true,
++        "mca": true,
++        "thread-id": -1,
++        "min-level": 13,
++        "xgetbv1": false,
++        "cid": false,
++        "hv-relaxed": false,
++        "fxsr": true,
++        "ds": false,
++        "hv-crash": false,
++        "xsaveopt": true,
++        "xtpr": false,
++        "avx512-vpopcntdq": false,
++        "phe": false,
++        "avx512vl": false,
++        "extapic": false,
++        "3dnowprefetch": true,
++        "cr8legacy": false,
++        "stibp": false,
++        "cpuid-0xb": true,
++        "xcrypt-en": false,
++        "kvm_pv_eoi": true,
++        "apic-id": 4294967295,
++        "pn": false,
++        "dca": false,
++        "vendor": "GenuineIntel",
++        "pku": false,
++        "smx": false,
++        "cmp-legacy": false,
++        "cmp_legacy": false,
++        "avx512-4fmaps": false,
++        "vmcb-clean": false,
++        "vmcb_clean": false,
++        "3dnowext": false,
++        "hle": true,
++        "npt": false,
++        "memory": "/machine/unattached/system[0]",
++        "clwb": false,
++        "lbrv": false,
++        "adx": true,
++        "ss": true,
++        "pni": true,
++        "svm_lock": false,
++        "svm-lock": false,
++        "smep": true,
++        "pfthreshold": false,
++        "smap": true,
++        "x2apic": true,
++        "avx512vbmi": false,
++        "i64": true,
++        "flushbyasid": false,
++        "f16c": true,
++        "ace2-en": false,
++        "pat": true,
++        "pae": true,
++        "sse": true,
++        "phe-en": false,
++        "kvm-nopiodelay": true,
++        "kvm_nopiodelay": true,
++        "tm": false,
++        "kvmclock-stable-bit": true,
++        "hypervisor": true,
++        "socket-id": -1,
++        "pcommit": false,
++        "syscall": true,
++        "level": 13,
++        "avx512dq": false,
++        "svm": false,
++        "full-cpuid-auto-level": true,
++        "invtsc": false,
++        "sse3": true,
++        "sse2": true,
++        "est": false,
++        "avx512ifma": false,
++        "tm2": false,
++        "kvm-pv-eoi": true,
++        "cx8": true,
++        "kvm-mmu": false,
++        "kvm_mmu": false,
++        "sse4_2": true,
++        "sse4.2": true,
++        "sse4-2": true,
++        "pge": true,
++        "fill-mtrr-mask": true,
++        "pdcm": false,
++        "nodeid_msr": false,
++        "model": 79,
++        "movbe": true,
++        "nrip-save": false,
++        "nrip_save": false,
++        "sse4a": false,
++        "ssse3": true,
++        "kvm_pv_unhalt": true,
++        "invpcid": true,
++        "pdpe1gb": true,
++        "tsc-deadline": true,
++        "fma": true,
++        "cx16": true,
++        "de": true,
++        "enforce": false,
++        "stepping": 1,
++        "xsave": true,
++        "clflush": true,
++        "arch-facilities": false,
++        "skinit": false,
++        "tce": false,
++        "tsc": true,
++        "fpu": true,
++        "ds-cpl": false,
++        "ds_cpl": false,
++        "ibs": false,
++        "host-phys-bits": true,
++        "fma4": false,
++        "la57": false,
++        "osvw": false,
++        "check": true,
++        "hv-spinlocks": -1,
++        "pmm": false,
++        "apic": true,
++        "pmu": false,
++        "spec-ctrl": false,
++        "min-xlevel2": 0,
++        "tsc-adjust": true,
++        "tsc_adjust": true,
++        "kvm-steal-time": true,
++        "kvm_steal_time": true,
++        "kvmclock": true,
++        "l3-cache": true,
++        "lwp": false,
++        "xop": false,
++        "ibpb": false,
++        "avx": true,
++        "ospke": false,
++        "ace2": false,
++        "acpi": false,
++        "avx512bw": false,
++        "hv-vapic": false,
++        "fsgsbase": true,
++        "ht": false,
++        "nx": true,
++        "pclmulqdq": true,
++        "mmxext": false,
++        "popcnt": true,
++        "xsaves": false,
++        "lm": true,
++        "umip": false,
++        "avx2": true,
++        "pse": true,
++        "sep": true,
++        "pclmuldq": true,
++        "nodeid-msr": false,
++        "kvm": true,
++        "misalignsse": false,
++        "min-xlevel": 2147483656,
++        "bmi2": true,
++        "bmi1": true,
++        "kvm-pv-unhalt": true,
++        "realized": false,
++        "tsc-scale": false,
++        "tsc_scale": false,
++        "topoext": false,
++        "xlevel2": 0,
++        "clflushopt": false,
++        "kvm-no-smi-migration": false,
++        "monitor": false,
++        "avx512er": false,
++        "pmm-en": false,
++        "pcid": true,
++        "3dnow": false,
++        "erms": true,
++        "lahf-lm": true,
++        "lahf_lm": true,
++        "xstore": false,
++        "fxsr-opt": false,
++        "fxsr_opt": false,
++        "rtm": true,
++        "lmce": true,
++        "hv-time": false,
++        "perfctr-nb": false,
++        "perfctr_nb": false,
++        "ffxsr": false,
++        "rdrand": true,
++        "rdseed": true,
++        "avx512-4vnniw": false,
++        "vme": true,
++        "vmx": false,
++        "dtes64": false,
++        "mtrr": true,
++        "rdtscp": true,
++        "pse36": true,
++        "tbm": false,
++        "wdt": false,
++        "pause_filter": false,
++        "model-id": "Intel(R) Xeon(R) CPU E5-2630 v4 @ 2.20GHz",
++        "sha-ni": false,
++        "abm": true,
++        "avx512pf": false,
++        "xstore-en": false
++      }
++    }
++  },
++  "id": "model-expansion"
++}
++
++
++{
++  "return": [
++    {
++      "name": "max",
++      "typename": "max-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": false
++    },
++    {
++      "name": "host",
++      "typename": "host-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": false
++    },
++    {
++      "name": "base",
++      "typename": "base-x86_64-cpu",
++      "unavailable-features": [],
++      "static": true,
++      "migration-safe": true
++    },
++    {
++      "name": "qemu64",
++      "typename": "qemu64-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "qemu32",
++      "typename": "qemu32-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "phenom",
++      "typename": "phenom-x86_64-cpu",
++      "unavailable-features": [
++        "mmxext",
++        "fxsr-opt",
++        "3dnowext",
++        "3dnow",
++        "sse4a",
++        "npt"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "pentium3",
++      "typename": "pentium3-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "pentium2",
++      "typename": "pentium2-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "pentium",
++      "typename": "pentium-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "n270",
++      "typename": "n270-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "kvm64",
++      "typename": "kvm64-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "kvm32",
++      "typename": "kvm32-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "cpu64-rhel6",
++      "typename": "cpu64-rhel6-x86_64-cpu",
++      "unavailable-features": [
++        "sse4a"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "coreduo",
++      "typename": "coreduo-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "core2duo",
++      "typename": "core2duo-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "athlon",
++      "typename": "athlon-x86_64-cpu",
++      "unavailable-features": [
++        "mmxext",
++        "3dnowext",
++        "3dnow"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Westmere",
++      "typename": "Westmere-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Westmere-IBRS",
++      "typename": "Westmere-IBRS-x86_64-cpu",
++      "unavailable-features": [
++        "spec-ctrl"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Skylake-Client",
++      "typename": "Skylake-Client-x86_64-cpu",
++      "unavailable-features": [
++        "mpx",
++        "xsavec",
++        "xgetbv1",
++        "mpx",
++        "mpx"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Skylake-Client-IBRS",
++      "typename": "Skylake-Client-IBRS-x86_64-cpu",
++      "unavailable-features": [
++        "mpx",
++        "spec-ctrl",
++        "xsavec",
++        "xgetbv1",
++        "mpx",
++        "mpx"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "SandyBridge",
++      "typename": "SandyBridge-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "SandyBridge-IBRS",
++      "typename": "SandyBridge-IBRS-x86_64-cpu",
++      "unavailable-features": [
++        "spec-ctrl"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Penryn",
++      "typename": "Penryn-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Opteron_G5",
++      "typename": "Opteron_G5-x86_64-cpu",
++      "unavailable-features": [
++        "sse4a",
++        "misalignsse",
++        "xop",
++        "fma4",
++        "tbm"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Opteron_G4",
++      "typename": "Opteron_G4-x86_64-cpu",
++      "unavailable-features": [
++        "sse4a",
++        "misalignsse",
++        "xop",
++        "fma4"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Opteron_G3",
++      "typename": "Opteron_G3-x86_64-cpu",
++      "unavailable-features": [
++        "sse4a",
++        "misalignsse"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Opteron_G2",
++      "typename": "Opteron_G2-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Opteron_G1",
++      "typename": "Opteron_G1-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Nehalem",
++      "typename": "Nehalem-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Nehalem-IBRS",
++      "typename": "Nehalem-IBRS-x86_64-cpu",
++      "unavailable-features": [
++        "spec-ctrl"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "IvyBridge",
++      "typename": "IvyBridge-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "IvyBridge-IBRS",
++      "typename": "IvyBridge-IBRS-x86_64-cpu",
++      "unavailable-features": [
++        "spec-ctrl"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Haswell",
++      "typename": "Haswell-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Haswell-noTSX",
++      "typename": "Haswell-noTSX-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Haswell-noTSX-IBRS",
++      "typename": "Haswell-noTSX-IBRS-x86_64-cpu",
++      "unavailable-features": [
++        "spec-ctrl"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Haswell-IBRS",
++      "typename": "Haswell-IBRS-x86_64-cpu",
++      "unavailable-features": [
++        "spec-ctrl"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Conroe",
++      "typename": "Conroe-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Broadwell",
++      "typename": "Broadwell-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Broadwell-noTSX",
++      "typename": "Broadwell-noTSX-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Broadwell-noTSX-IBRS",
++      "typename": "Broadwell-noTSX-IBRS-x86_64-cpu",
++      "unavailable-features": [
++        "spec-ctrl"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Broadwell-IBRS",
++      "typename": "Broadwell-IBRS-x86_64-cpu",
++      "unavailable-features": [
++        "spec-ctrl"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "486",
++      "typename": "486-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    }
++  ],
++  "id": "definitions"
++}
+diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E5-2630-v4.xml b/tests/cputestdata/x86_64-cpuid-Xeon-E5-2630-v4.xml
+new file mode 100644
+index 0000000000..d74c207104
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Xeon-E5-2630-v4.xml
+@@ -0,0 +1,43 @@
++<!-- Intel(R) Xeon(R) CPU E5-2630 v4 @ 2.20GHz -->
++<cpudata arch='x86'>
++  <cpuid eax_in='0x00000000' ecx_in='0x00' eax='0x00000014' ebx='0x756e6547' ecx='0x6c65746e' edx='0x49656e69'/>
++  <cpuid eax_in='0x00000001' ecx_in='0x00' eax='0x000406f1' ebx='0x01200800' ecx='0x7ffefbff' edx='0xbfebfbff'/>
++  <cpuid eax_in='0x00000002' ecx_in='0x00' eax='0x76036301' ebx='0x00f0b5ff' ecx='0x00000000' edx='0x00c30000'/>
++  <cpuid eax_in='0x00000003' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x00000004' ecx_in='0x00' eax='0x3c004121' ebx='0x01c0003f' ecx='0x0000003f' edx='0x00000000'/>
++  <cpuid eax_in='0x00000004' ecx_in='0x01' eax='0x3c004122' ebx='0x01c0003f' ecx='0x0000003f' edx='0x00000000'/>
++  <cpuid eax_in='0x00000004' ecx_in='0x02' eax='0x3c004143' ebx='0x01c0003f' ecx='0x000001ff' edx='0x00000000'/>
++  <cpuid eax_in='0x00000004' ecx_in='0x03' eax='0x3c07c163' ebx='0x04c0003f' ecx='0x00004fff' edx='0x00000006'/>
++  <cpuid eax_in='0x00000005' ecx_in='0x00' eax='0x00000040' ebx='0x00000040' ecx='0x00000003' edx='0x00002120'/>
++  <cpuid eax_in='0x00000006' ecx_in='0x00' eax='0x00000077' ebx='0x00000002' ecx='0x00000009' edx='0x00000000'/>
++  <cpuid eax_in='0x00000007' ecx_in='0x00' eax='0x00000000' ebx='0x021cbfbb' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x00000008' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x00000009' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x0000000a' ecx_in='0x00' eax='0x07300403' ebx='0x00000000' ecx='0x00000000' edx='0x00000603'/>
++  <cpuid eax_in='0x0000000b' ecx_in='0x00' eax='0x00000001' ebx='0x00000002' ecx='0x00000100' edx='0x00000001'/>
++  <cpuid eax_in='0x0000000b' ecx_in='0x01' eax='0x00000005' ebx='0x00000014' ecx='0x00000201' edx='0x00000001'/>
++  <cpuid eax_in='0x0000000c' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x0000000d' ecx_in='0x00' eax='0x00000007' ebx='0x00000340' ecx='0x00000340' edx='0x00000000'/>
++  <cpuid eax_in='0x0000000d' ecx_in='0x01' eax='0x00000001' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x0000000d' ecx_in='0x02' eax='0x00000100' ebx='0x00000240' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x0000000e' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x0000000f' ecx_in='0x00' eax='0x00000000' ebx='0x0000004f' ecx='0x00000000' edx='0x00000002'/>
++  <cpuid eax_in='0x0000000f' ecx_in='0x01' eax='0x00000000' ebx='0x0000a000' ecx='0x0000004f' edx='0x00000007'/>
++  <cpuid eax_in='0x00000010' ecx_in='0x00' eax='0x00000000' ebx='0x00000002' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x00000010' ecx_in='0x01' eax='0x00000013' ebx='0x000c0000' ecx='0x00000004' edx='0x0000000f'/>
++  <cpuid eax_in='0x00000011' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x00000012' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x00000013' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x00000014' ecx_in='0x00' eax='0x00000000' ebx='0x00000001' ecx='0x00000001' edx='0x00000000'/>
++  <cpuid eax_in='0x80000000' ecx_in='0x00' eax='0x80000008' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x80000001' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000121' edx='0x2c100800'/>
++  <cpuid eax_in='0x80000002' ecx_in='0x00' eax='0x65746e49' ebx='0x2952286c' ecx='0x6f655820' edx='0x2952286e'/>
++  <cpuid eax_in='0x80000003' ecx_in='0x00' eax='0x55504320' ebx='0x2d354520' ecx='0x30333632' edx='0x20347620'/>
++  <cpuid eax_in='0x80000004' ecx_in='0x00' eax='0x2e322040' ebx='0x48473032' ecx='0x0000007a' edx='0x00000000'/>
++  <cpuid eax_in='0x80000005' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x80000006' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x01006040' edx='0x00000000'/>
++  <cpuid eax_in='0x80000007' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000100'/>
++  <cpuid eax_in='0x80000008' ecx_in='0x00' eax='0x0000302e' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x80860000' ecx_in='0x00' eax='0x00000000' ebx='0x00000001' ecx='0x00000001' edx='0x00000000'/>
++  <cpuid eax_in='0xc0000000' ecx_in='0x00' eax='0x00000000' ebx='0x00000001' ecx='0x00000001' edx='0x00000000'/>
++</cpudata>
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-cputest-Add-data-for-Intel-R-Xeon-R-CPU-E5-2650.patch b/SOURCES/libvirt-cputest-Add-data-for-Intel-R-Xeon-R-CPU-E5-2650.patch
new file mode 100644
index 0000000..eb8dcdb
--- /dev/null
+++ b/SOURCES/libvirt-cputest-Add-data-for-Intel-R-Xeon-R-CPU-E5-2650.patch
@@ -0,0 +1,1144 @@
+From 2afffd01a71c3b2efeeaefed4829a87d46956c8b Mon Sep 17 00:00:00 2001
+Message-Id: <2afffd01a71c3b2efeeaefed4829a87d46956c8b@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:24:52 +0200
+Subject: [PATCH] cputest: Add data for Intel(R) Xeon(R) CPU E5-2650
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit 483679d48f6b5fb731bdedca3b5d3b33c011d6a3)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1686895
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <944ffeee03d77b02d000ea6c70d98307d850eaad.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ tests/cputest.c                               |   1 +
+ .../x86_64-cpuid-Xeon-E5-2650-disabled.xml    |   5 +
+ .../x86_64-cpuid-Xeon-E5-2650-enabled.xml     |   8 +
+ .../x86_64-cpuid-Xeon-E5-2650-guest.xml       |  29 +
+ .../x86_64-cpuid-Xeon-E5-2650-host.xml        |  30 +
+ .../x86_64-cpuid-Xeon-E5-2650-json.xml        |  14 +
+ .../x86_64-cpuid-Xeon-E5-2650.json            | 931 ++++++++++++++++++
+ .../cputestdata/x86_64-cpuid-Xeon-E5-2650.xml |  34 +
+ 8 files changed, 1052 insertions(+)
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-E5-2650-disabled.xml
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-E5-2650-enabled.xml
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-E5-2650-guest.xml
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-E5-2650-host.xml
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-E5-2650-json.xml
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-E5-2650.json
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-E5-2650.xml
+
+diff --git a/tests/cputest.c b/tests/cputest.c
+index e2c7860f3f..bcbfe2d08a 100644
+--- a/tests/cputest.c
++++ b/tests/cputest.c
+@@ -1197,6 +1197,7 @@ mymain(void)
+     DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-E5-2623-v4", JSON_MODELS);
+     DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-E5-2630-v3", JSON_HOST);
+     DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-E5-2630-v4", JSON_MODELS);
++    DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-E5-2650", JSON_MODELS);
+     DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-E5-2650-v3", JSON_HOST);
+     DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-E5-2650-v4", JSON_MODELS);
+     DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-E7-4820", JSON_HOST);
+diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E5-2650-disabled.xml b/tests/cputestdata/x86_64-cpuid-Xeon-E5-2650-disabled.xml
+new file mode 100644
+index 0000000000..d9538892eb
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Xeon-E5-2650-disabled.xml
+@@ -0,0 +1,5 @@
++<!-- Features disabled by QEMU -->
++<cpudata arch='x86'>
++  <cpuid eax_in='0x00000001' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x0804c1fc' edx='0xb0600000'/>
++  <cpuid eax_in='0x80000007' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000100'/>
++</cpudata>
+diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E5-2650-enabled.xml b/tests/cputestdata/x86_64-cpuid-Xeon-E5-2650-enabled.xml
+new file mode 100644
+index 0000000000..fcc1e84686
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Xeon-E5-2650-enabled.xml
+@@ -0,0 +1,8 @@
++<!-- Features enabled by QEMU -->
++<cpudata arch='x86'>
++  <cpuid eax_in='0x00000001' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x97ba2203' edx='0x0f8bfbff'/>
++  <cpuid eax_in='0x00000006' ecx_in='0x00' eax='0x00000004' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x00000007' ecx_in='0x00' eax='0x00000000' ebx='0x00000002' ecx='0x00000000' edx='0x8c000000'/>
++  <cpuid eax_in='0x0000000d' ecx_in='0x01' eax='0x00000001' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x80000001' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000001' edx='0x2c100800'/>
++</cpudata>
+diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E5-2650-guest.xml b/tests/cputestdata/x86_64-cpuid-Xeon-E5-2650-guest.xml
+new file mode 100644
+index 0000000000..e507642df1
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Xeon-E5-2650-guest.xml
+@@ -0,0 +1,29 @@
++<cpu mode='custom' match='exact'>
++  <model fallback='forbid'>SandyBridge-IBRS</model>
++  <vendor>Intel</vendor>
++  <feature policy='require' name='vme'/>
++  <feature policy='require' name='ds'/>
++  <feature policy='require' name='acpi'/>
++  <feature policy='require' name='ss'/>
++  <feature policy='require' name='ht'/>
++  <feature policy='require' name='tm'/>
++  <feature policy='require' name='pbe'/>
++  <feature policy='require' name='dtes64'/>
++  <feature policy='require' name='monitor'/>
++  <feature policy='require' name='ds_cpl'/>
++  <feature policy='require' name='vmx'/>
++  <feature policy='require' name='smx'/>
++  <feature policy='require' name='est'/>
++  <feature policy='require' name='tm2'/>
++  <feature policy='require' name='xtpr'/>
++  <feature policy='require' name='pdcm'/>
++  <feature policy='require' name='pcid'/>
++  <feature policy='require' name='dca'/>
++  <feature policy='require' name='osxsave'/>
++  <feature policy='require' name='arat'/>
++  <feature policy='require' name='stibp'/>
++  <feature policy='require' name='ssbd'/>
++  <feature policy='require' name='xsaveopt'/>
++  <feature policy='require' name='pdpe1gb'/>
++  <feature policy='require' name='invtsc'/>
++</cpu>
+diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E5-2650-host.xml b/tests/cputestdata/x86_64-cpuid-Xeon-E5-2650-host.xml
+new file mode 100644
+index 0000000000..80ca6c343f
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Xeon-E5-2650-host.xml
+@@ -0,0 +1,30 @@
++<cpu>
++  <arch>x86_64</arch>
++  <model>SandyBridge-IBRS</model>
++  <vendor>Intel</vendor>
++  <feature name='vme'/>
++  <feature name='ds'/>
++  <feature name='acpi'/>
++  <feature name='ss'/>
++  <feature name='ht'/>
++  <feature name='tm'/>
++  <feature name='pbe'/>
++  <feature name='dtes64'/>
++  <feature name='monitor'/>
++  <feature name='ds_cpl'/>
++  <feature name='vmx'/>
++  <feature name='smx'/>
++  <feature name='est'/>
++  <feature name='tm2'/>
++  <feature name='xtpr'/>
++  <feature name='pdcm'/>
++  <feature name='pcid'/>
++  <feature name='dca'/>
++  <feature name='osxsave'/>
++  <feature name='arat'/>
++  <feature name='stibp'/>
++  <feature name='ssbd'/>
++  <feature name='xsaveopt'/>
++  <feature name='pdpe1gb'/>
++  <feature name='invtsc'/>
++</cpu>
+diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E5-2650-json.xml b/tests/cputestdata/x86_64-cpuid-Xeon-E5-2650-json.xml
+new file mode 100644
+index 0000000000..bf587d3ffc
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Xeon-E5-2650-json.xml
+@@ -0,0 +1,14 @@
++<cpu mode='custom' match='exact'>
++  <model fallback='forbid'>SandyBridge-IBRS</model>
++  <vendor>Intel</vendor>
++  <feature policy='require' name='vme'/>
++  <feature policy='require' name='ss'/>
++  <feature policy='require' name='pcid'/>
++  <feature policy='require' name='hypervisor'/>
++  <feature policy='require' name='arat'/>
++  <feature policy='require' name='tsc_adjust'/>
++  <feature policy='require' name='stibp'/>
++  <feature policy='require' name='ssbd'/>
++  <feature policy='require' name='xsaveopt'/>
++  <feature policy='require' name='pdpe1gb'/>
++</cpu>
+diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E5-2650.json b/tests/cputestdata/x86_64-cpuid-Xeon-E5-2650.json
+new file mode 100644
+index 0000000000..a7a8542203
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Xeon-E5-2650.json
+@@ -0,0 +1,931 @@
++{
++  "return": {
++    "model": {
++      "name": "base",
++      "props": {
++        "phys-bits": 0,
++        "core-id": -1,
++        "xlevel": 2147483656,
++        "cmov": true,
++        "ia64": false,
++        "aes": true,
++        "mmx": true,
++        "rdpid": false,
++        "arat": true,
++        "gfni": false,
++        "pause-filter": false,
++        "xsavec": false,
++        "intel-pt": false,
++        "osxsave": false,
++        "hv-frequencies": false,
++        "tsc-frequency": 0,
++        "xd": true,
++        "hv-vendor-id": "",
++        "kvm-asyncpf": true,
++        "kvm_asyncpf": true,
++        "perfctr_core": false,
++        "perfctr-core": false,
++        "mpx": false,
++        "pbe": false,
++        "decodeassists": false,
++        "avx512cd": false,
++        "sse4_1": true,
++        "sse4.1": true,
++        "sse4-1": true,
++        "family": 6,
++        "legacy-cache": true,
++        "vmware-cpuid-freq": true,
++        "avx512f": false,
++        "msr": true,
++        "mce": true,
++        "mca": true,
++        "hv-runtime": false,
++        "xcrypt": false,
++        "thread-id": -1,
++        "min-level": 13,
++        "xgetbv1": false,
++        "cid": false,
++        "hv-relaxed": false,
++        "hv-crash": false,
++        "ds": false,
++        "fxsr": true,
++        "xsaveopt": true,
++        "xtpr": false,
++        "avx512vl": false,
++        "avx512-vpopcntdq": false,
++        "phe": false,
++        "extapic": false,
++        "3dnowprefetch": false,
++        "avx512vbmi2": false,
++        "cr8legacy": false,
++        "stibp": true,
++        "cpuid-0xb": true,
++        "xcrypt-en": false,
++        "kvm_pv_eoi": true,
++        "apic-id": 4294967295,
++        "pn": false,
++        "dca": false,
++        "vendor": "GenuineIntel",
++        "pku": false,
++        "smx": false,
++        "cmp_legacy": false,
++        "cmp-legacy": false,
++        "node-id": -1,
++        "avx512-4fmaps": false,
++        "vmcb_clean": false,
++        "vmcb-clean": false,
++        "3dnowext": false,
++        "hle": false,
++        "npt": false,
++        "memory": "/machine/unattached/system[0]",
++        "clwb": false,
++        "lbrv": false,
++        "adx": false,
++        "ss": true,
++        "pni": true,
++        "svm_lock": false,
++        "svm-lock": false,
++        "pfthreshold": false,
++        "smep": false,
++        "smap": false,
++        "x2apic": true,
++        "avx512vbmi": false,
++        "avx512vnni": false,
++        "hv-stimer": false,
++        "i64": true,
++        "flushbyasid": false,
++        "f16c": false,
++        "ace2-en": false,
++        "pat": true,
++        "pae": true,
++        "sse": true,
++        "phe-en": false,
++        "kvm_nopiodelay": true,
++        "kvm-nopiodelay": true,
++        "tm": false,
++        "kvmclock-stable-bit": true,
++        "hypervisor": true,
++        "socket-id": -1,
++        "pcommit": false,
++        "syscall": true,
++        "level": 13,
++        "avx512dq": false,
++        "svm": false,
++        "full-cpuid-auto-level": true,
++        "hv-reset": false,
++        "invtsc": false,
++        "sse3": true,
++        "sse2": true,
++        "ssbd": true,
++        "est": false,
++        "avx512ifma": false,
++        "tm2": false,
++        "kvm-pv-eoi": true,
++        "cx8": true,
++        "kvm_mmu": false,
++        "kvm-mmu": false,
++        "sse4_2": true,
++        "sse4.2": true,
++        "sse4-2": true,
++        "pge": true,
++        "fill-mtrr-mask": true,
++        "avx512bitalg": false,
++        "nodeid_msr": false,
++        "pdcm": false,
++        "movbe": false,
++        "model": 45,
++        "nrip_save": false,
++        "nrip-save": false,
++        "kvm_pv_unhalt": true,
++        "ssse3": true,
++        "sse4a": false,
++        "invpcid": false,
++        "pdpe1gb": true,
++        "tsc-deadline": true,
++        "fma": false,
++        "cx16": true,
++        "de": true,
++        "enforce": false,
++        "stepping": 7,
++        "xsave": true,
++        "clflush": true,
++        "skinit": false,
++        "tsc": true,
++        "tce": false,
++        "fpu": true,
++        "ibs": false,
++        "ds_cpl": false,
++        "ds-cpl": false,
++        "host-phys-bits": true,
++        "fma4": false,
++        "la57": false,
++        "osvw": false,
++        "check": true,
++        "hv-spinlocks": -1,
++        "pmu": false,
++        "pmm": false,
++        "apic": true,
++        "spec-ctrl": true,
++        "min-xlevel2": 0,
++        "tsc-adjust": true,
++        "tsc_adjust": true,
++        "kvm-steal-time": true,
++        "kvm_steal_time": true,
++        "kvmclock": true,
++        "l3-cache": true,
++        "lwp": false,
++        "ibpb": false,
++        "xop": false,
++        "avx": true,
++        "ospke": false,
++        "ace2": false,
++        "avx512bw": false,
++        "acpi": false,
++        "hv-vapic": false,
++        "fsgsbase": false,
++        "ht": false,
++        "nx": true,
++        "pclmulqdq": true,
++        "mmxext": false,
++        "vaes": false,
++        "popcnt": true,
++        "xsaves": false,
++        "tcg-cpuid": true,
++        "lm": true,
++        "umip": false,
++        "pse": true,
++        "avx2": false,
++        "sep": true,
++        "pclmuldq": true,
++        "virt-ssbd": false,
++        "x-hv-max-vps": -1,
++        "nodeid-msr": false,
++        "kvm": true,
++        "misalignsse": false,
++        "min-xlevel": 2147483656,
++        "kvm-pv-unhalt": true,
++        "bmi2": false,
++        "bmi1": false,
++        "realized": false,
++        "tsc_scale": false,
++        "tsc-scale": false,
++        "topoext": false,
++        "hv-vpindex": false,
++        "xlevel2": 0,
++        "clflushopt": false,
++        "kvm-no-smi-migration": false,
++        "monitor": false,
++        "avx512er": false,
++        "pmm-en": false,
++        "pcid": true,
++        "3dnow": false,
++        "erms": false,
++        "lahf-lm": true,
++        "lahf_lm": true,
++        "vpclmulqdq": false,
++        "fxsr-opt": false,
++        "hv-synic": false,
++        "xstore": false,
++        "fxsr_opt": false,
++        "kvm-hint-dedicated": false,
++        "rtm": false,
++        "lmce": true,
++        "hv-time": false,
++        "perfctr-nb": false,
++        "perfctr_nb": false,
++        "ffxsr": false,
++        "rdrand": false,
++        "rdseed": false,
++        "avx512-4vnniw": false,
++        "vmx": false,
++        "vme": true,
++        "dtes64": false,
++        "mtrr": true,
++        "rdtscp": true,
++        "pse36": true,
++        "kvm-pv-tlb-flush": false,
++        "tbm": false,
++        "wdt": false,
++        "pause_filter": false,
++        "sha-ni": false,
++        "model-id": "       Intel(R) Xeon(R) CPU E5-2650 0 @ 2.00GHz",
++        "abm": false,
++        "avx512pf": false,
++        "xstore-en": false
++      }
++    }
++  },
++  "id": "model-expansion"
++}
++
++{
++  "return": [
++    {
++      "name": "max",
++      "typename": "max-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": false
++    },
++    {
++      "name": "host",
++      "typename": "host-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": false
++    },
++    {
++      "name": "base",
++      "typename": "base-x86_64-cpu",
++      "unavailable-features": [],
++      "static": true,
++      "migration-safe": true
++    },
++    {
++      "name": "qemu64",
++      "typename": "qemu64-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "qemu32",
++      "typename": "qemu32-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "phenom",
++      "typename": "phenom-x86_64-cpu",
++      "unavailable-features": [
++        "mmxext",
++        "fxsr-opt",
++        "3dnowext",
++        "3dnow",
++        "abm",
++        "sse4a",
++        "npt"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "pentium3",
++      "typename": "pentium3-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "pentium2",
++      "typename": "pentium2-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "pentium",
++      "typename": "pentium-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "n270",
++      "typename": "n270-x86_64-cpu",
++      "unavailable-features": [
++        "movbe"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "kvm64",
++      "typename": "kvm64-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "kvm32",
++      "typename": "kvm32-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "cpu64-rhel6",
++      "typename": "cpu64-rhel6-x86_64-cpu",
++      "unavailable-features": [
++        "abm",
++        "sse4a"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "coreduo",
++      "typename": "coreduo-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "core2duo",
++      "typename": "core2duo-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "athlon",
++      "typename": "athlon-x86_64-cpu",
++      "unavailable-features": [
++        "mmxext",
++        "3dnowext",
++        "3dnow"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Westmere",
++      "typename": "Westmere-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Westmere-IBRS",
++      "typename": "Westmere-IBRS-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Skylake-Server",
++      "typename": "Skylake-Server-x86_64-cpu",
++      "unavailable-features": [
++        "fma",
++        "movbe",
++        "f16c",
++        "rdrand",
++        "fsgsbase",
++        "bmi1",
++        "hle",
++        "avx2",
++        "smep",
++        "bmi2",
++        "erms",
++        "invpcid",
++        "rtm",
++        "mpx",
++        "avx512f",
++        "avx512dq",
++        "rdseed",
++        "adx",
++        "smap",
++        "clflushopt",
++        "clwb",
++        "avx512cd",
++        "avx512bw",
++        "avx512vl",
++        "abm",
++        "3dnowprefetch",
++        "xsavec",
++        "xgetbv1",
++        "mpx",
++        "mpx",
++        "avx512f",
++        "avx512f",
++        "avx512f"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Skylake-Server-IBRS",
++      "typename": "Skylake-Server-IBRS-x86_64-cpu",
++      "unavailable-features": [
++        "fma",
++        "movbe",
++        "f16c",
++        "rdrand",
++        "fsgsbase",
++        "bmi1",
++        "hle",
++        "avx2",
++        "smep",
++        "bmi2",
++        "erms",
++        "invpcid",
++        "rtm",
++        "mpx",
++        "avx512f",
++        "avx512dq",
++        "rdseed",
++        "adx",
++        "smap",
++        "clwb",
++        "avx512cd",
++        "avx512bw",
++        "avx512vl",
++        "abm",
++        "3dnowprefetch",
++        "xsavec",
++        "xgetbv1",
++        "mpx",
++        "mpx",
++        "avx512f",
++        "avx512f",
++        "avx512f"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Skylake-Client",
++      "typename": "Skylake-Client-x86_64-cpu",
++      "unavailable-features": [
++        "fma",
++        "movbe",
++        "f16c",
++        "rdrand",
++        "fsgsbase",
++        "bmi1",
++        "hle",
++        "avx2",
++        "smep",
++        "bmi2",
++        "erms",
++        "invpcid",
++        "rtm",
++        "mpx",
++        "rdseed",
++        "adx",
++        "smap",
++        "abm",
++        "3dnowprefetch",
++        "xsavec",
++        "xgetbv1",
++        "mpx",
++        "mpx"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Skylake-Client-IBRS",
++      "typename": "Skylake-Client-IBRS-x86_64-cpu",
++      "unavailable-features": [
++        "fma",
++        "movbe",
++        "f16c",
++        "rdrand",
++        "fsgsbase",
++        "bmi1",
++        "hle",
++        "avx2",
++        "smep",
++        "bmi2",
++        "erms",
++        "invpcid",
++        "rtm",
++        "mpx",
++        "rdseed",
++        "adx",
++        "smap",
++        "abm",
++        "3dnowprefetch",
++        "xsavec",
++        "xgetbv1",
++        "mpx",
++        "mpx"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "SandyBridge",
++      "typename": "SandyBridge-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "SandyBridge-IBRS",
++      "typename": "SandyBridge-IBRS-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Penryn",
++      "typename": "Penryn-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Opteron_G5",
++      "typename": "Opteron_G5-x86_64-cpu",
++      "unavailable-features": [
++        "fma",
++        "f16c",
++        "abm",
++        "sse4a",
++        "misalignsse",
++        "3dnowprefetch",
++        "xop",
++        "fma4",
++        "tbm"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Opteron_G4",
++      "typename": "Opteron_G4-x86_64-cpu",
++      "unavailable-features": [
++        "abm",
++        "sse4a",
++        "misalignsse",
++        "3dnowprefetch",
++        "xop",
++        "fma4"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Opteron_G3",
++      "typename": "Opteron_G3-x86_64-cpu",
++      "unavailable-features": [
++        "abm",
++        "sse4a",
++        "misalignsse"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Opteron_G2",
++      "typename": "Opteron_G2-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Opteron_G1",
++      "typename": "Opteron_G1-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Nehalem",
++      "typename": "Nehalem-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Nehalem-IBRS",
++      "typename": "Nehalem-IBRS-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "IvyBridge",
++      "typename": "IvyBridge-x86_64-cpu",
++      "unavailable-features": [
++        "f16c",
++        "rdrand",
++        "fsgsbase",
++        "smep",
++        "erms"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "IvyBridge-IBRS",
++      "typename": "IvyBridge-IBRS-x86_64-cpu",
++      "unavailable-features": [
++        "f16c",
++        "rdrand",
++        "fsgsbase",
++        "smep",
++        "erms"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Haswell",
++      "typename": "Haswell-x86_64-cpu",
++      "unavailable-features": [
++        "fma",
++        "movbe",
++        "f16c",
++        "rdrand",
++        "fsgsbase",
++        "bmi1",
++        "hle",
++        "avx2",
++        "smep",
++        "bmi2",
++        "erms",
++        "invpcid",
++        "rtm",
++        "abm"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Haswell-noTSX",
++      "typename": "Haswell-noTSX-x86_64-cpu",
++      "unavailable-features": [
++        "fma",
++        "movbe",
++        "f16c",
++        "rdrand",
++        "fsgsbase",
++        "bmi1",
++        "avx2",
++        "smep",
++        "bmi2",
++        "erms",
++        "invpcid",
++        "abm"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Haswell-noTSX-IBRS",
++      "typename": "Haswell-noTSX-IBRS-x86_64-cpu",
++      "unavailable-features": [
++        "fma",
++        "movbe",
++        "f16c",
++        "rdrand",
++        "fsgsbase",
++        "bmi1",
++        "avx2",
++        "smep",
++        "bmi2",
++        "erms",
++        "invpcid",
++        "abm"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Haswell-IBRS",
++      "typename": "Haswell-IBRS-x86_64-cpu",
++      "unavailable-features": [
++        "fma",
++        "movbe",
++        "f16c",
++        "rdrand",
++        "fsgsbase",
++        "bmi1",
++        "hle",
++        "avx2",
++        "smep",
++        "bmi2",
++        "erms",
++        "invpcid",
++        "rtm",
++        "abm"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "EPYC",
++      "typename": "EPYC-x86_64-cpu",
++      "unavailable-features": [
++        "fma",
++        "movbe",
++        "f16c",
++        "rdrand",
++        "fsgsbase",
++        "bmi1",
++        "avx2",
++        "smep",
++        "bmi2",
++        "rdseed",
++        "adx",
++        "smap",
++        "clflushopt",
++        "sha-ni",
++        "mmxext",
++        "fxsr-opt",
++        "cr8legacy",
++        "abm",
++        "sse4a",
++        "misalignsse",
++        "3dnowprefetch",
++        "osvw",
++        "xsavec",
++        "xgetbv1"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "EPYC-IBPB",
++      "typename": "EPYC-IBPB-x86_64-cpu",
++      "unavailable-features": [
++        "fma",
++        "movbe",
++        "f16c",
++        "rdrand",
++        "fsgsbase",
++        "bmi1",
++        "avx2",
++        "smep",
++        "bmi2",
++        "rdseed",
++        "adx",
++        "smap",
++        "clflushopt",
++        "sha-ni",
++        "mmxext",
++        "fxsr-opt",
++        "cr8legacy",
++        "abm",
++        "sse4a",
++        "misalignsse",
++        "3dnowprefetch",
++        "osvw",
++        "ibpb",
++        "xsavec",
++        "xgetbv1"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Conroe",
++      "typename": "Conroe-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Broadwell",
++      "typename": "Broadwell-x86_64-cpu",
++      "unavailable-features": [
++        "fma",
++        "movbe",
++        "f16c",
++        "rdrand",
++        "fsgsbase",
++        "bmi1",
++        "hle",
++        "avx2",
++        "smep",
++        "bmi2",
++        "erms",
++        "invpcid",
++        "rtm",
++        "rdseed",
++        "adx",
++        "smap",
++        "abm",
++        "3dnowprefetch"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Broadwell-noTSX",
++      "typename": "Broadwell-noTSX-x86_64-cpu",
++      "unavailable-features": [
++        "fma",
++        "movbe",
++        "f16c",
++        "rdrand",
++        "fsgsbase",
++        "bmi1",
++        "avx2",
++        "smep",
++        "bmi2",
++        "erms",
++        "invpcid",
++        "rdseed",
++        "adx",
++        "smap",
++        "abm",
++        "3dnowprefetch"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Broadwell-noTSX-IBRS",
++      "typename": "Broadwell-noTSX-IBRS-x86_64-cpu",
++      "unavailable-features": [
++        "fma",
++        "movbe",
++        "f16c",
++        "rdrand",
++        "fsgsbase",
++        "bmi1",
++        "avx2",
++        "smep",
++        "bmi2",
++        "erms",
++        "invpcid",
++        "rdseed",
++        "adx",
++        "smap",
++        "abm",
++        "3dnowprefetch"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Broadwell-IBRS",
++      "typename": "Broadwell-IBRS-x86_64-cpu",
++      "unavailable-features": [
++        "fma",
++        "movbe",
++        "f16c",
++        "rdrand",
++        "fsgsbase",
++        "bmi1",
++        "hle",
++        "avx2",
++        "smep",
++        "bmi2",
++        "erms",
++        "invpcid",
++        "rtm",
++        "rdseed",
++        "adx",
++        "smap",
++        "abm",
++        "3dnowprefetch"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "486",
++      "typename": "486-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    }
++  ],
++  "id": "definitions"
++}
+diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E5-2650.xml b/tests/cputestdata/x86_64-cpuid-Xeon-E5-2650.xml
+new file mode 100644
+index 0000000000..b7ce0631ca
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Xeon-E5-2650.xml
+@@ -0,0 +1,34 @@
++<!-- Intel(R) Xeon(R) CPU E5-2650 0 @ 2.00GHz -->
++<cpudata arch='x86'>
++  <cpuid eax_in='0x00000000' ecx_in='0x00' eax='0x0000000d' ebx='0x756e6547' ecx='0x6c65746e' edx='0x49656e69'/>
++  <cpuid eax_in='0x00000001' ecx_in='0x00' eax='0x000206d7' ebx='0x05200800' ecx='0x1fbee3ff' edx='0xbfebfbff'/>
++  <cpuid eax_in='0x00000002' ecx_in='0x00' eax='0x76035a01' ebx='0x00f0b2ff' ecx='0x00000000' edx='0x00ca0000'/>
++  <cpuid eax_in='0x00000003' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x00000004' ecx_in='0x00' eax='0x3c004121' ebx='0x01c0003f' ecx='0x0000003f' edx='0x00000000'/>
++  <cpuid eax_in='0x00000004' ecx_in='0x01' eax='0x3c004122' ebx='0x01c0003f' ecx='0x0000003f' edx='0x00000000'/>
++  <cpuid eax_in='0x00000004' ecx_in='0x02' eax='0x3c004143' ebx='0x01c0003f' ecx='0x000001ff' edx='0x00000000'/>
++  <cpuid eax_in='0x00000004' ecx_in='0x03' eax='0x3c07c163' ebx='0x04c0003f' ecx='0x00003fff' edx='0x00000006'/>
++  <cpuid eax_in='0x00000005' ecx_in='0x00' eax='0x00000040' ebx='0x00000040' ecx='0x00000003' edx='0x00021120'/>
++  <cpuid eax_in='0x00000006' ecx_in='0x00' eax='0x00000077' ebx='0x00000002' ecx='0x00000009' edx='0x00000000'/>
++  <cpuid eax_in='0x00000007' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x9c000000'/>
++  <cpuid eax_in='0x00000008' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x00000009' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x0000000a' ecx_in='0x00' eax='0x07300403' ebx='0x00000000' ecx='0x00000000' edx='0x00000603'/>
++  <cpuid eax_in='0x0000000b' ecx_in='0x00' eax='0x00000001' ebx='0x00000002' ecx='0x00000100' edx='0x00000005'/>
++  <cpuid eax_in='0x0000000b' ecx_in='0x01' eax='0x00000005' ebx='0x00000010' ecx='0x00000201' edx='0x00000005'/>
++  <cpuid eax_in='0x0000000c' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x0000000d' ecx_in='0x00' eax='0x00000007' ebx='0x00000340' ecx='0x00000340' edx='0x00000000'/>
++  <cpuid eax_in='0x0000000d' ecx_in='0x01' eax='0x00000001' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x0000000d' ecx_in='0x02' eax='0x00000100' ebx='0x00000240' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x80000000' ecx_in='0x00' eax='0x80000008' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x80000001' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000001' edx='0x2c100800'/>
++  <cpuid eax_in='0x80000002' ecx_in='0x00' eax='0x20202020' ebx='0x49202020' ecx='0x6c65746e' edx='0x20295228'/>
++  <cpuid eax_in='0x80000003' ecx_in='0x00' eax='0x6e6f6558' ebx='0x20295228' ecx='0x20555043' edx='0x322d3545'/>
++  <cpuid eax_in='0x80000004' ecx_in='0x00' eax='0x20303536' ebx='0x20402030' ecx='0x30302e32' edx='0x007a4847'/>
++  <cpuid eax_in='0x80000005' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x80000006' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x01006040' edx='0x00000000'/>
++  <cpuid eax_in='0x80000007' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000100'/>
++  <cpuid eax_in='0x80000008' ecx_in='0x00' eax='0x0000302e' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x80860000' ecx_in='0x00' eax='0x00000007' ebx='0x00000340' ecx='0x00000340' edx='0x00000000'/>
++  <cpuid eax_in='0xc0000000' ecx_in='0x00' eax='0x00000007' ebx='0x00000340' ecx='0x00000340' edx='0x00000000'/>
++</cpudata>
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-cputest-Add-data-for-Intel-R-Xeon-R-CPU-E7540.patch b/SOURCES/libvirt-cputest-Add-data-for-Intel-R-Xeon-R-CPU-E7540.patch
new file mode 100644
index 0000000..cf8ab88
--- /dev/null
+++ b/SOURCES/libvirt-cputest-Add-data-for-Intel-R-Xeon-R-CPU-E7540.patch
@@ -0,0 +1,1317 @@
+From 50d3fe22f84e93fec523ae24302deac54db1dcfd Mon Sep 17 00:00:00 2001
+Message-Id: <50d3fe22f84e93fec523ae24302deac54db1dcfd@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:24:51 +0200
+Subject: [PATCH] cputest: Add data for Intel(R) Xeon(R) CPU E7540
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit 60046a236583a2f19c0ba6e7ab3a2823d20f177e)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1686895
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <7d56c795395ebb6b92d8650f5f956f7ddbb98947.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ tests/cputest.c                               |    1 +
+ .../x86_64-cpuid-Xeon-E7540-disabled.xml      |    5 +
+ .../x86_64-cpuid-Xeon-E7540-enabled.xml       |    7 +
+ .../x86_64-cpuid-Xeon-E7540-guest.xml         |   25 +
+ .../x86_64-cpuid-Xeon-E7540-host.xml          |   26 +
+ .../x86_64-cpuid-Xeon-E7540-json.xml          |   14 +
+ .../cputestdata/x86_64-cpuid-Xeon-E7540.json  | 1117 +++++++++++++++++
+ tests/cputestdata/x86_64-cpuid-Xeon-E7540.xml |   30 +
+ 8 files changed, 1225 insertions(+)
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-E7540-disabled.xml
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-E7540-enabled.xml
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-E7540-guest.xml
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-E7540-host.xml
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-E7540-json.xml
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-E7540.json
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-E7540.xml
+
+diff --git a/tests/cputest.c b/tests/cputest.c
+index 28d575a784..e2c7860f3f 100644
+--- a/tests/cputest.c
++++ b/tests/cputest.c
+@@ -1202,6 +1202,7 @@ mymain(void)
+     DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-E7-4820", JSON_HOST);
+     DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-E7-4830", JSON_MODELS_REQUIRED);
+     DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-E7-8890-v3", JSON_MODELS);
++    DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-E7540", JSON_MODELS);
+     DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-Gold-5115", JSON_MODELS);
+     DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-Gold-6148", JSON_HOST);
+     DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-W3520", JSON_HOST);
+diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E7540-disabled.xml b/tests/cputestdata/x86_64-cpuid-Xeon-E7540-disabled.xml
+new file mode 100644
+index 0000000000..49737fbdb1
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Xeon-E7540-disabled.xml
+@@ -0,0 +1,5 @@
++<!-- Features disabled by QEMU -->
++<cpudata arch='x86'>
++  <cpuid eax_in='0x00000001' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x0004c1bc' edx='0xb0600000'/>
++  <cpuid eax_in='0x80000007' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000100'/>
++</cpudata>
+diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E7540-enabled.xml b/tests/cputestdata/x86_64-cpuid-Xeon-E7540-enabled.xml
+new file mode 100644
+index 0000000000..8149ac04f0
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Xeon-E7540-enabled.xml
+@@ -0,0 +1,7 @@
++<!-- Features enabled by QEMU -->
++<cpudata arch='x86'>
++  <cpuid eax_in='0x00000001' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x81b82201' edx='0x0f8bfbff'/>
++  <cpuid eax_in='0x00000006' ecx_in='0x00' eax='0x00000004' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x00000007' ecx_in='0x00' eax='0x00000000' ebx='0x00000002' ecx='0x00000000' edx='0x8c000000'/>
++  <cpuid eax_in='0x80000001' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000001' edx='0x28100800'/>
++</cpudata>
+diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E7540-guest.xml b/tests/cputestdata/x86_64-cpuid-Xeon-E7540-guest.xml
+new file mode 100644
+index 0000000000..fc3e95253b
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Xeon-E7540-guest.xml
+@@ -0,0 +1,25 @@
++<cpu mode='custom' match='exact'>
++  <model fallback='forbid'>Nehalem-IBRS</model>
++  <vendor>Intel</vendor>
++  <feature policy='require' name='vme'/>
++  <feature policy='require' name='ds'/>
++  <feature policy='require' name='acpi'/>
++  <feature policy='require' name='ss'/>
++  <feature policy='require' name='ht'/>
++  <feature policy='require' name='tm'/>
++  <feature policy='require' name='pbe'/>
++  <feature policy='require' name='dtes64'/>
++  <feature policy='require' name='monitor'/>
++  <feature policy='require' name='ds_cpl'/>
++  <feature policy='require' name='vmx'/>
++  <feature policy='require' name='est'/>
++  <feature policy='require' name='tm2'/>
++  <feature policy='require' name='xtpr'/>
++  <feature policy='require' name='pdcm'/>
++  <feature policy='require' name='dca'/>
++  <feature policy='require' name='x2apic'/>
++  <feature policy='require' name='stibp'/>
++  <feature policy='require' name='ssbd'/>
++  <feature policy='require' name='rdtscp'/>
++  <feature policy='require' name='invtsc'/>
++</cpu>
+diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E7540-host.xml b/tests/cputestdata/x86_64-cpuid-Xeon-E7540-host.xml
+new file mode 100644
+index 0000000000..42b43116bd
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Xeon-E7540-host.xml
+@@ -0,0 +1,26 @@
++<cpu>
++  <arch>x86_64</arch>
++  <model>Nehalem-IBRS</model>
++  <vendor>Intel</vendor>
++  <feature name='vme'/>
++  <feature name='ds'/>
++  <feature name='acpi'/>
++  <feature name='ss'/>
++  <feature name='ht'/>
++  <feature name='tm'/>
++  <feature name='pbe'/>
++  <feature name='dtes64'/>
++  <feature name='monitor'/>
++  <feature name='ds_cpl'/>
++  <feature name='vmx'/>
++  <feature name='est'/>
++  <feature name='tm2'/>
++  <feature name='xtpr'/>
++  <feature name='pdcm'/>
++  <feature name='dca'/>
++  <feature name='x2apic'/>
++  <feature name='stibp'/>
++  <feature name='ssbd'/>
++  <feature name='rdtscp'/>
++  <feature name='invtsc'/>
++</cpu>
+diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E7540-json.xml b/tests/cputestdata/x86_64-cpuid-Xeon-E7540-json.xml
+new file mode 100644
+index 0000000000..32cd1000c8
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Xeon-E7540-json.xml
+@@ -0,0 +1,14 @@
++<cpu mode='custom' match='exact'>
++  <model fallback='forbid'>Nehalem-IBRS</model>
++  <vendor>Intel</vendor>
++  <feature policy='require' name='vme'/>
++  <feature policy='require' name='ss'/>
++  <feature policy='require' name='x2apic'/>
++  <feature policy='require' name='tsc-deadline'/>
++  <feature policy='require' name='hypervisor'/>
++  <feature policy='require' name='arat'/>
++  <feature policy='require' name='tsc_adjust'/>
++  <feature policy='require' name='stibp'/>
++  <feature policy='require' name='ssbd'/>
++  <feature policy='require' name='rdtscp'/>
++</cpu>
+diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E7540.json b/tests/cputestdata/x86_64-cpuid-Xeon-E7540.json
+new file mode 100644
+index 0000000000..ac8452509d
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Xeon-E7540.json
+@@ -0,0 +1,1117 @@
++{
++  "return": {
++    "model": {
++      "name": "base",
++      "props": {
++        "phys-bits": 0,
++        "core-id": -1,
++        "xlevel": 2147483656,
++        "cmov": true,
++        "ia64": false,
++        "aes": false,
++        "mmx": true,
++        "rdpid": false,
++        "arat": true,
++        "gfni": false,
++        "pause-filter": false,
++        "xsavec": false,
++        "intel-pt": false,
++        "osxsave": false,
++        "hv-frequencies": false,
++        "tsc-frequency": 0,
++        "xd": true,
++        "hv-vendor-id": "",
++        "kvm-asyncpf": true,
++        "kvm_asyncpf": true,
++        "perfctr_core": false,
++        "perfctr-core": false,
++        "mpx": false,
++        "pbe": false,
++        "decodeassists": false,
++        "avx512cd": false,
++        "sse4_1": true,
++        "sse4.1": true,
++        "sse4-1": true,
++        "family": 6,
++        "legacy-cache": true,
++        "vmware-cpuid-freq": true,
++        "avx512f": false,
++        "msr": true,
++        "mce": true,
++        "mca": true,
++        "hv-runtime": false,
++        "xcrypt": false,
++        "thread-id": -1,
++        "min-level": 11,
++        "xgetbv1": false,
++        "cid": false,
++        "hv-relaxed": false,
++        "hv-crash": false,
++        "ds": false,
++        "fxsr": true,
++        "xsaveopt": false,
++        "xtpr": false,
++        "avx512vl": false,
++        "avx512-vpopcntdq": false,
++        "phe": false,
++        "extapic": false,
++        "3dnowprefetch": false,
++        "avx512vbmi2": false,
++        "cr8legacy": false,
++        "stibp": true,
++        "cpuid-0xb": true,
++        "xcrypt-en": false,
++        "kvm_pv_eoi": true,
++        "apic-id": 4294967295,
++        "pn": false,
++        "dca": false,
++        "vendor": "GenuineIntel",
++        "pku": false,
++        "smx": false,
++        "cmp_legacy": false,
++        "cmp-legacy": false,
++        "node-id": -1,
++        "avx512-4fmaps": false,
++        "vmcb_clean": false,
++        "vmcb-clean": false,
++        "3dnowext": false,
++        "hle": false,
++        "npt": false,
++        "memory": "/machine/unattached/system[0]",
++        "clwb": false,
++        "lbrv": false,
++        "adx": false,
++        "ss": true,
++        "pni": true,
++        "svm_lock": false,
++        "svm-lock": false,
++        "pfthreshold": false,
++        "smep": false,
++        "smap": false,
++        "x2apic": true,
++        "avx512vbmi": false,
++        "avx512vnni": false,
++        "hv-stimer": false,
++        "i64": true,
++        "flushbyasid": false,
++        "f16c": false,
++        "ace2-en": false,
++        "pat": true,
++        "pae": true,
++        "sse": true,
++        "phe-en": false,
++        "kvm_nopiodelay": true,
++        "kvm-nopiodelay": true,
++        "tm": false,
++        "kvmclock-stable-bit": true,
++        "hypervisor": true,
++        "socket-id": -1,
++        "pcommit": false,
++        "syscall": true,
++        "level": 11,
++        "avx512dq": false,
++        "svm": false,
++        "full-cpuid-auto-level": true,
++        "hv-reset": false,
++        "invtsc": false,
++        "sse3": true,
++        "sse2": true,
++        "ssbd": true,
++        "est": false,
++        "avx512ifma": false,
++        "tm2": false,
++        "kvm-pv-eoi": true,
++        "cx8": true,
++        "kvm_mmu": false,
++        "kvm-mmu": false,
++        "sse4_2": true,
++        "sse4.2": true,
++        "sse4-2": true,
++        "pge": true,
++        "fill-mtrr-mask": true,
++        "avx512bitalg": false,
++        "nodeid_msr": false,
++        "pdcm": false,
++        "movbe": false,
++        "model": 46,
++        "nrip_save": false,
++        "nrip-save": false,
++        "kvm_pv_unhalt": true,
++        "ssse3": true,
++        "sse4a": false,
++        "invpcid": false,
++        "pdpe1gb": false,
++        "tsc-deadline": true,
++        "fma": false,
++        "cx16": true,
++        "de": true,
++        "enforce": false,
++        "stepping": 6,
++        "xsave": false,
++        "clflush": true,
++        "skinit": false,
++        "tsc": true,
++        "tce": false,
++        "fpu": true,
++        "ibs": false,
++        "ds_cpl": false,
++        "ds-cpl": false,
++        "host-phys-bits": true,
++        "fma4": false,
++        "la57": false,
++        "osvw": false,
++        "check": true,
++        "hv-spinlocks": -1,
++        "pmu": false,
++        "pmm": false,
++        "apic": true,
++        "spec-ctrl": true,
++        "min-xlevel2": 0,
++        "tsc-adjust": true,
++        "tsc_adjust": true,
++        "kvm-steal-time": true,
++        "kvm_steal_time": true,
++        "kvmclock": true,
++        "l3-cache": true,
++        "lwp": false,
++        "ibpb": false,
++        "xop": false,
++        "avx": false,
++        "ospke": false,
++        "ace2": false,
++        "avx512bw": false,
++        "acpi": false,
++        "hv-vapic": false,
++        "fsgsbase": false,
++        "ht": false,
++        "nx": true,
++        "pclmulqdq": false,
++        "mmxext": false,
++        "vaes": false,
++        "popcnt": true,
++        "xsaves": false,
++        "tcg-cpuid": true,
++        "lm": true,
++        "umip": false,
++        "pse": true,
++        "avx2": false,
++        "sep": true,
++        "pclmuldq": false,
++        "virt-ssbd": false,
++        "x-hv-max-vps": -1,
++        "nodeid-msr": false,
++        "kvm": true,
++        "misalignsse": false,
++        "min-xlevel": 2147483656,
++        "kvm-pv-unhalt": true,
++        "bmi2": false,
++        "bmi1": false,
++        "realized": false,
++        "tsc_scale": false,
++        "tsc-scale": false,
++        "topoext": false,
++        "hv-vpindex": false,
++        "xlevel2": 0,
++        "clflushopt": false,
++        "kvm-no-smi-migration": false,
++        "monitor": false,
++        "avx512er": false,
++        "pmm-en": false,
++        "pcid": false,
++        "3dnow": false,
++        "erms": false,
++        "lahf-lm": true,
++        "lahf_lm": true,
++        "vpclmulqdq": false,
++        "fxsr-opt": false,
++        "hv-synic": false,
++        "xstore": false,
++        "fxsr_opt": false,
++        "kvm-hint-dedicated": false,
++        "rtm": false,
++        "lmce": true,
++        "hv-time": false,
++        "perfctr-nb": false,
++        "perfctr_nb": false,
++        "ffxsr": false,
++        "rdrand": false,
++        "rdseed": false,
++        "avx512-4vnniw": false,
++        "vmx": false,
++        "vme": true,
++        "dtes64": false,
++        "mtrr": true,
++        "rdtscp": true,
++        "pse36": true,
++        "kvm-pv-tlb-flush": false,
++        "tbm": false,
++        "wdt": false,
++        "pause_filter": false,
++        "sha-ni": false,
++        "model-id": "Intel(R) Xeon(R) CPU           E7540  @ 2.00GHz",
++        "abm": false,
++        "avx512pf": false,
++        "xstore-en": false
++      }
++    }
++  },
++  "id": "model-expansion"
++}
++
++
++{
++  "return": [
++    {
++      "name": "max",
++      "typename": "max-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": false
++    },
++    {
++      "name": "host",
++      "typename": "host-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": false
++    },
++    {
++      "name": "base",
++      "typename": "base-x86_64-cpu",
++      "unavailable-features": [],
++      "static": true,
++      "migration-safe": true
++    },
++    {
++      "name": "qemu64",
++      "typename": "qemu64-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "qemu32",
++      "typename": "qemu32-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "phenom",
++      "typename": "phenom-x86_64-cpu",
++      "unavailable-features": [
++        "mmxext",
++        "fxsr-opt",
++        "pdpe1gb",
++        "3dnowext",
++        "3dnow",
++        "abm",
++        "sse4a",
++        "npt"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "pentium3",
++      "typename": "pentium3-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "pentium2",
++      "typename": "pentium2-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "pentium",
++      "typename": "pentium-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "n270",
++      "typename": "n270-x86_64-cpu",
++      "unavailable-features": [
++        "movbe"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "kvm64",
++      "typename": "kvm64-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "kvm32",
++      "typename": "kvm32-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "cpu64-rhel6",
++      "typename": "cpu64-rhel6-x86_64-cpu",
++      "unavailable-features": [
++        "abm",
++        "sse4a"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "coreduo",
++      "typename": "coreduo-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "core2duo",
++      "typename": "core2duo-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "athlon",
++      "typename": "athlon-x86_64-cpu",
++      "unavailable-features": [
++        "mmxext",
++        "3dnowext",
++        "3dnow"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Westmere",
++      "typename": "Westmere-x86_64-cpu",
++      "unavailable-features": [
++        "pclmulqdq",
++        "aes"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Westmere-IBRS",
++      "typename": "Westmere-IBRS-x86_64-cpu",
++      "unavailable-features": [
++        "pclmulqdq",
++        "aes"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Skylake-Server",
++      "typename": "Skylake-Server-x86_64-cpu",
++      "unavailable-features": [
++        "pclmulqdq",
++        "fma",
++        "pcid",
++        "movbe",
++        "aes",
++        "xsave",
++        "avx",
++        "f16c",
++        "rdrand",
++        "fsgsbase",
++        "bmi1",
++        "hle",
++        "avx2",
++        "smep",
++        "bmi2",
++        "erms",
++        "invpcid",
++        "rtm",
++        "mpx",
++        "avx512f",
++        "avx512dq",
++        "rdseed",
++        "adx",
++        "smap",
++        "clflushopt",
++        "clwb",
++        "avx512cd",
++        "avx512bw",
++        "avx512vl",
++        "pdpe1gb",
++        "abm",
++        "3dnowprefetch",
++        "xsaveopt",
++        "xsavec",
++        "xgetbv1",
++        "xsave",
++        "xsave",
++        "avx",
++        "mpx",
++        "mpx",
++        "avx512f",
++        "avx512f",
++        "avx512f"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Skylake-Server-IBRS",
++      "typename": "Skylake-Server-IBRS-x86_64-cpu",
++      "unavailable-features": [
++        "pclmulqdq",
++        "fma",
++        "pcid",
++        "movbe",
++        "aes",
++        "xsave",
++        "avx",
++        "f16c",
++        "rdrand",
++        "fsgsbase",
++        "bmi1",
++        "hle",
++        "avx2",
++        "smep",
++        "bmi2",
++        "erms",
++        "invpcid",
++        "rtm",
++        "mpx",
++        "avx512f",
++        "avx512dq",
++        "rdseed",
++        "adx",
++        "smap",
++        "clwb",
++        "avx512cd",
++        "avx512bw",
++        "avx512vl",
++        "pdpe1gb",
++        "abm",
++        "3dnowprefetch",
++        "xsaveopt",
++        "xsavec",
++        "xgetbv1",
++        "xsave",
++        "xsave",
++        "avx",
++        "mpx",
++        "mpx",
++        "avx512f",
++        "avx512f",
++        "avx512f"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Skylake-Client",
++      "typename": "Skylake-Client-x86_64-cpu",
++      "unavailable-features": [
++        "pclmulqdq",
++        "fma",
++        "pcid",
++        "movbe",
++        "aes",
++        "xsave",
++        "avx",
++        "f16c",
++        "rdrand",
++        "fsgsbase",
++        "bmi1",
++        "hle",
++        "avx2",
++        "smep",
++        "bmi2",
++        "erms",
++        "invpcid",
++        "rtm",
++        "mpx",
++        "rdseed",
++        "adx",
++        "smap",
++        "abm",
++        "3dnowprefetch",
++        "xsaveopt",
++        "xsavec",
++        "xgetbv1",
++        "xsave",
++        "xsave",
++        "avx",
++        "mpx",
++        "mpx"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Skylake-Client-IBRS",
++      "typename": "Skylake-Client-IBRS-x86_64-cpu",
++      "unavailable-features": [
++        "pclmulqdq",
++        "fma",
++        "pcid",
++        "movbe",
++        "aes",
++        "xsave",
++        "avx",
++        "f16c",
++        "rdrand",
++        "fsgsbase",
++        "bmi1",
++        "hle",
++        "avx2",
++        "smep",
++        "bmi2",
++        "erms",
++        "invpcid",
++        "rtm",
++        "mpx",
++        "rdseed",
++        "adx",
++        "smap",
++        "abm",
++        "3dnowprefetch",
++        "xsaveopt",
++        "xsavec",
++        "xgetbv1",
++        "xsave",
++        "xsave",
++        "avx",
++        "mpx",
++        "mpx"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "SandyBridge",
++      "typename": "SandyBridge-x86_64-cpu",
++      "unavailable-features": [
++        "pclmulqdq",
++        "aes",
++        "xsave",
++        "avx",
++        "xsaveopt",
++        "xsave",
++        "xsave",
++        "avx"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "SandyBridge-IBRS",
++      "typename": "SandyBridge-IBRS-x86_64-cpu",
++      "unavailable-features": [
++        "pclmulqdq",
++        "aes",
++        "xsave",
++        "avx",
++        "xsaveopt",
++        "xsave",
++        "xsave",
++        "avx"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Penryn",
++      "typename": "Penryn-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Opteron_G5",
++      "typename": "Opteron_G5-x86_64-cpu",
++      "unavailable-features": [
++        "pclmulqdq",
++        "fma",
++        "aes",
++        "xsave",
++        "avx",
++        "f16c",
++        "pdpe1gb",
++        "abm",
++        "sse4a",
++        "misalignsse",
++        "3dnowprefetch",
++        "xop",
++        "fma4",
++        "tbm",
++        "xsave",
++        "xsave",
++        "avx"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Opteron_G4",
++      "typename": "Opteron_G4-x86_64-cpu",
++      "unavailable-features": [
++        "pclmulqdq",
++        "aes",
++        "xsave",
++        "avx",
++        "pdpe1gb",
++        "abm",
++        "sse4a",
++        "misalignsse",
++        "3dnowprefetch",
++        "xop",
++        "fma4",
++        "xsave",
++        "xsave",
++        "avx"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Opteron_G3",
++      "typename": "Opteron_G3-x86_64-cpu",
++      "unavailable-features": [
++        "abm",
++        "sse4a",
++        "misalignsse"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Opteron_G2",
++      "typename": "Opteron_G2-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Opteron_G1",
++      "typename": "Opteron_G1-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Nehalem",
++      "typename": "Nehalem-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Nehalem-IBRS",
++      "typename": "Nehalem-IBRS-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "IvyBridge",
++      "typename": "IvyBridge-x86_64-cpu",
++      "unavailable-features": [
++        "pclmulqdq",
++        "aes",
++        "xsave",
++        "avx",
++        "f16c",
++        "rdrand",
++        "fsgsbase",
++        "smep",
++        "erms",
++        "xsaveopt",
++        "xsave",
++        "xsave",
++        "avx"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "IvyBridge-IBRS",
++      "typename": "IvyBridge-IBRS-x86_64-cpu",
++      "unavailable-features": [
++        "pclmulqdq",
++        "aes",
++        "xsave",
++        "avx",
++        "f16c",
++        "rdrand",
++        "fsgsbase",
++        "smep",
++        "erms",
++        "xsaveopt",
++        "xsave",
++        "xsave",
++        "avx"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Haswell",
++      "typename": "Haswell-x86_64-cpu",
++      "unavailable-features": [
++        "pclmulqdq",
++        "fma",
++        "pcid",
++        "movbe",
++        "aes",
++        "xsave",
++        "avx",
++        "f16c",
++        "rdrand",
++        "fsgsbase",
++        "bmi1",
++        "hle",
++        "avx2",
++        "smep",
++        "bmi2",
++        "erms",
++        "invpcid",
++        "rtm",
++        "abm",
++        "xsaveopt",
++        "xsave",
++        "xsave",
++        "avx"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Haswell-noTSX",
++      "typename": "Haswell-noTSX-x86_64-cpu",
++      "unavailable-features": [
++        "pclmulqdq",
++        "fma",
++        "pcid",
++        "movbe",
++        "aes",
++        "xsave",
++        "avx",
++        "f16c",
++        "rdrand",
++        "fsgsbase",
++        "bmi1",
++        "avx2",
++        "smep",
++        "bmi2",
++        "erms",
++        "invpcid",
++        "abm",
++        "xsaveopt",
++        "xsave",
++        "xsave",
++        "avx"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Haswell-noTSX-IBRS",
++      "typename": "Haswell-noTSX-IBRS-x86_64-cpu",
++      "unavailable-features": [
++        "pclmulqdq",
++        "fma",
++        "pcid",
++        "movbe",
++        "aes",
++        "xsave",
++        "avx",
++        "f16c",
++        "rdrand",
++        "fsgsbase",
++        "bmi1",
++        "avx2",
++        "smep",
++        "bmi2",
++        "erms",
++        "invpcid",
++        "abm",
++        "xsaveopt",
++        "xsave",
++        "xsave",
++        "avx"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Haswell-IBRS",
++      "typename": "Haswell-IBRS-x86_64-cpu",
++      "unavailable-features": [
++        "pclmulqdq",
++        "fma",
++        "pcid",
++        "movbe",
++        "aes",
++        "xsave",
++        "avx",
++        "f16c",
++        "rdrand",
++        "fsgsbase",
++        "bmi1",
++        "hle",
++        "avx2",
++        "smep",
++        "bmi2",
++        "erms",
++        "invpcid",
++        "rtm",
++        "abm",
++        "xsaveopt",
++        "xsave",
++        "xsave",
++        "avx"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "EPYC",
++      "typename": "EPYC-x86_64-cpu",
++      "unavailable-features": [
++        "pclmulqdq",
++        "fma",
++        "movbe",
++        "aes",
++        "xsave",
++        "avx",
++        "f16c",
++        "rdrand",
++        "fsgsbase",
++        "bmi1",
++        "avx2",
++        "smep",
++        "bmi2",
++        "rdseed",
++        "adx",
++        "smap",
++        "clflushopt",
++        "sha-ni",
++        "mmxext",
++        "fxsr-opt",
++        "pdpe1gb",
++        "cr8legacy",
++        "abm",
++        "sse4a",
++        "misalignsse",
++        "3dnowprefetch",
++        "osvw",
++        "xsaveopt",
++        "xsavec",
++        "xgetbv1",
++        "xsave",
++        "xsave",
++        "avx"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "EPYC-IBPB",
++      "typename": "EPYC-IBPB-x86_64-cpu",
++      "unavailable-features": [
++        "pclmulqdq",
++        "fma",
++        "movbe",
++        "aes",
++        "xsave",
++        "avx",
++        "f16c",
++        "rdrand",
++        "fsgsbase",
++        "bmi1",
++        "avx2",
++        "smep",
++        "bmi2",
++        "rdseed",
++        "adx",
++        "smap",
++        "clflushopt",
++        "sha-ni",
++        "mmxext",
++        "fxsr-opt",
++        "pdpe1gb",
++        "cr8legacy",
++        "abm",
++        "sse4a",
++        "misalignsse",
++        "3dnowprefetch",
++        "osvw",
++        "ibpb",
++        "xsaveopt",
++        "xsavec",
++        "xgetbv1",
++        "xsave",
++        "xsave",
++        "avx"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Conroe",
++      "typename": "Conroe-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Broadwell",
++      "typename": "Broadwell-x86_64-cpu",
++      "unavailable-features": [
++        "pclmulqdq",
++        "fma",
++        "pcid",
++        "movbe",
++        "aes",
++        "xsave",
++        "avx",
++        "f16c",
++        "rdrand",
++        "fsgsbase",
++        "bmi1",
++        "hle",
++        "avx2",
++        "smep",
++        "bmi2",
++        "erms",
++        "invpcid",
++        "rtm",
++        "rdseed",
++        "adx",
++        "smap",
++        "abm",
++        "3dnowprefetch",
++        "xsaveopt",
++        "xsave",
++        "xsave",
++        "avx"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Broadwell-noTSX",
++      "typename": "Broadwell-noTSX-x86_64-cpu",
++      "unavailable-features": [
++        "pclmulqdq",
++        "fma",
++        "pcid",
++        "movbe",
++        "aes",
++        "xsave",
++        "avx",
++        "f16c",
++        "rdrand",
++        "fsgsbase",
++        "bmi1",
++        "avx2",
++        "smep",
++        "bmi2",
++        "erms",
++        "invpcid",
++        "rdseed",
++        "adx",
++        "smap",
++        "abm",
++        "3dnowprefetch",
++        "xsaveopt",
++        "xsave",
++        "xsave",
++        "avx"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Broadwell-noTSX-IBRS",
++      "typename": "Broadwell-noTSX-IBRS-x86_64-cpu",
++      "unavailable-features": [
++        "pclmulqdq",
++        "fma",
++        "pcid",
++        "movbe",
++        "aes",
++        "xsave",
++        "avx",
++        "f16c",
++        "rdrand",
++        "fsgsbase",
++        "bmi1",
++        "avx2",
++        "smep",
++        "bmi2",
++        "erms",
++        "invpcid",
++        "rdseed",
++        "adx",
++        "smap",
++        "abm",
++        "3dnowprefetch",
++        "xsaveopt",
++        "xsave",
++        "xsave",
++        "avx"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Broadwell-IBRS",
++      "typename": "Broadwell-IBRS-x86_64-cpu",
++      "unavailable-features": [
++        "pclmulqdq",
++        "fma",
++        "pcid",
++        "movbe",
++        "aes",
++        "xsave",
++        "avx",
++        "f16c",
++        "rdrand",
++        "fsgsbase",
++        "bmi1",
++        "hle",
++        "avx2",
++        "smep",
++        "bmi2",
++        "erms",
++        "invpcid",
++        "rtm",
++        "rdseed",
++        "adx",
++        "smap",
++        "abm",
++        "3dnowprefetch",
++        "xsaveopt",
++        "xsave",
++        "xsave",
++        "avx"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "486",
++      "typename": "486-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    }
++  ],
++  "id": "definitions"
++}
+diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E7540.xml b/tests/cputestdata/x86_64-cpuid-Xeon-E7540.xml
+new file mode 100644
+index 0000000000..e80694b5e0
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Xeon-E7540.xml
+@@ -0,0 +1,30 @@
++<!-- Intel(R) Xeon(R) CPU           E7540  @ 2.00GHz -->
++<cpudata arch='x86'>
++  <cpuid eax_in='0x00000000' ecx_in='0x00' eax='0x0000000b' ebx='0x756e6547' ecx='0x6c65746e' edx='0x49656e69'/>
++  <cpuid eax_in='0x00000001' ecx_in='0x00' eax='0x000206e6' ebx='0x05200800' ecx='0x00bce3bd' edx='0xbfebfbff'/>
++  <cpuid eax_in='0x00000002' ecx_in='0x00' eax='0x55035a01' ebx='0x00f0b2eb' ecx='0x00000000' edx='0x09ca212c'/>
++  <cpuid eax_in='0x00000003' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x00000004' ecx_in='0x00' eax='0x3c004121' ebx='0x01c0003f' ecx='0x0000003f' edx='0x00000000'/>
++  <cpuid eax_in='0x00000004' ecx_in='0x01' eax='0x3c004122' ebx='0x00c0003f' ecx='0x0000007f' edx='0x00000000'/>
++  <cpuid eax_in='0x00000004' ecx_in='0x02' eax='0x3c004143' ebx='0x01c0003f' ecx='0x000001ff' edx='0x00000000'/>
++  <cpuid eax_in='0x00000004' ecx_in='0x03' eax='0x3c07c163' ebx='0x05c0003f' ecx='0x00002fff' edx='0x00000006'/>
++  <cpuid eax_in='0x00000005' ecx_in='0x00' eax='0x00000040' ebx='0x00000040' ecx='0x00000003' edx='0x00000120'/>
++  <cpuid eax_in='0x00000006' ecx_in='0x00' eax='0x00000003' ebx='0x00000001' ecx='0x00000001' edx='0x00000000'/>
++  <cpuid eax_in='0x00000007' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x9c000000'/>
++  <cpuid eax_in='0x00000008' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x00000009' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x0000000a' ecx_in='0x00' eax='0x07300403' ebx='0x00000044' ecx='0x00000000' edx='0x00000603'/>
++  <cpuid eax_in='0x0000000b' ecx_in='0x00' eax='0x00000001' ebx='0x00000002' ecx='0x00000100' edx='0x00000005'/>
++  <cpuid eax_in='0x0000000b' ecx_in='0x01' eax='0x00000005' ebx='0x0000000c' ecx='0x00000201' edx='0x00000005'/>
++  <cpuid eax_in='0x80000000' ecx_in='0x00' eax='0x80000008' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x80000001' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000001' edx='0x28100800'/>
++  <cpuid eax_in='0x80000002' ecx_in='0x00' eax='0x65746e49' ebx='0x2952286c' ecx='0x6f655820' edx='0x2952286e'/>
++  <cpuid eax_in='0x80000003' ecx_in='0x00' eax='0x55504320' ebx='0x20202020' ecx='0x20202020' edx='0x45202020'/>
++  <cpuid eax_in='0x80000004' ecx_in='0x00' eax='0x30343537' ebx='0x20402020' ecx='0x30302e32' edx='0x007a4847'/>
++  <cpuid eax_in='0x80000005' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x80000006' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x01006040' edx='0x00000000'/>
++  <cpuid eax_in='0x80000007' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000100'/>
++  <cpuid eax_in='0x80000008' ecx_in='0x00' eax='0x0000302c' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x80860000' ecx_in='0x00' eax='0x00000001' ebx='0x00000002' ecx='0x00000100' edx='0x00000005'/>
++  <cpuid eax_in='0xc0000000' ecx_in='0x00' eax='0x00000001' ebx='0x00000002' ecx='0x00000100' edx='0x00000005'/>
++</cpudata>
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-cputest-Add-data-for-Intel-R-Xeon-R-Platinum-8268-CPU.patch b/SOURCES/libvirt-cputest-Add-data-for-Intel-R-Xeon-R-Platinum-8268-CPU.patch
new file mode 100644
index 0000000..97de9d0
--- /dev/null
+++ b/SOURCES/libvirt-cputest-Add-data-for-Intel-R-Xeon-R-Platinum-8268-CPU.patch
@@ -0,0 +1,968 @@
+From 5a7f0fd05ad3c86dd8f8be7870bd536de2512baa Mon Sep 17 00:00:00 2001
+Message-Id: <5a7f0fd05ad3c86dd8f8be7870bd536de2512baa@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:25:20 +0200
+Subject: [PATCH] cputest: Add data for Intel(R) Xeon(R) Platinum 8268 CPU
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit e024625735daec9f9f0bc292f06e37d7099805f1)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1693433
+
+Conflicts:
+	tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-guest.xml
+	tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-host.xml
+            - md-clear feature did not exist at the time of the original
+              patch, but downstream already has it
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <809df143b79b1052ce3e643d9b97926b5bdd7001.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ tests/cputest.c                               |   1 +
+ ...6_64-cpuid-Xeon-Platinum-8268-disabled.xml |   7 +
+ ...86_64-cpuid-Xeon-Platinum-8268-enabled.xml |   8 +
+ .../x86_64-cpuid-Xeon-Platinum-8268-guest.xml |  36 +
+ .../x86_64-cpuid-Xeon-Platinum-8268-host.xml  |  37 +
+ .../x86_64-cpuid-Xeon-Platinum-8268-json.xml  |  13 +
+ .../x86_64-cpuid-Xeon-Platinum-8268.json      | 702 ++++++++++++++++++
+ .../x86_64-cpuid-Xeon-Platinum-8268.sig       |   4 +
+ .../x86_64-cpuid-Xeon-Platinum-8268.xml       |  54 ++
+ 9 files changed, 862 insertions(+)
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-disabled.xml
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-enabled.xml
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-guest.xml
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-host.xml
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-json.xml
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268.json
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268.sig
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268.xml
+
+diff --git a/tests/cputest.c b/tests/cputest.c
+index 0cb9a57592..e62cda34b7 100644
+--- a/tests/cputest.c
++++ b/tests/cputest.c
+@@ -1293,6 +1293,7 @@ mymain(void)
+     DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-E7540", JSON_MODELS);
+     DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-Gold-5115", JSON_MODELS);
+     DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-Gold-6148", JSON_HOST);
++    DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-Platinum-8268", JSON_HOST);
+     DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-W3520", JSON_HOST);
+     DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-X5460", JSON_NONE);
+ 
+diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-disabled.xml b/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-disabled.xml
+new file mode 100644
+index 0000000000..32522eb9af
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-disabled.xml
+@@ -0,0 +1,7 @@
++<!-- Features disabled by QEMU -->
++<cpudata arch='x86'>
++  <cpuid eax_in='0x00000001' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x0804c1fc' edx='0xb0600000'/>
++  <cpuid eax_in='0x00000007' ecx_in='0x00' eax='0x00000000' ebx='0x02001000' ecx='0x00000010' edx='0x28000000'/>
++  <cpuid eax_in='0x0000000f' ecx_in='0x01' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000006'/>
++  <cpuid eax_in='0x80000007' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000100'/>
++</cpudata>
+diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-enabled.xml b/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-enabled.xml
+new file mode 100644
+index 0000000000..434ac1956a
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-enabled.xml
+@@ -0,0 +1,8 @@
++<!-- Features enabled by QEMU -->
++<cpudata arch='x86'>
++  <cpuid eax_in='0x00000001' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0xf7fa3203' edx='0x0f8bfbff'/>
++  <cpuid eax_in='0x00000006' ecx_in='0x00' eax='0x00000004' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x00000007' ecx_in='0x00' eax='0x00000000' ebx='0xd19f4fbb' ecx='0x0000080c' edx='0x84000000'/>
++  <cpuid eax_in='0x0000000d' ecx_in='0x01' eax='0x0000000f' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x80000001' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000121' edx='0x2c100800'/>
++</cpudata>
+diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-guest.xml b/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-guest.xml
+new file mode 100644
+index 0000000000..2836481454
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-guest.xml
+@@ -0,0 +1,36 @@
++<cpu mode='custom' match='exact'>
++  <model fallback='forbid'>Skylake-Server-IBRS</model>
++  <vendor>Intel</vendor>
++  <feature policy='require' name='ds'/>
++  <feature policy='require' name='acpi'/>
++  <feature policy='require' name='ss'/>
++  <feature policy='require' name='ht'/>
++  <feature policy='require' name='tm'/>
++  <feature policy='require' name='pbe'/>
++  <feature policy='require' name='dtes64'/>
++  <feature policy='require' name='monitor'/>
++  <feature policy='require' name='ds_cpl'/>
++  <feature policy='require' name='vmx'/>
++  <feature policy='require' name='smx'/>
++  <feature policy='require' name='est'/>
++  <feature policy='require' name='tm2'/>
++  <feature policy='require' name='xtpr'/>
++  <feature policy='require' name='pdcm'/>
++  <feature policy='require' name='dca'/>
++  <feature policy='require' name='osxsave'/>
++  <feature policy='require' name='tsc_adjust'/>
++  <feature policy='require' name='cmt'/>
++  <feature policy='require' name='clflushopt'/>
++  <feature policy='require' name='intel-pt'/>
++  <feature policy='require' name='pku'/>
++  <feature policy='require' name='ospke'/>
++  <feature policy='require' name='avx512vnni'/>
++  <feature policy='require' name='md-clear'/>
++  <feature policy='require' name='stibp'/>
++  <feature policy='require' name='arch-capabilities'/>
++  <feature policy='require' name='ssbd'/>
++  <feature policy='require' name='xsaves'/>
++  <feature policy='require' name='mbm_total'/>
++  <feature policy='require' name='mbm_local'/>
++  <feature policy='require' name='invtsc'/>
++</cpu>
+diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-host.xml b/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-host.xml
+new file mode 100644
+index 0000000000..032d8ffeca
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-host.xml
+@@ -0,0 +1,37 @@
++<cpu>
++  <arch>x86_64</arch>
++  <model>Skylake-Server-IBRS</model>
++  <vendor>Intel</vendor>
++  <feature name='ds'/>
++  <feature name='acpi'/>
++  <feature name='ss'/>
++  <feature name='ht'/>
++  <feature name='tm'/>
++  <feature name='pbe'/>
++  <feature name='dtes64'/>
++  <feature name='monitor'/>
++  <feature name='ds_cpl'/>
++  <feature name='vmx'/>
++  <feature name='smx'/>
++  <feature name='est'/>
++  <feature name='tm2'/>
++  <feature name='xtpr'/>
++  <feature name='pdcm'/>
++  <feature name='dca'/>
++  <feature name='osxsave'/>
++  <feature name='tsc_adjust'/>
++  <feature name='cmt'/>
++  <feature name='clflushopt'/>
++  <feature name='intel-pt'/>
++  <feature name='pku'/>
++  <feature name='ospke'/>
++  <feature name='avx512vnni'/>
++  <feature name='md-clear'/>
++  <feature name='stibp'/>
++  <feature name='arch-capabilities'/>
++  <feature name='ssbd'/>
++  <feature name='xsaves'/>
++  <feature name='mbm_total'/>
++  <feature name='mbm_local'/>
++  <feature name='invtsc'/>
++</cpu>
+diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-json.xml b/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-json.xml
+new file mode 100644
+index 0000000000..12431de213
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268-json.xml
+@@ -0,0 +1,13 @@
++<cpu mode='custom' match='exact'>
++  <model fallback='forbid'>Skylake-Server-IBRS</model>
++  <vendor>Intel</vendor>
++  <feature policy='require' name='ss'/>
++  <feature policy='require' name='hypervisor'/>
++  <feature policy='require' name='tsc_adjust'/>
++  <feature policy='require' name='clflushopt'/>
++  <feature policy='require' name='umip'/>
++  <feature policy='require' name='pku'/>
++  <feature policy='require' name='avx512vnni'/>
++  <feature policy='require' name='ssbd'/>
++  <feature policy='require' name='xsaves'/>
++</cpu>
+diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268.json b/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268.json
+new file mode 100644
+index 0000000000..71451f893d
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268.json
+@@ -0,0 +1,702 @@
++{
++  "return": {
++    "model": {
++      "name": "base",
++      "props": {
++        "phys-bits": 0,
++        "core-id": -1,
++        "xlevel": 2147483656,
++        "cmov": true,
++        "ia64": false,
++        "ssb-no": false,
++        "aes": true,
++        "mmx": true,
++        "rdpid": false,
++        "arat": true,
++        "gfni": false,
++        "ibrs-all": true,
++        "pause-filter": false,
++        "xsavec": true,
++        "intel-pt": false,
++        "hv-frequencies": false,
++        "tsc-frequency": 0,
++        "xd": true,
++        "hv-vendor-id": "",
++        "kvm-asyncpf": true,
++        "kvm_asyncpf": true,
++        "perfctr_core": false,
++        "perfctr-core": false,
++        "mpx": true,
++        "pbe": false,
++        "decodeassists": false,
++        "avx512cd": true,
++        "sse4_1": true,
++        "sse4.1": true,
++        "sse4-1": true,
++        "family": 6,
++        "legacy-cache": true,
++        "vmware-cpuid-freq": true,
++        "wbnoinvd": false,
++        "avx512f": true,
++        "msr": true,
++        "mce": true,
++        "mca": true,
++        "hv-runtime": false,
++        "xcrypt": false,
++        "thread-id": -1,
++        "min-level": 13,
++        "xgetbv1": true,
++        "cid": false,
++        "hv-relaxed": false,
++        "hv-crash": false,
++        "ds": false,
++        "fxsr": true,
++        "xsaveopt": true,
++        "xtpr": false,
++        "hv-evmcs": false,
++        "avx512vl": true,
++        "avx512-vpopcntdq": false,
++        "phe": false,
++        "extapic": false,
++        "3dnowprefetch": true,
++        "avx512vbmi2": false,
++        "cr8legacy": false,
++        "cpuid-0xb": true,
++        "xcrypt-en": false,
++        "kvm_pv_eoi": true,
++        "apic-id": 4294967295,
++        "rsba": false,
++        "pn": false,
++        "dca": false,
++        "vendor": "GenuineIntel",
++        "hv-ipi": false,
++        "pku": true,
++        "smx": false,
++        "cmp_legacy": false,
++        "cmp-legacy": false,
++        "node-id": -1,
++        "avx512-4fmaps": false,
++        "vmcb_clean": false,
++        "vmcb-clean": false,
++        "3dnowext": false,
++        "amd-no-ssb": false,
++        "hle": true,
++        "npt": false,
++        "rdctl-no": true,
++        "memory": "/machine/unattached/system[0]",
++        "clwb": true,
++        "lbrv": false,
++        "adx": true,
++        "ss": true,
++        "pni": true,
++        "svm_lock": false,
++        "svm-lock": false,
++        "pfthreshold": false,
++        "smep": true,
++        "smap": true,
++        "x2apic": true,
++        "avx512vbmi": false,
++        "avx512vnni": true,
++        "hv-stimer": false,
++        "x-hv-synic-kvm-only": true,
++        "i64": true,
++        "flushbyasid": false,
++        "f16c": true,
++        "ace2-en": false,
++        "pat": true,
++        "pae": true,
++        "sse": true,
++        "phe-en": false,
++        "kvm_nopiodelay": true,
++        "kvm-nopiodelay": true,
++        "tm": false,
++        "kvmclock-stable-bit": true,
++        "hypervisor": true,
++        "socket-id": -1,
++        "pcommit": false,
++        "syscall": true,
++        "level": 13,
++        "avx512dq": true,
++        "x-migrate-smi-count": false,
++        "svm": false,
++        "full-cpuid-auto-level": true,
++        "hv-reset": false,
++        "invtsc": false,
++        "sse3": true,
++        "sse2": true,
++        "ssbd": true,
++        "est": false,
++        "avx512ifma": false,
++        "tm2": false,
++        "kvm-pv-ipi": true,
++        "kvm-pv-eoi": true,
++        "cx8": true,
++        "cldemote": false,
++        "hv-reenlightenment": false,
++        "kvm_mmu": false,
++        "kvm-mmu": false,
++        "sse4_2": true,
++        "sse4.2": true,
++        "sse4-2": true,
++        "pge": true,
++        "fill-mtrr-mask": true,
++        "avx512bitalg": false,
++        "nodeid_msr": false,
++        "pdcm": false,
++        "movbe": true,
++        "model": 85,
++        "nrip_save": false,
++        "nrip-save": false,
++        "kvm_pv_unhalt": true,
++        "ssse3": true,
++        "sse4a": false,
++        "invpcid": true,
++        "pdpe1gb": true,
++        "tsc-deadline": true,
++        "skip-l1dfl-vmentry": true,
++        "fma": true,
++        "cx16": true,
++        "de": true,
++        "enforce": false,
++        "stepping": 6,
++        "xsave": true,
++        "clflush": true,
++        "skinit": false,
++        "tsc": true,
++        "tce": false,
++        "fpu": true,
++        "ibs": false,
++        "ds_cpl": false,
++        "ds-cpl": false,
++        "host-phys-bits": true,
++        "fma4": false,
++        "la57": false,
++        "osvw": false,
++        "check": true,
++        "hv-spinlocks": -1,
++        "pmu": false,
++        "pmm": false,
++        "apic": true,
++        "spec-ctrl": true,
++        "min-xlevel2": 0,
++        "tsc-adjust": true,
++        "tsc_adjust": true,
++        "kvm-steal-time": true,
++        "kvm_steal_time": true,
++        "kvmclock": true,
++        "l3-cache": true,
++        "lwp": false,
++        "amd-ssbd": false,
++        "ibpb": false,
++        "xop": false,
++        "avx": true,
++        "ace2": false,
++        "avx512bw": true,
++        "acpi": false,
++        "hv-vapic": false,
++        "fsgsbase": true,
++        "ht": false,
++        "nx": true,
++        "pclmulqdq": true,
++        "mmxext": false,
++        "vaes": false,
++        "popcnt": true,
++        "xsaves": true,
++        "tcg-cpuid": true,
++        "lm": true,
++        "umip": true,
++        "pse": true,
++        "avx2": true,
++        "sep": true,
++        "pclmuldq": true,
++        "virt-ssbd": false,
++        "x-hv-max-vps": -1,
++        "nodeid-msr": false,
++        "kvm": true,
++        "misalignsse": false,
++        "min-xlevel": 2147483656,
++        "kvm-pv-unhalt": true,
++        "bmi2": true,
++        "bmi1": true,
++        "realized": false,
++        "tsc_scale": false,
++        "tsc-scale": false,
++        "topoext": false,
++        "hv-vpindex": false,
++        "xlevel2": 0,
++        "clflushopt": true,
++        "kvm-no-smi-migration": false,
++        "monitor": false,
++        "avx512er": false,
++        "pmm-en": false,
++        "pcid": true,
++        "arch-capabilities": false,
++        "3dnow": false,
++        "erms": true,
++        "lahf-lm": true,
++        "lahf_lm": true,
++        "vpclmulqdq": false,
++        "fxsr-opt": false,
++        "hv-synic": false,
++        "xstore": false,
++        "fxsr_opt": false,
++        "kvm-hint-dedicated": false,
++        "rtm": true,
++        "lmce": true,
++        "hv-time": false,
++        "perfctr-nb": false,
++        "perfctr_nb": false,
++        "ffxsr": false,
++        "hv-tlbflush": false,
++        "rdrand": true,
++        "rdseed": true,
++        "avx512-4vnniw": false,
++        "vmx": false,
++        "vme": true,
++        "dtes64": false,
++        "mtrr": true,
++        "rdtscp": true,
++        "pse36": true,
++        "kvm-pv-tlb-flush": true,
++        "tbm": false,
++        "wdt": false,
++        "pause_filter": false,
++        "sha-ni": false,
++        "model-id": "Intel(R) Xeon(R) Platinum 8268 CPU @ 2.90GHz",
++        "abm": true,
++        "avx512pf": false,
++        "xstore-en": false
++      }
++    }
++  },
++  "id": "model-expansion"
++}
++
++{
++  "return": [
++    {
++      "name": "max",
++      "typename": "max-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": false
++    },
++    {
++      "name": "host",
++      "typename": "host-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": false
++    },
++    {
++      "name": "base",
++      "typename": "base-x86_64-cpu",
++      "unavailable-features": [],
++      "static": true,
++      "migration-safe": true
++    },
++    {
++      "name": "qemu64",
++      "typename": "qemu64-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "qemu32",
++      "typename": "qemu32-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "phenom",
++      "typename": "phenom-x86_64-cpu",
++      "unavailable-features": [
++        "mmxext",
++        "fxsr-opt",
++        "3dnowext",
++        "3dnow",
++        "sse4a",
++        "npt"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "pentium3",
++      "typename": "pentium3-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "pentium2",
++      "typename": "pentium2-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "pentium",
++      "typename": "pentium-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "n270",
++      "typename": "n270-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "kvm64",
++      "typename": "kvm64-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "kvm32",
++      "typename": "kvm32-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "cpu64-rhel6",
++      "typename": "cpu64-rhel6-x86_64-cpu",
++      "unavailable-features": [
++        "sse4a"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "coreduo",
++      "typename": "coreduo-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "core2duo",
++      "typename": "core2duo-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "athlon",
++      "typename": "athlon-x86_64-cpu",
++      "unavailable-features": [
++        "mmxext",
++        "3dnowext",
++        "3dnow"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Westmere-IBRS",
++      "typename": "Westmere-IBRS-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Westmere",
++      "typename": "Westmere-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Skylake-Server-IBRS",
++      "typename": "Skylake-Server-IBRS-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Skylake-Server",
++      "typename": "Skylake-Server-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Skylake-Client-IBRS",
++      "typename": "Skylake-Client-IBRS-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Skylake-Client",
++      "typename": "Skylake-Client-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "SandyBridge-IBRS",
++      "typename": "SandyBridge-IBRS-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "SandyBridge",
++      "typename": "SandyBridge-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Penryn",
++      "typename": "Penryn-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Opteron_G5",
++      "typename": "Opteron_G5-x86_64-cpu",
++      "unavailable-features": [
++        "sse4a",
++        "misalignsse",
++        "xop",
++        "fma4",
++        "tbm"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Opteron_G4",
++      "typename": "Opteron_G4-x86_64-cpu",
++      "unavailable-features": [
++        "sse4a",
++        "misalignsse",
++        "xop",
++        "fma4"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Opteron_G3",
++      "typename": "Opteron_G3-x86_64-cpu",
++      "unavailable-features": [
++        "sse4a",
++        "misalignsse"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Opteron_G2",
++      "typename": "Opteron_G2-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Opteron_G1",
++      "typename": "Opteron_G1-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Nehalem-IBRS",
++      "typename": "Nehalem-IBRS-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Nehalem",
++      "typename": "Nehalem-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "KnightsMill",
++      "typename": "KnightsMill-x86_64-cpu",
++      "unavailable-features": [
++        "avx512pf",
++        "avx512er",
++        "avx512-vpopcntdq",
++        "avx512-4vnniw",
++        "avx512-4fmaps"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "IvyBridge-IBRS",
++      "typename": "IvyBridge-IBRS-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "IvyBridge",
++      "typename": "IvyBridge-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Icelake-Server",
++      "typename": "Icelake-Server-x86_64-cpu",
++      "unavailable-features": [
++        "avx512vbmi",
++        "",
++        "avx512vbmi2",
++        "gfni",
++        "vaes",
++        "vpclmulqdq",
++        "avx512bitalg",
++        "avx512-vpopcntdq",
++        "la57",
++        "wbnoinvd"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Icelake-Client",
++      "typename": "Icelake-Client-x86_64-cpu",
++      "unavailable-features": [
++        "avx512vbmi",
++        "",
++        "avx512vbmi2",
++        "gfni",
++        "vaes",
++        "vpclmulqdq",
++        "avx512bitalg",
++        "avx512-vpopcntdq",
++        "wbnoinvd"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Haswell-noTSX-IBRS",
++      "typename": "Haswell-noTSX-IBRS-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Haswell-noTSX",
++      "typename": "Haswell-noTSX-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Haswell-IBRS",
++      "typename": "Haswell-IBRS-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Haswell",
++      "typename": "Haswell-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "EPYC-IBPB",
++      "typename": "EPYC-IBPB-x86_64-cpu",
++      "unavailable-features": [
++        "sha-ni",
++        "mmxext",
++        "fxsr-opt",
++        "cr8legacy",
++        "sse4a",
++        "misalignsse",
++        "osvw",
++        "ibpb"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "EPYC",
++      "typename": "EPYC-x86_64-cpu",
++      "unavailable-features": [
++        "sha-ni",
++        "mmxext",
++        "fxsr-opt",
++        "cr8legacy",
++        "sse4a",
++        "misalignsse",
++        "osvw"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Conroe",
++      "typename": "Conroe-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Cascadelake-Server",
++      "typename": "Cascadelake-Server-x86_64-cpu",
++      "unavailable-features": [
++        ""
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Broadwell-noTSX-IBRS",
++      "typename": "Broadwell-noTSX-IBRS-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Broadwell-noTSX",
++      "typename": "Broadwell-noTSX-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Broadwell-IBRS",
++      "typename": "Broadwell-IBRS-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Broadwell",
++      "typename": "Broadwell-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "486",
++      "typename": "486-x86_64-cpu",
++      "unavailable-features": [],
++      "static": false,
++      "migration-safe": true
++    }
++  ],
++  "id": "definitions"
++}
+diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268.sig b/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268.sig
+new file mode 100644
+index 0000000000..018161ff52
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268.sig
+@@ -0,0 +1,4 @@
++050656
++family:     6 (0x06)
++model:     85 (0x55)
++stepping:   6 (0x06)
+diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268.xml b/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268.xml
+new file mode 100644
+index 0000000000..75472d44fe
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268.xml
+@@ -0,0 +1,54 @@
++<!-- Intel(R) Xeon(R) Platinum 8268 CPU @ 2.90GHz -->
++<cpudata arch='x86'>
++  <cpuid eax_in='0x00000000' ecx_in='0x00' eax='0x00000016' ebx='0x756e6547' ecx='0x6c65746e' edx='0x49656e69'/>
++  <cpuid eax_in='0x00000001' ecx_in='0x00' eax='0x00050656' ebx='0x44400800' ecx='0x7ffefbff' edx='0xbfebfbff'/>
++  <cpuid eax_in='0x00000002' ecx_in='0x00' eax='0x76036301' ebx='0x00f0b5ff' ecx='0x00000000' edx='0x00c30000'/>
++  <cpuid eax_in='0x00000003' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x00000004' ecx_in='0x00' eax='0x7c004121' ebx='0x01c0003f' ecx='0x0000003f' edx='0x00000000'/>
++  <cpuid eax_in='0x00000004' ecx_in='0x01' eax='0x7c004122' ebx='0x01c0003f' ecx='0x0000003f' edx='0x00000000'/>
++  <cpuid eax_in='0x00000004' ecx_in='0x02' eax='0x7c004143' ebx='0x03c0003f' ecx='0x000003ff' edx='0x00000000'/>
++  <cpuid eax_in='0x00000004' ecx_in='0x03' eax='0x7c0fc163' ebx='0x0280003f' ecx='0x0000cfff' edx='0x00000005'/>
++  <cpuid eax_in='0x00000005' ecx_in='0x00' eax='0x00000040' ebx='0x00000040' ecx='0x00000003' edx='0x00002020'/>
++  <cpuid eax_in='0x00000006' ecx_in='0x00' eax='0x00000077' ebx='0x00000002' ecx='0x00000009' edx='0x00000000'/>
++  <cpuid eax_in='0x00000007' ecx_in='0x00' eax='0x00000000' ebx='0xd39ffffb' ecx='0x00000818' edx='0xbc000400'/>
++  <cpuid eax_in='0x00000008' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x00000009' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x0000000a' ecx_in='0x00' eax='0x07300404' ebx='0x00000000' ecx='0x00000000' edx='0x00000603'/>
++  <cpuid eax_in='0x0000000b' ecx_in='0x00' eax='0x00000001' ebx='0x00000002' ecx='0x00000100' edx='0x00000044'/>
++  <cpuid eax_in='0x0000000b' ecx_in='0x01' eax='0x00000006' ebx='0x00000030' ecx='0x00000201' edx='0x00000044'/>
++  <cpuid eax_in='0x0000000c' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x0000000d' ecx_in='0x00' eax='0x000002ff' ebx='0x00000a88' ecx='0x00000a88' edx='0x00000000'/>
++  <cpuid eax_in='0x0000000d' ecx_in='0x01' eax='0x0000000f' ebx='0x00000a08' ecx='0x00000100' edx='0x00000000'/>
++  <cpuid eax_in='0x0000000d' ecx_in='0x02' eax='0x00000100' ebx='0x00000240' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x0000000d' ecx_in='0x03' eax='0x00000040' ebx='0x000003c0' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x0000000d' ecx_in='0x04' eax='0x00000040' ebx='0x00000400' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x0000000d' ecx_in='0x05' eax='0x00000040' ebx='0x00000440' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x0000000d' ecx_in='0x06' eax='0x00000200' ebx='0x00000480' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x0000000d' ecx_in='0x07' eax='0x00000400' ebx='0x00000680' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x0000000d' ecx_in='0x08' eax='0x00000080' ebx='0x00000000' ecx='0x00000001' edx='0x00000000'/>
++  <cpuid eax_in='0x0000000d' ecx_in='0x09' eax='0x00000008' ebx='0x00000a80' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x0000000e' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x0000000f' ecx_in='0x00' eax='0x00000000' ebx='0x000000cf' ecx='0x00000000' edx='0x00000002'/>
++  <cpuid eax_in='0x0000000f' ecx_in='0x01' eax='0x00000000' ebx='0x0001a000' ecx='0x000000cf' edx='0x00000007'/>
++  <cpuid eax_in='0x00000010' ecx_in='0x00' eax='0x00000000' ebx='0x0000000a' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x00000010' ecx_in='0x01' eax='0x0000000a' ebx='0x00000600' ecx='0x00000004' edx='0x0000000f'/>
++  <cpuid eax_in='0x00000010' ecx_in='0x03' eax='0x00000059' ebx='0x00000000' ecx='0x00000004' edx='0x00000007'/>
++  <cpuid eax_in='0x00000011' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x00000012' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x00000013' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x00000014' ecx_in='0x00' eax='0x00000001' ebx='0x0000000f' ecx='0x00000007' edx='0x00000000'/>
++  <cpuid eax_in='0x00000014' ecx_in='0x01' eax='0x02490002' ebx='0x003f3fff' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x00000015' ecx_in='0x00' eax='0x00000002' ebx='0x000000e8' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x00000016' ecx_in='0x00' eax='0x00000b54' ebx='0x00000f3c' ecx='0x00000064' edx='0x00000000'/>
++  <cpuid eax_in='0x80000000' ecx_in='0x00' eax='0x80000008' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x80000001' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000121' edx='0x2c100800'/>
++  <cpuid eax_in='0x80000002' ecx_in='0x00' eax='0x65746e49' ebx='0x2952286c' ecx='0x6f655820' edx='0x2952286e'/>
++  <cpuid eax_in='0x80000003' ecx_in='0x00' eax='0x616c5020' ebx='0x756e6974' ecx='0x3238206d' edx='0x43203836'/>
++  <cpuid eax_in='0x80000004' ecx_in='0x00' eax='0x40205550' ebx='0x392e3220' ecx='0x7a484730' edx='0x00000000'/>
++  <cpuid eax_in='0x80000005' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x80000006' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x01006040' edx='0x00000000'/>
++  <cpuid eax_in='0x80000007' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000100'/>
++  <cpuid eax_in='0x80000008' ecx_in='0x00' eax='0x0000302e' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
++  <cpuid eax_in='0x80860000' ecx_in='0x00' eax='0x00000b54' ebx='0x00000f3c' ecx='0x00000064' edx='0x00000000'/>
++  <cpuid eax_in='0xc0000000' ecx_in='0x00' eax='0x00000b54' ebx='0x00000f3c' ecx='0x00000064' edx='0x00000000'/>
++</cpudata>
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-cputest-Add-support-for-MSR-features-to-cpu-parse.sh.patch b/SOURCES/libvirt-cputest-Add-support-for-MSR-features-to-cpu-parse.sh.patch
new file mode 100644
index 0000000..0fae604
--- /dev/null
+++ b/SOURCES/libvirt-cputest-Add-support-for-MSR-features-to-cpu-parse.sh.patch
@@ -0,0 +1,41 @@
+From 7084115edc91fd3cff8ba35af1fc705c917973cf Mon Sep 17 00:00:00 2001
+Message-Id: <7084115edc91fd3cff8ba35af1fc705c917973cf@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:25:41 +0200
+Subject: [PATCH] cputest: Add support for MSR features to cpu-parse.sh
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The script just parses whatever cpu-gather.sh printed out.
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit 8904492e21537f3b820e577964e67ad670fa640b)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1697627
+
+Conflicts:
+	tests/cputestdata/cpu-parse.sh
+            - no need to update this script downstream
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <55c3125aef5a2d7bf7b2d7a6fc5c868af7903447.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268.xml | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268.xml b/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268.xml
+index 75472d44fe..f1261da891 100644
+--- a/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268.xml
++++ b/tests/cputestdata/x86_64-cpuid-Xeon-Platinum-8268.xml
+@@ -51,4 +51,5 @@
+   <cpuid eax_in='0x80000008' ecx_in='0x00' eax='0x0000302e' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/>
+   <cpuid eax_in='0x80860000' ecx_in='0x00' eax='0x00000b54' ebx='0x00000f3c' ecx='0x00000064' edx='0x00000000'/>
+   <cpuid eax_in='0xc0000000' ecx_in='0x00' eax='0x00000b54' ebx='0x00000f3c' ecx='0x00000064' edx='0x00000000'/>
++  <msr index='0x10a' edx='0x00000000' eax='0x0000002b'/>
+ </cpudata>
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-cputest-Test-CPU-signatures.patch b/SOURCES/libvirt-cputest-Test-CPU-signatures.patch
new file mode 100644
index 0000000..a1923a3
--- /dev/null
+++ b/SOURCES/libvirt-cputest-Test-CPU-signatures.patch
@@ -0,0 +1,755 @@
+From 58b7dda3dda6a768f465f2b8782ef665bd0d7f72 Mon Sep 17 00:00:00 2001
+Message-Id: <58b7dda3dda6a768f465f2b8782ef665bd0d7f72@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:25:08 +0200
+Subject: [PATCH] cputest: Test CPU signatures
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The signature computation code is not too complicated and it will likely
+never change so testing it is not very important. We do it mostly for a
+nice side effect of easily accessible signature numbers for all CPU
+data files.
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit dd08d27fc205c86961b6d957fbb92da5aead5d1b)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1686895
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <24fc3fddd709251f12a12589605c76634af8fb1b.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ tests/cputest.c                               | 86 +++++++++++++++++++
+ tests/cputestdata/x86_64-cpuid-A10-5800K.sig  |  4 +
+ tests/cputestdata/x86_64-cpuid-Atom-D510.sig  |  4 +
+ tests/cputestdata/x86_64-cpuid-Atom-N450.sig  |  4 +
+ .../cputestdata/x86_64-cpuid-Core-i5-2500.sig |  4 +
+ .../x86_64-cpuid-Core-i5-2540M.sig            |  4 +
+ .../x86_64-cpuid-Core-i5-4670T.sig            |  4 +
+ .../cputestdata/x86_64-cpuid-Core-i5-650.sig  |  4 +
+ .../cputestdata/x86_64-cpuid-Core-i5-6600.sig |  4 +
+ .../x86_64-cpuid-Core-i7-2600-xsaveopt.sig    |  4 +
+ .../cputestdata/x86_64-cpuid-Core-i7-2600.sig |  4 +
+ .../x86_64-cpuid-Core-i7-3520M.sig            |  4 +
+ .../x86_64-cpuid-Core-i7-3740QM.sig           |  4 +
+ .../cputestdata/x86_64-cpuid-Core-i7-3770.sig |  4 +
+ .../x86_64-cpuid-Core-i7-4510U.sig            |  4 +
+ .../x86_64-cpuid-Core-i7-4600U.sig            |  4 +
+ .../x86_64-cpuid-Core-i7-5600U-arat.sig       |  4 +
+ .../x86_64-cpuid-Core-i7-5600U-ibrs.sig       |  4 +
+ .../x86_64-cpuid-Core-i7-5600U.sig            |  4 +
+ .../x86_64-cpuid-Core-i7-7600U.sig            |  4 +
+ .../cputestdata/x86_64-cpuid-Core-i7-7700.sig |  4 +
+ .../cputestdata/x86_64-cpuid-Core-i7-8700.sig |  4 +
+ .../cputestdata/x86_64-cpuid-Core2-E6850.sig  |  4 +
+ .../cputestdata/x86_64-cpuid-Core2-Q9500.sig  |  4 +
+ .../x86_64-cpuid-EPYC-7601-32-Core-ibpb.sig   |  4 +
+ .../x86_64-cpuid-EPYC-7601-32-Core.sig        |  4 +
+ tests/cputestdata/x86_64-cpuid-FX-8150.sig    |  4 +
+ .../cputestdata/x86_64-cpuid-Opteron-1352.sig |  4 +
+ .../cputestdata/x86_64-cpuid-Opteron-2350.sig |  4 +
+ .../cputestdata/x86_64-cpuid-Opteron-6234.sig |  4 +
+ .../cputestdata/x86_64-cpuid-Opteron-6282.sig |  4 +
+ .../x86_64-cpuid-Pentium-P6100.sig            |  4 +
+ tests/cputestdata/x86_64-cpuid-Phenom-B95.sig |  4 +
+ .../x86_64-cpuid-Ryzen-7-1800X-Eight-Core.sig |  4 +
+ tests/cputestdata/x86_64-cpuid-Xeon-5110.sig  |  4 +
+ .../x86_64-cpuid-Xeon-E3-1245-v5.sig          |  4 +
+ .../x86_64-cpuid-Xeon-E5-2609-v3.sig          |  4 +
+ .../x86_64-cpuid-Xeon-E5-2623-v4.sig          |  4 +
+ .../x86_64-cpuid-Xeon-E5-2630-v3.sig          |  4 +
+ .../x86_64-cpuid-Xeon-E5-2630-v4.sig          |  4 +
+ .../x86_64-cpuid-Xeon-E5-2650-v3.sig          |  4 +
+ .../x86_64-cpuid-Xeon-E5-2650-v4.sig          |  4 +
+ .../cputestdata/x86_64-cpuid-Xeon-E5-2650.sig |  4 +
+ .../cputestdata/x86_64-cpuid-Xeon-E7-4820.sig |  4 +
+ .../cputestdata/x86_64-cpuid-Xeon-E7-4830.sig |  4 +
+ .../x86_64-cpuid-Xeon-E7-8890-v3.sig          |  4 +
+ tests/cputestdata/x86_64-cpuid-Xeon-E7540.sig |  4 +
+ .../x86_64-cpuid-Xeon-Gold-5115.sig           |  4 +
+ .../x86_64-cpuid-Xeon-Gold-6148.sig           |  4 +
+ tests/cputestdata/x86_64-cpuid-Xeon-W3520.sig |  4 +
+ tests/cputestdata/x86_64-cpuid-Xeon-X5460.sig |  4 +
+ 51 files changed, 286 insertions(+)
+ create mode 100644 tests/cputestdata/x86_64-cpuid-A10-5800K.sig
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Atom-D510.sig
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Atom-N450.sig
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Core-i5-2500.sig
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Core-i5-2540M.sig
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Core-i5-4670T.sig
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Core-i5-650.sig
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Core-i5-6600.sig
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Core-i7-2600-xsaveopt.sig
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Core-i7-2600.sig
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Core-i7-3520M.sig
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Core-i7-3740QM.sig
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Core-i7-3770.sig
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Core-i7-4510U.sig
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Core-i7-4600U.sig
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Core-i7-5600U-arat.sig
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Core-i7-5600U-ibrs.sig
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Core-i7-5600U.sig
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Core-i7-7600U.sig
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Core-i7-7700.sig
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Core-i7-8700.sig
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Core2-E6850.sig
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Core2-Q9500.sig
+ create mode 100644 tests/cputestdata/x86_64-cpuid-EPYC-7601-32-Core-ibpb.sig
+ create mode 100644 tests/cputestdata/x86_64-cpuid-EPYC-7601-32-Core.sig
+ create mode 100644 tests/cputestdata/x86_64-cpuid-FX-8150.sig
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Opteron-1352.sig
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Opteron-2350.sig
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Opteron-6234.sig
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Opteron-6282.sig
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Pentium-P6100.sig
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Phenom-B95.sig
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Ryzen-7-1800X-Eight-Core.sig
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-5110.sig
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-E3-1245-v5.sig
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-E5-2609-v3.sig
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-E5-2623-v4.sig
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-E5-2630-v3.sig
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-E5-2630-v4.sig
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-E5-2650-v3.sig
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-E5-2650-v4.sig
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-E5-2650.sig
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-E7-4820.sig
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-E7-4830.sig
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-E7-8890-v3.sig
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-E7540.sig
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-Gold-5115.sig
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-Gold-6148.sig
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-W3520.sig
+ create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-X5460.sig
+
+diff --git a/tests/cputest.c b/tests/cputest.c
+index 9e5f807823..0cb9a57592 100644
+--- a/tests/cputest.c
++++ b/tests/cputest.c
+@@ -37,6 +37,7 @@
+ #include "testutils.h"
+ #include "cpu_conf.h"
+ #include "cpu/cpu.h"
++#include "cpu/cpu_x86.h"
+ #include "cpu/cpu_map.h"
+ #include "virstring.h"
+ 
+@@ -648,6 +649,62 @@ cpuTestGuestCPUID(const void *arg)
+ }
+ 
+ 
++static int
++cpuTestCompareSignature(const struct data *data,
++                        virCPUDataPtr hostData)
++{
++    VIR_AUTOFREE(char *) result = NULL;
++    VIR_AUTOFREE(char *) sigStr = NULL;
++    unsigned long signature;
++    unsigned int family;
++    unsigned int model;
++    unsigned int stepping;
++
++    signature = virCPUx86DataGetSignature(hostData, &family, &model, &stepping);
++
++    if (virAsprintf(&result, "%s/cputestdata/%s-cpuid-%s.sig",
++                    abs_srcdir, virArchToString(data->arch), data->host) < 0)
++        return -1;
++
++    if (virAsprintf(&sigStr,
++                    "%1$06lx\n"
++                    "family:   %2$3u (0x%2$02x)\n"
++                    "model:    %3$3u (0x%3$02x)\n"
++                    "stepping: %4$3u (0x%4$02x)\n",
++                    signature, family, model, stepping) < 0)
++        return -1;
++
++    return virTestCompareToFile(sigStr, result);
++}
++
++
++static int
++cpuTestCPUIDSignature(const void *arg)
++{
++    const struct data *data = arg;
++    virCPUDataPtr hostData = NULL;
++    char *hostFile = NULL;
++    char *host = NULL;
++    int ret = -1;
++
++    if (virAsprintf(&hostFile, "%s/cputestdata/%s-cpuid-%s.xml",
++                    abs_srcdir, virArchToString(data->arch), data->host) < 0)
++        goto cleanup;
++
++    if (virTestLoadFile(hostFile, &host) < 0 ||
++        !(hostData = virCPUDataParse(host)))
++        goto cleanup;
++
++    ret = cpuTestCompareSignature(data, hostData);
++
++ cleanup:
++    virCPUDataFree(hostData);
++    VIR_FREE(hostFile);
++    VIR_FREE(host);
++    return ret;
++}
++
++
+ static int
+ cpuTestUpdateLiveCompare(virArch arch,
+                          virCPUDefPtr actual,
+@@ -869,6 +926,31 @@ cpuTestJSONCPUID(const void *arg)
+     VIR_FREE(result);
+     return ret;
+ }
++
++
++static int
++cpuTestJSONSignature(const void *arg)
++{
++    const struct data *data = arg;
++    virQEMUCapsPtr qemuCaps = NULL;
++    virCPUDataPtr hostData = NULL;
++    qemuMonitorCPUModelInfoPtr modelInfo;
++    int ret = -1;
++
++    if (!(qemuCaps = cpuTestMakeQEMUCaps(data)))
++        goto cleanup;
++
++    modelInfo = virQEMUCapsGetCPUModelInfo(qemuCaps, VIR_DOMAIN_VIRT_KVM);
++    if (!(hostData = virQEMUCapsGetCPUModelX86Data(modelInfo, false)))
++        goto cleanup;
++
++    ret = cpuTestCompareSignature(data, hostData);
++
++ cleanup:
++    virObjectUnref(qemuCaps);
++    virCPUDataFree(hostData);
++    return ret;
++}
+ #endif
+ 
+ 
+@@ -1014,6 +1096,8 @@ mymain(void)
+         if (json != JSON_NONE) { \
+             DO_TEST(arch, cpuTestJSONCPUID, host, host, \
+                     NULL, NULL, json, 0); \
++            DO_TEST(arch, cpuTestJSONSignature, host, host, \
++                    NULL, NULL, 0, 0); \
+         } \
+     } while (0)
+ #else
+@@ -1026,6 +1110,8 @@ mymain(void)
+                 NULL, NULL, 0, 0); \
+         DO_TEST(arch, cpuTestGuestCPUID, host, host, \
+                 NULL, NULL, json, 0); \
++        DO_TEST(arch, cpuTestCPUIDSignature, host, host, \
++                NULL, NULL, 0, 0); \
+         DO_TEST_JSON(arch, host, json); \
+         if (json != JSON_NONE) { \
+             DO_TEST(arch, cpuTestUpdateLive, host, host, \
+diff --git a/tests/cputestdata/x86_64-cpuid-A10-5800K.sig b/tests/cputestdata/x86_64-cpuid-A10-5800K.sig
+new file mode 100644
+index 0000000000..8045eda561
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-A10-5800K.sig
+@@ -0,0 +1,4 @@
++610f01
++family:    21 (0x15)
++model:     16 (0x10)
++stepping:   1 (0x01)
+diff --git a/tests/cputestdata/x86_64-cpuid-Atom-D510.sig b/tests/cputestdata/x86_64-cpuid-Atom-D510.sig
+new file mode 100644
+index 0000000000..d22d28ff8a
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Atom-D510.sig
+@@ -0,0 +1,4 @@
++0106ca
++family:     6 (0x06)
++model:     28 (0x1c)
++stepping:  10 (0x0a)
+diff --git a/tests/cputestdata/x86_64-cpuid-Atom-N450.sig b/tests/cputestdata/x86_64-cpuid-Atom-N450.sig
+new file mode 100644
+index 0000000000..d22d28ff8a
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Atom-N450.sig
+@@ -0,0 +1,4 @@
++0106ca
++family:     6 (0x06)
++model:     28 (0x1c)
++stepping:  10 (0x0a)
+diff --git a/tests/cputestdata/x86_64-cpuid-Core-i5-2500.sig b/tests/cputestdata/x86_64-cpuid-Core-i5-2500.sig
+new file mode 100644
+index 0000000000..9b113c3798
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Core-i5-2500.sig
+@@ -0,0 +1,4 @@
++0206a7
++family:     6 (0x06)
++model:     42 (0x2a)
++stepping:   7 (0x07)
+diff --git a/tests/cputestdata/x86_64-cpuid-Core-i5-2540M.sig b/tests/cputestdata/x86_64-cpuid-Core-i5-2540M.sig
+new file mode 100644
+index 0000000000..9b113c3798
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Core-i5-2540M.sig
+@@ -0,0 +1,4 @@
++0206a7
++family:     6 (0x06)
++model:     42 (0x2a)
++stepping:   7 (0x07)
+diff --git a/tests/cputestdata/x86_64-cpuid-Core-i5-4670T.sig b/tests/cputestdata/x86_64-cpuid-Core-i5-4670T.sig
+new file mode 100644
+index 0000000000..e2fb6c5dd2
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Core-i5-4670T.sig
+@@ -0,0 +1,4 @@
++0306c3
++family:     6 (0x06)
++model:     60 (0x3c)
++stepping:   3 (0x03)
+diff --git a/tests/cputestdata/x86_64-cpuid-Core-i5-650.sig b/tests/cputestdata/x86_64-cpuid-Core-i5-650.sig
+new file mode 100644
+index 0000000000..fc7c566de5
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Core-i5-650.sig
+@@ -0,0 +1,4 @@
++020652
++family:     6 (0x06)
++model:     37 (0x25)
++stepping:   2 (0x02)
+diff --git a/tests/cputestdata/x86_64-cpuid-Core-i5-6600.sig b/tests/cputestdata/x86_64-cpuid-Core-i5-6600.sig
+new file mode 100644
+index 0000000000..7e57c2ded6
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Core-i5-6600.sig
+@@ -0,0 +1,4 @@
++0506e3
++family:     6 (0x06)
++model:     94 (0x5e)
++stepping:   3 (0x03)
+diff --git a/tests/cputestdata/x86_64-cpuid-Core-i7-2600-xsaveopt.sig b/tests/cputestdata/x86_64-cpuid-Core-i7-2600-xsaveopt.sig
+new file mode 100644
+index 0000000000..9b113c3798
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Core-i7-2600-xsaveopt.sig
+@@ -0,0 +1,4 @@
++0206a7
++family:     6 (0x06)
++model:     42 (0x2a)
++stepping:   7 (0x07)
+diff --git a/tests/cputestdata/x86_64-cpuid-Core-i7-2600.sig b/tests/cputestdata/x86_64-cpuid-Core-i7-2600.sig
+new file mode 100644
+index 0000000000..9b113c3798
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Core-i7-2600.sig
+@@ -0,0 +1,4 @@
++0206a7
++family:     6 (0x06)
++model:     42 (0x2a)
++stepping:   7 (0x07)
+diff --git a/tests/cputestdata/x86_64-cpuid-Core-i7-3520M.sig b/tests/cputestdata/x86_64-cpuid-Core-i7-3520M.sig
+new file mode 100644
+index 0000000000..9c6ea10a83
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Core-i7-3520M.sig
+@@ -0,0 +1,4 @@
++0306a9
++family:     6 (0x06)
++model:     58 (0x3a)
++stepping:   9 (0x09)
+diff --git a/tests/cputestdata/x86_64-cpuid-Core-i7-3740QM.sig b/tests/cputestdata/x86_64-cpuid-Core-i7-3740QM.sig
+new file mode 100644
+index 0000000000..9c6ea10a83
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Core-i7-3740QM.sig
+@@ -0,0 +1,4 @@
++0306a9
++family:     6 (0x06)
++model:     58 (0x3a)
++stepping:   9 (0x09)
+diff --git a/tests/cputestdata/x86_64-cpuid-Core-i7-3770.sig b/tests/cputestdata/x86_64-cpuid-Core-i7-3770.sig
+new file mode 100644
+index 0000000000..9c6ea10a83
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Core-i7-3770.sig
+@@ -0,0 +1,4 @@
++0306a9
++family:     6 (0x06)
++model:     58 (0x3a)
++stepping:   9 (0x09)
+diff --git a/tests/cputestdata/x86_64-cpuid-Core-i7-4510U.sig b/tests/cputestdata/x86_64-cpuid-Core-i7-4510U.sig
+new file mode 100644
+index 0000000000..fd6726a3da
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Core-i7-4510U.sig
+@@ -0,0 +1,4 @@
++040651
++family:     6 (0x06)
++model:     69 (0x45)
++stepping:   1 (0x01)
+diff --git a/tests/cputestdata/x86_64-cpuid-Core-i7-4600U.sig b/tests/cputestdata/x86_64-cpuid-Core-i7-4600U.sig
+new file mode 100644
+index 0000000000..fd6726a3da
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Core-i7-4600U.sig
+@@ -0,0 +1,4 @@
++040651
++family:     6 (0x06)
++model:     69 (0x45)
++stepping:   1 (0x01)
+diff --git a/tests/cputestdata/x86_64-cpuid-Core-i7-5600U-arat.sig b/tests/cputestdata/x86_64-cpuid-Core-i7-5600U-arat.sig
+new file mode 100644
+index 0000000000..dd18d0f76d
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Core-i7-5600U-arat.sig
+@@ -0,0 +1,4 @@
++0306d4
++family:     6 (0x06)
++model:     61 (0x3d)
++stepping:   4 (0x04)
+diff --git a/tests/cputestdata/x86_64-cpuid-Core-i7-5600U-ibrs.sig b/tests/cputestdata/x86_64-cpuid-Core-i7-5600U-ibrs.sig
+new file mode 100644
+index 0000000000..dd18d0f76d
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Core-i7-5600U-ibrs.sig
+@@ -0,0 +1,4 @@
++0306d4
++family:     6 (0x06)
++model:     61 (0x3d)
++stepping:   4 (0x04)
+diff --git a/tests/cputestdata/x86_64-cpuid-Core-i7-5600U.sig b/tests/cputestdata/x86_64-cpuid-Core-i7-5600U.sig
+new file mode 100644
+index 0000000000..dd18d0f76d
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Core-i7-5600U.sig
+@@ -0,0 +1,4 @@
++0306d4
++family:     6 (0x06)
++model:     61 (0x3d)
++stepping:   4 (0x04)
+diff --git a/tests/cputestdata/x86_64-cpuid-Core-i7-7600U.sig b/tests/cputestdata/x86_64-cpuid-Core-i7-7600U.sig
+new file mode 100644
+index 0000000000..8f757722bb
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Core-i7-7600U.sig
+@@ -0,0 +1,4 @@
++0806e9
++family:     6 (0x06)
++model:    142 (0x8e)
++stepping:   9 (0x09)
+diff --git a/tests/cputestdata/x86_64-cpuid-Core-i7-7700.sig b/tests/cputestdata/x86_64-cpuid-Core-i7-7700.sig
+new file mode 100644
+index 0000000000..d4db84a618
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Core-i7-7700.sig
+@@ -0,0 +1,4 @@
++0906e9
++family:     6 (0x06)
++model:    158 (0x9e)
++stepping:   9 (0x09)
+diff --git a/tests/cputestdata/x86_64-cpuid-Core-i7-8700.sig b/tests/cputestdata/x86_64-cpuid-Core-i7-8700.sig
+new file mode 100644
+index 0000000000..45d6ea29d0
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Core-i7-8700.sig
+@@ -0,0 +1,4 @@
++0906ea
++family:     6 (0x06)
++model:    158 (0x9e)
++stepping:  10 (0x0a)
+diff --git a/tests/cputestdata/x86_64-cpuid-Core2-E6850.sig b/tests/cputestdata/x86_64-cpuid-Core2-E6850.sig
+new file mode 100644
+index 0000000000..2382914bc7
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Core2-E6850.sig
+@@ -0,0 +1,4 @@
++0006fb
++family:     6 (0x06)
++model:     15 (0x0f)
++stepping:  11 (0x0b)
+diff --git a/tests/cputestdata/x86_64-cpuid-Core2-Q9500.sig b/tests/cputestdata/x86_64-cpuid-Core2-Q9500.sig
+new file mode 100644
+index 0000000000..9aec5927d0
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Core2-Q9500.sig
+@@ -0,0 +1,4 @@
++01067a
++family:     6 (0x06)
++model:     23 (0x17)
++stepping:  10 (0x0a)
+diff --git a/tests/cputestdata/x86_64-cpuid-EPYC-7601-32-Core-ibpb.sig b/tests/cputestdata/x86_64-cpuid-EPYC-7601-32-Core-ibpb.sig
+new file mode 100644
+index 0000000000..8fe15b7991
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-EPYC-7601-32-Core-ibpb.sig
+@@ -0,0 +1,4 @@
++800f12
++family:    23 (0x17)
++model:      1 (0x01)
++stepping:   2 (0x02)
+diff --git a/tests/cputestdata/x86_64-cpuid-EPYC-7601-32-Core.sig b/tests/cputestdata/x86_64-cpuid-EPYC-7601-32-Core.sig
+new file mode 100644
+index 0000000000..8fe15b7991
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-EPYC-7601-32-Core.sig
+@@ -0,0 +1,4 @@
++800f12
++family:    23 (0x17)
++model:      1 (0x01)
++stepping:   2 (0x02)
+diff --git a/tests/cputestdata/x86_64-cpuid-FX-8150.sig b/tests/cputestdata/x86_64-cpuid-FX-8150.sig
+new file mode 100644
+index 0000000000..4b6440a315
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-FX-8150.sig
+@@ -0,0 +1,4 @@
++600f12
++family:    21 (0x15)
++model:      1 (0x01)
++stepping:   2 (0x02)
+diff --git a/tests/cputestdata/x86_64-cpuid-Opteron-1352.sig b/tests/cputestdata/x86_64-cpuid-Opteron-1352.sig
+new file mode 100644
+index 0000000000..d21535b4b9
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Opteron-1352.sig
+@@ -0,0 +1,4 @@
++100f23
++family:    16 (0x10)
++model:      2 (0x02)
++stepping:   3 (0x03)
+diff --git a/tests/cputestdata/x86_64-cpuid-Opteron-2350.sig b/tests/cputestdata/x86_64-cpuid-Opteron-2350.sig
+new file mode 100644
+index 0000000000..d21535b4b9
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Opteron-2350.sig
+@@ -0,0 +1,4 @@
++100f23
++family:    16 (0x10)
++model:      2 (0x02)
++stepping:   3 (0x03)
+diff --git a/tests/cputestdata/x86_64-cpuid-Opteron-6234.sig b/tests/cputestdata/x86_64-cpuid-Opteron-6234.sig
+new file mode 100644
+index 0000000000..4b6440a315
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Opteron-6234.sig
+@@ -0,0 +1,4 @@
++600f12
++family:    21 (0x15)
++model:      1 (0x01)
++stepping:   2 (0x02)
+diff --git a/tests/cputestdata/x86_64-cpuid-Opteron-6282.sig b/tests/cputestdata/x86_64-cpuid-Opteron-6282.sig
+new file mode 100644
+index 0000000000..4b6440a315
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Opteron-6282.sig
+@@ -0,0 +1,4 @@
++600f12
++family:    21 (0x15)
++model:      1 (0x01)
++stepping:   2 (0x02)
+diff --git a/tests/cputestdata/x86_64-cpuid-Pentium-P6100.sig b/tests/cputestdata/x86_64-cpuid-Pentium-P6100.sig
+new file mode 100644
+index 0000000000..8712d34023
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Pentium-P6100.sig
+@@ -0,0 +1,4 @@
++020655
++family:     6 (0x06)
++model:     37 (0x25)
++stepping:   5 (0x05)
+diff --git a/tests/cputestdata/x86_64-cpuid-Phenom-B95.sig b/tests/cputestdata/x86_64-cpuid-Phenom-B95.sig
+new file mode 100644
+index 0000000000..c93dbebc45
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Phenom-B95.sig
+@@ -0,0 +1,4 @@
++100f42
++family:    16 (0x10)
++model:      4 (0x04)
++stepping:   2 (0x02)
+diff --git a/tests/cputestdata/x86_64-cpuid-Ryzen-7-1800X-Eight-Core.sig b/tests/cputestdata/x86_64-cpuid-Ryzen-7-1800X-Eight-Core.sig
+new file mode 100644
+index 0000000000..031bb84902
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Ryzen-7-1800X-Eight-Core.sig
+@@ -0,0 +1,4 @@
++800f11
++family:    23 (0x17)
++model:      1 (0x01)
++stepping:   1 (0x01)
+diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-5110.sig b/tests/cputestdata/x86_64-cpuid-Xeon-5110.sig
+new file mode 100644
+index 0000000000..15f8400ca6
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Xeon-5110.sig
+@@ -0,0 +1,4 @@
++0006f6
++family:     6 (0x06)
++model:     15 (0x0f)
++stepping:   6 (0x06)
+diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E3-1245-v5.sig b/tests/cputestdata/x86_64-cpuid-Xeon-E3-1245-v5.sig
+new file mode 100644
+index 0000000000..7e57c2ded6
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Xeon-E3-1245-v5.sig
+@@ -0,0 +1,4 @@
++0506e3
++family:     6 (0x06)
++model:     94 (0x5e)
++stepping:   3 (0x03)
+diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E5-2609-v3.sig b/tests/cputestdata/x86_64-cpuid-Xeon-E5-2609-v3.sig
+new file mode 100644
+index 0000000000..2c548c9934
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Xeon-E5-2609-v3.sig
+@@ -0,0 +1,4 @@
++0306f2
++family:     6 (0x06)
++model:     63 (0x3f)
++stepping:   2 (0x02)
+diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E5-2623-v4.sig b/tests/cputestdata/x86_64-cpuid-Xeon-E5-2623-v4.sig
+new file mode 100644
+index 0000000000..4d1622a8ef
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Xeon-E5-2623-v4.sig
+@@ -0,0 +1,4 @@
++0406f1
++family:     6 (0x06)
++model:     79 (0x4f)
++stepping:   1 (0x01)
+diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E5-2630-v3.sig b/tests/cputestdata/x86_64-cpuid-Xeon-E5-2630-v3.sig
+new file mode 100644
+index 0000000000..2c548c9934
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Xeon-E5-2630-v3.sig
+@@ -0,0 +1,4 @@
++0306f2
++family:     6 (0x06)
++model:     63 (0x3f)
++stepping:   2 (0x02)
+diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E5-2630-v4.sig b/tests/cputestdata/x86_64-cpuid-Xeon-E5-2630-v4.sig
+new file mode 100644
+index 0000000000..4d1622a8ef
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Xeon-E5-2630-v4.sig
+@@ -0,0 +1,4 @@
++0406f1
++family:     6 (0x06)
++model:     79 (0x4f)
++stepping:   1 (0x01)
+diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E5-2650-v3.sig b/tests/cputestdata/x86_64-cpuid-Xeon-E5-2650-v3.sig
+new file mode 100644
+index 0000000000..2c548c9934
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Xeon-E5-2650-v3.sig
+@@ -0,0 +1,4 @@
++0306f2
++family:     6 (0x06)
++model:     63 (0x3f)
++stepping:   2 (0x02)
+diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E5-2650-v4.sig b/tests/cputestdata/x86_64-cpuid-Xeon-E5-2650-v4.sig
+new file mode 100644
+index 0000000000..4d1622a8ef
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Xeon-E5-2650-v4.sig
+@@ -0,0 +1,4 @@
++0406f1
++family:     6 (0x06)
++model:     79 (0x4f)
++stepping:   1 (0x01)
+diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E5-2650.sig b/tests/cputestdata/x86_64-cpuid-Xeon-E5-2650.sig
+new file mode 100644
+index 0000000000..d6493fe186
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Xeon-E5-2650.sig
+@@ -0,0 +1,4 @@
++0206d7
++family:     6 (0x06)
++model:     45 (0x2d)
++stepping:   7 (0x07)
+diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E7-4820.sig b/tests/cputestdata/x86_64-cpuid-Xeon-E7-4820.sig
+new file mode 100644
+index 0000000000..8738e95e41
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Xeon-E7-4820.sig
+@@ -0,0 +1,4 @@
++0206f2
++family:     6 (0x06)
++model:     47 (0x2f)
++stepping:   2 (0x02)
+diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E7-4830.sig b/tests/cputestdata/x86_64-cpuid-Xeon-E7-4830.sig
+new file mode 100644
+index 0000000000..8738e95e41
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Xeon-E7-4830.sig
+@@ -0,0 +1,4 @@
++0206f2
++family:     6 (0x06)
++model:     47 (0x2f)
++stepping:   2 (0x02)
+diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E7-8890-v3.sig b/tests/cputestdata/x86_64-cpuid-Xeon-E7-8890-v3.sig
+new file mode 100644
+index 0000000000..8fb489fac9
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Xeon-E7-8890-v3.sig
+@@ -0,0 +1,4 @@
++0306f4
++family:     6 (0x06)
++model:     63 (0x3f)
++stepping:   4 (0x04)
+diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E7540.sig b/tests/cputestdata/x86_64-cpuid-Xeon-E7540.sig
+new file mode 100644
+index 0000000000..afc150cf82
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Xeon-E7540.sig
+@@ -0,0 +1,4 @@
++0206e6
++family:     6 (0x06)
++model:     46 (0x2e)
++stepping:   6 (0x06)
+diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-Gold-5115.sig b/tests/cputestdata/x86_64-cpuid-Xeon-Gold-5115.sig
+new file mode 100644
+index 0000000000..1a3f3449f0
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Xeon-Gold-5115.sig
+@@ -0,0 +1,4 @@
++050654
++family:     6 (0x06)
++model:     85 (0x55)
++stepping:   4 (0x04)
+diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-Gold-6148.sig b/tests/cputestdata/x86_64-cpuid-Xeon-Gold-6148.sig
+new file mode 100644
+index 0000000000..1a3f3449f0
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Xeon-Gold-6148.sig
+@@ -0,0 +1,4 @@
++050654
++family:     6 (0x06)
++model:     85 (0x55)
++stepping:   4 (0x04)
+diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-W3520.sig b/tests/cputestdata/x86_64-cpuid-Xeon-W3520.sig
+new file mode 100644
+index 0000000000..4b641ba966
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Xeon-W3520.sig
+@@ -0,0 +1,4 @@
++0106a5
++family:     6 (0x06)
++model:     26 (0x1a)
++stepping:   5 (0x05)
+diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-X5460.sig b/tests/cputestdata/x86_64-cpuid-Xeon-X5460.sig
+new file mode 100644
+index 0000000000..e17253472f
+--- /dev/null
++++ b/tests/cputestdata/x86_64-cpuid-Xeon-X5460.sig
+@@ -0,0 +1,4 @@
++010676
++family:     6 (0x06)
++model:     23 (0x17)
++stepping:   6 (0x06)
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-daemon-Register-secret-driver-before-storage-driver.patch b/SOURCES/libvirt-daemon-Register-secret-driver-before-storage-driver.patch
new file mode 100644
index 0000000..3825d3b
--- /dev/null
+++ b/SOURCES/libvirt-daemon-Register-secret-driver-before-storage-driver.patch
@@ -0,0 +1,59 @@
+From 8a9a0815510ef6de1ee34b865a768d0c6fd7b828 Mon Sep 17 00:00:00 2001
+Message-Id: <8a9a0815510ef6de1ee34b865a768d0c6fd7b828@dist-git>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Thu, 27 Jun 2019 15:18:14 +0200
+Subject: [PATCH] daemon: Register secret driver before storage driver
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The order in which drivers are registered is important because
+their stateInitialize and stateAutoStart callback are called in
+that order. Well, stateAutoStart is going away and therefore if
+there is some dependency between two drivers (e.g. when
+initializing storage driver expects secret driver to be available
+already), the registration of such drivers must happen in correct
+order.
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit c6266ddb0214512200c5043f3196d3ca3e73919d)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1685151
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Message-Id: <f67abc5158c74a295438b5e2f1b8106e8910bfde.1561641375.git.mprivozn@redhat.com>
+Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/remote/remote_daemon.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/src/remote/remote_daemon.c b/src/remote/remote_daemon.c
+index 9f3a5f38ad..4cd6784099 100644
+--- a/src/remote/remote_daemon.c
++++ b/src/remote/remote_daemon.c
+@@ -314,6 +314,10 @@ static int daemonInitialize(void)
+     if (virDriverLoadModule("interface", "interfaceRegister", false) < 0)
+         return -1;
+ #endif
++#ifdef WITH_SECRETS
++    if (virDriverLoadModule("secret", "secretRegister", false) < 0)
++        return -1;
++#endif
+ #ifdef WITH_STORAGE
+     if (virDriverLoadModule("storage", "storageRegister", false) < 0)
+         return -1;
+@@ -322,10 +326,6 @@ static int daemonInitialize(void)
+     if (virDriverLoadModule("nodedev", "nodedevRegister", false) < 0)
+         return -1;
+ #endif
+-#ifdef WITH_SECRETS
+-    if (virDriverLoadModule("secret", "secretRegister", false) < 0)
+-        return -1;
+-#endif
+ #ifdef WITH_NWFILTER
+     if (virDriverLoadModule("nwfilter", "nwfilterRegister", false) < 0)
+         return -1;
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-docs-schemas-Decouple-the-virtio-options-from-each-other.patch b/SOURCES/libvirt-docs-schemas-Decouple-the-virtio-options-from-each-other.patch
new file mode 100644
index 0000000..fba0e09
--- /dev/null
+++ b/SOURCES/libvirt-docs-schemas-Decouple-the-virtio-options-from-each-other.patch
@@ -0,0 +1,44 @@
+From eb6fef622ded5762649db2d766c1eb3d876859c9 Mon Sep 17 00:00:00 2001
+Message-Id: <eb6fef622ded5762649db2d766c1eb3d876859c9@dist-git>
+From: Erik Skultety <eskultet@redhat.com>
+Date: Mon, 15 Jul 2019 08:52:07 +0200
+Subject: [PATCH] docs: schemas: Decouple the virtio options from each other
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Currently, all of the VirtioOptions are under a single <optional>
+element, however, neither our parser/formatter or QEMU driver requires
+the presence of all the options if only a single one from the set has
+been specified, so fix it and silence the schema validator.
+
+Signed-off-by: Erik Skultety <eskultet@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit 87b4e1cd7e7ec23dc69c8082948cd3bb49e18ff3)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1729675
+
+Signed-off-by: Erik Skultety <eskultet@redhat.com>
+Message-Id: <9d20b6d62248ef82a42128c461ef8c94cbc64e09.1563173480.git.eskultet@redhat.com>
+Reviewed-by: Andrea Bolognani <abologna@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ docs/schemas/domaincommon.rng | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
+index 2b6d4dced6..7d37caa246 100644
+--- a/docs/schemas/domaincommon.rng
++++ b/docs/schemas/domaincommon.rng
+@@ -5417,6 +5417,8 @@
+       <attribute name="iommu">
+         <ref name="virOnOff"/>
+       </attribute>
++    </optional>
++    <optional>
+       <attribute name="ats">
+         <ref name="virOnOff"/>
+       </attribute>
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-internal-introduce-a-family-of-NULLSTR-macros.patch b/SOURCES/libvirt-internal-introduce-a-family-of-NULLSTR-macros.patch
new file mode 100644
index 0000000..e4bf0c4
--- /dev/null
+++ b/SOURCES/libvirt-internal-introduce-a-family-of-NULLSTR-macros.patch
@@ -0,0 +1,55 @@
+From c93476692d7e0373f147c3ed20761ea1fe836e89 Mon Sep 17 00:00:00 2001
+Message-Id: <c93476692d7e0373f147c3ed20761ea1fe836e89@dist-git>
+From: =?UTF-8?q?J=C3=A1n=20Tomko?= <jtomko@redhat.com>
+Date: Mon, 1 Jul 2019 17:08:16 +0200
+Subject: [PATCH] internal: introduce a family of NULLSTR macros
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+NULLSTR_EMPTY, the quiet child,
+NULLSTR_STAR, the famous one and
+NULLSTR_MINUS, the grumpy one.
+
+Signed-off-by: Ján Tomko <jtomko@redhat.com>
+Reviewed-by: Andrea Bolognani <abologna@redhat.com>
+(cherry picked from commit bd5519deb75e9ff8adcd56d34cbe82dd6a341bcb)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <16722b79dbd931a33ef495b863c5716bb5d6e97c.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/internal.h | 15 +++++++++++++++
+ 1 file changed, 15 insertions(+)
+
+diff --git a/src/internal.h b/src/internal.h
+index 47ff0479d2..a4f6605a50 100644
+--- a/src/internal.h
++++ b/src/internal.h
+@@ -244,6 +244,21 @@
+  */
+ # define EMPTYSTR(s) ((s) ? (s) : "-")
+ 
++/*
++ * Turn a NULL string into an empty string
++ */
++# define NULLSTR_EMPTY(s) ((s) ? (s) : "")
++
++/*
++ * Turn a NULL string into a star
++ */
++# define NULLSTR_STAR(s) ((s) ? (s) : "*")
++
++/*
++ * Turn a NULL string into a minus sign
++ */
++# define NULLSTR_MINUS(s) ((s) ? (s) : "-")
++
+ /**
+  * SWAP:
+  *
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-lib-Drop-UDEVSETTLE.patch b/SOURCES/libvirt-lib-Drop-UDEVSETTLE.patch
new file mode 100644
index 0000000..33c3c7e
--- /dev/null
+++ b/SOURCES/libvirt-lib-Drop-UDEVSETTLE.patch
@@ -0,0 +1,73 @@
+From b5dbb3bd65642516a773a2cdf67efe977cfec4b4 Mon Sep 17 00:00:00 2001
+Message-Id: <b5dbb3bd65642516a773a2cdf67efe977cfec4b4@dist-git>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Thu, 27 Jun 2019 15:55:37 +0200
+Subject: [PATCH] lib: Drop UDEVSETTLE
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The udevsettle binary is no longer used anywhere as it was
+replaced by 'udevadm settle'. There's no reason for us to even
+check for it in configure.
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit 2944dcb2de014a881c3539a43f989c2a723e87ca)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1710575
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Message-Id: <b69a2303299a9d69d58d4d54cebd306cdba87c3b.1561643698.git.mprivozn@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ m4/virt-external-programs.m4 | 5 -----
+ src/util/virutil.c           | 6 +-----
+ 2 files changed, 1 insertion(+), 10 deletions(-)
+
+diff --git a/m4/virt-external-programs.m4 b/m4/virt-external-programs.m4
+index ab6149288f..3c915e1a65 100644
+--- a/m4/virt-external-programs.m4
++++ b/m4/virt-external-programs.m4
+@@ -46,7 +46,6 @@ AC_DEFUN([LIBVIRT_CHECK_EXTERNAL_PROGRAMS], [
+   AC_PATH_PROG([RADVD], [radvd], [radvd], [$LIBVIRT_SBIN_PATH])
+   AC_PATH_PROG([TC], [tc], [tc], [$LIBVIRT_SBIN_PATH])
+   AC_PATH_PROG([UDEVADM], [udevadm], [], [$LIBVIRT_SBIN_PATH])
+-  AC_PATH_PROG([UDEVSETTLE], [udevsettle], [], [$LIBVIRT_SBIN_PATH])
+   AC_PATH_PROG([MODPROBE], [modprobe], [modprobe], [$LIBVIRT_SBIN_PATH])
+   AC_PATH_PROG([RMMOD], [rmmod], [rmmod], [$LIBVIRT_SBIN_PATH])
+   AC_PATH_PROG([MMCTL], [mm-ctl], [mm-ctl], [$LIBVIRT_SBIN_PATH])
+@@ -71,10 +70,6 @@ AC_DEFUN([LIBVIRT_CHECK_EXTERNAL_PROGRAMS], [
+     AC_DEFINE_UNQUOTED([UDEVADM], ["$UDEVADM"],
+                        [Location or name of the udevadm program])
+   fi
+-  if test -n "$UDEVSETTLE"; then
+-    AC_DEFINE_UNQUOTED([UDEVSETTLE], ["$UDEVSETTLE"],
+-                       [Location or name of the udevsettle program])
+-  fi
+   if test -n "$MODPROBE"; then
+     AC_DEFINE_UNQUOTED([MODPROBE], ["$MODPROBE"],
+                        [Location or name of the modprobe program])
+diff --git a/src/util/virutil.c b/src/util/virutil.c
+index d37c1ac632..68d3217248 100644
+--- a/src/util/virutil.c
++++ b/src/util/virutil.c
+@@ -1621,14 +1621,10 @@ virSetUIDGIDWithCaps(uid_t uid, gid_t gid, gid_t *groups, int ngroups,
+ #endif
+ 
+ 
+-#if defined(UDEVADM) || defined(UDEVSETTLE)
++#if defined(UDEVADM)
+ void virWaitForDevices(void)
+ {
+-# ifdef UDEVADM
+     const char *const settleprog[] = { UDEVADM, "settle", NULL };
+-# else
+-    const char *const settleprog[] = { UDEVSETTLE, NULL };
+-# endif
+     int exitstatus;
+ 
+     if (access(settleprog[0], X_OK) != 0)
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-locking-restrict-sockets-to-mode-0600.patch b/SOURCES/libvirt-locking-restrict-sockets-to-mode-0600.patch
index 3d10e58..38abe7f 100644
--- a/SOURCES/libvirt-locking-restrict-sockets-to-mode-0600.patch
+++ b/SOURCES/libvirt-locking-restrict-sockets-to-mode-0600.patch
@@ -1,5 +1,5 @@
-From df3809f976bf16fd68cf127e1209282bd751186c Mon Sep 17 00:00:00 2001
-Message-Id: <df3809f976bf16fd68cf127e1209282bd751186c@dist-git>
+From 0fce9e5a4f4e7f12a5eb2fc0cc44f30f26d83157 Mon Sep 17 00:00:00 2001
+Message-Id: <0fce9e5a4f4e7f12a5eb2fc0cc44f30f26d83157@dist-git>
 From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= <berrange@redhat.com>
 Date: Wed, 15 May 2019 21:40:57 +0100
 Subject: [PATCH] locking: restrict sockets to mode 0600
@@ -17,7 +17,7 @@ Fixes CVE-2019-10132
 
 Reviewed-by: Ján Tomko <jtomko@redhat.com>
 Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
-(cherry picked from a private commit)
+(cherry picked from commit f111e09468693909b1f067aa575efdafd9a262a1)
 Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
 Message-Id: <20190515204058.28077-3-berrange@redhat.com>
 ---
@@ -50,5 +50,5 @@ index 45e0f20235..d701b27516 100644
  [Install]
  WantedBy=sockets.target
 -- 
-2.21.0
+2.22.0
 
diff --git a/SOURCES/libvirt-logging-restrict-sockets-to-mode-0600.patch b/SOURCES/libvirt-logging-restrict-sockets-to-mode-0600.patch
index 92d3cb9..cfb4301 100644
--- a/SOURCES/libvirt-logging-restrict-sockets-to-mode-0600.patch
+++ b/SOURCES/libvirt-logging-restrict-sockets-to-mode-0600.patch
@@ -1,5 +1,5 @@
-From b3feb1b383093fd4964de274bf6c96aade1a6d7e Mon Sep 17 00:00:00 2001
-Message-Id: <b3feb1b383093fd4964de274bf6c96aade1a6d7e@dist-git>
+From 3988a7d012fc93eaae82961f72f7c53f26763651 Mon Sep 17 00:00:00 2001
+Message-Id: <3988a7d012fc93eaae82961f72f7c53f26763651@dist-git>
 From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= <berrange@redhat.com>
 Date: Wed, 15 May 2019 21:40:58 +0100
 Subject: [PATCH] logging: restrict sockets to mode 0600
@@ -17,7 +17,7 @@ Fixes CVE-2019-10132
 
 Reviewed-by: Ján Tomko <jtomko@redhat.com>
 Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
-(cherry picked from a private commit)
+(cherry picked from commit e37bd65f9948c1185456b2cdaa3bd6e875af680f)
 Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
 Message-Id: <20190515204058.28077-4-berrange@redhat.com>
 ---
@@ -50,5 +50,5 @@ index 22b9360c8d..ae48cdab9a 100644
  [Install]
  WantedBy=sockets.target
 -- 
-2.21.0
+2.22.0
 
diff --git a/SOURCES/libvirt-lxc-Use-virCgroupGetMemoryStat.patch b/SOURCES/libvirt-lxc-Use-virCgroupGetMemoryStat.patch
new file mode 100644
index 0000000..8e84f9b
--- /dev/null
+++ b/SOURCES/libvirt-lxc-Use-virCgroupGetMemoryStat.patch
@@ -0,0 +1,100 @@
+From fef35da9603a70a60d29420b9cff0db4fc2f0f82 Mon Sep 17 00:00:00 2001
+Message-Id: <fef35da9603a70a60d29420b9cff0db4fc2f0f82@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:06:02 +0200
+Subject: [PATCH] lxc: Use virCgroupGetMemoryStat
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit e634c7cd0d3265506198e1f58f1af1fd774f06b1)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <28c2e0f232ee1c3bce10654df15aa212d5f09996.1561993099.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/lxc/lxc_cgroup.c | 65 +++++---------------------------------------
+ 1 file changed, 7 insertions(+), 58 deletions(-)
+
+diff --git a/src/lxc/lxc_cgroup.c b/src/lxc/lxc_cgroup.c
+index 8e937ec389..d93a19d684 100644
+--- a/src/lxc/lxc_cgroup.c
++++ b/src/lxc/lxc_cgroup.c
+@@ -220,64 +220,13 @@ static int virLXCCgroupGetMemTotal(virCgroupPtr cgroup,
+ static int virLXCCgroupGetMemStat(virCgroupPtr cgroup,
+                                   virLXCMeminfoPtr meminfo)
+ {
+-    int ret = 0;
+-    FILE *statfd = NULL;
+-    char *statFile = NULL;
+-    char *line = NULL;
+-    size_t n;
+-
+-    ret = virCgroupPathOfController(cgroup, VIR_CGROUP_CONTROLLER_MEMORY,
+-                                    "memory.stat", &statFile);
+-    if (ret != 0) {
+-        virReportSystemError(-ret, "%s",
+-                             _("cannot get the path of MEMORY cgroup controller"));
+-        return ret;
+-    }
+-
+-    statfd = fopen(statFile, "r");
+-    if (statfd == NULL) {
+-        ret = -errno;
+-        goto cleanup;
+-    }
+-
+-    while (getline(&line, &n, statfd) > 0) {
+-
+-        char *value = strchr(line, ' ');
+-        char *nl = value ? strchr(line, '\n') : NULL;
+-        unsigned long long stat_value;
+-
+-        if (!value)
+-            continue;
+-
+-        if (nl)
+-            *nl = '\0';
+-
+-        *value = '\0';
+-
+-        if (virStrToLong_ull(value + 1, NULL, 10, &stat_value) < 0) {
+-            ret = -EINVAL;
+-            goto cleanup;
+-        }
+-        if (STREQ(line, "cache"))
+-            meminfo->cached = stat_value >> 10;
+-        else if (STREQ(line, "inactive_anon"))
+-            meminfo->inactive_anon = stat_value >> 10;
+-        else if (STREQ(line, "active_anon"))
+-            meminfo->active_anon = stat_value >> 10;
+-        else if (STREQ(line, "inactive_file"))
+-            meminfo->inactive_file = stat_value >> 10;
+-        else if (STREQ(line, "active_file"))
+-            meminfo->active_file = stat_value >> 10;
+-        else if (STREQ(line, "unevictable"))
+-            meminfo->unevictable = stat_value >> 10;
+-    }
+-    ret = 0;
+-
+- cleanup:
+-    VIR_FREE(line);
+-    VIR_FREE(statFile);
+-    VIR_FORCE_FCLOSE(statfd);
+-    return ret;
++    return virCgroupGetMemoryStat(cgroup,
++                                  &meminfo->cached,
++                                  &meminfo->inactive_anon,
++                                  &meminfo->active_anon,
++                                  &meminfo->inactive_file,
++                                  &meminfo->active_file,
++                                  &meminfo->unevictable);
+ }
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-m4-Drop-needless-string-checks.patch b/SOURCES/libvirt-m4-Drop-needless-string-checks.patch
new file mode 100644
index 0000000..887ee23
--- /dev/null
+++ b/SOURCES/libvirt-m4-Drop-needless-string-checks.patch
@@ -0,0 +1,51 @@
+From 899e80657b58f8ef4c0faf452859fd9649d33b79 Mon Sep 17 00:00:00 2001
+Message-Id: <899e80657b58f8ef4c0faf452859fd9649d33b79@dist-git>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Thu, 27 Jun 2019 15:55:39 +0200
+Subject: [PATCH] m4: Drop needless string checks
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+We provide default values for both MODPROBE and RMMOD and thus
+there is no way that their paths can be empty strings.
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit 3c8d5762a9fcf3f7d23a41d0b49def0387ecddf7)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1710575
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Message-Id: <cb42f6a7b7462140e463a33a7b421ed441617266.1561643698.git.mprivozn@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ m4/virt-external-programs.m4 | 12 ++++--------
+ 1 file changed, 4 insertions(+), 8 deletions(-)
+
+diff --git a/m4/virt-external-programs.m4 b/m4/virt-external-programs.m4
+index f1ae104b32..0f995998c3 100644
+--- a/m4/virt-external-programs.m4
++++ b/m4/virt-external-programs.m4
+@@ -67,14 +67,10 @@ AC_DEFUN([LIBVIRT_CHECK_EXTERNAL_PROGRAMS], [
+                      [Location or name of the ovs-vsctl program])
+   AC_DEFINE_UNQUOTED([UDEVADM], ["$UDEVADM"],
+                      [Location or name of the udevadm program])
+-  if test -n "$MODPROBE"; then
+-    AC_DEFINE_UNQUOTED([MODPROBE], ["$MODPROBE"],
+-                       [Location or name of the modprobe program])
+-  fi
+-  if test -n "$RMMOD"; then
+-    AC_DEFINE_UNQUOTED([RMMOD], ["$RMMOD"],
+-                       [Location or name of the rmmod program])
+-  fi
++  AC_DEFINE_UNQUOTED([MODPROBE], ["$MODPROBE"],
++                     [Location or name of the modprobe program])
++  AC_DEFINE_UNQUOTED([RMMOD], ["$RMMOD"],
++                     [Location or name of the rmmod program])
+   AC_DEFINE_UNQUOTED([SCRUB], ["$SCRUB"],
+                      [Location or name of the scrub program (for wiping algorithms)])
+   AC_DEFINE_UNQUOTED([ADDR2LINE], ["$ADDR2LINE"],
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-m4-Provide-default-value-fore-UDEVADM.patch b/SOURCES/libvirt-m4-Provide-default-value-fore-UDEVADM.patch
new file mode 100644
index 0000000..de7a3aa
--- /dev/null
+++ b/SOURCES/libvirt-m4-Provide-default-value-fore-UDEVADM.patch
@@ -0,0 +1,100 @@
+From 1113a43a48b3c15f908a396ec88e9499df10f7b4 Mon Sep 17 00:00:00 2001
+Message-Id: <1113a43a48b3c15f908a396ec88e9499df10f7b4@dist-git>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Thu, 27 Jun 2019 15:55:38 +0200
+Subject: [PATCH] m4: Provide default value fore UDEVADM
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+It may happen that the system where libvirt is built at doesn't
+have udevadm binary but the one where it runs does have it.
+If we change how udevadm is run in virWaitForDevices() then we
+can safely pass a default value in m4 macro.
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit 523b799d3c356b9b4ea0b117a60cfc3b603eaffa)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1710575
+
+Difference to the upstream commit is that I had to drop
+VIR_AUTOPTR() of virCommand because that does not exist in the
+downstream yet.
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Message-Id: <3d2deafb1bf06eddd721fceb15961b27c8dbf0cf.1561643698.git.mprivozn@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ m4/virt-external-programs.m4 |  9 +++------
+ src/util/virutil.c           | 16 ++++++++--------
+ 2 files changed, 11 insertions(+), 14 deletions(-)
+
+diff --git a/m4/virt-external-programs.m4 b/m4/virt-external-programs.m4
+index 3c915e1a65..f1ae104b32 100644
+--- a/m4/virt-external-programs.m4
++++ b/m4/virt-external-programs.m4
+@@ -45,7 +45,7 @@ AC_DEFUN([LIBVIRT_CHECK_EXTERNAL_PROGRAMS], [
+   AC_PATH_PROG([DNSMASQ], [dnsmasq], [dnsmasq], [$LIBVIRT_SBIN_PATH])
+   AC_PATH_PROG([RADVD], [radvd], [radvd], [$LIBVIRT_SBIN_PATH])
+   AC_PATH_PROG([TC], [tc], [tc], [$LIBVIRT_SBIN_PATH])
+-  AC_PATH_PROG([UDEVADM], [udevadm], [], [$LIBVIRT_SBIN_PATH])
++  AC_PATH_PROG([UDEVADM], [udevadm], [udevadm], [$LIBVIRT_SBIN_PATH])
+   AC_PATH_PROG([MODPROBE], [modprobe], [modprobe], [$LIBVIRT_SBIN_PATH])
+   AC_PATH_PROG([RMMOD], [rmmod], [rmmod], [$LIBVIRT_SBIN_PATH])
+   AC_PATH_PROG([MMCTL], [mm-ctl], [mm-ctl], [$LIBVIRT_SBIN_PATH])
+@@ -65,11 +65,8 @@ AC_DEFUN([LIBVIRT_CHECK_EXTERNAL_PROGRAMS], [
+                      [Location or name of the mm-ctl program])
+   AC_DEFINE_UNQUOTED([OVSVSCTL], ["$OVSVSCTL"],
+                      [Location or name of the ovs-vsctl program])
+-
+-  if test -n "$UDEVADM"; then
+-    AC_DEFINE_UNQUOTED([UDEVADM], ["$UDEVADM"],
+-                       [Location or name of the udevadm program])
+-  fi
++  AC_DEFINE_UNQUOTED([UDEVADM], ["$UDEVADM"],
++                     [Location or name of the udevadm program])
+   if test -n "$MODPROBE"; then
+     AC_DEFINE_UNQUOTED([MODPROBE], ["$MODPROBE"],
+                        [Location or name of the modprobe program])
+diff --git a/src/util/virutil.c b/src/util/virutil.c
+index 68d3217248..cd67f54bc2 100644
+--- a/src/util/virutil.c
++++ b/src/util/virutil.c
+@@ -1621,25 +1621,25 @@ virSetUIDGIDWithCaps(uid_t uid, gid_t gid, gid_t *groups, int ngroups,
+ #endif
+ 
+ 
+-#if defined(UDEVADM)
+ void virWaitForDevices(void)
+ {
+-    const char *const settleprog[] = { UDEVADM, "settle", NULL };
++    virCommandPtr cmd = NULL;
++    VIR_AUTOFREE(char *) udev = NULL;
+     int exitstatus;
+ 
+-    if (access(settleprog[0], X_OK) != 0)
++    if (!(udev = virFindFileInPath(UDEVADM)))
++        return;
++
++    if (!(cmd = virCommandNewArgList(udev, "settle", NULL)))
+         return;
+ 
+     /*
+      * NOTE: we ignore errors here; this is just to make sure that any device
+      * nodes that are being created finish before we try to scan them.
+      */
+-    ignore_value(virRun(settleprog, &exitstatus));
++    ignore_value(virCommandRun(cmd, &exitstatus));
++    virCommandFree(cmd);
+ }
+-#else
+-void virWaitForDevices(void)
+-{}
+-#endif
+ 
+ #if WITH_DEVMAPPER
+ bool
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-nwfilter-fix-adding-std-MAC-and-IP-values-to-filter-binding.patch b/SOURCES/libvirt-nwfilter-fix-adding-std-MAC-and-IP-values-to-filter-binding.patch
new file mode 100644
index 0000000..aa55e53
--- /dev/null
+++ b/SOURCES/libvirt-nwfilter-fix-adding-std-MAC-and-IP-values-to-filter-binding.patch
@@ -0,0 +1,164 @@
+From a8234641ad57553aa054bded71ed97c94f3100f1 Mon Sep 17 00:00:00 2001
+Message-Id: <a8234641ad57553aa054bded71ed97c94f3100f1@dist-git>
+From: Nikolay Shirokovskiy <nshirokovskiy@virtuozzo.com>
+Date: Wed, 5 Jun 2019 14:51:10 +0200
+Subject: [PATCH] nwfilter: fix adding std MAC and IP values to filter binding
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Commit d1a7c08eb changed filter instantiation code to ignore MAC and IP
+variables explicitly specified for filter binding. It just replaces
+explicit values with values associated with the binding. Before the
+commit virNWFilterCreateVarsFrom was used so that explicit value
+take precedence. Let's bring old behavior back.
+
+This is useful. For example if domain has two interfaces it makes
+sense to list both mac adresses in MAC var of every interface
+filterref. So that if guest make a bond of these interfaces
+and start sending frames with one of the mac adresses from
+both interfaces we can pass outgress traffic from both
+interfaces too.
+
+Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
+Signed-off-by: Nikolay Shirokovskiy <nshirokovskiy@virtuozzo.com>
+(cherry picked from commit 01e11ebcb6e8f24662b7c67b70134c192785691c)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1691356
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Acked-by: Daniel P. Berrangé <berrange@redhat.com>
+---
+ src/nwfilter/nwfilter_gentech_driver.c | 92 +++++++++-----------------
+ 1 file changed, 32 insertions(+), 60 deletions(-)
+
+diff --git a/src/nwfilter/nwfilter_gentech_driver.c b/src/nwfilter/nwfilter_gentech_driver.c
+index e5dea91f83..ece5d28f41 100644
+--- a/src/nwfilter/nwfilter_gentech_driver.c
++++ b/src/nwfilter/nwfilter_gentech_driver.c
+@@ -128,60 +128,6 @@ virNWFilterRuleInstFree(virNWFilterRuleInstPtr inst)
+ }
+ 
+ 
+-/**
+- * virNWFilterVarHashmapAddStdValues:
+- * @tables: pointer to hash tabel to add values to
+- * @macaddr: The string of the MAC address to add to the hash table,
+- *    may be NULL
+- * @ipaddr: The string of the IP address to add to the hash table;
+- *    may be NULL
+- *
+- * Returns 0 in case of success, -1 in case an error happened with
+- * error having been reported.
+- *
+- * Adds a couple of standard keys (MAC, IP) to the hash table.
+- */
+-static int
+-virNWFilterVarHashmapAddStdValues(virHashTablePtr table,
+-                                  const char *macaddr,
+-                                  const virNWFilterVarValue *ipaddr)
+-{
+-    virNWFilterVarValue *val;
+-
+-    if (macaddr) {
+-        val = virNWFilterVarValueCreateSimpleCopyValue(macaddr);
+-        if (!val)
+-            return -1;
+-
+-        if (virHashUpdateEntry(table,
+-                               NWFILTER_STD_VAR_MAC,
+-                               val) < 0) {
+-            virNWFilterVarValueFree(val);
+-            virReportError(VIR_ERR_INTERNAL_ERROR,
+-                           "%s", _("Could not add variable 'MAC' to hashmap"));
+-            return -1;
+-        }
+-    }
+-
+-    if (ipaddr) {
+-        val = virNWFilterVarValueCopy(ipaddr);
+-        if (!val)
+-            return -1;
+-
+-        if (virHashUpdateEntry(table,
+-                               NWFILTER_STD_VAR_IP,
+-                               val) < 0) {
+-            virNWFilterVarValueFree(val);
+-            virReportError(VIR_ERR_INTERNAL_ERROR,
+-                           "%s", _("Could not add variable 'IP' to hashmap"));
+-            return -1;
+-        }
+-    }
+-
+-    return 0;
+-}
+-
+-
+ /**
+  * Convert a virHashTable into a string of comma-separated
+  * variable names.
+@@ -707,6 +653,28 @@ virNWFilterDoInstantiate(virNWFilterTechDriverPtr techdriver,
+ }
+ 
+ 
++static int
++virNWFilterVarHashmapAddStdValue(virHashTablePtr table,
++                                 const char *var,
++                                 const char *value)
++{
++    virNWFilterVarValue *val;
++
++    if (virHashLookup(table, var))
++        return 0;
++
++    if (!(val = virNWFilterVarValueCreateSimpleCopyValue(value)))
++        return -1;
++
++    if (virHashAddEntry(table, var, val) < 0) {
++        virNWFilterVarValueFree(val);
++        return -1;
++    }
++
++    return 0;
++}
++
++
+ /*
+  * Call this function while holding the NWFilter filter update lock
+  */
+@@ -719,7 +687,7 @@ virNWFilterInstantiateFilterUpdate(virNWFilterDriverStatePtr driver,
+                                    bool forceWithPendingReq,
+                                    bool *foundNewFilter)
+ {
+-    int rc;
++    int rc = -1;
+     const char *drvname = EBIPTABLES_DRIVER_ID;
+     virNWFilterTechDriverPtr techdriver;
+     virNWFilterObjPtr obj;
+@@ -745,14 +713,18 @@ virNWFilterInstantiateFilterUpdate(virNWFilterDriverStatePtr driver,
+         return -1;
+ 
+     virMacAddrFormat(&binding->mac, vmmacaddr);
++    if (virNWFilterVarHashmapAddStdValue(binding->filterparams,
++                                         NWFILTER_STD_VAR_MAC,
++                                         vmmacaddr) < 0)
++        goto err_exit;
+ 
+     ipaddr = virNWFilterIPAddrMapGetIPAddr(binding->portdevname);
+-
+-    if (virNWFilterVarHashmapAddStdValues(binding->filterparams,
+-                                          vmmacaddr, ipaddr) < 0) {
+-        rc = -1;
++    if (ipaddr &&
++        virNWFilterVarHashmapAddStdValue(binding->filterparams,
++                                         NWFILTER_STD_VAR_IP,
++                                         virNWFilterVarValueGetSimple(ipaddr)) < 0)
+         goto err_exit;
+-    }
++
+ 
+     filter = virNWFilterObjGetDef(obj);
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-qemu-Add-APIs-for-translating-CPU-features.patch b/SOURCES/libvirt-qemu-Add-APIs-for-translating-CPU-features.patch
new file mode 100644
index 0000000..4879d4d
--- /dev/null
+++ b/SOURCES/libvirt-qemu-Add-APIs-for-translating-CPU-features.patch
@@ -0,0 +1,124 @@
+From cb2374042f3e998b90e6ea025dadfae9333b49cd Mon Sep 17 00:00:00 2001
+Message-Id: <cb2374042f3e998b90e6ea025dadfae9333b49cd@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:25:51 +0200
+Subject: [PATCH] qemu: Add APIs for translating CPU features
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+So far we always used libvirt's name of each CPU feature relying on
+backward compatible aliases in QEMU. The new translation table can be
+used whenever QEMU mandates or prefers canonical feature names.
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit 61ee757e2002507d711c195628619b9eff38b57a)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1697627
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <5b080656d143733a77780affc6dd0d322216d6e7.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/qemu/qemu_capabilities.c | 64 ++++++++++++++++++++++++++++++++++++
+ src/qemu/qemu_capabilities.h |  8 +++++
+ 2 files changed, 72 insertions(+)
+
+diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
+index 851cb73cfc..d2a2f7418a 100644
+--- a/src/qemu/qemu_capabilities.c
++++ b/src/qemu/qemu_capabilities.c
+@@ -2755,6 +2755,70 @@ virQEMUCapsCPUFilterFeatures(const char *name,
+ }
+ 
+ 
++typedef struct _virQEMUCapsCPUFeatureTranslationTable virQEMUCapsCPUFeatureTranslationTable;
++typedef virQEMUCapsCPUFeatureTranslationTable *virQEMUCapsCPUFeatureTranslationTablePtr;
++struct _virQEMUCapsCPUFeatureTranslationTable {
++    const char *libvirt;
++    const char *qemu;
++};
++
++virQEMUCapsCPUFeatureTranslationTable virQEMUCapsCPUFeaturesX86[] = {
++    {"cmp_legacy", "cmp-legacy"},
++    {"ds_cpl", "ds-cpl"},
++    {"fxsr_opt", "fxsr-opt"},
++    {"kvm_pv_eoi", "kvm-pv-eoi"},
++    {"kvm_pv_unhalt", "kvm-pv-unhalt"},
++    {"lahf_lm", "lahf-lm"},
++    {"nodeid_msr", "nodeid-msr"},
++    {"pclmuldq", "pclmulqdq"},
++    {"perfctr_core", "perfctr-core"},
++    {"perfctr_nb", "perfctr-nb"},
++    {"tsc_adjust", "tsc-adjust"},
++    {NULL, NULL}
++};
++
++
++static const char *
++virQEMUCapsCPUFeatureTranslate(virQEMUCapsPtr qemuCaps,
++                               const char *feature,
++                               bool reversed)
++{
++    virQEMUCapsCPUFeatureTranslationTablePtr table = NULL;
++    virQEMUCapsCPUFeatureTranslationTablePtr entry;
++
++    if (ARCH_IS_X86(qemuCaps->arch))
++        table = virQEMUCapsCPUFeaturesX86;
++
++    if (!table || !feature)
++        return feature;
++
++    for (entry = table; entry->libvirt; entry++) {
++        const char *key = reversed ? entry->qemu : entry->libvirt;
++
++        if (STREQ(feature, key))
++            return reversed ? entry->libvirt : entry->qemu;
++    }
++
++    return feature;
++}
++
++
++const char *
++virQEMUCapsCPUFeatureToQEMU(virQEMUCapsPtr qemuCaps,
++                            const char *feature)
++{
++    return virQEMUCapsCPUFeatureTranslate(qemuCaps, feature, false);
++}
++
++
++const char *
++virQEMUCapsCPUFeatureFromQEMU(virQEMUCapsPtr qemuCaps,
++                              const char *feature)
++{
++    return virQEMUCapsCPUFeatureTranslate(qemuCaps, feature, true);
++}
++
++
+ /**
+  * Returns  0 when host CPU model provided by QEMU was filled in qemuCaps,
+  *          1 when the caller should fall back to using virCapsPtr->host.cpu,
+diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
+index bea4767f3c..8a27acd8a4 100644
+--- a/src/qemu/qemu_capabilities.h
++++ b/src/qemu/qemu_capabilities.h
+@@ -628,6 +628,14 @@ bool virQEMUCapsGuestIsNative(virArch host,
+ bool virQEMUCapsCPUFilterFeatures(const char *name,
+                                   void *opaque);
+ 
++const char *
++virQEMUCapsCPUFeatureToQEMU(virQEMUCapsPtr qemuCaps,
++                            const char *feature);
++
++const char *
++virQEMUCapsCPUFeatureFromQEMU(virQEMUCapsPtr qemuCaps,
++                              const char *feature);
++
+ virSEVCapabilityPtr
+ virQEMUCapsGetSEVCapabilities(virQEMUCapsPtr qemuCaps);
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-qemu-Add-ccw-support-for-vhost-vsock.patch b/SOURCES/libvirt-qemu-Add-ccw-support-for-vhost-vsock.patch
new file mode 100644
index 0000000..169cc85
--- /dev/null
+++ b/SOURCES/libvirt-qemu-Add-ccw-support-for-vhost-vsock.patch
@@ -0,0 +1,343 @@
+From 31a61d20cc35f444b2b49deb146d667fb122668d Mon Sep 17 00:00:00 2001
+Message-Id: <31a61d20cc35f444b2b49deb146d667fb122668d@dist-git>
+From: Boris Fiuczynski <fiuczy@linux.ibm.com>
+Date: Wed, 17 Apr 2019 14:46:01 +0200
+Subject: [PATCH] qemu: Add ccw support for vhost-vsock
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Add support and tests for vhost-vsock-ccw.
+
+Signed-off-by: Boris Fiuczynski <fiuczy@linux.ibm.com>
+(cherry picked from commit 927ef9f2a6ba22213501e99dcf5ecb5f62f8f72d)
+Signed-off-by: Ján Tomko <jtomko@redhat.com>
+
+RHEL 8.1: https://bugzilla.redhat.com/show_bug.cgi?id=1698855
+Message-Id: <ec91ac8fd92152e31ce4af53b4d38725cff805a7.1555505143.git.jtomko@redhat.com>
+
+Reviewed-by: Andrea Bolognani <abologna@redhat.com>
+---
+ src/qemu/qemu_command.c                       |  8 +++--
+ src/qemu/qemu_domain.c                        | 10 ++++--
+ src/qemu/qemu_domain_address.c                |  7 +++-
+ .../vhost-vsock-ccw-auto.s390x-latest.args    | 32 +++++++++++++++++++
+ .../qemuxml2argvdata/vhost-vsock-ccw-auto.xml | 25 +++++++++++++++
+ .../vhost-vsock-ccw.s390x-latest.args         | 32 +++++++++++++++++++
+ tests/qemuxml2argvdata/vhost-vsock-ccw.xml    | 32 +++++++++++++++++++
+ tests/qemuxml2argvtest.c                      |  2 ++
+ .../vhost-vsock-ccw-auto.xml                  | 32 +++++++++++++++++++
+ tests/qemuxml2xmloutdata/vhost-vsock-ccw.xml  |  1 +
+ tests/qemuxml2xmltest.c                       |  5 +++
+ 11 files changed, 181 insertions(+), 5 deletions(-)
+ create mode 100644 tests/qemuxml2argvdata/vhost-vsock-ccw-auto.s390x-latest.args
+ create mode 100644 tests/qemuxml2argvdata/vhost-vsock-ccw-auto.xml
+ create mode 100644 tests/qemuxml2argvdata/vhost-vsock-ccw.s390x-latest.args
+ create mode 100644 tests/qemuxml2argvdata/vhost-vsock-ccw.xml
+ create mode 100644 tests/qemuxml2xmloutdata/vhost-vsock-ccw-auto.xml
+ create mode 120000 tests/qemuxml2xmloutdata/vhost-vsock-ccw.xml
+
+diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
+index 66abd3fe86..a8c832bad8 100644
+--- a/src/qemu/qemu_command.c
++++ b/src/qemu/qemu_command.c
+@@ -10219,10 +10219,14 @@ qemuBuildVsockDevStr(virDomainDefPtr def,
+ {
+     qemuDomainVsockPrivatePtr priv = (qemuDomainVsockPrivatePtr)vsock->privateData;
+     virBuffer buf = VIR_BUFFER_INITIALIZER;
+-    const char *device = "vhost-vsock-pci";
+     char *ret = NULL;
+ 
+-    virBufferAsprintf(&buf, "%s", device);
++    if (vsock->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW) {
++        virBufferAddLit(&buf, "vhost-vsock-ccw");
++    } else {
++        virBufferAddLit(&buf, "vhost-vsock-pci");
++    }
++
+     virBufferAsprintf(&buf, ",id=%s", vsock->info.alias);
+     virBufferAsprintf(&buf, ",guest-cid=%u", vsock->guest_cid);
+     virBufferAsprintf(&buf, ",vhostfd=%s%u", fdprefix, priv->vhostfd);
+diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
+index c530733e97..be3477bf8a 100644
+--- a/src/qemu/qemu_domain.c
++++ b/src/qemu/qemu_domain.c
+@@ -5559,7 +5559,8 @@ qemuDomainDeviceDefValidateMemory(const virDomainMemoryDef *memory ATTRIBUTE_UNU
+ 
+ 
+ static int
+-qemuDomainDeviceDefValidateVsock(const virDomainVsockDef *vsock ATTRIBUTE_UNUSED,
++qemuDomainDeviceDefValidateVsock(const virDomainVsockDef *vsock,
++                                 const virDomainDef *def,
+                                  virQEMUCapsPtr qemuCaps)
+ {
+     if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VHOST_VSOCK)) {
+@@ -5568,6 +5569,11 @@ qemuDomainDeviceDefValidateVsock(const virDomainVsockDef *vsock ATTRIBUTE_UNUSED
+                          "with this QEMU binary"));
+         return -1;
+     }
++
++    if (!qemuDomainCheckCCWS390AddressSupport(def, vsock->info, qemuCaps,
++                                              "vsock"))
++        return -1;
++
+     return 0;
+ }
+ 
+@@ -5715,7 +5721,7 @@ qemuDomainDeviceDefValidate(const virDomainDeviceDef *dev,
+         break;
+ 
+     case VIR_DOMAIN_DEVICE_VSOCK:
+-        ret = qemuDomainDeviceDefValidateVsock(dev->data.vsock, qemuCaps);
++        ret = qemuDomainDeviceDefValidateVsock(dev->data.vsock, def, qemuCaps);
+         break;
+ 
+     case VIR_DOMAIN_DEVICE_TPM:
+diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c
+index 3e50521c11..79d2b9f9c4 100644
+--- a/src/qemu/qemu_domain_address.c
++++ b/src/qemu/qemu_domain_address.c
+@@ -310,7 +310,8 @@ qemuDomainPrimeVirtioDeviceAddresses(virDomainDefPtr def,
+        declare address-less virtio devices to be of address type 'type'
+        disks, networks, videos, consoles, controllers, memballoon and rng
+        in this order
+-       if type is ccw filesystem devices are declared to be of address type ccw
++       if type is ccw filesystem and vsock devices are declared to be of
++       address type ccw
+     */
+     size_t i;
+ 
+@@ -377,6 +378,10 @@ qemuDomainPrimeVirtioDeviceAddresses(virDomainDefPtr def,
+             if (def->fss[i]->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
+                 def->fss[i]->info.type = type;
+         }
++        if (def->vsock &&
++            def->vsock->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
++            def->vsock->info.type = type;
++        }
+     }
+ }
+ 
+diff --git a/tests/qemuxml2argvdata/vhost-vsock-ccw-auto.s390x-latest.args b/tests/qemuxml2argvdata/vhost-vsock-ccw-auto.s390x-latest.args
+new file mode 100644
+index 0000000000..6092f8e85c
+--- /dev/null
++++ b/tests/qemuxml2argvdata/vhost-vsock-ccw-auto.s390x-latest.args
+@@ -0,0 +1,32 @@
++LC_ALL=C \
++PATH=/bin \
++HOME=/home/test \
++USER=test \
++LOGNAME=test \
++QEMU_AUDIO_DRV=none \
++/usr/bin/qemu-system-s390x \
++-name guest=QEMUGuest1,debug-threads=on \
++-S \
++-object secret,id=masterKey0,format=raw,\
++file=/tmp/lib/domain--1-QEMUGuest1/master-key.aes \
++-machine s390-ccw-virtio,accel=tcg,usb=off,dump-guest-core=off \
++-m 214 \
++-realtime mlock=off \
++-smp 1,sockets=1,cores=1,threads=1 \
++-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \
++-display none \
++-no-user-config \
++-nodefaults \
++-chardev socket,id=charmonitor,fd=1729,server,nowait \
++-mon chardev=charmonitor,id=monitor,mode=control \
++-rtc base=utc \
++-no-shutdown \
++-boot strict=on \
++-drive file=/dev/HostVG/QEMUGuest1,format=raw,if=none,id=drive-virtio-disk0 \
++-device virtio-blk-ccw,scsi=off,devno=fe.0.0000,drive=drive-virtio-disk0,\
++id=virtio-disk0,bootindex=1 \
++-device virtio-balloon-ccw,id=balloon0,devno=fe.0.0001 \
++-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,\
++resourcecontrol=deny \
++-device vhost-vsock-ccw,id=vsock0,guest-cid=42,vhostfd=6789,devno=fe.0.0002 \
++-msg timestamp=on
+diff --git a/tests/qemuxml2argvdata/vhost-vsock-ccw-auto.xml b/tests/qemuxml2argvdata/vhost-vsock-ccw-auto.xml
+new file mode 100644
+index 0000000000..e5b60765ab
+--- /dev/null
++++ b/tests/qemuxml2argvdata/vhost-vsock-ccw-auto.xml
+@@ -0,0 +1,25 @@
++<domain type='qemu'>
++  <name>QEMUGuest1</name>
++  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
++  <memory unit='KiB'>219136</memory>
++  <currentMemory unit='KiB'>219136</currentMemory>
++  <vcpu placement='static'>1</vcpu>
++  <os>
++    <type arch='s390x' machine='s390-ccw-virtio'>hvm</type>
++    <boot dev='hd'/>
++  </os>
++  <clock offset='utc'/>
++  <on_poweroff>destroy</on_poweroff>
++  <on_reboot>restart</on_reboot>
++  <on_crash>destroy</on_crash>
++  <devices>
++    <emulator>/usr/bin/qemu-system-s390x</emulator>
++    <disk type='block' device='disk'>
++      <source dev='/dev/HostVG/QEMUGuest1'/>
++      <target dev='hda' bus='virtio'/>
++    </disk>
++    <vsock>
++      <cid auto='yes'/>
++    </vsock>
++  </devices>
++</domain>
+diff --git a/tests/qemuxml2argvdata/vhost-vsock-ccw.s390x-latest.args b/tests/qemuxml2argvdata/vhost-vsock-ccw.s390x-latest.args
+new file mode 100644
+index 0000000000..93eb3f3430
+--- /dev/null
++++ b/tests/qemuxml2argvdata/vhost-vsock-ccw.s390x-latest.args
+@@ -0,0 +1,32 @@
++LC_ALL=C \
++PATH=/bin \
++HOME=/home/test \
++USER=test \
++LOGNAME=test \
++QEMU_AUDIO_DRV=none \
++/usr/bin/qemu-system-s390x \
++-name guest=QEMUGuest1,debug-threads=on \
++-S \
++-object secret,id=masterKey0,format=raw,\
++file=/tmp/lib/domain--1-QEMUGuest1/master-key.aes \
++-machine s390-ccw-virtio,accel=tcg,usb=off,dump-guest-core=off \
++-m 214 \
++-realtime mlock=off \
++-smp 1,sockets=1,cores=1,threads=1 \
++-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \
++-display none \
++-no-user-config \
++-nodefaults \
++-chardev socket,id=charmonitor,fd=1729,server,nowait \
++-mon chardev=charmonitor,id=monitor,mode=control \
++-rtc base=utc \
++-no-shutdown \
++-boot strict=on \
++-drive file=/dev/HostVG/QEMUGuest1,format=raw,if=none,id=drive-virtio-disk0 \
++-device virtio-blk-ccw,scsi=off,devno=fe.0.0000,drive=drive-virtio-disk0,\
++id=virtio-disk0,bootindex=1 \
++-device virtio-balloon-ccw,id=balloon0,devno=fe.0.0001 \
++-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,\
++resourcecontrol=deny \
++-device vhost-vsock-ccw,id=vsock0,guest-cid=4,vhostfd=6789,devno=fe.0.0003 \
++-msg timestamp=on
+diff --git a/tests/qemuxml2argvdata/vhost-vsock-ccw.xml b/tests/qemuxml2argvdata/vhost-vsock-ccw.xml
+new file mode 100644
+index 0000000000..083061c6cc
+--- /dev/null
++++ b/tests/qemuxml2argvdata/vhost-vsock-ccw.xml
+@@ -0,0 +1,32 @@
++<domain type='qemu'>
++  <name>QEMUGuest1</name>
++  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
++  <memory unit='KiB'>219136</memory>
++  <currentMemory unit='KiB'>219136</currentMemory>
++  <vcpu placement='static'>1</vcpu>
++  <os>
++    <type arch='s390x' machine='s390-ccw-virtio'>hvm</type>
++    <boot dev='hd'/>
++  </os>
++  <clock offset='utc'/>
++  <on_poweroff>destroy</on_poweroff>
++  <on_reboot>restart</on_reboot>
++  <on_crash>destroy</on_crash>
++  <devices>
++    <emulator>/usr/bin/qemu-system-s390x</emulator>
++    <disk type='block' device='disk'>
++      <driver name='qemu' type='raw'/>
++      <source dev='/dev/HostVG/QEMUGuest1'/>
++      <target dev='hda' bus='virtio'/>
++      <address type='ccw' cssid='0xfe' ssid='0x0' devno='0x0000'/>
++    </disk>
++    <memballoon model='virtio'>
++      <address type='ccw' cssid='0xfe' ssid='0x0' devno='0x0001'/>
++    </memballoon>
++    <panic model='s390'/>
++    <vsock model='virtio'>
++      <cid auto='no' address='4'/>
++      <address type='ccw' cssid='0xfe' ssid='0x0' devno='0x0003'/>
++    </vsock>
++  </devices>
++</domain>
+diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
+index abb256c913..7f25cccf9d 100644
+--- a/tests/qemuxml2argvtest.c
++++ b/tests/qemuxml2argvtest.c
+@@ -2972,6 +2972,8 @@ mymain(void)
+ 
+     DO_TEST_CAPS_LATEST("vhost-vsock");
+     DO_TEST_CAPS_LATEST("vhost-vsock-auto");
++    DO_TEST_CAPS_ARCH_LATEST("vhost-vsock-ccw", "s390x");
++    DO_TEST_CAPS_ARCH_LATEST("vhost-vsock-ccw-auto", "s390x");
+ 
+     DO_TEST_CAPS_VER("launch-security-sev", "2.12.0");
+ 
+diff --git a/tests/qemuxml2xmloutdata/vhost-vsock-ccw-auto.xml b/tests/qemuxml2xmloutdata/vhost-vsock-ccw-auto.xml
+new file mode 100644
+index 0000000000..38a0fb3808
+--- /dev/null
++++ b/tests/qemuxml2xmloutdata/vhost-vsock-ccw-auto.xml
+@@ -0,0 +1,32 @@
++<domain type='qemu'>
++  <name>QEMUGuest1</name>
++  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
++  <memory unit='KiB'>219136</memory>
++  <currentMemory unit='KiB'>219136</currentMemory>
++  <vcpu placement='static'>1</vcpu>
++  <os>
++    <type arch='s390x' machine='s390-ccw-virtio'>hvm</type>
++    <boot dev='hd'/>
++  </os>
++  <clock offset='utc'/>
++  <on_poweroff>destroy</on_poweroff>
++  <on_reboot>restart</on_reboot>
++  <on_crash>destroy</on_crash>
++  <devices>
++    <emulator>/usr/bin/qemu-system-s390x</emulator>
++    <disk type='block' device='disk'>
++      <driver name='qemu' type='raw'/>
++      <source dev='/dev/HostVG/QEMUGuest1'/>
++      <target dev='hda' bus='virtio'/>
++      <address type='ccw' cssid='0xfe' ssid='0x0' devno='0x0000'/>
++    </disk>
++    <memballoon model='virtio'>
++      <address type='ccw' cssid='0xfe' ssid='0x0' devno='0x0001'/>
++    </memballoon>
++    <panic model='s390'/>
++    <vsock model='virtio'>
++      <cid auto='yes'/>
++      <address type='ccw' cssid='0xfe' ssid='0x0' devno='0x0002'/>
++    </vsock>
++  </devices>
++</domain>
+diff --git a/tests/qemuxml2xmloutdata/vhost-vsock-ccw.xml b/tests/qemuxml2xmloutdata/vhost-vsock-ccw.xml
+new file mode 120000
+index 0000000000..e0fa69dba9
+--- /dev/null
++++ b/tests/qemuxml2xmloutdata/vhost-vsock-ccw.xml
+@@ -0,0 +1 @@
++../qemuxml2argvdata/vhost-vsock-ccw.xml
+\ No newline at end of file
+diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
+index dbac863239..2a2bf01ffa 100644
+--- a/tests/qemuxml2xmltest.c
++++ b/tests/qemuxml2xmltest.c
+@@ -1231,6 +1231,11 @@ mymain(void)
+ 
+     DO_TEST("vhost-vsock", QEMU_CAPS_DEVICE_VHOST_VSOCK);
+     DO_TEST("vhost-vsock-auto", QEMU_CAPS_DEVICE_VHOST_VSOCK);
++    DO_TEST("vhost-vsock-ccw", QEMU_CAPS_DEVICE_VHOST_VSOCK,
++            QEMU_CAPS_CCW);
++    DO_TEST("vhost-vsock-ccw-auto", QEMU_CAPS_DEVICE_VHOST_VSOCK,
++            QEMU_CAPS_CCW);
++
+ 
+     if (getenv("LIBVIRT_SKIP_CLEANUP") == NULL)
+         virFileDeleteTree(fakerootdir);
+-- 
+2.21.0
+
diff --git a/SOURCES/libvirt-qemu-Add-hotpluging-support-for-PCI-devices-on-S390-guests.patch b/SOURCES/libvirt-qemu-Add-hotpluging-support-for-PCI-devices-on-S390-guests.patch
new file mode 100644
index 0000000..23ac15d
--- /dev/null
+++ b/SOURCES/libvirt-qemu-Add-hotpluging-support-for-PCI-devices-on-S390-guests.patch
@@ -0,0 +1,316 @@
+From 84d44b33a64b6fd7f77d021249d23dc054243ddf Mon Sep 17 00:00:00 2001
+Message-Id: <84d44b33a64b6fd7f77d021249d23dc054243ddf@dist-git>
+From: Yi Min Zhao <zyimin@linux.ibm.com>
+Date: Mon, 8 Apr 2019 10:57:29 +0200
+Subject: [PATCH] qemu: Add hotpluging support for PCI devices on S390 guests
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This commit adds hotplug support for PCI devices on S390 guests.
+There's no need to implement hot unplug for zPCI as QEMU implements
+an unplug callback which will unplug both PCI and zPCI device in a
+cascaded way.
+Currently, the following PCI devices are supported:
+  virtio-blk-pci
+  virtio-net-pci
+  virtio-rng-pci
+  virtio-input-host-pci
+  virtio-keyboard-pci
+  virtio-mouse-pci
+  virtio-tablet-pci
+  vfio-pci
+  SCSIVhost device
+
+Signed-off-by: Yi Min Zhao <zyimin@linux.ibm.com>
+Reviewed-by: Boris Fiuczynski <fiuczy@linux.ibm.com>
+Reviewed-by: Stefan Zimmermann <stzi@linux.ibm.com>
+Reviewed-by: Bjoern Walk <bwalk@linux.ibm.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Reviewed-by: Andrea Bolognani <abologna@redhat.com>
+
+(cherry picked from commit 1d1e264f13d14ed05838bae2fcec2ffef26671f2)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1508149
+
+Conflicts:
+
+  * src/qemu/qemu_hotplug.c
+    + context
+      - missing 83fe11e950bc
+
+Signed-off-by: Andrea Bolognani <abologna@redhat.com>
+Message-Id: <20190408085732.28684-13-abologna@redhat.com>
+Reviewed-by: Laine Stump <laine@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/qemu/qemu_hotplug.c | 160 +++++++++++++++++++++++++++++++++++++---
+ 1 file changed, 151 insertions(+), 9 deletions(-)
+
+diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
+index 776cd75474..abe2632556 100644
+--- a/src/qemu/qemu_hotplug.c
++++ b/src/qemu/qemu_hotplug.c
+@@ -154,6 +154,80 @@ qemuHotplugPrepareDiskAccess(virQEMUDriverPtr driver,
+ }
+ 
+ 
++static int
++qemuDomainAttachZPCIDevice(qemuMonitorPtr mon,
++                           virDomainDeviceInfoPtr info)
++{
++    char *devstr_zpci = NULL;
++    int ret = -1;
++
++    if (!(devstr_zpci = qemuBuildZPCIDevStr(info)))
++        goto cleanup;
++
++    if (qemuMonitorAddDevice(mon, devstr_zpci) < 0)
++        goto cleanup;
++
++    ret = 0;
++
++ cleanup:
++    VIR_FREE(devstr_zpci);
++    return ret;
++}
++
++
++static int
++qemuDomainDetachZPCIDevice(qemuMonitorPtr mon,
++                           virDomainDeviceInfoPtr info)
++{
++    char *zpciAlias = NULL;
++    int ret = -1;
++
++    if (virAsprintf(&zpciAlias, "zpci%d", info->addr.pci.zpci.uid) < 0)
++        goto cleanup;
++
++    if (qemuMonitorDelDevice(mon, zpciAlias) < 0)
++        goto cleanup;
++
++    ret = 0;
++
++ cleanup:
++    VIR_FREE(zpciAlias);
++    return ret;
++}
++
++
++static int
++qemuDomainAttachExtensionDevice(qemuMonitorPtr mon,
++                                virDomainDeviceInfoPtr info)
++{
++    if (info->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI ||
++        info->addr.pci.extFlags == VIR_PCI_ADDRESS_EXTENSION_NONE) {
++        return 0;
++    }
++
++    if (info->addr.pci.extFlags & VIR_PCI_ADDRESS_EXTENSION_ZPCI)
++        return qemuDomainAttachZPCIDevice(mon, info);
++
++    return 0;
++}
++
++
++static int
++qemuDomainDetachExtensionDevice(qemuMonitorPtr mon,
++                                virDomainDeviceInfoPtr info)
++{
++    if (info->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI ||
++        info->addr.pci.extFlags == VIR_PCI_ADDRESS_EXTENSION_NONE) {
++        return 0;
++    }
++
++    if (info->addr.pci.extFlags & VIR_PCI_ADDRESS_EXTENSION_ZPCI)
++        return qemuDomainDetachZPCIDevice(mon, info);
++
++    return 0;
++}
++
++
+ static int
+ qemuHotplugWaitForTrayEject(virQEMUDriverPtr driver,
+                             virDomainObjPtr vm,
+@@ -403,9 +477,14 @@ qemuDomainAttachDiskGeneric(virQEMUDriverPtr driver,
+     if (qemuBlockStorageSourceAttachApply(priv->mon, data) < 0)
+         goto exit_monitor;
+ 
+-    if (qemuMonitorAddDevice(priv->mon, devstr) < 0)
++    if (qemuDomainAttachExtensionDevice(priv->mon, &disk->info) < 0)
+         goto exit_monitor;
+ 
++    if (qemuMonitorAddDevice(priv->mon, devstr) < 0) {
++        ignore_value(qemuDomainDetachExtensionDevice(priv->mon, &disk->info));
++        goto exit_monitor;
++    }
++
+     if (qemuDomainObjExitMonitor(driver, vm) < 0) {
+         ret = -2;
+         goto error;
+@@ -519,7 +598,16 @@ int qemuDomainAttachControllerDevice(virQEMUDriverPtr driver,
+         goto cleanup;
+ 
+     qemuDomainObjEnterMonitor(driver, vm);
+-    ret = qemuMonitorAddDevice(priv->mon, devstr);
++
++    if ((ret = qemuDomainAttachExtensionDevice(priv->mon,
++                                               &controller->info)) < 0) {
++        goto exit_monitor;
++    }
++
++    if ((ret = qemuMonitorAddDevice(priv->mon, devstr)) < 0)
++        ignore_value(qemuDomainDetachExtensionDevice(priv->mon, &controller->info));
++
++ exit_monitor:
+     if (qemuDomainObjExitMonitor(driver, vm) < 0) {
+         releaseaddr = false;
+         ret = -1;
+@@ -969,6 +1057,7 @@ qemuDomainAttachNetDevice(virQEMUDriverPtr driver,
+     }
+ 
+     if (qemuDomainIsS390CCW(vm->def) &&
++        net->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI &&
+         virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_CCW)) {
+         net->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW;
+         if (!(ccwaddrs = qemuDomainCCWAddrSetCreateFromDomain(vm->def)))
+@@ -1038,7 +1127,15 @@ qemuDomainAttachNetDevice(virQEMUDriverPtr driver,
+         goto try_remove;
+ 
+     qemuDomainObjEnterMonitor(driver, vm);
++
++    if (qemuDomainAttachExtensionDevice(priv->mon, &net->info) < 0) {
++        ignore_value(qemuDomainObjExitMonitor(driver, vm));
++        virDomainAuditNet(vm, NULL, net, "attach", false);
++        goto try_remove;
++    }
++
+     if (qemuMonitorAddDevice(priv->mon, nicstr) < 0) {
++        ignore_value(qemuDomainDetachExtensionDevice(priv->mon, &net->info));
+         ignore_value(qemuDomainObjExitMonitor(driver, vm));
+         virDomainAuditNet(vm, NULL, net, "attach", false);
+         goto try_remove;
+@@ -1256,8 +1353,16 @@ qemuDomainAttachHostPCIDevice(virQEMUDriverPtr driver,
+         goto error;
+ 
+     qemuDomainObjEnterMonitor(driver, vm);
+-    ret = qemuMonitorAddDeviceWithFd(priv->mon, devstr,
+-                                     configfd, configfd_name);
++
++    if ((ret = qemuDomainAttachExtensionDevice(priv->mon, hostdev->info)) < 0)
++        goto exit_monitor;
++
++    if ((ret = qemuMonitorAddDeviceWithFd(priv->mon, devstr,
++                                          configfd, configfd_name)) < 0) {
++        ignore_value(qemuDomainDetachExtensionDevice(priv->mon, hostdev->info));
++    }
++
++ exit_monitor:
+     if (qemuDomainObjExitMonitor(driver, vm) < 0)
+         goto error;
+ 
+@@ -1913,9 +2018,14 @@ qemuDomainAttachRNGDevice(virQEMUDriverPtr driver,
+     if (qemuMonitorAddObject(priv->mon, &props, &objAlias) < 0)
+         goto exit_monitor;
+ 
+-    if (qemuMonitorAddDevice(priv->mon, devstr) < 0)
++    if (qemuDomainAttachExtensionDevice(priv->mon, &rng->info) < 0)
+         goto exit_monitor;
+ 
++    if (qemuMonitorAddDevice(priv->mon, devstr) < 0) {
++        ignore_value(qemuDomainDetachExtensionDevice(priv->mon, &rng->info));
++        goto exit_monitor;
++    }
++
+     if (qemuDomainObjExitMonitor(driver, vm) < 0) {
+         releaseaddr = false;
+         goto cleanup;
+@@ -2407,8 +2517,16 @@ qemuDomainAttachSCSIVHostDevice(virQEMUDriverPtr driver,
+ 
+     qemuDomainObjEnterMonitor(driver, vm);
+ 
+-    ret = qemuMonitorAddDeviceWithFd(priv->mon, devstr, vhostfd, vhostfdName);
++    if ((ret = qemuDomainAttachExtensionDevice(priv->mon, hostdev->info)) < 0)
++        goto exit_monitor;
+ 
++    if ((ret = qemuMonitorAddDeviceWithFd(priv->mon, devstr, vhostfd,
++                                          vhostfdName)) < 0) {
++        ignore_value(qemuDomainDetachExtensionDevice(priv->mon, hostdev->info));
++        goto exit_monitor;
++    }
++
++ exit_monitor:
+     if (qemuDomainObjExitMonitor(driver, vm) < 0 || ret < 0)
+         goto audit;
+ 
+@@ -2653,9 +2771,14 @@ qemuDomainAttachShmemDevice(virQEMUDriverPtr driver,
+ 
+     release_backing = true;
+ 
+-    if (qemuMonitorAddDevice(priv->mon, shmstr) < 0)
++    if (qemuDomainAttachExtensionDevice(priv->mon, &shmem->info) < 0)
+         goto exit_monitor;
+ 
++    if (qemuMonitorAddDevice(priv->mon, shmstr) < 0) {
++        ignore_value(qemuDomainDetachExtensionDevice(priv->mon, &shmem->info));
++        goto exit_monitor;
++    }
++
+     if (qemuDomainObjExitMonitor(driver, vm) < 0) {
+         release_address = false;
+         goto cleanup;
+@@ -2827,9 +2950,15 @@ qemuDomainAttachInputDevice(virQEMUDriverPtr driver,
+         goto cleanup;
+ 
+     qemuDomainObjEnterMonitor(driver, vm);
+-    if (qemuMonitorAddDevice(priv->mon, devstr) < 0)
++
++    if (qemuDomainAttachExtensionDevice(priv->mon, &input->info) < 0)
+         goto exit_monitor;
+ 
++    if (qemuMonitorAddDevice(priv->mon, devstr) < 0) {
++        ignore_value(qemuDomainDetachExtensionDevice(priv->mon, &input->info));
++        goto exit_monitor;
++    }
++
+     if (qemuDomainObjExitMonitor(driver, vm) < 0) {
+         releaseaddr = false;
+         goto cleanup;
+@@ -2906,9 +3035,15 @@ qemuDomainAttachVsockDevice(virQEMUDriverPtr driver,
+         goto cleanup;
+ 
+     qemuDomainObjEnterMonitor(driver, vm);
+-    if (qemuMonitorAddDeviceWithFd(priv->mon, devstr, vsockPriv->vhostfd, fdname) < 0)
++
++    if (qemuDomainAttachExtensionDevice(priv->mon, &vsock->info) < 0)
+         goto exit_monitor;
+ 
++    if (qemuMonitorAddDeviceWithFd(priv->mon, devstr, vsockPriv->vhostfd, fdname) < 0) {
++        ignore_value(qemuDomainDetachExtensionDevice(priv->mon, &vsock->info));
++        goto exit_monitor;
++    }
++
+     if (qemuDomainObjExitMonitor(driver, vm) < 0) {
+         releaseaddr = false;
+         goto cleanup;
+@@ -4932,10 +5067,17 @@ int qemuDomainDetachControllerDevice(virQEMUDriverPtr driver,
+         qemuDomainMarkDeviceForRemoval(vm, &detach->info);
+ 
+     qemuDomainObjEnterMonitor(driver, vm);
++    if (detach->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI &&
++        qemuDomainDetachExtensionDevice(priv->mon, &detach->info)) {
++        goto exit_monitor;
++    }
++
+     if (qemuMonitorDelDevice(priv->mon, detach->info.alias)) {
+         ignore_value(qemuDomainObjExitMonitor(driver, vm));
+         goto cleanup;
+     }
++
++ exit_monitor:
+     if (qemuDomainObjExitMonitor(driver, vm) < 0)
+         goto cleanup;
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-qemu-Add-type-filter-to-qemuMonitorJSONParsePropsList.patch b/SOURCES/libvirt-qemu-Add-type-filter-to-qemuMonitorJSONParsePropsList.patch
new file mode 100644
index 0000000..abaeb89
--- /dev/null
+++ b/SOURCES/libvirt-qemu-Add-type-filter-to-qemuMonitorJSONParsePropsList.patch
@@ -0,0 +1,89 @@
+From 3004a0c300e65777cf888a49eddcfdda8cd59941 Mon Sep 17 00:00:00 2001
+Message-Id: <3004a0c300e65777cf888a49eddcfdda8cd59941@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:26:00 +0200
+Subject: [PATCH] qemu: Add type filter to qemuMonitorJSONParsePropsList
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The function converts a list of QOM properties into a NULL-terminated
+array of property names. The new type parameter may be used to limit the
+result to properties of a specific type.
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit 430023e5ee3f7549104f5eb09e3c26563a11882c)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1697627
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <aaae4013352ac5c6724550a340921c394a701bcc.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/qemu/qemu_monitor_json.c | 14 ++++++++++----
+ 1 file changed, 10 insertions(+), 4 deletions(-)
+
+diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
+index 8fead72ecf..abf952cd34 100644
+--- a/src/qemu/qemu_monitor_json.c
++++ b/src/qemu/qemu_monitor_json.c
+@@ -6067,11 +6067,13 @@ int qemuMonitorJSONSetObjectProperty(qemuMonitorPtr mon,
+ static int
+ qemuMonitorJSONParsePropsList(virJSONValuePtr cmd,
+                               virJSONValuePtr reply,
++                              const char *type,
+                               char ***props)
+ {
+     virJSONValuePtr data;
+     char **proplist = NULL;
+     size_t n = 0;
++    size_t count = 0;
+     size_t i;
+     int ret = -1;
+ 
+@@ -6089,17 +6091,21 @@ qemuMonitorJSONParsePropsList(virJSONValuePtr cmd,
+         virJSONValuePtr child = virJSONValueArrayGet(data, i);
+         const char *tmp;
+ 
++        if (type &&
++            STRNEQ_NULLABLE(virJSONValueObjectGetString(child, "type"), type))
++            continue;
++
+         if (!(tmp = virJSONValueObjectGetString(child, "name"))) {
+             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                            _("reply data was missing 'name'"));
+             goto cleanup;
+         }
+ 
+-        if (VIR_STRDUP(proplist[i], tmp) < 0)
++        if (VIR_STRDUP(proplist[count++], tmp) < 0)
+             goto cleanup;
+     }
+ 
+-    ret = n;
++    ret = count;
+     *props = proplist;
+     proplist = NULL;
+ 
+@@ -6132,7 +6138,7 @@ int qemuMonitorJSONGetDeviceProps(qemuMonitorPtr mon,
+         goto cleanup;
+     }
+ 
+-    ret = qemuMonitorJSONParsePropsList(cmd, reply, props);
++    ret = qemuMonitorJSONParsePropsList(cmd, reply, NULL, props);
+  cleanup:
+     virJSONValueFree(reply);
+     virJSONValueFree(cmd);
+@@ -6164,7 +6170,7 @@ qemuMonitorJSONGetObjectProps(qemuMonitorPtr mon,
+         goto cleanup;
+     }
+ 
+-    ret = qemuMonitorJSONParsePropsList(cmd, reply, props);
++    ret = qemuMonitorJSONParsePropsList(cmd, reply, NULL, props);
+  cleanup:
+     virJSONValueFree(reply);
+     virJSONValueFree(cmd);
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-qemu-Add-zPCI-address-definition-check.patch b/SOURCES/libvirt-qemu-Add-zPCI-address-definition-check.patch
new file mode 100644
index 0000000..b88cfa0
--- /dev/null
+++ b/SOURCES/libvirt-qemu-Add-zPCI-address-definition-check.patch
@@ -0,0 +1,156 @@
+From 9aef6ea4b1d8a79e353bb34ab5559c698cad1eb1 Mon Sep 17 00:00:00 2001
+Message-Id: <9aef6ea4b1d8a79e353bb34ab5559c698cad1eb1@dist-git>
+From: Yi Min Zhao <zyimin@linux.ibm.com>
+Date: Mon, 8 Apr 2019 10:57:26 +0200
+Subject: [PATCH] qemu: Add zPCI address definition check
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+We should ensure that QEMU supports zPCI when a zPCI address is defined
+in XML and otherwise report an error. This patch introduces a generic
+validation function qemuDomainDeviceDefValidateAddress() which calls
+qemuDomainDeviceDefValidateZPCIAddress() if address type is PCI address.
+
+Signed-off-by: Yi Min Zhao <zyimin@linux.ibm.com>
+Reviewed-by: Boris Fiuczynski <fiuczy@linux.ibm.com>
+Reviewed-by: Andrea Bolognani <abologna@redhat.com>
+
+(cherry picked from commit e6565d54db3d52ae38b5934877be4d004c2d5f35)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1508149
+
+Conflicts:
+
+  * src/qemu/qemu_domain.c
+    + context
+      - missing 709f57c25be8
+
+Signed-off-by: Andrea Bolognani <abologna@redhat.com>
+Message-Id: <20190408085732.28684-10-abologna@redhat.com>
+Reviewed-by: Laine Stump <laine@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/qemu/qemu_domain.c                        | 36 +++++++++++++++++++
+ .../hostdev-vfio-zpci-wrong-arch.xml          | 34 ++++++++++++++++++
+ tests/qemuxml2argvtest.c                      |  2 ++
+ 3 files changed, 72 insertions(+)
+ create mode 100644 tests/qemuxml2argvdata/hostdev-vfio-zpci-wrong-arch.xml
+
+diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
+index da961f0de9..8604385aa2 100644
+--- a/src/qemu/qemu_domain.c
++++ b/src/qemu/qemu_domain.c
+@@ -5681,6 +5681,38 @@ qemuDomainDeviceDefValidateGraphics(const virDomainGraphicsDef *graphics,
+ }
+ 
+ 
++static int
++qemuDomainDeviceDefValidateZPCIAddress(virDomainDeviceInfoPtr info,
++                                       virQEMUCapsPtr qemuCaps)
++{
++    if (!virZPCIDeviceAddressIsEmpty(&info->addr.pci.zpci) &&
++        !virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_ZPCI)) {
++        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
++                       "%s",
++                       _("This QEMU binary doesn't support zPCI"));
++        return -1;
++    }
++
++    return 0;
++}
++
++
++static int
++qemuDomainDeviceDefValidateAddress(const virDomainDeviceDef *dev,
++                                   virQEMUCapsPtr qemuCaps)
++{
++    virDomainDeviceInfoPtr info;
++
++    if (!(info = virDomainDeviceGetInfo((virDomainDeviceDef *)dev)))
++        return 0;
++
++    if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI)
++        return qemuDomainDeviceDefValidateZPCIAddress(info, qemuCaps);
++
++    return 0;
++}
++
++
+ static int
+ qemuDomainDeviceDefValidate(const virDomainDeviceDef *dev,
+                             const virDomainDef *def,
+@@ -5694,6 +5726,9 @@ qemuDomainDeviceDefValidate(const virDomainDeviceDef *dev,
+                                             def->emulator)))
+         return -1;
+ 
++    if ((ret = qemuDomainDeviceDefValidateAddress(dev, qemuCaps)) < 0)
++        goto cleanup;
++
+     switch ((virDomainDeviceType)dev->type) {
+     case VIR_DOMAIN_DEVICE_NET:
+         ret = qemuDomainDeviceDefValidateNetwork(dev->data.net);
+@@ -5769,6 +5804,7 @@ qemuDomainDeviceDefValidate(const virDomainDeviceDef *dev,
+         break;
+     }
+ 
++ cleanup:
+     virObjectUnref(qemuCaps);
+     return ret;
+ }
+diff --git a/tests/qemuxml2argvdata/hostdev-vfio-zpci-wrong-arch.xml b/tests/qemuxml2argvdata/hostdev-vfio-zpci-wrong-arch.xml
+new file mode 100644
+index 0000000000..bfb2f83a3b
+--- /dev/null
++++ b/tests/qemuxml2argvdata/hostdev-vfio-zpci-wrong-arch.xml
+@@ -0,0 +1,34 @@
++<domain type='qemu'>
++  <name>QEMUGuest2</name>
++  <uuid>c7a5fdbd-edaf-9466-926a-d65c16db1809</uuid>
++  <memory unit='KiB'>219100</memory>
++  <currentMemory unit='KiB'>219100</currentMemory>
++  <vcpu placement='static'>1</vcpu>
++  <os>
++    <type arch='i686' machine='pc'>hvm</type>
++    <boot dev='hd'/>
++  </os>
++  <clock offset='utc'/>
++  <on_poweroff>destroy</on_poweroff>
++  <on_reboot>restart</on_reboot>
++  <on_crash>destroy</on_crash>
++  <devices>
++    <emulator>/usr/bin/qemu-system-i686</emulator>
++    <disk type='block' device='disk'>
++      <source dev='/dev/HostVG/QEMUGuest2'/>
++      <target dev='hda' bus='ide'/>
++      <address type='drive' controller='0' bus='0' target='0' unit='0'/>
++    </disk>
++    <controller type='pci' index='0' model='pci-root'/>
++    <hostdev mode='subsystem' type='pci' managed='yes'>
++      <driver name='vfio'/>
++      <source>
++        <address domain='0x0001' bus='00' slot='00' function='0'/>
++      </source>
++      <address type='pci' domain='0x0000' bus='0x00' slot='0x08' function='0x0'>
++        <zpci uid='0x0019' fid='0x0000001f'/>
++      </address>
++    </hostdev>
++    <memballoon model='virtio'/>
++  </devices>
++</domain>
+diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
+index 2eb2505971..1066de8bc4 100644
+--- a/tests/qemuxml2argvtest.c
++++ b/tests/qemuxml2argvtest.c
+@@ -1632,6 +1632,8 @@ mymain(void)
+     DO_TEST_PARSE_ERROR("hostdev-mdev-display-missing-graphics",
+             QEMU_CAPS_DEVICE_VFIO_PCI,
+             QEMU_CAPS_VFIO_PCI_DISPLAY);
++    DO_TEST_PARSE_ERROR("hostdev-vfio-zpci-wrong-arch",
++                        QEMU_CAPS_DEVICE_VFIO_PCI);
+     DO_TEST("hostdev-vfio-zpci",
+             QEMU_CAPS_DEVICE_VFIO_PCI,
+             QEMU_CAPS_DEVICE_ZPCI);
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-qemu-Allow-creating-ppc64-guests-with-graphics-and-no-USB-mouse.patch b/SOURCES/libvirt-qemu-Allow-creating-ppc64-guests-with-graphics-and-no-USB-mouse.patch
new file mode 100644
index 0000000..7a6af43
--- /dev/null
+++ b/SOURCES/libvirt-qemu-Allow-creating-ppc64-guests-with-graphics-and-no-USB-mouse.patch
@@ -0,0 +1,76 @@
+From 1c58390619bfdd6174b1d24bc5b64caae45487b0 Mon Sep 17 00:00:00 2001
+Message-Id: <1c58390619bfdd6174b1d24bc5b64caae45487b0@dist-git>
+From: Andrea Bolognani <abologna@redhat.com>
+Date: Wed, 17 Apr 2019 11:21:25 +0200
+Subject: [PATCH] qemu: Allow creating ppc64 guests with graphics and no USB
+ mouse
+
+The existing behavior for ppc64 guests is to always add a USB
+keyboard and mouse combo if graphics are present; unfortunately,
+this means any attempt to use a USB tablet will cause both pointing
+devices to show up in the guest, which in turn will result in poor
+user experience.
+
+We can't just stop adding the USB mouse or start adding a USB tablet
+instead, because existing applications and users might rely on the
+current behavior; however, we can avoid adding the USB mouse if a USB
+tablet is already present, thus allowing users and applications to
+create guests that contain a single pointing device.
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1683681
+
+Signed-off-by: Andrea Bolognani <abologna@redhat.com>
+Reviewed-by: Cole Robinson <crobinso@redhat.com>
+
+(cherry picked from commit 186bb479d0f409dc75175bea48a760838c479a6c)
+
+Conflicts:
+  * src/qemu/qemu_domain.c
+    + context in qemuDomainDefAddDefaultDevices()
+      - missing 6427bfc8b3bb
+
+Deleted:
+  * tests/qemuxml2argvdata/ppc64-pseries-graphics.ppc64-latest.args
+    + doesn't exist downstream
+      - missing 4d7ea75e1e73
+
+Signed-off-by: Andrea Bolognani <abologna@redhat.com>
+Message-Id: <20190417092125.10277-2-abologna@redhat.com>
+---
+ src/qemu/qemu_domain.c | 20 ++++++++++++++++++++
+ 1 file changed, 20 insertions(+)
+
+diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
+index be3477bf8a..cc2a896a07 100644
+--- a/src/qemu/qemu_domain.c
++++ b/src/qemu/qemu_domain.c
+@@ -3323,6 +3323,26 @@ qemuDomainDefAddDefaultDevices(virDomainDefPtr def,
+         def->memballoon = memballoon;
+     }
+ 
++    if (addDefaultUSBMouse) {
++        bool hasUSBTablet = false;
++        size_t j;
++
++        for (j = 0; j < def->ninputs; j++) {
++            if (def->inputs[j]->type == VIR_DOMAIN_INPUT_TYPE_TABLET &&
++                def->inputs[j]->bus == VIR_DOMAIN_INPUT_BUS_USB) {
++                hasUSBTablet = true;
++                break;
++            }
++        }
++
++        /* Historically, we have automatically added USB keyboard and
++         * mouse to some guests. While the former device is generally
++         * safe to have, adding the latter is undesiderable if a USB
++         * tablet is already present in the guest */
++        if (hasUSBTablet)
++            addDefaultUSBMouse = false;
++    }
++
+     if (addDefaultUSBKBD &&
+         def->ngraphics > 0 &&
+         virDomainDefMaybeAddInput(def,
+-- 
+2.21.0
+
diff --git a/SOURCES/libvirt-qemu-Auto-add-pci-root-for-s390-s390x-guests.patch b/SOURCES/libvirt-qemu-Auto-add-pci-root-for-s390-s390x-guests.patch
new file mode 100644
index 0000000..98d484f
--- /dev/null
+++ b/SOURCES/libvirt-qemu-Auto-add-pci-root-for-s390-s390x-guests.patch
@@ -0,0 +1,46 @@
+From dc63c5044631d30981960d96568cd2abb3d31ede Mon Sep 17 00:00:00 2001
+Message-Id: <dc63c5044631d30981960d96568cd2abb3d31ede@dist-git>
+From: Yi Min Zhao <zyimin@linux.ibm.com>
+Date: Mon, 8 Apr 2019 10:57:23 +0200
+Subject: [PATCH] qemu: Auto add pci-root for s390/s390x guests
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The pci-root depends on zpci capability. So autogenerate pci-root if
+zpci exists.
+
+Signed-off-by: Yi Min Zhao <zyimin@linux.ibm.com>
+Reviewed-by: Boris Fiuczynski <fiuczy@linux.ibm.com>
+Reviewed-by: Stefan Zimmermann <stzi@linux.ibm.com>
+Reviewed-by: Bjoern Walk <bwalk@linux.ibm.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Reviewed-by: Andrea Bolognani <abologna@redhat.com>
+
+(cherry picked from commit d46673913802b65dd7d33562cce41a78cbc85a88)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1508149
+
+Signed-off-by: Andrea Bolognani <abologna@redhat.com>
+Message-Id: <20190408085732.28684-7-abologna@redhat.com>
+Reviewed-by: Laine Stump <laine@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/qemu/qemu_domain.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
+index 21f0722495..da961f0de9 100644
+--- a/src/qemu/qemu_domain.c
++++ b/src/qemu/qemu_domain.c
+@@ -3228,6 +3228,7 @@ qemuDomainDefAddDefaultDevices(virDomainDefPtr def,
+     case VIR_ARCH_S390X:
+         addDefaultUSB = false;
+         addPanicDevice = true;
++        addPCIRoot = virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_ZPCI);
+         break;
+ 
+     case VIR_ARCH_SPARC:
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-qemu-Don-t-cache-microcode-version.patch b/SOURCES/libvirt-qemu-Don-t-cache-microcode-version.patch
index 9ca5d90..25c6132 100644
--- a/SOURCES/libvirt-qemu-Don-t-cache-microcode-version.patch
+++ b/SOURCES/libvirt-qemu-Don-t-cache-microcode-version.patch
@@ -1,5 +1,5 @@
-From b41057952aa267335c7e00380e77952a8b65086a Mon Sep 17 00:00:00 2001
-Message-Id: <b41057952aa267335c7e00380e77952a8b65086a@dist-git>
+From 6832d9d8dd0963f4865801a29e848ff3256b3282 Mon Sep 17 00:00:00 2001
+Message-Id: <6832d9d8dd0963f4865801a29e848ff3256b3282@dist-git>
 From: Jiri Denemark <jdenemar@redhat.com>
 Date: Fri, 12 Apr 2019 21:21:05 +0200
 Subject: [PATCH] qemu: Don't cache microcode version
@@ -20,7 +20,7 @@ Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
 Reviewed-by: Ján Tomko <jtomko@redhat.com>
 (cherry picked from commit 673c62a3b7855a0685d8f116e227c402720b9ee9)
 
-CVE-2018-11091, CVE-2018-12126, CVE-2018-12127, CVE-2018-12130
+CVE-2018-12126, CVE-2018-12127, CVE-2018-12130, CVE-2019-11091
 
 Conflicts:
 	src/qemu/qemu_capabilities.c
diff --git a/SOURCES/libvirt-qemu-Don-t-use-full-CPU-model-expansion.patch b/SOURCES/libvirt-qemu-Don-t-use-full-CPU-model-expansion.patch
new file mode 100644
index 0000000..e5dd84a
--- /dev/null
+++ b/SOURCES/libvirt-qemu-Don-t-use-full-CPU-model-expansion.patch
@@ -0,0 +1,2643 @@
+From a70b774016d7fa23e415e3c166a6549f257a2339 Mon Sep 17 00:00:00 2001
+Message-Id: <a70b774016d7fa23e415e3c166a6549f257a2339@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:25:57 +0200
+Subject: [PATCH] qemu: Don't use full CPU model expansion
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+We used type=full expansion on the result of previous type=static
+expansion to get all possible spellings of CPU features. Since we can
+now translate the QEMU's canonical names to our names, we can drop this
+magic and do only type=static CPU model expansion.
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit a3f2c802d240b6183b037ef4a1ca53b5de440800)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1697627
+
+Conflicts:
+	tests/qemucapabilitiesdata/caps_4.1.0.x86_64.xml
+            - file size based microcode version
+
+	tests/qemucapabilitiesdata/caps_4.1.0.x86_64.replies
+            - QMP message IDs are different
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <27ac93d749ca253f4a45481c656e085be874caa9.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/qemu/qemu_capabilities.c                  |    9 +-
+ .../caps_4.1.0.x86_64.replies                 | 1964 +----------------
+ .../caps_4.1.0.x86_64.xml                     |  228 +-
+ 3 files changed, 49 insertions(+), 2152 deletions(-)
+
+diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
+index 88c651ea7b..78be2d35f4 100644
+--- a/src/qemu/qemu_capabilities.c
++++ b/src/qemu/qemu_capabilities.c
+@@ -2421,10 +2421,13 @@ virQEMUCapsProbeQMPHostCPU(virQEMUCapsPtr qemuCaps,
+ 
+     /* Some x86_64 features defined in cpu_map.xml use spelling which differ
+      * from the one preferred by QEMU. Static expansion would give us only the
+-     * preferred spelling, thus we need to do a full expansion on the result of
+-     * the initial static expansion to get all variants of all features.
++     * preferred spelling. With new QEMU we always use the QEMU's canonical
++     * names of all features and translate between them and our names. But for
++     * older version of QEMU we need to do a full expansion on the result of
++     * the initial static expansion to get all variants of feature names.
+      */
+-    if (ARCH_IS_X86(qemuCaps->arch))
++    if (ARCH_IS_X86(qemuCaps->arch) &&
++        !virQEMUCapsGet(qemuCaps, QEMU_CAPS_CANONICAL_CPU_FEATURES))
+         type = QEMU_MONITOR_CPU_MODEL_EXPANSION_STATIC_FULL;
+     else
+         type = QEMU_MONITOR_CPU_MODEL_EXPANSION_STATIC;
+diff --git a/tests/qemucapabilitiesdata/caps_4.1.0.x86_64.replies b/tests/qemucapabilitiesdata/caps_4.1.0.x86_64.replies
+index 5b4d7a8484..300785b8bc 100644
+--- a/tests/qemucapabilitiesdata/caps_4.1.0.x86_64.replies
++++ b/tests/qemucapabilitiesdata/caps_4.1.0.x86_64.replies
+@@ -21545,495 +21545,6 @@
+   "id": "libvirt-52"
+ }
+ 
+-{
+-  "execute": "query-cpu-model-expansion",
+-  "arguments": {
+-    "type": "full",
+-    "model": {
+-      "name": "base",
+-      "props": {
+-        "cmov": true,
+-        "ia64": false,
+-        "ssb-no": false,
+-        "aes": true,
+-        "mmx": true,
+-        "rdpid": false,
+-        "arat": true,
+-        "gfni": false,
+-        "ibrs-all": false,
+-        "pause-filter": false,
+-        "xsavec": true,
+-        "intel-pt": false,
+-        "kvm-asyncpf": true,
+-        "perfctr-core": false,
+-        "mpx": true,
+-        "pbe": false,
+-        "avx512cd": false,
+-        "decodeassists": false,
+-        "sse4.1": true,
+-        "family": 6,
+-        "wbnoinvd": false,
+-        "avx512f": false,
+-        "msr": true,
+-        "mce": true,
+-        "mca": true,
+-        "xcrypt": false,
+-        "min-level": 13,
+-        "xgetbv1": true,
+-        "cid": false,
+-        "ds": false,
+-        "fxsr": true,
+-        "xsaveopt": true,
+-        "xtpr": false,
+-        "avx512vl": false,
+-        "avx512-vpopcntdq": false,
+-        "phe": false,
+-        "extapic": false,
+-        "3dnowprefetch": true,
+-        "avx512vbmi2": false,
+-        "cr8legacy": false,
+-        "stibp": false,
+-        "xcrypt-en": false,
+-        "pn": false,
+-        "rsba": false,
+-        "dca": false,
+-        "vendor": "GenuineIntel",
+-        "pku": false,
+-        "smx": false,
+-        "cmp-legacy": false,
+-        "avx512-4fmaps": false,
+-        "vmcb-clean": false,
+-        "hle": true,
+-        "3dnowext": false,
+-        "amd-no-ssb": false,
+-        "npt": false,
+-        "rdctl-no": false,
+-        "clwb": false,
+-        "lbrv": false,
+-        "adx": true,
+-        "ss": true,
+-        "pni": true,
+-        "svm-lock": false,
+-        "smep": true,
+-        "smap": true,
+-        "pfthreshold": false,
+-        "x2apic": true,
+-        "avx512vbmi": false,
+-        "avx512vnni": false,
+-        "flushbyasid": false,
+-        "f16c": true,
+-        "ace2-en": false,
+-        "pae": true,
+-        "pat": true,
+-        "sse": true,
+-        "phe-en": false,
+-        "kvm-nopiodelay": true,
+-        "tm": false,
+-        "kvmclock-stable-bit": true,
+-        "hypervisor": true,
+-        "mds-no": false,
+-        "pcommit": false,
+-        "syscall": true,
+-        "avx512dq": false,
+-        "svm": false,
+-        "invtsc": false,
+-        "sse2": true,
+-        "ssbd": false,
+-        "est": false,
+-        "avx512ifma": false,
+-        "tm2": false,
+-        "kvm-pv-eoi": true,
+-        "kvm-pv-ipi": true,
+-        "cx8": true,
+-        "cldemote": false,
+-        "kvm-mmu": false,
+-        "sse4.2": true,
+-        "pge": true,
+-        "avx512bitalg": false,
+-        "pdcm": false,
+-        "model": 94,
+-        "movbe": true,
+-        "nrip-save": false,
+-        "ssse3": true,
+-        "sse4a": false,
+-        "invpcid": true,
+-        "pdpe1gb": true,
+-        "tsc-deadline": true,
+-        "skip-l1dfl-vmentry": true,
+-        "fma": true,
+-        "cx16": true,
+-        "de": true,
+-        "stepping": 3,
+-        "xsave": true,
+-        "clflush": true,
+-        "skinit": false,
+-        "tsc": true,
+-        "tce": false,
+-        "fpu": true,
+-        "ds-cpl": false,
+-        "ibs": false,
+-        "fma4": false,
+-        "la57": false,
+-        "osvw": false,
+-        "apic": true,
+-        "pmm": false,
+-        "spec-ctrl": false,
+-        "tsc-adjust": true,
+-        "kvm-steal-time": true,
+-        "kvmclock": true,
+-        "lwp": false,
+-        "amd-ssbd": false,
+-        "xop": false,
+-        "ibpb": false,
+-        "avx": true,
+-        "movdiri": false,
+-        "acpi": false,
+-        "avx512bw": false,
+-        "ace2": false,
+-        "fsgsbase": true,
+-        "ht": false,
+-        "nx": true,
+-        "pclmulqdq": true,
+-        "mmxext": false,
+-        "popcnt": true,
+-        "vaes": false,
+-        "movdir64b": false,
+-        "xsaves": true,
+-        "lm": true,
+-        "umip": true,
+-        "pse": true,
+-        "avx2": true,
+-        "sep": true,
+-        "virt-ssbd": false,
+-        "nodeid-msr": false,
+-        "md-clear": false,
+-        "misalignsse": false,
+-        "min-xlevel": 2147483656,
+-        "bmi1": true,
+-        "bmi2": true,
+-        "kvm-pv-unhalt": true,
+-        "tsc-scale": false,
+-        "topoext": false,
+-        "clflushopt": true,
+-        "monitor": false,
+-        "avx512er": false,
+-        "pmm-en": false,
+-        "pcid": true,
+-        "arch-capabilities": true,
+-        "3dnow": false,
+-        "erms": true,
+-        "lahf-lm": true,
+-        "vpclmulqdq": false,
+-        "fxsr-opt": false,
+-        "xstore": false,
+-        "rtm": true,
+-        "kvm-hint-dedicated": false,
+-        "lmce": true,
+-        "perfctr-nb": false,
+-        "rdrand": true,
+-        "rdseed": true,
+-        "avx512-4vnniw": false,
+-        "vme": true,
+-        "vmx": true,
+-        "dtes64": false,
+-        "mtrr": true,
+-        "rdtscp": true,
+-        "pse36": true,
+-        "kvm-pv-tlb-flush": true,
+-        "tbm": false,
+-        "wdt": false,
+-        "model-id": "Intel(R) Xeon(R) CPU E3-1245 v5 @ 3.50GHz",
+-        "sha-ni": false,
+-        "abm": true,
+-        "avx512pf": false,
+-        "xstore-en": false
+-      }
+-    }
+-  },
+-  "id": "libvirt-53"
+-}
+-
+-{
+-  "return": {
+-    "model": {
+-      "name": "base",
+-      "props": {
+-        "phys-bits": 0,
+-        "core-id": -1,
+-        "xlevel": 2147483656,
+-        "cmov": true,
+-        "ia64": false,
+-        "ssb-no": false,
+-        "aes": true,
+-        "mmx": true,
+-        "rdpid": false,
+-        "arat": true,
+-        "gfni": false,
+-        "ibrs-all": false,
+-        "pause-filter": false,
+-        "xsavec": true,
+-        "intel-pt": false,
+-        "hv-frequencies": false,
+-        "tsc-frequency": 0,
+-        "xd": true,
+-        "x-intel-pt-auto-level": true,
+-        "hv-vendor-id": "",
+-        "kvm-asyncpf": true,
+-        "kvm_asyncpf": true,
+-        "perfctr_core": false,
+-        "perfctr-core": false,
+-        "mpx": true,
+-        "pbe": false,
+-        "decodeassists": false,
+-        "avx512cd": false,
+-        "sse4_1": true,
+-        "sse4.1": true,
+-        "sse4-1": true,
+-        "family": 6,
+-        "legacy-cache": true,
+-        "host-phys-bits-limit": 0,
+-        "vmware-cpuid-freq": true,
+-        "wbnoinvd": false,
+-        "avx512f": false,
+-        "msr": true,
+-        "mce": true,
+-        "mca": true,
+-        "hv-runtime": false,
+-        "xcrypt": false,
+-        "thread-id": -1,
+-        "min-level": 13,
+-        "xgetbv1": true,
+-        "cid": false,
+-        "hv-relaxed": false,
+-        "hv-crash": false,
+-        "ds": false,
+-        "fxsr": true,
+-        "xsaveopt": true,
+-        "xtpr": false,
+-        "hv-evmcs": false,
+-        "avx512vl": false,
+-        "avx512-vpopcntdq": false,
+-        "phe": false,
+-        "extapic": false,
+-        "3dnowprefetch": true,
+-        "avx512vbmi2": false,
+-        "cr8legacy": false,
+-        "stibp": false,
+-        "cpuid-0xb": true,
+-        "xcrypt-en": false,
+-        "kvm_pv_eoi": true,
+-        "apic-id": 4294967295,
+-        "rsba": false,
+-        "pn": false,
+-        "dca": false,
+-        "vendor": "GenuineIntel",
+-        "hv-ipi": false,
+-        "pku": false,
+-        "smx": false,
+-        "cmp_legacy": false,
+-        "cmp-legacy": false,
+-        "node-id": -1,
+-        "avx512-4fmaps": false,
+-        "vmcb_clean": false,
+-        "vmcb-clean": false,
+-        "3dnowext": false,
+-        "amd-no-ssb": false,
+-        "hle": true,
+-        "npt": false,
+-        "rdctl-no": false,
+-        "memory": "/machine/unattached/system[0]",
+-        "clwb": false,
+-        "lbrv": false,
+-        "adx": true,
+-        "ss": true,
+-        "pni": true,
+-        "svm_lock": false,
+-        "svm-lock": false,
+-        "pfthreshold": false,
+-        "smep": true,
+-        "smap": true,
+-        "x2apic": true,
+-        "avx512vbmi": false,
+-        "avx512vnni": false,
+-        "hv-stimer": false,
+-        "x-hv-synic-kvm-only": false,
+-        "i64": true,
+-        "flushbyasid": false,
+-        "f16c": true,
+-        "ace2-en": false,
+-        "pat": true,
+-        "pae": true,
+-        "sse": true,
+-        "phe-en": false,
+-        "kvm_nopiodelay": true,
+-        "kvm-nopiodelay": true,
+-        "tm": false,
+-        "kvmclock-stable-bit": true,
+-        "hypervisor": true,
+-        "socket-id": -1,
+-        "mds-no": false,
+-        "pcommit": false,
+-        "syscall": true,
+-        "level": 13,
+-        "avx512dq": false,
+-        "x-migrate-smi-count": true,
+-        "svm": false,
+-        "full-cpuid-auto-level": true,
+-        "hv-reset": false,
+-        "invtsc": false,
+-        "sse3": true,
+-        "sse2": true,
+-        "ssbd": false,
+-        "est": false,
+-        "avx512ifma": false,
+-        "tm2": false,
+-        "kvm-pv-ipi": true,
+-        "kvm-pv-eoi": true,
+-        "cx8": true,
+-        "cldemote": false,
+-        "hv-reenlightenment": false,
+-        "kvm_mmu": false,
+-        "kvm-mmu": false,
+-        "sse4_2": true,
+-        "sse4.2": true,
+-        "sse4-2": true,
+-        "pge": true,
+-        "fill-mtrr-mask": true,
+-        "avx512bitalg": false,
+-        "nodeid_msr": false,
+-        "pdcm": false,
+-        "movbe": true,
+-        "model": 94,
+-        "nrip_save": false,
+-        "nrip-save": false,
+-        "kvm_pv_unhalt": true,
+-        "ssse3": true,
+-        "sse4a": false,
+-        "invpcid": true,
+-        "pdpe1gb": true,
+-        "tsc-deadline": true,
+-        "skip-l1dfl-vmentry": true,
+-        "fma": true,
+-        "cx16": true,
+-        "de": true,
+-        "enforce": false,
+-        "stepping": 3,
+-        "xsave": true,
+-        "clflush": true,
+-        "skinit": false,
+-        "tsc": true,
+-        "tce": false,
+-        "fpu": true,
+-        "ibs": false,
+-        "ds_cpl": false,
+-        "ds-cpl": false,
+-        "host-phys-bits": false,
+-        "fma4": false,
+-        "la57": false,
+-        "osvw": false,
+-        "check": true,
+-        "hv-spinlocks": -1,
+-        "pmm": false,
+-        "pmu": false,
+-        "apic": true,
+-        "spec-ctrl": false,
+-        "min-xlevel2": 0,
+-        "tsc-adjust": true,
+-        "tsc_adjust": true,
+-        "kvm-steal-time": true,
+-        "kvm_steal_time": true,
+-        "kvmclock": true,
+-        "l3-cache": true,
+-        "lwp": false,
+-        "amd-ssbd": false,
+-        "ibpb": false,
+-        "xop": false,
+-        "avx": true,
+-        "movdiri": false,
+-        "ace2": false,
+-        "avx512bw": false,
+-        "acpi": false,
+-        "hv-vapic": false,
+-        "fsgsbase": true,
+-        "ht": false,
+-        "nx": true,
+-        "pclmulqdq": true,
+-        "mmxext": false,
+-        "vaes": false,
+-        "popcnt": true,
+-        "xsaves": true,
+-        "movdir64b": false,
+-        "tcg-cpuid": true,
+-        "lm": true,
+-        "umip": true,
+-        "pse": true,
+-        "avx2": true,
+-        "sep": true,
+-        "pclmuldq": true,
+-        "virt-ssbd": false,
+-        "x-hv-max-vps": -1,
+-        "nodeid-msr": false,
+-        "md-clear": false,
+-        "kvm": true,
+-        "misalignsse": false,
+-        "min-xlevel": 2147483656,
+-        "kvm-pv-unhalt": true,
+-        "bmi2": true,
+-        "bmi1": true,
+-        "realized": false,
+-        "tsc_scale": false,
+-        "tsc-scale": false,
+-        "topoext": false,
+-        "hv-vpindex": false,
+-        "xlevel2": 0,
+-        "clflushopt": true,
+-        "kvm-no-smi-migration": false,
+-        "monitor": false,
+-        "avx512er": false,
+-        "pmm-en": false,
+-        "pcid": true,
+-        "arch-capabilities": true,
+-        "3dnow": false,
+-        "erms": true,
+-        "lahf-lm": true,
+-        "lahf_lm": true,
+-        "vpclmulqdq": false,
+-        "fxsr-opt": false,
+-        "hv-synic": false,
+-        "xstore": false,
+-        "fxsr_opt": false,
+-        "kvm-hint-dedicated": false,
+-        "rtm": true,
+-        "lmce": true,
+-        "hv-time": false,
+-        "perfctr-nb": false,
+-        "perfctr_nb": false,
+-        "ffxsr": false,
+-        "hv-tlbflush": false,
+-        "rdrand": true,
+-        "rdseed": true,
+-        "avx512-4vnniw": false,
+-        "vmx": true,
+-        "vme": true,
+-        "dtes64": false,
+-        "mtrr": true,
+-        "rdtscp": true,
+-        "pse36": true,
+-        "kvm-pv-tlb-flush": true,
+-        "tbm": false,
+-        "wdt": false,
+-        "pause_filter": false,
+-        "sha-ni": false,
+-        "model-id": "Intel(R) Xeon(R) CPU E3-1245 v5 @ 3.50GHz",
+-        "abm": true,
+-        "avx512pf": false,
+-        "xstore-en": false
+-      }
+-    }
+-  },
+-  "id": "libvirt-53"
+-}
+-
+ {
+   "execute": "query-cpu-model-expansion",
+   "arguments": {
+@@ -22045,7 +21556,7 @@
+       }
+     }
+   },
+-  "id": "libvirt-54"
++  "id": "libvirt-53"
+ }
+ 
+ {
+@@ -22251,496 +21762,7 @@
+       }
+     }
+   },
+-  "id": "libvirt-54"
+-}
+-
+-{
+-  "execute": "query-cpu-model-expansion",
+-  "arguments": {
+-    "type": "full",
+-    "model": {
+-      "name": "base",
+-      "props": {
+-        "cmov": true,
+-        "ia64": false,
+-        "ssb-no": false,
+-        "aes": true,
+-        "mmx": true,
+-        "rdpid": false,
+-        "arat": true,
+-        "gfni": false,
+-        "ibrs-all": false,
+-        "pause-filter": false,
+-        "xsavec": true,
+-        "intel-pt": false,
+-        "kvm-asyncpf": true,
+-        "perfctr-core": false,
+-        "mpx": true,
+-        "pbe": false,
+-        "avx512cd": false,
+-        "decodeassists": false,
+-        "sse4.1": true,
+-        "family": 6,
+-        "wbnoinvd": false,
+-        "avx512f": false,
+-        "msr": true,
+-        "mce": true,
+-        "mca": true,
+-        "xcrypt": false,
+-        "min-level": 13,
+-        "xgetbv1": true,
+-        "cid": false,
+-        "ds": false,
+-        "fxsr": true,
+-        "xsaveopt": true,
+-        "xtpr": false,
+-        "avx512vl": false,
+-        "avx512-vpopcntdq": false,
+-        "phe": false,
+-        "extapic": false,
+-        "3dnowprefetch": true,
+-        "avx512vbmi2": false,
+-        "cr8legacy": false,
+-        "stibp": false,
+-        "xcrypt-en": false,
+-        "pn": false,
+-        "rsba": false,
+-        "dca": false,
+-        "vendor": "GenuineIntel",
+-        "pku": false,
+-        "smx": false,
+-        "cmp-legacy": false,
+-        "avx512-4fmaps": false,
+-        "vmcb-clean": false,
+-        "hle": true,
+-        "3dnowext": false,
+-        "amd-no-ssb": false,
+-        "npt": false,
+-        "rdctl-no": false,
+-        "clwb": false,
+-        "lbrv": false,
+-        "adx": true,
+-        "ss": true,
+-        "pni": true,
+-        "svm-lock": false,
+-        "smep": true,
+-        "smap": true,
+-        "pfthreshold": false,
+-        "x2apic": true,
+-        "avx512vbmi": false,
+-        "avx512vnni": false,
+-        "flushbyasid": false,
+-        "f16c": true,
+-        "ace2-en": false,
+-        "pae": true,
+-        "pat": true,
+-        "sse": true,
+-        "phe-en": false,
+-        "kvm-nopiodelay": true,
+-        "tm": false,
+-        "kvmclock-stable-bit": true,
+-        "hypervisor": true,
+-        "mds-no": false,
+-        "pcommit": false,
+-        "syscall": true,
+-        "avx512dq": false,
+-        "svm": false,
+-        "invtsc": false,
+-        "sse2": true,
+-        "ssbd": false,
+-        "est": false,
+-        "avx512ifma": false,
+-        "tm2": false,
+-        "kvm-pv-eoi": true,
+-        "kvm-pv-ipi": true,
+-        "cx8": true,
+-        "cldemote": false,
+-        "kvm-mmu": false,
+-        "sse4.2": true,
+-        "pge": true,
+-        "avx512bitalg": false,
+-        "pdcm": false,
+-        "model": 94,
+-        "movbe": true,
+-        "nrip-save": false,
+-        "ssse3": true,
+-        "sse4a": false,
+-        "invpcid": true,
+-        "pdpe1gb": true,
+-        "tsc-deadline": true,
+-        "skip-l1dfl-vmentry": true,
+-        "fma": true,
+-        "cx16": true,
+-        "de": true,
+-        "stepping": 3,
+-        "xsave": true,
+-        "clflush": true,
+-        "skinit": false,
+-        "tsc": true,
+-        "tce": false,
+-        "fpu": true,
+-        "ds-cpl": false,
+-        "ibs": false,
+-        "fma4": false,
+-        "la57": false,
+-        "osvw": false,
+-        "apic": true,
+-        "pmm": false,
+-        "spec-ctrl": false,
+-        "tsc-adjust": true,
+-        "kvm-steal-time": true,
+-        "kvmclock": true,
+-        "lwp": false,
+-        "amd-ssbd": false,
+-        "xop": false,
+-        "ibpb": false,
+-        "avx": true,
+-        "movdiri": false,
+-        "acpi": false,
+-        "avx512bw": false,
+-        "ace2": false,
+-        "fsgsbase": true,
+-        "ht": false,
+-        "nx": true,
+-        "pclmulqdq": true,
+-        "mmxext": false,
+-        "popcnt": true,
+-        "vaes": false,
+-        "movdir64b": false,
+-        "xsaves": true,
+-        "lm": true,
+-        "umip": true,
+-        "pse": true,
+-        "avx2": true,
+-        "sep": true,
+-        "virt-ssbd": false,
+-        "nodeid-msr": false,
+-        "md-clear": false,
+-        "misalignsse": false,
+-        "min-xlevel": 2147483656,
+-        "bmi1": true,
+-        "bmi2": true,
+-        "kvm-pv-unhalt": true,
+-        "tsc-scale": false,
+-        "topoext": false,
+-        "clflushopt": true,
+-        "monitor": false,
+-        "avx512er": false,
+-        "pmm-en": false,
+-        "pcid": true,
+-        "arch-capabilities": true,
+-        "3dnow": false,
+-        "erms": true,
+-        "lahf-lm": true,
+-        "vpclmulqdq": false,
+-        "fxsr-opt": false,
+-        "xstore": false,
+-        "rtm": true,
+-        "kvm-hint-dedicated": false,
+-        "lmce": true,
+-        "perfctr-nb": false,
+-        "rdrand": true,
+-        "rdseed": true,
+-        "avx512-4vnniw": false,
+-        "vme": true,
+-        "vmx": true,
+-        "dtes64": false,
+-        "mtrr": true,
+-        "rdtscp": true,
+-        "pse36": true,
+-        "kvm-pv-tlb-flush": true,
+-        "tbm": false,
+-        "wdt": false,
+-        "model-id": "Intel(R) Xeon(R) CPU E3-1245 v5 @ 3.50GHz",
+-        "sha-ni": false,
+-        "abm": true,
+-        "avx512pf": false,
+-        "xstore-en": false
+-      }
+-    }
+-  },
+-  "id": "libvirt-55"
+-}
+-
+-{
+-  "return": {
+-    "model": {
+-      "name": "base",
+-      "props": {
+-        "phys-bits": 0,
+-        "core-id": -1,
+-        "xlevel": 2147483656,
+-        "cmov": true,
+-        "ia64": false,
+-        "ssb-no": false,
+-        "aes": true,
+-        "mmx": true,
+-        "rdpid": false,
+-        "arat": true,
+-        "gfni": false,
+-        "ibrs-all": false,
+-        "pause-filter": false,
+-        "xsavec": true,
+-        "intel-pt": false,
+-        "hv-frequencies": false,
+-        "tsc-frequency": 0,
+-        "xd": true,
+-        "x-intel-pt-auto-level": true,
+-        "hv-vendor-id": "",
+-        "kvm-asyncpf": true,
+-        "kvm_asyncpf": true,
+-        "perfctr_core": false,
+-        "perfctr-core": false,
+-        "mpx": true,
+-        "pbe": false,
+-        "decodeassists": false,
+-        "avx512cd": false,
+-        "sse4_1": true,
+-        "sse4.1": true,
+-        "sse4-1": true,
+-        "family": 6,
+-        "legacy-cache": true,
+-        "host-phys-bits-limit": 0,
+-        "vmware-cpuid-freq": true,
+-        "wbnoinvd": false,
+-        "avx512f": false,
+-        "msr": true,
+-        "mce": true,
+-        "mca": true,
+-        "hv-runtime": false,
+-        "xcrypt": false,
+-        "thread-id": -1,
+-        "min-level": 13,
+-        "xgetbv1": true,
+-        "cid": false,
+-        "hv-relaxed": false,
+-        "hv-crash": false,
+-        "ds": false,
+-        "fxsr": true,
+-        "xsaveopt": true,
+-        "xtpr": false,
+-        "hv-evmcs": false,
+-        "avx512vl": false,
+-        "avx512-vpopcntdq": false,
+-        "phe": false,
+-        "extapic": false,
+-        "3dnowprefetch": true,
+-        "avx512vbmi2": false,
+-        "cr8legacy": false,
+-        "stibp": false,
+-        "cpuid-0xb": true,
+-        "xcrypt-en": false,
+-        "kvm_pv_eoi": true,
+-        "apic-id": 4294967295,
+-        "rsba": false,
+-        "pn": false,
+-        "dca": false,
+-        "vendor": "GenuineIntel",
+-        "hv-ipi": false,
+-        "pku": false,
+-        "smx": false,
+-        "cmp_legacy": false,
+-        "cmp-legacy": false,
+-        "node-id": -1,
+-        "avx512-4fmaps": false,
+-        "vmcb_clean": false,
+-        "vmcb-clean": false,
+-        "3dnowext": false,
+-        "amd-no-ssb": false,
+-        "hle": true,
+-        "npt": false,
+-        "rdctl-no": false,
+-        "memory": "/machine/unattached/system[0]",
+-        "clwb": false,
+-        "lbrv": false,
+-        "adx": true,
+-        "ss": true,
+-        "pni": true,
+-        "svm_lock": false,
+-        "svm-lock": false,
+-        "pfthreshold": false,
+-        "smep": true,
+-        "smap": true,
+-        "x2apic": true,
+-        "avx512vbmi": false,
+-        "avx512vnni": false,
+-        "hv-stimer": false,
+-        "x-hv-synic-kvm-only": false,
+-        "i64": true,
+-        "flushbyasid": false,
+-        "f16c": true,
+-        "ace2-en": false,
+-        "pat": true,
+-        "pae": true,
+-        "sse": true,
+-        "phe-en": false,
+-        "kvm_nopiodelay": true,
+-        "kvm-nopiodelay": true,
+-        "tm": false,
+-        "kvmclock-stable-bit": true,
+-        "hypervisor": true,
+-        "socket-id": -1,
+-        "mds-no": false,
+-        "pcommit": false,
+-        "syscall": true,
+-        "level": 13,
+-        "avx512dq": false,
+-        "x-migrate-smi-count": true,
+-        "svm": false,
+-        "full-cpuid-auto-level": true,
+-        "hv-reset": false,
+-        "invtsc": false,
+-        "sse3": true,
+-        "sse2": true,
+-        "ssbd": false,
+-        "est": false,
+-        "avx512ifma": false,
+-        "tm2": false,
+-        "kvm-pv-ipi": true,
+-        "kvm-pv-eoi": true,
+-        "cx8": true,
+-        "cldemote": false,
+-        "hv-reenlightenment": false,
+-        "kvm_mmu": false,
+-        "kvm-mmu": false,
+-        "sse4_2": true,
+-        "sse4.2": true,
+-        "sse4-2": true,
+-        "pge": true,
+-        "fill-mtrr-mask": true,
+-        "avx512bitalg": false,
+-        "nodeid_msr": false,
+-        "pdcm": false,
+-        "movbe": true,
+-        "model": 94,
+-        "nrip_save": false,
+-        "nrip-save": false,
+-        "kvm_pv_unhalt": true,
+-        "ssse3": true,
+-        "sse4a": false,
+-        "invpcid": true,
+-        "pdpe1gb": true,
+-        "tsc-deadline": true,
+-        "skip-l1dfl-vmentry": true,
+-        "fma": true,
+-        "cx16": true,
+-        "de": true,
+-        "enforce": false,
+-        "stepping": 3,
+-        "xsave": true,
+-        "clflush": true,
+-        "skinit": false,
+-        "tsc": true,
+-        "tce": false,
+-        "fpu": true,
+-        "ibs": false,
+-        "ds_cpl": false,
+-        "ds-cpl": false,
+-        "host-phys-bits": false,
+-        "fma4": false,
+-        "la57": false,
+-        "osvw": false,
+-        "check": true,
+-        "hv-spinlocks": -1,
+-        "pmm": false,
+-        "pmu": false,
+-        "apic": true,
+-        "spec-ctrl": false,
+-        "min-xlevel2": 0,
+-        "tsc-adjust": true,
+-        "tsc_adjust": true,
+-        "kvm-steal-time": true,
+-        "kvm_steal_time": true,
+-        "kvmclock": true,
+-        "l3-cache": true,
+-        "lwp": false,
+-        "amd-ssbd": false,
+-        "ibpb": false,
+-        "xop": false,
+-        "avx": true,
+-        "movdiri": false,
+-        "ace2": false,
+-        "avx512bw": false,
+-        "acpi": false,
+-        "hv-vapic": false,
+-        "fsgsbase": true,
+-        "ht": false,
+-        "nx": true,
+-        "pclmulqdq": true,
+-        "mmxext": false,
+-        "vaes": false,
+-        "popcnt": true,
+-        "xsaves": true,
+-        "movdir64b": false,
+-        "tcg-cpuid": true,
+-        "lm": true,
+-        "umip": true,
+-        "pse": true,
+-        "avx2": true,
+-        "sep": true,
+-        "pclmuldq": true,
+-        "virt-ssbd": false,
+-        "x-hv-max-vps": -1,
+-        "nodeid-msr": false,
+-        "md-clear": false,
+-        "kvm": true,
+-        "misalignsse": false,
+-        "min-xlevel": 2147483656,
+-        "kvm-pv-unhalt": true,
+-        "bmi2": true,
+-        "bmi1": true,
+-        "realized": false,
+-        "tsc_scale": false,
+-        "tsc-scale": false,
+-        "topoext": false,
+-        "hv-vpindex": false,
+-        "xlevel2": 0,
+-        "clflushopt": true,
+-        "kvm-no-smi-migration": false,
+-        "monitor": false,
+-        "avx512er": false,
+-        "pmm-en": false,
+-        "pcid": true,
+-        "arch-capabilities": true,
+-        "3dnow": false,
+-        "erms": true,
+-        "lahf-lm": true,
+-        "lahf_lm": true,
+-        "vpclmulqdq": false,
+-        "fxsr-opt": false,
+-        "hv-synic": false,
+-        "xstore": false,
+-        "fxsr_opt": false,
+-        "kvm-hint-dedicated": false,
+-        "rtm": true,
+-        "lmce": true,
+-        "hv-time": false,
+-        "perfctr-nb": false,
+-        "perfctr_nb": false,
+-        "ffxsr": false,
+-        "hv-tlbflush": false,
+-        "rdrand": true,
+-        "rdseed": true,
+-        "avx512-4vnniw": false,
+-        "vmx": true,
+-        "vme": true,
+-        "dtes64": false,
+-        "mtrr": true,
+-        "rdtscp": true,
+-        "pse36": true,
+-        "kvm-pv-tlb-flush": true,
+-        "tbm": false,
+-        "wdt": false,
+-        "pause_filter": false,
+-        "sha-ni": false,
+-        "model-id": "Intel(R) Xeon(R) CPU E3-1245 v5 @ 3.50GHz",
+-        "abm": true,
+-        "avx512pf": false,
+-        "xstore-en": false
+-      }
+-    }
+-  },
+-  "id": "libvirt-55"
++  "id": "libvirt-53"
+ }
+ 
+ {
+@@ -23697,495 +22719,6 @@
+   "id": "libvirt-3"
+ }
+ 
+-{
+-  "execute": "query-cpu-model-expansion",
+-  "arguments": {
+-    "type": "full",
+-    "model": {
+-      "name": "base",
+-      "props": {
+-        "cmov": true,
+-        "ia64": false,
+-        "ssb-no": false,
+-        "aes": true,
+-        "mmx": true,
+-        "rdpid": false,
+-        "arat": true,
+-        "gfni": false,
+-        "ibrs-all": false,
+-        "pause-filter": false,
+-        "xsavec": false,
+-        "intel-pt": false,
+-        "kvm-asyncpf": false,
+-        "perfctr-core": false,
+-        "mpx": true,
+-        "pbe": false,
+-        "avx512cd": false,
+-        "decodeassists": false,
+-        "sse4.1": true,
+-        "family": 6,
+-        "wbnoinvd": false,
+-        "avx512f": false,
+-        "msr": true,
+-        "mce": true,
+-        "mca": true,
+-        "xcrypt": false,
+-        "min-level": 13,
+-        "xgetbv1": true,
+-        "cid": false,
+-        "ds": false,
+-        "fxsr": true,
+-        "xsaveopt": true,
+-        "xtpr": false,
+-        "avx512vl": false,
+-        "avx512-vpopcntdq": false,
+-        "phe": false,
+-        "extapic": false,
+-        "3dnowprefetch": false,
+-        "avx512vbmi2": false,
+-        "cr8legacy": true,
+-        "stibp": false,
+-        "xcrypt-en": false,
+-        "pn": false,
+-        "rsba": false,
+-        "dca": false,
+-        "vendor": "AuthenticAMD",
+-        "pku": true,
+-        "smx": false,
+-        "cmp-legacy": false,
+-        "avx512-4fmaps": false,
+-        "vmcb-clean": false,
+-        "hle": false,
+-        "3dnowext": true,
+-        "amd-no-ssb": false,
+-        "npt": true,
+-        "rdctl-no": false,
+-        "clwb": true,
+-        "lbrv": false,
+-        "adx": true,
+-        "ss": true,
+-        "pni": true,
+-        "svm-lock": false,
+-        "smep": true,
+-        "smap": true,
+-        "pfthreshold": false,
+-        "x2apic": false,
+-        "avx512vbmi": false,
+-        "avx512vnni": false,
+-        "flushbyasid": false,
+-        "f16c": false,
+-        "ace2-en": false,
+-        "pae": true,
+-        "pat": true,
+-        "sse": true,
+-        "phe-en": false,
+-        "kvm-nopiodelay": false,
+-        "tm": false,
+-        "kvmclock-stable-bit": false,
+-        "hypervisor": true,
+-        "mds-no": false,
+-        "pcommit": true,
+-        "syscall": true,
+-        "avx512dq": false,
+-        "svm": true,
+-        "invtsc": false,
+-        "sse2": true,
+-        "ssbd": false,
+-        "est": false,
+-        "avx512ifma": false,
+-        "tm2": false,
+-        "kvm-pv-eoi": false,
+-        "kvm-pv-ipi": false,
+-        "cx8": true,
+-        "cldemote": false,
+-        "kvm-mmu": false,
+-        "sse4.2": true,
+-        "pge": true,
+-        "avx512bitalg": false,
+-        "pdcm": false,
+-        "model": 6,
+-        "movbe": true,
+-        "nrip-save": false,
+-        "ssse3": true,
+-        "sse4a": true,
+-        "invpcid": false,
+-        "pdpe1gb": true,
+-        "tsc-deadline": false,
+-        "skip-l1dfl-vmentry": false,
+-        "fma": false,
+-        "cx16": true,
+-        "de": true,
+-        "stepping": 3,
+-        "xsave": true,
+-        "clflush": true,
+-        "skinit": false,
+-        "tsc": true,
+-        "tce": false,
+-        "fpu": true,
+-        "ds-cpl": false,
+-        "ibs": false,
+-        "fma4": false,
+-        "la57": true,
+-        "osvw": false,
+-        "apic": true,
+-        "pmm": false,
+-        "spec-ctrl": false,
+-        "tsc-adjust": false,
+-        "kvm-steal-time": false,
+-        "kvmclock": false,
+-        "lwp": false,
+-        "amd-ssbd": false,
+-        "xop": false,
+-        "ibpb": false,
+-        "avx": false,
+-        "movdiri": false,
+-        "acpi": true,
+-        "avx512bw": false,
+-        "ace2": false,
+-        "fsgsbase": true,
+-        "ht": false,
+-        "nx": true,
+-        "pclmulqdq": true,
+-        "mmxext": true,
+-        "popcnt": true,
+-        "vaes": false,
+-        "movdir64b": false,
+-        "xsaves": false,
+-        "lm": true,
+-        "umip": false,
+-        "pse": true,
+-        "avx2": false,
+-        "sep": true,
+-        "virt-ssbd": false,
+-        "nodeid-msr": false,
+-        "md-clear": false,
+-        "misalignsse": false,
+-        "min-xlevel": 2147483658,
+-        "bmi1": true,
+-        "bmi2": true,
+-        "kvm-pv-unhalt": false,
+-        "tsc-scale": false,
+-        "topoext": false,
+-        "clflushopt": true,
+-        "monitor": true,
+-        "avx512er": false,
+-        "pmm-en": false,
+-        "pcid": false,
+-        "arch-capabilities": false,
+-        "3dnow": true,
+-        "erms": true,
+-        "lahf-lm": true,
+-        "vpclmulqdq": false,
+-        "fxsr-opt": false,
+-        "xstore": false,
+-        "rtm": false,
+-        "kvm-hint-dedicated": false,
+-        "lmce": false,
+-        "perfctr-nb": false,
+-        "rdrand": true,
+-        "rdseed": false,
+-        "avx512-4vnniw": false,
+-        "vme": false,
+-        "vmx": false,
+-        "dtes64": false,
+-        "mtrr": true,
+-        "rdtscp": true,
+-        "pse36": true,
+-        "kvm-pv-tlb-flush": false,
+-        "tbm": false,
+-        "wdt": false,
+-        "model-id": "QEMU TCG CPU version 2.5+",
+-        "sha-ni": false,
+-        "abm": true,
+-        "avx512pf": false,
+-        "xstore-en": false
+-      }
+-    }
+-  },
+-  "id": "libvirt-4"
+-}
+-
+-{
+-  "return": {
+-    "model": {
+-      "name": "base",
+-      "props": {
+-        "phys-bits": 0,
+-        "core-id": -1,
+-        "xlevel": 2147483658,
+-        "cmov": true,
+-        "ia64": false,
+-        "ssb-no": false,
+-        "aes": true,
+-        "mmx": true,
+-        "rdpid": false,
+-        "arat": true,
+-        "gfni": false,
+-        "ibrs-all": false,
+-        "pause-filter": false,
+-        "xsavec": false,
+-        "intel-pt": false,
+-        "hv-frequencies": false,
+-        "tsc-frequency": 0,
+-        "xd": true,
+-        "x-intel-pt-auto-level": true,
+-        "hv-vendor-id": "",
+-        "kvm-asyncpf": false,
+-        "kvm_asyncpf": false,
+-        "perfctr_core": false,
+-        "perfctr-core": false,
+-        "mpx": true,
+-        "pbe": false,
+-        "decodeassists": false,
+-        "avx512cd": false,
+-        "sse4_1": true,
+-        "sse4.1": true,
+-        "sse4-1": true,
+-        "family": 6,
+-        "legacy-cache": true,
+-        "host-phys-bits-limit": 0,
+-        "vmware-cpuid-freq": true,
+-        "wbnoinvd": false,
+-        "avx512f": false,
+-        "msr": true,
+-        "mce": true,
+-        "mca": true,
+-        "hv-runtime": false,
+-        "xcrypt": false,
+-        "thread-id": -1,
+-        "min-level": 13,
+-        "xgetbv1": true,
+-        "cid": false,
+-        "hv-relaxed": false,
+-        "hv-crash": false,
+-        "ds": false,
+-        "fxsr": true,
+-        "xsaveopt": true,
+-        "xtpr": false,
+-        "hv-evmcs": false,
+-        "avx512vl": false,
+-        "avx512-vpopcntdq": false,
+-        "phe": false,
+-        "extapic": false,
+-        "3dnowprefetch": false,
+-        "avx512vbmi2": false,
+-        "cr8legacy": true,
+-        "stibp": false,
+-        "cpuid-0xb": true,
+-        "xcrypt-en": false,
+-        "kvm_pv_eoi": false,
+-        "apic-id": 4294967295,
+-        "rsba": false,
+-        "pn": false,
+-        "dca": false,
+-        "vendor": "AuthenticAMD",
+-        "hv-ipi": false,
+-        "pku": true,
+-        "smx": false,
+-        "cmp_legacy": false,
+-        "cmp-legacy": false,
+-        "node-id": -1,
+-        "avx512-4fmaps": false,
+-        "vmcb_clean": false,
+-        "vmcb-clean": false,
+-        "3dnowext": true,
+-        "amd-no-ssb": false,
+-        "hle": false,
+-        "npt": true,
+-        "rdctl-no": false,
+-        "memory": "/machine/unattached/system[0]",
+-        "clwb": true,
+-        "lbrv": false,
+-        "adx": true,
+-        "ss": true,
+-        "pni": true,
+-        "svm_lock": false,
+-        "svm-lock": false,
+-        "pfthreshold": false,
+-        "smep": true,
+-        "smap": true,
+-        "x2apic": false,
+-        "avx512vbmi": false,
+-        "avx512vnni": false,
+-        "hv-stimer": false,
+-        "x-hv-synic-kvm-only": false,
+-        "i64": true,
+-        "flushbyasid": false,
+-        "f16c": false,
+-        "ace2-en": false,
+-        "pat": true,
+-        "pae": true,
+-        "sse": true,
+-        "phe-en": false,
+-        "kvm_nopiodelay": false,
+-        "kvm-nopiodelay": false,
+-        "tm": false,
+-        "kvmclock-stable-bit": false,
+-        "hypervisor": true,
+-        "socket-id": -1,
+-        "mds-no": false,
+-        "pcommit": true,
+-        "syscall": true,
+-        "level": 13,
+-        "avx512dq": false,
+-        "x-migrate-smi-count": true,
+-        "svm": true,
+-        "full-cpuid-auto-level": true,
+-        "hv-reset": false,
+-        "invtsc": false,
+-        "sse3": true,
+-        "sse2": true,
+-        "ssbd": false,
+-        "est": false,
+-        "avx512ifma": false,
+-        "tm2": false,
+-        "kvm-pv-ipi": false,
+-        "kvm-pv-eoi": false,
+-        "cx8": true,
+-        "cldemote": false,
+-        "hv-reenlightenment": false,
+-        "kvm_mmu": false,
+-        "kvm-mmu": false,
+-        "sse4_2": true,
+-        "sse4.2": true,
+-        "sse4-2": true,
+-        "pge": true,
+-        "fill-mtrr-mask": true,
+-        "avx512bitalg": false,
+-        "nodeid_msr": false,
+-        "pdcm": false,
+-        "movbe": true,
+-        "model": 6,
+-        "nrip_save": false,
+-        "nrip-save": false,
+-        "kvm_pv_unhalt": false,
+-        "ssse3": true,
+-        "sse4a": true,
+-        "invpcid": false,
+-        "pdpe1gb": true,
+-        "tsc-deadline": false,
+-        "skip-l1dfl-vmentry": false,
+-        "fma": false,
+-        "cx16": true,
+-        "de": true,
+-        "enforce": false,
+-        "stepping": 3,
+-        "xsave": true,
+-        "clflush": true,
+-        "skinit": false,
+-        "tsc": true,
+-        "tce": false,
+-        "fpu": true,
+-        "ibs": false,
+-        "ds_cpl": false,
+-        "ds-cpl": false,
+-        "host-phys-bits": false,
+-        "fma4": false,
+-        "la57": true,
+-        "osvw": false,
+-        "check": true,
+-        "hv-spinlocks": -1,
+-        "pmm": false,
+-        "pmu": false,
+-        "apic": true,
+-        "spec-ctrl": false,
+-        "min-xlevel2": 0,
+-        "tsc-adjust": false,
+-        "tsc_adjust": false,
+-        "kvm-steal-time": false,
+-        "kvm_steal_time": false,
+-        "kvmclock": false,
+-        "l3-cache": true,
+-        "lwp": false,
+-        "amd-ssbd": false,
+-        "ibpb": false,
+-        "xop": false,
+-        "avx": false,
+-        "movdiri": false,
+-        "ace2": false,
+-        "avx512bw": false,
+-        "acpi": true,
+-        "hv-vapic": false,
+-        "fsgsbase": true,
+-        "ht": false,
+-        "nx": true,
+-        "pclmulqdq": true,
+-        "mmxext": true,
+-        "vaes": false,
+-        "popcnt": true,
+-        "xsaves": false,
+-        "movdir64b": false,
+-        "tcg-cpuid": true,
+-        "lm": true,
+-        "umip": false,
+-        "pse": true,
+-        "avx2": false,
+-        "sep": true,
+-        "pclmuldq": true,
+-        "virt-ssbd": false,
+-        "x-hv-max-vps": -1,
+-        "nodeid-msr": false,
+-        "md-clear": false,
+-        "kvm": true,
+-        "misalignsse": false,
+-        "min-xlevel": 2147483658,
+-        "kvm-pv-unhalt": false,
+-        "bmi2": true,
+-        "bmi1": true,
+-        "realized": false,
+-        "tsc_scale": false,
+-        "tsc-scale": false,
+-        "topoext": false,
+-        "hv-vpindex": false,
+-        "xlevel2": 0,
+-        "clflushopt": true,
+-        "kvm-no-smi-migration": false,
+-        "monitor": true,
+-        "avx512er": false,
+-        "pmm-en": false,
+-        "pcid": false,
+-        "arch-capabilities": false,
+-        "3dnow": true,
+-        "erms": true,
+-        "lahf-lm": true,
+-        "lahf_lm": true,
+-        "vpclmulqdq": false,
+-        "fxsr-opt": false,
+-        "hv-synic": false,
+-        "xstore": false,
+-        "fxsr_opt": false,
+-        "kvm-hint-dedicated": false,
+-        "rtm": false,
+-        "lmce": false,
+-        "hv-time": false,
+-        "perfctr-nb": false,
+-        "perfctr_nb": false,
+-        "ffxsr": false,
+-        "hv-tlbflush": false,
+-        "rdrand": true,
+-        "rdseed": false,
+-        "avx512-4vnniw": false,
+-        "vmx": false,
+-        "vme": false,
+-        "dtes64": false,
+-        "mtrr": true,
+-        "rdtscp": true,
+-        "pse36": true,
+-        "kvm-pv-tlb-flush": false,
+-        "tbm": false,
+-        "wdt": false,
+-        "pause_filter": false,
+-        "sha-ni": false,
+-        "model-id": "QEMU TCG CPU version 2.5+",
+-        "abm": true,
+-        "avx512pf": false,
+-        "xstore-en": false
+-      }
+-    }
+-  },
+-  "id": "libvirt-4"
+-}
+-
+ {
+   "execute": "query-cpu-model-expansion",
+   "arguments": {
+@@ -24197,7 +22730,7 @@
+       }
+     }
+   },
+-  "id": "libvirt-5"
++  "id": "libvirt-4"
+ }
+ 
+ {
+@@ -24403,494 +22936,5 @@
+       }
+     }
+   },
+-  "id": "libvirt-5"
+-}
+-
+-{
+-  "execute": "query-cpu-model-expansion",
+-  "arguments": {
+-    "type": "full",
+-    "model": {
+-      "name": "base",
+-      "props": {
+-        "cmov": true,
+-        "ia64": false,
+-        "ssb-no": false,
+-        "aes": true,
+-        "mmx": true,
+-        "rdpid": false,
+-        "arat": true,
+-        "gfni": false,
+-        "ibrs-all": false,
+-        "pause-filter": false,
+-        "xsavec": false,
+-        "intel-pt": false,
+-        "kvm-asyncpf": false,
+-        "perfctr-core": false,
+-        "mpx": true,
+-        "pbe": false,
+-        "avx512cd": false,
+-        "decodeassists": false,
+-        "sse4.1": true,
+-        "family": 6,
+-        "wbnoinvd": false,
+-        "avx512f": false,
+-        "msr": true,
+-        "mce": true,
+-        "mca": true,
+-        "xcrypt": false,
+-        "min-level": 13,
+-        "xgetbv1": true,
+-        "cid": false,
+-        "ds": false,
+-        "fxsr": true,
+-        "xsaveopt": true,
+-        "xtpr": false,
+-        "avx512vl": false,
+-        "avx512-vpopcntdq": false,
+-        "phe": false,
+-        "extapic": false,
+-        "3dnowprefetch": false,
+-        "avx512vbmi2": false,
+-        "cr8legacy": true,
+-        "stibp": false,
+-        "xcrypt-en": false,
+-        "pn": false,
+-        "rsba": false,
+-        "dca": false,
+-        "vendor": "AuthenticAMD",
+-        "pku": true,
+-        "smx": false,
+-        "cmp-legacy": false,
+-        "avx512-4fmaps": false,
+-        "vmcb-clean": false,
+-        "hle": false,
+-        "3dnowext": true,
+-        "amd-no-ssb": false,
+-        "npt": true,
+-        "rdctl-no": false,
+-        "clwb": true,
+-        "lbrv": false,
+-        "adx": true,
+-        "ss": true,
+-        "pni": true,
+-        "svm-lock": false,
+-        "smep": true,
+-        "smap": true,
+-        "pfthreshold": false,
+-        "x2apic": false,
+-        "avx512vbmi": false,
+-        "avx512vnni": false,
+-        "flushbyasid": false,
+-        "f16c": false,
+-        "ace2-en": false,
+-        "pae": true,
+-        "pat": true,
+-        "sse": true,
+-        "phe-en": false,
+-        "kvm-nopiodelay": false,
+-        "tm": false,
+-        "kvmclock-stable-bit": false,
+-        "hypervisor": true,
+-        "mds-no": false,
+-        "pcommit": true,
+-        "syscall": true,
+-        "avx512dq": false,
+-        "svm": true,
+-        "invtsc": false,
+-        "sse2": true,
+-        "ssbd": false,
+-        "est": false,
+-        "avx512ifma": false,
+-        "tm2": false,
+-        "kvm-pv-eoi": false,
+-        "kvm-pv-ipi": false,
+-        "cx8": true,
+-        "cldemote": false,
+-        "kvm-mmu": false,
+-        "sse4.2": true,
+-        "pge": true,
+-        "avx512bitalg": false,
+-        "pdcm": false,
+-        "model": 6,
+-        "movbe": true,
+-        "nrip-save": false,
+-        "ssse3": true,
+-        "sse4a": true,
+-        "invpcid": false,
+-        "pdpe1gb": true,
+-        "tsc-deadline": false,
+-        "skip-l1dfl-vmentry": false,
+-        "fma": false,
+-        "cx16": true,
+-        "de": true,
+-        "stepping": 3,
+-        "xsave": true,
+-        "clflush": true,
+-        "skinit": false,
+-        "tsc": true,
+-        "tce": false,
+-        "fpu": true,
+-        "ds-cpl": false,
+-        "ibs": false,
+-        "fma4": false,
+-        "la57": true,
+-        "osvw": false,
+-        "apic": true,
+-        "pmm": false,
+-        "spec-ctrl": false,
+-        "tsc-adjust": false,
+-        "kvm-steal-time": false,
+-        "kvmclock": false,
+-        "lwp": false,
+-        "amd-ssbd": false,
+-        "xop": false,
+-        "ibpb": false,
+-        "avx": false,
+-        "movdiri": false,
+-        "acpi": true,
+-        "avx512bw": false,
+-        "ace2": false,
+-        "fsgsbase": true,
+-        "ht": false,
+-        "nx": true,
+-        "pclmulqdq": true,
+-        "mmxext": true,
+-        "popcnt": true,
+-        "vaes": false,
+-        "movdir64b": false,
+-        "xsaves": false,
+-        "lm": true,
+-        "umip": false,
+-        "pse": true,
+-        "avx2": false,
+-        "sep": true,
+-        "virt-ssbd": false,
+-        "nodeid-msr": false,
+-        "md-clear": false,
+-        "misalignsse": false,
+-        "min-xlevel": 2147483658,
+-        "bmi1": true,
+-        "bmi2": true,
+-        "kvm-pv-unhalt": false,
+-        "tsc-scale": false,
+-        "topoext": false,
+-        "clflushopt": true,
+-        "monitor": true,
+-        "avx512er": false,
+-        "pmm-en": false,
+-        "pcid": false,
+-        "arch-capabilities": false,
+-        "3dnow": true,
+-        "erms": true,
+-        "lahf-lm": true,
+-        "vpclmulqdq": false,
+-        "fxsr-opt": false,
+-        "xstore": false,
+-        "rtm": false,
+-        "kvm-hint-dedicated": false,
+-        "lmce": false,
+-        "perfctr-nb": false,
+-        "rdrand": true,
+-        "rdseed": false,
+-        "avx512-4vnniw": false,
+-        "vme": false,
+-        "vmx": false,
+-        "dtes64": false,
+-        "mtrr": true,
+-        "rdtscp": true,
+-        "pse36": true,
+-        "kvm-pv-tlb-flush": false,
+-        "tbm": false,
+-        "wdt": false,
+-        "model-id": "QEMU TCG CPU version 2.5+",
+-        "sha-ni": false,
+-        "abm": true,
+-        "avx512pf": false,
+-        "xstore-en": false
+-      }
+-    }
+-  },
+-  "id": "libvirt-6"
+-}
+-
+-{
+-  "return": {
+-    "model": {
+-      "name": "base",
+-      "props": {
+-        "phys-bits": 0,
+-        "core-id": -1,
+-        "xlevel": 2147483658,
+-        "cmov": true,
+-        "ia64": false,
+-        "ssb-no": false,
+-        "aes": true,
+-        "mmx": true,
+-        "rdpid": false,
+-        "arat": true,
+-        "gfni": false,
+-        "ibrs-all": false,
+-        "pause-filter": false,
+-        "xsavec": false,
+-        "intel-pt": false,
+-        "hv-frequencies": false,
+-        "tsc-frequency": 0,
+-        "xd": true,
+-        "x-intel-pt-auto-level": true,
+-        "hv-vendor-id": "",
+-        "kvm-asyncpf": false,
+-        "kvm_asyncpf": false,
+-        "perfctr_core": false,
+-        "perfctr-core": false,
+-        "mpx": true,
+-        "pbe": false,
+-        "decodeassists": false,
+-        "avx512cd": false,
+-        "sse4_1": true,
+-        "sse4.1": true,
+-        "sse4-1": true,
+-        "family": 6,
+-        "legacy-cache": true,
+-        "host-phys-bits-limit": 0,
+-        "vmware-cpuid-freq": true,
+-        "wbnoinvd": false,
+-        "avx512f": false,
+-        "msr": true,
+-        "mce": true,
+-        "mca": true,
+-        "hv-runtime": false,
+-        "xcrypt": false,
+-        "thread-id": -1,
+-        "min-level": 13,
+-        "xgetbv1": true,
+-        "cid": false,
+-        "hv-relaxed": false,
+-        "hv-crash": false,
+-        "ds": false,
+-        "fxsr": true,
+-        "xsaveopt": true,
+-        "xtpr": false,
+-        "hv-evmcs": false,
+-        "avx512vl": false,
+-        "avx512-vpopcntdq": false,
+-        "phe": false,
+-        "extapic": false,
+-        "3dnowprefetch": false,
+-        "avx512vbmi2": false,
+-        "cr8legacy": true,
+-        "stibp": false,
+-        "cpuid-0xb": true,
+-        "xcrypt-en": false,
+-        "kvm_pv_eoi": false,
+-        "apic-id": 4294967295,
+-        "rsba": false,
+-        "pn": false,
+-        "dca": false,
+-        "vendor": "AuthenticAMD",
+-        "hv-ipi": false,
+-        "pku": true,
+-        "smx": false,
+-        "cmp_legacy": false,
+-        "cmp-legacy": false,
+-        "node-id": -1,
+-        "avx512-4fmaps": false,
+-        "vmcb_clean": false,
+-        "vmcb-clean": false,
+-        "3dnowext": true,
+-        "amd-no-ssb": false,
+-        "hle": false,
+-        "npt": true,
+-        "rdctl-no": false,
+-        "memory": "/machine/unattached/system[0]",
+-        "clwb": true,
+-        "lbrv": false,
+-        "adx": true,
+-        "ss": true,
+-        "pni": true,
+-        "svm_lock": false,
+-        "svm-lock": false,
+-        "pfthreshold": false,
+-        "smep": true,
+-        "smap": true,
+-        "x2apic": false,
+-        "avx512vbmi": false,
+-        "avx512vnni": false,
+-        "hv-stimer": false,
+-        "x-hv-synic-kvm-only": false,
+-        "i64": true,
+-        "flushbyasid": false,
+-        "f16c": false,
+-        "ace2-en": false,
+-        "pat": true,
+-        "pae": true,
+-        "sse": true,
+-        "phe-en": false,
+-        "kvm_nopiodelay": false,
+-        "kvm-nopiodelay": false,
+-        "tm": false,
+-        "kvmclock-stable-bit": false,
+-        "hypervisor": true,
+-        "socket-id": -1,
+-        "mds-no": false,
+-        "pcommit": true,
+-        "syscall": true,
+-        "level": 13,
+-        "avx512dq": false,
+-        "x-migrate-smi-count": true,
+-        "svm": true,
+-        "full-cpuid-auto-level": true,
+-        "hv-reset": false,
+-        "invtsc": false,
+-        "sse3": true,
+-        "sse2": true,
+-        "ssbd": false,
+-        "est": false,
+-        "avx512ifma": false,
+-        "tm2": false,
+-        "kvm-pv-ipi": false,
+-        "kvm-pv-eoi": false,
+-        "cx8": true,
+-        "cldemote": false,
+-        "hv-reenlightenment": false,
+-        "kvm_mmu": false,
+-        "kvm-mmu": false,
+-        "sse4_2": true,
+-        "sse4.2": true,
+-        "sse4-2": true,
+-        "pge": true,
+-        "fill-mtrr-mask": true,
+-        "avx512bitalg": false,
+-        "nodeid_msr": false,
+-        "pdcm": false,
+-        "movbe": true,
+-        "model": 6,
+-        "nrip_save": false,
+-        "nrip-save": false,
+-        "kvm_pv_unhalt": false,
+-        "ssse3": true,
+-        "sse4a": true,
+-        "invpcid": false,
+-        "pdpe1gb": true,
+-        "tsc-deadline": false,
+-        "skip-l1dfl-vmentry": false,
+-        "fma": false,
+-        "cx16": true,
+-        "de": true,
+-        "enforce": false,
+-        "stepping": 3,
+-        "xsave": true,
+-        "clflush": true,
+-        "skinit": false,
+-        "tsc": true,
+-        "tce": false,
+-        "fpu": true,
+-        "ibs": false,
+-        "ds_cpl": false,
+-        "ds-cpl": false,
+-        "host-phys-bits": false,
+-        "fma4": false,
+-        "la57": true,
+-        "osvw": false,
+-        "check": true,
+-        "hv-spinlocks": -1,
+-        "pmm": false,
+-        "pmu": false,
+-        "apic": true,
+-        "spec-ctrl": false,
+-        "min-xlevel2": 0,
+-        "tsc-adjust": false,
+-        "tsc_adjust": false,
+-        "kvm-steal-time": false,
+-        "kvm_steal_time": false,
+-        "kvmclock": false,
+-        "l3-cache": true,
+-        "lwp": false,
+-        "amd-ssbd": false,
+-        "ibpb": false,
+-        "xop": false,
+-        "avx": false,
+-        "movdiri": false,
+-        "ace2": false,
+-        "avx512bw": false,
+-        "acpi": true,
+-        "hv-vapic": false,
+-        "fsgsbase": true,
+-        "ht": false,
+-        "nx": true,
+-        "pclmulqdq": true,
+-        "mmxext": true,
+-        "vaes": false,
+-        "popcnt": true,
+-        "xsaves": false,
+-        "movdir64b": false,
+-        "tcg-cpuid": true,
+-        "lm": true,
+-        "umip": false,
+-        "pse": true,
+-        "avx2": false,
+-        "sep": true,
+-        "pclmuldq": true,
+-        "virt-ssbd": false,
+-        "x-hv-max-vps": -1,
+-        "nodeid-msr": false,
+-        "md-clear": false,
+-        "kvm": true,
+-        "misalignsse": false,
+-        "min-xlevel": 2147483658,
+-        "kvm-pv-unhalt": false,
+-        "bmi2": true,
+-        "bmi1": true,
+-        "realized": false,
+-        "tsc_scale": false,
+-        "tsc-scale": false,
+-        "topoext": false,
+-        "hv-vpindex": false,
+-        "xlevel2": 0,
+-        "clflushopt": true,
+-        "kvm-no-smi-migration": false,
+-        "monitor": true,
+-        "avx512er": false,
+-        "pmm-en": false,
+-        "pcid": false,
+-        "arch-capabilities": false,
+-        "3dnow": true,
+-        "erms": true,
+-        "lahf-lm": true,
+-        "lahf_lm": true,
+-        "vpclmulqdq": false,
+-        "fxsr-opt": false,
+-        "hv-synic": false,
+-        "xstore": false,
+-        "fxsr_opt": false,
+-        "kvm-hint-dedicated": false,
+-        "rtm": false,
+-        "lmce": false,
+-        "hv-time": false,
+-        "perfctr-nb": false,
+-        "perfctr_nb": false,
+-        "ffxsr": false,
+-        "hv-tlbflush": false,
+-        "rdrand": true,
+-        "rdseed": false,
+-        "avx512-4vnniw": false,
+-        "vmx": false,
+-        "vme": false,
+-        "dtes64": false,
+-        "mtrr": true,
+-        "rdtscp": true,
+-        "pse36": true,
+-        "kvm-pv-tlb-flush": false,
+-        "tbm": false,
+-        "wdt": false,
+-        "pause_filter": false,
+-        "sha-ni": false,
+-        "model-id": "QEMU TCG CPU version 2.5+",
+-        "abm": true,
+-        "avx512pf": false,
+-        "xstore-en": false
+-      }
+-    }
+-  },
+-  "id": "libvirt-6"
++  "id": "libvirt-4"
+ }
+diff --git a/tests/qemucapabilitiesdata/caps_4.1.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_4.1.0.x86_64.xml
+index 9245641df8..33de2ed5a1 100644
+--- a/tests/qemucapabilitiesdata/caps_4.1.0.x86_64.xml
++++ b/tests/qemucapabilitiesdata/caps_4.1.0.x86_64.xml
+@@ -219,13 +219,10 @@
+   <flag name='canonical-cpu-features'/>
+   <version>4000050</version>
+   <kvmVersion>0</kvmVersion>
+-  <microcodeVersion>473743</microcodeVersion>
++  <microcodeVersion>424759</microcodeVersion>
+   <package>v4.0.0-1173-g9c70209b63</package>
+   <arch>x86_64</arch>
+   <hostCPU type='kvm' model='base' migratability='yes'>
+-    <property name='phys-bits' type='number' value='0'/>
+-    <property name='core-id' type='number' value='-1'/>
+-    <property name='xlevel' type='number' value='2147483656'/>
+     <property name='cmov' type='boolean' value='true' migratable='yes'/>
+     <property name='ia64' type='boolean' value='false'/>
+     <property name='ssb-no' type='boolean' value='false'/>
+@@ -238,44 +235,27 @@
+     <property name='pause-filter' type='boolean' value='false'/>
+     <property name='xsavec' type='boolean' value='true' migratable='yes'/>
+     <property name='intel-pt' type='boolean' value='false'/>
+-    <property name='hv-frequencies' type='boolean' value='false'/>
+-    <property name='tsc-frequency' type='number' value='0'/>
+-    <property name='xd' type='boolean' value='true' migratable='yes'/>
+-    <property name='x-intel-pt-auto-level' type='boolean' value='true' migratable='yes'/>
+-    <property name='hv-vendor-id' type='string' value=''/>
+     <property name='kvm-asyncpf' type='boolean' value='true' migratable='yes'/>
+-    <property name='kvm_asyncpf' type='boolean' value='true' migratable='yes'/>
+-    <property name='perfctr_core' type='boolean' value='false'/>
+     <property name='perfctr-core' type='boolean' value='false'/>
+     <property name='mpx' type='boolean' value='true' migratable='yes'/>
+     <property name='pbe' type='boolean' value='false'/>
+-    <property name='decodeassists' type='boolean' value='false'/>
+     <property name='avx512cd' type='boolean' value='false'/>
+-    <property name='sse4_1' type='boolean' value='true' migratable='yes'/>
++    <property name='decodeassists' type='boolean' value='false'/>
+     <property name='sse4.1' type='boolean' value='true' migratable='yes'/>
+-    <property name='sse4-1' type='boolean' value='true' migratable='yes'/>
+     <property name='family' type='number' value='6'/>
+-    <property name='legacy-cache' type='boolean' value='true' migratable='yes'/>
+-    <property name='host-phys-bits-limit' type='number' value='0'/>
+-    <property name='vmware-cpuid-freq' type='boolean' value='true' migratable='yes'/>
+     <property name='wbnoinvd' type='boolean' value='false'/>
+     <property name='avx512f' type='boolean' value='false'/>
+     <property name='msr' type='boolean' value='true' migratable='yes'/>
+     <property name='mce' type='boolean' value='true' migratable='yes'/>
+     <property name='mca' type='boolean' value='true' migratable='yes'/>
+-    <property name='hv-runtime' type='boolean' value='false'/>
+     <property name='xcrypt' type='boolean' value='false'/>
+-    <property name='thread-id' type='number' value='-1'/>
+     <property name='min-level' type='number' value='13'/>
+     <property name='xgetbv1' type='boolean' value='true' migratable='yes'/>
+     <property name='cid' type='boolean' value='false'/>
+-    <property name='hv-relaxed' type='boolean' value='false'/>
+-    <property name='hv-crash' type='boolean' value='false'/>
+     <property name='ds' type='boolean' value='false'/>
+     <property name='fxsr' type='boolean' value='true' migratable='yes'/>
+     <property name='xsaveopt' type='boolean' value='true' migratable='yes'/>
+     <property name='xtpr' type='boolean' value='false'/>
+-    <property name='hv-evmcs' type='boolean' value='false'/>
+     <property name='avx512vl' type='boolean' value='false'/>
+     <property name='avx512-vpopcntdq' type='boolean' value='false'/>
+     <property name='phe' type='boolean' value='false'/>
+@@ -284,94 +264,67 @@
+     <property name='avx512vbmi2' type='boolean' value='false'/>
+     <property name='cr8legacy' type='boolean' value='false'/>
+     <property name='stibp' type='boolean' value='false'/>
+-    <property name='cpuid-0xb' type='boolean' value='true' migratable='yes'/>
+     <property name='xcrypt-en' type='boolean' value='false'/>
+-    <property name='kvm_pv_eoi' type='boolean' value='true' migratable='yes'/>
+-    <property name='apic-id' type='number' value='4294967295'/>
+-    <property name='rsba' type='boolean' value='false'/>
+     <property name='pn' type='boolean' value='false'/>
++    <property name='rsba' type='boolean' value='false'/>
+     <property name='dca' type='boolean' value='false'/>
+     <property name='vendor' type='string' value='GenuineIntel'/>
+-    <property name='hv-ipi' type='boolean' value='false'/>
+     <property name='pku' type='boolean' value='false'/>
+     <property name='smx' type='boolean' value='false'/>
+-    <property name='cmp_legacy' type='boolean' value='false'/>
+     <property name='cmp-legacy' type='boolean' value='false'/>
+-    <property name='node-id' type='number' value='-1'/>
+     <property name='avx512-4fmaps' type='boolean' value='false'/>
+-    <property name='vmcb_clean' type='boolean' value='false'/>
+     <property name='vmcb-clean' type='boolean' value='false'/>
++    <property name='hle' type='boolean' value='true' migratable='yes'/>
+     <property name='3dnowext' type='boolean' value='false'/>
+     <property name='amd-no-ssb' type='boolean' value='false'/>
+-    <property name='hle' type='boolean' value='true' migratable='yes'/>
+     <property name='npt' type='boolean' value='false'/>
+     <property name='rdctl-no' type='boolean' value='false'/>
+-    <property name='memory' type='string' value='/machine/unattached/system[0]'/>
+     <property name='clwb' type='boolean' value='false'/>
+     <property name='lbrv' type='boolean' value='false'/>
+     <property name='adx' type='boolean' value='true' migratable='yes'/>
+     <property name='ss' type='boolean' value='true' migratable='yes'/>
+     <property name='pni' type='boolean' value='true' migratable='yes'/>
+-    <property name='svm_lock' type='boolean' value='false'/>
+     <property name='svm-lock' type='boolean' value='false'/>
+-    <property name='pfthreshold' type='boolean' value='false'/>
+     <property name='smep' type='boolean' value='true' migratable='yes'/>
+     <property name='smap' type='boolean' value='true' migratable='yes'/>
++    <property name='pfthreshold' type='boolean' value='false'/>
+     <property name='x2apic' type='boolean' value='true' migratable='yes'/>
+     <property name='avx512vbmi' type='boolean' value='false'/>
+     <property name='avx512vnni' type='boolean' value='false'/>
+-    <property name='hv-stimer' type='boolean' value='false'/>
+-    <property name='x-hv-synic-kvm-only' type='boolean' value='false'/>
+-    <property name='i64' type='boolean' value='true' migratable='yes'/>
+     <property name='flushbyasid' type='boolean' value='false'/>
+     <property name='f16c' type='boolean' value='true' migratable='yes'/>
+     <property name='ace2-en' type='boolean' value='false'/>
+-    <property name='pat' type='boolean' value='true' migratable='yes'/>
+     <property name='pae' type='boolean' value='true' migratable='yes'/>
++    <property name='pat' type='boolean' value='true' migratable='yes'/>
+     <property name='sse' type='boolean' value='true' migratable='yes'/>
+     <property name='phe-en' type='boolean' value='false'/>
+-    <property name='kvm_nopiodelay' type='boolean' value='true' migratable='yes'/>
+     <property name='kvm-nopiodelay' type='boolean' value='true' migratable='yes'/>
+     <property name='tm' type='boolean' value='false'/>
+     <property name='kvmclock-stable-bit' type='boolean' value='true' migratable='yes'/>
+     <property name='hypervisor' type='boolean' value='true' migratable='yes'/>
+-    <property name='socket-id' type='number' value='-1'/>
+     <property name='mds-no' type='boolean' value='false'/>
+     <property name='pcommit' type='boolean' value='false'/>
+     <property name='syscall' type='boolean' value='true' migratable='yes'/>
+-    <property name='level' type='number' value='13'/>
+     <property name='avx512dq' type='boolean' value='false'/>
+-    <property name='x-migrate-smi-count' type='boolean' value='true' migratable='yes'/>
+     <property name='svm' type='boolean' value='false'/>
+-    <property name='full-cpuid-auto-level' type='boolean' value='true' migratable='yes'/>
+-    <property name='hv-reset' type='boolean' value='false'/>
+     <property name='invtsc' type='boolean' value='false'/>
+-    <property name='sse3' type='boolean' value='true' migratable='yes'/>
+     <property name='sse2' type='boolean' value='true' migratable='yes'/>
+     <property name='ssbd' type='boolean' value='false'/>
+     <property name='est' type='boolean' value='false'/>
+     <property name='avx512ifma' type='boolean' value='false'/>
+     <property name='tm2' type='boolean' value='false'/>
+-    <property name='kvm-pv-ipi' type='boolean' value='true' migratable='yes'/>
+     <property name='kvm-pv-eoi' type='boolean' value='true' migratable='yes'/>
++    <property name='kvm-pv-ipi' type='boolean' value='true' migratable='yes'/>
+     <property name='cx8' type='boolean' value='true' migratable='yes'/>
+     <property name='cldemote' type='boolean' value='false'/>
+-    <property name='hv-reenlightenment' type='boolean' value='false'/>
+-    <property name='kvm_mmu' type='boolean' value='false'/>
+     <property name='kvm-mmu' type='boolean' value='false'/>
+-    <property name='sse4_2' type='boolean' value='true' migratable='yes'/>
+     <property name='sse4.2' type='boolean' value='true' migratable='yes'/>
+-    <property name='sse4-2' type='boolean' value='true' migratable='yes'/>
+     <property name='pge' type='boolean' value='true' migratable='yes'/>
+-    <property name='fill-mtrr-mask' type='boolean' value='true' migratable='yes'/>
+     <property name='avx512bitalg' type='boolean' value='false'/>
+-    <property name='nodeid_msr' type='boolean' value='false'/>
+     <property name='pdcm' type='boolean' value='false'/>
+-    <property name='movbe' type='boolean' value='true' migratable='yes'/>
+     <property name='model' type='number' value='94'/>
+-    <property name='nrip_save' type='boolean' value='false'/>
++    <property name='movbe' type='boolean' value='true' migratable='yes'/>
+     <property name='nrip-save' type='boolean' value='false'/>
+-    <property name='kvm_pv_unhalt' type='boolean' value='true' migratable='yes'/>
+     <property name='ssse3' type='boolean' value='true' migratable='yes'/>
+     <property name='sse4a' type='boolean' value='false'/>
+     <property name='invpcid' type='boolean' value='true' migratable='yes'/>
+@@ -381,7 +334,6 @@
+     <property name='fma' type='boolean' value='true' migratable='yes'/>
+     <property name='cx16' type='boolean' value='true' migratable='yes'/>
+     <property name='de' type='boolean' value='true' migratable='yes'/>
+-    <property name='enforce' type='boolean' value='false'/>
+     <property name='stepping' type='number' value='3'/>
+     <property name='xsave' type='boolean' value='true' migratable='yes'/>
+     <property name='clflush' type='boolean' value='true' migratable='yes'/>
+@@ -389,70 +341,51 @@
+     <property name='tsc' type='boolean' value='true' migratable='yes'/>
+     <property name='tce' type='boolean' value='false'/>
+     <property name='fpu' type='boolean' value='true' migratable='yes'/>
+-    <property name='ibs' type='boolean' value='false'/>
+-    <property name='ds_cpl' type='boolean' value='false'/>
+     <property name='ds-cpl' type='boolean' value='false'/>
+-    <property name='host-phys-bits' type='boolean' value='false'/>
++    <property name='ibs' type='boolean' value='false'/>
+     <property name='fma4' type='boolean' value='false'/>
+     <property name='la57' type='boolean' value='false'/>
+     <property name='osvw' type='boolean' value='false'/>
+-    <property name='check' type='boolean' value='true' migratable='yes'/>
+-    <property name='hv-spinlocks' type='number' value='-1'/>
+-    <property name='pmm' type='boolean' value='false'/>
+-    <property name='pmu' type='boolean' value='false'/>
+     <property name='apic' type='boolean' value='true' migratable='yes'/>
++    <property name='pmm' type='boolean' value='false'/>
+     <property name='spec-ctrl' type='boolean' value='false'/>
+-    <property name='min-xlevel2' type='number' value='0'/>
+     <property name='tsc-adjust' type='boolean' value='true' migratable='yes'/>
+-    <property name='tsc_adjust' type='boolean' value='true' migratable='yes'/>
+     <property name='kvm-steal-time' type='boolean' value='true' migratable='yes'/>
+-    <property name='kvm_steal_time' type='boolean' value='true' migratable='yes'/>
+     <property name='kvmclock' type='boolean' value='true' migratable='yes'/>
+-    <property name='l3-cache' type='boolean' value='true' migratable='yes'/>
+     <property name='lwp' type='boolean' value='false'/>
+     <property name='amd-ssbd' type='boolean' value='false'/>
+-    <property name='ibpb' type='boolean' value='false'/>
+     <property name='xop' type='boolean' value='false'/>
++    <property name='ibpb' type='boolean' value='false'/>
+     <property name='avx' type='boolean' value='true' migratable='yes'/>
+     <property name='movdiri' type='boolean' value='false'/>
+-    <property name='ace2' type='boolean' value='false'/>
+-    <property name='avx512bw' type='boolean' value='false'/>
+     <property name='acpi' type='boolean' value='false'/>
+-    <property name='hv-vapic' type='boolean' value='false'/>
++    <property name='avx512bw' type='boolean' value='false'/>
++    <property name='ace2' type='boolean' value='false'/>
+     <property name='fsgsbase' type='boolean' value='true' migratable='yes'/>
+     <property name='ht' type='boolean' value='false'/>
+     <property name='nx' type='boolean' value='true' migratable='yes'/>
+     <property name='pclmulqdq' type='boolean' value='true' migratable='yes'/>
+     <property name='mmxext' type='boolean' value='false'/>
+-    <property name='vaes' type='boolean' value='false'/>
+     <property name='popcnt' type='boolean' value='true' migratable='yes'/>
+-    <property name='xsaves' type='boolean' value='true' migratable='yes'/>
++    <property name='vaes' type='boolean' value='false'/>
+     <property name='movdir64b' type='boolean' value='false'/>
+-    <property name='tcg-cpuid' type='boolean' value='true' migratable='yes'/>
++    <property name='xsaves' type='boolean' value='true' migratable='yes'/>
+     <property name='lm' type='boolean' value='true' migratable='yes'/>
+     <property name='umip' type='boolean' value='true' migratable='yes'/>
+     <property name='pse' type='boolean' value='true' migratable='yes'/>
+     <property name='avx2' type='boolean' value='true' migratable='yes'/>
+     <property name='sep' type='boolean' value='true' migratable='yes'/>
+-    <property name='pclmuldq' type='boolean' value='true' migratable='yes'/>
+     <property name='virt-ssbd' type='boolean' value='false'/>
+-    <property name='x-hv-max-vps' type='number' value='-1'/>
+     <property name='nodeid-msr' type='boolean' value='false'/>
+     <property name='md-clear' type='boolean' value='false'/>
+-    <property name='kvm' type='boolean' value='true' migratable='yes'/>
+     <property name='misalignsse' type='boolean' value='false'/>
+     <property name='min-xlevel' type='number' value='2147483656'/>
+-    <property name='kvm-pv-unhalt' type='boolean' value='true' migratable='yes'/>
+-    <property name='bmi2' type='boolean' value='true' migratable='yes'/>
+     <property name='bmi1' type='boolean' value='true' migratable='yes'/>
+-    <property name='realized' type='boolean' value='false'/>
+-    <property name='tsc_scale' type='boolean' value='false'/>
++    <property name='bmi2' type='boolean' value='true' migratable='yes'/>
++    <property name='kvm-pv-unhalt' type='boolean' value='true' migratable='yes'/>
+     <property name='tsc-scale' type='boolean' value='false'/>
+     <property name='topoext' type='boolean' value='false'/>
+-    <property name='hv-vpindex' type='boolean' value='false'/>
+-    <property name='xlevel2' type='number' value='0'/>
+     <property name='clflushopt' type='boolean' value='true' migratable='yes'/>
+-    <property name='kvm-no-smi-migration' type='boolean' value='false'/>
+     <property name='monitor' type='boolean' value='false'/>
+     <property name='avx512er' type='boolean' value='false'/>
+     <property name='pmm-en' type='boolean' value='false'/>
+@@ -461,25 +394,18 @@
+     <property name='3dnow' type='boolean' value='false'/>
+     <property name='erms' type='boolean' value='true' migratable='yes'/>
+     <property name='lahf-lm' type='boolean' value='true' migratable='yes'/>
+-    <property name='lahf_lm' type='boolean' value='true' migratable='yes'/>
+     <property name='vpclmulqdq' type='boolean' value='false'/>
+     <property name='fxsr-opt' type='boolean' value='false'/>
+-    <property name='hv-synic' type='boolean' value='false'/>
+     <property name='xstore' type='boolean' value='false'/>
+-    <property name='fxsr_opt' type='boolean' value='false'/>
+-    <property name='kvm-hint-dedicated' type='boolean' value='false'/>
+     <property name='rtm' type='boolean' value='true' migratable='yes'/>
++    <property name='kvm-hint-dedicated' type='boolean' value='false'/>
+     <property name='lmce' type='boolean' value='true' migratable='yes'/>
+-    <property name='hv-time' type='boolean' value='false'/>
+     <property name='perfctr-nb' type='boolean' value='false'/>
+-    <property name='perfctr_nb' type='boolean' value='false'/>
+-    <property name='ffxsr' type='boolean' value='false'/>
+-    <property name='hv-tlbflush' type='boolean' value='false'/>
+     <property name='rdrand' type='boolean' value='true' migratable='yes'/>
+     <property name='rdseed' type='boolean' value='true' migratable='yes'/>
+     <property name='avx512-4vnniw' type='boolean' value='false'/>
+-    <property name='vmx' type='boolean' value='true' migratable='yes'/>
+     <property name='vme' type='boolean' value='true' migratable='yes'/>
++    <property name='vmx' type='boolean' value='true' migratable='yes'/>
+     <property name='dtes64' type='boolean' value='false'/>
+     <property name='mtrr' type='boolean' value='true' migratable='yes'/>
+     <property name='rdtscp' type='boolean' value='true' migratable='yes'/>
+@@ -487,17 +413,13 @@
+     <property name='kvm-pv-tlb-flush' type='boolean' value='true' migratable='yes'/>
+     <property name='tbm' type='boolean' value='false'/>
+     <property name='wdt' type='boolean' value='false'/>
+-    <property name='pause_filter' type='boolean' value='false'/>
+-    <property name='sha-ni' type='boolean' value='false'/>
+     <property name='model-id' type='string' value='Intel(R) Xeon(R) CPU E3-1245 v5 @ 3.50GHz'/>
++    <property name='sha-ni' type='boolean' value='false'/>
+     <property name='abm' type='boolean' value='true' migratable='yes'/>
+     <property name='avx512pf' type='boolean' value='false'/>
+     <property name='xstore-en' type='boolean' value='false'/>
+   </hostCPU>
+   <hostCPU type='tcg' model='base' migratability='yes'>
+-    <property name='phys-bits' type='number' value='0'/>
+-    <property name='core-id' type='number' value='-1'/>
+-    <property name='xlevel' type='number' value='2147483658'/>
+     <property name='cmov' type='boolean' value='true' migratable='yes'/>
+     <property name='ia64' type='boolean' value='false'/>
+     <property name='ssb-no' type='boolean' value='false'/>
+@@ -510,44 +432,27 @@
+     <property name='pause-filter' type='boolean' value='false'/>
+     <property name='xsavec' type='boolean' value='false'/>
+     <property name='intel-pt' type='boolean' value='false'/>
+-    <property name='hv-frequencies' type='boolean' value='false'/>
+-    <property name='tsc-frequency' type='number' value='0'/>
+-    <property name='xd' type='boolean' value='true' migratable='yes'/>
+-    <property name='x-intel-pt-auto-level' type='boolean' value='true' migratable='yes'/>
+-    <property name='hv-vendor-id' type='string' value=''/>
+     <property name='kvm-asyncpf' type='boolean' value='false'/>
+-    <property name='kvm_asyncpf' type='boolean' value='false'/>
+-    <property name='perfctr_core' type='boolean' value='false'/>
+     <property name='perfctr-core' type='boolean' value='false'/>
+     <property name='mpx' type='boolean' value='true' migratable='yes'/>
+     <property name='pbe' type='boolean' value='false'/>
+-    <property name='decodeassists' type='boolean' value='false'/>
+     <property name='avx512cd' type='boolean' value='false'/>
+-    <property name='sse4_1' type='boolean' value='true' migratable='yes'/>
++    <property name='decodeassists' type='boolean' value='false'/>
+     <property name='sse4.1' type='boolean' value='true' migratable='yes'/>
+-    <property name='sse4-1' type='boolean' value='true' migratable='yes'/>
+     <property name='family' type='number' value='6'/>
+-    <property name='legacy-cache' type='boolean' value='true' migratable='yes'/>
+-    <property name='host-phys-bits-limit' type='number' value='0'/>
+-    <property name='vmware-cpuid-freq' type='boolean' value='true' migratable='yes'/>
+     <property name='wbnoinvd' type='boolean' value='false'/>
+     <property name='avx512f' type='boolean' value='false'/>
+     <property name='msr' type='boolean' value='true' migratable='yes'/>
+     <property name='mce' type='boolean' value='true' migratable='yes'/>
+     <property name='mca' type='boolean' value='true' migratable='yes'/>
+-    <property name='hv-runtime' type='boolean' value='false'/>
+     <property name='xcrypt' type='boolean' value='false'/>
+-    <property name='thread-id' type='number' value='-1'/>
+     <property name='min-level' type='number' value='13'/>
+     <property name='xgetbv1' type='boolean' value='true' migratable='yes'/>
+     <property name='cid' type='boolean' value='false'/>
+-    <property name='hv-relaxed' type='boolean' value='false'/>
+-    <property name='hv-crash' type='boolean' value='false'/>
+     <property name='ds' type='boolean' value='false'/>
+     <property name='fxsr' type='boolean' value='true' migratable='yes'/>
+     <property name='xsaveopt' type='boolean' value='true' migratable='yes'/>
+     <property name='xtpr' type='boolean' value='false'/>
+-    <property name='hv-evmcs' type='boolean' value='false'/>
+     <property name='avx512vl' type='boolean' value='false'/>
+     <property name='avx512-vpopcntdq' type='boolean' value='false'/>
+     <property name='phe' type='boolean' value='false'/>
+@@ -556,94 +461,67 @@
+     <property name='avx512vbmi2' type='boolean' value='false'/>
+     <property name='cr8legacy' type='boolean' value='true' migratable='yes'/>
+     <property name='stibp' type='boolean' value='false'/>
+-    <property name='cpuid-0xb' type='boolean' value='true' migratable='yes'/>
+     <property name='xcrypt-en' type='boolean' value='false'/>
+-    <property name='kvm_pv_eoi' type='boolean' value='false'/>
+-    <property name='apic-id' type='number' value='4294967295'/>
+-    <property name='rsba' type='boolean' value='false'/>
+     <property name='pn' type='boolean' value='false'/>
++    <property name='rsba' type='boolean' value='false'/>
+     <property name='dca' type='boolean' value='false'/>
+     <property name='vendor' type='string' value='AuthenticAMD'/>
+-    <property name='hv-ipi' type='boolean' value='false'/>
+     <property name='pku' type='boolean' value='true' migratable='yes'/>
+     <property name='smx' type='boolean' value='false'/>
+-    <property name='cmp_legacy' type='boolean' value='false'/>
+     <property name='cmp-legacy' type='boolean' value='false'/>
+-    <property name='node-id' type='number' value='-1'/>
+     <property name='avx512-4fmaps' type='boolean' value='false'/>
+-    <property name='vmcb_clean' type='boolean' value='false'/>
+     <property name='vmcb-clean' type='boolean' value='false'/>
++    <property name='hle' type='boolean' value='false'/>
+     <property name='3dnowext' type='boolean' value='true' migratable='yes'/>
+     <property name='amd-no-ssb' type='boolean' value='false'/>
+-    <property name='hle' type='boolean' value='false'/>
+     <property name='npt' type='boolean' value='true' migratable='yes'/>
+     <property name='rdctl-no' type='boolean' value='false'/>
+-    <property name='memory' type='string' value='/machine/unattached/system[0]'/>
+     <property name='clwb' type='boolean' value='true' migratable='yes'/>
+     <property name='lbrv' type='boolean' value='false'/>
+     <property name='adx' type='boolean' value='true' migratable='yes'/>
+     <property name='ss' type='boolean' value='true' migratable='yes'/>
+     <property name='pni' type='boolean' value='true' migratable='yes'/>
+-    <property name='svm_lock' type='boolean' value='false'/>
+     <property name='svm-lock' type='boolean' value='false'/>
+-    <property name='pfthreshold' type='boolean' value='false'/>
+     <property name='smep' type='boolean' value='true' migratable='yes'/>
+     <property name='smap' type='boolean' value='true' migratable='yes'/>
++    <property name='pfthreshold' type='boolean' value='false'/>
+     <property name='x2apic' type='boolean' value='false'/>
+     <property name='avx512vbmi' type='boolean' value='false'/>
+     <property name='avx512vnni' type='boolean' value='false'/>
+-    <property name='hv-stimer' type='boolean' value='false'/>
+-    <property name='x-hv-synic-kvm-only' type='boolean' value='false'/>
+-    <property name='i64' type='boolean' value='true' migratable='yes'/>
+     <property name='flushbyasid' type='boolean' value='false'/>
+     <property name='f16c' type='boolean' value='false'/>
+     <property name='ace2-en' type='boolean' value='false'/>
+-    <property name='pat' type='boolean' value='true' migratable='yes'/>
+     <property name='pae' type='boolean' value='true' migratable='yes'/>
++    <property name='pat' type='boolean' value='true' migratable='yes'/>
+     <property name='sse' type='boolean' value='true' migratable='yes'/>
+     <property name='phe-en' type='boolean' value='false'/>
+-    <property name='kvm_nopiodelay' type='boolean' value='false'/>
+     <property name='kvm-nopiodelay' type='boolean' value='false'/>
+     <property name='tm' type='boolean' value='false'/>
+     <property name='kvmclock-stable-bit' type='boolean' value='false'/>
+     <property name='hypervisor' type='boolean' value='true' migratable='yes'/>
+-    <property name='socket-id' type='number' value='-1'/>
+     <property name='mds-no' type='boolean' value='false'/>
+     <property name='pcommit' type='boolean' value='true' migratable='yes'/>
+     <property name='syscall' type='boolean' value='true' migratable='yes'/>
+-    <property name='level' type='number' value='13'/>
+     <property name='avx512dq' type='boolean' value='false'/>
+-    <property name='x-migrate-smi-count' type='boolean' value='true' migratable='yes'/>
+     <property name='svm' type='boolean' value='true' migratable='yes'/>
+-    <property name='full-cpuid-auto-level' type='boolean' value='true' migratable='yes'/>
+-    <property name='hv-reset' type='boolean' value='false'/>
+     <property name='invtsc' type='boolean' value='false'/>
+-    <property name='sse3' type='boolean' value='true' migratable='yes'/>
+     <property name='sse2' type='boolean' value='true' migratable='yes'/>
+     <property name='ssbd' type='boolean' value='false'/>
+     <property name='est' type='boolean' value='false'/>
+     <property name='avx512ifma' type='boolean' value='false'/>
+     <property name='tm2' type='boolean' value='false'/>
+-    <property name='kvm-pv-ipi' type='boolean' value='false'/>
+     <property name='kvm-pv-eoi' type='boolean' value='false'/>
++    <property name='kvm-pv-ipi' type='boolean' value='false'/>
+     <property name='cx8' type='boolean' value='true' migratable='yes'/>
+     <property name='cldemote' type='boolean' value='false'/>
+-    <property name='hv-reenlightenment' type='boolean' value='false'/>
+-    <property name='kvm_mmu' type='boolean' value='false'/>
+     <property name='kvm-mmu' type='boolean' value='false'/>
+-    <property name='sse4_2' type='boolean' value='true' migratable='yes'/>
+     <property name='sse4.2' type='boolean' value='true' migratable='yes'/>
+-    <property name='sse4-2' type='boolean' value='true' migratable='yes'/>
+     <property name='pge' type='boolean' value='true' migratable='yes'/>
+-    <property name='fill-mtrr-mask' type='boolean' value='true' migratable='yes'/>
+     <property name='avx512bitalg' type='boolean' value='false'/>
+-    <property name='nodeid_msr' type='boolean' value='false'/>
+     <property name='pdcm' type='boolean' value='false'/>
+-    <property name='movbe' type='boolean' value='true' migratable='yes'/>
+     <property name='model' type='number' value='6'/>
+-    <property name='nrip_save' type='boolean' value='false'/>
++    <property name='movbe' type='boolean' value='true' migratable='yes'/>
+     <property name='nrip-save' type='boolean' value='false'/>
+-    <property name='kvm_pv_unhalt' type='boolean' value='false'/>
+     <property name='ssse3' type='boolean' value='true' migratable='yes'/>
+     <property name='sse4a' type='boolean' value='true' migratable='yes'/>
+     <property name='invpcid' type='boolean' value='false'/>
+@@ -653,7 +531,6 @@
+     <property name='fma' type='boolean' value='false'/>
+     <property name='cx16' type='boolean' value='true' migratable='yes'/>
+     <property name='de' type='boolean' value='true' migratable='yes'/>
+-    <property name='enforce' type='boolean' value='false'/>
+     <property name='stepping' type='number' value='3'/>
+     <property name='xsave' type='boolean' value='true' migratable='yes'/>
+     <property name='clflush' type='boolean' value='true' migratable='yes'/>
+@@ -661,70 +538,51 @@
+     <property name='tsc' type='boolean' value='true' migratable='yes'/>
+     <property name='tce' type='boolean' value='false'/>
+     <property name='fpu' type='boolean' value='true' migratable='yes'/>
+-    <property name='ibs' type='boolean' value='false'/>
+-    <property name='ds_cpl' type='boolean' value='false'/>
+     <property name='ds-cpl' type='boolean' value='false'/>
+-    <property name='host-phys-bits' type='boolean' value='false'/>
++    <property name='ibs' type='boolean' value='false'/>
+     <property name='fma4' type='boolean' value='false'/>
+     <property name='la57' type='boolean' value='true' migratable='yes'/>
+     <property name='osvw' type='boolean' value='false'/>
+-    <property name='check' type='boolean' value='true' migratable='yes'/>
+-    <property name='hv-spinlocks' type='number' value='-1'/>
+-    <property name='pmm' type='boolean' value='false'/>
+-    <property name='pmu' type='boolean' value='false'/>
+     <property name='apic' type='boolean' value='true' migratable='yes'/>
++    <property name='pmm' type='boolean' value='false'/>
+     <property name='spec-ctrl' type='boolean' value='false'/>
+-    <property name='min-xlevel2' type='number' value='0'/>
+     <property name='tsc-adjust' type='boolean' value='false'/>
+-    <property name='tsc_adjust' type='boolean' value='false'/>
+     <property name='kvm-steal-time' type='boolean' value='false'/>
+-    <property name='kvm_steal_time' type='boolean' value='false'/>
+     <property name='kvmclock' type='boolean' value='false'/>
+-    <property name='l3-cache' type='boolean' value='true' migratable='yes'/>
+     <property name='lwp' type='boolean' value='false'/>
+     <property name='amd-ssbd' type='boolean' value='false'/>
+-    <property name='ibpb' type='boolean' value='false'/>
+     <property name='xop' type='boolean' value='false'/>
++    <property name='ibpb' type='boolean' value='false'/>
+     <property name='avx' type='boolean' value='false'/>
+     <property name='movdiri' type='boolean' value='false'/>
+-    <property name='ace2' type='boolean' value='false'/>
+-    <property name='avx512bw' type='boolean' value='false'/>
+     <property name='acpi' type='boolean' value='true' migratable='yes'/>
+-    <property name='hv-vapic' type='boolean' value='false'/>
++    <property name='avx512bw' type='boolean' value='false'/>
++    <property name='ace2' type='boolean' value='false'/>
+     <property name='fsgsbase' type='boolean' value='true' migratable='yes'/>
+     <property name='ht' type='boolean' value='false'/>
+     <property name='nx' type='boolean' value='true' migratable='yes'/>
+     <property name='pclmulqdq' type='boolean' value='true' migratable='yes'/>
+     <property name='mmxext' type='boolean' value='true' migratable='yes'/>
+-    <property name='vaes' type='boolean' value='false'/>
+     <property name='popcnt' type='boolean' value='true' migratable='yes'/>
+-    <property name='xsaves' type='boolean' value='false'/>
++    <property name='vaes' type='boolean' value='false'/>
+     <property name='movdir64b' type='boolean' value='false'/>
+-    <property name='tcg-cpuid' type='boolean' value='true' migratable='yes'/>
++    <property name='xsaves' type='boolean' value='false'/>
+     <property name='lm' type='boolean' value='true' migratable='yes'/>
+     <property name='umip' type='boolean' value='false'/>
+     <property name='pse' type='boolean' value='true' migratable='yes'/>
+     <property name='avx2' type='boolean' value='false'/>
+     <property name='sep' type='boolean' value='true' migratable='yes'/>
+-    <property name='pclmuldq' type='boolean' value='true' migratable='yes'/>
+     <property name='virt-ssbd' type='boolean' value='false'/>
+-    <property name='x-hv-max-vps' type='number' value='-1'/>
+     <property name='nodeid-msr' type='boolean' value='false'/>
+     <property name='md-clear' type='boolean' value='false'/>
+-    <property name='kvm' type='boolean' value='true' migratable='yes'/>
+     <property name='misalignsse' type='boolean' value='false'/>
+     <property name='min-xlevel' type='number' value='2147483658'/>
+-    <property name='kvm-pv-unhalt' type='boolean' value='false'/>
+-    <property name='bmi2' type='boolean' value='true' migratable='yes'/>
+     <property name='bmi1' type='boolean' value='true' migratable='yes'/>
+-    <property name='realized' type='boolean' value='false'/>
+-    <property name='tsc_scale' type='boolean' value='false'/>
++    <property name='bmi2' type='boolean' value='true' migratable='yes'/>
++    <property name='kvm-pv-unhalt' type='boolean' value='false'/>
+     <property name='tsc-scale' type='boolean' value='false'/>
+     <property name='topoext' type='boolean' value='false'/>
+-    <property name='hv-vpindex' type='boolean' value='false'/>
+-    <property name='xlevel2' type='number' value='0'/>
+     <property name='clflushopt' type='boolean' value='true' migratable='yes'/>
+-    <property name='kvm-no-smi-migration' type='boolean' value='false'/>
+     <property name='monitor' type='boolean' value='true' migratable='yes'/>
+     <property name='avx512er' type='boolean' value='false'/>
+     <property name='pmm-en' type='boolean' value='false'/>
+@@ -733,25 +591,18 @@
+     <property name='3dnow' type='boolean' value='true' migratable='yes'/>
+     <property name='erms' type='boolean' value='true' migratable='yes'/>
+     <property name='lahf-lm' type='boolean' value='true' migratable='yes'/>
+-    <property name='lahf_lm' type='boolean' value='true' migratable='yes'/>
+     <property name='vpclmulqdq' type='boolean' value='false'/>
+     <property name='fxsr-opt' type='boolean' value='false'/>
+-    <property name='hv-synic' type='boolean' value='false'/>
+     <property name='xstore' type='boolean' value='false'/>
+-    <property name='fxsr_opt' type='boolean' value='false'/>
+-    <property name='kvm-hint-dedicated' type='boolean' value='false'/>
+     <property name='rtm' type='boolean' value='false'/>
++    <property name='kvm-hint-dedicated' type='boolean' value='false'/>
+     <property name='lmce' type='boolean' value='false'/>
+-    <property name='hv-time' type='boolean' value='false'/>
+     <property name='perfctr-nb' type='boolean' value='false'/>
+-    <property name='perfctr_nb' type='boolean' value='false'/>
+-    <property name='ffxsr' type='boolean' value='false'/>
+-    <property name='hv-tlbflush' type='boolean' value='false'/>
+     <property name='rdrand' type='boolean' value='true' migratable='yes'/>
+     <property name='rdseed' type='boolean' value='false'/>
+     <property name='avx512-4vnniw' type='boolean' value='false'/>
+-    <property name='vmx' type='boolean' value='false'/>
+     <property name='vme' type='boolean' value='false'/>
++    <property name='vmx' type='boolean' value='false'/>
+     <property name='dtes64' type='boolean' value='false'/>
+     <property name='mtrr' type='boolean' value='true' migratable='yes'/>
+     <property name='rdtscp' type='boolean' value='true' migratable='yes'/>
+@@ -759,9 +610,8 @@
+     <property name='kvm-pv-tlb-flush' type='boolean' value='false'/>
+     <property name='tbm' type='boolean' value='false'/>
+     <property name='wdt' type='boolean' value='false'/>
+-    <property name='pause_filter' type='boolean' value='false'/>
+-    <property name='sha-ni' type='boolean' value='false'/>
+     <property name='model-id' type='string' value='QEMU TCG CPU version 2.5+'/>
++    <property name='sha-ni' type='boolean' value='false'/>
+     <property name='abm' type='boolean' value='true' migratable='yes'/>
+     <property name='avx512pf' type='boolean' value='false'/>
+     <property name='xstore-en' type='boolean' value='false'/>
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-qemu-Don-t-use-mem-prealloc-among-with-.prealloc-yes.patch b/SOURCES/libvirt-qemu-Don-t-use-mem-prealloc-among-with-.prealloc-yes.patch
new file mode 100644
index 0000000..9022eec
--- /dev/null
+++ b/SOURCES/libvirt-qemu-Don-t-use-mem-prealloc-among-with-.prealloc-yes.patch
@@ -0,0 +1,200 @@
+From af079d99de7c556c3b9bb10037dae90e0f23f38a Mon Sep 17 00:00:00 2001
+Message-Id: <af079d99de7c556c3b9bb10037dae90e0f23f38a@dist-git>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Tue, 18 Dec 2018 11:47:36 +0100
+Subject: [PATCH] qemu: Don't use -mem-prealloc among with .prealloc=yes
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1624223
+
+There are two ways to request memory preallocation on cmd line:
+-mem-prealloc and .prealloc attribute for a memory-backend-file.
+However, as it turns out it's not safe to use both at the same
+time. If -mem-prealloc is used then qemu will fully allocate the
+memory (this is done by actually touching every page that has
+been allocated). Then, if .prealloc=yes is specified,
+mbind(flags = MPOL_MF_STRICT | MPOL_MF_MOVE) is called which:
+
+a) has to (possibly) move the memory to a different NUMA node,
+b) can have no effect when hugepages are in play (thus ignoring user
+request to place memory on desired NUMA nodes).
+
+Prefer -mem-prealloc as it is more backward compatible
+compared to switching to "-numa node,memdev=  + -object
+memory-backend-file".
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Reviewed-by: John Ferlan <jferlan@redhat.com>
+(cherry picked from commit c658764decf357ef2a064f09235fb6b8bd027f8b)
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+
+Conflicts:
+src/qemu/qemu_command.c:
+src/qemu/qemu_domain.c:
+src/qemu/qemu_domain.h: Context mostly, the upstream code
+                        diverged.
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Message-Id: <37771aafbb9d1855721efde7ade34c7b98fb1fc7.1545129996.git.mprivozn@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/qemu/qemu_command.c                       | 26 ++++++++++++-------
+ src/qemu/qemu_domain.c                        |  7 +++++
+ src/qemu/qemu_domain.h                        |  3 +++
+ .../hugepages-numa-default-dimm.args          |  2 +-
+ 4 files changed, 28 insertions(+), 10 deletions(-)
+
+diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
+index fa2b904239..7ffc4358e3 100644
+--- a/src/qemu/qemu_command.c
++++ b/src/qemu/qemu_command.c
+@@ -3185,11 +3185,13 @@ qemuBuildMemoryBackendProps(virJSONValuePtr *backendProps,
+         if (useHugepage) {
+             if (qemuGetDomainHupageMemPath(def, cfg, pagesize, &memPath) < 0)
+                 goto cleanup;
+-            prealloc = true;
++            if (!priv->memPrealloc)
++                prealloc = true;
+         } else if (mem->nvdimmPath) {
+             if (VIR_STRDUP(memPath, mem->nvdimmPath) < 0)
+                 goto cleanup;
+-            prealloc = true;
++            if (!priv->memPrealloc)
++                prealloc = true;
+         } else {
+             /* We can have both pagesize and mem source. If that's the case,
+              * prefer hugepages as those are more specific. */
+@@ -7603,7 +7605,8 @@ qemuBuildSmpCommandLine(virCommandPtr cmd,
+ static int
+ qemuBuildMemPathStr(virQEMUDriverConfigPtr cfg,
+                     const virDomainDef *def,
+-                    virCommandPtr cmd)
++                    virCommandPtr cmd,
++                    qemuDomainObjPrivatePtr priv)
+ {
+     const long system_page_size = virGetSystemPageSizeKB();
+     char *mem_path = NULL;
+@@ -7624,8 +7627,10 @@ qemuBuildMemPathStr(virQEMUDriverConfigPtr cfg,
+     if (qemuGetDomainHupageMemPath(def, cfg, def->mem.hugepages[0].size, &mem_path) < 0)
+         return -1;
+ 
+-    if (def->mem.allocation != VIR_DOMAIN_MEMORY_ALLOCATION_IMMEDIATE)
++    if (def->mem.allocation != VIR_DOMAIN_MEMORY_ALLOCATION_IMMEDIATE) {
+         virCommandAddArgList(cmd, "-mem-prealloc", NULL);
++        priv->memPrealloc = true;
++    }
+ 
+     virCommandAddArgList(cmd, "-mem-path", mem_path, NULL);
+     VIR_FREE(mem_path);
+@@ -7638,7 +7643,8 @@ static int
+ qemuBuildMemCommandLine(virCommandPtr cmd,
+                         virQEMUDriverConfigPtr cfg,
+                         const virDomainDef *def,
+-                        virQEMUCapsPtr qemuCaps)
++                        virQEMUCapsPtr qemuCaps,
++                        qemuDomainObjPrivatePtr priv)
+ {
+     if (qemuDomainDefValidateMemoryHotplug(def, qemuCaps, NULL) < 0)
+         return -1;
+@@ -7657,15 +7663,17 @@ qemuBuildMemCommandLine(virCommandPtr cmd,
+                               virDomainDefGetMemoryInitial(def) / 1024);
+     }
+ 
+-    if (def->mem.allocation == VIR_DOMAIN_MEMORY_ALLOCATION_IMMEDIATE)
++    if (def->mem.allocation == VIR_DOMAIN_MEMORY_ALLOCATION_IMMEDIATE) {
+         virCommandAddArgList(cmd, "-mem-prealloc", NULL);
++        priv->memPrealloc = true;
++    }
+ 
+     /*
+      * Add '-mem-path' (and '-mem-prealloc') parameter here if
+      * the hugepages and no numa node is specified.
+      */
+     if (!virDomainNumaGetNodeCount(def->numa) &&
+-        qemuBuildMemPathStr(cfg, def, cmd) < 0)
++        qemuBuildMemPathStr(cfg, def, cmd, priv) < 0)
+         return -1;
+ 
+     if (def->mem.locked && !virQEMUCapsGet(qemuCaps, QEMU_CAPS_REALTIME_MLOCK)) {
+@@ -7772,7 +7780,7 @@ qemuBuildNumaArgStr(virQEMUDriverConfigPtr cfg,
+     }
+ 
+     if (!needBackend &&
+-        qemuBuildMemPathStr(cfg, def, cmd) < 0)
++        qemuBuildMemPathStr(cfg, def, cmd, priv) < 0)
+         goto cleanup;
+ 
+     for (i = 0; i < ncells; i++) {
+@@ -10445,7 +10453,7 @@ qemuBuildCommandLine(virQEMUDriverPtr driver,
+     if (!migrateURI && !snapshot && qemuDomainAlignMemorySizes(def) < 0)
+         goto error;
+ 
+-    if (qemuBuildMemCommandLine(cmd, cfg, def, qemuCaps) < 0)
++    if (qemuBuildMemCommandLine(cmd, cfg, def, qemuCaps, priv) < 0)
+         goto error;
+ 
+     if (qemuBuildSmpCommandLine(cmd, def) < 0)
+diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
+index 8604385aa2..95b84af78a 100644
+--- a/src/qemu/qemu_domain.c
++++ b/src/qemu/qemu_domain.c
+@@ -1936,6 +1936,8 @@ qemuDomainObjPrivateDataClear(qemuDomainObjPrivatePtr priv)
+     VIR_FREE(priv->libDir);
+     VIR_FREE(priv->channelTargetDir);
+ 
++    priv->memPrealloc = false;
++
+     /* remove automatic pinning data */
+     virBitmapFree(priv->autoNodeset);
+     priv->autoNodeset = NULL;
+@@ -2439,6 +2441,9 @@ qemuDomainObjPrivateXMLFormat(virBufferPtr buf,
+ 
+     qemuDomainObjPrivateXMLFormatPR(buf, priv);
+ 
++    if (priv->memPrealloc)
++        virBufferAddLit(buf, "<memPrealloc/>\n");
++
+     if (qemuDomainObjPrivateXMLFormatBlockjobs(buf, vm) < 0)
+         return -1;
+ 
+@@ -2934,6 +2939,8 @@ qemuDomainObjPrivateXMLParse(xmlXPathContextPtr ctxt,
+     if (qemuDomainObjPrivateXMLParseBlockjobs(priv, ctxt) < 0)
+         goto error;
+ 
++    priv->memPrealloc = virXPathBoolean("boolean(./memPrealloc)", ctxt) == 1;
++
+     return 0;
+ 
+  error:
+diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
+index cc406e3ca0..8463a8b706 100644
+--- a/src/qemu/qemu_domain.h
++++ b/src/qemu/qemu_domain.h
+@@ -367,6 +367,9 @@ struct _qemuDomainObjPrivate {
+     /* qemuProcessStartCPUs stores the reason for starting vCPUs here for the
+      * RESUME event handler to use it */
+     virDomainRunningReason runningReason;
++
++    /* true if global -mem-prealloc appears on cmd line */
++    bool memPrealloc;
+ };
+ 
+ # define QEMU_DOMAIN_PRIVATE(vm) \
+diff --git a/tests/qemuxml2argvdata/hugepages-numa-default-dimm.args b/tests/qemuxml2argvdata/hugepages-numa-default-dimm.args
+index 855966a137..e7294a0882 100644
+--- a/tests/qemuxml2argvdata/hugepages-numa-default-dimm.args
++++ b/tests/qemuxml2argvdata/hugepages-numa-default-dimm.args
+@@ -13,7 +13,7 @@ QEMU_AUDIO_DRV=none \
+ -mem-prealloc \
+ -mem-path /dev/hugepages2M/libvirt/qemu/-1-fedora \
+ -numa node,nodeid=0,cpus=0-1,mem=1024 \
+--object memory-backend-file,id=memdimm0,prealloc=yes,\
++-object memory-backend-file,id=memdimm0,\
+ mem-path=/dev/hugepages1G/libvirt/qemu/-1-fedora,size=1073741824,\
+ host-nodes=1-3,policy=bind \
+ -device pc-dimm,node=0,memdev=memdimm0,id=dimm0,slot=0 \
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-qemu-Drop-MSR-features-from-host-model-with-old-QEMU.patch b/SOURCES/libvirt-qemu-Drop-MSR-features-from-host-model-with-old-QEMU.patch
new file mode 100644
index 0000000..da33e42
--- /dev/null
+++ b/SOURCES/libvirt-qemu-Drop-MSR-features-from-host-model-with-old-QEMU.patch
@@ -0,0 +1,65 @@
+From 360c3ee173809822e9363ec210a8197b66511a03 Mon Sep 17 00:00:00 2001
+Message-Id: <360c3ee173809822e9363ec210a8197b66511a03@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:26:12 +0200
+Subject: [PATCH] qemu: Drop MSR features from host-model with old QEMU
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+With QEMU versions which lack "unavailable-features" we use CPUID based
+detection of features which were enabled or disabled once QEMU starts.
+Thus using MSR features with host-model would result in all of them
+being marked as disabled in the active domain definition even though
+QEMU did not actually disable them.
+
+Let's make sure we add MSR features to host-model only when
+"unavailable-features" property is supported by QEMU.
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit 2674d00ed484091faf2b6e6b1efe58ee9a72b96b)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1697627
+
+Conflicts:
+	tests/domaincapsschemadata/qemu_3.1.0.x86_64.xml
+	tests/domaincapsschemadata/qemu_4.0.0.x86_64.xml
+            - missing
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <b7d9dd2f26053edb58fb8c3079334c2a494d07f9.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/qemu/qemu_capabilities.c | 15 +++++++++++++++
+ 1 file changed, 15 insertions(+)
+
+diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
+index 4be0ec305f..fbfe74d45b 100644
+--- a/src/qemu/qemu_capabilities.c
++++ b/src/qemu/qemu_capabilities.c
+@@ -3114,6 +3114,21 @@ virQEMUCapsInitHostCPUModel(virQEMUCapsPtr qemuCaps,
+             goto error;
+     }
+ 
++    if (ARCH_IS_X86(qemuCaps->arch) &&
++        !virQEMUCapsGet(qemuCaps, QEMU_CAPS_CPU_UNAVAILABLE_FEATURES)) {
++        if (cpu &&
++            virCPUDefFilterFeatures(cpu, virCPUx86FeatureFilterDropMSR, NULL) < 0)
++            goto error;
++
++        if (migCPU &&
++            virCPUDefFilterFeatures(migCPU, virCPUx86FeatureFilterDropMSR, NULL) < 0)
++            goto error;
++
++        if (fullCPU &&
++            virCPUDefFilterFeatures(fullCPU, virCPUx86FeatureFilterDropMSR, NULL) < 0)
++            goto error;
++    }
++
+     virQEMUCapsSetHostModel(qemuCaps, type, cpu, migCPU, fullCPU);
+ 
+  cleanup:
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-qemu-Drop-cleanup-label-from-qemuProcessInitCpuAffinity.patch b/SOURCES/libvirt-qemu-Drop-cleanup-label-from-qemuProcessInitCpuAffinity.patch
new file mode 100644
index 0000000..1923e7f
--- /dev/null
+++ b/SOURCES/libvirt-qemu-Drop-cleanup-label-from-qemuProcessInitCpuAffinity.patch
@@ -0,0 +1,74 @@
+From fa5cf4f38c5310ac24adf2011777c21827c3a727 Mon Sep 17 00:00:00 2001
+Message-Id: <fa5cf4f38c5310ac24adf2011777c21827c3a727@dist-git>
+From: Andrea Bolognani <abologna@redhat.com>
+Date: Tue, 11 Jun 2019 10:55:05 +0200
+Subject: [PATCH] qemu: Drop cleanup label from qemuProcessInitCpuAffinity()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+We're using VIR_AUTOPTR() for everything now, plus the
+cleanup section was not doing anything useful anyway.
+
+Signed-off-by: Andrea Bolognani <abologna@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit de563ebcf9d72e5815933a0d715aa9c462bf50cc)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1716908
+
+Signed-off-by: Andrea Bolognani <abologna@redhat.com>
+Message-Id: <20190611085506.12564-6-abologna@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/qemu/qemu_process.c | 18 ++++++++----------
+ 1 file changed, 8 insertions(+), 10 deletions(-)
+
+diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
+index 0b2b7964e1..d0945b9c65 100644
+--- a/src/qemu/qemu_process.c
++++ b/src/qemu/qemu_process.c
+@@ -2356,7 +2356,6 @@ qemuProcessGetAllCpuAffinity(virBitmapPtr *cpumapRet)
+ static int
+ qemuProcessInitCpuAffinity(virDomainObjPtr vm)
+ {
+-    int ret = -1;
+     VIR_AUTOPTR(virBitmap) cpumapToSet = NULL;
+     virDomainNumatuneMemMode mem_mode;
+     qemuDomainObjPrivatePtr priv = vm->privateData;
+@@ -2387,25 +2386,24 @@ qemuProcessInitCpuAffinity(virDomainObjPtr vm)
+                                              priv->autoNodeset,
+                                              &nodeset,
+                                              -1) < 0)
+-            goto cleanup;
++            return -1;
+ 
+         if (virNumaNodesetToCPUset(nodeset, &cpumapToSet) < 0)
+-            goto cleanup;
++            return -1;
+     } else if (vm->def->cputune.emulatorpin) {
+         if (virBitmapCopy(cpumapToSet, vm->def->cputune.emulatorpin) < 0)
+-            goto cleanup;
++            return -1;
+     } else {
+         if (qemuProcessGetAllCpuAffinity(&cpumapToSet) < 0)
+-            goto cleanup;
++            return -1;
+     }
+ 
+     if (cpumapToSet &&
+-        virProcessSetAffinity(vm->pid, cpumapToSet) < 0)
+-        goto cleanup;
++        virProcessSetAffinity(vm->pid, cpumapToSet) < 0) {
++        return -1;
++    }
+ 
+-    ret = 0;
+- cleanup:
+-    return ret;
++    return 0;
+ }
+ 
+ /* set link states to down on interfaces at qemu start */
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-qemu-Drop-user-prefix-for-guestfwd-netdev.patch b/SOURCES/libvirt-qemu-Drop-user-prefix-for-guestfwd-netdev.patch
new file mode 100644
index 0000000..d953baa
--- /dev/null
+++ b/SOURCES/libvirt-qemu-Drop-user-prefix-for-guestfwd-netdev.patch
@@ -0,0 +1,65 @@
+From 582d5e7db59ec7897dc0a2a78823860963be9855 Mon Sep 17 00:00:00 2001
+Message-Id: <582d5e7db59ec7897dc0a2a78823860963be9855@dist-git>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Thu, 27 Jun 2019 14:44:45 +0200
+Subject: [PATCH] qemu: Drop "user-" prefix for guestfwd netdev
+
+Introduced by d86c876a66e3.
+
+There is no real need to have "user-" prefix for chardev.
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Reviewed-by: John Ferlan <jferlan@redhat.com>
+(cherry picked from commit 18b8f677456714f04b87525602fa2b62cd4224e1)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1624204
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Message-Id: <f9a2801659530438c1253c63a9d754bf46825bfe.1561639408.git.mprivozn@redhat.com>
+Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/qemu/qemu_command.c                      | 2 +-
+ tests/qemuxml2argvdata/channel-guestfwd.args | 2 +-
+ tests/qemuxml2argvdata/name-escape.args      | 2 +-
+ 3 files changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
+index b5c0588e3c..2b885e98dd 100644
+--- a/src/qemu/qemu_command.c
++++ b/src/qemu/qemu_command.c
+@@ -10737,7 +10737,7 @@ qemuBuildChannelChrDeviceStr(char **deviceStr,
+         port = virSocketAddrGetPort(chr->target.addr);
+ 
+         if (virAsprintf(deviceStr,
+-                        "user,guestfwd=tcp:%s:%i-chardev:char%s,id=user-%s",
++                        "user,guestfwd=tcp:%s:%i-chardev:char%s,id=%s",
+                         addr, port, chr->info.alias, chr->info.alias) < 0)
+             goto cleanup;
+         break;
+diff --git a/tests/qemuxml2argvdata/channel-guestfwd.args b/tests/qemuxml2argvdata/channel-guestfwd.args
+index 6a660f7796..b4c857a6d7 100644
+--- a/tests/qemuxml2argvdata/channel-guestfwd.args
++++ b/tests/qemuxml2argvdata/channel-guestfwd.args
+@@ -25,5 +25,5 @@ server,nowait \
+ -drive file=/dev/HostVG/QEMUGuest1,format=raw,if=none,id=drive-ide0-0-0 \
+ -device ide-drive,bus=ide.0,unit=0,drive=drive-ide0-0-0,id=ide0-0-0 \
+ -chardev pipe,id=charchannel0,path=/tmp/guestfwd \
+--netdev user,guestfwd=tcp:10.0.2.1:4600-chardev:charchannel0,id=user-channel0 \
++-netdev user,guestfwd=tcp:10.0.2.1:4600-chardev:charchannel0,id=channel0 \
+ -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3
+diff --git a/tests/qemuxml2argvdata/name-escape.args b/tests/qemuxml2argvdata/name-escape.args
+index 382b8a1a9e..cbf594e808 100644
+--- a/tests/qemuxml2argvdata/name-escape.args
++++ b/tests/qemuxml2argvdata/name-escape.args
+@@ -37,7 +37,7 @@ cert3=cert3,db=/etc/pki/nssdb,,foo,id=smartcard0,bus=ccid0.0 \
+ -chardev file,id=charserial1,path=/tmp/serial.log,,foo,append=on \
+ -device isa-serial,chardev=charserial1,id=serial1 \
+ -chardev pipe,id=charchannel0,path=/tmp/guestfwd,,foo \
+--netdev user,guestfwd=tcp:10.0.2.1:4600-chardev:charchannel0,id=user-channel0 \
++-netdev user,guestfwd=tcp:10.0.2.1:4600-chardev:charchannel0,id=channel0 \
+ -vnc unix:/tmp/lib/domain--1-foo=1,,bar=2/vnc.sock \
+ -spice unix,addr=/tmp/lib/domain--1-foo=1,,bar=2/spice.sock,gl=on,\
+ rendernode=/dev/dri/foo,,bar \
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-qemu-Enable-PCI-multi-bus-for-S390-guests.patch b/SOURCES/libvirt-qemu-Enable-PCI-multi-bus-for-S390-guests.patch
new file mode 100644
index 0000000..c0f103b
--- /dev/null
+++ b/SOURCES/libvirt-qemu-Enable-PCI-multi-bus-for-S390-guests.patch
@@ -0,0 +1,54 @@
+From 2c4fb8fc19d1dd6ef8fafdfb1e48998020a368cd Mon Sep 17 00:00:00 2001
+Message-Id: <2c4fb8fc19d1dd6ef8fafdfb1e48998020a368cd@dist-git>
+From: Yi Min Zhao <zyimin@linux.ibm.com>
+Date: Mon, 8 Apr 2019 10:57:20 +0200
+Subject: [PATCH] qemu: Enable PCI multi bus for S390 guests
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+QEMU on s390 supports PCI multibus since forever.
+
+Signed-off-by: Yi Min Zhao <zyimin@linux.ibm.com>
+Reviewed-by: Boris Fiuczynski <fiuczy@linux.ibm.com>
+Reviewed-by: Stefan Zimmermann <stzi@linux.ibm.com>
+Reviewed-by: Bjoern Walk <bwalk@linux.ibm.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Reviewed-by: Andrea Bolognani <abologna@redhat.com>
+
+(cherry picked from commit f49a5e3bf4c275ddb8a60274d6ab941b2f99f553)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1508149
+
+Conflicts:
+
+  * src/qemu/qemu_capabilities.c
+    + context
+      - missing fa95035bd4c9
+
+Signed-off-by: Andrea Bolognani <abologna@redhat.com>
+Message-Id: <20190408085732.28684-4-abologna@redhat.com>
+Reviewed-by: Laine Stump <laine@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/qemu/qemu_capabilities.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
+index 8ca53abf2b..5539d168cd 100644
+--- a/src/qemu/qemu_capabilities.c
++++ b/src/qemu/qemu_capabilities.c
+@@ -1803,6 +1803,10 @@ bool virQEMUCapsHasPCIMultiBus(virQEMUCapsPtr qemuCaps,
+         return false;
+     }
+ 
++    /* S390 supports PCI-multibus. */
++    if (ARCH_IS_S390(def->os.arch))
++        return true;
++
+     /* If 'virt' supports PCI, it supports multibus.
+      * No extra conditions here for simplicity.
+      */
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-qemu-Fix-NULL-pointer-access-in-qemuProcessInitCpuAffinity.patch b/SOURCES/libvirt-qemu-Fix-NULL-pointer-access-in-qemuProcessInitCpuAffinity.patch
new file mode 100644
index 0000000..40014e2
--- /dev/null
+++ b/SOURCES/libvirt-qemu-Fix-NULL-pointer-access-in-qemuProcessInitCpuAffinity.patch
@@ -0,0 +1,47 @@
+From aa0f66af1237656b217f640a9877d5f1aa31cb41 Mon Sep 17 00:00:00 2001
+Message-Id: <aa0f66af1237656b217f640a9877d5f1aa31cb41@dist-git>
+From: Andrea Bolognani <abologna@redhat.com>
+Date: Tue, 11 Jun 2019 10:55:06 +0200
+Subject: [PATCH] qemu: Fix NULL pointer access in qemuProcessInitCpuAffinity()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Commit 2f2254c7f4e5 attempted to fix a memory leak by ensuring
+cpumapToSet is always a freshly allocated bitmap, but regrettably
+introduced a NULL pointer access while doing so, because it called
+virBitmapCopy() without allocating the destination bitmap first.
+
+Solve the issue by using virBitmapNewCopy() instead.
+
+Reported-by: John Ferlan <jferlan@redhat.com>
+Signed-off-by: Andrea Bolognani <abologna@redhat.com>
+Reviewed-by: Erik Skultety <eskultet@redhat.com>
+Reviewed-by: John Ferlan <jferlan@redhat.com>
+(cherry picked from commit a84922c09e9e1a0ca4f8fb1e8b4b1c7b55bd79e9)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1716908
+
+Signed-off-by: Andrea Bolognani <abologna@redhat.com>
+Message-Id: <20190611085506.12564-7-abologna@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/qemu/qemu_process.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
+index d0945b9c65..c220accfaf 100644
+--- a/src/qemu/qemu_process.c
++++ b/src/qemu/qemu_process.c
+@@ -2391,7 +2391,7 @@ qemuProcessInitCpuAffinity(virDomainObjPtr vm)
+         if (virNumaNodesetToCPUset(nodeset, &cpumapToSet) < 0)
+             return -1;
+     } else if (vm->def->cputune.emulatorpin) {
+-        if (virBitmapCopy(cpumapToSet, vm->def->cputune.emulatorpin) < 0)
++        if (!(cpumapToSet = virBitmapNewCopy(vm->def->cputune.emulatorpin)))
+             return -1;
+     } else {
+         if (qemuProcessGetAllCpuAffinity(&cpumapToSet) < 0)
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-qemu-Fix-leak-in-qemuProcessInitCpuAffinity.patch b/SOURCES/libvirt-qemu-Fix-leak-in-qemuProcessInitCpuAffinity.patch
new file mode 100644
index 0000000..b40ca14
--- /dev/null
+++ b/SOURCES/libvirt-qemu-Fix-leak-in-qemuProcessInitCpuAffinity.patch
@@ -0,0 +1,65 @@
+From 4c58428a2aebd952f7412ec1f4afa3045a09dff7 Mon Sep 17 00:00:00 2001
+Message-Id: <4c58428a2aebd952f7412ec1f4afa3045a09dff7@dist-git>
+From: Andrea Bolognani <abologna@redhat.com>
+Date: Tue, 11 Jun 2019 10:55:04 +0200
+Subject: [PATCH] qemu: Fix leak in qemuProcessInitCpuAffinity()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+In two out of three scenarios we are cleaning up properly after
+ourselves, but commit 5f2212c062c7 has changed the remaining one
+in a way that caused it to start leaking cpumapToSet.
+
+Refactor the logic so that cpumapToSet is always a freshly
+allocated bitmap that gets cleaned up automatically thanks to
+VIR_AUTOPTR(); this also allows us to remove the hostcpumap
+variable.
+
+Reported-by: John Ferlan <jferlan@redhat.com>
+Signed-off-by: Andrea Bolognani <abologna@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit 2f2254c7f4e5bff52ea62a77831230bebc076bab)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1716908
+
+Signed-off-by: Andrea Bolognani <abologna@redhat.com>
+Message-Id: <20190611085506.12564-5-abologna@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/qemu/qemu_process.c | 11 +++++------
+ 1 file changed, 5 insertions(+), 6 deletions(-)
+
+diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
+index a3b71354e1..0b2b7964e1 100644
+--- a/src/qemu/qemu_process.c
++++ b/src/qemu/qemu_process.c
+@@ -2357,8 +2357,7 @@ static int
+ qemuProcessInitCpuAffinity(virDomainObjPtr vm)
+ {
+     int ret = -1;
+-    virBitmapPtr cpumapToSet = NULL;
+-    VIR_AUTOPTR(virBitmap) hostcpumap = NULL;
++    VIR_AUTOPTR(virBitmap) cpumapToSet = NULL;
+     virDomainNumatuneMemMode mem_mode;
+     qemuDomainObjPrivatePtr priv = vm->privateData;
+ 
+@@ -2393,11 +2392,11 @@ qemuProcessInitCpuAffinity(virDomainObjPtr vm)
+         if (virNumaNodesetToCPUset(nodeset, &cpumapToSet) < 0)
+             goto cleanup;
+     } else if (vm->def->cputune.emulatorpin) {
+-        cpumapToSet = vm->def->cputune.emulatorpin;
+-    } else {
+-        if (qemuProcessGetAllCpuAffinity(&hostcpumap) < 0)
++        if (virBitmapCopy(cpumapToSet, vm->def->cputune.emulatorpin) < 0)
++            goto cleanup;
++    } else {
++        if (qemuProcessGetAllCpuAffinity(&cpumapToSet) < 0)
+             goto cleanup;
+-        cpumapToSet = hostcpumap;
+     }
+ 
+     if (cpumapToSet &&
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-qemu-Fix-qemuProcessInitCpuAffinity.patch b/SOURCES/libvirt-qemu-Fix-qemuProcessInitCpuAffinity.patch
new file mode 100644
index 0000000..23fd6a3
--- /dev/null
+++ b/SOURCES/libvirt-qemu-Fix-qemuProcessInitCpuAffinity.patch
@@ -0,0 +1,76 @@
+From 607f70a5d24d2df9c63861434c4ba1991226ee34 Mon Sep 17 00:00:00 2001
+Message-Id: <607f70a5d24d2df9c63861434c4ba1991226ee34@dist-git>
+From: Andrea Bolognani <abologna@redhat.com>
+Date: Tue, 11 Jun 2019 10:55:03 +0200
+Subject: [PATCH] qemu: Fix qemuProcessInitCpuAffinity()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Ever since the feature was introduced with commit 0f8e7ae33ace,
+it has contained a logic error in that it attempted to use a NUMA
+node map where a CPU map was expected.
+
+Because of that, guests using <numatune> might fail to start:
+
+  # virsh start guest
+  error: Failed to start domain guest
+  error: cannot set CPU affinity on process 40055: Invalid argument
+
+This was particularly easy to trigger on POWER 8 machines, where
+secondary threads always show up as offline in the host: having
+
+  <numatune>
+    <memory mode='strict' placement='static' nodeset='1'/>
+  </numatune>
+
+in the guest configuration, for example, would result in libvirt
+trying to set the process affinity so that it would prefer
+running on CPU 1, but since that's a secondary thread and thus
+shows up as offline, the operation would fail, and so would
+starting the guest.
+
+Use the newly introduced virNumaNodesetToCPUset() to convert the
+NUMA node map to a CPU map, which in the example above would be
+48,56,64,72,80,88 - a valid input for virProcessSetAffinity().
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1703661
+
+Signed-off-by: Andrea Bolognani <abologna@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit 5f2212c062c720716b7701fa0a5511311dc6e906)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1716908
+
+Signed-off-by: Andrea Bolognani <abologna@redhat.com>
+Message-Id: <20190611085506.12564-4-abologna@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/qemu/qemu_process.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
+index 8b05cef80c..a3b71354e1 100644
+--- a/src/qemu/qemu_process.c
++++ b/src/qemu/qemu_process.c
+@@ -2382,11 +2382,16 @@ qemuProcessInitCpuAffinity(virDomainObjPtr vm)
+     if (virDomainNumaGetNodeCount(vm->def->numa) <= 1 &&
+         virDomainNumatuneGetMode(vm->def->numa, -1, &mem_mode) == 0 &&
+         mem_mode == VIR_DOMAIN_NUMATUNE_MEM_STRICT) {
++        virBitmapPtr nodeset = NULL;
++
+         if (virDomainNumatuneMaybeGetNodeset(vm->def->numa,
+                                              priv->autoNodeset,
+-                                             &cpumapToSet,
++                                             &nodeset,
+                                              -1) < 0)
+             goto cleanup;
++
++        if (virNumaNodesetToCPUset(nodeset, &cpumapToSet) < 0)
++            goto cleanup;
+     } else if (vm->def->cputune.emulatorpin) {
+         cpumapToSet = vm->def->cputune.emulatorpin;
+     } else {
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-qemu-Forbid-MSR-features-with-old-QEMU.patch b/SOURCES/libvirt-qemu-Forbid-MSR-features-with-old-QEMU.patch
new file mode 100644
index 0000000..9370639
--- /dev/null
+++ b/SOURCES/libvirt-qemu-Forbid-MSR-features-with-old-QEMU.patch
@@ -0,0 +1,80 @@
+From e4f000025ac57ed4c731ffb0939f2e02bb84d856 Mon Sep 17 00:00:00 2001
+Message-Id: <e4f000025ac57ed4c731ffb0939f2e02bb84d856@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:26:11 +0200
+Subject: [PATCH] qemu: Forbid MSR features with old QEMU
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Without "unavailable-features" CPU property we cannot properly detect
+whether a specific MSR feature we asked for (either explicitly or
+implicitly via a CPU model) was disabled by QEMU for some reason.
+Because this could break migration, snapshots, and save/restore
+operaions, it's better to just forbid any use of MSR features with QEMU
+which lacks "unavailable-features" CPU property.
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit 8eb4a89f5f7973f50aa8b6fa0b1a45b825dda208)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1697627
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <b077794613a01d8ebd69b27afef1ad2452a4810d.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/qemu/qemu_process.c | 30 +++++++++++++++++++++++++++---
+ 1 file changed, 27 insertions(+), 3 deletions(-)
+
+diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
+index d147e524ee..db14d322f5 100644
+--- a/src/qemu/qemu_process.c
++++ b/src/qemu/qemu_process.c
+@@ -53,6 +53,7 @@
+ #include "qemu_extdevice.h"
+ 
+ #include "cpu/cpu.h"
++#include "cpu/cpu_x86.h"
+ #include "datatypes.h"
+ #include "virlog.h"
+ #include "virerror.h"
+@@ -5226,9 +5227,32 @@ qemuProcessStartValidate(virQEMUDriverPtr driver,
+     if (qemuProcessStartValidateShmem(vm) < 0)
+         return -1;
+ 
+-    if (vm->def->cpu &&
+-        virCPUValidateFeatures(vm->def->os.arch, vm->def->cpu) < 0)
+-        return -1;
++    if (vm->def->cpu) {
++        if (virCPUValidateFeatures(vm->def->os.arch, vm->def->cpu) < 0)
++            return -1;
++
++        if (ARCH_IS_X86(vm->def->os.arch) &&
++            !virQEMUCapsGet(qemuCaps, QEMU_CAPS_CPU_UNAVAILABLE_FEATURES)) {
++            VIR_AUTOSTRINGLIST features = NULL;
++            int n;
++
++            if ((n = virCPUDefCheckFeatures(vm->def->cpu,
++                                            virCPUx86FeatureFilterSelectMSR,
++                                            NULL,
++                                            &features)) < 0)
++                return -1;
++
++            if (n > 0) {
++                VIR_AUTOFREE(char *) str = NULL;
++
++                str = virStringListJoin((const char **)features, ", ");
++                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
++                               _("Some features cannot be reliably used "
++                                 "with this QEMU: %s"), str);
++                return -1;
++            }
++        }
++    }
+ 
+     if (qemuProcessStartValidateDisks(vm, qemuCaps) < 0)
+         return -1;
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-qemu-Generate-and-use-zPCI-device-in-QEMU-command-line.patch b/SOURCES/libvirt-qemu-Generate-and-use-zPCI-device-in-QEMU-command-line.patch
new file mode 100644
index 0000000..f403a75
--- /dev/null
+++ b/SOURCES/libvirt-qemu-Generate-and-use-zPCI-device-in-QEMU-command-line.patch
@@ -0,0 +1,834 @@
+From 37f8c26d43550986a8c6467aef4bf9d1ebe3a683 Mon Sep 17 00:00:00 2001
+Message-Id: <37f8c26d43550986a8c6467aef4bf9d1ebe3a683@dist-git>
+From: Yi Min Zhao <zyimin@linux.ibm.com>
+Date: Mon, 8 Apr 2019 10:57:28 +0200
+Subject: [PATCH] qemu: Generate and use zPCI device in QEMU command line
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Add new functions to generate zPCI command string and append it to
+QEMU command line. And the related tests are added.
+
+Signed-off-by: Yi Min Zhao <zyimin@linux.ibm.com>
+Reviewed-by: Boris Fiuczynski <fiuczy@linux.ibm.com>
+Reviewed-by: Stefan Zimmermann <stzi@linux.ibm.com>
+Reviewed-by: Bjoern Walk <bwalk@linux.ibm.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Reviewed-by: Andrea Bolognani <abologna@redhat.com>
+
+(cherry picked from commit 9d6be3ff79b4ce7588e2842d4a6c3e713a97a7ec)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1508149
+
+Conflicts:
+
+  * src/qemu/qemu_command.c
+    + context in qemuBuildInterfaceCommandLine()
+      - missing 4de4e4bc9911
+    + context in qemuBuildDiskCommandLine()
+      - missing b8936d265518
+
+  * tests/qemuxml2argvdata/hostdev-vfio-zpci.args
+    + no -boot in output
+      - missing caccbba64aa9
+
+Changes
+
+  * tests/qemuxml2argvdata/hostdev-vfio-zpci-autogenerate.args
+    tests/qemuxml2argvdata/hostdev-vfio-zpci-boundaries.args
+    tests/qemuxml2argvdata/hostdev-vfio-zpci-multidomain-many.args
+    + no -boot in output
+      - missing caccbba64aa9
+
+Signed-off-by: Andrea Bolognani <abologna@redhat.com>
+Message-Id: <20190408085732.28684-12-abologna@redhat.com>
+Reviewed-by: Laine Stump <laine@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/qemu/qemu_command.c                       | 104 ++++++++++++++++++
+ src/qemu/qemu_command.h                       |   2 +
+ .../disk-virtio-s390-zpci.args                |   1 +
+ .../hostdev-vfio-zpci-autogenerate.args       |  26 +++++
+ .../hostdev-vfio-zpci-autogenerate.xml        |  18 +++
+ .../hostdev-vfio-zpci-boundaries.args         |  30 +++++
+ .../hostdev-vfio-zpci-boundaries.xml          |  30 +++++
+ .../hostdev-vfio-zpci-multidomain-many.args   |  40 +++++++
+ .../hostdev-vfio-zpci-multidomain-many.xml    |  79 +++++++++++++
+ tests/qemuxml2argvdata/hostdev-vfio-zpci.args |   2 +
+ tests/qemuxml2argvtest.c                      |  13 +++
+ .../hostdev-vfio-zpci-autogenerate.xml        |  34 ++++++
+ .../hostdev-vfio-zpci-boundaries.xml          |  48 ++++++++
+ .../hostdev-vfio-zpci-multidomain-many.xml    |  97 ++++++++++++++++
+ tests/qemuxml2xmltest.c                       |  11 ++
+ 15 files changed, 535 insertions(+)
+ create mode 100644 tests/qemuxml2argvdata/hostdev-vfio-zpci-autogenerate.args
+ create mode 100644 tests/qemuxml2argvdata/hostdev-vfio-zpci-autogenerate.xml
+ create mode 100644 tests/qemuxml2argvdata/hostdev-vfio-zpci-boundaries.args
+ create mode 100644 tests/qemuxml2argvdata/hostdev-vfio-zpci-boundaries.xml
+ create mode 100644 tests/qemuxml2argvdata/hostdev-vfio-zpci-multidomain-many.args
+ create mode 100644 tests/qemuxml2argvdata/hostdev-vfio-zpci-multidomain-many.xml
+ create mode 100644 tests/qemuxml2xmloutdata/hostdev-vfio-zpci-autogenerate.xml
+ create mode 100644 tests/qemuxml2xmloutdata/hostdev-vfio-zpci-boundaries.xml
+ create mode 100644 tests/qemuxml2xmloutdata/hostdev-vfio-zpci-multidomain-many.xml
+
+diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
+index a8c832bad8..c06f396b44 100644
+--- a/src/qemu/qemu_command.c
++++ b/src/qemu/qemu_command.c
+@@ -2147,6 +2147,57 @@ qemuBuildDriveDevStr(const virDomainDef *def,
+     return NULL;
+ }
+ 
++char *
++qemuBuildZPCIDevStr(virDomainDeviceInfoPtr dev)
++{
++    virBuffer buf = VIR_BUFFER_INITIALIZER;
++
++    virBufferAsprintf(&buf,
++                      "zpci,uid=%u,fid=%u,target=%s,id=zpci%u",
++                      dev->addr.pci.zpci.uid,
++                      dev->addr.pci.zpci.fid,
++                      dev->alias,
++                      dev->addr.pci.zpci.uid);
++
++    if (virBufferCheckError(&buf) < 0) {
++        virBufferFreeAndReset(&buf);
++        return NULL;
++    }
++
++    return virBufferContentAndReset(&buf);
++}
++
++static int
++qemuCommandAddZPCIDevice(virCommandPtr cmd,
++                         virDomainDeviceInfoPtr dev)
++{
++    char *devstr = NULL;
++
++    virCommandAddArg(cmd, "-device");
++
++    if (!(devstr = qemuBuildZPCIDevStr(dev)))
++        return -1;
++
++    virCommandAddArg(cmd, devstr);
++
++    VIR_FREE(devstr);
++    return 0;
++}
++
++static int
++qemuCommandAddExtDevice(virCommandPtr cmd,
++                        virDomainDeviceInfoPtr dev)
++{
++    if (dev->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI ||
++        dev->addr.pci.extFlags == VIR_PCI_ADDRESS_EXTENSION_NONE) {
++        return 0;
++    }
++
++    if (dev->addr.pci.extFlags & VIR_PCI_ADDRESS_EXTENSION_ZPCI)
++        return qemuCommandAddZPCIDevice(cmd, dev);
++
++    return 0;
++}
+ 
+ static int
+ qemuBulildFloppyCommandLineOptions(virCommandPtr cmd,
+@@ -2267,6 +2318,9 @@ qemuBuildDiskCommandLine(virCommandPtr cmd,
+                                                    bootindex) < 0)
+                 return -1;
+         } else {
++            if (qemuCommandAddExtDevice(cmd, &disk->info) < 0)
++                return -1;
++
+             virCommandAddArg(cmd, "-device");
+ 
+             if (!(optstr = qemuBuildDriveDevStr(def, disk, bootindex,
+@@ -2466,6 +2520,9 @@ qemuBuildFSDevCommandLine(virCommandPtr cmd,
+         virCommandAddArg(cmd, optstr);
+         VIR_FREE(optstr);
+ 
++        if (qemuCommandAddExtDevice(cmd, &fs->info) < 0)
++            return -1;
++
+         virCommandAddArg(cmd, "-device");
+         if (!(optstr = qemuBuildFSDevStr(def, fs, qemuCaps)))
+             return -1;
+@@ -2950,6 +3007,11 @@ qemuBuildControllerDevCommandLine(virCommandPtr cmd,
+                 goto cleanup;
+ 
+             if (devstr) {
++                if (qemuCommandAddExtDevice(cmd, &cont->info) < 0) {
++                    VIR_FREE(devstr);
++                    goto cleanup;
++                }
++
+                 virCommandAddArg(cmd, "-device");
+                 virCommandAddArg(cmd, devstr);
+                 VIR_FREE(devstr);
+@@ -3753,6 +3815,9 @@ qemuBuildWatchdogCommandLine(virCommandPtr cmd,
+     if (!def->watchdog)
+         return 0;
+ 
++    if (qemuCommandAddExtDevice(cmd, &def->watchdog->info) < 0)
++        return -1;
++
+     virCommandAddArg(cmd, "-device");
+ 
+     optstr = qemuBuildWatchdogDevStr(def, watchdog, qemuCaps);
+@@ -3837,6 +3902,9 @@ qemuBuildMemballoonCommandLine(virCommandPtr cmd,
+     if (qemuBuildVirtioOptionsStr(&buf, def->memballoon->virtio, qemuCaps) < 0)
+         goto error;
+ 
++    if (qemuCommandAddExtDevice(cmd, &def->memballoon->info) < 0)
++        goto error;
++
+     virCommandAddArg(cmd, "-device");
+     virCommandAddArgBuffer(cmd, &buf);
+     return 0;
+@@ -4059,6 +4127,9 @@ qemuBuildInputCommandLine(virCommandPtr cmd,
+         virDomainInputDefPtr input = def->inputs[i];
+         char *devstr = NULL;
+ 
++        if (qemuCommandAddExtDevice(cmd, &input->info) < 0)
++            return -1;
++
+         if (qemuBuildInputDevStr(&devstr, def, input, qemuCaps) < 0)
+             return -1;
+ 
+@@ -4200,6 +4271,9 @@ qemuBuildSoundCommandLine(virCommandPtr cmd,
+         if (sound->model == VIR_DOMAIN_SOUND_MODEL_PCSPK) {
+             virCommandAddArgList(cmd, "-soundhw", "pcspk", NULL);
+         } else {
++            if (qemuCommandAddExtDevice(cmd, &sound->info) < 0)
++                return -1;
++
+             virCommandAddArg(cmd, "-device");
+             if (!(str = qemuBuildSoundDevStr(def, sound, qemuCaps)))
+                 return -1;
+@@ -4439,6 +4513,10 @@ qemuBuildVideoCommandLine(virCommandPtr cmd,
+         if (video->primary) {
+             if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_DEVICE_VIDEO_PRIMARY)) {
+ 
++                if (qemuCommandAddExtDevice(cmd,
++                                            &def->videos[i]->info) < 0)
++                    return -1;
++
+                 virCommandAddArg(cmd, "-device");
+ 
+                 if (!(str = qemuBuildDeviceVideoStr(def, video, qemuCaps)))
+@@ -4451,6 +4529,9 @@ qemuBuildVideoCommandLine(virCommandPtr cmd,
+                     return -1;
+             }
+         } else {
++            if (qemuCommandAddExtDevice(cmd, &def->videos[i]->info) < 0)
++                return -1;
++
+             virCommandAddArg(cmd, "-device");
+ 
+             if (!(str = qemuBuildDeviceVideoStr(def, video, qemuCaps)))
+@@ -5328,6 +5409,10 @@ qemuBuildHostdevCommandLine(virCommandPtr cmd,
+                                      VIR_COMMAND_PASS_FD_CLOSE_PARENT);
+                 }
+             }
++
++            if (qemuCommandAddExtDevice(cmd, hostdev->info) < 0)
++                return -1;
++
+             virCommandAddArg(cmd, "-device");
+             devstr = qemuBuildPCIHostdevDevStr(def, hostdev, bootIndex,
+                                                configfd_name, qemuCaps);
+@@ -5802,6 +5887,9 @@ qemuBuildRNGCommandLine(virLogManagerPtr logManager,
+         virCommandAddArgBuffer(cmd, &buf);
+ 
+         /* add the device */
++        if (qemuCommandAddExtDevice(cmd, &rng->info) < 0)
++            return -1;
++
+         if (!(tmp = qemuBuildRNGDevStr(def, rng, qemuCaps)))
+             return -1;
+         virCommandAddArgList(cmd, "-device", tmp, NULL);
+@@ -8654,11 +8742,17 @@ qemuBuildInterfaceCommandLine(virQEMUDriverPtr driver,
+      *   New way: -netdev type=tap,id=netdev1 -device e1000,id=netdev1
+      */
+     if (qemuDomainSupportsNicdev(def, net)) {
++        if (qemuCommandAddExtDevice(cmd, &net->info) < 0)
++            goto cleanup;
++
+         if (!(nic = qemuBuildNicDevStr(def, net, bootindex,
+                                        vhostfdSize, qemuCaps)))
+             goto cleanup;
+         virCommandAddArgList(cmd, "-device", nic, NULL);
+     } else {
++        if (qemuCommandAddExtDevice(cmd, &net->info) < 0)
++            goto cleanup;
++
+         if (!(nic = qemuBuildLegacyNicStr(net)))
+             goto cleanup;
+         virCommandAddArgList(cmd, "-net", nic, NULL);
+@@ -9105,6 +9199,12 @@ qemuBuildShmemCommandLine(virLogManagerPtr logManager,
+ 
+     if (!devstr)
+         return -1;
++
++    if (qemuCommandAddExtDevice(cmd, &shmem->info) < 0) {
++        VIR_FREE(devstr);
++        return -1;
++    }
++
+     virCommandAddArgList(cmd, "-device", devstr, NULL);
+     VIR_FREE(devstr);
+ 
+@@ -10259,6 +10359,10 @@ qemuBuildVsockCommandLine(virCommandPtr cmd,
+ 
+     virCommandPassFD(cmd, priv->vhostfd, VIR_COMMAND_PASS_FD_CLOSE_PARENT);
+     priv->vhostfd = -1;
++
++    if (qemuCommandAddExtDevice(cmd, &vsock->info) < 0)
++        goto cleanup;
++
+     virCommandAddArgList(cmd, "-device", devstr, NULL);
+ 
+     ret = 0;
+diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h
+index 4f1b360130..e8cd8ed04e 100644
+--- a/src/qemu/qemu_command.h
++++ b/src/qemu/qemu_command.h
+@@ -174,6 +174,8 @@ char *qemuBuildRedirdevDevStr(const virDomainDef *def,
+                               virDomainRedirdevDefPtr dev,
+                               virQEMUCapsPtr qemuCaps);
+ 
++char *qemuBuildZPCIDevStr(virDomainDeviceInfoPtr dev);
++
+ int qemuNetworkPrepareDevices(virDomainDefPtr def);
+ 
+ int qemuGetDriveSourceString(virStorageSourcePtr src,
+diff --git a/tests/qemuxml2argvdata/disk-virtio-s390-zpci.args b/tests/qemuxml2argvdata/disk-virtio-s390-zpci.args
+index 20e63a15b5..ffb5d1597e 100644
+--- a/tests/qemuxml2argvdata/disk-virtio-s390-zpci.args
++++ b/tests/qemuxml2argvdata/disk-virtio-s390-zpci.args
+@@ -21,6 +21,7 @@ server,nowait \
+ -no-shutdown \
+ -boot c \
+ -drive file=/dev/HostVG/QEMUGuest1,format=raw,if=none,id=drive-virtio-disk0 \
++-device zpci,uid=25,fid=31,target=virtio-disk0,id=zpci25 \
+ -device virtio-blk-pci,bus=pci.0,addr=0x8,drive=drive-virtio-disk0,\
+ id=virtio-disk0 \
+ -device virtio-balloon-ccw,id=balloon0,devno=fe.0.0000
+diff --git a/tests/qemuxml2argvdata/hostdev-vfio-zpci-autogenerate.args b/tests/qemuxml2argvdata/hostdev-vfio-zpci-autogenerate.args
+new file mode 100644
+index 0000000000..e5987e1053
+--- /dev/null
++++ b/tests/qemuxml2argvdata/hostdev-vfio-zpci-autogenerate.args
+@@ -0,0 +1,26 @@
++LC_ALL=C \
++PATH=/bin \
++HOME=/home/test \
++USER=test \
++LOGNAME=test \
++QEMU_AUDIO_DRV=none \
++/usr/bin/qemu-system-s390x \
++-name QEMUGuest1 \
++-S \
++-machine s390-ccw-virtio,accel=tcg,usb=off,dump-guest-core=off \
++-m 214 \
++-smp 1,sockets=1,cores=1,threads=1 \
++-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \
++-display none \
++-no-user-config \
++-nodefaults \
++-chardev socket,id=charmonitor,path=/tmp/lib/domain--1-QEMUGuest1/monitor.sock,\
++server,nowait \
++-mon chardev=charmonitor,id=monitor,mode=control \
++-rtc base=utc \
++-no-shutdown \
++-boot c \
++-device zpci,uid=1,fid=0,target=hostdev0,id=zpci1 \
++-device vfio-pci,host=00:00.0,id=hostdev0,bus=pci.0,addr=0x1 \
++-device zpci,uid=2,fid=1,target=balloon0,id=zpci2 \
++-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x2
+diff --git a/tests/qemuxml2argvdata/hostdev-vfio-zpci-autogenerate.xml b/tests/qemuxml2argvdata/hostdev-vfio-zpci-autogenerate.xml
+new file mode 100644
+index 0000000000..36161006ab
+--- /dev/null
++++ b/tests/qemuxml2argvdata/hostdev-vfio-zpci-autogenerate.xml
+@@ -0,0 +1,18 @@
++<domain type='qemu'>
++  <name>QEMUGuest1</name>
++  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
++  <memory>219100</memory>
++  <os>
++    <type arch='s390x' machine='s390-ccw-virtio'>hvm</type>
++  </os>
++  <devices>
++    <emulator>/usr/bin/qemu-system-s390x</emulator>
++    <hostdev mode='subsystem' type='pci'>
++      <driver name='vfio'/>
++      <source>
++        <address domain='0x0000' bus='0x00' slot='0x00' function='0x0'/>
++      </source>
++      <address type='pci'/>
++    </hostdev>
++  </devices>
++</domain>
+diff --git a/tests/qemuxml2argvdata/hostdev-vfio-zpci-boundaries.args b/tests/qemuxml2argvdata/hostdev-vfio-zpci-boundaries.args
+new file mode 100644
+index 0000000000..dcbb179a7d
+--- /dev/null
++++ b/tests/qemuxml2argvdata/hostdev-vfio-zpci-boundaries.args
+@@ -0,0 +1,30 @@
++LC_ALL=C \
++PATH=/bin \
++HOME=/home/test \
++USER=test \
++LOGNAME=test \
++QEMU_AUDIO_DRV=none \
++/usr/bin/qemu-system-s390x \
++-name QEMUGuest1 \
++-S \
++-machine s390-ccw-virtio,accel=tcg,usb=off,dump-guest-core=off \
++-m 214 \
++-smp 1,sockets=1,cores=1,threads=1 \
++-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \
++-display none \
++-no-user-config \
++-nodefaults \
++-chardev socket,id=charmonitor,path=/tmp/lib/domain--1-QEMUGuest1/monitor.sock,\
++server,nowait \
++-mon chardev=charmonitor,id=monitor,mode=control \
++-rtc base=utc \
++-no-shutdown \
++-boot c \
++-device zpci,uid=3,fid=2,target=pci.1,id=zpci3 \
++-device pci-bridge,chassis_nr=1,id=pci.1,bus=pci.0,addr=0x1 \
++-device zpci,uid=65535,fid=4294967295,target=hostdev0,id=zpci65535 \
++-device vfio-pci,host=ffff:00:00.0,id=hostdev0,bus=pci.1,addr=0x1f \
++-device zpci,uid=1,fid=0,target=hostdev1,id=zpci1 \
++-device vfio-pci,host=00:00.0,id=hostdev1,bus=pci.0,addr=0x2 \
++-device zpci,uid=2,fid=1,target=balloon0,id=zpci2 \
++-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3
+diff --git a/tests/qemuxml2argvdata/hostdev-vfio-zpci-boundaries.xml b/tests/qemuxml2argvdata/hostdev-vfio-zpci-boundaries.xml
+new file mode 100644
+index 0000000000..1e6060345b
+--- /dev/null
++++ b/tests/qemuxml2argvdata/hostdev-vfio-zpci-boundaries.xml
+@@ -0,0 +1,30 @@
++<domain type='qemu'>
++  <name>QEMUGuest1</name>
++  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
++  <memory>219100</memory>
++  <os>
++    <type arch='s390x' machine='s390-ccw-virtio'>hvm</type>
++  </os>
++  <devices>
++    <emulator>/usr/bin/qemu-system-s390x</emulator>
++    <controller type='pci' index='0' model='pci-root'/>
++    <hostdev mode='subsystem' type='pci'>
++      <driver name='vfio'/>
++      <source>
++        <address domain='0xffff' bus='0x00' slot='0x00' function='0x0'/>
++      </source>
++      <address type='pci' domain='0x0000' bus='0x01' slot='0x1f' function='0x0'>
++        <zpci uid='0xffff' fid='0xffffffff'/>
++      </address>
++    </hostdev>
++    <hostdev mode='subsystem' type='pci'>
++      <driver name='vfio'/>
++      <source>
++        <address domain='0x0000' bus='0x00' slot='0x00' function='0x0'/>
++      </source>
++      <address type='pci'>
++        <zpci uid='0x0001' fid='0x00000000'/>
++      </address>
++    </hostdev>
++  </devices>
++</domain>
+diff --git a/tests/qemuxml2argvdata/hostdev-vfio-zpci-multidomain-many.args b/tests/qemuxml2argvdata/hostdev-vfio-zpci-multidomain-many.args
+new file mode 100644
+index 0000000000..11a2e50f1e
+--- /dev/null
++++ b/tests/qemuxml2argvdata/hostdev-vfio-zpci-multidomain-many.args
+@@ -0,0 +1,40 @@
++LC_ALL=C \
++PATH=/bin \
++HOME=/home/test \
++USER=test \
++LOGNAME=test \
++QEMU_AUDIO_DRV=none \
++/usr/bin/qemu-system-s390x \
++-name QEMUGuest1 \
++-S \
++-machine s390-ccw-virtio,accel=tcg,usb=off,dump-guest-core=off \
++-m 214 \
++-smp 1,sockets=1,cores=1,threads=1 \
++-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \
++-display none \
++-no-user-config \
++-nodefaults \
++-chardev socket,id=charmonitor,path=/tmp/lib/domain--1-QEMUGuest1/monitor.sock,\
++server,nowait \
++-mon chardev=charmonitor,id=monitor,mode=control \
++-rtc base=utc \
++-no-shutdown \
++-boot c \
++-device zpci,uid=35,fid=63,target=hostdev0,id=zpci35 \
++-device vfio-pci,host=0001:00:00.0,id=hostdev0,bus=pci.0,addr=0x3 \
++-device zpci,uid=53,fid=104,target=hostdev1,id=zpci53 \
++-device vfio-pci,host=0002:00:00.0,id=hostdev1,bus=pci.0,addr=0x1 \
++-device zpci,uid=1,fid=1,target=hostdev2,id=zpci1 \
++-device vfio-pci,host=0003:00:00.0,id=hostdev2,bus=pci.0,addr=0x2 \
++-device zpci,uid=2,fid=2,target=hostdev3,id=zpci2 \
++-device vfio-pci,host=0004:00:00.0,id=hostdev3,bus=pci.0,addr=0x5 \
++-device zpci,uid=83,fid=0,target=hostdev4,id=zpci83 \
++-device vfio-pci,host=0005:00:00.0,id=hostdev4,bus=pci.0,addr=0x7 \
++-device zpci,uid=3,fid=114,target=hostdev5,id=zpci3 \
++-device vfio-pci,host=0006:00:00.0,id=hostdev5,bus=pci.0,addr=0x9 \
++-device zpci,uid=23,fid=3,target=hostdev6,id=zpci23 \
++-device vfio-pci,host=0007:00:00.0,id=hostdev6,bus=pci.0,addr=0x4 \
++-device zpci,uid=4,fid=40,target=hostdev7,id=zpci4 \
++-device vfio-pci,host=0008:00:00.0,id=hostdev7,bus=pci.0,addr=0x6 \
++-device zpci,uid=5,fid=4,target=balloon0,id=zpci5 \
++-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x8
+diff --git a/tests/qemuxml2argvdata/hostdev-vfio-zpci-multidomain-many.xml b/tests/qemuxml2argvdata/hostdev-vfio-zpci-multidomain-many.xml
+new file mode 100644
+index 0000000000..da8305dd6d
+--- /dev/null
++++ b/tests/qemuxml2argvdata/hostdev-vfio-zpci-multidomain-many.xml
+@@ -0,0 +1,79 @@
++<domain type='qemu'>
++  <name>QEMUGuest1</name>
++  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
++  <memory>219100</memory>
++  <os>
++    <type arch='s390x' machine='s390-ccw-virtio'>hvm</type>
++  </os>
++  <devices>
++    <emulator>/usr/bin/qemu-system-s390x</emulator>
++    <controller type='pci' index='0' model='pci-root'/>
++    <hostdev mode='subsystem' type='pci'>
++      <driver name='vfio'/>
++      <source>
++        <address domain='0x0001' bus='0x00' slot='0x00' function='0x0'/>
++      </source>
++      <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'>
++        <zpci uid='0x0023' fid='0x0000003f'/>
++      </address>
++    </hostdev>
++    <hostdev mode='subsystem' type='pci'>
++      <driver name='vfio'/>
++      <source>
++        <address domain='0x0002' bus='0x00' slot='0x00' function='0x0'/>
++      </source>
++      <address type='pci'>
++        <zpci uid='0x0035' fid='0x00000068'/>
++      </address>
++    </hostdev>
++    <hostdev mode='subsystem' type='pci'>
++      <driver name='vfio'/>
++      <source>
++        <address domain='0x0003' bus='0x00' slot='0x00' function='0x0'/>
++      </source>
++    </hostdev>
++    <hostdev mode='subsystem' type='pci'>
++      <driver name='vfio'/>
++      <source>
++        <address domain='0x0004' bus='0x00' slot='0x00' function='0x0'/>
++      </source>
++      <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/>
++    </hostdev>
++    <hostdev mode='subsystem' type='pci'>
++      <driver name='vfio'/>
++      <source>
++        <address domain='0x0005' bus='0x00' slot='0x00' function='0x0'/>
++      </source>
++      <address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'>
++        <zpci uid='0x0053'/>
++      </address>
++    </hostdev>
++    <hostdev mode='subsystem' type='pci'>
++      <driver name='vfio'/>
++      <source>
++        <address domain='0x0006' bus='0x00' slot='0x00' function='0x0'/>
++      </source>
++      <address type='pci' domain='0x0000' bus='0x00' slot='0x09' function='0x0'>
++        <zpci uid='0x0003' fid='0x00000072'/>
++      </address>
++    </hostdev>
++    <hostdev mode='subsystem' type='pci'>
++      <driver name='vfio'/>
++      <source>
++        <address domain='0x0007' bus='0x00' slot='0x00' function='0x0'/>
++      </source>
++      <address type='pci'>
++        <zpci uid='0x0017' fid='0x00000003'/>
++      </address>
++    </hostdev>
++    <hostdev mode='subsystem' type='pci'>
++      <driver name='vfio'/>
++      <source>
++        <address domain='0x0008' bus='0x00' slot='0x00' function='0x0'/>
++      </source>
++      <address type='pci'>
++        <zpci uid='0x0004' fid='0x00000028'/>
++      </address>
++    </hostdev>
++  </devices>
++</domain>
+diff --git a/tests/qemuxml2argvdata/hostdev-vfio-zpci.args b/tests/qemuxml2argvdata/hostdev-vfio-zpci.args
+index 622c504da0..80de60acaa 100644
+--- a/tests/qemuxml2argvdata/hostdev-vfio-zpci.args
++++ b/tests/qemuxml2argvdata/hostdev-vfio-zpci.args
+@@ -20,5 +20,7 @@ server,nowait \
+ -rtc base=utc \
+ -no-shutdown \
+ -boot c \
++-device zpci,uid=25,fid=31,target=hostdev0,id=zpci25 \
+ -device vfio-pci,host=00:00.0,id=hostdev0,bus=pci.0,addr=0x8 \
++-device zpci,uid=1,fid=0,target=balloon0,id=zpci1 \
+ -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x1
+diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
+index 1066de8bc4..9de0cbf7e9 100644
+--- a/tests/qemuxml2argvtest.c
++++ b/tests/qemuxml2argvtest.c
+@@ -1637,6 +1637,19 @@ mymain(void)
+     DO_TEST("hostdev-vfio-zpci",
+             QEMU_CAPS_DEVICE_VFIO_PCI,
+             QEMU_CAPS_DEVICE_ZPCI);
++    DO_TEST("hostdev-vfio-zpci-multidomain-many",
++            QEMU_CAPS_DEVICE_VFIO_PCI,
++            QEMU_CAPS_DEVICE_PCI_BRIDGE,
++            QEMU_CAPS_DEVICE_ZPCI);
++    DO_TEST("hostdev-vfio-zpci-autogenerate",
++            QEMU_CAPS_DEVICE_VFIO_PCI,
++            QEMU_CAPS_DEVICE_ZPCI);
++    DO_TEST("hostdev-vfio-zpci-boundaries",
++            QEMU_CAPS_DEVICE_VFIO_PCI,
++            QEMU_CAPS_DEVICE_PCI_BRIDGE,
++            QEMU_CAPS_DEVICE_ZPCI);
++    DO_TEST_PARSE_ERROR("hostdev-vfio-zpci",
++                        QEMU_CAPS_DEVICE_VFIO_PCI);
+     DO_TEST("pci-rom", NONE);
+     DO_TEST("pci-rom-disabled", NONE);
+     DO_TEST("pci-rom-disabled-invalid", NONE);
+diff --git a/tests/qemuxml2xmloutdata/hostdev-vfio-zpci-autogenerate.xml b/tests/qemuxml2xmloutdata/hostdev-vfio-zpci-autogenerate.xml
+new file mode 100644
+index 0000000000..e94e63bd0a
+--- /dev/null
++++ b/tests/qemuxml2xmloutdata/hostdev-vfio-zpci-autogenerate.xml
+@@ -0,0 +1,34 @@
++<domain type='qemu'>
++  <name>QEMUGuest1</name>
++  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
++  <memory unit='KiB'>219100</memory>
++  <currentMemory unit='KiB'>219100</currentMemory>
++  <vcpu placement='static'>1</vcpu>
++  <os>
++    <type arch='s390x' machine='s390-ccw-virtio'>hvm</type>
++    <boot dev='hd'/>
++  </os>
++  <clock offset='utc'/>
++  <on_poweroff>destroy</on_poweroff>
++  <on_reboot>restart</on_reboot>
++  <on_crash>destroy</on_crash>
++  <devices>
++    <emulator>/usr/bin/qemu-system-s390x</emulator>
++    <controller type='pci' index='0' model='pci-root'/>
++    <hostdev mode='subsystem' type='pci' managed='no'>
++      <driver name='vfio'/>
++      <source>
++        <address domain='0x0000' bus='0x00' slot='0x00' function='0x0'/>
++      </source>
++      <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'>
++        <zpci uid='0x0001' fid='0x00000000'/>
++      </address>
++    </hostdev>
++    <memballoon model='virtio'>
++      <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'>
++        <zpci uid='0x0002' fid='0x00000001'/>
++      </address>
++    </memballoon>
++    <panic model='s390'/>
++  </devices>
++</domain>
+diff --git a/tests/qemuxml2xmloutdata/hostdev-vfio-zpci-boundaries.xml b/tests/qemuxml2xmloutdata/hostdev-vfio-zpci-boundaries.xml
+new file mode 100644
+index 0000000000..81d2146188
+--- /dev/null
++++ b/tests/qemuxml2xmloutdata/hostdev-vfio-zpci-boundaries.xml
+@@ -0,0 +1,48 @@
++<domain type='qemu'>
++  <name>QEMUGuest1</name>
++  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
++  <memory unit='KiB'>219100</memory>
++  <currentMemory unit='KiB'>219100</currentMemory>
++  <vcpu placement='static'>1</vcpu>
++  <os>
++    <type arch='s390x' machine='s390-ccw-virtio'>hvm</type>
++    <boot dev='hd'/>
++  </os>
++  <clock offset='utc'/>
++  <on_poweroff>destroy</on_poweroff>
++  <on_reboot>restart</on_reboot>
++  <on_crash>destroy</on_crash>
++  <devices>
++    <emulator>/usr/bin/qemu-system-s390x</emulator>
++    <controller type='pci' index='0' model='pci-root'/>
++    <controller type='pci' index='1' model='pci-bridge'>
++      <model name='pci-bridge'/>
++      <target chassisNr='1'/>
++      <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/>
++    </controller>
++    <hostdev mode='subsystem' type='pci' managed='no'>
++      <driver name='vfio'/>
++      <source>
++        <address domain='0xffff' bus='0x00' slot='0x00' function='0x0'/>
++      </source>
++      <address type='pci' domain='0x0000' bus='0x01' slot='0x1f' function='0x0'>
++        <zpci uid='0xffff' fid='0xffffffff'/>
++      </address>
++    </hostdev>
++    <hostdev mode='subsystem' type='pci' managed='no'>
++      <driver name='vfio'/>
++      <source>
++        <address domain='0x0000' bus='0x00' slot='0x00' function='0x0'/>
++      </source>
++      <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'>
++        <zpci uid='0x0001' fid='0x00000000'/>
++      </address>
++    </hostdev>
++    <memballoon model='virtio'>
++      <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'>
++        <zpci uid='0x0002' fid='0x00000001'/>
++      </address>
++    </memballoon>
++    <panic model='s390'/>
++  </devices>
++</domain>
+diff --git a/tests/qemuxml2xmloutdata/hostdev-vfio-zpci-multidomain-many.xml b/tests/qemuxml2xmloutdata/hostdev-vfio-zpci-multidomain-many.xml
+new file mode 100644
+index 0000000000..e56106d103
+--- /dev/null
++++ b/tests/qemuxml2xmloutdata/hostdev-vfio-zpci-multidomain-many.xml
+@@ -0,0 +1,97 @@
++<domain type='qemu'>
++  <name>QEMUGuest1</name>
++  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
++  <memory unit='KiB'>219100</memory>
++  <currentMemory unit='KiB'>219100</currentMemory>
++  <vcpu placement='static'>1</vcpu>
++  <os>
++    <type arch='s390x' machine='s390-ccw-virtio'>hvm</type>
++    <boot dev='hd'/>
++  </os>
++  <clock offset='utc'/>
++  <on_poweroff>destroy</on_poweroff>
++  <on_reboot>restart</on_reboot>
++  <on_crash>destroy</on_crash>
++  <devices>
++    <emulator>/usr/bin/qemu-system-s390x</emulator>
++    <controller type='pci' index='0' model='pci-root'/>
++    <hostdev mode='subsystem' type='pci' managed='no'>
++      <driver name='vfio'/>
++      <source>
++        <address domain='0x0001' bus='0x00' slot='0x00' function='0x0'/>
++      </source>
++      <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'>
++        <zpci uid='0x0023' fid='0x0000003f'/>
++      </address>
++    </hostdev>
++    <hostdev mode='subsystem' type='pci' managed='no'>
++      <driver name='vfio'/>
++      <source>
++        <address domain='0x0002' bus='0x00' slot='0x00' function='0x0'/>
++      </source>
++      <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'>
++        <zpci uid='0x0035' fid='0x00000068'/>
++      </address>
++    </hostdev>
++    <hostdev mode='subsystem' type='pci' managed='no'>
++      <driver name='vfio'/>
++      <source>
++        <address domain='0x0003' bus='0x00' slot='0x00' function='0x0'/>
++      </source>
++      <address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'>
++        <zpci uid='0x0001' fid='0x00000001'/>
++      </address>
++    </hostdev>
++    <hostdev mode='subsystem' type='pci' managed='no'>
++      <driver name='vfio'/>
++      <source>
++        <address domain='0x0004' bus='0x00' slot='0x00' function='0x0'/>
++      </source>
++      <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'>
++        <zpci uid='0x0002' fid='0x00000002'/>
++      </address>
++    </hostdev>
++    <hostdev mode='subsystem' type='pci' managed='no'>
++      <driver name='vfio'/>
++      <source>
++        <address domain='0x0005' bus='0x00' slot='0x00' function='0x0'/>
++      </source>
++      <address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'>
++        <zpci uid='0x0053' fid='0x00000000'/>
++      </address>
++    </hostdev>
++    <hostdev mode='subsystem' type='pci' managed='no'>
++      <driver name='vfio'/>
++      <source>
++        <address domain='0x0006' bus='0x00' slot='0x00' function='0x0'/>
++      </source>
++      <address type='pci' domain='0x0000' bus='0x00' slot='0x09' function='0x0'>
++        <zpci uid='0x0003' fid='0x00000072'/>
++      </address>
++    </hostdev>
++    <hostdev mode='subsystem' type='pci' managed='no'>
++      <driver name='vfio'/>
++      <source>
++        <address domain='0x0007' bus='0x00' slot='0x00' function='0x0'/>
++      </source>
++      <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'>
++        <zpci uid='0x0017' fid='0x00000003'/>
++      </address>
++    </hostdev>
++    <hostdev mode='subsystem' type='pci' managed='no'>
++      <driver name='vfio'/>
++      <source>
++        <address domain='0x0008' bus='0x00' slot='0x00' function='0x0'/>
++      </source>
++      <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'>
++        <zpci uid='0x0004' fid='0x00000028'/>
++      </address>
++    </hostdev>
++    <memballoon model='virtio'>
++      <address type='pci' domain='0x0000' bus='0x00' slot='0x08' function='0x0'>
++        <zpci uid='0x0005' fid='0x00000004'/>
++      </address>
++    </memballoon>
++    <panic model='s390'/>
++  </devices>
++</domain>
+diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
+index a787f4f4a3..b2afc8a8ba 100644
+--- a/tests/qemuxml2xmltest.c
++++ b/tests/qemuxml2xmltest.c
+@@ -488,6 +488,17 @@ mymain(void)
+     DO_TEST("hostdev-vfio-zpci",
+             QEMU_CAPS_DEVICE_ZPCI,
+             QEMU_CAPS_CCW);
++    DO_TEST("hostdev-vfio-zpci-multidomain-many",
++            QEMU_CAPS_DEVICE_VFIO_PCI,
++            QEMU_CAPS_DEVICE_PCI_BRIDGE,
++            QEMU_CAPS_DEVICE_ZPCI);
++    DO_TEST("hostdev-vfio-zpci-autogenerate",
++            QEMU_CAPS_DEVICE_VFIO_PCI,
++            QEMU_CAPS_DEVICE_ZPCI);
++    DO_TEST("hostdev-vfio-zpci-boundaries",
++            QEMU_CAPS_DEVICE_VFIO_PCI,
++            QEMU_CAPS_DEVICE_PCI_BRIDGE,
++            QEMU_CAPS_DEVICE_ZPCI);
+     DO_TEST("hostdev-mdev-precreated", NONE);
+     DO_TEST("hostdev-mdev-display", QEMU_CAPS_VFIO_PCI_DISPLAY);
+     DO_TEST("pci-rom", NONE);
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-qemu-Introduce-generic-qemuMonitorGetGuestCPU.patch b/SOURCES/libvirt-qemu-Introduce-generic-qemuMonitorGetGuestCPU.patch
new file mode 100644
index 0000000..39ca791
--- /dev/null
+++ b/SOURCES/libvirt-qemu-Introduce-generic-qemuMonitorGetGuestCPU.patch
@@ -0,0 +1,323 @@
+From b61b68abeb8c2c93740698b81d59d2030eea8189 Mon Sep 17 00:00:00 2001
+Message-Id: <b61b68abeb8c2c93740698b81d59d2030eea8189@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:26:03 +0200
+Subject: [PATCH] qemu: Introduce generic qemuMonitorGetGuestCPU
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Unlike the old version (which is now called qemuMonitorGetGuestCPUx86),
+this monitor API checks for individual features by their names rather
+than processing CPUID bits. Thus we can get the list of enabled and
+disabled features for both CPUID and MSR features.
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit cc6d6b3cb995110a1d9da97f31ce68c2290f4332)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1697627
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <29634994c64ffbf3509238ccbe1937b599e55838.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/qemu/qemu_monitor.c      |  36 +++++++
+ src/qemu/qemu_monitor.h      |  10 ++
+ src/qemu/qemu_monitor_json.c | 186 +++++++++++++++++++++++++++++++++++
+ src/qemu/qemu_monitor_json.h |   7 ++
+ 4 files changed, 239 insertions(+)
+
+diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
+index b35187b66d..ae666ce633 100644
+--- a/src/qemu/qemu_monitor.c
++++ b/src/qemu/qemu_monitor.c
+@@ -4074,6 +4074,42 @@ qemuMonitorGetGuestCPUx86(qemuMonitorPtr mon,
+ }
+ 
+ 
++/**
++ * qemuMonitorGetGuestCPU:
++ * @mon: Pointer to the monitor
++ * @arch: CPU architecture
++ * @translate: callback for translating CPU feature names from QEMU to libvirt
++ * @opaque: data for @translate callback
++ * @enabled: returns the CPU data for all enabled features
++ * @disabled: returns the CPU data for features which we asked for
++ *      (either explicitly or via a named CPU model) but QEMU disabled them
++ *
++ * Retrieve the definition of the guest CPU from a running QEMU instance.
++ *
++ * Returns 0 on success, -1 on error.
++ */
++int
++qemuMonitorGetGuestCPU(qemuMonitorPtr mon,
++                       virArch arch,
++                       qemuMonitorCPUFeatureTranslationCallback translate,
++                       void *opaque,
++                       virCPUDataPtr *enabled,
++                       virCPUDataPtr *disabled)
++{
++    VIR_DEBUG("arch=%s translate=%p opaque=%p enabled=%p disabled=%p",
++              virArchToString(arch), translate, opaque, enabled, disabled);
++
++    QEMU_CHECK_MONITOR(mon);
++
++    *enabled = NULL;
++    if (disabled)
++        *disabled = NULL;
++
++    return qemuMonitorJSONGetGuestCPU(mon, arch, translate, opaque,
++                                      enabled, disabled);
++}
++
++
+ /**
+  * qemuMonitorRTCResetReinjection:
+  * @mon: Pointer to the monitor
+diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
+index b4d484c703..8d4f6e6062 100644
+--- a/src/qemu/qemu_monitor.h
++++ b/src/qemu/qemu_monitor.h
+@@ -1099,6 +1099,16 @@ int qemuMonitorGetGuestCPUx86(qemuMonitorPtr mon,
+                               virCPUDataPtr *data,
+                               virCPUDataPtr *disabled);
+ 
++typedef const char *(*qemuMonitorCPUFeatureTranslationCallback)(const char *name,
++                                                                void *opaque);
++
++int qemuMonitorGetGuestCPU(qemuMonitorPtr mon,
++                           virArch arch,
++                           qemuMonitorCPUFeatureTranslationCallback translate,
++                           void *opaque,
++                           virCPUDataPtr *enabled,
++                           virCPUDataPtr *disabled);
++
+ int qemuMonitorRTCResetReinjection(qemuMonitorPtr mon);
+ 
+ typedef struct _qemuMonitorIOThreadInfo qemuMonitorIOThreadInfo;
+diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
+index abf952cd34..00a0578809 100644
+--- a/src/qemu/qemu_monitor_json.c
++++ b/src/qemu/qemu_monitor_json.c
+@@ -5998,6 +5998,57 @@ int qemuMonitorJSONGetObjectProperty(qemuMonitorPtr mon,
+ }
+ 
+ 
++static int
++qemuMonitorJSONGetStringListProperty(qemuMonitorPtr mon,
++                                     const char *path,
++                                     const char *property,
++                                     char ***strList)
++{
++    VIR_AUTOPTR(virJSONValue) cmd = NULL;
++    VIR_AUTOPTR(virJSONValue) reply = NULL;
++    VIR_AUTOSTRINGLIST list = NULL;
++    virJSONValuePtr data;
++    size_t n;
++    size_t i;
++
++    *strList = NULL;
++
++    if (!(cmd = qemuMonitorJSONMakeCommand("qom-get",
++                                           "s:path", path,
++                                           "s:property", property,
++                                           NULL)))
++        return -1;
++
++    if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
++        return -1;
++
++    if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_ARRAY) < 0)
++        return -1;
++
++    data = virJSONValueObjectGetArray(reply, "return");
++    n = virJSONValueArraySize(data);
++
++    if (VIR_ALLOC_N(list, n + 1) < 0)
++        return -1;
++
++    for (i = 0; i < n; i++) {
++        virJSONValuePtr item = virJSONValueArrayGet(data, i);
++
++        if (virJSONValueGetType(item) != VIR_JSON_TYPE_STRING) {
++            virReportError(VIR_ERR_INTERNAL_ERROR,
++                           _("unexpected value in %s array"), property);
++            return -1;
++        }
++
++        if (VIR_STRDUP(list[i], virJSONValueGetString(item)) < 0)
++            return -1;
++    }
++
++    VIR_STEAL_PTR(*strList, list);
++    return n;
++}
++
++
+ #define MAKE_SET_CMD(STRING, VALUE) \
+     cmd = qemuMonitorJSONMakeCommand("qom-set", \
+                                       "s:path", path, \
+@@ -7207,6 +7258,141 @@ qemuMonitorJSONGetGuestCPUx86(qemuMonitorPtr mon,
+     return -1;
+ }
+ 
++
++static int
++qemuMonitorJSONGetCPUProperties(qemuMonitorPtr mon,
++                                char ***props)
++{
++    VIR_AUTOPTR(virJSONValue) cmd = NULL;
++    VIR_AUTOPTR(virJSONValue) reply = NULL;
++
++    *props = NULL;
++
++    if (!(cmd = qemuMonitorJSONMakeCommand("qom-list",
++                                           "s:path", QOM_CPU_PATH,
++                                           NULL)))
++        return -1;
++
++    if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
++        return -1;
++
++    if (qemuMonitorJSONHasError(reply, "DeviceNotFound"))
++        return 0;
++
++    return qemuMonitorJSONParsePropsList(cmd, reply, "bool", props);
++}
++
++
++static int
++qemuMonitorJSONGetCPUData(qemuMonitorPtr mon,
++                          qemuMonitorCPUFeatureTranslationCallback translate,
++                          void *opaque,
++                          virCPUDataPtr data)
++{
++    qemuMonitorJSONObjectProperty prop = { .type = QEMU_MONITOR_OBJECT_PROPERTY_BOOLEAN };
++    VIR_AUTOSTRINGLIST props = NULL;
++    char **p;
++
++    if (qemuMonitorJSONGetCPUProperties(mon, &props) < 0)
++        return -1;
++
++    for (p = props; p && *p; p++) {
++        const char *name = *p;
++
++        if (qemuMonitorJSONGetObjectProperty(mon, QOM_CPU_PATH, name, &prop) < 0)
++            return -1;
++
++        if (!prop.val.b)
++            continue;
++
++        if (translate)
++            name = translate(name, opaque);
++
++        if (virCPUDataAddFeature(data, name) < 0)
++            return -1;
++    }
++
++    return 0;
++}
++
++
++static int
++qemuMonitorJSONGetCPUDataDisabled(qemuMonitorPtr mon,
++                                  qemuMonitorCPUFeatureTranslationCallback translate,
++                                  void *opaque,
++                                  virCPUDataPtr data)
++{
++    VIR_AUTOSTRINGLIST props = NULL;
++    char **p;
++
++    if (qemuMonitorJSONGetStringListProperty(mon, QOM_CPU_PATH,
++                                             "unavailable-features", &props) < 0)
++        return -1;
++
++    for (p = props; p && *p; p++) {
++        const char *name = *p;
++
++        if (translate)
++            name = translate(name, opaque);
++
++        if (virCPUDataAddFeature(data, name) < 0)
++            return -1;
++    }
++
++    return 0;
++}
++
++
++/**
++ * qemuMonitorJSONGetGuestCPU:
++ * @mon: Pointer to the monitor
++ * @arch: CPU architecture
++ * @translate: callback for translating CPU feature names from QEMU to libvirt
++ * @opaque: data for @translate callback
++ * @enabled: returns the CPU data for all enabled features
++ * @disabled: returns the CPU data for features which we asked for
++ *      (either explicitly or via a named CPU model) but QEMU disabled them
++ *
++ * Retrieve the definition of the guest CPU from a running QEMU instance.
++ *
++ * Returns 0 on success, -1 on error.
++ */
++int
++qemuMonitorJSONGetGuestCPU(qemuMonitorPtr mon,
++                           virArch arch,
++                           qemuMonitorCPUFeatureTranslationCallback translate,
++                           void *opaque,
++                           virCPUDataPtr *enabled,
++                           virCPUDataPtr *disabled)
++{
++    virCPUDataPtr cpuEnabled = NULL;
++    virCPUDataPtr cpuDisabled = NULL;
++    int ret = -1;
++
++    if (!(cpuEnabled = virCPUDataNew(arch)) ||
++        !(cpuDisabled = virCPUDataNew(arch)))
++        goto cleanup;
++
++    if (qemuMonitorJSONGetCPUData(mon, translate, opaque, cpuEnabled) < 0)
++        goto cleanup;
++
++    if (disabled &&
++        qemuMonitorJSONGetCPUDataDisabled(mon, translate, opaque, cpuDisabled) < 0)
++        goto cleanup;
++
++    VIR_STEAL_PTR(*enabled, cpuEnabled);
++    if (disabled)
++        VIR_STEAL_PTR(*disabled, cpuDisabled);
++
++    ret = 0;
++
++ cleanup:
++    virCPUDataFree(cpuEnabled);
++    virCPUDataFree(cpuDisabled);
++    return ret;
++}
++
++
+ int
+ qemuMonitorJSONRTCResetReinjection(qemuMonitorPtr mon)
+ {
+diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h
+index 57bed027e2..29b10aad26 100644
+--- a/src/qemu/qemu_monitor_json.h
++++ b/src/qemu/qemu_monitor_json.h
+@@ -490,6 +490,13 @@ int qemuMonitorJSONGetGuestCPUx86(qemuMonitorPtr mon,
+                                   virCPUDataPtr *data,
+                                   virCPUDataPtr *disabled);
+ 
++int qemuMonitorJSONGetGuestCPU(qemuMonitorPtr mon,
++                               virArch arch,
++                               qemuMonitorCPUFeatureTranslationCallback translate,
++                               void *opaque,
++                               virCPUDataPtr *enabled,
++                               virCPUDataPtr *disabled);
++
+ int qemuMonitorJSONRTCResetReinjection(qemuMonitorPtr mon);
+ 
+ int qemuMonitorJSONGetIOThreads(qemuMonitorPtr mon,
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-qemu-Introduce-zPCI-capability.patch b/SOURCES/libvirt-qemu-Introduce-zPCI-capability.patch
new file mode 100644
index 0000000..2bb0270
--- /dev/null
+++ b/SOURCES/libvirt-qemu-Introduce-zPCI-capability.patch
@@ -0,0 +1,156 @@
+From 3ff9abfcfa6a79c47755a6e8d9da5b1bc4bdd655 Mon Sep 17 00:00:00 2001
+Message-Id: <3ff9abfcfa6a79c47755a6e8d9da5b1bc4bdd655@dist-git>
+From: Yi Min Zhao <zyimin@linux.ibm.com>
+Date: Mon, 8 Apr 2019 10:57:19 +0200
+Subject: [PATCH] qemu: Introduce zPCI capability
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Let's introduce zPCI capability.
+
+Signed-off-by: Yi Min Zhao <zyimin@linux.ibm.com>
+Reviewed-by: Boris Fiuczynski <fiuczy@linux.ibm.com>
+Reviewed-by: Stefan Zimmermann <stzi@linux.ibm.com>
+Reviewed-by: Bjoern Walk <bwalk@linux.ibm.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Reviewed-by: Andrea Bolognani <abologna@redhat.com>
+
+(cherry-picked from commit 29ad952f7e50bbbd920cbfb009a45b55fdb2f069)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1508149
+
+Conflicts:
+
+  * src/qemu/qemu_capabilities.c
+    src/qemu/qemu_capabilities.h
+    + several capabilities have not been backported
+
+Removed:
+
+  * tests/qemucapabilitiesdata/caps_3.0.0.s390x.xml
+    + the file does not exist at all downstream
+      - missing d7434ae8009f
+
+Signed-off-by: Andrea Bolognani <abologna@redhat.com>
+Message-Id: <20190408085732.28684-3-abologna@redhat.com>
+Reviewed-by: Laine Stump <laine@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/qemu/qemu_capabilities.c                     | 2 ++
+ src/qemu/qemu_capabilities.h                     | 1 +
+ tests/qemucapabilitiesdata/caps_2.10.0.s390x.xml | 1 +
+ tests/qemucapabilitiesdata/caps_2.11.0.s390x.xml | 1 +
+ tests/qemucapabilitiesdata/caps_2.12.0.s390x.xml | 1 +
+ tests/qemucapabilitiesdata/caps_2.7.0.s390x.xml  | 1 +
+ tests/qemucapabilitiesdata/caps_2.8.0.s390x.xml  | 1 +
+ tests/qemucapabilitiesdata/caps_2.9.0.s390x.xml  | 1 +
+ 8 files changed, 9 insertions(+)
+
+diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
+index 0d6fa02560..8ca53abf2b 100644
+--- a/src/qemu/qemu_capabilities.c
++++ b/src/qemu/qemu_capabilities.c
+@@ -512,6 +512,7 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST,
+               /* 315 */
+               "vfio-pci.display",
+               "vfio-ap",
++              "zpci",
+               "machine.pseries.cap-nested-hv",
+     );
+ 
+@@ -1153,6 +1154,7 @@ struct virQEMUCapsStringFlags virQEMUCapsObjectTypes[] = {
+     { "mch", QEMU_CAPS_DEVICE_MCH },
+     { "sev-guest", QEMU_CAPS_SEV_GUEST },
+     { "vfio-ap", QEMU_CAPS_DEVICE_VFIO_AP },
++    { "zpci", QEMU_CAPS_DEVICE_ZPCI },
+ };
+ 
+ static struct virQEMUCapsStringFlags virQEMUCapsDevicePropsVirtioBalloon[] = {
+diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
+index 9550df2cd5..bea4767f3c 100644
+--- a/src/qemu/qemu_capabilities.h
++++ b/src/qemu/qemu_capabilities.h
+@@ -492,6 +492,7 @@ typedef enum { /* virQEMUCapsFlags grouping marker for syntax-check */
+     /* 315 */
+     QEMU_CAPS_VFIO_PCI_DISPLAY, /* -device vfio-pci.display */
+     QEMU_CAPS_DEVICE_VFIO_AP, /* -device vfio-ap */
++    QEMU_CAPS_DEVICE_ZPCI, /* -device zpci */
+     QEMU_CAPS_MACHINE_PSERIES_CAP_NESTED_HV, /* -machine pseries.cap-nested-hv */
+ 
+     QEMU_CAPS_LAST /* this must always be the last item */
+diff --git a/tests/qemucapabilitiesdata/caps_2.10.0.s390x.xml b/tests/qemucapabilitiesdata/caps_2.10.0.s390x.xml
+index 7347f5683f..b46efe880d 100644
+--- a/tests/qemucapabilitiesdata/caps_2.10.0.s390x.xml
++++ b/tests/qemucapabilitiesdata/caps_2.10.0.s390x.xml
+@@ -120,6 +120,7 @@
+   <flag name='blockdev-del'/>
+   <flag name='vhost-vsock'/>
+   <flag name='egl-headless'/>
++  <flag name='zpci'/>
+   <version>2010000</version>
+   <kvmVersion>0</kvmVersion>
+   <microcodeVersion>307899</microcodeVersion>
+diff --git a/tests/qemucapabilitiesdata/caps_2.11.0.s390x.xml b/tests/qemucapabilitiesdata/caps_2.11.0.s390x.xml
+index b359f9a049..3ac1fc941c 100644
+--- a/tests/qemucapabilitiesdata/caps_2.11.0.s390x.xml
++++ b/tests/qemucapabilitiesdata/caps_2.11.0.s390x.xml
+@@ -127,6 +127,7 @@
+   <flag name='vhost-vsock'/>
+   <flag name='tpm-emulator'/>
+   <flag name='egl-headless'/>
++  <flag name='zpci'/>
+   <version>2011000</version>
+   <kvmVersion>0</kvmVersion>
+   <microcodeVersion>346751</microcodeVersion>
+diff --git a/tests/qemucapabilitiesdata/caps_2.12.0.s390x.xml b/tests/qemucapabilitiesdata/caps_2.12.0.s390x.xml
+index 7121da27a0..184f115fe4 100644
+--- a/tests/qemucapabilitiesdata/caps_2.12.0.s390x.xml
++++ b/tests/qemucapabilitiesdata/caps_2.12.0.s390x.xml
+@@ -135,6 +135,7 @@
+   <flag name='tpm-emulator'/>
+   <flag name='egl-headless'/>
+   <flag name='vfio-pci.display'/>
++  <flag name='zpci'/>
+   <version>2012000</version>
+   <kvmVersion>0</kvmVersion>
+   <microcodeVersion>375999</microcodeVersion>
+diff --git a/tests/qemucapabilitiesdata/caps_2.7.0.s390x.xml b/tests/qemucapabilitiesdata/caps_2.7.0.s390x.xml
+index 9ed25178f8..b04a9fbfd5 100644
+--- a/tests/qemucapabilitiesdata/caps_2.7.0.s390x.xml
++++ b/tests/qemucapabilitiesdata/caps_2.7.0.s390x.xml
+@@ -107,6 +107,7 @@
+   <flag name='nbd-tls'/>
+   <flag name='virtual-css-bridge'/>
+   <flag name='sdl-gl'/>
++  <flag name='zpci'/>
+   <version>2007000</version>
+   <kvmVersion>0</kvmVersion>
+   <microcodeVersion>220792</microcodeVersion>
+diff --git a/tests/qemucapabilitiesdata/caps_2.8.0.s390x.xml b/tests/qemucapabilitiesdata/caps_2.8.0.s390x.xml
+index 646239ff25..b2b267be8d 100644
+--- a/tests/qemucapabilitiesdata/caps_2.8.0.s390x.xml
++++ b/tests/qemucapabilitiesdata/caps_2.8.0.s390x.xml
+@@ -110,6 +110,7 @@
+   <flag name='virtual-css-bridge'/>
+   <flag name='sdl-gl'/>
+   <flag name='vhost-vsock'/>
++  <flag name='zpci'/>
+   <version>2007093</version>
+   <kvmVersion>0</kvmVersion>
+   <microcodeVersion>246206</microcodeVersion>
+diff --git a/tests/qemucapabilitiesdata/caps_2.9.0.s390x.xml b/tests/qemucapabilitiesdata/caps_2.9.0.s390x.xml
+index 09d68e1f18..f908ab88f3 100644
+--- a/tests/qemucapabilitiesdata/caps_2.9.0.s390x.xml
++++ b/tests/qemucapabilitiesdata/caps_2.9.0.s390x.xml
+@@ -114,6 +114,7 @@
+   <flag name='sdl-gl'/>
+   <flag name='blockdev-del'/>
+   <flag name='vhost-vsock'/>
++  <flag name='zpci'/>
+   <version>2009000</version>
+   <kvmVersion>0</kvmVersion>
+   <microcodeVersion>269625</microcodeVersion>
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-qemu-Make-qemuMonitorGetGuestCPU-usable-on-x86-only.patch b/SOURCES/libvirt-qemu-Make-qemuMonitorGetGuestCPU-usable-on-x86-only.patch
new file mode 100644
index 0000000..5440132
--- /dev/null
+++ b/SOURCES/libvirt-qemu-Make-qemuMonitorGetGuestCPU-usable-on-x86-only.patch
@@ -0,0 +1,228 @@
+From 53744fa2afeb19f0ce31cb109e0b3c1f1c8b815b Mon Sep 17 00:00:00 2001
+Message-Id: <53744fa2afeb19f0ce31cb109e0b3c1f1c8b815b@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:25:58 +0200
+Subject: [PATCH] qemu: Make qemuMonitorGetGuestCPU usable on x86 only
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+It was never implemented or used for anything else anyway. Mainly
+because it uses CPUID features bits. The function is renamed as
+qemuMonitorGetGuestCPUx86 to make this explicit.
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit 055f8f6bb953a8a489729d6cd62e55dee058b7e6)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1697627
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <8e07e0a4f5f751bacf5e23fcdc6b93265b819359.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/qemu/qemu_monitor.c      | 15 +++++-------
+ src/qemu/qemu_monitor.h      |  7 +++---
+ src/qemu/qemu_monitor_json.c | 47 +++++++++++++++---------------------
+ src/qemu/qemu_monitor_json.h |  7 +++---
+ src/qemu/qemu_process.c      |  3 +--
+ tests/qemumonitorjsontest.c  | 10 +++-----
+ 6 files changed, 36 insertions(+), 53 deletions(-)
+
+diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
+index bc116e4e2d..b35187b66d 100644
+--- a/src/qemu/qemu_monitor.c
++++ b/src/qemu/qemu_monitor.c
+@@ -4047,9 +4047,8 @@ qemuMonitorSetDomainLog(qemuMonitorPtr mon,
+ 
+ 
+ /**
+- * qemuMonitorJSONGetGuestCPU:
++ * qemuMonitorJSONGetGuestCPUx86:
+  * @mon: Pointer to the monitor
+- * @arch: arch of the guest
+  * @data: returns the cpu data
+  * @disabled: returns the CPU data for features which were disabled by QEMU
+  *
+@@ -4059,13 +4058,11 @@ qemuMonitorSetDomainLog(qemuMonitorPtr mon,
+  * -1 on other errors.
+  */
+ int
+-qemuMonitorGetGuestCPU(qemuMonitorPtr mon,
+-                       virArch arch,
+-                       virCPUDataPtr *data,
+-                       virCPUDataPtr *disabled)
++qemuMonitorGetGuestCPUx86(qemuMonitorPtr mon,
++                          virCPUDataPtr *data,
++                          virCPUDataPtr *disabled)
+ {
+-    VIR_DEBUG("arch=%s data=%p disabled=%p",
+-              virArchToString(arch), data, disabled);
++    VIR_DEBUG("data=%p disabled=%p", data, disabled);
+ 
+     QEMU_CHECK_MONITOR(mon);
+ 
+@@ -4073,7 +4070,7 @@ qemuMonitorGetGuestCPU(qemuMonitorPtr mon,
+     if (disabled)
+         *disabled = NULL;
+ 
+-    return qemuMonitorJSONGetGuestCPU(mon, arch, data, disabled);
++    return qemuMonitorJSONGetGuestCPUx86(mon, data, disabled);
+ }
+ 
+ 
+diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
+index 81474a04f6..b4d484c703 100644
+--- a/src/qemu/qemu_monitor.h
++++ b/src/qemu/qemu_monitor.h
+@@ -1095,10 +1095,9 @@ void qemuMonitorSetDomainLog(qemuMonitorPtr mon,
+                              void *opaque,
+                              virFreeCallback destroy);
+ 
+-int qemuMonitorGetGuestCPU(qemuMonitorPtr mon,
+-                           virArch arch,
+-                           virCPUDataPtr *data,
+-                           virCPUDataPtr *disabled);
++int qemuMonitorGetGuestCPUx86(qemuMonitorPtr mon,
++                              virCPUDataPtr *data,
++                              virCPUDataPtr *disabled);
+ 
+ int qemuMonitorRTCResetReinjection(qemuMonitorPtr mon);
+ 
+diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
+index e6ac82e96b..8fead72ecf 100644
+--- a/src/qemu/qemu_monitor_json.c
++++ b/src/qemu/qemu_monitor_json.c
+@@ -7157,9 +7157,8 @@ qemuMonitorJSONCheckCPUx86(qemuMonitorPtr mon)
+ 
+ 
+ /**
+- * qemuMonitorJSONGetGuestCPU:
++ * qemuMonitorJSONGetGuestCPUx86:
+  * @mon: Pointer to the monitor
+- * @arch: arch of the guest
+  * @data: returns the cpu data of the guest
+  * @disabled: returns the CPU data for features which were disabled by QEMU
+  *
+@@ -7169,40 +7168,32 @@ qemuMonitorJSONCheckCPUx86(qemuMonitorPtr mon)
+  * -1 on other errors.
+  */
+ int
+-qemuMonitorJSONGetGuestCPU(qemuMonitorPtr mon,
+-                           virArch arch,
+-                           virCPUDataPtr *data,
+-                           virCPUDataPtr *disabled)
++qemuMonitorJSONGetGuestCPUx86(qemuMonitorPtr mon,
++                              virCPUDataPtr *data,
++                              virCPUDataPtr *disabled)
+ {
+     virCPUDataPtr cpuEnabled = NULL;
+     virCPUDataPtr cpuDisabled = NULL;
+     int rc;
+ 
+-    if (ARCH_IS_X86(arch)) {
+-        if ((rc = qemuMonitorJSONCheckCPUx86(mon)) < 0)
+-            return -1;
+-        else if (!rc)
+-            return -2;
++    if ((rc = qemuMonitorJSONCheckCPUx86(mon)) < 0)
++        return -1;
++    else if (!rc)
++        return -2;
+ 
+-        if (qemuMonitorJSONGetCPUx86Data(mon, "feature-words",
+-                                         &cpuEnabled) < 0)
+-            goto error;
++    if (qemuMonitorJSONGetCPUx86Data(mon, "feature-words",
++                                     &cpuEnabled) < 0)
++        goto error;
+ 
+-        if (disabled &&
+-            qemuMonitorJSONGetCPUx86Data(mon, "filtered-features",
+-                                         &cpuDisabled) < 0)
+-            goto error;
++    if (disabled &&
++        qemuMonitorJSONGetCPUx86Data(mon, "filtered-features",
++                                     &cpuDisabled) < 0)
++        goto error;
+ 
+-        *data = cpuEnabled;
+-        if (disabled)
+-            *disabled = cpuDisabled;
+-        return 0;
+-    }
+-
+-    virReportError(VIR_ERR_INTERNAL_ERROR,
+-                   _("CPU definition retrieval isn't supported for '%s'"),
+-                   virArchToString(arch));
+-    return -1;
++    *data = cpuEnabled;
++    if (disabled)
++        *disabled = cpuDisabled;
++    return 0;
+ 
+  error:
+     virCPUDataFree(cpuEnabled);
+diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h
+index 66536ceb97..57bed027e2 100644
+--- a/src/qemu/qemu_monitor_json.h
++++ b/src/qemu/qemu_monitor_json.h
+@@ -486,10 +486,9 @@ int qemuMonitorJSONGetCPUx86Data(qemuMonitorPtr mon,
+                                  const char *property,
+                                  virCPUDataPtr *cpudata);
+ 
+-int qemuMonitorJSONGetGuestCPU(qemuMonitorPtr mon,
+-                               virArch arch,
+-                               virCPUDataPtr *data,
+-                               virCPUDataPtr *disabled);
++int qemuMonitorJSONGetGuestCPUx86(qemuMonitorPtr mon,
++                                  virCPUDataPtr *data,
++                                  virCPUDataPtr *disabled);
+ 
+ int qemuMonitorJSONRTCResetReinjection(qemuMonitorPtr mon);
+ 
+diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
+index bc573f96a4..59a739f262 100644
+--- a/src/qemu/qemu_process.c
++++ b/src/qemu/qemu_process.c
+@@ -4034,8 +4034,7 @@ qemuProcessFetchGuestCPU(virQEMUDriverPtr driver,
+     if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
+         goto error;
+ 
+-    rc = qemuMonitorGetGuestCPU(priv->mon, vm->def->os.arch,
+-                                &dataEnabled, &dataDisabled);
++    rc = qemuMonitorGetGuestCPUx86(priv->mon, &dataEnabled, &dataDisabled);
+ 
+     if (qemuDomainObjExitMonitor(driver, vm) < 0)
+         goto error;
+diff --git a/tests/qemumonitorjsontest.c b/tests/qemumonitorjsontest.c
+index 2eefd06b6e..ef9a549c04 100644
+--- a/tests/qemumonitorjsontest.c
++++ b/tests/qemumonitorjsontest.c
+@@ -2437,9 +2437,8 @@ testQemuMonitorJSONGetCPUData(const void *opaque)
+     if (qemuMonitorTestAddItem(test, "qom-get", jsonStr) < 0)
+         goto cleanup;
+ 
+-    if (qemuMonitorJSONGetGuestCPU(qemuMonitorTestGetMonitor(test),
+-                                   VIR_ARCH_X86_64,
+-                                   &cpuData, NULL) < 0)
++    if (qemuMonitorJSONGetGuestCPUx86(qemuMonitorTestGetMonitor(test),
++                                      &cpuData, NULL) < 0)
+         goto cleanup;
+ 
+     if (!(actual = virCPUDataFormat(cpuData)))
+@@ -2480,9 +2479,8 @@ testQemuMonitorJSONGetNonExistingCPUData(const void *opaque)
+                                "}") < 0)
+         goto cleanup;
+ 
+-    rv = qemuMonitorJSONGetGuestCPU(qemuMonitorTestGetMonitor(test),
+-                                   VIR_ARCH_X86_64,
+-                                   &cpuData, NULL);
++    rv = qemuMonitorJSONGetGuestCPUx86(qemuMonitorTestGetMonitor(test),
++                                       &cpuData, NULL);
+     if (rv != -2) {
+         virReportError(VIR_ERR_INTERNAL_ERROR,
+                        "Unexpected return value %d, expecting -2", rv);
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-qemu-Probe-for-max-x86_64-cpu-type.patch b/SOURCES/libvirt-qemu-Probe-for-max-x86_64-cpu-type.patch
new file mode 100644
index 0000000..35b0e23
--- /dev/null
+++ b/SOURCES/libvirt-qemu-Probe-for-max-x86_64-cpu-type.patch
@@ -0,0 +1,155 @@
+From e26a52e067bfeeab95f6cd4bb0717e202ffd7279 Mon Sep 17 00:00:00 2001
+Message-Id: <e26a52e067bfeeab95f6cd4bb0717e202ffd7279@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:25:52 +0200
+Subject: [PATCH] qemu: Probe for max-x86_64-cpu type
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+We will use it to check whether QEMU supports a specific CPU property.
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit 2a4c23210674b453f91569f0f4b9fd5ebe8d7906)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1697627
+
+Conflicts:
+	src/qemu/qemu_capabilities.c
+	src/qemu/qemu_capabilities.h
+	tests/qemucapabilitiesdata/caps_2.10.0.x86_64.xml
+	tests/qemucapabilitiesdata/caps_2.11.0.x86_64.xml
+	tests/qemucapabilitiesdata/caps_2.12.0.x86_64.xml
+	tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml
+	tests/qemucapabilitiesdata/caps_3.0.0.x86_64.xml
+            - several capabilities are missing
+
+	tests/qemucapabilitiesdata/caps_3.1.0.x86_64.xml
+	tests/qemucapabilitiesdata/caps_4.0.0.x86_64.xml
+            - test files are missing
+
+	tests/qemucapabilitiesdata/caps_4.1.0.x86_64.xml
+            - several capabilities are missing
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <5b1c1caf31b481ba608cc850463ff02b2381c382.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/qemu/qemu_capabilities.c                      | 2 ++
+ src/qemu/qemu_capabilities.h                      | 1 +
+ tests/qemucapabilitiesdata/caps_2.10.0.x86_64.xml | 1 +
+ tests/qemucapabilitiesdata/caps_2.11.0.x86_64.xml | 1 +
+ tests/qemucapabilitiesdata/caps_2.12.0.x86_64.xml | 1 +
+ tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml  | 1 +
+ tests/qemucapabilitiesdata/caps_3.0.0.x86_64.xml  | 1 +
+ tests/qemucapabilitiesdata/caps_4.1.0.x86_64.xml  | 1 +
+ 8 files changed, 9 insertions(+)
+
+diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
+index d2a2f7418a..4515da4b91 100644
+--- a/src/qemu/qemu_capabilities.c
++++ b/src/qemu/qemu_capabilities.c
+@@ -514,6 +514,7 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST,
+               "vfio-ap",
+               "zpci",
+               "machine.pseries.cap-nested-hv",
++              "x86-max-cpu",
+     );
+ 
+ 
+@@ -1155,6 +1156,7 @@ struct virQEMUCapsStringFlags virQEMUCapsObjectTypes[] = {
+     { "sev-guest", QEMU_CAPS_SEV_GUEST },
+     { "vfio-ap", QEMU_CAPS_DEVICE_VFIO_AP },
+     { "zpci", QEMU_CAPS_DEVICE_ZPCI },
++    { "max-x86_64-cpu", QEMU_CAPS_X86_MAX_CPU },
+ };
+ 
+ static struct virQEMUCapsStringFlags virQEMUCapsDevicePropsVirtioBalloon[] = {
+diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
+index 8a27acd8a4..25ed5064b9 100644
+--- a/src/qemu/qemu_capabilities.h
++++ b/src/qemu/qemu_capabilities.h
+@@ -494,6 +494,7 @@ typedef enum { /* virQEMUCapsFlags grouping marker for syntax-check */
+     QEMU_CAPS_DEVICE_VFIO_AP, /* -device vfio-ap */
+     QEMU_CAPS_DEVICE_ZPCI, /* -device zpci */
+     QEMU_CAPS_MACHINE_PSERIES_CAP_NESTED_HV, /* -machine pseries.cap-nested-hv */
++    QEMU_CAPS_X86_MAX_CPU, /* max-x86_64-cpu type exists */
+ 
+     QEMU_CAPS_LAST /* this must always be the last item */
+ } virQEMUCapsFlags;
+diff --git a/tests/qemucapabilitiesdata/caps_2.10.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_2.10.0.x86_64.xml
+index d69a148cd2..bb4c2abdeb 100644
+--- a/tests/qemucapabilitiesdata/caps_2.10.0.x86_64.xml
++++ b/tests/qemucapabilitiesdata/caps_2.10.0.x86_64.xml
+@@ -204,6 +204,7 @@
+   <flag name='vhost-vsock'/>
+   <flag name='mch'/>
+   <flag name='egl-headless'/>
++  <flag name='x86-max-cpu'/>
+   <version>2010000</version>
+   <kvmVersion>0</kvmVersion>
+   <microcodeVersion>367995</microcodeVersion>
+diff --git a/tests/qemucapabilitiesdata/caps_2.11.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_2.11.0.x86_64.xml
+index 210f774c4e..32268b29d2 100644
+--- a/tests/qemucapabilitiesdata/caps_2.11.0.x86_64.xml
++++ b/tests/qemucapabilitiesdata/caps_2.11.0.x86_64.xml
+@@ -208,6 +208,7 @@
+   <flag name='mch'/>
+   <flag name='mch.extended-tseg-mbytes'/>
+   <flag name='egl-headless'/>
++  <flag name='x86-max-cpu'/>
+   <version>2011000</version>
+   <kvmVersion>0</kvmVersion>
+   <microcodeVersion>371455</microcodeVersion>
+diff --git a/tests/qemucapabilitiesdata/caps_2.12.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_2.12.0.x86_64.xml
+index f0dc082640..f4416e7b55 100644
+--- a/tests/qemucapabilitiesdata/caps_2.12.0.x86_64.xml
++++ b/tests/qemucapabilitiesdata/caps_2.12.0.x86_64.xml
+@@ -213,6 +213,7 @@
+   <flag name='sev-guest'/>
+   <flag name='egl-headless'/>
+   <flag name='vfio-pci.display'/>
++  <flag name='x86-max-cpu'/>
+   <version>2011090</version>
+   <kvmVersion>0</kvmVersion>
+   <microcodeVersion>416196</microcodeVersion>
+diff --git a/tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml
+index 31ce52c787..e84d153d9a 100644
+--- a/tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml
++++ b/tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml
+@@ -198,6 +198,7 @@
+   <flag name='vmgenid'/>
+   <flag name='vhost-vsock'/>
+   <flag name='mch'/>
++  <flag name='x86-max-cpu'/>
+   <version>2009000</version>
+   <kvmVersion>0</kvmVersion>
+   <microcodeVersion>343984</microcodeVersion>
+diff --git a/tests/qemucapabilitiesdata/caps_3.0.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_3.0.0.x86_64.xml
+index 8992d645e7..dceb719fcf 100644
+--- a/tests/qemucapabilitiesdata/caps_3.0.0.x86_64.xml
++++ b/tests/qemucapabilitiesdata/caps_3.0.0.x86_64.xml
+@@ -215,6 +215,7 @@
+   <flag name='usb-storage.werror'/>
+   <flag name='egl-headless'/>
+   <flag name='vfio-pci.display'/>
++  <flag name='x86-max-cpu'/>
+   <version>2012090</version>
+   <kvmVersion>0</kvmVersion>
+   <microcodeVersion>438109</microcodeVersion>
+diff --git a/tests/qemucapabilitiesdata/caps_4.1.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_4.1.0.x86_64.xml
+index 93c5da537a..4836dbb8a4 100644
+--- a/tests/qemucapabilitiesdata/caps_4.1.0.x86_64.xml
++++ b/tests/qemucapabilitiesdata/caps_4.1.0.x86_64.xml
+@@ -214,6 +214,7 @@
+   <flag name='usb-storage.werror'/>
+   <flag name='egl-headless'/>
+   <flag name='vfio-pci.display'/>
++  <flag name='x86-max-cpu'/>
+   <version>4000050</version>
+   <kvmVersion>0</kvmVersion>
+   <microcodeVersion>456805</microcodeVersion>
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-qemu-Probe-for-unavailable-features-CPU-property.patch b/SOURCES/libvirt-qemu-Probe-for-unavailable-features-CPU-property.patch
new file mode 100644
index 0000000..76c7619
--- /dev/null
+++ b/SOURCES/libvirt-qemu-Probe-for-unavailable-features-CPU-property.patch
@@ -0,0 +1,3972 @@
+From 597dd548f0d5a5ddf662ad748f1b1a9f0a456dce Mon Sep 17 00:00:00 2001
+Message-Id: <597dd548f0d5a5ddf662ad748f1b1a9f0a456dce@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:25:53 +0200
+Subject: [PATCH] qemu: Probe for "unavailable-features" CPU property
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+It is similar to "filtered-features" property, which reports CPUID bits
+corresponding to disabled features, but more general. The
+"unavailable-features" property supports both CPUID and MSR features by
+listing their names.
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit 0d254bce4ec6fd62c0277d24e28bf018a4c6cb37)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1697627
+
+Conflicts:
+	src/qemu/qemu_capabilities.c
+            - several capabilities check are missing
+
+	tests/qemucapabilitiesdata/caps_2.12.0.x86_64.replies
+	tests/qemucapabilitiesdata/caps_3.0.0.x86_64.replies
+	tests/qemucapabilitiesdata/caps_4.1.0.x86_64.replies
+            - QMP message IDs are different
+
+	tests/qemucapabilitiesdata/caps_3.1.0.x86_64.replies
+	tests/qemucapabilitiesdata/caps_4.0.0.x86_64.replies
+            - missing
+
+	tests/qemucapabilitiesdata/caps_2.12.0.x86_64.xml
+	tests/qemucapabilitiesdata/caps_3.0.0.x86_64.xml
+	tests/qemucapabilitiesdata/caps_4.1.0.x86_64.xml
+            - file size based microcode version
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <2cf5c234b2b3e54250f0d8b1e12763d4f8e81247.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/qemu/qemu_capabilities.c                  |    8 +
+ src/qemu/qemu_capabilities.h                  |    1 +
+ .../caps_2.12.0.x86_64.replies                | 1078 ++++++++++++++-
+ .../caps_2.12.0.x86_64.xml                    |    2 +-
+ .../caps_3.0.0.x86_64.replies                 | 1116 +++++++++++++++-
+ .../caps_3.0.0.x86_64.xml                     |    2 +-
+ .../caps_4.1.0.x86_64.replies                 | 1188 ++++++++++++++++-
+ .../caps_4.1.0.x86_64.xml                     |    3 +-
+ 8 files changed, 3317 insertions(+), 81 deletions(-)
+
+diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
+index 4515da4b91..beec9d1497 100644
+--- a/src/qemu/qemu_capabilities.c
++++ b/src/qemu/qemu_capabilities.c
+@@ -515,6 +515,7 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST,
+               "zpci",
+               "machine.pseries.cap-nested-hv",
+               "x86-max-cpu",
++              "cpu-unavailable-features",
+     );
+ 
+ 
+@@ -1452,6 +1453,10 @@ static struct virQEMUCapsStringFlags virQEMUCapsObjectPropsSPAPRMachine[] = {
+     { "cap-nested-hv", QEMU_CAPS_MACHINE_PSERIES_CAP_NESTED_HV },
+ };
+ 
++static struct virQEMUCapsStringFlags virQEMUCapsObjectPropsMaxX86CPU[] = {
++    { "unavailable-features", QEMU_CAPS_CPU_UNAVAILABLE_FEATURES },
++};
++
+ static virQEMUCapsObjectTypeProps virQEMUCapsObjectProps[] = {
+     { "memory-backend-file", virQEMUCapsObjectPropsMemoryBackendFile,
+       ARRAY_CARDINALITY(virQEMUCapsObjectPropsMemoryBackendFile),
+@@ -1459,6 +1464,9 @@ static virQEMUCapsObjectTypeProps virQEMUCapsObjectProps[] = {
+     { "spapr-machine", virQEMUCapsObjectPropsSPAPRMachine,
+       ARRAY_CARDINALITY(virQEMUCapsObjectPropsSPAPRMachine),
+       -1 },
++    { "max-x86_64-cpu", virQEMUCapsObjectPropsMaxX86CPU,
++      ARRAY_CARDINALITY(virQEMUCapsObjectPropsMaxX86CPU),
++      QEMU_CAPS_X86_MAX_CPU },
+ };
+ 
+ static void
+diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
+index 25ed5064b9..5aa41efdb0 100644
+--- a/src/qemu/qemu_capabilities.h
++++ b/src/qemu/qemu_capabilities.h
+@@ -495,6 +495,7 @@ typedef enum { /* virQEMUCapsFlags grouping marker for syntax-check */
+     QEMU_CAPS_DEVICE_ZPCI, /* -device zpci */
+     QEMU_CAPS_MACHINE_PSERIES_CAP_NESTED_HV, /* -machine pseries.cap-nested-hv */
+     QEMU_CAPS_X86_MAX_CPU, /* max-x86_64-cpu type exists */
++    QEMU_CAPS_CPU_UNAVAILABLE_FEATURES, /* "unavailable-features" CPU property */
+ 
+     QEMU_CAPS_LAST /* this must always be the last item */
+ } virQEMUCapsFlags;
+diff --git a/tests/qemucapabilitiesdata/caps_2.12.0.x86_64.replies b/tests/qemucapabilitiesdata/caps_2.12.0.x86_64.replies
+index 6f37e4301e..66a5577e5e 100644
+--- a/tests/qemucapabilitiesdata/caps_2.12.0.x86_64.replies
++++ b/tests/qemucapabilitiesdata/caps_2.12.0.x86_64.replies
+@@ -5011,10 +5011,1040 @@
+ }
+ 
+ {
+-  "execute": "query-machines",
++  "execute": "qom-list-properties",
++  "arguments": {
++    "typename": "max-x86_64-cpu"
++  },
+   "id": "libvirt-43"
+ }
+ 
++{
++  "return": [
++    {
++      "name": "min-xlevel2",
++      "type": "uint32"
++    },
++    {
++      "name": "vendor",
++      "type": "string"
++    },
++    {
++      "name": "gfni",
++      "type": "bool"
++    },
++    {
++      "name": "clwb",
++      "type": "bool"
++    },
++    {
++      "name": "nx",
++      "type": "bool"
++    },
++    {
++      "name": "x2apic",
++      "type": "bool"
++    },
++    {
++      "name": "kvmclock-stable-bit",
++      "type": "bool"
++    },
++    {
++      "name": "vmcb_clean",
++      "type": "bool"
++    },
++    {
++      "name": "min-level",
++      "type": "uint32"
++    },
++    {
++      "name": "fxsr-opt",
++      "type": "bool"
++    },
++    {
++      "name": "skinit",
++      "type": "bool"
++    },
++    {
++      "name": "avx",
++      "type": "bool"
++    },
++    {
++      "name": "3dnowext",
++      "type": "bool"
++    },
++    {
++      "name": "hv-crash",
++      "type": "bool"
++    },
++    {
++      "name": "nodeid_msr",
++      "type": "bool"
++    },
++    {
++      "name": "hypervisor",
++      "type": "bool"
++    },
++    {
++      "name": "enforce",
++      "type": "bool"
++    },
++    {
++      "name": "stepping",
++      "type": "int"
++    },
++    {
++      "name": "sse4_2",
++      "type": "bool"
++    },
++    {
++      "name": "sse4_1",
++      "type": "bool"
++    },
++    {
++      "name": "x-hv-max-vps",
++      "type": "int32"
++    },
++    {
++      "name": "hv-frequencies",
++      "type": "bool"
++    },
++    {
++      "name": "kvm-hint-dedicated",
++      "type": "bool"
++    },
++    {
++      "name": "cmp_legacy",
++      "type": "bool"
++    },
++    {
++      "name": "tm2",
++      "type": "bool"
++    },
++    {
++      "name": "smx",
++      "type": "bool"
++    },
++    {
++      "name": "host-cache-info",
++      "type": "bool"
++    },
++    {
++      "name": "hv-vendor-id",
++      "type": "str"
++    },
++    {
++      "name": "movbe",
++      "type": "bool"
++    },
++    {
++      "name": "3dnowprefetch",
++      "type": "bool"
++    },
++    {
++      "name": "mtrr",
++      "type": "bool"
++    },
++    {
++      "name": "wdt",
++      "type": "bool"
++    },
++    {
++      "name": "thread-id",
++      "type": "int32"
++    },
++    {
++      "name": "aes",
++      "type": "bool"
++    },
++    {
++      "name": "apic-id",
++      "type": "uint32"
++    },
++    {
++      "name": "lm",
++      "type": "bool"
++    },
++    {
++      "name": "family",
++      "type": "int"
++    },
++    {
++      "name": "tsc-adjust",
++      "type": "bool"
++    },
++    {
++      "name": "pfthreshold",
++      "type": "bool"
++    },
++    {
++      "name": "ospke",
++      "type": "bool"
++    },
++    {
++      "name": "kvm-no-smi-migration",
++      "type": "bool"
++    },
++    {
++      "name": "pse",
++      "type": "bool"
++    },
++    {
++      "name": "filtered-features",
++      "type": "X86CPUFeatureWordInfo"
++    },
++    {
++      "name": "hv-vpindex",
++      "type": "bool"
++    },
++    {
++      "name": "adx",
++      "type": "bool"
++    },
++    {
++      "name": "avx512bitalg",
++      "type": "bool"
++    },
++    {
++      "name": "i64",
++      "type": "bool"
++    },
++    {
++      "name": "vaes",
++      "type": "bool"
++    },
++    {
++      "name": "ia64",
++      "type": "bool"
++    },
++    {
++      "name": "nodeid-msr",
++      "type": "bool"
++    },
++    {
++      "name": "ibpb",
++      "type": "bool"
++    },
++    {
++      "name": "hv-synic",
++      "type": "bool"
++    },
++    {
++      "name": "ibs",
++      "type": "bool"
++    },
++    {
++      "name": "kvm_mmu",
++      "type": "bool"
++    },
++    {
++      "name": "tcg-cpuid",
++      "type": "bool"
++    },
++    {
++      "name": "nrip_save",
++      "type": "bool"
++    },
++    {
++      "name": "kvm_nopiodelay",
++      "type": "bool"
++    },
++    {
++      "name": "lbrv",
++      "type": "bool"
++    },
++    {
++      "name": "rdtscp",
++      "type": "bool"
++    },
++    {
++      "name": "memory",
++      "type": "link<qemu:memory-region>"
++    },
++    {
++      "name": "avx512vbmi2",
++      "type": "bool"
++    },
++    {
++      "name": "ace2-en",
++      "type": "bool"
++    },
++    {
++      "name": "invtsc",
++      "type": "bool"
++    },
++    {
++      "name": "sse4.2",
++      "type": "bool"
++    },
++    {
++      "name": "sse4.1",
++      "type": "bool"
++    },
++    {
++      "name": "pbe",
++      "type": "bool"
++    },
++    {
++      "name": "rdrand",
++      "type": "bool"
++    },
++    {
++      "name": "socket-id",
++      "type": "int32"
++    },
++    {
++      "name": "hotpluggable",
++      "type": "bool"
++    },
++    {
++      "name": "kvm-steal-time",
++      "type": "bool"
++    },
++    {
++      "name": "l3-cache",
++      "type": "bool"
++    },
++    {
++      "name": "vmware-cpuid-freq",
++      "type": "bool"
++    },
++    {
++      "name": "xop",
++      "type": "bool"
++    },
++    {
++      "name": "tsc-frequency",
++      "type": "int"
++    },
++    {
++      "name": "fill-mtrr-mask",
++      "type": "bool"
++    },
++    {
++      "name": "core-id",
++      "type": "int32"
++    },
++    {
++      "name": "intel-pt",
++      "type": "bool"
++    },
++    {
++      "name": "pat",
++      "type": "bool"
++    },
++    {
++      "name": "pcid",
++      "type": "bool"
++    },
++    {
++      "name": "pclmulqdq",
++      "type": "bool"
++    },
++    {
++      "name": "sse4-2",
++      "type": "bool"
++    },
++    {
++      "name": "sse4-1",
++      "type": "bool"
++    },
++    {
++      "name": "sha-ni",
++      "type": "bool"
++    },
++    {
++      "name": "cmov",
++      "type": "bool"
++    },
++    {
++      "name": "pae",
++      "type": "bool"
++    },
++    {
++      "name": "smep",
++      "type": "bool"
++    },
++    {
++      "name": "abm",
++      "type": "bool"
++    },
++    {
++      "name": "xstore",
++      "type": "bool"
++    },
++    {
++      "name": "tsc_adjust",
++      "type": "bool"
++    },
++    {
++      "name": "type",
++      "type": "string"
++    },
++    {
++      "name": "kvm-asyncpf",
++      "type": "bool"
++    },
++    {
++      "name": "min-xlevel",
++      "type": "uint32"
++    },
++    {
++      "name": "pdpe1gb",
++      "type": "bool"
++    },
++    {
++      "name": "kvm-mmu",
++      "type": "bool"
++    },
++    {
++      "name": "kvm-pv-unhalt",
++      "type": "bool"
++    },
++    {
++      "name": "avx512f",
++      "type": "bool"
++    },
++    {
++      "name": "avx512vbmi",
++      "type": "bool"
++    },
++    {
++      "name": "avx512-4vnniw",
++      "type": "bool"
++    },
++    {
++      "name": "xd",
++      "type": "bool"
++    },
++    {
++      "name": "mmxext",
++      "type": "bool"
++    },
++    {
++      "name": "decodeassists",
++      "type": "bool"
++    },
++    {
++      "name": "ht",
++      "type": "bool"
++    },
++    {
++      "name": "xsave",
++      "type": "bool"
++    },
++    {
++      "name": "perfctr_core",
++      "type": "bool"
++    },
++    {
++      "name": "feature-words",
++      "type": "X86CPUFeatureWordInfo"
++    },
++    {
++      "name": "migratable",
++      "type": "bool"
++    },
++    {
++      "name": "3dnow",
++      "type": "bool"
++    },
++    {
++      "name": "spec-ctrl",
++      "type": "bool"
++    },
++    {
++      "name": "model",
++      "type": "int"
++    },
++    {
++      "name": "nrip-save",
++      "type": "bool"
++    },
++    {
++      "name": "lwp",
++      "type": "bool"
++    },
++    {
++      "name": "xstore-en",
++      "type": "bool"
++    },
++    {
++      "name": "avx512vl",
++      "type": "bool"
++    },
++    {
++      "name": "kvm_pv_unhalt",
++      "type": "bool"
++    },
++    {
++      "name": "bmi2",
++      "type": "bool"
++    },
++    {
++      "name": "bmi1",
++      "type": "bool"
++    },
++    {
++      "name": "la57",
++      "type": "bool"
++    },
++    {
++      "name": "ffxsr",
++      "type": "bool"
++    },
++    {
++      "name": "vmcb-clean",
++      "type": "bool"
++    },
++    {
++      "name": "pause-filter",
++      "type": "bool"
++    },
++    {
++      "name": "pni",
++      "type": "bool"
++    },
++    {
++      "name": "kvm_steal_time",
++      "type": "bool"
++    },
++    {
++      "name": "svm_lock",
++      "type": "bool"
++    },
++    {
++      "name": "pse36",
++      "type": "bool"
++    },
++    {
++      "name": "hv-stimer",
++      "type": "bool"
++    },
++    {
++      "name": "host-phys-bits",
++      "type": "bool"
++    },
++    {
++      "name": "extapic",
++      "type": "bool"
++    },
++    {
++      "name": "hv-spinlocks",
++      "type": "int"
++    },
++    {
++      "name": "pmu",
++      "type": "bool"
++    },
++    {
++      "name": "pmm",
++      "type": "bool"
++    },
++    {
++      "name": "vpclmulqdq",
++      "type": "bool"
++    },
++    {
++      "name": "avx512-vpopcntdq",
++      "type": "bool"
++    },
++    {
++      "name": "avx512er",
++      "type": "bool"
++    },
++    {
++      "name": "pdcm",
++      "type": "bool"
++    },
++    {
++      "name": "svm",
++      "type": "bool"
++    },
++    {
++      "name": "apic",
++      "type": "bool"
++    },
++    {
++      "name": "xcrypt-en",
++      "type": "bool"
++    },
++    {
++      "name": "cr8legacy",
++      "type": "bool"
++    },
++    {
++      "name": "fma4",
++      "type": "bool"
++    },
++    {
++      "name": "erms",
++      "type": "bool"
++    },
++    {
++      "name": "msr",
++      "type": "bool"
++    },
++    {
++      "name": "ds_cpl",
++      "type": "bool"
++    },
++    {
++      "name": "xlevel",
++      "type": "uint32"
++    },
++    {
++      "name": "hotplugged",
++      "type": "bool"
++    },
++    {
++      "name": "hv-relaxed",
++      "type": "bool"
++    },
++    {
++      "name": "perfctr-core",
++      "type": "bool"
++    },
++    {
++      "name": "sep",
++      "type": "bool"
++    },
++    {
++      "name": "smap",
++      "type": "bool"
++    },
++    {
++      "name": "sse3",
++      "type": "bool"
++    },
++    {
++      "name": "avx512dq",
++      "type": "bool"
++    },
++    {
++      "name": "ssse3",
++      "type": "bool"
++    },
++    {
++      "name": "pmm-en",
++      "type": "bool"
++    },
++    {
++      "name": "npt",
++      "type": "bool"
++    },
++    {
++      "name": "kvm-pv-tlb-flush",
++      "type": "bool"
++    },
++    {
++      "name": "tsc",
++      "type": "bool"
++    },
++    {
++      "name": "monitor",
++      "type": "bool"
++    },
++    {
++      "name": "f16c",
++      "type": "bool"
++    },
++    {
++      "name": "sse2",
++      "type": "bool"
++    },
++    {
++      "name": "rdpid",
++      "type": "bool"
++    },
++    {
++      "name": "mce",
++      "type": "bool"
++    },
++    {
++      "name": "full-cpuid-auto-level",
++      "type": "bool"
++    },
++    {
++      "name": "xtpr",
++      "type": "bool"
++    },
++    {
++      "name": "mca",
++      "type": "bool"
++    },
++    {
++      "name": "cid",
++      "type": "bool"
++    },
++    {
++      "name": "tm",
++      "type": "bool"
++    },
++    {
++      "name": "pku",
++      "type": "bool"
++    },
++    {
++      "name": "avx512vnni",
++      "type": "bool"
++    },
++    {
++      "name": "tce",
++      "type": "bool"
++    },
++    {
++      "name": "kvmclock",
++      "type": "bool"
++    },
++    {
++      "name": "sse4a",
++      "type": "bool"
++    },
++    {
++      "name": "ds",
++      "type": "bool"
++    },
++    {
++      "name": "lahf-lm",
++      "type": "bool"
++    },
++    {
++      "name": "xsaves",
++      "type": "bool"
++    },
++    {
++      "name": "clflushopt",
++      "type": "bool"
++    },
++    {
++      "name": "kvm",
++      "type": "bool"
++    },
++    {
++      "name": "ss",
++      "type": "bool"
++    },
++    {
++      "name": "flushbyasid",
++      "type": "bool"
++    },
++    {
++      "name": "pause_filter",
++      "type": "bool"
++    },
++    {
++      "name": "de",
++      "type": "bool"
++    },
++    {
++      "name": "est",
++      "type": "bool"
++    },
++    {
++      "name": "check",
++      "type": "bool"
++    },
++    {
++      "name": "lahf_lm",
++      "type": "bool"
++    },
++    {
++      "name": "dtes64",
++      "type": "bool"
++    },
++    {
++      "name": "vmx",
++      "type": "bool"
++    },
++    {
++      "name": "xsavec",
++      "type": "bool"
++    },
++    {
++      "name": "svm-lock",
++      "type": "bool"
++    },
++    {
++      "name": "avx512ifma",
++      "type": "bool"
++    },
++    {
++      "name": "clflush",
++      "type": "bool"
++    },
++    {
++      "name": "rdseed",
++      "type": "bool"
++    },
++    {
++      "name": "avx512cd",
++      "type": "bool"
++    },
++    {
++      "name": "xsaveopt",
++      "type": "bool"
++    },
++    {
++      "name": "tbm",
++      "type": "bool"
++    },
++    {
++      "name": "ace2",
++      "type": "bool"
++    },
++    {
++      "name": "vme",
++      "type": "bool"
++    },
++    {
++      "name": "kvm_asyncpf",
++      "type": "bool"
++    },
++    {
++      "name": "hv-vapic",
++      "type": "bool"
++    },
++    {
++      "name": "parent_bus",
++      "type": "link<bus>"
++    },
++    {
++      "name": "lmce",
++      "type": "bool"
++    },
++    {
++      "name": "hv-reset",
++      "type": "bool"
++    },
++    {
++      "name": "hv-runtime",
++      "type": "bool"
++    },
++    {
++      "name": "avx512bw",
++      "type": "bool"
++    },
++    {
++      "name": "xcrypt",
++      "type": "bool"
++    },
++    {
++      "name": "fpu",
++      "type": "bool"
++    },
++    {
++      "name": "fxsr",
++      "type": "bool"
++    },
++    {
++      "name": "ds-cpl",
++      "type": "bool"
++    },
++    {
++      "name": "kvm-pv-eoi",
++      "type": "bool"
++    },
++    {
++      "name": "hle",
++      "type": "bool"
++    },
++    {
++      "name": "cx8",
++      "type": "bool"
++    },
++    {
++      "name": "mpx",
++      "type": "bool"
++    },
++    {
++      "name": "invpcid",
++      "type": "bool"
++    },
++    {
++      "name": "pcommit",
++      "type": "bool"
++    },
++    {
++      "name": "arat",
++      "type": "bool"
++    },
++    {
++      "name": "sse",
++      "type": "bool"
++    },
++    {
++      "name": "syscall",
++      "type": "bool"
++    },
++    {
++      "name": "tsc_scale",
++      "type": "bool"
++    },
++    {
++      "name": "xlevel2",
++      "type": "uint32"
++    },
++    {
++      "name": "hv-time",
++      "type": "bool"
++    },
++    {
++      "name": "kvm_pv_eoi",
++      "type": "bool"
++    },
++    {
++      "name": "osvw",
++      "type": "bool"
++    },
++    {
++      "name": "perfctr-nb",
++      "type": "bool"
++    },
++    {
++      "name": "rtm",
++      "type": "bool"
++    },
++    {
++      "name": "avx512-4fmaps",
++      "type": "bool"
++    },
++    {
++      "name": "avx2",
++      "type": "bool"
++    },
++    {
++      "name": "perfctr_nb",
++      "type": "bool"
++    },
++    {
++      "name": "kvm-nopiodelay",
++      "type": "bool"
++    },
++    {
++      "name": "phys-bits",
++      "type": "uint32"
++    },
++    {
++      "name": "avx512pf",
++      "type": "bool"
++    },
++    {
++      "name": "level",
++      "type": "uint32"
++    },
++    {
++      "name": "osxsave",
++      "type": "bool"
++    },
++    {
++      "name": "cpuid-0xb",
++      "type": "bool"
++    },
++    {
++      "name": "tsc-deadline",
++      "type": "bool"
++    },
++    {
++      "name": "xgetbv1",
++      "type": "bool"
++    },
++    {
++      "name": "fxsr_opt",
++      "type": "bool"
++    },
++    {
++      "name": "popcnt",
++      "type": "bool"
++    },
++    {
++      "name": "umip",
++      "type": "bool"
++    },
++    {
++      "name": "realized",
++      "type": "bool"
++    },
++    {
++      "name": "phe",
++      "type": "bool"
++    },
++    {
++      "name": "cmp-legacy",
++      "type": "bool"
++    },
++    {
++      "name": "dca",
++      "type": "bool"
++    },
++    {
++      "name": "acpi",
++      "type": "bool"
++    },
++    {
++      "name": "pn",
++      "type": "bool"
++    },
++    {
++      "name": "model-id",
++      "type": "string"
++    },
++    {
++      "name": "crash-information",
++      "type": "GuestPanicInformation"
++    },
++    {
++      "name": "tsc-scale",
++      "type": "bool"
++    },
++    {
++      "name": "node-id",
++      "type": "int32"
++    },
++    {
++      "name": "cx16",
++      "type": "bool"
++    },
++    {
++      "name": "mmx",
++      "type": "bool"
++    },
++    {
++      "name": "topoext",
++      "type": "bool"
++    },
++    {
++      "name": "pge",
++      "type": "bool"
++    },
++    {
++      "name": "fsgsbase",
++      "type": "bool"
++    },
++    {
++      "name": "pclmuldq",
++      "type": "bool"
++    },
++    {
++      "name": "misalignsse",
++      "type": "bool"
++    },
++    {
++      "name": "phe-en",
++      "type": "bool"
++    },
++    {
++      "name": "fma",
++      "type": "bool"
++    }
++  ],
++  "id": "libvirt-43"
++}
++
++{
++  "execute": "query-machines",
++  "id": "libvirt-44"
++}
++
+ {
+   "return": [
+     {
+@@ -5211,12 +6241,12 @@
+       "cpu-max": 255
+     }
+   ],
+-  "id": "libvirt-43"
++  "id": "libvirt-44"
+ }
+ 
+ {
+   "execute": "query-cpu-definitions",
+-  "id": "libvirt-44"
++  "id": "libvirt-45"
+ }
+ 
+ {
+@@ -5730,12 +6760,12 @@
+       "migration-safe": true
+     }
+   ],
+-  "id": "libvirt-44"
++  "id": "libvirt-45"
+ }
+ 
+ {
+   "execute": "query-tpm-models",
+-  "id": "libvirt-45"
++  "id": "libvirt-46"
+ }
+ 
+ {
+@@ -5743,12 +6773,12 @@
+     "tpm-crb",
+     "tpm-tis"
+   ],
+-  "id": "libvirt-45"
++  "id": "libvirt-46"
+ }
+ 
+ {
+   "execute": "query-tpm-types",
+-  "id": "libvirt-46"
++  "id": "libvirt-47"
+ }
+ 
+ {
+@@ -5756,12 +6786,12 @@
+     "passthrough",
+     "emulator"
+   ],
+-  "id": "libvirt-46"
++  "id": "libvirt-47"
+ }
+ 
+ {
+   "execute": "query-command-line-options",
+-  "id": "libvirt-47"
++  "id": "libvirt-48"
+ }
+ 
+ {
+@@ -7048,12 +8078,12 @@
+       "option": "drive"
+     }
+   ],
+-  "id": "libvirt-47"
++  "id": "libvirt-48"
+ }
+ 
+ {
+   "execute": "query-migrate-capabilities",
+-  "id": "libvirt-48"
++  "id": "libvirt-49"
+ }
+ 
+ {
+@@ -7115,12 +8145,12 @@
+       "capability": "dirty-bitmaps"
+     }
+   ],
+-  "id": "libvirt-48"
++  "id": "libvirt-49"
+ }
+ 
+ {
+   "execute": "query-qmp-schema",
+-  "id": "libvirt-49"
++  "id": "libvirt-50"
+ }
+ 
+ {
+@@ -18488,7 +19518,7 @@
+       "meta-type": "object"
+     }
+   ],
+-  "id": "libvirt-49"
++  "id": "libvirt-50"
+ }
+ 
+ {
+@@ -18499,7 +19529,7 @@
+       "name": "host"
+     }
+   },
+-  "id": "libvirt-50"
++  "id": "libvirt-51"
+ }
+ 
+ {
+@@ -18689,7 +19719,7 @@
+       }
+     }
+   },
+-  "id": "libvirt-50"
++  "id": "libvirt-51"
+ }
+ 
+ {
+@@ -18881,7 +19911,7 @@
+       }
+     }
+   },
+-  "id": "libvirt-51"
++  "id": "libvirt-52"
+ }
+ 
+ {
+@@ -19136,7 +20166,7 @@
+       }
+     }
+   },
+-  "id": "libvirt-51"
++  "id": "libvirt-52"
+ }
+ 
+ {
+@@ -19150,7 +20180,7 @@
+       }
+     }
+   },
+-  "id": "libvirt-52"
++  "id": "libvirt-53"
+ }
+ 
+ {
+@@ -19340,7 +20370,7 @@
+       }
+     }
+   },
+-  "id": "libvirt-52"
++  "id": "libvirt-53"
+ }
+ 
+ {
+@@ -19532,7 +20562,7 @@
+       }
+     }
+   },
+-  "id": "libvirt-53"
++  "id": "libvirt-54"
+ }
+ 
+ {
+@@ -19787,12 +20817,12 @@
+       }
+     }
+   },
+-  "id": "libvirt-53"
++  "id": "libvirt-54"
+ }
+ 
+ {
+   "execute": "query-sev-capabilities",
+-  "id": "libvirt-54"
++  "id": "libvirt-55"
+ }
+ 
+ {
+@@ -19802,7 +20832,7 @@
+     "cert-chain": "AQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAA",
+     "pdh": "AQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAA"
+   },
+-  "id": "libvirt-54"
++  "id": "libvirt-55"
+ }
+ 
+ {
+diff --git a/tests/qemucapabilitiesdata/caps_2.12.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_2.12.0.x86_64.xml
+index f4416e7b55..a8a82ca110 100644
+--- a/tests/qemucapabilitiesdata/caps_2.12.0.x86_64.xml
++++ b/tests/qemucapabilitiesdata/caps_2.12.0.x86_64.xml
+@@ -216,7 +216,7 @@
+   <flag name='x86-max-cpu'/>
+   <version>2011090</version>
+   <kvmVersion>0</kvmVersion>
+-  <microcodeVersion>416196</microcodeVersion>
++  <microcodeVersion>431483</microcodeVersion>
+   <package>v2.12.0-rc0</package>
+   <arch>x86_64</arch>
+   <hostCPU type='kvm' model='base' migratability='yes'>
+diff --git a/tests/qemucapabilitiesdata/caps_3.0.0.x86_64.replies b/tests/qemucapabilitiesdata/caps_3.0.0.x86_64.replies
+index b2f8377248..9f44eb4fae 100644
+--- a/tests/qemucapabilitiesdata/caps_3.0.0.x86_64.replies
++++ b/tests/qemucapabilitiesdata/caps_3.0.0.x86_64.replies
+@@ -5123,10 +5123,1072 @@
+ }
+ 
+ {
+-  "execute": "query-machines",
++  "execute": "qom-list-properties",
++  "arguments": {
++    "typename": "max-x86_64-cpu"
++  },
+   "id": "libvirt-43"
+ }
+ 
++{
++  "return": [
++    {
++      "name": "min-xlevel2",
++      "type": "uint32"
++    },
++    {
++      "name": "amd-ssbd",
++      "type": "bool"
++    },
++    {
++      "name": "vendor",
++      "type": "string"
++    },
++    {
++      "name": "gfni",
++      "type": "bool"
++    },
++    {
++      "name": "clwb",
++      "type": "bool"
++    },
++    {
++      "name": "nx",
++      "type": "bool"
++    },
++    {
++      "name": "x2apic",
++      "type": "bool"
++    },
++    {
++      "name": "kvmclock-stable-bit",
++      "type": "bool"
++    },
++    {
++      "name": "vmcb_clean",
++      "type": "bool"
++    },
++    {
++      "name": "min-level",
++      "type": "uint32"
++    },
++    {
++      "name": "fxsr-opt",
++      "type": "bool"
++    },
++    {
++      "name": "skinit",
++      "type": "bool"
++    },
++    {
++      "name": "avx",
++      "type": "bool"
++    },
++    {
++      "name": "3dnowext",
++      "type": "bool"
++    },
++    {
++      "name": "nodeid_msr",
++      "type": "bool"
++    },
++    {
++      "name": "hv-crash",
++      "type": "bool"
++    },
++    {
++      "name": "hypervisor",
++      "type": "bool"
++    },
++    {
++      "name": "enforce",
++      "type": "bool"
++    },
++    {
++      "name": "stepping",
++      "type": "int"
++    },
++    {
++      "name": "sse4_2",
++      "type": "bool"
++    },
++    {
++      "name": "sse4_1",
++      "type": "bool"
++    },
++    {
++      "name": "x-hv-max-vps",
++      "type": "int32"
++    },
++    {
++      "name": "hv-frequencies",
++      "type": "bool"
++    },
++    {
++      "name": "kvm-hint-dedicated",
++      "type": "bool"
++    },
++    {
++      "name": "cmp_legacy",
++      "type": "bool"
++    },
++    {
++      "name": "tm2",
++      "type": "bool"
++    },
++    {
++      "name": "smx",
++      "type": "bool"
++    },
++    {
++      "name": "host-cache-info",
++      "type": "bool"
++    },
++    {
++      "name": "hv-vendor-id",
++      "type": "str"
++    },
++    {
++      "name": "movbe",
++      "type": "bool"
++    },
++    {
++      "name": "3dnowprefetch",
++      "type": "bool"
++    },
++    {
++      "name": "mtrr",
++      "type": "bool"
++    },
++    {
++      "name": "wdt",
++      "type": "bool"
++    },
++    {
++      "name": "thread-id",
++      "type": "int32"
++    },
++    {
++      "name": "aes",
++      "type": "bool"
++    },
++    {
++      "name": "apic-id",
++      "type": "uint32"
++    },
++    {
++      "name": "lm",
++      "type": "bool"
++    },
++    {
++      "name": "family",
++      "type": "int"
++    },
++    {
++      "name": "tsc-adjust",
++      "type": "bool"
++    },
++    {
++      "name": "pfthreshold",
++      "type": "bool"
++    },
++    {
++      "name": "kvm-no-smi-migration",
++      "type": "bool"
++    },
++    {
++      "name": "amd-no-ssb",
++      "type": "bool"
++    },
++    {
++      "name": "pse",
++      "type": "bool"
++    },
++    {
++      "name": "filtered-features",
++      "type": "X86CPUFeatureWordInfo"
++    },
++    {
++      "name": "hv-vpindex",
++      "type": "bool"
++    },
++    {
++      "name": "adx",
++      "type": "bool"
++    },
++    {
++      "name": "avx512bitalg",
++      "type": "bool"
++    },
++    {
++      "name": "i64",
++      "type": "bool"
++    },
++    {
++      "name": "vaes",
++      "type": "bool"
++    },
++    {
++      "name": "ia64",
++      "type": "bool"
++    },
++    {
++      "name": "nodeid-msr",
++      "type": "bool"
++    },
++    {
++      "name": "ibpb",
++      "type": "bool"
++    },
++    {
++      "name": "hv-synic",
++      "type": "bool"
++    },
++    {
++      "name": "ibs",
++      "type": "bool"
++    },
++    {
++      "name": "kvm_mmu",
++      "type": "bool"
++    },
++    {
++      "name": "tcg-cpuid",
++      "type": "bool"
++    },
++    {
++      "name": "nrip_save",
++      "type": "bool"
++    },
++    {
++      "name": "kvm_nopiodelay",
++      "type": "bool"
++    },
++    {
++      "name": "lbrv",
++      "type": "bool"
++    },
++    {
++      "name": "rdtscp",
++      "type": "bool"
++    },
++    {
++      "name": "memory",
++      "type": "link<qemu:memory-region>"
++    },
++    {
++      "name": "avx512vbmi2",
++      "type": "bool"
++    },
++    {
++      "name": "ace2-en",
++      "type": "bool"
++    },
++    {
++      "name": "invtsc",
++      "type": "bool"
++    },
++    {
++      "name": "sse4.2",
++      "type": "bool"
++    },
++    {
++      "name": "sse4.1",
++      "type": "bool"
++    },
++    {
++      "name": "pbe",
++      "type": "bool"
++    },
++    {
++      "name": "rdrand",
++      "type": "bool"
++    },
++    {
++      "name": "socket-id",
++      "type": "int32"
++    },
++    {
++      "name": "hotpluggable",
++      "type": "bool"
++    },
++    {
++      "name": "l3-cache",
++      "type": "bool"
++    },
++    {
++      "name": "kvm-steal-time",
++      "type": "bool"
++    },
++    {
++      "name": "vmware-cpuid-freq",
++      "type": "bool"
++    },
++    {
++      "name": "legacy-cache",
++      "type": "bool"
++    },
++    {
++      "name": "xop",
++      "type": "bool"
++    },
++    {
++      "name": "tsc-frequency",
++      "type": "int"
++    },
++    {
++      "name": "fill-mtrr-mask",
++      "type": "bool"
++    },
++    {
++      "name": "core-id",
++      "type": "int32"
++    },
++    {
++      "name": "intel-pt",
++      "type": "bool"
++    },
++    {
++      "name": "pat",
++      "type": "bool"
++    },
++    {
++      "name": "pcid",
++      "type": "bool"
++    },
++    {
++      "name": "pclmulqdq",
++      "type": "bool"
++    },
++    {
++      "name": "sse4-2",
++      "type": "bool"
++    },
++    {
++      "name": "sse4-1",
++      "type": "bool"
++    },
++    {
++      "name": "sha-ni",
++      "type": "bool"
++    },
++    {
++      "name": "cmov",
++      "type": "bool"
++    },
++    {
++      "name": "pae",
++      "type": "bool"
++    },
++    {
++      "name": "smep",
++      "type": "bool"
++    },
++    {
++      "name": "virt-ssbd",
++      "type": "bool"
++    },
++    {
++      "name": "abm",
++      "type": "bool"
++    },
++    {
++      "name": "xstore",
++      "type": "bool"
++    },
++    {
++      "name": "tsc_adjust",
++      "type": "bool"
++    },
++    {
++      "name": "type",
++      "type": "string"
++    },
++    {
++      "name": "kvm-asyncpf",
++      "type": "bool"
++    },
++    {
++      "name": "pdpe1gb",
++      "type": "bool"
++    },
++    {
++      "name": "min-xlevel",
++      "type": "uint32"
++    },
++    {
++      "name": "kvm-mmu",
++      "type": "bool"
++    },
++    {
++      "name": "kvm-pv-unhalt",
++      "type": "bool"
++    },
++    {
++      "name": "avx512f",
++      "type": "bool"
++    },
++    {
++      "name": "avx512vbmi",
++      "type": "bool"
++    },
++    {
++      "name": "avx512-4vnniw",
++      "type": "bool"
++    },
++    {
++      "name": "xd",
++      "type": "bool"
++    },
++    {
++      "name": "mmxext",
++      "type": "bool"
++    },
++    {
++      "name": "decodeassists",
++      "type": "bool"
++    },
++    {
++      "name": "ht",
++      "type": "bool"
++    },
++    {
++      "name": "xsave",
++      "type": "bool"
++    },
++    {
++      "name": "perfctr_core",
++      "type": "bool"
++    },
++    {
++      "name": "feature-words",
++      "type": "X86CPUFeatureWordInfo"
++    },
++    {
++      "name": "migratable",
++      "type": "bool"
++    },
++    {
++      "name": "3dnow",
++      "type": "bool"
++    },
++    {
++      "name": "spec-ctrl",
++      "type": "bool"
++    },
++    {
++      "name": "model",
++      "type": "int"
++    },
++    {
++      "name": "nrip-save",
++      "type": "bool"
++    },
++    {
++      "name": "lwp",
++      "type": "bool"
++    },
++    {
++      "name": "xstore-en",
++      "type": "bool"
++    },
++    {
++      "name": "avx512vl",
++      "type": "bool"
++    },
++    {
++      "name": "kvm_pv_unhalt",
++      "type": "bool"
++    },
++    {
++      "name": "bmi2",
++      "type": "bool"
++    },
++    {
++      "name": "bmi1",
++      "type": "bool"
++    },
++    {
++      "name": "la57",
++      "type": "bool"
++    },
++    {
++      "name": "ffxsr",
++      "type": "bool"
++    },
++    {
++      "name": "vmcb-clean",
++      "type": "bool"
++    },
++    {
++      "name": "pause-filter",
++      "type": "bool"
++    },
++    {
++      "name": "pni",
++      "type": "bool"
++    },
++    {
++      "name": "kvm_steal_time",
++      "type": "bool"
++    },
++    {
++      "name": "svm_lock",
++      "type": "bool"
++    },
++    {
++      "name": "pse36",
++      "type": "bool"
++    },
++    {
++      "name": "hv-stimer",
++      "type": "bool"
++    },
++    {
++      "name": "host-phys-bits",
++      "type": "bool"
++    },
++    {
++      "name": "extapic",
++      "type": "bool"
++    },
++    {
++      "name": "hv-spinlocks",
++      "type": "int"
++    },
++    {
++      "name": "pmu",
++      "type": "bool"
++    },
++    {
++      "name": "pmm",
++      "type": "bool"
++    },
++    {
++      "name": "vpclmulqdq",
++      "type": "bool"
++    },
++    {
++      "name": "avx512-vpopcntdq",
++      "type": "bool"
++    },
++    {
++      "name": "avx512er",
++      "type": "bool"
++    },
++    {
++      "name": "pdcm",
++      "type": "bool"
++    },
++    {
++      "name": "svm",
++      "type": "bool"
++    },
++    {
++      "name": "apic",
++      "type": "bool"
++    },
++    {
++      "name": "xcrypt-en",
++      "type": "bool"
++    },
++    {
++      "name": "cr8legacy",
++      "type": "bool"
++    },
++    {
++      "name": "fma4",
++      "type": "bool"
++    },
++    {
++      "name": "erms",
++      "type": "bool"
++    },
++    {
++      "name": "msr",
++      "type": "bool"
++    },
++    {
++      "name": "ds_cpl",
++      "type": "bool"
++    },
++    {
++      "name": "xlevel",
++      "type": "uint32"
++    },
++    {
++      "name": "sep",
++      "type": "bool"
++    },
++    {
++      "name": "hotplugged",
++      "type": "bool"
++    },
++    {
++      "name": "hv-relaxed",
++      "type": "bool"
++    },
++    {
++      "name": "cldemote",
++      "type": "bool"
++    },
++    {
++      "name": "perfctr-core",
++      "type": "bool"
++    },
++    {
++      "name": "avx512vnni",
++      "type": "bool"
++    },
++    {
++      "name": "smap",
++      "type": "bool"
++    },
++    {
++      "name": "sse3",
++      "type": "bool"
++    },
++    {
++      "name": "avx512dq",
++      "type": "bool"
++    },
++    {
++      "name": "ssse3",
++      "type": "bool"
++    },
++    {
++      "name": "pmm-en",
++      "type": "bool"
++    },
++    {
++      "name": "npt",
++      "type": "bool"
++    },
++    {
++      "name": "kvm-pv-tlb-flush",
++      "type": "bool"
++    },
++    {
++      "name": "tsc",
++      "type": "bool"
++    },
++    {
++      "name": "monitor",
++      "type": "bool"
++    },
++    {
++      "name": "f16c",
++      "type": "bool"
++    },
++    {
++      "name": "sse2",
++      "type": "bool"
++    },
++    {
++      "name": "rdpid",
++      "type": "bool"
++    },
++    {
++      "name": "mce",
++      "type": "bool"
++    },
++    {
++      "name": "full-cpuid-auto-level",
++      "type": "bool"
++    },
++    {
++      "name": "xtpr",
++      "type": "bool"
++    },
++    {
++      "name": "mca",
++      "type": "bool"
++    },
++    {
++      "name": "cid",
++      "type": "bool"
++    },
++    {
++      "name": "tm",
++      "type": "bool"
++    },
++    {
++      "name": "pku",
++      "type": "bool"
++    },
++    {
++      "name": "hv-tlbflush",
++      "type": "bool"
++    },
++    {
++      "name": "ds",
++      "type": "bool"
++    },
++    {
++      "name": "kvmclock",
++      "type": "bool"
++    },
++    {
++      "name": "tce",
++      "type": "bool"
++    },
++    {
++      "name": "sse4a",
++      "type": "bool"
++    },
++    {
++      "name": "lahf-lm",
++      "type": "bool"
++    },
++    {
++      "name": "xsaves",
++      "type": "bool"
++    },
++    {
++      "name": "clflushopt",
++      "type": "bool"
++    },
++    {
++      "name": "kvm",
++      "type": "bool"
++    },
++    {
++      "name": "ss",
++      "type": "bool"
++    },
++    {
++      "name": "flushbyasid",
++      "type": "bool"
++    },
++    {
++      "name": "md-clear",
++      "type": "bool"
++    },
++    {
++      "name": "pause_filter",
++      "type": "bool"
++    },
++    {
++      "name": "de",
++      "type": "bool"
++    },
++    {
++      "name": "est",
++      "type": "bool"
++    },
++    {
++      "name": "check",
++      "type": "bool"
++    },
++    {
++      "name": "lahf_lm",
++      "type": "bool"
++    },
++    {
++      "name": "dtes64",
++      "type": "bool"
++    },
++    {
++      "name": "vmx",
++      "type": "bool"
++    },
++    {
++      "name": "xsavec",
++      "type": "bool"
++    },
++    {
++      "name": "svm-lock",
++      "type": "bool"
++    },
++    {
++      "name": "avx512ifma",
++      "type": "bool"
++    },
++    {
++      "name": "clflush",
++      "type": "bool"
++    },
++    {
++      "name": "rdseed",
++      "type": "bool"
++    },
++    {
++      "name": "avx512cd",
++      "type": "bool"
++    },
++    {
++      "name": "xsaveopt",
++      "type": "bool"
++    },
++    {
++      "name": "tbm",
++      "type": "bool"
++    },
++    {
++      "name": "ace2",
++      "type": "bool"
++    },
++    {
++      "name": "vme",
++      "type": "bool"
++    },
++    {
++      "name": "kvm_asyncpf",
++      "type": "bool"
++    },
++    {
++      "name": "hv-vapic",
++      "type": "bool"
++    },
++    {
++      "name": "parent_bus",
++      "type": "link<bus>"
++    },
++    {
++      "name": "lmce",
++      "type": "bool"
++    },
++    {
++      "name": "x-migrate-smi-count",
++      "type": "bool"
++    },
++    {
++      "name": "hv-reset",
++      "type": "bool"
++    },
++    {
++      "name": "hv-runtime",
++      "type": "bool"
++    },
++    {
++      "name": "ssbd",
++      "type": "bool"
++    },
++    {
++      "name": "avx512bw",
++      "type": "bool"
++    },
++    {
++      "name": "xcrypt",
++      "type": "bool"
++    },
++    {
++      "name": "fpu",
++      "type": "bool"
++    },
++    {
++      "name": "fxsr",
++      "type": "bool"
++    },
++    {
++      "name": "ds-cpl",
++      "type": "bool"
++    },
++    {
++      "name": "kvm-pv-eoi",
++      "type": "bool"
++    },
++    {
++      "name": "hle",
++      "type": "bool"
++    },
++    {
++      "name": "cx8",
++      "type": "bool"
++    },
++    {
++      "name": "mpx",
++      "type": "bool"
++    },
++    {
++      "name": "invpcid",
++      "type": "bool"
++    },
++    {
++      "name": "pcommit",
++      "type": "bool"
++    },
++    {
++      "name": "arat",
++      "type": "bool"
++    },
++    {
++      "name": "sse",
++      "type": "bool"
++    },
++    {
++      "name": "syscall",
++      "type": "bool"
++    },
++    {
++      "name": "tsc_scale",
++      "type": "bool"
++    },
++    {
++      "name": "xlevel2",
++      "type": "uint32"
++    },
++    {
++      "name": "hv-time",
++      "type": "bool"
++    },
++    {
++      "name": "kvm_pv_eoi",
++      "type": "bool"
++    },
++    {
++      "name": "osvw",
++      "type": "bool"
++    },
++    {
++      "name": "perfctr-nb",
++      "type": "bool"
++    },
++    {
++      "name": "rtm",
++      "type": "bool"
++    },
++    {
++      "name": "avx512-4fmaps",
++      "type": "bool"
++    },
++    {
++      "name": "avx2",
++      "type": "bool"
++    },
++    {
++      "name": "perfctr_nb",
++      "type": "bool"
++    },
++    {
++      "name": "kvm-nopiodelay",
++      "type": "bool"
++    },
++    {
++      "name": "avx512pf",
++      "type": "bool"
++    },
++    {
++      "name": "level",
++      "type": "uint32"
++    },
++    {
++      "name": "phys-bits",
++      "type": "uint32"
++    },
++    {
++      "name": "cpuid-0xb",
++      "type": "bool"
++    },
++    {
++      "name": "tsc-deadline",
++      "type": "bool"
++    },
++    {
++      "name": "fxsr_opt",
++      "type": "bool"
++    },
++    {
++      "name": "xgetbv1",
++      "type": "bool"
++    },
++    {
++      "name": "popcnt",
++      "type": "bool"
++    },
++    {
++      "name": "umip",
++      "type": "bool"
++    },
++    {
++      "name": "realized",
++      "type": "bool"
++    },
++    {
++      "name": "phe",
++      "type": "bool"
++    },
++    {
++      "name": "cmp-legacy",
++      "type": "bool"
++    },
++    {
++      "name": "dca",
++      "type": "bool"
++    },
++    {
++      "name": "acpi",
++      "type": "bool"
++    },
++    {
++      "name": "pn",
++      "type": "bool"
++    },
++    {
++      "name": "model-id",
++      "type": "string"
++    },
++    {
++      "name": "crash-information",
++      "type": "GuestPanicInformation"
++    },
++    {
++      "name": "tsc-scale",
++      "type": "bool"
++    },
++    {
++      "name": "node-id",
++      "type": "int32"
++    },
++    {
++      "name": "hv-reenlightenment",
++      "type": "bool"
++    },
++    {
++      "name": "cx16",
++      "type": "bool"
++    },
++    {
++      "name": "mmx",
++      "type": "bool"
++    },
++    {
++      "name": "topoext",
++      "type": "bool"
++    },
++    {
++      "name": "pge",
++      "type": "bool"
++    },
++    {
++      "name": "fsgsbase",
++      "type": "bool"
++    },
++    {
++      "name": "pclmuldq",
++      "type": "bool"
++    },
++    {
++      "name": "misalignsse",
++      "type": "bool"
++    },
++    {
++      "name": "phe-en",
++      "type": "bool"
++    },
++    {
++      "name": "fma",
++      "type": "bool"
++    }
++  ],
++  "id": "libvirt-43"
++}
++
++{
++  "execute": "query-machines",
++  "id": "libvirt-44"
++}
++
+ {
+   "return": [
+     {
+@@ -5333,12 +6395,12 @@
+       "cpu-max": 255
+     }
+   ],
+-  "id": "libvirt-43"
++  "id": "libvirt-44"
+ }
+ 
+ {
+   "execute": "query-cpu-definitions",
+-  "id": "libvirt-44"
++  "id": "libvirt-45"
+ }
+ 
+ {
+@@ -5775,12 +6837,12 @@
+       "migration-safe": true
+     }
+   ],
+-  "id": "libvirt-44"
++  "id": "libvirt-45"
+ }
+ 
+ {
+   "execute": "query-tpm-models",
+-  "id": "libvirt-45"
++  "id": "libvirt-46"
+ }
+ 
+ {
+@@ -5788,12 +6850,12 @@
+     "tpm-crb",
+     "tpm-tis"
+   ],
+-  "id": "libvirt-45"
++  "id": "libvirt-46"
+ }
+ 
+ {
+   "execute": "query-tpm-types",
+-  "id": "libvirt-46"
++  "id": "libvirt-47"
+ }
+ 
+ {
+@@ -5801,12 +6863,12 @@
+     "passthrough",
+     "emulator"
+   ],
+-  "id": "libvirt-46"
++  "id": "libvirt-47"
+ }
+ 
+ {
+   "execute": "query-command-line-options",
+-  "id": "libvirt-47"
++  "id": "libvirt-48"
+ }
+ 
+ {
+@@ -7105,12 +8167,12 @@
+       "option": "drive"
+     }
+   ],
+-  "id": "libvirt-47"
++  "id": "libvirt-48"
+ }
+ 
+ {
+   "execute": "query-migrate-capabilities",
+-  "id": "libvirt-48"
++  "id": "libvirt-49"
+ }
+ 
+ {
+@@ -7180,12 +8242,12 @@
+       "capability": "late-block-activate"
+     }
+   ],
+-  "id": "libvirt-48"
++  "id": "libvirt-49"
+ }
+ 
+ {
+   "execute": "query-qmp-schema",
+-  "id": "libvirt-49"
++  "id": "libvirt-50"
+ }
+ 
+ {
+@@ -19425,7 +20487,7 @@
+       "meta-type": "object"
+     }
+   ],
+-  "id": "libvirt-49"
++  "id": "libvirt-50"
+ }
+ 
+ {
+@@ -19436,7 +20498,7 @@
+       "name": "host"
+     }
+   },
+-  "id": "libvirt-50"
++  "id": "libvirt-51"
+ }
+ 
+ {
+@@ -19629,7 +20691,7 @@
+       }
+     }
+   },
+-  "id": "libvirt-50"
++  "id": "libvirt-51"
+ }
+ 
+ {
+@@ -19824,7 +20886,7 @@
+       }
+     }
+   },
+-  "id": "libvirt-51"
++  "id": "libvirt-52"
+ }
+ 
+ {
+@@ -20086,7 +21148,7 @@
+       }
+     }
+   },
+-  "id": "libvirt-51"
++  "id": "libvirt-52"
+ }
+ 
+ {
+@@ -20100,7 +21162,7 @@
+       }
+     }
+   },
+-  "id": "libvirt-52"
++  "id": "libvirt-53"
+ }
+ 
+ {
+@@ -20293,7 +21355,7 @@
+       }
+     }
+   },
+-  "id": "libvirt-52"
++  "id": "libvirt-53"
+ }
+ 
+ {
+@@ -20488,7 +21550,7 @@
+       }
+     }
+   },
+-  "id": "libvirt-53"
++  "id": "libvirt-54"
+ }
+ 
+ {
+@@ -20750,16 +21812,16 @@
+       }
+     }
+   },
+-  "id": "libvirt-53"
+-}
+-
+-{
+-  "execute": "query-sev-capabilities",
+   "id": "libvirt-54"
+ }
+ 
+ {
+-  "id": "libvirt-54",
++  "execute": "query-sev-capabilities",
++  "id": "libvirt-55"
++}
++
++{
++  "id": "libvirt-55",
+   "error": {
+     "class": "GenericError",
+     "desc": "SEV feature is not available"
+diff --git a/tests/qemucapabilitiesdata/caps_3.0.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_3.0.0.x86_64.xml
+index dceb719fcf..22dc60d13e 100644
+--- a/tests/qemucapabilitiesdata/caps_3.0.0.x86_64.xml
++++ b/tests/qemucapabilitiesdata/caps_3.0.0.x86_64.xml
+@@ -218,7 +218,7 @@
+   <flag name='x86-max-cpu'/>
+   <version>2012090</version>
+   <kvmVersion>0</kvmVersion>
+-  <microcodeVersion>438109</microcodeVersion>
++  <microcodeVersion>453907</microcodeVersion>
+   <package>v3.0.0-rc0-31-g633e824037</package>
+   <arch>x86_64</arch>
+   <hostCPU type='kvm' model='base' migratability='yes'>
+diff --git a/tests/qemucapabilitiesdata/caps_4.1.0.x86_64.replies b/tests/qemucapabilitiesdata/caps_4.1.0.x86_64.replies
+index ab0ac1e7bf..82b320b1d0 100644
+--- a/tests/qemucapabilitiesdata/caps_4.1.0.x86_64.replies
++++ b/tests/qemucapabilitiesdata/caps_4.1.0.x86_64.replies
+@@ -5510,10 +5510,1144 @@
+ }
+ 
+ {
+-  "execute": "query-machines",
++  "execute": "qom-list-properties",
++  "arguments": {
++    "typename": "max-x86_64-cpu"
++  },
+   "id": "libvirt-43"
+ }
+ 
++{
++  "return": [
++    {
++      "name": "type",
++      "type": "string"
++    },
++    {
++      "name": "min-xlevel2",
++      "type": "uint32"
++    },
++    {
++      "name": "amd-ssbd",
++      "type": "bool"
++    },
++    {
++      "name": "vendor",
++      "type": "string"
++    },
++    {
++      "name": "gfni",
++      "type": "bool"
++    },
++    {
++      "name": "clwb",
++      "type": "bool"
++    },
++    {
++      "name": "nx",
++      "type": "bool"
++    },
++    {
++      "name": "x2apic",
++      "type": "bool"
++    },
++    {
++      "name": "mds-no",
++      "type": "bool"
++    },
++    {
++      "name": "kvmclock-stable-bit",
++      "type": "bool"
++    },
++    {
++      "name": "vmcb_clean",
++      "type": "bool"
++    },
++    {
++      "name": "min-level",
++      "type": "uint32"
++    },
++    {
++      "name": "fxsr-opt",
++      "type": "bool"
++    },
++    {
++      "name": "skinit",
++      "type": "bool"
++    },
++    {
++      "name": "avx",
++      "type": "bool"
++    },
++    {
++      "name": "unavailable-features",
++      "type": "strList"
++    },
++    {
++      "name": "3dnowext",
++      "type": "bool"
++    },
++    {
++      "name": "nodeid_msr",
++      "type": "bool"
++    },
++    {
++      "name": "hv-crash",
++      "type": "bool"
++    },
++    {
++      "name": "hypervisor",
++      "type": "bool"
++    },
++    {
++      "name": "enforce",
++      "type": "bool"
++    },
++    {
++      "name": "stepping",
++      "type": "int"
++    },
++    {
++      "name": "sse4_2",
++      "type": "bool"
++    },
++    {
++      "name": "sse4_1",
++      "type": "bool"
++    },
++    {
++      "name": "x-hv-max-vps",
++      "type": "int32"
++    },
++    {
++      "name": "hv-frequencies",
++      "type": "bool"
++    },
++    {
++      "name": "kvm-hint-dedicated",
++      "type": "bool"
++    },
++    {
++      "name": "cmp_legacy",
++      "type": "bool"
++    },
++    {
++      "name": "tm2",
++      "type": "bool"
++    },
++    {
++      "name": "smx",
++      "type": "bool"
++    },
++    {
++      "name": "host-cache-info",
++      "type": "bool"
++    },
++    {
++      "name": "kvm-pv-ipi",
++      "type": "bool"
++    },
++    {
++      "name": "hv-vendor-id",
++      "type": "str"
++    },
++    {
++      "name": "movbe",
++      "type": "bool"
++    },
++    {
++      "name": "3dnowprefetch",
++      "type": "bool"
++    },
++    {
++      "name": "mtrr",
++      "type": "bool"
++    },
++    {
++      "name": "wdt",
++      "type": "bool"
++    },
++    {
++      "name": "thread-id",
++      "type": "int32"
++    },
++    {
++      "name": "aes",
++      "type": "bool"
++    },
++    {
++      "name": "apic-id",
++      "type": "uint32"
++    },
++    {
++      "name": "lm",
++      "type": "bool"
++    },
++    {
++      "name": "family",
++      "type": "int"
++    },
++    {
++      "name": "tsc-adjust",
++      "type": "bool"
++    },
++    {
++      "name": "pfthreshold",
++      "type": "bool"
++    },
++    {
++      "name": "kvm-no-smi-migration",
++      "type": "bool"
++    },
++    {
++      "name": "amd-no-ssb",
++      "type": "bool"
++    },
++    {
++      "name": "pse",
++      "type": "bool"
++    },
++    {
++      "name": "filtered-features",
++      "type": "X86CPUFeatureWordInfo"
++    },
++    {
++      "name": "hv-evmcs",
++      "type": "bool"
++    },
++    {
++      "name": "hv-vpindex",
++      "type": "bool"
++    },
++    {
++      "name": "i64",
++      "type": "bool"
++    },
++    {
++      "name": "avx512bitalg",
++      "type": "bool"
++    },
++    {
++      "name": "adx",
++      "type": "bool"
++    },
++    {
++      "name": "vaes",
++      "type": "bool"
++    },
++    {
++      "name": "ia64",
++      "type": "bool"
++    },
++    {
++      "name": "nodeid-msr",
++      "type": "bool"
++    },
++    {
++      "name": "ibpb",
++      "type": "bool"
++    },
++    {
++      "name": "hv-synic",
++      "type": "bool"
++    },
++    {
++      "name": "ibs",
++      "type": "bool"
++    },
++    {
++      "name": "kvm_mmu",
++      "type": "bool"
++    },
++    {
++      "name": "tcg-cpuid",
++      "type": "bool"
++    },
++    {
++      "name": "nrip_save",
++      "type": "bool"
++    },
++    {
++      "name": "kvm_nopiodelay",
++      "type": "bool"
++    },
++    {
++      "name": "lbrv",
++      "type": "bool"
++    },
++    {
++      "name": "rdtscp",
++      "type": "bool"
++    },
++    {
++      "name": "memory",
++      "type": "link<qemu:memory-region>"
++    },
++    {
++      "name": "avx512vbmi2",
++      "type": "bool"
++    },
++    {
++      "name": "ace2-en",
++      "type": "bool"
++    },
++    {
++      "name": "invtsc",
++      "type": "bool"
++    },
++    {
++      "name": "sse4.2",
++      "type": "bool"
++    },
++    {
++      "name": "sse4.1",
++      "type": "bool"
++    },
++    {
++      "name": "pbe",
++      "type": "bool"
++    },
++    {
++      "name": "rdrand",
++      "type": "bool"
++    },
++    {
++      "name": "socket-id",
++      "type": "int32"
++    },
++    {
++      "name": "hotpluggable",
++      "type": "bool"
++    },
++    {
++      "name": "l3-cache",
++      "type": "bool"
++    },
++    {
++      "name": "kvm-steal-time",
++      "type": "bool"
++    },
++    {
++      "name": "vmware-cpuid-freq",
++      "type": "bool"
++    },
++    {
++      "name": "legacy-cache",
++      "type": "bool"
++    },
++    {
++      "name": "xop",
++      "type": "bool"
++    },
++    {
++      "name": "tsc-frequency",
++      "type": "int"
++    },
++    {
++      "name": "fill-mtrr-mask",
++      "type": "bool"
++    },
++    {
++      "name": "core-id",
++      "type": "int32"
++    },
++    {
++      "name": "intel-pt",
++      "type": "bool"
++    },
++    {
++      "name": "pat",
++      "type": "bool"
++    },
++    {
++      "name": "pcid",
++      "type": "bool"
++    },
++    {
++      "name": "rsba",
++      "type": "bool"
++    },
++    {
++      "name": "sse4-2",
++      "type": "bool"
++    },
++    {
++      "name": "sse4-1",
++      "type": "bool"
++    },
++    {
++      "name": "pclmulqdq",
++      "type": "bool"
++    },
++    {
++      "name": "sha-ni",
++      "type": "bool"
++    },
++    {
++      "name": "cmov",
++      "type": "bool"
++    },
++    {
++      "name": "pae",
++      "type": "bool"
++    },
++    {
++      "name": "smep",
++      "type": "bool"
++    },
++    {
++      "name": "arch-capabilities",
++      "type": "bool"
++    },
++    {
++      "name": "virt-ssbd",
++      "type": "bool"
++    },
++    {
++      "name": "abm",
++      "type": "bool"
++    },
++    {
++      "name": "xstore",
++      "type": "bool"
++    },
++    {
++      "name": "tsc_adjust",
++      "type": "bool"
++    },
++    {
++      "name": "kvm-asyncpf",
++      "type": "bool"
++    },
++    {
++      "name": "pdpe1gb",
++      "type": "bool"
++    },
++    {
++      "name": "min-xlevel",
++      "type": "uint32"
++    },
++    {
++      "name": "kvm-mmu",
++      "type": "bool"
++    },
++    {
++      "name": "kvm-pv-unhalt",
++      "type": "bool"
++    },
++    {
++      "name": "avx512f",
++      "type": "bool"
++    },
++    {
++      "name": "avx512vbmi",
++      "type": "bool"
++    },
++    {
++      "name": "xd",
++      "type": "bool"
++    },
++    {
++      "name": "avx512-4vnniw",
++      "type": "bool"
++    },
++    {
++      "name": "mmxext",
++      "type": "bool"
++    },
++    {
++      "name": "decodeassists",
++      "type": "bool"
++    },
++    {
++      "name": "ht",
++      "type": "bool"
++    },
++    {
++      "name": "xsave",
++      "type": "bool"
++    },
++    {
++      "name": "perfctr_core",
++      "type": "bool"
++    },
++    {
++      "name": "feature-words",
++      "type": "X86CPUFeatureWordInfo"
++    },
++    {
++      "name": "migratable",
++      "type": "bool"
++    },
++    {
++      "name": "3dnow",
++      "type": "bool"
++    },
++    {
++      "name": "spec-ctrl",
++      "type": "bool"
++    },
++    {
++      "name": "model",
++      "type": "int"
++    },
++    {
++      "name": "nrip-save",
++      "type": "bool"
++    },
++    {
++      "name": "lwp",
++      "type": "bool"
++    },
++    {
++      "name": "xstore-en",
++      "type": "bool"
++    },
++    {
++      "name": "avx512vl",
++      "type": "bool"
++    },
++    {
++      "name": "kvm_pv_unhalt",
++      "type": "bool"
++    },
++    {
++      "name": "bmi2",
++      "type": "bool"
++    },
++    {
++      "name": "bmi1",
++      "type": "bool"
++    },
++    {
++      "name": "la57",
++      "type": "bool"
++    },
++    {
++      "name": "ffxsr",
++      "type": "bool"
++    },
++    {
++      "name": "stibp",
++      "type": "bool"
++    },
++    {
++      "name": "vmcb-clean",
++      "type": "bool"
++    },
++    {
++      "name": "wbnoinvd",
++      "type": "bool"
++    },
++    {
++      "name": "pause-filter",
++      "type": "bool"
++    },
++    {
++      "name": "pni",
++      "type": "bool"
++    },
++    {
++      "name": "kvm_steal_time",
++      "type": "bool"
++    },
++    {
++      "name": "rdctl-no",
++      "type": "bool"
++    },
++    {
++      "name": "svm_lock",
++      "type": "bool"
++    },
++    {
++      "name": "ibrs-all",
++      "type": "bool"
++    },
++    {
++      "name": "pse36",
++      "type": "bool"
++    },
++    {
++      "name": "hv-stimer",
++      "type": "bool"
++    },
++    {
++      "name": "host-phys-bits",
++      "type": "bool"
++    },
++    {
++      "name": "extapic",
++      "type": "bool"
++    },
++    {
++      "name": "skip-l1dfl-vmentry",
++      "type": "bool"
++    },
++    {
++      "name": "hv-spinlocks",
++      "type": "int"
++    },
++    {
++      "name": "pmu",
++      "type": "bool"
++    },
++    {
++      "name": "pmm",
++      "type": "bool"
++    },
++    {
++      "name": "vpclmulqdq",
++      "type": "bool"
++    },
++    {
++      "name": "avx512-vpopcntdq",
++      "type": "bool"
++    },
++    {
++      "name": "avx512er",
++      "type": "bool"
++    },
++    {
++      "name": "pdcm",
++      "type": "bool"
++    },
++    {
++      "name": "svm",
++      "type": "bool"
++    },
++    {
++      "name": "apic",
++      "type": "bool"
++    },
++    {
++      "name": "xcrypt-en",
++      "type": "bool"
++    },
++    {
++      "name": "cr8legacy",
++      "type": "bool"
++    },
++    {
++      "name": "fma4",
++      "type": "bool"
++    },
++    {
++      "name": "host-phys-bits-limit",
++      "type": "uint8"
++    },
++    {
++      "name": "erms",
++      "type": "bool"
++    },
++    {
++      "name": "msr",
++      "type": "bool"
++    },
++    {
++      "name": "ds_cpl",
++      "type": "bool"
++    },
++    {
++      "name": "xlevel",
++      "type": "uint32"
++    },
++    {
++      "name": "xsaves",
++      "type": "bool"
++    },
++    {
++      "name": "hotplugged",
++      "type": "bool"
++    },
++    {
++      "name": "hv-relaxed",
++      "type": "bool"
++    },
++    {
++      "name": "pause_filter",
++      "type": "bool"
++    },
++    {
++      "name": "cldemote",
++      "type": "bool"
++    },
++    {
++      "name": "perfctr-core",
++      "type": "bool"
++    },
++    {
++      "name": "hv-ipi",
++      "type": "bool"
++    },
++    {
++      "name": "smap",
++      "type": "bool"
++    },
++    {
++      "name": "sse3",
++      "type": "bool"
++    },
++    {
++      "name": "avx512dq",
++      "type": "bool"
++    },
++    {
++      "name": "ssse3",
++      "type": "bool"
++    },
++    {
++      "name": "pmm-en",
++      "type": "bool"
++    },
++    {
++      "name": "npt",
++      "type": "bool"
++    },
++    {
++      "name": "kvm-pv-tlb-flush",
++      "type": "bool"
++    },
++    {
++      "name": "tsc",
++      "type": "bool"
++    },
++    {
++      "name": "monitor",
++      "type": "bool"
++    },
++    {
++      "name": "f16c",
++      "type": "bool"
++    },
++    {
++      "name": "sse2",
++      "type": "bool"
++    },
++    {
++      "name": "rdpid",
++      "type": "bool"
++    },
++    {
++      "name": "mce",
++      "type": "bool"
++    },
++    {
++      "name": "full-cpuid-auto-level",
++      "type": "bool"
++    },
++    {
++      "name": "xtpr",
++      "type": "bool"
++    },
++    {
++      "name": "mca",
++      "type": "bool"
++    },
++    {
++      "name": "cid",
++      "type": "bool"
++    },
++    {
++      "name": "tm",
++      "type": "bool"
++    },
++    {
++      "name": "sep",
++      "type": "bool"
++    },
++    {
++      "name": "avx512vnni",
++      "type": "bool"
++    },
++    {
++      "name": "ds",
++      "type": "bool"
++    },
++    {
++      "name": "pku",
++      "type": "bool"
++    },
++    {
++      "name": "tce",
++      "type": "bool"
++    },
++    {
++      "name": "sse4a",
++      "type": "bool"
++    },
++    {
++      "name": "kvmclock",
++      "type": "bool"
++    },
++    {
++      "name": "lahf-lm",
++      "type": "bool"
++    },
++    {
++      "name": "clflushopt",
++      "type": "bool"
++    },
++    {
++      "name": "kvm",
++      "type": "bool"
++    },
++    {
++      "name": "ss",
++      "type": "bool"
++    },
++    {
++      "name": "flushbyasid",
++      "type": "bool"
++    },
++    {
++      "name": "hv-tlbflush",
++      "type": "bool"
++    },
++    {
++      "name": "lahf_lm",
++      "type": "bool"
++    },
++    {
++      "name": "de",
++      "type": "bool"
++    },
++    {
++      "name": "xsavec",
++      "type": "bool"
++    },
++    {
++      "name": "est",
++      "type": "bool"
++    },
++    {
++      "name": "check",
++      "type": "bool"
++    },
++    {
++      "name": "movdir64b",
++      "type": "bool"
++    },
++    {
++      "name": "dtes64",
++      "type": "bool"
++    },
++    {
++      "name": "md-clear",
++      "type": "bool"
++    },
++    {
++      "name": "vmx",
++      "type": "bool"
++    },
++    {
++      "name": "svm-lock",
++      "type": "bool"
++    },
++    {
++      "name": "avx512ifma",
++      "type": "bool"
++    },
++    {
++      "name": "clflush",
++      "type": "bool"
++    },
++    {
++      "name": "rdseed",
++      "type": "bool"
++    },
++    {
++      "name": "avx512cd",
++      "type": "bool"
++    },
++    {
++      "name": "xsaveopt",
++      "type": "bool"
++    },
++    {
++      "name": "tbm",
++      "type": "bool"
++    },
++    {
++      "name": "ace2",
++      "type": "bool"
++    },
++    {
++      "name": "vme",
++      "type": "bool"
++    },
++    {
++      "name": "kvm_asyncpf",
++      "type": "bool"
++    },
++    {
++      "name": "hv-vapic",
++      "type": "bool"
++    },
++    {
++      "name": "parent_bus",
++      "type": "link<bus>"
++    },
++    {
++      "name": "lmce",
++      "type": "bool"
++    },
++    {
++      "name": "x-migrate-smi-count",
++      "type": "bool"
++    },
++    {
++      "name": "hv-reset",
++      "type": "bool"
++    },
++    {
++      "name": "hv-runtime",
++      "type": "bool"
++    },
++    {
++      "name": "ssbd",
++      "type": "bool"
++    },
++    {
++      "name": "avx512bw",
++      "type": "bool"
++    },
++    {
++      "name": "xcrypt",
++      "type": "bool"
++    },
++    {
++      "name": "fpu",
++      "type": "bool"
++    },
++    {
++      "name": "arat",
++      "type": "bool"
++    },
++    {
++      "name": "fxsr",
++      "type": "bool"
++    },
++    {
++      "name": "ds-cpl",
++      "type": "bool"
++    },
++    {
++      "name": "kvm-pv-eoi",
++      "type": "bool"
++    },
++    {
++      "name": "hle",
++      "type": "bool"
++    },
++    {
++      "name": "mpx",
++      "type": "bool"
++    },
++    {
++      "name": "invpcid",
++      "type": "bool"
++    },
++    {
++      "name": "cx8",
++      "type": "bool"
++    },
++    {
++      "name": "pcommit",
++      "type": "bool"
++    },
++    {
++      "name": "sse",
++      "type": "bool"
++    },
++    {
++      "name": "syscall",
++      "type": "bool"
++    },
++    {
++      "name": "tsc_scale",
++      "type": "bool"
++    },
++    {
++      "name": "movdiri",
++      "type": "bool"
++    },
++    {
++      "name": "ssb-no",
++      "type": "bool"
++    },
++    {
++      "name": "xlevel2",
++      "type": "uint32"
++    },
++    {
++      "name": "hv-time",
++      "type": "bool"
++    },
++    {
++      "name": "kvm_pv_eoi",
++      "type": "bool"
++    },
++    {
++      "name": "osvw",
++      "type": "bool"
++    },
++    {
++      "name": "perfctr-nb",
++      "type": "bool"
++    },
++    {
++      "name": "rtm",
++      "type": "bool"
++    },
++    {
++      "name": "avx512-4fmaps",
++      "type": "bool"
++    },
++    {
++      "name": "avx2",
++      "type": "bool"
++    },
++    {
++      "name": "perfctr_nb",
++      "type": "bool"
++    },
++    {
++      "name": "kvm-nopiodelay",
++      "type": "bool"
++    },
++    {
++      "name": "avx512pf",
++      "type": "bool"
++    },
++    {
++      "name": "level",
++      "type": "uint32"
++    },
++    {
++      "name": "phys-bits",
++      "type": "uint32"
++    },
++    {
++      "name": "cpuid-0xb",
++      "type": "bool"
++    },
++    {
++      "name": "tsc-deadline",
++      "type": "bool"
++    },
++    {
++      "name": "fxsr_opt",
++      "type": "bool"
++    },
++    {
++      "name": "xgetbv1",
++      "type": "bool"
++    },
++    {
++      "name": "popcnt",
++      "type": "bool"
++    },
++    {
++      "name": "umip",
++      "type": "bool"
++    },
++    {
++      "name": "realized",
++      "type": "bool"
++    },
++    {
++      "name": "phe",
++      "type": "bool"
++    },
++    {
++      "name": "cmp-legacy",
++      "type": "bool"
++    },
++    {
++      "name": "dca",
++      "type": "bool"
++    },
++    {
++      "name": "acpi",
++      "type": "bool"
++    },
++    {
++      "name": "pn",
++      "type": "bool"
++    },
++    {
++      "name": "model-id",
++      "type": "string"
++    },
++    {
++      "name": "crash-information",
++      "type": "GuestPanicInformation"
++    },
++    {
++      "name": "x-intel-pt-auto-level",
++      "type": "bool"
++    },
++    {
++      "name": "x-hv-synic-kvm-only",
++      "type": "bool"
++    },
++    {
++      "name": "tsc-scale",
++      "type": "bool"
++    },
++    {
++      "name": "node-id",
++      "type": "int32"
++    },
++    {
++      "name": "hv-reenlightenment",
++      "type": "bool"
++    },
++    {
++      "name": "cx16",
++      "type": "bool"
++    },
++    {
++      "name": "mmx",
++      "type": "bool"
++    },
++    {
++      "name": "topoext",
++      "type": "bool"
++    },
++    {
++      "name": "pge",
++      "type": "bool"
++    },
++    {
++      "name": "fsgsbase",
++      "type": "bool"
++    },
++    {
++      "name": "pclmuldq",
++      "type": "bool"
++    },
++    {
++      "name": "misalignsse",
++      "type": "bool"
++    },
++    {
++      "name": "phe-en",
++      "type": "bool"
++    },
++    {
++      "name": "fma",
++      "type": "bool"
++    }
++  ],
++  "id": "libvirt-43"
++}
++
++{
++  "execute": "query-machines",
++  "id": "libvirt-44"
++}
++
+ {
+   "return": [
+     {
+@@ -5755,12 +6889,12 @@
+       "alias": "q35"
+     }
+   ],
+-  "id": "libvirt-43"
++  "id": "libvirt-44"
+ }
+ 
+ {
+   "execute": "query-cpu-definitions",
+-  "id": "libvirt-44"
++  "id": "libvirt-45"
+ }
+ 
+ {
+@@ -6310,12 +7444,12 @@
+       "migration-safe": true
+     }
+   ],
+-  "id": "libvirt-44"
++  "id": "libvirt-45"
+ }
+ 
+ {
+   "execute": "query-tpm-models",
+-  "id": "libvirt-45"
++  "id": "libvirt-46"
+ }
+ 
+ {
+@@ -6323,12 +7457,12 @@
+     "tpm-crb",
+     "tpm-tis"
+   ],
+-  "id": "libvirt-45"
++  "id": "libvirt-46"
+ }
+ 
+ {
+   "execute": "query-tpm-types",
+-  "id": "libvirt-46"
++  "id": "libvirt-47"
+ }
+ 
+ {
+@@ -6336,12 +7470,12 @@
+     "passthrough",
+     "emulator"
+   ],
+-  "id": "libvirt-46"
++  "id": "libvirt-47"
+ }
+ 
+ {
+   "execute": "query-command-line-options",
+-  "id": "libvirt-47"
++  "id": "libvirt-48"
+ }
+ 
+ {
+@@ -7611,12 +8745,12 @@
+       "option": "drive"
+     }
+   ],
+-  "id": "libvirt-47"
++  "id": "libvirt-48"
+ }
+ 
+ {
+   "execute": "query-migrate-capabilities",
+-  "id": "libvirt-48"
++  "id": "libvirt-49"
+ }
+ 
+ {
+@@ -7690,12 +8824,12 @@
+       "capability": "x-ignore-shared"
+     }
+   ],
+-  "id": "libvirt-48"
++  "id": "libvirt-49"
+ }
+ 
+ {
+   "execute": "query-qmp-schema",
+-  "id": "libvirt-49"
++  "id": "libvirt-50"
+ }
+ 
+ {
+@@ -20178,7 +21312,7 @@
+       ]
+     }
+   ],
+-  "id": "libvirt-49"
++  "id": "libvirt-50"
+ }
+ 
+ {
+@@ -20189,7 +21323,7 @@
+       "name": "host"
+     }
+   },
+-  "id": "libvirt-50"
++  "id": "libvirt-51"
+ }
+ 
+ {
+@@ -20395,7 +21529,7 @@
+       }
+     }
+   },
+-  "id": "libvirt-50"
++  "id": "libvirt-51"
+ }
+ 
+ {
+@@ -20603,7 +21737,7 @@
+       }
+     }
+   },
+-  "id": "libvirt-51"
++  "id": "libvirt-52"
+ }
+ 
+ {
+@@ -20884,7 +22018,7 @@
+       }
+     }
+   },
+-  "id": "libvirt-51"
++  "id": "libvirt-52"
+ }
+ 
+ {
+@@ -20898,7 +22032,7 @@
+       }
+     }
+   },
+-  "id": "libvirt-52"
++  "id": "libvirt-53"
+ }
+ 
+ {
+@@ -21104,7 +22238,7 @@
+       }
+     }
+   },
+-  "id": "libvirt-52"
++  "id": "libvirt-53"
+ }
+ 
+ {
+@@ -21312,7 +22446,7 @@
+       }
+     }
+   },
+-  "id": "libvirt-53"
++  "id": "libvirt-54"
+ }
+ 
+ {
+@@ -21593,16 +22727,16 @@
+       }
+     }
+   },
+-  "id": "libvirt-53"
+-}
+-
+-{
+-  "execute": "query-sev-capabilities",
+   "id": "libvirt-54"
+ }
+ 
+ {
+-  "id": "libvirt-54",
++  "execute": "query-sev-capabilities",
++  "id": "libvirt-55"
++}
++
++{
++  "id": "libvirt-55",
+   "error": {
+     "class": "GenericError",
+     "desc": "SEV feature is not available"
+diff --git a/tests/qemucapabilitiesdata/caps_4.1.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_4.1.0.x86_64.xml
+index 4836dbb8a4..95d26dfce8 100644
+--- a/tests/qemucapabilitiesdata/caps_4.1.0.x86_64.xml
++++ b/tests/qemucapabilitiesdata/caps_4.1.0.x86_64.xml
+@@ -215,9 +215,10 @@
+   <flag name='egl-headless'/>
+   <flag name='vfio-pci.display'/>
+   <flag name='x86-max-cpu'/>
++  <flag name='cpu-unavailable-features'/>
+   <version>4000050</version>
+   <kvmVersion>0</kvmVersion>
+-  <microcodeVersion>456805</microcodeVersion>
++  <microcodeVersion>473743</microcodeVersion>
+   <package>v4.0.0-1173-g9c70209b63</package>
+   <arch>x86_64</arch>
+   <hostCPU type='kvm' model='base' migratability='yes'>
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-qemu-Probe-host-CPU-after-capabilities.patch b/SOURCES/libvirt-qemu-Probe-host-CPU-after-capabilities.patch
new file mode 100644
index 0000000..6229e6b
--- /dev/null
+++ b/SOURCES/libvirt-qemu-Probe-host-CPU-after-capabilities.patch
@@ -0,0 +1,403 @@
+From d2ef598bb59e613ce4a8b969ab9836604bd72727 Mon Sep 17 00:00:00 2001
+Message-Id: <d2ef598bb59e613ce4a8b969ab9836604bd72727@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:25:54 +0200
+Subject: [PATCH] qemu: Probe host CPU after capabilities
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The way we call query-cpu-model-expansion will rely on some capabilities
+bits. Let's make sure all capabilities are set before probing host CPU.
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit 6f6401fbae384c66ce6043ced30591050729a4ac)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1697627
+
+Conflicts:
+	src/qemu/qemu_capabilities.c
+            - various refactors were not backported
+
+	tests/qemucapabilitiesdata/caps_2.12.0.x86_64.replies
+	tests/qemucapabilitiesdata/caps_3.0.0.x86_64.replies
+            - QMP message IDs are different
+
+	tests/qemucapabilitiesdata/caps_3.1.0.x86_64.replies
+	tests/qemucapabilitiesdata/caps_4.0.0.x86_64.replies
+            - missing
+
+	tests/qemucapabilitiesdata/caps_4.1.0.x86_64.replies
+            - QMP message IDs are different
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <cea249ba54be2d9dca6f523a14b0af608163323f.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/qemu/qemu_capabilities.c                  |  8 +++-
+ .../caps_2.12.0.x86_64.replies                | 44 +++++++++----------
+ .../caps_3.0.0.x86_64.replies                 | 40 ++++++++---------
+ .../caps_4.1.0.x86_64.replies                 | 40 ++++++++---------
+ 4 files changed, 68 insertions(+), 64 deletions(-)
+
+diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
+index beec9d1497..fb260eae96 100644
+--- a/src/qemu/qemu_capabilities.c
++++ b/src/qemu/qemu_capabilities.c
+@@ -4343,8 +4343,6 @@ virQEMUCapsInitQMPMonitor(virQEMUCapsPtr qemuCaps,
+     if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_QUERY_QMP_SCHEMA) &&
+         virQEMUCapsProbeQMPSchemaCapabilities(qemuCaps, mon) < 0)
+         goto cleanup;
+-    if (virQEMUCapsProbeQMPHostCPU(qemuCaps, mon, false) < 0)
+-        goto cleanup;
+ 
+     /* 'intel-iommu' shows up as a device since 2.2.0, but can
+      * not be used with -device until 2.7.0. Before that it
+@@ -4394,6 +4392,12 @@ virQEMUCapsInitQMPMonitor(virQEMUCapsPtr qemuCaps,
+             virQEMUCapsClear(qemuCaps, QEMU_CAPS_SEV_GUEST);
+     }
+ 
++    /* The following probes rely on other previously probed capabilities.
++     * No capabilities bits should be set below this point. */
++
++    if (virQEMUCapsProbeQMPHostCPU(qemuCaps, mon, false) < 0)
++        goto cleanup;
++
+     ret = 0;
+  cleanup:
+     return ret;
+diff --git a/tests/qemucapabilitiesdata/caps_2.12.0.x86_64.replies b/tests/qemucapabilitiesdata/caps_2.12.0.x86_64.replies
+index 66a5577e5e..ecfe3386c4 100644
+--- a/tests/qemucapabilitiesdata/caps_2.12.0.x86_64.replies
++++ b/tests/qemucapabilitiesdata/caps_2.12.0.x86_64.replies
+@@ -19521,6 +19521,21 @@
+   "id": "libvirt-50"
+ }
+ 
++{
++  "execute": "query-sev-capabilities",
++  "id": "libvirt-51"
++}
++
++{
++  "return": {
++    "reduced-phys-bits": 1,
++    "cbitpos": 47,
++    "cert-chain": "AQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAA",
++    "pdh": "AQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAA"
++  },
++  "id": "libvirt-51"
++}
++
+ {
+   "execute": "query-cpu-model-expansion",
+   "arguments": {
+@@ -19529,7 +19544,7 @@
+       "name": "host"
+     }
+   },
+-  "id": "libvirt-51"
++  "id": "libvirt-52"
+ }
+ 
+ {
+@@ -19719,7 +19734,7 @@
+       }
+     }
+   },
+-  "id": "libvirt-51"
++  "id": "libvirt-52"
+ }
+ 
+ {
+@@ -19911,7 +19926,7 @@
+       }
+     }
+   },
+-  "id": "libvirt-52"
++  "id": "libvirt-53"
+ }
+ 
+ {
+@@ -20166,7 +20181,7 @@
+       }
+     }
+   },
+-  "id": "libvirt-52"
++  "id": "libvirt-53"
+ }
+ 
+ {
+@@ -20180,7 +20195,7 @@
+       }
+     }
+   },
+-  "id": "libvirt-53"
++  "id": "libvirt-54"
+ }
+ 
+ {
+@@ -20370,7 +20385,7 @@
+       }
+     }
+   },
+-  "id": "libvirt-53"
++  "id": "libvirt-54"
+ }
+ 
+ {
+@@ -20562,7 +20577,7 @@
+       }
+     }
+   },
+-  "id": "libvirt-54"
++  "id": "libvirt-55"
+ }
+ 
+ {
+@@ -20817,21 +20832,6 @@
+       }
+     }
+   },
+-  "id": "libvirt-54"
+-}
+-
+-{
+-  "execute": "query-sev-capabilities",
+-  "id": "libvirt-55"
+-}
+-
+-{
+-  "return": {
+-    "reduced-phys-bits": 1,
+-    "cbitpos": 47,
+-    "cert-chain": "AQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAA",
+-    "pdh": "AQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAAAQAAAAAOAAA"
+-  },
+   "id": "libvirt-55"
+ }
+ 
+diff --git a/tests/qemucapabilitiesdata/caps_3.0.0.x86_64.replies b/tests/qemucapabilitiesdata/caps_3.0.0.x86_64.replies
+index 9f44eb4fae..7fea8587fd 100644
+--- a/tests/qemucapabilitiesdata/caps_3.0.0.x86_64.replies
++++ b/tests/qemucapabilitiesdata/caps_3.0.0.x86_64.replies
+@@ -20490,6 +20490,19 @@
+   "id": "libvirt-50"
+ }
+ 
++{
++  "execute": "query-sev-capabilities",
++  "id": "libvirt-51"
++}
++
++{
++  "id": "libvirt-51",
++  "error": {
++    "class": "GenericError",
++    "desc": "SEV feature is not available"
++  }
++}
++
+ {
+   "execute": "query-cpu-model-expansion",
+   "arguments": {
+@@ -20498,7 +20511,7 @@
+       "name": "host"
+     }
+   },
+-  "id": "libvirt-51"
++  "id": "libvirt-52"
+ }
+ 
+ {
+@@ -20691,7 +20704,7 @@
+       }
+     }
+   },
+-  "id": "libvirt-51"
++  "id": "libvirt-52"
+ }
+ 
+ {
+@@ -20886,7 +20899,7 @@
+       }
+     }
+   },
+-  "id": "libvirt-52"
++  "id": "libvirt-53"
+ }
+ 
+ {
+@@ -21148,7 +21161,7 @@
+       }
+     }
+   },
+-  "id": "libvirt-52"
++  "id": "libvirt-53"
+ }
+ 
+ {
+@@ -21162,7 +21175,7 @@
+       }
+     }
+   },
+-  "id": "libvirt-53"
++  "id": "libvirt-54"
+ }
+ 
+ {
+@@ -21355,7 +21368,7 @@
+       }
+     }
+   },
+-  "id": "libvirt-53"
++  "id": "libvirt-54"
+ }
+ 
+ {
+@@ -21550,7 +21563,7 @@
+       }
+     }
+   },
+-  "id": "libvirt-54"
++  "id": "libvirt-55"
+ }
+ 
+ {
+@@ -21812,22 +21825,9 @@
+       }
+     }
+   },
+-  "id": "libvirt-54"
+-}
+-
+-{
+-  "execute": "query-sev-capabilities",
+   "id": "libvirt-55"
+ }
+ 
+-{
+-  "id": "libvirt-55",
+-  "error": {
+-    "class": "GenericError",
+-    "desc": "SEV feature is not available"
+-  }
+-}
+-
+ {
+   "execute": "qmp_capabilities",
+   "id": "libvirt-1"
+diff --git a/tests/qemucapabilitiesdata/caps_4.1.0.x86_64.replies b/tests/qemucapabilitiesdata/caps_4.1.0.x86_64.replies
+index 82b320b1d0..5b4d7a8484 100644
+--- a/tests/qemucapabilitiesdata/caps_4.1.0.x86_64.replies
++++ b/tests/qemucapabilitiesdata/caps_4.1.0.x86_64.replies
+@@ -21315,6 +21315,19 @@
+   "id": "libvirt-50"
+ }
+ 
++{
++  "execute": "query-sev-capabilities",
++  "id": "libvirt-51"
++}
++
++{
++  "id": "libvirt-51",
++  "error": {
++    "class": "GenericError",
++    "desc": "SEV feature is not available"
++  }
++}
++
+ {
+   "execute": "query-cpu-model-expansion",
+   "arguments": {
+@@ -21323,7 +21336,7 @@
+       "name": "host"
+     }
+   },
+-  "id": "libvirt-51"
++  "id": "libvirt-52"
+ }
+ 
+ {
+@@ -21529,7 +21542,7 @@
+       }
+     }
+   },
+-  "id": "libvirt-51"
++  "id": "libvirt-52"
+ }
+ 
+ {
+@@ -21737,7 +21750,7 @@
+       }
+     }
+   },
+-  "id": "libvirt-52"
++  "id": "libvirt-53"
+ }
+ 
+ {
+@@ -22018,7 +22031,7 @@
+       }
+     }
+   },
+-  "id": "libvirt-52"
++  "id": "libvirt-53"
+ }
+ 
+ {
+@@ -22032,7 +22045,7 @@
+       }
+     }
+   },
+-  "id": "libvirt-53"
++  "id": "libvirt-54"
+ }
+ 
+ {
+@@ -22238,7 +22251,7 @@
+       }
+     }
+   },
+-  "id": "libvirt-53"
++  "id": "libvirt-54"
+ }
+ 
+ {
+@@ -22446,7 +22459,7 @@
+       }
+     }
+   },
+-  "id": "libvirt-54"
++  "id": "libvirt-55"
+ }
+ 
+ {
+@@ -22727,22 +22740,9 @@
+       }
+     }
+   },
+-  "id": "libvirt-54"
+-}
+-
+-{
+-  "execute": "query-sev-capabilities",
+   "id": "libvirt-55"
+ }
+ 
+-{
+-  "id": "libvirt-55",
+-  "error": {
+-    "class": "GenericError",
+-    "desc": "SEV feature is not available"
+-  }
+-}
+-
+ {
+   "execute": "qmp_capabilities",
+   "id": "libvirt-1"
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-qemu-Rework-setting-process-affinity.patch b/SOURCES/libvirt-qemu-Rework-setting-process-affinity.patch
new file mode 100644
index 0000000..d86ed56
--- /dev/null
+++ b/SOURCES/libvirt-qemu-Rework-setting-process-affinity.patch
@@ -0,0 +1,265 @@
+From dc27c829fd5909394e69ed253979f19b47644569 Mon Sep 17 00:00:00 2001
+Message-Id: <dc27c829fd5909394e69ed253979f19b47644569@dist-git>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Wed, 5 Jun 2019 11:33:28 +0200
+Subject: [PATCH] qemu: Rework setting process affinity
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1503284
+
+The way we currently start qemu from CPU affinity POV is as
+follows:
+
+  1) the child process is set affinity to all online CPUs (unless
+  some vcpu pinning was given in the domain XML)
+
+  2) Once qemu is running, cpuset cgroup is configured taking
+  memory pinning into account
+
+Problem is that we let qemu allocate its memory just anywhere in
+1) and then rely in 2) to be able to move the memory to
+configured NUMA nodes. This might not be always possible (e.g.
+qemu might lock some parts of its memory) and is very suboptimal
+(copying large memory between NUMA nodes takes significant amount
+of time).
+
+The solution is to set affinity to one of (in priority order):
+  - The CPUs associated with NUMA memory affinity mask
+  - The CPUs associated with emulator pinning
+  - All online host CPUs
+
+Later (once QEMU has allocated its memory) we then change this
+again to (again in priority order):
+  - The CPUs associated with emulator pinning
+  - The CPUs returned by numad
+  - The CPUs associated with vCPU pinning
+  - All online host CPUs
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
+(cherry picked from commit f136b83139c63f20de0df3285d9e82df2fb97bfc)
+
+RHEL-8.1.0: https://bugzilla.redhat.com/show_bug.cgi?id=1716943
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Message-Id: <c5f31a30daef2be65dc404ab0f1fbfb15be0d062.1559727075.git.mprivozn@redhat.com>
+Reviewed-by: Andrea Bolognani <abologna@redhat.com>
+---
+ src/qemu/qemu_process.c | 132 +++++++++++++++++++---------------------
+ 1 file changed, 63 insertions(+), 69 deletions(-)
+
+diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
+index 2d2954ba18..6071b3ba3d 100644
+--- a/src/qemu/qemu_process.c
++++ b/src/qemu/qemu_process.c
+@@ -2335,6 +2335,21 @@ qemuProcessDetectIOThreadPIDs(virQEMUDriverPtr driver,
+ }
+ 
+ 
++static int
++qemuProcessGetAllCpuAffinity(virBitmapPtr *cpumapRet)
++{
++    *cpumapRet = NULL;
++
++    if (!virHostCPUHasBitmap())
++        return 0;
++
++    if (!(*cpumapRet = virHostCPUGetOnlineBitmap()))
++        return -1;
++
++    return 0;
++}
++
++
+ /*
+  * To be run between fork/exec of QEMU only
+  */
+@@ -2342,9 +2357,9 @@ static int
+ qemuProcessInitCpuAffinity(virDomainObjPtr vm)
+ {
+     int ret = -1;
+-    virBitmapPtr cpumap = NULL;
+     virBitmapPtr cpumapToSet = NULL;
+-    virBitmapPtr hostcpumap = NULL;
++    VIR_AUTOPTR(virBitmap) hostcpumap = NULL;
++    virDomainNumatuneMemMode mem_mode;
+     qemuDomainObjPrivatePtr priv = vm->privateData;
+ 
+     if (!vm->pid) {
+@@ -2353,59 +2368,39 @@ qemuProcessInitCpuAffinity(virDomainObjPtr vm)
+         return -1;
+     }
+ 
+-    if (vm->def->placement_mode == VIR_DOMAIN_CPU_PLACEMENT_MODE_AUTO) {
+-        VIR_DEBUG("Set CPU affinity with advisory nodeset from numad");
+-        cpumapToSet = priv->autoCpuset;
++    /* Here is the deal, we can't set cpuset.mems before qemu is
++     * started as it clashes with KVM allocation. Therefore, we
++     * used to let qemu allocate its memory anywhere as we would
++     * then move the memory to desired NUMA node via CGroups.
++     * However, that might not be always possible because qemu
++     * might lock some parts of its memory (e.g. due to VFIO).
++     * Even if it possible, memory has to be copied between NUMA
++     * nodes which is suboptimal.
++     * Solution is to set affinity that matches the best what we
++     * would have set in CGroups and then fix it later, once qemu
++     * is already running. */
++    if (virDomainNumaGetNodeCount(vm->def->numa) <= 1 &&
++        virDomainNumatuneGetMode(vm->def->numa, -1, &mem_mode) == 0 &&
++        mem_mode == VIR_DOMAIN_NUMATUNE_MEM_STRICT) {
++        if (virDomainNumatuneMaybeGetNodeset(vm->def->numa,
++                                             priv->autoNodeset,
++                                             &cpumapToSet,
++                                             -1) < 0)
++            goto cleanup;
++    } else if (vm->def->cputune.emulatorpin) {
++        cpumapToSet = vm->def->cputune.emulatorpin;
+     } else {
+-        VIR_DEBUG("Set CPU affinity with specified cpuset");
+-        if (vm->def->cpumask) {
+-            cpumapToSet = vm->def->cpumask;
+-        } else {
+-            /* You may think this is redundant, but we can't assume libvirtd
+-             * itself is running on all pCPUs, so we need to explicitly set
+-             * the spawned QEMU instance to all pCPUs if no map is given in
+-             * its config file */
+-            int hostcpus;
+-
+-            if (virHostCPUHasBitmap()) {
+-                hostcpumap = virHostCPUGetOnlineBitmap();
+-                cpumap = virProcessGetAffinity(vm->pid);
+-            }
+-
+-            if (hostcpumap && cpumap && virBitmapEqual(hostcpumap, cpumap)) {
+-                /* we're using all available CPUs, no reason to set
+-                 * mask. If libvirtd is running without explicit
+-                 * affinity, we can use hotplugged CPUs for this VM */
+-                ret = 0;
+-                goto cleanup;
+-            } else {
+-                /* setaffinity fails if you set bits for CPUs which
+-                 * aren't present, so we have to limit ourselves */
+-                if ((hostcpus = virHostCPUGetCount()) < 0)
+-                    goto cleanup;
+-
+-                if (hostcpus > QEMUD_CPUMASK_LEN)
+-                    hostcpus = QEMUD_CPUMASK_LEN;
+-
+-                virBitmapFree(cpumap);
+-                if (!(cpumap = virBitmapNew(hostcpus)))
+-                    goto cleanup;
+-
+-                virBitmapSetAll(cpumap);
+-
+-                cpumapToSet = cpumap;
+-            }
+-        }
++        if (qemuProcessGetAllCpuAffinity(&hostcpumap) < 0)
++            goto cleanup;
++        cpumapToSet = hostcpumap;
+     }
+ 
+-    if (virProcessSetAffinity(vm->pid, cpumapToSet) < 0)
++    if (cpumapToSet &&
++        virProcessSetAffinity(vm->pid, cpumapToSet) < 0)
+         goto cleanup;
+ 
+     ret = 0;
+-
+  cleanup:
+-    virBitmapFree(cpumap);
+-    virBitmapFree(hostcpumap);
+     return ret;
+ }
+ 
+@@ -2478,7 +2473,8 @@ qemuProcessSetupPid(virDomainObjPtr vm,
+     qemuDomainObjPrivatePtr priv = vm->privateData;
+     virDomainNumatuneMemMode mem_mode;
+     virCgroupPtr cgroup = NULL;
+-    virBitmapPtr use_cpumask;
++    virBitmapPtr use_cpumask = NULL;
++    VIR_AUTOPTR(virBitmap) hostcpumap = NULL;
+     char *mem_mask = NULL;
+     int ret = -1;
+ 
+@@ -2490,12 +2486,21 @@ qemuProcessSetupPid(virDomainObjPtr vm,
+     }
+ 
+     /* Infer which cpumask shall be used. */
+-    if (cpumask)
++    if (cpumask) {
+         use_cpumask = cpumask;
+-    else if (vm->def->placement_mode == VIR_DOMAIN_CPU_PLACEMENT_MODE_AUTO)
++    } else if (vm->def->placement_mode == VIR_DOMAIN_CPU_PLACEMENT_MODE_AUTO) {
+         use_cpumask = priv->autoCpuset;
+-    else
++    } else if (vm->def->cpumask) {
+         use_cpumask = vm->def->cpumask;
++    } else {
++        /* You may think this is redundant, but we can't assume libvirtd
++         * itself is running on all pCPUs, so we need to explicitly set
++         * the spawned QEMU instance to all pCPUs if no map is given in
++         * its config file */
++        if (qemuProcessGetAllCpuAffinity(&hostcpumap) < 0)
++            goto cleanup;
++        use_cpumask = hostcpumap;
++    }
+ 
+     /*
+      * If CPU cgroup controller is not initialized here, then we need
+@@ -2520,13 +2525,7 @@ qemuProcessSetupPid(virDomainObjPtr vm,
+                 qemuSetupCgroupCpusetCpus(cgroup, use_cpumask) < 0)
+                 goto cleanup;
+ 
+-            /*
+-             * Don't setup cpuset.mems for the emulator, they need to
+-             * be set up after initialization in order for kvm
+-             * allocations to succeed.
+-             */
+-            if (nameval != VIR_CGROUP_THREAD_EMULATOR &&
+-                mem_mask && virCgroupSetCpusetMems(cgroup, mem_mask) < 0)
++            if (mem_mask && virCgroupSetCpusetMems(cgroup, mem_mask) < 0)
+                 goto cleanup;
+ 
+         }
+@@ -6440,12 +6439,7 @@ qemuProcessLaunch(virConnectPtr conn,
+ 
+     /* This must be done after cgroup placement to avoid resetting CPU
+      * affinity */
+-    if (!vm->def->cputune.emulatorpin &&
+-        qemuProcessInitCpuAffinity(vm) < 0)
+-        goto cleanup;
+-
+-    VIR_DEBUG("Setting emulator tuning/settings");
+-    if (qemuProcessSetupEmulator(vm) < 0)
++    if (qemuProcessInitCpuAffinity(vm) < 0)
+         goto cleanup;
+ 
+     VIR_DEBUG("Setting cgroup for external devices (if required)");
+@@ -6514,10 +6508,6 @@ qemuProcessLaunch(virConnectPtr conn,
+     if (qemuProcessUpdateAndVerifyCPU(driver, vm, asyncJob) < 0)
+         goto cleanup;
+ 
+-    VIR_DEBUG("Setting up post-init cgroup restrictions");
+-    if (qemuSetupCpusetMems(vm) < 0)
+-        goto cleanup;
+-
+     VIR_DEBUG("setting up hotpluggable cpus");
+     if (qemuDomainHasHotpluggableStartupVcpus(vm->def)) {
+         if (qemuDomainRefreshVcpuInfo(driver, vm, asyncJob, false) < 0)
+@@ -6543,6 +6533,10 @@ qemuProcessLaunch(virConnectPtr conn,
+     if (qemuProcessDetectIOThreadPIDs(driver, vm, asyncJob) < 0)
+         goto cleanup;
+ 
++    VIR_DEBUG("Setting emulator tuning/settings");
++    if (qemuProcessSetupEmulator(vm) < 0)
++        goto cleanup;
++
+     VIR_DEBUG("Setting global CPU cgroup (if required)");
+     if (qemuSetupGlobalCpuCgroup(vm) < 0)
+         goto cleanup;
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-qemu-Set-up-EMULATOR-thread-and-cpuset.mems-before-exec-ing-qemu.patch b/SOURCES/libvirt-qemu-Set-up-EMULATOR-thread-and-cpuset.mems-before-exec-ing-qemu.patch
new file mode 100644
index 0000000..3605c9b
--- /dev/null
+++ b/SOURCES/libvirt-qemu-Set-up-EMULATOR-thread-and-cpuset.mems-before-exec-ing-qemu.patch
@@ -0,0 +1,70 @@
+From ac89574e251dfecf34606083e402194ded63dba2 Mon Sep 17 00:00:00 2001
+Message-Id: <ac89574e251dfecf34606083e402194ded63dba2@dist-git>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Wed, 5 Jun 2019 11:33:29 +0200
+Subject: [PATCH] qemu: Set up EMULATOR thread and cpuset.mems before
+ exec()-ing qemu
+
+It's funny how this went unnoticed for such a long time. Long
+story short, if a domain is configured with
+VIR_DOMAIN_NUMATUNE_MEM_STRICT libvirt doesn't really honour
+that. This is because of 7e72ac787848 after which libvirt allowed
+qemu to allocate memory just anywhere and only after that it used
+some magic involving cpuset.memory_migrate and cpuset.mems to
+move the memory to desired NUMA nodes. This was done in order to
+work around some KVM bug where KVM would fail if there wasn't a
+DMA zone available on the NUMA node. Well, while the work around
+might stopped libvirt tickling the KVM bug it also caused a bug
+on libvirt side: if there is not enough memory on configured NUMA
+node(s) then any attempt to start a domain must fail. Because of
+the way we play with guest memory domains can start just happily.
+
+The solution is to move the child we've just forked into emulator
+cgroup, set up cpuset.mems and exec() qemu only after that.
+
+This basically reverts 7e72ac787848b7434c9 which was a workaround
+for kernel bug. This bug was apparently fixed because I've tested
+this successfully with recent kernel.
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Reviewed-by: Martin Kletzander <mkletzan@redhat.com>
+(cherry picked from commit 0eaa4716e1b8f6eb59d77049aed3735c3b5fbdd6)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1716943
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Message-Id: <fe479c5bad92778ec29f1c1bf4fb0c7b9049f3ab.1559727075.git.mprivozn@redhat.com>
+Reviewed-by: Andrea Bolognani <abologna@redhat.com>
+---
+ src/qemu/qemu_process.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
+index 6071b3ba3d..8b05cef80c 100644
+--- a/src/qemu/qemu_process.c
++++ b/src/qemu/qemu_process.c
+@@ -6442,6 +6442,10 @@ qemuProcessLaunch(virConnectPtr conn,
+     if (qemuProcessInitCpuAffinity(vm) < 0)
+         goto cleanup;
+ 
++    VIR_DEBUG("Setting emulator tuning/settings");
++    if (qemuProcessSetupEmulator(vm) < 0)
++        goto cleanup;
++
+     VIR_DEBUG("Setting cgroup for external devices (if required)");
+     if (qemuSetupCgroupForExtDevices(vm, driver) < 0)
+         goto cleanup;
+@@ -6533,10 +6537,6 @@ qemuProcessLaunch(virConnectPtr conn,
+     if (qemuProcessDetectIOThreadPIDs(driver, vm, asyncJob) < 0)
+         goto cleanup;
+ 
+-    VIR_DEBUG("Setting emulator tuning/settings");
+-    if (qemuProcessSetupEmulator(vm) < 0)
+-        goto cleanup;
+-
+     VIR_DEBUG("Setting global CPU cgroup (if required)");
+     if (qemuSetupGlobalCpuCgroup(vm) < 0)
+         goto cleanup;
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-qemu-Translate-feature-names-from-query-cpu-model-expansion.patch b/SOURCES/libvirt-qemu-Translate-feature-names-from-query-cpu-model-expansion.patch
new file mode 100644
index 0000000..757e07d
--- /dev/null
+++ b/SOURCES/libvirt-qemu-Translate-feature-names-from-query-cpu-model-expansion.patch
@@ -0,0 +1,133 @@
+From f047006a60d92f9c5e66ac9c2c532f8ac4c2ba28 Mon Sep 17 00:00:00 2001
+Message-Id: <f047006a60d92f9c5e66ac9c2c532f8ac4c2ba28@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:25:56 +0200
+Subject: [PATCH] qemu: Translate feature names from query-cpu-model-expansion
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+By default query-cpu-model-expansion only reports canonical names of all
+CPU features. We do some magic and call the command twice to get all
+possible spellings of the features, but being able to consume canonical
+names will allow us to drop this magic.
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit ec232c5ddc3cc47651a815dcf4cff7cd31910b3e)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1697627
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <5a50943665bc9df69bb99c25763f0b99a7364d8c.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/qemu/qemu_capabilities.c | 19 +++++++++++--------
+ src/qemu/qemu_capspriv.h     |  3 ++-
+ tests/cputest.c              |  2 +-
+ 3 files changed, 14 insertions(+), 10 deletions(-)
+
+diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
+index c48d66b39b..88c651ea7b 100644
+--- a/src/qemu/qemu_capabilities.c
++++ b/src/qemu/qemu_capabilities.c
+@@ -2868,11 +2868,12 @@ virQEMUCapsInitCPUModelS390(virQEMUCapsPtr qemuCaps,
+     for (i = 0; i < modelInfo->nprops; i++) {
+         virCPUFeatureDefPtr feature = cpu->features + cpu->nfeatures;
+         qemuMonitorCPUPropertyPtr prop = modelInfo->props + i;
++        const char *name = virQEMUCapsCPUFeatureFromQEMU(qemuCaps, prop->name);
+ 
+         if (prop->type != QEMU_MONITOR_CPU_PROPERTY_BOOLEAN)
+             continue;
+ 
+-        if (VIR_STRDUP(feature->name, prop->name) < 0)
++        if (VIR_STRDUP(feature->name, name) < 0)
+             return -1;
+ 
+         if (!prop->value.boolean ||
+@@ -2888,7 +2889,8 @@ virQEMUCapsInitCPUModelS390(virQEMUCapsPtr qemuCaps,
+ 
+ 
+ virCPUDataPtr
+-virQEMUCapsGetCPUModelX86Data(qemuMonitorCPUModelInfoPtr model,
++virQEMUCapsGetCPUModelX86Data(virQEMUCapsPtr qemuCaps,
++                              qemuMonitorCPUModelInfoPtr model,
+                               bool migratable)
+ {
+     unsigned long long sigFamily = 0;
+@@ -2903,6 +2905,7 @@ virQEMUCapsGetCPUModelX86Data(qemuMonitorCPUModelInfoPtr model,
+ 
+     for (i = 0; i < model->nprops; i++) {
+         qemuMonitorCPUPropertyPtr prop = model->props + i;
++        const char *name = virQEMUCapsCPUFeatureFromQEMU(qemuCaps, prop->name);
+ 
+         switch (prop->type) {
+         case QEMU_MONITOR_CPU_PROPERTY_BOOLEAN:
+@@ -2910,23 +2913,23 @@ virQEMUCapsGetCPUModelX86Data(qemuMonitorCPUModelInfoPtr model,
+                 (migratable && prop->migratable == VIR_TRISTATE_BOOL_NO))
+                 continue;
+ 
+-            if (virCPUx86DataAddFeature(data, prop->name) < 0)
++            if (virCPUx86DataAddFeature(data, name) < 0)
+                 goto cleanup;
+ 
+             break;
+ 
+         case QEMU_MONITOR_CPU_PROPERTY_STRING:
+-            if (STREQ(prop->name, "vendor") &&
++            if (STREQ(name, "vendor") &&
+                 virCPUx86DataSetVendor(data, prop->value.string) < 0)
+                 goto cleanup;
+             break;
+ 
+         case QEMU_MONITOR_CPU_PROPERTY_NUMBER:
+-            if (STREQ(prop->name, "family"))
++            if (STREQ(name, "family"))
+                 sigFamily = prop->value.number;
+-            else if (STREQ(prop->name, "model"))
++            else if (STREQ(name, "model"))
+                 sigModel = prop->value.number;
+-            else if (STREQ(prop->name, "stepping"))
++            else if (STREQ(name, "stepping"))
+                 sigStepping = prop->value.number;
+             break;
+ 
+@@ -2964,7 +2967,7 @@ virQEMUCapsInitCPUModelX86(virQEMUCapsPtr qemuCaps,
+     if (!model)
+         return 1;
+ 
+-    if (!(data = virQEMUCapsGetCPUModelX86Data(model, migratable)))
++    if (!(data = virQEMUCapsGetCPUModelX86Data(qemuCaps, model, migratable)))
+         goto cleanup;
+ 
+     if (cpuDecode(cpu, data, virQEMUCapsGetCPUDefinitions(qemuCaps, type)) < 0)
+diff --git a/src/qemu/qemu_capspriv.h b/src/qemu/qemu_capspriv.h
+index c3b7f934a9..b17deb01d7 100644
+--- a/src/qemu/qemu_capspriv.h
++++ b/src/qemu/qemu_capspriv.h
+@@ -85,7 +85,8 @@ virQEMUCapsSetCPUModelInfo(virQEMUCapsPtr qemuCaps,
+                            qemuMonitorCPUModelInfoPtr modelInfo);
+ 
+ virCPUDataPtr
+-virQEMUCapsGetCPUModelX86Data(qemuMonitorCPUModelInfoPtr model,
++virQEMUCapsGetCPUModelX86Data(virQEMUCapsPtr qemuCaps,
++                              qemuMonitorCPUModelInfoPtr model,
+                               bool migratable);
+ 
+ virCPUDefPtr
+diff --git a/tests/cputest.c b/tests/cputest.c
+index e62cda34b7..1ce50caccd 100644
+--- a/tests/cputest.c
++++ b/tests/cputest.c
+@@ -941,7 +941,7 @@ cpuTestJSONSignature(const void *arg)
+         goto cleanup;
+ 
+     modelInfo = virQEMUCapsGetCPUModelInfo(qemuCaps, VIR_DOMAIN_VIRT_KVM);
+-    if (!(hostData = virQEMUCapsGetCPUModelX86Data(modelInfo, false)))
++    if (!(hostData = virQEMUCapsGetCPUModelX86Data(qemuCaps, modelInfo, false)))
+         goto cleanup;
+ 
+     ret = cpuTestCompareSignature(data, hostData);
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-qemu-Use-tmpChr-in-qemuDomainDetachChrDevice-to-build-device-string.patch b/SOURCES/libvirt-qemu-Use-tmpChr-in-qemuDomainDetachChrDevice-to-build-device-string.patch
new file mode 100644
index 0000000..ca4f86b
--- /dev/null
+++ b/SOURCES/libvirt-qemu-Use-tmpChr-in-qemuDomainDetachChrDevice-to-build-device-string.patch
@@ -0,0 +1,43 @@
+From cdb5af98d3801255903c4237269ca5723abc36c1 Mon Sep 17 00:00:00 2001
+Message-Id: <cdb5af98d3801255903c4237269ca5723abc36c1@dist-git>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Thu, 27 Jun 2019 14:44:44 +0200
+Subject: [PATCH] qemu: Use @tmpChr in qemuDomainDetachChrDevice to build
+ device string
+
+So far we are passing @chr to qemuBuildChrDeviceStr. This is
+suboptimal (in fact wrong) because @chr is just parsed XML
+definition provided by user which by definition may lack some
+information. On the other hand, @tmpChr is the one that was found
+using @chr in domain definition so it contains the same amount of
+information or more.
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Reviewed-by: John Ferlan <jferlan@redhat.com>
+(cherry picked from commit f538f5ed3a876c3cb67ae5b7a01f133f192aca13)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1624204
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Message-Id: <75600f93c5e22f43762635ac97f5a0acef1cf465.1561639408.git.mprivozn@redhat.com>
+Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/qemu/qemu_hotplug.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
+index 5b9a5683bb..da9d56ffb1 100644
+--- a/src/qemu/qemu_hotplug.c
++++ b/src/qemu/qemu_hotplug.c
+@@ -5753,7 +5753,7 @@ int qemuDomainDetachChrDevice(virQEMUDriverPtr driver,
+ 
+     sa_assert(tmpChr->info.alias);
+ 
+-    if (qemuBuildChrDeviceStr(&devstr, vmdef, chr, priv->qemuCaps) < 0)
++    if (qemuBuildChrDeviceStr(&devstr, vmdef, tmpChr, priv->qemuCaps) < 0)
+         goto cleanup;
+ 
+     if (!async)
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-qemu-domain-Simplify-non-VFIO-memLockLimit-calculation-for-PPC64.patch b/SOURCES/libvirt-qemu-domain-Simplify-non-VFIO-memLockLimit-calculation-for-PPC64.patch
new file mode 100644
index 0000000..6931e00
--- /dev/null
+++ b/SOURCES/libvirt-qemu-domain-Simplify-non-VFIO-memLockLimit-calculation-for-PPC64.patch
@@ -0,0 +1,66 @@
+From 18f38f4aee3a3472f5e50786ee221d8d397bc6a8 Mon Sep 17 00:00:00 2001
+Message-Id: <18f38f4aee3a3472f5e50786ee221d8d397bc6a8@dist-git>
+From: Daniel Henrique Barboza <danielhb413@gmail.com>
+Date: Fri, 3 May 2019 13:54:50 +0200
+Subject: [PATCH] qemu: domain: Simplify non-VFIO memLockLimit calculation for
+ PPC64
+
+@passthroughLimit is being calculated even if @usesVFIO is false. After
+that, an if-else conditional is used to check if we're going to sum it
+up with @baseLimit.
+
+This patch initializes @passthroughLimit to zero and always returns
+@memKB = @baseLimit + @passthroughLimit. The conditional is then used to
+calculate @passthroughLimit if @usesVFIO == true. This results in some
+cycles being spared for the @usesVFIO == false scenario, but the real
+motivation is to make the code simpler to add an alternative formula to
+calculate @passthroughLimit for NVLink2.
+
+Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com>
+Reviewed-by: Erik Skultety <eskultet@redhat.com>
+(cherry picked from commit cf7c5212876b2403de5b0fafedec33af4439526e)
+
+https: //bugzilla.redhat.com/show_bug.cgi?id=1505998
+Signed-off-by: Erik Skultety <eskultet@redhat.com>
+Message-Id: <a6380e14dfb1c8cb463f5e3eb25bda78dc9d7dd8.1556884442.git.eskultet@redhat.com>
+Reviewed-by: Andrea Bolognani <abologna@redhat.com>
+---
+ src/qemu/qemu_domain.c | 13 +++++--------
+ 1 file changed, 5 insertions(+), 8 deletions(-)
+
+diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
+index cc2a896a07..d936090d87 100644
+--- a/src/qemu/qemu_domain.c
++++ b/src/qemu/qemu_domain.c
+@@ -9840,7 +9840,7 @@ qemuDomainGetMemLockLimitBytes(virDomainDefPtr def)
+         unsigned long long maxMemory;
+         unsigned long long memory;
+         unsigned long long baseLimit;
+-        unsigned long long passthroughLimit;
++        unsigned long long passthroughLimit = 0;
+         size_t nPCIHostBridges = 0;
+         bool usesVFIO = false;
+ 
+@@ -9906,15 +9906,12 @@ qemuDomainGetMemLockLimitBytes(virDomainDefPtr def)
+          * kiB pages, less still if the guest is mapped with hugepages (unlike
+          * the default 32-bit DMA window, DDW windows can use large IOMMU
+          * pages). 8 MiB is for second and further level overheads, like (b) */
+-        passthroughLimit = MAX(2 * 1024 * 1024 * nPCIHostBridges,
+-                               memory +
+-                               memory / 512 * nPCIHostBridges + 8192);
+-
+         if (usesVFIO)
+-            memKB = baseLimit + passthroughLimit;
+-        else
+-            memKB = baseLimit;
++            passthroughLimit = MAX(2 * 1024 * 1024 * nPCIHostBridges,
++                                   memory +
++                                   memory / 512 * nPCIHostBridges + 8192);
+ 
++        memKB = baseLimit + passthroughLimit;
+         goto done;
+     }
+ 
+-- 
+2.21.0
+
diff --git a/SOURCES/libvirt-qemu-process-SEV-Assume-libDir-to-be-the-directory-to-create-files-in.patch b/SOURCES/libvirt-qemu-process-SEV-Assume-libDir-to-be-the-directory-to-create-files-in.patch
new file mode 100644
index 0000000..2020e7f
--- /dev/null
+++ b/SOURCES/libvirt-qemu-process-SEV-Assume-libDir-to-be-the-directory-to-create-files-in.patch
@@ -0,0 +1,66 @@
+From 0e97054a08adcd9648d006a8b03effa7f7cf2e94 Mon Sep 17 00:00:00 2001
+Message-Id: <0e97054a08adcd9648d006a8b03effa7f7cf2e94@dist-git>
+From: Erik Skultety <eskultet@redhat.com>
+Date: Thu, 3 Jan 2019 10:03:45 +0100
+Subject: [PATCH] qemu: process: SEV: Assume libDir to be the directory to
+ create files in
+
+Since SEV operates on a per domain basis, it's very likely that all
+SEV launch-related data will be created under
+/var/lib/libvirt/qemu/<domain_name>. Therefore, when calling into
+qemuProcessSEVCreateFile we can assume @libDir as the directory prefix
+rather than passing it explicitly.
+
+Signed-off-by: Erik Skultety <eskultet@redhat.com>
+Acked-by: Michal Privoznik <mprivozn@redhat.com>
+(cherry picked from commit 2c4c7de1595330a828015dd750b5ef3874f289d1)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1658112
+
+Signed-off-by: Erik Skultety <eskultet@redhat.com>
+Message-Id: <0f59cc4873d5faab4339e79714377da9f889703c.1546506016.git.eskultet@redhat.com>
+Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/qemu/qemu_process.c | 9 +++++----
+ 1 file changed, 5 insertions(+), 4 deletions(-)
+
+diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
+index c0f95dd5f1..757e2d33a4 100644
+--- a/src/qemu/qemu_process.c
++++ b/src/qemu/qemu_process.c
+@@ -5985,14 +5985,15 @@ qemuProcessPrepareDomain(virQEMUDriverPtr driver,
+ 
+ 
+ static int
+-qemuProcessSEVCreateFile(const char *configDir,
++qemuProcessSEVCreateFile(virDomainObjPtr vm,
+                          const char *name,
+                          const char *data)
+ {
++    qemuDomainObjPrivatePtr priv = vm->privateData;
+     char *configFile;
+     int ret = -1;
+ 
+-    if (!(configFile = virFileBuildPath(configDir, name, ".base64")))
++    if (!(configFile = virFileBuildPath(priv->libDir, name, ".base64")))
+         return -1;
+ 
+     if (virFileRewriteStr(configFile, S_IRUSR | S_IWUSR, data) < 0) {
+@@ -6029,12 +6030,12 @@ qemuProcessPrepareSEVGuestInput(virDomainObjPtr vm)
+     }
+ 
+     if (sev->dh_cert) {
+-        if (qemuProcessSEVCreateFile(priv->libDir, "dh_cert", sev->dh_cert) < 0)
++        if (qemuProcessSEVCreateFile(vm, "dh_cert", sev->dh_cert) < 0)
+             return -1;
+     }
+ 
+     if (sev->session) {
+-        if (qemuProcessSEVCreateFile(priv->libDir, "session", sev->session) < 0)
++        if (qemuProcessSEVCreateFile(vm, "session", sev->session) < 0)
+             return -1;
+     }
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-qemu-process-SEV-Relabel-guest-owner-s-SEV-files-created-before-start.patch b/SOURCES/libvirt-qemu-process-SEV-Relabel-guest-owner-s-SEV-files-created-before-start.patch
new file mode 100644
index 0000000..c1e0647
--- /dev/null
+++ b/SOURCES/libvirt-qemu-process-SEV-Relabel-guest-owner-s-SEV-files-created-before-start.patch
@@ -0,0 +1,51 @@
+From dc905fbc1f420a8d7856d9ff7f27b3faae352098 Mon Sep 17 00:00:00 2001
+Message-Id: <dc905fbc1f420a8d7856d9ff7f27b3faae352098@dist-git>
+From: Erik Skultety <eskultet@redhat.com>
+Date: Thu, 3 Jan 2019 10:03:46 +0100
+Subject: [PATCH] qemu: process: SEV: Relabel guest owner's SEV files created
+ before start
+
+Before launching a SEV guest we take the base64-encoded guest owner's
+data specified in launchSecurity and create files with the same content
+under /var/lib/libvirt/qemu/<domain>. The reason for this is that we
+need to pass these files on to QEMU which then uses them to communicate
+with the SEV firmware, except when it doesn't have permissions to open
+those files since we don't relabel them.
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1658112
+
+Signed-off-by: Erik Skultety <eskultet@redhat.com>
+Acked-by: Michal Privoznik <mprivozn@redhat.com>
+(cherry picked from commit 7dc31fe503e540d5b4ee4f94d61842aa6e302e94)
+Signed-off-by: Erik Skultety <eskultet@redhat.com>
+Message-Id: <6bde21a3bda257a042d6f6c1d78ab1bf12c196d3.1546506016.git.eskultet@redhat.com>
+Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/qemu/qemu_process.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
+index 757e2d33a4..bc573f96a4 100644
+--- a/src/qemu/qemu_process.c
++++ b/src/qemu/qemu_process.c
+@@ -5990,6 +5990,7 @@ qemuProcessSEVCreateFile(virDomainObjPtr vm,
+                          const char *data)
+ {
+     qemuDomainObjPrivatePtr priv = vm->privateData;
++    virQEMUDriverPtr driver = priv->driver;
+     char *configFile;
+     int ret = -1;
+ 
+@@ -6002,6 +6003,9 @@ qemuProcessSEVCreateFile(virDomainObjPtr vm,
+         goto cleanup;
+     }
+ 
++    if (qemuSecurityDomainSetPathLabel(driver, vm, configFile, true) < 0)
++        goto cleanup;
++
+     ret = 0;
+  cleanup:
+     VIR_FREE(configFile);
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-qemuBuildMemoryBackendProps-Pass-priv-instead-of-its-individual-members.patch b/SOURCES/libvirt-qemuBuildMemoryBackendProps-Pass-priv-instead-of-its-individual-members.patch
new file mode 100644
index 0000000..778d3b0
--- /dev/null
+++ b/SOURCES/libvirt-qemuBuildMemoryBackendProps-Pass-priv-instead-of-its-individual-members.patch
@@ -0,0 +1,172 @@
+From c59ebd3e7bd1307ef6907a830dc9617eb6fe39b2 Mon Sep 17 00:00:00 2001
+Message-Id: <c59ebd3e7bd1307ef6907a830dc9617eb6fe39b2@dist-git>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Tue, 18 Dec 2018 11:47:35 +0100
+Subject: [PATCH] qemuBuildMemoryBackendProps: Pass @priv instead of its
+ individual members
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1624223
+
+So far we have two arguments that we are passing to
+qemuBuildMemoryBackendProps() and that are taken from domain
+private data: @qemuCaps and @autoNodeset. In the next commit I
+will use one more item from there. Therefore, instead of having
+it as yet another argument to the function, pass pointer to the
+private data object.
+
+There is one change in qemuDomainAttachMemory() where previously
+@autoNodeset was NULL but now is priv->autoNodeset (which may be
+set). This is safe to do as @autoNodeset is advisory only.
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Reviewed-by: John Ferlan <jferlan@redhat.com>
+(cherry picked from commit 9923584c628e160705124ad81d782a7214aac8d3)
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+
+Conflicts:
+src/qemu/qemu_command.c: Context mostly, as memfd backend is not
+                         backported (24b74d187ca).
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Message-Id: <71d56cdc7e5cdd0c9b664ded2a4cf93e3e9d38b0.1545129996.git.mprivozn@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/qemu/qemu_command.c | 28 +++++++++++++---------------
+ src/qemu/qemu_command.h |  3 +--
+ src/qemu/qemu_hotplug.c |  2 +-
+ 3 files changed, 15 insertions(+), 18 deletions(-)
+
+diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
+index c06f396b44..fa2b904239 100644
+--- a/src/qemu/qemu_command.c
++++ b/src/qemu/qemu_command.c
+@@ -3041,22 +3041,21 @@ qemuBuildControllerDevCommandLine(virCommandPtr cmd,
+  * @backendProps: [out] constructed object
+  * @alias: alias of the device
+  * @cfg: qemu driver config object
+- * @qemuCaps: qemu capabilities object
++ * @priv: pointer to domain private object
+  * @def: domain definition object
+  * @mem: memory definition object
+- * @autoNodeset: fallback nodeset in case of automatic NUMA placement
+  * @force: forcibly use one of the backends
+  *
+  * Creates a configuration object that represents memory backend of given guest
+- * NUMA node (domain @def and @mem). Use @autoNodeset to fine tune the
++ * NUMA node (domain @def and @mem). Use @priv->autoNodeset to fine tune the
+  * placement of the memory on the host NUMA nodes.
+  *
+  * By default, if no memory-backend-* object is necessary to fulfil the guest
+  * configuration value of 1 is returned. This behaviour can be suppressed by
+  * setting @force to true in which case 0 would be returned.
+  *
+- * Then, if one of the two memory-backend-* should be used, the @qemuCaps is
+- * consulted to check if qemu does support it.
++ * Then, if one of the two memory-backend-* should be used, the @priv->qemuCaps
++ * is consulted to check if qemu does support it.
+  *
+  * Returns: 0 on success,
+  *          1 on success and if there's no need to use memory-backend-*
+@@ -3066,10 +3065,9 @@ int
+ qemuBuildMemoryBackendProps(virJSONValuePtr *backendProps,
+                             const char *alias,
+                             virQEMUDriverConfigPtr cfg,
+-                            virQEMUCapsPtr qemuCaps,
++                            qemuDomainObjPrivatePtr priv,
+                             virDomainDefPtr def,
+                             virDomainMemoryDefPtr mem,
+-                            virBitmapPtr autoNodeset,
+                             bool force)
+ {
+     const char *backendType = "memory-backend-file";
+@@ -3207,7 +3205,7 @@ qemuBuildMemoryBackendProps(virJSONValuePtr *backendProps,
+ 
+         if (!mem->nvdimmPath &&
+             discard == VIR_TRISTATE_BOOL_YES) {
+-            if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_MEMORY_FILE_DISCARD)) {
++            if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_OBJECT_MEMORY_FILE_DISCARD)) {
+                 virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                                _("this QEMU doesn't support memory discard"));
+                 goto cleanup;
+@@ -3244,7 +3242,7 @@ qemuBuildMemoryBackendProps(virJSONValuePtr *backendProps,
+     if (mem->sourceNodes) {
+         nodemask = mem->sourceNodes;
+     } else {
+-        if (virDomainNumatuneMaybeGetNodeset(def->numa, autoNodeset,
++        if (virDomainNumatuneMaybeGetNodeset(def->numa, priv->autoNodeset,
+                                              &nodemask, mem->targetNode) < 0)
+             goto cleanup;
+     }
+@@ -3270,13 +3268,13 @@ qemuBuildMemoryBackendProps(virJSONValuePtr *backendProps,
+     } else {
+         /* otherwise check the required capability */
+         if (STREQ(backendType, "memory-backend-file") &&
+-            !virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_MEMORY_FILE)) {
++            !virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_OBJECT_MEMORY_FILE)) {
+             virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                            _("this qemu doesn't support the "
+                              "memory-backend-file object"));
+             goto cleanup;
+         } else if (STREQ(backendType, "memory-backend-ram") &&
+-                   !virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_MEMORY_RAM)) {
++                   !virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_OBJECT_MEMORY_RAM)) {
+             virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                            _("this qemu doesn't support the "
+                              "memory-backend-ram object"));
+@@ -3319,8 +3317,8 @@ qemuBuildMemoryCellBackendStr(virDomainDefPtr def,
+     mem.targetNode = cell;
+     mem.info.alias = alias;
+ 
+-    if ((rc = qemuBuildMemoryBackendProps(&props, alias, cfg, priv->qemuCaps,
+-                                          def, &mem, priv->autoNodeset, false)) < 0)
++    if ((rc = qemuBuildMemoryBackendProps(&props, alias, cfg,
++                                          priv, def, &mem, false)) < 0)
+         goto cleanup;
+ 
+     if (virQEMUBuildObjectCommandlineFromJSON(buf, props) < 0)
+@@ -3356,8 +3354,8 @@ qemuBuildMemoryDimmBackendStr(virBufferPtr buf,
+     if (virAsprintf(&alias, "mem%s", mem->info.alias) < 0)
+         goto cleanup;
+ 
+-    if (qemuBuildMemoryBackendProps(&props, alias, cfg, priv->qemuCaps,
+-                                    def, mem, priv->autoNodeset, true) < 0)
++    if (qemuBuildMemoryBackendProps(&props, alias, cfg,
++                                    priv, def, mem, true) < 0)
+         goto cleanup;
+ 
+     if (virQEMUBuildObjectCommandlineFromJSON(buf, props) < 0)
+diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h
+index e8cd8ed04e..bf46bde48f 100644
+--- a/src/qemu/qemu_command.h
++++ b/src/qemu/qemu_command.h
+@@ -125,10 +125,9 @@ int qemuBuildControllerDevStr(const virDomainDef *domainDef,
+ int qemuBuildMemoryBackendProps(virJSONValuePtr *backendProps,
+                                 const char *alias,
+                                 virQEMUDriverConfigPtr cfg,
+-                                virQEMUCapsPtr qemuCaps,
++                                qemuDomainObjPrivatePtr priv,
+                                 virDomainDefPtr def,
+                                 virDomainMemoryDefPtr mem,
+-                                virBitmapPtr autoNodeset,
+                                 bool force);
+ 
+ char *qemuBuildMemoryDeviceStr(virDomainMemoryDefPtr mem);
+diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
+index 410cdca3c5..5b9a5683bb 100644
+--- a/src/qemu/qemu_hotplug.c
++++ b/src/qemu/qemu_hotplug.c
+@@ -2121,7 +2121,7 @@ qemuDomainAttachMemory(virQEMUDriverPtr driver,
+         goto cleanup;
+ 
+     if (qemuBuildMemoryBackendProps(&props, objalias, cfg,
+-                                    priv->qemuCaps, vm->def, mem, NULL, true) < 0)
++                                    priv, vm->def, mem, true) < 0)
+         goto cleanup;
+ 
+     if (qemuProcessBuildDestroyMemoryPaths(driver, vm, mem, true) < 0)
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-qemuDomainRemoveRNGDevice-Remove-associated-chardev-too.patch b/SOURCES/libvirt-qemuDomainRemoveRNGDevice-Remove-associated-chardev-too.patch
new file mode 100644
index 0000000..61af820
--- /dev/null
+++ b/SOURCES/libvirt-qemuDomainRemoveRNGDevice-Remove-associated-chardev-too.patch
@@ -0,0 +1,76 @@
+From d50cf2d60114e7e33c2bd25fb67566a889057b77 Mon Sep 17 00:00:00 2001
+Message-Id: <d50cf2d60114e7e33c2bd25fb67566a889057b77@dist-git>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Mon, 8 Apr 2019 10:57:30 +0200
+Subject: [PATCH] qemuDomainRemoveRNGDevice: Remove associated chardev too
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1656014
+
+An RNG device can consists of more devices than RND device
+itself. For instance, in case of EGD there is a chardev that
+connects to EGD daemon and feeds the qemu with random data. When
+doing RNG device removal we have to remove the associated chardev
+as well.
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+
+(cherry picked from commit 7730a2ead4279e3a11771e1069096747988410cf)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1508149
+
+Signed-off-by: Andrea Bolognani <abologna@redhat.com>
+Message-Id: <20190408085732.28684-14-abologna@redhat.com>
+Reviewed-by: Laine Stump <laine@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/qemu/qemu_hotplug.c | 16 +++++++++++++---
+ 1 file changed, 13 insertions(+), 3 deletions(-)
+
+diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
+index abe2632556..8394efa739 100644
+--- a/src/qemu/qemu_hotplug.c
++++ b/src/qemu/qemu_hotplug.c
+@@ -4408,7 +4408,7 @@ qemuDomainRemoveRNGDevice(virQEMUDriverPtr driver,
+     qemuDomainObjPrivatePtr priv = vm->privateData;
+     ssize_t idx;
+     int ret = -1;
+-    int rc;
++    int rc = 0;
+ 
+     VIR_DEBUG("Removing RNG device %s from domain %p %s",
+               rng->info.alias, vm, vm->def->name);
+@@ -4422,7 +4422,17 @@ qemuDomainRemoveRNGDevice(virQEMUDriverPtr driver,
+ 
+     qemuDomainObjEnterMonitor(driver, vm);
+ 
+-    rc = qemuMonitorDelObject(priv->mon, objAlias);
++    if (qemuDomainDetachExtensionDevice(priv->mon, &rng->info) < 0)
++        rc = -1;
++
++    if (rc == 0 &&
++        qemuMonitorDelObject(priv->mon, objAlias) < 0)
++        rc = -1;
++
++    if (rng->backend == VIR_DOMAIN_RNG_BACKEND_EGD &&
++        rc == 0 &&
++        qemuMonitorDetachCharDev(priv->mon, charAlias) < 0)
++        rc = -1;
+ 
+     if (qemuDomainObjExitMonitor(driver, vm) < 0)
+         goto cleanup;
+@@ -4431,7 +4441,7 @@ qemuDomainRemoveRNGDevice(virQEMUDriverPtr driver,
+         rc == 0 &&
+         qemuDomainDelChardevTLSObjects(driver, vm, rng->source.chardev,
+                                        charAlias) < 0)
+-        goto cleanup;
++        rc = -1;
+ 
+     virDomainAuditRNG(vm, rng, NULL, "detach", rc == 0);
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-qemuProcessBuildDestroyMemoryPathsImpl-Don-t-overwrite-error.patch b/SOURCES/libvirt-qemuProcessBuildDestroyMemoryPathsImpl-Don-t-overwrite-error.patch
new file mode 100644
index 0000000..0329ea3
--- /dev/null
+++ b/SOURCES/libvirt-qemuProcessBuildDestroyMemoryPathsImpl-Don-t-overwrite-error.patch
@@ -0,0 +1,45 @@
+From ab0cc413165b8a80d68b30b7e69c611f7087a29b Mon Sep 17 00:00:00 2001
+Message-Id: <ab0cc413165b8a80d68b30b7e69c611f7087a29b@dist-git>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Thu, 3 Jan 2019 10:03:43 +0100
+Subject: [PATCH] qemuProcessBuildDestroyMemoryPathsImpl: Don't overwrite error
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The qemuSecurityDomainSetPathLabel() function reports perfect
+error itself. Do not overwrite it to something less meaningful.
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit 577e68dff90e617a20165dfede0390faa1e24031)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1658112
+
+Signed-off-by: Erik Skultety <eskultet@redhat.com>
+Message-Id: <7ca28756d9a136d67b01df15efe1271266017164.1546506016.git.eskultet@redhat.com>
+Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/qemu/qemu_process.c | 5 +----
+ 1 file changed, 1 insertion(+), 4 deletions(-)
+
+diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
+index c220accfaf..34aac69afc 100644
+--- a/src/qemu/qemu_process.c
++++ b/src/qemu/qemu_process.c
+@@ -3672,11 +3672,8 @@ qemuProcessBuildDestroyMemoryPathsImpl(virQEMUDriverPtr driver,
+         }
+ 
+         if (qemuSecurityDomainSetPathLabel(driver->securityManager,
+-                                           def, path, true) < 0) {
+-            virReportError(VIR_ERR_INTERNAL_ERROR,
+-                            _("Unable to label %s"), path);
++                                           def, path, true) < 0)
+             return -1;
+-        }
+     } else {
+         if (virFileDeleteTree(path) < 0)
+             return -1;
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-qemu_capabilities-Inroduce-virQEMUCapsGetCPUModelX86Data.patch b/SOURCES/libvirt-qemu_capabilities-Inroduce-virQEMUCapsGetCPUModelX86Data.patch
new file mode 100644
index 0000000..4ad6900
--- /dev/null
+++ b/SOURCES/libvirt-qemu_capabilities-Inroduce-virQEMUCapsGetCPUModelX86Data.patch
@@ -0,0 +1,120 @@
+From 2d8d4379690e55d8d9a0b194ddef33d073154c7b Mon Sep 17 00:00:00 2001
+Message-Id: <2d8d4379690e55d8d9a0b194ddef33d073154c7b@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:25:03 +0200
+Subject: [PATCH] qemu_capabilities: Inroduce virQEMUCapsGetCPUModelX86Data
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The code for transforming qemuMonitorCPUModelInfo data from QEMU into
+virCPUDefPtr consumable by virCPU* APIs was hidden inside
+virQEMUCapsInitCPUModelX86. This patch moves it into a new function to
+make it usable in tests.
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit 30e4faac2f3e72aec29be9963d7a5394153e812f)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1686895
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <e91c6c1e8de59a6cc151154f7c2a9eae79249fa5.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/qemu/qemu_capabilities.c | 50 ++++++++++++++++++++++++------------
+ src/qemu/qemu_capspriv.h     |  4 +++
+ 2 files changed, 38 insertions(+), 16 deletions(-)
+
+diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
+index 5539d168cd..5a7160d02e 100644
+--- a/src/qemu/qemu_capabilities.c
++++ b/src/qemu/qemu_capabilities.c
+@@ -2812,28 +2812,17 @@ virQEMUCapsInitCPUModelS390(virQEMUCapsPtr qemuCaps,
+ }
+ 
+ 
+-/**
+- * Returns  0 when host CPU model provided by QEMU was filled in qemuCaps,
+- *          1 when the caller should fall back to using virCapsPtr->host.cpu,
+- *         -1 on error.
+- */
+-static int
+-virQEMUCapsInitCPUModelX86(virQEMUCapsPtr qemuCaps,
+-                           virDomainVirtType type,
+-                           qemuMonitorCPUModelInfoPtr model,
+-                           virCPUDefPtr cpu,
+-                           bool migratable)
++virCPUDataPtr
++virQEMUCapsGetCPUModelX86Data(qemuMonitorCPUModelInfoPtr model,
++                              bool migratable)
+ {
+-    virCPUDataPtr data = NULL;
+     unsigned long long sigFamily = 0;
+     unsigned long long sigModel = 0;
+     unsigned long long sigStepping = 0;
+-    int ret = -1;
++    virCPUDataPtr data = NULL;
++    virCPUDataPtr ret = NULL;
+     size_t i;
+ 
+-    if (!model)
+-        return 1;
+-
+     if (!(data = virCPUDataNew(VIR_ARCH_X86_64)))
+         goto cleanup;
+ 
+@@ -2874,6 +2863,35 @@ virQEMUCapsInitCPUModelX86(virQEMUCapsPtr qemuCaps,
+     if (virCPUx86DataSetSignature(data, sigFamily, sigModel, sigStepping) < 0)
+         goto cleanup;
+ 
++    VIR_STEAL_PTR(ret, data);
++
++ cleanup:
++    virCPUDataFree(data);
++    return ret;
++}
++
++
++/**
++ * Returns  0 when host CPU model provided by QEMU was filled in qemuCaps,
++ *          1 when the caller should fall back to using virCapsPtr->host.cpu,
++ *         -1 on error.
++ */
++static int
++virQEMUCapsInitCPUModelX86(virQEMUCapsPtr qemuCaps,
++                           virDomainVirtType type,
++                           qemuMonitorCPUModelInfoPtr model,
++                           virCPUDefPtr cpu,
++                           bool migratable)
++{
++    virCPUDataPtr data = NULL;
++    int ret = -1;
++
++    if (!model)
++        return 1;
++
++    if (!(data = virQEMUCapsGetCPUModelX86Data(model, migratable)))
++        goto cleanup;
++
+     if (cpuDecode(cpu, data, virQEMUCapsGetCPUDefinitions(qemuCaps, type)) < 0)
+         goto cleanup;
+ 
+diff --git a/src/qemu/qemu_capspriv.h b/src/qemu/qemu_capspriv.h
+index cb5e0dd9a9..70cdbbc504 100644
+--- a/src/qemu/qemu_capspriv.h
++++ b/src/qemu/qemu_capspriv.h
+@@ -80,6 +80,10 @@ virQEMUCapsSetCPUModelInfo(virQEMUCapsPtr qemuCaps,
+                            virDomainVirtType type,
+                            qemuMonitorCPUModelInfoPtr modelInfo);
+ 
++virCPUDataPtr
++virQEMUCapsGetCPUModelX86Data(qemuMonitorCPUModelInfoPtr model,
++                              bool migratable);
++
+ virCPUDefPtr
+ virQEMUCapsProbeHostCPUForEmulator(virArch hostArch,
+                                    virQEMUCapsPtr qemuCaps,
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-qemu_capabilities-Introduce-virQEMUCapsGetCPUModelInfo.patch b/SOURCES/libvirt-qemu_capabilities-Introduce-virQEMUCapsGetCPUModelInfo.patch
new file mode 100644
index 0000000..e28993f
--- /dev/null
+++ b/SOURCES/libvirt-qemu_capabilities-Introduce-virQEMUCapsGetCPUModelInfo.patch
@@ -0,0 +1,65 @@
+From 161668ec1a5e6b5cba0136ef50926b5c53802941 Mon Sep 17 00:00:00 2001
+Message-Id: <161668ec1a5e6b5cba0136ef50926b5c53802941@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:25:04 +0200
+Subject: [PATCH] qemu_capabilities: Introduce virQEMUCapsGetCPUModelInfo
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This is a simple wrapper around virQEMUCapsGetHostCPUData usable in
+tests for getting qemuMonitorCPUModelInfoPtr from QEMU caps.
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit 8aa47cc072fb9a3a8e8b15c6509aae648f5c24e0)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1686895
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <4e467c308f24313e69e21c637663f6744482b266.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/qemu/qemu_capabilities.c | 10 ++++++++++
+ src/qemu/qemu_capspriv.h     |  4 ++++
+ 2 files changed, 14 insertions(+)
+
+diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
+index 5a7160d02e..942cbf272d 100644
+--- a/src/qemu/qemu_capabilities.c
++++ b/src/qemu/qemu_capabilities.c
+@@ -3049,6 +3049,16 @@ virQEMUCapsInitHostCPUModel(virQEMUCapsPtr qemuCaps,
+ }
+ 
+ 
++qemuMonitorCPUModelInfoPtr
++virQEMUCapsGetCPUModelInfo(virQEMUCapsPtr qemuCaps,
++                           virDomainVirtType type)
++{
++    virQEMUCapsHostCPUDataPtr cpuData = virQEMUCapsGetHostCPUData(qemuCaps, type);
++
++    return cpuData->info;
++}
++
++
+ void
+ virQEMUCapsSetCPUModelInfo(virQEMUCapsPtr qemuCaps,
+                            virDomainVirtType type,
+diff --git a/src/qemu/qemu_capspriv.h b/src/qemu/qemu_capspriv.h
+index 70cdbbc504..c3b7f934a9 100644
+--- a/src/qemu/qemu_capspriv.h
++++ b/src/qemu/qemu_capspriv.h
+@@ -75,6 +75,10 @@ virQEMUCapsInitCPUModel(virQEMUCapsPtr qemuCaps,
+ void
+ virQEMUCapsInitQMPBasicArch(virQEMUCapsPtr qemuCaps);
+ 
++qemuMonitorCPUModelInfoPtr
++virQEMUCapsGetCPUModelInfo(virQEMUCapsPtr qemuCaps,
++                           virDomainVirtType type);
++
+ void
+ virQEMUCapsSetCPUModelInfo(virQEMUCapsPtr qemuCaps,
+                            virDomainVirtType type,
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-qemu_capabilities-Use-virQEMUCapsGetCPUModelInfo.patch b/SOURCES/libvirt-qemu_capabilities-Use-virQEMUCapsGetCPUModelInfo.patch
new file mode 100644
index 0000000..d3429bd
--- /dev/null
+++ b/SOURCES/libvirt-qemu_capabilities-Use-virQEMUCapsGetCPUModelInfo.patch
@@ -0,0 +1,132 @@
+From deeb15a330b987612c8f50df1de8b2acfc2ed703 Mon Sep 17 00:00:00 2001
+Message-Id: <deeb15a330b987612c8f50df1de8b2acfc2ed703@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:25:05 +0200
+Subject: [PATCH] qemu_capabilities: Use virQEMUCapsGetCPUModelInfo
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Most places in qemu_capabilities.c which call virQEMUCapsGetHostCPUData
+actually need qemuMonitorCPUModelInfoPtr from QEMU caps. Let's use the
+wrapper introduced in the previous commit instead.
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit 793a9293caabc9876bf7734150ba3acdd85d1649)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1686895
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <6d9804c79ffda5aed3e1ac772b7cc003e930490d.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/qemu/qemu_capabilities.c | 31 ++++++++++++++-----------------
+ 1 file changed, 14 insertions(+), 17 deletions(-)
+
+diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
+index 942cbf272d..851cb73cfc 100644
+--- a/src/qemu/qemu_capabilities.c
++++ b/src/qemu/qemu_capabilities.c
+@@ -2395,7 +2395,6 @@ virQEMUCapsProbeQMPHostCPU(virQEMUCapsPtr qemuCaps,
+     const char *model;
+     qemuMonitorCPUModelExpansionType type;
+     virDomainVirtType virtType;
+-    virQEMUCapsHostCPUDataPtr cpuData;
+     int ret = -1;
+ 
+     if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_QUERY_CPU_MODEL_EXPANSION))
+@@ -2409,8 +2408,6 @@ virQEMUCapsProbeQMPHostCPU(virQEMUCapsPtr qemuCaps,
+         model = "host";
+     }
+ 
+-    cpuData = virQEMUCapsGetHostCPUData(qemuCaps, virtType);
+-
+     /* Some x86_64 features defined in cpu_map.xml use spelling which differ
+      * from the one preferred by QEMU. Static expansion would give us only the
+      * preferred spelling, thus we need to do a full expansion on the result of
+@@ -2462,7 +2459,8 @@ virQEMUCapsProbeQMPHostCPU(virQEMUCapsPtr qemuCaps,
+         modelInfo->migratability = true;
+     }
+ 
+-    VIR_STEAL_PTR(cpuData->info, modelInfo);
++    virQEMUCapsSetCPUModelInfo(qemuCaps, virtType, modelInfo);
++    modelInfo = NULL;
+     ret = 0;
+ 
+  cleanup:
+@@ -2487,24 +2485,24 @@ virQEMUCapsGetCPUFeatures(virQEMUCapsPtr qemuCaps,
+                           bool migratable,
+                           char ***features)
+ {
+-    virQEMUCapsHostCPUDataPtr data;
++    qemuMonitorCPUModelInfoPtr modelInfo;
+     char **list;
+     size_t i;
+     size_t n;
+     int ret = -1;
+ 
+     *features = NULL;
+-    data = virQEMUCapsGetHostCPUData(qemuCaps, virtType);
++    modelInfo = virQEMUCapsGetCPUModelInfo(qemuCaps, virtType);
+ 
+-    if (!data->info)
++    if (!modelInfo)
+         return 0;
+ 
+-    if (VIR_ALLOC_N(list, data->info->nprops + 1) < 0)
++    if (VIR_ALLOC_N(list, modelInfo->nprops + 1) < 0)
+         return -1;
+ 
+     n = 0;
+-    for (i = 0; i < data->info->nprops; i++) {
+-        qemuMonitorCPUPropertyPtr prop = data->info->props + i;
++    for (i = 0; i < modelInfo->nprops; i++) {
++        qemuMonitorCPUPropertyPtr prop = modelInfo->props + i;
+ 
+         if (migratable && prop->migratable == VIR_TRISTATE_BOOL_NO)
+             continue;
+@@ -2514,7 +2512,7 @@ virQEMUCapsGetCPUFeatures(virQEMUCapsPtr qemuCaps,
+     }
+ 
+     VIR_STEAL_PTR(*features, list);
+-    if (migratable && !data->info->migratability)
++    if (migratable && !modelInfo->migratability)
+         ret = 1;
+     else
+         ret = 0;
+@@ -2915,17 +2913,17 @@ virQEMUCapsInitCPUModel(virQEMUCapsPtr qemuCaps,
+                         virCPUDefPtr cpu,
+                         bool migratable)
+ {
+-    virQEMUCapsHostCPUDataPtr cpuData = virQEMUCapsGetHostCPUData(qemuCaps, type);
++    qemuMonitorCPUModelInfoPtr modelInfo = virQEMUCapsGetCPUModelInfo(qemuCaps, type);
+     int ret = 1;
+ 
+-    if (migratable && cpuData->info && !cpuData->info->migratability)
++    if (migratable && modelInfo && !modelInfo->migratability)
+         return 1;
+ 
+     if (ARCH_IS_S390(qemuCaps->arch)) {
+-        ret = virQEMUCapsInitCPUModelS390(qemuCaps, type, cpuData->info,
++        ret = virQEMUCapsInitCPUModelS390(qemuCaps, type, modelInfo,
+                                           cpu, migratable);
+     } else if (ARCH_IS_X86(qemuCaps->arch)) {
+-        ret = virQEMUCapsInitCPUModelX86(qemuCaps, type, cpuData->info,
++        ret = virQEMUCapsInitCPUModelX86(qemuCaps, type, modelInfo,
+                                          cpu, migratable);
+     }
+ 
+@@ -3655,8 +3653,7 @@ virQEMUCapsFormatHostCPUModelInfo(virQEMUCapsPtr qemuCaps,
+                                   virBufferPtr buf,
+                                   virDomainVirtType type)
+ {
+-    virQEMUCapsHostCPUDataPtr cpuData = virQEMUCapsGetHostCPUData(qemuCaps, type);
+-    qemuMonitorCPUModelInfoPtr model = cpuData->info;
++    qemuMonitorCPUModelInfoPtr model = virQEMUCapsGetCPUModelInfo(qemuCaps, type);
+     const char *typeStr = type == VIR_DOMAIN_VIRT_KVM ? "kvm" : "tcg";
+     size_t i;
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-qemu_command-Use-canonical-names-of-CPU-features.patch b/SOURCES/libvirt-qemu_command-Use-canonical-names-of-CPU-features.patch
new file mode 100644
index 0000000..64028b2
--- /dev/null
+++ b/SOURCES/libvirt-qemu_command-Use-canonical-names-of-CPU-features.patch
@@ -0,0 +1,137 @@
+From 243a37dbf1a42f75a2529b954dac40bb0dd4059e Mon Sep 17 00:00:00 2001
+Message-Id: <243a37dbf1a42f75a2529b954dac40bb0dd4059e@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:25:55 +0200
+Subject: [PATCH] qemu_command: Use canonical names of CPU features
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+When building QEMU command line, we should use the preferred spelling of
+each CPU feature without relying on compatibility aliases (which may be
+removed at some point).
+
+The "unavailable-features" CPU property is used as a witness for the
+correct names of the features in our translation table.
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit 5030a7450b0f0117a7903303572c6bda6c012327)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1697627
+
+Conflicts:
+	src/qemu/qemu_capabilities.c
+            - several refactors are missing
+
+	tests/qemuxml2argvdata/eoi-disabled.x86_64-latest.args
+	tests/qemuxml2argvdata/eoi-enabled.x86_64-latest.args
+	tests/qemuxml2argvdata/kvmclock+eoi-disabled.x86_64-latest.args
+	tests/qemuxml2argvdata/pv-spinlock-disabled.x86_64-latest.args
+	tests/qemuxml2argvdata/pv-spinlock-enabled.x86_64-latest.args
+            - these were not backported
+
+	tests/qemuxml2argvdata/cpu-translation.x86_64-latest.args
+            - downstream patch to add rtm=on and hle=on for Haswell
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <5d34d0b9087230e4dc0f0936b34e73b5f1781832.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/qemu/qemu_capabilities.c                              | 8 +++++++-
+ src/qemu/qemu_capabilities.h                              | 1 +
+ src/qemu/qemu_command.c                                   | 2 ++
+ tests/qemucapabilitiesdata/caps_4.1.0.x86_64.xml          | 1 +
+ tests/qemuxml2argvdata/cpu-translation.x86_64-latest.args | 6 +++---
+ 5 files changed, 14 insertions(+), 4 deletions(-)
+
+diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
+index fb260eae96..c48d66b39b 100644
+--- a/src/qemu/qemu_capabilities.c
++++ b/src/qemu/qemu_capabilities.c
+@@ -516,6 +516,7 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST,
+               "machine.pseries.cap-nested-hv",
+               "x86-max-cpu",
+               "cpu-unavailable-features",
++              "canonical-cpu-features",
+     );
+ 
+ 
+@@ -2799,7 +2800,9 @@ virQEMUCapsCPUFeatureTranslate(virQEMUCapsPtr qemuCaps,
+     if (ARCH_IS_X86(qemuCaps->arch))
+         table = virQEMUCapsCPUFeaturesX86;
+ 
+-    if (!table || !feature)
++    if (!table ||
++        !feature ||
++        !virQEMUCapsGet(qemuCaps, QEMU_CAPS_CANONICAL_CPU_FEATURES))
+         return feature;
+ 
+     for (entry = table; entry->libvirt; entry++) {
+@@ -4381,6 +4384,9 @@ virQEMUCapsInitQMPMonitor(virQEMUCapsPtr qemuCaps,
+             virQEMUCapsClear(qemuCaps, QEMU_CAPS_DEVICE_VFIO_CCW);
+     }
+ 
++    if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_CPU_UNAVAILABLE_FEATURES))
++        virQEMUCapsSet(qemuCaps, QEMU_CAPS_CANONICAL_CPU_FEATURES);
++
+     /* Probe for SEV capabilities */
+     if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_SEV_GUEST)) {
+         int rc = virQEMUCapsProbeQMPSEVCapabilities(qemuCaps, mon);
+diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
+index 5aa41efdb0..1767b2ab6c 100644
+--- a/src/qemu/qemu_capabilities.h
++++ b/src/qemu/qemu_capabilities.h
+@@ -496,6 +496,7 @@ typedef enum { /* virQEMUCapsFlags grouping marker for syntax-check */
+     QEMU_CAPS_MACHINE_PSERIES_CAP_NESTED_HV, /* -machine pseries.cap-nested-hv */
+     QEMU_CAPS_X86_MAX_CPU, /* max-x86_64-cpu type exists */
+     QEMU_CAPS_CPU_UNAVAILABLE_FEATURES, /* "unavailable-features" CPU property */
++    QEMU_CAPS_CANONICAL_CPU_FEATURES, /* avoid CPU feature aliases */
+ 
+     QEMU_CAPS_LAST /* this must always be the last item */
+ } virQEMUCapsFlags;
+diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
+index bea9a208e5..b5c0588e3c 100644
+--- a/src/qemu/qemu_command.c
++++ b/src/qemu/qemu_command.c
+@@ -6819,6 +6819,8 @@ qemuBuildCpuFeature(virQEMUCapsPtr qemuCaps,
+                     const char *name,
+                     bool state)
+ {
++    name = virQEMUCapsCPUFeatureToQEMU(qemuCaps, name);
++
+     if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_QUERY_CPU_MODEL_EXPANSION))
+         virBufferAsprintf(buf, ",%s=%s", name, state ? "on" : "off");
+     else
+diff --git a/tests/qemucapabilitiesdata/caps_4.1.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_4.1.0.x86_64.xml
+index 95d26dfce8..9245641df8 100644
+--- a/tests/qemucapabilitiesdata/caps_4.1.0.x86_64.xml
++++ b/tests/qemucapabilitiesdata/caps_4.1.0.x86_64.xml
+@@ -216,6 +216,7 @@
+   <flag name='vfio-pci.display'/>
+   <flag name='x86-max-cpu'/>
+   <flag name='cpu-unavailable-features'/>
++  <flag name='canonical-cpu-features'/>
+   <version>4000050</version>
+   <kvmVersion>0</kvmVersion>
+   <microcodeVersion>473743</microcodeVersion>
+diff --git a/tests/qemuxml2argvdata/cpu-translation.x86_64-latest.args b/tests/qemuxml2argvdata/cpu-translation.x86_64-latest.args
+index 898b987086..6bc88bbe86 100644
+--- a/tests/qemuxml2argvdata/cpu-translation.x86_64-latest.args
++++ b/tests/qemuxml2argvdata/cpu-translation.x86_64-latest.args
+@@ -10,9 +10,9 @@ QEMU_AUDIO_DRV=none \
+ -object secret,id=masterKey0,format=raw,\
+ file=/tmp/lib/domain--1-QEMUGuest1/master-key.aes \
+ -machine pc,accel=tcg,usb=off,dump-guest-core=off \
+--cpu Haswell,pclmuldq=on,ds_cpl=on,tsc_adjust=on,fxsr_opt=on,lahf_lm=on,\
+-cmp_legacy=on,nodeid_msr=on,perfctr_core=on,perfctr_nb=on,rtm=on,hle=on,\
+-kvm_pv_eoi=on,kvm_pv_unhalt=on \
++-cpu Haswell,pclmulqdq=on,ds-cpl=on,tsc-adjust=on,fxsr-opt=on,lahf-lm=on,\
++cmp-legacy=on,nodeid-msr=on,perfctr-core=on,perfctr-nb=on,rtm=on,hle=on,\
++kvm-pv-eoi=on,kvm-pv-unhalt=on \
+ -m 214 \
+ -realtime mlock=off \
+ -smp 1,sockets=1,cores=1,threads=1 \
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-qemu_command-Use-consistent-syntax-for-CPU-features.patch b/SOURCES/libvirt-qemu_command-Use-consistent-syntax-for-CPU-features.patch
new file mode 100644
index 0000000..4c375b5
--- /dev/null
+++ b/SOURCES/libvirt-qemu_command-Use-consistent-syntax-for-CPU-features.patch
@@ -0,0 +1,121 @@
+From b3f714b0907ff1a906d8725efb26733caa913b01 Mon Sep 17 00:00:00 2001
+Message-Id: <b3f714b0907ff1a906d8725efb26733caa913b01@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:25:47 +0200
+Subject: [PATCH] qemu_command: Use consistent syntax for CPU features
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Normal CPU features use modern -cpu ...,feature=on|off syntax when
+available, but kvm features kept using the old +feature or -feature.
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit e1ba4073961091522b1560472c5559124bd3c034)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1697627
+
+Conflicts:
+	tests/qemuxml2argvdata/eoi-disabled.x86_64-latest.args
+	tests/qemuxml2argvdata/eoi-enabled.x86_64-latest.args
+	tests/qemuxml2argvdata/kvmclock+eoi-disabled.x86_64-latest.args
+	tests/qemuxml2argvdata/pv-spinlock-disabled.x86_64-latest.args
+	tests/qemuxml2argvdata/pv-spinlock-enabled.x86_64-latest.args
+            - not backported
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <da608f8dcef1eeb3e62d4c1d921c8182c1b4d533.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/qemu/qemu_command.c | 46 +++++++++++++++++++----------------------
+ 1 file changed, 21 insertions(+), 25 deletions(-)
+
+diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
+index 7ffc4358e3..bea9a208e5 100644
+--- a/src/qemu/qemu_command.c
++++ b/src/qemu/qemu_command.c
+@@ -6813,6 +6813,19 @@ qemuBuildGlobalControllerCommandLine(virCommandPtr cmd,
+ }
+ 
+ 
++static void
++qemuBuildCpuFeature(virQEMUCapsPtr qemuCaps,
++                    virBufferPtr buf,
++                    const char *name,
++                    bool state)
++{
++    if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_QUERY_CPU_MODEL_EXPANSION))
++        virBufferAsprintf(buf, ",%s=%s", name, state ? "on" : "off");
++    else
++        virBufferAsprintf(buf, ",%c%s", state ? '+' : '-', name);
++}
++
++
+ static int
+ qemuBuildCpuModelArgStr(virQEMUDriverPtr driver,
+                         const virDomainDef *def,
+@@ -6890,18 +6903,12 @@ qemuBuildCpuModelArgStr(virQEMUDriverPtr driver,
+         switch ((virCPUFeaturePolicy) cpu->features[i].policy) {
+         case VIR_CPU_FEATURE_FORCE:
+         case VIR_CPU_FEATURE_REQUIRE:
+-            if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_QUERY_CPU_MODEL_EXPANSION))
+-                virBufferAsprintf(buf, ",%s=on", cpu->features[i].name);
+-            else
+-                virBufferAsprintf(buf, ",+%s", cpu->features[i].name);
++            qemuBuildCpuFeature(qemuCaps, buf, cpu->features[i].name, true);
+             break;
+ 
+         case VIR_CPU_FEATURE_DISABLE:
+         case VIR_CPU_FEATURE_FORBID:
+-            if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_QUERY_CPU_MODEL_EXPANSION))
+-                virBufferAsprintf(buf, ",%s=off", cpu->features[i].name);
+-            else
+-                virBufferAsprintf(buf, ",-%s", cpu->features[i].name);
++            qemuBuildCpuFeature(qemuCaps, buf, cpu->features[i].name, false);
+             break;
+ 
+         case VIR_CPU_FEATURE_OPTIONAL:
+@@ -6982,8 +6989,8 @@ qemuBuildCpuCommandLine(virCommandPtr cmd,
+ 
+         if (timer->name == VIR_DOMAIN_TIMER_NAME_KVMCLOCK &&
+             timer->present != -1) {
+-            virBufferAsprintf(&buf, ",%ckvmclock",
+-                              timer->present ? '+' : '-');
++            qemuBuildCpuFeature(qemuCaps, &buf, "kvmclock",
++                                !!timer->present);
+         } else if (timer->name == VIR_DOMAIN_TIMER_NAME_HYPERVCLOCK &&
+                    timer->present == 1) {
+             virBufferAddLit(&buf, ",hv_time");
+@@ -6994,24 +7001,13 @@ qemuBuildCpuCommandLine(virCommandPtr cmd,
+     }
+ 
+     if (def->apic_eoi) {
+-        char sign;
+-        if (def->apic_eoi == VIR_TRISTATE_SWITCH_ON)
+-            sign = '+';
+-        else
+-            sign = '-';
+-
+-        virBufferAsprintf(&buf, ",%ckvm_pv_eoi", sign);
++        qemuBuildCpuFeature(qemuCaps, &buf, "kvm_pv_eoi",
++                            def->apic_eoi == VIR_TRISTATE_SWITCH_ON);
+     }
+ 
+     if (def->features[VIR_DOMAIN_FEATURE_PVSPINLOCK]) {
+-        char sign;
+-        if (def->features[VIR_DOMAIN_FEATURE_PVSPINLOCK] ==
+-            VIR_TRISTATE_SWITCH_ON)
+-            sign = '+';
+-        else
+-            sign = '-';
+-
+-        virBufferAsprintf(&buf, ",%ckvm_pv_unhalt", sign);
++        qemuBuildCpuFeature(qemuCaps, &buf, "kvm_pv_unhalt",
++                            def->features[VIR_DOMAIN_FEATURE_PVSPINLOCK] == VIR_TRISTATE_SWITCH_ON);
+     }
+ 
+     if (def->features[VIR_DOMAIN_FEATURE_HYPERV] == VIR_TRISTATE_SWITCH_ON) {
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-qemu_domain-NVLink2-bridge-detection-function-for-PPC64.patch b/SOURCES/libvirt-qemu_domain-NVLink2-bridge-detection-function-for-PPC64.patch
new file mode 100644
index 0000000..6722b86
--- /dev/null
+++ b/SOURCES/libvirt-qemu_domain-NVLink2-bridge-detection-function-for-PPC64.patch
@@ -0,0 +1,85 @@
+From 8996236421b4adf090ac721e8d525953deb9687a Mon Sep 17 00:00:00 2001
+Message-Id: <8996236421b4adf090ac721e8d525953deb9687a@dist-git>
+From: Daniel Henrique Barboza <danielhb413@gmail.com>
+Date: Fri, 3 May 2019 13:54:52 +0200
+Subject: [PATCH] qemu_domain: NVLink2 bridge detection function for PPC64
+
+The NVLink2 support in QEMU implements the detection of NVLink2
+capable devices by verifying the attributes of the VFIO mem region
+QEMU allocates for the NVIDIA GPUs. To properly allocate an
+adequate amount of memLock, Libvirt needs this information before
+a QEMU instance is even created, thus querying QEMU is not
+possible and opening a VFIO window is too much.
+
+An alternative is presented in this patch. Making the following
+assumptions:
+
+- if we want GPU RAM to be available in the guest, an NVLink2 bridge
+must be passed through;
+
+- an unknown PCI device can be classified as a NVLink2 bridge
+if its device tree node has 'ibm,gpu', 'ibm,nvlink',
+'ibm,nvlink-speed' and 'memory-region'.
+
+This patch introduces a helper called @ppc64VFIODeviceIsNV2Bridge
+that checks the device tree node of a given PCI device and
+check if it meets the criteria to be a NVLink2 bridge. This
+new function will be used in a follow-up patch that, using the
+first assumption, will set up the rlimits of the guest
+accordingly.
+
+Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com>
+(cherry picked from commit cc9f03801c2618102027ddc4a988193ae290b651)
+
+https: //bugzilla.redhat.com/show_bug.cgi?id=1505998
+Signed-off-by: Erik Skultety <eskultet@redhat.com>
+Message-Id: <99efa386adcf68789b7c8cffda2ef24f5f47f0c4.1556884443.git.eskultet@redhat.com>
+Reviewed-by: Andrea Bolognani <abologna@redhat.com>
+---
+ src/qemu/qemu_domain.c | 30 ++++++++++++++++++++++++++++++
+ 1 file changed, 30 insertions(+)
+
+diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
+index f91de0b743..a8bc618389 100644
+--- a/src/qemu/qemu_domain.c
++++ b/src/qemu/qemu_domain.c
+@@ -9805,6 +9805,36 @@ qemuDomainUpdateCurrentMemorySize(virQEMUDriverPtr driver,
+ }
+ 
+ 
++/**
++ * ppc64VFIODeviceIsNV2Bridge:
++ * @device: string with the PCI device address
++ *
++ * This function receives a string that represents a PCI device,
++ * such as '0004:04:00.0', and tells if the device is a NVLink2
++ * bridge.
++ */
++static ATTRIBUTE_UNUSED bool
++ppc64VFIODeviceIsNV2Bridge(const char *device)
++{
++    const char *nvlink2Files[] = {"ibm,gpu", "ibm,nvlink",
++                                  "ibm,nvlink-speed", "memory-region"};
++    size_t i;
++
++    for (i = 0; i < ARRAY_CARDINALITY(nvlink2Files); i++) {
++        VIR_AUTOFREE(char *) file = NULL;
++
++        if ((virAsprintf(&file, "/sys/bus/pci/devices/%s/of_node/%s",
++                         device, nvlink2Files[i])) < 0)
++            return false;
++
++        if (!virFileExists(file))
++            return false;
++    }
++
++    return true;
++}
++
++
+ /**
+  * getPPC64MemLockLimitBytes:
+  * @def: domain definition
+-- 
+2.21.0
+
diff --git a/SOURCES/libvirt-qemu_domain-add-a-PPC64-memLockLimit-helper.patch b/SOURCES/libvirt-qemu_domain-add-a-PPC64-memLockLimit-helper.patch
new file mode 100644
index 0000000..82280d5
--- /dev/null
+++ b/SOURCES/libvirt-qemu_domain-add-a-PPC64-memLockLimit-helper.patch
@@ -0,0 +1,219 @@
+From 051451a1b9cefa42ecfd6d27dcb6a12ef49de072 Mon Sep 17 00:00:00 2001
+Message-Id: <051451a1b9cefa42ecfd6d27dcb6a12ef49de072@dist-git>
+From: Daniel Henrique Barboza <danielhb413@gmail.com>
+Date: Fri, 3 May 2019 13:54:51 +0200
+Subject: [PATCH] qemu_domain: add a PPC64 memLockLimit helper
+
+There is a lot of documentation in the comments about how PPC64 handles
+passthrough VFIO devices to calculate the @memLockLimit. And more will
+be added with the PPC64 NVLink2 support code.
+
+Let's remove the PPC64 code from qemuDomainGetMemLockLimitBytes()
+body and put it into a helper function. This will simplify the
+flow of qemuDomainGetMemLockLimitBytes() that handles all the other
+platforms and improves readability of the PPC64 specifics.
+
+Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com>
+Reviewed-by: Erik Skultety <eskultet@redhat.com>
+(cherry picked from commit 7a686fd2eae8d5674bb1213d8517dc5814fa6bf3)
+
+https: //bugzilla.redhat.com/show_bug.cgi?id=1505998
+Signed-off-by: Erik Skultety <eskultet@redhat.com>
+Message-Id: <ccdf9fefeb624585559606d00b6ac19b574733b3.1556884443.git.eskultet@redhat.com>
+Reviewed-by: Andrea Bolognani <abologna@redhat.com>
+---
+ src/qemu/qemu_domain.c | 171 ++++++++++++++++++++++-------------------
+ 1 file changed, 93 insertions(+), 78 deletions(-)
+
+diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
+index d936090d87..f91de0b743 100644
+--- a/src/qemu/qemu_domain.c
++++ b/src/qemu/qemu_domain.c
+@@ -9805,6 +9805,97 @@ qemuDomainUpdateCurrentMemorySize(virQEMUDriverPtr driver,
+ }
+ 
+ 
++/**
++ * getPPC64MemLockLimitBytes:
++ * @def: domain definition
++ *
++ * A PPC64 helper that calculates the memory locking limit in order for
++ * the guest to operate properly.
++ */
++static unsigned long long
++getPPC64MemLockLimitBytes(virDomainDefPtr def)
++{
++    unsigned long long memKB = 0;
++    unsigned long long baseLimit = 0;
++    unsigned long long memory = 0;
++    unsigned long long maxMemory = 0;
++    unsigned long long passthroughLimit = 0;
++    size_t i, nPCIHostBridges = 0;
++    bool usesVFIO = false;
++
++    for (i = 0; i < def->ncontrollers; i++) {
++        virDomainControllerDefPtr cont = def->controllers[i];
++
++        if (!virDomainControllerIsPSeriesPHB(cont))
++            continue;
++
++        nPCIHostBridges++;
++    }
++
++    for (i = 0; i < def->nhostdevs; i++) {
++        virDomainHostdevDefPtr dev = def->hostdevs[i];
++
++        if (dev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
++            dev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI &&
++            dev->source.subsys.u.pci.backend == VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO) {
++            usesVFIO = true;
++            break;
++        }
++    }
++
++    memory = virDomainDefGetMemoryTotal(def);
++
++    if (def->mem.max_memory)
++        maxMemory = def->mem.max_memory;
++    else
++        maxMemory = memory;
++
++    /* baseLimit := maxMemory / 128                                  (a)
++     *              + 4 MiB * #PHBs + 8 MiB                          (b)
++     *
++     * (a) is the hash table
++     *
++     * (b) is accounting for the 32-bit DMA window - it could be either the
++     * KVM accelerated TCE tables for emulated devices, or the VFIO
++     * userspace view. The 4 MiB per-PHB (including the default one) covers
++     * a 2GiB DMA window: default is 1GiB, but it's possible it'll be
++     * increased to help performance. The 8 MiB extra should be plenty for
++     * the TCE table index for any reasonable number of PHBs and several
++     * spapr-vlan or spapr-vscsi devices (512kB + a tiny bit each) */
++    baseLimit = maxMemory / 128 +
++                4096 * nPCIHostBridges +
++                8192;
++
++    /* passthroughLimit := max( 2 GiB * #PHBs,                       (c)
++     *                          memory                               (d)
++     *                          + memory * 1/512 * #PHBs + 8 MiB )   (e)
++     *
++     * (c) is the pre-DDW VFIO DMA window accounting. We're allowing 2 GiB
++     * rather than 1 GiB
++     *
++     * (d) is the with-DDW (and memory pre-registration and related
++     * features) DMA window accounting - assuming that we only account RAM
++     * once, even if mapped to multiple PHBs
++     *
++     * (e) is the with-DDW userspace view and overhead for the 64-bit DMA
++     * window. This is based a bit on expected guest behaviour, but there
++     * really isn't a way to completely avoid that. We assume the guest
++     * requests a 64-bit DMA window (per PHB) just big enough to map all
++     * its RAM. 4 kiB page size gives the 1/512; it will be less with 64
++     * kiB pages, less still if the guest is mapped with hugepages (unlike
++     * the default 32-bit DMA window, DDW windows can use large IOMMU
++     * pages). 8 MiB is for second and further level overheads, like (b) */
++    if (usesVFIO)
++        passthroughLimit = MAX(2 * 1024 * 1024 * nPCIHostBridges,
++                               memory +
++                               memory / 512 * nPCIHostBridges + 8192);
++
++    memKB = baseLimit + passthroughLimit;
++
++    return memKB << 10;
++}
++
++
+ /**
+  * qemuDomainGetMemLockLimitBytes:
+  * @def: domain definition
+@@ -9836,84 +9927,8 @@ qemuDomainGetMemLockLimitBytes(virDomainDefPtr def)
+     if (def->mem.locked)
+         return VIR_DOMAIN_MEMORY_PARAM_UNLIMITED;
+ 
+-    if (ARCH_IS_PPC64(def->os.arch) && def->virtType == VIR_DOMAIN_VIRT_KVM) {
+-        unsigned long long maxMemory;
+-        unsigned long long memory;
+-        unsigned long long baseLimit;
+-        unsigned long long passthroughLimit = 0;
+-        size_t nPCIHostBridges = 0;
+-        bool usesVFIO = false;
+-
+-        for (i = 0; i < def->ncontrollers; i++) {
+-            virDomainControllerDefPtr cont = def->controllers[i];
+-
+-            if (!virDomainControllerIsPSeriesPHB(cont))
+-                continue;
+-
+-            nPCIHostBridges++;
+-        }
+-
+-        for (i = 0; i < def->nhostdevs; i++) {
+-            virDomainHostdevDefPtr dev = def->hostdevs[i];
+-
+-            if (dev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
+-                dev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI &&
+-                dev->source.subsys.u.pci.backend == VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO) {
+-                usesVFIO = true;
+-                break;
+-            }
+-        }
+-
+-        memory = virDomainDefGetMemoryTotal(def);
+-
+-        if (def->mem.max_memory)
+-            maxMemory = def->mem.max_memory;
+-        else
+-            maxMemory = memory;
+-
+-        /* baseLimit := maxMemory / 128                                  (a)
+-         *              + 4 MiB * #PHBs + 8 MiB                          (b)
+-         *
+-         * (a) is the hash table
+-         *
+-         * (b) is accounting for the 32-bit DMA window - it could be either the
+-         * KVM accelerated TCE tables for emulated devices, or the VFIO
+-         * userspace view. The 4 MiB per-PHB (including the default one) covers
+-         * a 2GiB DMA window: default is 1GiB, but it's possible it'll be
+-         * increased to help performance. The 8 MiB extra should be plenty for
+-         * the TCE table index for any reasonable number of PHBs and several
+-         * spapr-vlan or spapr-vscsi devices (512kB + a tiny bit each) */
+-        baseLimit = maxMemory / 128 +
+-                    4096 * nPCIHostBridges +
+-                    8192;
+-
+-        /* passthroughLimit := max( 2 GiB * #PHBs,                       (c)
+-         *                          memory                               (d)
+-         *                          + memory * 1/512 * #PHBs + 8 MiB )   (e)
+-         *
+-         * (c) is the pre-DDW VFIO DMA window accounting. We're allowing 2 GiB
+-         * rather than 1 GiB
+-         *
+-         * (d) is the with-DDW (and memory pre-registration and related
+-         * features) DMA window accounting - assuming that we only account RAM
+-         * once, even if mapped to multiple PHBs
+-         *
+-         * (e) is the with-DDW userspace view and overhead for the 64-bit DMA
+-         * window. This is based a bit on expected guest behaviour, but there
+-         * really isn't a way to completely avoid that. We assume the guest
+-         * requests a 64-bit DMA window (per PHB) just big enough to map all
+-         * its RAM. 4 kiB page size gives the 1/512; it will be less with 64
+-         * kiB pages, less still if the guest is mapped with hugepages (unlike
+-         * the default 32-bit DMA window, DDW windows can use large IOMMU
+-         * pages). 8 MiB is for second and further level overheads, like (b) */
+-        if (usesVFIO)
+-            passthroughLimit = MAX(2 * 1024 * 1024 * nPCIHostBridges,
+-                                   memory +
+-                                   memory / 512 * nPCIHostBridges + 8192);
+-
+-        memKB = baseLimit + passthroughLimit;
+-        goto done;
+-    }
++    if (ARCH_IS_PPC64(def->os.arch) && def->virtType == VIR_DOMAIN_VIRT_KVM)
++        return getPPC64MemLockLimitBytes(def);
+ 
+     /* For device passthrough using VFIO the guest memory and MMIO memory
+      * regions need to be locked persistent in order to allow DMA.
+-- 
+2.21.0
+
diff --git a/SOURCES/libvirt-qemu_hotplug-Attach-guestfwd-using-netdev_add.patch b/SOURCES/libvirt-qemu_hotplug-Attach-guestfwd-using-netdev_add.patch
new file mode 100644
index 0000000..7d56c49
--- /dev/null
+++ b/SOURCES/libvirt-qemu_hotplug-Attach-guestfwd-using-netdev_add.patch
@@ -0,0 +1,65 @@
+From c120b5738e38dfa06bcd958d65c18308cab977b2 Mon Sep 17 00:00:00 2001
+Message-Id: <c120b5738e38dfa06bcd958d65c18308cab977b2@dist-git>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Thu, 27 Jun 2019 14:44:46 +0200
+Subject: [PATCH] qemu_hotplug: Attach guestfwd using netdev_add
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1624204
+
+The guestfwd channels are -netdevs really. Hotplug them as such.
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Reviewed-by: John Ferlan <jferlan@redhat.com>
+(cherry picked from commit 903315dc8ffeb2af651207f090a53526decabc92)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1624204
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Message-Id: <16a7ca67708755fe216f78295c56eae44275f5b1.1561639408.git.mprivozn@redhat.com>
+Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/qemu/qemu_hotplug.c | 20 +++++++++++++++-----
+ 1 file changed, 15 insertions(+), 5 deletions(-)
+
+diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
+index da9d56ffb1..468389fa7a 100644
+--- a/src/qemu/qemu_hotplug.c
++++ b/src/qemu/qemu_hotplug.c
+@@ -1864,10 +1864,14 @@ int qemuDomainAttachChrDevice(virQEMUDriverPtr driver,
+     char *tlsAlias = NULL;
+     const char *secAlias = NULL;
+     bool need_release = false;
++    bool guestfwd = false;
+ 
+-    if (chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL &&
+-        qemuDomainPrepareChannel(chr, priv->channelTargetDir) < 0)
+-        goto cleanup;
++    if (chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL) {
++        guestfwd = chr->targetType == VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_GUESTFWD;
++
++        if (qemuDomainPrepareChannel(chr, priv->channelTargetDir) < 0)
++            goto cleanup;
++    }
+ 
+     if (qemuAssignDeviceChrAlias(vmdef, chr, -1) < 0)
+         goto cleanup;
+@@ -1909,8 +1913,14 @@ int qemuDomainAttachChrDevice(virQEMUDriverPtr driver,
+         goto exit_monitor;
+     chardevAttached = true;
+ 
+-    if (qemuMonitorAddDevice(priv->mon, devstr) < 0)
+-        goto exit_monitor;
++    if (guestfwd) {
++        if (qemuMonitorAddNetdev(priv->mon, devstr,
++                                 NULL, NULL, 0, NULL, NULL, 0) < 0)
++            goto exit_monitor;
++    } else {
++        if (qemuMonitorAddDevice(priv->mon, devstr) < 0)
++            goto exit_monitor;
++    }
+ 
+     if (qemuDomainObjExitMonitor(driver, vm) < 0)
+         goto audit;
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-qemu_hotplug-Check-for-duplicate-drive-addresses.patch b/SOURCES/libvirt-qemu_hotplug-Check-for-duplicate-drive-addresses.patch
new file mode 100644
index 0000000..bc3d90e
--- /dev/null
+++ b/SOURCES/libvirt-qemu_hotplug-Check-for-duplicate-drive-addresses.patch
@@ -0,0 +1,43 @@
+From 6402d8133b33af901247afccdc78b332b453ff11 Mon Sep 17 00:00:00 2001
+Message-Id: <6402d8133b33af901247afccdc78b332b453ff11@dist-git>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Thu, 18 Apr 2019 19:36:33 +0200
+Subject: [PATCH] qemu_hotplug: Check for duplicate drive addresses
+
+RHEL-7.7: https://bugzilla.redhat.com/show_bug.cgi?id=1692296
+RHEL-8.1.0: https://bugzilla.redhat.com/show_bug.cgi?id=1692354
+
+This tries to fix the same problem as f1d65853000 but it's doing
+so in a less invasive way.
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Tested-by: Daniel Henrique Barboza <danielhb413@gmail.com>
+Reviewed-by: Jim Fehlig <jfehlig@suse.com>
+(cherry picked from commit ddc72f99027b063feaf34e5fda89916b6b2c8943)
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Message-Id: <a40b26d1696401699fae7aeea2714f8b51935766.1555608962.git.mprivozn@redhat.com>
+Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/qemu/qemu_hotplug.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
+index 397a2bdde2..776cd75474 100644
+--- a/src/qemu/qemu_hotplug.c
++++ b/src/qemu/qemu_hotplug.c
+@@ -612,6 +612,12 @@ qemuDomainAttachSCSIDisk(virQEMUDriverPtr driver,
+         return -1;
+     }
+ 
++    if (virDomainSCSIDriveAddressIsUsed(vm->def, &disk->info.addr.drive)) {
++        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
++                       _("Domain already contains a disk with that address"));
++        return -1;
++    }
++
+     /* Let's make sure the disk has a controller defined and loaded before
+      * trying to add it. The controller used by the disk must exist before a
+      * qemu command line string is generated.
+-- 
+2.21.0
+
diff --git a/SOURCES/libvirt-qemu_hotplug-Detach-guestfwd-using-netdev_del.patch b/SOURCES/libvirt-qemu_hotplug-Detach-guestfwd-using-netdev_del.patch
new file mode 100644
index 0000000..8930cf3
--- /dev/null
+++ b/SOURCES/libvirt-qemu_hotplug-Detach-guestfwd-using-netdev_del.patch
@@ -0,0 +1,137 @@
+From a86cb3601add390b718377be021128fc18e4c9b2 Mon Sep 17 00:00:00 2001
+Message-Id: <a86cb3601add390b718377be021128fc18e4c9b2@dist-git>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Thu, 27 Jun 2019 14:44:47 +0200
+Subject: [PATCH] qemu_hotplug: Detach guestfwd using netdev_del
+
+The guestfwd channels are -netdevs really. Hotunplug them as
+such. Also, DEVICE_DELETED event is not triggered (surprisingly,
+since we're not issuing device_del rather than netdev_del) and
+associated chardev is removed automagically too. This means that
+we need to do qemuDomainRemoveChrDevice() minus monitor call to
+remove the chardev.
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Reviewed-by: John Ferlan <jferlan@redhat.com>
+(cherry picked from commit 112f3a8d0f324c0705326957cca4508602b25eba)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1624204
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Message-Id: <de45d53975997bcdbb4260055664a7b0a0079bbe.1561639408.git.mprivozn@redhat.com>
+Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/qemu/qemu_hotplug.c | 48 ++++++++++++++++++++++++++++-------------
+ 1 file changed, 33 insertions(+), 15 deletions(-)
+
+diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
+index 468389fa7a..05489cf116 100644
+--- a/src/qemu/qemu_hotplug.c
++++ b/src/qemu/qemu_hotplug.c
+@@ -4355,25 +4355,28 @@ qemuDomainRemoveNetDevice(virQEMUDriverPtr driver,
+ static int
+ qemuDomainRemoveChrDevice(virQEMUDriverPtr driver,
+                           virDomainObjPtr vm,
+-                          virDomainChrDefPtr chr)
++                          virDomainChrDefPtr chr,
++                          bool monitor)
+ {
+     virObjectEventPtr event;
+     char *charAlias = NULL;
+     qemuDomainObjPrivatePtr priv = vm->privateData;
+     int ret = -1;
+-    int rc;
++    int rc = 0;
+ 
+     VIR_DEBUG("Removing character device %s from domain %p %s",
+               chr->info.alias, vm, vm->def->name);
+ 
+-    if (!(charAlias = qemuAliasChardevFromDevAlias(chr->info.alias)))
+-        goto cleanup;
++    if (monitor) {
++        if (!(charAlias = qemuAliasChardevFromDevAlias(chr->info.alias)))
++            goto cleanup;
+ 
+-    qemuDomainObjEnterMonitor(driver, vm);
+-    rc = qemuMonitorDetachCharDev(priv->mon, charAlias);
++        qemuDomainObjEnterMonitor(driver, vm);
++        rc = qemuMonitorDetachCharDev(priv->mon, charAlias);
+ 
+-    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+-        goto cleanup;
++        if (qemuDomainObjExitMonitor(driver, vm) < 0)
++            goto cleanup;
++    }
+ 
+     if (rc == 0 &&
+         qemuDomainDelChardevTLSObjects(driver, vm, chr->source, charAlias) < 0)
+@@ -4674,7 +4677,7 @@ qemuDomainRemoveDevice(virQEMUDriverPtr driver,
+         break;
+ 
+     case VIR_DOMAIN_DEVICE_CHR:
+-        ret = qemuDomainRemoveChrDevice(driver, vm, dev->data.chr);
++        ret = qemuDomainRemoveChrDevice(driver, vm, dev->data.chr, true);
+         break;
+     case VIR_DOMAIN_DEVICE_RNG:
+         ret = qemuDomainRemoveRNGDevice(driver, vm, dev->data.rng);
+@@ -5749,6 +5752,7 @@ int qemuDomainDetachChrDevice(virQEMUDriverPtr driver,
+     virDomainDefPtr vmdef = vm->def;
+     virDomainChrDefPtr tmpChr;
+     char *devstr = NULL;
++    bool guestfwd = false;
+ 
+     if (!(tmpChr = virDomainChrFind(vmdef, chr))) {
+         virReportError(VIR_ERR_DEVICE_MISSING,
+@@ -5758,6 +5762,11 @@ int qemuDomainDetachChrDevice(virQEMUDriverPtr driver,
+         goto cleanup;
+     }
+ 
++    /* guestfwd channels are not really -device rather than
++     * -netdev. We need to treat them slightly differently. */
++    guestfwd = tmpChr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL &&
++               tmpChr->targetType == VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_GUESTFWD;
++
+     if (!tmpChr->info.alias && qemuAssignDeviceChrAlias(vmdef, tmpChr, -1) < 0)
+         goto cleanup;
+ 
+@@ -5766,22 +5775,31 @@ int qemuDomainDetachChrDevice(virQEMUDriverPtr driver,
+     if (qemuBuildChrDeviceStr(&devstr, vmdef, tmpChr, priv->qemuCaps) < 0)
+         goto cleanup;
+ 
+-    if (!async)
++    if (!async && !guestfwd)
+         qemuDomainMarkDeviceForRemoval(vm, &tmpChr->info);
+ 
+     qemuDomainObjEnterMonitor(driver, vm);
+-    if (devstr && qemuMonitorDelDevice(priv->mon, tmpChr->info.alias) < 0) {
+-        ignore_value(qemuDomainObjExitMonitor(driver, vm));
+-        goto cleanup;
++    if (guestfwd) {
++        if (qemuMonitorRemoveNetdev(priv->mon, tmpChr->info.alias) < 0) {
++            ignore_value(qemuDomainObjExitMonitor(driver, vm));
++            goto cleanup;
++        }
++    } else {
++        if (devstr && qemuMonitorDelDevice(priv->mon, tmpChr->info.alias) < 0) {
++            ignore_value(qemuDomainObjExitMonitor(driver, vm));
++            goto cleanup;
++        }
+     }
+     if (qemuDomainObjExitMonitor(driver, vm) < 0)
+         goto cleanup;
+ 
+-    if (async) {
++    if (guestfwd) {
++        ret = qemuDomainRemoveChrDevice(driver, vm, tmpChr, false);
++    } else if (async) {
+         ret = 0;
+     } else {
+         if ((ret = qemuDomainWaitForDeviceRemoval(vm)) == 1)
+-            ret = qemuDomainRemoveChrDevice(driver, vm, tmpChr);
++            ret = qemuDomainRemoveChrDevice(driver, vm, tmpChr, true);
+     }
+ 
+  cleanup:
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-qemu_hotplug-remove-another-erroneous-qemuDomainDetachExtensionDevice-call.patch b/SOURCES/libvirt-qemu_hotplug-remove-another-erroneous-qemuDomainDetachExtensionDevice-call.patch
new file mode 100644
index 0000000..9b5bd21
--- /dev/null
+++ b/SOURCES/libvirt-qemu_hotplug-remove-another-erroneous-qemuDomainDetachExtensionDevice-call.patch
@@ -0,0 +1,52 @@
+From 0ca4828af101259cf2cbe30004c68f2081394f91 Mon Sep 17 00:00:00 2001
+Message-Id: <0ca4828af101259cf2cbe30004c68f2081394f91@dist-git>
+From: Laine Stump <laine@laine.org>
+Date: Mon, 8 Apr 2019 10:57:32 +0200
+Subject: [PATCH] qemu_hotplug: remove another erroneous
+ qemuDomainDetachExtensionDevice() call
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+qemuDomainRemoveRNGDevice() calls qemuDomainDetachExtensionDevice().
+According to commit 1d1e264f1 that added this code, it should not be
+necessary to explicitly remove the zPCI extension device for a PCI
+device during unplug, because "QEMU implements an unplug callback
+which will unplug both PCI and zPCI device in a cascaded way". In
+fact, no other devices call qemuDomainDetachExtensionDevice() during
+their qemuDomainRemove*Device() function, so it should be removed from
+qemuDomainRemoveRNGDevice as well.
+
+Signed-off-by: Laine Stump <laine@laine.org>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Reviewed-by: Boris Fiuczynski <fiuczy@linux.ibm.com>
+
+(cherry picked from commit e18e9b72a99f93cd4b14f39c60baa7c5ea35e5db)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1508149
+
+Signed-off-by: Andrea Bolognani <abologna@redhat.com>
+Message-Id: <20190408085732.28684-16-abologna@redhat.com>
+Reviewed-by: Laine Stump <laine@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/qemu/qemu_hotplug.c | 3 ---
+ 1 file changed, 3 deletions(-)
+
+diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
+index f16213c6e0..410cdca3c5 100644
+--- a/src/qemu/qemu_hotplug.c
++++ b/src/qemu/qemu_hotplug.c
+@@ -4422,9 +4422,6 @@ qemuDomainRemoveRNGDevice(virQEMUDriverPtr driver,
+ 
+     qemuDomainObjEnterMonitor(driver, vm);
+ 
+-    if (qemuDomainDetachExtensionDevice(priv->mon, &rng->info) < 0)
+-        rc = -1;
+-
+     if (rc == 0 &&
+         qemuMonitorDelObject(priv->mon, objAlias) < 0)
+         rc = -1;
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-qemu_hotplug-remove-erroneous-call-to-qemuDomainDetachExtensionDevice.patch b/SOURCES/libvirt-qemu_hotplug-remove-erroneous-call-to-qemuDomainDetachExtensionDevice.patch
new file mode 100644
index 0000000..b026299
--- /dev/null
+++ b/SOURCES/libvirt-qemu_hotplug-remove-erroneous-call-to-qemuDomainDetachExtensionDevice.patch
@@ -0,0 +1,99 @@
+From 77404a4f0ff85fbc0a2c24afc736ffbd8b82ef4d Mon Sep 17 00:00:00 2001
+Message-Id: <77404a4f0ff85fbc0a2c24afc736ffbd8b82ef4d@dist-git>
+From: Laine Stump <laine@laine.org>
+Date: Mon, 8 Apr 2019 10:57:31 +0200
+Subject: [PATCH] qemu_hotplug: remove erroneous call to
+ qemuDomainDetachExtensionDevice()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+qemuDomainDetachControllerDevice() calls
+qemuDomainDetachExtensionDevice() when the controller type is
+PCI. This is incorrect in multiple ways:
+
+* Any code that tears down a device should be in the
+  qemuDomainRemove*Device() function (which is called after libvirt
+  gets a DEVICE_DELETED event from qemu indicating that the guest is
+  finished with the device on its end. The qemuDomainDetach*Device()
+  functions should only contain code that ensures the requested
+  operation is valid, and sends the command to qemu to initiate the
+  unplug.
+
+* qemuDomainDetachExtensionDevice() is a function that applies to
+  devices that plug into a PCI slot, *not* necessarily PCI controllers
+  (which is what's being checked in the offending code). The proper
+  way to check for this would be to see if the DeviceInfo for the
+  controller device had a PCI address, not to check if the controller
+  is a PCI controller (the code being removed was doing the latter).
+
+* According to commit 1d1e264f1 that added this code (and other
+  support for hotplugging zPCI devices on s390), it's not necessary to
+  explicitly detach the zPCI device when unplugging a PCI device. To
+  quote:
+
+       There's no need to implement hot unplug for zPCI as QEMU
+       implements an unplug callback which will unplug both PCI and
+       zPCI device in a cascaded way.
+
+  and the evidence bears this out - all the other uses of
+  qemuDomainDetachExtensionDevice() (except one, which I believe is
+  also in error, and is being removed in a separate patch) are only to
+  remove the zPCI extension device in cases where it was successfully
+  added, but there was some other failure later in the hotplug process
+  (so there was no regular PCI device to remove and trigger removal of
+  the zPCI extension device).
+
+* PCI controllers are not hot pluggable, so this is dead code
+  anyway. (The only controllers that can currently be
+  hotplugged/unplugged are SCSI controllers).
+
+Signed-off-by: Laine Stump <laine@laine.org>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Reviewed-by: Boris Fiuczynski <fiuczy@linux.ibm.com>
+
+(cherry picked from commit 143291698358f5a1e693c768893d89038420af25)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1508149
+
+Conflicts:
+
+  * src/qemu/qemu_hotplug.c
+    + the code dealing with entering and exiting the monitor is
+      quite a bit different because we don't have backported
+      qemuDomainDeleteDevice() downstream
+      - missing 4cd13478ac33
+
+Signed-off-by: Andrea Bolognani <abologna@redhat.com>
+Message-Id: <20190408085732.28684-15-abologna@redhat.com>
+Reviewed-by: Laine Stump <laine@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/qemu/qemu_hotplug.c | 6 ------
+ 1 file changed, 6 deletions(-)
+
+diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
+index 8394efa739..f16213c6e0 100644
+--- a/src/qemu/qemu_hotplug.c
++++ b/src/qemu/qemu_hotplug.c
+@@ -5077,17 +5077,11 @@ int qemuDomainDetachControllerDevice(virQEMUDriverPtr driver,
+         qemuDomainMarkDeviceForRemoval(vm, &detach->info);
+ 
+     qemuDomainObjEnterMonitor(driver, vm);
+-    if (detach->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI &&
+-        qemuDomainDetachExtensionDevice(priv->mon, &detach->info)) {
+-        goto exit_monitor;
+-    }
+-
+     if (qemuMonitorDelDevice(priv->mon, detach->info.alias)) {
+         ignore_value(qemuDomainObjExitMonitor(driver, vm));
+         goto cleanup;
+     }
+ 
+- exit_monitor:
+     if (qemuDomainObjExitMonitor(driver, vm) < 0)
+         goto cleanup;
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-qemu_process-Prefer-generic-qemuMonitorGetGuestCPU.patch b/SOURCES/libvirt-qemu_process-Prefer-generic-qemuMonitorGetGuestCPU.patch
new file mode 100644
index 0000000..881c87c
--- /dev/null
+++ b/SOURCES/libvirt-qemu_process-Prefer-generic-qemuMonitorGetGuestCPU.patch
@@ -0,0 +1,81 @@
+From 894b1e28647f0fd46da3ffc64afc358d438153f9 Mon Sep 17 00:00:00 2001
+Message-Id: <894b1e28647f0fd46da3ffc64afc358d438153f9@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:26:04 +0200
+Subject: [PATCH] qemu_process: Prefer generic qemuMonitorGetGuestCPU
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+When updating guest CPU definition according to the vCPU actually
+created by QEMU, we want to use the generic qemuMonitorGetGuestCPU to
+get both CPUID and MSR features.
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit 63acb7bfd56f117309e4fcaf438639d4d7bc7dcb)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1697627
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <711a363fde6df79fe9a26b6b4cb0a185cc5ad3cb.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/qemu/qemu_process.c | 24 ++++++++++++++++++++++--
+ 1 file changed, 22 insertions(+), 2 deletions(-)
+
+diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
+index 59a739f262..d147e524ee 100644
+--- a/src/qemu/qemu_process.c
++++ b/src/qemu/qemu_process.c
+@@ -4013,6 +4013,16 @@ qemuProcessVerifyCPUFeatures(virDomainDefPtr def,
+ }
+ 
+ 
++static const char *
++qemuProcessTranslateCPUFeatures(const char *name,
++                                void *opaque)
++{
++    virQEMUCapsPtr qemuCaps = opaque;
++
++    return virQEMUCapsCPUFeatureFromQEMU(qemuCaps, name);
++}
++
++
+ static int
+ qemuProcessFetchGuestCPU(virQEMUDriverPtr driver,
+                          virDomainObjPtr vm,
+@@ -4023,18 +4033,28 @@ qemuProcessFetchGuestCPU(virQEMUDriverPtr driver,
+     qemuDomainObjPrivatePtr priv = vm->privateData;
+     virCPUDataPtr dataEnabled = NULL;
+     virCPUDataPtr dataDisabled = NULL;
++    bool generic;
+     int rc;
+ 
+     *enabled = NULL;
+     *disabled = NULL;
+ 
+-    if (!ARCH_IS_X86(vm->def->os.arch))
++    generic = virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_CPU_UNAVAILABLE_FEATURES);
++
++    if (!generic && !ARCH_IS_X86(vm->def->os.arch))
+         return 0;
+ 
+     if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
+         goto error;
+ 
+-    rc = qemuMonitorGetGuestCPUx86(priv->mon, &dataEnabled, &dataDisabled);
++    if (generic) {
++        rc = qemuMonitorGetGuestCPU(priv->mon,
++                                    vm->def->os.arch,
++                                    qemuProcessTranslateCPUFeatures, priv->qemuCaps,
++                                    &dataEnabled, &dataDisabled);
++    } else {
++        rc = qemuMonitorGetGuestCPUx86(priv->mon, &dataEnabled, &dataDisabled);
++    }
+ 
+     if (qemuDomainObjExitMonitor(driver, vm) < 0)
+         goto error;
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-qemu_security-Fully-implement-qemuSecurityDomainSetPathLabel.patch b/SOURCES/libvirt-qemu_security-Fully-implement-qemuSecurityDomainSetPathLabel.patch
new file mode 100644
index 0000000..49f1358
--- /dev/null
+++ b/SOURCES/libvirt-qemu_security-Fully-implement-qemuSecurityDomainSetPathLabel.patch
@@ -0,0 +1,166 @@
+From 86f741bf77f39d4af3698b71797e430c2a6989c3 Mon Sep 17 00:00:00 2001
+Message-Id: <86f741bf77f39d4af3698b71797e430c2a6989c3@dist-git>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Thu, 3 Jan 2019 10:03:44 +0100
+Subject: [PATCH] qemu_security: Fully implement qemuSecurityDomainSetPathLabel
+
+Even though the current use of the function does not require full
+implementation with transactions (none of the callers pass a path
+somewhere under /dev), it doesn't hurt either. Moreover, in
+future patches the paradigm is going to shift so that any API
+that touches a file is required to use transactions.
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Reviewed-by: John Ferlan <jferlan@redhat.com>
+(cherry picked from commit da24db2d30352c094f76dffb523e7f344ff8e30d)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1658112
+
+Signed-off-by: Erik Skultety <eskultet@redhat.com>
+Message-Id: <4de2beabd9868259f1856f7eafcc835b5b2a3d6b.1546506016.git.eskultet@redhat.com>
+Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/qemu/qemu_domain.c   |  3 +--
+ src/qemu/qemu_process.c  | 15 ++++++---------
+ src/qemu/qemu_security.c | 30 ++++++++++++++++++++++++++++++
+ src/qemu/qemu_security.h |  6 +++++-
+ 4 files changed, 42 insertions(+), 12 deletions(-)
+
+diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
+index 95b84af78a..c9899b9e6d 100644
+--- a/src/qemu/qemu_domain.c
++++ b/src/qemu/qemu_domain.c
+@@ -801,8 +801,7 @@ qemuDomainWriteMasterKeyFile(virQEMUDriverPtr driver,
+         goto cleanup;
+     }
+ 
+-    if (qemuSecurityDomainSetPathLabel(driver->securityManager,
+-                                       vm->def, path, false) < 0)
++    if (qemuSecurityDomainSetPathLabel(driver, vm, path, false) < 0)
+         goto cleanup;
+ 
+     ret = 0;
+diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
+index 34aac69afc..c0f95dd5f1 100644
+--- a/src/qemu/qemu_process.c
++++ b/src/qemu/qemu_process.c
+@@ -2778,8 +2778,7 @@ qemuProcessStartManagedPRDaemon(virDomainObjPtr vm)
+         virCgroupAddMachineTask(priv->cgroup, cpid) < 0)
+         goto cleanup;
+ 
+-    if (qemuSecurityDomainSetPathLabel(driver->securityManager,
+-                                       vm->def, socketPath, true) < 0)
++    if (qemuSecurityDomainSetPathLabel(driver, vm, socketPath, true) < 0)
+         goto cleanup;
+ 
+     priv->prDaemonRunning = true;
+@@ -3656,7 +3655,7 @@ qemuProcessNeedMemoryBackingPath(virDomainDefPtr def,
+ 
+ static int
+ qemuProcessBuildDestroyMemoryPathsImpl(virQEMUDriverPtr driver,
+-                                       virDomainDefPtr def,
++                                       virDomainObjPtr vm,
+                                        const char *path,
+                                        bool build)
+ {
+@@ -3671,8 +3670,7 @@ qemuProcessBuildDestroyMemoryPathsImpl(virQEMUDriverPtr driver,
+             return -1;
+         }
+ 
+-        if (qemuSecurityDomainSetPathLabel(driver->securityManager,
+-                                           def, path, true) < 0)
++        if (qemuSecurityDomainSetPathLabel(driver, vm, path, true) < 0)
+             return -1;
+     } else {
+         if (virFileDeleteTree(path) < 0)
+@@ -3708,7 +3706,7 @@ qemuProcessBuildDestroyMemoryPaths(virQEMUDriverPtr driver,
+             if (!path)
+                 goto cleanup;
+ 
+-            if (qemuProcessBuildDestroyMemoryPathsImpl(driver, vm->def,
++            if (qemuProcessBuildDestroyMemoryPathsImpl(driver, vm,
+                                                        path, build) < 0)
+                 goto cleanup;
+ 
+@@ -3720,7 +3718,7 @@ qemuProcessBuildDestroyMemoryPaths(virQEMUDriverPtr driver,
+         if (qemuGetMemoryBackingDomainPath(vm->def, cfg, &path) < 0)
+             goto cleanup;
+ 
+-        if (qemuProcessBuildDestroyMemoryPathsImpl(driver, vm->def,
++        if (qemuProcessBuildDestroyMemoryPathsImpl(driver, vm,
+                                                    path, build) < 0)
+             goto cleanup;
+ 
+@@ -4904,8 +4902,7 @@ qemuProcessMakeDir(virQEMUDriverPtr driver,
+         goto cleanup;
+     }
+ 
+-    if (qemuSecurityDomainSetPathLabel(driver->securityManager,
+-                                       vm->def, path, true) < 0)
++    if (qemuSecurityDomainSetPathLabel(driver, vm, path, true) < 0)
+         goto cleanup;
+ 
+     ret = 0;
+diff --git a/src/qemu/qemu_security.c b/src/qemu/qemu_security.c
+index af3be42854..268def309a 100644
+--- a/src/qemu/qemu_security.c
++++ b/src/qemu/qemu_security.c
+@@ -493,3 +493,33 @@ qemuSecurityCleanupTPMEmulator(virQEMUDriverPtr driver,
+ {
+     virSecurityManagerRestoreTPMLabels(driver->securityManager, def);
+ }
++
++
++int
++qemuSecurityDomainSetPathLabel(virQEMUDriverPtr driver,
++                               virDomainObjPtr vm,
++                               const char *path,
++                               bool allowSubtree)
++{
++    int ret = -1;
++
++    if (qemuDomainNamespaceEnabled(vm, QEMU_DOMAIN_NS_MOUNT) &&
++        virSecurityManagerTransactionStart(driver->securityManager) < 0)
++        goto cleanup;
++
++    if (virSecurityManagerDomainSetPathLabel(driver->securityManager,
++                                             vm->def,
++                                             path,
++                                             allowSubtree) < 0)
++        goto cleanup;
++
++    if (qemuDomainNamespaceEnabled(vm, QEMU_DOMAIN_NS_MOUNT) &&
++        virSecurityManagerTransactionCommit(driver->securityManager,
++                                            vm->pid) < 0)
++        goto cleanup;
++
++    ret = 0;
++ cleanup:
++    virSecurityManagerTransactionAbort(driver->securityManager);
++    return ret;
++}
+diff --git a/src/qemu/qemu_security.h b/src/qemu/qemu_security.h
+index a189b63828..fd11fbdd9d 100644
+--- a/src/qemu/qemu_security.h
++++ b/src/qemu/qemu_security.h
+@@ -95,12 +95,16 @@ int qemuSecurityStartTPMEmulator(virQEMUDriverPtr driver,
+ void qemuSecurityCleanupTPMEmulator(virQEMUDriverPtr driver,
+                                     virDomainDefPtr def);
+ 
++int qemuSecurityDomainSetPathLabel(virQEMUDriverPtr driver,
++                                   virDomainObjPtr vm,
++                                   const char *path,
++                                   bool allowSubtree);
++
+ /* Please note that for these APIs there is no wrapper yet. Do NOT blindly add
+  * new APIs here. If an API can touch a /dev file add a proper wrapper instead.
+  */
+ # define qemuSecurityCheckAllLabel virSecurityManagerCheckAllLabel
+ # define qemuSecurityClearSocketLabel virSecurityManagerClearSocketLabel
+-# define qemuSecurityDomainSetPathLabel virSecurityManagerDomainSetPathLabel
+ # define qemuSecurityGenLabel virSecurityManagerGenLabel
+ # define qemuSecurityGetBaseLabel virSecurityManagerGetBaseLabel
+ # define qemuSecurityGetDOI virSecurityManagerGetDOI
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-qemuhotplugtest-Don-t-plug-a-SCSI-disk-at-unit-7.patch b/SOURCES/libvirt-qemuhotplugtest-Don-t-plug-a-SCSI-disk-at-unit-7.patch
new file mode 100644
index 0000000..ec69f83
--- /dev/null
+++ b/SOURCES/libvirt-qemuhotplugtest-Don-t-plug-a-SCSI-disk-at-unit-7.patch
@@ -0,0 +1,71 @@
+From 310eeaa9bedbbe58a6cdbdbc2e057fc6d6c66586 Mon Sep 17 00:00:00 2001
+Message-Id: <310eeaa9bedbbe58a6cdbdbc2e057fc6d6c66586@dist-git>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Thu, 18 Apr 2019 19:36:32 +0200
+Subject: [PATCH] qemuhotplugtest: Don't plug a SCSI disk at unit 7
+
+RHEL-7.7: https://bugzilla.redhat.com/show_bug.cgi?id=1692296
+RHEL-8.1.0: https://bugzilla.redhat.com/show_bug.cgi?id=1692354
+
+Unit number 7 is kind of special. It's reserved for SCSI
+controller. The comment in virDomainSCSIDriveAddressIsUsed()
+summarizes that pretty nicely. Libvirt would never generate
+such address.
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Tested-by: Daniel Henrique Barboza <danielhb413@gmail.com>
+Reviewed-by: Jim Fehlig <jfehlig@suse.com>
+(cherry picked from commit ee2c5ef39fd91345893904433c6f458685543af5)
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Message-Id: <cd6f1b6289c9a00a4094540bb3656446b8d4cc1e.1555608962.git.mprivozn@redhat.com>
+Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ tests/qemuhotplugtest.c                                       | 2 +-
+ tests/qemuhotplugtestdevices/qemuhotplug-disk-scsi-2.xml      | 2 +-
+ ...uhotplug-base-without-scsi-controller-live+disk-scsi-2.xml | 4 ++--
+ 3 files changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/tests/qemuhotplugtest.c b/tests/qemuhotplugtest.c
+index 663e33ed00..8e0086a269 100644
+--- a/tests/qemuhotplugtest.c
++++ b/tests/qemuhotplugtest.c
+@@ -761,7 +761,7 @@ mymain(void)
+                    "device_del", QMP_OK,
+                    "human-monitor-command", HMP(""));
+     DO_TEST_DETACH("base-with-scsi-controller-live", "disk-scsi-2", false, false,
+-                   "device_del", QMP_DEVICE_DELETED("scsi3-0-5-7") QMP_OK,
++                   "device_del", QMP_DEVICE_DELETED("scsi3-0-5-6") QMP_OK,
+                    "human-monitor-command", HMP(""));
+ 
+     DO_TEST_ATTACH("base-live", "qemu-agent", false, true,
+diff --git a/tests/qemuhotplugtestdevices/qemuhotplug-disk-scsi-2.xml b/tests/qemuhotplugtestdevices/qemuhotplug-disk-scsi-2.xml
+index 3a847fbda6..876afb182f 100644
+--- a/tests/qemuhotplugtestdevices/qemuhotplug-disk-scsi-2.xml
++++ b/tests/qemuhotplugtestdevices/qemuhotplug-disk-scsi-2.xml
+@@ -2,7 +2,7 @@
+   <driver name='qemu' type='raw' cache='none'/>
+   <source file='/dev/null'/>
+   <target dev='sdf' bus='scsi'/>
+-  <address type='drive' controller='3' bus='0' target='5' unit='7'/>
++  <address type='drive' controller='3' bus='0' target='5' unit='6'/>
+   <readonly/>
+   <shareable/>
+ </disk>
+diff --git a/tests/qemuhotplugtestdomains/qemuhotplug-base-without-scsi-controller-live+disk-scsi-2.xml b/tests/qemuhotplugtestdomains/qemuhotplug-base-without-scsi-controller-live+disk-scsi-2.xml
+index d35fea6f5f..72b5174825 100644
+--- a/tests/qemuhotplugtestdomains/qemuhotplug-base-without-scsi-controller-live+disk-scsi-2.xml
++++ b/tests/qemuhotplugtestdomains/qemuhotplug-base-without-scsi-controller-live+disk-scsi-2.xml
+@@ -26,8 +26,8 @@
+       <target dev='sdf' bus='scsi'/>
+       <readonly/>
+       <shareable/>
+-      <alias name='scsi3-0-5-7'/>
+-      <address type='drive' controller='3' bus='0' target='5' unit='7'/>
++      <alias name='scsi3-0-5-6'/>
++      <address type='drive' controller='3' bus='0' target='5' unit='6'/>
+     </disk>
+     <controller type='usb' index='0'>
+       <alias name='usb'/>
+-- 
+2.21.0
+
diff --git a/SOURCES/libvirt-qemuhotplugtest-Test-guestfwd-attach-and-detach.patch b/SOURCES/libvirt-qemuhotplugtest-Test-guestfwd-attach-and-detach.patch
new file mode 100644
index 0000000..291a266
--- /dev/null
+++ b/SOURCES/libvirt-qemuhotplugtest-Test-guestfwd-attach-and-detach.patch
@@ -0,0 +1,117 @@
+From 37dbf9fd0da8345ad03948543b9ae64954d219e1 Mon Sep 17 00:00:00 2001
+Message-Id: <37dbf9fd0da8345ad03948543b9ae64954d219e1@dist-git>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Thu, 27 Jun 2019 14:44:48 +0200
+Subject: [PATCH] qemuhotplugtest: Test guestfwd attach and detach
+
+Previous two commits demonstrate a hole in our test scenario.
+Fix that.
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Reviewed-by: John Ferlan <jferlan@redhat.com>
+(cherry picked from commit 17ddfd420a0dbcdd3f76fbecf7428acb301db188)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1624204
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Message-Id: <08fcf2bbdefa193065ecb3c28f8d5a5a61cfeb69.1561639408.git.mprivozn@redhat.com>
+Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ tests/qemuhotplugtest.c                       |  6 ++
+ .../qemuhotplug-guestfwd.xml                  |  4 ++
+ .../qemuhotplug-base-live+guestfwd.xml        | 55 +++++++++++++++++++
+ 3 files changed, 65 insertions(+)
+ create mode 100644 tests/qemuhotplugtestdevices/qemuhotplug-guestfwd.xml
+ create mode 100644 tests/qemuhotplugtestdomains/qemuhotplug-base-live+guestfwd.xml
+
+diff --git a/tests/qemuhotplugtest.c b/tests/qemuhotplugtest.c
+index 8e0086a269..aaa3492d4c 100644
+--- a/tests/qemuhotplugtest.c
++++ b/tests/qemuhotplugtest.c
+@@ -836,6 +836,12 @@ mymain(void)
+     DO_TEST_DETACH("base-live", "watchdog-user-alias-full", false, false,
+                    "device_del", QMP_OK);
+ 
++    DO_TEST_ATTACH("base-live", "guestfwd", false, true,
++                   "chardev-add", QMP_OK,
++                   "netdev_add", QMP_OK);
++    DO_TEST_DETACH("base-live", "guestfwd", false, false,
++                   "netdev_del", QMP_OK);
++
+ #define DO_TEST_CPU_GROUP(prefix, vcpus, modernhp, expectfail) \
+     do { \
+         cpudata.test = prefix; \
+diff --git a/tests/qemuhotplugtestdevices/qemuhotplug-guestfwd.xml b/tests/qemuhotplugtestdevices/qemuhotplug-guestfwd.xml
+new file mode 100644
+index 0000000000..c67dbdb8df
+--- /dev/null
++++ b/tests/qemuhotplugtestdevices/qemuhotplug-guestfwd.xml
+@@ -0,0 +1,4 @@
++<channel type='unix'>
++  <source mode='bind' path='/tmp/guestfwd'/>
++  <target type='guestfwd' address='10.0.2.1' port='4600'/>
++</channel>
+diff --git a/tests/qemuhotplugtestdomains/qemuhotplug-base-live+guestfwd.xml b/tests/qemuhotplugtestdomains/qemuhotplug-base-live+guestfwd.xml
+new file mode 100644
+index 0000000000..8d7294123b
+--- /dev/null
++++ b/tests/qemuhotplugtestdomains/qemuhotplug-base-live+guestfwd.xml
+@@ -0,0 +1,55 @@
++<domain type='kvm' id='7'>
++  <name>hotplug</name>
++  <uuid>d091ea82-29e6-2e34-3005-f02617b36e87</uuid>
++  <memory unit='KiB'>4194304</memory>
++  <currentMemory unit='KiB'>4194304</currentMemory>
++  <vcpu placement='static'>4</vcpu>
++  <os>
++    <type arch='x86_64' machine='pc'>hvm</type>
++    <boot dev='hd'/>
++  </os>
++  <features>
++    <acpi/>
++    <apic/>
++    <pae/>
++  </features>
++  <clock offset='utc'/>
++  <on_poweroff>destroy</on_poweroff>
++  <on_reboot>restart</on_reboot>
++  <on_crash>restart</on_crash>
++  <devices>
++    <emulator>/usr/bin/qemu-system-x86_64</emulator>
++    <controller type='usb' index='0'>
++      <alias name='usb'/>
++      <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/>
++    </controller>
++    <controller type='ide' index='0'>
++      <alias name='ide'/>
++      <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
++    </controller>
++    <controller type='scsi' index='0' model='virtio-scsi'>
++      <alias name='scsi0'/>
++      <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
++    </controller>
++    <controller type='pci' index='0' model='pci-root'>
++      <alias name='pci'/>
++    </controller>
++    <controller type='virtio-serial' index='0'>
++      <alias name='virtio-serial0'/>
++      <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
++    </controller>
++    <channel type='unix'>
++      <source mode='bind' path='/tmp/guestfwd'/>
++      <target type='guestfwd' address='10.0.2.1' port='4600'/>
++      <alias name='channel0'/>
++    </channel>
++    <input type='mouse' bus='ps2'>
++      <alias name='input0'/>
++    </input>
++    <input type='keyboard' bus='ps2'>
++      <alias name='input1'/>
++    </input>
++    <memballoon model='none'/>
++  </devices>
++  <seclabel type='none' model='none'/>
++</domain>
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-qemuxml2argvtest-Add-test-for-CPU-features-translation.patch b/SOURCES/libvirt-qemuxml2argvtest-Add-test-for-CPU-features-translation.patch
new file mode 100644
index 0000000..de15331
--- /dev/null
+++ b/SOURCES/libvirt-qemuxml2argvtest-Add-test-for-CPU-features-translation.patch
@@ -0,0 +1,134 @@
+From 3ddc4c63f770fa6e2b2e37915c3f70598aa59d97 Mon Sep 17 00:00:00 2001
+Message-Id: <3ddc4c63f770fa6e2b2e37915c3f70598aa59d97@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:25:50 +0200
+Subject: [PATCH] qemuxml2argvtest: Add test for CPU features translation
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This should cover all CPU features for which QEMU prefers spelling that
+differs from the one used by libvirt.
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit 24aa210d90770a6ea2313ebf2047c0a802932dca)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1697627
+
+Conflicts:
+	tests/qemuxml2argvdata/cpu-translation.x86_64-latest.args
+            - old command line
+            - downstream patch to add rtm=on and hle=on for Haswell
+
+	tests/qemuxml2argvdata/cpu-translation.x86_64-4.0.0.args
+            - dropped as there are no 4.0.0 capabilities downstream
+
+	tests/qemuxml2argvtest.c
+            - dropped cpu-translation test with QEMU 4.0.0
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <6ce0d74bdf9a66c0908fd8162902b1f75870189b.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ .../cpu-translation.x86_64-latest.args        | 33 ++++++++++++++++++
+ tests/qemuxml2argvdata/cpu-translation.xml    | 34 +++++++++++++++++++
+ tests/qemuxml2argvtest.c                      |  1 +
+ 3 files changed, 68 insertions(+)
+ create mode 100644 tests/qemuxml2argvdata/cpu-translation.x86_64-latest.args
+ create mode 100644 tests/qemuxml2argvdata/cpu-translation.xml
+
+diff --git a/tests/qemuxml2argvdata/cpu-translation.x86_64-latest.args b/tests/qemuxml2argvdata/cpu-translation.x86_64-latest.args
+new file mode 100644
+index 0000000000..898b987086
+--- /dev/null
++++ b/tests/qemuxml2argvdata/cpu-translation.x86_64-latest.args
+@@ -0,0 +1,33 @@
++LC_ALL=C \
++PATH=/bin \
++HOME=/home/test \
++USER=test \
++LOGNAME=test \
++QEMU_AUDIO_DRV=none \
++/usr/bin/qemu-system-x86_64 \
++-name guest=QEMUGuest1,debug-threads=on \
++-S \
++-object secret,id=masterKey0,format=raw,\
++file=/tmp/lib/domain--1-QEMUGuest1/master-key.aes \
++-machine pc,accel=tcg,usb=off,dump-guest-core=off \
++-cpu Haswell,pclmuldq=on,ds_cpl=on,tsc_adjust=on,fxsr_opt=on,lahf_lm=on,\
++cmp_legacy=on,nodeid_msr=on,perfctr_core=on,perfctr_nb=on,rtm=on,hle=on,\
++kvm_pv_eoi=on,kvm_pv_unhalt=on \
++-m 214 \
++-realtime mlock=off \
++-smp 1,sockets=1,cores=1,threads=1 \
++-uuid c7a5fdbd-fade-9455-926a-d65c16db1809 \
++-display none \
++-no-user-config \
++-nodefaults \
++-chardev socket,id=charmonitor,fd=1729,server,nowait \
++-mon chardev=charmonitor,id=monitor,mode=control \
++-rtc base=utc \
++-no-shutdown \
++-no-acpi \
++-boot strict=on \
++-device piix3-usb-uhci,id=usb,bus=pci.0,addr=0x1.0x2 \
++-device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x2 \
++-sandbox on,obsolete=deny,elevateprivileges=deny,spawn=deny,\
++resourcecontrol=deny \
++-msg timestamp=on
+diff --git a/tests/qemuxml2argvdata/cpu-translation.xml b/tests/qemuxml2argvdata/cpu-translation.xml
+new file mode 100644
+index 0000000000..4054f3d3be
+--- /dev/null
++++ b/tests/qemuxml2argvdata/cpu-translation.xml
+@@ -0,0 +1,34 @@
++<domain type='qemu'>
++  <name>QEMUGuest1</name>
++  <uuid>c7a5fdbd-fade-9455-926a-d65c16db1809</uuid>
++  <memory unit='KiB'>219100</memory>
++  <currentMemory unit='KiB'>219100</currentMemory>
++  <vcpu placement='static'>1</vcpu>
++  <os>
++    <type arch='x86_64' machine='pc'>hvm</type>
++    <boot dev='network'/>
++  </os>
++  <features>
++    <apic eoi='on'/>
++    <pvspinlock state='on'/>
++  </features>
++  <cpu mode='custom'>
++    <model fallback='forbid'>Haswell</model>
++    <feature name='pclmuldq' policy='require'/>
++    <feature name='ds_cpl' policy='require'/>
++    <feature name='tsc_adjust' policy='require'/>
++    <feature name='fxsr_opt' policy='require'/>
++    <feature name='lahf_lm' policy='require'/>
++    <feature name='cmp_legacy' policy='require'/>
++    <feature name='nodeid_msr' policy='require'/>
++    <feature name='perfctr_core' policy='require'/>
++    <feature name='perfctr_nb' policy='require'/>
++  </cpu>
++  <clock offset='utc'/>
++  <on_poweroff>destroy</on_poweroff>
++  <on_reboot>restart</on_reboot>
++  <on_crash>destroy</on_crash>
++  <devices>
++      <emulator>/usr/bin/qemu-system-x86_64</emulator>
++  </devices>
++</domain>
+diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
+index 9de0cbf7e9..03d6a60736 100644
+--- a/tests/qemuxml2argvtest.c
++++ b/tests/qemuxml2argvtest.c
+@@ -1741,6 +1741,7 @@ mymain(void)
+     DO_TEST("cpu-Haswell-noTSX", QEMU_CAPS_KVM);
+     DO_TEST("cpu-host-model-cmt", NONE);
+     DO_TEST("cpu-tsc-frequency", QEMU_CAPS_KVM);
++    DO_TEST_CAPS_LATEST("cpu-translation");
+     qemuTestSetHostCPU(driver.caps, NULL);
+ 
+     DO_TEST("encrypted-disk", QEMU_CAPS_QCOW2_LUKS, QEMU_CAPS_OBJECT_SECRET);
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-rpc-virnetlibsshsession-update-deprecated-functions.patch b/SOURCES/libvirt-rpc-virnetlibsshsession-update-deprecated-functions.patch
new file mode 100644
index 0000000..a846323
--- /dev/null
+++ b/SOURCES/libvirt-rpc-virnetlibsshsession-update-deprecated-functions.patch
@@ -0,0 +1,63 @@
+From aa46a438d03839963badb7bdd2904a71f0662942 Mon Sep 17 00:00:00 2001
+Message-Id: <aa46a438d03839963badb7bdd2904a71f0662942@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Fri, 21 Jun 2019 09:30:36 +0200
+Subject: [PATCH] rpc: virnetlibsshsession: update deprecated functions
+
+In libssh 0.9.0 functions ssh_is_server_known and ssh_write_knownhost
+are marked as deprecated.
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1722735
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <e6b648f51b2d3a2714d7e28249dd390f707994b1.1561102197.git.phrdina@redhat.com>
+Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ m4/virt-libssh.m4             | 8 ++++++++
+ src/rpc/virnetlibsshsession.c | 4 ++--
+ 2 files changed, 10 insertions(+), 2 deletions(-)
+
+diff --git a/m4/virt-libssh.m4 b/m4/virt-libssh.m4
+index 01c3b75c72..132447da16 100644
+--- a/m4/virt-libssh.m4
++++ b/m4/virt-libssh.m4
+@@ -33,6 +33,14 @@ AC_DEFUN([LIBVIRT_CHECK_LIBSSH],[
+       [],
+       [AC_DEFINE_UNQUOTED([ssh_get_server_publickey], [ssh_get_publickey],
+             [ssh_get_publickey is deprecated and replaced by ssh_get_server_publickey.])])
++    AC_CHECK_FUNC([ssh_session_is_known_server],
++      [],
++      [AC_DEFINE_UNQUOTED([ssh_session_is_known_server], [ssh_is_server_known],
++            [ssh_is_server_known is deprecated and replaced by ssh_session_is_known_server.])])
++    AC_CHECK_FUNC([ssh_session_update_known_hosts],
++      [],
++      [AC_DEFINE_UNQUOTED([ssh_session_update_known_hosts], [ssh_write_knownhost],
++            [ssh_write_knownhost is deprecated and replaced by ssh_session_update_known_hosts.])])
+     CFLAGS="$old_CFLAGS"
+     LIBS="$old_LIBS"
+   fi
+diff --git a/src/rpc/virnetlibsshsession.c b/src/rpc/virnetlibsshsession.c
+index df819f6169..7bc2bd33ee 100644
+--- a/src/rpc/virnetlibsshsession.c
++++ b/src/rpc/virnetlibsshsession.c
+@@ -287,7 +287,7 @@ virNetLibsshCheckHostKey(virNetLibsshSessionPtr sess)
+     if (sess->hostKeyVerify == VIR_NET_LIBSSH_HOSTKEY_VERIFY_IGNORE)
+         return 0;
+ 
+-    state = ssh_is_server_known(sess->session);
++    state = ssh_session_is_known_server(sess->session);
+ 
+     switch (state) {
+     case SSH_SERVER_KNOWN_OK:
+@@ -381,7 +381,7 @@ virNetLibsshCheckHostKey(virNetLibsshSessionPtr sess)
+ 
+         /* write the host key file, if specified */
+         if (sess->knownHostsFile) {
+-            if (ssh_write_knownhost(sess->session) < 0) {
++            if (ssh_session_update_known_hosts(sess->session) < 0) {
+                 errmsg = ssh_get_error(sess->session);
+                 virReportError(VIR_ERR_LIBSSH,
+                                _("failed to write known_host file '%s': %s"),
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-test-Introduce-virnetdevopenvswitchtest.patch b/SOURCES/libvirt-test-Introduce-virnetdevopenvswitchtest.patch
new file mode 100644
index 0000000..b270449
--- /dev/null
+++ b/SOURCES/libvirt-test-Introduce-virnetdevopenvswitchtest.patch
@@ -0,0 +1,356 @@
+From e1699c1bb0cbf20ea24db8607492a8f418ee8f95 Mon Sep 17 00:00:00 2001
+Message-Id: <e1699c1bb0cbf20ea24db8607492a8f418ee8f95@dist-git>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Tue, 30 Jul 2019 15:30:52 +0200
+Subject: [PATCH] test: Introduce virnetdevopenvswitchtest
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Test if our parsing of interface stats as returned by ovs-vsctl
+works as expected. To achieve this without having to mock
+virCommand* I'm separating parsing of stats into a separate
+function.
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit cc34260f5a8715d208ee45a6ebaa79e5264cbe68)
+
+Conflicts:
+- src/libvirt_private.syms: Context, no
+    virNetDevOpenvswitchInterfaceGetMaster()
+- src/util/virnetdevopenvswitch.c: Unknown, conflict in a
+    comment, the diff looks the same to me.
+- tests/Makefile.am: Context, no virnetworkportxml2xmldata in
+    EXTRA_DIST
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1721434
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Message-Id: <a46322e55761cff95f64c7ee023e95abed9a375a.1564493409.git.mprivozn@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/libvirt_private.syms                   |   1 +
+ src/util/virnetdevopenvswitch.c            |  93 ++++++++++++-------
+ src/util/virnetdevopenvswitch.h            |   4 +
+ tests/Makefile.am                          |  13 ++-
+ tests/virnetdevopenvswitchdata/stats1.json |   1 +
+ tests/virnetdevopenvswitchdata/stats2.json |   1 +
+ tests/virnetdevopenvswitchtest.c           | 101 +++++++++++++++++++++
+ 7 files changed, 177 insertions(+), 37 deletions(-)
+ create mode 100644 tests/virnetdevopenvswitchdata/stats1.json
+ create mode 100644 tests/virnetdevopenvswitchdata/stats2.json
+ create mode 100644 tests/virnetdevopenvswitchtest.c
+
+diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
+index 8132f9664b..f4b54cee0b 100644
+--- a/src/libvirt_private.syms
++++ b/src/libvirt_private.syms
+@@ -2422,6 +2422,7 @@ virNetDevMidonetUnbindPort;
+ virNetDevOpenvswitchAddPort;
+ virNetDevOpenvswitchGetMigrateData;
+ virNetDevOpenvswitchGetVhostuserIfname;
++virNetDevOpenvswitchInterfaceParseStats;
+ virNetDevOpenvswitchInterfaceStats;
+ virNetDevOpenvswitchRemovePort;
+ virNetDevOpenvswitchSetMigrateData;
+diff --git a/src/util/virnetdevopenvswitch.c b/src/util/virnetdevopenvswitch.c
+index dbd832053b..ac8ec09b65 100644
+--- a/src/util/virnetdevopenvswitch.c
++++ b/src/util/virnetdevopenvswitch.c
+@@ -306,49 +306,30 @@ int virNetDevOpenvswitchSetMigrateData(char *migrate, const char *ifname)
+     return 0;
+ }
+ 
++
+ /**
+- * virNetDevOpenvswitchInterfaceStats:
+- * @ifname: the name of the interface
+- * @stats: the retreived domain interface stat
++ * virNetDevOpenvswitchInterfaceParseStats:
++ * @json: Input string in JSON format
++ * @stats: parsed stats
+  *
+- * Retrieves the OVS interfaces stats
++ * For given input string @json parse interface statistics and store them into
++ * @stats.
+  *
+- * Returns 0 in case of success or -1 in case of failure
++ * Returns: 0 on success,
++ *         -1 otherwise (with error reported).
+  */
+ int
+-virNetDevOpenvswitchInterfaceStats(const char *ifname,
+-                                   virDomainInterfaceStatsPtr stats)
++virNetDevOpenvswitchInterfaceParseStats(const char *json,
++                                        virDomainInterfaceStatsPtr stats)
+ {
+-    VIR_AUTOPTR(virCommand) cmd = NULL;
+-    VIR_AUTOFREE(char *) output = NULL;
+     VIR_AUTOPTR(virJSONValue) jsonStats = NULL;
+     virJSONValuePtr jsonMap = NULL;
+     size_t i;
+ 
+-    cmd = virCommandNew(OVSVSCTL);
+-    virNetDevOpenvswitchAddTimeout(cmd);
+-    virCommandAddArgList(cmd, "--if-exists", "--format=list", "--data=json",
+-                         "--no-headings", "--columns=statistics", "list",
+-                         "Interface", ifname, NULL);
+-    virCommandSetOutputBuffer(cmd, &output);
++    stats->rx_bytes = stats->rx_packets = stats->rx_errs = stats->rx_drop = -1;
++    stats->tx_bytes = stats->tx_packets = stats->tx_errs = stats->tx_drop = -1;
+ 
+-    /* The above command returns either:
+-     * 1) empty string if @ifname doesn't exist, or
+-     * 2) a JSON array, for instance:
+-     *    ["map",[["collisions",0],["rx_bytes",0],["rx_crc_err",0],["rx_dropped",0],
+-     *    ["rx_errors",0],["rx_frame_err",0],["rx_over_err",0],["rx_packets",0],
+-     *    ["tx_bytes",12406],["tx_dropped",0],["tx_errors",0],["tx_packets",173]]]
+-     */
+-
+-    if (virCommandRun(cmd, NULL) < 0 ||
+-        STREQ_NULLABLE(output, "")) {
+-        /* no ovs-vsctl or interface 'ifname' doesn't exists in ovs */
+-        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+-                       _("Interface not found"));
+-        return -1;
+-    }
+-
+-    if (!(jsonStats = virJSONValueFromString(output)) ||
++    if (!(jsonStats = virJSONValueFromString(json)) ||
+         !virJSONValueIsArray(jsonStats) ||
+         !(jsonMap = virJSONValueArrayGet(jsonStats, 1))) {
+         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+@@ -356,9 +337,6 @@ virNetDevOpenvswitchInterfaceStats(const char *ifname,
+         return -1;
+     }
+ 
+-    stats->rx_bytes = stats->rx_packets = stats->rx_errs = stats->rx_drop = -1;
+-    stats->tx_bytes = stats->tx_packets = stats->tx_errs = stats->tx_drop = -1;
+-
+     for (i = 0; i < virJSONValueArraySize(jsonMap); i++) {
+         virJSONValuePtr item = virJSONValueArrayGet(jsonMap, i);
+         virJSONValuePtr jsonKey;
+@@ -399,6 +377,51 @@ virNetDevOpenvswitchInterfaceStats(const char *ifname,
+         }
+     }
+ 
++    return 0;
++}
++
++/**
++ * virNetDevOpenvswitchInterfaceStats:
++ * @ifname: the name of the interface
++ * @stats: the retrieved domain interface stat
++ *
++ * Retrieves the OVS interfaces stats
++ *
++ * Returns 0 in case of success or -1 in case of failure
++ */
++int
++virNetDevOpenvswitchInterfaceStats(const char *ifname,
++                                   virDomainInterfaceStatsPtr stats)
++{
++    VIR_AUTOPTR(virCommand) cmd = NULL;
++    VIR_AUTOFREE(char *) output = NULL;
++
++    cmd = virCommandNew(OVSVSCTL);
++    virNetDevOpenvswitchAddTimeout(cmd);
++    virCommandAddArgList(cmd, "--if-exists", "--format=list", "--data=json",
++                         "--no-headings", "--columns=statistics", "list",
++                         "Interface", ifname, NULL);
++    virCommandSetOutputBuffer(cmd, &output);
++
++    /* The above command returns either:
++     * 1) empty string if @ifname doesn't exist, or
++     * 2) a JSON array, for instance:
++     *    ["map",[["collisions",0],["rx_bytes",0],["rx_crc_err",0],["rx_dropped",0],
++     *    ["rx_errors",0],["rx_frame_err",0],["rx_over_err",0],["rx_packets",0],
++     *    ["tx_bytes",12406],["tx_dropped",0],["tx_errors",0],["tx_packets",173]]]
++     */
++
++    if (virCommandRun(cmd, NULL) < 0 ||
++        STREQ_NULLABLE(output, "")) {
++        /* no ovs-vsctl or interface 'ifname' doesn't exists in ovs */
++        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
++                       _("Interface not found"));
++        return -1;
++    }
++
++    if (virNetDevOpenvswitchInterfaceParseStats(output, stats) < 0)
++        return -1;
++
+     if (stats->rx_bytes == -1 &&
+         stats->rx_packets == -1 &&
+         stats->rx_errs == -1 &&
+diff --git a/src/util/virnetdevopenvswitch.h b/src/util/virnetdevopenvswitch.h
+index 6f6e620c22..c1a211dec1 100644
+--- a/src/util/virnetdevopenvswitch.h
++++ b/src/util/virnetdevopenvswitch.h
+@@ -53,6 +53,10 @@ int virNetDevOpenvswitchGetMigrateData(char **migrate, const char *ifname)
+ int virNetDevOpenvswitchSetMigrateData(char *migrate, const char *ifname)
+     ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;
+ 
++int virNetDevOpenvswitchInterfaceParseStats(const char *json,
++                                            virDomainInterfaceStatsPtr stats)
++    ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK;
++
+ int virNetDevOpenvswitchInterfaceStats(const char *ifname,
+                                        virDomainInterfaceStatsPtr stats)
+     ATTRIBUTE_NONNULL(1) ATTRIBUTE_RETURN_CHECK;
+diff --git a/tests/Makefile.am b/tests/Makefile.am
+index c0337ea10c..201de1d37d 100644
+--- a/tests/Makefile.am
++++ b/tests/Makefile.am
+@@ -157,6 +157,7 @@ EXTRA_DIST = \
+ 	virmock.h \
+ 	virnetdaemondata \
+ 	virnetdevtestdata \
++	virnetdevopenvswitchdata \
+ 	virnwfilterbindingxml2xmldata \
+ 	virpcitestdata \
+ 	virscsidata \
+@@ -1230,9 +1231,17 @@ virmacmaptest_SOURCES = \
+ 	virmacmaptest.c testutils.h testutils.c
+ virmacmaptest_LDADD = $(LDADDS)
+ 
+-test_programs += virmacmaptest
++virnetdevopenvswitchtest_SOURCES = \
++	virnetdevopenvswitchtest.c testutils.h testutils.c
++virnetdevopenvswitchtest_LDADD = $(LDADDS)
++
++test_programs += \
++	virmacmaptest \
++	virnetdevopenvswitchtest
+ else ! WITH_YAJL
+-EXTRA_DIST +=  virmacmaptest.c
++EXTRA_DIST += \
++	virmacmaptest.c \
++	virnetdevopenvswitchtest.c
+ endif ! WITH_YAJL
+ 
+ virnetdevtest_SOURCES = \
+diff --git a/tests/virnetdevopenvswitchdata/stats1.json b/tests/virnetdevopenvswitchdata/stats1.json
+new file mode 100644
+index 0000000000..1138c6271e
+--- /dev/null
++++ b/tests/virnetdevopenvswitchdata/stats1.json
+@@ -0,0 +1 @@
++["map",[["collisions",1],["rx_bytes",2],["rx_crc_err",3],["rx_dropped",4],["rx_errors",5],["rx_frame_err",6],["rx_over_err",7],["rx_packets",8],["tx_bytes",9],["tx_dropped",10],["tx_errors",11],["tx_packets",12]]]
+diff --git a/tests/virnetdevopenvswitchdata/stats2.json b/tests/virnetdevopenvswitchdata/stats2.json
+new file mode 100644
+index 0000000000..d84be7e011
+--- /dev/null
++++ b/tests/virnetdevopenvswitchdata/stats2.json
+@@ -0,0 +1 @@
++["map",[["collisions",0],["rx_bytes",0],["rx_crc_err",0],["rx_dropped",0],["rx_errors",0],["rx_frame_err",0],["rx_over_err",0],["rx_packets",0],["tx_bytes",12406],["tx_dropped",0],["tx_errors",0],["tx_packets",173]]]
+diff --git a/tests/virnetdevopenvswitchtest.c b/tests/virnetdevopenvswitchtest.c
+new file mode 100644
+index 0000000000..f01e77cbba
+--- /dev/null
++++ b/tests/virnetdevopenvswitchtest.c
+@@ -0,0 +1,101 @@
++/*
++ * Copyright (C) 2019 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
++ * License as published by the Free Software Foundation; either
++ * version 2.1 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with this library.  If not, see
++ * <http://www.gnu.org/licenses/>.
++ */
++
++#include <config.h>
++
++#include "testutils.h"
++#include "virnetdevopenvswitch.h"
++
++#define VIR_FROM_THIS VIR_FROM_NONE
++
++typedef struct _InterfaceParseStatsData InterfaceParseStatsData;
++struct _InterfaceParseStatsData {
++    const char *filename;
++    const virDomainInterfaceStatsStruct stats;
++};
++
++
++static int
++testInterfaceParseStats(const void *opaque)
++{
++    const InterfaceParseStatsData *data = opaque;
++    VIR_AUTOFREE(char *) filename = NULL;
++    VIR_AUTOFREE(char *) buf = NULL;
++    virDomainInterfaceStatsStruct actual;
++
++    if (virAsprintf(&filename, "%s/virnetdevopenvswitchdata/%s",
++                    abs_srcdir, data->filename) < 0)
++        return -1;
++
++    if (virFileReadAll(filename, 1024, &buf) < 0)
++        return -1;
++
++    if (virNetDevOpenvswitchInterfaceParseStats(buf, &actual) < 0)
++        return -1;
++
++    if (memcmp(&actual, &data->stats, sizeof(actual)) != 0) {
++        fprintf(stderr,
++                "Expected stats: %lld %lld %lld %lld %lld %lld %lld %lld\n"
++                "Actual stats: %lld %lld %lld %lld %lld %lld %lld %lld",
++                data->stats.rx_bytes,
++                data->stats.rx_packets,
++                data->stats.rx_errs,
++                data->stats.rx_drop,
++                data->stats.tx_bytes,
++                data->stats.tx_packets,
++                data->stats.tx_errs,
++                data->stats.tx_drop,
++                actual.rx_bytes,
++                actual.rx_packets,
++                actual.rx_errs,
++                actual.rx_drop,
++                actual.tx_bytes,
++                actual.tx_packets,
++                actual.tx_errs,
++                actual.tx_drop);
++
++        return -1;
++    }
++
++    return 0;
++}
++
++
++static int
++mymain(void)
++{
++    int ret = 0;
++
++#define TEST_INTERFACE_STATS(file, \
++                             rxBytes, rxPackets, rxErrs, rxDrop, \
++                             txBytes, txPackets, txErrs, txDrop) \
++    do { \
++        const InterfaceParseStatsData data = {.filename = file, .stats = { \
++                             rxBytes, rxPackets, rxErrs, rxDrop, \
++                             txBytes, txPackets, txErrs, txDrop}}; \
++        if (virTestRun("Interface stats " file, testInterfaceParseStats, &data) < 0) \
++            ret = -1; \
++    } while (0)
++
++    TEST_INTERFACE_STATS("stats1.json", 9, 12, 11, 10, 2, 8, 5, 4);
++    TEST_INTERFACE_STATS("stats2.json", 12406, 173, 0, 0, 0, 0, 0, 0);
++
++    return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
++}
++
++VIR_TEST_MAIN(mymain);
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-tests-Add-QEMU-caps-data-for-future-4.1.0.patch b/SOURCES/libvirt-tests-Add-QEMU-caps-data-for-future-4.1.0.patch
new file mode 100644
index 0000000..3334ae5
--- /dev/null
+++ b/SOURCES/libvirt-tests-Add-QEMU-caps-data-for-future-4.1.0.patch
@@ -0,0 +1,25247 @@
+From e4ded1e96b54db8f56af824a1e3e1acdf2f84e71 Mon Sep 17 00:00:00 2001
+Message-Id: <e4ded1e96b54db8f56af824a1e3e1acdf2f84e71@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:25:48 +0200
+Subject: [PATCH] tests: Add QEMU caps data for future 4.1.0
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit fb5bde121fcc0dc99926fe71c17a0ff668003250)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1697627
+
+Conflicts:
+	tests/qemucapabilitiesdata/caps_4.1.0.x86_64.replies
+	tests/qemucapabilitiesdata/caps_4.1.0.x86_64.xml
+            - different set of probed capabilities
+
+	tests/qemucapabilitiestest.c
+            - upstream uses testQemuCapsIterate
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <baa57d2576fd4ddde8dc4808da0704fe7c5ee394.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ .../caps_4.1.0.x86_64.replies                 | 23762 ++++++++++++++++
+ .../caps_4.1.0.x86_64.xml                     |  1424 +
+ tests/qemucapabilitiestest.c                  |     1 +
+ 3 files changed, 25187 insertions(+)
+ create mode 100644 tests/qemucapabilitiesdata/caps_4.1.0.x86_64.replies
+ create mode 100644 tests/qemucapabilitiesdata/caps_4.1.0.x86_64.xml
+
+diff --git a/tests/qemucapabilitiesdata/caps_4.1.0.x86_64.replies b/tests/qemucapabilitiesdata/caps_4.1.0.x86_64.replies
+new file mode 100644
+index 0000000000..ab0ac1e7bf
+--- /dev/null
++++ b/tests/qemucapabilitiesdata/caps_4.1.0.x86_64.replies
+@@ -0,0 +1,23762 @@
++{
++  "execute": "qmp_capabilities",
++  "id": "libvirt-1"
++}
++
++{
++  "return": {
++  },
++  "id": "libvirt-1"
++}
++
++{
++  "execute": "query-version",
++  "id": "libvirt-2"
++}
++
++{
++  "return": {
++    "qemu": {
++      "micro": 50,
++      "minor": 0,
++      "major": 4
++    },
++    "package": "v4.0.0-1173-g9c70209b63"
++  },
++  "id": "libvirt-2"
++}
++
++{
++  "execute": "query-target",
++  "id": "libvirt-3"
++}
++
++{
++  "return": {
++    "arch": "x86_64"
++  },
++  "id": "libvirt-3"
++}
++
++{
++  "execute": "query-commands",
++  "id": "libvirt-4"
++}
++
++{
++  "return": [
++    {
++      "name": "netdev_add"
++    },
++    {
++      "name": "device_add"
++    },
++    {
++      "name": "query-qmp-schema"
++    },
++    {
++      "name": "query-cpu-definitions"
++    },
++    {
++      "name": "query-cpu-model-expansion"
++    },
++    {
++      "name": "query-sev-capabilities"
++    },
++    {
++      "name": "query-sev-launch-measure"
++    },
++    {
++      "name": "query-sev"
++    },
++    {
++      "name": "rtc-reset-reinjection"
++    },
++    {
++      "name": "set-numa-node"
++    },
++    {
++      "name": "query-vm-generation-id"
++    },
++    {
++      "name": "query-hotpluggable-cpus"
++    },
++    {
++      "name": "xen-load-devices-state"
++    },
++    {
++      "name": "query-acpi-ospm-status"
++    },
++    {
++      "name": "query-memory-devices"
++    },
++    {
++      "name": "query-memdev"
++    },
++    {
++      "name": "query-command-line-options"
++    },
++    {
++      "name": "query-target"
++    },
++    {
++      "name": "query-fdsets"
++    },
++    {
++      "name": "remove-fd"
++    },
++    {
++      "name": "add-fd"
++    },
++    {
++      "name": "query-memory-size-summary"
++    },
++    {
++      "name": "query-current-machine"
++    },
++    {
++      "name": "query-machines"
++    },
++    {
++      "name": "closefd"
++    },
++    {
++      "name": "getfd"
++    },
++    {
++      "name": "object-del"
++    },
++    {
++      "name": "object-add"
++    },
++    {
++      "name": "query-dump-guest-memory-capability"
++    },
++    {
++      "name": "query-dump"
++    },
++    {
++      "name": "dump-guest-memory"
++    },
++    {
++      "name": "device_del"
++    },
++    {
++      "name": "xen-set-global-dirty-log"
++    },
++    {
++      "name": "qom-list-properties"
++    },
++    {
++      "name": "device-list-properties"
++    },
++    {
++      "name": "qom-list-types"
++    },
++    {
++      "name": "change"
++    },
++    {
++      "name": "qom-set"
++    },
++    {
++      "name": "qom-get"
++    },
++    {
++      "name": "qom-list"
++    },
++    {
++      "name": "human-monitor-command"
++    },
++    {
++      "name": "balloon"
++    },
++    {
++      "name": "inject-nmi"
++    },
++    {
++      "name": "system_wakeup"
++    },
++    {
++      "name": "x-exit-preconfig"
++    },
++    {
++      "name": "cont"
++    },
++    {
++      "name": "pmemsave"
++    },
++    {
++      "name": "memsave"
++    },
++    {
++      "name": "cpu-add"
++    },
++    {
++      "name": "system_powerdown"
++    },
++    {
++      "name": "system_reset"
++    },
++    {
++      "name": "stop"
++    },
++    {
++      "name": "quit"
++    },
++    {
++      "name": "query-pci"
++    },
++    {
++      "name": "query-balloon"
++    },
++    {
++      "name": "query-iothreads"
++    },
++    {
++      "name": "query-cpus-fast"
++    },
++    {
++      "name": "query-cpus"
++    },
++    {
++      "name": "query-events"
++    },
++    {
++      "name": "query-uuid"
++    },
++    {
++      "name": "query-kvm"
++    },
++    {
++      "name": "query-name"
++    },
++    {
++      "name": "add_client"
++    },
++    {
++      "name": "query-commands"
++    },
++    {
++      "name": "query-version"
++    },
++    {
++      "name": "qmp_capabilities"
++    },
++    {
++      "name": "trace-event-set-state"
++    },
++    {
++      "name": "trace-event-get-state"
++    },
++    {
++      "name": "transaction"
++    },
++    {
++      "name": "migrate-pause"
++    },
++    {
++      "name": "migrate-recover"
++    },
++    {
++      "name": "query-colo-status"
++    },
++    {
++      "name": "xen-colo-do-checkpoint"
++    },
++    {
++      "name": "query-xen-replication-status"
++    },
++    {
++      "name": "xen-set-replication"
++    },
++    {
++      "name": "xen-save-devices-state"
++    },
++    {
++      "name": "migrate-incoming"
++    },
++    {
++      "name": "migrate"
++    },
++    {
++      "name": "query-migrate-cache-size"
++    },
++    {
++      "name": "migrate-set-cache-size"
++    },
++    {
++      "name": "migrate_set_speed"
++    },
++    {
++      "name": "migrate_set_downtime"
++    },
++    {
++      "name": "migrate-continue"
++    },
++    {
++      "name": "migrate_cancel"
++    },
++    {
++      "name": "x-colo-lost-heartbeat"
++    },
++    {
++      "name": "migrate-start-postcopy"
++    },
++    {
++      "name": "client_migrate_info"
++    },
++    {
++      "name": "query-migrate-parameters"
++    },
++    {
++      "name": "migrate-set-parameters"
++    },
++    {
++      "name": "query-migrate-capabilities"
++    },
++    {
++      "name": "migrate-set-capabilities"
++    },
++    {
++      "name": "query-migrate"
++    },
++    {
++      "name": "query-display-options"
++    },
++    {
++      "name": "input-send-event"
++    },
++    {
++      "name": "send-key"
++    },
++    {
++      "name": "query-mice"
++    },
++    {
++      "name": "change-vnc-password"
++    },
++    {
++      "name": "query-vnc-servers"
++    },
++    {
++      "name": "query-vnc"
++    },
++    {
++      "name": "query-spice"
++    },
++    {
++      "name": "screendump"
++    },
++    {
++      "name": "expire_password"
++    },
++    {
++      "name": "set_password"
++    },
++    {
++      "name": "query-tpm"
++    },
++    {
++      "name": "query-tpm-types"
++    },
++    {
++      "name": "query-tpm-models"
++    },
++    {
++      "name": "query-rocker-of-dpa-groups"
++    },
++    {
++      "name": "query-rocker-of-dpa-flows"
++    },
++    {
++      "name": "query-rocker-ports"
++    },
++    {
++      "name": "query-rocker"
++    },
++    {
++      "name": "announce-self"
++    },
++    {
++      "name": "query-rx-filter"
++    },
++    {
++      "name": "netdev_del"
++    },
++    {
++      "name": "set_link"
++    },
++    {
++      "name": "chardev-send-break"
++    },
++    {
++      "name": "chardev-remove"
++    },
++    {
++      "name": "chardev-change"
++    },
++    {
++      "name": "chardev-add"
++    },
++    {
++      "name": "ringbuf-read"
++    },
++    {
++      "name": "ringbuf-write"
++    },
++    {
++      "name": "query-chardev-backends"
++    },
++    {
++      "name": "query-chardev"
++    },
++    {
++      "name": "nbd-server-stop"
++    },
++    {
++      "name": "nbd-server-remove"
++    },
++    {
++      "name": "nbd-server-add"
++    },
++    {
++      "name": "nbd-server-start"
++    },
++    {
++      "name": "eject"
++    },
++    {
++      "name": "blockdev-snapshot-delete-internal-sync"
++    },
++    {
++      "name": "blockdev-snapshot-internal-sync"
++    },
++    {
++      "name": "query-pr-managers"
++    },
++    {
++      "name": "x-blockdev-set-iothread"
++    },
++    {
++      "name": "x-blockdev-change"
++    },
++    {
++      "name": "block-set-write-threshold"
++    },
++    {
++      "name": "blockdev-change-medium"
++    },
++    {
++      "name": "blockdev-insert-medium"
++    },
++    {
++      "name": "blockdev-remove-medium"
++    },
++    {
++      "name": "blockdev-close-tray"
++    },
++    {
++      "name": "blockdev-open-tray"
++    },
++    {
++      "name": "blockdev-create"
++    },
++    {
++      "name": "blockdev-del"
++    },
++    {
++      "name": "x-blockdev-reopen"
++    },
++    {
++      "name": "blockdev-add"
++    },
++    {
++      "name": "block-job-finalize"
++    },
++    {
++      "name": "block-job-dismiss"
++    },
++    {
++      "name": "block-job-complete"
++    },
++    {
++      "name": "block-job-resume"
++    },
++    {
++      "name": "block-job-pause"
++    },
++    {
++      "name": "block-job-cancel"
++    },
++    {
++      "name": "block-job-set-speed"
++    },
++    {
++      "name": "block-stream"
++    },
++    {
++      "name": "block_set_io_throttle"
++    },
++    {
++      "name": "blockdev-mirror"
++    },
++    {
++      "name": "x-debug-block-dirty-bitmap-sha256"
++    },
++    {
++      "name": "block-dirty-bitmap-merge"
++    },
++    {
++      "name": "block-dirty-bitmap-disable"
++    },
++    {
++      "name": "block-dirty-bitmap-enable"
++    },
++    {
++      "name": "block-dirty-bitmap-clear"
++    },
++    {
++      "name": "block-dirty-bitmap-remove"
++    },
++    {
++      "name": "block-dirty-bitmap-add"
++    },
++    {
++      "name": "drive-mirror"
++    },
++    {
++      "name": "x-debug-query-block-graph"
++    },
++    {
++      "name": "query-named-block-nodes"
++    },
++    {
++      "name": "blockdev-backup"
++    },
++    {
++      "name": "drive-backup"
++    },
++    {
++      "name": "block-commit"
++    },
++    {
++      "name": "change-backing-file"
++    },
++    {
++      "name": "blockdev-snapshot"
++    },
++    {
++      "name": "blockdev-snapshot-sync"
++    },
++    {
++      "name": "block_resize"
++    },
++    {
++      "name": "block_passwd"
++    },
++    {
++      "name": "query-block-jobs"
++    },
++    {
++      "name": "query-blockstats"
++    },
++    {
++      "name": "query-block"
++    },
++    {
++      "name": "block-latency-histogram-set"
++    },
++    {
++      "name": "query-jobs"
++    },
++    {
++      "name": "job-finalize"
++    },
++    {
++      "name": "job-dismiss"
++    },
++    {
++      "name": "job-complete"
++    },
++    {
++      "name": "job-cancel"
++    },
++    {
++      "name": "job-resume"
++    },
++    {
++      "name": "job-pause"
++    },
++    {
++      "name": "watchdog-set-action"
++    },
++    {
++      "name": "query-status"
++    }
++  ],
++  "id": "libvirt-4"
++}
++
++{
++  "execute": "add-fd",
++  "arguments": {
++    "fdset-id": 0,
++    "opaque": "/dev/null"
++  },
++  "id": "libvirt-5"
++}
++
++{
++  "return": {
++    "fd": 18,
++    "fdset-id": 0
++  },
++  "id": "libvirt-5"
++}
++
++{
++  "execute": "block-commit",
++  "arguments": {
++    "device": "bogus"
++  },
++  "id": "libvirt-6"
++}
++
++{
++  "id": "libvirt-6",
++  "error": {
++    "class": "DeviceNotFound",
++    "desc": "Device 'bogus' not found"
++  }
++}
++
++{
++  "execute": "query-kvm",
++  "id": "libvirt-7"
++}
++
++{
++  "return": {
++    "enabled": true,
++    "present": true
++  },
++  "id": "libvirt-7"
++}
++
++{
++  "execute": "query-events",
++  "id": "libvirt-8"
++}
++
++{
++  "return": [
++    {
++      "name": "RTC_CHANGE"
++    },
++    {
++      "name": "ACPI_DEVICE_OST"
++    },
++    {
++      "name": "MEM_UNPLUG_ERROR"
++    },
++    {
++      "name": "DUMP_COMPLETED"
++    },
++    {
++      "name": "DEVICE_DELETED"
++    },
++    {
++      "name": "BALLOON_CHANGE"
++    },
++    {
++      "name": "COLO_EXIT"
++    },
++    {
++      "name": "MIGRATION_PASS"
++    },
++    {
++      "name": "MIGRATION"
++    },
++    {
++      "name": "VNC_DISCONNECTED"
++    },
++    {
++      "name": "VNC_INITIALIZED"
++    },
++    {
++      "name": "VNC_CONNECTED"
++    },
++    {
++      "name": "SPICE_MIGRATE_COMPLETED"
++    },
++    {
++      "name": "SPICE_DISCONNECTED"
++    },
++    {
++      "name": "SPICE_INITIALIZED"
++    },
++    {
++      "name": "SPICE_CONNECTED"
++    },
++    {
++      "name": "RDMA_GID_STATUS_CHANGED"
++    },
++    {
++      "name": "NIC_RX_FILTER_CHANGED"
++    },
++    {
++      "name": "VSERPORT_CHANGE"
++    },
++    {
++      "name": "QUORUM_REPORT_BAD"
++    },
++    {
++      "name": "QUORUM_FAILURE"
++    },
++    {
++      "name": "PR_MANAGER_STATUS_CHANGED"
++    },
++    {
++      "name": "DEVICE_TRAY_MOVED"
++    },
++    {
++      "name": "BLOCK_WRITE_THRESHOLD"
++    },
++    {
++      "name": "BLOCK_JOB_PENDING"
++    },
++    {
++      "name": "BLOCK_JOB_READY"
++    },
++    {
++      "name": "BLOCK_JOB_ERROR"
++    },
++    {
++      "name": "BLOCK_JOB_CANCELLED"
++    },
++    {
++      "name": "BLOCK_JOB_COMPLETED"
++    },
++    {
++      "name": "BLOCK_IO_ERROR"
++    },
++    {
++      "name": "BLOCK_IMAGE_CORRUPTED"
++    },
++    {
++      "name": "JOB_STATUS_CHANGE"
++    },
++    {
++      "name": "GUEST_PANICKED"
++    },
++    {
++      "name": "WATCHDOG"
++    },
++    {
++      "name": "WAKEUP"
++    },
++    {
++      "name": "SUSPEND_DISK"
++    },
++    {
++      "name": "SUSPEND"
++    },
++    {
++      "name": "RESUME"
++    },
++    {
++      "name": "STOP"
++    },
++    {
++      "name": "RESET"
++    },
++    {
++      "name": "POWERDOWN"
++    },
++    {
++      "name": "SHUTDOWN"
++    }
++  ],
++  "id": "libvirt-8"
++}
++
++{
++  "execute": "qom-list-types",
++  "id": "libvirt-9"
++}
++
++{
++  "return": [
++    {
++      "name": "vhost-vsock-pci",
++      "parent": "vhost-vsock-pci-base"
++    },
++    {
++      "name": "scsi-generic",
++      "parent": "scsi-device"
++    },
++    {
++      "name": "qio-channel-tls",
++      "parent": "qio-channel"
++    },
++    {
++      "name": "scsi-hd",
++      "parent": "scsi-disk-base"
++    },
++    {
++      "name": "usb-bot",
++      "parent": "usb-storage-dev"
++    },
++    {
++      "name": "chardev-null",
++      "parent": "chardev"
++    },
++    {
++      "name": "chardev-parallel",
++      "parent": "chardev"
++    },
++    {
++      "name": "qemu-xhci",
++      "parent": "base-xhci"
++    },
++    {
++      "name": "lsi53c895a",
++      "parent": "pci-device"
++    },
++    {
++      "name": "kvm-ioapic",
++      "parent": "ioapic-common"
++    },
++    {
++      "name": "cpu-cluster",
++      "parent": "device"
++    },
++    {
++      "name": "virtio-keyboard-pci",
++      "parent": "virtio-input-hid-pci"
++    },
++    {
++      "name": "xen-sysbus",
++      "parent": "bus"
++    },
++    {
++      "name": "xen-bus",
++      "parent": "bus"
++    },
++    {
++      "name": "i440FX",
++      "parent": "pci-device"
++    },
++    {
++      "name": "ide-hd",
++      "parent": "ide-device"
++    },
++    {
++      "name": "Opteron_G1-x86_64-cpu",
++      "parent": "x86_64-cpu"
++    },
++    {
++      "name": "kvm64-x86_64-cpu",
++      "parent": "x86_64-cpu"
++    },
++    {
++      "name": "vhost-scsi-pci-non-transitional",
++      "parent": "vhost-scsi-pci-base"
++    },
++    {
++      "name": "virtio-net-device",
++      "parent": "virtio-device"
++    },
++    {
++      "name": "kvm-i8259",
++      "parent": "pic-common"
++    },
++    {
++      "name": "virtio-9p-pci-non-transitional",
++      "parent": "virtio-9p-pci-base"
++    },
++    {
++      "name": "chardev-pty",
++      "parent": "chardev"
++    },
++    {
++      "name": "xen-apic",
++      "parent": "apic-common"
++    },
++    {
++      "name": "SUNW,fdtwo",
++      "parent": "base-sysbus-fdc"
++    },
++    {
++      "name": "isa-pcspk",
++      "parent": "isa-device"
++    },
++    {
++      "name": "Haswell-IBRS-x86_64-cpu",
++      "parent": "x86_64-cpu"
++    },
++    {
++      "name": "pc-q35-4.1-machine",
++      "parent": "generic-pc-machine"
++    },
++    {
++      "name": "loader",
++      "parent": "device"
++    },
++    {
++      "name": "filter-rewriter",
++      "parent": "netfilter"
++    },
++    {
++      "name": "pc-q35-4.0-machine",
++      "parent": "generic-pc-machine"
++    },
++    {
++      "name": "virtio-serial-pci",
++      "parent": "virtio-serial-pci-base"
++    },
++    {
++      "name": "Nehalem-IBRS-x86_64-cpu",
++      "parent": "x86_64-cpu"
++    },
++    {
++      "name": "pc-0.12-machine",
++      "parent": "generic-pc-machine"
++    },
++    {
++      "name": "pcie-root-port",
++      "parent": "pcie-root-port-base"
++    },
++    {
++      "name": "virtio-crypto-device",
++      "parent": "virtio-device"
++    },
++    {
++      "name": "usb-host",
++      "parent": "usb-device"
++    },
++    {
++      "name": "Icelake-Client-x86_64-cpu",
++      "parent": "x86_64-cpu"
++    },
++    {
++      "name": "usb-bt-dongle",
++      "parent": "usb-device"
++    },
++    {
++      "name": "igd-passthrough-isa-bridge",
++      "parent": "pci-device"
++    },
++    {
++      "name": "usb-mtp",
++      "parent": "usb-device"
++    },
++    {
++      "name": "qemu64-x86_64-cpu",
++      "parent": "x86_64-cpu"
++    },
++    {
++      "name": "virtio-input-host-pci",
++      "parent": "virtio-input-pci"
++    },
++    {
++      "name": "pc-i440fx-2.10-machine",
++      "parent": "generic-pc-machine"
++    },
++    {
++      "name": "phenom-x86_64-cpu",
++      "parent": "x86_64-cpu"
++    },
++    {
++      "name": "e1000",
++      "parent": "e1000-base"
++    },
++    {
++      "name": "PIIX3-xen",
++      "parent": "pci-piix3"
++    },
++    {
++      "name": "sysbus-ahci",
++      "parent": "sys-bus-device"
++    },
++    {
++      "name": "ccid-card-emulated",
++      "parent": "ccid-card"
++    },
++    {
++      "name": "ich9-usb-uhci5",
++      "parent": "pci-uhci-usb"
++    },
++    {
++      "name": "pc-i440fx-1.4-machine",
++      "parent": "generic-pc-machine"
++    },
++    {
++      "name": "ICH9-LPC",
++      "parent": "pci-device"
++    },
++    {
++      "name": "pc-q35-2.6-machine",
++      "parent": "generic-pc-machine"
++    },
++    {
++      "name": "ich9-usb-uhci6",
++      "parent": "pci-uhci-usb"
++    },
++    {
++      "name": "ich9-usb-uhci4",
++      "parent": "pci-uhci-usb"
++    },
++    {
++      "name": "chardev-spicevmc",
++      "parent": "chardev-spice"
++    },
++    {
++      "name": "ich9-usb-uhci3",
++      "parent": "pci-uhci-usb"
++    },
++    {
++      "name": "ich9-usb-uhci2",
++      "parent": "pci-uhci-usb"
++    },
++    {
++      "name": "ich9-usb-uhci1",
++      "parent": "pci-uhci-usb"
++    },
++    {
++      "name": "tls-creds-psk",
++      "parent": "tls-creds"
++    },
++    {
++      "name": "tpci200",
++      "parent": "pci-device"
++    },
++    {
++      "name": "memory-backend-file",
++      "parent": "memory-backend"
++    },
++    {
++      "name": "pc-q35-2.5-machine",
++      "parent": "generic-pc-machine"
++    },
++    {
++      "name": "AMDVI-PCI",
++      "parent": "pci-device"
++    },
++    {
++      "name": "filter-redirector",
++      "parent": "netfilter"
++    },
++    {
++      "name": "rtl8139",
++      "parent": "pci-device"
++    },
++    {
++      "name": "chardev-hci",
++      "parent": "chardev"
++    },
++    {
++      "name": "pc-q35-2.4-machine",
++      "parent": "generic-pc-machine"
++    },
++    {
++      "name": "container",
++      "parent": "object"
++    },
++    {
++      "name": "pc-i440fx-3.1-machine",
++      "parent": "generic-pc-machine"
++    },
++    {
++      "name": "megasas",
++      "parent": "megasas-base"
++    },
++    {
++      "name": "base-x86_64-cpu",
++      "parent": "x86_64-cpu"
++    },
++    {
++      "name": "virtio-balloon-pci-non-transitional",
++      "parent": "virtio-balloon-pci-base"
++    },
++    {
++      "name": "qxl-vga",
++      "parent": "pci-qxl"
++    },
++    {
++      "name": "scsi-block",
++      "parent": "scsi-disk-base"
++    },
++    {
++      "name": "Opteron_G2-x86_64-cpu",
++      "parent": "x86_64-cpu"
++    },
++    {
++      "name": "unimplemented-device",
++      "parent": "sys-bus-device"
++    },
++    {
++      "name": "vhost-user-input",
++      "parent": "virtio-input-device"
++    },
++    {
++      "name": "tls-creds-anon",
++      "parent": "tls-creds"
++    },
++    {
++      "name": "pc-i440fx-3.0-machine",
++      "parent": "generic-pc-machine"
++    },
++    {
++      "name": "scsi-cd",
++      "parent": "scsi-disk-base"
++    },
++    {
++      "name": "pxb-bus",
++      "parent": "PCI"
++    },
++    {
++      "name": "pc-0.14-machine",
++      "parent": "generic-pc-machine"
++    },
++    {
++      "name": "accel",
++      "parent": "object"
++    },
++    {
++      "name": "floppy-bus",
++      "parent": "bus"
++    },
++    {
++      "name": "usb-audio",
++      "parent": "usb-device"
++    },
++    {
++      "name": "virtio-vga",
++      "parent": "virtio-vga-base"
++    },
++    {
++      "name": "pc-i440fx-2.12-machine",
++      "parent": "generic-pc-machine"
++    },
++    {
++      "name": "vmware-svga",
++      "parent": "pci-device"
++    },
++    {
++      "name": "pc-0.13-machine",
++      "parent": "generic-pc-machine"
++    },
++    {
++      "name": "isa-serial",
++      "parent": "isa-device"
++    },
++    {
++      "name": "virtio-serial-device",
++      "parent": "virtio-device"
++    },
++    {
++      "name": "isa-debug-exit",
++      "parent": "isa-device"
++    },
++    {
++      "name": "vhost-scsi-pci",
++      "parent": "vhost-scsi-pci-base"
++    },
++    {
++      "name": "chardev-gdb",
++      "parent": "chardev"
++    },
++    {
++      "name": "fdc37m81x-superio",
++      "parent": "isa-superio"
++    },
++    {
++      "name": "pc-testdev",
++      "parent": "isa-device"
++    },
++    {
++      "name": "xen-backend",
++      "parent": "xen-sysdev"
++    },
++    {
++      "name": "Haswell-noTSX-IBRS-x86_64-cpu",
++      "parent": "x86_64-cpu"
++    },
++    {
++      "name": "pr-manager-helper",
++      "parent": "pr-manager"
++    },
++    {
++      "name": "fw_cfg_mem",
++      "parent": "fw_cfg"
++    },
++    {
++      "name": "virtio-scsi-pci-transitional",
++      "parent": "virtio-scsi-pci-base"
++    },
++    {
++      "name": "usb-uas",
++      "parent": "usb-device"
++    },
++    {
++      "name": "ide-cd",
++      "parent": "ide-device"
++    },
++    {
++      "name": "pc-q35-2.8-machine",
++      "parent": "generic-pc-machine"
++    },
++    {
++      "name": "pc-i440fx-2.11-machine",
++      "parent": "generic-pc-machine"
++    },
++    {
++      "name": "pc-i440fx-1.6-machine",
++      "parent": "generic-pc-machine"
++    },
++    {
++      "name": "virtio-balloon-pci",
++      "parent": "virtio-balloon-pci-base"
++    },
++    {
++      "name": "chardev-socket",
++      "parent": "chardev"
++    },
++    {
++      "name": "iothread",
++      "parent": "object"
++    },
++    {
++      "name": "sb16",
++      "parent": "isa-device"
++    },
++    {
++      "name": "chardev-mux",
++      "parent": "chardev"
++    },
++    {
++      "name": "pc-q35-2.7-machine",
++      "parent": "generic-pc-machine"
++    },
++    {
++      "name": "pc-i440fx-1.5-machine",
++      "parent": "generic-pc-machine"
++    },
++    {
++      "name": "486-x86_64-cpu",
++      "parent": "x86_64-cpu"
++    },
++    {
++      "name": "bochs-display",
++      "parent": "pci-device"
++    },
++    {
++      "name": "usb-ccid",
++      "parent": "usb-device"
++    },
++    {
++      "name": "isa-cirrus-vga",
++      "parent": "isa-device"
++    },
++    {
++      "name": "qio-channel-rdma",
++      "parent": "qio-channel"
++    },
++    {
++      "name": "vhost-vsock-device",
++      "parent": "virtio-device"
++    },
++    {
++      "name": "sdhci-pci",
++      "parent": "pci-device"
++    },
++    {
++      "name": "virtio-input-host-device",
++      "parent": "virtio-input-device"
++    },
++    {
++      "name": "i82559er",
++      "parent": "pci-device"
++    },
++    {
++      "name": "pci-bridge",
++      "parent": "base-pci-bridge"
++    },
++    {
++      "name": "cs4231a",
++      "parent": "isa-device"
++    },
++    {
++      "name": "ivshmem-doorbell",
++      "parent": "ivshmem-common"
++    },
++    {
++      "name": "chardev-udp",
++      "parent": "chardev"
++    },
++    {
++      "name": "virtio-rng-device",
++      "parent": "virtio-device"
++    },
++    {
++      "name": "isa-parallel",
++      "parent": "isa-device"
++    },
++    {
++      "name": "piix4-ide",
++      "parent": "pci-ide"
++    },
++    {
++      "name": "adlib",
++      "parent": "isa-device"
++    },
++    {
++      "name": "pc-0.15-machine",
++      "parent": "generic-pc-machine"
++    },
++    {
++      "name": "authz-list-file",
++      "parent": "authz"
++    },
++    {
++      "name": "kvmvapic",
++      "parent": "sys-bus-device"
++    },
++    {
++      "name": "hda-micro",
++      "parent": "hda-audio"
++    },
++    {
++      "name": "pci-bridge-seat",
++      "parent": "pci-bridge"
++    },
++    {
++      "name": "dc390",
++      "parent": "am53c974"
++    },
++    {
++      "name": "chardev-pipe",
++      "parent": "chardev-fd"
++    },
++    {
++      "name": "qemu,register",
++      "parent": "device"
++    },
++    {
++      "name": "IDE",
++      "parent": "bus"
++    },
++    {
++      "name": "fw_cfg_io",
++      "parent": "fw_cfg"
++    },
++    {
++      "name": "tpm-crb",
++      "parent": "device"
++    },
++    {
++      "name": "am53c974",
++      "parent": "pci-device"
++    },
++    {
++      "name": "memory-backend-ram",
++      "parent": "memory-backend"
++    },
++    {
++      "name": "xen-cdrom",
++      "parent": "xen-block"
++    },
++    {
++      "name": "virtio-blk-device",
++      "parent": "virtio-device"
++    },
++    {
++      "name": "pc-q35-2.9-machine",
++      "parent": "generic-pc-machine"
++    },
++    {
++      "name": "nvdimm",
++      "parent": "pc-dimm"
++    },
++    {
++      "name": "mc146818rtc",
++      "parent": "isa-device"
++    },
++    {
++      "name": "qio-channel-websock",
++      "parent": "qio-channel"
++    },
++    {
++      "name": "qio-channel-file",
++      "parent": "qio-channel"
++    },
++    {
++      "name": "chardev-msmouse",
++      "parent": "chardev"
++    },
++    {
++      "name": "pc-i440fx-1.7-machine",
++      "parent": "generic-pc-machine"
++    },
++    {
++      "name": "pc-q35-4.0.1-machine",
++      "parent": "generic-pc-machine"
++    },
++    {
++      "name": "cryptodev-backend-builtin",
++      "parent": "cryptodev-backend"
++    },
++    {
++      "name": "hda-output",
++      "parent": "hda-audio"
++    },
++    {
++      "name": "KnightsMill-x86_64-cpu",
++      "parent": "x86_64-cpu"
++    },
++    {
++      "name": "chardev-spiceport",
++      "parent": "chardev-spice"
++    },
++    {
++      "name": "VGA",
++      "parent": "pci-vga"
++    },
++    {
++      "name": "vfio-pci-nohotplug",
++      "parent": "vfio-pci"
++    },
++    {
++      "name": "sga",
++      "parent": "isa-device"
++    },
++    {
++      "name": "i8257",
++      "parent": "isa-device"
++    },
++    {
++      "name": "qio-net-listener",
++      "parent": "object"
++    },
++    {
++      "name": "port92",
++      "parent": "isa-device"
++    },
++    {
++      "name": "mptsas1068",
++      "parent": "pci-device"
++    },
++    {
++      "name": "edu",
++      "parent": "pci-device"
++    },
++    {
++      "name": "Dhyana-x86_64-cpu",
++      "parent": "x86_64-cpu"
++    },
++    {
++      "name": "virtio-mouse-pci",
++      "parent": "virtio-input-hid-pci"
++    },
++    {
++      "name": "Skylake-Client-x86_64-cpu",
++      "parent": "x86_64-cpu"
++    },
++    {
++      "name": "ICH9 SMB",
++      "parent": "pci-device"
++    },
++    {
++      "name": "Broadwell-x86_64-cpu",
++      "parent": "x86_64-cpu"
++    },
++    {
++      "name": "vfio-pci-igd-lpc-bridge",
++      "parent": "pci-device"
++    },
++    {
++      "name": "HDA",
++      "parent": "bus"
++    },
++    {
++      "name": "n270-x86_64-cpu",
++      "parent": "x86_64-cpu"
++    },
++    {
++      "name": "usb-redir",
++      "parent": "usb-device"
++    },
++    {
++      "name": "pcm3680_pci",
++      "parent": "pci-device"
++    },
++    {
++      "name": "floppy",
++      "parent": "device"
++    },
++    {
++      "name": "qemu:memory-region",
++      "parent": "object"
++    },
++    {
++      "name": "mioe3680_pci",
++      "parent": "pci-device"
++    },
++    {
++      "name": "sysbus-ohci",
++      "parent": "sys-bus-device"
++    },
++    {
++      "name": "chardev-ringbuf",
++      "parent": "chardev"
++    },
++    {
++      "name": "max-x86_64-cpu",
++      "parent": "x86_64-cpu"
++    },
++    {
++      "name": "can-bus",
++      "parent": "object"
++    },
++    {
++      "name": "qtest-accel",
++      "parent": "accel"
++    },
++    {
++      "name": "qio-channel-command",
++      "parent": "qio-channel"
++    },
++    {
++      "name": "pxb-host",
++      "parent": "pci-host-bridge"
++    },
++    {
++      "name": "IvyBridge-x86_64-cpu",
++      "parent": "x86_64-cpu"
++    },
++    {
++      "name": "vhost-user-gpu",
++      "parent": "virtio-gpu-base"
++    },
++    {
++      "name": "xio3130-downstream",
++      "parent": "pcie-slot"
++    },
++    {
++      "name": "virtio-gpu-device",
++      "parent": "virtio-gpu-base"
++    },
++    {
++      "name": "virtio-blk-pci",
++      "parent": "virtio-blk-pci-base"
++    },
++    {
++      "name": "cirrus-vga",
++      "parent": "pci-device"
++    },
++    {
++      "name": "isa-ipmi-kcs",
++      "parent": "isa-device"
++    },
++    {
++      "name": "kvmclock",
++      "parent": "sys-bus-device"
++    },
++    {
++      "name": "cryptodev-vhost-user",
++      "parent": "cryptodev-backend"
++    },
++    {
++      "name": "Opteron_G3-x86_64-cpu",
++      "parent": "x86_64-cpu"
++    },
++    {
++      "name": "lsi53c810",
++      "parent": "lsi53c895a"
++    },
++    {
++      "name": "System",
++      "parent": "bus"
++    },
++    {
++      "name": "Westmere-IBRS-x86_64-cpu",
++      "parent": "x86_64-cpu"
++    },
++    {
++      "name": "usb-serial",
++      "parent": "usb-serial-dev"
++    },
++    {
++      "name": "Cascadelake-Server-x86_64-cpu",
++      "parent": "x86_64-cpu"
++    },
++    {
++      "name": "vt82c686b-usb-uhci",
++      "parent": "pci-uhci-usb"
++    },
++    {
++      "name": "chardev-braille",
++      "parent": "chardev"
++    },
++    {
++      "name": "chardev-file",
++      "parent": "chardev-fd"
++    },
++    {
++      "name": "vhost-user-scsi-pci-non-transitional",
++      "parent": "vhost-user-scsi-pci-base"
++    },
++    {
++      "name": "xen-sysdev",
++      "parent": "sys-bus-device"
++    },
++    {
++      "name": "intel-iommu",
++      "parent": "x86-iommu"
++    },
++    {
++      "name": "pc-q35-2.10-machine",
++      "parent": "generic-pc-machine"
++    },
++    {
++      "name": "tpm-tis",
++      "parent": "isa-device"
++    },
++    {
++      "name": "PCIE",
++      "parent": "PCI"
++    },
++    {
++      "name": "pcie-pci-bridge",
++      "parent": "base-pci-bridge"
++    },
++    {
++      "name": "ccid-card-passthru",
++      "parent": "ccid-card"
++    },
++    {
++      "name": "qio-dns-resolver",
++      "parent": "object"
++    },
++    {
++      "name": "vhost-user-blk-pci",
++      "parent": "vhost-user-blk-pci-base"
++    },
++    {
++      "name": "virtio-net-pci-transitional",
++      "parent": "virtio-net-pci-base"
++    },
++    {
++      "name": "virtio-serial-bus",
++      "parent": "bus"
++    },
++    {
++      "name": "kvm-pit",
++      "parent": "pit-common"
++    },
++    {
++      "name": "secondary-vga",
++      "parent": "pci-vga"
++    },
++    {
++      "name": "vhost-scsi",
++      "parent": "vhost-scsi-common"
++    },
++    {
++      "name": "pci-ohci",
++      "parent": "pci-device"
++    },
++    {
++      "name": "cfi.pflash01",
++      "parent": "sys-bus-device"
++    },
++    {
++      "name": "usb-hub",
++      "parent": "usb-device"
++    },
++    {
++      "name": "ccid-bus",
++      "parent": "bus"
++    },
++    {
++      "name": "xenpv-machine",
++      "parent": "machine"
++    },
++    {
++      "name": "EPYC-IBPB-x86_64-cpu",
++      "parent": "x86_64-cpu"
++    },
++    {
++      "name": "input-linux",
++      "parent": "object"
++    },
++    {
++      "name": "piix3-ide-xen",
++      "parent": "pci-ide"
++    },
++    {
++      "name": "vmgenid",
++      "parent": "device"
++    },
++    {
++      "name": "virtio-rng-pci-transitional",
++      "parent": "virtio-rng-pci-base"
++    },
++    {
++      "name": "virtio-serial-pci-transitional",
++      "parent": "virtio-serial-pci-base"
++    },
++    {
++      "name": "ati-vga",
++      "parent": "pci-device"
++    },
++    {
++      "name": "pc-q35-3.0-machine",
++      "parent": "generic-pc-machine"
++    },
++    {
++      "name": "pci-serial",
++      "parent": "pci-device"
++    },
++    {
++      "name": "vmport",
++      "parent": "isa-device"
++    },
++    {
++      "name": "vhost-user-scsi-pci",
++      "parent": "vhost-user-scsi-pci-base"
++    },
++    {
++      "name": "ipmi-bmc-extern",
++      "parent": "ipmi-bmc"
++    },
++    {
++      "name": "PIIX4_PM",
++      "parent": "pci-device"
++    },
++    {
++      "name": "i8042",
++      "parent": "isa-device"
++    },
++    {
++      "name": "coreduo-x86_64-cpu",
++      "parent": "x86_64-cpu"
++    },
++    {
++      "name": "i82559c",
++      "parent": "pci-device"
++    },
++    {
++      "name": "i82559b",
++      "parent": "pci-device"
++    },
++    {
++      "name": "i82559a",
++      "parent": "pci-device"
++    },
++    {
++      "name": "virtio-blk-pci-non-transitional",
++      "parent": "virtio-blk-pci-base"
++    },
++    {
++      "name": "pc-q35-2.12-machine",
++      "parent": "generic-pc-machine"
++    },
++    {
++      "name": "SCSI",
++      "parent": "bus"
++    },
++    {
++      "name": "rocker",
++      "parent": "pci-device"
++    },
++    {
++      "name": "pcnet",
++      "parent": "pci-device"
++    },
++    {
++      "name": "rng-egd",
++      "parent": "rng-backend"
++    },
++    {
++      "name": "Skylake-Server-IBRS-x86_64-cpu",
++      "parent": "x86_64-cpu"
++    },
++    {
++      "name": "Opteron_G4-x86_64-cpu",
++      "parent": "x86_64-cpu"
++    },
++    {
++      "name": "pc-q35-2.11-machine",
++      "parent": "generic-pc-machine"
++    },
++    {
++      "name": "chardev-testdev",
++      "parent": "chardev"
++    },
++    {
++      "name": "PIIX3",
++      "parent": "pci-piix3"
++    },
++    {
++      "name": "filter-dump",
++      "parent": "netfilter"
++    },
++    {
++      "name": "migration",
++      "parent": "device"
++    },
++    {
++      "name": "vmmouse",
++      "parent": "isa-device"
++    },
++    {
++      "name": "i82558b",
++      "parent": "pci-device"
++    },
++    {
++      "name": "i82558a",
++      "parent": "pci-device"
++    },
++    {
++      "name": "ioapic",
++      "parent": "ioapic-common"
++    },
++    {
++      "name": "smbus-eeprom",
++      "parent": "smbus-device"
++    },
++    {
++      "name": "Haswell-x86_64-cpu",
++      "parent": "x86_64-cpu"
++    },
++    {
++      "name": "i82801",
++      "parent": "pci-device"
++    },
++    {
++      "name": "tls-creds-x509",
++      "parent": "tls-creds"
++    },
++    {
++      "name": "virtio-net-pci",
++      "parent": "virtio-net-pci-base"
++    },
++    {
++      "name": "virtio-keyboard-device",
++      "parent": "virtio-input-hid-device"
++    },
++    {
++      "name": "i82562",
++      "parent": "pci-device"
++    },
++    {
++      "name": "Haswell-noTSX-x86_64-cpu",
++      "parent": "x86_64-cpu"
++    },
++    {
++      "name": "usb-net",
++      "parent": "usb-device"
++    },
++    {
++      "name": "tpm-passthrough",
++      "parent": "tpm-backend"
++    },
++    {
++      "name": "q35-pcihost",
++      "parent": "pcie-host-bridge"
++    },
++    {
++      "name": "amd-iommu",
++      "parent": "x86-iommu"
++    },
++    {
++      "name": "i440FX-pcihost",
++      "parent": "pci-host-bridge"
++    },
++    {
++      "name": "i82557c",
++      "parent": "pci-device"
++    },
++    {
++      "name": "i82557b",
++      "parent": "pci-device"
++    },
++    {
++      "name": "i82557a",
++      "parent": "pci-device"
++    },
++    {
++      "name": "chardev-memory",
++      "parent": "chardev-ringbuf"
++    },
++    {
++      "name": "isa-i8259",
++      "parent": "pic-common"
++    },
++    {
++      "name": "virtio-gpu-pci",
++      "parent": "virtio-gpu-pci-base"
++    },
++    {
++      "name": "pc-i440fx-2.0-machine",
++      "parent": "generic-pc-machine"
++    },
++    {
++      "name": "SandyBridge-x86_64-cpu",
++      "parent": "x86_64-cpu"
++    },
++    {
++      "name": "split-irq",
++      "parent": "device"
++    },
++    {
++      "name": "usb-mouse",
++      "parent": "usb-hid"
++    },
++    {
++      "name": "i82551",
++      "parent": "pci-device"
++    },
++    {
++      "name": "sdhci-bus",
++      "parent": "sd-bus"
++    },
++    {
++      "name": "i82550",
++      "parent": "pci-device"
++    },
++    {
++      "name": "pc-q35-3.1-machine",
++      "parent": "generic-pc-machine"
++    },
++    {
++      "name": "host-x86_64-cpu",
++      "parent": "max-x86_64-cpu"
++    },
++    {
++      "name": "virtio-crypto-pci",
++      "parent": "virtio-pci"
++    },
++    {
++      "name": "ich9-usb-ehci2",
++      "parent": "pci-ehci-usb"
++    },
++    {
++      "name": "vfio-pci",
++      "parent": "pci-device"
++    },
++    {
++      "name": "ich9-usb-ehci1",
++      "parent": "pci-ehci-usb"
++    },
++    {
++      "name": "filter-mirror",
++      "parent": "netfilter"
++    },
++    {
++      "name": "xen-disk",
++      "parent": "xen-block"
++    },
++    {
++      "name": "isa-ide",
++      "parent": "isa-device"
++    },
++    {
++      "name": "irq",
++      "parent": "object"
++    },
++    {
++      "name": "throttle-group",
++      "parent": "object"
++    },
++    {
++      "name": "IvyBridge-IBRS-x86_64-cpu",
++      "parent": "x86_64-cpu"
++    },
++    {
++      "name": "memory-backend-memfd",
++      "parent": "memory-backend"
++    },
++    {
++      "name": "can-host-socketcan",
++      "parent": "can-host"
++    },
++    {
++      "name": "qio-channel-socket",
++      "parent": "qio-channel"
++    },
++    {
++      "name": "nec-usb-xhci",
++      "parent": "base-xhci"
++    },
++    {
++      "name": "virtio-serial-pci-non-transitional",
++      "parent": "virtio-serial-pci-base"
++    },
++    {
++      "name": "virtio-rng-pci-non-transitional",
++      "parent": "virtio-rng-pci-base"
++    },
++    {
++      "name": "piix3-usb-uhci",
++      "parent": "pci-uhci-usb"
++    },
++    {
++      "name": "virtserialport",
++      "parent": "virtio-serial-port"
++    },
++    {
++      "name": "pvscsi",
++      "parent": "pci-device"
++    },
++    {
++      "name": "sd-bus",
++      "parent": "bus"
++    },
++    {
++      "name": "Opteron_G5-x86_64-cpu",
++      "parent": "x86_64-cpu"
++    },
++    {
++      "name": "ich9-ahci",
++      "parent": "pci-device"
++    },
++    {
++      "name": "chardev-stdio",
++      "parent": "chardev-fd"
++    },
++    {
++      "name": "Skylake-Client-IBRS-x86_64-cpu",
++      "parent": "x86_64-cpu"
++    },
++    {
++      "name": "pc-dimm",
++      "parent": "device"
++    },
++    {
++      "name": "gus",
++      "parent": "isa-device"
++    },
++    {
++      "name": "vhost-vsock-pci-non-transitional",
++      "parent": "vhost-vsock-pci-base"
++    },
++    {
++      "name": "hyperv-testdev",
++      "parent": "isa-device"
++    },
++    {
++      "name": "isa-vga",
++      "parent": "isa-device"
++    },
++    {
++      "name": "pc-i440fx-2.2-machine",
++      "parent": "generic-pc-machine"
++    },
++    {
++      "name": "xen-pci-passthrough",
++      "parent": "pci-device"
++    },
++    {
++      "name": "cryptodev-backend",
++      "parent": "object"
++    },
++    {
++      "name": "IndustryPack",
++      "parent": "bus"
++    },
++    {
++      "name": "pc-i440fx-2.1-machine",
++      "parent": "generic-pc-machine"
++    },
++    {
++      "name": "pc-i440fx-4.0-machine",
++      "parent": "generic-pc-machine"
++    },
++    {
++      "name": "Icelake-Server-x86_64-cpu",
++      "parent": "x86_64-cpu"
++    },
++    {
++      "name": "or-irq",
++      "parent": "device"
++    },
++    {
++      "name": "ipmi-bmc-sim",
++      "parent": "ipmi-bmc"
++    },
++    {
++      "name": "Broadwell-noTSX-x86_64-cpu",
++      "parent": "x86_64-cpu"
++    },
++    {
++      "name": "usb-ehci",
++      "parent": "pci-ehci-usb"
++    },
++    {
++      "name": "pentium2-x86_64-cpu",
++      "parent": "x86_64-cpu"
++    },
++    {
++      "name": "chardev-vc",
++      "parent": "chardev"
++    },
++    {
++      "name": "virtio-rng-pci",
++      "parent": "virtio-rng-pci-base"
++    },
++    {
++      "name": "filter-replay",
++      "parent": "netfilter"
++    },
++    {
++      "name": "vhost-user-vga",
++      "parent": "virtio-vga-base"
++    },
++    {
++      "name": "vhost-user-blk-pci-transitional",
++      "parent": "vhost-user-blk-pci-base"
++    },
++    {
++      "name": "e1000-82545em",
++      "parent": "e1000-base"
++    },
++    {
++      "name": "chardev-wctablet",
++      "parent": "chardev"
++    },
++    {
++      "name": "vhost-user-gpu-pci",
++      "parent": "virtio-gpu-pci-base"
++    },
++    {
++      "name": "hyperv-synic",
++      "parent": "device"
++    },
++    {
++      "name": "pc-i440fx-2.5-machine",
++      "parent": "generic-pc-machine"
++    },
++    {
++      "name": "e1000-82544gc",
++      "parent": "e1000-base"
++    },
++    {
++      "name": "hpet",
++      "parent": "sys-bus-device"
++    },
++    {
++      "name": "Broadwell-noTSX-IBRS-x86_64-cpu",
++      "parent": "x86_64-cpu"
++    },
++    {
++      "name": "ioh3420",
++      "parent": "pcie-root-port-base"
++    },
++    {
++      "name": "pc-i440fx-2.4-machine",
++      "parent": "generic-pc-machine"
++    },
++    {
++      "name": "virtio-9p-pci",
++      "parent": "virtio-9p-pci-base"
++    },
++    {
++      "name": "vmcoreinfo",
++      "parent": "device"
++    },
++    {
++      "name": "filter-buffer",
++      "parent": "netfilter"
++    },
++    {
++      "name": "pci-serial-4x",
++      "parent": "pci-device"
++    },
++    {
++      "name": "athlon-x86_64-cpu",
++      "parent": "x86_64-cpu"
++    },
++    {
++      "name": "ich9-intel-hda",
++      "parent": "intel-hda-generic"
++    },
++    {
++      "name": "pc-i440fx-2.3-machine",
++      "parent": "generic-pc-machine"
++    },
++    {
++      "name": "virtio-9p-device",
++      "parent": "virtio-device"
++    },
++    {
++      "name": "imx-usdhc",
++      "parent": "generic-sdhci"
++    },
++    {
++      "name": "pc-i440fx-4.1-machine",
++      "parent": "generic-pc-machine"
++    },
++    {
++      "name": "vhost-user-blk-pci-non-transitional",
++      "parent": "vhost-user-blk-pci-base"
++    },
++    {
++      "name": "xen-bridge",
++      "parent": "sys-bus-device"
++    },
++    {
++      "name": "vhost-user-backend",
++      "parent": "object"
++    },
++    {
++      "name": "isa-ipmi-bt",
++      "parent": "isa-device"
++    },
++    {
++      "name": "ipoctal232",
++      "parent": "ipack-device"
++    },
++    {
++      "name": "virtio-tablet-device",
++      "parent": "virtio-input-hid-device"
++    },
++    {
++      "name": "virtio-scsi-pci",
++      "parent": "virtio-scsi-pci-base"
++    },
++    {
++      "name": "piix3-ide",
++      "parent": "pci-ide"
++    },
++    {
++      "name": "virtio-pci-bus",
++      "parent": "virtio-bus"
++    },
++    {
++      "name": "xen-pvdevice",
++      "parent": "pci-device"
++    },
++    {
++      "name": "ES1370",
++      "parent": "pci-device"
++    },
++    {
++      "name": "x3130-upstream",
++      "parent": "pcie-port"
++    },
++    {
++      "name": "xenfv-machine",
++      "parent": "generic-pc-machine"
++    },
++    {
++      "name": "pci-testdev",
++      "parent": "pci-device"
++    },
++    {
++      "name": "qemu-console",
++      "parent": "object"
++    },
++    {
++      "name": "ISA",
++      "parent": "bus"
++    },
++    {
++      "name": "piix4-usb-uhci",
++      "parent": "pci-uhci-usb"
++    },
++    {
++      "name": "virtio-balloon-pci-transitional",
++      "parent": "virtio-balloon-pci-base"
++    },
++    {
++      "name": "pc-i440fx-2.7-machine",
++      "parent": "generic-pc-machine"
++    },
++    {
++      "name": "tcg-accel",
++      "parent": "accel"
++    },
++    {
++      "name": "virtconsole",
++      "parent": "virtserialport"
++    },
++    {
++      "name": "pci-serial-2x",
++      "parent": "pci-device"
++    },
++    {
++      "name": "pentium3-x86_64-cpu",
++      "parent": "x86_64-cpu"
++    },
++    {
++      "name": "vhost-user-scsi-pci-transitional",
++      "parent": "vhost-user-scsi-pci-base"
++    },
++    {
++      "name": "ne2k_isa",
++      "parent": "isa-device"
++    },
++    {
++      "name": "isa-fdc",
++      "parent": "isa-device"
++    },
++    {
++      "name": "Nehalem-x86_64-cpu",
++      "parent": "x86_64-cpu"
++    },
++    {
++      "name": "pc-i440fx-2.6-machine",
++      "parent": "generic-pc-machine"
++    },
++    {
++      "name": "xen-platform",
++      "parent": "pci-device"
++    },
++    {
++      "name": "chardev-serial",
++      "parent": "chardev-fd"
++    },
++    {
++      "name": "authz-pam",
++      "parent": "authz"
++    },
++    {
++      "name": "igd-passthrough-i440FX",
++      "parent": "i440FX"
++    },
++    {
++      "name": "colo-compare",
++      "parent": "object"
++    },
++    {
++      "name": "virtio-tablet-pci",
++      "parent": "virtio-input-hid-pci"
++    },
++    {
++      "name": "e1000e",
++      "parent": "pci-device"
++    },
++    {
++      "name": "usb-bus",
++      "parent": "bus"
++    },
++    {
++      "name": "i82801b11-bridge",
++      "parent": "base-pci-bridge"
++    },
++    {
++      "name": "PCI",
++      "parent": "bus"
++    },
++    {
++      "name": "usb-storage",
++      "parent": "usb-storage-dev"
++    },
++    {
++      "name": "vhost-user-scsi",
++      "parent": "vhost-scsi-common"
++    },
++    {
++      "name": "mch",
++      "parent": "pci-device"
++    },
++    {
++      "name": "ib700",
++      "parent": "isa-device"
++    },
++    {
++      "name": "tpm-emulator",
++      "parent": "tpm-backend"
++    },
++    {
++      "name": "esp",
++      "parent": "sys-bus-device"
++    },
++    {
++      "name": "isabus-bridge",
++      "parent": "sys-bus-device"
++    },
++    {
++      "name": "qemu32-x86_64-cpu",
++      "parent": "x86_64-cpu"
++    },
++    {
++      "name": "ne2k_pci",
++      "parent": "pci-device"
++    },
++    {
++      "name": "Broadwell-IBRS-x86_64-cpu",
++      "parent": "x86_64-cpu"
++    },
++    {
++      "name": "vhost-user-blk",
++      "parent": "virtio-device"
++    },
++    {
++      "name": "ivshmem-plain",
++      "parent": "ivshmem-common"
++    },
++    {
++      "name": "usb-kbd",
++      "parent": "usb-hid"
++    },
++    {
++      "name": "isa-applesmc",
++      "parent": "isa-device"
++    },
++    {
++      "name": "xen-accel",
++      "parent": "accel"
++    },
++    {
++      "name": "secret",
++      "parent": "object"
++    },
++    {
++      "name": "hda-duplex",
++      "parent": "hda-audio"
++    },
++    {
++      "name": "authz-simple",
++      "parent": "authz"
++    },
++    {
++      "name": "kvm32-x86_64-cpu",
++      "parent": "x86_64-cpu"
++    },
++    {
++      "name": "virtio-9p-pci-transitional",
++      "parent": "virtio-9p-pci-base"
++    },
++    {
++      "name": "pc-i440fx-2.9-machine",
++      "parent": "generic-pc-machine"
++    },
++    {
++      "name": "kvm-apic",
++      "parent": "apic-common"
++    },
++    {
++      "name": "sev-guest",
++      "parent": "object"
++    },
++    {
++      "name": "virtio-balloon-device",
++      "parent": "virtio-device"
++    },
++    {
++      "name": "none-machine",
++      "parent": "machine"
++    },
++    {
++      "name": "sysbus-fdc",
++      "parent": "base-sysbus-fdc"
++    },
++    {
++      "name": "ramfb",
++      "parent": "sys-bus-device"
++    },
++    {
++      "name": "megasas-gen2",
++      "parent": "megasas-base"
++    },
++    {
++      "name": "usb-tablet",
++      "parent": "usb-hid"
++    },
++    {
++      "name": "pc-1.0-machine",
++      "parent": "generic-pc-machine"
++    },
++    {
++      "name": "vhost-scsi-pci-transitional",
++      "parent": "vhost-scsi-pci-base"
++    },
++    {
++      "name": "core2duo-x86_64-cpu",
++      "parent": "x86_64-cpu"
++    },
++    {
++      "name": "qxl",
++      "parent": "pci-qxl"
++    },
++    {
++      "name": "isa-debugcon",
++      "parent": "isa-device"
++    },
++    {
++      "name": "pc-i440fx-2.8-machine",
++      "parent": "generic-pc-machine"
++    },
++    {
++      "name": "nvme",
++      "parent": "pci-device"
++    },
++    {
++      "name": "SandyBridge-IBRS-x86_64-cpu",
++      "parent": "x86_64-cpu"
++    },
++    {
++      "name": "Skylake-Server-x86_64-cpu",
++      "parent": "x86_64-cpu"
++    },
++    {
++      "name": "pentium-x86_64-cpu",
++      "parent": "x86_64-cpu"
++    },
++    {
++      "name": "vhost-user-input-pci",
++      "parent": "virtio-input-pci"
++    },
++    {
++      "name": "usb-braille",
++      "parent": "usb-serial-dev"
++    },
++    {
++      "name": "qio-channel-buffer",
++      "parent": "qio-channel"
++    },
++    {
++      "name": "scsi-disk",
++      "parent": "scsi-disk-base"
++    },
++    {
++      "name": "intel-hda",
++      "parent": "intel-hda-generic"
++    },
++    {
++      "name": "kvm-accel",
++      "parent": "accel"
++    },
++    {
++      "name": "pxb-pcie-bus",
++      "parent": "PCIE"
++    },
++    {
++      "name": "virtio-scsi-device",
++      "parent": "virtio-scsi-common"
++    },
++    {
++      "name": "AC97",
++      "parent": "pci-device"
++    },
++    {
++      "name": "usb-wacom-tablet",
++      "parent": "usb-device"
++    },
++    {
++      "name": "virtio-blk-pci-transitional",
++      "parent": "virtio-blk-pci-base"
++    },
++    {
++      "name": "i2c-bus",
++      "parent": "bus"
++    },
++    {
++      "name": "EPYC-x86_64-cpu",
++      "parent": "x86_64-cpu"
++    },
++    {
++      "name": "virtio-mouse-device",
++      "parent": "virtio-input-hid-device"
++    },
++    {
++      "name": "Conroe-x86_64-cpu",
++      "parent": "x86_64-cpu"
++    },
++    {
++      "name": "pxb-pcie",
++      "parent": "pci-device"
++    },
++    {
++      "name": "pc-1.3-machine",
++      "parent": "generic-pc-machine"
++    },
++    {
++      "name": "authz-list",
++      "parent": "authz"
++    },
++    {
++      "name": "ide-drive",
++      "parent": "ide-device"
++    },
++    {
++      "name": "generic-sdhci",
++      "parent": "sys-bus-device"
++    },
++    {
++      "name": "pvrdma",
++      "parent": "pci-device"
++    },
++    {
++      "name": "pc-1.2-machine",
++      "parent": "generic-pc-machine"
++    },
++    {
++      "name": "isa-pit",
++      "parent": "pit-common"
++    },
++    {
++      "name": "pxb",
++      "parent": "pci-device"
++    },
++    {
++      "name": "virtio-net-pci-non-transitional",
++      "parent": "virtio-net-pci-base"
++    },
++    {
++      "name": "virtio-scsi-pci-non-transitional",
++      "parent": "virtio-scsi-pci-base"
++    },
++    {
++      "name": "intel-iommu-iommu-memory-region",
++      "parent": "qemu:iommu-memory-region"
++    },
++    {
++      "name": "pc-1.1-machine",
++      "parent": "generic-pc-machine"
++    },
++    {
++      "name": "sd-card",
++      "parent": "device"
++    },
++    {
++      "name": "kvaser_pci",
++      "parent": "pci-device"
++    },
++    {
++      "name": "vmxnet3",
++      "parent": "pci-device"
++    },
++    {
++      "name": "i6300esb",
++      "parent": "pci-device"
++    },
++    {
++      "name": "Westmere-x86_64-cpu",
++      "parent": "x86_64-cpu"
++    },
++    {
++      "name": "amd-iommu-iommu-memory-region",
++      "parent": "qemu:iommu-memory-region"
++    },
++    {
++      "name": "pvpanic",
++      "parent": "isa-device"
++    },
++    {
++      "name": "Penryn-x86_64-cpu",
++      "parent": "x86_64-cpu"
++    },
++    {
++      "name": "vhost-vsock-pci-transitional",
++      "parent": "vhost-vsock-pci-base"
++    },
++    {
++      "name": "apic",
++      "parent": "apic-common"
++    },
++    {
++      "name": "isapc-machine",
++      "parent": "generic-pc-machine"
++    },
++    {
++      "name": "rng-random",
++      "parent": "rng-backend"
++    }
++  ],
++  "id": "libvirt-9"
++}
++
++{
++  "execute": "device-list-properties",
++  "arguments": {
++    "typename": "virtio-blk-pci"
++  },
++  "id": "libvirt-10"
++}
++
++{
++  "return": [
++    {
++      "name": "iothread",
++      "type": "link<iothread>"
++    },
++    {
++      "name": "notify_on_empty",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "request-merging",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "secs",
++      "type": "uint32"
++    },
++    {
++      "name": "min_io_size",
++      "type": "uint16"
++    },
++    {
++      "name": "event_idx",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "serial",
++      "type": "str"
++    },
++    {
++      "name": "heads",
++      "type": "uint32"
++    },
++    {
++      "name": "ioeventfd",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "multifunction",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "rombar",
++      "type": "uint32"
++    },
++    {
++      "name": "write-zeroes",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "scsi",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "cyls",
++      "type": "uint32"
++    },
++    {
++      "name": "x-disable-pcie",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "logical_block_size",
++      "description": "A power of two between 512 and 32768",
++      "type": "uint16"
++    },
++    {
++      "name": "bootindex",
++      "type": "int32"
++    },
++    {
++      "name": "indirect_desc",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "max-write-zeroes-sectors",
++      "type": "uint32"
++    },
++    {
++      "name": "queue-size",
++      "type": "uint16"
++    },
++    {
++      "name": "disable-modern",
++      "type": "bool"
++    },
++    {
++      "name": "drive",
++      "description": "Node name or ID of a block device to use as a backend",
++      "type": "str"
++    },
++    {
++      "name": "x-pcie-lnkctl-init",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "disable-legacy",
++      "description": "on/off/auto",
++      "type": "OnOffAuto"
++    },
++    {
++      "name": "command_serr_enable",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "werror",
++      "description": "Error handling policy, report/ignore/enospc/stop/auto",
++      "type": "BlockdevOnError"
++    },
++    {
++      "name": "any_layout",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "discard_granularity",
++      "type": "uint32"
++    },
++    {
++      "name": "rerror",
++      "description": "Error handling policy, report/ignore/enospc/stop/auto",
++      "type": "BlockdevOnError"
++    },
++    {
++      "name": "page-per-vq",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "x-pcie-deverr-init",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "x-pcie-pm-init",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "max-discard-sectors",
++      "type": "uint32"
++    },
++    {
++      "name": "x-pcie-lnksta-dllla",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "share-rw",
++      "type": "bool"
++    },
++    {
++      "name": "physical_block_size",
++      "description": "A power of two between 512 and 32768",
++      "type": "uint16"
++    },
++    {
++      "name": "config-wce",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "class",
++      "type": "uint32"
++    },
++    {
++      "name": "addr",
++      "description": "Slot and optional function number, example: 06.0 or 06",
++      "type": "int32"
++    },
++    {
++      "name": "migrate-extra",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "modern-pio-notify",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "vectors",
++      "type": "uint32"
++    },
++    {
++      "name": "iommu_platform",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "x-pcie-extcap-init",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "virtio-backend",
++      "type": "child<virtio-blk-device>"
++    },
++    {
++      "name": "x-ignore-backend-features",
++      "type": "bool"
++    },
++    {
++      "name": "discard",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "write-cache",
++      "description": "on/off/auto",
++      "type": "OnOffAuto"
++    },
++    {
++      "name": "num-queues",
++      "type": "uint16"
++    },
++    {
++      "name": "opt_io_size",
++      "type": "uint32"
++    },
++    {
++      "name": "ats",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "romfile",
++      "type": "str"
++    },
++    {
++      "name": "virtio-pci-bus-master-bug-migration",
++      "description": "on/off",
++      "type": "bool"
++    }
++  ],
++  "id": "libvirt-10"
++}
++
++{
++  "execute": "device-list-properties",
++  "arguments": {
++    "typename": "virtio-net-pci"
++  },
++  "id": "libvirt-11"
++}
++
++{
++  "return": [
++    {
++      "name": "ctrl_mac_addr",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "romfile",
++      "type": "str"
++    },
++    {
++      "name": "x-pcie-lnksta-dllla",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "status",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "notify_on_empty",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "command_serr_enable",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "indirect_desc",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "x-pcie-pm-init",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "rsc_interval",
++      "type": "uint32"
++    },
++    {
++      "name": "guest_csum",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "speed",
++      "type": "int32"
++    },
++    {
++      "name": "ctrl_rx",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "ctrl_vq",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "bootindex",
++      "type": "int32"
++    },
++    {
++      "name": "multifunction",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "disable-modern",
++      "type": "bool"
++    },
++    {
++      "name": "mrg_rxbuf",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "host_tso6",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "x-txtimer",
++      "type": "uint32"
++    },
++    {
++      "name": "host_tso4",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "rombar",
++      "type": "uint32"
++    },
++    {
++      "name": "ctrl_rx_extra",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "gso",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "page-per-vq",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "x-disable-pcie",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "x-ignore-backend-features",
++      "type": "bool"
++    },
++    {
++      "name": "x-txburst",
++      "type": "int32"
++    },
++    {
++      "name": "iommu_platform",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "x-pcie-lnkctl-init",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "host_mtu",
++      "type": "uint16"
++    },
++    {
++      "name": "ctrl_vlan",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "guest_tso4",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "virtio-backend",
++      "type": "child<virtio-net-device>"
++    },
++    {
++      "name": "event_idx",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "vectors",
++      "type": "uint32"
++    },
++    {
++      "name": "guest_announce",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "host_ecn",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "addr",
++      "description": "Slot and optional function number, example: 06.0 or 06",
++      "type": "int32"
++    },
++    {
++      "name": "ats",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "host_ufo",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "duplex",
++      "type": "str"
++    },
++    {
++      "name": "guest_tso6",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "ctrl_guest_offloads",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "csum",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "modern-pio-notify",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "ioeventfd",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "mq",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "any_layout",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "guest_ecn",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "guest_ufo",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "virtio-pci-bus-master-bug-migration",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "mac",
++      "description": "Ethernet 6-byte MAC Address, example: 52:54:00:12:34:56",
++      "type": "str"
++    },
++    {
++      "name": "tx_queue_size",
++      "type": "uint16"
++    },
++    {
++      "name": "disable-legacy",
++      "description": "on/off/auto",
++      "type": "OnOffAuto"
++    },
++    {
++      "name": "tx",
++      "type": "str"
++    },
++    {
++      "name": "x-pcie-extcap-init",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "x-mtu-bypass-backend",
++      "type": "bool"
++    },
++    {
++      "name": "x-pcie-deverr-init",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "netdev",
++      "description": "ID of a netdev to use as a backend",
++      "type": "str"
++    },
++    {
++      "name": "migrate-extra",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "guest_rsc_ext",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "rx_queue_size",
++      "type": "uint16"
++    }
++  ],
++  "id": "libvirt-11"
++}
++
++{
++  "execute": "device-list-properties",
++  "arguments": {
++    "typename": "virtio-scsi-pci"
++  },
++  "id": "libvirt-12"
++}
++
++{
++  "return": [
++    {
++      "name": "event_idx",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "ioeventfd",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "multifunction",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "rombar",
++      "type": "uint32"
++    },
++    {
++      "name": "virtqueue_size",
++      "type": "uint32"
++    },
++    {
++      "name": "x-disable-pcie",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "indirect_desc",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "x-pcie-lnkctl-init",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "disable-modern",
++      "type": "bool"
++    },
++    {
++      "name": "num_queues",
++      "type": "uint32"
++    },
++    {
++      "name": "cmd_per_lun",
++      "type": "uint32"
++    },
++    {
++      "name": "disable-legacy",
++      "description": "on/off/auto",
++      "type": "OnOffAuto"
++    },
++    {
++      "name": "command_serr_enable",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "hotplug",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "page-per-vq",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "x-pcie-deverr-init",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "x-pcie-pm-init",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "x-pcie-lnksta-dllla",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "max_sectors",
++      "type": "uint32"
++    },
++    {
++      "name": "param_change",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "any_layout",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "iothread",
++      "type": "link<iothread>"
++    },
++    {
++      "name": "addr",
++      "description": "Slot and optional function number, example: 06.0 or 06",
++      "type": "int32"
++    },
++    {
++      "name": "migrate-extra",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "modern-pio-notify",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "vectors",
++      "type": "uint32"
++    },
++    {
++      "name": "x-pcie-extcap-init",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "virtio-backend",
++      "type": "child<virtio-scsi-device>"
++    },
++    {
++      "name": "x-ignore-backend-features",
++      "type": "bool"
++    },
++    {
++      "name": "notify_on_empty",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "iommu_platform",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "ats",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "romfile",
++      "type": "str"
++    },
++    {
++      "name": "virtio-pci-bus-master-bug-migration",
++      "description": "on/off",
++      "type": "bool"
++    }
++  ],
++  "id": "libvirt-12"
++}
++
++{
++  "execute": "device-list-properties",
++  "arguments": {
++    "typename": "virtio-net-ccw"
++  },
++  "id": "libvirt-13"
++}
++
++{
++  "id": "libvirt-13",
++  "error": {
++    "class": "DeviceNotFound",
++    "desc": "Device 'virtio-net-ccw' not found"
++  }
++}
++
++{
++  "execute": "device-list-properties",
++  "arguments": {
++    "typename": "virtio-scsi-ccw"
++  },
++  "id": "libvirt-14"
++}
++
++{
++  "id": "libvirt-14",
++  "error": {
++    "class": "DeviceNotFound",
++    "desc": "Device 'virtio-scsi-ccw' not found"
++  }
++}
++
++{
++  "execute": "device-list-properties",
++  "arguments": {
++    "typename": "virtio-net-s390"
++  },
++  "id": "libvirt-15"
++}
++
++{
++  "id": "libvirt-15",
++  "error": {
++    "class": "DeviceNotFound",
++    "desc": "Device 'virtio-net-s390' not found"
++  }
++}
++
++{
++  "execute": "device-list-properties",
++  "arguments": {
++    "typename": "pci-assign"
++  },
++  "id": "libvirt-16"
++}
++
++{
++  "id": "libvirt-16",
++  "error": {
++    "class": "DeviceNotFound",
++    "desc": "Device 'pci-assign' not found"
++  }
++}
++
++{
++  "execute": "device-list-properties",
++  "arguments": {
++    "typename": "kvm-pci-assign"
++  },
++  "id": "libvirt-17"
++}
++
++{
++  "id": "libvirt-17",
++  "error": {
++    "class": "DeviceNotFound",
++    "desc": "Device 'kvm-pci-assign' not found"
++  }
++}
++
++{
++  "execute": "device-list-properties",
++  "arguments": {
++    "typename": "vfio-pci"
++  },
++  "id": "libvirt-18"
++}
++
++{
++  "return": [
++    {
++      "name": "x-igd-opregion",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "x-pci-vendor-id",
++      "type": "uint32"
++    },
++    {
++      "name": "yres",
++      "type": "uint32"
++    },
++    {
++      "name": "x-pci-sub-device-id",
++      "type": "uint32"
++    },
++    {
++      "name": "x-no-kvm-ioeventfd",
++      "type": "bool"
++    },
++    {
++      "name": "multifunction",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "rombar",
++      "type": "uint32"
++    },
++    {
++      "name": "x-no-kvm-msi",
++      "type": "bool"
++    },
++    {
++      "name": "x-req",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "xres",
++      "type": "uint32"
++    },
++    {
++      "name": "x-no-vfio-ioeventfd",
++      "type": "bool"
++    },
++    {
++      "name": "x-no-kvm-intx",
++      "type": "bool"
++    },
++    {
++      "name": "host",
++      "description": "Address (bus/device/function) of the host device, example: 04:10.0",
++      "type": "str"
++    },
++    {
++      "name": "x-no-kvm-msix",
++      "type": "bool"
++    },
++    {
++      "name": "command_serr_enable",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "x-balloon-allowed",
++      "type": "bool"
++    },
++    {
++      "name": "x-pcie-lnksta-dllla",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "x-pci-sub-vendor-id",
++      "type": "uint32"
++    },
++    {
++      "name": "x-pci-device-id",
++      "type": "uint32"
++    },
++    {
++      "name": "x-no-geforce-quirks",
++      "type": "bool"
++    },
++    {
++      "name": "display",
++      "description": "on/off/auto",
++      "type": "OnOffAuto"
++    },
++    {
++      "name": "x-nv-gpudirect-clique",
++      "description": "NVIDIA GPUDirect Clique ID (0 - 15)",
++      "type": "uint4"
++    },
++    {
++      "name": "x-igd-gms",
++      "type": "uint32"
++    },
++    {
++      "name": "addr",
++      "description": "Slot and optional function number, example: 06.0 or 06",
++      "type": "int32"
++    },
++    {
++      "name": "x-msix-relocation",
++      "description": "off/auto/bar0/bar1/bar2/bar3/bar4/bar5",
++      "type": "OffAutoPCIBAR"
++    },
++    {
++      "name": "x-intx-mmap-timeout-ms",
++      "type": "uint32"
++    },
++    {
++      "name": "x-pcie-extcap-init",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "x-no-mmap",
++      "type": "bool"
++    },
++    {
++      "name": "bootindex",
++      "type": "int32"
++    },
++    {
++      "name": "sysfsdev",
++      "type": "str"
++    },
++    {
++      "name": "x-vga",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "romfile",
++      "type": "str"
++    }
++  ],
++  "id": "libvirt-18"
++}
++
++{
++  "execute": "device-list-properties",
++  "arguments": {
++    "typename": "scsi-disk"
++  },
++  "id": "libvirt-19"
++}
++
++{
++  "return": [
++    {
++      "name": "min_io_size",
++      "type": "uint16"
++    },
++    {
++      "name": "secs",
++      "type": "uint32"
++    },
++    {
++      "name": "removable",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "channel",
++      "type": "uint32"
++    },
++    {
++      "name": "heads",
++      "type": "uint32"
++    },
++    {
++      "name": "lun",
++      "type": "uint32"
++    },
++    {
++      "name": "dpofua",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "ver",
++      "type": "str"
++    },
++    {
++      "name": "scsi-id",
++      "type": "uint32"
++    },
++    {
++      "name": "cyls",
++      "type": "uint32"
++    },
++    {
++      "name": "logical_block_size",
++      "description": "A power of two between 512 and 32768",
++      "type": "uint16"
++    },
++    {
++      "name": "rotation_rate",
++      "type": "uint16"
++    },
++    {
++      "name": "drive",
++      "description": "Node name or ID of a block device to use as a backend",
++      "type": "str"
++    },
++    {
++      "name": "scsi_version",
++      "type": "int32"
++    },
++    {
++      "name": "werror",
++      "description": "Error handling policy, report/ignore/enospc/stop/auto",
++      "type": "BlockdevOnError"
++    },
++    {
++      "name": "discard_granularity",
++      "type": "uint32"
++    },
++    {
++      "name": "port_wwn",
++      "type": "uint64"
++    },
++    {
++      "name": "max_unmap_size",
++      "type": "uint64"
++    },
++    {
++      "name": "rerror",
++      "description": "Error handling policy, report/ignore/enospc/stop/auto",
++      "type": "BlockdevOnError"
++    },
++    {
++      "name": "max_io_size",
++      "type": "uint64"
++    },
++    {
++      "name": "device_id",
++      "type": "str"
++    },
++    {
++      "name": "wwn",
++      "type": "uint64"
++    },
++    {
++      "name": "share-rw",
++      "type": "bool"
++    },
++    {
++      "name": "product",
++      "type": "str"
++    },
++    {
++      "name": "vendor",
++      "type": "str"
++    },
++    {
++      "name": "physical_block_size",
++      "description": "A power of two between 512 and 32768",
++      "type": "uint16"
++    },
++    {
++      "name": "port_index",
++      "type": "uint16"
++    },
++    {
++      "name": "bootindex",
++      "type": "int32"
++    },
++    {
++      "name": "serial",
++      "type": "str"
++    },
++    {
++      "name": "write-cache",
++      "description": "on/off/auto",
++      "type": "OnOffAuto"
++    },
++    {
++      "name": "opt_io_size",
++      "type": "uint32"
++    }
++  ],
++  "id": "libvirt-19"
++}
++
++{
++  "execute": "device-list-properties",
++  "arguments": {
++    "typename": "ide-drive"
++  },
++  "id": "libvirt-20"
++}
++
++{
++  "return": [
++    {
++      "name": "serial",
++      "type": "str"
++    },
++    {
++      "name": "secs",
++      "type": "uint32"
++    },
++    {
++      "name": "logical_block_size",
++      "description": "A power of two between 512 and 32768",
++      "type": "uint16"
++    },
++    {
++      "name": "discard_granularity",
++      "type": "uint32"
++    },
++    {
++      "name": "bootindex",
++      "type": "int32"
++    },
++    {
++      "name": "rotation_rate",
++      "type": "uint16"
++    },
++    {
++      "name": "drive",
++      "description": "Node name or ID of a block device to use as a backend",
++      "type": "str"
++    },
++    {
++      "name": "heads",
++      "type": "uint32"
++    },
++    {
++      "name": "write-cache",
++      "description": "on/off/auto",
++      "type": "OnOffAuto"
++    },
++    {
++      "name": "share-rw",
++      "type": "bool"
++    },
++    {
++      "name": "min_io_size",
++      "type": "uint16"
++    },
++    {
++      "name": "opt_io_size",
++      "type": "uint32"
++    },
++    {
++      "name": "bios-chs-trans",
++      "description": "Logical CHS translation algorithm, auto/none/lba/large/rechs",
++      "type": "BiosAtaTranslation"
++    },
++    {
++      "name": "unit",
++      "type": "uint32"
++    },
++    {
++      "name": "wwn",
++      "type": "uint64"
++    },
++    {
++      "name": "werror",
++      "description": "Error handling policy, report/ignore/enospc/stop/auto",
++      "type": "BlockdevOnError"
++    },
++    {
++      "name": "model",
++      "type": "str"
++    },
++    {
++      "name": "rerror",
++      "description": "Error handling policy, report/ignore/enospc/stop/auto",
++      "type": "BlockdevOnError"
++    },
++    {
++      "name": "ver",
++      "type": "str"
++    },
++    {
++      "name": "physical_block_size",
++      "description": "A power of two between 512 and 32768",
++      "type": "uint16"
++    },
++    {
++      "name": "cyls",
++      "type": "uint32"
++    }
++  ],
++  "id": "libvirt-20"
++}
++
++{
++  "execute": "device-list-properties",
++  "arguments": {
++    "typename": "PIIX4_PM"
++  },
++  "id": "libvirt-21"
++}
++
++{
++  "return": [
++    {
++      "name": "memory-hotplug-support",
++      "type": "bool"
++    },
++    {
++      "name": "rombar",
++      "type": "uint32"
++    },
++    {
++      "name": "x-pcie-lnksta-dllla",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "acpi-pci-hotplug-with-bridge-support",
++      "type": "bool"
++    },
++    {
++      "name": "multifunction",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "romfile",
++      "type": "str"
++    },
++    {
++      "name": "disable_s4",
++      "type": "uint8"
++    },
++    {
++      "name": "disable_s3",
++      "type": "uint8"
++    },
++    {
++      "name": "x-pcie-extcap-init",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "command_serr_enable",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "s4_val",
++      "type": "uint8"
++    },
++    {
++      "name": "smb_io_base",
++      "type": "uint32"
++    },
++    {
++      "name": "addr",
++      "description": "Slot and optional function number, example: 06.0 or 06",
++      "type": "int32"
++    }
++  ],
++  "id": "libvirt-21"
++}
++
++{
++  "execute": "device-list-properties",
++  "arguments": {
++    "typename": "usb-redir"
++  },
++  "id": "libvirt-22"
++}
++
++{
++  "return": [
++    {
++      "name": "filter",
++      "type": "str"
++    },
++    {
++      "name": "msos-desc",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "serial",
++      "type": "str"
++    },
++    {
++      "name": "bootindex",
++      "type": "int32"
++    },
++    {
++      "name": "port",
++      "type": "str"
++    },
++    {
++      "name": "debug",
++      "type": "uint8"
++    },
++    {
++      "name": "streams",
++      "type": "bool"
++    },
++    {
++      "name": "chardev",
++      "description": "ID of a chardev to use as a backend",
++      "type": "str"
++    },
++    {
++      "name": "full-path",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "attached",
++      "type": "bool"
++    }
++  ],
++  "id": "libvirt-22"
++}
++
++{
++  "execute": "device-list-properties",
++  "arguments": {
++    "typename": "usb-host"
++  },
++  "id": "libvirt-23"
++}
++
++{
++  "return": [
++    {
++      "name": "isobufs",
++      "type": "uint32"
++    },
++    {
++      "name": "hostaddr",
++      "type": "uint32"
++    },
++    {
++      "name": "msos-desc",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "productid",
++      "type": "uint32"
++    },
++    {
++      "name": "serial",
++      "type": "str"
++    },
++    {
++      "name": "bootindex",
++      "type": "int32"
++    },
++    {
++      "name": "guest-reset",
++      "type": "bool"
++    },
++    {
++      "name": "isobsize",
++      "type": "uint32"
++    },
++    {
++      "name": "port",
++      "type": "str"
++    },
++    {
++      "name": "vendorid",
++      "type": "uint32"
++    },
++    {
++      "name": "pipeline",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "attached",
++      "type": "bool"
++    },
++    {
++      "name": "hostport",
++      "type": "str"
++    },
++    {
++      "name": "full-path",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "loglevel",
++      "type": "uint32"
++    },
++    {
++      "name": "hostbus",
++      "type": "uint32"
++    }
++  ],
++  "id": "libvirt-23"
++}
++
++{
++  "execute": "device-list-properties",
++  "arguments": {
++    "typename": "scsi-generic"
++  },
++  "id": "libvirt-24"
++}
++
++{
++  "return": [
++    {
++      "name": "bootindex",
++      "type": "int32"
++    },
++    {
++      "name": "drive",
++      "description": "Node name or ID of a block device to use as a backend",
++      "type": "str"
++    },
++    {
++      "name": "lun",
++      "type": "uint32"
++    },
++    {
++      "name": "share-rw",
++      "type": "bool"
++    },
++    {
++      "name": "channel",
++      "type": "uint32"
++    },
++    {
++      "name": "scsi-id",
++      "type": "uint32"
++    }
++  ],
++  "id": "libvirt-24"
++}
++
++{
++  "execute": "device-list-properties",
++  "arguments": {
++    "typename": "i440FX-pcihost"
++  },
++  "id": "libvirt-25"
++}
++
++{
++  "return": [
++    {
++      "name": "short_root_bus",
++      "type": "uint32"
++    },
++    {
++      "name": "pci-conf-idx[0]",
++      "type": "child<qemu:memory-region>"
++    },
++    {
++      "name": "pci-hole64-end",
++      "type": "uint64"
++    },
++    {
++      "name": "pci-hole-end",
++      "type": "uint32"
++    },
++    {
++      "name": "pci-hole-start",
++      "type": "uint32"
++    },
++    {
++      "name": "pci-hole64-start",
++      "type": "uint64"
++    },
++    {
++      "name": "pci-hole64-size",
++      "type": "size"
++    },
++    {
++      "name": "pci-conf-data[0]",
++      "type": "child<qemu:memory-region>"
++    },
++    {
++      "name": "x-pci-hole64-fix",
++      "type": "bool"
++    }
++  ],
++  "id": "libvirt-25"
++}
++
++{
++  "execute": "device-list-properties",
++  "arguments": {
++    "typename": "q35-pcihost"
++  },
++  "id": "libvirt-26"
++}
++
++{
++  "return": [
++    {
++      "name": "short_root_bus",
++      "type": "uint32"
++    },
++    {
++      "name": "system-mem",
++      "type": "link<qemu:memory-region>"
++    },
++    {
++      "name": "pci-conf-idx[0]",
++      "type": "child<qemu:memory-region>"
++    },
++    {
++      "name": "pcie-mmcfg-mmio[0]",
++      "type": "child<qemu:memory-region>"
++    },
++    {
++      "name": "pci-hole64-start",
++      "type": "uint64"
++    },
++    {
++      "name": "io-mem",
++      "type": "link<qemu:memory-region>"
++    },
++    {
++      "name": "pci-hole64-end",
++      "type": "uint64"
++    },
++    {
++      "name": "pci-hole-end",
++      "type": "uint32"
++    },
++    {
++      "name": "above-4g-mem-size",
++      "type": "size"
++    },
++    {
++      "name": "below-4g-mem-size",
++      "type": "size"
++    },
++    {
++      "name": "ram-mem",
++      "type": "link<qemu:memory-region>"
++    },
++    {
++      "name": "pci-hole-start",
++      "type": "uint32"
++    },
++    {
++      "name": "MCFG",
++      "type": "uint64"
++    },
++    {
++      "name": "mch",
++      "type": "child<mch>"
++    },
++    {
++      "name": "pci-hole64-size",
++      "type": "size"
++    },
++    {
++      "name": "pci-mem",
++      "type": "link<qemu:memory-region>"
++    },
++    {
++      "name": "pci-conf-data[0]",
++      "type": "child<qemu:memory-region>"
++    },
++    {
++      "name": "x-pci-hole64-fix",
++      "type": "bool"
++    },
++    {
++      "name": "mcfg_size",
++      "type": "uint64"
++    }
++  ],
++  "id": "libvirt-26"
++}
++
++{
++  "execute": "device-list-properties",
++  "arguments": {
++    "typename": "usb-storage"
++  },
++  "id": "libvirt-27"
++}
++
++{
++  "return": [
++    {
++      "name": "serial",
++      "type": "str"
++    },
++    {
++      "name": "msos-desc",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "logical_block_size",
++      "description": "A power of two between 512 and 32768",
++      "type": "uint16"
++    },
++    {
++      "name": "discard_granularity",
++      "type": "uint32"
++    },
++    {
++      "name": "drive",
++      "description": "Node name or ID of a block device to use as a backend",
++      "type": "str"
++    },
++    {
++      "name": "bootindex",
++      "type": "int32"
++    },
++    {
++      "name": "write-cache",
++      "description": "on/off/auto",
++      "type": "OnOffAuto"
++    },
++    {
++      "name": "share-rw",
++      "type": "bool"
++    },
++    {
++      "name": "min_io_size",
++      "type": "uint16"
++    },
++    {
++      "name": "opt_io_size",
++      "type": "uint32"
++    },
++    {
++      "name": "port",
++      "type": "str"
++    },
++    {
++      "name": "attached",
++      "type": "bool"
++    },
++    {
++      "name": "werror",
++      "description": "Error handling policy, report/ignore/enospc/stop/auto",
++      "type": "BlockdevOnError"
++    },
++    {
++      "name": "full-path",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "rerror",
++      "description": "Error handling policy, report/ignore/enospc/stop/auto",
++      "type": "BlockdevOnError"
++    },
++    {
++      "name": "removable",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "physical_block_size",
++      "description": "A power of two between 512 and 32768",
++      "type": "uint16"
++    }
++  ],
++  "id": "libvirt-27"
++}
++
++{
++  "execute": "device-list-properties",
++  "arguments": {
++    "typename": "kvm-pit"
++  },
++  "id": "libvirt-28"
++}
++
++{
++  "return": [
++    {
++      "name": "iobase",
++      "type": "uint32"
++    },
++    {
++      "name": "lost_tick_policy",
++      "type": "LostTickPolicy"
++    }
++  ],
++  "id": "libvirt-28"
++}
++
++{
++  "execute": "device-list-properties",
++  "arguments": {
++    "typename": "VGA"
++  },
++  "id": "libvirt-29"
++}
++
++{
++  "return": [
++    {
++      "name": "rombar",
++      "type": "uint32"
++    },
++    {
++      "name": "x-pcie-lnksta-dllla",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "mmio",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "multifunction",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "qemu-extended-regs",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "big-endian-framebuffer",
++      "type": "bool"
++    },
++    {
++      "name": "command_serr_enable",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "romfile",
++      "type": "str"
++    },
++    {
++      "name": "yres",
++      "type": "uint32"
++    },
++    {
++      "name": "vgamem_mb",
++      "type": "uint32"
++    },
++    {
++      "name": "x-pcie-extcap-init",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "addr",
++      "description": "Slot and optional function number, example: 06.0 or 06",
++      "type": "int32"
++    },
++    {
++      "name": "global-vmstate",
++      "type": "bool"
++    },
++    {
++      "name": "edid",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "xres",
++      "type": "uint32"
++    }
++  ],
++  "id": "libvirt-29"
++}
++
++{
++  "execute": "device-list-properties",
++  "arguments": {
++    "typename": "vmware-svga"
++  },
++  "id": "libvirt-30"
++}
++
++{
++  "return": [
++    {
++      "name": "rombar",
++      "type": "uint32"
++    },
++    {
++      "name": "x-pcie-lnksta-dllla",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "multifunction",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "romfile",
++      "type": "str"
++    },
++    {
++      "name": "vgamem_mb",
++      "type": "uint32"
++    },
++    {
++      "name": "x-pcie-extcap-init",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "command_serr_enable",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "addr",
++      "description": "Slot and optional function number, example: 06.0 or 06",
++      "type": "int32"
++    },
++    {
++      "name": "global-vmstate",
++      "type": "bool"
++    }
++  ],
++  "id": "libvirt-30"
++}
++
++{
++  "execute": "device-list-properties",
++  "arguments": {
++    "typename": "qxl"
++  },
++  "id": "libvirt-31"
++}
++
++{
++  "return": [
++    {
++      "name": "command_serr_enable",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "rombar",
++      "type": "uint32"
++    },
++    {
++      "name": "x-pcie-lnksta-dllla",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "yres",
++      "type": "uint32"
++    },
++    {
++      "name": "ram_size_mb",
++      "type": "uint32"
++    },
++    {
++      "name": "global-vmstate",
++      "type": "bool"
++    },
++    {
++      "name": "multifunction",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "vgamem_mb",
++      "type": "uint32"
++    },
++    {
++      "name": "romfile",
++      "type": "str"
++    },
++    {
++      "name": "addr",
++      "description": "Slot and optional function number, example: 06.0 or 06",
++      "type": "int32"
++    },
++    {
++      "name": "debug",
++      "type": "uint32"
++    },
++    {
++      "name": "vram_size_mb",
++      "type": "uint32"
++    },
++    {
++      "name": "revision",
++      "type": "uint32"
++    },
++    {
++      "name": "ram_size",
++      "type": "uint32"
++    },
++    {
++      "name": "vram64_size_mb",
++      "type": "uint32"
++    },
++    {
++      "name": "x-pcie-extcap-init",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "guestdebug",
++      "type": "uint32"
++    },
++    {
++      "name": "vram_size",
++      "type": "uint64"
++    },
++    {
++      "name": "surfaces",
++      "type": "int32"
++    },
++    {
++      "name": "max_outputs",
++      "type": "uint16"
++    },
++    {
++      "name": "xres",
++      "type": "uint32"
++    },
++    {
++      "name": "cmdlog",
++      "type": "uint32"
++    }
++  ],
++  "id": "libvirt-31"
++}
++
++{
++  "execute": "device-list-properties",
++  "arguments": {
++    "typename": "virtio-gpu-pci"
++  },
++  "id": "libvirt-32"
++}
++
++{
++  "return": [
++    {
++      "name": "event_idx",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "yres",
++      "type": "uint32"
++    },
++    {
++      "name": "ioeventfd",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "multifunction",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "rombar",
++      "type": "uint32"
++    },
++    {
++      "name": "xres",
++      "type": "uint32"
++    },
++    {
++      "name": "x-disable-pcie",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "indirect_desc",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "disable-modern",
++      "type": "bool"
++    },
++    {
++      "name": "x-pcie-lnkctl-init",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "disable-legacy",
++      "description": "on/off/auto",
++      "type": "OnOffAuto"
++    },
++    {
++      "name": "command_serr_enable",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "page-per-vq",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "x-pcie-deverr-init",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "max_outputs",
++      "type": "uint32"
++    },
++    {
++      "name": "x-pcie-pm-init",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "x-pcie-lnksta-dllla",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "any_layout",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "addr",
++      "description": "Slot and optional function number, example: 06.0 or 06",
++      "type": "int32"
++    },
++    {
++      "name": "edid",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "migrate-extra",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "modern-pio-notify",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "vectors",
++      "type": "uint32"
++    },
++    {
++      "name": "iommu_platform",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "x-pcie-extcap-init",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "max_hostmem",
++      "type": "size"
++    },
++    {
++      "name": "virtio-backend",
++      "type": "child<virtio-gpu-device>"
++    },
++    {
++      "name": "x-ignore-backend-features",
++      "type": "bool"
++    },
++    {
++      "name": "stats",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "notify_on_empty",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "virgl",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "ats",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "romfile",
++      "type": "str"
++    },
++    {
++      "name": "virtio-pci-bus-master-bug-migration",
++      "description": "on/off",
++      "type": "bool"
++    }
++  ],
++  "id": "libvirt-32"
++}
++
++{
++  "execute": "device-list-properties",
++  "arguments": {
++    "typename": "virtio-gpu-device"
++  },
++  "id": "libvirt-33"
++}
++
++{
++  "return": [
++    {
++      "name": "notify_on_empty",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "any_layout",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "indirect_desc",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "event_idx",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "yres",
++      "type": "uint32"
++    },
++    {
++      "name": "stats",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "iommu_platform",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "virgl",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "edid",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "max_outputs",
++      "type": "uint32"
++    },
++    {
++      "name": "max_hostmem",
++      "type": "size"
++    },
++    {
++      "name": "xres",
++      "type": "uint32"
++    }
++  ],
++  "id": "libvirt-33"
++}
++
++{
++  "execute": "device-list-properties",
++  "arguments": {
++    "typename": "ICH9-LPC"
++  },
++  "id": "libvirt-34"
++}
++
++{
++  "return": [
++    {
++      "name": "memory-hotplug-support",
++      "type": "bool"
++    },
++    {
++      "name": "rombar",
++      "type": "uint32"
++    },
++    {
++      "name": "sci_int",
++      "type": "uint32"
++    },
++    {
++      "name": "x-pcie-lnksta-dllla",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "gpe0_blk_len",
++      "type": "uint32"
++    },
++    {
++      "name": "pm_io_base",
++      "type": "uint32"
++    },
++    {
++      "name": "noreboot",
++      "type": "bool"
++    },
++    {
++      "name": "multifunction",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "cpu-hotplug-legacy",
++      "type": "bool"
++    },
++    {
++      "name": "acpi_disable_cmd",
++      "type": "uint8"
++    },
++    {
++      "name": "x-smi-broadcast",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "romfile",
++      "type": "str"
++    },
++    {
++      "name": "disable_s3",
++      "type": "uint8"
++    },
++    {
++      "name": "s4_val",
++      "type": "uint8"
++    },
++    {
++      "name": "x-pcie-extcap-init",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "command_serr_enable",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "addr",
++      "description": "Slot and optional function number, example: 06.0 or 06",
++      "type": "int32"
++    },
++    {
++      "name": "acpi_enable_cmd",
++      "type": "uint8"
++    },
++    {
++      "name": "enable_tco",
++      "type": "bool"
++    },
++    {
++      "name": "disable_s4",
++      "type": "uint8"
++    },
++    {
++      "name": "gpe0_blk",
++      "type": "uint32"
++    }
++  ],
++  "id": "libvirt-34"
++}
++
++{
++  "execute": "device-list-properties",
++  "arguments": {
++    "typename": "virtio-balloon-pci"
++  },
++  "id": "libvirt-35"
++}
++
++{
++  "return": [
++    {
++      "name": "guest-stats-polling-interval",
++      "type": "int"
++    },
++    {
++      "name": "event_idx",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "multifunction",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "rombar",
++      "type": "uint32"
++    },
++    {
++      "name": "x-disable-pcie",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "indirect_desc",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "x-pcie-lnkctl-init",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "disable-modern",
++      "type": "bool"
++    },
++    {
++      "name": "free-page-hint",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "disable-legacy",
++      "description": "on/off/auto",
++      "type": "OnOffAuto"
++    },
++    {
++      "name": "command_serr_enable",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "guest-stats",
++      "type": "guest statistics"
++    },
++    {
++      "name": "deflate-on-oom",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "page-per-vq",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "x-pcie-deverr-init",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "x-pcie-pm-init",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "x-pcie-lnksta-dllla",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "any_layout",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "iothread",
++      "type": "link<iothread>"
++    },
++    {
++      "name": "class",
++      "type": "uint32"
++    },
++    {
++      "name": "addr",
++      "description": "Slot and optional function number, example: 06.0 or 06",
++      "type": "int32"
++    },
++    {
++      "name": "migrate-extra",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "modern-pio-notify",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "x-pcie-extcap-init",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "virtio-backend",
++      "type": "child<virtio-balloon-device>"
++    },
++    {
++      "name": "x-ignore-backend-features",
++      "type": "bool"
++    },
++    {
++      "name": "notify_on_empty",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "iommu_platform",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "ats",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "virtio-pci-bus-master-bug-migration",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "romfile",
++      "type": "str"
++    }
++  ],
++  "id": "libvirt-35"
++}
++
++{
++  "execute": "device-list-properties",
++  "arguments": {
++    "typename": "virtio-balloon-ccw"
++  },
++  "id": "libvirt-36"
++}
++
++{
++  "id": "libvirt-36",
++  "error": {
++    "class": "DeviceNotFound",
++    "desc": "Device 'virtio-balloon-ccw' not found"
++  }
++}
++
++{
++  "execute": "device-list-properties",
++  "arguments": {
++    "typename": "virtio-balloon-device"
++  },
++  "id": "libvirt-37"
++}
++
++{
++  "return": [
++    {
++      "name": "notify_on_empty",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "any_layout",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "indirect_desc",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "guest-stats",
++      "type": "guest statistics"
++    },
++    {
++      "name": "guest-stats-polling-interval",
++      "type": "int"
++    },
++    {
++      "name": "iothread",
++      "type": "link<iothread>"
++    },
++    {
++      "name": "event_idx",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "free-page-hint",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "iommu_platform",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "deflate-on-oom",
++      "description": "on/off",
++      "type": "bool"
++    }
++  ],
++  "id": "libvirt-37"
++}
++
++{
++  "execute": "device-list-properties",
++  "arguments": {
++    "typename": "nec-usb-xhci"
++  },
++  "id": "libvirt-38"
++}
++
++{
++  "return": [
++    {
++      "name": "rombar",
++      "type": "uint32"
++    },
++    {
++      "name": "intrs",
++      "type": "uint32"
++    },
++    {
++      "name": "x-pcie-lnksta-dllla",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "msix",
++      "description": "on/off/auto",
++      "type": "OnOffAuto"
++    },
++    {
++      "name": "multifunction",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "msi",
++      "description": "on/off/auto",
++      "type": "OnOffAuto"
++    },
++    {
++      "name": "superspeed-ports-first",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "streams",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "romfile",
++      "type": "str"
++    },
++    {
++      "name": "force-pcie-endcap",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "x-pcie-extcap-init",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "command_serr_enable",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "addr",
++      "description": "Slot and optional function number, example: 06.0 or 06",
++      "type": "int32"
++    },
++    {
++      "name": "p3",
++      "type": "uint32"
++    },
++    {
++      "name": "p2",
++      "type": "uint32"
++    },
++    {
++      "name": "slots",
++      "type": "uint32"
++    }
++  ],
++  "id": "libvirt-38"
++}
++
++{
++  "execute": "device-list-properties",
++  "arguments": {
++    "typename": "intel-iommu"
++  },
++  "id": "libvirt-39"
++}
++
++{
++  "return": [
++    {
++      "name": "eim",
++      "description": "on/off/auto",
++      "type": "OnOffAuto"
++    },
++    {
++      "name": "caching-mode",
++      "type": "bool"
++    },
++    {
++      "name": "x-buggy-eim",
++      "type": "bool"
++    },
++    {
++      "name": "intremap",
++      "description": "on/off/auto",
++      "type": "OnOffAuto"
++    },
++    {
++      "name": "version",
++      "type": "uint32"
++    },
++    {
++      "name": "x-scalable-mode",
++      "type": "bool"
++    },
++    {
++      "name": "dma-drain",
++      "type": "bool"
++    },
++    {
++      "name": "pt",
++      "type": "bool"
++    },
++    {
++      "name": "device-iotlb",
++      "type": "bool"
++    },
++    {
++      "name": "aw-bits",
++      "type": "uint8"
++    }
++  ],
++  "id": "libvirt-39"
++}
++
++{
++  "execute": "device-list-properties",
++  "arguments": {
++    "typename": "mch"
++  },
++  "id": "libvirt-40"
++}
++
++{
++  "return": [
++    {
++      "name": "rombar",
++      "type": "uint32"
++    },
++    {
++      "name": "x-pcie-lnksta-dllla",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "multifunction",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "extended-tseg-mbytes",
++      "type": "uint16"
++    },
++    {
++      "name": "romfile",
++      "type": "str"
++    },
++    {
++      "name": "x-pcie-extcap-init",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "command_serr_enable",
++      "description": "on/off",
++      "type": "bool"
++    },
++    {
++      "name": "addr",
++      "description": "Slot and optional function number, example: 06.0 or 06",
++      "type": "int32"
++    }
++  ],
++  "id": "libvirt-40"
++}
++
++{
++  "execute": "qom-list-properties",
++  "arguments": {
++    "typename": "memory-backend-file"
++  },
++  "id": "libvirt-41"
++}
++
++{
++  "return": [
++    {
++      "name": "type",
++      "type": "string"
++    },
++    {
++      "name": "policy",
++      "description": "Set the NUMA policy",
++      "type": "HostMemPolicy"
++    },
++    {
++      "name": "dump",
++      "description": "Set to 'off' to exclude from core dump",
++      "type": "bool"
++    },
++    {
++      "name": "share",
++      "description": "Mark the memory as private to QEMU or shared",
++      "type": "bool"
++    },
++    {
++      "name": "prealloc",
++      "description": "Preallocate memory",
++      "type": "bool"
++    },
++    {
++      "name": "size",
++      "description": "Size of the memory region (ex: 500M)",
++      "type": "int"
++    },
++    {
++      "name": "x-use-canonical-path-for-ramblock-id",
++      "type": "bool"
++    },
++    {
++      "name": "host-nodes",
++      "description": "Binds memory to the list of NUMA host nodes",
++      "type": "int"
++    },
++    {
++      "name": "merge",
++      "description": "Mark memory as mergeable",
++      "type": "bool"
++    },
++    {
++      "name": "pmem",
++      "type": "bool"
++    },
++    {
++      "name": "align",
++      "type": "int"
++    },
++    {
++      "name": "mem-path",
++      "type": "string"
++    },
++    {
++      "name": "discard-data",
++      "type": "bool"
++    }
++  ],
++  "id": "libvirt-41"
++}
++
++{
++  "execute": "qom-list-properties",
++  "arguments": {
++    "typename": "spapr-machine"
++  },
++  "id": "libvirt-42"
++}
++
++{
++  "id": "libvirt-42",
++  "error": {
++    "class": "DeviceNotFound",
++    "desc": "Class 'spapr-machine' not found"
++  }
++}
++
++{
++  "execute": "query-machines",
++  "id": "libvirt-43"
++}
++
++{
++  "return": [
++    {
++      "hotpluggable-cpus": true,
++      "name": "isapc",
++      "cpu-max": 1
++    },
++    {
++      "hotpluggable-cpus": true,
++      "name": "pc-1.1",
++      "cpu-max": 255
++    },
++    {
++      "hotpluggable-cpus": true,
++      "name": "pc-1.2",
++      "cpu-max": 255
++    },
++    {
++      "hotpluggable-cpus": true,
++      "name": "pc-1.3",
++      "cpu-max": 255
++    },
++    {
++      "hotpluggable-cpus": true,
++      "name": "pc-i440fx-2.8",
++      "cpu-max": 255
++    },
++    {
++      "hotpluggable-cpus": true,
++      "name": "pc-1.0",
++      "cpu-max": 255
++    },
++    {
++      "hotpluggable-cpus": false,
++      "name": "none",
++      "cpu-max": 1
++    },
++    {
++      "hotpluggable-cpus": true,
++      "name": "pc-i440fx-2.9",
++      "cpu-max": 255
++    },
++    {
++      "hotpluggable-cpus": true,
++      "name": "pc-i440fx-2.6",
++      "cpu-max": 255
++    },
++    {
++      "hotpluggable-cpus": true,
++      "name": "pc-i440fx-2.7",
++      "cpu-max": 255
++    },
++    {
++      "hotpluggable-cpus": true,
++      "name": "xenfv",
++      "cpu-max": 128
++    },
++    {
++      "hotpluggable-cpus": true,
++      "name": "pc-i440fx-4.1",
++      "is-default": true,
++      "cpu-max": 255,
++      "alias": "pc"
++    },
++    {
++      "hotpluggable-cpus": true,
++      "name": "pc-i440fx-2.3",
++      "cpu-max": 255
++    },
++    {
++      "hotpluggable-cpus": true,
++      "name": "pc-i440fx-2.4",
++      "cpu-max": 255
++    },
++    {
++      "hotpluggable-cpus": true,
++      "name": "pc-i440fx-2.5",
++      "cpu-max": 255
++    },
++    {
++      "hotpluggable-cpus": true,
++      "name": "pc-i440fx-4.0",
++      "cpu-max": 255
++    },
++    {
++      "hotpluggable-cpus": true,
++      "name": "pc-i440fx-2.1",
++      "cpu-max": 255
++    },
++    {
++      "hotpluggable-cpus": true,
++      "name": "pc-i440fx-2.2",
++      "cpu-max": 255
++    },
++    {
++      "hotpluggable-cpus": true,
++      "name": "pc-q35-3.1",
++      "cpu-max": 288
++    },
++    {
++      "hotpluggable-cpus": true,
++      "name": "pc-i440fx-2.0",
++      "cpu-max": 255
++    },
++    {
++      "hotpluggable-cpus": true,
++      "name": "pc-q35-2.11",
++      "cpu-max": 288
++    },
++    {
++      "hotpluggable-cpus": true,
++      "name": "pc-q35-2.12",
++      "cpu-max": 288
++    },
++    {
++      "hotpluggable-cpus": true,
++      "name": "pc-q35-3.0",
++      "cpu-max": 288
++    },
++    {
++      "hotpluggable-cpus": false,
++      "name": "xenpv",
++      "cpu-max": 1
++    },
++    {
++      "hotpluggable-cpus": true,
++      "name": "pc-q35-2.10",
++      "cpu-max": 288
++    },
++    {
++      "hotpluggable-cpus": true,
++      "name": "pc-q35-4.0.1",
++      "cpu-max": 288
++    },
++    {
++      "hotpluggable-cpus": true,
++      "name": "pc-i440fx-1.7",
++      "cpu-max": 255
++    },
++    {
++      "hotpluggable-cpus": true,
++      "name": "pc-q35-2.9",
++      "cpu-max": 288
++    },
++    {
++      "hotpluggable-cpus": true,
++      "name": "pc-0.15",
++      "cpu-max": 255
++    },
++    {
++      "hotpluggable-cpus": true,
++      "name": "pc-i440fx-1.5",
++      "cpu-max": 255
++    },
++    {
++      "hotpluggable-cpus": true,
++      "name": "pc-q35-2.7",
++      "cpu-max": 255
++    },
++    {
++      "hotpluggable-cpus": true,
++      "name": "pc-i440fx-1.6",
++      "cpu-max": 255
++    },
++    {
++      "hotpluggable-cpus": true,
++      "name": "pc-i440fx-2.11",
++      "cpu-max": 255
++    },
++    {
++      "hotpluggable-cpus": true,
++      "name": "pc-q35-2.8",
++      "cpu-max": 288
++    },
++    {
++      "hotpluggable-cpus": true,
++      "name": "pc-0.13",
++      "cpu-max": 255
++    },
++    {
++      "hotpluggable-cpus": true,
++      "name": "pc-i440fx-2.12",
++      "cpu-max": 255
++    },
++    {
++      "hotpluggable-cpus": true,
++      "name": "pc-0.14",
++      "cpu-max": 255
++    },
++    {
++      "hotpluggable-cpus": true,
++      "name": "pc-i440fx-3.0",
++      "cpu-max": 255
++    },
++    {
++      "hotpluggable-cpus": true,
++      "name": "pc-i440fx-3.1",
++      "cpu-max": 255
++    },
++    {
++      "hotpluggable-cpus": true,
++      "name": "pc-q35-2.4",
++      "cpu-max": 255
++    },
++    {
++      "hotpluggable-cpus": true,
++      "name": "pc-q35-2.5",
++      "cpu-max": 255
++    },
++    {
++      "hotpluggable-cpus": true,
++      "name": "pc-q35-2.6",
++      "cpu-max": 255
++    },
++    {
++      "hotpluggable-cpus": true,
++      "name": "pc-i440fx-1.4",
++      "cpu-max": 255
++    },
++    {
++      "hotpluggable-cpus": true,
++      "name": "pc-i440fx-2.10",
++      "cpu-max": 255
++    },
++    {
++      "hotpluggable-cpus": true,
++      "name": "pc-0.12",
++      "cpu-max": 255
++    },
++    {
++      "hotpluggable-cpus": true,
++      "name": "pc-q35-4.0",
++      "cpu-max": 288
++    },
++    {
++      "hotpluggable-cpus": true,
++      "name": "pc-q35-4.1",
++      "cpu-max": 288,
++      "alias": "q35"
++    }
++  ],
++  "id": "libvirt-43"
++}
++
++{
++  "execute": "query-cpu-definitions",
++  "id": "libvirt-44"
++}
++
++{
++  "return": [
++    {
++      "name": "max",
++      "typename": "max-x86_64-cpu",
++      "unavailable-features": [
++      ],
++      "static": false,
++      "migration-safe": false
++    },
++    {
++      "name": "host",
++      "typename": "host-x86_64-cpu",
++      "unavailable-features": [
++      ],
++      "static": false,
++      "migration-safe": false
++    },
++    {
++      "name": "base",
++      "typename": "base-x86_64-cpu",
++      "unavailable-features": [
++      ],
++      "static": true,
++      "migration-safe": true
++    },
++    {
++      "name": "qemu64",
++      "typename": "qemu64-x86_64-cpu",
++      "unavailable-features": [
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "qemu32",
++      "typename": "qemu32-x86_64-cpu",
++      "unavailable-features": [
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "phenom",
++      "typename": "phenom-x86_64-cpu",
++      "unavailable-features": [
++        "mmxext",
++        "fxsr-opt",
++        "3dnowext",
++        "3dnow",
++        "sse4a",
++        "npt"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "pentium3",
++      "typename": "pentium3-x86_64-cpu",
++      "unavailable-features": [
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "pentium2",
++      "typename": "pentium2-x86_64-cpu",
++      "unavailable-features": [
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "pentium",
++      "typename": "pentium-x86_64-cpu",
++      "unavailable-features": [
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "n270",
++      "typename": "n270-x86_64-cpu",
++      "unavailable-features": [
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "kvm64",
++      "typename": "kvm64-x86_64-cpu",
++      "unavailable-features": [
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "kvm32",
++      "typename": "kvm32-x86_64-cpu",
++      "unavailable-features": [
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "coreduo",
++      "typename": "coreduo-x86_64-cpu",
++      "unavailable-features": [
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "core2duo",
++      "typename": "core2duo-x86_64-cpu",
++      "unavailable-features": [
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "athlon",
++      "typename": "athlon-x86_64-cpu",
++      "unavailable-features": [
++        "mmxext",
++        "3dnowext",
++        "3dnow"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Westmere-IBRS",
++      "typename": "Westmere-IBRS-x86_64-cpu",
++      "unavailable-features": [
++        "spec-ctrl"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Westmere",
++      "typename": "Westmere-x86_64-cpu",
++      "unavailable-features": [
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Skylake-Server-IBRS",
++      "typename": "Skylake-Server-IBRS-x86_64-cpu",
++      "unavailable-features": [
++        "avx512f",
++        "avx512dq",
++        "clwb",
++        "avx512cd",
++        "avx512bw",
++        "avx512vl",
++        "pku",
++        "spec-ctrl",
++        "avx512f",
++        "avx512f",
++        "avx512f",
++        "pku"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Skylake-Server",
++      "typename": "Skylake-Server-x86_64-cpu",
++      "unavailable-features": [
++        "avx512f",
++        "avx512dq",
++        "clwb",
++        "avx512cd",
++        "avx512bw",
++        "avx512vl",
++        "pku",
++        "avx512f",
++        "avx512f",
++        "avx512f",
++        "pku"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Skylake-Client-IBRS",
++      "typename": "Skylake-Client-IBRS-x86_64-cpu",
++      "unavailable-features": [
++        "spec-ctrl"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Skylake-Client",
++      "typename": "Skylake-Client-x86_64-cpu",
++      "unavailable-features": [
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "SandyBridge-IBRS",
++      "typename": "SandyBridge-IBRS-x86_64-cpu",
++      "unavailable-features": [
++        "spec-ctrl"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "SandyBridge",
++      "typename": "SandyBridge-x86_64-cpu",
++      "unavailable-features": [
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Penryn",
++      "typename": "Penryn-x86_64-cpu",
++      "unavailable-features": [
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Opteron_G5",
++      "typename": "Opteron_G5-x86_64-cpu",
++      "unavailable-features": [
++        "sse4a",
++        "misalignsse",
++        "xop",
++        "fma4",
++        "tbm",
++        "npt",
++        "nrip-save"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Opteron_G4",
++      "typename": "Opteron_G4-x86_64-cpu",
++      "unavailable-features": [
++        "sse4a",
++        "misalignsse",
++        "xop",
++        "fma4",
++        "npt",
++        "nrip-save"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Opteron_G3",
++      "typename": "Opteron_G3-x86_64-cpu",
++      "unavailable-features": [
++        "sse4a",
++        "misalignsse"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Opteron_G2",
++      "typename": "Opteron_G2-x86_64-cpu",
++      "unavailable-features": [
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Opteron_G1",
++      "typename": "Opteron_G1-x86_64-cpu",
++      "unavailable-features": [
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Nehalem-IBRS",
++      "typename": "Nehalem-IBRS-x86_64-cpu",
++      "unavailable-features": [
++        "spec-ctrl"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Nehalem",
++      "typename": "Nehalem-x86_64-cpu",
++      "unavailable-features": [
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "KnightsMill",
++      "typename": "KnightsMill-x86_64-cpu",
++      "unavailable-features": [
++        "avx512f",
++        "avx512pf",
++        "avx512er",
++        "avx512cd",
++        "avx512-vpopcntdq",
++        "avx512-4vnniw",
++        "avx512-4fmaps",
++        "avx512f",
++        "avx512f",
++        "avx512f"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "IvyBridge-IBRS",
++      "typename": "IvyBridge-IBRS-x86_64-cpu",
++      "unavailable-features": [
++        "spec-ctrl"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "IvyBridge",
++      "typename": "IvyBridge-x86_64-cpu",
++      "unavailable-features": [
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Icelake-Server",
++      "typename": "Icelake-Server-x86_64-cpu",
++      "unavailable-features": [
++        "avx512f",
++        "avx512dq",
++        "clwb",
++        "avx512cd",
++        "avx512bw",
++        "avx512vl",
++        "avx512vbmi",
++        "pku",
++        "avx512vbmi2",
++        "gfni",
++        "vaes",
++        "vpclmulqdq",
++        "avx512vnni",
++        "avx512bitalg",
++        "avx512-vpopcntdq",
++        "la57",
++        "spec-ctrl",
++        "ssbd",
++        "wbnoinvd",
++        "avx512f",
++        "avx512f",
++        "avx512f",
++        "pku"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Icelake-Client",
++      "typename": "Icelake-Client-x86_64-cpu",
++      "unavailable-features": [
++        "avx512vbmi",
++        "pku",
++        "avx512vbmi2",
++        "gfni",
++        "vaes",
++        "vpclmulqdq",
++        "avx512vnni",
++        "avx512bitalg",
++        "avx512-vpopcntdq",
++        "spec-ctrl",
++        "ssbd",
++        "wbnoinvd",
++        "pku"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Haswell-noTSX-IBRS",
++      "typename": "Haswell-noTSX-IBRS-x86_64-cpu",
++      "unavailable-features": [
++        "spec-ctrl"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Haswell-noTSX",
++      "typename": "Haswell-noTSX-x86_64-cpu",
++      "unavailable-features": [
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Haswell-IBRS",
++      "typename": "Haswell-IBRS-x86_64-cpu",
++      "unavailable-features": [
++        "spec-ctrl"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Haswell",
++      "typename": "Haswell-x86_64-cpu",
++      "unavailable-features": [
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "EPYC-IBPB",
++      "typename": "EPYC-IBPB-x86_64-cpu",
++      "unavailable-features": [
++        "sha-ni",
++        "mmxext",
++        "fxsr-opt",
++        "cr8legacy",
++        "sse4a",
++        "misalignsse",
++        "osvw",
++        "ibpb",
++        "npt",
++        "nrip-save"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "EPYC",
++      "typename": "EPYC-x86_64-cpu",
++      "unavailable-features": [
++        "sha-ni",
++        "mmxext",
++        "fxsr-opt",
++        "cr8legacy",
++        "sse4a",
++        "misalignsse",
++        "osvw",
++        "npt",
++        "nrip-save"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Dhyana",
++      "typename": "Dhyana-x86_64-cpu",
++      "unavailable-features": [
++        "mmxext",
++        "fxsr-opt",
++        "cr8legacy",
++        "sse4a",
++        "misalignsse",
++        "osvw",
++        "ibpb",
++        "npt",
++        "nrip-save"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Conroe",
++      "typename": "Conroe-x86_64-cpu",
++      "unavailable-features": [
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Cascadelake-Server",
++      "typename": "Cascadelake-Server-x86_64-cpu",
++      "unavailable-features": [
++        "avx512f",
++        "avx512dq",
++        "clwb",
++        "avx512cd",
++        "avx512bw",
++        "avx512vl",
++        "pku",
++        "avx512vnni",
++        "spec-ctrl",
++        "ssbd",
++        "avx512f",
++        "avx512f",
++        "avx512f",
++        "pku"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Broadwell-noTSX-IBRS",
++      "typename": "Broadwell-noTSX-IBRS-x86_64-cpu",
++      "unavailable-features": [
++        "spec-ctrl"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Broadwell-noTSX",
++      "typename": "Broadwell-noTSX-x86_64-cpu",
++      "unavailable-features": [
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Broadwell-IBRS",
++      "typename": "Broadwell-IBRS-x86_64-cpu",
++      "unavailable-features": [
++        "spec-ctrl"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Broadwell",
++      "typename": "Broadwell-x86_64-cpu",
++      "unavailable-features": [
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "486",
++      "typename": "486-x86_64-cpu",
++      "unavailable-features": [
++      ],
++      "static": false,
++      "migration-safe": true
++    }
++  ],
++  "id": "libvirt-44"
++}
++
++{
++  "execute": "query-tpm-models",
++  "id": "libvirt-45"
++}
++
++{
++  "return": [
++    "tpm-crb",
++    "tpm-tis"
++  ],
++  "id": "libvirt-45"
++}
++
++{
++  "execute": "query-tpm-types",
++  "id": "libvirt-46"
++}
++
++{
++  "return": [
++    "passthrough",
++    "emulator"
++  ],
++  "id": "libvirt-46"
++}
++
++{
++  "execute": "query-command-line-options",
++  "id": "libvirt-47"
++}
++
++{
++  "return": [
++    {
++      "parameters": [
++        {
++          "name": "timeout",
++          "help": "Request timeout in seconds (default 0 = no timeout)",
++          "type": "number"
++        },
++        {
++          "name": "initiator-name",
++          "help": "Initiator iqn name to use when connecting",
++          "type": "string"
++        },
++        {
++          "name": "header-digest",
++          "help": "HeaderDigest setting. {CRC32C|CRC32C-NONE|NONE-CRC32C|NONE}",
++          "type": "string"
++        },
++        {
++          "name": "password-secret",
++          "help": "ID of the secret providing password for CHAP authentication to target",
++          "type": "string"
++        },
++        {
++          "name": "password",
++          "help": "password for CHAP authentication to target",
++          "type": "string"
++        },
++        {
++          "name": "user",
++          "help": "username for CHAP authentication to target",
++          "type": "string"
++        }
++      ],
++      "option": "iscsi"
++    },
++    {
++      "parameters": [
++        {
++          "name": "non-adaptive",
++          "type": "boolean"
++        },
++        {
++          "name": "lossy",
++          "type": "boolean"
++        },
++        {
++          "name": "sasl-authz",
++          "type": "string"
++        },
++        {
++          "name": "tls-authz",
++          "type": "string"
++        },
++        {
++          "name": "acl",
++          "type": "boolean"
++        },
++        {
++          "name": "sasl",
++          "type": "boolean"
++        },
++        {
++          "name": "key-delay-ms",
++          "type": "number"
++        },
++        {
++          "name": "lock-key-sync",
++          "type": "boolean"
++        },
++        {
++          "name": "reverse",
++          "type": "boolean"
++        },
++        {
++          "name": "password",
++          "type": "boolean"
++        },
++        {
++          "name": "ipv6",
++          "type": "boolean"
++        },
++        {
++          "name": "ipv4",
++          "type": "boolean"
++        },
++        {
++          "name": "to",
++          "type": "number"
++        },
++        {
++          "name": "connections",
++          "type": "number"
++        },
++        {
++          "name": "head",
++          "type": "number"
++        },
++        {
++          "name": "display",
++          "type": "string"
++        },
++        {
++          "name": "share",
++          "type": "string"
++        },
++        {
++          "name": "tls-creds",
++          "type": "string"
++        },
++        {
++          "name": "websocket",
++          "type": "string"
++        },
++        {
++          "name": "vnc",
++          "type": "string"
++        }
++      ],
++      "option": "vnc"
++    },
++    {
++      "parameters": [
++        {
++          "name": "rendernode",
++          "type": "string"
++        },
++        {
++          "name": "gl",
++          "type": "boolean"
++        },
++        {
++          "name": "head",
++          "type": "number"
++        },
++        {
++          "name": "display",
++          "type": "string"
++        },
++        {
++          "name": "seamless-migration",
++          "type": "boolean"
++        },
++        {
++          "name": "playback-compression",
++          "type": "boolean"
++        },
++        {
++          "name": "agent-mouse",
++          "type": "boolean"
++        },
++        {
++          "name": "streaming-video",
++          "type": "string"
++        },
++        {
++          "name": "zlib-glz-wan-compression",
++          "type": "string"
++        },
++        {
++          "name": "jpeg-wan-compression",
++          "type": "string"
++        },
++        {
++          "name": "image-compression",
++          "type": "string"
++        },
++        {
++          "name": "plaintext-channel",
++          "type": "string"
++        },
++        {
++          "name": "tls-channel",
++          "type": "string"
++        },
++        {
++          "name": "tls-ciphers",
++          "type": "string"
++        },
++        {
++          "name": "x509-dh-key-file",
++          "type": "string"
++        },
++        {
++          "name": "x509-cacert-file",
++          "type": "string"
++        },
++        {
++          "name": "x509-cert-file",
++          "type": "string"
++        },
++        {
++          "name": "x509-key-password",
++          "type": "string"
++        },
++        {
++          "name": "x509-key-file",
++          "type": "string"
++        },
++        {
++          "name": "x509-dir",
++          "type": "string"
++        },
++        {
++          "name": "sasl",
++          "type": "boolean"
++        },
++        {
++          "name": "disable-agent-file-xfer",
++          "type": "boolean"
++        },
++        {
++          "name": "disable-copy-paste",
++          "type": "boolean"
++        },
++        {
++          "name": "disable-ticketing",
++          "type": "boolean"
++        },
++        {
++          "name": "password",
++          "type": "string"
++        },
++        {
++          "name": "unix",
++          "type": "boolean"
++        },
++        {
++          "name": "ipv6",
++          "type": "boolean"
++        },
++        {
++          "name": "ipv4",
++          "type": "boolean"
++        },
++        {
++          "name": "addr",
++          "type": "string"
++        },
++        {
++          "name": "tls-port",
++          "type": "number"
++        },
++        {
++          "name": "port",
++          "type": "number"
++        }
++      ],
++      "option": "spice"
++    },
++    {
++      "parameters": [
++      ],
++      "option": "smbios"
++    },
++    {
++      "parameters": [
++      ],
++      "option": "acpi"
++    },
++    {
++      "parameters": [
++        {
++          "name": "dmode",
++          "type": "number"
++        },
++        {
++          "name": "fmode",
++          "type": "number"
++        },
++        {
++          "name": "sock_fd",
++          "type": "number"
++        },
++        {
++          "name": "socket",
++          "type": "string"
++        },
++        {
++          "name": "readonly",
++          "type": "boolean"
++        },
++        {
++          "name": "writeout",
++          "type": "string"
++        },
++        {
++          "name": "security_model",
++          "type": "string"
++        },
++        {
++          "name": "mount_tag",
++          "type": "string"
++        },
++        {
++          "name": "path",
++          "type": "string"
++        },
++        {
++          "name": "fsdriver",
++          "type": "string"
++        }
++      ],
++      "option": "virtfs"
++    },
++    {
++      "parameters": [
++        {
++          "name": "throttling.iops-size",
++          "help": "when limiting by iops max size of an I/O in bytes",
++          "type": "number"
++        },
++        {
++          "name": "throttling.bps-write-max-length",
++          "help": "length of the bps-write-max burst period, in seconds",
++          "type": "number"
++        },
++        {
++          "name": "throttling.bps-read-max-length",
++          "help": "length of the bps-read-max burst period, in seconds",
++          "type": "number"
++        },
++        {
++          "name": "throttling.bps-total-max-length",
++          "help": "length of the bps-total-max burst period, in seconds",
++          "type": "number"
++        },
++        {
++          "name": "throttling.iops-write-max-length",
++          "help": "length of the iops-write-max burst period, in seconds",
++          "type": "number"
++        },
++        {
++          "name": "throttling.iops-read-max-length",
++          "help": "length of the iops-read-max burst period, in seconds",
++          "type": "number"
++        },
++        {
++          "name": "throttling.iops-total-max-length",
++          "help": "length of the iops-total-max burst period, in seconds",
++          "type": "number"
++        },
++        {
++          "name": "throttling.bps-write-max",
++          "help": "total bytes write burst",
++          "type": "number"
++        },
++        {
++          "name": "throttling.bps-read-max",
++          "help": "total bytes read burst",
++          "type": "number"
++        },
++        {
++          "name": "throttling.bps-total-max",
++          "help": "total bytes burst",
++          "type": "number"
++        },
++        {
++          "name": "throttling.iops-write-max",
++          "help": "I/O operations write burst",
++          "type": "number"
++        },
++        {
++          "name": "throttling.iops-read-max",
++          "help": "I/O operations read burst",
++          "type": "number"
++        },
++        {
++          "name": "throttling.iops-total-max",
++          "help": "I/O operations burst",
++          "type": "number"
++        },
++        {
++          "name": "throttling.bps-write",
++          "help": "limit write bytes per second",
++          "type": "number"
++        },
++        {
++          "name": "throttling.bps-read",
++          "help": "limit read bytes per second",
++          "type": "number"
++        },
++        {
++          "name": "throttling.bps-total",
++          "help": "limit total bytes per second",
++          "type": "number"
++        },
++        {
++          "name": "throttling.iops-write",
++          "help": "limit write operations per second",
++          "type": "number"
++        },
++        {
++          "name": "throttling.iops-read",
++          "help": "limit read operations per second",
++          "type": "number"
++        },
++        {
++          "name": "throttling.iops-total",
++          "help": "limit total I/O operations per second",
++          "type": "number"
++        },
++        {
++          "name": "dmode",
++          "type": "number"
++        },
++        {
++          "name": "fmode",
++          "type": "number"
++        },
++        {
++          "name": "sock_fd",
++          "type": "number"
++        },
++        {
++          "name": "socket",
++          "type": "string"
++        },
++        {
++          "name": "readonly",
++          "type": "boolean"
++        },
++        {
++          "name": "writeout",
++          "type": "string"
++        },
++        {
++          "name": "security_model",
++          "type": "string"
++        },
++        {
++          "name": "path",
++          "type": "string"
++        },
++        {
++          "name": "fsdriver",
++          "type": "string"
++        }
++      ],
++      "option": "fsdev"
++    },
++    {
++      "parameters": [
++        {
++          "name": "resourcecontrol",
++          "type": "string"
++        },
++        {
++          "name": "spawn",
++          "type": "string"
++        },
++        {
++          "name": "elevateprivileges",
++          "type": "string"
++        },
++        {
++          "name": "obsolete",
++          "type": "string"
++        },
++        {
++          "name": "enable",
++          "type": "boolean"
++        }
++      ],
++      "option": "sandbox"
++    },
++    {
++      "parameters": [
++        {
++          "name": "string",
++          "help": "Sets content of the blob to be inserted from a string",
++          "type": "string"
++        },
++        {
++          "name": "file",
++          "help": "Sets the name of the file from which the fw_cfg blob will be loaded",
++          "type": "string"
++        },
++        {
++          "name": "name",
++          "help": "Sets the fw_cfg name of the blob to be inserted",
++          "type": "string"
++        }
++      ],
++      "option": "fw_cfg"
++    },
++    {
++      "parameters": [
++      ],
++      "option": ""
++    },
++    {
++      "parameters": [
++        {
++          "name": "rrsnapshot",
++          "type": "string"
++        },
++        {
++          "name": "rrfile",
++          "type": "string"
++        },
++        {
++          "name": "rr",
++          "type": "string"
++        },
++        {
++          "name": "sleep",
++          "type": "boolean"
++        },
++        {
++          "name": "align",
++          "type": "boolean"
++        },
++        {
++          "name": "shift",
++          "type": "string"
++        }
++      ],
++      "option": "icount"
++    },
++    {
++      "parameters": [
++      ],
++      "option": "numa"
++    },
++    {
++      "parameters": [
++        {
++          "name": "debug-threads",
++          "help": "When enabled, name the individual threads; defaults off.\nNOTE: The thread names are for debugging and not a\nstable API.",
++          "type": "boolean"
++        },
++        {
++          "name": "process",
++          "help": "Sets the name of the QEMU process, as shown in top etc",
++          "type": "string"
++        },
++        {
++          "name": "guest",
++          "help": "Sets the name of the guest.\nThis name will be displayed in the SDL window caption.\nThe name will also be used for the VNC server",
++          "type": "string"
++        }
++      ],
++      "option": "name"
++    },
++    {
++      "parameters": [
++        {
++          "name": "timestamp",
++          "type": "boolean"
++        }
++      ],
++      "option": "msg"
++    },
++    {
++      "parameters": [
++        {
++          "name": "cpu-pm",
++          "type": "boolean"
++        },
++        {
++          "name": "mem-lock",
++          "type": "boolean"
++        }
++      ],
++      "option": "overcommit"
++    },
++    {
++      "parameters": [
++        {
++          "name": "mlock",
++          "type": "boolean"
++        }
++      ],
++      "option": "realtime"
++    },
++    {
++      "parameters": [
++      ],
++      "option": "tpmdev"
++    },
++    {
++      "parameters": [
++      ],
++      "option": "object"
++    },
++    {
++      "parameters": [
++        {
++          "name": "opaque",
++          "help": "free-form string used to describe fd",
++          "type": "string"
++        },
++        {
++          "name": "set",
++          "help": "ID of the fd set to add fd to",
++          "type": "number"
++        },
++        {
++          "name": "fd",
++          "help": "file descriptor of which a duplicate is added to fd set",
++          "type": "number"
++        }
++      ],
++      "option": "add-fd"
++    },
++    {
++      "parameters": [
++        {
++          "name": "strict",
++          "type": "boolean"
++        },
++        {
++          "name": "reboot-timeout",
++          "type": "number"
++        },
++        {
++          "name": "splash-time",
++          "type": "number"
++        },
++        {
++          "name": "splash",
++          "type": "string"
++        },
++        {
++          "name": "menu",
++          "type": "boolean"
++        },
++        {
++          "name": "once",
++          "type": "string"
++        },
++        {
++          "name": "order",
++          "type": "string"
++        }
++      ],
++      "option": "boot-opts"
++    },
++    {
++      "parameters": [
++        {
++          "name": "maxcpus",
++          "type": "number"
++        },
++        {
++          "name": "threads",
++          "type": "number"
++        },
++        {
++          "name": "cores",
++          "type": "number"
++        },
++        {
++          "name": "sockets",
++          "type": "number"
++        },
++        {
++          "name": "cpus",
++          "type": "number"
++        }
++      ],
++      "option": "smp-opts"
++    },
++    {
++      "parameters": [
++        {
++          "name": "maxmem",
++          "type": "size"
++        },
++        {
++          "name": "slots",
++          "type": "number"
++        },
++        {
++          "name": "size",
++          "type": "size"
++        }
++      ],
++      "option": "memory"
++    },
++    {
++      "parameters": [
++        {
++          "name": "thread",
++          "help": "Enable/disable multi-threaded TCG",
++          "type": "string"
++        },
++        {
++          "name": "accel",
++          "help": "Select the type of accelerator",
++          "type": "string"
++        }
++      ],
++      "option": "accel"
++    },
++    {
++      "parameters": [
++        {
++          "name": "loadparm",
++          "help": "Up to 8 chars in set of [A-Za-z0-9. ](lower case chars converted to upper case) to pass to machine loader, boot manager, and guest kernel",
++          "type": "string"
++        },
++        {
++          "name": "dea-key-wrap",
++          "help": "enable/disable DEA key wrapping using the CPACF wrapping key",
++          "type": "boolean"
++        },
++        {
++          "name": "aes-key-wrap",
++          "help": "enable/disable AES key wrapping using the CPACF wrapping key",
++          "type": "boolean"
++        },
++        {
++          "name": "suppress-vmdesc",
++          "help": "Set on to disable self-describing migration",
++          "type": "boolean"
++        },
++        {
++          "name": "iommu",
++          "help": "Set on/off to enable/disable Intel IOMMU (VT-d)",
++          "type": "boolean"
++        },
++        {
++          "name": "firmware",
++          "help": "firmware image",
++          "type": "string"
++        },
++        {
++          "name": "usb",
++          "help": "Set on/off to enable/disable usb",
++          "type": "boolean"
++        },
++        {
++          "name": "mem-merge",
++          "help": "enable/disable memory merge support",
++          "type": "boolean"
++        },
++        {
++          "name": "dump-guest-core",
++          "help": "Include guest memory in  a core dump",
++          "type": "boolean"
++        },
++        {
++          "name": "dt_compatible",
++          "help": "Overrides the \"compatible\" property of the dt root node",
++          "type": "string"
++        },
++        {
++          "name": "phandle_start",
++          "help": "The first phandle ID we may generate dynamically",
++          "type": "number"
++        },
++        {
++          "name": "dumpdtb",
++          "help": "Dump current dtb to a file and quit",
++          "type": "string"
++        },
++        {
++          "name": "dtb",
++          "help": "Linux kernel device tree file",
++          "type": "string"
++        },
++        {
++          "name": "append",
++          "help": "Linux kernel command line",
++          "type": "string"
++        },
++        {
++          "name": "initrd",
++          "help": "Linux initial ramdisk file",
++          "type": "string"
++        },
++        {
++          "name": "kernel",
++          "help": "Linux kernel image file",
++          "type": "string"
++        },
++        {
++          "name": "kvm_shadow_mem",
++          "help": "KVM shadow MMU size",
++          "type": "size"
++        },
++        {
++          "name": "kernel_irqchip",
++          "help": "use KVM in-kernel irqchip",
++          "type": "boolean"
++        },
++        {
++          "name": "accel",
++          "help": "accelerator list",
++          "type": "string"
++        },
++        {
++          "name": "type",
++          "help": "emulated machine",
++          "type": "string"
++        }
++      ],
++      "option": "machine"
++    },
++    {
++      "parameters": [
++        {
++          "name": "romfile",
++          "type": "string"
++        },
++        {
++          "name": "bootindex",
++          "type": "number"
++        }
++      ],
++      "option": "option-rom"
++    },
++    {
++      "parameters": [
++        {
++          "name": "file",
++          "type": "string"
++        },
++        {
++          "name": "events",
++          "type": "string"
++        },
++        {
++          "name": "enable",
++          "type": "string"
++        }
++      ],
++      "option": "trace"
++    },
++    {
++      "parameters": [
++        {
++          "name": "pretty",
++          "type": "boolean"
++        },
++        {
++          "name": "chardev",
++          "type": "string"
++        },
++        {
++          "name": "mode",
++          "type": "string"
++        }
++      ],
++      "option": "mon"
++    },
++    {
++      "parameters": [
++        {
++          "name": "value",
++          "type": "string"
++        },
++        {
++          "name": "property",
++          "type": "string"
++        },
++        {
++          "name": "driver",
++          "type": "string"
++        }
++      ],
++      "option": "global"
++    },
++    {
++      "parameters": [
++        {
++          "name": "driftfix",
++          "type": "string"
++        },
++        {
++          "name": "clock",
++          "type": "string"
++        },
++        {
++          "name": "base",
++          "type": "string"
++        }
++      ],
++      "option": "rtc"
++    },
++    {
++      "parameters": [
++      ],
++      "option": "net"
++    },
++    {
++      "parameters": [
++      ],
++      "option": "nic"
++    },
++    {
++      "parameters": [
++      ],
++      "option": "netdev"
++    },
++    {
++      "parameters": [
++      ],
++      "option": "device"
++    },
++    {
++      "parameters": [
++        {
++          "name": "logappend",
++          "type": "boolean"
++        },
++        {
++          "name": "logfile",
++          "type": "string"
++        },
++        {
++          "name": "append",
++          "type": "boolean"
++        },
++        {
++          "name": "chardev",
++          "type": "string"
++        },
++        {
++          "name": "size",
++          "type": "size"
++        },
++        {
++          "name": "debug",
++          "type": "number"
++        },
++        {
++          "name": "name",
++          "type": "string"
++        },
++        {
++          "name": "signal",
++          "type": "boolean"
++        },
++        {
++          "name": "mux",
++          "type": "boolean"
++        },
++        {
++          "name": "rows",
++          "type": "number"
++        },
++        {
++          "name": "cols",
++          "type": "number"
++        },
++        {
++          "name": "height",
++          "type": "number"
++        },
++        {
++          "name": "width",
++          "type": "number"
++        },
++        {
++          "name": "websocket",
++          "type": "boolean"
++        },
++        {
++          "name": "tls-authz",
++          "type": "string"
++        },
++        {
++          "name": "tls-creds",
++          "type": "string"
++        },
++        {
++          "name": "tn3270",
++          "type": "boolean"
++        },
++        {
++          "name": "telnet",
++          "type": "boolean"
++        },
++        {
++          "name": "reconnect",
++          "type": "number"
++        },
++        {
++          "name": "delay",
++          "type": "boolean"
++        },
++        {
++          "name": "server",
++          "type": "boolean"
++        },
++        {
++          "name": "wait",
++          "type": "boolean"
++        },
++        {
++          "name": "ipv6",
++          "type": "boolean"
++        },
++        {
++          "name": "ipv4",
++          "type": "boolean"
++        },
++        {
++          "name": "to",
++          "type": "number"
++        },
++        {
++          "name": "localport",
++          "type": "string"
++        },
++        {
++          "name": "localaddr",
++          "type": "string"
++        },
++        {
++          "name": "fd",
++          "type": "string"
++        },
++        {
++          "name": "port",
++          "type": "string"
++        },
++        {
++          "name": "host",
++          "type": "string"
++        },
++        {
++          "name": "path",
++          "type": "string"
++        },
++        {
++          "name": "backend",
++          "type": "string"
++        }
++      ],
++      "option": "chardev"
++    },
++    {
++      "parameters": [
++        {
++          "name": "copy-on-read",
++          "help": "copy read data from backing file into image file",
++          "type": "boolean"
++        },
++        {
++          "name": "werror",
++          "help": "write error action",
++          "type": "string"
++        },
++        {
++          "name": "rerror",
++          "help": "read error action",
++          "type": "string"
++        },
++        {
++          "name": "read-only",
++          "help": "open drive file as read-only",
++          "type": "boolean"
++        },
++        {
++          "name": "file",
++          "help": "file name",
++          "type": "string"
++        },
++        {
++          "name": "if",
++          "help": "interface (ide, scsi, sd, mtd, floppy, pflash, virtio)",
++          "type": "string"
++        },
++        {
++          "name": "media",
++          "help": "media type (disk, cdrom)",
++          "type": "string"
++        },
++        {
++          "name": "index",
++          "help": "index number",
++          "type": "number"
++        },
++        {
++          "name": "unit",
++          "help": "unit number (i.e. lun for scsi)",
++          "type": "number"
++        },
++        {
++          "name": "bus",
++          "help": "bus number",
++          "type": "number"
++        },
++        {
++          "name": "stats-account-failed",
++          "help": "whether to account for failed I/O operations in the statistics",
++          "type": "boolean"
++        },
++        {
++          "name": "stats-account-invalid",
++          "help": "whether to account for invalid I/O operations in the statistics",
++          "type": "boolean"
++        },
++        {
++          "name": "detect-zeroes",
++          "help": "try to optimize zero writes (off, on, unmap)",
++          "type": "string"
++        },
++        {
++          "name": "throttling.group",
++          "help": "name of the block throttling group",
++          "type": "string"
++        },
++        {
++          "name": "throttling.iops-size",
++          "help": "when limiting by iops max size of an I/O in bytes",
++          "type": "number"
++        },
++        {
++          "name": "throttling.bps-write-max-length",
++          "help": "length of the bps-write-max burst period, in seconds",
++          "type": "number"
++        },
++        {
++          "name": "throttling.bps-read-max-length",
++          "help": "length of the bps-read-max burst period, in seconds",
++          "type": "number"
++        },
++        {
++          "name": "throttling.bps-total-max-length",
++          "help": "length of the bps-total-max burst period, in seconds",
++          "type": "number"
++        },
++        {
++          "name": "throttling.iops-write-max-length",
++          "help": "length of the iops-write-max burst period, in seconds",
++          "type": "number"
++        },
++        {
++          "name": "throttling.iops-read-max-length",
++          "help": "length of the iops-read-max burst period, in seconds",
++          "type": "number"
++        },
++        {
++          "name": "throttling.iops-total-max-length",
++          "help": "length of the iops-total-max burst period, in seconds",
++          "type": "number"
++        },
++        {
++          "name": "throttling.bps-write-max",
++          "help": "total bytes write burst",
++          "type": "number"
++        },
++        {
++          "name": "throttling.bps-read-max",
++          "help": "total bytes read burst",
++          "type": "number"
++        },
++        {
++          "name": "throttling.bps-total-max",
++          "help": "total bytes burst",
++          "type": "number"
++        },
++        {
++          "name": "throttling.iops-write-max",
++          "help": "I/O operations write burst",
++          "type": "number"
++        },
++        {
++          "name": "throttling.iops-read-max",
++          "help": "I/O operations read burst",
++          "type": "number"
++        },
++        {
++          "name": "throttling.iops-total-max",
++          "help": "I/O operations burst",
++          "type": "number"
++        },
++        {
++          "name": "throttling.bps-write",
++          "help": "limit write bytes per second",
++          "type": "number"
++        },
++        {
++          "name": "throttling.bps-read",
++          "help": "limit read bytes per second",
++          "type": "number"
++        },
++        {
++          "name": "throttling.bps-total",
++          "help": "limit total bytes per second",
++          "type": "number"
++        },
++        {
++          "name": "throttling.iops-write",
++          "help": "limit write operations per second",
++          "type": "number"
++        },
++        {
++          "name": "throttling.iops-read",
++          "help": "limit read operations per second",
++          "type": "number"
++        },
++        {
++          "name": "throttling.iops-total",
++          "help": "limit total I/O operations per second",
++          "type": "number"
++        },
++        {
++          "name": "werror",
++          "help": "write error action",
++          "type": "string"
++        },
++        {
++          "name": "format",
++          "help": "disk format (raw, qcow2, ...)",
++          "type": "string"
++        },
++        {
++          "name": "cache.writeback",
++          "help": "Enable writeback mode",
++          "type": "boolean"
++        },
++        {
++          "name": "aio",
++          "help": "host AIO implementation (threads, native)",
++          "type": "string"
++        },
++        {
++          "name": "snapshot",
++          "help": "enable/disable snapshot mode",
++          "type": "boolean"
++        },
++        {
++          "name": "force-share",
++          "help": "always accept other writers (default: off)",
++          "type": "boolean"
++        },
++        {
++          "name": "discard",
++          "help": "discard operation (ignore/off, unmap/on)",
++          "type": "string"
++        },
++        {
++          "name": "auto-read-only",
++          "help": "Node can become read-only if opening read-write fails",
++          "type": "boolean"
++        },
++        {
++          "name": "cache.no-flush",
++          "help": "Ignore flush requests",
++          "type": "boolean"
++        },
++        {
++          "name": "cache.direct",
++          "help": "Bypass software writeback cache on the host",
++          "type": "boolean"
++        },
++        {
++          "name": "driver",
++          "help": "Block driver to use for the node",
++          "type": "string"
++        },
++        {
++          "name": "node-name",
++          "help": "Node name of the block device node",
++          "type": "string"
++        }
++      ],
++      "option": "drive"
++    }
++  ],
++  "id": "libvirt-47"
++}
++
++{
++  "execute": "query-migrate-capabilities",
++  "id": "libvirt-48"
++}
++
++{
++  "return": [
++    {
++      "state": false,
++      "capability": "xbzrle"
++    },
++    {
++      "state": false,
++      "capability": "rdma-pin-all"
++    },
++    {
++      "state": false,
++      "capability": "auto-converge"
++    },
++    {
++      "state": false,
++      "capability": "zero-blocks"
++    },
++    {
++      "state": false,
++      "capability": "compress"
++    },
++    {
++      "state": false,
++      "capability": "events"
++    },
++    {
++      "state": false,
++      "capability": "postcopy-ram"
++    },
++    {
++      "state": false,
++      "capability": "x-colo"
++    },
++    {
++      "state": false,
++      "capability": "release-ram"
++    },
++    {
++      "state": false,
++      "capability": "block"
++    },
++    {
++      "state": false,
++      "capability": "return-path"
++    },
++    {
++      "state": false,
++      "capability": "pause-before-switchover"
++    },
++    {
++      "state": false,
++      "capability": "multifd"
++    },
++    {
++      "state": false,
++      "capability": "dirty-bitmaps"
++    },
++    {
++      "state": false,
++      "capability": "postcopy-blocktime"
++    },
++    {
++      "state": false,
++      "capability": "late-block-activate"
++    },
++    {
++      "state": false,
++      "capability": "x-ignore-shared"
++    }
++  ],
++  "id": "libvirt-48"
++}
++
++{
++  "execute": "query-qmp-schema",
++  "id": "libvirt-49"
++}
++
++{
++  "return": [
++    {
++      "name": "query-status",
++      "ret-type": "1",
++      "meta-type": "command",
++      "arg-type": "0"
++    },
++    {
++      "name": "SHUTDOWN",
++      "meta-type": "event",
++      "arg-type": "2"
++    },
++    {
++      "name": "POWERDOWN",
++      "meta-type": "event",
++      "arg-type": "0"
++    },
++    {
++      "name": "RESET",
++      "meta-type": "event",
++      "arg-type": "3"
++    },
++    {
++      "name": "STOP",
++      "meta-type": "event",
++      "arg-type": "0"
++    },
++    {
++      "name": "RESUME",
++      "meta-type": "event",
++      "arg-type": "0"
++    },
++    {
++      "name": "SUSPEND",
++      "meta-type": "event",
++      "arg-type": "0"
++    },
++    {
++      "name": "SUSPEND_DISK",
++      "meta-type": "event",
++      "arg-type": "0"
++    },
++    {
++      "name": "WAKEUP",
++      "meta-type": "event",
++      "arg-type": "0"
++    },
++    {
++      "name": "WATCHDOG",
++      "meta-type": "event",
++      "arg-type": "4"
++    },
++    {
++      "name": "watchdog-set-action",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "5"
++    },
++    {
++      "name": "GUEST_PANICKED",
++      "meta-type": "event",
++      "arg-type": "6"
++    },
++    {
++      "name": "JOB_STATUS_CHANGE",
++      "meta-type": "event",
++      "arg-type": "7"
++    },
++    {
++      "name": "job-pause",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "8"
++    },
++    {
++      "name": "job-resume",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "9"
++    },
++    {
++      "name": "job-cancel",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "10"
++    },
++    {
++      "name": "job-complete",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "11"
++    },
++    {
++      "name": "job-dismiss",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "12"
++    },
++    {
++      "name": "job-finalize",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "13"
++    },
++    {
++      "name": "query-jobs",
++      "ret-type": "[14]",
++      "meta-type": "command",
++      "arg-type": "0"
++    },
++    {
++      "name": "block-latency-histogram-set",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "15"
++    },
++    {
++      "name": "query-block",
++      "ret-type": "[16]",
++      "meta-type": "command",
++      "arg-type": "0"
++    },
++    {
++      "name": "query-blockstats",
++      "ret-type": "[18]",
++      "meta-type": "command",
++      "arg-type": "17"
++    },
++    {
++      "name": "query-block-jobs",
++      "ret-type": "[19]",
++      "meta-type": "command",
++      "arg-type": "0"
++    },
++    {
++      "name": "block_passwd",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "20"
++    },
++    {
++      "name": "block_resize",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "21"
++    },
++    {
++      "name": "blockdev-snapshot-sync",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "22"
++    },
++    {
++      "name": "blockdev-snapshot",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "23"
++    },
++    {
++      "name": "change-backing-file",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "24"
++    },
++    {
++      "name": "block-commit",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "25"
++    },
++    {
++      "name": "drive-backup",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "26"
++    },
++    {
++      "name": "blockdev-backup",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "27"
++    },
++    {
++      "name": "query-named-block-nodes",
++      "ret-type": "[28]",
++      "meta-type": "command",
++      "arg-type": "0"
++    },
++    {
++      "name": "x-debug-query-block-graph",
++      "ret-type": "29",
++      "meta-type": "command",
++      "arg-type": "0"
++    },
++    {
++      "name": "drive-mirror",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "30"
++    },
++    {
++      "name": "block-dirty-bitmap-add",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "31"
++    },
++    {
++      "name": "block-dirty-bitmap-remove",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "32"
++    },
++    {
++      "name": "block-dirty-bitmap-clear",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "32"
++    },
++    {
++      "name": "block-dirty-bitmap-enable",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "32"
++    },
++    {
++      "name": "block-dirty-bitmap-disable",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "32"
++    },
++    {
++      "name": "block-dirty-bitmap-merge",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "33"
++    },
++    {
++      "name": "x-debug-block-dirty-bitmap-sha256",
++      "ret-type": "34",
++      "meta-type": "command",
++      "arg-type": "32"
++    },
++    {
++      "name": "blockdev-mirror",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "35"
++    },
++    {
++      "name": "block_set_io_throttle",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "36"
++    },
++    {
++      "name": "block-stream",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "37"
++    },
++    {
++      "name": "block-job-set-speed",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "38"
++    },
++    {
++      "name": "block-job-cancel",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "39"
++    },
++    {
++      "name": "block-job-pause",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "40"
++    },
++    {
++      "name": "block-job-resume",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "41"
++    },
++    {
++      "name": "block-job-complete",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "42"
++    },
++    {
++      "name": "block-job-dismiss",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "43"
++    },
++    {
++      "name": "block-job-finalize",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "44"
++    },
++    {
++      "name": "blockdev-add",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "45"
++    },
++    {
++      "name": "x-blockdev-reopen",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "45"
++    },
++    {
++      "name": "blockdev-del",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "46"
++    },
++    {
++      "name": "blockdev-create",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "47"
++    },
++    {
++      "name": "blockdev-open-tray",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "48"
++    },
++    {
++      "name": "blockdev-close-tray",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "49"
++    },
++    {
++      "name": "blockdev-remove-medium",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "50"
++    },
++    {
++      "name": "blockdev-insert-medium",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "51"
++    },
++    {
++      "name": "blockdev-change-medium",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "52"
++    },
++    {
++      "name": "BLOCK_IMAGE_CORRUPTED",
++      "meta-type": "event",
++      "arg-type": "53"
++    },
++    {
++      "name": "BLOCK_IO_ERROR",
++      "meta-type": "event",
++      "arg-type": "54"
++    },
++    {
++      "name": "BLOCK_JOB_COMPLETED",
++      "meta-type": "event",
++      "arg-type": "55"
++    },
++    {
++      "name": "BLOCK_JOB_CANCELLED",
++      "meta-type": "event",
++      "arg-type": "56"
++    },
++    {
++      "name": "BLOCK_JOB_ERROR",
++      "meta-type": "event",
++      "arg-type": "57"
++    },
++    {
++      "name": "BLOCK_JOB_READY",
++      "meta-type": "event",
++      "arg-type": "58"
++    },
++    {
++      "name": "BLOCK_JOB_PENDING",
++      "meta-type": "event",
++      "arg-type": "59"
++    },
++    {
++      "name": "BLOCK_WRITE_THRESHOLD",
++      "meta-type": "event",
++      "arg-type": "60"
++    },
++    {
++      "name": "block-set-write-threshold",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "61"
++    },
++    {
++      "name": "x-blockdev-change",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "62"
++    },
++    {
++      "name": "x-blockdev-set-iothread",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "63"
++    },
++    {
++      "name": "query-pr-managers",
++      "ret-type": "[64]",
++      "meta-type": "command",
++      "arg-type": "0"
++    },
++    {
++      "name": "blockdev-snapshot-internal-sync",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "65"
++    },
++    {
++      "name": "blockdev-snapshot-delete-internal-sync",
++      "ret-type": "67",
++      "meta-type": "command",
++      "arg-type": "66"
++    },
++    {
++      "name": "eject",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "68"
++    },
++    {
++      "name": "nbd-server-start",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "69"
++    },
++    {
++      "name": "nbd-server-add",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "70"
++    },
++    {
++      "name": "nbd-server-remove",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "71"
++    },
++    {
++      "name": "nbd-server-stop",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "0"
++    },
++    {
++      "name": "DEVICE_TRAY_MOVED",
++      "meta-type": "event",
++      "arg-type": "72"
++    },
++    {
++      "name": "PR_MANAGER_STATUS_CHANGED",
++      "meta-type": "event",
++      "arg-type": "73"
++    },
++    {
++      "name": "QUORUM_FAILURE",
++      "meta-type": "event",
++      "arg-type": "74"
++    },
++    {
++      "name": "QUORUM_REPORT_BAD",
++      "meta-type": "event",
++      "arg-type": "75"
++    },
++    {
++      "name": "query-chardev",
++      "ret-type": "[76]",
++      "meta-type": "command",
++      "arg-type": "0"
++    },
++    {
++      "name": "query-chardev-backends",
++      "ret-type": "[77]",
++      "meta-type": "command",
++      "arg-type": "0"
++    },
++    {
++      "name": "ringbuf-write",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "78"
++    },
++    {
++      "name": "ringbuf-read",
++      "ret-type": "str",
++      "meta-type": "command",
++      "arg-type": "79"
++    },
++    {
++      "name": "chardev-add",
++      "ret-type": "81",
++      "meta-type": "command",
++      "arg-type": "80"
++    },
++    {
++      "name": "chardev-change",
++      "ret-type": "81",
++      "meta-type": "command",
++      "arg-type": "82"
++    },
++    {
++      "name": "chardev-remove",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "83"
++    },
++    {
++      "name": "chardev-send-break",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "84"
++    },
++    {
++      "name": "VSERPORT_CHANGE",
++      "meta-type": "event",
++      "arg-type": "85"
++    },
++    {
++      "name": "set_link",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "86"
++    },
++    {
++      "name": "netdev_add",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "87"
++    },
++    {
++      "name": "netdev_del",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "88"
++    },
++    {
++      "name": "query-rx-filter",
++      "ret-type": "[90]",
++      "meta-type": "command",
++      "arg-type": "89"
++    },
++    {
++      "name": "NIC_RX_FILTER_CHANGED",
++      "meta-type": "event",
++      "arg-type": "91"
++    },
++    {
++      "name": "announce-self",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "92"
++    },
++    {
++      "name": "RDMA_GID_STATUS_CHANGED",
++      "meta-type": "event",
++      "arg-type": "93"
++    },
++    {
++      "name": "query-rocker",
++      "ret-type": "95",
++      "meta-type": "command",
++      "arg-type": "94"
++    },
++    {
++      "name": "query-rocker-ports",
++      "ret-type": "[97]",
++      "meta-type": "command",
++      "arg-type": "96"
++    },
++    {
++      "name": "query-rocker-of-dpa-flows",
++      "ret-type": "[99]",
++      "meta-type": "command",
++      "arg-type": "98"
++    },
++    {
++      "name": "query-rocker-of-dpa-groups",
++      "ret-type": "[101]",
++      "meta-type": "command",
++      "arg-type": "100"
++    },
++    {
++      "name": "query-tpm-models",
++      "ret-type": "[102]",
++      "meta-type": "command",
++      "arg-type": "0"
++    },
++    {
++      "name": "query-tpm-types",
++      "ret-type": "[103]",
++      "meta-type": "command",
++      "arg-type": "0"
++    },
++    {
++      "name": "query-tpm",
++      "ret-type": "[104]",
++      "meta-type": "command",
++      "arg-type": "0"
++    },
++    {
++      "name": "set_password",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "105"
++    },
++    {
++      "name": "expire_password",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "106"
++    },
++    {
++      "name": "screendump",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "107"
++    },
++    {
++      "name": "query-spice",
++      "ret-type": "108",
++      "meta-type": "command",
++      "arg-type": "0"
++    },
++    {
++      "name": "SPICE_CONNECTED",
++      "meta-type": "event",
++      "arg-type": "109"
++    },
++    {
++      "name": "SPICE_INITIALIZED",
++      "meta-type": "event",
++      "arg-type": "110"
++    },
++    {
++      "name": "SPICE_DISCONNECTED",
++      "meta-type": "event",
++      "arg-type": "111"
++    },
++    {
++      "name": "SPICE_MIGRATE_COMPLETED",
++      "meta-type": "event",
++      "arg-type": "0"
++    },
++    {
++      "name": "query-vnc",
++      "ret-type": "112",
++      "meta-type": "command",
++      "arg-type": "0"
++    },
++    {
++      "name": "query-vnc-servers",
++      "ret-type": "[113]",
++      "meta-type": "command",
++      "arg-type": "0"
++    },
++    {
++      "name": "change-vnc-password",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "114"
++    },
++    {
++      "name": "VNC_CONNECTED",
++      "meta-type": "event",
++      "arg-type": "115"
++    },
++    {
++      "name": "VNC_INITIALIZED",
++      "meta-type": "event",
++      "arg-type": "116"
++    },
++    {
++      "name": "VNC_DISCONNECTED",
++      "meta-type": "event",
++      "arg-type": "117"
++    },
++    {
++      "name": "query-mice",
++      "ret-type": "[118]",
++      "meta-type": "command",
++      "arg-type": "0"
++    },
++    {
++      "name": "send-key",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "119"
++    },
++    {
++      "name": "input-send-event",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "120"
++    },
++    {
++      "name": "query-display-options",
++      "ret-type": "121",
++      "meta-type": "command",
++      "arg-type": "0"
++    },
++    {
++      "name": "query-migrate",
++      "ret-type": "122",
++      "meta-type": "command",
++      "arg-type": "0"
++    },
++    {
++      "name": "migrate-set-capabilities",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "123"
++    },
++    {
++      "name": "query-migrate-capabilities",
++      "ret-type": "[124]",
++      "meta-type": "command",
++      "arg-type": "0"
++    },
++    {
++      "name": "migrate-set-parameters",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "125"
++    },
++    {
++      "name": "query-migrate-parameters",
++      "ret-type": "126",
++      "meta-type": "command",
++      "arg-type": "0"
++    },
++    {
++      "name": "client_migrate_info",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "127"
++    },
++    {
++      "name": "migrate-start-postcopy",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "0"
++    },
++    {
++      "name": "MIGRATION",
++      "meta-type": "event",
++      "arg-type": "128"
++    },
++    {
++      "name": "MIGRATION_PASS",
++      "meta-type": "event",
++      "arg-type": "129"
++    },
++    {
++      "name": "COLO_EXIT",
++      "meta-type": "event",
++      "arg-type": "130"
++    },
++    {
++      "name": "x-colo-lost-heartbeat",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "0"
++    },
++    {
++      "name": "migrate_cancel",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "0"
++    },
++    {
++      "name": "migrate-continue",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "131"
++    },
++    {
++      "name": "migrate_set_downtime",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "132"
++    },
++    {
++      "name": "migrate_set_speed",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "133"
++    },
++    {
++      "name": "migrate-set-cache-size",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "134"
++    },
++    {
++      "name": "query-migrate-cache-size",
++      "ret-type": "int",
++      "meta-type": "command",
++      "arg-type": "0"
++    },
++    {
++      "name": "migrate",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "135"
++    },
++    {
++      "name": "migrate-incoming",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "136"
++    },
++    {
++      "name": "xen-save-devices-state",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "137"
++    },
++    {
++      "name": "xen-set-replication",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "138"
++    },
++    {
++      "name": "query-xen-replication-status",
++      "ret-type": "139",
++      "meta-type": "command",
++      "arg-type": "0"
++    },
++    {
++      "name": "xen-colo-do-checkpoint",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "0"
++    },
++    {
++      "name": "query-colo-status",
++      "ret-type": "140",
++      "meta-type": "command",
++      "arg-type": "0"
++    },
++    {
++      "name": "migrate-recover",
++      "ret-type": "0",
++      "allow-oob": true,
++      "meta-type": "command",
++      "arg-type": "141"
++    },
++    {
++      "name": "migrate-pause",
++      "ret-type": "0",
++      "allow-oob": true,
++      "meta-type": "command",
++      "arg-type": "0"
++    },
++    {
++      "name": "transaction",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "142"
++    },
++    {
++      "name": "trace-event-get-state",
++      "ret-type": "[144]",
++      "meta-type": "command",
++      "arg-type": "143"
++    },
++    {
++      "name": "trace-event-set-state",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "145"
++    },
++    {
++      "name": "query-qmp-schema",
++      "ret-type": "[146]",
++      "meta-type": "command",
++      "arg-type": "0"
++    },
++    {
++      "name": "qmp_capabilities",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "147"
++    },
++    {
++      "name": "query-version",
++      "ret-type": "148",
++      "meta-type": "command",
++      "arg-type": "0"
++    },
++    {
++      "name": "query-commands",
++      "ret-type": "[149]",
++      "meta-type": "command",
++      "arg-type": "0"
++    },
++    {
++      "name": "add_client",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "150"
++    },
++    {
++      "name": "query-name",
++      "ret-type": "151",
++      "meta-type": "command",
++      "arg-type": "0"
++    },
++    {
++      "name": "query-kvm",
++      "ret-type": "152",
++      "meta-type": "command",
++      "arg-type": "0"
++    },
++    {
++      "name": "query-uuid",
++      "ret-type": "153",
++      "meta-type": "command",
++      "arg-type": "0"
++    },
++    {
++      "name": "query-events",
++      "ret-type": "[154]",
++      "meta-type": "command",
++      "arg-type": "0"
++    },
++    {
++      "name": "query-cpus",
++      "ret-type": "[155]",
++      "meta-type": "command",
++      "arg-type": "0"
++    },
++    {
++      "name": "query-cpus-fast",
++      "ret-type": "[156]",
++      "meta-type": "command",
++      "arg-type": "0"
++    },
++    {
++      "name": "query-iothreads",
++      "ret-type": "[157]",
++      "meta-type": "command",
++      "arg-type": "0"
++    },
++    {
++      "name": "query-balloon",
++      "ret-type": "158",
++      "meta-type": "command",
++      "arg-type": "0"
++    },
++    {
++      "name": "BALLOON_CHANGE",
++      "meta-type": "event",
++      "arg-type": "159"
++    },
++    {
++      "name": "query-pci",
++      "ret-type": "[160]",
++      "meta-type": "command",
++      "arg-type": "0"
++    },
++    {
++      "name": "quit",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "0"
++    },
++    {
++      "name": "stop",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "0"
++    },
++    {
++      "name": "system_reset",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "0"
++    },
++    {
++      "name": "system_powerdown",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "0"
++    },
++    {
++      "name": "cpu-add",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "161"
++    },
++    {
++      "name": "memsave",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "162"
++    },
++    {
++      "name": "pmemsave",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "163"
++    },
++    {
++      "name": "cont",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "0"
++    },
++    {
++      "name": "x-exit-preconfig",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "0"
++    },
++    {
++      "name": "system_wakeup",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "0"
++    },
++    {
++      "name": "inject-nmi",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "0"
++    },
++    {
++      "name": "balloon",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "164"
++    },
++    {
++      "name": "human-monitor-command",
++      "ret-type": "str",
++      "meta-type": "command",
++      "arg-type": "165"
++    },
++    {
++      "name": "qom-list",
++      "ret-type": "[167]",
++      "meta-type": "command",
++      "arg-type": "166"
++    },
++    {
++      "name": "qom-get",
++      "ret-type": "any",
++      "meta-type": "command",
++      "arg-type": "168"
++    },
++    {
++      "name": "qom-set",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "169"
++    },
++    {
++      "name": "change",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "170"
++    },
++    {
++      "name": "qom-list-types",
++      "ret-type": "[172]",
++      "meta-type": "command",
++      "arg-type": "171"
++    },
++    {
++      "name": "device-list-properties",
++      "ret-type": "[167]",
++      "meta-type": "command",
++      "arg-type": "173"
++    },
++    {
++      "name": "qom-list-properties",
++      "ret-type": "[167]",
++      "meta-type": "command",
++      "arg-type": "174"
++    },
++    {
++      "name": "xen-set-global-dirty-log",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "175"
++    },
++    {
++      "name": "device_add",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "176"
++    },
++    {
++      "name": "device_del",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "177"
++    },
++    {
++      "name": "DEVICE_DELETED",
++      "meta-type": "event",
++      "arg-type": "178"
++    },
++    {
++      "name": "dump-guest-memory",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "179"
++    },
++    {
++      "name": "query-dump",
++      "ret-type": "180",
++      "meta-type": "command",
++      "arg-type": "0"
++    },
++    {
++      "name": "DUMP_COMPLETED",
++      "meta-type": "event",
++      "arg-type": "181"
++    },
++    {
++      "name": "query-dump-guest-memory-capability",
++      "ret-type": "182",
++      "meta-type": "command",
++      "arg-type": "0"
++    },
++    {
++      "name": "object-add",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "183"
++    },
++    {
++      "name": "object-del",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "184"
++    },
++    {
++      "name": "getfd",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "185"
++    },
++    {
++      "name": "closefd",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "186"
++    },
++    {
++      "name": "query-machines",
++      "ret-type": "[187]",
++      "meta-type": "command",
++      "arg-type": "0"
++    },
++    {
++      "name": "query-current-machine",
++      "ret-type": "188",
++      "meta-type": "command",
++      "arg-type": "0"
++    },
++    {
++      "name": "query-memory-size-summary",
++      "ret-type": "189",
++      "meta-type": "command",
++      "arg-type": "0"
++    },
++    {
++      "name": "add-fd",
++      "ret-type": "191",
++      "meta-type": "command",
++      "arg-type": "190"
++    },
++    {
++      "name": "remove-fd",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "192"
++    },
++    {
++      "name": "query-fdsets",
++      "ret-type": "[193]",
++      "meta-type": "command",
++      "arg-type": "0"
++    },
++    {
++      "name": "query-target",
++      "ret-type": "194",
++      "meta-type": "command",
++      "arg-type": "0"
++    },
++    {
++      "name": "query-command-line-options",
++      "ret-type": "[196]",
++      "meta-type": "command",
++      "arg-type": "195"
++    },
++    {
++      "name": "query-memdev",
++      "ret-type": "[197]",
++      "meta-type": "command",
++      "arg-type": "0"
++    },
++    {
++      "name": "query-memory-devices",
++      "ret-type": "[198]",
++      "meta-type": "command",
++      "arg-type": "0"
++    },
++    {
++      "name": "MEM_UNPLUG_ERROR",
++      "meta-type": "event",
++      "arg-type": "199"
++    },
++    {
++      "name": "query-acpi-ospm-status",
++      "ret-type": "[200]",
++      "meta-type": "command",
++      "arg-type": "0"
++    },
++    {
++      "name": "ACPI_DEVICE_OST",
++      "meta-type": "event",
++      "arg-type": "201"
++    },
++    {
++      "name": "xen-load-devices-state",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "202"
++    },
++    {
++      "name": "query-hotpluggable-cpus",
++      "ret-type": "[203]",
++      "meta-type": "command",
++      "arg-type": "0"
++    },
++    {
++      "name": "query-vm-generation-id",
++      "ret-type": "204",
++      "meta-type": "command",
++      "arg-type": "0"
++    },
++    {
++      "name": "set-numa-node",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "205"
++    },
++    {
++      "name": "RTC_CHANGE",
++      "meta-type": "event",
++      "arg-type": "206"
++    },
++    {
++      "name": "rtc-reset-reinjection",
++      "ret-type": "0",
++      "meta-type": "command",
++      "arg-type": "0"
++    },
++    {
++      "name": "query-sev",
++      "ret-type": "207",
++      "meta-type": "command",
++      "arg-type": "0"
++    },
++    {
++      "name": "query-sev-launch-measure",
++      "ret-type": "208",
++      "meta-type": "command",
++      "arg-type": "0"
++    },
++    {
++      "name": "query-sev-capabilities",
++      "ret-type": "209",
++      "meta-type": "command",
++      "arg-type": "0"
++    },
++    {
++      "name": "query-cpu-model-expansion",
++      "ret-type": "217",
++      "meta-type": "command",
++      "arg-type": "216"
++    },
++    {
++      "name": "query-cpu-definitions",
++      "ret-type": "[218]",
++      "meta-type": "command",
++      "arg-type": "0"
++    },
++    {
++      "name": "0",
++      "members": [
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "1",
++      "members": [
++        {
++          "name": "running",
++          "type": "bool"
++        },
++        {
++          "name": "singlestep",
++          "type": "bool"
++        },
++        {
++          "name": "status",
++          "type": "219"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "2",
++      "members": [
++        {
++          "name": "guest",
++          "type": "bool"
++        },
++        {
++          "name": "reason",
++          "type": "220"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "3",
++      "members": [
++        {
++          "name": "guest",
++          "type": "bool"
++        },
++        {
++          "name": "reason",
++          "type": "220"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "4",
++      "members": [
++        {
++          "name": "action",
++          "type": "221"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "5",
++      "members": [
++        {
++          "name": "action",
++          "type": "221"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "6",
++      "members": [
++        {
++          "name": "action",
++          "type": "222"
++        },
++        {
++          "name": "info",
++          "default": null,
++          "type": "223"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "7",
++      "members": [
++        {
++          "name": "id",
++          "type": "str"
++        },
++        {
++          "name": "status",
++          "type": "224"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "8",
++      "members": [
++        {
++          "name": "id",
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "9",
++      "members": [
++        {
++          "name": "id",
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "10",
++      "members": [
++        {
++          "name": "id",
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "11",
++      "members": [
++        {
++          "name": "id",
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "12",
++      "members": [
++        {
++          "name": "id",
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "13",
++      "members": [
++        {
++          "name": "id",
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "[14]",
++      "element-type": "14",
++      "meta-type": "array"
++    },
++    {
++      "name": "14",
++      "members": [
++        {
++          "name": "id",
++          "type": "str"
++        },
++        {
++          "name": "type",
++          "type": "225"
++        },
++        {
++          "name": "status",
++          "type": "224"
++        },
++        {
++          "name": "current-progress",
++          "type": "int"
++        },
++        {
++          "name": "total-progress",
++          "type": "int"
++        },
++        {
++          "name": "error",
++          "default": null,
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "15",
++      "members": [
++        {
++          "name": "id",
++          "type": "str"
++        },
++        {
++          "name": "boundaries",
++          "default": null,
++          "type": "[int]"
++        },
++        {
++          "name": "boundaries-read",
++          "default": null,
++          "type": "[int]"
++        },
++        {
++          "name": "boundaries-write",
++          "default": null,
++          "type": "[int]"
++        },
++        {
++          "name": "boundaries-flush",
++          "default": null,
++          "type": "[int]"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "[16]",
++      "element-type": "16",
++      "meta-type": "array"
++    },
++    {
++      "name": "16",
++      "members": [
++        {
++          "name": "device",
++          "type": "str"
++        },
++        {
++          "name": "qdev",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "type",
++          "type": "str"
++        },
++        {
++          "name": "removable",
++          "type": "bool"
++        },
++        {
++          "name": "locked",
++          "type": "bool"
++        },
++        {
++          "name": "inserted",
++          "default": null,
++          "type": "28"
++        },
++        {
++          "name": "tray_open",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "io-status",
++          "default": null,
++          "type": "226"
++        },
++        {
++          "name": "dirty-bitmaps",
++          "default": null,
++          "type": "[227]"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "17",
++      "members": [
++        {
++          "name": "query-nodes",
++          "default": null,
++          "type": "bool"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "[18]",
++      "element-type": "18",
++      "meta-type": "array"
++    },
++    {
++      "name": "18",
++      "members": [
++        {
++          "name": "device",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "qdev",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "node-name",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "stats",
++          "type": "228"
++        },
++        {
++          "name": "parent",
++          "default": null,
++          "type": "18"
++        },
++        {
++          "name": "backing",
++          "default": null,
++          "type": "18"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "[19]",
++      "element-type": "19",
++      "meta-type": "array"
++    },
++    {
++      "name": "19",
++      "members": [
++        {
++          "name": "type",
++          "type": "str"
++        },
++        {
++          "name": "device",
++          "type": "str"
++        },
++        {
++          "name": "len",
++          "type": "int"
++        },
++        {
++          "name": "offset",
++          "type": "int"
++        },
++        {
++          "name": "busy",
++          "type": "bool"
++        },
++        {
++          "name": "paused",
++          "type": "bool"
++        },
++        {
++          "name": "speed",
++          "type": "int"
++        },
++        {
++          "name": "io-status",
++          "type": "226"
++        },
++        {
++          "name": "ready",
++          "type": "bool"
++        },
++        {
++          "name": "status",
++          "type": "224"
++        },
++        {
++          "name": "auto-finalize",
++          "type": "bool"
++        },
++        {
++          "name": "auto-dismiss",
++          "type": "bool"
++        },
++        {
++          "name": "error",
++          "default": null,
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "20",
++      "members": [
++        {
++          "name": "device",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "node-name",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "password",
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "21",
++      "members": [
++        {
++          "name": "device",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "node-name",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "size",
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "22",
++      "members": [
++        {
++          "name": "device",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "node-name",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "snapshot-file",
++          "type": "str"
++        },
++        {
++          "name": "snapshot-node-name",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "format",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "mode",
++          "default": null,
++          "type": "229"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "23",
++      "members": [
++        {
++          "name": "node",
++          "type": "str"
++        },
++        {
++          "name": "overlay",
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "24",
++      "members": [
++        {
++          "name": "device",
++          "type": "str"
++        },
++        {
++          "name": "image-node-name",
++          "type": "str"
++        },
++        {
++          "name": "backing-file",
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "25",
++      "members": [
++        {
++          "name": "job-id",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "device",
++          "type": "str"
++        },
++        {
++          "name": "base-node",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "base",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "top-node",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "top",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "backing-file",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "speed",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "filter-node-name",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "auto-finalize",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "auto-dismiss",
++          "default": null,
++          "type": "bool"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "26",
++      "members": [
++        {
++          "name": "job-id",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "device",
++          "type": "str"
++        },
++        {
++          "name": "target",
++          "type": "str"
++        },
++        {
++          "name": "format",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "sync",
++          "type": "230"
++        },
++        {
++          "name": "mode",
++          "default": null,
++          "type": "229"
++        },
++        {
++          "name": "speed",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "bitmap",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "compress",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "on-source-error",
++          "default": null,
++          "type": "231"
++        },
++        {
++          "name": "on-target-error",
++          "default": null,
++          "type": "231"
++        },
++        {
++          "name": "auto-finalize",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "auto-dismiss",
++          "default": null,
++          "type": "bool"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "27",
++      "members": [
++        {
++          "name": "job-id",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "device",
++          "type": "str"
++        },
++        {
++          "name": "target",
++          "type": "str"
++        },
++        {
++          "name": "sync",
++          "type": "230"
++        },
++        {
++          "name": "speed",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "bitmap",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "compress",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "on-source-error",
++          "default": null,
++          "type": "231"
++        },
++        {
++          "name": "on-target-error",
++          "default": null,
++          "type": "231"
++        },
++        {
++          "name": "auto-finalize",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "auto-dismiss",
++          "default": null,
++          "type": "bool"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "[28]",
++      "element-type": "28",
++      "meta-type": "array"
++    },
++    {
++      "name": "28",
++      "members": [
++        {
++          "name": "file",
++          "type": "str"
++        },
++        {
++          "name": "node-name",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "ro",
++          "type": "bool"
++        },
++        {
++          "name": "drv",
++          "type": "str"
++        },
++        {
++          "name": "backing_file",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "backing_file_depth",
++          "type": "int"
++        },
++        {
++          "name": "encrypted",
++          "type": "bool"
++        },
++        {
++          "name": "encryption_key_missing",
++          "type": "bool"
++        },
++        {
++          "name": "detect_zeroes",
++          "type": "232"
++        },
++        {
++          "name": "bps",
++          "type": "int"
++        },
++        {
++          "name": "bps_rd",
++          "type": "int"
++        },
++        {
++          "name": "bps_wr",
++          "type": "int"
++        },
++        {
++          "name": "iops",
++          "type": "int"
++        },
++        {
++          "name": "iops_rd",
++          "type": "int"
++        },
++        {
++          "name": "iops_wr",
++          "type": "int"
++        },
++        {
++          "name": "image",
++          "type": "233"
++        },
++        {
++          "name": "bps_max",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "bps_rd_max",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "bps_wr_max",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "iops_max",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "iops_rd_max",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "iops_wr_max",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "bps_max_length",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "bps_rd_max_length",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "bps_wr_max_length",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "iops_max_length",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "iops_rd_max_length",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "iops_wr_max_length",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "iops_size",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "group",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "cache",
++          "type": "234"
++        },
++        {
++          "name": "write_threshold",
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "29",
++      "members": [
++        {
++          "name": "nodes",
++          "type": "[235]"
++        },
++        {
++          "name": "edges",
++          "type": "[236]"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "30",
++      "members": [
++        {
++          "name": "job-id",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "device",
++          "type": "str"
++        },
++        {
++          "name": "target",
++          "type": "str"
++        },
++        {
++          "name": "format",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "node-name",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "replaces",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "sync",
++          "type": "230"
++        },
++        {
++          "name": "mode",
++          "default": null,
++          "type": "229"
++        },
++        {
++          "name": "speed",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "granularity",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "buf-size",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "on-source-error",
++          "default": null,
++          "type": "231"
++        },
++        {
++          "name": "on-target-error",
++          "default": null,
++          "type": "231"
++        },
++        {
++          "name": "unmap",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "copy-mode",
++          "default": null,
++          "type": "237"
++        },
++        {
++          "name": "auto-finalize",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "auto-dismiss",
++          "default": null,
++          "type": "bool"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "31",
++      "members": [
++        {
++          "name": "node",
++          "type": "str"
++        },
++        {
++          "name": "name",
++          "type": "str"
++        },
++        {
++          "name": "granularity",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "persistent",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "autoload",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "disabled",
++          "default": null,
++          "type": "bool"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "32",
++      "members": [
++        {
++          "name": "node",
++          "type": "str"
++        },
++        {
++          "name": "name",
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "33",
++      "members": [
++        {
++          "name": "node",
++          "type": "str"
++        },
++        {
++          "name": "target",
++          "type": "str"
++        },
++        {
++          "name": "bitmaps",
++          "type": "[238]"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "34",
++      "members": [
++        {
++          "name": "sha256",
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "35",
++      "members": [
++        {
++          "name": "job-id",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "device",
++          "type": "str"
++        },
++        {
++          "name": "target",
++          "type": "str"
++        },
++        {
++          "name": "replaces",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "sync",
++          "type": "230"
++        },
++        {
++          "name": "speed",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "granularity",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "buf-size",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "on-source-error",
++          "default": null,
++          "type": "231"
++        },
++        {
++          "name": "on-target-error",
++          "default": null,
++          "type": "231"
++        },
++        {
++          "name": "filter-node-name",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "copy-mode",
++          "default": null,
++          "type": "237"
++        },
++        {
++          "name": "auto-finalize",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "auto-dismiss",
++          "default": null,
++          "type": "bool"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "36",
++      "members": [
++        {
++          "name": "device",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "id",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "bps",
++          "type": "int"
++        },
++        {
++          "name": "bps_rd",
++          "type": "int"
++        },
++        {
++          "name": "bps_wr",
++          "type": "int"
++        },
++        {
++          "name": "iops",
++          "type": "int"
++        },
++        {
++          "name": "iops_rd",
++          "type": "int"
++        },
++        {
++          "name": "iops_wr",
++          "type": "int"
++        },
++        {
++          "name": "bps_max",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "bps_rd_max",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "bps_wr_max",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "iops_max",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "iops_rd_max",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "iops_wr_max",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "bps_max_length",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "bps_rd_max_length",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "bps_wr_max_length",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "iops_max_length",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "iops_rd_max_length",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "iops_wr_max_length",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "iops_size",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "group",
++          "default": null,
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "37",
++      "members": [
++        {
++          "name": "job-id",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "device",
++          "type": "str"
++        },
++        {
++          "name": "base",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "base-node",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "backing-file",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "speed",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "on-error",
++          "default": null,
++          "type": "231"
++        },
++        {
++          "name": "auto-finalize",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "auto-dismiss",
++          "default": null,
++          "type": "bool"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "38",
++      "members": [
++        {
++          "name": "device",
++          "type": "str"
++        },
++        {
++          "name": "speed",
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "39",
++      "members": [
++        {
++          "name": "device",
++          "type": "str"
++        },
++        {
++          "name": "force",
++          "default": null,
++          "type": "bool"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "40",
++      "members": [
++        {
++          "name": "device",
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "41",
++      "members": [
++        {
++          "name": "device",
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "42",
++      "members": [
++        {
++          "name": "device",
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "43",
++      "members": [
++        {
++          "name": "id",
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "44",
++      "members": [
++        {
++          "name": "id",
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "45",
++      "tag": "driver",
++      "variants": [
++        {
++          "case": "blkdebug",
++          "type": "242"
++        },
++        {
++          "case": "blklogwrites",
++          "type": "243"
++        },
++        {
++          "case": "blkverify",
++          "type": "244"
++        },
++        {
++          "case": "bochs",
++          "type": "245"
++        },
++        {
++          "case": "cloop",
++          "type": "245"
++        },
++        {
++          "case": "copy-on-read",
++          "type": "245"
++        },
++        {
++          "case": "dmg",
++          "type": "245"
++        },
++        {
++          "case": "file",
++          "type": "246"
++        },
++        {
++          "case": "ftp",
++          "type": "247"
++        },
++        {
++          "case": "ftps",
++          "type": "248"
++        },
++        {
++          "case": "gluster",
++          "type": "249"
++        },
++        {
++          "case": "host_cdrom",
++          "type": "246"
++        },
++        {
++          "case": "host_device",
++          "type": "246"
++        },
++        {
++          "case": "http",
++          "type": "250"
++        },
++        {
++          "case": "https",
++          "type": "251"
++        },
++        {
++          "case": "iscsi",
++          "type": "252"
++        },
++        {
++          "case": "luks",
++          "type": "253"
++        },
++        {
++          "case": "nbd",
++          "type": "254"
++        },
++        {
++          "case": "nfs",
++          "type": "255"
++        },
++        {
++          "case": "null-aio",
++          "type": "256"
++        },
++        {
++          "case": "null-co",
++          "type": "256"
++        },
++        {
++          "case": "nvme",
++          "type": "257"
++        },
++        {
++          "case": "parallels",
++          "type": "245"
++        },
++        {
++          "case": "qcow2",
++          "type": "258"
++        },
++        {
++          "case": "qcow",
++          "type": "259"
++        },
++        {
++          "case": "qed",
++          "type": "260"
++        },
++        {
++          "case": "quorum",
++          "type": "261"
++        },
++        {
++          "case": "raw",
++          "type": "262"
++        },
++        {
++          "case": "rbd",
++          "type": "263"
++        },
++        {
++          "case": "replication",
++          "type": "264"
++        },
++        {
++          "case": "sheepdog",
++          "type": "265"
++        },
++        {
++          "case": "ssh",
++          "type": "266"
++        },
++        {
++          "case": "throttle",
++          "type": "267"
++        },
++        {
++          "case": "vdi",
++          "type": "245"
++        },
++        {
++          "case": "vhdx",
++          "type": "245"
++        },
++        {
++          "case": "vmdk",
++          "type": "260"
++        },
++        {
++          "case": "vpc",
++          "type": "245"
++        },
++        {
++          "case": "vvfat",
++          "type": "268"
++        },
++        {
++          "case": "vxhs",
++          "type": "269"
++        }
++      ],
++      "members": [
++        {
++          "name": "driver",
++          "type": "239"
++        },
++        {
++          "name": "node-name",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "discard",
++          "default": null,
++          "type": "240"
++        },
++        {
++          "name": "cache",
++          "default": null,
++          "type": "241"
++        },
++        {
++          "name": "read-only",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "auto-read-only",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "force-share",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "detect-zeroes",
++          "default": null,
++          "type": "232"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "46",
++      "members": [
++        {
++          "name": "node-name",
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "47",
++      "members": [
++        {
++          "name": "job-id",
++          "type": "str"
++        },
++        {
++          "name": "options",
++          "type": "270"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "48",
++      "members": [
++        {
++          "name": "device",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "id",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "force",
++          "default": null,
++          "type": "bool"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "49",
++      "members": [
++        {
++          "name": "device",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "id",
++          "default": null,
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "50",
++      "members": [
++        {
++          "name": "id",
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "51",
++      "members": [
++        {
++          "name": "id",
++          "type": "str"
++        },
++        {
++          "name": "node-name",
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "52",
++      "members": [
++        {
++          "name": "device",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "id",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "filename",
++          "type": "str"
++        },
++        {
++          "name": "format",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "read-only-mode",
++          "default": null,
++          "type": "271"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "53",
++      "members": [
++        {
++          "name": "device",
++          "type": "str"
++        },
++        {
++          "name": "node-name",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "msg",
++          "type": "str"
++        },
++        {
++          "name": "offset",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "size",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "fatal",
++          "type": "bool"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "54",
++      "members": [
++        {
++          "name": "device",
++          "type": "str"
++        },
++        {
++          "name": "node-name",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "operation",
++          "type": "272"
++        },
++        {
++          "name": "action",
++          "type": "273"
++        },
++        {
++          "name": "nospace",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "reason",
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "55",
++      "members": [
++        {
++          "name": "type",
++          "type": "225"
++        },
++        {
++          "name": "device",
++          "type": "str"
++        },
++        {
++          "name": "len",
++          "type": "int"
++        },
++        {
++          "name": "offset",
++          "type": "int"
++        },
++        {
++          "name": "speed",
++          "type": "int"
++        },
++        {
++          "name": "error",
++          "default": null,
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "56",
++      "members": [
++        {
++          "name": "type",
++          "type": "225"
++        },
++        {
++          "name": "device",
++          "type": "str"
++        },
++        {
++          "name": "len",
++          "type": "int"
++        },
++        {
++          "name": "offset",
++          "type": "int"
++        },
++        {
++          "name": "speed",
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "57",
++      "members": [
++        {
++          "name": "device",
++          "type": "str"
++        },
++        {
++          "name": "operation",
++          "type": "272"
++        },
++        {
++          "name": "action",
++          "type": "273"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "58",
++      "members": [
++        {
++          "name": "type",
++          "type": "225"
++        },
++        {
++          "name": "device",
++          "type": "str"
++        },
++        {
++          "name": "len",
++          "type": "int"
++        },
++        {
++          "name": "offset",
++          "type": "int"
++        },
++        {
++          "name": "speed",
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "59",
++      "members": [
++        {
++          "name": "type",
++          "type": "225"
++        },
++        {
++          "name": "id",
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "60",
++      "members": [
++        {
++          "name": "node-name",
++          "type": "str"
++        },
++        {
++          "name": "amount-exceeded",
++          "type": "int"
++        },
++        {
++          "name": "write-threshold",
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "61",
++      "members": [
++        {
++          "name": "node-name",
++          "type": "str"
++        },
++        {
++          "name": "write-threshold",
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "62",
++      "members": [
++        {
++          "name": "parent",
++          "type": "str"
++        },
++        {
++          "name": "child",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "node",
++          "default": null,
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "63",
++      "members": [
++        {
++          "name": "node-name",
++          "type": "str"
++        },
++        {
++          "name": "iothread",
++          "type": "274"
++        },
++        {
++          "name": "force",
++          "default": null,
++          "type": "bool"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "[64]",
++      "element-type": "64",
++      "meta-type": "array"
++    },
++    {
++      "name": "64",
++      "members": [
++        {
++          "name": "id",
++          "type": "str"
++        },
++        {
++          "name": "connected",
++          "type": "bool"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "65",
++      "members": [
++        {
++          "name": "device",
++          "type": "str"
++        },
++        {
++          "name": "name",
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "66",
++      "members": [
++        {
++          "name": "device",
++          "type": "str"
++        },
++        {
++          "name": "id",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "name",
++          "default": null,
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "67",
++      "members": [
++        {
++          "name": "id",
++          "type": "str"
++        },
++        {
++          "name": "name",
++          "type": "str"
++        },
++        {
++          "name": "vm-state-size",
++          "type": "int"
++        },
++        {
++          "name": "date-sec",
++          "type": "int"
++        },
++        {
++          "name": "date-nsec",
++          "type": "int"
++        },
++        {
++          "name": "vm-clock-sec",
++          "type": "int"
++        },
++        {
++          "name": "vm-clock-nsec",
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "68",
++      "members": [
++        {
++          "name": "device",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "id",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "force",
++          "default": null,
++          "type": "bool"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "69",
++      "members": [
++        {
++          "name": "addr",
++          "type": "275"
++        },
++        {
++          "name": "tls-creds",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "tls-authz",
++          "default": null,
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "70",
++      "members": [
++        {
++          "name": "device",
++          "type": "str"
++        },
++        {
++          "name": "name",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "writable",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "bitmap",
++          "default": null,
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "71",
++      "members": [
++        {
++          "name": "name",
++          "type": "str"
++        },
++        {
++          "name": "mode",
++          "default": null,
++          "type": "276"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "72",
++      "members": [
++        {
++          "name": "device",
++          "type": "str"
++        },
++        {
++          "name": "id",
++          "type": "str"
++        },
++        {
++          "name": "tray-open",
++          "type": "bool"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "73",
++      "members": [
++        {
++          "name": "id",
++          "type": "str"
++        },
++        {
++          "name": "connected",
++          "type": "bool"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "74",
++      "members": [
++        {
++          "name": "reference",
++          "type": "str"
++        },
++        {
++          "name": "sector-num",
++          "type": "int"
++        },
++        {
++          "name": "sectors-count",
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "75",
++      "members": [
++        {
++          "name": "type",
++          "type": "277"
++        },
++        {
++          "name": "error",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "node-name",
++          "type": "str"
++        },
++        {
++          "name": "sector-num",
++          "type": "int"
++        },
++        {
++          "name": "sectors-count",
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "[76]",
++      "element-type": "76",
++      "meta-type": "array"
++    },
++    {
++      "name": "76",
++      "members": [
++        {
++          "name": "label",
++          "type": "str"
++        },
++        {
++          "name": "filename",
++          "type": "str"
++        },
++        {
++          "name": "frontend-open",
++          "type": "bool"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "[77]",
++      "element-type": "77",
++      "meta-type": "array"
++    },
++    {
++      "name": "77",
++      "members": [
++        {
++          "name": "name",
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "78",
++      "members": [
++        {
++          "name": "device",
++          "type": "str"
++        },
++        {
++          "name": "data",
++          "type": "str"
++        },
++        {
++          "name": "format",
++          "default": null,
++          "type": "278"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "79",
++      "members": [
++        {
++          "name": "device",
++          "type": "str"
++        },
++        {
++          "name": "size",
++          "type": "int"
++        },
++        {
++          "name": "format",
++          "default": null,
++          "type": "278"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "str",
++      "json-type": "string",
++      "meta-type": "builtin"
++    },
++    {
++      "name": "80",
++      "members": [
++        {
++          "name": "id",
++          "type": "str"
++        },
++        {
++          "name": "backend",
++          "type": "279"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "81",
++      "members": [
++        {
++          "name": "pty",
++          "default": null,
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "82",
++      "members": [
++        {
++          "name": "id",
++          "type": "str"
++        },
++        {
++          "name": "backend",
++          "type": "279"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "83",
++      "members": [
++        {
++          "name": "id",
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "84",
++      "members": [
++        {
++          "name": "id",
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "85",
++      "members": [
++        {
++          "name": "id",
++          "type": "str"
++        },
++        {
++          "name": "open",
++          "type": "bool"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "86",
++      "members": [
++        {
++          "name": "name",
++          "type": "str"
++        },
++        {
++          "name": "up",
++          "type": "bool"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "87",
++      "members": [
++        {
++          "name": "type",
++          "type": "str"
++        },
++        {
++          "name": "id",
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "88",
++      "members": [
++        {
++          "name": "id",
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "89",
++      "members": [
++        {
++          "name": "name",
++          "default": null,
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "[90]",
++      "element-type": "90",
++      "meta-type": "array"
++    },
++    {
++      "name": "90",
++      "members": [
++        {
++          "name": "name",
++          "type": "str"
++        },
++        {
++          "name": "promiscuous",
++          "type": "bool"
++        },
++        {
++          "name": "multicast",
++          "type": "280"
++        },
++        {
++          "name": "unicast",
++          "type": "280"
++        },
++        {
++          "name": "vlan",
++          "type": "280"
++        },
++        {
++          "name": "broadcast-allowed",
++          "type": "bool"
++        },
++        {
++          "name": "multicast-overflow",
++          "type": "bool"
++        },
++        {
++          "name": "unicast-overflow",
++          "type": "bool"
++        },
++        {
++          "name": "main-mac",
++          "type": "str"
++        },
++        {
++          "name": "vlan-table",
++          "type": "[int]"
++        },
++        {
++          "name": "unicast-table",
++          "type": "[str]"
++        },
++        {
++          "name": "multicast-table",
++          "type": "[str]"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "91",
++      "members": [
++        {
++          "name": "name",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "path",
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "92",
++      "members": [
++        {
++          "name": "initial",
++          "type": "int"
++        },
++        {
++          "name": "max",
++          "type": "int"
++        },
++        {
++          "name": "rounds",
++          "type": "int"
++        },
++        {
++          "name": "step",
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "93",
++      "members": [
++        {
++          "name": "netdev",
++          "type": "str"
++        },
++        {
++          "name": "gid-status",
++          "type": "bool"
++        },
++        {
++          "name": "subnet-prefix",
++          "type": "int"
++        },
++        {
++          "name": "interface-id",
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "94",
++      "members": [
++        {
++          "name": "name",
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "95",
++      "members": [
++        {
++          "name": "name",
++          "type": "str"
++        },
++        {
++          "name": "id",
++          "type": "int"
++        },
++        {
++          "name": "ports",
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "96",
++      "members": [
++        {
++          "name": "name",
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "[97]",
++      "element-type": "97",
++      "meta-type": "array"
++    },
++    {
++      "name": "97",
++      "members": [
++        {
++          "name": "name",
++          "type": "str"
++        },
++        {
++          "name": "enabled",
++          "type": "bool"
++        },
++        {
++          "name": "link-up",
++          "type": "bool"
++        },
++        {
++          "name": "speed",
++          "type": "int"
++        },
++        {
++          "name": "duplex",
++          "type": "281"
++        },
++        {
++          "name": "autoneg",
++          "type": "282"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "98",
++      "members": [
++        {
++          "name": "name",
++          "type": "str"
++        },
++        {
++          "name": "tbl-id",
++          "default": null,
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "[99]",
++      "element-type": "99",
++      "meta-type": "array"
++    },
++    {
++      "name": "99",
++      "members": [
++        {
++          "name": "cookie",
++          "type": "int"
++        },
++        {
++          "name": "hits",
++          "type": "int"
++        },
++        {
++          "name": "key",
++          "type": "283"
++        },
++        {
++          "name": "mask",
++          "type": "284"
++        },
++        {
++          "name": "action",
++          "type": "285"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "100",
++      "members": [
++        {
++          "name": "name",
++          "type": "str"
++        },
++        {
++          "name": "type",
++          "default": null,
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "[101]",
++      "element-type": "101",
++      "meta-type": "array"
++    },
++    {
++      "name": "101",
++      "members": [
++        {
++          "name": "id",
++          "type": "int"
++        },
++        {
++          "name": "type",
++          "type": "int"
++        },
++        {
++          "name": "vlan-id",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "pport",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "index",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "out-pport",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "group-id",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "set-vlan-id",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "pop-vlan",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "group-ids",
++          "default": null,
++          "type": "[int]"
++        },
++        {
++          "name": "set-eth-src",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "set-eth-dst",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "ttl-check",
++          "default": null,
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "[102]",
++      "element-type": "102",
++      "meta-type": "array"
++    },
++    {
++      "name": "102",
++      "meta-type": "enum",
++      "values": [
++        "tpm-tis",
++        "tpm-crb"
++      ]
++    },
++    {
++      "name": "[103]",
++      "element-type": "103",
++      "meta-type": "array"
++    },
++    {
++      "name": "103",
++      "meta-type": "enum",
++      "values": [
++        "passthrough",
++        "emulator"
++      ]
++    },
++    {
++      "name": "[104]",
++      "element-type": "104",
++      "meta-type": "array"
++    },
++    {
++      "name": "104",
++      "members": [
++        {
++          "name": "id",
++          "type": "str"
++        },
++        {
++          "name": "model",
++          "type": "102"
++        },
++        {
++          "name": "options",
++          "type": "286"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "105",
++      "members": [
++        {
++          "name": "protocol",
++          "type": "str"
++        },
++        {
++          "name": "password",
++          "type": "str"
++        },
++        {
++          "name": "connected",
++          "default": null,
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "106",
++      "members": [
++        {
++          "name": "protocol",
++          "type": "str"
++        },
++        {
++          "name": "time",
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "107",
++      "members": [
++        {
++          "name": "filename",
++          "type": "str"
++        },
++        {
++          "name": "device",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "head",
++          "default": null,
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "108",
++      "members": [
++        {
++          "name": "enabled",
++          "type": "bool"
++        },
++        {
++          "name": "migrated",
++          "type": "bool"
++        },
++        {
++          "name": "host",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "port",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "tls-port",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "auth",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "compiled-version",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "mouse-mode",
++          "type": "287"
++        },
++        {
++          "name": "channels",
++          "default": null,
++          "type": "[288]"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "109",
++      "members": [
++        {
++          "name": "server",
++          "type": "289"
++        },
++        {
++          "name": "client",
++          "type": "289"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "110",
++      "members": [
++        {
++          "name": "server",
++          "type": "290"
++        },
++        {
++          "name": "client",
++          "type": "288"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "111",
++      "members": [
++        {
++          "name": "server",
++          "type": "289"
++        },
++        {
++          "name": "client",
++          "type": "289"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "112",
++      "members": [
++        {
++          "name": "enabled",
++          "type": "bool"
++        },
++        {
++          "name": "host",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "family",
++          "default": null,
++          "type": "291"
++        },
++        {
++          "name": "service",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "auth",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "clients",
++          "default": null,
++          "type": "[292]"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "[113]",
++      "element-type": "113",
++      "meta-type": "array"
++    },
++    {
++      "name": "113",
++      "members": [
++        {
++          "name": "id",
++          "type": "str"
++        },
++        {
++          "name": "server",
++          "type": "[293]"
++        },
++        {
++          "name": "clients",
++          "type": "[292]"
++        },
++        {
++          "name": "auth",
++          "type": "294"
++        },
++        {
++          "name": "vencrypt",
++          "default": null,
++          "type": "295"
++        },
++        {
++          "name": "display",
++          "default": null,
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "114",
++      "members": [
++        {
++          "name": "password",
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "115",
++      "members": [
++        {
++          "name": "server",
++          "type": "296"
++        },
++        {
++          "name": "client",
++          "type": "297"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "116",
++      "members": [
++        {
++          "name": "server",
++          "type": "296"
++        },
++        {
++          "name": "client",
++          "type": "292"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "117",
++      "members": [
++        {
++          "name": "server",
++          "type": "296"
++        },
++        {
++          "name": "client",
++          "type": "292"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "[118]",
++      "element-type": "118",
++      "meta-type": "array"
++    },
++    {
++      "name": "118",
++      "members": [
++        {
++          "name": "name",
++          "type": "str"
++        },
++        {
++          "name": "index",
++          "type": "int"
++        },
++        {
++          "name": "current",
++          "type": "bool"
++        },
++        {
++          "name": "absolute",
++          "type": "bool"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "119",
++      "members": [
++        {
++          "name": "keys",
++          "type": "[298]"
++        },
++        {
++          "name": "hold-time",
++          "default": null,
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "120",
++      "members": [
++        {
++          "name": "device",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "head",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "events",
++          "type": "[299]"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "121",
++      "tag": "type",
++      "variants": [
++        {
++          "case": "gtk",
++          "type": "302"
++        },
++        {
++          "case": "curses",
++          "type": "303"
++        },
++        {
++          "case": "egl-headless",
++          "type": "304"
++        },
++        {
++          "case": "default",
++          "type": "0"
++        },
++        {
++          "case": "none",
++          "type": "0"
++        },
++        {
++          "case": "sdl",
++          "type": "0"
++        },
++        {
++          "case": "cocoa",
++          "type": "0"
++        },
++        {
++          "case": "spice-app",
++          "type": "0"
++        }
++      ],
++      "members": [
++        {
++          "name": "type",
++          "type": "300"
++        },
++        {
++          "name": "full-screen",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "window-close",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "gl",
++          "default": null,
++          "type": "301"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "122",
++      "members": [
++        {
++          "name": "status",
++          "default": null,
++          "type": "305"
++        },
++        {
++          "name": "ram",
++          "default": null,
++          "type": "306"
++        },
++        {
++          "name": "disk",
++          "default": null,
++          "type": "306"
++        },
++        {
++          "name": "xbzrle-cache",
++          "default": null,
++          "type": "307"
++        },
++        {
++          "name": "total-time",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "expected-downtime",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "downtime",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "setup-time",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "cpu-throttle-percentage",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "error-desc",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "postcopy-blocktime",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "postcopy-vcpu-blocktime",
++          "default": null,
++          "type": "[int]"
++        },
++        {
++          "name": "compression",
++          "default": null,
++          "type": "308"
++        },
++        {
++          "name": "socket-address",
++          "default": null,
++          "type": "[309]"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "123",
++      "members": [
++        {
++          "name": "capabilities",
++          "type": "[124]"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "[124]",
++      "element-type": "124",
++      "meta-type": "array"
++    },
++    {
++      "name": "124",
++      "members": [
++        {
++          "name": "capability",
++          "type": "310"
++        },
++        {
++          "name": "state",
++          "type": "bool"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "125",
++      "members": [
++        {
++          "name": "announce-initial",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "announce-max",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "announce-rounds",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "announce-step",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "compress-level",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "compress-threads",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "compress-wait-thread",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "decompress-threads",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "cpu-throttle-initial",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "cpu-throttle-increment",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "tls-creds",
++          "default": null,
++          "type": "274"
++        },
++        {
++          "name": "tls-hostname",
++          "default": null,
++          "type": "274"
++        },
++        {
++          "name": "tls-authz",
++          "default": null,
++          "type": "274"
++        },
++        {
++          "name": "max-bandwidth",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "downtime-limit",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "x-checkpoint-delay",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "block-incremental",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "multifd-channels",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "xbzrle-cache-size",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "max-postcopy-bandwidth",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "max-cpu-throttle",
++          "default": null,
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "126",
++      "members": [
++        {
++          "name": "announce-initial",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "announce-max",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "announce-rounds",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "announce-step",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "compress-level",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "compress-threads",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "compress-wait-thread",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "decompress-threads",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "cpu-throttle-initial",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "cpu-throttle-increment",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "tls-creds",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "tls-hostname",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "tls-authz",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "max-bandwidth",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "downtime-limit",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "x-checkpoint-delay",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "block-incremental",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "multifd-channels",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "xbzrle-cache-size",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "max-postcopy-bandwidth",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "max-cpu-throttle",
++          "default": null,
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "127",
++      "members": [
++        {
++          "name": "protocol",
++          "type": "str"
++        },
++        {
++          "name": "hostname",
++          "type": "str"
++        },
++        {
++          "name": "port",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "tls-port",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "cert-subject",
++          "default": null,
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "128",
++      "members": [
++        {
++          "name": "status",
++          "type": "305"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "129",
++      "members": [
++        {
++          "name": "pass",
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "130",
++      "members": [
++        {
++          "name": "mode",
++          "type": "311"
++        },
++        {
++          "name": "reason",
++          "type": "312"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "131",
++      "members": [
++        {
++          "name": "state",
++          "type": "305"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "132",
++      "members": [
++        {
++          "name": "value",
++          "type": "number"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "133",
++      "members": [
++        {
++          "name": "value",
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "134",
++      "members": [
++        {
++          "name": "value",
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "int",
++      "json-type": "int",
++      "meta-type": "builtin"
++    },
++    {
++      "name": "135",
++      "members": [
++        {
++          "name": "uri",
++          "type": "str"
++        },
++        {
++          "name": "blk",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "inc",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "detach",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "resume",
++          "default": null,
++          "type": "bool"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "136",
++      "members": [
++        {
++          "name": "uri",
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "137",
++      "members": [
++        {
++          "name": "filename",
++          "type": "str"
++        },
++        {
++          "name": "live",
++          "default": null,
++          "type": "bool"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "138",
++      "members": [
++        {
++          "name": "enable",
++          "type": "bool"
++        },
++        {
++          "name": "primary",
++          "type": "bool"
++        },
++        {
++          "name": "failover",
++          "default": null,
++          "type": "bool"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "139",
++      "members": [
++        {
++          "name": "error",
++          "type": "bool"
++        },
++        {
++          "name": "desc",
++          "default": null,
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "140",
++      "members": [
++        {
++          "name": "mode",
++          "type": "311"
++        },
++        {
++          "name": "last-mode",
++          "type": "311"
++        },
++        {
++          "name": "reason",
++          "type": "312"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "141",
++      "members": [
++        {
++          "name": "uri",
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "142",
++      "members": [
++        {
++          "name": "actions",
++          "type": "[313]"
++        },
++        {
++          "name": "properties",
++          "default": null,
++          "type": "314"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "143",
++      "members": [
++        {
++          "name": "name",
++          "type": "str"
++        },
++        {
++          "name": "vcpu",
++          "default": null,
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "[144]",
++      "element-type": "144",
++      "meta-type": "array"
++    },
++    {
++      "name": "144",
++      "members": [
++        {
++          "name": "name",
++          "type": "str"
++        },
++        {
++          "name": "state",
++          "type": "315"
++        },
++        {
++          "name": "vcpu",
++          "type": "bool"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "145",
++      "members": [
++        {
++          "name": "name",
++          "type": "str"
++        },
++        {
++          "name": "enable",
++          "type": "bool"
++        },
++        {
++          "name": "ignore-unavailable",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "vcpu",
++          "default": null,
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "[146]",
++      "element-type": "146",
++      "meta-type": "array"
++    },
++    {
++      "name": "146",
++      "tag": "meta-type",
++      "variants": [
++        {
++          "case": "builtin",
++          "type": "317"
++        },
++        {
++          "case": "enum",
++          "type": "318"
++        },
++        {
++          "case": "array",
++          "type": "319"
++        },
++        {
++          "case": "object",
++          "type": "320"
++        },
++        {
++          "case": "alternate",
++          "type": "321"
++        },
++        {
++          "case": "command",
++          "type": "322"
++        },
++        {
++          "case": "event",
++          "type": "323"
++        }
++      ],
++      "members": [
++        {
++          "name": "name",
++          "type": "str"
++        },
++        {
++          "name": "meta-type",
++          "type": "316"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "147",
++      "members": [
++        {
++          "name": "enable",
++          "default": null,
++          "type": "[324]"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "148",
++      "members": [
++        {
++          "name": "qemu",
++          "type": "325"
++        },
++        {
++          "name": "package",
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "[149]",
++      "element-type": "149",
++      "meta-type": "array"
++    },
++    {
++      "name": "149",
++      "members": [
++        {
++          "name": "name",
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "150",
++      "members": [
++        {
++          "name": "protocol",
++          "type": "str"
++        },
++        {
++          "name": "fdname",
++          "type": "str"
++        },
++        {
++          "name": "skipauth",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "tls",
++          "default": null,
++          "type": "bool"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "151",
++      "members": [
++        {
++          "name": "name",
++          "default": null,
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "152",
++      "members": [
++        {
++          "name": "enabled",
++          "type": "bool"
++        },
++        {
++          "name": "present",
++          "type": "bool"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "153",
++      "members": [
++        {
++          "name": "UUID",
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "[154]",
++      "element-type": "154",
++      "meta-type": "array"
++    },
++    {
++      "name": "154",
++      "members": [
++        {
++          "name": "name",
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "[155]",
++      "element-type": "155",
++      "meta-type": "array"
++    },
++    {
++      "name": "155",
++      "tag": "arch",
++      "variants": [
++        {
++          "case": "x86",
++          "type": "328"
++        },
++        {
++          "case": "sparc",
++          "type": "329"
++        },
++        {
++          "case": "ppc",
++          "type": "330"
++        },
++        {
++          "case": "mips",
++          "type": "331"
++        },
++        {
++          "case": "tricore",
++          "type": "332"
++        },
++        {
++          "case": "s390",
++          "type": "333"
++        },
++        {
++          "case": "riscv",
++          "type": "334"
++        },
++        {
++          "case": "other",
++          "type": "0"
++        }
++      ],
++      "members": [
++        {
++          "name": "CPU",
++          "type": "int"
++        },
++        {
++          "name": "current",
++          "type": "bool"
++        },
++        {
++          "name": "halted",
++          "type": "bool"
++        },
++        {
++          "name": "qom_path",
++          "type": "str"
++        },
++        {
++          "name": "thread_id",
++          "type": "int"
++        },
++        {
++          "name": "props",
++          "default": null,
++          "type": "326"
++        },
++        {
++          "name": "arch",
++          "type": "327"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "[156]",
++      "element-type": "156",
++      "meta-type": "array"
++    },
++    {
++      "name": "156",
++      "tag": "target",
++      "variants": [
++        {
++          "case": "s390x",
++          "type": "333"
++        },
++        {
++          "case": "aarch64",
++          "type": "0"
++        },
++        {
++          "case": "alpha",
++          "type": "0"
++        },
++        {
++          "case": "arm",
++          "type": "0"
++        },
++        {
++          "case": "cris",
++          "type": "0"
++        },
++        {
++          "case": "hppa",
++          "type": "0"
++        },
++        {
++          "case": "i386",
++          "type": "0"
++        },
++        {
++          "case": "lm32",
++          "type": "0"
++        },
++        {
++          "case": "m68k",
++          "type": "0"
++        },
++        {
++          "case": "microblaze",
++          "type": "0"
++        },
++        {
++          "case": "microblazeel",
++          "type": "0"
++        },
++        {
++          "case": "mips",
++          "type": "0"
++        },
++        {
++          "case": "mips64",
++          "type": "0"
++        },
++        {
++          "case": "mips64el",
++          "type": "0"
++        },
++        {
++          "case": "mipsel",
++          "type": "0"
++        },
++        {
++          "case": "moxie",
++          "type": "0"
++        },
++        {
++          "case": "nios2",
++          "type": "0"
++        },
++        {
++          "case": "or1k",
++          "type": "0"
++        },
++        {
++          "case": "ppc",
++          "type": "0"
++        },
++        {
++          "case": "ppc64",
++          "type": "0"
++        },
++        {
++          "case": "riscv32",
++          "type": "0"
++        },
++        {
++          "case": "riscv64",
++          "type": "0"
++        },
++        {
++          "case": "sh4",
++          "type": "0"
++        },
++        {
++          "case": "sh4eb",
++          "type": "0"
++        },
++        {
++          "case": "sparc",
++          "type": "0"
++        },
++        {
++          "case": "sparc64",
++          "type": "0"
++        },
++        {
++          "case": "tricore",
++          "type": "0"
++        },
++        {
++          "case": "unicore32",
++          "type": "0"
++        },
++        {
++          "case": "x86_64",
++          "type": "0"
++        },
++        {
++          "case": "xtensa",
++          "type": "0"
++        },
++        {
++          "case": "xtensaeb",
++          "type": "0"
++        }
++      ],
++      "members": [
++        {
++          "name": "cpu-index",
++          "type": "int"
++        },
++        {
++          "name": "qom-path",
++          "type": "str"
++        },
++        {
++          "name": "thread-id",
++          "type": "int"
++        },
++        {
++          "name": "props",
++          "default": null,
++          "type": "326"
++        },
++        {
++          "name": "arch",
++          "type": "327"
++        },
++        {
++          "name": "target",
++          "type": "335"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "[157]",
++      "element-type": "157",
++      "meta-type": "array"
++    },
++    {
++      "name": "157",
++      "members": [
++        {
++          "name": "id",
++          "type": "str"
++        },
++        {
++          "name": "thread-id",
++          "type": "int"
++        },
++        {
++          "name": "poll-max-ns",
++          "type": "int"
++        },
++        {
++          "name": "poll-grow",
++          "type": "int"
++        },
++        {
++          "name": "poll-shrink",
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "158",
++      "members": [
++        {
++          "name": "actual",
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "159",
++      "members": [
++        {
++          "name": "actual",
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "[160]",
++      "element-type": "160",
++      "meta-type": "array"
++    },
++    {
++      "name": "160",
++      "members": [
++        {
++          "name": "bus",
++          "type": "int"
++        },
++        {
++          "name": "devices",
++          "type": "[336]"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "161",
++      "members": [
++        {
++          "name": "id",
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "162",
++      "members": [
++        {
++          "name": "val",
++          "type": "int"
++        },
++        {
++          "name": "size",
++          "type": "int"
++        },
++        {
++          "name": "filename",
++          "type": "str"
++        },
++        {
++          "name": "cpu-index",
++          "default": null,
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "163",
++      "members": [
++        {
++          "name": "val",
++          "type": "int"
++        },
++        {
++          "name": "size",
++          "type": "int"
++        },
++        {
++          "name": "filename",
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "164",
++      "members": [
++        {
++          "name": "value",
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "165",
++      "members": [
++        {
++          "name": "command-line",
++          "type": "str"
++        },
++        {
++          "name": "cpu-index",
++          "default": null,
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "166",
++      "members": [
++        {
++          "name": "path",
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "[167]",
++      "element-type": "167",
++      "meta-type": "array"
++    },
++    {
++      "name": "167",
++      "members": [
++        {
++          "name": "name",
++          "type": "str"
++        },
++        {
++          "name": "type",
++          "type": "str"
++        },
++        {
++          "name": "description",
++          "default": null,
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "168",
++      "members": [
++        {
++          "name": "path",
++          "type": "str"
++        },
++        {
++          "name": "property",
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "any",
++      "json-type": "value",
++      "meta-type": "builtin"
++    },
++    {
++      "name": "169",
++      "members": [
++        {
++          "name": "path",
++          "type": "str"
++        },
++        {
++          "name": "property",
++          "type": "str"
++        },
++        {
++          "name": "value",
++          "type": "any"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "170",
++      "members": [
++        {
++          "name": "device",
++          "type": "str"
++        },
++        {
++          "name": "target",
++          "type": "str"
++        },
++        {
++          "name": "arg",
++          "default": null,
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "171",
++      "members": [
++        {
++          "name": "implements",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "abstract",
++          "default": null,
++          "type": "bool"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "[172]",
++      "element-type": "172",
++      "meta-type": "array"
++    },
++    {
++      "name": "172",
++      "members": [
++        {
++          "name": "name",
++          "type": "str"
++        },
++        {
++          "name": "abstract",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "parent",
++          "default": null,
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "173",
++      "members": [
++        {
++          "name": "typename",
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "174",
++      "members": [
++        {
++          "name": "typename",
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "175",
++      "members": [
++        {
++          "name": "enable",
++          "type": "bool"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "176",
++      "members": [
++        {
++          "name": "driver",
++          "type": "str"
++        },
++        {
++          "name": "bus",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "id",
++          "default": null,
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "177",
++      "members": [
++        {
++          "name": "id",
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "178",
++      "members": [
++        {
++          "name": "device",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "path",
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "179",
++      "members": [
++        {
++          "name": "paging",
++          "type": "bool"
++        },
++        {
++          "name": "protocol",
++          "type": "str"
++        },
++        {
++          "name": "detach",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "begin",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "length",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "format",
++          "default": null,
++          "type": "337"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "180",
++      "members": [
++        {
++          "name": "status",
++          "type": "338"
++        },
++        {
++          "name": "completed",
++          "type": "int"
++        },
++        {
++          "name": "total",
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "181",
++      "members": [
++        {
++          "name": "result",
++          "type": "180"
++        },
++        {
++          "name": "error",
++          "default": null,
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "182",
++      "members": [
++        {
++          "name": "formats",
++          "type": "[337]"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "183",
++      "members": [
++        {
++          "name": "qom-type",
++          "type": "str"
++        },
++        {
++          "name": "id",
++          "type": "str"
++        },
++        {
++          "name": "props",
++          "default": null,
++          "type": "any"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "184",
++      "members": [
++        {
++          "name": "id",
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "185",
++      "members": [
++        {
++          "name": "fdname",
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "186",
++      "members": [
++        {
++          "name": "fdname",
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "[187]",
++      "element-type": "187",
++      "meta-type": "array"
++    },
++    {
++      "name": "187",
++      "members": [
++        {
++          "name": "name",
++          "type": "str"
++        },
++        {
++          "name": "alias",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "is-default",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "cpu-max",
++          "type": "int"
++        },
++        {
++          "name": "hotpluggable-cpus",
++          "type": "bool"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "188",
++      "members": [
++        {
++          "name": "wakeup-suspend-support",
++          "type": "bool"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "189",
++      "members": [
++        {
++          "name": "base-memory",
++          "type": "int"
++        },
++        {
++          "name": "plugged-memory",
++          "default": null,
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "190",
++      "members": [
++        {
++          "name": "fdset-id",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "opaque",
++          "default": null,
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "191",
++      "members": [
++        {
++          "name": "fdset-id",
++          "type": "int"
++        },
++        {
++          "name": "fd",
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "192",
++      "members": [
++        {
++          "name": "fdset-id",
++          "type": "int"
++        },
++        {
++          "name": "fd",
++          "default": null,
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "[193]",
++      "element-type": "193",
++      "meta-type": "array"
++    },
++    {
++      "name": "193",
++      "members": [
++        {
++          "name": "fdset-id",
++          "type": "int"
++        },
++        {
++          "name": "fds",
++          "type": "[339]"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "194",
++      "members": [
++        {
++          "name": "arch",
++          "type": "335"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "195",
++      "members": [
++        {
++          "name": "option",
++          "default": null,
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "[196]",
++      "element-type": "196",
++      "meta-type": "array"
++    },
++    {
++      "name": "196",
++      "members": [
++        {
++          "name": "option",
++          "type": "str"
++        },
++        {
++          "name": "parameters",
++          "type": "[340]"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "[197]",
++      "element-type": "197",
++      "meta-type": "array"
++    },
++    {
++      "name": "197",
++      "members": [
++        {
++          "name": "id",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "size",
++          "type": "int"
++        },
++        {
++          "name": "merge",
++          "type": "bool"
++        },
++        {
++          "name": "dump",
++          "type": "bool"
++        },
++        {
++          "name": "prealloc",
++          "type": "bool"
++        },
++        {
++          "name": "host-nodes",
++          "type": "[int]"
++        },
++        {
++          "name": "policy",
++          "type": "341"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "[198]",
++      "element-type": "198",
++      "meta-type": "array"
++    },
++    {
++      "name": "198",
++      "tag": "type",
++      "variants": [
++        {
++          "case": "dimm",
++          "type": "343"
++        },
++        {
++          "case": "nvdimm",
++          "type": "343"
++        }
++      ],
++      "members": [
++        {
++          "name": "type",
++          "type": "342"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "199",
++      "members": [
++        {
++          "name": "device",
++          "type": "str"
++        },
++        {
++          "name": "msg",
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "[200]",
++      "element-type": "200",
++      "meta-type": "array"
++    },
++    {
++      "name": "200",
++      "members": [
++        {
++          "name": "device",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "slot",
++          "type": "str"
++        },
++        {
++          "name": "slot-type",
++          "type": "344"
++        },
++        {
++          "name": "source",
++          "type": "int"
++        },
++        {
++          "name": "status",
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "201",
++      "members": [
++        {
++          "name": "info",
++          "type": "200"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "202",
++      "members": [
++        {
++          "name": "filename",
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "[203]",
++      "element-type": "203",
++      "meta-type": "array"
++    },
++    {
++      "name": "203",
++      "members": [
++        {
++          "name": "type",
++          "type": "str"
++        },
++        {
++          "name": "vcpus-count",
++          "type": "int"
++        },
++        {
++          "name": "props",
++          "type": "326"
++        },
++        {
++          "name": "qom-path",
++          "default": null,
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "204",
++      "members": [
++        {
++          "name": "guid",
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "205",
++      "tag": "type",
++      "variants": [
++        {
++          "case": "node",
++          "type": "346"
++        },
++        {
++          "case": "dist",
++          "type": "347"
++        },
++        {
++          "case": "cpu",
++          "type": "348"
++        }
++      ],
++      "members": [
++        {
++          "name": "type",
++          "type": "345"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "206",
++      "members": [
++        {
++          "name": "offset",
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "207",
++      "members": [
++        {
++          "name": "enabled",
++          "type": "bool"
++        },
++        {
++          "name": "api-major",
++          "type": "int"
++        },
++        {
++          "name": "api-minor",
++          "type": "int"
++        },
++        {
++          "name": "build-id",
++          "type": "int"
++        },
++        {
++          "name": "policy",
++          "type": "int"
++        },
++        {
++          "name": "state",
++          "type": "349"
++        },
++        {
++          "name": "handle",
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "208",
++      "members": [
++        {
++          "name": "data",
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "209",
++      "members": [
++        {
++          "name": "pdh",
++          "type": "str"
++        },
++        {
++          "name": "cert-chain",
++          "type": "str"
++        },
++        {
++          "name": "cbitpos",
++          "type": "int"
++        },
++        {
++          "name": "reduced-phys-bits",
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "216",
++      "members": [
++        {
++          "name": "type",
++          "type": "352"
++        },
++        {
++          "name": "model",
++          "type": "350"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "217",
++      "members": [
++        {
++          "name": "model",
++          "type": "350"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "[218]",
++      "element-type": "218",
++      "meta-type": "array"
++    },
++    {
++      "name": "218",
++      "members": [
++        {
++          "name": "name",
++          "type": "str"
++        },
++        {
++          "name": "migration-safe",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "static",
++          "type": "bool"
++        },
++        {
++          "name": "unavailable-features",
++          "default": null,
++          "type": "[str]"
++        },
++        {
++          "name": "typename",
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "bool",
++      "json-type": "boolean",
++      "meta-type": "builtin"
++    },
++    {
++      "name": "219",
++      "meta-type": "enum",
++      "values": [
++        "debug",
++        "inmigrate",
++        "internal-error",
++        "io-error",
++        "paused",
++        "postmigrate",
++        "prelaunch",
++        "finish-migrate",
++        "restore-vm",
++        "running",
++        "save-vm",
++        "shutdown",
++        "suspended",
++        "watchdog",
++        "guest-panicked",
++        "colo",
++        "preconfig"
++      ]
++    },
++    {
++      "name": "220",
++      "meta-type": "enum",
++      "values": [
++        "none",
++        "host-error",
++        "host-qmp-quit",
++        "host-qmp-system-reset",
++        "host-signal",
++        "host-ui",
++        "guest-shutdown",
++        "guest-reset",
++        "guest-panic",
++        "subsystem-reset"
++      ]
++    },
++    {
++      "name": "221",
++      "meta-type": "enum",
++      "values": [
++        "reset",
++        "shutdown",
++        "poweroff",
++        "pause",
++        "debug",
++        "none",
++        "inject-nmi"
++      ]
++    },
++    {
++      "name": "222",
++      "meta-type": "enum",
++      "values": [
++        "pause",
++        "poweroff"
++      ]
++    },
++    {
++      "name": "223",
++      "tag": "type",
++      "variants": [
++        {
++          "case": "hyper-v",
++          "type": "354"
++        },
++        {
++          "case": "s390",
++          "type": "355"
++        }
++      ],
++      "members": [
++        {
++          "name": "type",
++          "type": "353"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "224",
++      "meta-type": "enum",
++      "values": [
++        "undefined",
++        "created",
++        "running",
++        "paused",
++        "ready",
++        "standby",
++        "waiting",
++        "pending",
++        "aborting",
++        "concluded",
++        "null"
++      ]
++    },
++    {
++      "name": "225",
++      "meta-type": "enum",
++      "values": [
++        "commit",
++        "stream",
++        "mirror",
++        "backup",
++        "create"
++      ]
++    },
++    {
++      "name": "[int]",
++      "element-type": "int",
++      "meta-type": "array"
++    },
++    {
++      "name": "226",
++      "meta-type": "enum",
++      "values": [
++        "ok",
++        "failed",
++        "nospace"
++      ]
++    },
++    {
++      "name": "[227]",
++      "element-type": "227",
++      "meta-type": "array"
++    },
++    {
++      "name": "227",
++      "members": [
++        {
++          "name": "name",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "count",
++          "type": "int"
++        },
++        {
++          "name": "granularity",
++          "type": "int"
++        },
++        {
++          "name": "recording",
++          "type": "bool"
++        },
++        {
++          "name": "busy",
++          "type": "bool"
++        },
++        {
++          "name": "status",
++          "type": "356"
++        },
++        {
++          "name": "persistent",
++          "type": "bool"
++        },
++        {
++          "name": "inconsistent",
++          "default": null,
++          "type": "bool"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "228",
++      "members": [
++        {
++          "name": "rd_bytes",
++          "type": "int"
++        },
++        {
++          "name": "wr_bytes",
++          "type": "int"
++        },
++        {
++          "name": "rd_operations",
++          "type": "int"
++        },
++        {
++          "name": "wr_operations",
++          "type": "int"
++        },
++        {
++          "name": "flush_operations",
++          "type": "int"
++        },
++        {
++          "name": "flush_total_time_ns",
++          "type": "int"
++        },
++        {
++          "name": "wr_total_time_ns",
++          "type": "int"
++        },
++        {
++          "name": "rd_total_time_ns",
++          "type": "int"
++        },
++        {
++          "name": "wr_highest_offset",
++          "type": "int"
++        },
++        {
++          "name": "rd_merged",
++          "type": "int"
++        },
++        {
++          "name": "wr_merged",
++          "type": "int"
++        },
++        {
++          "name": "idle_time_ns",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "failed_rd_operations",
++          "type": "int"
++        },
++        {
++          "name": "failed_wr_operations",
++          "type": "int"
++        },
++        {
++          "name": "failed_flush_operations",
++          "type": "int"
++        },
++        {
++          "name": "invalid_rd_operations",
++          "type": "int"
++        },
++        {
++          "name": "invalid_wr_operations",
++          "type": "int"
++        },
++        {
++          "name": "invalid_flush_operations",
++          "type": "int"
++        },
++        {
++          "name": "account_invalid",
++          "type": "bool"
++        },
++        {
++          "name": "account_failed",
++          "type": "bool"
++        },
++        {
++          "name": "timed_stats",
++          "type": "[357]"
++        },
++        {
++          "name": "rd_latency_histogram",
++          "default": null,
++          "type": "358"
++        },
++        {
++          "name": "wr_latency_histogram",
++          "default": null,
++          "type": "358"
++        },
++        {
++          "name": "flush_latency_histogram",
++          "default": null,
++          "type": "358"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "229",
++      "meta-type": "enum",
++      "values": [
++        "existing",
++        "absolute-paths"
++      ]
++    },
++    {
++      "name": "230",
++      "meta-type": "enum",
++      "values": [
++        "top",
++        "full",
++        "none",
++        "incremental"
++      ]
++    },
++    {
++      "name": "231",
++      "meta-type": "enum",
++      "values": [
++        "report",
++        "ignore",
++        "enospc",
++        "stop",
++        "auto"
++      ]
++    },
++    {
++      "name": "232",
++      "meta-type": "enum",
++      "values": [
++        "off",
++        "on",
++        "unmap"
++      ]
++    },
++    {
++      "name": "233",
++      "members": [
++        {
++          "name": "filename",
++          "type": "str"
++        },
++        {
++          "name": "format",
++          "type": "str"
++        },
++        {
++          "name": "dirty-flag",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "actual-size",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "virtual-size",
++          "type": "int"
++        },
++        {
++          "name": "cluster-size",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "encrypted",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "compressed",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "backing-filename",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "full-backing-filename",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "backing-filename-format",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "snapshots",
++          "default": null,
++          "type": "[67]"
++        },
++        {
++          "name": "backing-image",
++          "default": null,
++          "type": "233"
++        },
++        {
++          "name": "format-specific",
++          "default": null,
++          "type": "359"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "234",
++      "members": [
++        {
++          "name": "writeback",
++          "type": "bool"
++        },
++        {
++          "name": "direct",
++          "type": "bool"
++        },
++        {
++          "name": "no-flush",
++          "type": "bool"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "[235]",
++      "element-type": "235",
++      "meta-type": "array"
++    },
++    {
++      "name": "235",
++      "members": [
++        {
++          "name": "id",
++          "type": "int"
++        },
++        {
++          "name": "type",
++          "type": "360"
++        },
++        {
++          "name": "name",
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "[236]",
++      "element-type": "236",
++      "meta-type": "array"
++    },
++    {
++      "name": "236",
++      "members": [
++        {
++          "name": "parent",
++          "type": "int"
++        },
++        {
++          "name": "child",
++          "type": "int"
++        },
++        {
++          "name": "name",
++          "type": "str"
++        },
++        {
++          "name": "perm",
++          "type": "[361]"
++        },
++        {
++          "name": "shared-perm",
++          "type": "[361]"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "237",
++      "meta-type": "enum",
++      "values": [
++        "background",
++        "write-blocking"
++      ]
++    },
++    {
++      "name": "[238]",
++      "element-type": "238",
++      "meta-type": "array"
++    },
++    {
++      "name": "238",
++      "members": [
++        {
++          "type": "str"
++        },
++        {
++          "type": "32"
++        }
++      ],
++      "meta-type": "alternate"
++    },
++    {
++      "name": "239",
++      "meta-type": "enum",
++      "values": [
++        "blkdebug",
++        "blklogwrites",
++        "blkverify",
++        "bochs",
++        "cloop",
++        "copy-on-read",
++        "dmg",
++        "file",
++        "ftp",
++        "ftps",
++        "gluster",
++        "host_cdrom",
++        "host_device",
++        "http",
++        "https",
++        "iscsi",
++        "luks",
++        "nbd",
++        "nfs",
++        "null-aio",
++        "null-co",
++        "nvme",
++        "parallels",
++        "qcow",
++        "qcow2",
++        "qed",
++        "quorum",
++        "raw",
++        "rbd",
++        "replication",
++        "sheepdog",
++        "ssh",
++        "throttle",
++        "vdi",
++        "vhdx",
++        "vmdk",
++        "vpc",
++        "vvfat",
++        "vxhs"
++      ]
++    },
++    {
++      "name": "240",
++      "meta-type": "enum",
++      "values": [
++        "ignore",
++        "unmap"
++      ]
++    },
++    {
++      "name": "241",
++      "members": [
++        {
++          "name": "direct",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "no-flush",
++          "default": null,
++          "type": "bool"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "242",
++      "members": [
++        {
++          "name": "image",
++          "type": "362"
++        },
++        {
++          "name": "config",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "align",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "max-transfer",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "opt-write-zero",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "max-write-zero",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "opt-discard",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "max-discard",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "inject-error",
++          "default": null,
++          "type": "[363]"
++        },
++        {
++          "name": "set-state",
++          "default": null,
++          "type": "[364]"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "243",
++      "members": [
++        {
++          "name": "file",
++          "type": "362"
++        },
++        {
++          "name": "log",
++          "type": "362"
++        },
++        {
++          "name": "log-sector-size",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "log-append",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "log-super-update-interval",
++          "default": null,
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "244",
++      "members": [
++        {
++          "name": "test",
++          "type": "362"
++        },
++        {
++          "name": "raw",
++          "type": "362"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "245",
++      "members": [
++        {
++          "name": "file",
++          "type": "362"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "246",
++      "members": [
++        {
++          "name": "filename",
++          "type": "str"
++        },
++        {
++          "name": "pr-manager",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "locking",
++          "default": null,
++          "type": "365"
++        },
++        {
++          "name": "aio",
++          "default": null,
++          "type": "366"
++        },
++        {
++          "name": "drop-cache",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "x-check-cache-dropped",
++          "default": null,
++          "type": "bool"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "247",
++      "members": [
++        {
++          "name": "url",
++          "type": "str"
++        },
++        {
++          "name": "readahead",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "timeout",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "username",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "password-secret",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "proxy-username",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "proxy-password-secret",
++          "default": null,
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "248",
++      "members": [
++        {
++          "name": "url",
++          "type": "str"
++        },
++        {
++          "name": "readahead",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "timeout",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "username",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "password-secret",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "proxy-username",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "proxy-password-secret",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "sslverify",
++          "default": null,
++          "type": "bool"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "249",
++      "members": [
++        {
++          "name": "volume",
++          "type": "str"
++        },
++        {
++          "name": "path",
++          "type": "str"
++        },
++        {
++          "name": "server",
++          "type": "[309]"
++        },
++        {
++          "name": "debug",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "logfile",
++          "default": null,
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "250",
++      "members": [
++        {
++          "name": "url",
++          "type": "str"
++        },
++        {
++          "name": "readahead",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "timeout",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "username",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "password-secret",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "proxy-username",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "proxy-password-secret",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "cookie",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "cookie-secret",
++          "default": null,
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "251",
++      "members": [
++        {
++          "name": "url",
++          "type": "str"
++        },
++        {
++          "name": "readahead",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "timeout",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "username",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "password-secret",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "proxy-username",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "proxy-password-secret",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "cookie",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "sslverify",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "cookie-secret",
++          "default": null,
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "252",
++      "members": [
++        {
++          "name": "transport",
++          "type": "367"
++        },
++        {
++          "name": "portal",
++          "type": "str"
++        },
++        {
++          "name": "target",
++          "type": "str"
++        },
++        {
++          "name": "lun",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "user",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "password-secret",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "initiator-name",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "header-digest",
++          "default": null,
++          "type": "368"
++        },
++        {
++          "name": "timeout",
++          "default": null,
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "253",
++      "members": [
++        {
++          "name": "file",
++          "type": "362"
++        },
++        {
++          "name": "key-secret",
++          "default": null,
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "254",
++      "members": [
++        {
++          "name": "server",
++          "type": "309"
++        },
++        {
++          "name": "export",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "tls-creds",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "x-dirty-bitmap",
++          "default": null,
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "255",
++      "members": [
++        {
++          "name": "server",
++          "type": "369"
++        },
++        {
++          "name": "path",
++          "type": "str"
++        },
++        {
++          "name": "user",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "group",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "tcp-syn-count",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "readahead-size",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "page-cache-size",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "debug",
++          "default": null,
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "256",
++      "members": [
++        {
++          "name": "size",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "latency-ns",
++          "default": null,
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "257",
++      "members": [
++        {
++          "name": "device",
++          "type": "str"
++        },
++        {
++          "name": "namespace",
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "258",
++      "members": [
++        {
++          "name": "file",
++          "type": "362"
++        },
++        {
++          "name": "backing",
++          "default": null,
++          "type": "370"
++        },
++        {
++          "name": "lazy-refcounts",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "pass-discard-request",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "pass-discard-snapshot",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "pass-discard-other",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "overlap-check",
++          "default": null,
++          "type": "371"
++        },
++        {
++          "name": "cache-size",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "l2-cache-size",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "l2-cache-entry-size",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "refcount-cache-size",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "cache-clean-interval",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "encrypt",
++          "default": null,
++          "type": "372"
++        },
++        {
++          "name": "data-file",
++          "default": null,
++          "type": "362"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "259",
++      "members": [
++        {
++          "name": "file",
++          "type": "362"
++        },
++        {
++          "name": "backing",
++          "default": null,
++          "type": "370"
++        },
++        {
++          "name": "encrypt",
++          "default": null,
++          "type": "373"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "260",
++      "members": [
++        {
++          "name": "file",
++          "type": "362"
++        },
++        {
++          "name": "backing",
++          "default": null,
++          "type": "370"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "261",
++      "members": [
++        {
++          "name": "blkverify",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "children",
++          "type": "[362]"
++        },
++        {
++          "name": "vote-threshold",
++          "type": "int"
++        },
++        {
++          "name": "rewrite-corrupted",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "read-pattern",
++          "default": null,
++          "type": "374"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "262",
++      "members": [
++        {
++          "name": "file",
++          "type": "362"
++        },
++        {
++          "name": "offset",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "size",
++          "default": null,
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "263",
++      "members": [
++        {
++          "name": "pool",
++          "type": "str"
++        },
++        {
++          "name": "image",
++          "type": "str"
++        },
++        {
++          "name": "conf",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "snapshot",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "user",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "auth-client-required",
++          "default": null,
++          "type": "[375]"
++        },
++        {
++          "name": "key-secret",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "server",
++          "default": null,
++          "type": "[376]"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "264",
++      "members": [
++        {
++          "name": "file",
++          "type": "362"
++        },
++        {
++          "name": "mode",
++          "type": "377"
++        },
++        {
++          "name": "top-id",
++          "default": null,
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "265",
++      "members": [
++        {
++          "name": "server",
++          "type": "309"
++        },
++        {
++          "name": "vdi",
++          "type": "str"
++        },
++        {
++          "name": "snap-id",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "tag",
++          "default": null,
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "266",
++      "members": [
++        {
++          "name": "server",
++          "type": "378"
++        },
++        {
++          "name": "path",
++          "type": "str"
++        },
++        {
++          "name": "user",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "host-key-check",
++          "default": null,
++          "type": "379"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "267",
++      "members": [
++        {
++          "name": "throttle-group",
++          "type": "str"
++        },
++        {
++          "name": "file",
++          "type": "362"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "268",
++      "members": [
++        {
++          "name": "dir",
++          "type": "str"
++        },
++        {
++          "name": "fat-type",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "floppy",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "label",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "rw",
++          "default": null,
++          "type": "bool"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "269",
++      "members": [
++        {
++          "name": "vdisk-id",
++          "type": "str"
++        },
++        {
++          "name": "server",
++          "type": "376"
++        },
++        {
++          "name": "tls-creds",
++          "default": null,
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "270",
++      "tag": "driver",
++      "variants": [
++        {
++          "case": "file",
++          "type": "380"
++        },
++        {
++          "case": "gluster",
++          "type": "381"
++        },
++        {
++          "case": "luks",
++          "type": "382"
++        },
++        {
++          "case": "nfs",
++          "type": "383"
++        },
++        {
++          "case": "parallels",
++          "type": "384"
++        },
++        {
++          "case": "qcow",
++          "type": "385"
++        },
++        {
++          "case": "qcow2",
++          "type": "386"
++        },
++        {
++          "case": "qed",
++          "type": "387"
++        },
++        {
++          "case": "rbd",
++          "type": "388"
++        },
++        {
++          "case": "sheepdog",
++          "type": "389"
++        },
++        {
++          "case": "ssh",
++          "type": "390"
++        },
++        {
++          "case": "vdi",
++          "type": "391"
++        },
++        {
++          "case": "vhdx",
++          "type": "392"
++        },
++        {
++          "case": "vmdk",
++          "type": "393"
++        },
++        {
++          "case": "vpc",
++          "type": "394"
++        },
++        {
++          "case": "blkdebug",
++          "type": "0"
++        },
++        {
++          "case": "blklogwrites",
++          "type": "0"
++        },
++        {
++          "case": "blkverify",
++          "type": "0"
++        },
++        {
++          "case": "bochs",
++          "type": "0"
++        },
++        {
++          "case": "cloop",
++          "type": "0"
++        },
++        {
++          "case": "copy-on-read",
++          "type": "0"
++        },
++        {
++          "case": "dmg",
++          "type": "0"
++        },
++        {
++          "case": "ftp",
++          "type": "0"
++        },
++        {
++          "case": "ftps",
++          "type": "0"
++        },
++        {
++          "case": "host_cdrom",
++          "type": "0"
++        },
++        {
++          "case": "host_device",
++          "type": "0"
++        },
++        {
++          "case": "http",
++          "type": "0"
++        },
++        {
++          "case": "https",
++          "type": "0"
++        },
++        {
++          "case": "iscsi",
++          "type": "0"
++        },
++        {
++          "case": "nbd",
++          "type": "0"
++        },
++        {
++          "case": "null-aio",
++          "type": "0"
++        },
++        {
++          "case": "null-co",
++          "type": "0"
++        },
++        {
++          "case": "nvme",
++          "type": "0"
++        },
++        {
++          "case": "quorum",
++          "type": "0"
++        },
++        {
++          "case": "raw",
++          "type": "0"
++        },
++        {
++          "case": "replication",
++          "type": "0"
++        },
++        {
++          "case": "throttle",
++          "type": "0"
++        },
++        {
++          "case": "vvfat",
++          "type": "0"
++        },
++        {
++          "case": "vxhs",
++          "type": "0"
++        }
++      ],
++      "members": [
++        {
++          "name": "driver",
++          "type": "239"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "271",
++      "meta-type": "enum",
++      "values": [
++        "retain",
++        "read-only",
++        "read-write"
++      ]
++    },
++    {
++      "name": "272",
++      "meta-type": "enum",
++      "values": [
++        "read",
++        "write"
++      ]
++    },
++    {
++      "name": "273",
++      "meta-type": "enum",
++      "values": [
++        "ignore",
++        "report",
++        "stop"
++      ]
++    },
++    {
++      "name": "274",
++      "members": [
++        {
++          "type": "str"
++        },
++        {
++          "type": "null"
++        }
++      ],
++      "meta-type": "alternate"
++    },
++    {
++      "name": "275",
++      "tag": "type",
++      "variants": [
++        {
++          "case": "inet",
++          "type": "396"
++        },
++        {
++          "case": "unix",
++          "type": "397"
++        },
++        {
++          "case": "vsock",
++          "type": "398"
++        },
++        {
++          "case": "fd",
++          "type": "399"
++        }
++      ],
++      "members": [
++        {
++          "name": "type",
++          "type": "395"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "276",
++      "meta-type": "enum",
++      "values": [
++        "safe",
++        "hard"
++      ]
++    },
++    {
++      "name": "277",
++      "meta-type": "enum",
++      "values": [
++        "read",
++        "write",
++        "flush"
++      ]
++    },
++    {
++      "name": "278",
++      "meta-type": "enum",
++      "values": [
++        "utf8",
++        "base64"
++      ]
++    },
++    {
++      "name": "279",
++      "tag": "type",
++      "variants": [
++        {
++          "case": "file",
++          "type": "401"
++        },
++        {
++          "case": "serial",
++          "type": "402"
++        },
++        {
++          "case": "parallel",
++          "type": "402"
++        },
++        {
++          "case": "pipe",
++          "type": "402"
++        },
++        {
++          "case": "socket",
++          "type": "403"
++        },
++        {
++          "case": "udp",
++          "type": "404"
++        },
++        {
++          "case": "pty",
++          "type": "405"
++        },
++        {
++          "case": "null",
++          "type": "405"
++        },
++        {
++          "case": "mux",
++          "type": "406"
++        },
++        {
++          "case": "msmouse",
++          "type": "405"
++        },
++        {
++          "case": "wctablet",
++          "type": "405"
++        },
++        {
++          "case": "braille",
++          "type": "405"
++        },
++        {
++          "case": "testdev",
++          "type": "405"
++        },
++        {
++          "case": "stdio",
++          "type": "407"
++        },
++        {
++          "case": "console",
++          "type": "405"
++        },
++        {
++          "case": "spicevmc",
++          "type": "408"
++        },
++        {
++          "case": "spiceport",
++          "type": "409"
++        },
++        {
++          "case": "vc",
++          "type": "410"
++        },
++        {
++          "case": "ringbuf",
++          "type": "411"
++        },
++        {
++          "case": "memory",
++          "type": "411"
++        }
++      ],
++      "members": [
++        {
++          "name": "type",
++          "type": "400"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "280",
++      "meta-type": "enum",
++      "values": [
++        "normal",
++        "none",
++        "all"
++      ]
++    },
++    {
++      "name": "[str]",
++      "element-type": "str",
++      "meta-type": "array"
++    },
++    {
++      "name": "281",
++      "meta-type": "enum",
++      "values": [
++        "half",
++        "full"
++      ]
++    },
++    {
++      "name": "282",
++      "meta-type": "enum",
++      "values": [
++        "off",
++        "on"
++      ]
++    },
++    {
++      "name": "283",
++      "members": [
++        {
++          "name": "priority",
++          "type": "int"
++        },
++        {
++          "name": "tbl-id",
++          "type": "int"
++        },
++        {
++          "name": "in-pport",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "tunnel-id",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "vlan-id",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "eth-type",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "eth-src",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "eth-dst",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "ip-proto",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "ip-tos",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "ip-dst",
++          "default": null,
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "284",
++      "members": [
++        {
++          "name": "in-pport",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "tunnel-id",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "vlan-id",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "eth-src",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "eth-dst",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "ip-proto",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "ip-tos",
++          "default": null,
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "285",
++      "members": [
++        {
++          "name": "goto-tbl",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "group-id",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "tunnel-lport",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "vlan-id",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "new-vlan-id",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "out-pport",
++          "default": null,
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "286",
++      "tag": "type",
++      "variants": [
++        {
++          "case": "passthrough",
++          "type": "413"
++        },
++        {
++          "case": "emulator",
++          "type": "414"
++        }
++      ],
++      "members": [
++        {
++          "name": "type",
++          "type": "412"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "287",
++      "meta-type": "enum",
++      "values": [
++        "client",
++        "server",
++        "unknown"
++      ]
++    },
++    {
++      "name": "[288]",
++      "element-type": "288",
++      "meta-type": "array"
++    },
++    {
++      "name": "288",
++      "members": [
++        {
++          "name": "host",
++          "type": "str"
++        },
++        {
++          "name": "port",
++          "type": "str"
++        },
++        {
++          "name": "family",
++          "type": "291"
++        },
++        {
++          "name": "connection-id",
++          "type": "int"
++        },
++        {
++          "name": "channel-type",
++          "type": "int"
++        },
++        {
++          "name": "channel-id",
++          "type": "int"
++        },
++        {
++          "name": "tls",
++          "type": "bool"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "289",
++      "members": [
++        {
++          "name": "host",
++          "type": "str"
++        },
++        {
++          "name": "port",
++          "type": "str"
++        },
++        {
++          "name": "family",
++          "type": "291"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "290",
++      "members": [
++        {
++          "name": "host",
++          "type": "str"
++        },
++        {
++          "name": "port",
++          "type": "str"
++        },
++        {
++          "name": "family",
++          "type": "291"
++        },
++        {
++          "name": "auth",
++          "default": null,
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "291",
++      "meta-type": "enum",
++      "values": [
++        "ipv4",
++        "ipv6",
++        "unix",
++        "vsock",
++        "unknown"
++      ]
++    },
++    {
++      "name": "[292]",
++      "element-type": "292",
++      "meta-type": "array"
++    },
++    {
++      "name": "292",
++      "members": [
++        {
++          "name": "host",
++          "type": "str"
++        },
++        {
++          "name": "service",
++          "type": "str"
++        },
++        {
++          "name": "family",
++          "type": "291"
++        },
++        {
++          "name": "websocket",
++          "type": "bool"
++        },
++        {
++          "name": "x509_dname",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "sasl_username",
++          "default": null,
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "[293]",
++      "element-type": "293",
++      "meta-type": "array"
++    },
++    {
++      "name": "293",
++      "members": [
++        {
++          "name": "host",
++          "type": "str"
++        },
++        {
++          "name": "service",
++          "type": "str"
++        },
++        {
++          "name": "family",
++          "type": "291"
++        },
++        {
++          "name": "websocket",
++          "type": "bool"
++        },
++        {
++          "name": "auth",
++          "type": "294"
++        },
++        {
++          "name": "vencrypt",
++          "default": null,
++          "type": "295"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "294",
++      "meta-type": "enum",
++      "values": [
++        "none",
++        "vnc",
++        "ra2",
++        "ra2ne",
++        "tight",
++        "ultra",
++        "tls",
++        "vencrypt",
++        "sasl"
++      ]
++    },
++    {
++      "name": "295",
++      "meta-type": "enum",
++      "values": [
++        "plain",
++        "tls-none",
++        "x509-none",
++        "tls-vnc",
++        "x509-vnc",
++        "tls-plain",
++        "x509-plain",
++        "tls-sasl",
++        "x509-sasl"
++      ]
++    },
++    {
++      "name": "296",
++      "members": [
++        {
++          "name": "host",
++          "type": "str"
++        },
++        {
++          "name": "service",
++          "type": "str"
++        },
++        {
++          "name": "family",
++          "type": "291"
++        },
++        {
++          "name": "websocket",
++          "type": "bool"
++        },
++        {
++          "name": "auth",
++          "default": null,
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "297",
++      "members": [
++        {
++          "name": "host",
++          "type": "str"
++        },
++        {
++          "name": "service",
++          "type": "str"
++        },
++        {
++          "name": "family",
++          "type": "291"
++        },
++        {
++          "name": "websocket",
++          "type": "bool"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "[298]",
++      "element-type": "298",
++      "meta-type": "array"
++    },
++    {
++      "name": "298",
++      "tag": "type",
++      "variants": [
++        {
++          "case": "number",
++          "type": "416"
++        },
++        {
++          "case": "qcode",
++          "type": "417"
++        }
++      ],
++      "members": [
++        {
++          "name": "type",
++          "type": "415"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "[299]",
++      "element-type": "299",
++      "meta-type": "array"
++    },
++    {
++      "name": "299",
++      "tag": "type",
++      "variants": [
++        {
++          "case": "key",
++          "type": "419"
++        },
++        {
++          "case": "btn",
++          "type": "420"
++        },
++        {
++          "case": "rel",
++          "type": "421"
++        },
++        {
++          "case": "abs",
++          "type": "421"
++        }
++      ],
++      "members": [
++        {
++          "name": "type",
++          "type": "418"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "300",
++      "meta-type": "enum",
++      "values": [
++        "default",
++        "none",
++        "gtk",
++        "sdl",
++        "egl-headless",
++        "curses",
++        "cocoa",
++        "spice-app"
++      ]
++    },
++    {
++      "name": "301",
++      "meta-type": "enum",
++      "values": [
++        "off",
++        "on",
++        "core",
++        "es"
++      ]
++    },
++    {
++      "name": "302",
++      "members": [
++        {
++          "name": "grab-on-hover",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "zoom-to-fit",
++          "default": null,
++          "type": "bool"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "303",
++      "members": [
++        {
++          "name": "charset",
++          "default": null,
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "304",
++      "members": [
++        {
++          "name": "rendernode",
++          "default": null,
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "305",
++      "meta-type": "enum",
++      "values": [
++        "none",
++        "setup",
++        "cancelling",
++        "cancelled",
++        "active",
++        "postcopy-active",
++        "postcopy-paused",
++        "postcopy-recover",
++        "completed",
++        "failed",
++        "colo",
++        "pre-switchover",
++        "device"
++      ]
++    },
++    {
++      "name": "306",
++      "members": [
++        {
++          "name": "transferred",
++          "type": "int"
++        },
++        {
++          "name": "remaining",
++          "type": "int"
++        },
++        {
++          "name": "total",
++          "type": "int"
++        },
++        {
++          "name": "duplicate",
++          "type": "int"
++        },
++        {
++          "name": "skipped",
++          "type": "int"
++        },
++        {
++          "name": "normal",
++          "type": "int"
++        },
++        {
++          "name": "normal-bytes",
++          "type": "int"
++        },
++        {
++          "name": "dirty-pages-rate",
++          "type": "int"
++        },
++        {
++          "name": "mbps",
++          "type": "number"
++        },
++        {
++          "name": "dirty-sync-count",
++          "type": "int"
++        },
++        {
++          "name": "postcopy-requests",
++          "type": "int"
++        },
++        {
++          "name": "page-size",
++          "type": "int"
++        },
++        {
++          "name": "multifd-bytes",
++          "type": "int"
++        },
++        {
++          "name": "pages-per-second",
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "307",
++      "members": [
++        {
++          "name": "cache-size",
++          "type": "int"
++        },
++        {
++          "name": "bytes",
++          "type": "int"
++        },
++        {
++          "name": "pages",
++          "type": "int"
++        },
++        {
++          "name": "cache-miss",
++          "type": "int"
++        },
++        {
++          "name": "cache-miss-rate",
++          "type": "number"
++        },
++        {
++          "name": "overflow",
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "308",
++      "members": [
++        {
++          "name": "pages",
++          "type": "int"
++        },
++        {
++          "name": "busy",
++          "type": "int"
++        },
++        {
++          "name": "busy-rate",
++          "type": "number"
++        },
++        {
++          "name": "compressed-size",
++          "type": "int"
++        },
++        {
++          "name": "compression-rate",
++          "type": "number"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "[309]",
++      "element-type": "309",
++      "meta-type": "array"
++    },
++    {
++      "name": "309",
++      "tag": "type",
++      "variants": [
++        {
++          "case": "inet",
++          "type": "378"
++        },
++        {
++          "case": "unix",
++          "type": "423"
++        },
++        {
++          "case": "vsock",
++          "type": "424"
++        },
++        {
++          "case": "fd",
++          "type": "425"
++        }
++      ],
++      "members": [
++        {
++          "name": "type",
++          "type": "422"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "310",
++      "meta-type": "enum",
++      "values": [
++        "xbzrle",
++        "rdma-pin-all",
++        "auto-converge",
++        "zero-blocks",
++        "compress",
++        "events",
++        "postcopy-ram",
++        "x-colo",
++        "release-ram",
++        "block",
++        "return-path",
++        "pause-before-switchover",
++        "multifd",
++        "dirty-bitmaps",
++        "postcopy-blocktime",
++        "late-block-activate",
++        "x-ignore-shared"
++      ]
++    },
++    {
++      "name": "311",
++      "meta-type": "enum",
++      "values": [
++        "none",
++        "primary",
++        "secondary"
++      ]
++    },
++    {
++      "name": "312",
++      "meta-type": "enum",
++      "values": [
++        "none",
++        "request",
++        "error",
++        "processing"
++      ]
++    },
++    {
++      "name": "number",
++      "json-type": "number",
++      "meta-type": "builtin"
++    },
++    {
++      "name": "[313]",
++      "element-type": "313",
++      "meta-type": "array"
++    },
++    {
++      "name": "313",
++      "tag": "type",
++      "variants": [
++        {
++          "case": "abort",
++          "type": "427"
++        },
++        {
++          "case": "block-dirty-bitmap-add",
++          "type": "428"
++        },
++        {
++          "case": "block-dirty-bitmap-clear",
++          "type": "429"
++        },
++        {
++          "case": "block-dirty-bitmap-enable",
++          "type": "429"
++        },
++        {
++          "case": "block-dirty-bitmap-disable",
++          "type": "429"
++        },
++        {
++          "case": "block-dirty-bitmap-merge",
++          "type": "430"
++        },
++        {
++          "case": "blockdev-backup",
++          "type": "431"
++        },
++        {
++          "case": "blockdev-snapshot",
++          "type": "432"
++        },
++        {
++          "case": "blockdev-snapshot-internal-sync",
++          "type": "433"
++        },
++        {
++          "case": "blockdev-snapshot-sync",
++          "type": "434"
++        },
++        {
++          "case": "drive-backup",
++          "type": "435"
++        }
++      ],
++      "members": [
++        {
++          "name": "type",
++          "type": "426"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "314",
++      "members": [
++        {
++          "name": "completion-mode",
++          "default": null,
++          "type": "436"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "315",
++      "meta-type": "enum",
++      "values": [
++        "unavailable",
++        "disabled",
++        "enabled"
++      ]
++    },
++    {
++      "name": "316",
++      "meta-type": "enum",
++      "values": [
++        "builtin",
++        "enum",
++        "array",
++        "object",
++        "alternate",
++        "command",
++        "event"
++      ]
++    },
++    {
++      "name": "317",
++      "members": [
++        {
++          "name": "json-type",
++          "type": "437"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "318",
++      "members": [
++        {
++          "name": "values",
++          "type": "[str]"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "319",
++      "members": [
++        {
++          "name": "element-type",
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "320",
++      "members": [
++        {
++          "name": "members",
++          "type": "[438]"
++        },
++        {
++          "name": "tag",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "variants",
++          "default": null,
++          "type": "[439]"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "321",
++      "members": [
++        {
++          "name": "members",
++          "type": "[440]"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "322",
++      "members": [
++        {
++          "name": "arg-type",
++          "type": "str"
++        },
++        {
++          "name": "ret-type",
++          "type": "str"
++        },
++        {
++          "name": "allow-oob",
++          "default": null,
++          "type": "bool"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "323",
++      "members": [
++        {
++          "name": "arg-type",
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "[324]",
++      "element-type": "324",
++      "meta-type": "array"
++    },
++    {
++      "name": "324",
++      "meta-type": "enum",
++      "values": [
++        "oob"
++      ]
++    },
++    {
++      "name": "325",
++      "members": [
++        {
++          "name": "major",
++          "type": "int"
++        },
++        {
++          "name": "minor",
++          "type": "int"
++        },
++        {
++          "name": "micro",
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "326",
++      "members": [
++        {
++          "name": "node-id",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "socket-id",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "core-id",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "thread-id",
++          "default": null,
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "327",
++      "meta-type": "enum",
++      "values": [
++        "x86",
++        "sparc",
++        "ppc",
++        "mips",
++        "tricore",
++        "s390",
++        "riscv",
++        "other"
++      ]
++    },
++    {
++      "name": "328",
++      "members": [
++        {
++          "name": "pc",
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "329",
++      "members": [
++        {
++          "name": "pc",
++          "type": "int"
++        },
++        {
++          "name": "npc",
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "330",
++      "members": [
++        {
++          "name": "nip",
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "331",
++      "members": [
++        {
++          "name": "PC",
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "332",
++      "members": [
++        {
++          "name": "PC",
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "333",
++      "members": [
++        {
++          "name": "cpu-state",
++          "type": "441"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "334",
++      "members": [
++        {
++          "name": "pc",
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "335",
++      "meta-type": "enum",
++      "values": [
++        "aarch64",
++        "alpha",
++        "arm",
++        "cris",
++        "hppa",
++        "i386",
++        "lm32",
++        "m68k",
++        "microblaze",
++        "microblazeel",
++        "mips",
++        "mips64",
++        "mips64el",
++        "mipsel",
++        "moxie",
++        "nios2",
++        "or1k",
++        "ppc",
++        "ppc64",
++        "riscv32",
++        "riscv64",
++        "s390x",
++        "sh4",
++        "sh4eb",
++        "sparc",
++        "sparc64",
++        "tricore",
++        "unicore32",
++        "x86_64",
++        "xtensa",
++        "xtensaeb"
++      ]
++    },
++    {
++      "name": "[336]",
++      "element-type": "336",
++      "meta-type": "array"
++    },
++    {
++      "name": "336",
++      "members": [
++        {
++          "name": "bus",
++          "type": "int"
++        },
++        {
++          "name": "slot",
++          "type": "int"
++        },
++        {
++          "name": "function",
++          "type": "int"
++        },
++        {
++          "name": "class_info",
++          "type": "442"
++        },
++        {
++          "name": "id",
++          "type": "443"
++        },
++        {
++          "name": "irq",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "qdev_id",
++          "type": "str"
++        },
++        {
++          "name": "pci_bridge",
++          "default": null,
++          "type": "444"
++        },
++        {
++          "name": "regions",
++          "type": "[445]"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "337",
++      "meta-type": "enum",
++      "values": [
++        "elf",
++        "kdump-zlib",
++        "kdump-lzo",
++        "kdump-snappy",
++        "win-dmp"
++      ]
++    },
++    {
++      "name": "338",
++      "meta-type": "enum",
++      "values": [
++        "none",
++        "active",
++        "completed",
++        "failed"
++      ]
++    },
++    {
++      "name": "[337]",
++      "element-type": "337",
++      "meta-type": "array"
++    },
++    {
++      "name": "[339]",
++      "element-type": "339",
++      "meta-type": "array"
++    },
++    {
++      "name": "339",
++      "members": [
++        {
++          "name": "fd",
++          "type": "int"
++        },
++        {
++          "name": "opaque",
++          "default": null,
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "[340]",
++      "element-type": "340",
++      "meta-type": "array"
++    },
++    {
++      "name": "340",
++      "members": [
++        {
++          "name": "name",
++          "type": "str"
++        },
++        {
++          "name": "type",
++          "type": "446"
++        },
++        {
++          "name": "help",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "default",
++          "default": null,
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "341",
++      "meta-type": "enum",
++      "values": [
++        "default",
++        "preferred",
++        "bind",
++        "interleave"
++      ]
++    },
++    {
++      "name": "342",
++      "meta-type": "enum",
++      "values": [
++        "dimm",
++        "nvdimm"
++      ]
++    },
++    {
++      "name": "343",
++      "members": [
++        {
++          "name": "data",
++          "type": "447"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "344",
++      "meta-type": "enum",
++      "values": [
++        "DIMM",
++        "CPU"
++      ]
++    },
++    {
++      "name": "345",
++      "meta-type": "enum",
++      "values": [
++        "node",
++        "dist",
++        "cpu"
++      ]
++    },
++    {
++      "name": "346",
++      "members": [
++        {
++          "name": "nodeid",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "cpus",
++          "default": null,
++          "type": "[int]"
++        },
++        {
++          "name": "mem",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "memdev",
++          "default": null,
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "347",
++      "members": [
++        {
++          "name": "src",
++          "type": "int"
++        },
++        {
++          "name": "dst",
++          "type": "int"
++        },
++        {
++          "name": "val",
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "348",
++      "members": [
++        {
++          "name": "node-id",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "socket-id",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "core-id",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "thread-id",
++          "default": null,
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "349",
++      "meta-type": "enum",
++      "values": [
++        "uninit",
++        "launch-update",
++        "launch-secret",
++        "running",
++        "send-update",
++        "receive-update"
++      ]
++    },
++    {
++      "name": "350",
++      "members": [
++        {
++          "name": "name",
++          "type": "str"
++        },
++        {
++          "name": "props",
++          "default": null,
++          "type": "any"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "351",
++      "meta-type": "enum",
++      "values": [
++        "incompatible",
++        "identical",
++        "superset",
++        "subset"
++      ]
++    },
++    {
++      "name": "352",
++      "meta-type": "enum",
++      "values": [
++        "static",
++        "full"
++      ]
++    },
++    {
++      "name": "353",
++      "meta-type": "enum",
++      "values": [
++        "hyper-v",
++        "s390"
++      ]
++    },
++    {
++      "name": "354",
++      "members": [
++        {
++          "name": "arg1",
++          "type": "int"
++        },
++        {
++          "name": "arg2",
++          "type": "int"
++        },
++        {
++          "name": "arg3",
++          "type": "int"
++        },
++        {
++          "name": "arg4",
++          "type": "int"
++        },
++        {
++          "name": "arg5",
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "355",
++      "members": [
++        {
++          "name": "core",
++          "type": "int"
++        },
++        {
++          "name": "psw-mask",
++          "type": "int"
++        },
++        {
++          "name": "psw-addr",
++          "type": "int"
++        },
++        {
++          "name": "reason",
++          "type": "448"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "356",
++      "meta-type": "enum",
++      "values": [
++        "active",
++        "disabled",
++        "frozen",
++        "locked",
++        "inconsistent"
++      ]
++    },
++    {
++      "name": "[357]",
++      "element-type": "357",
++      "meta-type": "array"
++    },
++    {
++      "name": "357",
++      "members": [
++        {
++          "name": "interval_length",
++          "type": "int"
++        },
++        {
++          "name": "min_rd_latency_ns",
++          "type": "int"
++        },
++        {
++          "name": "max_rd_latency_ns",
++          "type": "int"
++        },
++        {
++          "name": "avg_rd_latency_ns",
++          "type": "int"
++        },
++        {
++          "name": "min_wr_latency_ns",
++          "type": "int"
++        },
++        {
++          "name": "max_wr_latency_ns",
++          "type": "int"
++        },
++        {
++          "name": "avg_wr_latency_ns",
++          "type": "int"
++        },
++        {
++          "name": "min_flush_latency_ns",
++          "type": "int"
++        },
++        {
++          "name": "max_flush_latency_ns",
++          "type": "int"
++        },
++        {
++          "name": "avg_flush_latency_ns",
++          "type": "int"
++        },
++        {
++          "name": "avg_rd_queue_depth",
++          "type": "number"
++        },
++        {
++          "name": "avg_wr_queue_depth",
++          "type": "number"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "358",
++      "members": [
++        {
++          "name": "boundaries",
++          "type": "[int]"
++        },
++        {
++          "name": "bins",
++          "type": "[int]"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "[67]",
++      "element-type": "67",
++      "meta-type": "array"
++    },
++    {
++      "name": "359",
++      "tag": "type",
++      "variants": [
++        {
++          "case": "qcow2",
++          "type": "450"
++        },
++        {
++          "case": "vmdk",
++          "type": "451"
++        },
++        {
++          "case": "luks",
++          "type": "452"
++        }
++      ],
++      "members": [
++        {
++          "name": "type",
++          "type": "449"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "360",
++      "meta-type": "enum",
++      "values": [
++        "block-backend",
++        "block-job",
++        "block-driver"
++      ]
++    },
++    {
++      "name": "[361]",
++      "element-type": "361",
++      "meta-type": "array"
++    },
++    {
++      "name": "361",
++      "meta-type": "enum",
++      "values": [
++        "consistent-read",
++        "write",
++        "write-unchanged",
++        "resize",
++        "graph-mod"
++      ]
++    },
++    {
++      "name": "362",
++      "members": [
++        {
++          "type": "45"
++        },
++        {
++          "type": "str"
++        }
++      ],
++      "meta-type": "alternate"
++    },
++    {
++      "name": "[363]",
++      "element-type": "363",
++      "meta-type": "array"
++    },
++    {
++      "name": "363",
++      "members": [
++        {
++          "name": "event",
++          "type": "453"
++        },
++        {
++          "name": "state",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "errno",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "sector",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "once",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "immediately",
++          "default": null,
++          "type": "bool"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "[364]",
++      "element-type": "364",
++      "meta-type": "array"
++    },
++    {
++      "name": "364",
++      "members": [
++        {
++          "name": "event",
++          "type": "453"
++        },
++        {
++          "name": "state",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "new_state",
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "365",
++      "meta-type": "enum",
++      "values": [
++        "auto",
++        "on",
++        "off"
++      ]
++    },
++    {
++      "name": "366",
++      "meta-type": "enum",
++      "values": [
++        "threads",
++        "native"
++      ]
++    },
++    {
++      "name": "367",
++      "meta-type": "enum",
++      "values": [
++        "tcp",
++        "iser"
++      ]
++    },
++    {
++      "name": "368",
++      "meta-type": "enum",
++      "values": [
++        "crc32c",
++        "none",
++        "crc32c-none",
++        "none-crc32c"
++      ]
++    },
++    {
++      "name": "369",
++      "members": [
++        {
++          "name": "type",
++          "type": "454"
++        },
++        {
++          "name": "host",
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "370",
++      "members": [
++        {
++          "type": "45"
++        },
++        {
++          "type": "str"
++        },
++        {
++          "type": "null"
++        }
++      ],
++      "meta-type": "alternate"
++    },
++    {
++      "name": "371",
++      "members": [
++        {
++          "type": "455"
++        },
++        {
++          "type": "456"
++        }
++      ],
++      "meta-type": "alternate"
++    },
++    {
++      "name": "372",
++      "tag": "format",
++      "variants": [
++        {
++          "case": "aes",
++          "type": "458"
++        },
++        {
++          "case": "luks",
++          "type": "459"
++        }
++      ],
++      "members": [
++        {
++          "name": "format",
++          "type": "457"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "373",
++      "tag": "format",
++      "variants": [
++        {
++          "case": "aes",
++          "type": "458"
++        }
++      ],
++      "members": [
++        {
++          "name": "format",
++          "type": "460"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "[362]",
++      "element-type": "362",
++      "meta-type": "array"
++    },
++    {
++      "name": "374",
++      "meta-type": "enum",
++      "values": [
++        "quorum",
++        "fifo"
++      ]
++    },
++    {
++      "name": "[375]",
++      "element-type": "375",
++      "meta-type": "array"
++    },
++    {
++      "name": "375",
++      "meta-type": "enum",
++      "values": [
++        "cephx",
++        "none"
++      ]
++    },
++    {
++      "name": "[376]",
++      "element-type": "376",
++      "meta-type": "array"
++    },
++    {
++      "name": "376",
++      "members": [
++        {
++          "name": "host",
++          "type": "str"
++        },
++        {
++          "name": "port",
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "377",
++      "meta-type": "enum",
++      "values": [
++        "primary",
++        "secondary"
++      ]
++    },
++    {
++      "name": "378",
++      "members": [
++        {
++          "name": "host",
++          "type": "str"
++        },
++        {
++          "name": "port",
++          "type": "str"
++        },
++        {
++          "name": "numeric",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "to",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "ipv4",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "ipv6",
++          "default": null,
++          "type": "bool"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "379",
++      "tag": "mode",
++      "variants": [
++        {
++          "case": "hash",
++          "type": "462"
++        },
++        {
++          "case": "none",
++          "type": "0"
++        },
++        {
++          "case": "known_hosts",
++          "type": "0"
++        }
++      ],
++      "members": [
++        {
++          "name": "mode",
++          "type": "461"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "380",
++      "members": [
++        {
++          "name": "filename",
++          "type": "str"
++        },
++        {
++          "name": "size",
++          "type": "int"
++        },
++        {
++          "name": "preallocation",
++          "default": null,
++          "type": "463"
++        },
++        {
++          "name": "nocow",
++          "default": null,
++          "type": "bool"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "381",
++      "members": [
++        {
++          "name": "location",
++          "type": "249"
++        },
++        {
++          "name": "size",
++          "type": "int"
++        },
++        {
++          "name": "preallocation",
++          "default": null,
++          "type": "463"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "382",
++      "members": [
++        {
++          "name": "key-secret",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "cipher-alg",
++          "default": null,
++          "type": "464"
++        },
++        {
++          "name": "cipher-mode",
++          "default": null,
++          "type": "465"
++        },
++        {
++          "name": "ivgen-alg",
++          "default": null,
++          "type": "466"
++        },
++        {
++          "name": "ivgen-hash-alg",
++          "default": null,
++          "type": "467"
++        },
++        {
++          "name": "hash-alg",
++          "default": null,
++          "type": "467"
++        },
++        {
++          "name": "iter-time",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "file",
++          "type": "362"
++        },
++        {
++          "name": "size",
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "383",
++      "members": [
++        {
++          "name": "location",
++          "type": "255"
++        },
++        {
++          "name": "size",
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "384",
++      "members": [
++        {
++          "name": "file",
++          "type": "362"
++        },
++        {
++          "name": "size",
++          "type": "int"
++        },
++        {
++          "name": "cluster-size",
++          "default": null,
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "385",
++      "members": [
++        {
++          "name": "file",
++          "type": "362"
++        },
++        {
++          "name": "size",
++          "type": "int"
++        },
++        {
++          "name": "backing-file",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "encrypt",
++          "default": null,
++          "type": "468"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "386",
++      "members": [
++        {
++          "name": "file",
++          "type": "362"
++        },
++        {
++          "name": "data-file",
++          "default": null,
++          "type": "362"
++        },
++        {
++          "name": "data-file-raw",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "size",
++          "type": "int"
++        },
++        {
++          "name": "version",
++          "default": null,
++          "type": "469"
++        },
++        {
++          "name": "backing-file",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "backing-fmt",
++          "default": null,
++          "type": "239"
++        },
++        {
++          "name": "encrypt",
++          "default": null,
++          "type": "468"
++        },
++        {
++          "name": "cluster-size",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "preallocation",
++          "default": null,
++          "type": "463"
++        },
++        {
++          "name": "lazy-refcounts",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "refcount-bits",
++          "default": null,
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "387",
++      "members": [
++        {
++          "name": "file",
++          "type": "362"
++        },
++        {
++          "name": "size",
++          "type": "int"
++        },
++        {
++          "name": "backing-file",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "backing-fmt",
++          "default": null,
++          "type": "239"
++        },
++        {
++          "name": "cluster-size",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "table-size",
++          "default": null,
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "388",
++      "members": [
++        {
++          "name": "location",
++          "type": "263"
++        },
++        {
++          "name": "size",
++          "type": "int"
++        },
++        {
++          "name": "cluster-size",
++          "default": null,
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "389",
++      "members": [
++        {
++          "name": "location",
++          "type": "265"
++        },
++        {
++          "name": "size",
++          "type": "int"
++        },
++        {
++          "name": "backing-file",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "preallocation",
++          "default": null,
++          "type": "463"
++        },
++        {
++          "name": "redundancy",
++          "default": null,
++          "type": "470"
++        },
++        {
++          "name": "object-size",
++          "default": null,
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "390",
++      "members": [
++        {
++          "name": "location",
++          "type": "266"
++        },
++        {
++          "name": "size",
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "391",
++      "members": [
++        {
++          "name": "file",
++          "type": "362"
++        },
++        {
++          "name": "size",
++          "type": "int"
++        },
++        {
++          "name": "preallocation",
++          "default": null,
++          "type": "463"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "392",
++      "members": [
++        {
++          "name": "file",
++          "type": "362"
++        },
++        {
++          "name": "size",
++          "type": "int"
++        },
++        {
++          "name": "log-size",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "block-size",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "subformat",
++          "default": null,
++          "type": "471"
++        },
++        {
++          "name": "block-state-zero",
++          "default": null,
++          "type": "bool"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "393",
++      "members": [
++        {
++          "name": "file",
++          "type": "362"
++        },
++        {
++          "name": "size",
++          "type": "int"
++        },
++        {
++          "name": "extents",
++          "default": null,
++          "type": "[362]"
++        },
++        {
++          "name": "subformat",
++          "default": null,
++          "type": "472"
++        },
++        {
++          "name": "backing-file",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "adapter-type",
++          "default": null,
++          "type": "473"
++        },
++        {
++          "name": "hwversion",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "zeroed-grain",
++          "default": null,
++          "type": "bool"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "394",
++      "members": [
++        {
++          "name": "file",
++          "type": "362"
++        },
++        {
++          "name": "size",
++          "type": "int"
++        },
++        {
++          "name": "subformat",
++          "default": null,
++          "type": "474"
++        },
++        {
++          "name": "force-size",
++          "default": null,
++          "type": "bool"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "null",
++      "json-type": "null",
++      "meta-type": "builtin"
++    },
++    {
++      "name": "395",
++      "meta-type": "enum",
++      "values": [
++        "inet",
++        "unix",
++        "vsock",
++        "fd"
++      ]
++    },
++    {
++      "name": "396",
++      "members": [
++        {
++          "name": "data",
++          "type": "378"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "397",
++      "members": [
++        {
++          "name": "data",
++          "type": "423"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "398",
++      "members": [
++        {
++          "name": "data",
++          "type": "424"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "399",
++      "members": [
++        {
++          "name": "data",
++          "type": "425"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "400",
++      "meta-type": "enum",
++      "values": [
++        "file",
++        "serial",
++        "parallel",
++        "pipe",
++        "socket",
++        "udp",
++        "pty",
++        "null",
++        "mux",
++        "msmouse",
++        "wctablet",
++        "braille",
++        "testdev",
++        "stdio",
++        "console",
++        "spicevmc",
++        "spiceport",
++        "vc",
++        "ringbuf",
++        "memory"
++      ]
++    },
++    {
++      "name": "401",
++      "members": [
++        {
++          "name": "data",
++          "type": "475"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "402",
++      "members": [
++        {
++          "name": "data",
++          "type": "476"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "403",
++      "members": [
++        {
++          "name": "data",
++          "type": "477"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "404",
++      "members": [
++        {
++          "name": "data",
++          "type": "478"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "405",
++      "members": [
++        {
++          "name": "data",
++          "type": "479"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "406",
++      "members": [
++        {
++          "name": "data",
++          "type": "480"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "407",
++      "members": [
++        {
++          "name": "data",
++          "type": "481"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "408",
++      "members": [
++        {
++          "name": "data",
++          "type": "482"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "409",
++      "members": [
++        {
++          "name": "data",
++          "type": "483"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "410",
++      "members": [
++        {
++          "name": "data",
++          "type": "484"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "411",
++      "members": [
++        {
++          "name": "data",
++          "type": "485"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "412",
++      "meta-type": "enum",
++      "values": [
++        "passthrough",
++        "emulator"
++      ]
++    },
++    {
++      "name": "413",
++      "members": [
++        {
++          "name": "data",
++          "type": "486"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "414",
++      "members": [
++        {
++          "name": "data",
++          "type": "487"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "415",
++      "meta-type": "enum",
++      "values": [
++        "number",
++        "qcode"
++      ]
++    },
++    {
++      "name": "416",
++      "members": [
++        {
++          "name": "data",
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "417",
++      "members": [
++        {
++          "name": "data",
++          "type": "488"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "418",
++      "meta-type": "enum",
++      "values": [
++        "key",
++        "btn",
++        "rel",
++        "abs"
++      ]
++    },
++    {
++      "name": "419",
++      "members": [
++        {
++          "name": "data",
++          "type": "489"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "420",
++      "members": [
++        {
++          "name": "data",
++          "type": "490"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "421",
++      "members": [
++        {
++          "name": "data",
++          "type": "491"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "422",
++      "meta-type": "enum",
++      "values": [
++        "inet",
++        "unix",
++        "vsock",
++        "fd"
++      ]
++    },
++    {
++      "name": "423",
++      "members": [
++        {
++          "name": "path",
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "424",
++      "members": [
++        {
++          "name": "cid",
++          "type": "str"
++        },
++        {
++          "name": "port",
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "425",
++      "members": [
++        {
++          "name": "str",
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "426",
++      "meta-type": "enum",
++      "values": [
++        "abort",
++        "block-dirty-bitmap-add",
++        "block-dirty-bitmap-clear",
++        "block-dirty-bitmap-enable",
++        "block-dirty-bitmap-disable",
++        "block-dirty-bitmap-merge",
++        "blockdev-backup",
++        "blockdev-snapshot",
++        "blockdev-snapshot-internal-sync",
++        "blockdev-snapshot-sync",
++        "drive-backup"
++      ]
++    },
++    {
++      "name": "427",
++      "members": [
++        {
++          "name": "data",
++          "type": "492"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "428",
++      "members": [
++        {
++          "name": "data",
++          "type": "31"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "429",
++      "members": [
++        {
++          "name": "data",
++          "type": "32"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "430",
++      "members": [
++        {
++          "name": "data",
++          "type": "33"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "431",
++      "members": [
++        {
++          "name": "data",
++          "type": "27"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "432",
++      "members": [
++        {
++          "name": "data",
++          "type": "23"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "433",
++      "members": [
++        {
++          "name": "data",
++          "type": "65"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "434",
++      "members": [
++        {
++          "name": "data",
++          "type": "22"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "435",
++      "members": [
++        {
++          "name": "data",
++          "type": "26"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "436",
++      "meta-type": "enum",
++      "values": [
++        "individual",
++        "grouped"
++      ]
++    },
++    {
++      "name": "437",
++      "meta-type": "enum",
++      "values": [
++        "string",
++        "number",
++        "int",
++        "boolean",
++        "null",
++        "object",
++        "array",
++        "value"
++      ]
++    },
++    {
++      "name": "[438]",
++      "element-type": "438",
++      "meta-type": "array"
++    },
++    {
++      "name": "438",
++      "members": [
++        {
++          "name": "name",
++          "type": "str"
++        },
++        {
++          "name": "type",
++          "type": "str"
++        },
++        {
++          "name": "default",
++          "default": null,
++          "type": "any"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "[439]",
++      "element-type": "439",
++      "meta-type": "array"
++    },
++    {
++      "name": "439",
++      "members": [
++        {
++          "name": "case",
++          "type": "str"
++        },
++        {
++          "name": "type",
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "[440]",
++      "element-type": "440",
++      "meta-type": "array"
++    },
++    {
++      "name": "440",
++      "members": [
++        {
++          "name": "type",
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "441",
++      "meta-type": "enum",
++      "values": [
++        "uninitialized",
++        "stopped",
++        "check-stop",
++        "operating",
++        "load"
++      ]
++    },
++    {
++      "name": "442",
++      "members": [
++        {
++          "name": "desc",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "class",
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "443",
++      "members": [
++        {
++          "name": "device",
++          "type": "int"
++        },
++        {
++          "name": "vendor",
++          "type": "int"
++        },
++        {
++          "name": "subsystem",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "subsystem-vendor",
++          "default": null,
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "444",
++      "members": [
++        {
++          "name": "bus",
++          "type": "493"
++        },
++        {
++          "name": "devices",
++          "default": null,
++          "type": "[336]"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "[445]",
++      "element-type": "445",
++      "meta-type": "array"
++    },
++    {
++      "name": "445",
++      "members": [
++        {
++          "name": "bar",
++          "type": "int"
++        },
++        {
++          "name": "type",
++          "type": "str"
++        },
++        {
++          "name": "address",
++          "type": "int"
++        },
++        {
++          "name": "size",
++          "type": "int"
++        },
++        {
++          "name": "prefetch",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "mem_type_64",
++          "default": null,
++          "type": "bool"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "446",
++      "meta-type": "enum",
++      "values": [
++        "string",
++        "boolean",
++        "number",
++        "size"
++      ]
++    },
++    {
++      "name": "447",
++      "members": [
++        {
++          "name": "id",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "addr",
++          "type": "int"
++        },
++        {
++          "name": "size",
++          "type": "int"
++        },
++        {
++          "name": "slot",
++          "type": "int"
++        },
++        {
++          "name": "node",
++          "type": "int"
++        },
++        {
++          "name": "memdev",
++          "type": "str"
++        },
++        {
++          "name": "hotplugged",
++          "type": "bool"
++        },
++        {
++          "name": "hotpluggable",
++          "type": "bool"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "448",
++      "meta-type": "enum",
++      "values": [
++        "unknown",
++        "disabled-wait",
++        "extint-loop",
++        "pgmint-loop",
++        "opint-loop"
++      ]
++    },
++    {
++      "name": "449",
++      "meta-type": "enum",
++      "values": [
++        "qcow2",
++        "vmdk",
++        "luks"
++      ]
++    },
++    {
++      "name": "450",
++      "members": [
++        {
++          "name": "data",
++          "type": "494"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "451",
++      "members": [
++        {
++          "name": "data",
++          "type": "495"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "452",
++      "members": [
++        {
++          "name": "data",
++          "type": "496"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "453",
++      "meta-type": "enum",
++      "values": [
++        "l1_update",
++        "l1_grow_alloc_table",
++        "l1_grow_write_table",
++        "l1_grow_activate_table",
++        "l2_load",
++        "l2_update",
++        "l2_update_compressed",
++        "l2_alloc_cow_read",
++        "l2_alloc_write",
++        "read_aio",
++        "read_backing_aio",
++        "read_compressed",
++        "write_aio",
++        "write_compressed",
++        "vmstate_load",
++        "vmstate_save",
++        "cow_read",
++        "cow_write",
++        "reftable_load",
++        "reftable_grow",
++        "reftable_update",
++        "refblock_load",
++        "refblock_update",
++        "refblock_update_part",
++        "refblock_alloc",
++        "refblock_alloc_hookup",
++        "refblock_alloc_write",
++        "refblock_alloc_write_blocks",
++        "refblock_alloc_write_table",
++        "refblock_alloc_switch_table",
++        "cluster_alloc",
++        "cluster_alloc_bytes",
++        "cluster_free",
++        "flush_to_os",
++        "flush_to_disk",
++        "pwritev_rmw_head",
++        "pwritev_rmw_after_head",
++        "pwritev_rmw_tail",
++        "pwritev_rmw_after_tail",
++        "pwritev",
++        "pwritev_zero",
++        "pwritev_done",
++        "empty_image_prepare",
++        "l1_shrink_write_table",
++        "l1_shrink_free_l2_clusters",
++        "cor_write",
++        "cluster_alloc_space"
++      ]
++    },
++    {
++      "name": "454",
++      "meta-type": "enum",
++      "values": [
++        "inet"
++      ]
++    },
++    {
++      "name": "455",
++      "members": [
++        {
++          "name": "template",
++          "default": null,
++          "type": "456"
++        },
++        {
++          "name": "main-header",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "active-l1",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "active-l2",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "refcount-table",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "refcount-block",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "snapshot-table",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "inactive-l1",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "inactive-l2",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "bitmap-directory",
++          "default": null,
++          "type": "bool"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "456",
++      "meta-type": "enum",
++      "values": [
++        "none",
++        "constant",
++        "cached",
++        "all"
++      ]
++    },
++    {
++      "name": "457",
++      "meta-type": "enum",
++      "values": [
++        "aes",
++        "luks"
++      ]
++    },
++    {
++      "name": "458",
++      "members": [
++        {
++          "name": "key-secret",
++          "default": null,
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "459",
++      "members": [
++        {
++          "name": "key-secret",
++          "default": null,
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "460",
++      "meta-type": "enum",
++      "values": [
++        "aes"
++      ]
++    },
++    {
++      "name": "461",
++      "meta-type": "enum",
++      "values": [
++        "none",
++        "hash",
++        "known_hosts"
++      ]
++    },
++    {
++      "name": "462",
++      "members": [
++        {
++          "name": "type",
++          "type": "497"
++        },
++        {
++          "name": "hash",
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "463",
++      "meta-type": "enum",
++      "values": [
++        "off",
++        "metadata",
++        "falloc",
++        "full"
++      ]
++    },
++    {
++      "name": "464",
++      "meta-type": "enum",
++      "values": [
++        "aes-128",
++        "aes-192",
++        "aes-256",
++        "des-rfb",
++        "3des",
++        "cast5-128",
++        "serpent-128",
++        "serpent-192",
++        "serpent-256",
++        "twofish-128",
++        "twofish-192",
++        "twofish-256"
++      ]
++    },
++    {
++      "name": "465",
++      "meta-type": "enum",
++      "values": [
++        "ecb",
++        "cbc",
++        "xts",
++        "ctr"
++      ]
++    },
++    {
++      "name": "466",
++      "meta-type": "enum",
++      "values": [
++        "plain",
++        "plain64",
++        "essiv"
++      ]
++    },
++    {
++      "name": "467",
++      "meta-type": "enum",
++      "values": [
++        "md5",
++        "sha1",
++        "sha224",
++        "sha256",
++        "sha384",
++        "sha512",
++        "ripemd160"
++      ]
++    },
++    {
++      "name": "468",
++      "tag": "format",
++      "variants": [
++        {
++          "case": "qcow",
++          "type": "458"
++        },
++        {
++          "case": "luks",
++          "type": "499"
++        }
++      ],
++      "members": [
++        {
++          "name": "format",
++          "type": "498"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "469",
++      "meta-type": "enum",
++      "values": [
++        "v2",
++        "v3"
++      ]
++    },
++    {
++      "name": "470",
++      "tag": "type",
++      "variants": [
++        {
++          "case": "full",
++          "type": "501"
++        },
++        {
++          "case": "erasure-coded",
++          "type": "502"
++        }
++      ],
++      "members": [
++        {
++          "name": "type",
++          "type": "500"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "471",
++      "meta-type": "enum",
++      "values": [
++        "dynamic",
++        "fixed"
++      ]
++    },
++    {
++      "name": "472",
++      "meta-type": "enum",
++      "values": [
++        "monolithicSparse",
++        "monolithicFlat",
++        "twoGbMaxExtentSparse",
++        "twoGbMaxExtentFlat",
++        "streamOptimized"
++      ]
++    },
++    {
++      "name": "473",
++      "meta-type": "enum",
++      "values": [
++        "ide",
++        "buslogic",
++        "lsilogic",
++        "legacyESX"
++      ]
++    },
++    {
++      "name": "474",
++      "meta-type": "enum",
++      "values": [
++        "dynamic",
++        "fixed"
++      ]
++    },
++    {
++      "name": "475",
++      "members": [
++        {
++          "name": "logfile",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "logappend",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "in",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "out",
++          "type": "str"
++        },
++        {
++          "name": "append",
++          "default": null,
++          "type": "bool"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "476",
++      "members": [
++        {
++          "name": "logfile",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "logappend",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "device",
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "477",
++      "members": [
++        {
++          "name": "logfile",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "logappend",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "addr",
++          "type": "275"
++        },
++        {
++          "name": "tls-creds",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "tls-authz",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "server",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "wait",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "nodelay",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "telnet",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "tn3270",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "websocket",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "reconnect",
++          "default": null,
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "478",
++      "members": [
++        {
++          "name": "logfile",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "logappend",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "remote",
++          "type": "275"
++        },
++        {
++          "name": "local",
++          "default": null,
++          "type": "275"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "479",
++      "members": [
++        {
++          "name": "logfile",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "logappend",
++          "default": null,
++          "type": "bool"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "480",
++      "members": [
++        {
++          "name": "logfile",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "logappend",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "chardev",
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "481",
++      "members": [
++        {
++          "name": "logfile",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "logappend",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "signal",
++          "default": null,
++          "type": "bool"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "482",
++      "members": [
++        {
++          "name": "logfile",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "logappend",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "type",
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "483",
++      "members": [
++        {
++          "name": "logfile",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "logappend",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "fqdn",
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "484",
++      "members": [
++        {
++          "name": "logfile",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "logappend",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "width",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "height",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "cols",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "rows",
++          "default": null,
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "485",
++      "members": [
++        {
++          "name": "logfile",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "logappend",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "size",
++          "default": null,
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "486",
++      "members": [
++        {
++          "name": "path",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "cancel-path",
++          "default": null,
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "487",
++      "members": [
++        {
++          "name": "chardev",
++          "type": "str"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "488",
++      "meta-type": "enum",
++      "values": [
++        "unmapped",
++        "shift",
++        "shift_r",
++        "alt",
++        "alt_r",
++        "ctrl",
++        "ctrl_r",
++        "menu",
++        "esc",
++        "1",
++        "2",
++        "3",
++        "4",
++        "5",
++        "6",
++        "7",
++        "8",
++        "9",
++        "0",
++        "minus",
++        "equal",
++        "backspace",
++        "tab",
++        "q",
++        "w",
++        "e",
++        "r",
++        "t",
++        "y",
++        "u",
++        "i",
++        "o",
++        "p",
++        "bracket_left",
++        "bracket_right",
++        "ret",
++        "a",
++        "s",
++        "d",
++        "f",
++        "g",
++        "h",
++        "j",
++        "k",
++        "l",
++        "semicolon",
++        "apostrophe",
++        "grave_accent",
++        "backslash",
++        "z",
++        "x",
++        "c",
++        "v",
++        "b",
++        "n",
++        "m",
++        "comma",
++        "dot",
++        "slash",
++        "asterisk",
++        "spc",
++        "caps_lock",
++        "f1",
++        "f2",
++        "f3",
++        "f4",
++        "f5",
++        "f6",
++        "f7",
++        "f8",
++        "f9",
++        "f10",
++        "num_lock",
++        "scroll_lock",
++        "kp_divide",
++        "kp_multiply",
++        "kp_subtract",
++        "kp_add",
++        "kp_enter",
++        "kp_decimal",
++        "sysrq",
++        "kp_0",
++        "kp_1",
++        "kp_2",
++        "kp_3",
++        "kp_4",
++        "kp_5",
++        "kp_6",
++        "kp_7",
++        "kp_8",
++        "kp_9",
++        "less",
++        "f11",
++        "f12",
++        "print",
++        "home",
++        "pgup",
++        "pgdn",
++        "end",
++        "left",
++        "up",
++        "down",
++        "right",
++        "insert",
++        "delete",
++        "stop",
++        "again",
++        "props",
++        "undo",
++        "front",
++        "copy",
++        "open",
++        "paste",
++        "find",
++        "cut",
++        "lf",
++        "help",
++        "meta_l",
++        "meta_r",
++        "compose",
++        "pause",
++        "ro",
++        "hiragana",
++        "henkan",
++        "yen",
++        "muhenkan",
++        "katakanahiragana",
++        "kp_comma",
++        "kp_equals",
++        "power",
++        "sleep",
++        "wake",
++        "audionext",
++        "audioprev",
++        "audiostop",
++        "audioplay",
++        "audiomute",
++        "volumeup",
++        "volumedown",
++        "mediaselect",
++        "mail",
++        "calculator",
++        "computer",
++        "ac_home",
++        "ac_back",
++        "ac_forward",
++        "ac_refresh",
++        "ac_bookmarks"
++      ]
++    },
++    {
++      "name": "489",
++      "members": [
++        {
++          "name": "key",
++          "type": "298"
++        },
++        {
++          "name": "down",
++          "type": "bool"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "490",
++      "members": [
++        {
++          "name": "button",
++          "type": "503"
++        },
++        {
++          "name": "down",
++          "type": "bool"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "491",
++      "members": [
++        {
++          "name": "axis",
++          "type": "504"
++        },
++        {
++          "name": "value",
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "492",
++      "members": [
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "493",
++      "members": [
++        {
++          "name": "number",
++          "type": "int"
++        },
++        {
++          "name": "secondary",
++          "type": "int"
++        },
++        {
++          "name": "subordinate",
++          "type": "int"
++        },
++        {
++          "name": "io_range",
++          "type": "505"
++        },
++        {
++          "name": "memory_range",
++          "type": "505"
++        },
++        {
++          "name": "prefetchable_range",
++          "type": "505"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "494",
++      "members": [
++        {
++          "name": "compat",
++          "type": "str"
++        },
++        {
++          "name": "data-file",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "data-file-raw",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "lazy-refcounts",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "corrupt",
++          "default": null,
++          "type": "bool"
++        },
++        {
++          "name": "refcount-bits",
++          "type": "int"
++        },
++        {
++          "name": "encrypt",
++          "default": null,
++          "type": "506"
++        },
++        {
++          "name": "bitmaps",
++          "default": null,
++          "type": "[507]"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "495",
++      "members": [
++        {
++          "name": "create-type",
++          "type": "str"
++        },
++        {
++          "name": "cid",
++          "type": "int"
++        },
++        {
++          "name": "parent-cid",
++          "type": "int"
++        },
++        {
++          "name": "extents",
++          "type": "[233]"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "496",
++      "members": [
++        {
++          "name": "cipher-alg",
++          "type": "464"
++        },
++        {
++          "name": "cipher-mode",
++          "type": "465"
++        },
++        {
++          "name": "ivgen-alg",
++          "type": "466"
++        },
++        {
++          "name": "ivgen-hash-alg",
++          "default": null,
++          "type": "467"
++        },
++        {
++          "name": "hash-alg",
++          "type": "467"
++        },
++        {
++          "name": "payload-offset",
++          "type": "int"
++        },
++        {
++          "name": "master-key-iters",
++          "type": "int"
++        },
++        {
++          "name": "uuid",
++          "type": "str"
++        },
++        {
++          "name": "slots",
++          "type": "[508]"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "497",
++      "meta-type": "enum",
++      "values": [
++        "md5",
++        "sha1"
++      ]
++    },
++    {
++      "name": "498",
++      "meta-type": "enum",
++      "values": [
++        "qcow",
++        "luks"
++      ]
++    },
++    {
++      "name": "499",
++      "members": [
++        {
++          "name": "key-secret",
++          "default": null,
++          "type": "str"
++        },
++        {
++          "name": "cipher-alg",
++          "default": null,
++          "type": "464"
++        },
++        {
++          "name": "cipher-mode",
++          "default": null,
++          "type": "465"
++        },
++        {
++          "name": "ivgen-alg",
++          "default": null,
++          "type": "466"
++        },
++        {
++          "name": "ivgen-hash-alg",
++          "default": null,
++          "type": "467"
++        },
++        {
++          "name": "hash-alg",
++          "default": null,
++          "type": "467"
++        },
++        {
++          "name": "iter-time",
++          "default": null,
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "500",
++      "meta-type": "enum",
++      "values": [
++        "full",
++        "erasure-coded"
++      ]
++    },
++    {
++      "name": "501",
++      "members": [
++        {
++          "name": "copies",
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "502",
++      "members": [
++        {
++          "name": "data-strips",
++          "type": "int"
++        },
++        {
++          "name": "parity-strips",
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "503",
++      "meta-type": "enum",
++      "values": [
++        "left",
++        "middle",
++        "right",
++        "wheel-up",
++        "wheel-down",
++        "side",
++        "extra"
++      ]
++    },
++    {
++      "name": "504",
++      "meta-type": "enum",
++      "values": [
++        "x",
++        "y"
++      ]
++    },
++    {
++      "name": "505",
++      "members": [
++        {
++          "name": "base",
++          "type": "int"
++        },
++        {
++          "name": "limit",
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "506",
++      "tag": "format",
++      "variants": [
++        {
++          "case": "luks",
++          "type": "496"
++        },
++        {
++          "case": "aes",
++          "type": "0"
++        }
++      ],
++      "members": [
++        {
++          "name": "format",
++          "type": "457"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "[507]",
++      "element-type": "507",
++      "meta-type": "array"
++    },
++    {
++      "name": "507",
++      "members": [
++        {
++          "name": "name",
++          "type": "str"
++        },
++        {
++          "name": "granularity",
++          "type": "int"
++        },
++        {
++          "name": "flags",
++          "type": "[509]"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "[233]",
++      "element-type": "233",
++      "meta-type": "array"
++    },
++    {
++      "name": "[508]",
++      "element-type": "508",
++      "meta-type": "array"
++    },
++    {
++      "name": "508",
++      "members": [
++        {
++          "name": "active",
++          "type": "bool"
++        },
++        {
++          "name": "iters",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "stripes",
++          "default": null,
++          "type": "int"
++        },
++        {
++          "name": "key-offset",
++          "type": "int"
++        }
++      ],
++      "meta-type": "object"
++    },
++    {
++      "name": "[509]",
++      "element-type": "509",
++      "meta-type": "array"
++    },
++    {
++      "name": "509",
++      "meta-type": "enum",
++      "values": [
++        "in-use",
++        "auto"
++      ]
++    }
++  ],
++  "id": "libvirt-49"
++}
++
++{
++  "execute": "query-cpu-model-expansion",
++  "arguments": {
++    "type": "static",
++    "model": {
++      "name": "host"
++    }
++  },
++  "id": "libvirt-50"
++}
++
++{
++  "return": {
++    "model": {
++      "name": "base",
++      "props": {
++        "cmov": true,
++        "ia64": false,
++        "ssb-no": false,
++        "aes": true,
++        "mmx": true,
++        "rdpid": false,
++        "arat": true,
++        "gfni": false,
++        "ibrs-all": false,
++        "pause-filter": false,
++        "xsavec": true,
++        "intel-pt": false,
++        "kvm-asyncpf": true,
++        "perfctr-core": false,
++        "mpx": true,
++        "pbe": false,
++        "avx512cd": false,
++        "decodeassists": false,
++        "sse4.1": true,
++        "family": 6,
++        "wbnoinvd": false,
++        "avx512f": false,
++        "msr": true,
++        "mce": true,
++        "mca": true,
++        "xcrypt": false,
++        "min-level": 13,
++        "xgetbv1": true,
++        "cid": false,
++        "ds": false,
++        "fxsr": true,
++        "xsaveopt": true,
++        "xtpr": false,
++        "avx512vl": false,
++        "avx512-vpopcntdq": false,
++        "phe": false,
++        "extapic": false,
++        "3dnowprefetch": true,
++        "avx512vbmi2": false,
++        "cr8legacy": false,
++        "stibp": false,
++        "xcrypt-en": false,
++        "pn": false,
++        "rsba": false,
++        "dca": false,
++        "vendor": "GenuineIntel",
++        "pku": false,
++        "smx": false,
++        "cmp-legacy": false,
++        "avx512-4fmaps": false,
++        "vmcb-clean": false,
++        "hle": true,
++        "3dnowext": false,
++        "amd-no-ssb": false,
++        "npt": false,
++        "rdctl-no": false,
++        "clwb": false,
++        "lbrv": false,
++        "adx": true,
++        "ss": true,
++        "pni": true,
++        "svm-lock": false,
++        "smep": true,
++        "smap": true,
++        "pfthreshold": false,
++        "x2apic": true,
++        "avx512vbmi": false,
++        "avx512vnni": false,
++        "flushbyasid": false,
++        "f16c": true,
++        "ace2-en": false,
++        "pae": true,
++        "pat": true,
++        "sse": true,
++        "phe-en": false,
++        "kvm-nopiodelay": true,
++        "tm": false,
++        "kvmclock-stable-bit": true,
++        "hypervisor": true,
++        "mds-no": false,
++        "pcommit": false,
++        "syscall": true,
++        "avx512dq": false,
++        "svm": false,
++        "invtsc": false,
++        "sse2": true,
++        "ssbd": false,
++        "est": false,
++        "avx512ifma": false,
++        "tm2": false,
++        "kvm-pv-eoi": true,
++        "kvm-pv-ipi": true,
++        "cx8": true,
++        "cldemote": false,
++        "kvm-mmu": false,
++        "sse4.2": true,
++        "pge": true,
++        "avx512bitalg": false,
++        "pdcm": false,
++        "model": 94,
++        "movbe": true,
++        "nrip-save": false,
++        "ssse3": true,
++        "sse4a": false,
++        "invpcid": true,
++        "pdpe1gb": true,
++        "tsc-deadline": true,
++        "skip-l1dfl-vmentry": true,
++        "fma": true,
++        "cx16": true,
++        "de": true,
++        "stepping": 3,
++        "xsave": true,
++        "clflush": true,
++        "skinit": false,
++        "tsc": true,
++        "tce": false,
++        "fpu": true,
++        "ds-cpl": false,
++        "ibs": false,
++        "fma4": false,
++        "la57": false,
++        "osvw": false,
++        "apic": true,
++        "pmm": false,
++        "spec-ctrl": false,
++        "tsc-adjust": true,
++        "kvm-steal-time": true,
++        "kvmclock": true,
++        "lwp": false,
++        "amd-ssbd": false,
++        "xop": false,
++        "ibpb": false,
++        "avx": true,
++        "movdiri": false,
++        "acpi": false,
++        "avx512bw": false,
++        "ace2": false,
++        "fsgsbase": true,
++        "ht": false,
++        "nx": true,
++        "pclmulqdq": true,
++        "mmxext": false,
++        "popcnt": true,
++        "vaes": false,
++        "movdir64b": false,
++        "xsaves": true,
++        "lm": true,
++        "umip": true,
++        "pse": true,
++        "avx2": true,
++        "sep": true,
++        "virt-ssbd": false,
++        "nodeid-msr": false,
++        "md-clear": false,
++        "misalignsse": false,
++        "min-xlevel": 2147483656,
++        "bmi1": true,
++        "bmi2": true,
++        "kvm-pv-unhalt": true,
++        "tsc-scale": false,
++        "topoext": false,
++        "clflushopt": true,
++        "monitor": false,
++        "avx512er": false,
++        "pmm-en": false,
++        "pcid": true,
++        "arch-capabilities": true,
++        "3dnow": false,
++        "erms": true,
++        "lahf-lm": true,
++        "vpclmulqdq": false,
++        "fxsr-opt": false,
++        "xstore": false,
++        "rtm": true,
++        "kvm-hint-dedicated": false,
++        "lmce": true,
++        "perfctr-nb": false,
++        "rdrand": true,
++        "rdseed": true,
++        "avx512-4vnniw": false,
++        "vme": true,
++        "vmx": true,
++        "dtes64": false,
++        "mtrr": true,
++        "rdtscp": true,
++        "pse36": true,
++        "kvm-pv-tlb-flush": true,
++        "tbm": false,
++        "wdt": false,
++        "model-id": "Intel(R) Xeon(R) CPU E3-1245 v5 @ 3.50GHz",
++        "sha-ni": false,
++        "abm": true,
++        "avx512pf": false,
++        "xstore-en": false
++      }
++    }
++  },
++  "id": "libvirt-50"
++}
++
++{
++  "execute": "query-cpu-model-expansion",
++  "arguments": {
++    "type": "full",
++    "model": {
++      "name": "base",
++      "props": {
++        "cmov": true,
++        "ia64": false,
++        "ssb-no": false,
++        "aes": true,
++        "mmx": true,
++        "rdpid": false,
++        "arat": true,
++        "gfni": false,
++        "ibrs-all": false,
++        "pause-filter": false,
++        "xsavec": true,
++        "intel-pt": false,
++        "kvm-asyncpf": true,
++        "perfctr-core": false,
++        "mpx": true,
++        "pbe": false,
++        "avx512cd": false,
++        "decodeassists": false,
++        "sse4.1": true,
++        "family": 6,
++        "wbnoinvd": false,
++        "avx512f": false,
++        "msr": true,
++        "mce": true,
++        "mca": true,
++        "xcrypt": false,
++        "min-level": 13,
++        "xgetbv1": true,
++        "cid": false,
++        "ds": false,
++        "fxsr": true,
++        "xsaveopt": true,
++        "xtpr": false,
++        "avx512vl": false,
++        "avx512-vpopcntdq": false,
++        "phe": false,
++        "extapic": false,
++        "3dnowprefetch": true,
++        "avx512vbmi2": false,
++        "cr8legacy": false,
++        "stibp": false,
++        "xcrypt-en": false,
++        "pn": false,
++        "rsba": false,
++        "dca": false,
++        "vendor": "GenuineIntel",
++        "pku": false,
++        "smx": false,
++        "cmp-legacy": false,
++        "avx512-4fmaps": false,
++        "vmcb-clean": false,
++        "hle": true,
++        "3dnowext": false,
++        "amd-no-ssb": false,
++        "npt": false,
++        "rdctl-no": false,
++        "clwb": false,
++        "lbrv": false,
++        "adx": true,
++        "ss": true,
++        "pni": true,
++        "svm-lock": false,
++        "smep": true,
++        "smap": true,
++        "pfthreshold": false,
++        "x2apic": true,
++        "avx512vbmi": false,
++        "avx512vnni": false,
++        "flushbyasid": false,
++        "f16c": true,
++        "ace2-en": false,
++        "pae": true,
++        "pat": true,
++        "sse": true,
++        "phe-en": false,
++        "kvm-nopiodelay": true,
++        "tm": false,
++        "kvmclock-stable-bit": true,
++        "hypervisor": true,
++        "mds-no": false,
++        "pcommit": false,
++        "syscall": true,
++        "avx512dq": false,
++        "svm": false,
++        "invtsc": false,
++        "sse2": true,
++        "ssbd": false,
++        "est": false,
++        "avx512ifma": false,
++        "tm2": false,
++        "kvm-pv-eoi": true,
++        "kvm-pv-ipi": true,
++        "cx8": true,
++        "cldemote": false,
++        "kvm-mmu": false,
++        "sse4.2": true,
++        "pge": true,
++        "avx512bitalg": false,
++        "pdcm": false,
++        "model": 94,
++        "movbe": true,
++        "nrip-save": false,
++        "ssse3": true,
++        "sse4a": false,
++        "invpcid": true,
++        "pdpe1gb": true,
++        "tsc-deadline": true,
++        "skip-l1dfl-vmentry": true,
++        "fma": true,
++        "cx16": true,
++        "de": true,
++        "stepping": 3,
++        "xsave": true,
++        "clflush": true,
++        "skinit": false,
++        "tsc": true,
++        "tce": false,
++        "fpu": true,
++        "ds-cpl": false,
++        "ibs": false,
++        "fma4": false,
++        "la57": false,
++        "osvw": false,
++        "apic": true,
++        "pmm": false,
++        "spec-ctrl": false,
++        "tsc-adjust": true,
++        "kvm-steal-time": true,
++        "kvmclock": true,
++        "lwp": false,
++        "amd-ssbd": false,
++        "xop": false,
++        "ibpb": false,
++        "avx": true,
++        "movdiri": false,
++        "acpi": false,
++        "avx512bw": false,
++        "ace2": false,
++        "fsgsbase": true,
++        "ht": false,
++        "nx": true,
++        "pclmulqdq": true,
++        "mmxext": false,
++        "popcnt": true,
++        "vaes": false,
++        "movdir64b": false,
++        "xsaves": true,
++        "lm": true,
++        "umip": true,
++        "pse": true,
++        "avx2": true,
++        "sep": true,
++        "virt-ssbd": false,
++        "nodeid-msr": false,
++        "md-clear": false,
++        "misalignsse": false,
++        "min-xlevel": 2147483656,
++        "bmi1": true,
++        "bmi2": true,
++        "kvm-pv-unhalt": true,
++        "tsc-scale": false,
++        "topoext": false,
++        "clflushopt": true,
++        "monitor": false,
++        "avx512er": false,
++        "pmm-en": false,
++        "pcid": true,
++        "arch-capabilities": true,
++        "3dnow": false,
++        "erms": true,
++        "lahf-lm": true,
++        "vpclmulqdq": false,
++        "fxsr-opt": false,
++        "xstore": false,
++        "rtm": true,
++        "kvm-hint-dedicated": false,
++        "lmce": true,
++        "perfctr-nb": false,
++        "rdrand": true,
++        "rdseed": true,
++        "avx512-4vnniw": false,
++        "vme": true,
++        "vmx": true,
++        "dtes64": false,
++        "mtrr": true,
++        "rdtscp": true,
++        "pse36": true,
++        "kvm-pv-tlb-flush": true,
++        "tbm": false,
++        "wdt": false,
++        "model-id": "Intel(R) Xeon(R) CPU E3-1245 v5 @ 3.50GHz",
++        "sha-ni": false,
++        "abm": true,
++        "avx512pf": false,
++        "xstore-en": false
++      }
++    }
++  },
++  "id": "libvirt-51"
++}
++
++{
++  "return": {
++    "model": {
++      "name": "base",
++      "props": {
++        "phys-bits": 0,
++        "core-id": -1,
++        "xlevel": 2147483656,
++        "cmov": true,
++        "ia64": false,
++        "ssb-no": false,
++        "aes": true,
++        "mmx": true,
++        "rdpid": false,
++        "arat": true,
++        "gfni": false,
++        "ibrs-all": false,
++        "pause-filter": false,
++        "xsavec": true,
++        "intel-pt": false,
++        "hv-frequencies": false,
++        "tsc-frequency": 0,
++        "xd": true,
++        "x-intel-pt-auto-level": true,
++        "hv-vendor-id": "",
++        "kvm-asyncpf": true,
++        "kvm_asyncpf": true,
++        "perfctr_core": false,
++        "perfctr-core": false,
++        "mpx": true,
++        "pbe": false,
++        "decodeassists": false,
++        "avx512cd": false,
++        "sse4_1": true,
++        "sse4.1": true,
++        "sse4-1": true,
++        "family": 6,
++        "legacy-cache": true,
++        "host-phys-bits-limit": 0,
++        "vmware-cpuid-freq": true,
++        "wbnoinvd": false,
++        "avx512f": false,
++        "msr": true,
++        "mce": true,
++        "mca": true,
++        "hv-runtime": false,
++        "xcrypt": false,
++        "thread-id": -1,
++        "min-level": 13,
++        "xgetbv1": true,
++        "cid": false,
++        "hv-relaxed": false,
++        "hv-crash": false,
++        "ds": false,
++        "fxsr": true,
++        "xsaveopt": true,
++        "xtpr": false,
++        "hv-evmcs": false,
++        "avx512vl": false,
++        "avx512-vpopcntdq": false,
++        "phe": false,
++        "extapic": false,
++        "3dnowprefetch": true,
++        "avx512vbmi2": false,
++        "cr8legacy": false,
++        "stibp": false,
++        "cpuid-0xb": true,
++        "xcrypt-en": false,
++        "kvm_pv_eoi": true,
++        "apic-id": 4294967295,
++        "rsba": false,
++        "pn": false,
++        "dca": false,
++        "vendor": "GenuineIntel",
++        "hv-ipi": false,
++        "pku": false,
++        "smx": false,
++        "cmp_legacy": false,
++        "cmp-legacy": false,
++        "node-id": -1,
++        "avx512-4fmaps": false,
++        "vmcb_clean": false,
++        "vmcb-clean": false,
++        "3dnowext": false,
++        "amd-no-ssb": false,
++        "hle": true,
++        "npt": false,
++        "rdctl-no": false,
++        "memory": "/machine/unattached/system[0]",
++        "clwb": false,
++        "lbrv": false,
++        "adx": true,
++        "ss": true,
++        "pni": true,
++        "svm_lock": false,
++        "svm-lock": false,
++        "pfthreshold": false,
++        "smep": true,
++        "smap": true,
++        "x2apic": true,
++        "avx512vbmi": false,
++        "avx512vnni": false,
++        "hv-stimer": false,
++        "x-hv-synic-kvm-only": false,
++        "i64": true,
++        "flushbyasid": false,
++        "f16c": true,
++        "ace2-en": false,
++        "pat": true,
++        "pae": true,
++        "sse": true,
++        "phe-en": false,
++        "kvm_nopiodelay": true,
++        "kvm-nopiodelay": true,
++        "tm": false,
++        "kvmclock-stable-bit": true,
++        "hypervisor": true,
++        "socket-id": -1,
++        "mds-no": false,
++        "pcommit": false,
++        "syscall": true,
++        "level": 13,
++        "avx512dq": false,
++        "x-migrate-smi-count": true,
++        "svm": false,
++        "full-cpuid-auto-level": true,
++        "hv-reset": false,
++        "invtsc": false,
++        "sse3": true,
++        "sse2": true,
++        "ssbd": false,
++        "est": false,
++        "avx512ifma": false,
++        "tm2": false,
++        "kvm-pv-ipi": true,
++        "kvm-pv-eoi": true,
++        "cx8": true,
++        "cldemote": false,
++        "hv-reenlightenment": false,
++        "kvm_mmu": false,
++        "kvm-mmu": false,
++        "sse4_2": true,
++        "sse4.2": true,
++        "sse4-2": true,
++        "pge": true,
++        "fill-mtrr-mask": true,
++        "avx512bitalg": false,
++        "nodeid_msr": false,
++        "pdcm": false,
++        "movbe": true,
++        "model": 94,
++        "nrip_save": false,
++        "nrip-save": false,
++        "kvm_pv_unhalt": true,
++        "ssse3": true,
++        "sse4a": false,
++        "invpcid": true,
++        "pdpe1gb": true,
++        "tsc-deadline": true,
++        "skip-l1dfl-vmentry": true,
++        "fma": true,
++        "cx16": true,
++        "de": true,
++        "enforce": false,
++        "stepping": 3,
++        "xsave": true,
++        "clflush": true,
++        "skinit": false,
++        "tsc": true,
++        "tce": false,
++        "fpu": true,
++        "ibs": false,
++        "ds_cpl": false,
++        "ds-cpl": false,
++        "host-phys-bits": false,
++        "fma4": false,
++        "la57": false,
++        "osvw": false,
++        "check": true,
++        "hv-spinlocks": -1,
++        "pmm": false,
++        "pmu": false,
++        "apic": true,
++        "spec-ctrl": false,
++        "min-xlevel2": 0,
++        "tsc-adjust": true,
++        "tsc_adjust": true,
++        "kvm-steal-time": true,
++        "kvm_steal_time": true,
++        "kvmclock": true,
++        "l3-cache": true,
++        "lwp": false,
++        "amd-ssbd": false,
++        "ibpb": false,
++        "xop": false,
++        "avx": true,
++        "movdiri": false,
++        "ace2": false,
++        "avx512bw": false,
++        "acpi": false,
++        "hv-vapic": false,
++        "fsgsbase": true,
++        "ht": false,
++        "nx": true,
++        "pclmulqdq": true,
++        "mmxext": false,
++        "vaes": false,
++        "popcnt": true,
++        "xsaves": true,
++        "movdir64b": false,
++        "tcg-cpuid": true,
++        "lm": true,
++        "umip": true,
++        "pse": true,
++        "avx2": true,
++        "sep": true,
++        "pclmuldq": true,
++        "virt-ssbd": false,
++        "x-hv-max-vps": -1,
++        "nodeid-msr": false,
++        "md-clear": false,
++        "kvm": true,
++        "misalignsse": false,
++        "min-xlevel": 2147483656,
++        "kvm-pv-unhalt": true,
++        "bmi2": true,
++        "bmi1": true,
++        "realized": false,
++        "tsc_scale": false,
++        "tsc-scale": false,
++        "topoext": false,
++        "hv-vpindex": false,
++        "xlevel2": 0,
++        "clflushopt": true,
++        "kvm-no-smi-migration": false,
++        "monitor": false,
++        "avx512er": false,
++        "pmm-en": false,
++        "pcid": true,
++        "arch-capabilities": true,
++        "3dnow": false,
++        "erms": true,
++        "lahf-lm": true,
++        "lahf_lm": true,
++        "vpclmulqdq": false,
++        "fxsr-opt": false,
++        "hv-synic": false,
++        "xstore": false,
++        "fxsr_opt": false,
++        "kvm-hint-dedicated": false,
++        "rtm": true,
++        "lmce": true,
++        "hv-time": false,
++        "perfctr-nb": false,
++        "perfctr_nb": false,
++        "ffxsr": false,
++        "hv-tlbflush": false,
++        "rdrand": true,
++        "rdseed": true,
++        "avx512-4vnniw": false,
++        "vmx": true,
++        "vme": true,
++        "dtes64": false,
++        "mtrr": true,
++        "rdtscp": true,
++        "pse36": true,
++        "kvm-pv-tlb-flush": true,
++        "tbm": false,
++        "wdt": false,
++        "pause_filter": false,
++        "sha-ni": false,
++        "model-id": "Intel(R) Xeon(R) CPU E3-1245 v5 @ 3.50GHz",
++        "abm": true,
++        "avx512pf": false,
++        "xstore-en": false
++      }
++    }
++  },
++  "id": "libvirt-51"
++}
++
++{
++  "execute": "query-cpu-model-expansion",
++  "arguments": {
++    "type": "static",
++    "model": {
++      "name": "host",
++      "props": {
++        "migratable": false
++      }
++    }
++  },
++  "id": "libvirt-52"
++}
++
++{
++  "return": {
++    "model": {
++      "name": "base",
++      "props": {
++        "cmov": true,
++        "ia64": false,
++        "ssb-no": false,
++        "aes": true,
++        "mmx": true,
++        "rdpid": false,
++        "arat": true,
++        "gfni": false,
++        "ibrs-all": false,
++        "pause-filter": false,
++        "xsavec": true,
++        "intel-pt": false,
++        "kvm-asyncpf": true,
++        "perfctr-core": false,
++        "mpx": true,
++        "pbe": false,
++        "avx512cd": false,
++        "decodeassists": false,
++        "sse4.1": true,
++        "family": 6,
++        "wbnoinvd": false,
++        "avx512f": false,
++        "msr": true,
++        "mce": true,
++        "mca": true,
++        "xcrypt": false,
++        "min-level": 13,
++        "xgetbv1": true,
++        "cid": false,
++        "ds": false,
++        "fxsr": true,
++        "xsaveopt": true,
++        "xtpr": false,
++        "avx512vl": false,
++        "avx512-vpopcntdq": false,
++        "phe": false,
++        "extapic": false,
++        "3dnowprefetch": true,
++        "avx512vbmi2": false,
++        "cr8legacy": false,
++        "stibp": false,
++        "xcrypt-en": false,
++        "pn": false,
++        "rsba": false,
++        "dca": false,
++        "vendor": "GenuineIntel",
++        "pku": false,
++        "smx": false,
++        "cmp-legacy": false,
++        "avx512-4fmaps": false,
++        "vmcb-clean": false,
++        "hle": true,
++        "3dnowext": false,
++        "amd-no-ssb": false,
++        "npt": false,
++        "rdctl-no": false,
++        "clwb": false,
++        "lbrv": false,
++        "adx": true,
++        "ss": true,
++        "pni": true,
++        "svm-lock": false,
++        "smep": true,
++        "smap": true,
++        "pfthreshold": false,
++        "x2apic": true,
++        "avx512vbmi": false,
++        "avx512vnni": false,
++        "flushbyasid": false,
++        "f16c": true,
++        "ace2-en": false,
++        "pae": true,
++        "pat": true,
++        "sse": true,
++        "phe-en": false,
++        "kvm-nopiodelay": true,
++        "tm": false,
++        "kvmclock-stable-bit": true,
++        "hypervisor": true,
++        "mds-no": false,
++        "pcommit": false,
++        "syscall": true,
++        "avx512dq": false,
++        "svm": false,
++        "invtsc": false,
++        "sse2": true,
++        "ssbd": false,
++        "est": false,
++        "avx512ifma": false,
++        "tm2": false,
++        "kvm-pv-eoi": true,
++        "kvm-pv-ipi": true,
++        "cx8": true,
++        "cldemote": false,
++        "kvm-mmu": false,
++        "sse4.2": true,
++        "pge": true,
++        "avx512bitalg": false,
++        "pdcm": false,
++        "model": 94,
++        "movbe": true,
++        "nrip-save": false,
++        "ssse3": true,
++        "sse4a": false,
++        "invpcid": true,
++        "pdpe1gb": true,
++        "tsc-deadline": true,
++        "skip-l1dfl-vmentry": true,
++        "fma": true,
++        "cx16": true,
++        "de": true,
++        "stepping": 3,
++        "xsave": true,
++        "clflush": true,
++        "skinit": false,
++        "tsc": true,
++        "tce": false,
++        "fpu": true,
++        "ds-cpl": false,
++        "ibs": false,
++        "fma4": false,
++        "la57": false,
++        "osvw": false,
++        "apic": true,
++        "pmm": false,
++        "spec-ctrl": false,
++        "tsc-adjust": true,
++        "kvm-steal-time": true,
++        "kvmclock": true,
++        "lwp": false,
++        "amd-ssbd": false,
++        "xop": false,
++        "ibpb": false,
++        "avx": true,
++        "movdiri": false,
++        "acpi": false,
++        "avx512bw": false,
++        "ace2": false,
++        "fsgsbase": true,
++        "ht": false,
++        "nx": true,
++        "pclmulqdq": true,
++        "mmxext": false,
++        "popcnt": true,
++        "vaes": false,
++        "movdir64b": false,
++        "xsaves": true,
++        "lm": true,
++        "umip": true,
++        "pse": true,
++        "avx2": true,
++        "sep": true,
++        "virt-ssbd": false,
++        "nodeid-msr": false,
++        "md-clear": false,
++        "misalignsse": false,
++        "min-xlevel": 2147483656,
++        "bmi1": true,
++        "bmi2": true,
++        "kvm-pv-unhalt": true,
++        "tsc-scale": false,
++        "topoext": false,
++        "clflushopt": true,
++        "monitor": false,
++        "avx512er": false,
++        "pmm-en": false,
++        "pcid": true,
++        "arch-capabilities": true,
++        "3dnow": false,
++        "erms": true,
++        "lahf-lm": true,
++        "vpclmulqdq": false,
++        "fxsr-opt": false,
++        "xstore": false,
++        "rtm": true,
++        "kvm-hint-dedicated": false,
++        "lmce": true,
++        "perfctr-nb": false,
++        "rdrand": true,
++        "rdseed": true,
++        "avx512-4vnniw": false,
++        "vme": true,
++        "vmx": true,
++        "dtes64": false,
++        "mtrr": true,
++        "rdtscp": true,
++        "pse36": true,
++        "kvm-pv-tlb-flush": true,
++        "tbm": false,
++        "wdt": false,
++        "model-id": "Intel(R) Xeon(R) CPU E3-1245 v5 @ 3.50GHz",
++        "sha-ni": false,
++        "abm": true,
++        "avx512pf": false,
++        "xstore-en": false
++      }
++    }
++  },
++  "id": "libvirt-52"
++}
++
++{
++  "execute": "query-cpu-model-expansion",
++  "arguments": {
++    "type": "full",
++    "model": {
++      "name": "base",
++      "props": {
++        "cmov": true,
++        "ia64": false,
++        "ssb-no": false,
++        "aes": true,
++        "mmx": true,
++        "rdpid": false,
++        "arat": true,
++        "gfni": false,
++        "ibrs-all": false,
++        "pause-filter": false,
++        "xsavec": true,
++        "intel-pt": false,
++        "kvm-asyncpf": true,
++        "perfctr-core": false,
++        "mpx": true,
++        "pbe": false,
++        "avx512cd": false,
++        "decodeassists": false,
++        "sse4.1": true,
++        "family": 6,
++        "wbnoinvd": false,
++        "avx512f": false,
++        "msr": true,
++        "mce": true,
++        "mca": true,
++        "xcrypt": false,
++        "min-level": 13,
++        "xgetbv1": true,
++        "cid": false,
++        "ds": false,
++        "fxsr": true,
++        "xsaveopt": true,
++        "xtpr": false,
++        "avx512vl": false,
++        "avx512-vpopcntdq": false,
++        "phe": false,
++        "extapic": false,
++        "3dnowprefetch": true,
++        "avx512vbmi2": false,
++        "cr8legacy": false,
++        "stibp": false,
++        "xcrypt-en": false,
++        "pn": false,
++        "rsba": false,
++        "dca": false,
++        "vendor": "GenuineIntel",
++        "pku": false,
++        "smx": false,
++        "cmp-legacy": false,
++        "avx512-4fmaps": false,
++        "vmcb-clean": false,
++        "hle": true,
++        "3dnowext": false,
++        "amd-no-ssb": false,
++        "npt": false,
++        "rdctl-no": false,
++        "clwb": false,
++        "lbrv": false,
++        "adx": true,
++        "ss": true,
++        "pni": true,
++        "svm-lock": false,
++        "smep": true,
++        "smap": true,
++        "pfthreshold": false,
++        "x2apic": true,
++        "avx512vbmi": false,
++        "avx512vnni": false,
++        "flushbyasid": false,
++        "f16c": true,
++        "ace2-en": false,
++        "pae": true,
++        "pat": true,
++        "sse": true,
++        "phe-en": false,
++        "kvm-nopiodelay": true,
++        "tm": false,
++        "kvmclock-stable-bit": true,
++        "hypervisor": true,
++        "mds-no": false,
++        "pcommit": false,
++        "syscall": true,
++        "avx512dq": false,
++        "svm": false,
++        "invtsc": false,
++        "sse2": true,
++        "ssbd": false,
++        "est": false,
++        "avx512ifma": false,
++        "tm2": false,
++        "kvm-pv-eoi": true,
++        "kvm-pv-ipi": true,
++        "cx8": true,
++        "cldemote": false,
++        "kvm-mmu": false,
++        "sse4.2": true,
++        "pge": true,
++        "avx512bitalg": false,
++        "pdcm": false,
++        "model": 94,
++        "movbe": true,
++        "nrip-save": false,
++        "ssse3": true,
++        "sse4a": false,
++        "invpcid": true,
++        "pdpe1gb": true,
++        "tsc-deadline": true,
++        "skip-l1dfl-vmentry": true,
++        "fma": true,
++        "cx16": true,
++        "de": true,
++        "stepping": 3,
++        "xsave": true,
++        "clflush": true,
++        "skinit": false,
++        "tsc": true,
++        "tce": false,
++        "fpu": true,
++        "ds-cpl": false,
++        "ibs": false,
++        "fma4": false,
++        "la57": false,
++        "osvw": false,
++        "apic": true,
++        "pmm": false,
++        "spec-ctrl": false,
++        "tsc-adjust": true,
++        "kvm-steal-time": true,
++        "kvmclock": true,
++        "lwp": false,
++        "amd-ssbd": false,
++        "xop": false,
++        "ibpb": false,
++        "avx": true,
++        "movdiri": false,
++        "acpi": false,
++        "avx512bw": false,
++        "ace2": false,
++        "fsgsbase": true,
++        "ht": false,
++        "nx": true,
++        "pclmulqdq": true,
++        "mmxext": false,
++        "popcnt": true,
++        "vaes": false,
++        "movdir64b": false,
++        "xsaves": true,
++        "lm": true,
++        "umip": true,
++        "pse": true,
++        "avx2": true,
++        "sep": true,
++        "virt-ssbd": false,
++        "nodeid-msr": false,
++        "md-clear": false,
++        "misalignsse": false,
++        "min-xlevel": 2147483656,
++        "bmi1": true,
++        "bmi2": true,
++        "kvm-pv-unhalt": true,
++        "tsc-scale": false,
++        "topoext": false,
++        "clflushopt": true,
++        "monitor": false,
++        "avx512er": false,
++        "pmm-en": false,
++        "pcid": true,
++        "arch-capabilities": true,
++        "3dnow": false,
++        "erms": true,
++        "lahf-lm": true,
++        "vpclmulqdq": false,
++        "fxsr-opt": false,
++        "xstore": false,
++        "rtm": true,
++        "kvm-hint-dedicated": false,
++        "lmce": true,
++        "perfctr-nb": false,
++        "rdrand": true,
++        "rdseed": true,
++        "avx512-4vnniw": false,
++        "vme": true,
++        "vmx": true,
++        "dtes64": false,
++        "mtrr": true,
++        "rdtscp": true,
++        "pse36": true,
++        "kvm-pv-tlb-flush": true,
++        "tbm": false,
++        "wdt": false,
++        "model-id": "Intel(R) Xeon(R) CPU E3-1245 v5 @ 3.50GHz",
++        "sha-ni": false,
++        "abm": true,
++        "avx512pf": false,
++        "xstore-en": false
++      }
++    }
++  },
++  "id": "libvirt-53"
++}
++
++{
++  "return": {
++    "model": {
++      "name": "base",
++      "props": {
++        "phys-bits": 0,
++        "core-id": -1,
++        "xlevel": 2147483656,
++        "cmov": true,
++        "ia64": false,
++        "ssb-no": false,
++        "aes": true,
++        "mmx": true,
++        "rdpid": false,
++        "arat": true,
++        "gfni": false,
++        "ibrs-all": false,
++        "pause-filter": false,
++        "xsavec": true,
++        "intel-pt": false,
++        "hv-frequencies": false,
++        "tsc-frequency": 0,
++        "xd": true,
++        "x-intel-pt-auto-level": true,
++        "hv-vendor-id": "",
++        "kvm-asyncpf": true,
++        "kvm_asyncpf": true,
++        "perfctr_core": false,
++        "perfctr-core": false,
++        "mpx": true,
++        "pbe": false,
++        "decodeassists": false,
++        "avx512cd": false,
++        "sse4_1": true,
++        "sse4.1": true,
++        "sse4-1": true,
++        "family": 6,
++        "legacy-cache": true,
++        "host-phys-bits-limit": 0,
++        "vmware-cpuid-freq": true,
++        "wbnoinvd": false,
++        "avx512f": false,
++        "msr": true,
++        "mce": true,
++        "mca": true,
++        "hv-runtime": false,
++        "xcrypt": false,
++        "thread-id": -1,
++        "min-level": 13,
++        "xgetbv1": true,
++        "cid": false,
++        "hv-relaxed": false,
++        "hv-crash": false,
++        "ds": false,
++        "fxsr": true,
++        "xsaveopt": true,
++        "xtpr": false,
++        "hv-evmcs": false,
++        "avx512vl": false,
++        "avx512-vpopcntdq": false,
++        "phe": false,
++        "extapic": false,
++        "3dnowprefetch": true,
++        "avx512vbmi2": false,
++        "cr8legacy": false,
++        "stibp": false,
++        "cpuid-0xb": true,
++        "xcrypt-en": false,
++        "kvm_pv_eoi": true,
++        "apic-id": 4294967295,
++        "rsba": false,
++        "pn": false,
++        "dca": false,
++        "vendor": "GenuineIntel",
++        "hv-ipi": false,
++        "pku": false,
++        "smx": false,
++        "cmp_legacy": false,
++        "cmp-legacy": false,
++        "node-id": -1,
++        "avx512-4fmaps": false,
++        "vmcb_clean": false,
++        "vmcb-clean": false,
++        "3dnowext": false,
++        "amd-no-ssb": false,
++        "hle": true,
++        "npt": false,
++        "rdctl-no": false,
++        "memory": "/machine/unattached/system[0]",
++        "clwb": false,
++        "lbrv": false,
++        "adx": true,
++        "ss": true,
++        "pni": true,
++        "svm_lock": false,
++        "svm-lock": false,
++        "pfthreshold": false,
++        "smep": true,
++        "smap": true,
++        "x2apic": true,
++        "avx512vbmi": false,
++        "avx512vnni": false,
++        "hv-stimer": false,
++        "x-hv-synic-kvm-only": false,
++        "i64": true,
++        "flushbyasid": false,
++        "f16c": true,
++        "ace2-en": false,
++        "pat": true,
++        "pae": true,
++        "sse": true,
++        "phe-en": false,
++        "kvm_nopiodelay": true,
++        "kvm-nopiodelay": true,
++        "tm": false,
++        "kvmclock-stable-bit": true,
++        "hypervisor": true,
++        "socket-id": -1,
++        "mds-no": false,
++        "pcommit": false,
++        "syscall": true,
++        "level": 13,
++        "avx512dq": false,
++        "x-migrate-smi-count": true,
++        "svm": false,
++        "full-cpuid-auto-level": true,
++        "hv-reset": false,
++        "invtsc": false,
++        "sse3": true,
++        "sse2": true,
++        "ssbd": false,
++        "est": false,
++        "avx512ifma": false,
++        "tm2": false,
++        "kvm-pv-ipi": true,
++        "kvm-pv-eoi": true,
++        "cx8": true,
++        "cldemote": false,
++        "hv-reenlightenment": false,
++        "kvm_mmu": false,
++        "kvm-mmu": false,
++        "sse4_2": true,
++        "sse4.2": true,
++        "sse4-2": true,
++        "pge": true,
++        "fill-mtrr-mask": true,
++        "avx512bitalg": false,
++        "nodeid_msr": false,
++        "pdcm": false,
++        "movbe": true,
++        "model": 94,
++        "nrip_save": false,
++        "nrip-save": false,
++        "kvm_pv_unhalt": true,
++        "ssse3": true,
++        "sse4a": false,
++        "invpcid": true,
++        "pdpe1gb": true,
++        "tsc-deadline": true,
++        "skip-l1dfl-vmentry": true,
++        "fma": true,
++        "cx16": true,
++        "de": true,
++        "enforce": false,
++        "stepping": 3,
++        "xsave": true,
++        "clflush": true,
++        "skinit": false,
++        "tsc": true,
++        "tce": false,
++        "fpu": true,
++        "ibs": false,
++        "ds_cpl": false,
++        "ds-cpl": false,
++        "host-phys-bits": false,
++        "fma4": false,
++        "la57": false,
++        "osvw": false,
++        "check": true,
++        "hv-spinlocks": -1,
++        "pmm": false,
++        "pmu": false,
++        "apic": true,
++        "spec-ctrl": false,
++        "min-xlevel2": 0,
++        "tsc-adjust": true,
++        "tsc_adjust": true,
++        "kvm-steal-time": true,
++        "kvm_steal_time": true,
++        "kvmclock": true,
++        "l3-cache": true,
++        "lwp": false,
++        "amd-ssbd": false,
++        "ibpb": false,
++        "xop": false,
++        "avx": true,
++        "movdiri": false,
++        "ace2": false,
++        "avx512bw": false,
++        "acpi": false,
++        "hv-vapic": false,
++        "fsgsbase": true,
++        "ht": false,
++        "nx": true,
++        "pclmulqdq": true,
++        "mmxext": false,
++        "vaes": false,
++        "popcnt": true,
++        "xsaves": true,
++        "movdir64b": false,
++        "tcg-cpuid": true,
++        "lm": true,
++        "umip": true,
++        "pse": true,
++        "avx2": true,
++        "sep": true,
++        "pclmuldq": true,
++        "virt-ssbd": false,
++        "x-hv-max-vps": -1,
++        "nodeid-msr": false,
++        "md-clear": false,
++        "kvm": true,
++        "misalignsse": false,
++        "min-xlevel": 2147483656,
++        "kvm-pv-unhalt": true,
++        "bmi2": true,
++        "bmi1": true,
++        "realized": false,
++        "tsc_scale": false,
++        "tsc-scale": false,
++        "topoext": false,
++        "hv-vpindex": false,
++        "xlevel2": 0,
++        "clflushopt": true,
++        "kvm-no-smi-migration": false,
++        "monitor": false,
++        "avx512er": false,
++        "pmm-en": false,
++        "pcid": true,
++        "arch-capabilities": true,
++        "3dnow": false,
++        "erms": true,
++        "lahf-lm": true,
++        "lahf_lm": true,
++        "vpclmulqdq": false,
++        "fxsr-opt": false,
++        "hv-synic": false,
++        "xstore": false,
++        "fxsr_opt": false,
++        "kvm-hint-dedicated": false,
++        "rtm": true,
++        "lmce": true,
++        "hv-time": false,
++        "perfctr-nb": false,
++        "perfctr_nb": false,
++        "ffxsr": false,
++        "hv-tlbflush": false,
++        "rdrand": true,
++        "rdseed": true,
++        "avx512-4vnniw": false,
++        "vmx": true,
++        "vme": true,
++        "dtes64": false,
++        "mtrr": true,
++        "rdtscp": true,
++        "pse36": true,
++        "kvm-pv-tlb-flush": true,
++        "tbm": false,
++        "wdt": false,
++        "pause_filter": false,
++        "sha-ni": false,
++        "model-id": "Intel(R) Xeon(R) CPU E3-1245 v5 @ 3.50GHz",
++        "abm": true,
++        "avx512pf": false,
++        "xstore-en": false
++      }
++    }
++  },
++  "id": "libvirt-53"
++}
++
++{
++  "execute": "query-sev-capabilities",
++  "id": "libvirt-54"
++}
++
++{
++  "id": "libvirt-54",
++  "error": {
++    "class": "GenericError",
++    "desc": "SEV feature is not available"
++  }
++}
++
++{
++  "execute": "qmp_capabilities",
++  "id": "libvirt-1"
++}
++
++{
++  "return": {
++  },
++  "id": "libvirt-1"
++}
++
++{
++  "execute": "query-cpu-definitions",
++  "id": "libvirt-2"
++}
++
++{
++  "return": [
++    {
++      "name": "max",
++      "typename": "max-x86_64-cpu",
++      "unavailable-features": [
++      ],
++      "static": false,
++      "migration-safe": false
++    },
++    {
++      "name": "host",
++      "typename": "host-x86_64-cpu",
++      "unavailable-features": [
++        "kvm"
++      ],
++      "static": false,
++      "migration-safe": false
++    },
++    {
++      "name": "base",
++      "typename": "base-x86_64-cpu",
++      "unavailable-features": [
++      ],
++      "static": true,
++      "migration-safe": true
++    },
++    {
++      "name": "qemu64",
++      "typename": "qemu64-x86_64-cpu",
++      "unavailable-features": [
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "qemu32",
++      "typename": "qemu32-x86_64-cpu",
++      "unavailable-features": [
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "phenom",
++      "typename": "phenom-x86_64-cpu",
++      "unavailable-features": [
++        "fxsr-opt"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "pentium3",
++      "typename": "pentium3-x86_64-cpu",
++      "unavailable-features": [
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "pentium2",
++      "typename": "pentium2-x86_64-cpu",
++      "unavailable-features": [
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "pentium",
++      "typename": "pentium-x86_64-cpu",
++      "unavailable-features": [
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "n270",
++      "typename": "n270-x86_64-cpu",
++      "unavailable-features": [
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "kvm64",
++      "typename": "kvm64-x86_64-cpu",
++      "unavailable-features": [
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "kvm32",
++      "typename": "kvm32-x86_64-cpu",
++      "unavailable-features": [
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "coreduo",
++      "typename": "coreduo-x86_64-cpu",
++      "unavailable-features": [
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "core2duo",
++      "typename": "core2duo-x86_64-cpu",
++      "unavailable-features": [
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "athlon",
++      "typename": "athlon-x86_64-cpu",
++      "unavailable-features": [
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Westmere-IBRS",
++      "typename": "Westmere-IBRS-x86_64-cpu",
++      "unavailable-features": [
++        "spec-ctrl"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Westmere",
++      "typename": "Westmere-x86_64-cpu",
++      "unavailable-features": [
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Skylake-Server-IBRS",
++      "typename": "Skylake-Server-IBRS-x86_64-cpu",
++      "unavailable-features": [
++        "fma",
++        "pcid",
++        "x2apic",
++        "tsc-deadline",
++        "avx",
++        "f16c",
++        "hle",
++        "avx2",
++        "invpcid",
++        "rtm",
++        "avx512f",
++        "avx512dq",
++        "rdseed",
++        "avx512cd",
++        "avx512bw",
++        "avx512vl",
++        "spec-ctrl",
++        "3dnowprefetch",
++        "xsavec"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Skylake-Server",
++      "typename": "Skylake-Server-x86_64-cpu",
++      "unavailable-features": [
++        "fma",
++        "pcid",
++        "x2apic",
++        "tsc-deadline",
++        "avx",
++        "f16c",
++        "hle",
++        "avx2",
++        "invpcid",
++        "rtm",
++        "avx512f",
++        "avx512dq",
++        "rdseed",
++        "avx512cd",
++        "avx512bw",
++        "avx512vl",
++        "3dnowprefetch",
++        "xsavec"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Skylake-Client-IBRS",
++      "typename": "Skylake-Client-IBRS-x86_64-cpu",
++      "unavailable-features": [
++        "fma",
++        "pcid",
++        "x2apic",
++        "tsc-deadline",
++        "avx",
++        "f16c",
++        "hle",
++        "avx2",
++        "invpcid",
++        "rtm",
++        "rdseed",
++        "spec-ctrl",
++        "3dnowprefetch",
++        "xsavec"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Skylake-Client",
++      "typename": "Skylake-Client-x86_64-cpu",
++      "unavailable-features": [
++        "fma",
++        "pcid",
++        "x2apic",
++        "tsc-deadline",
++        "avx",
++        "f16c",
++        "hle",
++        "avx2",
++        "invpcid",
++        "rtm",
++        "rdseed",
++        "3dnowprefetch",
++        "xsavec"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "SandyBridge-IBRS",
++      "typename": "SandyBridge-IBRS-x86_64-cpu",
++      "unavailable-features": [
++        "x2apic",
++        "tsc-deadline",
++        "avx",
++        "spec-ctrl"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "SandyBridge",
++      "typename": "SandyBridge-x86_64-cpu",
++      "unavailable-features": [
++        "x2apic",
++        "tsc-deadline",
++        "avx"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Penryn",
++      "typename": "Penryn-x86_64-cpu",
++      "unavailable-features": [
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Opteron_G5",
++      "typename": "Opteron_G5-x86_64-cpu",
++      "unavailable-features": [
++        "fma",
++        "avx",
++        "f16c",
++        "misalignsse",
++        "3dnowprefetch",
++        "xop",
++        "fma4",
++        "tbm",
++        "nrip-save"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Opteron_G4",
++      "typename": "Opteron_G4-x86_64-cpu",
++      "unavailable-features": [
++        "avx",
++        "misalignsse",
++        "3dnowprefetch",
++        "xop",
++        "fma4",
++        "nrip-save"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Opteron_G3",
++      "typename": "Opteron_G3-x86_64-cpu",
++      "unavailable-features": [
++        "misalignsse"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Opteron_G2",
++      "typename": "Opteron_G2-x86_64-cpu",
++      "unavailable-features": [
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Opteron_G1",
++      "typename": "Opteron_G1-x86_64-cpu",
++      "unavailable-features": [
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Nehalem-IBRS",
++      "typename": "Nehalem-IBRS-x86_64-cpu",
++      "unavailable-features": [
++        "spec-ctrl"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Nehalem",
++      "typename": "Nehalem-x86_64-cpu",
++      "unavailable-features": [
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "KnightsMill",
++      "typename": "KnightsMill-x86_64-cpu",
++      "unavailable-features": [
++        "fma",
++        "x2apic",
++        "tsc-deadline",
++        "avx",
++        "f16c",
++        "avx2",
++        "avx512f",
++        "rdseed",
++        "avx512pf",
++        "avx512er",
++        "avx512cd",
++        "avx512-vpopcntdq",
++        "avx512-4vnniw",
++        "avx512-4fmaps",
++        "3dnowprefetch"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "IvyBridge-IBRS",
++      "typename": "IvyBridge-IBRS-x86_64-cpu",
++      "unavailable-features": [
++        "x2apic",
++        "tsc-deadline",
++        "avx",
++        "f16c",
++        "spec-ctrl"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "IvyBridge",
++      "typename": "IvyBridge-x86_64-cpu",
++      "unavailable-features": [
++        "x2apic",
++        "tsc-deadline",
++        "avx",
++        "f16c"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Icelake-Server",
++      "typename": "Icelake-Server-x86_64-cpu",
++      "unavailable-features": [
++        "fma",
++        "pcid",
++        "x2apic",
++        "tsc-deadline",
++        "avx",
++        "f16c",
++        "hle",
++        "avx2",
++        "invpcid",
++        "rtm",
++        "avx512f",
++        "avx512dq",
++        "rdseed",
++        "avx512cd",
++        "avx512bw",
++        "avx512vl",
++        "avx512vbmi",
++        "umip",
++        "avx512vbmi2",
++        "gfni",
++        "vaes",
++        "vpclmulqdq",
++        "avx512vnni",
++        "avx512bitalg",
++        "avx512-vpopcntdq",
++        "spec-ctrl",
++        "ssbd",
++        "3dnowprefetch",
++        "wbnoinvd",
++        "xsavec"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Icelake-Client",
++      "typename": "Icelake-Client-x86_64-cpu",
++      "unavailable-features": [
++        "fma",
++        "pcid",
++        "x2apic",
++        "tsc-deadline",
++        "avx",
++        "f16c",
++        "hle",
++        "avx2",
++        "invpcid",
++        "rtm",
++        "rdseed",
++        "avx512vbmi",
++        "umip",
++        "avx512vbmi2",
++        "gfni",
++        "vaes",
++        "vpclmulqdq",
++        "avx512vnni",
++        "avx512bitalg",
++        "avx512-vpopcntdq",
++        "spec-ctrl",
++        "ssbd",
++        "3dnowprefetch",
++        "wbnoinvd",
++        "xsavec"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Haswell-noTSX-IBRS",
++      "typename": "Haswell-noTSX-IBRS-x86_64-cpu",
++      "unavailable-features": [
++        "fma",
++        "pcid",
++        "x2apic",
++        "tsc-deadline",
++        "avx",
++        "f16c",
++        "avx2",
++        "invpcid",
++        "spec-ctrl"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Haswell-noTSX",
++      "typename": "Haswell-noTSX-x86_64-cpu",
++      "unavailable-features": [
++        "fma",
++        "pcid",
++        "x2apic",
++        "tsc-deadline",
++        "avx",
++        "f16c",
++        "avx2",
++        "invpcid"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Haswell-IBRS",
++      "typename": "Haswell-IBRS-x86_64-cpu",
++      "unavailable-features": [
++        "fma",
++        "pcid",
++        "x2apic",
++        "tsc-deadline",
++        "avx",
++        "f16c",
++        "hle",
++        "avx2",
++        "invpcid",
++        "rtm",
++        "spec-ctrl"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Haswell",
++      "typename": "Haswell-x86_64-cpu",
++      "unavailable-features": [
++        "fma",
++        "pcid",
++        "x2apic",
++        "tsc-deadline",
++        "avx",
++        "f16c",
++        "hle",
++        "avx2",
++        "invpcid",
++        "rtm"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "EPYC-IBPB",
++      "typename": "EPYC-IBPB-x86_64-cpu",
++      "unavailable-features": [
++        "fma",
++        "avx",
++        "f16c",
++        "avx2",
++        "rdseed",
++        "sha-ni",
++        "fxsr-opt",
++        "misalignsse",
++        "3dnowprefetch",
++        "osvw",
++        "topoext",
++        "ibpb",
++        "nrip-save",
++        "xsavec"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "EPYC",
++      "typename": "EPYC-x86_64-cpu",
++      "unavailable-features": [
++        "fma",
++        "avx",
++        "f16c",
++        "avx2",
++        "rdseed",
++        "sha-ni",
++        "fxsr-opt",
++        "misalignsse",
++        "3dnowprefetch",
++        "osvw",
++        "topoext",
++        "nrip-save",
++        "xsavec"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Dhyana",
++      "typename": "Dhyana-x86_64-cpu",
++      "unavailable-features": [
++        "fma",
++        "avx",
++        "f16c",
++        "avx2",
++        "rdseed",
++        "fxsr-opt",
++        "misalignsse",
++        "3dnowprefetch",
++        "osvw",
++        "topoext",
++        "ibpb",
++        "nrip-save",
++        "xsavec"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Conroe",
++      "typename": "Conroe-x86_64-cpu",
++      "unavailable-features": [
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Cascadelake-Server",
++      "typename": "Cascadelake-Server-x86_64-cpu",
++      "unavailable-features": [
++        "fma",
++        "pcid",
++        "x2apic",
++        "tsc-deadline",
++        "avx",
++        "f16c",
++        "hle",
++        "avx2",
++        "invpcid",
++        "rtm",
++        "avx512f",
++        "avx512dq",
++        "rdseed",
++        "avx512cd",
++        "avx512bw",
++        "avx512vl",
++        "avx512vnni",
++        "spec-ctrl",
++        "ssbd",
++        "3dnowprefetch",
++        "xsavec"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Broadwell-noTSX-IBRS",
++      "typename": "Broadwell-noTSX-IBRS-x86_64-cpu",
++      "unavailable-features": [
++        "fma",
++        "pcid",
++        "x2apic",
++        "tsc-deadline",
++        "avx",
++        "f16c",
++        "avx2",
++        "invpcid",
++        "rdseed",
++        "spec-ctrl",
++        "3dnowprefetch"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Broadwell-noTSX",
++      "typename": "Broadwell-noTSX-x86_64-cpu",
++      "unavailable-features": [
++        "fma",
++        "pcid",
++        "x2apic",
++        "tsc-deadline",
++        "avx",
++        "f16c",
++        "avx2",
++        "invpcid",
++        "rdseed",
++        "3dnowprefetch"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Broadwell-IBRS",
++      "typename": "Broadwell-IBRS-x86_64-cpu",
++      "unavailable-features": [
++        "fma",
++        "pcid",
++        "x2apic",
++        "tsc-deadline",
++        "avx",
++        "f16c",
++        "hle",
++        "avx2",
++        "invpcid",
++        "rtm",
++        "rdseed",
++        "spec-ctrl",
++        "3dnowprefetch"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "Broadwell",
++      "typename": "Broadwell-x86_64-cpu",
++      "unavailable-features": [
++        "fma",
++        "pcid",
++        "x2apic",
++        "tsc-deadline",
++        "avx",
++        "f16c",
++        "hle",
++        "avx2",
++        "invpcid",
++        "rtm",
++        "rdseed",
++        "3dnowprefetch"
++      ],
++      "static": false,
++      "migration-safe": true
++    },
++    {
++      "name": "486",
++      "typename": "486-x86_64-cpu",
++      "unavailable-features": [
++      ],
++      "static": false,
++      "migration-safe": true
++    }
++  ],
++  "id": "libvirt-2"
++}
++
++{
++  "execute": "query-cpu-model-expansion",
++  "arguments": {
++    "type": "static",
++    "model": {
++      "name": "max"
++    }
++  },
++  "id": "libvirt-3"
++}
++
++{
++  "return": {
++    "model": {
++      "name": "base",
++      "props": {
++        "cmov": true,
++        "ia64": false,
++        "ssb-no": false,
++        "aes": true,
++        "mmx": true,
++        "rdpid": false,
++        "arat": true,
++        "gfni": false,
++        "ibrs-all": false,
++        "pause-filter": false,
++        "xsavec": false,
++        "intel-pt": false,
++        "kvm-asyncpf": false,
++        "perfctr-core": false,
++        "mpx": true,
++        "pbe": false,
++        "avx512cd": false,
++        "decodeassists": false,
++        "sse4.1": true,
++        "family": 6,
++        "wbnoinvd": false,
++        "avx512f": false,
++        "msr": true,
++        "mce": true,
++        "mca": true,
++        "xcrypt": false,
++        "min-level": 13,
++        "xgetbv1": true,
++        "cid": false,
++        "ds": false,
++        "fxsr": true,
++        "xsaveopt": true,
++        "xtpr": false,
++        "avx512vl": false,
++        "avx512-vpopcntdq": false,
++        "phe": false,
++        "extapic": false,
++        "3dnowprefetch": false,
++        "avx512vbmi2": false,
++        "cr8legacy": true,
++        "stibp": false,
++        "xcrypt-en": false,
++        "pn": false,
++        "rsba": false,
++        "dca": false,
++        "vendor": "AuthenticAMD",
++        "pku": true,
++        "smx": false,
++        "cmp-legacy": false,
++        "avx512-4fmaps": false,
++        "vmcb-clean": false,
++        "hle": false,
++        "3dnowext": true,
++        "amd-no-ssb": false,
++        "npt": true,
++        "rdctl-no": false,
++        "clwb": true,
++        "lbrv": false,
++        "adx": true,
++        "ss": true,
++        "pni": true,
++        "svm-lock": false,
++        "smep": true,
++        "smap": true,
++        "pfthreshold": false,
++        "x2apic": false,
++        "avx512vbmi": false,
++        "avx512vnni": false,
++        "flushbyasid": false,
++        "f16c": false,
++        "ace2-en": false,
++        "pae": true,
++        "pat": true,
++        "sse": true,
++        "phe-en": false,
++        "kvm-nopiodelay": false,
++        "tm": false,
++        "kvmclock-stable-bit": false,
++        "hypervisor": true,
++        "mds-no": false,
++        "pcommit": true,
++        "syscall": true,
++        "avx512dq": false,
++        "svm": true,
++        "invtsc": false,
++        "sse2": true,
++        "ssbd": false,
++        "est": false,
++        "avx512ifma": false,
++        "tm2": false,
++        "kvm-pv-eoi": false,
++        "kvm-pv-ipi": false,
++        "cx8": true,
++        "cldemote": false,
++        "kvm-mmu": false,
++        "sse4.2": true,
++        "pge": true,
++        "avx512bitalg": false,
++        "pdcm": false,
++        "model": 6,
++        "movbe": true,
++        "nrip-save": false,
++        "ssse3": true,
++        "sse4a": true,
++        "invpcid": false,
++        "pdpe1gb": true,
++        "tsc-deadline": false,
++        "skip-l1dfl-vmentry": false,
++        "fma": false,
++        "cx16": true,
++        "de": true,
++        "stepping": 3,
++        "xsave": true,
++        "clflush": true,
++        "skinit": false,
++        "tsc": true,
++        "tce": false,
++        "fpu": true,
++        "ds-cpl": false,
++        "ibs": false,
++        "fma4": false,
++        "la57": true,
++        "osvw": false,
++        "apic": true,
++        "pmm": false,
++        "spec-ctrl": false,
++        "tsc-adjust": false,
++        "kvm-steal-time": false,
++        "kvmclock": false,
++        "lwp": false,
++        "amd-ssbd": false,
++        "xop": false,
++        "ibpb": false,
++        "avx": false,
++        "movdiri": false,
++        "acpi": true,
++        "avx512bw": false,
++        "ace2": false,
++        "fsgsbase": true,
++        "ht": false,
++        "nx": true,
++        "pclmulqdq": true,
++        "mmxext": true,
++        "popcnt": true,
++        "vaes": false,
++        "movdir64b": false,
++        "xsaves": false,
++        "lm": true,
++        "umip": false,
++        "pse": true,
++        "avx2": false,
++        "sep": true,
++        "virt-ssbd": false,
++        "nodeid-msr": false,
++        "md-clear": false,
++        "misalignsse": false,
++        "min-xlevel": 2147483658,
++        "bmi1": true,
++        "bmi2": true,
++        "kvm-pv-unhalt": false,
++        "tsc-scale": false,
++        "topoext": false,
++        "clflushopt": true,
++        "monitor": true,
++        "avx512er": false,
++        "pmm-en": false,
++        "pcid": false,
++        "arch-capabilities": false,
++        "3dnow": true,
++        "erms": true,
++        "lahf-lm": true,
++        "vpclmulqdq": false,
++        "fxsr-opt": false,
++        "xstore": false,
++        "rtm": false,
++        "kvm-hint-dedicated": false,
++        "lmce": false,
++        "perfctr-nb": false,
++        "rdrand": true,
++        "rdseed": false,
++        "avx512-4vnniw": false,
++        "vme": false,
++        "vmx": false,
++        "dtes64": false,
++        "mtrr": true,
++        "rdtscp": true,
++        "pse36": true,
++        "kvm-pv-tlb-flush": false,
++        "tbm": false,
++        "wdt": false,
++        "model-id": "QEMU TCG CPU version 2.5+",
++        "sha-ni": false,
++        "abm": true,
++        "avx512pf": false,
++        "xstore-en": false
++      }
++    }
++  },
++  "id": "libvirt-3"
++}
++
++{
++  "execute": "query-cpu-model-expansion",
++  "arguments": {
++    "type": "full",
++    "model": {
++      "name": "base",
++      "props": {
++        "cmov": true,
++        "ia64": false,
++        "ssb-no": false,
++        "aes": true,
++        "mmx": true,
++        "rdpid": false,
++        "arat": true,
++        "gfni": false,
++        "ibrs-all": false,
++        "pause-filter": false,
++        "xsavec": false,
++        "intel-pt": false,
++        "kvm-asyncpf": false,
++        "perfctr-core": false,
++        "mpx": true,
++        "pbe": false,
++        "avx512cd": false,
++        "decodeassists": false,
++        "sse4.1": true,
++        "family": 6,
++        "wbnoinvd": false,
++        "avx512f": false,
++        "msr": true,
++        "mce": true,
++        "mca": true,
++        "xcrypt": false,
++        "min-level": 13,
++        "xgetbv1": true,
++        "cid": false,
++        "ds": false,
++        "fxsr": true,
++        "xsaveopt": true,
++        "xtpr": false,
++        "avx512vl": false,
++        "avx512-vpopcntdq": false,
++        "phe": false,
++        "extapic": false,
++        "3dnowprefetch": false,
++        "avx512vbmi2": false,
++        "cr8legacy": true,
++        "stibp": false,
++        "xcrypt-en": false,
++        "pn": false,
++        "rsba": false,
++        "dca": false,
++        "vendor": "AuthenticAMD",
++        "pku": true,
++        "smx": false,
++        "cmp-legacy": false,
++        "avx512-4fmaps": false,
++        "vmcb-clean": false,
++        "hle": false,
++        "3dnowext": true,
++        "amd-no-ssb": false,
++        "npt": true,
++        "rdctl-no": false,
++        "clwb": true,
++        "lbrv": false,
++        "adx": true,
++        "ss": true,
++        "pni": true,
++        "svm-lock": false,
++        "smep": true,
++        "smap": true,
++        "pfthreshold": false,
++        "x2apic": false,
++        "avx512vbmi": false,
++        "avx512vnni": false,
++        "flushbyasid": false,
++        "f16c": false,
++        "ace2-en": false,
++        "pae": true,
++        "pat": true,
++        "sse": true,
++        "phe-en": false,
++        "kvm-nopiodelay": false,
++        "tm": false,
++        "kvmclock-stable-bit": false,
++        "hypervisor": true,
++        "mds-no": false,
++        "pcommit": true,
++        "syscall": true,
++        "avx512dq": false,
++        "svm": true,
++        "invtsc": false,
++        "sse2": true,
++        "ssbd": false,
++        "est": false,
++        "avx512ifma": false,
++        "tm2": false,
++        "kvm-pv-eoi": false,
++        "kvm-pv-ipi": false,
++        "cx8": true,
++        "cldemote": false,
++        "kvm-mmu": false,
++        "sse4.2": true,
++        "pge": true,
++        "avx512bitalg": false,
++        "pdcm": false,
++        "model": 6,
++        "movbe": true,
++        "nrip-save": false,
++        "ssse3": true,
++        "sse4a": true,
++        "invpcid": false,
++        "pdpe1gb": true,
++        "tsc-deadline": false,
++        "skip-l1dfl-vmentry": false,
++        "fma": false,
++        "cx16": true,
++        "de": true,
++        "stepping": 3,
++        "xsave": true,
++        "clflush": true,
++        "skinit": false,
++        "tsc": true,
++        "tce": false,
++        "fpu": true,
++        "ds-cpl": false,
++        "ibs": false,
++        "fma4": false,
++        "la57": true,
++        "osvw": false,
++        "apic": true,
++        "pmm": false,
++        "spec-ctrl": false,
++        "tsc-adjust": false,
++        "kvm-steal-time": false,
++        "kvmclock": false,
++        "lwp": false,
++        "amd-ssbd": false,
++        "xop": false,
++        "ibpb": false,
++        "avx": false,
++        "movdiri": false,
++        "acpi": true,
++        "avx512bw": false,
++        "ace2": false,
++        "fsgsbase": true,
++        "ht": false,
++        "nx": true,
++        "pclmulqdq": true,
++        "mmxext": true,
++        "popcnt": true,
++        "vaes": false,
++        "movdir64b": false,
++        "xsaves": false,
++        "lm": true,
++        "umip": false,
++        "pse": true,
++        "avx2": false,
++        "sep": true,
++        "virt-ssbd": false,
++        "nodeid-msr": false,
++        "md-clear": false,
++        "misalignsse": false,
++        "min-xlevel": 2147483658,
++        "bmi1": true,
++        "bmi2": true,
++        "kvm-pv-unhalt": false,
++        "tsc-scale": false,
++        "topoext": false,
++        "clflushopt": true,
++        "monitor": true,
++        "avx512er": false,
++        "pmm-en": false,
++        "pcid": false,
++        "arch-capabilities": false,
++        "3dnow": true,
++        "erms": true,
++        "lahf-lm": true,
++        "vpclmulqdq": false,
++        "fxsr-opt": false,
++        "xstore": false,
++        "rtm": false,
++        "kvm-hint-dedicated": false,
++        "lmce": false,
++        "perfctr-nb": false,
++        "rdrand": true,
++        "rdseed": false,
++        "avx512-4vnniw": false,
++        "vme": false,
++        "vmx": false,
++        "dtes64": false,
++        "mtrr": true,
++        "rdtscp": true,
++        "pse36": true,
++        "kvm-pv-tlb-flush": false,
++        "tbm": false,
++        "wdt": false,
++        "model-id": "QEMU TCG CPU version 2.5+",
++        "sha-ni": false,
++        "abm": true,
++        "avx512pf": false,
++        "xstore-en": false
++      }
++    }
++  },
++  "id": "libvirt-4"
++}
++
++{
++  "return": {
++    "model": {
++      "name": "base",
++      "props": {
++        "phys-bits": 0,
++        "core-id": -1,
++        "xlevel": 2147483658,
++        "cmov": true,
++        "ia64": false,
++        "ssb-no": false,
++        "aes": true,
++        "mmx": true,
++        "rdpid": false,
++        "arat": true,
++        "gfni": false,
++        "ibrs-all": false,
++        "pause-filter": false,
++        "xsavec": false,
++        "intel-pt": false,
++        "hv-frequencies": false,
++        "tsc-frequency": 0,
++        "xd": true,
++        "x-intel-pt-auto-level": true,
++        "hv-vendor-id": "",
++        "kvm-asyncpf": false,
++        "kvm_asyncpf": false,
++        "perfctr_core": false,
++        "perfctr-core": false,
++        "mpx": true,
++        "pbe": false,
++        "decodeassists": false,
++        "avx512cd": false,
++        "sse4_1": true,
++        "sse4.1": true,
++        "sse4-1": true,
++        "family": 6,
++        "legacy-cache": true,
++        "host-phys-bits-limit": 0,
++        "vmware-cpuid-freq": true,
++        "wbnoinvd": false,
++        "avx512f": false,
++        "msr": true,
++        "mce": true,
++        "mca": true,
++        "hv-runtime": false,
++        "xcrypt": false,
++        "thread-id": -1,
++        "min-level": 13,
++        "xgetbv1": true,
++        "cid": false,
++        "hv-relaxed": false,
++        "hv-crash": false,
++        "ds": false,
++        "fxsr": true,
++        "xsaveopt": true,
++        "xtpr": false,
++        "hv-evmcs": false,
++        "avx512vl": false,
++        "avx512-vpopcntdq": false,
++        "phe": false,
++        "extapic": false,
++        "3dnowprefetch": false,
++        "avx512vbmi2": false,
++        "cr8legacy": true,
++        "stibp": false,
++        "cpuid-0xb": true,
++        "xcrypt-en": false,
++        "kvm_pv_eoi": false,
++        "apic-id": 4294967295,
++        "rsba": false,
++        "pn": false,
++        "dca": false,
++        "vendor": "AuthenticAMD",
++        "hv-ipi": false,
++        "pku": true,
++        "smx": false,
++        "cmp_legacy": false,
++        "cmp-legacy": false,
++        "node-id": -1,
++        "avx512-4fmaps": false,
++        "vmcb_clean": false,
++        "vmcb-clean": false,
++        "3dnowext": true,
++        "amd-no-ssb": false,
++        "hle": false,
++        "npt": true,
++        "rdctl-no": false,
++        "memory": "/machine/unattached/system[0]",
++        "clwb": true,
++        "lbrv": false,
++        "adx": true,
++        "ss": true,
++        "pni": true,
++        "svm_lock": false,
++        "svm-lock": false,
++        "pfthreshold": false,
++        "smep": true,
++        "smap": true,
++        "x2apic": false,
++        "avx512vbmi": false,
++        "avx512vnni": false,
++        "hv-stimer": false,
++        "x-hv-synic-kvm-only": false,
++        "i64": true,
++        "flushbyasid": false,
++        "f16c": false,
++        "ace2-en": false,
++        "pat": true,
++        "pae": true,
++        "sse": true,
++        "phe-en": false,
++        "kvm_nopiodelay": false,
++        "kvm-nopiodelay": false,
++        "tm": false,
++        "kvmclock-stable-bit": false,
++        "hypervisor": true,
++        "socket-id": -1,
++        "mds-no": false,
++        "pcommit": true,
++        "syscall": true,
++        "level": 13,
++        "avx512dq": false,
++        "x-migrate-smi-count": true,
++        "svm": true,
++        "full-cpuid-auto-level": true,
++        "hv-reset": false,
++        "invtsc": false,
++        "sse3": true,
++        "sse2": true,
++        "ssbd": false,
++        "est": false,
++        "avx512ifma": false,
++        "tm2": false,
++        "kvm-pv-ipi": false,
++        "kvm-pv-eoi": false,
++        "cx8": true,
++        "cldemote": false,
++        "hv-reenlightenment": false,
++        "kvm_mmu": false,
++        "kvm-mmu": false,
++        "sse4_2": true,
++        "sse4.2": true,
++        "sse4-2": true,
++        "pge": true,
++        "fill-mtrr-mask": true,
++        "avx512bitalg": false,
++        "nodeid_msr": false,
++        "pdcm": false,
++        "movbe": true,
++        "model": 6,
++        "nrip_save": false,
++        "nrip-save": false,
++        "kvm_pv_unhalt": false,
++        "ssse3": true,
++        "sse4a": true,
++        "invpcid": false,
++        "pdpe1gb": true,
++        "tsc-deadline": false,
++        "skip-l1dfl-vmentry": false,
++        "fma": false,
++        "cx16": true,
++        "de": true,
++        "enforce": false,
++        "stepping": 3,
++        "xsave": true,
++        "clflush": true,
++        "skinit": false,
++        "tsc": true,
++        "tce": false,
++        "fpu": true,
++        "ibs": false,
++        "ds_cpl": false,
++        "ds-cpl": false,
++        "host-phys-bits": false,
++        "fma4": false,
++        "la57": true,
++        "osvw": false,
++        "check": true,
++        "hv-spinlocks": -1,
++        "pmm": false,
++        "pmu": false,
++        "apic": true,
++        "spec-ctrl": false,
++        "min-xlevel2": 0,
++        "tsc-adjust": false,
++        "tsc_adjust": false,
++        "kvm-steal-time": false,
++        "kvm_steal_time": false,
++        "kvmclock": false,
++        "l3-cache": true,
++        "lwp": false,
++        "amd-ssbd": false,
++        "ibpb": false,
++        "xop": false,
++        "avx": false,
++        "movdiri": false,
++        "ace2": false,
++        "avx512bw": false,
++        "acpi": true,
++        "hv-vapic": false,
++        "fsgsbase": true,
++        "ht": false,
++        "nx": true,
++        "pclmulqdq": true,
++        "mmxext": true,
++        "vaes": false,
++        "popcnt": true,
++        "xsaves": false,
++        "movdir64b": false,
++        "tcg-cpuid": true,
++        "lm": true,
++        "umip": false,
++        "pse": true,
++        "avx2": false,
++        "sep": true,
++        "pclmuldq": true,
++        "virt-ssbd": false,
++        "x-hv-max-vps": -1,
++        "nodeid-msr": false,
++        "md-clear": false,
++        "kvm": true,
++        "misalignsse": false,
++        "min-xlevel": 2147483658,
++        "kvm-pv-unhalt": false,
++        "bmi2": true,
++        "bmi1": true,
++        "realized": false,
++        "tsc_scale": false,
++        "tsc-scale": false,
++        "topoext": false,
++        "hv-vpindex": false,
++        "xlevel2": 0,
++        "clflushopt": true,
++        "kvm-no-smi-migration": false,
++        "monitor": true,
++        "avx512er": false,
++        "pmm-en": false,
++        "pcid": false,
++        "arch-capabilities": false,
++        "3dnow": true,
++        "erms": true,
++        "lahf-lm": true,
++        "lahf_lm": true,
++        "vpclmulqdq": false,
++        "fxsr-opt": false,
++        "hv-synic": false,
++        "xstore": false,
++        "fxsr_opt": false,
++        "kvm-hint-dedicated": false,
++        "rtm": false,
++        "lmce": false,
++        "hv-time": false,
++        "perfctr-nb": false,
++        "perfctr_nb": false,
++        "ffxsr": false,
++        "hv-tlbflush": false,
++        "rdrand": true,
++        "rdseed": false,
++        "avx512-4vnniw": false,
++        "vmx": false,
++        "vme": false,
++        "dtes64": false,
++        "mtrr": true,
++        "rdtscp": true,
++        "pse36": true,
++        "kvm-pv-tlb-flush": false,
++        "tbm": false,
++        "wdt": false,
++        "pause_filter": false,
++        "sha-ni": false,
++        "model-id": "QEMU TCG CPU version 2.5+",
++        "abm": true,
++        "avx512pf": false,
++        "xstore-en": false
++      }
++    }
++  },
++  "id": "libvirt-4"
++}
++
++{
++  "execute": "query-cpu-model-expansion",
++  "arguments": {
++    "type": "static",
++    "model": {
++      "name": "max",
++      "props": {
++        "migratable": false
++      }
++    }
++  },
++  "id": "libvirt-5"
++}
++
++{
++  "return": {
++    "model": {
++      "name": "base",
++      "props": {
++        "cmov": true,
++        "ia64": false,
++        "ssb-no": false,
++        "aes": true,
++        "mmx": true,
++        "rdpid": false,
++        "arat": true,
++        "gfni": false,
++        "ibrs-all": false,
++        "pause-filter": false,
++        "xsavec": false,
++        "intel-pt": false,
++        "kvm-asyncpf": false,
++        "perfctr-core": false,
++        "mpx": true,
++        "pbe": false,
++        "avx512cd": false,
++        "decodeassists": false,
++        "sse4.1": true,
++        "family": 6,
++        "wbnoinvd": false,
++        "avx512f": false,
++        "msr": true,
++        "mce": true,
++        "mca": true,
++        "xcrypt": false,
++        "min-level": 13,
++        "xgetbv1": true,
++        "cid": false,
++        "ds": false,
++        "fxsr": true,
++        "xsaveopt": true,
++        "xtpr": false,
++        "avx512vl": false,
++        "avx512-vpopcntdq": false,
++        "phe": false,
++        "extapic": false,
++        "3dnowprefetch": false,
++        "avx512vbmi2": false,
++        "cr8legacy": true,
++        "stibp": false,
++        "xcrypt-en": false,
++        "pn": false,
++        "rsba": false,
++        "dca": false,
++        "vendor": "AuthenticAMD",
++        "pku": true,
++        "smx": false,
++        "cmp-legacy": false,
++        "avx512-4fmaps": false,
++        "vmcb-clean": false,
++        "hle": false,
++        "3dnowext": true,
++        "amd-no-ssb": false,
++        "npt": true,
++        "rdctl-no": false,
++        "clwb": true,
++        "lbrv": false,
++        "adx": true,
++        "ss": true,
++        "pni": true,
++        "svm-lock": false,
++        "smep": true,
++        "smap": true,
++        "pfthreshold": false,
++        "x2apic": false,
++        "avx512vbmi": false,
++        "avx512vnni": false,
++        "flushbyasid": false,
++        "f16c": false,
++        "ace2-en": false,
++        "pae": true,
++        "pat": true,
++        "sse": true,
++        "phe-en": false,
++        "kvm-nopiodelay": false,
++        "tm": false,
++        "kvmclock-stable-bit": false,
++        "hypervisor": true,
++        "mds-no": false,
++        "pcommit": true,
++        "syscall": true,
++        "avx512dq": false,
++        "svm": true,
++        "invtsc": false,
++        "sse2": true,
++        "ssbd": false,
++        "est": false,
++        "avx512ifma": false,
++        "tm2": false,
++        "kvm-pv-eoi": false,
++        "kvm-pv-ipi": false,
++        "cx8": true,
++        "cldemote": false,
++        "kvm-mmu": false,
++        "sse4.2": true,
++        "pge": true,
++        "avx512bitalg": false,
++        "pdcm": false,
++        "model": 6,
++        "movbe": true,
++        "nrip-save": false,
++        "ssse3": true,
++        "sse4a": true,
++        "invpcid": false,
++        "pdpe1gb": true,
++        "tsc-deadline": false,
++        "skip-l1dfl-vmentry": false,
++        "fma": false,
++        "cx16": true,
++        "de": true,
++        "stepping": 3,
++        "xsave": true,
++        "clflush": true,
++        "skinit": false,
++        "tsc": true,
++        "tce": false,
++        "fpu": true,
++        "ds-cpl": false,
++        "ibs": false,
++        "fma4": false,
++        "la57": true,
++        "osvw": false,
++        "apic": true,
++        "pmm": false,
++        "spec-ctrl": false,
++        "tsc-adjust": false,
++        "kvm-steal-time": false,
++        "kvmclock": false,
++        "lwp": false,
++        "amd-ssbd": false,
++        "xop": false,
++        "ibpb": false,
++        "avx": false,
++        "movdiri": false,
++        "acpi": true,
++        "avx512bw": false,
++        "ace2": false,
++        "fsgsbase": true,
++        "ht": false,
++        "nx": true,
++        "pclmulqdq": true,
++        "mmxext": true,
++        "popcnt": true,
++        "vaes": false,
++        "movdir64b": false,
++        "xsaves": false,
++        "lm": true,
++        "umip": false,
++        "pse": true,
++        "avx2": false,
++        "sep": true,
++        "virt-ssbd": false,
++        "nodeid-msr": false,
++        "md-clear": false,
++        "misalignsse": false,
++        "min-xlevel": 2147483658,
++        "bmi1": true,
++        "bmi2": true,
++        "kvm-pv-unhalt": false,
++        "tsc-scale": false,
++        "topoext": false,
++        "clflushopt": true,
++        "monitor": true,
++        "avx512er": false,
++        "pmm-en": false,
++        "pcid": false,
++        "arch-capabilities": false,
++        "3dnow": true,
++        "erms": true,
++        "lahf-lm": true,
++        "vpclmulqdq": false,
++        "fxsr-opt": false,
++        "xstore": false,
++        "rtm": false,
++        "kvm-hint-dedicated": false,
++        "lmce": false,
++        "perfctr-nb": false,
++        "rdrand": true,
++        "rdseed": false,
++        "avx512-4vnniw": false,
++        "vme": false,
++        "vmx": false,
++        "dtes64": false,
++        "mtrr": true,
++        "rdtscp": true,
++        "pse36": true,
++        "kvm-pv-tlb-flush": false,
++        "tbm": false,
++        "wdt": false,
++        "model-id": "QEMU TCG CPU version 2.5+",
++        "sha-ni": false,
++        "abm": true,
++        "avx512pf": false,
++        "xstore-en": false
++      }
++    }
++  },
++  "id": "libvirt-5"
++}
++
++{
++  "execute": "query-cpu-model-expansion",
++  "arguments": {
++    "type": "full",
++    "model": {
++      "name": "base",
++      "props": {
++        "cmov": true,
++        "ia64": false,
++        "ssb-no": false,
++        "aes": true,
++        "mmx": true,
++        "rdpid": false,
++        "arat": true,
++        "gfni": false,
++        "ibrs-all": false,
++        "pause-filter": false,
++        "xsavec": false,
++        "intel-pt": false,
++        "kvm-asyncpf": false,
++        "perfctr-core": false,
++        "mpx": true,
++        "pbe": false,
++        "avx512cd": false,
++        "decodeassists": false,
++        "sse4.1": true,
++        "family": 6,
++        "wbnoinvd": false,
++        "avx512f": false,
++        "msr": true,
++        "mce": true,
++        "mca": true,
++        "xcrypt": false,
++        "min-level": 13,
++        "xgetbv1": true,
++        "cid": false,
++        "ds": false,
++        "fxsr": true,
++        "xsaveopt": true,
++        "xtpr": false,
++        "avx512vl": false,
++        "avx512-vpopcntdq": false,
++        "phe": false,
++        "extapic": false,
++        "3dnowprefetch": false,
++        "avx512vbmi2": false,
++        "cr8legacy": true,
++        "stibp": false,
++        "xcrypt-en": false,
++        "pn": false,
++        "rsba": false,
++        "dca": false,
++        "vendor": "AuthenticAMD",
++        "pku": true,
++        "smx": false,
++        "cmp-legacy": false,
++        "avx512-4fmaps": false,
++        "vmcb-clean": false,
++        "hle": false,
++        "3dnowext": true,
++        "amd-no-ssb": false,
++        "npt": true,
++        "rdctl-no": false,
++        "clwb": true,
++        "lbrv": false,
++        "adx": true,
++        "ss": true,
++        "pni": true,
++        "svm-lock": false,
++        "smep": true,
++        "smap": true,
++        "pfthreshold": false,
++        "x2apic": false,
++        "avx512vbmi": false,
++        "avx512vnni": false,
++        "flushbyasid": false,
++        "f16c": false,
++        "ace2-en": false,
++        "pae": true,
++        "pat": true,
++        "sse": true,
++        "phe-en": false,
++        "kvm-nopiodelay": false,
++        "tm": false,
++        "kvmclock-stable-bit": false,
++        "hypervisor": true,
++        "mds-no": false,
++        "pcommit": true,
++        "syscall": true,
++        "avx512dq": false,
++        "svm": true,
++        "invtsc": false,
++        "sse2": true,
++        "ssbd": false,
++        "est": false,
++        "avx512ifma": false,
++        "tm2": false,
++        "kvm-pv-eoi": false,
++        "kvm-pv-ipi": false,
++        "cx8": true,
++        "cldemote": false,
++        "kvm-mmu": false,
++        "sse4.2": true,
++        "pge": true,
++        "avx512bitalg": false,
++        "pdcm": false,
++        "model": 6,
++        "movbe": true,
++        "nrip-save": false,
++        "ssse3": true,
++        "sse4a": true,
++        "invpcid": false,
++        "pdpe1gb": true,
++        "tsc-deadline": false,
++        "skip-l1dfl-vmentry": false,
++        "fma": false,
++        "cx16": true,
++        "de": true,
++        "stepping": 3,
++        "xsave": true,
++        "clflush": true,
++        "skinit": false,
++        "tsc": true,
++        "tce": false,
++        "fpu": true,
++        "ds-cpl": false,
++        "ibs": false,
++        "fma4": false,
++        "la57": true,
++        "osvw": false,
++        "apic": true,
++        "pmm": false,
++        "spec-ctrl": false,
++        "tsc-adjust": false,
++        "kvm-steal-time": false,
++        "kvmclock": false,
++        "lwp": false,
++        "amd-ssbd": false,
++        "xop": false,
++        "ibpb": false,
++        "avx": false,
++        "movdiri": false,
++        "acpi": true,
++        "avx512bw": false,
++        "ace2": false,
++        "fsgsbase": true,
++        "ht": false,
++        "nx": true,
++        "pclmulqdq": true,
++        "mmxext": true,
++        "popcnt": true,
++        "vaes": false,
++        "movdir64b": false,
++        "xsaves": false,
++        "lm": true,
++        "umip": false,
++        "pse": true,
++        "avx2": false,
++        "sep": true,
++        "virt-ssbd": false,
++        "nodeid-msr": false,
++        "md-clear": false,
++        "misalignsse": false,
++        "min-xlevel": 2147483658,
++        "bmi1": true,
++        "bmi2": true,
++        "kvm-pv-unhalt": false,
++        "tsc-scale": false,
++        "topoext": false,
++        "clflushopt": true,
++        "monitor": true,
++        "avx512er": false,
++        "pmm-en": false,
++        "pcid": false,
++        "arch-capabilities": false,
++        "3dnow": true,
++        "erms": true,
++        "lahf-lm": true,
++        "vpclmulqdq": false,
++        "fxsr-opt": false,
++        "xstore": false,
++        "rtm": false,
++        "kvm-hint-dedicated": false,
++        "lmce": false,
++        "perfctr-nb": false,
++        "rdrand": true,
++        "rdseed": false,
++        "avx512-4vnniw": false,
++        "vme": false,
++        "vmx": false,
++        "dtes64": false,
++        "mtrr": true,
++        "rdtscp": true,
++        "pse36": true,
++        "kvm-pv-tlb-flush": false,
++        "tbm": false,
++        "wdt": false,
++        "model-id": "QEMU TCG CPU version 2.5+",
++        "sha-ni": false,
++        "abm": true,
++        "avx512pf": false,
++        "xstore-en": false
++      }
++    }
++  },
++  "id": "libvirt-6"
++}
++
++{
++  "return": {
++    "model": {
++      "name": "base",
++      "props": {
++        "phys-bits": 0,
++        "core-id": -1,
++        "xlevel": 2147483658,
++        "cmov": true,
++        "ia64": false,
++        "ssb-no": false,
++        "aes": true,
++        "mmx": true,
++        "rdpid": false,
++        "arat": true,
++        "gfni": false,
++        "ibrs-all": false,
++        "pause-filter": false,
++        "xsavec": false,
++        "intel-pt": false,
++        "hv-frequencies": false,
++        "tsc-frequency": 0,
++        "xd": true,
++        "x-intel-pt-auto-level": true,
++        "hv-vendor-id": "",
++        "kvm-asyncpf": false,
++        "kvm_asyncpf": false,
++        "perfctr_core": false,
++        "perfctr-core": false,
++        "mpx": true,
++        "pbe": false,
++        "decodeassists": false,
++        "avx512cd": false,
++        "sse4_1": true,
++        "sse4.1": true,
++        "sse4-1": true,
++        "family": 6,
++        "legacy-cache": true,
++        "host-phys-bits-limit": 0,
++        "vmware-cpuid-freq": true,
++        "wbnoinvd": false,
++        "avx512f": false,
++        "msr": true,
++        "mce": true,
++        "mca": true,
++        "hv-runtime": false,
++        "xcrypt": false,
++        "thread-id": -1,
++        "min-level": 13,
++        "xgetbv1": true,
++        "cid": false,
++        "hv-relaxed": false,
++        "hv-crash": false,
++        "ds": false,
++        "fxsr": true,
++        "xsaveopt": true,
++        "xtpr": false,
++        "hv-evmcs": false,
++        "avx512vl": false,
++        "avx512-vpopcntdq": false,
++        "phe": false,
++        "extapic": false,
++        "3dnowprefetch": false,
++        "avx512vbmi2": false,
++        "cr8legacy": true,
++        "stibp": false,
++        "cpuid-0xb": true,
++        "xcrypt-en": false,
++        "kvm_pv_eoi": false,
++        "apic-id": 4294967295,
++        "rsba": false,
++        "pn": false,
++        "dca": false,
++        "vendor": "AuthenticAMD",
++        "hv-ipi": false,
++        "pku": true,
++        "smx": false,
++        "cmp_legacy": false,
++        "cmp-legacy": false,
++        "node-id": -1,
++        "avx512-4fmaps": false,
++        "vmcb_clean": false,
++        "vmcb-clean": false,
++        "3dnowext": true,
++        "amd-no-ssb": false,
++        "hle": false,
++        "npt": true,
++        "rdctl-no": false,
++        "memory": "/machine/unattached/system[0]",
++        "clwb": true,
++        "lbrv": false,
++        "adx": true,
++        "ss": true,
++        "pni": true,
++        "svm_lock": false,
++        "svm-lock": false,
++        "pfthreshold": false,
++        "smep": true,
++        "smap": true,
++        "x2apic": false,
++        "avx512vbmi": false,
++        "avx512vnni": false,
++        "hv-stimer": false,
++        "x-hv-synic-kvm-only": false,
++        "i64": true,
++        "flushbyasid": false,
++        "f16c": false,
++        "ace2-en": false,
++        "pat": true,
++        "pae": true,
++        "sse": true,
++        "phe-en": false,
++        "kvm_nopiodelay": false,
++        "kvm-nopiodelay": false,
++        "tm": false,
++        "kvmclock-stable-bit": false,
++        "hypervisor": true,
++        "socket-id": -1,
++        "mds-no": false,
++        "pcommit": true,
++        "syscall": true,
++        "level": 13,
++        "avx512dq": false,
++        "x-migrate-smi-count": true,
++        "svm": true,
++        "full-cpuid-auto-level": true,
++        "hv-reset": false,
++        "invtsc": false,
++        "sse3": true,
++        "sse2": true,
++        "ssbd": false,
++        "est": false,
++        "avx512ifma": false,
++        "tm2": false,
++        "kvm-pv-ipi": false,
++        "kvm-pv-eoi": false,
++        "cx8": true,
++        "cldemote": false,
++        "hv-reenlightenment": false,
++        "kvm_mmu": false,
++        "kvm-mmu": false,
++        "sse4_2": true,
++        "sse4.2": true,
++        "sse4-2": true,
++        "pge": true,
++        "fill-mtrr-mask": true,
++        "avx512bitalg": false,
++        "nodeid_msr": false,
++        "pdcm": false,
++        "movbe": true,
++        "model": 6,
++        "nrip_save": false,
++        "nrip-save": false,
++        "kvm_pv_unhalt": false,
++        "ssse3": true,
++        "sse4a": true,
++        "invpcid": false,
++        "pdpe1gb": true,
++        "tsc-deadline": false,
++        "skip-l1dfl-vmentry": false,
++        "fma": false,
++        "cx16": true,
++        "de": true,
++        "enforce": false,
++        "stepping": 3,
++        "xsave": true,
++        "clflush": true,
++        "skinit": false,
++        "tsc": true,
++        "tce": false,
++        "fpu": true,
++        "ibs": false,
++        "ds_cpl": false,
++        "ds-cpl": false,
++        "host-phys-bits": false,
++        "fma4": false,
++        "la57": true,
++        "osvw": false,
++        "check": true,
++        "hv-spinlocks": -1,
++        "pmm": false,
++        "pmu": false,
++        "apic": true,
++        "spec-ctrl": false,
++        "min-xlevel2": 0,
++        "tsc-adjust": false,
++        "tsc_adjust": false,
++        "kvm-steal-time": false,
++        "kvm_steal_time": false,
++        "kvmclock": false,
++        "l3-cache": true,
++        "lwp": false,
++        "amd-ssbd": false,
++        "ibpb": false,
++        "xop": false,
++        "avx": false,
++        "movdiri": false,
++        "ace2": false,
++        "avx512bw": false,
++        "acpi": true,
++        "hv-vapic": false,
++        "fsgsbase": true,
++        "ht": false,
++        "nx": true,
++        "pclmulqdq": true,
++        "mmxext": true,
++        "vaes": false,
++        "popcnt": true,
++        "xsaves": false,
++        "movdir64b": false,
++        "tcg-cpuid": true,
++        "lm": true,
++        "umip": false,
++        "pse": true,
++        "avx2": false,
++        "sep": true,
++        "pclmuldq": true,
++        "virt-ssbd": false,
++        "x-hv-max-vps": -1,
++        "nodeid-msr": false,
++        "md-clear": false,
++        "kvm": true,
++        "misalignsse": false,
++        "min-xlevel": 2147483658,
++        "kvm-pv-unhalt": false,
++        "bmi2": true,
++        "bmi1": true,
++        "realized": false,
++        "tsc_scale": false,
++        "tsc-scale": false,
++        "topoext": false,
++        "hv-vpindex": false,
++        "xlevel2": 0,
++        "clflushopt": true,
++        "kvm-no-smi-migration": false,
++        "monitor": true,
++        "avx512er": false,
++        "pmm-en": false,
++        "pcid": false,
++        "arch-capabilities": false,
++        "3dnow": true,
++        "erms": true,
++        "lahf-lm": true,
++        "lahf_lm": true,
++        "vpclmulqdq": false,
++        "fxsr-opt": false,
++        "hv-synic": false,
++        "xstore": false,
++        "fxsr_opt": false,
++        "kvm-hint-dedicated": false,
++        "rtm": false,
++        "lmce": false,
++        "hv-time": false,
++        "perfctr-nb": false,
++        "perfctr_nb": false,
++        "ffxsr": false,
++        "hv-tlbflush": false,
++        "rdrand": true,
++        "rdseed": false,
++        "avx512-4vnniw": false,
++        "vmx": false,
++        "vme": false,
++        "dtes64": false,
++        "mtrr": true,
++        "rdtscp": true,
++        "pse36": true,
++        "kvm-pv-tlb-flush": false,
++        "tbm": false,
++        "wdt": false,
++        "pause_filter": false,
++        "sha-ni": false,
++        "model-id": "QEMU TCG CPU version 2.5+",
++        "abm": true,
++        "avx512pf": false,
++        "xstore-en": false
++      }
++    }
++  },
++  "id": "libvirt-6"
++}
+diff --git a/tests/qemucapabilitiesdata/caps_4.1.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_4.1.0.x86_64.xml
+new file mode 100644
+index 0000000000..93c5da537a
+--- /dev/null
++++ b/tests/qemucapabilitiesdata/caps_4.1.0.x86_64.xml
+@@ -0,0 +1,1424 @@
++<qemuCaps>
++  <qemuctime>0</qemuctime>
++  <selfctime>0</selfctime>
++  <selfvers>0</selfvers>
++  <usedQMP/>
++  <flag name='kvm'/>
++  <flag name='no-hpet'/>
++  <flag name='spice'/>
++  <flag name='boot-index'/>
++  <flag name='hda-duplex'/>
++  <flag name='ccid-emulated'/>
++  <flag name='ccid-passthru'/>
++  <flag name='virtio-tx-alg'/>
++  <flag name='virtio-blk-pci.ioeventfd'/>
++  <flag name='sga'/>
++  <flag name='virtio-blk-pci.event_idx'/>
++  <flag name='virtio-net-pci.event_idx'/>
++  <flag name='piix3-usb-uhci'/>
++  <flag name='piix4-usb-uhci'/>
++  <flag name='usb-ehci'/>
++  <flag name='ich9-usb-ehci1'/>
++  <flag name='vt82c686b-usb-uhci'/>
++  <flag name='pci-ohci'/>
++  <flag name='usb-redir'/>
++  <flag name='usb-hub'/>
++  <flag name='ich9-ahci'/>
++  <flag name='no-acpi'/>
++  <flag name='virtio-blk-pci.scsi'/>
++  <flag name='scsi-disk.channel'/>
++  <flag name='scsi-block'/>
++  <flag name='transaction'/>
++  <flag name='block-job-async'/>
++  <flag name='scsi-cd'/>
++  <flag name='ide-cd'/>
++  <flag name='hda-micro'/>
++  <flag name='dump-guest-memory'/>
++  <flag name='nec-usb-xhci'/>
++  <flag name='balloon-event'/>
++  <flag name='lsi'/>
++  <flag name='virtio-scsi-pci'/>
++  <flag name='blockio'/>
++  <flag name='disable-s3'/>
++  <flag name='disable-s4'/>
++  <flag name='usb-redir.filter'/>
++  <flag name='ide-drive.wwn'/>
++  <flag name='scsi-disk.wwn'/>
++  <flag name='seccomp-sandbox'/>
++  <flag name='reboot-timeout'/>
++  <flag name='seamless-migration'/>
++  <flag name='block-commit'/>
++  <flag name='vnc'/>
++  <flag name='drive-mirror'/>
++  <flag name='usb-redir.bootindex'/>
++  <flag name='usb-host.bootindex'/>
++  <flag name='blockdev-snapshot-sync'/>
++  <flag name='qxl'/>
++  <flag name='VGA'/>
++  <flag name='cirrus-vga'/>
++  <flag name='vmware-svga'/>
++  <flag name='device-video-primary'/>
++  <flag name='usb-serial'/>
++  <flag name='usb-net'/>
++  <flag name='add-fd'/>
++  <flag name='nbd-server'/>
++  <flag name='virtio-rng'/>
++  <flag name='rng-random'/>
++  <flag name='rng-egd'/>
++  <flag name='megasas'/>
++  <flag name='tpm-passthrough'/>
++  <flag name='tpm-tis'/>
++  <flag name='pci-bridge'/>
++  <flag name='vfio-pci'/>
++  <flag name='vfio-pci.bootindex'/>
++  <flag name='scsi-generic'/>
++  <flag name='scsi-generic.bootindex'/>
++  <flag name='mem-merge'/>
++  <flag name='vnc-websocket'/>
++  <flag name='drive-discard'/>
++  <flag name='mlock'/>
++  <flag name='device-del-event'/>
++  <flag name='dmi-to-pci-bridge'/>
++  <flag name='i440fx-pci-hole64-size'/>
++  <flag name='q35-pci-hole64-size'/>
++  <flag name='usb-storage'/>
++  <flag name='usb-storage.removable'/>
++  <flag name='ich9-intel-hda'/>
++  <flag name='kvm-pit-lost-tick-policy'/>
++  <flag name='boot-strict'/>
++  <flag name='pvpanic'/>
++  <flag name='spice-file-xfer-disable'/>
++  <flag name='spiceport'/>
++  <flag name='usb-kbd'/>
++  <flag name='msg-timestamp'/>
++  <flag name='active-commit'/>
++  <flag name='change-backing-file'/>
++  <flag name='memory-backend-ram'/>
++  <flag name='numa'/>
++  <flag name='memory-backend-file'/>
++  <flag name='usb-audio'/>
++  <flag name='rtc-reset-reinjection'/>
++  <flag name='splash-timeout'/>
++  <flag name='iothread'/>
++  <flag name='migrate-rdma'/>
++  <flag name='drive-iotune-max'/>
++  <flag name='VGA.vgamem_mb'/>
++  <flag name='vmware-svga.vgamem_mb'/>
++  <flag name='qxl.vgamem_mb'/>
++  <flag name='pc-dimm'/>
++  <flag name='machine-vmport-opt'/>
++  <flag name='aes-key-wrap'/>
++  <flag name='dea-key-wrap'/>
++  <flag name='pci-serial'/>
++  <flag name='vhost-user-multiqueue'/>
++  <flag name='migration-event'/>
++  <flag name='ioh3420'/>
++  <flag name='x3130-upstream'/>
++  <flag name='xio3130-downstream'/>
++  <flag name='rtl8139'/>
++  <flag name='e1000'/>
++  <flag name='virtio-net'/>
++  <flag name='gic-version'/>
++  <flag name='incoming-defer'/>
++  <flag name='virtio-gpu'/>
++  <flag name='virtio-gpu.virgl'/>
++  <flag name='virtio-keyboard'/>
++  <flag name='virtio-mouse'/>
++  <flag name='virtio-tablet'/>
++  <flag name='virtio-input-host'/>
++  <flag name='chardev-file-append'/>
++  <flag name='ich9-disable-s3'/>
++  <flag name='ich9-disable-s4'/>
++  <flag name='vserport-change-event'/>
++  <flag name='virtio-balloon-pci.deflate-on-oom'/>
++  <flag name='mptsas1068'/>
++  <flag name='spice-gl'/>
++  <flag name='qxl.vram64_size_mb'/>
++  <flag name='chardev-logfile'/>
++  <flag name='debug-threads'/>
++  <flag name='secret'/>
++  <flag name='pxb'/>
++  <flag name='pxb-pcie'/>
++  <flag name='device-tray-moved-event'/>
++  <flag name='nec-usb-xhci-ports'/>
++  <flag name='virtio-scsi-pci.iothread'/>
++  <flag name='name-guest'/>
++  <flag name='qxl.max_outputs'/>
++  <flag name='spice-unix'/>
++  <flag name='drive-detect-zeroes'/>
++  <flag name='tls-creds-x509'/>
++  <flag name='intel-iommu'/>
++  <flag name='smm'/>
++  <flag name='virtio-pci-disable-legacy'/>
++  <flag name='query-hotpluggable-cpus'/>
++  <flag name='virtio-net.rx_queue_size'/>
++  <flag name='virtio-vga'/>
++  <flag name='drive-iotune-max-length'/>
++  <flag name='ivshmem-plain'/>
++  <flag name='ivshmem-doorbell'/>
++  <flag name='query-qmp-schema'/>
++  <flag name='gluster.debug_level'/>
++  <flag name='vhost-scsi'/>
++  <flag name='drive-iotune-group'/>
++  <flag name='query-cpu-model-expansion'/>
++  <flag name='virtio-net.host_mtu'/>
++  <flag name='spice-rendernode'/>
++  <flag name='nvdimm'/>
++  <flag name='pcie-root-port'/>
++  <flag name='query-cpu-definitions'/>
++  <flag name='block-write-threshold'/>
++  <flag name='query-named-block-nodes'/>
++  <flag name='cpu-cache'/>
++  <flag name='qemu-xhci'/>
++  <flag name='kernel-irqchip'/>
++  <flag name='kernel-irqchip.split'/>
++  <flag name='intel-iommu.intremap'/>
++  <flag name='intel-iommu.caching-mode'/>
++  <flag name='intel-iommu.eim'/>
++  <flag name='intel-iommu.device-iotlb'/>
++  <flag name='virtio.iommu_platform'/>
++  <flag name='virtio.ats'/>
++  <flag name='loadparm'/>
++  <flag name='vnc-multi-servers'/>
++  <flag name='virtio-net.tx_queue_size'/>
++  <flag name='chardev-reconnect'/>
++  <flag name='virtio-gpu.max_outputs'/>
++  <flag name='vxhs'/>
++  <flag name='virtio-blk.num-queues'/>
++  <flag name='vmcoreinfo'/>
++  <flag name='numa.dist'/>
++  <flag name='disk-share-rw'/>
++  <flag name='iscsi.password-secret'/>
++  <flag name='isa-serial'/>
++  <flag name='dump-completed'/>
++  <flag name='qcow2-luks'/>
++  <flag name='pcie-pci-bridge'/>
++  <flag name='seccomp-blacklist'/>
++  <flag name='query-cpus-fast'/>
++  <flag name='disk-write-cache'/>
++  <flag name='nbd-tls'/>
++  <flag name='tpm-crb'/>
++  <flag name='pr-manager-helper'/>
++  <flag name='qom-list-properties'/>
++  <flag name='memory-backend-file.discard-data'/>
++  <flag name='sdl-gl'/>
++  <flag name='screendump_device'/>
++  <flag name='hda-output'/>
++  <flag name='blockdev-del'/>
++  <flag name='vmgenid'/>
++  <flag name='vhost-vsock'/>
++  <flag name='chardev-fd-pass'/>
++  <flag name='tpm-emulator'/>
++  <flag name='mch'/>
++  <flag name='mch.extended-tseg-mbytes'/>
++  <flag name='usb-storage.werror'/>
++  <flag name='egl-headless'/>
++  <flag name='vfio-pci.display'/>
++  <version>4000050</version>
++  <kvmVersion>0</kvmVersion>
++  <microcodeVersion>456805</microcodeVersion>
++  <package>v4.0.0-1173-g9c70209b63</package>
++  <arch>x86_64</arch>
++  <hostCPU type='kvm' model='base' migratability='yes'>
++    <property name='phys-bits' type='number' value='0'/>
++    <property name='core-id' type='number' value='-1'/>
++    <property name='xlevel' type='number' value='2147483656'/>
++    <property name='cmov' type='boolean' value='true' migratable='yes'/>
++    <property name='ia64' type='boolean' value='false'/>
++    <property name='ssb-no' type='boolean' value='false'/>
++    <property name='aes' type='boolean' value='true' migratable='yes'/>
++    <property name='mmx' type='boolean' value='true' migratable='yes'/>
++    <property name='rdpid' type='boolean' value='false'/>
++    <property name='arat' type='boolean' value='true' migratable='yes'/>
++    <property name='gfni' type='boolean' value='false'/>
++    <property name='ibrs-all' type='boolean' value='false'/>
++    <property name='pause-filter' type='boolean' value='false'/>
++    <property name='xsavec' type='boolean' value='true' migratable='yes'/>
++    <property name='intel-pt' type='boolean' value='false'/>
++    <property name='hv-frequencies' type='boolean' value='false'/>
++    <property name='tsc-frequency' type='number' value='0'/>
++    <property name='xd' type='boolean' value='true' migratable='yes'/>
++    <property name='x-intel-pt-auto-level' type='boolean' value='true' migratable='yes'/>
++    <property name='hv-vendor-id' type='string' value=''/>
++    <property name='kvm-asyncpf' type='boolean' value='true' migratable='yes'/>
++    <property name='kvm_asyncpf' type='boolean' value='true' migratable='yes'/>
++    <property name='perfctr_core' type='boolean' value='false'/>
++    <property name='perfctr-core' type='boolean' value='false'/>
++    <property name='mpx' type='boolean' value='true' migratable='yes'/>
++    <property name='pbe' type='boolean' value='false'/>
++    <property name='decodeassists' type='boolean' value='false'/>
++    <property name='avx512cd' type='boolean' value='false'/>
++    <property name='sse4_1' type='boolean' value='true' migratable='yes'/>
++    <property name='sse4.1' type='boolean' value='true' migratable='yes'/>
++    <property name='sse4-1' type='boolean' value='true' migratable='yes'/>
++    <property name='family' type='number' value='6'/>
++    <property name='legacy-cache' type='boolean' value='true' migratable='yes'/>
++    <property name='host-phys-bits-limit' type='number' value='0'/>
++    <property name='vmware-cpuid-freq' type='boolean' value='true' migratable='yes'/>
++    <property name='wbnoinvd' type='boolean' value='false'/>
++    <property name='avx512f' type='boolean' value='false'/>
++    <property name='msr' type='boolean' value='true' migratable='yes'/>
++    <property name='mce' type='boolean' value='true' migratable='yes'/>
++    <property name='mca' type='boolean' value='true' migratable='yes'/>
++    <property name='hv-runtime' type='boolean' value='false'/>
++    <property name='xcrypt' type='boolean' value='false'/>
++    <property name='thread-id' type='number' value='-1'/>
++    <property name='min-level' type='number' value='13'/>
++    <property name='xgetbv1' type='boolean' value='true' migratable='yes'/>
++    <property name='cid' type='boolean' value='false'/>
++    <property name='hv-relaxed' type='boolean' value='false'/>
++    <property name='hv-crash' type='boolean' value='false'/>
++    <property name='ds' type='boolean' value='false'/>
++    <property name='fxsr' type='boolean' value='true' migratable='yes'/>
++    <property name='xsaveopt' type='boolean' value='true' migratable='yes'/>
++    <property name='xtpr' type='boolean' value='false'/>
++    <property name='hv-evmcs' type='boolean' value='false'/>
++    <property name='avx512vl' type='boolean' value='false'/>
++    <property name='avx512-vpopcntdq' type='boolean' value='false'/>
++    <property name='phe' type='boolean' value='false'/>
++    <property name='extapic' type='boolean' value='false'/>
++    <property name='3dnowprefetch' type='boolean' value='true' migratable='yes'/>
++    <property name='avx512vbmi2' type='boolean' value='false'/>
++    <property name='cr8legacy' type='boolean' value='false'/>
++    <property name='stibp' type='boolean' value='false'/>
++    <property name='cpuid-0xb' type='boolean' value='true' migratable='yes'/>
++    <property name='xcrypt-en' type='boolean' value='false'/>
++    <property name='kvm_pv_eoi' type='boolean' value='true' migratable='yes'/>
++    <property name='apic-id' type='number' value='4294967295'/>
++    <property name='rsba' type='boolean' value='false'/>
++    <property name='pn' type='boolean' value='false'/>
++    <property name='dca' type='boolean' value='false'/>
++    <property name='vendor' type='string' value='GenuineIntel'/>
++    <property name='hv-ipi' type='boolean' value='false'/>
++    <property name='pku' type='boolean' value='false'/>
++    <property name='smx' type='boolean' value='false'/>
++    <property name='cmp_legacy' type='boolean' value='false'/>
++    <property name='cmp-legacy' type='boolean' value='false'/>
++    <property name='node-id' type='number' value='-1'/>
++    <property name='avx512-4fmaps' type='boolean' value='false'/>
++    <property name='vmcb_clean' type='boolean' value='false'/>
++    <property name='vmcb-clean' type='boolean' value='false'/>
++    <property name='3dnowext' type='boolean' value='false'/>
++    <property name='amd-no-ssb' type='boolean' value='false'/>
++    <property name='hle' type='boolean' value='true' migratable='yes'/>
++    <property name='npt' type='boolean' value='false'/>
++    <property name='rdctl-no' type='boolean' value='false'/>
++    <property name='memory' type='string' value='/machine/unattached/system[0]'/>
++    <property name='clwb' type='boolean' value='false'/>
++    <property name='lbrv' type='boolean' value='false'/>
++    <property name='adx' type='boolean' value='true' migratable='yes'/>
++    <property name='ss' type='boolean' value='true' migratable='yes'/>
++    <property name='pni' type='boolean' value='true' migratable='yes'/>
++    <property name='svm_lock' type='boolean' value='false'/>
++    <property name='svm-lock' type='boolean' value='false'/>
++    <property name='pfthreshold' type='boolean' value='false'/>
++    <property name='smep' type='boolean' value='true' migratable='yes'/>
++    <property name='smap' type='boolean' value='true' migratable='yes'/>
++    <property name='x2apic' type='boolean' value='true' migratable='yes'/>
++    <property name='avx512vbmi' type='boolean' value='false'/>
++    <property name='avx512vnni' type='boolean' value='false'/>
++    <property name='hv-stimer' type='boolean' value='false'/>
++    <property name='x-hv-synic-kvm-only' type='boolean' value='false'/>
++    <property name='i64' type='boolean' value='true' migratable='yes'/>
++    <property name='flushbyasid' type='boolean' value='false'/>
++    <property name='f16c' type='boolean' value='true' migratable='yes'/>
++    <property name='ace2-en' type='boolean' value='false'/>
++    <property name='pat' type='boolean' value='true' migratable='yes'/>
++    <property name='pae' type='boolean' value='true' migratable='yes'/>
++    <property name='sse' type='boolean' value='true' migratable='yes'/>
++    <property name='phe-en' type='boolean' value='false'/>
++    <property name='kvm_nopiodelay' type='boolean' value='true' migratable='yes'/>
++    <property name='kvm-nopiodelay' type='boolean' value='true' migratable='yes'/>
++    <property name='tm' type='boolean' value='false'/>
++    <property name='kvmclock-stable-bit' type='boolean' value='true' migratable='yes'/>
++    <property name='hypervisor' type='boolean' value='true' migratable='yes'/>
++    <property name='socket-id' type='number' value='-1'/>
++    <property name='mds-no' type='boolean' value='false'/>
++    <property name='pcommit' type='boolean' value='false'/>
++    <property name='syscall' type='boolean' value='true' migratable='yes'/>
++    <property name='level' type='number' value='13'/>
++    <property name='avx512dq' type='boolean' value='false'/>
++    <property name='x-migrate-smi-count' type='boolean' value='true' migratable='yes'/>
++    <property name='svm' type='boolean' value='false'/>
++    <property name='full-cpuid-auto-level' type='boolean' value='true' migratable='yes'/>
++    <property name='hv-reset' type='boolean' value='false'/>
++    <property name='invtsc' type='boolean' value='false'/>
++    <property name='sse3' type='boolean' value='true' migratable='yes'/>
++    <property name='sse2' type='boolean' value='true' migratable='yes'/>
++    <property name='ssbd' type='boolean' value='false'/>
++    <property name='est' type='boolean' value='false'/>
++    <property name='avx512ifma' type='boolean' value='false'/>
++    <property name='tm2' type='boolean' value='false'/>
++    <property name='kvm-pv-ipi' type='boolean' value='true' migratable='yes'/>
++    <property name='kvm-pv-eoi' type='boolean' value='true' migratable='yes'/>
++    <property name='cx8' type='boolean' value='true' migratable='yes'/>
++    <property name='cldemote' type='boolean' value='false'/>
++    <property name='hv-reenlightenment' type='boolean' value='false'/>
++    <property name='kvm_mmu' type='boolean' value='false'/>
++    <property name='kvm-mmu' type='boolean' value='false'/>
++    <property name='sse4_2' type='boolean' value='true' migratable='yes'/>
++    <property name='sse4.2' type='boolean' value='true' migratable='yes'/>
++    <property name='sse4-2' type='boolean' value='true' migratable='yes'/>
++    <property name='pge' type='boolean' value='true' migratable='yes'/>
++    <property name='fill-mtrr-mask' type='boolean' value='true' migratable='yes'/>
++    <property name='avx512bitalg' type='boolean' value='false'/>
++    <property name='nodeid_msr' type='boolean' value='false'/>
++    <property name='pdcm' type='boolean' value='false'/>
++    <property name='movbe' type='boolean' value='true' migratable='yes'/>
++    <property name='model' type='number' value='94'/>
++    <property name='nrip_save' type='boolean' value='false'/>
++    <property name='nrip-save' type='boolean' value='false'/>
++    <property name='kvm_pv_unhalt' type='boolean' value='true' migratable='yes'/>
++    <property name='ssse3' type='boolean' value='true' migratable='yes'/>
++    <property name='sse4a' type='boolean' value='false'/>
++    <property name='invpcid' type='boolean' value='true' migratable='yes'/>
++    <property name='pdpe1gb' type='boolean' value='true' migratable='yes'/>
++    <property name='tsc-deadline' type='boolean' value='true' migratable='yes'/>
++    <property name='skip-l1dfl-vmentry' type='boolean' value='true' migratable='yes'/>
++    <property name='fma' type='boolean' value='true' migratable='yes'/>
++    <property name='cx16' type='boolean' value='true' migratable='yes'/>
++    <property name='de' type='boolean' value='true' migratable='yes'/>
++    <property name='enforce' type='boolean' value='false'/>
++    <property name='stepping' type='number' value='3'/>
++    <property name='xsave' type='boolean' value='true' migratable='yes'/>
++    <property name='clflush' type='boolean' value='true' migratable='yes'/>
++    <property name='skinit' type='boolean' value='false'/>
++    <property name='tsc' type='boolean' value='true' migratable='yes'/>
++    <property name='tce' type='boolean' value='false'/>
++    <property name='fpu' type='boolean' value='true' migratable='yes'/>
++    <property name='ibs' type='boolean' value='false'/>
++    <property name='ds_cpl' type='boolean' value='false'/>
++    <property name='ds-cpl' type='boolean' value='false'/>
++    <property name='host-phys-bits' type='boolean' value='false'/>
++    <property name='fma4' type='boolean' value='false'/>
++    <property name='la57' type='boolean' value='false'/>
++    <property name='osvw' type='boolean' value='false'/>
++    <property name='check' type='boolean' value='true' migratable='yes'/>
++    <property name='hv-spinlocks' type='number' value='-1'/>
++    <property name='pmm' type='boolean' value='false'/>
++    <property name='pmu' type='boolean' value='false'/>
++    <property name='apic' type='boolean' value='true' migratable='yes'/>
++    <property name='spec-ctrl' type='boolean' value='false'/>
++    <property name='min-xlevel2' type='number' value='0'/>
++    <property name='tsc-adjust' type='boolean' value='true' migratable='yes'/>
++    <property name='tsc_adjust' type='boolean' value='true' migratable='yes'/>
++    <property name='kvm-steal-time' type='boolean' value='true' migratable='yes'/>
++    <property name='kvm_steal_time' type='boolean' value='true' migratable='yes'/>
++    <property name='kvmclock' type='boolean' value='true' migratable='yes'/>
++    <property name='l3-cache' type='boolean' value='true' migratable='yes'/>
++    <property name='lwp' type='boolean' value='false'/>
++    <property name='amd-ssbd' type='boolean' value='false'/>
++    <property name='ibpb' type='boolean' value='false'/>
++    <property name='xop' type='boolean' value='false'/>
++    <property name='avx' type='boolean' value='true' migratable='yes'/>
++    <property name='movdiri' type='boolean' value='false'/>
++    <property name='ace2' type='boolean' value='false'/>
++    <property name='avx512bw' type='boolean' value='false'/>
++    <property name='acpi' type='boolean' value='false'/>
++    <property name='hv-vapic' type='boolean' value='false'/>
++    <property name='fsgsbase' type='boolean' value='true' migratable='yes'/>
++    <property name='ht' type='boolean' value='false'/>
++    <property name='nx' type='boolean' value='true' migratable='yes'/>
++    <property name='pclmulqdq' type='boolean' value='true' migratable='yes'/>
++    <property name='mmxext' type='boolean' value='false'/>
++    <property name='vaes' type='boolean' value='false'/>
++    <property name='popcnt' type='boolean' value='true' migratable='yes'/>
++    <property name='xsaves' type='boolean' value='true' migratable='yes'/>
++    <property name='movdir64b' type='boolean' value='false'/>
++    <property name='tcg-cpuid' type='boolean' value='true' migratable='yes'/>
++    <property name='lm' type='boolean' value='true' migratable='yes'/>
++    <property name='umip' type='boolean' value='true' migratable='yes'/>
++    <property name='pse' type='boolean' value='true' migratable='yes'/>
++    <property name='avx2' type='boolean' value='true' migratable='yes'/>
++    <property name='sep' type='boolean' value='true' migratable='yes'/>
++    <property name='pclmuldq' type='boolean' value='true' migratable='yes'/>
++    <property name='virt-ssbd' type='boolean' value='false'/>
++    <property name='x-hv-max-vps' type='number' value='-1'/>
++    <property name='nodeid-msr' type='boolean' value='false'/>
++    <property name='md-clear' type='boolean' value='false'/>
++    <property name='kvm' type='boolean' value='true' migratable='yes'/>
++    <property name='misalignsse' type='boolean' value='false'/>
++    <property name='min-xlevel' type='number' value='2147483656'/>
++    <property name='kvm-pv-unhalt' type='boolean' value='true' migratable='yes'/>
++    <property name='bmi2' type='boolean' value='true' migratable='yes'/>
++    <property name='bmi1' type='boolean' value='true' migratable='yes'/>
++    <property name='realized' type='boolean' value='false'/>
++    <property name='tsc_scale' type='boolean' value='false'/>
++    <property name='tsc-scale' type='boolean' value='false'/>
++    <property name='topoext' type='boolean' value='false'/>
++    <property name='hv-vpindex' type='boolean' value='false'/>
++    <property name='xlevel2' type='number' value='0'/>
++    <property name='clflushopt' type='boolean' value='true' migratable='yes'/>
++    <property name='kvm-no-smi-migration' type='boolean' value='false'/>
++    <property name='monitor' type='boolean' value='false'/>
++    <property name='avx512er' type='boolean' value='false'/>
++    <property name='pmm-en' type='boolean' value='false'/>
++    <property name='pcid' type='boolean' value='true' migratable='yes'/>
++    <property name='arch-capabilities' type='boolean' value='true' migratable='yes'/>
++    <property name='3dnow' type='boolean' value='false'/>
++    <property name='erms' type='boolean' value='true' migratable='yes'/>
++    <property name='lahf-lm' type='boolean' value='true' migratable='yes'/>
++    <property name='lahf_lm' type='boolean' value='true' migratable='yes'/>
++    <property name='vpclmulqdq' type='boolean' value='false'/>
++    <property name='fxsr-opt' type='boolean' value='false'/>
++    <property name='hv-synic' type='boolean' value='false'/>
++    <property name='xstore' type='boolean' value='false'/>
++    <property name='fxsr_opt' type='boolean' value='false'/>
++    <property name='kvm-hint-dedicated' type='boolean' value='false'/>
++    <property name='rtm' type='boolean' value='true' migratable='yes'/>
++    <property name='lmce' type='boolean' value='true' migratable='yes'/>
++    <property name='hv-time' type='boolean' value='false'/>
++    <property name='perfctr-nb' type='boolean' value='false'/>
++    <property name='perfctr_nb' type='boolean' value='false'/>
++    <property name='ffxsr' type='boolean' value='false'/>
++    <property name='hv-tlbflush' type='boolean' value='false'/>
++    <property name='rdrand' type='boolean' value='true' migratable='yes'/>
++    <property name='rdseed' type='boolean' value='true' migratable='yes'/>
++    <property name='avx512-4vnniw' type='boolean' value='false'/>
++    <property name='vmx' type='boolean' value='true' migratable='yes'/>
++    <property name='vme' type='boolean' value='true' migratable='yes'/>
++    <property name='dtes64' type='boolean' value='false'/>
++    <property name='mtrr' type='boolean' value='true' migratable='yes'/>
++    <property name='rdtscp' type='boolean' value='true' migratable='yes'/>
++    <property name='pse36' type='boolean' value='true' migratable='yes'/>
++    <property name='kvm-pv-tlb-flush' type='boolean' value='true' migratable='yes'/>
++    <property name='tbm' type='boolean' value='false'/>
++    <property name='wdt' type='boolean' value='false'/>
++    <property name='pause_filter' type='boolean' value='false'/>
++    <property name='sha-ni' type='boolean' value='false'/>
++    <property name='model-id' type='string' value='Intel(R) Xeon(R) CPU E3-1245 v5 @ 3.50GHz'/>
++    <property name='abm' type='boolean' value='true' migratable='yes'/>
++    <property name='avx512pf' type='boolean' value='false'/>
++    <property name='xstore-en' type='boolean' value='false'/>
++  </hostCPU>
++  <hostCPU type='tcg' model='base' migratability='yes'>
++    <property name='phys-bits' type='number' value='0'/>
++    <property name='core-id' type='number' value='-1'/>
++    <property name='xlevel' type='number' value='2147483658'/>
++    <property name='cmov' type='boolean' value='true' migratable='yes'/>
++    <property name='ia64' type='boolean' value='false'/>
++    <property name='ssb-no' type='boolean' value='false'/>
++    <property name='aes' type='boolean' value='true' migratable='yes'/>
++    <property name='mmx' type='boolean' value='true' migratable='yes'/>
++    <property name='rdpid' type='boolean' value='false'/>
++    <property name='arat' type='boolean' value='true' migratable='yes'/>
++    <property name='gfni' type='boolean' value='false'/>
++    <property name='ibrs-all' type='boolean' value='false'/>
++    <property name='pause-filter' type='boolean' value='false'/>
++    <property name='xsavec' type='boolean' value='false'/>
++    <property name='intel-pt' type='boolean' value='false'/>
++    <property name='hv-frequencies' type='boolean' value='false'/>
++    <property name='tsc-frequency' type='number' value='0'/>
++    <property name='xd' type='boolean' value='true' migratable='yes'/>
++    <property name='x-intel-pt-auto-level' type='boolean' value='true' migratable='yes'/>
++    <property name='hv-vendor-id' type='string' value=''/>
++    <property name='kvm-asyncpf' type='boolean' value='false'/>
++    <property name='kvm_asyncpf' type='boolean' value='false'/>
++    <property name='perfctr_core' type='boolean' value='false'/>
++    <property name='perfctr-core' type='boolean' value='false'/>
++    <property name='mpx' type='boolean' value='true' migratable='yes'/>
++    <property name='pbe' type='boolean' value='false'/>
++    <property name='decodeassists' type='boolean' value='false'/>
++    <property name='avx512cd' type='boolean' value='false'/>
++    <property name='sse4_1' type='boolean' value='true' migratable='yes'/>
++    <property name='sse4.1' type='boolean' value='true' migratable='yes'/>
++    <property name='sse4-1' type='boolean' value='true' migratable='yes'/>
++    <property name='family' type='number' value='6'/>
++    <property name='legacy-cache' type='boolean' value='true' migratable='yes'/>
++    <property name='host-phys-bits-limit' type='number' value='0'/>
++    <property name='vmware-cpuid-freq' type='boolean' value='true' migratable='yes'/>
++    <property name='wbnoinvd' type='boolean' value='false'/>
++    <property name='avx512f' type='boolean' value='false'/>
++    <property name='msr' type='boolean' value='true' migratable='yes'/>
++    <property name='mce' type='boolean' value='true' migratable='yes'/>
++    <property name='mca' type='boolean' value='true' migratable='yes'/>
++    <property name='hv-runtime' type='boolean' value='false'/>
++    <property name='xcrypt' type='boolean' value='false'/>
++    <property name='thread-id' type='number' value='-1'/>
++    <property name='min-level' type='number' value='13'/>
++    <property name='xgetbv1' type='boolean' value='true' migratable='yes'/>
++    <property name='cid' type='boolean' value='false'/>
++    <property name='hv-relaxed' type='boolean' value='false'/>
++    <property name='hv-crash' type='boolean' value='false'/>
++    <property name='ds' type='boolean' value='false'/>
++    <property name='fxsr' type='boolean' value='true' migratable='yes'/>
++    <property name='xsaveopt' type='boolean' value='true' migratable='yes'/>
++    <property name='xtpr' type='boolean' value='false'/>
++    <property name='hv-evmcs' type='boolean' value='false'/>
++    <property name='avx512vl' type='boolean' value='false'/>
++    <property name='avx512-vpopcntdq' type='boolean' value='false'/>
++    <property name='phe' type='boolean' value='false'/>
++    <property name='extapic' type='boolean' value='false'/>
++    <property name='3dnowprefetch' type='boolean' value='false'/>
++    <property name='avx512vbmi2' type='boolean' value='false'/>
++    <property name='cr8legacy' type='boolean' value='true' migratable='yes'/>
++    <property name='stibp' type='boolean' value='false'/>
++    <property name='cpuid-0xb' type='boolean' value='true' migratable='yes'/>
++    <property name='xcrypt-en' type='boolean' value='false'/>
++    <property name='kvm_pv_eoi' type='boolean' value='false'/>
++    <property name='apic-id' type='number' value='4294967295'/>
++    <property name='rsba' type='boolean' value='false'/>
++    <property name='pn' type='boolean' value='false'/>
++    <property name='dca' type='boolean' value='false'/>
++    <property name='vendor' type='string' value='AuthenticAMD'/>
++    <property name='hv-ipi' type='boolean' value='false'/>
++    <property name='pku' type='boolean' value='true' migratable='yes'/>
++    <property name='smx' type='boolean' value='false'/>
++    <property name='cmp_legacy' type='boolean' value='false'/>
++    <property name='cmp-legacy' type='boolean' value='false'/>
++    <property name='node-id' type='number' value='-1'/>
++    <property name='avx512-4fmaps' type='boolean' value='false'/>
++    <property name='vmcb_clean' type='boolean' value='false'/>
++    <property name='vmcb-clean' type='boolean' value='false'/>
++    <property name='3dnowext' type='boolean' value='true' migratable='yes'/>
++    <property name='amd-no-ssb' type='boolean' value='false'/>
++    <property name='hle' type='boolean' value='false'/>
++    <property name='npt' type='boolean' value='true' migratable='yes'/>
++    <property name='rdctl-no' type='boolean' value='false'/>
++    <property name='memory' type='string' value='/machine/unattached/system[0]'/>
++    <property name='clwb' type='boolean' value='true' migratable='yes'/>
++    <property name='lbrv' type='boolean' value='false'/>
++    <property name='adx' type='boolean' value='true' migratable='yes'/>
++    <property name='ss' type='boolean' value='true' migratable='yes'/>
++    <property name='pni' type='boolean' value='true' migratable='yes'/>
++    <property name='svm_lock' type='boolean' value='false'/>
++    <property name='svm-lock' type='boolean' value='false'/>
++    <property name='pfthreshold' type='boolean' value='false'/>
++    <property name='smep' type='boolean' value='true' migratable='yes'/>
++    <property name='smap' type='boolean' value='true' migratable='yes'/>
++    <property name='x2apic' type='boolean' value='false'/>
++    <property name='avx512vbmi' type='boolean' value='false'/>
++    <property name='avx512vnni' type='boolean' value='false'/>
++    <property name='hv-stimer' type='boolean' value='false'/>
++    <property name='x-hv-synic-kvm-only' type='boolean' value='false'/>
++    <property name='i64' type='boolean' value='true' migratable='yes'/>
++    <property name='flushbyasid' type='boolean' value='false'/>
++    <property name='f16c' type='boolean' value='false'/>
++    <property name='ace2-en' type='boolean' value='false'/>
++    <property name='pat' type='boolean' value='true' migratable='yes'/>
++    <property name='pae' type='boolean' value='true' migratable='yes'/>
++    <property name='sse' type='boolean' value='true' migratable='yes'/>
++    <property name='phe-en' type='boolean' value='false'/>
++    <property name='kvm_nopiodelay' type='boolean' value='false'/>
++    <property name='kvm-nopiodelay' type='boolean' value='false'/>
++    <property name='tm' type='boolean' value='false'/>
++    <property name='kvmclock-stable-bit' type='boolean' value='false'/>
++    <property name='hypervisor' type='boolean' value='true' migratable='yes'/>
++    <property name='socket-id' type='number' value='-1'/>
++    <property name='mds-no' type='boolean' value='false'/>
++    <property name='pcommit' type='boolean' value='true' migratable='yes'/>
++    <property name='syscall' type='boolean' value='true' migratable='yes'/>
++    <property name='level' type='number' value='13'/>
++    <property name='avx512dq' type='boolean' value='false'/>
++    <property name='x-migrate-smi-count' type='boolean' value='true' migratable='yes'/>
++    <property name='svm' type='boolean' value='true' migratable='yes'/>
++    <property name='full-cpuid-auto-level' type='boolean' value='true' migratable='yes'/>
++    <property name='hv-reset' type='boolean' value='false'/>
++    <property name='invtsc' type='boolean' value='false'/>
++    <property name='sse3' type='boolean' value='true' migratable='yes'/>
++    <property name='sse2' type='boolean' value='true' migratable='yes'/>
++    <property name='ssbd' type='boolean' value='false'/>
++    <property name='est' type='boolean' value='false'/>
++    <property name='avx512ifma' type='boolean' value='false'/>
++    <property name='tm2' type='boolean' value='false'/>
++    <property name='kvm-pv-ipi' type='boolean' value='false'/>
++    <property name='kvm-pv-eoi' type='boolean' value='false'/>
++    <property name='cx8' type='boolean' value='true' migratable='yes'/>
++    <property name='cldemote' type='boolean' value='false'/>
++    <property name='hv-reenlightenment' type='boolean' value='false'/>
++    <property name='kvm_mmu' type='boolean' value='false'/>
++    <property name='kvm-mmu' type='boolean' value='false'/>
++    <property name='sse4_2' type='boolean' value='true' migratable='yes'/>
++    <property name='sse4.2' type='boolean' value='true' migratable='yes'/>
++    <property name='sse4-2' type='boolean' value='true' migratable='yes'/>
++    <property name='pge' type='boolean' value='true' migratable='yes'/>
++    <property name='fill-mtrr-mask' type='boolean' value='true' migratable='yes'/>
++    <property name='avx512bitalg' type='boolean' value='false'/>
++    <property name='nodeid_msr' type='boolean' value='false'/>
++    <property name='pdcm' type='boolean' value='false'/>
++    <property name='movbe' type='boolean' value='true' migratable='yes'/>
++    <property name='model' type='number' value='6'/>
++    <property name='nrip_save' type='boolean' value='false'/>
++    <property name='nrip-save' type='boolean' value='false'/>
++    <property name='kvm_pv_unhalt' type='boolean' value='false'/>
++    <property name='ssse3' type='boolean' value='true' migratable='yes'/>
++    <property name='sse4a' type='boolean' value='true' migratable='yes'/>
++    <property name='invpcid' type='boolean' value='false'/>
++    <property name='pdpe1gb' type='boolean' value='true' migratable='yes'/>
++    <property name='tsc-deadline' type='boolean' value='false'/>
++    <property name='skip-l1dfl-vmentry' type='boolean' value='false'/>
++    <property name='fma' type='boolean' value='false'/>
++    <property name='cx16' type='boolean' value='true' migratable='yes'/>
++    <property name='de' type='boolean' value='true' migratable='yes'/>
++    <property name='enforce' type='boolean' value='false'/>
++    <property name='stepping' type='number' value='3'/>
++    <property name='xsave' type='boolean' value='true' migratable='yes'/>
++    <property name='clflush' type='boolean' value='true' migratable='yes'/>
++    <property name='skinit' type='boolean' value='false'/>
++    <property name='tsc' type='boolean' value='true' migratable='yes'/>
++    <property name='tce' type='boolean' value='false'/>
++    <property name='fpu' type='boolean' value='true' migratable='yes'/>
++    <property name='ibs' type='boolean' value='false'/>
++    <property name='ds_cpl' type='boolean' value='false'/>
++    <property name='ds-cpl' type='boolean' value='false'/>
++    <property name='host-phys-bits' type='boolean' value='false'/>
++    <property name='fma4' type='boolean' value='false'/>
++    <property name='la57' type='boolean' value='true' migratable='yes'/>
++    <property name='osvw' type='boolean' value='false'/>
++    <property name='check' type='boolean' value='true' migratable='yes'/>
++    <property name='hv-spinlocks' type='number' value='-1'/>
++    <property name='pmm' type='boolean' value='false'/>
++    <property name='pmu' type='boolean' value='false'/>
++    <property name='apic' type='boolean' value='true' migratable='yes'/>
++    <property name='spec-ctrl' type='boolean' value='false'/>
++    <property name='min-xlevel2' type='number' value='0'/>
++    <property name='tsc-adjust' type='boolean' value='false'/>
++    <property name='tsc_adjust' type='boolean' value='false'/>
++    <property name='kvm-steal-time' type='boolean' value='false'/>
++    <property name='kvm_steal_time' type='boolean' value='false'/>
++    <property name='kvmclock' type='boolean' value='false'/>
++    <property name='l3-cache' type='boolean' value='true' migratable='yes'/>
++    <property name='lwp' type='boolean' value='false'/>
++    <property name='amd-ssbd' type='boolean' value='false'/>
++    <property name='ibpb' type='boolean' value='false'/>
++    <property name='xop' type='boolean' value='false'/>
++    <property name='avx' type='boolean' value='false'/>
++    <property name='movdiri' type='boolean' value='false'/>
++    <property name='ace2' type='boolean' value='false'/>
++    <property name='avx512bw' type='boolean' value='false'/>
++    <property name='acpi' type='boolean' value='true' migratable='yes'/>
++    <property name='hv-vapic' type='boolean' value='false'/>
++    <property name='fsgsbase' type='boolean' value='true' migratable='yes'/>
++    <property name='ht' type='boolean' value='false'/>
++    <property name='nx' type='boolean' value='true' migratable='yes'/>
++    <property name='pclmulqdq' type='boolean' value='true' migratable='yes'/>
++    <property name='mmxext' type='boolean' value='true' migratable='yes'/>
++    <property name='vaes' type='boolean' value='false'/>
++    <property name='popcnt' type='boolean' value='true' migratable='yes'/>
++    <property name='xsaves' type='boolean' value='false'/>
++    <property name='movdir64b' type='boolean' value='false'/>
++    <property name='tcg-cpuid' type='boolean' value='true' migratable='yes'/>
++    <property name='lm' type='boolean' value='true' migratable='yes'/>
++    <property name='umip' type='boolean' value='false'/>
++    <property name='pse' type='boolean' value='true' migratable='yes'/>
++    <property name='avx2' type='boolean' value='false'/>
++    <property name='sep' type='boolean' value='true' migratable='yes'/>
++    <property name='pclmuldq' type='boolean' value='true' migratable='yes'/>
++    <property name='virt-ssbd' type='boolean' value='false'/>
++    <property name='x-hv-max-vps' type='number' value='-1'/>
++    <property name='nodeid-msr' type='boolean' value='false'/>
++    <property name='md-clear' type='boolean' value='false'/>
++    <property name='kvm' type='boolean' value='true' migratable='yes'/>
++    <property name='misalignsse' type='boolean' value='false'/>
++    <property name='min-xlevel' type='number' value='2147483658'/>
++    <property name='kvm-pv-unhalt' type='boolean' value='false'/>
++    <property name='bmi2' type='boolean' value='true' migratable='yes'/>
++    <property name='bmi1' type='boolean' value='true' migratable='yes'/>
++    <property name='realized' type='boolean' value='false'/>
++    <property name='tsc_scale' type='boolean' value='false'/>
++    <property name='tsc-scale' type='boolean' value='false'/>
++    <property name='topoext' type='boolean' value='false'/>
++    <property name='hv-vpindex' type='boolean' value='false'/>
++    <property name='xlevel2' type='number' value='0'/>
++    <property name='clflushopt' type='boolean' value='true' migratable='yes'/>
++    <property name='kvm-no-smi-migration' type='boolean' value='false'/>
++    <property name='monitor' type='boolean' value='true' migratable='yes'/>
++    <property name='avx512er' type='boolean' value='false'/>
++    <property name='pmm-en' type='boolean' value='false'/>
++    <property name='pcid' type='boolean' value='false'/>
++    <property name='arch-capabilities' type='boolean' value='false'/>
++    <property name='3dnow' type='boolean' value='true' migratable='yes'/>
++    <property name='erms' type='boolean' value='true' migratable='yes'/>
++    <property name='lahf-lm' type='boolean' value='true' migratable='yes'/>
++    <property name='lahf_lm' type='boolean' value='true' migratable='yes'/>
++    <property name='vpclmulqdq' type='boolean' value='false'/>
++    <property name='fxsr-opt' type='boolean' value='false'/>
++    <property name='hv-synic' type='boolean' value='false'/>
++    <property name='xstore' type='boolean' value='false'/>
++    <property name='fxsr_opt' type='boolean' value='false'/>
++    <property name='kvm-hint-dedicated' type='boolean' value='false'/>
++    <property name='rtm' type='boolean' value='false'/>
++    <property name='lmce' type='boolean' value='false'/>
++    <property name='hv-time' type='boolean' value='false'/>
++    <property name='perfctr-nb' type='boolean' value='false'/>
++    <property name='perfctr_nb' type='boolean' value='false'/>
++    <property name='ffxsr' type='boolean' value='false'/>
++    <property name='hv-tlbflush' type='boolean' value='false'/>
++    <property name='rdrand' type='boolean' value='true' migratable='yes'/>
++    <property name='rdseed' type='boolean' value='false'/>
++    <property name='avx512-4vnniw' type='boolean' value='false'/>
++    <property name='vmx' type='boolean' value='false'/>
++    <property name='vme' type='boolean' value='false'/>
++    <property name='dtes64' type='boolean' value='false'/>
++    <property name='mtrr' type='boolean' value='true' migratable='yes'/>
++    <property name='rdtscp' type='boolean' value='true' migratable='yes'/>
++    <property name='pse36' type='boolean' value='true' migratable='yes'/>
++    <property name='kvm-pv-tlb-flush' type='boolean' value='false'/>
++    <property name='tbm' type='boolean' value='false'/>
++    <property name='wdt' type='boolean' value='false'/>
++    <property name='pause_filter' type='boolean' value='false'/>
++    <property name='sha-ni' type='boolean' value='false'/>
++    <property name='model-id' type='string' value='QEMU TCG CPU version 2.5+'/>
++    <property name='abm' type='boolean' value='true' migratable='yes'/>
++    <property name='avx512pf' type='boolean' value='false'/>
++    <property name='xstore-en' type='boolean' value='false'/>
++  </hostCPU>
++  <cpu type='kvm' name='max' usable='yes'/>
++  <cpu type='kvm' name='host' usable='yes'/>
++  <cpu type='kvm' name='base' usable='yes'/>
++  <cpu type='kvm' name='qemu64' usable='yes'/>
++  <cpu type='kvm' name='qemu32' usable='yes'/>
++  <cpu type='kvm' name='phenom' usable='no'>
++    <blocker name='mmxext'/>
++    <blocker name='fxsr-opt'/>
++    <blocker name='3dnowext'/>
++    <blocker name='3dnow'/>
++    <blocker name='sse4a'/>
++    <blocker name='npt'/>
++  </cpu>
++  <cpu type='kvm' name='pentium3' usable='yes'/>
++  <cpu type='kvm' name='pentium2' usable='yes'/>
++  <cpu type='kvm' name='pentium' usable='yes'/>
++  <cpu type='kvm' name='n270' usable='yes'/>
++  <cpu type='kvm' name='kvm64' usable='yes'/>
++  <cpu type='kvm' name='kvm32' usable='yes'/>
++  <cpu type='kvm' name='coreduo' usable='yes'/>
++  <cpu type='kvm' name='core2duo' usable='yes'/>
++  <cpu type='kvm' name='athlon' usable='no'>
++    <blocker name='mmxext'/>
++    <blocker name='3dnowext'/>
++    <blocker name='3dnow'/>
++  </cpu>
++  <cpu type='kvm' name='Westmere-IBRS' usable='no'>
++    <blocker name='spec-ctrl'/>
++  </cpu>
++  <cpu type='kvm' name='Westmere' usable='yes'/>
++  <cpu type='kvm' name='Skylake-Server-IBRS' usable='no'>
++    <blocker name='avx512f'/>
++    <blocker name='avx512dq'/>
++    <blocker name='clwb'/>
++    <blocker name='avx512cd'/>
++    <blocker name='avx512bw'/>
++    <blocker name='avx512vl'/>
++    <blocker name='pku'/>
++    <blocker name='spec-ctrl'/>
++    <blocker name='avx512f'/>
++    <blocker name='avx512f'/>
++    <blocker name='avx512f'/>
++    <blocker name='pku'/>
++  </cpu>
++  <cpu type='kvm' name='Skylake-Server' usable='no'>
++    <blocker name='avx512f'/>
++    <blocker name='avx512dq'/>
++    <blocker name='clwb'/>
++    <blocker name='avx512cd'/>
++    <blocker name='avx512bw'/>
++    <blocker name='avx512vl'/>
++    <blocker name='pku'/>
++    <blocker name='avx512f'/>
++    <blocker name='avx512f'/>
++    <blocker name='avx512f'/>
++    <blocker name='pku'/>
++  </cpu>
++  <cpu type='kvm' name='Skylake-Client-IBRS' usable='no'>
++    <blocker name='spec-ctrl'/>
++  </cpu>
++  <cpu type='kvm' name='Skylake-Client' usable='yes'/>
++  <cpu type='kvm' name='SandyBridge-IBRS' usable='no'>
++    <blocker name='spec-ctrl'/>
++  </cpu>
++  <cpu type='kvm' name='SandyBridge' usable='yes'/>
++  <cpu type='kvm' name='Penryn' usable='yes'/>
++  <cpu type='kvm' name='Opteron_G5' usable='no'>
++    <blocker name='sse4a'/>
++    <blocker name='misalignsse'/>
++    <blocker name='xop'/>
++    <blocker name='fma4'/>
++    <blocker name='tbm'/>
++    <blocker name='npt'/>
++    <blocker name='nrip-save'/>
++  </cpu>
++  <cpu type='kvm' name='Opteron_G4' usable='no'>
++    <blocker name='sse4a'/>
++    <blocker name='misalignsse'/>
++    <blocker name='xop'/>
++    <blocker name='fma4'/>
++    <blocker name='npt'/>
++    <blocker name='nrip-save'/>
++  </cpu>
++  <cpu type='kvm' name='Opteron_G3' usable='no'>
++    <blocker name='sse4a'/>
++    <blocker name='misalignsse'/>
++  </cpu>
++  <cpu type='kvm' name='Opteron_G2' usable='yes'/>
++  <cpu type='kvm' name='Opteron_G1' usable='yes'/>
++  <cpu type='kvm' name='Nehalem-IBRS' usable='no'>
++    <blocker name='spec-ctrl'/>
++  </cpu>
++  <cpu type='kvm' name='Nehalem' usable='yes'/>
++  <cpu type='kvm' name='KnightsMill' usable='no'>
++    <blocker name='avx512f'/>
++    <blocker name='avx512pf'/>
++    <blocker name='avx512er'/>
++    <blocker name='avx512cd'/>
++    <blocker name='avx512-vpopcntdq'/>
++    <blocker name='avx512-4vnniw'/>
++    <blocker name='avx512-4fmaps'/>
++    <blocker name='avx512f'/>
++    <blocker name='avx512f'/>
++    <blocker name='avx512f'/>
++  </cpu>
++  <cpu type='kvm' name='IvyBridge-IBRS' usable='no'>
++    <blocker name='spec-ctrl'/>
++  </cpu>
++  <cpu type='kvm' name='IvyBridge' usable='yes'/>
++  <cpu type='kvm' name='Icelake-Server' usable='no'>
++    <blocker name='avx512f'/>
++    <blocker name='avx512dq'/>
++    <blocker name='clwb'/>
++    <blocker name='avx512cd'/>
++    <blocker name='avx512bw'/>
++    <blocker name='avx512vl'/>
++    <blocker name='avx512vbmi'/>
++    <blocker name='pku'/>
++    <blocker name='avx512vbmi2'/>
++    <blocker name='gfni'/>
++    <blocker name='vaes'/>
++    <blocker name='vpclmulqdq'/>
++    <blocker name='avx512vnni'/>
++    <blocker name='avx512bitalg'/>
++    <blocker name='avx512-vpopcntdq'/>
++    <blocker name='la57'/>
++    <blocker name='spec-ctrl'/>
++    <blocker name='ssbd'/>
++    <blocker name='wbnoinvd'/>
++    <blocker name='avx512f'/>
++    <blocker name='avx512f'/>
++    <blocker name='avx512f'/>
++    <blocker name='pku'/>
++  </cpu>
++  <cpu type='kvm' name='Icelake-Client' usable='no'>
++    <blocker name='avx512vbmi'/>
++    <blocker name='pku'/>
++    <blocker name='avx512vbmi2'/>
++    <blocker name='gfni'/>
++    <blocker name='vaes'/>
++    <blocker name='vpclmulqdq'/>
++    <blocker name='avx512vnni'/>
++    <blocker name='avx512bitalg'/>
++    <blocker name='avx512-vpopcntdq'/>
++    <blocker name='spec-ctrl'/>
++    <blocker name='ssbd'/>
++    <blocker name='wbnoinvd'/>
++    <blocker name='pku'/>
++  </cpu>
++  <cpu type='kvm' name='Haswell-noTSX-IBRS' usable='no'>
++    <blocker name='spec-ctrl'/>
++  </cpu>
++  <cpu type='kvm' name='Haswell-noTSX' usable='yes'/>
++  <cpu type='kvm' name='Haswell-IBRS' usable='no'>
++    <blocker name='spec-ctrl'/>
++  </cpu>
++  <cpu type='kvm' name='Haswell' usable='yes'/>
++  <cpu type='kvm' name='EPYC-IBPB' usable='no'>
++    <blocker name='sha-ni'/>
++    <blocker name='mmxext'/>
++    <blocker name='fxsr-opt'/>
++    <blocker name='cr8legacy'/>
++    <blocker name='sse4a'/>
++    <blocker name='misalignsse'/>
++    <blocker name='osvw'/>
++    <blocker name='ibpb'/>
++    <blocker name='npt'/>
++    <blocker name='nrip-save'/>
++  </cpu>
++  <cpu type='kvm' name='EPYC' usable='no'>
++    <blocker name='sha-ni'/>
++    <blocker name='mmxext'/>
++    <blocker name='fxsr-opt'/>
++    <blocker name='cr8legacy'/>
++    <blocker name='sse4a'/>
++    <blocker name='misalignsse'/>
++    <blocker name='osvw'/>
++    <blocker name='npt'/>
++    <blocker name='nrip-save'/>
++  </cpu>
++  <cpu type='kvm' name='Dhyana' usable='no'>
++    <blocker name='mmxext'/>
++    <blocker name='fxsr-opt'/>
++    <blocker name='cr8legacy'/>
++    <blocker name='sse4a'/>
++    <blocker name='misalignsse'/>
++    <blocker name='osvw'/>
++    <blocker name='ibpb'/>
++    <blocker name='npt'/>
++    <blocker name='nrip-save'/>
++  </cpu>
++  <cpu type='kvm' name='Conroe' usable='yes'/>
++  <cpu type='kvm' name='Cascadelake-Server' usable='no'>
++    <blocker name='avx512f'/>
++    <blocker name='avx512dq'/>
++    <blocker name='clwb'/>
++    <blocker name='avx512cd'/>
++    <blocker name='avx512bw'/>
++    <blocker name='avx512vl'/>
++    <blocker name='pku'/>
++    <blocker name='avx512vnni'/>
++    <blocker name='spec-ctrl'/>
++    <blocker name='ssbd'/>
++    <blocker name='avx512f'/>
++    <blocker name='avx512f'/>
++    <blocker name='avx512f'/>
++    <blocker name='pku'/>
++  </cpu>
++  <cpu type='kvm' name='Broadwell-noTSX-IBRS' usable='no'>
++    <blocker name='spec-ctrl'/>
++  </cpu>
++  <cpu type='kvm' name='Broadwell-noTSX' usable='yes'/>
++  <cpu type='kvm' name='Broadwell-IBRS' usable='no'>
++    <blocker name='spec-ctrl'/>
++  </cpu>
++  <cpu type='kvm' name='Broadwell' usable='yes'/>
++  <cpu type='kvm' name='486' usable='yes'/>
++  <cpu type='tcg' name='max' usable='yes'/>
++  <cpu type='tcg' name='host' usable='no'>
++    <blocker name='kvm'/>
++  </cpu>
++  <cpu type='tcg' name='base' usable='yes'/>
++  <cpu type='tcg' name='qemu64' usable='yes'/>
++  <cpu type='tcg' name='qemu32' usable='yes'/>
++  <cpu type='tcg' name='phenom' usable='no'>
++    <blocker name='fxsr-opt'/>
++  </cpu>
++  <cpu type='tcg' name='pentium3' usable='yes'/>
++  <cpu type='tcg' name='pentium2' usable='yes'/>
++  <cpu type='tcg' name='pentium' usable='yes'/>
++  <cpu type='tcg' name='n270' usable='yes'/>
++  <cpu type='tcg' name='kvm64' usable='yes'/>
++  <cpu type='tcg' name='kvm32' usable='yes'/>
++  <cpu type='tcg' name='coreduo' usable='yes'/>
++  <cpu type='tcg' name='core2duo' usable='yes'/>
++  <cpu type='tcg' name='athlon' usable='yes'/>
++  <cpu type='tcg' name='Westmere-IBRS' usable='no'>
++    <blocker name='spec-ctrl'/>
++  </cpu>
++  <cpu type='tcg' name='Westmere' usable='yes'/>
++  <cpu type='tcg' name='Skylake-Server-IBRS' usable='no'>
++    <blocker name='fma'/>
++    <blocker name='pcid'/>
++    <blocker name='x2apic'/>
++    <blocker name='tsc-deadline'/>
++    <blocker name='avx'/>
++    <blocker name='f16c'/>
++    <blocker name='hle'/>
++    <blocker name='avx2'/>
++    <blocker name='invpcid'/>
++    <blocker name='rtm'/>
++    <blocker name='avx512f'/>
++    <blocker name='avx512dq'/>
++    <blocker name='rdseed'/>
++    <blocker name='avx512cd'/>
++    <blocker name='avx512bw'/>
++    <blocker name='avx512vl'/>
++    <blocker name='spec-ctrl'/>
++    <blocker name='3dnowprefetch'/>
++    <blocker name='xsavec'/>
++  </cpu>
++  <cpu type='tcg' name='Skylake-Server' usable='no'>
++    <blocker name='fma'/>
++    <blocker name='pcid'/>
++    <blocker name='x2apic'/>
++    <blocker name='tsc-deadline'/>
++    <blocker name='avx'/>
++    <blocker name='f16c'/>
++    <blocker name='hle'/>
++    <blocker name='avx2'/>
++    <blocker name='invpcid'/>
++    <blocker name='rtm'/>
++    <blocker name='avx512f'/>
++    <blocker name='avx512dq'/>
++    <blocker name='rdseed'/>
++    <blocker name='avx512cd'/>
++    <blocker name='avx512bw'/>
++    <blocker name='avx512vl'/>
++    <blocker name='3dnowprefetch'/>
++    <blocker name='xsavec'/>
++  </cpu>
++  <cpu type='tcg' name='Skylake-Client-IBRS' usable='no'>
++    <blocker name='fma'/>
++    <blocker name='pcid'/>
++    <blocker name='x2apic'/>
++    <blocker name='tsc-deadline'/>
++    <blocker name='avx'/>
++    <blocker name='f16c'/>
++    <blocker name='hle'/>
++    <blocker name='avx2'/>
++    <blocker name='invpcid'/>
++    <blocker name='rtm'/>
++    <blocker name='rdseed'/>
++    <blocker name='spec-ctrl'/>
++    <blocker name='3dnowprefetch'/>
++    <blocker name='xsavec'/>
++  </cpu>
++  <cpu type='tcg' name='Skylake-Client' usable='no'>
++    <blocker name='fma'/>
++    <blocker name='pcid'/>
++    <blocker name='x2apic'/>
++    <blocker name='tsc-deadline'/>
++    <blocker name='avx'/>
++    <blocker name='f16c'/>
++    <blocker name='hle'/>
++    <blocker name='avx2'/>
++    <blocker name='invpcid'/>
++    <blocker name='rtm'/>
++    <blocker name='rdseed'/>
++    <blocker name='3dnowprefetch'/>
++    <blocker name='xsavec'/>
++  </cpu>
++  <cpu type='tcg' name='SandyBridge-IBRS' usable='no'>
++    <blocker name='x2apic'/>
++    <blocker name='tsc-deadline'/>
++    <blocker name='avx'/>
++    <blocker name='spec-ctrl'/>
++  </cpu>
++  <cpu type='tcg' name='SandyBridge' usable='no'>
++    <blocker name='x2apic'/>
++    <blocker name='tsc-deadline'/>
++    <blocker name='avx'/>
++  </cpu>
++  <cpu type='tcg' name='Penryn' usable='yes'/>
++  <cpu type='tcg' name='Opteron_G5' usable='no'>
++    <blocker name='fma'/>
++    <blocker name='avx'/>
++    <blocker name='f16c'/>
++    <blocker name='misalignsse'/>
++    <blocker name='3dnowprefetch'/>
++    <blocker name='xop'/>
++    <blocker name='fma4'/>
++    <blocker name='tbm'/>
++    <blocker name='nrip-save'/>
++  </cpu>
++  <cpu type='tcg' name='Opteron_G4' usable='no'>
++    <blocker name='avx'/>
++    <blocker name='misalignsse'/>
++    <blocker name='3dnowprefetch'/>
++    <blocker name='xop'/>
++    <blocker name='fma4'/>
++    <blocker name='nrip-save'/>
++  </cpu>
++  <cpu type='tcg' name='Opteron_G3' usable='no'>
++    <blocker name='misalignsse'/>
++  </cpu>
++  <cpu type='tcg' name='Opteron_G2' usable='yes'/>
++  <cpu type='tcg' name='Opteron_G1' usable='yes'/>
++  <cpu type='tcg' name='Nehalem-IBRS' usable='no'>
++    <blocker name='spec-ctrl'/>
++  </cpu>
++  <cpu type='tcg' name='Nehalem' usable='yes'/>
++  <cpu type='tcg' name='KnightsMill' usable='no'>
++    <blocker name='fma'/>
++    <blocker name='x2apic'/>
++    <blocker name='tsc-deadline'/>
++    <blocker name='avx'/>
++    <blocker name='f16c'/>
++    <blocker name='avx2'/>
++    <blocker name='avx512f'/>
++    <blocker name='rdseed'/>
++    <blocker name='avx512pf'/>
++    <blocker name='avx512er'/>
++    <blocker name='avx512cd'/>
++    <blocker name='avx512-vpopcntdq'/>
++    <blocker name='avx512-4vnniw'/>
++    <blocker name='avx512-4fmaps'/>
++    <blocker name='3dnowprefetch'/>
++  </cpu>
++  <cpu type='tcg' name='IvyBridge-IBRS' usable='no'>
++    <blocker name='x2apic'/>
++    <blocker name='tsc-deadline'/>
++    <blocker name='avx'/>
++    <blocker name='f16c'/>
++    <blocker name='spec-ctrl'/>
++  </cpu>
++  <cpu type='tcg' name='IvyBridge' usable='no'>
++    <blocker name='x2apic'/>
++    <blocker name='tsc-deadline'/>
++    <blocker name='avx'/>
++    <blocker name='f16c'/>
++  </cpu>
++  <cpu type='tcg' name='Icelake-Server' usable='no'>
++    <blocker name='fma'/>
++    <blocker name='pcid'/>
++    <blocker name='x2apic'/>
++    <blocker name='tsc-deadline'/>
++    <blocker name='avx'/>
++    <blocker name='f16c'/>
++    <blocker name='hle'/>
++    <blocker name='avx2'/>
++    <blocker name='invpcid'/>
++    <blocker name='rtm'/>
++    <blocker name='avx512f'/>
++    <blocker name='avx512dq'/>
++    <blocker name='rdseed'/>
++    <blocker name='avx512cd'/>
++    <blocker name='avx512bw'/>
++    <blocker name='avx512vl'/>
++    <blocker name='avx512vbmi'/>
++    <blocker name='umip'/>
++    <blocker name='avx512vbmi2'/>
++    <blocker name='gfni'/>
++    <blocker name='vaes'/>
++    <blocker name='vpclmulqdq'/>
++    <blocker name='avx512vnni'/>
++    <blocker name='avx512bitalg'/>
++    <blocker name='avx512-vpopcntdq'/>
++    <blocker name='spec-ctrl'/>
++    <blocker name='ssbd'/>
++    <blocker name='3dnowprefetch'/>
++    <blocker name='wbnoinvd'/>
++    <blocker name='xsavec'/>
++  </cpu>
++  <cpu type='tcg' name='Icelake-Client' usable='no'>
++    <blocker name='fma'/>
++    <blocker name='pcid'/>
++    <blocker name='x2apic'/>
++    <blocker name='tsc-deadline'/>
++    <blocker name='avx'/>
++    <blocker name='f16c'/>
++    <blocker name='hle'/>
++    <blocker name='avx2'/>
++    <blocker name='invpcid'/>
++    <blocker name='rtm'/>
++    <blocker name='rdseed'/>
++    <blocker name='avx512vbmi'/>
++    <blocker name='umip'/>
++    <blocker name='avx512vbmi2'/>
++    <blocker name='gfni'/>
++    <blocker name='vaes'/>
++    <blocker name='vpclmulqdq'/>
++    <blocker name='avx512vnni'/>
++    <blocker name='avx512bitalg'/>
++    <blocker name='avx512-vpopcntdq'/>
++    <blocker name='spec-ctrl'/>
++    <blocker name='ssbd'/>
++    <blocker name='3dnowprefetch'/>
++    <blocker name='wbnoinvd'/>
++    <blocker name='xsavec'/>
++  </cpu>
++  <cpu type='tcg' name='Haswell-noTSX-IBRS' usable='no'>
++    <blocker name='fma'/>
++    <blocker name='pcid'/>
++    <blocker name='x2apic'/>
++    <blocker name='tsc-deadline'/>
++    <blocker name='avx'/>
++    <blocker name='f16c'/>
++    <blocker name='avx2'/>
++    <blocker name='invpcid'/>
++    <blocker name='spec-ctrl'/>
++  </cpu>
++  <cpu type='tcg' name='Haswell-noTSX' usable='no'>
++    <blocker name='fma'/>
++    <blocker name='pcid'/>
++    <blocker name='x2apic'/>
++    <blocker name='tsc-deadline'/>
++    <blocker name='avx'/>
++    <blocker name='f16c'/>
++    <blocker name='avx2'/>
++    <blocker name='invpcid'/>
++  </cpu>
++  <cpu type='tcg' name='Haswell-IBRS' usable='no'>
++    <blocker name='fma'/>
++    <blocker name='pcid'/>
++    <blocker name='x2apic'/>
++    <blocker name='tsc-deadline'/>
++    <blocker name='avx'/>
++    <blocker name='f16c'/>
++    <blocker name='hle'/>
++    <blocker name='avx2'/>
++    <blocker name='invpcid'/>
++    <blocker name='rtm'/>
++    <blocker name='spec-ctrl'/>
++  </cpu>
++  <cpu type='tcg' name='Haswell' usable='no'>
++    <blocker name='fma'/>
++    <blocker name='pcid'/>
++    <blocker name='x2apic'/>
++    <blocker name='tsc-deadline'/>
++    <blocker name='avx'/>
++    <blocker name='f16c'/>
++    <blocker name='hle'/>
++    <blocker name='avx2'/>
++    <blocker name='invpcid'/>
++    <blocker name='rtm'/>
++  </cpu>
++  <cpu type='tcg' name='EPYC-IBPB' usable='no'>
++    <blocker name='fma'/>
++    <blocker name='avx'/>
++    <blocker name='f16c'/>
++    <blocker name='avx2'/>
++    <blocker name='rdseed'/>
++    <blocker name='sha-ni'/>
++    <blocker name='fxsr-opt'/>
++    <blocker name='misalignsse'/>
++    <blocker name='3dnowprefetch'/>
++    <blocker name='osvw'/>
++    <blocker name='topoext'/>
++    <blocker name='ibpb'/>
++    <blocker name='nrip-save'/>
++    <blocker name='xsavec'/>
++  </cpu>
++  <cpu type='tcg' name='EPYC' usable='no'>
++    <blocker name='fma'/>
++    <blocker name='avx'/>
++    <blocker name='f16c'/>
++    <blocker name='avx2'/>
++    <blocker name='rdseed'/>
++    <blocker name='sha-ni'/>
++    <blocker name='fxsr-opt'/>
++    <blocker name='misalignsse'/>
++    <blocker name='3dnowprefetch'/>
++    <blocker name='osvw'/>
++    <blocker name='topoext'/>
++    <blocker name='nrip-save'/>
++    <blocker name='xsavec'/>
++  </cpu>
++  <cpu type='tcg' name='Dhyana' usable='no'>
++    <blocker name='fma'/>
++    <blocker name='avx'/>
++    <blocker name='f16c'/>
++    <blocker name='avx2'/>
++    <blocker name='rdseed'/>
++    <blocker name='fxsr-opt'/>
++    <blocker name='misalignsse'/>
++    <blocker name='3dnowprefetch'/>
++    <blocker name='osvw'/>
++    <blocker name='topoext'/>
++    <blocker name='ibpb'/>
++    <blocker name='nrip-save'/>
++    <blocker name='xsavec'/>
++  </cpu>
++  <cpu type='tcg' name='Conroe' usable='yes'/>
++  <cpu type='tcg' name='Cascadelake-Server' usable='no'>
++    <blocker name='fma'/>
++    <blocker name='pcid'/>
++    <blocker name='x2apic'/>
++    <blocker name='tsc-deadline'/>
++    <blocker name='avx'/>
++    <blocker name='f16c'/>
++    <blocker name='hle'/>
++    <blocker name='avx2'/>
++    <blocker name='invpcid'/>
++    <blocker name='rtm'/>
++    <blocker name='avx512f'/>
++    <blocker name='avx512dq'/>
++    <blocker name='rdseed'/>
++    <blocker name='avx512cd'/>
++    <blocker name='avx512bw'/>
++    <blocker name='avx512vl'/>
++    <blocker name='avx512vnni'/>
++    <blocker name='spec-ctrl'/>
++    <blocker name='ssbd'/>
++    <blocker name='3dnowprefetch'/>
++    <blocker name='xsavec'/>
++  </cpu>
++  <cpu type='tcg' name='Broadwell-noTSX-IBRS' usable='no'>
++    <blocker name='fma'/>
++    <blocker name='pcid'/>
++    <blocker name='x2apic'/>
++    <blocker name='tsc-deadline'/>
++    <blocker name='avx'/>
++    <blocker name='f16c'/>
++    <blocker name='avx2'/>
++    <blocker name='invpcid'/>
++    <blocker name='rdseed'/>
++    <blocker name='spec-ctrl'/>
++    <blocker name='3dnowprefetch'/>
++  </cpu>
++  <cpu type='tcg' name='Broadwell-noTSX' usable='no'>
++    <blocker name='fma'/>
++    <blocker name='pcid'/>
++    <blocker name='x2apic'/>
++    <blocker name='tsc-deadline'/>
++    <blocker name='avx'/>
++    <blocker name='f16c'/>
++    <blocker name='avx2'/>
++    <blocker name='invpcid'/>
++    <blocker name='rdseed'/>
++    <blocker name='3dnowprefetch'/>
++  </cpu>
++  <cpu type='tcg' name='Broadwell-IBRS' usable='no'>
++    <blocker name='fma'/>
++    <blocker name='pcid'/>
++    <blocker name='x2apic'/>
++    <blocker name='tsc-deadline'/>
++    <blocker name='avx'/>
++    <blocker name='f16c'/>
++    <blocker name='hle'/>
++    <blocker name='avx2'/>
++    <blocker name='invpcid'/>
++    <blocker name='rtm'/>
++    <blocker name='rdseed'/>
++    <blocker name='spec-ctrl'/>
++    <blocker name='3dnowprefetch'/>
++  </cpu>
++  <cpu type='tcg' name='Broadwell' usable='no'>
++    <blocker name='fma'/>
++    <blocker name='pcid'/>
++    <blocker name='x2apic'/>
++    <blocker name='tsc-deadline'/>
++    <blocker name='avx'/>
++    <blocker name='f16c'/>
++    <blocker name='hle'/>
++    <blocker name='avx2'/>
++    <blocker name='invpcid'/>
++    <blocker name='rtm'/>
++    <blocker name='rdseed'/>
++    <blocker name='3dnowprefetch'/>
++  </cpu>
++  <cpu type='tcg' name='486' usable='yes'/>
++  <machine name='pc-i440fx-4.1' alias='pc' hotplugCpus='yes' maxCpus='255'/>
++  <machine name='isapc' hotplugCpus='yes' maxCpus='1'/>
++  <machine name='pc-1.1' hotplugCpus='yes' maxCpus='255'/>
++  <machine name='pc-1.2' hotplugCpus='yes' maxCpus='255'/>
++  <machine name='pc-1.3' hotplugCpus='yes' maxCpus='255'/>
++  <machine name='pc-i440fx-2.8' hotplugCpus='yes' maxCpus='255'/>
++  <machine name='pc-1.0' hotplugCpus='yes' maxCpus='255'/>
++  <machine name='pc-i440fx-2.9' hotplugCpus='yes' maxCpus='255'/>
++  <machine name='pc-i440fx-2.6' hotplugCpus='yes' maxCpus='255'/>
++  <machine name='pc-i440fx-2.7' hotplugCpus='yes' maxCpus='255'/>
++  <machine name='xenfv' hotplugCpus='yes' maxCpus='128'/>
++  <machine name='pc-i440fx-2.3' hotplugCpus='yes' maxCpus='255'/>
++  <machine name='pc-i440fx-2.4' hotplugCpus='yes' maxCpus='255'/>
++  <machine name='pc-i440fx-2.5' hotplugCpus='yes' maxCpus='255'/>
++  <machine name='pc-i440fx-4.0' hotplugCpus='yes' maxCpus='255'/>
++  <machine name='pc-i440fx-2.1' hotplugCpus='yes' maxCpus='255'/>
++  <machine name='pc-i440fx-2.2' hotplugCpus='yes' maxCpus='255'/>
++  <machine name='pc-q35-3.1' hotplugCpus='yes' maxCpus='288'/>
++  <machine name='pc-i440fx-2.0' hotplugCpus='yes' maxCpus='255'/>
++  <machine name='pc-q35-2.11' hotplugCpus='yes' maxCpus='288'/>
++  <machine name='pc-q35-2.12' hotplugCpus='yes' maxCpus='288'/>
++  <machine name='pc-q35-3.0' hotplugCpus='yes' maxCpus='288'/>
++  <machine name='xenpv' maxCpus='1'/>
++  <machine name='pc-q35-2.10' hotplugCpus='yes' maxCpus='288'/>
++  <machine name='pc-q35-4.0.1' hotplugCpus='yes' maxCpus='288'/>
++  <machine name='pc-i440fx-1.7' hotplugCpus='yes' maxCpus='255'/>
++  <machine name='pc-q35-2.9' hotplugCpus='yes' maxCpus='288'/>
++  <machine name='pc-0.15' hotplugCpus='yes' maxCpus='255'/>
++  <machine name='pc-i440fx-1.5' hotplugCpus='yes' maxCpus='255'/>
++  <machine name='pc-q35-2.7' hotplugCpus='yes' maxCpus='255'/>
++  <machine name='pc-i440fx-1.6' hotplugCpus='yes' maxCpus='255'/>
++  <machine name='pc-i440fx-2.11' hotplugCpus='yes' maxCpus='255'/>
++  <machine name='pc-q35-2.8' hotplugCpus='yes' maxCpus='288'/>
++  <machine name='pc-0.13' hotplugCpus='yes' maxCpus='255'/>
++  <machine name='pc-i440fx-2.12' hotplugCpus='yes' maxCpus='255'/>
++  <machine name='pc-0.14' hotplugCpus='yes' maxCpus='255'/>
++  <machine name='pc-i440fx-3.0' hotplugCpus='yes' maxCpus='255'/>
++  <machine name='pc-i440fx-3.1' hotplugCpus='yes' maxCpus='255'/>
++  <machine name='pc-q35-2.4' hotplugCpus='yes' maxCpus='255'/>
++  <machine name='pc-q35-2.5' hotplugCpus='yes' maxCpus='255'/>
++  <machine name='pc-q35-2.6' hotplugCpus='yes' maxCpus='255'/>
++  <machine name='pc-i440fx-1.4' hotplugCpus='yes' maxCpus='255'/>
++  <machine name='pc-i440fx-2.10' hotplugCpus='yes' maxCpus='255'/>
++  <machine name='pc-0.12' hotplugCpus='yes' maxCpus='255'/>
++  <machine name='pc-q35-4.0' hotplugCpus='yes' maxCpus='288'/>
++  <machine name='pc-q35-4.1' alias='q35' hotplugCpus='yes' maxCpus='288'/>
++</qemuCaps>
+diff --git a/tests/qemucapabilitiestest.c b/tests/qemucapabilitiestest.c
+index ccc4e45817..775f78e16f 100644
+--- a/tests/qemucapabilitiestest.c
++++ b/tests/qemucapabilitiestest.c
+@@ -178,6 +178,7 @@ mymain(void)
+     DO_TEST("x86_64", "caps_2.11.0");
+     DO_TEST("x86_64", "caps_2.12.0");
+     DO_TEST("x86_64", "caps_3.0.0");
++    DO_TEST("x86_64", "caps_4.1.0");
+     DO_TEST("aarch64", "caps_2.6.0");
+     DO_TEST("aarch64", "caps_2.10.0");
+     DO_TEST("aarch64", "caps_2.12.0");
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-tests-Add-domain-capabilities-case-for-QEMU-4.1.0.patch b/SOURCES/libvirt-tests-Add-domain-capabilities-case-for-QEMU-4.1.0.patch
new file mode 100644
index 0000000..c38fdc0
--- /dev/null
+++ b/SOURCES/libvirt-tests-Add-domain-capabilities-case-for-QEMU-4.1.0.patch
@@ -0,0 +1,203 @@
+From d5a656f2fe0e7aea8f56a4b4c59dcc3d5e906411 Mon Sep 17 00:00:00 2001
+Message-Id: <d5a656f2fe0e7aea8f56a4b4c59dcc3d5e906411@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:25:49 +0200
+Subject: [PATCH] tests: Add domain capabilities case for QEMU 4.1.0
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit 9ceee2f4bb5d6cefa24c3aedcb7addbe7907c60b)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1697627
+
+Conflicts:
+	tests/domaincapstest.c
+            - several cases are missing
+
+	tests/domaincapsschemadata/qemu_4.1.0.x86_64.xml
+            - some capabilities are not reported in domaincaps
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <87edadf46f7d4d7ad161b2ab433632f9d0f66920.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ .../qemu_4.1.0.x86_64.xml                     | 148 ++++++++++++++++++
+ tests/domaincapstest.c                        |   4 +
+ 2 files changed, 152 insertions(+)
+ create mode 100644 tests/domaincapsschemadata/qemu_4.1.0.x86_64.xml
+
+diff --git a/tests/domaincapsschemadata/qemu_4.1.0.x86_64.xml b/tests/domaincapsschemadata/qemu_4.1.0.x86_64.xml
+new file mode 100644
+index 0000000000..47aed6a43a
+--- /dev/null
++++ b/tests/domaincapsschemadata/qemu_4.1.0.x86_64.xml
+@@ -0,0 +1,148 @@
++<domainCapabilities>
++  <path>/usr/bin/qemu-system-x86_64</path>
++  <domain>kvm</domain>
++  <machine>pc-i440fx-4.1</machine>
++  <arch>x86_64</arch>
++  <vcpu max='255'/>
++  <iothreads supported='yes'/>
++  <os supported='yes'>
++    <loader supported='yes'>
++      <value>/usr/share/AAVMF/AAVMF_CODE.fd</value>
++      <value>/usr/share/AAVMF/AAVMF32_CODE.fd</value>
++      <value>/usr/share/OVMF/OVMF_CODE.fd</value>
++      <enum name='type'>
++        <value>rom</value>
++        <value>pflash</value>
++      </enum>
++      <enum name='readonly'>
++        <value>yes</value>
++        <value>no</value>
++      </enum>
++    </loader>
++  </os>
++  <cpu>
++    <mode name='host-passthrough' supported='yes'/>
++    <mode name='host-model' supported='yes'>
++      <model fallback='forbid'>Skylake-Client</model>
++      <vendor>Intel</vendor>
++      <feature policy='require' name='ss'/>
++      <feature policy='require' name='vmx'/>
++      <feature policy='require' name='hypervisor'/>
++      <feature policy='require' name='tsc_adjust'/>
++      <feature policy='require' name='clflushopt'/>
++      <feature policy='require' name='umip'/>
++      <feature policy='require' name='arch-capabilities'/>
++      <feature policy='require' name='xsaves'/>
++      <feature policy='require' name='pdpe1gb'/>
++    </mode>
++    <mode name='custom' supported='yes'>
++      <model usable='yes'>qemu64</model>
++      <model usable='yes'>qemu32</model>
++      <model usable='no'>phenom</model>
++      <model usable='yes'>pentium3</model>
++      <model usable='yes'>pentium2</model>
++      <model usable='yes'>pentium</model>
++      <model usable='yes'>n270</model>
++      <model usable='yes'>kvm64</model>
++      <model usable='yes'>kvm32</model>
++      <model usable='yes'>coreduo</model>
++      <model usable='yes'>core2duo</model>
++      <model usable='no'>athlon</model>
++      <model usable='no'>Westmere-IBRS</model>
++      <model usable='yes'>Westmere</model>
++      <model usable='no'>Skylake-Server-IBRS</model>
++      <model usable='no'>Skylake-Server</model>
++      <model usable='no'>Skylake-Client-IBRS</model>
++      <model usable='yes'>Skylake-Client</model>
++      <model usable='no'>SandyBridge-IBRS</model>
++      <model usable='yes'>SandyBridge</model>
++      <model usable='yes'>Penryn</model>
++      <model usable='no'>Opteron_G5</model>
++      <model usable='no'>Opteron_G4</model>
++      <model usable='no'>Opteron_G3</model>
++      <model usable='yes'>Opteron_G2</model>
++      <model usable='yes'>Opteron_G1</model>
++      <model usable='no'>Nehalem-IBRS</model>
++      <model usable='yes'>Nehalem</model>
++      <model usable='no'>IvyBridge-IBRS</model>
++      <model usable='yes'>IvyBridge</model>
++      <model usable='no'>Icelake-Server</model>
++      <model usable='no'>Icelake-Client</model>
++      <model usable='no'>Haswell-noTSX-IBRS</model>
++      <model usable='yes'>Haswell-noTSX</model>
++      <model usable='no'>Haswell-IBRS</model>
++      <model usable='yes'>Haswell</model>
++      <model usable='no'>EPYC-IBPB</model>
++      <model usable='no'>EPYC</model>
++      <model usable='yes'>Conroe</model>
++      <model usable='no'>Cascadelake-Server</model>
++      <model usable='no'>Broadwell-noTSX-IBRS</model>
++      <model usable='yes'>Broadwell-noTSX</model>
++      <model usable='no'>Broadwell-IBRS</model>
++      <model usable='yes'>Broadwell</model>
++      <model usable='yes'>486</model>
++    </mode>
++  </cpu>
++  <devices>
++    <disk supported='yes'>
++      <enum name='diskDevice'>
++        <value>disk</value>
++        <value>cdrom</value>
++        <value>floppy</value>
++        <value>lun</value>
++      </enum>
++      <enum name='bus'>
++        <value>ide</value>
++        <value>fdc</value>
++        <value>scsi</value>
++        <value>virtio</value>
++        <value>usb</value>
++        <value>sata</value>
++      </enum>
++    </disk>
++    <graphics supported='yes'>
++      <enum name='type'>
++        <value>sdl</value>
++        <value>vnc</value>
++        <value>spice</value>
++      </enum>
++    </graphics>
++    <video supported='yes'>
++      <enum name='modelType'>
++        <value>vga</value>
++        <value>cirrus</value>
++        <value>vmvga</value>
++        <value>qxl</value>
++        <value>virtio</value>
++      </enum>
++    </video>
++    <hostdev supported='yes'>
++      <enum name='mode'>
++        <value>subsystem</value>
++      </enum>
++      <enum name='startupPolicy'>
++        <value>default</value>
++        <value>mandatory</value>
++        <value>requisite</value>
++        <value>optional</value>
++      </enum>
++      <enum name='subsysType'>
++        <value>usb</value>
++        <value>pci</value>
++        <value>scsi</value>
++      </enum>
++      <enum name='capsType'/>
++      <enum name='pciBackend'>
++        <value>default</value>
++        <value>kvm</value>
++        <value>vfio</value>
++      </enum>
++    </hostdev>
++  </devices>
++  <features>
++    <gic supported='no'/>
++    <vmcoreinfo supported='yes'/>
++    <genid supported='yes'/>
++    <sev supported='no'/>
++  </features>
++</domainCapabilities>
+diff --git a/tests/domaincapstest.c b/tests/domaincapstest.c
+index 06e77fd586..30e7eea3cb 100644
+--- a/tests/domaincapstest.c
++++ b/tests/domaincapstest.c
+@@ -504,6 +504,10 @@ mymain(void)
+                  "/usr/bin/qemu-system-s390x", NULL,
+                  "s390x", VIR_DOMAIN_VIRT_KVM);
+ 
++    DO_TEST_QEMU("4.1.0", "caps_4.1.0",
++                 "/usr/bin/qemu-system-x86_64", NULL,
++                 "x86_64", VIR_DOMAIN_VIRT_KVM);
++
+     virObjectUnref(cfg);
+ 
+ #endif /* WITH_QEMU */
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-tests-Augment-vcgrouptest-to-add-virCgroupGetMemoryStat.patch b/SOURCES/libvirt-tests-Augment-vcgrouptest-to-add-virCgroupGetMemoryStat.patch
new file mode 100644
index 0000000..ea4446e
--- /dev/null
+++ b/SOURCES/libvirt-tests-Augment-vcgrouptest-to-add-virCgroupGetMemoryStat.patch
@@ -0,0 +1,112 @@
+From 356b50b2014aafc7c1555e11cf93650dad39f03a Mon Sep 17 00:00:00 2001
+Message-Id: <356b50b2014aafc7c1555e11cf93650dad39f03a@dist-git>
+From: John Ferlan <jferlan@redhat.com>
+Date: Mon, 1 Jul 2019 17:08:08 +0200
+Subject: [PATCH] tests: Augment vcgrouptest to add virCgroupGetMemoryStat
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Add a test to fetch the GetMemoryStat output. This only gets
+data for v1 only right now since the v2 data from commit 61ff6021
+is rather useless returning all 0's. The v1 data was originally
+added in commit d1452470.
+
+Signed-off-by: John Ferlan <jferlan@redhat.com>
+Reviewed-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 99b8ef7a98d6ad4a01549204195f5e17ee1984ee)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <3c217939ce31a379e149865bc0f3342fc334ba42.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ tests/vircgrouptest.c | 64 +++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 64 insertions(+)
+
+diff --git a/tests/vircgrouptest.c b/tests/vircgrouptest.c
+index 118b1bc246..e9cf792bdd 100644
+--- a/tests/vircgrouptest.c
++++ b/tests/vircgrouptest.c
+@@ -803,6 +803,67 @@ static int testCgroupGetMemoryUsage(const void *args ATTRIBUTE_UNUSED)
+     return ret;
+ }
+ 
++
++static int
++testCgroupGetMemoryStat(const void *args ATTRIBUTE_UNUSED)
++{
++    virCgroupPtr cgroup = NULL;
++    int rv;
++    int ret = -1;
++    size_t i;
++
++    const unsigned long long expected_values[] = {
++        1336619008ULL,
++        67100672ULL,
++        145887232ULL,
++        661872640ULL,
++        627400704UL,
++        3690496ULL
++    };
++    const char* names[] = {
++        "cache",
++        "active_anon",
++        "inactive_anon",
++        "active_file",
++        "inactive_file",
++        "unevictable"
++    };
++    unsigned long long values[ARRAY_CARDINALITY(expected_values)];
++
++    if ((rv = virCgroupNewPartition("/virtualmachines", true,
++                                    (1 << VIR_CGROUP_CONTROLLER_MEMORY),
++                                    &cgroup)) < 0) {
++        fprintf(stderr, "Could not create /virtualmachines cgroup: %d\n", -rv);
++        goto cleanup;
++    }
++
++    if ((rv = virCgroupGetMemoryStat(cgroup, &values[0],
++                                     &values[1], &values[2],
++                                     &values[3], &values[4],
++                                     &values[5])) < 0) {
++        fprintf(stderr, "Could not retrieve GetMemoryStat for /virtualmachines cgroup: %d\n", -rv);
++        goto cleanup;
++    }
++
++    for (i = 0; i < ARRAY_CARDINALITY(expected_values); i++) {
++        /* NB: virCgroupGetMemoryStat returns a KiB scaled value */
++        if ((expected_values[i] >> 10) != values[i]) {
++            fprintf(stderr,
++                    "Wrong value (%llu) for %s from virCgroupGetMemoryStat "
++                    "(expected %llu)\n",
++                    values[i], names[i], (expected_values[i] >> 10));
++            goto cleanup;
++        }
++    }
++
++    ret = 0;
++
++ cleanup:
++    virCgroupFree(&cgroup);
++    return ret;
++}
++
++
+ static int testCgroupGetBlkioIoServiced(const void *args ATTRIBUTE_UNUSED)
+ {
+     virCgroupPtr cgroup = NULL;
+@@ -1036,6 +1097,9 @@ mymain(void)
+     if (virTestRun("virCgroupGetMemoryUsage works", testCgroupGetMemoryUsage, NULL) < 0)
+         ret = -1;
+ 
++    if (virTestRun("virCgroupGetMemoryStat works", testCgroupGetMemoryStat, NULL) < 0)
++        ret = -1;
++
+     if (virTestRun("virCgroupGetPercpuStats works", testCgroupGetPercpuStats, NULL) < 0)
+         ret = -1;
+     cleanupFakeFS(fakerootdir);
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-tests-Resolve-possible-overrun.patch b/SOURCES/libvirt-tests-Resolve-possible-overrun.patch
new file mode 100644
index 0000000..097fd9c
--- /dev/null
+++ b/SOURCES/libvirt-tests-Resolve-possible-overrun.patch
@@ -0,0 +1,84 @@
+From c8e10c7f4644646194bbcb1514bbf110ec7374ad Mon Sep 17 00:00:00 2001
+Message-Id: <c8e10c7f4644646194bbcb1514bbf110ec7374ad@dist-git>
+From: John Ferlan <jferlan@redhat.com>
+Date: Mon, 1 Jul 2019 17:06:11 +0200
+Subject: [PATCH] tests: Resolve possible overrun
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Coverity noted that each of the fmemopen called used the strlen value
+in order to allocate space, but that neglected space for terminating
+null string. So just add 1 to the strlen.
+
+Signed-off-by: John Ferlan <jferlan@redhat.com>
+Reviewed-by: Erik Skultety <eskultet@redhat.com>
+(cherry picked from commit 7eb56dcd9ef4c21f8f4bc5e639dc4dd01e6d572a)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <a0d52bead1b7e31bfa1c1938c7ae19fe0a7605d4.1561993099.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ tests/vircgroupmock.c | 21 ++++++++++++---------
+ 1 file changed, 12 insertions(+), 9 deletions(-)
+
+diff --git a/tests/vircgroupmock.c b/tests/vircgroupmock.c
+index 51861be38e..bae8304f6c 100644
+--- a/tests/vircgroupmock.c
++++ b/tests/vircgroupmock.c
+@@ -468,12 +468,13 @@ FILE *fopen(const char *path, const char *mode)
+         if (STREQ(mode, "r")) {
+             if (allinone)
+                 return fmemopen((void *)procmountsallinone,
+-                                strlen(procmountsallinone), mode);
++                                strlen(procmountsallinone) + 1, mode);
+             else if (logind)
+                 return fmemopen((void *)procmountslogind,
+-                                strlen(procmountslogind), mode);
++                                strlen(procmountslogind) + 1, mode);
+             else
+-                return fmemopen((void *)procmounts, strlen(procmounts), mode);
++                return fmemopen((void *)procmounts,
++                                strlen(procmounts) + 1, mode);
+         } else {
+             errno = EACCES;
+             return NULL;
+@@ -483,12 +484,13 @@ FILE *fopen(const char *path, const char *mode)
+         if (STREQ(mode, "r")) {
+             if (allinone)
+                 return fmemopen((void *)proccgroupsallinone,
+-                                strlen(proccgroupsallinone), mode);
++                                strlen(proccgroupsallinone) + 1, mode);
+             else if (logind)
+                 return fmemopen((void *)proccgroupslogind,
+-                                strlen(proccgroupslogind), mode);
++                                strlen(proccgroupslogind) + 1, mode);
+             else
+-                return fmemopen((void *)proccgroups, strlen(proccgroups), mode);
++                return fmemopen((void *)proccgroups,
++                                strlen(proccgroups) + 1, mode);
+         } else {
+             errno = EACCES;
+             return NULL;
+@@ -498,12 +500,13 @@ FILE *fopen(const char *path, const char *mode)
+         if (STREQ(mode, "r")) {
+             if (allinone)
+                 return fmemopen((void *)procselfcgroupsallinone,
+-                                strlen(procselfcgroupsallinone), mode);
++                                strlen(procselfcgroupsallinone) + 1, mode);
+             else if (logind)
+                 return fmemopen((void *)procselfcgroupslogind,
+-                                strlen(procselfcgroupslogind), mode);
++                                strlen(procselfcgroupslogind) + 1, mode);
+             else
+-                return fmemopen((void *)procselfcgroups, strlen(procselfcgroups), mode);
++                return fmemopen((void *)procselfcgroups,
++                                strlen(procselfcgroups) + 1, mode);
+         } else {
+             errno = EACCES;
+             return NULL;
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-tests-Use-correct-function-name-in-error-path.patch b/SOURCES/libvirt-tests-Use-correct-function-name-in-error-path.patch
new file mode 100644
index 0000000..73e3d8a
--- /dev/null
+++ b/SOURCES/libvirt-tests-Use-correct-function-name-in-error-path.patch
@@ -0,0 +1,40 @@
+From ef6054cc51d7a847e1d34b74b28b76fd1c1bb6da Mon Sep 17 00:00:00 2001
+Message-Id: <ef6054cc51d7a847e1d34b74b28b76fd1c1bb6da@dist-git>
+From: John Ferlan <jferlan@redhat.com>
+Date: Mon, 1 Jul 2019 17:08:06 +0200
+Subject: [PATCH] tests: Use correct function name in error path
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Commit id 5eb61e6846 neglected to change the name in the wrong value
+output to virCgroupGetPercpuStats from virCgroupGetMemoryUsage.
+
+Signed-off-by: John Ferlan <jferlan@redhat.com>
+(cherry picked from commit 4608af30f9f9a4089b530d85d9b11c2f88424a09)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <e1e0e9efc289cf396e173031d787e45f416dc474.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ tests/vircgrouptest.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/tests/vircgrouptest.c b/tests/vircgrouptest.c
+index 7fde50b463..118b1bc246 100644
+--- a/tests/vircgrouptest.c
++++ b/tests/vircgrouptest.c
+@@ -757,7 +757,7 @@ static int testCgroupGetPercpuStats(const void *args ATTRIBUTE_UNUSED)
+ 
+         if (params[i].value.ul != expected[i]) {
+             fprintf(stderr,
+-                    "Wrong value from virCgroupGetMemoryUsage at %zu (expected %llu)\n",
++                    "Wrong value from virCgroupGetPercpuStats at %zu (expected %llu)\n",
+                     i, params[i].value.ul);
+             goto cleanup;
+         }
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-tests-qemuxml2argv-add-CAPS_ARCH_LATEST-macro.patch b/SOURCES/libvirt-tests-qemuxml2argv-add-CAPS_ARCH_LATEST-macro.patch
new file mode 100644
index 0000000..050e8f3
--- /dev/null
+++ b/SOURCES/libvirt-tests-qemuxml2argv-add-CAPS_ARCH_LATEST-macro.patch
@@ -0,0 +1,99 @@
+From d87b6566d14526883e9439ebd3f922fc7ed22abb Mon Sep 17 00:00:00 2001
+Message-Id: <d87b6566d14526883e9439ebd3f922fc7ed22abb@dist-git>
+From: Bjoern Walk <bwalk@linux.ibm.com>
+Date: Wed, 17 Apr 2019 14:46:00 +0200
+Subject: [PATCH] tests: qemuxml2argv: add CAPS_ARCH_LATEST macro
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Testing with the latest capabilities is possible with the x86_64 centric
+implemented macro CAPS_LATEST. The new macro CAPS_ARCH_LATEST provides
+the user the ability to specify the desired architecture when testing with
+the latest capabilities.
+
+Signed-off-by: Bjoern Walk <bwalk@linux.ibm.com>
+Reviewed-by: Boris Fiuczynski <fiuczy@linux.ibm.com>
+(cherry picked from commit bc4c83838d51f42b86d189280c9011494ef435f0)
+Signed-off-by: Ján Tomko <jtomko@redhat.com>
+
+RHEL 8.1: https://bugzilla.redhat.com/show_bug.cgi?id=1698855
+Message-Id: <c75aeb78417e458e1fc0c9a5994e4d462cf1c0a0.1555505143.git.jtomko@redhat.com>
+
+Reviewed-by: Andrea Bolognani <abologna@redhat.com>
+---
+ tests/qemuxml2argvtest.c | 31 +++++++++++++++++++++++--------
+ 1 file changed, 23 insertions(+), 8 deletions(-)
+
+diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
+index 690a39054e..abb256c913 100644
+--- a/tests/qemuxml2argvtest.c
++++ b/tests/qemuxml2argvtest.c
+@@ -623,10 +623,11 @@ testCompareXMLToArgv(const void *data)
+ static int
+ mymain(void)
+ {
+-    int ret = 0;
++    int ret = 0, i;
+     char *fakerootdir;
+     bool skipLegacyCPUs = false;
+-    char *capslatest_x86_64 = NULL;
++    const char *archs[] = { "x86_64", "s390x" };
++    virHashTablePtr capslatest = NULL;
+ 
+     if (VIR_STRDUP_QUIET(fakerootdir, FAKEROOTDIRTEMPLATE) < 0) {
+         fprintf(stderr, "Out of memory\n");
+@@ -695,12 +696,23 @@ mymain(void)
+     if (VIR_STRDUP_QUIET(driver.config->memoryBackingDir, "/var/lib/libvirt/qemu/ram") < 0)
+         return EXIT_FAILURE;
+ 
+-    if (!(capslatest_x86_64 = testQemuGetLatestCapsForArch(abs_srcdir "/qemucapabilitiesdata",
+-                                                           "x86_64", "xml")))
++    capslatest = virHashCreate(4, virHashValueFree);
++    if (!capslatest)
+         return EXIT_FAILURE;
+ 
+-    VIR_TEST_VERBOSE("\nlatest caps x86_64: %s\n", capslatest_x86_64);
++    VIR_TEST_VERBOSE("\n");
+ 
++    for (i = 0; i < ARRAY_CARDINALITY(archs); ++i) {
++        char *cap = testQemuGetLatestCapsForArch(abs_srcdir "/qemucapabilitiesdata",
++                                                 archs[i], "xml");
++
++        if (!cap || virHashAddEntry(capslatest, archs[i], cap) < 0)
++            return EXIT_FAILURE;
++
++        VIR_TEST_VERBOSE("latest caps for %s: %s\n", archs[i], cap);
++    }
++
++    VIR_TEST_VERBOSE("\n");
+ 
+ /**
+  * The following set of macros allows testing of XML -> argv conversion with a
+@@ -748,9 +760,12 @@ mymain(void)
+ # define DO_TEST_CAPS_VER(name, ver) \
+     DO_TEST_CAPS_ARCH_VER(name, "x86_64", ver)
+ 
++# define DO_TEST_CAPS_ARCH_LATEST(name, arch) \
++    DO_TEST_CAPS_INTERNAL(name, arch "-latest", NULL, 0, 0, arch, \
++                          virHashLookup(capslatest, arch), true)
++
+ # define DO_TEST_CAPS_LATEST(name) \
+-    DO_TEST_CAPS_INTERNAL(name, "x86_64-latest", NULL, 0, 0, "x86_64", \
+-                          capslatest_x86_64, true)
++    DO_TEST_CAPS_ARCH_LATEST(name, "x86_64")
+ 
+ /**
+  * The following test macros should be used only in cases when the tests require
+@@ -2966,7 +2981,7 @@ mymain(void)
+     VIR_FREE(driver.config->nbdTLSx509certdir);
+     qemuTestDriverFree(&driver);
+     VIR_FREE(fakerootdir);
+-    VIR_FREE(capslatest_x86_64);
++    virHashFree(capslatest);
+ 
+     return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
+ }
+-- 
+2.21.0
+
diff --git a/SOURCES/libvirt-util-Avoid-possible-error-in-virCommandMassClose.patch b/SOURCES/libvirt-util-Avoid-possible-error-in-virCommandMassClose.patch
new file mode 100644
index 0000000..9806fc9
--- /dev/null
+++ b/SOURCES/libvirt-util-Avoid-possible-error-in-virCommandMassClose.patch
@@ -0,0 +1,47 @@
+From abf1be5d4639ca4b58d56633129a7cf1389b97f3 Mon Sep 17 00:00:00 2001
+Message-Id: <abf1be5d4639ca4b58d56633129a7cf1389b97f3@dist-git>
+From: John Ferlan <jferlan@redhat.com>
+Date: Tue, 30 Jul 2019 16:04:52 +0200
+Subject: [PATCH] util: Avoid possible error in virCommandMassClose
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Avoid the chance that sysconf(_SC_OPEN_MAX) returns -1 and thus
+would cause virBitmapNew would attempt to allocate a very large
+bitmap.
+
+Found by Coverity
+
+Signed-off-by: John Ferlan <jferlan@redhat.com>
+ACKed-by: Peter Krempa <pkrempa@redhat.com>
+(cherry picked from commit 6ae4f4a4ceb123417b732e869d53099983ae8d3f)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1721434
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Message-Id: <e17edd9e1f50630c019ec7206a0f15cd8c3e474a.1564495366.git.mprivozn@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircommand.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/src/util/vircommand.c b/src/util/vircommand.c
+index dfc7e5428b..c53e3f47db 100644
+--- a/src/util/vircommand.c
++++ b/src/util/vircommand.c
+@@ -560,6 +560,11 @@ virCommandMassClose(virCommandPtr cmd,
+      * Therefore we can safely allocate memory here (and transitively call
+      * opendir/readdir) without a deadlock. */
+ 
++    if (openmax < 0) {
++        virReportSystemError(errno, "%s", _("sysconf(_SC_OPEN_MAX) failed"));
++        return -1;
++    }
++
+     if (!(fds = virBitmapNew(openmax)))
+         return -1;
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-util-Fix-virCgroupGetMemoryStat.patch b/SOURCES/libvirt-util-Fix-virCgroupGetMemoryStat.patch
new file mode 100644
index 0000000..2e3e9f5
--- /dev/null
+++ b/SOURCES/libvirt-util-Fix-virCgroupGetMemoryStat.patch
@@ -0,0 +1,89 @@
+From bab2adc524f6a9a10a89a1055d8a15ed85e1df5a Mon Sep 17 00:00:00 2001
+Message-Id: <bab2adc524f6a9a10a89a1055d8a15ed85e1df5a@dist-git>
+From: Peter Chubb <Peter.Chubb@data61.csiro.au>
+Date: Mon, 1 Jul 2019 17:08:07 +0200
+Subject: [PATCH] util: Fix virCgroupGetMemoryStat
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Commit 901d2b9c introduced virCgroupGetMemoryStat and replaced
+the LXC virLXCCgroupGetMemStat logic in commit e634c7cd0. However,
+in doing so the replacement wasn't exact as the LXC logic used
+getline() to process the cgroup controller data, while the new
+virCgroupGetMemoryStat used "memory.stat" manual buffer read/
+processing which neglected to forward through @line in order
+to read each line in the output.
+
+To fix that, we should be sure to carry forward the @line value
+for each line read updating it beyond that current @newLine value
+once we've calculated the values that we want.
+
+Signed-off-by: Peter Chubb <peter.chubb@data61.csiro.au>
+Reviewed-by: John Ferlan <jferlan@redhat.com>
+Reviewed-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit b8176d6eaa943bc9825ecc99d86c0c301e688dd0)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <e5fcbe6cbcfc0cc54ebbf01167080845f590268b.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroupv1.c | 7 ++++++-
+ src/util/vircgroupv2.c | 7 ++++++-
+ 2 files changed, 12 insertions(+), 2 deletions(-)
+
+diff --git a/src/util/vircgroupv1.c b/src/util/vircgroupv1.c
+index 97d108d3ac..3147084f21 100644
+--- a/src/util/vircgroupv1.c
++++ b/src/util/vircgroupv1.c
+@@ -1477,7 +1477,7 @@ virCgroupV1GetMemoryStat(virCgroupPtr group,
+ 
+     line = stat;
+ 
+-    while (line) {
++    while (*line) {
+         char *newLine = strchr(line, '\n');
+         char *valueStr = strchr(line, ' ');
+         unsigned long long value;
+@@ -1507,6 +1507,11 @@ virCgroupV1GetMemoryStat(virCgroupPtr group,
+             inactiveFileVal = value >> 10;
+         else if (STREQ(line, "unevictable"))
+             unevictableVal = value >> 10;
++
++        if (newLine)
++            line = newLine + 1;
++        else
++            break;
+     }
+ 
+     *cache = cacheVal;
+diff --git a/src/util/vircgroupv2.c b/src/util/vircgroupv2.c
+index d6362e2b05..bff2f78d7e 100644
+--- a/src/util/vircgroupv2.c
++++ b/src/util/vircgroupv2.c
+@@ -1069,7 +1069,7 @@ virCgroupV2GetMemoryStat(virCgroupPtr group,
+ 
+     line = stat;
+ 
+-    while (line) {
++    while (*line) {
+         char *newLine = strchr(line, '\n');
+         char *valueStr = strchr(line, ' ');
+         unsigned long long value;
+@@ -1103,6 +1103,11 @@ virCgroupV2GetMemoryStat(virCgroupPtr group,
+             inactiveFileVal = value >> 10;
+         else if (STREQ(line, "unevictable"))
+             unevictableVal = value >> 10;
++
++        if (newLine)
++            line = newLine + 1;
++        else
++            break;
+     }
+ 
+     *cache = cacheVal;
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-util-Introduce-virBitmapUnion.patch b/SOURCES/libvirt-util-Introduce-virBitmapUnion.patch
new file mode 100644
index 0000000..d2895be
--- /dev/null
+++ b/SOURCES/libvirt-util-Introduce-virBitmapUnion.patch
@@ -0,0 +1,149 @@
+From 6ee2c599db989189e639c3de88d20045c62a1d2c Mon Sep 17 00:00:00 2001
+Message-Id: <6ee2c599db989189e639c3de88d20045c62a1d2c@dist-git>
+From: Andrea Bolognani <abologna@redhat.com>
+Date: Tue, 11 Jun 2019 10:55:01 +0200
+Subject: [PATCH] util: Introduce virBitmapUnion()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Andrea Bolognani <abologna@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit 1b2ac8010cc1fe871f538b3f48c5e48213c5c074)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1716908
+
+Signed-off-by: Andrea Bolognani <abologna@redhat.com>
+Message-Id: <20190611085506.12564-2-abologna@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/libvirt_private.syms |  1 +
+ src/util/virbitmap.c     | 27 +++++++++++++++++++++++++++
+ src/util/virbitmap.h     |  4 ++++
+ tests/virbitmaptest.c    | 38 ++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 70 insertions(+)
+
+diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
+index ee7625b0f3..05c96c29e2 100644
+--- a/src/libvirt_private.syms
++++ b/src/libvirt_private.syms
+@@ -1476,6 +1476,7 @@ virBitmapSubtract;
+ virBitmapToData;
+ virBitmapToDataBuf;
+ virBitmapToString;
++virBitmapUnion;
+ 
+ 
+ # util/virbuffer.h
+diff --git a/src/util/virbitmap.c b/src/util/virbitmap.c
+index ef18dad255..49e542a4e6 100644
+--- a/src/util/virbitmap.c
++++ b/src/util/virbitmap.c
+@@ -1265,6 +1265,33 @@ virBitmapIntersect(virBitmapPtr a,
+ }
+ 
+ 
++/**
++ * virBitmapUnion:
++ * @a: bitmap, modified to contain result
++ * @b: other bitmap
++ *
++ * Performs union of two bitmaps: a = union(a, b)
++ *
++ * Returns 0 on success, <0 on failure.
++ */
++int
++virBitmapUnion(virBitmapPtr a,
++               const virBitmap *b)
++{
++    size_t i;
++
++    if (a->nbits < b->nbits &&
++        virBitmapExpand(a, b->nbits - 1) < 0) {
++        return -1;
++    }
++
++    for (i = 0; i < b->map_len; i++)
++        a->map[i] |= b->map[i];
++
++    return 0;
++}
++
++
+ /**
+  * virBitmapSubtract:
+  * @a: minuend/result
+diff --git a/src/util/virbitmap.h b/src/util/virbitmap.h
+index 312e7e2933..5934508d11 100644
+--- a/src/util/virbitmap.h
++++ b/src/util/virbitmap.h
+@@ -151,6 +151,10 @@ bool virBitmapOverlaps(virBitmapPtr b1,
+ void virBitmapIntersect(virBitmapPtr a, virBitmapPtr b)
+     ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
+ 
++int virBitmapUnion(virBitmapPtr a,
++                   const virBitmap *b)
++    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
++
+ void virBitmapSubtract(virBitmapPtr a, virBitmapPtr b)
+     ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
+ 
+diff --git a/tests/virbitmaptest.c b/tests/virbitmaptest.c
+index 2fbafc0a76..cafe865dde 100644
+--- a/tests/virbitmaptest.c
++++ b/tests/virbitmaptest.c
+@@ -740,6 +740,34 @@ test14(const void *opaque)
+     return ret;
+ }
+ 
++/* virBitmapUnion() */
++static int
++test15(const void *opaque)
++{
++    const struct testBinaryOpData *data = opaque;
++    VIR_AUTOPTR(virBitmap) amap = NULL;
++    VIR_AUTOPTR(virBitmap) bmap = NULL;
++    VIR_AUTOPTR(virBitmap) resmap = NULL;
++
++    if (!(amap = virBitmapParseUnlimited(data->a)) ||
++        !(bmap = virBitmapParseUnlimited(data->b)) ||
++        !(resmap = virBitmapParseUnlimited(data->res))) {
++        return -1;
++    }
++
++    if (virBitmapUnion(amap, bmap) < 0)
++        return -1;
++
++    if (!virBitmapEqual(amap, resmap)) {
++        fprintf(stderr,
++                "\n bitmap union failed: union('%s', '%s') != '%s'\n",
++                data->a, data->b, data->res);
++        return -1;
++    }
++
++    return 0;
++}
++
+ 
+ #define TESTBINARYOP(A, B, RES, FUNC) \
+     testBinaryOpData.a = A; \
+@@ -798,6 +826,16 @@ mymain(void)
+     TESTBINARYOP("0-3", "0,^0", "0-3", test14);
+     TESTBINARYOP("0,2", "1,3", "0,2", test14);
+ 
++    /* virBitmapUnion() */
++    virTestCounterReset("test15-");
++    TESTBINARYOP("0-1", "0-1", "0-1", test15);
++    TESTBINARYOP("0", "1", "0-1", test15);
++    TESTBINARYOP("0-1", "2-3", "0-3", test15);
++    TESTBINARYOP("0-3", "1-2", "0-3", test15);
++    TESTBINARYOP("0,^0", "12345", "12345", test15);
++    TESTBINARYOP("12345", "0,^0", "12345", test15);
++    TESTBINARYOP("0,^0", "0,^0", "0,^0", test15);
++
+     return ret;
+ }
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-util-Introduce-virNumaNodesetToCPUset.patch b/SOURCES/libvirt-util-Introduce-virNumaNodesetToCPUset.patch
new file mode 100644
index 0000000..f35c94e
--- /dev/null
+++ b/SOURCES/libvirt-util-Introduce-virNumaNodesetToCPUset.patch
@@ -0,0 +1,128 @@
+From e624d2040a5a8e16e670accc52e110393d9fb2b8 Mon Sep 17 00:00:00 2001
+Message-Id: <e624d2040a5a8e16e670accc52e110393d9fb2b8@dist-git>
+From: Andrea Bolognani <abologna@redhat.com>
+Date: Tue, 11 Jun 2019 10:55:02 +0200
+Subject: [PATCH] util: Introduce virNumaNodesetToCPUset()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This helper converts a set of NUMA node to the set of CPUs
+they contain.
+
+Signed-off-by: Andrea Bolognani <abologna@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit 2d2b26f96fed1e95dd4495168cee73c5c4092634)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1716908
+
+Signed-off-by: Andrea Bolognani <abologna@redhat.com>
+Message-Id: <20190611085506.12564-3-abologna@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/libvirt_private.syms |  1 +
+ src/util/virnuma.c       | 55 ++++++++++++++++++++++++++++++++++++++++
+ src/util/virnuma.h       |  2 ++
+ 3 files changed, 58 insertions(+)
+
+diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
+index 05c96c29e2..7c48908a54 100644
+--- a/src/libvirt_private.syms
++++ b/src/libvirt_private.syms
+@@ -2485,6 +2485,7 @@ virNumaGetPages;
+ virNumaIsAvailable;
+ virNumaNodeIsAvailable;
+ virNumaNodesetIsAvailable;
++virNumaNodesetToCPUset;
+ virNumaSetPagePoolSize;
+ virNumaSetupMemoryPolicy;
+ 
+diff --git a/src/util/virnuma.c b/src/util/virnuma.c
+index fd15714553..75f80dcd30 100644
+--- a/src/util/virnuma.c
++++ b/src/util/virnuma.c
+@@ -311,6 +311,49 @@ virNumaGetNodeCPUs(int node,
+ # undef MASK_CPU_ISSET
+ # undef n_bits
+ 
++/**
++ * virNumaNodesetToCPUset:
++ * @nodeset: bitmap containing a set of NUMA nodes
++ * @cpuset: return location for a bitmap containing a set of CPUs
++ *
++ * Convert a set of NUMA node to the set of CPUs they contain.
++ *
++ * Returns 0 on success, <0 on failure.
++ */
++int
++virNumaNodesetToCPUset(virBitmapPtr nodeset,
++                       virBitmapPtr *cpuset)
++{
++    VIR_AUTOPTR(virBitmap) allNodesCPUs = NULL;
++    size_t nodesetSize;
++    size_t i;
++
++    *cpuset = NULL;
++
++    if (!nodeset)
++        return 0;
++
++    allNodesCPUs = virBitmapNewEmpty();
++    nodesetSize = virBitmapSize(nodeset);
++
++    for (i = 0; i < nodesetSize; i++) {
++        VIR_AUTOPTR(virBitmap) nodeCPUs = NULL;
++
++        if (!virBitmapIsBitSet(nodeset, i))
++            continue;
++
++        if (virNumaGetNodeCPUs(i, &nodeCPUs) < 0)
++            return -1;
++
++        if (virBitmapUnion(allNodesCPUs, nodeCPUs) < 0)
++            return -1;
++    }
++
++    VIR_STEAL_PTR(*cpuset, allNodesCPUs);
++
++    return 0;
++}
++
+ #else /* !WITH_NUMACTL */
+ 
+ int
+@@ -365,6 +408,18 @@ virNumaGetNodeCPUs(int node ATTRIBUTE_UNUSED,
+                    _("NUMA isn't available on this host"));
+     return -1;
+ }
++
++int
++virNumaNodesetToCPUset(virBitmapPtr nodeset ATTRIBUTE_UNUSED,
++                       virBitmapPtr *cpuset)
++{
++    *cpuset = NULL;
++
++    virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
++                   _("NUMA isn't available on this host"));
++    return -1;
++}
++
+ #endif /* !WITH_NUMACTL */
+ 
+ /**
+diff --git a/src/util/virnuma.h b/src/util/virnuma.h
+index a3ffb6d6c7..df7911db4e 100644
+--- a/src/util/virnuma.h
++++ b/src/util/virnuma.h
+@@ -48,6 +48,8 @@ int virNumaGetNodeMemory(int node,
+ unsigned int virNumaGetMaxCPUs(void);
+ 
+ int virNumaGetNodeCPUs(int node, virBitmapPtr *cpus) ATTRIBUTE_NOINLINE;
++int virNumaNodesetToCPUset(virBitmapPtr nodeset,
++                           virBitmapPtr *cpuset);
+ 
+ int virNumaGetPageInfo(int node,
+                        unsigned int page_size,
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-util-Propagate-numad-failures-correctly.patch b/SOURCES/libvirt-util-Propagate-numad-failures-correctly.patch
new file mode 100644
index 0000000..6414f96
--- /dev/null
+++ b/SOURCES/libvirt-util-Propagate-numad-failures-correctly.patch
@@ -0,0 +1,63 @@
+From 8722ee949b2099c4a4ac246fba868ae47cb828d2 Mon Sep 17 00:00:00 2001
+Message-Id: <8722ee949b2099c4a4ac246fba868ae47cb828d2@dist-git>
+From: Andrea Bolognani <abologna@redhat.com>
+Date: Tue, 11 Jun 2019 10:13:50 +0200
+Subject: [PATCH] util: Propagate numad failures correctly
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Right now, if numad fails, we raise an error but return an
+empty string to the caller instead of a NULL pointer, which
+means processing will continue and the user will see
+
+  # virsh start guest
+  error: Failed to start domain guest
+  error: invalid argument: Failed to parse bitmap ''
+
+instead of a more reasonable
+
+  # virsh start guest
+  error: Failed to start domain guest
+  error: operation failed: Failed to query numad for the advisory nodeset
+
+Make sure the user gets a better error message.
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1716387
+
+Signed-off-by: Andrea Bolognani <abologna@redhat.com>
+Reviewed-by: Daniel Henrique Barboza <danielhb413@gmail.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit b34fb1fb6f99628932ad68db1ce4985a06def17f)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1716907
+
+Signed-off-by: Andrea Bolognani <abologna@redhat.com>
+Message-Id: <20190611081350.6476-2-abologna@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/virnuma.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/src/util/virnuma.c b/src/util/virnuma.c
+index 784db0a7ce..fd15714553 100644
+--- a/src/util/virnuma.c
++++ b/src/util/virnuma.c
+@@ -66,10 +66,12 @@ virNumaGetAutoPlacementAdvice(unsigned short vcpus,
+ 
+     virCommandSetOutputBuffer(cmd, &output);
+ 
+-    if (virCommandRun(cmd, NULL) < 0)
+-        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
++    if (virCommandRun(cmd, NULL) < 0) {
++        virReportError(VIR_ERR_OPERATION_FAILED, "%s",
+                        _("Failed to query numad for the "
+                          "advisory nodeset"));
++        VIR_FREE(output);
++    }
+ 
+     virCommandFree(cmd);
+     return output;
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-util-Rework-virStringListAdd.patch b/SOURCES/libvirt-util-Rework-virStringListAdd.patch
new file mode 100644
index 0000000..1fcd4d1
--- /dev/null
+++ b/SOURCES/libvirt-util-Rework-virStringListAdd.patch
@@ -0,0 +1,145 @@
+From e7d53ee08ec9929974fb4159be8359c4ba88f5b2 Mon Sep 17 00:00:00 2001
+Message-Id: <e7d53ee08ec9929974fb4159be8359c4ba88f5b2@dist-git>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Fri, 21 Jun 2019 09:26:05 +0200
+Subject: [PATCH] util: Rework virStringListAdd
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+So every caller does the same: they use virStringListAdd() to add
+new item into the list and then free the old copy to replace it
+with new list. It's not very memory effective, nor environmental
+friendly.
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Reviewed-by: Erik Skultety <eskultet@redhat.com>
+(cherry picked from commit 71a390e0fdb4e6cbeaef4c9045a501a6c8de5412)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1697627
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <a9764c87b3f557a2fd9ac8c5fcd077a3d713e2ca.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/virmacmap.c  |  8 ++------
+ src/util/virstring.c  | 33 ++++++++++++---------------------
+ src/util/virstring.h  |  4 ++--
+ tests/virstringtest.c |  6 +-----
+ 4 files changed, 17 insertions(+), 34 deletions(-)
+
+diff --git a/src/util/virmacmap.c b/src/util/virmacmap.c
+index 88ca9b3f36..c7b700fa05 100644
+--- a/src/util/virmacmap.c
++++ b/src/util/virmacmap.c
+@@ -90,7 +90,6 @@ virMacMapAddLocked(virMacMapPtr mgr,
+ {
+     int ret = -1;
+     char **macsList = NULL;
+-    char **newMacsList = NULL;
+ 
+     if ((macsList = virHashLookup(mgr->macs, domain)) &&
+         virStringListHasString((const char**) macsList, mac)) {
+@@ -98,15 +97,12 @@ virMacMapAddLocked(virMacMapPtr mgr,
+         goto cleanup;
+     }
+ 
+-    if (!(newMacsList = virStringListAdd((const char **) macsList, mac)) ||
+-        virHashUpdateEntry(mgr->macs, domain, newMacsList) < 0)
++    if (virStringListAdd(&macsList, mac) < 0 ||
++        virHashUpdateEntry(mgr->macs, domain, macsList) < 0)
+         goto cleanup;
+-    newMacsList = NULL;
+-    virStringListFree(macsList);
+ 
+     ret = 0;
+  cleanup:
+-    virStringListFree(newMacsList);
+     return ret;
+ }
+ 
+diff --git a/src/util/virstring.c b/src/util/virstring.c
+index 0f13b6c664..74fa2f6a94 100644
+--- a/src/util/virstring.c
++++ b/src/util/virstring.c
+@@ -175,32 +175,23 @@ char *virStringListJoin(const char **strings,
+  * @strings: a NULL-terminated array of strings
+  * @item: string to add
+  *
+- * Creates new strings list with all strings duplicated and @item
+- * at the end of the list. Callers is responsible for freeing
+- * both @strings and returned list.
++ * Appends @item into string list @strings. If *@strings is not
++ * allocated yet new string list is created.
++ *
++ * Returns: 0 on success,
++ *         -1 otherwise
+  */
+-char **
+-virStringListAdd(const char **strings,
++int
++virStringListAdd(char ***strings,
+                  const char *item)
+ {
+-    char **ret = NULL;
+-    size_t i = virStringListLength(strings);
++    size_t i = virStringListLength((const char **) *strings);
+ 
+-    if (VIR_ALLOC_N(ret, i + 2) < 0)
+-        goto error;
++    if (VIR_EXPAND_N(*strings, i, 2) < 0 ||
++        VIR_STRDUP((*strings)[i - 2], item) < 0)
++        return -1;
+ 
+-    for (i = 0; strings && strings[i]; i++) {
+-        if (VIR_STRDUP(ret[i], strings[i]) < 0)
+-            goto error;
+-    }
+-
+-    if (VIR_STRDUP(ret[i], item) < 0)
+-        goto error;
+-
+-    return ret;
+- error:
+-    virStringListFree(ret);
+-    return NULL;
++    return 0;
+ }
+ 
+ 
+diff --git a/src/util/virstring.h b/src/util/virstring.h
+index e68b9eec79..a3db08ce58 100644
+--- a/src/util/virstring.h
++++ b/src/util/virstring.h
+@@ -41,8 +41,8 @@ char *virStringListJoin(const char **strings,
+                         const char *delim)
+     ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
+ 
+-char **virStringListAdd(const char **strings,
+-                        const char *item);
++int virStringListAdd(char ***strings,
++                     const char *item);
+ void virStringListRemove(char ***strings,
+                          const char *item);
+ 
+diff --git a/tests/virstringtest.c b/tests/virstringtest.c
+index 1230aba5b7..1a1e6364d1 100644
+--- a/tests/virstringtest.c
++++ b/tests/virstringtest.c
+@@ -179,12 +179,8 @@ static int testAdd(const void *args)
+     size_t i;
+ 
+     for (i = 0; data->tokens[i]; i++) {
+-        char **tmp = virStringListAdd((const char **)list, data->tokens[i]);
+-        if (!tmp)
++        if (virStringListAdd(&list, data->tokens[i]) < 0)
+             goto cleanup;
+-        virStringListFree(list);
+-        list = tmp;
+-        tmp = NULL;
+     }
+ 
+     if (!list &&
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-util-alloc-add-macros-for-implementing-automatic-cleanup-functionality.patch b/SOURCES/libvirt-util-alloc-add-macros-for-implementing-automatic-cleanup-functionality.patch
new file mode 100644
index 0000000..8d9fb2c
--- /dev/null
+++ b/SOURCES/libvirt-util-alloc-add-macros-for-implementing-automatic-cleanup-functionality.patch
@@ -0,0 +1,78 @@
+From 78f99c03b31dd7850a2eeebbf88e47e391376293 Mon Sep 17 00:00:00 2001
+Message-Id: <78f99c03b31dd7850a2eeebbf88e47e391376293@dist-git>
+From: Sukrit Bhatnagar <skrtbhtngr@gmail.com>
+Date: Fri, 3 May 2019 13:54:30 +0200
+Subject: [PATCH] util: alloc: add macros for implementing automatic cleanup
+ functionality
+
+New macros are introduced which help in adding GNU C's cleanup
+attribute to variable declarations. Variables declared with these
+macros will have their allocated memory freed automatically when
+they go out of scope.
+
+Signed-off-by: Sukrit Bhatnagar <skrtbhtngr@gmail.com>
+Reviewed-by: Erik Skultety <eskultet@redhat.com>
+(cherry picked from commit dcec13f5a2ba17223d403ff9e9fed916a4dd9c04)
+
+https: //bugzilla.redhat.com/show_bug.cgi?id=1505998
+Signed-off-by: Erik Skultety <eskultet@redhat.com>
+Message-Id: <7ca85d7157eda723aac994f7c9f0f04ed9a35ab5.1556884442.git.eskultet@redhat.com>
+Reviewed-by: Andrea Bolognani <abologna@redhat.com>
+---
+ src/util/viralloc.h | 42 ++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 42 insertions(+)
+
+diff --git a/src/util/viralloc.h b/src/util/viralloc.h
+index 69d0f904f1..a23aa188bb 100644
+--- a/src/util/viralloc.h
++++ b/src/util/viralloc.h
+@@ -596,4 +596,46 @@ void virAllocTestInit(void);
+ int virAllocTestCount(void);
+ void virAllocTestOOM(int n, int m);
+ void virAllocTestHook(void (*func)(int, void*), void *data);
++
++# define VIR_AUTOPTR_FUNC_NAME(type) type##AutoPtrFree
++
++/**
++ * VIR_DEFINE_AUTOPTR_FUNC:
++ * @type: type of the variable to be freed automatically
++ * @func: cleanup function to be automatically called
++ *
++ * This macro defines a function for automatic freeing of
++ * resources allocated to a variable of type @type. This newly
++ * defined function works as a necessary wrapper around @func.
++ */
++# define VIR_DEFINE_AUTOPTR_FUNC(type, func) \
++    static inline void VIR_AUTOPTR_FUNC_NAME(type)(type **_ptr) \
++    { \
++        if (*_ptr) \
++            (func)(*_ptr); \
++        *_ptr = NULL; \
++    } \
++
++/**
++ * VIR_AUTOFREE:
++ * @type: type of the variable to be freed automatically
++ *
++ * Macro to automatically free the memory allocated to
++ * the variable declared with it by calling virFree
++ * when the variable goes out of scope.
++ */
++# define VIR_AUTOFREE(type) __attribute__((cleanup(virFree))) type
++
++/**
++ * VIR_AUTOPTR:
++ * @type: type of the variable to be freed automatically
++ *
++ * Macro to automatically free the memory allocated to
++ * the variable declared with it by calling the function
++ * defined by VIR_DEFINE_AUTOPTR_FUNC when the variable
++ * goes out of scope.
++ */
++# define VIR_AUTOPTR(type) \
++    __attribute__((cleanup(VIR_AUTOPTR_FUNC_NAME(type)))) type *
++
+ #endif /* __VIR_MEMORY_H_ */
+-- 
+2.21.0
+
diff --git a/SOURCES/libvirt-util-bitmap-define-cleanup-function-using-VIR_DEFINE_AUTOPTR_FUNC.patch b/SOURCES/libvirt-util-bitmap-define-cleanup-function-using-VIR_DEFINE_AUTOPTR_FUNC.patch
new file mode 100644
index 0000000..278fe5f
--- /dev/null
+++ b/SOURCES/libvirt-util-bitmap-define-cleanup-function-using-VIR_DEFINE_AUTOPTR_FUNC.patch
@@ -0,0 +1,66 @@
+From 2fe1b73a5dbbfd79c3a1a8c48747a68846785e3b Mon Sep 17 00:00:00 2001
+Message-Id: <2fe1b73a5dbbfd79c3a1a8c48747a68846785e3b@dist-git>
+From: Sukrit Bhatnagar <skrtbhtngr@gmail.com>
+Date: Wed, 5 Jun 2019 11:33:27 +0200
+Subject: [PATCH] util: bitmap: define cleanup function using
+ VIR_DEFINE_AUTOPTR_FUNC
+
+Using the new VIR_DEFINE_AUTOPTR_FUNC macro defined in
+src/util/viralloc.h, define a new wrapper around an existing
+cleanup function which will be called when a variable declared
+with VIR_AUTOPTR macro goes out of scope. Also, drop the redundant
+viralloc.h include, since that has moved from the source module into the
+header.
+
+When a variable of type virBitmapPtr is declared using
+VIR_AUTOPTR, the function virBitmapFree will be run
+automatically on it when it goes out of scope.
+
+Signed-off-by: Sukrit Bhatnagar <skrtbhtngr@gmail.com>
+Reviewed-by: Erik Skultety <eskultet@redhat.com>
+(cherry picked from commit a3c915e662f8c25cac683e20bbc419b497555e13)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1716943
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Message-Id: <fcbb5d4453100962a2fc83e486da799012eec675.1559727075.git.mprivozn@redhat.com>
+Reviewed-by: Andrea Bolognani <abologna@redhat.com>
+---
+ src/util/virbitmap.c | 1 -
+ src/util/virbitmap.h | 3 +++
+ 2 files changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/src/util/virbitmap.c b/src/util/virbitmap.c
+index 0cc5292d8c..ef18dad255 100644
+--- a/src/util/virbitmap.c
++++ b/src/util/virbitmap.c
+@@ -31,7 +31,6 @@
+ #include <sys/types.h>
+ 
+ #include "virbitmap.h"
+-#include "viralloc.h"
+ #include "virbuffer.h"
+ #include "c-ctype.h"
+ #include "count-one-bits.h"
+diff --git a/src/util/virbitmap.h b/src/util/virbitmap.h
+index 2464814055..312e7e2933 100644
+--- a/src/util/virbitmap.h
++++ b/src/util/virbitmap.h
+@@ -25,6 +25,7 @@
+ # define __BITMAP_H__
+ 
+ # include "internal.h"
++# include "viralloc.h"
+ 
+ # include <sys/types.h>
+ 
+@@ -155,4 +156,6 @@ void virBitmapSubtract(virBitmapPtr a, virBitmapPtr b)
+ 
+ void virBitmapShrink(virBitmapPtr map, size_t b);
+ 
++VIR_DEFINE_AUTOPTR_FUNC(virBitmap, virBitmapFree)
++
+ #endif
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-util-cgroup-use-VIR_AUTOFREE-instead-of-VIR_FREE-for-scalar-types.patch b/SOURCES/libvirt-util-cgroup-use-VIR_AUTOFREE-instead-of-VIR_FREE-for-scalar-types.patch
new file mode 100644
index 0000000..bfe6577
--- /dev/null
+++ b/SOURCES/libvirt-util-cgroup-use-VIR_AUTOFREE-instead-of-VIR_FREE-for-scalar-types.patch
@@ -0,0 +1,1528 @@
+From 02e35feddf3a72cfd52db8485f3de637b7f518ea Mon Sep 17 00:00:00 2001
+Message-Id: <02e35feddf3a72cfd52db8485f3de637b7f518ea@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:05:47 +0200
+Subject: [PATCH] util: cgroup: use VIR_AUTOFREE instead of VIR_FREE for scalar
+ types
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+By making use of GNU C's cleanup attribute handled by the
+VIR_AUTOFREE macro for declaring scalar variables, majority
+of the VIR_FREE calls can be dropped, which in turn leads to
+getting rid of most of our cleanup sections.
+
+Signed-off-by: Sukrit Bhatnagar <skrtbhtngr@gmail.com>
+Reviewed-by: Erik Skultety <eskultet@redhat.com>
+(cherry picked from commit 94f1855f099445d4a18d5e5f114b60b7c58798ad)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <97a6e61acf698facf2554b05d03cd490ecc25f7e.1561993099.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c | 528 +++++++++++++++----------------------------
+ 1 file changed, 181 insertions(+), 347 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index e810a3d81d..6bf4e88da1 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -163,7 +163,7 @@ virCgroupPartitionNeedsEscaping(const char *path)
+ {
+     FILE *fp = NULL;
+     int ret = 0;
+-    char *line = NULL;
++    VIR_AUTOFREE(char *) line = NULL;
+     size_t buflen;
+ 
+     /* If it starts with 'cgroup.' or a '_' of any
+@@ -223,7 +223,6 @@ virCgroupPartitionNeedsEscaping(const char *path)
+     }
+ 
+  cleanup:
+-    VIR_FREE(line);
+     VIR_FORCE_FCLOSE(fp);
+     return ret;
+ }
+@@ -256,41 +255,40 @@ virCgroupValidateMachineGroup(virCgroupPtr group,
+                               const char *machinename)
+ {
+     size_t i;
+-    bool valid = false;
+-    char *partname = NULL;
+-    char *scopename_old = NULL;
+-    char *scopename_new = NULL;
+-    char *partmachinename = NULL;
++    VIR_AUTOFREE(char *) partname = NULL;
++    VIR_AUTOFREE(char *) scopename_old = NULL;
++    VIR_AUTOFREE(char *) scopename_new = NULL;
++    VIR_AUTOFREE(char *) partmachinename = NULL;
+ 
+     if (virAsprintf(&partname, "%s.libvirt-%s",
+                     name, drivername) < 0)
+-        goto cleanup;
++        return false;
+ 
+     if (virCgroupPartitionEscape(&partname) < 0)
+-        goto cleanup;
++        return false;
+ 
+     if (machinename &&
+         (virAsprintf(&partmachinename, "%s.libvirt-%s",
+                      machinename, drivername) < 0 ||
+          virCgroupPartitionEscape(&partmachinename) < 0))
+-        goto cleanup;
++        return false;
+ 
+     if (!(scopename_old = virSystemdMakeScopeName(name, drivername, true)))
+-        goto cleanup;
++        return false;
+ 
+     /* We should keep trying even if this failed */
+     if (!machinename)
+         virResetLastError();
+     else if (!(scopename_new = virSystemdMakeScopeName(machinename,
+                                                        drivername, false)))
+-        goto cleanup;
++        return false;
+ 
+     if (virCgroupPartitionEscape(&scopename_old) < 0)
+-        goto cleanup;
++        return false;
+ 
+     if (scopename_new &&
+         virCgroupPartitionEscape(&scopename_new) < 0)
+-        goto cleanup;
++        return false;
+ 
+     for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
+         char *tmp;
+@@ -303,7 +301,7 @@ virCgroupValidateMachineGroup(virCgroupPtr group,
+ 
+         tmp = strrchr(group->controllers[i].placement, '/');
+         if (!tmp)
+-            goto cleanup;
++            return false;
+ 
+         if (stripEmulatorSuffix &&
+             (i == VIR_CGROUP_CONTROLLER_CPU ||
+@@ -313,7 +311,7 @@ virCgroupValidateMachineGroup(virCgroupPtr group,
+                 *tmp = '\0';
+             tmp = strrchr(group->controllers[i].placement, '/');
+             if (!tmp)
+-                goto cleanup;
++                return false;
+         }
+ 
+         tmp++;
+@@ -329,18 +327,11 @@ virCgroupValidateMachineGroup(virCgroupPtr group,
+                       tmp, virCgroupControllerTypeToString(i),
+                       name, NULLSTR(machinename), partname,
+                       scopename_old, NULLSTR(scopename_new));
+-            goto cleanup;
++            return false;
+         }
+     }
+ 
+-    valid = true;
+-
+- cleanup:
+-    VIR_FREE(partmachinename);
+-    VIR_FREE(partname);
+-    VIR_FREE(scopename_old);
+-    VIR_FREE(scopename_new);
+-    return valid;
++    return true;
+ }
+ 
+ 
+@@ -378,7 +369,6 @@ virCgroupDetectMountsFromFile(virCgroupPtr group,
+     FILE *mounts = NULL;
+     struct mntent entry;
+     char buf[CGROUP_MAX_VAL];
+-    char *linksrc = NULL;
+     int ret = -1;
+ 
+     mounts = fopen(path, "r");
+@@ -433,8 +423,9 @@ virCgroupDetectMountsFromFile(virCgroupPtr group,
+                     /* If it is a co-mount it has a filename like "cpu,cpuacct"
+                      * and we must identify the symlink path */
+                     if (checkLinks && strchr(tmp2 + 1, ',')) {
++                        VIR_AUTOFREE(char *) linksrc = NULL;
++
+                         *tmp2 = '\0';
+-                        VIR_FREE(linksrc);
+                         if (virAsprintf(&linksrc, "%s/%s",
+                                         entry.mnt_dir, typestr) < 0)
+                             goto cleanup;
+@@ -468,7 +459,6 @@ virCgroupDetectMountsFromFile(virCgroupPtr group,
+ 
+     ret = 0;
+  cleanup:
+-    VIR_FREE(linksrc);
+     VIR_FORCE_FCLOSE(mounts);
+     return ret;
+ }
+@@ -547,7 +537,7 @@ virCgroupDetectPlacement(virCgroupPtr group,
+     FILE *mapping  = NULL;
+     char line[1024];
+     int ret = -1;
+-    char *procfile;
++    VIR_AUTOFREE(char *) procfile = NULL;
+ 
+     VIR_DEBUG("Detecting placement for pid %lld path %s",
+               (long long) pid, path);
+@@ -628,9 +618,7 @@ virCgroupDetectPlacement(virCgroupPtr group,
+     ret = 0;
+ 
+  cleanup:
+-    VIR_FREE(procfile);
+     VIR_FORCE_FCLOSE(mapping);
+-
+     return ret;
+ }
+ 
+@@ -786,8 +774,7 @@ virCgroupSetValueStr(virCgroupPtr group,
+                      const char *key,
+                      const char *value)
+ {
+-    int ret = -1;
+-    char *keypath = NULL;
++    VIR_AUTOFREE(char *) keypath = NULL;
+     char *tmp = NULL;
+ 
+     if (virCgroupPathOfController(group, controller, key, &keypath) < 0)
+@@ -800,18 +787,14 @@ virCgroupSetValueStr(virCgroupPtr group,
+             virReportSystemError(errno,
+                                  _("Invalid value '%s' for '%s'"),
+                                  value, tmp + 1);
+-            goto cleanup;
++            return -1;
+         }
+         virReportSystemError(errno,
+                              _("Unable to write to '%s'"), keypath);
+-        goto cleanup;
++        return -1;
+     }
+ 
+-    ret = 0;
+-
+- cleanup:
+-    VIR_FREE(keypath);
+-    return ret;
++    return 0;
+ }
+ 
+ 
+@@ -821,8 +804,8 @@ virCgroupGetValueStr(virCgroupPtr group,
+                      const char *key,
+                      char **value)
+ {
+-    char *keypath = NULL;
+-    int ret = -1, rc;
++    VIR_AUTOFREE(char *) keypath = NULL;
++    int rc;
+ 
+     *value = NULL;
+ 
+@@ -834,18 +817,14 @@ virCgroupGetValueStr(virCgroupPtr group,
+     if ((rc = virFileReadAll(keypath, 1024*1024, value)) < 0) {
+         virReportSystemError(errno,
+                              _("Unable to read from '%s'"), keypath);
+-        goto cleanup;
++        return -1;
+     }
+ 
+     /* Terminated with '\n' has sometimes harmful effects to the caller */
+     if (rc > 0 && (*value)[rc - 1] == '\n')
+         (*value)[rc - 1] = '\0';
+ 
+-    ret = 0;
+-
+- cleanup:
+-    VIR_FREE(keypath);
+-    return ret;
++    return 0;
+ }
+ 
+ 
+@@ -856,8 +835,8 @@ virCgroupGetValueForBlkDev(virCgroupPtr group,
+                            const char *path,
+                            char **value)
+ {
+-    char *prefix = NULL;
+-    char *str = NULL;
++    VIR_AUTOFREE(char *) prefix = NULL;
++    VIR_AUTOFREE(char *) str = NULL;
+     char **lines = NULL;
+     int ret = -1;
+ 
+@@ -875,8 +854,6 @@ virCgroupGetValueForBlkDev(virCgroupPtr group,
+ 
+     ret = 0;
+  error:
+-    VIR_FREE(str);
+-    VIR_FREE(prefix);
+     virStringListFree(lines);
+     return ret;
+ }
+@@ -888,17 +865,12 @@ virCgroupSetValueU64(virCgroupPtr group,
+                      const char *key,
+                      unsigned long long int value)
+ {
+-    char *strval = NULL;
+-    int ret;
++    VIR_AUTOFREE(char *) strval = NULL;
+ 
+     if (virAsprintf(&strval, "%llu", value) < 0)
+         return -1;
+ 
+-    ret = virCgroupSetValueStr(group, controller, key, strval);
+-
+-    VIR_FREE(strval);
+-
+-    return ret;
++    return virCgroupSetValueStr(group, controller, key, strval);
+ }
+ 
+ 
+@@ -908,17 +880,12 @@ virCgroupSetValueI64(virCgroupPtr group,
+                      const char *key,
+                      long long int value)
+ {
+-    char *strval = NULL;
+-    int ret;
++    VIR_AUTOFREE(char *) strval = NULL;
+ 
+     if (virAsprintf(&strval, "%lld", value) < 0)
+         return -1;
+ 
+-    ret = virCgroupSetValueStr(group, controller, key, strval);
+-
+-    VIR_FREE(strval);
+-
+-    return ret;
++    return virCgroupSetValueStr(group, controller, key, strval);
+ }
+ 
+ 
+@@ -928,24 +895,19 @@ virCgroupGetValueI64(virCgroupPtr group,
+                      const char *key,
+                      long long int *value)
+ {
+-    char *strval = NULL;
+-    int ret = -1;
++    VIR_AUTOFREE(char *) strval = NULL;
+ 
+     if (virCgroupGetValueStr(group, controller, key, &strval) < 0)
+-        goto cleanup;
++        return -1;
+ 
+     if (virStrToLong_ll(strval, NULL, 10, value) < 0) {
+         virReportError(VIR_ERR_INTERNAL_ERROR,
+                        _("Unable to parse '%s' as an integer"),
+                        strval);
+-        goto cleanup;
++        return -1;
+     }
+ 
+-    ret = 0;
+-
+- cleanup:
+-    VIR_FREE(strval);
+-    return ret;
++    return 0;
+ }
+ 
+ 
+@@ -955,24 +917,19 @@ virCgroupGetValueU64(virCgroupPtr group,
+                      const char *key,
+                      unsigned long long int *value)
+ {
+-    char *strval = NULL;
+-    int ret = -1;
++    VIR_AUTOFREE(char *) strval = NULL;
+ 
+     if (virCgroupGetValueStr(group, controller, key, &strval) < 0)
+-        goto cleanup;
++        return -1;
+ 
+     if (virStrToLong_ull(strval, NULL, 10, value) < 0) {
+         virReportError(VIR_ERR_INTERNAL_ERROR,
+                        _("Unable to parse '%s' as an integer"),
+                        strval);
+-        goto cleanup;
++        return -1;
+     }
+ 
+-    ret = 0;
+-
+- cleanup:
+-    VIR_FREE(strval);
+-    return ret;
++    return 0;
+ }
+ 
+ 
+@@ -988,7 +945,7 @@ virCgroupCpuSetInherit(virCgroupPtr parent, virCgroupPtr group)
+ 
+     VIR_DEBUG("Setting up inheritance %s -> %s", parent->path, group->path);
+     for (i = 0; i < ARRAY_CARDINALITY(inherit_values); i++) {
+-        char *value;
++        VIR_AUTOFREE(char *) value = NULL;
+ 
+         if (virCgroupGetValueStr(parent,
+                                  VIR_CGROUP_CONTROLLER_CPUSET,
+@@ -1001,11 +958,8 @@ virCgroupCpuSetInherit(virCgroupPtr parent, virCgroupPtr group)
+         if (virCgroupSetValueStr(group,
+                                  VIR_CGROUP_CONTROLLER_CPUSET,
+                                  inherit_values[i],
+-                                 value) < 0) {
+-            VIR_FREE(value);
++                                 value) < 0)
+             return -1;
+-        }
+-        VIR_FREE(value);
+     }
+ 
+     return 0;
+@@ -1044,11 +998,10 @@ virCgroupMakeGroup(virCgroupPtr parent,
+                    unsigned int flags)
+ {
+     size_t i;
+-    int ret = -1;
+ 
+     VIR_DEBUG("Make group %s", group->path);
+     for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
+-        char *path = NULL;
++        VIR_AUTOFREE(char *) path = NULL;
+ 
+         /* We must never mkdir() in systemd's hierarchy */
+         if (i == VIR_CGROUP_CONTROLLER_SYSTEMD) {
+@@ -1074,10 +1027,8 @@ virCgroupMakeGroup(virCgroupPtr parent,
+         if (!virFileExists(path)) {
+             if (!create ||
+                 mkdir(path, 0755) < 0) {
+-                if (errno == EEXIST) {
+-                    VIR_FREE(path);
++                if (errno == EEXIST)
+                     continue;
+-                }
+                 /* With a kernel that doesn't support multi-level directory
+                  * for blkio controller, libvirt will fail and disable all
+                  * other controllers even though they are available. So
+@@ -1085,24 +1036,20 @@ virCgroupMakeGroup(virCgroupPtr parent,
+                 if (i == VIR_CGROUP_CONTROLLER_BLKIO) {
+                     VIR_DEBUG("Ignoring mkdir failure with blkio controller. Kernel probably too old");
+                     VIR_FREE(group->controllers[i].mountPoint);
+-                    VIR_FREE(path);
+                     continue;
+                 } else {
+                     virReportSystemError(errno,
+                                          _("Failed to create controller %s for group"),
+                                          virCgroupControllerTypeToString(i));
+-                    VIR_FREE(path);
+-                    goto cleanup;
++                    return -1;
+                 }
+             }
+             if (group->controllers[VIR_CGROUP_CONTROLLER_CPUSET].mountPoint != NULL &&
+                 (i == VIR_CGROUP_CONTROLLER_CPUSET ||
+                  STREQ(group->controllers[i].mountPoint,
+                        group->controllers[VIR_CGROUP_CONTROLLER_CPUSET].mountPoint))) {
+-                if (virCgroupCpuSetInherit(parent, group) < 0) {
+-                    VIR_FREE(path);
+-                    goto cleanup;
+-                }
++                if (virCgroupCpuSetInherit(parent, group) < 0)
++                    return -1;
+             }
+             /*
+              * Note that virCgroupSetMemoryUseHierarchy should always be
+@@ -1113,21 +1060,14 @@ virCgroupMakeGroup(virCgroupPtr parent,
+                 (i == VIR_CGROUP_CONTROLLER_MEMORY ||
+                  STREQ(group->controllers[i].mountPoint,
+                        group->controllers[VIR_CGROUP_CONTROLLER_MEMORY].mountPoint))) {
+-                if (virCgroupSetMemoryUseHierarchy(group) < 0) {
+-                    VIR_FREE(path);
+-                    goto cleanup;
+-                }
++                if (virCgroupSetMemoryUseHierarchy(group) < 0)
++                    return -1;
+             }
+         }
+-
+-        VIR_FREE(path);
+     }
+ 
+     VIR_DEBUG("Done making controllers for group");
+-    ret = 0;
+-
+- cleanup:
+-    return ret;
++    return 0;
+ }
+ 
+ 
+@@ -1339,9 +1279,9 @@ virCgroupNewPartition(const char *path,
+                       virCgroupPtr *group)
+ {
+     int ret = -1;
+-    char *parentPath = NULL;
++    VIR_AUTOFREE(char *) parentPath = NULL;
++    VIR_AUTOFREE(char *) newPath = NULL;
+     virCgroupPtr parent = NULL;
+-    char *newPath = NULL;
+     VIR_DEBUG("path=%s create=%d controllers=%x",
+               path, create, controllers);
+ 
+@@ -1381,8 +1321,6 @@ virCgroupNewPartition(const char *path,
+     if (ret != 0)
+         virCgroupFree(group);
+     virCgroupFree(&parent);
+-    VIR_FREE(parentPath);
+-    VIR_FREE(newPath);
+     return ret;
+ }
+ 
+@@ -1421,18 +1359,17 @@ virCgroupNewDomainPartition(virCgroupPtr partition,
+                             bool create,
+                             virCgroupPtr *group)
+ {
+-    int ret = -1;
+-    char *grpname = NULL;
++    VIR_AUTOFREE(char *)grpname = NULL;
+ 
+     if (virAsprintf(&grpname, "%s.libvirt-%s",
+                     name, driver) < 0)
+-        goto cleanup;
++        return -1;
+ 
+     if (virCgroupPartitionEscape(&grpname) < 0)
+-        goto cleanup;
++        return -1;
+ 
+     if (virCgroupNew(-1, grpname, partition, -1, group) < 0)
+-        goto cleanup;
++        return -1;
+ 
+     /*
+      * Create a cgroup with memory.use_hierarchy enabled to
+@@ -1448,14 +1385,10 @@ virCgroupNewDomainPartition(virCgroupPtr partition,
+                            VIR_CGROUP_MEM_HIERACHY) < 0) {
+         virCgroupRemove(*group);
+         virCgroupFree(group);
+-        goto cleanup;
++        return -1;
+     }
+ 
+-    ret = 0;
+-
+- cleanup:
+-    VIR_FREE(grpname);
+-    return ret;
++    return 0;
+ }
+ 
+ 
+@@ -1477,27 +1410,26 @@ virCgroupNewThread(virCgroupPtr domain,
+                    bool create,
+                    virCgroupPtr *group)
+ {
+-    int ret = -1;
+-    char *name = NULL;
++    VIR_AUTOFREE(char *) name = NULL;
+     int controllers;
+ 
+     switch (nameval) {
+     case VIR_CGROUP_THREAD_VCPU:
+         if (virAsprintf(&name, "vcpu%d", id) < 0)
+-            goto cleanup;
++            return -1;
+         break;
+     case VIR_CGROUP_THREAD_EMULATOR:
+         if (VIR_STRDUP(name, "emulator") < 0)
+-            goto cleanup;
++            return -1;
+         break;
+     case VIR_CGROUP_THREAD_IOTHREAD:
+         if (virAsprintf(&name, "iothread%d", id) < 0)
+-            goto cleanup;
++            return -1;
+         break;
+     case VIR_CGROUP_THREAD_LAST:
+         virReportError(VIR_ERR_INTERNAL_ERROR,
+                        _("unexpected name value %d"), nameval);
+-        goto cleanup;
++        return -1;
+     }
+ 
+     controllers = ((1 << VIR_CGROUP_CONTROLLER_CPU) |
+@@ -1505,18 +1437,15 @@ virCgroupNewThread(virCgroupPtr domain,
+                    (1 << VIR_CGROUP_CONTROLLER_CPUSET));
+ 
+     if (virCgroupNew(-1, name, domain, controllers, group) < 0)
+-        goto cleanup;
++        return -1;
+ 
+     if (virCgroupMakeGroup(domain, *group, create, VIR_CGROUP_NONE) < 0) {
+         virCgroupRemove(*group);
+         virCgroupFree(group);
+-        goto cleanup;
++        return -1;
+     }
+ 
+-    ret = 0;
+- cleanup:
+-    VIR_FREE(name);
+-    return ret;
++    return 0;
+ }
+ 
+ 
+@@ -1577,7 +1506,7 @@ virCgroupNewMachineSystemd(const char *name,
+     int ret = -1;
+     int rv;
+     virCgroupPtr init, parent = NULL;
+-    char *path = NULL;
++    VIR_AUTOFREE(char *) path = NULL;
+     char *offset;
+ 
+     VIR_DEBUG("Trying to setup machine '%s' via systemd", name);
+@@ -1662,7 +1591,6 @@ virCgroupNewMachineSystemd(const char *name,
+     ret = 0;
+  cleanup:
+     virCgroupFree(&parent);
+-    VIR_FREE(path);
+     return ret;
+ }
+ 
+@@ -1894,9 +1822,11 @@ virCgroupGetBlkioIoServiced(virCgroupPtr group,
+                             long long *requests_write)
+ {
+     long long stats_val;
+-    char *str1 = NULL, *str2 = NULL, *p1, *p2;
++    VIR_AUTOFREE(char *) str1 = NULL;
++    VIR_AUTOFREE(char *) str2 = NULL;
++    char *p1 = NULL;
++    char *p2 = NULL;
+     size_t i;
+-    int ret = -1;
+ 
+     const char *value_names[] = {
+         "Read ",
+@@ -1919,12 +1849,12 @@ virCgroupGetBlkioIoServiced(virCgroupPtr group,
+     if (virCgroupGetValueStr(group,
+                              VIR_CGROUP_CONTROLLER_BLKIO,
+                              "blkio.throttle.io_service_bytes", &str1) < 0)
+-        goto cleanup;
++        return -1;
+ 
+     if (virCgroupGetValueStr(group,
+                              VIR_CGROUP_CONTROLLER_BLKIO,
+                              "blkio.throttle.io_serviced", &str2) < 0)
+-        goto cleanup;
++        return -1;
+ 
+     /* sum up all entries of the same kind, from all devices */
+     for (i = 0; i < ARRAY_CARDINALITY(value_names); i++) {
+@@ -1938,7 +1868,7 @@ virCgroupGetBlkioIoServiced(virCgroupPtr group,
+                                _("Cannot parse byte %sstat '%s'"),
+                                value_names[i],
+                                p1);
+-                goto cleanup;
++                return -1;
+             }
+ 
+             if (stats_val < 0 ||
+@@ -1947,7 +1877,7 @@ virCgroupGetBlkioIoServiced(virCgroupPtr group,
+                 virReportError(VIR_ERR_OVERFLOW,
+                                _("Sum of byte %sstat overflows"),
+                                value_names[i]);
+-                goto cleanup;
++                return -1;
+             }
+             *bytes_ptrs[i] += stats_val;
+         }
+@@ -1959,7 +1889,7 @@ virCgroupGetBlkioIoServiced(virCgroupPtr group,
+                                _("Cannot parse %srequest stat '%s'"),
+                                value_names[i],
+                                p2);
+-                goto cleanup;
++                return -1;
+             }
+ 
+             if (stats_val < 0 ||
+@@ -1968,18 +1898,13 @@ virCgroupGetBlkioIoServiced(virCgroupPtr group,
+                 virReportError(VIR_ERR_OVERFLOW,
+                                _("Sum of %srequest stat overflows"),
+                                value_names[i]);
+-                goto cleanup;
++                return -1;
+             }
+             *requests_ptrs[i] += stats_val;
+         }
+     }
+ 
+-    ret = 0;
+-
+- cleanup:
+-    VIR_FREE(str2);
+-    VIR_FREE(str1);
+-    return ret;
++    return 0;
+ }
+ 
+ 
+@@ -2003,9 +1928,12 @@ virCgroupGetBlkioIoDeviceServiced(virCgroupPtr group,
+                                   long long *requests_read,
+                                   long long *requests_write)
+ {
+-    char *str1 = NULL, *str2 = NULL, *str3 = NULL, *p1, *p2;
++    VIR_AUTOFREE(char *) str1 = NULL;
++    VIR_AUTOFREE(char *) str2 = NULL;
++    VIR_AUTOFREE(char *) str3 = NULL;
++    char *p1 = NULL;
++    char *p2 = NULL;
+     size_t i;
+-    int ret = -1;
+ 
+     const char *value_names[] = {
+         "Read ",
+@@ -2023,28 +1951,28 @@ virCgroupGetBlkioIoDeviceServiced(virCgroupPtr group,
+     if (virCgroupGetValueStr(group,
+                              VIR_CGROUP_CONTROLLER_BLKIO,
+                              "blkio.throttle.io_service_bytes", &str1) < 0)
+-        goto cleanup;
++        return -1;
+ 
+     if (virCgroupGetValueStr(group,
+                              VIR_CGROUP_CONTROLLER_BLKIO,
+                              "blkio.throttle.io_serviced", &str2) < 0)
+-        goto cleanup;
++        return -1;
+ 
+     if (!(str3 = virCgroupGetBlockDevString(path)))
+-        goto cleanup;
++        return -1;
+ 
+     if (!(p1 = strstr(str1, str3))) {
+         virReportError(VIR_ERR_INTERNAL_ERROR,
+                        _("Cannot find byte stats for block device '%s'"),
+                        str3);
+-        goto cleanup;
++        return -1;
+     }
+ 
+     if (!(p2 = strstr(str2, str3))) {
+         virReportError(VIR_ERR_INTERNAL_ERROR,
+                        _("Cannot find request stats for block device '%s'"),
+                        str3);
+-        goto cleanup;
++        return -1;
+     }
+ 
+     for (i = 0; i < ARRAY_CARDINALITY(value_names); i++) {
+@@ -2052,38 +1980,32 @@ virCgroupGetBlkioIoDeviceServiced(virCgroupPtr group,
+             virReportError(VIR_ERR_INTERNAL_ERROR,
+                            _("Cannot find byte %sstats for block device '%s'"),
+                            value_names[i], str3);
+-            goto cleanup;
++            return -1;
+         }
+ 
+         if (virStrToLong_ll(p1 + strlen(value_names[i]), &p1, 10, bytes_ptrs[i]) < 0) {
+             virReportError(VIR_ERR_INTERNAL_ERROR,
+                            _("Cannot parse %sstat '%s'"),
+                            value_names[i], p1 + strlen(value_names[i]));
+-            goto cleanup;
++            return -1;
+         }
+ 
+         if (!(p2 = strstr(p2, value_names[i]))) {
+             virReportError(VIR_ERR_INTERNAL_ERROR,
+                            _("Cannot find request %sstats for block device '%s'"),
+                            value_names[i], str3);
+-            goto cleanup;
++            return -1;
+         }
+ 
+         if (virStrToLong_ll(p2 + strlen(value_names[i]), &p2, 10, requests_ptrs[i]) < 0) {
+             virReportError(VIR_ERR_INTERNAL_ERROR,
+                            _("Cannot parse %sstat '%s'"),
+                            value_names[i], p2 + strlen(value_names[i]));
+-            goto cleanup;
++            return -1;
+         }
+     }
+ 
+-    ret = 0;
+-
+- cleanup:
+-    VIR_FREE(str3);
+-    VIR_FREE(str2);
+-    VIR_FREE(str1);
+-    return ret;
++    return 0;
+ }
+ 
+ 
+@@ -2139,24 +2061,19 @@ virCgroupSetBlkioDeviceReadIops(virCgroupPtr group,
+                                 const char *path,
+                                 unsigned int riops)
+ {
+-    char *str = NULL;
+-    char *blkstr = NULL;
+-    int ret = -1;
++    VIR_AUTOFREE(char *) str = NULL;
++    VIR_AUTOFREE(char *) blkstr = NULL;
+ 
+     if (!(blkstr = virCgroupGetBlockDevString(path)))
+         return -1;
+ 
+     if (virAsprintf(&str, "%s%u", blkstr, riops) < 0)
+-        goto error;
++        return -1;
+ 
+-    ret = virCgroupSetValueStr(group,
++    return virCgroupSetValueStr(group,
+                                VIR_CGROUP_CONTROLLER_BLKIO,
+                                "blkio.throttle.read_iops_device",
+                                str);
+- error:
+-    VIR_FREE(blkstr);
+-    VIR_FREE(str);
+-    return ret;
+ }
+ 
+ 
+@@ -2173,24 +2090,19 @@ virCgroupSetBlkioDeviceWriteIops(virCgroupPtr group,
+                                  const char *path,
+                                  unsigned int wiops)
+ {
+-    char *str = NULL;
+-    char *blkstr = NULL;
+-    int ret = -1;
++    VIR_AUTOFREE(char *) str = NULL;
++    VIR_AUTOFREE(char *) blkstr = NULL;
+ 
+     if (!(blkstr = virCgroupGetBlockDevString(path)))
+         return -1;
+ 
+     if (virAsprintf(&str, "%s%u", blkstr, wiops) < 0)
+-        goto error;
++        return -1;
+ 
+-    ret = virCgroupSetValueStr(group,
++    return virCgroupSetValueStr(group,
+                                VIR_CGROUP_CONTROLLER_BLKIO,
+                                "blkio.throttle.write_iops_device",
+                                str);
+- error:
+-    VIR_FREE(blkstr);
+-    VIR_FREE(str);
+-    return ret;
+ }
+ 
+ 
+@@ -2207,24 +2119,19 @@ virCgroupSetBlkioDeviceReadBps(virCgroupPtr group,
+                                const char *path,
+                                unsigned long long rbps)
+ {
+-    char *str = NULL;
+-    char *blkstr = NULL;
+-    int ret = -1;
++    VIR_AUTOFREE(char *) str = NULL;
++    VIR_AUTOFREE(char *) blkstr = NULL;
+ 
+     if (!(blkstr = virCgroupGetBlockDevString(path)))
+         return -1;
+ 
+     if (virAsprintf(&str, "%s%llu", blkstr, rbps) < 0)
+-        goto error;
++        return -1;
+ 
+-    ret = virCgroupSetValueStr(group,
++    return virCgroupSetValueStr(group,
+                                VIR_CGROUP_CONTROLLER_BLKIO,
+                                "blkio.throttle.read_bps_device",
+                                str);
+- error:
+-    VIR_FREE(blkstr);
+-    VIR_FREE(str);
+-    return ret;
+ }
+ 
+ /**
+@@ -2240,24 +2147,19 @@ virCgroupSetBlkioDeviceWriteBps(virCgroupPtr group,
+                                 const char *path,
+                                 unsigned long long wbps)
+ {
+-    char *str = NULL;
+-    char *blkstr = NULL;
+-    int ret = -1;
++    VIR_AUTOFREE(char *) str = NULL;
++    VIR_AUTOFREE(char *) blkstr = NULL;
+ 
+     if (!(blkstr = virCgroupGetBlockDevString(path)))
+         return -1;
+ 
+     if (virAsprintf(&str, "%s%llu", blkstr, wbps) < 0)
+-        goto error;
++        return -1;
+ 
+-    ret = virCgroupSetValueStr(group,
++    return virCgroupSetValueStr(group,
+                                VIR_CGROUP_CONTROLLER_BLKIO,
+                                "blkio.throttle.write_bps_device",
+                                str);
+- error:
+-    VIR_FREE(blkstr);
+-    VIR_FREE(str);
+-    return ret;
+ }
+ 
+ 
+@@ -2275,24 +2177,19 @@ virCgroupSetBlkioDeviceWeight(virCgroupPtr group,
+                               const char *path,
+                               unsigned int weight)
+ {
+-    char *str = NULL;
+-    char *blkstr = NULL;
+-    int ret = -1;
++    VIR_AUTOFREE(char *) str = NULL;
++    VIR_AUTOFREE(char *) blkstr = NULL;
+ 
+     if (!(blkstr = virCgroupGetBlockDevString(path)))
+         return -1;
+ 
+     if (virAsprintf(&str, "%s%d", blkstr, weight) < 0)
+-        goto error;
++        return -1;
+ 
+-    ret = virCgroupSetValueStr(group,
++    return virCgroupSetValueStr(group,
+                                VIR_CGROUP_CONTROLLER_BLKIO,
+                                "blkio.weight_device",
+                                str);
+- error:
+-    VIR_FREE(blkstr);
+-    VIR_FREE(str);
+-    return ret;
+ }
+ 
+ /**
+@@ -2308,15 +2205,14 @@ virCgroupGetBlkioDeviceReadIops(virCgroupPtr group,
+                                 const char *path,
+                                 unsigned int *riops)
+ {
+-    char *str = NULL;
+-    int ret = -1;
++    VIR_AUTOFREE(char *) str = NULL;
+ 
+     if (virCgroupGetValueForBlkDev(group,
+                                    VIR_CGROUP_CONTROLLER_BLKIO,
+                                    "blkio.throttle.read_iops_device",
+                                    path,
+                                    &str) < 0)
+-        goto error;
++        return -1;
+ 
+     if (!str) {
+         *riops = 0;
+@@ -2324,13 +2220,10 @@ virCgroupGetBlkioDeviceReadIops(virCgroupPtr group,
+         virReportError(VIR_ERR_INTERNAL_ERROR,
+                        _("Unable to parse '%s' as an integer"),
+                        str);
+-        goto error;
++        return -1;
+     }
+ 
+-    ret = 0;
+- error:
+-    VIR_FREE(str);
+-    return ret;
++    return 0;
+ }
+ 
+ /**
+@@ -2346,15 +2239,14 @@ virCgroupGetBlkioDeviceWriteIops(virCgroupPtr group,
+                                  const char *path,
+                                  unsigned int *wiops)
+ {
+-    char *str = NULL;
+-    int ret = -1;
++    VIR_AUTOFREE(char *) str = NULL;
+ 
+     if (virCgroupGetValueForBlkDev(group,
+                                    VIR_CGROUP_CONTROLLER_BLKIO,
+                                    "blkio.throttle.write_iops_device",
+                                    path,
+                                    &str) < 0)
+-        goto error;
++        return -1;
+ 
+     if (!str) {
+         *wiops = 0;
+@@ -2362,13 +2254,10 @@ virCgroupGetBlkioDeviceWriteIops(virCgroupPtr group,
+         virReportError(VIR_ERR_INTERNAL_ERROR,
+                        _("Unable to parse '%s' as an integer"),
+                        str);
+-        goto error;
++        return -1;
+     }
+ 
+-    ret = 0;
+- error:
+-    VIR_FREE(str);
+-    return ret;
++    return 0;
+ }
+ 
+ /**
+@@ -2384,15 +2273,14 @@ virCgroupGetBlkioDeviceReadBps(virCgroupPtr group,
+                                const char *path,
+                                unsigned long long *rbps)
+ {
+-    char *str = NULL;
+-    int ret = -1;
++    VIR_AUTOFREE(char *) str = NULL;
+ 
+     if (virCgroupGetValueForBlkDev(group,
+                                    VIR_CGROUP_CONTROLLER_BLKIO,
+                                    "blkio.throttle.read_bps_device",
+                                    path,
+                                    &str) < 0)
+-        goto error;
++        return -1;
+ 
+     if (!str) {
+         *rbps = 0;
+@@ -2400,13 +2288,10 @@ virCgroupGetBlkioDeviceReadBps(virCgroupPtr group,
+         virReportError(VIR_ERR_INTERNAL_ERROR,
+                        _("Unable to parse '%s' as an integer"),
+                        str);
+-        goto error;
++        return -1;
+     }
+ 
+-    ret = 0;
+- error:
+-    VIR_FREE(str);
+-    return ret;
++    return 0;
+ }
+ 
+ /**
+@@ -2422,15 +2307,14 @@ virCgroupGetBlkioDeviceWriteBps(virCgroupPtr group,
+                                 const char *path,
+                                 unsigned long long *wbps)
+ {
+-    char *str = NULL;
+-    int ret = -1;
++    VIR_AUTOFREE(char *) str = NULL;
+ 
+     if (virCgroupGetValueForBlkDev(group,
+                                    VIR_CGROUP_CONTROLLER_BLKIO,
+                                    "blkio.throttle.write_bps_device",
+                                    path,
+                                    &str) < 0)
+-        goto error;
++        return -1;
+ 
+     if (!str) {
+         *wbps = 0;
+@@ -2438,13 +2322,10 @@ virCgroupGetBlkioDeviceWriteBps(virCgroupPtr group,
+         virReportError(VIR_ERR_INTERNAL_ERROR,
+                        _("Unable to parse '%s' as an integer"),
+                        str);
+-        goto error;
++        return -1;
+     }
+ 
+-    ret = 0;
+- error:
+-    VIR_FREE(str);
+-    return ret;
++    return 0;
+ }
+ 
+ /**
+@@ -2460,15 +2341,14 @@ virCgroupGetBlkioDeviceWeight(virCgroupPtr group,
+                               const char *path,
+                               unsigned int *weight)
+ {
+-    char *str = NULL;
+-    int ret = -1;
++    VIR_AUTOFREE(char *) str = NULL;
+ 
+     if (virCgroupGetValueForBlkDev(group,
+                                    VIR_CGROUP_CONTROLLER_BLKIO,
+                                    "blkio.weight_device",
+                                    path,
+                                    &str) < 0)
+-        goto error;
++        return -1;
+ 
+     if (!str) {
+         *weight = 0;
+@@ -2476,13 +2356,10 @@ virCgroupGetBlkioDeviceWeight(virCgroupPtr group,
+         virReportError(VIR_ERR_INTERNAL_ERROR,
+                        _("Unable to parse '%s' as an integer"),
+                        str);
+-        goto error;
++        return -1;
+     }
+ 
+-    ret = 0;
+- error:
+-    VIR_FREE(str);
+-    return ret;
++    return 0;
+ }
+ 
+ 
+@@ -2941,36 +2818,29 @@ int
+ virCgroupAllowDevice(virCgroupPtr group, char type, int major, int minor,
+                      int perms)
+ {
+-    int ret = -1;
+-    char *devstr = NULL;
+-    char *majorstr = NULL;
+-    char *minorstr = NULL;
++    VIR_AUTOFREE(char *) devstr = NULL;
++    VIR_AUTOFREE(char *) majorstr = NULL;
++    VIR_AUTOFREE(char *) minorstr = NULL;
+ 
+     if ((major < 0 && VIR_STRDUP(majorstr, "*") < 0) ||
+         (major >= 0 && virAsprintf(&majorstr, "%i", major) < 0))
+-        goto cleanup;
++        return -1;
+ 
+     if ((minor < 0 && VIR_STRDUP(minorstr, "*") < 0) ||
+         (minor >= 0 && virAsprintf(&minorstr, "%i", minor) < 0))
+-        goto cleanup;
++        return -1;
+ 
+     if (virAsprintf(&devstr, "%c %s:%s %s", type, majorstr, minorstr,
+                     virCgroupGetDevicePermsString(perms)) < 0)
+-        goto cleanup;
++        return -1;
+ 
+     if (virCgroupSetValueStr(group,
+                              VIR_CGROUP_CONTROLLER_DEVICES,
+                              "devices.allow",
+                              devstr) < 0)
+-        goto cleanup;
++        return -1;
+ 
+-    ret = 0;
+-
+- cleanup:
+-    VIR_FREE(devstr);
+-    VIR_FREE(majorstr);
+-    VIR_FREE(minorstr);
+-    return ret;
++    return 0;
+ }
+ 
+ 
+@@ -3032,36 +2902,29 @@ int
+ virCgroupDenyDevice(virCgroupPtr group, char type, int major, int minor,
+                     int perms)
+ {
+-    int ret = -1;
+-    char *devstr = NULL;
+-    char *majorstr = NULL;
+-    char *minorstr = NULL;
++    VIR_AUTOFREE(char *) devstr = NULL;
++    VIR_AUTOFREE(char *) majorstr = NULL;
++    VIR_AUTOFREE(char *) minorstr = NULL;
+ 
+     if ((major < 0 && VIR_STRDUP(majorstr, "*") < 0) ||
+         (major >= 0 && virAsprintf(&majorstr, "%i", major) < 0))
+-        goto cleanup;
++        return -1;
+ 
+     if ((minor < 0 && VIR_STRDUP(minorstr, "*") < 0) ||
+         (minor >= 0 && virAsprintf(&minorstr, "%i", minor) < 0))
+-        goto cleanup;
++        return -1;
+ 
+     if (virAsprintf(&devstr, "%c %s:%s %s", type, majorstr, minorstr,
+                     virCgroupGetDevicePermsString(perms)) < 0)
+-        goto cleanup;
++        return -1;
+ 
+     if (virCgroupSetValueStr(group,
+                              VIR_CGROUP_CONTROLLER_DEVICES,
+                              "devices.deny",
+                              devstr) < 0)
+-        goto cleanup;
++        return -1;
+ 
+-    ret = 0;
+-
+- cleanup:
+-    VIR_FREE(devstr);
+-    VIR_FREE(majorstr);
+-    VIR_FREE(minorstr);
+-    return ret;
++    return 0;
+ }
+ 
+ 
+@@ -3131,10 +2994,10 @@ virCgroupGetPercpuVcpuSum(virCgroupPtr group,
+ {
+     int ret = -1;
+     ssize_t i = -1;
+-    char *buf = NULL;
+     virCgroupPtr group_vcpu = NULL;
+ 
+     while ((i = virBitmapNextSetBit(guestvcpus, i)) >= 0) {
++        VIR_AUTOFREE(char *) buf = NULL;
+         char *pos;
+         unsigned long long tmp;
+         ssize_t j;
+@@ -3159,13 +3022,11 @@ virCgroupGetPercpuVcpuSum(virCgroupPtr group,
+         }
+ 
+         virCgroupFree(&group_vcpu);
+-        VIR_FREE(buf);
+     }
+ 
+     ret = 0;
+  cleanup:
+     virCgroupFree(&group_vcpu);
+-    VIR_FREE(buf);
+     return ret;
+ }
+ 
+@@ -3202,8 +3063,8 @@ virCgroupGetPercpuStats(virCgroupPtr group,
+     size_t i;
+     int need_cpus, total_cpus;
+     char *pos;
+-    char *buf = NULL;
+-    unsigned long long *sum_cpu_time = NULL;
++    VIR_AUTOFREE(char *) buf = NULL;
++    VIR_AUTOFREE(unsigned long long *) sum_cpu_time = NULL;
+     virTypedParameterPtr ent;
+     int param_idx;
+     unsigned long long cpu_time;
+@@ -3289,8 +3150,6 @@ virCgroupGetPercpuStats(virCgroupPtr group,
+ 
+  cleanup:
+     virBitmapFree(cpumap);
+-    VIR_FREE(sum_cpu_time);
+-    VIR_FREE(buf);
+     return ret;
+ }
+ 
+@@ -3461,7 +3320,7 @@ virCgroupRemoveRecursively(char *grppath)
+     /* This is best-effort cleanup: we want to log failures with just
+      * VIR_ERROR instead of normal virReportError */
+     while ((direrr = virDirRead(grpdir, &ent, NULL)) > 0) {
+-        char *path;
++        VIR_AUTOFREE(char *) path = NULL;
+ 
+         if (ent->d_type != DT_DIR) continue;
+ 
+@@ -3470,7 +3329,6 @@ virCgroupRemoveRecursively(char *grppath)
+             break;
+         }
+         rc = virCgroupRemoveRecursively(path);
+-        VIR_FREE(path);
+         if (rc != 0)
+             break;
+     }
+@@ -3508,10 +3366,11 @@ virCgroupRemove(virCgroupPtr group)
+ {
+     int rc = 0;
+     size_t i;
+-    char *grppath = NULL;
+ 
+     VIR_DEBUG("Removing cgroup %s", group->path);
+     for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
++        VIR_AUTOFREE(char *) grppath = NULL;
++
+         /* Skip over controllers not mounted */
+         if (!group->controllers[i].mountPoint)
+             continue;
+@@ -3533,7 +3392,6 @@ virCgroupRemove(virCgroupPtr group)
+ 
+         VIR_DEBUG("Removing cgroup %s and all child cgroups", grppath);
+         rc = virCgroupRemoveRecursively(grppath);
+-        VIR_FREE(grppath);
+     }
+     VIR_DEBUG("Done removing cgroup %s", group->path);
+ 
+@@ -3549,7 +3407,7 @@ virCgroupKillInternal(virCgroupPtr group, int signum, virHashTablePtr pids)
+ {
+     int ret = -1;
+     bool killedAny = false;
+-    char *keypath = NULL;
++    VIR_AUTOFREE(char *) keypath = NULL;
+     bool done = false;
+     FILE *fp = NULL;
+     VIR_DEBUG("group=%p path=%s signum=%d pids=%p",
+@@ -3613,7 +3471,6 @@ virCgroupKillInternal(virCgroupPtr group, int signum, virHashTablePtr pids)
+     ret = killedAny ? 1 : 0;
+ 
+  cleanup:
+-    VIR_FREE(keypath);
+     VIR_FORCE_FCLOSE(fp);
+ 
+     return ret;
+@@ -3678,7 +3535,7 @@ virCgroupKillRecursiveInternal(virCgroupPtr group,
+     int ret = -1;
+     int rc;
+     bool killedAny = false;
+-    char *keypath = NULL;
++    VIR_AUTOFREE(char *) keypath = NULL;
+     DIR *dp = NULL;
+     virCgroupPtr subgroup = NULL;
+     struct dirent *ent;
+@@ -3732,7 +3589,6 @@ virCgroupKillRecursiveInternal(virCgroupPtr group,
+ 
+  cleanup:
+     virCgroupFree(&subgroup);
+-    VIR_FREE(keypath);
+     VIR_DIR_CLOSE(dp);
+     return ret;
+ }
+@@ -3846,9 +3702,8 @@ int
+ virCgroupGetCpuacctStat(virCgroupPtr group, unsigned long long *user,
+                         unsigned long long *sys)
+ {
+-    char *str;
++    VIR_AUTOFREE(char *) str = NULL;
+     char *p;
+-    int ret = -1;
+     static double scale = -1.0;
+ 
+     if (virCgroupGetValueStr(group, VIR_CGROUP_CONTROLLER_CPUACCT,
+@@ -3860,14 +3715,14 @@ virCgroupGetCpuacctStat(virCgroupPtr group, unsigned long long *user,
+         virReportError(VIR_ERR_INTERNAL_ERROR,
+                        _("Cannot parse user stat '%s'"),
+                        p);
+-        goto cleanup;
++        return -1;
+     }
+     if (!(p = STRSKIP(p, "\nsystem ")) ||
+         virStrToLong_ull(p, NULL, 10, sys) < 0) {
+         virReportError(VIR_ERR_INTERNAL_ERROR,
+                        _("Cannot parse sys stat '%s'"),
+                        p);
+-        goto cleanup;
++        return -1;
+     }
+     /* times reported are in system ticks (generally 100 Hz), but that
+      * rate can theoretically vary between machines.  Scale things
+@@ -3877,17 +3732,14 @@ virCgroupGetCpuacctStat(virCgroupPtr group, unsigned long long *user,
+         if (ticks_per_sec == -1) {
+             virReportSystemError(errno, "%s",
+                                  _("Cannot determine system clock HZ"));
+-            goto cleanup;
++            return -1;
+         }
+         scale = 1000000000.0 / ticks_per_sec;
+     }
+     *user *= scale;
+     *sys *= scale;
+ 
+-    ret = 0;
+- cleanup:
+-    VIR_FREE(str);
+-    return ret;
++    return 0;
+ }
+ 
+ 
+@@ -3913,10 +3765,9 @@ int
+ virCgroupBindMount(virCgroupPtr group, const char *oldroot,
+                    const char *mountopts)
+ {
+-    int ret = -1;
+     size_t i;
+-    char *opts = NULL;
+-    char *root = NULL;
++    VIR_AUTOFREE(char *) opts = NULL;
++    VIR_AUTOFREE(char *) root = NULL;
+ 
+     if (!(root = virCgroupIdentifyRoot(group)))
+         return -1;
+@@ -3927,18 +3778,18 @@ virCgroupBindMount(virCgroupPtr group, const char *oldroot,
+         virReportSystemError(errno,
+                              _("Unable to create directory %s"),
+                              root);
+-        goto cleanup;
++        return -1;
+     }
+ 
+     if (virAsprintf(&opts,
+                     "mode=755,size=65536%s", mountopts) < 0)
+-        goto cleanup;
++        return -1;
+ 
+     if (mount("tmpfs", root, "tmpfs", MS_NOSUID|MS_NODEV|MS_NOEXEC, opts) < 0) {
+         virReportSystemError(errno,
+                              _("Failed to mount %s on %s type %s"),
+                              "tmpfs", root, "tmpfs");
+-        goto cleanup;
++        return -1;
+     }
+ 
+     for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
+@@ -3946,11 +3797,11 @@ virCgroupBindMount(virCgroupPtr group, const char *oldroot,
+             continue;
+ 
+         if (!virFileExists(group->controllers[i].mountPoint)) {
+-            char *src;
++            VIR_AUTOFREE(char *) src = NULL;
+             if (virAsprintf(&src, "%s%s",
+                             oldroot,
+                             group->controllers[i].mountPoint) < 0)
+-                goto cleanup;
++                return -1;
+ 
+             VIR_DEBUG("Create mount point '%s'",
+                       group->controllers[i].mountPoint);
+@@ -3958,8 +3809,7 @@ virCgroupBindMount(virCgroupPtr group, const char *oldroot,
+                 virReportSystemError(errno,
+                                      _("Unable to create directory %s"),
+                                      group->controllers[i].mountPoint);
+-                VIR_FREE(src);
+-                goto cleanup;
++                return -1;
+             }
+ 
+             if (mount(src, group->controllers[i].mountPoint, "none", MS_BIND,
+@@ -3967,11 +3817,8 @@ virCgroupBindMount(virCgroupPtr group, const char *oldroot,
+                 virReportSystemError(errno,
+                                      _("Failed to bind cgroup '%s' on '%s'"),
+                                      src, group->controllers[i].mountPoint);
+-                VIR_FREE(src);
+-                goto cleanup;
++                return -1;
+             }
+-
+-            VIR_FREE(src);
+         }
+ 
+         if (group->controllers[i].linkPoint) {
+@@ -3984,16 +3831,12 @@ virCgroupBindMount(virCgroupPtr group, const char *oldroot,
+                                      _("Unable to symlink directory %s to %s"),
+                                      group->controllers[i].mountPoint,
+                                      group->controllers[i].linkPoint);
+-                goto cleanup;
++                return -1;
+             }
+         }
+     }
+-    ret = 0;
+ 
+- cleanup:
+-    VIR_FREE(root);
+-    VIR_FREE(opts);
+-    return ret;
++    return 0;
+ }
+ 
+ 
+@@ -4004,11 +3847,11 @@ int virCgroupSetOwner(virCgroupPtr cgroup,
+ {
+     int ret = -1;
+     size_t i;
+-    char *base = NULL, *entry = NULL;
+     DIR *dh = NULL;
+     int direrr;
+ 
+     for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
++        VIR_AUTOFREE(char *) base = NULL;
+         struct dirent *de;
+ 
+         if (!((1 << i) & controllers))
+@@ -4025,6 +3868,8 @@ int virCgroupSetOwner(virCgroupPtr cgroup,
+             goto cleanup;
+ 
+         while ((direrr = virDirRead(dh, &de, base)) > 0) {
++            VIR_AUTOFREE(char *) entry = NULL;
++
+             if (virAsprintf(&entry, "%s/%s", base, de->d_name) < 0)
+                 goto cleanup;
+ 
+@@ -4034,8 +3879,6 @@ int virCgroupSetOwner(virCgroupPtr cgroup,
+                                      entry, uid, gid);
+                 goto cleanup;
+             }
+-
+-            VIR_FREE(entry);
+         }
+         if (direrr < 0)
+             goto cleanup;
+@@ -4047,7 +3890,6 @@ int virCgroupSetOwner(virCgroupPtr cgroup,
+             goto cleanup;
+         }
+ 
+-        VIR_FREE(base);
+         VIR_DIR_CLOSE(dh);
+     }
+ 
+@@ -4055,8 +3897,6 @@ int virCgroupSetOwner(virCgroupPtr cgroup,
+ 
+  cleanup:
+     VIR_DIR_CLOSE(dh);
+-    VIR_FREE(entry);
+-    VIR_FREE(base);
+     return ret;
+ }
+ 
+@@ -4071,8 +3911,7 @@ int virCgroupSetOwner(virCgroupPtr cgroup,
+ bool
+ virCgroupSupportsCpuBW(virCgroupPtr cgroup)
+ {
+-    char *path = NULL;
+-    bool ret = false;
++    VIR_AUTOFREE(char *) path = NULL;
+ 
+     if (!cgroup)
+         return false;
+@@ -4080,21 +3919,17 @@ virCgroupSupportsCpuBW(virCgroupPtr cgroup)
+     if (virCgroupPathOfController(cgroup, VIR_CGROUP_CONTROLLER_CPU,
+                                   "cpu.cfs_period_us", &path) < 0) {
+         virResetLastError();
+-        goto cleanup;
++        return false;
+     }
+ 
+-    ret = virFileExists(path);
+-
+- cleanup:
+-    VIR_FREE(path);
+-    return ret;
++    return virFileExists(path);
+ }
+ 
+ int
+ virCgroupHasEmptyTasks(virCgroupPtr cgroup, int controller)
+ {
+     int ret = -1;
+-    char *content = NULL;
++    VIR_AUTOFREE(char *) content = NULL;
+ 
+     if (!cgroup)
+         return -1;
+@@ -4104,7 +3939,6 @@ virCgroupHasEmptyTasks(virCgroupPtr cgroup, int controller)
+     if (ret == 0 && content[0] == '\0')
+         ret = 1;
+ 
+-    VIR_FREE(content);
+     return ret;
+ }
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-util-command-Ignore-bitmap-errors-when-enumerating-file-descriptors-to-close.patch b/SOURCES/libvirt-util-command-Ignore-bitmap-errors-when-enumerating-file-descriptors-to-close.patch
new file mode 100644
index 0000000..05e45db
--- /dev/null
+++ b/SOURCES/libvirt-util-command-Ignore-bitmap-errors-when-enumerating-file-descriptors-to-close.patch
@@ -0,0 +1,62 @@
+From 2544ab6ac5b788d2df319afaef8d495409aa7b32 Mon Sep 17 00:00:00 2001
+Message-Id: <2544ab6ac5b788d2df319afaef8d495409aa7b32@dist-git>
+From: Peter Krempa <pkrempa@redhat.com>
+Date: Tue, 30 Jul 2019 16:04:51 +0200
+Subject: [PATCH] util: command: Ignore bitmap errors when enumerating file
+ descriptors to close
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+virCommandMassCloseGetFDsLinux fails when running libvird on valgrind
+with the following message:
+
+libvirt:  error : internal error: unable to set FD as open: 1024
+
+This is because valgrind opens few file descriptors beyond the limit:
+
+65701125 lr-x------. 1 root root 64 Jul 18 14:48 1024 -> /home/pipo/build/libvirt/gcc/src/.libs/libvirtd
+65701126 lrwx------. 1 root root 64 Jul 18 14:48 1025 -> '/tmp/valgrind_proc_3849_cmdline_186612e3 (deleted)'
+65701127 lrwx------. 1 root root 64 Jul 18 14:48 1026 -> '/tmp/valgrind_proc_3849_auxv_186612e3 (deleted)'
+65701128 lrwx------. 1 root root 64 Jul 18 14:48 1027 -> /dev/pts/11
+65701129 lr-x------. 1 root root 64 Jul 18 14:48 1028 -> 'pipe:[65689522]'
+65701130 l-wx------. 1 root root 64 Jul 18 14:48 1029 -> 'pipe:[65689522]'
+65701131 lr-x------. 1 root root 64 Jul 18 14:48 1030 -> /tmp/vgdb-pipe-from-vgdb-to-3849-by-root-on-angien
+
+Ignore bitmap errors in this case since we'd leak those FD's anyways in
+the previous scenario.
+
+Signed-off-by: Peter Krempa <pkrempa@redhat.com>
+Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
+(cherry picked from commit 728343983787cbd4d7ae8fa2007a157bb140f02a)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1721434
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Message-Id: <b10f29e40efb516e15a053c2e3aa8963c3ea9715.1564495366.git.mprivozn@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircommand.c | 7 +------
+ 1 file changed, 1 insertion(+), 6 deletions(-)
+
+diff --git a/src/util/vircommand.c b/src/util/vircommand.c
+index 2353a4a554..dfc7e5428b 100644
+--- a/src/util/vircommand.c
++++ b/src/util/vircommand.c
+@@ -519,12 +519,7 @@ virCommandMassCloseGetFDsLinux(virCommandPtr cmd ATTRIBUTE_UNUSED,
+             goto cleanup;
+         }
+ 
+-        if (virBitmapSetBit(fds, fd) < 0) {
+-            virReportError(VIR_ERR_INTERNAL_ERROR,
+-                           _("unable to set FD as open: %d"),
+-                           fd);
+-            goto cleanup;
+-        }
++        ignore_value(virBitmapSetBit(fds, fd));
+     }
+ 
+     if (rc < 0)
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-util-command-define-cleanup-function-using-VIR_DEFINE_AUTOPTR_FUNC.patch b/SOURCES/libvirt-util-command-define-cleanup-function-using-VIR_DEFINE_AUTOPTR_FUNC.patch
new file mode 100644
index 0000000..ff97244
--- /dev/null
+++ b/SOURCES/libvirt-util-command-define-cleanup-function-using-VIR_DEFINE_AUTOPTR_FUNC.patch
@@ -0,0 +1,69 @@
+From 47babc4b1ad1c615df10385bbaafdd30d9359b7a Mon Sep 17 00:00:00 2001
+Message-Id: <47babc4b1ad1c615df10385bbaafdd30d9359b7a@dist-git>
+From: Sukrit Bhatnagar <skrtbhtngr@gmail.com>
+Date: Tue, 30 Jul 2019 15:30:46 +0200
+Subject: [PATCH] util: command: define cleanup function using
+ VIR_DEFINE_AUTOPTR_FUNC
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Using the new VIR_DEFINE_AUTOPTR_FUNC macro defined in
+src/util/viralloc.h, define a new wrapper around an existing
+cleanup function which will be called when a variable declared
+with VIR_AUTOPTR macro goes out of scope. Also, drop the redundant
+viralloc.h include, since that has moved from the source module into the
+header.
+
+When a variable of type virCommandPtr is declared using VIR_AUTOPTR,
+the function virCommandFree will be run automatically on it when it
+goes out of scope.
+
+Signed-off-by: Sukrit Bhatnagar <skrtbhtngr@gmail.com>
+Reviewed-by: Erik Skultety <eskultet@redhat.com>
+(cherry picked from commit 7e343758920cc954d448b6b14df5707bcd0dbd20)
+
+Prerequisite of: https://bugzilla.redhat.com/show_bug.cgi?id=1721434
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Message-Id: <40a1fc21abc06c057574a4616eef9981dbfb25dd.1564493409.git.mprivozn@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircommand.c | 1 -
+ src/util/vircommand.h | 2 ++
+ 2 files changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/src/util/vircommand.c b/src/util/vircommand.c
+index c2b8a1a3c3..d328431373 100644
+--- a/src/util/vircommand.c
++++ b/src/util/vircommand.c
+@@ -44,7 +44,6 @@
+ 
+ #define __VIR_COMMAND_PRIV_H_ALLOW__
+ #include "vircommandpriv.h"
+-#include "viralloc.h"
+ #include "virerror.h"
+ #include "virutil.h"
+ #include "virlog.h"
+diff --git a/src/util/vircommand.h b/src/util/vircommand.h
+index 883e212959..90bcc6c89d 100644
+--- a/src/util/vircommand.h
++++ b/src/util/vircommand.h
+@@ -24,6 +24,7 @@
+ 
+ # include "internal.h"
+ # include "virbuffer.h"
++# include "viralloc.h"
+ 
+ typedef struct _virCommand virCommand;
+ typedef virCommand *virCommandPtr;
+@@ -218,5 +219,6 @@ int virCommandRunNul(virCommandPtr cmd,
+                      virCommandRunNulFunc func,
+                      void *data);
+ 
++VIR_DEFINE_AUTOPTR_FUNC(virCommand, virCommandFree)
+ 
+ #endif /* __VIR_COMMAND_H__ */
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-util-command-use-VIR_AUTOFREE-instead-of-VIR_FREE-for-scalar-types.patch b/SOURCES/libvirt-util-command-use-VIR_AUTOFREE-instead-of-VIR_FREE-for-scalar-types.patch
new file mode 100644
index 0000000..4e000f4
--- /dev/null
+++ b/SOURCES/libvirt-util-command-use-VIR_AUTOFREE-instead-of-VIR_FREE-for-scalar-types.patch
@@ -0,0 +1,194 @@
+From 63fe889c0e3d5c9cf44ab030fb63baee3646cb9f Mon Sep 17 00:00:00 2001
+Message-Id: <63fe889c0e3d5c9cf44ab030fb63baee3646cb9f@dist-git>
+From: Sukrit Bhatnagar <skrtbhtngr@gmail.com>
+Date: Tue, 30 Jul 2019 15:30:45 +0200
+Subject: [PATCH] util: command: use VIR_AUTOFREE instead of VIR_FREE for
+ scalar types
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+By making use of GNU C's cleanup attribute handled by the
+VIR_AUTOFREE macro for declaring scalar variables, majority
+of the VIR_FREE calls can be dropped, which in turn leads to
+getting rid of most of our cleanup sections.
+
+Signed-off-by: Sukrit Bhatnagar <skrtbhtngr@gmail.com>
+Reviewed-by: Erik Skultety <eskultet@redhat.com>
+(cherry picked from commit 46a1f0bb648dec58d6ce4b0eccbb59be435d9073)
+
+Prerequisite of: https://bugzilla.redhat.com/show_bug.cgi?id=1721434
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Message-Id: <f79e228ffb4335b228575e3b35adeb30848497bb.1564493409.git.mprivozn@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircommand.c | 40 ++++++++++++----------------------------
+ 1 file changed, 12 insertions(+), 28 deletions(-)
+
+diff --git a/src/util/vircommand.c b/src/util/vircommand.c
+index 6dab105f56..c2b8a1a3c3 100644
+--- a/src/util/vircommand.c
++++ b/src/util/vircommand.c
+@@ -508,11 +508,11 @@ virExec(virCommandPtr cmd)
+     int childout = -1;
+     int childerr = -1;
+     int tmpfd;
+-    char *binarystr = NULL;
++    VIR_AUTOFREE(char *) binarystr = NULL;
+     const char *binary = NULL;
+     int ret;
+     struct sigaction waxon, waxoff;
+-    gid_t *groups = NULL;
++    VIR_AUTOFREE(gid_t *) groups = NULL;
+     int ngroups;
+ 
+     if (cmd->args[0][0] != '/') {
+@@ -605,9 +605,6 @@ virExec(virCommandPtr cmd)
+ 
+         cmd->pid = pid;
+ 
+-        VIR_FREE(groups);
+-        VIR_FREE(binarystr);
+-
+         return 0;
+     }
+ 
+@@ -797,9 +794,6 @@ virExec(virCommandPtr cmd)
+     /* This is cleanup of parent process only - child
+        should never jump here on error */
+ 
+-    VIR_FREE(binarystr);
+-    VIR_FREE(groups);
+-
+     /* NB we don't virReportError() on any failures here
+        because the code which jumped here already raised
+        an error condition which we must not overwrite */
+@@ -2387,7 +2381,7 @@ int
+ virCommandRunAsync(virCommandPtr cmd, pid_t *pid)
+ {
+     int ret = -1;
+-    char *str = NULL;
++    VIR_AUTOFREE(char *) str = NULL;
+     size_t i;
+     bool synchronous = false;
+     int infd[2] = {-1, -1};
+@@ -2512,7 +2506,6 @@ virCommandRunAsync(virCommandPtr cmd, pid_t *pid)
+         VIR_FORCE_CLOSE(cmd->infd);
+         VIR_FORCE_CLOSE(cmd->inpipe);
+     }
+-    VIR_FREE(str);
+     return ret;
+ }
+ 
+@@ -2589,8 +2582,8 @@ virCommandWait(virCommandPtr cmd, int *exitstatus)
+         if (exitstatus && (cmd->rawStatus || WIFEXITED(status))) {
+             *exitstatus = cmd->rawStatus ? status : WEXITSTATUS(status);
+         } else if (status) {
+-            char *str = virCommandToString(cmd);
+-            char *st = virProcessTranslateStatus(status);
++            VIR_AUTOFREE(char *) str = virCommandToString(cmd);
++            VIR_AUTOFREE(char *) st = virProcessTranslateStatus(status);
+             bool haveErrMsg = cmd->errbuf && *cmd->errbuf && (*cmd->errbuf)[0];
+ 
+             virReportError(VIR_ERR_INTERNAL_ERROR,
+@@ -2598,8 +2591,6 @@ virCommandWait(virCommandPtr cmd, int *exitstatus)
+                            str ? str : cmd->args[0], NULLSTR(st),
+                            haveErrMsg ? ": " : "",
+                            haveErrMsg ? *cmd->errbuf : "");
+-            VIR_FREE(str);
+-            VIR_FREE(st);
+             return -1;
+         }
+     }
+@@ -2719,7 +2710,7 @@ int virCommandHandshakeWait(virCommandPtr cmd)
+         return -1;
+     }
+     if (c != '1') {
+-        char *msg;
++        VIR_AUTOFREE(char *) msg = NULL;
+         ssize_t len;
+         if (VIR_ALLOC_N(msg, 1024) < 0) {
+             VIR_FORCE_CLOSE(cmd->handshakeWait[0]);
+@@ -2732,7 +2723,6 @@ int virCommandHandshakeWait(virCommandPtr cmd)
+ 
+         if ((len = saferead(cmd->handshakeWait[0], msg, 1024)) < 0) {
+             VIR_FORCE_CLOSE(cmd->handshakeWait[0]);
+-            VIR_FREE(msg);
+             virReportSystemError(errno, "%s",
+                                  _("No error message from child failure"));
+             return -1;
+@@ -2740,7 +2730,6 @@ int virCommandHandshakeWait(virCommandPtr cmd)
+         VIR_FORCE_CLOSE(cmd->handshakeWait[0]);
+         msg[len-1] = '\0';
+         virReportError(VIR_ERR_INTERNAL_ERROR, "%s", msg);
+-        VIR_FREE(msg);
+         return -1;
+     }
+     VIR_FORCE_CLOSE(cmd->handshakeWait[0]);
+@@ -2854,8 +2843,8 @@ virCommandFree(virCommandPtr cmd)
+  * This requests asynchronous string IO on @cmd. It is useful in
+  * combination with virCommandRunAsync():
+  *
+- *      virCommandPtr cmd = virCommandNew*(...);
+- *      char *buf = NULL;
++ *      VIR_AUTOPTR(virCommand) cmd = virCommandNew*(...);
++ *      VIR_AUTOFREE(char *) buf = NULL;
+  *
+  *      ...
+  *
+@@ -2863,21 +2852,18 @@ virCommandFree(virCommandPtr cmd)
+  *      virCommandDoAsyncIO(cmd);
+  *
+  *      if (virCommandRunAsync(cmd, NULL) < 0)
+- *          goto cleanup;
++ *          return;
+  *
+  *      ...
+  *
+  *      if (virCommandWait(cmd, NULL) < 0)
+- *          goto cleanup;
++ *          return;
+  *
+  *      // @buf now contains @cmd's stdout
+  *      VIR_DEBUG("STDOUT: %s", NULLSTR(buf));
+  *
+  *      ...
+  *
+- *  cleanup:
+- *      VIR_FREE(buf);
+- *      virCommandFree(cmd);
+  *
+  * The libvirt's event loop is used for handling stdios of @cmd.
+  * Since current implementation uses strlen to determine length
+@@ -2970,11 +2956,11 @@ virCommandRunRegex(virCommandPtr cmd,
+ {
+     int err;
+     regex_t *reg;
+-    regmatch_t *vars = NULL;
++    VIR_AUTOFREE(regmatch_t *) vars = NULL;
+     size_t i, j, k;
+     int totgroups = 0, ngroup = 0, maxvars = 0;
+     char **groups;
+-    char *outbuf = NULL;
++    VIR_AUTOFREE(char *) outbuf = NULL;
+     char **lines = NULL;
+     int ret = -1;
+ 
+@@ -3055,13 +3041,11 @@ virCommandRunRegex(virCommandPtr cmd,
+     ret = 0;
+  cleanup:
+     virStringListFree(lines);
+-    VIR_FREE(outbuf);
+     if (groups) {
+         for (j = 0; j < totgroups; j++)
+             VIR_FREE(groups[j]);
+         VIR_FREE(groups);
+     }
+-    VIR_FREE(vars);
+ 
+     for (i = 0; i < nregex; i++)
+         regfree(&reg[i]);
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-util-enable-cgroups-v2-cpuset-controller-for-threads.patch b/SOURCES/libvirt-util-enable-cgroups-v2-cpuset-controller-for-threads.patch
new file mode 100644
index 0000000..4da907c
--- /dev/null
+++ b/SOURCES/libvirt-util-enable-cgroups-v2-cpuset-controller-for-threads.patch
@@ -0,0 +1,44 @@
+From 77eb53c13d2d9a641143cc374f8262c2cb004120 Mon Sep 17 00:00:00 2001
+Message-Id: <77eb53c13d2d9a641143cc374f8262c2cb004120@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:08:14 +0200
+Subject: [PATCH] util: enable cgroups v2 cpuset controller for threads
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+When we create cgroup for qemu threads we need to enable cpuset
+controller in order to use it.
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit a6aedcf39bd3212a3cd624b765bb724fd36d6a8a)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <1dfb136ea7a417fdcc03b84c59bb364a75e24d52.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroupv2.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/src/util/vircgroupv2.c b/src/util/vircgroupv2.c
+index ef1f286726..04638c4e50 100644
+--- a/src/util/vircgroupv2.c
++++ b/src/util/vircgroupv2.c
+@@ -401,6 +401,12 @@ virCgroupV2MakeGroup(virCgroupPtr parent ATTRIBUTE_UNUSED,
+                                             VIR_CGROUP_CONTROLLER_CPU) < 0) {
+                 return -1;
+             }
++
++            if (virCgroupV2HasController(parent, VIR_CGROUP_CONTROLLER_CPUSET) &&
++                virCgroupV2EnableController(parent,
++                                            VIR_CGROUP_CONTROLLER_CPUSET) < 0) {
++                return -1;
++            }
+         } else {
+             size_t i;
+             for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-util-file-introduce-VIR_AUTOCLOSE-macro-to-close-fd-of-the-file-automatically.patch b/SOURCES/libvirt-util-file-introduce-VIR_AUTOCLOSE-macro-to-close-fd-of-the-file-automatically.patch
new file mode 100644
index 0000000..10b3612
--- /dev/null
+++ b/SOURCES/libvirt-util-file-introduce-VIR_AUTOCLOSE-macro-to-close-fd-of-the-file-automatically.patch
@@ -0,0 +1,68 @@
+From 3d08d15b8fb214233e6b426bffe8f8b89969529a Mon Sep 17 00:00:00 2001
+Message-Id: <3d08d15b8fb214233e6b426bffe8f8b89969529a@dist-git>
+From: Shi Lei <shi_lei@massclouds.com>
+Date: Fri, 21 Jun 2019 09:25:42 +0200
+Subject: [PATCH] util: file: introduce VIR_AUTOCLOSE macro to close fd of the
+ file automatically
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Shi Lei <shi_lei@massclouds.com>
+(cherry picked from commit 09d35afd2c3058688290d5d818343d0f6aa2dd6e)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1697627
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <93cb7516e852b96a82eac8dd71acdccc81ef13f9.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/virfile.h | 18 ++++++++++++++++--
+ 1 file changed, 16 insertions(+), 2 deletions(-)
+
+diff --git a/src/util/virfile.h b/src/util/virfile.h
+index 51c221e069..fa03269289 100644
+--- a/src/util/virfile.h
++++ b/src/util/virfile.h
+@@ -53,6 +53,11 @@ int virFileClose(int *fdptr, virFileCloseFlags flags)
+ int virFileFclose(FILE **file, bool preserve_errno) ATTRIBUTE_RETURN_CHECK;
+ FILE *virFileFdopen(int *fdptr, const char *mode) ATTRIBUTE_RETURN_CHECK;
+ 
++static inline void virForceCloseHelper(int *fd)
++{
++    ignore_value(virFileClose(fd, VIR_FILE_CLOSE_PRESERVE_ERRNO));
++}
++
+ /* For use on normal paths; caller must check return value,
+    and failure sets errno per close. */
+ # define VIR_CLOSE(FD) virFileClose(&(FD), 0)
+@@ -63,8 +68,7 @@ FILE *virFileFdopen(int *fdptr, const char *mode) ATTRIBUTE_RETURN_CHECK;
+ 
+ /* For use on cleanup paths; errno is unaffected by close,
+    and no return value to worry about. */
+-# define VIR_FORCE_CLOSE(FD) \
+-    ignore_value(virFileClose(&(FD), VIR_FILE_CLOSE_PRESERVE_ERRNO))
++# define VIR_FORCE_CLOSE(FD) virForceCloseHelper(&(FD))
+ # define VIR_FORCE_FCLOSE(FILE) ignore_value(virFileFclose(&(FILE), true))
+ 
+ /* Similar VIR_FORCE_CLOSE() but ignores EBADF errors since they are expected
+@@ -79,6 +83,16 @@ FILE *virFileFdopen(int *fdptr, const char *mode) ATTRIBUTE_RETURN_CHECK;
+                  VIR_FILE_CLOSE_PRESERVE_ERRNO | \
+                  VIR_FILE_CLOSE_DONT_LOG))
+ 
++/**
++ * VIR_AUTOCLOSE:
++ *
++ * Macro to automatically force close the fd by calling virForceCloseHelper
++ * when the fd goes out of scope. It's used to eliminate VIR_FORCE_CLOSE
++ * in cleanup sections.
++ */
++# define VIR_AUTOCLOSE __attribute__((cleanup(virForceCloseHelper))) int
++
++
+ /* Opaque type for managing a wrapper around a fd.  */
+ struct _virFileWrapperFd;
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-util-implement-virCgroupV2-Set-Get-CpusetCpus.patch b/SOURCES/libvirt-util-implement-virCgroupV2-Set-Get-CpusetCpus.patch
new file mode 100644
index 0000000..153d769
--- /dev/null
+++ b/SOURCES/libvirt-util-implement-virCgroupV2-Set-Get-CpusetCpus.patch
@@ -0,0 +1,66 @@
+From 40020f9a96747e4e4b108c3cbef32222174bc2ab Mon Sep 17 00:00:00 2001
+Message-Id: <40020f9a96747e4e4b108c3cbef32222174bc2ab@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:08:13 +0200
+Subject: [PATCH] util: implement virCgroupV2(Set|Get)CpusetCpus
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 3b72c84ff1c1b8b393ba9c2ccb004f8eb1ebda95)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <6146318ef3b9ca769029e33c4617056cdb652844.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroupv2.c | 24 ++++++++++++++++++++++++
+ 1 file changed, 24 insertions(+)
+
+diff --git a/src/util/vircgroupv2.c b/src/util/vircgroupv2.c
+index bc6ced2367..ef1f286726 100644
+--- a/src/util/vircgroupv2.c
++++ b/src/util/vircgroupv2.c
+@@ -1601,6 +1601,28 @@ virCgroupV2GetCpusetMemoryMigrate(virCgroupPtr group ATTRIBUTE_UNUSED,
+ }
+ 
+ 
++static int
++virCgroupV2SetCpusetCpus(virCgroupPtr group,
++                         const char *cpus)
++{
++    return virCgroupSetValueStr(group,
++                                VIR_CGROUP_CONTROLLER_CPUSET,
++                                "cpuset.cpus",
++                                cpus);
++}
++
++
++static int
++virCgroupV2GetCpusetCpus(virCgroupPtr group,
++                         char **cpus)
++{
++    return virCgroupGetValueStr(group,
++                                VIR_CGROUP_CONTROLLER_CPUSET,
++                                "cpuset.cpus",
++                                cpus);
++}
++
++
+ virCgroupBackend virCgroupV2Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V2,
+ 
+@@ -1665,6 +1687,8 @@ virCgroupBackend virCgroupV2Backend = {
+     .getCpusetMems = virCgroupV2GetCpusetMems,
+     .setCpusetMemoryMigrate = virCgroupV2SetCpusetMemoryMigrate,
+     .getCpusetMemoryMigrate = virCgroupV2GetCpusetMemoryMigrate,
++    .setCpusetCpus = virCgroupV2SetCpusetCpus,
++    .getCpusetCpus = virCgroupV2GetCpusetCpus,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-util-implement-virCgroupV2-Set-Get-CpusetMemoryMigrate.patch b/SOURCES/libvirt-util-implement-virCgroupV2-Set-Get-CpusetMemoryMigrate.patch
new file mode 100644
index 0000000..39314e1
--- /dev/null
+++ b/SOURCES/libvirt-util-implement-virCgroupV2-Set-Get-CpusetMemoryMigrate.patch
@@ -0,0 +1,64 @@
+From 0cde517cd560d47824e0e98fab32b62cbd0f89ea Mon Sep 17 00:00:00 2001
+Message-Id: <0cde517cd560d47824e0e98fab32b62cbd0f89ea@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:08:12 +0200
+Subject: [PATCH] util: implement virCgroupV2(Set|Get)CpusetMemoryMigrate
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Cgroups v2 don't have memory_migrate interface and the migration is
+enabled by default.
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 77c1cf4da2f761a91756c09fa4fd37ae1802e650)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <b9de5444564a4e6f74c31c6b360e83879c451272.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroupv2.c | 19 +++++++++++++++++++
+ 1 file changed, 19 insertions(+)
+
+diff --git a/src/util/vircgroupv2.c b/src/util/vircgroupv2.c
+index 59b8c4ad2c..bc6ced2367 100644
+--- a/src/util/vircgroupv2.c
++++ b/src/util/vircgroupv2.c
+@@ -1584,6 +1584,23 @@ virCgroupV2GetCpusetMems(virCgroupPtr group,
+ }
+ 
+ 
++static int
++virCgroupV2SetCpusetMemoryMigrate(virCgroupPtr group ATTRIBUTE_UNUSED,
++                                  bool migrate ATTRIBUTE_UNUSED)
++{
++    return 0;
++}
++
++
++static int
++virCgroupV2GetCpusetMemoryMigrate(virCgroupPtr group ATTRIBUTE_UNUSED,
++                                  bool *migrate)
++{
++    *migrate = true;
++    return 0;
++}
++
++
+ virCgroupBackend virCgroupV2Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V2,
+ 
+@@ -1646,6 +1663,8 @@ virCgroupBackend virCgroupV2Backend = {
+ 
+     .setCpusetMems = virCgroupV2SetCpusetMems,
+     .getCpusetMems = virCgroupV2GetCpusetMems,
++    .setCpusetMemoryMigrate = virCgroupV2SetCpusetMemoryMigrate,
++    .getCpusetMemoryMigrate = virCgroupV2GetCpusetMemoryMigrate,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-util-implement-virCgroupV2-Set-Get-CpusetMems.patch b/SOURCES/libvirt-util-implement-virCgroupV2-Set-Get-CpusetMems.patch
new file mode 100644
index 0000000..ec50860
--- /dev/null
+++ b/SOURCES/libvirt-util-implement-virCgroupV2-Set-Get-CpusetMems.patch
@@ -0,0 +1,67 @@
+From df01b3c361e5bdcd8505798336b15b862e9c6bea Mon Sep 17 00:00:00 2001
+Message-Id: <df01b3c361e5bdcd8505798336b15b862e9c6bea@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:08:11 +0200
+Subject: [PATCH] util: implement virCgroupV2(Set|Get)CpusetMems
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 74e7da060543a87610b42fc6ba26a45b0a6e3974)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <2bb5ec423c37893ebbf2f882da13cc4e55b23941.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroupv2.c | 25 +++++++++++++++++++++++++
+ 1 file changed, 25 insertions(+)
+
+diff --git a/src/util/vircgroupv2.c b/src/util/vircgroupv2.c
+index 8658454d8b..59b8c4ad2c 100644
+--- a/src/util/vircgroupv2.c
++++ b/src/util/vircgroupv2.c
+@@ -1562,6 +1562,28 @@ virCgroupV2GetCpuacctStat(virCgroupPtr group,
+ }
+ 
+ 
++static int
++virCgroupV2SetCpusetMems(virCgroupPtr group,
++                         const char *mems)
++{
++    return virCgroupSetValueStr(group,
++                                VIR_CGROUP_CONTROLLER_CPUSET,
++                                "cpuset.mems",
++                                mems);
++}
++
++
++static int
++virCgroupV2GetCpusetMems(virCgroupPtr group,
++                         char **mems)
++{
++    return virCgroupGetValueStr(group,
++                                VIR_CGROUP_CONTROLLER_CPUSET,
++                                "cpuset.mems",
++                                mems);
++}
++
++
+ virCgroupBackend virCgroupV2Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V2,
+ 
+@@ -1621,6 +1643,9 @@ virCgroupBackend virCgroupV2Backend = {
+ 
+     .getCpuacctUsage = virCgroupV2GetCpuacctUsage,
+     .getCpuacctStat = virCgroupV2GetCpuacctStat,
++
++    .setCpusetMems = virCgroupV2SetCpusetMems,
++    .getCpusetMems = virCgroupV2GetCpusetMems,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-util-introduce-cgroup-v2-files.patch b/SOURCES/libvirt-util-introduce-cgroup-v2-files.patch
new file mode 100644
index 0000000..4234cdc
--- /dev/null
+++ b/SOURCES/libvirt-util-introduce-cgroup-v2-files.patch
@@ -0,0 +1,256 @@
+From 04bdbfa106768447822f3e8eeb2946e1f7bfb2b5 Mon Sep 17 00:00:00 2001
+Message-Id: <04bdbfa106768447822f3e8eeb2946e1f7bfb2b5@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:07:12 +0200
+Subject: [PATCH] util: introduce cgroup v2 files
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Place cgroup v2 backend type before cgroup v1 to make it obvious
+that cgroup v2 is preferred implementation.
+
+Following patches will introduce support for hybrid configuration
+which will allow us to use both at the same time, but we should
+prefer cgroup v2 regardless.
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit b4ddf5ae62ee3a50c7ead1e00914a141e5798096)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <fcbffeda541380f2e11e42f192b80276153bc84f.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/Makefile.am             |  1 +
+ src/libvirt_private.syms    |  3 ++
+ src/util/Makefile.inc.am    |  2 ++
+ src/util/vircgroup.c        |  3 ++
+ src/util/vircgroupbackend.c |  2 ++
+ src/util/vircgroupbackend.h |  3 +-
+ src/util/vircgrouppriv.h    |  9 ++++++
+ src/util/vircgroupv2.c      | 63 +++++++++++++++++++++++++++++++++++++
+ src/util/vircgroupv2.h      | 27 ++++++++++++++++
+ 9 files changed, 112 insertions(+), 1 deletion(-)
+ create mode 100644 src/util/vircgroupv2.c
+ create mode 100644 src/util/vircgroupv2.h
+
+diff --git a/src/Makefile.am b/src/Makefile.am
+index 0def0a3b19..cc8e29a45a 100644
+--- a/src/Makefile.am
++++ b/src/Makefile.am
+@@ -680,6 +680,7 @@ libvirt_setuid_rpc_client_la_SOURCES = \
+ 		util/vircgroup.c \
+ 		util/vircgroupbackend.c \
+ 		util/vircgroupv1.c \
++		util/vircgroupv2.c \
+ 		util/vircommand.c \
+ 		util/virconf.c \
+ 		util/virdbus.c \
+diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
+index b144955154..8132f9664b 100644
+--- a/src/libvirt_private.syms
++++ b/src/libvirt_private.syms
+@@ -1598,6 +1598,9 @@ virCgroupBackendRegister;
+ # util/vircgroupv1.h
+ virCgroupV1Register;
+ 
++# util/vircgroupv2.h
++virCgroupV2Register;
++
+ # util/virclosecallbacks.h
+ virCloseCallbacksGet;
+ virCloseCallbacksGetConn;
+diff --git a/src/util/Makefile.inc.am b/src/util/Makefile.inc.am
+index 725ece98e9..24a98632a3 100644
+--- a/src/util/Makefile.inc.am
++++ b/src/util/Makefile.inc.am
+@@ -27,6 +27,8 @@ UTIL_SOURCES = \
+ 	util/vircgroupbackend.h \
+ 	util/vircgroupv1.c \
+ 	util/vircgroupv1.h \
++	util/vircgroupv2.c \
++	util/vircgroupv2.h \
+ 	util/virclosecallbacks.c \
+ 	util/virclosecallbacks.h \
+ 	util/vircommand.c \
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index 7ec1399bc6..42930582db 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -1240,6 +1240,9 @@ virCgroupFree(virCgroupPtr *group)
+         VIR_FREE((*group)->legacy[i].placement);
+     }
+ 
++    VIR_FREE((*group)->unified.mountPoint);
++    VIR_FREE((*group)->unified.placement);
++
+     VIR_FREE((*group)->path);
+     VIR_FREE(*group);
+ }
+diff --git a/src/util/vircgroupbackend.c b/src/util/vircgroupbackend.c
+index d854c9711d..79fe6cb73d 100644
+--- a/src/util/vircgroupbackend.c
++++ b/src/util/vircgroupbackend.c
+@@ -21,6 +21,7 @@
+ 
+ #include "vircgroupbackend.h"
+ #include "vircgroupv1.h"
++#include "vircgroupv2.h"
+ #include "virerror.h"
+ #include "virthread.h"
+ 
+@@ -28,6 +29,7 @@
+ 
+ VIR_ENUM_DECL(virCgroupBackend);
+ VIR_ENUM_IMPL(virCgroupBackend, VIR_CGROUP_BACKEND_TYPE_LAST,
++              "cgroup V2",
+               "cgroup V1");
+ 
+ static virOnceControl virCgroupBackendOnce = VIR_ONCE_CONTROL_INITIALIZER;
+diff --git a/src/util/vircgroupbackend.h b/src/util/vircgroupbackend.h
+index 1c5744ef76..b1f19233e4 100644
+--- a/src/util/vircgroupbackend.h
++++ b/src/util/vircgroupbackend.h
+@@ -50,7 +50,8 @@ typedef enum {
+ } virCgroupBackendTaskFlags;
+ 
+ typedef enum {
+-    VIR_CGROUP_BACKEND_TYPE_V1 = 0,
++    VIR_CGROUP_BACKEND_TYPE_V2 = 0,
++    VIR_CGROUP_BACKEND_TYPE_V1,
+     VIR_CGROUP_BACKEND_TYPE_LAST,
+ } virCgroupBackendType;
+ 
+diff --git a/src/util/vircgrouppriv.h b/src/util/vircgrouppriv.h
+index c50a25f195..4a0d75ddbc 100644
+--- a/src/util/vircgrouppriv.h
++++ b/src/util/vircgrouppriv.h
+@@ -45,12 +45,21 @@ struct _virCgroupV1Controller {
+ typedef struct _virCgroupV1Controller virCgroupV1Controller;
+ typedef virCgroupV1Controller *virCgroupV1ControllerPtr;
+ 
++struct _virCgroupV2Controller {
++    int controllers;
++    char *mountPoint;
++    char *placement;
++};
++typedef struct _virCgroupV2Controller virCgroupV2Controller;
++typedef virCgroupV2Controller *virCgroupV2ControllerPtr;
++
+ struct _virCgroup {
+     char *path;
+ 
+     virCgroupBackendPtr backend;
+ 
+     virCgroupV1Controller legacy[VIR_CGROUP_CONTROLLER_LAST];
++    virCgroupV2Controller unified;
+ };
+ 
+ int virCgroupSetValueStr(virCgroupPtr group,
+diff --git a/src/util/vircgroupv2.c b/src/util/vircgroupv2.c
+new file mode 100644
+index 0000000000..23bf81dae2
+--- /dev/null
++++ b/src/util/vircgroupv2.c
+@@ -0,0 +1,63 @@
++/*
++ * vircgroupv2.c: methods for cgroups v2 backend
++ *
++ * Copyright (C) 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
++ * License as published by the Free Software Foundation; either
++ * version 2.1 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with this library.  If not, see
++ * <http://www.gnu.org/licenses/>.
++ */
++#include <config.h>
++
++#include "internal.h"
++
++#define __VIR_CGROUP_ALLOW_INCLUDE_PRIV_H__
++#include "vircgrouppriv.h"
++#undef __VIR_CGROUP_ALLOW_INCLUDE_PRIV_H__
++
++#include "vircgroup.h"
++#include "vircgroupbackend.h"
++#include "vircgroupv2.h"
++#include "virlog.h"
++
++VIR_LOG_INIT("util.cgroup");
++
++#define VIR_FROM_THIS VIR_FROM_CGROUP
++
++VIR_ENUM_DECL(virCgroupV2Controller);
++VIR_ENUM_IMPL(virCgroupV2Controller, VIR_CGROUP_CONTROLLER_LAST,
++              "cpu", "cpuacct", "cpuset", "memory", "devices",
++              "freezer", "io", "net_cls", "perf_event", "name=systemd");
++
++#ifdef __linux__
++
++virCgroupBackend virCgroupV2Backend = {
++    .type = VIR_CGROUP_BACKEND_TYPE_V2,
++};
++
++
++void
++virCgroupV2Register(void)
++{
++    virCgroupBackendRegister(&virCgroupV2Backend);
++}
++
++#else /* !__linux__ */
++
++void
++virCgroupV2Register(void)
++{
++    VIR_INFO("Control groups not supported on this platform");
++}
++
++#endif /* !__linux__ */
+diff --git a/src/util/vircgroupv2.h b/src/util/vircgroupv2.h
+new file mode 100644
+index 0000000000..a5d0bd0978
+--- /dev/null
++++ b/src/util/vircgroupv2.h
+@@ -0,0 +1,27 @@
++/*
++ * vircgroupv2.h: methods for cgroups v2 backend
++ *
++ * Copyright (C) 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
++ * License as published by the Free Software Foundation; either
++ * version 2.1 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with this library.  If not, see
++ * <http://www.gnu.org/licenses/>.
++ */
++
++#ifndef __VIR_CGROUP_V2_H__
++# define __VIR_CGROUP_V2_H__
++
++void
++virCgroupV2Register(void);
++
++#endif /* __VIR_CGROUP_V2_H__ */
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-util-introduce-vircgroupbackend-files.patch b/SOURCES/libvirt-util-introduce-vircgroupbackend-files.patch
new file mode 100644
index 0000000..78471e2
--- /dev/null
+++ b/SOURCES/libvirt-util-introduce-vircgroupbackend-files.patch
@@ -0,0 +1,197 @@
+From 2396295b2654156d62165bc1d94e2a3f4d1e4733 Mon Sep 17 00:00:00 2001
+Message-Id: <2396295b2654156d62165bc1d94e2a3f4d1e4733@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:06:21 +0200
+Subject: [PATCH] util: introduce vircgroupbackend files
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+We will need to extract current cgroup v1 implementation into separate
+backend because there will be new cgroup v2 implementation and both will
+have to co-exist.
+
+Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 1a2dbb5595871efa8de1ed258d94f0b60561a040)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <dbe1f56fc1ba95c077092303b1f17b67e8f9075a.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/Makefile.am             |  1 +
+ src/libvirt_private.syms    |  3 ++
+ src/util/Makefile.inc.am    |  2 ++
+ src/util/vircgroupbackend.c | 64 +++++++++++++++++++++++++++++++++++++
+ src/util/vircgroupbackend.h | 46 ++++++++++++++++++++++++++
+ 5 files changed, 116 insertions(+)
+ create mode 100644 src/util/vircgroupbackend.c
+ create mode 100644 src/util/vircgroupbackend.h
+
+diff --git a/src/Makefile.am b/src/Makefile.am
+index db8c8ebd1a..c4e797f5a2 100644
+--- a/src/Makefile.am
++++ b/src/Makefile.am
+@@ -678,6 +678,7 @@ libvirt_setuid_rpc_client_la_SOURCES = \
+ 		util/virbitmap.c \
+ 		util/virbuffer.c \
+ 		util/vircgroup.c \
++		util/vircgroupbackend.c \
+ 		util/vircommand.c \
+ 		util/virconf.c \
+ 		util/virdbus.c \
+diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
+index 8c4be84fd5..627eb5e587 100644
+--- a/src/libvirt_private.syms
++++ b/src/libvirt_private.syms
+@@ -1591,6 +1591,9 @@ virCgroupSetOwner;
+ virCgroupSupportsCpuBW;
+ virCgroupTerminateMachine;
+ 
++# util/vircgroupbackend.h
++virCgroupBackendGetAll;
++virCgroupBackendRegister;
+ 
+ # util/virclosecallbacks.h
+ virCloseCallbacksGet;
+diff --git a/src/util/Makefile.inc.am b/src/util/Makefile.inc.am
+index 2cef465208..a9185bd7b7 100644
+--- a/src/util/Makefile.inc.am
++++ b/src/util/Makefile.inc.am
+@@ -23,6 +23,8 @@ UTIL_SOURCES = \
+ 	util/virperf.h \
+ 	util/vircgroup.c \
+ 	util/vircgroup.h util/vircgrouppriv.h \
++	util/vircgroupbackend.c \
++	util/vircgroupbackend.h \
+ 	util/virclosecallbacks.c \
+ 	util/virclosecallbacks.h \
+ 	util/vircommand.c \
+diff --git a/src/util/vircgroupbackend.c b/src/util/vircgroupbackend.c
+new file mode 100644
+index 0000000000..e014bfc0e6
+--- /dev/null
++++ b/src/util/vircgroupbackend.c
+@@ -0,0 +1,64 @@
++/*
++ * vircgroupbackend.c: methods for cgroups backend
++ *
++ * Copyright (C) 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
++ * License as published by the Free Software Foundation; either
++ * version 2.1 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with this library.  If not, see
++ * <http://www.gnu.org/licenses/>.
++ */
++#include <config.h>
++
++#include "vircgroupbackend.h"
++#include "virerror.h"
++#include "virthread.h"
++
++#define VIR_FROM_THIS VIR_FROM_CGROUP
++
++VIR_ENUM_DECL(virCgroupBackend);
++VIR_ENUM_IMPL(virCgroupBackend, VIR_CGROUP_BACKEND_TYPE_LAST,
++              "cgroup V1");
++
++static virOnceControl virCgroupBackendOnce = VIR_ONCE_CONTROL_INITIALIZER;
++static virCgroupBackendPtr virCgroupBackends[VIR_CGROUP_BACKEND_TYPE_LAST] = { 0 };
++
++void
++virCgroupBackendRegister(virCgroupBackendPtr backend)
++{
++    if (virCgroupBackends[backend->type]) {
++        virReportError(VIR_ERR_INTERNAL_ERROR,
++                       _("Cgroup backend '%s' already registered."),
++                       virCgroupBackendTypeToString(backend->type));
++        return;
++    }
++
++    virCgroupBackends[backend->type] = backend;
++}
++
++
++static void
++virCgroupBackendOnceInit(void)
++{
++}
++
++
++virCgroupBackendPtr *
++virCgroupBackendGetAll(void)
++{
++    if (virOnce(&virCgroupBackendOnce, virCgroupBackendOnceInit) < 0) {
++        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
++                       _("Failed to initialize cgroup backend."));
++        return NULL;
++    }
++    return virCgroupBackends;
++}
+diff --git a/src/util/vircgroupbackend.h b/src/util/vircgroupbackend.h
+new file mode 100644
+index 0000000000..db052485a8
+--- /dev/null
++++ b/src/util/vircgroupbackend.h
+@@ -0,0 +1,46 @@
++/*
++ * vircgroupbackend.h: methods for cgroups backend
++ *
++ * Copyright (C) 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
++ * License as published by the Free Software Foundation; either
++ * version 2.1 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with this library.  If not, see
++ * <http://www.gnu.org/licenses/>.
++ */
++
++#ifndef __VIR_CGROUP_BACKEND_H__
++# define __VIR_CGROUP_BACKEND_H__
++
++# include "internal.h"
++
++# include "vircgroup.h"
++
++
++typedef enum {
++    VIR_CGROUP_BACKEND_TYPE_V1 = 0,
++    VIR_CGROUP_BACKEND_TYPE_LAST,
++} virCgroupBackendType;
++
++struct _virCgroupBackend {
++    virCgroupBackendType type;
++};
++typedef struct _virCgroupBackend virCgroupBackend;
++typedef virCgroupBackend *virCgroupBackendPtr;
++
++void
++virCgroupBackendRegister(virCgroupBackendPtr backend);
++
++virCgroupBackendPtr *
++virCgroupBackendGetAll(void);
++
++#endif /* __VIR_CGROUP_BACKEND_H__ */
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-util-json-define-cleanup-function-using-VIR_DEFINE_AUTOPTR_FUNC.patch b/SOURCES/libvirt-util-json-define-cleanup-function-using-VIR_DEFINE_AUTOPTR_FUNC.patch
new file mode 100644
index 0000000..2b9884b
--- /dev/null
+++ b/SOURCES/libvirt-util-json-define-cleanup-function-using-VIR_DEFINE_AUTOPTR_FUNC.patch
@@ -0,0 +1,69 @@
+From 25ceaef5ff5e392dace991db3e737dbdb50a6bba Mon Sep 17 00:00:00 2001
+Message-Id: <25ceaef5ff5e392dace991db3e737dbdb50a6bba@dist-git>
+From: Sukrit Bhatnagar <skrtbhtngr@gmail.com>
+Date: Fri, 21 Jun 2019 09:26:02 +0200
+Subject: [PATCH] util: json: define cleanup function using
+ VIR_DEFINE_AUTOPTR_FUNC
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Using the new VIR_DEFINE_AUTOPTR_FUNC macro defined in
+src/util/viralloc.h, define a new wrapper around an existing
+cleanup function which will be called when a variable declared
+with VIR_AUTOPTR macro goes out of scope. Also, drop the redundant
+viralloc.h include, since that has moved from the source module into the
+header.
+
+When a variable of type virJSONValuePtr is declared using
+VIR_AUTOPTR, the function virJSONValueFree will be run
+automatically on it when it goes out of scope.
+
+Signed-off-by: Sukrit Bhatnagar <skrtbhtngr@gmail.com>
+Reviewed-by: Erik Skultety <eskultet@redhat.com>
+(cherry picked from commit b5b5cdd69ca1c954635f9f6dda05d6b15b01cc8a)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1697627
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <4dd72d7d93725d77a2bd89fbd890fe3d774f29d2.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/virjson.c | 1 -
+ src/util/virjson.h | 3 +++
+ 2 files changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/src/util/virjson.c b/src/util/virjson.c
+index 0559d40b64..92f3994e92 100644
+--- a/src/util/virjson.c
++++ b/src/util/virjson.c
+@@ -24,7 +24,6 @@
+ #include <config.h>
+ 
+ #include "virjson.h"
+-#include "viralloc.h"
+ #include "virerror.h"
+ #include "virlog.h"
+ #include "virstring.h"
+diff --git a/src/util/virjson.h b/src/util/virjson.h
+index e4a82bdbc8..75f7f17b44 100644
+--- a/src/util/virjson.h
++++ b/src/util/virjson.h
+@@ -26,6 +26,7 @@
+ 
+ # include "internal.h"
+ # include "virbitmap.h"
++# include "viralloc.h"
+ 
+ # include <stdarg.h>
+ 
+@@ -156,4 +157,6 @@ char *virJSONStringReformat(const char *jsonstr, bool pretty);
+ 
+ virJSONValuePtr virJSONValueObjectDeflatten(virJSONValuePtr json);
+ 
++VIR_DEFINE_AUTOPTR_FUNC(virJSONValue, virJSONValueFree)
++
+ #endif /* __VIR_JSON_H_ */
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-util-moving-type-argument-to-avoid-issues-with-mount-syscall.patch b/SOURCES/libvirt-util-moving-type-argument-to-avoid-issues-with-mount-syscall.patch
new file mode 100644
index 0000000..a70a5d7
--- /dev/null
+++ b/SOURCES/libvirt-util-moving-type-argument-to-avoid-issues-with-mount-syscall.patch
@@ -0,0 +1,43 @@
+From bb4d2abe30f8ad3de4f7f3201de897440cdd545c Mon Sep 17 00:00:00 2001
+Message-Id: <bb4d2abe30f8ad3de4f7f3201de897440cdd545c@dist-git>
+From: Julio Faracco <jcfaracco@gmail.com>
+Date: Mon, 1 Jul 2019 17:05:46 +0200
+Subject: [PATCH] util: moving 'type' argument to avoid issues with mount()
+ syscall.
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This commit fixes a mount call inside virgroup.c file. The NULL value
+into 'type' argument is causing a valgrind issue. See commit 794b576c
+for more details. The best approach to fix it is moving NULL to "none"
+filesytem.
+
+Signed-off-by: Julio Faracco <jcfaracco@gmail.com>
+(cherry picked from commit 4539301bc84ee65558a48c1c3c22aa04f458dbe0)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <006a95f4385f575718eee431fc905702cff3e848.1561993099.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index 0a31947b0d..e810a3d81d 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -3962,7 +3962,7 @@ virCgroupBindMount(virCgroupPtr group, const char *oldroot,
+                 goto cleanup;
+             }
+ 
+-            if (mount(src, group->controllers[i].mountPoint, NULL, MS_BIND,
++            if (mount(src, group->controllers[i].mountPoint, "none", MS_BIND,
+                       NULL) < 0) {
+                 virReportSystemError(errno,
+                                      _("Failed to bind cgroup '%s' on '%s'"),
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-util-netdevopenvswitch-use-VIR_AUTOFREE-instead-of-VIR_FREE-for-scalar-types.patch b/SOURCES/libvirt-util-netdevopenvswitch-use-VIR_AUTOFREE-instead-of-VIR_FREE-for-scalar-types.patch
new file mode 100644
index 0000000..2d6c088
--- /dev/null
+++ b/SOURCES/libvirt-util-netdevopenvswitch-use-VIR_AUTOFREE-instead-of-VIR_FREE-for-scalar-types.patch
@@ -0,0 +1,98 @@
+From ca441a9e1e6d757cd1aa7dfb84c0e37cb1924b87 Mon Sep 17 00:00:00 2001
+Message-Id: <ca441a9e1e6d757cd1aa7dfb84c0e37cb1924b87@dist-git>
+From: Sukrit Bhatnagar <skrtbhtngr@gmail.com>
+Date: Tue, 30 Jul 2019 15:30:47 +0200
+Subject: [PATCH] util: netdevopenvswitch: use VIR_AUTOFREE instead of VIR_FREE
+ for scalar types
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+By making use of GNU C's cleanup attribute handled by the
+VIR_AUTOFREE macro for declaring scalar variables, majority
+of the VIR_FREE calls can be dropped, which in turn leads to
+getting rid of most of our cleanup sections.
+
+Signed-off-by: Sukrit Bhatnagar <skrtbhtngr@gmail.com>
+Reviewed-by: Erik Skultety <eskultet@redhat.com>
+(cherry picked from commit 2d9be4d8b4cfea2a85a8ebe21ffadf4b3101a09b)
+
+Prerequisite of: https://bugzilla.redhat.com/show_bug.cgi?id=1721434
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Message-Id: <56656242ad6da70744bfda6d0757125eea669751.1564493409.git.mprivozn@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/virnetdevopenvswitch.c | 18 ++++++------------
+ 1 file changed, 6 insertions(+), 12 deletions(-)
+
+diff --git a/src/util/virnetdevopenvswitch.c b/src/util/virnetdevopenvswitch.c
+index f86f698430..36c587efdb 100644
+--- a/src/util/virnetdevopenvswitch.c
++++ b/src/util/virnetdevopenvswitch.c
+@@ -149,10 +149,10 @@ int virNetDevOpenvswitchAddPort(const char *brname, const char *ifname,
+     char macaddrstr[VIR_MAC_STRING_BUFLEN];
+     char ifuuidstr[VIR_UUID_STRING_BUFLEN];
+     char vmuuidstr[VIR_UUID_STRING_BUFLEN];
+-    char *attachedmac_ex_id = NULL;
+-    char *ifaceid_ex_id = NULL;
+-    char *profile_ex_id = NULL;
+-    char *vmid_ex_id = NULL;
++    VIR_AUTOFREE(char *) attachedmac_ex_id = NULL;
++    VIR_AUTOFREE(char *) ifaceid_ex_id = NULL;
++    VIR_AUTOFREE(char *) profile_ex_id = NULL;
++    VIR_AUTOFREE(char *) vmid_ex_id = NULL;
+ 
+     virMacAddrFormat(macaddr, macaddrstr);
+     virUUIDFormat(ovsport->interfaceID, ifuuidstr);
+@@ -209,10 +209,6 @@ int virNetDevOpenvswitchAddPort(const char *brname, const char *ifname,
+ 
+     ret = 0;
+  cleanup:
+-    VIR_FREE(attachedmac_ex_id);
+-    VIR_FREE(ifaceid_ex_id);
+-    VIR_FREE(vmid_ex_id);
+-    VIR_FREE(profile_ex_id);
+     virCommandFree(cmd);
+     return ret;
+ }
+@@ -339,10 +335,10 @@ virNetDevOpenvswitchInterfaceStats(const char *ifname,
+                                    virDomainInterfaceStatsPtr stats)
+ {
+     virCommandPtr cmd = NULL;
+-    char *output;
+     char *tmp;
+     bool gotStats = false;
+     int ret = -1;
++    VIR_AUTOFREE(char *) output = NULL;
+ 
+     /* Just ensure the interface exists in ovs */
+     cmd = virCommandNew(OVSVSCTL);
+@@ -399,7 +395,6 @@ virNetDevOpenvswitchInterfaceStats(const char *ifname,
+     ret = 0;
+ 
+  cleanup:
+-    VIR_FREE(output);
+     virCommandFree(cmd);
+     return ret;
+ }
+@@ -425,7 +420,7 @@ virNetDevOpenvswitchGetVhostuserIfname(const char *path,
+     size_t ntokens = 0;
+     int status;
+     int ret = -1;
+-    char *ovs_timeout = NULL;
++    VIR_AUTOFREE(char *) ovs_timeout = NULL;
+ 
+     /* Openvswitch vhostuser path are hardcoded to
+      * /<runstatedir>/openvswitch/<ifname>
+@@ -457,7 +452,6 @@ virNetDevOpenvswitchGetVhostuserIfname(const char *path,
+  cleanup:
+     virStringListFreeCount(tokens, ntokens);
+     virCommandFree(cmd);
+-    VIR_FREE(ovs_timeout);
+     return ret;
+ }
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-util-netdevopenvswitch-use-VIR_AUTOPTR-for-aggregate-types.patch b/SOURCES/libvirt-util-netdevopenvswitch-use-VIR_AUTOPTR-for-aggregate-types.patch
new file mode 100644
index 0000000..2618401
--- /dev/null
+++ b/SOURCES/libvirt-util-netdevopenvswitch-use-VIR_AUTOPTR-for-aggregate-types.patch
@@ -0,0 +1,277 @@
+From d808105a19611b7561c7ab0e4b128fbabebc88e2 Mon Sep 17 00:00:00 2001
+Message-Id: <d808105a19611b7561c7ab0e4b128fbabebc88e2@dist-git>
+From: Sukrit Bhatnagar <skrtbhtngr@gmail.com>
+Date: Tue, 30 Jul 2019 15:30:49 +0200
+Subject: [PATCH] util: netdevopenvswitch: use VIR_AUTOPTR for aggregate types
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+By making use of GNU C's cleanup attribute handled by the
+VIR_AUTOPTR macro for declaring aggregate pointer variables,
+majority of the calls to *Free functions can be dropped, which
+in turn leads to getting rid of most of our cleanup sections.
+
+Signed-off-by: Sukrit Bhatnagar <skrtbhtngr@gmail.com>
+Reviewed-by: Erik Skultety <eskultet@redhat.com>
+(cherry picked from commit 1077b46de6730eea76884b921bed1ece65be26ef)
+
+Prerequisite of: https://bugzilla.redhat.com/show_bug.cgi?id=1721434
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Message-Id: <1b5f75ad2258bb10ea75fe646271e9625d49f998.1564493409.git.mprivozn@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/virnetdevopenvswitch.c | 80 +++++++++++----------------------
+ 1 file changed, 27 insertions(+), 53 deletions(-)
+
+diff --git a/src/util/virnetdevopenvswitch.c b/src/util/virnetdevopenvswitch.c
+index 0dcd49d40f..2f5c7ac789 100644
+--- a/src/util/virnetdevopenvswitch.c
++++ b/src/util/virnetdevopenvswitch.c
+@@ -144,11 +144,10 @@ int virNetDevOpenvswitchAddPort(const char *brname, const char *ifname,
+                                    virNetDevVPortProfilePtr ovsport,
+                                    virNetDevVlanPtr virtVlan)
+ {
+-    int ret = -1;
+-    virCommandPtr cmd = NULL;
+     char macaddrstr[VIR_MAC_STRING_BUFLEN];
+     char ifuuidstr[VIR_UUID_STRING_BUFLEN];
+     char vmuuidstr[VIR_UUID_STRING_BUFLEN];
++    VIR_AUTOPTR(virCommand) cmd = NULL;
+     VIR_AUTOFREE(char *) attachedmac_ex_id = NULL;
+     VIR_AUTOFREE(char *) ifaceid_ex_id = NULL;
+     VIR_AUTOFREE(char *) profile_ex_id = NULL;
+@@ -160,17 +159,17 @@ int virNetDevOpenvswitchAddPort(const char *brname, const char *ifname,
+ 
+     if (virAsprintf(&attachedmac_ex_id, "external-ids:attached-mac=\"%s\"",
+                     macaddrstr) < 0)
+-        goto cleanup;
++        return -1;
+     if (virAsprintf(&ifaceid_ex_id, "external-ids:iface-id=\"%s\"",
+                     ifuuidstr) < 0)
+-        goto cleanup;
++        return -1;
+     if (virAsprintf(&vmid_ex_id, "external-ids:vm-id=\"%s\"",
+                     vmuuidstr) < 0)
+-        goto cleanup;
++        return -1;
+     if (ovsport->profileID[0] != '\0') {
+         if (virAsprintf(&profile_ex_id, "external-ids:port-profile=\"%s\"",
+                         ovsport->profileID) < 0)
+-            goto cleanup;
++            return -1;
+     }
+ 
+     cmd = virCommandNew(OVSVSCTL);
+@@ -179,7 +178,7 @@ int virNetDevOpenvswitchAddPort(const char *brname, const char *ifname,
+                          ifname, "--", "add-port", brname, ifname, NULL);
+ 
+     if (virNetDevOpenvswitchConstructVlans(cmd, virtVlan) < 0)
+-        goto cleanup;
++        return -1;
+ 
+     if (ovsport->profileID[0] == '\0') {
+         virCommandAddArgList(cmd,
+@@ -204,13 +203,10 @@ int virNetDevOpenvswitchAddPort(const char *brname, const char *ifname,
+         virReportError(VIR_ERR_INTERNAL_ERROR,
+                        _("Unable to add port %s to OVS bridge %s"),
+                        ifname, brname);
+-        goto cleanup;
++        return -1;
+     }
+ 
+-    ret = 0;
+- cleanup:
+-    virCommandFree(cmd);
+-    return ret;
++    return 0;
+ }
+ 
+ /**
+@@ -223,8 +219,7 @@ int virNetDevOpenvswitchAddPort(const char *brname, const char *ifname,
+  */
+ int virNetDevOpenvswitchRemovePort(const char *brname ATTRIBUTE_UNUSED, const char *ifname)
+ {
+-    int ret = -1;
+-    virCommandPtr cmd = NULL;
++    VIR_AUTOPTR(virCommand) cmd = NULL;
+ 
+     cmd = virCommandNew(OVSVSCTL);
+     virNetDevOpenvswitchAddTimeout(cmd);
+@@ -233,13 +228,10 @@ int virNetDevOpenvswitchRemovePort(const char *brname ATTRIBUTE_UNUSED, const ch
+     if (virCommandRun(cmd, NULL) < 0) {
+         virReportError(VIR_ERR_INTERNAL_ERROR,
+                        _("Unable to delete port %s from OVS"), ifname);
+-        goto cleanup;
++        return -1;
+     }
+ 
+-    ret = 0;
+- cleanup:
+-    virCommandFree(cmd);
+-    return ret;
++    return 0;
+ }
+ 
+ /**
+@@ -253,9 +245,8 @@ int virNetDevOpenvswitchRemovePort(const char *brname ATTRIBUTE_UNUSED, const ch
+  */
+ int virNetDevOpenvswitchGetMigrateData(char **migrate, const char *ifname)
+ {
+-    virCommandPtr cmd = NULL;
+     size_t len;
+-    int ret = -1;
++    VIR_AUTOPTR(virCommand) cmd = NULL;
+ 
+     cmd = virCommandNew(OVSVSCTL);
+     virNetDevOpenvswitchAddTimeout(cmd);
+@@ -269,7 +260,7 @@ int virNetDevOpenvswitchGetMigrateData(char **migrate, const char *ifname)
+         virReportError(VIR_ERR_INTERNAL_ERROR,
+                        _("Unable to run command to get OVS port data for "
+                          "interface %s"), ifname);
+-        goto cleanup;
++        return -1;
+     }
+ 
+     /* Wipeout the newline, if it exists */
+@@ -277,10 +268,7 @@ int virNetDevOpenvswitchGetMigrateData(char **migrate, const char *ifname)
+     if (len > 0)
+         (*migrate)[len - 1] = '\0';
+ 
+-    ret = 0;
+- cleanup:
+-    virCommandFree(cmd);
+-    return ret;
++    return 0;
+ }
+ 
+ /**
+@@ -294,8 +282,7 @@ int virNetDevOpenvswitchGetMigrateData(char **migrate, const char *ifname)
+  */
+ int virNetDevOpenvswitchSetMigrateData(char *migrate, const char *ifname)
+ {
+-    virCommandPtr cmd = NULL;
+-    int ret = -1;
++    VIR_AUTOPTR(virCommand) cmd = NULL;
+ 
+     if (!migrate) {
+         VIR_DEBUG("No OVS port data for interface %s", ifname);
+@@ -312,13 +299,10 @@ int virNetDevOpenvswitchSetMigrateData(char *migrate, const char *ifname)
+         virReportError(VIR_ERR_INTERNAL_ERROR,
+                        _("Unable to run command to set OVS port data for "
+                          "interface %s"), ifname);
+-        goto cleanup;
++        return -1;
+     }
+ 
+-    ret = 0;
+- cleanup:
+-    virCommandFree(cmd);
+-    return ret;
++    return 0;
+ }
+ 
+ /**
+@@ -334,10 +318,9 @@ int
+ virNetDevOpenvswitchInterfaceStats(const char *ifname,
+                                    virDomainInterfaceStatsPtr stats)
+ {
+-    virCommandPtr cmd = NULL;
+     char *tmp;
+     bool gotStats = false;
+-    int ret = -1;
++    VIR_AUTOPTR(virCommand) cmd = NULL;
+     VIR_AUTOFREE(char *) output = NULL;
+ 
+     /* Just ensure the interface exists in ovs */
+@@ -350,7 +333,7 @@ virNetDevOpenvswitchInterfaceStats(const char *ifname,
+         /* no ovs-vsctl or interface 'ifname' doesn't exists in ovs */
+         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                        _("Interface not found"));
+-        goto cleanup;
++        return -1;
+     }
+ 
+ #define GET_STAT(name, member) \
+@@ -369,7 +352,7 @@ virNetDevOpenvswitchInterfaceStats(const char *ifname,
+                 *tmp != '\n') { \
+                 virReportError(VIR_ERR_INTERNAL_ERROR, "%s", \
+                                _("Fail to parse ovs-vsctl output")); \
+-                goto cleanup; \
++                return -1; \
+             } \
+             gotStats = true; \
+         } \
+@@ -389,14 +372,10 @@ virNetDevOpenvswitchInterfaceStats(const char *ifname,
+     if (!gotStats) {
+         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                        _("Interface doesn't have any statistics"));
+-        goto cleanup;
++        return -1;
+     }
+ 
+-    ret = 0;
+-
+- cleanup:
+-    virCommandFree(cmd);
+-    return ret;
++    return 0;
+ }
+ 
+ /**
+@@ -414,12 +393,12 @@ int
+ virNetDevOpenvswitchGetVhostuserIfname(const char *path,
+                                        char **ifname)
+ {
+-    virCommandPtr cmd = NULL;
+     char *tmpIfname = NULL;
+     char **tokens = NULL;
+     size_t ntokens = 0;
+     int status;
+     int ret = -1;
++    VIR_AUTOPTR(virCommand) cmd = NULL;
+ 
+     /* Openvswitch vhostuser path are hardcoded to
+      * /<runstatedir>/openvswitch/<ifname>
+@@ -450,7 +429,6 @@ virNetDevOpenvswitchGetVhostuserIfname(const char *path,
+ 
+  cleanup:
+     virStringListFreeCount(tokens, ntokens);
+-    virCommandFree(cmd);
+     return ret;
+ }
+ 
+@@ -466,8 +444,7 @@ virNetDevOpenvswitchGetVhostuserIfname(const char *path,
+ int virNetDevOpenvswitchUpdateVlan(const char *ifname,
+                                    virNetDevVlanPtr virtVlan)
+ {
+-    int ret = -1;
+-    virCommandPtr cmd = NULL;
++    VIR_AUTOPTR(virCommand) cmd = NULL;
+ 
+     cmd = virCommandNew(OVSVSCTL);
+     virNetDevOpenvswitchAddTimeout(cmd);
+@@ -478,16 +455,13 @@ int virNetDevOpenvswitchUpdateVlan(const char *ifname,
+                          "--", "--if-exists", "set", "Port", ifname, NULL);
+ 
+     if (virNetDevOpenvswitchConstructVlans(cmd, virtVlan) < 0)
+-        goto cleanup;
++        return -1;
+ 
+     if (virCommandRun(cmd, NULL) < 0) {
+         virReportError(VIR_ERR_INTERNAL_ERROR,
+                        _("Unable to set vlan configuration on port %s"), ifname);
+-        goto cleanup;
++        return -1;
+     }
+ 
+-    ret = 0;
+- cleanup:
+-    virCommandFree(cmd);
+-    return ret;
++    return 0;
+ }
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-util-skip-RDMA-detection-for-non-PCI-network-devices.patch b/SOURCES/libvirt-util-skip-RDMA-detection-for-non-PCI-network-devices.patch
new file mode 100644
index 0000000..356bb43
--- /dev/null
+++ b/SOURCES/libvirt-util-skip-RDMA-detection-for-non-PCI-network-devices.patch
@@ -0,0 +1,51 @@
+From dce9613ddab9d780ce9aabeb9a084ffec307899c Mon Sep 17 00:00:00 2001
+Message-Id: <dce9613ddab9d780ce9aabeb9a084ffec307899c@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 20 May 2019 10:12:55 +0200
+Subject: [PATCH] util: skip RDMA detection for non-PCI network devices
+
+Only PCI devices have '/sys/class/net/<ifname>/device/resource' so we
+need to skip this check for all other network devices.
+
+Without this patch and RDMA enabled libvirt will not detect any network
+device that doesn't have the path above which includes 'lo', 'virbr',
+'tun', etc.
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1639258
+
+Reviewed-by: Andrea Bolognani <abologna@redhat.com>
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit f38ef0fac0582ac0cbb749af9d3f8ba515a6084a)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1693299
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <5d2c32fd3f2d7e3f9664d395c00cdfc942c738ce.1558339954.git.phrdina@redhat.com>
+Reviewed-by: Andrea Bolognani <abologna@redhat.com>
+---
+ src/util/virnetdev.c | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+diff --git a/src/util/virnetdev.c b/src/util/virnetdev.c
+index b250af9e2c..9ca3ce69bc 100644
+--- a/src/util/virnetdev.c
++++ b/src/util/virnetdev.c
+@@ -3016,8 +3016,14 @@ virNetDevRDMAFeature(const char *ifname,
+ 
+     if (virAsprintf(&eth_devpath, SYSFS_NET_DIR "%s/device/resource", ifname) < 0)
+         goto cleanup;
+-    if (!virFileExists(eth_devpath))
++
++    /* If /sys/class/net/<ifname>/device/resource doesn't exist it is not a PCI
++     * device and therefore it will not have RDMA. */
++    if (!virFileExists(eth_devpath)) {
++        ret = 0;
+         goto cleanup;
++    }
++
+     if (virFileReadAll(eth_devpath, RESOURCE_FILE_LEN, &eth_res_buf) < 0)
+         goto cleanup;
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-util-string-Introduce-macro-for-automatic-string-lists.patch b/SOURCES/libvirt-util-string-Introduce-macro-for-automatic-string-lists.patch
new file mode 100644
index 0000000..9c99563
--- /dev/null
+++ b/SOURCES/libvirt-util-string-Introduce-macro-for-automatic-string-lists.patch
@@ -0,0 +1,94 @@
+From b9490d128b1a65d4d1ca273ddd54c696fa62ad73 Mon Sep 17 00:00:00 2001
+Message-Id: <b9490d128b1a65d4d1ca273ddd54c696fa62ad73@dist-git>
+From: Peter Krempa <pkrempa@redhat.com>
+Date: Fri, 21 Jun 2019 09:26:01 +0200
+Subject: [PATCH] util: string: Introduce macro for automatic string lists
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Similar to VIR_AUTOPTR, VIR_AUTOSTRINGLIST defines a list of strings
+which will be freed if the pointer is leaving scope.
+
+Signed-off-by: Peter Krempa <pkrempa@redhat.com>
+Reviewed-by: Erik Skultety <eskultet@redhat.com>
+(cherry picked from commit daefda165b28b399478137c75b5466f865c65be5)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1697627
+
+Conflicts:
+	src/util/virstring.h
+            - different header file guard
+            - no AUTOPTR for string lists
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <7f1e7edf9c9a096fde1a2adf37090f8190e99be2.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/libvirt_private.syms |  1 +
+ src/util/virstring.c     | 10 ++++++++++
+ src/util/virstring.h     | 10 ++++++++++
+ 3 files changed, 21 insertions(+)
+
+diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
+index a20e0593f0..06374deaae 100644
+--- a/src/libvirt_private.syms
++++ b/src/libvirt_private.syms
+@@ -2923,6 +2923,7 @@ virStringHasControlChars;
+ virStringIsEmpty;
+ virStringIsPrintable;
+ virStringListAdd;
++virStringListAutoFree;
+ virStringListFree;
+ virStringListFreeCount;
+ virStringListGetFirstWithPrefix;
+diff --git a/src/util/virstring.c b/src/util/virstring.c
+index 15f367af7c..0f13b6c664 100644
+--- a/src/util/virstring.c
++++ b/src/util/virstring.c
+@@ -332,6 +332,16 @@ void virStringListFree(char **strings)
+ }
+ 
+ 
++void virStringListAutoFree(char ***strings)
++{
++    if (!*strings)
++        return;
++
++    virStringListFree(*strings);
++    *strings = NULL;
++}
++
++
+ /**
+  * virStringListFreeCount:
+  * @strings: array of strings to free
+diff --git a/src/util/virstring.h b/src/util/virstring.h
+index 607ae66e99..e68b9eec79 100644
+--- a/src/util/virstring.h
++++ b/src/util/virstring.h
+@@ -53,6 +53,7 @@ int virStringListCopy(char ***dst,
+                       const char **src);
+ 
+ void virStringListFree(char **strings);
++void virStringListAutoFree(char ***strings);
+ void virStringListFreeCount(char **strings,
+                             size_t count);
+ 
+@@ -309,4 +310,13 @@ int virStringParsePort(const char *str,
+                        unsigned int *port)
+     ATTRIBUTE_NONNULL(2) ATTRIBUTE_RETURN_CHECK;
+ 
++/**
++ * VIR_AUTOSTRINGLIST:
++ *
++ * Declares a NULL-terminated list of strings which will be automatically freed
++ * when the pointer goes out of scope.
++ */
++# define VIR_AUTOSTRINGLIST \
++        __attribute__((cleanup(virStringListAutoFree))) char **
++
+ #endif /* __VIR_STRING_H__ */
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-util-suppress-unimportant-ovs-vsctl-errors-when-getting-interface-stats.patch b/SOURCES/libvirt-util-suppress-unimportant-ovs-vsctl-errors-when-getting-interface-stats.patch
new file mode 100644
index 0000000..7f450bc
--- /dev/null
+++ b/SOURCES/libvirt-util-suppress-unimportant-ovs-vsctl-errors-when-getting-interface-stats.patch
@@ -0,0 +1,55 @@
+From 53282d1e7f34724c6be7704ec56324c507894397 Mon Sep 17 00:00:00 2001
+Message-Id: <53282d1e7f34724c6be7704ec56324c507894397@dist-git>
+From: Laine Stump <laine@laine.org>
+Date: Tue, 30 Jul 2019 15:30:50 +0200
+Subject: [PATCH] util: suppress unimportant ovs-vsctl errors when getting
+ interface stats
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+commit edaf13565 modified the stats retrieval for OVS interfaces to
+not fail when one of the fields was unrecognized by the ovs-vsctl
+command, but ovs-vsctl was still returning an error, and libvirt was
+cluttering the logs with these inconsequential error messages.
+
+This patch modifies the GET_STAT macro to add "--if-exists" to the
+ovs-vsctl command, which causes it to return an empty string (and exit
+with success) if the requested statistic isn't in its database, thus
+eliminating the ugly error messages from the log.
+
+Resolves: https://bugzilla.redhat.com/1683175
+
+Signed-off-by: Laine Stump <laine@laine.org>
+(cherry picked from commit 3f7cba3f5ea1731b9028b89b671cbd7e7d5e0421)
+
+Prerequisite of: https://bugzilla.redhat.com/show_bug.cgi?id=1721434
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Message-Id: <e0309b32467a30a8a9be8371ef8cbba1713d662c.1564493409.git.mprivozn@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/virnetdevopenvswitch.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/src/util/virnetdevopenvswitch.c b/src/util/virnetdevopenvswitch.c
+index 2f5c7ac789..cb403aaf2e 100644
+--- a/src/util/virnetdevopenvswitch.c
++++ b/src/util/virnetdevopenvswitch.c
+@@ -342,10 +342,10 @@ virNetDevOpenvswitchInterfaceStats(const char *ifname,
+         virCommandFree(cmd); \
+         cmd = virCommandNew(OVSVSCTL); \
+         virNetDevOpenvswitchAddTimeout(cmd); \
+-        virCommandAddArgList(cmd, "get", "Interface", ifname, \
+-                             "statistics:" name, NULL); \
++        virCommandAddArgList(cmd, "--if-exists", "get", "Interface", \
++                             ifname, "statistics:" name, NULL); \
+         virCommandSetOutputBuffer(cmd, &output); \
+-        if (virCommandRun(cmd, NULL) < 0) { \
++        if (virCommandRun(cmd, NULL) < 0 || !output || !*output || *output == '\n') { \
+             stats->member = -1; \
+         } else { \
+             if (virStrToLong_ll(output, &tmp, 10, &stats->member) < 0 || \
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-util-vircgroup-improve-controller-detection.patch b/SOURCES/libvirt-util-vircgroup-improve-controller-detection.patch
new file mode 100644
index 0000000..ad2ca4c
--- /dev/null
+++ b/SOURCES/libvirt-util-vircgroup-improve-controller-detection.patch
@@ -0,0 +1,117 @@
+From 8c784cd15bbac88334271f95d14a9770c1b2d864 Mon Sep 17 00:00:00 2001
+Message-Id: <8c784cd15bbac88334271f95d14a9770c1b2d864@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:08:17 +0200
+Subject: [PATCH] util: vircgroup: improve controller detection
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This affects only cgroups v2 where enabled controllers are not based on
+available mount points but on the list provided in cgroup.controllers
+file.  However, moving it will fill in placement as well, so it needs
+to be freed together with mount point if we don't need that controller.
+
+Before this patch we were assuming that all controllers available in
+root cgroup where available in all other sub-cgroups which was wrong.
+
+In order to fix it we need to move the cgroup controllers detection
+after cgroup placement was prepared in order to build correct path for
+cgroup.controllers file.
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Reviewed-by: Peter Krempa <pkrempa@redhat.com>
+(cherry picked from commit d3007c844d8aa0caa0328ab18275be375f597704)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <cec99e4c53912c3ee6f45012fc4fd760f6e8445b.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c   | 32 ++++++++++++++++----------------
+ src/util/vircgroupv1.c |  1 +
+ src/util/vircgroupv2.c |  5 +++--
+ 3 files changed, 20 insertions(+), 18 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index 4f71a1d197..ff2a0b75b5 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -386,22 +386,6 @@ virCgroupDetect(virCgroupPtr group,
+             return -1;
+     }
+ 
+-    for (i = 0; i < VIR_CGROUP_BACKEND_TYPE_LAST; i++) {
+-        if (group->backends[i]) {
+-            int rc = group->backends[i]->detectControllers(group, controllers, parent);
+-            if (rc < 0)
+-                return -1;
+-            controllersAvailable |= rc;
+-        }
+-    }
+-
+-    /* Check that at least 1 controller is available */
+-    if (controllersAvailable == 0) {
+-        virReportSystemError(ENXIO, "%s",
+-                             _("At least one cgroup controller is required"));
+-        return -1;
+-    }
+-
+     /* In some cases we can copy part of the placement info
+      * based on the parent cgroup...
+      */
+@@ -426,6 +410,22 @@ virCgroupDetect(virCgroupPtr group,
+         }
+     }
+ 
++    for (i = 0; i < VIR_CGROUP_BACKEND_TYPE_LAST; i++) {
++        if (group->backends[i]) {
++            int rc = group->backends[i]->detectControllers(group, controllers, parent);
++            if (rc < 0)
++                return -1;
++            controllersAvailable |= rc;
++        }
++    }
++
++    /* Check that at least 1 controller is available */
++    if (controllersAvailable == 0) {
++        virReportSystemError(ENXIO, "%s",
++                             _("At least one cgroup controller is required"));
++        return -1;
++    }
++
+     return 0;
+ }
+ 
+diff --git a/src/util/vircgroupv1.c b/src/util/vircgroupv1.c
+index 784a963b79..5b218c7f78 100644
+--- a/src/util/vircgroupv1.c
++++ b/src/util/vircgroupv1.c
+@@ -463,6 +463,7 @@ virCgroupV1DetectControllers(virCgroupPtr group,
+                     }
+                 }
+                 VIR_FREE(group->legacy[i].mountPoint);
++                VIR_FREE(group->legacy[i].placement);
+             }
+         }
+     } else {
+diff --git a/src/util/vircgroupv2.c b/src/util/vircgroupv2.c
+index 60598712c8..10f8a9bbdf 100644
+--- a/src/util/vircgroupv2.c
++++ b/src/util/vircgroupv2.c
+@@ -249,8 +249,9 @@ virCgroupV2ParseControllersFile(virCgroupPtr group)
+     char **contList = NULL;
+     char **tmp;
+ 
+-    if (virAsprintf(&contFile, "%s/cgroup.controllers",
+-                    group->unified.mountPoint) < 0)
++    if (virAsprintf(&contFile, "%s%s/cgroup.controllers",
++                    group->unified.mountPoint,
++                    NULLSTR_EMPTY(group->unified.placement)) < 0)
+         return -1;
+ 
+     rc = virFileReadAll(contFile, 1024 * 1024, &contStr);
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-util-vircgroup-introduce-virCgroup-Get-Set-ValueRaw.patch b/SOURCES/libvirt-util-vircgroup-introduce-virCgroup-Get-Set-ValueRaw.patch
new file mode 100644
index 0000000..de8b405
--- /dev/null
+++ b/SOURCES/libvirt-util-vircgroup-introduce-virCgroup-Get-Set-ValueRaw.patch
@@ -0,0 +1,161 @@
+From 7ff748b22516848e8432d56ffa25a20452569648 Mon Sep 17 00:00:00 2001
+Message-Id: <7ff748b22516848e8432d56ffa25a20452569648@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Tue, 2 Jul 2019 15:13:24 +0200
+Subject: [PATCH] util: vircgroup: introduce virCgroup(Get|Set)ValueRaw
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+If we need to get a path of specific file and we need to check its
+existence before we use it then we can reuse that path to get/set
+values instead of calling the existing get/set value functions which
+would be building the path again.
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit 3f741f9ace878e8aa9f537992b877a1e059d53a9)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1658890
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <176473826dad107b8880a33355b59dcefcb75e63.1562073117.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c     | 74 +++++++++++++++++++++++++---------------
+ src/util/vircgrouppriv.h |  6 ++++
+ 2 files changed, 52 insertions(+), 28 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index 3c99934b25..769e23a523 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -460,28 +460,22 @@ virCgroupGetBlockDevString(const char *path)
+ 
+ 
+ int
+-virCgroupSetValueStr(virCgroupPtr group,
+-                     int controller,
+-                     const char *key,
++virCgroupSetValueRaw(const char *path,
+                      const char *value)
+ {
+-    VIR_AUTOFREE(char *) keypath = NULL;
+-    char *tmp = NULL;
++    char *tmp;
+ 
+-    if (virCgroupPathOfController(group, controller, key, &keypath) < 0)
+-        return -1;
+-
+-    VIR_DEBUG("Set value '%s' to '%s'", keypath, value);
+-    if (virFileWriteStr(keypath, value, 0) < 0) {
++    VIR_DEBUG("Set value '%s' to '%s'", path, value);
++    if (virFileWriteStr(path, value, 0) < 0) {
+         if (errno == EINVAL &&
+-            (tmp = strrchr(keypath, '/'))) {
++            (tmp = strrchr(path, '/'))) {
+             virReportSystemError(errno,
+                                  _("Invalid value '%s' for '%s'"),
+                                  value, tmp + 1);
+             return -1;
+         }
+         virReportSystemError(errno,
+-                             _("Unable to write to '%s'"), keypath);
++                             _("Unable to write to '%s'"), path);
+         return -1;
+     }
+ 
+@@ -489,6 +483,45 @@ virCgroupSetValueStr(virCgroupPtr group,
+ }
+ 
+ 
++int
++virCgroupGetValueRaw(const char *path,
++                     char **value)
++{
++    int rc;
++
++    *value = NULL;
++
++    VIR_DEBUG("Get value %s", path);
++
++    if ((rc = virFileReadAll(path, 1024*1024, value)) < 0) {
++        virReportSystemError(errno,
++                             _("Unable to read from '%s'"), path);
++        return -1;
++    }
++
++    /* Terminated with '\n' has sometimes harmful effects to the caller */
++    if (rc > 0 && (*value)[rc - 1] == '\n')
++        (*value)[rc - 1] = '\0';
++
++    return 0;
++}
++
++
++int
++virCgroupSetValueStr(virCgroupPtr group,
++                     int controller,
++                     const char *key,
++                     const char *value)
++{
++    VIR_AUTOFREE(char *) keypath = NULL;
++
++    if (virCgroupPathOfController(group, controller, key, &keypath) < 0)
++        return -1;
++
++    return virCgroupSetValueRaw(keypath, value);
++}
++
++
+ int
+ virCgroupGetValueStr(virCgroupPtr group,
+                      int controller,
+@@ -496,26 +529,11 @@ virCgroupGetValueStr(virCgroupPtr group,
+                      char **value)
+ {
+     VIR_AUTOFREE(char *) keypath = NULL;
+-    int rc;
+-
+-    *value = NULL;
+ 
+     if (virCgroupPathOfController(group, controller, key, &keypath) < 0)
+         return -1;
+ 
+-    VIR_DEBUG("Get value %s", keypath);
+-
+-    if ((rc = virFileReadAll(keypath, 1024*1024, value)) < 0) {
+-        virReportSystemError(errno,
+-                             _("Unable to read from '%s'"), keypath);
+-        return -1;
+-    }
+-
+-    /* Terminated with '\n' has sometimes harmful effects to the caller */
+-    if (rc > 0 && (*value)[rc - 1] == '\n')
+-        (*value)[rc - 1] = '\0';
+-
+-    return 0;
++    return virCgroupGetValueRaw(keypath, value);
+ }
+ 
+ 
+diff --git a/src/util/vircgrouppriv.h b/src/util/vircgrouppriv.h
+index 6067f5cdc8..bdb3d493b1 100644
+--- a/src/util/vircgrouppriv.h
++++ b/src/util/vircgrouppriv.h
+@@ -62,6 +62,12 @@ struct _virCgroup {
+     virCgroupV2Controller unified;
+ };
+ 
++int virCgroupSetValueRaw(const char *path,
++                         const char *value);
++
++int virCgroupGetValueRaw(const char *path,
++                         char **value);
++
+ int virCgroupSetValueStr(virCgroupPtr group,
+                          int controller,
+                          const char *key,
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-util-vircgroup-move-virCgroupGetValueStr-out-of-virCgroupGetValueForBlkDev.patch b/SOURCES/libvirt-util-vircgroup-move-virCgroupGetValueStr-out-of-virCgroupGetValueForBlkDev.patch
new file mode 100644
index 0000000..6484836
--- /dev/null
+++ b/SOURCES/libvirt-util-vircgroup-move-virCgroupGetValueStr-out-of-virCgroupGetValueForBlkDev.patch
@@ -0,0 +1,323 @@
+From 10bd6c74aa383403fae5ef7f4aec98d28246d972 Mon Sep 17 00:00:00 2001
+Message-Id: <10bd6c74aa383403fae5ef7f4aec98d28246d972@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Tue, 2 Jul 2019 15:13:25 +0200
+Subject: [PATCH] util: vircgroup: move virCgroupGetValueStr out of
+ virCgroupGetValueForBlkDev
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+If we need to get a path of specific file and we need to check its
+existence before we use it then we can reuse that path to get value
+for specific device.  This way we will not build the path again in
+virCgroupGetValueForBlkDev.
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit c23829f18a9b104466af88eb909a3fd9660b9cbe)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1658890
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <72fe6534d0e19e271bac2aeb35bac028e67cfac2.1562073117.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c     |  8 +----
+ src/util/vircgrouppriv.h |  6 ++--
+ src/util/vircgroupv1.c   | 70 ++++++++++++++++++++++++++--------------
+ src/util/vircgroupv2.c   | 65 +++++++++++++++++++++++--------------
+ 4 files changed, 88 insertions(+), 61 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index 769e23a523..37f6def08d 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -538,20 +538,14 @@ virCgroupGetValueStr(virCgroupPtr group,
+ 
+ 
+ int
+-virCgroupGetValueForBlkDev(virCgroupPtr group,
+-                           int controller,
+-                           const char *key,
++virCgroupGetValueForBlkDev(const char *str,
+                            const char *path,
+                            char **value)
+ {
+     VIR_AUTOFREE(char *) prefix = NULL;
+-    VIR_AUTOFREE(char *) str = NULL;
+     char **lines = NULL;
+     int ret = -1;
+ 
+-    if (virCgroupGetValueStr(group, controller, key, &str) < 0)
+-        goto error;
+-
+     if (!(prefix = virCgroupGetBlockDevString(path)))
+         goto error;
+ 
+diff --git a/src/util/vircgrouppriv.h b/src/util/vircgrouppriv.h
+index bdb3d493b1..aec38e2ac5 100644
+--- a/src/util/vircgrouppriv.h
++++ b/src/util/vircgrouppriv.h
+@@ -102,10 +102,8 @@ int virCgroupPartitionEscape(char **path);
+ 
+ char *virCgroupGetBlockDevString(const char *path);
+ 
+-int virCgroupGetValueForBlkDev(virCgroupPtr group,
+-                               int controller,
+-                               const char *key,
+-                               const char *path,
++int virCgroupGetValueForBlkDev(const char *str,
++                               const char *devPath,
+                                char **value);
+ 
+ int virCgroupNew(pid_t pid,
+diff --git a/src/util/vircgroupv1.c b/src/util/vircgroupv1.c
+index 58bd20d636..e51db6ee1f 100644
+--- a/src/util/vircgroupv1.c
++++ b/src/util/vircgroupv1.c
+@@ -1181,12 +1181,16 @@ virCgroupV1GetBlkioDeviceWeight(virCgroupPtr group,
+                                 unsigned int *weight)
+ {
+     VIR_AUTOFREE(char *) str = NULL;
++    VIR_AUTOFREE(char *) value = NULL;
+ 
+-    if (virCgroupGetValueForBlkDev(group,
+-                                   VIR_CGROUP_CONTROLLER_BLKIO,
+-                                   "blkio.weight_device",
+-                                   path,
+-                                   &str) < 0)
++    if (virCgroupGetValueStr(group,
++                             VIR_CGROUP_CONTROLLER_BLKIO,
++                             "blkio.weight_device",
++                             &value) < 0) {
++        return -1;
++    }
++
++    if (virCgroupGetValueForBlkDev(value, path, &str) < 0)
+         return -1;
+ 
+     if (!str) {
+@@ -1229,12 +1233,16 @@ virCgroupV1GetBlkioDeviceReadIops(virCgroupPtr group,
+                                   unsigned int *riops)
+ {
+     VIR_AUTOFREE(char *) str = NULL;
++    VIR_AUTOFREE(char *) value = NULL;
+ 
+-    if (virCgroupGetValueForBlkDev(group,
+-                                   VIR_CGROUP_CONTROLLER_BLKIO,
+-                                   "blkio.throttle.read_iops_device",
+-                                   path,
+-                                   &str) < 0)
++    if (virCgroupGetValueStr(group,
++                             VIR_CGROUP_CONTROLLER_BLKIO,
++                             "blkio.throttle.read_iops_device",
++                             &value) < 0) {
++        return -1;
++    }
++
++    if (virCgroupGetValueForBlkDev(value, path, &str) < 0)
+         return -1;
+ 
+     if (!str) {
+@@ -1277,12 +1285,16 @@ virCgroupV1GetBlkioDeviceWriteIops(virCgroupPtr group,
+                                    unsigned int *wiops)
+ {
+     VIR_AUTOFREE(char *) str = NULL;
++    VIR_AUTOFREE(char *) value = NULL;
+ 
+-    if (virCgroupGetValueForBlkDev(group,
+-                                   VIR_CGROUP_CONTROLLER_BLKIO,
+-                                   "blkio.throttle.write_iops_device",
+-                                   path,
+-                                   &str) < 0)
++    if (virCgroupGetValueStr(group,
++                             VIR_CGROUP_CONTROLLER_BLKIO,
++                             "blkio.throttle.write_iops_device",
++                             &value) < 0) {
++        return -1;
++    }
++
++    if (virCgroupGetValueForBlkDev(value, path, &str) < 0)
+         return -1;
+ 
+     if (!str) {
+@@ -1325,12 +1337,16 @@ virCgroupV1GetBlkioDeviceReadBps(virCgroupPtr group,
+                                  unsigned long long *rbps)
+ {
+     VIR_AUTOFREE(char *) str = NULL;
++    VIR_AUTOFREE(char *) value = NULL;
+ 
+-    if (virCgroupGetValueForBlkDev(group,
+-                                   VIR_CGROUP_CONTROLLER_BLKIO,
+-                                   "blkio.throttle.read_bps_device",
+-                                   path,
+-                                   &str) < 0)
++    if (virCgroupGetValueStr(group,
++                             VIR_CGROUP_CONTROLLER_BLKIO,
++                             "blkio.throttle.read_bps_device",
++                             &value) < 0) {
++        return -1;
++    }
++
++    if (virCgroupGetValueForBlkDev(value, path, &str) < 0)
+         return -1;
+ 
+     if (!str) {
+@@ -1373,12 +1389,16 @@ virCgroupV1GetBlkioDeviceWriteBps(virCgroupPtr group,
+                                   unsigned long long *wbps)
+ {
+     VIR_AUTOFREE(char *) str = NULL;
++    VIR_AUTOFREE(char *) value = NULL;
+ 
+-    if (virCgroupGetValueForBlkDev(group,
+-                                   VIR_CGROUP_CONTROLLER_BLKIO,
+-                                   "blkio.throttle.write_bps_device",
+-                                   path,
+-                                   &str) < 0)
++    if (virCgroupGetValueStr(group,
++                             VIR_CGROUP_CONTROLLER_BLKIO,
++                             "blkio.throttle.write_bps_device",
++                             &value) < 0) {
++        return -1;
++    }
++
++    if (virCgroupGetValueForBlkDev(value, path, &str) < 0)
+         return -1;
+ 
+     if (!str) {
+diff --git a/src/util/vircgroupv2.c b/src/util/vircgroupv2.c
+index 749efa199b..e9bb331dd4 100644
+--- a/src/util/vircgroupv2.c
++++ b/src/util/vircgroupv2.c
+@@ -787,15 +787,18 @@ virCgroupV2GetBlkioDeviceWeight(virCgroupPtr group,
+                                 unsigned int *weight)
+ {
+     VIR_AUTOFREE(char *) str = NULL;
++    VIR_AUTOFREE(char *) value = NULL;
+ 
+-    if (virCgroupGetValueForBlkDev(group,
+-                                   VIR_CGROUP_CONTROLLER_BLKIO,
+-                                   "io.weight",
+-                                   path,
+-                                   &str) < 0) {
++    if (virCgroupGetValueStr(group,
++                             VIR_CGROUP_CONTROLLER_BLKIO,
++                             "io.weight",
++                             &value) < 0) {
+         return -1;
+     }
+ 
++    if (virCgroupGetValueForBlkDev(value, path, &str) < 0)
++        return -1;
++
+     if (!str) {
+         *weight = 0;
+     } else if (virStrToLong_ui(str, NULL, 10, weight) < 0) {
+@@ -841,17 +844,20 @@ virCgroupV2GetBlkioDeviceReadIops(virCgroupPtr group,
+                                   unsigned int *riops)
+ {
+     VIR_AUTOFREE(char *) str = NULL;
++    VIR_AUTOFREE(char *) value = NULL;
+     const char *name = "riops=";
+     char *tmp;
+ 
+-    if (virCgroupGetValueForBlkDev(group,
+-                                   VIR_CGROUP_CONTROLLER_BLKIO,
+-                                   "io.max",
+-                                   path,
+-                                   &str) < 0) {
++    if (virCgroupGetValueStr(group,
++                             VIR_CGROUP_CONTROLLER_BLKIO,
++                             "io.max",
++                             &value) < 0) {
+         return -1;
+     }
+ 
++    if (virCgroupGetValueForBlkDev(value, path, &str) < 0)
++        return -1;
++
+     if (!str) {
+         *riops = 0;
+     } else {
+@@ -909,17 +915,20 @@ virCgroupV2GetBlkioDeviceWriteIops(virCgroupPtr group,
+                                    unsigned int *wiops)
+ {
+     VIR_AUTOFREE(char *) str = NULL;
++    VIR_AUTOFREE(char *) value = NULL;
+     const char *name = "wiops=";
+     char *tmp;
+ 
+-    if (virCgroupGetValueForBlkDev(group,
+-                                   VIR_CGROUP_CONTROLLER_BLKIO,
+-                                   "io.max",
+-                                   path,
+-                                   &str) < 0) {
++    if (virCgroupGetValueStr(group,
++                             VIR_CGROUP_CONTROLLER_BLKIO,
++                             "io.max",
++                             &value) < 0) {
+         return -1;
+     }
+ 
++    if (virCgroupGetValueForBlkDev(value, path, &str) < 0)
++        return -1;
++
+     if (!str) {
+         *wiops = 0;
+     } else {
+@@ -977,17 +986,20 @@ virCgroupV2GetBlkioDeviceReadBps(virCgroupPtr group,
+                                  unsigned long long *rbps)
+ {
+     VIR_AUTOFREE(char *) str = NULL;
++    VIR_AUTOFREE(char *) value = NULL;
+     const char *name = "rbps=";
+     char *tmp;
+ 
+-    if (virCgroupGetValueForBlkDev(group,
+-                                   VIR_CGROUP_CONTROLLER_BLKIO,
+-                                   "io.max",
+-                                   path,
+-                                   &str) < 0) {
++    if (virCgroupGetValueStr(group,
++                             VIR_CGROUP_CONTROLLER_BLKIO,
++                             "io.max",
++                             &value) < 0) {
+         return -1;
+     }
+ 
++    if (virCgroupGetValueForBlkDev(value, path, &str) < 0)
++        return -1;
++
+     if (!str) {
+         *rbps = 0;
+     } else {
+@@ -1045,17 +1057,20 @@ virCgroupV2GetBlkioDeviceWriteBps(virCgroupPtr group,
+                                   unsigned long long *wbps)
+ {
+     VIR_AUTOFREE(char *) str = NULL;
++    VIR_AUTOFREE(char *) value = NULL;
+     const char *name = "wbps=";
+     char *tmp;
+ 
+-    if (virCgroupGetValueForBlkDev(group,
+-                                   VIR_CGROUP_CONTROLLER_BLKIO,
+-                                   "io.max",
+-                                   path,
+-                                   &str) < 0) {
++    if (virCgroupGetValueStr(group,
++                             VIR_CGROUP_CONTROLLER_BLKIO,
++                             "io.max",
++                             &value) < 0) {
+         return -1;
+     }
+ 
++    if (virCgroupGetValueForBlkDev(value, path, &str) < 0)
++        return -1;
++
+     if (!str) {
+         *wbps = 0;
+     } else {
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-util-vircgroup-pass-parent-cgroup-into-virCgroupDetectControllersCB.patch b/SOURCES/libvirt-util-vircgroup-pass-parent-cgroup-into-virCgroupDetectControllersCB.patch
new file mode 100644
index 0000000..e184088
--- /dev/null
+++ b/SOURCES/libvirt-util-vircgroup-pass-parent-cgroup-into-virCgroupDetectControllersCB.patch
@@ -0,0 +1,105 @@
+From 6403a3028222b103d7ef8ecf89aabe92242667da Mon Sep 17 00:00:00 2001
+Message-Id: <6403a3028222b103d7ef8ecf89aabe92242667da@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:08:15 +0200
+Subject: [PATCH] util: vircgroup: pass parent cgroup into
+ virCgroupDetectControllersCB
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+In cgroups v2 we don't have to detect available controllers every single
+time if we are creating a new cgroup based on parent cgroup.
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit 7bca1c9bdc85247446129f856e27c80a32819e17)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <f31650dee05403189825c50e55daf3456c7de1cc.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c        |  2 +-
+ src/util/vircgroupbackend.h |  3 ++-
+ src/util/vircgroupv1.c      |  3 ++-
+ src/util/vircgroupv2.c      | 17 +++++++++++------
+ 4 files changed, 16 insertions(+), 9 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index 736b5043a8..4f71a1d197 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -388,7 +388,7 @@ virCgroupDetect(virCgroupPtr group,
+ 
+     for (i = 0; i < VIR_CGROUP_BACKEND_TYPE_LAST; i++) {
+         if (group->backends[i]) {
+-            int rc = group->backends[i]->detectControllers(group, controllers);
++            int rc = group->backends[i]->detectControllers(group, controllers, parent);
+             if (rc < 0)
+                 return -1;
+             controllersAvailable |= rc;
+diff --git a/src/util/vircgroupbackend.h b/src/util/vircgroupbackend.h
+index a825dc4be7..05af118ec1 100644
+--- a/src/util/vircgroupbackend.h
++++ b/src/util/vircgroupbackend.h
+@@ -96,7 +96,8 @@ typedef char *
+ 
+ typedef int
+ (*virCgroupDetectControllersCB)(virCgroupPtr group,
+-                                int controllers);
++                                int controllers,
++                                virCgroupPtr parent);
+ 
+ typedef bool
+ (*virCgroupHasControllerCB)(virCgroupPtr cgroup,
+diff --git a/src/util/vircgroupv1.c b/src/util/vircgroupv1.c
+index 7098dc5644..784a963b79 100644
+--- a/src/util/vircgroupv1.c
++++ b/src/util/vircgroupv1.c
+@@ -419,7 +419,8 @@ virCgroupV1StealPlacement(virCgroupPtr group)
+ 
+ static int
+ virCgroupV1DetectControllers(virCgroupPtr group,
+-                             int controllers)
++                             int controllers,
++                             virCgroupPtr parent ATTRIBUTE_UNUSED)
+ {
+     size_t i;
+     size_t j;
+diff --git a/src/util/vircgroupv2.c b/src/util/vircgroupv2.c
+index 04638c4e50..60598712c8 100644
+--- a/src/util/vircgroupv2.c
++++ b/src/util/vircgroupv2.c
+@@ -284,16 +284,21 @@ virCgroupV2ParseControllersFile(virCgroupPtr group)
+ 
+ static int
+ virCgroupV2DetectControllers(virCgroupPtr group,
+-                             int controllers)
++                             int controllers,
++                             virCgroupPtr parent)
+ {
+     size_t i;
+ 
+-    if (virCgroupV2ParseControllersFile(group) < 0)
+-        return -1;
++    if (parent) {
++        group->unified.controllers = parent->unified.controllers;
++    } else {
++        if (virCgroupV2ParseControllersFile(group) < 0)
++            return -1;
+ 
+-    /* In cgroup v2 there is no cpuacct controller, the cpu.stat file always
+-     * exists with usage stats. */
+-    group->unified.controllers |= 1 << VIR_CGROUP_CONTROLLER_CPUACCT;
++        /* In cgroup v2 there is no cpuacct controller, the cpu.stat file always
++         * exists with usage stats. */
++        group->unified.controllers |= 1 << VIR_CGROUP_CONTROLLER_CPUACCT;
++    }
+ 
+     for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++)
+         VIR_DEBUG("Controller '%s' present=%s",
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-util-vircgroupv1-add-support-for-BFQ-blkio-files.patch b/SOURCES/libvirt-util-vircgroupv1-add-support-for-BFQ-blkio-files.patch
new file mode 100644
index 0000000..894ba09
--- /dev/null
+++ b/SOURCES/libvirt-util-vircgroupv1-add-support-for-BFQ-blkio-files.patch
@@ -0,0 +1,202 @@
+From a6c731357b9c74e5cc298f04267312ad3bb635fa Mon Sep 17 00:00:00 2001
+Message-Id: <a6c731357b9c74e5cc298f04267312ad3bb635fa@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Tue, 2 Jul 2019 15:13:26 +0200
+Subject: [PATCH] util: vircgroupv1: add support for BFQ blkio files
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+In kernel 4.12 there was introduced new BFQ scheduler and in kernel
+5.0 the old CFQ scheduler was removed.  This has an implication on
+the cgroups file names.
+
+If the CFQ controller is enabled we use these two files:
+
+    blkio.weight
+    blkio.weight_device
+
+The new BFQ controller expose only one file with different name:
+
+    blkio.bfq.weight
+
+The reason is that BFQ controller doesn't support per-device weight.
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit 035ebe9390a630964f391816f05c9cc7792212ad)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1658890
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <b66aa3f8ec343e90f9ccd2e458707051c65b4d0d.1562073117.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroupv1.c | 114 ++++++++++++++++++++++++++++++++---------
+ 1 file changed, 90 insertions(+), 24 deletions(-)
+
+diff --git a/src/util/vircgroupv1.c b/src/util/vircgroupv1.c
+index e51db6ee1f..a7d6c92e4c 100644
+--- a/src/util/vircgroupv1.c
++++ b/src/util/vircgroupv1.c
+@@ -949,10 +949,33 @@ static int
+ virCgroupV1SetBlkioWeight(virCgroupPtr group,
+                           unsigned int weight)
+ {
+-    return virCgroupSetValueU64(group,
+-                                VIR_CGROUP_CONTROLLER_BLKIO,
+-                                "blkio.weight",
+-                                weight);
++    VIR_AUTOFREE(char *) path = NULL;
++    VIR_AUTOFREE(char *) value = NULL;
++
++    if (virCgroupV1PathOfController(group, VIR_CGROUP_CONTROLLER_BLKIO,
++                                    "blkio.bfq.weight", &path) < 0) {
++        return -1;
++    }
++
++    if (!virFileExists(path)) {
++        VIR_FREE(path);
++
++        if (virCgroupV1PathOfController(group, VIR_CGROUP_CONTROLLER_BLKIO,
++                                        "blkio.weight", &path) < 0) {
++            return -1;
++        }
++    }
++
++    if (!virFileExists(path)) {
++        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
++                       _("blkio device weight is valid only for bfq or cfq scheduler"));
++        return -1;
++    }
++
++    if (virAsprintf(&value, "%u", weight) < 0)
++        return -1;
++
++    return virCgroupSetValueRaw(path, value);
+ }
+ 
+ 
+@@ -960,14 +983,40 @@ static int
+ virCgroupV1GetBlkioWeight(virCgroupPtr group,
+                           unsigned int *weight)
+ {
+-    unsigned long long tmp;
+-    int ret;
+-    ret = virCgroupGetValueU64(group,
+-                               VIR_CGROUP_CONTROLLER_BLKIO,
+-                               "blkio.weight", &tmp);
+-    if (ret == 0)
+-        *weight = tmp;
+-    return ret;
++    VIR_AUTOFREE(char *) path = NULL;
++    VIR_AUTOFREE(char *) value = NULL;
++
++    if (virCgroupV1PathOfController(group, VIR_CGROUP_CONTROLLER_BLKIO,
++                                    "blkio.bfq.weight", &path) < 0) {
++        return -1;
++    }
++
++    if (!virFileExists(path)) {
++        VIR_FREE(path);
++
++        if (virCgroupV1PathOfController(group, VIR_CGROUP_CONTROLLER_BLKIO,
++                                        "blkio.weight", &path) < 0) {
++            return -1;
++        }
++    }
++
++    if (!virFileExists(path)) {
++        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
++                       _("blkio device weight is valid only for bfq or cfq scheduler"));
++        return -1;
++    }
++
++    if (virCgroupGetValueRaw(path, &value) < 0)
++        return -1;
++
++    if (virStrToLong_ui(value, NULL, 10, weight) < 0) {
++        virReportError(VIR_ERR_INTERNAL_ERROR,
++                       _("Unable to parse '%s' as an integer"),
++                       value);
++        return -1;
++    }
++
++    return 0;
+ }
+ 
+ 
+@@ -1156,41 +1205,58 @@ virCgroupV1GetBlkioIoDeviceServiced(virCgroupPtr group,
+ 
+ static int
+ virCgroupV1SetBlkioDeviceWeight(virCgroupPtr group,
+-                                const char *path,
++                                const char *devPath,
+                                 unsigned int weight)
+ {
+     VIR_AUTOFREE(char *) str = NULL;
+     VIR_AUTOFREE(char *) blkstr = NULL;
++    VIR_AUTOFREE(char *) path = NULL;
+ 
+-    if (!(blkstr = virCgroupGetBlockDevString(path)))
++    if (!(blkstr = virCgroupGetBlockDevString(devPath)))
+         return -1;
+ 
+     if (virAsprintf(&str, "%s%d", blkstr, weight) < 0)
+         return -1;
+ 
+-    return virCgroupSetValueStr(group,
+-                                VIR_CGROUP_CONTROLLER_BLKIO,
+-                                "blkio.weight_device",
+-                                str);
++    if (virCgroupV1PathOfController(group, VIR_CGROUP_CONTROLLER_BLKIO,
++                                    "blkio.weight_device", &path) < 0) {
++        return -1;
++    }
++
++    if (!virFileExists(path)) {
++        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
++                       _("blkio device weight is valid only for cfq scheduler"));
++        return -1;
++    }
++
++    return virCgroupSetValueRaw(path, str);
+ }
+ 
+ 
+ static int
+ virCgroupV1GetBlkioDeviceWeight(virCgroupPtr group,
+-                                const char *path,
++                                const char *devPath,
+                                 unsigned int *weight)
+ {
+     VIR_AUTOFREE(char *) str = NULL;
+     VIR_AUTOFREE(char *) value = NULL;
++    VIR_AUTOFREE(char *) path = NULL;
+ 
+-    if (virCgroupGetValueStr(group,
+-                             VIR_CGROUP_CONTROLLER_BLKIO,
+-                             "blkio.weight_device",
+-                             &value) < 0) {
++    if (virCgroupV1PathOfController(group, VIR_CGROUP_CONTROLLER_BLKIO,
++                                    "blkio.weight_device", &path) < 0) {
+         return -1;
+     }
+ 
+-    if (virCgroupGetValueForBlkDev(value, path, &str) < 0)
++    if (!virFileExists(path)) {
++        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
++                       _("blkio device weight is valid only for cfq scheduler"));
++        return -1;
++    }
++
++    if (virCgroupGetValueRaw(path, &value) < 0)
++        return -1;
++
++    if (virCgroupGetValueForBlkDev(value, devPath, &str) < 0)
+         return -1;
+ 
+     if (!str) {
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-util-vircgroupv2-add-support-for-BFQ-files.patch b/SOURCES/libvirt-util-vircgroupv2-add-support-for-BFQ-files.patch
new file mode 100644
index 0000000..9ece80d
--- /dev/null
+++ b/SOURCES/libvirt-util-vircgroupv2-add-support-for-BFQ-files.patch
@@ -0,0 +1,211 @@
+From 785b8c27bef20182789d1715d0b3c1d3fe28a9f9 Mon Sep 17 00:00:00 2001
+Message-Id: <785b8c27bef20182789d1715d0b3c1d3fe28a9f9@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Tue, 2 Jul 2019 15:13:27 +0200
+Subject: [PATCH] util: vircgroupv2: add support for BFQ files
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+In kernel 4.12 there was introduced new BFQ scheduler and in kernel
+5.0 the old CFQ scheduler was removed.  This has an implication on
+the cgroups file names.
+
+If the CFQ controller is enabled we use one file:
+
+    io.weight
+
+The new BFQ controller expose one file with different name:
+
+    io.bfq.weight
+
+Except for different name they have different syntax.
+
+io.weight:
+
+    default $val
+    major:minor $val
+
+io.bfq.weight:
+
+    $val
+
+The difference is that BFQ doesn't support per-device weight.
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit 7e8a1a6e21cee67f6fa5bd2126ec17f96e5857d6)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1658890
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <d41b50b6f3d3ef064b7f3274c762a7c41bf8e1ec.1562073117.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroupv2.c | 101 +++++++++++++++++++++++++++++++----------
+ 1 file changed, 78 insertions(+), 23 deletions(-)
+
+diff --git a/src/util/vircgroupv2.c b/src/util/vircgroupv2.c
+index e9bb331dd4..b4e90ed46d 100644
+--- a/src/util/vircgroupv2.c
++++ b/src/util/vircgroupv2.c
+@@ -591,15 +591,35 @@ static int
+ virCgroupV2SetBlkioWeight(virCgroupPtr group,
+                           unsigned int weight)
+ {
++    VIR_AUTOFREE(char *) path = NULL;
+     VIR_AUTOFREE(char *) value = NULL;
++    const char *format = "%u";
+ 
+-    if (virAsprintf(&value, "default %u", weight) < 0)
++    if (virCgroupV2PathOfController(group, VIR_CGROUP_CONTROLLER_BLKIO,
++                                    "io.bfq.weight", &path) < 0) {
++        return -1;
++    }
++
++    if (!virFileExists(path)) {
++        VIR_FREE(path);
++        format = "default %u";
++
++        if (virCgroupV2PathOfController(group, VIR_CGROUP_CONTROLLER_BLKIO,
++                                        "io.weight", &path) < 0) {
++            return -1;
++        }
++    }
++
++    if (!virFileExists(path)) {
++        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
++                       _("blkio weight is valid only for bfq or cfq scheduler"));
++        return -1;
++    }
++
++    if (virAsprintf(&value, format, weight) < 0)
+         return -1;
+ 
+-    return virCgroupSetValueStr(group,
+-                                VIR_CGROUP_CONTROLLER_BLKIO,
+-                                "io.weight",
+-                                value);
++    return virCgroupSetValueRaw(path, value);
+ }
+ 
+ 
+@@ -607,20 +627,38 @@ static int
+ virCgroupV2GetBlkioWeight(virCgroupPtr group,
+                           unsigned int *weight)
+ {
++    VIR_AUTOFREE(char *) path = NULL;
+     VIR_AUTOFREE(char *) value = NULL;
+     char *tmp;
+ 
+-    if (virCgroupGetValueStr(group, VIR_CGROUP_CONTROLLER_BLKIO,
+-                             "io.weight", &value) < 0) {
++    if (virCgroupV2PathOfController(group, VIR_CGROUP_CONTROLLER_BLKIO,
++                                    "io.bfq.weight", &path) < 0) {
+         return -1;
+     }
+ 
+-    if (!(tmp = strstr(value, "default "))) {
+-        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+-                       _("Cannot find default io weight."));
++    if (!virFileExists(path)) {
++        VIR_FREE(path);
++
++        if (virCgroupV2PathOfController(group, VIR_CGROUP_CONTROLLER_BLKIO,
++                                        "io.weight", &path) < 0) {
++            return -1;
++        }
++    }
++
++    if (!virFileExists(path)) {
++        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
++                       _("blkio weight is valid only for bfq or cfq scheduler"));
+         return -1;
+     }
+-    tmp += strlen("default ");
++
++    if (virCgroupGetValueRaw(path, &value) < 0)
++        return -1;
++
++    if ((tmp = strstr(value, "default "))) {
++        tmp += strlen("default ");
++    } else {
++        tmp = value;
++    }
+ 
+     if (virStrToLong_ui(tmp, NULL, 10, weight) < 0) {
+         virReportError(VIR_ERR_INTERNAL_ERROR,
+@@ -762,41 +800,58 @@ virCgroupV2GetBlkioIoDeviceServiced(virCgroupPtr group,
+ 
+ static int
+ virCgroupV2SetBlkioDeviceWeight(virCgroupPtr group,
+-                                const char *path,
++                                const char *devPath,
+                                 unsigned int weight)
+ {
++    VIR_AUTOFREE(char *) path = NULL;
+     VIR_AUTOFREE(char *) str = NULL;
+     VIR_AUTOFREE(char *) blkstr = NULL;
+ 
+-    if (!(blkstr = virCgroupGetBlockDevString(path)))
++    if (!(blkstr = virCgroupGetBlockDevString(devPath)))
+         return -1;
+ 
+     if (virAsprintf(&str, "%s%d", blkstr, weight) < 0)
+         return -1;
+ 
+-    return virCgroupSetValueStr(group,
+-                                VIR_CGROUP_CONTROLLER_BLKIO,
+-                                "io.weight",
+-                                str);
++    if (virCgroupV2PathOfController(group, VIR_CGROUP_CONTROLLER_BLKIO,
++                                    "io.weight", &path) < 0) {
++        return -1;
++    }
++
++    if (!virFileExists(path)) {
++        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
++                       _("blkio device weight is valid only for cfq scheduler"));
++        return -1;
++    }
++
++    return virCgroupSetValueRaw(path, str);
+ }
+ 
+ 
+ static int
+ virCgroupV2GetBlkioDeviceWeight(virCgroupPtr group,
+-                                const char *path,
++                                const char *devPath,
+                                 unsigned int *weight)
+ {
++    VIR_AUTOFREE(char *) path = NULL;
+     VIR_AUTOFREE(char *) str = NULL;
+     VIR_AUTOFREE(char *) value = NULL;
+ 
+-    if (virCgroupGetValueStr(group,
+-                             VIR_CGROUP_CONTROLLER_BLKIO,
+-                             "io.weight",
+-                             &value) < 0) {
++    if (virCgroupV2PathOfController(group, VIR_CGROUP_CONTROLLER_BLKIO,
++                                    "io.weight", &path) < 0) {
+         return -1;
+     }
+ 
+-    if (virCgroupGetValueForBlkDev(value, path, &str) < 0)
++    if (!virFileExists(path)) {
++        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
++                       _("blkio device weight is valid only for cfq scheduler"));
++        return -1;
++    }
++
++    if (virCgroupGetValueRaw(path, &value) < 0)
++        return -1;
++
++    if (virCgroupGetValueForBlkDev(value, devPath, &str) < 0)
+         return -1;
+ 
+     if (!str) {
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-util-vircgroupv2-don-t-error-out-if-enabling-controller-fails.patch b/SOURCES/libvirt-util-vircgroupv2-don-t-error-out-if-enabling-controller-fails.patch
new file mode 100644
index 0000000..d7545c6
--- /dev/null
+++ b/SOURCES/libvirt-util-vircgroupv2-don-t-error-out-if-enabling-controller-fails.patch
@@ -0,0 +1,64 @@
+From 02b2342b6b5e45e3f41cb145521f53118ba8430f Mon Sep 17 00:00:00 2001
+Message-Id: <02b2342b6b5e45e3f41cb145521f53118ba8430f@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:08:21 +0200
+Subject: [PATCH] util: vircgroupv2: don't error out if enabling controller
+ fails
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Currently CPU controller cannot be enabled if there is any real-time
+task running and is assigned to non-root cgroup which is the case on
+several distributions with graphical environment.
+
+Instead of erroring out treat it as the controller is not available.
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Reviewed-by: Peter Krempa <pkrempa@redhat.com>
+(cherry picked from commit 1d49cdcd116186e079db5668893da17f56141652)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <4a10dec59ca8cf5a2f81acf70d43f48b0a3bfd82.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroupv2.c | 13 ++++++++++++-
+ 1 file changed, 12 insertions(+), 1 deletion(-)
+
+diff --git a/src/util/vircgroupv2.c b/src/util/vircgroupv2.c
+index a67d5cfe04..e1ab1849ba 100644
+--- a/src/util/vircgroupv2.c
++++ b/src/util/vircgroupv2.c
+@@ -437,6 +437,8 @@ virCgroupV2MakeGroup(virCgroupPtr parent ATTRIBUTE_UNUSED,
+         } else {
+             size_t i;
+             for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
++                int rc;
++
+                 if (!virCgroupV2HasController(parent, i))
+                     continue;
+ 
+@@ -444,8 +446,17 @@ virCgroupV2MakeGroup(virCgroupPtr parent ATTRIBUTE_UNUSED,
+                 if (i == VIR_CGROUP_CONTROLLER_CPUACCT)
+                     continue;
+ 
+-                if (virCgroupV2EnableController(parent, i, true) < 0)
++                rc = virCgroupV2EnableController(parent, i, false);
++                if (rc < 0) {
++                    if (rc == -2) {
++                        virResetLastError();
++                        VIR_DEBUG("failed to enable '%s' controller, skipping",
++                                  virCgroupV2ControllerTypeToString(i));
++                        group->unified.controllers &= ~(1 << i);
++                        continue;
++                    }
+                     return -1;
++                }
+             }
+         }
+     }
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-util-vircgroupv2-enable-CPU-controller-only-if-it-s-available.patch b/SOURCES/libvirt-util-vircgroupv2-enable-CPU-controller-only-if-it-s-available.patch
new file mode 100644
index 0000000..e8f69c6
--- /dev/null
+++ b/SOURCES/libvirt-util-vircgroupv2-enable-CPU-controller-only-if-it-s-available.patch
@@ -0,0 +1,44 @@
+From aa699de198c52868d08679176dd8355deb24ef82 Mon Sep 17 00:00:00 2001
+Message-Id: <aa699de198c52868d08679176dd8355deb24ef82@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:08:19 +0200
+Subject: [PATCH] util: vircgroupv2: enable CPU controller only if it's
+ available
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+It might happen that we are not able to enable CPU controller so we
+can enable it for thread sub-cgroups only if it's available in parent
+cgroup.
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit f9d1c08557ddb981a0d889200431185a9c4920e0)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <2a13e05dfbbe52f05541c881964ce92709e5d36a.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroupv2.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/src/util/vircgroupv2.c b/src/util/vircgroupv2.c
+index 04cbadd6a6..98d313bf82 100644
+--- a/src/util/vircgroupv2.c
++++ b/src/util/vircgroupv2.c
+@@ -403,7 +403,8 @@ virCgroupV2MakeGroup(virCgroupPtr parent ATTRIBUTE_UNUSED,
+                 return -1;
+             }
+ 
+-            if (virCgroupV2EnableController(parent,
++            if (virCgroupV2HasController(parent, VIR_CGROUP_CONTROLLER_CPU) &&
++                virCgroupV2EnableController(parent,
+                                             VIR_CGROUP_CONTROLLER_CPU) < 0) {
+                 return -1;
+             }
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-util-vircgroupv2-mark-only-requested-controllers-as-available.patch b/SOURCES/libvirt-util-vircgroupv2-mark-only-requested-controllers-as-available.patch
new file mode 100644
index 0000000..e055eca
--- /dev/null
+++ b/SOURCES/libvirt-util-vircgroupv2-mark-only-requested-controllers-as-available.patch
@@ -0,0 +1,53 @@
+From 54d26cd3d6839c67970d19559aaa13294c55f9a0 Mon Sep 17 00:00:00 2001
+Message-Id: <54d26cd3d6839c67970d19559aaa13294c55f9a0@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:08:22 +0200
+Subject: [PATCH] util: vircgroupv2: mark only requested controllers as
+ available
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+When detecting available controllers on host we can be limited by list
+of controllers from qemu.conf file.
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Reviewed-by: Peter Krempa <pkrempa@redhat.com>
+(cherry picked from commit 05807e5d42f23832ab7dab17fb7e51b48b0a7c7b)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <40e05984144af026205a123c5b0f9cb841dcec67.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroupv2.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/src/util/vircgroupv2.c b/src/util/vircgroupv2.c
+index e1ab1849ba..bdeab397a3 100644
+--- a/src/util/vircgroupv2.c
++++ b/src/util/vircgroupv2.c
+@@ -301,15 +301,15 @@ virCgroupV2DetectControllers(virCgroupPtr group,
+         group->unified.controllers |= 1 << VIR_CGROUP_CONTROLLER_CPUACCT;
+     }
+ 
++    if (controllers >= 0)
++        group->unified.controllers &= controllers;
++
+     for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++)
+         VIR_DEBUG("Controller '%s' present=%s",
+                   virCgroupV2ControllerTypeToString(i),
+                   (group->unified.controllers & 1 << i) ? "yes" : "no");
+ 
+-    if (controllers >= 0)
+-        return controllers & group->unified.controllers;
+-    else
+-        return group->unified.controllers;
++    return group->unified.controllers;
+ }
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-util-vircgroupv2-separate-return-values-of-virCgroupV2EnableController.patch b/SOURCES/libvirt-util-vircgroupv2-separate-return-values-of-virCgroupV2EnableController.patch
new file mode 100644
index 0000000..fad981f
--- /dev/null
+++ b/SOURCES/libvirt-util-vircgroupv2-separate-return-values-of-virCgroupV2EnableController.patch
@@ -0,0 +1,104 @@
+From 3980cde103a2804abc62a2eb3bcea39cccf20286 Mon Sep 17 00:00:00 2001
+Message-Id: <3980cde103a2804abc62a2eb3bcea39cccf20286@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:08:20 +0200
+Subject: [PATCH] util: vircgroupv2: separate return values of
+ virCgroupV2EnableController
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+In order to skip controllers that we are not able to activate we need
+to return different return value so the caller can decide what to do.
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Reviewed-by: Peter Krempa <pkrempa@redhat.com>
+(cherry picked from commit 29a94a3fefeea0fb29b0b9f485c83c49b5bdae71)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <d0356666404a39fd0d6499490f60df17f3ee90b5.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroupv2.c | 32 ++++++++++++++++++++++++++------
+ 1 file changed, 26 insertions(+), 6 deletions(-)
+
+diff --git a/src/util/vircgroupv2.c b/src/util/vircgroupv2.c
+index 98d313bf82..a67d5cfe04 100644
+--- a/src/util/vircgroupv2.c
++++ b/src/util/vircgroupv2.c
+@@ -352,22 +352,40 @@ virCgroupV2PathOfController(virCgroupPtr group,
+ }
+ 
+ 
++/**
++ * virCgroupV2EnableController:
++ *
++ * Returns: -1 on fatal error
++ *          -2 if we failed to write into cgroup.subtree_control
++ *          0 on success
++ */
+ static int
+ virCgroupV2EnableController(virCgroupPtr parent,
+-                            int controller)
++                            int controller,
++                            bool report)
+ {
+     VIR_AUTOFREE(char *) val = NULL;
++    VIR_AUTOFREE(char *) path = NULL;
+ 
+     if (virAsprintf(&val, "+%s",
+                     virCgroupV2ControllerTypeToString(controller)) < 0) {
+         return -1;
+     }
+ 
+-    if (virCgroupSetValueStr(parent, controller,
+-                             "cgroup.subtree_control", val) < 0) {
++    if (virCgroupPathOfController(parent, controller,
++                                  "cgroup.subtree_control", &path) < 0) {
+         return -1;
+     }
+ 
++    if (virFileWriteStr(path, val, 0) < 0) {
++        if (report) {
++            virReportSystemError(errno,
++                                 _("Failed to enable controller '%s' for '%s'"),
++                                 val, path);
++        }
++        return -2;
++    }
++
+     return 0;
+ }
+ 
+@@ -405,13 +423,15 @@ virCgroupV2MakeGroup(virCgroupPtr parent ATTRIBUTE_UNUSED,
+ 
+             if (virCgroupV2HasController(parent, VIR_CGROUP_CONTROLLER_CPU) &&
+                 virCgroupV2EnableController(parent,
+-                                            VIR_CGROUP_CONTROLLER_CPU) < 0) {
++                                            VIR_CGROUP_CONTROLLER_CPU,
++                                            true) < 0) {
+                 return -1;
+             }
+ 
+             if (virCgroupV2HasController(parent, VIR_CGROUP_CONTROLLER_CPUSET) &&
+                 virCgroupV2EnableController(parent,
+-                                            VIR_CGROUP_CONTROLLER_CPUSET) < 0) {
++                                            VIR_CGROUP_CONTROLLER_CPUSET,
++                                            true) < 0) {
+                 return -1;
+             }
+         } else {
+@@ -424,7 +444,7 @@ virCgroupV2MakeGroup(virCgroupPtr parent ATTRIBUTE_UNUSED,
+                 if (i == VIR_CGROUP_CONTROLLER_CPUACCT)
+                     continue;
+ 
+-                if (virCgroupV2EnableController(parent, i) < 0)
++                if (virCgroupV2EnableController(parent, i, true) < 0)
+                     return -1;
+             }
+         }
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-util-vircgroupv2-stop-enabling-missing-controllers-with-systemd.patch b/SOURCES/libvirt-util-vircgroupv2-stop-enabling-missing-controllers-with-systemd.patch
new file mode 100644
index 0000000..f724143
--- /dev/null
+++ b/SOURCES/libvirt-util-vircgroupv2-stop-enabling-missing-controllers-with-systemd.patch
@@ -0,0 +1,80 @@
+From c06173bae3630cd1f953e69c4dd8df98904892a5 Mon Sep 17 00:00:00 2001
+Message-Id: <c06173bae3630cd1f953e69c4dd8df98904892a5@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:08:24 +0200
+Subject: [PATCH] util: vircgroupv2: stop enabling missing controllers with
+ systemd
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Because of a systemd delegation policy [1] we should not write to any
+cgroups files owned by systemd which in case of cgroups v2 includes
+'cgroups.subtree_control'.
+
+systemd will enable controllers automatically for us to have them
+available for VM cgroups.
+
+[1] <https://github.com/systemd/systemd/blob/master/docs/CGROUP_DELEGATION.md>
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit 62dd4d25a2bc5ee33ed22728dc79a5da99906748)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <273d20b3ced7f8b3ea0cc761cff25601f03e318f.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c        | 2 +-
+ src/util/vircgroupbackend.h | 3 +++
+ src/util/vircgroupv2.c      | 5 +++++
+ 3 files changed, 9 insertions(+), 1 deletion(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index a7fb595bce..3c99934b25 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -1075,7 +1075,7 @@ virCgroupEnableMissingControllers(char *path,
+                          &tmp) < 0)
+             goto cleanup;
+ 
+-        if (virCgroupMakeGroup(parent, tmp, true, VIR_CGROUP_NONE) < 0) {
++        if (virCgroupMakeGroup(parent, tmp, true, VIR_CGROUP_SYSTEMD) < 0) {
+             virCgroupFree(&tmp);
+             goto cleanup;
+         }
+diff --git a/src/util/vircgroupbackend.h b/src/util/vircgroupbackend.h
+index a825dc4be7..2b5be21a76 100644
+--- a/src/util/vircgroupbackend.h
++++ b/src/util/vircgroupbackend.h
+@@ -35,6 +35,9 @@ typedef enum {
+                                        * attaching tasks
+                                        */
+     VIR_CGROUP_THREAD = 1 << 1, /* cgroup v2 handles threads differently */
++    VIR_CGROUP_SYSTEMD = 1 << 2, /* with systemd and cgroups v2 we cannot
++                                  * manually enable controllers that systemd
++                                  * doesn't know how to delegate */
+ } virCgroupBackendFlags;
+ 
+ typedef enum {
+diff --git a/src/util/vircgroupv2.c b/src/util/vircgroupv2.c
+index b0ed889cc8..749efa199b 100644
+--- a/src/util/vircgroupv2.c
++++ b/src/util/vircgroupv2.c
+@@ -394,6 +394,11 @@ virCgroupV2MakeGroup(virCgroupPtr parent ATTRIBUTE_UNUSED,
+     VIR_AUTOFREE(char *) path = NULL;
+     int controller;
+ 
++    if (flags & VIR_CGROUP_SYSTEMD) {
++        VIR_DEBUG("Running with systemd so we should not create cgroups ourselves.");
++        return 0;
++    }
++
+     VIR_DEBUG("Make group %s", group->path);
+ 
+     controller = virCgroupV2GetAnyController(group);
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-util-vircgroupv2-use-any-controller-to-create-thread-directory.patch b/SOURCES/libvirt-util-vircgroupv2-use-any-controller-to-create-thread-directory.patch
new file mode 100644
index 0000000..40b3ee5
--- /dev/null
+++ b/SOURCES/libvirt-util-vircgroupv2-use-any-controller-to-create-thread-directory.patch
@@ -0,0 +1,42 @@
+From 281c86a0556bd04ad2b3d7264f36c109c646a692 Mon Sep 17 00:00:00 2001
+Message-Id: <281c86a0556bd04ad2b3d7264f36c109c646a692@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:08:18 +0200
+Subject: [PATCH] util: vircgroupv2: use any controller to create thread
+ directory
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The assumption that CPU controller would be always enabled is wrong, we
+should use any available controller to create a new sub-cgroup.
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit 535bdf83c0b0372e725650c56b4996ff83406254)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <c66a8d07101971e7842f3a6fa8a84373a0c9e90f.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroupv2.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/util/vircgroupv2.c b/src/util/vircgroupv2.c
+index 10f8a9bbdf..04cbadd6a6 100644
+--- a/src/util/vircgroupv2.c
++++ b/src/util/vircgroupv2.c
+@@ -398,7 +398,7 @@ virCgroupV2MakeGroup(virCgroupPtr parent ATTRIBUTE_UNUSED,
+ 
+     if (create) {
+         if (flags & VIR_CGROUP_THREAD) {
+-            if (virCgroupSetValueStr(group, VIR_CGROUP_CONTROLLER_CPU,
++            if (virCgroupSetValueStr(group, controller,
+                                      "cgroup.type", "threaded") < 0) {
+                 return -1;
+             }
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-util-virnetdevopenvswitch-Drop-an-unused-variable-ovs_timeout.patch b/SOURCES/libvirt-util-virnetdevopenvswitch-Drop-an-unused-variable-ovs_timeout.patch
new file mode 100644
index 0000000..f5032da
--- /dev/null
+++ b/SOURCES/libvirt-util-virnetdevopenvswitch-Drop-an-unused-variable-ovs_timeout.patch
@@ -0,0 +1,42 @@
+From bf73e16686f339b35637aa6fd401d0ed8d9e191a Mon Sep 17 00:00:00 2001
+Message-Id: <bf73e16686f339b35637aa6fd401d0ed8d9e191a@dist-git>
+From: Erik Skultety <eskultet@redhat.com>
+Date: Tue, 30 Jul 2019 15:30:48 +0200
+Subject: [PATCH] util: virnetdevopenvswitch: Drop an unused variable
+ @ovs_timeout
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Technically, it was never used ever since commit @f4d06ca8fd9 introduced
+it, but the fact that we called VIR_FREE on it was enough for Clang to
+never complain about it.
+
+Signed-off-by: Erik Skultety <eskultet@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit cc4d44ab31ffb2500cf52081e87b137385ec76e6)
+
+Prerequisite of: https://bugzilla.redhat.com/show_bug.cgi?id=1721434
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Message-Id: <a43450d34db47937012358004f45a6a17821883c.1564493409.git.mprivozn@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/virnetdevopenvswitch.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/src/util/virnetdevopenvswitch.c b/src/util/virnetdevopenvswitch.c
+index 36c587efdb..0dcd49d40f 100644
+--- a/src/util/virnetdevopenvswitch.c
++++ b/src/util/virnetdevopenvswitch.c
+@@ -420,7 +420,6 @@ virNetDevOpenvswitchGetVhostuserIfname(const char *path,
+     size_t ntokens = 0;
+     int status;
+     int ret = -1;
+-    VIR_AUTOFREE(char *) ovs_timeout = NULL;
+ 
+     /* Openvswitch vhostuser path are hardcoded to
+      * /<runstatedir>/openvswitch/<ifname>
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-virCommand-use-procfs-to-learn-opened-FDs.patch b/SOURCES/libvirt-virCommand-use-procfs-to-learn-opened-FDs.patch
new file mode 100644
index 0000000..57a022d
--- /dev/null
+++ b/SOURCES/libvirt-virCommand-use-procfs-to-learn-opened-FDs.patch
@@ -0,0 +1,145 @@
+From 53d2fa1d52ddc8d1d219a6882f84241a996ea752 Mon Sep 17 00:00:00 2001
+Message-Id: <53d2fa1d52ddc8d1d219a6882f84241a996ea752@dist-git>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Tue, 30 Jul 2019 15:30:54 +0200
+Subject: [PATCH] virCommand: use procfs to learn opened FDs
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+When spawning a child process, between fork() and exec() we close
+all file descriptors and keep only those the caller wants us to
+pass onto the child. The problem is how we do that. Currently, we
+get the limit of opened files and then iterate through each one
+of them and either close() it or make it survive exec(). This
+approach is suboptimal (although, not that much in default
+configurations where the limit is pretty low - 1024). We have
+/proc where we can learn what FDs we hold open and thus we can
+selectively close only those.
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit 432faf259b696043ee5d7e8f657d855419a9a3fa)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1721434
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Message-Id: <a9bee8e6412dc010caccef2bded857bb2a1c5eb0.1564493409.git.mprivozn@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircommand.c | 86 +++++++++++++++++++++++++++++++++++++++----
+ 1 file changed, 78 insertions(+), 8 deletions(-)
+
+diff --git a/src/util/vircommand.c b/src/util/vircommand.c
+index 8ae9a952a3..2353a4a554 100644
+--- a/src/util/vircommand.c
++++ b/src/util/vircommand.c
+@@ -491,27 +491,97 @@ virExecCommon(virCommandPtr cmd, gid_t *groups, int ngroups)
+     return ret;
+ }
+ 
++# ifdef __linux__
++/* On Linux, we can utilize procfs and read the table of opened
++ * FDs and selectively close only those FDs we don't want to pass
++ * onto child process (well, the one we will exec soon since this
++ * is called from the child). */
++static int
++virCommandMassCloseGetFDsLinux(virCommandPtr cmd ATTRIBUTE_UNUSED,
++                               virBitmapPtr fds)
++{
++    DIR *dp = NULL;
++    struct dirent *entry;
++    const char *dirName = "/proc/self/fd";
++    int rc;
++    int ret = -1;
++
++    if (virDirOpen(&dp, dirName) < 0)
++        return -1;
++
++    while ((rc = virDirRead(dp, &entry, dirName)) > 0) {
++        int fd;
++
++        if (virStrToLong_i(entry->d_name, NULL, 10, &fd) < 0) {
++            virReportError(VIR_ERR_INTERNAL_ERROR,
++                           _("unable to parse FD: %s"),
++                           entry->d_name);
++            goto cleanup;
++        }
++
++        if (virBitmapSetBit(fds, fd) < 0) {
++            virReportError(VIR_ERR_INTERNAL_ERROR,
++                           _("unable to set FD as open: %d"),
++                           fd);
++            goto cleanup;
++        }
++    }
++
++    if (rc < 0)
++        goto cleanup;
++
++    ret = 0;
++ cleanup:
++    VIR_DIR_CLOSE(dp);
++    return ret;
++}
++
++# else /* !__linux__ */
++
++static int
++virCommandMassCloseGetFDsGeneric(virCommandPtr cmd ATTRIBUTE_UNUSED,
++                                 virBitmapPtr fds)
++{
++    virBitmapSetAll(fds);
++    return 0;
++}
++# endif /* !__linux__ */
++
+ static int
+ virCommandMassClose(virCommandPtr cmd,
+                     int childin,
+                     int childout,
+                     int childerr)
+ {
++    VIR_AUTOPTR(virBitmap) fds = NULL;
+     int openmax = sysconf(_SC_OPEN_MAX);
+-    int fd;
+-    int tmpfd;
++    int fd = -1;
+ 
+-    if (openmax < 0) {
+-        virReportSystemError(errno,  "%s",
+-                             _("sysconf(_SC_OPEN_MAX) failed"));
++    /* In general, it is not safe to call malloc() between fork() and exec()
++     * because the child might have forked at the worst possible time, i.e.
++     * when another thread was in malloc() and thus held its lock. That is to
++     * say, POSIX does not mandate malloc() to be async-safe. Fortunately,
++     * glibc developers are aware of this and made malloc() async-safe.
++     * Therefore we can safely allocate memory here (and transitively call
++     * opendir/readdir) without a deadlock. */
++
++    if (!(fds = virBitmapNew(openmax)))
+         return -1;
+-    }
+ 
+-    for (fd = 3; fd < openmax; fd++) {
++# ifdef __linux__
++    if (virCommandMassCloseGetFDsLinux(cmd, fds) < 0)
++        return -1;
++# else
++    if (virCommandMassCloseGetFDsGeneric(cmd, fds) < 0)
++        return -1;
++# endif
++
++    fd = virBitmapNextSetBit(fds, 2);
++    for (; fd >= 0; fd = virBitmapNextSetBit(fds, fd)) {
+         if (fd == childin || fd == childout || fd == childerr)
+             continue;
+         if (!virCommandFDIsSet(cmd, fd)) {
+-            tmpfd = fd;
++            int tmpfd = fd;
+             VIR_MASS_CLOSE(tmpfd);
+         } else if (virSetInherit(fd, true) < 0) {
+             virReportSystemError(errno, _("failed to preserve fd %d"), fd);
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-virDomainObjListAddLocked-Produce-better-error-message-than-Duplicate-key.patch b/SOURCES/libvirt-virDomainObjListAddLocked-Produce-better-error-message-than-Duplicate-key.patch
new file mode 100644
index 0000000..674e3b6
--- /dev/null
+++ b/SOURCES/libvirt-virDomainObjListAddLocked-Produce-better-error-message-than-Duplicate-key.patch
@@ -0,0 +1,123 @@
+From 874617d278b58554feee567b2e79d208aaef214c Mon Sep 17 00:00:00 2001
+Message-Id: <874617d278b58554feee567b2e79d208aaef214c@dist-git>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Tue, 6 Aug 2019 13:29:22 +0200
+Subject: [PATCH] virDomainObjListAddLocked: Produce better error message than
+ 'Duplicate key'
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+If there are two concurrent threads, one of which is removing a
+domain from the list and the other is trying to add it back they
+may serialize in the following order:
+
+1) vm->removing is set and @vm is unlocked.
+2) The tread that's trying to add the domain onto the list locks
+   the list and tries to find, if the domain already exists.
+3) Our lookup functions say it doesn't, so the thread proceeds to
+   virHashAddEntry() which fails with 'Duplicate key' error.
+
+This is obviously not helpful error message at all.
+
+The problem lies in our lookup functions
+(virDomainObjListFindByUUIDLocked() and
+virDomainObjListFindByNameLocked()) which return NULL even if the
+object is still on the list. They do this so that the object is
+not mistakenly looked up by some driver. The fix consists of
+moving 'removing' check one level up and thus allowing
+virDomainObjListAddLocked() to produce meaningful error message.
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Reviewed-by: Cole Robinson <crobinso@redhat.com>
+(cherry picked from commit a5c71129bf2c12a827f1bc00149acd1c572ffe9c)
+
+Signed-off-by: Ján Tomko <jtomko@redhat.com>
+RHEL-8.1.0: https://bugzilla.redhat.com/show_bug.cgi?id=1737790
+Message-Id: <c63ca487bf56af5240e273b5a112a753c2bc85a3.1565090956.git.jtomko@redhat.com>
+Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
+---
+ src/conf/virdomainobjlist.c | 35 +++++++++++++++++++++--------------
+ 1 file changed, 21 insertions(+), 14 deletions(-)
+
+diff --git a/src/conf/virdomainobjlist.c b/src/conf/virdomainobjlist.c
+index e7c3e326ca..3b388e2ba2 100644
+--- a/src/conf/virdomainobjlist.c
++++ b/src/conf/virdomainobjlist.c
+@@ -142,14 +142,9 @@ virDomainObjListFindByUUIDLocked(virDomainObjListPtr doms,
+ 
+     virUUIDFormat(uuid, uuidstr);
+     obj = virHashLookup(doms->objs, uuidstr);
+-    virObjectRef(obj);
+     if (obj) {
++        virObjectRef(obj);
+         virObjectLock(obj);
+-        if (obj->removing) {
+-            virObjectUnlock(obj);
+-            virObjectUnref(obj);
+-            obj = NULL;
+-        }
+     }
+     return obj;
+ }
+@@ -173,6 +168,12 @@ virDomainObjListFindByUUID(virDomainObjListPtr doms,
+     obj = virDomainObjListFindByUUIDLocked(doms, uuid);
+     virObjectRWUnlock(doms);
+ 
++    if (obj && obj->removing) {
++        virObjectUnlock(obj);
++        virObjectUnref(obj);
++        obj = NULL;
++    }
++
+     return obj;
+ }
+ 
+@@ -184,14 +185,9 @@ virDomainObjListFindByNameLocked(virDomainObjListPtr doms,
+     virDomainObjPtr obj;
+ 
+     obj = virHashLookup(doms->objsName, name);
+-    virObjectRef(obj);
+     if (obj) {
++        virObjectRef(obj);
+         virObjectLock(obj);
+-        if (obj->removing) {
+-            virObjectUnlock(obj);
+-            virObjectUnref(obj);
+-            obj = NULL;
+-        }
+     }
+     return obj;
+ }
+@@ -215,6 +211,12 @@ virDomainObjListFindByName(virDomainObjListPtr doms,
+     obj = virDomainObjListFindByNameLocked(doms, name);
+     virObjectRWUnlock(doms);
+ 
++    if (obj && obj->removing) {
++        virObjectUnlock(obj);
++        virObjectUnref(obj);
++        obj = NULL;
++    }
++
+     return obj;
+ }
+ 
+@@ -286,8 +288,13 @@ virDomainObjListAddLocked(virDomainObjListPtr doms,
+ 
+     /* See if a VM with matching UUID already exists */
+     if ((vm = virDomainObjListFindByUUIDLocked(doms, def->uuid))) {
+-        /* UUID matches, but if names don't match, refuse it */
+-        if (STRNEQ(vm->def->name, def->name)) {
++        if (vm->removing) {
++            virReportError(VIR_ERR_OPERATION_FAILED,
++                           _("domain '%s' is already being removed"),
++                           vm->def->name);
++            goto error;
++        } else if (STRNEQ(vm->def->name, def->name)) {
++            /* UUID matches, but if names don't match, refuse it */
+             virUUIDFormat(vm->def->uuid, uuidstr);
+             virReportError(VIR_ERR_OPERATION_FAILED,
+                            _("domain '%s' is already defined with uuid %s"),
+-- 
+2.22.1
+
diff --git a/SOURCES/libvirt-virDomainObjListAddLocked-fix-double-free.patch b/SOURCES/libvirt-virDomainObjListAddLocked-fix-double-free.patch
new file mode 100644
index 0000000..0f08e90
--- /dev/null
+++ b/SOURCES/libvirt-virDomainObjListAddLocked-fix-double-free.patch
@@ -0,0 +1,64 @@
+From ad3f8f1d128f726d1504079ec34b68f6db297d3a Mon Sep 17 00:00:00 2001
+Message-Id: <ad3f8f1d128f726d1504079ec34b68f6db297d3a@dist-git>
+From: Marc Hartmayer <mhartmay@linux.ibm.com>
+Date: Wed, 10 Jul 2019 11:49:45 +0200
+Subject: [PATCH] virDomainObjListAddLocked: fix double free
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+If @vm has flagged as "to be removed" virDomainObjListFindByNameLocked
+returns NULL (although the definition actually exists). Therefore, the
+possibility exits that "virHashAddEntry" will raise the error
+"Duplicate key" => virDomainObjListAddObjLocked fails =>
+virDomainObjEndAPI(&vm) is called and this leads to a freeing of @def
+since @def is already assigned to vm->def. But actually this leads to
+a double free since the common usage pattern is that the caller of
+virDomainObjListAdd(Locked) is responsible for freeing @def in case of
+an error.
+
+Let's fix this by setting vm->def to NULL in case of an error.
+
+Backtrace:
+
+   ➤  bt
+   #0  virFree (ptrptr=0x7575757575757575)
+   #1  0x000003ffb5b25b3e in virDomainResourceDefFree
+   #2  0x000003ffb5b37c34 in virDomainDefFree
+   #3  0x000003ff9123f734 in qemuDomainDefineXMLFlags
+   #4  0x000003ff9123f7f4 in qemuDomainDefineXML
+   #5  0x000003ffb5cd2c84 in virDomainDefineXML
+   #6  0x000000011745aa82 in remoteDispatchDomainDefineXML
+   ...
+
+Reviewed-by: Bjoern Walk <bwalk@linux.ibm.com>
+Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
+(cherry picked from commit 7e760f61577e6c4adbb0b015f8f7ac1796570cdd)
+Signed-off-by: Ján Tomko <jtomko@redhat.com>
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1728530
+Message-Id: <b651c347f5775c8298347ef8602d0205fab9c3e7.1562752178.git.jtomko@redhat.com>
+Reviewed-by: Andrea Bolognani <abologna@redhat.com>
+---
+ src/conf/virdomainobjlist.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/src/conf/virdomainobjlist.c b/src/conf/virdomainobjlist.c
+index 72064d7c66..e7c3e326ca 100644
+--- a/src/conf/virdomainobjlist.c
++++ b/src/conf/virdomainobjlist.c
+@@ -329,8 +329,10 @@ virDomainObjListAddLocked(virDomainObjListPtr doms,
+             goto cleanup;
+         vm->def = def;
+ 
+-        if (virDomainObjListAddObjLocked(doms, vm) < 0)
++        if (virDomainObjListAddObjLocked(doms, vm) < 0) {
++            vm->def = NULL;
+             goto error;
++        }
+     }
+  cleanup:
+     return vm;
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-virNetDevOpenvswitchInterfaceStats-Optimize-for-speed.patch b/SOURCES/libvirt-virNetDevOpenvswitchInterfaceStats-Optimize-for-speed.patch
new file mode 100644
index 0000000..5b105e6
--- /dev/null
+++ b/SOURCES/libvirt-virNetDevOpenvswitchInterfaceStats-Optimize-for-speed.patch
@@ -0,0 +1,175 @@
+From dbcd08b082f3e96cf09328041549c0f1dc4e1335 Mon Sep 17 00:00:00 2001
+Message-Id: <dbcd08b082f3e96cf09328041549c0f1dc4e1335@dist-git>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Tue, 30 Jul 2019 15:30:51 +0200
+Subject: [PATCH] virNetDevOpenvswitchInterfaceStats: Optimize for speed
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+We run 'ovs-vsctl' nine times (first to find if interface is
+there and then eight times = for each stats member separately).
+This is very inefficient. I've found a way to run it once and
+with a bit of help from virJSON module we can parse out stats
+we need.
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit c297eab52599c91a4cb26b66dbdfe9d07c3142d3)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1721434
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Message-Id: <ba02a9b373ff7014e1edfc98da4edf11abe34a9e.1564493409.git.mprivozn@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/virnetdevopenvswitch.c | 111 +++++++++++++++++++++-----------
+ 1 file changed, 74 insertions(+), 37 deletions(-)
+
+diff --git a/src/util/virnetdevopenvswitch.c b/src/util/virnetdevopenvswitch.c
+index cb403aaf2e..dbd832053b 100644
+--- a/src/util/virnetdevopenvswitch.c
++++ b/src/util/virnetdevopenvswitch.c
+@@ -35,6 +35,7 @@
+ #include "virmacaddr.h"
+ #include "virstring.h"
+ #include "virlog.h"
++#include "virjson.h"
+ 
+ #define VIR_FROM_THIS VIR_FROM_NONE
+ 
+@@ -318,58 +319,94 @@ int
+ virNetDevOpenvswitchInterfaceStats(const char *ifname,
+                                    virDomainInterfaceStatsPtr stats)
+ {
+-    char *tmp;
+-    bool gotStats = false;
+     VIR_AUTOPTR(virCommand) cmd = NULL;
+     VIR_AUTOFREE(char *) output = NULL;
++    VIR_AUTOPTR(virJSONValue) jsonStats = NULL;
++    virJSONValuePtr jsonMap = NULL;
++    size_t i;
+ 
+-    /* Just ensure the interface exists in ovs */
+     cmd = virCommandNew(OVSVSCTL);
+     virNetDevOpenvswitchAddTimeout(cmd);
+-    virCommandAddArgList(cmd, "get", "Interface", ifname, "name", NULL);
++    virCommandAddArgList(cmd, "--if-exists", "--format=list", "--data=json",
++                         "--no-headings", "--columns=statistics", "list",
++                         "Interface", ifname, NULL);
+     virCommandSetOutputBuffer(cmd, &output);
+ 
+-    if (virCommandRun(cmd, NULL) < 0) {
++    /* The above command returns either:
++     * 1) empty string if @ifname doesn't exist, or
++     * 2) a JSON array, for instance:
++     *    ["map",[["collisions",0],["rx_bytes",0],["rx_crc_err",0],["rx_dropped",0],
++     *    ["rx_errors",0],["rx_frame_err",0],["rx_over_err",0],["rx_packets",0],
++     *    ["tx_bytes",12406],["tx_dropped",0],["tx_errors",0],["tx_packets",173]]]
++     */
++
++    if (virCommandRun(cmd, NULL) < 0 ||
++        STREQ_NULLABLE(output, "")) {
+         /* no ovs-vsctl or interface 'ifname' doesn't exists in ovs */
+         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                        _("Interface not found"));
+         return -1;
+     }
+ 
+-#define GET_STAT(name, member) \
+-    do { \
+-        VIR_FREE(output); \
+-        virCommandFree(cmd); \
+-        cmd = virCommandNew(OVSVSCTL); \
+-        virNetDevOpenvswitchAddTimeout(cmd); \
+-        virCommandAddArgList(cmd, "--if-exists", "get", "Interface", \
+-                             ifname, "statistics:" name, NULL); \
+-        virCommandSetOutputBuffer(cmd, &output); \
+-        if (virCommandRun(cmd, NULL) < 0 || !output || !*output || *output == '\n') { \
+-            stats->member = -1; \
+-        } else { \
+-            if (virStrToLong_ll(output, &tmp, 10, &stats->member) < 0 || \
+-                *tmp != '\n') { \
+-                virReportError(VIR_ERR_INTERNAL_ERROR, "%s", \
+-                               _("Fail to parse ovs-vsctl output")); \
+-                return -1; \
+-            } \
+-            gotStats = true; \
+-        } \
+-    } while (0)
++    if (!(jsonStats = virJSONValueFromString(output)) ||
++        !virJSONValueIsArray(jsonStats) ||
++        !(jsonMap = virJSONValueArrayGet(jsonStats, 1))) {
++        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
++                       _("Unable to parse ovs-vsctl output"));
++        return -1;
++    }
+ 
+-    /* The TX/RX fields appear to be swapped here
+-     * because this is the host view. */
+-    GET_STAT("rx_bytes", tx_bytes);
+-    GET_STAT("rx_packets", tx_packets);
+-    GET_STAT("rx_errors", tx_errs);
+-    GET_STAT("rx_dropped", tx_drop);
+-    GET_STAT("tx_bytes", rx_bytes);
+-    GET_STAT("tx_packets", rx_packets);
+-    GET_STAT("tx_errors", rx_errs);
+-    GET_STAT("tx_dropped", rx_drop);
++    stats->rx_bytes = stats->rx_packets = stats->rx_errs = stats->rx_drop = -1;
++    stats->tx_bytes = stats->tx_packets = stats->tx_errs = stats->tx_drop = -1;
+ 
+-    if (!gotStats) {
++    for (i = 0; i < virJSONValueArraySize(jsonMap); i++) {
++        virJSONValuePtr item = virJSONValueArrayGet(jsonMap, i);
++        virJSONValuePtr jsonKey;
++        virJSONValuePtr jsonVal;
++        const char *key;
++        long long val;
++
++        if (!item ||
++            (!(jsonKey = virJSONValueArrayGet(item, 0))) ||
++            (!(jsonVal = virJSONValueArrayGet(item, 1))) ||
++            (!(key = virJSONValueGetString(jsonKey))) ||
++            (virJSONValueGetNumberLong(jsonVal, &val) < 0)) {
++            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
++                           _("Malformed ovs-vsctl output"));
++            return -1;
++        }
++
++        /* The TX/RX fields appear to be swapped here
++         * because this is the host view. */
++        if (STREQ(key, "rx_bytes")) {
++            stats->tx_bytes = val;
++        } else if (STREQ(key, "rx_packets")) {
++            stats->tx_packets = val;
++        } else if (STREQ(key, "rx_errors")) {
++            stats->tx_errs = val;
++        } else if (STREQ(key, "rx_dropped")) {
++            stats->tx_drop = val;
++        } else if (STREQ(key, "tx_bytes")) {
++            stats->rx_bytes = val;
++        } else if (STREQ(key, "tx_packets")) {
++            stats->rx_packets = val;
++        } else if (STREQ(key, "tx_errors")) {
++            stats->rx_errs = val;
++        } else if (STREQ(key, "tx_dropped")) {
++            stats->rx_drop = val;
++        } else {
++            VIR_DEBUG("Unused ovs-vsctl stat key=%s val=%lld", key, val);
++        }
++    }
++
++    if (stats->rx_bytes == -1 &&
++        stats->rx_packets == -1 &&
++        stats->rx_errs == -1 &&
++        stats->rx_drop == -1 &&
++        stats->tx_bytes == -1 &&
++        stats->tx_packets == -1 &&
++        stats->tx_errs == -1 &&
++        stats->tx_drop == -1) {
+         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                        _("Interface doesn't have any statistics"));
+         return -1;
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-virWaitForDevices-Drop-confusing-part-of-comment.patch b/SOURCES/libvirt-virWaitForDevices-Drop-confusing-part-of-comment.patch
new file mode 100644
index 0000000..40d598d
--- /dev/null
+++ b/SOURCES/libvirt-virWaitForDevices-Drop-confusing-part-of-comment.patch
@@ -0,0 +1,41 @@
+From a72b338a9127075ea9ededcdc201dc87b65fe731 Mon Sep 17 00:00:00 2001
+Message-Id: <a72b338a9127075ea9ededcdc201dc87b65fe731@dist-git>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Thu, 27 Jun 2019 15:55:36 +0200
+Subject: [PATCH] virWaitForDevices: Drop confusing part of comment
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+It's not true that there is a backup loop. There isn't. Drop this
+part of the comment to not confuse anybody.
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit 0cabcd98f1ef82588016a692afbe5a47a4a0b42e)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1710575
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Message-Id: <3faa00d11315ede9c72b32b1aa1f8797e1638dfe.1561643698.git.mprivozn@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/virutil.c | 2 --
+ 1 file changed, 2 deletions(-)
+
+diff --git a/src/util/virutil.c b/src/util/virutil.c
+index 88e17e2c0f..d37c1ac632 100644
+--- a/src/util/virutil.c
++++ b/src/util/virutil.c
+@@ -1637,8 +1637,6 @@ void virWaitForDevices(void)
+     /*
+      * NOTE: we ignore errors here; this is just to make sure that any device
+      * nodes that are being created finish before we try to scan them.
+-     * If this fails for any reason, we still have the backup of polling for
+-     * 5 seconds for device nodes.
+      */
+     ignore_value(virRun(settleprog, &exitstatus));
+ }
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-Call-virCgroupRemove-inside-virCgroupMakeGroup.patch b/SOURCES/libvirt-vircgroup-Call-virCgroupRemove-inside-virCgroupMakeGroup.patch
new file mode 100644
index 0000000..cebbe6b
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-Call-virCgroupRemove-inside-virCgroupMakeGroup.patch
@@ -0,0 +1,106 @@
+From 9831bda48172881b14f3c473b625ce5ddbd04300 Mon Sep 17 00:00:00 2001
+Message-Id: <9831bda48172881b14f3c473b625ce5ddbd04300@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:06:08 +0200
+Subject: [PATCH] vircgroup: Call virCgroupRemove inside virCgroupMakeGroup
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This fixes virCgroupEnableMissingControllers where virCgroupRemove
+was not called in case virCgroupMakeGroup failed.
+
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit b013bdfd797489e6c254917da299842fe051d058)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <09accbd84f3da1d7c6682357cf6c9a720631a247.1561993099.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c | 18 +++++++++---------
+ 1 file changed, 9 insertions(+), 9 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index 8646a4a479..dde9ed21a2 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -1052,7 +1052,7 @@ virCgroupMakeGroup(virCgroupPtr parent,
+         }
+ 
+         if (virCgroupPathOfController(group, i, "", &path) < 0)
+-            return -1;
++            goto error;
+ 
+         /* As of Feb 2011, clang can't see that the above function
+          * call did not modify group. */
+@@ -1076,7 +1076,7 @@ virCgroupMakeGroup(virCgroupPtr parent,
+                     virReportSystemError(errno,
+                                          _("Failed to create controller %s for group"),
+                                          virCgroupControllerTypeToString(i));
+-                    return -1;
++                    goto error;
+                 }
+             }
+             if (group->controllers[VIR_CGROUP_CONTROLLER_CPUSET].mountPoint != NULL &&
+@@ -1084,7 +1084,7 @@ virCgroupMakeGroup(virCgroupPtr parent,
+                  STREQ(group->controllers[i].mountPoint,
+                        group->controllers[VIR_CGROUP_CONTROLLER_CPUSET].mountPoint))) {
+                 if (virCgroupCpuSetInherit(parent, group) < 0)
+-                    return -1;
++                    goto error;
+             }
+             /*
+              * Note that virCgroupSetMemoryUseHierarchy should always be
+@@ -1096,13 +1096,17 @@ virCgroupMakeGroup(virCgroupPtr parent,
+                  STREQ(group->controllers[i].mountPoint,
+                        group->controllers[VIR_CGROUP_CONTROLLER_MEMORY].mountPoint))) {
+                 if (virCgroupSetMemoryUseHierarchy(group) < 0)
+-                    return -1;
++                    goto error;
+             }
+         }
+     }
+ 
+     VIR_DEBUG("Done making controllers for group");
+     return 0;
++
++ error:
++    virCgroupRemove(group);
++    return -1;
+ }
+ 
+ 
+@@ -1316,10 +1320,8 @@ virCgroupNewPartition(const char *path,
+         if (virCgroupNew(-1, parentPath, NULL, controllers, &parent) < 0)
+             goto cleanup;
+ 
+-        if (virCgroupMakeGroup(parent, *group, create, VIR_CGROUP_NONE) < 0) {
+-            virCgroupRemove(*group);
++        if (virCgroupMakeGroup(parent, *group, create, VIR_CGROUP_NONE) < 0)
+             goto cleanup;
+-        }
+     }
+ 
+     ret = 0;
+@@ -1389,7 +1391,6 @@ virCgroupNewDomainPartition(virCgroupPtr partition,
+      */
+     if (virCgroupMakeGroup(partition, *group, create,
+                            VIR_CGROUP_MEM_HIERACHY) < 0) {
+-        virCgroupRemove(*group);
+         virCgroupFree(group);
+         return -1;
+     }
+@@ -1446,7 +1447,6 @@ virCgroupNewThread(virCgroupPtr domain,
+         return -1;
+ 
+     if (virCgroupMakeGroup(domain, *group, create, VIR_CGROUP_NONE) < 0) {
+-        virCgroupRemove(*group);
+         virCgroupFree(group);
+         return -1;
+     }
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-Duplicate-string-before-modifying.patch b/SOURCES/libvirt-vircgroup-Duplicate-string-before-modifying.patch
new file mode 100644
index 0000000..9e0a069
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-Duplicate-string-before-modifying.patch
@@ -0,0 +1,75 @@
+From d0add5355b434df64c5f9fb28b9ab4bdd86f93f2 Mon Sep 17 00:00:00 2001
+Message-Id: <d0add5355b434df64c5f9fb28b9ab4bdd86f93f2@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:06:04 +0200
+Subject: [PATCH] vircgroup: Duplicate string before modifying
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The 'mntDir' is part of 'struct mntent' as a result of getmntent_r
+therefore we should not mangle with it.
+
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 4b2fb60777bdad70df2871dad1d0e604cda078c6)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <b57526226460be172899f5a6e14f185eabb18cea.1561993099.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c | 14 +++++++++-----
+ 1 file changed, 9 insertions(+), 5 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index df38bb77e0..45b854e864 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -350,18 +350,22 @@ virCgroupCopyMounts(virCgroupPtr group,
+ 
+ 
+ static int
+-virCgroupResolveMountLink(char *mntDir,
++virCgroupResolveMountLink(const char *mntDir,
+                           const char *typeStr,
+                           virCgroupControllerPtr controller)
+ {
+     VIR_AUTOFREE(char *) linkSrc = NULL;
++    VIR_AUTOFREE(char *) tmp = NULL;
+     char *dirName;
+     struct stat sb;
+ 
+-    dirName = strrchr(mntDir, '/');
++    if (VIR_STRDUP(tmp, mntDir) < 0)
++        return -1;
++
++    dirName = strrchr(tmp, '/');
+     if (!dirName) {
+         virReportError(VIR_ERR_INTERNAL_ERROR,
+-                       _("Missing '/' separator in cgroup mount '%s'"), mntDir);
++                       _("Missing '/' separator in cgroup mount '%s'"), tmp);
+         return -1;
+     }
+ 
+@@ -369,14 +373,14 @@ virCgroupResolveMountLink(char *mntDir,
+         return 0;
+ 
+     *dirName = '\0';
+-    if (virAsprintf(&linkSrc, "%s/%s", mntDir, typeStr) < 0)
++    if (virAsprintf(&linkSrc, "%s/%s", tmp, typeStr) < 0)
+         return -1;
+     *dirName = '/';
+ 
+     if (lstat(linkSrc, &sb) < 0) {
+         if (errno == ENOENT) {
+             VIR_WARN("Controller %s co-mounted at %s is missing symlink at %s",
+-                     typeStr, mntDir, linkSrc);
++                     typeStr, tmp, linkSrc);
+         } else {
+             virReportSystemError(errno, _("Cannot stat %s"), linkSrc);
+             return -1;
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-Extract-controller-detection-into-function.patch b/SOURCES/libvirt-vircgroup-Extract-controller-detection-into-function.patch
new file mode 100644
index 0000000..e6a7b90
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-Extract-controller-detection-into-function.patch
@@ -0,0 +1,95 @@
+From 931ae6bf56044020c057716e1db59288beca2bc8 Mon Sep 17 00:00:00 2001
+Message-Id: <931ae6bf56044020c057716e1db59288beca2bc8@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:06:05 +0200
+Subject: [PATCH] vircgroup: Extract controller detection into function
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit bddf975c7615a30da0709b6c1509b43440d72393)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <484f007f9f43d727b829bb18fa4ad2f116a7fae1.1561993099.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c | 48 +++++++++++++++++++++++++++++---------------
+ 1 file changed, 32 insertions(+), 16 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index 45b854e864..6f27c50cbd 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -631,24 +631,11 @@ virCgroupDetectPlacement(virCgroupPtr group,
+ 
+ 
+ static int
+-virCgroupDetect(virCgroupPtr group,
+-                pid_t pid,
+-                int controllers,
+-                const char *path,
+-                virCgroupPtr parent)
++virCgroupDetectControllers(virCgroupPtr group,
++                           int controllers)
+ {
+     size_t i;
+     size_t j;
+-    VIR_DEBUG("group=%p controllers=%d path=%s parent=%p",
+-              group, controllers, path, parent);
+-
+-    if (parent) {
+-        if (virCgroupCopyMounts(group, parent) < 0)
+-            return -1;
+-    } else {
+-        if (virCgroupDetectMounts(group) < 0)
+-            return -1;
+-    }
+ 
+     if (controllers >= 0) {
+         VIR_DEBUG("Filtering controllers %d", controllers);
+@@ -703,8 +690,37 @@ virCgroupDetect(virCgroupPtr group,
+         }
+     }
+ 
++    return controllers;
++}
++
++
++static int
++virCgroupDetect(virCgroupPtr group,
++                pid_t pid,
++                int controllers,
++                const char *path,
++                virCgroupPtr parent)
++{
++    size_t i;
++    int rc;
++
++    VIR_DEBUG("group=%p controllers=%d path=%s parent=%p",
++              group, controllers, path, parent);
++
++    if (parent) {
++        if (virCgroupCopyMounts(group, parent) < 0)
++            return -1;
++    } else {
++        if (virCgroupDetectMounts(group) < 0)
++            return -1;
++    }
++
++    rc = virCgroupDetectControllers(group, controllers);
++    if (rc < 0)
++        return -1;
++
+     /* Check that at least 1 controller is available */
+-    if (!controllers) {
++    if (rc == 0) {
+         virReportSystemError(ENXIO, "%s",
+                              _("At least one cgroup controller is required"));
+         return -1;
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-Extract-file-link-resolving-into-separate-function.patch b/SOURCES/libvirt-vircgroup-Extract-file-link-resolving-into-separate-function.patch
new file mode 100644
index 0000000..65a6823
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-Extract-file-link-resolving-into-separate-function.patch
@@ -0,0 +1,137 @@
+From d7a8cd2fdafd168eb1672e7ecde1700463792518 Mon Sep 17 00:00:00 2001
+Message-Id: <d7a8cd2fdafd168eb1672e7ecde1700463792518@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:05:50 +0200
+Subject: [PATCH] vircgroup: Extract file link resolving into separate function
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 00a0085aa17677003e89cdafceb6a0260af43fb8)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <6d3c5594a53824ceac258a0f54162ec8af5aef37.1561993099.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c | 85 +++++++++++++++++++++++++-------------------
+ 1 file changed, 48 insertions(+), 37 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index 5144b33d43..8ddedbfe7c 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -356,6 +356,51 @@ virCgroupCopyMounts(virCgroupPtr group,
+ }
+ 
+ 
++static int
++virCgroupResolveMountLink(char *mntDir,
++                          const char *typeStr,
++                          virCgroupControllerPtr controller)
++{
++    VIR_AUTOFREE(char *) linkSrc = NULL;
++    char *dirName;
++    struct stat sb;
++
++    dirName = strrchr(mntDir, '/');
++    if (!dirName) {
++        virReportError(VIR_ERR_INTERNAL_ERROR,
++                       _("Missing '/' separator in cgroup mount '%s'"), mntDir);
++        return -1;
++    }
++
++    if (!strchr(dirName + 1, ','))
++        return 0;
++
++    *dirName = '\0';
++    if (virAsprintf(&linkSrc, "%s/%s", mntDir, typeStr) < 0)
++        return -1;
++    *dirName = '/';
++
++    if (lstat(linkSrc, &sb) < 0) {
++        if (errno == ENOENT) {
++            VIR_WARN("Controller %s co-mounted at %s is missing symlink at %s",
++                     typeStr, mntDir, linkSrc);
++        } else {
++            virReportSystemError(errno, _("Cannot stat %s"), linkSrc);
++            return -1;
++        }
++    } else {
++        if (!S_ISLNK(sb.st_mode)) {
++            VIR_WARN("Expecting a symlink at %s for controller %s",
++                     linkSrc, typeStr);
++        } else {
++            VIR_STEAL_PTR(controller->linkPoint, linkSrc);
++        }
++    }
++
++    return 0;
++}
++
++
+ /*
+  * Process /proc/mounts figuring out what controllers are
+  * mounted and where
+@@ -397,8 +442,6 @@ virCgroupDetectMountsFromFile(virCgroupPtr group,
+                 }
+ 
+                 if (typelen == len && STREQLEN(typestr, tmp, len)) {
+-                    struct stat sb;
+-                    char *tmp2;
+ 
+                     /* Note that the lines in /proc/mounts have the same
+                      * order than the mount operations, and that there may
+@@ -412,44 +455,12 @@ virCgroupDetectMountsFromFile(virCgroupPtr group,
+                     if (VIR_STRDUP(controller->mountPoint, entry.mnt_dir) < 0)
+                         goto cleanup;
+ 
+-                    tmp2 = strrchr(entry.mnt_dir, '/');
+-                    if (!tmp2) {
+-                        virReportError(VIR_ERR_INTERNAL_ERROR,
+-                                       _("Missing '/' separator in cgroup mount '%s'"),
+-                                       entry.mnt_dir);
+-                        goto cleanup;
+-                    }
+-
+                     /* If it is a co-mount it has a filename like "cpu,cpuacct"
+                      * and we must identify the symlink path */
+-                    if (checkLinks && strchr(tmp2 + 1, ',')) {
+-                        VIR_AUTOFREE(char *) linksrc = NULL;
+-
+-                        *tmp2 = '\0';
+-                        if (virAsprintf(&linksrc, "%s/%s",
+-                                        entry.mnt_dir, typestr) < 0)
++                    if (checkLinks &&
++                        virCgroupResolveMountLink(entry.mnt_dir, typestr,
++                                                  controller) < 0) {
+                             goto cleanup;
+-                        *tmp2 = '/';
+-
+-                        if (lstat(linksrc, &sb) < 0) {
+-                            if (errno == ENOENT) {
+-                                VIR_WARN("Controller %s co-mounted at %s is missing symlink at %s",
+-                                         typestr, entry.mnt_dir, linksrc);
+-                            } else {
+-                                virReportSystemError(errno,
+-                                                     _("Cannot stat %s"),
+-                                                     linksrc);
+-                                goto cleanup;
+-                            }
+-                        } else {
+-                            if (!S_ISLNK(sb.st_mode)) {
+-                                VIR_WARN("Expecting a symlink at %s for controller %s",
+-                                         linksrc, typestr);
+-                            } else {
+-                                controller->linkPoint = linksrc;
+-                                linksrc = NULL;
+-                            }
+-                        }
+                     }
+                 }
+                 tmp = next;
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-Extract-mount-options-matching-into-function.patch b/SOURCES/libvirt-vircgroup-Extract-mount-options-matching-into-function.patch
new file mode 100644
index 0000000..c513497
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-Extract-mount-options-matching-into-function.patch
@@ -0,0 +1,127 @@
+From 75f8c320bb6a09f111db513c52c71bbb5b3b7b9f Mon Sep 17 00:00:00 2001
+Message-Id: <75f8c320bb6a09f111db513c52c71bbb5b3b7b9f@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:05:56 +0200
+Subject: [PATCH] vircgroup: Extract mount options matching into function
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 6d5b91f0f5527ed79b39f1f1a375a35869e75356)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <6c5aa678b08ceb1efd6d1bda2350a979ca59035b.1561993099.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c | 84 ++++++++++++++++++++++++++------------------
+ 1 file changed, 49 insertions(+), 35 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index 9032bcbb63..ec9994780a 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -399,6 +399,33 @@ virCgroupResolveMountLink(char *mntDir,
+ }
+ 
+ 
++static bool
++virCgroupMountOptsMatchController(const char *mntOpts,
++                                  const char *typeStr)
++{
++    const char *tmp = mntOpts;
++    int typeLen = strlen(typeStr);
++
++    while (tmp) {
++        const char *next = strchr(tmp, ',');
++        int len;
++        if (next) {
++            len = next - tmp;
++            next++;
++        } else {
++            len = strlen(tmp);
++        }
++
++        if (typeLen == len && STREQLEN(typeStr, tmp, len))
++            return true;
++
++        tmp = next;
++    }
++
++    return false;
++}
++
++
+ /*
+  * Process /proc/mounts figuring out what controllers are
+  * mounted and where
+@@ -426,42 +453,29 @@ virCgroupDetectMountsFromFile(virCgroupPtr group,
+ 
+         for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
+             const char *typestr = virCgroupControllerTypeToString(i);
+-            int typelen = strlen(typestr);
+-            char *tmp = entry.mnt_opts;
+-            virCgroupControllerPtr controller = &group->controllers[i];
+-            while (tmp) {
+-                char *next = strchr(tmp, ',');
+-                int len;
+-                if (next) {
+-                    len = next-tmp;
+-                    next++;
+-                } else {
+-                    len = strlen(tmp);
++
++            if (virCgroupMountOptsMatchController(entry.mnt_opts, typestr)) {
++                /* Note that the lines in /proc/mounts have the same
++                 * order than the mount operations, and that there may
++                 * be duplicates due to bind mounts. This means
++                 * that the same mount point may be processed more than
++                 * once. We need to save the results of the last one,
++                 * and we need to be careful to release the memory used
++                 * by previous processing. */
++                virCgroupControllerPtr controller = &group->controllers[i];
++
++                VIR_FREE(controller->mountPoint);
++                VIR_FREE(controller->linkPoint);
++                if (VIR_STRDUP(controller->mountPoint, entry.mnt_dir) < 0)
++                    goto cleanup;
++
++                /* If it is a co-mount it has a filename like "cpu,cpuacct"
++                 * and we must identify the symlink path */
++                if (checkLinks &&
++                    virCgroupResolveMountLink(entry.mnt_dir, typestr,
++                                              controller) < 0) {
++                    goto cleanup;
+                 }
+-
+-                if (typelen == len && STREQLEN(typestr, tmp, len)) {
+-
+-                    /* Note that the lines in /proc/mounts have the same
+-                     * order than the mount operations, and that there may
+-                     * be duplicates due to bind mounts. This means
+-                     * that the same mount point may be processed more than
+-                     * once. We need to save the results of the last one,
+-                     * and we need to be careful to release the memory used
+-                     * by previous processing. */
+-                    VIR_FREE(controller->mountPoint);
+-                    VIR_FREE(controller->linkPoint);
+-                    if (VIR_STRDUP(controller->mountPoint, entry.mnt_dir) < 0)
+-                        goto cleanup;
+-
+-                    /* If it is a co-mount it has a filename like "cpu,cpuacct"
+-                     * and we must identify the symlink path */
+-                    if (checkLinks &&
+-                        virCgroupResolveMountLink(entry.mnt_dir, typestr,
+-                                                  controller) < 0) {
+-                            goto cleanup;
+-                    }
+-                }
+-                tmp = next;
+             }
+         }
+     }
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-Extract-placement-validation-into-function.patch b/SOURCES/libvirt-vircgroup-Extract-placement-validation-into-function.patch
new file mode 100644
index 0000000..8513ce4
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-Extract-placement-validation-into-function.patch
@@ -0,0 +1,102 @@
+From 489202ad9fe2dd9e417335c7274ba522adfc490b Mon Sep 17 00:00:00 2001
+Message-Id: <489202ad9fe2dd9e417335c7274ba522adfc490b@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:06:06 +0200
+Subject: [PATCH] vircgroup: Extract placement validation into function
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 3ae7b99094dc72616f902289afc407df738c9ce9)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <5728512c8e969952c0502fb4119f2930ae4bc49c.1561993099.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c | 52 +++++++++++++++++++++++++++-----------------
+ 1 file changed, 32 insertions(+), 20 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index 6f27c50cbd..2bc4febf23 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -630,6 +630,36 @@ virCgroupDetectPlacement(virCgroupPtr group,
+ }
+ 
+ 
++static int
++virCgroupValidatePlacement(virCgroupPtr group,
++                           pid_t pid)
++{
++    size_t i;
++
++    for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
++        if (!group->controllers[i].mountPoint)
++            continue;
++
++        if (!group->controllers[i].placement) {
++            virReportError(VIR_ERR_INTERNAL_ERROR,
++                           _("Could not find placement for controller %s at %s"),
++                           virCgroupControllerTypeToString(i),
++                           group->controllers[i].placement);
++            return -1;
++        }
++
++        VIR_DEBUG("Detected mount/mapping %zu:%s at %s in %s for pid %lld",
++                  i,
++                  virCgroupControllerTypeToString(i),
++                  group->controllers[i].mountPoint,
++                  group->controllers[i].placement,
++                  (long long) pid);
++    }
++
++    return 0;
++}
++
++
+ static int
+ virCgroupDetectControllers(virCgroupPtr group,
+                            int controllers)
+@@ -701,7 +731,6 @@ virCgroupDetect(virCgroupPtr group,
+                 const char *path,
+                 virCgroupPtr parent)
+ {
+-    size_t i;
+     int rc;
+ 
+     VIR_DEBUG("group=%p controllers=%d path=%s parent=%p",
+@@ -738,25 +767,8 @@ virCgroupDetect(virCgroupPtr group,
+         return -1;
+ 
+     /* Check that for every mounted controller, we found our placement */
+-    for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
+-        if (!group->controllers[i].mountPoint)
+-            continue;
+-
+-        if (!group->controllers[i].placement) {
+-            virReportError(VIR_ERR_INTERNAL_ERROR,
+-                           _("Could not find placement for controller %s at %s"),
+-                           virCgroupControllerTypeToString(i),
+-                           group->controllers[i].placement);
+-            return -1;
+-        }
+-
+-        VIR_DEBUG("Detected mount/mapping %zu:%s at %s in %s for pid %lld",
+-                  i,
+-                  virCgroupControllerTypeToString(i),
+-                  group->controllers[i].mountPoint,
+-                  group->controllers[i].placement,
+-                  (long long) pid);
+-    }
++    if (virCgroupValidatePlacement(group, pid) < 0)
++        return -1;
+ 
+     return 0;
+ }
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-Introduce-standard-set-of-typedefs-and-use-them.patch b/SOURCES/libvirt-vircgroup-Introduce-standard-set-of-typedefs-and-use-them.patch
new file mode 100644
index 0000000..d57c77a
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-Introduce-standard-set-of-typedefs-and-use-them.patch
@@ -0,0 +1,72 @@
+From aeec7565df4f246c937f494c99a8d2d1ff03168d Mon Sep 17 00:00:00 2001
+Message-Id: <aeec7565df4f246c937f494c99a8d2d1ff03168d@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:05:49 +0200
+Subject: [PATCH] vircgroup: Introduce standard set of typedefs and use them
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit cd77242504c8f3ba8d4ff7d1a7d4234f0aa5ede3)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <7e482b4826c05db78d1136bfa6091ab5d3097f47.1561993099.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c     | 2 +-
+ src/util/vircgroup.h     | 3 ++-
+ src/util/vircgrouppriv.h | 4 +++-
+ 3 files changed, 6 insertions(+), 3 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index 7602641713..5144b33d43 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -385,7 +385,7 @@ virCgroupDetectMountsFromFile(virCgroupPtr group,
+             const char *typestr = virCgroupControllerTypeToString(i);
+             int typelen = strlen(typestr);
+             char *tmp = entry.mnt_opts;
+-            struct _virCgroupController *controller = &group->controllers[i];
++            virCgroupControllerPtr controller = &group->controllers[i];
+             while (tmp) {
+                 char *next = strchr(tmp, ',');
+                 int len;
+diff --git a/src/util/vircgroup.h b/src/util/vircgroup.h
+index cfa69b67cb..af93316197 100644
+--- a/src/util/vircgroup.h
++++ b/src/util/vircgroup.h
+@@ -29,7 +29,8 @@
+ # include "virbitmap.h"
+ 
+ struct _virCgroup;
+-typedef struct _virCgroup *virCgroupPtr;
++typedef struct _virCgroup virCgroup;
++typedef virCgroup *virCgroupPtr;
+ 
+ enum {
+     VIR_CGROUP_CONTROLLER_CPU,
+diff --git a/src/util/vircgrouppriv.h b/src/util/vircgrouppriv.h
+index 71788639d6..1b47d3b858 100644
+--- a/src/util/vircgrouppriv.h
++++ b/src/util/vircgrouppriv.h
+@@ -41,11 +41,13 @@ struct _virCgroupController {
+     char *linkPoint;
+     char *placement;
+ };
++typedef struct _virCgroupController virCgroupController;
++typedef virCgroupController *virCgroupControllerPtr;
+ 
+ struct _virCgroup {
+     char *path;
+ 
+-    struct _virCgroupController controllers[VIR_CGROUP_CONTROLLER_LAST];
++    virCgroupController controllers[VIR_CGROUP_CONTROLLER_LAST];
+ };
+ 
+ int virCgroupDetectMountsFromFile(virCgroupPtr group,
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-Introduce-virCgroupEnableMissingControllers.patch b/SOURCES/libvirt-vircgroup-Introduce-virCgroupEnableMissingControllers.patch
new file mode 100644
index 0000000..fa468a2
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-Introduce-virCgroupEnableMissingControllers.patch
@@ -0,0 +1,185 @@
+From cef7b5074c5638c67828d44357809fae84354000 Mon Sep 17 00:00:00 2001
+Message-Id: <cef7b5074c5638c67828d44357809fae84354000@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:05:58 +0200
+Subject: [PATCH] vircgroup: Introduce virCgroupEnableMissingControllers
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit fc221c053ba3a0f5b9ce609936e010180bbda64f)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <c00a45e34f017f784f46831dba6275942f973bd8.1561993099.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c | 127 ++++++++++++++++++++++++-------------------
+ 1 file changed, 70 insertions(+), 57 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index 7888dab716..a2c971fbf4 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -1494,68 +1494,22 @@ virCgroupNewDetectMachine(const char *name,
+ }
+ 
+ 
+-/*
+- * Returns 0 on success, -1 on fatal error, -2 on systemd not available
+- */
+ static int
+-virCgroupNewMachineSystemd(const char *name,
+-                           const char *drivername,
+-                           const unsigned char *uuid,
+-                           const char *rootdir,
+-                           pid_t pidleader,
+-                           bool isContainer,
+-                           size_t nnicindexes,
+-                           int *nicindexes,
+-                           const char *partition,
+-                           int controllers,
+-                           virCgroupPtr *group)
++virCgroupEnableMissingControllers(char *path,
++                                  pid_t pidleader,
++                                  int controllers,
++                                  virCgroupPtr *group)
+ {
++    virCgroupPtr parent = NULL;
++    char *offset = path;
+     int ret = -1;
+-    int rv;
+-    virCgroupPtr init, parent = NULL;
+-    VIR_AUTOFREE(char *) path = NULL;
+-    char *offset;
+-
+-    VIR_DEBUG("Trying to setup machine '%s' via systemd", name);
+-    if ((rv = virSystemdCreateMachine(name,
+-                                      drivername,
+-                                      uuid,
+-                                      rootdir,
+-                                      pidleader,
+-                                      isContainer,
+-                                      nnicindexes,
+-                                      nicindexes,
+-                                      partition)) < 0)
+-        return rv;
+-
+-    if (controllers != -1)
+-        controllers |= (1 << VIR_CGROUP_CONTROLLER_SYSTEMD);
+-
+-    VIR_DEBUG("Detecting systemd placement");
+-    if (virCgroupNewDetect(pidleader,
+-                           controllers,
+-                           &init) < 0)
+-        return -1;
+-
+-    path = init->controllers[VIR_CGROUP_CONTROLLER_SYSTEMD].placement;
+-    init->controllers[VIR_CGROUP_CONTROLLER_SYSTEMD].placement = NULL;
+-    virCgroupFree(&init);
+-
+-    if (!path || STREQ(path, "/") || path[0] != '/') {
+-        VIR_DEBUG("Systemd didn't setup its controller");
+-        ret = -2;
+-        goto cleanup;
+-    }
+-
+-    offset = path;
+ 
+     if (virCgroupNew(pidleader,
+                      "",
+                      NULL,
+                      controllers,
+                      &parent) < 0)
+-        goto cleanup;
+-
++        return ret;
+ 
+     for (;;) {
+         virCgroupPtr tmp;
+@@ -1585,6 +1539,68 @@ virCgroupNewMachineSystemd(const char *name,
+         }
+     }
+ 
++    ret = 0;
++ cleanup:
++    virCgroupFree(&parent);
++    return ret;
++}
++
++
++/*
++ * Returns 0 on success, -1 on fatal error, -2 on systemd not available
++ */
++static int
++virCgroupNewMachineSystemd(const char *name,
++                           const char *drivername,
++                           const unsigned char *uuid,
++                           const char *rootdir,
++                           pid_t pidleader,
++                           bool isContainer,
++                           size_t nnicindexes,
++                           int *nicindexes,
++                           const char *partition,
++                           int controllers,
++                           virCgroupPtr *group)
++{
++    int rv;
++    virCgroupPtr init;
++    VIR_AUTOFREE(char *) path = NULL;
++
++    VIR_DEBUG("Trying to setup machine '%s' via systemd", name);
++    if ((rv = virSystemdCreateMachine(name,
++                                      drivername,
++                                      uuid,
++                                      rootdir,
++                                      pidleader,
++                                      isContainer,
++                                      nnicindexes,
++                                      nicindexes,
++                                      partition)) < 0)
++        return rv;
++
++    if (controllers != -1)
++        controllers |= (1 << VIR_CGROUP_CONTROLLER_SYSTEMD);
++
++    VIR_DEBUG("Detecting systemd placement");
++    if (virCgroupNewDetect(pidleader,
++                           controllers,
++                           &init) < 0)
++        return -1;
++
++    path = init->controllers[VIR_CGROUP_CONTROLLER_SYSTEMD].placement;
++    init->controllers[VIR_CGROUP_CONTROLLER_SYSTEMD].placement = NULL;
++    virCgroupFree(&init);
++
++    if (!path || STREQ(path, "/") || path[0] != '/') {
++        VIR_DEBUG("Systemd didn't setup its controller");
++        return -2;
++    }
++
++    if (virCgroupEnableMissingControllers(path, pidleader,
++                                          controllers, group) < 0) {
++        return -1;
++    }
++
+     if (virCgroupAddTask(*group, pidleader) < 0) {
+         virErrorPtr saved = virSaveLastError();
+         virCgroupRemove(*group);
+@@ -1595,10 +1611,7 @@ virCgroupNewMachineSystemd(const char *name,
+         }
+     }
+ 
+-    ret = 0;
+- cleanup:
+-    virCgroupFree(&parent);
+-    return ret;
++    return 0;
+ }
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-Introduce-virCgroupGetMemoryStat.patch b/SOURCES/libvirt-vircgroup-Introduce-virCgroupGetMemoryStat.patch
new file mode 100644
index 0000000..903d5ac
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-Introduce-virCgroupGetMemoryStat.patch
@@ -0,0 +1,155 @@
+From d91df2c6090f79ef0135f2240181b8dbf87597b0 Mon Sep 17 00:00:00 2001
+Message-Id: <d91df2c6090f79ef0135f2240181b8dbf87597b0@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:06:01 +0200
+Subject: [PATCH] vircgroup: Introduce virCgroupGetMemoryStat
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 901d2b9c8716f2717439d5843cab412ab8d7b247)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <b70cd9890f218f943b094bc6b040867c6d69bc6b.1561993099.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/libvirt_private.syms |  1 +
+ src/util/vircgroup.c     | 88 ++++++++++++++++++++++++++++++++++++++++
+ src/util/vircgroup.h     |  7 ++++
+ 3 files changed, 96 insertions(+)
+
+diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
+index 47695eb507..2ec9d8f4bf 100644
+--- a/src/libvirt_private.syms
++++ b/src/libvirt_private.syms
+@@ -1551,6 +1551,7 @@ virCgroupGetDomainTotalCpuStats;
+ virCgroupGetFreezerState;
+ virCgroupGetMemoryHardLimit;
+ virCgroupGetMemorySoftLimit;
++virCgroupGetMemoryStat;
+ virCgroupGetMemoryUsage;
+ virCgroupGetMemSwapHardLimit;
+ virCgroupGetMemSwapUsage;
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index a94f958d75..0ed83932ac 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -2427,6 +2427,94 @@ virCgroupSetMemory(virCgroupPtr group, unsigned long long kb)
+ }
+ 
+ 
++/**
++ * virCgroupGetMemoryStat:
++ *
++ * @group: The cgroup to change memory for
++ * @cache: page cache memory in KiB
++ * @activeAnon: anonymous and swap cache memory in KiB
++ * @inactiveAnon: anonymous and swap cache memory in KiB
++ * @activeFile: file-backed memory in KiB
++ * @inactiveFile: file-backed memory in KiB
++ * @unevictable: memory that cannot be reclaimed KiB
++ *
++ * Returns: 0 on success, -1 on error
++ */
++int
++virCgroupGetMemoryStat(virCgroupPtr group,
++                       unsigned long long *cache,
++                       unsigned long long *activeAnon,
++                       unsigned long long *inactiveAnon,
++                       unsigned long long *activeFile,
++                       unsigned long long *inactiveFile,
++                       unsigned long long *unevictable)
++{
++    int ret = -1;
++    char *stat = NULL;
++    char *line = NULL;
++    unsigned long long cacheVal = 0;
++    unsigned long long activeAnonVal = 0;
++    unsigned long long inactiveAnonVal = 0;
++    unsigned long long activeFileVal = 0;
++    unsigned long long inactiveFileVal = 0;
++    unsigned long long unevictableVal = 0;
++
++    if (virCgroupGetValueStr(group,
++                             VIR_CGROUP_CONTROLLER_MEMORY,
++                             "memory.stat",
++                             &stat) < 0) {
++        return -1;
++    }
++
++    line = stat;
++
++    while (line) {
++        char *newLine = strchr(line, '\n');
++        char *valueStr = strchr(line, ' ');
++        unsigned long long value;
++
++        if (newLine)
++            *newLine = '\0';
++
++        if (!valueStr) {
++            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
++                           _("Cannot parse 'memory.stat' cgroup file."));
++            goto cleanup;
++        }
++        *valueStr = '\0';
++
++        if (virStrToLong_ull(valueStr + 1, NULL, 10, &value) < 0)
++            goto cleanup;
++
++        if (STREQ(line, "cache"))
++            cacheVal = value >> 10;
++        else if (STREQ(line, "active_anon"))
++            activeAnonVal = value >> 10;
++        else if (STREQ(line, "inactive_anon"))
++            inactiveAnonVal = value >> 10;
++        else if (STREQ(line, "active_file"))
++            activeFileVal = value >> 10;
++        else if (STREQ(line, "inactive_file"))
++            inactiveFileVal = value >> 10;
++        else if (STREQ(line, "unevictable"))
++            unevictableVal = value >> 10;
++    }
++
++    *cache = cacheVal;
++    *activeAnon = activeAnonVal;
++    *inactiveAnon = inactiveAnonVal;
++    *activeFile = activeFileVal;
++    *inactiveFile = inactiveFileVal;
++    *unevictable = unevictableVal;
++
++    ret = 0;
++
++ cleanup:
++    VIR_FREE(stat);
++    return ret;
++}
++
++
+ /**
+  * virCgroupGetMemoryUsage:
+  *
+diff --git a/src/util/vircgroup.h b/src/util/vircgroup.h
+index 48be077aba..c7fdaaede4 100644
+--- a/src/util/vircgroup.h
++++ b/src/util/vircgroup.h
+@@ -177,6 +177,13 @@ int virCgroupGetBlkioDeviceWriteBps(virCgroupPtr group,
+                                     unsigned long long *wbps);
+ 
+ int virCgroupSetMemory(virCgroupPtr group, unsigned long long kb);
++int virCgroupGetMemoryStat(virCgroupPtr group,
++                           unsigned long long *cache,
++                           unsigned long long *activeAnon,
++                           unsigned long long *inactiveAnon,
++                           unsigned long long *activeFile,
++                           unsigned long long *inactiveFile,
++                           unsigned long long *unevictable);
+ int virCgroupGetMemoryUsage(virCgroupPtr group, unsigned long *kb);
+ 
+ int virCgroupSetMemoryHardLimit(virCgroupPtr group, unsigned long long kb);
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-Move-function-used-in-tests-into-vircgrouppriv.h.patch b/SOURCES/libvirt-vircgroup-Move-function-used-in-tests-into-vircgrouppriv.h.patch
new file mode 100644
index 0000000..73f8b2d
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-Move-function-used-in-tests-into-vircgrouppriv.h.patch
@@ -0,0 +1,74 @@
+From 0a488720d9702ccedf9e37f639772f67e0180d33 Mon Sep 17 00:00:00 2001
+Message-Id: <0a488720d9702ccedf9e37f639772f67e0180d33@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:05:54 +0200
+Subject: [PATCH] vircgroup: Move function used in tests into vircgrouppriv.h
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 8ea2d5a6cbe9d14f30ffb8dbe0922945f0f490cb)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <2f8afe33e9c7db8173b360eeaac3ae2e2385eda5.1561993099.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.h     | 13 -------------
+ src/util/vircgrouppriv.h | 13 +++++++++++++
+ 2 files changed, 13 insertions(+), 13 deletions(-)
+
+diff --git a/src/util/vircgroup.h b/src/util/vircgroup.h
+index 138bb3c076..48be077aba 100644
+--- a/src/util/vircgroup.h
++++ b/src/util/vircgroup.h
+@@ -64,22 +64,9 @@ typedef enum {
+ 
+ bool virCgroupAvailable(void);
+ 
+-int virCgroupNewPartition(const char *path,
+-                          bool create,
+-                          int controllers,
+-                          virCgroupPtr *group)
+-    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(4);
+-
+ int virCgroupNewSelf(virCgroupPtr *group)
+     ATTRIBUTE_NONNULL(1);
+ 
+-int virCgroupNewDomainPartition(virCgroupPtr partition,
+-                                const char *driver,
+-                                const char *name,
+-                                bool create,
+-                                virCgroupPtr *group)
+-    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(5);
+-
+ int virCgroupNewThread(virCgroupPtr domain,
+                        virCgroupThreadName nameval,
+                        int id,
+diff --git a/src/util/vircgrouppriv.h b/src/util/vircgrouppriv.h
+index 1b47d3b858..a0034f3889 100644
+--- a/src/util/vircgrouppriv.h
++++ b/src/util/vircgrouppriv.h
+@@ -54,4 +54,17 @@ int virCgroupDetectMountsFromFile(virCgroupPtr group,
+                                   const char *path,
+                                   bool checkLinks);
+ 
++int virCgroupNewPartition(const char *path,
++                          bool create,
++                          int controllers,
++                          virCgroupPtr *group)
++    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(4);
++
++int virCgroupNewDomainPartition(virCgroupPtr partition,
++                                const char *driver,
++                                const char *name,
++                                bool create,
++                                virCgroupPtr *group)
++    ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(5);
++
+ #endif /* __VIR_CGROUP_PRIV_H__ */
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-Remove-obsolete-sa_assert.patch b/SOURCES/libvirt-vircgroup-Remove-obsolete-sa_assert.patch
new file mode 100644
index 0000000..5dca2d2
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-Remove-obsolete-sa_assert.patch
@@ -0,0 +1,40 @@
+From 45fd4b2e1b694ca15bfd124f6b5e24e79a670a47 Mon Sep 17 00:00:00 2001
+Message-Id: <45fd4b2e1b694ca15bfd124f6b5e24e79a670a47@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:06:10 +0200
+Subject: [PATCH] vircgroup: Remove obsolete sa_assert
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit b14b88b74c10c9e20f87218c5994681fc35c2c57)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <3e004259ee462b47a9e1069ac2f4e9d67a914f6e.1561993099.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c | 4 ----
+ 1 file changed, 4 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index 02de33f74f..64507bf8aa 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -1054,10 +1054,6 @@ virCgroupMakeGroup(virCgroupPtr parent,
+         if (virCgroupPathOfController(group, i, "", &path) < 0)
+             goto error;
+ 
+-        /* As of Feb 2011, clang can't see that the above function
+-         * call did not modify group. */
+-        sa_assert(group->controllers[i].mountPoint);
+-
+         VIR_DEBUG("Make controller %s", path);
+         if (!virFileExists(path)) {
+             if (!create ||
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-Remove-pointless-bool-parameter.patch b/SOURCES/libvirt-vircgroup-Remove-pointless-bool-parameter.patch
new file mode 100644
index 0000000..675d861
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-Remove-pointless-bool-parameter.patch
@@ -0,0 +1,60 @@
+From 7191b04edf95dd3180657ec45aec17c80dfdf083 Mon Sep 17 00:00:00 2001
+Message-Id: <7191b04edf95dd3180657ec45aec17c80dfdf083@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:05:55 +0200
+Subject: [PATCH] vircgroup: Remove pointless bool parameter
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 0490a74aa11a2d993c50da266b8c2234c5a447ca)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <19e5a131d50721e94d43b37e139dda8dd9994df3.1561993099.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c | 11 ++++-------
+ 1 file changed, 4 insertions(+), 7 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index 7d8bf3419a..9032bcbb63 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -251,7 +251,6 @@ static bool
+ virCgroupValidateMachineGroup(virCgroupPtr group,
+                               const char *name,
+                               const char *drivername,
+-                              bool stripEmulatorSuffix,
+                               const char *machinename)
+ {
+     size_t i;
+@@ -303,10 +302,9 @@ virCgroupValidateMachineGroup(virCgroupPtr group,
+         if (!tmp)
+             return false;
+ 
+-        if (stripEmulatorSuffix &&
+-            (i == VIR_CGROUP_CONTROLLER_CPU ||
+-             i == VIR_CGROUP_CONTROLLER_CPUACCT ||
+-             i == VIR_CGROUP_CONTROLLER_CPUSET)) {
++        if (i == VIR_CGROUP_CONTROLLER_CPU ||
++            i == VIR_CGROUP_CONTROLLER_CPUACCT ||
++            i == VIR_CGROUP_CONTROLLER_CPUSET) {
+             if (STREQ(tmp, "/emulator"))
+                 *tmp = '\0';
+             tmp = strrchr(group->controllers[i].placement, '/');
+@@ -1486,8 +1484,7 @@ virCgroupNewDetectMachine(const char *name,
+         return -1;
+     }
+ 
+-    if (!virCgroupValidateMachineGroup(*group, name, drivername,
+-                                       true, machinename)) {
++    if (!virCgroupValidateMachineGroup(*group, name, drivername, machinename)) {
+         VIR_DEBUG("Failed to validate machine name for '%s' driver '%s'",
+                   name, drivername);
+         virCgroupFree(group);
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-Remove-unused-function-virCgroupKill.patch b/SOURCES/libvirt-vircgroup-Remove-unused-function-virCgroupKill.patch
new file mode 100644
index 0000000..eb61496
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-Remove-unused-function-virCgroupKill.patch
@@ -0,0 +1,105 @@
+From a4ed662c80b9241f4bc599fded59ace585db25c9 Mon Sep 17 00:00:00 2001
+Message-Id: <a4ed662c80b9241f4bc599fded59ace585db25c9@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:05:51 +0200
+Subject: [PATCH] vircgroup: Remove unused function virCgroupKill()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit c8b1ae607d638b958dc51ba2041bd87ea72683de)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <9f04fae641e673c68253864c858e2123c2252296.1561993099.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/libvirt_private.syms |  1 -
+ src/util/vircgroup.c     | 37 -------------------------------------
+ src/util/vircgroup.h     |  1 -
+ 3 files changed, 39 deletions(-)
+
+diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
+index f158a17b49..3117c8009a 100644
+--- a/src/libvirt_private.syms
++++ b/src/libvirt_private.syms
+@@ -1558,7 +1558,6 @@ virCgroupGetMemSwapUsage;
+ virCgroupGetPercpuStats;
+ virCgroupHasController;
+ virCgroupHasEmptyTasks;
+-virCgroupKill;
+ virCgroupKillPainfully;
+ virCgroupKillRecursive;
+ virCgroupNewDetect;
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index 8ddedbfe7c..5f949edec8 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -3510,33 +3510,6 @@ virCgroupPidCopy(const void *name)
+ }
+ 
+ 
+-/*
+- * Returns 1 if some PIDs are killed, 0 if none are killed, or -1 on error
+- */
+-int
+-virCgroupKill(virCgroupPtr group, int signum)
+-{
+-    VIR_DEBUG("group=%p path=%s signum=%d", group, group->path, signum);
+-    int ret;
+-    /* The 'tasks' file in cgroups can contain duplicated
+-     * pids, so we use a hash to track which we've already
+-     * killed.
+-     */
+-    virHashTablePtr pids = virHashCreateFull(100,
+-                                             NULL,
+-                                             virCgroupPidCode,
+-                                             virCgroupPidEqual,
+-                                             virCgroupPidCopy,
+-                                             NULL);
+-
+-    ret = virCgroupKillInternal(group, signum, pids);
+-
+-    virHashFree(pids);
+-
+-    return ret;
+-}
+-
+-
+ static int
+ virCgroupKillRecursiveInternal(virCgroupPtr group,
+                                int signum,
+@@ -4585,16 +4558,6 @@ virCgroupRemove(virCgroupPtr group ATTRIBUTE_UNUSED)
+ }
+ 
+ 
+-int
+-virCgroupKill(virCgroupPtr group ATTRIBUTE_UNUSED,
+-              int signum ATTRIBUTE_UNUSED)
+-{
+-    virReportSystemError(ENOSYS, "%s",
+-                         _("Control groups not supported on this platform"));
+-    return -1;
+-}
+-
+-
+ int
+ virCgroupKillRecursive(virCgroupPtr group ATTRIBUTE_UNUSED,
+                        int signum ATTRIBUTE_UNUSED)
+diff --git a/src/util/vircgroup.h b/src/util/vircgroup.h
+index af93316197..a23a491d95 100644
+--- a/src/util/vircgroup.h
++++ b/src/util/vircgroup.h
+@@ -280,7 +280,6 @@ int virCgroupGetCpusetCpus(virCgroupPtr group, char **cpus);
+ int virCgroupRemoveRecursively(char *grppath);
+ int virCgroupRemove(virCgroupPtr group);
+ 
+-int virCgroupKill(virCgroupPtr group, int signum);
+ int virCgroupKillRecursive(virCgroupPtr group, int signum);
+ int virCgroupKillPainfully(virCgroupPtr group);
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-Remove-virCgroupAddTaskController.patch b/SOURCES/libvirt-vircgroup-Remove-virCgroupAddTaskController.patch
new file mode 100644
index 0000000..ed026fa
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-Remove-virCgroupAddTaskController.patch
@@ -0,0 +1,76 @@
+From 88322908f3dfad6217b1c2a2a0f8968b079d0795 Mon Sep 17 00:00:00 2001
+Message-Id: <88322908f3dfad6217b1c2a2a0f8968b079d0795@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:06:00 +0200
+Subject: [PATCH] vircgroup: Remove virCgroupAddTaskController
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+There is no need for this function, both of the checks are done
+later by virCgroupGetControllerPath.
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit db868852fdb32c76955c925dcbd92b2d6d9bfeb2)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <b6c7c27ed52a39343d7d0f14feab71726ff0c279.1561993099.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c | 31 +------------------------------
+ 1 file changed, 1 insertion(+), 30 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index 5adf9d3c11..a94f958d75 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -1128,35 +1128,6 @@ virCgroupNew(pid_t pid,
+ }
+ 
+ 
+-/**
+- * virCgroupAddTaskController:
+- *
+- * @group: The cgroup to add a task to
+- * @pid: The pid of the task to add
+- * @controller: The cgroup controller to be operated on
+- *
+- * Returns: 0 on success or -1 on error
+- */
+-static int
+-virCgroupAddTaskController(virCgroupPtr group, pid_t pid, int controller)
+-{
+-    if (controller < 0 || controller >= VIR_CGROUP_CONTROLLER_LAST) {
+-        virReportError(VIR_ERR_INTERNAL_ERROR,
+-                       _("Controller %d out of range"), controller);
+-        return -1;
+-    }
+-
+-    if (!group->controllers[controller].mountPoint) {
+-        virReportError(VIR_ERR_INTERNAL_ERROR,
+-                       _("Controller '%s' not mounted"),
+-                       virCgroupControllerTypeToString(controller));
+-        return -1;
+-    }
+-
+-    return virCgroupSetValueI64(group, controller, "tasks", pid);
+-}
+-
+-
+ static int
+ virCgroupAddTaskInternal(virCgroupPtr group, pid_t pid, bool withSystemd)
+ {
+@@ -1174,7 +1145,7 @@ virCgroupAddTaskInternal(virCgroupPtr group, pid_t pid, bool withSystemd)
+         if (i == VIR_CGROUP_CONTROLLER_SYSTEMD && !withSystemd)
+             continue;
+ 
+-        if (virCgroupAddTaskController(group, pid, i) < 0)
++        if (virCgroupSetValueI64(group, i, "tasks", pid) < 0)
+             goto cleanup;
+     }
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-Rename-structs-to-start-with-underscore.patch b/SOURCES/libvirt-vircgroup-Rename-structs-to-start-with-underscore.patch
new file mode 100644
index 0000000..870aba6
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-Rename-structs-to-start-with-underscore.patch
@@ -0,0 +1,80 @@
+From b47ae363dedecaf569906aa3a1349f6e32f4b520 Mon Sep 17 00:00:00 2001
+Message-Id: <b47ae363dedecaf569906aa3a1349f6e32f4b520@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:05:48 +0200
+Subject: [PATCH] vircgroup: Rename structs to start with underscore
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 70dc671a276ba90099bd1c8ba05e450f092244ff)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <49ff9517362f541da5580fe9acc132319872e732.1561993099.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c     | 2 +-
+ src/util/vircgroup.h     | 4 ++--
+ src/util/vircgrouppriv.h | 6 +++---
+ 3 files changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index 6bf4e88da1..7602641713 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -385,7 +385,7 @@ virCgroupDetectMountsFromFile(virCgroupPtr group,
+             const char *typestr = virCgroupControllerTypeToString(i);
+             int typelen = strlen(typestr);
+             char *tmp = entry.mnt_opts;
+-            struct virCgroupController *controller = &group->controllers[i];
++            struct _virCgroupController *controller = &group->controllers[i];
+             while (tmp) {
+                 char *next = strchr(tmp, ',');
+                 int len;
+diff --git a/src/util/vircgroup.h b/src/util/vircgroup.h
+index d833927678..cfa69b67cb 100644
+--- a/src/util/vircgroup.h
++++ b/src/util/vircgroup.h
+@@ -28,8 +28,8 @@
+ # include "virutil.h"
+ # include "virbitmap.h"
+ 
+-struct virCgroup;
+-typedef struct virCgroup *virCgroupPtr;
++struct _virCgroup;
++typedef struct _virCgroup *virCgroupPtr;
+ 
+ enum {
+     VIR_CGROUP_CONTROLLER_CPU,
+diff --git a/src/util/vircgrouppriv.h b/src/util/vircgrouppriv.h
+index 722863e5b6..71788639d6 100644
+--- a/src/util/vircgrouppriv.h
++++ b/src/util/vircgrouppriv.h
+@@ -31,7 +31,7 @@
+ 
+ # include "vircgroup.h"
+ 
+-struct virCgroupController {
++struct _virCgroupController {
+     int type;
+     char *mountPoint;
+     /* If mountPoint holds several controllers co-mounted,
+@@ -42,10 +42,10 @@ struct virCgroupController {
+     char *placement;
+ };
+ 
+-struct virCgroup {
++struct _virCgroup {
+     char *path;
+ 
+-    struct virCgroupController controllers[VIR_CGROUP_CONTROLLER_LAST];
++    struct _virCgroupController controllers[VIR_CGROUP_CONTROLLER_LAST];
+ };
+ 
+ int virCgroupDetectMountsFromFile(virCgroupPtr group,
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-Simplify-if-conditions-in-virCgroupMakeGroup.patch b/SOURCES/libvirt-vircgroup-Simplify-if-conditions-in-virCgroupMakeGroup.patch
new file mode 100644
index 0000000..27c69fb
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-Simplify-if-conditions-in-virCgroupMakeGroup.patch
@@ -0,0 +1,62 @@
+From af1714ac39a383b8a8fb0bc577fbe5e85fd8be10 Mon Sep 17 00:00:00 2001
+Message-Id: <af1714ac39a383b8a8fb0bc577fbe5e85fd8be10@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:06:09 +0200
+Subject: [PATCH] vircgroup: Simplify if conditions in virCgroupMakeGroup
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 0ec8416f04460f3bbf7907231b28028c3daed7e7)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <b6f7814df6e28a2b68e07c0eb490bda3f340ab7c.1561993099.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c | 20 ++++++++------------
+ 1 file changed, 8 insertions(+), 12 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index dde9ed21a2..02de33f74f 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -1079,24 +1079,20 @@ virCgroupMakeGroup(virCgroupPtr parent,
+                     goto error;
+                 }
+             }
+-            if (group->controllers[VIR_CGROUP_CONTROLLER_CPUSET].mountPoint != NULL &&
+-                (i == VIR_CGROUP_CONTROLLER_CPUSET ||
+-                 STREQ(group->controllers[i].mountPoint,
+-                       group->controllers[VIR_CGROUP_CONTROLLER_CPUSET].mountPoint))) {
+-                if (virCgroupCpuSetInherit(parent, group) < 0)
+-                    goto error;
++            if (i == VIR_CGROUP_CONTROLLER_CPUSET &&
++                group->controllers[i].mountPoint != NULL &&
++                virCgroupCpuSetInherit(parent, group) < 0) {
++                goto error;
+             }
+             /*
+              * Note that virCgroupSetMemoryUseHierarchy should always be
+              * called prior to creating subcgroups and attaching tasks.
+              */
+             if ((flags & VIR_CGROUP_MEM_HIERACHY) &&
+-                (group->controllers[VIR_CGROUP_CONTROLLER_MEMORY].mountPoint != NULL) &&
+-                (i == VIR_CGROUP_CONTROLLER_MEMORY ||
+-                 STREQ(group->controllers[i].mountPoint,
+-                       group->controllers[VIR_CGROUP_CONTROLLER_MEMORY].mountPoint))) {
+-                if (virCgroupSetMemoryUseHierarchy(group) < 0)
+-                    goto error;
++                i == VIR_CGROUP_CONTROLLER_MEMORY &&
++                group->controllers[i].mountPoint != NULL &&
++                virCgroupSetMemoryUseHierarchy(group) < 0) {
++                goto error;
+             }
+         }
+     }
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-Split-virCgroupPathOfController-into-two-functions.patch b/SOURCES/libvirt-vircgroup-Split-virCgroupPathOfController-into-two-functions.patch
new file mode 100644
index 0000000..6ec3520
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-Split-virCgroupPathOfController-into-two-functions.patch
@@ -0,0 +1,138 @@
+From 51e0205bf57346f381143b498cfe0a77852a8da1 Mon Sep 17 00:00:00 2001
+Message-Id: <51e0205bf57346f381143b498cfe0a77852a8da1@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:06:07 +0200
+Subject: [PATCH] vircgroup: Split virCgroupPathOfController into two functions
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The case where we need path of any controller is only for internal use
+so move it out to a different function.
+
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 998658bd1ebdc5fd9ec43131c381cece1a3893cf)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <7578336183563ecf49d686f6705724db25037191.1561993099.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c | 54 ++++++++++++++++++++++++++------------------
+ src/util/vircgroup.h |  2 +-
+ 2 files changed, 33 insertions(+), 23 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index 2bc4febf23..8646a4a479 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -1772,28 +1772,13 @@ virCgroupHasController(virCgroupPtr cgroup, int controller)
+ 
+ int
+ virCgroupPathOfController(virCgroupPtr group,
+-                          int controller,
++                          unsigned int controller,
+                           const char *key,
+                           char **path)
+ {
+-    if (controller == -1) {
+-        size_t i;
+-        for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
+-            /* Reject any controller with a placement
+-             * of '/' to avoid doing bad stuff to the root
+-             * cgroup
+-             */
+-            if (group->controllers[i].mountPoint &&
+-                group->controllers[i].placement &&
+-                STRNEQ(group->controllers[i].placement, "/")) {
+-                controller = i;
+-                break;
+-            }
+-        }
+-    }
+-    if (controller == -1) {
+-        virReportSystemError(ENOSYS, "%s",
+-                             _("No controllers are mounted"));
++    if (controller >= VIR_CGROUP_CONTROLLER_LAST) {
++        virReportError(VIR_ERR_INTERNAL_ERROR,
++                       _("Invalid controller id '%d'"), controller);
+         return -1;
+     }
+ 
+@@ -3505,6 +3490,31 @@ virCgroupRemove(virCgroupPtr group)
+ }
+ 
+ 
++static int
++virCgroupPathOfAnyController(virCgroupPtr group,
++                             const char *name,
++                             char **keypath)
++{
++    size_t i;
++
++    for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
++        /* Reject any controller with a placement
++         * of '/' to avoid doing bad stuff to the root
++         * cgroup
++         */
++        if (group->controllers[i].mountPoint &&
++            group->controllers[i].placement &&
++            STRNEQ(group->controllers[i].placement, "/")) {
++            return virCgroupPathOfController(group, i, name, keypath);
++        }
++    }
++
++    virReportSystemError(ENOSYS, "%s",
++                         _("No controllers are mounted"));
++    return -1;
++}
++
++
+ /*
+  * Returns 1 if some PIDs are killed, 0 if none are killed, or -1 on error
+  */
+@@ -3519,7 +3529,7 @@ virCgroupKillInternal(virCgroupPtr group, int signum, virHashTablePtr pids)
+     VIR_DEBUG("group=%p path=%s signum=%d pids=%p",
+               group, group->path, signum, pids);
+ 
+-    if (virCgroupPathOfController(group, -1, "tasks", &keypath) < 0)
++    if (virCgroupPathOfAnyController(group, "tasks", &keypath) < 0)
+         return -1;
+ 
+     /* PIDs may be forking as we kill them, so loop
+@@ -3622,7 +3632,7 @@ virCgroupKillRecursiveInternal(virCgroupPtr group,
+     VIR_DEBUG("group=%p path=%s signum=%d pids=%p",
+               group, group->path, signum, pids);
+ 
+-    if (virCgroupPathOfController(group, -1, "", &keypath) < 0)
++    if (virCgroupPathOfAnyController(group, "", &keypath) < 0)
+         return -1;
+ 
+     if ((rc = virCgroupKillInternal(group, signum, pids)) < 0)
+@@ -4180,7 +4190,7 @@ virCgroupHasController(virCgroupPtr cgroup ATTRIBUTE_UNUSED,
+ 
+ int
+ virCgroupPathOfController(virCgroupPtr group ATTRIBUTE_UNUSED,
+-                          int controller ATTRIBUTE_UNUSED,
++                          unsigned int controller ATTRIBUTE_UNUSED,
+                           const char *key ATTRIBUTE_UNUSED,
+                           char **path ATTRIBUTE_UNUSED)
+ {
+diff --git a/src/util/vircgroup.h b/src/util/vircgroup.h
+index c7fdaaede4..ee3b7c7222 100644
+--- a/src/util/vircgroup.h
++++ b/src/util/vircgroup.h
+@@ -114,7 +114,7 @@ void virCgroupFree(virCgroupPtr *group);
+ 
+ bool virCgroupHasController(virCgroupPtr cgroup, int controller);
+ int virCgroupPathOfController(virCgroupPtr group,
+-                              int controller,
++                              unsigned int controller,
+                               const char *key,
+                               char **path);
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-Unexport-unused-function-virCgroupAddTaskController.patch b/SOURCES/libvirt-vircgroup-Unexport-unused-function-virCgroupAddTaskController.patch
new file mode 100644
index 0000000..509f992
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-Unexport-unused-function-virCgroupAddTaskController.patch
@@ -0,0 +1,148 @@
+From 7dd9c146f4713fd15b6d6642b910af29846d96e2 Mon Sep 17 00:00:00 2001
+Message-Id: <7dd9c146f4713fd15b6d6642b910af29846d96e2@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:05:52 +0200
+Subject: [PATCH] vircgroup: Unexport unused function
+ virCgroupAddTaskController()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 0aaac42a6eb3fb8b5aa412d5153e0d6ae459c631)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <30f7f52a9e7d0b9ce838a2d32cc6ec0a0cf97788.1561993099.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/libvirt_private.syms |  1 -
+ src/util/vircgroup.c     | 69 +++++++++++++++++-----------------------
+ src/util/vircgroup.h     |  4 ---
+ 3 files changed, 29 insertions(+), 45 deletions(-)
+
+diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
+index 3117c8009a..41fca88d09 100644
+--- a/src/libvirt_private.syms
++++ b/src/libvirt_private.syms
+@@ -1515,7 +1515,6 @@ virBufferVasprintf;
+ # util/vircgroup.h
+ virCgroupAddMachineTask;
+ virCgroupAddTask;
+-virCgroupAddTaskController;
+ virCgroupAllowAllDevices;
+ virCgroupAllowDevice;
+ virCgroupAllowDevicePath;
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index 5f949edec8..8ef6fb5e1a 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -1136,6 +1136,35 @@ virCgroupNew(pid_t pid,
+ }
+ 
+ 
++/**
++ * virCgroupAddTaskController:
++ *
++ * @group: The cgroup to add a task to
++ * @pid: The pid of the task to add
++ * @controller: The cgroup controller to be operated on
++ *
++ * Returns: 0 on success or -1 on error
++ */
++static int
++virCgroupAddTaskController(virCgroupPtr group, pid_t pid, int controller)
++{
++    if (controller < 0 || controller >= VIR_CGROUP_CONTROLLER_LAST) {
++        virReportError(VIR_ERR_INTERNAL_ERROR,
++                       _("Controller %d out of range"), controller);
++        return -1;
++    }
++
++    if (!group->controllers[controller].mountPoint) {
++        virReportError(VIR_ERR_INTERNAL_ERROR,
++                       _("Controller '%s' not mounted"),
++                       virCgroupControllerTypeToString(controller));
++        return -1;
++    }
++
++    return virCgroupSetValueI64(group, controller, "tasks", pid);
++}
++
++
+ static int
+ virCgroupAddTaskInternal(virCgroupPtr group, pid_t pid, bool withSystemd)
+ {
+@@ -1197,35 +1226,6 @@ virCgroupAddMachineTask(virCgroupPtr group, pid_t pid)
+ }
+ 
+ 
+-/**
+- * virCgroupAddTaskController:
+- *
+- * @group: The cgroup to add a task to
+- * @pid: The pid of the task to add
+- * @controller: The cgroup controller to be operated on
+- *
+- * Returns: 0 on success or -1 on error
+- */
+-int
+-virCgroupAddTaskController(virCgroupPtr group, pid_t pid, int controller)
+-{
+-    if (controller < 0 || controller >= VIR_CGROUP_CONTROLLER_LAST) {
+-        virReportError(VIR_ERR_INTERNAL_ERROR,
+-                       _("Controller %d out of range"), controller);
+-        return -1;
+-    }
+-
+-    if (!group->controllers[controller].mountPoint) {
+-        virReportError(VIR_ERR_INTERNAL_ERROR,
+-                       _("Controller '%s' not mounted"),
+-                       virCgroupControllerTypeToString(controller));
+-        return -1;
+-    }
+-
+-    return virCgroupSetValueI64(group, controller, "tasks", pid);
+-}
+-
+-
+ static int
+ virCgroupSetPartitionSuffix(const char *path, char **res)
+ {
+@@ -4115,17 +4115,6 @@ virCgroupAddMachineTask(virCgroupPtr group ATTRIBUTE_UNUSED,
+ }
+ 
+ 
+-int
+-virCgroupAddTaskController(virCgroupPtr group ATTRIBUTE_UNUSED,
+-                           pid_t pid ATTRIBUTE_UNUSED,
+-                           int controller ATTRIBUTE_UNUSED)
+-{
+-    virReportSystemError(ENXIO, "%s",
+-                         _("Control groups not supported on this platform"));
+-    return -1;
+-}
+-
+-
+ int
+ virCgroupGetBlkioIoServiced(virCgroupPtr group ATTRIBUTE_UNUSED,
+                             long long *bytes_read ATTRIBUTE_UNUSED,
+diff --git a/src/util/vircgroup.h b/src/util/vircgroup.h
+index a23a491d95..74c7dbcccc 100644
+--- a/src/util/vircgroup.h
++++ b/src/util/vircgroup.h
+@@ -134,10 +134,6 @@ int virCgroupPathOfController(virCgroupPtr group,
+ int virCgroupAddTask(virCgroupPtr group, pid_t pid);
+ int virCgroupAddMachineTask(virCgroupPtr group, pid_t pid);
+ 
+-int virCgroupAddTaskController(virCgroupPtr group,
+-                               pid_t pid,
+-                               int controller);
+-
+ int virCgroupSetBlkioWeight(virCgroupPtr group, unsigned int weight);
+ int virCgroupGetBlkioWeight(virCgroupPtr group, unsigned int *weight);
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-Unexport-unused-function-virCgroupRemoveRecursively.patch b/SOURCES/libvirt-vircgroup-Unexport-unused-function-virCgroupRemoveRecursively.patch
new file mode 100644
index 0000000..efe0168
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-Unexport-unused-function-virCgroupRemoveRecursively.patch
@@ -0,0 +1,80 @@
+From 6ee7a399fe93348c24c4535a2ada43ea67144a22 Mon Sep 17 00:00:00 2001
+Message-Id: <6ee7a399fe93348c24c4535a2ada43ea67144a22@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:05:53 +0200
+Subject: [PATCH] vircgroup: Unexport unused function
+ virCgroupRemoveRecursively
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 32686849fcdc2faca8735869eaa8d5453283a84c)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <0e830b8383a92e496cd492d8b91b26172dd0e667.1561993099.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/libvirt_private.syms |  1 -
+ src/util/vircgroup.c     | 11 +----------
+ src/util/vircgroup.h     |  1 -
+ 3 files changed, 1 insertion(+), 12 deletions(-)
+
+diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
+index 41fca88d09..47695eb507 100644
+--- a/src/libvirt_private.syms
++++ b/src/libvirt_private.syms
+@@ -1569,7 +1569,6 @@ virCgroupNewSelf;
+ virCgroupNewThread;
+ virCgroupPathOfController;
+ virCgroupRemove;
+-virCgroupRemoveRecursively;
+ virCgroupSetBlkioDeviceReadBps;
+ virCgroupSetBlkioDeviceReadIops;
+ virCgroupSetBlkioDeviceWeight;
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index 8ef6fb5e1a..7d8bf3419a 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -3312,7 +3312,7 @@ virCgroupGetCpuacctPercpuUsage(virCgroupPtr group, char **usage)
+ }
+ 
+ 
+-int
++static int
+ virCgroupRemoveRecursively(char *grppath)
+ {
+     DIR *grpdir;
+@@ -4529,15 +4529,6 @@ virCgroupSetCpuCfsQuota(virCgroupPtr group ATTRIBUTE_UNUSED,
+ }
+ 
+ 
+-int
+-virCgroupRemoveRecursively(char *grppath ATTRIBUTE_UNUSED)
+-{
+-    virReportSystemError(ENXIO, "%s",
+-                         _("Control groups not supported on this platform"));
+-    return -1;
+-}
+-
+-
+ int
+ virCgroupRemove(virCgroupPtr group ATTRIBUTE_UNUSED)
+ {
+diff --git a/src/util/vircgroup.h b/src/util/vircgroup.h
+index 74c7dbcccc..138bb3c076 100644
+--- a/src/util/vircgroup.h
++++ b/src/util/vircgroup.h
+@@ -273,7 +273,6 @@ int virCgroupGetCpusetMemoryMigrate(virCgroupPtr group, bool *migrate);
+ int virCgroupSetCpusetCpus(virCgroupPtr group, const char *cpus);
+ int virCgroupGetCpusetCpus(virCgroupPtr group, char **cpus);
+ 
+-int virCgroupRemoveRecursively(char *grppath);
+ int virCgroupRemove(virCgroupPtr group);
+ 
+ int virCgroupKillRecursive(virCgroupPtr group, int signum);
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-Use-virCgroupMountOptsMatchController-in-virCgroupDetectPlacement.patch b/SOURCES/libvirt-vircgroup-Use-virCgroupMountOptsMatchController-in-virCgroupDetectPlacement.patch
new file mode 100644
index 0000000..4e1ce1e
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-Use-virCgroupMountOptsMatchController-in-virCgroupDetectPlacement.patch
@@ -0,0 +1,86 @@
+From dc8f41bf6bb689d86bc91d5aca7fb854a5ef847f Mon Sep 17 00:00:00 2001
+Message-Id: <dc8f41bf6bb689d86bc91d5aca7fb854a5ef847f@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:05:57 +0200
+Subject: [PATCH] vircgroup: Use virCgroupMountOptsMatchController in
+ virCgroupDetectPlacement
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 801d95d2597572612c346508446320a33aebc50d)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <9c2bb230e14ced391b0731bc2964155960025aa5.1561993099.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c | 43 ++++++++++++++-----------------------------
+ 1 file changed, 14 insertions(+), 29 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index ec9994780a..7888dab716 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -598,42 +598,27 @@ virCgroupDetectPlacement(virCgroupPtr group,
+ 
+         for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
+             const char *typestr = virCgroupControllerTypeToString(i);
+-            int typelen = strlen(typestr);
+-            char *tmp = controllers;
+-
+-            while (tmp) {
+-                char *next = strchr(tmp, ',');
+-                int len;
+-                if (next) {
+-                    len = next - tmp;
+-                    next++;
+-                } else {
+-                    len = strlen(tmp);
+-                }
+ 
++            if (virCgroupMountOptsMatchController(controllers, typestr) &&
++                group->controllers[i].mountPoint != NULL &&
++                group->controllers[i].placement == NULL) {
+                 /*
+                  * selfpath == "/" + path="" -> "/"
+                  * selfpath == "/libvirt.service" + path == "" -> "/libvirt.service"
+                  * selfpath == "/libvirt.service" + path == "foo" -> "/libvirt.service/foo"
+                  */
+-                if (typelen == len && STREQLEN(typestr, tmp, len) &&
+-                    group->controllers[i].mountPoint != NULL &&
+-                    group->controllers[i].placement == NULL) {
+-                    if (i == VIR_CGROUP_CONTROLLER_SYSTEMD) {
+-                        if (VIR_STRDUP(group->controllers[i].placement,
+-                                       selfpath) < 0)
+-                            goto cleanup;
+-                    } else {
+-                        if (virAsprintf(&group->controllers[i].placement,
+-                                        "%s%s%s", selfpath,
+-                                        (STREQ(selfpath, "/") ||
+-                                         STREQ(path, "") ? "" : "/"),
+-                                        path) < 0)
+-                            goto cleanup;
+-                    }
++                if (i == VIR_CGROUP_CONTROLLER_SYSTEMD) {
++                    if (VIR_STRDUP(group->controllers[i].placement,
++                                   selfpath) < 0)
++                        goto cleanup;
++                } else {
++                    if (virAsprintf(&group->controllers[i].placement,
++                                    "%s%s%s", selfpath,
++                                    (STREQ(selfpath, "/") ||
++                                     STREQ(path, "") ? "" : "/"),
++                                    path) < 0)
++                        goto cleanup;
+                 }
+-
+-                tmp = next;
+             }
+         }
+     }
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-add-support-for-hybrid-configuration.patch b/SOURCES/libvirt-vircgroup-add-support-for-hybrid-configuration.patch
new file mode 100644
index 0000000..413c5a0
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-add-support-for-hybrid-configuration.patch
@@ -0,0 +1,985 @@
+From 50c5a71ce4a4400d08deff481c8781f3fca755c8 Mon Sep 17 00:00:00 2001
+Message-Id: <50c5a71ce4a4400d08deff481c8781f3fca755c8@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:07:53 +0200
+Subject: [PATCH] vircgroup: add support for hybrid configuration
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This enables to use both cgroup v1 and v2 at the same time together
+with libvirt.  It is supported by kernel and there is valid use-case,
+not all controllers are implemented in cgroup v2 so there might be
+configurations where administrator would enable these missing
+controllers in cgroup v1.
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit b79d858518ed15b1a4271457fc9f39463dd99230)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <c84d8624633d438daa6b4de651eb6bb9e0afa25c.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c        | 351 ++++++++++++++++++++++++++----------
+ src/util/vircgroupbackend.c |  20 ++
+ src/util/vircgroupbackend.h |  16 +-
+ src/util/vircgrouppriv.h    |   2 +-
+ 4 files changed, 291 insertions(+), 98 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index a859628241..069f1ae396 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -232,6 +232,7 @@ virCgroupDetectMounts(virCgroupPtr group)
+     struct mntent entry;
+     char buf[CGROUP_MAX_VAL];
+     int ret = -1;
++    size_t i;
+ 
+     mounts = fopen("/proc/mounts", "r");
+     if (mounts == NULL) {
+@@ -240,11 +241,14 @@ virCgroupDetectMounts(virCgroupPtr group)
+     }
+ 
+     while (getmntent_r(mounts, &entry, buf, sizeof(buf)) != NULL) {
+-        if (group->backend->detectMounts(group,
+-                                         entry.mnt_type,
+-                                         entry.mnt_opts,
+-                                         entry.mnt_dir) < 0) {
+-            goto cleanup;
++        for (i = 0; i < VIR_CGROUP_BACKEND_TYPE_LAST; i++) {
++            if (group->backends[i] &&
++                group->backends[i]->detectMounts(group,
++                                                 entry.mnt_type,
++                                                 entry.mnt_opts,
++                                                 entry.mnt_dir) < 0) {
++                goto cleanup;
++            }
+         }
+     }
+ 
+@@ -307,6 +311,7 @@ virCgroupDetectPlacement(virCgroupPtr group,
+     }
+ 
+     while (fgets(line, sizeof(line), mapping) != NULL) {
++        size_t i;
+         char *controllers = strchr(line, ':');
+         char *selfpath = controllers ? strchr(controllers + 1, ':') : NULL;
+         char *nl = selfpath ? strchr(selfpath, '\n') : NULL;
+@@ -321,9 +326,12 @@ virCgroupDetectPlacement(virCgroupPtr group,
+         controllers++;
+         selfpath++;
+ 
+-        if (group->backend->detectPlacement(group, path, controllers,
+-                                            selfpath) < 0) {
+-            goto cleanup;
++        for (i = 0; i < VIR_CGROUP_BACKEND_TYPE_LAST; i++) {
++            if (group->backends[i] &&
++                group->backends[i]->detectPlacement(group, path, controllers,
++                                                    selfpath) < 0) {
++                goto cleanup;
++            }
+         }
+     }
+ 
+@@ -342,8 +350,9 @@ virCgroupDetect(virCgroupPtr group,
+                 const char *path,
+                 virCgroupPtr parent)
+ {
+-    int rc;
+     size_t i;
++    bool backendAvailable = false;
++    int controllersAvailable = 0;
+     virCgroupBackendPtr *backends = virCgroupBackendGetAll();
+ 
+     VIR_DEBUG("group=%p controllers=%d path=%s parent=%p",
+@@ -354,31 +363,40 @@ virCgroupDetect(virCgroupPtr group,
+ 
+     for (i = 0; i < VIR_CGROUP_BACKEND_TYPE_LAST; i++) {
+         if (backends[i] && backends[i]->available()) {
+-            group->backend = backends[i];
+-            break;
++            group->backends[i] = backends[i];
++            backendAvailable = true;
+         }
+     }
+ 
+-    if (!group->backend) {
++    if (!backendAvailable) {
+         virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                        _("no cgroup backend available"));
+         return -1;
+     }
+ 
+     if (parent) {
+-        if (group->backend->copyMounts(group, parent) < 0)
+-            return -1;
++        for (i = 0; i < VIR_CGROUP_BACKEND_TYPE_LAST; i++) {
++            if (group->backends[i] &&
++                group->backends[i]->copyMounts(group, parent) < 0) {
++                return -1;
++            }
++        }
+     } else {
+         if (virCgroupDetectMounts(group) < 0)
+             return -1;
+     }
+ 
+-    rc = group->backend->detectControllers(group, controllers);
+-    if (rc < 0)
+-        return -1;
++    for (i = 0; i < VIR_CGROUP_BACKEND_TYPE_LAST; i++) {
++        if (group->backends[i]) {
++            int rc = group->backends[i]->detectControllers(group, controllers);
++            if (rc < 0)
++                return -1;
++            controllersAvailable |= rc;
++        }
++    }
+ 
+     /* Check that at least 1 controller is available */
+-    if (rc == 0) {
++    if (controllersAvailable == 0) {
+         virReportSystemError(ENXIO, "%s",
+                              _("At least one cgroup controller is required"));
+         return -1;
+@@ -387,17 +405,26 @@ virCgroupDetect(virCgroupPtr group,
+     /* In some cases we can copy part of the placement info
+      * based on the parent cgroup...
+      */
+-    if ((parent || path[0] == '/') &&
+-        group->backend->copyPlacement(group, path, parent) < 0)
+-        return -1;
++    if (parent || path[0] == '/') {
++        for (i = 0; i < VIR_CGROUP_BACKEND_TYPE_LAST; i++) {
++            if (group->backends[i] &&
++                group->backends[i]->copyPlacement(group, path, parent) < 0) {
++                return -1;
++            }
++        }
++    }
+ 
+     /* ... but use /proc/cgroups to fill in the rest */
+     if (virCgroupDetectPlacement(group, pid, path) < 0)
+         return -1;
+ 
+     /* Check that for every mounted controller, we found our placement */
+-    if (group->backend->validatePlacement(group, pid) < 0)
+-        return -1;
++    for (i = 0; i < VIR_CGROUP_BACKEND_TYPE_LAST; i++) {
++        if (group->backends[i] &&
++            group->backends[i]->validatePlacement(group, pid) < 0) {
++            return -1;
++        }
++    }
+ 
+     return 0;
+ }
+@@ -603,9 +630,14 @@ virCgroupMakeGroup(virCgroupPtr parent,
+                    bool create,
+                    unsigned int flags)
+ {
+-    if (group->backend->makeGroup(parent, group, create, flags) < 0) {
+-        virCgroupRemove(group);
+-        return -1;
++    size_t i;
++
++    for (i = 0; i < VIR_CGROUP_BACKEND_TYPE_LAST; i++) {
++        if (group->backends[i] &&
++            group->backends[i]->makeGroup(parent, group, create, flags) < 0) {
++            virCgroupRemove(group);
++            return -1;
++        }
+     }
+ 
+     return 0;
+@@ -666,6 +698,24 @@ virCgroupNew(pid_t pid,
+ }
+ 
+ 
++static int
++virCgroupAddTaskInternal(virCgroupPtr group,
++                         pid_t pid,
++                         unsigned int flags)
++{
++    size_t i;
++
++    for (i = 0; i < VIR_CGROUP_BACKEND_TYPE_LAST; i++) {
++        if (group->backends[i] &&
++            group->backends[i]->addTask(group, pid, flags) < 0) {
++            return -1;
++        }
++    }
++
++    return 0;
++}
++
++
+ /**
+  * virCgroupAddProcess:
+  *
+@@ -680,7 +730,7 @@ virCgroupNew(pid_t pid,
+ int
+ virCgroupAddProcess(virCgroupPtr group, pid_t pid)
+ {
+-    return group->backend->addTask(group, pid, VIR_CGROUP_TASK_PROCESS);
++    return virCgroupAddTaskInternal(group, pid, VIR_CGROUP_TASK_PROCESS);
+ }
+ 
+ /**
+@@ -697,9 +747,9 @@ virCgroupAddProcess(virCgroupPtr group, pid_t pid)
+ int
+ virCgroupAddMachineProcess(virCgroupPtr group, pid_t pid)
+ {
+-    return group->backend->addTask(group, pid,
+-                                   VIR_CGROUP_TASK_PROCESS |
+-                                   VIR_CGROUP_TASK_SYSTEMD);
++    return virCgroupAddTaskInternal(group, pid,
++                                    VIR_CGROUP_TASK_PROCESS |
++                                    VIR_CGROUP_TASK_SYSTEMD);
+ }
+ 
+ /**
+@@ -717,7 +767,7 @@ int
+ virCgroupAddThread(virCgroupPtr group,
+                    pid_t pid)
+ {
+-    return group->backend->addTask(group, pid, VIR_CGROUP_TASK_THREAD);
++    return virCgroupAddTaskInternal(group, pid, VIR_CGROUP_TASK_THREAD);
+ }
+ 
+ 
+@@ -971,17 +1021,24 @@ virCgroupNewDetectMachine(const char *name,
+                           char *machinename,
+                           virCgroupPtr *group)
+ {
++    size_t i;
++
+     if (virCgroupNewDetect(pid, controllers, group) < 0) {
+         if (virCgroupNewIgnoreError())
+             return 0;
+         return -1;
+     }
+ 
+-    if (!(*group)->backend->validateMachineGroup(*group, name, drivername, machinename)) {
+-        VIR_DEBUG("Failed to validate machine name for '%s' driver '%s'",
+-                  name, drivername);
+-        virCgroupFree(group);
+-        return 0;
++    for (i = 0; i < VIR_CGROUP_BACKEND_TYPE_LAST; i++) {
++        if ((*group)->backends[i] &&
++            !(*group)->backends[i]->validateMachineGroup(*group, name,
++                                                         drivername,
++                                                         machinename)) {
++            VIR_DEBUG("Failed to validate machine name for '%s' driver '%s'",
++                      name, drivername);
++            virCgroupFree(group);
++            return 0;
++        }
+     }
+ 
+     return 0;
+@@ -1059,6 +1116,7 @@ virCgroupNewMachineSystemd(const char *name,
+     int rv;
+     virCgroupPtr init;
+     VIR_AUTOFREE(char *) path = NULL;
++    size_t i;
+ 
+     VIR_DEBUG("Trying to setup machine '%s' via systemd", name);
+     if ((rv = virSystemdCreateMachine(name,
+@@ -1081,7 +1139,12 @@ virCgroupNewMachineSystemd(const char *name,
+                            &init) < 0)
+         return -1;
+ 
+-    path = init->backend->stealPlacement(init);
++    for (i = 0; i < VIR_CGROUP_BACKEND_TYPE_LAST; i++) {
++        if (init->backends[i] &&
++            (path = init->backends[i]->stealPlacement(init))) {
++            break;
++        }
++    }
+     virCgroupFree(&init);
+ 
+     if (!path || STREQ(path, "/") || path[0] != '/') {
+@@ -1260,12 +1323,21 @@ virCgroupFree(virCgroupPtr *group)
+ bool
+ virCgroupHasController(virCgroupPtr cgroup, int controller)
+ {
++    size_t i;
++
+     if (!cgroup)
+         return false;
+     if (controller < 0 || controller >= VIR_CGROUP_CONTROLLER_LAST)
+         return false;
+ 
+-    return cgroup->backend->hasController(cgroup, controller);
++    for (i = 0; i < VIR_CGROUP_BACKEND_TYPE_LAST; i++) {
++        if (cgroup->backends[i] &&
++            cgroup->backends[i]->hasController(cgroup, controller)) {
++            return true;
++        }
++    }
++
++    return false;
+ }
+ 
+ 
+@@ -1281,7 +1353,8 @@ virCgroupPathOfController(virCgroupPtr group,
+         return -1;
+     }
+ 
+-    return group->backend->pathOfController(group, controller, key, path);
++    VIR_CGROUP_BACKEND_CALL(group, controller, pathOfController, -1,
++                            controller, key, path);
+ }
+ 
+ 
+@@ -1303,7 +1376,8 @@ virCgroupGetBlkioIoServiced(virCgroupPtr group,
+                             long long *requests_read,
+                             long long *requests_write)
+ {
+-    VIR_CGROUP_BACKEND_CALL(group, getBlkioIoServiced, -1,
++    VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_BLKIO,
++                            getBlkioIoServiced, -1,
+                             bytes_read, bytes_write,
+                             requests_read, requests_write);
+ }
+@@ -1329,7 +1403,8 @@ virCgroupGetBlkioIoDeviceServiced(virCgroupPtr group,
+                                   long long *requests_read,
+                                   long long *requests_write)
+ {
+-    VIR_CGROUP_BACKEND_CALL(group, getBlkioIoDeviceServiced, -1,
++    VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_BLKIO,
++                            getBlkioIoDeviceServiced, -1,
+                             path, bytes_read, bytes_write,
+                             requests_read, requests_write);
+ }
+@@ -1346,7 +1421,8 @@ virCgroupGetBlkioIoDeviceServiced(virCgroupPtr group,
+ int
+ virCgroupSetBlkioWeight(virCgroupPtr group, unsigned int weight)
+ {
+-    VIR_CGROUP_BACKEND_CALL(group, setBlkioWeight, -1, weight);
++    VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_BLKIO,
++                            setBlkioWeight, -1, weight);
+ }
+ 
+ 
+@@ -1361,7 +1437,8 @@ virCgroupSetBlkioWeight(virCgroupPtr group, unsigned int weight)
+ int
+ virCgroupGetBlkioWeight(virCgroupPtr group, unsigned int *weight)
+ {
+-    VIR_CGROUP_BACKEND_CALL(group, getBlkioWeight, -1, weight);
++    VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_BLKIO,
++                            getBlkioWeight, -1, weight);
+ }
+ 
+ /**
+@@ -1377,7 +1454,8 @@ virCgroupSetBlkioDeviceReadIops(virCgroupPtr group,
+                                 const char *path,
+                                 unsigned int riops)
+ {
+-    VIR_CGROUP_BACKEND_CALL(group, setBlkioDeviceReadIops, -1, path, riops);
++    VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_BLKIO,
++                            setBlkioDeviceReadIops, -1, path, riops);
+ }
+ 
+ 
+@@ -1394,7 +1472,8 @@ virCgroupSetBlkioDeviceWriteIops(virCgroupPtr group,
+                                  const char *path,
+                                  unsigned int wiops)
+ {
+-    VIR_CGROUP_BACKEND_CALL(group, setBlkioDeviceWriteIops, -1, path, wiops);
++    VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_BLKIO,
++                            setBlkioDeviceWriteIops, -1, path, wiops);
+ }
+ 
+ 
+@@ -1411,7 +1490,8 @@ virCgroupSetBlkioDeviceReadBps(virCgroupPtr group,
+                                const char *path,
+                                unsigned long long rbps)
+ {
+-    VIR_CGROUP_BACKEND_CALL(group, setBlkioDeviceReadBps, -1, path, rbps);
++    VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_BLKIO,
++                            setBlkioDeviceReadBps, -1, path, rbps);
+ }
+ 
+ /**
+@@ -1427,7 +1507,8 @@ virCgroupSetBlkioDeviceWriteBps(virCgroupPtr group,
+                                 const char *path,
+                                 unsigned long long wbps)
+ {
+-    VIR_CGROUP_BACKEND_CALL(group, setBlkioDeviceWriteBps, -1, path, wbps);
++    VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_BLKIO,
++                            setBlkioDeviceWriteBps, -1, path, wbps);
+ }
+ 
+ 
+@@ -1445,7 +1526,8 @@ virCgroupSetBlkioDeviceWeight(virCgroupPtr group,
+                               const char *path,
+                               unsigned int weight)
+ {
+-    VIR_CGROUP_BACKEND_CALL(group, setBlkioDeviceWeight, -1, path, weight);
++    VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_BLKIO,
++                            setBlkioDeviceWeight, -1, path, weight);
+ }
+ 
+ /**
+@@ -1461,7 +1543,8 @@ virCgroupGetBlkioDeviceReadIops(virCgroupPtr group,
+                                 const char *path,
+                                 unsigned int *riops)
+ {
+-    VIR_CGROUP_BACKEND_CALL(group, getBlkioDeviceReadIops, -1, path, riops);
++    VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_BLKIO,
++                            getBlkioDeviceReadIops, -1, path, riops);
+ }
+ 
+ /**
+@@ -1477,7 +1560,8 @@ virCgroupGetBlkioDeviceWriteIops(virCgroupPtr group,
+                                  const char *path,
+                                  unsigned int *wiops)
+ {
+-    VIR_CGROUP_BACKEND_CALL(group, getBlkioDeviceWriteIops, -1, path, wiops);
++    VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_BLKIO,
++                            getBlkioDeviceWriteIops, -1, path, wiops);
+ }
+ 
+ /**
+@@ -1493,7 +1577,8 @@ virCgroupGetBlkioDeviceReadBps(virCgroupPtr group,
+                                const char *path,
+                                unsigned long long *rbps)
+ {
+-    VIR_CGROUP_BACKEND_CALL(group, getBlkioDeviceReadBps, -1, path, rbps);
++    VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_BLKIO,
++                            getBlkioDeviceReadBps, -1, path, rbps);
+ }
+ 
+ /**
+@@ -1509,7 +1594,8 @@ virCgroupGetBlkioDeviceWriteBps(virCgroupPtr group,
+                                 const char *path,
+                                 unsigned long long *wbps)
+ {
+-    VIR_CGROUP_BACKEND_CALL(group, getBlkioDeviceWriteBps, -1, path, wbps);
++    VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_BLKIO,
++                            getBlkioDeviceWriteBps, -1, path, wbps);
+ }
+ 
+ /**
+@@ -1525,7 +1611,8 @@ virCgroupGetBlkioDeviceWeight(virCgroupPtr group,
+                               const char *path,
+                               unsigned int *weight)
+ {
+-    VIR_CGROUP_BACKEND_CALL(group, getBlkioDeviceWeight, -1, path, weight);
++    VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_BLKIO,
++                            getBlkioDeviceWeight, -1, path, weight);
+ }
+ 
+ 
+@@ -1540,7 +1627,8 @@ virCgroupGetBlkioDeviceWeight(virCgroupPtr group,
+ int
+ virCgroupSetMemory(virCgroupPtr group, unsigned long long kb)
+ {
+-    VIR_CGROUP_BACKEND_CALL(group, setMemory, -1, kb);
++    VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_MEMORY,
++                            setMemory, -1, kb);
+ }
+ 
+ 
+@@ -1566,7 +1654,8 @@ virCgroupGetMemoryStat(virCgroupPtr group,
+                        unsigned long long *inactiveFile,
+                        unsigned long long *unevictable)
+ {
+-    VIR_CGROUP_BACKEND_CALL(group, getMemoryStat, -1, cache,
++    VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_MEMORY,
++                            getMemoryStat, -1, cache,
+                             activeAnon, inactiveAnon,
+                             activeFile, inactiveFile,
+                             unevictable);
+@@ -1584,7 +1673,8 @@ virCgroupGetMemoryStat(virCgroupPtr group,
+ int
+ virCgroupGetMemoryUsage(virCgroupPtr group, unsigned long *kb)
+ {
+-    VIR_CGROUP_BACKEND_CALL(group, getMemoryUsage, -1, kb);
++    VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_MEMORY,
++                            getMemoryUsage, -1, kb);
+ }
+ 
+ 
+@@ -1599,7 +1689,8 @@ virCgroupGetMemoryUsage(virCgroupPtr group, unsigned long *kb)
+ int
+ virCgroupSetMemoryHardLimit(virCgroupPtr group, unsigned long long kb)
+ {
+-    VIR_CGROUP_BACKEND_CALL(group, setMemoryHardLimit, -1, kb);
++    VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_MEMORY,
++                            setMemoryHardLimit, -1, kb);
+ }
+ 
+ 
+@@ -1614,7 +1705,8 @@ virCgroupSetMemoryHardLimit(virCgroupPtr group, unsigned long long kb)
+ int
+ virCgroupGetMemoryHardLimit(virCgroupPtr group, unsigned long long *kb)
+ {
+-    VIR_CGROUP_BACKEND_CALL(group, getMemoryHardLimit, -1, kb);
++    VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_MEMORY,
++                            getMemoryHardLimit, -1, kb);
+ }
+ 
+ 
+@@ -1629,7 +1721,8 @@ virCgroupGetMemoryHardLimit(virCgroupPtr group, unsigned long long *kb)
+ int
+ virCgroupSetMemorySoftLimit(virCgroupPtr group, unsigned long long kb)
+ {
+-    VIR_CGROUP_BACKEND_CALL(group, setMemorySoftLimit, -1, kb);
++    VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_MEMORY,
++                            setMemorySoftLimit, -1, kb);
+ }
+ 
+ 
+@@ -1644,7 +1737,8 @@ virCgroupSetMemorySoftLimit(virCgroupPtr group, unsigned long long kb)
+ int
+ virCgroupGetMemorySoftLimit(virCgroupPtr group, unsigned long long *kb)
+ {
+-    VIR_CGROUP_BACKEND_CALL(group, getMemorySoftLimit, -1, kb);
++    VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_MEMORY,
++                            getMemorySoftLimit, -1, kb);
+ }
+ 
+ 
+@@ -1659,7 +1753,8 @@ virCgroupGetMemorySoftLimit(virCgroupPtr group, unsigned long long *kb)
+ int
+ virCgroupSetMemSwapHardLimit(virCgroupPtr group, unsigned long long kb)
+ {
+-    VIR_CGROUP_BACKEND_CALL(group, setMemSwapHardLimit, -1, kb);
++    VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_MEMORY,
++                            setMemSwapHardLimit, -1, kb);
+ }
+ 
+ 
+@@ -1674,7 +1769,8 @@ virCgroupSetMemSwapHardLimit(virCgroupPtr group, unsigned long long kb)
+ int
+ virCgroupGetMemSwapHardLimit(virCgroupPtr group, unsigned long long *kb)
+ {
+-    VIR_CGROUP_BACKEND_CALL(group, getMemSwapHardLimit, -1, kb);
++    VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_MEMORY,
++                            getMemSwapHardLimit, -1, kb);
+ }
+ 
+ 
+@@ -1689,7 +1785,8 @@ virCgroupGetMemSwapHardLimit(virCgroupPtr group, unsigned long long *kb)
+ int
+ virCgroupGetMemSwapUsage(virCgroupPtr group, unsigned long long *kb)
+ {
+-    VIR_CGROUP_BACKEND_CALL(group, getMemSwapUsage, -1, kb);
++    VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_MEMORY,
++                            getMemSwapUsage, -1, kb);
+ }
+ 
+ 
+@@ -1704,7 +1801,8 @@ virCgroupGetMemSwapUsage(virCgroupPtr group, unsigned long long *kb)
+ int
+ virCgroupSetCpusetMems(virCgroupPtr group, const char *mems)
+ {
+-    VIR_CGROUP_BACKEND_CALL(group, setCpusetMems, -1, mems);
++    VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_CPUSET,
++                            setCpusetMems, -1, mems);
+ }
+ 
+ 
+@@ -1719,7 +1817,8 @@ virCgroupSetCpusetMems(virCgroupPtr group, const char *mems)
+ int
+ virCgroupGetCpusetMems(virCgroupPtr group, char **mems)
+ {
+-    VIR_CGROUP_BACKEND_CALL(group, getCpusetMems, -1, mems);
++    VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_CPUSET,
++                            getCpusetMems, -1, mems);
+ }
+ 
+ 
+@@ -1734,7 +1833,8 @@ virCgroupGetCpusetMems(virCgroupPtr group, char **mems)
+ int
+ virCgroupSetCpusetMemoryMigrate(virCgroupPtr group, bool migrate)
+ {
+-    VIR_CGROUP_BACKEND_CALL(group, setCpusetMemoryMigrate, -1, migrate);
++    VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_CPUSET,
++                            setCpusetMemoryMigrate, -1, migrate);
+ }
+ 
+ 
+@@ -1749,7 +1849,8 @@ virCgroupSetCpusetMemoryMigrate(virCgroupPtr group, bool migrate)
+ int
+ virCgroupGetCpusetMemoryMigrate(virCgroupPtr group, bool *migrate)
+ {
+-    VIR_CGROUP_BACKEND_CALL(group, getCpusetMemoryMigrate, -1, migrate);
++    VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_CPUSET,
++                            getCpusetMemoryMigrate, -1, migrate);
+ }
+ 
+ 
+@@ -1764,7 +1865,8 @@ virCgroupGetCpusetMemoryMigrate(virCgroupPtr group, bool *migrate)
+ int
+ virCgroupSetCpusetCpus(virCgroupPtr group, const char *cpus)
+ {
+-    VIR_CGROUP_BACKEND_CALL(group, setCpusetCpus, -1, cpus);
++    VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_CPUSET,
++                            setCpusetCpus, -1, cpus);
+ }
+ 
+ 
+@@ -1779,7 +1881,8 @@ virCgroupSetCpusetCpus(virCgroupPtr group, const char *cpus)
+ int
+ virCgroupGetCpusetCpus(virCgroupPtr group, char **cpus)
+ {
+-    VIR_CGROUP_BACKEND_CALL(group, getCpusetCpus, -1, cpus);
++    VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_CPUSET,
++                            getCpusetCpus, -1, cpus);
+ }
+ 
+ 
+@@ -1793,7 +1896,8 @@ virCgroupGetCpusetCpus(virCgroupPtr group, char **cpus)
+ int
+ virCgroupDenyAllDevices(virCgroupPtr group)
+ {
+-    VIR_CGROUP_BACKEND_CALL(group, denyAllDevices, -1);
++    VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_DEVICES,
++                            denyAllDevices, -1);
+ }
+ 
+ /**
+@@ -1813,7 +1917,8 @@ virCgroupDenyAllDevices(virCgroupPtr group)
+ int
+ virCgroupAllowAllDevices(virCgroupPtr group, int perms)
+ {
+-    VIR_CGROUP_BACKEND_CALL(group, allowAllDevices, -1, perms);
++    VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_DEVICES,
++                            allowAllDevices, -1, perms);
+ }
+ 
+ 
+@@ -1832,7 +1937,8 @@ int
+ virCgroupAllowDevice(virCgroupPtr group, char type, int major, int minor,
+                      int perms)
+ {
+-    VIR_CGROUP_BACKEND_CALL(group, allowDevice, -1, type, major, minor, perms);
++    VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_DEVICES,
++                            allowDevice, -1, type, major, minor, perms);
+ }
+ 
+ 
+@@ -1871,7 +1977,8 @@ virCgroupAllowDevicePath(virCgroupPtr group,
+     if (!S_ISCHR(sb.st_mode) && !S_ISBLK(sb.st_mode))
+         return 1;
+ 
+-    VIR_CGROUP_BACKEND_CALL(group, allowDevice, -1,
++    VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_DEVICES,
++                            allowDevice, -1,
+                             S_ISCHR(sb.st_mode) ? 'c' : 'b',
+                             major(sb.st_rdev),
+                             minor(sb.st_rdev),
+@@ -1894,7 +2001,8 @@ int
+ virCgroupDenyDevice(virCgroupPtr group, char type, int major, int minor,
+                     int perms)
+ {
+-    VIR_CGROUP_BACKEND_CALL(group, denyDevice, -1, type, major, minor, perms);
++    VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_DEVICES,
++                            denyDevice, -1, type, major, minor, perms);
+ }
+ 
+ 
+@@ -1933,7 +2041,8 @@ virCgroupDenyDevicePath(virCgroupPtr group,
+     if (!S_ISCHR(sb.st_mode) && !S_ISBLK(sb.st_mode))
+         return 1;
+ 
+-    VIR_CGROUP_BACKEND_CALL(group, denyDevice, -1,
++    VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_DEVICES,
++                            denyDevice, -1,
+                             S_ISCHR(sb.st_mode) ? 'c' : 'b',
+                             major(sb.st_rdev),
+                             minor(sb.st_rdev),
+@@ -2176,14 +2285,16 @@ virCgroupGetDomainTotalCpuStats(virCgroupPtr group,
+ int
+ virCgroupSetCpuShares(virCgroupPtr group, unsigned long long shares)
+ {
+-    VIR_CGROUP_BACKEND_CALL(group, setCpuShares, -1, shares);
++    VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_CPU,
++                            setCpuShares, -1, shares);
+ }
+ 
+ 
+ int
+ virCgroupGetCpuShares(virCgroupPtr group, unsigned long long *shares)
+ {
+-    VIR_CGROUP_BACKEND_CALL(group, getCpuShares, -1, shares);
++    VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_CPU,
++                            getCpuShares, -1, shares);
+ }
+ 
+ 
+@@ -2198,7 +2309,8 @@ virCgroupGetCpuShares(virCgroupPtr group, unsigned long long *shares)
+ int
+ virCgroupSetCpuCfsPeriod(virCgroupPtr group, unsigned long long cfs_period)
+ {
+-    VIR_CGROUP_BACKEND_CALL(group, setCpuCfsPeriod, -1, cfs_period);
++    VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_CPU,
++                            setCpuCfsPeriod, -1, cfs_period);
+ }
+ 
+ 
+@@ -2213,7 +2325,8 @@ virCgroupSetCpuCfsPeriod(virCgroupPtr group, unsigned long long cfs_period)
+ int
+ virCgroupGetCpuCfsPeriod(virCgroupPtr group, unsigned long long *cfs_period)
+ {
+-    VIR_CGROUP_BACKEND_CALL(group, getCpuCfsPeriod, -1, cfs_period);
++    VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_CPU,
++                            getCpuCfsPeriod, -1, cfs_period);
+ }
+ 
+ 
+@@ -2229,14 +2342,16 @@ virCgroupGetCpuCfsPeriod(virCgroupPtr group, unsigned long long *cfs_period)
+ int
+ virCgroupSetCpuCfsQuota(virCgroupPtr group, long long cfs_quota)
+ {
+-    VIR_CGROUP_BACKEND_CALL(group, setCpuCfsQuota, -1, cfs_quota);
++    VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_CPU,
++                            setCpuCfsQuota, -1, cfs_quota);
+ }
+ 
+ 
+ int
+ virCgroupGetCpuacctPercpuUsage(virCgroupPtr group, char **usage)
+ {
+-    VIR_CGROUP_BACKEND_CALL(group, getCpuacctPercpuUsage, -1, usage);
++    VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_CPUACCT,
++                            getCpuacctPercpuUsage, -1, usage);
+ }
+ 
+ 
+@@ -2303,7 +2418,16 @@ virCgroupRemoveRecursively(char *grppath)
+ int
+ virCgroupRemove(virCgroupPtr group)
+ {
+-    return group->backend->remove(group);
++    size_t i;
++
++    for (i = 0; i < VIR_CGROUP_BACKEND_TYPE_LAST; i++) {
++        if (group->backends[i] &&
++            group->backends[i]->remove(group) < 0) {
++            return -1;
++        }
++    }
++
++    return 0;
+ }
+ 
+ 
+@@ -2312,11 +2436,16 @@ virCgroupPathOfAnyController(virCgroupPtr group,
+                              const char *name,
+                              char **keypath)
+ {
++    size_t i;
+     int controller;
+ 
+-    controller = group->backend->getAnyController(group);
+-    if (controller >= 0)
+-        return virCgroupPathOfController(group, controller, name, keypath);
++    for (i = 0; i < VIR_CGROUP_BACKEND_TYPE_LAST; i++) {
++        if (group->backends[i]) {
++            controller = group->backends[i]->getAnyController(group);
++            if (controller >= 0)
++                return virCgroupPathOfController(group, controller, name, keypath);
++        }
++    }
+ 
+     virReportSystemError(ENOSYS, "%s",
+                          _("No controllers are mounted"));
+@@ -2552,14 +2681,16 @@ virCgroupKillPainfully(virCgroupPtr group)
+ int
+ virCgroupGetCpuCfsQuota(virCgroupPtr group, long long *cfs_quota)
+ {
+-    VIR_CGROUP_BACKEND_CALL(group, getCpuCfsQuota, -1, cfs_quota);
++    VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_CPU,
++                            getCpuCfsQuota, -1, cfs_quota);
+ }
+ 
+ 
+ int
+ virCgroupGetCpuacctUsage(virCgroupPtr group, unsigned long long *usage)
+ {
+-    VIR_CGROUP_BACKEND_CALL(group, getCpuacctUsage, -1, usage);
++    VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_CPUACCT,
++                            getCpuacctUsage, -1, usage);
+ }
+ 
+ 
+@@ -2567,21 +2698,24 @@ int
+ virCgroupGetCpuacctStat(virCgroupPtr group, unsigned long long *user,
+                         unsigned long long *sys)
+ {
+-    VIR_CGROUP_BACKEND_CALL(group, getCpuacctStat, -1, user, sys);
++    VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_CPUACCT,
++                            getCpuacctStat, -1, user, sys);
+ }
+ 
+ 
+ int
+ virCgroupSetFreezerState(virCgroupPtr group, const char *state)
+ {
+-    VIR_CGROUP_BACKEND_CALL(group, setFreezerState, -1, state);
++    VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_FREEZER,
++                            setFreezerState, -1, state);
+ }
+ 
+ 
+ int
+ virCgroupGetFreezerState(virCgroupPtr group, char **state)
+ {
+-    VIR_CGROUP_BACKEND_CALL(group, getFreezerState, -1, state);
++    VIR_CGROUP_BACKEND_CALL(group, VIR_CGROUP_CONTROLLER_FREEZER,
++                            getFreezerState, -1, state);
+ }
+ 
+ 
+@@ -2589,7 +2723,16 @@ int
+ virCgroupBindMount(virCgroupPtr group, const char *oldroot,
+                    const char *mountopts)
+ {
+-    return group->backend->bindMount(group, oldroot, mountopts);
++    size_t i;
++
++    for (i = 0; i < VIR_CGROUP_BACKEND_TYPE_LAST; i++) {
++        if (group->backends[i] &&
++            group->backends[i]->bindMount(group, oldroot, mountopts) < 0) {
++            return -1;
++        }
++    }
++
++    return 0;
+ }
+ 
+ 
+@@ -2598,7 +2741,16 @@ int virCgroupSetOwner(virCgroupPtr cgroup,
+                       gid_t gid,
+                       int controllers)
+ {
+-    return cgroup->backend->setOwner(cgroup, uid, gid, controllers);
++    size_t i;
++
++    for (i = 0; i < VIR_CGROUP_BACKEND_TYPE_LAST; i++) {
++        if (cgroup->backends[i] &&
++            cgroup->backends[i]->setOwner(cgroup, uid, gid, controllers) < 0) {
++            return -1;
++        }
++    }
++
++    return 0;
+ }
+ 
+ 
+@@ -2612,13 +2764,24 @@ int virCgroupSetOwner(virCgroupPtr cgroup,
+ bool
+ virCgroupSupportsCpuBW(virCgroupPtr cgroup)
+ {
+-    VIR_CGROUP_BACKEND_CALL(cgroup, supportsCpuBW, false);
++    VIR_CGROUP_BACKEND_CALL(cgroup, VIR_CGROUP_CONTROLLER_CPU,
++                            supportsCpuBW, false);
+ }
+ 
+ int
+ virCgroupHasEmptyTasks(virCgroupPtr cgroup, int controller)
+ {
+-    return cgroup->backend->hasEmptyTasks(cgroup, controller);
++    size_t i;
++
++    for (i = 0; i < VIR_CGROUP_BACKEND_TYPE_LAST; i++) {
++        if (cgroup->backends[i]) {
++            int rc = cgroup->backends[i]->hasEmptyTasks(cgroup, controller);
++            if (rc <= 0)
++                return rc;
++        }
++    }
++
++    return 1;
+ }
+ 
+ bool
+diff --git a/src/util/vircgroupbackend.c b/src/util/vircgroupbackend.c
+index 7ee39ac8ca..2e90781dc3 100644
+--- a/src/util/vircgroupbackend.c
++++ b/src/util/vircgroupbackend.c
+@@ -20,6 +20,9 @@
+ #include <config.h>
+ 
+ #include "vircgroupbackend.h"
++#define __VIR_CGROUP_ALLOW_INCLUDE_PRIV_H__
++#include "vircgrouppriv.h"
++#undef __VIR_CGROUP_ALLOW_INCLUDE_PRIV_H__
+ #include "vircgroupv1.h"
+ #include "vircgroupv2.h"
+ #include "virerror.h"
+@@ -67,3 +70,20 @@ virCgroupBackendGetAll(void)
+     }
+     return virCgroupBackends;
+ }
++
++
++virCgroupBackendPtr
++virCgroupBackendForController(virCgroupPtr group,
++                              unsigned int controller)
++{
++    size_t i;
++
++    for (i = 0; i < VIR_CGROUP_BACKEND_TYPE_LAST; i++) {
++        if (group->backends[i] &&
++            group->backends[i]->hasController(group, controller)) {
++            return group->backends[i];
++        }
++    }
++
++    return NULL;
++}
+diff --git a/src/util/vircgroupbackend.h b/src/util/vircgroupbackend.h
+index 86d1539e07..bc60b44643 100644
+--- a/src/util/vircgroupbackend.h
++++ b/src/util/vircgroupbackend.h
+@@ -436,12 +436,22 @@ virCgroupBackendRegister(virCgroupBackendPtr backend);
+ virCgroupBackendPtr *
+ virCgroupBackendGetAll(void);
+ 
+-# define VIR_CGROUP_BACKEND_CALL(group, func, ret, ...) \
+-    if (!group->backend->func) { \
++virCgroupBackendPtr
++virCgroupBackendForController(virCgroupPtr group,
++                              unsigned int controller);
++
++# define VIR_CGROUP_BACKEND_CALL(group, controller, func, ret, ...) \
++    virCgroupBackendPtr backend = virCgroupBackendForController(group, controller); \
++    if (!backend) { \
++        virReportError(VIR_ERR_INTERNAL_ERROR, \
++                       _("failed to get cgroup backend for '%s'"), #func); \
++        return ret; \
++    } \
++    if (!backend->func) { \
+         virReportError(VIR_ERR_OPERATION_UNSUPPORTED, \
+                        _("operation '%s' not supported"), #func); \
+         return ret; \
+     } \
+-    return group->backend->func(group, ##__VA_ARGS__);
++    return backend->func(group, ##__VA_ARGS__);
+ 
+ #endif /* __VIR_CGROUP_BACKEND_H__ */
+diff --git a/src/util/vircgrouppriv.h b/src/util/vircgrouppriv.h
+index 4a0d75ddbc..8f24b0891e 100644
+--- a/src/util/vircgrouppriv.h
++++ b/src/util/vircgrouppriv.h
+@@ -56,7 +56,7 @@ typedef virCgroupV2Controller *virCgroupV2ControllerPtr;
+ struct _virCgroup {
+     char *path;
+ 
+-    virCgroupBackendPtr backend;
++    virCgroupBackendPtr backends[VIR_CGROUP_BACKEND_TYPE_LAST];
+ 
+     virCgroupV1Controller legacy[VIR_CGROUP_CONTROLLER_LAST];
+     virCgroupV2Controller unified;
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-cleanup-controllers-not-managed-by-systemd-on-error.patch b/SOURCES/libvirt-vircgroup-cleanup-controllers-not-managed-by-systemd-on-error.patch
new file mode 100644
index 0000000..ac36ae5
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-cleanup-controllers-not-managed-by-systemd-on-error.patch
@@ -0,0 +1,77 @@
+From b77a6e6821bc45e4761fc7b23665f585761570ca Mon Sep 17 00:00:00 2001
+Message-Id: <b77a6e6821bc45e4761fc7b23665f585761570ca@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:06:12 +0200
+Subject: [PATCH] vircgroup: cleanup controllers not managed by systemd on
+ error
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+If virCgroupEnableMissingControllers() fails it could have already
+created some directories, we should clean it up as well.
+
+Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 1602aa28f820ada66f707cef3e536e8572fbda1e)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <e056c233653eaf09f55643fc075e17506bb754e2.1561993099.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c | 25 +++++++++++++++----------
+ 1 file changed, 15 insertions(+), 10 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index 64507bf8aa..6aa30a82be 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -1555,6 +1555,7 @@ virCgroupNewMachineSystemd(const char *name,
+     int rv;
+     virCgroupPtr init;
+     VIR_AUTOFREE(char *) path = NULL;
++    virErrorPtr saved = NULL;
+ 
+     VIR_DEBUG("Trying to setup machine '%s' via systemd", name);
+     if ((rv = virSystemdCreateMachine(name,
+@@ -1588,20 +1589,24 @@ virCgroupNewMachineSystemd(const char *name,
+ 
+     if (virCgroupEnableMissingControllers(path, pidleader,
+                                           controllers, group) < 0) {
+-        return -1;
++        goto error;
+     }
+ 
+-    if (virCgroupAddTask(*group, pidleader) < 0) {
+-        virErrorPtr saved = virSaveLastError();
+-        virCgroupRemove(*group);
+-        virCgroupFree(group);
+-        if (saved) {
+-            virSetError(saved);
+-            virFreeError(saved);
+-        }
+-    }
++    if (virCgroupAddTask(*group, pidleader) < 0)
++        goto error;
+ 
+     return 0;
++
++ error:
++    saved = virSaveLastError();
++    virCgroupRemove(*group);
++    virCgroupFree(group);
++    if (saved) {
++        virSetError(saved);
++        virFreeError(saved);
++    }
++
++    return -1;
+ }
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-detect-available-backend-for-cgroup.patch b/SOURCES/libvirt-vircgroup-detect-available-backend-for-cgroup.patch
new file mode 100644
index 0000000..790edb2
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-detect-available-backend-for-cgroup.patch
@@ -0,0 +1,151 @@
+From 81bf1dade08ee40a9ecc32f5d384fdf35e3edbf3 Mon Sep 17 00:00:00 2001
+Message-Id: <81bf1dade08ee40a9ecc32f5d384fdf35e3edbf3@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:06:24 +0200
+Subject: [PATCH] vircgroup: detect available backend for cgroup
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+We need to update one test-case because now new cgroup object will be
+created only if there is any cgroup backend available.
+
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit f60af21594801088fff217aebf33b58825bd8a80)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <2815d54d5cffdef81bf9a41136b2d6a7e1d75b55.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c     | 18 ++++++++++++++++++
+ src/util/vircgrouppriv.h |  3 +++
+ tests/vircgrouptest.c    | 38 +++-----------------------------------
+ 3 files changed, 24 insertions(+), 35 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index 47a3b9ed58..15d0cb65ac 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -711,10 +711,28 @@ virCgroupDetect(virCgroupPtr group,
+                 virCgroupPtr parent)
+ {
+     int rc;
++    size_t i;
++    virCgroupBackendPtr *backends = virCgroupBackendGetAll();
+ 
+     VIR_DEBUG("group=%p controllers=%d path=%s parent=%p",
+               group, controllers, path, parent);
+ 
++    if (!backends)
++        return -1;
++
++    for (i = 0; i < VIR_CGROUP_BACKEND_TYPE_LAST; i++) {
++        if (backends[i] && backends[i]->available()) {
++            group->backend = backends[i];
++            break;
++        }
++    }
++
++    if (!group->backend) {
++        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
++                       _("no cgroup backend available"));
++        return -1;
++    }
++
+     if (parent) {
+         if (virCgroupCopyMounts(group, parent) < 0)
+             return -1;
+diff --git a/src/util/vircgrouppriv.h b/src/util/vircgrouppriv.h
+index 046c96c52c..2caa966fee 100644
+--- a/src/util/vircgrouppriv.h
++++ b/src/util/vircgrouppriv.h
+@@ -30,6 +30,7 @@
+ # define __VIR_CGROUP_PRIV_H__
+ 
+ # include "vircgroup.h"
++# include "vircgroupbackend.h"
+ 
+ struct _virCgroupController {
+     int type;
+@@ -47,6 +48,8 @@ typedef virCgroupController *virCgroupControllerPtr;
+ struct _virCgroup {
+     char *path;
+ 
++    virCgroupBackendPtr backend;
++
+     virCgroupController controllers[VIR_CGROUP_CONTROLLER_LAST];
+ };
+ 
+diff --git a/tests/vircgrouptest.c b/tests/vircgrouptest.c
+index 5031a2973d..588a6e824d 100644
+--- a/tests/vircgrouptest.c
++++ b/tests/vircgrouptest.c
+@@ -114,16 +114,6 @@ const char *mountsAllInOne[VIR_CGROUP_CONTROLLER_LAST] = {
+     [VIR_CGROUP_CONTROLLER_BLKIO] = "/not/really/sys/fs/cgroup",
+     [VIR_CGROUP_CONTROLLER_SYSTEMD] = NULL,
+ };
+-const char *mountsLogind[VIR_CGROUP_CONTROLLER_LAST] = {
+-    [VIR_CGROUP_CONTROLLER_CPU] = NULL,
+-    [VIR_CGROUP_CONTROLLER_CPUACCT] = NULL,
+-    [VIR_CGROUP_CONTROLLER_CPUSET] = NULL,
+-    [VIR_CGROUP_CONTROLLER_MEMORY] = NULL,
+-    [VIR_CGROUP_CONTROLLER_DEVICES] = NULL,
+-    [VIR_CGROUP_CONTROLLER_FREEZER] = NULL,
+-    [VIR_CGROUP_CONTROLLER_BLKIO] = NULL,
+-    [VIR_CGROUP_CONTROLLER_SYSTEMD] = "/not/really/sys/fs/cgroup/systemd",
+-};
+ 
+ const char *links[VIR_CGROUP_CONTROLLER_LAST] = {
+     [VIR_CGROUP_CONTROLLER_CPU] = "/not/really/sys/fs/cgroup/cpu",
+@@ -147,17 +137,6 @@ const char *linksAllInOne[VIR_CGROUP_CONTROLLER_LAST] = {
+     [VIR_CGROUP_CONTROLLER_SYSTEMD] = NULL,
+ };
+ 
+-const char *linksLogind[VIR_CGROUP_CONTROLLER_LAST] = {
+-    [VIR_CGROUP_CONTROLLER_CPU] = NULL,
+-    [VIR_CGROUP_CONTROLLER_CPUACCT] = NULL,
+-    [VIR_CGROUP_CONTROLLER_CPUSET] = NULL,
+-    [VIR_CGROUP_CONTROLLER_MEMORY] = NULL,
+-    [VIR_CGROUP_CONTROLLER_DEVICES] = NULL,
+-    [VIR_CGROUP_CONTROLLER_FREEZER] = NULL,
+-    [VIR_CGROUP_CONTROLLER_BLKIO] = NULL,
+-    [VIR_CGROUP_CONTROLLER_SYSTEMD] = NULL,
+-};
+-
+ 
+ struct _detectMountsData {
+     const char *file;
+@@ -555,24 +534,13 @@ static int testCgroupNewForSelfLogind(const void *args ATTRIBUTE_UNUSED)
+ {
+     virCgroupPtr cgroup = NULL;
+     int ret = -1;
+-    const char *placement[VIR_CGROUP_CONTROLLER_LAST] = {
+-        [VIR_CGROUP_CONTROLLER_CPU] = NULL,
+-        [VIR_CGROUP_CONTROLLER_CPUACCT] = NULL,
+-        [VIR_CGROUP_CONTROLLER_CPUSET] = NULL,
+-        [VIR_CGROUP_CONTROLLER_MEMORY] = NULL,
+-        [VIR_CGROUP_CONTROLLER_DEVICES] = NULL,
+-        [VIR_CGROUP_CONTROLLER_FREEZER] = NULL,
+-        [VIR_CGROUP_CONTROLLER_BLKIO] = NULL,
+-        [VIR_CGROUP_CONTROLLER_SYSTEMD] = "/",
+-    };
+ 
+-    if (virCgroupNewSelf(&cgroup) < 0) {
+-        fprintf(stderr, "Cannot create cgroup for self\n");
++    if (virCgroupNewSelf(&cgroup) == 0) {
++        fprintf(stderr, "Expected cgroup creation to fail.\n");
+         goto cleanup;
+     }
+ 
+-    ret = validateCgroup(cgroup, "", mountsLogind, linksLogind, placement);
+-
++    ret = 0;
+  cleanup:
+     virCgroupFree(&cgroup);
+     return ret;
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-extract-v1-detect-functions.patch b/SOURCES/libvirt-vircgroup-extract-v1-detect-functions.patch
new file mode 100644
index 0000000..845153a
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-extract-v1-detect-functions.patch
@@ -0,0 +1,426 @@
+From e1184bde63a7ed92fb99fc4eba4b4abdf6a01815 Mon Sep 17 00:00:00 2001
+Message-Id: <e1184bde63a7ed92fb99fc4eba4b4abdf6a01815@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:06:27 +0200
+Subject: [PATCH] vircgroup: extract v1 detect functions
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 42a3fcc02bcaec4a0c037a5c59ca63f3fc90e90f)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <3a918fc4eda51c5e9aff5efc93fe14886470578e.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c        | 138 ++-----------------------------
+ src/util/vircgroupbackend.h |  14 ++++
+ src/util/vircgroupv1.c      | 158 ++++++++++++++++++++++++++++++++++++
+ 3 files changed, 180 insertions(+), 130 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index 9d644d37d1..10c99a66fd 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -235,82 +235,6 @@ virCgroupPartitionEscape(char **path)
+ }
+ 
+ 
+-static int
+-virCgroupResolveMountLink(const char *mntDir,
+-                          const char *typeStr,
+-                          virCgroupControllerPtr controller)
+-{
+-    VIR_AUTOFREE(char *) linkSrc = NULL;
+-    VIR_AUTOFREE(char *) tmp = NULL;
+-    char *dirName;
+-    struct stat sb;
+-
+-    if (VIR_STRDUP(tmp, mntDir) < 0)
+-        return -1;
+-
+-    dirName = strrchr(tmp, '/');
+-    if (!dirName) {
+-        virReportError(VIR_ERR_INTERNAL_ERROR,
+-                       _("Missing '/' separator in cgroup mount '%s'"), tmp);
+-        return -1;
+-    }
+-
+-    if (!strchr(dirName + 1, ','))
+-        return 0;
+-
+-    *dirName = '\0';
+-    if (virAsprintf(&linkSrc, "%s/%s", tmp, typeStr) < 0)
+-        return -1;
+-    *dirName = '/';
+-
+-    if (lstat(linkSrc, &sb) < 0) {
+-        if (errno == ENOENT) {
+-            VIR_WARN("Controller %s co-mounted at %s is missing symlink at %s",
+-                     typeStr, tmp, linkSrc);
+-        } else {
+-            virReportSystemError(errno, _("Cannot stat %s"), linkSrc);
+-            return -1;
+-        }
+-    } else {
+-        if (!S_ISLNK(sb.st_mode)) {
+-            VIR_WARN("Expecting a symlink at %s for controller %s",
+-                     linkSrc, typeStr);
+-        } else {
+-            VIR_STEAL_PTR(controller->linkPoint, linkSrc);
+-        }
+-    }
+-
+-    return 0;
+-}
+-
+-
+-static bool
+-virCgroupMountOptsMatchController(const char *mntOpts,
+-                                  const char *typeStr)
+-{
+-    const char *tmp = mntOpts;
+-    int typeLen = strlen(typeStr);
+-
+-    while (tmp) {
+-        const char *next = strchr(tmp, ',');
+-        int len;
+-        if (next) {
+-            len = next - tmp;
+-            next++;
+-        } else {
+-            len = strlen(tmp);
+-        }
+-
+-        if (typeLen == len && STREQLEN(typeStr, tmp, len))
+-            return true;
+-
+-        tmp = next;
+-    }
+-
+-    return false;
+-}
+-
+-
+ /*
+  * Process /proc/mounts figuring out what controllers are
+  * mounted and where
+@@ -318,7 +242,6 @@ virCgroupMountOptsMatchController(const char *mntOpts,
+ static int
+ virCgroupDetectMounts(virCgroupPtr group)
+ {
+-    size_t i;
+     FILE *mounts = NULL;
+     struct mntent entry;
+     char buf[CGROUP_MAX_VAL];
+@@ -331,34 +254,11 @@ virCgroupDetectMounts(virCgroupPtr group)
+     }
+ 
+     while (getmntent_r(mounts, &entry, buf, sizeof(buf)) != NULL) {
+-        if (STRNEQ(entry.mnt_type, "cgroup"))
+-            continue;
+-
+-        for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
+-            const char *typestr = virCgroupControllerTypeToString(i);
+-
+-            if (virCgroupMountOptsMatchController(entry.mnt_opts, typestr)) {
+-                /* Note that the lines in /proc/mounts have the same
+-                 * order than the mount operations, and that there may
+-                 * be duplicates due to bind mounts. This means
+-                 * that the same mount point may be processed more than
+-                 * once. We need to save the results of the last one,
+-                 * and we need to be careful to release the memory used
+-                 * by previous processing. */
+-                virCgroupControllerPtr controller = &group->controllers[i];
+-
+-                VIR_FREE(controller->mountPoint);
+-                VIR_FREE(controller->linkPoint);
+-                if (VIR_STRDUP(controller->mountPoint, entry.mnt_dir) < 0)
+-                    goto cleanup;
+-
+-                /* If it is a co-mount it has a filename like "cpu,cpuacct"
+-                 * and we must identify the symlink path */
+-                if (virCgroupResolveMountLink(entry.mnt_dir, typestr,
+-                                              controller) < 0) {
+-                    goto cleanup;
+-                }
+-            }
++        if (group->backend->detectMounts(group,
++                                         entry.mnt_type,
++                                         entry.mnt_opts,
++                                         entry.mnt_dir) < 0) {
++            goto cleanup;
+         }
+     }
+ 
+@@ -432,7 +332,6 @@ virCgroupDetectPlacement(virCgroupPtr group,
+                          pid_t pid,
+                          const char *path)
+ {
+-    size_t i;
+     FILE *mapping  = NULL;
+     char line[1024];
+     int ret = -1;
+@@ -472,30 +371,9 @@ virCgroupDetectPlacement(virCgroupPtr group,
+         controllers++;
+         selfpath++;
+ 
+-        for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
+-            const char *typestr = virCgroupControllerTypeToString(i);
+-
+-            if (virCgroupMountOptsMatchController(controllers, typestr) &&
+-                group->controllers[i].mountPoint != NULL &&
+-                group->controllers[i].placement == NULL) {
+-                /*
+-                 * selfpath == "/" + path="" -> "/"
+-                 * selfpath == "/libvirt.service" + path == "" -> "/libvirt.service"
+-                 * selfpath == "/libvirt.service" + path == "foo" -> "/libvirt.service/foo"
+-                 */
+-                if (i == VIR_CGROUP_CONTROLLER_SYSTEMD) {
+-                    if (VIR_STRDUP(group->controllers[i].placement,
+-                                   selfpath) < 0)
+-                        goto cleanup;
+-                } else {
+-                    if (virAsprintf(&group->controllers[i].placement,
+-                                    "%s%s%s", selfpath,
+-                                    (STREQ(selfpath, "/") ||
+-                                     STREQ(path, "") ? "" : "/"),
+-                                    path) < 0)
+-                        goto cleanup;
+-                }
+-            }
++        if (group->backend->detectPlacement(group, path, controllers,
++                                            selfpath) < 0) {
++            goto cleanup;
+         }
+     }
+ 
+diff --git a/src/util/vircgroupbackend.h b/src/util/vircgroupbackend.h
+index 81ee597fc8..fadc7efdcf 100644
+--- a/src/util/vircgroupbackend.h
++++ b/src/util/vircgroupbackend.h
+@@ -45,6 +45,18 @@ typedef int
+ (*virCgroupCopyMountsCB)(virCgroupPtr group,
+                          virCgroupPtr parent);
+ 
++typedef int
++(*virCgroupDetectMountsCB)(virCgroupPtr group,
++                           const char *mntType,
++                           const char *mntOpts,
++                           const char *mntDir);
++
++typedef int
++(*virCgroupDetectPlacementCB)(virCgroupPtr group,
++                              const char *path,
++                              const char *controllers,
++                              const char *selfpath);
++
+ struct _virCgroupBackend {
+     virCgroupBackendType type;
+ 
+@@ -52,6 +64,8 @@ struct _virCgroupBackend {
+     virCgroupAvailableCB available;
+     virCgroupValidateMachineGroupCB validateMachineGroup;
+     virCgroupCopyMountsCB copyMounts;
++    virCgroupDetectMountsCB detectMounts;
++    virCgroupDetectPlacementCB detectPlacement;
+ };
+ typedef struct _virCgroupBackend virCgroupBackend;
+ typedef virCgroupBackend *virCgroupBackendPtr;
+diff --git a/src/util/vircgroupv1.c b/src/util/vircgroupv1.c
+index 50b58ab413..bd9f28f6e9 100644
+--- a/src/util/vircgroupv1.c
++++ b/src/util/vircgroupv1.c
+@@ -23,6 +23,7 @@
+ #if defined HAVE_MNTENT_H && defined HAVE_GETMNTENT_R
+ # include <mntent.h>
+ #endif
++#include <sys/stat.h>
+ 
+ #include "internal.h"
+ 
+@@ -38,6 +39,7 @@
+ #include "virlog.h"
+ #include "virstring.h"
+ #include "virsystemd.h"
++#include "virerror.h"
+ 
+ VIR_LOG_INIT("util.cgroup");
+ 
+@@ -181,12 +183,168 @@ virCgroupV1CopyMounts(virCgroupPtr group,
+ }
+ 
+ 
++static int
++virCgroupV1ResolveMountLink(const char *mntDir,
++                            const char *typeStr,
++                            virCgroupControllerPtr controller)
++{
++    VIR_AUTOFREE(char *) linkSrc = NULL;
++    VIR_AUTOFREE(char *) tmp = NULL;
++    char *dirName;
++    struct stat sb;
++
++    if (VIR_STRDUP(tmp, mntDir) < 0)
++        return -1;
++
++    dirName = strrchr(tmp, '/');
++    if (!dirName) {
++        virReportError(VIR_ERR_INTERNAL_ERROR,
++                       _("Missing '/' separator in cgroup mount '%s'"), tmp);
++        return -1;
++    }
++
++    if (!strchr(dirName + 1, ','))
++        return 0;
++
++    *dirName = '\0';
++    if (virAsprintf(&linkSrc, "%s/%s", tmp, typeStr) < 0)
++        return -1;
++    *dirName = '/';
++
++    if (lstat(linkSrc, &sb) < 0) {
++        if (errno == ENOENT) {
++            VIR_WARN("Controller %s co-mounted at %s is missing symlink at %s",
++                     typeStr, tmp, linkSrc);
++        } else {
++            virReportSystemError(errno, _("Cannot stat %s"), linkSrc);
++            return -1;
++        }
++    } else {
++        if (!S_ISLNK(sb.st_mode)) {
++            VIR_WARN("Expecting a symlink at %s for controller %s",
++                     linkSrc, typeStr);
++        } else {
++            VIR_STEAL_PTR(controller->linkPoint, linkSrc);
++        }
++    }
++
++    return 0;
++}
++
++
++static bool
++virCgroupV1MountOptsMatchController(const char *mntOpts,
++                                    const char *typeStr)
++{
++    const char *tmp = mntOpts;
++    int typeLen = strlen(typeStr);
++
++    while (tmp) {
++        const char *next = strchr(tmp, ',');
++        int len;
++        if (next) {
++            len = next - tmp;
++            next++;
++        } else {
++            len = strlen(tmp);
++        }
++
++        if (typeLen == len && STREQLEN(typeStr, tmp, len))
++            return true;
++
++        tmp = next;
++    }
++
++    return false;
++}
++
++
++static int
++virCgroupV1DetectMounts(virCgroupPtr group,
++                        const char *mntType,
++                        const char *mntOpts,
++                        const char *mntDir)
++{
++    size_t i;
++
++    if (STRNEQ(mntType, "cgroup"))
++        return 0;
++
++    for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
++        const char *typestr = virCgroupV1ControllerTypeToString(i);
++
++        if (virCgroupV1MountOptsMatchController(mntOpts, typestr)) {
++            /* Note that the lines in /proc/mounts have the same
++             * order than the mount operations, and that there may
++             * be duplicates due to bind mounts. This means
++             * that the same mount point may be processed more than
++             * once. We need to save the results of the last one,
++             * and we need to be careful to release the memory used
++             * by previous processing. */
++            virCgroupControllerPtr controller = &group->controllers[i];
++
++            VIR_FREE(controller->mountPoint);
++            VIR_FREE(controller->linkPoint);
++            if (VIR_STRDUP(controller->mountPoint, mntDir) < 0)
++                return -1;
++
++            /* If it is a co-mount it has a filename like "cpu,cpuacct"
++             * and we must identify the symlink path */
++            if (virCgroupV1ResolveMountLink(mntDir, typestr, controller) < 0)
++                return -1;
++        }
++    }
++
++    return 0;
++}
++
++
++static int
++virCgroupV1DetectPlacement(virCgroupPtr group,
++                           const char *path,
++                           const char *controllers,
++                           const char *selfpath)
++{
++    size_t i;
++
++    for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
++        const char *typestr = virCgroupV1ControllerTypeToString(i);
++
++        if (virCgroupV1MountOptsMatchController(controllers, typestr) &&
++            group->controllers[i].mountPoint != NULL &&
++            group->controllers[i].placement == NULL) {
++            /*
++             * selfpath == "/" + path="" -> "/"
++             * selfpath == "/libvirt.service" + path == "" -> "/libvirt.service"
++             * selfpath == "/libvirt.service" + path == "foo" -> "/libvirt.service/foo"
++             */
++            if (i == VIR_CGROUP_CONTROLLER_SYSTEMD) {
++                if (VIR_STRDUP(group->controllers[i].placement,
++                               selfpath) < 0)
++                    return -1;
++            } else {
++                if (virAsprintf(&group->controllers[i].placement,
++                                "%s%s%s", selfpath,
++                                (STREQ(selfpath, "/") ||
++                                 STREQ(path, "") ? "" : "/"),
++                                path) < 0)
++                    return -1;
++            }
++        }
++    }
++
++    return 0;
++}
++
++
+ virCgroupBackend virCgroupV1Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V1,
+ 
+     .available = virCgroupV1Available,
+     .validateMachineGroup = virCgroupV1ValidateMachineGroup,
+     .copyMounts = virCgroupV1CopyMounts,
++    .detectMounts = virCgroupV1DetectMounts,
++    .detectPlacement = virCgroupV1DetectPlacement,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-extract-virCgroupV1-Allow-Deny-AllDevices.patch b/SOURCES/libvirt-vircgroup-extract-virCgroupV1-Allow-Deny-AllDevices.patch
new file mode 100644
index 0000000..d4dbcdf
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-extract-virCgroupV1-Allow-Deny-AllDevices.patch
@@ -0,0 +1,140 @@
+From 4cf3b3d335b83b5feb49e71775b6a8f1fddbbce9 Mon Sep 17 00:00:00 2001
+Message-Id: <4cf3b3d335b83b5feb49e71775b6a8f1fddbbce9@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:06:55 +0200
+Subject: [PATCH] vircgroup: extract virCgroupV1(Allow|Deny)AllDevices
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit fd9a0368b91c425f860115c0451067ee917574d1)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <cec0c47305736e9da14175d4002509b5583e4ab0.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c        | 18 ++----------------
+ src/util/vircgroupbackend.h |  9 +++++++++
+ src/util/vircgroupv1.c      | 31 +++++++++++++++++++++++++++++++
+ 3 files changed, 42 insertions(+), 16 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index a30fc6241d..67c68f3dc6 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -1822,10 +1822,7 @@ virCgroupGetCpusetCpus(virCgroupPtr group, char **cpus)
+ int
+ virCgroupDenyAllDevices(virCgroupPtr group)
+ {
+-    return virCgroupSetValueStr(group,
+-                                VIR_CGROUP_CONTROLLER_DEVICES,
+-                                "devices.deny",
+-                                "a");
++    VIR_CGROUP_BACKEND_CALL(group, denyAllDevices, -1);
+ }
+ 
+ /**
+@@ -1845,18 +1842,7 @@ virCgroupDenyAllDevices(virCgroupPtr group)
+ int
+ virCgroupAllowAllDevices(virCgroupPtr group, int perms)
+ {
+-    int ret = -1;
+-
+-    if (virCgroupAllowDevice(group, 'b', -1, -1, perms) < 0)
+-        goto cleanup;
+-
+-    if (virCgroupAllowDevice(group, 'c', -1, -1, perms) < 0)
+-        goto cleanup;
+-
+-    ret = 0;
+-
+- cleanup:
+-    return ret;
++    VIR_CGROUP_BACKEND_CALL(group, allowAllDevices, -1, perms);
+ }
+ 
+ 
+diff --git a/src/util/vircgroupbackend.h b/src/util/vircgroupbackend.h
+index 04897b5895..436c83f6fa 100644
+--- a/src/util/vircgroupbackend.h
++++ b/src/util/vircgroupbackend.h
+@@ -269,6 +269,13 @@ typedef int
+                          int minor,
+                          int perms);
+ 
++typedef int
++(*virCgroupAllowAllDevicesCB)(virCgroupPtr group,
++                              int perms);
++
++typedef int
++(*virCgroupDenyAllDevicesCB)(virCgroupPtr group);
++
+ struct _virCgroupBackend {
+     virCgroupBackendType type;
+ 
+@@ -321,6 +328,8 @@ struct _virCgroupBackend {
+ 
+     virCgroupAllowDeviceCB allowDevice;
+     virCgroupDenyDeviceCB denyDevice;
++    virCgroupAllowAllDevicesCB allowAllDevices;
++    virCgroupDenyAllDevicesCB denyAllDevices;
+ };
+ typedef struct _virCgroupBackend virCgroupBackend;
+ typedef virCgroupBackend *virCgroupBackendPtr;
+diff --git a/src/util/vircgroupv1.c b/src/util/vircgroupv1.c
+index 02cd7ab956..34393812d2 100644
+--- a/src/util/vircgroupv1.c
++++ b/src/util/vircgroupv1.c
+@@ -1737,6 +1737,35 @@ virCgroupV1DenyDevice(virCgroupPtr group,
+ }
+ 
+ 
++static int
++virCgroupV1AllowAllDevices(virCgroupPtr group,
++                           int perms)
++{
++    int ret = -1;
++
++    if (virCgroupV1AllowDevice(group, 'b', -1, -1, perms) < 0)
++        goto cleanup;
++
++    if (virCgroupV1AllowDevice(group, 'c', -1, -1, perms) < 0)
++        goto cleanup;
++
++    ret = 0;
++
++ cleanup:
++    return ret;
++}
++
++
++static int
++virCgroupV1DenyAllDevices(virCgroupPtr group)
++{
++    return virCgroupSetValueStr(group,
++                                VIR_CGROUP_CONTROLLER_DEVICES,
++                                "devices.deny",
++                                "a");
++}
++
++
+ virCgroupBackend virCgroupV1Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V1,
+ 
+@@ -1787,6 +1816,8 @@ virCgroupBackend virCgroupV1Backend = {
+ 
+     .allowDevice = virCgroupV1AllowDevice,
+     .denyDevice = virCgroupV1DenyDevice,
++    .allowAllDevices = virCgroupV1AllowAllDevices,
++    .denyAllDevices = virCgroupV1DenyAllDevices,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-extract-virCgroupV1-Allow-Deny-Device.patch b/SOURCES/libvirt-vircgroup-extract-virCgroupV1-Allow-Deny-Device.patch
new file mode 100644
index 0000000..234d5f8
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-extract-virCgroupV1-Allow-Deny-Device.patch
@@ -0,0 +1,250 @@
+From 43695c7877a99d12bab96ec17c7d7de250ffc39a Mon Sep 17 00:00:00 2001
+Message-Id: <43695c7877a99d12bab96ec17c7d7de250ffc39a@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:06:54 +0200
+Subject: [PATCH] vircgroup: extract virCgroupV1(Allow|Deny)Device
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 8cbb0c76ba24878229830c8d53b365cf4dc1b54d)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <9a4073085dbeb674b24544aa253960bb2b1b53dc.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c        | 68 +++++++-----------------------------
+ src/util/vircgroupbackend.h | 17 +++++++++
+ src/util/vircgroupv1.c      | 69 +++++++++++++++++++++++++++++++++++++
+ 3 files changed, 98 insertions(+), 56 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index 088e97cb3f..a30fc6241d 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -1875,29 +1875,7 @@ int
+ virCgroupAllowDevice(virCgroupPtr group, char type, int major, int minor,
+                      int perms)
+ {
+-    VIR_AUTOFREE(char *) devstr = NULL;
+-    VIR_AUTOFREE(char *) majorstr = NULL;
+-    VIR_AUTOFREE(char *) minorstr = NULL;
+-
+-    if ((major < 0 && VIR_STRDUP(majorstr, "*") < 0) ||
+-        (major >= 0 && virAsprintf(&majorstr, "%i", major) < 0))
+-        return -1;
+-
+-    if ((minor < 0 && VIR_STRDUP(minorstr, "*") < 0) ||
+-        (minor >= 0 && virAsprintf(&minorstr, "%i", minor) < 0))
+-        return -1;
+-
+-    if (virAsprintf(&devstr, "%c %s:%s %s", type, majorstr, minorstr,
+-                    virCgroupGetDevicePermsString(perms)) < 0)
+-        return -1;
+-
+-    if (virCgroupSetValueStr(group,
+-                             VIR_CGROUP_CONTROLLER_DEVICES,
+-                             "devices.allow",
+-                             devstr) < 0)
+-        return -1;
+-
+-    return 0;
++    VIR_CGROUP_BACKEND_CALL(group, allowDevice, -1, type, major, minor, perms);
+ }
+ 
+ 
+@@ -1936,11 +1914,11 @@ virCgroupAllowDevicePath(virCgroupPtr group,
+     if (!S_ISCHR(sb.st_mode) && !S_ISBLK(sb.st_mode))
+         return 1;
+ 
+-    return virCgroupAllowDevice(group,
+-                                S_ISCHR(sb.st_mode) ? 'c' : 'b',
+-                                major(sb.st_rdev),
+-                                minor(sb.st_rdev),
+-                                perms);
++    VIR_CGROUP_BACKEND_CALL(group, allowDevice, -1,
++                            S_ISCHR(sb.st_mode) ? 'c' : 'b',
++                            major(sb.st_rdev),
++                            minor(sb.st_rdev),
++                            perms);
+ }
+ 
+ 
+@@ -1959,29 +1937,7 @@ int
+ virCgroupDenyDevice(virCgroupPtr group, char type, int major, int minor,
+                     int perms)
+ {
+-    VIR_AUTOFREE(char *) devstr = NULL;
+-    VIR_AUTOFREE(char *) majorstr = NULL;
+-    VIR_AUTOFREE(char *) minorstr = NULL;
+-
+-    if ((major < 0 && VIR_STRDUP(majorstr, "*") < 0) ||
+-        (major >= 0 && virAsprintf(&majorstr, "%i", major) < 0))
+-        return -1;
+-
+-    if ((minor < 0 && VIR_STRDUP(minorstr, "*") < 0) ||
+-        (minor >= 0 && virAsprintf(&minorstr, "%i", minor) < 0))
+-        return -1;
+-
+-    if (virAsprintf(&devstr, "%c %s:%s %s", type, majorstr, minorstr,
+-                    virCgroupGetDevicePermsString(perms)) < 0)
+-        return -1;
+-
+-    if (virCgroupSetValueStr(group,
+-                             VIR_CGROUP_CONTROLLER_DEVICES,
+-                             "devices.deny",
+-                             devstr) < 0)
+-        return -1;
+-
+-    return 0;
++    VIR_CGROUP_BACKEND_CALL(group, denyDevice, -1, type, major, minor, perms);
+ }
+ 
+ 
+@@ -2020,11 +1976,11 @@ virCgroupDenyDevicePath(virCgroupPtr group,
+     if (!S_ISCHR(sb.st_mode) && !S_ISBLK(sb.st_mode))
+         return 1;
+ 
+-    return virCgroupDenyDevice(group,
+-                               S_ISCHR(sb.st_mode) ? 'c' : 'b',
+-                               major(sb.st_rdev),
+-                               minor(sb.st_rdev),
+-                               perms);
++    VIR_CGROUP_BACKEND_CALL(group, denyDevice, -1,
++                            S_ISCHR(sb.st_mode) ? 'c' : 'b',
++                            major(sb.st_rdev),
++                            minor(sb.st_rdev),
++                            perms);
+ }
+ 
+ 
+diff --git a/src/util/vircgroupbackend.h b/src/util/vircgroupbackend.h
+index 27e6b18ea2..04897b5895 100644
+--- a/src/util/vircgroupbackend.h
++++ b/src/util/vircgroupbackend.h
+@@ -255,6 +255,20 @@ typedef int
+ (*virCgroupGetMemSwapUsageCB)(virCgroupPtr group,
+                               unsigned long long *kb);
+ 
++typedef int
++(*virCgroupAllowDeviceCB)(virCgroupPtr group,
++                          char type,
++                          int major,
++                          int minor,
++                          int perms);
++
++typedef int
++(*virCgroupDenyDeviceCB)(virCgroupPtr group,
++                         char type,
++                         int major,
++                         int minor,
++                         int perms);
++
+ struct _virCgroupBackend {
+     virCgroupBackendType type;
+ 
+@@ -304,6 +318,9 @@ struct _virCgroupBackend {
+     virCgroupSetMemSwapHardLimitCB setMemSwapHardLimit;
+     virCgroupGetMemSwapHardLimitCB getMemSwapHardLimit;
+     virCgroupGetMemSwapUsageCB getMemSwapUsage;
++
++    virCgroupAllowDeviceCB allowDevice;
++    virCgroupDenyDeviceCB denyDevice;
+ };
+ typedef struct _virCgroupBackend virCgroupBackend;
+ typedef virCgroupBackend *virCgroupBackendPtr;
+diff --git a/src/util/vircgroupv1.c b/src/util/vircgroupv1.c
+index 55b1d3ebd0..02cd7ab956 100644
+--- a/src/util/vircgroupv1.c
++++ b/src/util/vircgroupv1.c
+@@ -1671,6 +1671,72 @@ virCgroupV1GetMemSwapUsage(virCgroupPtr group,
+ }
+ 
+ 
++static int
++virCgroupV1AllowDevice(virCgroupPtr group,
++                       char type,
++                       int major,
++                       int minor,
++                       int perms)
++{
++    VIR_AUTOFREE(char *) devstr = NULL;
++    VIR_AUTOFREE(char *) majorstr = NULL;
++    VIR_AUTOFREE(char *) minorstr = NULL;
++
++    if ((major < 0 && VIR_STRDUP(majorstr, "*") < 0) ||
++        (major >= 0 && virAsprintf(&majorstr, "%i", major) < 0))
++        return -1;
++
++    if ((minor < 0 && VIR_STRDUP(minorstr, "*") < 0) ||
++        (minor >= 0 && virAsprintf(&minorstr, "%i", minor) < 0))
++        return -1;
++
++    if (virAsprintf(&devstr, "%c %s:%s %s", type, majorstr, minorstr,
++                    virCgroupGetDevicePermsString(perms)) < 0)
++        return -1;
++
++    if (virCgroupSetValueStr(group,
++                             VIR_CGROUP_CONTROLLER_DEVICES,
++                             "devices.allow",
++                             devstr) < 0)
++        return -1;
++
++    return 0;
++}
++
++
++static int
++virCgroupV1DenyDevice(virCgroupPtr group,
++                      char type,
++                      int major,
++                      int minor,
++                      int perms)
++{
++    VIR_AUTOFREE(char *) devstr = NULL;
++    VIR_AUTOFREE(char *) majorstr = NULL;
++    VIR_AUTOFREE(char *) minorstr = NULL;
++
++    if ((major < 0 && VIR_STRDUP(majorstr, "*") < 0) ||
++        (major >= 0 && virAsprintf(&majorstr, "%i", major) < 0))
++        return -1;
++
++    if ((minor < 0 && VIR_STRDUP(minorstr, "*") < 0) ||
++        (minor >= 0 && virAsprintf(&minorstr, "%i", minor) < 0))
++        return -1;
++
++    if (virAsprintf(&devstr, "%c %s:%s %s", type, majorstr, minorstr,
++                    virCgroupGetDevicePermsString(perms)) < 0)
++        return -1;
++
++    if (virCgroupSetValueStr(group,
++                             VIR_CGROUP_CONTROLLER_DEVICES,
++                             "devices.deny",
++                             devstr) < 0)
++        return -1;
++
++    return 0;
++}
++
++
+ virCgroupBackend virCgroupV1Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V1,
+ 
+@@ -1718,6 +1784,9 @@ virCgroupBackend virCgroupV1Backend = {
+     .setMemSwapHardLimit = virCgroupV1SetMemSwapHardLimit,
+     .getMemSwapHardLimit = virCgroupV1GetMemSwapHardLimit,
+     .getMemSwapUsage = virCgroupV1GetMemSwapUsage,
++
++    .allowDevice = virCgroupV1AllowDevice,
++    .denyDevice = virCgroupV1DenyDevice,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-extract-virCgroupV1-Set-Get-BlkioDeviceReadBps.patch b/SOURCES/libvirt-vircgroup-extract-virCgroupV1-Set-Get-BlkioDeviceReadBps.patch
new file mode 100644
index 0000000..13c3c14
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-extract-virCgroupV1-Set-Get-BlkioDeviceReadBps.patch
@@ -0,0 +1,181 @@
+From d18c1d955b505493213e540d427868cc74e03c64 Mon Sep 17 00:00:00 2001
+Message-Id: <d18c1d955b505493213e540d427868cc74e03c64@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:06:47 +0200
+Subject: [PATCH] vircgroup: extract virCgroupV1(Set|Get)BlkioDeviceReadBps
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 32f199250bd52fe52cba6bfbc3ee6a7f6c88c2ff)
+
+Conflicts:
+    src/util/vircgroup.c - missing commit 34e9c29357
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <562851da4866890cef588cf7f6f890118f3f81f4.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c        | 34 ++-----------------------
+ src/util/vircgroupbackend.h | 12 +++++++++
+ src/util/vircgroupv1.c      | 50 +++++++++++++++++++++++++++++++++++++
+ 3 files changed, 64 insertions(+), 32 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index 4b682d72d7..ab587ea306 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -1419,19 +1419,7 @@ virCgroupSetBlkioDeviceReadBps(virCgroupPtr group,
+                                const char *path,
+                                unsigned long long rbps)
+ {
+-    VIR_AUTOFREE(char *) str = NULL;
+-    VIR_AUTOFREE(char *) blkstr = NULL;
+-
+-    if (!(blkstr = virCgroupGetBlockDevString(path)))
+-        return -1;
+-
+-    if (virAsprintf(&str, "%s%llu", blkstr, rbps) < 0)
+-        return -1;
+-
+-    return virCgroupSetValueStr(group,
+-                               VIR_CGROUP_CONTROLLER_BLKIO,
+-                               "blkio.throttle.read_bps_device",
+-                               str);
++    VIR_CGROUP_BACKEND_CALL(group, setBlkioDeviceReadBps, -1, path, rbps);
+ }
+ 
+ /**
+@@ -1525,25 +1513,7 @@ virCgroupGetBlkioDeviceReadBps(virCgroupPtr group,
+                                const char *path,
+                                unsigned long long *rbps)
+ {
+-    VIR_AUTOFREE(char *) str = NULL;
+-
+-    if (virCgroupGetValueForBlkDev(group,
+-                                   VIR_CGROUP_CONTROLLER_BLKIO,
+-                                   "blkio.throttle.read_bps_device",
+-                                   path,
+-                                   &str) < 0)
+-        return -1;
+-
+-    if (!str) {
+-        *rbps = 0;
+-    } else if (virStrToLong_ull(str, NULL, 10, rbps) < 0) {
+-        virReportError(VIR_ERR_INTERNAL_ERROR,
+-                       _("Unable to parse '%s' as an integer"),
+-                       str);
+-        return -1;
+-    }
+-
+-    return 0;
++    VIR_CGROUP_BACKEND_CALL(group, getBlkioDeviceReadBps, -1, path, rbps);
+ }
+ 
+ /**
+diff --git a/src/util/vircgroupbackend.h b/src/util/vircgroupbackend.h
+index 58e1828e01..3f1055a5d8 100644
+--- a/src/util/vircgroupbackend.h
++++ b/src/util/vircgroupbackend.h
+@@ -190,6 +190,16 @@ typedef int
+                                       const char *path,
+                                       unsigned int *wiops);
+ 
++typedef int
++(*virCgroupSetBlkioDeviceReadBpsCB)(virCgroupPtr group,
++                                    const char *path,
++                                    unsigned long long rbps);
++
++typedef int
++(*virCgroupGetBlkioDeviceReadBpsCB)(virCgroupPtr group,
++                                    const char *path,
++                                    unsigned long long *rbps);
++
+ struct _virCgroupBackend {
+     virCgroupBackendType type;
+ 
+@@ -224,6 +234,8 @@ struct _virCgroupBackend {
+     virCgroupGetBlkioDeviceReadIopsCB getBlkioDeviceReadIops;
+     virCgroupSetBlkioDeviceWriteIopsCB setBlkioDeviceWriteIops;
+     virCgroupGetBlkioDeviceWriteIopsCB getBlkioDeviceWriteIops;
++    virCgroupSetBlkioDeviceReadBpsCB setBlkioDeviceReadBps;
++    virCgroupGetBlkioDeviceReadBpsCB getBlkioDeviceReadBps;
+ };
+ typedef struct _virCgroupBackend virCgroupBackend;
+ typedef virCgroupBackend *virCgroupBackendPtr;
+diff --git a/src/util/vircgroupv1.c b/src/util/vircgroupv1.c
+index 5b0199a89f..e5663ccfb9 100644
+--- a/src/util/vircgroupv1.c
++++ b/src/util/vircgroupv1.c
+@@ -1282,6 +1282,54 @@ virCgroupV1GetBlkioDeviceWriteIops(virCgroupPtr group,
+ }
+ 
+ 
++static int
++virCgroupV1SetBlkioDeviceReadBps(virCgroupPtr group,
++                                 const char *path,
++                                 unsigned long long rbps)
++{
++    VIR_AUTOFREE(char *) str = NULL;
++    VIR_AUTOFREE(char *) blkstr = NULL;
++
++    if (!(blkstr = virCgroupGetBlockDevString(path)))
++        return -1;
++
++    if (virAsprintf(&str, "%s%llu", blkstr, rbps) < 0)
++        return -1;
++
++    return virCgroupSetValueStr(group,
++                                VIR_CGROUP_CONTROLLER_BLKIO,
++                                "blkio.throttle.read_bps_device",
++                                str);
++}
++
++
++static int
++virCgroupV1GetBlkioDeviceReadBps(virCgroupPtr group,
++                                 const char *path,
++                                 unsigned long long *rbps)
++{
++    VIR_AUTOFREE(char *) str = NULL;
++
++    if (virCgroupGetValueForBlkDev(group,
++                                   VIR_CGROUP_CONTROLLER_BLKIO,
++                                   "blkio.throttle.read_bps_device",
++                                   path,
++                                   &str) < 0)
++        return -1;
++
++    if (!str) {
++        *rbps = 0;
++    } else if (virStrToLong_ull(str, NULL, 10, rbps) < 0) {
++        virReportError(VIR_ERR_INTERNAL_ERROR,
++                       _("Unable to parse '%s' as an integer"),
++                       str);
++        return -1;
++    }
++
++    return 0;
++}
++
++
+ virCgroupBackend virCgroupV1Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V1,
+ 
+@@ -1314,6 +1362,8 @@ virCgroupBackend virCgroupV1Backend = {
+     .getBlkioDeviceReadIops = virCgroupV1GetBlkioDeviceReadIops,
+     .setBlkioDeviceWriteIops = virCgroupV1SetBlkioDeviceWriteIops,
+     .getBlkioDeviceWriteIops = virCgroupV1GetBlkioDeviceWriteIops,
++    .setBlkioDeviceReadBps = virCgroupV1SetBlkioDeviceReadBps,
++    .getBlkioDeviceReadBps = virCgroupV1GetBlkioDeviceReadBps,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-extract-virCgroupV1-Set-Get-BlkioDeviceReadIops.patch b/SOURCES/libvirt-vircgroup-extract-virCgroupV1-Set-Get-BlkioDeviceReadIops.patch
new file mode 100644
index 0000000..878a5cd
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-extract-virCgroupV1-Set-Get-BlkioDeviceReadIops.patch
@@ -0,0 +1,181 @@
+From 0528d90148bcacba3fdbaa831ba89e043da94790 Mon Sep 17 00:00:00 2001
+Message-Id: <0528d90148bcacba3fdbaa831ba89e043da94790@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:06:45 +0200
+Subject: [PATCH] vircgroup: extract virCgroupV1(Set|Get)BlkioDeviceReadIops
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit dfaf5c6de1afa04fee1d9d97e79925fcc63682de)
+
+Conflicts:
+    src/util/vircgroup.c - missing commit 34e9c29357
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <52a494fa2de2835abd887d804f4047febc87bb60.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c        | 34 ++-----------------------
+ src/util/vircgroupbackend.h | 12 +++++++++
+ src/util/vircgroupv1.c      | 50 +++++++++++++++++++++++++++++++++++++
+ 3 files changed, 64 insertions(+), 32 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index 83ceb3a9cb..b8cbd95e0c 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -1385,19 +1385,7 @@ virCgroupSetBlkioDeviceReadIops(virCgroupPtr group,
+                                 const char *path,
+                                 unsigned int riops)
+ {
+-    VIR_AUTOFREE(char *) str = NULL;
+-    VIR_AUTOFREE(char *) blkstr = NULL;
+-
+-    if (!(blkstr = virCgroupGetBlockDevString(path)))
+-        return -1;
+-
+-    if (virAsprintf(&str, "%s%u", blkstr, riops) < 0)
+-        return -1;
+-
+-    return virCgroupSetValueStr(group,
+-                               VIR_CGROUP_CONTROLLER_BLKIO,
+-                               "blkio.throttle.read_iops_device",
+-                               str);
++    VIR_CGROUP_BACKEND_CALL(group, setBlkioDeviceReadIops, -1, path, riops);
+ }
+ 
+ 
+@@ -1517,25 +1505,7 @@ virCgroupGetBlkioDeviceReadIops(virCgroupPtr group,
+                                 const char *path,
+                                 unsigned int *riops)
+ {
+-    VIR_AUTOFREE(char *) str = NULL;
+-
+-    if (virCgroupGetValueForBlkDev(group,
+-                                   VIR_CGROUP_CONTROLLER_BLKIO,
+-                                   "blkio.throttle.read_iops_device",
+-                                   path,
+-                                   &str) < 0)
+-        return -1;
+-
+-    if (!str) {
+-        *riops = 0;
+-    } else if (virStrToLong_ui(str, NULL, 10, riops) < 0) {
+-        virReportError(VIR_ERR_INTERNAL_ERROR,
+-                       _("Unable to parse '%s' as an integer"),
+-                       str);
+-        return -1;
+-    }
+-
+-    return 0;
++    VIR_CGROUP_BACKEND_CALL(group, getBlkioDeviceReadIops, -1, path, riops);
+ }
+ 
+ /**
+diff --git a/src/util/vircgroupbackend.h b/src/util/vircgroupbackend.h
+index aef2a87c61..0b7b4db1a4 100644
+--- a/src/util/vircgroupbackend.h
++++ b/src/util/vircgroupbackend.h
+@@ -170,6 +170,16 @@ typedef int
+                                    const char *path,
+                                    unsigned int *weight);
+ 
++typedef int
++(*virCgroupSetBlkioDeviceReadIopsCB)(virCgroupPtr group,
++                                     const char *path,
++                                     unsigned int riops);
++
++typedef int
++(*virCgroupGetBlkioDeviceReadIopsCB)(virCgroupPtr group,
++                                     const char *path,
++                                     unsigned int *riops);
++
+ struct _virCgroupBackend {
+     virCgroupBackendType type;
+ 
+@@ -200,6 +210,8 @@ struct _virCgroupBackend {
+     virCgroupGetBlkioIoDeviceServicedCB getBlkioIoDeviceServiced;
+     virCgroupSetBlkioDeviceWeightCB setBlkioDeviceWeight;
+     virCgroupGetBlkioDeviceWeightCB getBlkioDeviceWeight;
++    virCgroupSetBlkioDeviceReadIopsCB setBlkioDeviceReadIops;
++    virCgroupGetBlkioDeviceReadIopsCB getBlkioDeviceReadIops;
+ };
+ typedef struct _virCgroupBackend virCgroupBackend;
+ typedef virCgroupBackend *virCgroupBackendPtr;
+diff --git a/src/util/vircgroupv1.c b/src/util/vircgroupv1.c
+index 1e5f38a2ee..47b0c13f38 100644
+--- a/src/util/vircgroupv1.c
++++ b/src/util/vircgroupv1.c
+@@ -1186,6 +1186,54 @@ virCgroupV1GetBlkioDeviceWeight(virCgroupPtr group,
+ }
+ 
+ 
++static int
++virCgroupV1SetBlkioDeviceReadIops(virCgroupPtr group,
++                                  const char *path,
++                                  unsigned int riops)
++{
++    VIR_AUTOFREE(char *) str = NULL;
++    VIR_AUTOFREE(char *) blkstr = NULL;
++
++    if (!(blkstr = virCgroupGetBlockDevString(path)))
++        return -1;
++
++    if (virAsprintf(&str, "%s%u", blkstr, riops) < 0)
++        return -1;
++
++    return virCgroupSetValueStr(group,
++                                VIR_CGROUP_CONTROLLER_BLKIO,
++                                "blkio.throttle.read_iops_device",
++                                str);
++}
++
++
++static int
++virCgroupV1GetBlkioDeviceReadIops(virCgroupPtr group,
++                                  const char *path,
++                                  unsigned int *riops)
++{
++    VIR_AUTOFREE(char *) str = NULL;
++
++    if (virCgroupGetValueForBlkDev(group,
++                                   VIR_CGROUP_CONTROLLER_BLKIO,
++                                   "blkio.throttle.read_iops_device",
++                                   path,
++                                   &str) < 0)
++        return -1;
++
++    if (!str) {
++        *riops = 0;
++    } else if (virStrToLong_ui(str, NULL, 10, riops) < 0) {
++        virReportError(VIR_ERR_INTERNAL_ERROR,
++                       _("Unable to parse '%s' as an integer"),
++                       str);
++        return -1;
++    }
++
++    return 0;
++}
++
++
+ virCgroupBackend virCgroupV1Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V1,
+ 
+@@ -1214,6 +1262,8 @@ virCgroupBackend virCgroupV1Backend = {
+     .getBlkioIoDeviceServiced = virCgroupV1GetBlkioIoDeviceServiced,
+     .setBlkioDeviceWeight = virCgroupV1SetBlkioDeviceWeight,
+     .getBlkioDeviceWeight = virCgroupV1GetBlkioDeviceWeight,
++    .setBlkioDeviceReadIops = virCgroupV1SetBlkioDeviceReadIops,
++    .getBlkioDeviceReadIops = virCgroupV1GetBlkioDeviceReadIops,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-extract-virCgroupV1-Set-Get-BlkioDeviceWeight.patch b/SOURCES/libvirt-vircgroup-extract-virCgroupV1-Set-Get-BlkioDeviceWeight.patch
new file mode 100644
index 0000000..7d870b2
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-extract-virCgroupV1-Set-Get-BlkioDeviceWeight.patch
@@ -0,0 +1,208 @@
+From af26c5b793fcd0206a105e75c6583ddfe57557c2 Mon Sep 17 00:00:00 2001
+Message-Id: <af26c5b793fcd0206a105e75c6583ddfe57557c2@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:06:44 +0200
+Subject: [PATCH] vircgroup: extract virCgroupV1(Set|Get)BlkioDeviceWeight
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 8f50f9ca24596c838082c7d8da4ffe7104d22b23)
+
+Conflicts:
+    src/util/vircgroup.c - missing commit 34e9c29357
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <1ad5f481f00748a6808760b50f4d1d0116191073.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c        | 36 +++-----------------------
+ src/util/vircgroupbackend.h | 12 +++++++++
+ src/util/vircgrouppriv.h    |  6 +++++
+ src/util/vircgroupv1.c      | 50 +++++++++++++++++++++++++++++++++++++
+ 4 files changed, 71 insertions(+), 33 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index fd39144ed2..83ceb3a9cb 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -498,7 +498,7 @@ virCgroupGetValueStr(virCgroupPtr group,
+ }
+ 
+ 
+-static int
++int
+ virCgroupGetValueForBlkDev(virCgroupPtr group,
+                            int controller,
+                            const char *key,
+@@ -1501,19 +1501,7 @@ virCgroupSetBlkioDeviceWeight(virCgroupPtr group,
+                               const char *path,
+                               unsigned int weight)
+ {
+-    VIR_AUTOFREE(char *) str = NULL;
+-    VIR_AUTOFREE(char *) blkstr = NULL;
+-
+-    if (!(blkstr = virCgroupGetBlockDevString(path)))
+-        return -1;
+-
+-    if (virAsprintf(&str, "%s%d", blkstr, weight) < 0)
+-        return -1;
+-
+-    return virCgroupSetValueStr(group,
+-                               VIR_CGROUP_CONTROLLER_BLKIO,
+-                               "blkio.weight_device",
+-                               str);
++    VIR_CGROUP_BACKEND_CALL(group, setBlkioDeviceWeight, -1, path, weight);
+ }
+ 
+ /**
+@@ -1665,25 +1653,7 @@ virCgroupGetBlkioDeviceWeight(virCgroupPtr group,
+                               const char *path,
+                               unsigned int *weight)
+ {
+-    VIR_AUTOFREE(char *) str = NULL;
+-
+-    if (virCgroupGetValueForBlkDev(group,
+-                                   VIR_CGROUP_CONTROLLER_BLKIO,
+-                                   "blkio.weight_device",
+-                                   path,
+-                                   &str) < 0)
+-        return -1;
+-
+-    if (!str) {
+-        *weight = 0;
+-    } else if (virStrToLong_ui(str, NULL, 10, weight) < 0) {
+-        virReportError(VIR_ERR_INTERNAL_ERROR,
+-                       _("Unable to parse '%s' as an integer"),
+-                       str);
+-        return -1;
+-    }
+-
+-    return 0;
++    VIR_CGROUP_BACKEND_CALL(group, getBlkioDeviceWeight, -1, path, weight);
+ }
+ 
+ 
+diff --git a/src/util/vircgroupbackend.h b/src/util/vircgroupbackend.h
+index e16d631a0f..aef2a87c61 100644
+--- a/src/util/vircgroupbackend.h
++++ b/src/util/vircgroupbackend.h
+@@ -160,6 +160,16 @@ typedef int
+                                        long long *requests_read,
+                                        long long *requests_write);
+ 
++typedef int
++(*virCgroupSetBlkioDeviceWeightCB)(virCgroupPtr group,
++                                   const char *path,
++                                   unsigned int weight);
++
++typedef int
++(*virCgroupGetBlkioDeviceWeightCB)(virCgroupPtr group,
++                                   const char *path,
++                                   unsigned int *weight);
++
+ struct _virCgroupBackend {
+     virCgroupBackendType type;
+ 
+@@ -188,6 +198,8 @@ struct _virCgroupBackend {
+     virCgroupGetBlkioWeightCB getBlkioWeight;
+     virCgroupGetBlkioIoServicedCB getBlkioIoServiced;
+     virCgroupGetBlkioIoDeviceServicedCB getBlkioIoDeviceServiced;
++    virCgroupSetBlkioDeviceWeightCB setBlkioDeviceWeight;
++    virCgroupGetBlkioDeviceWeightCB getBlkioDeviceWeight;
+ };
+ typedef struct _virCgroupBackend virCgroupBackend;
+ typedef virCgroupBackend *virCgroupBackendPtr;
+diff --git a/src/util/vircgrouppriv.h b/src/util/vircgrouppriv.h
+index 525c288a9a..3a968c1ce2 100644
+--- a/src/util/vircgrouppriv.h
++++ b/src/util/vircgrouppriv.h
+@@ -82,6 +82,12 @@ int virCgroupPartitionEscape(char **path);
+ 
+ char *virCgroupGetBlockDevString(const char *path);
+ 
++int virCgroupGetValueForBlkDev(virCgroupPtr group,
++                               int controller,
++                               const char *key,
++                               const char *path,
++                               char **value);
++
+ int virCgroupNewPartition(const char *path,
+                           bool create,
+                           int controllers,
+diff --git a/src/util/vircgroupv1.c b/src/util/vircgroupv1.c
+index 79c4812aef..1e5f38a2ee 100644
+--- a/src/util/vircgroupv1.c
++++ b/src/util/vircgroupv1.c
+@@ -1138,6 +1138,54 @@ virCgroupV1GetBlkioIoDeviceServiced(virCgroupPtr group,
+ }
+ 
+ 
++static int
++virCgroupV1SetBlkioDeviceWeight(virCgroupPtr group,
++                                const char *path,
++                                unsigned int weight)
++{
++    VIR_AUTOFREE(char *) str = NULL;
++    VIR_AUTOFREE(char *) blkstr = NULL;
++
++    if (!(blkstr = virCgroupGetBlockDevString(path)))
++        return -1;
++
++    if (virAsprintf(&str, "%s%d", blkstr, weight) < 0)
++        return -1;
++
++    return virCgroupSetValueStr(group,
++                                VIR_CGROUP_CONTROLLER_BLKIO,
++                                "blkio.weight_device",
++                                str);
++}
++
++
++static int
++virCgroupV1GetBlkioDeviceWeight(virCgroupPtr group,
++                                const char *path,
++                                unsigned int *weight)
++{
++    VIR_AUTOFREE(char *) str = NULL;
++
++    if (virCgroupGetValueForBlkDev(group,
++                                   VIR_CGROUP_CONTROLLER_BLKIO,
++                                   "blkio.weight_device",
++                                   path,
++                                   &str) < 0)
++        return -1;
++
++    if (!str) {
++        *weight = 0;
++    } else if (virStrToLong_ui(str, NULL, 10, weight) < 0) {
++        virReportError(VIR_ERR_INTERNAL_ERROR,
++                       _("Unable to parse '%s' as an integer"),
++                       str);
++        return -1;
++    }
++
++    return 0;
++}
++
++
+ virCgroupBackend virCgroupV1Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V1,
+ 
+@@ -1164,6 +1212,8 @@ virCgroupBackend virCgroupV1Backend = {
+     .getBlkioWeight = virCgroupV1GetBlkioWeight,
+     .getBlkioIoServiced = virCgroupV1GetBlkioIoServiced,
+     .getBlkioIoDeviceServiced = virCgroupV1GetBlkioIoDeviceServiced,
++    .setBlkioDeviceWeight = virCgroupV1SetBlkioDeviceWeight,
++    .getBlkioDeviceWeight = virCgroupV1GetBlkioDeviceWeight,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-extract-virCgroupV1-Set-Get-BlkioDeviceWriteBps.patch b/SOURCES/libvirt-vircgroup-extract-virCgroupV1-Set-Get-BlkioDeviceWriteBps.patch
new file mode 100644
index 0000000..273253a
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-extract-virCgroupV1-Set-Get-BlkioDeviceWriteBps.patch
@@ -0,0 +1,181 @@
+From a9c415edc1bc386ac6f4be91e98fe23469b62011 Mon Sep 17 00:00:00 2001
+Message-Id: <a9c415edc1bc386ac6f4be91e98fe23469b62011@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:06:48 +0200
+Subject: [PATCH] vircgroup: extract virCgroupV1(Set|Get)BlkioDeviceWriteBps
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 02fe32d3aa965b21342bc2dee245e6e8e5ca8bf7)
+
+Conflicts:
+    src/util/vircgroup.c - missing commit 34e9c29357
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <3bbdc28fe71070c8e351679a17d6889b866b46fd.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c        | 34 ++-----------------------
+ src/util/vircgroupbackend.h | 12 +++++++++
+ src/util/vircgroupv1.c      | 50 +++++++++++++++++++++++++++++++++++++
+ 3 files changed, 64 insertions(+), 32 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index ab587ea306..684bce4997 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -1435,19 +1435,7 @@ virCgroupSetBlkioDeviceWriteBps(virCgroupPtr group,
+                                 const char *path,
+                                 unsigned long long wbps)
+ {
+-    VIR_AUTOFREE(char *) str = NULL;
+-    VIR_AUTOFREE(char *) blkstr = NULL;
+-
+-    if (!(blkstr = virCgroupGetBlockDevString(path)))
+-        return -1;
+-
+-    if (virAsprintf(&str, "%s%llu", blkstr, wbps) < 0)
+-        return -1;
+-
+-    return virCgroupSetValueStr(group,
+-                               VIR_CGROUP_CONTROLLER_BLKIO,
+-                               "blkio.throttle.write_bps_device",
+-                               str);
++    VIR_CGROUP_BACKEND_CALL(group, setBlkioDeviceWriteBps, -1, path, wbps);
+ }
+ 
+ 
+@@ -1529,25 +1517,7 @@ virCgroupGetBlkioDeviceWriteBps(virCgroupPtr group,
+                                 const char *path,
+                                 unsigned long long *wbps)
+ {
+-    VIR_AUTOFREE(char *) str = NULL;
+-
+-    if (virCgroupGetValueForBlkDev(group,
+-                                   VIR_CGROUP_CONTROLLER_BLKIO,
+-                                   "blkio.throttle.write_bps_device",
+-                                   path,
+-                                   &str) < 0)
+-        return -1;
+-
+-    if (!str) {
+-        *wbps = 0;
+-    } else if (virStrToLong_ull(str, NULL, 10, wbps) < 0) {
+-        virReportError(VIR_ERR_INTERNAL_ERROR,
+-                       _("Unable to parse '%s' as an integer"),
+-                       str);
+-        return -1;
+-    }
+-
+-    return 0;
++    VIR_CGROUP_BACKEND_CALL(group, getBlkioDeviceWriteBps, -1, path, wbps);
+ }
+ 
+ /**
+diff --git a/src/util/vircgroupbackend.h b/src/util/vircgroupbackend.h
+index 3f1055a5d8..67e795a2b7 100644
+--- a/src/util/vircgroupbackend.h
++++ b/src/util/vircgroupbackend.h
+@@ -200,6 +200,16 @@ typedef int
+                                     const char *path,
+                                     unsigned long long *rbps);
+ 
++typedef int
++(*virCgroupSetBlkioDeviceWriteBpsCB)(virCgroupPtr group,
++                                     const char *path,
++                                     unsigned long long wbps);
++
++typedef int
++(*virCgroupGetBlkioDeviceWriteBpsCB)(virCgroupPtr group,
++                                     const char *path,
++                                     unsigned long long *wbps);
++
+ struct _virCgroupBackend {
+     virCgroupBackendType type;
+ 
+@@ -236,6 +246,8 @@ struct _virCgroupBackend {
+     virCgroupGetBlkioDeviceWriteIopsCB getBlkioDeviceWriteIops;
+     virCgroupSetBlkioDeviceReadBpsCB setBlkioDeviceReadBps;
+     virCgroupGetBlkioDeviceReadBpsCB getBlkioDeviceReadBps;
++    virCgroupSetBlkioDeviceWriteBpsCB setBlkioDeviceWriteBps;
++    virCgroupGetBlkioDeviceWriteBpsCB getBlkioDeviceWriteBps;
+ };
+ typedef struct _virCgroupBackend virCgroupBackend;
+ typedef virCgroupBackend *virCgroupBackendPtr;
+diff --git a/src/util/vircgroupv1.c b/src/util/vircgroupv1.c
+index e5663ccfb9..c044414dfd 100644
+--- a/src/util/vircgroupv1.c
++++ b/src/util/vircgroupv1.c
+@@ -1330,6 +1330,54 @@ virCgroupV1GetBlkioDeviceReadBps(virCgroupPtr group,
+ }
+ 
+ 
++static int
++virCgroupV1SetBlkioDeviceWriteBps(virCgroupPtr group,
++                                  const char *path,
++                                  unsigned long long wbps)
++{
++    VIR_AUTOFREE(char *) str = NULL;
++    VIR_AUTOFREE(char *) blkstr = NULL;
++
++    if (!(blkstr = virCgroupGetBlockDevString(path)))
++        return -1;
++
++    if (virAsprintf(&str, "%s%llu", blkstr, wbps) < 0)
++        return -1;
++
++    return virCgroupSetValueStr(group,
++                                VIR_CGROUP_CONTROLLER_BLKIO,
++                                "blkio.throttle.write_bps_device",
++                                str);
++}
++
++
++static int
++virCgroupV1GetBlkioDeviceWriteBps(virCgroupPtr group,
++                                  const char *path,
++                                  unsigned long long *wbps)
++{
++    VIR_AUTOFREE(char *) str = NULL;
++
++    if (virCgroupGetValueForBlkDev(group,
++                                   VIR_CGROUP_CONTROLLER_BLKIO,
++                                   "blkio.throttle.write_bps_device",
++                                   path,
++                                   &str) < 0)
++        return -1;
++
++    if (!str) {
++        *wbps = 0;
++    } else if (virStrToLong_ull(str, NULL, 10, wbps) < 0) {
++        virReportError(VIR_ERR_INTERNAL_ERROR,
++                       _("Unable to parse '%s' as an integer"),
++                       str);
++        return -1;
++    }
++
++    return 0;
++}
++
++
+ virCgroupBackend virCgroupV1Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V1,
+ 
+@@ -1364,6 +1412,8 @@ virCgroupBackend virCgroupV1Backend = {
+     .getBlkioDeviceWriteIops = virCgroupV1GetBlkioDeviceWriteIops,
+     .setBlkioDeviceReadBps = virCgroupV1SetBlkioDeviceReadBps,
+     .getBlkioDeviceReadBps = virCgroupV1GetBlkioDeviceReadBps,
++    .setBlkioDeviceWriteBps = virCgroupV1SetBlkioDeviceWriteBps,
++    .getBlkioDeviceWriteBps = virCgroupV1GetBlkioDeviceWriteBps,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-extract-virCgroupV1-Set-Get-BlkioDeviceWriteIops.patch b/SOURCES/libvirt-vircgroup-extract-virCgroupV1-Set-Get-BlkioDeviceWriteIops.patch
new file mode 100644
index 0000000..caffe32
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-extract-virCgroupV1-Set-Get-BlkioDeviceWriteIops.patch
@@ -0,0 +1,181 @@
+From b80aeea66090c760fb2863d8bb7d682ff40a8361 Mon Sep 17 00:00:00 2001
+Message-Id: <b80aeea66090c760fb2863d8bb7d682ff40a8361@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:06:46 +0200
+Subject: [PATCH] vircgroup: extract virCgroupV1(Set|Get)BlkioDeviceWriteIops
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 2edd0bcda65122ba16f92c2b95f06ae7dad072ba)
+
+Conflicts:
+    src/util/vircgroup.c - missing commit 34e9c29357
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <10671a59ba137b61325a9d5a730f53a2032dd49b.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c        | 34 ++-----------------------
+ src/util/vircgroupbackend.h | 12 +++++++++
+ src/util/vircgroupv1.c      | 50 +++++++++++++++++++++++++++++++++++++
+ 3 files changed, 64 insertions(+), 32 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index b8cbd95e0c..4b682d72d7 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -1402,19 +1402,7 @@ virCgroupSetBlkioDeviceWriteIops(virCgroupPtr group,
+                                  const char *path,
+                                  unsigned int wiops)
+ {
+-    VIR_AUTOFREE(char *) str = NULL;
+-    VIR_AUTOFREE(char *) blkstr = NULL;
+-
+-    if (!(blkstr = virCgroupGetBlockDevString(path)))
+-        return -1;
+-
+-    if (virAsprintf(&str, "%s%u", blkstr, wiops) < 0)
+-        return -1;
+-
+-    return virCgroupSetValueStr(group,
+-                               VIR_CGROUP_CONTROLLER_BLKIO,
+-                               "blkio.throttle.write_iops_device",
+-                               str);
++    VIR_CGROUP_BACKEND_CALL(group, setBlkioDeviceWriteIops, -1, path, wiops);
+ }
+ 
+ 
+@@ -1521,25 +1509,7 @@ virCgroupGetBlkioDeviceWriteIops(virCgroupPtr group,
+                                  const char *path,
+                                  unsigned int *wiops)
+ {
+-    VIR_AUTOFREE(char *) str = NULL;
+-
+-    if (virCgroupGetValueForBlkDev(group,
+-                                   VIR_CGROUP_CONTROLLER_BLKIO,
+-                                   "blkio.throttle.write_iops_device",
+-                                   path,
+-                                   &str) < 0)
+-        return -1;
+-
+-    if (!str) {
+-        *wiops = 0;
+-    } else if (virStrToLong_ui(str, NULL, 10, wiops) < 0) {
+-        virReportError(VIR_ERR_INTERNAL_ERROR,
+-                       _("Unable to parse '%s' as an integer"),
+-                       str);
+-        return -1;
+-    }
+-
+-    return 0;
++    VIR_CGROUP_BACKEND_CALL(group, getBlkioDeviceWriteIops, -1, path, wiops);
+ }
+ 
+ /**
+diff --git a/src/util/vircgroupbackend.h b/src/util/vircgroupbackend.h
+index 0b7b4db1a4..58e1828e01 100644
+--- a/src/util/vircgroupbackend.h
++++ b/src/util/vircgroupbackend.h
+@@ -180,6 +180,16 @@ typedef int
+                                      const char *path,
+                                      unsigned int *riops);
+ 
++typedef int
++(*virCgroupSetBlkioDeviceWriteIopsCB)(virCgroupPtr group,
++                                      const char *path,
++                                      unsigned int wiops);
++
++typedef int
++(*virCgroupGetBlkioDeviceWriteIopsCB)(virCgroupPtr group,
++                                      const char *path,
++                                      unsigned int *wiops);
++
+ struct _virCgroupBackend {
+     virCgroupBackendType type;
+ 
+@@ -212,6 +222,8 @@ struct _virCgroupBackend {
+     virCgroupGetBlkioDeviceWeightCB getBlkioDeviceWeight;
+     virCgroupSetBlkioDeviceReadIopsCB setBlkioDeviceReadIops;
+     virCgroupGetBlkioDeviceReadIopsCB getBlkioDeviceReadIops;
++    virCgroupSetBlkioDeviceWriteIopsCB setBlkioDeviceWriteIops;
++    virCgroupGetBlkioDeviceWriteIopsCB getBlkioDeviceWriteIops;
+ };
+ typedef struct _virCgroupBackend virCgroupBackend;
+ typedef virCgroupBackend *virCgroupBackendPtr;
+diff --git a/src/util/vircgroupv1.c b/src/util/vircgroupv1.c
+index 47b0c13f38..5b0199a89f 100644
+--- a/src/util/vircgroupv1.c
++++ b/src/util/vircgroupv1.c
+@@ -1234,6 +1234,54 @@ virCgroupV1GetBlkioDeviceReadIops(virCgroupPtr group,
+ }
+ 
+ 
++static int
++virCgroupV1SetBlkioDeviceWriteIops(virCgroupPtr group,
++                                   const char *path,
++                                   unsigned int wiops)
++{
++    VIR_AUTOFREE(char *) str = NULL;
++    VIR_AUTOFREE(char *) blkstr = NULL;
++
++    if (!(blkstr = virCgroupGetBlockDevString(path)))
++        return -1;
++
++    if (virAsprintf(&str, "%s%u", blkstr, wiops) < 0)
++        return -1;
++
++    return virCgroupSetValueStr(group,
++                                VIR_CGROUP_CONTROLLER_BLKIO,
++                                "blkio.throttle.write_iops_device",
++                                str);
++}
++
++
++static int
++virCgroupV1GetBlkioDeviceWriteIops(virCgroupPtr group,
++                                   const char *path,
++                                   unsigned int *wiops)
++{
++    VIR_AUTOFREE(char *) str = NULL;
++
++    if (virCgroupGetValueForBlkDev(group,
++                                   VIR_CGROUP_CONTROLLER_BLKIO,
++                                   "blkio.throttle.write_iops_device",
++                                   path,
++                                   &str) < 0)
++        return -1;
++
++    if (!str) {
++        *wiops = 0;
++    } else if (virStrToLong_ui(str, NULL, 10, wiops) < 0) {
++        virReportError(VIR_ERR_INTERNAL_ERROR,
++                       _("Unable to parse '%s' as an integer"),
++                       str);
++        return -1;
++    }
++
++    return 0;
++}
++
++
+ virCgroupBackend virCgroupV1Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V1,
+ 
+@@ -1264,6 +1312,8 @@ virCgroupBackend virCgroupV1Backend = {
+     .getBlkioDeviceWeight = virCgroupV1GetBlkioDeviceWeight,
+     .setBlkioDeviceReadIops = virCgroupV1SetBlkioDeviceReadIops,
+     .getBlkioDeviceReadIops = virCgroupV1GetBlkioDeviceReadIops,
++    .setBlkioDeviceWriteIops = virCgroupV1SetBlkioDeviceWriteIops,
++    .getBlkioDeviceWriteIops = virCgroupV1GetBlkioDeviceWriteIops,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-extract-virCgroupV1-Set-Get-BlkioWeight.patch b/SOURCES/libvirt-vircgroup-extract-virCgroupV1-Set-Get-BlkioWeight.patch
new file mode 100644
index 0000000..e58c368
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-extract-virCgroupV1-Set-Get-BlkioWeight.patch
@@ -0,0 +1,150 @@
+From 7fae41a63cd97501e3a4bf8fade48949d754f738 Mon Sep 17 00:00:00 2001
+Message-Id: <7fae41a63cd97501e3a4bf8fade48949d754f738@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:06:41 +0200
+Subject: [PATCH] vircgroup: extract virCgroupV1(Set|Get)BlkioWeight
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit c57b0be0cc200abb21cbe0473d96f447fd37b27d)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <23b514919f71ed2a44c04d7f62a031c4edc14365.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c        | 14 ++------------
+ src/util/vircgroupbackend.h | 20 ++++++++++++++++++++
+ src/util/vircgroupv1.c      | 29 +++++++++++++++++++++++++++++
+ 3 files changed, 51 insertions(+), 12 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index e57aecb08a..d2ffa8aefe 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -1510,10 +1510,7 @@ virCgroupGetBlkioIoDeviceServiced(virCgroupPtr group,
+ int
+ virCgroupSetBlkioWeight(virCgroupPtr group, unsigned int weight)
+ {
+-    return virCgroupSetValueU64(group,
+-                                VIR_CGROUP_CONTROLLER_BLKIO,
+-                                "blkio.weight",
+-                                weight);
++    VIR_CGROUP_BACKEND_CALL(group, setBlkioWeight, -1, weight);
+ }
+ 
+ 
+@@ -1528,14 +1525,7 @@ virCgroupSetBlkioWeight(virCgroupPtr group, unsigned int weight)
+ int
+ virCgroupGetBlkioWeight(virCgroupPtr group, unsigned int *weight)
+ {
+-    unsigned long long tmp;
+-    int ret;
+-    ret = virCgroupGetValueU64(group,
+-                               VIR_CGROUP_CONTROLLER_BLKIO,
+-                               "blkio.weight", &tmp);
+-    if (ret == 0)
+-        *weight = tmp;
+-    return ret;
++    VIR_CGROUP_BACKEND_CALL(group, getBlkioWeight, -1, weight);
+ }
+ 
+ /**
+diff --git a/src/util/vircgroupbackend.h b/src/util/vircgroupbackend.h
+index 74af796c2f..ccce65f1e2 100644
+--- a/src/util/vircgroupbackend.h
++++ b/src/util/vircgroupbackend.h
+@@ -137,6 +137,14 @@ typedef int
+                        gid_t gid,
+                        int controllers);
+ 
++typedef int
++(*virCgroupSetBlkioWeightCB)(virCgroupPtr group,
++                             unsigned int weight);
++
++typedef int
++(*virCgroupGetBlkioWeightCB)(virCgroupPtr group,
++                             unsigned int *weight);
++
+ struct _virCgroupBackend {
+     virCgroupBackendType type;
+ 
+@@ -159,6 +167,10 @@ struct _virCgroupBackend {
+     virCgroupHasEmptyTasksCB hasEmptyTasks;
+     virCgroupBindMountCB bindMount;
+     virCgroupSetOwnerCB setOwner;
++
++    /* Optional cgroup controller specific callbacks. */
++    virCgroupSetBlkioWeightCB setBlkioWeight;
++    virCgroupGetBlkioWeightCB getBlkioWeight;
+ };
+ typedef struct _virCgroupBackend virCgroupBackend;
+ typedef virCgroupBackend *virCgroupBackendPtr;
+@@ -169,4 +181,12 @@ virCgroupBackendRegister(virCgroupBackendPtr backend);
+ virCgroupBackendPtr *
+ virCgroupBackendGetAll(void);
+ 
++# define VIR_CGROUP_BACKEND_CALL(group, func, ret, ...) \
++    if (!group->backend->func) { \
++        virReportError(VIR_ERR_OPERATION_UNSUPPORTED, \
++                       _("operation '%s' not supported"), #func); \
++        return ret; \
++    } \
++    return group->backend->func(group, ##__VA_ARGS__);
++
+ #endif /* __VIR_CGROUP_BACKEND_H__ */
+diff --git a/src/util/vircgroupv1.c b/src/util/vircgroupv1.c
+index c1e2583912..d67b3164ce 100644
+--- a/src/util/vircgroupv1.c
++++ b/src/util/vircgroupv1.c
+@@ -929,6 +929,32 @@ virCgroupV1SetOwner(virCgroupPtr cgroup,
+ }
+ 
+ 
++static int
++virCgroupV1SetBlkioWeight(virCgroupPtr group,
++                          unsigned int weight)
++{
++    return virCgroupSetValueU64(group,
++                                VIR_CGROUP_CONTROLLER_BLKIO,
++                                "blkio.weight",
++                                weight);
++}
++
++
++static int
++virCgroupV1GetBlkioWeight(virCgroupPtr group,
++                          unsigned int *weight)
++{
++    unsigned long long tmp;
++    int ret;
++    ret = virCgroupGetValueU64(group,
++                               VIR_CGROUP_CONTROLLER_BLKIO,
++                               "blkio.weight", &tmp);
++    if (ret == 0)
++        *weight = tmp;
++    return ret;
++}
++
++
+ virCgroupBackend virCgroupV1Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V1,
+ 
+@@ -950,6 +976,9 @@ virCgroupBackend virCgroupV1Backend = {
+     .hasEmptyTasks = virCgroupV1HasEmptyTasks,
+     .bindMount = virCgroupV1BindMount,
+     .setOwner = virCgroupV1SetOwner,
++
++    .setBlkioWeight = virCgroupV1SetBlkioWeight,
++    .getBlkioWeight = virCgroupV1GetBlkioWeight,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-extract-virCgroupV1-Set-Get-CpuCfsPeriod.patch b/SOURCES/libvirt-vircgroup-extract-virCgroupV1-Set-Get-CpuCfsPeriod.patch
new file mode 100644
index 0000000..eeb8623
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-extract-virCgroupV1-Set-Get-CpuCfsPeriod.patch
@@ -0,0 +1,142 @@
+From 39640f2e78035b667588513395187a96ae71d6c4 Mon Sep 17 00:00:00 2001
+Message-Id: <39640f2e78035b667588513395187a96ae71d6c4@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:06:57 +0200
+Subject: [PATCH] vircgroup: extract virCgroupV1(Set|Get)CpuCfsPeriod
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit c840448ebbeb3d4c34eafecf9c9c31c86f2f020f)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <93321a564a636498ef3e4144af737bcfc6e0f07a.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c        | 18 ++----------------
+ src/util/vircgroupbackend.h | 10 ++++++++++
+ src/util/vircgroupv1.c      | 32 ++++++++++++++++++++++++++++++++
+ 3 files changed, 44 insertions(+), 16 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index 953e353ec3..f4d995b22a 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -2227,19 +2227,7 @@ virCgroupGetCpuShares(virCgroupPtr group, unsigned long long *shares)
+ int
+ virCgroupSetCpuCfsPeriod(virCgroupPtr group, unsigned long long cfs_period)
+ {
+-    /* The cfs_period should be greater or equal than 1ms, and less or equal
+-     * than 1s.
+-     */
+-    if (cfs_period < 1000 || cfs_period > 1000000) {
+-        virReportError(VIR_ERR_INVALID_ARG,
+-                       _("cfs_period '%llu' must be in range (1000, 1000000)"),
+-                       cfs_period);
+-        return -1;
+-    }
+-
+-    return virCgroupSetValueU64(group,
+-                                VIR_CGROUP_CONTROLLER_CPU,
+-                                "cpu.cfs_period_us", cfs_period);
++    VIR_CGROUP_BACKEND_CALL(group, setCpuCfsPeriod, -1, cfs_period);
+ }
+ 
+ 
+@@ -2254,9 +2242,7 @@ virCgroupSetCpuCfsPeriod(virCgroupPtr group, unsigned long long cfs_period)
+ int
+ virCgroupGetCpuCfsPeriod(virCgroupPtr group, unsigned long long *cfs_period)
+ {
+-    return virCgroupGetValueU64(group,
+-                                VIR_CGROUP_CONTROLLER_CPU,
+-                                "cpu.cfs_period_us", cfs_period);
++    VIR_CGROUP_BACKEND_CALL(group, getCpuCfsPeriod, -1, cfs_period);
+ }
+ 
+ 
+diff --git a/src/util/vircgroupbackend.h b/src/util/vircgroupbackend.h
+index 54fbead8a2..7dc1f77bfd 100644
+--- a/src/util/vircgroupbackend.h
++++ b/src/util/vircgroupbackend.h
+@@ -284,6 +284,14 @@ typedef int
+ (*virCgroupGetCpuSharesCB)(virCgroupPtr group,
+                            unsigned long long *shares);
+ 
++typedef int
++(*virCgroupSetCpuCfsPeriodCB)(virCgroupPtr group,
++                              unsigned long long cfs_period);
++
++typedef int
++(*virCgroupGetCpuCfsPeriodCB)(virCgroupPtr group,
++                              unsigned long long *cfs_period);
++
+ struct _virCgroupBackend {
+     virCgroupBackendType type;
+ 
+@@ -341,6 +349,8 @@ struct _virCgroupBackend {
+ 
+     virCgroupSetCpuSharesCB setCpuShares;
+     virCgroupGetCpuSharesCB getCpuShares;
++    virCgroupSetCpuCfsPeriodCB setCpuCfsPeriod;
++    virCgroupGetCpuCfsPeriodCB getCpuCfsPeriod;
+ };
+ typedef struct _virCgroupBackend virCgroupBackend;
+ typedef virCgroupBackend *virCgroupBackendPtr;
+diff --git a/src/util/vircgroupv1.c b/src/util/vircgroupv1.c
+index 537845bafe..dc4cf1e9db 100644
+--- a/src/util/vircgroupv1.c
++++ b/src/util/vircgroupv1.c
+@@ -1786,6 +1786,36 @@ virCgroupV1GetCpuShares(virCgroupPtr group,
+ }
+ 
+ 
++static int
++virCgroupV1SetCpuCfsPeriod(virCgroupPtr group,
++                           unsigned long long cfs_period)
++{
++    /* The cfs_period should be greater or equal than 1ms, and less or equal
++     * than 1s.
++     */
++    if (cfs_period < 1000 || cfs_period > 1000000) {
++        virReportError(VIR_ERR_INVALID_ARG,
++                       _("cfs_period '%llu' must be in range (1000, 1000000)"),
++                       cfs_period);
++        return -1;
++    }
++
++    return virCgroupSetValueU64(group,
++                                VIR_CGROUP_CONTROLLER_CPU,
++                                "cpu.cfs_period_us", cfs_period);
++}
++
++
++static int
++virCgroupV1GetCpuCfsPeriod(virCgroupPtr group,
++                           unsigned long long *cfs_period)
++{
++    return virCgroupGetValueU64(group,
++                                VIR_CGROUP_CONTROLLER_CPU,
++                                "cpu.cfs_period_us", cfs_period);
++}
++
++
+ virCgroupBackend virCgroupV1Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V1,
+ 
+@@ -1841,6 +1871,8 @@ virCgroupBackend virCgroupV1Backend = {
+ 
+     .setCpuShares = virCgroupV1SetCpuShares,
+     .getCpuShares = virCgroupV1GetCpuShares,
++    .setCpuCfsPeriod = virCgroupV1SetCpuCfsPeriod,
++    .getCpuCfsPeriod = virCgroupV1GetCpuCfsPeriod,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-extract-virCgroupV1-Set-Get-CpuCfsQuota.patch b/SOURCES/libvirt-vircgroup-extract-virCgroupV1-Set-Get-CpuCfsQuota.patch
new file mode 100644
index 0000000..6782693
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-extract-virCgroupV1-Set-Get-CpuCfsQuota.patch
@@ -0,0 +1,168 @@
+From 1ae8ce96561e368af7e68d3837d9e794b023c530 Mon Sep 17 00:00:00 2001
+Message-Id: <1ae8ce96561e368af7e68d3837d9e794b023c530@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:06:58 +0200
+Subject: [PATCH] vircgroup: extract virCgroupV1(Set|Get)CpuCfsQuota
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 5436fd75d808ad7b595a06bfd727e8de3283ef1a)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <cb76fa8f21f7a46d9e3b9fa19bcfb5c22652a53a.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c        | 20 +++-----------------
+ src/util/vircgroupbackend.h | 10 ++++++++++
+ src/util/vircgrouppriv.h    |  5 +++++
+ src/util/vircgroupv1.c      | 32 ++++++++++++++++++++++++++++++++
+ 4 files changed, 50 insertions(+), 17 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index f4d995b22a..a3e7954d03 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -559,7 +559,7 @@ virCgroupSetValueI64(virCgroupPtr group,
+ }
+ 
+ 
+-static int
++int
+ virCgroupGetValueI64(virCgroupPtr group,
+                      int controller,
+                      const char *key,
+@@ -2258,19 +2258,7 @@ virCgroupGetCpuCfsPeriod(virCgroupPtr group, unsigned long long *cfs_period)
+ int
+ virCgroupSetCpuCfsQuota(virCgroupPtr group, long long cfs_quota)
+ {
+-    /* The cfs_quota should be greater or equal than 1ms */
+-    if (cfs_quota >= 0 &&
+-        (cfs_quota < 1000 ||
+-         cfs_quota > ULLONG_MAX / 1000)) {
+-        virReportError(VIR_ERR_INVALID_ARG,
+-                       _("cfs_quota '%lld' must be in range (1000, %llu)"),
+-                       cfs_quota, ULLONG_MAX / 1000);
+-        return -1;
+-    }
+-
+-    return virCgroupSetValueI64(group,
+-                                VIR_CGROUP_CONTROLLER_CPU,
+-                                "cpu.cfs_quota_us", cfs_quota);
++    VIR_CGROUP_BACKEND_CALL(group, setCpuCfsQuota, -1, cfs_quota);
+ }
+ 
+ 
+@@ -2594,9 +2582,7 @@ virCgroupKillPainfully(virCgroupPtr group)
+ int
+ virCgroupGetCpuCfsQuota(virCgroupPtr group, long long *cfs_quota)
+ {
+-    return virCgroupGetValueI64(group,
+-                                VIR_CGROUP_CONTROLLER_CPU,
+-                                "cpu.cfs_quota_us", cfs_quota);
++    VIR_CGROUP_BACKEND_CALL(group, getCpuCfsQuota, -1, cfs_quota);
+ }
+ 
+ 
+diff --git a/src/util/vircgroupbackend.h b/src/util/vircgroupbackend.h
+index 7dc1f77bfd..f7c230db76 100644
+--- a/src/util/vircgroupbackend.h
++++ b/src/util/vircgroupbackend.h
+@@ -292,6 +292,14 @@ typedef int
+ (*virCgroupGetCpuCfsPeriodCB)(virCgroupPtr group,
+                               unsigned long long *cfs_period);
+ 
++typedef int
++(*virCgroupSetCpuCfsQuotaCB)(virCgroupPtr group,
++                             long long cfs_quota);
++
++typedef int
++(*virCgroupGetCpuCfsQuotaCB)(virCgroupPtr group,
++                             long long *cfs_quota);
++
+ struct _virCgroupBackend {
+     virCgroupBackendType type;
+ 
+@@ -351,6 +359,8 @@ struct _virCgroupBackend {
+     virCgroupGetCpuSharesCB getCpuShares;
+     virCgroupSetCpuCfsPeriodCB setCpuCfsPeriod;
+     virCgroupGetCpuCfsPeriodCB getCpuCfsPeriod;
++    virCgroupSetCpuCfsQuotaCB setCpuCfsQuota;
++    virCgroupGetCpuCfsQuotaCB getCpuCfsQuota;
+ };
+ typedef struct _virCgroupBackend virCgroupBackend;
+ typedef virCgroupBackend *virCgroupBackendPtr;
+diff --git a/src/util/vircgrouppriv.h b/src/util/vircgrouppriv.h
+index 7b985280e1..38c911e8ed 100644
+--- a/src/util/vircgrouppriv.h
++++ b/src/util/vircgrouppriv.h
+@@ -78,6 +78,11 @@ int virCgroupSetValueI64(virCgroupPtr group,
+                          const char *key,
+                          long long int value);
+ 
++int virCgroupGetValueI64(virCgroupPtr group,
++                         int controller,
++                         const char *key,
++                         long long int *value);
++
+ int virCgroupPartitionEscape(char **path);
+ 
+ char *virCgroupGetBlockDevString(const char *path);
+diff --git a/src/util/vircgroupv1.c b/src/util/vircgroupv1.c
+index dc4cf1e9db..25f7376026 100644
+--- a/src/util/vircgroupv1.c
++++ b/src/util/vircgroupv1.c
+@@ -1816,6 +1816,36 @@ virCgroupV1GetCpuCfsPeriod(virCgroupPtr group,
+ }
+ 
+ 
++static int
++virCgroupV1SetCpuCfsQuota(virCgroupPtr group,
++                          long long cfs_quota)
++{
++    /* The cfs_quota should be greater or equal than 1ms */
++    if (cfs_quota >= 0 &&
++        (cfs_quota < 1000 ||
++         cfs_quota > ULLONG_MAX / 1000)) {
++        virReportError(VIR_ERR_INVALID_ARG,
++                       _("cfs_quota '%lld' must be in range (1000, %llu)"),
++                       cfs_quota, ULLONG_MAX / 1000);
++        return -1;
++    }
++
++    return virCgroupSetValueI64(group,
++                                VIR_CGROUP_CONTROLLER_CPU,
++                                "cpu.cfs_quota_us", cfs_quota);
++}
++
++
++static int
++virCgroupV1GetCpuCfsQuota(virCgroupPtr group,
++                          long long *cfs_quota)
++{
++    return virCgroupGetValueI64(group,
++                                VIR_CGROUP_CONTROLLER_CPU,
++                                "cpu.cfs_quota_us", cfs_quota);
++}
++
++
+ virCgroupBackend virCgroupV1Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V1,
+ 
+@@ -1873,6 +1903,8 @@ virCgroupBackend virCgroupV1Backend = {
+     .getCpuShares = virCgroupV1GetCpuShares,
+     .setCpuCfsPeriod = virCgroupV1SetCpuCfsPeriod,
+     .getCpuCfsPeriod = virCgroupV1GetCpuCfsPeriod,
++    .setCpuCfsQuota = virCgroupV1SetCpuCfsQuota,
++    .getCpuCfsQuota = virCgroupV1GetCpuCfsQuota,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-extract-virCgroupV1-Set-Get-CpuShares.patch b/SOURCES/libvirt-vircgroup-extract-virCgroupV1-Set-Get-CpuShares.patch
new file mode 100644
index 0000000..7ca2ec0
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-extract-virCgroupV1-Set-Get-CpuShares.patch
@@ -0,0 +1,123 @@
+From 86865e9638ec63808b1f68e4bd9b4896b5438ece Mon Sep 17 00:00:00 2001
+Message-Id: <86865e9638ec63808b1f68e4bd9b4896b5438ece@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:06:56 +0200
+Subject: [PATCH] vircgroup: extract virCgroupV1(Set|Get)CpuShares
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 857aac1f55bc1c44be4c03c4b721632caedd2a23)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <d43fdbd54cb3c387df54c11d2bd24483c717bd5a.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c        |  8 ++------
+ src/util/vircgroupbackend.h | 11 +++++++++++
+ src/util/vircgroupv1.c      | 23 +++++++++++++++++++++++
+ 3 files changed, 36 insertions(+), 6 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index 67c68f3dc6..953e353ec3 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -2205,18 +2205,14 @@ virCgroupGetDomainTotalCpuStats(virCgroupPtr group,
+ int
+ virCgroupSetCpuShares(virCgroupPtr group, unsigned long long shares)
+ {
+-    return virCgroupSetValueU64(group,
+-                                VIR_CGROUP_CONTROLLER_CPU,
+-                                "cpu.shares", shares);
++    VIR_CGROUP_BACKEND_CALL(group, setCpuShares, -1, shares);
+ }
+ 
+ 
+ int
+ virCgroupGetCpuShares(virCgroupPtr group, unsigned long long *shares)
+ {
+-    return virCgroupGetValueU64(group,
+-                                VIR_CGROUP_CONTROLLER_CPU,
+-                                "cpu.shares", shares);
++    VIR_CGROUP_BACKEND_CALL(group, getCpuShares, -1, shares);
+ }
+ 
+ 
+diff --git a/src/util/vircgroupbackend.h b/src/util/vircgroupbackend.h
+index 436c83f6fa..54fbead8a2 100644
+--- a/src/util/vircgroupbackend.h
++++ b/src/util/vircgroupbackend.h
+@@ -276,6 +276,14 @@ typedef int
+ typedef int
+ (*virCgroupDenyAllDevicesCB)(virCgroupPtr group);
+ 
++typedef int
++(*virCgroupSetCpuSharesCB)(virCgroupPtr group,
++                           unsigned long long shares);
++
++typedef int
++(*virCgroupGetCpuSharesCB)(virCgroupPtr group,
++                           unsigned long long *shares);
++
+ struct _virCgroupBackend {
+     virCgroupBackendType type;
+ 
+@@ -330,6 +338,9 @@ struct _virCgroupBackend {
+     virCgroupDenyDeviceCB denyDevice;
+     virCgroupAllowAllDevicesCB allowAllDevices;
+     virCgroupDenyAllDevicesCB denyAllDevices;
++
++    virCgroupSetCpuSharesCB setCpuShares;
++    virCgroupGetCpuSharesCB getCpuShares;
+ };
+ typedef struct _virCgroupBackend virCgroupBackend;
+ typedef virCgroupBackend *virCgroupBackendPtr;
+diff --git a/src/util/vircgroupv1.c b/src/util/vircgroupv1.c
+index 34393812d2..537845bafe 100644
+--- a/src/util/vircgroupv1.c
++++ b/src/util/vircgroupv1.c
+@@ -1766,6 +1766,26 @@ virCgroupV1DenyAllDevices(virCgroupPtr group)
+ }
+ 
+ 
++static int
++virCgroupV1SetCpuShares(virCgroupPtr group,
++                        unsigned long long shares)
++{
++    return virCgroupSetValueU64(group,
++                                VIR_CGROUP_CONTROLLER_CPU,
++                                "cpu.shares", shares);
++}
++
++
++static int
++virCgroupV1GetCpuShares(virCgroupPtr group,
++                        unsigned long long *shares)
++{
++    return virCgroupGetValueU64(group,
++                                VIR_CGROUP_CONTROLLER_CPU,
++                                "cpu.shares", shares);
++}
++
++
+ virCgroupBackend virCgroupV1Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V1,
+ 
+@@ -1818,6 +1838,9 @@ virCgroupBackend virCgroupV1Backend = {
+     .denyDevice = virCgroupV1DenyDevice,
+     .allowAllDevices = virCgroupV1AllowAllDevices,
+     .denyAllDevices = virCgroupV1DenyAllDevices,
++
++    .setCpuShares = virCgroupV1SetCpuShares,
++    .getCpuShares = virCgroupV1GetCpuShares,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-extract-virCgroupV1-Set-Get-CpusetCpus.patch b/SOURCES/libvirt-vircgroup-extract-virCgroupV1-Set-Get-CpusetCpus.patch
new file mode 100644
index 0000000..0f05e83
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-extract-virCgroupV1-Set-Get-CpusetCpus.patch
@@ -0,0 +1,126 @@
+From d45a116567b6ad1cc87060651a4d1c8d83384ba8 Mon Sep 17 00:00:00 2001
+Message-Id: <d45a116567b6ad1cc87060651a4d1c8d83384ba8@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:07:05 +0200
+Subject: [PATCH] vircgroup: extract virCgroupV1(Set|Get)CpusetCpus
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 2b09065e0fb4b40e05a46f0592d978d3cb72278f)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <e68c2c6509b0e9e76c923c980f2d73f0a756cfd1.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c        | 10 ++--------
+ src/util/vircgroupbackend.h | 10 ++++++++++
+ src/util/vircgroupv1.c      | 24 ++++++++++++++++++++++++
+ 3 files changed, 36 insertions(+), 8 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index 1a5ed472df..b159bda1bb 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -1772,10 +1772,7 @@ virCgroupGetCpusetMemoryMigrate(virCgroupPtr group, bool *migrate)
+ int
+ virCgroupSetCpusetCpus(virCgroupPtr group, const char *cpus)
+ {
+-    return virCgroupSetValueStr(group,
+-                                VIR_CGROUP_CONTROLLER_CPUSET,
+-                                "cpuset.cpus",
+-                                cpus);
++    VIR_CGROUP_BACKEND_CALL(group, setCpusetCpus, -1, cpus);
+ }
+ 
+ 
+@@ -1790,10 +1787,7 @@ virCgroupSetCpusetCpus(virCgroupPtr group, const char *cpus)
+ int
+ virCgroupGetCpusetCpus(virCgroupPtr group, char **cpus)
+ {
+-    return virCgroupGetValueStr(group,
+-                                VIR_CGROUP_CONTROLLER_CPUSET,
+-                                "cpuset.cpus",
+-                                cpus);
++    VIR_CGROUP_BACKEND_CALL(group, getCpusetCpus, -1, cpus);
+ }
+ 
+ 
+diff --git a/src/util/vircgroupbackend.h b/src/util/vircgroupbackend.h
+index d4e4c4a6cc..1c5744ef76 100644
+--- a/src/util/vircgroupbackend.h
++++ b/src/util/vircgroupbackend.h
+@@ -340,6 +340,14 @@ typedef int
+ (*virCgroupGetCpusetMemoryMigrateCB)(virCgroupPtr group,
+                                      bool *migrate);
+ 
++typedef int
++(*virCgroupSetCpusetCpusCB)(virCgroupPtr group,
++                            const char *cpus);
++
++typedef int
++(*virCgroupGetCpusetCpusCB)(virCgroupPtr group,
++                            char **cpus);
++
+ struct _virCgroupBackend {
+     virCgroupBackendType type;
+ 
+@@ -414,6 +422,8 @@ struct _virCgroupBackend {
+     virCgroupGetCpusetMemsCB getCpusetMems;
+     virCgroupSetCpusetMemoryMigrateCB setCpusetMemoryMigrate;
+     virCgroupGetCpusetMemoryMigrateCB getCpusetMemoryMigrate;
++    virCgroupSetCpusetCpusCB setCpusetCpus;
++    virCgroupGetCpusetCpusCB getCpusetCpus;
+ };
+ typedef struct _virCgroupBackend virCgroupBackend;
+ typedef virCgroupBackend *virCgroupBackendPtr;
+diff --git a/src/util/vircgroupv1.c b/src/util/vircgroupv1.c
+index 3a41899dd8..54e7d6ea9a 100644
+--- a/src/util/vircgroupv1.c
++++ b/src/util/vircgroupv1.c
+@@ -1996,6 +1996,28 @@ virCgroupV1GetCpusetMemoryMigrate(virCgroupPtr group,
+ }
+ 
+ 
++static int
++virCgroupV1SetCpusetCpus(virCgroupPtr group,
++                         const char *cpus)
++{
++    return virCgroupSetValueStr(group,
++                                VIR_CGROUP_CONTROLLER_CPUSET,
++                                "cpuset.cpus",
++                                cpus);
++}
++
++
++static int
++virCgroupV1GetCpusetCpus(virCgroupPtr group,
++                         char **cpus)
++{
++    return virCgroupGetValueStr(group,
++                                VIR_CGROUP_CONTROLLER_CPUSET,
++                                "cpuset.cpus",
++                                cpus);
++}
++
++
+ virCgroupBackend virCgroupV1Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V1,
+ 
+@@ -2068,6 +2090,8 @@ virCgroupBackend virCgroupV1Backend = {
+     .getCpusetMems = virCgroupV1GetCpusetMems,
+     .setCpusetMemoryMigrate = virCgroupV1SetCpusetMemoryMigrate,
+     .getCpusetMemoryMigrate = virCgroupV1GetCpusetMemoryMigrate,
++    .setCpusetCpus = virCgroupV1SetCpusetCpus,
++    .getCpusetCpus = virCgroupV1GetCpusetCpus,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-extract-virCgroupV1-Set-Get-CpusetMemoryMigrate.patch b/SOURCES/libvirt-vircgroup-extract-virCgroupV1-Set-Get-CpusetMemoryMigrate.patch
new file mode 100644
index 0000000..0b0a5c9
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-extract-virCgroupV1-Set-Get-CpusetMemoryMigrate.patch
@@ -0,0 +1,132 @@
+From e8af2c7b172894ae3cfacd6de98b01af63947b05 Mon Sep 17 00:00:00 2001
+Message-Id: <e8af2c7b172894ae3cfacd6de98b01af63947b05@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:07:04 +0200
+Subject: [PATCH] vircgroup: extract virCgroupV1(Set|Get)CpusetMemoryMigrate
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 7f3aedacac33fd4775d7def3734422108d6cd93e)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <0067ed0a20d90451ab63112dc273ddb8344569ca.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c        | 13 ++-----------
+ src/util/vircgroupbackend.h | 10 ++++++++++
+ src/util/vircgroupv1.c      | 27 +++++++++++++++++++++++++++
+ 3 files changed, 39 insertions(+), 11 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index 700e597157..1a5ed472df 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -1742,10 +1742,7 @@ virCgroupGetCpusetMems(virCgroupPtr group, char **mems)
+ int
+ virCgroupSetCpusetMemoryMigrate(virCgroupPtr group, bool migrate)
+ {
+-    return virCgroupSetValueStr(group,
+-                                VIR_CGROUP_CONTROLLER_CPUSET,
+-                                "cpuset.memory_migrate",
+-                                migrate ? "1" : "0");
++    VIR_CGROUP_BACKEND_CALL(group, setCpusetMemoryMigrate, -1, migrate);
+ }
+ 
+ 
+@@ -1760,13 +1757,7 @@ virCgroupSetCpusetMemoryMigrate(virCgroupPtr group, bool migrate)
+ int
+ virCgroupGetCpusetMemoryMigrate(virCgroupPtr group, bool *migrate)
+ {
+-    unsigned long long value = 0;
+-    int ret = virCgroupGetValueU64(group,
+-                                   VIR_CGROUP_CONTROLLER_CPUSET,
+-                                   "cpuset.memory_migrate",
+-                                   &value);
+-    *migrate = !!value;
+-    return ret;
++    VIR_CGROUP_BACKEND_CALL(group, getCpusetMemoryMigrate, -1, migrate);
+ }
+ 
+ 
+diff --git a/src/util/vircgroupbackend.h b/src/util/vircgroupbackend.h
+index 35221e90df..d4e4c4a6cc 100644
+--- a/src/util/vircgroupbackend.h
++++ b/src/util/vircgroupbackend.h
+@@ -332,6 +332,14 @@ typedef int
+ (*virCgroupGetCpusetMemsCB)(virCgroupPtr group,
+                             char **mems);
+ 
++typedef int
++(*virCgroupSetCpusetMemoryMigrateCB)(virCgroupPtr group,
++                                     bool migrate);
++
++typedef int
++(*virCgroupGetCpusetMemoryMigrateCB)(virCgroupPtr group,
++                                     bool *migrate);
++
+ struct _virCgroupBackend {
+     virCgroupBackendType type;
+ 
+@@ -404,6 +412,8 @@ struct _virCgroupBackend {
+ 
+     virCgroupSetCpusetMemsCB setCpusetMems;
+     virCgroupGetCpusetMemsCB getCpusetMems;
++    virCgroupSetCpusetMemoryMigrateCB setCpusetMemoryMigrate;
++    virCgroupGetCpusetMemoryMigrateCB getCpusetMemoryMigrate;
+ };
+ typedef struct _virCgroupBackend virCgroupBackend;
+ typedef virCgroupBackend *virCgroupBackendPtr;
+diff --git a/src/util/vircgroupv1.c b/src/util/vircgroupv1.c
+index be9a6b82b4..3a41899dd8 100644
+--- a/src/util/vircgroupv1.c
++++ b/src/util/vircgroupv1.c
+@@ -1971,6 +1971,31 @@ virCgroupV1GetCpusetMems(virCgroupPtr group,
+ }
+ 
+ 
++static int
++virCgroupV1SetCpusetMemoryMigrate(virCgroupPtr group,
++                                  bool migrate)
++{
++    return virCgroupSetValueStr(group,
++                                VIR_CGROUP_CONTROLLER_CPUSET,
++                                "cpuset.memory_migrate",
++                                migrate ? "1" : "0");
++}
++
++
++static int
++virCgroupV1GetCpusetMemoryMigrate(virCgroupPtr group,
++                                  bool *migrate)
++{
++    unsigned long long value = 0;
++    int ret = virCgroupGetValueU64(group,
++                                   VIR_CGROUP_CONTROLLER_CPUSET,
++                                   "cpuset.memory_migrate",
++                                   &value);
++    *migrate = !!value;
++    return ret;
++}
++
++
+ virCgroupBackend virCgroupV1Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V1,
+ 
+@@ -2041,6 +2066,8 @@ virCgroupBackend virCgroupV1Backend = {
+ 
+     .setCpusetMems = virCgroupV1SetCpusetMems,
+     .getCpusetMems = virCgroupV1GetCpusetMems,
++    .setCpusetMemoryMigrate = virCgroupV1SetCpusetMemoryMigrate,
++    .getCpusetMemoryMigrate = virCgroupV1GetCpusetMemoryMigrate,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-extract-virCgroupV1-Set-Get-CpusetMems.patch b/SOURCES/libvirt-vircgroup-extract-virCgroupV1-Set-Get-CpusetMems.patch
new file mode 100644
index 0000000..4577480
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-extract-virCgroupV1-Set-Get-CpusetMems.patch
@@ -0,0 +1,128 @@
+From 1f5aa6a591ba44492813f5a1a92d0fd2480ae3e7 Mon Sep 17 00:00:00 2001
+Message-Id: <1f5aa6a591ba44492813f5a1a92d0fd2480ae3e7@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:07:03 +0200
+Subject: [PATCH] vircgroup: extract virCgroupV1(Set|Get)CpusetMems
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 41510b1b74b9d15a64aaefa83826ddf00c999fe0)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <163d30216cc48d77abac54b014faa779c64aa629.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c        | 10 ++--------
+ src/util/vircgroupbackend.h | 11 +++++++++++
+ src/util/vircgroupv1.c      | 25 +++++++++++++++++++++++++
+ 3 files changed, 38 insertions(+), 8 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index 8b14c053e9..700e597157 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -1712,10 +1712,7 @@ virCgroupGetMemSwapUsage(virCgroupPtr group, unsigned long long *kb)
+ int
+ virCgroupSetCpusetMems(virCgroupPtr group, const char *mems)
+ {
+-    return virCgroupSetValueStr(group,
+-                                VIR_CGROUP_CONTROLLER_CPUSET,
+-                                "cpuset.mems",
+-                                mems);
++    VIR_CGROUP_BACKEND_CALL(group, setCpusetMems, -1, mems);
+ }
+ 
+ 
+@@ -1730,10 +1727,7 @@ virCgroupSetCpusetMems(virCgroupPtr group, const char *mems)
+ int
+ virCgroupGetCpusetMems(virCgroupPtr group, char **mems)
+ {
+-    return virCgroupGetValueStr(group,
+-                                VIR_CGROUP_CONTROLLER_CPUSET,
+-                                "cpuset.mems",
+-                                mems);
++    VIR_CGROUP_BACKEND_CALL(group, getCpusetMems, -1, mems);
+ }
+ 
+ 
+diff --git a/src/util/vircgroupbackend.h b/src/util/vircgroupbackend.h
+index 2c16706c96..35221e90df 100644
+--- a/src/util/vircgroupbackend.h
++++ b/src/util/vircgroupbackend.h
+@@ -324,6 +324,14 @@ typedef int
+ (*virCgroupGetFreezerStateCB)(virCgroupPtr group,
+                               char **state);
+ 
++typedef int
++(*virCgroupSetCpusetMemsCB)(virCgroupPtr group,
++                            const char *mems);
++
++typedef int
++(*virCgroupGetCpusetMemsCB)(virCgroupPtr group,
++                            char **mems);
++
+ struct _virCgroupBackend {
+     virCgroupBackendType type;
+ 
+@@ -393,6 +401,9 @@ struct _virCgroupBackend {
+ 
+     virCgroupSetFreezerStateCB setFreezerState;
+     virCgroupGetFreezerStateCB getFreezerState;
++
++    virCgroupSetCpusetMemsCB setCpusetMems;
++    virCgroupGetCpusetMemsCB getCpusetMems;
+ };
+ typedef struct _virCgroupBackend virCgroupBackend;
+ typedef virCgroupBackend *virCgroupBackendPtr;
+diff --git a/src/util/vircgroupv1.c b/src/util/vircgroupv1.c
+index 7580f8b756..be9a6b82b4 100644
+--- a/src/util/vircgroupv1.c
++++ b/src/util/vircgroupv1.c
+@@ -1949,6 +1949,28 @@ virCgroupV1GetFreezerState(virCgroupPtr group,
+ }
+ 
+ 
++static int
++virCgroupV1SetCpusetMems(virCgroupPtr group,
++                         const char *mems)
++{
++    return virCgroupSetValueStr(group,
++                                VIR_CGROUP_CONTROLLER_CPUSET,
++                                "cpuset.mems",
++                                mems);
++}
++
++
++static int
++virCgroupV1GetCpusetMems(virCgroupPtr group,
++                         char **mems)
++{
++    return virCgroupGetValueStr(group,
++                                VIR_CGROUP_CONTROLLER_CPUSET,
++                                "cpuset.mems",
++                                mems);
++}
++
++
+ virCgroupBackend virCgroupV1Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V1,
+ 
+@@ -2016,6 +2038,9 @@ virCgroupBackend virCgroupV1Backend = {
+ 
+     .setFreezerState = virCgroupV1SetFreezerState,
+     .getFreezerState = virCgroupV1GetFreezerState,
++
++    .setCpusetMems = virCgroupV1SetCpusetMems,
++    .getCpusetMems = virCgroupV1GetCpusetMems,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-extract-virCgroupV1-Set-Get-FreezerState.patch b/SOURCES/libvirt-vircgroup-extract-virCgroupV1-Set-Get-FreezerState.patch
new file mode 100644
index 0000000..c2bf1c6
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-extract-virCgroupV1-Set-Get-FreezerState.patch
@@ -0,0 +1,123 @@
+From c68fdfdc5432ec922ca9ead1e3a0880a6112fea6 Mon Sep 17 00:00:00 2001
+Message-Id: <c68fdfdc5432ec922ca9ead1e3a0880a6112fea6@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:07:02 +0200
+Subject: [PATCH] vircgroup: extract virCgroupV1(Set|Get)FreezerState
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 269a8e2718f96d5c015ad5d792fdf6759b7faee5)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <a3223b27d03cc952fcf5d7aedbc7fbfd95052b1a.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c        |  8 ++------
+ src/util/vircgroupbackend.h | 11 +++++++++++
+ src/util/vircgroupv1.c      | 23 +++++++++++++++++++++++
+ 3 files changed, 36 insertions(+), 6 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index 090fe140bb..8b14c053e9 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -2603,18 +2603,14 @@ virCgroupGetCpuacctStat(virCgroupPtr group, unsigned long long *user,
+ int
+ virCgroupSetFreezerState(virCgroupPtr group, const char *state)
+ {
+-    return virCgroupSetValueStr(group,
+-                                VIR_CGROUP_CONTROLLER_FREEZER,
+-                                "freezer.state", state);
++    VIR_CGROUP_BACKEND_CALL(group, setFreezerState, -1, state);
+ }
+ 
+ 
+ int
+ virCgroupGetFreezerState(virCgroupPtr group, char **state)
+ {
+-    return virCgroupGetValueStr(group,
+-                                VIR_CGROUP_CONTROLLER_FREEZER,
+-                                "freezer.state", state);
++    VIR_CGROUP_BACKEND_CALL(group, getFreezerState, -1, state);
+ }
+ 
+ 
+diff --git a/src/util/vircgroupbackend.h b/src/util/vircgroupbackend.h
+index 3e3a73777d..2c16706c96 100644
+--- a/src/util/vircgroupbackend.h
++++ b/src/util/vircgroupbackend.h
+@@ -316,6 +316,14 @@ typedef int
+                              unsigned long long *user,
+                              unsigned long long *sys);
+ 
++typedef int
++(*virCgroupSetFreezerStateCB)(virCgroupPtr group,
++                              const char *state);
++
++typedef int
++(*virCgroupGetFreezerStateCB)(virCgroupPtr group,
++                              char **state);
++
+ struct _virCgroupBackend {
+     virCgroupBackendType type;
+ 
+@@ -382,6 +390,9 @@ struct _virCgroupBackend {
+     virCgroupGetCpuacctUsageCB getCpuacctUsage;
+     virCgroupGetCpuacctPercpuUsageCB getCpuacctPercpuUsage;
+     virCgroupGetCpuacctStatCB getCpuacctStat;
++
++    virCgroupSetFreezerStateCB setFreezerState;
++    virCgroupGetFreezerStateCB getFreezerState;
+ };
+ typedef struct _virCgroupBackend virCgroupBackend;
+ typedef virCgroupBackend *virCgroupBackendPtr;
+diff --git a/src/util/vircgroupv1.c b/src/util/vircgroupv1.c
+index 23a91adf60..7580f8b756 100644
+--- a/src/util/vircgroupv1.c
++++ b/src/util/vircgroupv1.c
+@@ -1929,6 +1929,26 @@ virCgroupV1GetCpuacctStat(virCgroupPtr group,
+ }
+ 
+ 
++static int
++virCgroupV1SetFreezerState(virCgroupPtr group,
++                           const char *state)
++{
++    return virCgroupSetValueStr(group,
++                                VIR_CGROUP_CONTROLLER_FREEZER,
++                                "freezer.state", state);
++}
++
++
++static int
++virCgroupV1GetFreezerState(virCgroupPtr group,
++                           char **state)
++{
++    return virCgroupGetValueStr(group,
++                                VIR_CGROUP_CONTROLLER_FREEZER,
++                                "freezer.state", state);
++}
++
++
+ virCgroupBackend virCgroupV1Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V1,
+ 
+@@ -1993,6 +2013,9 @@ virCgroupBackend virCgroupV1Backend = {
+     .getCpuacctUsage = virCgroupV1GetCpuacctUsage,
+     .getCpuacctPercpuUsage = virCgroupV1GetCpuacctPercpuUsage,
+     .getCpuacctStat = virCgroupV1GetCpuacctStat,
++
++    .setFreezerState = virCgroupV1SetFreezerState,
++    .getFreezerState = virCgroupV1GetFreezerState,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-extract-virCgroupV1-Set-Get-Memory-Limit.patch b/SOURCES/libvirt-vircgroup-extract-virCgroupV1-Set-Get-Memory-Limit.patch
new file mode 100644
index 0000000..c316c2d
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-extract-virCgroupV1-Set-Get-Memory-Limit.patch
@@ -0,0 +1,478 @@
+From 5101d214a63b31847f80048d4ee34b5e62176ddd Mon Sep 17 00:00:00 2001
+Message-Id: <5101d214a63b31847f80048d4ee34b5e62176ddd@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:06:52 +0200
+Subject: [PATCH] vircgroup: extract virCgroupV1(Set|Get)Memory*Limit
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+They all need virCgroupV1GetMemoryUnlimitedKB() so it's easier to
+move them in one commit.
+
+Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 900c58b7f963d5054921e31bbd0b6005155b284a)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <c85e4973bb1718a5c9a36f971f9544b46b213183.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c        | 128 ++-------------------------
+ src/util/vircgroupbackend.h |  30 +++++++
+ src/util/vircgrouppriv.h    |   6 ++
+ src/util/vircgroupv1.c      | 168 ++++++++++++++++++++++++++++++++++++
+ 4 files changed, 211 insertions(+), 121 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index ed7252243c..6708eef0da 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -634,7 +634,7 @@ virCgroupMakeGroup(virCgroupPtr parent,
+  *
+  * Returns 0 on success, -1 on error
+  */
+-static int
++int
+ virCgroupNew(pid_t pid,
+              const char *path,
+              virCgroupPtr parent,
+@@ -1537,51 +1537,6 @@ virCgroupGetBlkioDeviceWeight(virCgroupPtr group,
+ }
+ 
+ 
+-/*
+- * Retrieve the "memory.limit_in_bytes" value from the memory controller
+- * root dir. This value cannot be modified by userspace and therefore
+- * is the maximum limit value supported by cgroups on the local system.
+- * Returns this value scaled to KB or falls back to the original
+- * VIR_DOMAIN_MEMORY_PARAM_UNLIMITED. Either way, remember the return
+- * value to avoid unnecessary cgroup filesystem access.
+- */
+-static unsigned long long int virCgroupMemoryUnlimitedKB;
+-static virOnceControl virCgroupMemoryOnce = VIR_ONCE_CONTROL_INITIALIZER;
+-
+-static void
+-virCgroupMemoryOnceInit(void)
+-{
+-    virCgroupPtr group;
+-    unsigned long long int mem_unlimited = 0ULL;
+-
+-    if (virCgroupNew(-1, "/", NULL, -1, &group) < 0)
+-        goto cleanup;
+-
+-    if (!virCgroupHasController(group, VIR_CGROUP_CONTROLLER_MEMORY))
+-        goto cleanup;
+-
+-    ignore_value(virCgroupGetValueU64(group,
+-                                      VIR_CGROUP_CONTROLLER_MEMORY,
+-                                      "memory.limit_in_bytes",
+-                                      &mem_unlimited));
+- cleanup:
+-    virCgroupFree(&group);
+-    virCgroupMemoryUnlimitedKB = mem_unlimited >> 10;
+-}
+-
+-static unsigned long long int
+-virCgroupGetMemoryUnlimitedKB(void)
+-{
+-    if (virOnce(&virCgroupMemoryOnce, virCgroupMemoryOnceInit) < 0)
+-        VIR_DEBUG("Init failed, will fall back to defaults.");
+-
+-    if (virCgroupMemoryUnlimitedKB)
+-        return virCgroupMemoryUnlimitedKB;
+-    else
+-        return VIR_DOMAIN_MEMORY_PARAM_UNLIMITED;
+-}
+-
+-
+ /**
+  * virCgroupSetMemory:
+  *
+@@ -1652,7 +1607,7 @@ virCgroupGetMemoryUsage(virCgroupPtr group, unsigned long *kb)
+ int
+ virCgroupSetMemoryHardLimit(virCgroupPtr group, unsigned long long kb)
+ {
+-    return virCgroupSetMemory(group, kb);
++    VIR_CGROUP_BACKEND_CALL(group, setMemoryHardLimit, -1, kb);
+ }
+ 
+ 
+@@ -1667,18 +1622,7 @@ virCgroupSetMemoryHardLimit(virCgroupPtr group, unsigned long long kb)
+ int
+ virCgroupGetMemoryHardLimit(virCgroupPtr group, unsigned long long *kb)
+ {
+-    long long unsigned int limit_in_bytes;
+-
+-    if (virCgroupGetValueU64(group,
+-                             VIR_CGROUP_CONTROLLER_MEMORY,
+-                             "memory.limit_in_bytes", &limit_in_bytes) < 0)
+-        return -1;
+-
+-    *kb = limit_in_bytes >> 10;
+-    if (*kb >= virCgroupGetMemoryUnlimitedKB())
+-        *kb = VIR_DOMAIN_MEMORY_PARAM_UNLIMITED;
+-
+-    return 0;
++    VIR_CGROUP_BACKEND_CALL(group, getMemoryHardLimit, -1, kb);
+ }
+ 
+ 
+@@ -1693,25 +1637,7 @@ virCgroupGetMemoryHardLimit(virCgroupPtr group, unsigned long long *kb)
+ int
+ virCgroupSetMemorySoftLimit(virCgroupPtr group, unsigned long long kb)
+ {
+-    unsigned long long maxkb = VIR_DOMAIN_MEMORY_PARAM_UNLIMITED;
+-
+-    if (kb > maxkb) {
+-        virReportError(VIR_ERR_INVALID_ARG,
+-                       _("Memory '%llu' must be less than %llu"),
+-                       kb, maxkb);
+-        return -1;
+-    }
+-
+-    if (kb == maxkb)
+-        return virCgroupSetValueI64(group,
+-                                    VIR_CGROUP_CONTROLLER_MEMORY,
+-                                    "memory.soft_limit_in_bytes",
+-                                    -1);
+-    else
+-        return virCgroupSetValueU64(group,
+-                                    VIR_CGROUP_CONTROLLER_MEMORY,
+-                                    "memory.soft_limit_in_bytes",
+-                                    kb << 10);
++    VIR_CGROUP_BACKEND_CALL(group, setMemorySoftLimit, -1, kb);
+ }
+ 
+ 
+@@ -1726,18 +1652,7 @@ virCgroupSetMemorySoftLimit(virCgroupPtr group, unsigned long long kb)
+ int
+ virCgroupGetMemorySoftLimit(virCgroupPtr group, unsigned long long *kb)
+ {
+-    long long unsigned int limit_in_bytes;
+-
+-    if (virCgroupGetValueU64(group,
+-                             VIR_CGROUP_CONTROLLER_MEMORY,
+-                             "memory.soft_limit_in_bytes", &limit_in_bytes) < 0)
+-        return -1;
+-
+-    *kb = limit_in_bytes >> 10;
+-    if (*kb >= virCgroupGetMemoryUnlimitedKB())
+-        *kb = VIR_DOMAIN_MEMORY_PARAM_UNLIMITED;
+-
+-    return 0;
++    VIR_CGROUP_BACKEND_CALL(group, getMemorySoftLimit, -1, kb);
+ }
+ 
+ 
+@@ -1752,25 +1667,7 @@ virCgroupGetMemorySoftLimit(virCgroupPtr group, unsigned long long *kb)
+ int
+ virCgroupSetMemSwapHardLimit(virCgroupPtr group, unsigned long long kb)
+ {
+-    unsigned long long maxkb = VIR_DOMAIN_MEMORY_PARAM_UNLIMITED;
+-
+-    if (kb > maxkb) {
+-        virReportError(VIR_ERR_INVALID_ARG,
+-                       _("Memory '%llu' must be less than %llu"),
+-                       kb, maxkb);
+-        return -1;
+-    }
+-
+-    if (kb == maxkb)
+-        return virCgroupSetValueI64(group,
+-                                    VIR_CGROUP_CONTROLLER_MEMORY,
+-                                    "memory.memsw.limit_in_bytes",
+-                                    -1);
+-    else
+-        return virCgroupSetValueU64(group,
+-                                    VIR_CGROUP_CONTROLLER_MEMORY,
+-                                    "memory.memsw.limit_in_bytes",
+-                                    kb << 10);
++    VIR_CGROUP_BACKEND_CALL(group, setMemSwapHardLimit, -1, kb);
+ }
+ 
+ 
+@@ -1785,18 +1682,7 @@ virCgroupSetMemSwapHardLimit(virCgroupPtr group, unsigned long long kb)
+ int
+ virCgroupGetMemSwapHardLimit(virCgroupPtr group, unsigned long long *kb)
+ {
+-    long long unsigned int limit_in_bytes;
+-
+-    if (virCgroupGetValueU64(group,
+-                             VIR_CGROUP_CONTROLLER_MEMORY,
+-                             "memory.memsw.limit_in_bytes", &limit_in_bytes) < 0)
+-        return -1;
+-
+-    *kb = limit_in_bytes >> 10;
+-    if (*kb >= virCgroupGetMemoryUnlimitedKB())
+-        *kb = VIR_DOMAIN_MEMORY_PARAM_UNLIMITED;
+-
+-    return 0;
++    VIR_CGROUP_BACKEND_CALL(group, getMemSwapHardLimit, -1, kb);
+ }
+ 
+ 
+diff --git a/src/util/vircgroupbackend.h b/src/util/vircgroupbackend.h
+index 8bdfc5c835..cdbca4b907 100644
+--- a/src/util/vircgroupbackend.h
++++ b/src/util/vircgroupbackend.h
+@@ -227,6 +227,30 @@ typedef int
+ (*virCgroupGetMemoryUsageCB)(virCgroupPtr group,
+                              unsigned long *kb);
+ 
++typedef int
++(*virCgroupSetMemoryHardLimitCB)(virCgroupPtr group,
++                                 unsigned long long kb);
++
++typedef int
++(*virCgroupGetMemoryHardLimitCB)(virCgroupPtr group,
++                                 unsigned long long *kb);
++
++typedef int
++(*virCgroupSetMemorySoftLimitCB)(virCgroupPtr group,
++                                 unsigned long long kb);
++
++typedef int
++(*virCgroupGetMemorySoftLimitCB)(virCgroupPtr group,
++                                 unsigned long long *kb);
++
++typedef int
++(*virCgroupSetMemSwapHardLimitCB)(virCgroupPtr group,
++                                  unsigned long long kb);
++
++typedef int
++(*virCgroupGetMemSwapHardLimitCB)(virCgroupPtr group,
++                                  unsigned long long *kb);
++
+ struct _virCgroupBackend {
+     virCgroupBackendType type;
+ 
+@@ -269,6 +293,12 @@ struct _virCgroupBackend {
+     virCgroupSetMemoryCB setMemory;
+     virCgroupGetMemoryStatCB getMemoryStat;
+     virCgroupGetMemoryUsageCB getMemoryUsage;
++    virCgroupSetMemoryHardLimitCB setMemoryHardLimit;
++    virCgroupGetMemoryHardLimitCB getMemoryHardLimit;
++    virCgroupSetMemorySoftLimitCB setMemorySoftLimit;
++    virCgroupGetMemorySoftLimitCB getMemorySoftLimit;
++    virCgroupSetMemSwapHardLimitCB setMemSwapHardLimit;
++    virCgroupGetMemSwapHardLimitCB getMemSwapHardLimit;
+ };
+ typedef struct _virCgroupBackend virCgroupBackend;
+ typedef virCgroupBackend *virCgroupBackendPtr;
+diff --git a/src/util/vircgrouppriv.h b/src/util/vircgrouppriv.h
+index 3a968c1ce2..7b985280e1 100644
+--- a/src/util/vircgrouppriv.h
++++ b/src/util/vircgrouppriv.h
+@@ -88,6 +88,12 @@ int virCgroupGetValueForBlkDev(virCgroupPtr group,
+                                const char *path,
+                                char **value);
+ 
++int virCgroupNew(pid_t pid,
++                 const char *path,
++                 virCgroupPtr parent,
++                 int controllers,
++                 virCgroupPtr *group);
++
+ int virCgroupNewPartition(const char *path,
+                           bool create,
+                           int controllers,
+diff --git a/src/util/vircgroupv1.c b/src/util/vircgroupv1.c
+index 4f1d79a758..779288fb97 100644
+--- a/src/util/vircgroupv1.c
++++ b/src/util/vircgroupv1.c
+@@ -1378,6 +1378,51 @@ virCgroupV1GetBlkioDeviceWriteBps(virCgroupPtr group,
+ }
+ 
+ 
++/*
++ * Retrieve the "memory.limit_in_bytes" value from the memory controller
++ * root dir. This value cannot be modified by userspace and therefore
++ * is the maximum limit value supported by cgroups on the local system.
++ * Returns this value scaled to KB or falls back to the original
++ * VIR_DOMAIN_MEMORY_PARAM_UNLIMITED. Either way, remember the return
++ * value to avoid unnecessary cgroup filesystem access.
++ */
++static unsigned long long int virCgroupV1MemoryUnlimitedKB;
++static virOnceControl virCgroupV1MemoryOnce = VIR_ONCE_CONTROL_INITIALIZER;
++
++static void
++virCgroupV1MemoryOnceInit(void)
++{
++    virCgroupPtr group;
++    unsigned long long int mem_unlimited = 0ULL;
++
++    if (virCgroupNew(-1, "/", NULL, -1, &group) < 0)
++        goto cleanup;
++
++    if (!virCgroupV1HasController(group, VIR_CGROUP_CONTROLLER_MEMORY))
++        goto cleanup;
++
++    ignore_value(virCgroupGetValueU64(group,
++                                      VIR_CGROUP_CONTROLLER_MEMORY,
++                                      "memory.limit_in_bytes",
++                                      &mem_unlimited));
++ cleanup:
++    virCgroupFree(&group);
++    virCgroupV1MemoryUnlimitedKB = mem_unlimited >> 10;
++}
++
++static unsigned long long int
++virCgroupV1GetMemoryUnlimitedKB(void)
++{
++    if (virOnce(&virCgroupV1MemoryOnce, virCgroupV1MemoryOnceInit) < 0)
++        VIR_DEBUG("Init failed, will fall back to defaults.");
++
++    if (virCgroupV1MemoryUnlimitedKB)
++        return virCgroupV1MemoryUnlimitedKB;
++    else
++        return VIR_DOMAIN_MEMORY_PARAM_UNLIMITED;
++}
++
++
+ static int
+ virCgroupV1SetMemory(virCgroupPtr group,
+                      unsigned long long kb)
+@@ -1494,6 +1539,123 @@ virCgroupV1GetMemoryUsage(virCgroupPtr group,
+ }
+ 
+ 
++static int
++virCgroupV1SetMemoryHardLimit(virCgroupPtr group,
++                              unsigned long long kb)
++{
++    return virCgroupV1SetMemory(group, kb);
++}
++
++
++static int
++virCgroupV1GetMemoryHardLimit(virCgroupPtr group,
++                              unsigned long long *kb)
++{
++    long long unsigned int limit_in_bytes;
++
++    if (virCgroupGetValueU64(group,
++                             VIR_CGROUP_CONTROLLER_MEMORY,
++                             "memory.limit_in_bytes", &limit_in_bytes) < 0)
++        return -1;
++
++    *kb = limit_in_bytes >> 10;
++    if (*kb >= virCgroupV1GetMemoryUnlimitedKB())
++        *kb = VIR_DOMAIN_MEMORY_PARAM_UNLIMITED;
++
++    return 0;
++}
++
++
++static int
++virCgroupV1SetMemorySoftLimit(virCgroupPtr group,
++                              unsigned long long kb)
++{
++    unsigned long long maxkb = VIR_DOMAIN_MEMORY_PARAM_UNLIMITED;
++
++    if (kb > maxkb) {
++        virReportError(VIR_ERR_INVALID_ARG,
++                       _("Memory '%llu' must be less than %llu"),
++                       kb, maxkb);
++        return -1;
++    }
++
++    if (kb == maxkb)
++        return virCgroupSetValueI64(group,
++                                    VIR_CGROUP_CONTROLLER_MEMORY,
++                                    "memory.soft_limit_in_bytes",
++                                    -1);
++    else
++        return virCgroupSetValueU64(group,
++                                    VIR_CGROUP_CONTROLLER_MEMORY,
++                                    "memory.soft_limit_in_bytes",
++                                    kb << 10);
++}
++
++
++static int
++virCgroupV1GetMemorySoftLimit(virCgroupPtr group,
++                              unsigned long long *kb)
++{
++    long long unsigned int limit_in_bytes;
++
++    if (virCgroupGetValueU64(group,
++                             VIR_CGROUP_CONTROLLER_MEMORY,
++                             "memory.soft_limit_in_bytes", &limit_in_bytes) < 0)
++        return -1;
++
++    *kb = limit_in_bytes >> 10;
++    if (*kb >= virCgroupV1GetMemoryUnlimitedKB())
++        *kb = VIR_DOMAIN_MEMORY_PARAM_UNLIMITED;
++
++    return 0;
++}
++
++
++static int
++virCgroupV1SetMemSwapHardLimit(virCgroupPtr group,
++                               unsigned long long kb)
++{
++    unsigned long long maxkb = VIR_DOMAIN_MEMORY_PARAM_UNLIMITED;
++
++    if (kb > maxkb) {
++        virReportError(VIR_ERR_INVALID_ARG,
++                       _("Memory '%llu' must be less than %llu"),
++                       kb, maxkb);
++        return -1;
++    }
++
++    if (kb == maxkb)
++        return virCgroupSetValueI64(group,
++                                    VIR_CGROUP_CONTROLLER_MEMORY,
++                                    "memory.memsw.limit_in_bytes",
++                                    -1);
++    else
++        return virCgroupSetValueU64(group,
++                                    VIR_CGROUP_CONTROLLER_MEMORY,
++                                    "memory.memsw.limit_in_bytes",
++                                    kb << 10);
++}
++
++
++static int
++virCgroupV1GetMemSwapHardLimit(virCgroupPtr group,
++                               unsigned long long *kb)
++{
++    long long unsigned int limit_in_bytes;
++
++    if (virCgroupGetValueU64(group,
++                             VIR_CGROUP_CONTROLLER_MEMORY,
++                             "memory.memsw.limit_in_bytes", &limit_in_bytes) < 0)
++        return -1;
++
++    *kb = limit_in_bytes >> 10;
++    if (*kb >= virCgroupV1GetMemoryUnlimitedKB())
++        *kb = VIR_DOMAIN_MEMORY_PARAM_UNLIMITED;
++
++    return 0;
++}
++
++
+ virCgroupBackend virCgroupV1Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V1,
+ 
+@@ -1534,6 +1696,12 @@ virCgroupBackend virCgroupV1Backend = {
+     .setMemory = virCgroupV1SetMemory,
+     .getMemoryStat = virCgroupV1GetMemoryStat,
+     .getMemoryUsage = virCgroupV1GetMemoryUsage,
++    .setMemoryHardLimit = virCgroupV1SetMemoryHardLimit,
++    .getMemoryHardLimit = virCgroupV1GetMemoryHardLimit,
++    .setMemorySoftLimit = virCgroupV1SetMemorySoftLimit,
++    .getMemorySoftLimit = virCgroupV1GetMemorySoftLimit,
++    .setMemSwapHardLimit = virCgroupV1SetMemSwapHardLimit,
++    .getMemSwapHardLimit = virCgroupV1GetMemSwapHardLimit,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-extract-virCgroupV1AddTask.patch b/SOURCES/libvirt-vircgroup-extract-virCgroupV1AddTask.patch
new file mode 100644
index 0000000..ca3e8d8
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-extract-virCgroupV1AddTask.patch
@@ -0,0 +1,234 @@
+From a756729403915485dbd3cbdf4f252806318c227c Mon Sep 17 00:00:00 2001
+Message-Id: <a756729403915485dbd3cbdf4f252806318c227c@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:06:37 +0200
+Subject: [PATCH] vircgroup: extract virCgroupV1AddTask
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 064024e70afd6ad08993444b3839eb3ba67426f2)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <558f1a90ce9b0fc5a9688c5a44bf85dd523c37e5.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c        | 56 ++++---------------------------------
+ src/util/vircgroupbackend.h | 20 +++++++++++++
+ src/util/vircgrouppriv.h    |  5 ++++
+ src/util/vircgroupv1.c      | 31 ++++++++++++++++++++
+ 4 files changed, 62 insertions(+), 50 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index 33d34d6eda..a5076cb554 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -544,7 +544,7 @@ virCgroupSetValueU64(virCgroupPtr group,
+ }
+ 
+ 
+-static int
++int
+ virCgroupSetValueI64(virCgroupPtr group,
+                      int controller,
+                      const char *key,
+@@ -672,50 +672,6 @@ virCgroupNew(pid_t pid,
+ }
+ 
+ 
+-typedef enum {
+-    /* Adds a whole process with all threads to specific cgroup except
+-     * to systemd named controller. */
+-    VIR_CGROUP_TASK_PROCESS = 1 << 0,
+-
+-    /* Same as VIR_CGROUP_TASK_PROCESS but it also adds the task to systemd
+-     * named controller. */
+-    VIR_CGROUP_TASK_SYSTEMD = 1 << 1,
+-
+-    /* Moves only specific thread into cgroup except to systemd
+-     * named controller. */
+-    VIR_CGROUP_TASK_THREAD = 1 << 2,
+-} virCgroupTaskFlags;
+-
+-
+-static int
+-virCgroupAddTaskInternal(virCgroupPtr group,
+-                         pid_t pid,
+-                         unsigned int flags)
+-{
+-    int ret = -1;
+-    size_t i;
+-
+-    for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
+-        /* Skip over controllers not mounted */
+-        if (!group->controllers[i].mountPoint)
+-            continue;
+-
+-        /* We must never add tasks in systemd's hierarchy
+-         * unless we're intentionally trying to move a
+-         * task into a systemd machine scope */
+-        if (i == VIR_CGROUP_CONTROLLER_SYSTEMD &&
+-            !(flags & VIR_CGROUP_TASK_SYSTEMD))
+-            continue;
+-
+-        if (virCgroupSetValueI64(group, i, "tasks", pid) < 0)
+-            goto cleanup;
+-    }
+-
+-    ret = 0;
+- cleanup:
+-    return ret;
+-}
+-
+ /**
+  * virCgroupAddProcess:
+  *
+@@ -730,7 +686,7 @@ virCgroupAddTaskInternal(virCgroupPtr group,
+ int
+ virCgroupAddProcess(virCgroupPtr group, pid_t pid)
+ {
+-    return virCgroupAddTaskInternal(group, pid, VIR_CGROUP_TASK_PROCESS);
++    return group->backend->addTask(group, pid, VIR_CGROUP_TASK_PROCESS);
+ }
+ 
+ /**
+@@ -747,9 +703,9 @@ virCgroupAddProcess(virCgroupPtr group, pid_t pid)
+ int
+ virCgroupAddMachineProcess(virCgroupPtr group, pid_t pid)
+ {
+-    return virCgroupAddTaskInternal(group, pid,
+-                                    VIR_CGROUP_TASK_PROCESS |
+-                                    VIR_CGROUP_TASK_SYSTEMD);
++    return group->backend->addTask(group, pid,
++                                   VIR_CGROUP_TASK_PROCESS |
++                                   VIR_CGROUP_TASK_SYSTEMD);
+ }
+ 
+ /**
+@@ -767,7 +723,7 @@ int
+ virCgroupAddThread(virCgroupPtr group,
+                    pid_t pid)
+ {
+-    return virCgroupAddTaskInternal(group, pid, VIR_CGROUP_TASK_THREAD);
++    return group->backend->addTask(group, pid, VIR_CGROUP_TASK_THREAD);
+ }
+ 
+ 
+diff --git a/src/util/vircgroupbackend.h b/src/util/vircgroupbackend.h
+index 1f28c51c49..bff1f8938e 100644
+--- a/src/util/vircgroupbackend.h
++++ b/src/util/vircgroupbackend.h
+@@ -35,6 +35,20 @@ typedef enum {
+                                        */
+ } virCgroupBackendFlags;
+ 
++typedef enum {
++    /* Adds a whole process with all threads to specific cgroup except
++     * to systemd named controller. */
++    VIR_CGROUP_TASK_PROCESS = 1 << 0,
++
++    /* Same as VIR_CGROUP_TASK_PROCESS but it also adds the task to systemd
++     * named controller. */
++    VIR_CGROUP_TASK_SYSTEMD = 1 << 1,
++
++    /* Moves only specific thread into cgroup except to systemd
++     * named controller. */
++    VIR_CGROUP_TASK_THREAD = 1 << 2,
++} virCgroupBackendTaskFlags;
++
+ typedef enum {
+     VIR_CGROUP_BACKEND_TYPE_V1 = 0,
+     VIR_CGROUP_BACKEND_TYPE_LAST,
+@@ -103,6 +117,11 @@ typedef int
+ typedef int
+ (*virCgroupRemoveCB)(virCgroupPtr group);
+ 
++typedef int
++(*virCgroupAddTaskCB)(virCgroupPtr group,
++                      pid_t pid,
++                      unsigned int flags);
++
+ struct _virCgroupBackend {
+     virCgroupBackendType type;
+ 
+@@ -121,6 +140,7 @@ struct _virCgroupBackend {
+     virCgroupPathOfControllerCB pathOfController;
+     virCgroupMakeGroupCB makeGroup;
+     virCgroupRemoveCB remove;
++    virCgroupAddTaskCB addTask;
+ };
+ typedef struct _virCgroupBackend virCgroupBackend;
+ typedef virCgroupBackend *virCgroupBackendPtr;
+diff --git a/src/util/vircgrouppriv.h b/src/util/vircgrouppriv.h
+index a760b9bcfd..01714370be 100644
+--- a/src/util/vircgrouppriv.h
++++ b/src/util/vircgrouppriv.h
+@@ -73,6 +73,11 @@ int virCgroupGetValueU64(virCgroupPtr group,
+                          const char *key,
+                          unsigned long long int *value);
+ 
++int virCgroupSetValueI64(virCgroupPtr group,
++                         int controller,
++                         const char *key,
++                         long long int value);
++
+ int virCgroupPartitionEscape(char **path);
+ 
+ int virCgroupNewPartition(const char *path,
+diff --git a/src/util/vircgroupv1.c b/src/util/vircgroupv1.c
+index 4d4b51094a..fda2c43eef 100644
+--- a/src/util/vircgroupv1.c
++++ b/src/util/vircgroupv1.c
+@@ -706,6 +706,36 @@ virCgroupV1Remove(virCgroupPtr group)
+ }
+ 
+ 
++static int
++virCgroupV1AddTask(virCgroupPtr group,
++                   pid_t pid,
++                   unsigned int flags)
++{
++    int ret = -1;
++    size_t i;
++
++    for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
++        /* Skip over controllers not mounted */
++        if (!group->controllers[i].mountPoint)
++            continue;
++
++        /* We must never add tasks in systemd's hierarchy
++         * unless we're intentionally trying to move a
++         * task into a systemd machine scope */
++        if (i == VIR_CGROUP_CONTROLLER_SYSTEMD &&
++            !(flags & VIR_CGROUP_TASK_SYSTEMD))
++            continue;
++
++        if (virCgroupSetValueI64(group, i, "tasks", pid) < 0)
++            goto cleanup;
++    }
++
++    ret = 0;
++ cleanup:
++    return ret;
++}
++
++
+ virCgroupBackend virCgroupV1Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V1,
+ 
+@@ -723,6 +753,7 @@ virCgroupBackend virCgroupV1Backend = {
+     .pathOfController = virCgroupV1PathOfController,
+     .makeGroup = virCgroupV1MakeGroup,
+     .remove = virCgroupV1Remove,
++    .addTask = virCgroupV1AddTask,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-extract-virCgroupV1Available.patch b/SOURCES/libvirt-vircgroup-extract-virCgroupV1Available.patch
new file mode 100644
index 0000000..a8f932f
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-extract-virCgroupV1Available.patch
@@ -0,0 +1,173 @@
+From 0dcb8bdc63970be07228108f602a7425612bd1fe Mon Sep 17 00:00:00 2001
+Message-Id: <0dcb8bdc63970be07228108f602a7425612bd1fe@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:06:23 +0200
+Subject: [PATCH] vircgroup: extract virCgroupV1Available
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 57d35b72c9049348b36382ce88bee32553e0fae5)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <c54c63779affc0f0a30224fd8001aa53fff9df52.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c        | 28 ++++++++--------------------
+ src/util/vircgroupbackend.h |  7 +++++++
+ src/util/vircgroupv1.c      | 35 +++++++++++++++++++++++++++++++++++
+ 3 files changed, 50 insertions(+), 20 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index d55f411daa..47a3b9ed58 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -51,6 +51,7 @@
+ 
+ #include "virutil.h"
+ #include "viralloc.h"
++#include "vircgroupbackend.h"
+ #include "virerror.h"
+ #include "virlog.h"
+ #include "virfile.h"
+@@ -64,8 +65,6 @@
+ 
+ VIR_LOG_INIT("util.cgroup");
+ 
+-#define CGROUP_MAX_VAL 512
+-
+ #define VIR_FROM_THIS VIR_FROM_CGROUP
+ 
+ #define CGROUP_NB_TOTAL_CPU_STAT_PARAM 3
+@@ -132,29 +131,18 @@ virCgroupGetDevicePermsString(int perms)
+ bool
+ virCgroupAvailable(void)
+ {
+-    bool ret = false;
+-    FILE *mounts = NULL;
+-    struct mntent entry;
+-    char buf[CGROUP_MAX_VAL];
++    size_t i;
++    virCgroupBackendPtr *backends = virCgroupBackendGetAll();
+ 
+-    if (!virFileExists("/proc/cgroups"))
++    if (!backends)
+         return false;
+ 
+-    if (!(mounts = fopen("/proc/mounts", "r")))
+-        return false;
+-
+-    while (getmntent_r(mounts, &entry, buf, sizeof(buf)) != NULL) {
+-        /* We're looking for at least one 'cgroup' fs mount,
+-         * which is *not* a named mount. */
+-        if (STREQ(entry.mnt_type, "cgroup") &&
+-            !strstr(entry.mnt_opts, "name=")) {
+-            ret = true;
+-            break;
+-        }
++    for (i = 0; i < VIR_CGROUP_BACKEND_TYPE_LAST; i++) {
++        if (backends[i] && backends[i]->available())
++            return true;
+     }
+ 
+-    VIR_FORCE_FCLOSE(mounts);
+-    return ret;
++    return false;
+ }
+ 
+ 
+diff --git a/src/util/vircgroupbackend.h b/src/util/vircgroupbackend.h
+index db052485a8..88f51416b0 100644
+--- a/src/util/vircgroupbackend.h
++++ b/src/util/vircgroupbackend.h
+@@ -25,14 +25,21 @@
+ 
+ # include "vircgroup.h"
+ 
++# define CGROUP_MAX_VAL 512
+ 
+ typedef enum {
+     VIR_CGROUP_BACKEND_TYPE_V1 = 0,
+     VIR_CGROUP_BACKEND_TYPE_LAST,
+ } virCgroupBackendType;
+ 
++typedef bool
++(*virCgroupAvailableCB)(void);
++
+ struct _virCgroupBackend {
+     virCgroupBackendType type;
++
++    /* Mandatory callbacks that need to be implemented for every backend. */
++    virCgroupAvailableCB available;
+ };
+ typedef struct _virCgroupBackend virCgroupBackend;
+ typedef virCgroupBackend *virCgroupBackendPtr;
+diff --git a/src/util/vircgroupv1.c b/src/util/vircgroupv1.c
+index 4dda7865f1..73045b1109 100644
+--- a/src/util/vircgroupv1.c
++++ b/src/util/vircgroupv1.c
+@@ -20,6 +20,10 @@
+  */
+ #include <config.h>
+ 
++#if defined HAVE_MNTENT_H && defined HAVE_GETMNTENT_R
++# include <mntent.h>
++#endif
++
+ #include "internal.h"
+ 
+ #define __VIR_CGROUP_ALLOW_INCLUDE_PRIV_H__
+@@ -29,6 +33,7 @@
+ #include "vircgroup.h"
+ #include "vircgroupbackend.h"
+ #include "vircgroupv1.h"
++#include "virfile.h"
+ #include "virlog.h"
+ 
+ VIR_LOG_INIT("util.cgroup");
+@@ -43,8 +48,38 @@ VIR_ENUM_IMPL(virCgroupV1Controller, VIR_CGROUP_CONTROLLER_LAST,
+               "name=systemd");
+ 
+ 
++/* We're looking for at least one 'cgroup' fs mount,
++ * which is *not* a named mount. */
++static bool
++virCgroupV1Available(void)
++{
++    bool ret = false;
++    FILE *mounts = NULL;
++    struct mntent entry;
++    char buf[CGROUP_MAX_VAL];
++
++    if (!virFileExists("/proc/cgroups"))
++        return false;
++
++    if (!(mounts = fopen("/proc/mounts", "r")))
++        return false;
++
++    while (getmntent_r(mounts, &entry, buf, sizeof(buf)) != NULL) {
++        if (STREQ(entry.mnt_type, "cgroup") && !strstr(entry.mnt_opts, "name=")) {
++            ret = true;
++            break;
++        }
++    }
++
++    VIR_FORCE_FCLOSE(mounts);
++    return ret;
++}
++
++
+ virCgroupBackend virCgroupV1Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V1,
++
++    .available = virCgroupV1Available,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-extract-virCgroupV1BindMount.patch b/SOURCES/libvirt-vircgroup-extract-virCgroupV1BindMount.patch
new file mode 100644
index 0000000..9528463
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-extract-virCgroupV1BindMount.patch
@@ -0,0 +1,310 @@
+From 7ee971869f488f806a728eead8be82c287a35fc4 Mon Sep 17 00:00:00 2001
+Message-Id: <7ee971869f488f806a728eead8be82c287a35fc4@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:06:39 +0200
+Subject: [PATCH] vircgroup: extract virCgroupV1BindMount
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 8dc1b6ce50a6c007c0d2149ac7106221c99beb6f)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <71e4dbba49af93bcc36eefc92725e493a0447214.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c        | 102 +-------------------------------
+ src/util/vircgroupbackend.h |   6 ++
+ src/util/vircgroupv1.c      | 113 ++++++++++++++++++++++++++++++++++++
+ 3 files changed, 120 insertions(+), 101 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index d4d02d8f5b..7789966472 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -3179,35 +3179,6 @@ virCgroupKillPainfully(virCgroupPtr group)
+ }
+ 
+ 
+-static char *
+-virCgroupIdentifyRoot(virCgroupPtr group)
+-{
+-    char *ret = NULL;
+-    size_t i;
+-
+-    for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
+-        char *tmp;
+-        if (!group->controllers[i].mountPoint)
+-            continue;
+-        if (!(tmp = strrchr(group->controllers[i].mountPoint, '/'))) {
+-            virReportError(VIR_ERR_INTERNAL_ERROR,
+-                           _("Could not find directory separator in %s"),
+-                           group->controllers[i].mountPoint);
+-            return NULL;
+-        }
+-
+-        if (VIR_STRNDUP(ret, group->controllers[i].mountPoint,
+-                        tmp - group->controllers[i].mountPoint) < 0)
+-            return NULL;
+-        return ret;
+-    }
+-
+-    virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+-                   _("Could not find any mounted controllers"));
+-    return NULL;
+-}
+-
+-
+ /**
+  * virCgroupGetCpuCfsQuota:
+  *
+@@ -3302,78 +3273,7 @@ int
+ virCgroupBindMount(virCgroupPtr group, const char *oldroot,
+                    const char *mountopts)
+ {
+-    size_t i;
+-    VIR_AUTOFREE(char *) opts = NULL;
+-    VIR_AUTOFREE(char *) root = NULL;
+-
+-    if (!(root = virCgroupIdentifyRoot(group)))
+-        return -1;
+-
+-    VIR_DEBUG("Mounting cgroups at '%s'", root);
+-
+-    if (virFileMakePath(root) < 0) {
+-        virReportSystemError(errno,
+-                             _("Unable to create directory %s"),
+-                             root);
+-        return -1;
+-    }
+-
+-    if (virAsprintf(&opts,
+-                    "mode=755,size=65536%s", mountopts) < 0)
+-        return -1;
+-
+-    if (mount("tmpfs", root, "tmpfs", MS_NOSUID|MS_NODEV|MS_NOEXEC, opts) < 0) {
+-        virReportSystemError(errno,
+-                             _("Failed to mount %s on %s type %s"),
+-                             "tmpfs", root, "tmpfs");
+-        return -1;
+-    }
+-
+-    for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
+-        if (!group->controllers[i].mountPoint)
+-            continue;
+-
+-        if (!virFileExists(group->controllers[i].mountPoint)) {
+-            VIR_AUTOFREE(char *) src = NULL;
+-            if (virAsprintf(&src, "%s%s",
+-                            oldroot,
+-                            group->controllers[i].mountPoint) < 0)
+-                return -1;
+-
+-            VIR_DEBUG("Create mount point '%s'",
+-                      group->controllers[i].mountPoint);
+-            if (virFileMakePath(group->controllers[i].mountPoint) < 0) {
+-                virReportSystemError(errno,
+-                                     _("Unable to create directory %s"),
+-                                     group->controllers[i].mountPoint);
+-                return -1;
+-            }
+-
+-            if (mount(src, group->controllers[i].mountPoint, "none", MS_BIND,
+-                      NULL) < 0) {
+-                virReportSystemError(errno,
+-                                     _("Failed to bind cgroup '%s' on '%s'"),
+-                                     src, group->controllers[i].mountPoint);
+-                return -1;
+-            }
+-        }
+-
+-        if (group->controllers[i].linkPoint) {
+-            VIR_DEBUG("Link mount point '%s' to '%s'",
+-                      group->controllers[i].mountPoint,
+-                      group->controllers[i].linkPoint);
+-            if (symlink(group->controllers[i].mountPoint,
+-                        group->controllers[i].linkPoint) < 0) {
+-                virReportSystemError(errno,
+-                                     _("Unable to symlink directory %s to %s"),
+-                                     group->controllers[i].mountPoint,
+-                                     group->controllers[i].linkPoint);
+-                return -1;
+-            }
+-        }
+-    }
+-
+-    return 0;
++    return group->backend->bindMount(group, oldroot, mountopts);
+ }
+ 
+ 
+diff --git a/src/util/vircgroupbackend.h b/src/util/vircgroupbackend.h
+index 3e0f6d01f4..caeec3de60 100644
+--- a/src/util/vircgroupbackend.h
++++ b/src/util/vircgroupbackend.h
+@@ -126,6 +126,11 @@ typedef int
+ (*virCgroupHasEmptyTasksCB)(virCgroupPtr cgroup,
+                             int controller);
+ 
++typedef int
++(*virCgroupBindMountCB)(virCgroupPtr group,
++                        const char *oldroot,
++                        const char *mountopts);
++
+ struct _virCgroupBackend {
+     virCgroupBackendType type;
+ 
+@@ -146,6 +151,7 @@ struct _virCgroupBackend {
+     virCgroupRemoveCB remove;
+     virCgroupAddTaskCB addTask;
+     virCgroupHasEmptyTasksCB hasEmptyTasks;
++    virCgroupBindMountCB bindMount;
+ };
+ typedef struct _virCgroupBackend virCgroupBackend;
+ typedef virCgroupBackend *virCgroupBackendPtr;
+diff --git a/src/util/vircgroupv1.c b/src/util/vircgroupv1.c
+index b057cdfd9e..d63525dfb0 100644
+--- a/src/util/vircgroupv1.c
++++ b/src/util/vircgroupv1.c
+@@ -24,6 +24,9 @@
+ # include <mntent.h>
+ #endif
+ #include <sys/stat.h>
++#if defined HAVE_SYS_MOUNT_H
++# include <sys/mount.h>
++#endif
+ 
+ #include "internal.h"
+ 
+@@ -755,6 +758,115 @@ virCgroupV1HasEmptyTasks(virCgroupPtr cgroup,
+ }
+ 
+ 
++static char *
++virCgroupV1IdentifyRoot(virCgroupPtr group)
++{
++    char *ret = NULL;
++    size_t i;
++
++    for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
++        char *tmp;
++        if (!group->controllers[i].mountPoint)
++            continue;
++        if (!(tmp = strrchr(group->controllers[i].mountPoint, '/'))) {
++            virReportError(VIR_ERR_INTERNAL_ERROR,
++                           _("Could not find directory separator in %s"),
++                           group->controllers[i].mountPoint);
++            return NULL;
++        }
++
++        if (VIR_STRNDUP(ret, group->controllers[i].mountPoint,
++                        tmp - group->controllers[i].mountPoint) < 0)
++            return NULL;
++        return ret;
++    }
++
++    virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
++                   _("Could not find any mounted v1 controllers"));
++    return NULL;
++}
++
++
++static int
++virCgroupV1BindMount(virCgroupPtr group,
++                     const char *oldroot,
++                     const char *mountopts)
++{
++    size_t i;
++    VIR_AUTOFREE(char *) opts = NULL;
++    VIR_AUTOFREE(char *) root = NULL;
++
++    if (!(root = virCgroupV1IdentifyRoot(group)))
++        return -1;
++
++    VIR_DEBUG("Mounting cgroups at '%s'", root);
++
++    if (virFileMakePath(root) < 0) {
++        virReportSystemError(errno,
++                             _("Unable to create directory %s"),
++                             root);
++        return -1;
++    }
++
++    if (virAsprintf(&opts,
++                    "mode=755,size=65536%s", mountopts) < 0)
++        return -1;
++
++    if (mount("tmpfs", root, "tmpfs", MS_NOSUID|MS_NODEV|MS_NOEXEC, opts) < 0) {
++        virReportSystemError(errno,
++                             _("Failed to mount %s on %s type %s"),
++                             "tmpfs", root, "tmpfs");
++        return -1;
++    }
++
++    for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
++        if (!group->controllers[i].mountPoint)
++            continue;
++
++        if (!virFileExists(group->controllers[i].mountPoint)) {
++            VIR_AUTOFREE(char *) src = NULL;
++            if (virAsprintf(&src, "%s%s",
++                            oldroot,
++                            group->controllers[i].mountPoint) < 0)
++                return -1;
++
++            VIR_DEBUG("Create mount point '%s'",
++                      group->controllers[i].mountPoint);
++            if (virFileMakePath(group->controllers[i].mountPoint) < 0) {
++                virReportSystemError(errno,
++                                     _("Unable to create directory %s"),
++                                     group->controllers[i].mountPoint);
++                return -1;
++            }
++
++            if (mount(src, group->controllers[i].mountPoint, "none", MS_BIND,
++                      NULL) < 0) {
++                virReportSystemError(errno,
++                                     _("Failed to bind cgroup '%s' on '%s'"),
++                                     src, group->controllers[i].mountPoint);
++                return -1;
++            }
++        }
++
++        if (group->controllers[i].linkPoint) {
++            VIR_DEBUG("Link mount point '%s' to '%s'",
++                      group->controllers[i].mountPoint,
++                      group->controllers[i].linkPoint);
++            if (symlink(group->controllers[i].mountPoint,
++                        group->controllers[i].linkPoint) < 0) {
++                virReportSystemError(errno,
++                                     _("Unable to symlink directory %s to %s"),
++                                     group->controllers[i].mountPoint,
++                                     group->controllers[i].linkPoint);
++                return -1;
++            }
++        }
++    }
++
++    return 0;
++}
++
++
+ virCgroupBackend virCgroupV1Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V1,
+ 
+@@ -774,6 +886,7 @@ virCgroupBackend virCgroupV1Backend = {
+     .remove = virCgroupV1Remove,
+     .addTask = virCgroupV1AddTask,
+     .hasEmptyTasks = virCgroupV1HasEmptyTasks,
++    .bindMount = virCgroupV1BindMount,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-extract-virCgroupV1CopyMounts.patch b/SOURCES/libvirt-vircgroup-extract-virCgroupV1CopyMounts.patch
new file mode 100644
index 0000000..08ce542
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-extract-virCgroupV1CopyMounts.patch
@@ -0,0 +1,129 @@
+From ac37b7c9693d27c9c20f87b3fd077bf55ac1d34f Mon Sep 17 00:00:00 2001
+Message-Id: <ac37b7c9693d27c9c20f87b3fd077bf55ac1d34f@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:06:26 +0200
+Subject: [PATCH] vircgroup: extract virCgroupV1CopyMounts
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 47941ea7f52be44f609a6b6acc8895644039e617)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <b833625dd800eee0c3aac96f120ca27dae81ce89.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c        | 23 +----------------------
+ src/util/vircgroupbackend.h |  5 +++++
+ src/util/vircgroupv1.c      | 22 ++++++++++++++++++++++
+ 3 files changed, 28 insertions(+), 22 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index 6825623478..9d644d37d1 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -235,27 +235,6 @@ virCgroupPartitionEscape(char **path)
+ }
+ 
+ 
+-static int
+-virCgroupCopyMounts(virCgroupPtr group,
+-                    virCgroupPtr parent)
+-{
+-    size_t i;
+-    for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
+-        if (!parent->controllers[i].mountPoint)
+-            continue;
+-
+-        if (VIR_STRDUP(group->controllers[i].mountPoint,
+-                       parent->controllers[i].mountPoint) < 0)
+-            return -1;
+-
+-        if (VIR_STRDUP(group->controllers[i].linkPoint,
+-                       parent->controllers[i].linkPoint) < 0)
+-            return -1;
+-    }
+-    return 0;
+-}
+-
+-
+ static int
+ virCgroupResolveMountLink(const char *mntDir,
+                           const char *typeStr,
+@@ -653,7 +632,7 @@ virCgroupDetect(virCgroupPtr group,
+     }
+ 
+     if (parent) {
+-        if (virCgroupCopyMounts(group, parent) < 0)
++        if (group->backend->copyMounts(group, parent) < 0)
+             return -1;
+     } else {
+         if (virCgroupDetectMounts(group) < 0)
+diff --git a/src/util/vircgroupbackend.h b/src/util/vircgroupbackend.h
+index daf47bac09..81ee597fc8 100644
+--- a/src/util/vircgroupbackend.h
++++ b/src/util/vircgroupbackend.h
+@@ -41,12 +41,17 @@ typedef bool
+                                    const char *drivername,
+                                    const char *machinename);
+ 
++typedef int
++(*virCgroupCopyMountsCB)(virCgroupPtr group,
++                         virCgroupPtr parent);
++
+ struct _virCgroupBackend {
+     virCgroupBackendType type;
+ 
+     /* Mandatory callbacks that need to be implemented for every backend. */
+     virCgroupAvailableCB available;
+     virCgroupValidateMachineGroupCB validateMachineGroup;
++    virCgroupCopyMountsCB copyMounts;
+ };
+ typedef struct _virCgroupBackend virCgroupBackend;
+ typedef virCgroupBackend *virCgroupBackendPtr;
+diff --git a/src/util/vircgroupv1.c b/src/util/vircgroupv1.c
+index b78cdcab53..50b58ab413 100644
+--- a/src/util/vircgroupv1.c
++++ b/src/util/vircgroupv1.c
+@@ -160,11 +160,33 @@ virCgroupV1ValidateMachineGroup(virCgroupPtr group,
+ }
+ 
+ 
++static int
++virCgroupV1CopyMounts(virCgroupPtr group,
++                      virCgroupPtr parent)
++{
++    size_t i;
++    for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
++        if (!parent->controllers[i].mountPoint)
++            continue;
++
++        if (VIR_STRDUP(group->controllers[i].mountPoint,
++                       parent->controllers[i].mountPoint) < 0)
++            return -1;
++
++        if (VIR_STRDUP(group->controllers[i].linkPoint,
++                       parent->controllers[i].linkPoint) < 0)
++            return -1;
++    }
++    return 0;
++}
++
++
+ virCgroupBackend virCgroupV1Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V1,
+ 
+     .available = virCgroupV1Available,
+     .validateMachineGroup = virCgroupV1ValidateMachineGroup,
++    .copyMounts = virCgroupV1CopyMounts,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-extract-virCgroupV1CopyPlacement.patch b/SOURCES/libvirt-vircgroup-extract-virCgroupV1CopyPlacement.patch
new file mode 100644
index 0000000..dacd6d8
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-extract-virCgroupV1CopyPlacement.patch
@@ -0,0 +1,163 @@
+From b246f8418526ea154fe2f0223f6f34ea86b90ea4 Mon Sep 17 00:00:00 2001
+Message-Id: <b246f8418526ea154fe2f0223f6f34ea86b90ea4@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:06:28 +0200
+Subject: [PATCH] vircgroup: extract virCgroupV1CopyPlacement
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 229a8b5d3504efdbe8cd25bb3a127ec74ab4bbd3)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <9a9b8e24c5574e7b61e19a46d9978bf0dc1b32d3.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c        | 38 +------------------------------------
+ src/util/vircgroupbackend.h |  6 ++++++
+ src/util/vircgroupv1.c      | 37 ++++++++++++++++++++++++++++++++++++
+ 3 files changed, 44 insertions(+), 37 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index 10c99a66fd..b63321ca33 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -269,42 +269,6 @@ virCgroupDetectMounts(virCgroupPtr group)
+ }
+ 
+ 
+-static int
+-virCgroupCopyPlacement(virCgroupPtr group,
+-                       const char *path,
+-                       virCgroupPtr parent)
+-{
+-    size_t i;
+-    for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
+-        if (!group->controllers[i].mountPoint)
+-            continue;
+-
+-        if (i == VIR_CGROUP_CONTROLLER_SYSTEMD)
+-            continue;
+-
+-        if (path[0] == '/') {
+-            if (VIR_STRDUP(group->controllers[i].placement, path) < 0)
+-                return -1;
+-        } else {
+-            /*
+-             * parent == "/" + path="" => "/"
+-             * parent == "/libvirt.service" + path == "" => "/libvirt.service"
+-             * parent == "/libvirt.service" + path == "foo" => "/libvirt.service/foo"
+-             */
+-            if (virAsprintf(&group->controllers[i].placement,
+-                            "%s%s%s",
+-                            parent->controllers[i].placement,
+-                            (STREQ(parent->controllers[i].placement, "/") ||
+-                             STREQ(path, "") ? "" : "/"),
+-                            path) < 0)
+-                return -1;
+-        }
+-    }
+-
+-    return 0;
+-}
+-
+-
+ /*
+  * virCgroupDetectPlacement:
+  * @group: the group to process
+@@ -532,7 +496,7 @@ virCgroupDetect(virCgroupPtr group,
+      * based on the parent cgroup...
+      */
+     if ((parent || path[0] == '/') &&
+-        virCgroupCopyPlacement(group, path, parent) < 0)
++        group->backend->copyPlacement(group, path, parent) < 0)
+         return -1;
+ 
+     /* ... but use /proc/cgroups to fill in the rest */
+diff --git a/src/util/vircgroupbackend.h b/src/util/vircgroupbackend.h
+index fadc7efdcf..85906e7191 100644
+--- a/src/util/vircgroupbackend.h
++++ b/src/util/vircgroupbackend.h
+@@ -45,6 +45,11 @@ typedef int
+ (*virCgroupCopyMountsCB)(virCgroupPtr group,
+                          virCgroupPtr parent);
+ 
++typedef int
++(*virCgroupCopyPlacementCB)(virCgroupPtr group,
++                            const char *path,
++                            virCgroupPtr parent);
++
+ typedef int
+ (*virCgroupDetectMountsCB)(virCgroupPtr group,
+                            const char *mntType,
+@@ -64,6 +69,7 @@ struct _virCgroupBackend {
+     virCgroupAvailableCB available;
+     virCgroupValidateMachineGroupCB validateMachineGroup;
+     virCgroupCopyMountsCB copyMounts;
++    virCgroupCopyPlacementCB copyPlacement;
+     virCgroupDetectMountsCB detectMounts;
+     virCgroupDetectPlacementCB detectPlacement;
+ };
+diff --git a/src/util/vircgroupv1.c b/src/util/vircgroupv1.c
+index bd9f28f6e9..68bb1c6f5d 100644
+--- a/src/util/vircgroupv1.c
++++ b/src/util/vircgroupv1.c
+@@ -183,6 +183,42 @@ virCgroupV1CopyMounts(virCgroupPtr group,
+ }
+ 
+ 
++static int
++virCgroupV1CopyPlacement(virCgroupPtr group,
++                         const char *path,
++                         virCgroupPtr parent)
++{
++    size_t i;
++    for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
++        if (!group->controllers[i].mountPoint)
++            continue;
++
++        if (i == VIR_CGROUP_CONTROLLER_SYSTEMD)
++            continue;
++
++        if (path[0] == '/') {
++            if (VIR_STRDUP(group->controllers[i].placement, path) < 0)
++                return -1;
++        } else {
++            /*
++             * parent == "/" + path="" => "/"
++             * parent == "/libvirt.service" + path == "" => "/libvirt.service"
++             * parent == "/libvirt.service" + path == "foo" => "/libvirt.service/foo"
++             */
++            if (virAsprintf(&group->controllers[i].placement,
++                            "%s%s%s",
++                            parent->controllers[i].placement,
++                            (STREQ(parent->controllers[i].placement, "/") ||
++                             STREQ(path, "") ? "" : "/"),
++                            path) < 0)
++                return -1;
++        }
++    }
++
++    return 0;
++}
++
++
+ static int
+ virCgroupV1ResolveMountLink(const char *mntDir,
+                             const char *typeStr,
+@@ -343,6 +379,7 @@ virCgroupBackend virCgroupV1Backend = {
+     .available = virCgroupV1Available,
+     .validateMachineGroup = virCgroupV1ValidateMachineGroup,
+     .copyMounts = virCgroupV1CopyMounts,
++    .copyPlacement = virCgroupV1CopyPlacement,
+     .detectMounts = virCgroupV1DetectMounts,
+     .detectPlacement = virCgroupV1DetectPlacement,
+ };
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-extract-virCgroupV1DetectControllers.patch b/SOURCES/libvirt-vircgroup-extract-virCgroupV1DetectControllers.patch
new file mode 100644
index 0000000..dbf60ef
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-extract-virCgroupV1DetectControllers.patch
@@ -0,0 +1,218 @@
+From c5ff4dbe89d9a57da51bb92389ebd9e5af4dd8dc Mon Sep 17 00:00:00 2001
+Message-Id: <c5ff4dbe89d9a57da51bb92389ebd9e5af4dd8dc@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:06:31 +0200
+Subject: [PATCH] vircgroup: extract virCgroupV1DetectControllers
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit d7f77dd6d5bcf91c3422a15842c2b7c2714510af)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <a066563f5d5183b6e09ae73cbfb3defb478bb693.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c        | 66 +------------------------------------
+ src/util/vircgroupbackend.h |  5 +++
+ src/util/vircgroupv1.c      | 65 ++++++++++++++++++++++++++++++++++++
+ 3 files changed, 71 insertions(+), 65 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index 0e64ad67f4..2e74cbbff4 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -349,70 +349,6 @@ virCgroupDetectPlacement(virCgroupPtr group,
+ }
+ 
+ 
+-static int
+-virCgroupDetectControllers(virCgroupPtr group,
+-                           int controllers)
+-{
+-    size_t i;
+-    size_t j;
+-
+-    if (controllers >= 0) {
+-        VIR_DEBUG("Filtering controllers %d", controllers);
+-        /* First mark requested but non-existing controllers to be ignored */
+-        for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
+-            if (((1 << i) & controllers)) {
+-                /* Remove non-existent controllers  */
+-                if (!group->controllers[i].mountPoint) {
+-                    VIR_DEBUG("Requested controller '%s' not mounted, ignoring",
+-                              virCgroupControllerTypeToString(i));
+-                    controllers &= ~(1 << i);
+-                }
+-            }
+-        }
+-        for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
+-            VIR_DEBUG("Controller '%s' wanted=%s, mount='%s'",
+-                      virCgroupControllerTypeToString(i),
+-                      (1 << i) & controllers ? "yes" : "no",
+-                      NULLSTR(group->controllers[i].mountPoint));
+-            if (!((1 << i) & controllers) &&
+-                group->controllers[i].mountPoint) {
+-                /* Check whether a request to disable a controller
+-                 * clashes with co-mounting of controllers */
+-                for (j = 0; j < VIR_CGROUP_CONTROLLER_LAST; j++) {
+-                    if (j == i)
+-                        continue;
+-                    if (!((1 << j) & controllers))
+-                        continue;
+-
+-                    if (STREQ_NULLABLE(group->controllers[i].mountPoint,
+-                                       group->controllers[j].mountPoint)) {
+-                        virReportSystemError(EINVAL,
+-                                             _("Controller '%s' is not wanted, but '%s' is co-mounted"),
+-                                             virCgroupControllerTypeToString(i),
+-                                             virCgroupControllerTypeToString(j));
+-                        return -1;
+-                    }
+-                }
+-                VIR_FREE(group->controllers[i].mountPoint);
+-            }
+-        }
+-    } else {
+-        VIR_DEBUG("Auto-detecting controllers");
+-        controllers = 0;
+-        for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
+-            VIR_DEBUG("Controller '%s' present=%s",
+-                      virCgroupControllerTypeToString(i),
+-                      group->controllers[i].mountPoint ? "yes" : "no");
+-            if (group->controllers[i].mountPoint == NULL)
+-                continue;
+-            controllers |= (1 << i);
+-        }
+-    }
+-
+-    return controllers;
+-}
+-
+-
+ static int
+ virCgroupDetect(virCgroupPtr group,
+                 pid_t pid,
+@@ -451,7 +387,7 @@ virCgroupDetect(virCgroupPtr group,
+             return -1;
+     }
+ 
+-    rc = virCgroupDetectControllers(group, controllers);
++    rc = group->backend->detectControllers(group, controllers);
+     if (rc < 0)
+         return -1;
+ 
+diff --git a/src/util/vircgroupbackend.h b/src/util/vircgroupbackend.h
+index 9c0bd89793..011d1b00da 100644
+--- a/src/util/vircgroupbackend.h
++++ b/src/util/vircgroupbackend.h
+@@ -69,6 +69,10 @@ typedef int
+ typedef char *
+ (*virCgroupStealPlacementCB)(virCgroupPtr group);
+ 
++typedef int
++(*virCgroupDetectControllersCB)(virCgroupPtr group,
++                                int controllers);
++
+ struct _virCgroupBackend {
+     virCgroupBackendType type;
+ 
+@@ -81,6 +85,7 @@ struct _virCgroupBackend {
+     virCgroupDetectPlacementCB detectPlacement;
+     virCgroupValidatePlacementCB validatePlacement;
+     virCgroupStealPlacementCB stealPlacement;
++    virCgroupDetectControllersCB detectControllers;
+ };
+ typedef struct _virCgroupBackend virCgroupBackend;
+ typedef virCgroupBackend *virCgroupBackendPtr;
+diff --git a/src/util/vircgroupv1.c b/src/util/vircgroupv1.c
+index 446546fd58..11a86c061a 100644
+--- a/src/util/vircgroupv1.c
++++ b/src/util/vircgroupv1.c
+@@ -414,6 +414,70 @@ virCgroupV1StealPlacement(virCgroupPtr group)
+ }
+ 
+ 
++static int
++virCgroupV1DetectControllers(virCgroupPtr group,
++                             int controllers)
++{
++    size_t i;
++    size_t j;
++
++    if (controllers >= 0) {
++        VIR_DEBUG("Filtering controllers %d", controllers);
++        /* First mark requested but non-existing controllers to be ignored */
++        for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
++            if (((1 << i) & controllers)) {
++                /* Remove non-existent controllers  */
++                if (!group->controllers[i].mountPoint) {
++                    VIR_DEBUG("Requested controller '%s' not mounted, ignoring",
++                              virCgroupV1ControllerTypeToString(i));
++                    controllers &= ~(1 << i);
++                }
++            }
++        }
++        for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
++            VIR_DEBUG("Controller '%s' wanted=%s, mount='%s'",
++                      virCgroupV1ControllerTypeToString(i),
++                      (1 << i) & controllers ? "yes" : "no",
++                      NULLSTR(group->controllers[i].mountPoint));
++            if (!((1 << i) & controllers) &&
++                group->controllers[i].mountPoint) {
++                /* Check whether a request to disable a controller
++                 * clashes with co-mounting of controllers */
++                for (j = 0; j < VIR_CGROUP_CONTROLLER_LAST; j++) {
++                    if (j == i)
++                        continue;
++                    if (!((1 << j) & controllers))
++                        continue;
++
++                    if (STREQ_NULLABLE(group->controllers[i].mountPoint,
++                                       group->controllers[j].mountPoint)) {
++                        virReportSystemError(EINVAL,
++                                             _("V1 controller '%s' is not wanted, but '%s' is co-mounted"),
++                                             virCgroupV1ControllerTypeToString(i),
++                                             virCgroupV1ControllerTypeToString(j));
++                        return -1;
++                    }
++                }
++                VIR_FREE(group->controllers[i].mountPoint);
++            }
++        }
++    } else {
++        VIR_DEBUG("Auto-detecting controllers");
++        controllers = 0;
++        for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
++            VIR_DEBUG("Controller '%s' present=%s",
++                      virCgroupV1ControllerTypeToString(i),
++                      group->controllers[i].mountPoint ? "yes" : "no");
++            if (group->controllers[i].mountPoint == NULL)
++                continue;
++            controllers |= (1 << i);
++        }
++    }
++
++    return controllers;
++}
++
++
+ virCgroupBackend virCgroupV1Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V1,
+ 
+@@ -425,6 +489,7 @@ virCgroupBackend virCgroupV1Backend = {
+     .detectPlacement = virCgroupV1DetectPlacement,
+     .validatePlacement = virCgroupV1ValidatePlacement,
+     .stealPlacement = virCgroupV1StealPlacement,
++    .detectControllers = virCgroupV1DetectControllers,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-extract-virCgroupV1GetAnyController.patch b/SOURCES/libvirt-vircgroup-extract-virCgroupV1GetAnyController.patch
new file mode 100644
index 0000000..5e7acc3
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-extract-virCgroupV1GetAnyController.patch
@@ -0,0 +1,118 @@
+From 98be75680dd7026b7156b3f9a0bd220f00714387 Mon Sep 17 00:00:00 2001
+Message-Id: <98be75680dd7026b7156b3f9a0bd220f00714387@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:06:33 +0200
+Subject: [PATCH] vircgroup: extract virCgroupV1GetAnyController
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit d6564037e8161bbdd270a822f5a2aafd90c7df10)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <fc1d1ba80e734d7cdbdf6300e0199b48ede77bd1.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c        | 16 ++++------------
+ src/util/vircgroupbackend.h |  4 ++++
+ src/util/vircgroupv1.c      | 22 ++++++++++++++++++++++
+ 3 files changed, 30 insertions(+), 12 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index 5bbe42b699..a6f529accd 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -3173,19 +3173,11 @@ virCgroupPathOfAnyController(virCgroupPtr group,
+                              const char *name,
+                              char **keypath)
+ {
+-    size_t i;
++    int controller;
+ 
+-    for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
+-        /* Reject any controller with a placement
+-         * of '/' to avoid doing bad stuff to the root
+-         * cgroup
+-         */
+-        if (group->controllers[i].mountPoint &&
+-            group->controllers[i].placement &&
+-            STRNEQ(group->controllers[i].placement, "/")) {
+-            return virCgroupPathOfController(group, i, name, keypath);
+-        }
+-    }
++    controller = group->backend->getAnyController(group);
++    if (controller >= 0)
++        return virCgroupPathOfController(group, controller, name, keypath);
+ 
+     virReportSystemError(ENOSYS, "%s",
+                          _("No controllers are mounted"));
+diff --git a/src/util/vircgroupbackend.h b/src/util/vircgroupbackend.h
+index 29b2fd119f..b4eaa89021 100644
+--- a/src/util/vircgroupbackend.h
++++ b/src/util/vircgroupbackend.h
+@@ -77,6 +77,9 @@ typedef bool
+ (*virCgroupHasControllerCB)(virCgroupPtr cgroup,
+                             int controller);
+ 
++typedef int
++(*virCgroupGetAnyControllerCB)(virCgroupPtr group);
++
+ struct _virCgroupBackend {
+     virCgroupBackendType type;
+ 
+@@ -91,6 +94,7 @@ struct _virCgroupBackend {
+     virCgroupStealPlacementCB stealPlacement;
+     virCgroupDetectControllersCB detectControllers;
+     virCgroupHasControllerCB hasController;
++    virCgroupGetAnyControllerCB getAnyController;
+ };
+ typedef struct _virCgroupBackend virCgroupBackend;
+ typedef virCgroupBackend *virCgroupBackendPtr;
+diff --git a/src/util/vircgroupv1.c b/src/util/vircgroupv1.c
+index 0638f48d50..bae16b8294 100644
+--- a/src/util/vircgroupv1.c
++++ b/src/util/vircgroupv1.c
+@@ -486,6 +486,27 @@ virCgroupV1HasController(virCgroupPtr group,
+ }
+ 
+ 
++static int
++virCgroupV1GetAnyController(virCgroupPtr group)
++{
++    size_t i;
++
++    for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
++        /* Reject any controller with a placement
++         * of '/' to avoid doing bad stuff to the root
++         * cgroup
++         */
++        if (group->controllers[i].mountPoint &&
++            group->controllers[i].placement &&
++            STRNEQ(group->controllers[i].placement, "/")) {
++            return i;
++        }
++    }
++
++    return -1;
++}
++
++
+ virCgroupBackend virCgroupV1Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V1,
+ 
+@@ -499,6 +520,7 @@ virCgroupBackend virCgroupV1Backend = {
+     .stealPlacement = virCgroupV1StealPlacement,
+     .detectControllers = virCgroupV1DetectControllers,
+     .hasController = virCgroupV1HasController,
++    .getAnyController = virCgroupV1GetAnyController,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-extract-virCgroupV1GetBlkioIoDeviceServiced.patch b/SOURCES/libvirt-vircgroup-extract-virCgroupV1GetBlkioIoDeviceServiced.patch
new file mode 100644
index 0000000..7617d08
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-extract-virCgroupV1GetBlkioIoDeviceServiced.patch
@@ -0,0 +1,278 @@
+From 0418e750369292b3bb7a855b998344042a87622c Mon Sep 17 00:00:00 2001
+Message-Id: <0418e750369292b3bb7a855b998344042a87622c@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:06:43 +0200
+Subject: [PATCH] vircgroup: extract virCgroupV1GetBlkioIoDeviceServiced
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 44809a28ecfe6f79d18abb55685024128228c7ad)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <faf6e33b119a729cb9afc63f7446ccb5fcecfb04.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c        | 83 ++--------------------------------
+ src/util/vircgroupbackend.h |  9 ++++
+ src/util/vircgrouppriv.h    |  2 +
+ src/util/vircgroupv1.c      | 90 +++++++++++++++++++++++++++++++++++++
+ 4 files changed, 105 insertions(+), 79 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index 8e46777920..fd39144ed2 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -409,7 +409,7 @@ virCgroupDetect(virCgroupPtr group,
+ }
+ 
+ 
+-static char *
++char *
+ virCgroupGetBlockDevString(const char *path)
+ {
+     char *ret = NULL;
+@@ -1337,84 +1337,9 @@ virCgroupGetBlkioIoDeviceServiced(virCgroupPtr group,
+                                   long long *requests_read,
+                                   long long *requests_write)
+ {
+-    VIR_AUTOFREE(char *) str1 = NULL;
+-    VIR_AUTOFREE(char *) str2 = NULL;
+-    VIR_AUTOFREE(char *) str3 = NULL;
+-    char *p1 = NULL;
+-    char *p2 = NULL;
+-    size_t i;
+-
+-    const char *value_names[] = {
+-        "Read ",
+-        "Write "
+-    };
+-    long long *bytes_ptrs[] = {
+-        bytes_read,
+-        bytes_write
+-    };
+-    long long *requests_ptrs[] = {
+-        requests_read,
+-        requests_write
+-    };
+-
+-    if (virCgroupGetValueStr(group,
+-                             VIR_CGROUP_CONTROLLER_BLKIO,
+-                             "blkio.throttle.io_service_bytes", &str1) < 0)
+-        return -1;
+-
+-    if (virCgroupGetValueStr(group,
+-                             VIR_CGROUP_CONTROLLER_BLKIO,
+-                             "blkio.throttle.io_serviced", &str2) < 0)
+-        return -1;
+-
+-    if (!(str3 = virCgroupGetBlockDevString(path)))
+-        return -1;
+-
+-    if (!(p1 = strstr(str1, str3))) {
+-        virReportError(VIR_ERR_INTERNAL_ERROR,
+-                       _("Cannot find byte stats for block device '%s'"),
+-                       str3);
+-        return -1;
+-    }
+-
+-    if (!(p2 = strstr(str2, str3))) {
+-        virReportError(VIR_ERR_INTERNAL_ERROR,
+-                       _("Cannot find request stats for block device '%s'"),
+-                       str3);
+-        return -1;
+-    }
+-
+-    for (i = 0; i < ARRAY_CARDINALITY(value_names); i++) {
+-        if (!(p1 = strstr(p1, value_names[i]))) {
+-            virReportError(VIR_ERR_INTERNAL_ERROR,
+-                           _("Cannot find byte %sstats for block device '%s'"),
+-                           value_names[i], str3);
+-            return -1;
+-        }
+-
+-        if (virStrToLong_ll(p1 + strlen(value_names[i]), &p1, 10, bytes_ptrs[i]) < 0) {
+-            virReportError(VIR_ERR_INTERNAL_ERROR,
+-                           _("Cannot parse %sstat '%s'"),
+-                           value_names[i], p1 + strlen(value_names[i]));
+-            return -1;
+-        }
+-
+-        if (!(p2 = strstr(p2, value_names[i]))) {
+-            virReportError(VIR_ERR_INTERNAL_ERROR,
+-                           _("Cannot find request %sstats for block device '%s'"),
+-                           value_names[i], str3);
+-            return -1;
+-        }
+-
+-        if (virStrToLong_ll(p2 + strlen(value_names[i]), &p2, 10, requests_ptrs[i]) < 0) {
+-            virReportError(VIR_ERR_INTERNAL_ERROR,
+-                           _("Cannot parse %sstat '%s'"),
+-                           value_names[i], p2 + strlen(value_names[i]));
+-            return -1;
+-        }
+-    }
+-
+-    return 0;
++    VIR_CGROUP_BACKEND_CALL(group, getBlkioIoDeviceServiced, -1,
++                            path, bytes_read, bytes_write,
++                            requests_read, requests_write);
+ }
+ 
+ 
+diff --git a/src/util/vircgroupbackend.h b/src/util/vircgroupbackend.h
+index 585a2eb353..e16d631a0f 100644
+--- a/src/util/vircgroupbackend.h
++++ b/src/util/vircgroupbackend.h
+@@ -152,6 +152,14 @@ typedef int
+                                  long long *requests_read,
+                                  long long *requests_write);
+ 
++typedef int
++(*virCgroupGetBlkioIoDeviceServicedCB)(virCgroupPtr group,
++                                       const char *path,
++                                       long long *bytes_read,
++                                       long long *bytes_write,
++                                       long long *requests_read,
++                                       long long *requests_write);
++
+ struct _virCgroupBackend {
+     virCgroupBackendType type;
+ 
+@@ -179,6 +187,7 @@ struct _virCgroupBackend {
+     virCgroupSetBlkioWeightCB setBlkioWeight;
+     virCgroupGetBlkioWeightCB getBlkioWeight;
+     virCgroupGetBlkioIoServicedCB getBlkioIoServiced;
++    virCgroupGetBlkioIoDeviceServicedCB getBlkioIoDeviceServiced;
+ };
+ typedef struct _virCgroupBackend virCgroupBackend;
+ typedef virCgroupBackend *virCgroupBackendPtr;
+diff --git a/src/util/vircgrouppriv.h b/src/util/vircgrouppriv.h
+index 01714370be..525c288a9a 100644
+--- a/src/util/vircgrouppriv.h
++++ b/src/util/vircgrouppriv.h
+@@ -80,6 +80,8 @@ int virCgroupSetValueI64(virCgroupPtr group,
+ 
+ int virCgroupPartitionEscape(char **path);
+ 
++char *virCgroupGetBlockDevString(const char *path);
++
+ int virCgroupNewPartition(const char *path,
+                           bool create,
+                           int controllers,
+diff --git a/src/util/vircgroupv1.c b/src/util/vircgroupv1.c
+index 1afdad4afc..79c4812aef 100644
+--- a/src/util/vircgroupv1.c
++++ b/src/util/vircgroupv1.c
+@@ -1049,6 +1049,95 @@ virCgroupV1GetBlkioIoServiced(virCgroupPtr group,
+ }
+ 
+ 
++static int
++virCgroupV1GetBlkioIoDeviceServiced(virCgroupPtr group,
++                                    const char *path,
++                                    long long *bytes_read,
++                                    long long *bytes_write,
++                                    long long *requests_read,
++                                    long long *requests_write)
++{
++    VIR_AUTOFREE(char *) str1 = NULL;
++    VIR_AUTOFREE(char *) str2 = NULL;
++    VIR_AUTOFREE(char *) str3 = NULL;
++    char *p1 = NULL;
++    char *p2 = NULL;
++    size_t i;
++
++    const char *value_names[] = {
++        "Read ",
++        "Write "
++    };
++    long long *bytes_ptrs[] = {
++        bytes_read,
++        bytes_write
++    };
++    long long *requests_ptrs[] = {
++        requests_read,
++        requests_write
++    };
++
++    if (virCgroupGetValueStr(group,
++                             VIR_CGROUP_CONTROLLER_BLKIO,
++                             "blkio.throttle.io_service_bytes", &str1) < 0)
++        return -1;
++
++    if (virCgroupGetValueStr(group,
++                             VIR_CGROUP_CONTROLLER_BLKIO,
++                             "blkio.throttle.io_serviced", &str2) < 0)
++        return -1;
++
++    if (!(str3 = virCgroupGetBlockDevString(path)))
++        return -1;
++
++    if (!(p1 = strstr(str1, str3))) {
++        virReportError(VIR_ERR_INTERNAL_ERROR,
++                       _("Cannot find byte stats for block device '%s'"),
++                       str3);
++        return -1;
++    }
++
++    if (!(p2 = strstr(str2, str3))) {
++        virReportError(VIR_ERR_INTERNAL_ERROR,
++                       _("Cannot find request stats for block device '%s'"),
++                       str3);
++        return -1;
++    }
++
++    for (i = 0; i < ARRAY_CARDINALITY(value_names); i++) {
++        if (!(p1 = strstr(p1, value_names[i]))) {
++            virReportError(VIR_ERR_INTERNAL_ERROR,
++                           _("Cannot find byte %sstats for block device '%s'"),
++                           value_names[i], str3);
++            return -1;
++        }
++
++        if (virStrToLong_ll(p1 + strlen(value_names[i]), &p1, 10, bytes_ptrs[i]) < 0) {
++            virReportError(VIR_ERR_INTERNAL_ERROR,
++                           _("Cannot parse %sstat '%s'"),
++                           value_names[i], p1 + strlen(value_names[i]));
++            return -1;
++        }
++
++        if (!(p2 = strstr(p2, value_names[i]))) {
++            virReportError(VIR_ERR_INTERNAL_ERROR,
++                           _("Cannot find request %sstats for block device '%s'"),
++                           value_names[i], str3);
++            return -1;
++        }
++
++        if (virStrToLong_ll(p2 + strlen(value_names[i]), &p2, 10, requests_ptrs[i]) < 0) {
++            virReportError(VIR_ERR_INTERNAL_ERROR,
++                           _("Cannot parse %sstat '%s'"),
++                           value_names[i], p2 + strlen(value_names[i]));
++            return -1;
++        }
++    }
++
++    return 0;
++}
++
++
+ virCgroupBackend virCgroupV1Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V1,
+ 
+@@ -1074,6 +1163,7 @@ virCgroupBackend virCgroupV1Backend = {
+     .setBlkioWeight = virCgroupV1SetBlkioWeight,
+     .getBlkioWeight = virCgroupV1GetBlkioWeight,
+     .getBlkioIoServiced = virCgroupV1GetBlkioIoServiced,
++    .getBlkioIoDeviceServiced = virCgroupV1GetBlkioIoDeviceServiced,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-extract-virCgroupV1GetBlkioIoServiced.patch b/SOURCES/libvirt-vircgroup-extract-virCgroupV1GetBlkioIoServiced.patch
new file mode 100644
index 0000000..660292e
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-extract-virCgroupV1GetBlkioIoServiced.patch
@@ -0,0 +1,265 @@
+From 3cb8992be4013fb3ae978c62f6a433080e74130a Mon Sep 17 00:00:00 2001
+Message-Id: <3cb8992be4013fb3ae978c62f6a433080e74130a@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:06:42 +0200
+Subject: [PATCH] vircgroup: extract virCgroupV1GetBlkioIoServiced
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 4baa08ace12d2db7e7023b2abe915360bc7dcddf)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <aa03ae2eef4e9a09d28562f7218c302ec095a912.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c        | 87 ++-------------------------------
+ src/util/vircgroupbackend.h |  8 ++++
+ src/util/vircgroupv1.c      | 95 +++++++++++++++++++++++++++++++++++++
+ 3 files changed, 106 insertions(+), 84 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index d2ffa8aefe..8e46777920 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -1311,90 +1311,9 @@ virCgroupGetBlkioIoServiced(virCgroupPtr group,
+                             long long *requests_read,
+                             long long *requests_write)
+ {
+-    long long stats_val;
+-    VIR_AUTOFREE(char *) str1 = NULL;
+-    VIR_AUTOFREE(char *) str2 = NULL;
+-    char *p1 = NULL;
+-    char *p2 = NULL;
+-    size_t i;
+-
+-    const char *value_names[] = {
+-        "Read ",
+-        "Write "
+-    };
+-    long long *bytes_ptrs[] = {
+-        bytes_read,
+-        bytes_write
+-    };
+-    long long *requests_ptrs[] = {
+-        requests_read,
+-        requests_write
+-    };
+-
+-    *bytes_read = 0;
+-    *bytes_write = 0;
+-    *requests_read = 0;
+-    *requests_write = 0;
+-
+-    if (virCgroupGetValueStr(group,
+-                             VIR_CGROUP_CONTROLLER_BLKIO,
+-                             "blkio.throttle.io_service_bytes", &str1) < 0)
+-        return -1;
+-
+-    if (virCgroupGetValueStr(group,
+-                             VIR_CGROUP_CONTROLLER_BLKIO,
+-                             "blkio.throttle.io_serviced", &str2) < 0)
+-        return -1;
+-
+-    /* sum up all entries of the same kind, from all devices */
+-    for (i = 0; i < ARRAY_CARDINALITY(value_names); i++) {
+-        p1 = str1;
+-        p2 = str2;
+-
+-        while ((p1 = strstr(p1, value_names[i]))) {
+-            p1 += strlen(value_names[i]);
+-            if (virStrToLong_ll(p1, &p1, 10, &stats_val) < 0) {
+-                virReportError(VIR_ERR_INTERNAL_ERROR,
+-                               _("Cannot parse byte %sstat '%s'"),
+-                               value_names[i],
+-                               p1);
+-                return -1;
+-            }
+-
+-            if (stats_val < 0 ||
+-                (stats_val > 0 && *bytes_ptrs[i] > (LLONG_MAX - stats_val)))
+-            {
+-                virReportError(VIR_ERR_OVERFLOW,
+-                               _("Sum of byte %sstat overflows"),
+-                               value_names[i]);
+-                return -1;
+-            }
+-            *bytes_ptrs[i] += stats_val;
+-        }
+-
+-        while ((p2 = strstr(p2, value_names[i]))) {
+-            p2 += strlen(value_names[i]);
+-            if (virStrToLong_ll(p2, &p2, 10, &stats_val) < 0) {
+-                virReportError(VIR_ERR_INTERNAL_ERROR,
+-                               _("Cannot parse %srequest stat '%s'"),
+-                               value_names[i],
+-                               p2);
+-                return -1;
+-            }
+-
+-            if (stats_val < 0 ||
+-                (stats_val > 0 && *requests_ptrs[i] > (LLONG_MAX - stats_val)))
+-            {
+-                virReportError(VIR_ERR_OVERFLOW,
+-                               _("Sum of %srequest stat overflows"),
+-                               value_names[i]);
+-                return -1;
+-            }
+-            *requests_ptrs[i] += stats_val;
+-        }
+-    }
+-
+-    return 0;
++    VIR_CGROUP_BACKEND_CALL(group, getBlkioIoServiced, -1,
++                            bytes_read, bytes_write,
++                            requests_read, requests_write);
+ }
+ 
+ 
+diff --git a/src/util/vircgroupbackend.h b/src/util/vircgroupbackend.h
+index ccce65f1e2..585a2eb353 100644
+--- a/src/util/vircgroupbackend.h
++++ b/src/util/vircgroupbackend.h
+@@ -145,6 +145,13 @@ typedef int
+ (*virCgroupGetBlkioWeightCB)(virCgroupPtr group,
+                              unsigned int *weight);
+ 
++typedef int
++(*virCgroupGetBlkioIoServicedCB)(virCgroupPtr group,
++                                 long long *bytes_read,
++                                 long long *bytes_write,
++                                 long long *requests_read,
++                                 long long *requests_write);
++
+ struct _virCgroupBackend {
+     virCgroupBackendType type;
+ 
+@@ -171,6 +178,7 @@ struct _virCgroupBackend {
+     /* Optional cgroup controller specific callbacks. */
+     virCgroupSetBlkioWeightCB setBlkioWeight;
+     virCgroupGetBlkioWeightCB getBlkioWeight;
++    virCgroupGetBlkioIoServicedCB getBlkioIoServiced;
+ };
+ typedef struct _virCgroupBackend virCgroupBackend;
+ typedef virCgroupBackend *virCgroupBackendPtr;
+diff --git a/src/util/vircgroupv1.c b/src/util/vircgroupv1.c
+index d67b3164ce..1afdad4afc 100644
+--- a/src/util/vircgroupv1.c
++++ b/src/util/vircgroupv1.c
+@@ -955,6 +955,100 @@ virCgroupV1GetBlkioWeight(virCgroupPtr group,
+ }
+ 
+ 
++static int
++virCgroupV1GetBlkioIoServiced(virCgroupPtr group,
++                              long long *bytes_read,
++                              long long *bytes_write,
++                              long long *requests_read,
++                              long long *requests_write)
++{
++    long long stats_val;
++    VIR_AUTOFREE(char *) str1 = NULL;
++    VIR_AUTOFREE(char *) str2 = NULL;
++    char *p1 = NULL;
++    char *p2 = NULL;
++    size_t i;
++
++    const char *value_names[] = {
++        "Read ",
++        "Write "
++    };
++    long long *bytes_ptrs[] = {
++        bytes_read,
++        bytes_write
++    };
++    long long *requests_ptrs[] = {
++        requests_read,
++        requests_write
++    };
++
++    *bytes_read = 0;
++    *bytes_write = 0;
++    *requests_read = 0;
++    *requests_write = 0;
++
++    if (virCgroupGetValueStr(group,
++                             VIR_CGROUP_CONTROLLER_BLKIO,
++                             "blkio.throttle.io_service_bytes", &str1) < 0)
++        return -1;
++
++    if (virCgroupGetValueStr(group,
++                             VIR_CGROUP_CONTROLLER_BLKIO,
++                             "blkio.throttle.io_serviced", &str2) < 0)
++        return -1;
++
++    /* sum up all entries of the same kind, from all devices */
++    for (i = 0; i < ARRAY_CARDINALITY(value_names); i++) {
++        p1 = str1;
++        p2 = str2;
++
++        while ((p1 = strstr(p1, value_names[i]))) {
++            p1 += strlen(value_names[i]);
++            if (virStrToLong_ll(p1, &p1, 10, &stats_val) < 0) {
++                virReportError(VIR_ERR_INTERNAL_ERROR,
++                               _("Cannot parse byte %sstat '%s'"),
++                               value_names[i],
++                               p1);
++                return -1;
++            }
++
++            if (stats_val < 0 ||
++                (stats_val > 0 && *bytes_ptrs[i] > (LLONG_MAX - stats_val)))
++            {
++                virReportError(VIR_ERR_OVERFLOW,
++                               _("Sum of byte %sstat overflows"),
++                               value_names[i]);
++                return -1;
++            }
++            *bytes_ptrs[i] += stats_val;
++        }
++
++        while ((p2 = strstr(p2, value_names[i]))) {
++            p2 += strlen(value_names[i]);
++            if (virStrToLong_ll(p2, &p2, 10, &stats_val) < 0) {
++                virReportError(VIR_ERR_INTERNAL_ERROR,
++                               _("Cannot parse %srequest stat '%s'"),
++                               value_names[i],
++                               p2);
++                return -1;
++            }
++
++            if (stats_val < 0 ||
++                (stats_val > 0 && *requests_ptrs[i] > (LLONG_MAX - stats_val)))
++            {
++                virReportError(VIR_ERR_OVERFLOW,
++                               _("Sum of %srequest stat overflows"),
++                               value_names[i]);
++                return -1;
++            }
++            *requests_ptrs[i] += stats_val;
++        }
++    }
++
++    return 0;
++}
++
++
+ virCgroupBackend virCgroupV1Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V1,
+ 
+@@ -979,6 +1073,7 @@ virCgroupBackend virCgroupV1Backend = {
+ 
+     .setBlkioWeight = virCgroupV1SetBlkioWeight,
+     .getBlkioWeight = virCgroupV1GetBlkioWeight,
++    .getBlkioIoServiced = virCgroupV1GetBlkioIoServiced,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-extract-virCgroupV1GetCpuacct-Usage.patch b/SOURCES/libvirt-vircgroup-extract-virCgroupV1GetCpuacct-Usage.patch
new file mode 100644
index 0000000..ac8db97
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-extract-virCgroupV1GetCpuacct-Usage.patch
@@ -0,0 +1,122 @@
+From 1d91616a1f70531a38695b1634e5538e1699b648 Mon Sep 17 00:00:00 2001
+Message-Id: <1d91616a1f70531a38695b1634e5538e1699b648@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:07:00 +0200
+Subject: [PATCH] vircgroup: extract virCgroupV1GetCpuacct*Usage
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 83704663234b894251eb197638e81b652674103e)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <fa6bba63dd9a7d3ad733b3107a613033e6fa6cd2.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c        |  7 ++-----
+ src/util/vircgroupbackend.h | 11 +++++++++++
+ src/util/vircgroupv1.c      | 22 ++++++++++++++++++++++
+ 3 files changed, 35 insertions(+), 5 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index fa9fa52019..4f791204d3 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -2265,8 +2265,7 @@ virCgroupSetCpuCfsQuota(virCgroupPtr group, long long cfs_quota)
+ int
+ virCgroupGetCpuacctPercpuUsage(virCgroupPtr group, char **usage)
+ {
+-    return virCgroupGetValueStr(group, VIR_CGROUP_CONTROLLER_CPUACCT,
+-                                "cpuacct.usage_percpu", usage);
++    VIR_CGROUP_BACKEND_CALL(group, getCpuacctPercpuUsage, -1, usage);
+ }
+ 
+ 
+@@ -2589,9 +2588,7 @@ virCgroupGetCpuCfsQuota(virCgroupPtr group, long long *cfs_quota)
+ int
+ virCgroupGetCpuacctUsage(virCgroupPtr group, unsigned long long *usage)
+ {
+-    return virCgroupGetValueU64(group,
+-                                VIR_CGROUP_CONTROLLER_CPUACCT,
+-                                "cpuacct.usage", usage);
++    VIR_CGROUP_BACKEND_CALL(group, getCpuacctUsage, -1, usage);
+ }
+ 
+ 
+diff --git a/src/util/vircgroupbackend.h b/src/util/vircgroupbackend.h
+index d3d5e7c222..39a75a69f4 100644
+--- a/src/util/vircgroupbackend.h
++++ b/src/util/vircgroupbackend.h
+@@ -303,6 +303,14 @@ typedef int
+ typedef bool
+ (*virCgroupSupportsCpuBWCB)(virCgroupPtr cgroup);
+ 
++typedef int
++(*virCgroupGetCpuacctUsageCB)(virCgroupPtr group,
++                              unsigned long long *usage);
++
++typedef int
++(*virCgroupGetCpuacctPercpuUsageCB)(virCgroupPtr group,
++                                    char **usage);
++
+ struct _virCgroupBackend {
+     virCgroupBackendType type;
+ 
+@@ -365,6 +373,9 @@ struct _virCgroupBackend {
+     virCgroupSetCpuCfsQuotaCB setCpuCfsQuota;
+     virCgroupGetCpuCfsQuotaCB getCpuCfsQuota;
+     virCgroupSupportsCpuBWCB supportsCpuBW;
++
++    virCgroupGetCpuacctUsageCB getCpuacctUsage;
++    virCgroupGetCpuacctPercpuUsageCB getCpuacctPercpuUsage;
+ };
+ typedef struct _virCgroupBackend virCgroupBackend;
+ typedef virCgroupBackend *virCgroupBackendPtr;
+diff --git a/src/util/vircgroupv1.c b/src/util/vircgroupv1.c
+index f2a8839f6e..9fb0c5cb96 100644
+--- a/src/util/vircgroupv1.c
++++ b/src/util/vircgroupv1.c
+@@ -1864,6 +1864,25 @@ virCgroupV1SupportsCpuBW(virCgroupPtr cgroup)
+ }
+ 
+ 
++static int
++virCgroupV1GetCpuacctUsage(virCgroupPtr group,
++                           unsigned long long *usage)
++{
++    return virCgroupGetValueU64(group,
++                                VIR_CGROUP_CONTROLLER_CPUACCT,
++                                "cpuacct.usage", usage);
++}
++
++
++static int
++virCgroupV1GetCpuacctPercpuUsage(virCgroupPtr group,
++                                 char **usage)
++{
++    return virCgroupGetValueStr(group, VIR_CGROUP_CONTROLLER_CPUACCT,
++                                "cpuacct.usage_percpu", usage);
++}
++
++
+ virCgroupBackend virCgroupV1Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V1,
+ 
+@@ -1924,6 +1943,9 @@ virCgroupBackend virCgroupV1Backend = {
+     .setCpuCfsQuota = virCgroupV1SetCpuCfsQuota,
+     .getCpuCfsQuota = virCgroupV1GetCpuCfsQuota,
+     .supportsCpuBW = virCgroupV1SupportsCpuBW,
++
++    .getCpuacctUsage = virCgroupV1GetCpuacctUsage,
++    .getCpuacctPercpuUsage = virCgroupV1GetCpuacctPercpuUsage,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-extract-virCgroupV1GetCpuacctStat.patch b/SOURCES/libvirt-vircgroup-extract-virCgroupV1GetCpuacctStat.patch
new file mode 100644
index 0000000..7dbc0b4
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-extract-virCgroupV1GetCpuacctStat.patch
@@ -0,0 +1,167 @@
+From 97f3e1cef9707ac7b1e744aef51880d4538e286a Mon Sep 17 00:00:00 2001
+Message-Id: <97f3e1cef9707ac7b1e744aef51880d4538e286a@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:07:01 +0200
+Subject: [PATCH] vircgroup: extract virCgroupV1GetCpuacctStat
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit e294615f9d849ee4923621db2224fce713018458)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <06921474355374c68d49725851f915e9bf44feeb.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c        | 39 +-----------------------------
+ src/util/vircgroupbackend.h |  6 +++++
+ src/util/vircgroupv1.c      | 47 +++++++++++++++++++++++++++++++++++++
+ 3 files changed, 54 insertions(+), 38 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index 4f791204d3..090fe140bb 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -2596,44 +2596,7 @@ int
+ virCgroupGetCpuacctStat(virCgroupPtr group, unsigned long long *user,
+                         unsigned long long *sys)
+ {
+-    VIR_AUTOFREE(char *) str = NULL;
+-    char *p;
+-    static double scale = -1.0;
+-
+-    if (virCgroupGetValueStr(group, VIR_CGROUP_CONTROLLER_CPUACCT,
+-                             "cpuacct.stat", &str) < 0)
+-        return -1;
+-
+-    if (!(p = STRSKIP(str, "user ")) ||
+-        virStrToLong_ull(p, &p, 10, user) < 0) {
+-        virReportError(VIR_ERR_INTERNAL_ERROR,
+-                       _("Cannot parse user stat '%s'"),
+-                       p);
+-        return -1;
+-    }
+-    if (!(p = STRSKIP(p, "\nsystem ")) ||
+-        virStrToLong_ull(p, NULL, 10, sys) < 0) {
+-        virReportError(VIR_ERR_INTERNAL_ERROR,
+-                       _("Cannot parse sys stat '%s'"),
+-                       p);
+-        return -1;
+-    }
+-    /* times reported are in system ticks (generally 100 Hz), but that
+-     * rate can theoretically vary between machines.  Scale things
+-     * into approximate nanoseconds.  */
+-    if (scale < 0) {
+-        long ticks_per_sec = sysconf(_SC_CLK_TCK);
+-        if (ticks_per_sec == -1) {
+-            virReportSystemError(errno, "%s",
+-                                 _("Cannot determine system clock HZ"));
+-            return -1;
+-        }
+-        scale = 1000000000.0 / ticks_per_sec;
+-    }
+-    *user *= scale;
+-    *sys *= scale;
+-
+-    return 0;
++    VIR_CGROUP_BACKEND_CALL(group, getCpuacctStat, -1, user, sys);
+ }
+ 
+ 
+diff --git a/src/util/vircgroupbackend.h b/src/util/vircgroupbackend.h
+index 39a75a69f4..3e3a73777d 100644
+--- a/src/util/vircgroupbackend.h
++++ b/src/util/vircgroupbackend.h
+@@ -311,6 +311,11 @@ typedef int
+ (*virCgroupGetCpuacctPercpuUsageCB)(virCgroupPtr group,
+                                     char **usage);
+ 
++typedef int
++(*virCgroupGetCpuacctStatCB)(virCgroupPtr group,
++                             unsigned long long *user,
++                             unsigned long long *sys);
++
+ struct _virCgroupBackend {
+     virCgroupBackendType type;
+ 
+@@ -376,6 +381,7 @@ struct _virCgroupBackend {
+ 
+     virCgroupGetCpuacctUsageCB getCpuacctUsage;
+     virCgroupGetCpuacctPercpuUsageCB getCpuacctPercpuUsage;
++    virCgroupGetCpuacctStatCB getCpuacctStat;
+ };
+ typedef struct _virCgroupBackend virCgroupBackend;
+ typedef virCgroupBackend *virCgroupBackendPtr;
+diff --git a/src/util/vircgroupv1.c b/src/util/vircgroupv1.c
+index 9fb0c5cb96..23a91adf60 100644
+--- a/src/util/vircgroupv1.c
++++ b/src/util/vircgroupv1.c
+@@ -1883,6 +1883,52 @@ virCgroupV1GetCpuacctPercpuUsage(virCgroupPtr group,
+ }
+ 
+ 
++static int
++virCgroupV1GetCpuacctStat(virCgroupPtr group,
++                          unsigned long long *user,
++                          unsigned long long *sys)
++{
++    VIR_AUTOFREE(char *) str = NULL;
++    char *p;
++    static double scale = -1.0;
++
++    if (virCgroupGetValueStr(group, VIR_CGROUP_CONTROLLER_CPUACCT,
++                             "cpuacct.stat", &str) < 0)
++        return -1;
++
++    if (!(p = STRSKIP(str, "user ")) ||
++        virStrToLong_ull(p, &p, 10, user) < 0) {
++        virReportError(VIR_ERR_INTERNAL_ERROR,
++                       _("Cannot parse user stat '%s'"),
++                       p);
++        return -1;
++    }
++    if (!(p = STRSKIP(p, "\nsystem ")) ||
++        virStrToLong_ull(p, NULL, 10, sys) < 0) {
++        virReportError(VIR_ERR_INTERNAL_ERROR,
++                       _("Cannot parse sys stat '%s'"),
++                       p);
++        return -1;
++    }
++    /* times reported are in system ticks (generally 100 Hz), but that
++     * rate can theoretically vary between machines.  Scale things
++     * into approximate nanoseconds.  */
++    if (scale < 0) {
++        long ticks_per_sec = sysconf(_SC_CLK_TCK);
++        if (ticks_per_sec == -1) {
++            virReportSystemError(errno, "%s",
++                                 _("Cannot determine system clock HZ"));
++            return -1;
++        }
++        scale = 1000000000.0 / ticks_per_sec;
++    }
++    *user *= scale;
++    *sys *= scale;
++
++    return 0;
++}
++
++
+ virCgroupBackend virCgroupV1Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V1,
+ 
+@@ -1946,6 +1992,7 @@ virCgroupBackend virCgroupV1Backend = {
+ 
+     .getCpuacctUsage = virCgroupV1GetCpuacctUsage,
+     .getCpuacctPercpuUsage = virCgroupV1GetCpuacctPercpuUsage,
++    .getCpuacctStat = virCgroupV1GetCpuacctStat,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-extract-virCgroupV1GetMemSwapUsage.patch b/SOURCES/libvirt-vircgroup-extract-virCgroupV1GetMemSwapUsage.patch
new file mode 100644
index 0000000..bf8d146
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-extract-virCgroupV1GetMemSwapUsage.patch
@@ -0,0 +1,105 @@
+From 3e61b08bd5d925b262e3ca84d234670917604fda Mon Sep 17 00:00:00 2001
+Message-Id: <3e61b08bd5d925b262e3ca84d234670917604fda@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:06:53 +0200
+Subject: [PATCH] vircgroup: extract virCgroupV1GetMemSwapUsage
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 87d9fc5b3bfbe217af1a5316af4392540f676657)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <c660f81cdf6e8771917e54c44d362ebb4d2fbdb4.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c        |  9 +--------
+ src/util/vircgroupbackend.h |  5 +++++
+ src/util/vircgroupv1.c      | 16 ++++++++++++++++
+ 3 files changed, 22 insertions(+), 8 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index 6708eef0da..088e97cb3f 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -1697,14 +1697,7 @@ virCgroupGetMemSwapHardLimit(virCgroupPtr group, unsigned long long *kb)
+ int
+ virCgroupGetMemSwapUsage(virCgroupPtr group, unsigned long long *kb)
+ {
+-    long long unsigned int usage_in_bytes;
+-    int ret;
+-    ret = virCgroupGetValueU64(group,
+-                               VIR_CGROUP_CONTROLLER_MEMORY,
+-                               "memory.memsw.usage_in_bytes", &usage_in_bytes);
+-    if (ret == 0)
+-        *kb = usage_in_bytes >> 10;
+-    return ret;
++    VIR_CGROUP_BACKEND_CALL(group, getMemSwapUsage, -1, kb);
+ }
+ 
+ 
+diff --git a/src/util/vircgroupbackend.h b/src/util/vircgroupbackend.h
+index cdbca4b907..27e6b18ea2 100644
+--- a/src/util/vircgroupbackend.h
++++ b/src/util/vircgroupbackend.h
+@@ -251,6 +251,10 @@ typedef int
+ (*virCgroupGetMemSwapHardLimitCB)(virCgroupPtr group,
+                                   unsigned long long *kb);
+ 
++typedef int
++(*virCgroupGetMemSwapUsageCB)(virCgroupPtr group,
++                              unsigned long long *kb);
++
+ struct _virCgroupBackend {
+     virCgroupBackendType type;
+ 
+@@ -299,6 +303,7 @@ struct _virCgroupBackend {
+     virCgroupGetMemorySoftLimitCB getMemorySoftLimit;
+     virCgroupSetMemSwapHardLimitCB setMemSwapHardLimit;
+     virCgroupGetMemSwapHardLimitCB getMemSwapHardLimit;
++    virCgroupGetMemSwapUsageCB getMemSwapUsage;
+ };
+ typedef struct _virCgroupBackend virCgroupBackend;
+ typedef virCgroupBackend *virCgroupBackendPtr;
+diff --git a/src/util/vircgroupv1.c b/src/util/vircgroupv1.c
+index 779288fb97..55b1d3ebd0 100644
+--- a/src/util/vircgroupv1.c
++++ b/src/util/vircgroupv1.c
+@@ -1656,6 +1656,21 @@ virCgroupV1GetMemSwapHardLimit(virCgroupPtr group,
+ }
+ 
+ 
++static int
++virCgroupV1GetMemSwapUsage(virCgroupPtr group,
++                           unsigned long long *kb)
++{
++    long long unsigned int usage_in_bytes;
++    int ret;
++    ret = virCgroupGetValueU64(group,
++                               VIR_CGROUP_CONTROLLER_MEMORY,
++                               "memory.memsw.usage_in_bytes", &usage_in_bytes);
++    if (ret == 0)
++        *kb = usage_in_bytes >> 10;
++    return ret;
++}
++
++
+ virCgroupBackend virCgroupV1Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V1,
+ 
+@@ -1702,6 +1717,7 @@ virCgroupBackend virCgroupV1Backend = {
+     .getMemorySoftLimit = virCgroupV1GetMemorySoftLimit,
+     .setMemSwapHardLimit = virCgroupV1SetMemSwapHardLimit,
+     .getMemSwapHardLimit = virCgroupV1GetMemSwapHardLimit,
++    .getMemSwapUsage = virCgroupV1GetMemSwapUsage,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-extract-virCgroupV1GetMemoryStat.patch b/SOURCES/libvirt-vircgroup-extract-virCgroupV1GetMemoryStat.patch
new file mode 100644
index 0000000..4f408fc
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-extract-virCgroupV1GetMemoryStat.patch
@@ -0,0 +1,228 @@
+From 22e8736edafd1ac369adead17d924bd6b9536817 Mon Sep 17 00:00:00 2001
+Message-Id: <22e8736edafd1ac369adead17d924bd6b9536817@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:06:50 +0200
+Subject: [PATCH] vircgroup: extract virCgroupV1GetMemoryStat
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 64bfbd7ceb328d27becf98e0539d0ab4bcda8163)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <cafcbd973766d6e41a57c23e83b34912fe67e3f5.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c        | 67 ++------------------------------
+ src/util/vircgroupbackend.h | 10 +++++
+ src/util/vircgroupv1.c      | 76 +++++++++++++++++++++++++++++++++++++
+ 3 files changed, 90 insertions(+), 63 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index 4053c65939..786034d555 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -1619,69 +1619,10 @@ virCgroupGetMemoryStat(virCgroupPtr group,
+                        unsigned long long *inactiveFile,
+                        unsigned long long *unevictable)
+ {
+-    int ret = -1;
+-    char *stat = NULL;
+-    char *line = NULL;
+-    unsigned long long cacheVal = 0;
+-    unsigned long long activeAnonVal = 0;
+-    unsigned long long inactiveAnonVal = 0;
+-    unsigned long long activeFileVal = 0;
+-    unsigned long long inactiveFileVal = 0;
+-    unsigned long long unevictableVal = 0;
+-
+-    if (virCgroupGetValueStr(group,
+-                             VIR_CGROUP_CONTROLLER_MEMORY,
+-                             "memory.stat",
+-                             &stat) < 0) {
+-        return -1;
+-    }
+-
+-    line = stat;
+-
+-    while (line) {
+-        char *newLine = strchr(line, '\n');
+-        char *valueStr = strchr(line, ' ');
+-        unsigned long long value;
+-
+-        if (newLine)
+-            *newLine = '\0';
+-
+-        if (!valueStr) {
+-            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+-                           _("Cannot parse 'memory.stat' cgroup file."));
+-            goto cleanup;
+-        }
+-        *valueStr = '\0';
+-
+-        if (virStrToLong_ull(valueStr + 1, NULL, 10, &value) < 0)
+-            goto cleanup;
+-
+-        if (STREQ(line, "cache"))
+-            cacheVal = value >> 10;
+-        else if (STREQ(line, "active_anon"))
+-            activeAnonVal = value >> 10;
+-        else if (STREQ(line, "inactive_anon"))
+-            inactiveAnonVal = value >> 10;
+-        else if (STREQ(line, "active_file"))
+-            activeFileVal = value >> 10;
+-        else if (STREQ(line, "inactive_file"))
+-            inactiveFileVal = value >> 10;
+-        else if (STREQ(line, "unevictable"))
+-            unevictableVal = value >> 10;
+-    }
+-
+-    *cache = cacheVal;
+-    *activeAnon = activeAnonVal;
+-    *inactiveAnon = inactiveAnonVal;
+-    *activeFile = activeFileVal;
+-    *inactiveFile = inactiveFileVal;
+-    *unevictable = unevictableVal;
+-
+-    ret = 0;
+-
+- cleanup:
+-    VIR_FREE(stat);
+-    return ret;
++    VIR_CGROUP_BACKEND_CALL(group, getMemoryStat, -1, cache,
++                            activeAnon, inactiveAnon,
++                            activeFile, inactiveFile,
++                            unevictable);
+ }
+ 
+ 
+diff --git a/src/util/vircgroupbackend.h b/src/util/vircgroupbackend.h
+index e1f75c5c31..99754a6310 100644
+--- a/src/util/vircgroupbackend.h
++++ b/src/util/vircgroupbackend.h
+@@ -214,6 +214,15 @@ typedef int
+ (*virCgroupSetMemoryCB)(virCgroupPtr group,
+                         unsigned long long kb);
+ 
++typedef int
++(*virCgroupGetMemoryStatCB)(virCgroupPtr group,
++                            unsigned long long *cache,
++                            unsigned long long *activeAnon,
++                            unsigned long long *inactiveAnon,
++                            unsigned long long *activeFile,
++                            unsigned long long *inactiveFile,
++                            unsigned long long *unevictable);
++
+ struct _virCgroupBackend {
+     virCgroupBackendType type;
+ 
+@@ -254,6 +263,7 @@ struct _virCgroupBackend {
+     virCgroupGetBlkioDeviceWriteBpsCB getBlkioDeviceWriteBps;
+ 
+     virCgroupSetMemoryCB setMemory;
++    virCgroupGetMemoryStatCB getMemoryStat;
+ };
+ typedef struct _virCgroupBackend virCgroupBackend;
+ typedef virCgroupBackend *virCgroupBackendPtr;
+diff --git a/src/util/vircgroupv1.c b/src/util/vircgroupv1.c
+index 17a4d67972..fcb2607e26 100644
+--- a/src/util/vircgroupv1.c
++++ b/src/util/vircgroupv1.c
+@@ -1404,6 +1404,81 @@ virCgroupV1SetMemory(virCgroupPtr group,
+ }
+ 
+ 
++static int
++virCgroupV1GetMemoryStat(virCgroupPtr group,
++                         unsigned long long *cache,
++                         unsigned long long *activeAnon,
++                         unsigned long long *inactiveAnon,
++                         unsigned long long *activeFile,
++                         unsigned long long *inactiveFile,
++                         unsigned long long *unevictable)
++{
++    int ret = -1;
++    char *stat = NULL;
++    char *line = NULL;
++    unsigned long long cacheVal = 0;
++    unsigned long long activeAnonVal = 0;
++    unsigned long long inactiveAnonVal = 0;
++    unsigned long long activeFileVal = 0;
++    unsigned long long inactiveFileVal = 0;
++    unsigned long long unevictableVal = 0;
++
++    if (virCgroupGetValueStr(group,
++                             VIR_CGROUP_CONTROLLER_MEMORY,
++                             "memory.stat",
++                             &stat) < 0) {
++        return -1;
++    }
++
++    line = stat;
++
++    while (line) {
++        char *newLine = strchr(line, '\n');
++        char *valueStr = strchr(line, ' ');
++        unsigned long long value;
++
++        if (newLine)
++            *newLine = '\0';
++
++        if (!valueStr) {
++            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
++                           _("Cannot parse 'memory.stat' cgroup file."));
++            goto cleanup;
++        }
++        *valueStr = '\0';
++
++        if (virStrToLong_ull(valueStr + 1, NULL, 10, &value) < 0)
++            goto cleanup;
++
++        if (STREQ(line, "cache"))
++            cacheVal = value >> 10;
++        else if (STREQ(line, "active_anon"))
++            activeAnonVal = value >> 10;
++        else if (STREQ(line, "inactive_anon"))
++            inactiveAnonVal = value >> 10;
++        else if (STREQ(line, "active_file"))
++            activeFileVal = value >> 10;
++        else if (STREQ(line, "inactive_file"))
++            inactiveFileVal = value >> 10;
++        else if (STREQ(line, "unevictable"))
++            unevictableVal = value >> 10;
++    }
++
++    *cache = cacheVal;
++    *activeAnon = activeAnonVal;
++    *inactiveAnon = inactiveAnonVal;
++    *activeFile = activeFileVal;
++    *inactiveFile = inactiveFileVal;
++    *unevictable = unevictableVal;
++
++    ret = 0;
++
++ cleanup:
++    VIR_FREE(stat);
++    return ret;
++}
++
++
+ virCgroupBackend virCgroupV1Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V1,
+ 
+@@ -1442,6 +1517,7 @@ virCgroupBackend virCgroupV1Backend = {
+     .getBlkioDeviceWriteBps = virCgroupV1GetBlkioDeviceWriteBps,
+ 
+     .setMemory = virCgroupV1SetMemory,
++    .getMemoryStat = virCgroupV1GetMemoryStat,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-extract-virCgroupV1GetMemoryUsage.patch b/SOURCES/libvirt-vircgroup-extract-virCgroupV1GetMemoryUsage.patch
new file mode 100644
index 0000000..8fc79e2
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-extract-virCgroupV1GetMemoryUsage.patch
@@ -0,0 +1,105 @@
+From fadcb498572cd664d45d31039f2bd34e22cc02b3 Mon Sep 17 00:00:00 2001
+Message-Id: <fadcb498572cd664d45d31039f2bd34e22cc02b3@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:06:51 +0200
+Subject: [PATCH] vircgroup: extract virCgroupV1GetMemoryUsage
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit e92f8bad6681439d50251e7ac13e5f9f1bef62d5)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <aa1a9f774f8757730539caad64376dc6f4be9e70.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c        |  9 +--------
+ src/util/vircgroupbackend.h |  5 +++++
+ src/util/vircgroupv1.c      | 16 ++++++++++++++++
+ 3 files changed, 22 insertions(+), 8 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index 786034d555..ed7252243c 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -1637,14 +1637,7 @@ virCgroupGetMemoryStat(virCgroupPtr group,
+ int
+ virCgroupGetMemoryUsage(virCgroupPtr group, unsigned long *kb)
+ {
+-    long long unsigned int usage_in_bytes;
+-    int ret;
+-    ret = virCgroupGetValueU64(group,
+-                               VIR_CGROUP_CONTROLLER_MEMORY,
+-                               "memory.usage_in_bytes", &usage_in_bytes);
+-    if (ret == 0)
+-        *kb = (unsigned long) usage_in_bytes >> 10;
+-    return ret;
++    VIR_CGROUP_BACKEND_CALL(group, getMemoryUsage, -1, kb);
+ }
+ 
+ 
+diff --git a/src/util/vircgroupbackend.h b/src/util/vircgroupbackend.h
+index 99754a6310..8bdfc5c835 100644
+--- a/src/util/vircgroupbackend.h
++++ b/src/util/vircgroupbackend.h
+@@ -223,6 +223,10 @@ typedef int
+                             unsigned long long *inactiveFile,
+                             unsigned long long *unevictable);
+ 
++typedef int
++(*virCgroupGetMemoryUsageCB)(virCgroupPtr group,
++                             unsigned long *kb);
++
+ struct _virCgroupBackend {
+     virCgroupBackendType type;
+ 
+@@ -264,6 +268,7 @@ struct _virCgroupBackend {
+ 
+     virCgroupSetMemoryCB setMemory;
+     virCgroupGetMemoryStatCB getMemoryStat;
++    virCgroupGetMemoryUsageCB getMemoryUsage;
+ };
+ typedef struct _virCgroupBackend virCgroupBackend;
+ typedef virCgroupBackend *virCgroupBackendPtr;
+diff --git a/src/util/vircgroupv1.c b/src/util/vircgroupv1.c
+index fcb2607e26..4f1d79a758 100644
+--- a/src/util/vircgroupv1.c
++++ b/src/util/vircgroupv1.c
+@@ -1479,6 +1479,21 @@ virCgroupV1GetMemoryStat(virCgroupPtr group,
+ }
+ 
+ 
++static int
++virCgroupV1GetMemoryUsage(virCgroupPtr group,
++                          unsigned long *kb)
++{
++    long long unsigned int usage_in_bytes;
++    int ret;
++    ret = virCgroupGetValueU64(group,
++                               VIR_CGROUP_CONTROLLER_MEMORY,
++                               "memory.usage_in_bytes", &usage_in_bytes);
++    if (ret == 0)
++        *kb = (unsigned long) usage_in_bytes >> 10;
++    return ret;
++}
++
++
+ virCgroupBackend virCgroupV1Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V1,
+ 
+@@ -1518,6 +1533,7 @@ virCgroupBackend virCgroupV1Backend = {
+ 
+     .setMemory = virCgroupV1SetMemory,
+     .getMemoryStat = virCgroupV1GetMemoryStat,
++    .getMemoryUsage = virCgroupV1GetMemoryUsage,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-extract-virCgroupV1HasController.patch b/SOURCES/libvirt-vircgroup-extract-virCgroupV1HasController.patch
new file mode 100644
index 0000000..7865a7d
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-extract-virCgroupV1HasController.patch
@@ -0,0 +1,92 @@
+From 784cb29187b72cd44c528b1435b27ca5f0a36f33 Mon Sep 17 00:00:00 2001
+Message-Id: <784cb29187b72cd44c528b1435b27ca5f0a36f33@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:06:32 +0200
+Subject: [PATCH] vircgroup: extract virCgroupV1HasController
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 5e2df3d07f63128259a9677acdbbbcd983069110)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <e823ddab991e14aa8cb5e9b9d139236eb460b594.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c        | 3 ++-
+ src/util/vircgroupbackend.h | 5 +++++
+ src/util/vircgroupv1.c      | 9 +++++++++
+ 3 files changed, 16 insertions(+), 1 deletion(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index 2e74cbbff4..5bbe42b699 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -1443,7 +1443,8 @@ virCgroupHasController(virCgroupPtr cgroup, int controller)
+         return false;
+     if (controller < 0 || controller >= VIR_CGROUP_CONTROLLER_LAST)
+         return false;
+-    return cgroup->controllers[controller].mountPoint != NULL;
++
++    return cgroup->backend->hasController(cgroup, controller);
+ }
+ 
+ 
+diff --git a/src/util/vircgroupbackend.h b/src/util/vircgroupbackend.h
+index 011d1b00da..29b2fd119f 100644
+--- a/src/util/vircgroupbackend.h
++++ b/src/util/vircgroupbackend.h
+@@ -73,6 +73,10 @@ typedef int
+ (*virCgroupDetectControllersCB)(virCgroupPtr group,
+                                 int controllers);
+ 
++typedef bool
++(*virCgroupHasControllerCB)(virCgroupPtr cgroup,
++                            int controller);
++
+ struct _virCgroupBackend {
+     virCgroupBackendType type;
+ 
+@@ -86,6 +90,7 @@ struct _virCgroupBackend {
+     virCgroupValidatePlacementCB validatePlacement;
+     virCgroupStealPlacementCB stealPlacement;
+     virCgroupDetectControllersCB detectControllers;
++    virCgroupHasControllerCB hasController;
+ };
+ typedef struct _virCgroupBackend virCgroupBackend;
+ typedef virCgroupBackend *virCgroupBackendPtr;
+diff --git a/src/util/vircgroupv1.c b/src/util/vircgroupv1.c
+index 11a86c061a..0638f48d50 100644
+--- a/src/util/vircgroupv1.c
++++ b/src/util/vircgroupv1.c
+@@ -478,6 +478,14 @@ virCgroupV1DetectControllers(virCgroupPtr group,
+ }
+ 
+ 
++static bool
++virCgroupV1HasController(virCgroupPtr group,
++                         int controller)
++{
++    return group->controllers[controller].mountPoint != NULL;
++}
++
++
+ virCgroupBackend virCgroupV1Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V1,
+ 
+@@ -490,6 +498,7 @@ virCgroupBackend virCgroupV1Backend = {
+     .validatePlacement = virCgroupV1ValidatePlacement,
+     .stealPlacement = virCgroupV1StealPlacement,
+     .detectControllers = virCgroupV1DetectControllers,
++    .hasController = virCgroupV1HasController,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-extract-virCgroupV1HasEmptyTasks.patch b/SOURCES/libvirt-vircgroup-extract-virCgroupV1HasEmptyTasks.patch
new file mode 100644
index 0000000..b040247
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-extract-virCgroupV1HasEmptyTasks.patch
@@ -0,0 +1,113 @@
+From 272c540c20234508b31dcb9a7c3b548e2e328656 Mon Sep 17 00:00:00 2001
+Message-Id: <272c540c20234508b31dcb9a7c3b548e2e328656@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:06:38 +0200
+Subject: [PATCH] vircgroup: extract virCgroupV1HasEmptyTasks
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit c4047141a0af36c5d428bfcc1f14d012f8352a11)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <e81675457cc7dd357792080ff07d5e1159b88738.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c        | 13 +------------
+ src/util/vircgroupbackend.h |  5 +++++
+ src/util/vircgroupv1.c      | 20 ++++++++++++++++++++
+ 3 files changed, 26 insertions(+), 12 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index a5076cb554..d4d02d8f5b 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -3465,18 +3465,7 @@ virCgroupSupportsCpuBW(virCgroupPtr cgroup)
+ int
+ virCgroupHasEmptyTasks(virCgroupPtr cgroup, int controller)
+ {
+-    int ret = -1;
+-    VIR_AUTOFREE(char *) content = NULL;
+-
+-    if (!cgroup)
+-        return -1;
+-
+-    ret = virCgroupGetValueStr(cgroup, controller, "tasks", &content);
+-
+-    if (ret == 0 && content[0] == '\0')
+-        ret = 1;
+-
+-    return ret;
++    return cgroup->backend->hasEmptyTasks(cgroup, controller);
+ }
+ 
+ bool
+diff --git a/src/util/vircgroupbackend.h b/src/util/vircgroupbackend.h
+index bff1f8938e..3e0f6d01f4 100644
+--- a/src/util/vircgroupbackend.h
++++ b/src/util/vircgroupbackend.h
+@@ -122,6 +122,10 @@ typedef int
+                       pid_t pid,
+                       unsigned int flags);
+ 
++typedef int
++(*virCgroupHasEmptyTasksCB)(virCgroupPtr cgroup,
++                            int controller);
++
+ struct _virCgroupBackend {
+     virCgroupBackendType type;
+ 
+@@ -141,6 +145,7 @@ struct _virCgroupBackend {
+     virCgroupMakeGroupCB makeGroup;
+     virCgroupRemoveCB remove;
+     virCgroupAddTaskCB addTask;
++    virCgroupHasEmptyTasksCB hasEmptyTasks;
+ };
+ typedef struct _virCgroupBackend virCgroupBackend;
+ typedef virCgroupBackend *virCgroupBackendPtr;
+diff --git a/src/util/vircgroupv1.c b/src/util/vircgroupv1.c
+index fda2c43eef..b057cdfd9e 100644
+--- a/src/util/vircgroupv1.c
++++ b/src/util/vircgroupv1.c
+@@ -736,6 +736,25 @@ virCgroupV1AddTask(virCgroupPtr group,
+ }
+ 
+ 
++static int
++virCgroupV1HasEmptyTasks(virCgroupPtr cgroup,
++                         int controller)
++{
++    int ret = -1;
++    VIR_AUTOFREE(char *) content = NULL;
++
++    if (!cgroup)
++        return -1;
++
++    ret = virCgroupGetValueStr(cgroup, controller, "tasks", &content);
++
++    if (ret == 0 && content[0] == '\0')
++        ret = 1;
++
++    return ret;
++}
++
++
+ virCgroupBackend virCgroupV1Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V1,
+ 
+@@ -754,6 +773,7 @@ virCgroupBackend virCgroupV1Backend = {
+     .makeGroup = virCgroupV1MakeGroup,
+     .remove = virCgroupV1Remove,
+     .addTask = virCgroupV1AddTask,
++    .hasEmptyTasks = virCgroupV1HasEmptyTasks,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-extract-virCgroupV1MakeGroup.patch b/SOURCES/libvirt-vircgroup-extract-virCgroupV1MakeGroup.patch
new file mode 100644
index 0000000..1ddd66d
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-extract-virCgroupV1MakeGroup.patch
@@ -0,0 +1,446 @@
+From d72932998be48ff4eeb1b9d73d6f5d60560be031 Mon Sep 17 00:00:00 2001
+Message-Id: <d72932998be48ff4eeb1b9d73d6f5d60560be031@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:06:35 +0200
+Subject: [PATCH] vircgroup: extract virCgroupV1MakeGroup
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 152c0f0bf52d4f727e09f388fef5c836c3c94db4)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <b90114ff10174e747131ddc3dfeb4fe177d4bf21.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c        | 141 ++----------------------------------
+ src/util/vircgroupbackend.h |  15 ++++
+ src/util/vircgrouppriv.h    |  20 +++++
+ src/util/vircgroupv1.c      | 132 +++++++++++++++++++++++++++++++++
+ 4 files changed, 174 insertions(+), 134 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index 438d9b4e70..8f0ea4de9a 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -80,14 +80,6 @@ VIR_ENUM_IMPL(virCgroupController, VIR_CGROUP_CONTROLLER_LAST,
+               "freezer", "blkio", "net_cls", "perf_event",
+               "name=systemd");
+ 
+-typedef enum {
+-    VIR_CGROUP_NONE = 0, /* create subdir under each cgroup if possible. */
+-    VIR_CGROUP_MEM_HIERACHY = 1 << 0, /* call virCgroupSetMemoryUseHierarchy
+-                                       * before creating subcgroups and
+-                                       * attaching tasks
+-                                       */
+-} virCgroupFlags;
+-
+ 
+ /**
+  * virCgroupGetDevicePermsString:
+@@ -446,7 +438,7 @@ virCgroupGetBlockDevString(const char *path)
+ }
+ 
+ 
+-static int
++int
+ virCgroupSetValueStr(virCgroupPtr group,
+                      int controller,
+                      const char *key,
+@@ -476,7 +468,7 @@ virCgroupSetValueStr(virCgroupPtr group,
+ }
+ 
+ 
+-static int
++int
+ virCgroupGetValueStr(virCgroupPtr group,
+                      int controller,
+                      const char *key,
+@@ -537,7 +529,7 @@ virCgroupGetValueForBlkDev(virCgroupPtr group,
+ }
+ 
+ 
+-static int
++int
+ virCgroupSetValueU64(virCgroupPtr group,
+                      int controller,
+                      const char *key,
+@@ -589,7 +581,7 @@ virCgroupGetValueI64(virCgroupPtr group,
+ }
+ 
+ 
+-static int
++int
+ virCgroupGetValueU64(virCgroupPtr group,
+                      int controller,
+                      const char *key,
+@@ -611,137 +603,18 @@ virCgroupGetValueU64(virCgroupPtr group,
+ }
+ 
+ 
+-static int
+-virCgroupCpuSetInherit(virCgroupPtr parent, virCgroupPtr group)
+-{
+-    size_t i;
+-    const char *inherit_values[] = {
+-        "cpuset.cpus",
+-        "cpuset.mems",
+-        "cpuset.memory_migrate",
+-    };
+-
+-    VIR_DEBUG("Setting up inheritance %s -> %s", parent->path, group->path);
+-    for (i = 0; i < ARRAY_CARDINALITY(inherit_values); i++) {
+-        VIR_AUTOFREE(char *) value = NULL;
+-
+-        if (virCgroupGetValueStr(parent,
+-                                 VIR_CGROUP_CONTROLLER_CPUSET,
+-                                 inherit_values[i],
+-                                 &value) < 0)
+-            return -1;
+-
+-        VIR_DEBUG("Inherit %s = %s", inherit_values[i], value);
+-
+-        if (virCgroupSetValueStr(group,
+-                                 VIR_CGROUP_CONTROLLER_CPUSET,
+-                                 inherit_values[i],
+-                                 value) < 0)
+-            return -1;
+-    }
+-
+-    return 0;
+-}
+-
+-
+-static int
+-virCgroupSetMemoryUseHierarchy(virCgroupPtr group)
+-{
+-    unsigned long long value;
+-    const char *filename = "memory.use_hierarchy";
+-
+-    if (virCgroupGetValueU64(group,
+-                             VIR_CGROUP_CONTROLLER_MEMORY,
+-                             filename, &value) < 0)
+-        return -1;
+-
+-    /* Setting twice causes error, so if already enabled, skip setting */
+-    if (value == 1)
+-        return 0;
+-
+-    VIR_DEBUG("Setting up %s/%s", group->path, filename);
+-    if (virCgroupSetValueU64(group,
+-                             VIR_CGROUP_CONTROLLER_MEMORY,
+-                             filename, 1) < 0)
+-        return -1;
+-
+-    return 0;
+-}
+-
+-
+ static int
+ virCgroupMakeGroup(virCgroupPtr parent,
+                    virCgroupPtr group,
+                    bool create,
+                    unsigned int flags)
+ {
+-    size_t i;
+-
+-    VIR_DEBUG("Make group %s", group->path);
+-    for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
+-        VIR_AUTOFREE(char *) path = NULL;
+-
+-        /* We must never mkdir() in systemd's hierarchy */
+-        if (i == VIR_CGROUP_CONTROLLER_SYSTEMD) {
+-            VIR_DEBUG("Not creating systemd controller group");
+-            continue;
+-        }
+-
+-        /* Skip over controllers that aren't mounted */
+-        if (!group->controllers[i].mountPoint) {
+-            VIR_DEBUG("Skipping unmounted controller %s",
+-                      virCgroupControllerTypeToString(i));
+-            continue;
+-        }
+-
+-        if (virCgroupPathOfController(group, i, "", &path) < 0)
+-            goto error;
+-
+-        VIR_DEBUG("Make controller %s", path);
+-        if (!virFileExists(path)) {
+-            if (!create ||
+-                mkdir(path, 0755) < 0) {
+-                if (errno == EEXIST)
+-                    continue;
+-                /* With a kernel that doesn't support multi-level directory
+-                 * for blkio controller, libvirt will fail and disable all
+-                 * other controllers even though they are available. So
+-                 * treat blkio as unmounted if mkdir fails. */
+-                if (i == VIR_CGROUP_CONTROLLER_BLKIO) {
+-                    VIR_DEBUG("Ignoring mkdir failure with blkio controller. Kernel probably too old");
+-                    VIR_FREE(group->controllers[i].mountPoint);
+-                    continue;
+-                } else {
+-                    virReportSystemError(errno,
+-                                         _("Failed to create controller %s for group"),
+-                                         virCgroupControllerTypeToString(i));
+-                    goto error;
+-                }
+-            }
+-            if (i == VIR_CGROUP_CONTROLLER_CPUSET &&
+-                group->controllers[i].mountPoint != NULL &&
+-                virCgroupCpuSetInherit(parent, group) < 0) {
+-                goto error;
+-            }
+-            /*
+-             * Note that virCgroupSetMemoryUseHierarchy should always be
+-             * called prior to creating subcgroups and attaching tasks.
+-             */
+-            if ((flags & VIR_CGROUP_MEM_HIERACHY) &&
+-                i == VIR_CGROUP_CONTROLLER_MEMORY &&
+-                group->controllers[i].mountPoint != NULL &&
+-                virCgroupSetMemoryUseHierarchy(group) < 0) {
+-                goto error;
+-            }
+-        }
++    if (group->backend->makeGroup(parent, group, create, flags) < 0) {
++        virCgroupRemove(group);
++        return -1;
+     }
+ 
+-    VIR_DEBUG("Done making controllers for group");
+     return 0;
+-
+- error:
+-    virCgroupRemove(group);
+-    return -1;
+ }
+ 
+ 
+diff --git a/src/util/vircgroupbackend.h b/src/util/vircgroupbackend.h
+index 916227ba6a..b2848c2076 100644
+--- a/src/util/vircgroupbackend.h
++++ b/src/util/vircgroupbackend.h
+@@ -27,6 +27,14 @@
+ 
+ # define CGROUP_MAX_VAL 512
+ 
++typedef enum {
++    VIR_CGROUP_NONE = 0, /* create subdir under each cgroup if possible. */
++    VIR_CGROUP_MEM_HIERACHY = 1 << 0, /* call virCgroupSetMemoryUseHierarchy
++                                       * before creating subcgroups and
++                                       * attaching tasks
++                                       */
++} virCgroupBackendFlags;
++
+ typedef enum {
+     VIR_CGROUP_BACKEND_TYPE_V1 = 0,
+     VIR_CGROUP_BACKEND_TYPE_LAST,
+@@ -86,6 +94,12 @@ typedef int
+                                const char *key,
+                                char **path);
+ 
++typedef int
++(*virCgroupMakeGroupCB)(virCgroupPtr parent,
++                        virCgroupPtr group,
++                        bool create,
++                        unsigned int flags);
++
+ struct _virCgroupBackend {
+     virCgroupBackendType type;
+ 
+@@ -102,6 +116,7 @@ struct _virCgroupBackend {
+     virCgroupHasControllerCB hasController;
+     virCgroupGetAnyControllerCB getAnyController;
+     virCgroupPathOfControllerCB pathOfController;
++    virCgroupMakeGroupCB makeGroup;
+ };
+ typedef struct _virCgroupBackend virCgroupBackend;
+ typedef virCgroupBackend *virCgroupBackendPtr;
+diff --git a/src/util/vircgrouppriv.h b/src/util/vircgrouppriv.h
+index e7f4a1f0fc..2e731458d5 100644
+--- a/src/util/vircgrouppriv.h
++++ b/src/util/vircgrouppriv.h
+@@ -53,6 +53,26 @@ struct _virCgroup {
+     virCgroupController controllers[VIR_CGROUP_CONTROLLER_LAST];
+ };
+ 
++int virCgroupSetValueStr(virCgroupPtr group,
++                         int controller,
++                         const char *key,
++                         const char *value);
++
++int virCgroupGetValueStr(virCgroupPtr group,
++                         int controller,
++                         const char *key,
++                         char **value);
++
++int virCgroupSetValueU64(virCgroupPtr group,
++                         int controller,
++                         const char *key,
++                         unsigned long long int value);
++
++int virCgroupGetValueU64(virCgroupPtr group,
++                         int controller,
++                         const char *key,
++                         unsigned long long int *value);
++
+ int virCgroupPartitionEscape(char **path);
+ 
+ int virCgroupNewPartition(const char *path,
+diff --git a/src/util/vircgroupv1.c b/src/util/vircgroupv1.c
+index a6302d71b1..653e848a83 100644
+--- a/src/util/vircgroupv1.c
++++ b/src/util/vircgroupv1.c
+@@ -537,6 +537,137 @@ virCgroupV1PathOfController(virCgroupPtr group,
+ }
+ 
+ 
++static int
++virCgroupV1CpuSetInherit(virCgroupPtr parent,
++                         virCgroupPtr group)
++{
++    size_t i;
++    const char *inherit_values[] = {
++        "cpuset.cpus",
++        "cpuset.mems",
++        "cpuset.memory_migrate",
++    };
++
++    VIR_DEBUG("Setting up inheritance %s -> %s", parent->path, group->path);
++    for (i = 0; i < ARRAY_CARDINALITY(inherit_values); i++) {
++        VIR_AUTOFREE(char *) value = NULL;
++
++        if (virCgroupGetValueStr(parent,
++                                 VIR_CGROUP_CONTROLLER_CPUSET,
++                                 inherit_values[i],
++                                 &value) < 0)
++            return -1;
++
++        VIR_DEBUG("Inherit %s = %s", inherit_values[i], value);
++
++        if (virCgroupSetValueStr(group,
++                                 VIR_CGROUP_CONTROLLER_CPUSET,
++                                 inherit_values[i],
++                                 value) < 0)
++            return -1;
++    }
++
++    return 0;
++}
++
++
++static int
++virCgroupV1SetMemoryUseHierarchy(virCgroupPtr group)
++{
++    unsigned long long value;
++    const char *filename = "memory.use_hierarchy";
++
++    if (virCgroupGetValueU64(group,
++                             VIR_CGROUP_CONTROLLER_MEMORY,
++                             filename, &value) < 0)
++        return -1;
++
++    /* Setting twice causes error, so if already enabled, skip setting */
++    if (value == 1)
++        return 0;
++
++    VIR_DEBUG("Setting up %s/%s", group->path, filename);
++    if (virCgroupSetValueU64(group,
++                             VIR_CGROUP_CONTROLLER_MEMORY,
++                             filename, 1) < 0)
++        return -1;
++
++    return 0;
++}
++
++
++static int
++virCgroupV1MakeGroup(virCgroupPtr parent,
++                     virCgroupPtr group,
++                     bool create,
++                     unsigned int flags)
++{
++    size_t i;
++
++    VIR_DEBUG("Make group %s", group->path);
++    for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
++        VIR_AUTOFREE(char *) path = NULL;
++
++        /* We must never mkdir() in systemd's hierarchy */
++        if (i == VIR_CGROUP_CONTROLLER_SYSTEMD) {
++            VIR_DEBUG("Not creating systemd controller group");
++            continue;
++        }
++
++        /* Skip over controllers that aren't mounted */
++        if (!group->controllers[i].mountPoint) {
++            VIR_DEBUG("Skipping unmounted controller %s",
++                      virCgroupV1ControllerTypeToString(i));
++            continue;
++        }
++
++        if (virCgroupV1PathOfController(group, i, "", &path) < 0)
++            return -1;
++
++        VIR_DEBUG("Make controller %s", path);
++        if (!virFileExists(path)) {
++            if (!create ||
++                mkdir(path, 0755) < 0) {
++                if (errno == EEXIST)
++                    continue;
++                /* With a kernel that doesn't support multi-level directory
++                 * for blkio controller, libvirt will fail and disable all
++                 * other controllers even though they are available. So
++                 * treat blkio as unmounted if mkdir fails. */
++                if (i == VIR_CGROUP_CONTROLLER_BLKIO) {
++                    VIR_DEBUG("Ignoring mkdir failure with blkio controller. Kernel probably too old");
++                    VIR_FREE(group->controllers[i].mountPoint);
++                    continue;
++                } else {
++                    virReportSystemError(errno,
++                                         _("Failed to create v1 controller %s for group"),
++                                         virCgroupV1ControllerTypeToString(i));
++                    return -1;
++                }
++            }
++            if (i == VIR_CGROUP_CONTROLLER_CPUSET &&
++                group->controllers[i].mountPoint != NULL &&
++                virCgroupV1CpuSetInherit(parent, group) < 0) {
++                return -1;
++            }
++            /*
++             * Note that virCgroupV1SetMemoryUseHierarchy should always be
++             * called prior to creating subcgroups and attaching tasks.
++             */
++            if ((flags & VIR_CGROUP_MEM_HIERACHY) &&
++                i == VIR_CGROUP_CONTROLLER_MEMORY &&
++                group->controllers[i].mountPoint != NULL &&
++                virCgroupV1SetMemoryUseHierarchy(group) < 0) {
++                return -1;
++            }
++        }
++    }
++
++    VIR_DEBUG("Done making controllers for group");
++    return 0;
++}
++
++
+ virCgroupBackend virCgroupV1Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V1,
+ 
+@@ -552,6 +683,7 @@ virCgroupBackend virCgroupV1Backend = {
+     .hasController = virCgroupV1HasController,
+     .getAnyController = virCgroupV1GetAnyController,
+     .pathOfController = virCgroupV1PathOfController,
++    .makeGroup = virCgroupV1MakeGroup,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-extract-virCgroupV1PathOfController.patch b/SOURCES/libvirt-vircgroup-extract-virCgroupV1PathOfController.patch
new file mode 100644
index 0000000..d0dc80a
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-extract-virCgroupV1PathOfController.patch
@@ -0,0 +1,135 @@
+From 66611194a3195560a9aea899b9da724154a03609 Mon Sep 17 00:00:00 2001
+Message-Id: <66611194a3195560a9aea899b9da724154a03609@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:06:34 +0200
+Subject: [PATCH] vircgroup: extract virCgroupV1PathOfController
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 57890b2ab49b27ca9dc8a3922fe61e586aca8f77)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <0867ff8a5f46a8909e621bfb730942cfac3b2cdb.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c        | 22 +---------------------
+ src/util/vircgroupbackend.h |  7 +++++++
+ src/util/vircgroupv1.c      | 31 +++++++++++++++++++++++++++++++
+ 3 files changed, 39 insertions(+), 21 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index a6f529accd..438d9b4e70 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -1460,27 +1460,7 @@ virCgroupPathOfController(virCgroupPtr group,
+         return -1;
+     }
+ 
+-    if (group->controllers[controller].mountPoint == NULL) {
+-        virReportError(VIR_ERR_INTERNAL_ERROR,
+-                       _("Controller '%s' is not mounted"),
+-                       virCgroupControllerTypeToString(controller));
+-        return -1;
+-    }
+-
+-    if (group->controllers[controller].placement == NULL) {
+-        virReportError(VIR_ERR_INTERNAL_ERROR,
+-                       _("Controller '%s' is not enabled for group"),
+-                       virCgroupControllerTypeToString(controller));
+-        return -1;
+-    }
+-
+-    if (virAsprintf(path, "%s%s/%s",
+-                    group->controllers[controller].mountPoint,
+-                    group->controllers[controller].placement,
+-                    key ? key : "") < 0)
+-        return -1;
+-
+-    return 0;
++    return group->backend->pathOfController(group, controller, key, path);
+ }
+ 
+ 
+diff --git a/src/util/vircgroupbackend.h b/src/util/vircgroupbackend.h
+index b4eaa89021..916227ba6a 100644
+--- a/src/util/vircgroupbackend.h
++++ b/src/util/vircgroupbackend.h
+@@ -80,6 +80,12 @@ typedef bool
+ typedef int
+ (*virCgroupGetAnyControllerCB)(virCgroupPtr group);
+ 
++typedef int
++(*virCgroupPathOfControllerCB)(virCgroupPtr group,
++                               int controller,
++                               const char *key,
++                               char **path);
++
+ struct _virCgroupBackend {
+     virCgroupBackendType type;
+ 
+@@ -95,6 +101,7 @@ struct _virCgroupBackend {
+     virCgroupDetectControllersCB detectControllers;
+     virCgroupHasControllerCB hasController;
+     virCgroupGetAnyControllerCB getAnyController;
++    virCgroupPathOfControllerCB pathOfController;
+ };
+ typedef struct _virCgroupBackend virCgroupBackend;
+ typedef virCgroupBackend *virCgroupBackendPtr;
+diff --git a/src/util/vircgroupv1.c b/src/util/vircgroupv1.c
+index bae16b8294..a6302d71b1 100644
+--- a/src/util/vircgroupv1.c
++++ b/src/util/vircgroupv1.c
+@@ -507,6 +507,36 @@ virCgroupV1GetAnyController(virCgroupPtr group)
+ }
+ 
+ 
++static int
++virCgroupV1PathOfController(virCgroupPtr group,
++                            int controller,
++                            const char *key,
++                            char **path)
++{
++    if (group->controllers[controller].mountPoint == NULL) {
++        virReportError(VIR_ERR_INTERNAL_ERROR,
++                       _("v1 controller '%s' is not mounted"),
++                       virCgroupV1ControllerTypeToString(controller));
++        return -1;
++    }
++
++    if (group->controllers[controller].placement == NULL) {
++        virReportError(VIR_ERR_INTERNAL_ERROR,
++                       _("v1 controller '%s' is not enabled for group"),
++                       virCgroupV1ControllerTypeToString(controller));
++        return -1;
++    }
++
++    if (virAsprintf(path, "%s%s/%s",
++                    group->controllers[controller].mountPoint,
++                    group->controllers[controller].placement,
++                    key ? key : "") < 0)
++        return -1;
++
++    return 0;
++}
++
++
+ virCgroupBackend virCgroupV1Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V1,
+ 
+@@ -521,6 +551,7 @@ virCgroupBackend virCgroupV1Backend = {
+     .detectControllers = virCgroupV1DetectControllers,
+     .hasController = virCgroupV1HasController,
+     .getAnyController = virCgroupV1GetAnyController,
++    .pathOfController = virCgroupV1PathOfController,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-extract-virCgroupV1Remove.patch b/SOURCES/libvirt-vircgroup-extract-virCgroupV1Remove.patch
new file mode 100644
index 0000000..6dfd27d
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-extract-virCgroupV1Remove.patch
@@ -0,0 +1,172 @@
+From 251261233d1dcfe086230f6b079c8b3b6518d60f Mon Sep 17 00:00:00 2001
+Message-Id: <251261233d1dcfe086230f6b079c8b3b6518d60f@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:06:36 +0200
+Subject: [PATCH] vircgroup: extract virCgroupV1Remove
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit b148d080495a989db6960ad4ac7e83e576957dfe)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <bf11de0f39d11e0c9122461848a50024b4096553.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c        | 35 ++-------------------------------
+ src/util/vircgroupbackend.h |  4 ++++
+ src/util/vircgrouppriv.h    |  2 ++
+ src/util/vircgroupv1.c      | 39 +++++++++++++++++++++++++++++++++++++
+ 4 files changed, 47 insertions(+), 33 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index 8f0ea4de9a..33d34d6eda 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -2923,7 +2923,7 @@ virCgroupGetCpuacctPercpuUsage(virCgroupPtr group, char **usage)
+ }
+ 
+ 
+-static int
++int
+ virCgroupRemoveRecursively(char *grppath)
+ {
+     DIR *grpdir;
+@@ -2986,38 +2986,7 @@ virCgroupRemoveRecursively(char *grppath)
+ int
+ virCgroupRemove(virCgroupPtr group)
+ {
+-    int rc = 0;
+-    size_t i;
+-
+-    VIR_DEBUG("Removing cgroup %s", group->path);
+-    for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
+-        VIR_AUTOFREE(char *) grppath = NULL;
+-
+-        /* Skip over controllers not mounted */
+-        if (!group->controllers[i].mountPoint)
+-            continue;
+-
+-        /* We must never rmdir() in systemd's hierarchy */
+-        if (i == VIR_CGROUP_CONTROLLER_SYSTEMD)
+-            continue;
+-
+-        /* Don't delete the root group, if we accidentally
+-           ended up in it for some reason */
+-        if (STREQ(group->controllers[i].placement, "/"))
+-            continue;
+-
+-        if (virCgroupPathOfController(group,
+-                                      i,
+-                                      NULL,
+-                                      &grppath) != 0)
+-            continue;
+-
+-        VIR_DEBUG("Removing cgroup %s and all child cgroups", grppath);
+-        rc = virCgroupRemoveRecursively(grppath);
+-    }
+-    VIR_DEBUG("Done removing cgroup %s", group->path);
+-
+-    return rc;
++    return group->backend->remove(group);
+ }
+ 
+ 
+diff --git a/src/util/vircgroupbackend.h b/src/util/vircgroupbackend.h
+index b2848c2076..1f28c51c49 100644
+--- a/src/util/vircgroupbackend.h
++++ b/src/util/vircgroupbackend.h
+@@ -100,6 +100,9 @@ typedef int
+                         bool create,
+                         unsigned int flags);
+ 
++typedef int
++(*virCgroupRemoveCB)(virCgroupPtr group);
++
+ struct _virCgroupBackend {
+     virCgroupBackendType type;
+ 
+@@ -117,6 +120,7 @@ struct _virCgroupBackend {
+     virCgroupGetAnyControllerCB getAnyController;
+     virCgroupPathOfControllerCB pathOfController;
+     virCgroupMakeGroupCB makeGroup;
++    virCgroupRemoveCB remove;
+ };
+ typedef struct _virCgroupBackend virCgroupBackend;
+ typedef virCgroupBackend *virCgroupBackendPtr;
+diff --git a/src/util/vircgrouppriv.h b/src/util/vircgrouppriv.h
+index 2e731458d5..a760b9bcfd 100644
+--- a/src/util/vircgrouppriv.h
++++ b/src/util/vircgrouppriv.h
+@@ -88,4 +88,6 @@ int virCgroupNewDomainPartition(virCgroupPtr partition,
+                                 virCgroupPtr *group)
+     ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(5);
+ 
++int virCgroupRemoveRecursively(char *grppath);
++
+ #endif /* __VIR_CGROUP_PRIV_H__ */
+diff --git a/src/util/vircgroupv1.c b/src/util/vircgroupv1.c
+index 653e848a83..4d4b51094a 100644
+--- a/src/util/vircgroupv1.c
++++ b/src/util/vircgroupv1.c
+@@ -668,6 +668,44 @@ virCgroupV1MakeGroup(virCgroupPtr parent,
+ }
+ 
+ 
++static int
++virCgroupV1Remove(virCgroupPtr group)
++{
++    int rc = 0;
++    size_t i;
++
++    VIR_DEBUG("Removing cgroup %s", group->path);
++    for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
++        VIR_AUTOFREE(char *) grppath = NULL;
++
++        /* Skip over controllers not mounted */
++        if (!group->controllers[i].mountPoint)
++            continue;
++
++        /* We must never rmdir() in systemd's hierarchy */
++        if (i == VIR_CGROUP_CONTROLLER_SYSTEMD)
++            continue;
++
++        /* Don't delete the root group, if we accidentally
++           ended up in it for some reason */
++        if (STREQ(group->controllers[i].placement, "/"))
++            continue;
++
++        if (virCgroupV1PathOfController(group,
++                                        i,
++                                        NULL,
++                                        &grppath) != 0)
++            continue;
++
++        VIR_DEBUG("Removing cgroup %s and all child cgroups", grppath);
++        rc = virCgroupRemoveRecursively(grppath);
++    }
++    VIR_DEBUG("Done removing cgroup %s", group->path);
++
++    return rc;
++}
++
++
+ virCgroupBackend virCgroupV1Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V1,
+ 
+@@ -684,6 +722,7 @@ virCgroupBackend virCgroupV1Backend = {
+     .getAnyController = virCgroupV1GetAnyController,
+     .pathOfController = virCgroupV1PathOfController,
+     .makeGroup = virCgroupV1MakeGroup,
++    .remove = virCgroupV1Remove,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-extract-virCgroupV1SetMemory.patch b/SOURCES/libvirt-vircgroup-extract-virCgroupV1SetMemory.patch
new file mode 100644
index 0000000..975964c
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-extract-virCgroupV1SetMemory.patch
@@ -0,0 +1,129 @@
+From 75e53d9323c069ece39b40a99675425967ac2d62 Mon Sep 17 00:00:00 2001
+Message-Id: <75e53d9323c069ece39b40a99675425967ac2d62@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:06:49 +0200
+Subject: [PATCH] vircgroup: extract virCgroupV1SetMemory
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 53f43deb0dfa666cb8c614cabbf5add075ccc33f)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <d24181f343e9a9ca60165d1f936cc9ec9c0616ec.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c        | 20 +-------------------
+ src/util/vircgroupbackend.h |  6 ++++++
+ src/util/vircgroupv1.c      | 28 ++++++++++++++++++++++++++++
+ 3 files changed, 35 insertions(+), 19 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index 684bce4997..4053c65939 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -1593,25 +1593,7 @@ virCgroupGetMemoryUnlimitedKB(void)
+ int
+ virCgroupSetMemory(virCgroupPtr group, unsigned long long kb)
+ {
+-    unsigned long long maxkb = VIR_DOMAIN_MEMORY_PARAM_UNLIMITED;
+-
+-    if (kb > maxkb) {
+-        virReportError(VIR_ERR_INVALID_ARG,
+-                       _("Memory '%llu' must be less than %llu"),
+-                       kb, maxkb);
+-        return -1;
+-    }
+-
+-    if (kb == maxkb)
+-        return virCgroupSetValueI64(group,
+-                                    VIR_CGROUP_CONTROLLER_MEMORY,
+-                                    "memory.limit_in_bytes",
+-                                    -1);
+-    else
+-        return virCgroupSetValueU64(group,
+-                                    VIR_CGROUP_CONTROLLER_MEMORY,
+-                                    "memory.limit_in_bytes",
+-                                    kb << 10);
++    VIR_CGROUP_BACKEND_CALL(group, setMemory, -1, kb);
+ }
+ 
+ 
+diff --git a/src/util/vircgroupbackend.h b/src/util/vircgroupbackend.h
+index 67e795a2b7..e1f75c5c31 100644
+--- a/src/util/vircgroupbackend.h
++++ b/src/util/vircgroupbackend.h
+@@ -210,6 +210,10 @@ typedef int
+                                      const char *path,
+                                      unsigned long long *wbps);
+ 
++typedef int
++(*virCgroupSetMemoryCB)(virCgroupPtr group,
++                        unsigned long long kb);
++
+ struct _virCgroupBackend {
+     virCgroupBackendType type;
+ 
+@@ -248,6 +252,8 @@ struct _virCgroupBackend {
+     virCgroupGetBlkioDeviceReadBpsCB getBlkioDeviceReadBps;
+     virCgroupSetBlkioDeviceWriteBpsCB setBlkioDeviceWriteBps;
+     virCgroupGetBlkioDeviceWriteBpsCB getBlkioDeviceWriteBps;
++
++    virCgroupSetMemoryCB setMemory;
+ };
+ typedef struct _virCgroupBackend virCgroupBackend;
+ typedef virCgroupBackend *virCgroupBackendPtr;
+diff --git a/src/util/vircgroupv1.c b/src/util/vircgroupv1.c
+index c044414dfd..17a4d67972 100644
+--- a/src/util/vircgroupv1.c
++++ b/src/util/vircgroupv1.c
+@@ -1378,6 +1378,32 @@ virCgroupV1GetBlkioDeviceWriteBps(virCgroupPtr group,
+ }
+ 
+ 
++static int
++virCgroupV1SetMemory(virCgroupPtr group,
++                     unsigned long long kb)
++{
++    unsigned long long maxkb = VIR_DOMAIN_MEMORY_PARAM_UNLIMITED;
++
++    if (kb > maxkb) {
++        virReportError(VIR_ERR_INVALID_ARG,
++                       _("Memory '%llu' must be less than %llu"),
++                       kb, maxkb);
++        return -1;
++    }
++
++    if (kb == maxkb)
++        return virCgroupSetValueI64(group,
++                                    VIR_CGROUP_CONTROLLER_MEMORY,
++                                    "memory.limit_in_bytes",
++                                    -1);
++    else
++        return virCgroupSetValueU64(group,
++                                    VIR_CGROUP_CONTROLLER_MEMORY,
++                                    "memory.limit_in_bytes",
++                                    kb << 10);
++}
++
++
+ virCgroupBackend virCgroupV1Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V1,
+ 
+@@ -1414,6 +1440,8 @@ virCgroupBackend virCgroupV1Backend = {
+     .getBlkioDeviceReadBps = virCgroupV1GetBlkioDeviceReadBps,
+     .setBlkioDeviceWriteBps = virCgroupV1SetBlkioDeviceWriteBps,
+     .getBlkioDeviceWriteBps = virCgroupV1GetBlkioDeviceWriteBps,
++
++    .setMemory = virCgroupV1SetMemory,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-extract-virCgroupV1SetOwner.patch b/SOURCES/libvirt-vircgroup-extract-virCgroupV1SetOwner.patch
new file mode 100644
index 0000000..975b387
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-extract-virCgroupV1SetOwner.patch
@@ -0,0 +1,198 @@
+From 955ac573d3291bfb069664e2df9f4edb0ed09313 Mon Sep 17 00:00:00 2001
+Message-Id: <955ac573d3291bfb069664e2df9f4edb0ed09313@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:06:40 +0200
+Subject: [PATCH] vircgroup: extract virCgroupV1SetOwner
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit dad061101d34a8e4b76ec3c03253ed3e83b50b2a)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <644b2434def24cbb7834a7950595c110d5438166.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c        | 54 +------------------------------
+ src/util/vircgroupbackend.h |  7 +++++
+ src/util/vircgroupv1.c      | 63 +++++++++++++++++++++++++++++++++++++
+ 3 files changed, 71 insertions(+), 53 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index 7789966472..e57aecb08a 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -3282,59 +3282,7 @@ int virCgroupSetOwner(virCgroupPtr cgroup,
+                       gid_t gid,
+                       int controllers)
+ {
+-    int ret = -1;
+-    size_t i;
+-    DIR *dh = NULL;
+-    int direrr;
+-
+-    for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
+-        VIR_AUTOFREE(char *) base = NULL;
+-        struct dirent *de;
+-
+-        if (!((1 << i) & controllers))
+-            continue;
+-
+-        if (!cgroup->controllers[i].mountPoint)
+-            continue;
+-
+-        if (virAsprintf(&base, "%s%s", cgroup->controllers[i].mountPoint,
+-                        cgroup->controllers[i].placement) < 0)
+-            goto cleanup;
+-
+-        if (virDirOpen(&dh, base) < 0)
+-            goto cleanup;
+-
+-        while ((direrr = virDirRead(dh, &de, base)) > 0) {
+-            VIR_AUTOFREE(char *) entry = NULL;
+-
+-            if (virAsprintf(&entry, "%s/%s", base, de->d_name) < 0)
+-                goto cleanup;
+-
+-            if (chown(entry, uid, gid) < 0) {
+-                virReportSystemError(errno,
+-                                     _("cannot chown '%s' to (%u, %u)"),
+-                                     entry, uid, gid);
+-                goto cleanup;
+-            }
+-        }
+-        if (direrr < 0)
+-            goto cleanup;
+-
+-        if (chown(base, uid, gid) < 0) {
+-            virReportSystemError(errno,
+-                                 _("cannot chown '%s' to (%u, %u)"),
+-                                 base, uid, gid);
+-            goto cleanup;
+-        }
+-
+-        VIR_DIR_CLOSE(dh);
+-    }
+-
+-    ret = 0;
+-
+- cleanup:
+-    VIR_DIR_CLOSE(dh);
+-    return ret;
++    return cgroup->backend->setOwner(cgroup, uid, gid, controllers);
+ }
+ 
+ 
+diff --git a/src/util/vircgroupbackend.h b/src/util/vircgroupbackend.h
+index caeec3de60..74af796c2f 100644
+--- a/src/util/vircgroupbackend.h
++++ b/src/util/vircgroupbackend.h
+@@ -131,6 +131,12 @@ typedef int
+                         const char *oldroot,
+                         const char *mountopts);
+ 
++typedef int
++(*virCgroupSetOwnerCB)(virCgroupPtr cgroup,
++                       uid_t uid,
++                       gid_t gid,
++                       int controllers);
++
+ struct _virCgroupBackend {
+     virCgroupBackendType type;
+ 
+@@ -152,6 +158,7 @@ struct _virCgroupBackend {
+     virCgroupAddTaskCB addTask;
+     virCgroupHasEmptyTasksCB hasEmptyTasks;
+     virCgroupBindMountCB bindMount;
++    virCgroupSetOwnerCB setOwner;
+ };
+ typedef struct _virCgroupBackend virCgroupBackend;
+ typedef virCgroupBackend *virCgroupBackendPtr;
+diff --git a/src/util/vircgroupv1.c b/src/util/vircgroupv1.c
+index d63525dfb0..c1e2583912 100644
+--- a/src/util/vircgroupv1.c
++++ b/src/util/vircgroupv1.c
+@@ -867,6 +867,68 @@ virCgroupV1BindMount(virCgroupPtr group,
+ }
+ 
+ 
++static int
++virCgroupV1SetOwner(virCgroupPtr cgroup,
++                    uid_t uid,
++                    gid_t gid,
++                    int controllers)
++{
++    int ret = -1;
++    size_t i;
++    DIR *dh = NULL;
++    int direrr;
++
++    for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
++        VIR_AUTOFREE(char *) base = NULL;
++        struct dirent *de;
++
++        if (!((1 << i) & controllers))
++            continue;
++
++        if (!cgroup->controllers[i].mountPoint)
++            continue;
++
++        if (virAsprintf(&base, "%s%s", cgroup->controllers[i].mountPoint,
++                        cgroup->controllers[i].placement) < 0)
++            goto cleanup;
++
++        if (virDirOpen(&dh, base) < 0)
++            goto cleanup;
++
++        while ((direrr = virDirRead(dh, &de, base)) > 0) {
++            VIR_AUTOFREE(char *) entry = NULL;
++
++            if (virAsprintf(&entry, "%s/%s", base, de->d_name) < 0)
++                goto cleanup;
++
++            if (chown(entry, uid, gid) < 0) {
++                virReportSystemError(errno,
++                                     _("cannot chown '%s' to (%u, %u)"),
++                                     entry, uid, gid);
++                goto cleanup;
++            }
++        }
++        if (direrr < 0)
++            goto cleanup;
++
++        if (chown(base, uid, gid) < 0) {
++            virReportSystemError(errno,
++                                 _("cannot chown '%s' to (%u, %u)"),
++                                 base, uid, gid);
++            goto cleanup;
++        }
++
++        VIR_DIR_CLOSE(dh);
++    }
++
++    ret = 0;
++
++ cleanup:
++    VIR_DIR_CLOSE(dh);
++    return ret;
++}
++
++
+ virCgroupBackend virCgroupV1Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V1,
+ 
+@@ -887,6 +949,7 @@ virCgroupBackend virCgroupV1Backend = {
+     .addTask = virCgroupV1AddTask,
+     .hasEmptyTasks = virCgroupV1HasEmptyTasks,
+     .bindMount = virCgroupV1BindMount,
++    .setOwner = virCgroupV1SetOwner,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-extract-virCgroupV1StealPlacement.patch b/SOURCES/libvirt-vircgroup-extract-virCgroupV1StealPlacement.patch
new file mode 100644
index 0000000..11e2ff4
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-extract-virCgroupV1StealPlacement.patch
@@ -0,0 +1,94 @@
+From 6f37c631f12c0e9b7e9fe8ade5b5a98392090cfb Mon Sep 17 00:00:00 2001
+Message-Id: <6f37c631f12c0e9b7e9fe8ade5b5a98392090cfb@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:06:30 +0200
+Subject: [PATCH] vircgroup: extract virCgroupV1StealPlacement
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 12264c12c819259edeb3e5adb59281906b673ca7)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <5f083ec4400455a10608945377f943a071e36c43.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c        |  3 +--
+ src/util/vircgroupbackend.h |  4 ++++
+ src/util/vircgroupv1.c      | 12 ++++++++++++
+ 3 files changed, 17 insertions(+), 2 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index b17a1dcbb7..0e64ad67f4 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -1323,8 +1323,7 @@ virCgroupNewMachineSystemd(const char *name,
+                            &init) < 0)
+         return -1;
+ 
+-    path = init->controllers[VIR_CGROUP_CONTROLLER_SYSTEMD].placement;
+-    init->controllers[VIR_CGROUP_CONTROLLER_SYSTEMD].placement = NULL;
++    path = init->backend->stealPlacement(init);
+     virCgroupFree(&init);
+ 
+     if (!path || STREQ(path, "/") || path[0] != '/') {
+diff --git a/src/util/vircgroupbackend.h b/src/util/vircgroupbackend.h
+index 086cfb8090..9c0bd89793 100644
+--- a/src/util/vircgroupbackend.h
++++ b/src/util/vircgroupbackend.h
+@@ -66,6 +66,9 @@ typedef int
+ (*virCgroupValidatePlacementCB)(virCgroupPtr group,
+                                 pid_t pid);
+ 
++typedef char *
++(*virCgroupStealPlacementCB)(virCgroupPtr group);
++
+ struct _virCgroupBackend {
+     virCgroupBackendType type;
+ 
+@@ -77,6 +80,7 @@ struct _virCgroupBackend {
+     virCgroupDetectMountsCB detectMounts;
+     virCgroupDetectPlacementCB detectPlacement;
+     virCgroupValidatePlacementCB validatePlacement;
++    virCgroupStealPlacementCB stealPlacement;
+ };
+ typedef struct _virCgroupBackend virCgroupBackend;
+ typedef virCgroupBackend *virCgroupBackendPtr;
+diff --git a/src/util/vircgroupv1.c b/src/util/vircgroupv1.c
+index 2c905a832a..446546fd58 100644
+--- a/src/util/vircgroupv1.c
++++ b/src/util/vircgroupv1.c
+@@ -403,6 +403,17 @@ virCgroupV1ValidatePlacement(virCgroupPtr group,
+ }
+ 
+ 
++static char *
++virCgroupV1StealPlacement(virCgroupPtr group)
++{
++    char *ret = NULL;
++
++    VIR_STEAL_PTR(ret, group->controllers[VIR_CGROUP_CONTROLLER_SYSTEMD].placement);
++
++    return ret;
++}
++
++
+ virCgroupBackend virCgroupV1Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V1,
+ 
+@@ -413,6 +424,7 @@ virCgroupBackend virCgroupV1Backend = {
+     .detectMounts = virCgroupV1DetectMounts,
+     .detectPlacement = virCgroupV1DetectPlacement,
+     .validatePlacement = virCgroupV1ValidatePlacement,
++    .stealPlacement = virCgroupV1StealPlacement,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-extract-virCgroupV1SupportsCpuBW.patch b/SOURCES/libvirt-vircgroup-extract-virCgroupV1SupportsCpuBW.patch
new file mode 100644
index 0000000..18f0dc8
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-extract-virCgroupV1SupportsCpuBW.patch
@@ -0,0 +1,111 @@
+From 36f035a5d6620f5f39f4aec45d4ec1ec0fa7ccbc Mon Sep 17 00:00:00 2001
+Message-Id: <36f035a5d6620f5f39f4aec45d4ec1ec0fa7ccbc@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:06:59 +0200
+Subject: [PATCH] vircgroup: extract virCgroupV1SupportsCpuBW
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit d182fac0bb07ff06ca938b40030849f86dfa24f1)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <679862bf39de7fbd81ab5b1e65c61cf578abb944.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c        | 13 +------------
+ src/util/vircgroupbackend.h |  4 ++++
+ src/util/vircgroupv1.c      | 19 +++++++++++++++++++
+ 3 files changed, 24 insertions(+), 12 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index a3e7954d03..fa9fa52019 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -2685,18 +2685,7 @@ int virCgroupSetOwner(virCgroupPtr cgroup,
+ bool
+ virCgroupSupportsCpuBW(virCgroupPtr cgroup)
+ {
+-    VIR_AUTOFREE(char *) path = NULL;
+-
+-    if (!cgroup)
+-        return false;
+-
+-    if (virCgroupPathOfController(cgroup, VIR_CGROUP_CONTROLLER_CPU,
+-                                  "cpu.cfs_period_us", &path) < 0) {
+-        virResetLastError();
+-        return false;
+-    }
+-
+-    return virFileExists(path);
++    VIR_CGROUP_BACKEND_CALL(cgroup, supportsCpuBW, false);
+ }
+ 
+ int
+diff --git a/src/util/vircgroupbackend.h b/src/util/vircgroupbackend.h
+index f7c230db76..d3d5e7c222 100644
+--- a/src/util/vircgroupbackend.h
++++ b/src/util/vircgroupbackend.h
+@@ -300,6 +300,9 @@ typedef int
+ (*virCgroupGetCpuCfsQuotaCB)(virCgroupPtr group,
+                              long long *cfs_quota);
+ 
++typedef bool
++(*virCgroupSupportsCpuBWCB)(virCgroupPtr cgroup);
++
+ struct _virCgroupBackend {
+     virCgroupBackendType type;
+ 
+@@ -361,6 +364,7 @@ struct _virCgroupBackend {
+     virCgroupGetCpuCfsPeriodCB getCpuCfsPeriod;
+     virCgroupSetCpuCfsQuotaCB setCpuCfsQuota;
+     virCgroupGetCpuCfsQuotaCB getCpuCfsQuota;
++    virCgroupSupportsCpuBWCB supportsCpuBW;
+ };
+ typedef struct _virCgroupBackend virCgroupBackend;
+ typedef virCgroupBackend *virCgroupBackendPtr;
+diff --git a/src/util/vircgroupv1.c b/src/util/vircgroupv1.c
+index 25f7376026..f2a8839f6e 100644
+--- a/src/util/vircgroupv1.c
++++ b/src/util/vircgroupv1.c
+@@ -1846,6 +1846,24 @@ virCgroupV1GetCpuCfsQuota(virCgroupPtr group,
+ }
+ 
+ 
++static bool
++virCgroupV1SupportsCpuBW(virCgroupPtr cgroup)
++{
++    VIR_AUTOFREE(char *) path = NULL;
++
++    if (!cgroup)
++        return false;
++
++    if (virCgroupV1PathOfController(cgroup, VIR_CGROUP_CONTROLLER_CPU,
++                                    "cpu.cfs_period_us", &path) < 0) {
++        virResetLastError();
++        return false;
++    }
++
++    return virFileExists(path);
++}
++
++
+ virCgroupBackend virCgroupV1Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V1,
+ 
+@@ -1905,6 +1923,7 @@ virCgroupBackend virCgroupV1Backend = {
+     .getCpuCfsPeriod = virCgroupV1GetCpuCfsPeriod,
+     .setCpuCfsQuota = virCgroupV1SetCpuCfsQuota,
+     .getCpuCfsQuota = virCgroupV1GetCpuCfsQuota,
++    .supportsCpuBW = virCgroupV1SupportsCpuBW,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-extract-virCgroupV1ValidateMachineGroup.patch b/SOURCES/libvirt-vircgroup-extract-virCgroupV1ValidateMachineGroup.patch
new file mode 100644
index 0000000..a8bbadb
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-extract-virCgroupV1ValidateMachineGroup.patch
@@ -0,0 +1,290 @@
+From e950a43b63a79cf68e835d800688d759ba408178 Mon Sep 17 00:00:00 2001
+Message-Id: <e950a43b63a79cf68e835d800688d759ba408178@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:06:25 +0200
+Subject: [PATCH] vircgroup: extract virCgroupV1ValidateMachineGroup
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 61629d5be3a4809fe05feb15adbc8f2c27916702)
+
+Conflicts:
+    src/util/vircgroupv1.c: missing commit c0abcca417
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <a34a0141721e9e27c0b3337108c13d36caa6bb79.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c        | 85 +------------------------------------
+ src/util/vircgroupbackend.h |  7 +++
+ src/util/vircgrouppriv.h    |  2 +
+ src/util/vircgroupv1.c      | 85 +++++++++++++++++++++++++++++++++++++
+ 4 files changed, 96 insertions(+), 83 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index 15d0cb65ac..6825623478 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -216,7 +216,7 @@ virCgroupPartitionNeedsEscaping(const char *path)
+ }
+ 
+ 
+-static int
++int
+ virCgroupPartitionEscape(char **path)
+ {
+     int rc;
+@@ -235,87 +235,6 @@ virCgroupPartitionEscape(char **path)
+ }
+ 
+ 
+-static bool
+-virCgroupValidateMachineGroup(virCgroupPtr group,
+-                              const char *name,
+-                              const char *drivername,
+-                              const char *machinename)
+-{
+-    size_t i;
+-    VIR_AUTOFREE(char *) partname = NULL;
+-    VIR_AUTOFREE(char *) scopename_old = NULL;
+-    VIR_AUTOFREE(char *) scopename_new = NULL;
+-    VIR_AUTOFREE(char *) partmachinename = NULL;
+-
+-    if (virAsprintf(&partname, "%s.libvirt-%s",
+-                    name, drivername) < 0)
+-        return false;
+-
+-    if (virCgroupPartitionEscape(&partname) < 0)
+-        return false;
+-
+-    if (virAsprintf(&partmachinename, "%s.libvirt-%s",
+-                    machinename, drivername) < 0 ||
+-        virCgroupPartitionEscape(&partmachinename) < 0)
+-        return false;
+-
+-    if (!(scopename_old = virSystemdMakeScopeName(name, drivername, true)))
+-        return false;
+-
+-    if (!(scopename_new = virSystemdMakeScopeName(machinename,
+-                                                  drivername, false)))
+-        return false;
+-
+-    if (virCgroupPartitionEscape(&scopename_old) < 0)
+-        return false;
+-
+-    if (virCgroupPartitionEscape(&scopename_new) < 0)
+-        return false;
+-
+-    for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
+-        char *tmp;
+-
+-        if (i == VIR_CGROUP_CONTROLLER_SYSTEMD)
+-            continue;
+-
+-        if (!group->controllers[i].placement)
+-            continue;
+-
+-        tmp = strrchr(group->controllers[i].placement, '/');
+-        if (!tmp)
+-            return false;
+-
+-        if (i == VIR_CGROUP_CONTROLLER_CPU ||
+-            i == VIR_CGROUP_CONTROLLER_CPUACCT ||
+-            i == VIR_CGROUP_CONTROLLER_CPUSET) {
+-            if (STREQ(tmp, "/emulator"))
+-                *tmp = '\0';
+-            tmp = strrchr(group->controllers[i].placement, '/');
+-            if (!tmp)
+-                return false;
+-        }
+-
+-        tmp++;
+-
+-        if (STRNEQ(tmp, name) &&
+-            STRNEQ(tmp, machinename) &&
+-            STRNEQ(tmp, partname) &&
+-            STRNEQ(tmp, partmachinename) &&
+-            STRNEQ(tmp, scopename_old) &&
+-            STRNEQ(tmp, scopename_new)) {
+-            VIR_DEBUG("Name '%s' for controller '%s' does not match "
+-                      "'%s', '%s', '%s', '%s' or '%s'",
+-                      tmp, virCgroupControllerTypeToString(i),
+-                      name, machinename, partname,
+-                      scopename_old, scopename_new);
+-            return false;
+-        }
+-    }
+-
+-    return true;
+-}
+-
+-
+ static int
+ virCgroupCopyMounts(virCgroupPtr group,
+                     virCgroupPtr parent)
+@@ -1508,7 +1427,7 @@ virCgroupNewDetectMachine(const char *name,
+         return -1;
+     }
+ 
+-    if (!virCgroupValidateMachineGroup(*group, name, drivername, machinename)) {
++    if (!(*group)->backend->validateMachineGroup(*group, name, drivername, machinename)) {
+         VIR_DEBUG("Failed to validate machine name for '%s' driver '%s'",
+                   name, drivername);
+         virCgroupFree(group);
+diff --git a/src/util/vircgroupbackend.h b/src/util/vircgroupbackend.h
+index 88f51416b0..daf47bac09 100644
+--- a/src/util/vircgroupbackend.h
++++ b/src/util/vircgroupbackend.h
+@@ -35,11 +35,18 @@ typedef enum {
+ typedef bool
+ (*virCgroupAvailableCB)(void);
+ 
++typedef bool
++(*virCgroupValidateMachineGroupCB)(virCgroupPtr group,
++                                   const char *name,
++                                   const char *drivername,
++                                   const char *machinename);
++
+ struct _virCgroupBackend {
+     virCgroupBackendType type;
+ 
+     /* Mandatory callbacks that need to be implemented for every backend. */
+     virCgroupAvailableCB available;
++    virCgroupValidateMachineGroupCB validateMachineGroup;
+ };
+ typedef struct _virCgroupBackend virCgroupBackend;
+ typedef virCgroupBackend *virCgroupBackendPtr;
+diff --git a/src/util/vircgrouppriv.h b/src/util/vircgrouppriv.h
+index 2caa966fee..e7f4a1f0fc 100644
+--- a/src/util/vircgrouppriv.h
++++ b/src/util/vircgrouppriv.h
+@@ -53,6 +53,8 @@ struct _virCgroup {
+     virCgroupController controllers[VIR_CGROUP_CONTROLLER_LAST];
+ };
+ 
++int virCgroupPartitionEscape(char **path);
++
+ int virCgroupNewPartition(const char *path,
+                           bool create,
+                           int controllers,
+diff --git a/src/util/vircgroupv1.c b/src/util/vircgroupv1.c
+index 73045b1109..b78cdcab53 100644
+--- a/src/util/vircgroupv1.c
++++ b/src/util/vircgroupv1.c
+@@ -30,11 +30,14 @@
+ #include "vircgrouppriv.h"
+ #undef __VIR_CGROUP_ALLOW_INCLUDE_PRIV_H__
+ 
++#include "viralloc.h"
+ #include "vircgroup.h"
+ #include "vircgroupbackend.h"
+ #include "vircgroupv1.h"
+ #include "virfile.h"
+ #include "virlog.h"
++#include "virstring.h"
++#include "virsystemd.h"
+ 
+ VIR_LOG_INIT("util.cgroup");
+ 
+@@ -76,10 +79,92 @@ virCgroupV1Available(void)
+ }
+ 
+ 
++static bool
++virCgroupV1ValidateMachineGroup(virCgroupPtr group,
++                                const char *name,
++                                const char *drivername,
++                                const char *machinename)
++{
++    size_t i;
++    VIR_AUTOFREE(char *) partname = NULL;
++    VIR_AUTOFREE(char *) scopename_old = NULL;
++    VIR_AUTOFREE(char *) scopename_new = NULL;
++    VIR_AUTOFREE(char *) partmachinename = NULL;
++
++    if (virAsprintf(&partname, "%s.libvirt-%s",
++                    name, drivername) < 0)
++        return false;
++
++    if (virCgroupPartitionEscape(&partname) < 0)
++        return false;
++
++    if (virAsprintf(&partmachinename, "%s.libvirt-%s",
++                    machinename, drivername) < 0 ||
++        virCgroupPartitionEscape(&partmachinename) < 0)
++        return false;
++
++    if (!(scopename_old = virSystemdMakeScopeName(name, drivername, true)))
++        return false;
++
++    if (!(scopename_new = virSystemdMakeScopeName(machinename,
++                                                  drivername, false)))
++        return false;
++
++    if (virCgroupPartitionEscape(&scopename_old) < 0)
++        return false;
++
++    if (virCgroupPartitionEscape(&scopename_new) < 0)
++        return false;
++
++    for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
++        char *tmp;
++
++        if (i == VIR_CGROUP_CONTROLLER_SYSTEMD)
++            continue;
++
++        if (!group->controllers[i].placement)
++            continue;
++
++        tmp = strrchr(group->controllers[i].placement, '/');
++        if (!tmp)
++            return false;
++
++        if (i == VIR_CGROUP_CONTROLLER_CPU ||
++            i == VIR_CGROUP_CONTROLLER_CPUACCT ||
++            i == VIR_CGROUP_CONTROLLER_CPUSET) {
++            if (STREQ(tmp, "/emulator"))
++                *tmp = '\0';
++            tmp = strrchr(group->controllers[i].placement, '/');
++            if (!tmp)
++                return false;
++        }
++
++        tmp++;
++
++        if (STRNEQ(tmp, name) &&
++            STRNEQ(tmp, machinename) &&
++            STRNEQ(tmp, partname) &&
++            STRNEQ(tmp, partmachinename) &&
++            STRNEQ(tmp, scopename_old) &&
++            STRNEQ(tmp, scopename_new)) {
++            VIR_DEBUG("Name '%s' for controller '%s' does not match "
++                      "'%s', '%s', '%s', '%s' or '%s'",
++                      tmp, virCgroupV1ControllerTypeToString(i),
++                      name, machinename, partname,
++                      scopename_old, scopename_new);
++            return false;
++        }
++    }
++
++    return true;
++}
++
++
+ virCgroupBackend virCgroupV1Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V1,
+ 
+     .available = virCgroupV1Available,
++    .validateMachineGroup = virCgroupV1ValidateMachineGroup,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-extract-virCgroupV1ValidatePlacement.patch b/SOURCES/libvirt-vircgroup-extract-virCgroupV1ValidatePlacement.patch
new file mode 100644
index 0000000..ddd9afb
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-extract-virCgroupV1ValidatePlacement.patch
@@ -0,0 +1,150 @@
+From a4fad1d74b1af03d7bd89d4ef1bc1be4d7c9feca Mon Sep 17 00:00:00 2001
+Message-Id: <a4fad1d74b1af03d7bd89d4ef1bc1be4d7c9feca@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:06:29 +0200
+Subject: [PATCH] vircgroup: extract virCgroupV1ValidatePlacement
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit b549a66edf46ced7c2b922408f3c7cdad2539e0b)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <0fac794a48f75788ccfab8614ac8e7f051df2719.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c        | 32 +-------------------------------
+ src/util/vircgroupbackend.h |  5 +++++
+ src/util/vircgroupv1.c      | 31 +++++++++++++++++++++++++++++++
+ 3 files changed, 37 insertions(+), 31 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index b63321ca33..b17a1dcbb7 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -349,36 +349,6 @@ virCgroupDetectPlacement(virCgroupPtr group,
+ }
+ 
+ 
+-static int
+-virCgroupValidatePlacement(virCgroupPtr group,
+-                           pid_t pid)
+-{
+-    size_t i;
+-
+-    for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
+-        if (!group->controllers[i].mountPoint)
+-            continue;
+-
+-        if (!group->controllers[i].placement) {
+-            virReportError(VIR_ERR_INTERNAL_ERROR,
+-                           _("Could not find placement for controller %s at %s"),
+-                           virCgroupControllerTypeToString(i),
+-                           group->controllers[i].placement);
+-            return -1;
+-        }
+-
+-        VIR_DEBUG("Detected mount/mapping %zu:%s at %s in %s for pid %lld",
+-                  i,
+-                  virCgroupControllerTypeToString(i),
+-                  group->controllers[i].mountPoint,
+-                  group->controllers[i].placement,
+-                  (long long) pid);
+-    }
+-
+-    return 0;
+-}
+-
+-
+ static int
+ virCgroupDetectControllers(virCgroupPtr group,
+                            int controllers)
+@@ -504,7 +474,7 @@ virCgroupDetect(virCgroupPtr group,
+         return -1;
+ 
+     /* Check that for every mounted controller, we found our placement */
+-    if (virCgroupValidatePlacement(group, pid) < 0)
++    if (group->backend->validatePlacement(group, pid) < 0)
+         return -1;
+ 
+     return 0;
+diff --git a/src/util/vircgroupbackend.h b/src/util/vircgroupbackend.h
+index 85906e7191..086cfb8090 100644
+--- a/src/util/vircgroupbackend.h
++++ b/src/util/vircgroupbackend.h
+@@ -62,6 +62,10 @@ typedef int
+                               const char *controllers,
+                               const char *selfpath);
+ 
++typedef int
++(*virCgroupValidatePlacementCB)(virCgroupPtr group,
++                                pid_t pid);
++
+ struct _virCgroupBackend {
+     virCgroupBackendType type;
+ 
+@@ -72,6 +76,7 @@ struct _virCgroupBackend {
+     virCgroupCopyPlacementCB copyPlacement;
+     virCgroupDetectMountsCB detectMounts;
+     virCgroupDetectPlacementCB detectPlacement;
++    virCgroupValidatePlacementCB validatePlacement;
+ };
+ typedef struct _virCgroupBackend virCgroupBackend;
+ typedef virCgroupBackend *virCgroupBackendPtr;
+diff --git a/src/util/vircgroupv1.c b/src/util/vircgroupv1.c
+index 68bb1c6f5d..2c905a832a 100644
+--- a/src/util/vircgroupv1.c
++++ b/src/util/vircgroupv1.c
+@@ -373,6 +373,36 @@ virCgroupV1DetectPlacement(virCgroupPtr group,
+ }
+ 
+ 
++static int
++virCgroupV1ValidatePlacement(virCgroupPtr group,
++                             pid_t pid)
++{
++    size_t i;
++
++    for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
++        if (!group->controllers[i].mountPoint)
++            continue;
++
++        if (!group->controllers[i].placement) {
++            virReportError(VIR_ERR_INTERNAL_ERROR,
++                           _("Could not find placement for v1 controller %s at %s"),
++                           virCgroupV1ControllerTypeToString(i),
++                           group->controllers[i].placement);
++            return -1;
++        }
++
++        VIR_DEBUG("Detected mount/mapping %zu:%s at %s in %s for pid %lld",
++                  i,
++                  virCgroupV1ControllerTypeToString(i),
++                  group->controllers[i].mountPoint,
++                  group->controllers[i].placement,
++                  (long long) pid);
++    }
++
++    return 0;
++}
++
++
+ virCgroupBackend virCgroupV1Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V1,
+ 
+@@ -382,6 +412,7 @@ virCgroupBackend virCgroupV1Backend = {
+     .copyPlacement = virCgroupV1CopyPlacement,
+     .detectMounts = virCgroupV1DetectMounts,
+     .detectPlacement = virCgroupV1DetectPlacement,
++    .validatePlacement = virCgroupV1ValidatePlacement,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-fix-MinGW-build.patch b/SOURCES/libvirt-vircgroup-fix-MinGW-build.patch
new file mode 100644
index 0000000..8f34771
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-fix-MinGW-build.patch
@@ -0,0 +1,52 @@
+From 86426efffd910c22c9cfadc50516883b606c6946 Mon Sep 17 00:00:00 2001
+Message-Id: <86426efffd910c22c9cfadc50516883b606c6946@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:06:03 +0200
+Subject: [PATCH] vircgroup: fix MinGW build
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Broken by commit <901d2b9c87>.
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit baebd9f3d84b5cb86c7c6f35eb41cf9fb7e9b624)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <bb4185916d7e3937b58f9019feb5abf3ba6e4823.1561993099.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c | 15 +++++++++++++++
+ 1 file changed, 15 insertions(+)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index 0ed83932ac..df38bb77e0 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -4335,6 +4335,21 @@ virCgroupSetMemory(virCgroupPtr group ATTRIBUTE_UNUSED,
+ }
+ 
+ 
++int
++virCgroupGetMemoryStat(virCgroupPtr group ATTRIBUTE_UNUSED,
++                       unsigned long long *cache ATTRIBUTE_UNUSED,
++                       unsigned long long *activeAnon ATTRIBUTE_UNUSED,
++                       unsigned long long *inactiveAnon ATTRIBUTE_UNUSED,
++                       unsigned long long *activeFile ATTRIBUTE_UNUSED,
++                       unsigned long long *inactiveFile ATTRIBUTE_UNUSED,
++                       unsigned long long *unevictable ATTRIBUTE_UNUSED)
++{
++    virReportSystemError(ENOSYS, "%s",
++                         _("Control groups not supported on this platform"));
++    return -1;
++}
++
++
+ int
+ virCgroupGetMemoryUsage(virCgroupPtr group ATTRIBUTE_UNUSED,
+                         unsigned long *kb ATTRIBUTE_UNUSED)
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-fix-bug-in-virCgroupEnableMissingControllers.patch b/SOURCES/libvirt-vircgroup-fix-bug-in-virCgroupEnableMissingControllers.patch
new file mode 100644
index 0000000..18175d4
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-fix-bug-in-virCgroupEnableMissingControllers.patch
@@ -0,0 +1,50 @@
+From 5abd9049c8bdea6170dc455033e37811ba875db8 Mon Sep 17 00:00:00 2001
+Message-Id: <5abd9049c8bdea6170dc455033e37811ba875db8@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:06:13 +0200
+Subject: [PATCH] vircgroup: fix bug in virCgroupEnableMissingControllers
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+If we are on host with systemd we need to build cgroup hierarchy
+ourselves for controllers that are not managed by systemd.
+
+As a starting parent we need to force root group because
+virCgroupMakeGroup() takes that parent in order to inherit values
+for cpuset controller.
+
+By default cpuset controller is managed by systemd so we will never
+hit the issue but for v2 cgroups we need to use parent cgroup every
+time.
+
+Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 63b4ed0dd3e1555b4c9d82ef0ca0648493f75af2)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <ae150854a6a02300cd3329c538373b770320f504.1561993099.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index 6aa30a82be..2328957818 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -1495,7 +1495,7 @@ virCgroupEnableMissingControllers(char *path,
+     int ret = -1;
+ 
+     if (virCgroupNew(pidleader,
+-                     "",
++                     "/",
+                      NULL,
+                      controllers,
+                      &parent) < 0)
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-fix-cgroups-v2-controllers-detection.patch b/SOURCES/libvirt-vircgroup-fix-cgroups-v2-controllers-detection.patch
new file mode 100644
index 0000000..e7f4d03
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-fix-cgroups-v2-controllers-detection.patch
@@ -0,0 +1,128 @@
+From b220fdba77897f65f3e7e963868f22d7ace58724 Mon Sep 17 00:00:00 2001
+Message-Id: <b220fdba77897f65f3e7e963868f22d7ace58724@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Thu, 25 Jul 2019 13:37:01 +0200
+Subject: [PATCH] vircgroup: fix cgroups v2 controllers detection
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+When creating new group for cgroups v2 the we cannot check
+cgroups.controllers for that cgroup because the directory is created
+later.  In that case we should check cgroups.subtree_control of parent
+group to get list of controllers enabled for child cgroups.
+
+In order to achieve that we will prefer the parent group if it exists,
+the current group will be used only for root group.
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Acked-by: Peter Krempa <pkrempa@redhat.com>
+(cherry picked from commit 7b77f3a11e9ae3e3cf0ccb71bd72d4a865b7c71e)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <ff6427994e0904f5649b70206f8f73129d1b8452.1564054553.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c        |  2 +-
+ src/util/vircgroupbackend.h |  3 ++-
+ src/util/vircgroupv1.c      |  3 ++-
+ src/util/vircgroupv2.c      | 23 ++++++++++++++++-------
+ 4 files changed, 21 insertions(+), 10 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index 37f6def08d..2c067edc5c 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -412,7 +412,7 @@ virCgroupDetect(virCgroupPtr group,
+ 
+     for (i = 0; i < VIR_CGROUP_BACKEND_TYPE_LAST; i++) {
+         if (group->backends[i]) {
+-            int rc = group->backends[i]->detectControllers(group, controllers);
++            int rc = group->backends[i]->detectControllers(group, controllers, parent);
+             if (rc < 0)
+                 return -1;
+             controllersAvailable |= rc;
+diff --git a/src/util/vircgroupbackend.h b/src/util/vircgroupbackend.h
+index 2b5be21a76..b97f686368 100644
+--- a/src/util/vircgroupbackend.h
++++ b/src/util/vircgroupbackend.h
+@@ -99,7 +99,8 @@ typedef char *
+ 
+ typedef int
+ (*virCgroupDetectControllersCB)(virCgroupPtr group,
+-                                int controllers);
++                                int controllers,
++                                virCgroupPtr parent);
+ 
+ typedef bool
+ (*virCgroupHasControllerCB)(virCgroupPtr cgroup,
+diff --git a/src/util/vircgroupv1.c b/src/util/vircgroupv1.c
+index a7d6c92e4c..925e8ee1c1 100644
+--- a/src/util/vircgroupv1.c
++++ b/src/util/vircgroupv1.c
+@@ -419,7 +419,8 @@ virCgroupV1StealPlacement(virCgroupPtr group)
+ 
+ static int
+ virCgroupV1DetectControllers(virCgroupPtr group,
+-                             int controllers)
++                             int controllers,
++                             virCgroupPtr parent ATTRIBUTE_UNUSED)
+ {
+     size_t i;
+     size_t j;
+diff --git a/src/util/vircgroupv2.c b/src/util/vircgroupv2.c
+index b4e90ed46d..7b3cd64cc5 100644
+--- a/src/util/vircgroupv2.c
++++ b/src/util/vircgroupv2.c
+@@ -241,7 +241,8 @@ virCgroupV2StealPlacement(virCgroupPtr group)
+ 
+ 
+ static int
+-virCgroupV2ParseControllersFile(virCgroupPtr group)
++virCgroupV2ParseControllersFile(virCgroupPtr group,
++                                virCgroupPtr parent)
+ {
+     int rc;
+     VIR_AUTOFREE(char *) contStr = NULL;
+@@ -249,10 +250,17 @@ virCgroupV2ParseControllersFile(virCgroupPtr group)
+     char **contList = NULL;
+     char **tmp;
+ 
+-    if (virAsprintf(&contFile, "%s%s/cgroup.controllers",
+-                    group->unified.mountPoint,
+-                    NULLSTR_EMPTY(group->unified.placement)) < 0)
+-        return -1;
++    if (parent) {
++        if (virAsprintf(&contFile, "%s%s/cgroup.subtree_control",
++                        parent->unified.mountPoint,
++                        NULLSTR_EMPTY(parent->unified.placement)) < 0)
++            return -1;
++    } else {
++        if (virAsprintf(&contFile, "%s%s/cgroup.controllers",
++                        group->unified.mountPoint,
++                        NULLSTR_EMPTY(group->unified.placement)) < 0)
++            return -1;
++    }
+ 
+     rc = virFileReadAll(contFile, 1024 * 1024, &contStr);
+     if (rc < 0) {
+@@ -285,11 +293,12 @@ virCgroupV2ParseControllersFile(virCgroupPtr group)
+ 
+ static int
+ virCgroupV2DetectControllers(virCgroupPtr group,
+-                             int controllers)
++                             int controllers,
++                             virCgroupPtr parent)
+ {
+     size_t i;
+ 
+-    if (virCgroupV2ParseControllersFile(group) < 0)
++    if (virCgroupV2ParseControllersFile(group, parent) < 0)
+         return -1;
+ 
+     /* In cgroup v2 there is no cpuacct controller, the cpu.stat file always
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-include-system-headers-only-on-linux.patch b/SOURCES/libvirt-vircgroup-include-system-headers-only-on-linux.patch
new file mode 100644
index 0000000..436ee86
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-include-system-headers-only-on-linux.patch
@@ -0,0 +1,83 @@
+From 05df743686ad42fa006877341b7719ff4a890a70 Mon Sep 17 00:00:00 2001
+Message-Id: <05df743686ad42fa006877341b7719ff4a890a70@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:07:09 +0200
+Subject: [PATCH] vircgroup: include system headers only on linux
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+All the system headers are used only if we are compiling on linux
+and they all are present otherwise we would have seen build errors
+because in our tests/vircgrouptest.c we use only __linux__ to check
+whether to skip the cgroup tests or not.
+
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 6ef37ed3b8e7cc5fd83ff2b84bf08deea62d3bd0)
+
+Conflicts:
+    src/util/vircgroup.c - missing commits 9403b63102 5165ff0971
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <78f1905b381e5d9dce9daeabcf157e2fe65ddffe.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c | 35 +++++++++++++++++------------------
+ 1 file changed, 17 insertions(+), 18 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index f1ecb1dbeb..a376b9b89a 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -23,28 +23,27 @@
+  */
+ #include <config.h>
+ 
+-#include <stdio.h>
+-#if defined HAVE_MNTENT_H && defined HAVE_SYS_MOUNT_H \
+-    && defined HAVE_GETMNTENT_R
++#ifdef __linux__
++# include <stdio.h>
+ # include <mntent.h>
+ # include <sys/mount.h>
+-#endif
+-#include <fcntl.h>
+-#include <string.h>
+-#include <errno.h>
+-#include <stdlib.h>
+-#include <sys/stat.h>
++# include <fcntl.h>
++# include <string.h>
++# include <errno.h>
++# include <stdlib.h>
++# include <sys/stat.h>
+ 
+-#ifdef MAJOR_IN_MKDEV
+-# include <sys/mkdev.h>
+-#elif MAJOR_IN_SYSMACROS
+-# include <sys/sysmacros.h>
+-#endif
++# ifdef MAJOR_IN_MKDEV
++#  include <sys/mkdev.h>
++# elif MAJOR_IN_SYSMACROS
++#  include <sys/sysmacros.h>
++# endif
+ 
+-#include <sys/types.h>
+-#include <signal.h>
+-#include <dirent.h>
+-#include <unistd.h>
++# include <sys/types.h>
++# include <signal.h>
++# include <dirent.h>
++# include <unistd.h>
++#endif /* __linux__ */
+ 
+ #define __VIR_CGROUP_ALLOW_INCLUDE_PRIV_H__
+ #include "vircgrouppriv.h"
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-introduce-cgroup-v1-backend-files.patch b/SOURCES/libvirt-vircgroup-introduce-cgroup-v1-backend-files.patch
new file mode 100644
index 0000000..8a6dd5d
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-introduce-cgroup-v1-backend-files.patch
@@ -0,0 +1,186 @@
+From d1b618c627d848ed4549912d83be397f969935d2 Mon Sep 17 00:00:00 2001
+Message-Id: <d1b618c627d848ed4549912d83be397f969935d2@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:06:22 +0200
+Subject: [PATCH] vircgroup: introduce cgroup v1 backend files
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 1f221d610dc510b82f17407a81a0acd56d9efc5b)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <d49ee905c005a855d89ed463e81aa935b07f003e.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/Makefile.am             |  1 +
+ src/libvirt_private.syms    |  3 ++
+ src/util/Makefile.inc.am    |  2 ++
+ src/util/vircgroupbackend.c |  2 ++
+ src/util/vircgroupv1.c      | 55 +++++++++++++++++++++++++++++++++++++
+ src/util/vircgroupv1.h      | 27 ++++++++++++++++++
+ 6 files changed, 90 insertions(+)
+ create mode 100644 src/util/vircgroupv1.c
+ create mode 100644 src/util/vircgroupv1.h
+
+diff --git a/src/Makefile.am b/src/Makefile.am
+index c4e797f5a2..0def0a3b19 100644
+--- a/src/Makefile.am
++++ b/src/Makefile.am
+@@ -679,6 +679,7 @@ libvirt_setuid_rpc_client_la_SOURCES = \
+ 		util/virbuffer.c \
+ 		util/vircgroup.c \
+ 		util/vircgroupbackend.c \
++		util/vircgroupv1.c \
+ 		util/vircommand.c \
+ 		util/virconf.c \
+ 		util/virdbus.c \
+diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
+index 627eb5e587..b144955154 100644
+--- a/src/libvirt_private.syms
++++ b/src/libvirt_private.syms
+@@ -1595,6 +1595,9 @@ virCgroupTerminateMachine;
+ virCgroupBackendGetAll;
+ virCgroupBackendRegister;
+ 
++# util/vircgroupv1.h
++virCgroupV1Register;
++
+ # util/virclosecallbacks.h
+ virCloseCallbacksGet;
+ virCloseCallbacksGetConn;
+diff --git a/src/util/Makefile.inc.am b/src/util/Makefile.inc.am
+index a9185bd7b7..725ece98e9 100644
+--- a/src/util/Makefile.inc.am
++++ b/src/util/Makefile.inc.am
+@@ -25,6 +25,8 @@ UTIL_SOURCES = \
+ 	util/vircgroup.h util/vircgrouppriv.h \
+ 	util/vircgroupbackend.c \
+ 	util/vircgroupbackend.h \
++	util/vircgroupv1.c \
++	util/vircgroupv1.h \
+ 	util/virclosecallbacks.c \
+ 	util/virclosecallbacks.h \
+ 	util/vircommand.c \
+diff --git a/src/util/vircgroupbackend.c b/src/util/vircgroupbackend.c
+index e014bfc0e6..d854c9711d 100644
+--- a/src/util/vircgroupbackend.c
++++ b/src/util/vircgroupbackend.c
+@@ -20,6 +20,7 @@
+ #include <config.h>
+ 
+ #include "vircgroupbackend.h"
++#include "vircgroupv1.h"
+ #include "virerror.h"
+ #include "virthread.h"
+ 
+@@ -49,6 +50,7 @@ virCgroupBackendRegister(virCgroupBackendPtr backend)
+ static void
+ virCgroupBackendOnceInit(void)
+ {
++    virCgroupV1Register();
+ }
+ 
+ 
+diff --git a/src/util/vircgroupv1.c b/src/util/vircgroupv1.c
+new file mode 100644
+index 0000000000..4dda7865f1
+--- /dev/null
++++ b/src/util/vircgroupv1.c
+@@ -0,0 +1,55 @@
++/*
++ * vircgroupv1.c: methods for cgroups v1 backend
++ *
++ * Copyright (C) 2010-2015,2018 Red Hat, Inc.
++ * Copyright IBM Corp. 2008
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Lesser General Public
++ * License as published by the Free Software Foundation; either
++ * version 2.1 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with this library.  If not, see
++ * <http://www.gnu.org/licenses/>.
++ */
++#include <config.h>
++
++#include "internal.h"
++
++#define __VIR_CGROUP_ALLOW_INCLUDE_PRIV_H__
++#include "vircgrouppriv.h"
++#undef __VIR_CGROUP_ALLOW_INCLUDE_PRIV_H__
++
++#include "vircgroup.h"
++#include "vircgroupbackend.h"
++#include "vircgroupv1.h"
++#include "virlog.h"
++
++VIR_LOG_INIT("util.cgroup");
++
++#define VIR_FROM_THIS VIR_FROM_CGROUP
++
++
++VIR_ENUM_DECL(virCgroupV1Controller);
++VIR_ENUM_IMPL(virCgroupV1Controller, VIR_CGROUP_CONTROLLER_LAST,
++              "cpu", "cpuacct", "cpuset", "memory", "devices",
++              "freezer", "blkio", "net_cls", "perf_event",
++              "name=systemd");
++
++
++virCgroupBackend virCgroupV1Backend = {
++    .type = VIR_CGROUP_BACKEND_TYPE_V1,
++};
++
++
++void
++virCgroupV1Register(void)
++{
++    virCgroupBackendRegister(&virCgroupV1Backend);
++}
+diff --git a/src/util/vircgroupv1.h b/src/util/vircgroupv1.h
+new file mode 100644
+index 0000000000..517517c109
+--- /dev/null
++++ b/src/util/vircgroupv1.h
+@@ -0,0 +1,27 @@
++/*
++ * vircgroupv1.h: methods for cgroups v1 backend
++ *
++ * Copyright (C) 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
++ * License as published by the Free Software Foundation; either
++ * version 2.1 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with this library.  If not, see
++ * <http://www.gnu.org/licenses/>.
++ */
++
++#ifndef __VIR_CGROUP_V1_H__
++# define __VIR_CGROUP_V1_H__
++
++void
++virCgroupV1Register(void);
++
++#endif /* __VIR_CGROUP_V1_H__ */
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-introduce-virCgroupAddThread.patch b/SOURCES/libvirt-vircgroup-introduce-virCgroupAddThread.patch
new file mode 100644
index 0000000..5203d96
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-introduce-virCgroupAddThread.patch
@@ -0,0 +1,126 @@
+From 83b13b08025476233d7acc7d37297abda861be32 Mon Sep 17 00:00:00 2001
+Message-Id: <83b13b08025476233d7acc7d37297abda861be32@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:06:16 +0200
+Subject: [PATCH] vircgroup: introduce virCgroupAddThread
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Once we introduce cgroup v2 support we need to handle processes and
+threads differently.
+
+Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 7b526ea57c8ca02e49f6a8cc71a6910f56803bde)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <ed2085fc086090e3865b08758e973e0eedd78a4d.1561993099.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/libvirt_private.syms |  1 +
+ src/qemu/qemu_process.c  |  2 +-
+ src/util/vircgroup.c     | 32 ++++++++++++++++++++++++++++++++
+ src/util/vircgroup.h     |  1 +
+ 4 files changed, 35 insertions(+), 1 deletion(-)
+
+diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
+index 5dd24e2e66..f8c1a0df16 100644
+--- a/src/libvirt_private.syms
++++ b/src/libvirt_private.syms
+@@ -1515,6 +1515,7 @@ virBufferVasprintf;
+ # util/vircgroup.h
+ virCgroupAddMachineProcess;
+ virCgroupAddProcess;
++virCgroupAddThread;
+ virCgroupAllowAllDevices;
+ virCgroupAllowDevice;
+ virCgroupAllowDevicePath;
+diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
+index c21586fa12..0cd61f02bb 100644
+--- a/src/qemu/qemu_process.c
++++ b/src/qemu/qemu_process.c
+@@ -2538,7 +2538,7 @@ qemuProcessSetupPid(virDomainObjPtr vm,
+             goto cleanup;
+ 
+         /* Move the thread to the sub dir */
+-        if (virCgroupAddProcess(cgroup, pid) < 0)
++        if (virCgroupAddThread(cgroup, pid) < 0)
+             goto cleanup;
+ 
+     }
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index 5aa8596b9c..f08fe3600e 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -1164,6 +1164,10 @@ typedef enum {
+     /* Same as VIR_CGROUP_TASK_PROCESS but it also adds the task to systemd
+      * named controller. */
+     VIR_CGROUP_TASK_SYSTEMD = 1 << 1,
++
++    /* Moves only specific thread into cgroup except to systemd
++     * named controller. */
++    VIR_CGROUP_TASK_THREAD = 1 << 2,
+ } virCgroupTaskFlags;
+ 
+ 
+@@ -1232,6 +1236,24 @@ virCgroupAddMachineProcess(virCgroupPtr group, pid_t pid)
+                                     VIR_CGROUP_TASK_SYSTEMD);
+ }
+ 
++/**
++ * virCgroupAddThread:
++ *
++ * @group: The cgroup to add a thread to
++ * @pid: The pid of the thread to add
++ *
++ * Will add the thread to all controllers, except the
++ * systemd unit controller.
++ *
++ * Returns: 0 on success, -1 on error
++ */
++int
++virCgroupAddThread(virCgroupPtr group,
++                   pid_t pid)
++{
++    return virCgroupAddTaskInternal(group, pid, VIR_CGROUP_TASK_THREAD);
++}
++
+ 
+ static int
+ virCgroupSetPartitionSuffix(const char *path, char **res)
+@@ -4233,6 +4255,16 @@ virCgroupAddMachineProcess(virCgroupPtr group ATTRIBUTE_UNUSED,
+ }
+ 
+ 
++int
++virCgroupAddThread(virCgroupPtr group ATTRIBUTE_UNUSED,
++                   pid_t pid ATTRIBUTE_UNUSED)
++{
++    virReportSystemError(ENXIO, "%s",
++                         _("Control groups not supported on this platform"));
++    return -1;
++}
++
++
+ int
+ virCgroupGetBlkioIoServiced(virCgroupPtr group ATTRIBUTE_UNUSED,
+                             long long *bytes_read ATTRIBUTE_UNUSED,
+diff --git a/src/util/vircgroup.h b/src/util/vircgroup.h
+index bbd4c2ed57..1f676f21c3 100644
+--- a/src/util/vircgroup.h
++++ b/src/util/vircgroup.h
+@@ -120,6 +120,7 @@ int virCgroupPathOfController(virCgroupPtr group,
+ 
+ int virCgroupAddProcess(virCgroupPtr group, pid_t pid);
+ int virCgroupAddMachineProcess(virCgroupPtr group, pid_t pid);
++int virCgroupAddThread(virCgroupPtr group, pid_t pid);
+ 
+ int virCgroupSetBlkioWeight(virCgroupPtr group, unsigned int weight);
+ int virCgroupGetBlkioWeight(virCgroupPtr group, unsigned int *weight);
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-introduce-virCgroupKillRecursiveCB.patch b/SOURCES/libvirt-vircgroup-introduce-virCgroupKillRecursiveCB.patch
new file mode 100644
index 0000000..cd77f04
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-introduce-virCgroupKillRecursiveCB.patch
@@ -0,0 +1,286 @@
+From 8b35858852e5c170410d4462fdf2bb19659b8894 Mon Sep 17 00:00:00 2001
+Message-Id: <8b35858852e5c170410d4462fdf2bb19659b8894@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:08:09 +0200
+Subject: [PATCH] vircgroup: introduce virCgroupKillRecursiveCB
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The rewrite to support cgroup v2 missed this function.  In cgroup v2
+we have different files to track tasks.
+
+We would fail to remove cgroup on non-systemd OSes if there is any
+extra process assigned to guest cgroup because we would not kill any
+process form the guest cgroup.
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit b532546823fde032fe827d41735a0d591c3bc0b8)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <2414a178eb8aba977e7369bba0b37a18cdfec654.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c        | 69 ++++++++++++++++++++-----------------
+ src/util/vircgroupbackend.h |  7 ++++
+ src/util/vircgrouppriv.h    |  8 +++++
+ src/util/vircgroupv1.c      | 16 +++++++++
+ src/util/vircgroupv2.c      | 16 +++++++++
+ 5 files changed, 84 insertions(+), 32 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index 069f1ae396..736b5043a8 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -2431,33 +2431,15 @@ virCgroupRemove(virCgroupPtr group)
+ }
+ 
+ 
+-static int
+-virCgroupPathOfAnyController(virCgroupPtr group,
+-                             const char *name,
+-                             char **keypath)
+-{
+-    size_t i;
+-    int controller;
+-
+-    for (i = 0; i < VIR_CGROUP_BACKEND_TYPE_LAST; i++) {
+-        if (group->backends[i]) {
+-            controller = group->backends[i]->getAnyController(group);
+-            if (controller >= 0)
+-                return virCgroupPathOfController(group, controller, name, keypath);
+-        }
+-    }
+-
+-    virReportSystemError(ENOSYS, "%s",
+-                         _("No controllers are mounted"));
+-    return -1;
+-}
+-
+-
+ /*
+  * Returns 1 if some PIDs are killed, 0 if none are killed, or -1 on error
+  */
+ static int
+-virCgroupKillInternal(virCgroupPtr group, int signum, virHashTablePtr pids)
++virCgroupKillInternal(virCgroupPtr group,
++                      int signum,
++                      virHashTablePtr pids,
++                      int controller,
++                      const char *taskFile)
+ {
+     int ret = -1;
+     bool killedAny = false;
+@@ -2467,7 +2449,7 @@ virCgroupKillInternal(virCgroupPtr group, int signum, virHashTablePtr pids)
+     VIR_DEBUG("group=%p path=%s signum=%d pids=%p",
+               group, group->path, signum, pids);
+ 
+-    if (virCgroupPathOfAnyController(group, "tasks", &keypath) < 0)
++    if (virCgroupPathOfController(group, controller, taskFile, &keypath) < 0)
+         return -1;
+ 
+     /* PIDs may be forking as we kill them, so loop
+@@ -2553,10 +2535,12 @@ virCgroupPidCopy(const void *name)
+ }
+ 
+ 
+-static int
++int
+ virCgroupKillRecursiveInternal(virCgroupPtr group,
+                                int signum,
+                                virHashTablePtr pids,
++                               int controller,
++                               const char *taskFile,
+                                bool dormdir)
+ {
+     int ret = -1;
+@@ -2570,11 +2554,13 @@ virCgroupKillRecursiveInternal(virCgroupPtr group,
+     VIR_DEBUG("group=%p path=%s signum=%d pids=%p",
+               group, group->path, signum, pids);
+ 
+-    if (virCgroupPathOfAnyController(group, "", &keypath) < 0)
++    if (virCgroupPathOfController(group, controller, "", &keypath) < 0)
+         return -1;
+ 
+-    if ((rc = virCgroupKillInternal(group, signum, pids)) < 0)
++    if ((rc = virCgroupKillInternal(group, signum, pids,
++                                    controller, taskFile)) < 0) {
+         goto cleanup;
++    }
+     if (rc == 1)
+         killedAny = true;
+ 
+@@ -2598,7 +2584,7 @@ virCgroupKillRecursiveInternal(virCgroupPtr group,
+             goto cleanup;
+ 
+         if ((rc = virCgroupKillRecursiveInternal(subgroup, signum, pids,
+-                                                 true)) < 0)
++                                                 controller, taskFile, true)) < 0)
+             goto cleanup;
+         if (rc == 1)
+             killedAny = true;
+@@ -2624,8 +2610,10 @@ virCgroupKillRecursiveInternal(virCgroupPtr group,
+ int
+ virCgroupKillRecursive(virCgroupPtr group, int signum)
+ {
+-    int ret;
+-    VIR_DEBUG("group=%p path=%s signum=%d", group, group->path, signum);
++    int ret = 0;
++    int rc;
++    size_t i;
++    virCgroupBackendPtr *backends = virCgroupBackendGetAll();
+     virHashTablePtr pids = virHashCreateFull(100,
+                                              NULL,
+                                              virCgroupPidCode,
+@@ -2633,10 +2621,27 @@ virCgroupKillRecursive(virCgroupPtr group, int signum)
+                                              virCgroupPidCopy,
+                                              NULL);
+ 
+-    ret = virCgroupKillRecursiveInternal(group, signum, pids, false);
++    VIR_DEBUG("group=%p path=%s signum=%d", group, group->path, signum);
+ 
++    if (!backends) {
++        ret = -1;
++        goto cleanup;
++    }
++
++    for (i = 0; i < VIR_CGROUP_BACKEND_TYPE_LAST; i++) {
++        if (backends[i]) {
++            rc = backends[i]->killRecursive(group, signum, pids);
++            if (rc < 0) {
++                ret = -1;
++                goto cleanup;
++            }
++            if (rc > 0)
++                ret = rc;
++        }
++    }
++
++ cleanup:
+     virHashFree(pids);
+-
+     return ret;
+ }
+ 
+diff --git a/src/util/vircgroupbackend.h b/src/util/vircgroupbackend.h
+index bc60b44643..a825dc4be7 100644
+--- a/src/util/vircgroupbackend.h
++++ b/src/util/vircgroupbackend.h
+@@ -24,6 +24,7 @@
+ # include "internal.h"
+ 
+ # include "vircgroup.h"
++# include "virhash.h"
+ 
+ # define CGROUP_MAX_VAL 512
+ 
+@@ -128,6 +129,11 @@ typedef int
+ (*virCgroupHasEmptyTasksCB)(virCgroupPtr cgroup,
+                             int controller);
+ 
++typedef int
++(*virCgroupKillRecursiveCB)(virCgroupPtr group,
++                            int signum,
++                            virHashTablePtr pids);
++
+ typedef int
+ (*virCgroupBindMountCB)(virCgroupPtr group,
+                         const char *oldroot,
+@@ -370,6 +376,7 @@ struct _virCgroupBackend {
+     virCgroupRemoveCB remove;
+     virCgroupAddTaskCB addTask;
+     virCgroupHasEmptyTasksCB hasEmptyTasks;
++    virCgroupKillRecursiveCB killRecursive;
+     virCgroupBindMountCB bindMount;
+     virCgroupSetOwnerCB setOwner;
+ 
+diff --git a/src/util/vircgrouppriv.h b/src/util/vircgrouppriv.h
+index 8f24b0891e..6067f5cdc8 100644
+--- a/src/util/vircgrouppriv.h
++++ b/src/util/vircgrouppriv.h
+@@ -123,4 +123,12 @@ int virCgroupNewDomainPartition(virCgroupPtr partition,
+ 
+ int virCgroupRemoveRecursively(char *grppath);
+ 
++
++int virCgroupKillRecursiveInternal(virCgroupPtr group,
++                                   int signum,
++                                   virHashTablePtr pids,
++                                   int controller,
++                                   const char *taskFile,
++                                   bool dormdir);
++
+ #endif /* __VIR_CGROUP_PRIV_H__ */
+diff --git a/src/util/vircgroupv1.c b/src/util/vircgroupv1.c
+index 3147084f21..7098dc5644 100644
+--- a/src/util/vircgroupv1.c
++++ b/src/util/vircgroupv1.c
+@@ -758,6 +758,21 @@ virCgroupV1HasEmptyTasks(virCgroupPtr cgroup,
+ }
+ 
+ 
++static int
++virCgroupV1KillRecursive(virCgroupPtr group,
++                         int signum,
++                         virHashTablePtr pids)
++{
++    int controller = virCgroupV1GetAnyController(group);
++
++    if (controller < 0)
++        return -1;
++
++    return virCgroupKillRecursiveInternal(group, signum, pids, controller,
++                                          "tasks", false);
++}
++
++
+ static char *
+ virCgroupV1IdentifyRoot(virCgroupPtr group)
+ {
+@@ -2042,6 +2057,7 @@ virCgroupBackend virCgroupV1Backend = {
+     .remove = virCgroupV1Remove,
+     .addTask = virCgroupV1AddTask,
+     .hasEmptyTasks = virCgroupV1HasEmptyTasks,
++    .killRecursive = virCgroupV1KillRecursive,
+     .bindMount = virCgroupV1BindMount,
+     .setOwner = virCgroupV1SetOwner,
+ 
+diff --git a/src/util/vircgroupv2.c b/src/util/vircgroupv2.c
+index bff2f78d7e..5652fcfffb 100644
+--- a/src/util/vircgroupv2.c
++++ b/src/util/vircgroupv2.c
+@@ -463,6 +463,21 @@ virCgroupV2HasEmptyTasks(virCgroupPtr cgroup,
+ }
+ 
+ 
++static int
++virCgroupV2KillRecursive(virCgroupPtr group,
++                         int signum,
++                         virHashTablePtr pids)
++{
++    int controller = virCgroupV2GetAnyController(group);
++
++    if (controller < 0)
++        return -1;
++
++    return virCgroupKillRecursiveInternal(group, signum, pids, controller,
++                                          "cgroup.threads", false);
++}
++
++
+ static int
+ virCgroupV2BindMount(virCgroupPtr group,
+                      const char *oldroot,
+@@ -1559,6 +1574,7 @@ virCgroupBackend virCgroupV2Backend = {
+     .remove = virCgroupV2Remove,
+     .addTask = virCgroupV2AddTask,
+     .hasEmptyTasks = virCgroupV2HasEmptyTasks,
++    .killRecursive = virCgroupV2KillRecursive,
+     .bindMount = virCgroupV2BindMount,
+     .setOwner = virCgroupV2SetOwner,
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-introduce-virCgroupTaskFlags.patch b/SOURCES/libvirt-vircgroup-introduce-virCgroupTaskFlags.patch
new file mode 100644
index 0000000..4677c8b
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-introduce-virCgroupTaskFlags.patch
@@ -0,0 +1,86 @@
+From 482d6964af9e1f8a4d52253e6474ce11f4a1ca5f Mon Sep 17 00:00:00 2001
+Message-Id: <482d6964af9e1f8a4d52253e6474ce11f4a1ca5f@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:06:15 +0200
+Subject: [PATCH] vircgroup: introduce virCgroupTaskFlags
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Use flags in virCgroupAddTaskInternal instead of boolean parameter.
+Following patch will add new flag to indicate thread instead of process.
+
+Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 36c5989c54cf335b365f4e179a4d7ab7d174bd6e)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <a2cf781e5090f8f3ba2aec04aadb80c957001f7c.1561993099.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c | 24 ++++++++++++++++++++----
+ 1 file changed, 20 insertions(+), 4 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index cf510fb019..5aa8596b9c 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -1156,8 +1156,21 @@ virCgroupNew(pid_t pid,
+ }
+ 
+ 
++typedef enum {
++    /* Adds a whole process with all threads to specific cgroup except
++     * to systemd named controller. */
++    VIR_CGROUP_TASK_PROCESS = 1 << 0,
++
++    /* Same as VIR_CGROUP_TASK_PROCESS but it also adds the task to systemd
++     * named controller. */
++    VIR_CGROUP_TASK_SYSTEMD = 1 << 1,
++} virCgroupTaskFlags;
++
++
+ static int
+-virCgroupAddTaskInternal(virCgroupPtr group, pid_t pid, bool withSystemd)
++virCgroupAddTaskInternal(virCgroupPtr group,
++                         pid_t pid,
++                         unsigned int flags)
+ {
+     int ret = -1;
+     size_t i;
+@@ -1170,7 +1183,8 @@ virCgroupAddTaskInternal(virCgroupPtr group, pid_t pid, bool withSystemd)
+         /* We must never add tasks in systemd's hierarchy
+          * unless we're intentionally trying to move a
+          * task into a systemd machine scope */
+-        if (i == VIR_CGROUP_CONTROLLER_SYSTEMD && !withSystemd)
++        if (i == VIR_CGROUP_CONTROLLER_SYSTEMD &&
++            !(flags & VIR_CGROUP_TASK_SYSTEMD))
+             continue;
+ 
+         if (virCgroupSetValueI64(group, i, "tasks", pid) < 0)
+@@ -1196,7 +1210,7 @@ virCgroupAddTaskInternal(virCgroupPtr group, pid_t pid, bool withSystemd)
+ int
+ virCgroupAddProcess(virCgroupPtr group, pid_t pid)
+ {
+-    return virCgroupAddTaskInternal(group, pid, false);
++    return virCgroupAddTaskInternal(group, pid, VIR_CGROUP_TASK_PROCESS);
+ }
+ 
+ /**
+@@ -1213,7 +1227,9 @@ virCgroupAddProcess(virCgroupPtr group, pid_t pid)
+ int
+ virCgroupAddMachineProcess(virCgroupPtr group, pid_t pid)
+ {
+-    return virCgroupAddTaskInternal(group, pid, true);
++    return virCgroupAddTaskInternal(group, pid,
++                                    VIR_CGROUP_TASK_PROCESS |
++                                    VIR_CGROUP_TASK_SYSTEMD);
+ }
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-introduce-virCgroupV2-Set-Get-BlkioDeviceReadBps.patch b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2-Set-Get-BlkioDeviceReadBps.patch
new file mode 100644
index 0000000..5b44c95
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2-Set-Get-BlkioDeviceReadBps.patch
@@ -0,0 +1,112 @@
+From 7ca4f79d91300d6d6da1ac31d745852e35d4220f Mon Sep 17 00:00:00 2001
+Message-Id: <7ca4f79d91300d6d6da1ac31d745852e35d4220f@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:07:37 +0200
+Subject: [PATCH] vircgroup: introduce virCgroupV2(Set|Get)BlkioDeviceReadBps
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 353ce9453e836da1d42993e71c88011f8515e538)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <5fedf92d6740e387df3e88e3abf6b711d79f3dbe.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroupv2.c | 70 ++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 70 insertions(+)
+
+diff --git a/src/util/vircgroupv2.c b/src/util/vircgroupv2.c
+index 1d25c0ae1f..b303e9cb10 100644
+--- a/src/util/vircgroupv2.c
++++ b/src/util/vircgroupv2.c
+@@ -879,6 +879,74 @@ virCgroupV2GetBlkioDeviceWriteIops(virCgroupPtr group,
+ }
+ 
+ 
++static int
++virCgroupV2SetBlkioDeviceReadBps(virCgroupPtr group,
++                                 const char *path,
++                                 unsigned long long rbps)
++{
++    VIR_AUTOFREE(char *) str = NULL;
++    VIR_AUTOFREE(char *) blkstr = NULL;
++
++    if (!(blkstr = virCgroupGetBlockDevString(path)))
++        return -1;
++
++    if (rbps == 0) {
++        if (virAsprintf(&str, "%srbps=max", blkstr) < 0)
++            return -1;
++    } else {
++        if (virAsprintf(&str, "%srbps=%llu", blkstr, rbps) < 0)
++            return -1;
++    }
++
++    return virCgroupSetValueStr(group,
++                                VIR_CGROUP_CONTROLLER_BLKIO,
++                                "io.max",
++                                str);
++}
++
++
++static int
++virCgroupV2GetBlkioDeviceReadBps(virCgroupPtr group,
++                                 const char *path,
++                                 unsigned long long *rbps)
++{
++    VIR_AUTOFREE(char *) str = NULL;
++    const char *name = "rbps=";
++    char *tmp;
++
++    if (virCgroupGetValueForBlkDev(group,
++                                   VIR_CGROUP_CONTROLLER_BLKIO,
++                                   "io.max",
++                                   path,
++                                   &str) < 0) {
++        return -1;
++    }
++
++    if (!str) {
++        *rbps = 0;
++    } else {
++        if (!(tmp = strstr(str, name))) {
++            virReportError(VIR_ERR_INTERNAL_ERROR,
++                           _("Unable to find '%s' limit for block device '%s'"),
++                           name, path);
++            return -1;
++        }
++        tmp += strlen(name);
++
++        if (STREQLEN(tmp, "max", 3)) {
++            *rbps = 0;
++        } else if (virStrToLong_ull(tmp, NULL, 10, rbps) < 0) {
++            virReportError(VIR_ERR_INTERNAL_ERROR,
++                           _("Unable to parse '%s' as an integer"),
++                           str);
++            return -1;
++        }
++    }
++
++    return 0;
++}
++
++
+ virCgroupBackend virCgroupV2Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V2,
+ 
+@@ -911,6 +979,8 @@ virCgroupBackend virCgroupV2Backend = {
+     .getBlkioDeviceReadIops = virCgroupV2GetBlkioDeviceReadIops,
+     .setBlkioDeviceWriteIops = virCgroupV2SetBlkioDeviceWriteIops,
+     .getBlkioDeviceWriteIops = virCgroupV2GetBlkioDeviceWriteIops,
++    .setBlkioDeviceReadBps = virCgroupV2SetBlkioDeviceReadBps,
++    .getBlkioDeviceReadBps = virCgroupV2GetBlkioDeviceReadBps,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-introduce-virCgroupV2-Set-Get-BlkioDeviceReadIops.patch b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2-Set-Get-BlkioDeviceReadIops.patch
new file mode 100644
index 0000000..500aa29
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2-Set-Get-BlkioDeviceReadIops.patch
@@ -0,0 +1,112 @@
+From 87e723cfed87955b7d23e0d2ea7bac61b57daf21 Mon Sep 17 00:00:00 2001
+Message-Id: <87e723cfed87955b7d23e0d2ea7bac61b57daf21@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:07:35 +0200
+Subject: [PATCH] vircgroup: introduce virCgroupV2(Set|Get)BlkioDeviceReadIops
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 862f630825a74a2605fca52bb66d8f04edefa75b)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <4afdb39491c625603a7b9963648d20148477cc33.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroupv2.c | 70 ++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 70 insertions(+)
+
+diff --git a/src/util/vircgroupv2.c b/src/util/vircgroupv2.c
+index 86b3fc127a..8cecc43f76 100644
+--- a/src/util/vircgroupv2.c
++++ b/src/util/vircgroupv2.c
+@@ -743,6 +743,74 @@ virCgroupV2GetBlkioDeviceWeight(virCgroupPtr group,
+ }
+ 
+ 
++static int
++virCgroupV2SetBlkioDeviceReadIops(virCgroupPtr group,
++                                  const char *path,
++                                  unsigned int riops)
++{
++    VIR_AUTOFREE(char *) str = NULL;
++    VIR_AUTOFREE(char *) blkstr = NULL;
++
++    if (!(blkstr = virCgroupGetBlockDevString(path)))
++        return -1;
++
++    if (riops == 0) {
++        if (virAsprintf(&str, "%sriops=max", blkstr) < 0)
++            return -1;
++    } else {
++        if (virAsprintf(&str, "%sriops=%u", blkstr, riops) < 0)
++            return -1;
++    }
++
++    return virCgroupSetValueStr(group,
++                                VIR_CGROUP_CONTROLLER_BLKIO,
++                                "io.max",
++                                str);
++}
++
++
++static int
++virCgroupV2GetBlkioDeviceReadIops(virCgroupPtr group,
++                                  const char *path,
++                                  unsigned int *riops)
++{
++    VIR_AUTOFREE(char *) str = NULL;
++    const char *name = "riops=";
++    char *tmp;
++
++    if (virCgroupGetValueForBlkDev(group,
++                                   VIR_CGROUP_CONTROLLER_BLKIO,
++                                   "io.max",
++                                   path,
++                                   &str) < 0) {
++        return -1;
++    }
++
++    if (!str) {
++        *riops = 0;
++    } else {
++        if (!(tmp = strstr(str, name))) {
++            virReportError(VIR_ERR_INTERNAL_ERROR,
++                           _("Unable to find '%s' limit for block device '%s'"),
++                           name, path);
++            return -1;
++        }
++        tmp += strlen(name);
++
++        if (STREQLEN(tmp, "max", 3)) {
++            *riops = 0;
++        } else if (virStrToLong_ui(tmp, NULL, 10, riops) < 0) {
++            virReportError(VIR_ERR_INTERNAL_ERROR,
++                           _("Unable to parse '%s' as an integer"),
++                           str);
++            return -1;
++        }
++    }
++
++    return 0;
++}
++
++
+ virCgroupBackend virCgroupV2Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V2,
+ 
+@@ -771,6 +839,8 @@ virCgroupBackend virCgroupV2Backend = {
+     .getBlkioIoDeviceServiced = virCgroupV2GetBlkioIoDeviceServiced,
+     .setBlkioDeviceWeight = virCgroupV2SetBlkioDeviceWeight,
+     .getBlkioDeviceWeight = virCgroupV2GetBlkioDeviceWeight,
++    .setBlkioDeviceReadIops = virCgroupV2SetBlkioDeviceReadIops,
++    .getBlkioDeviceReadIops = virCgroupV2GetBlkioDeviceReadIops,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-introduce-virCgroupV2-Set-Get-BlkioDeviceWeight.patch b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2-Set-Get-BlkioDeviceWeight.patch
new file mode 100644
index 0000000..a73e4a7
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2-Set-Get-BlkioDeviceWeight.patch
@@ -0,0 +1,93 @@
+From 39b7d11c4b75b3213054f7730887acca90f62969 Mon Sep 17 00:00:00 2001
+Message-Id: <39b7d11c4b75b3213054f7730887acca90f62969@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:07:34 +0200
+Subject: [PATCH] vircgroup: introduce virCgroupV2(Set|Get)BlkioDeviceWeight
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 568f746eafce1194dc10cc91a41c91bf08fadd53)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <5dd74b70bcec7b3cd7186b53e76857dcf1d21c6f.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroupv2.c | 51 ++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 51 insertions(+)
+
+diff --git a/src/util/vircgroupv2.c b/src/util/vircgroupv2.c
+index fcf39406e1..86b3fc127a 100644
+--- a/src/util/vircgroupv2.c
++++ b/src/util/vircgroupv2.c
+@@ -694,6 +694,55 @@ virCgroupV2GetBlkioIoDeviceServiced(virCgroupPtr group,
+ }
+ 
+ 
++static int
++virCgroupV2SetBlkioDeviceWeight(virCgroupPtr group,
++                                const char *path,
++                                unsigned int weight)
++{
++    VIR_AUTOFREE(char *) str = NULL;
++    VIR_AUTOFREE(char *) blkstr = NULL;
++
++    if (!(blkstr = virCgroupGetBlockDevString(path)))
++        return -1;
++
++    if (virAsprintf(&str, "%s%d", blkstr, weight) < 0)
++        return -1;
++
++    return virCgroupSetValueStr(group,
++                                VIR_CGROUP_CONTROLLER_BLKIO,
++                                "io.weight",
++                                str);
++}
++
++
++static int
++virCgroupV2GetBlkioDeviceWeight(virCgroupPtr group,
++                                const char *path,
++                                unsigned int *weight)
++{
++    VIR_AUTOFREE(char *) str = NULL;
++
++    if (virCgroupGetValueForBlkDev(group,
++                                   VIR_CGROUP_CONTROLLER_BLKIO,
++                                   "io.weight",
++                                   path,
++                                   &str) < 0) {
++        return -1;
++    }
++
++    if (!str) {
++        *weight = 0;
++    } else if (virStrToLong_ui(str, NULL, 10, weight) < 0) {
++        virReportError(VIR_ERR_INTERNAL_ERROR,
++                       _("Unable to parse '%s' as an integer"),
++                       str);
++        return -1;
++    }
++
++    return 0;
++}
++
++
+ virCgroupBackend virCgroupV2Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V2,
+ 
+@@ -720,6 +769,8 @@ virCgroupBackend virCgroupV2Backend = {
+     .getBlkioWeight = virCgroupV2GetBlkioWeight,
+     .getBlkioIoServiced = virCgroupV2GetBlkioIoServiced,
+     .getBlkioIoDeviceServiced = virCgroupV2GetBlkioIoDeviceServiced,
++    .setBlkioDeviceWeight = virCgroupV2SetBlkioDeviceWeight,
++    .getBlkioDeviceWeight = virCgroupV2GetBlkioDeviceWeight,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-introduce-virCgroupV2-Set-Get-BlkioDeviceWriteBps.patch b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2-Set-Get-BlkioDeviceWriteBps.patch
new file mode 100644
index 0000000..0012244
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2-Set-Get-BlkioDeviceWriteBps.patch
@@ -0,0 +1,112 @@
+From b5ce0e989440de2c3d4bfb8b325d85ca25ace4ca Mon Sep 17 00:00:00 2001
+Message-Id: <b5ce0e989440de2c3d4bfb8b325d85ca25ace4ca@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:07:38 +0200
+Subject: [PATCH] vircgroup: introduce virCgroupV2(Set|Get)BlkioDeviceWriteBps
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 91756fb64a370e48a6bcdd1973126a8c7a36e4f7)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <3d70ebb985fa8132e45ba12bbb8e78ac80557a78.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroupv2.c | 70 ++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 70 insertions(+)
+
+diff --git a/src/util/vircgroupv2.c b/src/util/vircgroupv2.c
+index b303e9cb10..52d31925c2 100644
+--- a/src/util/vircgroupv2.c
++++ b/src/util/vircgroupv2.c
+@@ -947,6 +947,74 @@ virCgroupV2GetBlkioDeviceReadBps(virCgroupPtr group,
+ }
+ 
+ 
++static int
++virCgroupV2SetBlkioDeviceWriteBps(virCgroupPtr group,
++                                  const char *path,
++                                  unsigned long long wbps)
++{
++    VIR_AUTOFREE(char *) str = NULL;
++    VIR_AUTOFREE(char *) blkstr = NULL;
++
++    if (!(blkstr = virCgroupGetBlockDevString(path)))
++        return -1;
++
++    if (wbps == 0) {
++        if (virAsprintf(&str, "%swbps=max", blkstr) < 0)
++            return -1;
++    } else {
++        if (virAsprintf(&str, "%swbps=%llu", blkstr, wbps) < 0)
++            return -1;
++    }
++
++    return virCgroupSetValueStr(group,
++                                VIR_CGROUP_CONTROLLER_BLKIO,
++                                "io.max",
++                                str);
++}
++
++
++static int
++virCgroupV2GetBlkioDeviceWriteBps(virCgroupPtr group,
++                                  const char *path,
++                                  unsigned long long *wbps)
++{
++    VIR_AUTOFREE(char *) str = NULL;
++    const char *name = "wbps=";
++    char *tmp;
++
++    if (virCgroupGetValueForBlkDev(group,
++                                   VIR_CGROUP_CONTROLLER_BLKIO,
++                                   "io.max",
++                                   path,
++                                   &str) < 0) {
++        return -1;
++    }
++
++    if (!str) {
++        *wbps = 0;
++    } else {
++        if (!(tmp = strstr(str, name))) {
++            virReportError(VIR_ERR_INTERNAL_ERROR,
++                           _("Unable to find '%s' limit for block device '%s'"),
++                           name, path);
++            return -1;
++        }
++        tmp += strlen(name);
++
++        if (STREQLEN(tmp, "max", 3)) {
++            *wbps = 0;
++        } else if (virStrToLong_ull(tmp, NULL, 10, wbps) < 0) {
++            virReportError(VIR_ERR_INTERNAL_ERROR,
++                           _("Unable to parse '%s' as an integer"),
++                           str);
++            return -1;
++        }
++    }
++
++    return 0;
++}
++
++
+ virCgroupBackend virCgroupV2Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V2,
+ 
+@@ -981,6 +1049,8 @@ virCgroupBackend virCgroupV2Backend = {
+     .getBlkioDeviceWriteIops = virCgroupV2GetBlkioDeviceWriteIops,
+     .setBlkioDeviceReadBps = virCgroupV2SetBlkioDeviceReadBps,
+     .getBlkioDeviceReadBps = virCgroupV2GetBlkioDeviceReadBps,
++    .setBlkioDeviceWriteBps = virCgroupV2SetBlkioDeviceWriteBps,
++    .getBlkioDeviceWriteBps = virCgroupV2GetBlkioDeviceWriteBps,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-introduce-virCgroupV2-Set-Get-BlkioDeviceWriteIops.patch b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2-Set-Get-BlkioDeviceWriteIops.patch
new file mode 100644
index 0000000..2d15aac
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2-Set-Get-BlkioDeviceWriteIops.patch
@@ -0,0 +1,112 @@
+From eca0f75e6f67ec9e445b90685143992b6929cef0 Mon Sep 17 00:00:00 2001
+Message-Id: <eca0f75e6f67ec9e445b90685143992b6929cef0@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:07:36 +0200
+Subject: [PATCH] vircgroup: introduce virCgroupV2(Set|Get)BlkioDeviceWriteIops
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 438587033bdaf714238a98703c9efc7b0dada51f)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <7937bd2aa5da315f8351e3f312f5aee71b682c30.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroupv2.c | 70 ++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 70 insertions(+)
+
+diff --git a/src/util/vircgroupv2.c b/src/util/vircgroupv2.c
+index 8cecc43f76..1d25c0ae1f 100644
+--- a/src/util/vircgroupv2.c
++++ b/src/util/vircgroupv2.c
+@@ -811,6 +811,74 @@ virCgroupV2GetBlkioDeviceReadIops(virCgroupPtr group,
+ }
+ 
+ 
++static int
++virCgroupV2SetBlkioDeviceWriteIops(virCgroupPtr group,
++                                   const char *path,
++                                   unsigned int wiops)
++{
++    VIR_AUTOFREE(char *) str = NULL;
++    VIR_AUTOFREE(char *) blkstr = NULL;
++
++    if (!(blkstr = virCgroupGetBlockDevString(path)))
++        return -1;
++
++    if (wiops == 0) {
++        if (virAsprintf(&str, "%swiops=max", blkstr) < 0)
++            return -1;
++    } else {
++        if (virAsprintf(&str, "%swiops=%u", blkstr, wiops) < 0)
++            return -1;
++    }
++
++    return virCgroupSetValueStr(group,
++                                VIR_CGROUP_CONTROLLER_BLKIO,
++                                "io.max",
++                                str);
++}
++
++
++static int
++virCgroupV2GetBlkioDeviceWriteIops(virCgroupPtr group,
++                                   const char *path,
++                                   unsigned int *wiops)
++{
++    VIR_AUTOFREE(char *) str = NULL;
++    const char *name = "wiops=";
++    char *tmp;
++
++    if (virCgroupGetValueForBlkDev(group,
++                                   VIR_CGROUP_CONTROLLER_BLKIO,
++                                   "io.max",
++                                   path,
++                                   &str) < 0) {
++        return -1;
++    }
++
++    if (!str) {
++        *wiops = 0;
++    } else {
++        if (!(tmp = strstr(str, name))) {
++            virReportError(VIR_ERR_INTERNAL_ERROR,
++                           _("Unable to find '%s' limit for block device '%s'"),
++                           name, path);
++            return -1;
++        }
++        tmp += strlen(name);
++
++        if (STREQLEN(tmp, "max", 3)) {
++            *wiops = 0;
++        } else if (virStrToLong_ui(tmp, NULL, 10, wiops) < 0) {
++            virReportError(VIR_ERR_INTERNAL_ERROR,
++                           _("Unable to parse '%s' as an integer"),
++                           str);
++            return -1;
++        }
++    }
++
++    return 0;
++}
++
++
+ virCgroupBackend virCgroupV2Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V2,
+ 
+@@ -841,6 +909,8 @@ virCgroupBackend virCgroupV2Backend = {
+     .getBlkioDeviceWeight = virCgroupV2GetBlkioDeviceWeight,
+     .setBlkioDeviceReadIops = virCgroupV2SetBlkioDeviceReadIops,
+     .getBlkioDeviceReadIops = virCgroupV2GetBlkioDeviceReadIops,
++    .setBlkioDeviceWriteIops = virCgroupV2SetBlkioDeviceWriteIops,
++    .getBlkioDeviceWriteIops = virCgroupV2GetBlkioDeviceWriteIops,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-introduce-virCgroupV2-Set-Get-BlkioWeight.patch b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2-Set-Get-BlkioWeight.patch
new file mode 100644
index 0000000..755c0a1
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2-Set-Get-BlkioWeight.patch
@@ -0,0 +1,91 @@
+From ba7babc00b91a08c7c62858b6c34f1f0c77af0ce Mon Sep 17 00:00:00 2001
+Message-Id: <ba7babc00b91a08c7c62858b6c34f1f0c77af0ce@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:07:31 +0200
+Subject: [PATCH] vircgroup: introduce virCgroupV2(Set|Get)BlkioWeight
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 11bb7f1561be311b71f3899332dfabe61c55a793)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <8e485d7c092d35f80e10da00af74fd30554b43bf.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroupv2.c | 49 ++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 49 insertions(+)
+
+diff --git a/src/util/vircgroupv2.c b/src/util/vircgroupv2.c
+index 27519d80e3..f7863a5690 100644
+--- a/src/util/vircgroupv2.c
++++ b/src/util/vircgroupv2.c
+@@ -521,6 +521,52 @@ virCgroupV2SetOwner(virCgroupPtr cgroup,
+ }
+ 
+ 
++static int
++virCgroupV2SetBlkioWeight(virCgroupPtr group,
++                          unsigned int weight)
++{
++    VIR_AUTOFREE(char *) value = NULL;
++
++    if (virAsprintf(&value, "default %u", weight) < 0)
++        return -1;
++
++    return virCgroupSetValueStr(group,
++                                VIR_CGROUP_CONTROLLER_BLKIO,
++                                "io.weight",
++                                value);
++}
++
++
++static int
++virCgroupV2GetBlkioWeight(virCgroupPtr group,
++                          unsigned int *weight)
++{
++    VIR_AUTOFREE(char *) value = NULL;
++    char *tmp;
++
++    if (virCgroupGetValueStr(group, VIR_CGROUP_CONTROLLER_BLKIO,
++                             "io.weight", &value) < 0) {
++        return -1;
++    }
++
++    if (!(tmp = strstr(value, "default "))) {
++        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
++                       _("Cannot find default io weight."));
++        return -1;
++    }
++    tmp += strlen("default ");
++
++    if (virStrToLong_ui(tmp, NULL, 10, weight) < 0) {
++        virReportError(VIR_ERR_INTERNAL_ERROR,
++                       _("Unable to parse '%s' as an integer"),
++                       tmp);
++        return -1;
++    }
++
++    return 0;
++}
++
++
+ virCgroupBackend virCgroupV2Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V2,
+ 
+@@ -542,6 +588,9 @@ virCgroupBackend virCgroupV2Backend = {
+     .hasEmptyTasks = virCgroupV2HasEmptyTasks,
+     .bindMount = virCgroupV2BindMount,
+     .setOwner = virCgroupV2SetOwner,
++
++    .setBlkioWeight = virCgroupV2SetBlkioWeight,
++    .getBlkioWeight = virCgroupV2GetBlkioWeight,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-introduce-virCgroupV2-Set-Get-CpuCfsPeriod.patch b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2-Set-Get-CpuCfsPeriod.patch
new file mode 100644
index 0000000..bfece79
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2-Set-Get-CpuCfsPeriod.patch
@@ -0,0 +1,116 @@
+From 05610561d752380d3f75780056fea927d723b53b Mon Sep 17 00:00:00 2001
+Message-Id: <05610561d752380d3f75780056fea927d723b53b@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:07:47 +0200
+Subject: [PATCH] vircgroup: introduce virCgroupV2(Set|Get)CpuCfsPeriod
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+In order to set CPU cfs period using cgroup v2 'cpu.max' interface
+we need to load the current value of CPU cfs quota first because
+format of 'cpu.max' interface is '$quota $period' and in order to
+change 'period' we need to write 'quota' as well.  Writing only one
+number changes only 'quota'.
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 832422457214421211304bfb0c92b00546dcec53)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <21d457977390fd50b26a2ea5f7f904946578accb.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroupv2.c | 68 ++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 68 insertions(+)
+
+diff --git a/src/util/vircgroupv2.c b/src/util/vircgroupv2.c
+index cb9dd3d8e8..876785e4e1 100644
+--- a/src/util/vircgroupv2.c
++++ b/src/util/vircgroupv2.c
+@@ -1325,6 +1325,72 @@ virCgroupV2GetCpuShares(virCgroupPtr group,
+ }
+ 
+ 
++static int
++virCgroupV2SetCpuCfsPeriod(virCgroupPtr group,
++                           unsigned long long cfs_period)
++{
++    VIR_AUTOFREE(char *) value = NULL;
++    VIR_AUTOFREE(char *) str = NULL;
++    char *tmp;
++
++    /* The cfs_period should be greater or equal than 1ms, and less or equal
++     * than 1s.
++     */
++    if (cfs_period < 1000 || cfs_period > 1000000) {
++        virReportError(VIR_ERR_INVALID_ARG,
++                       _("cfs_period '%llu' must be in range (1000, 1000000)"),
++                       cfs_period);
++        return -1;
++    }
++
++    if (virCgroupGetValueStr(group, VIR_CGROUP_CONTROLLER_CPU,
++                             "cpu.max", &str) < 0) {
++        return -1;
++    }
++
++    if (!(tmp = strchr(str, ' '))) {
++        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
++                       _("Invalid 'cpu.max' data."));
++        return -1;
++    }
++    *tmp = '\n';
++
++    if (virAsprintf(&value, "%s %llu", str, cfs_period) < 0)
++        return -1;
++
++    return virCgroupSetValueStr(group, VIR_CGROUP_CONTROLLER_CPU,
++                                "cpu.max", value);
++}
++
++
++static int
++virCgroupV2GetCpuCfsPeriod(virCgroupPtr group,
++                           unsigned long long *cfs_period)
++{
++    VIR_AUTOFREE(char *) str = NULL;
++    char *tmp;
++
++    if (virCgroupGetValueStr(group, VIR_CGROUP_CONTROLLER_CPU,
++                             "cpu.max", &str) < 0) {
++        return -1;
++    }
++
++    if (!(tmp = strchr(str, ' '))) {
++        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
++                       _("Invalid 'cpu.max' data."));
++        return -1;
++    }
++
++    if (virStrToLong_ull(tmp, NULL, 10, cfs_period) < 0) {
++        virReportError(VIR_ERR_INTERNAL_ERROR,
++                       _("Failed to parse value '%s' from cpu.max."), str);
++        return -1;
++    }
++
++    return 0;
++}
++
++
+ virCgroupBackend virCgroupV2Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V2,
+ 
+@@ -1375,6 +1441,8 @@ virCgroupBackend virCgroupV2Backend = {
+ 
+     .setCpuShares = virCgroupV2SetCpuShares,
+     .getCpuShares = virCgroupV2GetCpuShares,
++    .setCpuCfsPeriod = virCgroupV2SetCpuCfsPeriod,
++    .getCpuCfsPeriod = virCgroupV2GetCpuCfsPeriod,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-introduce-virCgroupV2-Set-Get-CpuCfsQuota.patch b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2-Set-Get-CpuCfsQuota.patch
new file mode 100644
index 0000000..118afd2
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2-Set-Get-CpuCfsQuota.patch
@@ -0,0 +1,94 @@
+From 518ed664601680039546889ea3ebb9a957f26e16 Mon Sep 17 00:00:00 2001
+Message-Id: <518ed664601680039546889ea3ebb9a957f26e16@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:07:48 +0200
+Subject: [PATCH] vircgroup: introduce virCgroupV2(Set|Get)CpuCfsQuota
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 8e2c887ffa552b59a3dd80fa73ee60791c960565)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <7fe344c65f7394026a2d9feb45920cd177f5f71c.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroupv2.c | 52 ++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 52 insertions(+)
+
+diff --git a/src/util/vircgroupv2.c b/src/util/vircgroupv2.c
+index 876785e4e1..a0a7e55493 100644
+--- a/src/util/vircgroupv2.c
++++ b/src/util/vircgroupv2.c
+@@ -1391,6 +1391,56 @@ virCgroupV2GetCpuCfsPeriod(virCgroupPtr group,
+ }
+ 
+ 
++static int
++virCgroupV2SetCpuCfsQuota(virCgroupPtr group,
++                          long long cfs_quota)
++{
++    /* The cfs_quota should be greater or equal than 1ms */
++    if (cfs_quota >= 0 &&
++        (cfs_quota < 1000 ||
++         cfs_quota > ULLONG_MAX / 1000)) {
++        virReportError(VIR_ERR_INVALID_ARG,
++                       _("cfs_quota '%lld' must be in range (1000, %llu)"),
++                       cfs_quota, ULLONG_MAX / 1000);
++        return -1;
++    }
++
++    if (cfs_quota == ULLONG_MAX / 1000) {
++        return virCgroupSetValueStr(group,
++                                    VIR_CGROUP_CONTROLLER_CPU,
++                                    "cpu.max", "max");
++    }
++
++    return virCgroupSetValueI64(group,
++                                VIR_CGROUP_CONTROLLER_CPU,
++                                "cpu.max", cfs_quota);
++}
++
++
++static int
++virCgroupV2GetCpuCfsQuota(virCgroupPtr group,
++                          long long *cfs_quota)
++{
++    VIR_AUTOFREE(char *) str = NULL;
++
++    if (virCgroupGetValueStr(group, VIR_CGROUP_CONTROLLER_CPU,
++                             "cpu.max", &str) < 0) {
++        return -1;
++    }
++
++    if (STREQLEN(str, "max", 3))
++        *cfs_quota = ULLONG_MAX / 1000;
++
++    if (virStrToLong_ll(str, NULL, 10, cfs_quota) < 0) {
++        virReportError(VIR_ERR_INTERNAL_ERROR,
++                       _("Failed to parse value '%s' from cpu.max."), str);
++        return -1;
++    }
++
++    return 0;
++}
++
++
+ virCgroupBackend virCgroupV2Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V2,
+ 
+@@ -1443,6 +1493,8 @@ virCgroupBackend virCgroupV2Backend = {
+     .getCpuShares = virCgroupV2GetCpuShares,
+     .setCpuCfsPeriod = virCgroupV2SetCpuCfsPeriod,
+     .getCpuCfsPeriod = virCgroupV2GetCpuCfsPeriod,
++    .setCpuCfsQuota = virCgroupV2SetCpuCfsQuota,
++    .getCpuCfsQuota = virCgroupV2GetCpuCfsQuota,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-introduce-virCgroupV2-Set-Get-CpuShares.patch b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2-Set-Get-CpuShares.patch
new file mode 100644
index 0000000..16317e9
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2-Set-Get-CpuShares.patch
@@ -0,0 +1,65 @@
+From aa652c60bb88208f8a73b8d5ae87eab7cb24d23c Mon Sep 17 00:00:00 2001
+Message-Id: <aa652c60bb88208f8a73b8d5ae87eab7cb24d23c@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:07:46 +0200
+Subject: [PATCH] vircgroup: introduce virCgroupV2(Set|Get)CpuShares
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit b8ca5afc22b4d3af3c8637573f1c3d12887fbb0a)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <5b6c973caaa4b82333949366f034eccaec24277c.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroupv2.c | 23 +++++++++++++++++++++++
+ 1 file changed, 23 insertions(+)
+
+diff --git a/src/util/vircgroupv2.c b/src/util/vircgroupv2.c
+index 8d184bd963..cb9dd3d8e8 100644
+--- a/src/util/vircgroupv2.c
++++ b/src/util/vircgroupv2.c
+@@ -1305,6 +1305,26 @@ virCgroupV2GetMemSwapUsage(virCgroupPtr group,
+ }
+ 
+ 
++static int
++virCgroupV2SetCpuShares(virCgroupPtr group,
++                        unsigned long long shares)
++{
++    return virCgroupSetValueU64(group,
++                                VIR_CGROUP_CONTROLLER_CPU,
++                                "cpu.weight", shares);
++}
++
++
++static int
++virCgroupV2GetCpuShares(virCgroupPtr group,
++                        unsigned long long *shares)
++{
++    return virCgroupGetValueU64(group,
++                                VIR_CGROUP_CONTROLLER_CPU,
++                                "cpu.weight", shares);
++}
++
++
+ virCgroupBackend virCgroupV2Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V2,
+ 
+@@ -1352,6 +1372,9 @@ virCgroupBackend virCgroupV2Backend = {
+     .setMemSwapHardLimit = virCgroupV2SetMemSwapHardLimit,
+     .getMemSwapHardLimit = virCgroupV2GetMemSwapHardLimit,
+     .getMemSwapUsage = virCgroupV2GetMemSwapUsage,
++
++    .setCpuShares = virCgroupV2SetCpuShares,
++    .getCpuShares = virCgroupV2GetCpuShares,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-introduce-virCgroupV2-Set-Get-MemSwapHardLimit.patch b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2-Set-Get-MemSwapHardLimit.patch
new file mode 100644
index 0000000..cfdad31
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2-Set-Get-MemSwapHardLimit.patch
@@ -0,0 +1,104 @@
+From 86212853c9f16bbed77c2310aed1795fdb04f59d Mon Sep 17 00:00:00 2001
+Message-Id: <86212853c9f16bbed77c2310aed1795fdb04f59d@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:07:44 +0200
+Subject: [PATCH] vircgroup: introduce virCgroupV2(Set|Get)MemSwapHardLimit
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit df63fd1f8f17354c5f81c991ff1bb7d12f96d986)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <39af05bcaea91a81740ba6d0b766f773f0e8580b.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroupv2.c | 62 ++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 62 insertions(+)
+
+diff --git a/src/util/vircgroupv2.c b/src/util/vircgroupv2.c
+index d8a1d7712f..fed6792e16 100644
+--- a/src/util/vircgroupv2.c
++++ b/src/util/vircgroupv2.c
+@@ -1230,6 +1230,66 @@ virCgroupV2GetMemorySoftLimit(virCgroupPtr group,
+ }
+ 
+ 
++static int
++virCgroupV2SetMemSwapHardLimit(virCgroupPtr group,
++                               unsigned long long kb)
++{
++    unsigned long long maxkb = VIR_DOMAIN_MEMORY_PARAM_UNLIMITED;
++
++    if (kb > maxkb) {
++        virReportError(VIR_ERR_INVALID_ARG,
++                       _("Memory '%llu' must be less than %llu"),
++                       kb, maxkb);
++        return -1;
++    }
++
++    if (kb == maxkb) {
++        return virCgroupSetValueStr(group,
++                                    VIR_CGROUP_CONTROLLER_MEMORY,
++                                    "memory.swap.max",
++                                    "max");
++    } else {
++        return virCgroupSetValueU64(group,
++                                    VIR_CGROUP_CONTROLLER_MEMORY,
++                                    "memory.swap.max",
++                                    kb << 10);
++    }
++}
++
++
++static int
++virCgroupV2GetMemSwapHardLimit(virCgroupPtr group,
++                               unsigned long long *kb)
++{
++    VIR_AUTOFREE(char *) value = NULL;
++    unsigned long long max;
++
++    if (virCgroupGetValueStr(group,
++                             VIR_CGROUP_CONTROLLER_MEMORY,
++                             "memory.swap.max", &value) < 0) {
++        return -1;
++    }
++
++    if (STREQ(value, "max")) {
++        *kb = VIR_DOMAIN_MEMORY_PARAM_UNLIMITED;
++        return 0;
++    }
++
++    if (virStrToLong_ull(value, NULL, 10, &max) < 0) {
++        virReportError(VIR_ERR_INTERNAL_ERROR,
++                       _("Failed to parse value '%s' as number."),
++                       value);
++        return -1;
++    }
++
++    *kb = max >> 10;
++    if (*kb >= VIR_DOMAIN_MEMORY_PARAM_UNLIMITED)
++        *kb = VIR_DOMAIN_MEMORY_PARAM_UNLIMITED;
++
++    return 0;
++}
++
++
+ virCgroupBackend virCgroupV2Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V2,
+ 
+@@ -1274,6 +1334,8 @@ virCgroupBackend virCgroupV2Backend = {
+     .getMemoryHardLimit = virCgroupV2GetMemoryHardLimit,
+     .setMemorySoftLimit = virCgroupV2SetMemorySoftLimit,
+     .getMemorySoftLimit = virCgroupV2GetMemorySoftLimit,
++    .setMemSwapHardLimit = virCgroupV2SetMemSwapHardLimit,
++    .getMemSwapHardLimit = virCgroupV2GetMemSwapHardLimit,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-introduce-virCgroupV2-Set-Get-MemoryHardLimit.patch b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2-Set-Get-MemoryHardLimit.patch
new file mode 100644
index 0000000..ea250c2
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2-Set-Get-MemoryHardLimit.patch
@@ -0,0 +1,85 @@
+From d9dca0b3b1ad64bcde8d96b05538d4656ca93af3 Mon Sep 17 00:00:00 2001
+Message-Id: <d9dca0b3b1ad64bcde8d96b05538d4656ca93af3@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:07:42 +0200
+Subject: [PATCH] vircgroup: introduce virCgroupV2(Set|Get)MemoryHardLimit
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 2aa5385c58d50270d7084f8d11a22ac993275dc0)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <dc9320d118699dc39071dc1f15b1094112cf5a04.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroupv2.c | 43 ++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 43 insertions(+)
+
+diff --git a/src/util/vircgroupv2.c b/src/util/vircgroupv2.c
+index 87d357b0a7..81a577d28f 100644
+--- a/src/util/vircgroupv2.c
++++ b/src/util/vircgroupv2.c
+@@ -1130,6 +1130,47 @@ virCgroupV2GetMemoryUsage(virCgroupPtr group,
+ }
+ 
+ 
++static int
++virCgroupV2SetMemoryHardLimit(virCgroupPtr group,
++                              unsigned long long kb)
++{
++    return virCgroupV2SetMemory(group, kb);
++}
++
++
++static int
++virCgroupV2GetMemoryHardLimit(virCgroupPtr group,
++                              unsigned long long *kb)
++{
++    VIR_AUTOFREE(char *) value = NULL;
++    unsigned long long max;
++
++    if (virCgroupGetValueStr(group,
++                             VIR_CGROUP_CONTROLLER_MEMORY,
++                             "memory.max", &value) < 0) {
++        return -1;
++    }
++
++    if (STREQ(value, "max")) {
++        *kb = VIR_DOMAIN_MEMORY_PARAM_UNLIMITED;
++        return 0;
++    }
++
++    if (virStrToLong_ull(value, NULL, 10, &max) < 0) {
++        virReportError(VIR_ERR_INTERNAL_ERROR,
++                       _("Failed to parse value '%s' as number."),
++                       value);
++        return -1;
++    }
++
++    *kb = max >> 10;
++    if (*kb >= VIR_DOMAIN_MEMORY_PARAM_UNLIMITED)
++        *kb = VIR_DOMAIN_MEMORY_PARAM_UNLIMITED;
++
++    return 0;
++}
++
++
+ virCgroupBackend virCgroupV2Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V2,
+ 
+@@ -1170,6 +1211,8 @@ virCgroupBackend virCgroupV2Backend = {
+     .setMemory = virCgroupV2SetMemory,
+     .getMemoryStat = virCgroupV2GetMemoryStat,
+     .getMemoryUsage = virCgroupV2GetMemoryUsage,
++    .setMemoryHardLimit = virCgroupV2SetMemoryHardLimit,
++    .getMemoryHardLimit = virCgroupV2GetMemoryHardLimit,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-introduce-virCgroupV2-Set-Get-MemorySoftLimit.patch b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2-Set-Get-MemorySoftLimit.patch
new file mode 100644
index 0000000..294f6e6
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2-Set-Get-MemorySoftLimit.patch
@@ -0,0 +1,103 @@
+From 6a1f3fdcf13ff1fdcbd1f63443a1e5d05b2ddd1c Mon Sep 17 00:00:00 2001
+Message-Id: <6a1f3fdcf13ff1fdcbd1f63443a1e5d05b2ddd1c@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:07:43 +0200
+Subject: [PATCH] vircgroup: introduce virCgroupV2(Set|Get)MemorySoftLimit
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 94db4bf86ea10e9853f62c4ea079a432482a58df)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <a59c442f9098898c0196a5fb2a0d3527ce277153.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroupv2.c | 61 ++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 61 insertions(+)
+
+diff --git a/src/util/vircgroupv2.c b/src/util/vircgroupv2.c
+index 81a577d28f..d8a1d7712f 100644
+--- a/src/util/vircgroupv2.c
++++ b/src/util/vircgroupv2.c
+@@ -1171,6 +1171,65 @@ virCgroupV2GetMemoryHardLimit(virCgroupPtr group,
+ }
+ 
+ 
++static int
++virCgroupV2SetMemorySoftLimit(virCgroupPtr group,
++                              unsigned long long kb)
++{
++    unsigned long long maxkb = VIR_DOMAIN_MEMORY_PARAM_UNLIMITED;
++
++    if (kb > maxkb) {
++        virReportError(VIR_ERR_INVALID_ARG,
++                       _("Memory '%llu' must be less than %llu"),
++                       kb, maxkb);
++        return -1;
++    }
++
++    if (kb == maxkb) {
++        return virCgroupSetValueStr(group,
++                                    VIR_CGROUP_CONTROLLER_MEMORY,
++                                    "memory.high",
++                                    "max");
++    } else {
++        return virCgroupSetValueU64(group,
++                                    VIR_CGROUP_CONTROLLER_MEMORY,
++                                    "memory.high",
++                                    kb << 10);
++    }
++}
++
++
++static int
++virCgroupV2GetMemorySoftLimit(virCgroupPtr group,
++                              unsigned long long *kb)
++{
++    VIR_AUTOFREE(char *) value = NULL;
++    unsigned long long high;
++
++    if (virCgroupGetValueStr(group,
++                             VIR_CGROUP_CONTROLLER_MEMORY,
++                             "memory.high", &value) < 0)
++        return -1;
++
++    if (STREQ(value, "max")) {
++        *kb = VIR_DOMAIN_MEMORY_PARAM_UNLIMITED;
++        return 0;
++    }
++
++    if (virStrToLong_ull(value, NULL, 10, &high) < 0) {
++        virReportError(VIR_ERR_INTERNAL_ERROR,
++                       _("Failed to parse value '%s' as number."),
++                       value);
++        return -1;
++    }
++
++    *kb = high >> 10;
++    if (*kb >= VIR_DOMAIN_MEMORY_PARAM_UNLIMITED)
++        *kb = VIR_DOMAIN_MEMORY_PARAM_UNLIMITED;
++
++    return 0;
++}
++
++
+ virCgroupBackend virCgroupV2Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V2,
+ 
+@@ -1213,6 +1272,8 @@ virCgroupBackend virCgroupV2Backend = {
+     .getMemoryUsage = virCgroupV2GetMemoryUsage,
+     .setMemoryHardLimit = virCgroupV2SetMemoryHardLimit,
+     .getMemoryHardLimit = virCgroupV2GetMemoryHardLimit,
++    .setMemorySoftLimit = virCgroupV2SetMemorySoftLimit,
++    .getMemorySoftLimit = virCgroupV2GetMemorySoftLimit,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-introduce-virCgroupV2AddTask.patch b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2AddTask.patch
new file mode 100644
index 0000000..8d2d50f
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2AddTask.patch
@@ -0,0 +1,67 @@
+From cb154a1d153edf2c399493a4336aebdccdc628f5 Mon Sep 17 00:00:00 2001
+Message-Id: <cb154a1d153edf2c399493a4336aebdccdc628f5@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:07:27 +0200
+Subject: [PATCH] vircgroup: introduce virCgroupV2AddTask
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+In cgroups v2 we need to handle threads and processes differently.
+If you need to move a process you need to write its pid into
+cgrou.procs file and it will move the process with all its threads
+as well.  The whole process will be moved if you use tid of any thread.
+
+In order to move only threads at first we need to create threaded group
+and after that we can write the relevant thread tids into cgroup.threads
+file.  Threads can be moved only into cgroups that are children of
+cgroup of its process.
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 48572f8825f2bbd7dabb5afb34efbf7afa2f7302)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <d6fb582c80903fc7725e2dd15165bd167c916f04.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroupv2.c | 15 +++++++++++++++
+ 1 file changed, 15 insertions(+)
+
+diff --git a/src/util/vircgroupv2.c b/src/util/vircgroupv2.c
+index b5fad47ca0..6ffb5ce786 100644
+--- a/src/util/vircgroupv2.c
++++ b/src/util/vircgroupv2.c
+@@ -432,6 +432,20 @@ virCgroupV2Remove(virCgroupPtr group)
+ }
+ 
+ 
++static int
++virCgroupV2AddTask(virCgroupPtr group,
++                   pid_t pid,
++                   unsigned int flags)
++{
++    int controller = virCgroupV2GetAnyController(group);
++
++    if (flags & VIR_CGROUP_TASK_THREAD)
++        return virCgroupSetValueI64(group, controller, "cgroup.threads", pid);
++    else
++        return virCgroupSetValueI64(group, controller, "cgroup.procs", pid);
++}
++
++
+ virCgroupBackend virCgroupV2Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V2,
+ 
+@@ -449,6 +463,7 @@ virCgroupBackend virCgroupV2Backend = {
+     .pathOfController = virCgroupV2PathOfController,
+     .makeGroup = virCgroupV2MakeGroup,
+     .remove = virCgroupV2Remove,
++    .addTask = virCgroupV2AddTask,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-introduce-virCgroupV2Available.patch b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2Available.patch
new file mode 100644
index 0000000..db453d3
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2Available.patch
@@ -0,0 +1,116 @@
+From 4551f704f56b289735ed17f3b9ee0f9663183d09 Mon Sep 17 00:00:00 2001
+Message-Id: <4551f704f56b289735ed17f3b9ee0f9663183d09@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:07:13 +0200
+Subject: [PATCH] vircgroup: introduce virCgroupV2Available
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+We cannot detect only mount points to figure out whether cgroup v2
+is available because systemd uses cgroup v2 for process tracking and
+all controllers are mounted as cgroup v1 controllers.
+
+To make sure that this is no the situation we need to check
+'cgroup.controllers' file if it's not empty to make sure that cgroup
+v2 is not mounted only for process tracking.
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 034ef217d73aa240340dd22590402bb9636648b5)
+
+Conflicts:
+    src/util/vircgroupv2.c: missing commit c0abcca417
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <46bcb2f86e4ca5f029f67be5385770d725ef5c42.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroupv2.c | 51 ++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 51 insertions(+)
+
+diff --git a/src/util/vircgroupv2.c b/src/util/vircgroupv2.c
+index 23bf81dae2..4ab9f2b792 100644
+--- a/src/util/vircgroupv2.c
++++ b/src/util/vircgroupv2.c
+@@ -19,16 +19,23 @@
+  */
+ #include <config.h>
+ 
++#ifdef __linux__
++# include <mntent.h>
++#endif /* __linux__ */
++
+ #include "internal.h"
+ 
+ #define __VIR_CGROUP_ALLOW_INCLUDE_PRIV_H__
+ #include "vircgrouppriv.h"
+ #undef __VIR_CGROUP_ALLOW_INCLUDE_PRIV_H__
+ 
++#include "viralloc.h"
+ #include "vircgroup.h"
+ #include "vircgroupbackend.h"
+ #include "vircgroupv2.h"
++#include "virfile.h"
+ #include "virlog.h"
++#include "virstring.h"
+ 
+ VIR_LOG_INIT("util.cgroup");
+ 
+@@ -41,8 +48,52 @@ VIR_ENUM_IMPL(virCgroupV2Controller, VIR_CGROUP_CONTROLLER_LAST,
+ 
+ #ifdef __linux__
+ 
++/* We're looking for one 'cgroup2' fs mount which has some
++ * controllers enabled. */
++static bool
++virCgroupV2Available(void)
++{
++    bool ret = false;
++    FILE *mounts = NULL;
++    struct mntent entry;
++    char buf[CGROUP_MAX_VAL];
++
++    if (!(mounts = fopen("/proc/mounts", "r")))
++        return false;
++
++    while (getmntent_r(mounts, &entry, buf, sizeof(buf)) != NULL) {
++        VIR_AUTOFREE(char *) contFile = NULL;
++        VIR_AUTOFREE(char *) contStr = NULL;
++
++        if (STRNEQ(entry.mnt_type, "cgroup2"))
++            continue;
++
++        /* Systemd uses cgroup v2 for process tracking but no controller is
++         * available. We should consider this configuration as cgroup v2 is
++         * not available. */
++        if (virAsprintf(&contFile, "%s/cgroup.controllers", entry.mnt_dir) < 0)
++            goto cleanup;
++
++        if (virFileReadAll(contFile, 1024 * 1024, &contStr) < 0)
++            goto cleanup;
++
++        if (STREQ(contStr, ""))
++            continue;
++
++        ret = true;
++        break;
++    }
++
++ cleanup:
++    VIR_FORCE_FCLOSE(mounts);
++    return ret;
++}
++
++
+ virCgroupBackend virCgroupV2Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V2,
++
++    .available = virCgroupV2Available,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-introduce-virCgroupV2BindMount.patch b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2BindMount.patch
new file mode 100644
index 0000000..a9373eb
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2BindMount.patch
@@ -0,0 +1,83 @@
+From 583928aa5c4d1b28304aa6484ad20cd2036407ae Mon Sep 17 00:00:00 2001
+Message-Id: <583928aa5c4d1b28304aa6484ad20cd2036407ae@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:07:29 +0200
+Subject: [PATCH] vircgroup: introduce virCgroupV2BindMount
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit cda8ed0646d82f95d4424cfadfb9233037b1d815)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <c99f93d93fe7a944219b860a2a76b18303c27479.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroupv2.c | 34 ++++++++++++++++++++++++++++++++++
+ 1 file changed, 34 insertions(+)
+
+diff --git a/src/util/vircgroupv2.c b/src/util/vircgroupv2.c
+index 074e6ec110..90ce660908 100644
+--- a/src/util/vircgroupv2.c
++++ b/src/util/vircgroupv2.c
+@@ -21,6 +21,7 @@
+ 
+ #ifdef __linux__
+ # include <mntent.h>
++# include <sys/mount.h>
+ #endif /* __linux__ */
+ 
+ #include "internal.h"
+@@ -462,6 +463,38 @@ virCgroupV2HasEmptyTasks(virCgroupPtr cgroup,
+ }
+ 
+ 
++static int
++virCgroupV2BindMount(virCgroupPtr group,
++                     const char *oldroot,
++                     const char *mountopts)
++{
++    VIR_AUTOFREE(char *) opts = NULL;
++    VIR_AUTOFREE(char *) src = NULL;
++
++    VIR_DEBUG("Mounting cgroups at '%s'", group->unified.mountPoint);
++
++    if (virFileMakePath(group->unified.mountPoint) < 0) {
++        virReportSystemError(errno, _("Unable to create directory %s"),
++                             group->unified.mountPoint);
++        return -1;
++    }
++
++    if (virAsprintf(&opts, "mode=755,size=65536%s", mountopts) < 0)
++        return -1;
++
++    if (virAsprintf(&src, "%s%s", oldroot, group->unified.mountPoint) < 0)
++        return -1;
++
++    if (mount(src, group->unified.mountPoint, "none", MS_BIND, NULL) < 0) {
++        virReportSystemError(errno, _("Failed to bind cgroup '%s' on '%s'"),
++                             src, group->unified.mountPoint);
++        return -1;
++    }
++
++    return 0;
++}
++
++
+ virCgroupBackend virCgroupV2Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V2,
+ 
+@@ -481,6 +514,7 @@ virCgroupBackend virCgroupV2Backend = {
+     .remove = virCgroupV2Remove,
+     .addTask = virCgroupV2AddTask,
+     .hasEmptyTasks = virCgroupV2HasEmptyTasks,
++    .bindMount = virCgroupV2BindMount,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-introduce-virCgroupV2CopyMounts.patch b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2CopyMounts.patch
new file mode 100644
index 0000000..334d251
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2CopyMounts.patch
@@ -0,0 +1,49 @@
+From 5429c3dfd57da26b6d6fd6368bc88d695ea2e852 Mon Sep 17 00:00:00 2001
+Message-Id: <5429c3dfd57da26b6d6fd6368bc88d695ea2e852@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:07:15 +0200
+Subject: [PATCH] vircgroup: introduce virCgroupV2CopyMounts
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 38a3fb56471d77102f58f19a1e68d3fb372e5cb0)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <67863a638cc2666f1f2f8e7151125c32952aa247.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroupv2.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/src/util/vircgroupv2.c b/src/util/vircgroupv2.c
+index 02dc4e4686..5d3c80b309 100644
+--- a/src/util/vircgroupv2.c
++++ b/src/util/vircgroupv2.c
+@@ -132,11 +132,20 @@ virCgroupV2ValidateMachineGroup(virCgroupPtr group,
+ }
+ 
+ 
++static int
++virCgroupV2CopyMounts(virCgroupPtr group,
++                      virCgroupPtr parent)
++{
++    return VIR_STRDUP(group->unified.mountPoint, parent->unified.mountPoint);
++}
++
++
+ virCgroupBackend virCgroupV2Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V2,
+ 
+     .available = virCgroupV2Available,
+     .validateMachineGroup = virCgroupV2ValidateMachineGroup,
++    .copyMounts = virCgroupV2CopyMounts,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-introduce-virCgroupV2CopyPlacement.patch b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2CopyPlacement.patch
new file mode 100644
index 0000000..c2b9e4a
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2CopyPlacement.patch
@@ -0,0 +1,68 @@
+From 1cabfada0f1a83ae78b6a7dbb9128512369fd6f4 Mon Sep 17 00:00:00 2001
+Message-Id: <1cabfada0f1a83ae78b6a7dbb9128512369fd6f4@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:07:16 +0200
+Subject: [PATCH] vircgroup: introduce virCgroupV2CopyPlacement
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 7a86201dd6e8cc7e418ea0891aeb44bacd08a10d)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <70993f08246ff3782d9b4a5bdf9187a0c1b57882.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroupv2.c | 27 +++++++++++++++++++++++++++
+ 1 file changed, 27 insertions(+)
+
+diff --git a/src/util/vircgroupv2.c b/src/util/vircgroupv2.c
+index 5d3c80b309..ed87b35db7 100644
+--- a/src/util/vircgroupv2.c
++++ b/src/util/vircgroupv2.c
+@@ -140,12 +140,39 @@ virCgroupV2CopyMounts(virCgroupPtr group,
+ }
+ 
+ 
++static int
++virCgroupV2CopyPlacement(virCgroupPtr group,
++                         const char *path,
++                         virCgroupPtr parent)
++{
++    if (path[0] == '/') {
++        if (VIR_STRDUP(group->unified.placement, path) < 0)
++            return -1;
++    } else {
++        /*
++         * parent == "/" + path="" => "/"
++         * parent == "/libvirt.service" + path == "" => "/libvirt.service"
++         * parent == "/libvirt.service" + path == "foo" => "/libvirt.service/foo"
++         */
++        if (virAsprintf(&group->unified.placement, "%s%s%s",
++                        parent->unified.placement,
++                        (STREQ(parent->unified.placement, "/") ||
++                         STREQ(path, "") ? "" : "/"),
++                        path) < 0)
++            return -1;
++    }
++
++    return 0;
++}
++
++
+ virCgroupBackend virCgroupV2Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V2,
+ 
+     .available = virCgroupV2Available,
+     .validateMachineGroup = virCgroupV2ValidateMachineGroup,
+     .copyMounts = virCgroupV2CopyMounts,
++    .copyPlacement = virCgroupV2CopyPlacement,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-introduce-virCgroupV2DetectControllers.patch b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2DetectControllers.patch
new file mode 100644
index 0000000..af1b97e
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2DetectControllers.patch
@@ -0,0 +1,125 @@
+From 079999bce280ca42a47a1521bb3b7bd06f7985f2 Mon Sep 17 00:00:00 2001
+Message-Id: <079999bce280ca42a47a1521bb3b7bd06f7985f2@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:07:21 +0200
+Subject: [PATCH] vircgroup: introduce virCgroupV2DetectControllers
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Cgroup v2 has only single mount point for all controllers.  The list
+of controllers is stored in cgroup.controllers file, name of controllers
+are separated by space.
+
+In cgroup v2 there is no cpuacct controller, the cpu.stat file always
+exists with usage stats.
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit e1bb7fffe2571e6a337bd87a9c5ed487ee6ee046)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <2186bc99cdcfc420b1aaf516fc808dfbf582a1d0.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroupv2.c | 69 ++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 69 insertions(+)
+
+diff --git a/src/util/vircgroupv2.c b/src/util/vircgroupv2.c
+index 270a6fb305..c8f2573864 100644
+--- a/src/util/vircgroupv2.c
++++ b/src/util/vircgroupv2.c
+@@ -33,6 +33,7 @@
+ #include "vircgroup.h"
+ #include "vircgroupbackend.h"
+ #include "vircgroupv2.h"
++#include "virerror.h"
+ #include "virfile.h"
+ #include "virlog.h"
+ #include "virstring.h"
+@@ -231,6 +232,73 @@ virCgroupV2StealPlacement(virCgroupPtr group)
+ }
+ 
+ 
++static int
++virCgroupV2ParseControllersFile(virCgroupPtr group)
++{
++    int rc;
++    VIR_AUTOFREE(char *) contStr = NULL;
++    VIR_AUTOFREE(char *) contFile = NULL;
++    char **contList = NULL;
++    char **tmp;
++
++    if (virAsprintf(&contFile, "%s/cgroup.controllers",
++                    group->unified.mountPoint) < 0)
++        return -1;
++
++    rc = virFileReadAll(contFile, 1024 * 1024, &contStr);
++    if (rc < 0) {
++        virReportSystemError(errno, _("Unable to read from '%s'"), contFile);
++        return -1;
++    }
++
++    virTrimSpaces(contStr, NULL);
++
++    contList = virStringSplit(contStr, " ", 20);
++    if (!contList)
++        return -1;
++
++    tmp = contList;
++
++    while (*tmp) {
++        int type = virCgroupV2ControllerTypeFromString(*tmp);
++
++        if (type >= 0)
++            group->unified.controllers |= 1 << type;
++
++        tmp++;
++    }
++
++    virStringListFree(contList);
++
++    return 0;
++}
++
++
++static int
++virCgroupV2DetectControllers(virCgroupPtr group,
++                             int controllers)
++{
++    size_t i;
++
++    if (virCgroupV2ParseControllersFile(group) < 0)
++        return -1;
++
++    /* In cgroup v2 there is no cpuacct controller, the cpu.stat file always
++     * exists with usage stats. */
++    group->unified.controllers |= 1 << VIR_CGROUP_CONTROLLER_CPUACCT;
++
++    for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++)
++        VIR_DEBUG("Controller '%s' present=%s",
++                  virCgroupV2ControllerTypeToString(i),
++                  (group->unified.controllers & 1 << i) ? "yes" : "no");
++
++    if (controllers >= 0)
++        return controllers & group->unified.controllers;
++    else
++        return group->unified.controllers;
++}
++
++
+ virCgroupBackend virCgroupV2Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V2,
+ 
+@@ -242,6 +310,7 @@ virCgroupBackend virCgroupV2Backend = {
+     .detectPlacement = virCgroupV2DetectPlacement,
+     .validatePlacement = virCgroupV2ValidatePlacement,
+     .stealPlacement = virCgroupV2StealPlacement,
++    .detectControllers = virCgroupV2DetectControllers,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-introduce-virCgroupV2DetectMounts.patch b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2DetectMounts.patch
new file mode 100644
index 0000000..de683e7
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2DetectMounts.patch
@@ -0,0 +1,58 @@
+From d27635600023556a1e1ea566f0860facdf8d69c9 Mon Sep 17 00:00:00 2001
+Message-Id: <d27635600023556a1e1ea566f0860facdf8d69c9@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:07:17 +0200
+Subject: [PATCH] vircgroup: introduce virCgroupV2DetectMounts
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 50f61a46fcd0f25f98bb89db74bea76bca5dc4a4)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <050f43f97c07f9dc1c17f477c043fbe3a6759396.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroupv2.c | 16 ++++++++++++++++
+ 1 file changed, 16 insertions(+)
+
+diff --git a/src/util/vircgroupv2.c b/src/util/vircgroupv2.c
+index ed87b35db7..19a9ba38f8 100644
+--- a/src/util/vircgroupv2.c
++++ b/src/util/vircgroupv2.c
+@@ -166,6 +166,21 @@ virCgroupV2CopyPlacement(virCgroupPtr group,
+ }
+ 
+ 
++static int
++virCgroupV2DetectMounts(virCgroupPtr group,
++                        const char *mntType,
++                        const char *mntOpts ATTRIBUTE_UNUSED,
++                        const char *mntDir)
++{
++    if (STRNEQ(mntType, "cgroup2"))
++        return 0;
++
++    VIR_FREE(group->unified.mountPoint);
++
++    return VIR_STRDUP(group->unified.mountPoint, mntDir);
++}
++
++
+ virCgroupBackend virCgroupV2Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V2,
+ 
+@@ -173,6 +188,7 @@ virCgroupBackend virCgroupV2Backend = {
+     .validateMachineGroup = virCgroupV2ValidateMachineGroup,
+     .copyMounts = virCgroupV2CopyMounts,
+     .copyPlacement = virCgroupV2CopyPlacement,
++    .detectMounts = virCgroupV2DetectMounts,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-introduce-virCgroupV2DetectPlacement.patch b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2DetectPlacement.patch
new file mode 100644
index 0000000..3998c21
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2DetectPlacement.patch
@@ -0,0 +1,72 @@
+From af9bf10ff9d8a6f0ae9b6d898138144bf7dcd161 Mon Sep 17 00:00:00 2001
+Message-Id: <af9bf10ff9d8a6f0ae9b6d898138144bf7dcd161@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:07:18 +0200
+Subject: [PATCH] vircgroup: introduce virCgroupV2DetectPlacement
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+If the placement was copied from parent or set to absolute path
+there is nothing to do, otherwise set the placement based on
+process placement from /proc/self/cgroup or /proc/{pid}/cgroup.
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 1efcf202e777d32600e90f3176e0357053341533)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <7fcc9d25385c40df5531e5b7171338a624d0c4fb.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroupv2.c | 26 ++++++++++++++++++++++++++
+ 1 file changed, 26 insertions(+)
+
+diff --git a/src/util/vircgroupv2.c b/src/util/vircgroupv2.c
+index 19a9ba38f8..fb1aa2de0a 100644
+--- a/src/util/vircgroupv2.c
++++ b/src/util/vircgroupv2.c
+@@ -181,6 +181,31 @@ virCgroupV2DetectMounts(virCgroupPtr group,
+ }
+ 
+ 
++static int
++virCgroupV2DetectPlacement(virCgroupPtr group,
++                           const char *path,
++                           const char *controllers ATTRIBUTE_UNUSED,
++                           const char *selfpath)
++{
++    if (group->unified.placement)
++        return 0;
++
++    /*
++     * selfpath == "/" + path="" -> "/"
++     * selfpath == "/libvirt.service" + path == "" -> "/libvirt.service"
++     * selfpath == "/libvirt.service" + path == "foo" -> "/libvirt.service/foo"
++     */
++    if (virAsprintf(&group->unified.placement,
++                    "%s%s%s", selfpath,
++                    (STREQ(selfpath, "/") ||
++                     STREQ(path, "") ? "" : "/"),
++                    path) < 0)
++        return -1;
++
++    return 0;
++}
++
++
+ virCgroupBackend virCgroupV2Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V2,
+ 
+@@ -189,6 +214,7 @@ virCgroupBackend virCgroupV2Backend = {
+     .copyMounts = virCgroupV2CopyMounts,
+     .copyPlacement = virCgroupV2CopyPlacement,
+     .detectMounts = virCgroupV2DetectMounts,
++    .detectPlacement = virCgroupV2DetectPlacement,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-introduce-virCgroupV2GetAnyController.patch b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2GetAnyController.patch
new file mode 100644
index 0000000..601d42b
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2GetAnyController.patch
@@ -0,0 +1,51 @@
+From 6fc9abce93fb193d748c45dbe47920b287c9aa07 Mon Sep 17 00:00:00 2001
+Message-Id: <6fc9abce93fb193d748c45dbe47920b287c9aa07@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:07:23 +0200
+Subject: [PATCH] vircgroup: introduce virCgroupV2GetAnyController
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 171c700cd8c5509dc868c00faed9a16feaa2339d)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <2bc9d83fa5195d1650a8801c69b850ff86fd8386.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroupv2.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/src/util/vircgroupv2.c b/src/util/vircgroupv2.c
+index babce95aeb..65cbad533b 100644
+--- a/src/util/vircgroupv2.c
++++ b/src/util/vircgroupv2.c
+@@ -307,6 +307,14 @@ virCgroupV2HasController(virCgroupPtr group,
+ }
+ 
+ 
++static int
++virCgroupV2GetAnyController(virCgroupPtr group)
++{
++    /* The least significant bit is position 1. */
++    return ffs(group->unified.controllers) - 1;
++}
++
++
+ virCgroupBackend virCgroupV2Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V2,
+ 
+@@ -320,6 +328,7 @@ virCgroupBackend virCgroupV2Backend = {
+     .stealPlacement = virCgroupV2StealPlacement,
+     .detectControllers = virCgroupV2DetectControllers,
+     .hasController = virCgroupV2HasController,
++    .getAnyController = virCgroupV2GetAnyController,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-introduce-virCgroupV2GetBlkioIoDeviceServiced.patch b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2GetBlkioIoDeviceServiced.patch
new file mode 100644
index 0000000..3b8bc9a
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2GetBlkioIoDeviceServiced.patch
@@ -0,0 +1,106 @@
+From e549b6a2270598ad1e736837430573fafb6a7e64 Mon Sep 17 00:00:00 2001
+Message-Id: <e549b6a2270598ad1e736837430573fafb6a7e64@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:07:33 +0200
+Subject: [PATCH] vircgroup: introduce virCgroupV2GetBlkioIoDeviceServiced
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 93fa369df5edbf693cee472a9a8c2caa313ae2a0)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <c5774ab538aab66d306032ebcc330f36d47d318a.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroupv2.c | 64 ++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 64 insertions(+)
+
+diff --git a/src/util/vircgroupv2.c b/src/util/vircgroupv2.c
+index 000fd4c747..fcf39406e1 100644
+--- a/src/util/vircgroupv2.c
++++ b/src/util/vircgroupv2.c
+@@ -631,6 +631,69 @@ virCgroupV2GetBlkioIoServiced(virCgroupPtr group,
+ }
+ 
+ 
++static int
++virCgroupV2GetBlkioIoDeviceServiced(virCgroupPtr group,
++                                    const char *path,
++                                    long long *bytes_read,
++                                    long long *bytes_write,
++                                    long long *requests_read,
++                                    long long *requests_write)
++{
++    VIR_AUTOFREE(char *) str1 = NULL;
++    VIR_AUTOFREE(char *) str2 = NULL;
++    char *p1;
++    size_t i;
++
++    const char *value_names[] = {
++        "rbytes=",
++        "wbytes=",
++        "rios=",
++        "wios=",
++    };
++    long long *value_ptrs[] = {
++        bytes_read,
++        bytes_write,
++        requests_read,
++        requests_write
++    };
++
++    if (virCgroupGetValueStr(group,
++                             VIR_CGROUP_CONTROLLER_BLKIO,
++                             "io.stat", &str1) < 0) {
++        return -1;
++    }
++
++    if (!(str2 = virCgroupGetBlockDevString(path)))
++        return -1;
++
++    if (!(p1 = strstr(str1, str2))) {
++        virReportError(VIR_ERR_INTERNAL_ERROR,
++                       _("Cannot find byte stats for block device '%s'"),
++                       str2);
++        return -1;
++    }
++
++    for (i = 0; i < ARRAY_CARDINALITY(value_names); i++) {
++        if (!(p1 = strstr(p1, value_names[i]))) {
++            virReportError(VIR_ERR_INTERNAL_ERROR,
++                           _("Cannot find byte '%s' stats for block device '%s'"),
++                           value_names[i], str2);
++            return -1;
++        }
++
++        p1 += strlen(value_names[i]);
++        if (virStrToLong_ll(p1, &p1, 10, value_ptrs[i]) < 0) {
++            virReportError(VIR_ERR_INTERNAL_ERROR,
++                           _("Cannot parse '%s' stat '%s'"),
++                           value_names[i], p1);
++            return -1;
++        }
++    }
++
++    return 0;
++}
++
++
+ virCgroupBackend virCgroupV2Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V2,
+ 
+@@ -656,6 +719,7 @@ virCgroupBackend virCgroupV2Backend = {
+     .setBlkioWeight = virCgroupV2SetBlkioWeight,
+     .getBlkioWeight = virCgroupV2GetBlkioWeight,
+     .getBlkioIoServiced = virCgroupV2GetBlkioIoServiced,
++    .getBlkioIoDeviceServiced = virCgroupV2GetBlkioIoDeviceServiced,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-introduce-virCgroupV2GetBlkioIoServiced.patch b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2GetBlkioIoServiced.patch
new file mode 100644
index 0000000..81ec8b6
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2GetBlkioIoServiced.patch
@@ -0,0 +1,107 @@
+From abf2cfc52b828aa892b446385875381f735ff947 Mon Sep 17 00:00:00 2001
+Message-Id: <abf2cfc52b828aa892b446385875381f735ff947@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:07:32 +0200
+Subject: [PATCH] vircgroup: introduce virCgroupV2GetBlkioIoServiced
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 709260add941a247b3829cf940624333cb445bb7)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <f178386744bb4d74f41acecb82807d451c255fc9.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroupv2.c | 65 ++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 65 insertions(+)
+
+diff --git a/src/util/vircgroupv2.c b/src/util/vircgroupv2.c
+index f7863a5690..000fd4c747 100644
+--- a/src/util/vircgroupv2.c
++++ b/src/util/vircgroupv2.c
+@@ -567,6 +567,70 @@ virCgroupV2GetBlkioWeight(virCgroupPtr group,
+ }
+ 
+ 
++static int
++virCgroupV2GetBlkioIoServiced(virCgroupPtr group,
++                              long long *bytes_read,
++                              long long *bytes_write,
++                              long long *requests_read,
++                              long long *requests_write)
++{
++    long long stats_val;
++    VIR_AUTOFREE(char *) str1 = NULL;
++    char *p1;
++    size_t i;
++
++    const char *value_names[] = {
++        "rbytes=",
++        "wbytes=",
++        "rios=",
++        "wios=",
++    };
++    long long *value_ptrs[] = {
++        bytes_read,
++        bytes_write,
++        requests_read,
++        requests_write
++    };
++
++    *bytes_read = 0;
++    *bytes_write = 0;
++    *requests_read = 0;
++    *requests_write = 0;
++
++    if (virCgroupGetValueStr(group,
++                             VIR_CGROUP_CONTROLLER_BLKIO,
++                             "io.stat", &str1) < 0) {
++        return -1;
++    }
++
++    /* sum up all entries of the same kind, from all devices */
++    for (i = 0; i < ARRAY_CARDINALITY(value_names); i++) {
++        p1 = str1;
++
++        while ((p1 = strstr(p1, value_names[i]))) {
++            p1 += strlen(value_names[i]);
++            if (virStrToLong_ll(p1, &p1, 10, &stats_val) < 0) {
++                virReportError(VIR_ERR_INTERNAL_ERROR,
++                               _("Cannot parse byte '%s' stat '%s'"),
++                               value_names[i], p1);
++                return -1;
++            }
++
++            if (stats_val < 0 ||
++                (stats_val > 0 && *value_ptrs[i] > (LLONG_MAX - stats_val))) {
++                virReportError(VIR_ERR_OVERFLOW,
++                               _("Sum of byte '%s' stat overflows"),
++                               value_names[i]);
++                return -1;
++            }
++            *value_ptrs[i] += stats_val;
++        }
++    }
++
++    return 0;
++}
++
++
+ virCgroupBackend virCgroupV2Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V2,
+ 
+@@ -591,6 +655,7 @@ virCgroupBackend virCgroupV2Backend = {
+ 
+     .setBlkioWeight = virCgroupV2SetBlkioWeight,
+     .getBlkioWeight = virCgroupV2GetBlkioWeight,
++    .getBlkioIoServiced = virCgroupV2GetBlkioIoServiced,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-introduce-virCgroupV2GetCpuacctStat.patch b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2GetCpuacctStat.patch
new file mode 100644
index 0000000..6370f22
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2GetCpuacctStat.patch
@@ -0,0 +1,91 @@
+From d54383e93c3d3a71008d4b3a48b4dafba2368609 Mon Sep 17 00:00:00 2001
+Message-Id: <d54383e93c3d3a71008d4b3a48b4dafba2368609@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:07:51 +0200
+Subject: [PATCH] vircgroup: introduce virCgroupV2GetCpuacctStat
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 4d1d5c92bdefc38bc68bde5f9bd2dbd3c11bff2a)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <62365d349154035cfab2115d66430dcf3c7bdd03.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroupv2.c | 49 ++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 49 insertions(+)
+
+diff --git a/src/util/vircgroupv2.c b/src/util/vircgroupv2.c
+index afa243b3c7..d6362e2b05 100644
+--- a/src/util/vircgroupv2.c
++++ b/src/util/vircgroupv2.c
+@@ -1487,6 +1487,54 @@ virCgroupV2GetCpuacctUsage(virCgroupPtr group,
+ }
+ 
+ 
++static int
++virCgroupV2GetCpuacctStat(virCgroupPtr group,
++                          unsigned long long *user,
++                          unsigned long long *sys)
++{
++    VIR_AUTOFREE(char *) str = NULL;
++    char *tmp;
++    unsigned long long userVal = 0;
++    unsigned long long sysVal = 0;
++
++    if (virCgroupGetValueStr(group, VIR_CGROUP_CONTROLLER_CPUACCT,
++                             "cpu.stat", &str) < 0) {
++        return -1;
++    }
++
++    if (!(tmp = strstr(str, "user_usec "))) {
++        virReportError(VIR_ERR_INTERNAL_ERROR,
++                       _("cannot parse cpu user stat '%s'"), str);
++        return -1;
++    }
++    tmp += strlen("user_usec ");
++
++    if (virStrToLong_ull(tmp, &tmp, 10, &userVal) < 0) {
++        virReportError(VIR_ERR_INTERNAL_ERROR,
++                       _("Failed to parse value '%s' as number."), tmp);
++        return -1;
++    }
++
++    if (!(tmp = strstr(str, "system_usec "))) {
++        virReportError(VIR_ERR_INTERNAL_ERROR,
++                       _("cannot parse cpu sys stat '%s'"), str);
++        return -1;
++    }
++    tmp += strlen("system_usec ");
++
++    if (virStrToLong_ull(tmp, &tmp, 10, &sysVal) < 0) {
++        virReportError(VIR_ERR_INTERNAL_ERROR,
++                       _("Failed to parse value '%s' as number."), tmp);
++        return -1;
++    }
++
++    *user = userVal * 1000;
++    *sys = sysVal * 1000;
++
++    return 0;
++}
++
++
+ virCgroupBackend virCgroupV2Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V2,
+ 
+@@ -1544,6 +1592,7 @@ virCgroupBackend virCgroupV2Backend = {
+     .supportsCpuBW = virCgroupV2SupportsCpuBW,
+ 
+     .getCpuacctUsage = virCgroupV2GetCpuacctUsage,
++    .getCpuacctStat = virCgroupV2GetCpuacctStat,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-introduce-virCgroupV2GetCpuacctUsage.patch b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2GetCpuacctUsage.patch
new file mode 100644
index 0000000..6f16073
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2GetCpuacctUsage.patch
@@ -0,0 +1,75 @@
+From e0764ef7577519de460fc2c2d52127eafb077200 Mon Sep 17 00:00:00 2001
+Message-Id: <e0764ef7577519de460fc2c2d52127eafb077200@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:07:50 +0200
+Subject: [PATCH] vircgroup: introduce virCgroupV2GetCpuacctUsage
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 567fcbdca56ac409e856a0be8425b2218d02fe81)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <26dc66d290ee4d5a4ba67470552df9d2fa4ae86b.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroupv2.c | 33 +++++++++++++++++++++++++++++++++
+ 1 file changed, 33 insertions(+)
+
+diff --git a/src/util/vircgroupv2.c b/src/util/vircgroupv2.c
+index 55f79af204..afa243b3c7 100644
+--- a/src/util/vircgroupv2.c
++++ b/src/util/vircgroupv2.c
+@@ -1456,6 +1456,37 @@ virCgroupV2SupportsCpuBW(virCgroupPtr cgroup)
+ }
+ 
+ 
++static int
++virCgroupV2GetCpuacctUsage(virCgroupPtr group,
++                           unsigned long long *usage)
++{
++    VIR_AUTOFREE(char *) str = NULL;
++    char *tmp;
++
++    if (virCgroupGetValueStr(group, VIR_CGROUP_CONTROLLER_CPUACCT,
++                             "cpu.stat", &str) < 0) {
++        return -1;
++    }
++
++    if (!(tmp = strstr(str, "usage_usec "))) {
++        virReportError(VIR_ERR_INTERNAL_ERROR,
++                       _("cannot parse cpu usage stat '%s'"), str);
++        return -1;
++    }
++    tmp += strlen("usage_usec ");
++
++    if (virStrToLong_ull(tmp, &tmp, 10, usage) < 0) {
++        virReportError(VIR_ERR_INTERNAL_ERROR,
++                       _("Failed to parse value '%s' as number."), tmp);
++        return -1;
++    }
++
++    *usage *= 1000;
++
++    return 0;
++}
++
++
+ virCgroupBackend virCgroupV2Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V2,
+ 
+@@ -1511,6 +1542,8 @@ virCgroupBackend virCgroupV2Backend = {
+     .setCpuCfsQuota = virCgroupV2SetCpuCfsQuota,
+     .getCpuCfsQuota = virCgroupV2GetCpuCfsQuota,
+     .supportsCpuBW = virCgroupV2SupportsCpuBW,
++
++    .getCpuacctUsage = virCgroupV2GetCpuacctUsage,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-introduce-virCgroupV2GetMemSwapUsage.patch b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2GetMemSwapUsage.patch
new file mode 100644
index 0000000..2e1b584
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2GetMemSwapUsage.patch
@@ -0,0 +1,58 @@
+From 64df2fa746eab23c73578c53b6d8501cbec2d04c Mon Sep 17 00:00:00 2001
+Message-Id: <64df2fa746eab23c73578c53b6d8501cbec2d04c@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:07:45 +0200
+Subject: [PATCH] vircgroup: introduce virCgroupV2GetMemSwapUsage
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 3f728c720b782e853de4c43999a37aeceb3f95b8)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <c7135a2e07a613fb4f285556bc703843bb2fd872.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroupv2.c | 16 ++++++++++++++++
+ 1 file changed, 16 insertions(+)
+
+diff --git a/src/util/vircgroupv2.c b/src/util/vircgroupv2.c
+index fed6792e16..8d184bd963 100644
+--- a/src/util/vircgroupv2.c
++++ b/src/util/vircgroupv2.c
+@@ -1290,6 +1290,21 @@ virCgroupV2GetMemSwapHardLimit(virCgroupPtr group,
+ }
+ 
+ 
++static int
++virCgroupV2GetMemSwapUsage(virCgroupPtr group,
++                           unsigned long long *kb)
++{
++    unsigned long long usage_in_bytes;
++    int ret;
++    ret = virCgroupGetValueU64(group,
++                               VIR_CGROUP_CONTROLLER_MEMORY,
++                               "memory.swap.current", &usage_in_bytes);
++    if (ret == 0)
++        *kb = (unsigned long) usage_in_bytes >> 10;
++    return ret;
++}
++
++
+ virCgroupBackend virCgroupV2Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V2,
+ 
+@@ -1336,6 +1351,7 @@ virCgroupBackend virCgroupV2Backend = {
+     .getMemorySoftLimit = virCgroupV2GetMemorySoftLimit,
+     .setMemSwapHardLimit = virCgroupV2SetMemSwapHardLimit,
+     .getMemSwapHardLimit = virCgroupV2GetMemSwapHardLimit,
++    .getMemSwapUsage = virCgroupV2GetMemSwapUsage,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-introduce-virCgroupV2GetMemoryStat.patch b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2GetMemoryStat.patch
new file mode 100644
index 0000000..1233bef
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2GetMemoryStat.patch
@@ -0,0 +1,117 @@
+From 7b4215f8a38221fd90bf15a3ced42cce55adf105 Mon Sep 17 00:00:00 2001
+Message-Id: <7b4215f8a38221fd90bf15a3ced42cce55adf105@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:07:40 +0200
+Subject: [PATCH] vircgroup: introduce virCgroupV2GetMemoryStat
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit d080c001660ed0f173066b3db63ecac4edb773fc)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <9ebb30d0c01bdb6e356928701cd56501fe43af5e.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroupv2.c | 75 ++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 75 insertions(+)
+
+diff --git a/src/util/vircgroupv2.c b/src/util/vircgroupv2.c
+index 1b7215d98b..1c7854909f 100644
+--- a/src/util/vircgroupv2.c
++++ b/src/util/vircgroupv2.c
+@@ -1042,6 +1042,80 @@ virCgroupV2SetMemory(virCgroupPtr group,
+ }
+ 
+ 
++static int
++virCgroupV2GetMemoryStat(virCgroupPtr group,
++                         unsigned long long *cache,
++                         unsigned long long *activeAnon,
++                         unsigned long long *inactiveAnon,
++                         unsigned long long *activeFile,
++                         unsigned long long *inactiveFile,
++                         unsigned long long *unevictable)
++{
++    VIR_AUTOFREE(char *) stat = NULL;
++    char *line = NULL;
++    unsigned long long cacheVal = 0;
++    unsigned long long activeAnonVal = 0;
++    unsigned long long inactiveAnonVal = 0;
++    unsigned long long activeFileVal = 0;
++    unsigned long long inactiveFileVal = 0;
++    unsigned long long unevictableVal = 0;
++
++    if (virCgroupGetValueStr(group,
++                             VIR_CGROUP_CONTROLLER_MEMORY,
++                             "memory.stat",
++                             &stat) < 0) {
++        return -1;
++    }
++
++    line = stat;
++
++    while (line) {
++        char *newLine = strchr(line, '\n');
++        char *valueStr = strchr(line, ' ');
++        unsigned long long value;
++
++        if (newLine)
++            *newLine = '\0';
++
++        if (!valueStr) {
++            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
++                           _("Cannot parse 'memory.stat' cgroup file."));
++            return -1;
++        }
++        *valueStr = '\0';
++
++        if (virStrToLong_ull(valueStr + 1, NULL, 10, &value) < 0) {
++            virReportError(VIR_ERR_INTERNAL_ERROR,
++                           _("Unable to parse '%s' as an integer"),
++                           valueStr + 1);
++            return -1;
++        }
++
++        if (STREQ(line, "file"))
++            cacheVal = value >> 10;
++        else if (STREQ(line, "active_anon"))
++            activeAnonVal = value >> 10;
++        else if (STREQ(line, "inactive_anon"))
++            inactiveAnonVal = value >> 10;
++        else if (STREQ(line, "active_file"))
++            activeFileVal = value >> 10;
++        else if (STREQ(line, "inactive_file"))
++            inactiveFileVal = value >> 10;
++        else if (STREQ(line, "unevictable"))
++            unevictableVal = value >> 10;
++    }
++
++    *cache = cacheVal;
++    *activeAnon = activeAnonVal;
++    *inactiveAnon = inactiveAnonVal;
++    *activeFile = activeFileVal;
++    *inactiveFile = inactiveFileVal;
++    *unevictable = unevictableVal;
++
++    return 0;
++}
++
++
+ virCgroupBackend virCgroupV2Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V2,
+ 
+@@ -1080,6 +1154,7 @@ virCgroupBackend virCgroupV2Backend = {
+     .getBlkioDeviceWriteBps = virCgroupV2GetBlkioDeviceWriteBps,
+ 
+     .setMemory = virCgroupV2SetMemory,
++    .getMemoryStat = virCgroupV2GetMemoryStat,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-introduce-virCgroupV2GetMemoryUsage.patch b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2GetMemoryUsage.patch
new file mode 100644
index 0000000..64e2f07
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2GetMemoryUsage.patch
@@ -0,0 +1,57 @@
+From 0f9d55fe0fbbdc66a5fdc2236c9433aab840a1b9 Mon Sep 17 00:00:00 2001
+Message-Id: <0f9d55fe0fbbdc66a5fdc2236c9433aab840a1b9@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:07:41 +0200
+Subject: [PATCH] vircgroup: introduce virCgroupV2GetMemoryUsage
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 495f60edcb123a714706f765027ea190f8d20da3)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <fe7485f1f5e5743721ff623ecddac0d27dbc3f1e.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroupv2.c | 15 +++++++++++++++
+ 1 file changed, 15 insertions(+)
+
+diff --git a/src/util/vircgroupv2.c b/src/util/vircgroupv2.c
+index 1c7854909f..87d357b0a7 100644
+--- a/src/util/vircgroupv2.c
++++ b/src/util/vircgroupv2.c
+@@ -1116,6 +1116,20 @@ virCgroupV2GetMemoryStat(virCgroupPtr group,
+ }
+ 
+ 
++static int
++virCgroupV2GetMemoryUsage(virCgroupPtr group,
++                          unsigned long *kb)
++{
++    unsigned long long usage_in_bytes;
++    int ret = virCgroupGetValueU64(group,
++                                   VIR_CGROUP_CONTROLLER_MEMORY,
++                                   "memory.current", &usage_in_bytes);
++    if (ret == 0)
++        *kb = (unsigned long) usage_in_bytes >> 10;
++    return ret;
++}
++
++
+ virCgroupBackend virCgroupV2Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V2,
+ 
+@@ -1155,6 +1169,7 @@ virCgroupBackend virCgroupV2Backend = {
+ 
+     .setMemory = virCgroupV2SetMemory,
+     .getMemoryStat = virCgroupV2GetMemoryStat,
++    .getMemoryUsage = virCgroupV2GetMemoryUsage,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-introduce-virCgroupV2HasController.patch b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2HasController.patch
new file mode 100644
index 0000000..9221fa2
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2HasController.patch
@@ -0,0 +1,51 @@
+From e5f2fdbd6499d97073ad20fe1ea491accecff704 Mon Sep 17 00:00:00 2001
+Message-Id: <e5f2fdbd6499d97073ad20fe1ea491accecff704@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:07:22 +0200
+Subject: [PATCH] vircgroup: introduce virCgroupV2HasController
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit c8f08a5346919b3d963908eb0b61fc077dbdbccd)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <8dfef2b4c814027c13ab2d693144ec77844bff7a.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroupv2.c | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/src/util/vircgroupv2.c b/src/util/vircgroupv2.c
+index c8f2573864..babce95aeb 100644
+--- a/src/util/vircgroupv2.c
++++ b/src/util/vircgroupv2.c
+@@ -299,6 +299,14 @@ virCgroupV2DetectControllers(virCgroupPtr group,
+ }
+ 
+ 
++static bool
++virCgroupV2HasController(virCgroupPtr group,
++                         int controller)
++{
++    return group->unified.controllers & (1 << controller);
++}
++
++
+ virCgroupBackend virCgroupV2Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V2,
+ 
+@@ -311,6 +319,7 @@ virCgroupBackend virCgroupV2Backend = {
+     .validatePlacement = virCgroupV2ValidatePlacement,
+     .stealPlacement = virCgroupV2StealPlacement,
+     .detectControllers = virCgroupV2DetectControllers,
++    .hasController = virCgroupV2HasController,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-introduce-virCgroupV2HasEmptyTasks.patch b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2HasEmptyTasks.patch
new file mode 100644
index 0000000..2c6a126
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2HasEmptyTasks.patch
@@ -0,0 +1,59 @@
+From 40a3ab5f35bb847ae210160b5bcb2b3ab8990e5a Mon Sep 17 00:00:00 2001
+Message-Id: <40a3ab5f35bb847ae210160b5bcb2b3ab8990e5a@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:07:28 +0200
+Subject: [PATCH] vircgroup: introduce virCgroupV2HasEmptyTasks
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 38411bb831a8c5086145b9781168349bc64fbc25)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <36bb2bd62faa6528de46da822d026f67be9f6d16.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroupv2.c | 17 +++++++++++++++++
+ 1 file changed, 17 insertions(+)
+
+diff --git a/src/util/vircgroupv2.c b/src/util/vircgroupv2.c
+index 6ffb5ce786..074e6ec110 100644
+--- a/src/util/vircgroupv2.c
++++ b/src/util/vircgroupv2.c
+@@ -446,6 +446,22 @@ virCgroupV2AddTask(virCgroupPtr group,
+ }
+ 
+ 
++static int
++virCgroupV2HasEmptyTasks(virCgroupPtr cgroup,
++                         int controller)
++{
++    int ret = -1;
++    VIR_AUTOFREE(char *) content = NULL;
++
++    ret = virCgroupGetValueStr(cgroup, controller, "cgroup.procs", &content);
++
++    if (ret == 0 && content[0] == '\0')
++        ret = 1;
++
++    return ret;
++}
++
++
+ virCgroupBackend virCgroupV2Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V2,
+ 
+@@ -464,6 +480,7 @@ virCgroupBackend virCgroupV2Backend = {
+     .makeGroup = virCgroupV2MakeGroup,
+     .remove = virCgroupV2Remove,
+     .addTask = virCgroupV2AddTask,
++    .hasEmptyTasks = virCgroupV2HasEmptyTasks,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-introduce-virCgroupV2MakeGroup.patch b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2MakeGroup.patch
new file mode 100644
index 0000000..aeb0055
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2MakeGroup.patch
@@ -0,0 +1,174 @@
+From 4a7aa0ff6839fd9ccefce19d63c48beed32ee7f1 Mon Sep 17 00:00:00 2001
+Message-Id: <4a7aa0ff6839fd9ccefce19d63c48beed32ee7f1@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:07:25 +0200
+Subject: [PATCH] vircgroup: introduce virCgroupV2MakeGroup
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+When creating cgroup hierarchy we need to enable controllers in the
+parent cgroup in order to be usable.  That means writing "+{controller}"
+into cgroup.subtree_control file.  We can enable only controllers that
+are enabled for parent cgroup, that means we need to do that for the
+whole cgroup tree.
+
+Cgroups for threads needs to be handled differently in cgroup v2.  There
+are two types of controllers:
+
+    - domain controllers: these cannot be enabled for threads
+    - threaded controllers: these can be enabled for threads
+
+In addition there are multiple types of cgroups:
+
+    - domain: normal cgroup
+    - domain threaded: a domain cgroup that serves as root for threaded
+                       cgroups
+    - domain invalid: invalid cgroup, can be changed into threaded, this
+                      is the default state if you create subgroup inside
+                      domain threaded group or threaded group
+    - threaded: threaded cgroup which can have domain threaded or
+                threaded as parent group
+
+In order to create threaded cgroup it's sufficient to write "threaded"
+into cgroup.type file, it will automatically make parent cgroup
+"domain threaded" if it was only "domain".  In case the parent cgroup
+is already "domain threaded" or "threaded" it will modify only the type
+of current cgroup.  After that we can enable threaded controllers.
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 89f52abd07d3f991ddd22990e5d61338ff350a99)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <165b3b0f0fd1e5a4b52e4b9e86e4137b3598f7ee.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c        |  2 +-
+ src/util/vircgroupbackend.h |  1 +
+ src/util/vircgroupv2.c      | 76 +++++++++++++++++++++++++++++++++++++
+ 3 files changed, 78 insertions(+), 1 deletion(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index 42930582db..a859628241 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -942,7 +942,7 @@ virCgroupNewThread(virCgroupPtr domain,
+     if (virCgroupNew(-1, name, domain, controllers, group) < 0)
+         return -1;
+ 
+-    if (virCgroupMakeGroup(domain, *group, create, VIR_CGROUP_NONE) < 0) {
++    if (virCgroupMakeGroup(domain, *group, create, VIR_CGROUP_THREAD) < 0) {
+         virCgroupFree(group);
+         return -1;
+     }
+diff --git a/src/util/vircgroupbackend.h b/src/util/vircgroupbackend.h
+index b1f19233e4..86d1539e07 100644
+--- a/src/util/vircgroupbackend.h
++++ b/src/util/vircgroupbackend.h
+@@ -33,6 +33,7 @@ typedef enum {
+                                        * before creating subcgroups and
+                                        * attaching tasks
+                                        */
++    VIR_CGROUP_THREAD = 1 << 1, /* cgroup v2 handles threads differently */
+ } virCgroupBackendFlags;
+ 
+ typedef enum {
+diff --git a/src/util/vircgroupv2.c b/src/util/vircgroupv2.c
+index 6695901766..cf8bd01317 100644
+--- a/src/util/vircgroupv2.c
++++ b/src/util/vircgroupv2.c
+@@ -338,6 +338,81 @@ virCgroupV2PathOfController(virCgroupPtr group,
+ }
+ 
+ 
++static int
++virCgroupV2EnableController(virCgroupPtr parent,
++                            int controller)
++{
++    VIR_AUTOFREE(char *) val = NULL;
++
++    if (virAsprintf(&val, "+%s",
++                    virCgroupV2ControllerTypeToString(controller)) < 0) {
++        return -1;
++    }
++
++    if (virCgroupSetValueStr(parent, controller,
++                             "cgroup.subtree_control", val) < 0) {
++        return -1;
++    }
++
++    return 0;
++}
++
++
++static int
++virCgroupV2MakeGroup(virCgroupPtr parent ATTRIBUTE_UNUSED,
++                     virCgroupPtr group,
++                     bool create,
++                     unsigned int flags)
++{
++    VIR_AUTOFREE(char *) path = NULL;
++    int controller;
++
++    VIR_DEBUG("Make group %s", group->path);
++
++    controller = virCgroupV2GetAnyController(group);
++    if (virCgroupV2PathOfController(group, controller, "", &path) < 0)
++        return -1;
++
++    VIR_DEBUG("Make controller %s", path);
++
++    if (!virFileExists(path) &&
++        (!create || (mkdir(path, 0755) < 0 && errno != EEXIST))) {
++        virReportSystemError(errno, _("Failed to create v2 cgroup '%s'"),
++                             group->path);
++        return -1;
++    }
++
++    if (create) {
++        if (flags & VIR_CGROUP_THREAD) {
++            if (virCgroupSetValueStr(group, VIR_CGROUP_CONTROLLER_CPU,
++                                     "cgroup.type", "threaded") < 0) {
++                return -1;
++            }
++
++            if (virCgroupV2EnableController(parent,
++                                            VIR_CGROUP_CONTROLLER_CPU) < 0) {
++                return -1;
++            }
++        } else {
++            size_t i;
++            for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
++                if (!virCgroupV2HasController(parent, i))
++                    continue;
++
++                /* Controllers that are implicitly enabled if available. */
++                if (i == VIR_CGROUP_CONTROLLER_CPUACCT)
++                    continue;
++
++                if (virCgroupV2EnableController(parent, i) < 0)
++                    return -1;
++            }
++        }
++    }
++
++    return 0;
++}
++
++
+ virCgroupBackend virCgroupV2Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V2,
+ 
+@@ -353,6 +428,7 @@ virCgroupBackend virCgroupV2Backend = {
+     .hasController = virCgroupV2HasController,
+     .getAnyController = virCgroupV2GetAnyController,
+     .pathOfController = virCgroupV2PathOfController,
++    .makeGroup = virCgroupV2MakeGroup,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-introduce-virCgroupV2PathOfController.patch b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2PathOfController.patch
new file mode 100644
index 0000000..012f7ba
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2PathOfController.patch
@@ -0,0 +1,66 @@
+From 2a826bcdbe8e34af71634250ae814d5ff81d6ffc Mon Sep 17 00:00:00 2001
+Message-Id: <2a826bcdbe8e34af71634250ae814d5ff81d6ffc@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:07:24 +0200
+Subject: [PATCH] vircgroup: introduce virCgroupV2PathOfController
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 0542640a9c480993c7e8be6917b0f513277b4cea)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <91b63d07af48bdb0fdc9648f4e5e4808cc90ad0e.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroupv2.c | 24 ++++++++++++++++++++++++
+ 1 file changed, 24 insertions(+)
+
+diff --git a/src/util/vircgroupv2.c b/src/util/vircgroupv2.c
+index 65cbad533b..6695901766 100644
+--- a/src/util/vircgroupv2.c
++++ b/src/util/vircgroupv2.c
+@@ -315,6 +315,29 @@ virCgroupV2GetAnyController(virCgroupPtr group)
+ }
+ 
+ 
++static int
++virCgroupV2PathOfController(virCgroupPtr group,
++                            int controller,
++                            const char *key,
++                            char **path)
++{
++    if (!virCgroupV2HasController(group, controller)) {
++        virReportError(VIR_ERR_INTERNAL_ERROR,
++                       _("v2 controller '%s' is not available"),
++                       virCgroupV2ControllerTypeToString(controller));
++        return -1;
++    }
++
++    if (virAsprintf(path, "%s%s/%s",
++                    group->unified.mountPoint,
++                    group->unified.placement,
++                    key ? key : "") < 0)
++        return -1;
++
++    return 0;
++}
++
++
+ virCgroupBackend virCgroupV2Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V2,
+ 
+@@ -329,6 +352,7 @@ virCgroupBackend virCgroupV2Backend = {
+     .detectControllers = virCgroupV2DetectControllers,
+     .hasController = virCgroupV2HasController,
+     .getAnyController = virCgroupV2GetAnyController,
++    .pathOfController = virCgroupV2PathOfController,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-introduce-virCgroupV2Remove.patch b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2Remove.patch
new file mode 100644
index 0000000..0dc70a5
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2Remove.patch
@@ -0,0 +1,62 @@
+From 4a95be40b1a56cc0eb6d6f56161d536f22380804 Mon Sep 17 00:00:00 2001
+Message-Id: <4a95be40b1a56cc0eb6d6f56161d536f22380804@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:07:26 +0200
+Subject: [PATCH] vircgroup: introduce virCgroupV2Remove
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 4fe4847438c8ff042d6d39718b26023199e67c8a)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <a7464dfade07325cf93291200356e33235020a2e.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroupv2.c | 20 ++++++++++++++++++++
+ 1 file changed, 20 insertions(+)
+
+diff --git a/src/util/vircgroupv2.c b/src/util/vircgroupv2.c
+index cf8bd01317..b5fad47ca0 100644
+--- a/src/util/vircgroupv2.c
++++ b/src/util/vircgroupv2.c
+@@ -413,6 +413,25 @@ virCgroupV2MakeGroup(virCgroupPtr parent ATTRIBUTE_UNUSED,
+ }
+ 
+ 
++static int
++virCgroupV2Remove(virCgroupPtr group)
++{
++    VIR_AUTOFREE(char *) grppath = NULL;
++    int controller;
++
++    /* Don't delete the root group, if we accidentally
++       ended up in it for some reason */
++    if (STREQ(group->unified.placement, "/"))
++        return 0;
++
++    controller = virCgroupV2GetAnyController(group);
++    if (virCgroupV2PathOfController(group, controller, "", &grppath) < 0)
++        return 0;
++
++    return virCgroupRemoveRecursively(grppath);
++}
++
++
+ virCgroupBackend virCgroupV2Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V2,
+ 
+@@ -429,6 +448,7 @@ virCgroupBackend virCgroupV2Backend = {
+     .getAnyController = virCgroupV2GetAnyController,
+     .pathOfController = virCgroupV2PathOfController,
+     .makeGroup = virCgroupV2MakeGroup,
++    .remove = virCgroupV2Remove,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-introduce-virCgroupV2SetMemory.patch b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2SetMemory.patch
new file mode 100644
index 0000000..2dfb833
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2SetMemory.patch
@@ -0,0 +1,71 @@
+From 9697d24cc223028555629af325af8607de350d06 Mon Sep 17 00:00:00 2001
+Message-Id: <9697d24cc223028555629af325af8607de350d06@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:07:39 +0200
+Subject: [PATCH] vircgroup: introduce virCgroupV2SetMemory
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 63bd23a6ad17331cdc31bc07fd8b21a96d4b2eb0)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <d2076f596f9e8b58571e19334f23e295f72a2ee5.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroupv2.c | 29 +++++++++++++++++++++++++++++
+ 1 file changed, 29 insertions(+)
+
+diff --git a/src/util/vircgroupv2.c b/src/util/vircgroupv2.c
+index 52d31925c2..1b7215d98b 100644
+--- a/src/util/vircgroupv2.c
++++ b/src/util/vircgroupv2.c
+@@ -1015,6 +1015,33 @@ virCgroupV2GetBlkioDeviceWriteBps(virCgroupPtr group,
+ }
+ 
+ 
++static int
++virCgroupV2SetMemory(virCgroupPtr group,
++                     unsigned long long kb)
++{
++    unsigned long long maxkb = VIR_DOMAIN_MEMORY_PARAM_UNLIMITED;
++
++    if (kb > maxkb) {
++        virReportError(VIR_ERR_INVALID_ARG,
++                       _("Memory '%llu' must be less than %llu"),
++                       kb, maxkb);
++        return -1;
++    }
++
++    if (kb == maxkb) {
++        return virCgroupSetValueStr(group,
++                                    VIR_CGROUP_CONTROLLER_MEMORY,
++                                    "memory.max",
++                                    "max");
++    } else {
++        return virCgroupSetValueU64(group,
++                                    VIR_CGROUP_CONTROLLER_MEMORY,
++                                    "memory.max",
++                                    kb << 10);
++    }
++}
++
++
+ virCgroupBackend virCgroupV2Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V2,
+ 
+@@ -1051,6 +1078,8 @@ virCgroupBackend virCgroupV2Backend = {
+     .getBlkioDeviceReadBps = virCgroupV2GetBlkioDeviceReadBps,
+     .setBlkioDeviceWriteBps = virCgroupV2SetBlkioDeviceWriteBps,
+     .getBlkioDeviceWriteBps = virCgroupV2GetBlkioDeviceWriteBps,
++
++    .setMemory = virCgroupV2SetMemory,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-introduce-virCgroupV2SetOwner.patch b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2SetOwner.patch
new file mode 100644
index 0000000..4df00cb
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2SetOwner.patch
@@ -0,0 +1,69 @@
+From c7f704deec7b42ec02ae13a678474b3ca62fecbd Mon Sep 17 00:00:00 2001
+Message-Id: <c7f704deec7b42ec02ae13a678474b3ca62fecbd@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:07:30 +0200
+Subject: [PATCH] vircgroup: introduce virCgroupV2SetOwner
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 525ac6885b508759f8618f136f04554c95138ae8)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <778612847c720bc6567b98708532175ada48ce44.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroupv2.c | 27 +++++++++++++++++++++++++++
+ 1 file changed, 27 insertions(+)
+
+diff --git a/src/util/vircgroupv2.c b/src/util/vircgroupv2.c
+index 90ce660908..27519d80e3 100644
+--- a/src/util/vircgroupv2.c
++++ b/src/util/vircgroupv2.c
+@@ -495,6 +495,32 @@ virCgroupV2BindMount(virCgroupPtr group,
+ }
+ 
+ 
++static int
++virCgroupV2SetOwner(virCgroupPtr cgroup,
++                    uid_t uid,
++                    gid_t gid,
++                    int controllers ATTRIBUTE_UNUSED)
++{
++    VIR_AUTOFREE(char *) base = NULL;
++
++    if (virAsprintf(&base, "%s%s", cgroup->unified.mountPoint,
++                    cgroup->unified.placement) < 0) {
++        return -1;
++    }
++
++    if (virFileChownFiles(base, uid, gid) < 0)
++        return -1;
++
++    if (chown(base, uid, gid) < 0) {
++        virReportSystemError(errno, _("cannot chown '%s' to (%u, %u)"),
++                             base, uid, gid);
++        return -1;
++    }
++
++    return 0;
++}
++
++
+ virCgroupBackend virCgroupV2Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V2,
+ 
+@@ -515,6 +541,7 @@ virCgroupBackend virCgroupV2Backend = {
+     .addTask = virCgroupV2AddTask,
+     .hasEmptyTasks = virCgroupV2HasEmptyTasks,
+     .bindMount = virCgroupV2BindMount,
++    .setOwner = virCgroupV2SetOwner,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-introduce-virCgroupV2StealPlacement.patch b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2StealPlacement.patch
new file mode 100644
index 0000000..e120096
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2StealPlacement.patch
@@ -0,0 +1,54 @@
+From f335c220a4ac822b6b66c8bd4dca0c85aad187f7 Mon Sep 17 00:00:00 2001
+Message-Id: <f335c220a4ac822b6b66c8bd4dca0c85aad187f7@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:07:20 +0200
+Subject: [PATCH] vircgroup: introduce virCgroupV2StealPlacement
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit f7394dcf010fc4be50b822e290e701430d45325d)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <5e3bd896f2aa16a3637b90d1c8bd3b0676c2acbd.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroupv2.c | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+diff --git a/src/util/vircgroupv2.c b/src/util/vircgroupv2.c
+index 815d8fca9b..270a6fb305 100644
+--- a/src/util/vircgroupv2.c
++++ b/src/util/vircgroupv2.c
+@@ -220,6 +220,17 @@ virCgroupV2ValidatePlacement(virCgroupPtr group,
+ }
+ 
+ 
++static char *
++virCgroupV2StealPlacement(virCgroupPtr group)
++{
++    char *ret;
++
++    VIR_STEAL_PTR(ret, group->unified.placement);
++
++    return ret;
++}
++
++
+ virCgroupBackend virCgroupV2Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V2,
+ 
+@@ -230,6 +241,7 @@ virCgroupBackend virCgroupV2Backend = {
+     .detectMounts = virCgroupV2DetectMounts,
+     .detectPlacement = virCgroupV2DetectPlacement,
+     .validatePlacement = virCgroupV2ValidatePlacement,
++    .stealPlacement = virCgroupV2StealPlacement,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-introduce-virCgroupV2SupportsCpuBW.patch b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2SupportsCpuBW.patch
new file mode 100644
index 0000000..4387129
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2SupportsCpuBW.patch
@@ -0,0 +1,58 @@
+From 59084112841259e4ff74bde8ad7ebf32280fdcca Mon Sep 17 00:00:00 2001
+Message-Id: <59084112841259e4ff74bde8ad7ebf32280fdcca@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:07:49 +0200
+Subject: [PATCH] vircgroup: introduce virCgroupV2SupportsCpuBW
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 5a4d90ae6af6ea5dd1bb6ae5e3fec7307a5f1257)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <e0f39a4ebc452685be49eaea66266fef5921c989.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroupv2.c | 16 ++++++++++++++++
+ 1 file changed, 16 insertions(+)
+
+diff --git a/src/util/vircgroupv2.c b/src/util/vircgroupv2.c
+index a0a7e55493..55f79af204 100644
+--- a/src/util/vircgroupv2.c
++++ b/src/util/vircgroupv2.c
+@@ -1441,6 +1441,21 @@ virCgroupV2GetCpuCfsQuota(virCgroupPtr group,
+ }
+ 
+ 
++static bool
++virCgroupV2SupportsCpuBW(virCgroupPtr cgroup)
++{
++    VIR_AUTOFREE(char *) path = NULL;
++
++    if (virCgroupV2PathOfController(cgroup, VIR_CGROUP_CONTROLLER_CPU,
++                                    "cpu.max", &path) < 0) {
++        virResetLastError();
++        return false;
++    }
++
++    return virFileExists(path);
++}
++
++
+ virCgroupBackend virCgroupV2Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V2,
+ 
+@@ -1495,6 +1510,7 @@ virCgroupBackend virCgroupV2Backend = {
+     .getCpuCfsPeriod = virCgroupV2GetCpuCfsPeriod,
+     .setCpuCfsQuota = virCgroupV2SetCpuCfsQuota,
+     .getCpuCfsQuota = virCgroupV2GetCpuCfsQuota,
++    .supportsCpuBW = virCgroupV2SupportsCpuBW,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-introduce-virCgroupV2ValidateMachineGroup.patch b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2ValidateMachineGroup.patch
new file mode 100644
index 0000000..976237b
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2ValidateMachineGroup.patch
@@ -0,0 +1,94 @@
+From 3928ca076fac13572f14c20f38bcf5fb205d7670 Mon Sep 17 00:00:00 2001
+Message-Id: <3928ca076fac13572f14c20f38bcf5fb205d7670@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:07:14 +0200
+Subject: [PATCH] vircgroup: introduce virCgroupV2ValidateMachineGroup
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+When reconnecting to a domain we are validating the cgroup name.
+In case of cgroup v2 we need to validate only the new format for host
+without systemd '{machinename}.libvirt-{drivername}' or scope name
+generated by systemd.
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 3a365ef697b8fedb929725c46753481a63ae3de7)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <97d6369bcfc2943c708fd9bfc94f71ab10e00535.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroupv2.c | 43 ++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 43 insertions(+)
+
+diff --git a/src/util/vircgroupv2.c b/src/util/vircgroupv2.c
+index 4ab9f2b792..02dc4e4686 100644
+--- a/src/util/vircgroupv2.c
++++ b/src/util/vircgroupv2.c
+@@ -36,6 +36,7 @@
+ #include "virfile.h"
+ #include "virlog.h"
+ #include "virstring.h"
++#include "virsystemd.h"
+ 
+ VIR_LOG_INIT("util.cgroup");
+ 
+@@ -90,10 +91,52 @@ virCgroupV2Available(void)
+ }
+ 
+ 
++static bool
++virCgroupV2ValidateMachineGroup(virCgroupPtr group,
++                                const char *name ATTRIBUTE_UNUSED,
++                                const char *drivername,
++                                const char *machinename)
++{
++    VIR_AUTOFREE(char *) partmachinename = NULL;
++    VIR_AUTOFREE(char *) scopename = NULL;
++    char *tmp;
++
++    if (virAsprintf(&partmachinename, "%s.libvirt-%s", machinename,
++                    drivername) < 0) {
++        return false;
++    }
++
++    if (virCgroupPartitionEscape(&partmachinename) < 0)
++        return false;
++
++    if (!(scopename = virSystemdMakeScopeName(machinename, drivername,
++                                              false))) {
++        return false;
++    }
++
++    if (virCgroupPartitionEscape(&scopename) < 0)
++        return false;
++
++    if (!(tmp = strrchr(group->unified.placement, '/')))
++        return false;
++    tmp++;
++
++    if (STRNEQ(tmp, partmachinename) &&
++        STRNEQ(tmp, scopename)) {
++        VIR_DEBUG("Name '%s' for unified does not match '%s' or '%s'",
++                  tmp, partmachinename, scopename);
++        return false;
++    }
++
++    return true;
++}
++
++
+ virCgroupBackend virCgroupV2Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V2,
+ 
+     .available = virCgroupV2Available,
++    .validateMachineGroup = virCgroupV2ValidateMachineGroup,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-introduce-virCgroupV2ValidatePlacement.patch b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2ValidatePlacement.patch
new file mode 100644
index 0000000..bfbf697
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-introduce-virCgroupV2ValidatePlacement.patch
@@ -0,0 +1,57 @@
+From 64cc7545de4c32deda12cd1c6088b065c0a09592 Mon Sep 17 00:00:00 2001
+Message-Id: <64cc7545de4c32deda12cd1c6088b065c0a09592@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:07:19 +0200
+Subject: [PATCH] vircgroup: introduce virCgroupV2ValidatePlacement
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 9aa8226d866f7a274179bfe900d441cbd2f5ae12)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <db5e4f6695d27deead1d53a7397101e086261039.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroupv2.c | 15 +++++++++++++++
+ 1 file changed, 15 insertions(+)
+
+diff --git a/src/util/vircgroupv2.c b/src/util/vircgroupv2.c
+index fb1aa2de0a..815d8fca9b 100644
+--- a/src/util/vircgroupv2.c
++++ b/src/util/vircgroupv2.c
+@@ -206,6 +206,20 @@ virCgroupV2DetectPlacement(virCgroupPtr group,
+ }
+ 
+ 
++static int
++virCgroupV2ValidatePlacement(virCgroupPtr group,
++                             pid_t pid ATTRIBUTE_UNUSED)
++{
++    if (!group->unified.placement) {
++        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
++                       _("Could not find placement for v2 controller"));
++        return -1;
++    }
++
++    return 0;
++}
++
++
+ virCgroupBackend virCgroupV2Backend = {
+     .type = VIR_CGROUP_BACKEND_TYPE_V2,
+ 
+@@ -215,6 +229,7 @@ virCgroupBackend virCgroupV2Backend = {
+     .copyPlacement = virCgroupV2CopyPlacement,
+     .detectMounts = virCgroupV2DetectMounts,
+     .detectPlacement = virCgroupV2DetectPlacement,
++    .validatePlacement = virCgroupV2ValidatePlacement,
+ };
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-machinename-will-never-be-NULL.patch b/SOURCES/libvirt-vircgroup-machinename-will-never-be-NULL.patch
new file mode 100644
index 0000000..e1ae46f
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-machinename-will-never-be-NULL.patch
@@ -0,0 +1,87 @@
+From 440629a5a95d167af717a70c8d992e104866229a Mon Sep 17 00:00:00 2001
+Message-Id: <440629a5a95d167af717a70c8d992e104866229a@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:05:59 +0200
+Subject: [PATCH] vircgroup: machinename will never be NULL
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Commit <eaf2c9f89107b9f60cf8db2c919f78b987ff7177> moved machineName
+generation before virCgroupNewDetectMachine() is called.
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit f9d18f89f7df937b922816aeae0024d8bd6dc72e)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <2e0f6a4d02b3f97f5b9efa74a6553d5ce11d077a.1561993099.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c | 27 +++++++++++----------------
+ 1 file changed, 11 insertions(+), 16 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index a2c971fbf4..5adf9d3c11 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -266,27 +266,22 @@ virCgroupValidateMachineGroup(virCgroupPtr group,
+     if (virCgroupPartitionEscape(&partname) < 0)
+         return false;
+ 
+-    if (machinename &&
+-        (virAsprintf(&partmachinename, "%s.libvirt-%s",
+-                     machinename, drivername) < 0 ||
+-         virCgroupPartitionEscape(&partmachinename) < 0))
++    if (virAsprintf(&partmachinename, "%s.libvirt-%s",
++                    machinename, drivername) < 0 ||
++        virCgroupPartitionEscape(&partmachinename) < 0)
+         return false;
+ 
+     if (!(scopename_old = virSystemdMakeScopeName(name, drivername, true)))
+         return false;
+ 
+-    /* We should keep trying even if this failed */
+-    if (!machinename)
+-        virResetLastError();
+-    else if (!(scopename_new = virSystemdMakeScopeName(machinename,
+-                                                       drivername, false)))
++    if (!(scopename_new = virSystemdMakeScopeName(machinename,
++                                                  drivername, false)))
+         return false;
+ 
+     if (virCgroupPartitionEscape(&scopename_old) < 0)
+         return false;
+ 
+-    if (scopename_new &&
+-        virCgroupPartitionEscape(&scopename_new) < 0)
++    if (virCgroupPartitionEscape(&scopename_new) < 0)
+         return false;
+ 
+     for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
+@@ -315,16 +310,16 @@ virCgroupValidateMachineGroup(virCgroupPtr group,
+         tmp++;
+ 
+         if (STRNEQ(tmp, name) &&
+-            STRNEQ_NULLABLE(tmp, machinename) &&
++            STRNEQ(tmp, machinename) &&
+             STRNEQ(tmp, partname) &&
+-            STRNEQ_NULLABLE(tmp, partmachinename) &&
++            STRNEQ(tmp, partmachinename) &&
+             STRNEQ(tmp, scopename_old) &&
+-            STRNEQ_NULLABLE(tmp, scopename_new)) {
++            STRNEQ(tmp, scopename_new)) {
+             VIR_DEBUG("Name '%s' for controller '%s' does not match "
+                       "'%s', '%s', '%s', '%s' or '%s'",
+                       tmp, virCgroupControllerTypeToString(i),
+-                      name, NULLSTR(machinename), partname,
+-                      scopename_old, NULLSTR(scopename_new));
++                      name, machinename, partname,
++                      scopename_old, scopename_new);
+             return false;
+         }
+     }
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-register-cgroup-v2-backend.patch b/SOURCES/libvirt-vircgroup-register-cgroup-v2-backend.patch
new file mode 100644
index 0000000..2b650a3
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-register-cgroup-v2-backend.patch
@@ -0,0 +1,39 @@
+From 6b4f272c7de58d13d89a7ebb981b43ac53c41198 Mon Sep 17 00:00:00 2001
+Message-Id: <6b4f272c7de58d13d89a7ebb981b43ac53c41198@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:07:52 +0200
+Subject: [PATCH] vircgroup: register cgroup v2 backend
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+All mandatory callbacks are implemented for cgroup v2 backend so we
+can register it now.
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit a77f5326919e0d79f01686762ecc8656e4e6adc9)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <9d7990e568c23aa43ccd85011e845c840db97a27.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroupbackend.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/src/util/vircgroupbackend.c b/src/util/vircgroupbackend.c
+index 79fe6cb73d..7ee39ac8ca 100644
+--- a/src/util/vircgroupbackend.c
++++ b/src/util/vircgroupbackend.c
+@@ -52,6 +52,7 @@ virCgroupBackendRegister(virCgroupBackendPtr backend)
+ static void
+ virCgroupBackendOnceInit(void)
+ {
++    virCgroupV2Register();
+     virCgroupV1Register();
+ }
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-remove-VIR_CGROUP_SUPPORTED.patch b/SOURCES/libvirt-vircgroup-remove-VIR_CGROUP_SUPPORTED.patch
new file mode 100644
index 0000000..2e27127
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-remove-VIR_CGROUP_SUPPORTED.patch
@@ -0,0 +1,72 @@
+From 2a09df456c5cceabdd6d6eee167061a74d7de9ea Mon Sep 17 00:00:00 2001
+Message-Id: <2a09df456c5cceabdd6d6eee167061a74d7de9ea@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:07:08 +0200
+Subject: [PATCH] vircgroup: remove VIR_CGROUP_SUPPORTED
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+tests/vircgrouptest.c uses #ifdef __linux__ for a long time and no
+failure was reported so far so it's safe to assume that __linux__ is
+good enough to guard cgroup code.
+
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 0df626698865e5158192a9090dfe4f76c2e44fc5)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <aa849f9f6c3bd44f7167a6ce08f16c4a0b7da72b.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c | 11 +++--------
+ 1 file changed, 3 insertions(+), 8 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index 349c388e0a..f1ecb1dbeb 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -70,11 +70,6 @@ VIR_LOG_INIT("util.cgroup");
+ #define CGROUP_NB_TOTAL_CPU_STAT_PARAM 3
+ #define CGROUP_NB_PER_CPU_STAT_PARAM   1
+ 
+-#if defined(__linux__) && defined(HAVE_GETMNTENT_R) && \
+-    defined(_DIRENT_HAVE_D_TYPE) && defined(_SC_CLK_TCK)
+-# define VIR_CGROUP_SUPPORTED
+-#endif
+-
+ VIR_ENUM_IMPL(virCgroupController, VIR_CGROUP_CONTROLLER_LAST,
+               "cpu", "cpuacct", "cpuset", "memory", "devices",
+               "freezer", "blkio", "net_cls", "perf_event",
+@@ -119,7 +114,7 @@ virCgroupGetDevicePermsString(int perms)
+ }
+ 
+ 
+-#ifdef VIR_CGROUP_SUPPORTED
++#ifdef __linux__
+ bool
+ virCgroupAvailable(void)
+ {
+@@ -2643,7 +2638,7 @@ virCgroupControllerAvailable(int controller)
+     return ret;
+ }
+ 
+-#else /* !VIR_CGROUP_SUPPORTED */
++#else /* !__linux__ */
+ 
+ bool
+ virCgroupAvailable(void)
+@@ -3404,7 +3399,7 @@ virCgroupControllerAvailable(int controller ATTRIBUTE_UNUSED)
+ {
+     return false;
+ }
+-#endif /* !VIR_CGROUP_SUPPORTED */
++#endif /* !__linux__ */
+ 
+ 
+ int
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-rename-controllers-to-legacy.patch b/SOURCES/libvirt-vircgroup-rename-controllers-to-legacy.patch
new file mode 100644
index 0000000..3b79453
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-rename-controllers-to-legacy.patch
@@ -0,0 +1,524 @@
+From da3574e1bcbc4779b516e8bf14f56abf2a19885d Mon Sep 17 00:00:00 2001
+Message-Id: <da3574e1bcbc4779b516e8bf14f56abf2a19885d@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:07:07 +0200
+Subject: [PATCH] vircgroup: rename controllers to legacy
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+With the introduction of cgroup v2 there are new names used with
+cgroups based on which version is used:
+
+    - legacy: cgroup v1
+    - unified: cgroup v2
+    - hybrid: cgroup v1 and cgroup v2
+
+Let's use 'legacy' instead of 'cgroupv1' or 'controllers' in our code.
+
+Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 65ba48d26745450e5079f171052caa7309c99fdf)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <b9853bf7cd21097e0248448362f6178e31ab6279.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroup.c     |   6 +-
+ src/util/vircgrouppriv.h |   2 +-
+ src/util/vircgroupv1.c   | 140 +++++++++++++++++++--------------------
+ tests/vircgrouptest.c    |  14 ++--
+ 4 files changed, 81 insertions(+), 81 deletions(-)
+
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index b159bda1bb..349c388e0a 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -1246,9 +1246,9 @@ virCgroupFree(virCgroupPtr *group)
+         return;
+ 
+     for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
+-        VIR_FREE((*group)->controllers[i].mountPoint);
+-        VIR_FREE((*group)->controllers[i].linkPoint);
+-        VIR_FREE((*group)->controllers[i].placement);
++        VIR_FREE((*group)->legacy[i].mountPoint);
++        VIR_FREE((*group)->legacy[i].linkPoint);
++        VIR_FREE((*group)->legacy[i].placement);
+     }
+ 
+     VIR_FREE((*group)->path);
+diff --git a/src/util/vircgrouppriv.h b/src/util/vircgrouppriv.h
+index ee6aeedbb5..c50a25f195 100644
+--- a/src/util/vircgrouppriv.h
++++ b/src/util/vircgrouppriv.h
+@@ -50,7 +50,7 @@ struct _virCgroup {
+ 
+     virCgroupBackendPtr backend;
+ 
+-    virCgroupV1Controller controllers[VIR_CGROUP_CONTROLLER_LAST];
++    virCgroupV1Controller legacy[VIR_CGROUP_CONTROLLER_LAST];
+ };
+ 
+ int virCgroupSetValueStr(virCgroupPtr group,
+diff --git a/src/util/vircgroupv1.c b/src/util/vircgroupv1.c
+index 0ba8757348..482615f3c8 100644
+--- a/src/util/vircgroupv1.c
++++ b/src/util/vircgroupv1.c
+@@ -127,10 +127,10 @@ virCgroupV1ValidateMachineGroup(virCgroupPtr group,
+         if (i == VIR_CGROUP_CONTROLLER_SYSTEMD)
+             continue;
+ 
+-        if (!group->controllers[i].placement)
++        if (!group->legacy[i].placement)
+             continue;
+ 
+-        tmp = strrchr(group->controllers[i].placement, '/');
++        tmp = strrchr(group->legacy[i].placement, '/');
+         if (!tmp)
+             return false;
+ 
+@@ -139,7 +139,7 @@ virCgroupV1ValidateMachineGroup(virCgroupPtr group,
+             i == VIR_CGROUP_CONTROLLER_CPUSET) {
+             if (STREQ(tmp, "/emulator"))
+                 *tmp = '\0';
+-            tmp = strrchr(group->controllers[i].placement, '/');
++            tmp = strrchr(group->legacy[i].placement, '/');
+             if (!tmp)
+                 return false;
+         }
+@@ -171,15 +171,15 @@ virCgroupV1CopyMounts(virCgroupPtr group,
+ {
+     size_t i;
+     for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
+-        if (!parent->controllers[i].mountPoint)
++        if (!parent->legacy[i].mountPoint)
+             continue;
+ 
+-        if (VIR_STRDUP(group->controllers[i].mountPoint,
+-                       parent->controllers[i].mountPoint) < 0)
++        if (VIR_STRDUP(group->legacy[i].mountPoint,
++                       parent->legacy[i].mountPoint) < 0)
+             return -1;
+ 
+-        if (VIR_STRDUP(group->controllers[i].linkPoint,
+-                       parent->controllers[i].linkPoint) < 0)
++        if (VIR_STRDUP(group->legacy[i].linkPoint,
++                       parent->legacy[i].linkPoint) < 0)
+             return -1;
+     }
+     return 0;
+@@ -193,14 +193,14 @@ virCgroupV1CopyPlacement(virCgroupPtr group,
+ {
+     size_t i;
+     for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
+-        if (!group->controllers[i].mountPoint)
++        if (!group->legacy[i].mountPoint)
+             continue;
+ 
+         if (i == VIR_CGROUP_CONTROLLER_SYSTEMD)
+             continue;
+ 
+         if (path[0] == '/') {
+-            if (VIR_STRDUP(group->controllers[i].placement, path) < 0)
++            if (VIR_STRDUP(group->legacy[i].placement, path) < 0)
+                 return -1;
+         } else {
+             /*
+@@ -208,10 +208,10 @@ virCgroupV1CopyPlacement(virCgroupPtr group,
+              * parent == "/libvirt.service" + path == "" => "/libvirt.service"
+              * parent == "/libvirt.service" + path == "foo" => "/libvirt.service/foo"
+              */
+-            if (virAsprintf(&group->controllers[i].placement,
++            if (virAsprintf(&group->legacy[i].placement,
+                             "%s%s%s",
+-                            parent->controllers[i].placement,
+-                            (STREQ(parent->controllers[i].placement, "/") ||
++                            parent->legacy[i].placement,
++                            (STREQ(parent->legacy[i].placement, "/") ||
+                              STREQ(path, "") ? "" : "/"),
+                             path) < 0)
+                 return -1;
+@@ -320,7 +320,7 @@ virCgroupV1DetectMounts(virCgroupPtr group,
+              * once. We need to save the results of the last one,
+              * and we need to be careful to release the memory used
+              * by previous processing. */
+-            virCgroupV1ControllerPtr controller = &group->controllers[i];
++            virCgroupV1ControllerPtr controller = &group->legacy[i];
+ 
+             VIR_FREE(controller->mountPoint);
+             VIR_FREE(controller->linkPoint);
+@@ -350,19 +350,19 @@ virCgroupV1DetectPlacement(virCgroupPtr group,
+         const char *typestr = virCgroupV1ControllerTypeToString(i);
+ 
+         if (virCgroupV1MountOptsMatchController(controllers, typestr) &&
+-            group->controllers[i].mountPoint != NULL &&
+-            group->controllers[i].placement == NULL) {
++            group->legacy[i].mountPoint != NULL &&
++            group->legacy[i].placement == NULL) {
+             /*
+              * selfpath == "/" + path="" -> "/"
+              * selfpath == "/libvirt.service" + path == "" -> "/libvirt.service"
+              * selfpath == "/libvirt.service" + path == "foo" -> "/libvirt.service/foo"
+              */
+             if (i == VIR_CGROUP_CONTROLLER_SYSTEMD) {
+-                if (VIR_STRDUP(group->controllers[i].placement,
++                if (VIR_STRDUP(group->legacy[i].placement,
+                                selfpath) < 0)
+                     return -1;
+             } else {
+-                if (virAsprintf(&group->controllers[i].placement,
++                if (virAsprintf(&group->legacy[i].placement,
+                                 "%s%s%s", selfpath,
+                                 (STREQ(selfpath, "/") ||
+                                  STREQ(path, "") ? "" : "/"),
+@@ -383,22 +383,22 @@ virCgroupV1ValidatePlacement(virCgroupPtr group,
+     size_t i;
+ 
+     for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
+-        if (!group->controllers[i].mountPoint)
++        if (!group->legacy[i].mountPoint)
+             continue;
+ 
+-        if (!group->controllers[i].placement) {
++        if (!group->legacy[i].placement) {
+             virReportError(VIR_ERR_INTERNAL_ERROR,
+                            _("Could not find placement for v1 controller %s at %s"),
+                            virCgroupV1ControllerTypeToString(i),
+-                           group->controllers[i].placement);
++                           group->legacy[i].placement);
+             return -1;
+         }
+ 
+         VIR_DEBUG("Detected mount/mapping %zu:%s at %s in %s for pid %lld",
+                   i,
+                   virCgroupV1ControllerTypeToString(i),
+-                  group->controllers[i].mountPoint,
+-                  group->controllers[i].placement,
++                  group->legacy[i].mountPoint,
++                  group->legacy[i].placement,
+                   (long long) pid);
+     }
+ 
+@@ -411,7 +411,7 @@ virCgroupV1StealPlacement(virCgroupPtr group)
+ {
+     char *ret = NULL;
+ 
+-    VIR_STEAL_PTR(ret, group->controllers[VIR_CGROUP_CONTROLLER_SYSTEMD].placement);
++    VIR_STEAL_PTR(ret, group->legacy[VIR_CGROUP_CONTROLLER_SYSTEMD].placement);
+ 
+     return ret;
+ }
+@@ -430,7 +430,7 @@ virCgroupV1DetectControllers(virCgroupPtr group,
+         for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
+             if (((1 << i) & controllers)) {
+                 /* Remove non-existent controllers  */
+-                if (!group->controllers[i].mountPoint) {
++                if (!group->legacy[i].mountPoint) {
+                     VIR_DEBUG("Requested controller '%s' not mounted, ignoring",
+                               virCgroupV1ControllerTypeToString(i));
+                     controllers &= ~(1 << i);
+@@ -441,9 +441,9 @@ virCgroupV1DetectControllers(virCgroupPtr group,
+             VIR_DEBUG("Controller '%s' wanted=%s, mount='%s'",
+                       virCgroupV1ControllerTypeToString(i),
+                       (1 << i) & controllers ? "yes" : "no",
+-                      NULLSTR(group->controllers[i].mountPoint));
++                      NULLSTR(group->legacy[i].mountPoint));
+             if (!((1 << i) & controllers) &&
+-                group->controllers[i].mountPoint) {
++                group->legacy[i].mountPoint) {
+                 /* Check whether a request to disable a controller
+                  * clashes with co-mounting of controllers */
+                 for (j = 0; j < VIR_CGROUP_CONTROLLER_LAST; j++) {
+@@ -452,8 +452,8 @@ virCgroupV1DetectControllers(virCgroupPtr group,
+                     if (!((1 << j) & controllers))
+                         continue;
+ 
+-                    if (STREQ_NULLABLE(group->controllers[i].mountPoint,
+-                                       group->controllers[j].mountPoint)) {
++                    if (STREQ_NULLABLE(group->legacy[i].mountPoint,
++                                       group->legacy[j].mountPoint)) {
+                         virReportSystemError(EINVAL,
+                                              _("V1 controller '%s' is not wanted, but '%s' is co-mounted"),
+                                              virCgroupV1ControllerTypeToString(i),
+@@ -461,7 +461,7 @@ virCgroupV1DetectControllers(virCgroupPtr group,
+                         return -1;
+                     }
+                 }
+-                VIR_FREE(group->controllers[i].mountPoint);
++                VIR_FREE(group->legacy[i].mountPoint);
+             }
+         }
+     } else {
+@@ -470,8 +470,8 @@ virCgroupV1DetectControllers(virCgroupPtr group,
+         for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
+             VIR_DEBUG("Controller '%s' present=%s",
+                       virCgroupV1ControllerTypeToString(i),
+-                      group->controllers[i].mountPoint ? "yes" : "no");
+-            if (group->controllers[i].mountPoint == NULL)
++                      group->legacy[i].mountPoint ? "yes" : "no");
++            if (group->legacy[i].mountPoint == NULL)
+                 continue;
+             controllers |= (1 << i);
+         }
+@@ -485,7 +485,7 @@ static bool
+ virCgroupV1HasController(virCgroupPtr group,
+                          int controller)
+ {
+-    return group->controllers[controller].mountPoint != NULL;
++    return group->legacy[controller].mountPoint != NULL;
+ }
+ 
+ 
+@@ -499,9 +499,9 @@ virCgroupV1GetAnyController(virCgroupPtr group)
+          * of '/' to avoid doing bad stuff to the root
+          * cgroup
+          */
+-        if (group->controllers[i].mountPoint &&
+-            group->controllers[i].placement &&
+-            STRNEQ(group->controllers[i].placement, "/")) {
++        if (group->legacy[i].mountPoint &&
++            group->legacy[i].placement &&
++            STRNEQ(group->legacy[i].placement, "/")) {
+             return i;
+         }
+     }
+@@ -516,14 +516,14 @@ virCgroupV1PathOfController(virCgroupPtr group,
+                             const char *key,
+                             char **path)
+ {
+-    if (group->controllers[controller].mountPoint == NULL) {
++    if (group->legacy[controller].mountPoint == NULL) {
+         virReportError(VIR_ERR_INTERNAL_ERROR,
+                        _("v1 controller '%s' is not mounted"),
+                        virCgroupV1ControllerTypeToString(controller));
+         return -1;
+     }
+ 
+-    if (group->controllers[controller].placement == NULL) {
++    if (group->legacy[controller].placement == NULL) {
+         virReportError(VIR_ERR_INTERNAL_ERROR,
+                        _("v1 controller '%s' is not enabled for group"),
+                        virCgroupV1ControllerTypeToString(controller));
+@@ -531,8 +531,8 @@ virCgroupV1PathOfController(virCgroupPtr group,
+     }
+ 
+     if (virAsprintf(path, "%s%s/%s",
+-                    group->controllers[controller].mountPoint,
+-                    group->controllers[controller].placement,
++                    group->legacy[controller].mountPoint,
++                    group->legacy[controller].placement,
+                     key ? key : "") < 0)
+         return -1;
+ 
+@@ -618,7 +618,7 @@ virCgroupV1MakeGroup(virCgroupPtr parent,
+         }
+ 
+         /* Skip over controllers that aren't mounted */
+-        if (!group->controllers[i].mountPoint) {
++        if (!group->legacy[i].mountPoint) {
+             VIR_DEBUG("Skipping unmounted controller %s",
+                       virCgroupV1ControllerTypeToString(i));
+             continue;
+@@ -639,7 +639,7 @@ virCgroupV1MakeGroup(virCgroupPtr parent,
+                  * treat blkio as unmounted if mkdir fails. */
+                 if (i == VIR_CGROUP_CONTROLLER_BLKIO) {
+                     VIR_DEBUG("Ignoring mkdir failure with blkio controller. Kernel probably too old");
+-                    VIR_FREE(group->controllers[i].mountPoint);
++                    VIR_FREE(group->legacy[i].mountPoint);
+                     continue;
+                 } else {
+                     virReportSystemError(errno,
+@@ -649,7 +649,7 @@ virCgroupV1MakeGroup(virCgroupPtr parent,
+                 }
+             }
+             if (i == VIR_CGROUP_CONTROLLER_CPUSET &&
+-                group->controllers[i].mountPoint != NULL &&
++                group->legacy[i].mountPoint != NULL &&
+                 virCgroupV1CpuSetInherit(parent, group) < 0) {
+                 return -1;
+             }
+@@ -659,7 +659,7 @@ virCgroupV1MakeGroup(virCgroupPtr parent,
+              */
+             if ((flags & VIR_CGROUP_MEM_HIERACHY) &&
+                 i == VIR_CGROUP_CONTROLLER_MEMORY &&
+-                group->controllers[i].mountPoint != NULL &&
++                group->legacy[i].mountPoint != NULL &&
+                 virCgroupV1SetMemoryUseHierarchy(group) < 0) {
+                 return -1;
+             }
+@@ -682,7 +682,7 @@ virCgroupV1Remove(virCgroupPtr group)
+         VIR_AUTOFREE(char *) grppath = NULL;
+ 
+         /* Skip over controllers not mounted */
+-        if (!group->controllers[i].mountPoint)
++        if (!group->legacy[i].mountPoint)
+             continue;
+ 
+         /* We must never rmdir() in systemd's hierarchy */
+@@ -691,7 +691,7 @@ virCgroupV1Remove(virCgroupPtr group)
+ 
+         /* Don't delete the root group, if we accidentally
+            ended up in it for some reason */
+-        if (STREQ(group->controllers[i].placement, "/"))
++        if (STREQ(group->legacy[i].placement, "/"))
+             continue;
+ 
+         if (virCgroupV1PathOfController(group,
+@@ -719,7 +719,7 @@ virCgroupV1AddTask(virCgroupPtr group,
+ 
+     for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
+         /* Skip over controllers not mounted */
+-        if (!group->controllers[i].mountPoint)
++        if (!group->legacy[i].mountPoint)
+             continue;
+ 
+         /* We must never add tasks in systemd's hierarchy
+@@ -766,17 +766,17 @@ virCgroupV1IdentifyRoot(virCgroupPtr group)
+ 
+     for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
+         char *tmp;
+-        if (!group->controllers[i].mountPoint)
++        if (!group->legacy[i].mountPoint)
+             continue;
+-        if (!(tmp = strrchr(group->controllers[i].mountPoint, '/'))) {
++        if (!(tmp = strrchr(group->legacy[i].mountPoint, '/'))) {
+             virReportError(VIR_ERR_INTERNAL_ERROR,
+                            _("Could not find directory separator in %s"),
+-                           group->controllers[i].mountPoint);
++                           group->legacy[i].mountPoint);
+             return NULL;
+         }
+ 
+-        if (VIR_STRNDUP(ret, group->controllers[i].mountPoint,
+-                        tmp - group->controllers[i].mountPoint) < 0)
++        if (VIR_STRNDUP(ret, group->legacy[i].mountPoint,
++                        tmp - group->legacy[i].mountPoint) < 0)
+             return NULL;
+         return ret;
+     }
+@@ -820,44 +820,44 @@ virCgroupV1BindMount(virCgroupPtr group,
+     }
+ 
+     for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
+-        if (!group->controllers[i].mountPoint)
++        if (!group->legacy[i].mountPoint)
+             continue;
+ 
+-        if (!virFileExists(group->controllers[i].mountPoint)) {
++        if (!virFileExists(group->legacy[i].mountPoint)) {
+             VIR_AUTOFREE(char *) src = NULL;
+             if (virAsprintf(&src, "%s%s",
+                             oldroot,
+-                            group->controllers[i].mountPoint) < 0)
++                            group->legacy[i].mountPoint) < 0)
+                 return -1;
+ 
+             VIR_DEBUG("Create mount point '%s'",
+-                      group->controllers[i].mountPoint);
+-            if (virFileMakePath(group->controllers[i].mountPoint) < 0) {
++                      group->legacy[i].mountPoint);
++            if (virFileMakePath(group->legacy[i].mountPoint) < 0) {
+                 virReportSystemError(errno,
+                                      _("Unable to create directory %s"),
+-                                     group->controllers[i].mountPoint);
++                                     group->legacy[i].mountPoint);
+                 return -1;
+             }
+ 
+-            if (mount(src, group->controllers[i].mountPoint, "none", MS_BIND,
++            if (mount(src, group->legacy[i].mountPoint, "none", MS_BIND,
+                       NULL) < 0) {
+                 virReportSystemError(errno,
+                                      _("Failed to bind cgroup '%s' on '%s'"),
+-                                     src, group->controllers[i].mountPoint);
++                                     src, group->legacy[i].mountPoint);
+                 return -1;
+             }
+         }
+ 
+-        if (group->controllers[i].linkPoint) {
++        if (group->legacy[i].linkPoint) {
+             VIR_DEBUG("Link mount point '%s' to '%s'",
+-                      group->controllers[i].mountPoint,
+-                      group->controllers[i].linkPoint);
+-            if (symlink(group->controllers[i].mountPoint,
+-                        group->controllers[i].linkPoint) < 0) {
++                      group->legacy[i].mountPoint,
++                      group->legacy[i].linkPoint);
++            if (symlink(group->legacy[i].mountPoint,
++                        group->legacy[i].linkPoint) < 0) {
+                 virReportSystemError(errno,
+                                      _("Unable to symlink directory %s to %s"),
+-                                     group->controllers[i].mountPoint,
+-                                     group->controllers[i].linkPoint);
++                                     group->legacy[i].mountPoint,
++                                     group->legacy[i].linkPoint);
+                 return -1;
+             }
+         }
+@@ -885,11 +885,11 @@ virCgroupV1SetOwner(virCgroupPtr cgroup,
+         if (!((1 << i) & controllers))
+             continue;
+ 
+-        if (!cgroup->controllers[i].mountPoint)
++        if (!cgroup->legacy[i].mountPoint)
+             continue;
+ 
+-        if (virAsprintf(&base, "%s%s", cgroup->controllers[i].mountPoint,
+-                        cgroup->controllers[i].placement) < 0)
++        if (virAsprintf(&base, "%s%s", cgroup->legacy[i].mountPoint,
++                        cgroup->legacy[i].placement) < 0)
+             goto cleanup;
+ 
+         if (virDirOpen(&dh, base) < 0)
+diff --git a/tests/vircgrouptest.c b/tests/vircgrouptest.c
+index 588a6e824d..c4bf987ca1 100644
+--- a/tests/vircgrouptest.c
++++ b/tests/vircgrouptest.c
+@@ -56,25 +56,25 @@ static int validateCgroup(virCgroupPtr cgroup,
+ 
+     for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
+         if (STRNEQ_NULLABLE(expectMountPoint[i],
+-                            cgroup->controllers[i].mountPoint)) {
++                            cgroup->legacy[i].mountPoint)) {
+             fprintf(stderr, "Wrong mount '%s', expected '%s' for '%s'\n",
+-                    cgroup->controllers[i].mountPoint,
++                    cgroup->legacy[i].mountPoint,
+                     expectMountPoint[i],
+                     virCgroupControllerTypeToString(i));
+             return -1;
+         }
+         if (STRNEQ_NULLABLE(expectLinkPoint[i],
+-                            cgroup->controllers[i].linkPoint)) {
++                            cgroup->legacy[i].linkPoint)) {
+             fprintf(stderr, "Wrong link '%s', expected '%s' for '%s'\n",
+-                    cgroup->controllers[i].linkPoint,
++                    cgroup->legacy[i].linkPoint,
+                     expectLinkPoint[i],
+                     virCgroupControllerTypeToString(i));
+             return -1;
+         }
+         if (STRNEQ_NULLABLE(expectPlacement[i],
+-                            cgroup->controllers[i].placement)) {
++                            cgroup->legacy[i].placement)) {
+             fprintf(stderr, "Wrong placement '%s', expected '%s' for '%s'\n",
+-                    cgroup->controllers[i].placement,
++                    cgroup->legacy[i].placement,
+                     expectPlacement[i],
+                     virCgroupControllerTypeToString(i));
+             return -1;
+@@ -174,7 +174,7 @@ testCgroupDetectMounts(const void *args)
+     for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
+         virBufferAsprintf(&buf, "%-12s %s\n",
+                           virCgroupControllerTypeToString(i),
+-                          NULLSTR(group->controllers[i].mountPoint));
++                          NULLSTR(group->legacy[i].mountPoint));
+     }
+     if (virBufferCheckError(&buf) < 0)
+         goto cleanup;
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-rename-virCgroupAdd.-Task-to-virCgroupAdd.-Process.patch b/SOURCES/libvirt-vircgroup-rename-virCgroupAdd.-Task-to-virCgroupAdd.-Process.patch
new file mode 100644
index 0000000..b682d5d
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-rename-virCgroupAdd.-Task-to-virCgroupAdd.-Process.patch
@@ -0,0 +1,222 @@
+From d91f1d09bcd6297034d7a9b87c40036aafc2b20c Mon Sep 17 00:00:00 2001
+Message-Id: <d91f1d09bcd6297034d7a9b87c40036aafc2b20c@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:06:14 +0200
+Subject: [PATCH] vircgroup: rename virCgroupAdd.*Task to virCgroupAdd.*Process
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+In cgroup v2 we need to handle processes and threads differently,
+following patch will introduce virCgroupAddThread.
+
+Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 0772c34685848dabf73574feeb2dd35b2edd9e18)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <75bd43c8342b621a7c01e1431a29bc505e7c155f.1561993099.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/libvirt-lxc.c        |  2 +-
+ src/libvirt_private.syms |  4 ++--
+ src/lxc/lxc_controller.c |  4 ++--
+ src/qemu/qemu_process.c  |  4 ++--
+ src/qemu/qemu_tpm.c      |  2 +-
+ src/util/vircgroup.c     | 32 ++++++++++++++++----------------
+ src/util/vircgroup.h     |  4 ++--
+ 7 files changed, 26 insertions(+), 26 deletions(-)
+
+diff --git a/src/libvirt-lxc.c b/src/libvirt-lxc.c
+index c9f2146487..9bf0174b95 100644
+--- a/src/libvirt-lxc.c
++++ b/src/libvirt-lxc.c
+@@ -306,7 +306,7 @@ int virDomainLxcEnterCGroup(virDomainPtr domain,
+     if (virCgroupNewDetect(domain->id, -1, &cgroup) < 0)
+         goto error;
+ 
+-    if (virCgroupAddTask(cgroup, getpid()) < 0)
++    if (virCgroupAddProcess(cgroup, getpid()) < 0)
+         goto error;
+ 
+     virCgroupFree(&cgroup);
+diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
+index 2ec9d8f4bf..5dd24e2e66 100644
+--- a/src/libvirt_private.syms
++++ b/src/libvirt_private.syms
+@@ -1513,8 +1513,8 @@ virBufferVasprintf;
+ 
+ 
+ # util/vircgroup.h
+-virCgroupAddMachineTask;
+-virCgroupAddTask;
++virCgroupAddMachineProcess;
++virCgroupAddProcess;
+ virCgroupAllowAllDevices;
+ virCgroupAllowDevice;
+ virCgroupAllowDevicePath;
+diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c
+index 4e84391bf5..4ead2dc9f0 100644
+--- a/src/lxc/lxc_controller.c
++++ b/src/lxc/lxc_controller.c
+@@ -875,12 +875,12 @@ static int virLXCControllerSetupCgroupLimits(virLXCControllerPtr ctrl)
+                                             ctrl->nicindexes)))
+         goto cleanup;
+ 
+-    if (virCgroupAddMachineTask(ctrl->cgroup, getpid()) < 0)
++    if (virCgroupAddMachineProcess(ctrl->cgroup, getpid()) < 0)
+         goto cleanup;
+ 
+     /* Add all qemu-nbd tasks to the cgroup */
+     for (i = 0; i < ctrl->nnbdpids; i++) {
+-        if (virCgroupAddMachineTask(ctrl->cgroup, ctrl->nbdpids[i]) < 0)
++        if (virCgroupAddMachineProcess(ctrl->cgroup, ctrl->nbdpids[i]) < 0)
+             goto cleanup;
+     }
+ 
+diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
+index db14d322f5..c21586fa12 100644
+--- a/src/qemu/qemu_process.c
++++ b/src/qemu/qemu_process.c
+@@ -2538,7 +2538,7 @@ qemuProcessSetupPid(virDomainObjPtr vm,
+             goto cleanup;
+ 
+         /* Move the thread to the sub dir */
+-        if (virCgroupAddTask(cgroup, pid) < 0)
++        if (virCgroupAddProcess(cgroup, pid) < 0)
+             goto cleanup;
+ 
+     }
+@@ -2776,7 +2776,7 @@ qemuProcessStartManagedPRDaemon(virDomainObjPtr vm)
+     }
+ 
+     if (priv->cgroup &&
+-        virCgroupAddMachineTask(priv->cgroup, cpid) < 0)
++        virCgroupAddMachineProcess(priv->cgroup, cpid) < 0)
+         goto cleanup;
+ 
+     if (qemuSecurityDomainSetPathLabel(driver, vm, socketPath, true) < 0)
+diff --git a/src/qemu/qemu_tpm.c b/src/qemu/qemu_tpm.c
+index 278b262c48..c64114feac 100644
+--- a/src/qemu/qemu_tpm.c
++++ b/src/qemu/qemu_tpm.c
+@@ -905,7 +905,7 @@ qemuExtTPMSetupCgroup(virQEMUDriverPtr driver,
+                            _("Could not get process id of swtpm"));
+             goto cleanup;
+         }
+-        if (virCgroupAddTask(cgroup, pid) < 0)
++        if (virCgroupAddProcess(cgroup, pid) < 0)
+             goto cleanup;
+         break;
+     case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH:
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index 2328957818..cf510fb019 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -1183,35 +1183,35 @@ virCgroupAddTaskInternal(virCgroupPtr group, pid_t pid, bool withSystemd)
+ }
+ 
+ /**
+- * virCgroupAddTask:
++ * virCgroupAddProcess:
+  *
+- * @group: The cgroup to add a task to
+- * @pid: The pid of the task to add
++ * @group: The cgroup to add a process to
++ * @pid: The pid of the process to add
+  *
+- * Will add the task to all controllers, except the
++ * Will add the process to all controllers, except the
+  * systemd unit controller.
+  *
+  * Returns: 0 on success, -1 on error
+  */
+ int
+-virCgroupAddTask(virCgroupPtr group, pid_t pid)
++virCgroupAddProcess(virCgroupPtr group, pid_t pid)
+ {
+     return virCgroupAddTaskInternal(group, pid, false);
+ }
+ 
+ /**
+- * virCgroupAddMachineTask:
++ * virCgroupAddMachineProcess:
+  *
+- * @group: The cgroup to add a task to
+- * @pid: The pid of the task to add
++ * @group: The cgroup to add a process to
++ * @pid: The pid of the process to add
+  *
+- * Will add the task to all controllers, including the
++ * Will add the process to all controllers, including the
+  * systemd unit controller.
+  *
+  * Returns: 0 on success, -1 on error
+  */
+ int
+-virCgroupAddMachineTask(virCgroupPtr group, pid_t pid)
++virCgroupAddMachineProcess(virCgroupPtr group, pid_t pid)
+ {
+     return virCgroupAddTaskInternal(group, pid, true);
+ }
+@@ -1592,7 +1592,7 @@ virCgroupNewMachineSystemd(const char *name,
+         goto error;
+     }
+ 
+-    if (virCgroupAddTask(*group, pidleader) < 0)
++    if (virCgroupAddProcess(*group, pidleader) < 0)
+         goto error;
+ 
+     return 0;
+@@ -1648,7 +1648,7 @@ virCgroupNewMachineManual(const char *name,
+                                     group) < 0)
+         goto cleanup;
+ 
+-    if (virCgroupAddTask(*group, pidleader) < 0) {
++    if (virCgroupAddProcess(*group, pidleader) < 0) {
+         virErrorPtr saved = virSaveLastError();
+         virCgroupRemove(*group);
+         virCgroupFree(group);
+@@ -4198,8 +4198,8 @@ virCgroupPathOfController(virCgroupPtr group ATTRIBUTE_UNUSED,
+ 
+ 
+ int
+-virCgroupAddTask(virCgroupPtr group ATTRIBUTE_UNUSED,
+-                 pid_t pid ATTRIBUTE_UNUSED)
++virCgroupAddProcess(virCgroupPtr group ATTRIBUTE_UNUSED,
++                    pid_t pid ATTRIBUTE_UNUSED)
+ {
+     virReportSystemError(ENXIO, "%s",
+                          _("Control groups not supported on this platform"));
+@@ -4208,8 +4208,8 @@ virCgroupAddTask(virCgroupPtr group ATTRIBUTE_UNUSED,
+ 
+ 
+ int
+-virCgroupAddMachineTask(virCgroupPtr group ATTRIBUTE_UNUSED,
+-                        pid_t pid ATTRIBUTE_UNUSED)
++virCgroupAddMachineProcess(virCgroupPtr group ATTRIBUTE_UNUSED,
++                           pid_t pid ATTRIBUTE_UNUSED)
+ {
+     virReportSystemError(ENXIO, "%s",
+                          _("Control groups not supported on this platform"));
+diff --git a/src/util/vircgroup.h b/src/util/vircgroup.h
+index ee3b7c7222..bbd4c2ed57 100644
+--- a/src/util/vircgroup.h
++++ b/src/util/vircgroup.h
+@@ -118,8 +118,8 @@ int virCgroupPathOfController(virCgroupPtr group,
+                               const char *key,
+                               char **path);
+ 
+-int virCgroupAddTask(virCgroupPtr group, pid_t pid);
+-int virCgroupAddMachineTask(virCgroupPtr group, pid_t pid);
++int virCgroupAddProcess(virCgroupPtr group, pid_t pid);
++int virCgroupAddMachineProcess(virCgroupPtr group, pid_t pid);
+ 
+ int virCgroupSetBlkioWeight(virCgroupPtr group, unsigned int weight);
+ int virCgroupGetBlkioWeight(virCgroupPtr group, unsigned int *weight);
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroup-rename-virCgroupController-into-virCgroupV1Controller.patch b/SOURCES/libvirt-vircgroup-rename-virCgroupController-into-virCgroupV1Controller.patch
new file mode 100644
index 0000000..a6ed638
--- /dev/null
+++ b/SOURCES/libvirt-vircgroup-rename-virCgroupController-into-virCgroupV1Controller.patch
@@ -0,0 +1,82 @@
+From 648fecd5f67da4d118632251365e5dd93d987d3c Mon Sep 17 00:00:00 2001
+Message-Id: <648fecd5f67da4d118632251365e5dd93d987d3c@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:07:06 +0200
+Subject: [PATCH] vircgroup: rename virCgroupController into
+ virCgroupV1Controller
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit bebf732cfae2c1786cb92e7ba3217c551543e3a9)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <4f23fb7e55cf80372867783a87c95cac02653a94.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgrouppriv.h | 8 ++++----
+ src/util/vircgroupv1.c   | 4 ++--
+ 2 files changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/src/util/vircgrouppriv.h b/src/util/vircgrouppriv.h
+index 38c911e8ed..ee6aeedbb5 100644
+--- a/src/util/vircgrouppriv.h
++++ b/src/util/vircgrouppriv.h
+@@ -32,7 +32,7 @@
+ # include "vircgroup.h"
+ # include "vircgroupbackend.h"
+ 
+-struct _virCgroupController {
++struct _virCgroupV1Controller {
+     int type;
+     char *mountPoint;
+     /* If mountPoint holds several controllers co-mounted,
+@@ -42,15 +42,15 @@ struct _virCgroupController {
+     char *linkPoint;
+     char *placement;
+ };
+-typedef struct _virCgroupController virCgroupController;
+-typedef virCgroupController *virCgroupControllerPtr;
++typedef struct _virCgroupV1Controller virCgroupV1Controller;
++typedef virCgroupV1Controller *virCgroupV1ControllerPtr;
+ 
+ struct _virCgroup {
+     char *path;
+ 
+     virCgroupBackendPtr backend;
+ 
+-    virCgroupController controllers[VIR_CGROUP_CONTROLLER_LAST];
++    virCgroupV1Controller controllers[VIR_CGROUP_CONTROLLER_LAST];
+ };
+ 
+ int virCgroupSetValueStr(virCgroupPtr group,
+diff --git a/src/util/vircgroupv1.c b/src/util/vircgroupv1.c
+index 54e7d6ea9a..0ba8757348 100644
+--- a/src/util/vircgroupv1.c
++++ b/src/util/vircgroupv1.c
+@@ -225,7 +225,7 @@ virCgroupV1CopyPlacement(virCgroupPtr group,
+ static int
+ virCgroupV1ResolveMountLink(const char *mntDir,
+                             const char *typeStr,
+-                            virCgroupControllerPtr controller)
++                            virCgroupV1ControllerPtr controller)
+ {
+     VIR_AUTOFREE(char *) linkSrc = NULL;
+     VIR_AUTOFREE(char *) tmp = NULL;
+@@ -320,7 +320,7 @@ virCgroupV1DetectMounts(virCgroupPtr group,
+              * once. We need to save the results of the last one,
+              * and we need to be careful to release the memory used
+              * by previous processing. */
+-            virCgroupControllerPtr controller = &group->controllers[i];
++            virCgroupV1ControllerPtr controller = &group->controllers[i];
+ 
+             VIR_FREE(controller->mountPoint);
+             VIR_FREE(controller->linkPoint);
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroupmock-add-support-to-test-cgroup-v2.patch b/SOURCES/libvirt-vircgroupmock-add-support-to-test-cgroup-v2.patch
new file mode 100644
index 0000000..55ae3fc
--- /dev/null
+++ b/SOURCES/libvirt-vircgroupmock-add-support-to-test-cgroup-v2.patch
@@ -0,0 +1,253 @@
+From 5b4d8244ee6361111903a956843b03739f006b4a Mon Sep 17 00:00:00 2001
+Message-Id: <5b4d8244ee6361111903a956843b03739f006b4a@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:07:55 +0200
+Subject: [PATCH] vircgroupmock: add support to test cgroup v2
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+We need to create the cgroup v2 sysfs the same way as we do for
+cgroup v1.
+
+This introduces new VIR_CGROUP_MOCK_MODE env variable which will
+configure which cgroup mode each test requires.  There are three
+different modes:
+
+    - legacy: only cgroup v1 is available and it's the default mode
+    - hybrid: both cgroup v1 and cgroup v2 are available and have some
+        controllers
+    - unified: only cgroup v2 is available
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 61ff6021d842a3baf2f6cbc3f37dd272f6c86563)
+
+Conflicts:
+    src/util/vircgroupv2.c: missing commit c0abcca417
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <26937fa61f83f373ff46d4a7d6cc8cb2dfd3c66d.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ tests/vircgroupmock.c | 162 ++++++++++++++++++++++++++++++++++++++----
+ 1 file changed, 147 insertions(+), 15 deletions(-)
+
+diff --git a/tests/vircgroupmock.c b/tests/vircgroupmock.c
+index fcc00a7a7b..2041b1e970 100644
+--- a/tests/vircgroupmock.c
++++ b/tests/vircgroupmock.c
+@@ -36,6 +36,7 @@
+ 
+ # include <stdarg.h>
+ # include "testutilslxc.h"
++# include "viralloc.h"
+ # include "virstring.h"
+ # include "virfile.h"
+ 
+@@ -107,7 +108,8 @@ static int make_file(const char *path,
+     return ret;
+ }
+ 
+-static int make_controller(const char *path, mode_t mode)
++
++static int make_controller_v1(const char *path, mode_t mode)
+ {
+     int ret = -1;
+     const char *controller;
+@@ -233,11 +235,86 @@ static int make_controller(const char *path, mode_t mode)
+         goto cleanup;
+     }
+ 
++# undef MAKE_FILE
++
+     ret = 0;
+  cleanup:
+     return ret;
+ }
+ 
++
++static int make_controller_v2(const char *path, mode_t mode)
++{
++    if (!STRPREFIX(path, fakesysfscgroupdir)) {
++        errno = EINVAL;
++        return -1;
++    }
++
++    if (real_mkdir(path, mode) < 0 && errno != EEXIST)
++        return -1;
++
++# define MAKE_FILE(name, value) \
++    do { \
++        if (make_file(path, name, value) < 0) \
++            return -1; \
++    } while (0)
++
++    MAKE_FILE("cgroup.controllers", "cpu io memory\n");
++    MAKE_FILE("cgroup.subtree_control", "");
++    MAKE_FILE("cgroup.type", "domain\n");
++    MAKE_FILE("cpu.max", "max 100000\n");
++    MAKE_FILE("cpu.stat",
++              "usage_usec 0\n"
++              "user_usec 0\n"
++              "system_usec 0\n"
++              "nr_periods 0\n"
++              "nr_throttled 0\n"
++              "throttled_usec 0\n");
++    MAKE_FILE("cpu.weight", "100\n");
++    MAKE_FILE("memory.current", "1455321088\n");
++    MAKE_FILE("memory.high", "max\n");
++    MAKE_FILE("memory.max", "max\n");
++    MAKE_FILE("memory.stat",
++              "anon 0\n"
++              "file 0\n"
++              "kernel_stack 0\n"
++              "slab 0\n"
++              "sock 0\n"
++              "shmem 0\n"
++              "file_mapped 0\n"
++              "file_dirty 0\n"
++              "file_writeback 0\n"
++              "inactive_anon 0\n"
++              "active_anon 0\n"
++              "inactive_file 0\n"
++              "active_file 0\n"
++              "unevictable 0\n"
++              "slab_reclaimable 0\n"
++              "slab_unreclaimable 0\n"
++              "pgfault 0\n"
++              "pgmajfault 0\n"
++              "pgrefill 0\n"
++              "pgscan 0\n"
++              "pgsteal 0\n"
++              "pgactivate 0\n"
++              "pgdeactivate 0\n"
++              "pglazyfree 0\n"
++              "pglazyfreed 0\n"
++              "workingset_refault 0\n"
++              "workingset_activate 0\n"
++              "workingset_nodereclaim 0\n");
++    MAKE_FILE("memory.swap.current", "0\n");
++    MAKE_FILE("memory.swap.max", "max\n");
++    MAKE_FILE("io.stat", "8:0 rbytes=26828800 wbytes=77062144 rios=2256 wios=7849 dbytes=0 dios=0\n");
++    MAKE_FILE("io.max", "");
++    MAKE_FILE("io.weight", "default 100\n");
++
++# undef MAKE_FILE
++
++    return 0;
++}
++
++
+ static void init_syms(void)
+ {
+     if (real_fopen)
+@@ -251,16 +328,64 @@ static void init_syms(void)
+     VIR_MOCK_REAL_INIT(open);
+ }
+ 
++
++static int make_controller(const char *path, mode_t mode)
++{
++    const char *mock;
++    bool unified = false;
++    bool hybrid = false;
++
++    mock = getenv("VIR_CGROUP_MOCK_MODE");
++    if (mock) {
++        if (STREQ(mock, "unified")) {
++            unified = true;
++        } else if (STREQ(mock, "hybrid")) {
++            hybrid = true;
++        } else {
++            fprintf(stderr, "invalid mode '%s'\n", mock);
++            abort();
++        }
++    }
++
++    if (unified || (hybrid && strstr(path, "unified"))) {
++        return make_controller_v2(path, mode);
++    } else {
++        return make_controller_v1(path, mode);
++    }
++}
++
++
+ static void init_sysfs(void)
+ {
+-    if (fakerootdir && fakesysfscgroupdir)
+-        return;
++    const char *mock;
++    char *newfakerootdir;
++    bool unified = false;
++    bool hybrid = false;
+ 
+-    if (!(fakerootdir = getenv("LIBVIRT_FAKE_ROOT_DIR"))) {
++    if (!(newfakerootdir = getenv("LIBVIRT_FAKE_ROOT_DIR"))) {
+         fprintf(stderr, "Missing LIBVIRT_FAKE_ROOT_DIR env variable\n");
+         abort();
+     }
+ 
++    if (fakerootdir && STREQ(fakerootdir, newfakerootdir))
++        return;
++
++    fakerootdir = newfakerootdir;
++
++    mock = getenv("VIR_CGROUP_MOCK_MODE");
++    if (mock) {
++        if (STREQ(mock, "unified")) {
++            unified = true;
++        } else if (STREQ(mock, "hybrid")) {
++            hybrid = true;
++        } else {
++            fprintf(stderr, "invalid mode '%s'\n", mock);
++            abort();
++        }
++    }
++
++    VIR_FREE(fakesysfscgroupdir);
++
+     if (virAsprintfQuiet(&fakesysfscgroupdir, "%s%s",
+                          fakerootdir, SYSFS_CGROUP_PREFIX) < 0)
+         abort();
+@@ -283,18 +408,25 @@ static void init_sysfs(void)
+         free(path); \
+     } while (0)
+ 
+-    MAKE_CONTROLLER("cpu");
+-    MAKE_CONTROLLER("cpuacct");
+-    MAKE_CONTROLLER("cpu,cpuacct");
+-    MAKE_CONTROLLER("cpu,cpuacct/system");
+-    MAKE_CONTROLLER("cpuset");
+-    MAKE_CONTROLLER("blkio");
+-    MAKE_CONTROLLER("memory");
+-    MAKE_CONTROLLER("freezer");
++    if (unified) {
++        MAKE_CONTROLLER("");
++    } else if (hybrid) {
++        MAKE_CONTROLLER("unified");
++        MAKE_CONTROLLER("cpuset");
++        MAKE_CONTROLLER("freezer");
++    } else {
++        MAKE_CONTROLLER("cpu");
++        MAKE_CONTROLLER("cpuacct");
++        MAKE_CONTROLLER("cpu,cpuacct");
++        MAKE_CONTROLLER("cpuset");
++        MAKE_CONTROLLER("blkio");
++        MAKE_CONTROLLER("memory");
++        MAKE_CONTROLLER("freezer");
+ 
+-    if (make_file(fakesysfscgroupdir,
+-                  SYSFS_CPU_PRESENT_MOCKED, "8-23,48-159\n") < 0)
+-        abort();
++        if (make_file(fakesysfscgroupdir,
++                      SYSFS_CPU_PRESENT_MOCKED, "8-23,48-159\n") < 0)
++            abort();
++    }
+ }
+ 
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroupmock-change-cgroup-prefix.patch b/SOURCES/libvirt-vircgroupmock-change-cgroup-prefix.patch
new file mode 100644
index 0000000..82784b1
--- /dev/null
+++ b/SOURCES/libvirt-vircgroupmock-change-cgroup-prefix.patch
@@ -0,0 +1,104 @@
+From bbb7b7a4cb906bdeaf46ab664ce67a0a27b9ef5d Mon Sep 17 00:00:00 2001
+Message-Id: <bbb7b7a4cb906bdeaf46ab664ce67a0a27b9ef5d@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:07:54 +0200
+Subject: [PATCH] vircgroupmock: change cgroup prefix
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Remove the trailing '/' from prefix.  This change is required in order
+to introduce tests for unified cgroups.  They are usually mounted in
+'/sys/fs/cgroup'.
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 9bd1979e37ca703f8e29c2dfca83a9cd04af2982)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <cdff08c2966b44ad1c3c7d166fc39c20f4bd0ba2.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ tests/vircgroupmock.c | 16 ++++++++--------
+ 1 file changed, 8 insertions(+), 8 deletions(-)
+
+diff --git a/tests/vircgroupmock.c b/tests/vircgroupmock.c
+index 3afe2fe192..fcc00a7a7b 100644
+--- a/tests/vircgroupmock.c
++++ b/tests/vircgroupmock.c
+@@ -58,7 +58,7 @@ const char *fakedevicedir0 = FAKEDEVDIR0;
+ const char *fakedevicedir1 = FAKEDEVDIR1;
+ 
+ 
+-# define SYSFS_CGROUP_PREFIX "/not/really/sys/fs/cgroup/"
++# define SYSFS_CGROUP_PREFIX "/not/really/sys/fs/cgroup"
+ # define SYSFS_CPU_PRESENT "/sys/devices/system/cpu/present"
+ # define SYSFS_CPU_PRESENT_MOCKED "devices_system_cpu_present"
+ 
+@@ -356,7 +356,7 @@ int access(const char *path, int mode)
+     if (STRPREFIX(path, SYSFS_CGROUP_PREFIX)) {
+         init_sysfs();
+         char *newpath;
+-        if (asprintf(&newpath, "%s/%s",
++        if (asprintf(&newpath, "%s%s",
+                      fakesysfscgroupdir,
+                      path + strlen(SYSFS_CGROUP_PREFIX)) < 0) {
+             errno = ENOMEM;
+@@ -388,7 +388,7 @@ int __lxstat(int ver, const char *path, struct stat *sb)
+     if (STRPREFIX(path, SYSFS_CGROUP_PREFIX)) {
+         init_sysfs();
+         char *newpath;
+-        if (asprintf(&newpath, "%s/%s",
++        if (asprintf(&newpath, "%s%s",
+                      fakesysfscgroupdir,
+                      path + strlen(SYSFS_CGROUP_PREFIX)) < 0) {
+             errno = ENOMEM;
+@@ -419,7 +419,7 @@ int lstat(const char *path, struct stat *sb)
+     if (STRPREFIX(path, SYSFS_CGROUP_PREFIX)) {
+         init_sysfs();
+         char *newpath;
+-        if (asprintf(&newpath, "%s/%s",
++        if (asprintf(&newpath, "%s%s",
+                      fakesysfscgroupdir,
+                      path + strlen(SYSFS_CGROUP_PREFIX)) < 0) {
+             errno = ENOMEM;
+@@ -450,7 +450,7 @@ int __xstat(int ver, const char *path, struct stat *sb)
+     if (STRPREFIX(path, SYSFS_CGROUP_PREFIX)) {
+         init_sysfs();
+         char *newpath;
+-        if (asprintf(&newpath, "%s/%s",
++        if (asprintf(&newpath, "%s%s",
+                      fakesysfscgroupdir,
+                      path + strlen(SYSFS_CGROUP_PREFIX)) < 0) {
+             errno = ENOMEM;
+@@ -489,7 +489,7 @@ int stat(const char *path, struct stat *sb)
+         }
+     } else if (STRPREFIX(path, SYSFS_CGROUP_PREFIX)) {
+         init_sysfs();
+-        if (asprintf(&newpath, "%s/%s",
++        if (asprintf(&newpath, "%s%s",
+                      fakesysfscgroupdir,
+                      path + strlen(SYSFS_CGROUP_PREFIX)) < 0) {
+             errno = ENOMEM;
+@@ -521,7 +521,7 @@ int mkdir(const char *path, mode_t mode)
+     if (STRPREFIX(path, SYSFS_CGROUP_PREFIX)) {
+         init_sysfs();
+         char *newpath;
+-        if (asprintf(&newpath, "%s/%s",
++        if (asprintf(&newpath, "%s%s",
+                      fakesysfscgroupdir,
+                      path + strlen(SYSFS_CGROUP_PREFIX)) < 0) {
+             errno = ENOMEM;
+@@ -554,7 +554,7 @@ int open(const char *path, int flags, ...)
+ 
+     if (STRPREFIX(path, SYSFS_CGROUP_PREFIX)) {
+         init_sysfs();
+-        if (asprintf(&newpath, "%s/%s",
++        if (asprintf(&newpath, "%s%s",
+                      fakesysfscgroupdir,
+                      path + strlen(SYSFS_CGROUP_PREFIX)) < 0) {
+             errno = ENOMEM;
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroupmock-cleanup-unused-cgroup-files.patch b/SOURCES/libvirt-vircgroupmock-cleanup-unused-cgroup-files.patch
new file mode 100644
index 0000000..8a2d326
--- /dev/null
+++ b/SOURCES/libvirt-vircgroupmock-cleanup-unused-cgroup-files.patch
@@ -0,0 +1,150 @@
+From 0542ea82913e75374a5efb0c7dde147036d32d20 Mon Sep 17 00:00:00 2001
+Message-Id: <0542ea82913e75374a5efb0c7dde147036d32d20@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:06:17 +0200
+Subject: [PATCH] vircgroupmock: cleanup unused cgroup files
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit f9085cf702f5fe5bf786045b9cc95365ab4e628b)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <efa74d1882ab59aca1379f2a95a568eb0cb02134.1561993099.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ tests/vircgroupmock.c | 73 -------------------------------------------
+ 1 file changed, 73 deletions(-)
+
+diff --git a/tests/vircgroupmock.c b/tests/vircgroupmock.c
+index bae8304f6c..cd5422dcba 100644
+--- a/tests/vircgroupmock.c
++++ b/tests/vircgroupmock.c
+@@ -214,13 +214,7 @@ static int make_controller(const char *path, mode_t mode)
+     if (STRPREFIX(controller, "cpu,cpuacct")) {
+         MAKE_FILE("cpu.cfs_period_us", "100000\n");
+         MAKE_FILE("cpu.cfs_quota_us", "-1\n");
+-        MAKE_FILE("cpu.rt_period_us", "1000000\n");
+-        MAKE_FILE("cpu.rt_runtime_us", "950000\n");
+         MAKE_FILE("cpu.shares", "1024\n");
+-        MAKE_FILE("cpu.stat",
+-                  "nr_periods 0\n"
+-                  "nr_throttled 0\n"
+-                  "throttled_time 0\n");
+         MAKE_FILE("cpuacct.stat",
+                   "user 216687025\n"
+                   "system 43421396\n");
+@@ -235,46 +229,19 @@ static int make_controller(const char *path, mode_t mode)
+                   "709566900 0 0 0 0 0 0 0 444777342 0 0 0 0 0 0 0 "
+                   "5683512916 0 0 0 0 0 0 0 635751356 0 0 0 0 0 0 0\n");
+     } else if (STRPREFIX(controller, "cpuset")) {
+-        MAKE_FILE("cpuset.cpu_exclusive", "1\n");
+         if (STREQ(controller, "cpuset"))
+             MAKE_FILE("cpuset.cpus", "0-1");
+         else
+             MAKE_FILE("cpuset.cpus", ""); /* Values don't inherit */
+-        MAKE_FILE("cpuset.mem_exclusive", "1\n");
+-        MAKE_FILE("cpuset.mem_hardwall", "0\n");
+         MAKE_FILE("cpuset.memory_migrate", "0\n");
+-        MAKE_FILE("cpuset.memory_pressure", "0\n");
+-        MAKE_FILE("cpuset.memory_pressure_enabled", "0\n");
+-        MAKE_FILE("cpuset.memory_spread_page", "0\n");
+-        MAKE_FILE("cpuset.memory_spread_slab", "0\n");
+         if (STREQ(controller, "cpuset"))
+             MAKE_FILE("cpuset.mems", "0");
+         else
+             MAKE_FILE("cpuset.mems", ""); /* Values don't inherit */
+-        MAKE_FILE("cpuset.sched_load_balance", "1\n");
+-        MAKE_FILE("cpuset.sched_relax_domain_level", "-1\n");
+     } else if (STRPREFIX(controller, "memory")) {
+-        MAKE_FILE("memory.failcnt", "0\n");
+-        MAKE_FILE("memory.force_empty", ""); /* Write only */
+-        MAKE_FILE("memory.kmem.tcp.failcnt", "0\n");
+-        MAKE_FILE("memory.kmem.tcp.limit_in_bytes", "9223372036854775807\n");
+-        MAKE_FILE("memory.kmem.tcp.max_usage_in_bytes", "0\n");
+-        MAKE_FILE("memory.kmem.tcp.usage_in_bytes", "16384\n");
+         MAKE_FILE("memory.limit_in_bytes", "9223372036854775807\n");
+-        MAKE_FILE("memory.max_usage_in_bytes", "0\n");
+-        MAKE_FILE("memory.memsw.failcnt", ""); /* Not supported */
+         MAKE_FILE("memory.memsw.limit_in_bytes", ""); /* Not supported */
+-        MAKE_FILE("memory.memsw.max_usage_in_bytes", ""); /* Not supported */
+         MAKE_FILE("memory.memsw.usage_in_bytes", ""); /* Not supported */
+-        MAKE_FILE("memory.move_charge_at_immigrate", "0\n");
+-        MAKE_FILE("memory.numa_stat",
+-                  "total=367664 N0=367664\n"
+-                  "file=314764 N0=314764\n"
+-                  "anon=51999 N0=51999\n"
+-                  "unevictable=901 N0=901\n");
+-        MAKE_FILE("memory.oom_control",
+-                  "oom_kill_disable 0\n"
+-                  "under_oom 0\n");
+         MAKE_FILE("memory.soft_limit_in_bytes", "9223372036854775807\n");
+         MAKE_FILE("memory.stat",
+                   "cache 1336619008\n"
+@@ -306,50 +273,11 @@ static int make_controller(const char *path, mode_t mode)
+                   "recent_rotated_file 2547948\n"
+                   "recent_scanned_anon 113796164\n"
+                   "recent_scanned_file 8199863\n");
+-        MAKE_FILE("memory.swappiness", "60\n");
+         MAKE_FILE("memory.usage_in_bytes", "1455321088\n");
+         MAKE_FILE("memory.use_hierarchy", "0\n");
+     } else if (STRPREFIX(controller, "freezer")) {
+         MAKE_FILE("freezer.state", "THAWED");
+     } else if (STRPREFIX(controller, "blkio")) {
+-        MAKE_FILE("blkio.io_merged",
+-                  "8:0 Read 1100949\n"
+-                  "8:0 Write 2248076\n"
+-                  "8:0 Sync 63063\n"
+-                  "8:0 Async 3285962\n"
+-                  "8:0 Total 3349025\n");
+-        MAKE_FILE("blkio.io_queued",
+-                  "8:0 Read 0\n"
+-                  "8:0 Write 0\n"
+-                  "8:0 Sync 0\n"
+-                  "8:0 Async 0\n"
+-                  "8:0 Total 0\n");
+-        MAKE_FILE("blkio.io_service_bytes",
+-                  "8:0 Read 59542078464\n"
+-                  "8:0 Write 397369182208\n"
+-                  "8:0 Sync 234080922624\n"
+-                  "8:0 Async 222830338048\n"
+-                  "8:0 Total 456911260672\n");
+-        MAKE_FILE("blkio.io_serviced",
+-                  "8:0 Read 3402504\n"
+-                  "8:0 Write 14966516\n"
+-                  "8:0 Sync 12064031\n"
+-                  "8:0 Async 6304989\n"
+-                  "8:0 Total 18369020\n");
+-        MAKE_FILE("blkio.io_service_time",
+-                  "8:0 Read 10747537542349\n"
+-                  "8:0 Write 9200028590575\n"
+-                  "8:0 Sync 6449319855381\n"
+-                  "8:0 Async 13498246277543\n"
+-                  "8:0 Total 19947566132924\n");
+-        MAKE_FILE("blkio.io_wait_time",
+-                  "8:0 Read 14687514824889\n"
+-                  "8:0 Write 357748452187691\n"
+-                  "8:0 Sync 55296974349413\n"
+-                  "8:0 Async 317138992663167\n"
+-                  "8:0 Total 372435967012580\n");
+-        MAKE_FILE("blkio.reset_stats", ""); /* Write only */
+-        MAKE_FILE("blkio.sectors", "8:0 892404806\n");
+         MAKE_FILE("blkio.throttle.io_service_bytes",
+                   "8:0 Read 59542107136\n"
+                   "8:0 Write 411440480256\n"
+@@ -376,7 +304,6 @@ static int make_controller(const char *path, mode_t mode)
+         MAKE_FILE("blkio.throttle.read_iops_device", "");
+         MAKE_FILE("blkio.throttle.write_bps_device", "");
+         MAKE_FILE("blkio.throttle.write_iops_device", "");
+-        MAKE_FILE("blkio.time", "8:0 61019089\n");
+         MAKE_FILE("blkio.weight", "1000\n");
+         MAKE_FILE("blkio.weight_device", "");
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroupmock-rewrite-cgroup-fopen-mocking.patch b/SOURCES/libvirt-vircgroupmock-rewrite-cgroup-fopen-mocking.patch
new file mode 100644
index 0000000..2abb06c
--- /dev/null
+++ b/SOURCES/libvirt-vircgroupmock-rewrite-cgroup-fopen-mocking.patch
@@ -0,0 +1,390 @@
+From d323cd99b256b368c37f0a36eef8b3b2d6213346 Mon Sep 17 00:00:00 2001
+Message-Id: <d323cd99b256b368c37f0a36eef8b3b2d6213346@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:06:18 +0200
+Subject: [PATCH] vircgroupmock: rewrite cgroup fopen mocking
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Move all the cgroup data into separate files out of vircgroupmock.c
+and rework the fopen function to load data from files.  This will
+make it easier to add more test cases.
+
+Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 5cf1b25708328ad4006572801d0829548418cfe7)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <efee26b41a026de90498f4abd724f1c7d85d6731.1561993099.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ tests/vircgroupdata/all-in-one.cgroups     |   7 ++
+ tests/vircgroupdata/all-in-one.mounts      |   2 +-
+ tests/vircgroupdata/all-in-one.parsed      |  12 +-
+ tests/vircgroupdata/all-in-one.self.cgroup |   1 +
+ tests/vircgroupdata/logind.cgroups         |  10 ++
+ tests/vircgroupdata/logind.mounts          |   2 +
+ tests/vircgroupdata/logind.self.cgroup     |   1 +
+ tests/vircgroupdata/systemd.cgroups        |   8 ++
+ tests/vircgroupdata/systemd.mounts         |  11 ++
+ tests/vircgroupdata/systemd.self.cgroup    |   6 +
+ tests/vircgroupmock.c                      | 136 +++------------------
+ tests/vircgrouptest.c                      |  10 +-
+ 12 files changed, 79 insertions(+), 127 deletions(-)
+ create mode 100644 tests/vircgroupdata/all-in-one.cgroups
+ create mode 100644 tests/vircgroupdata/all-in-one.self.cgroup
+ create mode 100644 tests/vircgroupdata/logind.cgroups
+ create mode 100644 tests/vircgroupdata/logind.mounts
+ create mode 100644 tests/vircgroupdata/logind.self.cgroup
+ create mode 100644 tests/vircgroupdata/systemd.cgroups
+ create mode 100644 tests/vircgroupdata/systemd.mounts
+ create mode 100644 tests/vircgroupdata/systemd.self.cgroup
+
+diff --git a/tests/vircgroupdata/all-in-one.cgroups b/tests/vircgroupdata/all-in-one.cgroups
+new file mode 100644
+index 0000000000..7208e5a0b6
+--- /dev/null
++++ b/tests/vircgroupdata/all-in-one.cgroups
+@@ -0,0 +1,7 @@
++#subsys_name    hierarchy       num_cgroups     enabled
++cpuset   6   1  1
++cpu      6   1  1
++cpuacct  6   1  1
++memory   6   1  1
++devices  6   1  1
++blkio    6   1  1
+diff --git a/tests/vircgroupdata/all-in-one.mounts b/tests/vircgroupdata/all-in-one.mounts
+index 14093b961c..76c579ff69 100644
+--- a/tests/vircgroupdata/all-in-one.mounts
++++ b/tests/vircgroupdata/all-in-one.mounts
+@@ -4,4 +4,4 @@ proc /proc proc rw,nosuid,nodev,noexec,relatime 0 0
+ udev /dev devtmpfs rw,relatime,size=16458560k,nr_inodes=4114640,mode=755 0 0
+ devpts /dev/pts devpts rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=000 0 0
+ nfsd /proc/fs/nfsd nfsd rw,relatime 0 0
+-cgroup /sys/fs/cgroup cgroup rw,relatime,blkio,devices,memory,cpuacct,cpu,cpuset 0 0
++cgroup /not/really/sys/fs/cgroup cgroup rw,relatime,blkio,devices,memory,cpuacct,cpu,cpuset 0 0
+diff --git a/tests/vircgroupdata/all-in-one.parsed b/tests/vircgroupdata/all-in-one.parsed
+index 2701778fea..d703d08fb9 100644
+--- a/tests/vircgroupdata/all-in-one.parsed
++++ b/tests/vircgroupdata/all-in-one.parsed
+@@ -1,10 +1,10 @@
+-cpu          /sys/fs/cgroup
+-cpuacct      /sys/fs/cgroup
+-cpuset       /sys/fs/cgroup
+-memory       /sys/fs/cgroup
+-devices      /sys/fs/cgroup
++cpu          /not/really/sys/fs/cgroup
++cpuacct      /not/really/sys/fs/cgroup
++cpuset       /not/really/sys/fs/cgroup
++memory       /not/really/sys/fs/cgroup
++devices      /not/really/sys/fs/cgroup
+ freezer      <null>
+-blkio        /sys/fs/cgroup
++blkio        /not/really/sys/fs/cgroup
+ net_cls      <null>
+ perf_event   <null>
+ name=systemd <null>
+diff --git a/tests/vircgroupdata/all-in-one.self.cgroup b/tests/vircgroupdata/all-in-one.self.cgroup
+new file mode 100644
+index 0000000000..cf237502e9
+--- /dev/null
++++ b/tests/vircgroupdata/all-in-one.self.cgroup
+@@ -0,0 +1 @@
++6:blkio,devices,memory,cpuacct,cpu,cpuset:/
+diff --git a/tests/vircgroupdata/logind.cgroups b/tests/vircgroupdata/logind.cgroups
+new file mode 100644
+index 0000000000..9d46f130e0
+--- /dev/null
++++ b/tests/vircgroupdata/logind.cgroups
+@@ -0,0 +1,10 @@
++#subsys_name    hierarchy       num_cgroups     enabled
++cpuset    0  1  1
++cpu       0  1  1
++cpuacct   0  1  1
++memory    0  1  0
++devices   0  1  1
++freezer   0  1  1
++net_cls   0  1  1
++blkio     0  1  1
++perf_event  0  1  1
+diff --git a/tests/vircgroupdata/logind.mounts b/tests/vircgroupdata/logind.mounts
+new file mode 100644
+index 0000000000..3ab908aee9
+--- /dev/null
++++ b/tests/vircgroupdata/logind.mounts
+@@ -0,0 +1,2 @@
++none /not/really/sys/fs/cgroup tmpfs rw,rootcontext=system_u:object_r:sysfs_t:s0,seclabel,relatime,size=4k,mode=755 0 0
++systemd /not/really/sys/fs/cgroup/systemd cgroup rw,nosuid,nodev,noexec,relatime,name=systemd 0 0
+diff --git a/tests/vircgroupdata/logind.self.cgroup b/tests/vircgroupdata/logind.self.cgroup
+new file mode 100644
+index 0000000000..31e0cfe8eb
+--- /dev/null
++++ b/tests/vircgroupdata/logind.self.cgroup
+@@ -0,0 +1 @@
++0:name=systemd:/
+diff --git a/tests/vircgroupdata/systemd.cgroups b/tests/vircgroupdata/systemd.cgroups
+new file mode 100644
+index 0000000000..d32dfab222
+--- /dev/null
++++ b/tests/vircgroupdata/systemd.cgroups
+@@ -0,0 +1,8 @@
++#subsys_name    hierarchy       num_cgroups     enabled
++cpuset  2       4       1
++cpu     3       48      1
++cpuacct 3       48      1
++memory  4       4       1
++devices 5       4       1
++freezer 6       4       1
++blkio   8       4       1
+diff --git a/tests/vircgroupdata/systemd.mounts b/tests/vircgroupdata/systemd.mounts
+new file mode 100644
+index 0000000000..75572c86f7
+--- /dev/null
++++ b/tests/vircgroupdata/systemd.mounts
+@@ -0,0 +1,11 @@
++rootfs / rootfs rw 0 0
++tmpfs /run tmpfs rw,seclabel,nosuid,nodev,mode=755 0 0
++tmpfs /not/really/sys/fs/cgroup tmpfs rw,seclabel,nosuid,nodev,noexec,mode=755 0 0
++cgroup /not/really/sys/fs/cgroup/systemd cgroup rw,nosuid,nodev,noexec,relatime,release_agent=/usr/lib/systemd/systemd-cgroups-agent,name=systemd 0 0
++cgroup /not/really/sys/fs/cgroup/cpuset cgroup rw,nosuid,nodev,noexec,relatime,cpuset 0 0
++cgroup /not/really/sys/fs/cgroup/cpu,cpuacct cgroup rw,nosuid,nodev,noexec,relatime,cpuacct,cpu 0 0
++cgroup /not/really/sys/fs/cgroup/freezer cgroup rw,nosuid,nodev,noexec,relatime,freezer 0 0
++cgroup /not/really/sys/fs/cgroup/blkio cgroup rw,nosuid,nodev,noexec,relatime,blkio 0 0
++cgroup /not/really/sys/fs/cgroup/memory cgroup rw,nosuid,nodev,noexec,relatime,memory 0 0
++/dev/sda1 /boot ext4 rw,seclabel,relatime,data=ordered 0 0
++tmpfs /tmp tmpfs rw,seclabel,relatime,size=1024000k 0 0
+diff --git a/tests/vircgroupdata/systemd.self.cgroup b/tests/vircgroupdata/systemd.self.cgroup
+new file mode 100644
+index 0000000000..2b95af79d2
+--- /dev/null
++++ b/tests/vircgroupdata/systemd.self.cgroup
+@@ -0,0 +1,6 @@
++115:memory:/
++8:blkio:/
++6:freezer:/
++3:cpuacct,cpu:/system
++2:cpuset:/
++1:name=systemd:/user/berrange/123
+diff --git a/tests/vircgroupmock.c b/tests/vircgroupmock.c
+index cd5422dcba..3afe2fe192 100644
+--- a/tests/vircgroupmock.c
++++ b/tests/vircgroupmock.c
+@@ -81,85 +81,6 @@ const char *fakedevicedir1 = FAKEDEVDIR1;
+  * of files beneath it
+  */
+ 
+-/*
+- * Intentionally missing the 'devices' mount.
+- * Co-mounting cpu & cpuacct controllers
+- * An anonymous controller for systemd
+- */
+-const char *procmounts =
+-    "rootfs / rootfs rw 0 0\n"
+-    "tmpfs /run tmpfs rw,seclabel,nosuid,nodev,mode=755 0 0\n"
+-    "tmpfs /not/really/sys/fs/cgroup tmpfs rw,seclabel,nosuid,nodev,noexec,mode=755 0 0\n"
+-    "cgroup /not/really/sys/fs/cgroup/systemd cgroup rw,nosuid,nodev,noexec,relatime,release_agent=/usr/lib/systemd/systemd-cgroups-agent,name=systemd 0 0\n"
+-    "cgroup /not/really/sys/fs/cgroup/cpuset cgroup rw,nosuid,nodev,noexec,relatime,cpuset 0 0\n"
+-    "cgroup /not/really/sys/fs/cgroup/cpu,cpuacct cgroup rw,nosuid,nodev,noexec,relatime,cpuacct,cpu 0 0\n"
+-    "cgroup /not/really/sys/fs/cgroup/freezer cgroup rw,nosuid,nodev,noexec,relatime,freezer 0 0\n"
+-    "cgroup /not/really/sys/fs/cgroup/blkio cgroup rw,nosuid,nodev,noexec,relatime,blkio 0 0\n"
+-    "cgroup /not/really/sys/fs/cgroup/memory cgroup rw,nosuid,nodev,noexec,relatime,memory 0 0\n"
+-    "/dev/sda1 /boot ext4 rw,seclabel,relatime,data=ordered 0 0\n"
+-    "tmpfs /tmp tmpfs rw,seclabel,relatime,size=1024000k 0 0\n";
+-
+-const char *procselfcgroups =
+-    "115:memory:/\n"
+-    "8:blkio:/\n"
+-    "6:freezer:/\n"
+-    "3:cpuacct,cpu:/system\n"
+-    "2:cpuset:/\n"
+-    "1:name=systemd:/user/berrange/123\n";
+-
+-const char *proccgroups =
+-    "#subsys_name    hierarchy       num_cgroups     enabled\n"
+-    "cpuset  2       4       1\n"
+-    "cpu     3       48      1\n"
+-    "cpuacct 3       48      1\n"
+-    "memory  4       4       1\n"
+-    "devices 5       4       1\n"
+-    "freezer 6       4       1\n"
+-    "blkio   8       4       1\n";
+-
+-
+-const char *procmountsallinone =
+-    "rootfs / rootfs rw 0 0\n"
+-    "sysfs /sys sysfs rw,nosuid,nodev,noexec,relatime 0 0\n"
+-    "proc /proc proc rw,nosuid,nodev,noexec,relatime 0 0\n"
+-    "udev /dev devtmpfs rw,relatime,size=16458560k,nr_inodes=4114640,mode=755 0 0\n"
+-    "devpts /dev/pts devpts rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=000 0 0\n"
+-    "nfsd /proc/fs/nfsd nfsd rw,relatime 0 0\n"
+-    "cgroup /not/really/sys/fs/cgroup cgroup rw,relatime,blkio,devices,memory,cpuacct,cpu,cpuset 0 0\n";
+-
+-const char *procselfcgroupsallinone =
+-    "6:blkio,devices,memory,cpuacct,cpu,cpuset:/";
+-
+-const char *proccgroupsallinone =
+-    "#subsys_name    hierarchy       num_cgroups     enabled\n"
+-    "cpuset   6   1  1\n"
+-    "cpu      6   1  1\n"
+-    "cpuacct  6   1  1\n"
+-    "memory   6   1  1\n"
+-    "devices  6   1  1\n"
+-    "blkio    6   1  1\n";
+-
+-const char *procmountslogind =
+-    "none /not/really/sys/fs/cgroup tmpfs rw,rootcontext=system_u:object_r:sysfs_t:s0,seclabel,relatime,size=4k,mode=755 0 0\n"
+-    "systemd /not/really/sys/fs/cgroup/systemd cgroup rw,nosuid,nodev,noexec,relatime,name=systemd 0 0\n";
+-
+-const char *procselfcgroupslogind =
+-    "1:name=systemd:/\n";
+-
+-const char *proccgroupslogind =
+-    "#subsys_name    hierarchy       num_cgroups     enabled\n"
+-    "cpuset    0  1  1\n"
+-    "cpu       0  1  1\n"
+-    "cpuacct   0  1  1\n"
+-    "memory    0  1  0\n"
+-    "devices   0  1  1\n"
+-    "freezer   0  1  1\n"
+-    "net_cls   0  1  1\n"
+-    "blkio     0  1  1\n"
+-    "perf_event  0  1  1\n";
+-
+-
+-
+ static int make_file(const char *path,
+                      const char *name,
+                      const char *value)
+@@ -379,29 +300,16 @@ static void init_sysfs(void)
+ 
+ FILE *fopen(const char *path, const char *mode)
+ {
+-    const char *mock;
+-    bool allinone = false, logind = false;
+-    init_syms();
++    char *filepath = NULL;
++    const char *type = NULL;
++    FILE *rc = NULL;
++    const char *filename = getenv("VIR_CGROUP_MOCK_FILENAME");
+ 
+-    mock = getenv("VIR_CGROUP_MOCK_MODE");
+-    if (mock) {
+-        if (STREQ(mock, "allinone"))
+-            allinone = true;
+-        else if (STREQ(mock, "logind"))
+-            logind = true;
+-    }
++    init_syms();
+ 
+     if (STREQ(path, "/proc/mounts")) {
+         if (STREQ(mode, "r")) {
+-            if (allinone)
+-                return fmemopen((void *)procmountsallinone,
+-                                strlen(procmountsallinone) + 1, mode);
+-            else if (logind)
+-                return fmemopen((void *)procmountslogind,
+-                                strlen(procmountslogind) + 1, mode);
+-            else
+-                return fmemopen((void *)procmounts,
+-                                strlen(procmounts) + 1, mode);
++            type = "mounts";
+         } else {
+             errno = EACCES;
+             return NULL;
+@@ -409,15 +317,7 @@ FILE *fopen(const char *path, const char *mode)
+     }
+     if (STREQ(path, "/proc/cgroups")) {
+         if (STREQ(mode, "r")) {
+-            if (allinone)
+-                return fmemopen((void *)proccgroupsallinone,
+-                                strlen(proccgroupsallinone) + 1, mode);
+-            else if (logind)
+-                return fmemopen((void *)proccgroupslogind,
+-                                strlen(proccgroupslogind) + 1, mode);
+-            else
+-                return fmemopen((void *)proccgroups,
+-                                strlen(proccgroups) + 1, mode);
++            type = "cgroups";
+         } else {
+             errno = EACCES;
+             return NULL;
+@@ -425,21 +325,25 @@ FILE *fopen(const char *path, const char *mode)
+     }
+     if (STREQ(path, "/proc/self/cgroup")) {
+         if (STREQ(mode, "r")) {
+-            if (allinone)
+-                return fmemopen((void *)procselfcgroupsallinone,
+-                                strlen(procselfcgroupsallinone) + 1, mode);
+-            else if (logind)
+-                return fmemopen((void *)procselfcgroupslogind,
+-                                strlen(procselfcgroupslogind) + 1, mode);
+-            else
+-                return fmemopen((void *)procselfcgroups,
+-                                strlen(procselfcgroups) + 1, mode);
++            type = "self.cgroup";
+         } else {
+             errno = EACCES;
+             return NULL;
+         }
+     }
+ 
++    if (type) {
++        if (!filename)
++            abort();
++        if (virAsprintfQuiet(&filepath, "%s/vircgroupdata/%s.%s",
++                             abs_srcdir, filename, type) < 0) {
++            abort();
++        }
++        rc = real_fopen(filepath, mode);
++        free(filepath);
++        return rc;
++    }
++
+     return real_fopen(path, mode);
+ }
+ 
+diff --git a/tests/vircgrouptest.c b/tests/vircgrouptest.c
+index be50f3e73c..7968903cad 100644
+--- a/tests/vircgrouptest.c
++++ b/tests/vircgrouptest.c
+@@ -890,6 +890,7 @@ mymain(void)
+     DETECT_MOUNTS("no-cgroups");
+     DETECT_MOUNTS("kubevirt");
+ 
++    setenv("VIR_CGROUP_MOCK_FILENAME", "systemd", 1);
+     if (virTestRun("New cgroup for self", testCgroupNewForSelf, NULL) < 0)
+         ret = -1;
+ 
+@@ -925,20 +926,21 @@ mymain(void)
+ 
+     if (virTestRun("virCgroupGetPercpuStats works", testCgroupGetPercpuStats, NULL) < 0)
+         ret = -1;
++    unsetenv("VIR_CGROUP_MOCK_FILENAME");
+ 
+-    setenv("VIR_CGROUP_MOCK_MODE", "allinone", 1);
++    setenv("VIR_CGROUP_MOCK_FILENAME", "all-in-one", 1);
+     if (virTestRun("New cgroup for self (allinone)", testCgroupNewForSelfAllInOne, NULL) < 0)
+         ret = -1;
+     if (virTestRun("Cgroup available", testCgroupAvailable, (void*)0x1) < 0)
+         ret = -1;
+-    unsetenv("VIR_CGROUP_MOCK_MODE");
++    unsetenv("VIR_CGROUP_MOCK_FILENAME");
+ 
+-    setenv("VIR_CGROUP_MOCK_MODE", "logind", 1);
++    setenv("VIR_CGROUP_MOCK_FILENAME", "logind", 1);
+     if (virTestRun("New cgroup for self (logind)", testCgroupNewForSelfLogind, NULL) < 0)
+         ret = -1;
+     if (virTestRun("Cgroup available", testCgroupAvailable, (void*)0x0) < 0)
+         ret = -1;
+-    unsetenv("VIR_CGROUP_MOCK_MODE");
++    unsetenv("VIR_CGROUP_MOCK_FILENAME");
+ 
+     if (getenv("LIBVIRT_SKIP_CLEANUP") == NULL)
+         virFileDeleteTree(fakerootdir);
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgrouptest-add-cgroup-v2-tests.patch b/SOURCES/libvirt-vircgrouptest-add-cgroup-v2-tests.patch
new file mode 100644
index 0000000..4d676e4
--- /dev/null
+++ b/SOURCES/libvirt-vircgrouptest-add-cgroup-v2-tests.patch
@@ -0,0 +1,83 @@
+From 8b85c2ad4afbad2998163ac61b376320b4f392b8 Mon Sep 17 00:00:00 2001
+Message-Id: <8b85c2ad4afbad2998163ac61b376320b4f392b8@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:08:01 +0200
+Subject: [PATCH] vircgrouptest: add cgroup v2 tests
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit edf59855cf9b78fc4dc95f4b2833d87188decc71)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <5354c6c494c94b274e3b366188597ccd0828aefa.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ tests/vircgrouptest.c | 36 ++++++++++++++++++++++++++++++++----
+ 1 file changed, 32 insertions(+), 4 deletions(-)
+
+diff --git a/tests/vircgrouptest.c b/tests/vircgrouptest.c
+index 87f8fa7e67..3b844f0fbf 100644
+--- a/tests/vircgrouptest.c
++++ b/tests/vircgrouptest.c
+@@ -570,14 +570,35 @@ static int testCgroupNewForSelfAllInOne(const void *args ATTRIBUTE_UNUSED)
+ static int testCgroupNewForSelfLogind(const void *args ATTRIBUTE_UNUSED)
+ {
+     virCgroupPtr cgroup = NULL;
+-    int ret = -1;
+ 
+-    if (virCgroupNewSelf(&cgroup) == 0) {
+-        fprintf(stderr, "Expected cgroup creation to fail.\n");
++    if (virCgroupNewSelf(&cgroup) >= 0) {
++        fprintf(stderr, "Expected to fail, only systemd cgroup available.\n");
++        virCgroupFree(&cgroup);
++        return -1;
++    }
++
++    return 0;
++}
++
++
++static int testCgroupNewForSelfUnified(const void *args ATTRIBUTE_UNUSED)
++{
++    virCgroupPtr cgroup = NULL;
++    int ret = -1;
++    const char *empty[VIR_CGROUP_CONTROLLER_LAST] = { 0 };
++    unsigned int controllers =
++        (1 << VIR_CGROUP_CONTROLLER_CPU) |
++        (1 << VIR_CGROUP_CONTROLLER_CPUACCT) |
++        (1 << VIR_CGROUP_CONTROLLER_MEMORY) |
++        (1 << VIR_CGROUP_CONTROLLER_BLKIO);
++
++    if (virCgroupNewSelf(&cgroup) < 0) {
++        fprintf(stderr, "Cannot create cgroup for self\n");
+         goto cleanup;
+     }
+ 
+-    ret = 0;
++    ret = validateCgroup(cgroup, "", empty, empty, empty,
++                         "/not/really/sys/fs/cgroup", "/", controllers);
+  cleanup:
+     virCgroupFree(&cgroup);
+     return ret;
+@@ -994,7 +1015,14 @@ mymain(void)
+         ret = -1;
+     cleanupFakeFS(fakerootdir);
+ 
++    /* cgroup unified */
+ 
++    fakerootdir = initFakeFS("unified", "unified");
++    if (virTestRun("New cgroup for self (unified)", testCgroupNewForSelfUnified, NULL) < 0)
++        ret = -1;
++    if (virTestRun("Cgroup available (unified)", testCgroupAvailable, (void*)0x1) < 0)
++        ret = -1;
++    cleanupFakeFS(fakerootdir);
+ 
+     return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
+ }
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgrouptest-add-detect-mounts-test-for-cgroup-v2.patch b/SOURCES/libvirt-vircgrouptest-add-detect-mounts-test-for-cgroup-v2.patch
new file mode 100644
index 0000000..38cbd13
--- /dev/null
+++ b/SOURCES/libvirt-vircgrouptest-add-detect-mounts-test-for-cgroup-v2.patch
@@ -0,0 +1,115 @@
+From ab8447f6e6a5ab8e3d278be61bc9ccc93c435d3b Mon Sep 17 00:00:00 2001
+Message-Id: <ab8447f6e6a5ab8e3d278be61bc9ccc93c435d3b@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:07:58 +0200
+Subject: [PATCH] vircgrouptest: add detect mounts test for cgroup v2
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 8f43c7a698b7a360d508eccc82ffc08e930cc3f8)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <10b25253a0f4705093b96cfe56a0c64bb2114785.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ tests/vircgroupdata/unified.cgroups     | 13 +++++++++++++
+ tests/vircgroupdata/unified.mounts      | 20 ++++++++++++++++++++
+ tests/vircgroupdata/unified.parsed      | 11 +++++++++++
+ tests/vircgroupdata/unified.self.cgroup |  1 +
+ tests/vircgrouptest.c                   |  3 +++
+ 5 files changed, 48 insertions(+)
+ create mode 100644 tests/vircgroupdata/unified.cgroups
+ create mode 100644 tests/vircgroupdata/unified.mounts
+ create mode 100644 tests/vircgroupdata/unified.parsed
+ create mode 100644 tests/vircgroupdata/unified.self.cgroup
+
+diff --git a/tests/vircgroupdata/unified.cgroups b/tests/vircgroupdata/unified.cgroups
+new file mode 100644
+index 0000000000..e0d8a3561c
+--- /dev/null
++++ b/tests/vircgroupdata/unified.cgroups
+@@ -0,0 +1,13 @@
++#subsys_name	hierarchy	num_cgroups	enabled
++cpuset      0       1       1
++cpu         0       1       1
++cpuacct     0       1       1
++blkio       0       1       1
++memory      0       1       1
++devices     0       1       1
++freezer     0       1       1
++net_cls     0       1       1
++perf_event  0       1       1
++net_prio    0       1       1
++hugetlb     0       1       1
++pids        0       1       1
+diff --git a/tests/vircgroupdata/unified.mounts b/tests/vircgroupdata/unified.mounts
+new file mode 100644
+index 0000000000..b4ab94a2c3
+--- /dev/null
++++ b/tests/vircgroupdata/unified.mounts
+@@ -0,0 +1,20 @@
++sysfs /sys sysfs rw,seclabel,nosuid,nodev,noexec,relatime 0 0
++proc /proc proc rw,nosuid,nodev,noexec,relatime 0 0
++devtmpfs /dev devtmpfs rw,seclabel,nosuid,size=1009844k,nr_inodes=252461,mode=755 0 0
++securityfs /sys/kernel/security securityfs rw,nosuid,nodev,noexec,relatime 0 0
++tmpfs /dev/shm tmpfs rw,seclabel,nosuid,nodev 0 0
++devpts /dev/pts devpts rw,seclabel,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=000 0 0
++tmpfs /run tmpfs rw,seclabel,nosuid,nodev,mode=755 0 0
++cgroup2 /not/really/sys/fs/cgroup cgroup2 rw,seclabel,nosuid,nodev,noexec,relatime,nsdelegate 0 0
++pstore /sys/fs/pstore pstore rw,seclabel,nosuid,nodev,noexec,relatime 0 0
++bpf /sys/fs/bpf bpf rw,nosuid,nodev,noexec,relatime,mode=700 0 0
++configfs /sys/kernel/config configfs rw,relatime 0 0
++/dev/vda2 / ext4 rw,seclabel,relatime 0 0
++selinuxfs /sys/fs/selinux selinuxfs rw,relatime 0 0
++debugfs /sys/kernel/debug debugfs rw,seclabel,relatime 0 0
++hugetlbfs /dev/hugepages hugetlbfs rw,seclabel,relatime,pagesize=2M 0 0
++systemd-1 /proc/sys/fs/binfmt_misc autofs rw,relatime,fd=40,pgrp=1,timeout=0,minproto=5,maxproto=5,direct,pipe_ino=14586 0 0
++mqueue /dev/mqueue mqueue rw,seclabel,relatime 0 0
++tmpfs /tmp tmpfs rw,seclabel,nosuid,nodev 0 0
++sunrpc /var/lib/nfs/rpc_pipefs rpc_pipefs rw,relatime 0 0
++tmpfs /run/user/0 tmpfs rw,seclabel,nosuid,nodev,relatime,size=204000k,mode=700 0 0
+diff --git a/tests/vircgroupdata/unified.parsed b/tests/vircgroupdata/unified.parsed
+new file mode 100644
+index 0000000000..3de0fc643d
+--- /dev/null
++++ b/tests/vircgroupdata/unified.parsed
+@@ -0,0 +1,11 @@
++cpu          <null>
++cpuacct      <null>
++cpuset       <null>
++memory       <null>
++devices      <null>
++freezer      <null>
++blkio        <null>
++net_cls      <null>
++perf_event   <null>
++name=systemd <null>
++unified      /not/really/sys/fs/cgroup
+diff --git a/tests/vircgroupdata/unified.self.cgroup b/tests/vircgroupdata/unified.self.cgroup
+new file mode 100644
+index 0000000000..1e027b2a3c
+--- /dev/null
++++ b/tests/vircgroupdata/unified.self.cgroup
+@@ -0,0 +1 @@
++0::/
+diff --git a/tests/vircgrouptest.c b/tests/vircgrouptest.c
+index b66682e6c8..1ce1371ddc 100644
+--- a/tests/vircgrouptest.c
++++ b/tests/vircgrouptest.c
+@@ -900,6 +900,9 @@ mymain(void)
+     DETECT_MOUNTS("all-in-one");
+     DETECT_MOUNTS_FAIL("no-cgroups");
+     DETECT_MOUNTS("kubevirt");
++    fakerootdir = initFakeFS("unified", NULL);
++    DETECT_MOUNTS("unified");
++    cleanupFakeFS(fakerootdir);
+ 
+     fakerootdir = initFakeFS(NULL, "systemd");
+     if (virTestRun("New cgroup for self", testCgroupNewForSelf, NULL) < 0)
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgrouptest-add-detect-mounts-test-for-hybrid-cgroups.patch b/SOURCES/libvirt-vircgrouptest-add-detect-mounts-test-for-hybrid-cgroups.patch
new file mode 100644
index 0000000..298390f
--- /dev/null
+++ b/SOURCES/libvirt-vircgrouptest-add-detect-mounts-test-for-hybrid-cgroups.patch
@@ -0,0 +1,125 @@
+From 804df2c86f609fee35603273329f773e6eead7a8 Mon Sep 17 00:00:00 2001
+Message-Id: <804df2c86f609fee35603273329f773e6eead7a8@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:07:59 +0200
+Subject: [PATCH] vircgrouptest: add detect mounts test for hybrid cgroups
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 1981c79c4b068b918c3f34093ed2e634811b4147)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <8692433b683cef60139ee0b11052fd7f0de9ea41.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ tests/vircgroupdata/hybrid.cgroups     | 12 ++++++++++++
+ tests/vircgroupdata/hybrid.mounts      | 23 +++++++++++++++++++++++
+ tests/vircgroupdata/hybrid.parsed      | 11 +++++++++++
+ tests/vircgroupdata/hybrid.self.cgroup |  9 +++++++++
+ tests/vircgrouptest.c                  |  3 +++
+ 5 files changed, 58 insertions(+)
+ create mode 100644 tests/vircgroupdata/hybrid.cgroups
+ create mode 100644 tests/vircgroupdata/hybrid.mounts
+ create mode 100644 tests/vircgroupdata/hybrid.parsed
+ create mode 100644 tests/vircgroupdata/hybrid.self.cgroup
+
+diff --git a/tests/vircgroupdata/hybrid.cgroups b/tests/vircgroupdata/hybrid.cgroups
+new file mode 100644
+index 0000000000..7f3bc7b8cb
+--- /dev/null
++++ b/tests/vircgroupdata/hybrid.cgroups
+@@ -0,0 +1,12 @@
++#subsys_name	hierarchy	num_cgroups	enabled
++cpuset      2       1       1
++cpu         0       1       1
++cpuacct     0       1       1
++blkio       0       1       1
++memory      0       1       1
++devices     3       1       1
++freezer     5       1       1
++net_cls     4       1       1
++perf_event  6       1       1
++hugetlb     7       1       1
++pids        8       1       1
+diff --git a/tests/vircgroupdata/hybrid.mounts b/tests/vircgroupdata/hybrid.mounts
+new file mode 100644
+index 0000000000..d6f5f82115
+--- /dev/null
++++ b/tests/vircgroupdata/hybrid.mounts
+@@ -0,0 +1,23 @@
++proc /proc proc rw,nosuid,nodev,noexec,relatime 0 0
++sysfs /sys sysfs rw,nosuid,nodev,noexec,relatime 0 0
++devtmpfs /dev devtmpfs rw,nosuid,size=10240k,nr_inodes=502705,mode=755 0 0
++devpts /dev/pts devpts rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=000 0 0
++tmpfs /dev/shm tmpfs rw,nosuid,nodev,noexec 0 0
++tmpfs /run tmpfs rw,nosuid,nodev,noexec,mode=755 0 0
++mqueue /dev/mqueue mqueue rw,nosuid,nodev,noexec,relatime 0 0
++securityfs /sys/kernel/security securityfs rw,nosuid,nodev,noexec,relatime 0 0
++debugfs /sys/kernel/debug debugfs rw,nosuid,nodev,noexec,relatime 0 0
++configfs /sys/kernel/config configfs rw,nosuid,nodev,noexec,relatime 0 0
++fusectl /sys/fs/fuse/connections fusectl rw,nosuid,nodev,noexec,relatime 0 0
++selinuxfs /sys/fs/selinux selinuxfs rw,relatime 0 0
++pstore /sys/fs/pstore pstore rw,nosuid,nodev,noexec,relatime 0 0
++cgroup_root /not/really/sys/fs/cgroup tmpfs rw,nosuid,nodev,noexec,relatime,size=10240k,mode=755 0 0
++openrc /not/really/sys/fs/cgroup/openrc cgroup rw,nosuid,nodev,noexec,relatime,release_agent=/lib64/rc/sh/cgroup-release-agent.sh,name=openrc 0 0
++none /not/really/sys/fs/cgroup/unified cgroup2 rw,nosuid,nodev,noexec,relatime,nsdelegate 0 0
++cpuset /not/really/sys/fs/cgroup/cpuset cgroup rw,nosuid,nodev,noexec,relatime,cpuset 0 0
++devices /not/really/sys/fs/cgroup/devices cgroup rw,nosuid,nodev,noexec,relatime,devices 0 0
++net_cls /not/really/sys/fs/cgroup/net_cls cgroup rw,nosuid,nodev,noexec,relatime,net_cls 0 0
++freezer /not/really/sys/fs/cgroup/freezer cgroup rw,nosuid,nodev,noexec,relatime,freezer 0 0
++perf_event /not/really/sys/fs/cgroup/perf_event cgroup rw,nosuid,nodev,noexec,relatime,perf_event 0 0
++hugetlb /not/really/sys/fs/cgroup/hugetlb cgroup rw,nosuid,nodev,noexec,relatime,hugetlb 0 0
++pids /not/really/sys/fs/cgroup/pids cgroup rw,nosuid,nodev,noexec,relatime,pids 0 0
+diff --git a/tests/vircgroupdata/hybrid.parsed b/tests/vircgroupdata/hybrid.parsed
+new file mode 100644
+index 0000000000..7600de5f45
+--- /dev/null
++++ b/tests/vircgroupdata/hybrid.parsed
+@@ -0,0 +1,11 @@
++cpu          <null>
++cpuacct      <null>
++cpuset       /not/really/sys/fs/cgroup/cpuset
++memory       <null>
++devices      /not/really/sys/fs/cgroup/devices
++freezer      /not/really/sys/fs/cgroup/freezer
++blkio        <null>
++net_cls      /not/really/sys/fs/cgroup/net_cls
++perf_event   /not/really/sys/fs/cgroup/perf_event
++name=systemd <null>
++unified      /not/really/sys/fs/cgroup/unified
+diff --git a/tests/vircgroupdata/hybrid.self.cgroup b/tests/vircgroupdata/hybrid.self.cgroup
+new file mode 100644
+index 0000000000..2a08905c91
+--- /dev/null
++++ b/tests/vircgroupdata/hybrid.self.cgroup
+@@ -0,0 +1,9 @@
++8:pids:/
++7:hugetlb:/
++6:perf_event:/
++5:freezer:/
++4:net_cls:/
++3:devices:/
++2:cpuset:/
++1:name=openrc:/
++0::/
+diff --git a/tests/vircgrouptest.c b/tests/vircgrouptest.c
+index 1ce1371ddc..aeb2840823 100644
+--- a/tests/vircgrouptest.c
++++ b/tests/vircgrouptest.c
+@@ -903,6 +903,9 @@ mymain(void)
+     fakerootdir = initFakeFS("unified", NULL);
+     DETECT_MOUNTS("unified");
+     cleanupFakeFS(fakerootdir);
++    fakerootdir = initFakeFS("hybrid", NULL);
++    DETECT_MOUNTS("hybrid");
++    cleanupFakeFS(fakerootdir);
+ 
+     fakerootdir = initFakeFS(NULL, "systemd");
+     if (virTestRun("New cgroup for self", testCgroupNewForSelf, NULL) < 0)
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgrouptest-add-hybrid-tests.patch b/SOURCES/libvirt-vircgrouptest-add-hybrid-tests.patch
new file mode 100644
index 0000000..b01a628
--- /dev/null
+++ b/SOURCES/libvirt-vircgrouptest-add-hybrid-tests.patch
@@ -0,0 +1,90 @@
+From 0628a57a5b4a28d644970a2ad82cfadc14a3cd9f Mon Sep 17 00:00:00 2001
+Message-Id: <0628a57a5b4a28d644970a2ad82cfadc14a3cd9f@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:08:02 +0200
+Subject: [PATCH] vircgrouptest: add hybrid tests
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit a26de856f98119bf651ed9928c64b6f96f78f185)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <434692bd0df2a6f28c93e3cc071187144820d836.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ tests/vircgrouptest.c | 48 +++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 48 insertions(+)
+
+diff --git a/tests/vircgrouptest.c b/tests/vircgrouptest.c
+index 3b844f0fbf..7fde50b463 100644
+--- a/tests/vircgrouptest.c
++++ b/tests/vircgrouptest.c
+@@ -605,6 +605,45 @@ static int testCgroupNewForSelfUnified(const void *args ATTRIBUTE_UNUSED)
+ }
+ 
+ 
++static int testCgroupNewForSelfHybrid(const void *args ATTRIBUTE_UNUSED)
++{
++    virCgroupPtr cgroup = NULL;
++    int ret = -1;
++    const char *empty[VIR_CGROUP_CONTROLLER_LAST] = { 0 };
++    const char *mounts[VIR_CGROUP_CONTROLLER_LAST] = {
++        [VIR_CGROUP_CONTROLLER_CPUSET] = "/not/really/sys/fs/cgroup/cpuset",
++        [VIR_CGROUP_CONTROLLER_DEVICES] = "/not/really/sys/fs/cgroup/devices",
++        [VIR_CGROUP_CONTROLLER_FREEZER] = "/not/really/sys/fs/cgroup/freezer",
++        [VIR_CGROUP_CONTROLLER_NET_CLS] = "/not/really/sys/fs/cgroup/net_cls",
++        [VIR_CGROUP_CONTROLLER_PERF_EVENT] = "/not/really/sys/fs/cgroup/perf_event",
++    };
++    const char *placement[VIR_CGROUP_CONTROLLER_LAST] = {
++        [VIR_CGROUP_CONTROLLER_CPUSET] = "/",
++        [VIR_CGROUP_CONTROLLER_DEVICES] = "/",
++        [VIR_CGROUP_CONTROLLER_FREEZER] = "/",
++        [VIR_CGROUP_CONTROLLER_NET_CLS] = "/",
++        [VIR_CGROUP_CONTROLLER_PERF_EVENT] = "/",
++    };
++    unsigned int controllers =
++        (1 << VIR_CGROUP_CONTROLLER_CPU) |
++        (1 << VIR_CGROUP_CONTROLLER_CPUACCT) |
++        (1 << VIR_CGROUP_CONTROLLER_MEMORY) |
++        (1 << VIR_CGROUP_CONTROLLER_BLKIO);
++
++    if (virCgroupNewSelf(&cgroup) < 0) {
++        fprintf(stderr, "Cannot create cgroup for self\n");
++        goto cleanup;
++    }
++
++    ret = validateCgroup(cgroup, "", mounts, empty, placement,
++                         "/not/really/sys/fs/cgroup/unified", "/", controllers);
++
++ cleanup:
++    virCgroupFree(&cgroup);
++    return ret;
++}
++
++
+ static int testCgroupAvailable(const void *args)
+ {
+     bool got = virCgroupAvailable();
+@@ -1024,6 +1063,15 @@ mymain(void)
+         ret = -1;
+     cleanupFakeFS(fakerootdir);
+ 
++    /* cgroup hybrid */
++
++    fakerootdir = initFakeFS("hybrid", "hybrid");
++    if (virTestRun("New cgroup for self (hybrid)", testCgroupNewForSelfHybrid, NULL) < 0)
++        ret = -1;
++    if (virTestRun("Cgroup available (hybrid)", testCgroupAvailable, (void*)0x1) < 0)
++        ret = -1;
++    cleanupFakeFS(fakerootdir);
++
+     return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
+ }
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgrouptest-call-virCgroupDetectMounts-directly.patch b/SOURCES/libvirt-vircgrouptest-call-virCgroupDetectMounts-directly.patch
new file mode 100644
index 0000000..77285a2
--- /dev/null
+++ b/SOURCES/libvirt-vircgrouptest-call-virCgroupDetectMounts-directly.patch
@@ -0,0 +1,163 @@
+From 094b38a5c13a27f2f48897bd8cf811741a754db7 Mon Sep 17 00:00:00 2001
+Message-Id: <094b38a5c13a27f2f48897bd8cf811741a754db7@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:06:19 +0200
+Subject: [PATCH] vircgrouptest: call virCgroupDetectMounts directly
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Because we can set which files to return for cgroup tests there
+is no need to have special function tailored to run tests.
+
+Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 4988f4b347d3c56af4bdb9852d1461f08f6cfced)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <5b3185e7dd49ac4d9a56532e6d77ad1aa098db95.1561993099.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/libvirt_private.syms |  2 +-
+ src/util/vircgroup.c     | 21 +++++----------------
+ src/util/vircgrouppriv.h |  4 +---
+ tests/vircgrouptest.c    | 16 ++++++++--------
+ 4 files changed, 15 insertions(+), 28 deletions(-)
+
+diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
+index f8c1a0df16..b66beb7f91 100644
+--- a/src/libvirt_private.syms
++++ b/src/libvirt_private.syms
+@@ -1528,7 +1528,7 @@ virCgroupDelThread;
+ virCgroupDenyAllDevices;
+ virCgroupDenyDevice;
+ virCgroupDenyDevicePath;
+-virCgroupDetectMountsFromFile;
++virCgroupDetectMounts;
+ virCgroupFree;
+ virCgroupGetBlkioDeviceReadBps;
+ virCgroupGetBlkioDeviceReadIops;
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index f08fe3600e..53f5faafd2 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -430,9 +430,7 @@ virCgroupMountOptsMatchController(const char *mntOpts,
+  * mounted and where
+  */
+ int
+-virCgroupDetectMountsFromFile(virCgroupPtr group,
+-                              const char *path,
+-                              bool checkLinks)
++virCgroupDetectMounts(virCgroupPtr group)
+ {
+     size_t i;
+     FILE *mounts = NULL;
+@@ -440,9 +438,9 @@ virCgroupDetectMountsFromFile(virCgroupPtr group,
+     char buf[CGROUP_MAX_VAL];
+     int ret = -1;
+ 
+-    mounts = fopen(path, "r");
++    mounts = fopen("/proc/mounts", "r");
+     if (mounts == NULL) {
+-        virReportSystemError(errno, _("Unable to open %s"), path);
++        virReportSystemError(errno, "%s", _("Unable to open /proc/mounts"));
+         return -1;
+     }
+ 
+@@ -470,8 +468,7 @@ virCgroupDetectMountsFromFile(virCgroupPtr group,
+ 
+                 /* If it is a co-mount it has a filename like "cpu,cpuacct"
+                  * and we must identify the symlink path */
+-                if (checkLinks &&
+-                    virCgroupResolveMountLink(entry.mnt_dir, typestr,
++                if (virCgroupResolveMountLink(entry.mnt_dir, typestr,
+                                               controller) < 0) {
+                     goto cleanup;
+                 }
+@@ -485,12 +482,6 @@ virCgroupDetectMountsFromFile(virCgroupPtr group,
+     return ret;
+ }
+ 
+-static int
+-virCgroupDetectMounts(virCgroupPtr group)
+-{
+-    return virCgroupDetectMountsFromFile(group, "/proc/mounts", true);
+-}
+-
+ 
+ static int
+ virCgroupCopyPlacement(virCgroupPtr group,
+@@ -4090,9 +4081,7 @@ virCgroupAvailable(void)
+ 
+ 
+ int
+-virCgroupDetectMountsFromFile(virCgroupPtr group ATTRIBUTE_UNUSED,
+-                              const char *path ATTRIBUTE_UNUSED,
+-                              bool checkLinks ATTRIBUTE_UNUSED)
++virCgroupDetectMounts(virCgroupPtr group ATTRIBUTE_UNUSED)
+ {
+     virReportSystemError(ENXIO, "%s",
+                          _("Control groups not supported on this platform"));
+diff --git a/src/util/vircgrouppriv.h b/src/util/vircgrouppriv.h
+index a0034f3889..f78fe8bb9c 100644
+--- a/src/util/vircgrouppriv.h
++++ b/src/util/vircgrouppriv.h
+@@ -50,9 +50,7 @@ struct _virCgroup {
+     virCgroupController controllers[VIR_CGROUP_CONTROLLER_LAST];
+ };
+ 
+-int virCgroupDetectMountsFromFile(virCgroupPtr group,
+-                                  const char *path,
+-                                  bool checkLinks);
++int virCgroupDetectMounts(virCgroupPtr group);
+ 
+ int virCgroupNewPartition(const char *path,
+                           bool create,
+diff --git a/tests/vircgrouptest.c b/tests/vircgrouptest.c
+index 7968903cad..6a38091a86 100644
+--- a/tests/vircgrouptest.c
++++ b/tests/vircgrouptest.c
+@@ -164,21 +164,21 @@ testCgroupDetectMounts(const void *args)
+ {
+     int result = -1;
+     const char *file = args;
+-    char *mounts = NULL;
+     char *parsed = NULL;
+     const char *actual;
+     virCgroupPtr group = NULL;
+     virBuffer buf = VIR_BUFFER_INITIALIZER;
+     size_t i;
+ 
+-    if (virAsprintf(&mounts, "%s/vircgroupdata/%s.mounts",
+-                    abs_srcdir, file) < 0 ||
+-        virAsprintf(&parsed, "%s/vircgroupdata/%s.parsed",
+-                    abs_srcdir, file) < 0 ||
+-        VIR_ALLOC(group) < 0)
++    setenv("VIR_CGROUP_MOCK_FILENAME", file, 1);
++
++    if (virAsprintf(&parsed, "%s/vircgroupdata/%s.parsed", abs_srcdir, file) < 0)
+         goto cleanup;
+ 
+-    if (virCgroupDetectMountsFromFile(group, mounts, false) < 0)
++    if (VIR_ALLOC(group) < 0)
++        goto cleanup;
++
++    if (virCgroupDetectMounts(group) < 0)
+         goto cleanup;
+ 
+     for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
+@@ -196,7 +196,7 @@ testCgroupDetectMounts(const void *args)
+     result = 0;
+ 
+  cleanup:
+-    VIR_FREE(mounts);
++    unsetenv("VIR_CGROUP_MOCK_FILENAME");
+     VIR_FREE(parsed);
+     virCgroupFree(&group);
+     virBufferFreeAndReset(&buf);
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgrouptest-call-virCgroupNewSelf-instead-virCgroupDetectMounts.patch b/SOURCES/libvirt-vircgrouptest-call-virCgroupNewSelf-instead-virCgroupDetectMounts.patch
new file mode 100644
index 0000000..1984f62
--- /dev/null
+++ b/SOURCES/libvirt-vircgrouptest-call-virCgroupNewSelf-instead-virCgroupDetectMounts.patch
@@ -0,0 +1,544 @@
+From e3b6a0736a5b8e23041006ac004cccf1e48ae528 Mon Sep 17 00:00:00 2001
+Message-Id: <e3b6a0736a5b8e23041006ac004cccf1e48ae528@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:06:20 +0200
+Subject: [PATCH] vircgrouptest: call virCgroupNewSelf instead
+ virCgroupDetectMounts
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This will be required once cgroup v2 is introduced.  The cgroup
+detection is not simple and we will have multiple backends so we
+should not just jump into the middle of the detection code.
+
+In order to use virCgroupNewSelf we need to create all the remaining
+data files:
+
+    - {name}.cgroups represents /proc/cgroups, it is a list of cgroup
+      controllers compiled into kernel
+
+    - {name}.self.cgroup represents /proc/self/cgroup, it describes
+      cgroups to which the process belongs
+
+For "no-cgroups" we need to modify the expected behavior because
+virCgroupNewSelf() will fail if there are no controllers available.
+
+Reviewed-by: Fabiano Fidêncio <fidencio@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 8b62008d2bc5442f7755e579ea754ffd5e3f9691)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <3d1ddcca1a1e323e607445c5d1089698122efdd8.1561993099.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/libvirt_private.syms                      |  1 -
+ src/util/vircgroup.c                          | 11 +------
+ src/util/vircgrouppriv.h                      |  2 --
+ tests/vircgroupdata/cgroups1.cgroups          | 11 +++++++
+ tests/vircgroupdata/cgroups1.self.cgroup      | 11 +++++++
+ tests/vircgroupdata/cgroups2.cgroups          | 10 +++++++
+ tests/vircgroupdata/cgroups2.self.cgroup      | 10 +++++++
+ tests/vircgroupdata/cgroups3.cgroups          | 12 ++++++++
+ tests/vircgroupdata/cgroups3.self.cgroup      | 12 ++++++++
+ tests/vircgroupdata/fedora-18.cgroups         | 10 +++++++
+ tests/vircgroupdata/fedora-18.self.cgroup     |  9 ++++++
+ tests/vircgroupdata/fedora-21.cgroups         | 12 ++++++++
+ tests/vircgroupdata/fedora-21.self.cgroup     | 10 +++++++
+ tests/vircgroupdata/kubevirt.cgroups          | 10 +++++++
+ tests/vircgroupdata/kubevirt.self.cgroup      | 10 +++++++
+ tests/vircgroupdata/no-cgroups.cgroups        |  8 +++++
+ tests/vircgroupdata/no-cgroups.parsed         | 10 -------
+ tests/vircgroupdata/no-cgroups.self.cgroup    |  0
+ tests/vircgroupdata/ovirt-node-6.6.cgroups    |  9 ++++++
+ .../vircgroupdata/ovirt-node-6.6.self.cgroup  |  8 +++++
+ tests/vircgroupdata/ovirt-node-7.1.cgroups    | 11 +++++++
+ .../vircgroupdata/ovirt-node-7.1.self.cgroup  | 10 +++++++
+ tests/vircgroupdata/rhel-7.1.cgroups          | 11 +++++++
+ tests/vircgroupdata/rhel-7.1.self.cgroup      | 10 +++++++
+ tests/vircgrouptest.c                         | 30 ++++++++++++++-----
+ 25 files changed, 217 insertions(+), 31 deletions(-)
+ create mode 100644 tests/vircgroupdata/cgroups1.cgroups
+ create mode 100644 tests/vircgroupdata/cgroups1.self.cgroup
+ create mode 100644 tests/vircgroupdata/cgroups2.cgroups
+ create mode 100644 tests/vircgroupdata/cgroups2.self.cgroup
+ create mode 100644 tests/vircgroupdata/cgroups3.cgroups
+ create mode 100644 tests/vircgroupdata/cgroups3.self.cgroup
+ create mode 100644 tests/vircgroupdata/fedora-18.cgroups
+ create mode 100644 tests/vircgroupdata/fedora-18.self.cgroup
+ create mode 100644 tests/vircgroupdata/fedora-21.cgroups
+ create mode 100644 tests/vircgroupdata/fedora-21.self.cgroup
+ create mode 100644 tests/vircgroupdata/kubevirt.cgroups
+ create mode 100644 tests/vircgroupdata/kubevirt.self.cgroup
+ create mode 100644 tests/vircgroupdata/no-cgroups.cgroups
+ delete mode 100644 tests/vircgroupdata/no-cgroups.parsed
+ create mode 100644 tests/vircgroupdata/no-cgroups.self.cgroup
+ create mode 100644 tests/vircgroupdata/ovirt-node-6.6.cgroups
+ create mode 100644 tests/vircgroupdata/ovirt-node-6.6.self.cgroup
+ create mode 100644 tests/vircgroupdata/ovirt-node-7.1.cgroups
+ create mode 100644 tests/vircgroupdata/ovirt-node-7.1.self.cgroup
+ create mode 100644 tests/vircgroupdata/rhel-7.1.cgroups
+ create mode 100644 tests/vircgroupdata/rhel-7.1.self.cgroup
+
+diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
+index b66beb7f91..8c4be84fd5 100644
+--- a/src/libvirt_private.syms
++++ b/src/libvirt_private.syms
+@@ -1528,7 +1528,6 @@ virCgroupDelThread;
+ virCgroupDenyAllDevices;
+ virCgroupDenyDevice;
+ virCgroupDenyDevicePath;
+-virCgroupDetectMounts;
+ virCgroupFree;
+ virCgroupGetBlkioDeviceReadBps;
+ virCgroupGetBlkioDeviceReadIops;
+diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
+index 53f5faafd2..d55f411daa 100644
+--- a/src/util/vircgroup.c
++++ b/src/util/vircgroup.c
+@@ -429,7 +429,7 @@ virCgroupMountOptsMatchController(const char *mntOpts,
+  * Process /proc/mounts figuring out what controllers are
+  * mounted and where
+  */
+-int
++static int
+ virCgroupDetectMounts(virCgroupPtr group)
+ {
+     size_t i;
+@@ -4080,15 +4080,6 @@ virCgroupAvailable(void)
+ }
+ 
+ 
+-int
+-virCgroupDetectMounts(virCgroupPtr group ATTRIBUTE_UNUSED)
+-{
+-    virReportSystemError(ENXIO, "%s",
+-                         _("Control groups not supported on this platform"));
+-    return -1;
+-}
+-
+-
+ int
+ virCgroupNewPartition(const char *path ATTRIBUTE_UNUSED,
+                       bool create ATTRIBUTE_UNUSED,
+diff --git a/src/util/vircgrouppriv.h b/src/util/vircgrouppriv.h
+index f78fe8bb9c..046c96c52c 100644
+--- a/src/util/vircgrouppriv.h
++++ b/src/util/vircgrouppriv.h
+@@ -50,8 +50,6 @@ struct _virCgroup {
+     virCgroupController controllers[VIR_CGROUP_CONTROLLER_LAST];
+ };
+ 
+-int virCgroupDetectMounts(virCgroupPtr group);
+-
+ int virCgroupNewPartition(const char *path,
+                           bool create,
+                           int controllers,
+diff --git a/tests/vircgroupdata/cgroups1.cgroups b/tests/vircgroupdata/cgroups1.cgroups
+new file mode 100644
+index 0000000000..a03c290a98
+--- /dev/null
++++ b/tests/vircgroupdata/cgroups1.cgroups
+@@ -0,0 +1,11 @@
++#subsys_name    hierarchy       num_cgroups     enabled
++cpuset      1       1       1
++cpu         2       1       1
++cpuacct     3       1       1
++blkio       8       1       1
++memory      4       1       1
++devices     5       1       1
++freezer     6       1       1
++net_cls     7       1       1
++net_prio    9       1       1
++hugetlb     10      1       1
+diff --git a/tests/vircgroupdata/cgroups1.self.cgroup b/tests/vircgroupdata/cgroups1.self.cgroup
+new file mode 100644
+index 0000000000..181f0c22f8
+--- /dev/null
++++ b/tests/vircgroupdata/cgroups1.self.cgroup
+@@ -0,0 +1,11 @@
++10:hugetlb:/
++9:net_prio:/
++8:blkio:/
++7:net_cls:/
++6:freezer:/
++5:devices:/
++4:memory:/
++3:cpuacct:/
++2:cpu:/
++1:cpuset:/
++0:name=openrc:/
+diff --git a/tests/vircgroupdata/cgroups2.cgroups b/tests/vircgroupdata/cgroups2.cgroups
+new file mode 100644
+index 0000000000..f0a7699559
+--- /dev/null
++++ b/tests/vircgroupdata/cgroups2.cgroups
+@@ -0,0 +1,10 @@
++#subsys_name    hierarchy       num_cgroups     enabled
++cpuset      1       1       1
++cpu         2       1       1
++cpuacct     3       1       1
++blkio       7       1       1
++memory      4       1       1
++devices     5       1       1
++freezer     6       1       1
++perf_event  8       1       1
++hugetlb     9       1       1
+diff --git a/tests/vircgroupdata/cgroups2.self.cgroup b/tests/vircgroupdata/cgroups2.self.cgroup
+new file mode 100644
+index 0000000000..3d0e793e5a
+--- /dev/null
++++ b/tests/vircgroupdata/cgroups2.self.cgroup
+@@ -0,0 +1,10 @@
++9:hugetlb:/
++8:perf_event:/
++7:blkio:/
++6:freezer:/
++5:devices:/
++4:memory:/
++3:cpuacct:/
++2:cpu:/
++1:cpuset:/
++0:name=openrc:/
+diff --git a/tests/vircgroupdata/cgroups3.cgroups b/tests/vircgroupdata/cgroups3.cgroups
+new file mode 100644
+index 0000000000..294d95dedf
+--- /dev/null
++++ b/tests/vircgroupdata/cgroups3.cgroups
+@@ -0,0 +1,12 @@
++#subsys_name    hierarchy       num_cgroups     enabled
++cpuset      1       1       1
++cpu         2       1       1
++cpuacct     3       1       1
++blkio       8       1       1
++memory      4       1       1
++devices     5       1       1
++freezer     6       1       1
++net_cls     7       1       1
++perf_event  9       1       1
++net_prio    10      1       1
++hugetlb     11      1       1
+diff --git a/tests/vircgroupdata/cgroups3.self.cgroup b/tests/vircgroupdata/cgroups3.self.cgroup
+new file mode 100644
+index 0000000000..bf346abdf9
+--- /dev/null
++++ b/tests/vircgroupdata/cgroups3.self.cgroup
+@@ -0,0 +1,12 @@
++11:hugetlb:/
++10:net_prio:/
++9:perf_event:/
++8:blkio:/
++7:net_cls:/
++6:freezer:/
++5:devices:/
++4:memory:/
++3:cpuacct:/
++2:cpu:/
++1:cpuset:/
++0:name=openrc:/
+diff --git a/tests/vircgroupdata/fedora-18.cgroups b/tests/vircgroupdata/fedora-18.cgroups
+new file mode 100644
+index 0000000000..8eb41087f3
+--- /dev/null
++++ b/tests/vircgroupdata/fedora-18.cgroups
+@@ -0,0 +1,10 @@
++#subsys_name    hierarchy       num_cgroups     enabled
++cpuset      1       1       1
++cpu         2       1       1
++cpuacct     2       1       1
++blkio       7       1       1
++memory      3       1       1
++devices     4       1       1
++freezer     5       1       1
++net_cls     6       1       1
++perf_event  8       1       1
+diff --git a/tests/vircgroupdata/fedora-18.self.cgroup b/tests/vircgroupdata/fedora-18.self.cgroup
+new file mode 100644
+index 0000000000..da9ad8ad4d
+--- /dev/null
++++ b/tests/vircgroupdata/fedora-18.self.cgroup
+@@ -0,0 +1,9 @@
++8:perf_event:/
++7:blkio:/
++6:net_cls:/
++5:freezer:/
++4:devices:/
++3:memory:/
++2:cpu,cpuacct:/
++1:cpuset:/
++0:name=systemd:/
+diff --git a/tests/vircgroupdata/fedora-21.cgroups b/tests/vircgroupdata/fedora-21.cgroups
+new file mode 100644
+index 0000000000..3e1401ee98
+--- /dev/null
++++ b/tests/vircgroupdata/fedora-21.cgroups
+@@ -0,0 +1,12 @@
++#subsys_name    hierarchy       num_cgroups     enabled
++cpuset      1       1       1
++cpu         2       1       1
++cpuacct     2       1       1
++blkio       7       1       1
++memory      3       1       1
++devices     4       1       1
++freezer     5       1       1
++net_cls     6       1       1
++perf_event  8       1       1
++net_prio    6       1       1
++hugetlb     9       1       1
+diff --git a/tests/vircgroupdata/fedora-21.self.cgroup b/tests/vircgroupdata/fedora-21.self.cgroup
+new file mode 100644
+index 0000000000..4c666bd59e
+--- /dev/null
++++ b/tests/vircgroupdata/fedora-21.self.cgroup
+@@ -0,0 +1,10 @@
++9:hugetlb:/
++8:perf_event:/
++7:blkio:/
++6:net_cls,net_prio:/
++5:freezer:/
++4:devices:/
++3:memory:/
++2:cpu,cpuacct:/
++1:cpuset:/
++0:name=systemd:/
+diff --git a/tests/vircgroupdata/kubevirt.cgroups b/tests/vircgroupdata/kubevirt.cgroups
+new file mode 100644
+index 0000000000..f0a7699559
+--- /dev/null
++++ b/tests/vircgroupdata/kubevirt.cgroups
+@@ -0,0 +1,10 @@
++#subsys_name    hierarchy       num_cgroups     enabled
++cpuset      1       1       1
++cpu         2       1       1
++cpuacct     3       1       1
++blkio       7       1       1
++memory      4       1       1
++devices     5       1       1
++freezer     6       1       1
++perf_event  8       1       1
++hugetlb     9       1       1
+diff --git a/tests/vircgroupdata/kubevirt.self.cgroup b/tests/vircgroupdata/kubevirt.self.cgroup
+new file mode 100644
+index 0000000000..3d0e793e5a
+--- /dev/null
++++ b/tests/vircgroupdata/kubevirt.self.cgroup
+@@ -0,0 +1,10 @@
++9:hugetlb:/
++8:perf_event:/
++7:blkio:/
++6:freezer:/
++5:devices:/
++4:memory:/
++3:cpuacct:/
++2:cpu:/
++1:cpuset:/
++0:name=openrc:/
+diff --git a/tests/vircgroupdata/no-cgroups.cgroups b/tests/vircgroupdata/no-cgroups.cgroups
+new file mode 100644
+index 0000000000..3ed1d4e45e
+--- /dev/null
++++ b/tests/vircgroupdata/no-cgroups.cgroups
+@@ -0,0 +1,8 @@
++#subsys_name    hierarchy       num_cgroups     enabled
++cpuset      0       1       1
++cpu         0       1       1
++cpuacct     0       1       1
++memory      0       1       1
++devices     0       1       1
++freezer     0       1       1
++blkio       0       1       1
+diff --git a/tests/vircgroupdata/no-cgroups.parsed b/tests/vircgroupdata/no-cgroups.parsed
+deleted file mode 100644
+index bf4eea085f..0000000000
+--- a/tests/vircgroupdata/no-cgroups.parsed
++++ /dev/null
+@@ -1,10 +0,0 @@
+-cpu          <null>
+-cpuacct      <null>
+-cpuset       <null>
+-memory       <null>
+-devices      <null>
+-freezer      <null>
+-blkio        <null>
+-net_cls      <null>
+-perf_event   <null>
+-name=systemd <null>
+diff --git a/tests/vircgroupdata/no-cgroups.self.cgroup b/tests/vircgroupdata/no-cgroups.self.cgroup
+new file mode 100644
+index 0000000000..e69de29bb2
+diff --git a/tests/vircgroupdata/ovirt-node-6.6.cgroups b/tests/vircgroupdata/ovirt-node-6.6.cgroups
+new file mode 100644
+index 0000000000..aaabf11a44
+--- /dev/null
++++ b/tests/vircgroupdata/ovirt-node-6.6.cgroups
+@@ -0,0 +1,9 @@
++#subsys_name    hierarchy       num_cgroups     enabled
++cpuset      0       1       1
++cpu         1       1       1
++cpuacct     2       1       1
++blkio       7       1       1
++memory      3       1       1
++devices     4       1       1
++freezer     5       1       1
++net_cls     6       1       1
+diff --git a/tests/vircgroupdata/ovirt-node-6.6.self.cgroup b/tests/vircgroupdata/ovirt-node-6.6.self.cgroup
+new file mode 100644
+index 0000000000..dadc8155fa
+--- /dev/null
++++ b/tests/vircgroupdata/ovirt-node-6.6.self.cgroup
+@@ -0,0 +1,8 @@
++7:blkio:/
++6:net_cls:/
++5:freezer:/
++4:devices:/
++3:memory:/
++2:cpuacct:/
++1:cpu:/
++0:cpuset:/
+diff --git a/tests/vircgroupdata/ovirt-node-7.1.cgroups b/tests/vircgroupdata/ovirt-node-7.1.cgroups
+new file mode 100644
+index 0000000000..687297ad4a
+--- /dev/null
++++ b/tests/vircgroupdata/ovirt-node-7.1.cgroups
+@@ -0,0 +1,11 @@
++#subsys_name    hierarchy       num_cgroups     enabled
++cpuset      1       1       1
++cpu         2       1       1
++cpuacct     2       1       1
++blkio       7       1       1
++memory      3       1       1
++devices     4       1       1
++freezer     5       1       1
++net_cls     6       1       1
++perf_event  8       1       1
++hugetlb     9       1       1
+diff --git a/tests/vircgroupdata/ovirt-node-7.1.self.cgroup b/tests/vircgroupdata/ovirt-node-7.1.self.cgroup
+new file mode 100644
+index 0000000000..f07e8e20f5
+--- /dev/null
++++ b/tests/vircgroupdata/ovirt-node-7.1.self.cgroup
+@@ -0,0 +1,10 @@
++9:hugetlb:/
++8:perf_event:/
++7:blkio:/
++6:net_cls:/
++5:freezer:/
++4:devices:/
++3:memory:/
++2:cpu,cpuacct:/
++1:cpuset:/
++0:name=systemd:/
+diff --git a/tests/vircgroupdata/rhel-7.1.cgroups b/tests/vircgroupdata/rhel-7.1.cgroups
+new file mode 100644
+index 0000000000..687297ad4a
+--- /dev/null
++++ b/tests/vircgroupdata/rhel-7.1.cgroups
+@@ -0,0 +1,11 @@
++#subsys_name    hierarchy       num_cgroups     enabled
++cpuset      1       1       1
++cpu         2       1       1
++cpuacct     2       1       1
++blkio       7       1       1
++memory      3       1       1
++devices     4       1       1
++freezer     5       1       1
++net_cls     6       1       1
++perf_event  8       1       1
++hugetlb     9       1       1
+diff --git a/tests/vircgroupdata/rhel-7.1.self.cgroup b/tests/vircgroupdata/rhel-7.1.self.cgroup
+new file mode 100644
+index 0000000000..f07e8e20f5
+--- /dev/null
++++ b/tests/vircgroupdata/rhel-7.1.self.cgroup
+@@ -0,0 +1,10 @@
++9:hugetlb:/
++8:perf_event:/
++7:blkio:/
++6:net_cls:/
++5:freezer:/
++4:devices:/
++3:memory:/
++2:cpu,cpuacct:/
++1:cpuset:/
++0:name=systemd:/
+diff --git a/tests/vircgrouptest.c b/tests/vircgrouptest.c
+index 6a38091a86..5031a2973d 100644
+--- a/tests/vircgrouptest.c
++++ b/tests/vircgrouptest.c
+@@ -159,26 +159,37 @@ const char *linksLogind[VIR_CGROUP_CONTROLLER_LAST] = {
+ };
+ 
+ 
++struct _detectMountsData {
++    const char *file;
++    bool fail;
++};
++
++
+ static int
+ testCgroupDetectMounts(const void *args)
+ {
+     int result = -1;
+-    const char *file = args;
++    const struct _detectMountsData *data = args;
+     char *parsed = NULL;
+     const char *actual;
+     virCgroupPtr group = NULL;
+     virBuffer buf = VIR_BUFFER_INITIALIZER;
+     size_t i;
+ 
+-    setenv("VIR_CGROUP_MOCK_FILENAME", file, 1);
++    setenv("VIR_CGROUP_MOCK_FILENAME", data->file, 1);
+ 
+-    if (virAsprintf(&parsed, "%s/vircgroupdata/%s.parsed", abs_srcdir, file) < 0)
++    if (virAsprintf(&parsed, "%s/vircgroupdata/%s.parsed",
++                    abs_srcdir, data->file) < 0) {
+         goto cleanup;
++    }
+ 
+-    if (VIR_ALLOC(group) < 0)
++    if (virCgroupNewSelf(&group) < 0) {
++        if (data->fail)
++            result = 0;
+         goto cleanup;
++    }
+ 
+-    if (virCgroupDetectMounts(group) < 0)
++    if (data->fail)
+         goto cleanup;
+ 
+     for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
+@@ -870,13 +881,16 @@ mymain(void)
+ 
+     setenv("LIBVIRT_FAKE_ROOT_DIR", fakerootdir, 1);
+ 
+-# define DETECT_MOUNTS(file) \
++# define DETECT_MOUNTS_FULL(file, fail) \
+     do { \
++        struct _detectMountsData data = { file, fail }; \
+         if (virTestRun("Detect cgroup mounts for " file, \
+                        testCgroupDetectMounts, \
+-                       file) < 0) \
++                       &data) < 0) \
+             ret = -1; \
+     } while (0)
++# define DETECT_MOUNTS(file) DETECT_MOUNTS_FULL(file, false);
++# define DETECT_MOUNTS_FAIL(file) DETECT_MOUNTS_FULL(file, true);
+ 
+     DETECT_MOUNTS("ovirt-node-6.6");
+     DETECT_MOUNTS("ovirt-node-7.1");
+@@ -887,7 +901,7 @@ mymain(void)
+     DETECT_MOUNTS("cgroups2");
+     DETECT_MOUNTS("cgroups3");
+     DETECT_MOUNTS("all-in-one");
+-    DETECT_MOUNTS("no-cgroups");
++    DETECT_MOUNTS_FAIL("no-cgroups");
+     DETECT_MOUNTS("kubevirt");
+ 
+     setenv("VIR_CGROUP_MOCK_FILENAME", "systemd", 1);
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgrouptest-introduce-initFakeFS-and-cleanupFakeFS-helpers.patch b/SOURCES/libvirt-vircgrouptest-introduce-initFakeFS-and-cleanupFakeFS-helpers.patch
new file mode 100644
index 0000000..521994b
--- /dev/null
+++ b/SOURCES/libvirt-vircgrouptest-introduce-initFakeFS-and-cleanupFakeFS-helpers.patch
@@ -0,0 +1,120 @@
+From d1c2f060ea724b4f430f9e3198676e18bf0656af Mon Sep 17 00:00:00 2001
+Message-Id: <d1c2f060ea724b4f430f9e3198676e18bf0656af@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:07:56 +0200
+Subject: [PATCH] vircgrouptest: introduce initFakeFS and cleanupFakeFS helpers
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+We need to configure multiple env variables for each set of tests so
+create helper functions to do that.
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 9b9c6528a2f867a3be79022b4f282116d2efd3cd)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <b9c0307500ba7b4e95ed097a457590a54dcd0ddb.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ tests/vircgrouptest.c | 48 ++++++++++++++++++++++++++++++++-----------
+ 1 file changed, 36 insertions(+), 12 deletions(-)
+
+diff --git a/tests/vircgrouptest.c b/tests/vircgrouptest.c
+index c4bf987ca1..1837383e61 100644
+--- a/tests/vircgrouptest.c
++++ b/tests/vircgrouptest.c
+@@ -831,10 +831,10 @@ static int testCgroupGetBlkioIoDeviceServiced(const void *args ATTRIBUTE_UNUSED)
+ 
+ # define FAKEROOTDIRTEMPLATE abs_builddir "/fakerootdir-XXXXXX"
+ 
+-static int
+-mymain(void)
++static char *
++initFakeFS(const char *mode,
++           const char *filename)
+ {
+-    int ret = 0;
+     char *fakerootdir;
+ 
+     if (VIR_STRDUP_QUIET(fakerootdir, FAKEROOTDIRTEMPLATE) < 0) {
+@@ -849,6 +849,33 @@ mymain(void)
+ 
+     setenv("LIBVIRT_FAKE_ROOT_DIR", fakerootdir, 1);
+ 
++    if (mode)
++        setenv("VIR_CGROUP_MOCK_MODE", mode, 1);
++
++    if (filename)
++        setenv("VIR_CGROUP_MOCK_FILENAME", filename, 1);
++
++    return fakerootdir;
++}
++
++static void
++cleanupFakeFS(char *fakerootdir)
++{
++    if (getenv("LIBVIRT_SKIP_CLEANUP") == NULL)
++        virFileDeleteTree(fakerootdir);
++
++    VIR_FREE(fakerootdir);
++    unsetenv("LIBVIRT_FAKE_ROOT_DIR");
++    unsetenv("VIR_CGROUP_MOCK_MODE");
++    unsetenv("VIR_CGROUP_MOCK_FILENAME");
++}
++
++static int
++mymain(void)
++{
++    int ret = 0;
++    char *fakerootdir;
++
+ # define DETECT_MOUNTS_FULL(file, fail) \
+     do { \
+         struct _detectMountsData data = { file, fail }; \
+@@ -872,7 +899,7 @@ mymain(void)
+     DETECT_MOUNTS_FAIL("no-cgroups");
+     DETECT_MOUNTS("kubevirt");
+ 
+-    setenv("VIR_CGROUP_MOCK_FILENAME", "systemd", 1);
++    fakerootdir = initFakeFS(NULL, "systemd");
+     if (virTestRun("New cgroup for self", testCgroupNewForSelf, NULL) < 0)
+         ret = -1;
+ 
+@@ -908,26 +935,23 @@ mymain(void)
+ 
+     if (virTestRun("virCgroupGetPercpuStats works", testCgroupGetPercpuStats, NULL) < 0)
+         ret = -1;
+-    unsetenv("VIR_CGROUP_MOCK_FILENAME");
++    cleanupFakeFS(fakerootdir);
+ 
+-    setenv("VIR_CGROUP_MOCK_FILENAME", "all-in-one", 1);
++    fakerootdir = initFakeFS(NULL, "all-in-one");
+     if (virTestRun("New cgroup for self (allinone)", testCgroupNewForSelfAllInOne, NULL) < 0)
+         ret = -1;
+     if (virTestRun("Cgroup available", testCgroupAvailable, (void*)0x1) < 0)
+         ret = -1;
+-    unsetenv("VIR_CGROUP_MOCK_FILENAME");
++    cleanupFakeFS(fakerootdir);
+ 
+-    setenv("VIR_CGROUP_MOCK_FILENAME", "logind", 1);
++    fakerootdir = initFakeFS(NULL, "logind");
+     if (virTestRun("New cgroup for self (logind)", testCgroupNewForSelfLogind, NULL) < 0)
+         ret = -1;
+     if (virTestRun("Cgroup available", testCgroupAvailable, (void*)0x0) < 0)
+         ret = -1;
+-    unsetenv("VIR_CGROUP_MOCK_FILENAME");
++    cleanupFakeFS(fakerootdir);
+ 
+-    if (getenv("LIBVIRT_SKIP_CLEANUP") == NULL)
+-        virFileDeleteTree(fakerootdir);
+ 
+-    VIR_FREE(fakerootdir);
+ 
+     return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
+ }
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgrouptest-prepare-testCgroupDetectMounts-for-cgroup-v2.patch b/SOURCES/libvirt-vircgrouptest-prepare-testCgroupDetectMounts-for-cgroup-v2.patch
new file mode 100644
index 0000000..41df5c6
--- /dev/null
+++ b/SOURCES/libvirt-vircgrouptest-prepare-testCgroupDetectMounts-for-cgroup-v2.patch
@@ -0,0 +1,137 @@
+From 541ede1193bfb32f73d76918d755c0f3d403e5ce Mon Sep 17 00:00:00 2001
+Message-Id: <541ede1193bfb32f73d76918d755c0f3d403e5ce@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:07:57 +0200
+Subject: [PATCH] vircgrouptest: prepare testCgroupDetectMounts for cgroup v2
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 9f8d170dab8dc30d4563cb038e5aef393b0d1128)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <f9905a25dc85ad266308c81afeeab379ca20a8ba.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ tests/vircgroupdata/all-in-one.parsed     | 1 +
+ tests/vircgroupdata/cgroups1.parsed       | 1 +
+ tests/vircgroupdata/cgroups2.parsed       | 1 +
+ tests/vircgroupdata/cgroups3.parsed       | 1 +
+ tests/vircgroupdata/fedora-18.parsed      | 1 +
+ tests/vircgroupdata/fedora-21.parsed      | 1 +
+ tests/vircgroupdata/kubevirt.parsed       | 1 +
+ tests/vircgroupdata/ovirt-node-6.6.parsed | 1 +
+ tests/vircgroupdata/ovirt-node-7.1.parsed | 1 +
+ tests/vircgroupdata/rhel-7.1.parsed       | 1 +
+ tests/vircgrouptest.c                     | 2 ++
+ 11 files changed, 12 insertions(+)
+
+diff --git a/tests/vircgroupdata/all-in-one.parsed b/tests/vircgroupdata/all-in-one.parsed
+index d703d08fb9..97c96e8ecd 100644
+--- a/tests/vircgroupdata/all-in-one.parsed
++++ b/tests/vircgroupdata/all-in-one.parsed
+@@ -8,3 +8,4 @@ blkio        /not/really/sys/fs/cgroup
+ net_cls      <null>
+ perf_event   <null>
+ name=systemd <null>
++unified      <null>
+diff --git a/tests/vircgroupdata/cgroups1.parsed b/tests/vircgroupdata/cgroups1.parsed
+index b6916f17a1..16431aa006 100644
+--- a/tests/vircgroupdata/cgroups1.parsed
++++ b/tests/vircgroupdata/cgroups1.parsed
+@@ -8,3 +8,4 @@ blkio        /sys/fs/cgroup/blkio
+ net_cls      /sys/fs/cgroup/net_cls
+ perf_event   <null>
+ name=systemd <null>
++unified      <null>
+diff --git a/tests/vircgroupdata/cgroups2.parsed b/tests/vircgroupdata/cgroups2.parsed
+index 5eb2bc7bb2..d1bb0dcb7c 100644
+--- a/tests/vircgroupdata/cgroups2.parsed
++++ b/tests/vircgroupdata/cgroups2.parsed
+@@ -8,3 +8,4 @@ blkio        /sys/fs/cgroup/blkio
+ net_cls      <null>
+ perf_event   /sys/fs/cgroup/perf_event
+ name=systemd <null>
++unified      <null>
+diff --git a/tests/vircgroupdata/cgroups3.parsed b/tests/vircgroupdata/cgroups3.parsed
+index 2b1f3825c1..44e475c9d2 100644
+--- a/tests/vircgroupdata/cgroups3.parsed
++++ b/tests/vircgroupdata/cgroups3.parsed
+@@ -8,3 +8,4 @@ blkio        /sys/fs/cgroup/blkio
+ net_cls      /sys/fs/cgroup/net_cls
+ perf_event   /sys/fs/cgroup/perf_event
+ name=systemd <null>
++unified      <null>
+diff --git a/tests/vircgroupdata/fedora-18.parsed b/tests/vircgroupdata/fedora-18.parsed
+index 8d5ba75c7e..662a38a9e8 100644
+--- a/tests/vircgroupdata/fedora-18.parsed
++++ b/tests/vircgroupdata/fedora-18.parsed
+@@ -8,3 +8,4 @@ blkio        /sys/fs/cgroup/blkio
+ net_cls      /sys/fs/cgroup/net_cls
+ perf_event   /sys/fs/cgroup/perf_event
+ name=systemd /sys/fs/cgroup/systemd
++unified      <null>
+diff --git a/tests/vircgroupdata/fedora-21.parsed b/tests/vircgroupdata/fedora-21.parsed
+index 3377af0382..4e447fd7bd 100644
+--- a/tests/vircgroupdata/fedora-21.parsed
++++ b/tests/vircgroupdata/fedora-21.parsed
+@@ -8,3 +8,4 @@ blkio        /sys/fs/cgroup/blkio
+ net_cls      /sys/fs/cgroup/net_cls,net_prio
+ perf_event   /sys/fs/cgroup/perf_event
+ name=systemd /sys/fs/cgroup/systemd
++unified      <null>
+diff --git a/tests/vircgroupdata/kubevirt.parsed b/tests/vircgroupdata/kubevirt.parsed
+index 6948707238..bf977f8363 100644
+--- a/tests/vircgroupdata/kubevirt.parsed
++++ b/tests/vircgroupdata/kubevirt.parsed
+@@ -8,3 +8,4 @@ blkio        /sys/fs/cgroup/blkio
+ net_cls      <null>
+ perf_event   /sys/fs/cgroup/perf_event
+ name=systemd <null>
++unified      <null>
+diff --git a/tests/vircgroupdata/ovirt-node-6.6.parsed b/tests/vircgroupdata/ovirt-node-6.6.parsed
+index 01bf466be6..9d10813d8c 100644
+--- a/tests/vircgroupdata/ovirt-node-6.6.parsed
++++ b/tests/vircgroupdata/ovirt-node-6.6.parsed
+@@ -8,3 +8,4 @@ blkio        /cgroup/blkio
+ net_cls      /cgroup/net_cls
+ perf_event   <null>
+ name=systemd <null>
++unified      <null>
+diff --git a/tests/vircgroupdata/ovirt-node-7.1.parsed b/tests/vircgroupdata/ovirt-node-7.1.parsed
+index 8d5ba75c7e..662a38a9e8 100644
+--- a/tests/vircgroupdata/ovirt-node-7.1.parsed
++++ b/tests/vircgroupdata/ovirt-node-7.1.parsed
+@@ -8,3 +8,4 @@ blkio        /sys/fs/cgroup/blkio
+ net_cls      /sys/fs/cgroup/net_cls
+ perf_event   /sys/fs/cgroup/perf_event
+ name=systemd /sys/fs/cgroup/systemd
++unified      <null>
+diff --git a/tests/vircgroupdata/rhel-7.1.parsed b/tests/vircgroupdata/rhel-7.1.parsed
+index 8d5ba75c7e..662a38a9e8 100644
+--- a/tests/vircgroupdata/rhel-7.1.parsed
++++ b/tests/vircgroupdata/rhel-7.1.parsed
+@@ -8,3 +8,4 @@ blkio        /sys/fs/cgroup/blkio
+ net_cls      /sys/fs/cgroup/net_cls
+ perf_event   /sys/fs/cgroup/perf_event
+ name=systemd /sys/fs/cgroup/systemd
++unified      <null>
+diff --git a/tests/vircgrouptest.c b/tests/vircgrouptest.c
+index 1837383e61..b66682e6c8 100644
+--- a/tests/vircgrouptest.c
++++ b/tests/vircgrouptest.c
+@@ -176,6 +176,8 @@ testCgroupDetectMounts(const void *args)
+                           virCgroupControllerTypeToString(i),
+                           NULLSTR(group->legacy[i].mountPoint));
+     }
++    virBufferAsprintf(&buf, "%-12s %s\n",
++                      "unified", NULLSTR(group->unified.mountPoint));
+     if (virBufferCheckError(&buf) < 0)
+         goto cleanup;
+ 
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgrouptest-prepare-validateCgroup-for-cgroupv2.patch b/SOURCES/libvirt-vircgrouptest-prepare-validateCgroup-for-cgroupv2.patch
new file mode 100644
index 0000000..fe04791
--- /dev/null
+++ b/SOURCES/libvirt-vircgrouptest-prepare-validateCgroup-for-cgroupv2.patch
@@ -0,0 +1,150 @@
+From f186ff31027a18b0568cf8c31da4fbffb7e3ead7 Mon Sep 17 00:00:00 2001
+Message-Id: <f186ff31027a18b0568cf8c31da4fbffb7e3ead7@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:08:00 +0200
+Subject: [PATCH] vircgrouptest: prepare validateCgroup for cgroupv2
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 2a3df5fac52abb0d414d221a5da3bb957675a094)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <b5ae08efdc04ae116b8af6041a751672e090506b.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ tests/vircgrouptest.c | 53 +++++++++++++++++++++++++++++++++++--------
+ 1 file changed, 44 insertions(+), 9 deletions(-)
+
+diff --git a/tests/vircgrouptest.c b/tests/vircgrouptest.c
+index aeb2840823..87f8fa7e67 100644
+--- a/tests/vircgrouptest.c
++++ b/tests/vircgrouptest.c
+@@ -44,7 +44,10 @@ static int validateCgroup(virCgroupPtr cgroup,
+                           const char *expectPath,
+                           const char **expectMountPoint,
+                           const char **expectLinkPoint,
+-                          const char **expectPlacement)
++                          const char **expectPlacement,
++                          const char *expectUnifiedMountPoint,
++                          const char *expectUnifiedPlacement,
++                          unsigned int expectUnifiedControllers)
+ {
+     size_t i;
+ 
+@@ -81,6 +84,38 @@ static int validateCgroup(virCgroupPtr cgroup,
+         }
+     }
+ 
++    if (STRNEQ_NULLABLE(expectUnifiedMountPoint,
++                        cgroup->unified.mountPoint)) {
++        fprintf(stderr, "Wrong mount '%s', expected '%s' for 'unified'\n",
++                cgroup->unified.mountPoint,
++                expectUnifiedMountPoint);
++        return -1;
++    }
++    if (STRNEQ_NULLABLE(expectUnifiedPlacement,
++                        cgroup->unified.placement)) {
++        fprintf(stderr, "Wrong placement '%s', expected '%s' for 'unified'\n",
++                cgroup->unified.placement,
++                expectUnifiedPlacement);
++        return -1;
++    }
++    if (expectUnifiedControllers != cgroup->unified.controllers) {
++        for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
++            int type = 1 << i;
++            if ((expectUnifiedControllers & type) != (cgroup->unified.controllers & type)) {
++                const char *typeStr = virCgroupControllerTypeToString(i);
++                if (expectUnifiedControllers & type) {
++                    fprintf(stderr, "expected controller '%s' for 'unified', "
++                            "but it's missing\n", typeStr);
++                } else {
++                    fprintf(stderr, "existing controller '%s' for 'unified', "
++                            "but it's not expected\n", typeStr);
++                }
++            }
++
++        }
++        return -1;
++    }
++
+     return 0;
+ }
+ 
+@@ -216,7 +251,7 @@ static int testCgroupNewForSelf(const void *args ATTRIBUTE_UNUSED)
+         goto cleanup;
+     }
+ 
+-    ret = validateCgroup(cgroup, "", mountsFull, links, placement);
++    ret = validateCgroup(cgroup, "", mountsFull, links, placement, NULL, NULL, 0);
+ 
+  cleanup:
+     virCgroupFree(&cgroup);
+@@ -295,14 +330,14 @@ static int testCgroupNewForPartition(const void *args ATTRIBUTE_UNUSED)
+         fprintf(stderr, "Cannot create /virtualmachines cgroup: %d\n", -rv);
+         goto cleanup;
+     }
+-    ret = validateCgroup(cgroup, "/virtualmachines.partition", mountsSmall, links, placementSmall);
++    ret = validateCgroup(cgroup, "/virtualmachines.partition", mountsSmall, links, placementSmall, NULL, NULL, 0);
+     virCgroupFree(&cgroup);
+ 
+     if ((rv = virCgroupNewPartition("/virtualmachines", true, -1, &cgroup)) != 0) {
+         fprintf(stderr, "Cannot create /virtualmachines cgroup: %d\n", -rv);
+         goto cleanup;
+     }
+-    ret = validateCgroup(cgroup, "/virtualmachines.partition", mountsFull, links, placementFull);
++    ret = validateCgroup(cgroup, "/virtualmachines.partition", mountsFull, links, placementFull, NULL, NULL, 0);
+ 
+  cleanup:
+     virCgroupFree(&cgroup);
+@@ -352,7 +387,7 @@ static int testCgroupNewForPartitionNested(const void *args ATTRIBUTE_UNUSED)
+     }
+ 
+     ret = validateCgroup(cgroup, "/deployment.partition/production.partition",
+-                         mountsFull, links, placementFull);
++                         mountsFull, links, placementFull, NULL, NULL, 0);
+ 
+  cleanup:
+     virCgroupFree(&cgroup);
+@@ -408,7 +443,7 @@ static int testCgroupNewForPartitionNestedDeep(const void *args ATTRIBUTE_UNUSED
+     }
+ 
+     ret = validateCgroup(cgroup, "/user/berrange.user/production.partition",
+-                         mountsFull, links, placementFull);
++                         mountsFull, links, placementFull, NULL, NULL, 0);
+ 
+  cleanup:
+     virCgroupFree(&cgroup);
+@@ -444,7 +479,7 @@ static int testCgroupNewForPartitionDomain(const void *args ATTRIBUTE_UNUSED)
+         goto cleanup;
+     }
+ 
+-    ret = validateCgroup(domaincgroup, "/production.partition/foo.libvirt-lxc", mountsFull, links, placement);
++    ret = validateCgroup(domaincgroup, "/production.partition/foo.libvirt-lxc", mountsFull, links, placement, NULL, NULL, 0);
+ 
+  cleanup:
+     virCgroupFree(&partitioncgroup);
+@@ -495,7 +530,7 @@ static int testCgroupNewForPartitionDomainEscaped(const void *args ATTRIBUTE_UNU
+      * since our fake /proc/cgroups pretends this controller
+      * isn't compiled into the kernel
+      */
+-    ret = validateCgroup(domaincgroup, "/_cgroup.evil/net_cls.evil/__evil.evil/_cpu.foo.libvirt-lxc", mountsFull, links, placement);
++    ret = validateCgroup(domaincgroup, "/_cgroup.evil/net_cls.evil/__evil.evil/_cpu.foo.libvirt-lxc", mountsFull, links, placement, NULL, NULL, 0);
+ 
+  cleanup:
+     virCgroupFree(&partitioncgroup3);
+@@ -524,7 +559,7 @@ static int testCgroupNewForSelfAllInOne(const void *args ATTRIBUTE_UNUSED)
+         goto cleanup;
+     }
+ 
+-    ret = validateCgroup(cgroup, "", mountsAllInOne, linksAllInOne, placement);
++    ret = validateCgroup(cgroup, "", mountsAllInOne, linksAllInOne, placement, NULL, NULL, 0);
+ 
+  cleanup:
+     virCgroupFree(&cgroup);
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroupv1-fix-build-on-non-linux-OSes.patch b/SOURCES/libvirt-vircgroupv1-fix-build-on-non-linux-OSes.patch
new file mode 100644
index 0000000..b25993f
--- /dev/null
+++ b/SOURCES/libvirt-vircgroupv1-fix-build-on-non-linux-OSes.patch
@@ -0,0 +1,94 @@
+From 2b27d54de68a4581a9b46fe5c399b45c0014fcbd Mon Sep 17 00:00:00 2001
+Message-Id: <2b27d54de68a4581a9b46fe5c399b45c0014fcbd@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:07:10 +0200
+Subject: [PATCH] vircgroupv1: fix build on non-linux OSes
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Cgroups are linux specific and we need to make sure that the code is
+compiled only on linux.  On different OSes it fails the compilation:
+
+../../src/util/vircgroupv1.c:65:19: error: variable has incomplete type 'struct mntent'
+    struct mntent entry;
+                  ^
+../../src/util/vircgroupv1.c:65:12: note: forward declaration of 'struct mntent'
+    struct mntent entry;
+           ^
+../../src/util/vircgroupv1.c:74:12: error: implicit declaration of function 'getmntent_r' is invalid in C99 [-Werror,-Wimplicit-function-declaration]
+    while (getmntent_r(mounts, &entry, buf, sizeof(buf)) != NULL) {
+           ^
+../../src/util/vircgroupv1.c:814:39: error: use of undeclared identifier 'MS_NOSUID'
+    if (mount("tmpfs", root, "tmpfs", MS_NOSUID|MS_NODEV|MS_NOEXEC, opts) < 0) {
+                                      ^
+../../src/util/vircgroupv1.c:814:49: error: use of undeclared identifier 'MS_NODEV'
+    if (mount("tmpfs", root, "tmpfs", MS_NOSUID|MS_NODEV|MS_NOEXEC, opts) < 0) {
+                                                ^
+../../src/util/vircgroupv1.c:814:58: error: use of undeclared identifier 'MS_NOEXEC'
+    if (mount("tmpfs", root, "tmpfs", MS_NOSUID|MS_NODEV|MS_NOEXEC, opts) < 0) {
+                                                         ^
+../../src/util/vircgroupv1.c:841:65: error: use of undeclared identifier 'MS_BIND'
+            if (mount(src, group->legacy[i].mountPoint, "none", MS_BIND,
+                                                                ^
+
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 0615c8436ac868889454bee2781b6c9993518597)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <a1b4d0cfa90a65f5c431a388e6f51be2ab9a7cdd.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroupv1.c | 20 +++++++++++++++-----
+ 1 file changed, 15 insertions(+), 5 deletions(-)
+
+diff --git a/src/util/vircgroupv1.c b/src/util/vircgroupv1.c
+index 482615f3c8..97d108d3ac 100644
+--- a/src/util/vircgroupv1.c
++++ b/src/util/vircgroupv1.c
+@@ -20,13 +20,11 @@
+  */
+ #include <config.h>
+ 
+-#if defined HAVE_MNTENT_H && defined HAVE_GETMNTENT_R
++#ifdef __linux__
+ # include <mntent.h>
+-#endif
+-#include <sys/stat.h>
+-#if defined HAVE_SYS_MOUNT_H
++# include <sys/stat.h>
+ # include <sys/mount.h>
+-#endif
++#endif /* __linux__ */
+ 
+ #include "internal.h"
+ 
+@@ -56,6 +54,8 @@ VIR_ENUM_IMPL(virCgroupV1Controller, VIR_CGROUP_CONTROLLER_LAST,
+               "name=systemd");
+ 
+ 
++#ifdef __linux__
++
+ /* We're looking for at least one 'cgroup' fs mount,
+  * which is *not* a named mount. */
+ static bool
+@@ -2100,3 +2100,13 @@ virCgroupV1Register(void)
+ {
+     virCgroupBackendRegister(&virCgroupV1Backend);
+ }
++
++#else /* !__linux__ */
++
++void
++virCgroupV1Register(void)
++{
++    VIR_INFO("Control groups not supported on this platform");
++}
++
++#endif /* !__linux__ */
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroupv2-fix-abort-in-VIR_AUTOFREE.patch b/SOURCES/libvirt-vircgroupv2-fix-abort-in-VIR_AUTOFREE.patch
new file mode 100644
index 0000000..105f2f3
--- /dev/null
+++ b/SOURCES/libvirt-vircgroupv2-fix-abort-in-VIR_AUTOFREE.patch
@@ -0,0 +1,65 @@
+From c627fa58c17960e5eed999049bf966b5ea952c3b Mon Sep 17 00:00:00 2001
+Message-Id: <c627fa58c17960e5eed999049bf966b5ea952c3b@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Fri, 30 Aug 2019 16:35:33 +0200
+Subject: [PATCH] vircgroupv2: fix abort in VIR_AUTOFREE
+
+Introduced by commit <c854e0bd33c7a5afb04a36465bf04f861b2efef5> that
+tried to fix an issue where we would fail to parse values from files.
+
+We cannot change the original pointer that is going to be used by
+VIR_AUTOFREE.
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1747440
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Acked-by: Peter Krempa <pkrempa@redhat.com>
+(cherry picked from commit 9a99b01f8d3b2be491f9f8412c6f894d30d7e2fe)
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <c9be614c3648b2901481f257ba1af3fcd8fe7e76.1567175708.git.phrdina@redhat.com>
+Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/util/vircgroupv2.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/src/util/vircgroupv2.c b/src/util/vircgroupv2.c
+index e31a2d1121..e7b9093754 100644
+--- a/src/util/vircgroupv2.c
++++ b/src/util/vircgroupv2.c
+@@ -848,6 +848,7 @@ virCgroupV2GetBlkioDeviceWeight(virCgroupPtr group,
+     VIR_AUTOFREE(char *) path = NULL;
+     VIR_AUTOFREE(char *) str = NULL;
+     VIR_AUTOFREE(char *) value = NULL;
++    char *tmp;
+ 
+     if (virCgroupV2PathOfController(group, VIR_CGROUP_CONTROLLER_BLKIO,
+                                     "io.weight", &path) < 0) {
+@@ -868,7 +869,7 @@ virCgroupV2GetBlkioDeviceWeight(virCgroupPtr group,
+ 
+     if (!str) {
+         *weight = 0;
+-    } else if (virStrToLong_ui(str, &str, 10, weight) < 0) {
++    } else if (virStrToLong_ui(str, &tmp, 10, weight) < 0) {
+         virReportError(VIR_ERR_INTERNAL_ERROR,
+                        _("Unable to parse '%s' as an integer"),
+                        str);
+@@ -1575,6 +1576,7 @@ virCgroupV2GetCpuCfsQuota(virCgroupPtr group,
+                           long long *cfs_quota)
+ {
+     VIR_AUTOFREE(char *) str = NULL;
++    char *tmp;
+ 
+     if (virCgroupGetValueStr(group, VIR_CGROUP_CONTROLLER_CPU,
+                              "cpu.max", &str) < 0) {
+@@ -1586,7 +1588,7 @@ virCgroupV2GetCpuCfsQuota(virCgroupPtr group,
+         return 0;
+     }
+ 
+-    if (virStrToLong_ll(str, &str, 10, cfs_quota) < 0) {
++    if (virStrToLong_ll(str, &tmp, 10, cfs_quota) < 0) {
+         virReportError(VIR_ERR_INTERNAL_ERROR,
+                        _("Failed to parse value '%s' from cpu.max."), str);
+         return -1;
+-- 
+2.23.0
+
diff --git a/SOURCES/libvirt-vircgroupv2-fix-parsing-multiple-values-in-single-file.patch b/SOURCES/libvirt-vircgroupv2-fix-parsing-multiple-values-in-single-file.patch
new file mode 100644
index 0000000..c76eb62
--- /dev/null
+++ b/SOURCES/libvirt-vircgroupv2-fix-parsing-multiple-values-in-single-file.patch
@@ -0,0 +1,105 @@
+From ae178683071d3948d1d1da6205726a3e24923b45 Mon Sep 17 00:00:00 2001
+Message-Id: <ae178683071d3948d1d1da6205726a3e24923b45@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Wed, 21 Aug 2019 09:42:34 +0200
+Subject: [PATCH] vircgroupv2: fix parsing multiple values in single file
+
+Our virStrToLong* helpers converts string to integers where it wraps
+strtol standard function.  After the conversion happens and there are
+some remaining invalid characters our helpers will fail if the second
+argument is NULL.
+
+We need to pass pointer to string in cases where there are multiple
+values in a single file.
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1741825
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
+(cherry picked from commit c854e0bd33c7a5afb04a36465bf04f861b2efef5)
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <49fe97f452eb4247040b1f322d348a3eea931efe.1566373284.git.phrdina@redhat.com>
+Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/util/vircgroupv2.c | 16 ++++++++--------
+ 1 file changed, 8 insertions(+), 8 deletions(-)
+
+diff --git a/src/util/vircgroupv2.c b/src/util/vircgroupv2.c
+index 9ae47e775e..e129686a52 100644
+--- a/src/util/vircgroupv2.c
++++ b/src/util/vircgroupv2.c
+@@ -672,7 +672,7 @@ virCgroupV2GetBlkioWeight(virCgroupPtr group,
+         tmp = value;
+     }
+ 
+-    if (virStrToLong_ui(tmp, NULL, 10, weight) < 0) {
++    if (virStrToLong_ui(tmp, &tmp, 10, weight) < 0) {
+         virReportError(VIR_ERR_INTERNAL_ERROR,
+                        _("Unable to parse '%s' as an integer"),
+                        tmp);
+@@ -868,7 +868,7 @@ virCgroupV2GetBlkioDeviceWeight(virCgroupPtr group,
+ 
+     if (!str) {
+         *weight = 0;
+-    } else if (virStrToLong_ui(str, NULL, 10, weight) < 0) {
++    } else if (virStrToLong_ui(str, &str, 10, weight) < 0) {
+         virReportError(VIR_ERR_INTERNAL_ERROR,
+                        _("Unable to parse '%s' as an integer"),
+                        str);
+@@ -938,7 +938,7 @@ virCgroupV2GetBlkioDeviceReadIops(virCgroupPtr group,
+ 
+         if (STREQLEN(tmp, "max", 3)) {
+             *riops = 0;
+-        } else if (virStrToLong_ui(tmp, NULL, 10, riops) < 0) {
++        } else if (virStrToLong_ui(tmp, &tmp, 10, riops) < 0) {
+             virReportError(VIR_ERR_INTERNAL_ERROR,
+                            _("Unable to parse '%s' as an integer"),
+                            str);
+@@ -1009,7 +1009,7 @@ virCgroupV2GetBlkioDeviceWriteIops(virCgroupPtr group,
+ 
+         if (STREQLEN(tmp, "max", 3)) {
+             *wiops = 0;
+-        } else if (virStrToLong_ui(tmp, NULL, 10, wiops) < 0) {
++        } else if (virStrToLong_ui(tmp, &tmp, 10, wiops) < 0) {
+             virReportError(VIR_ERR_INTERNAL_ERROR,
+                            _("Unable to parse '%s' as an integer"),
+                            str);
+@@ -1080,7 +1080,7 @@ virCgroupV2GetBlkioDeviceReadBps(virCgroupPtr group,
+ 
+         if (STREQLEN(tmp, "max", 3)) {
+             *rbps = 0;
+-        } else if (virStrToLong_ull(tmp, NULL, 10, rbps) < 0) {
++        } else if (virStrToLong_ull(tmp, &tmp, 10, rbps) < 0) {
+             virReportError(VIR_ERR_INTERNAL_ERROR,
+                            _("Unable to parse '%s' as an integer"),
+                            str);
+@@ -1151,7 +1151,7 @@ virCgroupV2GetBlkioDeviceWriteBps(virCgroupPtr group,
+ 
+         if (STREQLEN(tmp, "max", 3)) {
+             *wbps = 0;
+-        } else if (virStrToLong_ull(tmp, NULL, 10, wbps) < 0) {
++        } else if (virStrToLong_ull(tmp, &tmp, 10, wbps) < 0) {
+             virReportError(VIR_ERR_INTERNAL_ERROR,
+                            _("Unable to parse '%s' as an integer"),
+                            str);
+@@ -1534,7 +1534,7 @@ virCgroupV2GetCpuCfsPeriod(virCgroupPtr group,
+         return -1;
+     }
+ 
+-    if (virStrToLong_ull(tmp, NULL, 10, cfs_period) < 0) {
++    if (virStrToLong_ull(tmp, &tmp, 10, cfs_period) < 0) {
+         virReportError(VIR_ERR_INTERNAL_ERROR,
+                        _("Failed to parse value '%s' from cpu.max."), str);
+         return -1;
+@@ -1584,7 +1584,7 @@ virCgroupV2GetCpuCfsQuota(virCgroupPtr group,
+     if (STREQLEN(str, "max", 3))
+         *cfs_quota = ULLONG_MAX / 1000;
+ 
+-    if (virStrToLong_ll(str, NULL, 10, cfs_quota) < 0) {
++    if (virStrToLong_ll(str, &str, 10, cfs_quota) < 0) {
+         virReportError(VIR_ERR_INTERNAL_ERROR,
+                        _("Failed to parse value '%s' from cpu.max."), str);
+         return -1;
+-- 
+2.23.0
+
diff --git a/SOURCES/libvirt-vircgroupv2-fix-setting-cpu.max-period.patch b/SOURCES/libvirt-vircgroupv2-fix-setting-cpu.max-period.patch
new file mode 100644
index 0000000..c07b46e
--- /dev/null
+++ b/SOURCES/libvirt-vircgroupv2-fix-setting-cpu.max-period.patch
@@ -0,0 +1,42 @@
+From 164b5885c6916d39a71a4778da9782c9dc6cadf0 Mon Sep 17 00:00:00 2001
+Message-Id: <164b5885c6916d39a71a4778da9782c9dc6cadf0@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Fri, 6 Sep 2019 09:29:41 +0200
+Subject: [PATCH] vircgroupv2: fix setting cpu.max period
+
+When we set cpu.max period we need to parse the cpu.max file first as
+it contains both quota and period values separated by space.  When only
+a single number is written to that file it will set quota.  However,
+in order to change period we need to write both values.
+
+The code was prepared for that but mistakenly used new line to end the
+string with the first value.
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1749227
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Reviewed-by: Erik Skultety <eskultet@redhat.com>
+(cherry picked from commit 0bd4ad193d8ba7f0104f4739f19f2731e7cf9f56)
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <3a1021b39f7b5add388e98eae4caa63975b60fc3.1567754949.git.phrdina@redhat.com>
+Reviewed-by: Erik Skultety <eskultet@redhat.com>
+---
+ src/util/vircgroupv2.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/src/util/vircgroupv2.c b/src/util/vircgroupv2.c
+index e7b9093754..13a51e67a4 100644
+--- a/src/util/vircgroupv2.c
++++ b/src/util/vircgroupv2.c
+@@ -1507,7 +1507,7 @@ virCgroupV2SetCpuCfsPeriod(virCgroupPtr group,
+                        _("Invalid 'cpu.max' data."));
+         return -1;
+     }
+-    *tmp = '\n';
++    *tmp = '\0';
+ 
+     if (virAsprintf(&value, "%s %llu", str, cfs_period) < 0)
+         return -1;
+-- 
+2.23.0
+
diff --git a/SOURCES/libvirt-vircgroupv2-fix-virCgroupV2GetCpuCfsQuota-for-max-value.patch b/SOURCES/libvirt-vircgroupv2-fix-virCgroupV2GetCpuCfsQuota-for-max-value.patch
new file mode 100644
index 0000000..06680d6
--- /dev/null
+++ b/SOURCES/libvirt-vircgroupv2-fix-virCgroupV2GetCpuCfsQuota-for-max-value.patch
@@ -0,0 +1,39 @@
+From dd46b194155d91d44d8c10f5bca48a5b4d296f63 Mon Sep 17 00:00:00 2001
+Message-Id: <dd46b194155d91d44d8c10f5bca48a5b4d296f63@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Wed, 21 Aug 2019 09:42:35 +0200
+Subject: [PATCH] vircgroupv2: fix virCgroupV2GetCpuCfsQuota for "max" value
+
+If the first value in cpu.max is "max" return from function.
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1741837
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
+(cherry picked from commit 23689cddd4542041cdfa3416705993d373033961)
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <287fbea9b44a5f7263505dc5fbd72d1bf2692bc6.1566373284.git.phrdina@redhat.com>
+Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/util/vircgroupv2.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/src/util/vircgroupv2.c b/src/util/vircgroupv2.c
+index e129686a52..e31a2d1121 100644
+--- a/src/util/vircgroupv2.c
++++ b/src/util/vircgroupv2.c
+@@ -1581,8 +1581,10 @@ virCgroupV2GetCpuCfsQuota(virCgroupPtr group,
+         return -1;
+     }
+ 
+-    if (STREQLEN(str, "max", 3))
++    if (STREQLEN(str, "max", 3)) {
+         *cfs_quota = ULLONG_MAX / 1000;
++        return 0;
++    }
+ 
+     if (virStrToLong_ll(str, &str, 10, cfs_quota) < 0) {
+         virReportError(VIR_ERR_INTERNAL_ERROR,
+-- 
+2.23.0
+
diff --git a/SOURCES/libvirt-vircgroupv2-fix-virCgroupV2ValidateMachineGroup.patch b/SOURCES/libvirt-vircgroupv2-fix-virCgroupV2ValidateMachineGroup.patch
new file mode 100644
index 0000000..0b7339d
--- /dev/null
+++ b/SOURCES/libvirt-vircgroupv2-fix-virCgroupV2ValidateMachineGroup.patch
@@ -0,0 +1,47 @@
+From 9193cc6a2395f2f26bcae2d990f78b2860b08ae9 Mon Sep 17 00:00:00 2001
+Message-Id: <9193cc6a2395f2f26bcae2d990f78b2860b08ae9@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:08:10 +0200
+Subject: [PATCH] vircgroupv2: fix virCgroupV2ValidateMachineGroup
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+When libvirt is reconnecting to running domain that uses cgroup v2
+the QEMU process reports cgroup for the emulator directory because the
+main thread is in that cgroup.  We need to remove the "/emulator" part
+in order to match with the root cgroup directory name for that domain.
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 634bd528cb194439f0bea0815f579d0b0c1b1a92)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <963bff76d79df2da95b1881fc9b7329be7b59d52.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroupv2.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+diff --git a/src/util/vircgroupv2.c b/src/util/vircgroupv2.c
+index 5652fcfffb..8658454d8b 100644
+--- a/src/util/vircgroupv2.c
++++ b/src/util/vircgroupv2.c
+@@ -121,6 +121,13 @@ virCgroupV2ValidateMachineGroup(virCgroupPtr group,
+ 
+     if (!(tmp = strrchr(group->unified.placement, '/')))
+         return false;
++
++    if (STREQ(tmp, "/emulator")) {
++        *tmp = '\0';
++
++        if (!(tmp = strrchr(group->unified.placement, '/')))
++            return false;
++    }
+     tmp++;
+ 
+     if (STRNEQ(tmp, partmachinename) &&
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircgroupv2-store-enabled-controllers.patch b/SOURCES/libvirt-vircgroupv2-store-enabled-controllers.patch
new file mode 100644
index 0000000..86a974a
--- /dev/null
+++ b/SOURCES/libvirt-vircgroupv2-store-enabled-controllers.patch
@@ -0,0 +1,79 @@
+From 6d526969ab72e7c35b988a7154d8343001a05208 Mon Sep 17 00:00:00 2001
+Message-Id: <6d526969ab72e7c35b988a7154d8343001a05208@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Thu, 25 Jul 2019 13:37:02 +0200
+Subject: [PATCH] vircgroupv2: store enabled controllers
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+In cgroups v2 when a new group is created by default no controller is
+enabled so the detection code will not detect any controllers.
+
+When enabling the controllers we should also store them for the group.
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Acked-by: Peter Krempa <pkrempa@redhat.com>
+(cherry picked from commit 56fdf3f025207a550726767e3f0ec1f290603ba4)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <3cef886d4257a746e5a7182246d5457664d8bcec.1564054553.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircgroupv2.c | 11 +++++++----
+ 1 file changed, 7 insertions(+), 4 deletions(-)
+
+diff --git a/src/util/vircgroupv2.c b/src/util/vircgroupv2.c
+index 7b3cd64cc5..9ae47e775e 100644
+--- a/src/util/vircgroupv2.c
++++ b/src/util/vircgroupv2.c
+@@ -364,7 +364,8 @@ virCgroupV2PathOfController(virCgroupPtr group,
+  *          0 on success
+  */
+ static int
+-virCgroupV2EnableController(virCgroupPtr parent,
++virCgroupV2EnableController(virCgroupPtr group,
++                            virCgroupPtr parent,
+                             int controller,
+                             bool report)
+ {
+@@ -390,6 +391,8 @@ virCgroupV2EnableController(virCgroupPtr parent,
+         return -2;
+     }
+ 
++    group->unified.controllers |= 1 << controller;
++
+     return 0;
+ }
+ 
+@@ -431,14 +434,14 @@ virCgroupV2MakeGroup(virCgroupPtr parent ATTRIBUTE_UNUSED,
+             }
+ 
+             if (virCgroupV2HasController(parent, VIR_CGROUP_CONTROLLER_CPU) &&
+-                virCgroupV2EnableController(parent,
++                virCgroupV2EnableController(group, parent,
+                                             VIR_CGROUP_CONTROLLER_CPU,
+                                             true) < 0) {
+                 return -1;
+             }
+ 
+             if (virCgroupV2HasController(parent, VIR_CGROUP_CONTROLLER_CPUSET) &&
+-                virCgroupV2EnableController(parent,
++                virCgroupV2EnableController(group, parent,
+                                             VIR_CGROUP_CONTROLLER_CPUSET,
+                                             true) < 0) {
+                 return -1;
+@@ -455,7 +458,7 @@ virCgroupV2MakeGroup(virCgroupPtr parent ATTRIBUTE_UNUSED,
+                 if (i == VIR_CGROUP_CONTROLLER_CPUACCT)
+                     continue;
+ 
+-                rc = virCgroupV2EnableController(parent, i, false);
++                rc = virCgroupV2EnableController(group, parent, i, false);
+                 if (rc < 0) {
+                     if (rc == -2) {
+                         virResetLastError();
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircommand-Separate-mass-FD-closing-into-a-function.patch b/SOURCES/libvirt-vircommand-Separate-mass-FD-closing-into-a-function.patch
new file mode 100644
index 0000000..eea098c
--- /dev/null
+++ b/SOURCES/libvirt-vircommand-Separate-mass-FD-closing-into-a-function.patch
@@ -0,0 +1,111 @@
+From 0f27acb41229aa29d539f1975c36c78f75fdf11c Mon Sep 17 00:00:00 2001
+Message-Id: <0f27acb41229aa29d539f1975c36c78f75fdf11c@dist-git>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Tue, 30 Jul 2019 15:30:53 +0200
+Subject: [PATCH] vircommand: Separate mass FD closing into a function
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+I will optimize this code a bit in the next commit. But for that
+it is better if the code lives in a separate function.
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit c1a9bfbbba48fea44fdfbe532e084c5323c9c9b3)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1721434
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Message-Id: <6de04910a1dc7c2e5554983b504b1a9932411a60.1564493409.git.mprivozn@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/vircommand.c | 52 ++++++++++++++++++++++++++++---------------
+ 1 file changed, 34 insertions(+), 18 deletions(-)
+
+diff --git a/src/util/vircommand.c b/src/util/vircommand.c
+index d328431373..8ae9a952a3 100644
+--- a/src/util/vircommand.c
++++ b/src/util/vircommand.c
+@@ -491,6 +491,37 @@ virExecCommon(virCommandPtr cmd, gid_t *groups, int ngroups)
+     return ret;
+ }
+ 
++static int
++virCommandMassClose(virCommandPtr cmd,
++                    int childin,
++                    int childout,
++                    int childerr)
++{
++    int openmax = sysconf(_SC_OPEN_MAX);
++    int fd;
++    int tmpfd;
++
++    if (openmax < 0) {
++        virReportSystemError(errno,  "%s",
++                             _("sysconf(_SC_OPEN_MAX) failed"));
++        return -1;
++    }
++
++    for (fd = 3; fd < openmax; fd++) {
++        if (fd == childin || fd == childout || fd == childerr)
++            continue;
++        if (!virCommandFDIsSet(cmd, fd)) {
++            tmpfd = fd;
++            VIR_MASS_CLOSE(tmpfd);
++        } else if (virSetInherit(fd, true) < 0) {
++            virReportSystemError(errno, _("failed to preserve fd %d"), fd);
++            return -1;
++        }
++    }
++
++    return 0;
++}
++
+ /*
+  * virExec:
+  * @cmd virCommandPtr containing all information about the program to
+@@ -500,13 +531,12 @@ static int
+ virExec(virCommandPtr cmd)
+ {
+     pid_t pid;
+-    int null = -1, fd, openmax;
++    int null = -1;
+     int pipeout[2] = {-1, -1};
+     int pipeerr[2] = {-1, -1};
+     int childin = cmd->infd;
+     int childout = -1;
+     int childerr = -1;
+-    int tmpfd;
+     VIR_AUTOFREE(char *) binarystr = NULL;
+     const char *binary = NULL;
+     int ret;
+@@ -612,23 +642,9 @@ virExec(virCommandPtr cmd)
+     if (cmd->mask)
+         umask(cmd->mask);
+     ret = EXIT_CANCELED;
+-    openmax = sysconf(_SC_OPEN_MAX);
+-    if (openmax < 0) {
+-        virReportSystemError(errno,  "%s",
+-                             _("sysconf(_SC_OPEN_MAX) failed"));
++
++    if (virCommandMassClose(cmd, childin, childout, childerr) < 0)
+         goto fork_error;
+-    }
+-    for (fd = 3; fd < openmax; fd++) {
+-        if (fd == childin || fd == childout || fd == childerr)
+-            continue;
+-        if (!virCommandFDIsSet(cmd, fd)) {
+-            tmpfd = fd;
+-            VIR_MASS_CLOSE(tmpfd);
+-        } else if (virSetInherit(fd, true) < 0) {
+-            virReportSystemError(errno, _("failed to preserve fd %d"), fd);
+-            goto fork_error;
+-        }
+-    }
+ 
+     if (prepareStdFd(childin, STDIN_FILENO) < 0) {
+         virReportSystemError(errno,
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-vircpuhost-Add-support-for-reading-MSRs.patch b/SOURCES/libvirt-vircpuhost-Add-support-for-reading-MSRs.patch
new file mode 100644
index 0000000..1f5ccce
--- /dev/null
+++ b/SOURCES/libvirt-vircpuhost-Add-support-for-reading-MSRs.patch
@@ -0,0 +1,155 @@
+From 6094ea6111dd57274b6037e76f662a06b8e5c9d1 Mon Sep 17 00:00:00 2001
+Message-Id: <6094ea6111dd57274b6037e76f662a06b8e5c9d1@dist-git>
+From: Jiri Denemark <jdenemar@redhat.com>
+Date: Fri, 21 Jun 2019 09:25:43 +0200
+Subject: [PATCH] vircpuhost: Add support for reading MSRs
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The new virHostCPUGetMSR internal API will try to read the MSR from
+/dev/cpu/0/msr and if it is not possible (the device does not exist or
+libvirt is running unprivileged), it will fallback to asking KVM for the
+MSR using KVM_GET_MSRS ioctl.
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+(cherry picked from commit df4b46737f43a1a67f9b5de2840213a1bd2b3cce)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1697627
+
+Conflicts:
+	src/util/virhostcpu.h
+            - different header file guard symbol
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <0d4c18704c435cccc2b18ebd55f4f914caf05d13.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/libvirt_private.syms |  1 +
+ src/util/virhostcpu.c    | 80 ++++++++++++++++++++++++++++++++++++++++
+ src/util/virhostcpu.h    |  3 ++
+ 3 files changed, 84 insertions(+)
+
+diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
+index 347667b17c..9ebc5384fb 100644
+--- a/src/libvirt_private.syms
++++ b/src/libvirt_private.syms
+@@ -1974,6 +1974,7 @@ virHostCPUGetInfo;
+ virHostCPUGetKVMMaxVCPUs;
+ virHostCPUGetMap;
+ virHostCPUGetMicrocodeVersion;
++virHostCPUGetMSR;
+ virHostCPUGetOnline;
+ virHostCPUGetOnlineBitmap;
+ virHostCPUGetPresentBitmap;
+diff --git a/src/util/virhostcpu.c b/src/util/virhostcpu.c
+index effe04ca3a..d0c47faa18 100644
+--- a/src/util/virhostcpu.c
++++ b/src/util/virhostcpu.c
+@@ -64,6 +64,7 @@
+ VIR_LOG_INIT("util.hostcpu");
+ 
+ #define KVM_DEVICE "/dev/kvm"
++#define MSR_DEVICE "/dev/cpu/0/msr"
+ 
+ 
+ #if defined(__FreeBSD__) || defined(__APPLE__)
+@@ -1266,3 +1267,82 @@ virHostCPUGetMicrocodeVersion(void)
+ }
+ 
+ #endif /* __linux__ */
++
++
++#if HAVE_LINUX_KVM_H && defined(KVM_GET_MSRS)
++static int
++virHostCPUGetMSRFromKVM(unsigned long index,
++                        uint64_t *result)
++{
++    VIR_AUTOCLOSE fd = -1;
++    struct {
++        struct kvm_msrs header;
++        struct kvm_msr_entry entry;
++    } msr = {
++        .header = { .nmsrs = 1 },
++        .entry = { .index = index },
++    };
++
++    if ((fd = open(KVM_DEVICE, O_RDONLY)) < 0) {
++        virReportSystemError(errno, _("Unable to open %s"), KVM_DEVICE);
++        return -1;
++    }
++
++    if (ioctl(fd, KVM_GET_MSRS, &msr) < 0) {
++        VIR_DEBUG("Cannot get MSR 0x%lx from KVM", index);
++        return 1;
++    }
++
++    *result = msr.entry.data;
++    return 0;
++}
++
++#else
++
++static int
++virHostCPUGetMSRFromKVM(unsigned long index ATTRIBUTE_UNUSED,
++                        uint64_t *result ATTRIBUTE_UNUSED)
++{
++    virReportSystemError(ENOSYS, "%s",
++                         _("Reading MSRs via KVM is not supported on this platform"));
++    return -1;
++}
++#endif /* HAVE_LINUX_KVM_H && defined(KVM_GET_MSRS) */
++
++
++/*
++ * Returns 0 on success,
++ *         1 when the MSR is not supported by the host CPU,
++*         -1 on error.
++ */
++int
++virHostCPUGetMSR(unsigned long index,
++                 uint64_t *msr)
++{
++    VIR_AUTOCLOSE fd = -1;
++    char ebuf[1024];
++
++    *msr = 0;
++
++    if ((fd = open(MSR_DEVICE, O_RDONLY)) < 0) {
++        VIR_DEBUG("Unable to open %s: %s",
++                  MSR_DEVICE, virStrerror(errno, ebuf, sizeof(ebuf)));
++    } else {
++        int rc = pread(fd, msr, sizeof(*msr), index);
++
++        if (rc == sizeof(*msr))
++            return 0;
++
++        if (rc < 0 && errno == EIO) {
++            VIR_DEBUG("CPU does not support MSR 0x%lx", index);
++            return 1;
++        }
++
++        VIR_DEBUG("Cannot read MSR 0x%lx from %s: %s",
++                  index, MSR_DEVICE, virStrerror(errno, ebuf, sizeof(ebuf)));
++    }
++
++    VIR_DEBUG("Falling back to KVM ioctl");
++
++    return virHostCPUGetMSRFromKVM(index, msr);
++}
+diff --git a/src/util/virhostcpu.h b/src/util/virhostcpu.h
+index f9f3359288..e705623d4f 100644
+--- a/src/util/virhostcpu.h
++++ b/src/util/virhostcpu.h
+@@ -68,4 +68,7 @@ int virHostCPUGetOnline(unsigned int cpu, bool *online);
+ 
+ unsigned int virHostCPUGetMicrocodeVersion(void);
+ 
++int virHostCPUGetMSR(unsigned long index,
++                     uint64_t *msr);
++
+ #endif /* __VIR_HOSTCPU_H__*/
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-virdbus-Grab-a-ref-as-long-as-the-while-loop-is-executed.patch b/SOURCES/libvirt-virdbus-Grab-a-ref-as-long-as-the-while-loop-is-executed.patch
new file mode 100644
index 0000000..499c3d4
--- /dev/null
+++ b/SOURCES/libvirt-virdbus-Grab-a-ref-as-long-as-the-while-loop-is-executed.patch
@@ -0,0 +1,49 @@
+From 2b04ec4cfae111f315514395030ab1106b6370da Mon Sep 17 00:00:00 2001
+Message-Id: <2b04ec4cfae111f315514395030ab1106b6370da@dist-git>
+From: Marc Hartmayer <mhartmay@linux.vnet.ibm.com>
+Date: Fri, 16 Aug 2019 16:01:55 +0200
+Subject: [PATCH] virdbus: Grab a ref as long as the while loop is executed
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Grab a ref for info->bus (a DBus connection) as long as the while loop
+is running. With the grabbed reference it is ensured that info->bus
+isn't freed as long as the while loop is executed. This is necessary
+as it's allowed to drop the last ref for the bus connection in a
+handler.
+
+There was already a bug of this kind in libdbus itself:
+https://bugs.freedesktop.org/show_bug.cgi?id=15635.
+
+Signed-off-by: Marc Hartmayer <mhartmay@linux.ibm.com>
+Reviewed-by: Boris Fiuczynski <fiuczy@linux.ibm.com>
+Reviewed-by: John Ferlan <jferlan@redhat.com>
+(cherry picked from commit 6707ffd11c1d8940ca7dfa7aaef707a60ef6756e)
+
+RHEL-8.1.0: https://bugzilla.redhat.com/show_bug.cgi?id=1741900
+Signed-off-by: Ján Tomko <jtomko@redhat.com>
+Message-Id: <9656cea8218d901d5e44a157362cd0f009ff1a7d.1565964111.git.jtomko@redhat.com>
+Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
+---
+ src/util/virdbus.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/src/util/virdbus.c b/src/util/virdbus.c
+index ba8b684f17..d0e2c76e48 100644
+--- a/src/util/virdbus.c
++++ b/src/util/virdbus.c
+@@ -198,8 +198,10 @@ static void virDBusWatchCallback(int fdatch ATTRIBUTE_UNUSED,
+ 
+     (void)dbus_watch_handle(watch, dbus_flags);
+ 
++    dbus_connection_ref(info->bus);
+     while (dbus_connection_dispatch(info->bus) == DBUS_DISPATCH_DATA_REMAINS)
+         /* keep dispatching while data remains */;
++    dbus_connection_unref(info->bus);
+ }
+ 
+ 
+-- 
+2.22.1
+
diff --git a/SOURCES/libvirt-virfile-Detect-ceph-as-shared-FS.patch b/SOURCES/libvirt-virfile-Detect-ceph-as-shared-FS.patch
new file mode 100644
index 0000000..0576034
--- /dev/null
+++ b/SOURCES/libvirt-virfile-Detect-ceph-as-shared-FS.patch
@@ -0,0 +1,139 @@
+From 6dd1c06ab2d05193d8cfee720f16d6b1d84b2cdf Mon Sep 17 00:00:00 2001
+Message-Id: <6dd1c06ab2d05193d8cfee720f16d6b1d84b2cdf@dist-git>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Tue, 4 Jun 2019 13:27:35 +0200
+Subject: [PATCH] virfile: Detect ceph as shared FS
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1665553
+
+Ceph can be mounted just like any other filesystem and in fact is
+a shared and cluster filesystem. The filesystem magic constant
+was taken from kernel sources as it is not in magic.h yet.
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Reviewed-by: Erik Skultety <eskultet@redhat.com>
+(cherry picked from commit 6dd2a2ae6386b1d51edcc9a434f56d7f9dc2cb35)
+https: //bugzilla.redhat.com/show_bug.cgi?id=1698133
+Message-Id: <55c1009db101780867229bdeea3f739db2efafeb.1559647301.git.pkrempa@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/virfile.c            | 9 ++++++++-
+ src/util/virfile.h            | 1 +
+ src/util/virstoragefile.c     | 3 ++-
+ tests/virfiledata/mounts3.txt | 2 ++
+ tests/virfilemock.c           | 5 +++++
+ tests/virfiletest.c           | 2 ++
+ 6 files changed, 20 insertions(+), 2 deletions(-)
+
+diff --git a/src/util/virfile.c b/src/util/virfile.c
+index 716b55d770..471d309062 100644
+--- a/src/util/virfile.c
++++ b/src/util/virfile.c
+@@ -3537,6 +3537,9 @@ int virFilePrintf(FILE *fp, const char *msg, ...)
+ # ifndef FUSE_SUPER_MAGIC
+ #  define FUSE_SUPER_MAGIC 0x65735546
+ # endif
++# ifndef CEPH_SUPER_MAGIC
++#  define CEPH_SUPER_MAGIC 0x00C36400
++# endif
+ 
+ # define PROC_MOUNTS "/proc/mounts"
+ 
+@@ -3682,6 +3685,9 @@ virFileIsSharedFSType(const char *path,
+     if ((fstypes & VIR_FILE_SHFS_CIFS) &&
+         (f_type == CIFS_SUPER_MAGIC))
+         return 1;
++    if ((fstypes & VIR_FILE_SHFS_CEPH) &&
++        (f_type == CEPH_SUPER_MAGIC))
++        return 1;
+ 
+     return 0;
+ }
+@@ -3845,7 +3851,8 @@ int virFileIsSharedFS(const char *path)
+                                  VIR_FILE_SHFS_OCFS |
+                                  VIR_FILE_SHFS_AFS |
+                                  VIR_FILE_SHFS_SMB |
+-                                 VIR_FILE_SHFS_CIFS);
++                                 VIR_FILE_SHFS_CIFS |
++                                 VIR_FILE_SHFS_CEPH);
+ }
+ 
+ 
+diff --git a/src/util/virfile.h b/src/util/virfile.h
+index 6f1e802fde..1d16e96b59 100644
+--- a/src/util/virfile.h
++++ b/src/util/virfile.h
+@@ -205,6 +205,7 @@ enum {
+     VIR_FILE_SHFS_AFS = (1 << 3),
+     VIR_FILE_SHFS_SMB = (1 << 4),
+     VIR_FILE_SHFS_CIFS = (1 << 5),
++    VIR_FILE_SHFS_CEPH = (1 << 6),
+ };
+ 
+ int virFileIsSharedFSType(const char *path, int fstypes) ATTRIBUTE_NONNULL(1);
+diff --git a/src/util/virstoragefile.c b/src/util/virstoragefile.c
+index 58f67278da..0b15219c3e 100644
+--- a/src/util/virstoragefile.c
++++ b/src/util/virstoragefile.c
+@@ -1366,7 +1366,8 @@ int virStorageFileIsClusterFS(const char *path)
+      */
+     return virFileIsSharedFSType(path,
+                                  VIR_FILE_SHFS_GFS2 |
+-                                 VIR_FILE_SHFS_OCFS);
++                                 VIR_FILE_SHFS_OCFS |
++                                 VIR_FILE_SHFS_CEPH);
+ }
+ 
+ #ifdef LVS
+diff --git a/tests/virfiledata/mounts3.txt b/tests/virfiledata/mounts3.txt
+index 134c6e8f81..68eded048c 100644
+--- a/tests/virfiledata/mounts3.txt
++++ b/tests/virfiledata/mounts3.txt
+@@ -33,3 +33,5 @@ host:/nfs /nfs nfs4 rw,relatime,vers=4.1,rsize=1048576,wsize=1048576,namlen=255,
+ dev /nfs/blah devtmpfs rw,nosuid,relatime,size=10240k,nr_inodes=4093060,mode=755 0 0
+ host:/gv0 /gluster fuse.glusterfs rw 0 0
+ root@host:/tmp/mkdir /gluster/sshfs fuse.sshfs rw 0 0
++192.168.0.1:/ceph/data /ceph ceph rw,noatime,name=cephfs,secret=<hidden>,acl,wsize=16777216 0 0
++192.168.0.1,192.168.0.2,192.168.0.3:/ceph/data2 /ceph/multi ceph rw,noatime,name=cephfs,secret=<hidden>,acl,wsize=16777216 0 0
+diff --git a/tests/virfilemock.c b/tests/virfilemock.c
+index ae5c8d025a..eb5182df66 100644
+--- a/tests/virfilemock.c
++++ b/tests/virfilemock.c
+@@ -88,6 +88,9 @@ setmntent(const char *filename, const char *type)
+ #ifndef FUSE_SUPER_MAGIC
+ # define FUSE_SUPER_MAGIC 0x65735546
+ #endif
++#ifndef CEPH_SUPER_MAGIC
++# define CEPH_SUPER_MAGIC 0x00c36400
++#endif
+ 
+ 
+ static int
+@@ -134,6 +137,8 @@ statfs_mock(const char *mtab,
+             ftype = CIFS_SUPER_MAGIC;
+         } else if (STRPREFIX(mb.mnt_type, "fuse")) {
+             ftype = FUSE_SUPER_MAGIC;
++        } else if (STRPREFIX(mb.mnt_type, "ceph")) {
++            ftype = CEPH_SUPER_MAGIC;
+         } else {
+             /* Everything else is EXT4. We don't care really for other paths. */
+             ftype = EXT4_SUPER_MAGIC;
+diff --git a/tests/virfiletest.c b/tests/virfiletest.c
+index a246d601ba..972c07fdc5 100644
+--- a/tests/virfiletest.c
++++ b/tests/virfiletest.c
+@@ -458,6 +458,8 @@ mymain(void)
+     DO_TEST_FILE_IS_SHARED_FS_TYPE("mounts3.txt", "/gluster/file", true);
+     DO_TEST_FILE_IS_SHARED_FS_TYPE("mounts3.txt", "/gluster/sshfs/file", false);
+     DO_TEST_FILE_IS_SHARED_FS_TYPE("mounts3.txt", "/some/symlink/file", true);
++    DO_TEST_FILE_IS_SHARED_FS_TYPE("mounts3.txt", "/ceph/file", true);
++    DO_TEST_FILE_IS_SHARED_FS_TYPE("mounts3.txt", "/ceph/multi/file", true);
+ 
+     return ret != 0 ? EXIT_FAILURE : EXIT_SUCCESS;
+ }
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-virfile-added-GPFS-as-shared-fs.patch b/SOURCES/libvirt-virfile-added-GPFS-as-shared-fs.patch
new file mode 100644
index 0000000..b807638
--- /dev/null
+++ b/SOURCES/libvirt-virfile-added-GPFS-as-shared-fs.patch
@@ -0,0 +1,124 @@
+From fca427057cfad652bd787096b9af94d273c69185 Mon Sep 17 00:00:00 2001
+Message-Id: <fca427057cfad652bd787096b9af94d273c69185@dist-git>
+From: Diego Michelotto <diego.michelotto@cnaf.infn.it>
+Date: Tue, 4 Jun 2019 13:27:36 +0200
+Subject: [PATCH] virfile: added GPFS as shared fs
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Added GPFS as shared file system recognized during live migration
+security checks.
+
+GPFS is 'IBM General Parallel File System' also called
+'IBM Spectrum Scale'
+
+BUG: https://bugzilla.redhat.com/show_bug.cgi?id=1679528
+
+Signed-off-by: Diego Michelotto <diego.michelotto@cnaf.infn.it>
+Signed-off-by: Peter Krempa <pkrempa@redhat.com>
+(cherry picked from commit d163b940a73a0d6b8277a4bccef2b60936933cf0)
+https: //bugzilla.redhat.com/show_bug.cgi?id=1698133
+Message-Id: <5d98c30627de2ed2fd02a77ecadaac0585c5fb15.1559647301.git.pkrempa@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/virfile.c            | 9 ++++++++-
+ src/util/virfile.h            | 1 +
+ tests/virfiledata/mounts3.txt | 1 +
+ tests/virfilemock.c           | 5 +++++
+ tests/virfiletest.c           | 1 +
+ 5 files changed, 16 insertions(+), 1 deletion(-)
+
+diff --git a/src/util/virfile.c b/src/util/virfile.c
+index 471d309062..e0564295dd 100644
+--- a/src/util/virfile.c
++++ b/src/util/virfile.c
+@@ -3540,6 +3540,9 @@ int virFilePrintf(FILE *fp, const char *msg, ...)
+ # ifndef CEPH_SUPER_MAGIC
+ #  define CEPH_SUPER_MAGIC 0x00C36400
+ # endif
++# ifndef GPFS_SUPER_MAGIC
++#  define GPFS_SUPER_MAGIC 0x47504653
++# endif
+ 
+ # define PROC_MOUNTS "/proc/mounts"
+ 
+@@ -3688,6 +3691,9 @@ virFileIsSharedFSType(const char *path,
+     if ((fstypes & VIR_FILE_SHFS_CEPH) &&
+         (f_type == CEPH_SUPER_MAGIC))
+         return 1;
++    if ((fstypes & VIR_FILE_SHFS_GPFS) &&
++        (f_type == GPFS_SUPER_MAGIC))
++        return 1;
+ 
+     return 0;
+ }
+@@ -3852,7 +3858,8 @@ int virFileIsSharedFS(const char *path)
+                                  VIR_FILE_SHFS_AFS |
+                                  VIR_FILE_SHFS_SMB |
+                                  VIR_FILE_SHFS_CIFS |
+-                                 VIR_FILE_SHFS_CEPH);
++                                 VIR_FILE_SHFS_CEPH |
++                                 VIR_FILE_SHFS_GPFS);
+ }
+ 
+ 
+diff --git a/src/util/virfile.h b/src/util/virfile.h
+index 1d16e96b59..51c221e069 100644
+--- a/src/util/virfile.h
++++ b/src/util/virfile.h
+@@ -206,6 +206,7 @@ enum {
+     VIR_FILE_SHFS_SMB = (1 << 4),
+     VIR_FILE_SHFS_CIFS = (1 << 5),
+     VIR_FILE_SHFS_CEPH = (1 << 6),
++    VIR_FILE_SHFS_GPFS = (1 << 7),
+ };
+ 
+ int virFileIsSharedFSType(const char *path, int fstypes) ATTRIBUTE_NONNULL(1);
+diff --git a/tests/virfiledata/mounts3.txt b/tests/virfiledata/mounts3.txt
+index 68eded048c..4377e5d471 100644
+--- a/tests/virfiledata/mounts3.txt
++++ b/tests/virfiledata/mounts3.txt
+@@ -35,3 +35,4 @@ host:/gv0 /gluster fuse.glusterfs rw 0 0
+ root@host:/tmp/mkdir /gluster/sshfs fuse.sshfs rw 0 0
+ 192.168.0.1:/ceph/data /ceph ceph rw,noatime,name=cephfs,secret=<hidden>,acl,wsize=16777216 0 0
+ 192.168.0.1,192.168.0.2,192.168.0.3:/ceph/data2 /ceph/multi ceph rw,noatime,name=cephfs,secret=<hidden>,acl,wsize=16777216 0 0
++gpfs_data /gpfs/data gpfs rw,relatime 0 0
+diff --git a/tests/virfilemock.c b/tests/virfilemock.c
+index eb5182df66..02f26433d4 100644
+--- a/tests/virfilemock.c
++++ b/tests/virfilemock.c
+@@ -91,6 +91,9 @@ setmntent(const char *filename, const char *type)
+ #ifndef CEPH_SUPER_MAGIC
+ # define CEPH_SUPER_MAGIC 0x00c36400
+ #endif
++#ifndef GPFS_SUPER_MAGIC
++# define GPFS_SUPER_MAGIC 0x47504653
++#endif
+ 
+ 
+ static int
+@@ -139,6 +142,8 @@ statfs_mock(const char *mtab,
+             ftype = FUSE_SUPER_MAGIC;
+         } else if (STRPREFIX(mb.mnt_type, "ceph")) {
+             ftype = CEPH_SUPER_MAGIC;
++        } else if (STRPREFIX(mb.mnt_type, "gpfs")) {
++            ftype = GPFS_SUPER_MAGIC;
+         } else {
+             /* Everything else is EXT4. We don't care really for other paths. */
+             ftype = EXT4_SUPER_MAGIC;
+diff --git a/tests/virfiletest.c b/tests/virfiletest.c
+index 972c07fdc5..5f17676c75 100644
+--- a/tests/virfiletest.c
++++ b/tests/virfiletest.c
+@@ -460,6 +460,7 @@ mymain(void)
+     DO_TEST_FILE_IS_SHARED_FS_TYPE("mounts3.txt", "/some/symlink/file", true);
+     DO_TEST_FILE_IS_SHARED_FS_TYPE("mounts3.txt", "/ceph/file", true);
+     DO_TEST_FILE_IS_SHARED_FS_TYPE("mounts3.txt", "/ceph/multi/file", true);
++    DO_TEST_FILE_IS_SHARED_FS_TYPE("mounts3.txt", "/gpfs/data", true);
+ 
+     return ret != 0 ? EXIT_FAILURE : EXIT_SUCCESS;
+ }
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-virhostcpu-Make-virHostCPUGetMSR-work-only-on-x86.patch b/SOURCES/libvirt-virhostcpu-Make-virHostCPUGetMSR-work-only-on-x86.patch
new file mode 100644
index 0000000..e9b18c4
--- /dev/null
+++ b/SOURCES/libvirt-virhostcpu-Make-virHostCPUGetMSR-work-only-on-x86.patch
@@ -0,0 +1,89 @@
+From 7ff2ecfcd684bcf4865ceac786f1c6809d84d0aa Mon Sep 17 00:00:00 2001
+Message-Id: <7ff2ecfcd684bcf4865ceac786f1c6809d84d0aa@dist-git>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Fri, 21 Jun 2019 09:25:44 +0200
+Subject: [PATCH] virhostcpu: Make virHostCPUGetMSR() work only on x86
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Model specific registers are a thing only on x86. Also, the
+/dev/cpu/0/msr path exists only on Linux and the fallback
+mechanism (asking KVM) exists on Linux and FreeBSD only.
+
+Therefore, move the function within #ifdef that checks all
+aforementioned constraints and provide a dummy stub for all
+other cases.
+
+This fixes the build on my arm box, mingw-* builds, etc.
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Reviewed-by: Jiri Denemark <jdenemar@redhat.com>
+(cherry picked from commit ae3d812b006b84c6d06605868d19554ea0156392)
+
+https://bugzilla.redhat.com/show_bug.cgi?id=1697627
+
+Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
+Message-Id: <0f234c69059ad57462bb71d42983cdaedea26e78.1561068591.git.jdenemar@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ src/util/virhostcpu.c | 32 ++++++++++++++++++--------------
+ 1 file changed, 18 insertions(+), 14 deletions(-)
+
+diff --git a/src/util/virhostcpu.c b/src/util/virhostcpu.c
+index d0c47faa18..aafa84c8e5 100644
+--- a/src/util/virhostcpu.c
++++ b/src/util/virhostcpu.c
+@@ -1269,7 +1269,9 @@ virHostCPUGetMicrocodeVersion(void)
+ #endif /* __linux__ */
+ 
+ 
+-#if HAVE_LINUX_KVM_H && defined(KVM_GET_MSRS)
++#if HAVE_LINUX_KVM_H && defined(KVM_GET_MSRS) && \
++    (defined(__i386__) || defined(__x86_64__)) && \
++    (defined(__linux__) || defined(__FreeBSD__))
+ static int
+ virHostCPUGetMSRFromKVM(unsigned long index,
+                         uint64_t *result)
+@@ -1297,19 +1299,6 @@ virHostCPUGetMSRFromKVM(unsigned long index,
+     return 0;
+ }
+ 
+-#else
+-
+-static int
+-virHostCPUGetMSRFromKVM(unsigned long index ATTRIBUTE_UNUSED,
+-                        uint64_t *result ATTRIBUTE_UNUSED)
+-{
+-    virReportSystemError(ENOSYS, "%s",
+-                         _("Reading MSRs via KVM is not supported on this platform"));
+-    return -1;
+-}
+-#endif /* HAVE_LINUX_KVM_H && defined(KVM_GET_MSRS) */
+-
+-
+ /*
+  * Returns 0 on success,
+  *         1 when the MSR is not supported by the host CPU,
+@@ -1346,3 +1335,18 @@ virHostCPUGetMSR(unsigned long index,
+ 
+     return virHostCPUGetMSRFromKVM(index, msr);
+ }
++
++#else
++
++int
++virHostCPUGetMSR(unsigned long index ATTRIBUTE_UNUSED,
++                 uint64_t *msr ATTRIBUTE_UNUSED)
++{
++    virReportSystemError(ENOSYS, "%s",
++                         _("Reading MSRs is not supported on this platform"));
++    return -1;
++}
++
++#endif /* HAVE_LINUX_KVM_H && defined(KVM_GET_MSRS) && \
++          (defined(__i386__) || defined(__x86_64__)) && \
++          (defined(__linux__) || defined(__FreeBSD__)) */
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-virt-host-validate-Fix-build-on-non-Linux.patch b/SOURCES/libvirt-virt-host-validate-Fix-build-on-non-Linux.patch
new file mode 100644
index 0000000..39c9f15
--- /dev/null
+++ b/SOURCES/libvirt-virt-host-validate-Fix-build-on-non-Linux.patch
@@ -0,0 +1,45 @@
+From f3366321b1911d327985ed16717a8589869d6fb3 Mon Sep 17 00:00:00 2001
+Message-Id: <f3366321b1911d327985ed16717a8589869d6fb3@dist-git>
+From: Michal Privoznik <mprivozn@redhat.com>
+Date: Mon, 1 Jul 2019 17:08:05 +0200
+Subject: [PATCH] virt-host-validate: Fix build on non-Linux
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+For non-Linux platforms we have
+virHostValidateCGroupControllers() stub which only reports an
+error. But we are not marking the ignored arguments the way we
+should.
+
+Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
+Reviewed-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 8524faf8c4007edfbc5363a018821139667a9e32)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <34a0cf3fd56060036b473a82c9b2b39beba0d589.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ tools/virt-host-validate-common.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/tools/virt-host-validate-common.c b/tools/virt-host-validate-common.c
+index 73165d673a..5dd1605daa 100644
+--- a/tools/virt-host-validate-common.c
++++ b/tools/virt-host-validate-common.c
+@@ -324,8 +324,8 @@ int virHostValidateCGroupControllers(const char *hvname,
+     return ret;
+ }
+ #else /*  !__linux__ */
+-int virHostValidateCGroupControllers(const char *hvname,
+-                                     int controllers,
++int virHostValidateCGroupControllers(const char *hvname ATTRIBUTE_UNUSED,
++                                     int controllers ATTRIBUTE_UNUSED,
+                                      virHostValidateLevel level)
+ {
+     virHostMsgFail(level, "%s", "This platform does not support cgroups");
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-virt-host-validate-require-freezer-for-LXC.patch b/SOURCES/libvirt-virt-host-validate-require-freezer-for-LXC.patch
new file mode 100644
index 0000000..a54edba
--- /dev/null
+++ b/SOURCES/libvirt-virt-host-validate-require-freezer-for-LXC.patch
@@ -0,0 +1,38 @@
+From f150121476cbe99dcca7378583aa1f0533c072d1 Mon Sep 17 00:00:00 2001
+Message-Id: <f150121476cbe99dcca7378583aa1f0533c072d1@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:08:04 +0200
+Subject: [PATCH] virt-host-validate: require freezer for LXC
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Cgroup freezer support for LXC was added in libvirt-0.7.2.
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 0a7101c89b787d2f45690f8ad3a4b932b000b758)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <ffd30e592e34a26e5b610b07b705da9727ce3cd2.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ tools/virt-host-validate-lxc.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/tools/virt-host-validate-lxc.c b/tools/virt-host-validate-lxc.c
+index 3c55b1b26d..8613f37cc7 100644
+--- a/tools/virt-host-validate-lxc.c
++++ b/tools/virt-host-validate-lxc.c
+@@ -70,6 +70,7 @@ int virHostValidateLXC(void)
+                                          (1 << VIR_CGROUP_CONTROLLER_CPUACCT) |
+                                          (1 << VIR_CGROUP_CONTROLLER_CPUSET) |
+                                          (1 << VIR_CGROUP_CONTROLLER_DEVICES) |
++                                         (1 << VIR_CGROUP_CONTROLLER_FREEZER) |
+                                          (1 << VIR_CGROUP_CONTROLLER_BLKIO),
+                                          VIR_HOST_VALIDATE_FAIL) < 0) {
+         ret = -1;
+-- 
+2.22.0
+
diff --git a/SOURCES/libvirt-virt-host-validate-rewrite-cgroup-detection-to-use-util-vircgroup.patch b/SOURCES/libvirt-virt-host-validate-rewrite-cgroup-detection-to-use-util-vircgroup.patch
new file mode 100644
index 0000000..9e9a6fe
--- /dev/null
+++ b/SOURCES/libvirt-virt-host-validate-rewrite-cgroup-detection-to-use-util-vircgroup.patch
@@ -0,0 +1,371 @@
+From 0ede215415509022d94092b75ef075495c91a5d5 Mon Sep 17 00:00:00 2001
+Message-Id: <0ede215415509022d94092b75ef075495c91a5d5@dist-git>
+From: Pavel Hrdina <phrdina@redhat.com>
+Date: Mon, 1 Jul 2019 17:08:03 +0200
+Subject: [PATCH] virt-host-validate: rewrite cgroup detection to use
+ util/vircgroup
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This removes code duplication and simplifies cgroup detection.
+As a drawback we will not have separate messages to enable cgroup
+controller in kernel or to mount it.  On the other side the rewrite
+adds support for cgroup v2.
+
+The kernel config support was wrong because it was parsing
+'/proc/self/cgroup' instead of '/proc/cgroups/' file.
+
+The mount suggestion is removed as well because it will not work
+with cgroup v2.
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+(cherry picked from commit 0f4d7daa8cd43b62911413c2cc1614f87380e459)
+
+Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1689297
+
+Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
+Message-Id: <0a79b9dcaee25d04b993c4e6576d75ce7c45ac0f.1561993100.git.phrdina@redhat.com>
+Reviewed-by: Ján Tomko <jtomko@redhat.com>
+---
+ tools/virt-host-validate-common.c | 164 ++++++------------------------
+ tools/virt-host-validate-common.h |   7 +-
+ tools/virt-host-validate-lxc.c    |  38 ++-----
+ tools/virt-host-validate-qemu.c   |  38 ++-----
+ 4 files changed, 53 insertions(+), 194 deletions(-)
+
+diff --git a/tools/virt-host-validate-common.c b/tools/virt-host-validate-common.c
+index c45dfc5d8c..73165d673a 100644
+--- a/tools/virt-host-validate-common.c
++++ b/tools/virt-host-validate-common.c
+@@ -26,12 +26,10 @@
+ #include <stdio.h>
+ #include <unistd.h>
+ #include <sys/utsname.h>
+-#ifdef HAVE_MNTENT_H
+-# include <mntent.h>
+-#endif /* HAVE_MNTENT_H */
+ #include <sys/stat.h>
+ 
+ #include "viralloc.h"
++#include "vircgroup.h"
+ #include "virfile.h"
+ #include "virt-host-validate-common.h"
+ #include "virstring.h"
+@@ -290,152 +288,50 @@ int virHostValidateLinuxKernel(const char *hvname,
+     }
+ }
+ 
+-
+-static int virHostValidateCGroupSupport(const char *hvname,
+-                                        const char *cg_name,
+-                                        virHostValidateLevel level,
+-                                        const char *config_name)
++#ifdef __linux__
++int virHostValidateCGroupControllers(const char *hvname,
++                                     int controllers,
++                                     virHostValidateLevel level)
+ {
+-    virHostMsgCheck(hvname, "for cgroup '%s' controller support", cg_name);
+-    FILE *fp = fopen("/proc/self/cgroup", "r");
+-    size_t len = 0;
+-    char *line = NULL;
+-    ssize_t ret;
+-    bool matched = false;
++    virCgroupPtr group = NULL;
++    int ret = 0;
++    size_t i;
+ 
+-    if (!fp)
+-        goto error;
++    if (virCgroupNewSelf(&group) < 0)
++        return -1;
+ 
+-    while ((ret = getline(&line, &len, fp)) >= 0 && !matched) {
+-        char **cgroups;
+-        char *start;
+-        char *end;
+-        size_t ncgroups;
+-        size_t i;
++    for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
++        int flag = 1 << i;
++        const char *cg_name = virCgroupControllerTypeToString(i);
+ 
+-        /* Each line in this file looks like
+-         *
+-         *   4:cpu,cpuacct:/machine.slice/machine-qemu\x2dtest.scope/emulator
+-         *
+-         * Since multiple cgroups can be part of the same line and some cgroup
+-         * names can appear as part of other cgroup names (eg. 'cpu' is a
+-         * prefix for both 'cpuacct' and 'cpuset'), it's not enough to simply
+-         * check whether the cgroup name is present somewhere inside the file.
+-         *
+-         * Moreover, there's nothing stopping the cgroup name from appearing
+-         * in an unrelated mount point name as well */
+-
+-        /* Look for the first colon.
+-         * The part we're interested in starts right after it */
+-        if (!(start = strchr(line, ':')))
+-            continue;
+-        start++;
+-
+-        /* Look for the second colon.
+-         * The part we're interested in ends exactly there */
+-        if (!(end = strchr(start, ':')))
+-            continue;
+-        *end = '\0';
+-
+-        if (!(cgroups = virStringSplitCount(start, ",", 0, &ncgroups)))
++        if (!(controllers & flag))
+             continue;
+ 
+-        /* Look for the matching cgroup */
+-        for (i = 0; i < ncgroups; i++) {
+-            if (STREQ(cgroups[i], cg_name))
+-                matched = true;
++        virHostMsgCheck(hvname, "for cgroup '%s' controller support", cg_name);
++
++        if (!virCgroupHasController(group, i)) {
++            ret = -1;
++            virHostMsgFail(level, "Enable '%s' in kernel Kconfig file or "
++                           "mount/enable cgroup controller in your system",
++                           cg_name);
++        } else {
++            virHostMsgPass();
+         }
+-
+-        virStringListFreeCount(cgroups, ncgroups);
+     }
+ 
+-    VIR_FREE(line);
+-    VIR_FORCE_FCLOSE(fp);
+-    if (!matched)
+-        goto error;
++    virCgroupFree(&group);
+ 
+-    virHostMsgPass();
+-    return 0;
+-
+- error:
+-    VIR_FREE(line);
+-    virHostMsgFail(level, "Enable CONFIG_%s in kernel Kconfig file", config_name);
+-    return -1;
++    return ret;
+ }
+-
+-#ifdef HAVE_MNTENT_H
+-static int virHostValidateCGroupMount(const char *hvname,
+-                                      const char *cg_name,
+-                                      virHostValidateLevel level)
++#else /*  !__linux__ */
++int virHostValidateCGroupControllers(const char *hvname,
++                                     int controllers,
++                                     virHostValidateLevel level)
+ {
+-    virHostMsgCheck(hvname, "for cgroup '%s' controller mount-point", cg_name);
+-    FILE *fp = setmntent("/proc/mounts", "r");
+-    struct mntent ent;
+-    char mntbuf[1024];
+-    bool matched = false;
+-
+-    if (!fp)
+-        goto error;
+-
+-    while (getmntent_r(fp, &ent, mntbuf, sizeof(mntbuf)) && !matched) {
+-        char **opts;
+-        size_t nopts;
+-        size_t i;
+-
+-        /* Ignore non-cgroup mounts */
+-        if (STRNEQ(ent.mnt_type, "cgroup"))
+-            continue;
+-
+-        if (!(opts = virStringSplitCount(ent.mnt_opts, ",", 0, &nopts)))
+-            continue;
+-
+-        /* Look for a mount option matching the cgroup name */
+-        for (i = 0; i < nopts; i++) {
+-            if (STREQ(opts[i], cg_name))
+-                matched = true;
+-        }
+-
+-        virStringListFreeCount(opts, nopts);
+-    }
+-    endmntent(fp);
+-    if (!matched)
+-        goto error;
+-
+-    virHostMsgPass();
+-    return 0;
+-
+- error:
+-    virHostMsgFail(level, "Mount '%s' cgroup controller (suggested at /sys/fs/cgroup/%s)",
+-                   cg_name, cg_name);
+-    return -1;
+-}
+-#else /* ! HAVE_MNTENT_H */
+-static int virHostValidateCGroupMount(const char *hvname,
+-                                      const char *cg_name,
+-                                      virHostValidateLevel level)
+-{
+-    virHostMsgCheck(hvname, "for cgroup '%s' controller mount-point", cg_name);
+     virHostMsgFail(level, "%s", "This platform does not support cgroups");
+     return -1;
+ }
+-#endif /* ! HAVE_MNTENT_H */
+-
+-int virHostValidateCGroupController(const char *hvname,
+-                                    const char *cg_name,
+-                                    virHostValidateLevel level,
+-                                    const char *config_name)
+-{
+-    if (virHostValidateCGroupSupport(hvname,
+-                                     cg_name,
+-                                     level,
+-                                     config_name) < 0)
+-        return -1;
+-    if (virHostValidateCGroupMount(hvname,
+-                                   cg_name,
+-                                   level) < 0)
+-        return -1;
+-    return 0;
+-}
++#endif /* !__linux__ */
+ 
+ int virHostValidateIOMMU(const char *hvname,
+                          virHostValidateLevel level)
+diff --git a/tools/virt-host-validate-common.h b/tools/virt-host-validate-common.h
+index b6fe17daa7..b23dd7cdbe 100644
+--- a/tools/virt-host-validate-common.h
++++ b/tools/virt-host-validate-common.h
+@@ -77,10 +77,9 @@ int virHostValidateNamespace(const char *hvname,
+                              virHostValidateLevel level,
+                              const char *hint);
+ 
+-int virHostValidateCGroupController(const char *hvname,
+-                                    const char *cg_name,
+-                                    virHostValidateLevel level,
+-                                    const char *config_name);
++int virHostValidateCGroupControllers(const char *hvname,
++                                     int controllers,
++                                     virHostValidateLevel level);
+ 
+ int virHostValidateIOMMU(const char *hvname,
+                          virHostValidateLevel level);
+diff --git a/tools/virt-host-validate-lxc.c b/tools/virt-host-validate-lxc.c
+index 64d9279c30..3c55b1b26d 100644
+--- a/tools/virt-host-validate-lxc.c
++++ b/tools/virt-host-validate-lxc.c
+@@ -23,6 +23,7 @@
+ 
+ #include "virt-host-validate-lxc.h"
+ #include "virt-host-validate-common.h"
++#include "vircgroup.h"
+ 
+ int virHostValidateLXC(void)
+ {
+@@ -63,35 +64,16 @@ int virHostValidateLXC(void)
+                                  _("User namespace support is recommended")) < 0)
+         ret = -1;
+ 
+-    if (virHostValidateCGroupController("LXC", "memory",
+-                                        VIR_HOST_VALIDATE_FAIL,
+-                                        "MEMCG") < 0)
+-        ret = -1;
+-
+-    if (virHostValidateCGroupController("LXC", "cpu",
+-                                        VIR_HOST_VALIDATE_FAIL,
+-                                        "CGROUP_CPU") < 0)
+-        ret = -1;
+-
+-    if (virHostValidateCGroupController("LXC", "cpuacct",
+-                                        VIR_HOST_VALIDATE_FAIL,
+-                                        "CGROUP_CPUACCT") < 0)
+-        ret = -1;
+-
+-    if (virHostValidateCGroupController("LXC", "cpuset",
+-                                        VIR_HOST_VALIDATE_FAIL,
+-                                        "CPUSETS") < 0)
+-        ret = -1;
+-
+-    if (virHostValidateCGroupController("LXC", "devices",
+-                                        VIR_HOST_VALIDATE_FAIL,
+-                                        "CGROUP_DEVICE") < 0)
+-        ret = -1;
+-
+-    if (virHostValidateCGroupController("LXC", "blkio",
+-                                        VIR_HOST_VALIDATE_FAIL,
+-                                        "BLK_CGROUP") < 0)
++    if (virHostValidateCGroupControllers("LXC",
++                                         (1 << VIR_CGROUP_CONTROLLER_MEMORY) |
++                                         (1 << VIR_CGROUP_CONTROLLER_CPU) |
++                                         (1 << VIR_CGROUP_CONTROLLER_CPUACCT) |
++                                         (1 << VIR_CGROUP_CONTROLLER_CPUSET) |
++                                         (1 << VIR_CGROUP_CONTROLLER_DEVICES) |
++                                         (1 << VIR_CGROUP_CONTROLLER_BLKIO),
++                                         VIR_HOST_VALIDATE_FAIL) < 0) {
+         ret = -1;
++    }
+ 
+ #if WITH_FUSE
+     if (virHostValidateDeviceExists("LXC", "/sys/fs/fuse/connections",
+diff --git a/tools/virt-host-validate-qemu.c b/tools/virt-host-validate-qemu.c
+index d7573ea8b3..ff3c1f0231 100644
+--- a/tools/virt-host-validate-qemu.c
++++ b/tools/virt-host-validate-qemu.c
+@@ -26,6 +26,7 @@
+ #include "virt-host-validate-common.h"
+ #include "virarch.h"
+ #include "virbitmap.h"
++#include "vircgroup.h"
+ 
+ int virHostValidateQEMU(void)
+ {
+@@ -96,35 +97,16 @@ int virHostValidateQEMU(void)
+                                     _("Load the 'tun' module to enable networking for QEMU guests")) < 0)
+         ret = -1;
+ 
+-    if (virHostValidateCGroupController("QEMU", "memory",
+-                                        VIR_HOST_VALIDATE_WARN,
+-                                        "MEMCG") < 0)
+-        ret = -1;
+-
+-    if (virHostValidateCGroupController("QEMU", "cpu",
+-                                        VIR_HOST_VALIDATE_WARN,
+-                                        "CGROUP_CPU") < 0)
+-        ret = -1;
+-
+-    if (virHostValidateCGroupController("QEMU", "cpuacct",
+-                                        VIR_HOST_VALIDATE_WARN,
+-                                        "CGROUP_CPUACCT") < 0)
+-        ret = -1;
+-
+-    if (virHostValidateCGroupController("QEMU", "cpuset",
+-                                        VIR_HOST_VALIDATE_WARN,
+-                                        "CPUSETS") < 0)
+-        ret = -1;
+-
+-    if (virHostValidateCGroupController("QEMU", "devices",
+-                                        VIR_HOST_VALIDATE_WARN,
+-                                        "CGROUP_DEVICES") < 0)
+-        ret = -1;
+-
+-    if (virHostValidateCGroupController("QEMU", "blkio",
+-                                        VIR_HOST_VALIDATE_WARN,
+-                                        "BLK_CGROUP") < 0)
++    if (virHostValidateCGroupControllers("QEMU",
++                                         (1 << VIR_CGROUP_CONTROLLER_MEMORY) |
++                                         (1 << VIR_CGROUP_CONTROLLER_CPU) |
++                                         (1 << VIR_CGROUP_CONTROLLER_CPUACCT) |
++                                         (1 << VIR_CGROUP_CONTROLLER_CPUSET) |
++                                         (1 << VIR_CGROUP_CONTROLLER_DEVICES) |
++                                         (1 << VIR_CGROUP_CONTROLLER_BLKIO),
++                                         VIR_HOST_VALIDATE_WARN) < 0) {
+         ret = -1;
++    }
+ 
+     if (virHostValidateIOMMU("QEMU",
+                              VIR_HOST_VALIDATE_WARN) < 0)
+-- 
+2.22.0
+
diff --git a/SPECS/libvirt.spec b/SPECS/libvirt.spec
index 1b453db..fa6e7f7 100644
--- a/SPECS/libvirt.spec
+++ b/SPECS/libvirt.spec
@@ -69,9 +69,17 @@
 %else
     %define with_storage_sheepdog 0
 %endif
-%define with_storage_gluster 0%{!?_without_storage_gluster:1}
 %define with_numactl          0%{!?_without_numactl:1}
 
+%define with_storage_gluster 0%{!?_without_storage_gluster:1}
+%ifnarch %{qemu_kvm_arches}
+    # gluster is only built where qemu driver is enabled on RHEL 8
+    %if 0%{?rhel} >= 8
+        %define with_storage_gluster 0
+    %endif
+%endif
+
+
 # F25+ has zfs-fuse
 %if 0%{?fedora}
     %define with_storage_zfs      0%{!?_without_storage_zfs:1}
@@ -243,7 +251,7 @@
 Summary: Library providing a simple virtualization API
 Name: libvirt
 Version: 4.5.0
-Release: 24.3%{?dist}%{?extra_release}
+Release: 35%{?dist}%{?extra_release}
 License: LGPLv2+
 URL: https://libvirt.org/
 
@@ -448,17 +456,354 @@ Patch192: libvirt-util-remove-test-code-accidentally-committed-to-virFirewallDZo
 Patch193: libvirt-qemu-command-Don-t-skip-readonly-and-throttling-info-for-empty-drive.patch
 Patch194: libvirt-util-fix-memory-leak-in-virFirewallDInterfaceSetZone.patch
 Patch195: libvirt-network-explicitly-allow-icmp-icmpv6-in-libvirt-zonefile.patch
-Patch196: libvirt-cpu_x86-Do-not-cache-microcode-version.patch
-Patch197: libvirt-qemu-Don-t-cache-microcode-version.patch
-Patch198: libvirt-cputest-Add-data-for-Intel-R-Xeon-R-CPU-E3-1225-v5.patch
-Patch199: libvirt-cpu_map-Define-md-clear-CPUID-bit.patch
-Patch200: libvirt-admin-reject-clients-unless-their-UID-matches-the-current-UID.patch
-Patch201: libvirt-locking-restrict-sockets-to-mode-0600.patch
-Patch202: libvirt-logging-restrict-sockets-to-mode-0600.patch
-Patch203: libvirt-api-disallow-virDomainSaveImageGetXMLDesc-on-read-only-connections.patch
-Patch204: libvirt-api-disallow-virDomainManagedSaveDefineXML-on-read-only-connections.patch
-Patch205: libvirt-api-disallow-virConnectGetDomainCapabilities-on-read-only-connections.patch
-Patch206: libvirt-api-disallow-virConnect-HypervisorCPU-on-read-only-connections.patch
+Patch196: libvirt-tests-qemuxml2argv-add-CAPS_ARCH_LATEST-macro.patch
+Patch197: libvirt-qemu-Add-ccw-support-for-vhost-vsock.patch
+Patch198: libvirt-qemu-Allow-creating-ppc64-guests-with-graphics-and-no-USB-mouse.patch
+Patch199: libvirt-conf-Expose-virDomainSCSIDriveAddressIsUsed.patch
+Patch200: libvirt-qemuhotplugtest-Don-t-plug-a-SCSI-disk-at-unit-7.patch
+Patch201: libvirt-qemu_hotplug-Check-for-duplicate-drive-addresses.patch
+Patch202: libvirt-cpu_map-Add-support-for-cldemote-CPU-feature.patch
+Patch203: libvirt-util-alloc-add-macros-for-implementing-automatic-cleanup-functionality.patch
+Patch204: libvirt-qemu-domain-Simplify-non-VFIO-memLockLimit-calculation-for-PPC64.patch
+Patch205: libvirt-qemu_domain-add-a-PPC64-memLockLimit-helper.patch
+Patch206: libvirt-qemu_domain-NVLink2-bridge-detection-function-for-PPC64.patch
+Patch207: libvirt-PPC64-support-for-NVIDIA-V100-GPU-with-NVLink2-passthrough.patch
+Patch208: libvirt-cpu_x86-Do-not-cache-microcode-version.patch
+Patch209: libvirt-qemu-Don-t-cache-microcode-version.patch
+Patch210: libvirt-cputest-Add-data-for-Intel-R-Xeon-R-CPU-E3-1225-v5.patch
+Patch211: libvirt-cpu_map-Define-md-clear-CPUID-bit.patch
+Patch212: libvirt-admin-reject-clients-unless-their-UID-matches-the-current-UID.patch
+Patch213: libvirt-locking-restrict-sockets-to-mode-0600.patch
+Patch214: libvirt-logging-restrict-sockets-to-mode-0600.patch
+Patch215: libvirt-util-skip-RDMA-detection-for-non-PCI-network-devices.patch
+Patch216: libvirt-virfile-Detect-ceph-as-shared-FS.patch
+Patch217: libvirt-virfile-added-GPFS-as-shared-fs.patch
+Patch218: libvirt-util-bitmap-define-cleanup-function-using-VIR_DEFINE_AUTOPTR_FUNC.patch
+Patch219: libvirt-qemu-Rework-setting-process-affinity.patch
+Patch220: libvirt-qemu-Set-up-EMULATOR-thread-and-cpuset.mems-before-exec-ing-qemu.patch
+Patch221: libvirt-conf-Add-definitions-for-uid-and-fid-PCI-address-attributes.patch
+Patch222: libvirt-qemu-Introduce-zPCI-capability.patch
+Patch223: libvirt-qemu-Enable-PCI-multi-bus-for-S390-guests.patch
+Patch224: libvirt-conf-Introduce-extension-flag-and-zPCI-member-for-PCI-address.patch
+Patch225: libvirt-conf-Introduce-address-caching-for-PCI-extensions.patch
+Patch226: libvirt-qemu-Auto-add-pci-root-for-s390-s390x-guests.patch
+Patch227: libvirt-conf-use-virXMLFormatElement-in-virDomainDeviceInfoFormat.patch
+Patch228: libvirt-conf-Introduce-parser-formatter-for-uid-and-fid.patch
+Patch229: libvirt-qemu-Add-zPCI-address-definition-check.patch
+Patch230: libvirt-conf-Allocate-release-uid-and-fid-in-PCI-address.patch
+Patch231: libvirt-qemu-Generate-and-use-zPCI-device-in-QEMU-command-line.patch
+Patch232: libvirt-qemu-Add-hotpluging-support-for-PCI-devices-on-S390-guests.patch
+Patch233: libvirt-qemuDomainRemoveRNGDevice-Remove-associated-chardev-too.patch
+Patch234: libvirt-qemu_hotplug-remove-erroneous-call-to-qemuDomainDetachExtensionDevice.patch
+Patch235: libvirt-qemu_hotplug-remove-another-erroneous-qemuDomainDetachExtensionDevice-call.patch
+Patch236: libvirt-util-Propagate-numad-failures-correctly.patch
+Patch237: libvirt-util-Introduce-virBitmapUnion.patch
+Patch238: libvirt-util-Introduce-virNumaNodesetToCPUset.patch
+Patch239: libvirt-qemu-Fix-qemuProcessInitCpuAffinity.patch
+Patch240: libvirt-qemu-Fix-leak-in-qemuProcessInitCpuAffinity.patch
+Patch241: libvirt-qemu-Drop-cleanup-label-from-qemuProcessInitCpuAffinity.patch
+Patch242: libvirt-qemu-Fix-NULL-pointer-access-in-qemuProcessInitCpuAffinity.patch
+Patch243: libvirt-qemuBuildMemoryBackendProps-Pass-priv-instead-of-its-individual-members.patch
+Patch244: libvirt-qemu-Don-t-use-mem-prealloc-among-with-.prealloc-yes.patch
+Patch245: libvirt-nwfilter-fix-adding-std-MAC-and-IP-values-to-filter-binding.patch
+Patch246: libvirt-qemuProcessBuildDestroyMemoryPathsImpl-Don-t-overwrite-error.patch
+Patch247: libvirt-qemu_security-Fully-implement-qemuSecurityDomainSetPathLabel.patch
+Patch248: libvirt-qemu-process-SEV-Assume-libDir-to-be-the-directory-to-create-files-in.patch
+Patch249: libvirt-qemu-process-SEV-Relabel-guest-owner-s-SEV-files-created-before-start.patch
+Patch250: libvirt-api-disallow-virDomainSaveImageGetXMLDesc-on-read-only-connections.patch
+Patch251: libvirt-api-disallow-virDomainManagedSaveDefineXML-on-read-only-connections.patch
+Patch252: libvirt-api-disallow-virConnectGetDomainCapabilities-on-read-only-connections.patch
+Patch253: libvirt-api-disallow-virConnect-HypervisorCPU-on-read-only-connections.patch
+Patch254: libvirt-rpc-virnetlibsshsession-update-deprecated-functions.patch
+Patch255: libvirt-cpu-allow-include-files-for-CPU-definition.patch
+Patch256: libvirt-cpu-fix-cleanup-when-signature-parsing-fails.patch
+Patch257: libvirt-cpu-push-more-parsing-logic-into-common-code.patch
+Patch258: libvirt-cpu-simplify-failure-cleanup-paths.patch
+Patch259: libvirt-cpu_map-Add-support-for-arch-capabilities-feature.patch
+Patch260: libvirt-cputest-Add-data-for-Intel-R-Xeon-R-CPU-E5-2630-v4.patch
+Patch261: libvirt-cputest-Add-data-for-Intel-R-Core-TM-i7-7600U.patch
+Patch262: libvirt-cputest-Add-data-for-Intel-R-Xeon-R-CPU-E7540.patch
+Patch263: libvirt-cputest-Add-data-for-Intel-R-Xeon-R-CPU-E5-2650.patch
+Patch264: libvirt-cputest-Add-data-for-Intel-R-Core-TM-i7-8700.patch
+Patch265: libvirt-cpu_x86-Separate-ancestor-model-parsing-from-x86ModelParse.patch
+Patch266: libvirt-cpu_x86-Separate-signature-parsing-from-x86ModelParse.patch
+Patch267: libvirt-cpu_x86-Separate-vendor-parsing-from-x86ModelParse.patch
+Patch268: libvirt-cpu_x86-Separate-feature-list-parsing-from-x86ModelParse.patch
+Patch269: libvirt-cpu_x86-Make-sure-CPU-model-names-are-unique-in-cpu_map.patch
+Patch270: libvirt-cpu_x86-Add-x86ModelCopySignatures-helper.patch
+Patch271: libvirt-cpu_x86-Store-CPU-signature-in-an-array.patch
+Patch272: libvirt-cpu_x86-Allow-multiple-signatures-for-a-CPU-model.patch
+Patch273: libvirt-cpu_x86-Log-decoded-CPU-model-and-signatures.patch
+Patch274: libvirt-qemu_capabilities-Inroduce-virQEMUCapsGetCPUModelX86Data.patch
+Patch275: libvirt-qemu_capabilities-Introduce-virQEMUCapsGetCPUModelInfo.patch
+Patch276: libvirt-qemu_capabilities-Use-virQEMUCapsGetCPUModelInfo.patch
+Patch277: libvirt-cpu_x86-Add-virCPUx86DataGetSignature-for-tests.patch
+Patch278: libvirt-cpu_map-Add-hex-representation-of-signatures.patch
+Patch279: libvirt-cputest-Test-CPU-signatures.patch
+Patch280: libvirt-cpu_map-Add-more-signatures-for-Conroe-CPU-model.patch
+Patch281: libvirt-cpu_map-Add-more-signatures-for-Penryn-CPU-model.patch
+Patch282: libvirt-cpu_map-Add-more-signatures-for-Nehalem-CPU-models.patch
+Patch283: libvirt-cpu_map-Add-more-signatures-for-Westmere-CPU-model.patch
+Patch284: libvirt-cpu_map-Add-more-signatures-for-SandyBridge-CPU-models.patch
+Patch285: libvirt-cpu_map-Add-more-signatures-for-IvyBridge-CPU-models.patch
+Patch286: libvirt-cpu_map-Add-more-signatures-for-Haswell-CPU-models.patch
+Patch287: libvirt-cpu_map-Add-more-signatures-for-Broadwell-CPU-models.patch
+Patch288: libvirt-cpu_map-Add-more-signatures-for-Skylake-Client-CPU-models.patch
+Patch289: libvirt-cpu-Don-t-access-invalid-memory-in-virCPUx86Translate.patch
+Patch290: libvirt-cpu_x86-Require-cpuid-within-feature-in-CPU-map.patch
+Patch291: libvirt-cputest-Add-data-for-Intel-R-Xeon-R-Platinum-8268-CPU.patch
+Patch292: libvirt-cpu_map-Add-Cascadelake-Server-CPU-model.patch
+Patch293: libvirt-cpu_x86-Introduce-virCPUx86DataItem-container-struct.patch
+Patch294: libvirt-cpu_x86-Rename-virCPUx86Vendor.cpuid.patch
+Patch295: libvirt-cpu_x86-Rename-virCPUx86DataItem-variables.patch
+Patch296: libvirt-cpu_x86-Rename-x86DataCpuidNext-function.patch
+Patch297: libvirt-cpu_x86-Rename-x86DataCpuid.patch
+Patch298: libvirt-cpu_x86-Rename-virCPUx86CPUIDSorter.patch
+Patch299: libvirt-cpu_x86-Rename-virCPUx86DataAddCPUIDInt.patch
+Patch300: libvirt-cpu_x86-Rename-virCPUx86DataAddCPUID.patch
+Patch301: libvirt-cpu_x86-Rename-virCPUx86VendorToCPUID.patch
+Patch302: libvirt-cpu_x86-Simplify-x86DataAdd.patch
+Patch303: libvirt-cpu_x86-Introduce-virCPUx86DataCmp.patch
+Patch304: libvirt-cpu_x86-Make-x86cpuidSetBits-more-general.patch
+Patch305: libvirt-cpu_x86-Make-x86cpuidClearBits-more-general.patch
+Patch306: libvirt-cpu_x86-Make-x86cpuidAndBits-more-general.patch
+Patch307: libvirt-cpu_x86-Make-x86cpuidMatchMasked-more-general.patch
+Patch308: libvirt-cpu_x86-Make-x86cpuidMatch-more-general.patch
+Patch309: libvirt-cpu_x86-Store-virCPUx86DataItem-content-in-union.patch
+Patch310: libvirt-cpu_x86-Add-support-for-storing-MSR-features-in-CPU-map.patch
+Patch311: libvirt-cpu_x86-Move-CheckFeature-functions.patch
+Patch312: libvirt-cputest-Add-support-for-MSR-features-to-cpu-parse.sh.patch
+Patch313: libvirt-util-file-introduce-VIR_AUTOCLOSE-macro-to-close-fd-of-the-file-automatically.patch
+Patch314: libvirt-vircpuhost-Add-support-for-reading-MSRs.patch
+Patch315: libvirt-virhostcpu-Make-virHostCPUGetMSR-work-only-on-x86.patch
+Patch316: libvirt-cpu_x86-Fix-placement-of-CheckFeature-functions.patch
+Patch317: libvirt-cpu_conf-Introduce-virCPUDefFilterFeatures.patch
+Patch318: libvirt-qemu_command-Use-consistent-syntax-for-CPU-features.patch
+Patch319: libvirt-tests-Add-QEMU-caps-data-for-future-4.1.0.patch
+Patch320: libvirt-tests-Add-domain-capabilities-case-for-QEMU-4.1.0.patch
+Patch321: libvirt-qemuxml2argvtest-Add-test-for-CPU-features-translation.patch
+Patch322: libvirt-qemu-Add-APIs-for-translating-CPU-features.patch
+Patch323: libvirt-qemu-Probe-for-max-x86_64-cpu-type.patch
+Patch324: libvirt-qemu-Probe-for-unavailable-features-CPU-property.patch
+Patch325: libvirt-qemu-Probe-host-CPU-after-capabilities.patch
+Patch326: libvirt-qemu_command-Use-canonical-names-of-CPU-features.patch
+Patch327: libvirt-qemu-Translate-feature-names-from-query-cpu-model-expansion.patch
+Patch328: libvirt-qemu-Don-t-use-full-CPU-model-expansion.patch
+Patch329: libvirt-qemu-Make-qemuMonitorGetGuestCPU-usable-on-x86-only.patch
+Patch330: libvirt-cpu-Introduce-virCPUDataAddFeature.patch
+Patch331: libvirt-qemu-Add-type-filter-to-qemuMonitorJSONParsePropsList.patch
+Patch332: libvirt-util-string-Introduce-macro-for-automatic-string-lists.patch
+Patch333: libvirt-util-json-define-cleanup-function-using-VIR_DEFINE_AUTOPTR_FUNC.patch
+Patch334: libvirt-qemu-Introduce-generic-qemuMonitorGetGuestCPU.patch
+Patch335: libvirt-qemu_process-Prefer-generic-qemuMonitorGetGuestCPU.patch
+Patch336: libvirt-util-Rework-virStringListAdd.patch
+Patch337: libvirt-conf-Introduce-virCPUDefCheckFeatures.patch
+Patch338: libvirt-cpu_x86-Turn-virCPUx86DataIteratorInit-into-a-function.patch
+Patch339: libvirt-cpu_x86-Introduce-virCPUx86FeatureFilter-MSR.patch
+Patch340: libvirt-cpu_x86-Read-CPU-features-from-IA32_ARCH_CAPABILITIES-MSR.patch
+Patch341: libvirt-cpu_map-Introduce-IA32_ARCH_CAPABILITIES-MSR-features.patch
+Patch342: libvirt-qemu-Forbid-MSR-features-with-old-QEMU.patch
+Patch343: libvirt-qemu-Drop-MSR-features-from-host-model-with-old-QEMU.patch
+Patch344: libvirt-cpu_x86-Fix-memory-leak-virCPUx86GetHost.patch
+Patch345: libvirt-qemu-Use-tmpChr-in-qemuDomainDetachChrDevice-to-build-device-string.patch
+Patch346: libvirt-qemu-Drop-user-prefix-for-guestfwd-netdev.patch
+Patch347: libvirt-qemu_hotplug-Attach-guestfwd-using-netdev_add.patch
+Patch348: libvirt-qemu_hotplug-Detach-guestfwd-using-netdev_del.patch
+Patch349: libvirt-qemuhotplugtest-Test-guestfwd-attach-and-detach.patch
+Patch350: libvirt-daemon-Register-secret-driver-before-storage-driver.patch
+Patch351: libvirt-bhyve-Move-autostarting-of-domains-into-bhyveStateInitialize.patch
+Patch352: libvirt-Revert-virStateDriver-Separate-AutoStart-from-Initialize.patch
+Patch353: libvirt-Revert-Separate-out-StateAutoStart-from-StateInitialize.patch
+Patch354: libvirt-util-moving-type-argument-to-avoid-issues-with-mount-syscall.patch
+Patch355: libvirt-util-cgroup-use-VIR_AUTOFREE-instead-of-VIR_FREE-for-scalar-types.patch
+Patch356: libvirt-vircgroup-Rename-structs-to-start-with-underscore.patch
+Patch357: libvirt-vircgroup-Introduce-standard-set-of-typedefs-and-use-them.patch
+Patch358: libvirt-vircgroup-Extract-file-link-resolving-into-separate-function.patch
+Patch359: libvirt-vircgroup-Remove-unused-function-virCgroupKill.patch
+Patch360: libvirt-vircgroup-Unexport-unused-function-virCgroupAddTaskController.patch
+Patch361: libvirt-vircgroup-Unexport-unused-function-virCgroupRemoveRecursively.patch
+Patch362: libvirt-vircgroup-Move-function-used-in-tests-into-vircgrouppriv.h.patch
+Patch363: libvirt-vircgroup-Remove-pointless-bool-parameter.patch
+Patch364: libvirt-vircgroup-Extract-mount-options-matching-into-function.patch
+Patch365: libvirt-vircgroup-Use-virCgroupMountOptsMatchController-in-virCgroupDetectPlacement.patch
+Patch366: libvirt-vircgroup-Introduce-virCgroupEnableMissingControllers.patch
+Patch367: libvirt-vircgroup-machinename-will-never-be-NULL.patch
+Patch368: libvirt-vircgroup-Remove-virCgroupAddTaskController.patch
+Patch369: libvirt-vircgroup-Introduce-virCgroupGetMemoryStat.patch
+Patch370: libvirt-lxc-Use-virCgroupGetMemoryStat.patch
+Patch371: libvirt-vircgroup-fix-MinGW-build.patch
+Patch372: libvirt-vircgroup-Duplicate-string-before-modifying.patch
+Patch373: libvirt-vircgroup-Extract-controller-detection-into-function.patch
+Patch374: libvirt-vircgroup-Extract-placement-validation-into-function.patch
+Patch375: libvirt-vircgroup-Split-virCgroupPathOfController-into-two-functions.patch
+Patch376: libvirt-vircgroup-Call-virCgroupRemove-inside-virCgroupMakeGroup.patch
+Patch377: libvirt-vircgroup-Simplify-if-conditions-in-virCgroupMakeGroup.patch
+Patch378: libvirt-vircgroup-Remove-obsolete-sa_assert.patch
+Patch379: libvirt-tests-Resolve-possible-overrun.patch
+Patch380: libvirt-vircgroup-cleanup-controllers-not-managed-by-systemd-on-error.patch
+Patch381: libvirt-vircgroup-fix-bug-in-virCgroupEnableMissingControllers.patch
+Patch382: libvirt-vircgroup-rename-virCgroupAdd.-Task-to-virCgroupAdd.-Process.patch
+Patch383: libvirt-vircgroup-introduce-virCgroupTaskFlags.patch
+Patch384: libvirt-vircgroup-introduce-virCgroupAddThread.patch
+Patch385: libvirt-vircgroupmock-cleanup-unused-cgroup-files.patch
+Patch386: libvirt-vircgroupmock-rewrite-cgroup-fopen-mocking.patch
+Patch387: libvirt-vircgrouptest-call-virCgroupDetectMounts-directly.patch
+Patch388: libvirt-vircgrouptest-call-virCgroupNewSelf-instead-virCgroupDetectMounts.patch
+Patch389: libvirt-util-introduce-vircgroupbackend-files.patch
+Patch390: libvirt-vircgroup-introduce-cgroup-v1-backend-files.patch
+Patch391: libvirt-vircgroup-extract-virCgroupV1Available.patch
+Patch392: libvirt-vircgroup-detect-available-backend-for-cgroup.patch
+Patch393: libvirt-vircgroup-extract-virCgroupV1ValidateMachineGroup.patch
+Patch394: libvirt-vircgroup-extract-virCgroupV1CopyMounts.patch
+Patch395: libvirt-vircgroup-extract-v1-detect-functions.patch
+Patch396: libvirt-vircgroup-extract-virCgroupV1CopyPlacement.patch
+Patch397: libvirt-vircgroup-extract-virCgroupV1ValidatePlacement.patch
+Patch398: libvirt-vircgroup-extract-virCgroupV1StealPlacement.patch
+Patch399: libvirt-vircgroup-extract-virCgroupV1DetectControllers.patch
+Patch400: libvirt-vircgroup-extract-virCgroupV1HasController.patch
+Patch401: libvirt-vircgroup-extract-virCgroupV1GetAnyController.patch
+Patch402: libvirt-vircgroup-extract-virCgroupV1PathOfController.patch
+Patch403: libvirt-vircgroup-extract-virCgroupV1MakeGroup.patch
+Patch404: libvirt-vircgroup-extract-virCgroupV1Remove.patch
+Patch405: libvirt-vircgroup-extract-virCgroupV1AddTask.patch
+Patch406: libvirt-vircgroup-extract-virCgroupV1HasEmptyTasks.patch
+Patch407: libvirt-vircgroup-extract-virCgroupV1BindMount.patch
+Patch408: libvirt-vircgroup-extract-virCgroupV1SetOwner.patch
+Patch409: libvirt-vircgroup-extract-virCgroupV1-Set-Get-BlkioWeight.patch
+Patch410: libvirt-vircgroup-extract-virCgroupV1GetBlkioIoServiced.patch
+Patch411: libvirt-vircgroup-extract-virCgroupV1GetBlkioIoDeviceServiced.patch
+Patch412: libvirt-vircgroup-extract-virCgroupV1-Set-Get-BlkioDeviceWeight.patch
+Patch413: libvirt-vircgroup-extract-virCgroupV1-Set-Get-BlkioDeviceReadIops.patch
+Patch414: libvirt-vircgroup-extract-virCgroupV1-Set-Get-BlkioDeviceWriteIops.patch
+Patch415: libvirt-vircgroup-extract-virCgroupV1-Set-Get-BlkioDeviceReadBps.patch
+Patch416: libvirt-vircgroup-extract-virCgroupV1-Set-Get-BlkioDeviceWriteBps.patch
+Patch417: libvirt-vircgroup-extract-virCgroupV1SetMemory.patch
+Patch418: libvirt-vircgroup-extract-virCgroupV1GetMemoryStat.patch
+Patch419: libvirt-vircgroup-extract-virCgroupV1GetMemoryUsage.patch
+Patch420: libvirt-vircgroup-extract-virCgroupV1-Set-Get-Memory-Limit.patch
+Patch421: libvirt-vircgroup-extract-virCgroupV1GetMemSwapUsage.patch
+Patch422: libvirt-vircgroup-extract-virCgroupV1-Allow-Deny-Device.patch
+Patch423: libvirt-vircgroup-extract-virCgroupV1-Allow-Deny-AllDevices.patch
+Patch424: libvirt-vircgroup-extract-virCgroupV1-Set-Get-CpuShares.patch
+Patch425: libvirt-vircgroup-extract-virCgroupV1-Set-Get-CpuCfsPeriod.patch
+Patch426: libvirt-vircgroup-extract-virCgroupV1-Set-Get-CpuCfsQuota.patch
+Patch427: libvirt-vircgroup-extract-virCgroupV1SupportsCpuBW.patch
+Patch428: libvirt-vircgroup-extract-virCgroupV1GetCpuacct-Usage.patch
+Patch429: libvirt-vircgroup-extract-virCgroupV1GetCpuacctStat.patch
+Patch430: libvirt-vircgroup-extract-virCgroupV1-Set-Get-FreezerState.patch
+Patch431: libvirt-vircgroup-extract-virCgroupV1-Set-Get-CpusetMems.patch
+Patch432: libvirt-vircgroup-extract-virCgroupV1-Set-Get-CpusetMemoryMigrate.patch
+Patch433: libvirt-vircgroup-extract-virCgroupV1-Set-Get-CpusetCpus.patch
+Patch434: libvirt-vircgroup-rename-virCgroupController-into-virCgroupV1Controller.patch
+Patch435: libvirt-vircgroup-rename-controllers-to-legacy.patch
+Patch436: libvirt-vircgroup-remove-VIR_CGROUP_SUPPORTED.patch
+Patch437: libvirt-vircgroup-include-system-headers-only-on-linux.patch
+Patch438: libvirt-vircgroupv1-fix-build-on-non-linux-OSes.patch
+Patch439: libvirt-Revert-vircgroup-cleanup-controllers-not-managed-by-systemd-on-error.patch
+Patch440: libvirt-util-introduce-cgroup-v2-files.patch
+Patch441: libvirt-vircgroup-introduce-virCgroupV2Available.patch
+Patch442: libvirt-vircgroup-introduce-virCgroupV2ValidateMachineGroup.patch
+Patch443: libvirt-vircgroup-introduce-virCgroupV2CopyMounts.patch
+Patch444: libvirt-vircgroup-introduce-virCgroupV2CopyPlacement.patch
+Patch445: libvirt-vircgroup-introduce-virCgroupV2DetectMounts.patch
+Patch446: libvirt-vircgroup-introduce-virCgroupV2DetectPlacement.patch
+Patch447: libvirt-vircgroup-introduce-virCgroupV2ValidatePlacement.patch
+Patch448: libvirt-vircgroup-introduce-virCgroupV2StealPlacement.patch
+Patch449: libvirt-vircgroup-introduce-virCgroupV2DetectControllers.patch
+Patch450: libvirt-vircgroup-introduce-virCgroupV2HasController.patch
+Patch451: libvirt-vircgroup-introduce-virCgroupV2GetAnyController.patch
+Patch452: libvirt-vircgroup-introduce-virCgroupV2PathOfController.patch
+Patch453: libvirt-vircgroup-introduce-virCgroupV2MakeGroup.patch
+Patch454: libvirt-vircgroup-introduce-virCgroupV2Remove.patch
+Patch455: libvirt-vircgroup-introduce-virCgroupV2AddTask.patch
+Patch456: libvirt-vircgroup-introduce-virCgroupV2HasEmptyTasks.patch
+Patch457: libvirt-vircgroup-introduce-virCgroupV2BindMount.patch
+Patch458: libvirt-vircgroup-introduce-virCgroupV2SetOwner.patch
+Patch459: libvirt-vircgroup-introduce-virCgroupV2-Set-Get-BlkioWeight.patch
+Patch460: libvirt-vircgroup-introduce-virCgroupV2GetBlkioIoServiced.patch
+Patch461: libvirt-vircgroup-introduce-virCgroupV2GetBlkioIoDeviceServiced.patch
+Patch462: libvirt-vircgroup-introduce-virCgroupV2-Set-Get-BlkioDeviceWeight.patch
+Patch463: libvirt-vircgroup-introduce-virCgroupV2-Set-Get-BlkioDeviceReadIops.patch
+Patch464: libvirt-vircgroup-introduce-virCgroupV2-Set-Get-BlkioDeviceWriteIops.patch
+Patch465: libvirt-vircgroup-introduce-virCgroupV2-Set-Get-BlkioDeviceReadBps.patch
+Patch466: libvirt-vircgroup-introduce-virCgroupV2-Set-Get-BlkioDeviceWriteBps.patch
+Patch467: libvirt-vircgroup-introduce-virCgroupV2SetMemory.patch
+Patch468: libvirt-vircgroup-introduce-virCgroupV2GetMemoryStat.patch
+Patch469: libvirt-vircgroup-introduce-virCgroupV2GetMemoryUsage.patch
+Patch470: libvirt-vircgroup-introduce-virCgroupV2-Set-Get-MemoryHardLimit.patch
+Patch471: libvirt-vircgroup-introduce-virCgroupV2-Set-Get-MemorySoftLimit.patch
+Patch472: libvirt-vircgroup-introduce-virCgroupV2-Set-Get-MemSwapHardLimit.patch
+Patch473: libvirt-vircgroup-introduce-virCgroupV2GetMemSwapUsage.patch
+Patch474: libvirt-vircgroup-introduce-virCgroupV2-Set-Get-CpuShares.patch
+Patch475: libvirt-vircgroup-introduce-virCgroupV2-Set-Get-CpuCfsPeriod.patch
+Patch476: libvirt-vircgroup-introduce-virCgroupV2-Set-Get-CpuCfsQuota.patch
+Patch477: libvirt-vircgroup-introduce-virCgroupV2SupportsCpuBW.patch
+Patch478: libvirt-vircgroup-introduce-virCgroupV2GetCpuacctUsage.patch
+Patch479: libvirt-vircgroup-introduce-virCgroupV2GetCpuacctStat.patch
+Patch480: libvirt-vircgroup-register-cgroup-v2-backend.patch
+Patch481: libvirt-vircgroup-add-support-for-hybrid-configuration.patch
+Patch482: libvirt-vircgroupmock-change-cgroup-prefix.patch
+Patch483: libvirt-vircgroupmock-add-support-to-test-cgroup-v2.patch
+Patch484: libvirt-vircgrouptest-introduce-initFakeFS-and-cleanupFakeFS-helpers.patch
+Patch485: libvirt-vircgrouptest-prepare-testCgroupDetectMounts-for-cgroup-v2.patch
+Patch486: libvirt-vircgrouptest-add-detect-mounts-test-for-cgroup-v2.patch
+Patch487: libvirt-vircgrouptest-add-detect-mounts-test-for-hybrid-cgroups.patch
+Patch488: libvirt-vircgrouptest-prepare-validateCgroup-for-cgroupv2.patch
+Patch489: libvirt-vircgrouptest-add-cgroup-v2-tests.patch
+Patch490: libvirt-vircgrouptest-add-hybrid-tests.patch
+Patch491: libvirt-virt-host-validate-rewrite-cgroup-detection-to-use-util-vircgroup.patch
+Patch492: libvirt-virt-host-validate-require-freezer-for-LXC.patch
+Patch493: libvirt-virt-host-validate-Fix-build-on-non-Linux.patch
+Patch494: libvirt-tests-Use-correct-function-name-in-error-path.patch
+Patch495: libvirt-util-Fix-virCgroupGetMemoryStat.patch
+Patch496: libvirt-tests-Augment-vcgrouptest-to-add-virCgroupGetMemoryStat.patch
+Patch497: libvirt-vircgroup-introduce-virCgroupKillRecursiveCB.patch
+Patch498: libvirt-vircgroupv2-fix-virCgroupV2ValidateMachineGroup.patch
+Patch499: libvirt-util-implement-virCgroupV2-Set-Get-CpusetMems.patch
+Patch500: libvirt-util-implement-virCgroupV2-Set-Get-CpusetMemoryMigrate.patch
+Patch501: libvirt-util-implement-virCgroupV2-Set-Get-CpusetCpus.patch
+Patch502: libvirt-util-enable-cgroups-v2-cpuset-controller-for-threads.patch
+Patch503: libvirt-util-vircgroup-pass-parent-cgroup-into-virCgroupDetectControllersCB.patch
+Patch504: libvirt-internal-introduce-a-family-of-NULLSTR-macros.patch
+Patch505: libvirt-util-vircgroup-improve-controller-detection.patch
+Patch506: libvirt-util-vircgroupv2-use-any-controller-to-create-thread-directory.patch
+Patch507: libvirt-util-vircgroupv2-enable-CPU-controller-only-if-it-s-available.patch
+Patch508: libvirt-util-vircgroupv2-separate-return-values-of-virCgroupV2EnableController.patch
+Patch509: libvirt-util-vircgroupv2-don-t-error-out-if-enabling-controller-fails.patch
+Patch510: libvirt-util-vircgroupv2-mark-only-requested-controllers-as-available.patch
+Patch511: libvirt-Revert-util-vircgroup-pass-parent-cgroup-into-virCgroupDetectControllersCB.patch
+Patch512: libvirt-util-vircgroupv2-stop-enabling-missing-controllers-with-systemd.patch
+Patch513: libvirt-virWaitForDevices-Drop-confusing-part-of-comment.patch
+Patch514: libvirt-lib-Drop-UDEVSETTLE.patch
+Patch515: libvirt-m4-Provide-default-value-fore-UDEVADM.patch
+Patch516: libvirt-m4-Drop-needless-string-checks.patch
+Patch517: libvirt-util-vircgroup-introduce-virCgroup-Get-Set-ValueRaw.patch
+Patch518: libvirt-util-vircgroup-move-virCgroupGetValueStr-out-of-virCgroupGetValueForBlkDev.patch
+Patch519: libvirt-util-vircgroupv1-add-support-for-BFQ-blkio-files.patch
+Patch520: libvirt-util-vircgroupv2-add-support-for-BFQ-files.patch
+Patch521: libvirt-Handle-copying-bitmaps-to-larger-data-buffers.patch
+Patch522: libvirt-virDomainObjListAddLocked-fix-double-free.patch
+Patch523: libvirt-docs-schemas-Decouple-the-virtio-options-from-each-other.patch
+Patch524: libvirt-util-command-use-VIR_AUTOFREE-instead-of-VIR_FREE-for-scalar-types.patch
+Patch525: libvirt-util-command-define-cleanup-function-using-VIR_DEFINE_AUTOPTR_FUNC.patch
+Patch526: libvirt-util-netdevopenvswitch-use-VIR_AUTOFREE-instead-of-VIR_FREE-for-scalar-types.patch
+Patch527: libvirt-util-virnetdevopenvswitch-Drop-an-unused-variable-ovs_timeout.patch
+Patch528: libvirt-util-netdevopenvswitch-use-VIR_AUTOPTR-for-aggregate-types.patch
+Patch529: libvirt-util-suppress-unimportant-ovs-vsctl-errors-when-getting-interface-stats.patch
+Patch530: libvirt-virNetDevOpenvswitchInterfaceStats-Optimize-for-speed.patch
+Patch531: libvirt-test-Introduce-virnetdevopenvswitchtest.patch
+Patch532: libvirt-vircommand-Separate-mass-FD-closing-into-a-function.patch
+Patch533: libvirt-virCommand-use-procfs-to-learn-opened-FDs.patch
+Patch534: libvirt-util-command-Ignore-bitmap-errors-when-enumerating-file-descriptors-to-close.patch
+Patch535: libvirt-util-Avoid-possible-error-in-virCommandMassClose.patch
+Patch536: libvirt-vircgroup-fix-cgroups-v2-controllers-detection.patch
+Patch537: libvirt-vircgroupv2-store-enabled-controllers.patch
+Patch538: libvirt-virDomainObjListAddLocked-Produce-better-error-message-than-Duplicate-key.patch
+Patch539: libvirt-virdbus-Grab-a-ref-as-long-as-the-while-loop-is-executed.patch
+Patch540: libvirt-vircgroupv2-fix-parsing-multiple-values-in-single-file.patch
+Patch541: libvirt-vircgroupv2-fix-virCgroupV2GetCpuCfsQuota-for-max-value.patch
+Patch542: libvirt-vircgroupv2-fix-abort-in-VIR_AUTOFREE.patch
+Patch543: libvirt-vircgroupv2-fix-setting-cpu.max-period.patch
 
 Requires: libvirt-daemon = %{version}-%{release}
 Requires: libvirt-daemon-config-network = %{version}-%{release}
@@ -2370,27 +2715,381 @@ exit 0
 
 
 %changelog
-* Sun Jun 30 2019 Danilo de Paula <ddepaula@redhat.com> - 4.5.0-24.3
+* Mon Sep 16 2019 Jiri Denemark <jdenemar@redhat.com> - 4.5.0-35
+- vircgroupv2: fix setting cpu.max period (rhbz#1749227)
+
+* Wed Sep  4 2019 Jiri Denemark <jdenemar@redhat.com> - 4.5.0-34
+- vircgroupv2: fix abort in VIR_AUTOFREE (rhbz#1747440)
+
+* Mon Aug 26 2019 Jiri Denemark <jdenemar@redhat.com> - 4.5.0-33
+- vircgroupv2: fix parsing multiple values in single file (rhbz#1741825)
+- vircgroupv2: fix virCgroupV2GetCpuCfsQuota for "max" value (rhbz#1741837)
+
+* Mon Aug 19 2019 Jiri Denemark <jdenemar@redhat.com> - 4.5.0-32
+- virDomainObjListAddLocked: Produce better error message than 'Duplicate key' (rhbz#1737790)
+- virdbus: Grab a ref as long as the while loop is executed (rhbz#1741900)
+
+* Tue Jul 30 2019 Jiri Denemark <jdenemar@redhat.com> - 4.5.0-31
+- virDomainObjListAddLocked: fix double free (rhbz#1728530)
+- docs: schemas: Decouple the virtio options from each other (rhbz#1729675)
+- util: command: use VIR_AUTOFREE instead of VIR_FREE for scalar types (rhbz#1721434)
+- util: command: define cleanup function using VIR_DEFINE_AUTOPTR_FUNC (rhbz#1721434)
+- util: netdevopenvswitch: use VIR_AUTOFREE instead of VIR_FREE for scalar types (rhbz#1721434)
+- util: virnetdevopenvswitch: Drop an unused variable @ovs_timeout (rhbz#1721434)
+- util: netdevopenvswitch: use VIR_AUTOPTR for aggregate types (rhbz#1721434)
+- util: suppress unimportant ovs-vsctl errors when getting interface stats (rhbz#1721434)
+- virNetDevOpenvswitchInterfaceStats: Optimize for speed (rhbz#1721434)
+- test: Introduce virnetdevopenvswitchtest (rhbz#1721434)
+- vircommand: Separate mass FD closing into a function (rhbz#1721434)
+- virCommand: use procfs to learn opened FDs (rhbz#1721434)
+- util: command: Ignore bitmap errors when enumerating file descriptors to close (rhbz#1721434)
+- util: Avoid possible error in virCommandMassClose (rhbz#1721434)
+- vircgroup: fix cgroups v2 controllers detection (rhbz#1689297)
+- vircgroupv2: store enabled controllers (rhbz#1689297)
+
+* Wed Jul  3 2019 Jiri Denemark <jdenemar@redhat.com> - 4.5.0-30
+- virWaitForDevices: Drop confusing part of comment (rhbz#1710575)
+- lib: Drop UDEVSETTLE (rhbz#1710575)
+- m4: Provide default value fore UDEVADM (rhbz#1710575)
+- m4: Drop needless string checks (rhbz#1710575)
+- util: vircgroup: introduce virCgroup(Get|Set)ValueRaw (rhbz#1658890)
+- util: vircgroup: move virCgroupGetValueStr out of virCgroupGetValueForBlkDev (rhbz#1658890)
+- util: vircgroupv1: add support for BFQ blkio files (rhbz#1658890)
+- util: vircgroupv2: add support for BFQ files (rhbz#1658890)
+- Handle copying bitmaps to larger data buffers (rhbz#1703160)
+
+* Tue Jul  2 2019 Jiri Denemark <jdenemar@redhat.com> - 4.5.0-29
+- cpu: allow include files for CPU definition (rhbz#1686895)
+- cpu: fix cleanup when signature parsing fails (rhbz#1686895)
+- cpu: push more parsing logic into common code (rhbz#1686895)
+- cpu: simplify failure cleanup paths (rhbz#1686895)
+- cpu_map: Add support for arch-capabilities feature (rhbz#1693433)
+- cputest: Add data for Intel(R) Xeon(R) CPU E5-2630 v4 (rhbz#1686895)
+- cputest: Add data for Intel(R) Core(TM) i7-7600U (rhbz#1686895)
+- cputest: Add data for Intel(R) Xeon(R) CPU E7540 (rhbz#1686895)
+- cputest: Add data for Intel(R) Xeon(R) CPU E5-2650 (rhbz#1686895)
+- cputest: Add data for Intel(R) Core(TM) i7-8700 (rhbz#1686895)
+- cpu_x86: Separate ancestor model parsing from x86ModelParse (rhbz#1686895)
+- cpu_x86: Separate signature parsing from x86ModelParse (rhbz#1686895)
+- cpu_x86: Separate vendor parsing from x86ModelParse (rhbz#1686895)
+- cpu_x86: Separate feature list parsing from x86ModelParse (rhbz#1686895)
+- cpu_x86: Make sure CPU model names are unique in cpu_map (rhbz#1686895)
+- cpu_x86: Add x86ModelCopySignatures helper (rhbz#1686895)
+- cpu_x86: Store CPU signature in an array (rhbz#1686895)
+- cpu_x86: Allow multiple signatures for a CPU model (rhbz#1686895)
+- cpu_x86: Log decoded CPU model and signatures (rhbz#1686895)
+- qemu_capabilities: Inroduce virQEMUCapsGetCPUModelX86Data (rhbz#1686895)
+- qemu_capabilities: Introduce virQEMUCapsGetCPUModelInfo (rhbz#1686895)
+- qemu_capabilities: Use virQEMUCapsGetCPUModelInfo (rhbz#1686895)
+- cpu_x86: Add virCPUx86DataGetSignature for tests (rhbz#1686895)
+- cpu_map: Add hex representation of signatures (rhbz#1686895)
+- cputest: Test CPU signatures (rhbz#1686895)
+- cpu_map: Add more signatures for Conroe CPU model (rhbz#1686895)
+- cpu_map: Add more signatures for Penryn CPU model (rhbz#1686895)
+- cpu_map: Add more signatures for Nehalem CPU models (rhbz#1686895)
+- cpu_map: Add more signatures for Westmere CPU model (rhbz#1686895)
+- cpu_map: Add more signatures for SandyBridge CPU models (rhbz#1686895)
+- cpu_map: Add more signatures for IvyBridge CPU models (rhbz#1686895)
+- cpu_map: Add more signatures for Haswell CPU models (rhbz#1686895)
+- cpu_map: Add more signatures for Broadwell CPU models (rhbz#1686895)
+- cpu_map: Add more signatures for Skylake-Client CPU models (rhbz#1686895)
+- cpu: Don't access invalid memory in virCPUx86Translate (rhbz#1686895)
+- cpu_x86: Require <cpuid> within <feature> in CPU map (rhbz#1697627)
+- cputest: Add data for Intel(R) Xeon(R) Platinum 8268 CPU (rhbz#1693433)
+- cpu_map: Add Cascadelake-Server CPU model (rhbz#1693433)
+- cpu_x86: Introduce virCPUx86DataItem container struct (rhbz#1697627)
+- cpu_x86: Rename virCPUx86Vendor.cpuid (rhbz#1697627)
+- cpu_x86: Rename virCPUx86DataItem variables (rhbz#1697627)
+- cpu_x86: Rename x86DataCpuidNext function (rhbz#1697627)
+- cpu_x86: Rename x86DataCpuid (rhbz#1697627)
+- cpu_x86: Rename virCPUx86CPUIDSorter (rhbz#1697627)
+- cpu_x86: Rename virCPUx86DataAddCPUIDInt (rhbz#1697627)
+- cpu_x86: Rename virCPUx86DataAddCPUID (rhbz#1697627)
+- cpu_x86: Rename virCPUx86VendorToCPUID (rhbz#1697627)
+- cpu_x86: Simplify x86DataAdd (rhbz#1697627)
+- cpu_x86: Introduce virCPUx86DataCmp (rhbz#1697627)
+- cpu_x86: Make x86cpuidSetBits more general (rhbz#1697627)
+- cpu_x86: Make x86cpuidClearBits more general (rhbz#1697627)
+- cpu_x86: Make x86cpuidAndBits more general (rhbz#1697627)
+- cpu_x86: Make x86cpuidMatchMasked more general (rhbz#1697627)
+- cpu_x86: Make x86cpuidMatch more general (rhbz#1697627)
+- cpu_x86: Store virCPUx86DataItem content in union (rhbz#1697627)
+- cpu_x86: Add support for storing MSR features in CPU map (rhbz#1697627)
+- cpu_x86: Move *CheckFeature functions (rhbz#1697627)
+- cputest: Add support for MSR features to cpu-parse.sh (rhbz#1697627)
+- util: file: introduce VIR_AUTOCLOSE macro to close fd of the file automatically (rhbz#1697627)
+- vircpuhost: Add support for reading MSRs (rhbz#1697627)
+- virhostcpu: Make virHostCPUGetMSR() work only on x86 (rhbz#1697627)
+- cpu_x86: Fix placement of *CheckFeature functions (rhbz#1697627)
+- cpu_conf: Introduce virCPUDefFilterFeatures (rhbz#1697627)
+- qemu_command: Use consistent syntax for CPU features (rhbz#1697627)
+- tests: Add QEMU caps data for future 4.1.0 (rhbz#1697627)
+- tests: Add domain capabilities case for QEMU 4.1.0 (rhbz#1697627)
+- qemuxml2argvtest: Add test for CPU features translation (rhbz#1697627)
+- qemu: Add APIs for translating CPU features (rhbz#1697627)
+- qemu: Probe for max-x86_64-cpu type (rhbz#1697627)
+- qemu: Probe for "unavailable-features" CPU property (rhbz#1697627)
+- qemu: Probe host CPU after capabilities (rhbz#1697627)
+- qemu_command: Use canonical names of CPU features (rhbz#1697627)
+- qemu: Translate feature names from query-cpu-model-expansion (rhbz#1697627)
+- qemu: Don't use full CPU model expansion (rhbz#1697627)
+- qemu: Make qemuMonitorGetGuestCPU usable on x86 only (rhbz#1697627)
+- cpu: Introduce virCPUDataAddFeature (rhbz#1697627)
+- qemu: Add type filter to qemuMonitorJSONParsePropsList (rhbz#1697627)
+- util: string: Introduce macro for automatic string lists (rhbz#1697627)
+- util: json: define cleanup function using VIR_DEFINE_AUTOPTR_FUNC (rhbz#1697627)
+- qemu: Introduce generic qemuMonitorGetGuestCPU (rhbz#1697627)
+- qemu_process: Prefer generic qemuMonitorGetGuestCPU (rhbz#1697627)
+- util: Rework virStringListAdd (rhbz#1697627)
+- conf: Introduce virCPUDefCheckFeatures (rhbz#1697627)
+- cpu_x86: Turn virCPUx86DataIteratorInit into a function (rhbz#1697627)
+- cpu_x86: Introduce virCPUx86FeatureFilter*MSR (rhbz#1697627)
+- cpu_x86: Read CPU features from IA32_ARCH_CAPABILITIES MSR (rhbz#1697627)
+- cpu_map: Introduce IA32_ARCH_CAPABILITIES MSR features (rhbz#1697627)
+- qemu: Forbid MSR features with old QEMU (rhbz#1697627)
+- qemu: Drop MSR features from host-model with old QEMU (rhbz#1697627)
+- cpu_x86: Fix memory leak - virCPUx86GetHost (rhbz#1697627)
+- qemu: Use @tmpChr in qemuDomainDetachChrDevice to build device string (rhbz#1624204)
+- qemu: Drop "user-" prefix for guestfwd netdev (rhbz#1624204)
+- qemu_hotplug: Attach guestfwd using netdev_add (rhbz#1624204)
+- qemu_hotplug: Detach guestfwd using netdev_del (rhbz#1624204)
+- qemuhotplugtest: Test guestfwd attach and detach (rhbz#1624204)
+- daemon: Register secret driver before storage driver (rhbz#1685151)
+- bhyve: Move autostarting of domains into bhyveStateInitialize (rhbz#1685151)
+- Revert "virStateDriver - Separate AutoStart from Initialize" (rhbz#1685151)
+- Revert "Separate out StateAutoStart from StateInitialize" (rhbz#1685151)
+- util: moving 'type' argument to avoid issues with mount() syscall. (rhbz#1689297)
+- util: cgroup: use VIR_AUTOFREE instead of VIR_FREE for scalar types (rhbz#1689297)
+- vircgroup: Rename structs to start with underscore (rhbz#1689297)
+- vircgroup: Introduce standard set of typedefs and use them (rhbz#1689297)
+- vircgroup: Extract file link resolving into separate function (rhbz#1689297)
+- vircgroup: Remove unused function virCgroupKill() (rhbz#1689297)
+- vircgroup: Unexport unused function virCgroupAddTaskController() (rhbz#1689297)
+- vircgroup: Unexport unused function virCgroupRemoveRecursively (rhbz#1689297)
+- vircgroup: Move function used in tests into vircgrouppriv.h (rhbz#1689297)
+- vircgroup: Remove pointless bool parameter (rhbz#1689297)
+- vircgroup: Extract mount options matching into function (rhbz#1689297)
+- vircgroup: Use virCgroupMountOptsMatchController in virCgroupDetectPlacement (rhbz#1689297)
+- vircgroup: Introduce virCgroupEnableMissingControllers (rhbz#1689297)
+- vircgroup: machinename will never be NULL (rhbz#1689297)
+- vircgroup: Remove virCgroupAddTaskController (rhbz#1689297)
+- vircgroup: Introduce virCgroupGetMemoryStat (rhbz#1689297)
+- lxc: Use virCgroupGetMemoryStat (rhbz#1689297)
+- vircgroup: fix MinGW build (rhbz#1689297)
+- vircgroup: Duplicate string before modifying (rhbz#1689297)
+- vircgroup: Extract controller detection into function (rhbz#1689297)
+- vircgroup: Extract placement validation into function (rhbz#1689297)
+- vircgroup: Split virCgroupPathOfController into two functions (rhbz#1689297)
+- vircgroup: Call virCgroupRemove inside virCgroupMakeGroup (rhbz#1689297)
+- vircgroup: Simplify if conditions in virCgroupMakeGroup (rhbz#1689297)
+- vircgroup: Remove obsolete sa_assert (rhbz#1689297)
+- tests: Resolve possible overrun (rhbz#1689297)
+- vircgroup: cleanup controllers not managed by systemd on error (rhbz#1689297)
+- vircgroup: fix bug in virCgroupEnableMissingControllers (rhbz#1689297)
+- vircgroup: rename virCgroupAdd.*Task to virCgroupAdd.*Process (rhbz#1689297)
+- vircgroup: introduce virCgroupTaskFlags (rhbz#1689297)
+- vircgroup: introduce virCgroupAddThread (rhbz#1689297)
+- vircgroupmock: cleanup unused cgroup files (rhbz#1689297)
+- vircgroupmock: rewrite cgroup fopen mocking (rhbz#1689297)
+- vircgrouptest: call virCgroupDetectMounts directly (rhbz#1689297)
+- vircgrouptest: call virCgroupNewSelf instead virCgroupDetectMounts (rhbz#1689297)
+- util: introduce vircgroupbackend files (rhbz#1689297)
+- vircgroup: introduce cgroup v1 backend files (rhbz#1689297)
+- vircgroup: extract virCgroupV1Available (rhbz#1689297)
+- vircgroup: detect available backend for cgroup (rhbz#1689297)
+- vircgroup: extract virCgroupV1ValidateMachineGroup (rhbz#1689297)
+- vircgroup: extract virCgroupV1CopyMounts (rhbz#1689297)
+- vircgroup: extract v1 detect functions (rhbz#1689297)
+- vircgroup: extract virCgroupV1CopyPlacement (rhbz#1689297)
+- vircgroup: extract virCgroupV1ValidatePlacement (rhbz#1689297)
+- vircgroup: extract virCgroupV1StealPlacement (rhbz#1689297)
+- vircgroup: extract virCgroupV1DetectControllers (rhbz#1689297)
+- vircgroup: extract virCgroupV1HasController (rhbz#1689297)
+- vircgroup: extract virCgroupV1GetAnyController (rhbz#1689297)
+- vircgroup: extract virCgroupV1PathOfController (rhbz#1689297)
+- vircgroup: extract virCgroupV1MakeGroup (rhbz#1689297)
+- vircgroup: extract virCgroupV1Remove (rhbz#1689297)
+- vircgroup: extract virCgroupV1AddTask (rhbz#1689297)
+- vircgroup: extract virCgroupV1HasEmptyTasks (rhbz#1689297)
+- vircgroup: extract virCgroupV1BindMount (rhbz#1689297)
+- vircgroup: extract virCgroupV1SetOwner (rhbz#1689297)
+- vircgroup: extract virCgroupV1(Set|Get)BlkioWeight (rhbz#1689297)
+- vircgroup: extract virCgroupV1GetBlkioIoServiced (rhbz#1689297)
+- vircgroup: extract virCgroupV1GetBlkioIoDeviceServiced (rhbz#1689297)
+- vircgroup: extract virCgroupV1(Set|Get)BlkioDeviceWeight (rhbz#1689297)
+- vircgroup: extract virCgroupV1(Set|Get)BlkioDeviceReadIops (rhbz#1689297)
+- vircgroup: extract virCgroupV1(Set|Get)BlkioDeviceWriteIops (rhbz#1689297)
+- vircgroup: extract virCgroupV1(Set|Get)BlkioDeviceReadBps (rhbz#1689297)
+- vircgroup: extract virCgroupV1(Set|Get)BlkioDeviceWriteBps (rhbz#1689297)
+- vircgroup: extract virCgroupV1SetMemory (rhbz#1689297)
+- vircgroup: extract virCgroupV1GetMemoryStat (rhbz#1689297)
+- vircgroup: extract virCgroupV1GetMemoryUsage (rhbz#1689297)
+- vircgroup: extract virCgroupV1(Set|Get)Memory*Limit (rhbz#1689297)
+- vircgroup: extract virCgroupV1GetMemSwapUsage (rhbz#1689297)
+- vircgroup: extract virCgroupV1(Allow|Deny)Device (rhbz#1689297)
+- vircgroup: extract virCgroupV1(Allow|Deny)AllDevices (rhbz#1689297)
+- vircgroup: extract virCgroupV1(Set|Get)CpuShares (rhbz#1689297)
+- vircgroup: extract virCgroupV1(Set|Get)CpuCfsPeriod (rhbz#1689297)
+- vircgroup: extract virCgroupV1(Set|Get)CpuCfsQuota (rhbz#1689297)
+- vircgroup: extract virCgroupV1SupportsCpuBW (rhbz#1689297)
+- vircgroup: extract virCgroupV1GetCpuacct*Usage (rhbz#1689297)
+- vircgroup: extract virCgroupV1GetCpuacctStat (rhbz#1689297)
+- vircgroup: extract virCgroupV1(Set|Get)FreezerState (rhbz#1689297)
+- vircgroup: extract virCgroupV1(Set|Get)CpusetMems (rhbz#1689297)
+- vircgroup: extract virCgroupV1(Set|Get)CpusetMemoryMigrate (rhbz#1689297)
+- vircgroup: extract virCgroupV1(Set|Get)CpusetCpus (rhbz#1689297)
+- vircgroup: rename virCgroupController into virCgroupV1Controller (rhbz#1689297)
+- vircgroup: rename controllers to legacy (rhbz#1689297)
+- vircgroup: remove VIR_CGROUP_SUPPORTED (rhbz#1689297)
+- vircgroup: include system headers only on linux (rhbz#1689297)
+- vircgroupv1: fix build on non-linux OSes (rhbz#1689297)
+- Revert "vircgroup: cleanup controllers not managed by systemd on error" (rhbz#1689297)
+- util: introduce cgroup v2 files (rhbz#1689297)
+- vircgroup: introduce virCgroupV2Available (rhbz#1689297)
+- vircgroup: introduce virCgroupV2ValidateMachineGroup (rhbz#1689297)
+- vircgroup: introduce virCgroupV2CopyMounts (rhbz#1689297)
+- vircgroup: introduce virCgroupV2CopyPlacement (rhbz#1689297)
+- vircgroup: introduce virCgroupV2DetectMounts (rhbz#1689297)
+- vircgroup: introduce virCgroupV2DetectPlacement (rhbz#1689297)
+- vircgroup: introduce virCgroupV2ValidatePlacement (rhbz#1689297)
+- vircgroup: introduce virCgroupV2StealPlacement (rhbz#1689297)
+- vircgroup: introduce virCgroupV2DetectControllers (rhbz#1689297)
+- vircgroup: introduce virCgroupV2HasController (rhbz#1689297)
+- vircgroup: introduce virCgroupV2GetAnyController (rhbz#1689297)
+- vircgroup: introduce virCgroupV2PathOfController (rhbz#1689297)
+- vircgroup: introduce virCgroupV2MakeGroup (rhbz#1689297)
+- vircgroup: introduce virCgroupV2Remove (rhbz#1689297)
+- vircgroup: introduce virCgroupV2AddTask (rhbz#1689297)
+- vircgroup: introduce virCgroupV2HasEmptyTasks (rhbz#1689297)
+- vircgroup: introduce virCgroupV2BindMount (rhbz#1689297)
+- vircgroup: introduce virCgroupV2SetOwner (rhbz#1689297)
+- vircgroup: introduce virCgroupV2(Set|Get)BlkioWeight (rhbz#1689297)
+- vircgroup: introduce virCgroupV2GetBlkioIoServiced (rhbz#1689297)
+- vircgroup: introduce virCgroupV2GetBlkioIoDeviceServiced (rhbz#1689297)
+- vircgroup: introduce virCgroupV2(Set|Get)BlkioDeviceWeight (rhbz#1689297)
+- vircgroup: introduce virCgroupV2(Set|Get)BlkioDeviceReadIops (rhbz#1689297)
+- vircgroup: introduce virCgroupV2(Set|Get)BlkioDeviceWriteIops (rhbz#1689297)
+- vircgroup: introduce virCgroupV2(Set|Get)BlkioDeviceReadBps (rhbz#1689297)
+- vircgroup: introduce virCgroupV2(Set|Get)BlkioDeviceWriteBps (rhbz#1689297)
+- vircgroup: introduce virCgroupV2SetMemory (rhbz#1689297)
+- vircgroup: introduce virCgroupV2GetMemoryStat (rhbz#1689297)
+- vircgroup: introduce virCgroupV2GetMemoryUsage (rhbz#1689297)
+- vircgroup: introduce virCgroupV2(Set|Get)MemoryHardLimit (rhbz#1689297)
+- vircgroup: introduce virCgroupV2(Set|Get)MemorySoftLimit (rhbz#1689297)
+- vircgroup: introduce virCgroupV2(Set|Get)MemSwapHardLimit (rhbz#1689297)
+- vircgroup: introduce virCgroupV2GetMemSwapUsage (rhbz#1689297)
+- vircgroup: introduce virCgroupV2(Set|Get)CpuShares (rhbz#1689297)
+- vircgroup: introduce virCgroupV2(Set|Get)CpuCfsPeriod (rhbz#1689297)
+- vircgroup: introduce virCgroupV2(Set|Get)CpuCfsQuota (rhbz#1689297)
+- vircgroup: introduce virCgroupV2SupportsCpuBW (rhbz#1689297)
+- vircgroup: introduce virCgroupV2GetCpuacctUsage (rhbz#1689297)
+- vircgroup: introduce virCgroupV2GetCpuacctStat (rhbz#1689297)
+- vircgroup: register cgroup v2 backend (rhbz#1689297)
+- vircgroup: add support for hybrid configuration (rhbz#1689297)
+- vircgroupmock: change cgroup prefix (rhbz#1689297)
+- vircgroupmock: add support to test cgroup v2 (rhbz#1689297)
+- vircgrouptest: introduce initFakeFS and cleanupFakeFS helpers (rhbz#1689297)
+- vircgrouptest: prepare testCgroupDetectMounts for cgroup v2 (rhbz#1689297)
+- vircgrouptest: add detect mounts test for cgroup v2 (rhbz#1689297)
+- vircgrouptest: add detect mounts test for hybrid cgroups (rhbz#1689297)
+- vircgrouptest: prepare validateCgroup for cgroupv2 (rhbz#1689297)
+- vircgrouptest: add cgroup v2 tests (rhbz#1689297)
+- vircgrouptest: add hybrid tests (rhbz#1689297)
+- virt-host-validate: rewrite cgroup detection to use util/vircgroup (rhbz#1689297)
+- virt-host-validate: require freezer for LXC (rhbz#1689297)
+- virt-host-validate: Fix build on non-Linux (rhbz#1689297)
+- tests: Use correct function name in error path (rhbz#1689297)
+- util: Fix virCgroupGetMemoryStat (rhbz#1689297)
+- tests: Augment vcgrouptest to add virCgroupGetMemoryStat (rhbz#1689297)
+- vircgroup: introduce virCgroupKillRecursiveCB (rhbz#1689297)
+- vircgroupv2: fix virCgroupV2ValidateMachineGroup (rhbz#1689297)
+- util: implement virCgroupV2(Set|Get)CpusetMems (rhbz#1689297)
+- util: implement virCgroupV2(Set|Get)CpusetMemoryMigrate (rhbz#1689297)
+- util: implement virCgroupV2(Set|Get)CpusetCpus (rhbz#1689297)
+- util: enable cgroups v2 cpuset controller for threads (rhbz#1689297)
+- util: vircgroup: pass parent cgroup into virCgroupDetectControllersCB (rhbz#1689297)
+- internal: introduce a family of NULLSTR macros (rhbz#1689297)
+- util: vircgroup: improve controller detection (rhbz#1689297)
+- util: vircgroupv2: use any controller to create thread directory (rhbz#1689297)
+- util: vircgroupv2: enable CPU controller only if it's available (rhbz#1689297)
+- util: vircgroupv2: separate return values of virCgroupV2EnableController (rhbz#1689297)
+- util: vircgroupv2: don't error out if enabling controller fails (rhbz#1689297)
+- util: vircgroupv2: mark only requested controllers as available (rhbz#1689297)
+- Revert "util: vircgroup: pass parent cgroup into virCgroupDetectControllersCB" (rhbz#1689297)
+- util: vircgroupv2: stop enabling missing controllers with systemd (rhbz#1689297)
+
+* Fri Jun 28 2019 Danilo de Paula <ddepaula@redhat.com> - 4.5.0-28
 - Rebuild all virt packages to fix RHEL's upgrade path
-- Resolves: rhbz#1696354
-  (Ensure modular RPM upgrade path [ZStream Clone] [rhel-8.0.0.z])
+- Resolves: rhbz#1695587
+  (Ensure modular RPM upgrade path)
 
-* Tue Jun 18 2019 Jiri Denemark <jdenemar@redhat.com> - 4.5.0-23.3.el8
+* Fri Jun 21 2019 Jiri Denemark <jdenemar@redhat.com> - 4.5.0-27
+- RHEL: spec: Disable gluster on i686 (rhbz#1722668)
+- rpc: virnetlibsshsession: update deprecated functions (rhbz#1722735)
+
+* Thu Jun 20 2019 Jiri Denemark <jdenemar@redhat.com> - 4.5.0-26
 - api: disallow virDomainSaveImageGetXMLDesc on read-only connections (CVE-2019-10161)
 - api: disallow virDomainManagedSaveDefineXML on read-only connections (CVE-2019-10166)
 - api: disallow virConnectGetDomainCapabilities on read-only connections (CVE-2019-10167)
 - api: disallow virConnect*HypervisorCPU on read-only connections (CVE-2019-10168)
 
-* Thu May 16 2019 Jiri Denemark <jdenemar@redhat.com> - 4.5.0-23.2.el8
+* Fri Jun 14 2019 Jiri Denemark <jdenemar@redhat.com> - 4.5.0-25
 - admin: reject clients unless their UID matches the current UID (CVE-2019-10132)
 - locking: restrict sockets to mode 0600 (CVE-2019-10132)
 - logging: restrict sockets to mode 0600 (CVE-2019-10132)
-
-* Mon May  6 2019 Jiri Denemark <jdenemar@redhat.com> - 4.5.0-23.1.el8
-- cpu_x86: Do not cache microcode version (CVE-2018-12130, CVE-2018-12126, CVE-2018-11091, CVE-2018-12127)
-- qemu: Don't cache microcode version (CVE-2018-12130, CVE-2018-12126, CVE-2018-11091, CVE-2018-12127)
-- cputest: Add data for Intel(R) Xeon(R) CPU E3-1225 v5 (CVE-2018-12130, CVE-2018-12126, CVE-2018-11091, CVE-2018-12127)
-- cpu_map: Define md-clear CPUID bit (CVE-2018-12130, CVE-2018-12126, CVE-2018-11091, CVE-2018-12127)
+- util: skip RDMA detection for non-PCI network devices (rhbz#1693299)
+- virfile: Detect ceph as shared FS (rhbz#1698133)
+- virfile: added GPFS as shared fs (rhbz#1698133)
+- util: bitmap: define cleanup function using VIR_DEFINE_AUTOPTR_FUNC (rhbz#1716943)
+- qemu: Rework setting process affinity (rhbz#1716943)
+- qemu: Set up EMULATOR thread and cpuset.mems before exec()-ing qemu (rhbz#1716943)
+- conf: Add definitions for 'uid' and 'fid' PCI address attributes (rhbz#1508149)
+- qemu: Introduce zPCI capability (rhbz#1508149)
+- qemu: Enable PCI multi bus for S390 guests (rhbz#1508149)
+- conf: Introduce extension flag and zPCI member for PCI address (rhbz#1508149)
+- conf: Introduce address caching for PCI extensions (rhbz#1508149)
+- qemu: Auto add pci-root for s390/s390x guests (rhbz#1508149)
+- conf: use virXMLFormatElement() in virDomainDeviceInfoFormat() (rhbz#1508149)
+- conf: Introduce parser, formatter for uid and fid (rhbz#1508149)
+- qemu: Add zPCI address definition check (rhbz#1508149)
+- conf: Allocate/release 'uid' and 'fid' in PCI address (rhbz#1508149)
+- qemu: Generate and use zPCI device in QEMU command line (rhbz#1508149)
+- qemu: Add hotpluging support for PCI devices on S390 guests (rhbz#1508149)
+- qemuDomainRemoveRNGDevice: Remove associated chardev too (rhbz#1508149)
+- qemu_hotplug: remove erroneous call to qemuDomainDetachExtensionDevice() (rhbz#1508149)
+- qemu_hotplug: remove another erroneous qemuDomainDetachExtensionDevice() call (rhbz#1508149)
+- util: Propagate numad failures correctly (rhbz#1716907)
+- util: Introduce virBitmapUnion() (rhbz#1716908)
+- util: Introduce virNumaNodesetToCPUset() (rhbz#1716908)
+- qemu: Fix qemuProcessInitCpuAffinity() (rhbz#1716908)
+- qemu: Fix leak in qemuProcessInitCpuAffinity() (rhbz#1716908)
+- qemu: Drop cleanup label from qemuProcessInitCpuAffinity() (rhbz#1716908)
+- qemu: Fix NULL pointer access in qemuProcessInitCpuAffinity() (rhbz#1716908)
+- qemuBuildMemoryBackendProps: Pass @priv instead of its individual members (rhbz#1624223)
+- qemu: Don't use -mem-prealloc among with .prealloc=yes (rhbz#1624223)
+- nwfilter: fix adding std MAC and IP values to filter binding (rhbz#1691356)
+- qemuProcessBuildDestroyMemoryPathsImpl: Don't overwrite error (rhbz#1658112)
+- qemu_security: Fully implement qemuSecurityDomainSetPathLabel (rhbz#1658112)
+- qemu: process: SEV: Assume libDir to be the directory to create files in (rhbz#1658112)
+- qemu: process: SEV: Relabel guest owner's SEV files created before start (rhbz#1658112)
+
+* Tue May 14 2019 Jiri Denemark <jdenemar@redhat.com> - 4.5.0-24
+- tests: qemuxml2argv: add CAPS_ARCH_LATEST macro (rhbz#1698855)
+- qemu: Add ccw support for vhost-vsock (rhbz#1698855)
+- qemu: Allow creating ppc64 guests with graphics and no USB mouse (rhbz#1683681)
+- conf: Expose virDomainSCSIDriveAddressIsUsed (rhbz#1692354)
+- qemuhotplugtest: Don't plug a SCSI disk at unit 7 (rhbz#1692354)
+- qemu_hotplug: Check for duplicate drive addresses (rhbz#1692354)
+- cpu_map: Add support for cldemote CPU feature (rhbz#1537731)
+- util: alloc: add macros for implementing automatic cleanup functionality (rhbz#1505998)
+- qemu: domain: Simplify non-VFIO memLockLimit calculation for PPC64 (rhbz#1505998)
+- qemu_domain: add a PPC64 memLockLimit helper (rhbz#1505998)
+- qemu_domain: NVLink2 bridge detection function for PPC64 (rhbz#1505998)
+- PPC64 support for NVIDIA V100 GPU with NVLink2 passthrough (rhbz#1505998)
+- cpu_x86: Do not cache microcode version (CVE-2018-12127, CVE-2019-11091, CVE-2018-12126, CVE-2018-12130)
+- qemu: Don't cache microcode version (CVE-2018-12127, CVE-2019-11091, CVE-2018-12126, CVE-2018-12130)
+- cputest: Add data for Intel(R) Xeon(R) CPU E3-1225 v5 (CVE-2018-12127, CVE-2019-11091, CVE-2018-12126, CVE-2018-12130)
+- cpu_map: Define md-clear CPUID bit (CVE-2018-12127, CVE-2019-11091, CVE-2018-12126, CVE-2018-12130)
 
 * Fri Feb 15 2019 Jiri Denemark <jdenemar@redhat.com> - 4.5.0-23
 - network: explicitly allow icmp/icmpv6 in libvirt zonefile (rhbz#1650320)