<div dir="ltr">  ping for reviews  <br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Wed, Apr 22, 2020 at 3:12 PM ZhengZhenyu <<a href="mailto:zheng.zhenyu@foxmail.com">zheng.zhenyu@foxmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Add helper functions to parse vendor and model from<br>
xml for ARM arch, and use them as callbacks when<br>
load cpu maps.<br>
<br>
Signed-off-by: Zhenyu Zheng <<a href="mailto:zhengzhenyulixi@gmail.com" target="_blank">zhengzhenyulixi@gmail.com</a>><br>
---<br>
 src/cpu/cpu_arm.c | 173 +++++++++++++++++++++++++++++++++++++++++++++-<br>
 1 file changed, 170 insertions(+), 3 deletions(-)<br>
<br>
diff --git a/src/cpu/cpu_arm.c b/src/cpu/cpu_arm.c<br>
index 2009904cc9..6e9ff9bf11 100644<br>
--- a/src/cpu/cpu_arm.c<br>
+++ b/src/cpu/cpu_arm.c<br>
@@ -204,6 +204,174 @@ virCPUarmMapFeatureParse(xmlXPathContextPtr ctxt G_GNUC_UNUSED,<br>
     return 0;<br>
 }<br>
<br>
+static virCPUarmVendorPtr<br>
+virCPUarmVendorFindByID(virCPUarmMapPtr map,<br>
+                        unsigned long vendor_id)<br>
+{<br>
+    size_t i;<br>
+<br>
+    for (i = 0; i < map->nvendors; i++) {<br>
+        if (map->vendors[i]->value == vendor_id)<br>
+            return map->vendors[i];<br>
+    }<br>
+<br>
+    return NULL;<br>
+}<br>
+<br>
+<br>
+static virCPUarmVendorPtr<br>
+virCPUarmVendorFindByName(virCPUarmMapPtr map,<br>
+                          const char *name)<br>
+{<br>
+    size_t i;<br>
+<br>
+    for (i = 0; i < map->nvendors; i++) {<br>
+        if (STREQ(map->vendors[i]->name, name))<br>
+            return map->vendors[i];<br>
+    }<br>
+<br>
+    return NULL;<br>
+}<br>
+<br>
+<br>
+static int<br>
+virCPUarmVendorParse(xmlXPathContextPtr ctxt,<br>
+               const char *name,<br>
+               void *data)<br>
+{<br>
+    virCPUarmMapPtr map = data;<br>
+    virCPUarmVendorPtr vendor = NULL;<br>
+    int ret = -1;<br>
+<br>
+    if (VIR_ALLOC(vendor) < 0)<br>
+        return ret;<br>
+<br>
+    vendor->name = g_strdup(name);<br>
+<br>
+    if (virCPUarmVendorFindByName(map, vendor->name)) {<br>
+        virReportError(VIR_ERR_INTERNAL_ERROR,<br>
+                       _("CPU vendor %s already defined"),<br>
+                       vendor->name);<br>
+        goto cleanup;<br>
+    }<br>
+<br>
+    if (virXPathULongHex("string(@value)", ctxt, &vendor->value) < 0) {<br>
+        virReportError(VIR_ERR_INTERNAL_ERROR,<br>
+                       "%s", _("Missing CPU vendor value"));<br>
+        goto cleanup;<br>
+    }<br>
+<br>
+    if (virCPUarmVendorFindByID(map, vendor->value)) {<br>
+        virReportError(VIR_ERR_INTERNAL_ERROR,<br>
+                       _("CPU vendor value 0x%2lx already defined"),<br>
+                       vendor->value);<br>
+        goto cleanup;<br>
+    }<br>
+<br>
+    if (VIR_APPEND_ELEMENT(map->vendors, map->nvendors, vendor) < 0)<br>
+        goto cleanup;<br>
+<br>
+    ret = 0;<br>
+<br>
+ cleanup:<br>
+    virCPUarmVendorFree(vendor);<br>
+    return ret;<br>
+<br>
+}<br>
+<br>
+static virCPUarmModelPtr<br>
+virCPUarmModelFind(virCPUarmMapPtr map,<br>
+                   const char *name)<br>
+{<br>
+    size_t i;<br>
+<br>
+    for (i = 0; i < map->nmodels; i++) {<br>
+        if (STREQ(map->models[i]->name, name))<br>
+            return map->models[i];<br>
+    }<br>
+<br>
+    return NULL;<br>
+}<br>
+<br>
+#if defined(__aarch64__)<br>
+static virCPUarmModelPtr<br>
+virCPUarmModelFindByPVR(virCPUarmMapPtr map,<br>
+                        unsigned long pvr)<br>
+{<br>
+    size_t i;<br>
+<br>
+    for (i = 0; i < map->nmodels; i++) {<br>
+        if (map->models[i]->data.pvr == pvr)<br>
+            return map->models[i];<br>
+    }<br>
+<br>
+    return NULL;<br>
+}<br>
+#endif<br>
+<br>
+static int<br>
+virCPUarmModelParse(xmlXPathContextPtr ctxt,<br>
+              const char *name,<br>
+              void *data)<br>
+{<br>
+    virCPUarmMapPtr map = data;<br>
+    virCPUarmModel *model;<br>
+    g_autofree xmlNodePtr *nodes = NULL;<br>
+    g_autofree char *vendor = NULL;<br>
+<br>
+    if (VIR_ALLOC(model) < 0)<br>
+        goto error;<br>
+<br>
+    model->name = g_strdup(name);<br>
+<br>
+    if (virCPUarmModelFind(map, model->name)) {<br>
+        virReportError(VIR_ERR_INTERNAL_ERROR,<br>
+                       _("CPU model %s already defined"),<br>
+                       model->name);<br>
+        goto error;<br>
+    }<br>
+<br>
+    if (virXPathBoolean("boolean(./vendor)", ctxt)) {<br>
+        vendor = virXPathString("string(./vendor/@name)", ctxt);<br>
+        if (!vendor) {<br>
+            virReportError(VIR_ERR_INTERNAL_ERROR,<br>
+                           _("Invalid vendor element in CPU model %s"),<br>
+                           model->name);<br>
+            goto error;<br>
+        }<br>
+<br>
+        if (!(model->vendor = virCPUarmVendorFindByName(map, vendor))) {<br>
+            virReportError(VIR_ERR_INTERNAL_ERROR,<br>
+                           _("Unknown vendor %s referenced by CPU model %s"),<br>
+                           vendor, model->name);<br>
+            goto error;<br>
+        }<br>
+    }<br>
+<br>
+    if (!virXPathBoolean("boolean(./pvr)", ctxt)) {<br>
+        virReportError(VIR_ERR_INTERNAL_ERROR,<br>
+                       _("Missing PVR information for CPU model %s"),<br>
+                       model->name);<br>
+        goto error;<br>
+    }<br>
+<br>
+    if (virXPathULongHex("string(./pvr/@value)", ctxt, &model->data.pvr) < 0) {<br>
+        virReportError(VIR_ERR_INTERNAL_ERROR,<br>
+                       _("Missing or invalid PVR value in CPU model %s"),<br>
+                       model->name);<br>
+        goto error;<br>
+    }<br>
+<br>
+    if (VIR_APPEND_ELEMENT(map->models, map->nmodels, model) < 0)<br>
+        goto error;<br>
+<br>
+    return 0;<br>
+<br>
+ error:<br>
+    virCPUarmModelFree(model);<br>
+    return -1;<br>
+}<br>
+<br>
 static virCPUarmMapPtr<br>
 virCPUarmLoadMap(void)<br>
 {<br>
@@ -211,8 +379,8 @@ virCPUarmLoadMap(void)<br>
<br>
     map = virCPUarmMapNew();<br>
<br>
-    if (cpuMapLoad("arm", NULL, virCPUarmMapFeatureParse, NULL, map) < 0)<br>
-        return NULL;<br>
+    if (cpuMapLoad("arm", virCPUarmVendorParse, virCPUarmMapFeatureParse,<br>
+                   virCPUarmModelParse, map) < 0)<br>
<br>
     return g_steal_pointer(&map);<br>
 }<br>
@@ -273,7 +441,6 @@ virCPUarmUpdate(virCPUDefPtr guest,<br>
     return ret;<br>
 }<br>
<br>
-<br>
 static virCPUDefPtr<br>
 virCPUarmBaseline(virCPUDefPtr *cpus,<br>
                   unsigned int ncpus G_GNUC_UNUSED,<br>
-- <br>
2.26.0.windows.1<br>
<br>
</blockquote></div>