:p
atchew
Login
Add a new library api to check for the support of a specific cpu type. Used the new api to check support for some older x86 cpu models before running the tests. CC: thuth@redhat.com CC: imammedo@redhat.com CC: qemu-devel@nongnu.org CC: pbonzini@redhat.com CC: lvivier@redhat.com Ani Sinha (3): qtest/x86/numa-test: do not use the obsolete 'pentium' cpu tests/qtest/libqtest: add qtest_has_cpu() api tests/qtest/x86: check for availability of older cpu models before running tests tests/qtest/libqtest.c | 84 +++++++++++ tests/qtest/libqtest.h | 8 ++ tests/qtest/numa-test.c | 3 +- tests/qtest/test-x86-cpuid-compat.c | 214 +++++++++++++++++----------- 4 files changed, 221 insertions(+), 88 deletions(-) -- 2.42.0
'pentium' cpu is old and obsolete and should be avoided for running tests if its not strictly needed. Use 'max' cpu instead for generic non-cpu specific numa test. CC: thuth@redhat.com Reviewed-by: Thomas Huth <thuth@redhat.com> Signed-off-by: Ani Sinha <anisinha@redhat.com> --- tests/qtest/numa-test.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) changelog: review tag added. No other changes. diff --git a/tests/qtest/numa-test.c b/tests/qtest/numa-test.c index XXXXXXX..XXXXXXX 100644 --- a/tests/qtest/numa-test.c +++ b/tests/qtest/numa-test.c @@ -XXX,XX +XXX,XX @@ static void pc_numa_cpu(const void *data) QTestState *qts; g_autofree char *cli = NULL; - cli = make_cli(data, "-cpu pentium -machine smp.cpus=8,smp.sockets=2,smp.cores=2,smp.threads=2 " + cli = make_cli(data, + "-cpu max -machine smp.cpus=8,smp.sockets=2,smp.cores=2,smp.threads=2 " "-numa node,nodeid=0,memdev=ram -numa node,nodeid=1 " "-numa cpu,node-id=1,socket-id=0 " "-numa cpu,node-id=0,socket-id=1,core-id=0 " -- 2.42.0
Added a new test api qtest_has_cpu() in order to check availability of some cpu models in the current QEMU binary. The specific architecture of the QEMU binary is selected using the QTEST_QEMU_BINARY environment variable. This api would be useful to run tests against some older cpu models after checking if QEMU actually supported these models. CC: thuth@redhat.com Signed-off-by: Ani Sinha <anisinha@redhat.com> --- tests/qtest/libqtest.c | 84 ++++++++++++++++++++++++++++++++++++++++++ tests/qtest/libqtest.h | 8 ++++ 2 files changed, 92 insertions(+) diff --git a/tests/qtest/libqtest.c b/tests/qtest/libqtest.c index XXXXXXX..XXXXXXX 100644 --- a/tests/qtest/libqtest.c +++ b/tests/qtest/libqtest.c @@ -XXX,XX +XXX,XX @@ #include "qapi/qmp/qjson.h" #include "qapi/qmp/qlist.h" #include "qapi/qmp/qstring.h" +#include "qapi/qmp/qbool.h" #define MAX_IRQ 256 @@ -XXX,XX +XXX,XX @@ struct MachInfo { char *alias; }; +struct CpuInfo { + char *name; + char *alias_of; + bool deprecated; +}; + static void qtest_free_machine_list(struct MachInfo *machines) { if (machines) { @@ -XXX,XX +XXX,XX @@ static struct MachInfo *qtest_get_machines(const char *var) return machines; } +static struct CpuInfo *qtest_get_cpus(void) +{ + static struct CpuInfo *cpus; + QDict *response, *minfo; + QList *list; + const QListEntry *p; + QObject *qobj; + QString *qstr; + QBool *qbool; + QTestState *qts; + int idx; + + if (cpus) { + return cpus; + } + + silence_spawn_log = !g_test_verbose(); + + qts = qtest_init_with_env(NULL, "-machine none"); + response = qtest_qmp(qts, "{ 'execute': 'query-cpu-definitions' }"); + g_assert(response); + list = qdict_get_qlist(response, "return"); + g_assert(list); + + cpus = g_new(struct CpuInfo, qlist_size(list) + 1); + + for (p = qlist_first(list), idx = 0; p; p = qlist_next(p), idx++) { + minfo = qobject_to(QDict, qlist_entry_obj(p)); + g_assert(minfo); + + qobj = qdict_get(minfo, "name"); + g_assert(qobj); + qstr = qobject_to(QString, qobj); + g_assert(qstr); + cpus[idx].name = g_strdup(qstring_get_str(qstr)); + + qobj = qdict_get(minfo, "alias_of"); + if (qobj) { /* old machines do not report aliases */ + qstr = qobject_to(QString, qobj); + g_assert(qstr); + cpus[idx].alias_of = g_strdup(qstring_get_str(qstr)); + } else { + cpus[idx].alias_of = NULL; + } + + qobj = qdict_get(minfo, "deprecated"); + qbool = qobject_to(QBool, qobj); + g_assert(qbool); + cpus[idx].deprecated = qbool_get_bool(qbool); + } + + qtest_quit(qts); + qobject_unref(response); + + silence_spawn_log = false; + + memset(&cpus[idx], 0, sizeof(struct CpuInfo)); /* Terminating entry */ + return cpus; +} + +bool qtest_has_cpu(const char *cpu) +{ + struct CpuInfo *cpus; + int i; + + cpus = qtest_get_cpus(); + + for (i = 0; cpus[i].name != NULL; i++) { + if (g_str_equal(cpu, cpus[i].name) || + (cpus[i].alias_of && g_str_equal(cpu, cpus[i].alias_of))) { + return true; + } + } + + return false; +} + void qtest_cb_for_every_machine(void (*cb)(const char *machine), bool skip_old_versioned) { diff --git a/tests/qtest/libqtest.h b/tests/qtest/libqtest.h index XXXXXXX..XXXXXXX 100644 --- a/tests/qtest/libqtest.h +++ b/tests/qtest/libqtest.h @@ -XXX,XX +XXX,XX @@ bool qtest_has_machine(const char *machine); */ bool qtest_has_machine_with_env(const char *var, const char *machine); +/** + * qtest_has_cpu: + * @cpu: The cpu to look for + * + * Returns: true if the cpu is available in the target binary. + */ +bool qtest_has_cpu(const char *cpu); + /** * qtest_has_device: * @device: The device to look for -- 2.42.0
Some older cpu models like 486, athlon, pentium, penryn, phenom, core2duo etc may not be available in all builds. Check for their availability in qemu before running the corresponding tests. The order of the tests has been altered so that all tests for similar checks under a specific cpu is placed together. One minor correction. Replaced 'phenom' with '486' in the test 'x86/cpuid/auto-level/phenom/arat' matching the cpu used. CC: thuth@redhat.com CC: imammedo@redhat.com Signed-off-by: Ani Sinha <anisinha@redhat.com> --- tests/qtest/test-x86-cpuid-compat.c | 214 +++++++++++++++++----------- 1 file changed, 127 insertions(+), 87 deletions(-) diff --git a/tests/qtest/test-x86-cpuid-compat.c b/tests/qtest/test-x86-cpuid-compat.c index XXXXXXX..XXXXXXX 100644 --- a/tests/qtest/test-x86-cpuid-compat.c +++ b/tests/qtest/test-x86-cpuid-compat.c @@ -XXX,XX +XXX,XX @@ static void test_plus_minus(void) int main(int argc, char **argv) { + bool has_486, has_athlon, has_conroe; + bool has_core2duo, has_penryn, has_pentium, has_phenom; + g_test_init(&argc, &argv, NULL); - g_test_add_func("/x86/cpuid/parsing-plus-minus/subprocess", - test_plus_minus_subprocess); - g_test_add_func("/x86/cpuid/parsing-plus-minus", test_plus_minus); + has_486 = qtest_has_cpu("486"); + has_athlon = qtest_has_cpu("athlon"); + has_conroe = qtest_has_cpu("Conroe"); + has_core2duo = qtest_has_cpu("core2duo"); + has_penryn = qtest_has_cpu("Penryn"); + has_pentium = qtest_has_cpu("pentium"); + has_phenom = qtest_has_cpu("phenom"); + + if (has_pentium) { + g_test_add_func("/x86/cpuid/parsing-plus-minus/subprocess", + test_plus_minus_subprocess); + g_test_add_func("/x86/cpuid/parsing-plus-minus", test_plus_minus); + } /* Original level values for CPU models: */ - add_cpuid_test("x86/cpuid/phenom/level", - "-cpu phenom", "level", 5); - add_cpuid_test("x86/cpuid/Conroe/level", - "-cpu Conroe", "level", 10); + if (has_486) { + add_cpuid_test("x86/cpuid/486/xlevel", + "-cpu 486", "xlevel", 0); + } + if (has_phenom) { + add_cpuid_test("x86/cpuid/phenom/level", + "-cpu phenom", "level", 5); + add_cpuid_test("x86/cpuid/phenom/xlevel", + "-cpu phenom", "xlevel", 0x8000001A); + } + if (has_athlon) { + add_cpuid_test("x86/cpuid/athlon/xlevel", + "-cpu athlon", "xlevel", 0x80000008); + } + if (has_core2duo) { + add_cpuid_test("x86/cpuid/core2duo/xlevel", + "-cpu core2duo", "xlevel", 0x80000008); + } + if (has_conroe) { + add_cpuid_test("x86/cpuid/Conroe/level", + "-cpu Conroe", "level", 10); + } add_cpuid_test("x86/cpuid/SandyBridge/level", "-cpu SandyBridge", "level", 0xd); - add_cpuid_test("x86/cpuid/486/xlevel", - "-cpu 486", "xlevel", 0); - add_cpuid_test("x86/cpuid/core2duo/xlevel", - "-cpu core2duo", "xlevel", 0x80000008); - add_cpuid_test("x86/cpuid/phenom/xlevel", - "-cpu phenom", "xlevel", 0x8000001A); - add_cpuid_test("x86/cpuid/athlon/xlevel", - "-cpu athlon", "xlevel", 0x80000008); /* If level is not large enough, it should increase automatically: */ - /* CPUID[6].EAX: */ - add_cpuid_test("x86/cpuid/auto-level/phenom/arat", - "-cpu 486,arat=on", "level", 6); - /* CPUID[EAX=7,ECX=0].EBX: */ - add_cpuid_test("x86/cpuid/auto-level/phenom/fsgsbase", - "-cpu phenom,fsgsbase=on", "level", 7); - /* CPUID[EAX=7,ECX=0].ECX: */ - add_cpuid_test("x86/cpuid/auto-level/phenom/avx512vbmi", - "-cpu phenom,avx512vbmi=on", "level", 7); - /* CPUID[EAX=0xd,ECX=1].EAX: */ - add_cpuid_test("x86/cpuid/auto-level/phenom/xsaveopt", - "-cpu phenom,xsaveopt=on", "level", 0xd); - /* CPUID[8000_0001].EDX: */ - add_cpuid_test("x86/cpuid/auto-xlevel/486/3dnow", - "-cpu 486,3dnow=on", "xlevel", 0x80000001); - /* CPUID[8000_0001].ECX: */ - add_cpuid_test("x86/cpuid/auto-xlevel/486/sse4a", - "-cpu 486,sse4a=on", "xlevel", 0x80000001); - /* CPUID[8000_0007].EDX: */ - add_cpuid_test("x86/cpuid/auto-xlevel/486/invtsc", - "-cpu 486,invtsc=on", "xlevel", 0x80000007); - /* CPUID[8000_000A].EDX: */ - add_cpuid_test("x86/cpuid/auto-xlevel/486/npt", - "-cpu 486,svm=on,npt=on", "xlevel", 0x8000000A); - /* CPUID[C000_0001].EDX: */ - add_cpuid_test("x86/cpuid/auto-xlevel2/phenom/xstore", - "-cpu phenom,xstore=on", "xlevel2", 0xC0000001); - /* SVM needs CPUID[0x8000000A] */ - add_cpuid_test("x86/cpuid/auto-xlevel/athlon/svm", - "-cpu athlon,svm=on", "xlevel", 0x8000000A); - + if (has_486) { + /* CPUID[6].EAX: */ + add_cpuid_test("x86/cpuid/auto-level/486/arat", + "-cpu 486,arat=on", "level", 6); + /* CPUID[8000_0001].EDX: */ + add_cpuid_test("x86/cpuid/auto-xlevel/486/3dnow", + "-cpu 486,3dnow=on", "xlevel", 0x80000001); + /* CPUID[8000_0001].ECX: */ + add_cpuid_test("x86/cpuid/auto-xlevel/486/sse4a", + "-cpu 486,sse4a=on", "xlevel", 0x80000001); + /* CPUID[8000_0007].EDX: */ + add_cpuid_test("x86/cpuid/auto-xlevel/486/invtsc", + "-cpu 486,invtsc=on", "xlevel", 0x80000007); + /* CPUID[8000_000A].EDX: */ + add_cpuid_test("x86/cpuid/auto-xlevel/486/npt", + "-cpu 486,svm=on,npt=on", "xlevel", 0x8000000A); + } + if (has_phenom) { + /* CPUID[EAX=7,ECX=0].EBX: */ + add_cpuid_test("x86/cpuid/auto-level/phenom/fsgsbase", + "-cpu phenom,fsgsbase=on", "level", 7); + /* CPUID[EAX=7,ECX=0].ECX: */ + add_cpuid_test("x86/cpuid/auto-level/phenom/avx512vbmi", + "-cpu phenom,avx512vbmi=on", "level", 7); + /* CPUID[EAX=0xd,ECX=1].EAX: */ + add_cpuid_test("x86/cpuid/auto-level/phenom/xsaveopt", + "-cpu phenom,xsaveopt=on", "level", 0xd); + /* CPUID[C000_0001].EDX: */ + add_cpuid_test("x86/cpuid/auto-xlevel2/phenom/xstore", + "-cpu phenom,xstore=on", "xlevel2", 0xC0000001); + } + if (has_athlon) { + /* SVM needs CPUID[0x8000000A] */ + add_cpuid_test("x86/cpuid/auto-xlevel/athlon/svm", + "-cpu athlon,svm=on", "xlevel", 0x8000000A); + } /* If level is already large enough, it shouldn't change: */ add_cpuid_test("x86/cpuid/auto-level/SandyBridge/multiple", "-cpu SandyBridge,arat=on,fsgsbase=on,avx512vbmi=on", "level", 0xd); /* If level is explicitly set, it shouldn't change: */ - add_cpuid_test("x86/cpuid/auto-level/486/fixed/0xF", - "-cpu 486,level=0xF,arat=on,fsgsbase=on,avx512vbmi=on,xsaveopt=on", - "level", 0xF); - add_cpuid_test("x86/cpuid/auto-level/486/fixed/2", - "-cpu 486,level=2,arat=on,fsgsbase=on,avx512vbmi=on,xsaveopt=on", - "level", 2); - add_cpuid_test("x86/cpuid/auto-level/486/fixed/0", - "-cpu 486,level=0,arat=on,fsgsbase=on,avx512vbmi=on,xsaveopt=on", - "level", 0); + if (has_486) { + add_cpuid_test("x86/cpuid/auto-level/486/fixed/0xF", + "-cpu 486,level=0xF,arat=on,fsgsbase=on,avx512vbmi=on,xsaveopt=on", + "level", 0xF); + add_cpuid_test("x86/cpuid/auto-level/486/fixed/2", + "-cpu 486,level=2,arat=on,fsgsbase=on,avx512vbmi=on,xsaveopt=on", + "level", 2); + add_cpuid_test("x86/cpuid/auto-level/486/fixed/0", + "-cpu 486,level=0,arat=on,fsgsbase=on,avx512vbmi=on,xsaveopt=on", + "level", 0); + } /* if xlevel is already large enough, it shouldn't change: */ - add_cpuid_test("x86/cpuid/auto-xlevel/phenom/3dnow", - "-cpu phenom,3dnow=on,sse4a=on,invtsc=on,npt=on,svm=on", - "xlevel", 0x8000001A); + if (has_phenom) { + add_cpuid_test("x86/cpuid/auto-xlevel/phenom/3dnow", + "-cpu phenom,3dnow=on,sse4a=on,invtsc=on,npt=on,svm=on", + "xlevel", 0x8000001A); + } + /* If xlevel is explicitly set, it shouldn't change: */ - add_cpuid_test("x86/cpuid/auto-xlevel/486/fixed/80000002", - "-cpu 486,xlevel=0x80000002,3dnow=on,sse4a=on,invtsc=on,npt=on,svm=on", - "xlevel", 0x80000002); - add_cpuid_test("x86/cpuid/auto-xlevel/486/fixed/8000001A", - "-cpu 486,xlevel=0x8000001A,3dnow=on,sse4a=on,invtsc=on,npt=on,svm=on", - "xlevel", 0x8000001A); - add_cpuid_test("x86/cpuid/auto-xlevel/phenom/fixed/0", - "-cpu 486,xlevel=0,3dnow=on,sse4a=on,invtsc=on,npt=on,svm=on", - "xlevel", 0); - - /* if xlevel2 is already large enough, it shouldn't change: */ - add_cpuid_test("x86/cpuid/auto-xlevel2/486/fixed", - "-cpu 486,xlevel2=0xC0000002,xstore=on", - "xlevel2", 0xC0000002); + if (has_486) { + add_cpuid_test("x86/cpuid/auto-xlevel/486/fixed/80000002", + "-cpu 486,xlevel=0x80000002,3dnow=on,sse4a=on,invtsc=on,npt=on,svm=on", + "xlevel", 0x80000002); + add_cpuid_test("x86/cpuid/auto-xlevel/486/fixed/8000001A", + "-cpu 486,xlevel=0x8000001A,3dnow=on,sse4a=on,invtsc=on,npt=on,svm=on", + "xlevel", 0x8000001A); + add_cpuid_test("x86/cpuid/auto-xlevel/phenom/fixed/0", + "-cpu 486,xlevel=0,3dnow=on,sse4a=on,invtsc=on,npt=on,svm=on", + "xlevel", 0); + + /* if xlevel2 is already large enough, it shouldn't change: */ + add_cpuid_test("x86/cpuid/auto-xlevel2/486/fixed", + "-cpu 486,xlevel2=0xC0000002,xstore=on", + "xlevel2", 0xC0000002); + } + /* Check compatibility of old machine-types that didn't * auto-increase level/xlevel/xlevel2: */ - if (qtest_has_machine("pc-i440fx-2.7")) { + if (qtest_has_machine("pc-i440fx-2.7") && has_486) { add_cpuid_test("x86/cpuid/auto-level/pc-2.7", "-machine pc-i440fx-2.7 -cpu 486,arat=on,avx512vbmi=on,xsaveopt=on", "level", 1); @@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv) * and the compat code that sets default level shouldn't * disable the auto-level=7 code: */ - if (qtest_has_machine("pc-i440fx-2.3")) { + if (qtest_has_machine("pc-i440fx-2.3") && has_penryn) { add_cpuid_test("x86/cpuid/auto-level7/pc-i440fx-2.3/off", "-machine pc-i440fx-2.3 -cpu Penryn", "level", 4); @@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv) "-machine pc-i440fx-2.3 -cpu Penryn,erms=on", "level", 7); } - if (qtest_has_machine("pc-i440fx-2.9")) { + if (qtest_has_machine("pc-i440fx-2.9") && has_conroe) { add_cpuid_test("x86/cpuid/auto-level7/pc-i440fx-2.9/off", "-machine pc-i440fx-2.9 -cpu Conroe", "level", 10); @@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv) } /* Test feature parsing */ - add_feature_test("x86/cpuid/features/plus", - "-cpu 486,+arat", - 6, 0, "EAX", 2, true); - add_feature_test("x86/cpuid/features/minus", - "-cpu pentium,-mmx", - 1, 0, "EDX", 23, false); - add_feature_test("x86/cpuid/features/on", - "-cpu 486,arat=on", - 6, 0, "EAX", 2, true); - add_feature_test("x86/cpuid/features/off", - "-cpu pentium,mmx=off", - 1, 0, "EDX", 23, false); + if (has_486) { + add_feature_test("x86/cpuid/features/plus", + "-cpu 486,+arat", + 6, 0, "EAX", 2, true); + add_feature_test("x86/cpuid/features/on", + "-cpu 486,arat=on", + 6, 0, "EAX", 2, true); + } + if (has_pentium) { + add_feature_test("x86/cpuid/features/minus", + "-cpu pentium,-mmx", + 1, 0, "EDX", 23, false); + add_feature_test("x86/cpuid/features/off", + "-cpu pentium,mmx=off", + 1, 0, "EDX", 23, false); + } add_feature_test("x86/cpuid/features/max-plus-invtsc", "-cpu max,+invtsc", 0x80000007, 0, "EDX", 8, true); -- 2.42.0
Add a new library api to check for the support of a specific cpu type. Used the new api to check support for some older x86 cpu models before running the tests. CC: thuth@redhat.com CC: imammedo@redhat.com CC: qemu-devel@nongnu.org CC: pbonzini@redhat.com CC: lvivier@redhat.com CC: mst@redhat.com Ani Sinha (3): qtest/x86/numa-test: do not use the obsolete 'pentium' cpu tests/qtest/libqtest: add qtest_has_cpu_model() api tests/qtest/x86: check for availability of older cpu models before running tests tests/qtest/libqtest.c | 83 ++++++++++++++ tests/qtest/libqtest.h | 8 ++ tests/qtest/numa-test.c | 3 +- tests/qtest/test-x86-cpuid-compat.c | 170 ++++++++++++++++++---------- 4 files changed, 201 insertions(+), 63 deletions(-) -- 2.42.0
'pentium' cpu is old and obsolete and should be avoided for running tests if its not strictly needed. Use 'max' cpu instead for generic non-cpu specific numa test. CC: thuth@redhat.com Reviewed-by: Thomas Huth <thuth@redhat.com> Reviewed-by: Igor Mammedov <imammedo@redhat.com> Signed-off-by: Ani Sinha <anisinha@redhat.com> --- tests/qtest/numa-test.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/qtest/numa-test.c b/tests/qtest/numa-test.c index XXXXXXX..XXXXXXX 100644 --- a/tests/qtest/numa-test.c +++ b/tests/qtest/numa-test.c @@ -XXX,XX +XXX,XX @@ static void pc_numa_cpu(const void *data) QTestState *qts; g_autofree char *cli = NULL; - cli = make_cli(data, "-cpu pentium -machine smp.cpus=8,smp.sockets=2,smp.cores=2,smp.threads=2 " + cli = make_cli(data, + "-cpu max -machine smp.cpus=8,smp.sockets=2,smp.cores=2,smp.threads=2 " "-numa node,nodeid=0,memdev=ram -numa node,nodeid=1 " "-numa cpu,node-id=1,socket-id=0 " "-numa cpu,node-id=0,socket-id=1,core-id=0 " -- 2.42.0
Added a new test api qtest_has_cpu_model() in order to check availability of some cpu models in the current QEMU binary. The specific architecture of the QEMU binary is selected using the QTEST_QEMU_BINARY environment variable. This api would be useful to run tests against some older cpu models after checking if QEMU actually supported these models. CC: thuth@redhat.com Signed-off-by: Ani Sinha <anisinha@redhat.com> Reviewed-by: Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> --- tests/qtest/libqtest.c | 83 ++++++++++++++++++++++++++++++++++++++++++ tests/qtest/libqtest.h | 8 ++++ 2 files changed, 91 insertions(+) changelog: v2: changes related to suggestions made by danpb. added tags. v3: phil's suggestion to rename function and structure names. diff --git a/tests/qtest/libqtest.c b/tests/qtest/libqtest.c index XXXXXXX..XXXXXXX 100644 --- a/tests/qtest/libqtest.c +++ b/tests/qtest/libqtest.c @@ -XXX,XX +XXX,XX @@ #include "qapi/qmp/qjson.h" #include "qapi/qmp/qlist.h" #include "qapi/qmp/qstring.h" +#include "qapi/qmp/qbool.h" #define MAX_IRQ 256 @@ -XXX,XX +XXX,XX @@ struct MachInfo { char *alias; }; +struct CpuModel { + char *name; + char *alias_of; + bool deprecated; +}; + static void qtest_free_machine_list(struct MachInfo *machines) { if (machines) { @@ -XXX,XX +XXX,XX @@ static struct MachInfo *qtest_get_machines(const char *var) return machines; } +static struct CpuModel *qtest_get_cpu_models(void) +{ + static struct CpuModel *cpus; + QDict *response, *minfo; + QList *list; + const QListEntry *p; + QObject *qobj; + QString *qstr; + QBool *qbool; + QTestState *qts; + int idx; + + if (cpus) { + return cpus; + } + + silence_spawn_log = !g_test_verbose(); + + qts = qtest_init_with_env(NULL, "-machine none"); + response = qtest_qmp(qts, "{ 'execute': 'query-cpu-definitions' }"); + g_assert(response); + list = qdict_get_qlist(response, "return"); + g_assert(list); + + cpus = g_new0(struct CpuModel, qlist_size(list) + 1); + + for (p = qlist_first(list), idx = 0; p; p = qlist_next(p), idx++) { + minfo = qobject_to(QDict, qlist_entry_obj(p)); + g_assert(minfo); + + qobj = qdict_get(minfo, "name"); + g_assert(qobj); + qstr = qobject_to(QString, qobj); + g_assert(qstr); + cpus[idx].name = g_strdup(qstring_get_str(qstr)); + + qobj = qdict_get(minfo, "alias_of"); + if (qobj) { /* old machines do not report aliases */ + qstr = qobject_to(QString, qobj); + g_assert(qstr); + cpus[idx].alias_of = g_strdup(qstring_get_str(qstr)); + } else { + cpus[idx].alias_of = NULL; + } + + qobj = qdict_get(minfo, "deprecated"); + qbool = qobject_to(QBool, qobj); + g_assert(qbool); + cpus[idx].deprecated = qbool_get_bool(qbool); + } + + qtest_quit(qts); + qobject_unref(response); + + silence_spawn_log = false; + + return cpus; +} + +bool qtest_has_cpu_model(const char *cpu) +{ + struct CpuModel *cpus; + int i; + + cpus = qtest_get_cpu_models(); + + for (i = 0; cpus[i].name != NULL; i++) { + if (g_str_equal(cpu, cpus[i].name) || + (cpus[i].alias_of && g_str_equal(cpu, cpus[i].alias_of))) { + return true; + } + } + + return false; +} + void qtest_cb_for_every_machine(void (*cb)(const char *machine), bool skip_old_versioned) { diff --git a/tests/qtest/libqtest.h b/tests/qtest/libqtest.h index XXXXXXX..XXXXXXX 100644 --- a/tests/qtest/libqtest.h +++ b/tests/qtest/libqtest.h @@ -XXX,XX +XXX,XX @@ bool qtest_has_machine(const char *machine); */ bool qtest_has_machine_with_env(const char *var, const char *machine); +/** + * qtest_has_cpu_model: + * @cpu: The cpu to look for + * + * Returns: true if the cpu is available in the target binary. + */ +bool qtest_has_cpu_model(const char *cpu); + /** * qtest_has_device: * @device: The device to look for -- 2.42.0
It is better to check if some older cpu models like 486, athlon, pentium, penryn, phenom, core2duo etc are available before running their corresponding tests. Some downstream distributions may no longer support these older cpu models. Signature of add_feature_test() has been modified to return void as FeatureTestArgs* was not used by the caller. One minor correction. Replaced 'phenom' with '486' in the test 'x86/cpuid/auto-level/phenom/arat' matching the cpu used. CC: thuth@redhat.com CC: imammedo@redhat.com Signed-off-by: Ani Sinha <anisinha@redhat.com> Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> --- tests/qtest/test-x86-cpuid-compat.c | 170 ++++++++++++++++++---------- 1 file changed, 108 insertions(+), 62 deletions(-) changelog: v2: reworked as per suggestion from danpb. v3: reworked as_feature_test() same way as add_cpuid_test() v4: phil's suggestion. tags added. diff --git a/tests/qtest/test-x86-cpuid-compat.c b/tests/qtest/test-x86-cpuid-compat.c index XXXXXXX..XXXXXXX 100644 --- a/tests/qtest/test-x86-cpuid-compat.c +++ b/tests/qtest/test-x86-cpuid-compat.c @@ -XXX,XX +XXX,XX @@ static void test_cpuid_prop(const void *data) g_free(path); } -static void add_cpuid_test(const char *name, const char *cmdline, +static void add_cpuid_test(const char *name, const char *cpu, + const char *cpufeat, const char *machine, const char *property, int64_t expected_value) { CpuidTestArgs *args = g_new0(CpuidTestArgs, 1); + char *cmdline; + char *save; + + if (!qtest_has_cpu_model(cpu)) { + return; + } + cmdline = g_strdup_printf("-cpu %s", cpu); + + if (cpufeat) { + save = cmdline; + cmdline = g_strdup_printf("%s,%s", cmdline, cpufeat); + g_free(save); + } + if (machine) { + save = cmdline; + cmdline = g_strdup_printf("-machine %s %s", machine, cmdline); + g_free(save); + } args->cmdline = cmdline; args->property = property; args->expected_value = expected_value; @@ -XXX,XX +XXX,XX @@ static void test_feature_flag(const void *data) * either "feature-words" or "filtered-features", when running QEMU * using cmdline */ -static FeatureTestArgs *add_feature_test(const char *name, const char *cmdline, - uint32_t eax, uint32_t ecx, - const char *reg, int bitnr, - bool expected_value) +static void add_feature_test(const char *name, const char *cpu, + const char *cpufeat, uint32_t eax, + uint32_t ecx, const char *reg, + int bitnr, bool expected_value) { FeatureTestArgs *args = g_new0(FeatureTestArgs, 1); + char *cmdline; + + if (!qtest_has_cpu_model(cpu)) { + return; + } + + if (cpufeat) { + cmdline = g_strdup_printf("-cpu %s,%s", cpu, cpufeat); + } else { + cmdline = g_strdup_printf("-cpu %s", cpu); + } + args->cmdline = cmdline; args->in_eax = eax; args->in_ecx = ecx; @@ -XXX,XX +XXX,XX @@ static FeatureTestArgs *add_feature_test(const char *name, const char *cmdline, args->bitnr = bitnr; args->expected_value = expected_value; qtest_add_data_func(name, args, test_feature_flag); - return args; + return; } static void test_plus_minus_subprocess(void) { char *path; + if (!qtest_has_cpu_model("pentium")) { + return; + } + /* Rules: * 1)"-foo" overrides "+foo" * 2) "[+-]foo" overrides "foo=..." @@ -XXX,XX +XXX,XX @@ static void test_plus_minus_subprocess(void) static void test_plus_minus(void) { + if (!qtest_has_cpu_model("pentium")) { + return; + } + g_test_trap_subprocess("/x86/cpuid/parsing-plus-minus/subprocess", 0, 0); g_test_trap_assert_passed(); g_test_trap_assert_stderr("*Ambiguous CPU model string. " @@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv) /* Original level values for CPU models: */ add_cpuid_test("x86/cpuid/phenom/level", - "-cpu phenom", "level", 5); + "phenom", NULL, NULL, "level", 5); add_cpuid_test("x86/cpuid/Conroe/level", - "-cpu Conroe", "level", 10); + "Conroe", NULL, NULL, "level", 10); add_cpuid_test("x86/cpuid/SandyBridge/level", - "-cpu SandyBridge", "level", 0xd); + "SandyBridge", NULL, NULL, "level", 0xd); add_cpuid_test("x86/cpuid/486/xlevel", - "-cpu 486", "xlevel", 0); + "486", NULL, NULL, "xlevel", 0); add_cpuid_test("x86/cpuid/core2duo/xlevel", - "-cpu core2duo", "xlevel", 0x80000008); + "core2duo", NULL, NULL, "xlevel", 0x80000008); add_cpuid_test("x86/cpuid/phenom/xlevel", - "-cpu phenom", "xlevel", 0x8000001A); + "phenom", NULL, NULL, "xlevel", 0x8000001A); add_cpuid_test("x86/cpuid/athlon/xlevel", - "-cpu athlon", "xlevel", 0x80000008); + "athlon", NULL, NULL, "xlevel", 0x80000008); /* If level is not large enough, it should increase automatically: */ /* CPUID[6].EAX: */ - add_cpuid_test("x86/cpuid/auto-level/phenom/arat", - "-cpu 486,arat=on", "level", 6); + add_cpuid_test("x86/cpuid/auto-level/486/arat", + "486", "arat=on", NULL, "level", 6); /* CPUID[EAX=7,ECX=0].EBX: */ add_cpuid_test("x86/cpuid/auto-level/phenom/fsgsbase", - "-cpu phenom,fsgsbase=on", "level", 7); + "phenom", "fsgsbase=on", NULL, "level", 7); /* CPUID[EAX=7,ECX=0].ECX: */ add_cpuid_test("x86/cpuid/auto-level/phenom/avx512vbmi", - "-cpu phenom,avx512vbmi=on", "level", 7); + "phenom", "avx512vbmi=on", NULL, "level", 7); /* CPUID[EAX=0xd,ECX=1].EAX: */ add_cpuid_test("x86/cpuid/auto-level/phenom/xsaveopt", - "-cpu phenom,xsaveopt=on", "level", 0xd); + "phenom", "xsaveopt=on", NULL, "level", 0xd); /* CPUID[8000_0001].EDX: */ add_cpuid_test("x86/cpuid/auto-xlevel/486/3dnow", - "-cpu 486,3dnow=on", "xlevel", 0x80000001); + "486", "3dnow=on", NULL, "xlevel", 0x80000001); /* CPUID[8000_0001].ECX: */ add_cpuid_test("x86/cpuid/auto-xlevel/486/sse4a", - "-cpu 486,sse4a=on", "xlevel", 0x80000001); + "486", "sse4a=on", NULL, "xlevel", 0x80000001); /* CPUID[8000_0007].EDX: */ add_cpuid_test("x86/cpuid/auto-xlevel/486/invtsc", - "-cpu 486,invtsc=on", "xlevel", 0x80000007); + "486", "invtsc=on", NULL, "xlevel", 0x80000007); /* CPUID[8000_000A].EDX: */ add_cpuid_test("x86/cpuid/auto-xlevel/486/npt", - "-cpu 486,svm=on,npt=on", "xlevel", 0x8000000A); + "486", "svm=on,npt=on", NULL, "xlevel", 0x8000000A); /* CPUID[C000_0001].EDX: */ add_cpuid_test("x86/cpuid/auto-xlevel2/phenom/xstore", - "-cpu phenom,xstore=on", "xlevel2", 0xC0000001); + "phenom", "xstore=on", NULL, "xlevel2", 0xC0000001); /* SVM needs CPUID[0x8000000A] */ add_cpuid_test("x86/cpuid/auto-xlevel/athlon/svm", - "-cpu athlon,svm=on", "xlevel", 0x8000000A); + "athlon", "svm=on", NULL, "xlevel", 0x8000000A); /* If level is already large enough, it shouldn't change: */ add_cpuid_test("x86/cpuid/auto-level/SandyBridge/multiple", - "-cpu SandyBridge,arat=on,fsgsbase=on,avx512vbmi=on", - "level", 0xd); + "SandyBridge", "arat=on,fsgsbase=on,avx512vbmi=on", + NULL, "level", 0xd); /* If level is explicitly set, it shouldn't change: */ add_cpuid_test("x86/cpuid/auto-level/486/fixed/0xF", - "-cpu 486,level=0xF,arat=on,fsgsbase=on,avx512vbmi=on,xsaveopt=on", - "level", 0xF); + "486", + "level=0xF,arat=on,fsgsbase=on,avx512vbmi=on,xsaveopt=on", + NULL, "level", 0xF); add_cpuid_test("x86/cpuid/auto-level/486/fixed/2", - "-cpu 486,level=2,arat=on,fsgsbase=on,avx512vbmi=on,xsaveopt=on", - "level", 2); + "486", + "level=2,arat=on,fsgsbase=on,avx512vbmi=on,xsaveopt=on", + NULL, "level", 2); add_cpuid_test("x86/cpuid/auto-level/486/fixed/0", - "-cpu 486,level=0,arat=on,fsgsbase=on,avx512vbmi=on,xsaveopt=on", - "level", 0); + "486", + "level=0,arat=on,fsgsbase=on,avx512vbmi=on,xsaveopt=on", + NULL, "level", 0); /* if xlevel is already large enough, it shouldn't change: */ add_cpuid_test("x86/cpuid/auto-xlevel/phenom/3dnow", - "-cpu phenom,3dnow=on,sse4a=on,invtsc=on,npt=on,svm=on", - "xlevel", 0x8000001A); + "phenom", "3dnow=on,sse4a=on,invtsc=on,npt=on,svm=on", + NULL, "xlevel", 0x8000001A); /* If xlevel is explicitly set, it shouldn't change: */ add_cpuid_test("x86/cpuid/auto-xlevel/486/fixed/80000002", - "-cpu 486,xlevel=0x80000002,3dnow=on,sse4a=on,invtsc=on,npt=on,svm=on", - "xlevel", 0x80000002); + "486", + "xlevel=0x80000002,3dnow=on,sse4a=on,invtsc=on,npt=on,svm=on", + NULL, "xlevel", 0x80000002); add_cpuid_test("x86/cpuid/auto-xlevel/486/fixed/8000001A", - "-cpu 486,xlevel=0x8000001A,3dnow=on,sse4a=on,invtsc=on,npt=on,svm=on", - "xlevel", 0x8000001A); + "486", + "xlevel=0x8000001A,3dnow=on,sse4a=on,invtsc=on,npt=on,svm=on", + NULL, "xlevel", 0x8000001A); add_cpuid_test("x86/cpuid/auto-xlevel/phenom/fixed/0", - "-cpu 486,xlevel=0,3dnow=on,sse4a=on,invtsc=on,npt=on,svm=on", - "xlevel", 0); + "486", + "xlevel=0,3dnow=on,sse4a=on,invtsc=on,npt=on,svm=on", + NULL, "xlevel", 0); /* if xlevel2 is already large enough, it shouldn't change: */ add_cpuid_test("x86/cpuid/auto-xlevel2/486/fixed", - "-cpu 486,xlevel2=0xC0000002,xstore=on", - "xlevel2", 0xC0000002); + "486", "xlevel2=0xC0000002,xstore=on", + NULL, "xlevel2", 0xC0000002); /* Check compatibility of old machine-types that didn't * auto-increase level/xlevel/xlevel2: */ if (qtest_has_machine("pc-i440fx-2.7")) { add_cpuid_test("x86/cpuid/auto-level/pc-2.7", - "-machine pc-i440fx-2.7 -cpu 486,arat=on,avx512vbmi=on,xsaveopt=on", - "level", 1); + "486", "arat=on,avx512vbmi=on,xsaveopt=on", + "pc-i440fx-2.7", "level", 1); add_cpuid_test("x86/cpuid/auto-xlevel/pc-2.7", - "-machine pc-i440fx-2.7 -cpu 486,3dnow=on,sse4a=on,invtsc=on,npt=on,svm=on", - "xlevel", 0); + "486", "3dnow=on,sse4a=on,invtsc=on,npt=on,svm=on", + "pc-i440fx-2.7", "xlevel", 0); add_cpuid_test("x86/cpuid/auto-xlevel2/pc-2.7", - "-machine pc-i440fx-2.7 -cpu 486,xstore=on", + "486", "xstore=on", "pc-i440fx-2.7", "xlevel2", 0); } /* @@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv) */ if (qtest_has_machine("pc-i440fx-2.3")) { add_cpuid_test("x86/cpuid/auto-level7/pc-i440fx-2.3/off", - "-machine pc-i440fx-2.3 -cpu Penryn", + "Penryn", NULL, "pc-i440fx-2.3", "level", 4); add_cpuid_test("x86/cpuid/auto-level7/pc-i440fx-2.3/on", - "-machine pc-i440fx-2.3 -cpu Penryn,erms=on", + "Penryn", "erms=on", "pc-i440fx-2.3", "level", 7); } if (qtest_has_machine("pc-i440fx-2.9")) { add_cpuid_test("x86/cpuid/auto-level7/pc-i440fx-2.9/off", - "-machine pc-i440fx-2.9 -cpu Conroe", + "Conroe", NULL, "pc-i440fx-2.9", "level", 10); add_cpuid_test("x86/cpuid/auto-level7/pc-i440fx-2.9/on", - "-machine pc-i440fx-2.9 -cpu Conroe,erms=on", + "Conroe", "erms=on", "pc-i440fx-2.9", "level", 10); } @@ -XXX,XX +XXX,XX @@ int main(int argc, char **argv) */ if (qtest_has_machine("pc-i440fx-2.3")) { add_cpuid_test("x86/cpuid/xlevel-compat/pc-i440fx-2.3", - "-machine pc-i440fx-2.3 -cpu SandyBridge", + "SandyBridge", NULL, "pc-i440fx-2.3", "xlevel", 0x8000000a); } if (qtest_has_machine("pc-i440fx-2.4")) { add_cpuid_test("x86/cpuid/xlevel-compat/pc-i440fx-2.4/npt-off", - "-machine pc-i440fx-2.4 -cpu SandyBridge,", + "SandyBridge", NULL, "pc-i440fx-2.4", "xlevel", 0x80000008); add_cpuid_test("x86/cpuid/xlevel-compat/pc-i440fx-2.4/npt-on", - "-machine pc-i440fx-2.4 -cpu SandyBridge,svm=on,npt=on", + "SandyBridge", "svm=on,npt=on", "pc-i440fx-2.4", "xlevel", 0x80000008); } /* Test feature parsing */ add_feature_test("x86/cpuid/features/plus", - "-cpu 486,+arat", + "486", "+arat", 6, 0, "EAX", 2, true); add_feature_test("x86/cpuid/features/minus", - "-cpu pentium,-mmx", + "pentium", "-mmx", 1, 0, "EDX", 23, false); add_feature_test("x86/cpuid/features/on", - "-cpu 486,arat=on", + "486", "arat=on", 6, 0, "EAX", 2, true); add_feature_test("x86/cpuid/features/off", - "-cpu pentium,mmx=off", + "pentium", "mmx=off", 1, 0, "EDX", 23, false); + add_feature_test("x86/cpuid/features/max-plus-invtsc", - "-cpu max,+invtsc", + "max" , "+invtsc", 0x80000007, 0, "EDX", 8, true); add_feature_test("x86/cpuid/features/max-invtsc-on", - "-cpu max,invtsc=on", + "max", "invtsc=on", 0x80000007, 0, "EDX", 8, true); add_feature_test("x86/cpuid/features/max-minus-mmx", - "-cpu max,-mmx", + "max", "-mmx", 1, 0, "EDX", 23, false); add_feature_test("x86/cpuid/features/max-invtsc-on,mmx=off", - "-cpu max,mmx=off", + "max", "mmx=off", 1, 0, "EDX", 23, false); return g_test_run(); -- 2.42.0