Add helper functions to parse vendor and model for ARM and use
them as callback when load maps.

Signed-of-by: Zhenyu Zheng <zhengzhenyul...@gmail.com>
---
 src/cpu/cpu_arm.c | 143 +++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 142 insertions(+), 1 deletion(-)

diff --git a/src/cpu/cpu_arm.c b/src/cpu/cpu_arm.c
index 2a05f43118..969025b5cf 100644
--- a/src/cpu/cpu_arm.c
+++ b/src/cpu/cpu_arm.c
@@ -181,6 +181,147 @@ virCPUarmMapFeatureFind(virCPUarmMapPtr map,
     return NULL;
 }
 
+static virCPUarmVendorPtr
+armVendorFindByID(virCPUarmMapPtr map,
+                  unsigned long vendor_id)
+{
+    size_t i;
+
+    for (i = 0; i < map->nvendors; i++) {
+        if (map->vendors[i]->value == vendor_id)
+            return map->vendors[i];
+    }
+
+    return NULL;
+}
+
+
+static virCPUarmVendorPtr
+armVendorFindByName(virCPUarmMapPtr map,
+                    const char *name)
+{
+    size_t i;
+
+    for (i = 0; i < map->nvendors; i++) {
+        if (STREQ(map->vendors[i]->name, name))
+            return map->vendors[i];
+    }
+
+    return NULL;
+}
+
+
+static int
+armVendorParse(xmlXPathContextPtr ctxt,
+               const char *name,
+               void *data)
+{
+    virCPUarmMapPtr map = (virCPUarmMapPtr)data;
+    virCPUarmVendorPtr vendor = NULL;
+    int ret = -1;
+
+    if (VIR_ALLOC(vendor) < 0)
+        return ret;
+
+    vendor->name = g_strdup(name);
+
+    if (armVendorFindByName(map, vendor->name)) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("CPU vendor %s already defined"), vendor->name);
+        goto cleanup;
+    }
+
+    if (virXPathULongHex("string(@value)", ctxt, &vendor->value) < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       "%s", _("Missing CPU vendor value"));
+        goto cleanup;
+    }
+
+    if (armVendorFindByID(map, vendor->value)) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("CPU vendor value 0x%2lx already defined"), 
vendor->value);
+        goto cleanup;
+    }
+
+    if (VIR_APPEND_ELEMENT(map->vendors, map->nvendors, vendor) < 0)
+        goto cleanup;
+
+    ret = 0;
+
+ cleanup:
+    armVendorFree(vendor);
+    return ret;
+
+}
+
+static virCPUarmModelPtr
+armModelFind(virCPUarmMapPtr map,
+             const char *name)
+{
+    size_t i;
+
+    for (i = 0; i < map->nmodels; i++) {
+        if (STREQ(map->models[i]->name, name))
+            return map->models[i];
+    }
+
+    return NULL;
+}
+
+static int
+armModelParse(xmlXPathContextPtr ctxt,
+              const char *name,
+              void *data)
+{
+    virCPUarmMapPtr map = (virCPUarmMapPtr)data;
+    virCPUarmModel *model;
+    xmlNodePtr *nodes = NULL;
+    char *vendor = NULL;
+    int ret = -1;
+
+    if (VIR_ALLOC(model) < 0)
+        goto error;
+
+    model->name = g_strdup(name);
+
+    if (armModelFind(map, model->name)) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("CPU model %s already defined"), model->name);
+        goto error;
+    }
+
+    if (virXPathBoolean("boolean(./vendor)", ctxt)) {
+        vendor = virXPathString("string(./vendor/@name)", ctxt);
+        if (!vendor) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           _("Invalid vendor element in CPU model %s"),
+                           model->name);
+            goto error;
+        }
+
+        if (!(model->vendor = armVendorFindByName(map, vendor))) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           _("Unknown vendor %s referenced by CPU model %s"),
+                           vendor, model->name);
+            goto error;
+        }
+    }
+
+    if (VIR_APPEND_ELEMENT(map->models, map->nmodels, model) < 0)
+        goto error;
+
+    ret = 0;
+
+ cleanup:
+    VIR_FREE(vendor);
+    VIR_FREE(nodes);
+    return ret;
+
+ error:
+    armModelFree(model);
+    goto cleanup;
+}
+
 static int
 virCPUarmMapFeatureParse(xmlXPathContextPtr ctxt G_GNUC_UNUSED,
                          const char *name,
@@ -210,7 +351,7 @@ virCPUarmLoadMap(void)
 
     map = virCPUarmMapNew();
 
-    if (cpuMapLoad("arm", NULL, virCPUarmMapFeatureParse, NULL, map) < 0)
+    if (cpuMapLoad("arm", armVendorParse, virCPUarmMapFeatureParse, 
armModelParse, map) < 0)
         return NULL;
 
     return g_steal_pointer(&map);
-- 
2.26.0.windows.1


Reply via email to