]> xenbits.xensource.com Git - libvirt.git/commitdiff
qemu: capabilities: force update if the microcode version does not match
authorPaolo Bonzini <pbonzini@redhat.com>
Tue, 12 Dec 2017 15:23:41 +0000 (16:23 +0100)
committerJiri Denemark <jdenemar@redhat.com>
Thu, 4 Jan 2018 15:52:03 +0000 (16:52 +0100)
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.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
32 files changed:
src/qemu/qemu_capabilities.c
src/qemu/qemu_capabilities.h
src/qemu/qemu_capspriv.h
src/qemu/qemu_driver.c
tests/qemucapabilitiesdata/caps_1.2.2.x86_64.xml
tests/qemucapabilitiesdata/caps_1.3.1.x86_64.xml
tests/qemucapabilitiesdata/caps_1.4.2.x86_64.xml
tests/qemucapabilitiesdata/caps_1.5.3.x86_64.xml
tests/qemucapabilitiesdata/caps_1.6.0.x86_64.xml
tests/qemucapabilitiesdata/caps_1.7.0.x86_64.xml
tests/qemucapabilitiesdata/caps_2.1.1.x86_64.xml
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.4.0.x86_64.xml
tests/qemucapabilitiesdata/caps_2.5.0.x86_64.xml
tests/qemucapabilitiesdata/caps_2.6.0-gicv2.aarch64.xml
tests/qemucapabilitiesdata/caps_2.6.0-gicv3.aarch64.xml
tests/qemucapabilitiesdata/caps_2.6.0.ppc64.xml
tests/qemucapabilitiesdata/caps_2.6.0.x86_64.xml
tests/qemucapabilitiesdata/caps_2.7.0.s390x.xml
tests/qemucapabilitiesdata/caps_2.7.0.x86_64.xml
tests/qemucapabilitiesdata/caps_2.8.0.s390x.xml
tests/qemucapabilitiesdata/caps_2.8.0.x86_64.xml
tests/qemucapabilitiesdata/caps_2.9.0.ppc64.xml
tests/qemucapabilitiesdata/caps_2.9.0.s390x.xml
tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml
tests/qemucapabilitiestest.c
tests/qemucapsprobe.c
tests/testutilsqemu.c

index 9673ef857b545bb20c9f1e94ba5d92807b5a812f..abf02a9b174fae672a50fd5412d16e2e0f17fbe7 100644 (file)
@@ -507,6 +507,7 @@ struct _virQEMUCaps {
     unsigned int version;
     unsigned int kvmVersion;
     unsigned int libvirtVersion;
+    unsigned int microcodeVersion;
     char *package;
 
     virArch arch;
@@ -2296,6 +2297,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;
@@ -3830,6 +3832,7 @@ struct _virQEMUCapsCachePriv {
     uid_t runUid;
     gid_t runGid;
     virArch hostArch;
+    unsigned int microcodeVersion;
 };
 typedef struct _virQEMUCapsCachePriv virQEMUCapsCachePriv;
 typedef virQEMUCapsCachePriv *virQEMUCapsCachePrivPtr;
@@ -3952,6 +3955,13 @@ virQEMUCapsLoadCache(virArch hostArch,
         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 &&
@@ -4230,6 +4240,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);
@@ -4371,6 +4384,16 @@ virQEMUCapsIsValid(void *data,
         return false;
     }
 
+    if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_KVM) &&
+        priv->microcodeVersion != qemuCaps->microcodeVersion) {
+        VIR_DEBUG("Outdated capabilities for '%s': microcode version changed "
+                  "(%u vs %u)",
+                  qemuCaps->binary,
+                  priv->microcodeVersion,
+                  qemuCaps->microcodeVersion);
+        return false;
+    }
+
     return true;
 }
 
