|
|
c1c534 |
From 4f1684dd855d48517e04507edadba2fd454e4ada Mon Sep 17 00:00:00 2001
|
|
|
c1c534 |
Message-Id: <4f1684dd855d48517e04507edadba2fd454e4ada@dist-git>
|
|
|
c1c534 |
From: Paolo Bonzini <pbonzini@redhat.com>
|
|
|
c1c534 |
Date: Tue, 12 Dec 2017 16:23:40 +0100
|
|
|
c1c534 |
Subject: [PATCH] conf: include x86 microcode version in virsh capabiltiies
|
|
|
c1c534 |
|
|
|
c1c534 |
A microcode update can cause the CPUID bits to change; an example
|
|
|
c1c534 |
from the past was the update that disabled TSX on several Haswell and
|
|
|
c1c534 |
Broadwell machines.
|
|
|
c1c534 |
|
|
|
c1c534 |
In order to track the x86 microcode version in the QEMU capabilities,
|
|
|
c1c534 |
we have to fetch it and store it in the host CPU. This also makes the
|
|
|
c1c534 |
version visible in "virsh capabilities", which is a nice side effect.
|
|
|
c1c534 |
|
|
|
c1c534 |
CVE-2017-5715
|
|
|
c1c534 |
|
|
|
c1c534 |
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
|
|
c1c534 |
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
|
|
|
c1c534 |
---
|
|
|
c1c534 |
src/conf/cpu_conf.c | 14 ++++++++++++++
|
|
|
c1c534 |
src/conf/cpu_conf.h | 1 +
|
|
|
c1c534 |
src/cpu/cpu_x86.c | 9 +++++++++
|
|
|
c1c534 |
3 files changed, 24 insertions(+)
|
|
|
c1c534 |
|
|
|
c1c534 |
diff --git a/src/conf/cpu_conf.c b/src/conf/cpu_conf.c
|
|
|
c1c534 |
index 669935acf8..7e00299c66 100644
|
|
|
c1c534 |
--- a/src/conf/cpu_conf.c
|
|
|
c1c534 |
+++ b/src/conf/cpu_conf.c
|
|
|
c1c534 |
@@ -130,6 +130,7 @@ virCPUDefCopyModelFilter(virCPUDefPtr dst,
|
|
|
c1c534 |
VIR_STRDUP(dst->vendor_id, src->vendor_id) < 0 ||
|
|
|
c1c534 |
VIR_ALLOC_N(dst->features, src->nfeatures) < 0)
|
|
|
c1c534 |
return -1;
|
|
|
c1c534 |
+ dst->microcodeVersion = src->microcodeVersion;
|
|
|
c1c534 |
dst->nfeatures_max = src->nfeatures;
|
|
|
c1c534 |
dst->nfeatures = 0;
|
|
|
c1c534 |
|
|
|
c1c534 |
@@ -181,6 +182,7 @@ virCPUDefStealModel(virCPUDefPtr dst,
|
|
|
c1c534 |
|
|
|
c1c534 |
VIR_STEAL_PTR(dst->model, src->model);
|
|
|
c1c534 |
VIR_STEAL_PTR(dst->features, src->features);
|
|
|
c1c534 |
+ dst->microcodeVersion = src->microcodeVersion;
|
|
|
c1c534 |
dst->nfeatures_max = src->nfeatures_max;
|
|
|
c1c534 |
src->nfeatures_max = 0;
|
|
|
c1c534 |
dst->nfeatures = src->nfeatures;
|
|
|
c1c534 |
@@ -382,6 +384,14 @@ virCPUDefParseXML(xmlXPathContextPtr ctxt,
|
|
|
c1c534 |
goto cleanup;
|
|
|
c1c534 |
}
|
|
|
c1c534 |
VIR_FREE(arch);
|
|
|
c1c534 |
+
|
|
|
c1c534 |
+ if (virXPathBoolean("boolean(./microcode[1]/@version)", ctxt) > 0 &&
|
|
|
c1c534 |
+ virXPathUInt("string(./microcode[1]/@version)", ctxt,
|
|
|
c1c534 |
+ &def->microcodeVersion) < 0) {
|
|
|
c1c534 |
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
c1c534 |
+ _("invalid microcode version"));
|
|
|
c1c534 |
+ goto cleanup;
|
|
|
c1c534 |
+ }
|
|
|
c1c534 |
}
|
|
|
c1c534 |
|
|
|
c1c534 |
if (!(def->model = virXPathString("string(./model[1])", ctxt)) &&
|
|
|
c1c534 |
@@ -720,6 +730,10 @@ virCPUDefFormatBuf(virBufferPtr buf,
|
|
|
c1c534 |
if (formatModel && def->vendor)
|
|
|
c1c534 |
virBufferEscapeString(buf, "<vendor>%s</vendor>\n", def->vendor);
|
|
|
c1c534 |
|
|
|
c1c534 |
+ if (def->type == VIR_CPU_TYPE_HOST && def->microcodeVersion)
|
|
|
c1c534 |
+ virBufferAsprintf(buf, "<microcode version='%u'/>\n",
|
|
|
c1c534 |
+ def->microcodeVersion);
|
|
|
c1c534 |
+
|
|
|
c1c534 |
if (def->sockets && def->cores && def->threads) {
|
|
|
c1c534 |
virBufferAddLit(buf, "
|
|
|
c1c534 |
virBufferAsprintf(buf, " sockets='%u'", def->sockets);
|
|
|
c1c534 |
diff --git a/src/conf/cpu_conf.h b/src/conf/cpu_conf.h
|
|
|
c1c534 |
index d1983f5d4f..9f2e7ee264 100644
|
|
|
c1c534 |
--- a/src/conf/cpu_conf.h
|
|
|
c1c534 |
+++ b/src/conf/cpu_conf.h
|
|
|
c1c534 |
@@ -133,6 +133,7 @@ struct _virCPUDef {
|
|
|
c1c534 |
char *vendor_id; /* vendor id returned by CPUID in the guest */
|
|
|
c1c534 |
int fallback; /* enum virCPUFallback */
|
|
|
c1c534 |
char *vendor;
|
|
|
c1c534 |
+ unsigned int microcodeVersion;
|
|
|
c1c534 |
unsigned int sockets;
|
|
|
c1c534 |
unsigned int cores;
|
|
|
c1c534 |
unsigned int threads;
|
|
|
c1c534 |
diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
|
|
|
c1c534 |
index 693e571a3d..ad35532fc1 100644
|
|
|
c1c534 |
--- a/src/cpu/cpu_x86.c
|
|
|
c1c534 |
+++ b/src/cpu/cpu_x86.c
|
|
|
c1c534 |
@@ -33,6 +33,7 @@
|
|
|
c1c534 |
#include "virbuffer.h"
|
|
|
c1c534 |
#include "virendian.h"
|
|
|
c1c534 |
#include "virstring.h"
|
|
|
c1c534 |
+#include "virhostcpu.h"
|
|
|
c1c534 |
|
|
|
c1c534 |
#define VIR_FROM_THIS VIR_FROM_CPU
|
|
|
c1c534 |
|
|
|
c1c534 |
@@ -153,6 +154,8 @@ struct _virCPUx86Map {
|
|
|
c1c534 |
};
|
|
|
c1c534 |
|
|
|
c1c534 |
static virCPUx86MapPtr cpuMap;
|
|
|
c1c534 |
+static unsigned int microcodeVersion;
|
|
|
c1c534 |
+
|
|
|
c1c534 |
int virCPUx86DriverOnceInit(void);
|
|
|
c1c534 |
VIR_ONCE_GLOBAL_INIT(virCPUx86Driver);
|
|
|
c1c534 |
|
|
|
c1c534 |
@@ -1409,6 +1412,8 @@ virCPUx86DriverOnceInit(void)
|
|
|
c1c534 |
if (!(cpuMap = virCPUx86LoadMap()))
|
|
|
c1c534 |
return -1;
|
|
|
c1c534 |
|
|
|
c1c534 |
+ microcodeVersion = virHostCPUGetMicrocodeVersion();
|
|
|
c1c534 |
+
|
|
|
c1c534 |
return 0;
|
|
|
c1c534 |
}
|
|
|
c1c534 |
|
|
|
c1c534 |
@@ -2424,6 +2429,9 @@ virCPUx86GetHost(virCPUDefPtr cpu,
|
|
|
c1c534 |
virCPUDataPtr cpuData = NULL;
|
|
|
c1c534 |
int ret = -1;
|
|
|
c1c534 |
|
|
|
c1c534 |
+ if (virCPUx86DriverInitialize() < 0)
|
|
|
c1c534 |
+ goto cleanup;
|
|
|
c1c534 |
+
|
|
|
c1c534 |
if (!(cpuData = virCPUDataNew(archs[0])))
|
|
|
c1c534 |
goto cleanup;
|
|
|
c1c534 |
|
|
|
c1c534 |
@@ -2432,6 +2440,7 @@ virCPUx86GetHost(virCPUDefPtr cpu,
|
|
|
c1c534 |
goto cleanup;
|
|
|
c1c534 |
|
|
|
c1c534 |
ret = x86DecodeCPUData(cpu, cpuData, models);
|
|
|
c1c534 |
+ cpu->microcodeVersion = microcodeVersion;
|
|
|
c1c534 |
|
|
|
c1c534 |
cleanup:
|
|
|
c1c534 |
virCPUx86DataFree(cpuData);
|
|
|
c1c534 |
--
|
|
|
c1c534 |
2.15.1
|
|
|
c1c534 |
|