|
|
4cd28d |
From a2fe4ef20df702070ffec676172c19e6c89b8312 Mon Sep 17 00:00:00 2001
|
|
|
4cd28d |
Message-Id: <a2fe4ef20df702070ffec676172c19e6c89b8312@dist-git>
|
|
|
4cd28d |
From: Paolo Bonzini <pbonzini@redhat.com>
|
|
|
4cd28d |
Date: Tue, 12 Dec 2017 16:23:40 +0100
|
|
|
4cd28d |
Subject: [PATCH] conf: include x86 microcode version in virsh capabiltiies
|
|
|
4cd28d |
|
|
|
4cd28d |
A microcode update can cause the CPUID bits to change; an example
|
|
|
4cd28d |
from the past was the update that disabled TSX on several Haswell and
|
|
|
4cd28d |
Broadwell machines.
|
|
|
4cd28d |
|
|
|
4cd28d |
In order to track the x86 microcode version in the QEMU capabilities,
|
|
|
4cd28d |
we have to fetch it and store it in the host CPU. This also makes the
|
|
|
4cd28d |
version visible in "virsh capabilities", which is a nice side effect.
|
|
|
4cd28d |
|
|
|
4cd28d |
CVE-2017-5715
|
|
|
4cd28d |
|
|
|
4cd28d |
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
|
|
4cd28d |
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
|
|
|
4cd28d |
|
|
|
4cd28d |
Conflicts:
|
|
|
4cd28d |
src/cpu/cpu_x86.c
|
|
|
4cd28d |
- context; x86DecodeCPUData has more parameters in 7.4
|
|
|
4cd28d |
---
|
|
|
4cd28d |
src/conf/capabilities.c | 12 ++++++++++++
|
|
|
4cd28d |
src/conf/capabilities.h | 2 ++
|
|
|
4cd28d |
src/conf/cpu_conf.c | 14 ++++++++++++++
|
|
|
4cd28d |
src/conf/cpu_conf.h | 1 +
|
|
|
4cd28d |
src/cpu/cpu_x86.c | 9 +++++++++
|
|
|
4cd28d |
src/libvirt_private.syms | 1 +
|
|
|
4cd28d |
6 files changed, 39 insertions(+)
|
|
|
4cd28d |
|
|
|
4cd28d |
diff --git a/src/conf/capabilities.c b/src/conf/capabilities.c
|
|
|
4cd28d |
index 08907aced1..fad6cc1c07 100644
|
|
|
4cd28d |
--- a/src/conf/capabilities.c
|
|
|
4cd28d |
+++ b/src/conf/capabilities.c
|
|
|
4cd28d |
@@ -355,6 +355,18 @@ virCapabilitiesAddHostNUMACell(virCapsPtr caps,
|
|
|
4cd28d |
}
|
|
|
4cd28d |
|
|
|
4cd28d |
|
|
|
4cd28d |
+/**
|
|
|
4cd28d |
+ * virCapabilitiesGetMicrocodeVersion:
|
|
|
4cd28d |
+ * @caps: capabilities to access
|
|
|
4cd28d |
+ *
|
|
|
4cd28d |
+ * Get host CPU microcode version, or 0 if unavailable
|
|
|
4cd28d |
+ */
|
|
|
4cd28d |
+unsigned int
|
|
|
4cd28d |
+virCapabilitiesGetMicrocodeVersion(virCapsPtr caps)
|
|
|
4cd28d |
+{
|
|
|
4cd28d |
+ return caps->host.cpu ? caps->host.cpu->microcodeVersion : 0;
|
|
|
4cd28d |
+}
|
|
|
4cd28d |
+
|
|
|
4cd28d |
/**
|
|
|
4cd28d |
* virCapabilitiesSetHostCPU:
|
|
|
4cd28d |
* @caps: capabilities to extend
|
|
|
4cd28d |
diff --git a/src/conf/capabilities.h b/src/conf/capabilities.h
|
|
|
4cd28d |
index d10eef3afd..75e0748e9e 100644
|
|
|
4cd28d |
--- a/src/conf/capabilities.h
|
|
|
4cd28d |
+++ b/src/conf/capabilities.h
|
|
|
4cd28d |
@@ -299,6 +299,8 @@ virBitmapPtr virCapabilitiesGetCpusForNodemask(virCapsPtr caps,
|
|
|
4cd28d |
|
|
|
4cd28d |
int virCapabilitiesGetNodeInfo(virNodeInfoPtr nodeinfo);
|
|
|
4cd28d |
|
|
|
4cd28d |
+unsigned int virCapabilitiesGetMicrocodeVersion(virCapsPtr caps);
|
|
|
4cd28d |
+
|
|
|
4cd28d |
int virCapabilitiesInitPages(virCapsPtr caps);
|
|
|
4cd28d |
|
|
|
4cd28d |
int virCapabilitiesInitNUMA(virCapsPtr caps);
|
|
|
4cd28d |
diff --git a/src/conf/cpu_conf.c b/src/conf/cpu_conf.c
|
|
|
4cd28d |
index e570dffcd2..239f671fa7 100644
|
|
|
4cd28d |
--- a/src/conf/cpu_conf.c
|
|
|
4cd28d |
+++ b/src/conf/cpu_conf.c
|
|
|
4cd28d |
@@ -127,6 +127,7 @@ virCPUDefCopyModelFilter(virCPUDefPtr dst,
|
|
|
4cd28d |
VIR_STRDUP(dst->vendor_id, src->vendor_id) < 0 ||
|
|
|
4cd28d |
VIR_ALLOC_N(dst->features, src->nfeatures) < 0)
|
|
|
4cd28d |
return -1;
|
|
|
4cd28d |
+ dst->microcodeVersion = src->microcodeVersion;
|
|
|
4cd28d |
dst->nfeatures_max = src->nfeatures;
|
|
|
4cd28d |
dst->nfeatures = 0;
|
|
|
4cd28d |
|
|
|
4cd28d |
@@ -178,6 +179,7 @@ virCPUDefStealModel(virCPUDefPtr dst,
|
|
|
4cd28d |
|
|
|
4cd28d |
VIR_STEAL_PTR(dst->model, src->model);
|
|
|
4cd28d |
VIR_STEAL_PTR(dst->features, src->features);
|
|
|
4cd28d |
+ dst->microcodeVersion = src->microcodeVersion;
|
|
|
4cd28d |
dst->nfeatures_max = src->nfeatures_max;
|
|
|
4cd28d |
src->nfeatures_max = 0;
|
|
|
4cd28d |
dst->nfeatures = src->nfeatures;
|
|
|
4cd28d |
@@ -379,6 +381,14 @@ virCPUDefParseXML(xmlXPathContextPtr ctxt,
|
|
|
4cd28d |
goto cleanup;
|
|
|
4cd28d |
}
|
|
|
4cd28d |
VIR_FREE(arch);
|
|
|
4cd28d |
+
|
|
|
4cd28d |
+ if (virXPathBoolean("boolean(./microcode[1]/@version)", ctxt) > 0 &&
|
|
|
4cd28d |
+ virXPathUInt("string(./microcode[1]/@version)", ctxt,
|
|
|
4cd28d |
+ &def->microcodeVersion) < 0) {
|
|
|
4cd28d |
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
4cd28d |
+ _("invalid microcode version"));
|
|
|
4cd28d |
+ goto cleanup;
|
|
|
4cd28d |
+ }
|
|
|
4cd28d |
}
|
|
|
4cd28d |
|
|
|
4cd28d |
if (!(def->model = virXPathString("string(./model[1])", ctxt)) &&
|
|
|
4cd28d |
@@ -720,6 +730,10 @@ virCPUDefFormatBuf(virBufferPtr buf,
|
|
|
4cd28d |
if (formatModel && def->vendor)
|
|
|
4cd28d |
virBufferEscapeString(buf, "<vendor>%s</vendor>\n", def->vendor);
|
|
|
4cd28d |
|
|
|
4cd28d |
+ if (def->type == VIR_CPU_TYPE_HOST && def->microcodeVersion)
|
|
|
4cd28d |
+ virBufferAsprintf(buf, "<microcode version='%u'/>\n",
|
|
|
4cd28d |
+ def->microcodeVersion);
|
|
|
4cd28d |
+
|
|
|
4cd28d |
if (def->sockets && def->cores && def->threads) {
|
|
|
4cd28d |
virBufferAddLit(buf, "
|
|
|
4cd28d |
virBufferAsprintf(buf, " sockets='%u'", def->sockets);
|
|
|
4cd28d |
diff --git a/src/conf/cpu_conf.h b/src/conf/cpu_conf.h
|
|
|
4cd28d |
index 1978814d36..1a13ae6e46 100644
|
|
|
4cd28d |
--- a/src/conf/cpu_conf.h
|
|
|
4cd28d |
+++ b/src/conf/cpu_conf.h
|
|
|
4cd28d |
@@ -133,6 +133,7 @@ struct _virCPUDef {
|
|
|
4cd28d |
char *vendor_id; /* vendor id returned by CPUID in the guest */
|
|
|
4cd28d |
int fallback; /* enum virCPUFallback */
|
|
|
4cd28d |
char *vendor;
|
|
|
4cd28d |
+ unsigned int microcodeVersion;
|
|
|
4cd28d |
unsigned int sockets;
|
|
|
4cd28d |
unsigned int cores;
|
|
|
4cd28d |
unsigned int threads;
|
|
|
4cd28d |
diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
|
|
|
4cd28d |
index 8af0a1a2b7..efef7f235d 100644
|
|
|
4cd28d |
--- a/src/cpu/cpu_x86.c
|
|
|
4cd28d |
+++ b/src/cpu/cpu_x86.c
|
|
|
4cd28d |
@@ -33,6 +33,7 @@
|
|
|
4cd28d |
#include "virbuffer.h"
|
|
|
4cd28d |
#include "virendian.h"
|
|
|
4cd28d |
#include "virstring.h"
|
|
|
4cd28d |
+#include "virhostcpu.h"
|
|
|
4cd28d |
|
|
|
4cd28d |
#define VIR_FROM_THIS VIR_FROM_CPU
|
|
|
4cd28d |
|
|
|
4cd28d |
@@ -153,6 +154,8 @@ struct _virCPUx86Map {
|
|
|
4cd28d |
};
|
|
|
4cd28d |
|
|
|
4cd28d |
static virCPUx86MapPtr cpuMap;
|
|
|
4cd28d |
+static unsigned int microcodeVersion;
|
|
|
4cd28d |
+
|
|
|
4cd28d |
int virCPUx86DriverOnceInit(void);
|
|
|
4cd28d |
VIR_ONCE_GLOBAL_INIT(virCPUx86Driver);
|
|
|
4cd28d |
|
|
|
4cd28d |
@@ -1391,6 +1394,8 @@ virCPUx86DriverOnceInit(void)
|
|
|
4cd28d |
if (!(cpuMap = virCPUx86LoadMap()))
|
|
|
4cd28d |
return -1;
|
|
|
4cd28d |
|
|
|
4cd28d |
+ microcodeVersion = virHostCPUGetMicrocodeVersion();
|
|
|
4cd28d |
+
|
|
|
4cd28d |
return 0;
|
|
|
4cd28d |
}
|
|
|
4cd28d |
|
|
|
4cd28d |
@@ -2408,6 +2413,9 @@ virCPUx86GetHost(virCPUDefPtr cpu,
|
|
|
4cd28d |
virCPUDataPtr cpuData = NULL;
|
|
|
4cd28d |
int ret = -1;
|
|
|
4cd28d |
|
|
|
4cd28d |
+ if (virCPUx86DriverInitialize() < 0)
|
|
|
4cd28d |
+ goto cleanup;
|
|
|
4cd28d |
+
|
|
|
4cd28d |
if (!(cpuData = virCPUDataNew(archs[0])))
|
|
|
4cd28d |
goto cleanup;
|
|
|
4cd28d |
|
|
|
4cd28d |
@@ -2416,6 +2424,7 @@ virCPUx86GetHost(virCPUDefPtr cpu,
|
|
|
4cd28d |
goto cleanup;
|
|
|
4cd28d |
|
|
|
4cd28d |
ret = x86DecodeCPUData(cpu, cpuData, models, nmodels, NULL);
|
|
|
4cd28d |
+ cpu->microcodeVersion = microcodeVersion;
|
|
|
4cd28d |
|
|
|
4cd28d |
cleanup:
|
|
|
4cd28d |
virCPUx86DataFree(cpuData);
|
|
|
4cd28d |
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
|
|
|
4cd28d |
index c50b6c2f77..c7834115fd 100644
|
|
|
4cd28d |
--- a/src/libvirt_private.syms
|
|
|
4cd28d |
+++ b/src/libvirt_private.syms
|
|
|
4cd28d |
@@ -57,6 +57,7 @@ virCapabilitiesFreeGuest;
|
|
|
4cd28d |
virCapabilitiesFreeMachines;
|
|
|
4cd28d |
virCapabilitiesFreeNUMAInfo;
|
|
|
4cd28d |
virCapabilitiesGetCpusForNodemask;
|
|
|
4cd28d |
+virCapabilitiesGetMicrocodeVersion;
|
|
|
4cd28d |
virCapabilitiesGetNodeInfo;
|
|
|
4cd28d |
virCapabilitiesHostSecModelAddBaseLabel;
|
|
|
4cd28d |
virCapabilitiesInitNUMA;
|
|
|
4cd28d |
--
|
|
|
4cd28d |
2.15.1
|
|
|
4cd28d |
|