[libvirt PATCH 00/11] Improve CPU model reporting in domain capabilities

See patches 04/11 and 10/11 for details. Patches 4, 6, and 10 were truncated as they include a lot of boring changes in tests, complete patches are available in my gitlab repo: git fetch git@gitlab.com:jirkade/libvirt.git domaincaps Jiri Denemark (11): conf: virDomainCapsCPUModelsAdd never fails cpu_ppc64: Avoid repeated loading of CPU map qemu: Do not pass qemuCaps to virQEMUCapsCPUFeature{To,From}QEMU domain_capabilities: Add vendor attribute for CPU models Introduce virCPUGetVendorForModel and use it in QEMU driver cpu_x86: Implement virCPUGetVendorForModel cpu_ppc64: Implement virCPUGetVendorForModel cpu_arm: Don't implement virCPUGetVendorForModel qemu_capabilities: Translate CPU blockers domain_capabilities: Add blockers attribute for CPU models NEWS: Document domain capabilities improvements NEWS.rst | 11 ++ docs/formatdomaincaps.rst | 20 ++- src/conf/domain_capabilities.c | 42 +++-- src/conf/domain_capabilities.h | 13 +- src/conf/schemas/domaincaps.rng | 8 + src/cpu/cpu.c | 25 +++ src/cpu/cpu.h | 8 + src/cpu/cpu_arm.c | 1 + src/cpu/cpu_ppc64.c | 67 ++++++-- src/cpu/cpu_x86.c | 19 +++ src/libvirt_private.syms | 1 + src/qemu/qemu_capabilities.c | 65 +++++--- src/qemu/qemu_capabilities.h | 4 +- src/qemu/qemu_command.c | 2 +- src/qemu/qemu_monitor.c | 7 +- src/qemu/qemu_monitor.h | 5 +- src/qemu/qemu_monitor_json.c | 11 +- src/qemu/qemu_monitor_json.h | 1 - src/qemu/qemu_process.c | 12 +- tests/cputest.c | 15 +- .../domaincapsdata/qemu_4.2.0-q35.x86_64.xml | 104 ++++++------ .../domaincapsdata/qemu_4.2.0-tcg.x86_64.xml | 104 ++++++------ .../qemu_4.2.0-virt.aarch64.xml | 72 ++++----- tests/domaincapsdata/qemu_4.2.0.aarch64.xml | 72 ++++----- tests/domaincapsdata/qemu_4.2.0.ppc64.xml | 6 +- tests/domaincapsdata/qemu_4.2.0.s390x.xml | 148 +++++++++--------- tests/domaincapsdata/qemu_4.2.0.x86_64.xml | 104 ++++++------ .../domaincapsdata/qemu_5.0.0-q35.x86_64.xml | 108 ++++++------- .../domaincapsdata/qemu_5.0.0-tcg.x86_64.xml | 108 ++++++------- .../qemu_5.0.0-virt.aarch64.xml | 74 ++++----- tests/domaincapsdata/qemu_5.0.0.aarch64.xml | 74 ++++----- tests/domaincapsdata/qemu_5.0.0.ppc64.xml | 8 +- tests/domaincapsdata/qemu_5.0.0.x86_64.xml | 108 ++++++------- .../domaincapsdata/qemu_5.1.0-q35.x86_64.xml | 108 ++++++------- .../domaincapsdata/qemu_5.1.0-tcg.x86_64.xml | 108 ++++++------- tests/domaincapsdata/qemu_5.1.0.x86_64.xml | 108 ++++++------- .../domaincapsdata/qemu_5.2.0-q35.x86_64.xml | 108 ++++++------- .../domaincapsdata/qemu_5.2.0-tcg.x86_64.xml | 108 ++++++------- .../qemu_5.2.0-virt.aarch64.xml | 74 ++++----- tests/domaincapsdata/qemu_5.2.0.aarch64.xml | 74 ++++----- tests/domaincapsdata/qemu_5.2.0.ppc64.xml | 8 +- tests/domaincapsdata/qemu_5.2.0.s390x.xml | 148 +++++++++--------- tests/domaincapsdata/qemu_5.2.0.x86_64.xml | 108 ++++++------- .../domaincapsdata/qemu_6.0.0-q35.x86_64.xml | 110 ++++++------- .../domaincapsdata/qemu_6.0.0-tcg.x86_64.xml | 110 ++++++------- .../qemu_6.0.0-virt.aarch64.xml | 76 ++++----- tests/domaincapsdata/qemu_6.0.0.aarch64.xml | 76 ++++----- tests/domaincapsdata/qemu_6.0.0.s390x.xml | 148 +++++++++--------- tests/domaincapsdata/qemu_6.0.0.x86_64.xml | 110 ++++++------- .../domaincapsdata/qemu_6.1.0-q35.x86_64.xml | 110 ++++++------- .../domaincapsdata/qemu_6.1.0-tcg.x86_64.xml | 110 ++++++------- tests/domaincapsdata/qemu_6.1.0.x86_64.xml | 110 ++++++------- .../domaincapsdata/qemu_6.2.0-q35.x86_64.xml | 110 ++++++------- .../domaincapsdata/qemu_6.2.0-tcg.x86_64.xml | 110 ++++++------- .../qemu_6.2.0-virt.aarch64.xml | 78 ++++----- tests/domaincapsdata/qemu_6.2.0.aarch64.xml | 78 ++++----- tests/domaincapsdata/qemu_6.2.0.ppc64.xml | 8 +- tests/domaincapsdata/qemu_6.2.0.x86_64.xml | 110 ++++++------- .../domaincapsdata/qemu_7.0.0-q35.x86_64.xml | 110 ++++++------- .../domaincapsdata/qemu_7.0.0-tcg.x86_64.xml | 110 ++++++------- .../qemu_7.0.0-virt.aarch64.xml | 78 ++++----- tests/domaincapsdata/qemu_7.0.0.aarch64.xml | 78 ++++----- tests/domaincapsdata/qemu_7.0.0.ppc64.xml | 8 +- tests/domaincapsdata/qemu_7.0.0.x86_64.xml | 110 ++++++------- .../domaincapsdata/qemu_7.1.0-q35.x86_64.xml | 106 ++++++------- .../domaincapsdata/qemu_7.1.0-tcg.x86_64.xml | 106 ++++++------- tests/domaincapsdata/qemu_7.1.0.x86_64.xml | 106 ++++++------- 67 files changed, 2389 insertions(+), 2256 deletions(-) -- 2.37.3

Since the function always returns 0, we can just return void and make callers simpler. Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/conf/domain_capabilities.c | 24 +++++++++--------------- src/conf/domain_capabilities.h | 11 ++++++----- src/qemu/qemu_capabilities.c | 9 ++++----- tests/cputest.c | 14 ++++---------- 4 files changed, 23 insertions(+), 35 deletions(-) diff --git a/src/conf/domain_capabilities.c b/src/conf/domain_capabilities.c index 653123f293..123c80a560 100644 --- a/src/conf/domain_capabilities.c +++ b/src/conf/domain_capabilities.c @@ -155,37 +155,33 @@ virDomainCapsCPUModelsNew(size_t nmodels) virDomainCapsCPUModels * virDomainCapsCPUModelsCopy(virDomainCapsCPUModels *old) { - g_autoptr(virDomainCapsCPUModels) cpuModels = NULL; + virDomainCapsCPUModels *cpuModels = NULL; size_t i; if (!(cpuModels = virDomainCapsCPUModelsNew(old->nmodels))) return NULL; for (i = 0; i < old->nmodels; i++) { - if (virDomainCapsCPUModelsAdd(cpuModels, - old->models[i].name, - old->models[i].usable, - old->models[i].blockers, - old->models[i].deprecated) < 0) - return NULL; + virDomainCapsCPUModelsAdd(cpuModels, + old->models[i].name, + old->models[i].usable, + old->models[i].blockers, + old->models[i].deprecated); } - return g_steal_pointer(&cpuModels); + return cpuModels; } -int +void virDomainCapsCPUModelsAdd(virDomainCapsCPUModels *cpuModels, const char *name, virDomainCapsCPUUsable usable, char **blockers, bool deprecated) { - g_autofree char * nameCopy = NULL; virDomainCapsCPUModel *cpu; - nameCopy = g_strdup(name); - VIR_RESIZE_N(cpuModels->models, cpuModels->nmodels_max, cpuModels->nmodels, 1); @@ -193,11 +189,9 @@ virDomainCapsCPUModelsAdd(virDomainCapsCPUModels *cpuModels, cpuModels->nmodels++; cpu->usable = usable; - cpu->name = g_steal_pointer(&nameCopy); + cpu->name = g_strdup(name); cpu->blockers = g_strdupv(blockers); cpu->deprecated = deprecated; - - return 0; } diff --git a/src/conf/domain_capabilities.h b/src/conf/domain_capabilities.h index a526969cda..7333276231 100644 --- a/src/conf/domain_capabilities.h +++ b/src/conf/domain_capabilities.h @@ -244,11 +244,12 @@ virDomainCaps *virDomainCapsNew(const char *path, virDomainCapsCPUModels *virDomainCapsCPUModelsNew(size_t nmodels); virDomainCapsCPUModels *virDomainCapsCPUModelsCopy(virDomainCapsCPUModels *old); -int virDomainCapsCPUModelsAdd(virDomainCapsCPUModels *cpuModels, - const char *name, - virDomainCapsCPUUsable usable, - char **blockers, - bool deprecated); +void +virDomainCapsCPUModelsAdd(virDomainCapsCPUModels *cpuModels, + const char *name, + virDomainCapsCPUUsable usable, + char **blockers, + bool deprecated); virDomainCapsCPUModel * virDomainCapsCPUModelsGet(virDomainCapsCPUModels *cpuModels, const char *name); diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 50bde370e8..2a0be77631 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -2179,7 +2179,7 @@ virQEMUCapsCPUDefsToModels(qemuMonitorCPUDefs *defs, const char **modelAllowed, const char **modelForbidden) { - g_autoptr(virDomainCapsCPUModels) cpuModels = NULL; + virDomainCapsCPUModels *cpuModels = NULL; size_t i; if (!(cpuModels = virDomainCapsCPUModelsNew(defs->ncpus))) @@ -2194,12 +2194,11 @@ virQEMUCapsCPUDefsToModels(qemuMonitorCPUDefs *defs, if (modelForbidden && g_strv_contains(modelForbidden, cpu->name)) continue; - if (virDomainCapsCPUModelsAdd(cpuModels, cpu->name, cpu->usable, - cpu->blockers, cpu->deprecated) < 0) - return NULL; + virDomainCapsCPUModelsAdd(cpuModels, cpu->name, cpu->usable, + cpu->blockers, cpu->deprecated); } - return g_steal_pointer(&cpuModels); + return cpuModels; } diff --git a/tests/cputest.c b/tests/cputest.c index b7ec79dfc6..9d24b9d0f5 100644 --- a/tests/cputest.c +++ b/tests/cputest.c @@ -823,9 +823,8 @@ cpuTestUpdateLive(const void *arg) usable = hvModel->usable; } - if (virDomainCapsCPUModelsAdd(models, expected->model, - usable, blockers, false) < 0) - return -1; + virDomainCapsCPUModelsAdd(models, expected->model, + usable, blockers, false); cpu->fallback = VIR_CPU_FALLBACK_ALLOW; ignore_value(virCPUTranslate(data->arch, cpu, models)); @@ -902,16 +901,11 @@ cpuTestInitModels(const char **list) return NULL; for (model = list; *model; model++) { - if (virDomainCapsCPUModelsAdd(cpus, *model, - VIR_DOMCAPS_CPU_USABLE_UNKNOWN, NULL, false) < 0) - goto error; + virDomainCapsCPUModelsAdd(cpus, *model, + VIR_DOMCAPS_CPU_USABLE_UNKNOWN, NULL, false); } return cpus; - - error: - virObjectUnref(cpus); - return NULL; } -- 2.37.3

The ppc64 CPU code still has to load and parse the CPU map everytime it needs to look at it, which can make some operations pretty slow. Other archs already switched to loading the CPU map once and keeping the parsed structure in memory. Let's switch ppc64 as well. Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/cpu/cpu_ppc64.c | 47 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 37 insertions(+), 10 deletions(-) diff --git a/src/cpu/cpu_ppc64.c b/src/cpu/cpu_ppc64.c index cd2df4ba4a..9997e14a89 100644 --- a/src/cpu/cpu_ppc64.c +++ b/src/cpu/cpu_ppc64.c @@ -53,6 +53,12 @@ struct _ppc64_map { struct _ppc64_model **models; }; +static virCPUppc64Map *cpuMap; + +int virCPUppc64DriverOnceInit(void); +VIR_ONCE_GLOBAL_INIT(virCPUppc64Driver); + + /* Convert a legacy CPU definition by transforming * model names to generation names: * POWER7_v2.1 => POWER7 @@ -365,8 +371,8 @@ ppc64ModelParse(xmlXPathContextPtr ctxt, } -static struct _ppc64_map * -ppc64LoadMap(void) +static virCPUppc64Map * +virCPUppc64LoadMap(void) { g_autoptr(virCPUppc64Map) map = NULL; @@ -378,12 +384,33 @@ ppc64LoadMap(void) return g_steal_pointer(&map); } + +int +virCPUppc64DriverOnceInit(void) +{ + if (!(cpuMap = virCPUppc64LoadMap())) + return -1; + + return 0; +} + + +static virCPUppc64Map * +virCPUppc64GetMap(void) +{ + if (virCPUppc64DriverInitialize() < 0) + return NULL; + + return cpuMap; +} + + static virCPUCompareResult ppc64Compute(virCPUDef *host, const virCPUDef *other, char **message) { - g_autoptr(virCPUppc64Map) map = NULL; + virCPUppc64Map *map = NULL; g_autoptr(virCPUppc64Model) host_model = NULL; g_autoptr(virCPUppc64Model) guest_model = NULL; g_autoptr(virCPUDef) cpu = NULL; @@ -428,7 +455,7 @@ ppc64Compute(virCPUDef *host, return VIR_CPU_COMPARE_INCOMPATIBLE; } - if (!(map = ppc64LoadMap())) + if (!(map = virCPUppc64GetMap())) return VIR_CPU_COMPARE_ERROR; /* Host CPU information */ @@ -526,10 +553,10 @@ ppc64DriverDecode(virCPUDef *cpu, const virCPUData *data, virDomainCapsCPUModels *models) { - g_autoptr(virCPUppc64Map) map = NULL; + virCPUppc64Map *map = NULL; const virCPUppc64Model *model; - if (!data || !(map = ppc64LoadMap())) + if (!data || !(map = virCPUppc64GetMap())) return -1; if (!(model = ppc64ModelFindPVR(map, data->data.ppc64.pvr[0].value))) { @@ -656,13 +683,13 @@ virCPUppc64Baseline(virCPUDef **cpus, const char **features G_GNUC_UNUSED, bool migratable G_GNUC_UNUSED) { - g_autoptr(virCPUppc64Map) map = NULL; + virCPUppc64Map *map = NULL; const virCPUppc64Model *model; const virCPUppc64Vendor *vendor = NULL; g_autoptr(virCPUDef) cpu = NULL; size_t i; - if (!(map = ppc64LoadMap())) + if (!(map = virCPUppc64GetMap())) return NULL; if (!(model = ppc64ModelFind(map, cpus[0]->model))) { @@ -737,10 +764,10 @@ virCPUppc64Baseline(virCPUDef **cpus, static int virCPUppc64DriverGetModels(char ***models) { - g_autoptr(virCPUppc64Map) map = NULL; + virCPUppc64Map *map = NULL; size_t i; - if (!(map = ppc64LoadMap())) + if (!(map = virCPUppc64GetMap())) return -1; if (models) { -- 2.37.3

