diff --git a/src/cpu/cpu_arm.c b/src/cpu/cpu_arm.c index 324c701e81adeb3f876dd7bc44beab41a862e7a4..38629b0bc786ebccb5a60b3058da4ec74e8ce46b 100644 --- a/src/cpu/cpu_arm.c +++ b/src/cpu/cpu_arm.c @@ -661,6 +661,7 @@ virCPUarmDecode(virCPUDef *cpu, if (cpuData->features) { cpu->nfeatures = g_strv_length(cpuData->features); + cpu->nfeatures_max = cpu->nfeatures; cpu->features = g_new0(virCPUFeatureDef, cpu->nfeatures); for (i = 0; i < cpu->nfeatures; i++) { diff --git a/src/cpu_map/arm_Tengyun-S5000C.xml b/src/cpu_map/arm_Tengyun-S5000C.xml new file mode 100644 index 0000000000000000000000000000000000000000..f8fa593c19b3d1494bff0f55ef1a3e5519b8bd83 --- /dev/null +++ b/src/cpu_map/arm_Tengyun-S5000C.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/cpu_map/index.xml b/src/cpu_map/index.xml index 5d18a4aed697df2778dd793d80e30170fea7c03a..bca4a3d363312caa44f4b0e958defc16fd674ee9 100644 --- a/src/cpu_map/index.xml +++ b/src/cpu_map/index.xml @@ -119,5 +119,6 @@ + diff --git a/src/cpu_map/meson.build b/src/cpu_map/meson.build index ca4934d363d0bde8749bfa7d7f4eb3fb746fcb2f..409f3c0c5e12f1eccff5b61e1ee3121b20824a80 100644 --- a/src/cpu_map/meson.build +++ b/src/cpu_map/meson.build @@ -11,6 +11,7 @@ cpumap_data = [ 'arm_Neoverse-N2.xml', 'arm_Neoverse-V1.xml', 'arm_Tengyun-S2500.xml', + 'arm_Tengyun-S5000C.xml', 'arm_ThunderX299xx.xml', 'arm_vendors.xml', 'index.xml', diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 95529970049696c2436b59f58aa65cb35282a308..c21f0e55dc6f834eb059400de99043c493dc5e5d 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -3718,6 +3718,62 @@ virQEMUCapsInitCPUModelX86(virQEMUCaps *qemuCaps, return 0; } +/** + * Returns 0 when host CPU model provided by QEMU was filled in qemuCaps, + * 1 when the caller should fall back to using virCaps *->host.cpu, + * 2 when cpu model info is not supported for this configuration, + * -1 on error. + */ +static int +virQEMUCapsInitCPUModelARM(virQEMUCaps *qemuCaps, + virDomainVirtType type, + qemuMonitorCPUModelInfo *modelInfo, + virCPUDef *cpu, + bool migratable) +{ + size_t i; + g_autoptr(virCPUDef) hostCPU = NULL; + + if (!modelInfo) { + if (type == VIR_DOMAIN_VIRT_KVM) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("missing host CPU model info from QEMU " + "capabilities for binary %s"), + qemuCaps->binary); + return -1; + } + return 2; + } + + if (!(hostCPU = virQEMUCapsProbeHostCPU(qemuCaps->arch, NULL))) + return -1; + + cpu->model = g_strdup(hostCPU->model); + cpu->features = g_new0(virCPUFeatureDef, modelInfo->nprops); + + cpu->nfeatures_max = modelInfo->nprops; + cpu->nfeatures = 0; + + for (i = 0; i < modelInfo->nprops; i++) { + virCPUFeatureDef *feature = cpu->features + cpu->nfeatures; + qemuMonitorCPUProperty *prop = modelInfo->props + i; + const char *name = virQEMUCapsCPUFeatureFromQEMU(qemuCaps->arch, prop->name); + + if (prop->type != QEMU_MONITOR_CPU_PROPERTY_BOOLEAN) + continue; + + feature->name = g_strdup(name); + + if (!prop->value.boolean || + (migratable && prop->migratable == VIR_TRISTATE_BOOL_NO)) + feature->policy = VIR_CPU_FEATURE_DISABLE; + else + feature->policy = VIR_CPU_FEATURE_REQUIRE; + cpu->nfeatures++; + } + + return 0; +} /** * Returns 0 when host CPU model provided by QEMU was filled in qemuCaps, @@ -3743,8 +3799,11 @@ virQEMUCapsInitCPUModel(virQEMUCaps *qemuCaps, } else if (ARCH_IS_X86(qemuCaps->arch)) { ret = virQEMUCapsInitCPUModelX86(qemuCaps, type, modelInfo, cpu, migratable); - } else if (ARCH_IS_ARM(qemuCaps->arch) || ARCH_IS_LOONGARCH(qemuCaps->arch)) { - ret = 2; + } else if (ARCH_IS_ARM(qemuCaps->arch)) { + ret = virQEMUCapsInitCPUModelARM(qemuCaps, type, modelInfo, + cpu, migratable); + } else if (ARCH_IS_LOONGARCH(qemuCaps->arch)) { + ret = 2; } if (ret == 0)