QEMU has the ability to mark CPUs as deprecated. This should be exposed to management applications in the domain capabilities. This attribute is only set when the model is actually deprecated. Signed-off-by: Daniel P. Berrangé <berrange@xxxxxxxxxx> --- docs/formatdomaincaps.html.in | 10 ++++++---- docs/schemas/domaincaps.rng | 8 ++++++++ src/conf/domain_capabilities.c | 14 ++++++++++---- src/conf/domain_capabilities.h | 4 +++- src/qemu/qemu_capabilities.c | 10 +++++++++- src/qemu/qemu_monitor.c | 1 + src/qemu/qemu_monitor.h | 1 + src/qemu/qemu_monitor_json.c | 4 ++++ tests/cputest.c | 4 ++-- tests/domaincapsdata/qemu_5.2.0-q35.x86_64.xml | 4 ++-- tests/domaincapsdata/qemu_5.2.0-tcg.x86_64.xml | 4 ++-- tests/domaincapsdata/qemu_5.2.0.x86_64.xml | 4 ++-- tests/qemucapabilitiesdata/caps_5.2.0.x86_64.xml | 16 ++++++++-------- 13 files changed, 58 insertions(+), 26 deletions(-) diff --git a/docs/formatdomaincaps.html.in b/docs/formatdomaincaps.html.in index 65ab5574d3..8df88f5355 100644 --- a/docs/formatdomaincaps.html.in +++ b/docs/formatdomaincaps.html.in @@ -214,9 +214,9 @@ <feature policy='require' name='vmx'/> </mode> <mode name='custom' supported='yes'> - <model usable='no'>Broadwell</model> - <model usable='yes'>Broadwell-noTSX</model> - <model usable='no'>Haswell</model> + <model usable='no' deprecated='no'>Broadwell</model> + <model usable='yes' deprecated='no'>Broadwell-noTSX</model> + <model usable='no' deprecated='yes'>Haswell</model> ... </mode> </cpu> @@ -262,7 +262,9 @@ cannot be used without disabling some features that the CPU of such model is expected to have. A special value <code>unknown</code> indicates libvirt does not have enough information to provide the - usability data. + usability data. The <code>deprecated</code> attribute reflects + the hypervisor's policy on usage of this model + <span class="since">(since 7.1.0)</span>. </dd> </dl> diff --git a/docs/schemas/domaincaps.rng b/docs/schemas/domaincaps.rng index 0dbffb28ac..a57ef715c3 100644 --- a/docs/schemas/domaincaps.rng +++ b/docs/schemas/domaincaps.rng @@ -138,6 +138,14 @@ <value>unknown</value> </choice> </attribute> + <optional> + <attribute name="deprecated"> + <choice> + <value>yes</value> + <value>no</value> + </choice> + </attribute> + </optional> <text/> </element> </zeroOrMore> diff --git a/src/conf/domain_capabilities.c b/src/conf/domain_capabilities.c index 8130311590..cdb1b31af6 100644 --- a/src/conf/domain_capabilities.c +++ b/src/conf/domain_capabilities.c @@ -175,7 +175,8 @@ virDomainCapsCPUModelsCopy(virDomainCapsCPUModelsPtr old) if (virDomainCapsCPUModelsAdd(cpuModels, old->models[i].name, old->models[i].usable, - old->models[i].blockers) < 0) + old->models[i].blockers, + old->models[i].deprecated) < 0) goto error; } @@ -191,7 +192,8 @@ int virDomainCapsCPUModelsAdd(virDomainCapsCPUModelsPtr cpuModels, const char *name, virDomainCapsCPUUsable usable, - char **blockers) + char **blockers, + bool deprecated) { g_autofree char * nameCopy = NULL; virDomainCapsCPUModelPtr cpu; @@ -208,6 +210,7 @@ virDomainCapsCPUModelsAdd(virDomainCapsCPUModelsPtr cpuModels, cpu->usable = usable; cpu->name = g_steal_pointer(&nameCopy); cpu->blockers = g_strdupv(blockers); + cpu->deprecated = deprecated; return 0; } @@ -388,8 +391,11 @@ virDomainCapsCPUCustomFormat(virBufferPtr buf, for (i = 0; i < custom->nmodels; i++) { virDomainCapsCPUModelPtr model = custom->models + i; - virBufferAsprintf(buf, "<model usable='%s'>%s</model>\n", - virDomainCapsCPUUsableTypeToString(model->usable), + virBufferAsprintf(buf, "<model usable='%s'", + virDomainCapsCPUUsableTypeToString(model->usable)); + if (model->deprecated) + virBufferAddLit(buf, " deprecated='yes'"); + virBufferAsprintf(buf, ">%s</model>\n", model->name); } diff --git a/src/conf/domain_capabilities.h b/src/conf/domain_capabilities.h index b22d40abb2..f454780185 100644 --- a/src/conf/domain_capabilities.h +++ b/src/conf/domain_capabilities.h @@ -146,6 +146,7 @@ struct _virDomainCapsCPUModel { char *name; virDomainCapsCPUUsable usable; char **blockers; /* NULL-terminated list of usability blockers */ + bool deprecated; }; typedef struct _virDomainCapsCPUModels virDomainCapsCPUModels; @@ -228,7 +229,8 @@ virDomainCapsCPUModelsPtr virDomainCapsCPUModelsCopy(virDomainCapsCPUModelsPtr o int virDomainCapsCPUModelsAdd(virDomainCapsCPUModelsPtr cpuModels, const char *name, virDomainCapsCPUUsable usable, - char **blockers); + char **blockers, + bool deprecated); virDomainCapsCPUModelPtr virDomainCapsCPUModelsGet(virDomainCapsCPUModelsPtr cpuModels, const char *name); diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index d656732c3e..61467eb6c2 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -2176,7 +2176,7 @@ virQEMUCapsCPUDefsToModels(qemuMonitorCPUDefsPtr defs, continue; if (virDomainCapsCPUModelsAdd(cpuModels, cpu->name, cpu->usable, - cpu->blockers) < 0) + cpu->blockers, cpu->deprecated) < 0) return NULL; } @@ -3896,6 +3896,7 @@ virQEMUCapsLoadCPUModels(virQEMUCapsAccelPtr caps, int usable = VIR_DOMCAPS_CPU_USABLE_UNKNOWN; g_autofree char * strUsable = NULL; g_autofree xmlNodePtr * blockerNodes = NULL; + g_autofree char *deprecated = NULL; int nblockers; if ((strUsable = virXMLPropString(nodes[i], "usable")) && @@ -3940,6 +3941,11 @@ virQEMUCapsLoadCPUModels(virQEMUCapsAccelPtr caps, } } } + + deprecated = virXMLPropString(nodes[i], "deprecated"); + if (deprecated && + STREQ(deprecated, "yes")) + cpu->deprecated = true; } caps->cpuModels = g_steal_pointer(&defs); @@ -4448,6 +4454,8 @@ virQEMUCapsFormatCPUModels(virQEMUCapsAccelPtr caps, virBufferAsprintf(buf, " usable='%s'", virDomainCapsCPUUsableTypeToString(cpu->usable)); } + if (cpu->deprecated) + virBufferAddLit(buf, " deprecated='yes'"); if (cpu->blockers) { size_t j; diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index 09b8617097..990519252e 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -3673,6 +3673,7 @@ qemuMonitorCPUDefsCopy(qemuMonitorCPUDefsPtr src) cpuDst->name = g_strdup(cpuSrc->name); cpuDst->type = g_strdup(cpuSrc->type); cpuDst->blockers = g_strdupv(cpuSrc->blockers); + cpuDst->deprecated = cpuSrc->deprecated; } return g_steal_pointer(&defs); diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index a07617ec28..67f149ebde 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -1193,6 +1193,7 @@ struct _qemuMonitorCPUDefInfo { char *name; char *type; char **blockers; /* NULL-terminated string list */ + bool deprecated; }; typedef struct _qemuMonitorCPUDefs qemuMonitorCPUDefs; diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index 8a75a2734e..6534878d45 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -5896,6 +5896,10 @@ qemuMonitorJSONGetCPUDefinitions(qemuMonitorPtr mon, cpu->usable = VIR_DOMCAPS_CPU_USABLE_NO; } + + if (virJSONValueObjectHasKey(child, "deprecated") && + virJSONValueObjectGetBoolean(child, "deprecated", &cpu->deprecated) < 0) + return -1; } *cpuDefs = g_steal_pointer(&defs); diff --git a/tests/cputest.c b/tests/cputest.c index 4c75ee535f..593861dfe9 100644 --- a/tests/cputest.c +++ b/tests/cputest.c @@ -846,7 +846,7 @@ cpuTestUpdateLive(const void *arg) } if (virDomainCapsCPUModelsAdd(models, expected->model, - usable, blockers) < 0) + usable, blockers, false) < 0) goto cleanup; cpu->fallback = VIR_CPU_FALLBACK_ALLOW; @@ -953,7 +953,7 @@ cpuTestInitModels(const char **list) for (model = list; *model; model++) { if (virDomainCapsCPUModelsAdd(cpus, *model, - VIR_DOMCAPS_CPU_USABLE_UNKNOWN, NULL) < 0) + VIR_DOMCAPS_CPU_USABLE_UNKNOWN, NULL, false) < 0) goto error; } diff --git a/tests/domaincapsdata/qemu_5.2.0-q35.x86_64.xml b/tests/domaincapsdata/qemu_5.2.0-q35.x86_64.xml index 7111bdf2c5..5a5232751d 100644 --- a/tests/domaincapsdata/qemu_5.2.0-q35.x86_64.xml +++ b/tests/domaincapsdata/qemu_5.2.0-q35.x86_64.xml @@ -91,8 +91,8 @@ <model usable='no'>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='no' deprecated='yes'>Icelake-Client-noTSX</model> + <model usable='no' deprecated='yes'>Icelake-Client</model> <model usable='no'>Haswell-noTSX-IBRS</model> <model usable='no'>Haswell-noTSX</model> <model usable='no'>Haswell-IBRS</model> diff --git a/tests/domaincapsdata/qemu_5.2.0-tcg.x86_64.xml b/tests/domaincapsdata/qemu_5.2.0-tcg.x86_64.xml index 9d2e870b1c..63546dc0a5 100644 --- a/tests/domaincapsdata/qemu_5.2.0-tcg.x86_64.xml +++ b/tests/domaincapsdata/qemu_5.2.0-tcg.x86_64.xml @@ -96,8 +96,8 @@ <model usable='no'>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='no' deprecated='yes'>Icelake-Client-noTSX</model> + <model usable='no' deprecated='yes'>Icelake-Client</model> <model usable='no'>Haswell-noTSX-IBRS</model> <model usable='no'>Haswell-noTSX</model> <model usable='no'>Haswell-IBRS</model> diff --git a/tests/domaincapsdata/qemu_5.2.0.x86_64.xml b/tests/domaincapsdata/qemu_5.2.0.x86_64.xml index d8113c4e92..efc21244b3 100644 --- a/tests/domaincapsdata/qemu_5.2.0.x86_64.xml +++ b/tests/domaincapsdata/qemu_5.2.0.x86_64.xml @@ -90,8 +90,8 @@ <model usable='no'>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='no' deprecated='yes'>Icelake-Client-noTSX</model> + <model usable='no' deprecated='yes'>Icelake-Client</model> <model usable='no'>Haswell-noTSX-IBRS</model> <model usable='no'>Haswell-noTSX</model> <model usable='no'>Haswell-IBRS</model> diff --git a/tests/qemucapabilitiesdata/caps_5.2.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_5.2.0.x86_64.xml index dea2ff4b54..7f15bcda09 100644 --- a/tests/qemucapabilitiesdata/caps_5.2.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_5.2.0.x86_64.xml @@ -1055,7 +1055,7 @@ <blocker name='avx512f'/> <blocker name='pku'/> </cpu> - <cpu type='kvm' name='Icelake-Client-v2' typename='Icelake-Client-v2-x86_64-cpu' usable='no'> + <cpu type='kvm' name='Icelake-Client-v2' typename='Icelake-Client-v2-x86_64-cpu' usable='no' deprecated='yes'> <blocker name='pcid'/> <blocker name='erms'/> <blocker name='invpcid'/> @@ -1071,7 +1071,7 @@ <blocker name='spec-ctrl'/> <blocker name='pku'/> </cpu> - <cpu type='kvm' name='Icelake-Client-v1' typename='Icelake-Client-v1-x86_64-cpu' usable='no'> + <cpu type='kvm' name='Icelake-Client-v1' typename='Icelake-Client-v1-x86_64-cpu' usable='no' deprecated='yes'> <blocker name='pcid'/> <blocker name='hle'/> <blocker name='erms'/> @@ -1089,7 +1089,7 @@ <blocker name='spec-ctrl'/> <blocker name='pku'/> </cpu> - <cpu type='kvm' name='Icelake-Client-noTSX' typename='Icelake-Client-noTSX-x86_64-cpu' usable='no'> + <cpu type='kvm' name='Icelake-Client-noTSX' typename='Icelake-Client-noTSX-x86_64-cpu' usable='no' deprecated='yes'> <blocker name='pcid'/> <blocker name='erms'/> <blocker name='invpcid'/> @@ -1105,7 +1105,7 @@ <blocker name='spec-ctrl'/> <blocker name='pku'/> </cpu> - <cpu type='kvm' name='Icelake-Client' typename='Icelake-Client-x86_64-cpu' usable='no'> + <cpu type='kvm' name='Icelake-Client' typename='Icelake-Client-x86_64-cpu' usable='no' deprecated='yes'> <blocker name='pcid'/> <blocker name='hle'/> <blocker name='erms'/> @@ -2429,7 +2429,7 @@ <blocker name='wbnoinvd'/> <blocker name='xsavec'/> </cpu> - <cpu type='tcg' name='Icelake-Client-v2' typename='Icelake-Client-v2-x86_64-cpu' usable='no'> + <cpu type='tcg' name='Icelake-Client-v2' typename='Icelake-Client-v2-x86_64-cpu' usable='no' deprecated='yes'> <blocker name='fma'/> <blocker name='pcid'/> <blocker name='x2apic'/> @@ -2454,7 +2454,7 @@ <blocker name='wbnoinvd'/> <blocker name='xsavec'/> </cpu> - <cpu type='tcg' name='Icelake-Client-v1' typename='Icelake-Client-v1-x86_64-cpu' usable='no'> + <cpu type='tcg' name='Icelake-Client-v1' typename='Icelake-Client-v1-x86_64-cpu' usable='no' deprecated='yes'> <blocker name='fma'/> <blocker name='pcid'/> <blocker name='x2apic'/> @@ -2481,7 +2481,7 @@ <blocker name='wbnoinvd'/> <blocker name='xsavec'/> </cpu> - <cpu type='tcg' name='Icelake-Client-noTSX' typename='Icelake-Client-noTSX-x86_64-cpu' usable='no'> + <cpu type='tcg' name='Icelake-Client-noTSX' typename='Icelake-Client-noTSX-x86_64-cpu' usable='no' deprecated='yes'> <blocker name='fma'/> <blocker name='pcid'/> <blocker name='x2apic'/> @@ -2506,7 +2506,7 @@ <blocker name='wbnoinvd'/> <blocker name='xsavec'/> </cpu> - <cpu type='tcg' name='Icelake-Client' typename='Icelake-Client-x86_64-cpu' usable='no'> + <cpu type='tcg' name='Icelake-Client' typename='Icelake-Client-x86_64-cpu' usable='no' deprecated='yes'> <blocker name='fma'/> <blocker name='pcid'/> <blocker name='x2apic'/> -- 2.29.2