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

Andrea Bolognani abologna at redhat.com
Wed Nov 6 15:47:08 UTC 2019


For now we only perform very basic validation, such as making sure
that the user is not trying to enable/disable unknown CPU features
and the like.

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

diff --git a/src/cpu/cpu_arm.c b/src/cpu/cpu_arm.c
index a102c6fda4..70dba6021c 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,137 @@ static const virArch archs[] = {
     VIR_ARCH_AARCH64,
 };
 
+typedef struct _virCPUarmFeature virCPUarmFeature;
+typedef virCPUarmFeature *virCPUarmFeaturePtr;
+struct _virCPUarmFeature {
+    char *name;
+};
+
+static virCPUarmFeaturePtr
+virCPUarmFeatureNew(void)
+{
+    return g_new0(virCPUarmFeature, 1);
+}
+
+static void
+virCPUarmFeatureFree(virCPUarmFeaturePtr feature)
+{
+    if (!feature)
+        return;
+
+    g_free(feature->name);
+
+    g_free(feature);
+}
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(virCPUarmFeature, virCPUarmFeatureFree);
+
+typedef struct _virCPUarmMap virCPUarmMap;
+typedef virCPUarmMap *virCPUarmMapPtr;
+struct _virCPUarmMap {
+    GPtrArray *features;
+};
+
+static virCPUarmMapPtr
+virCPUarmMapNew(void)
+{
+    virCPUarmMapPtr map;
+
+    map = g_new0(virCPUarmMap, 1);
+
+    map->features = g_ptr_array_new();
+    g_ptr_array_set_free_func(map->features,
+                              (GDestroyNotify) virCPUarmFeatureFree);
+
+    return map;
+}
+
+static void
+virCPUarmMapFree(virCPUarmMapPtr map)
+{
+    if (!map)
+        return;
+
+    g_ptr_array_free(map->features, TRUE);
+
+    g_free(map);
+}
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC(virCPUarmMap, virCPUarmMapFree);
+
+static virCPUarmFeaturePtr
+virCPUarmMapFeatureFind(virCPUarmMapPtr map,
+                        const char *name)
+{
+    size_t i;
+
+    for (i = 0; i < map->features->len; i++) {
+        virCPUarmFeaturePtr feature = g_ptr_array_index(map->features, i);
+
+        if (STREQ(feature->name, name))
+            return feature;
+    }
+
+    return NULL;
+}
+
+static int
+virCPUarmMapFeatureParse(xmlXPathContextPtr ctxt G_GNUC_UNUSED,
+                         const char *name,
+                         void *data)
+{
+    g_autoptr(virCPUarmFeature) feature = NULL;
+    virCPUarmMapPtr map = data;
+
+    if (virCPUarmMapFeatureFind(map, name)) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+                       _("CPU feature %s already defined"), name);
+        return -1;
+    }
+
+    feature = virCPUarmFeatureNew();
+    feature->name = g_strdup(name);
+
+    g_ptr_array_add(map->features, g_steal_pointer(&feature));
+
+    return 0;
+}
+
+static virCPUarmMapPtr
+virCPUarmLoadMap(void)
+{
+    g_autoptr(virCPUarmMap) map = NULL;
+
+    map = virCPUarmMapNew();
+
+    if (cpuMapLoad("arm", NULL, virCPUarmMapFeatureParse, NULL, map) < 0)
+        return NULL;
+
+    return g_steal_pointer(&map);
+}
+
+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,
@@ -99,6 +232,29 @@ virCPUarmCompare(virCPUDefPtr host G_GNUC_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++) {
+        virCPUFeatureDefPtr feature = &cpu->features[i];
+
+        if (!virCPUarmMapFeatureFind(map, feature->name)) {
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                           _("unknown CPU feature: %s"),
+                           feature->name);
+            return -1;
+        }
+    }
+
+    return 0;
+}
+
 struct cpuArchDriver cpuDriverArm = {
     .name = "arm",
     .arch = archs,
@@ -108,4 +264,5 @@ struct cpuArchDriver cpuDriverArm = {
     .encode = NULL,
     .baseline = virCPUarmBaseline,
     .update = virCPUarmUpdate,
+    .validateFeatures = virCPUarmValidateFeatures,
 };
-- 
2.21.0




More information about the libvir-list mailing list