@@ -5197,6 +5220,7 @@ virQEMUCapsNewForBinaryInternal(virArch hostArch,
                                 const char *libDir,
                                 uid_t runUid,
                                 gid_t runGid,
+                                unsigned int microcodeVersion,
                                 bool qmpOnly)
 {
     virQEMUCapsPtr qemuCaps;
@@ -5253,6 +5277,9 @@ virQEMUCapsNewForBinaryInternal(virArch hostArch,
     virQEMUCapsInitHostCPUModel(qemuCaps, hostArch, VIR_DOMAIN_VIRT_KVM);
     virQEMUCapsInitHostCPUModel(qemuCaps, hostArch, VIR_DOMAIN_VIRT_QEMU);
 
+    if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_KVM))
+        qemuCaps->microcodeVersion = microcodeVersion;
+
  cleanup:
     VIR_FREE(qmperr);
     return qemuCaps;
@@ -5274,6 +5301,7 @@ virQEMUCapsNewData(const char *binary,
                                            priv->libDir,
                                            priv->runUid,
                                            priv->runGid,
+                                           priv->microcodeVersion,
                                            false);
 }
 
@@ -5356,7 +5384,8 @@ virFileCachePtr
 virQEMUCapsCacheNew(const char *libDir,
                     const char *cacheDir,
                     uid_t runUid,
-                    gid_t runGid)
+                    gid_t runGid,
+                    unsigned int microcodeVersion)
 {
     char *capsCacheDir = NULL;
     virFileCachePtr cache = NULL;
@@ -5379,6 +5408,7 @@ virQEMUCapsCacheNew(const char *libDir,
 
     priv->runUid = runUid;
     priv->runGid = runGid;
+    priv->microcodeVersion = microcodeVersion;
 
  cleanup:
     VIR_FREE(capsCacheDir);
@@ -5856,3 +5886,11 @@ virQEMUCapsFillDomainCaps(virCapsPtr caps,
         return -1;
     return 0;
 }
+
+
+void
+virQEMUCapsSetMicrocodeVersion(virQEMUCapsPtr qemuCaps,
+                               unsigned int microcodeVersion)
+{
+    qemuCaps->microcodeVersion = microcodeVersion;
+}
index e73dbaa5576da16942099472f032936da4be4a35..8bb0b6a2327e8d766eba61f94a0eadc371b8ce7e 100644 (file)
@@ -520,8 +520,10 @@ void virQEMUCapsFilterByMachineType(virQEMUCapsPtr qemuCaps,
                                     const char *machineType);
 
 virFileCachePtr virQEMUCapsCacheNew(const char *libDir,
-                                        const char *cacheDir,
-                                        uid_t uid, gid_t gid);
+                                    const char *cacheDir,
+                                    uid_t uid,
+                                    gid_t gid,
+                                    unsigned int microcodeVersion);
 virQEMUCapsPtr virQEMUCapsCacheLookup(virFileCachePtr cache,
                                       const char *binary);
 virQEMUCapsPtr virQEMUCapsCacheLookupCopy(virFileCachePtr cache,
index 219daa36294db2b0427db78547b1876a93f697d1..98d163b9202063f3bde38f9ee802fda8d4a4b25a 100644 (file)
@@ -36,6 +36,7 @@ virQEMUCapsNewForBinaryInternal(virArch hostArch,
                                 const char *libDir,
                                 uid_t runUid,
                                 gid_t runGid,
+                                unsigned int microcodeVersion,
                                 bool qmpOnly);
 
 int virQEMUCapsLoadCache(virArch hostArch,
@@ -102,4 +103,8 @@ int
 virQEMUCapsProbeQMPCPUDefinitions(virQEMUCapsPtr qemuCaps,
                                   qemuMonitorPtr mon,
                                   bool tcg);
+
+void
+virQEMUCapsSetMicrocodeVersion(virQEMUCapsPtr qemuCaps,
+                               unsigned int microcodeVersion);
 #endif
index 97b194b057038f8b7a83f36483cd5a9a1a9b8680..1ebc1177f889633a2922b63b3b9bbeaaafc3cf0b 100644 (file)
@@ -633,6 +633,8 @@ qemuStateInitialize(bool privileged,
     char *hugepagePath = NULL;
     char *memoryBackingPath = NULL;
     size_t i;
+    virCPUDefPtr hostCPU = NULL;
+    unsigned int microcodeVersion = 0;
 
     if (VIR_ALLOC(qemu_driver) < 0)
         return -1;
@@ -855,10 +857,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;
 
index d560811ab73feda089cc5a346f4578f08e0b8f77..3001d487c6bd9cac5245ae16fe51989287e90c07 100644 (file)
   <flag name='isa-serial'/>
   <version>1002002</version>
   <kvmVersion>0</kvmVersion>
+  <microcodeVersion>26900</microcodeVersion>
   <package></package>
   <arch>x86_64</arch>
   <cpu type='kvm' name='qemu64'/>
index 576475f7fa35ca90248ad09514bf6b5c7f0435fa..283f30ef07eb5dfb3b61a64148e9b64629669574 100644 (file)
   <flag name='isa-serial'/>
   <version>1003001</version>
   <kvmVersion>0</kvmVersion>
+  <microcodeVersion>30198</microcodeVersion>
   <package></package>
   <arch>x86_64</arch>
   <cpu type='kvm' name='qemu64'/>
index 0c271d3e41a9396d0888d6b0adfb7253fde59aad..200069ae868b5fcddc8ec94366301a821cf7a923 100644 (file)
   <flag name='isa-serial'/>
   <version>1004002</version>
   <kvmVersion>0</kvmVersion>
+  <microcodeVersion>30915</microcodeVersion>
   <package></package>
   <arch>x86_64</arch>
   <cpu type='kvm' name='Opteron_G5'/>
index 5c667975bf429bb2889668e6043d14985da506d4..e02c0961cd249a0e59354016c97b082286a06ca3 100644 (file)
   <flag name='isa-serial'/>
   <version>1005003</version>
   <kvmVersion>0</kvmVersion>
+  <microcodeVersion>47019</microcodeVersion>
   <package></package>
   <arch>x86_64</arch>
   <cpu type='kvm' name='Opteron_G5'/>
index 8ae07a91db40cf1bf0f16f721e087e2732a50fdc..e3896685e939bea76c4441f9a0fc83039aa1e70e 100644 (file)
   <flag name='isa-serial'/>
   <version>1006000</version>
   <kvmVersion>0</kvmVersion>
+  <microcodeVersion>45248</microcodeVersion>
   <package></package>
   <arch>x86_64</arch>
   <cpu type='kvm' name='Opteron_G5'/>
index 34bd6be1cd66f9a78b209b56587a034b71aa2c09..5b4d1ea66189c1adc90fa0a2de6009103b577a04 100644 (file)
   <flag name='isa-serial'/>
   <version>1007000</version>
   <kvmVersion>0</kvmVersion>
+  <microcodeVersion>50692</microcodeVersion>
   <package></package>
   <arch>x86_64</arch>
   <cpu type='kvm' name='Opteron_G5'/>
index 0d7c144ff7806f253a11abaeb1b83c52ad5f3ccf..200e57adac7ba6ae3eb39145f21ee8e92bd46b33 100644 (file)
   <flag name='isa-serial'/>
   <version>2001001</version>
   <kvmVersion>0</kvmVersion>
+  <microcodeVersion>59488</microcodeVersion>
   <package></package>
   <arch>x86_64</arch>
   <cpu type='kvm' name='Opteron_G5'/>
index eeb1840d3f67014a8e34ee23746eb8a1dea79832..51d19aacb194db36592cdd2db8ccf9f65372f0e3 100644 (file)
   <flag name='pl011'/>
   <version>2010000</version>
   <kvmVersion>0</kvmVersion>
+  <microcodeVersion>304138</microcodeVersion>
   <package> (v2.10.0)</package>
   <arch>aarch64</arch>
   <cpu type='kvm' name='pxa262'/>
index 1e7b95ec02e062341de5cd2e658be7ea3fb316d5..b8309f35b32a869713a0f90426c7c6b73cc6bd06 100644 (file)
   <flag name='pl011'/>
   <version>2010000</version>
   <kvmVersion>0</kvmVersion>
+  <microcodeVersion>304138</microcodeVersion>
   <package> (v2.10.0)</package>
   <arch>aarch64</arch>
   <cpu type='kvm' name='pxa262'/>
index ca55e11ebebc938745b689702bf1e4b260632bf8..c866ce3ee8e473572e8b30267cc08b2b81c06c18 100644 (file)
   <flag name='isa-serial'/>
   <version>2010000</version>
   <kvmVersion>0</kvmVersion>
+  <microcodeVersion>383421</microcodeVersion>
   <package> (v2.10.0)</package>
   <arch>ppc64</arch>
   <cpu type='kvm' name='default'/>
index 64e70f54be1a185331c87ce22c101d52944a613e..e9115d304ed4a5840d789d61c9b99b109ec1432e 100644 (file)
   <flag name='iscsi.password-secret'/>
   <version>2010000</version>
   <kvmVersion>0</kvmVersion>
+  <microcodeVersion>304153</microcodeVersion>
   <package></package>
   <arch>s390x</arch>
   <hostCPU type='kvm' model='z14-base' migratability='no'>
index 8fea70a522d7ed93e8b3c514b2b36061fe9ebb67..1687417081494b8e11de5083f26de361a77bbda3 100644 (file)
   <flag name='isa-serial'/>
   <version>2010000</version>
   <kvmVersion>0</kvmVersion>
+  <microcodeVersion>345185</microcodeVersion>
   <package> (v2.10.0)</package>
   <arch>x86_64</arch>
   <hostCPU type='kvm' model='base' migratability='yes'>
index 5007523c1f2bedfdae35382bf930d5c835322274..9b315aecf4c856865f06013fb4cc6d7ea73b051e 100644 (file)
   <flag name='isa-serial'/>
   <version>2004000</version>
   <kvmVersion>0</kvmVersion>
+  <microcodeVersion>75653</microcodeVersion>
   <package></package>
   <arch>x86_64</arch>
   <cpu type='kvm' name='Opteron_G5'/>
index a9ad292d0145bf4eba0ac5021026de0816663b28..3096eadf723b910b73b89c7354a3d706265138e1 100644 (file)
   <flag name='isa-serial'/>
   <version>2005000</version>
   <kvmVersion>0</kvmVersion>
+  <microcodeVersion>216775</microcodeVersion>
   <package></package>
   <arch>x86_64</arch>
   <cpu type='kvm' name='Opteron_G5'/>
index d3e2e18faa6922ed64de76fc7578bc95eca9ebe2..4cdd894a970e655f477545e5623320d126e637c1 100644 (file)
   <flag name='pl011'/>
   <version>2006000</version>
   <kvmVersion>0</kvmVersion>
+  <microcodeVersion>228838</microcodeVersion>
   <package></package>
   <arch>aarch64</arch>
   <cpu type='kvm' name='pxa262'/>
index bc86d03537224d34ae416985829dc80df7d1ead4..5655af7d3d0d2d2e6921cfbd43f0c95ddbcdf27b 100644 (file)
   <flag name='pl011'/>
   <version>2006000</version>
   <kvmVersion>0</kvmVersion>
+  <microcodeVersion>228838</microcodeVersion>
   <package></package>
   <arch>aarch64</arch>
   <cpu type='kvm' name='pxa262'/>
index 27d99bd93702ef42db95d851cbf78ec29c82077d..31701bb40bf93a9fa5d9076d833d88cc4081fb53 100644 (file)
   <flag name='isa-serial'/>
   <version>2006000</version>
   <kvmVersion>0</kvmVersion>
+  <microcodeVersion>263602</microcodeVersion>
   <package></package>
   <arch>ppc64</arch>
   <cpu type='kvm' name='default'/>
index 97621612ab70c913664e6c37715744ad703c9beb..6ae19ffd363035fc596054687ea909e04bbc4e3b 100644 (file)
   <flag name='isa-serial'/>
   <version>2006000</version>
   <kvmVersion>0</kvmVersion>
+  <microcodeVersion>227579</microcodeVersion>
   <package></package>
   <arch>x86_64</arch>
   <cpu type='kvm' name='Opteron_G5'/>
index c2f310cd46294a8480d5af0e784b4374a1eedd72..b6ec680d5ca5919e899cf23052d213ecd39bd437 100644 (file)
   <flag name='sclplmconsole'/>
   <version>2007000</version>
   <kvmVersion>0</kvmVersion>
+  <microcodeVersion>217559</microcodeVersion>
   <package></package>
   <arch>s390x</arch>
   <cpu type='kvm' name='host'/>
index e4ea9452c530471bf9a1b42c845940ea27f0b5e6..294ac126e591da320dbe8757575d022c2539c8ef 100644 (file)
   <flag name='isa-serial'/>
   <version>2007000</version>
   <kvmVersion>0</kvmVersion>
+  <microcodeVersion>239276</microcodeVersion>
   <package> (v2.7.0)</package>
   <arch>x86_64</arch>
   <cpu type='kvm' name='Opteron_G5'/>
index f6e024dc617ffab4c6400483a46ab0812625e5ad..d788ad206e3ef8b8ef2828723a42cabb78d2f894 100644 (file)
   <flag name='sclplmconsole'/>
   <version>2007093</version>
   <kvmVersion>0</kvmVersion>
+  <microcodeVersion>242460</microcodeVersion>
   <package></package>
   <arch>s390x</arch>
   <hostCPU type='kvm' model='zEC12.2-base' migratability='no'>
index c6d3e21d5c1b7edaebf0e332c11c6a5fcfc14292..156563d99ae7d5ccf94d888b9ab1f88bba083fbf 100644 (file)
   <flag name='isa-serial'/>
   <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'/>
index 96aa5d59fcc45ed5f0cf770858d53d1f95de04ab..cca643a3a5b7468f2631736d3f5273f5c3e3957e 100644 (file)
   <flag name='isa-serial'/>
   <version>2009000</version>
   <kvmVersion>0</kvmVersion>
+  <microcodeVersion>347135</microcodeVersion>
   <package> (v2.9.0)</package>
   <arch>ppc64</arch>
   <cpu type='kvm' name='default'/>
index baac0b7aeb272fb1de425f22c975d330d94b9f09..5d0f0aa6c6ce73ffb36ac6c24bf73645d4d9a1c7 100644 (file)
   <flag name='iscsi.password-secret'/>
   <version>2009000</version>
   <kvmVersion>0</kvmVersion>
+  <microcodeVersion>265878</microcodeVersion>
   <package></package>
   <arch>s390x</arch>
   <hostCPU type='kvm' model='z13.2-base' migratability='no'>
index 9f489129fbed79e9a4ba40ed91c35aa25fe90e9c..907f543ee38c815112037a255f7bea33a3903ea0 100644 (file)
   <flag name='isa-serial'/>
   <version>2009000</version>
   <kvmVersion>0</kvmVersion>
+  <microcodeVersion>321194</microcodeVersion>
   <package> (v2.9.0)</package>
   <arch>x86_64</arch>
   <hostCPU type='kvm' model='base' migratability='yes'>
index dde5f767b8b3cf8a35e9f2d2b203364dbcb3f616..87807b413509d37ee6cfe01202205425a910cbcc 100644 (file)
@@ -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)))
         goto cleanup;
index 4b8d6229b4f70551c9456f9610f10e0a6d068d44..a5f5a38b169ab35c670e059d7f7b21ca5396e016 100644 (file)
@@ -72,7 +72,7 @@ main(int argc, char **argv)
         return EXIT_FAILURE;
 
     if (!(caps = virQEMUCapsNewForBinaryInternal(VIR_ARCH_NONE, argv[1], "/tmp",
-                                                 -1, -1, true)))
+                                                 -1, -1, 0, true)))
         return EXIT_FAILURE;
 
     virObjectUnref(caps);
index 2c7124bf26f2207e74f027f1ef4030b02c75c74e..f8182033fc486a249382859d2836d0bc7844f7a1 100644 (file)
@@ -603,7 +603,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;