Add parsing of LoongArch CPU vendors from the CPU map XML files. This introduces the virCPULoongArchData structure, the CPU map container, vendor lookup helpers. Add memory management for the CPU map and vendor objects, register src/cpu/cpu_loongarch.c in po/POTFILES for translation, and provide a stub decode callback so the driver can be registered. Signed-off-by: Xianglai Li <lixianglai@loongson.cn> --- Cc: Bibo Mao <maobibo@loongson.cn> po/POTFILES | 1 + src/cpu/cpu.h | 2 + src/cpu/cpu_loongarch.c | 163 ++++++++++++++++++++++++++++++++++- src/cpu/cpu_loongarch_data.h | 34 ++++++++ 4 files changed, 199 insertions(+), 1 deletion(-) create mode 100644 src/cpu/cpu_loongarch_data.h diff --git a/po/POTFILES b/po/POTFILES index 3812d6af88..504d5c28bd 100644 --- a/po/POTFILES +++ b/po/POTFILES @@ -74,6 +74,7 @@ src/conf/virsecretobj.c src/conf/virstorageobj.c src/cpu/cpu.c src/cpu/cpu_arm.c +src/cpu/cpu_loongarch.c src/cpu/cpu_map.c src/cpu/cpu_ppc64.c src/cpu/cpu_riscv64.c diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index 65711ac085..08b49ccefa 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -27,6 +27,7 @@ #include "cpu_x86_data.h" #include "cpu_ppc64_data.h" #include "cpu_arm_data.h" +#include "cpu_loongarch_data.h" typedef struct _virCPUData virCPUData; @@ -36,6 +37,7 @@ struct _virCPUData { virCPUx86Data x86; virCPUppc64Data ppc64; virCPUarmData arm; + virCPULoongArchData loongarch; /* generic driver needs no data */ } data; }; diff --git a/src/cpu/cpu_loongarch.c b/src/cpu/cpu_loongarch.c index 0e2b0b5848..d1ed447881 100644 --- a/src/cpu/cpu_loongarch.c +++ b/src/cpu/cpu_loongarch.c @@ -21,12 +21,30 @@ #include <config.h> #include "virlog.h" #include "cpu.h" +#include "viralloc.h" +#include "cpu_map.h" #define VIR_FROM_THIS VIR_FROM_CPU VIR_LOG_INIT("cpu.cpu_loongarch"); +typedef struct _virCPULoongArchVendor virCPULoongArchVendor; +struct _virCPULoongArchVendor { + char *name; + uint32_t value; +}; + +typedef struct _virCPULoongArchMap virCPULoongArchMap; +struct _virCPULoongArchMap { + size_t nvendors; + virCPULoongArchVendor **vendors; +}; + static const virArch archs[] = { VIR_ARCH_LOONGARCH64 }; +static virCPULoongArchMap *cpuMap; + +int virCPULoongArchDriverOnceInit(void); +VIR_ONCE_GLOBAL_INIT(virCPULoongArchDriver); static virCPUCompareResult virCPULoongArchCompare(virCPUDef *host G_GNUC_UNUSED, @@ -36,6 +54,149 @@ virCPULoongArchCompare(virCPUDef *host G_GNUC_UNUSED, return VIR_CPU_COMPARE_IDENTICAL; } +static void +virCPULoongArchVendorFree(virCPULoongArchVendor *vendor) +{ + if (!vendor) + return; + + g_free(vendor->name); + g_free(vendor); +} + +G_DEFINE_AUTOPTR_CLEANUP_FUNC(virCPULoongArchVendor, virCPULoongArchVendorFree); + +static virCPULoongArchMap * +virCPULoongArchMapNew(void) +{ + virCPULoongArchMap *map; + + map = g_new0(virCPULoongArchMap, 1); + + return map; +} + +static void +virCPULoongArchMapFree(virCPULoongArchMap *map) +{ + size_t i; + + if (!map) + return; + + for (i = 0; i < map->nvendors; i++) + virCPULoongArchVendorFree(map->vendors[i]); + g_free(map->vendors); + g_free(map); +} +G_DEFINE_AUTOPTR_CLEANUP_FUNC(virCPULoongArchMap, virCPULoongArchMapFree); + +static virCPULoongArchVendor * +virCPULoongArchVendorFindByName(virCPULoongArchMap *map, + const char *name) +{ + size_t i; + + for (i = 0; i < map->nvendors; i++) { + if (STREQ(map->vendors[i]->name, name)) + return map->vendors[i]; + } + + return NULL; +} + +static virCPULoongArchVendor * +virCPULoongArchVendorFindByID(virCPULoongArchMap *map, + uint32_t vendor_id) +{ + size_t i; + + for (i = 0; i < map->nvendors; i++) { + if (map->vendors[i]->value == vendor_id) + return map->vendors[i]; + } + + return NULL; +} + +static int +virCPULoongArchMapVendorParse(xmlXPathContextPtr ctxt, + const char *name, + void *data) +{ + virCPULoongArchMap *map = data; + g_autoptr(virCPULoongArchVendor) vendor = NULL; + + vendor = g_new0(virCPULoongArchVendor, 1); + vendor->name = g_strdup(name); + + if (virCPULoongArchVendorFindByName(map, vendor->name)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("CPU vendor %1$s already defined"), + vendor->name); + return -1; + } + + if (virXMLPropUInt(ctxt->node, "value", 16, VIR_XML_PROP_REQUIRED, + &vendor->value) < 0) + return -1; + + if (virCPULoongArchVendorFindByID(map, vendor->value)) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("CPU vendor value 0x%1$2x already defined"), + vendor->value); + return -1; + } + + VIR_APPEND_ELEMENT(map->vendors, map->nvendors, vendor); + return 0; +} + +static virCPULoongArchMap * +virCPULoongArchLoadMap(void) +{ + g_autoptr(virCPULoongArchMap) map = NULL; + + map = virCPULoongArchMapNew(); + + if (cpuMapLoad("loongarch", virCPULoongArchMapVendorParse, + NULL, NULL, map) < 0) + return NULL; + + return g_steal_pointer(&map); +} + +static virCPULoongArchMap * +virCPULoongArchGetMap(void) +{ + if (virCPULoongArchDriverInitialize() < 0) + return NULL; + + return cpuMap; +} + +int +virCPULoongArchDriverOnceInit(void) +{ + if (!(cpuMap = virCPULoongArchLoadMap())) + return -1; + + return 0; +} + +static int +virCPULoongArchDriverDecode(virCPUDef *cpu G_GNUC_UNUSED, + const virCPUData *cpuData, + virDomainCapsCPUModels *models G_GNUC_UNUSED) +{ + virCPULoongArchMap *map = NULL; + + if (!cpuData || !(map = virCPULoongArchGetMap())) + return -1; + + return 0; +} + static int virCPULoongArchUpdate(virCPUDef *guest G_GNUC_UNUSED, const virCPUDef *host G_GNUC_UNUSED, @@ -50,7 +211,7 @@ struct cpuArchDriver cpuDriverLoongArch = { .arch = archs, .narch = G_N_ELEMENTS(archs), .compare = virCPULoongArchCompare, - .decode = NULL, + .decode = virCPULoongArchDriverDecode, .encode = NULL, .dataFree = NULL, .baseline = NULL, diff --git a/src/cpu/cpu_loongarch_data.h b/src/cpu/cpu_loongarch_data.h new file mode 100644 index 0000000000..673a4b37e6 --- /dev/null +++ b/src/cpu/cpu_loongarch_data.h @@ -0,0 +1,34 @@ +/* + * cpu_loongarch_data.h: 64-bit LoongArch CPU specific data + * + * Copyright (C) 2026 LOONGSON Corporation. + * + * 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 + * <http://www.gnu.org/licenses/>. + */ + +#pragma once + +typedef struct _virCPULoongArchFeature virCPULoongArchFeature; +struct _virCPULoongArchFeature { + char *name; + uint32_t index; + uint32_t value; + int policy; /* enum virCPUFeaturePolicy */ +}; + +typedef struct _virCPULoongArchData virCPULoongArchData; +struct _virCPULoongArchData { + GPtrArray *features; +}; -- 2.39.1