From ea6c107a5fd327f905dd2d04e6b1c07f9e2b3511 Mon Sep 17 00:00:00 2001 From: Andrea Bolognani Date: Fri, 11 Oct 2019 10:05:49 +0200 Subject: [PATCH] cpu: Validate ARM CPU features 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 Tested-by: Andrew Jones Reviewed-by: Michal Privoznik --- 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, };