44
}
45
46
typedef struct CpuidTestArgs {
47
- const char *cmdline;
47
+ /* test name */
48
+ const char *name;
49
+ /* CPU type */
50
+ const char *cpu;
51
+ /* CPU features (may be NULL) */
52
+ const char *cpufeat;
53
+ /* machine type (may be NULL to use default machine) */
54
+ const char *machine;
55
+ /* CPU property to read */
56
const char *property;
57
+ /* expected value of the property */
58
int64_t expected_value;
59
} CpuidTestArgs;
60
61
static void test_cpuid_prop(const void *data)
62
{
63
const CpuidTestArgs *args = data;
64
+ char *cmdline;
65
+ char *save;
66
char *path;
67
QNum *value;
68
int64_t val;
69
59
- qtest_start(args->cmdline);
70
+ cmdline = g_strdup_printf("-cpu %s", args->cpu);
71
+
72
+ if (args->cpufeat) {
73
+ save = cmdline;
74
+ cmdline = g_strdup_printf("%s,%s", cmdline, args->cpufeat);
75
+ g_free(save);
76
+ }
77
+ if (args->machine) {
78
+ save = cmdline;
79
+ cmdline = g_strdup_printf("-machine %s %s", args->machine, cmdline);
80
+ g_free(save);
81
+ }
82
+
83
+ qtest_start(cmdline);
84
path = get_cpu0_qom_path();
85
value = qobject_to(QNum, qom_get(path, args->property));
86
g_assert(qnum_get_try_int(value, &val));
89
90
qobject_unref(value);
91
g_free(path);
68
- g_free((void *)args->cmdline);
69
- g_free((void *)data);
70
-}
71
-
72
-static void add_cpuid_test(const char *name, const char *cpu,
73
- const char *cpufeat, const char *machine,
74
- const char *property, int64_t expected_value)
75
-{
76
- CpuidTestArgs *args = g_new0(CpuidTestArgs, 1);
77
- char *cmdline;
78
- char *save;
79
-
80
- if (!qtest_has_cpu_model(cpu)) {
81
- return;
82
- }
83
- cmdline = g_strdup_printf("-cpu %s", cpu);
84
-
85
- if (cpufeat) {
86
- save = cmdline;
87
- cmdline = g_strdup_printf("%s,%s", cmdline, cpufeat);
88
- g_free(save);
89
- }
90
- if (machine) {
91
- save = cmdline;
92
- cmdline = g_strdup_printf("-machine %s %s", machine, cmdline);
93
- g_free(save);
94
- }
95
- args->cmdline = cmdline;
96
- args->property = property;
97
- args->expected_value = expected_value;
98
- qtest_add_data_func(name, args, test_cpuid_prop);
92
+ g_free(cmdline);
93
}
94
101
-
95
/* Parameters to a add_feature_test() test case */
96
typedef struct FeatureTestArgs {
97
/* cmdline to start QEMU */
242
g_test_trap_assert_stdout("");
243
}
244
252
-int main(int argc, char **argv)
253
-{
254
- g_test_init(&argc, &argv, NULL);
255
-
256
- g_test_add_func("/x86/cpuid/parsing-plus-minus/subprocess",
257
- test_plus_minus_subprocess);
258
- g_test_add_func("/x86/cpuid/parsing-plus-minus", test_plus_minus);
259
-
245
+static const CpuidTestArgs cpuid_tests[] = {
246
/* Original level values for CPU models: */
261
- add_cpuid_test("x86/cpuid/phenom/level",
262
- "phenom", NULL, NULL, "level", 5);
263
- add_cpuid_test("x86/cpuid/Conroe/level",
264
- "Conroe", NULL, NULL, "level", 10);
265
- add_cpuid_test("x86/cpuid/SandyBridge/level",
266
- "SandyBridge", NULL, NULL, "level", 0xd);
267
- add_cpuid_test("x86/cpuid/486/xlevel",
268
- "486", NULL, NULL, "xlevel", 0);
269
- add_cpuid_test("x86/cpuid/core2duo/xlevel",
270
- "core2duo", NULL, NULL, "xlevel", 0x80000008);
271
- add_cpuid_test("x86/cpuid/phenom/xlevel",
272
- "phenom", NULL, NULL, "xlevel", 0x8000001A);
273
- add_cpuid_test("x86/cpuid/athlon/xlevel",
274
- "athlon", NULL, NULL, "xlevel", 0x80000008);
275
-
247
+ {
248
+ "x86/cpuid/phenom/level",
249
+ "phenom", NULL, NULL, "level", 5,
250
+ },
251
+ {
252
+ "x86/cpuid/Conroe/level",
253
+ "Conroe", NULL, NULL, "level", 10,
254
+ },
255
+ {
256
+ "x86/cpuid/SandyBridge/level",
257
+ "SandyBridge", NULL, NULL, "level", 0xd,
258
+ },
259
+ {
260
+ "x86/cpuid/486/xlevel",
261
+ "486", NULL, NULL, "xlevel", 0,
262
+ },
263
+ {
264
+ "x86/cpuid/core2duo/xlevel",
265
+ "core2duo", NULL, NULL, "xlevel", 0x80000008,
266
+ },
267
+ {
268
+ "x86/cpuid/phenom/xlevel",
269
+ "phenom", NULL, NULL, "xlevel", 0x8000001A,
270
+ },
271
+ {
272
+ "x86/cpuid/athlon/xlevel",
273
+ "athlon", NULL, NULL, "xlevel", 0x80000008,
274
+ },
275
/* If level is not large enough, it should increase automatically: */
276
/* CPUID[6].EAX: */
278
- add_cpuid_test("x86/cpuid/auto-level/486/arat",
279
- "486", "arat=on", NULL, "level", 6);
277
+ {
278
+ "x86/cpuid/auto-level/486/arat",
279
+ "486", "arat=on", NULL, "level", 6,
280
+ },
281
/* CPUID[EAX=7,ECX=0].EBX: */
281
- add_cpuid_test("x86/cpuid/auto-level/phenom/fsgsbase",
282
- "phenom", "fsgsbase=on", NULL, "level", 7);
282
+ {
283
+ "x86/cpuid/auto-level/phenom/fsgsbase",
284
+ "phenom", "fsgsbase=on", NULL, "level", 7,
285
+ },
286
/* CPUID[EAX=7,ECX=0].ECX: */
284
- add_cpuid_test("x86/cpuid/auto-level/phenom/avx512vbmi",
285
- "phenom", "avx512vbmi=on", NULL, "level", 7);
287
+ {
288
+ "x86/cpuid/auto-level/phenom/avx512vbmi",
289
+ "phenom", "avx512vbmi=on", NULL, "level", 7,
290
+ },
291
/* CPUID[EAX=0xd,ECX=1].EAX: */
287
- add_cpuid_test("x86/cpuid/auto-level/phenom/xsaveopt",
288
- "phenom", "xsaveopt=on", NULL, "level", 0xd);
292
+ {
293
+ "x86/cpuid/auto-level/phenom/xsaveopt",
294
+ "phenom", "xsaveopt=on", NULL, "level", 0xd,
295
+ },
296
/* CPUID[8000_0001].EDX: */
290
- add_cpuid_test("x86/cpuid/auto-xlevel/486/3dnow",
291
- "486", "3dnow=on", NULL, "xlevel", 0x80000001);
297
+ {
298
+ "x86/cpuid/auto-xlevel/486/3dnow",
299
+ "486", "3dnow=on", NULL, "xlevel", 0x80000001,
300
+ },
301
/* CPUID[8000_0001].ECX: */
293
- add_cpuid_test("x86/cpuid/auto-xlevel/486/sse4a",
294
- "486", "sse4a=on", NULL, "xlevel", 0x80000001);
302
+ {
303
+ "x86/cpuid/auto-xlevel/486/sse4a",
304
+ "486", "sse4a=on", NULL, "xlevel", 0x80000001,
305
+ },
306
/* CPUID[8000_0007].EDX: */
296
- add_cpuid_test("x86/cpuid/auto-xlevel/486/invtsc",
297
- "486", "invtsc=on", NULL, "xlevel", 0x80000007);
307
+ {
308
+ "x86/cpuid/auto-xlevel/486/invtsc",
309
+ "486", "invtsc=on", NULL, "xlevel", 0x80000007,
310
+ },
311
/* CPUID[8000_000A].EDX: */
299
- add_cpuid_test("x86/cpuid/auto-xlevel/486/npt",
300
- "486", "svm=on,npt=on", NULL, "xlevel", 0x8000000A);
312
+ {
313
+ "x86/cpuid/auto-xlevel/486/npt",
314
+ "486", "svm=on,npt=on", NULL, "xlevel", 0x8000000A,
315
+ },
316
/* CPUID[C000_0001].EDX: */
302
- add_cpuid_test("x86/cpuid/auto-xlevel2/phenom/xstore",
303
- "phenom", "xstore=on", NULL, "xlevel2", 0xC0000001);
317
+ {
318
+ "x86/cpuid/auto-xlevel2/phenom/xstore",
319
+ "phenom", "xstore=on", NULL, "xlevel2", 0xC0000001,
320
+ },
321
/* SVM needs CPUID[0x8000000A] */
305
- add_cpuid_test("x86/cpuid/auto-xlevel/athlon/svm",
306
- "athlon", "svm=on", NULL, "xlevel", 0x8000000A);
307
-
308
-
322
+ {
323
+ "x86/cpuid/auto-xlevel/athlon/svm",
324
+ "athlon", "svm=on", NULL, "xlevel", 0x8000000A,
325
+ },
326
/* If level is already large enough, it shouldn't change: */
310
- add_cpuid_test("x86/cpuid/auto-level/SandyBridge/multiple",
311
- "SandyBridge", "arat=on,fsgsbase=on,avx512vbmi=on",
312
- NULL, "level", 0xd);
327
+ {
328
+ "x86/cpuid/auto-level/SandyBridge/multiple",
329
+ "SandyBridge", "arat=on,fsgsbase=on,avx512vbmi=on",
330
+ NULL, "level", 0xd,
331
+ },
332
/* If level is explicitly set, it shouldn't change: */
314
- add_cpuid_test("x86/cpuid/auto-level/486/fixed/0xF",
315
- "486",
316
- "level=0xF,arat=on,fsgsbase=on,avx512vbmi=on,xsaveopt=on",
317
- NULL, "level", 0xF);
318
- add_cpuid_test("x86/cpuid/auto-level/486/fixed/2",
319
- "486",
320
- "level=2,arat=on,fsgsbase=on,avx512vbmi=on,xsaveopt=on",
321
- NULL, "level", 2);
322
- add_cpuid_test("x86/cpuid/auto-level/486/fixed/0",
323
- "486",
324
- "level=0,arat=on,fsgsbase=on,avx512vbmi=on,xsaveopt=on",
325
- NULL, "level", 0);
326
-
333
+ {
334
+ "x86/cpuid/auto-level/486/fixed/0xF",
335
+ "486",
336
+ "level=0xF,arat=on,fsgsbase=on,avx512vbmi=on,xsaveopt=on",
337
+ NULL, "level", 0xF,
338
+ },
339
+ {
340
+ "x86/cpuid/auto-level/486/fixed/2",
341
+ "486",
342
+ "level=2,arat=on,fsgsbase=on,avx512vbmi=on,xsaveopt=on",
343
+ NULL, "level", 2,
344
+ },
345
+ {
346
+ "x86/cpuid/auto-level/486/fixed/0",
347
+ "486",
348
+ "level=0,arat=on,fsgsbase=on,avx512vbmi=on,xsaveopt=on",
349
+ NULL, "level", 0,
350
+ },
351
/* if xlevel is already large enough, it shouldn't change: */
328
- add_cpuid_test("x86/cpuid/auto-xlevel/phenom/3dnow",
329
- "phenom", "3dnow=on,sse4a=on,invtsc=on,npt=on,svm=on",
330
- NULL, "xlevel", 0x8000001A);
352
+ {
353
+ "x86/cpuid/auto-xlevel/phenom/3dnow",
354
+ "phenom", "3dnow=on,sse4a=on,invtsc=on,npt=on,svm=on",
355
+ NULL, "xlevel", 0x8000001A,
356
+ },
357
/* If xlevel is explicitly set, it shouldn't change: */
332
- add_cpuid_test("x86/cpuid/auto-xlevel/486/fixed/80000002",
333
- "486",
334
- "xlevel=0x80000002,3dnow=on,sse4a=on,invtsc=on,npt=on,svm=on",
335
- NULL, "xlevel", 0x80000002);
336
- add_cpuid_test("x86/cpuid/auto-xlevel/486/fixed/8000001A",
337
- "486",
338
- "xlevel=0x8000001A,3dnow=on,sse4a=on,invtsc=on,npt=on,svm=on",
339
- NULL, "xlevel", 0x8000001A);
340
- add_cpuid_test("x86/cpuid/auto-xlevel/phenom/fixed/0",
341
- "486",
342
- "xlevel=0,3dnow=on,sse4a=on,invtsc=on,npt=on,svm=on",
343
- NULL, "xlevel", 0);
344
-
358
+ {
359
+ "x86/cpuid/auto-xlevel/486/fixed/80000002",
360
+ "486",
361
+ "xlevel=0x80000002,3dnow=on,sse4a=on,invtsc=on,npt=on,svm=on",
362
+ NULL, "xlevel", 0x80000002,
363
+ },
364
+ {
365
+ "x86/cpuid/auto-xlevel/486/fixed/8000001A",
366
+ "486",
367
+ "xlevel=0x8000001A,3dnow=on,sse4a=on,invtsc=on,npt=on,svm=on",
368
+ NULL, "xlevel", 0x8000001A,
369
+ },
370
+ {
371
+ "x86/cpuid/auto-xlevel/phenom/fixed/0",
372
+ "486",
373
+ "xlevel=0,3dnow=on,sse4a=on,invtsc=on,npt=on,svm=on",
374
+ NULL, "xlevel", 0,
375
+ },
376
/* if xlevel2 is already large enough, it shouldn't change: */
346
- add_cpuid_test("x86/cpuid/auto-xlevel2/486/fixed",
347
- "486", "xlevel2=0xC0000002,xstore=on",
348
- NULL, "xlevel2", 0xC0000002);
377
+ {
378
+ "x86/cpuid/auto-xlevel2/486/fixed",
379
+ "486", "xlevel2=0xC0000002,xstore=on",
380
+ NULL, "xlevel2", 0xC0000002,
381
+ },
382
+};
383
+
384
+int main(int argc, char **argv)
385
+{
386
+ g_test_init(&argc, &argv, NULL);
387
+
388
+ g_test_add_func("/x86/cpuid/parsing-plus-minus/subprocess",
389
+ test_plus_minus_subprocess);
390
+ g_test_add_func("/x86/cpuid/parsing-plus-minus", test_plus_minus);
391
+
392
+ for (int i = 0; i < ARRAY_SIZE(cpuid_tests); i++) {
393
+ if (!qtest_has_cpu_model(cpuid_tests[i].cpu)) {
394
+ continue;
395
+ }
396
+ qtest_add_data_func(cpuid_tests[i].name,
397
+ &cpuid_tests[i], test_cpuid_prop);
398
+ }
399
400
/* Test feature parsing */
401
add_feature_test("x86/cpuid/features/plus",