[libvirt] [PATCH RFC 09/11] cpu: Validate ARM CPU features

Andrea Bolognani abologna at redhat.com
Thu Jul 25 14:06:23 UTC 2019


Signed-off-by: Andrea Bolognani <abologna at redhat.com>
---
 src/cpu/cpu_arm.c | 171 ++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 171 insertions(+)

diff --git a/src/cpu/cpu_arm.c b/src/cpu/cpu_arm.c
index 65d69c00af..fd504c8aef 100644
--- a/src/cpu/cpu_arm.c
+++ b/src/cpu/cpu_arm.c
@@ -23,7 +23,9 @@
 
 #include "viralloc.h"
 #include "cpu.h"
+#include "cpu_map.h"
 #include "virstring.h"
+#include "virxml.h"
 
 #define VIR_FROM_THIS VIR_FROM_CPU
 
@@ -34,6 +36,153 @@ static const virArch archs[] = {
     VIR_ARCH_AARCH64,
 };
 
+typedef struct _virCPUarmFeature virCPUarmFeature;
+typedef virCPUarmFeature *virCPUarmFeaturePtr;
+struct _virCPUarmFeature {
+    char *name;
+};
+
+static virCPUarmFeaturePtr
+virCPUarmFeatureNew(void)
+{
+    virCPUarmFeaturePtr feature;
+
+    if (VIR_ALLOC(feature) < 0)
+        return NULL;
+
+    return feature;
+}
+
+static void
+virCPUarmFeatureFree(virCPUarmFeaturePtr feature)
+{
+    if (!feature)
+        return;
+
+    VIR_FREE(feature->name);
+    VIR_FREE(feature);
+}
+
+typedef struct _virCPUarmMap virCPUarmMap;
+typedef virCPUarmMap *virCPUarmMapPtr;
+struct _virCPUarmMap {
+    size_t nfeatures;
+    virCPUarmFeaturePtr *features;
+};
+
+static virCPUarmMapPtr
+virCPUarmMapNew(void)
+{
+    virCPUarmMapPtr map;
+
+    if (VIR_ALLOC(map) < 0)
+        return NULL;
+
+    return map;
+}
+
+static void
+virCPUarmMapFree(virCPUarmMapPtr map)
+{
+    size_t i;
+
+    if (!map)
+        return;
+
+    for (i = 0; i < map->nfeatures; i++)
+        virCPUarmFeatureFree(map->features[i]);
+    VIR_FREE(map->features);
+
+    VIR_FREE(map);
+}
+
+static virCPUarmFeaturePtr
+virCPUarmMapFeatureFind(virCPUarmMapPtr map,
+                        const char *name)
+{
+    size_t i;
+
+    for (i = 0; i < map->nfeatures; i++) {
+        if (STREQ(map->features[i]->name, name))
+            return map->features[i];
+    }
+
+    return NULL;
+}
+
+static int
+virCPUarmMapFeatureParse(xmlXPathContextPtr ctxt ATTRIBUTE_UNUSED,
+                         const char *name,
+                         void *data)
+{
+    virCPUarmMapPtr map = data;
+    virCPUarmFeaturePtr feature;
+    int ret = -1;
+
+    if (!(feature = virCPUarmFeatureNew()))
+        goto cleanup;
+
+    if (VIR_STRDUP(feature->name, name) < 0)
+        goto cleanup;
+
+    if (virCPUarmMapFeatureFind(map, feature->name)) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("CPU feature %s already defined"), feature->name);
+        goto cleanup;
+    }
+
+    if (VIR_APPEND_ELEMENT(map->features, map->nfeatures, feature) < 0)
+        goto cleanup;
+
+    ret = 0;
+
+ cleanup:
+    virCPUarmFeatureFree(feature);
+
+    return ret;
+}
+
+static virCPUarmMapPtr
+virCPUarmLoadMap(void)
+{
+    virCPUarmMapPtr map;
+
+    if (!(map = virCPUarmMapNew()))
+        goto error;
+
+    if (cpuMapLoad("arm", NULL, virCPUarmMapFeatureParse, NULL, map) < 0)
+        goto error;
+
+    return map;
+
+ error:
+    virCPUarmMapFree(map);
+
+    return NULL;
+}
+
+static virCPUarmMapPtr cpuMap;
+
+int virCPUarmDriverOnceInit(void);
+VIR_ONCE_GLOBAL_INIT(virCPUarmDriver);
+
+int
+virCPUarmDriverOnceInit(void)
+{
+    if (!(cpuMap = virCPUarmLoadMap()))
+        return -1;
+
+    return 0;
+}
+
+static virCPUarmMapPtr
+virCPUarmGetMap(void)
+{
+    if (virCPUarmDriverInitialize() < 0)
+        return NULL;
+
+    return cpuMap;
+}
 
 static int
 virCPUarmUpdate(virCPUDefPtr guest,
@@ -98,6 +247,27 @@ virCPUarmCompare(virCPUDefPtr host ATTRIBUTE_UNUSED,
     return VIR_CPU_COMPARE_IDENTICAL;
 }
 
+static int
+virCPUarmValidateFeatures(virCPUDefPtr cpu)
+{
+    virCPUarmMapPtr map;
+    size_t i;
+
+    if (!(map = virCPUarmGetMap()))
+        return -1;
+
+    for (i = 0; i < cpu->nfeatures; i++) {
+        if (!virCPUarmMapFeatureFind(map, cpu->features[i].name)) {
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                           _("unknown CPU feature: %s"),
+                           cpu->features[i].name);
+            return -1;
+        }
+    }
+
+    return 0;
+}
+
 struct cpuArchDriver cpuDriverArm = {
     .name = "arm",
     .arch = archs,
@@ -107,4 +277,5 @@ struct cpuArchDriver cpuDriverArm = {
     .encode = NULL,
     .baseline = virCPUarmBaseline,
     .update = virCPUarmUpdate,
+    .validateFeatures = virCPUarmValidateFeatures,
 };
-- 
2.21.0




More information about the libvir-list mailing list