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