[libvirt] [PATCH 23/36] cpu_x86: Add support for storing MSR features in CPU map

Jiri Denemark jdenemar at redhat.com
Mon Apr 8 08:42:27 UTC 2019


Signed-off-by: Jiri Denemark <jdenemar at redhat.com>
---
 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, "<cpudata arch='x86'>\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,
+                              "  <msr index='0x%x' eax='0x%08x' edx='0x%08x'/>\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
 
-- 
2.21.0




More information about the libvir-list mailing list