79c4324644
Change-Id: I2d302dda68298877c65c99147f5bf22186a59aac
288 lines
7.4 KiB
Diff
288 lines
7.4 KiB
Diff
From a0574d45603010761d3f3034f97457fda94d2266 Mon Sep 17 00:00:00 2001
|
|
From: Xu Yandong <xuyandong2@huawei.com>
|
|
Date: Fri, 17 Apr 2020 18:13:32 +0800
|
|
Subject: cpu/arm: add load cpu map parse function
|
|
|
|
Signed-off-by: Xu Yandong <xuyandong2@huawei.com>
|
|
---
|
|
src/cpu/cpu_arm.c | 223 +++++++++++++++++++++++++++++++++++++++++++++-
|
|
1 file changed, 220 insertions(+), 3 deletions(-)
|
|
|
|
diff --git a/src/cpu/cpu_arm.c b/src/cpu/cpu_arm.c
|
|
index 230cd27..d85f111 100644
|
|
--- a/src/cpu/cpu_arm.c
|
|
+++ b/src/cpu/cpu_arm.c
|
|
@@ -67,7 +67,7 @@ virCPUarmDataClear(virCPUarmData *data)
|
|
if (!data)
|
|
return;
|
|
|
|
- VIR_FREE(data->features);
|
|
+ g_free(data->features);
|
|
}
|
|
|
|
static void
|
|
@@ -77,12 +77,64 @@ virCPUarmDataFree(virCPUDataPtr cpuData)
|
|
return;
|
|
|
|
virCPUarmDataClear(&cpuData->data.arm);
|
|
- VIR_FREE(cpuData);
|
|
+ g_free(cpuData);
|
|
}
|
|
|
|
+typedef struct _virCPUarmVendor virCPUarmVendor;
|
|
+typedef virCPUarmVendor *virCPUarmVendorPtr;
|
|
+struct _virCPUarmVendor {
|
|
+ char *name;
|
|
+ unsigned long value;
|
|
+};
|
|
+
|
|
+static virCPUarmVendorPtr
|
|
+virCPUarmVendorNew(void)
|
|
+{
|
|
+ return g_new0(virCPUarmVendor, 1);
|
|
+}
|
|
+
|
|
+static void
|
|
+virCPUarmVendorFree(virCPUarmVendorPtr vendor)
|
|
+{
|
|
+ if (!vendor)
|
|
+ return;
|
|
+
|
|
+ g_free(vendor->name);
|
|
+ VIR_FREE(vendor);
|
|
+}
|
|
+
|
|
+typedef struct _virCPUarmModel virCPUarmModel;
|
|
+typedef virCPUarmModel *virCPUarmModelPtr;
|
|
+struct _virCPUarmModel {
|
|
+ char *name;
|
|
+ virCPUarmVendorPtr vendor;
|
|
+ virCPUarmData data;
|
|
+};
|
|
+
|
|
+static virCPUarmModelPtr
|
|
+virCPUarmModelNew(void)
|
|
+{
|
|
+ return g_new0(virCPUarmModel, 1);
|
|
+}
|
|
+
|
|
+static void
|
|
+virCPUarmModelFree(virCPUarmModelPtr model)
|
|
+{
|
|
+ if (!model)
|
|
+ return;
|
|
+
|
|
+ virCPUarmDataClear(&model->data);
|
|
+ g_free(model->name);
|
|
+ g_free(model);
|
|
+}
|
|
+
|
|
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(virCPUarmModel, virCPUarmModelFree);
|
|
+
|
|
typedef struct _virCPUarmMap virCPUarmMap;
|
|
typedef virCPUarmMap *virCPUarmMapPtr;
|
|
struct _virCPUarmMap {
|
|
+ GPtrArray *vendors;
|
|
+ GPtrArray *models;
|
|
GPtrArray *features;
|
|
};
|
|
|
|
@@ -93,6 +145,14 @@ virCPUarmMapNew(void)
|
|
|
|
map = g_new0(virCPUarmMap, 1);
|
|
|
|
+ map->vendors = g_ptr_array_new();
|
|
+ g_ptr_array_set_free_func(map->vendors,
|
|
+ (GDestroyNotify) virCPUarmVendorFree);
|
|
+
|
|
+ map->models = g_ptr_array_new();
|
|
+ g_ptr_array_set_free_func(map->models,
|
|
+ (GDestroyNotify) virCPUarmModelFree);
|
|
+
|
|
map->features = g_ptr_array_new();
|
|
g_ptr_array_set_free_func(map->features,
|
|
(GDestroyNotify) virCPUarmFeatureFree);
|
|
@@ -106,6 +166,8 @@ virCPUarmMapFree(virCPUarmMapPtr map)
|
|
if (!map)
|
|
return;
|
|
|
|
+ g_ptr_array_free(map->vendors, TRUE);
|
|
+ g_ptr_array_free(map->models, TRUE);
|
|
g_ptr_array_free(map->features, TRUE);
|
|
|
|
g_free(map);
|
|
@@ -151,6 +213,161 @@ virCPUarmMapFeatureParse(xmlXPathContextPtr ctxt G_GNUC_UNUSED,
|
|
return 0;
|
|
}
|
|
|
|
+static virCPUarmVendorPtr
|
|
+virCPUarmVendorFindByID(virCPUarmMapPtr map,
|
|
+ unsigned long vendor_id)
|
|
+{
|
|
+ size_t i;
|
|
+
|
|
+ for (i = 0; i < map->vendors->len; i++) {
|
|
+ virCPUarmVendorPtr vendor = g_ptr_array_index(map->vendors, i);
|
|
+
|
|
+ if (vendor->value == vendor_id)
|
|
+ return vendor;
|
|
+ }
|
|
+
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
+static virCPUarmVendorPtr
|
|
+virCPUarmVendorFindByName(virCPUarmMapPtr map,
|
|
+ const char *name)
|
|
+{
|
|
+ size_t i;
|
|
+
|
|
+ for (i = 0; i < map->vendors->len; i++) {
|
|
+ virCPUarmVendorPtr vendor = g_ptr_array_index(map->vendors, i);
|
|
+
|
|
+ if (STREQ(vendor->name, name))
|
|
+ return vendor;
|
|
+ }
|
|
+
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
+static int
|
|
+virCPUarmVendorParse(xmlXPathContextPtr ctxt,
|
|
+ const char *name,
|
|
+ void *data)
|
|
+{
|
|
+ virCPUarmMapPtr map = (virCPUarmMapPtr)data;
|
|
+ g_autoptr(virCPUarmVendor) vendor = NULL;
|
|
+ int ret = -1;
|
|
+
|
|
+ if (virCPUarmVendorFindByName(map, name)) {
|
|
+ virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
+ _("CPU vendor %s already defined"), name);
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ vendor = virCPUarmVendorNew();
|
|
+ vendor->name = g_strdup(name);
|
|
+
|
|
+ if (virXPathULongHex("string(@value)", ctxt, &vendor->value) < 0) {
|
|
+ virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
+ "%s", _("Missing CPU vendor value"));
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ if (virCPUarmVendorFindByID(map, vendor->value)) {
|
|
+ virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
+ _("CPU vendor value 0x%2lx already defined"), vendor->value);
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ g_ptr_array_add(map->vendors, g_steal_pointer(&vendor));
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static virCPUarmModelPtr
|
|
+virCPUarmModelFindByPVR(virCPUarmMapPtr map,
|
|
+ unsigned long pvr)
|
|
+{
|
|
+ size_t i;
|
|
+
|
|
+ for (i = 0; i < map->models->len; i++) {
|
|
+ virCPUarmModelPtr model = g_ptr_array_index(map->models, i);
|
|
+
|
|
+ if (STREQ(model->pvr, pvr))
|
|
+ return model;
|
|
+ }
|
|
+
|
|
+ return NULL;
|
|
+
|
|
+}
|
|
+
|
|
+static virCPUarmModelPtr
|
|
+virCPUarmModelFindByName(virCPUarmMapPtr map,
|
|
+ const char *name)
|
|
+{
|
|
+ size_t i;
|
|
+
|
|
+ for (i = 0; i < map->models->len; i++) {
|
|
+ virCPUarmModelPtr model = g_ptr_array_index(map->models, i);
|
|
+
|
|
+ if (STREQ(model->name, name))
|
|
+ return model;
|
|
+ }
|
|
+
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
+static int
|
|
+virCPUarmModelParse(xmlXPathContextPtr ctxt,
|
|
+ const char *name,
|
|
+ void *data)
|
|
+{
|
|
+ virCPUarmMapPtr map = (virCPUarmMapPtr)data;
|
|
+ g_autoptr(virCPUarmModel) model = NULL;
|
|
+ char *vendor = NULL;
|
|
+ int ret = -1;
|
|
+
|
|
+ if (virCPUarmModelFindByName(map, name)) {
|
|
+ virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
+ _("CPU model %s already defined"), name);
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ model = virCPUarmModelNew();
|
|
+ model->name = g_strdup(name);
|
|
+
|
|
+ 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"),
|
|
+ name);
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ if (!(model->vendor = virCPUarmVendorFindByName(map, vendor))) {
|
|
+ virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
+ _("Unknown vendor %s referenced by CPU model %s"),
|
|
+ vendor, model->name);
|
|
+ return -1;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (!virXPathBoolean("boolean(./pvr)", ctxt)) {
|
|
+ virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
+ _("Missing PVR information for CPU model %s"),
|
|
+ model->name);
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ if (virXPathULongHex("string(./pvr/@value)", ctxt, &model->data.pvr) < 0) {
|
|
+ virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
+ _("Missing or invalid PVR value in CPU model %s"),
|
|
+ model->name);
|
|
+ return -1;
|
|
+ }
|
|
+
|
|
+ g_ptr_array_add(map->models, g_steal_pointer(&model));
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
static virCPUarmMapPtr
|
|
virCPUarmLoadMap(void)
|
|
{
|
|
@@ -158,7 +375,7 @@ virCPUarmLoadMap(void)
|
|
|
|
map = virCPUarmMapNew();
|
|
|
|
- if (cpuMapLoad("arm", NULL, virCPUarmMapFeatureParse, NULL, map) < 0)
|
|
+ if (cpuMapLoad("arm", virCPUarmVendorParse, virCPUarmMapFeatureParse, virCPUarmModelParse, map) < 0)
|
|
return NULL;
|
|
|
|
return g_steal_pointer(&map);
|
|
--
|
|
2.23.0
|
|
|