]>
Commit | Line | Data |
---|---|---|
6efef58e EH |
1 | #include "qemu/osdep.h" |
2 | #include "qemu-common.h" | |
3 | #include "qapi/qmp/qlist.h" | |
4 | #include "qapi/qmp/qdict.h" | |
5 | #include "qapi/qmp/qint.h" | |
6 | #include "libqtest.h" | |
7 | ||
8 | static char *get_cpu0_qom_path(void) | |
9 | { | |
10 | QDict *resp; | |
11 | QList *ret; | |
12 | QDict *cpu0; | |
13 | char *path; | |
14 | ||
15 | resp = qmp("{'execute': 'query-cpus', 'arguments': {}}"); | |
16 | g_assert(qdict_haskey(resp, "return")); | |
17 | ret = qdict_get_qlist(resp, "return"); | |
18 | ||
19 | cpu0 = qobject_to_qdict(qlist_peek(ret)); | |
20 | path = g_strdup(qdict_get_str(cpu0, "qom_path")); | |
21 | QDECREF(resp); | |
22 | return path; | |
23 | } | |
24 | ||
25 | static QObject *qom_get(const char *path, const char *prop) | |
26 | { | |
27 | QDict *resp = qmp("{ 'execute': 'qom-get'," | |
28 | " 'arguments': { 'path': %s," | |
29 | " 'property': %s } }", | |
30 | path, prop); | |
31 | QObject *ret = qdict_get(resp, "return"); | |
32 | qobject_incref(ret); | |
33 | QDECREF(resp); | |
34 | return ret; | |
35 | } | |
36 | ||
37 | typedef struct CpuidTestArgs { | |
38 | const char *cmdline; | |
39 | const char *property; | |
40 | int64_t expected_value; | |
41 | } CpuidTestArgs; | |
42 | ||
43 | static void test_cpuid_prop(const void *data) | |
44 | { | |
45 | const CpuidTestArgs *args = data; | |
46 | char *path; | |
47 | QInt *value; | |
48 | ||
49 | qtest_start(args->cmdline); | |
50 | path = get_cpu0_qom_path(); | |
51 | value = qobject_to_qint(qom_get(path, args->property)); | |
52 | g_assert_cmpint(qint_get_int(value), ==, args->expected_value); | |
53 | qtest_end(); | |
54 | ||
55 | QDECREF(value); | |
56 | g_free(path); | |
57 | } | |
58 | ||
59 | static void add_cpuid_test(const char *name, const char *cmdline, | |
60 | const char *property, int64_t expected_value) | |
61 | { | |
62 | CpuidTestArgs *args = g_new0(CpuidTestArgs, 1); | |
63 | args->cmdline = cmdline; | |
64 | args->property = property; | |
65 | args->expected_value = expected_value; | |
66 | qtest_add_data_func(name, args, test_cpuid_prop); | |
67 | } | |
68 | ||
69 | int main(int argc, char **argv) | |
70 | { | |
71 | g_test_init(&argc, &argv, NULL); | |
72 | ||
73 | /* Original level values for CPU models: */ | |
74 | add_cpuid_test("x86/cpuid/phenom/level", | |
75 | "-cpu phenom", "level", 5); | |
76 | add_cpuid_test("x86/cpuid/Conroe/level", | |
77 | "-cpu Conroe", "level", 10); | |
78 | add_cpuid_test("x86/cpuid/SandyBridge/level", | |
79 | "-cpu SandyBridge", "level", 0xd); | |
80 | add_cpuid_test("x86/cpuid/486/xlevel", | |
81 | "-cpu 486", "xlevel", 0); | |
82 | add_cpuid_test("x86/cpuid/core2duo/xlevel", | |
83 | "-cpu core2duo", "xlevel", 0x80000008); | |
84 | add_cpuid_test("x86/cpuid/phenom/xlevel", | |
85 | "-cpu phenom", "xlevel", 0x8000001A); | |
86 | ||
87 | /* If level is not large enough, it should increase automatically: */ | |
c39c0edf EH |
88 | /* CPUID[6].EAX: */ |
89 | add_cpuid_test("x86/cpuid/auto-level/phenom/arat", | |
90 | "-cpu 486,+arat", "level", 6); | |
6efef58e EH |
91 | /* CPUID[EAX=7,ECX=0].EBX: */ |
92 | add_cpuid_test("x86/cpuid/auto-level/phenom/fsgsbase", | |
93 | "-cpu phenom,+fsgsbase", "level", 7); | |
c39c0edf EH |
94 | /* CPUID[EAX=7,ECX=0].ECX: */ |
95 | add_cpuid_test("x86/cpuid/auto-level/phenom/avx512vbmi", | |
96 | "-cpu phenom,+avx512vbmi", "level", 7); | |
97 | /* CPUID[EAX=0xd,ECX=1].EAX: */ | |
98 | add_cpuid_test("x86/cpuid/auto-level/phenom/xsaveopt", | |
99 | "-cpu phenom,+xsaveopt", "level", 0xd); | |
100 | /* CPUID[8000_0001].EDX: */ | |
101 | add_cpuid_test("x86/cpuid/auto-xlevel/486/3dnow", | |
102 | "-cpu 486,+3dnow", "xlevel", 0x80000001); | |
103 | /* CPUID[8000_0001].ECX: */ | |
104 | add_cpuid_test("x86/cpuid/auto-xlevel/486/sse4a", | |
105 | "-cpu 486,+sse4a", "xlevel", 0x80000001); | |
106 | /* CPUID[8000_0007].EDX: */ | |
107 | add_cpuid_test("x86/cpuid/auto-xlevel/486/invtsc", | |
108 | "-cpu 486,+invtsc", "xlevel", 0x80000007); | |
109 | /* CPUID[8000_000A].EDX: */ | |
110 | add_cpuid_test("x86/cpuid/auto-xlevel/486/npt", | |
111 | "-cpu 486,+npt", "xlevel", 0x8000000A); | |
112 | /* CPUID[C000_0001].EDX: */ | |
113 | add_cpuid_test("x86/cpuid/auto-xlevel2/phenom/xstore", | |
114 | "-cpu phenom,+xstore", "xlevel2", 0xC0000001); | |
115 | ||
6efef58e EH |
116 | |
117 | /* If level is already large enough, it shouldn't change: */ | |
118 | add_cpuid_test("x86/cpuid/auto-level/SandyBridge/multiple", | |
119 | "-cpu SandyBridge,+arat,+fsgsbase,+avx512vbmi", | |
120 | "level", 0xd); | |
c39c0edf EH |
121 | /* If level is explicitly set, it shouldn't change: */ |
122 | add_cpuid_test("x86/cpuid/auto-level/486/fixed/0xF", | |
123 | "-cpu 486,level=0xF,+arat,+fsgsbase,+avx512vbmi,+xsaveopt", | |
124 | "level", 0xF); | |
125 | add_cpuid_test("x86/cpuid/auto-level/486/fixed/2", | |
126 | "-cpu 486,level=2,+arat,+fsgsbase,+avx512vbmi,+xsaveopt", | |
127 | "level", 2); | |
128 | add_cpuid_test("x86/cpuid/auto-level/486/fixed/0", | |
129 | "-cpu 486,level=0,+arat,+fsgsbase,+avx512vbmi,+xsaveopt", | |
130 | "level", 0); | |
6efef58e EH |
131 | |
132 | /* if xlevel is already large enough, it shouldn't change: */ | |
133 | add_cpuid_test("x86/cpuid/auto-xlevel/phenom/3dnow", | |
134 | "-cpu phenom,+3dnow,+sse4a,+invtsc,+npt", | |
135 | "xlevel", 0x8000001A); | |
c39c0edf EH |
136 | /* If xlevel is explicitly set, it shouldn't change: */ |
137 | add_cpuid_test("x86/cpuid/auto-xlevel/486/fixed/80000002", | |
138 | "-cpu 486,xlevel=0x80000002,+3dnow,+sse4a,+invtsc,+npt", | |
139 | "xlevel", 0x80000002); | |
140 | add_cpuid_test("x86/cpuid/auto-xlevel/486/fixed/8000001A", | |
141 | "-cpu 486,xlevel=0x8000001A,+3dnow,+sse4a,+invtsc,+npt", | |
142 | "xlevel", 0x8000001A); | |
143 | add_cpuid_test("x86/cpuid/auto-xlevel/phenom/fixed/0", | |
144 | "-cpu 486,xlevel=0,+3dnow,+sse4a,+invtsc,+npt", | |
145 | "xlevel", 0); | |
6efef58e EH |
146 | |
147 | /* if xlevel2 is already large enough, it shouldn't change: */ | |
148 | add_cpuid_test("x86/cpuid/auto-xlevel2/486/fixed", | |
149 | "-cpu 486,xlevel2=0xC0000002,+xstore", | |
150 | "xlevel2", 0xC0000002); | |
151 | ||
df3e9af8 EH |
152 | /* Check compatibility of old machine-types that didn't |
153 | * auto-increase level/xlevel/xlevel2: */ | |
154 | ||
155 | add_cpuid_test("x86/cpuid/auto-level/pc-2.7", | |
156 | "-machine pc-i440fx-2.7 -cpu 486,+arat,+avx512vbmi,+xsaveopt", | |
157 | "level", 1); | |
158 | add_cpuid_test("x86/cpuid/auto-xlevel/pc-2.7", | |
159 | "-machine pc-i440fx-2.7 -cpu 486,+3dnow,+sse4a,+invtsc,+npt", | |
160 | "xlevel", 0); | |
161 | add_cpuid_test("x86/cpuid/auto-xlevel2/pc-2.7", | |
162 | "-machine pc-i440fx-2.7 -cpu 486,+xstore", | |
163 | "xlevel2", 0); | |
164 | ||
6efef58e EH |
165 | return g_test_run(); |
166 | } |