diff --git a/libvirt-cpu-arm-add-cpu-data-free-function-to-virCPUarmDataF.patch b/libvirt-cpu-arm-add-cpu-data-free-function-to-virCPUarmDataF.patch new file mode 100644 index 0000000..2adbb48 --- /dev/null +++ b/libvirt-cpu-arm-add-cpu-data-free-function-to-virCPUarmDataF.patch @@ -0,0 +1,51 @@ +From efde450d2d0648475cde04f04f5e26c1a006c226 Mon Sep 17 00:00:00 2001 +From: Xu Yandong +Date: Fri, 17 Apr 2020 14:40:27 +0800 +Subject: cpu/arm: add cpu data free function to virCPUarmDataFree + +Signed-off-by: Xu Yandong +--- + src/cpu/cpu_arm.c | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + +diff --git a/src/cpu/cpu_arm.c b/src/cpu/cpu_arm.c +index ee58021..230cd27 100644 +--- a/src/cpu/cpu_arm.c ++++ b/src/cpu/cpu_arm.c +@@ -61,6 +61,25 @@ virCPUarmFeatureFree(virCPUarmFeaturePtr feature) + + G_DEFINE_AUTOPTR_CLEANUP_FUNC(virCPUarmFeature, virCPUarmFeatureFree); + ++static void ++virCPUarmDataClear(virCPUarmData *data) ++{ ++ if (!data) ++ return; ++ ++ VIR_FREE(data->features); ++} ++ ++static void ++virCPUarmDataFree(virCPUDataPtr cpuData) ++{ ++ if (!cpuData) ++ return; ++ ++ virCPUarmDataClear(&cpuData->data.arm); ++ VIR_FREE(cpuData); ++} ++ + typedef struct _virCPUarmMap virCPUarmMap; + typedef virCPUarmMap *virCPUarmMapPtr; + struct _virCPUarmMap { +@@ -259,6 +278,7 @@ struct cpuArchDriver cpuDriverArm = { + .compare = virCPUarmCompare, + .decode = NULL, + .encode = NULL, ++ .dataFree = virCPUarmDataFree, + .baseline = virCPUarmBaseline, + .update = virCPUarmUpdate, + .validateFeatures = virCPUarmValidateFeatures, +-- +2.23.0 + diff --git a/libvirt-cpu-arm-add-decode-function.patch b/libvirt-cpu-arm-add-decode-function.patch new file mode 100644 index 0000000..6b43380 --- /dev/null +++ b/libvirt-cpu-arm-add-decode-function.patch @@ -0,0 +1,275 @@ +From c69a629367b0e9bfa1a034301a4c3f88ad080586 Mon Sep 17 00:00:00 2001 +From: Xu Yandong +Date: Sat, 18 Apr 2020 11:16:13 +0800 +Subject: cpu/arm: add decode function + +Signed-off-by: Xu Yandong +--- + src/cpu/cpu_arm.c | 150 ++++++++++++++++++++++++++++++++++-------- + src/cpu_map/index.xml | 3 - + 2 files changed, 122 insertions(+), 31 deletions(-) + +diff --git a/src/cpu/cpu_arm.c b/src/cpu/cpu_arm.c +index d85f111..eb9b1c9 100644 +--- a/src/cpu/cpu_arm.c ++++ b/src/cpu/cpu_arm.c +@@ -55,7 +55,6 @@ virCPUarmFeatureFree(virCPUarmFeaturePtr feature) + return; + + g_free(feature->name); +- + g_free(feature); + } + +@@ -80,6 +79,8 @@ virCPUarmDataFree(virCPUDataPtr cpuData) + g_free(cpuData); + } + ++G_DEFINE_AUTOPTR_CLEANUP_FUNC(virCPUData, virCPUarmDataFree); ++ + typedef struct _virCPUarmVendor virCPUarmVendor; + typedef virCPUarmVendor *virCPUarmVendorPtr; + struct _virCPUarmVendor { +@@ -103,6 +104,8 @@ virCPUarmVendorFree(virCPUarmVendorPtr vendor) + VIR_FREE(vendor); + } + ++G_DEFINE_AUTOPTR_CLEANUP_FUNC(virCPUarmVendor, virCPUarmVendorFree); ++ + typedef struct _virCPUarmModel virCPUarmModel; + typedef virCPUarmModel *virCPUarmModelPtr; + struct _virCPUarmModel { +@@ -175,6 +178,38 @@ virCPUarmMapFree(virCPUarmMapPtr map) + + G_DEFINE_AUTOPTR_CLEANUP_FUNC(virCPUarmMap, virCPUarmMapFree); + ++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 virCPUarmFeaturePtr + virCPUarmMapFeatureFind(virCPUarmMapPtr map, + const char *name) +@@ -213,36 +248,43 @@ virCPUarmMapFeatureParse(xmlXPathContextPtr ctxt G_GNUC_UNUSED, + return 0; + } + +-static virCPUarmVendorPtr +-virCPUarmVendorFindByID(virCPUarmMapPtr map, +- unsigned long vendor_id) ++static int ++armCpuDataParseFeatures(virCPUDefPtr cpu, ++ const virCPUarmData *cpuData) + { ++ int ret = -1; + size_t i; ++ char **features; + +- for (i = 0; i < map->vendors->len; i++) { +- virCPUarmVendorPtr vendor = g_ptr_array_index(map->vendors, i); ++ if (!cpu || !cpuData) ++ return ret; + +- if (vendor->value == vendor_id) +- return vendor; +- } ++ if (!(features = virStringSplitCount(cpuData->features, " ", ++ 0, &cpu->nfeatures))) ++ return ret; + +- return NULL; +-} ++ if (cpu->nfeatures) { ++ if (VIR_ALLOC_N(cpu->features, cpu->nfeatures) < 0) ++ goto error; + +-static virCPUarmVendorPtr +-virCPUarmVendorFindByName(virCPUarmMapPtr map, +- const char *name) +-{ +- size_t i; ++ for (i = 0; i < cpu->nfeatures; i++) { ++ cpu->features[i].policy = VIR_CPU_FEATURE_REQUIRE; ++ cpu->features[i].name = g_strdup(features[i]); ++ } ++ } + +- for (i = 0; i < map->vendors->len; i++) { +- virCPUarmVendorPtr vendor = g_ptr_array_index(map->vendors, i); ++ ret = 0; + +- if (STREQ(vendor->name, name)) +- return vendor; +- } ++cleanup: ++ virStringListFree(features); ++ return ret; + +- return NULL; ++error: ++ for (i = 0; i < cpu->nfeatures; i++) ++ VIR_FREE(cpu->features[i].name); ++ VIR_FREE(cpu->features); ++ cpu->nfeatures = 0; ++ goto cleanup; + } + + static int +@@ -252,7 +294,6 @@ virCPUarmVendorParse(xmlXPathContextPtr ctxt, + { + virCPUarmMapPtr map = (virCPUarmMapPtr)data; + g_autoptr(virCPUarmVendor) vendor = NULL; +- int ret = -1; + + if (virCPUarmVendorFindByName(map, name)) { + virReportError(VIR_ERR_INTERNAL_ERROR, +@@ -289,7 +330,7 @@ virCPUarmModelFindByPVR(virCPUarmMapPtr map, + for (i = 0; i < map->models->len; i++) { + virCPUarmModelPtr model = g_ptr_array_index(map->models, i); + +- if (STREQ(model->pvr, pvr)) ++ if (model->data.pvr == pvr) + return model; + } + +@@ -299,7 +340,7 @@ virCPUarmModelFindByPVR(virCPUarmMapPtr map, + + static virCPUarmModelPtr + virCPUarmModelFindByName(virCPUarmMapPtr map, +- const char *name) ++ const char *name) + { + size_t i; + +@@ -321,7 +362,6 @@ virCPUarmModelParse(xmlXPathContextPtr ctxt, + virCPUarmMapPtr map = (virCPUarmMapPtr)data; + g_autoptr(virCPUarmModel) model = NULL; + char *vendor = NULL; +- int ret = -1; + + if (virCPUarmModelFindByName(map, name)) { + virReportError(VIR_ERR_INTERNAL_ERROR, +@@ -404,6 +444,60 @@ virCPUarmGetMap(void) + return cpuMap; + } + ++static int ++virCPUarmDecode(virCPUDefPtr cpu, ++ const virCPUarmData *cpuData, ++ virDomainCapsCPUModelsPtr models) ++{ ++ virCPUarmMapPtr map; ++ virCPUarmModelPtr model; ++ virCPUarmVendorPtr vendor = NULL; ++ ++ if (!cpuData || !(map = virCPUarmGetMap())) ++ return -1; ++ ++ if (!(model = virCPUarmModelFindByPVR(map, cpuData->pvr))) { ++ virReportError(VIR_ERR_OPERATION_FAILED, ++ _("Cannot find CPU model with PVR 0x%03lx"), ++ cpuData->pvr); ++ return -1; ++ } ++ ++ if (!virCPUModelIsAllowed(model->name, models)) { ++ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, ++ _("CPU model %s is not supported by hypervisor"), ++ model->name); ++ return -1; ++ } ++ ++ cpu->model = g_strdup(model->name); ++ ++ if (cpuData->vendor_id && ++ !(vendor = virCPUarmVendorFindByID(map, cpuData->vendor_id))) { ++ virReportError(VIR_ERR_OPERATION_FAILED, ++ _("Cannot find CPU vendor with vendor id 0x%02lx"), ++ cpuData->vendor_id); ++ return -1; ++ } ++ ++ if (vendor) ++ cpu->vendor = g_strdup(vendor->name); ++ ++ if (cpuData->features && ++ armCpuDataParseFeatures(cpu, cpuData) < 0) ++ return -1; ++ ++ return 0; ++} ++ ++static int ++virCPUarmDecodeCPUData(virCPUDefPtr cpu, ++ const virCPUData *data, ++ virDomainCapsCPUModelsPtr models) ++{ ++ return virCPUarmDecode(cpu, &data->data.arm, models); ++} ++ + static int + virCPUarmUpdate(virCPUDefPtr guest, + const virCPUDef *host) +@@ -432,7 +526,7 @@ virCPUarmUpdate(virCPUDefPtr guest, + guest->match = VIR_CPU_MATCH_EXACT; + ret = 0; + +- cleanup: ++cleanup: + virCPUDefFree(updated); + return ret; + } +@@ -493,7 +587,7 @@ struct cpuArchDriver cpuDriverArm = { + .arch = archs, + .narch = G_N_ELEMENTS(archs), + .compare = virCPUarmCompare, +- .decode = NULL, ++ .decode = virCPUarmDecodeCPUData, + .encode = NULL, + .dataFree = virCPUarmDataFree, + .baseline = virCPUarmBaseline, +diff --git a/src/cpu_map/index.xml b/src/cpu_map/index.xml +index 2e78834..985af86 100644 +--- a/src/cpu_map/index.xml ++++ b/src/cpu_map/index.xml +@@ -86,9 +86,6 @@ + + + +- +- +- + + + +-- +2.23.0 + diff --git a/libvirt-cpu-arm-add-load-cpu-map-parse-function.patch b/libvirt-cpu-arm-add-load-cpu-map-parse-function.patch new file mode 100644 index 0000000..cf59ab2 --- /dev/null +++ b/libvirt-cpu-arm-add-load-cpu-map-parse-function.patch @@ -0,0 +1,287 @@ +From a0574d45603010761d3f3034f97457fda94d2266 Mon Sep 17 00:00:00 2001 +From: Xu Yandong +Date: Fri, 17 Apr 2020 18:13:32 +0800 +Subject: cpu/arm: add load cpu map parse function + +Signed-off-by: Xu Yandong +--- + 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 + diff --git a/libvirt-cpu-arm-add-virCPUarmGetHost-implment.patch b/libvirt-cpu-arm-add-virCPUarmGetHost-implment.patch new file mode 100644 index 0000000..9812042 --- /dev/null +++ b/libvirt-cpu-arm-add-virCPUarmGetHost-implment.patch @@ -0,0 +1,127 @@ +From 208c9f1eb9a06d2550b7b3cfe0172840925255d4 Mon Sep 17 00:00:00 2001 +From: Xu Yandong +Date: Mon, 20 Apr 2020 17:29:17 +0800 +Subject: cpu/arm: add virCPUarmGetHost implment + +Signed-off-by: Xu Yandong +--- + src/cpu/cpu_arm.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 86 insertions(+) + +diff --git a/src/cpu/cpu_arm.c b/src/cpu/cpu_arm.c +index eb9b1c9..78e604c 100644 +--- a/src/cpu/cpu_arm.c ++++ b/src/cpu/cpu_arm.c +@@ -26,9 +26,15 @@ + #include "cpu_map.h" + #include "virstring.h" + #include "virxml.h" ++#include "virfile.h" + + #define VIR_FROM_THIS VIR_FROM_CPU + ++static const char *sysinfoCpuinfo = "/proc/cpuinfo"; ++ ++#define CPUINFO sysinfoCpuinfo ++#define CPUINFO_FILE_LEN (1024*1024) /* 1MB limit for /proc/cpuinfo file */ ++ + static const virArch archs[] = { + VIR_ARCH_ARMV6L, + VIR_ARCH_ARMV7B, +@@ -531,6 +537,85 @@ cleanup: + return ret; + } + ++static int ++armCpuDataFromCpuInfo(virCPUarmData *data) ++{ ++ g_autofree char *str_vendor = NULL; ++ g_autofree char *str_pvr = NULL; ++ g_autofree char *outbuf = NULL; ++ char *eol = NULL; ++ const char *cur; ++ ++ if (!data) ++ return -1; ++ ++ if (virFileReadAll(CPUINFO, CPUINFO_FILE_LEN, &outbuf) < 0) { ++ virReportError(VIR_ERR_INTERNAL_ERROR, ++ _("Failed to open %s"), CPUINFO); ++ return -1; ++ } ++ ++ /* Account for format 'CPU implementer : XXXX' */ ++ if ((cur = strstr(outbuf, "CPU implementer")) == NULL) { ++ virReportError(VIR_ERR_INTERNAL_ERROR, ++ _("there is no \"CPU implementer\" info in %s"), CPUINFO); ++ return -1; ++ } ++ ++ cur = strchr(cur, ':') + 1; ++ eol = strchr(cur, '\n'); ++ virSkipSpaces(&cur); ++ if (!eol || !(str_vendor = g_strndup(cur, eol - cur)) || ++ virStrToLong_ul(str_vendor, NULL, 16, &data->vendor_id) < 0) ++ return -1; ++ ++ /* Account for format 'CPU part : XXXX' */ ++ if ((cur = strstr(outbuf, "CPU part")) == NULL) { ++ virReportError(VIR_ERR_INTERNAL_ERROR, ++ _("there is no \"CPU part\" info in %s"), CPUINFO); ++ return -1; ++ } ++ ++ cur = strchr(cur, ':') + 1; ++ eol = strchr(cur, '\n'); ++ virSkipSpaces(&cur); ++ if (!eol || !(str_pvr = g_strndup(cur, eol - cur)) || ++ virStrToLong_ul(str_pvr, NULL, 16, &data->pvr) < 0) ++ return -1; ++ ++ /* Account for format 'CPU Features : XXXX' */ ++ if ((cur = strstr(outbuf, "Features")) == NULL) { ++ virReportError(VIR_ERR_INTERNAL_ERROR, ++ _("there is no \"Features\" info in %s"), CPUINFO); ++ return -1; ++ } ++ cur = strchr(cur, ':') + 1; ++ eol = strchr(cur, '\n'); ++ virSkipSpaces(&cur); ++ if (eol && !(data->features = g_strndup(cur, eol - cur))) ++ return -1; ++ ++ return 0; ++} ++ ++static int ++virCPUarmGetHost(virCPUDefPtr cpu, ++ virDomainCapsCPUModelsPtr models) ++{ ++ g_autoptr(virCPUData) cpuData = NULL; ++ ++ if (virCPUarmDriverInitialize() < 0) ++ return -1; ++ ++ if (!(cpuData = virCPUDataNew(archs[0]))) ++ return -1; ++ ++ if (armCpuDataFromCpuInfo(&cpuData->data.arm) < 0) ++ return -1; ++ ++ return virCPUarmDecodeCPUData(cpu, cpuData, models); ++} ++ + + static virCPUDefPtr + virCPUarmBaseline(virCPUDefPtr *cpus, +@@ -590,6 +675,7 @@ struct cpuArchDriver cpuDriverArm = { + .decode = virCPUarmDecodeCPUData, + .encode = NULL, + .dataFree = virCPUarmDataFree, ++ .getHost = virCPUarmGetHost, + .baseline = virCPUarmBaseline, + .update = virCPUarmUpdate, + .validateFeatures = virCPUarmValidateFeatures, +-- +2.23.0 + diff --git a/libvirt-cpu-arm-implment-cpu-baseline-function.patch b/libvirt-cpu-arm-implment-cpu-baseline-function.patch new file mode 100644 index 0000000..d9dc344 --- /dev/null +++ b/libvirt-cpu-arm-implment-cpu-baseline-function.patch @@ -0,0 +1,216 @@ +From 4606782bde2a6e75e88d782fc58e5db5365502c2 Mon Sep 17 00:00:00 2001 +From: Xu Yandong +Date: Mon, 20 Apr 2020 19:17:56 +0800 +Subject: cpu/arm: implment cpu baseline function + +Signed-off-by: Xu Yandong +--- + src/cpu/cpu_arm.c | 178 ++++++++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 174 insertions(+), 4 deletions(-) + +diff --git a/src/cpu/cpu_arm.c b/src/cpu/cpu_arm.c +index 78e604c..a7c9523 100644 +--- a/src/cpu/cpu_arm.c ++++ b/src/cpu/cpu_arm.c +@@ -616,24 +616,194 @@ virCPUarmGetHost(virCPUDefPtr cpu, + return virCPUarmDecodeCPUData(cpu, cpuData, models); + } + ++static void ++virCPUarmDataIntersect(virCPUarmData *data1, ++ const virCPUarmData *data2) ++{ ++ char **features = NULL; ++ char **features1 = NULL; ++ char **features2 = NULL; ++ size_t count = 0; ++ size_t i; ++ ++ if (!data1 || !data2) ++ return; ++ ++ data1->pvr = MIN(data1->pvr, data2->pvr); ++ ++ if (virStringIsEmpty(data1->features) || ++ virStringIsEmpty(data2->features)) { ++ VIR_FREE(data1->features); ++ return; ++ } ++ ++ if (STREQ_NULLABLE(data1->features, data2->features)) ++ return; ++ ++ if (!(features = virStringSplitCount(data1->features, " ", 0, &count)) || ++ !(features1 = virStringSplitCount(data1->features, " ", 0, &count)) || ++ !(features2 = virStringSplit(data2->features, " ", 0))) ++ goto cleanup; ++ ++ for (i = 0; i < count; i++) { ++ if (!virStringListHasString((const char**)features2, features1[i])) ++ virStringListRemove(&features, features1[i]); ++ } ++ ++ VIR_FREE(data1->features); ++ if (features) ++ data1->features = virStringListJoin((const char**)features, " "); ++ ++cleanup: ++ virStringListFree(features); ++ virStringListFree(features1); ++ virStringListFree(features2); ++ return; ++} ++ ++static void ++virCPUarmDataCopy(virCPUarmData *dst, const virCPUarmData *src) ++{ ++ dst->features = g_strdup(src->features); ++ dst->vendor_id = src->vendor_id; ++ dst->pvr = src->pvr; ++} ++ ++static virCPUarmModelPtr ++virCPUarmModelCopy(virCPUarmModelPtr model) ++{ ++ g_autoptr(virCPUarmModel) copy = NULL; ++ ++ copy = virCPUarmModelNew(); ++ ++ virCPUarmDataCopy(©->data, &model->data); ++ copy->name = g_strdup(model->name); ++ copy->vendor = model->vendor; ++ ++ return g_steal_pointer(©); ++} ++ ++static virCPUarmModelPtr ++virCPUarmModelFromCPU(const virCPUDef *cpu, ++ virCPUarmMapPtr map) ++{ ++ g_autoptr(virCPUarmModel) model = NULL; ++ virCPUarmVendorPtr vendor = NULL; ++ char **features = NULL; ++ size_t i; ++ ++ if (!cpu->model) { ++ virReportError(VIR_ERR_INVALID_ARG, "%s", ++ _("no CPU model specified")); ++ return NULL; ++ } ++ ++ if (!(model = virCPUarmModelFindByName(map, cpu->model))) { ++ virReportError(VIR_ERR_INTERNAL_ERROR, ++ _("Unknown CPU model %s"), cpu->model); ++ return NULL; ++ } ++ ++ if (!(model = virCPUarmModelCopy(model))) ++ return NULL; ++ ++ if (cpu->vendor) { ++ if (!(vendor = virCPUarmVendorFindByName(map, cpu->vendor))) { ++ virReportError(VIR_ERR_INTERNAL_ERROR, ++ _("Unknown CPU vendor %s"), cpu->vendor); ++ return NULL; ++ } ++ model->data.vendor_id = vendor->value; ++ } ++ ++ if (cpu->nfeatures) { ++ if (VIR_REALLOC_N(features, cpu->nfeatures + 1) < 0) ++ return model; ++ ++ features[cpu->nfeatures] = NULL; ++ for (i = 0; i < cpu->nfeatures; i++) ++ features[i] = g_strdup(cpu->features[i].name); ++ VIR_FREE(model->data.features); ++ model->data.features = virStringListJoin((const char **)features, " "); ++ } ++ ++ virStringListFree(features); ++ return g_steal_pointer(&model); ++} + + static virCPUDefPtr + virCPUarmBaseline(virCPUDefPtr *cpus, +- unsigned int ncpus G_GNUC_UNUSED, +- virDomainCapsCPUModelsPtr models G_GNUC_UNUSED, ++ unsigned int ncpus, ++ virDomainCapsCPUModelsPtr models, + const char **features G_GNUC_UNUSED, + bool migratable G_GNUC_UNUSED) + { +- virCPUDefPtr cpu = NULL; ++ virCPUarmMapPtr map = NULL; ++ g_autoptr(virCPUDef) cpu = NULL; ++ g_autoptr(virCPUarmModel) model = NULL; ++ g_autoptr(virCPUarmModel) baseModel = NULL; ++ virCPUarmVendorPtr vendor = NULL; ++ bool outputVendor = true; ++ size_t i; + + cpu = virCPUDefNew(); + + cpu->model = g_strdup(cpus[0]->model); + ++ cpu->arch = cpus[0]->arch; + cpu->type = VIR_CPU_TYPE_GUEST; + cpu->match = VIR_CPU_MATCH_EXACT; ++ cpu->fallback = VIR_CPU_FALLBACK_FORBID; ++ ++ if (!(map = virCPUarmGetMap())) ++ return NULL; ++ ++ if (!(baseModel = virCPUarmModelFromCPU(cpus[0], map))) ++ return NULL; ++ ++ if (!cpus[0]->vendor) { ++ outputVendor = false; ++ } else if (!(vendor = virCPUarmVendorFindByName(map, cpus[0]->vendor))) { ++ virReportError(VIR_ERR_OPERATION_FAILED, ++ _("Unknown CPU vendor %s"), cpus[0]->vendor); ++ return NULL; ++ } ++ ++ for (i = 0; i < ncpus; i++) { ++ const char *vn = NULL; ++ if (!(model = virCPUarmModelFromCPU(cpus[i], map))) ++ return NULL; ++ ++ if (cpus[i]->vendor) { ++ vn = cpus[i]->vendor; ++ } else { ++ outputVendor = false; ++ } ++ ++ if (vn) { ++ if (!vendor) { ++ if (!(vendor = virCPUarmVendorFindByName(map, vn))) { ++ virReportError(VIR_ERR_OPERATION_FAILED, ++ _("Unknown CPU vendor %s"), vn); ++ return NULL; ++ } ++ } else if (STRNEQ(vendor->name, vn)) { ++ virReportError(VIR_ERR_OPERATION_FAILED, ++ "%s", _("CPU vendors do not match")); ++ return NULL; ++ } ++ ++ virCPUarmDataIntersect(&baseModel->data, &model->data); ++ } ++ } ++ ++ if (virCPUarmDecode(cpu, &baseModel->data, models) < 0) ++ return NULL; ++ ++ if (!outputVendor) ++ g_free(cpu->vendor); + +- return cpu; ++ return g_steal_pointer(&cpu); + } + + static virCPUCompareResult +-- +2.23.0 + diff --git a/libvirt-cpu-arm-implment-cpu-compare-function.patch b/libvirt-cpu-arm-implment-cpu-compare-function.patch new file mode 100644 index 0000000..c08e4bb --- /dev/null +++ b/libvirt-cpu-arm-implment-cpu-compare-function.patch @@ -0,0 +1,239 @@ +From 1a70b1e3bdbd8d0dcf9281341bc23b4ff2ffaa3a Mon Sep 17 00:00:00 2001 +From: Xu Yandong +Date: Mon, 20 Apr 2020 19:33:49 +0800 +Subject: cpu/arm: implment cpu compare function + +Signed-off-by: Xu Yandong +--- + src/cpu/cpu_arm.c | 196 +++++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 193 insertions(+), 3 deletions(-) + +diff --git a/src/cpu/cpu_arm.c b/src/cpu/cpu_arm.c +index a7c9523..3ef54b9 100644 +--- a/src/cpu/cpu_arm.c ++++ b/src/cpu/cpu_arm.c +@@ -21,6 +21,7 @@ + + #include + ++#include "virlog.h" + #include "viralloc.h" + #include "cpu.h" + #include "cpu_map.h" +@@ -30,6 +31,8 @@ + + #define VIR_FROM_THIS VIR_FROM_CPU + ++VIR_LOG_INIT("cpu.cpu_arm"); ++ + static const char *sysinfoCpuinfo = "/proc/cpuinfo"; + + #define CPUINFO sysinfoCpuinfo +@@ -806,14 +809,201 @@ virCPUarmBaseline(virCPUDefPtr *cpus, + return g_steal_pointer(&cpu); + } + ++static bool ++virCPUarmFeaturesIsSub(char *subFeatures, ++ char *fullFeatures) ++{ ++ bool ret = false; ++ char **sub = NULL; ++ char **full = NULL; ++ size_t subCount = 0; ++ size_t fullCount = 0; ++ size_t i; ++ ++ if (virStringIsEmpty(subFeatures)) ++ return true; ++ ++ if (virStringIsEmpty(fullFeatures)) ++ return ret; ++ ++ if (STREQ(subFeatures, fullFeatures)) ++ return true; ++ ++ if (!(sub = virStringSplitCount(subFeatures, " ", 0, &subCount)) || ++ !(full = virStringSplitCount(fullFeatures, " ", 0, &fullCount)) || ++ subCount > fullCount) ++ goto cleanup; ++ ++ for (i = 0; i < subCount; i++) { ++ if (!virStringListHasString((const char**)full, sub[i])) ++ goto cleanup; ++ } ++ ++ ret = true; ++ ++ cleanup: ++ virStringListFree(sub); ++ virStringListFree(full); ++ return ret; ++} ++ ++static virCPUDataPtr ++armMakeCPUData(virArch arch, ++ virCPUarmData *data) ++{ ++ virCPUDataPtr cpuData; ++ ++ if (!(cpuData = virCPUDataNew(arch))) ++ return NULL; ++ ++ virCPUarmDataCopy(&cpuData->data.arm, data); ++ ++ return cpuData; ++} ++ + static virCPUCompareResult +-virCPUarmCompare(virCPUDefPtr host G_GNUC_UNUSED, +- virCPUDefPtr cpu G_GNUC_UNUSED, +- bool failMessages G_GNUC_UNUSED) ++armCompute(virCPUDefPtr host, ++ virCPUDefPtr cpu, ++ virCPUDataPtr *guestData, ++ char **message) + { ++ virCPUarmMapPtr map = NULL; ++ g_autoptr(virCPUarmModel) hostModel = NULL; ++ g_autoptr(virCPUarmModel) guestModel = NULL; ++ virArch arch; ++ size_t i; ++ ++ if (cpu->arch != VIR_ARCH_NONE) { ++ bool found = false; ++ ++ for (i = 0; i < G_N_ELEMENTS(archs); i++) { ++ if (archs[i] == cpu->arch) { ++ found = true; ++ break; ++ } ++ } ++ ++ if (!found) { ++ VIR_DEBUG("CPU arch %s does not match host arch", ++ virArchToString(cpu->arch)); ++ if (message) ++ *message = g_strdup_printf(_("CPU arch %s does not match host arch"), ++ virArchToString(cpu->arch)); ++ ++ return VIR_CPU_COMPARE_INCOMPATIBLE; ++ } ++ arch = cpu->arch; ++ } else { ++ arch = host->arch; ++ } ++ ++ if (cpu->vendor && ++ (!host->vendor || STRNEQ(cpu->vendor, host->vendor))) { ++ VIR_DEBUG("host CPU vendor does not match required CPU vendor %s", ++ cpu->vendor); ++ if (message) ++ *message = g_strdup_printf(_("host CPU vendor does not match required " ++ "CPU vendor %s"), ++ cpu->vendor); ++ ++ return VIR_CPU_COMPARE_INCOMPATIBLE; ++ } ++ ++ if (!(map = virCPUarmGetMap())) ++ return VIR_CPU_COMPARE_ERROR; ++ ++ /* Host CPU information */ ++ if (!(hostModel = virCPUarmModelFromCPU(host, map))) ++ return VIR_CPU_COMPARE_ERROR; ++ ++ if (cpu->type == VIR_CPU_TYPE_GUEST) { ++ /* Guest CPU information */ ++ switch (cpu->mode) { ++ case VIR_CPU_MODE_HOST_MODEL: ++ case VIR_CPU_MODE_HOST_PASSTHROUGH: ++ /* host-model and host-passthrough: ++ * the guest CPU is the same as the host */ ++ guestModel = virCPUarmModelCopy(hostModel); ++ break; ++ ++ case VIR_CPU_MODE_CUSTOM: ++ /* custom: ++ * look up guest CPU information */ ++ guestModel = virCPUarmModelFromCPU(cpu, map); ++ break; ++ } ++ } else { ++ /* Other host CPU information */ ++ guestModel = virCPUarmModelFromCPU(cpu, map); ++ } ++ ++ if (!guestModel) ++ return VIR_CPU_COMPARE_ERROR; ++ ++ if (STRNEQ(guestModel->name, hostModel->name)) { ++ VIR_DEBUG("host CPU model %s does not match required CPU model %s", ++ hostModel->name, guestModel->name); ++ if (message) ++ *message = g_strdup_printf(_("host CPU model %s does not match required " ++ "CPU model %s"), ++ hostModel->name, guestModel->name); ++ ++ return VIR_CPU_COMPARE_INCOMPATIBLE; ++ } ++ ++ if (!virCPUarmFeaturesIsSub(guestModel->data.features, hostModel->data.features)) { ++ VIR_DEBUG("guest CPU features '%s' is not subset of " ++ "host CPU features '%s'", ++ guestModel->data.features, hostModel->data.features); ++ if (message) ++ *message = g_strdup_printf(_("guest CPU features '%s' is not subset of " ++ "host CPU features '%s'"), ++ guestModel->data.features, ++ hostModel->data.features); ++ ++ return VIR_CPU_COMPARE_INCOMPATIBLE; ++ } ++ ++ if (guestData && ++ !(*guestData = armMakeCPUData(arch, &guestModel->data))) ++ return VIR_CPU_COMPARE_ERROR; ++ + return VIR_CPU_COMPARE_IDENTICAL; + } + ++static virCPUCompareResult ++virCPUarmCompare(virCPUDefPtr host, ++ virCPUDefPtr cpu, ++ bool failMessages) ++{ ++ virCPUCompareResult ret = VIR_CPU_COMPARE_ERROR; ++ g_autofree char *message = NULL; ++ ++ if (!host || !host->model) { ++ if (failMessages) { ++ virReportError(VIR_ERR_CPU_INCOMPATIBLE, "%s", ++ _("unknown host CPU")); ++ } else { ++ VIR_WARN("unknown host CPU"); ++ return VIR_CPU_COMPARE_INCOMPATIBLE; ++ } ++ return VIR_CPU_COMPARE_ERROR; ++ } ++ ++ ret = armCompute(host, cpu, NULL, &message); ++ ++ if (failMessages && ret == VIR_CPU_COMPARE_INCOMPATIBLE) { ++ if (message) { ++ virReportError(VIR_ERR_CPU_INCOMPATIBLE, "%s", message); ++ } else { ++ virReportError(VIR_ERR_CPU_INCOMPATIBLE, NULL); ++ } ++ return VIR_CPU_COMPARE_ERROR; ++ } ++ ++ return ret; ++} ++ + static int + virCPUarmValidateFeatures(virCPUDefPtr cpu) + { +-- +2.23.0 + diff --git a/libvirt-cpu-introduce-virCPUarmData-to-virCPUData.patch b/libvirt-cpu-introduce-virCPUarmData-to-virCPUData.patch new file mode 100644 index 0000000..51afaa1 --- /dev/null +++ b/libvirt-cpu-introduce-virCPUarmData-to-virCPUData.patch @@ -0,0 +1,76 @@ +From 43ebd81b60121ce002a58ebc046b19f31bb23cb6 Mon Sep 17 00:00:00 2001 +From: Xu Yandong +Date: Thu, 16 Apr 2020 11:00:49 +0800 +Subject: cpu: introduce virCPUarmData to virCPUData + +introduce virCPUarmData to virCPUData union, CPUarmData include +vendor id, pvr and cpu features. + +Signed-off-by: Xu Yandong +--- + src/cpu/cpu.h | 2 ++ + src/cpu/cpu_arm_data.h | 32 ++++++++++++++++++++++++++++++++ + 2 files changed, 34 insertions(+) + create mode 100644 src/cpu/cpu_arm_data.h + +diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h +index f779d2b..ec22a18 100644 +--- a/src/cpu/cpu.h ++++ b/src/cpu/cpu.h +@@ -27,6 +27,7 @@ + #include "cpu_conf.h" + #include "cpu_x86_data.h" + #include "cpu_ppc64_data.h" ++#include "cpu_arm_data.h" + + + typedef struct _virCPUData virCPUData; +@@ -36,6 +37,7 @@ struct _virCPUData { + union { + virCPUx86Data x86; + virCPUppc64Data ppc64; ++ virCPUarmData arm; + /* generic driver needs no data */ + } data; + }; +diff --git a/src/cpu/cpu_arm_data.h b/src/cpu/cpu_arm_data.h +new file mode 100644 +index 0000000..72b3a29 +--- /dev/null ++++ b/src/cpu/cpu_arm_data.h +@@ -0,0 +1,32 @@ ++/* ++ * cpu_arm_data.h: 64-bit arm CPU specific data ++ * ++ * Copyright (C) 2019. Huawei Technologies Co., Ltd. All rights reserved. ++ * ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2.1 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU Lesser General Public ++ * License along with this library; If not, see ++ * . ++ * ++ */ ++ ++#pragma once ++ ++ ++#define VIR_CPU_ARM_DATA_INIT { 0 } ++ ++typedef struct _virCPUarmData virCPUarmData; ++struct _virCPUarmData { ++ unsigned long vendor_id; ++ unsigned long pvr; ++ char *features; ++}; +-- +2.23.0 + diff --git a/libvirt-cpu_map-Introduce-arm-CPU-models.patch b/libvirt-cpu_map-Introduce-arm-CPU-models.patch new file mode 100644 index 0000000..b47a7c5 --- /dev/null +++ b/libvirt-cpu_map-Introduce-arm-CPU-models.patch @@ -0,0 +1,150 @@ +From b305f4c05d22277ba6092bc0c2a15b752959bdec Mon Sep 17 00:00:00 2001 +From: Xu Yandong +Date: Thu, 16 Apr 2020 10:57:11 +0800 +Subject: cpu_map: Introduce arm CPU models + +Support vendor and model for virConnectGetCapabilities in ARM, +add arm cpu info to cpu map. + +Signed-off-by: Xu Yandong +--- + src/cpu_map/Makefile.inc.am | 5 +++++ + src/cpu_map/arm_Kunpeng-920.xml | 24 ++++++++++++++++++++++++ + src/cpu_map/arm_cortex-a53.xml | 6 ++++++ + src/cpu_map/arm_cortex-a57.xml | 6 ++++++ + src/cpu_map/arm_cortex-a72.xml | 6 ++++++ + src/cpu_map/arm_vendors.xml | 14 ++++++++++++++ + src/cpu_map/index.xml | 12 ++++++++++++ + 7 files changed, 73 insertions(+) + create mode 100644 src/cpu_map/arm_Kunpeng-920.xml + create mode 100644 src/cpu_map/arm_cortex-a53.xml + create mode 100644 src/cpu_map/arm_cortex-a57.xml + create mode 100644 src/cpu_map/arm_cortex-a72.xml + create mode 100644 src/cpu_map/arm_vendors.xml + +diff --git a/src/cpu_map/Makefile.inc.am b/src/cpu_map/Makefile.inc.am +index be64c9a..8663877 100644 +--- a/src/cpu_map/Makefile.inc.am ++++ b/src/cpu_map/Makefile.inc.am +@@ -67,6 +67,11 @@ cpumap_DATA = \ + cpu_map/x86_Skylake-Server-noTSX-IBRS.xml \ + cpu_map/x86_Westmere.xml \ + cpu_map/x86_Westmere-IBRS.xml \ ++ cpu_map/arm_vendors.xml \ ++ cpu_map/arm_cortex-a53.xml \ ++ cpu_map/arm_cortex-a57.xml \ ++ cpu_map/arm_cortex-a72.xml \ ++ cpu_map/arm_Kunpeng-920.xml \ + $(NULL) + + EXTRA_DIST += $(cpumap_DATA) +diff --git a/src/cpu_map/arm_Kunpeng-920.xml b/src/cpu_map/arm_Kunpeng-920.xml +new file mode 100644 +index 0000000..b681546 +--- /dev/null ++++ b/src/cpu_map/arm_Kunpeng-920.xml +@@ -0,0 +1,24 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/src/cpu_map/arm_cortex-a53.xml b/src/cpu_map/arm_cortex-a53.xml +new file mode 100644 +index 0000000..3580236 +--- /dev/null ++++ b/src/cpu_map/arm_cortex-a53.xml +@@ -0,0 +1,6 @@ ++ ++ ++ ++ ++ ++ +diff --git a/src/cpu_map/arm_cortex-a57.xml b/src/cpu_map/arm_cortex-a57.xml +new file mode 100644 +index 0000000..3bc4324 +--- /dev/null ++++ b/src/cpu_map/arm_cortex-a57.xml +@@ -0,0 +1,6 @@ ++ ++ ++ ++ ++ ++ +diff --git a/src/cpu_map/arm_cortex-a72.xml b/src/cpu_map/arm_cortex-a72.xml +new file mode 100644 +index 0000000..c509a40 +--- /dev/null ++++ b/src/cpu_map/arm_cortex-a72.xml +@@ -0,0 +1,6 @@ ++ ++ ++ ++ ++ ++ +diff --git a/src/cpu_map/arm_vendors.xml b/src/cpu_map/arm_vendors.xml +new file mode 100644 +index 0000000..840bf9a +--- /dev/null ++++ b/src/cpu_map/arm_vendors.xml +@@ -0,0 +1,14 @@ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/src/cpu_map/index.xml b/src/cpu_map/index.xml +index 50b030d..2e78834 100644 +--- a/src/cpu_map/index.xml ++++ b/src/cpu_map/index.xml +@@ -87,4 +87,16 @@ + + + ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ + +-- +2.23.0 + diff --git a/libvirt-tests-add-baseline-test-cases-for-arm-CPU.patch b/libvirt-tests-add-baseline-test-cases-for-arm-CPU.patch new file mode 100644 index 0000000..719a6a7 --- /dev/null +++ b/libvirt-tests-add-baseline-test-cases-for-arm-CPU.patch @@ -0,0 +1,263 @@ +From 89b60f0cefe533a5fda021fae303e7662c141d02 Mon Sep 17 00:00:00 2001 +From: Xu Yandong +Date: Mon, 16 Oct 2017 17:45:48 +0800 +Subject: [PATCH 11/11] tests: add baseline test cases for arm CPU + +add baseline test cases for aarch64 + +Signed-off-by: Xu Yandong +--- + tests/cputest.c | 7 +++++ + .../aarch64-baseline-incompatible-vendors.xml | 26 +++++++++++++++++++ + ...-baseline-no-compatible-feature-result.xml | 4 +++ + ...aarch64-baseline-no-compatible-feature.xml | 19 ++++++++++++++ + .../aarch64-baseline-no-feature-result.xml | 4 +++ + .../aarch64-baseline-no-feature.xml | 7 +++++ + .../cputestdata/aarch64-baseline-no-model.xml | 13 ++++++++++ + .../aarch64-baseline-no-vendor-result.xml | 10 +++++++ + .../aarch64-baseline-no-vendor.xml | 13 ++++++++++ + ...baseline-one-compatible-feature-result.xml | 5 ++++ + ...arch64-baseline-one-compatible-feature.xml | 20 ++++++++++++++ + .../aarch64-baseline-one-feature-result.xml | 5 ++++ + .../aarch64-baseline-one-feature.xml | 8 ++++++ + 13 files changed, 141 insertions(+) + create mode 100644 tests/cputestdata/aarch64-baseline-incompatible-vendors.xml + create mode 100644 tests/cputestdata/aarch64-baseline-no-compatible-feature-result.xml + create mode 100644 tests/cputestdata/aarch64-baseline-no-compatible-feature.xml + create mode 100644 tests/cputestdata/aarch64-baseline-no-feature-result.xml + create mode 100644 tests/cputestdata/aarch64-baseline-no-feature.xml + create mode 100644 tests/cputestdata/aarch64-baseline-no-model.xml + create mode 100644 tests/cputestdata/aarch64-baseline-no-vendor-result.xml + create mode 100644 tests/cputestdata/aarch64-baseline-no-vendor.xml + create mode 100644 tests/cputestdata/aarch64-baseline-one-compatible-feature-result.xml + create mode 100644 tests/cputestdata/aarch64-baseline-one-compatible-feature.xml + create mode 100644 tests/cputestdata/aarch64-baseline-one-feature-result.xml + create mode 100644 tests/cputestdata/aarch64-baseline-one-feature.xml + +diff --git a/tests/cputest.c b/tests/cputest.c +index e4b4531..3657fa4 100644 +--- a/tests/cputest.c ++++ b/tests/cputest.c +@@ -1194,6 +1194,13 @@ mymain(void) + DO_TEST_BASELINE(VIR_ARCH_PPC64, "same-model", 0, 0); + DO_TEST_BASELINE(VIR_ARCH_PPC64, "legacy", 0, -1); + ++ DO_TEST_BASELINE(VIR_ARCH_AARCH64, "incompatible-vendors", 0, -1); ++ DO_TEST_BASELINE(VIR_ARCH_AARCH64, "no-vendor", 0, 0); ++ DO_TEST_BASELINE(VIR_ARCH_AARCH64, "no-feature", 0, 0); ++ DO_TEST_BASELINE(VIR_ARCH_AARCH64, "one-feature", 0, 0); ++ DO_TEST_BASELINE(VIR_ARCH_AARCH64, "no-compatible-feature", 0, 0); ++ DO_TEST_BASELINE(VIR_ARCH_AARCH64, "one-compatible-feature", 0, 0); ++ + /* CPU features */ + DO_TEST_HASFEATURE(VIR_ARCH_X86_64, "host", "vmx", YES); + DO_TEST_HASFEATURE(VIR_ARCH_X86_64, "host", "lm", YES); +diff --git a/tests/cputestdata/aarch64-baseline-incompatible-vendors.xml b/tests/cputestdata/aarch64-baseline-incompatible-vendors.xml +new file mode 100644 +index 0000000..f2c71a1 +--- /dev/null ++++ b/tests/cputestdata/aarch64-baseline-incompatible-vendors.xml +@@ -0,0 +1,26 @@ ++ ++ ++ aarch64 ++ cortex-a57 ++ ARM ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ aarch64 ++ cortex-a72 ++ Hisilicon ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/tests/cputestdata/aarch64-baseline-no-compatible-feature-result.xml b/tests/cputestdata/aarch64-baseline-no-compatible-feature-result.xml +new file mode 100644 +index 0000000..6db66aa +--- /dev/null ++++ b/tests/cputestdata/aarch64-baseline-no-compatible-feature-result.xml +@@ -0,0 +1,4 @@ ++ ++ cortex-a57 ++ ARM ++ +diff --git a/tests/cputestdata/aarch64-baseline-no-compatible-feature.xml b/tests/cputestdata/aarch64-baseline-no-compatible-feature.xml +new file mode 100644 +index 0000000..5fd3228 +--- /dev/null ++++ b/tests/cputestdata/aarch64-baseline-no-compatible-feature.xml +@@ -0,0 +1,19 @@ ++ ++ ++ aarch64 ++ cortex-a57 ++ ARM ++ ++ ++ ++ ++ ++ ++ ++ aarch64 ++ cortex-a57 ++ ARM ++ ++ ++ ++ +diff --git a/tests/cputestdata/aarch64-baseline-no-feature-result.xml b/tests/cputestdata/aarch64-baseline-no-feature-result.xml +new file mode 100644 +index 0000000..6db66aa +--- /dev/null ++++ b/tests/cputestdata/aarch64-baseline-no-feature-result.xml +@@ -0,0 +1,4 @@ ++ ++ cortex-a57 ++ ARM ++ +diff --git a/tests/cputestdata/aarch64-baseline-no-feature.xml b/tests/cputestdata/aarch64-baseline-no-feature.xml +new file mode 100644 +index 0000000..0d6af96 +--- /dev/null ++++ b/tests/cputestdata/aarch64-baseline-no-feature.xml +@@ -0,0 +1,7 @@ ++ ++ ++ aarch64 ++ cortex-a57 ++ ARM ++ ++ +diff --git a/tests/cputestdata/aarch64-baseline-no-model.xml b/tests/cputestdata/aarch64-baseline-no-model.xml +new file mode 100644 +index 0000000..6033e4c +--- /dev/null ++++ b/tests/cputestdata/aarch64-baseline-no-model.xml +@@ -0,0 +1,13 @@ ++ ++ ++ aarch64 ++ ARM ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/tests/cputestdata/aarch64-baseline-no-vendor-result.xml b/tests/cputestdata/aarch64-baseline-no-vendor-result.xml +new file mode 100644 +index 0000000..c1d74c2 +--- /dev/null ++++ b/tests/cputestdata/aarch64-baseline-no-vendor-result.xml +@@ -0,0 +1,10 @@ ++ ++ cortex-a57 ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/tests/cputestdata/aarch64-baseline-no-vendor.xml b/tests/cputestdata/aarch64-baseline-no-vendor.xml +new file mode 100644 +index 0000000..8aacb3e +--- /dev/null ++++ b/tests/cputestdata/aarch64-baseline-no-vendor.xml +@@ -0,0 +1,13 @@ ++ ++ ++ aarch64 ++ cortex-a57 ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/tests/cputestdata/aarch64-baseline-one-compatible-feature-result.xml b/tests/cputestdata/aarch64-baseline-one-compatible-feature-result.xml +new file mode 100644 +index 0000000..84c559d +--- /dev/null ++++ b/tests/cputestdata/aarch64-baseline-one-compatible-feature-result.xml +@@ -0,0 +1,5 @@ ++ ++ cortex-a57 ++ ARM ++ ++ +diff --git a/tests/cputestdata/aarch64-baseline-one-compatible-feature.xml b/tests/cputestdata/aarch64-baseline-one-compatible-feature.xml +new file mode 100644 +index 0000000..c85059b +--- /dev/null ++++ b/tests/cputestdata/aarch64-baseline-one-compatible-feature.xml +@@ -0,0 +1,20 @@ ++ ++ ++ aarch64 ++ cortex-a57 ++ ARM ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ aarch64 ++ cortex-a57 ++ ARM ++ ++ ++ +diff --git a/tests/cputestdata/aarch64-baseline-one-feature-result.xml b/tests/cputestdata/aarch64-baseline-one-feature-result.xml +new file mode 100644 +index 0000000..0fcea51 +--- /dev/null ++++ b/tests/cputestdata/aarch64-baseline-one-feature-result.xml +@@ -0,0 +1,5 @@ ++ ++ cortex-a57 ++ ARM ++ ++ +diff --git a/tests/cputestdata/aarch64-baseline-one-feature.xml b/tests/cputestdata/aarch64-baseline-one-feature.xml +new file mode 100644 +index 0000000..e0ae15f +--- /dev/null ++++ b/tests/cputestdata/aarch64-baseline-one-feature.xml +@@ -0,0 +1,8 @@ ++ ++ ++ aarch64 ++ cortex-a57 ++ ARM ++ ++ ++ +-- +2.23.0 + diff --git a/libvirt-tests-add-cpu-compare-test-cases-for-arm-CPU.patch b/libvirt-tests-add-cpu-compare-test-cases-for-arm-CPU.patch new file mode 100644 index 0000000..9ed2f82 --- /dev/null +++ b/libvirt-tests-add-cpu-compare-test-cases-for-arm-CPU.patch @@ -0,0 +1,171 @@ +From 8c57ff0e9b940eb1e29a4aa3e8a9d04b03424989 Mon Sep 17 00:00:00 2001 +From: Xu Yandong +Date: Mon, 16 Oct 2017 17:55:48 +0800 +Subject: tests: add cpu compare test cases for arm CPU + +add cpu compare test cases for arm CPU + +Signed-off-by: Xu Yandong +--- + tests/cputest.c | 10 ++++++++++ + .../aarch64-guest-compat-incompatible.xml | 4 ++++ + tests/cputestdata/aarch64-guest-compat-none.xml | 1 + + tests/cputestdata/aarch64-guest-compat-valid.xml | 3 +++ + tests/cputestdata/aarch64-guest-exact.xml | 4 ++++ + tests/cputestdata/aarch64-guest-features-invalid.xml | 12 ++++++++++++ + tests/cputestdata/aarch64-guest-features-valid.xml | 7 +++++++ + .../aarch64-guest-legacy-incompatible.xml | 4 ++++ + tests/cputestdata/aarch64-guest-legacy.xml | 4 ++++ + tests/cputestdata/aarch64-guest-strict.xml | 4 ++++ + tests/cputestdata/aarch64-host.xml | 12 ++++++++++++ + 11 files changed, 65 insertions(+) + create mode 100644 tests/cputestdata/aarch64-guest-compat-incompatible.xml + create mode 100644 tests/cputestdata/aarch64-guest-compat-none.xml + create mode 100644 tests/cputestdata/aarch64-guest-compat-valid.xml + create mode 100644 tests/cputestdata/aarch64-guest-exact.xml + create mode 100644 tests/cputestdata/aarch64-guest-features-invalid.xml + create mode 100644 tests/cputestdata/aarch64-guest-features-valid.xml + create mode 100644 tests/cputestdata/aarch64-guest-legacy-incompatible.xml + create mode 100644 tests/cputestdata/aarch64-guest-legacy.xml + create mode 100644 tests/cputestdata/aarch64-guest-strict.xml + create mode 100644 tests/cputestdata/aarch64-host.xml + +diff --git a/tests/cputest.c b/tests/cputest.c +index 1f59f0d..e4b4531 100644 +--- a/tests/cputest.c ++++ b/tests/cputest.c +@@ -1140,6 +1140,16 @@ mymain(void) + DO_TEST_COMPARE(VIR_ARCH_PPC64, "host", "guest-compat-invalid", VIR_CPU_COMPARE_ERROR); + DO_TEST_COMPARE(VIR_ARCH_PPC64, "host", "guest-compat-incompatible", VIR_CPU_COMPARE_INCOMPATIBLE); + ++ DO_TEST_COMPARE(VIR_ARCH_AARCH64, "host", "guest-strict", VIR_CPU_COMPARE_IDENTICAL); ++ DO_TEST_COMPARE(VIR_ARCH_AARCH64, "host", "guest-exact", VIR_CPU_COMPARE_INCOMPATIBLE); ++ DO_TEST_COMPARE(VIR_ARCH_AARCH64, "host", "guest-legacy", VIR_CPU_COMPARE_IDENTICAL); ++ DO_TEST_COMPARE(VIR_ARCH_AARCH64, "host", "guest-legacy-incompatible", VIR_CPU_COMPARE_INCOMPATIBLE); ++ DO_TEST_COMPARE(VIR_ARCH_AARCH64, "host", "guest-compat-none", VIR_CPU_COMPARE_IDENTICAL); ++ DO_TEST_COMPARE(VIR_ARCH_AARCH64, "host", "guest-compat-valid", VIR_CPU_COMPARE_IDENTICAL); ++ DO_TEST_COMPARE(VIR_ARCH_AARCH64, "host", "guest-compat-incompatible", VIR_CPU_COMPARE_INCOMPATIBLE); ++ DO_TEST_COMPARE(VIR_ARCH_AARCH64, "host", "guest-features-valid", VIR_CPU_COMPARE_IDENTICAL); ++ DO_TEST_COMPARE(VIR_ARCH_AARCH64, "host", "guest-features-invalid", VIR_CPU_COMPARE_INCOMPATIBLE); ++ + /* guest updates for migration + * automatically compares host CPU with the result */ + DO_TEST_UPDATE(VIR_ARCH_X86_64, "host", "min", VIR_CPU_COMPARE_IDENTICAL); +diff --git a/tests/cputestdata/aarch64-guest-compat-incompatible.xml b/tests/cputestdata/aarch64-guest-compat-incompatible.xml +new file mode 100644 +index 0000000..f68ead5 +--- /dev/null ++++ b/tests/cputestdata/aarch64-guest-compat-incompatible.xml +@@ -0,0 +1,4 @@ ++ ++ cortex-a72 ++ ARM ++ +diff --git a/tests/cputestdata/aarch64-guest-compat-none.xml b/tests/cputestdata/aarch64-guest-compat-none.xml +new file mode 100644 +index 0000000..fd50c03 +--- /dev/null ++++ b/tests/cputestdata/aarch64-guest-compat-none.xml +@@ -0,0 +1 @@ ++ +diff --git a/tests/cputestdata/aarch64-guest-compat-valid.xml b/tests/cputestdata/aarch64-guest-compat-valid.xml +new file mode 100644 +index 0000000..0206d6e +--- /dev/null ++++ b/tests/cputestdata/aarch64-guest-compat-valid.xml +@@ -0,0 +1,3 @@ ++ ++ cortex-a57 ++ +diff --git a/tests/cputestdata/aarch64-guest-exact.xml b/tests/cputestdata/aarch64-guest-exact.xml +new file mode 100644 +index 0000000..bbbe65f +--- /dev/null ++++ b/tests/cputestdata/aarch64-guest-exact.xml +@@ -0,0 +1,4 @@ ++ ++ cortex-a72 ++ ARM ++ +diff --git a/tests/cputestdata/aarch64-guest-features-invalid.xml b/tests/cputestdata/aarch64-guest-features-invalid.xml +new file mode 100644 +index 0000000..afbb402 +--- /dev/null ++++ b/tests/cputestdata/aarch64-guest-features-invalid.xml +@@ -0,0 +1,12 @@ ++ ++ cortex-a57 ++ ARM ++ ++ ++ ++ ++ ++ ++ ++ ++ +diff --git a/tests/cputestdata/aarch64-guest-features-valid.xml b/tests/cputestdata/aarch64-guest-features-valid.xml +new file mode 100644 +index 0000000..0858f76 +--- /dev/null ++++ b/tests/cputestdata/aarch64-guest-features-valid.xml +@@ -0,0 +1,7 @@ ++ ++ cortex-a57 ++ ARM ++ ++ ++ ++ +diff --git a/tests/cputestdata/aarch64-guest-legacy-incompatible.xml b/tests/cputestdata/aarch64-guest-legacy-incompatible.xml +new file mode 100644 +index 0000000..2f1941d +--- /dev/null ++++ b/tests/cputestdata/aarch64-guest-legacy-incompatible.xml +@@ -0,0 +1,4 @@ ++ ++ cortex-a72 ++ ARM ++ +diff --git a/tests/cputestdata/aarch64-guest-legacy.xml b/tests/cputestdata/aarch64-guest-legacy.xml +new file mode 100644 +index 0000000..64a05e4 +--- /dev/null ++++ b/tests/cputestdata/aarch64-guest-legacy.xml +@@ -0,0 +1,4 @@ ++ ++ cortex-a57 ++ ARM ++ +diff --git a/tests/cputestdata/aarch64-guest-strict.xml b/tests/cputestdata/aarch64-guest-strict.xml +new file mode 100644 +index 0000000..a057ebd +--- /dev/null ++++ b/tests/cputestdata/aarch64-guest-strict.xml +@@ -0,0 +1,4 @@ ++ ++ cortex-a57 ++ ARM ++ +diff --git a/tests/cputestdata/aarch64-host.xml b/tests/cputestdata/aarch64-host.xml +new file mode 100644 +index 0000000..60c20f2 +--- /dev/null ++++ b/tests/cputestdata/aarch64-host.xml +@@ -0,0 +1,12 @@ ++ ++ aarch64 ++ cortex-a57 ++ ARM ++ ++ ++ ++ ++ ++ ++ ++ +-- +2.23.0 + diff --git a/libvirt.spec b/libvirt.spec index 577007f..8959f74 100644 --- a/libvirt.spec +++ b/libvirt.spec @@ -99,7 +99,7 @@ Summary: Library providing a simple virtualization API Name: libvirt Version: 6.2.0 -Release: 2 +Release: 3 License: LGPLv2+ URL: https://libvirt.org/ @@ -113,6 +113,16 @@ Patch0002: libvirt-qemu-fix-a-concurrent-operation-situation.patch Patch0003: libvirt-cgroup-cleanup-eventParams-when-virTypedParamsAddULL.patch Patch0004: libvirt-nodedev-fix-potential-heap-use-after-free.patch Patch0005: libvirt-po-Refresh-translation-for-running-state.patch +Patch0006: libvirt-cpu_map-Introduce-arm-CPU-models.patch +Patch0007: libvirt-cpu-introduce-virCPUarmData-to-virCPUData.patch +Patch0008: libvirt-cpu-arm-add-cpu-data-free-function-to-virCPUarmDataF.patch +Patch0009: libvirt-cpu-arm-add-load-cpu-map-parse-function.patch +Patch0010: libvirt-cpu-arm-add-decode-function.patch +Patch0011: libvirt-cpu-arm-add-virCPUarmGetHost-implment.patch +Patch0012: libvirt-cpu-arm-implment-cpu-baseline-function.patch +Patch0013: libvirt-cpu-arm-implment-cpu-compare-function.patch +Patch0014: libvirt-tests-add-cpu-compare-test-cases-for-arm-CPU.patch +Patch0015: libvirt-tests-add-baseline-test-cases-for-arm-CPU.patch Requires: libvirt-daemon = %{version}-%{release} @@ -1846,6 +1856,9 @@ exit 0 %changelog +* Mon May 11 2020 Xu Yandong - 6.2.0-3 +- Checkout cpu capabilities support for ARM architecture. +- Support Kunpeng-920 CPU. * Mon Apr 20 2020 Xu Yandong - 6.2.0-2 - Checkout bugfixs from 5.5.0 release. * Tue Apr 14 2020 Xu Yandong - 6.2.0-1