134 lines
4.3 KiB
Diff
134 lines
4.3 KiB
Diff
From c628c42493170bfd70f30d9fb56d0067e6e4828a Mon Sep 17 00:00:00 2001
|
|
From: Paolo Bonzini <pbonzini@redhat.com>
|
|
Date: Tue, 19 Jun 2018 16:47:20 +0100
|
|
Subject: [PATCH 15/19] conf: include x86 microcode version in virsh
|
|
capabiltiies
|
|
|
|
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.
|
|
|
|
In order to track the x86 microcode version in the QEMU capabilities,
|
|
we have to fetch it and store it in the host CPU. This also makes the
|
|
version visible in "virsh capabilities", which is a nice side effect.
|
|
|
|
CVE-2017-5715
|
|
|
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
|
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
|
|
---
|
|
src/conf/cpu_conf.c | 14 ++++++++++++++
|
|
src/conf/cpu_conf.h | 1 +
|
|
src/cpu/cpu_x86.c | 9 +++++++++
|
|
3 files changed, 24 insertions(+)
|
|
|
|
diff --git a/src/conf/cpu_conf.c b/src/conf/cpu_conf.c
|
|
index c21d11d244..3f3c25320e 100644
|
|
--- a/src/conf/cpu_conf.c
|
|
+++ b/src/conf/cpu_conf.c
|
|
@@ -127,6 +127,7 @@ virCPUDefCopyModelFilter(virCPUDefPtr dst,
|
|
VIR_STRDUP(dst->vendor_id, src->vendor_id) < 0 ||
|
|
VIR_ALLOC_N(dst->features, src->nfeatures) < 0)
|
|
return -1;
|
|
+ dst->microcodeVersion = src->microcodeVersion;
|
|
dst->nfeatures_max = src->nfeatures;
|
|
dst->nfeatures = 0;
|
|
|
|
@@ -178,6 +179,7 @@ virCPUDefStealModel(virCPUDefPtr dst,
|
|
|
|
VIR_STEAL_PTR(dst->model, src->model);
|
|
VIR_STEAL_PTR(dst->features, src->features);
|
|
+ dst->microcodeVersion = src->microcodeVersion;
|
|
dst->nfeatures_max = src->nfeatures_max;
|
|
src->nfeatures_max = 0;
|
|
dst->nfeatures = src->nfeatures;
|
|
@@ -379,6 +381,14 @@ virCPUDefParseXML(xmlXPathContextPtr ctxt,
|
|
goto cleanup;
|
|
}
|
|
VIR_FREE(arch);
|
|
+
|
|
+ if (virXPathBoolean("boolean(./microcode[1]/@version)", ctxt) > 0 &&
|
|
+ virXPathUInt("string(./microcode[1]/@version)", ctxt,
|
|
+ &def->microcodeVersion) < 0) {
|
|
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
+ _("invalid microcode version"));
|
|
+ goto cleanup;
|
|
+ }
|
|
}
|
|
|
|
if (!(def->model = virXPathString("string(./model[1])", ctxt)) &&
|
|
@@ -723,6 +733,10 @@ virCPUDefFormatBuf(virBufferPtr buf,
|
|
if (formatModel && def->vendor)
|
|
virBufferEscapeString(buf, "<vendor>%s</vendor>\n", def->vendor);
|
|
|
|
+ if (def->type == VIR_CPU_TYPE_HOST && def->microcodeVersion)
|
|
+ virBufferAsprintf(buf, "<microcode version='%u'/>\n",
|
|
+ def->microcodeVersion);
|
|
+
|
|
if (def->sockets && def->cores && def->threads) {
|
|
virBufferAddLit(buf, "<topology");
|
|
virBufferAsprintf(buf, " sockets='%u'", def->sockets);
|
|
diff --git a/src/conf/cpu_conf.h b/src/conf/cpu_conf.h
|
|
index b44974f47e..a30ecf8681 100644
|
|
--- a/src/conf/cpu_conf.h
|
|
+++ b/src/conf/cpu_conf.h
|
|
@@ -133,6 +133,7 @@ struct _virCPUDef {
|
|
char *vendor_id; /* vendor id returned by CPUID in the guest */
|
|
int fallback; /* enum virCPUFallback */
|
|
char *vendor;
|
|
+ unsigned int microcodeVersion;
|
|
unsigned int sockets;
|
|
unsigned int cores;
|
|
unsigned int threads;
|
|
diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
|
|
index 0cb0dcacb3..41aaa61c35 100644
|
|
--- a/src/cpu/cpu_x86.c
|
|
+++ b/src/cpu/cpu_x86.c
|
|
@@ -33,6 +33,7 @@
|
|
#include "virbuffer.h"
|
|
#include "virendian.h"
|
|
#include "virstring.h"
|
|
+#include "virhostcpu.h"
|
|
|
|
#define VIR_FROM_THIS VIR_FROM_CPU
|
|
|
|
@@ -153,6 +154,8 @@ struct _virCPUx86Map {
|
|
};
|
|
|
|
static virCPUx86MapPtr cpuMap;
|
|
+static unsigned int microcodeVersion;
|
|
+
|
|
int virCPUx86DriverOnceInit(void);
|
|
VIR_ONCE_GLOBAL_INIT(virCPUx86Driver);
|
|
|
|
@@ -1392,6 +1395,8 @@ virCPUx86DriverOnceInit(void)
|
|
if (!(cpuMap = virCPUx86LoadMap()))
|
|
return -1;
|
|
|
|
+ microcodeVersion = virHostCPUGetMicrocodeVersion();
|
|
+
|
|
return 0;
|
|
}
|
|
|
|
@@ -2409,6 +2414,9 @@ virCPUx86GetHost(virCPUDefPtr cpu,
|
|
virCPUDataPtr cpuData = NULL;
|
|
int ret = -1;
|
|
|
|
+ if (virCPUx86DriverInitialize() < 0)
|
|
+ goto cleanup;
|
|
+
|
|
if (!(cpuData = virCPUDataNew(archs[0])))
|
|
goto cleanup;
|
|
|
|
@@ -2417,6 +2425,7 @@ virCPUx86GetHost(virCPUDefPtr cpu,
|
|
goto cleanup;
|
|
|
|
ret = x86DecodeCPUData(cpu, cpuData, models, nmodels, NULL);
|
|
+ cpu->microcodeVersion = microcodeVersion;
|
|
|
|
cleanup:
|
|
virCPUx86DataFree(cpuData);
|
|
--
|
|
2.17.0
|
|
|