[libvirt] [PATCH 1/7] cpu: Add support for loading and storing CPU data

Jiri Denemark jdenemar at redhat.com
Tue Jul 23 16:11:30 UTC 2013


---
 src/cpu/cpu.c            |  41 ++++++++++++++
 src/cpu/cpu.h            |  13 +++++
 src/cpu/cpu_x86.c        | 135 +++++++++++++++++++++++++++++++++++++++--------
 src/libvirt_private.syms |   2 +
 4 files changed, 170 insertions(+), 21 deletions(-)

diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c
index 4124354..8bd689e 100644
--- a/src/cpu/cpu.c
+++ b/src/cpu/cpu.c
@@ -438,6 +438,47 @@ cpuHasFeature(const virCPUDataPtr data,
     return driver->hasFeature(data, feature);
 }
 
+char *
+cpuDataFormat(const virCPUDataPtr data)
+{
+    struct cpuArchDriver *driver;
+
+    VIR_DEBUG("data=%p", data);
+
+    if (!(driver = cpuGetSubDriver(data->arch)))
+        return NULL;
+
+    if (!driver->dataFormat) {
+        virReportError(VIR_ERR_NO_SUPPORT,
+                       _("cannot format %s CPU data"),
+                       virArchToString(data->arch));
+        return NULL;
+    }
+
+    return driver->dataFormat(data);
+}
+
+virCPUDataPtr
+cpuDataParse(virArch arch,
+             const char *xmlStr)
+{
+    struct cpuArchDriver *driver;
+
+    VIR_DEBUG("arch=%s, xmlStr=%s", virArchToString(arch), xmlStr);
+
+    if (!(driver = cpuGetSubDriver(arch)))
+        return NULL;
+
+    if (!driver->dataParse) {
+        virReportError(VIR_ERR_NO_SUPPORT,
+                       _("cannot parse %s CPU data"),
+                       virArchToString(arch));
+        return NULL;
+    }
+
+    return driver->dataParse(xmlStr);
+}
+
 bool
 cpuModelIsAllowed(const char *model,
                   const char **models,
diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h
index 4003435..e1473fe 100644
--- a/src/cpu/cpu.h
+++ b/src/cpu/cpu.h
@@ -91,6 +91,11 @@ typedef int
 (*cpuArchHasFeature) (const virCPUDataPtr data,
                       const char *feature);
 
+typedef char *
+(*cpuArchDataFormat)(const virCPUDataPtr data);
+
+typedef virCPUDataPtr
+(*cpuArchDataParse) (const char *xmlStr);
 
 struct cpuArchDriver {
     const char *name;
@@ -105,6 +110,8 @@ struct cpuArchDriver {
     cpuArchBaseline     baseline;
     cpuArchUpdate       update;
     cpuArchHasFeature    hasFeature;
+    cpuArchDataFormat   dataFormat;
+    cpuArchDataParse    dataParse;
 };
 
 
@@ -165,6 +172,12 @@ extern int
 cpuHasFeature(const virCPUDataPtr data,
               const char *feature);
 
+char *
+cpuDataFormat(const virCPUDataPtr data);
+
+virCPUDataPtr
+cpuDataParse(virArch arch,
+             const char *xmlStr);
 
 bool
 cpuModelIsAllowed(const char *model,
diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c
index a388f0f..560a2a9 100644
--- a/src/cpu/cpu_x86.c
+++ b/src/cpu/cpu_x86.c
@@ -666,12 +666,42 @@ x86FeatureNames(const struct x86_map *map,
 
 
 static int
+x86ParseCPUID(xmlXPathContextPtr ctxt,
+              struct cpuX86cpuid *cpuid)
+{
+    unsigned long fun, eax, ebx, ecx, edx;
+    int ret_fun, ret_eax, ret_ebx, ret_ecx, ret_edx;
+
+    memset(cpuid, 0, sizeof(*cpuid));
+
+    fun = eax = ebx = ecx = edx = 0;
+    ret_fun = virXPathULongHex("string(@function)", ctxt, &fun);
+    ret_eax = virXPathULongHex("string(@eax)", ctxt, &eax);
+    ret_ebx = virXPathULongHex("string(@ebx)", ctxt, &ebx);
+    ret_ecx = virXPathULongHex("string(@ecx)", ctxt, &ecx);
+    ret_edx = virXPathULongHex("string(@edx)", ctxt, &edx);
+
+    if (ret_fun < 0 || ret_eax == -2 || ret_ebx == -2
+        || ret_ecx == -2 || ret_edx == -2)
+        return -1;
+
+    cpuid->function = fun;
+    cpuid->eax = eax;
+    cpuid->ebx = ebx;
+    cpuid->ecx = ecx;
+    cpuid->edx = edx;
+    return 0;
+}
+
+
+static int
 x86FeatureLoad(xmlXPathContextPtr ctxt,
                struct x86_map *map)
 {
     xmlNodePtr *nodes = NULL;
     xmlNodePtr ctxt_node = ctxt->node;
     struct x86_feature *feature;
+    struct cpuX86cpuid cpuid;
     int ret = 0;
     size_t i;
     int n;
@@ -697,31 +727,13 @@ x86FeatureLoad(xmlXPathContextPtr ctxt,
         goto ignore;
 
     for (i = 0; i < n; i++) {
-        struct cpuX86cpuid cpuid;
-        unsigned long fun, eax, ebx, ecx, edx;
-        int ret_fun, ret_eax, ret_ebx, ret_ecx, ret_edx;
-
         ctxt->node = nodes[i];
-        fun = eax = ebx = ecx = edx = 0;
-        ret_fun = virXPathULongHex("string(@function)", ctxt, &fun);
-        ret_eax = virXPathULongHex("string(@eax)", ctxt, &eax);
-        ret_ebx = virXPathULongHex("string(@ebx)", ctxt, &ebx);
-        ret_ecx = virXPathULongHex("string(@ecx)", ctxt, &ecx);
-        ret_edx = virXPathULongHex("string(@edx)", ctxt, &edx);
-
-        if (ret_fun < 0 || ret_eax == -2 || ret_ebx == -2
-            || ret_ecx == -2 || ret_edx == -2) {
+        if (x86ParseCPUID(ctxt, &cpuid) < 0) {
             virReportError(VIR_ERR_INTERNAL_ERROR,
-                           _("Invalid cpuid[%zu] in %s feature"), i, feature->name);
+                           _("Invalid cpuid[%zu] in %s feature"),
+                           i, feature->name);
             goto ignore;
         }
-
-        cpuid.function = fun;
-        cpuid.eax = eax;
-        cpuid.ebx = ebx;
-        cpuid.ecx = ecx;
-        cpuid.edx = edx;
-
         if (x86DataAddCpuid(feature->data, &cpuid))
             goto error;
     }
@@ -1124,6 +1136,85 @@ error:
 }
 
 
+static char *
+x86CPUDataFormat(const virCPUDataPtr data)
+{
+    struct data_iterator iter = DATA_ITERATOR_INIT(data->data.x86);
+    struct cpuX86cpuid *cpuid;
+    virBuffer buf = VIR_BUFFER_INITIALIZER;
+
+    virBufferAddLit(&buf, "<cpudata arch='x86'>\n");
+    while ((cpuid = x86DataCpuidNext(&iter))) {
+        virBufferAsprintf(&buf,
+                          "  <cpuid function='0x%08x'"
+                          " eax='0x%08x' ebx='0x%08x'"
+                          " ecx='0x%08x' edx='0x%08x'/>\n",
+                          cpuid->function,
+                          cpuid->eax, cpuid->ebx, cpuid->ecx, cpuid->edx);
+    }
+    virBufferAddLit(&buf, "</cpudata>\n");
+
+    if (virBufferError(&buf)) {
+        virBufferFreeAndReset(&buf);
+        virReportOOMError();
+        return NULL;
+    }
+
+    return virBufferContentAndReset(&buf);
+}
+
+
+static virCPUDataPtr
+x86CPUDataParse(const char *xmlStr)
+{
+    xmlDocPtr xml = NULL;
+    xmlXPathContextPtr ctxt = NULL;
+    xmlNodePtr *nodes = NULL;
+    virCPUDataPtr cpuData = NULL;
+    struct cpuX86Data *data = NULL;
+    struct cpuX86cpuid cpuid;
+    size_t i;
+    int n;
+
+    if (VIR_ALLOC(data) < 0)
+        goto cleanup;
+
+    if (!(xml = virXMLParseStringCtxt(xmlStr, _("CPU data"), &ctxt))) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("cannot parse CPU data"));
+        goto cleanup;
+    }
+    ctxt->node = xmlDocGetRootElement(xml);
+
+    n = virXPathNodeSet("/cpudata[@arch='x86']/data", ctxt, &nodes);
+    if (n < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("no x86 CPU data found"));
+        goto cleanup;
+    }
+
+    for (i = 0; i < n; i++) {
+        ctxt->node = nodes[i];
+        if (x86ParseCPUID(ctxt, &cpuid) < 0) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           _("failed to parse cpuid[%zu]"), i);
+            goto cleanup;
+        }
+        if (x86DataAddCpuid(data, &cpuid) < 0)
+            goto cleanup;
+    }
+
+    cpuData = x86MakeCPUData(VIR_ARCH_X86_64, &data);
+
+cleanup:
+    VIR_FREE(nodes);
+    xmlXPathFreeContext(ctxt);
+    xmlFreeDoc(xml);
+    x86DataFree(data);
+    return cpuData;
+}
+
+
 /* A helper macro to exit the cpu computation function without writing
  * redundant code:
  * MSG: error message
@@ -1920,4 +2011,6 @@ struct cpuArchDriver cpuDriverX86 = {
     .baseline   = x86Baseline,
     .update     = x86Update,
     .hasFeature = x86HasFeature,
+    .dataFormat = x86CPUDataFormat,
+    .dataParse  = x86CPUDataParse,
 };
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 76873ad..e0f3876 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -712,7 +712,9 @@ cpuBaseline;
 cpuBaselineXML;
 cpuCompare;
 cpuCompareXML;
+cpuDataFormat;
 cpuDataFree;
+cpuDataParse;
 cpuDecode;
 cpuEncode;
 cpuGuestData;
-- 
1.8.3.2




More information about the libvir-list mailing list