[libvirt] [PATCH 00/23] Fix host-model if the chosen CPU model has more features in QEMU compared to our cpu_map.xml

When decoding CPUID data to virCPUDef we need to be careful about using a CPU model which cannot be directly used on the current host. Normally, libvirt would notice the features which prevent the model from being usable and it would disable them in the computed virCPUDef, but this won't work in case the definition of the CPU model in QEMU contains more features than what we have in cpu_map.xml. We need to count with the usability blockers we got from QEMU and explicitly disable all of them to make the computed virCPUDef usable. https://bugzilla.redhat.com/show_bug.cgi?id=1464832 Jiri Denemark (23): util: Introduce virStringListCopy conf: Add usability blockers to virDomainCapsCPUModel qemu: Store CPU usability blockers in caps cache qemu: Parse unavailable features for CPU models cpu: Use virDomainCapsCPUModelsPtr in cpu driver APIs cpu: Drop unused parameter from cpuDecode cpu: Return model from virCPUModelIsAllowed cpu_x86: Move x86FeatureFind* to avoid forward prototypes cpu_x86: Disable blockers from unusable CPU models cputest: Replace json bool with enum cputest: Avoid calling json_reformat in cpu-parse.sh cputest: Print correct feature in virCPUUpdateLive test cputest: Test CPU usability blockers cputest: Separate QEMUCaps creation from cpuTestCPUIDJson build: Export virCPUModelIsAllowed private API cputest: Use CPU models from QEMU when available cputest: Add query-cpu-definitions reply for Core-i5-2540M cputest: Add CPUID data for Intel(R) Xeon(R) CPU E7-4830 cputest: Add query-cpu-definitions reply for Xeon-E7-4830 cputest: Update Xeon-E3-1245 data cputest: Add query-cpu-definitions reply for Xeon-E3-1245 cputest: Update Core-i7-2600 data cputest: Make a crippled version of Core-i7-2600 src/conf/domain_capabilities.c | 30 +- src/conf/domain_capabilities.h | 7 +- src/cpu/cpu.c | 95 +- src/cpu/cpu.h | 31 +- src/cpu/cpu_arm.c | 3 +- src/cpu/cpu_ppc64.c | 14 +- src/cpu/cpu_x86.c | 108 +- src/libvirt_private.syms | 1 + src/libxl/libxl_capabilities.c | 2 +- src/libxl/libxl_driver.c | 2 +- src/qemu/qemu_capabilities.c | 123 +-- src/qemu/qemu_capabilities.h | 6 +- src/qemu/qemu_capspriv.h | 5 + src/qemu/qemu_driver.c | 2 +- src/qemu/qemu_monitor.c | 2 + src/qemu/qemu_monitor.h | 1 + src/qemu/qemu_monitor_json.c | 26 +- src/qemu/qemu_process.c | 9 +- src/test/test_driver.c | 2 +- src/util/virstring.c | 37 + src/util/virstring.h | 3 + tests/cputest.c | 324 ++++-- tests/cputestdata/cpu-cpuid.py | 26 +- tests/cputestdata/cpu-gather.sh | 1 + tests/cputestdata/cpu-parse.sh | 2 +- tests/cputestdata/cpu-reformat.py | 9 + tests/cputestdata/x86_64-cpuid-Core-i5-2540M.json | 362 +++++++ .../x86_64-cpuid-Core-i7-2600-disabled.xml | 1 - .../x86_64-cpuid-Core-i7-2600-enabled.xml | 1 + .../cputestdata/x86_64-cpuid-Core-i7-2600-json.xml | 1 + ...x86_64-cpuid-Core-i7-2600-xsaveopt-disabled.xml | 6 + .../x86_64-cpuid-Core-i7-2600-xsaveopt-enabled.xml | 8 + .../x86_64-cpuid-Core-i7-2600-xsaveopt-guest.xml | 25 + .../x86_64-cpuid-Core-i7-2600-xsaveopt-host.xml | 25 + .../x86_64-cpuid-Core-i7-2600-xsaveopt-json.xml | 11 + .../x86_64-cpuid-Core-i7-2600-xsaveopt.json | 615 +++++++++++ .../x86_64-cpuid-Core-i7-2600-xsaveopt.xml | 33 + tests/cputestdata/x86_64-cpuid-Core-i7-2600.json | 496 ++++++++- tests/cputestdata/x86_64-cpuid-Core-i7-2600.xml | 6 +- .../x86_64-cpuid-Xeon-E3-1245-disabled.xml | 1 - .../x86_64-cpuid-Xeon-E3-1245-enabled.xml | 2 +- .../cputestdata/x86_64-cpuid-Xeon-E3-1245-json.xml | 1 + tests/cputestdata/x86_64-cpuid-Xeon-E3-1245.json | 712 +++++++++---- tests/cputestdata/x86_64-cpuid-Xeon-E3-1245.xml | 7 +- .../x86_64-cpuid-Xeon-E7-4830-disabled.xml | 5 + .../x86_64-cpuid-Xeon-E7-4830-enabled.xml | 8 + .../x86_64-cpuid-Xeon-E7-4830-guest.xml | 28 + .../cputestdata/x86_64-cpuid-Xeon-E7-4830-host.xml | 29 + .../cputestdata/x86_64-cpuid-Xeon-E7-4830-json.xml | 14 + tests/cputestdata/x86_64-cpuid-Xeon-E7-4830.json | 657 ++++++++++++ tests/cputestdata/x86_64-cpuid-Xeon-E7-4830.xml | 30 + tests/domaincapstest.c | 6 +- tests/qemucapabilitiesdata/caps_2.10.0.s390x.xml | 1102 ++++++++++++++++++-- tests/qemucapabilitiesdata/caps_2.10.0.x86_64.xml | 236 ++++- tests/qemucapabilitiesdata/caps_2.8.0.x86_64.xml | 154 ++- tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml | 154 ++- 56 files changed, 4927 insertions(+), 680 deletions(-) create mode 100755 tests/cputestdata/cpu-reformat.py create mode 100644 tests/cputestdata/x86_64-cpuid-Core-i7-2600-xsaveopt-disabled.xml create mode 100644 tests/cputestdata/x86_64-cpuid-Core-i7-2600-xsaveopt-enabled.xml create mode 100644 tests/cputestdata/x86_64-cpuid-Core-i7-2600-xsaveopt-guest.xml create mode 100644 tests/cputestdata/x86_64-cpuid-Core-i7-2600-xsaveopt-host.xml create mode 100644 tests/cputestdata/x86_64-cpuid-Core-i7-2600-xsaveopt-json.xml create mode 100644 tests/cputestdata/x86_64-cpuid-Core-i7-2600-xsaveopt.json create mode 100644 tests/cputestdata/x86_64-cpuid-Core-i7-2600-xsaveopt.xml create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-E7-4830-disabled.xml create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-E7-4830-enabled.xml create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-E7-4830-guest.xml create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-E7-4830-host.xml create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-E7-4830-json.xml create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-E7-4830.json create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-E7-4830.xml -- 2.14.2

The API makes a deep copy of a NULL-terminated string list. Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/util/virstring.c | 37 +++++++++++++++++++++++++++++++++++++ src/util/virstring.h | 3 +++ 2 files changed, 40 insertions(+) diff --git a/src/util/virstring.c b/src/util/virstring.c index 0288d1e677..820b282ac5 100644 --- a/src/util/virstring.c +++ b/src/util/virstring.c @@ -239,6 +239,43 @@ virStringListRemove(char ***strings, } +/** + * virStringListCopy: + * @dst: where to store the copy of @strings + * @src: a NULL-terminated array of strings + * + * Makes a deep copy of the @src string list and stores it in @dst. Callers + * are responsible for freeing both @dst and @src. + * + * Returns 0 on success, -1 on error. + */ +int +virStringListCopy(char ***dst, + const char **src) +{ + char **copy = NULL; + size_t i; + + if (!src) + return 0; + + if (VIR_ALLOC_N(copy, virStringListLength(src) + 1) < 0) + goto error; + + for (i = 0; src[i]; i++) { + if (VIR_STRDUP(copy[i], src[i]) < 0) + goto error; + } + + *dst = copy; + return 0; + + error: + virStringListFree(copy); + return -1; +} + + /** * virStringListFree: * @str_array: a NULL-terminated array of strings to free diff --git a/src/util/virstring.h b/src/util/virstring.h index 1290fcce15..cfd91be314 100644 --- a/src/util/virstring.h +++ b/src/util/virstring.h @@ -46,6 +46,9 @@ char **virStringListAdd(const char **strings, void virStringListRemove(char ***strings, const char *item); +int virStringListCopy(char ***dst, + const char **src); + void virStringListFree(char **strings); void virStringListFreeCount(char **strings, size_t count); -- 2.14.2

On 10/04/2017 10:58 AM, Jiri Denemark wrote:
The API makes a deep copy of a NULL-terminated string list.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/util/virstring.c | 37 +++++++++++++++++++++++++++++++++++++ src/util/virstring.h | 3 +++ 2 files changed, 40 insertions(+)
diff --git a/src/util/virstring.c b/src/util/virstring.c index 0288d1e677..820b282ac5 100644 --- a/src/util/virstring.c +++ b/src/util/virstring.c @@ -239,6 +239,43 @@ virStringListRemove(char ***strings, }
+/** + * virStringListCopy: + * @dst: where to store the copy of @strings + * @src: a NULL-terminated array of strings + * + * Makes a deep copy of the @src string list and stores it in @dst. Callers + * are responsible for freeing both @dst and @src. + * + * Returns 0 on success, -1 on error. + */ +int +virStringListCopy(char ***dst, + const char **src) +{
I think it would make more sense to have this return @copy (or call it @dst, doesn't matter) rather than 0, -1 which only means @dst wasn't populated. There's only 1 consumer (in patch 2)... w/ the return of char** similar to other vir*Copy's and even virStringListAdd... Reviewed-by: John Ferlan <jferlan@redhat.com> John Ironically virStringListAdd does essentially the same thing if you pass @item==NULL since VIR_STRDUP(x, NULL) just sets x to NULL... Of course the other difference is that @dst in the *Add case could be an array of NULL string entries.
+ char **copy = NULL; + size_t i; + + if (!src) + return 0; + + if (VIR_ALLOC_N(copy, virStringListLength(src) + 1) < 0)> + goto error; + + for (i = 0; src[i]; i++) { + if (VIR_STRDUP(copy[i], src[i]) < 0) + goto error; + } + + *dst = copy; + return 0; + + error: + virStringListFree(copy); + return -1; +} + + /** * virStringListFree: * @str_array: a NULL-terminated array of strings to free diff --git a/src/util/virstring.h b/src/util/virstring.h index 1290fcce15..cfd91be314 100644 --- a/src/util/virstring.h +++ b/src/util/virstring.h @@ -46,6 +46,9 @@ char **virStringListAdd(const char **strings, void virStringListRemove(char ***strings, const char *item);
+int virStringListCopy(char ***dst, + const char **src); + void virStringListFree(char **strings); void virStringListFreeCount(char **strings, size_t count);

On Thu, Oct 12, 2017 at 07:22:51 -0400, John Ferlan wrote:
On 10/04/2017 10:58 AM, Jiri Denemark wrote:
The API makes a deep copy of a NULL-terminated string list.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/util/virstring.c | 37 +++++++++++++++++++++++++++++++++++++ src/util/virstring.h | 3 +++ 2 files changed, 40 insertions(+)
diff --git a/src/util/virstring.c b/src/util/virstring.c index 0288d1e677..820b282ac5 100644 --- a/src/util/virstring.c +++ b/src/util/virstring.c @@ -239,6 +239,43 @@ virStringListRemove(char ***strings, }
+/** + * virStringListCopy: + * @dst: where to store the copy of @strings + * @src: a NULL-terminated array of strings + * + * Makes a deep copy of the @src string list and stores it in @dst. Callers + * are responsible for freeing both @dst and @src. + * + * Returns 0 on success, -1 on error. + */ +int +virStringListCopy(char ***dst, + const char **src) +{
I think it would make more sense to have this return @copy (or call it @dst, doesn't matter) rather than 0, -1 which only means @dst wasn't populated. There's only 1 consumer (in patch 2)...
Returning the pointer rather than int makes it impossible to allow NULL input since returning NULL would mean something failed. This is similar to VIR_STRDUP and several others. Jirka

On 10/13/2017 09:27 AM, Jiri Denemark wrote:
On Thu, Oct 12, 2017 at 07:22:51 -0400, John Ferlan wrote:
On 10/04/2017 10:58 AM, Jiri Denemark wrote:
The API makes a deep copy of a NULL-terminated string list.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/util/virstring.c | 37 +++++++++++++++++++++++++++++++++++++ src/util/virstring.h | 3 +++ 2 files changed, 40 insertions(+)
diff --git a/src/util/virstring.c b/src/util/virstring.c index 0288d1e677..820b282ac5 100644 --- a/src/util/virstring.c +++ b/src/util/virstring.c @@ -239,6 +239,43 @@ virStringListRemove(char ***strings, }
+/** + * virStringListCopy: + * @dst: where to store the copy of @strings + * @src: a NULL-terminated array of strings + * + * Makes a deep copy of the @src string list and stores it in @dst. Callers + * are responsible for freeing both @dst and @src. + * + * Returns 0 on success, -1 on error. + */ +int +virStringListCopy(char ***dst, + const char **src) +{
I think it would make more sense to have this return @copy (or call it @dst, doesn't matter) rather than 0, -1 which only means @dst wasn't populated. There's only 1 consumer (in patch 2)...
Returning the pointer rather than int makes it impossible to allow NULL input since returning NULL would mean something failed. This is similar to VIR_STRDUP and several others.
Jirka
However, if !src, then you're returning 0 and @dst is not changed and the caller *still* needs to check it. While this works for what you have there's also other examples where callers will do: if (blockers && !blockersCopy = virStringListCopy(blockers)) goto error; What you have works for your implementation mostly because virDomainCapsCPUModelsAddSteal allows/checks for a NULL 4th parameter and you initialize blockersCopy = NULL. But future eventual other callers would have to check the returned value for 0 and the returned @dst parameter anyway before using it. Because your check is hidden deeper in another call someone mimicing your code sequence may not realize that a NULL input @src would return an indeterminate @dst result. Obviously my preference is for return @dst, but I'm OK with what you've done as long you modify the comments to indicate it's up to the caller to validate @dst. Furthermore, since @src is a (const char **) input value, no sense in telling the caller they must free it... Finally, I think there should be a "if (dst) *dst = NULL", prior to "if (!src)" - at least that avoids one more ambiguity. IDC - either way, I trust that you can handle either option appropriately for my R-B. John

On Fri, Oct 13, 2017 at 14:14:37 -0400, John Ferlan wrote:
On 10/13/2017 09:27 AM, Jiri Denemark wrote:
On Thu, Oct 12, 2017 at 07:22:51 -0400, John Ferlan wrote:
On 10/04/2017 10:58 AM, Jiri Denemark wrote:
The API makes a deep copy of a NULL-terminated string list.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/util/virstring.c | 37 +++++++++++++++++++++++++++++++++++++ src/util/virstring.h | 3 +++ 2 files changed, 40 insertions(+)
diff --git a/src/util/virstring.c b/src/util/virstring.c index 0288d1e677..820b282ac5 100644 --- a/src/util/virstring.c +++ b/src/util/virstring.c @@ -239,6 +239,43 @@ virStringListRemove(char ***strings, }
+/** + * virStringListCopy: + * @dst: where to store the copy of @strings + * @src: a NULL-terminated array of strings + * + * Makes a deep copy of the @src string list and stores it in @dst. Callers + * are responsible for freeing both @dst and @src. + * + * Returns 0 on success, -1 on error. + */ +int +virStringListCopy(char ***dst, + const char **src) +{
I think it would make more sense to have this return @copy (or call it @dst, doesn't matter) rather than 0, -1 which only means @dst wasn't populated. There's only 1 consumer (in patch 2)...
Returning the pointer rather than int makes it impossible to allow NULL input since returning NULL would mean something failed. This is similar to VIR_STRDUP and several others.
Jirka
However, if !src, then you're returning 0 and @dst is not changed and the caller *still* needs to check it. While this works for what you have there's also other examples where callers will do:
if (blockers && !blockersCopy = virStringListCopy(blockers)) goto error;
Yeah, that's what returning a pointer would require, but when the function returns int, it's just if (virStringListCopy(©, blockers) < 0) goto error; If blockers are supposed to be non-NULL, the caller would need a separate check for it (possibly returning an error) in both cases.
Obviously my preference is for return @dst, but I'm OK with what you've done as long you modify the comments to indicate it's up to the caller to validate @dst.
No, there's no need to validate @dst at all. The caller may validate @src if it requires it to be non-NULL.
Furthermore, since @src is a (const char **) input value, no sense in telling the caller they must free it...
OK
Finally, I think there should be a "if (dst) *dst = NULL", prior to "if (!src)" - at least that avoids one more ambiguity.
Yeah, this part is obviously missing there. Jirka

When a hypervisor marks a CPU model as unusable on the current host, it may also give us a list of features which prevent the model from being usable. Storing this list in virDomainCapsCPUModel will help the CPU driver with creating a host-model CPU configuration. Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/conf/domain_capabilities.c | 30 ++++++++++++++++++++++-------- src/conf/domain_capabilities.h | 7 +++++-- src/qemu/qemu_capabilities.c | 11 ++++++----- tests/domaincapstest.c | 6 +++--- 4 files changed, 36 insertions(+), 18 deletions(-) diff --git a/src/conf/domain_capabilities.c b/src/conf/domain_capabilities.c index f62038b96c..be34576204 100644 --- a/src/conf/domain_capabilities.c +++ b/src/conf/domain_capabilities.c @@ -163,7 +163,8 @@ virDomainCapsCPUModelsCopy(virDomainCapsCPUModelsPtr old) for (i = 0; i < old->nmodels; i++) { if (virDomainCapsCPUModelsAdd(cpuModels, old->models[i].name, -1, - old->models[i].usable) < 0) + old->models[i].usable, + old->models[i].blockers) < 0) goto error; } @@ -195,7 +196,8 @@ virDomainCapsCPUModelsFilter(virDomainCapsCPUModelsPtr old, if (virDomainCapsCPUModelsAdd(cpuModels, old->models[i].name, -1, - old->models[i].usable) < 0) + old->models[i].usable, + old->models[i].blockers) < 0) goto error; } @@ -210,7 +212,8 @@ virDomainCapsCPUModelsFilter(virDomainCapsCPUModelsPtr old, int virDomainCapsCPUModelsAddSteal(virDomainCapsCPUModelsPtr cpuModels, char **name, - virDomainCapsCPUUsable usable) + virDomainCapsCPUUsable usable, + char ***blockers) { if (VIR_RESIZE_N(cpuModels->models, cpuModels->nmodels_max, cpuModels->nmodels, 1) < 0) @@ -218,6 +221,10 @@ virDomainCapsCPUModelsAddSteal(virDomainCapsCPUModelsPtr cpuModels, cpuModels->models[cpuModels->nmodels].usable = usable; VIR_STEAL_PTR(cpuModels->models[cpuModels->nmodels].name, *name); + + if (blockers) + VIR_STEAL_PTR(cpuModels->models[cpuModels->nmodels].blockers, *blockers); + cpuModels->nmodels++; return 0; } @@ -227,20 +234,27 @@ int virDomainCapsCPUModelsAdd(virDomainCapsCPUModelsPtr cpuModels, const char *name, ssize_t nameLen, - virDomainCapsCPUUsable usable) + virDomainCapsCPUUsable usable, + char **blockers) { - char *copy = NULL; + char *nameCopy = NULL; + char **blockersCopy = NULL; - if (VIR_STRNDUP(copy, name, nameLen) < 0) + if (VIR_STRNDUP(nameCopy, name, nameLen) < 0) goto error; - if (virDomainCapsCPUModelsAddSteal(cpuModels, ©, usable) < 0) + if (virStringListCopy(&blockersCopy, (const char **)blockers) < 0) + goto error; + + if (virDomainCapsCPUModelsAddSteal(cpuModels, &nameCopy, + usable, &blockersCopy) < 0) goto error; return 0; error: - VIR_FREE(copy); + VIR_FREE(nameCopy); + virStringListFree(blockersCopy); return -1; } diff --git a/src/conf/domain_capabilities.h b/src/conf/domain_capabilities.h index 82183c4524..8c71dec21e 100644 --- a/src/conf/domain_capabilities.h +++ b/src/conf/domain_capabilities.h @@ -116,6 +116,7 @@ typedef virDomainCapsCPUModel *virDomainCapsCPUModelPtr; struct _virDomainCapsCPUModel { char *name; virDomainCapsCPUUsable usable; + char **blockers; /* NULL-terminated list of usability blockers */ }; typedef struct _virDomainCapsCPUModels virDomainCapsCPUModels; @@ -171,11 +172,13 @@ virDomainCapsCPUModelsPtr virDomainCapsCPUModelsFilter(virDomainCapsCPUModelsPtr const char **blacklist); int virDomainCapsCPUModelsAddSteal(virDomainCapsCPUModelsPtr cpuModels, char **name, - virDomainCapsCPUUsable usable); + virDomainCapsCPUUsable usable, + char ***blockers); int virDomainCapsCPUModelsAdd(virDomainCapsCPUModelsPtr cpuModels, const char *name, ssize_t nameLen, - virDomainCapsCPUUsable usable); + virDomainCapsCPUUsable usable, + char **blockers); # define VIR_DOMAIN_CAPS_ENUM_SET(capsEnum, ...) \ do { \ diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 085910dd4d..b20dd6ec32 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -795,7 +795,7 @@ virQEMUCapsParseX86Models(const char *output, } if (virDomainCapsCPUModelsAdd(cpus, p, len, - VIR_DOMCAPS_CPU_USABLE_UNKNOWN) < 0) + VIR_DOMCAPS_CPU_USABLE_UNKNOWN, NULL) < 0) goto error; } while ((p = next)); @@ -853,7 +853,7 @@ virQEMUCapsParsePPCModels(const char *output, continue; if (virDomainCapsCPUModelsAdd(cpus, p, t - p - 1, - VIR_DOMCAPS_CPU_USABLE_UNKNOWN) < 0) + VIR_DOMCAPS_CPU_USABLE_UNKNOWN, NULL) < 0) goto error; } while ((p = next)); @@ -2524,7 +2524,7 @@ virQEMUCapsAddCPUDefinitions(virQEMUCapsPtr qemuCaps, } for (i = 0; i < count; i++) { - if (virDomainCapsCPUModelsAdd(cpus, name[i], -1, usable) < 0) + if (virDomainCapsCPUModelsAdd(cpus, name[i], -1, usable, NULL) < 0) return -1; } @@ -3005,7 +3005,8 @@ virQEMUCapsProbeQMPCPUDefinitions(virQEMUCapsPtr qemuCaps, else if (cpus[i]->usable == VIR_TRISTATE_BOOL_NO) usable = VIR_DOMCAPS_CPU_USABLE_NO; - if (virDomainCapsCPUModelsAddSteal(models, &cpus[i]->name, usable) < 0) + if (virDomainCapsCPUModelsAddSteal(models, &cpus[i]->name, usable, + NULL) < 0) goto cleanup; } @@ -3768,7 +3769,7 @@ virQEMUCapsLoadCPUModels(virQEMUCapsPtr qemuCaps, goto cleanup; } - if (virDomainCapsCPUModelsAddSteal(cpus, &str, usable) < 0) + if (virDomainCapsCPUModelsAddSteal(cpus, &str, usable, NULL) < 0) goto cleanup; } diff --git a/tests/domaincapstest.c b/tests/domaincapstest.c index 2719473244..7aeac4507f 100644 --- a/tests/domaincapstest.c +++ b/tests/domaincapstest.c @@ -88,11 +88,11 @@ fillAllCaps(virDomainCapsPtr domCaps) cpu->hostModel = virCPUDefCopy(&host); if (!(cpu->custom = virDomainCapsCPUModelsNew(3)) || virDomainCapsCPUModelsAdd(cpu->custom, "Model1", -1, - VIR_DOMCAPS_CPU_USABLE_UNKNOWN) < 0 || + VIR_DOMCAPS_CPU_USABLE_UNKNOWN, NULL) < 0 || virDomainCapsCPUModelsAdd(cpu->custom, "Model2", -1, - VIR_DOMCAPS_CPU_USABLE_NO) < 0 || + VIR_DOMCAPS_CPU_USABLE_NO, NULL) < 0 || virDomainCapsCPUModelsAdd(cpu->custom, "Model3", -1, - VIR_DOMCAPS_CPU_USABLE_YES) < 0) + VIR_DOMCAPS_CPU_USABLE_YES, NULL) < 0) return -1; disk->supported = true; -- 2.14.2

On 10/04/2017 10:58 AM, Jiri Denemark wrote:
When a hypervisor marks a CPU model as unusable on the current host, it may also give us a list of features which prevent the model from being usable. Storing this list in virDomainCapsCPUModel will help the CPU driver with creating a host-model CPU configuration.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/conf/domain_capabilities.c | 30 ++++++++++++++++++++++-------- src/conf/domain_capabilities.h | 7 +++++-- src/qemu/qemu_capabilities.c | 11 ++++++----- tests/domaincapstest.c | 6 +++--- 4 files changed, 36 insertions(+), 18 deletions(-)
diff --git a/src/conf/domain_capabilities.c b/src/conf/domain_capabilities.c index f62038b96c..be34576204 100644 --- a/src/conf/domain_capabilities.c +++ b/src/conf/domain_capabilities.c @@ -163,7 +163,8 @@ virDomainCapsCPUModelsCopy(virDomainCapsCPUModelsPtr old) for (i = 0; i < old->nmodels; i++) { if (virDomainCapsCPUModelsAdd(cpuModels, old->models[i].name, -1, - old->models[i].usable) < 0) + old->models[i].usable, + old->models[i].blockers) < 0) goto error; }
@@ -195,7 +196,8 @@ virDomainCapsCPUModelsFilter(virDomainCapsCPUModelsPtr old,
if (virDomainCapsCPUModelsAdd(cpuModels, old->models[i].name, -1, - old->models[i].usable) < 0) + old->models[i].usable, + old->models[i].blockers) < 0) goto error; }
@@ -210,7 +212,8 @@ virDomainCapsCPUModelsFilter(virDomainCapsCPUModelsPtr old, int virDomainCapsCPUModelsAddSteal(virDomainCapsCPUModelsPtr cpuModels, char **name, - virDomainCapsCPUUsable usable) + virDomainCapsCPUUsable usable, + char ***blockers) { if (VIR_RESIZE_N(cpuModels->models, cpuModels->nmodels_max, cpuModels->nmodels, 1) < 0) @@ -218,6 +221,10 @@ virDomainCapsCPUModelsAddSteal(virDomainCapsCPUModelsPtr cpuModels,
cpuModels->models[cpuModels->nmodels].usable = usable; VIR_STEAL_PTR(cpuModels->models[cpuModels->nmodels].name, *name); + + if (blockers) + VIR_STEAL_PTR(cpuModels->models[cpuModels->nmodels].blockers, *blockers); +
So @name is required and @blockers can be NULL/optional... Hopefully no one ever gets confused.
cpuModels->nmodels++; return 0; } @@ -227,20 +234,27 @@ int virDomainCapsCPUModelsAdd(virDomainCapsCPUModelsPtr cpuModels, const char *name, ssize_t nameLen, - virDomainCapsCPUUsable usable) + virDomainCapsCPUUsable usable, + char **blockers) { - char *copy = NULL; + char *nameCopy = NULL; + char **blockersCopy = NULL;
- if (VIR_STRNDUP(copy, name, nameLen) < 0) + if (VIR_STRNDUP(nameCopy, name, nameLen) < 0) goto error;
- if (virDomainCapsCPUModelsAddSteal(cpuModels, ©, usable) < 0) + if (virStringListCopy(&blockersCopy, (const char **)blockers) < 0)
Obviously based on patch 1 comment, this would change slightly... Reviewed-by: John Ferlan <jferlan@redhat.com> John [...]

On Thu, Oct 12, 2017 at 07:23:25 -0400, John Ferlan wrote:
On 10/04/2017 10:58 AM, Jiri Denemark wrote:
When a hypervisor marks a CPU model as unusable on the current host, it may also give us a list of features which prevent the model from being usable. Storing this list in virDomainCapsCPUModel will help the CPU driver with creating a host-model CPU configuration.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/conf/domain_capabilities.c | 30 ++++++++++++++++++++++-------- src/conf/domain_capabilities.h | 7 +++++-- src/qemu/qemu_capabilities.c | 11 ++++++----- tests/domaincapstest.c | 6 +++--- 4 files changed, 36 insertions(+), 18 deletions(-)
diff --git a/src/conf/domain_capabilities.c b/src/conf/domain_capabilities.c index f62038b96c..be34576204 100644 --- a/src/conf/domain_capabilities.c +++ b/src/conf/domain_capabilities.c @@ -163,7 +163,8 @@ virDomainCapsCPUModelsCopy(virDomainCapsCPUModelsPtr old) for (i = 0; i < old->nmodels; i++) { if (virDomainCapsCPUModelsAdd(cpuModels, old->models[i].name, -1, - old->models[i].usable) < 0) + old->models[i].usable, + old->models[i].blockers) < 0) goto error; }
@@ -195,7 +196,8 @@ virDomainCapsCPUModelsFilter(virDomainCapsCPUModelsPtr old,
if (virDomainCapsCPUModelsAdd(cpuModels, old->models[i].name, -1, - old->models[i].usable) < 0) + old->models[i].usable, + old->models[i].blockers) < 0) goto error; }
@@ -210,7 +212,8 @@ virDomainCapsCPUModelsFilter(virDomainCapsCPUModelsPtr old, int virDomainCapsCPUModelsAddSteal(virDomainCapsCPUModelsPtr cpuModels, char **name, - virDomainCapsCPUUsable usable) + virDomainCapsCPUUsable usable, + char ***blockers) { if (VIR_RESIZE_N(cpuModels->models, cpuModels->nmodels_max, cpuModels->nmodels, 1) < 0) @@ -218,6 +221,10 @@ virDomainCapsCPUModelsAddSteal(virDomainCapsCPUModelsPtr cpuModels,
cpuModels->models[cpuModels->nmodels].usable = usable; VIR_STEAL_PTR(cpuModels->models[cpuModels->nmodels].name, *name); + + if (blockers) + VIR_STEAL_PTR(cpuModels->models[cpuModels->nmodels].blockers, *blockers); +
So @name is required and @blockers can be NULL/optional... Hopefully no one ever gets confused.
I don't think there's any room for confusion since @blockers only make sense if the CPU model @name is unusable. They are naturally optional. Jirka

Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/qemu/qemu_capabilities.c | 51 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 49 insertions(+), 2 deletions(-) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index b20dd6ec32..1ce2aa375f 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -3727,6 +3727,10 @@ virQEMUCapsLoadCPUModels(virQEMUCapsPtr qemuCaps, size_t i; int n; int ret = -1; + xmlNodePtr node; + xmlNodePtr *blockerNodes = NULL; + char **blockers = NULL; + int nblockers; if (type == VIR_DOMAIN_VIRT_KVM) n = virXPathNodeSet("./cpu[@type='kvm']", ctxt, &nodes); @@ -3769,7 +3773,34 @@ virQEMUCapsLoadCPUModels(virQEMUCapsPtr qemuCaps, goto cleanup; } - if (virDomainCapsCPUModelsAddSteal(cpus, &str, usable, NULL) < 0) + node = ctxt->node; + ctxt->node = nodes[i]; + nblockers = virXPathNodeSet("./blocker", ctxt, &blockerNodes); + ctxt->node = node; + + if (nblockers < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("failed to parse qemu capabilities cpus")); + goto cleanup; + } + + if (nblockers > 0) { + size_t j; + + if (VIR_ALLOC_N(blockers, nblockers + 1) < 0) + goto cleanup; + + for (j = 0; j < nblockers; j++) { + if (!(blockers[j] = virXMLPropString(blockerNodes[j], "name"))) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("missing blocker name in QEMU " + "capabilities cache")); + goto cleanup; + } + } + } + + if (virDomainCapsCPUModelsAddSteal(cpus, &str, usable, &blockers) < 0) goto cleanup; } @@ -3778,6 +3809,8 @@ virQEMUCapsLoadCPUModels(virQEMUCapsPtr qemuCaps, cleanup: VIR_FREE(nodes); VIR_FREE(str); + VIR_FREE(blockerNodes); + virStringListFree(blockers); return ret; } @@ -4135,7 +4168,21 @@ virQEMUCapsFormatCPUModels(virQEMUCapsPtr qemuCaps, virBufferAsprintf(buf, " usable='%s'", virDomainCapsCPUUsableTypeToString(cpu->usable)); } - virBufferAddLit(buf, "/>\n"); + + if (cpu->blockers) { + size_t j; + + virBufferAddLit(buf, ">\n"); + virBufferAdjustIndent(buf, 2); + + for (j = 0; cpu->blockers[j]; j++) + virBufferAsprintf(buf, "<blocker name='%s'/>\n", cpu->blockers[j]); + + virBufferAdjustIndent(buf, -2); + virBufferAddLit(buf, "</cpu>\n"); + } else { + virBufferAddLit(buf, "/>\n"); + } } } -- 2.14.2

On 10/04/2017 10:58 AM, Jiri Denemark wrote:
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/qemu/qemu_capabilities.c | 51 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 49 insertions(+), 2 deletions(-)
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index b20dd6ec32..1ce2aa375f 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -3727,6 +3727,10 @@ virQEMUCapsLoadCPUModels(virQEMUCapsPtr qemuCaps, size_t i; int n; int ret = -1; + xmlNodePtr node; + xmlNodePtr *blockerNodes = NULL; + char **blockers = NULL; + int nblockers;
if (type == VIR_DOMAIN_VIRT_KVM) n = virXPathNodeSet("./cpu[@type='kvm']", ctxt, &nodes); @@ -3769,7 +3773,34 @@ virQEMUCapsLoadCPUModels(virQEMUCapsPtr qemuCaps, goto cleanup; }
- if (virDomainCapsCPUModelsAddSteal(cpus, &str, usable, NULL) < 0) + node = ctxt->node; + ctxt->node = nodes[i]; + nblockers = virXPathNodeSet("./blocker", ctxt, &blockerNodes); + ctxt->node = node; + + if (nblockers < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("failed to parse qemu capabilities cpus"));
s/qemu/QEMU s/cpus/blockers/ Reviewed-by: John Ferlan <jferlan@redhat.com> John [...]

On Thu, Oct 12, 2017 at 07:23:41 -0400, John Ferlan wrote:
On 10/04/2017 10:58 AM, Jiri Denemark wrote:
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/qemu/qemu_capabilities.c | 51 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 49 insertions(+), 2 deletions(-)
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index b20dd6ec32..1ce2aa375f 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -3727,6 +3727,10 @@ virQEMUCapsLoadCPUModels(virQEMUCapsPtr qemuCaps, size_t i; int n; int ret = -1; + xmlNodePtr node; + xmlNodePtr *blockerNodes = NULL; + char **blockers = NULL; + int nblockers;
if (type == VIR_DOMAIN_VIRT_KVM) n = virXPathNodeSet("./cpu[@type='kvm']", ctxt, &nodes); @@ -3769,7 +3773,34 @@ virQEMUCapsLoadCPUModels(virQEMUCapsPtr qemuCaps, goto cleanup; }
- if (virDomainCapsCPUModelsAddSteal(cpus, &str, usable, NULL) < 0) + node = ctxt->node; + ctxt->node = nodes[i]; + nblockers = virXPathNodeSet("./blocker", ctxt, &blockerNodes); + ctxt->node = node; + + if (nblockers < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("failed to parse qemu capabilities cpus"));
s/qemu/QEMU s/cpus/blockers/
Oops, too much copypasta. I changed it to "failed to parse CPU blockers in QEMU capabilities" Jirka

query-cpu-definitions QMP command returns a list of unavailable features which prevent CPU models from being usable on the current host. So far we only checked whether the list was empty to mark CPU models as (un)usable. This patch parses all unavailable features for each CPU model and stores them in virDomainCapsCPUModel as a list of usability blockers. Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/qemu/qemu_capabilities.c | 2 +- src/qemu/qemu_monitor.c | 2 + src/qemu/qemu_monitor.h | 1 + src/qemu/qemu_monitor_json.c | 26 +- tests/qemucapabilitiesdata/caps_2.10.0.s390x.xml | 1102 +++++++++++++++++++-- tests/qemucapabilitiesdata/caps_2.10.0.x86_64.xml | 236 ++++- tests/qemucapabilitiesdata/caps_2.8.0.x86_64.xml | 154 ++- tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml | 154 ++- 8 files changed, 1556 insertions(+), 121 deletions(-) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 1ce2aa375f..7ddc6cafd4 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -3006,7 +3006,7 @@ virQEMUCapsProbeQMPCPUDefinitions(virQEMUCapsPtr qemuCaps, usable = VIR_DOMCAPS_CPU_USABLE_NO; if (virDomainCapsCPUModelsAddSteal(models, &cpus[i]->name, usable, - NULL) < 0) + &cpus[i]->blockers) < 0) goto cleanup; } diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index 363ad76cfe..04bf1ab5c1 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -3736,6 +3736,8 @@ qemuMonitorCPUDefInfoFree(qemuMonitorCPUDefInfoPtr cpu) { if (!cpu) return; + + virStringListFree(cpu->blockers); VIR_FREE(cpu->name); VIR_FREE(cpu); } diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index 6414d2483a..ee6f27cf35 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -972,6 +972,7 @@ typedef qemuMonitorCPUDefInfo *qemuMonitorCPUDefInfoPtr; struct _qemuMonitorCPUDefInfo { virTristateBool usable; char *name; + char **blockers; /* NULL-terminated string list */ }; int qemuMonitorGetCPUDefinitions(qemuMonitorPtr mon, diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index c63d250d36..fcdd58b369 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -5076,6 +5076,8 @@ qemuMonitorJSONGetCPUDefinitions(qemuMonitorPtr mon, if (virJSONValueObjectHasKey(child, "unavailable-features")) { virJSONValuePtr blockers; + size_t j; + int len; blockers = virJSONValueObjectGetArray(child, "unavailable-features"); @@ -5086,10 +5088,32 @@ qemuMonitorJSONGetCPUDefinitions(qemuMonitorPtr mon, goto cleanup; } - if (virJSONValueArraySize(blockers) > 0) + len = virJSONValueArraySize(blockers); + + if (len != 0) cpu->usable = VIR_TRISTATE_BOOL_NO; else cpu->usable = VIR_TRISTATE_BOOL_YES; + + if (len > 0 && VIR_ALLOC_N(cpu->blockers, len + 1) < 0) + goto cleanup; + + for (j = 0; j < len; j++) { + virJSONValuePtr blocker = virJSONValueArrayGet(blockers, j); + char *name; + + if (blocker->type != VIR_JSON_TYPE_STRING) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("unexpected value in unavailable-features " + "array")); + goto cleanup; + } + + if (VIR_STRDUP(name, virJSONValueGetString(blocker)) < 0) + goto cleanup; + + cpu->blockers[j] = name; + } } } diff --git a/tests/qemucapabilitiesdata/caps_2.10.0.s390x.xml b/tests/qemucapabilitiesdata/caps_2.10.0.s390x.xml index 2806345b9d..1d3edc527b 100644 --- a/tests/qemucapabilitiesdata/caps_2.10.0.s390x.xml +++ b/tests/qemucapabilitiesdata/caps_2.10.0.s390x.xml @@ -241,72 +241,1050 @@ <cpu type='kvm' name='z196-base' usable='yes'/> <cpu type='kvm' name='z13-base' usable='yes'/> <cpu type='kvm' name='z890' usable='yes'/> - <cpu type='tcg' name='z10EC-base' usable='no'/> - <cpu type='tcg' name='z9EC-base' usable='no'/> - <cpu type='tcg' name='z196.2-base' usable='no'/> + <cpu type='tcg' name='z10EC-base' usable='no'> + <blocker name='dateh2'/> + <blocker name='pfpo'/> + <blocker name='dfphp'/> + <blocker name='dfp'/> + <blocker name='ectg'/> + <blocker name='parseh'/> + <blocker name='hfpue'/> + <blocker name='hfpm'/> + <blocker name='csske'/> + <blocker name='srs'/> + <blocker name='asnlxr'/> + <blocker name='msa'/> + <blocker name='tods'/> + <blocker name='type'/> + </cpu> + <cpu type='tcg' name='z9EC-base' usable='no'> + <blocker name='dateh2'/> + <blocker name='hfpue'/> + <blocker name='hfpm'/> + <blocker name='srs'/> + <blocker name='asnlxr'/> + <blocker name='msa'/> + <blocker name='tods'/> + <blocker name='type'/> + </cpu> + <cpu type='tcg' name='z196.2-base' usable='no'> + <blocker name='dateh2'/> + <blocker name='iacc2'/> + <blocker name='cmpsceh'/> + <blocker name='pfpo'/> + <blocker name='dfphp'/> + <blocker name='dfp'/> + <blocker name='sprogp'/> + <blocker name='fpe'/> + <blocker name='emon'/> + <blocker name='ectg'/> + <blocker name='parseh'/> + <blocker name='hfpue'/> + <blocker name='hfpm'/> + <blocker name='nonqks'/> + <blocker name='csske'/> + <blocker name='srs'/> + <blocker name='asnlxr'/> + <blocker name='msa'/> + <blocker name='tods'/> + <blocker name='type'/> + </cpu> <cpu type='tcg' name='z900-base' usable='yes'/> - <cpu type='tcg' name='z990' usable='no'/> - <cpu type='tcg' name='z900.2-base' usable='no'/> + <cpu type='tcg' name='z990' usable='no'> + <blocker name='hfpm'/> + <blocker name='msa'/> + <blocker name='type'/> + </cpu> + <cpu type='tcg' name='z900.2-base' usable='no'> + <blocker name='type'/> + </cpu> <cpu type='tcg' name='host'/> - <cpu type='tcg' name='z900.3' usable='no'/> - <cpu type='tcg' name='z114' usable='no'/> - <cpu type='tcg' name='z890-base' usable='no'/> - <cpu type='tcg' name='z13.2-base' usable='no'/> - <cpu type='tcg' name='zEC12.2' usable='no'/> - <cpu type='tcg' name='z10BC' usable='no'/> - <cpu type='tcg' name='z900.2' usable='no'/> - <cpu type='tcg' name='z10BC.2' usable='no'/> - <cpu type='tcg' name='z196' usable='no'/> - <cpu type='tcg' name='z9EC' usable='no'/> - <cpu type='tcg' name='z990-base' usable='no'/> - <cpu type='tcg' name='z10EC.3' usable='no'/> + <cpu type='tcg' name='z900.3' usable='no'> + <blocker name='type'/> + </cpu> + <cpu type='tcg' name='z114' usable='no'> + <blocker name='cmm'/> + <blocker name='dateh2'/> + <blocker name='aefsi'/> + <blocker name='sthyi'/> + <blocker name='iacc2'/> + <blocker name='cmpsceh'/> + <blocker name='pfpo'/> + <blocker name='dfphp'/> + <blocker name='dfp'/> + <blocker name='sprogp'/> + <blocker name='fpe'/> + <blocker name='emon'/> + <blocker name='ectg'/> + <blocker name='parseh'/> + <blocker name='hfpue'/> + <blocker name='hfpm'/> + <blocker name='nonqks'/> + <blocker name='ipter'/> + <blocker name='csske'/> + <blocker name='srs'/> + <blocker name='edat'/> + <blocker name='asnlxr'/> + <blocker name='msa4'/> + <blocker name='msa3'/> + <blocker name='msa2'/> + <blocker name='msa1'/> + <blocker name='msa'/> + <blocker name='tods'/> + <blocker name='type'/> + </cpu> + <cpu type='tcg' name='z890-base' usable='no'> + <blocker name='hfpm'/> + <blocker name='msa'/> + <blocker name='type'/> + </cpu> + <cpu type='tcg' name='z13.2-base' usable='no'> + <blocker name='dateh2'/> + <blocker name='dfppc'/> + <blocker name='iacc2'/> + <blocker name='dfpzc'/> + <blocker name='cmpsceh'/> + <blocker name='pfpo'/> + <blocker name='dfphp'/> + <blocker name='dfp'/> + <blocker name='sprogp'/> + <blocker name='fpe'/> + <blocker name='emon'/> + <blocker name='ectg'/> + <blocker name='parseh'/> + <blocker name='hfpue'/> + <blocker name='hfpm'/> + <blocker name='nonqks'/> + <blocker name='csske'/> + <blocker name='srs'/> + <blocker name='asnlxr'/> + <blocker name='msa'/> + <blocker name='gen13ptff'/> + <blocker name='tods'/> + <blocker name='type'/> + </cpu> + <cpu type='tcg' name='zEC12.2' usable='no'> + <blocker name='cmm'/> + <blocker name='dateh2'/> + <blocker name='esop'/> + <blocker name='sea_esop2'/> + <blocker name='edat2'/> + <blocker name='aefsi'/> + <blocker name='sthyi'/> + <blocker name='te'/> + <blocker name='aen'/> + <blocker name='zpci'/> + <blocker name='ri'/> + <blocker name='iacc2'/> + <blocker name='cte'/> + <blocker name='dfpzc'/> + <blocker name='cmpsceh'/> + <blocker name='pfpo'/> + <blocker name='dfphp'/> + <blocker name='dfp'/> + <blocker name='sprogp'/> + <blocker name='fpe'/> + <blocker name='emon'/> + <blocker name='ectg'/> + <blocker name='parseh'/> + <blocker name='hfpue'/> + <blocker name='hfpm'/> + <blocker name='nonqks'/> + <blocker name='ipter'/> + <blocker name='csske'/> + <blocker name='srs'/> + <blocker name='edat'/> + <blocker name='asnlxr'/> + <blocker name='msa4'/> + <blocker name='msa3'/> + <blocker name='msa2'/> + <blocker name='msa1'/> + <blocker name='msa'/> + <blocker name='tods'/> + <blocker name='type'/> + </cpu> + <cpu type='tcg' name='z10BC' usable='no'> + <blocker name='cmm'/> + <blocker name='dateh2'/> + <blocker name='sthyi'/> + <blocker name='pfpo'/> + <blocker name='dfphp'/> + <blocker name='dfp'/> + <blocker name='ectg'/> + <blocker name='parseh'/> + <blocker name='hfpue'/> + <blocker name='hfpm'/> + <blocker name='csske'/> + <blocker name='srs'/> + <blocker name='edat'/> + <blocker name='asnlxr'/> + <blocker name='msa2'/> + <blocker name='msa1'/> + <blocker name='msa'/> + <blocker name='tods'/> + <blocker name='type'/> + </cpu> + <cpu type='tcg' name='z900.2' usable='no'> + <blocker name='type'/> + </cpu> + <cpu type='tcg' name='z10BC.2' usable='no'> + <blocker name='cmm'/> + <blocker name='dateh2'/> + <blocker name='sthyi'/> + <blocker name='pfpo'/> + <blocker name='dfphp'/> + <blocker name='dfp'/> + <blocker name='ectg'/> + <blocker name='parseh'/> + <blocker name='hfpue'/> + <blocker name='hfpm'/> + <blocker name='csske'/> + <blocker name='srs'/> + <blocker name='edat'/> + <blocker name='asnlxr'/> + <blocker name='msa2'/> + <blocker name='msa1'/> + <blocker name='msa'/> + <blocker name='tods'/> + <blocker name='type'/> + </cpu> + <cpu type='tcg' name='z196' usable='no'> + <blocker name='cmm'/> + <blocker name='dateh2'/> + <blocker name='aefsi'/> + <blocker name='sthyi'/> + <blocker name='iacc2'/> + <blocker name='cmpsceh'/> + <blocker name='pfpo'/> + <blocker name='dfphp'/> + <blocker name='dfp'/> + <blocker name='sprogp'/> + <blocker name='fpe'/> + <blocker name='emon'/> + <blocker name='ectg'/> + <blocker name='parseh'/> + <blocker name='hfpue'/> + <blocker name='hfpm'/> + <blocker name='nonqks'/> + <blocker name='ipter'/> + <blocker name='csske'/> + <blocker name='srs'/> + <blocker name='edat'/> + <blocker name='asnlxr'/> + <blocker name='msa4'/> + <blocker name='msa3'/> + <blocker name='msa2'/> + <blocker name='msa1'/> + <blocker name='msa'/> + <blocker name='tods'/> + <blocker name='type'/> + </cpu> + <cpu type='tcg' name='z9EC' usable='no'> + <blocker name='cmm'/> + <blocker name='dateh2'/> + <blocker name='sthyi'/> + <blocker name='hfpue'/> + <blocker name='hfpm'/> + <blocker name='srs'/> + <blocker name='asnlxr'/> + <blocker name='msa1'/> + <blocker name='msa'/> + <blocker name='tods'/> + <blocker name='type'/> + </cpu> + <cpu type='tcg' name='z990-base' usable='no'> + <blocker name='hfpm'/> + <blocker name='msa'/> + <blocker name='type'/> + </cpu> + <cpu type='tcg' name='z10EC.3' usable='no'> + <blocker name='cmm'/> + <blocker name='dateh2'/> + <blocker name='sthyi'/> + <blocker name='pfpo'/> + <blocker name='dfphp'/> + <blocker name='dfp'/> + <blocker name='ectg'/> + <blocker name='parseh'/> + <blocker name='hfpue'/> + <blocker name='hfpm'/> + <blocker name='csske'/> + <blocker name='srs'/> + <blocker name='edat'/> + <blocker name='asnlxr'/> + <blocker name='msa2'/> + <blocker name='msa1'/> + <blocker name='msa'/> + <blocker name='tods'/> + <blocker name='type'/> + </cpu> <cpu type='tcg' name='z900' usable='yes'/> - <cpu type='tcg' name='z9EC.3-base' usable='no'/> - <cpu type='tcg' name='z990.5-base' usable='no'/> - <cpu type='tcg' name='z10EC.2' usable='no'/> - <cpu type='tcg' name='z9BC.2' usable='no'/> - <cpu type='tcg' name='z10EC' usable='no'/> - <cpu type='tcg' name='z990.3-base' usable='no'/> - <cpu type='tcg' name='z14' usable='no'/> - <cpu type='tcg' name='z13s' usable='no'/> - <cpu type='tcg' name='z10EC.3-base' usable='no'/> - <cpu type='tcg' name='zEC12.2-base' usable='no'/> - <cpu type='tcg' name='z890.3-base' usable='no'/> - <cpu type='tcg' name='z9EC.3' usable='no'/> - <cpu type='tcg' name='z990.5' usable='no'/> - <cpu type='tcg' name='z13' usable='no'/> - <cpu type='tcg' name='z13s-base' usable='no'/> - <cpu type='tcg' name='z14-base' usable='no'/> - <cpu type='tcg' name='z9EC.2' usable='no'/> - <cpu type='tcg' name='z990.4' usable='no'/> - <cpu type='tcg' name='zEC12-base' usable='no'/> - <cpu type='tcg' name='z9EC.2-base' usable='no'/> - <cpu type='tcg' name='zBC12' usable='no'/> - <cpu type='tcg' name='z196.2' usable='no'/> - <cpu type='tcg' name='z990.3' usable='no'/> - <cpu type='tcg' name='z990.2-base' usable='no'/> - <cpu type='tcg' name='z900.3-base' usable='no'/> - <cpu type='tcg' name='z890.3' usable='no'/> - <cpu type='tcg' name='z10EC.2-base' usable='no'/> - <cpu type='tcg' name='z990.2' usable='no'/> - <cpu type='tcg' name='z890.2' usable='no'/> - <cpu type='tcg' name='zBC12-base' usable='no'/> - <cpu type='tcg' name='z800-base' usable='no'/> - <cpu type='tcg' name='zEC12' usable='no'/> - <cpu type='tcg' name='z9BC.2-base' usable='no'/> - <cpu type='tcg' name='z9BC' usable='no'/> - <cpu type='tcg' name='z10BC.2-base' usable='no'/> - <cpu type='tcg' name='z990.4-base' usable='no'/> + <cpu type='tcg' name='z9EC.3-base' usable='no'> + <blocker name='dateh2'/> + <blocker name='hfpue'/> + <blocker name='hfpm'/> + <blocker name='srs'/> + <blocker name='asnlxr'/> + <blocker name='msa'/> + <blocker name='tods'/> + <blocker name='type'/> + </cpu> + <cpu type='tcg' name='z990.5-base' usable='no'> + <blocker name='hfpm'/> + <blocker name='msa'/> + <blocker name='type'/> + </cpu> + <cpu type='tcg' name='z10EC.2' usable='no'> + <blocker name='cmm'/> + <blocker name='dateh2'/> + <blocker name='sthyi'/> + <blocker name='pfpo'/> + <blocker name='dfphp'/> + <blocker name='dfp'/> + <blocker name='ectg'/> + <blocker name='parseh'/> + <blocker name='hfpue'/> + <blocker name='hfpm'/> + <blocker name='csske'/> + <blocker name='srs'/> + <blocker name='edat'/> + <blocker name='asnlxr'/> + <blocker name='msa2'/> + <blocker name='msa1'/> + <blocker name='msa'/> + <blocker name='tods'/> + <blocker name='type'/> + </cpu> + <cpu type='tcg' name='z9BC.2' usable='no'> + <blocker name='cmm'/> + <blocker name='dateh2'/> + <blocker name='sthyi'/> + <blocker name='hfpue'/> + <blocker name='hfpm'/> + <blocker name='srs'/> + <blocker name='asnlxr'/> + <blocker name='msa1'/> + <blocker name='msa'/> + <blocker name='tods'/> + <blocker name='type'/> + </cpu> + <cpu type='tcg' name='z10EC' usable='no'> + <blocker name='cmm'/> + <blocker name='dateh2'/> + <blocker name='sthyi'/> + <blocker name='pfpo'/> + <blocker name='dfphp'/> + <blocker name='dfp'/> + <blocker name='ectg'/> + <blocker name='parseh'/> + <blocker name='hfpue'/> + <blocker name='hfpm'/> + <blocker name='csske'/> + <blocker name='srs'/> + <blocker name='edat'/> + <blocker name='asnlxr'/> + <blocker name='msa2'/> + <blocker name='msa1'/> + <blocker name='msa'/> + <blocker name='tods'/> + <blocker name='type'/> + </cpu> + <cpu type='tcg' name='z990.3-base' usable='no'> + <blocker name='hfpm'/> + <blocker name='msa'/> + <blocker name='type'/> + </cpu> + <cpu type='tcg' name='z14' usable='no'> + <blocker name='cmm'/> + <blocker name='dateh2'/> + <blocker name='esop'/> + <blocker name='vxeh'/> + <blocker name='vxpd'/> + <blocker name='gs'/> + <blocker name='sea_esop2'/> + <blocker name='iep'/> + <blocker name='vx'/> + <blocker name='dfppc'/> + <blocker name='edat2'/> + <blocker name='aefsi'/> + <blocker name='sthyi'/> + <blocker name='te'/> + <blocker name='ais'/> + <blocker name='aen'/> + <blocker name='zpci'/> + <blocker name='ri'/> + <blocker name='tsi'/> + <blocker name='sema'/> + <blocker name='minste2'/> + <blocker name='eec'/> + <blocker name='iacc2'/> + <blocker name='cte'/> + <blocker name='dfpzc'/> + <blocker name='cmpsceh'/> + <blocker name='pfpo'/> + <blocker name='dfphp'/> + <blocker name='dfp'/> + <blocker name='sprogp'/> + <blocker name='opc'/> + <blocker name='fpe'/> + <blocker name='emon'/> + <blocker name='ectg'/> + <blocker name='parseh'/> + <blocker name='hfpue'/> + <blocker name='hfpm'/> + <blocker name='nonqks'/> + <blocker name='ipter'/> + <blocker name='csske'/> + <blocker name='srs'/> + <blocker name='edat'/> + <blocker name='asnlxr'/> + <blocker name='msa8'/> + <blocker name='msa7'/> + <blocker name='msa6'/> + <blocker name='msa5'/> + <blocker name='msa4'/> + <blocker name='msa3'/> + <blocker name='msa2'/> + <blocker name='msa1'/> + <blocker name='msa'/> + <blocker name='gen13ptff'/> + <blocker name='tods'/> + <blocker name='type'/> + </cpu> + <cpu type='tcg' name='z13s' usable='no'> + <blocker name='cmm'/> + <blocker name='dateh2'/> + <blocker name='esop'/> + <blocker name='sea_esop2'/> + <blocker name='vx'/> + <blocker name='dfppc'/> + <blocker name='edat2'/> + <blocker name='aefsi'/> + <blocker name='sthyi'/> + <blocker name='te'/> + <blocker name='aen'/> + <blocker name='zpci'/> + <blocker name='ri'/> + <blocker name='iacc2'/> + <blocker name='cte'/> + <blocker name='dfpzc'/> + <blocker name='cmpsceh'/> + <blocker name='pfpo'/> + <blocker name='dfphp'/> + <blocker name='dfp'/> + <blocker name='sprogp'/> + <blocker name='fpe'/> + <blocker name='emon'/> + <blocker name='ectg'/> + <blocker name='parseh'/> + <blocker name='hfpue'/> + <blocker name='hfpm'/> + <blocker name='nonqks'/> + <blocker name='ipter'/> + <blocker name='csske'/> + <blocker name='srs'/> + <blocker name='edat'/> + <blocker name='asnlxr'/> + <blocker name='msa5'/> + <blocker name='msa4'/> + <blocker name='msa3'/> + <blocker name='msa2'/> + <blocker name='msa1'/> + <blocker name='msa'/> + <blocker name='gen13ptff'/> + <blocker name='tods'/> + <blocker name='type'/> + </cpu> + <cpu type='tcg' name='z10EC.3-base' usable='no'> + <blocker name='dateh2'/> + <blocker name='pfpo'/> + <blocker name='dfphp'/> + <blocker name='dfp'/> + <blocker name='ectg'/> + <blocker name='parseh'/> + <blocker name='hfpue'/> + <blocker name='hfpm'/> + <blocker name='csske'/> + <blocker name='srs'/> + <blocker name='asnlxr'/> + <blocker name='msa'/> + <blocker name='tods'/> + <blocker name='type'/> + </cpu> + <cpu type='tcg' name='zEC12.2-base' usable='no'> + <blocker name='dateh2'/> + <blocker name='iacc2'/> + <blocker name='dfpzc'/> + <blocker name='cmpsceh'/> + <blocker name='pfpo'/> + <blocker name='dfphp'/> + <blocker name='dfp'/> + <blocker name='sprogp'/> + <blocker name='fpe'/> + <blocker name='emon'/> + <blocker name='ectg'/> + <blocker name='parseh'/> + <blocker name='hfpue'/> + <blocker name='hfpm'/> + <blocker name='nonqks'/> + <blocker name='csske'/> + <blocker name='srs'/> + <blocker name='asnlxr'/> + <blocker name='msa'/> + <blocker name='tods'/> + <blocker name='type'/> + </cpu> + <cpu type='tcg' name='z890.3-base' usable='no'> + <blocker name='hfpm'/> + <blocker name='msa'/> + <blocker name='type'/> + </cpu> + <cpu type='tcg' name='z9EC.3' usable='no'> + <blocker name='cmm'/> + <blocker name='dateh2'/> + <blocker name='sthyi'/> + <blocker name='hfpue'/> + <blocker name='hfpm'/> + <blocker name='srs'/> + <blocker name='asnlxr'/> + <blocker name='msa1'/> + <blocker name='msa'/> + <blocker name='tods'/> + <blocker name='type'/> + </cpu> + <cpu type='tcg' name='z990.5' usable='no'> + <blocker name='hfpm'/> + <blocker name='msa'/> + <blocker name='type'/> + </cpu> + <cpu type='tcg' name='z13' usable='no'> + <blocker name='cmm'/> + <blocker name='dateh2'/> + <blocker name='esop'/> + <blocker name='sea_esop2'/> + <blocker name='vx'/> + <blocker name='dfppc'/> + <blocker name='edat2'/> + <blocker name='aefsi'/> + <blocker name='sthyi'/> + <blocker name='te'/> + <blocker name='aen'/> + <blocker name='zpci'/> + <blocker name='ri'/> + <blocker name='iacc2'/> + <blocker name='cte'/> + <blocker name='dfpzc'/> + <blocker name='cmpsceh'/> + <blocker name='pfpo'/> + <blocker name='dfphp'/> + <blocker name='dfp'/> + <blocker name='sprogp'/> + <blocker name='fpe'/> + <blocker name='emon'/> + <blocker name='ectg'/> + <blocker name='parseh'/> + <blocker name='hfpue'/> + <blocker name='hfpm'/> + <blocker name='nonqks'/> + <blocker name='ipter'/> + <blocker name='csske'/> + <blocker name='srs'/> + <blocker name='edat'/> + <blocker name='asnlxr'/> + <blocker name='msa5'/> + <blocker name='msa4'/> + <blocker name='msa3'/> + <blocker name='msa2'/> + <blocker name='msa1'/> + <blocker name='msa'/> + <blocker name='gen13ptff'/> + <blocker name='tods'/> + <blocker name='type'/> + </cpu> + <cpu type='tcg' name='z13s-base' usable='no'> + <blocker name='dateh2'/> + <blocker name='dfppc'/> + <blocker name='iacc2'/> + <blocker name='dfpzc'/> + <blocker name='cmpsceh'/> + <blocker name='pfpo'/> + <blocker name='dfphp'/> + <blocker name='dfp'/> + <blocker name='sprogp'/> + <blocker name='fpe'/> + <blocker name='emon'/> + <blocker name='ectg'/> + <blocker name='parseh'/> + <blocker name='hfpue'/> + <blocker name='hfpm'/> + <blocker name='nonqks'/> + <blocker name='csske'/> + <blocker name='srs'/> + <blocker name='asnlxr'/> + <blocker name='msa'/> + <blocker name='gen13ptff'/> + <blocker name='tods'/> + <blocker name='type'/> + </cpu> + <cpu type='tcg' name='z14-base' usable='no'> + <blocker name='dateh2'/> + <blocker name='dfppc'/> + <blocker name='tsi'/> + <blocker name='sema'/> + <blocker name='minste2'/> + <blocker name='eec'/> + <blocker name='iacc2'/> + <blocker name='dfpzc'/> + <blocker name='cmpsceh'/> + <blocker name='pfpo'/> + <blocker name='dfphp'/> + <blocker name='dfp'/> + <blocker name='sprogp'/> + <blocker name='opc'/> + <blocker name='fpe'/> + <blocker name='emon'/> + <blocker name='ectg'/> + <blocker name='parseh'/> + <blocker name='hfpue'/> + <blocker name='hfpm'/> + <blocker name='nonqks'/> + <blocker name='csske'/> + <blocker name='srs'/> + <blocker name='asnlxr'/> + <blocker name='msa'/> + <blocker name='gen13ptff'/> + <blocker name='tods'/> + <blocker name='type'/> + </cpu> + <cpu type='tcg' name='z9EC.2' usable='no'> + <blocker name='cmm'/> + <blocker name='dateh2'/> + <blocker name='sthyi'/> + <blocker name='hfpue'/> + <blocker name='hfpm'/> + <blocker name='srs'/> + <blocker name='asnlxr'/> + <blocker name='msa1'/> + <blocker name='msa'/> + <blocker name='tods'/> + <blocker name='type'/> + </cpu> + <cpu type='tcg' name='z990.4' usable='no'> + <blocker name='hfpm'/> + <blocker name='msa'/> + <blocker name='type'/> + </cpu> + <cpu type='tcg' name='zEC12-base' usable='no'> + <blocker name='dateh2'/> + <blocker name='iacc2'/> + <blocker name='dfpzc'/> + <blocker name='cmpsceh'/> + <blocker name='pfpo'/> + <blocker name='dfphp'/> + <blocker name='dfp'/> + <blocker name='sprogp'/> + <blocker name='fpe'/> + <blocker name='emon'/> + <blocker name='ectg'/> + <blocker name='parseh'/> + <blocker name='hfpue'/> + <blocker name='hfpm'/> + <blocker name='nonqks'/> + <blocker name='csske'/> + <blocker name='srs'/> + <blocker name='asnlxr'/> + <blocker name='msa'/> + <blocker name='tods'/> + <blocker name='type'/> + </cpu> + <cpu type='tcg' name='z9EC.2-base' usable='no'> + <blocker name='dateh2'/> + <blocker name='hfpue'/> + <blocker name='hfpm'/> + <blocker name='srs'/> + <blocker name='asnlxr'/> + <blocker name='msa'/> + <blocker name='tods'/> + <blocker name='type'/> + </cpu> + <cpu type='tcg' name='zBC12' usable='no'> + <blocker name='cmm'/> + <blocker name='dateh2'/> + <blocker name='esop'/> + <blocker name='sea_esop2'/> + <blocker name='edat2'/> + <blocker name='aefsi'/> + <blocker name='sthyi'/> + <blocker name='te'/> + <blocker name='aen'/> + <blocker name='zpci'/> + <blocker name='ri'/> + <blocker name='iacc2'/> + <blocker name='cte'/> + <blocker name='dfpzc'/> + <blocker name='cmpsceh'/> + <blocker name='pfpo'/> + <blocker name='dfphp'/> + <blocker name='dfp'/> + <blocker name='sprogp'/> + <blocker name='fpe'/> + <blocker name='emon'/> + <blocker name='ectg'/> + <blocker name='parseh'/> + <blocker name='hfpue'/> + <blocker name='hfpm'/> + <blocker name='nonqks'/> + <blocker name='ipter'/> + <blocker name='csske'/> + <blocker name='srs'/> + <blocker name='edat'/> + <blocker name='asnlxr'/> + <blocker name='msa4'/> + <blocker name='msa3'/> + <blocker name='msa2'/> + <blocker name='msa1'/> + <blocker name='msa'/> + <blocker name='tods'/> + <blocker name='type'/> + </cpu> + <cpu type='tcg' name='z196.2' usable='no'> + <blocker name='cmm'/> + <blocker name='dateh2'/> + <blocker name='aefsi'/> + <blocker name='sthyi'/> + <blocker name='iacc2'/> + <blocker name='cmpsceh'/> + <blocker name='pfpo'/> + <blocker name='dfphp'/> + <blocker name='dfp'/> + <blocker name='sprogp'/> + <blocker name='fpe'/> + <blocker name='emon'/> + <blocker name='ectg'/> + <blocker name='parseh'/> + <blocker name='hfpue'/> + <blocker name='hfpm'/> + <blocker name='nonqks'/> + <blocker name='ipter'/> + <blocker name='csske'/> + <blocker name='srs'/> + <blocker name='edat'/> + <blocker name='asnlxr'/> + <blocker name='msa4'/> + <blocker name='msa3'/> + <blocker name='msa2'/> + <blocker name='msa1'/> + <blocker name='msa'/> + <blocker name='tods'/> + <blocker name='type'/> + </cpu> + <cpu type='tcg' name='z990.3' usable='no'> + <blocker name='hfpm'/> + <blocker name='msa'/> + <blocker name='type'/> + </cpu> + <cpu type='tcg' name='z990.2-base' usable='no'> + <blocker name='hfpm'/> + <blocker name='msa'/> + <blocker name='type'/> + </cpu> + <cpu type='tcg' name='z900.3-base' usable='no'> + <blocker name='type'/> + </cpu> + <cpu type='tcg' name='z890.3' usable='no'> + <blocker name='hfpm'/> + <blocker name='msa'/> + <blocker name='type'/> + </cpu> + <cpu type='tcg' name='z10EC.2-base' usable='no'> + <blocker name='dateh2'/> + <blocker name='pfpo'/> + <blocker name='dfphp'/> + <blocker name='dfp'/> + <blocker name='ectg'/> + <blocker name='parseh'/> + <blocker name='hfpue'/> + <blocker name='hfpm'/> + <blocker name='csske'/> + <blocker name='srs'/> + <blocker name='asnlxr'/> + <blocker name='msa'/> + <blocker name='tods'/> + <blocker name='type'/> + </cpu> + <cpu type='tcg' name='z990.2' usable='no'> + <blocker name='hfpm'/> + <blocker name='msa'/> + <blocker name='type'/> + </cpu> + <cpu type='tcg' name='z890.2' usable='no'> + <blocker name='hfpm'/> + <blocker name='msa'/> + <blocker name='type'/> + </cpu> + <cpu type='tcg' name='zBC12-base' usable='no'> + <blocker name='dateh2'/> + <blocker name='iacc2'/> + <blocker name='dfpzc'/> + <blocker name='cmpsceh'/> + <blocker name='pfpo'/> + <blocker name='dfphp'/> + <blocker name='dfp'/> + <blocker name='sprogp'/> + <blocker name='fpe'/> + <blocker name='emon'/> + <blocker name='ectg'/> + <blocker name='parseh'/> + <blocker name='hfpue'/> + <blocker name='hfpm'/> + <blocker name='nonqks'/> + <blocker name='csske'/> + <blocker name='srs'/> + <blocker name='asnlxr'/> + <blocker name='msa'/> + <blocker name='tods'/> + <blocker name='type'/> + </cpu> + <cpu type='tcg' name='z800-base' usable='no'> + <blocker name='type'/> + </cpu> + <cpu type='tcg' name='zEC12' usable='no'> + <blocker name='cmm'/> + <blocker name='dateh2'/> + <blocker name='esop'/> + <blocker name='sea_esop2'/> + <blocker name='edat2'/> + <blocker name='aefsi'/> + <blocker name='sthyi'/> + <blocker name='te'/> + <blocker name='aen'/> + <blocker name='zpci'/> + <blocker name='ri'/> + <blocker name='iacc2'/> + <blocker name='cte'/> + <blocker name='dfpzc'/> + <blocker name='cmpsceh'/> + <blocker name='pfpo'/> + <blocker name='dfphp'/> + <blocker name='dfp'/> + <blocker name='sprogp'/> + <blocker name='fpe'/> + <blocker name='emon'/> + <blocker name='ectg'/> + <blocker name='parseh'/> + <blocker name='hfpue'/> + <blocker name='hfpm'/> + <blocker name='nonqks'/> + <blocker name='ipter'/> + <blocker name='csske'/> + <blocker name='srs'/> + <blocker name='edat'/> + <blocker name='asnlxr'/> + <blocker name='msa4'/> + <blocker name='msa3'/> + <blocker name='msa2'/> + <blocker name='msa1'/> + <blocker name='msa'/> + <blocker name='tods'/> + <blocker name='type'/> + </cpu> + <cpu type='tcg' name='z9BC.2-base' usable='no'> + <blocker name='dateh2'/> + <blocker name='hfpue'/> + <blocker name='hfpm'/> + <blocker name='srs'/> + <blocker name='asnlxr'/> + <blocker name='msa'/> + <blocker name='tods'/> + <blocker name='type'/> + </cpu> + <cpu type='tcg' name='z9BC' usable='no'> + <blocker name='cmm'/> + <blocker name='dateh2'/> + <blocker name='sthyi'/> + <blocker name='hfpue'/> + <blocker name='hfpm'/> + <blocker name='srs'/> + <blocker name='asnlxr'/> + <blocker name='msa1'/> + <blocker name='msa'/> + <blocker name='tods'/> + <blocker name='type'/> + </cpu> + <cpu type='tcg' name='z10BC.2-base' usable='no'> + <blocker name='dateh2'/> + <blocker name='pfpo'/> + <blocker name='dfphp'/> + <blocker name='dfp'/> + <blocker name='ectg'/> + <blocker name='parseh'/> + <blocker name='hfpue'/> + <blocker name='hfpm'/> + <blocker name='csske'/> + <blocker name='srs'/> + <blocker name='asnlxr'/> + <blocker name='msa'/> + <blocker name='tods'/> + <blocker name='type'/> + </cpu> + <cpu type='tcg' name='z990.4-base' usable='no'> + <blocker name='hfpm'/> + <blocker name='msa'/> + <blocker name='type'/> + </cpu> <cpu type='tcg' name='qemu' usable='yes'/> - <cpu type='tcg' name='z10BC-base' usable='no'/> - <cpu type='tcg' name='z9BC-base' usable='no'/> - <cpu type='tcg' name='z800' usable='no'/> - <cpu type='tcg' name='z890.2-base' usable='no'/> - <cpu type='tcg' name='z13.2' usable='no'/> - <cpu type='tcg' name='z114-base' usable='no'/> - <cpu type='tcg' name='z196-base' usable='no'/> - <cpu type='tcg' name='z13-base' usable='no'/> - <cpu type='tcg' name='z890' usable='no'/> + <cpu type='tcg' name='z10BC-base' usable='no'> + <blocker name='dateh2'/> + <blocker name='pfpo'/> + <blocker name='dfphp'/> + <blocker name='dfp'/> + <blocker name='ectg'/> + <blocker name='parseh'/> + <blocker name='hfpue'/> + <blocker name='hfpm'/> + <blocker name='csske'/> + <blocker name='srs'/> + <blocker name='asnlxr'/> + <blocker name='msa'/> + <blocker name='tods'/> + <blocker name='type'/> + </cpu> + <cpu type='tcg' name='z9BC-base' usable='no'> + <blocker name='dateh2'/> + <blocker name='hfpue'/> + <blocker name='hfpm'/> + <blocker name='srs'/> + <blocker name='asnlxr'/> + <blocker name='msa'/> + <blocker name='tods'/> + <blocker name='type'/> + </cpu> + <cpu type='tcg' name='z800' usable='no'> + <blocker name='type'/> + </cpu> + <cpu type='tcg' name='z890.2-base' usable='no'> + <blocker name='hfpm'/> + <blocker name='msa'/> + <blocker name='type'/> + </cpu> + <cpu type='tcg' name='z13.2' usable='no'> + <blocker name='cmm'/> + <blocker name='dateh2'/> + <blocker name='esop'/> + <blocker name='sea_esop2'/> + <blocker name='vx'/> + <blocker name='dfppc'/> + <blocker name='edat2'/> + <blocker name='aefsi'/> + <blocker name='sthyi'/> + <blocker name='te'/> + <blocker name='aen'/> + <blocker name='zpci'/> + <blocker name='ri'/> + <blocker name='iacc2'/> + <blocker name='cte'/> + <blocker name='dfpzc'/> + <blocker name='cmpsceh'/> + <blocker name='pfpo'/> + <blocker name='dfphp'/> + <blocker name='dfp'/> + <blocker name='sprogp'/> + <blocker name='fpe'/> + <blocker name='emon'/> + <blocker name='ectg'/> + <blocker name='parseh'/> + <blocker name='hfpue'/> + <blocker name='hfpm'/> + <blocker name='nonqks'/> + <blocker name='ipter'/> + <blocker name='csske'/> + <blocker name='srs'/> + <blocker name='edat'/> + <blocker name='asnlxr'/> + <blocker name='msa5'/> + <blocker name='msa4'/> + <blocker name='msa3'/> + <blocker name='msa2'/> + <blocker name='msa1'/> + <blocker name='msa'/> + <blocker name='gen13ptff'/> + <blocker name='tods'/> + <blocker name='type'/> + </cpu> + <cpu type='tcg' name='z114-base' usable='no'> + <blocker name='dateh2'/> + <blocker name='iacc2'/> + <blocker name='cmpsceh'/> + <blocker name='pfpo'/> + <blocker name='dfphp'/> + <blocker name='dfp'/> + <blocker name='sprogp'/> + <blocker name='fpe'/> + <blocker name='emon'/> + <blocker name='ectg'/> + <blocker name='parseh'/> + <blocker name='hfpue'/> + <blocker name='hfpm'/> + <blocker name='nonqks'/> + <blocker name='csske'/> + <blocker name='srs'/> + <blocker name='asnlxr'/> + <blocker name='msa'/> + <blocker name='tods'/> + <blocker name='type'/> + </cpu> + <cpu type='tcg' name='z196-base' usable='no'> + <blocker name='dateh2'/> + <blocker name='iacc2'/> + <blocker name='cmpsceh'/> + <blocker name='pfpo'/> + <blocker name='dfphp'/> + <blocker name='dfp'/> + <blocker name='sprogp'/> + <blocker name='fpe'/> + <blocker name='emon'/> + <blocker name='ectg'/> + <blocker name='parseh'/> + <blocker name='hfpue'/> + <blocker name='hfpm'/> + <blocker name='nonqks'/> + <blocker name='csske'/> + <blocker name='srs'/> + <blocker name='asnlxr'/> + <blocker name='msa'/> + <blocker name='tods'/> + <blocker name='type'/> + </cpu> + <cpu type='tcg' name='z13-base' usable='no'> + <blocker name='dateh2'/> + <blocker name='dfppc'/> + <blocker name='iacc2'/> + <blocker name='dfpzc'/> + <blocker name='cmpsceh'/> + <blocker name='pfpo'/> + <blocker name='dfphp'/> + <blocker name='dfp'/> + <blocker name='sprogp'/> + <blocker name='fpe'/> + <blocker name='emon'/> + <blocker name='ectg'/> + <blocker name='parseh'/> + <blocker name='hfpue'/> + <blocker name='hfpm'/> + <blocker name='nonqks'/> + <blocker name='csske'/> + <blocker name='srs'/> + <blocker name='asnlxr'/> + <blocker name='msa'/> + <blocker name='gen13ptff'/> + <blocker name='tods'/> + <blocker name='type'/> + </cpu> + <cpu type='tcg' name='z890' usable='no'> + <blocker name='hfpm'/> + <blocker name='msa'/> + <blocker name='type'/> + </cpu> <machine name='s390-ccw-virtio-2.10' alias='s390-ccw-virtio' maxCpus='248'/> <machine name='s390-ccw-virtio-2.7' maxCpus='248'/> <machine name='s390-ccw-virtio-2.6' maxCpus='248'/> diff --git a/tests/qemucapabilitiesdata/caps_2.10.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_2.10.0.x86_64.xml index 8a31431c09..1a4a73e0fb 100644 --- a/tests/qemucapabilitiesdata/caps_2.10.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_2.10.0.x86_64.xml @@ -700,7 +700,14 @@ <cpu type='kvm' name='base' usable='yes'/> <cpu type='kvm' name='qemu64' usable='yes'/> <cpu type='kvm' name='qemu32' usable='yes'/> - <cpu type='kvm' name='phenom' usable='no'/> + <cpu type='kvm' name='phenom' usable='no'> + <blocker name='mmxext'/> + <blocker name='fxsr-opt'/> + <blocker name='3dnowext'/> + <blocker name='3dnow'/> + <blocker name='sse4a'/> + <blocker name='npt'/> + </cpu> <cpu type='kvm' name='pentium3' usable='yes'/> <cpu type='kvm' name='pentium2' usable='yes'/> <cpu type='kvm' name='pentium' usable='yes'/> @@ -709,31 +716,104 @@ <cpu type='kvm' name='kvm32' usable='yes'/> <cpu type='kvm' name='coreduo' usable='yes'/> <cpu type='kvm' name='core2duo' usable='yes'/> - <cpu type='kvm' name='athlon' usable='no'/> + <cpu type='kvm' name='athlon' usable='no'> + <blocker name='mmxext'/> + <blocker name='3dnowext'/> + <blocker name='3dnow'/> + </cpu> <cpu type='kvm' name='Westmere' usable='yes'/> - <cpu type='kvm' name='Skylake-Server' usable='no'/> - <cpu type='kvm' name='Skylake-Client' usable='no'/> + <cpu type='kvm' name='Skylake-Server' usable='no'> + <blocker name='hle'/> + <blocker name='rtm'/> + <blocker name='mpx'/> + <blocker name='avx512f'/> + <blocker name='avx512dq'/> + <blocker name='rdseed'/> + <blocker name='adx'/> + <blocker name='smap'/> + <blocker name='clwb'/> + <blocker name='avx512cd'/> + <blocker name='avx512bw'/> + <blocker name='avx512vl'/> + <blocker name='3dnowprefetch'/> + <blocker name='xsavec'/> + <blocker name='xgetbv1'/> + <blocker name='mpx'/> + <blocker name='mpx'/> + <blocker name='avx512f'/> + <blocker name='avx512f'/> + <blocker name='avx512f'/> + </cpu> + <cpu type='kvm' name='Skylake-Client' usable='no'> + <blocker name='hle'/> + <blocker name='rtm'/> + <blocker name='mpx'/> + <blocker name='rdseed'/> + <blocker name='adx'/> + <blocker name='smap'/> + <blocker name='3dnowprefetch'/> + <blocker name='xsavec'/> + <blocker name='xgetbv1'/> + <blocker name='mpx'/> + <blocker name='mpx'/> + </cpu> <cpu type='kvm' name='SandyBridge' usable='yes'/> <cpu type='kvm' name='Penryn' usable='yes'/> - <cpu type='kvm' name='Opteron_G5' usable='no'/> - <cpu type='kvm' name='Opteron_G4' usable='no'/> - <cpu type='kvm' name='Opteron_G3' usable='no'/> + <cpu type='kvm' name='Opteron_G5' usable='no'> + <blocker name='sse4a'/> + <blocker name='misalignsse'/> + <blocker name='3dnowprefetch'/> + <blocker name='xop'/> + <blocker name='fma4'/> + <blocker name='tbm'/> + </cpu> + <cpu type='kvm' name='Opteron_G4' usable='no'> + <blocker name='sse4a'/> + <blocker name='misalignsse'/> + <blocker name='3dnowprefetch'/> + <blocker name='xop'/> + <blocker name='fma4'/> + </cpu> + <cpu type='kvm' name='Opteron_G3' usable='no'> + <blocker name='sse4a'/> + <blocker name='misalignsse'/> + </cpu> <cpu type='kvm' name='Opteron_G2' usable='yes'/> <cpu type='kvm' name='Opteron_G1' usable='yes'/> <cpu type='kvm' name='Nehalem' usable='yes'/> <cpu type='kvm' name='IvyBridge' usable='yes'/> - <cpu type='kvm' name='Haswell' usable='no'/> + <cpu type='kvm' name='Haswell' usable='no'> + <blocker name='hle'/> + <blocker name='rtm'/> + </cpu> <cpu type='kvm' name='Haswell-noTSX' usable='yes'/> <cpu type='kvm' name='Conroe' usable='yes'/> - <cpu type='kvm' name='Broadwell' usable='no'/> - <cpu type='kvm' name='Broadwell-noTSX' usable='no'/> + <cpu type='kvm' name='Broadwell' usable='no'> + <blocker name='hle'/> + <blocker name='rtm'/> + <blocker name='rdseed'/> + <blocker name='adx'/> + <blocker name='smap'/> + <blocker name='3dnowprefetch'/> + </cpu> + <cpu type='kvm' name='Broadwell-noTSX' usable='no'> + <blocker name='rdseed'/> + <blocker name='adx'/> + <blocker name='smap'/> + <blocker name='3dnowprefetch'/> + </cpu> <cpu type='kvm' name='486' usable='yes'/> <cpu type='tcg' name='max' usable='yes'/> - <cpu type='tcg' name='host' usable='no'/> + <cpu type='tcg' name='host' usable='no'> + <blocker name='kvm'/> + </cpu> <cpu type='tcg' name='base' usable='yes'/> <cpu type='tcg' name='qemu64' usable='yes'/> <cpu type='tcg' name='qemu32' usable='yes'/> - <cpu type='tcg' name='phenom' usable='no'/> + <cpu type='tcg' name='phenom' usable='no'> + <blocker name='fxsr-opt'/> + <blocker name='npt'/> + </cpu> <cpu type='tcg' name='pentium3' usable='yes'/> <cpu type='tcg' name='pentium2' usable='yes'/> <cpu type='tcg' name='pentium' usable='yes'/> @@ -744,22 +824,132 @@ <cpu type='tcg' name='core2duo' usable='yes'/> <cpu type='tcg' name='athlon' usable='yes'/> <cpu type='tcg' name='Westmere' usable='yes'/> - <cpu type='tcg' name='Skylake-Server' usable='no'/> - <cpu type='tcg' name='Skylake-Client' usable='no'/> - <cpu type='tcg' name='SandyBridge' usable='no'/> + <cpu type='tcg' name='Skylake-Server' usable='no'> + <blocker name='fma'/> + <blocker name='pcid'/> + <blocker name='x2apic'/> + <blocker name='tsc-deadline'/> + <blocker name='avx'/> + <blocker name='f16c'/> + <blocker name='rdrand'/> + <blocker name='hle'/> + <blocker name='avx2'/> + <blocker name='invpcid'/> + <blocker name='rtm'/> + <blocker name='avx512f'/> + <blocker name='avx512dq'/> + <blocker name='rdseed'/> + <blocker name='avx512cd'/> + <blocker name='avx512bw'/> + <blocker name='avx512vl'/> + <blocker name='3dnowprefetch'/> + <blocker name='xsavec'/> + </cpu> + <cpu type='tcg' name='Skylake-Client' usable='no'> + <blocker name='fma'/> + <blocker name='pcid'/> + <blocker name='x2apic'/> + <blocker name='tsc-deadline'/> + <blocker name='avx'/> + <blocker name='f16c'/> + <blocker name='rdrand'/> + <blocker name='hle'/> + <blocker name='avx2'/> + <blocker name='invpcid'/> + <blocker name='rtm'/> + <blocker name='rdseed'/> + <blocker name='3dnowprefetch'/> + <blocker name='xsavec'/> + </cpu> + <cpu type='tcg' name='SandyBridge' usable='no'> + <blocker name='x2apic'/> + <blocker name='tsc-deadline'/> + <blocker name='avx'/> + </cpu> <cpu type='tcg' name='Penryn' usable='yes'/> - <cpu type='tcg' name='Opteron_G5' usable='no'/> - <cpu type='tcg' name='Opteron_G4' usable='no'/> - <cpu type='tcg' name='Opteron_G3' usable='no'/> + <cpu type='tcg' name='Opteron_G5' usable='no'> + <blocker name='fma'/> + <blocker name='avx'/> + <blocker name='f16c'/> + <blocker name='misalignsse'/> + <blocker name='3dnowprefetch'/> + <blocker name='xop'/> + <blocker name='fma4'/> + <blocker name='tbm'/> + </cpu> + <cpu type='tcg' name='Opteron_G4' usable='no'> + <blocker name='avx'/> + <blocker name='misalignsse'/> + <blocker name='3dnowprefetch'/> + <blocker name='xop'/> + <blocker name='fma4'/> + </cpu> + <cpu type='tcg' name='Opteron_G3' usable='no'> + <blocker name='misalignsse'/> + </cpu> <cpu type='tcg' name='Opteron_G2' usable='yes'/> <cpu type='tcg' name='Opteron_G1' usable='yes'/> <cpu type='tcg' name='Nehalem' usable='yes'/> - <cpu type='tcg' name='IvyBridge' usable='no'/> - <cpu type='tcg' name='Haswell' usable='no'/> - <cpu type='tcg' name='Haswell-noTSX' usable='no'/> + <cpu type='tcg' name='IvyBridge' usable='no'> + <blocker name='x2apic'/> + <blocker name='tsc-deadline'/> + <blocker name='avx'/> + <blocker name='f16c'/> + <blocker name='rdrand'/> + </cpu> + <cpu type='tcg' name='Haswell' usable='no'> + <blocker name='fma'/> + <blocker name='pcid'/> + <blocker name='x2apic'/> + <blocker name='tsc-deadline'/> + <blocker name='avx'/> + <blocker name='f16c'/> + <blocker name='rdrand'/> + <blocker name='hle'/> + <blocker name='avx2'/> + <blocker name='invpcid'/> + <blocker name='rtm'/> + </cpu> + <cpu type='tcg' name='Haswell-noTSX' usable='no'> + <blocker name='fma'/> + <blocker name='pcid'/> + <blocker name='x2apic'/> + <blocker name='tsc-deadline'/> + <blocker name='avx'/> + <blocker name='f16c'/> + <blocker name='rdrand'/> + <blocker name='avx2'/> + <blocker name='invpcid'/> + </cpu> <cpu type='tcg' name='Conroe' usable='yes'/> - <cpu type='tcg' name='Broadwell' usable='no'/> - <cpu type='tcg' name='Broadwell-noTSX' usable='no'/> + <cpu type='tcg' name='Broadwell' usable='no'> + <blocker name='fma'/> + <blocker name='pcid'/> + <blocker name='x2apic'/> + <blocker name='tsc-deadline'/> + <blocker name='avx'/> + <blocker name='f16c'/> + <blocker name='rdrand'/> + <blocker name='hle'/> + <blocker name='avx2'/> + <blocker name='invpcid'/> + <blocker name='rtm'/> + <blocker name='rdseed'/> + <blocker name='3dnowprefetch'/> + </cpu> + <cpu type='tcg' name='Broadwell-noTSX' usable='no'> + <blocker name='fma'/> + <blocker name='pcid'/> + <blocker name='x2apic'/> + <blocker name='tsc-deadline'/> + <blocker name='avx'/> + <blocker name='f16c'/> + <blocker name='rdrand'/> + <blocker name='avx2'/> + <blocker name='invpcid'/> + <blocker name='rdseed'/> + <blocker name='3dnowprefetch'/> + </cpu> <cpu type='tcg' name='486' usable='yes'/> <machine name='pc-i440fx-2.10' alias='pc' hotplugCpus='yes' maxCpus='255'/> <machine name='pc-0.12' hotplugCpus='yes' maxCpus='255'/> diff --git a/tests/qemucapabilitiesdata/caps_2.8.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_2.8.0.x86_64.xml index 761f9d1415..7cea98cb36 100644 --- a/tests/qemucapabilitiesdata/caps_2.8.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_2.8.0.x86_64.xml @@ -216,7 +216,14 @@ <cpu type='kvm' name='host' usable='yes'/> <cpu type='kvm' name='qemu64' usable='yes'/> <cpu type='kvm' name='qemu32' usable='yes'/> - <cpu type='kvm' name='phenom' usable='no'/> + <cpu type='kvm' name='phenom' usable='no'> + <blocker name='mmxext'/> + <blocker name='fxsr-opt'/> + <blocker name='3dnowext'/> + <blocker name='3dnow'/> + <blocker name='sse4a'/> + <blocker name='npt'/> + </cpu> <cpu type='kvm' name='pentium3' usable='yes'/> <cpu type='kvm' name='pentium2' usable='yes'/> <cpu type='kvm' name='pentium' usable='yes'/> @@ -225,14 +232,32 @@ <cpu type='kvm' name='kvm32' usable='yes'/> <cpu type='kvm' name='coreduo' usable='yes'/> <cpu type='kvm' name='core2duo' usable='yes'/> - <cpu type='kvm' name='athlon' usable='no'/> + <cpu type='kvm' name='athlon' usable='no'> + <blocker name='mmxext'/> + <blocker name='3dnowext'/> + <blocker name='3dnow'/> + </cpu> <cpu type='kvm' name='Westmere' usable='yes'/> <cpu type='kvm' name='Skylake-Client' usable='yes'/> <cpu type='kvm' name='SandyBridge' usable='yes'/> <cpu type='kvm' name='Penryn' usable='yes'/> - <cpu type='kvm' name='Opteron_G5' usable='no'/> - <cpu type='kvm' name='Opteron_G4' usable='no'/> - <cpu type='kvm' name='Opteron_G3' usable='no'/> + <cpu type='kvm' name='Opteron_G5' usable='no'> + <blocker name='sse4a'/> + <blocker name='misalignsse'/> + <blocker name='xop'/> + <blocker name='fma4'/> + <blocker name='tbm'/> + </cpu> + <cpu type='kvm' name='Opteron_G4' usable='no'> + <blocker name='sse4a'/> + <blocker name='misalignsse'/> + <blocker name='xop'/> + <blocker name='fma4'/> + </cpu> + <cpu type='kvm' name='Opteron_G3' usable='no'> + <blocker name='sse4a'/> + <blocker name='misalignsse'/> + </cpu> <cpu type='kvm' name='Opteron_G2' usable='yes'/> <cpu type='kvm' name='Opteron_G1' usable='yes'/> <cpu type='kvm' name='Nehalem' usable='yes'/> @@ -243,10 +268,15 @@ <cpu type='kvm' name='Broadwell' usable='yes'/> <cpu type='kvm' name='Broadwell-noTSX' usable='yes'/> <cpu type='kvm' name='486' usable='yes'/> - <cpu type='tcg' name='host' usable='no'/> + <cpu type='tcg' name='host' usable='no'> + <blocker name='kvm'/> + </cpu> <cpu type='tcg' name='qemu64' usable='yes'/> <cpu type='tcg' name='qemu32' usable='yes'/> - <cpu type='tcg' name='phenom' usable='no'/> + <cpu type='tcg' name='phenom' usable='no'> + <blocker name='fxsr-opt'/> + <blocker name='npt'/> + </cpu> <cpu type='tcg' name='pentium3' usable='yes'/> <cpu type='tcg' name='pentium2' usable='yes'/> <cpu type='tcg' name='pentium' usable='yes'/> @@ -257,21 +287,111 @@ <cpu type='tcg' name='core2duo' usable='yes'/> <cpu type='tcg' name='athlon' usable='yes'/> <cpu type='tcg' name='Westmere' usable='yes'/> - <cpu type='tcg' name='Skylake-Client' usable='no'/> - <cpu type='tcg' name='SandyBridge' usable='no'/> + <cpu type='tcg' name='Skylake-Client' usable='no'> + <blocker name='fma'/> + <blocker name='pcid'/> + <blocker name='x2apic'/> + <blocker name='tsc-deadline'/> + <blocker name='avx'/> + <blocker name='f16c'/> + <blocker name='rdrand'/> + <blocker name='hle'/> + <blocker name='avx2'/> + <blocker name='invpcid'/> + <blocker name='rtm'/> + <blocker name='rdseed'/> + <blocker name='3dnowprefetch'/> + <blocker name='xsavec'/> + </cpu> + <cpu type='tcg' name='SandyBridge' usable='no'> + <blocker name='x2apic'/> + <blocker name='tsc-deadline'/> + <blocker name='avx'/> + </cpu> <cpu type='tcg' name='Penryn' usable='yes'/> - <cpu type='tcg' name='Opteron_G5' usable='no'/> - <cpu type='tcg' name='Opteron_G4' usable='no'/> - <cpu type='tcg' name='Opteron_G3' usable='no'/> + <cpu type='tcg' name='Opteron_G5' usable='no'> + <blocker name='fma'/> + <blocker name='avx'/> + <blocker name='f16c'/> + <blocker name='misalignsse'/> + <blocker name='3dnowprefetch'/> + <blocker name='xop'/> + <blocker name='fma4'/> + <blocker name='tbm'/> + </cpu> + <cpu type='tcg' name='Opteron_G4' usable='no'> + <blocker name='avx'/> + <blocker name='misalignsse'/> + <blocker name='3dnowprefetch'/> + <blocker name='xop'/> + <blocker name='fma4'/> + </cpu> + <cpu type='tcg' name='Opteron_G3' usable='no'> + <blocker name='misalignsse'/> + </cpu> <cpu type='tcg' name='Opteron_G2' usable='yes'/> <cpu type='tcg' name='Opteron_G1' usable='yes'/> <cpu type='tcg' name='Nehalem' usable='yes'/> - <cpu type='tcg' name='IvyBridge' usable='no'/> - <cpu type='tcg' name='Haswell' usable='no'/> - <cpu type='tcg' name='Haswell-noTSX' usable='no'/> + <cpu type='tcg' name='IvyBridge' usable='no'> + <blocker name='x2apic'/> + <blocker name='tsc-deadline'/> + <blocker name='avx'/> + <blocker name='f16c'/> + <blocker name='rdrand'/> + </cpu> + <cpu type='tcg' name='Haswell' usable='no'> + <blocker name='fma'/> + <blocker name='pcid'/> + <blocker name='x2apic'/> + <blocker name='tsc-deadline'/> + <blocker name='avx'/> + <blocker name='f16c'/> + <blocker name='rdrand'/> + <blocker name='hle'/> + <blocker name='avx2'/> + <blocker name='invpcid'/> + <blocker name='rtm'/> + </cpu> + <cpu type='tcg' name='Haswell-noTSX' usable='no'> + <blocker name='fma'/> + <blocker name='pcid'/> + <blocker name='x2apic'/> + <blocker name='tsc-deadline'/> + <blocker name='avx'/> + <blocker name='f16c'/> + <blocker name='rdrand'/> + <blocker name='avx2'/> + <blocker name='invpcid'/> + </cpu> <cpu type='tcg' name='Conroe' usable='yes'/> - <cpu type='tcg' name='Broadwell' usable='no'/> - <cpu type='tcg' name='Broadwell-noTSX' usable='no'/> + <cpu type='tcg' name='Broadwell' usable='no'> + <blocker name='fma'/> + <blocker name='pcid'/> + <blocker name='x2apic'/> + <blocker name='tsc-deadline'/> + <blocker name='avx'/> + <blocker name='f16c'/> + <blocker name='rdrand'/> + <blocker name='hle'/> + <blocker name='avx2'/> + <blocker name='invpcid'/> + <blocker name='rtm'/> + <blocker name='rdseed'/> + <blocker name='3dnowprefetch'/> + </cpu> + <cpu type='tcg' name='Broadwell-noTSX' usable='no'> + <blocker name='fma'/> + <blocker name='pcid'/> + <blocker name='x2apic'/> + <blocker name='tsc-deadline'/> + <blocker name='avx'/> + <blocker name='f16c'/> + <blocker name='rdrand'/> + <blocker name='avx2'/> + <blocker name='invpcid'/> + <blocker name='rdseed'/> + <blocker name='3dnowprefetch'/> + </cpu> <cpu type='tcg' name='486' usable='yes'/> <machine name='pc-i440fx-2.8' alias='pc' hotplugCpus='yes' maxCpus='255'/> <machine name='pc-0.12' hotplugCpus='yes' maxCpus='255'/> diff --git a/tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml index 3641d03323..c54ac89929 100644 --- a/tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml @@ -693,7 +693,14 @@ <cpu type='kvm' name='base' usable='yes'/> <cpu type='kvm' name='qemu64' usable='yes'/> <cpu type='kvm' name='qemu32' usable='yes'/> - <cpu type='kvm' name='phenom' usable='no'/> + <cpu type='kvm' name='phenom' usable='no'> + <blocker name='mmxext'/> + <blocker name='fxsr-opt'/> + <blocker name='3dnowext'/> + <blocker name='3dnow'/> + <blocker name='sse4a'/> + <blocker name='npt'/> + </cpu> <cpu type='kvm' name='pentium3' usable='yes'/> <cpu type='kvm' name='pentium2' usable='yes'/> <cpu type='kvm' name='pentium' usable='yes'/> @@ -702,14 +709,32 @@ <cpu type='kvm' name='kvm32' usable='yes'/> <cpu type='kvm' name='coreduo' usable='yes'/> <cpu type='kvm' name='core2duo' usable='yes'/> - <cpu type='kvm' name='athlon' usable='no'/> + <cpu type='kvm' name='athlon' usable='no'> + <blocker name='mmxext'/> + <blocker name='3dnowext'/> + <blocker name='3dnow'/> + </cpu> <cpu type='kvm' name='Westmere' usable='yes'/> <cpu type='kvm' name='Skylake-Client' usable='yes'/> <cpu type='kvm' name='SandyBridge' usable='yes'/> <cpu type='kvm' name='Penryn' usable='yes'/> - <cpu type='kvm' name='Opteron_G5' usable='no'/> - <cpu type='kvm' name='Opteron_G4' usable='no'/> - <cpu type='kvm' name='Opteron_G3' usable='no'/> + <cpu type='kvm' name='Opteron_G5' usable='no'> + <blocker name='sse4a'/> + <blocker name='misalignsse'/> + <blocker name='xop'/> + <blocker name='fma4'/> + <blocker name='tbm'/> + </cpu> + <cpu type='kvm' name='Opteron_G4' usable='no'> + <blocker name='sse4a'/> + <blocker name='misalignsse'/> + <blocker name='xop'/> + <blocker name='fma4'/> + </cpu> + <cpu type='kvm' name='Opteron_G3' usable='no'> + <blocker name='sse4a'/> + <blocker name='misalignsse'/> + </cpu> <cpu type='kvm' name='Opteron_G2' usable='yes'/> <cpu type='kvm' name='Opteron_G1' usable='yes'/> <cpu type='kvm' name='Nehalem' usable='yes'/> @@ -721,11 +746,16 @@ <cpu type='kvm' name='Broadwell-noTSX' usable='yes'/> <cpu type='kvm' name='486' usable='yes'/> <cpu type='tcg' name='max' usable='yes'/> - <cpu type='tcg' name='host' usable='no'/> + <cpu type='tcg' name='host' usable='no'> + <blocker name='kvm'/> + </cpu> <cpu type='tcg' name='base' usable='yes'/> <cpu type='tcg' name='qemu64' usable='yes'/> <cpu type='tcg' name='qemu32' usable='yes'/> - <cpu type='tcg' name='phenom' usable='no'/> + <cpu type='tcg' name='phenom' usable='no'> + <blocker name='fxsr-opt'/> + <blocker name='npt'/> + </cpu> <cpu type='tcg' name='pentium3' usable='yes'/> <cpu type='tcg' name='pentium2' usable='yes'/> <cpu type='tcg' name='pentium' usable='yes'/> @@ -736,21 +766,111 @@ <cpu type='tcg' name='core2duo' usable='yes'/> <cpu type='tcg' name='athlon' usable='yes'/> <cpu type='tcg' name='Westmere' usable='yes'/> - <cpu type='tcg' name='Skylake-Client' usable='no'/> - <cpu type='tcg' name='SandyBridge' usable='no'/> + <cpu type='tcg' name='Skylake-Client' usable='no'> + <blocker name='fma'/> + <blocker name='pcid'/> + <blocker name='x2apic'/> + <blocker name='tsc-deadline'/> + <blocker name='avx'/> + <blocker name='f16c'/> + <blocker name='rdrand'/> + <blocker name='hle'/> + <blocker name='avx2'/> + <blocker name='invpcid'/> + <blocker name='rtm'/> + <blocker name='rdseed'/> + <blocker name='3dnowprefetch'/> + <blocker name='xsavec'/> + </cpu> + <cpu type='tcg' name='SandyBridge' usable='no'> + <blocker name='x2apic'/> + <blocker name='tsc-deadline'/> + <blocker name='avx'/> + </cpu> <cpu type='tcg' name='Penryn' usable='yes'/> - <cpu type='tcg' name='Opteron_G5' usable='no'/> - <cpu type='tcg' name='Opteron_G4' usable='no'/> - <cpu type='tcg' name='Opteron_G3' usable='no'/> + <cpu type='tcg' name='Opteron_G5' usable='no'> + <blocker name='fma'/> + <blocker name='avx'/> + <blocker name='f16c'/> + <blocker name='misalignsse'/> + <blocker name='3dnowprefetch'/> + <blocker name='xop'/> + <blocker name='fma4'/> + <blocker name='tbm'/> + </cpu> + <cpu type='tcg' name='Opteron_G4' usable='no'> + <blocker name='avx'/> + <blocker name='misalignsse'/> + <blocker name='3dnowprefetch'/> + <blocker name='xop'/> + <blocker name='fma4'/> + </cpu> + <cpu type='tcg' name='Opteron_G3' usable='no'> + <blocker name='misalignsse'/> + </cpu> <cpu type='tcg' name='Opteron_G2' usable='yes'/> <cpu type='tcg' name='Opteron_G1' usable='yes'/> <cpu type='tcg' name='Nehalem' usable='yes'/> - <cpu type='tcg' name='IvyBridge' usable='no'/> - <cpu type='tcg' name='Haswell' usable='no'/> - <cpu type='tcg' name='Haswell-noTSX' usable='no'/> + <cpu type='tcg' name='IvyBridge' usable='no'> + <blocker name='x2apic'/> + <blocker name='tsc-deadline'/> + <blocker name='avx'/> + <blocker name='f16c'/> + <blocker name='rdrand'/> + </cpu> + <cpu type='tcg' name='Haswell' usable='no'> + <blocker name='fma'/> + <blocker name='pcid'/> + <blocker name='x2apic'/> + <blocker name='tsc-deadline'/> + <blocker name='avx'/> + <blocker name='f16c'/> + <blocker name='rdrand'/> + <blocker name='hle'/> + <blocker name='avx2'/> + <blocker name='invpcid'/> + <blocker name='rtm'/> + </cpu> + <cpu type='tcg' name='Haswell-noTSX' usable='no'> + <blocker name='fma'/> + <blocker name='pcid'/> + <blocker name='x2apic'/> + <blocker name='tsc-deadline'/> + <blocker name='avx'/> + <blocker name='f16c'/> + <blocker name='rdrand'/> + <blocker name='avx2'/> + <blocker name='invpcid'/> + </cpu> <cpu type='tcg' name='Conroe' usable='yes'/> - <cpu type='tcg' name='Broadwell' usable='no'/> - <cpu type='tcg' name='Broadwell-noTSX' usable='no'/> + <cpu type='tcg' name='Broadwell' usable='no'> + <blocker name='fma'/> + <blocker name='pcid'/> + <blocker name='x2apic'/> + <blocker name='tsc-deadline'/> + <blocker name='avx'/> + <blocker name='f16c'/> + <blocker name='rdrand'/> + <blocker name='hle'/> + <blocker name='avx2'/> + <blocker name='invpcid'/> + <blocker name='rtm'/> + <blocker name='rdseed'/> + <blocker name='3dnowprefetch'/> + </cpu> + <cpu type='tcg' name='Broadwell-noTSX' usable='no'> + <blocker name='fma'/> + <blocker name='pcid'/> + <blocker name='x2apic'/> + <blocker name='tsc-deadline'/> + <blocker name='avx'/> + <blocker name='f16c'/> + <blocker name='rdrand'/> + <blocker name='avx2'/> + <blocker name='invpcid'/> + <blocker name='rdseed'/> + <blocker name='3dnowprefetch'/> + </cpu> <cpu type='tcg' name='486' usable='yes'/> <machine name='pc-i440fx-2.9' alias='pc' hotplugCpus='yes' maxCpus='255'/> <machine name='pc-0.12' hotplugCpus='yes' maxCpus='255'/> -- 2.14.2

On 10/04/2017 10:58 AM, Jiri Denemark wrote:
query-cpu-definitions QMP command returns a list of unavailable features which prevent CPU models from being usable on the current host. So far we only checked whether the list was empty to mark CPU models as (un)usable. This patch parses all unavailable features for each CPU model and stores them in virDomainCapsCPUModel as a list of usability blockers.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/qemu/qemu_capabilities.c | 2 +- src/qemu/qemu_monitor.c | 2 + src/qemu/qemu_monitor.h | 1 + src/qemu/qemu_monitor_json.c | 26 +- tests/qemucapabilitiesdata/caps_2.10.0.s390x.xml | 1102 +++++++++++++++++++-- tests/qemucapabilitiesdata/caps_2.10.0.x86_64.xml | 236 ++++- tests/qemucapabilitiesdata/caps_2.8.0.x86_64.xml | 154 ++- tests/qemucapabilitiesdata/caps_2.9.0.x86_64.xml | 154 ++- 8 files changed, 1556 insertions(+), 121 deletions(-)
[...]
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index c63d250d36..fcdd58b369 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -5076,6 +5076,8 @@ qemuMonitorJSONGetCPUDefinitions(qemuMonitorPtr mon,
if (virJSONValueObjectHasKey(child, "unavailable-features")) { virJSONValuePtr blockers; + size_t j; + int len;
blockers = virJSONValueObjectGetArray(child, "unavailable-features"); @@ -5086,10 +5088,32 @@ qemuMonitorJSONGetCPUDefinitions(qemuMonitorPtr mon, goto cleanup; }
- if (virJSONValueArraySize(blockers) > 0) + len = virJSONValueArraySize(blockers); + + if (len != 0)
At this point len is either 0 (empty) or > 0 because if it was < 0 the virJSONValueObjectGetArray would have already caused a failure, right? So why not : if (len == 0) { cpu->usable = VIR_TRISTATE_BOOL_YES; continue; } cpu->usable = VIR_TRISTATE_BOOL_NO; if (VIR_ALLOC_N(cpu->blockers, len + 1) < 0) ...
cpu->usable = VIR_TRISTATE_BOOL_NO; else cpu->usable = VIR_TRISTATE_BOOL_YES; + + if (len > 0 && VIR_ALLOC_N(cpu->blockers, len + 1) < 0) + goto cleanup; + + for (j = 0; j < len; j++) { + virJSONValuePtr blocker = virJSONValueArrayGet(blockers, j); + char *name;
virJSONValueArrayGet can return NULL, but that shouldn't affect us since blockers is an ARRAY and there's no way j >= len...
+ + if (blocker->type != VIR_JSON_TYPE_STRING) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("unexpected value in unavailable-features " + "array")); + goto cleanup; + }
...but because of this check...
+ + if (VIR_STRDUP(name, virJSONValueGetString(blocker)) < 0) ...wouldn't virJSONValueGetString return a non NULL string, so...
+ goto cleanup; + + cpu->blockers[j] = name;
...why not just go direct to cpu->blockers[j]? Or did you come across something in testing that had a NULL return from the call to virJSONValueGetString(blocker)? Maybe a NULL entry should just be ignored so as to not tank the whole thing using the logic that if a blocker isn't there, by name, then is it a blocker?
+ } } }
Reviewed-by: John Ferlan <jferlan@redhat.com> John

On Thu, Oct 12, 2017 at 07:25:59 -0400, John Ferlan wrote:
On 10/04/2017 10:58 AM, Jiri Denemark wrote:
query-cpu-definitions QMP command returns a list of unavailable features which prevent CPU models from being usable on the current host. So far we only checked whether the list was empty to mark CPU models as (un)usable. This patch parses all unavailable features for each CPU model and stores them in virDomainCapsCPUModel as a list of usability blockers. [...]
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index c63d250d36..fcdd58b369 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -5086,10 +5088,32 @@ qemuMonitorJSONGetCPUDefinitions(qemuMonitorPtr mon, goto cleanup; }
- if (virJSONValueArraySize(blockers) > 0) + len = virJSONValueArraySize(blockers); + + if (len != 0)
At this point len is either 0 (empty) or > 0 because if it was < 0 the virJSONValueObjectGetArray would have already caused a failure, right?
So why not :
if (len == 0) { cpu->usable = VIR_TRISTATE_BOOL_YES; continue; }
cpu->usable = VIR_TRISTATE_BOOL_NO; if (VIR_ALLOC_N(cpu->blockers, len + 1) < 0)
OK
cpu->usable = VIR_TRISTATE_BOOL_NO; else cpu->usable = VIR_TRISTATE_BOOL_YES; + + if (len > 0 && VIR_ALLOC_N(cpu->blockers, len + 1) < 0) + goto cleanup; + + for (j = 0; j < len; j++) { + virJSONValuePtr blocker = virJSONValueArrayGet(blockers, j); + char *name;
virJSONValueArrayGet can return NULL, but that shouldn't affect us since blockers is an ARRAY and there's no way j >= len...
Right.
+ + if (blocker->type != VIR_JSON_TYPE_STRING) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("unexpected value in unavailable-features " + "array")); + goto cleanup; + }
...but because of this check...
+ + if (VIR_STRDUP(name, virJSONValueGetString(blocker)) < 0) ...wouldn't virJSONValueGetString return a non NULL string, so...
Sure, but this is not checking whether virJSONValueGetString returns NULL or not, this checks whether we successfully made a copy of the blocker string.
+ goto cleanup; + + cpu->blockers[j] = name;
...why not just go direct to cpu->blockers[j]? Or did you come across something in testing that had a NULL return from the call to virJSONValueGetString(blocker)?
Maybe a NULL entry should just be ignored so as to not tank the whole thing using the logic that if a blocker isn't there, by name, then is it a blocker?
I'm not really sure what you were trying to say. Is the temporary name variable confusing you? No problem, it's not needed at all, I changed the code so that VIR_STRDUP stores the result directly in cpu->blockers[j]. Jirka

On 10/13/2017 10:39 AM, Jiri Denemark wrote:
On Thu, Oct 12, 2017 at 07:25:59 -0400, John Ferlan wrote:
On 10/04/2017 10:58 AM, Jiri Denemark wrote:
query-cpu-definitions QMP command returns a list of unavailable features which prevent CPU models from being usable on the current host. So far we only checked whether the list was empty to mark CPU models as (un)usable. This patch parses all unavailable features for each CPU model and stores them in virDomainCapsCPUModel as a list of usability blockers. [...]
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index c63d250d36..fcdd58b369 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -5086,10 +5088,32 @@ qemuMonitorJSONGetCPUDefinitions(qemuMonitorPtr mon, goto cleanup; }
- if (virJSONValueArraySize(blockers) > 0) + len = virJSONValueArraySize(blockers); + + if (len != 0)
At this point len is either 0 (empty) or > 0 because if it was < 0 the virJSONValueObjectGetArray would have already caused a failure, right?
So why not :
if (len == 0) { cpu->usable = VIR_TRISTATE_BOOL_YES; continue; }
cpu->usable = VIR_TRISTATE_BOOL_NO; if (VIR_ALLOC_N(cpu->blockers, len + 1) < 0)
OK
cpu->usable = VIR_TRISTATE_BOOL_NO; else cpu->usable = VIR_TRISTATE_BOOL_YES; + + if (len > 0 && VIR_ALLOC_N(cpu->blockers, len + 1) < 0) + goto cleanup; + + for (j = 0; j < len; j++) { + virJSONValuePtr blocker = virJSONValueArrayGet(blockers, j); + char *name;
virJSONValueArrayGet can return NULL, but that shouldn't affect us since blockers is an ARRAY and there's no way j >= len...
Right.
+ + if (blocker->type != VIR_JSON_TYPE_STRING) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("unexpected value in unavailable-features " + "array")); + goto cleanup; + }
...but because of this check...
+ + if (VIR_STRDUP(name, virJSONValueGetString(blocker)) < 0) ...wouldn't virJSONValueGetString return a non NULL string, so...
Sure, but this is not checking whether virJSONValueGetString returns NULL or not, this checks whether we successfully made a copy of the blocker string.
+ goto cleanup; + + cpu->blockers[j] = name;
...why not just go direct to cpu->blockers[j]? Or did you come across something in testing that had a NULL return from the call to virJSONValueGetString(blocker)?
Maybe a NULL entry should just be ignored so as to not tank the whole thing using the logic that if a blocker isn't there, by name, then is it a blocker?
I'm not really sure what you were trying to say. Is the temporary name variable confusing you? No problem, it's not needed at all, I changed the code so that VIR_STRDUP stores the result directly in cpu->blockers[j].
Jirka
I think the first comment after ...why was more what I was wondering (vis-a-vis the usage of a local @name when direct assignment would also work) ... then I started thinking was there some edge condition that you were avoiding hence the extra cruft. It wouldn't seem right that you'd get a NULL blockers entry from QEMU, but then again making that assumption can be risky too (since VIR_STRDUP(xxx, NULL), just assigns NULL to xxx and doesn't cause an error. No matter - just me overthinking and overtyping. John

All APIs which expect a list of CPU models supported by hypervisors were switched from char **models and int models to just accept a pointer to virDomainCapsCPUModels object stored in domain capabilities. This avoids the need to transform virDomainCapsCPUModelsPtr into a NULL-terminated list of model names and also allows the various cpu driver APIs to access additional details (such as its usability) about each CPU model. Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/cpu/cpu.c | 78 +++++++++++++----------------------- src/cpu/cpu.h | 28 +++++-------- src/cpu/cpu_arm.c | 3 +- src/cpu/cpu_ppc64.c | 13 +++--- src/cpu/cpu_x86.c | 25 +++++------- src/libxl/libxl_capabilities.c | 2 +- src/libxl/libxl_driver.c | 2 +- src/qemu/qemu_capabilities.c | 63 ++++++------------------------ src/qemu/qemu_capabilities.h | 6 +-- src/qemu/qemu_driver.c | 2 +- src/qemu/qemu_process.c | 9 +---- src/test/test_driver.c | 2 +- tests/cputest.c | 89 ++++++++++++++++++++++++++++++------------ 13 files changed, 138 insertions(+), 184 deletions(-) diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index dc72ed42d8..842b0db2cd 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -192,7 +192,6 @@ virCPUCompare(virArch arch, * @cpu: CPU definition stub to be filled in * @data: internal CPU data to be decoded into @cpu definition * @models: list of CPU models that can be considered when decoding @data - * @nmodels: number of CPU models in @models * @preferred: CPU models that should be used if possible * * Decodes internal CPU data into a CPU definition consisting of a CPU model @@ -214,24 +213,17 @@ virCPUCompare(virArch arch, int cpuDecode(virCPUDefPtr cpu, const virCPUData *data, - const char **models, - unsigned int nmodels, + virDomainCapsCPUModelsPtr models, const char *preferred) { struct cpuArchDriver *driver; - VIR_DEBUG("cpu=%p, data=%p, nmodels=%u, preferred=%s", - cpu, data, nmodels, NULLSTR(preferred)); + VIR_DEBUG("cpu=%p, data=%p, models=%p, preferred=%s", + cpu, data, models, NULLSTR(preferred)); if (models) { size_t i; - for (i = 0; i < nmodels; i++) - VIR_DEBUG("models[%zu]=%s", i, NULLSTR(models[i])); - } - - if (models == NULL && nmodels != 0) { - virReportError(VIR_ERR_INVALID_ARG, "%s", - _("nonzero nmodels doesn't match with NULL models")); - return -1; + for (i = 0; i < models->nmodels; i++) + VIR_DEBUG("models[%zu]=%s", i, models->models[i].name); } if (cpu->type > VIR_CPU_TYPE_GUEST || @@ -251,7 +243,7 @@ cpuDecode(virCPUDefPtr cpu, return -1; } - return driver->decode(cpu, data, models, nmodels, preferred); + return driver->decode(cpu, data, models, preferred); } @@ -384,7 +376,6 @@ virCPUGetHostIsSupported(virArch arch) * @type: requested type of the CPU * @nodeInfo: simplified CPU topology (optional) * @models: list of CPU models that can be considered for host CPU - * @nmodels: number of CPU models in @models * * Create CPU definition describing the host's CPU. * @@ -412,15 +403,14 @@ virCPUDefPtr virCPUGetHost(virArch arch, virCPUType type, virNodeInfoPtr nodeInfo, - const char **models, - unsigned int nmodels) + virDomainCapsCPUModelsPtr models) { struct cpuArchDriver *driver; virCPUDefPtr cpu = NULL; - VIR_DEBUG("arch=%s, type=%s, nodeInfo=%p, models=%p, nmodels=%u", + VIR_DEBUG("arch=%s, type=%s, nodeInfo=%p, models=%p", virArchToString(arch), virCPUTypeToString(type), nodeInfo, - models, nmodels); + models); if (!(driver = cpuGetSubDriver(arch))) return NULL; @@ -462,7 +452,7 @@ virCPUGetHost(virArch arch, * filled in. */ if (driver->getHost) { - if (driver->getHost(cpu, models, nmodels) < 0 && + if (driver->getHost(cpu, models) < 0 && !nodeInfo) goto error; } else if (nodeInfo) { @@ -491,7 +481,7 @@ virCPUProbeHost(virArch arch) if (virCapabilitiesGetNodeInfo(&nodeinfo)) return NULL; - return virCPUGetHost(arch, VIR_CPU_TYPE_HOST, &nodeinfo, NULL, 0); + return virCPUGetHost(arch, VIR_CPU_TYPE_HOST, &nodeinfo, NULL); } @@ -501,11 +491,10 @@ virCPUProbeHost(virArch arch) * @cpus: list of host CPU definitions * @ncpus: number of CPUs in @cpus * @models: list of CPU models that can be considered for the baseline CPU - * @nmodels: number of CPU models in @models * @migratable: requests non-migratable features to be removed from the result * * Computes the most feature-rich CPU which is compatible with all given - * host CPUs. If @models array is NULL, all models supported by libvirt will + * host CPUs. If @models is NULL, all models supported by libvirt will * be considered when computing the baseline CPU model, otherwise the baseline * CPU model will be one of the provided CPU @models. * @@ -514,21 +503,20 @@ virCPUProbeHost(virArch arch) virCPUDefPtr cpuBaseline(virCPUDefPtr *cpus, unsigned int ncpus, - const char **models, - unsigned int nmodels, + virDomainCapsCPUModelsPtr models, bool migratable) { struct cpuArchDriver *driver; size_t i; - VIR_DEBUG("ncpus=%u, nmodels=%u", ncpus, nmodels); + VIR_DEBUG("ncpus=%u", ncpus); if (cpus) { for (i = 0; i < ncpus; i++) VIR_DEBUG("cpus[%zu]=%p", i, cpus[i]); } if (models) { - for (i = 0; i < nmodels; i++) - VIR_DEBUG("models[%zu]=%s", i, NULLSTR(models[i])); + for (i = 0; i < models->nmodels; i++) + VIR_DEBUG("models[%zu]=%s", i, models->models[i].name); } if (cpus == NULL && ncpus != 0) { @@ -555,12 +543,6 @@ cpuBaseline(virCPUDefPtr *cpus, } } - if (models == NULL && nmodels != 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, - "%s", _("nonzero nmodels doesn't match with NULL models")); - return NULL; - } - if ((driver = cpuGetSubDriver(cpus[0]->arch)) == NULL) return NULL; @@ -571,7 +553,7 @@ cpuBaseline(virCPUDefPtr *cpus, return NULL; } - return driver->baseline(cpus, ncpus, models, nmodels, migratable); + return driver->baseline(cpus, ncpus, models, migratable); } @@ -844,25 +826,23 @@ virCPUDataParse(const char *xmlStr) * * @model: CPU model to be checked * @models: list of supported CPU models - * @nmodels: number of models in @models * * Checks whether @model can be found in the list of supported @models. - * If @models is empty, all models are supported. + * If @models is NULL, all models are supported. * * Returns true if @model is supported, false otherwise. */ bool virCPUModelIsAllowed(const char *model, - const char **models, - unsigned int nmodels) + virDomainCapsCPUModelsPtr models) { size_t i; - if (!models || !nmodels) + if (!models) return true; - for (i = 0; i < nmodels; i++) { - if (models[i] && STREQ(models[i], model)) + for (i = 0; i < models->nmodels; i++) { + if (STREQ(models->models[i].name, model)) return true; } return false; @@ -908,8 +888,7 @@ virCPUGetModels(virArch arch, char ***models) * * @arch: CPU architecture * @cpu: CPU definition to be translated - * @models: NULL-terminated list of allowed CPU models (NULL if all are allowed) - * @nmodels: number of CPU models in @models + * @models: list of allowed CPU models (NULL if all are allowed) * * Translates @cpu model (if allowed by @cpu->fallback) to a closest CPU model * from @models list. @@ -922,13 +901,12 @@ virCPUGetModels(virArch arch, char ***models) int virCPUTranslate(virArch arch, virCPUDefPtr cpu, - const char **models, - unsigned int nmodels) + virDomainCapsCPUModelsPtr models) { struct cpuArchDriver *driver; - VIR_DEBUG("arch=%s, cpu=%p, model=%s, models=%p, nmodels=%u", - virArchToString(arch), cpu, NULLSTR(cpu->model), models, nmodels); + VIR_DEBUG("arch=%s, cpu=%p, model=%s, models=%p", + virArchToString(arch), cpu, NULLSTR(cpu->model), models); if (!(driver = cpuGetSubDriver(arch))) return -1; @@ -937,7 +915,7 @@ virCPUTranslate(virArch arch, cpu->mode == VIR_CPU_MODE_HOST_PASSTHROUGH) return 0; - if (virCPUModelIsAllowed(cpu->model, models, nmodels)) + if (virCPUModelIsAllowed(cpu->model, models)) return 0; if (cpu->fallback != VIR_CPU_FALLBACK_ALLOW) { @@ -954,7 +932,7 @@ virCPUTranslate(virArch arch, return -1; } - if (driver->translate(cpu, models, nmodels) < 0) + if (driver->translate(cpu, models) < 0) return -1; VIR_DEBUG("model=%s", NULLSTR(cpu->model)); diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index 5daff186c4..d325fe3d04 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -27,6 +27,7 @@ # include "virerror.h" # include "datatypes.h" # include "virarch.h" +# include "domain_capabilities.h" # include "cpu_conf.h" # include "cpu_x86_data.h" # include "cpu_ppc64_data.h" @@ -52,8 +53,7 @@ typedef virCPUCompareResult typedef int (*cpuArchDecode) (virCPUDefPtr cpu, const virCPUData *data, - const char **models, - unsigned int nmodels, + virDomainCapsCPUModelsPtr models, const char *preferred); typedef int @@ -71,14 +71,12 @@ typedef void typedef int (*virCPUArchGetHost)(virCPUDefPtr cpu, - const char **models, - unsigned int nmodels); + virDomainCapsCPUModelsPtr models); typedef virCPUDefPtr (*cpuArchBaseline) (virCPUDefPtr *cpus, unsigned int ncpus, - const char **models, - unsigned int nmodels, + virDomainCapsCPUModelsPtr models, bool migratable); typedef int @@ -109,8 +107,7 @@ typedef int typedef int (*virCPUArchTranslate)(virCPUDefPtr cpu, - const char **models, - unsigned int nmodels); + virDomainCapsCPUModelsPtr models); typedef int (*virCPUArchConvertLegacy)(virCPUDefPtr cpu); @@ -165,8 +162,7 @@ virCPUCompare(virArch arch, int cpuDecode (virCPUDefPtr cpu, const virCPUData *data, - const char **models, - unsigned int nmodels, + virDomainCapsCPUModelsPtr models, const char *preferred) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); @@ -194,8 +190,7 @@ virCPUDefPtr virCPUGetHost(virArch arch, virCPUType type, virNodeInfoPtr nodeInfo, - const char **models, - unsigned int nmodels); + virDomainCapsCPUModelsPtr models); virCPUDefPtr virCPUProbeHost(virArch arch); @@ -203,8 +198,7 @@ virCPUProbeHost(virArch arch); virCPUDefPtr cpuBaseline (virCPUDefPtr *cpus, unsigned int ncpus, - const char **models, - unsigned int nmodels, + virDomainCapsCPUModelsPtr models, bool migratable); int @@ -235,8 +229,7 @@ virCPUDataCheckFeature(const virCPUData *data, bool virCPUModelIsAllowed(const char *model, - const char **models, - unsigned int nmodels) + virDomainCapsCPUModelsPtr models) ATTRIBUTE_NONNULL(1); int @@ -245,8 +238,7 @@ virCPUGetModels(virArch arch, char ***models); int virCPUTranslate(virArch arch, virCPUDefPtr cpu, - const char **models, - unsigned int nmodels) + virDomainCapsCPUModelsPtr models) ATTRIBUTE_NONNULL(2); int diff --git a/src/cpu/cpu_arm.c b/src/cpu/cpu_arm.c index 474777656c..44cb4fea68 100644 --- a/src/cpu/cpu_arm.c +++ b/src/cpu/cpu_arm.c @@ -75,8 +75,7 @@ virCPUarmUpdate(virCPUDefPtr guest, static virCPUDefPtr armBaseline(virCPUDefPtr *cpus, unsigned int ncpus ATTRIBUTE_UNUSED, - const char **models ATTRIBUTE_UNUSED, - unsigned int nmodels ATTRIBUTE_UNUSED, + virDomainCapsCPUModelsPtr models ATTRIBUTE_UNUSED, bool migratable ATTRIBUTE_UNUSED) { virCPUDefPtr cpu = NULL; diff --git a/src/cpu/cpu_ppc64.c b/src/cpu/cpu_ppc64.c index b58e80a647..e5ae3a609f 100644 --- a/src/cpu/cpu_ppc64.c +++ b/src/cpu/cpu_ppc64.c @@ -663,8 +663,7 @@ virCPUppc64Compare(virCPUDefPtr host, static int ppc64DriverDecode(virCPUDefPtr cpu, const virCPUData *data, - const char **models, - unsigned int nmodels, + virDomainCapsCPUModelsPtr models, const char *preferred ATTRIBUTE_UNUSED) { int ret = -1; @@ -681,7 +680,7 @@ ppc64DriverDecode(virCPUDefPtr cpu, goto cleanup; } - if (!virCPUModelIsAllowed(model->name, models, nmodels)) { + if (!virCPUModelIsAllowed(model->name, models)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("CPU model %s is not supported by hypervisor"), model->name); @@ -714,8 +713,7 @@ virCPUppc64DataFree(virCPUDataPtr data) static int virCPUppc64GetHost(virCPUDefPtr cpu, - const char **models, - unsigned int nmodels) + virDomainCapsCPUModelsPtr models) { virCPUDataPtr cpuData = NULL; virCPUppc64Data *data; @@ -737,7 +735,7 @@ virCPUppc64GetHost(virCPUDefPtr cpu, #endif data->pvr[0].mask = 0xfffffffful; - ret = ppc64DriverDecode(cpu, cpuData, models, nmodels, NULL); + ret = ppc64DriverDecode(cpu, cpuData, models, NULL); cleanup: virCPUppc64DataFree(cpuData); @@ -766,8 +764,7 @@ virCPUppc64Update(virCPUDefPtr guest, static virCPUDefPtr ppc64DriverBaseline(virCPUDefPtr *cpus, unsigned int ncpus, - const char **models ATTRIBUTE_UNUSED, - unsigned int nmodels ATTRIBUTE_UNUSED, + virDomainCapsCPUModelsPtr models ATTRIBUTE_UNUSED, bool migratable ATTRIBUTE_UNUSED) { struct ppc64_map *map; diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c index 5ce205f9c1..3f9e83ca72 100644 --- a/src/cpu/cpu_x86.c +++ b/src/cpu/cpu_x86.c @@ -1820,8 +1820,7 @@ x86DataFilterTSX(virCPUx86Data *data, static int x86Decode(virCPUDefPtr cpu, const virCPUx86Data *cpuData, - const char **models, - unsigned int nmodels, + virDomainCapsCPUModelsPtr models, const char *preferred, bool migratable) { @@ -1855,7 +1854,7 @@ x86Decode(virCPUDefPtr cpu, */ for (i = map->nmodels - 1; i >= 0; i--) { candidate = map->models[i]; - if (!virCPUModelIsAllowed(candidate->name, models, nmodels)) { + if (!virCPUModelIsAllowed(candidate->name, models)) { if (preferred && STREQ(candidate->name, preferred)) { if (cpu->fallback != VIR_CPU_FALLBACK_ALLOW) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, @@ -1946,11 +1945,10 @@ x86Decode(virCPUDefPtr cpu, static int x86DecodeCPUData(virCPUDefPtr cpu, const virCPUData *data, - const char **models, - unsigned int nmodels, + virDomainCapsCPUModelsPtr models, const char *preferred) { - return x86Decode(cpu, &data->data.x86, models, nmodels, preferred, false); + return x86Decode(cpu, &data->data.x86, models, preferred, false); } @@ -2402,8 +2400,7 @@ cpuidSet(uint32_t base, virCPUDataPtr data) static int virCPUx86GetHost(virCPUDefPtr cpu, - const char **models, - unsigned int nmodels) + virDomainCapsCPUModelsPtr models) { virCPUDataPtr cpuData = NULL; int ret = -1; @@ -2415,7 +2412,7 @@ virCPUx86GetHost(virCPUDefPtr cpu, cpuidSet(CPUX86_EXTENDED, cpuData) < 0) goto cleanup; - ret = x86DecodeCPUData(cpu, cpuData, models, nmodels, NULL); + ret = x86DecodeCPUData(cpu, cpuData, models, NULL); cleanup: virCPUx86DataFree(cpuData); @@ -2427,8 +2424,7 @@ virCPUx86GetHost(virCPUDefPtr cpu, static virCPUDefPtr x86Baseline(virCPUDefPtr *cpus, unsigned int ncpus, - const char **models, - unsigned int nmodels, + virDomainCapsCPUModelsPtr models, bool migratable) { virCPUx86MapPtr map = NULL; @@ -2523,7 +2519,7 @@ x86Baseline(virCPUDefPtr *cpus, virCPUx86DataAddCPUIDInt(&base_model->data, &vendor->cpuid) < 0) goto error; - if (x86Decode(cpu, &base_model->data, models, nmodels, modelName, migratable) < 0) + if (x86Decode(cpu, &base_model->data, models, modelName, migratable) < 0) goto error; if (STREQ_NULLABLE(cpu->model, modelName)) @@ -2805,8 +2801,7 @@ virCPUx86GetModels(char ***models) static int virCPUx86Translate(virCPUDefPtr cpu, - const char **models, - unsigned int nmodels) + virDomainCapsCPUModelsPtr models) { virCPUDefPtr translated = NULL; virCPUx86MapPtr map; @@ -2830,7 +2825,7 @@ virCPUx86Translate(virCPUDefPtr cpu, if (!(translated = virCPUDefCopyWithoutModel(cpu))) goto cleanup; - if (x86Decode(translated, &model->data, models, nmodels, NULL, false) < 0) + if (x86Decode(translated, &model->data, models, NULL, false) < 0) goto cleanup; for (i = 0; i < cpu->nfeatures; i++) { diff --git a/src/libxl/libxl_capabilities.c b/src/libxl/libxl_capabilities.c index e0959202b3..4def561143 100644 --- a/src/libxl/libxl_capabilities.c +++ b/src/libxl/libxl_capabilities.c @@ -192,7 +192,7 @@ libxlCapsInitCPU(virCapsPtr caps, libxl_physinfo *phy_info, ret = 0; if (!(data = libxlCapsNodeData(cpu, phy_info->hw_cap, version)) || - cpuDecode(cpu, data, NULL, 0, NULL) < 0) { + cpuDecode(cpu, data, NULL, NULL) < 0) { VIR_WARN("Failed to initialize host cpu features"); goto error; } diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index bf3625e34a..34235fc57d 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -6463,7 +6463,7 @@ libxlConnectBaselineCPU(virConnectPtr conn, if (!(cpus = virCPUDefListParse(xmlCPUs, ncpus, VIR_CPU_TYPE_HOST))) goto cleanup; - if (!(cpu = cpuBaseline(cpus, ncpus, NULL, 0, + if (!(cpu = cpuBaseline(cpus, ncpus, NULL, !!(flags & VIR_CONNECT_BASELINE_CPU_MIGRATABLE)))) goto cleanup; diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 7ddc6cafd4..225cee4ef9 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -1167,18 +1167,8 @@ virQEMUCapsProbeHostCPUForEmulator(virArch hostArch, virQEMUCapsPtr qemuCaps, virDomainVirtType type) { - size_t nmodels; - char **models; - virCPUDefPtr cpu; - - if (virQEMUCapsGetCPUDefinitions(qemuCaps, type, &models, &nmodels) < 0) - return NULL; - - cpu = virCPUGetHost(hostArch, VIR_CPU_TYPE_GUEST, NULL, - (const char **) models, nmodels); - - virStringListFreeCount(models, nmodels); - return cpu; + return virCPUGetHost(hostArch, VIR_CPU_TYPE_GUEST, NULL, + virQEMUCapsGetCPUDefinitions(qemuCaps, type)); } @@ -2532,45 +2522,16 @@ virQEMUCapsAddCPUDefinitions(virQEMUCapsPtr qemuCaps, } -int +virDomainCapsCPUModelsPtr virQEMUCapsGetCPUDefinitions(virQEMUCapsPtr qemuCaps, - virDomainVirtType type, - char ***names, - size_t *count) + virDomainVirtType type) { - size_t i; - char **models = NULL; - virDomainCapsCPUModelsPtr cpus; - - *count = 0; - if (names) - *names = NULL; - if (type == VIR_DOMAIN_VIRT_KVM) - cpus = qemuCaps->kvmCPUModels; + return qemuCaps->kvmCPUModels; else - cpus = qemuCaps->tcgCPUModels; + return qemuCaps->tcgCPUModels; - if (!cpus) - return 0; - - if (names && VIR_ALLOC_N(models, cpus->nmodels) < 0) - return -1; - - for (i = 0; i < cpus->nmodels; i++) { - virDomainCapsCPUModelPtr cpu = cpus->models + i; - if (models && VIR_STRDUP(models[i], cpu->name) < 0) - goto error; - } - - if (names) - *names = models; - *count = cpus->nmodels; - return 0; - - error: - virStringListFreeCount(models, i); - return -1; + return NULL; } @@ -3392,8 +3353,6 @@ virQEMUCapsInitCPUModelX86(virQEMUCapsPtr qemuCaps, virCPUDataPtr data = NULL; unsigned long long sigFamily = 0; unsigned long long sigModel = 0; - size_t nmodels = 0; - char **models = NULL; int ret = -1; size_t i; @@ -3438,15 +3397,15 @@ virQEMUCapsInitCPUModelX86(virQEMUCapsPtr qemuCaps, if (virCPUx86DataSetSignature(data, sigFamily, sigModel) < 0) goto cleanup; - if (virQEMUCapsGetCPUDefinitions(qemuCaps, type, &models, &nmodels) < 0 || - cpuDecode(cpu, data, (const char **) models, nmodels, NULL) < 0) + if (cpuDecode(cpu, data, + virQEMUCapsGetCPUDefinitions(qemuCaps, type), + NULL) < 0) goto cleanup; ret = 0; cleanup: virCPUDataFree(data); - virStringListFreeCount(models, nmodels); return ret; } @@ -3532,7 +3491,7 @@ virQEMUCapsInitHostCPUModel(virQEMUCapsPtr qemuCaps, } else if (type == VIR_DOMAIN_VIRT_KVM && virCPUGetHostIsSupported(qemuCaps->arch)) { if (!(fullCPU = virCPUGetHost(qemuCaps->arch, VIR_CPU_TYPE_GUEST, - NULL, NULL, 0))) + NULL, NULL))) goto error; for (i = 0; i < cpu->nfeatures; i++) { diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index 214734ff2c..3b6fd26109 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -469,10 +469,8 @@ int virQEMUCapsAddCPUDefinitions(virQEMUCapsPtr qemuCaps, const char **name, size_t count, virDomainCapsCPUUsable usable); -int virQEMUCapsGetCPUDefinitions(virQEMUCapsPtr qemuCaps, - virDomainVirtType type, - char ***names, - size_t *count); +virDomainCapsCPUModelsPtr virQEMUCapsGetCPUDefinitions(virQEMUCapsPtr qemuCaps, + virDomainVirtType type); typedef enum { /* Host CPU definition reported in domain capabilities. */ diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 4855c9047d..55d8616ada 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -13051,7 +13051,7 @@ qemuConnectBaselineCPU(virConnectPtr conn ATTRIBUTE_UNUSED, if (!(cpus = virCPUDefListParse(xmlCPUs, ncpus, VIR_CPU_TYPE_HOST))) goto cleanup; - if (!(baseline = cpuBaseline(cpus, ncpus, NULL, 0, + if (!(baseline = cpuBaseline(cpus, ncpus, NULL, !!(flags & VIR_CONNECT_BASELINE_CPU_MIGRATABLE)))) goto cleanup; diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c index bde3ba462a..4341187852 100644 --- a/src/qemu/qemu_process.c +++ b/src/qemu/qemu_process.c @@ -5157,8 +5157,6 @@ qemuProcessUpdateGuestCPU(virDomainDefPtr def, unsigned int flags) { int ret = -1; - size_t nmodels = 0; - char **models = NULL; if (!def->cpu) return 0; @@ -5210,17 +5208,14 @@ qemuProcessUpdateGuestCPU(virDomainDefPtr def, VIR_QEMU_CAPS_HOST_CPU_MIGRATABLE)) < 0) goto cleanup; - if (virQEMUCapsGetCPUDefinitions(qemuCaps, def->virtType, - &models, &nmodels) < 0 || - virCPUTranslate(def->os.arch, def->cpu, - (const char **) models, nmodels) < 0) + if (virCPUTranslate(def->os.arch, def->cpu, + virQEMUCapsGetCPUDefinitions(qemuCaps, def->virtType)) < 0) goto cleanup; def->cpu->fallback = VIR_CPU_FALLBACK_FORBID; ret = 0; cleanup: - virStringListFreeCount(models, nmodels); return ret; } diff --git a/src/test/test_driver.c b/src/test/test_driver.c index 9b434e9a04..eeda5b224c 100644 --- a/src/test/test_driver.c +++ b/src/test/test_driver.c @@ -1545,7 +1545,7 @@ testConnectBaselineCPU(virConnectPtr conn ATTRIBUTE_UNUSED, if (!(cpus = virCPUDefListParse(xmlCPUs, ncpus, VIR_CPU_TYPE_HOST))) goto cleanup; - if (!(cpu = cpuBaseline(cpus, ncpus, NULL, 0, false))) + if (!(cpu = cpuBaseline(cpus, ncpus, NULL, false))) goto cleanup; if ((flags & VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES) && diff --git a/tests/cputest.c b/tests/cputest.c index 913ca77231..552c07e2c5 100644 --- a/tests/cputest.c +++ b/tests/cputest.c @@ -61,9 +61,8 @@ struct data { virArch arch; const char *host; const char *name; - const char **models; + virDomainCapsCPUModelsPtr models; const char *modelsName; - unsigned int nmodels; unsigned int flags; int result; }; @@ -264,13 +263,13 @@ cpuTestGuestCPU(const void *arg) } if (virCPUUpdate(host->arch, cpu, host) < 0 || - virCPUTranslate(host->arch, cpu, data->models, data->nmodels) < 0) { + virCPUTranslate(host->arch, cpu, data->models) < 0) { ret = -1; goto cleanup; } virBufferAsprintf(&buf, "%s+%s", data->host, data->name); - if (data->nmodels) + if (data->modelsName) virBufferAsprintf(&buf, ",%s", data->modelsName); virBufferAddLit(&buf, "-result"); @@ -322,7 +321,7 @@ cpuTestBaseline(const void *arg) if (!(cpus = cpuTestLoadMultiXML(data->arch, data->name, &ncpus))) goto cleanup; - baseline = cpuBaseline(cpus, ncpus, NULL, 0, + baseline = cpuBaseline(cpus, ncpus, NULL, !!(data->flags & VIR_CONNECT_BASELINE_CPU_MIGRATABLE)); if (baseline && @@ -492,7 +491,7 @@ cpuTestCPUID(bool guest, const void *arg) cpu->type = VIR_CPU_TYPE_HOST; } - if (cpuDecode(cpu, hostData, NULL, 0, NULL) < 0) + if (cpuDecode(cpu, hostData, NULL, NULL) < 0) goto cleanup; if (virAsprintf(&result, "cpuid-%s-%s", @@ -729,15 +728,43 @@ cpuTestJSONCPUID(const void *arg) #endif -static const char *model486[] = { "486" }; -static const char *nomodel[] = { "nomodel" }; -static const char *models[] = { "qemu64", "core2duo", "Nehalem" }; -static const char *haswell[] = { "SandyBridge", "Haswell" }; -static const char *ppc_models[] = { "POWER6", "POWER7", "POWER8" }; +static const char *model486_list[] = { "486", NULL }; +static const char *nomodel_list[] = { "nomodel", NULL }; +static const char *models_list[] = { "qemu64", "core2duo", "Nehalem", NULL }; +static const char *haswell_list[] = { "SandyBridge", "Haswell", NULL }; +static const char *ppc_models_list[] = { "POWER6", "POWER7", "POWER8", NULL }; + +static virDomainCapsCPUModelsPtr +cpuTestInitModels(const char **list) +{ + virDomainCapsCPUModelsPtr cpus; + const char **model; + + if (!(cpus = virDomainCapsCPUModelsNew(0))) + return NULL; + + for (model = list; *model; model++) { + if (virDomainCapsCPUModelsAdd(cpus, *model, -1, + VIR_DOMCAPS_CPU_USABLE_UNKNOWN, NULL) < 0) + goto error; + } + + return cpus; + + error: + virObjectUnref(cpus); + return NULL; +} + static int mymain(void) { + virDomainCapsCPUModelsPtr model486 = NULL; + virDomainCapsCPUModelsPtr nomodel = NULL; + virDomainCapsCPUModelsPtr models = NULL; + virDomainCapsCPUModelsPtr haswell = NULL; + virDomainCapsCPUModelsPtr ppc_models = NULL; int ret = 0; #if WITH_QEMU && WITH_YAJL @@ -747,13 +774,22 @@ mymain(void) virEventRegisterDefaultImpl(); #endif + if (!(model486 = cpuTestInitModels(model486_list)) || + !(nomodel = cpuTestInitModels(nomodel_list)) || + !(models = cpuTestInitModels(models_list)) || + !(haswell = cpuTestInitModels(haswell_list)) || + !(ppc_models = cpuTestInitModels(ppc_models_list))) { + ret = -1; + goto cleanup; + } + #define DO_TEST(arch, api, name, host, cpu, \ - models, nmodels, flags, result) \ + models, flags, result) \ do { \ struct data data = { \ arch, host, cpu, models, \ models == NULL ? NULL : #models, \ - nmodels, flags, result \ + flags, result \ }; \ char *testLabel; \ char *tmp; \ @@ -784,12 +820,12 @@ mymain(void) #define DO_TEST_COMPARE(arch, host, cpu, result) \ DO_TEST(arch, cpuTestCompare, \ host "/" cpu " (" #result ")", \ - host, cpu, NULL, 0, 0, result) + host, cpu, NULL, 0, result) #define DO_TEST_UPDATE_ONLY(arch, host, cpu) \ DO_TEST(arch, cpuTestUpdate, \ cpu " on " host, \ - host, cpu, NULL, 0, 0, 0) + host, cpu, NULL, 0, 0) #define DO_TEST_UPDATE(arch, host, cpu, result) \ do { \ @@ -809,7 +845,7 @@ mymain(void) ret = -1; \ } else { \ DO_TEST(arch, cpuTestBaseline, label, NULL, \ - "baseline-" name, NULL, 0, flags, result); \ + "baseline-" name, NULL, flags, result); \ } \ VIR_FREE(label); \ } while (0) @@ -817,21 +853,19 @@ mymain(void) #define DO_TEST_HASFEATURE(arch, host, feature, result) \ DO_TEST(arch, cpuTestHasFeature, \ host "/" feature " (" #result ")", \ - host, feature, NULL, 0, 0, result) + host, feature, NULL, 0, result) #define DO_TEST_GUESTCPU(arch, host, cpu, models, result) \ DO_TEST(arch, cpuTestGuestCPU, \ host "/" cpu " (" #models ")", \ - host, cpu, models, \ - models == NULL ? 0 : sizeof(models) / sizeof(char *), \ - 0, result) + host, cpu, models, 0, result) #if WITH_QEMU && WITH_YAJL # define DO_TEST_CPUID_JSON(arch, host, json) \ do { \ if (json) { \ DO_TEST(arch, cpuTestJSONCPUID, host, host, \ - NULL, NULL, 0, 0, 0); \ + NULL, NULL, 0, 0); \ } \ } while (0) #else @@ -841,13 +875,13 @@ mymain(void) #define DO_TEST_CPUID(arch, host, json) \ do { \ DO_TEST(arch, cpuTestHostCPUID, host, host, \ - NULL, NULL, 0, 0, 0); \ + NULL, NULL, 0, 0); \ DO_TEST(arch, cpuTestGuestCPUID, host, host, \ - NULL, NULL, 0, 0, 0); \ + NULL, NULL, 0, 0); \ DO_TEST_CPUID_JSON(arch, host, json); \ if (json) { \ DO_TEST(arch, cpuTestUpdateLive, host, host, \ - NULL, NULL, 0, 0, 0); \ + NULL, NULL, 0, 0); \ } \ } while (0) @@ -1012,10 +1046,17 @@ mymain(void) DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-W3520", true); DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-X5460", false); + cleanup: #if WITH_QEMU && WITH_YAJL qemuTestDriverFree(&driver); #endif + virObjectUnref(model486); + virObjectUnref(nomodel); + virObjectUnref(models); + virObjectUnref(haswell); + virObjectUnref(ppc_models); + return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; } -- 2.14.2

On 10/04/2017 10:58 AM, Jiri Denemark wrote:
All APIs which expect a list of CPU models supported by hypervisors were switched from char **models and int models to just accept a pointer to virDomainCapsCPUModels object stored in domain capabilities. This avoids the need to transform virDomainCapsCPUModelsPtr into a NULL-terminated list of model names and also allows the various cpu driver APIs to access additional details (such as its usability) about each CPU model.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/cpu/cpu.c | 78 +++++++++++++----------------------- src/cpu/cpu.h | 28 +++++-------- src/cpu/cpu_arm.c | 3 +- src/cpu/cpu_ppc64.c | 13 +++--- src/cpu/cpu_x86.c | 25 +++++------- src/libxl/libxl_capabilities.c | 2 +- src/libxl/libxl_driver.c | 2 +- src/qemu/qemu_capabilities.c | 63 ++++++------------------------ src/qemu/qemu_capabilities.h | 6 +-- src/qemu/qemu_driver.c | 2 +- src/qemu/qemu_process.c | 9 +---- src/test/test_driver.c | 2 +- tests/cputest.c | 89 ++++++++++++++++++++++++++++++------------ 13 files changed, 138 insertions(+), 184 deletions(-)
[...]
@@ -501,11 +491,10 @@ virCPUProbeHost(virArch arch) * @cpus: list of host CPU definitions * @ncpus: number of CPUs in @cpus * @models: list of CPU models that can be considered for the baseline CPU - * @nmodels: number of CPU models in @models * @migratable: requests non-migratable features to be removed from the result * * Computes the most feature-rich CPU which is compatible with all given - * host CPUs. If @models array is NULL, all models supported by libvirt will + * host CPUs. If @models is NULL, all models supported by libvirt will * be considered when computing the baseline CPU model, otherwise the baseline * CPU model will be one of the provided CPU @models. * @@ -514,21 +503,20 @@ virCPUProbeHost(virArch arch) virCPUDefPtr cpuBaseline(virCPUDefPtr *cpus, unsigned int ncpus, - const char **models, - unsigned int nmodels, + virDomainCapsCPUModelsPtr models, bool migratable) { struct cpuArchDriver *driver; size_t i;
- VIR_DEBUG("ncpus=%u, nmodels=%u", ncpus, nmodels); + VIR_DEBUG("ncpus=%u", ncpus);
You could add models=%p... not that it's necessary
if (cpus) { for (i = 0; i < ncpus; i++) VIR_DEBUG("cpus[%zu]=%p", i, cpus[i]); } if (models) { - for (i = 0; i < nmodels; i++) - VIR_DEBUG("models[%zu]=%s", i, NULLSTR(models[i])); + for (i = 0; i < models->nmodels; i++) + VIR_DEBUG("models[%zu]=%s", i, models->models[i].name); }
[...]
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 7ddc6cafd4..225cee4ef9 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c
[...]
-int +virDomainCapsCPUModelsPtr virQEMUCapsGetCPUDefinitions(virQEMUCapsPtr qemuCaps, - virDomainVirtType type, - char ***names, - size_t *count) + virDomainVirtType type) { - size_t i; - char **models = NULL; - virDomainCapsCPUModelsPtr cpus; - - *count = 0; - if (names) - *names = NULL; - if (type == VIR_DOMAIN_VIRT_KVM) - cpus = qemuCaps->kvmCPUModels; + return qemuCaps->kvmCPUModels; else - cpus = qemuCaps->tcgCPUModels; + return qemuCaps->tcgCPUModels;
- if (!cpus) - return 0; - - if (names && VIR_ALLOC_N(models, cpus->nmodels) < 0) - return -1; - - for (i = 0; i < cpus->nmodels; i++) { - virDomainCapsCPUModelPtr cpu = cpus->models + i; - if (models && VIR_STRDUP(models[i], cpu->name) < 0) - goto error; - } - - if (names) - *names = models; - *count = cpus->nmodels; - return 0; - - error: - virStringListFreeCount(models, i); - return -1; + return NULL;
Nice overall simplification, but how do we reach here? Wouldn't tcgCPUModels either be something or NULL. Previous code just returns 0 w/ @models and @nmodels untouched which would seemingly be the same with these changes. That would also say to me the "else" above would be unnecessary.
}
@@ -3392,8 +3353,6 @@ virQEMUCapsInitCPUModelX86(virQEMUCapsPtr qemuCaps, virCPUDataPtr data = NULL; unsigned long long sigFamily = 0; unsigned long long sigModel = 0; - size_t nmodels = 0; - char **models = NULL; int ret = -1; size_t i;
Reviewed-by: John Ferlan <jferlan@redhat.com> John

On Thu, Oct 12, 2017 at 07:27:22 -0400, John Ferlan wrote:
On 10/04/2017 10:58 AM, Jiri Denemark wrote:
All APIs which expect a list of CPU models supported by hypervisors were switched from char **models and int models to just accept a pointer to virDomainCapsCPUModels object stored in domain capabilities. This avoids the need to transform virDomainCapsCPUModelsPtr into a NULL-terminated list of model names and also allows the various cpu driver APIs to access additional details (such as its usability) about each CPU model.
...
@@ -514,21 +503,20 @@ virCPUProbeHost(virArch arch) virCPUDefPtr cpuBaseline(virCPUDefPtr *cpus, unsigned int ncpus, - const char **models, - unsigned int nmodels, + virDomainCapsCPUModelsPtr models, bool migratable) { struct cpuArchDriver *driver; size_t i;
- VIR_DEBUG("ncpus=%u, nmodels=%u", ncpus, nmodels); + VIR_DEBUG("ncpus=%u", ncpus);
You could add models=%p... not that it's necessary
Done.
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 7ddc6cafd4..225cee4ef9 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c [...] -int +virDomainCapsCPUModelsPtr virQEMUCapsGetCPUDefinitions(virQEMUCapsPtr qemuCaps, - virDomainVirtType type, - char ***names, - size_t *count) + virDomainVirtType type) { - size_t i; - char **models = NULL; - virDomainCapsCPUModelsPtr cpus; - - *count = 0; - if (names) - *names = NULL; - if (type == VIR_DOMAIN_VIRT_KVM) - cpus = qemuCaps->kvmCPUModels; + return qemuCaps->kvmCPUModels; else - cpus = qemuCaps->tcgCPUModels; + return qemuCaps->tcgCPUModels;
...
+ return NULL;
Nice overall simplification, but how do we reach here?
Eh, the "return NULL;" shouldn't be there. Jirka

The "preferred" parameter is not used by any caller of cpuDecode anymore. It's only used internally in cpu_x86 to implement cpuBaseline. Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/cpu/cpu.c | 15 ++++----------- src/cpu/cpu.h | 6 ++---- src/cpu/cpu_ppc64.c | 5 ++--- src/cpu/cpu_x86.c | 7 +++---- src/libxl/libxl_capabilities.c | 2 +- src/qemu/qemu_capabilities.c | 4 +--- tests/cputest.c | 2 +- 7 files changed, 14 insertions(+), 27 deletions(-) diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index 842b0db2cd..b815ed383a 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -192,34 +192,27 @@ virCPUCompare(virArch arch, * @cpu: CPU definition stub to be filled in * @data: internal CPU data to be decoded into @cpu definition * @models: list of CPU models that can be considered when decoding @data - * @preferred: CPU models that should be used if possible * * Decodes internal CPU data into a CPU definition consisting of a CPU model * and a list of CPU features. The @cpu model stub is supposed to have arch, * type, match and fallback members set, this function will add the rest. If * @models list is NULL, all models supported by libvirt will be considered * when decoding the data. In general, this function will select the model - * closest to the CPU specified by @data unless @preferred is non-NULL, in - * which case the @preferred model will be used as long as it is compatible - * with @data. + * closest to the CPU specified by @data. * * For VIR_ARCH_I686 and VIR_ARCH_X86_64 architectures this means the computed * CPU definition will have the shortest possible list of additional features. - * When @preferred is non-NULL, the @preferred model will be used even if - * other models would result in a shorter list of additional features. * * Returns 0 on success, -1 on error. */ int cpuDecode(virCPUDefPtr cpu, const virCPUData *data, - virDomainCapsCPUModelsPtr models, - const char *preferred) + virDomainCapsCPUModelsPtr models) { struct cpuArchDriver *driver; - VIR_DEBUG("cpu=%p, data=%p, models=%p, preferred=%s", - cpu, data, models, NULLSTR(preferred)); + VIR_DEBUG("cpu=%p, data=%p, models=%p", cpu, data, models); if (models) { size_t i; for (i = 0; i < models->nmodels; i++) @@ -243,7 +236,7 @@ cpuDecode(virCPUDefPtr cpu, return -1; } - return driver->decode(cpu, data, models, preferred); + return driver->decode(cpu, data, models); } diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index d325fe3d04..83d5bcb63f 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -53,8 +53,7 @@ typedef virCPUCompareResult typedef int (*cpuArchDecode) (virCPUDefPtr cpu, const virCPUData *data, - virDomainCapsCPUModelsPtr models, - const char *preferred); + virDomainCapsCPUModelsPtr models); typedef int (*cpuArchEncode) (virArch arch, @@ -162,8 +161,7 @@ virCPUCompare(virArch arch, int cpuDecode (virCPUDefPtr cpu, const virCPUData *data, - virDomainCapsCPUModelsPtr models, - const char *preferred) + virDomainCapsCPUModelsPtr models) ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2); int diff --git a/src/cpu/cpu_ppc64.c b/src/cpu/cpu_ppc64.c index e5ae3a609f..7eb27c59bd 100644 --- a/src/cpu/cpu_ppc64.c +++ b/src/cpu/cpu_ppc64.c @@ -663,8 +663,7 @@ virCPUppc64Compare(virCPUDefPtr host, static int ppc64DriverDecode(virCPUDefPtr cpu, const virCPUData *data, - virDomainCapsCPUModelsPtr models, - const char *preferred ATTRIBUTE_UNUSED) + virDomainCapsCPUModelsPtr models) { int ret = -1; struct ppc64_map *map; @@ -735,7 +734,7 @@ virCPUppc64GetHost(virCPUDefPtr cpu, #endif data->pvr[0].mask = 0xfffffffful; - ret = ppc64DriverDecode(cpu, cpuData, models, NULL); + ret = ppc64DriverDecode(cpu, cpuData, models); cleanup: virCPUppc64DataFree(cpuData); diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c index 3f9e83ca72..84ec878d1b 100644 --- a/src/cpu/cpu_x86.c +++ b/src/cpu/cpu_x86.c @@ -1945,10 +1945,9 @@ x86Decode(virCPUDefPtr cpu, static int x86DecodeCPUData(virCPUDefPtr cpu, const virCPUData *data, - virDomainCapsCPUModelsPtr models, - const char *preferred) + virDomainCapsCPUModelsPtr models) { - return x86Decode(cpu, &data->data.x86, models, preferred, false); + return x86Decode(cpu, &data->data.x86, models, NULL, false); } @@ -2412,7 +2411,7 @@ virCPUx86GetHost(virCPUDefPtr cpu, cpuidSet(CPUX86_EXTENDED, cpuData) < 0) goto cleanup; - ret = x86DecodeCPUData(cpu, cpuData, models, NULL); + ret = x86DecodeCPUData(cpu, cpuData, models); cleanup: virCPUx86DataFree(cpuData); diff --git a/src/libxl/libxl_capabilities.c b/src/libxl/libxl_capabilities.c index 4def561143..18596c7c72 100644 --- a/src/libxl/libxl_capabilities.c +++ b/src/libxl/libxl_capabilities.c @@ -192,7 +192,7 @@ libxlCapsInitCPU(virCapsPtr caps, libxl_physinfo *phy_info, ret = 0; if (!(data = libxlCapsNodeData(cpu, phy_info->hw_cap, version)) || - cpuDecode(cpu, data, NULL, NULL) < 0) { + cpuDecode(cpu, data, NULL) < 0) { VIR_WARN("Failed to initialize host cpu features"); goto error; } diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 225cee4ef9..5c8b1d76b0 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -3397,9 +3397,7 @@ virQEMUCapsInitCPUModelX86(virQEMUCapsPtr qemuCaps, if (virCPUx86DataSetSignature(data, sigFamily, sigModel) < 0) goto cleanup; - if (cpuDecode(cpu, data, - virQEMUCapsGetCPUDefinitions(qemuCaps, type), - NULL) < 0) + if (cpuDecode(cpu, data, virQEMUCapsGetCPUDefinitions(qemuCaps, type)) < 0) goto cleanup; ret = 0; diff --git a/tests/cputest.c b/tests/cputest.c index 552c07e2c5..cc95f1d551 100644 --- a/tests/cputest.c +++ b/tests/cputest.c @@ -491,7 +491,7 @@ cpuTestCPUID(bool guest, const void *arg) cpu->type = VIR_CPU_TYPE_HOST; } - if (cpuDecode(cpu, hostData, NULL, NULL) < 0) + if (cpuDecode(cpu, hostData, NULL) < 0) goto cleanup; if (virAsprintf(&result, "cpuid-%s-%s", -- 2.14.2

On 10/04/2017 10:58 AM, Jiri Denemark wrote:
The "preferred" parameter is not used by any caller of cpuDecode anymore. It's only used internally in cpu_x86 to implement cpuBaseline.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/cpu/cpu.c | 15 ++++----------- src/cpu/cpu.h | 6 ++---- src/cpu/cpu_ppc64.c | 5 ++--- src/cpu/cpu_x86.c | 7 +++---- src/libxl/libxl_capabilities.c | 2 +- src/qemu/qemu_capabilities.c | 4 +--- tests/cputest.c | 2 +- 7 files changed, 14 insertions(+), 27 deletions(-)
Reviewed-by: John Ferlan <jferlan@redhat.com> John

If a given CPU model is supported by the hypervisor, we want to know more about it, e.g., what features may block its usage on the current host and such details are stored in the virDomainCapsCPUModelsPtr list which virCPUModelIsAllowed uses to check whether the CPU model is supported. Thus if the CPU model is found in the list we can directly return a pointer to the corresponding virDomainCapsCPUModel if the caller needs to look at the details. Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/cpu/cpu.c | 18 ++++++++++++++---- src/cpu/cpu.h | 3 ++- src/cpu/cpu_ppc64.c | 2 +- src/cpu/cpu_x86.c | 2 +- 4 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index b815ed383a..48290a471b 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -819,24 +819,34 @@ virCPUDataParse(const char *xmlStr) * * @model: CPU model to be checked * @models: list of supported CPU models + * @hvModel: pointer to matching model from @models will be returned here * * Checks whether @model can be found in the list of supported @models. - * If @models is NULL, all models are supported. + * If @models is NULL, all models are supported. If both @models and @hvModel + * are non-NULL and @model is found in the list of supported models, @hvModel + * will be filled with the pointer to the matching CPU model from @models. * * Returns true if @model is supported, false otherwise. */ bool virCPUModelIsAllowed(const char *model, - virDomainCapsCPUModelsPtr models) + virDomainCapsCPUModelsPtr models, + virDomainCapsCPUModelPtr *hvModel) { size_t i; + if (hvModel) + *hvModel = NULL; + if (!models) return true; for (i = 0; i < models->nmodels; i++) { - if (STREQ(models->models[i].name, model)) + if (STREQ(models->models[i].name, model)) { + if (hvModel) + *hvModel = models->models + i; return true; + } } return false; } @@ -908,7 +918,7 @@ virCPUTranslate(virArch arch, cpu->mode == VIR_CPU_MODE_HOST_PASSTHROUGH) return 0; - if (virCPUModelIsAllowed(cpu->model, models)) + if (virCPUModelIsAllowed(cpu->model, models, NULL)) return 0; if (cpu->fallback != VIR_CPU_FALLBACK_ALLOW) { diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index 83d5bcb63f..2d81927a0b 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -227,7 +227,8 @@ virCPUDataCheckFeature(const virCPUData *data, bool virCPUModelIsAllowed(const char *model, - virDomainCapsCPUModelsPtr models) + virDomainCapsCPUModelsPtr models, + virDomainCapsCPUModelPtr *hvModel) ATTRIBUTE_NONNULL(1); int diff --git a/src/cpu/cpu_ppc64.c b/src/cpu/cpu_ppc64.c index 7eb27c59bd..9f990a3fb5 100644 --- a/src/cpu/cpu_ppc64.c +++ b/src/cpu/cpu_ppc64.c @@ -679,7 +679,7 @@ ppc64DriverDecode(virCPUDefPtr cpu, goto cleanup; } - if (!virCPUModelIsAllowed(model->name, models)) { + if (!virCPUModelIsAllowed(model->name, models, NULL)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("CPU model %s is not supported by hypervisor"), model->name); diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c index 84ec878d1b..198e80a5c2 100644 --- a/src/cpu/cpu_x86.c +++ b/src/cpu/cpu_x86.c @@ -1854,7 +1854,7 @@ x86Decode(virCPUDefPtr cpu, */ for (i = map->nmodels - 1; i >= 0; i--) { candidate = map->models[i]; - if (!virCPUModelIsAllowed(candidate->name, models)) { + if (!virCPUModelIsAllowed(candidate->name, models, NULL)) { if (preferred && STREQ(candidate->name, preferred)) { if (cpu->fallback != VIR_CPU_FALLBACK_ALLOW) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, -- 2.14.2

On 10/04/2017 10:58 AM, Jiri Denemark wrote:
If a given CPU model is supported by the hypervisor, we want to know more about it, e.g., what features may block its usage on the current host and such details are stored in the virDomainCapsCPUModelsPtr list which virCPUModelIsAllowed uses to check whether the CPU model is supported. Thus if the CPU model is found in the list we can directly return a pointer to the corresponding virDomainCapsCPUModel if the caller needs to look at the details.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/cpu/cpu.c | 18 ++++++++++++++---- src/cpu/cpu.h | 3 ++- src/cpu/cpu_ppc64.c | 2 +- src/cpu/cpu_x86.c | 2 +- 4 files changed, 18 insertions(+), 7 deletions(-)
diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index b815ed383a..48290a471b 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -819,24 +819,34 @@ virCPUDataParse(const char *xmlStr) * * @model: CPU model to be checked * @models: list of supported CPU models + * @hvModel: pointer to matching model from @models will be returned here
As later pointed out - 'hv' == hypervisor version. In any case, the 'ModelIsAllowed" now feels overloaded returning more than just true/false that a typical "Is" type function would return. Sorry, I don't have suggestions, so unless someone else is looking and has a better name, then just go with it. The only other concern is that since you're returning a pointer in the middle of some array, any concerns over some other thread changing things and freeing what you're looking at? e.g., should there be a way to deep copy the model information and force the caller to free when it's done? As long as you're comfortable with pointing in the middle of an array (and I didn't see anything existing that would seem to cause a problem), then fine go with what you have. Reviewed-by: John Ferlan <jferlan@redhat.com> John
* * Checks whether @model can be found in the list of supported @models. - * If @models is NULL, all models are supported. + * If @models is NULL, all models are supported. If both @models and @hvModel + * are non-NULL and @model is found in the list of supported models, @hvModel + * will be filled with the pointer to the matching CPU model from @models. * * Returns true if @model is supported, false otherwise. */ bool virCPUModelIsAllowed(const char *model, - virDomainCapsCPUModelsPtr models) + virDomainCapsCPUModelsPtr models, + virDomainCapsCPUModelPtr *hvModel) { size_t i;
+ if (hvModel) + *hvModel = NULL; + if (!models) return true;
for (i = 0; i < models->nmodels; i++) { - if (STREQ(models->models[i].name, model)) + if (STREQ(models->models[i].name, model)) { + if (hvModel) + *hvModel = models->models + i; return true; + } } return false; } @@ -908,7 +918,7 @@ virCPUTranslate(virArch arch, cpu->mode == VIR_CPU_MODE_HOST_PASSTHROUGH) return 0;
- if (virCPUModelIsAllowed(cpu->model, models)) + if (virCPUModelIsAllowed(cpu->model, models, NULL)) return 0;
if (cpu->fallback != VIR_CPU_FALLBACK_ALLOW) { [...]

On Thu, Oct 12, 2017 at 15:50:29 -0400, John Ferlan wrote:
On 10/04/2017 10:58 AM, Jiri Denemark wrote:
If a given CPU model is supported by the hypervisor, we want to know more about it, e.g., what features may block its usage on the current host and such details are stored in the virDomainCapsCPUModelsPtr list which virCPUModelIsAllowed uses to check whether the CPU model is supported. Thus if the CPU model is found in the list we can directly return a pointer to the corresponding virDomainCapsCPUModel if the caller needs to look at the details.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/cpu/cpu.c | 18 ++++++++++++++---- src/cpu/cpu.h | 3 ++- src/cpu/cpu_ppc64.c | 2 +- src/cpu/cpu_x86.c | 2 +- 4 files changed, 18 insertions(+), 7 deletions(-)
diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index b815ed383a..48290a471b 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -819,24 +819,34 @@ virCPUDataParse(const char *xmlStr) * * @model: CPU model to be checked * @models: list of supported CPU models + * @hvModel: pointer to matching model from @models will be returned here
As later pointed out - 'hv' == hypervisor version.
In any case, the 'ModelIsAllowed" now feels overloaded returning more than just true/false that a typical "Is" type function would return. Sorry, I don't have suggestions, so unless someone else is looking and has a better name, then just go with it.
Hmm, I have a suggestion. I should just create a separate function virDomainCapsCPUModelsGet or *Find which would just return a pointer to the CPU model structure from the models array and change virCPUModelIsAllowed into a simple wrapper around the new function. The callers which would pass non-NULL hvModel pointer would just call the underlying virDomainCapsCPUModelsGet function directly.
The only other concern is that since you're returning a pointer in the middle of some array, any concerns over some other thread changing things and freeing what you're looking at?
No. If there were any concerns like this even going through the array would be dangerous. Anyway, virDomainCapsCPUModelsPtr is a reference counted object which never changes once it's created. It can only go away and be replaced with another one. Jirka

On 10/13/2017 11:31 AM, Jiri Denemark wrote:
On Thu, Oct 12, 2017 at 15:50:29 -0400, John Ferlan wrote:
On 10/04/2017 10:58 AM, Jiri Denemark wrote:
If a given CPU model is supported by the hypervisor, we want to know more about it, e.g., what features may block its usage on the current host and such details are stored in the virDomainCapsCPUModelsPtr list which virCPUModelIsAllowed uses to check whether the CPU model is supported. Thus if the CPU model is found in the list we can directly return a pointer to the corresponding virDomainCapsCPUModel if the caller needs to look at the details.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/cpu/cpu.c | 18 ++++++++++++++---- src/cpu/cpu.h | 3 ++- src/cpu/cpu_ppc64.c | 2 +- src/cpu/cpu_x86.c | 2 +- 4 files changed, 18 insertions(+), 7 deletions(-)
diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c index b815ed383a..48290a471b 100644 --- a/src/cpu/cpu.c +++ b/src/cpu/cpu.c @@ -819,24 +819,34 @@ virCPUDataParse(const char *xmlStr) * * @model: CPU model to be checked * @models: list of supported CPU models + * @hvModel: pointer to matching model from @models will be returned here
As later pointed out - 'hv' == hypervisor version.
In any case, the 'ModelIsAllowed" now feels overloaded returning more than just true/false that a typical "Is" type function would return. Sorry, I don't have suggestions, so unless someone else is looking and has a better name, then just go with it.
Hmm, I have a suggestion. I should just create a separate function virDomainCapsCPUModelsGet or *Find which would just return a pointer to the CPU model structure from the models array and change virCPUModelIsAllowed into a simple wrapper around the new function. The callers which would pass non-NULL hvModel pointer would just call the underlying virDomainCapsCPUModelsGet function directly.
That would seem to work and Get would perhaps also imply it's not a copy but rather a pointer to something existing. John
The only other concern is that since you're returning a pointer in the middle of some array, any concerns over some other thread changing things and freeing what you're looking at?
No. If there were any concerns like this even going through the array would be dangerous. Anyway, virDomainCapsCPUModelsPtr is a reference counted object which never changes once it's created. It can only go away and be replaced with another one.
Jirka

On Fri, Oct 13, 2017 at 14:45:05 -0400, John Ferlan wrote:
In any case, the 'ModelIsAllowed" now feels overloaded returning more than just true/false that a typical "Is" type function would return. Sorry, I don't have suggestions, so unless someone else is looking and has a better name, then just go with it.
Hmm, I have a suggestion. I should just create a separate function virDomainCapsCPUModelsGet or *Find which would just return a pointer to the CPU model structure from the models array and change virCPUModelIsAllowed into a simple wrapper around the new function. The callers which would pass non-NULL hvModel pointer would just call the underlying virDomainCapsCPUModelsGet function directly.
That would seem to work and Get would perhaps also imply it's not a copy but rather a pointer to something existing.
Yeah, I think it looks better. See v2 of this series. Jirka

Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/cpu/cpu_x86.c | 61 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 31 insertions(+), 30 deletions(-) diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c index 198e80a5c2..e197e31310 100644 --- a/src/cpu/cpu_x86.c +++ b/src/cpu/cpu_x86.c @@ -240,6 +240,37 @@ x86cpuidAndBits(virCPUx86CPUID *cpuid, cpuid->edx &= mask->edx; } + +static virCPUx86FeaturePtr +x86FeatureFind(virCPUx86MapPtr map, + const char *name) +{ + size_t i; + + for (i = 0; i < map->nfeatures; i++) { + if (STREQ(map->features[i]->name, name)) + return map->features[i]; + } + + return NULL; +} + + +static virCPUx86FeaturePtr +x86FeatureFindInternal(const char *name) +{ + size_t i; + size_t count = ARRAY_CARDINALITY(x86_kvm_features); + + for (i = 0; i < count; i++) { + if (STREQ(x86_kvm_features[i].name, name)) + return x86_kvm_features + i; + } + + return NULL; +} + + static int virCPUx86CPUIDSorter(const void *a, const void *b) { @@ -753,36 +784,6 @@ x86FeatureFree(virCPUx86FeaturePtr feature) } -static virCPUx86FeaturePtr -x86FeatureFind(virCPUx86MapPtr map, - const char *name) -{ - size_t i; - - for (i = 0; i < map->nfeatures; i++) { - if (STREQ(map->features[i]->name, name)) - return map->features[i]; - } - - return NULL; -} - - -static virCPUx86FeaturePtr -x86FeatureFindInternal(const char *name) -{ - size_t i; - size_t count = ARRAY_CARDINALITY(x86_kvm_features); - - for (i = 0; i < count; i++) { - if (STREQ(x86_kvm_features[i].name, name)) - return x86_kvm_features + i; - } - - return NULL; -} - - static int x86FeatureInData(const char *name, const virCPUx86Data *data, -- 2.14.2

On 10/04/2017 10:58 AM, Jiri Denemark wrote:
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/cpu/cpu_x86.c | 61 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 31 insertions(+), 30 deletions(-)
Reviewed-by: John Ferlan <jferlan@redhat.com> John

When decoding CPUID data to virCPUDef we need to be careful about using a CPU model which cannot be directly used on the current host. Normally, libvirt would notice the features which prevent the model from being usable and it would disable them in the computed virCPUDef, but this won't work in case the definition of the CPU model in QEMU contains more features than what we have in cpu_map.xml. We need to count with the usability blockers we got from QEMU and explicitly disable all of them to make the computed virCPUDef usable. https://bugzilla.redhat.com/show_bug.cgi?id=1464832 Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/cpu/cpu_x86.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c index e197e31310..0dbc17f199 100644 --- a/src/cpu/cpu_x86.c +++ b/src/cpu/cpu_x86.c @@ -627,7 +627,8 @@ x86DataAddSignature(virCPUx86Data *data, static virCPUDefPtr x86DataToCPU(const virCPUx86Data *data, virCPUx86ModelPtr model, - virCPUx86MapPtr map) + virCPUx86MapPtr map, + virDomainCapsCPUModelPtr hvModel) { virCPUDefPtr cpu; virCPUx86Data copy = VIR_CPU_X86_DATA_INIT; @@ -647,6 +648,21 @@ x86DataToCPU(const virCPUx86Data *data, x86DataSubtract(©, &modelData); x86DataSubtract(&modelData, data); + /* The hypervisor's version of the CPU model (hvModel) may contain + * additional features which may be currently unavailable. Such features + * block usage of the CPU model and we need to explicitly disable them. + */ + if (hvModel && hvModel->blockers) { + char **blocker; + virCPUx86FeaturePtr feature; + + for (blocker = hvModel->blockers; *blocker; blocker++) { + if ((feature = x86FeatureFind(map, *blocker)) && + !x86DataIsSubset(©, &feature->data)) + x86DataAdd(&modelData, &feature->data); + } + } + /* because feature policy is ignored for host CPU */ cpu->type = VIR_CPU_TYPE_GUEST; @@ -1835,6 +1851,7 @@ x86Decode(virCPUDefPtr cpu, virCPUx86Data copy = VIR_CPU_X86_DATA_INIT; virCPUx86Data features = VIR_CPU_X86_DATA_INIT; virCPUx86VendorPtr vendor; + virDomainCapsCPUModelPtr hvModel; uint32_t signature; ssize_t i; int rc; @@ -1855,7 +1872,7 @@ x86Decode(virCPUDefPtr cpu, */ for (i = map->nmodels - 1; i >= 0; i--) { candidate = map->models[i]; - if (!virCPUModelIsAllowed(candidate->name, models, NULL)) { + if (!virCPUModelIsAllowed(candidate->name, models, &hvModel)) { if (preferred && STREQ(candidate->name, preferred)) { if (cpu->fallback != VIR_CPU_FALLBACK_ALLOW) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, @@ -1883,7 +1900,7 @@ x86Decode(virCPUDefPtr cpu, continue; } - if (!(cpuCandidate = x86DataToCPU(&data, candidate, map))) + if (!(cpuCandidate = x86DataToCPU(&data, candidate, map, hvModel))) goto cleanup; cpuCandidate->type = cpu->type; -- 2.14.2

On 10/04/2017 10:58 AM, Jiri Denemark wrote:
When decoding CPUID data to virCPUDef we need to be careful about using a CPU model which cannot be directly used on the current host. Normally, libvirt would notice the features which prevent the model from being usable and it would disable them in the computed virCPUDef, but this won't work in case the definition of the CPU model in QEMU contains more features than what we have in cpu_map.xml. We need to count with the usability blockers we got from QEMU and explicitly disable all of them to make the computed virCPUDef usable.
https://bugzilla.redhat.com/show_bug.cgi?id=1464832
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/cpu/cpu_x86.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-)
Reviewed-by: John Ferlan <jferlan@redhat.com> John

We will soon need to handle more than two values. Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- tests/cputest.c | 79 ++++++++++++++++++++++++++++++--------------------------- 1 file changed, 42 insertions(+), 37 deletions(-) diff --git a/tests/cputest.c b/tests/cputest.c index cc95f1d551..57cff04f38 100644 --- a/tests/cputest.c +++ b/tests/cputest.c @@ -670,6 +670,11 @@ cpuTestUpdateLive(const void *arg) } +typedef enum { + JSON_NONE, + JSON_HOST, +} cpuTestCPUIDJson; + #if WITH_QEMU && WITH_YAJL static int cpuTestJSONCPUID(const void *arg) @@ -863,7 +868,7 @@ mymain(void) #if WITH_QEMU && WITH_YAJL # define DO_TEST_CPUID_JSON(arch, host, json) \ do { \ - if (json) { \ + if (json != JSON_NONE) { \ DO_TEST(arch, cpuTestJSONCPUID, host, host, \ NULL, NULL, 0, 0); \ } \ @@ -879,7 +884,7 @@ mymain(void) DO_TEST(arch, cpuTestGuestCPUID, host, host, \ NULL, NULL, 0, 0); \ DO_TEST_CPUID_JSON(arch, host, json); \ - if (json) { \ + if (json != JSON_NONE) { \ DO_TEST(arch, cpuTestUpdateLive, host, host, \ NULL, NULL, 0, 0); \ } \ @@ -1010,41 +1015,41 @@ mymain(void) DO_TEST_GUESTCPU(VIR_ARCH_PPC64, "host", "guest-legacy-incompatible", ppc_models, -1); DO_TEST_GUESTCPU(VIR_ARCH_PPC64, "host", "guest-legacy-invalid", ppc_models, -1); - DO_TEST_CPUID(VIR_ARCH_X86_64, "A10-5800K", true); - DO_TEST_CPUID(VIR_ARCH_X86_64, "Atom-D510", false); - DO_TEST_CPUID(VIR_ARCH_X86_64, "Atom-N450", false); - DO_TEST_CPUID(VIR_ARCH_X86_64, "Core-i5-2500", true); - DO_TEST_CPUID(VIR_ARCH_X86_64, "Core-i5-2540M", true); - DO_TEST_CPUID(VIR_ARCH_X86_64, "Core-i5-4670T", true); - DO_TEST_CPUID(VIR_ARCH_X86_64, "Core-i5-6600", true); - DO_TEST_CPUID(VIR_ARCH_X86_64, "Core-i7-2600", true); - DO_TEST_CPUID(VIR_ARCH_X86_64, "Core-i7-3520M", false); - DO_TEST_CPUID(VIR_ARCH_X86_64, "Core-i7-3740QM", true); - DO_TEST_CPUID(VIR_ARCH_X86_64, "Core-i7-3770", true); - DO_TEST_CPUID(VIR_ARCH_X86_64, "Core-i7-4600U", true); - DO_TEST_CPUID(VIR_ARCH_X86_64, "Core-i7-4510U", true); - DO_TEST_CPUID(VIR_ARCH_X86_64, "Core-i7-5600U", true); - DO_TEST_CPUID(VIR_ARCH_X86_64, "Core-i7-5600U-arat", true); - DO_TEST_CPUID(VIR_ARCH_X86_64, "Core2-E6850", true); - DO_TEST_CPUID(VIR_ARCH_X86_64, "Core2-Q9500", false); - DO_TEST_CPUID(VIR_ARCH_X86_64, "EPYC-7601-32-Core", true); - DO_TEST_CPUID(VIR_ARCH_X86_64, "FX-8150", false); - DO_TEST_CPUID(VIR_ARCH_X86_64, "Opteron-1352", false); - DO_TEST_CPUID(VIR_ARCH_X86_64, "Opteron-2350", true); - DO_TEST_CPUID(VIR_ARCH_X86_64, "Opteron-6234", true); - DO_TEST_CPUID(VIR_ARCH_X86_64, "Opteron-6282", false); - DO_TEST_CPUID(VIR_ARCH_X86_64, "Pentium-P6100", false); - DO_TEST_CPUID(VIR_ARCH_X86_64, "Phenom-B95", true); - DO_TEST_CPUID(VIR_ARCH_X86_64, "Ryzen-7-1800X-Eight-Core", true); - DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-5110", false); - DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-E3-1245", true); - DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-E5-2630", true); - DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-E5-2650", true); - DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-E7-4820", true); - DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-E7-8890", false); - DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-Gold-6148", true); - DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-W3520", true); - DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-X5460", false); + DO_TEST_CPUID(VIR_ARCH_X86_64, "A10-5800K", JSON_HOST); + DO_TEST_CPUID(VIR_ARCH_X86_64, "Atom-D510", JSON_NONE); + DO_TEST_CPUID(VIR_ARCH_X86_64, "Atom-N450", JSON_NONE); + DO_TEST_CPUID(VIR_ARCH_X86_64, "Core-i5-2500", JSON_HOST); + DO_TEST_CPUID(VIR_ARCH_X86_64, "Core-i5-2540M", JSON_HOST); + DO_TEST_CPUID(VIR_ARCH_X86_64, "Core-i5-4670T", JSON_HOST); + DO_TEST_CPUID(VIR_ARCH_X86_64, "Core-i5-6600", JSON_HOST); + DO_TEST_CPUID(VIR_ARCH_X86_64, "Core-i7-2600", JSON_HOST); + DO_TEST_CPUID(VIR_ARCH_X86_64, "Core-i7-3520M", JSON_NONE); + DO_TEST_CPUID(VIR_ARCH_X86_64, "Core-i7-3740QM", JSON_HOST); + DO_TEST_CPUID(VIR_ARCH_X86_64, "Core-i7-3770", JSON_HOST); + DO_TEST_CPUID(VIR_ARCH_X86_64, "Core-i7-4600U", JSON_HOST); + DO_TEST_CPUID(VIR_ARCH_X86_64, "Core-i7-4510U", JSON_HOST); + DO_TEST_CPUID(VIR_ARCH_X86_64, "Core-i7-5600U", JSON_HOST); + DO_TEST_CPUID(VIR_ARCH_X86_64, "Core-i7-5600U-arat", JSON_HOST); + DO_TEST_CPUID(VIR_ARCH_X86_64, "Core2-E6850", JSON_HOST); + DO_TEST_CPUID(VIR_ARCH_X86_64, "Core2-Q9500", JSON_NONE); + DO_TEST_CPUID(VIR_ARCH_X86_64, "EPYC-7601-32-Core", JSON_HOST); + DO_TEST_CPUID(VIR_ARCH_X86_64, "FX-8150", JSON_NONE); + DO_TEST_CPUID(VIR_ARCH_X86_64, "Opteron-1352", JSON_NONE); + DO_TEST_CPUID(VIR_ARCH_X86_64, "Opteron-2350", JSON_HOST); + DO_TEST_CPUID(VIR_ARCH_X86_64, "Opteron-6234", JSON_HOST); + DO_TEST_CPUID(VIR_ARCH_X86_64, "Opteron-6282", JSON_NONE); + DO_TEST_CPUID(VIR_ARCH_X86_64, "Pentium-P6100", JSON_NONE); + DO_TEST_CPUID(VIR_ARCH_X86_64, "Phenom-B95", JSON_HOST); + DO_TEST_CPUID(VIR_ARCH_X86_64, "Ryzen-7-1800X-Eight-Core", JSON_HOST); + DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-5110", JSON_NONE); + DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-E3-1245", JSON_HOST); + DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-E5-2630", JSON_HOST); + DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-E5-2650", JSON_HOST); + DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-E7-4820", JSON_HOST); + DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-E7-8890", JSON_NONE); + DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-Gold-6148", JSON_HOST); + DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-W3520", JSON_HOST); + DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-X5460", JSON_NONE); cleanup: #if WITH_QEMU && WITH_YAJL -- 2.14.2

@title, consider: Replace bool with cpuTestCPUIDJson enum It's just the "json bool" that looks strange. On 10/04/2017 10:58 AM, Jiri Denemark wrote:
We will soon need to handle more than two values.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- tests/cputest.c | 79 ++++++++++++++++++++++++++++++--------------------------- 1 file changed, 42 insertions(+), 37 deletions(-)
Reviewed-by: John Ferlan <jferlan@redhat.com> John

Various version of json_reformat use different number of spaces for indenting. Let's use a simple python reformatter to gain full control over the formatting for consistent results. Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- tests/cputestdata/cpu-parse.sh | 2 +- tests/cputestdata/cpu-reformat.py | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) create mode 100755 tests/cputestdata/cpu-reformat.py diff --git a/tests/cputestdata/cpu-parse.sh b/tests/cputestdata/cpu-parse.sh index cd1ab024b3..96ff1074e0 100755 --- a/tests/cputestdata/cpu-parse.sh +++ b/tests/cputestdata/cpu-parse.sh @@ -42,7 +42,7 @@ json() while read; do $first || echo first=false - json_reformat <<<"$REPLY" | tr -s '\n' + $(dirname $0)/cpu-reformat.py <<<"$REPLY" done } diff --git a/tests/cputestdata/cpu-reformat.py b/tests/cputestdata/cpu-reformat.py new file mode 100755 index 0000000000..999ef1698c --- /dev/null +++ b/tests/cputestdata/cpu-reformat.py @@ -0,0 +1,9 @@ +#!/usr/bin/env python2 + +import sys +import json + +dec = json.JSONDecoder() +data, pos = dec.raw_decode(sys.stdin.read()) +json.dump(data, sys.stdout, indent = 2, separators = (',', ': ')) +print -- 2.14.2

On 10/04/2017 10:58 AM, Jiri Denemark wrote:
Various version of json_reformat use different number of spaces for indenting. Let's use a simple python reformatter to gain full control over the formatting for consistent results.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- tests/cputestdata/cpu-parse.sh | 2 +- tests/cputestdata/cpu-reformat.py | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) create mode 100755 tests/cputestdata/cpu-reformat.py
Looks reasonable - python, formatting, and scripting - not exactly in my wheel house. Still doesn't 'tr -s '\n' just replace multiple occurrences of \n with just one? I suppose that's being done along with some amount of space adding. Reviewed-by: John Ferlan <jferlan@redhat.com> John

On Thu, Oct 12, 2017 at 16:18:20 -0400, John Ferlan wrote:
On 10/04/2017 10:58 AM, Jiri Denemark wrote:
Various version of json_reformat use different number of spaces for indenting. Let's use a simple python reformatter to gain full control over the formatting for consistent results.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- tests/cputestdata/cpu-parse.sh | 2 +- tests/cputestdata/cpu-reformat.py | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) create mode 100755 tests/cputestdata/cpu-reformat.py
Looks reasonable - python, formatting, and scripting - not exactly in my wheel house. Still doesn't 'tr -s '\n' just replace multiple occurrences of \n with just one? I suppose that's being done along with some amount of space adding.
json_reformat formats empty arrays as ... "array": [ ], ... which breaks our test monitor. The python formatting code doesn't do that so we don't need "tr -s '\n'" anymore. Jirka

If the actual result does not match our expectation, the tests would not correctly show the difference if a CPU feature is disabled in the expected result and the actual result does not mention it at all. The test could complain about an unrelated CPU feature or it could even crash in case the actual result contains no more features to go through. Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- tests/cputest.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/cputest.c b/tests/cputest.c index 57cff04f38..dcfdf57d43 100644 --- a/tests/cputest.c +++ b/tests/cputest.c @@ -605,7 +605,7 @@ cpuTestUpdateLiveCompare(virArch arch, (cmp > 0 && featExp->policy == VIR_CPU_FEATURE_DISABLE)) { VIR_TEST_VERBOSE("Actual CPU has extra feature '%s'\n", - featAct->name); + cmp <= 0 ? featAct->name : featExp->name); ret = -1; } } -- 2.14.2

On 10/04/2017 10:58 AM, Jiri Denemark wrote:
If the actual result does not match our expectation, the tests would not correctly show the difference if a CPU feature is disabled in the expected result and the actual result does not mention it at all. The test could complain about an unrelated CPU feature or it could even crash in case the actual result contains no more features to go through.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- tests/cputest.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
I recognize this - it was something I noted at one time from a Coverity test failure... Reviewed-by: John Ferlan <jferlan@redhat.com> John

Gather query-cpu-definitions results and use them for testing CPU model usability blockers in CPUID to virCPUDef translation. Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/qemu/qemu_capabilities.c | 2 +- src/qemu/qemu_capspriv.h | 5 +++++ tests/cputest.c | 12 +++++++++++- tests/cputestdata/cpu-cpuid.py | 26 +++++++++++++++++++------- tests/cputestdata/cpu-gather.sh | 1 + 5 files changed, 37 insertions(+), 9 deletions(-) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 5c8b1d76b0..b5a5ba2b02 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -2933,7 +2933,7 @@ virQEMUCapsProbeQMPMachineTypes(virQEMUCapsPtr qemuCaps, } -static int +int virQEMUCapsProbeQMPCPUDefinitions(virQEMUCapsPtr qemuCaps, qemuMonitorPtr mon, bool tcg) diff --git a/src/qemu/qemu_capspriv.h b/src/qemu/qemu_capspriv.h index d05256bd35..f23995ec6e 100644 --- a/src/qemu/qemu_capspriv.h +++ b/src/qemu/qemu_capspriv.h @@ -101,4 +101,9 @@ virQEMUCapsParseHelpStr(const char *qemu, int virQEMUCapsParseDeviceStr(virQEMUCapsPtr qemuCaps, const char *str); + +int +virQEMUCapsProbeQMPCPUDefinitions(virQEMUCapsPtr qemuCaps, + qemuMonitorPtr mon, + bool tcg); #endif diff --git a/tests/cputest.c b/tests/cputest.c index dcfdf57d43..0a07a2da14 100644 --- a/tests/cputest.c +++ b/tests/cputest.c @@ -673,6 +673,7 @@ cpuTestUpdateLive(const void *arg) typedef enum { JSON_NONE, JSON_HOST, + JSON_MODELS, } cpuTestCPUIDJson; #if WITH_QEMU && WITH_YAJL @@ -704,10 +705,19 @@ cpuTestJSONCPUID(const void *arg) if (!(qemuCaps = virQEMUCapsNew())) goto cleanup; + virQEMUCapsSet(qemuCaps, QEMU_CAPS_KVM); + if (data->flags == JSON_MODELS) + virQEMUCapsSet(qemuCaps, QEMU_CAPS_QUERY_CPU_DEFINITIONS); + virQEMUCapsSetArch(qemuCaps, data->arch); virQEMUCapsSetCPUModelInfo(qemuCaps, VIR_DOMAIN_VIRT_KVM, model); model = NULL; + if (virQEMUCapsProbeQMPCPUDefinitions(qemuCaps, + qemuMonitorTestGetMonitor(testMon), + false) < 0) + goto cleanup; + if (VIR_ALLOC(cpu) < 0) goto cleanup; @@ -870,7 +880,7 @@ mymain(void) do { \ if (json != JSON_NONE) { \ DO_TEST(arch, cpuTestJSONCPUID, host, host, \ - NULL, NULL, 0, 0); \ + NULL, NULL, json, 0); \ } \ } while (0) #else diff --git a/tests/cputestdata/cpu-cpuid.py b/tests/cputestdata/cpu-cpuid.py index a2fd938c24..4fe8e8b952 100755 --- a/tests/cputestdata/cpu-cpuid.py +++ b/tests/cputestdata/cpu-cpuid.py @@ -228,17 +228,22 @@ def parseFeatureWords(path): s = f.read() props = {} - for i in range(5): + rest = [] + chunk = 0 + while s != "": (data, pos) = dec.raw_decode(s) - if i == 0: + if chunk == 0: features = data["return"] - else: + elif chunk < 5: keys = ["family", "model", "stepping", "model-id"] - props[keys[i - 1]] = data["return"] + props[keys[chunk - 1]] = data["return"] + else: + rest.append(data) while pos < len(s) and s[pos] != "{": pos += 1 s = s[pos:] + chunk += 1 if props["model-id"].find("Intel") != -1: props["vendor"] = "GenuineIntel" @@ -255,13 +260,13 @@ def parseFeatureWords(path): leaf = cpuidLeaf(cpuid, in_eax, in_ecx) leaf[feat["cpuid-register"].lower()] = feat["features"] - return props, cpuid + return props, cpuid, rest def parseQemu(path, features): cpuid = {} with open(path, "r") as f: - data = json.load(f) + data, pos = json.JSONDecoder().raw_decode(f.read()) for (prop, val) in data["return"]["model"]["props"].iteritems(): if val and prop in features: @@ -288,6 +293,7 @@ def parseCpuid(path): def formatCpuid(cpuid, path, comment): + print path with open(path, "w") as f: f.write("<!-- " + comment + " -->\n") f.write("<cpudata arch='x86'>\n") @@ -304,19 +310,25 @@ def formatCpuid(cpuid, path, comment): def convert(path): - props, cpuid = parseFeatureWords(path) + props, cpuid, rest = parseFeatureWords(path) for feature in cpuidMap: value = cpuidIsSet(cpuid, feature) for name in feature["names"]: props[name] = value + print path with open(path, "w") as f: json.dump({"return": {"model": {"name": "base", "props": props}}, "id": "model-expansion"}, f, indent = 2, separators = (',', ': ')) f.write("\n") + for chunk in rest: + f.write("\n") + json.dump(chunk, f, indent = 2, separators = (',', ': ')) + f.write("\n") + def diff(features, path): base = path.replace(".json", "") diff --git a/tests/cputestdata/cpu-gather.sh b/tests/cputestdata/cpu-gather.sh index 83963557ec..9c696f57bd 100755 --- a/tests/cputestdata/cpu-gather.sh +++ b/tests/cputestdata/cpu-gather.sh @@ -58,5 +58,6 @@ $( qom_get model-id fi ) +{"execute":"query-cpu-definitions","id":"definitions"} {"execute":"quit"} EOF -- 2.14.2

On 10/04/2017 10:58 AM, Jiri Denemark wrote:
Gather query-cpu-definitions results and use them for testing CPU model usability blockers in CPUID to virCPUDef translation.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/qemu/qemu_capabilities.c | 2 +- src/qemu/qemu_capspriv.h | 5 +++++ tests/cputest.c | 12 +++++++++++- tests/cputestdata/cpu-cpuid.py | 26 +++++++++++++++++++------- tests/cputestdata/cpu-gather.sh | 1 + 5 files changed, 37 insertions(+), 9 deletions(-)
Again python not my specialty ... although it would seem string manipulation would be so much easier for 'parseFeatureWords' Reviewed-by: John Ferlan <jferlan@redhat.com> John

To make the code reusable by other tests. Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- tests/cputest.c | 97 +++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 60 insertions(+), 37 deletions(-) diff --git a/tests/cputest.c b/tests/cputest.c index 0a07a2da14..b72c17a168 100644 --- a/tests/cputest.c +++ b/tests/cputest.c @@ -460,6 +460,64 @@ cpuTestHasFeature(const void *arg) } +typedef enum { + JSON_NONE, + JSON_HOST, + JSON_MODELS, +} cpuTestCPUIDJson; + +#if WITH_QEMU && WITH_YAJL +static virQEMUCapsPtr +cpuTestMakeQEMUCaps(const struct data *data) +{ + virQEMUCapsPtr qemuCaps = NULL; + qemuMonitorTestPtr testMon = NULL; + qemuMonitorCPUModelInfoPtr model = NULL; + char *json = NULL; + + if (virAsprintf(&json, "%s/cputestdata/%s-cpuid-%s.json", + abs_srcdir, virArchToString(data->arch), data->host) < 0) + goto error; + + if (!(testMon = qemuMonitorTestNewFromFile(json, driver.xmlopt, true))) + goto error; + + if (qemuMonitorGetCPUModelExpansion(qemuMonitorTestGetMonitor(testMon), + QEMU_MONITOR_CPU_MODEL_EXPANSION_STATIC, + "host", true, &model) < 0) + goto error; + + if (!(qemuCaps = virQEMUCapsNew())) + goto error; + + virQEMUCapsSet(qemuCaps, QEMU_CAPS_KVM); + if (data->flags == JSON_MODELS) + virQEMUCapsSet(qemuCaps, QEMU_CAPS_QUERY_CPU_DEFINITIONS); + + virQEMUCapsSetArch(qemuCaps, data->arch); + virQEMUCapsSetCPUModelInfo(qemuCaps, VIR_DOMAIN_VIRT_KVM, model); + model = NULL; + + if (virQEMUCapsProbeQMPCPUDefinitions(qemuCaps, + qemuMonitorTestGetMonitor(testMon), + false) < 0) + goto error; + + cleanup: + qemuMonitorCPUModelInfoFree(model); + qemuMonitorTestFree(testMon); + VIR_FREE(json); + + return qemuCaps; + + error: + virObjectUnref(qemuCaps); + qemuCaps = NULL; + goto cleanup; +} +#endif + + static int cpuTestCPUID(bool guest, const void *arg) { @@ -670,52 +728,20 @@ cpuTestUpdateLive(const void *arg) } -typedef enum { - JSON_NONE, - JSON_HOST, - JSON_MODELS, -} cpuTestCPUIDJson; - #if WITH_QEMU && WITH_YAJL static int cpuTestJSONCPUID(const void *arg) { const struct data *data = arg; - qemuMonitorCPUModelInfoPtr model = NULL; virQEMUCapsPtr qemuCaps = NULL; virCPUDefPtr cpu = NULL; - qemuMonitorTestPtr testMon = NULL; - char *json = NULL; char *result = NULL; int ret = -1; - if (virAsprintf(&json, "%s/cputestdata/%s-cpuid-%s.json", - abs_srcdir, virArchToString(data->arch), data->host) < 0 || - virAsprintf(&result, "cpuid-%s-json", data->host) < 0) + if (virAsprintf(&result, "cpuid-%s-json", data->host) < 0) goto cleanup; - if (!(testMon = qemuMonitorTestNewFromFile(json, driver.xmlopt, true))) - goto cleanup; - - if (qemuMonitorGetCPUModelExpansion(qemuMonitorTestGetMonitor(testMon), - QEMU_MONITOR_CPU_MODEL_EXPANSION_STATIC, - "host", true, &model) < 0) - goto cleanup; - - if (!(qemuCaps = virQEMUCapsNew())) - goto cleanup; - - virQEMUCapsSet(qemuCaps, QEMU_CAPS_KVM); - if (data->flags == JSON_MODELS) - virQEMUCapsSet(qemuCaps, QEMU_CAPS_QUERY_CPU_DEFINITIONS); - - virQEMUCapsSetArch(qemuCaps, data->arch); - virQEMUCapsSetCPUModelInfo(qemuCaps, VIR_DOMAIN_VIRT_KVM, model); - model = NULL; - - if (virQEMUCapsProbeQMPCPUDefinitions(qemuCaps, - qemuMonitorTestGetMonitor(testMon), - false) < 0) + if (!(qemuCaps = cpuTestMakeQEMUCaps(data))) goto cleanup; if (VIR_ALLOC(cpu) < 0) @@ -732,12 +758,9 @@ cpuTestJSONCPUID(const void *arg) ret = cpuTestCompareXML(data->arch, cpu, result); cleanup: - qemuMonitorCPUModelInfoFree(model); virObjectUnref(qemuCaps); - qemuMonitorTestFree(testMon); virCPUDefFree(cpu); VIR_FREE(result); - VIR_FREE(json); return ret; } #endif -- 2.14.2

On 10/04/2017 10:58 AM, Jiri Denemark wrote:
To make the code reusable by other tests.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- tests/cputest.c | 97 +++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 60 insertions(+), 37 deletions(-)
diff --git a/tests/cputest.c b/tests/cputest.c index 0a07a2da14..b72c17a168 100644 --- a/tests/cputest.c +++ b/tests/cputest.c @@ -460,6 +460,64 @@ cpuTestHasFeature(const void *arg) }
+typedef enum { + JSON_NONE, + JSON_HOST, + JSON_MODELS, +} cpuTestCPUIDJson; + +#if WITH_QEMU && WITH_YAJL +static virQEMUCapsPtr +cpuTestMakeQEMUCaps(const struct data *data) +{ + virQEMUCapsPtr qemuCaps = NULL; + qemuMonitorTestPtr testMon = NULL; + qemuMonitorCPUModelInfoPtr model = NULL; + char *json = NULL; + + if (virAsprintf(&json, "%s/cputestdata/%s-cpuid-%s.json", + abs_srcdir, virArchToString(data->arch), data->host) < 0) + goto error;
could be cleanup;
+ + if (!(testMon = qemuMonitorTestNewFromFile(json, driver.xmlopt, true))) + goto error;
same
+ + if (qemuMonitorGetCPUModelExpansion(qemuMonitorTestGetMonitor(testMon), + QEMU_MONITOR_CPU_MODEL_EXPANSION_STATIC, + "host", true, &model) < 0) + goto error;
same
+ + if (!(qemuCaps = virQEMUCapsNew())) + goto error;
same
+ + virQEMUCapsSet(qemuCaps, QEMU_CAPS_KVM); + if (data->flags == JSON_MODELS) + virQEMUCapsSet(qemuCaps, QEMU_CAPS_QUERY_CPU_DEFINITIONS); + + virQEMUCapsSetArch(qemuCaps, data->arch); + virQEMUCapsSetCPUModelInfo(qemuCaps, VIR_DOMAIN_VIRT_KVM, model); + model = NULL; + + if (virQEMUCapsProbeQMPCPUDefinitions(qemuCaps, + qemuMonitorTestGetMonitor(testMon), + false) < 0) + goto error;
Leaving only this one...
+ + cleanup: + qemuMonitorCPUModelInfoFree(model); + qemuMonitorTestFree(testMon); + VIR_FREE(json); + + return qemuCaps; + + error: + virObjectUnref(qemuCaps); + qemuCaps = NULL; + goto cleanup; +} +#endif + + static int cpuTestCPUID(bool guest, const void *arg) { @@ -670,52 +728,20 @@ cpuTestUpdateLive(const void *arg) }
-typedef enum { - JSON_NONE, - JSON_HOST, - JSON_MODELS, -} cpuTestCPUIDJson; - #if WITH_QEMU && WITH_YAJL static int cpuTestJSONCPUID(const void *arg) { const struct data *data = arg; - qemuMonitorCPUModelInfoPtr model = NULL; virQEMUCapsPtr qemuCaps = NULL; virCPUDefPtr cpu = NULL; - qemuMonitorTestPtr testMon = NULL; - char *json = NULL; char *result = NULL; int ret = -1;
- if (virAsprintf(&json, "%s/cputestdata/%s-cpuid-%s.json", - abs_srcdir, virArchToString(data->arch), data->host) < 0 || - virAsprintf(&result, "cpuid-%s-json", data->host) < 0) + if (virAsprintf(&result, "cpuid-%s-json", data->host) < 0) goto cleanup;
This one could seemingly just return -1 although what's here works, just a few extra steps to functions that do nothing. With or without adjustments... Reviewed-by: John Ferlan <jferlan@redhat.com> John
- if (!(testMon = qemuMonitorTestNewFromFile(json, driver.xmlopt, true))) - goto cleanup; - - if (qemuMonitorGetCPUModelExpansion(qemuMonitorTestGetMonitor(testMon), - QEMU_MONITOR_CPU_MODEL_EXPANSION_STATIC, - "host", true, &model) < 0) - goto cleanup; - - if (!(qemuCaps = virQEMUCapsNew())) - goto cleanup; - - virQEMUCapsSet(qemuCaps, QEMU_CAPS_KVM); - if (data->flags == JSON_MODELS) - virQEMUCapsSet(qemuCaps, QEMU_CAPS_QUERY_CPU_DEFINITIONS); - - virQEMUCapsSetArch(qemuCaps, data->arch); - virQEMUCapsSetCPUModelInfo(qemuCaps, VIR_DOMAIN_VIRT_KVM, model); - model = NULL; - - if (virQEMUCapsProbeQMPCPUDefinitions(qemuCaps, - qemuMonitorTestGetMonitor(testMon), - false) < 0) + if (!(qemuCaps = cpuTestMakeQEMUCaps(data))) goto cleanup;
if (VIR_ALLOC(cpu) < 0) @@ -732,12 +758,9 @@ cpuTestJSONCPUID(const void *arg) ret = cpuTestCompareXML(data->arch, cpu, result);
cleanup: - qemuMonitorCPUModelInfoFree(model); virObjectUnref(qemuCaps); - qemuMonitorTestFree(testMon); virCPUDefFree(cpu); VIR_FREE(result); - VIR_FREE(json); return ret; } #endif

On Thu, Oct 12, 2017 at 17:20:06 -0400, John Ferlan wrote:
On 10/04/2017 10:58 AM, Jiri Denemark wrote:
To make the code reusable by other tests.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- tests/cputest.c | 97 +++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 60 insertions(+), 37 deletions(-)
diff --git a/tests/cputest.c b/tests/cputest.c index 0a07a2da14..b72c17a168 100644 --- a/tests/cputest.c +++ b/tests/cputest.c @@ -460,6 +460,64 @@ cpuTestHasFeature(const void *arg) }
+typedef enum { + JSON_NONE, + JSON_HOST, + JSON_MODELS, +} cpuTestCPUIDJson; + +#if WITH_QEMU && WITH_YAJL +static virQEMUCapsPtr +cpuTestMakeQEMUCaps(const struct data *data) +{ + virQEMUCapsPtr qemuCaps = NULL; + qemuMonitorTestPtr testMon = NULL; + qemuMonitorCPUModelInfoPtr model = NULL; + char *json = NULL; + + if (virAsprintf(&json, "%s/cputestdata/%s-cpuid-%s.json", + abs_srcdir, virArchToString(data->arch), data->host) < 0) + goto error;
could be cleanup;
Yeah, but since we have the "error" label and we are jumping in case of error I think it's slightly better to keep it as is. And it's less fragile when someone comes and shuffles the code around. I don't really mind either way, though. Jirka

On 10/13/2017 01:27 PM, Jiri Denemark wrote:
On Thu, Oct 12, 2017 at 17:20:06 -0400, John Ferlan wrote:
On 10/04/2017 10:58 AM, Jiri Denemark wrote:
To make the code reusable by other tests.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- tests/cputest.c | 97 +++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 60 insertions(+), 37 deletions(-)
diff --git a/tests/cputest.c b/tests/cputest.c index 0a07a2da14..b72c17a168 100644 --- a/tests/cputest.c +++ b/tests/cputest.c @@ -460,6 +460,64 @@ cpuTestHasFeature(const void *arg) }
+typedef enum { + JSON_NONE, + JSON_HOST, + JSON_MODELS, +} cpuTestCPUIDJson; + +#if WITH_QEMU && WITH_YAJL +static virQEMUCapsPtr +cpuTestMakeQEMUCaps(const struct data *data) +{ + virQEMUCapsPtr qemuCaps = NULL; + qemuMonitorTestPtr testMon = NULL; + qemuMonitorCPUModelInfoPtr model = NULL; + char *json = NULL; + + if (virAsprintf(&json, "%s/cputestdata/%s-cpuid-%s.json", + abs_srcdir, virArchToString(data->arch), data->host) < 0) + goto error;
could be cleanup;
Yeah, but since we have the "error" label and we are jumping in case of error I think it's slightly better to keep it as is. And it's less fragile when someone comes and shuffles the code around. I don't really mind either way, though.
Jirka
Fair enough - leave it it as is. It wasn't that important. John

Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/libvirt_private.syms | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 5b1bc5e4fe..7494955845 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1113,6 +1113,7 @@ virCPUExpandFeatures; virCPUGetHost; virCPUGetHostIsSupported; virCPUGetModels; +virCPUModelIsAllowed; virCPUProbeHost; virCPUTranslate; virCPUUpdate; -- 2.14.2

On 10/04/2017 10:58 AM, Jiri Denemark wrote:
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/libvirt_private.syms | 1 + 1 file changed, 1 insertion(+)
This should either be merged earlier when changing the function arguments or in reality in the "next" patch which actually uses it. Reviewed-by: John Ferlan <jferlan@redhat.com> John

On Thu, Oct 12, 2017 at 17:20:18 -0400, John Ferlan wrote:
On 10/04/2017 10:58 AM, Jiri Denemark wrote:
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- src/libvirt_private.syms | 1 + 1 file changed, 1 insertion(+)
This should either be merged earlier when changing the function arguments or in reality in the "next" patch which actually uses it.
Or dropped completely in favor of virDomainCapsCPUModelsGet. Jirka

When testing cpuDecode for computing guest CPU definition from CPUID data (the CPU definition reported by domain capabilities), we need to use CPU models (and their usability blockers) from QEMU if they are available to cpuDecode in the same way it is actually used in the qemu driver. Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- tests/cputest.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 75 insertions(+), 6 deletions(-) diff --git a/tests/cputest.c b/tests/cputest.c index b72c17a168..18618ad309 100644 --- a/tests/cputest.c +++ b/tests/cputest.c @@ -515,6 +515,37 @@ cpuTestMakeQEMUCaps(const struct data *data) qemuCaps = NULL; goto cleanup; } + + +static virDomainCapsCPUModelsPtr +cpuTestGetCPUModels(const struct data *data) +{ + virDomainCapsCPUModelsPtr models = NULL; + virQEMUCapsPtr qemuCaps; + + if (data->flags != JSON_MODELS) + return NULL; + + if (!(qemuCaps = cpuTestMakeQEMUCaps(data))) + return NULL; + + models = virQEMUCapsGetCPUDefinitions(qemuCaps, VIR_DOMAIN_VIRT_KVM); + if (models) + virObjectRef(models); + + virObjectUnref(qemuCaps); + + return models; +} + +#else /* if WITH_QEMU && WITH_YAJL */ + +static virDomainCapsCPUModelsPtr +cpuTestGetCPUModels(const struct data *data ATTRIBUTE_UNUSED) +{ + return NULL; +} + #endif @@ -528,6 +559,7 @@ cpuTestCPUID(bool guest, const void *arg) char *host = NULL; virCPUDefPtr cpu = NULL; char *result = NULL; + virDomainCapsCPUModelsPtr models = NULL; if (virAsprintf(&hostFile, "%s/cputestdata/%s-cpuid-%s.xml", abs_srcdir, virArchToString(data->arch), data->host) < 0) @@ -549,7 +581,10 @@ cpuTestCPUID(bool guest, const void *arg) cpu->type = VIR_CPU_TYPE_HOST; } - if (cpuDecode(cpu, hostData, NULL) < 0) + if (guest) + models = cpuTestGetCPUModels(data); + + if (cpuDecode(cpu, hostData, models) < 0) goto cleanup; if (virAsprintf(&result, "cpuid-%s-%s", @@ -565,6 +600,7 @@ cpuTestCPUID(bool guest, const void *arg) virCPUDataFree(hostData); virCPUDefFree(cpu); VIR_FREE(result); + virObjectUnref(models); return ret; } @@ -686,6 +722,8 @@ cpuTestUpdateLive(const void *arg) virCPUDataPtr disabledData = NULL; char *expectedFile = NULL; virCPUDefPtr expected = NULL; + virDomainCapsCPUModelsPtr hvModels = NULL; + virDomainCapsCPUModelsPtr models = NULL; int ret = -1; if (virAsprintf(&cpuFile, "cpuid-%s-guest", data->host) < 0 || @@ -704,13 +742,42 @@ cpuTestUpdateLive(const void *arg) !(disabledData = virCPUDataParse(disabled))) goto cleanup; - if (virCPUUpdateLive(data->arch, cpu, enabledData, disabledData) < 0) - goto cleanup; - if (virAsprintf(&expectedFile, "cpuid-%s-json", data->host) < 0 || !(expected = cpuTestLoadXML(data->arch, expectedFile))) goto cleanup; + /* In case the host CPU signature does not exactly match any CPU model from + * cpu_map.xml, the CPU model we detect from CPUID may differ from the one + * we compute by asking QEMU. Since this test expands both CPU models and + * compares their features, we can try to translate the 'actual' CPU to + * use the CPU model from 'expected'. + */ + if (STRNEQ(cpu->model, expected->model)) { + virDomainCapsCPUModelPtr hvModel; + char **blockers = NULL; + virDomainCapsCPUUsable usable = VIR_DOMCAPS_CPU_USABLE_UNKNOWN; + + if (!(models = virDomainCapsCPUModelsNew(0))) + goto cleanup; + + if ((hvModels = cpuTestGetCPUModels(data)) && + virCPUModelIsAllowed(expected->model, hvModels, &hvModel)) { + blockers = hvModel->blockers; + usable = hvModel->usable; + } + + if (virDomainCapsCPUModelsAdd(models, expected->model, -1, + usable, blockers) < 0) + goto cleanup; + + cpu->fallback = VIR_CPU_FALLBACK_ALLOW; + ignore_value(virCPUTranslate(data->arch, cpu, models)); + cpu->fallback = VIR_CPU_FALLBACK_FORBID; + } + + if (virCPUUpdateLive(data->arch, cpu, enabledData, disabledData) < 0) + goto cleanup; + ret = cpuTestUpdateLiveCompare(data->arch, cpu, expected); cleanup: @@ -724,6 +791,8 @@ cpuTestUpdateLive(const void *arg) virCPUDataFree(disabledData); VIR_FREE(expectedFile); virCPUDefFree(expected); + virObjectUnref(hvModels); + virObjectUnref(models); return ret; } @@ -915,11 +984,11 @@ mymain(void) DO_TEST(arch, cpuTestHostCPUID, host, host, \ NULL, NULL, 0, 0); \ DO_TEST(arch, cpuTestGuestCPUID, host, host, \ - NULL, NULL, 0, 0); \ + NULL, NULL, json, 0); \ DO_TEST_CPUID_JSON(arch, host, json); \ if (json != JSON_NONE) { \ DO_TEST(arch, cpuTestUpdateLive, host, host, \ - NULL, NULL, 0, 0); \ + NULL, NULL, json, 0); \ } \ } while (0) -- 2.14.2

On 10/04/2017 10:58 AM, Jiri Denemark wrote:
When testing cpuDecode for computing guest CPU definition from CPUID data (the CPU definition reported by domain capabilities), we need to use CPU models (and their usability blockers) from QEMU if they are available to cpuDecode in the same way it is actually used in the qemu driver.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- tests/cputest.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 75 insertions(+), 6 deletions(-)
diff --git a/tests/cputest.c b/tests/cputest.c index b72c17a168..18618ad309 100644 --- a/tests/cputest.c +++ b/tests/cputest.c @@ -515,6 +515,37 @@ cpuTestMakeQEMUCaps(const struct data *data) qemuCaps = NULL; goto cleanup; } + + +static virDomainCapsCPUModelsPtr +cpuTestGetCPUModels(const struct data *data) +{ + virDomainCapsCPUModelsPtr models = NULL; + virQEMUCapsPtr qemuCaps; + + if (data->flags != JSON_MODELS) + return NULL; + + if (!(qemuCaps = cpuTestMakeQEMUCaps(data))) + return NULL; + + models = virQEMUCapsGetCPUDefinitions(qemuCaps, VIR_DOMAIN_VIRT_KVM); + if (models) + virObjectRef(models);
As I learned a while back virObjectRef() works on a NULL @models - so no need for the if (models) (and the Unref already doesn't have one).
+ + virObjectUnref(qemuCaps); + + return models; +} +
Reviewed-by: John Ferlan <jferlan@redhat.com> John

On Thu, Oct 12, 2017 at 17:21:53 -0400, John Ferlan wrote:
On 10/04/2017 10:58 AM, Jiri Denemark wrote:
When testing cpuDecode for computing guest CPU definition from CPUID data (the CPU definition reported by domain capabilities), we need to use CPU models (and their usability blockers) from QEMU if they are available to cpuDecode in the same way it is actually used in the qemu driver.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- tests/cputest.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 75 insertions(+), 6 deletions(-)
diff --git a/tests/cputest.c b/tests/cputest.c index b72c17a168..18618ad309 100644 --- a/tests/cputest.c +++ b/tests/cputest.c @@ -515,6 +515,37 @@ cpuTestMakeQEMUCaps(const struct data *data) qemuCaps = NULL; goto cleanup; } + + +static virDomainCapsCPUModelsPtr +cpuTestGetCPUModels(const struct data *data) +{ + virDomainCapsCPUModelsPtr models = NULL; + virQEMUCapsPtr qemuCaps; + + if (data->flags != JSON_MODELS) + return NULL; + + if (!(qemuCaps = cpuTestMakeQEMUCaps(data))) + return NULL; + + models = virQEMUCapsGetCPUDefinitions(qemuCaps, VIR_DOMAIN_VIRT_KVM); + if (models) + virObjectRef(models);
As I learned a while back virObjectRef() works on a NULL @models - so no need for the if (models) (and the Unref already doesn't have one).
Oh right. Somehow when I was checking it, I looked at VIR_OBJECT_NOTVALID macro and completely ignored its body and looked at the body of VIR_OBJECT_USAGE_PRINT_WARNING macro instead which made me think virObjectRef prints some nasty warnings when obj == NULL. Jirka

The unavailable features do not make any difference in this case, because this is a SandyBridge CPU which has an empty list of unavailable features. Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- tests/cputest.c | 2 +- tests/cputestdata/x86_64-cpuid-Core-i5-2540M.json | 362 ++++++++++++++++++++++ 2 files changed, 363 insertions(+), 1 deletion(-) diff --git a/tests/cputest.c b/tests/cputest.c index 18618ad309..1af467e5ee 100644 --- a/tests/cputest.c +++ b/tests/cputest.c @@ -1121,7 +1121,7 @@ mymain(void) DO_TEST_CPUID(VIR_ARCH_X86_64, "Atom-D510", JSON_NONE); DO_TEST_CPUID(VIR_ARCH_X86_64, "Atom-N450", JSON_NONE); DO_TEST_CPUID(VIR_ARCH_X86_64, "Core-i5-2500", JSON_HOST); - DO_TEST_CPUID(VIR_ARCH_X86_64, "Core-i5-2540M", JSON_HOST); + DO_TEST_CPUID(VIR_ARCH_X86_64, "Core-i5-2540M", JSON_MODELS); DO_TEST_CPUID(VIR_ARCH_X86_64, "Core-i5-4670T", JSON_HOST); DO_TEST_CPUID(VIR_ARCH_X86_64, "Core-i5-6600", JSON_HOST); DO_TEST_CPUID(VIR_ARCH_X86_64, "Core-i7-2600", JSON_HOST); diff --git a/tests/cputestdata/x86_64-cpuid-Core-i5-2540M.json b/tests/cputestdata/x86_64-cpuid-Core-i5-2540M.json index d813326f6f..a8ed64ed63 100644 --- a/tests/cputestdata/x86_64-cpuid-Core-i5-2540M.json +++ b/tests/cputestdata/x86_64-cpuid-Core-i5-2540M.json @@ -201,3 +201,365 @@ }, "id": "model-expansion" } + +{ + "return": [ + { + "typename": "max-x86_64-cpu", + "unavailable-features": [], + "migration-safe": false, + "static": false, + "name": "max" + }, + { + "typename": "host-x86_64-cpu", + "unavailable-features": [], + "migration-safe": false, + "static": false, + "name": "host" + }, + { + "typename": "base-x86_64-cpu", + "unavailable-features": [], + "migration-safe": true, + "static": true, + "name": "base" + }, + { + "typename": "qemu64-x86_64-cpu", + "unavailable-features": [], + "migration-safe": true, + "static": false, + "name": "qemu64" + }, + { + "typename": "qemu32-x86_64-cpu", + "unavailable-features": [], + "migration-safe": true, + "static": false, + "name": "qemu32" + }, + { + "typename": "phenom-x86_64-cpu", + "unavailable-features": [ + "mmxext", + "fxsr-opt", + "pdpe1gb", + "3dnowext", + "3dnow", + "abm", + "sse4a", + "npt" + ], + "migration-safe": true, + "static": false, + "name": "phenom" + }, + { + "typename": "pentium3-x86_64-cpu", + "unavailable-features": [], + "migration-safe": true, + "static": false, + "name": "pentium3" + }, + { + "typename": "pentium2-x86_64-cpu", + "unavailable-features": [], + "migration-safe": true, + "static": false, + "name": "pentium2" + }, + { + "typename": "pentium-x86_64-cpu", + "unavailable-features": [], + "migration-safe": true, + "static": false, + "name": "pentium" + }, + { + "typename": "n270-x86_64-cpu", + "unavailable-features": [ + "movbe" + ], + "migration-safe": true, + "static": false, + "name": "n270" + }, + { + "typename": "kvm64-x86_64-cpu", + "unavailable-features": [], + "migration-safe": true, + "static": false, + "name": "kvm64" + }, + { + "typename": "kvm32-x86_64-cpu", + "unavailable-features": [], + "migration-safe": true, + "static": false, + "name": "kvm32" + }, + { + "typename": "coreduo-x86_64-cpu", + "unavailable-features": [], + "migration-safe": true, + "static": false, + "name": "coreduo" + }, + { + "typename": "core2duo-x86_64-cpu", + "unavailable-features": [], + "migration-safe": true, + "static": false, + "name": "core2duo" + }, + { + "typename": "athlon-x86_64-cpu", + "unavailable-features": [ + "mmxext", + "3dnowext", + "3dnow" + ], + "migration-safe": true, + "static": false, + "name": "athlon" + }, + { + "typename": "Westmere-x86_64-cpu", + "unavailable-features": [], + "migration-safe": true, + "static": false, + "name": "Westmere" + }, + { + "typename": "Skylake-Client-x86_64-cpu", + "unavailable-features": [ + "fma", + "movbe", + "f16c", + "rdrand", + "fsgsbase", + "bmi1", + "hle", + "avx2", + "smep", + "bmi2", + "erms", + "invpcid", + "rtm", + "mpx", + "rdseed", + "adx", + "smap", + "abm", + "3dnowprefetch", + "xsavec", + "xgetbv1", + "mpx", + "mpx" + ], + "migration-safe": true, + "static": false, + "name": "Skylake-Client" + }, + { + "typename": "SandyBridge-x86_64-cpu", + "unavailable-features": [], + "migration-safe": true, + "static": false, + "name": "SandyBridge" + }, + { + "typename": "Penryn-x86_64-cpu", + "unavailable-features": [], + "migration-safe": true, + "static": false, + "name": "Penryn" + }, + { + "typename": "Opteron_G5-x86_64-cpu", + "unavailable-features": [ + "fma", + "f16c", + "pdpe1gb", + "abm", + "sse4a", + "misalignsse", + "3dnowprefetch", + "xop", + "fma4", + "tbm" + ], + "migration-safe": true, + "static": false, + "name": "Opteron_G5" + }, + { + "typename": "Opteron_G4-x86_64-cpu", + "unavailable-features": [ + "pdpe1gb", + "abm", + "sse4a", + "misalignsse", + "3dnowprefetch", + "xop", + "fma4" + ], + "migration-safe": true, + "static": false, + "name": "Opteron_G4" + }, + { + "typename": "Opteron_G3-x86_64-cpu", + "unavailable-features": [ + "abm", + "sse4a", + "misalignsse" + ], + "migration-safe": true, + "static": false, + "name": "Opteron_G3" + }, + { + "typename": "Opteron_G2-x86_64-cpu", + "unavailable-features": [], + "migration-safe": true, + "static": false, + "name": "Opteron_G2" + }, + { + "typename": "Opteron_G1-x86_64-cpu", + "unavailable-features": [], + "migration-safe": true, + "static": false, + "name": "Opteron_G1" + }, + { + "typename": "Nehalem-x86_64-cpu", + "unavailable-features": [], + "migration-safe": true, + "static": false, + "name": "Nehalem" + }, + { + "typename": "IvyBridge-x86_64-cpu", + "unavailable-features": [ + "f16c", + "rdrand", + "fsgsbase", + "smep", + "erms" + ], + "migration-safe": true, + "static": false, + "name": "IvyBridge" + }, + { + "typename": "Haswell-x86_64-cpu", + "unavailable-features": [ + "fma", + "movbe", + "f16c", + "rdrand", + "fsgsbase", + "bmi1", + "hle", + "avx2", + "smep", + "bmi2", + "erms", + "invpcid", + "rtm", + "abm" + ], + "migration-safe": true, + "static": false, + "name": "Haswell" + }, + { + "typename": "Haswell-noTSX-x86_64-cpu", + "unavailable-features": [ + "fma", + "movbe", + "f16c", + "rdrand", + "fsgsbase", + "bmi1", + "avx2", + "smep", + "bmi2", + "erms", + "invpcid", + "abm" + ], + "migration-safe": true, + "static": false, + "name": "Haswell-noTSX" + }, + { + "typename": "Conroe-x86_64-cpu", + "unavailable-features": [], + "migration-safe": true, + "static": false, + "name": "Conroe" + }, + { + "typename": "Broadwell-x86_64-cpu", + "unavailable-features": [ + "fma", + "movbe", + "f16c", + "rdrand", + "fsgsbase", + "bmi1", + "hle", + "avx2", + "smep", + "bmi2", + "erms", + "invpcid", + "rtm", + "rdseed", + "adx", + "smap", + "abm", + "3dnowprefetch" + ], + "migration-safe": true, + "static": false, + "name": "Broadwell" + }, + { + "typename": "Broadwell-noTSX-x86_64-cpu", + "unavailable-features": [ + "fma", + "movbe", + "f16c", + "rdrand", + "fsgsbase", + "bmi1", + "avx2", + "smep", + "bmi2", + "erms", + "invpcid", + "rdseed", + "adx", + "smap", + "abm", + "3dnowprefetch" + ], + "migration-safe": true, + "static": false, + "name": "Broadwell-noTSX" + }, + { + "typename": "486-x86_64-cpu", + "unavailable-features": [], + "migration-safe": true, + "static": false, + "name": "486" + } + ], + "id": "definitions" +} -- 2.14.2

On 10/04/2017 10:58 AM, Jiri Denemark wrote:
The unavailable features do not make any difference in this case, because this is a SandyBridge CPU which has an empty list of unavailable features.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- tests/cputest.c | 2 +- tests/cputestdata/x86_64-cpuid-Core-i5-2540M.json | 362 ++++++++++++++++++++++ 2 files changed, 363 insertions(+), 1 deletion(-)
[...]
diff --git a/tests/cputestdata/x86_64-cpuid-Core-i5-2540M.json b/tests/cputestdata/x86_64-cpuid-Core-i5-2540M.json index d813326f6f..a8ed64ed63 100644 --- a/tests/cputestdata/x86_64-cpuid-Core-i5-2540M.json +++ b/tests/cputestdata/x86_64-cpuid-Core-i5-2540M.json
[...]
+ { + "typename": "Skylake-Client-x86_64-cpu", + "unavailable-features": [ + "fma", + "movbe", + "f16c", + "rdrand", + "fsgsbase", + "bmi1", + "hle", + "avx2", + "smep", + "bmi2", + "erms", + "invpcid", + "rtm", + "mpx", + "rdseed", + "adx", + "smap", + "abm", + "3dnowprefetch", + "xsavec", + "xgetbv1", + "mpx", + "mpx"
Is this a typo or bad cut-n-paste - "mpx" three times in the list?
+ ], + "migration-safe": true, + "static": false, + "name": "Skylake-Client" + },
Others seemed fine... Tried looking through QEMU sources - got lost quickly and gave up. Reviewed-by: John Ferlan <jferlan@redhat.com> John

On Thu, Oct 12, 2017 at 17:49:33 -0400, John Ferlan wrote:
On 10/04/2017 10:58 AM, Jiri Denemark wrote:
The unavailable features do not make any difference in this case, because this is a SandyBridge CPU which has an empty list of unavailable features.
...
diff --git a/tests/cputestdata/x86_64-cpuid-Core-i5-2540M.json b/tests/cputestdata/x86_64-cpuid-Core-i5-2540M.json index d813326f6f..a8ed64ed63 100644 --- a/tests/cputestdata/x86_64-cpuid-Core-i5-2540M.json +++ b/tests/cputestdata/x86_64-cpuid-Core-i5-2540M.json
[...]
+ { + "typename": "Skylake-Client-x86_64-cpu", + "unavailable-features": [ ... + "mpx", + "mpx"
Is this a typo or bad cut-n-paste - "mpx" three times in the list?
It looks like a bug in QEMU since this is just a copy of real QEMU's reply on a host with this CPU. Some unavailable features appear more that once in the list (you can see it the following patches too). We don't care as long as each unavailable feature is there at least once. Jirka

Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- tests/cputest.c | 1 + .../x86_64-cpuid-Xeon-E7-4830-disabled.xml | 5 + .../x86_64-cpuid-Xeon-E7-4830-enabled.xml | 8 + .../x86_64-cpuid-Xeon-E7-4830-guest.xml | 28 +++ .../cputestdata/x86_64-cpuid-Xeon-E7-4830-host.xml | 29 +++ .../cputestdata/x86_64-cpuid-Xeon-E7-4830-json.xml | 13 ++ tests/cputestdata/x86_64-cpuid-Xeon-E7-4830.json | 235 +++++++++++++++++++++ tests/cputestdata/x86_64-cpuid-Xeon-E7-4830.xml | 30 +++ 8 files changed, 349 insertions(+) create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-E7-4830-disabled.xml create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-E7-4830-enabled.xml create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-E7-4830-guest.xml create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-E7-4830-host.xml create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-E7-4830-json.xml create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-E7-4830.json create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-E7-4830.xml diff --git a/tests/cputest.c b/tests/cputest.c index 1af467e5ee..f71b4982dd 100644 --- a/tests/cputest.c +++ b/tests/cputest.c @@ -1148,6 +1148,7 @@ mymain(void) DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-E5-2630", JSON_HOST); DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-E5-2650", JSON_HOST); DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-E7-4820", JSON_HOST); + DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-E7-4830", JSON_HOST); DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-E7-8890", JSON_NONE); DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-Gold-6148", JSON_HOST); DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-W3520", JSON_HOST); diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E7-4830-disabled.xml b/tests/cputestdata/x86_64-cpuid-Xeon-E7-4830-disabled.xml new file mode 100644 index 0000000000..a9cbd949e4 --- /dev/null +++ b/tests/cputestdata/x86_64-cpuid-Xeon-E7-4830-disabled.xml @@ -0,0 +1,5 @@ +<!-- Features disabled by QEMU --> +<cpudata arch='x86'> + <cpuid eax_in='0x00000001' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x0004c1fc' edx='0xb0600000'/> + <cpuid eax_in='0x80000007' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000100'/> +</cpudata> diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E7-4830-enabled.xml b/tests/cputestdata/x86_64-cpuid-Xeon-E7-4830-enabled.xml new file mode 100644 index 0000000000..1b80f414e5 --- /dev/null +++ b/tests/cputestdata/x86_64-cpuid-Xeon-E7-4830-enabled.xml @@ -0,0 +1,8 @@ +<!-- Features enabled by QEMU --> +<cpudata arch='x86'> + <cpuid eax_in='0x00000001' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x83ba2203' edx='0x0f8bfbff'/> + <cpuid eax_in='0x00000006' ecx_in='0x00' eax='0x00000004' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/> + <cpuid eax_in='0x00000007' ecx_in='0x00' eax='0x00000000' ebx='0x00000002' ecx='0x00000000' edx='0x00000000'/> + <cpuid eax_in='0x40000001' ecx_in='0x00' eax='0x010000fa' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/> + <cpuid eax_in='0x80000001' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000001' edx='0x2c100800'/> +</cpudata> diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E7-4830-guest.xml b/tests/cputestdata/x86_64-cpuid-Xeon-E7-4830-guest.xml new file mode 100644 index 0000000000..dbf8580a0e --- /dev/null +++ b/tests/cputestdata/x86_64-cpuid-Xeon-E7-4830-guest.xml @@ -0,0 +1,28 @@ +<cpu mode='custom' match='exact'> + <model fallback='forbid'>SandyBridge</model> + <vendor>Intel</vendor> + <feature policy='require' name='vme'/> + <feature policy='require' name='ds'/> + <feature policy='require' name='acpi'/> + <feature policy='require' name='ss'/> + <feature policy='require' name='ht'/> + <feature policy='require' name='tm'/> + <feature policy='require' name='pbe'/> + <feature policy='require' name='dtes64'/> + <feature policy='require' name='monitor'/> + <feature policy='require' name='ds_cpl'/> + <feature policy='require' name='vmx'/> + <feature policy='require' name='smx'/> + <feature policy='require' name='est'/> + <feature policy='require' name='tm2'/> + <feature policy='require' name='xtpr'/> + <feature policy='require' name='pdcm'/> + <feature policy='require' name='pcid'/> + <feature policy='require' name='dca'/> + <feature policy='require' name='arat'/> + <feature policy='require' name='pdpe1gb'/> + <feature policy='require' name='invtsc'/> + <feature policy='disable' name='tsc-deadline'/> + <feature policy='disable' name='xsave'/> + <feature policy='disable' name='avx'/> +</cpu> diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E7-4830-host.xml b/tests/cputestdata/x86_64-cpuid-Xeon-E7-4830-host.xml new file mode 100644 index 0000000000..52902479b9 --- /dev/null +++ b/tests/cputestdata/x86_64-cpuid-Xeon-E7-4830-host.xml @@ -0,0 +1,29 @@ +<cpu> + <arch>x86_64</arch> + <model>Westmere</model> + <vendor>Intel</vendor> + <feature name='vme'/> + <feature name='ds'/> + <feature name='acpi'/> + <feature name='ss'/> + <feature name='ht'/> + <feature name='tm'/> + <feature name='pbe'/> + <feature name='pclmuldq'/> + <feature name='dtes64'/> + <feature name='monitor'/> + <feature name='ds_cpl'/> + <feature name='vmx'/> + <feature name='smx'/> + <feature name='est'/> + <feature name='tm2'/> + <feature name='xtpr'/> + <feature name='pdcm'/> + <feature name='pcid'/> + <feature name='dca'/> + <feature name='x2apic'/> + <feature name='arat'/> + <feature name='pdpe1gb'/> + <feature name='rdtscp'/> + <feature name='invtsc'/> +</cpu> diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E7-4830-json.xml b/tests/cputestdata/x86_64-cpuid-Xeon-E7-4830-json.xml new file mode 100644 index 0000000000..c3f04d00d1 --- /dev/null +++ b/tests/cputestdata/x86_64-cpuid-Xeon-E7-4830-json.xml @@ -0,0 +1,13 @@ +<cpu mode='custom' match='exact'> + <model fallback='forbid'>SandyBridge</model> + <vendor>Intel</vendor> + <feature policy='require' name='vme'/> + <feature policy='require' name='ss'/> + <feature policy='require' name='pcid'/> + <feature policy='require' name='hypervisor'/> + <feature policy='require' name='arat'/> + <feature policy='require' name='tsc_adjust'/> + <feature policy='require' name='pdpe1gb'/> + <feature policy='disable' name='xsave'/> + <feature policy='disable' name='avx'/> +</cpu> diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E7-4830.json b/tests/cputestdata/x86_64-cpuid-Xeon-E7-4830.json new file mode 100644 index 0000000000..012e1d0c5c --- /dev/null +++ b/tests/cputestdata/x86_64-cpuid-Xeon-E7-4830.json @@ -0,0 +1,235 @@ +{ + "return": { + "model": { + "name": "base", + "props": { + "pfthreshold": false, + "pku": false, + "rtm": false, + "tsc_adjust": true, + "tsc-deadline": true, + "xstore-en": false, + "cpuid-0xb": true, + "abm": false, + "ia64": false, + "kvm-mmu": false, + "xsaveopt": false, + "hv-spinlocks": -1, + "tce": false, + "realized": false, + "kvm_steal_time": true, + "smep": false, + "fpu": true, + "xcrypt": false, + "sse4_2": true, + "clflush": true, + "sse4_1": true, + "flushbyasid": false, + "kvm-steal-time": true, + "lm": true, + "tsc": true, + "adx": false, + "fxsr": true, + "sha-ni": false, + "decodeassists": false, + "hv-relaxed": false, + "pclmuldq": true, + "xgetbv1": false, + "xstore": false, + "vmcb_clean": false, + "tsc-adjust": true, + "vme": true, + "vendor": "GenuineIntel", + "arat": true, + "ffxsr": false, + "de": true, + "aes": true, + "pse": true, + "ds-cpl": false, + "fxsr_opt": false, + "tbm": false, + "sse": true, + "phe-en": false, + "f16c": false, + "ds": false, + "mpx": false, + "vmware-cpuid-freq": true, + "avx512f": false, + "avx2": false, + "level": 11, + "pbe": false, + "cx16": true, + "ds_cpl": false, + "movbe": false, + "perfctr-nb": false, + "nrip_save": false, + "kvm_mmu": false, + "ospke": false, + "pmu": false, + "avx512ifma": false, + "stepping": 2, + "sep": true, + "sse4a": false, + "avx512dq": false, + "core-id": -1, + "i64": true, + "avx512-4vnniw": false, + "xsave": false, + "pmm": false, + "hle": false, + "nodeid_msr": false, + "hv-crash": false, + "est": false, + "osxsave": false, + "xop": false, + "smx": false, + "tsc-scale": false, + "monitor": false, + "avx512er": false, + "apic": true, + "sse4.1": true, + "sse4.2": true, + "hv-vapic": false, + "pause-filter": false, + "lahf-lm": true, + "kvm-nopiodelay": true, + "cmp_legacy": false, + "acpi": false, + "fma4": false, + "mmx": true, + "svm_lock": false, + "pcommit": false, + "mtrr": true, + "clwb": false, + "dca": false, + "pdcm": false, + "xcrypt-en": false, + "3dnow": false, + "invtsc": false, + "tm2": false, + "hv-time": false, + "hypervisor": true, + "kvmclock-stable-bit": true, + "xlevel": 2147483656, + "lahf_lm": true, + "enforce": false, + "pcid": true, + "sse4-1": true, + "lbrv": false, + "avx512-vpopcntdq": false, + "avx512-4fmaps": false, + "fill-mtrr-mask": true, + "pause_filter": false, + "svm-lock": false, + "popcnt": true, + "nrip-save": false, + "avx512vl": false, + "x2apic": true, + "kvmclock": true, + "smap": false, + "pdpe1gb": true, + "family": 6, + "min-level": 11, + "xlevel2": 0, + "dtes64": false, + "xd": true, + "kvm_pv_eoi": true, + "ace2": false, + "kvm_pv_unhalt": true, + "xtpr": false, + "perfctr_nb": false, + "avx512bw": false, + "l3-cache": true, + "nx": true, + "lwp": false, + "msr": true, + "syscall": true, + "tm": false, + "perfctr-core": false, + "memory": "/machine/unattached/system[0]", + "pge": true, + "pn": false, + "fma": false, + "nodeid-msr": false, + "xsavec": false, + "socket-id": -1, + "thread-id": -1, + "cx8": true, + "mce": true, + "avx512cd": false, + "cr8legacy": false, + "mca": true, + "avx512pf": false, + "pni": true, + "hv-vendor-id": "", + "rdseed": false, + "osvw": false, + "fsgsbase": false, + "model-id": " Intel(R) Xeon(R) CPU E7- 4830 @ 2.13GHz", + "cmp-legacy": false, + "kvm-pv-unhalt": true, + "rdtscp": true, + "mmxext": false, + "host-phys-bits": true, + "cid": false, + "vmx": false, + "ssse3": true, + "extapic": false, + "pse36": true, + "min-xlevel": 2147483656, + "ibs": false, + "la57": false, + "avx": false, + "kvm-no-smi-migration": false, + "ace2-en": false, + "umip": false, + "invpcid": false, + "bmi1": false, + "bmi2": false, + "vmcb-clean": false, + "erms": false, + "cmov": true, + "check": true, + "perfctr_core": false, + "misalignsse": false, + "clflushopt": false, + "pat": true, + "sse4-2": true, + "3dnowprefetch": false, + "rdpid": false, + "full-cpuid-auto-level": true, + "pae": true, + "wdt": false, + "tsc_scale": false, + "skinit": false, + "fxsr-opt": false, + "kvm_nopiodelay": true, + "phys-bits": 0, + "kvm": true, + "pmm-en": false, + "phe": false, + "3dnowext": false, + "lmce": true, + "ht": false, + "tsc-frequency": 0, + "kvm-pv-eoi": true, + "npt": false, + "apic-id": 4294967295, + "kvm_asyncpf": true, + "min-xlevel2": 0, + "pclmulqdq": true, + "svm": false, + "sse3": true, + "sse2": true, + "ss": true, + "topoext": false, + "rdrand": false, + "avx512vbmi": false, + "kvm-asyncpf": true, + "xsaves": false, + "model": 47 + } + } + }, + "id": "model-expansion" +} diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E7-4830.xml b/tests/cputestdata/x86_64-cpuid-Xeon-E7-4830.xml new file mode 100644 index 0000000000..d565238167 --- /dev/null +++ b/tests/cputestdata/x86_64-cpuid-Xeon-E7-4830.xml @@ -0,0 +1,30 @@ +<!-- Intel(R) Xeon(R) CPU E7- 4830 @ 2.13GHz --> +<cpudata arch='x86'> + <cpuid eax_in='0x00000000' ecx_in='0x00' eax='0x0000000b' ebx='0x756e6547' ecx='0x6c65746e' edx='0x49656e69'/> + <cpuid eax_in='0x00000001' ecx_in='0x00' eax='0x000206f2' ebx='0x80400800' ecx='0x02bee3ff' edx='0xbfebfbff'/> + <cpuid eax_in='0x00000002' ecx_in='0x00' eax='0x55035a01' ebx='0x00f0b2ec' ecx='0x00000000' edx='0x09ca212c'/> + <cpuid eax_in='0x00000003' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/> + <cpuid eax_in='0x00000004' ecx_in='0x00' eax='0x7c004121' ebx='0x01c0003f' ecx='0x0000003f' edx='0x00000000'/> + <cpuid eax_in='0x00000004' ecx_in='0x01' eax='0x7c004122' ebx='0x00c0003f' ecx='0x0000007f' edx='0x00000000'/> + <cpuid eax_in='0x00000004' ecx_in='0x02' eax='0x7c004143' ebx='0x01c0003f' ecx='0x000001ff' edx='0x00000000'/> + <cpuid eax_in='0x00000004' ecx_in='0x03' eax='0x7c0fc163' ebx='0x05c0003f' ecx='0x00003fff' edx='0x00000006'/> + <cpuid eax_in='0x00000005' ecx_in='0x00' eax='0x00000040' ebx='0x00000040' ecx='0x00000003' edx='0x00001120'/> + <cpuid eax_in='0x00000006' ecx_in='0x00' eax='0x00000007' ebx='0x00000001' ecx='0x00000009' edx='0x00000000'/> + <cpuid eax_in='0x00000007' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/> + <cpuid eax_in='0x00000008' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/> + <cpuid eax_in='0x00000009' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/> + <cpuid eax_in='0x0000000a' ecx_in='0x00' eax='0x07300403' ebx='0x00000004' ecx='0x00000000' edx='0x00000603'/> + <cpuid eax_in='0x0000000b' ecx_in='0x00' eax='0x00000001' ebx='0x00000002' ecx='0x00000100' edx='0x00000080'/> + <cpuid eax_in='0x0000000b' ecx_in='0x01' eax='0x00000006' ebx='0x00000010' ecx='0x00000201' edx='0x00000080'/> + <cpuid eax_in='0x80000000' ecx_in='0x00' eax='0x80000008' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/> + <cpuid eax_in='0x80000001' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000001' edx='0x2c100800'/> + <cpuid eax_in='0x80000002' ecx_in='0x00' eax='0x20202020' ebx='0x49202020' ecx='0x6c65746e' edx='0x20295228'/> + <cpuid eax_in='0x80000003' ecx_in='0x00' eax='0x6e6f6558' ebx='0x20295228' ecx='0x20555043' edx='0x202d3745'/> + <cpuid eax_in='0x80000004' ecx_in='0x00' eax='0x30333834' ebx='0x20402020' ecx='0x33312e32' edx='0x007a4847'/> + <cpuid eax_in='0x80000005' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/> + <cpuid eax_in='0x80000006' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x01006040' edx='0x00000000'/> + <cpuid eax_in='0x80000007' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000100'/> + <cpuid eax_in='0x80000008' ecx_in='0x00' eax='0x0000302c' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/> + <cpuid eax_in='0x80860000' ecx_in='0x00' eax='0x00000001' ebx='0x00000002' ecx='0x00000100' edx='0x00000080'/> + <cpuid eax_in='0xc0000000' ecx_in='0x00' eax='0x00000001' ebx='0x00000002' ecx='0x00000100' edx='0x00000080'/> +</cpudata> -- 2.14.2

On 10/04/2017 10:58 AM, Jiri Denemark wrote:
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- tests/cputest.c | 1 + .../x86_64-cpuid-Xeon-E7-4830-disabled.xml | 5 + .../x86_64-cpuid-Xeon-E7-4830-enabled.xml | 8 + .../x86_64-cpuid-Xeon-E7-4830-guest.xml | 28 +++ .../cputestdata/x86_64-cpuid-Xeon-E7-4830-host.xml | 29 +++ .../cputestdata/x86_64-cpuid-Xeon-E7-4830-json.xml | 13 ++ tests/cputestdata/x86_64-cpuid-Xeon-E7-4830.json | 235 +++++++++++++++++++++ tests/cputestdata/x86_64-cpuid-Xeon-E7-4830.xml | 30 +++ 8 files changed, 349 insertions(+) create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-E7-4830-disabled.xml create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-E7-4830-enabled.xml create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-E7-4830-guest.xml create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-E7-4830-host.xml create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-E7-4830-json.xml create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-E7-4830.json create mode 100644 tests/cputestdata/x86_64-cpuid-Xeon-E7-4830.xml
Wouldn't begin to know if they're valid or not, but tests pass, so... Reviewed-by: John Ferlan <jferlan@redhat.com> John

This CPU was incorrectly detected as SandyBridge before because the number of additional <feature> elements was the same for both SandyBridge and Westmere CPU models, but SandyBridge is newer (the CPU signature does not help here because it doesn't match any signature defined in cpu_map.xml). But since QEMU's version of SandyBridge CPU model contains xsaveopt which needs to be disabled, Westmere becomes the best CPU model when translating CPUID data to virCPUDef. Unfortunately, this doesn't help with translating the data we got from QEMU and the CPU model is still computed as SandyBridge in this case. Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- tests/cputest.c | 2 +- .../x86_64-cpuid-Xeon-E7-4830-guest.xml | 8 +- .../cputestdata/x86_64-cpuid-Xeon-E7-4830-json.xml | 1 + tests/cputestdata/x86_64-cpuid-Xeon-E7-4830.json | 422 +++++++++++++++++++++ 4 files changed, 428 insertions(+), 5 deletions(-) diff --git a/tests/cputest.c b/tests/cputest.c index f71b4982dd..f1aa227aac 100644 --- a/tests/cputest.c +++ b/tests/cputest.c @@ -1148,7 +1148,7 @@ mymain(void) DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-E5-2630", JSON_HOST); DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-E5-2650", JSON_HOST); DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-E7-4820", JSON_HOST); - DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-E7-4830", JSON_HOST); + DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-E7-4830", JSON_MODELS); DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-E7-8890", JSON_NONE); DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-Gold-6148", JSON_HOST); DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-W3520", JSON_HOST); diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E7-4830-guest.xml b/tests/cputestdata/x86_64-cpuid-Xeon-E7-4830-guest.xml index dbf8580a0e..659779687a 100644 --- a/tests/cputestdata/x86_64-cpuid-Xeon-E7-4830-guest.xml +++ b/tests/cputestdata/x86_64-cpuid-Xeon-E7-4830-guest.xml @@ -1,5 +1,5 @@ <cpu mode='custom' match='exact'> - <model fallback='forbid'>SandyBridge</model> + <model fallback='forbid'>Westmere</model> <vendor>Intel</vendor> <feature policy='require' name='vme'/> <feature policy='require' name='ds'/> @@ -8,6 +8,7 @@ <feature policy='require' name='ht'/> <feature policy='require' name='tm'/> <feature policy='require' name='pbe'/> + <feature policy='require' name='pclmuldq'/> <feature policy='require' name='dtes64'/> <feature policy='require' name='monitor'/> <feature policy='require' name='ds_cpl'/> @@ -19,10 +20,9 @@ <feature policy='require' name='pdcm'/> <feature policy='require' name='pcid'/> <feature policy='require' name='dca'/> + <feature policy='require' name='x2apic'/> <feature policy='require' name='arat'/> <feature policy='require' name='pdpe1gb'/> + <feature policy='require' name='rdtscp'/> <feature policy='require' name='invtsc'/> - <feature policy='disable' name='tsc-deadline'/> - <feature policy='disable' name='xsave'/> - <feature policy='disable' name='avx'/> </cpu> diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E7-4830-json.xml b/tests/cputestdata/x86_64-cpuid-Xeon-E7-4830-json.xml index c3f04d00d1..aae32bd7e2 100644 --- a/tests/cputestdata/x86_64-cpuid-Xeon-E7-4830-json.xml +++ b/tests/cputestdata/x86_64-cpuid-Xeon-E7-4830-json.xml @@ -10,4 +10,5 @@ <feature policy='require' name='pdpe1gb'/> <feature policy='disable' name='xsave'/> <feature policy='disable' name='avx'/> + <feature policy='disable' name='xsaveopt'/> </cpu> diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E7-4830.json b/tests/cputestdata/x86_64-cpuid-Xeon-E7-4830.json index 012e1d0c5c..732f65d1d9 100644 --- a/tests/cputestdata/x86_64-cpuid-Xeon-E7-4830.json +++ b/tests/cputestdata/x86_64-cpuid-Xeon-E7-4830.json @@ -233,3 +233,425 @@ }, "id": "model-expansion" } + +{ + "return": [ + { + "typename": "max-x86_64-cpu", + "unavailable-features": [], + "migration-safe": false, + "static": false, + "name": "max" + }, + { + "typename": "host-x86_64-cpu", + "unavailable-features": [], + "migration-safe": false, + "static": false, + "name": "host" + }, + { + "typename": "base-x86_64-cpu", + "unavailable-features": [], + "migration-safe": true, + "static": true, + "name": "base" + }, + { + "typename": "qemu64-x86_64-cpu", + "unavailable-features": [], + "migration-safe": true, + "static": false, + "name": "qemu64" + }, + { + "typename": "qemu32-x86_64-cpu", + "unavailable-features": [], + "migration-safe": true, + "static": false, + "name": "qemu32" + }, + { + "typename": "phenom-x86_64-cpu", + "unavailable-features": [ + "mmxext", + "fxsr-opt", + "3dnowext", + "3dnow", + "abm", + "sse4a", + "npt" + ], + "migration-safe": true, + "static": false, + "name": "phenom" + }, + { + "typename": "pentium3-x86_64-cpu", + "unavailable-features": [], + "migration-safe": true, + "static": false, + "name": "pentium3" + }, + { + "typename": "pentium2-x86_64-cpu", + "unavailable-features": [], + "migration-safe": true, + "static": false, + "name": "pentium2" + }, + { + "typename": "pentium-x86_64-cpu", + "unavailable-features": [], + "migration-safe": true, + "static": false, + "name": "pentium" + }, + { + "typename": "n270-x86_64-cpu", + "unavailable-features": [ + "movbe" + ], + "migration-safe": true, + "static": false, + "name": "n270" + }, + { + "typename": "kvm64-x86_64-cpu", + "unavailable-features": [], + "migration-safe": true, + "static": false, + "name": "kvm64" + }, + { + "typename": "kvm32-x86_64-cpu", + "unavailable-features": [], + "migration-safe": true, + "static": false, + "name": "kvm32" + }, + { + "typename": "cpu64-rhel6-x86_64-cpu", + "unavailable-features": [ + "abm", + "sse4a" + ], + "migration-safe": true, + "static": false, + "name": "cpu64-rhel6" + }, + { + "typename": "coreduo-x86_64-cpu", + "unavailable-features": [], + "migration-safe": true, + "static": false, + "name": "coreduo" + }, + { + "typename": "core2duo-x86_64-cpu", + "unavailable-features": [], + "migration-safe": true, + "static": false, + "name": "core2duo" + }, + { + "typename": "athlon-x86_64-cpu", + "unavailable-features": [ + "mmxext", + "3dnowext", + "3dnow" + ], + "migration-safe": true, + "static": false, + "name": "athlon" + }, + { + "typename": "Westmere-x86_64-cpu", + "unavailable-features": [], + "migration-safe": true, + "static": false, + "name": "Westmere" + }, + { + "typename": "Skylake-Client-x86_64-cpu", + "unavailable-features": [ + "fma", + "movbe", + "xsave", + "avx", + "f16c", + "rdrand", + "fsgsbase", + "bmi1", + "hle", + "avx2", + "smep", + "bmi2", + "erms", + "invpcid", + "rtm", + "mpx", + "rdseed", + "adx", + "smap", + "abm", + "3dnowprefetch", + "xsaveopt", + "xsavec", + "xgetbv1", + "xsave", + "xsave", + "avx", + "mpx", + "mpx" + ], + "migration-safe": true, + "static": false, + "name": "Skylake-Client" + }, + { + "typename": "SandyBridge-x86_64-cpu", + "unavailable-features": [ + "xsave", + "avx", + "xsaveopt", + "xsave", + "xsave", + "avx" + ], + "migration-safe": true, + "static": false, + "name": "SandyBridge" + }, + { + "typename": "Penryn-x86_64-cpu", + "unavailable-features": [], + "migration-safe": true, + "static": false, + "name": "Penryn" + }, + { + "typename": "Opteron_G5-x86_64-cpu", + "unavailable-features": [ + "fma", + "xsave", + "avx", + "f16c", + "abm", + "sse4a", + "misalignsse", + "3dnowprefetch", + "xop", + "fma4", + "tbm", + "xsave", + "xsave", + "avx" + ], + "migration-safe": true, + "static": false, + "name": "Opteron_G5" + }, + { + "typename": "Opteron_G4-x86_64-cpu", + "unavailable-features": [ + "xsave", + "avx", + "abm", + "sse4a", + "misalignsse", + "3dnowprefetch", + "xop", + "fma4", + "xsave", + "xsave", + "avx" + ], + "migration-safe": true, + "static": false, + "name": "Opteron_G4" + }, + { + "typename": "Opteron_G3-x86_64-cpu", + "unavailable-features": [ + "abm", + "sse4a", + "misalignsse" + ], + "migration-safe": true, + "static": false, + "name": "Opteron_G3" + }, + { + "typename": "Opteron_G2-x86_64-cpu", + "unavailable-features": [], + "migration-safe": true, + "static": false, + "name": "Opteron_G2" + }, + { + "typename": "Opteron_G1-x86_64-cpu", + "unavailable-features": [], + "migration-safe": true, + "static": false, + "name": "Opteron_G1" + }, + { + "typename": "Nehalem-x86_64-cpu", + "unavailable-features": [], + "migration-safe": true, + "static": false, + "name": "Nehalem" + }, + { + "typename": "IvyBridge-x86_64-cpu", + "unavailable-features": [ + "xsave", + "avx", + "f16c", + "rdrand", + "fsgsbase", + "smep", + "erms", + "xsaveopt", + "xsave", + "xsave", + "avx" + ], + "migration-safe": true, + "static": false, + "name": "IvyBridge" + }, + { + "typename": "Haswell-x86_64-cpu", + "unavailable-features": [ + "fma", + "movbe", + "xsave", + "avx", + "f16c", + "rdrand", + "fsgsbase", + "bmi1", + "hle", + "avx2", + "smep", + "bmi2", + "erms", + "invpcid", + "rtm", + "abm", + "xsaveopt", + "xsave", + "xsave", + "avx" + ], + "migration-safe": true, + "static": false, + "name": "Haswell" + }, + { + "typename": "Haswell-noTSX-x86_64-cpu", + "unavailable-features": [ + "fma", + "movbe", + "xsave", + "avx", + "f16c", + "rdrand", + "fsgsbase", + "bmi1", + "avx2", + "smep", + "bmi2", + "erms", + "invpcid", + "abm", + "xsaveopt", + "xsave", + "xsave", + "avx" + ], + "migration-safe": true, + "static": false, + "name": "Haswell-noTSX" + }, + { + "typename": "Conroe-x86_64-cpu", + "unavailable-features": [], + "migration-safe": true, + "static": false, + "name": "Conroe" + }, + { + "typename": "Broadwell-x86_64-cpu", + "unavailable-features": [ + "fma", + "movbe", + "xsave", + "avx", + "f16c", + "rdrand", + "fsgsbase", + "bmi1", + "hle", + "avx2", + "smep", + "bmi2", + "erms", + "invpcid", + "rtm", + "rdseed", + "adx", + "smap", + "abm", + "3dnowprefetch", + "xsaveopt", + "xsave", + "xsave", + "avx" + ], + "migration-safe": true, + "static": false, + "name": "Broadwell" + }, + { + "typename": "Broadwell-noTSX-x86_64-cpu", + "unavailable-features": [ + "fma", + "movbe", + "xsave", + "avx", + "f16c", + "rdrand", + "fsgsbase", + "bmi1", + "avx2", + "smep", + "bmi2", + "erms", + "invpcid", + "rdseed", + "adx", + "smap", + "abm", + "3dnowprefetch", + "xsaveopt", + "xsave", + "xsave", + "avx" + ], + "migration-safe": true, + "static": false, + "name": "Broadwell-noTSX" + }, + { + "typename": "486-x86_64-cpu", + "unavailable-features": [], + "migration-safe": true, + "static": false, + "name": "486" + } + ], + "id": "definitions" +} -- 2.14.2

On 10/04/2017 10:58 AM, Jiri Denemark wrote:
This CPU was incorrectly detected as SandyBridge before because the number of additional <feature> elements was the same for both SandyBridge and Westmere CPU models, but SandyBridge is newer (the CPU signature does not help here because it doesn't match any signature defined in cpu_map.xml). But since QEMU's version of SandyBridge CPU model contains xsaveopt which needs to be disabled, Westmere becomes the best CPU model when translating CPUID data to virCPUDef. Unfortunately, this doesn't help with translating the data we got from QEMU and the CPU model is still computed as SandyBridge in this case.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- tests/cputest.c | 2 +- .../x86_64-cpuid-Xeon-E7-4830-guest.xml | 8 +- .../cputestdata/x86_64-cpuid-Xeon-E7-4830-json.xml | 1 + tests/cputestdata/x86_64-cpuid-Xeon-E7-4830.json | 422 +++++++++++++++++++++ 4 files changed, 428 insertions(+), 5 deletions(-)
Similar "mpx" duplication, but otherwise seemingly fine. Reviewed-by: John Ferlan <jferlan@redhat.com> John

xsaves is supported by current QEMU/KVM on this CPU. Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- .../x86_64-cpuid-Xeon-E3-1245-disabled.xml | 1 - .../x86_64-cpuid-Xeon-E3-1245-enabled.xml | 2 +- .../cputestdata/x86_64-cpuid-Xeon-E3-1245-json.xml | 1 + tests/cputestdata/x86_64-cpuid-Xeon-E3-1245.json | 413 +++++++++++---------- tests/cputestdata/x86_64-cpuid-Xeon-E3-1245.xml | 7 +- 5 files changed, 232 insertions(+), 192 deletions(-) diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E3-1245-disabled.xml b/tests/cputestdata/x86_64-cpuid-Xeon-E3-1245-disabled.xml index 1a177705a8..4a0477f788 100644 --- a/tests/cputestdata/x86_64-cpuid-Xeon-E3-1245-disabled.xml +++ b/tests/cputestdata/x86_64-cpuid-Xeon-E3-1245-disabled.xml @@ -1,6 +1,5 @@ <!-- Features disabled by QEMU --> <cpudata arch='x86'> <cpuid eax_in='0x00000001' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x0800c1dc' edx='0xb0600000'/> - <cpuid eax_in='0x0000000d' ecx_in='0x01' eax='0x00000008' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/> <cpuid eax_in='0x80000007' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000100'/> </cpudata> diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E3-1245-enabled.xml b/tests/cputestdata/x86_64-cpuid-Xeon-E3-1245-enabled.xml index 2584042339..f31f7317b6 100644 --- a/tests/cputestdata/x86_64-cpuid-Xeon-E3-1245-enabled.xml +++ b/tests/cputestdata/x86_64-cpuid-Xeon-E3-1245-enabled.xml @@ -3,7 +3,7 @@ <cpuid eax_in='0x00000001' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0xf7fa3223' edx='0x0f8bfbff'/> <cpuid eax_in='0x00000006' ecx_in='0x00' eax='0x00000004' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/> <cpuid eax_in='0x00000007' ecx_in='0x00' eax='0x00000000' ebx='0x009c4fbb' ecx='0x00000000' edx='0x00000000'/> - <cpuid eax_in='0x0000000d' ecx_in='0x01' eax='0x00000007' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/> + <cpuid eax_in='0x0000000d' ecx_in='0x01' eax='0x0000000f' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/> <cpuid eax_in='0x40000001' ecx_in='0x00' eax='0x010000fa' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/> <cpuid eax_in='0x80000001' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000121' edx='0x2c100800'/> </cpudata> diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E3-1245-json.xml b/tests/cputestdata/x86_64-cpuid-Xeon-E3-1245-json.xml index 7af75509e6..ad98679027 100644 --- a/tests/cputestdata/x86_64-cpuid-Xeon-E3-1245-json.xml +++ b/tests/cputestdata/x86_64-cpuid-Xeon-E3-1245-json.xml @@ -6,5 +6,6 @@ <feature policy='require' name='hypervisor'/> <feature policy='require' name='tsc_adjust'/> <feature policy='require' name='clflushopt'/> + <feature policy='require' name='xsaves'/> <feature policy='require' name='pdpe1gb'/> </cpu> diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E3-1245.json b/tests/cputestdata/x86_64-cpuid-Xeon-E3-1245.json index 4828da5884..bb5d7d8830 100644 --- a/tests/cputestdata/x86_64-cpuid-Xeon-E3-1245.json +++ b/tests/cputestdata/x86_64-cpuid-Xeon-E3-1245.json @@ -3,199 +3,238 @@ "model": { "name": "base", "props": { - "pfthreshold": false, - "pku": false, - "rtm": true, - "tsc_adjust": true, - "tsc-deadline": true, - "xstore-en": false, - "tsc-scale": false, - "sse": true, - "smap": true, - "stepping": 3, - "tce": false, - "kvm_steal_time": true, - "smep": true, - "rdpid": false, - "xcrypt": false, - "sse4_2": true, - "monitor": false, - "sse4_1": true, - "kvm-mmu": false, - "flushbyasid": false, - "kvm-steal-time": true, - "lm": true, - "tsc": true, - "adx": true, - "fxsr": true, - "sha-ni": false, - "tm": false, - "pclmuldq": true, - "xgetbv1": true, - "xstore": false, - "vmcb_clean": false, - "vme": true, - "vendor": "GenuineIntel", - "arat": true, - "ffxsr": false, - "de": true, - "avx512f": false, - "pse": true, - "ds-cpl": false, - "tbm": false, - "ia64": false, - "phe-en": false, - "f16c": true, - "ds": false, - "mpx": true, - "tsc-adjust": true, - "aes": true, - "avx2": true, - "pbe": false, - "cx16": true, - "ds_cpl": false, - "movbe": true, - "perfctr-nb": false, - "nrip_save": false, - "kvm_mmu": false, - "ospke": false, - "avx512ifma": false, - "vmx": true, - "sep": true, - "xsaveopt": true, - "sse4a": false, - "avx512dq": false, - "i64": true, - "avx512-4vnniw": false, - "xsave": true, - "erms": true, - "hle": true, - "nodeid_msr": false, - "est": false, - "svm_lock": false, - "xop": false, - "model-id": "Intel(R) Xeon(R) CPU E3-1245 v5 @ 3.50GHz", - "abm": true, - "avx512er": false, - "sse4.1": true, - "sse4.2": true, - "pause-filter": false, - "lahf-lm": true, - "kvm-nopiodelay": true, - "cmp_legacy": false, - "acpi": false, - "fma4": false, - "popcnt": true, - "mmx": true, - "osxsave": false, - "pcommit": false, - "avx512pf": false, - "clwb": false, - "dca": false, - "pdcm": false, - "xcrypt-en": false, - "3dnow": false, - "invtsc": false, - "tm2": false, - "hypervisor": true, - "kvmclock-stable-bit": true, - "fxsr-opt": false, - "pcid": true, - "sse4-1": true, - "sse4-2": true, - "avx512-vpopcntdq": false, - "avx512-4fmaps": false, - "pause_filter": false, - "svm-lock": false, - "rdrand": true, - "nrip-save": false, - "avx512vl": false, - "x2apic": true, - "kvmclock": true, - "pge": true, - "family": 6, - "dtes64": false, - "xd": true, - "kvm_pv_eoi": true, - "ace2": false, - "kvm_pv_unhalt": true, - "xtpr": false, - "perfctr_nb": false, - "avx512bw": false, - "nx": true, - "lwp": false, - "msr": true, - "ace2-en": false, - "decodeassists": false, - "perfctr-core": false, - "pn": false, - "fma": true, - "nodeid-msr": false, - "kvm_asyncpf": true, - "clflush": true, - "cx8": true, - "mce": true, - "avx512cd": false, - "cr8legacy": false, - "mca": true, - "pni": true, - "rdseed": true, - "apic": true, - "fsgsbase": true, - "cmp-legacy": false, - "kvm-pv-unhalt": true, - "rdtscp": true, - "mmxext": false, - "cid": false, - "ssse3": true, - "extapic": false, - "pse36": true, - "mtrr": true, - "ibs": false, - "la57": false, - "avx": true, - "syscall": true, - "umip": false, - "invpcid": true, - "avx512vbmi": false, - "kvm-asyncpf": true, - "vmcb-clean": false, - "pmm": false, + "phys-bits": 0, + "core-id": -1, + "xlevel": 2147483656, "cmov": true, - "perfctr_core": false, - "misalignsse": false, - "clflushopt": true, - "pat": true, - "lbrv": false, - "3dnowprefetch": true, - "fpu": true, - "pae": true, - "wdt": false, - "tsc_scale": false, - "skinit": false, - "fxsr_opt": false, - "kvm_nopiodelay": true, - "pmm-en": false, - "phe": false, - "3dnowext": false, - "osvw": false, - "ht": false, - "pdpe1gb": true, - "kvm-pv-eoi": true, - "npt": false, + "ia64": false, + "aes": true, + "mmx": true, + "arat": true, + "rdpid": false, + "pause-filter": false, "xsavec": true, - "lahf_lm": true, - "pclmulqdq": true, + "osxsave": false, + "tsc-frequency": 0, + "xd": true, + "hv-vendor-id": "", + "kvm-asyncpf": true, + "kvm_asyncpf": true, + "perfctr_core": false, + "perfctr-core": false, + "mpx": true, + "avx512cd": false, + "decodeassists": false, + "pbe": false, + "sse4_1": true, + "sse4.1": true, + "sse4-1": true, + "family": 6, + "vmware-cpuid-freq": true, + "avx512f": false, + "xcrypt": false, + "hv-runtime": false, + "msr": true, + "mce": true, + "mca": true, + "thread-id": -1, + "min-level": 13, + "xgetbv1": true, + "cid": false, + "hv-relaxed": false, + "fxsr": true, + "ds": false, + "hv-crash": false, + "xsaveopt": true, + "xtpr": false, + "avx512-vpopcntdq": false, + "phe": false, + "avx512vl": false, + "extapic": false, + "3dnowprefetch": true, + "cr8legacy": false, + "cpuid-0xb": true, + "xcrypt-en": false, + "kvm_pv_eoi": true, + "apic-id": 4294967295, + "pn": false, + "dca": false, + "vendor": "GenuineIntel", + "pku": false, + "smx": false, + "cmp-legacy": false, + "cmp_legacy": false, + "node-id": -1, + "avx512-4fmaps": false, + "vmcb-clean": false, + "vmcb_clean": false, + "3dnowext": false, + "hle": true, + "npt": false, + "memory": "/machine/unattached/system[0]", + "clwb": false, + "lbrv": false, + "adx": true, + "ss": true, + "pni": true, + "svm_lock": false, + "svm-lock": false, + "smep": true, + "pfthreshold": false, + "smap": true, + "x2apic": true, + "avx512vbmi": false, + "hv-stimer": false, + "i64": true, + "flushbyasid": false, + "f16c": true, + "ace2-en": false, + "pat": true, + "pae": true, + "sse": true, + "phe-en": false, + "kvm-nopiodelay": true, + "kvm_nopiodelay": true, + "tm": false, + "kvmclock-stable-bit": true, + "hypervisor": true, + "socket-id": -1, + "pcommit": false, + "syscall": true, + "level": 13, + "avx512dq": false, "svm": false, + "full-cpuid-auto-level": true, + "hv-reset": false, + "invtsc": false, "sse3": true, "sse2": true, - "ss": true, - "topoext": false, - "smx": false, - "bmi1": true, + "est": false, + "avx512ifma": false, + "tm2": false, + "kvm-pv-eoi": true, + "cx8": true, + "kvm-mmu": false, + "kvm_mmu": false, + "sse4_2": true, + "sse4.2": true, + "sse4-2": true, + "pge": true, + "fill-mtrr-mask": true, + "pdcm": false, + "nodeid_msr": false, + "model": 94, + "movbe": true, + "nrip-save": false, + "nrip_save": false, + "sse4a": false, + "ssse3": true, + "kvm_pv_unhalt": true, + "invpcid": true, + "pdpe1gb": true, + "tsc-deadline": true, + "fma": true, + "cx16": true, + "de": true, + "enforce": false, + "stepping": 3, + "xsave": true, + "clflush": true, + "skinit": false, + "tce": false, + "tsc": true, + "fpu": true, + "ds-cpl": false, + "ds_cpl": false, + "ibs": false, + "host-phys-bits": false, + "fma4": false, + "la57": false, + "osvw": false, + "check": true, + "hv-spinlocks": -1, + "pmm": false, + "apic": true, + "pmu": false, + "min-xlevel2": 0, + "tsc-adjust": true, + "tsc_adjust": true, + "kvm-steal-time": true, + "kvm_steal_time": true, + "kvmclock": true, + "l3-cache": true, + "lwp": false, + "xop": false, + "avx": true, + "ospke": false, + "ace2": false, + "acpi": false, + "avx512bw": false, + "hv-vapic": false, + "fsgsbase": true, + "ht": false, + "nx": true, + "pclmulqdq": true, + "mmxext": false, + "popcnt": true, + "xsaves": true, + "tcg-cpuid": true, + "lm": true, + "umip": false, + "avx2": true, + "pse": true, + "sep": true, + "pclmuldq": true, + "nodeid-msr": false, + "kvm": true, + "misalignsse": false, + "min-xlevel": 2147483656, "bmi2": true, - "xsaves": false, - "model": 94 + "bmi1": true, + "kvm-pv-unhalt": true, + "realized": false, + "tsc_scale": false, + "tsc-scale": false, + "topoext": false, + "hv-vpindex": false, + "xlevel2": 0, + "clflushopt": true, + "kvm-no-smi-migration": false, + "monitor": false, + "avx512er": false, + "pmm-en": false, + "pcid": true, + "3dnow": false, + "erms": true, + "lahf-lm": true, + "lahf_lm": true, + "xstore": false, + "hv-synic": false, + "fxsr-opt": false, + "fxsr_opt": false, + "rtm": true, + "lmce": true, + "hv-time": false, + "perfctr-nb": false, + "perfctr_nb": false, + "ffxsr": false, + "rdrand": true, + "rdseed": true, + "avx512-4vnniw": false, + "vme": true, + "vmx": true, + "dtes64": false, + "mtrr": true, + "rdtscp": true, + "pse36": true, + "tbm": false, + "wdt": false, + "pause_filter": false, + "model-id": "Intel(R) Xeon(R) CPU E3-1245 v5 @ 3.50GHz", + "sha-ni": false, + "abm": true, + "avx512pf": false, + "xstore-en": false } } }, diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E3-1245.xml b/tests/cputestdata/x86_64-cpuid-Xeon-E3-1245.xml index 42992db7d9..f130a70f37 100644 --- a/tests/cputestdata/x86_64-cpuid-Xeon-E3-1245.xml +++ b/tests/cputestdata/x86_64-cpuid-Xeon-E3-1245.xml @@ -1,7 +1,7 @@ <!-- Intel(R) Xeon(R) CPU E3-1245 v5 @ 3.50GHz --> <cpudata arch='x86'> <cpuid eax_in='0x00000000' ecx_in='0x00' eax='0x00000016' ebx='0x756e6547' ecx='0x6c65746e' edx='0x49656e69'/> - <cpuid eax_in='0x00000001' ecx_in='0x00' eax='0x000506e3' ebx='0x00100800' ecx='0x7ffafbff' edx='0xbfebfbff'/> + <cpuid eax_in='0x00000001' ecx_in='0x00' eax='0x000506e3' ebx='0x06100800' ecx='0x7ffafbff' edx='0xbfebfbff'/> <cpuid eax_in='0x00000002' ecx_in='0x00' eax='0x76036301' ebx='0x00f0b5ff' ecx='0x00000000' edx='0x00c30000'/> <cpuid eax_in='0x00000003' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/> <cpuid eax_in='0x00000004' ecx_in='0x00' eax='0x1c004121' ebx='0x01c0003f' ecx='0x0000003f' edx='0x00000000'/> @@ -14,14 +14,15 @@ <cpuid eax_in='0x00000008' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/> <cpuid eax_in='0x00000009' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/> <cpuid eax_in='0x0000000a' ecx_in='0x00' eax='0x07300404' ebx='0x00000000' ecx='0x00000000' edx='0x00000603'/> - <cpuid eax_in='0x0000000b' ecx_in='0x00' eax='0x00000001' ebx='0x00000002' ecx='0x00000100' edx='0x00000000'/> - <cpuid eax_in='0x0000000b' ecx_in='0x01' eax='0x00000004' ebx='0x00000008' ecx='0x00000201' edx='0x00000000'/> + <cpuid eax_in='0x0000000b' ecx_in='0x00' eax='0x00000001' ebx='0x00000002' ecx='0x00000100' edx='0x00000006'/> + <cpuid eax_in='0x0000000b' ecx_in='0x01' eax='0x00000004' ebx='0x00000008' ecx='0x00000201' edx='0x00000006'/> <cpuid eax_in='0x0000000c' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/> <cpuid eax_in='0x0000000d' ecx_in='0x00' eax='0x0000001f' ebx='0x00000440' ecx='0x00000440' edx='0x00000000'/> <cpuid eax_in='0x0000000d' ecx_in='0x01' eax='0x0000000f' ebx='0x000003c0' ecx='0x00000100' edx='0x00000000'/> <cpuid eax_in='0x0000000d' ecx_in='0x02' eax='0x00000100' ebx='0x00000240' ecx='0x00000000' edx='0x00000000'/> <cpuid eax_in='0x0000000d' ecx_in='0x03' eax='0x00000040' ebx='0x000003c0' ecx='0x00000000' edx='0x00000000'/> <cpuid eax_in='0x0000000d' ecx_in='0x04' eax='0x00000040' ebx='0x00000400' ecx='0x00000000' edx='0x00000000'/> + <cpuid eax_in='0x0000000d' ecx_in='0x08' eax='0x00000080' ebx='0x00000000' ecx='0x00000001' edx='0x00000000'/> <cpuid eax_in='0x0000000e' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/> <cpuid eax_in='0x0000000f' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/> <cpuid eax_in='0x00000010' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/> -- 2.14.2

On 10/04/2017 10:58 AM, Jiri Denemark wrote:
xsaves is supported by current QEMU/KVM on this CPU.
Current as of when? Does this cause migration issues to have one version support and another not? What about save/restore type operations? I'm not against this, just curious. Not sure I ever want to know/compare all the bits and names, numbers, and code names. A rather daunting task.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- .../x86_64-cpuid-Xeon-E3-1245-disabled.xml | 1 - .../x86_64-cpuid-Xeon-E3-1245-enabled.xml | 2 +- .../cputestdata/x86_64-cpuid-Xeon-E3-1245-json.xml | 1 + tests/cputestdata/x86_64-cpuid-Xeon-E3-1245.json | 413 +++++++++++---------- tests/cputestdata/x86_64-cpuid-Xeon-E3-1245.xml | 7 +- 5 files changed, 232 insertions(+), 192 deletions(-)
Reviewed-by: John Ferlan <jferlan@redhat.com> John

On Thu, Oct 12, 2017 at 18:22:54 -0400, John Ferlan wrote:
On 10/04/2017 10:58 AM, Jiri Denemark wrote:
xsaves is supported by current QEMU/KVM on this CPU.
Current as of when?
Good question. The QEMU version (unknown) used to generate the original test data did not enable xsaves on the host while the version (also unknown) used to regenerate them enabled this feature. It's also possible the host is actually not exactly the same even though it has the same CPU model. I'm not sure if any configuration can influence availability of xsaves for guests. Perhaps I could have used different words in the commit message...
Does this cause migration issues to have one version support and another not? What about save/restore type operations?
It should cause any trouble. This is the point of all the code and these tests after all. When starting a domain we record what features were or were not really enabled in the virtual CPU and record this in domain XML so that we can ask for exactly the same CPU configuration during migration, restore, or snapshot revert. Jirka

Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- tests/cputest.c | 2 +- tests/cputestdata/x86_64-cpuid-Xeon-E3-1245.json | 299 +++++++++++++++++++++++ 2 files changed, 300 insertions(+), 1 deletion(-) diff --git a/tests/cputest.c b/tests/cputest.c index f1aa227aac..cfd63bfcf7 100644 --- a/tests/cputest.c +++ b/tests/cputest.c @@ -1144,7 +1144,7 @@ mymain(void) DO_TEST_CPUID(VIR_ARCH_X86_64, "Phenom-B95", JSON_HOST); DO_TEST_CPUID(VIR_ARCH_X86_64, "Ryzen-7-1800X-Eight-Core", JSON_HOST); DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-5110", JSON_NONE); - DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-E3-1245", JSON_HOST); + DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-E3-1245", JSON_MODELS); DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-E5-2630", JSON_HOST); DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-E5-2650", JSON_HOST); DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-E7-4820", JSON_HOST); diff --git a/tests/cputestdata/x86_64-cpuid-Xeon-E3-1245.json b/tests/cputestdata/x86_64-cpuid-Xeon-E3-1245.json index bb5d7d8830..33d8221853 100644 --- a/tests/cputestdata/x86_64-cpuid-Xeon-E3-1245.json +++ b/tests/cputestdata/x86_64-cpuid-Xeon-E3-1245.json @@ -240,3 +240,302 @@ }, "id": "model-expansion" } + +{ + "return": [ + { + "name": "max", + "typename": "max-x86_64-cpu", + "unavailable-features": [ + ], + "static": false, + "migration-safe": false + }, + { + "name": "host", + "typename": "host-x86_64-cpu", + "unavailable-features": [ + ], + "static": false, + "migration-safe": false + }, + { + "name": "base", + "typename": "base-x86_64-cpu", + "unavailable-features": [ + ], + "static": true, + "migration-safe": true + }, + { + "name": "qemu64", + "typename": "qemu64-x86_64-cpu", + "unavailable-features": [ + ], + "static": false, + "migration-safe": true + }, + { + "name": "qemu32", + "typename": "qemu32-x86_64-cpu", + "unavailable-features": [ + ], + "static": false, + "migration-safe": true + }, + { + "name": "phenom", + "typename": "phenom-x86_64-cpu", + "unavailable-features": [ + "mmxext", + "fxsr-opt", + "3dnowext", + "3dnow", + "sse4a", + "npt" + ], + "static": false, + "migration-safe": true + }, + { + "name": "pentium3", + "typename": "pentium3-x86_64-cpu", + "unavailable-features": [ + ], + "static": false, + "migration-safe": true + }, + { + "name": "pentium2", + "typename": "pentium2-x86_64-cpu", + "unavailable-features": [ + ], + "static": false, + "migration-safe": true + }, + { + "name": "pentium", + "typename": "pentium-x86_64-cpu", + "unavailable-features": [ + ], + "static": false, + "migration-safe": true + }, + { + "name": "n270", + "typename": "n270-x86_64-cpu", + "unavailable-features": [ + ], + "static": false, + "migration-safe": true + }, + { + "name": "kvm64", + "typename": "kvm64-x86_64-cpu", + "unavailable-features": [ + ], + "static": false, + "migration-safe": true + }, + { + "name": "kvm32", + "typename": "kvm32-x86_64-cpu", + "unavailable-features": [ + ], + "static": false, + "migration-safe": true + }, + { + "name": "coreduo", + "typename": "coreduo-x86_64-cpu", + "unavailable-features": [ + ], + "static": false, + "migration-safe": true + }, + { + "name": "core2duo", + "typename": "core2duo-x86_64-cpu", + "unavailable-features": [ + ], + "static": false, + "migration-safe": true + }, + { + "name": "athlon", + "typename": "athlon-x86_64-cpu", + "unavailable-features": [ + "mmxext", + "3dnowext", + "3dnow" + ], + "static": false, + "migration-safe": true + }, + { + "name": "Westmere", + "typename": "Westmere-x86_64-cpu", + "unavailable-features": [ + ], + "static": false, + "migration-safe": true + }, + { + "name": "Skylake-Server", + "typename": "Skylake-Server-x86_64-cpu", + "unavailable-features": [ + "avx512f", + "avx512dq", + "clwb", + "avx512cd", + "avx512bw", + "avx512vl", + "avx512f", + "avx512f", + "avx512f" + ], + "static": false, + "migration-safe": true + }, + { + "name": "Skylake-Client", + "typename": "Skylake-Client-x86_64-cpu", + "unavailable-features": [ + ], + "static": false, + "migration-safe": true + }, + { + "name": "SandyBridge", + "typename": "SandyBridge-x86_64-cpu", + "unavailable-features": [ + ], + "static": false, + "migration-safe": true + }, + { + "name": "Penryn", + "typename": "Penryn-x86_64-cpu", + "unavailable-features": [ + ], + "static": false, + "migration-safe": true + }, + { + "name": "Opteron_G5", + "typename": "Opteron_G5-x86_64-cpu", + "unavailable-features": [ + "sse4a", + "misalignsse", + "xop", + "fma4", + "tbm" + ], + "static": false, + "migration-safe": true + }, + { + "name": "Opteron_G4", + "typename": "Opteron_G4-x86_64-cpu", + "unavailable-features": [ + "sse4a", + "misalignsse", + "xop", + "fma4" + ], + "static": false, + "migration-safe": true + }, + { + "name": "Opteron_G3", + "typename": "Opteron_G3-x86_64-cpu", + "unavailable-features": [ + "sse4a", + "misalignsse" + ], + "static": false, + "migration-safe": true + }, + { + "name": "Opteron_G2", + "typename": "Opteron_G2-x86_64-cpu", + "unavailable-features": [ + ], + "static": false, + "migration-safe": true + }, + { + "name": "Opteron_G1", + "typename": "Opteron_G1-x86_64-cpu", + "unavailable-features": [ + ], + "static": false, + "migration-safe": true + }, + { + "name": "Nehalem", + "typename": "Nehalem-x86_64-cpu", + "unavailable-features": [ + ], + "static": false, + "migration-safe": true + }, + { + "name": "IvyBridge", + "typename": "IvyBridge-x86_64-cpu", + "unavailable-features": [ + ], + "static": false, + "migration-safe": true + }, + { + "name": "Haswell", + "typename": "Haswell-x86_64-cpu", + "unavailable-features": [ + ], + "static": false, + "migration-safe": true + }, + { + "name": "Haswell-noTSX", + "typename": "Haswell-noTSX-x86_64-cpu", + "unavailable-features": [ + ], + "static": false, + "migration-safe": true + }, + { + "name": "Conroe", + "typename": "Conroe-x86_64-cpu", + "unavailable-features": [ + ], + "static": false, + "migration-safe": true + }, + { + "name": "Broadwell", + "typename": "Broadwell-x86_64-cpu", + "unavailable-features": [ + ], + "static": false, + "migration-safe": true + }, + { + "name": "Broadwell-noTSX", + "typename": "Broadwell-noTSX-x86_64-cpu", + "unavailable-features": [ + ], + "static": false, + "migration-safe": true + }, + { + "name": "486", + "typename": "486-x86_64-cpu", + "unavailable-features": [ + ], + "static": false, + "migration-safe": true + } + ], + "id": "definitions" +} -- 2.14.2

On 10/04/2017 10:58 AM, Jiri Denemark wrote:
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- tests/cputest.c | 2 +- tests/cputestdata/x86_64-cpuid-Xeon-E3-1245.json | 299 +++++++++++++++++++++++ 2 files changed, 300 insertions(+), 1 deletion(-)
There's another repeating sequence later on of "avx512f" w/ Skylake-Server this time.... I dunno. Looks reasonable to me... Reviewed-by: John Ferlan <jferlan@redhat.com> John

arat is now enabled even if the hardware does not support it. Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- .../x86_64-cpuid-Core-i7-2600-disabled.xml | 1 - .../x86_64-cpuid-Core-i7-2600-enabled.xml | 1 + .../cputestdata/x86_64-cpuid-Core-i7-2600-json.xml | 1 + tests/cputestdata/x86_64-cpuid-Core-i7-2600.json | 496 +++++++++++++++++++-- tests/cputestdata/x86_64-cpuid-Core-i7-2600.xml | 6 +- 5 files changed, 455 insertions(+), 50 deletions(-) diff --git a/tests/cputestdata/x86_64-cpuid-Core-i7-2600-disabled.xml b/tests/cputestdata/x86_64-cpuid-Core-i7-2600-disabled.xml index f25d2888eb..510cd97a5b 100644 --- a/tests/cputestdata/x86_64-cpuid-Core-i7-2600-disabled.xml +++ b/tests/cputestdata/x86_64-cpuid-Core-i7-2600-disabled.xml @@ -1,6 +1,5 @@ <!-- Features disabled by QEMU --> <cpudata arch='x86'> <cpuid eax_in='0x00000001' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x0800c1fc' edx='0xb0600000'/> - <cpuid eax_in='0x00000006' ecx_in='0x00' eax='0x00000004' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/> <cpuid eax_in='0x80000007' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000100'/> </cpudata> diff --git a/tests/cputestdata/x86_64-cpuid-Core-i7-2600-enabled.xml b/tests/cputestdata/x86_64-cpuid-Core-i7-2600-enabled.xml index df99a21807..1581f800f1 100644 --- a/tests/cputestdata/x86_64-cpuid-Core-i7-2600-enabled.xml +++ b/tests/cputestdata/x86_64-cpuid-Core-i7-2600-enabled.xml @@ -1,6 +1,7 @@ <!-- Features enabled by QEMU --> <cpudata arch='x86'> <cpuid eax_in='0x00000001' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x97ba2203' edx='0x0f8bfbff'/> + <cpuid eax_in='0x00000006' ecx_in='0x00' eax='0x00000004' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/> <cpuid eax_in='0x00000007' ecx_in='0x00' eax='0x00000000' ebx='0x00000002' ecx='0x00000000' edx='0x00000000'/> <cpuid eax_in='0x0000000d' ecx_in='0x01' eax='0x00000001' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/> <cpuid eax_in='0x40000001' ecx_in='0x00' eax='0x010000fa' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/> diff --git a/tests/cputestdata/x86_64-cpuid-Core-i7-2600-json.xml b/tests/cputestdata/x86_64-cpuid-Core-i7-2600-json.xml index 25c87e164e..c9ae651922 100644 --- a/tests/cputestdata/x86_64-cpuid-Core-i7-2600-json.xml +++ b/tests/cputestdata/x86_64-cpuid-Core-i7-2600-json.xml @@ -5,6 +5,7 @@ <feature policy='require' name='ss'/> <feature policy='require' name='pcid'/> <feature policy='require' name='hypervisor'/> + <feature policy='require' name='arat'/> <feature policy='require' name='tsc_adjust'/> <feature policy='require' name='xsaveopt'/> </cpu> diff --git a/tests/cputestdata/x86_64-cpuid-Core-i7-2600.json b/tests/cputestdata/x86_64-cpuid-Core-i7-2600.json index 19c448c10b..c80c89b0d7 100644 --- a/tests/cputestdata/x86_64-cpuid-Core-i7-2600.json +++ b/tests/cputestdata/x86_64-cpuid-Core-i7-2600.json @@ -9,19 +9,21 @@ "tsc_adjust": true, "tsc-deadline": true, "xstore-en": false, - "tsc-scale": false, - "sse": true, - "smap": false, - "stepping": 7, + "cpuid-0xb": true, + "abm": false, + "ia64": false, + "kvm-mmu": false, + "xsaveopt": true, + "hv-spinlocks": -1, "tce": false, + "realized": false, "kvm_steal_time": true, "smep": false, - "rdpid": false, + "fpu": true, "xcrypt": false, "sse4_2": true, - "monitor": false, + "clflush": true, "sse4_1": true, - "kvm-mmu": false, "flushbyasid": false, "kvm-steal-time": true, "lm": true, @@ -29,28 +31,32 @@ "adx": false, "fxsr": true, "sha-ni": false, - "tm": false, + "decodeassists": false, + "hv-relaxed": false, "pclmuldq": true, "xgetbv1": false, "xstore": false, "vmcb_clean": false, + "tsc-adjust": true, "vme": true, "vendor": "GenuineIntel", - "arat": false, + "arat": true, "ffxsr": false, "de": true, - "avx512f": false, + "aes": true, "pse": true, "ds-cpl": false, + "fxsr_opt": false, "tbm": false, - "ia64": false, + "sse": true, "phe-en": false, "f16c": false, "ds": false, "mpx": false, - "tsc-adjust": true, - "aes": true, + "vmware-cpuid-freq": true, + "avx512f": false, "avx2": false, + "level": 13, "pbe": false, "cx16": true, "ds_cpl": false, @@ -59,37 +65,41 @@ "nrip_save": false, "kvm_mmu": false, "ospke": false, + "pmu": false, "avx512ifma": false, - "vmx": false, + "stepping": 7, "sep": true, - "xsaveopt": true, "sse4a": false, "avx512dq": false, + "core-id": -1, "i64": true, "avx512-4vnniw": false, "xsave": true, - "erms": false, + "pmm": false, "hle": false, "nodeid_msr": false, + "hv-crash": false, "est": false, - "svm_lock": false, + "osxsave": false, "xop": false, - "model-id": " Intel(R) Core(TM) i7-2600 CPU @ 3.40GHz", - "abm": false, + "smx": false, + "tsc-scale": false, + "monitor": false, "avx512er": false, + "apic": true, "sse4.1": true, "sse4.2": true, + "hv-vapic": false, "pause-filter": false, "lahf-lm": true, "kvm-nopiodelay": true, "cmp_legacy": false, "acpi": false, "fma4": false, - "popcnt": true, "mmx": true, - "osxsave": false, + "svm_lock": false, "pcommit": false, - "avx512pf": false, + "mtrr": true, "clwb": false, "dca": false, "pdcm": false, @@ -97,23 +107,30 @@ "3dnow": false, "invtsc": false, "tm2": false, + "hv-time": false, "hypervisor": true, "kvmclock-stable-bit": true, - "fxsr-opt": false, + "xlevel": 2147483656, + "lahf_lm": true, + "enforce": false, "pcid": true, "sse4-1": true, - "sse4-2": true, + "lbrv": false, "avx512-vpopcntdq": false, "avx512-4fmaps": false, + "fill-mtrr-mask": true, "pause_filter": false, "svm-lock": false, - "rdrand": false, + "popcnt": true, "nrip-save": false, "avx512vl": false, "x2apic": true, "kvmclock": true, - "pge": true, + "smap": false, + "pdpe1gb": false, "family": 6, + "min-level": 13, + "xlevel2": 0, "dtes64": false, "xd": true, "kvm_pv_eoi": true, @@ -122,78 +139,93 @@ "xtpr": false, "perfctr_nb": false, "avx512bw": false, + "l3-cache": true, "nx": true, "lwp": false, "msr": true, - "ace2-en": false, - "decodeassists": false, + "syscall": true, + "tm": false, "perfctr-core": false, + "memory": "/machine/unattached/system[0]", + "pge": true, "pn": false, "fma": false, "nodeid-msr": false, - "kvm_asyncpf": true, - "clflush": true, + "xsavec": false, + "socket-id": -1, + "thread-id": -1, "cx8": true, "mce": true, "avx512cd": false, "cr8legacy": false, "mca": true, + "avx512pf": false, "pni": true, + "hv-vendor-id": "", "rdseed": false, - "apic": true, + "osvw": false, "fsgsbase": false, + "model-id": " Intel(R) Core(TM) i7-2600 CPU @ 3.40GHz", "cmp-legacy": false, "kvm-pv-unhalt": true, "rdtscp": true, "mmxext": false, + "host-phys-bits": true, "cid": false, + "vmx": false, "ssse3": true, "extapic": false, "pse36": true, - "mtrr": true, + "min-xlevel": 2147483656, "ibs": false, "la57": false, "avx": true, - "syscall": true, + "kvm-no-smi-migration": false, + "ace2-en": false, "umip": false, "invpcid": false, - "avx512vbmi": false, - "kvm-asyncpf": true, + "bmi1": false, + "bmi2": false, "vmcb-clean": false, - "pmm": false, + "erms": false, "cmov": true, + "check": true, "perfctr_core": false, "misalignsse": false, "clflushopt": false, "pat": true, - "lbrv": false, + "sse4-2": true, "3dnowprefetch": false, - "fpu": true, + "rdpid": false, + "full-cpuid-auto-level": true, "pae": true, "wdt": false, "tsc_scale": false, "skinit": false, - "fxsr_opt": false, + "fxsr-opt": false, "kvm_nopiodelay": true, + "phys-bits": 0, + "kvm": true, "pmm-en": false, "phe": false, "3dnowext": false, - "osvw": false, + "lmce": true, "ht": false, - "pdpe1gb": false, + "tsc-frequency": 0, "kvm-pv-eoi": true, "npt": false, - "xsavec": false, - "lahf_lm": true, + "apic-id": 4294967295, + "kvm_asyncpf": true, + "min-xlevel2": 0, "pclmulqdq": true, "svm": false, "sse3": true, "sse2": true, "ss": true, "topoext": false, - "smx": false, - "bmi1": false, - "bmi2": false, + "rdrand": false, + "avx512vbmi": false, + "kvm-asyncpf": true, "xsaves": false, "model": 42 } @@ -201,3 +233,375 @@ }, "id": "model-expansion" } + +{ + "return": [ + { + "typename": "max-x86_64-cpu", + "unavailable-features": [], + "migration-safe": false, + "static": false, + "name": "max" + }, + { + "typename": "host-x86_64-cpu", + "unavailable-features": [], + "migration-safe": false, + "static": false, + "name": "host" + }, + { + "typename": "base-x86_64-cpu", + "unavailable-features": [], + "migration-safe": true, + "static": true, + "name": "base" + }, + { + "typename": "qemu64-x86_64-cpu", + "unavailable-features": [], + "migration-safe": true, + "static": false, + "name": "qemu64" + }, + { + "typename": "qemu32-x86_64-cpu", + "unavailable-features": [], + "migration-safe": true, + "static": false, + "name": "qemu32" + }, + { + "typename": "phenom-x86_64-cpu", + "unavailable-features": [ + "mmxext", + "fxsr-opt", + "pdpe1gb", + "3dnowext", + "3dnow", + "abm", + "sse4a", + "npt" + ], + "migration-safe": true, + "static": false, + "name": "phenom" + }, + { + "typename": "pentium3-x86_64-cpu", + "unavailable-features": [], + "migration-safe": true, + "static": false, + "name": "pentium3" + }, + { + "typename": "pentium2-x86_64-cpu", + "unavailable-features": [], + "migration-safe": true, + "static": false, + "name": "pentium2" + }, + { + "typename": "pentium-x86_64-cpu", + "unavailable-features": [], + "migration-safe": true, + "static": false, + "name": "pentium" + }, + { + "typename": "n270-x86_64-cpu", + "unavailable-features": [ + "movbe" + ], + "migration-safe": true, + "static": false, + "name": "n270" + }, + { + "typename": "kvm64-x86_64-cpu", + "unavailable-features": [], + "migration-safe": true, + "static": false, + "name": "kvm64" + }, + { + "typename": "kvm32-x86_64-cpu", + "unavailable-features": [], + "migration-safe": true, + "static": false, + "name": "kvm32" + }, + { + "typename": "cpu64-rhel6-x86_64-cpu", + "unavailable-features": [ + "abm", + "sse4a" + ], + "migration-safe": true, + "static": false, + "name": "cpu64-rhel6" + }, + { + "typename": "coreduo-x86_64-cpu", + "unavailable-features": [], + "migration-safe": true, + "static": false, + "name": "coreduo" + }, + { + "typename": "core2duo-x86_64-cpu", + "unavailable-features": [], + "migration-safe": true, + "static": false, + "name": "core2duo" + }, + { + "typename": "athlon-x86_64-cpu", + "unavailable-features": [ + "mmxext", + "3dnowext", + "3dnow" + ], + "migration-safe": true, + "static": false, + "name": "athlon" + }, + { + "typename": "Westmere-x86_64-cpu", + "unavailable-features": [], + "migration-safe": true, + "static": false, + "name": "Westmere" + }, + { + "typename": "Skylake-Client-x86_64-cpu", + "unavailable-features": [ + "fma", + "movbe", + "f16c", + "rdrand", + "fsgsbase", + "bmi1", + "hle", + "avx2", + "smep", + "bmi2", + "erms", + "invpcid", + "rtm", + "mpx", + "rdseed", + "adx", + "smap", + "abm", + "3dnowprefetch", + "xsavec", + "xgetbv1", + "mpx", + "mpx" + ], + "migration-safe": true, + "static": false, + "name": "Skylake-Client" + }, + { + "typename": "SandyBridge-x86_64-cpu", + "unavailable-features": [], + "migration-safe": true, + "static": false, + "name": "SandyBridge" + }, + { + "typename": "Penryn-x86_64-cpu", + "unavailable-features": [], + "migration-safe": true, + "static": false, + "name": "Penryn" + }, + { + "typename": "Opteron_G5-x86_64-cpu", + "unavailable-features": [ + "fma", + "f16c", + "pdpe1gb", + "abm", + "sse4a", + "misalignsse", + "3dnowprefetch", + "xop", + "fma4", + "tbm" + ], + "migration-safe": true, + "static": false, + "name": "Opteron_G5" + }, + { + "typename": "Opteron_G4-x86_64-cpu", + "unavailable-features": [ + "pdpe1gb", + "abm", + "sse4a", + "misalignsse", + "3dnowprefetch", + "xop", + "fma4" + ], + "migration-safe": true, + "static": false, + "name": "Opteron_G4" + }, + { + "typename": "Opteron_G3-x86_64-cpu", + "unavailable-features": [ + "abm", + "sse4a", + "misalignsse" + ], + "migration-safe": true, + "static": false, + "name": "Opteron_G3" + }, + { + "typename": "Opteron_G2-x86_64-cpu", + "unavailable-features": [], + "migration-safe": true, + "static": false, + "name": "Opteron_G2" + }, + { + "typename": "Opteron_G1-x86_64-cpu", + "unavailable-features": [], + "migration-safe": true, + "static": false, + "name": "Opteron_G1" + }, + { + "typename": "Nehalem-x86_64-cpu", + "unavailable-features": [], + "migration-safe": true, + "static": false, + "name": "Nehalem" + }, + { + "typename": "IvyBridge-x86_64-cpu", + "unavailable-features": [ + "f16c", + "rdrand", + "fsgsbase", + "smep", + "erms" + ], + "migration-safe": true, + "static": false, + "name": "IvyBridge" + }, + { + "typename": "Haswell-x86_64-cpu", + "unavailable-features": [ + "fma", + "movbe", + "f16c", + "rdrand", + "fsgsbase", + "bmi1", + "hle", + "avx2", + "smep", + "bmi2", + "erms", + "invpcid", + "rtm", + "abm" + ], + "migration-safe": true, + "static": false, + "name": "Haswell" + }, + { + "typename": "Haswell-noTSX-x86_64-cpu", + "unavailable-features": [ + "fma", + "movbe", + "f16c", + "rdrand", + "fsgsbase", + "bmi1", + "avx2", + "smep", + "bmi2", + "erms", + "invpcid", + "abm" + ], + "migration-safe": true, + "static": false, + "name": "Haswell-noTSX" + }, + { + "typename": "Conroe-x86_64-cpu", + "unavailable-features": [], + "migration-safe": true, + "static": false, + "name": "Conroe" + }, + { + "typename": "Broadwell-x86_64-cpu", + "unavailable-features": [ + "fma", + "movbe", + "f16c", + "rdrand", + "fsgsbase", + "bmi1", + "hle", + "avx2", + "smep", + "bmi2", + "erms", + "invpcid", + "rtm", + "rdseed", + "adx", + "smap", + "abm", + "3dnowprefetch" + ], + "migration-safe": true, + "static": false, + "name": "Broadwell" + }, + { + "typename": "Broadwell-noTSX-x86_64-cpu", + "unavailable-features": [ + "fma", + "movbe", + "f16c", + "rdrand", + "fsgsbase", + "bmi1", + "avx2", + "smep", + "bmi2", + "erms", + "invpcid", + "rdseed", + "adx", + "smap", + "abm", + "3dnowprefetch" + ], + "migration-safe": true, + "static": false, + "name": "Broadwell-noTSX" + }, + { + "typename": "486-x86_64-cpu", + "unavailable-features": [], + "migration-safe": true, + "static": false, + "name": "486" + } + ], + "id": "definitions" +} diff --git a/tests/cputestdata/x86_64-cpuid-Core-i7-2600.xml b/tests/cputestdata/x86_64-cpuid-Core-i7-2600.xml index ad15597d6b..8c0f847fef 100644 --- a/tests/cputestdata/x86_64-cpuid-Core-i7-2600.xml +++ b/tests/cputestdata/x86_64-cpuid-Core-i7-2600.xml @@ -1,7 +1,7 @@ <!-- Intel(R) Core(TM) i7-2600 CPU @ 3.40GHz --> <cpudata arch='x86'> <cpuid eax_in='0x00000000' ecx_in='0x00' eax='0x0000000d' ebx='0x756e6547' ecx='0x6c65746e' edx='0x49656e69'/> - <cpuid eax_in='0x00000001' ecx_in='0x00' eax='0x000206a7' ebx='0x05100800' ecx='0x1fbae3ff' edx='0xbfebfbff'/> + <cpuid eax_in='0x00000001' ecx_in='0x00' eax='0x000206a7' ebx='0x01100800' ecx='0x1fbae3ff' edx='0xbfebfbff'/> <cpuid eax_in='0x00000002' ecx_in='0x00' eax='0x76035a01' ebx='0x00f0b2ff' ecx='0x00000000' edx='0x00ca0000'/> <cpuid eax_in='0x00000003' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/> <cpuid eax_in='0x00000004' ecx_in='0x00' eax='0x1c004121' ebx='0x01c0003f' ecx='0x0000003f' edx='0x00000000'/> @@ -14,8 +14,8 @@ <cpuid eax_in='0x00000008' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/> <cpuid eax_in='0x00000009' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/> <cpuid eax_in='0x0000000a' ecx_in='0x00' eax='0x07300403' ebx='0x00000000' ecx='0x00000000' edx='0x00000603'/> - <cpuid eax_in='0x0000000b' ecx_in='0x00' eax='0x00000001' ebx='0x00000002' ecx='0x00000100' edx='0x00000005'/> - <cpuid eax_in='0x0000000b' ecx_in='0x01' eax='0x00000004' ebx='0x00000008' ecx='0x00000201' edx='0x00000005'/> + <cpuid eax_in='0x0000000b' ecx_in='0x00' eax='0x00000001' ebx='0x00000002' ecx='0x00000100' edx='0x00000001'/> + <cpuid eax_in='0x0000000b' ecx_in='0x01' eax='0x00000004' ebx='0x00000008' ecx='0x00000201' edx='0x00000001'/> <cpuid eax_in='0x0000000c' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/> <cpuid eax_in='0x0000000d' ecx_in='0x00' eax='0x00000007' ebx='0x00000340' ecx='0x00000340' edx='0x00000000'/> <cpuid eax_in='0x0000000d' ecx_in='0x01' eax='0x00000001' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/> -- 2.14.2

On 10/04/2017 10:58 AM, Jiri Denemark wrote:
arat is now enabled even if the hardware does not support it.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- .../x86_64-cpuid-Core-i7-2600-disabled.xml | 1 - .../x86_64-cpuid-Core-i7-2600-enabled.xml | 1 + .../cputestdata/x86_64-cpuid-Core-i7-2600-json.xml | 1 + tests/cputestdata/x86_64-cpuid-Core-i7-2600.json | 496 +++++++++++++++++++-- tests/cputestdata/x86_64-cpuid-Core-i7-2600.xml | 6 +- 5 files changed, 455 insertions(+), 50 deletions(-)
Similar question to two patches ago regarding when the feature was added and migrate/save/restore-ability. Still, looks reasonable to me... Reviewed-by: John Ferlan <jferlan@redhat.com> John One would think the order of the data would change radically... Hard, if not impossible to visually match up old/new data.

On Thu, Oct 12, 2017 at 18:22:42 -0400, John Ferlan wrote:
On 10/04/2017 10:58 AM, Jiri Denemark wrote:
arat is now enabled even if the hardware does not support it.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- .../x86_64-cpuid-Core-i7-2600-disabled.xml | 1 - .../x86_64-cpuid-Core-i7-2600-enabled.xml | 1 + .../cputestdata/x86_64-cpuid-Core-i7-2600-json.xml | 1 + tests/cputestdata/x86_64-cpuid-Core-i7-2600.json | 496 +++++++++++++++++++-- tests/cputestdata/x86_64-cpuid-Core-i7-2600.xml | 6 +- 5 files changed, 455 insertions(+), 50 deletions(-)
Similar question to two patches ago regarding when the feature was added and migrate/save/restore-ability.
Still, looks reasonable to me...
Reviewed-by: John Ferlan <jferlan@redhat.com>
John
One would think the order of the data would change radically... Hard, if not impossible to visually match up old/new data.
Yeah, it's easier to see the difference in the XMLs with raw CPUIDs. Jirka

xsaveopt is artificially removed from the host to test disabled feature which is only included in QEMU's version of the CPU model. Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- tests/cputest.c | 1 + ...x86_64-cpuid-Core-i7-2600-xsaveopt-disabled.xml | 6 + .../x86_64-cpuid-Core-i7-2600-xsaveopt-enabled.xml | 8 + .../x86_64-cpuid-Core-i7-2600-xsaveopt-guest.xml | 25 + .../x86_64-cpuid-Core-i7-2600-xsaveopt-host.xml | 25 + .../x86_64-cpuid-Core-i7-2600-xsaveopt-json.xml | 11 + .../x86_64-cpuid-Core-i7-2600-xsaveopt.json | 615 +++++++++++++++++++++ .../x86_64-cpuid-Core-i7-2600-xsaveopt.xml | 33 ++ 8 files changed, 724 insertions(+) create mode 100644 tests/cputestdata/x86_64-cpuid-Core-i7-2600-xsaveopt-disabled.xml create mode 100644 tests/cputestdata/x86_64-cpuid-Core-i7-2600-xsaveopt-enabled.xml create mode 100644 tests/cputestdata/x86_64-cpuid-Core-i7-2600-xsaveopt-guest.xml create mode 100644 tests/cputestdata/x86_64-cpuid-Core-i7-2600-xsaveopt-host.xml create mode 100644 tests/cputestdata/x86_64-cpuid-Core-i7-2600-xsaveopt-json.xml create mode 100644 tests/cputestdata/x86_64-cpuid-Core-i7-2600-xsaveopt.json create mode 100644 tests/cputestdata/x86_64-cpuid-Core-i7-2600-xsaveopt.xml diff --git a/tests/cputest.c b/tests/cputest.c index cfd63bfcf7..6b48956c4d 100644 --- a/tests/cputest.c +++ b/tests/cputest.c @@ -1125,6 +1125,7 @@ mymain(void) DO_TEST_CPUID(VIR_ARCH_X86_64, "Core-i5-4670T", JSON_HOST); DO_TEST_CPUID(VIR_ARCH_X86_64, "Core-i5-6600", JSON_HOST); DO_TEST_CPUID(VIR_ARCH_X86_64, "Core-i7-2600", JSON_HOST); + DO_TEST_CPUID(VIR_ARCH_X86_64, "Core-i7-2600-xsaveopt", JSON_MODELS); DO_TEST_CPUID(VIR_ARCH_X86_64, "Core-i7-3520M", JSON_NONE); DO_TEST_CPUID(VIR_ARCH_X86_64, "Core-i7-3740QM", JSON_HOST); DO_TEST_CPUID(VIR_ARCH_X86_64, "Core-i7-3770", JSON_HOST); diff --git a/tests/cputestdata/x86_64-cpuid-Core-i7-2600-xsaveopt-disabled.xml b/tests/cputestdata/x86_64-cpuid-Core-i7-2600-xsaveopt-disabled.xml new file mode 100644 index 0000000000..281cc1512a --- /dev/null +++ b/tests/cputestdata/x86_64-cpuid-Core-i7-2600-xsaveopt-disabled.xml @@ -0,0 +1,6 @@ +<!-- Features disabled by QEMU --> +<cpudata arch='x86'> + <cpuid eax_in='0x00000001' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x0800c1fc' edx='0xb0600000'/> + <cpuid eax_in='0x0000000d' ecx_in='0x01' eax='0x00000001' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/> + <cpuid eax_in='0x80000007' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000100'/> +</cpudata> diff --git a/tests/cputestdata/x86_64-cpuid-Core-i7-2600-xsaveopt-enabled.xml b/tests/cputestdata/x86_64-cpuid-Core-i7-2600-xsaveopt-enabled.xml new file mode 100644 index 0000000000..3c2d7e33d6 --- /dev/null +++ b/tests/cputestdata/x86_64-cpuid-Core-i7-2600-xsaveopt-enabled.xml @@ -0,0 +1,8 @@ +<!-- Features enabled by QEMU --> +<cpudata arch='x86'> + <cpuid eax_in='0x00000001' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x97ba2203' edx='0x0f8bfbff'/> + <cpuid eax_in='0x00000006' ecx_in='0x00' eax='0x00000004' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/> + <cpuid eax_in='0x00000007' ecx_in='0x00' eax='0x00000000' ebx='0x00000002' ecx='0x00000000' edx='0x00000000'/> + <cpuid eax_in='0x40000001' ecx_in='0x00' eax='0x010000fa' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/> + <cpuid eax_in='0x80000001' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000001' edx='0x28100800'/> +</cpudata> diff --git a/tests/cputestdata/x86_64-cpuid-Core-i7-2600-xsaveopt-guest.xml b/tests/cputestdata/x86_64-cpuid-Core-i7-2600-xsaveopt-guest.xml new file mode 100644 index 0000000000..9bb60009e8 --- /dev/null +++ b/tests/cputestdata/x86_64-cpuid-Core-i7-2600-xsaveopt-guest.xml @@ -0,0 +1,25 @@ +<cpu mode='custom' match='exact'> + <model fallback='forbid'>SandyBridge</model> + <vendor>Intel</vendor> + <feature policy='require' name='vme'/> + <feature policy='require' name='ds'/> + <feature policy='require' name='acpi'/> + <feature policy='require' name='ss'/> + <feature policy='require' name='ht'/> + <feature policy='require' name='tm'/> + <feature policy='require' name='pbe'/> + <feature policy='require' name='dtes64'/> + <feature policy='require' name='monitor'/> + <feature policy='require' name='ds_cpl'/> + <feature policy='require' name='vmx'/> + <feature policy='require' name='smx'/> + <feature policy='require' name='est'/> + <feature policy='require' name='tm2'/> + <feature policy='require' name='xtpr'/> + <feature policy='require' name='pdcm'/> + <feature policy='require' name='pcid'/> + <feature policy='require' name='osxsave'/> + <feature policy='require' name='arat'/> + <feature policy='require' name='invtsc'/> + <feature policy='disable' name='xsaveopt'/> +</cpu> diff --git a/tests/cputestdata/x86_64-cpuid-Core-i7-2600-xsaveopt-host.xml b/tests/cputestdata/x86_64-cpuid-Core-i7-2600-xsaveopt-host.xml new file mode 100644 index 0000000000..e139004923 --- /dev/null +++ b/tests/cputestdata/x86_64-cpuid-Core-i7-2600-xsaveopt-host.xml @@ -0,0 +1,25 @@ +<cpu> + <arch>x86_64</arch> + <model>SandyBridge</model> + <vendor>Intel</vendor> + <feature name='vme'/> + <feature name='ds'/> + <feature name='acpi'/> + <feature name='ss'/> + <feature name='ht'/> + <feature name='tm'/> + <feature name='pbe'/> + <feature name='dtes64'/> + <feature name='monitor'/> + <feature name='ds_cpl'/> + <feature name='vmx'/> + <feature name='smx'/> + <feature name='est'/> + <feature name='tm2'/> + <feature name='xtpr'/> + <feature name='pdcm'/> + <feature name='pcid'/> + <feature name='osxsave'/> + <feature name='arat'/> + <feature name='invtsc'/> +</cpu> diff --git a/tests/cputestdata/x86_64-cpuid-Core-i7-2600-xsaveopt-json.xml b/tests/cputestdata/x86_64-cpuid-Core-i7-2600-xsaveopt-json.xml new file mode 100644 index 0000000000..3a799052e7 --- /dev/null +++ b/tests/cputestdata/x86_64-cpuid-Core-i7-2600-xsaveopt-json.xml @@ -0,0 +1,11 @@ +<cpu mode='custom' match='exact'> + <model fallback='forbid'>SandyBridge</model> + <vendor>Intel</vendor> + <feature policy='require' name='vme'/> + <feature policy='require' name='ss'/> + <feature policy='require' name='pcid'/> + <feature policy='require' name='hypervisor'/> + <feature policy='require' name='arat'/> + <feature policy='require' name='tsc_adjust'/> + <feature policy='disable' name='xsaveopt'/> +</cpu> diff --git a/tests/cputestdata/x86_64-cpuid-Core-i7-2600-xsaveopt.json b/tests/cputestdata/x86_64-cpuid-Core-i7-2600-xsaveopt.json new file mode 100644 index 0000000000..ae079f3c54 --- /dev/null +++ b/tests/cputestdata/x86_64-cpuid-Core-i7-2600-xsaveopt.json @@ -0,0 +1,615 @@ +{ + "return": { + "model": { + "name": "base", + "props": { + "pfthreshold": false, + "pku": false, + "rtm": false, + "tsc_adjust": true, + "tsc-deadline": true, + "xstore-en": false, + "cpuid-0xb": true, + "abm": false, + "ia64": false, + "kvm-mmu": false, + "xsaveopt": false, + "hv-spinlocks": -1, + "tce": false, + "realized": false, + "kvm_steal_time": true, + "smep": false, + "fpu": true, + "xcrypt": false, + "sse4_2": true, + "clflush": true, + "sse4_1": true, + "flushbyasid": false, + "kvm-steal-time": true, + "lm": true, + "tsc": true, + "adx": false, + "fxsr": true, + "sha-ni": false, + "decodeassists": false, + "hv-relaxed": false, + "pclmuldq": true, + "xgetbv1": false, + "xstore": false, + "vmcb_clean": false, + "tsc-adjust": true, + "vme": true, + "vendor": "GenuineIntel", + "arat": true, + "ffxsr": false, + "de": true, + "aes": true, + "pse": true, + "ds-cpl": false, + "fxsr_opt": false, + "tbm": false, + "sse": true, + "phe-en": false, + "f16c": false, + "ds": false, + "mpx": false, + "vmware-cpuid-freq": true, + "avx512f": false, + "avx2": false, + "level": 13, + "pbe": false, + "cx16": true, + "ds_cpl": false, + "movbe": false, + "perfctr-nb": false, + "nrip_save": false, + "kvm_mmu": false, + "ospke": false, + "pmu": false, + "avx512ifma": false, + "stepping": 7, + "sep": true, + "sse4a": false, + "avx512dq": false, + "core-id": -1, + "i64": true, + "avx512-4vnniw": false, + "xsave": true, + "pmm": false, + "hle": false, + "nodeid_msr": false, + "hv-crash": false, + "est": false, + "osxsave": false, + "xop": false, + "smx": false, + "tsc-scale": false, + "monitor": false, + "avx512er": false, + "apic": true, + "sse4.1": true, + "sse4.2": true, + "hv-vapic": false, + "pause-filter": false, + "lahf-lm": true, + "kvm-nopiodelay": true, + "cmp_legacy": false, + "acpi": false, + "fma4": false, + "mmx": true, + "svm_lock": false, + "pcommit": false, + "mtrr": true, + "clwb": false, + "dca": false, + "pdcm": false, + "xcrypt-en": false, + "3dnow": false, + "invtsc": false, + "tm2": false, + "hv-time": false, + "hypervisor": true, + "kvmclock-stable-bit": true, + "xlevel": 2147483656, + "lahf_lm": true, + "enforce": false, + "pcid": true, + "sse4-1": true, + "lbrv": false, + "avx512-vpopcntdq": false, + "avx512-4fmaps": false, + "fill-mtrr-mask": true, + "pause_filter": false, + "svm-lock": false, + "popcnt": true, + "nrip-save": false, + "avx512vl": false, + "x2apic": true, + "kvmclock": true, + "smap": false, + "pdpe1gb": false, + "family": 6, + "min-level": 13, + "xlevel2": 0, + "dtes64": false, + "xd": true, + "kvm_pv_eoi": true, + "ace2": false, + "kvm_pv_unhalt": true, + "xtpr": false, + "perfctr_nb": false, + "avx512bw": false, + "l3-cache": true, + "nx": true, + "lwp": false, + "msr": true, + "syscall": true, + "tm": false, + "perfctr-core": false, + "memory": "/machine/unattached/system[0]", + "pge": true, + "pn": false, + "fma": false, + "nodeid-msr": false, + "xsavec": false, + "socket-id": -1, + "thread-id": -1, + "cx8": true, + "mce": true, + "avx512cd": false, + "cr8legacy": false, + "mca": true, + "avx512pf": false, + "pni": true, + "hv-vendor-id": "", + "rdseed": false, + "osvw": false, + "fsgsbase": false, + "model-id": " Intel(R) Core(TM) i7-2600 CPU @ 3.40GHz", + "cmp-legacy": false, + "kvm-pv-unhalt": true, + "rdtscp": true, + "mmxext": false, + "host-phys-bits": true, + "cid": false, + "vmx": false, + "ssse3": true, + "extapic": false, + "pse36": true, + "min-xlevel": 2147483656, + "ibs": false, + "la57": false, + "avx": true, + "kvm-no-smi-migration": false, + "ace2-en": false, + "umip": false, + "invpcid": false, + "bmi1": false, + "bmi2": false, + "vmcb-clean": false, + "erms": false, + "cmov": true, + "check": true, + "perfctr_core": false, + "misalignsse": false, + "clflushopt": false, + "pat": true, + "sse4-2": true, + "3dnowprefetch": false, + "rdpid": false, + "full-cpuid-auto-level": true, + "pae": true, + "wdt": false, + "tsc_scale": false, + "skinit": false, + "fxsr-opt": false, + "kvm_nopiodelay": true, + "phys-bits": 0, + "kvm": true, + "pmm-en": false, + "phe": false, + "3dnowext": false, + "lmce": true, + "ht": false, + "tsc-frequency": 0, + "kvm-pv-eoi": true, + "npt": false, + "apic-id": 4294967295, + "kvm_asyncpf": true, + "min-xlevel2": 0, + "pclmulqdq": true, + "svm": false, + "sse3": true, + "sse2": true, + "ss": true, + "topoext": false, + "rdrand": false, + "avx512vbmi": false, + "kvm-asyncpf": true, + "xsaves": false, + "model": 42 + } + } + }, + "id": "model-expansion" +} + +{ + "return": [ + { + "typename": "max-x86_64-cpu", + "unavailable-features": [], + "migration-safe": false, + "static": false, + "name": "max" + }, + { + "typename": "host-x86_64-cpu", + "unavailable-features": [], + "migration-safe": false, + "static": false, + "name": "host" + }, + { + "typename": "base-x86_64-cpu", + "unavailable-features": [], + "migration-safe": true, + "static": true, + "name": "base" + }, + { + "typename": "qemu64-x86_64-cpu", + "unavailable-features": [], + "migration-safe": true, + "static": false, + "name": "qemu64" + }, + { + "typename": "qemu32-x86_64-cpu", + "unavailable-features": [], + "migration-safe": true, + "static": false, + "name": "qemu32" + }, + { + "typename": "phenom-x86_64-cpu", + "unavailable-features": [ + "mmxext", + "fxsr-opt", + "pdpe1gb", + "3dnowext", + "3dnow", + "abm", + "sse4a", + "npt" + ], + "migration-safe": true, + "static": false, + "name": "phenom" + }, + { + "typename": "pentium3-x86_64-cpu", + "unavailable-features": [], + "migration-safe": true, + "static": false, + "name": "pentium3" + }, + { + "typename": "pentium2-x86_64-cpu", + "unavailable-features": [], + "migration-safe": true, + "static": false, + "name": "pentium2" + }, + { + "typename": "pentium-x86_64-cpu", + "unavailable-features": [], + "migration-safe": true, + "static": false, + "name": "pentium" + }, + { + "typename": "n270-x86_64-cpu", + "unavailable-features": [ + "movbe" + ], + "migration-safe": true, + "static": false, + "name": "n270" + }, + { + "typename": "kvm64-x86_64-cpu", + "unavailable-features": [], + "migration-safe": true, + "static": false, + "name": "kvm64" + }, + { + "typename": "kvm32-x86_64-cpu", + "unavailable-features": [], + "migration-safe": true, + "static": false, + "name": "kvm32" + }, + { + "typename": "cpu64-rhel6-x86_64-cpu", + "unavailable-features": [ + "abm", + "sse4a" + ], + "migration-safe": true, + "static": false, + "name": "cpu64-rhel6" + }, + { + "typename": "coreduo-x86_64-cpu", + "unavailable-features": [], + "migration-safe": true, + "static": false, + "name": "coreduo" + }, + { + "typename": "core2duo-x86_64-cpu", + "unavailable-features": [], + "migration-safe": true, + "static": false, + "name": "core2duo" + }, + { + "typename": "athlon-x86_64-cpu", + "unavailable-features": [ + "mmxext", + "3dnowext", + "3dnow" + ], + "migration-safe": true, + "static": false, + "name": "athlon" + }, + { + "typename": "Westmere-x86_64-cpu", + "unavailable-features": [], + "migration-safe": true, + "static": false, + "name": "Westmere" + }, + { + "typename": "Skylake-Client-x86_64-cpu", + "unavailable-features": [ + "fma", + "movbe", + "f16c", + "rdrand", + "fsgsbase", + "bmi1", + "hle", + "avx2", + "smep", + "bmi2", + "erms", + "invpcid", + "rtm", + "mpx", + "rdseed", + "adx", + "smap", + "abm", + "3dnowprefetch", + "xsavec", + "xgetbv1", + "mpx", + "mpx", + "xsaveopt" + ], + "migration-safe": true, + "static": false, + "name": "Skylake-Client" + }, + { + "typename": "SandyBridge-x86_64-cpu", + "unavailable-features": [ + "xsaveopt" + ], + "migration-safe": true, + "static": false, + "name": "SandyBridge" + }, + { + "typename": "Penryn-x86_64-cpu", + "unavailable-features": [], + "migration-safe": true, + "static": false, + "name": "Penryn" + }, + { + "typename": "Opteron_G5-x86_64-cpu", + "unavailable-features": [ + "fma", + "f16c", + "pdpe1gb", + "abm", + "sse4a", + "misalignsse", + "3dnowprefetch", + "xop", + "fma4", + "tbm" + ], + "migration-safe": true, + "static": false, + "name": "Opteron_G5" + }, + { + "typename": "Opteron_G4-x86_64-cpu", + "unavailable-features": [ + "pdpe1gb", + "abm", + "sse4a", + "misalignsse", + "3dnowprefetch", + "xop", + "fma4" + ], + "migration-safe": true, + "static": false, + "name": "Opteron_G4" + }, + { + "typename": "Opteron_G3-x86_64-cpu", + "unavailable-features": [ + "abm", + "sse4a", + "misalignsse" + ], + "migration-safe": true, + "static": false, + "name": "Opteron_G3" + }, + { + "typename": "Opteron_G2-x86_64-cpu", + "unavailable-features": [], + "migration-safe": true, + "static": false, + "name": "Opteron_G2" + }, + { + "typename": "Opteron_G1-x86_64-cpu", + "unavailable-features": [], + "migration-safe": true, + "static": false, + "name": "Opteron_G1" + }, + { + "typename": "Nehalem-x86_64-cpu", + "unavailable-features": [], + "migration-safe": true, + "static": false, + "name": "Nehalem" + }, + { + "typename": "IvyBridge-x86_64-cpu", + "unavailable-features": [ + "f16c", + "rdrand", + "fsgsbase", + "smep", + "erms", + "xsaveopt" + ], + "migration-safe": true, + "static": false, + "name": "IvyBridge" + }, + { + "typename": "Haswell-x86_64-cpu", + "unavailable-features": [ + "fma", + "movbe", + "f16c", + "rdrand", + "fsgsbase", + "bmi1", + "hle", + "avx2", + "smep", + "bmi2", + "erms", + "invpcid", + "rtm", + "abm", + "xsaveopt" + ], + "migration-safe": true, + "static": false, + "name": "Haswell" + }, + { + "typename": "Haswell-noTSX-x86_64-cpu", + "unavailable-features": [ + "fma", + "movbe", + "f16c", + "rdrand", + "fsgsbase", + "bmi1", + "avx2", + "smep", + "bmi2", + "erms", + "invpcid", + "abm", + "xsaveopt" + ], + "migration-safe": true, + "static": false, + "name": "Haswell-noTSX" + }, + { + "typename": "Conroe-x86_64-cpu", + "unavailable-features": [], + "migration-safe": true, + "static": false, + "name": "Conroe" + }, + { + "typename": "Broadwell-x86_64-cpu", + "unavailable-features": [ + "fma", + "movbe", + "f16c", + "rdrand", + "fsgsbase", + "bmi1", + "hle", + "avx2", + "smep", + "bmi2", + "erms", + "invpcid", + "rtm", + "rdseed", + "adx", + "smap", + "abm", + "3dnowprefetch", + "xsaveopt" + ], + "migration-safe": true, + "static": false, + "name": "Broadwell" + }, + { + "typename": "Broadwell-noTSX-x86_64-cpu", + "unavailable-features": [ + "fma", + "movbe", + "f16c", + "rdrand", + "fsgsbase", + "bmi1", + "avx2", + "smep", + "bmi2", + "erms", + "invpcid", + "rdseed", + "adx", + "smap", + "abm", + "3dnowprefetch", + "xsaveopt" + ], + "migration-safe": true, + "static": false, + "name": "Broadwell-noTSX" + }, + { + "typename": "486-x86_64-cpu", + "unavailable-features": [], + "migration-safe": true, + "static": false, + "name": "486" + } + ], + "id": "definitions" +} diff --git a/tests/cputestdata/x86_64-cpuid-Core-i7-2600-xsaveopt.xml b/tests/cputestdata/x86_64-cpuid-Core-i7-2600-xsaveopt.xml new file mode 100644 index 0000000000..c2c9730a41 --- /dev/null +++ b/tests/cputestdata/x86_64-cpuid-Core-i7-2600-xsaveopt.xml @@ -0,0 +1,33 @@ +<!-- Intel(R) Core(TM) i7-2600 CPU @ 3.40GHz --> +<cpudata arch='x86'> + <cpuid eax_in='0x00000000' ecx_in='0x00' eax='0x0000000d' ebx='0x756e6547' ecx='0x6c65746e' edx='0x49656e69'/> + <cpuid eax_in='0x00000001' ecx_in='0x00' eax='0x000206a7' ebx='0x01100800' ecx='0x1fbae3ff' edx='0xbfebfbff'/> + <cpuid eax_in='0x00000002' ecx_in='0x00' eax='0x76035a01' ebx='0x00f0b2ff' ecx='0x00000000' edx='0x00ca0000'/> + <cpuid eax_in='0x00000003' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/> + <cpuid eax_in='0x00000004' ecx_in='0x00' eax='0x1c004121' ebx='0x01c0003f' ecx='0x0000003f' edx='0x00000000'/> + <cpuid eax_in='0x00000004' ecx_in='0x01' eax='0x1c004122' ebx='0x01c0003f' ecx='0x0000003f' edx='0x00000000'/> + <cpuid eax_in='0x00000004' ecx_in='0x02' eax='0x1c004143' ebx='0x01c0003f' ecx='0x000001ff' edx='0x00000000'/> + <cpuid eax_in='0x00000004' ecx_in='0x03' eax='0x1c03c163' ebx='0x03c0003f' ecx='0x00001fff' edx='0x00000006'/> + <cpuid eax_in='0x00000005' ecx_in='0x00' eax='0x00000040' ebx='0x00000040' ecx='0x00000003' edx='0x00001120'/> + <cpuid eax_in='0x00000006' ecx_in='0x00' eax='0x00000077' ebx='0x00000002' ecx='0x00000009' edx='0x00000000'/> + <cpuid eax_in='0x00000007' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/> + <cpuid eax_in='0x00000008' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/> + <cpuid eax_in='0x00000009' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/> + <cpuid eax_in='0x0000000a' ecx_in='0x00' eax='0x07300403' ebx='0x00000000' ecx='0x00000000' edx='0x00000603'/> + <cpuid eax_in='0x0000000b' ecx_in='0x00' eax='0x00000001' ebx='0x00000002' ecx='0x00000100' edx='0x00000001'/> + <cpuid eax_in='0x0000000b' ecx_in='0x01' eax='0x00000004' ebx='0x00000008' ecx='0x00000201' edx='0x00000001'/> + <cpuid eax_in='0x0000000c' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/> + <cpuid eax_in='0x0000000d' ecx_in='0x00' eax='0x00000007' ebx='0x00000340' ecx='0x00000340' edx='0x00000000'/> + <cpuid eax_in='0x0000000d' ecx_in='0x02' eax='0x00000100' ebx='0x00000240' ecx='0x00000000' edx='0x00000000'/> + <cpuid eax_in='0x80000000' ecx_in='0x00' eax='0x80000008' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/> + <cpuid eax_in='0x80000001' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000001' edx='0x28100800'/> + <cpuid eax_in='0x80000002' ecx_in='0x00' eax='0x20202020' ebx='0x20202020' ecx='0x65746e49' edx='0x2952286c'/> + <cpuid eax_in='0x80000003' ecx_in='0x00' eax='0x726f4320' ebx='0x4d542865' ecx='0x37692029' edx='0x3036322d'/> + <cpuid eax_in='0x80000004' ecx_in='0x00' eax='0x50432030' ebx='0x20402055' ecx='0x30342e33' edx='0x007a4847'/> + <cpuid eax_in='0x80000005' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/> + <cpuid eax_in='0x80000006' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x01006040' edx='0x00000000'/> + <cpuid eax_in='0x80000007' ecx_in='0x00' eax='0x00000000' ebx='0x00000000' ecx='0x00000000' edx='0x00000100'/> + <cpuid eax_in='0x80000008' ecx_in='0x00' eax='0x00003024' ebx='0x00000000' ecx='0x00000000' edx='0x00000000'/> + <cpuid eax_in='0x80860000' ecx_in='0x00' eax='0x00000007' ebx='0x00000340' ecx='0x00000340' edx='0x00000000'/> + <cpuid eax_in='0xc0000000' ecx_in='0x00' eax='0x00000007' ebx='0x00000340' ecx='0x00000340' edx='0x00000000'/> +</cpudata> -- 2.14.2

On 10/04/2017 10:58 AM, Jiri Denemark wrote:
xsaveopt is artificially removed from the host to test disabled feature which is only included in QEMU's version of the CPU model.
Signed-off-by: Jiri Denemark <jdenemar@redhat.com> --- tests/cputest.c | 1 + ...x86_64-cpuid-Core-i7-2600-xsaveopt-disabled.xml | 6 + .../x86_64-cpuid-Core-i7-2600-xsaveopt-enabled.xml | 8 + .../x86_64-cpuid-Core-i7-2600-xsaveopt-guest.xml | 25 + .../x86_64-cpuid-Core-i7-2600-xsaveopt-host.xml | 25 + .../x86_64-cpuid-Core-i7-2600-xsaveopt-json.xml | 11 + .../x86_64-cpuid-Core-i7-2600-xsaveopt.json | 615 +++++++++++++++++++++ .../x86_64-cpuid-Core-i7-2600-xsaveopt.xml | 33 ++ 8 files changed, 724 insertions(+) create mode 100644 tests/cputestdata/x86_64-cpuid-Core-i7-2600-xsaveopt-disabled.xml create mode 100644 tests/cputestdata/x86_64-cpuid-Core-i7-2600-xsaveopt-enabled.xml create mode 100644 tests/cputestdata/x86_64-cpuid-Core-i7-2600-xsaveopt-guest.xml create mode 100644 tests/cputestdata/x86_64-cpuid-Core-i7-2600-xsaveopt-host.xml create mode 100644 tests/cputestdata/x86_64-cpuid-Core-i7-2600-xsaveopt-json.xml create mode 100644 tests/cputestdata/x86_64-cpuid-Core-i7-2600-xsaveopt.json create mode 100644 tests/cputestdata/x86_64-cpuid-Core-i7-2600-xsaveopt.xml
Reviewed-by: John Ferlan <jferlan@redhat.com> John This reminds me - time for an eye doctor visit... Right after a few drinks of something hard ;-)
participants (2)
-
Jiri Denemark
-
John Ferlan