Add parsing of LoongArch CPU features from the CPU map XML files.

Each feature is described by a CPUCFG register index and a value.
Feature lookup by name is also added.

The feature parsing callback is now passed to cpuMapLoad().

Signed-off-by: Xianglai Li <[email protected]>
---
Cc: Bibo Mao <[email protected]>

 src/cpu/cpu_loongarch.c | 92 ++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 90 insertions(+), 2 deletions(-)

diff --git a/src/cpu/cpu_loongarch.c b/src/cpu/cpu_loongarch.c
index d1ed447881..7d63630615 100644
--- a/src/cpu/cpu_loongarch.c
+++ b/src/cpu/cpu_loongarch.c
@@ -38,6 +38,7 @@ typedef struct _virCPULoongArchMap virCPULoongArchMap;
 struct _virCPULoongArchMap {
     size_t nvendors;
     virCPULoongArchVendor **vendors;
+    virCPULoongArchData data;
 };
 
 static const virArch archs[] = { VIR_ARCH_LOONGARCH64 };
@@ -54,6 +55,25 @@ virCPULoongArchCompare(virCPUDef *host G_GNUC_UNUSED,
     return VIR_CPU_COMPARE_IDENTICAL;
 }
 
+static virCPULoongArchFeature *
+virCPULoongArchFeatureNew(void)
+{
+    return g_new0(virCPULoongArchFeature, 1);
+}
+
+static void
+virCPULoongArchFeatureFree(virCPULoongArchFeature *feature)
+{
+    if (!feature)
+        return;
+
+    g_free(feature->name);
+    g_free(feature);
+}
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(virCPULoongArchFeature,
+                 virCPULoongArchFeatureFree);
+
 static void
 virCPULoongArchVendorFree(virCPULoongArchVendor *vendor)
 {
@@ -72,7 +92,9 @@ virCPULoongArchMapNew(void)
     virCPULoongArchMap *map;
 
     map = g_new0(virCPULoongArchMap, 1);
-
+    map->data.features = g_ptr_array_new();
+    g_ptr_array_set_free_func(map->data.features,
+                              (GDestroyNotify) virCPULoongArchFeatureFree);
     return map;
 }
 
@@ -87,10 +109,28 @@ virCPULoongArchMapFree(virCPULoongArchMap *map)
     for (i = 0; i < map->nvendors; i++)
         virCPULoongArchVendorFree(map->vendors[i]);
     g_free(map->vendors);
+    g_ptr_array_free(map->data.features, TRUE);
     g_free(map);
 }
 G_DEFINE_AUTOPTR_CLEANUP_FUNC(virCPULoongArchMap, virCPULoongArchMapFree);
 
+static virCPULoongArchFeature *
+virCPULoongArchMapFeatureFindByName(virCPULoongArchMap *map,
+                        const char *name)
+{
+    size_t i;
+    virCPULoongArchFeature *feature;
+
+    for (i = 0; i < map->data.features->len; i++) {
+        feature = g_ptr_array_index(map->data.features, i);
+        if (STREQ(feature->name, name))
+            return feature;
+    }
+
+    return NULL;
+}
+
+
 static virCPULoongArchVendor *
 virCPULoongArchVendorFindByName(virCPULoongArchMap *map,
                           const char *name)
@@ -119,6 +159,53 @@ virCPULoongArchVendorFindByID(virCPULoongArchMap *map,
     return NULL;
 }
 
+static int
+virCPULoongArchMapCpucfgParse(xmlNodePtr node,
+              virCPULoongArchFeature *feature)
+{
+    if (virXMLPropUInt(node, "index", 16, VIR_XML_PROP_REQUIRED,
+                            &feature->index) < 0)
+        return -1;
+    if (virXMLPropUInt(node, "value", 16, VIR_XML_PROP_REQUIRED,
+                            &feature->value) < 0)
+        return -1;
+
+    return 0;
+}
+
+static int
+virCPULoongArchMapFeatureParse(xmlXPathContextPtr ctxt,
+                         const char *name,
+                         void *data)
+{
+    g_autoptr(virCPULoongArchFeature) feature = NULL;
+    virCPULoongArchMap *map = data;
+    xmlNodePtr node;
+
+    if (virCPULoongArchMapFeatureFindByName(map, name)) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("CPU feature %1$s already defined"), name);
+        return -1;
+    }
+
+    feature = virCPULoongArchFeatureNew();
+    feature->name = g_strdup(name);
+
+    node = xmlFirstElementChild(ctxt->node);
+    if (node) {
+        if (virXMLNodeNameEqual(node, "cpucfg")) {
+            if (virCPULoongArchMapCpucfgParse(node, feature) < 0) {
+                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                               _("Invalid cpucfg"));
+                return -1;
+            }
+        }
+    }
+
+    g_ptr_array_add(map->data.features, g_steal_pointer(&feature));
+    return 0;
+}
+
 static int
 virCPULoongArchMapVendorParse(xmlXPathContextPtr ctxt,
                      const char *name,
@@ -160,7 +247,8 @@ virCPULoongArchLoadMap(void)
     map = virCPULoongArchMapNew();
 
     if (cpuMapLoad("loongarch", virCPULoongArchMapVendorParse,
-                   NULL, NULL, map) < 0)
+                   virCPULoongArchMapFeatureParse,
+                   NULL, map) < 0)
         return NULL;
 
     return g_steal_pointer(&map);
-- 
2.39.1

Reply via email to