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 <lixianglai@loongson.cn> --- Cc: Bibo Mao <maobibo@loongson.cn> 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