The only part of qemuCaps both functions are interested in is the CPU architecture. Changing them to expect just virArch makes the functions more reusable. Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/qemu/qemu_capabilities.c | 18 +++++++++--------- src/qemu/qemu_capabilities.h | 4 ++-- src/qemu/qemu_command.c | 2 +- src/qemu/qemu_monitor.c | 7 +++---- src/qemu/qemu_monitor.h | 5 ++--- src/qemu/qemu_monitor_json.c | 11 ++++------- src/qemu/qemu_monitor_json.h | 1 - src/qemu/qemu_process.c | 12 +----------- 8 files changed, 22 insertions(+), 38 deletions(-) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 2a0be77631..fc4a5f66f7 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -3108,7 +3108,7 @@ virQEMUCapsGetCPUFeatures(virQEMUCaps *qemuCaps, if (migratable && prop->migratable == VIR_TRISTATE_BOOL_NO) continue; - list[n++] = g_strdup(virQEMUCapsCPUFeatureFromQEMU(qemuCaps, prop->name)); + list[n++] = g_strdup(virQEMUCapsCPUFeatureFromQEMU(qemuCaps->arch, prop->name)); } *features = g_steal_pointer(&list); @@ -3434,14 +3434,14 @@ virQEMUCapsCPUFeatureTranslationTable virQEMUCapsCPUFeaturesX86[] = { static const char * -virQEMUCapsCPUFeatureTranslate(virQEMUCaps *qemuCaps, +virQEMUCapsCPUFeatureTranslate(virArch arch, const char *feature, bool reversed) { virQEMUCapsCPUFeatureTranslationTable *table = NULL; virQEMUCapsCPUFeatureTranslationTable *entry; - if (ARCH_IS_X86(qemuCaps->arch)) + if (ARCH_IS_X86(arch)) table = virQEMUCapsCPUFeaturesX86; if (!table || @@ -3460,18 +3460,18 @@ virQEMUCapsCPUFeatureTranslate(virQEMUCaps *qemuCaps, const char * -virQEMUCapsCPUFeatureToQEMU(virQEMUCaps *qemuCaps, +virQEMUCapsCPUFeatureToQEMU(virArch arch, const char *feature) { - return virQEMUCapsCPUFeatureTranslate(qemuCaps, feature, false); + return virQEMUCapsCPUFeatureTranslate(arch, feature, false); } const char * -virQEMUCapsCPUFeatureFromQEMU(virQEMUCaps *qemuCaps, +virQEMUCapsCPUFeatureFromQEMU(virArch arch, const char *feature) { - return virQEMUCapsCPUFeatureTranslate(qemuCaps, feature, true); + return virQEMUCapsCPUFeatureTranslate(arch, feature, true); } @@ -3510,7 +3510,7 @@ virQEMUCapsInitCPUModelS390(virQEMUCaps *qemuCaps, for (i = 0; i < modelInfo->nprops; i++) { virCPUFeatureDef *feature = cpu->features + cpu->nfeatures; qemuMonitorCPUProperty *prop = modelInfo->props + i; - const char *name = virQEMUCapsCPUFeatureFromQEMU(qemuCaps, prop->name); + const char *name = virQEMUCapsCPUFeatureFromQEMU(qemuCaps->arch, prop->name); if (prop->type != QEMU_MONITOR_CPU_PROPERTY_BOOLEAN) continue; @@ -3545,7 +3545,7 @@ virQEMUCapsGetCPUModelX86Data(virQEMUCaps *qemuCaps, for (i = 0; i < model->nprops; i++) { qemuMonitorCPUProperty *prop = model->props + i; - const char *name = virQEMUCapsCPUFeatureFromQEMU(qemuCaps, prop->name); + const char *name = virQEMUCapsCPUFeatureFromQEMU(qemuCaps->arch, prop->name); switch (prop->type) { case QEMU_MONITOR_CPU_PROPERTY_BOOLEAN: diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index ca919ff368..904ee54f60 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -838,11 +838,11 @@ bool virQEMUCapsCPUFilterFeatures(const char *name, void *opaque); const char * -virQEMUCapsCPUFeatureToQEMU(virQEMUCaps *qemuCaps, +virQEMUCapsCPUFeatureToQEMU(virArch arch, const char *feature); const char * -virQEMUCapsCPUFeatureFromQEMU(virQEMUCaps *qemuCaps, +virQEMUCapsCPUFeatureFromQEMU(virArch arch, const char *feature); virSEVCapability * diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 7ec44736d3..150824f2e1 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -6111,7 +6111,7 @@ qemuBuildCpuModelArgStr(virQEMUDriver *driver, for (i = 0; i < cpu->nfeatures; i++) { const char *featname = - virQEMUCapsCPUFeatureToQEMU(qemuCaps, cpu->features[i].name); + virQEMUCapsCPUFeatureToQEMU(def->os.arch, cpu->features[i].name); switch ((virCPUFeaturePolicy) cpu->features[i].policy) { case VIR_CPU_FEATURE_FORCE: case VIR_CPU_FEATURE_REQUIRE: diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index c2808c75a3..5eba154d96 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -3633,12 +3633,11 @@ qemuMonitorGetGuestCPU(qemuMonitor *mon, virArch arch, const char *cpuQOMPath, qemuMonitorCPUFeatureTranslationCallback translate, - void *opaque, virCPUData **enabled, virCPUData **disabled) { - VIR_DEBUG("arch=%s cpuQOMPath=%s translate=%p opaque=%p enabled=%p disabled=%p", - virArchToString(arch), cpuQOMPath, translate, opaque, enabled, disabled); + VIR_DEBUG("arch=%s cpuQOMPath=%s translate=%p enabled=%p disabled=%p", + virArchToString(arch), cpuQOMPath, translate, enabled, disabled); QEMU_CHECK_MONITOR(mon); @@ -3646,7 +3645,7 @@ qemuMonitorGetGuestCPU(qemuMonitor *mon, if (disabled) *disabled = NULL; - return qemuMonitorJSONGetGuestCPU(mon, arch, cpuQOMPath, translate, opaque, + return qemuMonitorJSONGetGuestCPU(mon, arch, cpuQOMPath, translate, enabled, disabled); } diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index 4d770486be..4fead0a998 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -1219,14 +1219,13 @@ int qemuMonitorGetGuestCPUx86(qemuMonitor *mon, virCPUData **data, virCPUData **disabled); -typedef const char *(*qemuMonitorCPUFeatureTranslationCallback)(const char *name, - void *opaque); +typedef const char *(*qemuMonitorCPUFeatureTranslationCallback)(virArch arch, + const char *name); int qemuMonitorGetGuestCPU(qemuMonitor *mon, virArch arch, const char *cpuQOMPath, qemuMonitorCPUFeatureTranslationCallback translate, - void *opaque, virCPUData **enabled, virCPUData **disabled); diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index b63400354b..f54b4609a9 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -6781,7 +6781,6 @@ static int qemuMonitorJSONGetCPUData(qemuMonitor *mon, const char *cpuQOMPath, qemuMonitorCPUFeatureTranslationCallback translate, - void *opaque, virCPUData *data) { qemuMonitorJSONObjectProperty prop = { .type = QEMU_MONITOR_OBJECT_PROPERTY_BOOLEAN }; @@ -6801,7 +6800,7 @@ qemuMonitorJSONGetCPUData(qemuMonitor *mon, continue; if (translate) - name = translate(name, opaque); + name = translate(data->arch, name); if (virCPUDataAddFeature(data, name) < 0) return -1; @@ -6815,7 +6814,6 @@ static int qemuMonitorJSONGetCPUDataDisabled(qemuMonitor *mon, const char *cpuQOMPath, qemuMonitorCPUFeatureTranslationCallback translate, - void *opaque, virCPUData *data) { g_auto(GStrv) props = NULL; @@ -6829,7 +6827,7 @@ qemuMonitorJSONGetCPUDataDisabled(qemuMonitor *mon, const char *name = *p; if (translate) - name = translate(name, opaque); + name = translate(data->arch, name); if (virCPUDataAddFeature(data, name) < 0) return -1; @@ -6859,7 +6857,6 @@ qemuMonitorJSONGetGuestCPU(qemuMonitor *mon, virArch arch, const char *cpuQOMPath, qemuMonitorCPUFeatureTranslationCallback translate, - void *opaque, virCPUData **enabled, virCPUData **disabled) { @@ -6870,11 +6867,11 @@ qemuMonitorJSONGetGuestCPU(qemuMonitor *mon, !(cpuDisabled = virCPUDataNew(arch))) return -1; - if (qemuMonitorJSONGetCPUData(mon, cpuQOMPath, translate, opaque, cpuEnabled) < 0) + if (qemuMonitorJSONGetCPUData(mon, cpuQOMPath, translate, cpuEnabled) < 0) return -1; if (disabled && - qemuMonitorJSONGetCPUDataDisabled(mon, cpuQOMPath, translate, opaque, cpuDisabled) < 0) + qemuMonitorJSONGetCPUDataDisabled(mon, cpuQOMPath, translate, cpuDisabled) < 0) return -1; *enabled = g_steal_pointer(&cpuEnabled); diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h index a53e6423df..f14d0b5bae 100644 --- a/src/qemu/qemu_monitor_json.h +++ b/src/qemu/qemu_monitor_json.h @@ -605,7 +605,6 @@ qemuMonitorJSONGetGuestCPU(qemuMonitor *mon, virArch arch, const char *cpuQOMPath, qemuMonitorCPUFeatureTranslationCallback translate, - void *opaque, virCPUData **enabled, virCPUData **disabled); diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index 998f4aa63c..de627d883c 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -4295,16 +4295,6 @@ qemuProcessVerifyCPUFeatures(virDomainDef *def, } -static const char * -qemuProcessTranslateCPUFeatures(const char *name, - void *opaque) -{ - virQEMUCaps *qemuCaps = opaque; - - return virQEMUCapsCPUFeatureFromQEMU(qemuCaps, name); -} - - /* returns the QOM path to the first vcpu */ static const char * qemuProcessGetVCPUQOMPath(virDomainObj *vm) @@ -4349,7 +4339,7 @@ qemuProcessFetchGuestCPU(virDomainObj *vm, rc = qemuMonitorGetGuestCPU(priv->mon, vm->def->os.arch, cpuQOMPath, - qemuProcessTranslateCPUFeatures, priv->qemuCaps, + virQEMUCapsCPUFeatureFromQEMU, &dataEnabled, &dataDisabled); } else { rc = qemuMonitorGetGuestCPUx86(priv->mon, cpuQOMPath, &dataEnabled, &dataDisabled); -- 2.37.3

Even though several CPU models from various vendors are reported as usable on a given host, user may still want to use only those that match the host vendor. Currently the only place where users can check the vendor of each CPU model is our CPU map, which is considered internal and users should not really be using it directly. So to allow for such filtering we now advertising the vendor of each CPU model in domain capabilities. Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- docs/formatdomaincaps.rst | 12 +- src/conf/domain_capabilities.c | 13 +- src/conf/domain_capabilities.h | 4 +- src/conf/schemas/domaincaps.rng | 3 + src/qemu/qemu_capabilities.c | 2 +- tests/cputest.c | 5 +- .../domaincapsdata/qemu_4.2.0-q35.x86_64.xml | 104 ++++++------ .../domaincapsdata/qemu_4.2.0-tcg.x86_64.xml | 104 ++++++------ .../qemu_4.2.0-virt.aarch64.xml | 72 ++++----- tests/domaincapsdata/qemu_4.2.0.aarch64.xml | 72 ++++----- tests/domaincapsdata/qemu_4.2.0.ppc64.xml | 6 +- tests/domaincapsdata/qemu_4.2.0.s390x.xml | 148 +++++++++--------- tests/domaincapsdata/qemu_4.2.0.x86_64.xml | 104 ++++++------ .../domaincapsdata/qemu_5.0.0-q35.x86_64.xml | 108 ++++++------- .../domaincapsdata/qemu_5.0.0-tcg.x86_64.xml | 108 ++++++------- .../qemu_5.0.0-virt.aarch64.xml | 74 ++++----- tests/domaincapsdata/qemu_5.0.0.aarch64.xml | 74 ++++----- tests/domaincapsdata/qemu_5.0.0.ppc64.xml | 8 +- tests/domaincapsdata/qemu_5.0.0.x86_64.xml | 108 ++++++------- .../domaincapsdata/qemu_5.1.0-q35.x86_64.xml | 108 ++++++------- .../domaincapsdata/qemu_5.1.0-tcg.x86_64.xml | 108 ++++++------- tests/domaincapsdata/qemu_5.1.0.x86_64.xml | 108 ++++++------- .../domaincapsdata/qemu_5.2.0-q35.x86_64.xml | 108 ++++++------- .../domaincapsdata/qemu_5.2.0-tcg.x86_64.xml | 108 ++++++------- .../qemu_5.2.0-virt.aarch64.xml | 74 ++++----- tests/domaincapsdata/qemu_5.2.0.aarch64.xml | 74 ++++----- tests/domaincapsdata/qemu_5.2.0.ppc64.xml | 8 +- tests/domaincapsdata/qemu_5.2.0.s390x.xml | 148 +++++++++--------- tests/domaincapsdata/qemu_5.2.0.x86_64.xml | 108 ++++++------- .../domaincapsdata/qemu_6.0.0-q35.x86_64.xml | 110 ++++++------- .../domaincapsdata/qemu_6.0.0-tcg.x86_64.xml | 110 ++++++------- .../qemu_6.0.0-virt.aarch64.xml | 76 ++++----- tests/domaincapsdata/qemu_6.0.0.aarch64.xml | 76 ++++----- tests/domaincapsdata/qemu_6.0.0.s390x.xml | 148 +++++++++--------- tests/domaincapsdata/qemu_6.0.0.x86_64.xml | 110 ++++++------- .../domaincapsdata/qemu_6.1.0-q35.x86_64.xml | 110 ++++++------- .../domaincapsdata/qemu_6.1.0-tcg.x86_64.xml | 110 ++++++------- tests/domaincapsdata/qemu_6.1.0.x86_64.xml | 110 ++++++------- .../domaincapsdata/qemu_6.2.0-q35.x86_64.xml | 110 ++++++------- .../domaincapsdata/qemu_6.2.0-tcg.x86_64.xml | 110 ++++++------- .../qemu_6.2.0-virt.aarch64.xml | 78 ++++----- tests/domaincapsdata/qemu_6.2.0.aarch64.xml | 78 ++++----- tests/domaincapsdata/qemu_6.2.0.ppc64.xml | 8 +- tests/domaincapsdata/qemu_6.2.0.x86_64.xml | 110 ++++++------- .../domaincapsdata/qemu_7.0.0-q35.x86_64.xml | 110 ++++++------- .../domaincapsdata/qemu_7.0.0-tcg.x86_64.xml | 110 ++++++------- .../qemu_7.0.0-virt.aarch64.xml | 78 ++++----- tests/domaincapsdata/qemu_7.0.0.aarch64.xml | 78 ++++----- tests/domaincapsdata/qemu_7.0.0.ppc64.xml | 8 +- tests/domaincapsdata/qemu_7.0.0.x86_64.xml | 110 ++++++------- .../domaincapsdata/qemu_7.1.0-q35.x86_64.xml | 106 ++++++------- .../domaincapsdata/qemu_7.1.0-tcg.x86_64.xml | 106 ++++++------- tests/domaincapsdata/qemu_7.1.0.x86_64.xml | 106 ++++++------- 53 files changed, 2183 insertions(+), 2164 deletions(-) diff --git a/docs/formatdomaincaps.rst b/docs/formatdomaincaps.rst index 70f46b972a..6ce780fb69 100644 --- a/docs/formatdomaincaps.rst +++ b/docs/formatdomaincaps.rst @@ -191,9 +191,10 @@ CPUs <formatdomain.html#cpu-model-and-topology>`__. <feature policy='require' name='vmx'/> </mode> <mode name='custom' supported='yes'> - <model usable='no' deprecated='no'>Broadwell</model> - <model usable='yes' deprecated='no'>Broadwell-noTSX</model> - <model usable='no' deprecated='yes'>Haswell</model> + <model usable='no' deprecated='no' vendor='Intel'>Broadwell</model> + <model usable='yes' deprecated='no' vendor='Intel'>Broadwell-noTSX</model> + <model usable='no' deprecated='yes' vendor='Intel'>Haswell</model> + <model usable='no' deprecated='no' vendor='AMD'>EPYC-Milan</model> ... </mode> </cpu> @@ -226,7 +227,10 @@ more details about it: CPU of such model is expected to have. A special value ``unknown`` indicates libvirt does not have enough information to provide the usability data. The ``deprecated`` attribute reflects the hypervisor's policy on usage of this - model :since:`(since 7.1.0)` . + model :since:`(since 7.1.0)`. The ``vendor`` attribute :since:`(since 8.9.0)` + contains the vendor of the CPU model for users who want to use CPU models + with specific vendors only. CPU models with undefined vendor will be listed + with ``vendor='unkwnown'``. I/O Threads ~~~~~~~~~~~ diff --git a/src/conf/domain_capabilities.c b/src/conf/domain_capabilities.c index 123c80a560..b5d8288982 100644 --- a/src/conf/domain_capabilities.c +++ b/src/conf/domain_capabilities.c @@ -105,6 +105,7 @@ virDomainCapsCPUModelsDispose(void *obj) for (i = 0; i < cpuModels->nmodels; i++) { g_free(cpuModels->models[i].name); g_strfreev(cpuModels->models[i].blockers); + g_free(cpuModels->models[i].vendor); } g_free(cpuModels->models); @@ -166,7 +167,8 @@ virDomainCapsCPUModelsCopy(virDomainCapsCPUModels *old) old->models[i].name, old->models[i].usable, old->models[i].blockers, - old->models[i].deprecated); + old->models[i].deprecated, + old->models[i].vendor); } return cpuModels; @@ -178,7 +180,8 @@ virDomainCapsCPUModelsAdd(virDomainCapsCPUModels *cpuModels, const char *name, virDomainCapsCPUUsable usable, char **blockers, - bool deprecated) + bool deprecated, + const char *vendor) { virDomainCapsCPUModel *cpu; @@ -192,6 +195,7 @@ virDomainCapsCPUModelsAdd(virDomainCapsCPUModels *cpuModels, cpu->name = g_strdup(name); cpu->blockers = g_strdupv(blockers); cpu->deprecated = deprecated; + cpu->vendor = g_strdup(vendor); } @@ -377,6 +381,11 @@ virDomainCapsCPUCustomFormat(virBuffer *buf, if (model->deprecated) virBufferAddLit(buf, " deprecated='yes'"); + if (model->vendor) + virBufferAsprintf(buf, " vendor='%s'", model->vendor); + else + virBufferAddLit(buf, " vendor='unknown'"); + virBufferAsprintf(buf, ">%s</model>\n", model->name); } diff --git a/src/conf/domain_capabilities.h b/src/conf/domain_capabilities.h index 7333276231..f5fa1fb8e3 100644 --- a/src/conf/domain_capabilities.h +++ b/src/conf/domain_capabilities.h @@ -159,6 +159,7 @@ struct _virDomainCapsCPUModel { virDomainCapsCPUUsable usable; char **blockers; /* NULL-terminated list of usability blockers */ bool deprecated; + char *vendor; }; typedef struct _virDomainCapsCPUModels virDomainCapsCPUModels; @@ -249,7 +250,8 @@ virDomainCapsCPUModelsAdd(virDomainCapsCPUModels *cpuModels, const char *name, virDomainCapsCPUUsable usable, char **blockers, - bool deprecated); + bool deprecated, + const char *vendor); virDomainCapsCPUModel * virDomainCapsCPUModelsGet(virDomainCapsCPUModels *cpuModels, const char *name); diff --git a/src/conf/schemas/domaincaps.rng b/src/conf/schemas/domaincaps.rng index 9cbc2467ab..c4cb9afeba 100644 --- a/src/conf/schemas/domaincaps.rng +++ b/src/conf/schemas/domaincaps.rng @@ -159,6 +159,9 @@ <ref name="virYesNo"/> </attribute> </optional> + <attribute name='vendor'> + <text/> + </attribute> <text/> </element> </zeroOrMore> diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index fc4a5f66f7..1c771dbfb9 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -2195,7 +2195,7 @@ virQEMUCapsCPUDefsToModels(qemuMonitorCPUDefs *defs, continue; virDomainCapsCPUModelsAdd(cpuModels, cpu->name, cpu->usable, - cpu->blockers, cpu->deprecated); + cpu->blockers, cpu->deprecated, NULL); } return cpuModels; diff --git a/tests/cputest.c b/tests/cputest.c index 9d24b9d0f5..52e0022ac3 100644 --- a/tests/cputest.c +++ b/tests/cputest.c @@ -824,7 +824,7 @@ cpuTestUpdateLive(const void *arg) } virDomainCapsCPUModelsAdd(models, expected->model, - usable, blockers, false); + usable, blockers, false, expected->vendor); cpu->fallback = VIR_CPU_FALLBACK_ALLOW; ignore_value(virCPUTranslate(data->arch, cpu, models)); @@ -902,7 +902,8 @@ cpuTestInitModels(const char **list) for (model = list; *model; model++) { virDomainCapsCPUModelsAdd(cpus, *model, - VIR_DOMCAPS_CPU_USABLE_UNKNOWN, NULL, false); + VIR_DOMCAPS_CPU_USABLE_UNKNOWN, + NULL, false, NULL); } return cpus; diff --git a/tests/domaincapsdata/qemu_4.2.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_4.2.0-q35.x86_64.xml index 0ec4c570ac..fa86554892 100644 --- a/tests/domaincapsdata/qemu_4.2.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_4.2.0-q35.x86_64.xml @@ -61,58 +61,58 @@ <feature policy='require' name='pschange-mc-no'/> </mode> <mode name='custom' supported='yes'> - <model usable='yes'>qemu64</model> - <model usable='yes'>qemu32</model> - <model usable='no'>phenom</model> - <model usable='yes'>pentium3</model> - <model usable='yes'>pentium2</model> - <model usable='yes'>pentium</model> - <model usable='yes'>n270</model> - <model usable='yes'>kvm64</model> - <model usable='yes'>kvm32</model> - <model usable='yes'>coreduo</model> - <model usable='yes'>core2duo</model> - <model usable='no'>athlon</model> - <model usable='yes'>Westmere-IBRS</model> - <model usable='yes'>Westmere</model> - <model usable='no'>Snowridge</model> - <model usable='no'>Skylake-Server-noTSX-IBRS</model> - <model usable='no'>Skylake-Server-IBRS</model> - <model usable='no'>Skylake-Server</model> - <model usable='yes'>Skylake-Client-noTSX-IBRS</model> - <model usable='yes'>Skylake-Client-IBRS</model> - <model usable='yes'>Skylake-Client</model> - <model usable='yes'>SandyBridge-IBRS</model> - <model usable='yes'>SandyBridge</model> - <model usable='yes'>Penryn</model> - <model usable='no'>Opteron_G5</model> - <model usable='no'>Opteron_G4</model> - <model usable='no'>Opteron_G3</model> - <model usable='yes'>Opteron_G2</model> - <model usable='yes'>Opteron_G1</model> - <model usable='yes'>Nehalem-IBRS</model> - <model usable='yes'>Nehalem</model> - <model usable='yes'>IvyBridge-IBRS</model> - <model usable='yes'>IvyBridge</model> - <model usable='no'>Icelake-Server-noTSX</model> - <model usable='no'>Icelake-Server</model> - <model usable='no'>Icelake-Client-noTSX</model> - <model usable='no'>Icelake-Client</model> - <model usable='yes'>Haswell-noTSX-IBRS</model> - <model usable='yes'>Haswell-noTSX</model> - <model usable='yes'>Haswell-IBRS</model> - <model usable='yes'>Haswell</model> - <model usable='no'>EPYC-IBPB</model> - <model usable='no'>EPYC</model> - <model usable='no'>Dhyana</model> - <model usable='yes'>Conroe</model> - <model usable='no'>Cascadelake-Server-noTSX</model> - <model usable='no'>Cascadelake-Server</model> - <model usable='yes'>Broadwell-noTSX-IBRS</model> - <model usable='yes'>Broadwell-noTSX</model> - <model usable='yes'>Broadwell-IBRS</model> - <model usable='yes'>Broadwell</model> - <model usable='yes'>486</model> + <model usable='yes' vendor='unknown'>qemu64</model> + <model usable='yes' vendor='unknown'>qemu32</model> + <model usable='no' vendor='unknown'>phenom</model> + <model usable='yes' vendor='unknown'>pentium3</model> + <model usable='yes' vendor='unknown'>pentium2</model> + <model usable='yes' vendor='unknown'>pentium</model> + <model usable='yes' vendor='unknown'>n270</model> + <model usable='yes' vendor='unknown'>kvm64</model> + <model usable='yes' vendor='unknown'>kvm32</model> + <model usable='yes' vendor='unknown'>coreduo</model> + <model usable='yes' vendor='unknown'>core2duo</model> + <model usable='no' vendor='unknown'>athlon</model> + <model usable='yes' vendor='unknown'>Westmere-IBRS</model> + <model usable='yes' vendor='unknown'>Westmere</model> + <model usable='no' vendor='unknown'>Snowridge</model> + <model usable='no' vendor='unknown'>Skylake-Server-noTSX-IBRS</model> + <model usable='no' vendor='unknown'>Skylake-Server-IBRS</model> + <model usable='no' vendor='unknown'>Skylake-Server</model> + <model usable='yes' vendor='unknown'>Skylake-Client-noTSX-IBRS</model> + <model usable='yes' vendor='unknown'>Skylake-Client-IBRS</model> + <model usable='yes' vendor='unknown'>Skylake-Client</model> + <model usable='yes' vendor='unknown'>SandyBridge-IBRS</model> + <model usable='yes' vendor='unknown'>SandyBridge</model> + <model usable='yes' vendor='unknown'>Penryn</model> + <model usable='no' vendor='unknown'>Opteron_G5</model> + <model usable='no' vendor='unknown'>Opteron_G4</model> + <model usable='no' vendor='unknown'>Opteron_G3</model> + <model usable='yes' vendor='unknown'>Opteron_G2</model> + <model usable='yes' vendor='unknown'>Opteron_G1</model> + <model usable='yes' vendor='unknown'>Nehalem-IBRS</model> + <model usable='yes' vendor='unknown'>Nehalem</model> + <model usable='yes' vendor='unknown'>IvyBridge-IBRS</model> + <model usable='yes' vendor='unknown'>IvyBridge</model> + <model usable='no' vendor='unknown'>Icelake-Server-noTSX</model> + <model usable='no' vendor='unknown'>Icelake-Server</model> + <model usable='no' vendor='unknown'>Icelake-Client-noTSX</model> + <model usable='no' vendor='unknown'>Icelake-Client</model> + <model usable='yes' vendor='unknown'>Haswell-noTSX-IBRS</model> + <model usable='yes' vendor='unknown'>Haswell-noTSX</model> + <model usable='yes' vendor='unknown'>Haswell-IBRS</model> + <model usable='yes' vendor='unknown'>Haswell</model> + <model usable='no' vendor='unknown'>EPYC-IBPB</model> + <model usable='no' vendor='unknown'>EPYC</model> + <model usable='no' vendor='unknown'>Dhyana</model> + <model usable='yes' vendor='unknown'>Conroe</model> + <model usable='no' vendor='unknown'>Cascadelake-Server-noTSX</model> + <model usable='no' vendor='unknown'>Cascadelake-Server</model> + <model usable='yes' vendor='unknown'>Broadwell-noTSX-IBRS</model> + <model usable='yes' vendor='unknown'>Broadwell-noTSX</model> + <model usable='yes' vendor='unknown'>Broadwell-IBRS</model> + <model usable='yes' vendor='unknown'>Broadwell</model> + <model usable='yes' vendor='unknown'>486</model> </mode> </cpu> <memoryBacking supported='yes'> ... -- 2.37.3

On a Tuesday in 2022, Jiri Denemark wrote:
Even though several CPU models from various vendors are reported as usable on a given host, user may still want to use only those that match the host vendor. Currently the only place where users can check the vendor of each CPU model is our CPU map, which is considered internal and users should not really be using it directly. So to allow for such filtering we now advertising the vendor of each CPU model in domain
*advertise
capabilities.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
Jano

So far QEMU driver does not get CPU model vendor from QEMU directly and it has to ask the CPU driver for the info stored in CPU map. Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/cpu/cpu.c | 25 +++++++++++++++++++++++++ src/cpu/cpu.h | 8 ++++++++ src/libvirt_private.syms | 1 + src/qemu/qemu_capabilities.c | 18 +++++++++++++----- 4 files changed, 47 insertions(+), 5 deletions(-) diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index d97ef5e873..7f3caf7a27 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -923,6 +923,31 @@ virCPUGetModels(virArch arch, char ***models) } +/** virCPUGetVendorForModel: + * + * @arch: CPU architecture + * @model: CPU model to be checked + * + * Returns @model's vendor or NULL if the vendor is unknown. + */ +const char * +virCPUGetVendorForModel(virArch arch, + const char *model) +{ + struct cpuArchDriver *driver; + + VIR_DEBUG("arch=%s", virArchToString(arch)); + + if (!(driver = cpuGetSubDriver(arch))) + return NULL; + + if (!driver->getVendorForModel) + return NULL; + + return driver->getVendorForModel(model); +} + + /** * virCPUTranslate: * diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index 41a62ce486..a4cdb37f03 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -105,6 +105,9 @@ typedef virCPUData * typedef int (*virCPUArchGetModels)(char ***models); +typedef const char * +(*virCPUArchGetVendorForModel)(const char *model); + typedef int (*virCPUArchTranslate)(virCPUDef *cpu, virDomainCapsCPUModels *models); @@ -150,6 +153,7 @@ struct cpuArchDriver { virCPUArchDataFormat dataFormat; virCPUArchDataParse dataParse; virCPUArchGetModels getModels; + virCPUArchGetVendorForModel getVendorForModel; virCPUArchTranslate translate; virCPUArchConvertLegacy convertLegacy; virCPUArchExpandFeatures expandFeatures; @@ -262,6 +266,10 @@ virCPUModelIsAllowed(const char *model, int virCPUGetModels(virArch arch, char ***models); +const char * +virCPUGetVendorForModel(virArch arch, + const char *model); + int virCPUTranslate(virArch arch, virCPUDef *cpu, diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 5be40dbefe..8c3a688d41 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1513,6 +1513,7 @@ virCPUExpandFeatures; virCPUGetHost; virCPUGetHostIsSupported; virCPUGetModels; +virCPUGetVendorForModel; virCPUProbeHost; virCPUTranslate; virCPUUpdate; diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 1c771dbfb9..8e8a84e614 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -2175,9 +2175,11 @@ virQEMUCapsAddCPUDefinitions(virQEMUCaps *qemuCaps, static virDomainCapsCPUModels * -virQEMUCapsCPUDefsToModels(qemuMonitorCPUDefs *defs, +virQEMUCapsCPUDefsToModels(virArch arch, + qemuMonitorCPUDefs *defs, const char **modelAllowed, - const char **modelForbidden) + const char **modelForbidden, + bool vendors) { virDomainCapsCPUModels *cpuModels = NULL; size_t i; @@ -2187,6 +2189,7 @@ virQEMUCapsCPUDefsToModels(qemuMonitorCPUDefs *defs, for (i = 0; i < defs->ncpus; i++) { qemuMonitorCPUDefInfo *cpu = defs->cpus + i; + char *vendor = NULL; if (modelAllowed && !g_strv_contains(modelAllowed, cpu->name)) continue; @@ -2194,8 +2197,11 @@ virQEMUCapsCPUDefsToModels(qemuMonitorCPUDefs *defs, if (modelForbidden && g_strv_contains(modelForbidden, cpu->name)) continue; + if (vendors) + vendor = g_strdup(virCPUGetVendorForModel(arch, cpu->name)); + virDomainCapsCPUModelsAdd(cpuModels, cpu->name, cpu->usable, - cpu->blockers, cpu->deprecated, NULL); + cpu->blockers, cpu->deprecated, vendor); } return cpuModels; @@ -2213,7 +2219,8 @@ virQEMUCapsGetCPUModels(virQEMUCaps *qemuCaps, if (!(defs = virQEMUCapsGetAccel(qemuCaps, type)->cpuModels)) return NULL; - return virQEMUCapsCPUDefsToModels(defs, modelAllowed, modelForbidden); + return virQEMUCapsCPUDefsToModels(qemuCaps->arch, defs, + modelAllowed, modelForbidden, true); } @@ -2946,7 +2953,8 @@ virQEMUCapsFetchCPUModels(qemuMonitor *mon, if (virQEMUCapsFetchCPUDefinitions(mon, arch, &defs) < 0) return -1; - if (defs && !(*cpuModels = virQEMUCapsCPUDefsToModels(defs, NULL, NULL))) + if (defs && + !(*cpuModels = virQEMUCapsCPUDefsToModels(arch, defs, NULL, NULL, false))) return -1; return 0; -- 2.37.3

Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/cpu/cpu_x86.c | 19 ++++ .../domaincapsdata/qemu_4.2.0-q35.x86_64.xml | 88 ++++++++--------- .../domaincapsdata/qemu_4.2.0-tcg.x86_64.xml | 88 ++++++++--------- tests/domaincapsdata/qemu_4.2.0.x86_64.xml | 88 ++++++++--------- .../domaincapsdata/qemu_5.0.0-q35.x86_64.xml | 92 +++++++++--------- .../domaincapsdata/qemu_5.0.0-tcg.x86_64.xml | 92 +++++++++--------- tests/domaincapsdata/qemu_5.0.0.x86_64.xml | 92 +++++++++--------- .../domaincapsdata/qemu_5.1.0-q35.x86_64.xml | 92 +++++++++--------- .../domaincapsdata/qemu_5.1.0-tcg.x86_64.xml | 92 +++++++++--------- tests/domaincapsdata/qemu_5.1.0.x86_64.xml | 92 +++++++++--------- .../domaincapsdata/qemu_5.2.0-q35.x86_64.xml | 92 +++++++++--------- .../domaincapsdata/qemu_5.2.0-tcg.x86_64.xml | 92 +++++++++--------- tests/domaincapsdata/qemu_5.2.0.x86_64.xml | 92 +++++++++--------- .../domaincapsdata/qemu_6.0.0-q35.x86_64.xml | 94 +++++++++---------- .../domaincapsdata/qemu_6.0.0-tcg.x86_64.xml | 94 +++++++++---------- tests/domaincapsdata/qemu_6.0.0.x86_64.xml | 94 +++++++++---------- .../domaincapsdata/qemu_6.1.0-q35.x86_64.xml | 94 +++++++++---------- .../domaincapsdata/qemu_6.1.0-tcg.x86_64.xml | 94 +++++++++---------- tests/domaincapsdata/qemu_6.1.0.x86_64.xml | 94 +++++++++---------- .../domaincapsdata/qemu_6.2.0-q35.x86_64.xml | 94 +++++++++---------- .../domaincapsdata/qemu_6.2.0-tcg.x86_64.xml | 94 +++++++++---------- tests/domaincapsdata/qemu_6.2.0.x86_64.xml | 94 +++++++++---------- .../domaincapsdata/qemu_7.0.0-q35.x86_64.xml | 94 +++++++++---------- .../domaincapsdata/qemu_7.0.0-tcg.x86_64.xml | 94 +++++++++---------- tests/domaincapsdata/qemu_7.0.0.x86_64.xml | 94 +++++++++---------- .../domaincapsdata/qemu_7.1.0-q35.x86_64.xml | 90 +++++++++--------- .../domaincapsdata/qemu_7.1.0-tcg.x86_64.xml | 90 +++++++++--------- tests/domaincapsdata/qemu_7.1.0.x86_64.xml | 90 +++++++++--------- 28 files changed, 1264 insertions(+), 1245 deletions(-) diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c index 9fcd6b8add..4d2379803c 100644 --- a/src/cpu/cpu_x86.c +++ b/src/cpu/cpu_x86.c @@ -3137,6 +3137,24 @@ virCPUx86GetModels(char ***models) } +static const char * +virCPUx86GetVendorForModel(const char *modelName) +{ + virCPUx86Map *map; + virCPUx86Model *model; + + if (!(map = virCPUx86GetMap())) + return NULL; + + model = x86ModelFind(map, modelName); + + if (!model || !model->vendor) + return NULL; + + return model->vendor->name; +} + + static int virCPUx86Translate(virCPUDef *cpu, virDomainCapsCPUModels *models) @@ -3539,6 +3557,7 @@ struct cpuArchDriver cpuDriverX86 = { .dataFormat = virCPUx86DataFormat, .dataParse = virCPUx86DataParse, .getModels = virCPUx86GetModels, + .getVendorForModel = virCPUx86GetVendorForModel, .translate = virCPUx86Translate, .expandFeatures = virCPUx86ExpandFeatures, .copyMigratable = virCPUx86CopyMigratable, diff --git a/tests/domaincapsdata/qemu_4.2.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_4.2.0-q35.x86_64.xml index fa86554892..dab12e5888 100644 --- a/tests/domaincapsdata/qemu_4.2.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_4.2.0-q35.x86_64.xml @@ -63,55 +63,55 @@ <mode name='custom' supported='yes'> <model usable='yes' vendor='unknown'>qemu64</model> <model usable='yes' vendor='unknown'>qemu32</model> - <model usable='no' vendor='unknown'>phenom</model> + <model usable='no' vendor='AMD'>phenom</model> <model usable='yes' vendor='unknown'>pentium3</model> <model usable='yes' vendor='unknown'>pentium2</model> <model usable='yes' vendor='unknown'>pentium</model> - <model usable='yes' vendor='unknown'>n270</model> + <model usable='yes' vendor='Intel'>n270</model> <model usable='yes' vendor='unknown'>kvm64</model> <model usable='yes' vendor='unknown'>kvm32</model> - <model usable='yes' vendor='unknown'>coreduo</model> - <model usable='yes' vendor='unknown'>core2duo</model> - <model usable='no' vendor='unknown'>athlon</model> - <model usable='yes' vendor='unknown'>Westmere-IBRS</model> - <model usable='yes' vendor='unknown'>Westmere</model> - <model usable='no' vendor='unknown'>Snowridge</model> - <model usable='no' vendor='unknown'>Skylake-Server-noTSX-IBRS</model> - <model usable='no' vendor='unknown'>Skylake-Server-IBRS</model> - <model usable='no' vendor='unknown'>Skylake-Server</model> - <model usable='yes' vendor='unknown'>Skylake-Client-noTSX-IBRS</model> - <model usable='yes' vendor='unknown'>Skylake-Client-IBRS</model> - <model usable='yes' vendor='unknown'>Skylake-Client</model> - <model usable='yes' vendor='unknown'>SandyBridge-IBRS</model> - <model usable='yes' vendor='unknown'>SandyBridge</model> - <model usable='yes' vendor='unknown'>Penryn</model> - <model usable='no' vendor='unknown'>Opteron_G5</model> - <model usable='no' vendor='unknown'>Opteron_G4</model> - <model usable='no' vendor='unknown'>Opteron_G3</model> - <model usable='yes' vendor='unknown'>Opteron_G2</model> - <model usable='yes' vendor='unknown'>Opteron_G1</model> - <model usable='yes' vendor='unknown'>Nehalem-IBRS</model> - <model usable='yes' vendor='unknown'>Nehalem</model> - <model usable='yes' vendor='unknown'>IvyBridge-IBRS</model> - <model usable='yes' vendor='unknown'>IvyBridge</model> - <model usable='no' vendor='unknown'>Icelake-Server-noTSX</model> - <model usable='no' vendor='unknown'>Icelake-Server</model> - <model usable='no' vendor='unknown'>Icelake-Client-noTSX</model> - <model usable='no' vendor='unknown'>Icelake-Client</model> - <model usable='yes' vendor='unknown'>Haswell-noTSX-IBRS</model> - <model usable='yes' vendor='unknown'>Haswell-noTSX</model> - <model usable='yes' vendor='unknown'>Haswell-IBRS</model> - <model usable='yes' vendor='unknown'>Haswell</model> - <model usable='no' vendor='unknown'>EPYC-IBPB</model> - <model usable='no' vendor='unknown'>EPYC</model> - <model usable='no' vendor='unknown'>Dhyana</model> - <model usable='yes' vendor='unknown'>Conroe</model> - <model usable='no' vendor='unknown'>Cascadelake-Server-noTSX</model> - <model usable='no' vendor='unknown'>Cascadelake-Server</model> - <model usable='yes' vendor='unknown'>Broadwell-noTSX-IBRS</model> - <model usable='yes' vendor='unknown'>Broadwell-noTSX</model> - <model usable='yes' vendor='unknown'>Broadwell-IBRS</model> - <model usable='yes' vendor='unknown'>Broadwell</model> + <model usable='yes' vendor='Intel'>coreduo</model> + <model usable='yes' vendor='Intel'>core2duo</model> + <model usable='no' vendor='AMD'>athlon</model> + <model usable='yes' vendor='Intel'>Westmere-IBRS</model> + <model usable='yes' vendor='Intel'>Westmere</model> + <model usable='no' vendor='Intel'>Snowridge</model> + <model usable='no' vendor='Intel'>Skylake-Server-noTSX-IBRS</model> + <model usable='no' vendor='Intel'>Skylake-Server-IBRS</model> + <model usable='no' vendor='Intel'>Skylake-Server</model> + <model usable='yes' vendor='Intel'>Skylake-Client-noTSX-IBRS</model> + <model usable='yes' vendor='Intel'>Skylake-Client-IBRS</model> + <model usable='yes' vendor='Intel'>Skylake-Client</model> + <model usable='yes' vendor='Intel'>SandyBridge-IBRS</model> + <model usable='yes' vendor='Intel'>SandyBridge</model> + <model usable='yes' vendor='Intel'>Penryn</model> + <model usable='no' vendor='AMD'>Opteron_G5</model> + <model usable='no' vendor='AMD'>Opteron_G4</model> + <model usable='no' vendor='AMD'>Opteron_G3</model> + <model usable='yes' vendor='AMD'>Opteron_G2</model> + <model usable='yes' vendor='AMD'>Opteron_G1</model> + <model usable='yes' vendor='Intel'>Nehalem-IBRS</model> + <model usable='yes' vendor='Intel'>Nehalem</model> + <model usable='yes' vendor='Intel'>IvyBridge-IBRS</model> + <model usable='yes' vendor='Intel'>IvyBridge</model> + <model usable='no' vendor='Intel'>Icelake-Server-noTSX</model> + <model usable='no' vendor='Intel'>Icelake-Server</model> + <model usable='no' vendor='Intel'>Icelake-Client-noTSX</model> + <model usable='no' vendor='Intel'>Icelake-Client</model> + <model usable='yes' vendor='Intel'>Haswell-noTSX-IBRS</model> + <model usable='yes' vendor='Intel'>Haswell-noTSX</model> + <model usable='yes' vendor='Intel'>Haswell-IBRS</model> + <model usable='yes' vendor='Intel'>Haswell</model> + <model usable='no' vendor='AMD'>EPYC-IBPB</model> + <model usable='no' vendor='AMD'>EPYC</model> + <model usable='no' vendor='Hygon'>Dhyana</model> + <model usable='yes' vendor='Intel'>Conroe</model> + <model usable='no' vendor='Intel'>Cascadelake-Server-noTSX</model> + <model usable='no' vendor='Intel'>Cascadelake-Server</model> + <model usable='yes' vendor='Intel'>Broadwell-noTSX-IBRS</model> + <model usable='yes' vendor='Intel'>Broadwell-noTSX</model> + <model usable='yes' vendor='Intel'>Broadwell-IBRS</model> + <model usable='yes' vendor='Intel'>Broadwell</model> <model usable='yes' vendor='unknown'>486</model> </mode> </cpu> ... -- 2.37.3

Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/cpu/cpu_ppc64.c | 20 ++++++++++++++++++++ tests/domaincapsdata/qemu_4.2.0.ppc64.xml | 6 +++--- tests/domaincapsdata/qemu_5.0.0.ppc64.xml | 8 ++++---- tests/domaincapsdata/qemu_5.2.0.ppc64.xml | 8 ++++---- tests/domaincapsdata/qemu_6.2.0.ppc64.xml | 8 ++++---- tests/domaincapsdata/qemu_7.0.0.ppc64.xml | 8 ++++---- 6 files changed, 39 insertions(+), 19 deletions(-) diff --git a/src/cpu/cpu_ppc64.c b/src/cpu/cpu_ppc64.c index 9997e14a89..7da67ec94a 100644 --- a/src/cpu/cpu_ppc64.c +++ b/src/cpu/cpu_ppc64.c @@ -780,6 +780,25 @@ virCPUppc64DriverGetModels(char ***models) return map->nmodels; } + +static const char * +virCPUppc64GetVendorForModel(const char *modelName) +{ + virCPUppc64Map *map = NULL; + virCPUppc64Model *model; + + if (!(map = virCPUppc64GetMap())) + return NULL; + + model = ppc64ModelFind(map, modelName); + + if (!model || !model->vendor) + return NULL; + + return model->vendor->name; +} + + struct cpuArchDriver cpuDriverPPC64 = { .name = "ppc64", .arch = archs, @@ -793,6 +812,7 @@ struct cpuArchDriver cpuDriverPPC64 = { .baseline = virCPUppc64Baseline, .update = virCPUppc64Update, .getModels = virCPUppc64DriverGetModels, + .getVendorForModel = virCPUppc64GetVendorForModel, .convertLegacy = virCPUppc64ConvertLegacy, .dataIsIdentical = virCPUppc64DataIsIdentical, }; diff --git a/tests/domaincapsdata/qemu_4.2.0.ppc64.xml b/tests/domaincapsdata/qemu_4.2.0.ppc64.xml index 6d09c5ae4e..7093c35355 100644 --- a/tests/domaincapsdata/qemu_4.2.0.ppc64.xml +++ b/tests/domaincapsdata/qemu_4.2.0.ppc64.xml @@ -40,9 +40,9 @@ <model fallback='allow'>POWER8</model> </mode> <mode name='custom' supported='yes'> - <model usable='unknown' vendor='unknown'>POWER9</model> - <model usable='unknown' vendor='unknown'>POWER8</model> - <model usable='unknown' vendor='unknown'>POWER7</model> + <model usable='unknown' vendor='IBM'>POWER9</model> + <model usable='unknown' vendor='IBM'>POWER8</model> + <model usable='unknown' vendor='IBM'>POWER7</model> </mode> </cpu> <memoryBacking supported='yes'> diff --git a/tests/domaincapsdata/qemu_5.0.0.ppc64.xml b/tests/domaincapsdata/qemu_5.0.0.ppc64.xml index 032a4f4e19..b944723885 100644 --- a/tests/domaincapsdata/qemu_5.0.0.ppc64.xml +++ b/tests/domaincapsdata/qemu_5.0.0.ppc64.xml @@ -40,10 +40,10 @@ <model fallback='allow'>POWER8</model> </mode> <mode name='custom' supported='yes'> - <model usable='unknown' vendor='unknown'>POWER10</model> - <model usable='unknown' vendor='unknown'>POWER9</model> - <model usable='unknown' vendor='unknown'>POWER8</model> - <model usable='unknown' vendor='unknown'>POWER7</model> + <model usable='unknown' vendor='IBM'>POWER10</model> + <model usable='unknown' vendor='IBM'>POWER9</model> + <model usable='unknown' vendor='IBM'>POWER8</model> + <model usable='unknown' vendor='IBM'>POWER7</model> </mode> </cpu> <memoryBacking supported='yes'> diff --git a/tests/domaincapsdata/qemu_5.2.0.ppc64.xml b/tests/domaincapsdata/qemu_5.2.0.ppc64.xml index 570d88235b..71f47c8748 100644 --- a/tests/domaincapsdata/qemu_5.2.0.ppc64.xml +++ b/tests/domaincapsdata/qemu_5.2.0.ppc64.xml @@ -40,10 +40,10 @@ <model fallback='allow'>POWER8</model> </mode> <mode name='custom' supported='yes'> - <model usable='unknown' vendor='unknown'>POWER10</model> - <model usable='unknown' vendor='unknown'>POWER9</model> - <model usable='unknown' vendor='unknown'>POWER8</model> - <model usable='unknown' vendor='unknown'>POWER7</model> + <model usable='unknown' vendor='IBM'>POWER10</model> + <model usable='unknown' vendor='IBM'>POWER9</model> + <model usable='unknown' vendor='IBM'>POWER8</model> + <model usable='unknown' vendor='IBM'>POWER7</model> </mode> </cpu> <memoryBacking supported='yes'> diff --git a/tests/domaincapsdata/qemu_6.2.0.ppc64.xml b/tests/domaincapsdata/qemu_6.2.0.ppc64.xml index c2fe03d227..bf2c679c51 100644 --- a/tests/domaincapsdata/qemu_6.2.0.ppc64.xml +++ b/tests/domaincapsdata/qemu_6.2.0.ppc64.xml @@ -40,10 +40,10 @@ <model fallback='allow'>POWER8</model> </mode> <mode name='custom' supported='yes'> - <model usable='unknown' vendor='unknown'>POWER10</model> - <model usable='unknown' vendor='unknown'>POWER9</model> - <model usable='unknown' vendor='unknown'>POWER8</model> - <model usable='unknown' vendor='unknown'>POWER7</model> + <model usable='unknown' vendor='IBM'>POWER10</model> + <model usable='unknown' vendor='IBM'>POWER9</model> + <model usable='unknown' vendor='IBM'>POWER8</model> + <model usable='unknown' vendor='IBM'>POWER7</model> </mode> </cpu> <memoryBacking supported='yes'> diff --git a/tests/domaincapsdata/qemu_7.0.0.ppc64.xml b/tests/domaincapsdata/qemu_7.0.0.ppc64.xml index 06e713373e..8f6f9f57e1 100644 --- a/tests/domaincapsdata/qemu_7.0.0.ppc64.xml +++ b/tests/domaincapsdata/qemu_7.0.0.ppc64.xml @@ -40,10 +40,10 @@ <model fallback='allow'>POWER8</model> </mode> <mode name='custom' supported='yes'> - <model usable='unknown' vendor='unknown'>POWER10</model> - <model usable='unknown' vendor='unknown'>POWER9</model> - <model usable='unknown' vendor='unknown'>POWER8</model> - <model usable='unknown' vendor='unknown'>POWER7</model> + <model usable='unknown' vendor='IBM'>POWER10</model> + <model usable='unknown' vendor='IBM'>POWER9</model> + <model usable='unknown' vendor='IBM'>POWER8</model> + <model usable='unknown' vendor='IBM'>POWER7</model> </mode> </cpu> <memoryBacking supported='yes'> -- 2.37.3

This patch is effectively a no-op, but I wanted to initialize .getVendorForModel explicitly as implementing this function does not even make sense on ARM. The CPU models in our CPU map are only used for describing host CPU in capabilities XML and cannot be used for guest CPU definition in domain XML anyway. The CPU models listed as supported in domain capabilities XML are just passed through from QEMU. Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/cpu/cpu_arm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cpu/cpu_arm.c b/src/cpu/cpu_arm.c index 599bb836ed..409b397155 100644 --- a/src/cpu/cpu_arm.c +++ b/src/cpu/cpu_arm.c @@ -714,6 +714,7 @@ struct cpuArchDriver cpuDriverArm = { #endif .decode = NULL, .encode = NULL, + .getVendorForModel = NULL, .dataCopyNew = virCPUarmDataCopyNew, .dataFree = virCPUarmDataFree, .baseline = virCPUarmBaseline, -- 2.37.3

The list of features reported by QEMU as blocking a particular CPU model on the current host cannot be directly used by libvirt (or its users) as QEMU uses different names for some features. We need to translate them before using them or presenting them to users. Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/qemu/qemu_capabilities.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 8e8a84e614..a19622c878 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -3907,7 +3907,8 @@ virQEMUCapsLoadHostCPUModelInfo(virQEMUCapsAccel *caps, static int -virQEMUCapsLoadCPUModels(virQEMUCapsAccel *caps, +virQEMUCapsLoadCPUModels(virArch arch, + virQEMUCapsAccel *caps, xmlXPathContextPtr ctxt, const char *typeStr) { @@ -3972,12 +3973,16 @@ virQEMUCapsLoadCPUModels(virQEMUCapsAccel *caps, cpu->blockers = g_new0(char *, nblockers + 1); for (j = 0; j < nblockers; j++) { - if (!(cpu->blockers[j] = virXMLPropString(blockerNodes[j], "name"))) { + g_autofree char *blocker = NULL; + + if (!(blocker = virXMLPropString(blockerNodes[j], "name"))) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("missing blocker name in QEMU " "capabilities cache")); return -1; } + + cpu->blockers[j] = g_strdup(virQEMUCapsCPUFeatureFromQEMU(arch, blocker)); } } @@ -4072,7 +4077,7 @@ virQEMUCapsLoadAccel(virQEMUCaps *qemuCaps, if (virQEMUCapsLoadHostCPUModelInfo(caps, ctxt, typeStr) < 0) return -1; - if (virQEMUCapsLoadCPUModels(caps, ctxt, typeStr) < 0) + if (virQEMUCapsLoadCPUModels(qemuCaps->arch, caps, ctxt, typeStr) < 0) return -1; if (virQEMUCapsLoadMachines(caps, ctxt, typeStr) < 0) @@ -4547,7 +4552,8 @@ virQEMUCapsFormatHostCPUModelInfo(virQEMUCapsAccel *caps, static void -virQEMUCapsFormatCPUModels(virQEMUCapsAccel *caps, +virQEMUCapsFormatCPUModels(virArch arch, + virQEMUCapsAccel *caps, virBuffer *buf, const char *typeStr) { @@ -4576,8 +4582,10 @@ virQEMUCapsFormatCPUModels(virQEMUCapsAccel *caps, virBufferAddLit(buf, ">\n"); virBufferAdjustIndent(buf, 2); - for (j = 0; cpu->blockers[j]; j++) - virBufferAsprintf(buf, "<blocker name='%s'/>\n", cpu->blockers[j]); + for (j = 0; cpu->blockers[j]; j++) { + virBufferAsprintf(buf, "<blocker name='%s'/>\n", + virQEMUCapsCPUFeatureToQEMU(arch, cpu->blockers[j])); + } virBufferAdjustIndent(buf, -2); virBufferAddLit(buf, "</cpu>\n"); @@ -4629,7 +4637,7 @@ virQEMUCapsFormatAccel(virQEMUCaps *qemuCaps, const char *typeStr = virQEMUCapsAccelStr(type); virQEMUCapsFormatHostCPUModelInfo(caps, buf, typeStr); - virQEMUCapsFormatCPUModels(caps, buf, typeStr); + virQEMUCapsFormatCPUModels(qemuCaps->arch, caps, buf, typeStr); virQEMUCapsFormatMachines(caps, buf, typeStr); } -- 2.37.3

We already show whether a specific CPU model is usable on the current host without modification via the 'usable' attribute of each CPU model. But it may be useful to actually see what features are blocking each CPU model from being usable. Especially when we already fetch the info from QEMU and propagating it to domain capabilities XML is all we need to do. Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- docs/formatdomaincaps.rst | 16 ++-- src/conf/domain_capabilities.c | 7 ++ src/conf/schemas/domaincaps.rng | 5 ++ .../domaincapsdata/qemu_4.2.0-q35.x86_64.xml | 36 ++++----- .../domaincapsdata/qemu_4.2.0-tcg.x86_64.xml | 72 +++++++++--------- tests/domaincapsdata/qemu_4.2.0.s390x.xml | 2 +- tests/domaincapsdata/qemu_4.2.0.x86_64.xml | 36 ++++----- .../domaincapsdata/qemu_5.0.0-q35.x86_64.xml | 40 +++++----- .../domaincapsdata/qemu_5.0.0-tcg.x86_64.xml | 72 +++++++++--------- tests/domaincapsdata/qemu_5.0.0.x86_64.xml | 40 +++++----- .../domaincapsdata/qemu_5.1.0-q35.x86_64.xml | 68 ++++++++--------- .../domaincapsdata/qemu_5.1.0-tcg.x86_64.xml | 72 +++++++++--------- tests/domaincapsdata/qemu_5.1.0.x86_64.xml | 68 ++++++++--------- .../domaincapsdata/qemu_5.2.0-q35.x86_64.xml | 68 ++++++++--------- .../domaincapsdata/qemu_5.2.0-tcg.x86_64.xml | 72 +++++++++--------- tests/domaincapsdata/qemu_5.2.0.x86_64.xml | 68 ++++++++--------- .../domaincapsdata/qemu_6.0.0-q35.x86_64.xml | 70 +++++++++--------- .../domaincapsdata/qemu_6.0.0-tcg.x86_64.xml | 74 +++++++++---------- tests/domaincapsdata/qemu_6.0.0.x86_64.xml | 70 +++++++++--------- .../domaincapsdata/qemu_6.1.0-q35.x86_64.xml | 70 +++++++++--------- .../domaincapsdata/qemu_6.1.0-tcg.x86_64.xml | 74 +++++++++---------- tests/domaincapsdata/qemu_6.1.0.x86_64.xml | 70 +++++++++--------- .../domaincapsdata/qemu_6.2.0-q35.x86_64.xml | 70 +++++++++--------- .../domaincapsdata/qemu_6.2.0-tcg.x86_64.xml | 74 +++++++++---------- tests/domaincapsdata/qemu_6.2.0.x86_64.xml | 70 +++++++++--------- .../domaincapsdata/qemu_7.0.0-q35.x86_64.xml | 70 +++++++++--------- .../domaincapsdata/qemu_7.0.0-tcg.x86_64.xml | 74 +++++++++---------- tests/domaincapsdata/qemu_7.0.0.x86_64.xml | 70 +++++++++--------- .../domaincapsdata/qemu_7.1.0-q35.x86_64.xml | 66 ++++++++--------- .../domaincapsdata/qemu_7.1.0-tcg.x86_64.xml | 70 +++++++++--------- tests/domaincapsdata/qemu_7.1.0.x86_64.xml | 66 ++++++++--------- 31 files changed, 907 insertions(+), 893 deletions(-) diff --git a/docs/formatdomaincaps.rst b/docs/formatdomaincaps.rst index 6ce780fb69..81211a3fe6 100644 --- a/docs/formatdomaincaps.rst +++ b/docs/formatdomaincaps.rst @@ -191,10 +191,10 @@ CPUs <formatdomain.html#cpu-model-and-topology>`__. <feature policy='require' name='vmx'/> </mode> <mode name='custom' supported='yes'> - <model usable='no' deprecated='no' vendor='Intel'>Broadwell</model> + <model usable='no' deprecated='no' vendor='Intel' blockers='hle,rtm'>Broadwell</model> <model usable='yes' deprecated='no' vendor='Intel'>Broadwell-noTSX</model> - <model usable='no' deprecated='yes' vendor='Intel'>Haswell</model> - <model usable='no' deprecated='no' vendor='AMD'>EPYC-Milan</model> + <model usable='no' deprecated='yes' vendor='Intel' blockers='hle,rtm'>Haswell</model> + <model usable='no' deprecated='no' vendor='AMD' blockers='pcid,erms,invpcid,pku,fsrm,ibrs,pku'>EPYC-Milan</model> ... </mode> </cpu> @@ -224,10 +224,12 @@ more details about it: by a dedicated ``model`` element. The ``usable`` attribute specifies whether the model can be used directly on the host. When usable='no' the corresponding model cannot be used without disabling some features that the - CPU of such model is expected to have. A special value ``unknown`` indicates - libvirt does not have enough information to provide the usability data. The - ``deprecated`` attribute reflects the hypervisor's policy on usage of this - model :since:`(since 7.1.0)`. The ``vendor`` attribute :since:`(since 8.9.0)` + CPU of such model is expected to have. :since:`Since 8.9.0` the ``blockers`` + attribute contains a comma separated list of these features. A special value + ``unknown`` of the attribute ``usable`` indicates libvirt does not have + enough information to provide the usability data. The ``deprecated`` + attribute reflects the hypervisor's policy on usage of this model + :since:`(since 7.1.0)`. The ``vendor`` attribute :since:`(since 8.9.0)` contains the vendor of the CPU model for users who want to use CPU models with specific vendors only. CPU models with undefined vendor will be listed with ``vendor='unkwnown'``. diff --git a/src/conf/domain_capabilities.c b/src/conf/domain_capabilities.c index b5d8288982..4a6418ca37 100644 --- a/src/conf/domain_capabilities.c +++ b/src/conf/domain_capabilities.c @@ -386,6 +386,13 @@ virDomainCapsCPUCustomFormat(virBuffer *buf, else virBufferAddLit(buf, " vendor='unknown'"); + if (model->usable == VIR_DOMCAPS_CPU_USABLE_NO && + model->blockers && + *model->blockers) { + virBufferAsprintf(buf, " blockers='%s'", + g_strjoinv(",", model->blockers)); + } + virBufferAsprintf(buf, ">%s</model>\n", model->name); } diff --git a/src/conf/schemas/domaincaps.rng b/src/conf/schemas/domaincaps.rng index c4cb9afeba..7783b49585 100644 --- a/src/conf/schemas/domaincaps.rng +++ b/src/conf/schemas/domaincaps.rng @@ -162,6 +162,11 @@ <attribute name='vendor'> <text/> </attribute> + <optional> + <attribute name='blockers'> + <text/> + </attribute> + </optional> <text/> </element> </zeroOrMore> diff --git a/tests/domaincapsdata/qemu_4.2.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_4.2.0-q35.x86_64.xml index dab12e5888..8ca9e8d2b2 100644 --- a/tests/domaincapsdata/qemu_4.2.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_4.2.0-q35.x86_64.xml @@ -63,7 +63,7 @@ <mode name='custom' supported='yes'> <model usable='yes' vendor='unknown'>qemu64</model> <model usable='yes' vendor='unknown'>qemu32</model> - <model usable='no' vendor='AMD'>phenom</model> + <model usable='no' vendor='AMD' blockers='mmxext,fxsr_opt,3dnowext,3dnow,sse4a,npt'>phenom</model> <model usable='yes' vendor='unknown'>pentium3</model> <model usable='yes' vendor='unknown'>pentium2</model> <model usable='yes' vendor='unknown'>pentium</model> @@ -72,42 +72,42 @@ <model usable='yes' vendor='unknown'>kvm32</model> <model usable='yes' vendor='Intel'>coreduo</model> <model usable='yes' vendor='Intel'>core2duo</model> - <model usable='no' vendor='AMD'>athlon</model> + <model usable='no' vendor='AMD' blockers='mmxext,3dnowext,3dnow'>athlon</model> <model usable='yes' vendor='Intel'>Westmere-IBRS</model> <model usable='yes' vendor='Intel'>Westmere</model> - <model usable='no' vendor='Intel'>Snowridge</model> - <model usable='no' vendor='Intel'>Skylake-Server-noTSX-IBRS</model> - <model usable='no' vendor='Intel'>Skylake-Server-IBRS</model> - <model usable='no' vendor='Intel'>Skylake-Server</model> + <model usable='no' vendor='Intel' blockers='clwb,sha-ni,gfni,cldemote,movdiri,movdir64b,core-capability,split-lock-detect'>Snowridge</model> + <model usable='no' vendor='Intel' blockers='avx512f,avx512dq,clwb,avx512cd,avx512bw,avx512vl,pku,avx512f,avx512f,avx512f,pku'>Skylake-Server-noTSX-IBRS</model> + <model usable='no' vendor='Intel' blockers='avx512f,avx512dq,clwb,avx512cd,avx512bw,avx512vl,pku,avx512f,avx512f,avx512f,pku'>Skylake-Server-IBRS</model> + <model usable='no' vendor='Intel' blockers='avx512f,avx512dq,clwb,avx512cd,avx512bw,avx512vl,pku,avx512f,avx512f,avx512f,pku'>Skylake-Server</model> <model usable='yes' vendor='Intel'>Skylake-Client-noTSX-IBRS</model> <model usable='yes' vendor='Intel'>Skylake-Client-IBRS</model> <model usable='yes' vendor='Intel'>Skylake-Client</model> <model usable='yes' vendor='Intel'>SandyBridge-IBRS</model> <model usable='yes' vendor='Intel'>SandyBridge</model> <model usable='yes' vendor='Intel'>Penryn</model> - <model usable='no' vendor='AMD'>Opteron_G5</model> - <model usable='no' vendor='AMD'>Opteron_G4</model> - <model usable='no' vendor='AMD'>Opteron_G3</model> + <model usable='no' vendor='AMD' blockers='sse4a,misalignsse,xop,fma4,tbm,npt,nrip-save'>Opteron_G5</model> + <model usable='no' vendor='AMD' blockers='sse4a,misalignsse,xop,fma4,npt,nrip-save'>Opteron_G4</model> + <model usable='no' vendor='AMD' blockers='sse4a,misalignsse'>Opteron_G3</model> <model usable='yes' vendor='AMD'>Opteron_G2</model> <model usable='yes' vendor='AMD'>Opteron_G1</model> <model usable='yes' vendor='Intel'>Nehalem-IBRS</model> <model usable='yes' vendor='Intel'>Nehalem</model> <model usable='yes' vendor='Intel'>IvyBridge-IBRS</model> <model usable='yes' vendor='Intel'>IvyBridge</model> - <model usable='no' vendor='Intel'>Icelake-Server-noTSX</model> - <model usable='no' vendor='Intel'>Icelake-Server</model> - <model usable='no' vendor='Intel'>Icelake-Client-noTSX</model> - <model usable='no' vendor='Intel'>Icelake-Client</model> + <model usable='no' vendor='Intel' blockers='avx512f,avx512dq,clwb,avx512cd,avx512bw,avx512vl,avx512vbmi,pku,avx512vbmi2,gfni,vaes,vpclmulqdq,avx512vnni,avx512bitalg,avx512-vpopcntdq,la57,wbnoinvd,avx512f,avx512f,avx512f,pku'>Icelake-Server-noTSX</model> + <model usable='no' vendor='Intel' blockers='avx512f,avx512dq,clwb,avx512cd,avx512bw,avx512vl,avx512vbmi,pku,avx512vbmi2,gfni,vaes,vpclmulqdq,avx512vnni,avx512bitalg,avx512-vpopcntdq,la57,wbnoinvd,avx512f,avx512f,avx512f,pku'>Icelake-Server</model> + <model usable='no' vendor='Intel' blockers='avx512vbmi,pku,avx512vbmi2,gfni,vaes,vpclmulqdq,avx512vnni,avx512bitalg,avx512-vpopcntdq,wbnoinvd,pku'>Icelake-Client-noTSX</model> + <model usable='no' vendor='Intel' blockers='avx512vbmi,pku,avx512vbmi2,gfni,vaes,vpclmulqdq,avx512vnni,avx512bitalg,avx512-vpopcntdq,wbnoinvd,pku'>Icelake-Client</model> <model usable='yes' vendor='Intel'>Haswell-noTSX-IBRS</model> <model usable='yes' vendor='Intel'>Haswell-noTSX</model> <model usable='yes' vendor='Intel'>Haswell-IBRS</model> <model usable='yes' vendor='Intel'>Haswell</model> - <model usable='no' vendor='AMD'>EPYC-IBPB</model> - <model usable='no' vendor='AMD'>EPYC</model> - <model usable='no' vendor='Hygon'>Dhyana</model> + <model usable='no' vendor='AMD' blockers='sha-ni,mmxext,fxsr_opt,cr8legacy,sse4a,misalignsse,osvw,ibpb,npt,nrip-save'>EPYC-IBPB</model> + <model usable='no' vendor='AMD' blockers='sha-ni,mmxext,fxsr_opt,cr8legacy,sse4a,misalignsse,osvw,ibpb,npt,nrip-save'>EPYC</model> + <model usable='no' vendor='Hygon' blockers='mmxext,fxsr_opt,cr8legacy,sse4a,misalignsse,osvw,ibpb,npt,nrip-save'>Dhyana</model> <model usable='yes' vendor='Intel'>Conroe</model> - <model usable='no' vendor='Intel'>Cascadelake-Server-noTSX</model> - <model usable='no' vendor='Intel'>Cascadelake-Server</model> + <model usable='no' vendor='Intel' blockers='avx512f,avx512dq,clwb,avx512cd,avx512bw,avx512vl,pku,avx512vnni,avx512f,avx512f,avx512f,pku,rdctl-no,ibrs-all,mds-no'>Cascadelake-Server-noTSX</model> + <model usable='no' vendor='Intel' blockers='avx512f,avx512dq,clwb,avx512cd,avx512bw,avx512vl,pku,avx512vnni,avx512f,avx512f,avx512f,pku,rdctl-no,ibrs-all,mds-no'>Cascadelake-Server</model> <model usable='yes' vendor='Intel'>Broadwell-noTSX-IBRS</model> <model usable='yes' vendor='Intel'>Broadwell-noTSX</model> <model usable='yes' vendor='Intel'>Broadwell-IBRS</model> ... -- 2.37.3

On Tue, Oct 04, 2022 at 04:28:53PM +0200, Jiri Denemark wrote:
We already show whether a specific CPU model is usable on the current host without modification via the 'usable' attribute of each CPU model. But it may be useful to actually see what features are blocking each CPU model from being usable. Especially when we already fetch the info from QEMU and propagating it to domain capabilities XML is all we need to do.
diff --git a/tests/domaincapsdata/qemu_4.2.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_4.2.0-q35.x86_64.xml index dab12e5888..8ca9e8d2b2 100644 --- a/tests/domaincapsdata/qemu_4.2.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_4.2.0-q35.x86_64.xml @@ -63,7 +63,7 @@ <mode name='custom' supported='yes'> <model usable='yes' vendor='unknown'>qemu64</model> <model usable='yes' vendor='unknown'>qemu32</model> - <model usable='no' vendor='AMD'>phenom</model> + <model usable='no' vendor='AMD' blockers='mmxext,fxsr_opt,3dnowext,3dnow,sse4a,npt'>phenom</model>
This is an XML design anti-pattern, because it invents a data format inside the attribute which the caller then has to further parse. If we want to expose this, it needs to be with child elements IMHO, but yes it will be more much more verbose. With regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|

On Tue, Oct 04, 2022 at 17:34:34 +0100, Daniel P. Berrangé wrote:
On Tue, Oct 04, 2022 at 04:28:53PM +0200, Jiri Denemark wrote:
We already show whether a specific CPU model is usable on the current host without modification via the 'usable' attribute of each CPU model. But it may be useful to actually see what features are blocking each CPU model from being usable. Especially when we already fetch the info from QEMU and propagating it to domain capabilities XML is all we need to do.
diff --git a/tests/domaincapsdata/qemu_4.2.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_4.2.0-q35.x86_64.xml index dab12e5888..8ca9e8d2b2 100644 --- a/tests/domaincapsdata/qemu_4.2.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_4.2.0-q35.x86_64.xml @@ -63,7 +63,7 @@ <mode name='custom' supported='yes'> <model usable='yes' vendor='unknown'>qemu64</model> <model usable='yes' vendor='unknown'>qemu32</model> - <model usable='no' vendor='AMD'>phenom</model> + <model usable='no' vendor='AMD' blockers='mmxext,fxsr_opt,3dnowext,3dnow,sse4a,npt'>phenom</model>
This is an XML design anti-pattern, because it invents a data format inside the attribute which the caller then has to further parse.
If we want to expose this, it needs to be with child elements IMHO, but yes it will be more much more verbose.
You're absolutely right, but that's the only option we have I'm afraid. Mixing subelements and text nodes is a much worse anti-pattern. I wish the model name was in an attribute, but it isn't and having <model usable='no' vendor='AMD'> <blocker name='mmxext'/> phenom </model> is just insane :-( Jirka

On Tue, Oct 04, 2022 at 07:35:31PM +0200, Jiri Denemark wrote:
On Tue, Oct 04, 2022 at 17:34:34 +0100, Daniel P. Berrangé wrote:
On Tue, Oct 04, 2022 at 04:28:53PM +0200, Jiri Denemark wrote:
We already show whether a specific CPU model is usable on the current host without modification via the 'usable' attribute of each CPU model. But it may be useful to actually see what features are blocking each CPU model from being usable. Especially when we already fetch the info from QEMU and propagating it to domain capabilities XML is all we need to do.
diff --git a/tests/domaincapsdata/qemu_4.2.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_4.2.0-q35.x86_64.xml index dab12e5888..8ca9e8d2b2 100644 --- a/tests/domaincapsdata/qemu_4.2.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_4.2.0-q35.x86_64.xml @@ -63,7 +63,7 @@ <mode name='custom' supported='yes'> <model usable='yes' vendor='unknown'>qemu64</model> <model usable='yes' vendor='unknown'>qemu32</model> - <model usable='no' vendor='AMD'>phenom</model> + <model usable='no' vendor='AMD' blockers='mmxext,fxsr_opt,3dnowext,3dnow,sse4a,npt'>phenom</model>
This is an XML design anti-pattern, because it invents a data format inside the attribute which the caller then has to further parse.
If we want to expose this, it needs to be with child elements IMHO, but yes it will be more much more verbose.
You're absolutely right, but that's the only option we have I'm afraid. Mixing subelements and text nodes is a much worse anti-pattern. I wish the model name was in an attribute, but it isn't and having
<model usable='no' vendor='AMD'> <blocker name='mmxext'/> phenom </model>
is just insane :-(
True, I wonder if there's a different approach to the overall problem that would be better. With regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|

On Tue, Oct 04, 2022 at 07:35:31PM +0200, Jiri Denemark wrote:
On Tue, Oct 04, 2022 at 17:34:34 +0100, Daniel P. Berrangé wrote:
On Tue, Oct 04, 2022 at 04:28:53PM +0200, Jiri Denemark wrote:
We already show whether a specific CPU model is usable on the current host without modification via the 'usable' attribute of each CPU model. But it may be useful to actually see what features are blocking each CPU model from being usable. Especially when we already fetch the info from QEMU and propagating it to domain capabilities XML is all we need to do.
diff --git a/tests/domaincapsdata/qemu_4.2.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_4.2.0-q35.x86_64.xml index dab12e5888..8ca9e8d2b2 100644 --- a/tests/domaincapsdata/qemu_4.2.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_4.2.0-q35.x86_64.xml @@ -63,7 +63,7 @@ <mode name='custom' supported='yes'> <model usable='yes' vendor='unknown'>qemu64</model> <model usable='yes' vendor='unknown'>qemu32</model> - <model usable='no' vendor='AMD'>phenom</model> + <model usable='no' vendor='AMD' blockers='mmxext,fxsr_opt,3dnowext,3dnow,sse4a,npt'>phenom</model>
This is an XML design anti-pattern, because it invents a data format inside the attribute which the caller then has to further parse.
If we want to expose this, it needs to be with child elements IMHO, but yes it will be more much more verbose.
You're absolutely right, but that's the only option we have I'm afraid. Mixing subelements and text nodes is a much worse anti-pattern. I wish the model name was in an attribute, but it isn't and having
<model usable='no' vendor='AMD'> <blocker name='mmxext'/> phenom </model>
is just insane :-(
True, I wonder if there's a different approach to the overall problem that would be better.
Actually a third option just came to my mind. It's not ideal either, but at least it would be a proper XML :-) <mode name='custom' supported='yes'> <model usable='yes' vendor='unknown'>qemu64</model> <model usable='no' vendor='AMD'>phenom</model> <blockers model='phenom'> <feature name='mmxext'/> <feature name='fxsr_opt'/> ... </blockers> <model ...>...</model> ... </mode> Jirka

On Tue, Oct 04, 2022 at 10:17:18PM +0200, Jiri Denemark wrote:
On Tue, Oct 04, 2022 at 07:35:31PM +0200, Jiri Denemark wrote:
On Tue, Oct 04, 2022 at 17:34:34 +0100, Daniel P. Berrangé wrote:
On Tue, Oct 04, 2022 at 04:28:53PM +0200, Jiri Denemark wrote:
We already show whether a specific CPU model is usable on the current host without modification via the 'usable' attribute of each CPU model. But it may be useful to actually see what features are blocking each CPU model from being usable. Especially when we already fetch the info from QEMU and propagating it to domain capabilities XML is all we need to do.
diff --git a/tests/domaincapsdata/qemu_4.2.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_4.2.0-q35.x86_64.xml index dab12e5888..8ca9e8d2b2 100644 --- a/tests/domaincapsdata/qemu_4.2.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_4.2.0-q35.x86_64.xml @@ -63,7 +63,7 @@ <mode name='custom' supported='yes'> <model usable='yes' vendor='unknown'>qemu64</model> <model usable='yes' vendor='unknown'>qemu32</model> - <model usable='no' vendor='AMD'>phenom</model> + <model usable='no' vendor='AMD' blockers='mmxext,fxsr_opt,3dnowext,3dnow,sse4a,npt'>phenom</model>
This is an XML design anti-pattern, because it invents a data format inside the attribute which the caller then has to further parse.
If we want to expose this, it needs to be with child elements IMHO, but yes it will be more much more verbose.
You're absolutely right, but that's the only option we have I'm afraid. Mixing subelements and text nodes is a much worse anti-pattern. I wish the model name was in an attribute, but it isn't and having
<model usable='no' vendor='AMD'> <blocker name='mmxext'/> phenom </model>
is just insane :-(
True, I wonder if there's a different approach to the overall problem that would be better.
Actually a third option just came to my mind. It's not ideal either, but at least it would be a proper XML :-)
<mode name='custom' supported='yes'> <model usable='yes' vendor='unknown'>qemu64</model> <model usable='no' vendor='AMD'>phenom</model> <blockers model='phenom'> <feature name='mmxext'/> <feature name='fxsr_opt'/> ... </blockers> <model ...>...</model> ... </mode>
Actually, looking atr this in practice, I don't think we should be including this information in domcapabilities at all. It gets waaaaaaaay too verbose, even with the custom syntax in this current patch impl. Take a look at this from one of my VMs, which uses the qemu64 model, and thus lacks a huge number of features: <model fallback='forbid'>Opteron_G3</model> <model usable='yes' vendor='unknown'>qemu64</model> <model usable='yes' vendor='unknown'>qemu32</model> <model usable='no' vendor='AMD' blockers='fxsr-opt'>phenom</model> <model usable='yes' vendor='unknown'>pentium3</model> <model usable='yes' vendor='unknown'>pentium2</model> <model usable='yes' vendor='unknown'>pentium</model> <model usable='yes' vendor='Intel'>n270</model> <model usable='yes' vendor='unknown'>kvm64</model> <model usable='yes' vendor='unknown'>kvm32</model> <model usable='yes' vendor='Intel'>coreduo</model> <model usable='yes' vendor='Intel'>core2duo</model> <model usable='yes' vendor='AMD'>athlon</model> <model usable='no' vendor='Intel' blockers='spec-ctrl'>Westmere-IBRS</model> <model usable='yes' vendor='Intel'>Westmere</model> <model usable='no' vendor='Intel' blockers='x2apic,tsc-deadline,rdseed,sha-ni,gfni,cldemote,movdiri,movdir64b,spec-ctrl,arch-capabilities,core-capability,ssbd,3dnowprefetch,xsavec,split-lock-detect'>Snowridge</model> <model usable='no' vendor='Intel' blockers='fma,pcid,x2apic,tsc-deadline,avx,f16c,avx2,invpcid,avx512f,avx512dq,rdseed,avx512cd,avx512bw,avx512vl,spec-ctrl,3dnowprefetch,xsavec'>Skylake-Server-noTSX-IBRS</model> <model usable='no' vendor='Intel' blockers='fma,pcid,x2apic,tsc-deadline,avx,f16c,hle,avx2,invpcid,rtm,avx512f,avx512dq,rdseed,avx512cd,avx512bw,avx512vl,spec-ctrl,3dnowprefetch,xsavec'>Skylake-Server-IBRS</model> <model usable='no' vendor='Intel' blockers='fma,pcid,x2apic,tsc-deadline,avx,f16c,hle,avx2,invpcid,rtm,avx512f,avx512dq,rdseed,avx512cd,avx512bw,avx512vl,3dnowprefetch,xsavec'>Skylake-Server</model> <model usable='no' vendor='Intel' blockers='fma,pcid,x2apic,tsc-deadline,avx,f16c,avx2,invpcid,rdseed,spec-ctrl,3dnowprefetch,xsavec'>Skylake-Client-noTSX-IBRS</model> <model usable='no' vendor='Intel' blockers='fma,pcid,x2apic,tsc-deadline,avx,f16c,hle,avx2,invpcid,rtm,rdseed,spec-ctrl,3dnowprefetch,xsavec'>Skylake-Client-IBRS</model> <model usable='no' vendor='Intel' blockers='fma,pcid,x2apic,tsc-deadline,avx,f16c,hle,avx2,invpcid,rtm,rdseed,3dnowprefetch,xsavec'>Skylake-Client</model> <model usable='no' vendor='Intel' blockers='x2apic,tsc-deadline,avx,spec-ctrl'>SandyBridge-IBRS</model> <model usable='no' vendor='Intel' blockers='x2apic,tsc-deadline,avx'>SandyBridge</model> <model usable='yes' vendor='Intel'>Penryn</model> <model usable='no' vendor='AMD' blockers='fma,avx,f16c,misalignsse,3dnowprefetch,xop,fma4,tbm,nrip-save'>Opteron_G5</model> <model usable='no' vendor='AMD' blockers='avx,misalignsse,3dnowprefetch,xop,fma4,nrip-save'>Opteron_G4</model> <model usable='no' vendor='AMD' blockers='misalignsse'>Opteron_G3</model> <model usable='yes' vendor='AMD'>Opteron_G2</model> <model usable='yes' vendor='AMD'>Opteron_G1</model> <model usable='no' vendor='Intel' blockers='spec-ctrl'>Nehalem-IBRS</model> <model usable='yes' vendor='Intel'>Nehalem</model> <model usable='no' vendor='Intel' blockers='x2apic,tsc-deadline,avx,f16c,spec-ctrl'>IvyBridge-IBRS</model> <model usable='no' vendor='Intel' blockers='x2apic,tsc-deadline,avx,f16c'>IvyBridge</model> <model usable='no' vendor='Intel' blockers='fma,pcid,x2apic,tsc-deadline,avx,f16c,avx2,invpcid,avx512f,avx512dq,rdseed,avx512cd,avx512bw,avx512vl,avx512vbmi,avx512vbmi2,gfni,vaes,vpclmulqdq,avx512vnni,avx512bitalg,avx512-vpopcntdq,spec-ctrl,ssbd,3dnowprefetch,wbnoinvd,xsavec'>Icelake-Server-noTSX</model> <model usable='no' vendor='Intel' blockers='fma,pcid,x2apic,tsc-deadline,avx,f16c,hle,avx2,invpcid,rtm,avx512f,avx512dq,rdseed,avx512cd,avx512bw,avx512vl,avx512vbmi,avx512vbmi2,gfni,vaes,vpclmulqdq,avx512vnni,avx512bitalg,avx512-vpopcntdq,spec-ctrl,ssbd,3dnowprefetch,wbnoinvd,xsavec'>Icelake-Server</model> <model usable='no' deprecated='yes' vendor='Intel' blockers='fma,pcid,x2apic,tsc-deadline,avx,f16c,avx2,invpcid,rdseed,avx512vbmi,avx512vbmi2,gfni,vaes,vpclmulqdq,avx512vnni,avx512bitalg,avx512-vpopcntdq,spec-ctrl,ssbd,3dnowprefetch,wbnoinvd,xsavec'>Icelake-Client-noTSX</model> <model usable='no' deprecated='yes' vendor='Intel' blockers='fma,pcid,x2apic,tsc-deadline,avx,f16c,hle,avx2,invpcid,rtm,rdseed,avx512vbmi,avx512vbmi2,gfni,vaes,vpclmulqdq,avx512vnni,avx512bitalg,avx512-vpopcntdq,spec-ctrl,ssbd,3dnowprefetch,wbnoinvd,xsavec'>Icelake-Client</model> <model usable='no' vendor='Intel' blockers='fma,pcid,x2apic,tsc-deadline,avx,f16c,avx2,invpcid,spec-ctrl'>Haswell-noTSX-IBRS</model> <model usable='no' vendor='Intel' blockers='fma,pcid,x2apic,tsc-deadline,avx,f16c,avx2,invpcid'>Haswell-noTSX</model> <model usable='no' vendor='Intel' blockers='fma,pcid,x2apic,tsc-deadline,avx,f16c,hle,avx2,invpcid,rtm,spec-ctrl'>Haswell-IBRS</model> <model usable='no' vendor='Intel' blockers='fma,pcid,x2apic,tsc-deadline,avx,f16c,hle,avx2,invpcid,rtm'>Haswell</model> <model usable='no' vendor='AMD' blockers='fma,avx,f16c,avx2,rdseed,sha-ni,rdpid,fxsr-opt,misalignsse,3dnowprefetch,osvw,topoext,perfctr-core,clzero,xsaveerptr,wbnoinvd,ibpb,amd-stibp,nrip-save,xsavec,xsaves'>EPYC-Rome</model> <model usable='no' vendor='AMD' blockers='fma,pcid,avx,f16c,avx2,invpcid,rdseed,sha-ni,rdpid,fsrm,fxsr-opt,misalignsse,3dnowprefetch,osvw,topoext,perfctr-core,clzero,xsaveerptr,wbnoinvd,ibpb,ibrs,amd-stibp,amd-ssbd,nrip-save,xsavec,xsaves'>EPYC-Milan</model> <model usable='no' vendor='AMD' blockers='fma,avx,f16c,avx2,rdseed,sha-ni,fxsr-opt,misalignsse,3dnowprefetch,osvw,topoext,ibpb,nrip-save,xsavec'>EPYC-IBPB</model> <model usable='no' vendor='AMD' blockers='fma,avx,f16c,avx2,rdseed,sha-ni,fxsr-opt,misalignsse,3dnowprefetch,osvw,topoext,nrip-save,xsavec'>EPYC</model> <model usable='no' vendor='Hygon' blockers='fma,avx,f16c,avx2,rdseed,fxsr-opt,misalignsse,3dnowprefetch,osvw,topoext,ibpb,nrip-save,xsavec'>Dhyana</model> <model usable='no' vendor='Intel' blockers='fma,pcid,x2apic,tsc-deadline,avx,f16c,hle,avx2,invpcid,rtm,avx512f,avx512dq,rdseed,avx512cd,avx512bw,avx512vl,avx512vnni,spec-ctrl,stibp,arch-capabilities,ssbd,avx512-bf16,3dnowprefetch,xsavec,rdctl-no,ibrs-all,skip-l1dfl-vmentry,mds-no,pschange-mc-no,taa-no'>Cooperlake</model> <model usable='yes' vendor='Intel'>Conroe</model> <model usable='no' vendor='Intel' blockers='fma,pcid,x2apic,tsc-deadline,avx,f16c,avx2,invpcid,avx512f,avx512dq,rdseed,avx512cd,avx512bw,avx512vl,avx512vnni,spec-ctrl,arch-capabilities,ssbd,3dnowprefetch,xsavec,rdctl-no,ibrs-all,skip-l1dfl-vmentry,mds-no'>Cascadelake-Server-noTSX</model> <model usable='no' vendor='Intel' blockers='fma,pcid,x2apic,tsc-deadline,avx,f16c,hle,avx2,invpcid,rtm,avx512f,avx512dq,rdseed,avx512cd,avx512bw,avx512vl,avx512vnni,spec-ctrl,ssbd,3dnowprefetch,xsavec'>Cascadelake-Server</model> <model usable='no' vendor='Intel' blockers='fma,pcid,x2apic,tsc-deadline,avx,f16c,avx2,invpcid,rdseed,spec-ctrl,3dnowprefetch'>Broadwell-noTSX-IBRS</model> <model usable='no' vendor='Intel' blockers='fma,pcid,x2apic,tsc-deadline,avx,f16c,avx2,invpcid,rdseed,3dnowprefetch'>Broadwell-noTSX</model> <model usable='no' vendor='Intel' blockers='fma,pcid,x2apic,tsc-deadline,avx,f16c,hle,avx2,invpcid,rtm,rdseed,spec-ctrl,3dnowprefetch'>Broadwell-IBRS</model> <model usable='no' vendor='Intel' blockers='fma,pcid,x2apic,tsc-deadline,avx,f16c,hle,avx2,invpcid,rtm,rdseed,3dnowprefetch'>Broadwell</model> <model usable='yes' vendor='unknown'>486</model> I think we need to expose this in a different way, using the CPU baseline APIs. THese already have a VIR_CPU_BASELINE_EXPAND_FEATURES flag. We should add a further VIR_CPU_BASELINE_BLOCKED_FEATURES flag to it. With regards, Daniel -- |: https://berrange.com -o- https://www.flickr.com/photos/dberrange :| |: https://libvirt.org -o- https://fstop138.berrange.com :| |: https://entangle-photo.org -o- https://www.instagram.com/dberrange :|

On Wed, Oct 05, 2022 at 09:07:55 +0100, Daniel P. Berrangé wrote:
On Tue, Oct 04, 2022 at 10:17:18PM +0200, Jiri Denemark wrote:
On Tue, Oct 04, 2022 at 07:35:31PM +0200, Jiri Denemark wrote:
On Tue, Oct 04, 2022 at 17:34:34 +0100, Daniel P. Berrangé wrote:
On Tue, Oct 04, 2022 at 04:28:53PM +0200, Jiri Denemark wrote:
We already show whether a specific CPU model is usable on the current host without modification via the 'usable' attribute of each CPU model. But it may be useful to actually see what features are blocking each CPU model from being usable. Especially when we already fetch the info from QEMU and propagating it to domain capabilities XML is all we need to do.
diff --git a/tests/domaincapsdata/qemu_4.2.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_4.2.0-q35.x86_64.xml index dab12e5888..8ca9e8d2b2 100644 --- a/tests/domaincapsdata/qemu_4.2.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_4.2.0-q35.x86_64.xml @@ -63,7 +63,7 @@ <mode name='custom' supported='yes'> <model usable='yes' vendor='unknown'>qemu64</model> <model usable='yes' vendor='unknown'>qemu32</model> - <model usable='no' vendor='AMD'>phenom</model> + <model usable='no' vendor='AMD' blockers='mmxext,fxsr_opt,3dnowext,3dnow,sse4a,npt'>phenom</model>
This is an XML design anti-pattern, because it invents a data format inside the attribute which the caller then has to further parse.
If we want to expose this, it needs to be with child elements IMHO, but yes it will be more much more verbose.
You're absolutely right, but that's the only option we have I'm afraid. Mixing subelements and text nodes is a much worse anti-pattern. I wish the model name was in an attribute, but it isn't and having
<model usable='no' vendor='AMD'> <blocker name='mmxext'/> phenom </model>
is just insane :-(
True, I wonder if there's a different approach to the overall problem that would be better.
Actually a third option just came to my mind. It's not ideal either, but at least it would be a proper XML :-)
<mode name='custom' supported='yes'> <model usable='yes' vendor='unknown'>qemu64</model> <model usable='no' vendor='AMD'>phenom</model> <blockers model='phenom'> <feature name='mmxext'/> <feature name='fxsr_opt'/> ... </blockers> <model ...>...</model> ... </mode>
Actually, looking atr this in practice, I don't think we should be including this information in domcapabilities at all. It gets waaaaaaaay too verbose, even with the custom syntax in this current patch impl. Take a look at this from one of my VMs, which uses the qemu64 model, and thus lacks a huge number of features: ... I think we need to expose this in a different way, using the CPU baseline APIs. THese already have a VIR_CPU_BASELINE_EXPAND_FEATURES flag. We should add a further VIR_CPU_BASELINE_BLOCKED_FEATURES flag to it.
Hmm, not a bad idea. And we don't even need a new flag, just a bit of documentation and a bug fix. When you pass just a simple <cpu> <arch>x86_64</arch> <model>EPYC</model> <vendor>AMD</vendor> </cpu> CPU definition to hypervisor-cpu-baseline, libvirt checks the host CPU model for features included in EPYC CPU model and disables those that are unavailable on the host: <cpu mode='custom' match='exact'> <model fallback='forbid'>EPYC</model> <vendor>AMD</vendor> <feature policy='disable' name='sha-ni'/> <feature policy='disable' name='mmxext'/> <feature policy='disable' name='cr8legacy'/> <feature policy='disable' name='sse4a'/> <feature policy='disable' name='misalignsse'/> <feature policy='disable' name='osvw'/> <feature policy='disable' name='monitor'/> </cpu> Although it does not exactly match the list of blockers from QEMU: sha-ni, mmxext, fxsr-opt, cr8legacy, sse4a, misalignsse, osvw. Libvirt disables some features which are not present in QEMU's blockers list (monitor), but this is fine as these features are included only in libvirt's EPYC and QEMU would not enable them anyway. Explicitly disabling them is a no-op for QEMU and helps pass libvirt internal checks. Seeing a non-empty list of disabled features for a CPU model marked as usable='yes' might just be a bit confusing. I guess just documenting this should be enough. On the other hand, the baseline CPU model does not disable some features QEMU would need to disable (fxsr-opt in the example above) because they are not included in the CPU model definition in libvirt. But this is a bug and I'm a bit surprised to see it as I believe I addressed this exact issue some time ago (although it's quite possible I'm just thinking about similar issue somewhere else). Jirka

Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- NEWS.rst | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/NEWS.rst b/NEWS.rst index 3049aa83f9..802d96d4ca 100644 --- a/NEWS.rst +++ b/NEWS.rst @@ -19,6 +19,17 @@ v8.9.0 (unreleased) * **Improvements** + * Add vendor attribute for CPU models in domain capabilities + + Users can now see the vendor of each CPU model in domain capabilities and + use it, e.g., for filtering usable CPU models based on host architecture. + + * Add blockers attribute for CPU models in domain capabilities + + In addition to reporting whether each CPU model is usable on the current + host domain capabilities XML now contains a list of features that block + usability of a particular CPU model. + * **Bug fixes** -- 2.37.3

On Tue, Oct 04, 2022 at 16:28:54 +0200, Jiri Denemark wrote:
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- NEWS.rst | 11 +++++++++++ 1 file changed, 11 insertions(+)
diff --git a/NEWS.rst b/NEWS.rst index 3049aa83f9..802d96d4ca 100644 --- a/NEWS.rst +++ b/NEWS.rst @@ -19,6 +19,17 @@ v8.9.0 (unreleased)
* **Improvements**
+ * Add vendor attribute for CPU models in domain capabilities + + Users can now see the vendor of each CPU model in domain capabilities and + use it, e.g., for filtering usable CPU models based on host architecture.
s/architecture/CPU vendor/ of course
+ + * Add blockers attribute for CPU models in domain capabilities + + In addition to reporting whether each CPU model is usable on the current + host domain capabilities XML now contains a list of features that block + usability of a particular CPU model. + * **Bug fixes**
Jirka

On a Tuesday in 2022, Jiri Denemark wrote:
See patches 04/11 and 10/11 for details.
Patches 4, 6, and 10 were truncated as they include a lot of boring changes in tests, complete patches are available in my gitlab repo:
git fetch git@gitlab.com:jirkade/libvirt.git domaincaps
Jiri Denemark (11): conf: virDomainCapsCPUModelsAdd never fails cpu_ppc64: Avoid repeated loading of CPU map qemu: Do not pass qemuCaps to virQEMUCapsCPUFeature{To,From}QEMU domain_capabilities: Add vendor attribute for CPU models Introduce virCPUGetVendorForModel and use it in QEMU driver cpu_x86: Implement virCPUGetVendorForModel cpu_ppc64: Implement virCPUGetVendorForModel cpu_arm: Don't implement virCPUGetVendorForModel qemu_capabilities: Translate CPU blockers domain_capabilities: Add blockers attribute for CPU models NEWS: Document domain capabilities improvements
NEWS.rst | 11 ++ docs/formatdomaincaps.rst | 20 ++- src/conf/domain_capabilities.c | 42 +++--
[...]
.../domaincapsdata/qemu_7.1.0-q35.x86_64.xml | 106 ++++++------- .../domaincapsdata/qemu_7.1.0-tcg.x86_64.xml | 106 ++++++------- tests/domaincapsdata/qemu_7.1.0.x86_64.xml | 106 ++++++------- 67 files changed, 2389 insertions(+), 2256 deletions(-)
Reviewed-by: Ján Tomko <jtomko@redhat.com> Jano
participants (3)
-
Daniel P. Berrangé
-
Jiri Denemark
-
Ján Tomko