Blob Blame History Raw
From ac08fdc6dcbdc6e9fdb976fd2143c663d3748752 Mon Sep 17 00:00:00 2001
Message-Id: <ac08fdc6dcbdc6e9fdb976fd2143c663d3748752@dist-git>
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Tue, 12 Dec 2017 16:23:41 +0100
Subject: [PATCH] qemu: capabilities: force update if the microcode version
 does not match

A microcode update can cause the CPUID bits to change; an example
from the past was the update that disabled TSX on several Haswell
and Broadwell machines.

Therefore, place microcode version in the virQEMUCaps struct and
XML, and rebuild the cache if the versions do not match.

CVE-2017-5715

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>

Conflicts:
	src/qemu/qemu_capabilities.c
	src/qemu/qemu_capabilities.h
            - virQEMUCapsCache is based on virFileCache in 7.5

	src/qemu/qemu_capspriv.h
            - context; more functions were added in 7.5

	tests/qemucapabilitiesdata/caps_2.10.0-gicv2.aarch64.xml
	tests/qemucapabilitiesdata/caps_2.10.0-gicv3.aarch64.xml
	tests/qemucapabilitiesdata/caps_2.10.0.ppc64.xml
	tests/qemucapabilitiesdata/caps_2.10.0.s390x.xml
	tests/qemucapabilitiesdata/caps_2.10.0.x86_64.xml
	tests/qemucapabilitiesdata/caps_2.9.0.ppc64.xml
	tests/qemucapabilitiesdata/caps_2.9.0.s390x.xml
            - missing in 7.4

	tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml
            - context; different package version in 7.4

	tests/qemucapsprobe.c
            - virQEMUCapsNewForBinaryInternal has fewer parameters
              in 7.5
---
 src/qemu/qemu_capabilities.c                       | 56 +++++++++++++++++++---
 src/qemu/qemu_capabilities.h                       |  7 ++-
 src/qemu/qemu_capspriv.h                           |  6 +++
 src/qemu/qemu_driver.c                             |  9 +++-
 tests/qemucapabilitiesdata/caps_1.2.2.x86_64.xml   |  1 +
 tests/qemucapabilitiesdata/caps_1.3.1.x86_64.xml   |  1 +
 tests/qemucapabilitiesdata/caps_1.4.2.x86_64.xml   |  1 +
 tests/qemucapabilitiesdata/caps_1.5.3.x86_64.xml   |  1 +
 tests/qemucapabilitiesdata/caps_1.6.0.x86_64.xml   |  1 +
 tests/qemucapabilitiesdata/caps_1.7.0.x86_64.xml   |  1 +
 tests/qemucapabilitiesdata/caps_2.1.1.x86_64.xml   |  1 +
 tests/qemucapabilitiesdata/caps_2.4.0.x86_64.xml   |  1 +
 tests/qemucapabilitiesdata/caps_2.5.0.x86_64.xml   |  1 +
 .../caps_2.6.0-gicv2.aarch64.xml                   |  1 +
 .../caps_2.6.0-gicv3.aarch64.xml                   |  1 +
 tests/qemucapabilitiesdata/caps_2.6.0.ppc64le.xml  |  1 +
 tests/qemucapabilitiesdata/caps_2.6.0.x86_64.xml   |  1 +
 tests/qemucapabilitiesdata/caps_2.7.0.s390x.xml    |  1 +
 tests/qemucapabilitiesdata/caps_2.7.0.x86_64.xml   |  1 +
 tests/qemucapabilitiesdata/caps_2.8.0.s390x.xml    |  1 +
 tests/qemucapabilitiesdata/caps_2.8.0.x86_64.xml   |  1 +
 tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml   |  1 +
 tests/qemucapabilitiestest.c                       | 14 ++++--
 tests/qemucapsprobe.c                              |  2 +-
 tests/testutilsqemu.c                              |  2 +-
 25 files changed, 98 insertions(+), 16 deletions(-)

diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index a42f8d9988..504e2c9587 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -426,6 +426,7 @@ struct _virQEMUCaps {
 
     unsigned int version;
     unsigned int kvmVersion;
+    unsigned int microcodeVersion;
     char *package;
 
     virArch arch;
@@ -2217,6 +2218,7 @@ virQEMUCapsPtr virQEMUCapsNewCopy(virQEMUCapsPtr qemuCaps)
 
     ret->version = qemuCaps->version;
     ret->kvmVersion = qemuCaps->kvmVersion;
+    ret->microcodeVersion = qemuCaps->microcodeVersion;
 
     if (VIR_STRDUP(ret->package, qemuCaps->package) < 0)
         goto error;
@@ -3817,6 +3819,13 @@ virQEMUCapsLoadCache(virCapsPtr caps,
         goto cleanup;
     }
 
+    if (virXPathUInt("string(./microcodeVersion)", ctxt,
+                     &qemuCaps->microcodeVersion) < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("missing microcode version in QEMU capabilities cache"));
+        goto cleanup;
+    }
+
     if (virXPathBoolean("boolean(./package)", ctxt) > 0) {
         qemuCaps->package = virXPathString("string(./package)", ctxt);
         if (!qemuCaps->package &&
@@ -4083,6 +4092,9 @@ virQEMUCapsFormatCache(virQEMUCapsPtr qemuCaps,
     virBufferAsprintf(&buf, "<kvmVersion>%d</kvmVersion>\n",
                       qemuCaps->kvmVersion);
 
+    virBufferAsprintf(&buf, "<microcodeVersion>%u</microcodeVersion>\n",
+                      qemuCaps->microcodeVersion);
+
     if (qemuCaps->package)
         virBufferAsprintf(&buf, "<package>%s</package>\n",
                           qemuCaps->package);
@@ -4286,7 +4298,8 @@ virQEMUCapsInitCached(virCapsPtr caps,
         goto discard;
     }
 
-    if (!virQEMUCapsIsValid(qemuCaps, qemuctime, runUid, runGid))
+    if (!virQEMUCapsIsValid(qemuCaps, qemuctime, runUid, runGid,
+                            virCapabilitiesGetMicrocodeVersion(caps)))
         goto discard;
 
     /* Discard cache if QEMU binary or libvirtd changed */
@@ -5138,6 +5151,7 @@ virQEMUCapsNewForBinaryInternal(virCapsPtr caps,
                                 const char *cacheDir,
                                 uid_t runUid,
                                 gid_t runGid,
+                                unsigned int microcodeVersion,
                                 bool qmpOnly)
 {
     virQEMUCapsPtr qemuCaps;
@@ -5204,6 +5218,9 @@ virQEMUCapsNewForBinaryInternal(virCapsPtr caps,
         virQEMUCapsInitHostCPUModel(qemuCaps, caps, VIR_DOMAIN_VIRT_QEMU);
     }
 
+    if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_KVM))
+        qemuCaps->microcodeVersion = microcodeVersion;
+
  cleanup:
     VIR_FREE(qmperr);
     return qemuCaps;
@@ -5220,10 +5237,12 @@ virQEMUCapsNewForBinary(virCapsPtr caps,
                         const char *libDir,
                         const char *cacheDir,
                         uid_t runUid,
-                        gid_t runGid)
+                        gid_t runGid,
+                        unsigned int microcodeVersion)
 {
     return virQEMUCapsNewForBinaryInternal(caps, binary, libDir, cacheDir,
-                                           runUid, runGid, false);
+                                           runUid, runGid, microcodeVersion,
+                                           false);
 }
 
 
@@ -5231,7 +5250,8 @@ bool
 virQEMUCapsIsValid(virQEMUCapsPtr qemuCaps,
                    time_t qemuctime,
                    uid_t runUid,
-                   gid_t runGid)
+                   gid_t runGid,
+                   unsigned int microcodeVersion)
 {
     bool kvmUsable;
 
@@ -5279,6 +5299,16 @@ virQEMUCapsIsValid(virQEMUCapsPtr qemuCaps,
         return false;
     }
 
+    if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_KVM) &&
+        microcodeVersion != qemuCaps->microcodeVersion) {
+        VIR_DEBUG("Outdated capabilities for '%s': microcode version changed "
+                  "(%u vs %u)",
+                  qemuCaps->binary,
+                  microcodeVersion,
+                  qemuCaps->microcodeVersion);
+        return false;
+    }
+
     return true;
 }
 
