xref: /qemu/tests/qtest/test-x86-cpuid-compat.c (revision 6efef58ed151f75bca29561bde6b8a65db43d4a2)
1*6efef58eSEduardo Habkost #include "qemu/osdep.h"
2*6efef58eSEduardo Habkost #include "qemu-common.h"
3*6efef58eSEduardo Habkost #include "qapi/qmp/qlist.h"
4*6efef58eSEduardo Habkost #include "qapi/qmp/qdict.h"
5*6efef58eSEduardo Habkost #include "qapi/qmp/qint.h"
6*6efef58eSEduardo Habkost #include "libqtest.h"
7*6efef58eSEduardo Habkost 
8*6efef58eSEduardo Habkost static char *get_cpu0_qom_path(void)
9*6efef58eSEduardo Habkost {
10*6efef58eSEduardo Habkost     QDict *resp;
11*6efef58eSEduardo Habkost     QList *ret;
12*6efef58eSEduardo Habkost     QDict *cpu0;
13*6efef58eSEduardo Habkost     char *path;
14*6efef58eSEduardo Habkost 
15*6efef58eSEduardo Habkost     resp = qmp("{'execute': 'query-cpus', 'arguments': {}}");
16*6efef58eSEduardo Habkost     g_assert(qdict_haskey(resp, "return"));
17*6efef58eSEduardo Habkost     ret = qdict_get_qlist(resp, "return");
18*6efef58eSEduardo Habkost 
19*6efef58eSEduardo Habkost     cpu0 = qobject_to_qdict(qlist_peek(ret));
20*6efef58eSEduardo Habkost     path = g_strdup(qdict_get_str(cpu0, "qom_path"));
21*6efef58eSEduardo Habkost     QDECREF(resp);
22*6efef58eSEduardo Habkost     return path;
23*6efef58eSEduardo Habkost }
24*6efef58eSEduardo Habkost 
25*6efef58eSEduardo Habkost static QObject *qom_get(const char *path, const char *prop)
26*6efef58eSEduardo Habkost {
27*6efef58eSEduardo Habkost     QDict *resp = qmp("{ 'execute': 'qom-get',"
28*6efef58eSEduardo Habkost                       "  'arguments': { 'path': %s,"
29*6efef58eSEduardo Habkost                       "                 'property': %s } }",
30*6efef58eSEduardo Habkost                       path, prop);
31*6efef58eSEduardo Habkost     QObject *ret = qdict_get(resp, "return");
32*6efef58eSEduardo Habkost     qobject_incref(ret);
33*6efef58eSEduardo Habkost     QDECREF(resp);
34*6efef58eSEduardo Habkost     return ret;
35*6efef58eSEduardo Habkost }
36*6efef58eSEduardo Habkost 
37*6efef58eSEduardo Habkost typedef struct CpuidTestArgs {
38*6efef58eSEduardo Habkost     const char *cmdline;
39*6efef58eSEduardo Habkost     const char *property;
40*6efef58eSEduardo Habkost     int64_t expected_value;
41*6efef58eSEduardo Habkost } CpuidTestArgs;
42*6efef58eSEduardo Habkost 
43*6efef58eSEduardo Habkost static void test_cpuid_prop(const void *data)
44*6efef58eSEduardo Habkost {
45*6efef58eSEduardo Habkost     const CpuidTestArgs *args = data;
46*6efef58eSEduardo Habkost     char *path;
47*6efef58eSEduardo Habkost     QInt *value;
48*6efef58eSEduardo Habkost 
49*6efef58eSEduardo Habkost     qtest_start(args->cmdline);
50*6efef58eSEduardo Habkost     path = get_cpu0_qom_path();
51*6efef58eSEduardo Habkost     value = qobject_to_qint(qom_get(path, args->property));
52*6efef58eSEduardo Habkost     g_assert_cmpint(qint_get_int(value), ==, args->expected_value);
53*6efef58eSEduardo Habkost     qtest_end();
54*6efef58eSEduardo Habkost 
55*6efef58eSEduardo Habkost     QDECREF(value);
56*6efef58eSEduardo Habkost     g_free(path);
57*6efef58eSEduardo Habkost }
58*6efef58eSEduardo Habkost 
59*6efef58eSEduardo Habkost static void add_cpuid_test(const char *name, const char *cmdline,
60*6efef58eSEduardo Habkost                            const char *property, int64_t expected_value)
61*6efef58eSEduardo Habkost {
62*6efef58eSEduardo Habkost     CpuidTestArgs *args = g_new0(CpuidTestArgs, 1);
63*6efef58eSEduardo Habkost     args->cmdline = cmdline;
64*6efef58eSEduardo Habkost     args->property = property;
65*6efef58eSEduardo Habkost     args->expected_value = expected_value;
66*6efef58eSEduardo Habkost     qtest_add_data_func(name, args, test_cpuid_prop);
67*6efef58eSEduardo Habkost }
68*6efef58eSEduardo Habkost 
69*6efef58eSEduardo Habkost int main(int argc, char **argv)
70*6efef58eSEduardo Habkost {
71*6efef58eSEduardo Habkost     g_test_init(&argc, &argv, NULL);
72*6efef58eSEduardo Habkost 
73*6efef58eSEduardo Habkost     /* Original level values for CPU models: */
74*6efef58eSEduardo Habkost     add_cpuid_test("x86/cpuid/phenom/level",
75*6efef58eSEduardo Habkost                    "-cpu phenom", "level", 5);
76*6efef58eSEduardo Habkost     add_cpuid_test("x86/cpuid/Conroe/level",
77*6efef58eSEduardo Habkost                    "-cpu Conroe", "level", 10);
78*6efef58eSEduardo Habkost     add_cpuid_test("x86/cpuid/SandyBridge/level",
79*6efef58eSEduardo Habkost                    "-cpu SandyBridge", "level", 0xd);
80*6efef58eSEduardo Habkost     add_cpuid_test("x86/cpuid/486/xlevel",
81*6efef58eSEduardo Habkost                    "-cpu 486", "xlevel", 0);
82*6efef58eSEduardo Habkost     add_cpuid_test("x86/cpuid/core2duo/xlevel",
83*6efef58eSEduardo Habkost                    "-cpu core2duo", "xlevel", 0x80000008);
84*6efef58eSEduardo Habkost     add_cpuid_test("x86/cpuid/phenom/xlevel",
85*6efef58eSEduardo Habkost                    "-cpu phenom", "xlevel", 0x8000001A);
86*6efef58eSEduardo Habkost 
87*6efef58eSEduardo Habkost     /* If level is not large enough, it should increase automatically: */
88*6efef58eSEduardo Habkost     /* CPUID[EAX=7,ECX=0].EBX: */
89*6efef58eSEduardo Habkost     add_cpuid_test("x86/cpuid/auto-level/phenom/fsgsbase",
90*6efef58eSEduardo Habkost                    "-cpu phenom,+fsgsbase", "level", 7);
91*6efef58eSEduardo Habkost 
92*6efef58eSEduardo Habkost     /* If level is already large enough, it shouldn't change: */
93*6efef58eSEduardo Habkost     add_cpuid_test("x86/cpuid/auto-level/SandyBridge/multiple",
94*6efef58eSEduardo Habkost                    "-cpu SandyBridge,+arat,+fsgsbase,+avx512vbmi",
95*6efef58eSEduardo Habkost                    "level", 0xd);
96*6efef58eSEduardo Habkost 
97*6efef58eSEduardo Habkost     /* if xlevel is already large enough, it shouldn't change: */
98*6efef58eSEduardo Habkost     add_cpuid_test("x86/cpuid/auto-xlevel/phenom/3dnow",
99*6efef58eSEduardo Habkost                    "-cpu phenom,+3dnow,+sse4a,+invtsc,+npt",
100*6efef58eSEduardo Habkost                    "xlevel", 0x8000001A);
101*6efef58eSEduardo Habkost 
102*6efef58eSEduardo Habkost     /* if xlevel2 is already large enough, it shouldn't change: */
103*6efef58eSEduardo Habkost     add_cpuid_test("x86/cpuid/auto-xlevel2/486/fixed",
104*6efef58eSEduardo Habkost                    "-cpu 486,xlevel2=0xC0000002,+xstore",
105*6efef58eSEduardo Habkost                    "xlevel2", 0xC0000002);
106*6efef58eSEduardo Habkost 
107*6efef58eSEduardo Habkost     return g_test_run();
108*6efef58eSEduardo Habkost }
109