From 808b0c73134cd3c6a7fdd387fd9654dbd41356ac Mon Sep 17 00:00:00 2001 Message-Id: <808b0c73134cd3c6a7fdd387fd9654dbd41356ac@dist-git> From: Jiri Denemark Date: Fri, 21 Jun 2019 09:25:39 +0200 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 (cherry picked from commit fcf4846a6bb902a5cd2230fff2a1e7591dcb7456) https://bugzilla.redhat.com/show_bug.cgi?id=1697627 Conflicts: tests/cputestdata/cpu-cpuid.py - no need to update this script downstream Signed-off-by: Jiri Denemark Message-Id: <0c37dabaaa6c2559b48918ca55e170750fe34ea0.1561068591.git.jdenemar@redhat.com> Reviewed-by: Ján Tomko --- src/cpu/cpu_x86.c | 127 +++++++++++++++++++++++++++++++++++++---- src/cpu/cpu_x86_data.h | 10 ++++ 2 files changed, 125 insertions(+), 12 deletions(-) diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c index e6da974b31..49562944c1 100644 --- a/src/cpu/cpu_x86.c +++ b/src/cpu/cpu_x86.c @@ -197,6 +197,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: @@ -207,6 +209,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; @@ -220,6 +228,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: @@ -230,6 +240,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; @@ -243,6 +259,8 @@ virCPUx86DataItemSetBits(virCPUx86DataItemPtr item, { virCPUx86CPUIDPtr cpuid; const virCPUx86CPUID *cpuidMask; + virCPUx86MSRPtr msr; + const virCPUx86MSR *msrMask; if (!mask) return; @@ -257,6 +275,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; @@ -270,6 +295,8 @@ virCPUx86DataItemClearBits(virCPUx86DataItemPtr item, { virCPUx86CPUIDPtr cpuid; const virCPUx86CPUID *cpuidMask; + virCPUx86MSRPtr msr; + const virCPUx86MSR *msrMask; if (!mask) return; @@ -284,6 +311,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; @@ -297,6 +331,8 @@ virCPUx86DataItemAndBits(virCPUx86DataItemPtr item, { virCPUx86CPUIDPtr cpuid; const virCPUx86CPUID *cpuidMask; + virCPUx86MSRPtr msr; + const virCPUx86MSR *msrMask; if (!mask) return; @@ -311,6 +347,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; @@ -373,6 +416,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; @@ -978,6 +1029,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, @@ -1010,25 +1086,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; } @@ -1544,6 +1630,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: @@ -1556,6 +1643,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; @@ -1579,7 +1673,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")); @@ -1591,11 +1685,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 da8e91fe71..454345b688 100644 --- a/src/cpu/cpu_x86_data.h +++ b/src/cpu/cpu_x86_data.h @@ -37,6 +37,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 @@ -74,6 +82,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; @@ -82,6 +91,7 @@ struct _virCPUx86DataItem { virCPUx86DataType type; union { virCPUx86CPUID cpuid; + virCPUx86MSR msr; } data; }; -- 2.22.0