@@ -5325,7 +5355,8 @@ virQEMUCapsCachePtr
 virQEMUCapsCacheNew(const char *libDir,
                     const char *cacheDir,
                     uid_t runUid,
-                    gid_t runGid)
+                    gid_t runGid,
+                    unsigned int microcodeVersion)
 {
     virQEMUCapsCachePtr cache;
 
@@ -5348,6 +5379,7 @@ virQEMUCapsCacheNew(const char *libDir,
 
     cache->runUid = runUid;
     cache->runGid = runGid;
+    cache->microcodeVersion = microcodeVersion;
 
     return cache;
 
@@ -5364,7 +5396,8 @@ virQEMUCapsCacheValidate(virQEMUCapsCachePtr cache,
                          virQEMUCapsPtr *qemuCaps)
 {
     if (*qemuCaps &&
-        !virQEMUCapsIsValid(*qemuCaps, 0, cache->runUid, cache->runGid)) {
+        !virQEMUCapsIsValid(*qemuCaps, 0, cache->runUid, cache->runGid,
+                            virCapabilitiesGetMicrocodeVersion(caps))) {
         VIR_DEBUG("Cached capabilities %p no longer valid for %s",
                   *qemuCaps, binary);
         virHashRemoveEntry(cache->binaries, binary);
@@ -5375,7 +5408,8 @@ virQEMUCapsCacheValidate(virQEMUCapsCachePtr cache,
         VIR_DEBUG("Creating capabilities for %s", binary);
         *qemuCaps = virQEMUCapsNewForBinary(caps, binary,
                                             cache->libDir, cache->cacheDir,
-                                            cache->runUid, cache->runGid);
+                                            cache->runUid, cache->runGid,
+                                            virCapabilitiesGetMicrocodeVersion(caps));
         if (*qemuCaps) {
             VIR_DEBUG("Caching capabilities %p for %s", *qemuCaps, binary);
             if (virHashAddEntry(cache->binaries, binary, *qemuCaps) < 0) {
@@ -5926,3 +5960,11 @@ virQEMUCapsFillDomainCaps(virCapsPtr caps,
         return -1;
     return 0;
 }
+
+
+void
+virQEMUCapsSetMicrocodeVersion(virQEMUCapsPtr qemuCaps,
+                               unsigned int microcodeVersion)
+{
+    qemuCaps->microcodeVersion = microcodeVersion;
+}
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
index bc4ad44496..d1a1d46b5a 100644
--- a/src/qemu/qemu_capabilities.h
+++ b/src/qemu/qemu_capabilities.h
@@ -497,7 +497,8 @@ int virQEMUCapsGetMachineTypesCaps(virQEMUCapsPtr qemuCaps,
 bool virQEMUCapsIsValid(virQEMUCapsPtr qemuCaps,
                         time_t ctime,
                         uid_t runUid,
-                        gid_t runGid);
+                        gid_t runGid,
+                        unsigned int microcodeVersion);
 
 void virQEMUCapsFilterByMachineType(virQEMUCapsPtr qemuCaps,
                                     const char *machineType);
@@ -509,7 +510,9 @@ void virQEMUCapsSetGICCapabilities(virQEMUCapsPtr qemuCaps,
 
 virQEMUCapsCachePtr virQEMUCapsCacheNew(const char *libDir,
                                         const char *cacheDir,
-                                        uid_t uid, gid_t gid);
+                                        uid_t uid,
+                                        gid_t gid,
+                                        unsigned int microcodeVersion);
 virQEMUCapsPtr virQEMUCapsCacheLookup(virCapsPtr caps,
                                       virQEMUCapsCachePtr cache,
                                       const char *binary);
diff --git a/src/qemu/qemu_capspriv.h b/src/qemu/qemu_capspriv.h
index 1baaaf3340..d39a71a2f8 100644
--- a/src/qemu/qemu_capspriv.h
+++ b/src/qemu/qemu_capspriv.h
@@ -35,6 +35,7 @@ struct _virQEMUCapsCache {
     char *cacheDir;
     uid_t runUid;
     gid_t runGid;
+    unsigned int microcodeVersion;
 };
 
 virQEMUCapsPtr virQEMUCapsNewCopy(virQEMUCapsPtr qemuCaps);
@@ -46,6 +47,7 @@ virQEMUCapsNewForBinaryInternal(virCapsPtr caps,
                                 const char *cacheDir,
                                 uid_t runUid,
                                 gid_t runGid,
+                                unsigned int microcodeVersion,
                                 bool qmpOnly);
 
 int virQEMUCapsLoadCache(virCapsPtr caps,
@@ -93,4 +95,8 @@ virCPUDefPtr
 virQEMUCapsProbeHostCPUForEmulator(virCapsPtr caps,
                                    virQEMUCapsPtr qemuCaps,
                                    virDomainVirtType type);
+
+void
+virQEMUCapsSetMicrocodeVersion(virQEMUCapsPtr qemuCaps,
+                               unsigned int microcodeVersion);
 #endif
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 498f787ad3..0943d222b4 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -628,6 +628,8 @@ qemuStateInitialize(bool privileged,
     gid_t run_gid = -1;
     char *hugepagePath = NULL;
     size_t i;
+    virCPUDefPtr hostCPU = NULL;
+    unsigned int microcodeVersion = 0;
 
     if (VIR_ALLOC(qemu_driver) < 0)
         return -1;
@@ -847,10 +849,15 @@ qemuStateInitialize(bool privileged,
         run_gid = cfg->group;
     }
 
+    if ((hostCPU = virCPUProbeHost(virArchFromHost())))
+        microcodeVersion = hostCPU->microcodeVersion;
+    virCPUDefFree(hostCPU);
+
     qemu_driver->qemuCapsCache = virQEMUCapsCacheNew(cfg->libDir,
                                                      cfg->cacheDir,
                                                      run_uid,
-                                                     run_gid);
+                                                     run_gid,
+                                                     microcodeVersion);
     if (!qemu_driver->qemuCapsCache)
         goto error;
 
diff --git a/tests/qemucapabilitiesdata/caps_1.2.2.x86_64.xml b/tests/qemucapabilitiesdata/caps_1.2.2.x86_64.xml
index 5ad406ce1b..12d5873251 100644
--- a/tests/qemucapabilitiesdata/caps_1.2.2.x86_64.xml
+++ b/tests/qemucapabilitiesdata/caps_1.2.2.x86_64.xml
@@ -112,6 +112,7 @@
   <flag name='query-cpu-definitions'/>
   <version>1002002</version>
   <kvmVersion>0</kvmVersion>
+  <microcodeVersion>26900</microcodeVersion>
   <package></package>
   <arch>x86_64</arch>
   <cpu type='kvm' name='qemu64'/>
diff --git a/tests/qemucapabilitiesdata/caps_1.3.1.x86_64.xml b/tests/qemucapabilitiesdata/caps_1.3.1.x86_64.xml
index 4ec731d655..8bfbf79a74 100644
--- a/tests/qemucapabilitiesdata/caps_1.3.1.x86_64.xml
+++ b/tests/qemucapabilitiesdata/caps_1.3.1.x86_64.xml
@@ -130,6 +130,7 @@
   <flag name='query-cpu-definitions'/>
   <version>1003001</version>
   <kvmVersion>0</kvmVersion>
+  <microcodeVersion>30198</microcodeVersion>
   <package></package>
   <arch>x86_64</arch>
   <cpu type='kvm' name='qemu64'/>
diff --git a/tests/qemucapabilitiesdata/caps_1.4.2.x86_64.xml b/tests/qemucapabilitiesdata/caps_1.4.2.x86_64.xml
index 601c62e65a..19925d0f29 100644
--- a/tests/qemucapabilitiesdata/caps_1.4.2.x86_64.xml
+++ b/tests/qemucapabilitiesdata/caps_1.4.2.x86_64.xml
@@ -131,6 +131,7 @@
   <flag name='query-cpu-definitions'/>
   <version>1004002</version>
   <kvmVersion>0</kvmVersion>
+  <microcodeVersion>30915</microcodeVersion>
   <package></package>
   <arch>x86_64</arch>
   <cpu type='kvm' name='Opteron_G5'/>
diff --git a/tests/qemucapabilitiesdata/caps_1.5.3.x86_64.xml b/tests/qemucapabilitiesdata/caps_1.5.3.x86_64.xml
index 14f34b2771..df3c2d87b6 100644
--- a/tests/qemucapabilitiesdata/caps_1.5.3.x86_64.xml
+++ b/tests/qemucapabilitiesdata/caps_1.5.3.x86_64.xml
@@ -143,6 +143,7 @@
   <flag name='kernel-irqchip'/>
   <version>1005003</version>
   <kvmVersion>0</kvmVersion>
+  <microcodeVersion>47019</microcodeVersion>
   <package></package>
   <arch>x86_64</arch>
   <cpu type='kvm' name='Opteron_G5'/>
diff --git a/tests/qemucapabilitiesdata/caps_1.6.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_1.6.0.x86_64.xml
index 8fc23d6aad..889cd96dde 100644
--- a/tests/qemucapabilitiesdata/caps_1.6.0.x86_64.xml
+++ b/tests/qemucapabilitiesdata/caps_1.6.0.x86_64.xml
@@ -148,6 +148,7 @@
   <flag name='kernel-irqchip'/>
   <version>1006000</version>
   <kvmVersion>0</kvmVersion>
+  <microcodeVersion>45248</microcodeVersion>
   <package></package>
   <arch>x86_64</arch>
   <cpu type='kvm' name='Opteron_G5'/>
diff --git a/tests/qemucapabilitiesdata/caps_1.7.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_1.7.0.x86_64.xml
index 47c8956b44..426fcfc139 100644
--- a/tests/qemucapabilitiesdata/caps_1.7.0.x86_64.xml
+++ b/tests/qemucapabilitiesdata/caps_1.7.0.x86_64.xml
@@ -150,6 +150,7 @@
   <flag name='kernel-irqchip'/>
   <version>1007000</version>
   <kvmVersion>0</kvmVersion>
+  <microcodeVersion>50692</microcodeVersion>
   <package></package>
   <arch>x86_64</arch>
   <cpu type='kvm' name='Opteron_G5'/>
diff --git a/tests/qemucapabilitiesdata/caps_2.1.1.x86_64.xml b/tests/qemucapabilitiesdata/caps_2.1.1.x86_64.xml
index afe7d53ff4..82737b2a7f 100644
--- a/tests/qemucapabilitiesdata/caps_2.1.1.x86_64.xml
+++ b/tests/qemucapabilitiesdata/caps_2.1.1.x86_64.xml
@@ -166,6 +166,7 @@
   <flag name='kernel-irqchip'/>
   <version>2001001</version>
   <kvmVersion>0</kvmVersion>
+  <microcodeVersion>59488</microcodeVersion>
   <package></package>
   <arch>x86_64</arch>
   <cpu type='kvm' name='Opteron_G5'/>
diff --git a/tests/qemucapabilitiesdata/caps_2.4.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_2.4.0.x86_64.xml
index 5bdc1a2bdd..dca3452861 100644
--- a/tests/qemucapabilitiesdata/caps_2.4.0.x86_64.xml
+++ b/tests/qemucapabilitiesdata/caps_2.4.0.x86_64.xml
@@ -188,6 +188,7 @@
   <flag name='kernel-irqchip'/>
   <version>2004000</version>
   <kvmVersion>0</kvmVersion>
+  <microcodeVersion>75653</microcodeVersion>
   <package></package>
   <arch>x86_64</arch>
   <cpu type='kvm' name='Opteron_G5'/>
diff --git a/tests/qemucapabilitiesdata/caps_2.5.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_2.5.0.x86_64.xml
index 36bc1342bb..03bc558c18 100644
--- a/tests/qemucapabilitiesdata/caps_2.5.0.x86_64.xml
+++ b/tests/qemucapabilitiesdata/caps_2.5.0.x86_64.xml
@@ -194,6 +194,7 @@
   <flag name='kernel-irqchip'/>
   <version>2005000</version>
   <kvmVersion>0</kvmVersion>
+  <microcodeVersion>216775</microcodeVersion>
   <package></package>
   <arch>x86_64</arch>
   <cpu type='kvm' name='Opteron_G5'/>
diff --git a/tests/qemucapabilitiesdata/caps_2.6.0-gicv2.aarch64.xml b/tests/qemucapabilitiesdata/caps_2.6.0-gicv2.aarch64.xml
index 33bc462084..c78719c778 100644
--- a/tests/qemucapabilitiesdata/caps_2.6.0-gicv2.aarch64.xml
+++ b/tests/qemucapabilitiesdata/caps_2.6.0-gicv2.aarch64.xml
@@ -172,6 +172,7 @@
   <flag name='kernel-irqchip.split'/>
   <version>2006000</version>
   <kvmVersion>0</kvmVersion>
+  <microcodeVersion>228838</microcodeVersion>
   <package></package>
   <arch>aarch64</arch>
   <cpu type='kvm' name='pxa262'/>
diff --git a/tests/qemucapabilitiesdata/caps_2.6.0-gicv3.aarch64.xml b/tests/qemucapabilitiesdata/caps_2.6.0-gicv3.aarch64.xml
index a8ce6b03b1..314b9407c0 100644
--- a/tests/qemucapabilitiesdata/caps_2.6.0-gicv3.aarch64.xml
+++ b/tests/qemucapabilitiesdata/caps_2.6.0-gicv3.aarch64.xml
@@ -172,6 +172,7 @@
   <flag name='kernel-irqchip.split'/>
   <version>2006000</version>
   <kvmVersion>0</kvmVersion>
+  <microcodeVersion>228838</microcodeVersion>
   <package></package>
   <arch>aarch64</arch>
   <cpu type='kvm' name='pxa262'/>
diff --git a/tests/qemucapabilitiesdata/caps_2.6.0.ppc64le.xml b/tests/qemucapabilitiesdata/caps_2.6.0.ppc64le.xml
index 425992f0d5..f09d0f74d1 100644
--- a/tests/qemucapabilitiesdata/caps_2.6.0.ppc64le.xml
+++ b/tests/qemucapabilitiesdata/caps_2.6.0.ppc64le.xml
@@ -166,6 +166,7 @@
   <flag name='kernel-irqchip.split'/>
   <version>2006000</version>
   <kvmVersion>0</kvmVersion>
+  <microcodeVersion>262913</microcodeVersion>
   <package></package>
   <arch>ppc64</arch>
   <cpu type='kvm' name='default'/>
diff --git a/tests/qemucapabilitiesdata/caps_2.6.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_2.6.0.x86_64.xml
index 97e71ec4f4..4dadf178bd 100644
--- a/tests/qemucapabilitiesdata/caps_2.6.0.x86_64.xml
+++ b/tests/qemucapabilitiesdata/caps_2.6.0.x86_64.xml
@@ -204,6 +204,7 @@
   <flag name='kernel-irqchip.split'/>
   <version>2006000</version>
   <kvmVersion>0</kvmVersion>
+  <microcodeVersion>227579</microcodeVersion>
   <package></package>
   <arch>x86_64</arch>
   <cpu type='kvm' name='Opteron_G5'/>
diff --git a/tests/qemucapabilitiesdata/caps_2.7.0.s390x.xml b/tests/qemucapabilitiesdata/caps_2.7.0.s390x.xml
index 70cce64179..75d77ccd13 100644
--- a/tests/qemucapabilitiesdata/caps_2.7.0.s390x.xml
+++ b/tests/qemucapabilitiesdata/caps_2.7.0.s390x.xml
@@ -134,6 +134,7 @@
   <flag name='kernel-irqchip.split'/>
   <version>2007000</version>
   <kvmVersion>0</kvmVersion>
+  <microcodeVersion>217559</microcodeVersion>
   <package></package>
   <arch>s390x</arch>
   <cpu type='kvm' name='host'/>
diff --git a/tests/qemucapabilitiesdata/caps_2.7.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_2.7.0.x86_64.xml
index 49c046212b..b9531ad2d2 100644
--- a/tests/qemucapabilitiesdata/caps_2.7.0.x86_64.xml
+++ b/tests/qemucapabilitiesdata/caps_2.7.0.x86_64.xml
@@ -207,6 +207,7 @@
   <flag name='intel-iommu.intremap'/>
   <version>2007000</version>
   <kvmVersion>0</kvmVersion>
+  <microcodeVersion>239276</microcodeVersion>
   <package> (v2.7.0)</package>
   <arch>x86_64</arch>
   <cpu type='kvm' name='Opteron_G5'/>
diff --git a/tests/qemucapabilitiesdata/caps_2.8.0.s390x.xml b/tests/qemucapabilitiesdata/caps_2.8.0.s390x.xml
index 51be9bce4d..a707d76bc3 100644
--- a/tests/qemucapabilitiesdata/caps_2.8.0.s390x.xml
+++ b/tests/qemucapabilitiesdata/caps_2.8.0.s390x.xml
@@ -136,6 +136,7 @@
   <flag name='kernel-irqchip.split'/>
   <version>2007093</version>
   <kvmVersion>0</kvmVersion>
+  <microcodeVersion>242460</microcodeVersion>
   <package></package>
   <arch>s390x</arch>
   <hostCPU type='kvm' model='zEC12.2-base' migratability='no'>
diff --git a/tests/qemucapabilitiesdata/caps_2.8.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_2.8.0.x86_64.xml
index 01edbc88da..d3bce6b15c 100644
--- a/tests/qemucapabilitiesdata/caps_2.8.0.x86_64.xml
+++ b/tests/qemucapabilitiesdata/caps_2.8.0.x86_64.xml
@@ -209,6 +209,7 @@
   <flag name='intel-iommu.eim'/>
   <version>2008000</version>
   <kvmVersion>0</kvmVersion>
+  <microcodeVersion>255931</microcodeVersion>
   <package> (v2.8.0)</package>
   <arch>x86_64</arch>
   <cpu type='kvm' name='host' usable='yes'/>
diff --git a/tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml
index 2140eab398..34dd9353d8 100644
--- a/tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml
+++ b/tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml
@@ -219,6 +219,7 @@
   <flag name='virtio.ats'/>
   <version>2008090</version>
   <kvmVersion>0</kvmVersion>
+  <microcodeVersion>317985</microcodeVersion>
   <package> (v2.9.0-rc0-142-g940a8ce)</package>
   <arch>x86_64</arch>
   <hostCPU type='kvm' model='base' migratability='yes'>
diff --git a/tests/qemucapabilitiestest.c b/tests/qemucapabilitiestest.c
index 2918ff4695..c817478e49 100644
--- a/tests/qemucapabilitiestest.c
+++ b/tests/qemucapabilitiestest.c
@@ -61,10 +61,16 @@ testQemuCaps(const void *opaque)
                                   qemuMonitorTestGetMonitor(mon)) < 0)
         goto cleanup;
 
-    if (virQEMUCapsGet(capsActual, QEMU_CAPS_KVM) &&
-        virQEMUCapsInitQMPMonitorTCG(capsActual,
-                                     qemuMonitorTestGetMonitor(mon)) < 0)
-        goto cleanup;
+    if (virQEMUCapsGet(capsActual, QEMU_CAPS_KVM)) {
+        if (virQEMUCapsInitQMPMonitorTCG(capsActual,
+                                         qemuMonitorTestGetMonitor(mon)) < 0)
+            goto cleanup;
+
+        /* Fill microcodeVersion with a "random" value which is the file
+         * length to provide a reproducible number for testing.
+         */
+        virQEMUCapsSetMicrocodeVersion(capsActual, virFileLength(repliesFile, -1));
+    }
 
     if (!(actual = virQEMUCapsFormatCache(capsActual, 0, 0)))
         goto cleanup;
diff --git a/tests/qemucapsprobe.c b/tests/qemucapsprobe.c
index 561c5d7c14..03bf81d3bd 100644
--- a/tests/qemucapsprobe.c
+++ b/tests/qemucapsprobe.c
@@ -71,7 +71,7 @@ main(int argc, char **argv)
         return EXIT_FAILURE;
 
     if (!(caps = virQEMUCapsNewForBinaryInternal(NULL, argv[1], "/tmp", NULL,
-                                                 -1, -1, true)))
+                                                 -1, -1, 0, true)))
         return EXIT_FAILURE;
 
     virObjectUnref(caps);
diff --git a/tests/testutilsqemu.c b/tests/testutilsqemu.c
index 4cc482dfb0..e0fb97fba1 100644
--- a/tests/testutilsqemu.c
+++ b/tests/testutilsqemu.c
@@ -600,7 +600,7 @@ int qemuTestDriverInit(virQEMUDriver *driver)
 
     /* Using /dev/null for libDir and cacheDir automatically produces errors
      * upon attempt to use any of them */
-    driver->qemuCapsCache = virQEMUCapsCacheNew("/dev/null", "/dev/null", 0, 0);
+    driver->qemuCapsCache = virQEMUCapsCacheNew("/dev/null", "/dev/null", 0, 0, 0);
     if (!driver->qemuCapsCache)
         goto error;
 
-- 
2.15.1