From fcf4846a6bb902a5cd2230fff2a1e7591dcb7456 Mon Sep 17 00:00:00 2001 From: Jiri Denemark Date: Tue, 19 Mar 2019 09:45:48 +0100 Subject: [PATCH] cpu_x86: Add support for storing MSR features in CPU map MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jiri Denemark Reviewed-by: Ján Tomko --- src/cpu/cpu_x86.c | 127 +++++++++++++++++++++++++++++---- src/cpu/cpu_x86_data.h | 10 +++ tests/cputestdata/cpu-cpuid.py | 3 +- 3 files changed, 127 insertions(+), 13 deletions(-) diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c index 192e067d38..57837209b4 100644 --- a/src/cpu/cpu_x86.c +++ b/src/cpu/cpu_x86.c @@ -199,6 +199,8 @@ virCPUx86DataItemMatch(const virCPUx86DataItem *item1, { const virCPUx86CPUID *cpuid1; const virCPUx86CPUID *cpuid2; + const virCPUx86MSR *msr1; + const virCPUx86MSR *msr2; switch (item1->type) { case VIR_CPU_X86_DATA_CPUID: @@ -209,6 +211,12 @@ virCPUx86DataItemMatch(const virCPUx86DataItem *item1, cpuid1->ecx == cpuid2->ecx && cpuid1->edx == cpuid2->edx); + case VIR_CPU_X86_DATA_MSR: + msr1 = &item1->data.msr; + msr2 = &item2->data.msr; + return (msr1->eax == msr2->eax && + msr1->edx == msr2->edx); + case VIR_CPU_X86_DATA_NONE: default: return false; @@ -222,6 +230,8 @@ virCPUx86DataItemMatchMasked(const virCPUx86DataItem *item, { const virCPUx86CPUID *cpuid; const virCPUx86CPUID *cpuidMask; + const virCPUx86MSR *msr; + const virCPUx86MSR *msrMask; switch (item->type) { case VIR_CPU_X86_DATA_CPUID: @@ -232,6 +242,12 @@ virCPUx86DataItemMatchMasked(const virCPUx86DataItem *item, (cpuid->ecx & cpuidMask->ecx) == cpuidMask->ecx && (cpuid->edx & cpuidMask->edx) == cpuidMask->edx); + case VIR_CPU_X86_DATA_MSR: + msr = &item->data.msr; + msrMask = &mask->data.msr; + return ((msr->eax & msrMask->eax) == msrMask->eax && + (msr->edx & msrMask->edx) == msrMask->edx); + case VIR_CPU_X86_DATA_NONE: default: return false; @@ -245,6 +261,8 @@ virCPUx86DataItemSetBits(virCPUx86DataItemPtr item, { virCPUx86CPUIDPtr cpuid; const virCPUx86CPUID *cpuidMask; + virCPUx86MSRPtr msr; + const virCPUx86MSR *msrMask; if (!mask) return; @@ -259,6 +277,13 @@ virCPUx86DataItemSetBits(virCPUx86DataItemPtr item, cpuid->edx |= cpuidMask->edx; break; + case VIR_CPU_X86_DATA_MSR: + msr = &item->data.msr; + msrMask = &mask->data.msr; + msr->eax |= msrMask->eax; + msr->edx |= msrMask->edx; + break; + case VIR_CPU_X86_DATA_NONE: default: break; @@ -272,6 +297,8 @@ virCPUx86DataItemClearBits(virCPUx86DataItemPtr item, { virCPUx86CPUIDPtr cpuid; const virCPUx86CPUID *cpuidMask; + virCPUx86MSRPtr msr; + const virCPUx86MSR *msrMask; if (!mask) return; @@ -286,6 +313,13 @@ virCPUx86DataItemClearBits(virCPUx86DataItemPtr item, cpuid->edx &= ~cpuidMask->edx; break; + case VIR_CPU_X86_DATA_MSR: + msr = &item->data.msr; + msrMask = &mask->data.msr; + msr->eax &= ~msrMask->eax; + msr->edx &= ~msrMask->edx; + break; + case VIR_CPU_X86_DATA_NONE: default: break; @@ -299,6 +333,8 @@ virCPUx86DataItemAndBits(virCPUx86DataItemPtr item, { virCPUx86CPUIDPtr cpuid; const virCPUx86CPUID *cpuidMask; + virCPUx86MSRPtr msr; + const virCPUx86MSR *msrMask; if (!mask) return; @@ -313,6 +349,13 @@ virCPUx86DataItemAndBits(virCPUx86DataItemPtr item, cpuid->edx &= cpuidMask->edx; break; + case VIR_CPU_X86_DATA_MSR: + msr = &item->data.msr; + msrMask = &mask->data.msr; + msr->eax &= msrMask->eax; + msr->edx &= msrMask->edx; + break; + case VIR_CPU_X86_DATA_NONE: default: break; @@ -375,6 +418,14 @@ virCPUx86DataSorter(const void *a, const void *b) break; + case VIR_CPU_X86_DATA_MSR: + if (da->data.msr.index > db->data.msr.index) + return 1; + else if (da->data.msr.index < db->data.msr.index) + return -1; + + break; + case VIR_CPU_X86_DATA_NONE: default: break; @@ -979,6 +1030,31 @@ x86ParseCPUID(xmlXPathContextPtr ctxt, } +static int +x86ParseMSR(xmlXPathContextPtr ctxt, + virCPUx86DataItemPtr item) +{ + virCPUx86MSRPtr msr; + unsigned long index; + unsigned long eax; + unsigned long edx; + + memset(item, 0, sizeof(*item)); + + if (virXPathULongHex("string(@index)", ctxt, &index) < 0 || + virXPathULongHex("string(@eax)", ctxt, &eax) < 0 || + virXPathULongHex("string(@edx)", ctxt, &edx) < 0) + return -1; + + item->type = VIR_CPU_X86_DATA_MSR; + msr = &item->data.msr; + msr->index = index; + msr->eax = eax; + msr->edx = edx; + return 0; +} + + static int x86FeatureParse(xmlXPathContextPtr ctxt, const char *name, @@ -1011,25 +1087,35 @@ x86FeatureParse(xmlXPathContextPtr ctxt, if (STREQ_NULLABLE(str, "no")) feature->migratable = false; - n = virXPathNodeSet("./cpuid", ctxt, &nodes); + n = virXPathNodeSet("./cpuid|./msr", ctxt, &nodes); if (n < 0) goto cleanup; if (n == 0) { virReportError(VIR_ERR_INTERNAL_ERROR, - _("Missing cpuid for feature %s"), + _("Missing cpuid or msr element in feature %s"), feature->name); goto cleanup; } for (i = 0; i < n; i++) { ctxt->node = nodes[i]; - if (x86ParseCPUID(ctxt, &item) < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("Invalid cpuid[%zu] in %s feature"), - i, feature->name); - goto cleanup; + if (virXMLNodeNameEqual(nodes[i], "cpuid")) { + if (x86ParseCPUID(ctxt, &item) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Invalid cpuid[%zu] in %s feature"), + i, feature->name); + goto cleanup; + } + } else { + if (x86ParseMSR(ctxt, &item) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Invalid msr[%zu] in %s feature"), + i, feature->name); + goto cleanup; + } } + if (virCPUx86DataAddItem(&feature->data, &item)) goto cleanup; } @@ -1545,6 +1631,7 @@ virCPUx86DataFormat(const virCPUData *data) virBufferAddLit(&buf, "\n"); while ((item = virCPUx86DataNext(&iter))) { virCPUx86CPUIDPtr cpuid; + virCPUx86MSRPtr msr; switch (item->type) { case VIR_CPU_X86_DATA_CPUID: @@ -1557,6 +1644,13 @@ virCPUx86DataFormat(const virCPUData *data) cpuid->eax, cpuid->ebx, cpuid->ecx, cpuid->edx); break; + case VIR_CPU_X86_DATA_MSR: + msr = &item->data.msr; + virBufferAsprintf(&buf, + " \n", + msr->index, msr->eax, msr->edx); + break; + case VIR_CPU_X86_DATA_NONE: default: break; @@ -1580,7 +1674,7 @@ virCPUx86DataParse(xmlXPathContextPtr ctxt) size_t i; int n; - n = virXPathNodeSet("/cpudata/cpuid", ctxt, &nodes); + n = virXPathNodeSet("/cpudata/cpuid|/cpudata/msr", ctxt, &nodes); if (n <= 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("no x86 CPU data found")); @@ -1592,11 +1686,20 @@ virCPUx86DataParse(xmlXPathContextPtr ctxt) for (i = 0; i < n; i++) { ctxt->node = nodes[i]; - if (x86ParseCPUID(ctxt, &item) < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("failed to parse cpuid[%zu]"), i); - goto error; + if (virXMLNodeNameEqual(nodes[i], "cpuid")) { + if (x86ParseCPUID(ctxt, &item) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("failed to parse cpuid[%zu]"), i); + goto error; + } + } else { + if (x86ParseMSR(ctxt, &item) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("failed to parse msr[%zu]"), i); + goto error; + } } + if (virCPUx86DataAdd(cpuData, &item) < 0) goto error; } diff --git a/src/cpu/cpu_x86_data.h b/src/cpu/cpu_x86_data.h index b16860b201..4600870c4c 100644 --- a/src/cpu/cpu_x86_data.h +++ b/src/cpu/cpu_x86_data.h @@ -33,6 +33,14 @@ struct _virCPUx86CPUID { uint32_t edx; }; +typedef struct _virCPUx86MSR virCPUx86MSR; +typedef virCPUx86MSR *virCPUx86MSRPtr; +struct _virCPUx86MSR { + uint32_t index; + uint32_t eax; + uint32_t edx; +}; + # define CPUX86_BASIC 0x0 # define CPUX86_KVM 0x40000000 # define CPUX86_EXTENDED 0x80000000 @@ -72,6 +80,7 @@ struct _virCPUx86CPUID { typedef enum { VIR_CPU_X86_DATA_NONE = 0, VIR_CPU_X86_DATA_CPUID, + VIR_CPU_X86_DATA_MSR, } virCPUx86DataType; typedef struct _virCPUx86DataItem virCPUx86DataItem; @@ -80,6 +89,7 @@ struct _virCPUx86DataItem { virCPUx86DataType type; union { virCPUx86CPUID cpuid; + virCPUx86MSR msr; } data; }; diff --git a/tests/cputestdata/cpu-cpuid.py b/tests/cputestdata/cpu-cpuid.py index f532475702..f549003124 100755 --- a/tests/cputestdata/cpu-cpuid.py +++ b/tests/cputestdata/cpu-cpuid.py @@ -307,7 +307,8 @@ def parseMap(): cpuMap = {} for feature in data["cpus"]["feature"]: - cpuMap[feature["@name"]] = parseFeature(feature["cpuid"]) + if "cpuid" in feature: + cpuMap[feature["@name"]] = parseFeature(feature["cpuid"]) return cpuMap