|
|
c480ed |
From 808b0c73134cd3c6a7fdd387fd9654dbd41356ac Mon Sep 17 00:00:00 2001
|
|
|
c480ed |
Message-Id: <808b0c73134cd3c6a7fdd387fd9654dbd41356ac@dist-git>
|
|
|
c480ed |
From: Jiri Denemark <jdenemar@redhat.com>
|
|
|
c480ed |
Date: Fri, 21 Jun 2019 09:25:39 +0200
|
|
|
c480ed |
Subject: [PATCH] cpu_x86: Add support for storing MSR features in CPU map
|
|
|
c480ed |
MIME-Version: 1.0
|
|
|
c480ed |
Content-Type: text/plain; charset=UTF-8
|
|
|
c480ed |
Content-Transfer-Encoding: 8bit
|
|
|
c480ed |
|
|
|
c480ed |
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
|
|
|
c480ed |
Reviewed-by: Ján Tomko <jtomko@redhat.com>
|
|
|
c480ed |
(cherry picked from commit fcf4846a6bb902a5cd2230fff2a1e7591dcb7456)
|
|
|
c480ed |
|
|
|
c480ed |
https://bugzilla.redhat.com/show_bug.cgi?id=1697627
|
|
|
c480ed |
|
|
|
c480ed |
Conflicts:
|
|
|
c480ed |
tests/cputestdata/cpu-cpuid.py
|
|
|
c480ed |
- no need to update this script downstream
|
|
|
c480ed |
|
|
|
c480ed |
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
|
|
|
c480ed |
Message-Id: <0c37dabaaa6c2559b48918ca55e170750fe34ea0.1561068591.git.jdenemar@redhat.com>
|
|
|
c480ed |
Reviewed-by: Ján Tomko <jtomko@redhat.com>
|
|
|
c480ed |
---
|
|
|
c480ed |
src/cpu/cpu_x86.c | 127 +++++++++++++++++++++++++++++++++++++----
|
|
|
c480ed |
src/cpu/cpu_x86_data.h | 10 ++++
|
|
|
c480ed |
2 files changed, 125 insertions(+), 12 deletions(-)
|
|
|
c480ed |
|
|
|
c480ed |
diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
|
|
|
c480ed |
index e6da974b31..49562944c1 100644
|
|
|
c480ed |
--- a/src/cpu/cpu_x86.c
|
|
|
c480ed |
+++ b/src/cpu/cpu_x86.c
|
|
|
c480ed |
@@ -197,6 +197,8 @@ virCPUx86DataItemMatch(const virCPUx86DataItem *item1,
|
|
|
c480ed |
{
|
|
|
c480ed |
const virCPUx86CPUID *cpuid1;
|
|
|
c480ed |
const virCPUx86CPUID *cpuid2;
|
|
|
c480ed |
+ const virCPUx86MSR *msr1;
|
|
|
c480ed |
+ const virCPUx86MSR *msr2;
|
|
|
c480ed |
|
|
|
c480ed |
switch (item1->type) {
|
|
|
c480ed |
case VIR_CPU_X86_DATA_CPUID:
|
|
|
c480ed |
@@ -207,6 +209,12 @@ virCPUx86DataItemMatch(const virCPUx86DataItem *item1,
|
|
|
c480ed |
cpuid1->ecx == cpuid2->ecx &&
|
|
|
c480ed |
cpuid1->edx == cpuid2->edx);
|
|
|
c480ed |
|
|
|
c480ed |
+ case VIR_CPU_X86_DATA_MSR:
|
|
|
c480ed |
+ msr1 = &item1->data.msr;
|
|
|
c480ed |
+ msr2 = &item2->data.msr;
|
|
|
c480ed |
+ return (msr1->eax == msr2->eax &&
|
|
|
c480ed |
+ msr1->edx == msr2->edx);
|
|
|
c480ed |
+
|
|
|
c480ed |
case VIR_CPU_X86_DATA_NONE:
|
|
|
c480ed |
default:
|
|
|
c480ed |
return false;
|
|
|
c480ed |
@@ -220,6 +228,8 @@ virCPUx86DataItemMatchMasked(const virCPUx86DataItem *item,
|
|
|
c480ed |
{
|
|
|
c480ed |
const virCPUx86CPUID *cpuid;
|
|
|
c480ed |
const virCPUx86CPUID *cpuidMask;
|
|
|
c480ed |
+ const virCPUx86MSR *msr;
|
|
|
c480ed |
+ const virCPUx86MSR *msrMask;
|
|
|
c480ed |
|
|
|
c480ed |
switch (item->type) {
|
|
|
c480ed |
case VIR_CPU_X86_DATA_CPUID:
|
|
|
c480ed |
@@ -230,6 +240,12 @@ virCPUx86DataItemMatchMasked(const virCPUx86DataItem *item,
|
|
|
c480ed |
(cpuid->ecx & cpuidMask->ecx) == cpuidMask->ecx &&
|
|
|
c480ed |
(cpuid->edx & cpuidMask->edx) == cpuidMask->edx);
|
|
|
c480ed |
|
|
|
c480ed |
+ case VIR_CPU_X86_DATA_MSR:
|
|
|
c480ed |
+ msr = &item->data.msr;
|
|
|
c480ed |
+ msrMask = &mask->data.msr;
|
|
|
c480ed |
+ return ((msr->eax & msrMask->eax) == msrMask->eax &&
|
|
|
c480ed |
+ (msr->edx & msrMask->edx) == msrMask->edx);
|
|
|
c480ed |
+
|
|
|
c480ed |
case VIR_CPU_X86_DATA_NONE:
|
|
|
c480ed |
default:
|
|
|
c480ed |
return false;
|
|
|
c480ed |
@@ -243,6 +259,8 @@ virCPUx86DataItemSetBits(virCPUx86DataItemPtr item,
|
|
|
c480ed |
{
|
|
|
c480ed |
virCPUx86CPUIDPtr cpuid;
|
|
|
c480ed |
const virCPUx86CPUID *cpuidMask;
|
|
|
c480ed |
+ virCPUx86MSRPtr msr;
|
|
|
c480ed |
+ const virCPUx86MSR *msrMask;
|
|
|
c480ed |
|
|
|
c480ed |
if (!mask)
|
|
|
c480ed |
return;
|
|
|
c480ed |
@@ -257,6 +275,13 @@ virCPUx86DataItemSetBits(virCPUx86DataItemPtr item,
|
|
|
c480ed |
cpuid->edx |= cpuidMask->edx;
|
|
|
c480ed |
break;
|
|
|
c480ed |
|
|
|
c480ed |
+ case VIR_CPU_X86_DATA_MSR:
|
|
|
c480ed |
+ msr = &item->data.msr;
|
|
|
c480ed |
+ msrMask = &mask->data.msr;
|
|
|
c480ed |
+ msr->eax |= msrMask->eax;
|
|
|
c480ed |
+ msr->edx |= msrMask->edx;
|
|
|
c480ed |
+ break;
|
|
|
c480ed |
+
|
|
|
c480ed |
case VIR_CPU_X86_DATA_NONE:
|
|
|
c480ed |
default:
|
|
|
c480ed |
break;
|
|
|
c480ed |
@@ -270,6 +295,8 @@ virCPUx86DataItemClearBits(virCPUx86DataItemPtr item,
|
|
|
c480ed |
{
|
|
|
c480ed |
virCPUx86CPUIDPtr cpuid;
|
|
|
c480ed |
const virCPUx86CPUID *cpuidMask;
|
|
|
c480ed |
+ virCPUx86MSRPtr msr;
|
|
|
c480ed |
+ const virCPUx86MSR *msrMask;
|
|
|
c480ed |
|
|
|
c480ed |
if (!mask)
|
|
|
c480ed |
return;
|
|
|
c480ed |
@@ -284,6 +311,13 @@ virCPUx86DataItemClearBits(virCPUx86DataItemPtr item,
|
|
|
c480ed |
cpuid->edx &= ~cpuidMask->edx;
|
|
|
c480ed |
break;
|
|
|
c480ed |
|
|
|
c480ed |
+ case VIR_CPU_X86_DATA_MSR:
|
|
|
c480ed |
+ msr = &item->data.msr;
|
|
|
c480ed |
+ msrMask = &mask->data.msr;
|
|
|
c480ed |
+ msr->eax &= ~msrMask->eax;
|
|
|
c480ed |
+ msr->edx &= ~msrMask->edx;
|
|
|
c480ed |
+ break;
|
|
|
c480ed |
+
|
|
|
c480ed |
case VIR_CPU_X86_DATA_NONE:
|
|
|
c480ed |
default:
|
|
|
c480ed |
break;
|
|
|
c480ed |
@@ -297,6 +331,8 @@ virCPUx86DataItemAndBits(virCPUx86DataItemPtr item,
|
|
|
c480ed |
{
|
|
|
c480ed |
virCPUx86CPUIDPtr cpuid;
|
|
|
c480ed |
const virCPUx86CPUID *cpuidMask;
|
|
|
c480ed |
+ virCPUx86MSRPtr msr;
|
|
|
c480ed |
+ const virCPUx86MSR *msrMask;
|
|
|
c480ed |
|
|
|
c480ed |
if (!mask)
|
|
|
c480ed |
return;
|
|
|
c480ed |
@@ -311,6 +347,13 @@ virCPUx86DataItemAndBits(virCPUx86DataItemPtr item,
|
|
|
c480ed |
cpuid->edx &= cpuidMask->edx;
|
|
|
c480ed |
break;
|
|
|
c480ed |
|
|
|
c480ed |
+ case VIR_CPU_X86_DATA_MSR:
|
|
|
c480ed |
+ msr = &item->data.msr;
|
|
|
c480ed |
+ msrMask = &mask->data.msr;
|
|
|
c480ed |
+ msr->eax &= msrMask->eax;
|
|
|
c480ed |
+ msr->edx &= msrMask->edx;
|
|
|
c480ed |
+ break;
|
|
|
c480ed |
+
|
|
|
c480ed |
case VIR_CPU_X86_DATA_NONE:
|
|
|
c480ed |
default:
|
|
|
c480ed |
break;
|
|
|
c480ed |
@@ -373,6 +416,14 @@ virCPUx86DataSorter(const void *a, const void *b)
|
|
|
c480ed |
|
|
|
c480ed |
break;
|
|
|
c480ed |
|
|
|
c480ed |
+ case VIR_CPU_X86_DATA_MSR:
|
|
|
c480ed |
+ if (da->data.msr.index > db->data.msr.index)
|
|
|
c480ed |
+ return 1;
|
|
|
c480ed |
+ else if (da->data.msr.index < db->data.msr.index)
|
|
|
c480ed |
+ return -1;
|
|
|
c480ed |
+
|
|
|
c480ed |
+ break;
|
|
|
c480ed |
+
|
|
|
c480ed |
case VIR_CPU_X86_DATA_NONE:
|
|
|
c480ed |
default:
|
|
|
c480ed |
break;
|
|
|
c480ed |
@@ -978,6 +1029,31 @@ x86ParseCPUID(xmlXPathContextPtr ctxt,
|
|
|
c480ed |
}
|
|
|
c480ed |
|
|
|
c480ed |
|
|
|
c480ed |
+static int
|
|
|
c480ed |
+x86ParseMSR(xmlXPathContextPtr ctxt,
|
|
|
c480ed |
+ virCPUx86DataItemPtr item)
|
|
|
c480ed |
+{
|
|
|
c480ed |
+ virCPUx86MSRPtr msr;
|
|
|
c480ed |
+ unsigned long index;
|
|
|
c480ed |
+ unsigned long eax;
|
|
|
c480ed |
+ unsigned long edx;
|
|
|
c480ed |
+
|
|
|
c480ed |
+ memset(item, 0, sizeof(*item));
|
|
|
c480ed |
+
|
|
|
c480ed |
+ if (virXPathULongHex("string(@index)", ctxt, &index) < 0 ||
|
|
|
c480ed |
+ virXPathULongHex("string(@eax)", ctxt, &eax) < 0 ||
|
|
|
c480ed |
+ virXPathULongHex("string(@edx)", ctxt, &edx) < 0)
|
|
|
c480ed |
+ return -1;
|
|
|
c480ed |
+
|
|
|
c480ed |
+ item->type = VIR_CPU_X86_DATA_MSR;
|
|
|
c480ed |
+ msr = &item->data.msr;
|
|
|
c480ed |
+ msr->index = index;
|
|
|
c480ed |
+ msr->eax = eax;
|
|
|
c480ed |
+ msr->edx = edx;
|
|
|
c480ed |
+ return 0;
|
|
|
c480ed |
+}
|
|
|
c480ed |
+
|
|
|
c480ed |
+
|
|
|
c480ed |
static int
|
|
|
c480ed |
x86FeatureParse(xmlXPathContextPtr ctxt,
|
|
|
c480ed |
const char *name,
|
|
|
c480ed |
@@ -1010,25 +1086,35 @@ x86FeatureParse(xmlXPathContextPtr ctxt,
|
|
|
c480ed |
if (STREQ_NULLABLE(str, "no"))
|
|
|
c480ed |
feature->migratable = false;
|
|
|
c480ed |
|
|
|
c480ed |
- n = virXPathNodeSet("./cpuid", ctxt, &nodes);
|
|
|
c480ed |
+ n = virXPathNodeSet("./cpuid|./msr", ctxt, &nodes);
|
|
|
c480ed |
if (n < 0)
|
|
|
c480ed |
goto cleanup;
|
|
|
c480ed |
|
|
|
c480ed |
if (n == 0) {
|
|
|
c480ed |
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
c480ed |
- _("Missing cpuid for feature %s"),
|
|
|
c480ed |
+ _("Missing cpuid or msr element in feature %s"),
|
|
|
c480ed |
feature->name);
|
|
|
c480ed |
goto cleanup;
|
|
|
c480ed |
}
|
|
|
c480ed |
|
|
|
c480ed |
for (i = 0; i < n; i++) {
|
|
|
c480ed |
ctxt->node = nodes[i];
|
|
|
c480ed |
- if (x86ParseCPUID(ctxt, &item) < 0) {
|
|
|
c480ed |
- virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
c480ed |
- _("Invalid cpuid[%zu] in %s feature"),
|
|
|
c480ed |
- i, feature->name);
|
|
|
c480ed |
- goto cleanup;
|
|
|
c480ed |
+ if (virXMLNodeNameEqual(nodes[i], "cpuid")) {
|
|
|
c480ed |
+ if (x86ParseCPUID(ctxt, &item) < 0) {
|
|
|
c480ed |
+ virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
c480ed |
+ _("Invalid cpuid[%zu] in %s feature"),
|
|
|
c480ed |
+ i, feature->name);
|
|
|
c480ed |
+ goto cleanup;
|
|
|
c480ed |
+ }
|
|
|
c480ed |
+ } else {
|
|
|
c480ed |
+ if (x86ParseMSR(ctxt, &item) < 0) {
|
|
|
c480ed |
+ virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
c480ed |
+ _("Invalid msr[%zu] in %s feature"),
|
|
|
c480ed |
+ i, feature->name);
|
|
|
c480ed |
+ goto cleanup;
|
|
|
c480ed |
+ }
|
|
|
c480ed |
}
|
|
|
c480ed |
+
|
|
|
c480ed |
if (virCPUx86DataAddItem(&feature->data, &item))
|
|
|
c480ed |
goto cleanup;
|
|
|
c480ed |
}
|
|
|
c480ed |
@@ -1544,6 +1630,7 @@ virCPUx86DataFormat(const virCPUData *data)
|
|
|
c480ed |
virBufferAddLit(&buf, "<cpudata arch='x86'>\n");
|
|
|
c480ed |
while ((item = virCPUx86DataNext(&iter))) {
|
|
|
c480ed |
virCPUx86CPUIDPtr cpuid;
|
|
|
c480ed |
+ virCPUx86MSRPtr msr;
|
|
|
c480ed |
|
|
|
c480ed |
switch (item->type) {
|
|
|
c480ed |
case VIR_CPU_X86_DATA_CPUID:
|
|
|
c480ed |
@@ -1556,6 +1643,13 @@ virCPUx86DataFormat(const virCPUData *data)
|
|
|
c480ed |
cpuid->eax, cpuid->ebx, cpuid->ecx, cpuid->edx);
|
|
|
c480ed |
break;
|
|
|
c480ed |
|
|
|
c480ed |
+ case VIR_CPU_X86_DATA_MSR:
|
|
|
c480ed |
+ msr = &item->data.msr;
|
|
|
c480ed |
+ virBufferAsprintf(&buf,
|
|
|
c480ed |
+ " <msr index='0x%x' eax='0x%08x' edx='0x%08x'/>\n",
|
|
|
c480ed |
+ msr->index, msr->eax, msr->edx);
|
|
|
c480ed |
+ break;
|
|
|
c480ed |
+
|
|
|
c480ed |
case VIR_CPU_X86_DATA_NONE:
|
|
|
c480ed |
default:
|
|
|
c480ed |
break;
|
|
|
c480ed |
@@ -1579,7 +1673,7 @@ virCPUx86DataParse(xmlXPathContextPtr ctxt)
|
|
|
c480ed |
size_t i;
|
|
|
c480ed |
int n;
|
|
|
c480ed |
|
|
|
c480ed |
- n = virXPathNodeSet("/cpudata/cpuid", ctxt, &nodes);
|
|
|
c480ed |
+ n = virXPathNodeSet("/cpudata/cpuid|/cpudata/msr", ctxt, &nodes);
|
|
|
c480ed |
if (n <= 0) {
|
|
|
c480ed |
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
c480ed |
_("no x86 CPU data found"));
|
|
|
c480ed |
@@ -1591,11 +1685,20 @@ virCPUx86DataParse(xmlXPathContextPtr ctxt)
|
|
|
c480ed |
|
|
|
c480ed |
for (i = 0; i < n; i++) {
|
|
|
c480ed |
ctxt->node = nodes[i];
|
|
|
c480ed |
- if (x86ParseCPUID(ctxt, &item) < 0) {
|
|
|
c480ed |
- virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
c480ed |
- _("failed to parse cpuid[%zu]"), i);
|
|
|
c480ed |
- goto error;
|
|
|
c480ed |
+ if (virXMLNodeNameEqual(nodes[i], "cpuid")) {
|
|
|
c480ed |
+ if (x86ParseCPUID(ctxt, &item) < 0) {
|
|
|
c480ed |
+ virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
c480ed |
+ _("failed to parse cpuid[%zu]"), i);
|
|
|
c480ed |
+ goto error;
|
|
|
c480ed |
+ }
|
|
|
c480ed |
+ } else {
|
|
|
c480ed |
+ if (x86ParseMSR(ctxt, &item) < 0) {
|
|
|
c480ed |
+ virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
c480ed |
+ _("failed to parse msr[%zu]"), i);
|
|
|
c480ed |
+ goto error;
|
|
|
c480ed |
+ }
|
|
|
c480ed |
}
|
|
|
c480ed |
+
|
|
|
c480ed |
if (virCPUx86DataAdd(cpuData, &item) < 0)
|
|
|
c480ed |
goto error;
|
|
|
c480ed |
}
|
|
|
c480ed |
diff --git a/src/cpu/cpu_x86_data.h b/src/cpu/cpu_x86_data.h
|
|
|
c480ed |
index da8e91fe71..454345b688 100644
|
|
|
c480ed |
--- a/src/cpu/cpu_x86_data.h
|
|
|
c480ed |
+++ b/src/cpu/cpu_x86_data.h
|
|
|
c480ed |
@@ -37,6 +37,14 @@ struct _virCPUx86CPUID {
|
|
|
c480ed |
uint32_t edx;
|
|
|
c480ed |
};
|
|
|
c480ed |
|
|
|
c480ed |
+typedef struct _virCPUx86MSR virCPUx86MSR;
|
|
|
c480ed |
+typedef virCPUx86MSR *virCPUx86MSRPtr;
|
|
|
c480ed |
+struct _virCPUx86MSR {
|
|
|
c480ed |
+ uint32_t index;
|
|
|
c480ed |
+ uint32_t eax;
|
|
|
c480ed |
+ uint32_t edx;
|
|
|
c480ed |
+};
|
|
|
c480ed |
+
|
|
|
c480ed |
# define CPUX86_BASIC 0x0
|
|
|
c480ed |
# define CPUX86_KVM 0x40000000
|
|
|
c480ed |
# define CPUX86_EXTENDED 0x80000000
|
|
|
c480ed |
@@ -74,6 +82,7 @@ struct _virCPUx86CPUID {
|
|
|
c480ed |
typedef enum {
|
|
|
c480ed |
VIR_CPU_X86_DATA_NONE = 0,
|
|
|
c480ed |
VIR_CPU_X86_DATA_CPUID,
|
|
|
c480ed |
+ VIR_CPU_X86_DATA_MSR,
|
|
|
c480ed |
} virCPUx86DataType;
|
|
|
c480ed |
|
|
|
c480ed |
typedef struct _virCPUx86DataItem virCPUx86DataItem;
|
|
|
c480ed |
@@ -82,6 +91,7 @@ struct _virCPUx86DataItem {
|
|
|
c480ed |
virCPUx86DataType type;
|
|
|
c480ed |
union {
|
|
|
c480ed |
virCPUx86CPUID cpuid;
|
|
|
c480ed |
+ virCPUx86MSR msr;
|
|
|
c480ed |
} data;
|
|
|
c480ed |
};
|
|
|
c480ed |
|
|
|
c480ed |
--
|
|
|
c480ed |
2.22.0
|
|
|
c480ed |
|