1 /*
2  * cputest.c: Test the libvirtd internal CPU APIs
3  *
4  * Copyright (C) 2010-2014 Red Hat, Inc.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library.  If not, see
18  * <http://www.gnu.org/licenses/>.
19  */
20 
21 #include <config.h>
22 
23 #include <unistd.h>
24 
25 #include <sys/types.h>
26 #include <fcntl.h>
27 
28 #include "internal.h"
29 #include "virxml.h"
30 #include "viralloc.h"
31 #include "virbuffer.h"
32 #include "testutils.h"
33 #include "cpu_conf.h"
34 #include "cpu/cpu.h"
35 #include "cpu/cpu_x86.h"
36 #include "cpu/cpu_map.h"
37 #include "virstring.h"
38 
39 #if WITH_QEMU
40 # include "testutilsqemu.h"
41 # include "qemumonitortestutils.h"
42 # define LIBVIRT_QEMU_CAPSPRIV_H_ALLOW
43 # include "qemu/qemu_capspriv.h"
44 #endif
45 
46 #define VIR_FROM_THIS VIR_FROM_CPU
47 
48 enum cpuTestBoolWithError {
49     FAIL    = -1,
50     NO      = 0,
51     YES     = 1
52 };
53 
54 
55 struct data {
56     virArch arch;
57     const char *host;
58     const char *name;
59     virDomainCapsCPUModels *models;
60     const char *modelsName;
61     unsigned int flags;
62     int result;
63 };
64 
65 #if WITH_QEMU
66 static virQEMUDriver driver;
67 #endif
68 
69 
70 static virCPUDef *
cpuTestLoadXML(virArch arch,const char * name)71 cpuTestLoadXML(virArch arch, const char *name)
72 {
73     g_autofree char *xml = NULL;
74     g_autoptr(xmlDoc) doc = NULL;
75     g_autoptr(xmlXPathContext) ctxt = NULL;
76     virCPUDef *cpu = NULL;
77 
78     xml = g_strdup_printf("%s/cputestdata/%s-%s.xml", abs_srcdir,
79                           virArchToString(arch), name);
80 
81     if (!(doc = virXMLParseFileCtxt(xml, &ctxt)))
82         return NULL;
83 
84     virCPUDefParseXML(ctxt, NULL, VIR_CPU_TYPE_AUTO, &cpu, false);
85 
86     return cpu;
87 }
88 
89 
90 static virCPUDef **
cpuTestLoadMultiXML(virArch arch,const char * name,unsigned int * count)91 cpuTestLoadMultiXML(virArch arch,
92                     const char *name,
93                     unsigned int *count)
94 {
95     g_autofree char *xml = NULL;
96     g_autoptr(xmlDoc) doc = NULL;
97     g_autoptr(xmlXPathContext) ctxt = NULL;
98     g_autofree xmlNodePtr *nodes = NULL;
99     virCPUDef **cpus = NULL;
100     int n;
101     size_t i;
102 
103     xml = g_strdup_printf("%s/cputestdata/%s-%s.xml", abs_srcdir,
104                           virArchToString(arch), name);
105 
106     if (!(doc = virXMLParseFileCtxt(xml, &ctxt)))
107         return NULL;
108 
109     n = virXPathNodeSet("/cpuTest/cpu", ctxt, &nodes);
110     if (n <= 0) {
111         fprintf(stderr, "\nNo /cpuTest/cpu elements found in %s\n", xml);
112         return NULL;
113     }
114 
115     cpus = g_new0(virCPUDef *, n);
116 
117     for (i = 0; i < n; i++) {
118         ctxt->node = nodes[i];
119         if (virCPUDefParseXML(ctxt, NULL, VIR_CPU_TYPE_HOST, &cpus[i],
120                               false) < 0)
121             goto error;
122     }
123 
124     *count = n;
125 
126     return cpus;
127 
128  error:
129     for (i = 0; i < n; i++)
130         virCPUDefFree(cpus[i]);
131     VIR_FREE(cpus);
132     return NULL;
133 }
134 
135 
136 static int
cpuTestCompareXML(virArch arch,virCPUDef * cpu,const char * name)137 cpuTestCompareXML(virArch arch,
138                   virCPUDef *cpu,
139                   const char *name)
140 {
141     g_autofree char *xml = NULL;
142     g_autofree char *actual = NULL;
143 
144     xml = g_strdup_printf("%s/cputestdata/%s-%s.xml", abs_srcdir,
145                           virArchToString(arch), name);
146 
147     if (!(actual = virCPUDefFormat(cpu, NULL)))
148         return -1;
149 
150     if (virTestCompareToFile(actual, xml) < 0)
151         return -1;
152 
153     return 0;
154 }
155 
156 
157 static const char *
cpuTestCompResStr(virCPUCompareResult result)158 cpuTestCompResStr(virCPUCompareResult result)
159 {
160     switch (result) {
161     case VIR_CPU_COMPARE_ERROR:         return "ERROR";
162     case VIR_CPU_COMPARE_INCOMPATIBLE:  return "INCOMPATIBLE";
163     case VIR_CPU_COMPARE_IDENTICAL:     return "IDENTICAL";
164     case VIR_CPU_COMPARE_SUPERSET:      return "SUPERSET";
165     case VIR_CPU_COMPARE_LAST:          break;
166     }
167 
168     return "unknown";
169 }
170 
171 
172 static const char *
cpuTestBoolWithErrorStr(enum cpuTestBoolWithError result)173 cpuTestBoolWithErrorStr(enum cpuTestBoolWithError result)
174 {
175     switch (result) {
176     case FAIL:  return "FAIL";
177     case NO:    return "NO";
178     case YES:   return "YES";
179     }
180 
181     return "unknown";
182 }
183 
184 
185 static int
cpuTestCompare(const void * arg)186 cpuTestCompare(const void *arg)
187 {
188     const struct data *data = arg;
189     g_autoptr(virCPUDef) host = NULL;
190     g_autoptr(virCPUDef) cpu = NULL;
191     virCPUCompareResult result;
192 
193     if (!(host = cpuTestLoadXML(data->arch, data->host)) ||
194         !(cpu = cpuTestLoadXML(data->arch, data->name)))
195         return -1;
196 
197     result = virCPUCompare(host->arch, host, cpu, false);
198     if (data->result == VIR_CPU_COMPARE_ERROR)
199         virResetLastError();
200 
201     if (data->result != result) {
202         VIR_TEST_VERBOSE("\nExpected result %s, got %s",
203                     cpuTestCompResStr(data->result),
204                     cpuTestCompResStr(result));
205         /* Pad to line up with test name ... in virTestRun */
206         VIR_TEST_VERBOSE("%74s", "... ");
207         return -1;
208     }
209 
210     return 0;
211 }
212 
213 
214 static int
cpuTestGuestCPU(const void * arg)215 cpuTestGuestCPU(const void *arg)
216 {
217     const struct data *data = arg;
218     int ret = -2;
219     g_autoptr(virCPUDef) host = NULL;
220     g_autoptr(virCPUDef) cpu = NULL;
221     virCPUCompareResult cmpResult;
222     g_auto(virBuffer) buf = VIR_BUFFER_INITIALIZER;
223     g_autofree char *result = NULL;
224 
225     if (!(host = cpuTestLoadXML(data->arch, data->host)) ||
226         !(cpu = cpuTestLoadXML(data->arch, data->name)))
227         goto cleanup;
228 
229     if (virCPUConvertLegacy(host->arch, cpu) < 0)
230         goto cleanup;
231 
232     cmpResult = virCPUCompare(host->arch, host, cpu, false);
233     if (cmpResult == VIR_CPU_COMPARE_ERROR ||
234         cmpResult == VIR_CPU_COMPARE_INCOMPATIBLE) {
235         ret = -1;
236         goto cleanup;
237     }
238 
239     if (virCPUUpdate(host->arch, cpu, host) < 0 ||
240         virCPUTranslate(host->arch, cpu, data->models) < 0) {
241         ret = -1;
242         goto cleanup;
243     }
244 
245     virBufferAsprintf(&buf, "%s+%s", data->host, data->name);
246     if (data->modelsName)
247         virBufferAsprintf(&buf, ",%s", data->modelsName);
248     virBufferAddLit(&buf, "-result");
249 
250     result = virBufferContentAndReset(&buf);
251 
252     if (cpuTestCompareXML(data->arch, cpu, result) < 0)
253         goto cleanup;
254 
255     ret = 0;
256 
257  cleanup:
258     if (ret == data->result) {
259         /* We got the result we expected, whether it was
260          * a success or a failure */
261         virResetLastError();
262         ret = 0;
263     } else {
264         VIR_TEST_VERBOSE("\nExpected result %d, got %d",
265                          data->result, ret);
266         /* Pad to line up with test name ... in virTestRun */
267         VIR_TEST_VERBOSE("%74s", "... ");
268         ret = -1;
269     }
270 
271     return ret;
272 }
273 
274 
275 static int
cpuTestBaseline(const void * arg)276 cpuTestBaseline(const void *arg)
277 {
278     const struct data *data = arg;
279     int ret = -1;
280     virCPUDef **cpus = NULL;
281     virCPUDef *baseline = NULL;
282     unsigned int ncpus = 0;
283     g_autofree char *result = NULL;
284     const char *suffix;
285     size_t i;
286 
287     if (!(cpus = cpuTestLoadMultiXML(data->arch, data->name, &ncpus)))
288         goto cleanup;
289 
290     baseline = virCPUBaseline(data->arch, cpus, ncpus, NULL, NULL,
291                               !!(data->flags & VIR_CONNECT_BASELINE_CPU_MIGRATABLE));
292 
293     if (baseline &&
294         (data->flags & VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES) &&
295         virCPUExpandFeatures(data->arch, baseline) < 0) {
296         virCPUDefFree(baseline);
297         baseline = NULL;
298     }
299 
300     if (data->result < 0) {
301         virResetLastError();
302         if (!baseline) {
303             ret = 0;
304         } else {
305             VIR_TEST_VERBOSE("\n%-70s... ",
306                     "virCPUBaseline was expected to fail but it succeeded");
307         }
308         goto cleanup;
309     }
310     if (!baseline)
311         goto cleanup;
312 
313     if (data->flags & VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES)
314         suffix = "expanded";
315     else if (data->flags & VIR_CONNECT_BASELINE_CPU_MIGRATABLE)
316         suffix = "migratable";
317     else
318         suffix = "result";
319     result = g_strdup_printf("%s-%s", data->name, suffix);
320 
321     if (cpuTestCompareXML(data->arch, baseline, result) < 0)
322         goto cleanup;
323 
324     for (i = 0; i < ncpus; i++) {
325         virCPUCompareResult cmp;
326 
327         cmp = virCPUCompare(cpus[i]->arch, cpus[i], baseline, false);
328         if (cmp != VIR_CPU_COMPARE_SUPERSET &&
329             cmp != VIR_CPU_COMPARE_IDENTICAL) {
330             VIR_TEST_VERBOSE("\nbaseline CPU is incompatible with CPU %zu",
331                              i);
332             VIR_TEST_VERBOSE("%74s", "... ");
333             ret = -1;
334             goto cleanup;
335         }
336     }
337 
338     ret = 0;
339 
340  cleanup:
341     if (cpus) {
342         for (i = 0; i < ncpus; i++)
343             virCPUDefFree(cpus[i]);
344         VIR_FREE(cpus);
345     }
346     virCPUDefFree(baseline);
347     return ret;
348 }
349 
350 
351 static int
cpuTestUpdate(const void * arg)352 cpuTestUpdate(const void *arg)
353 {
354     const struct data *data = arg;
355     g_autoptr(virCPUDef) host = NULL;
356     g_autoptr(virCPUDef) migHost = NULL;
357     g_autoptr(virCPUDef) cpu = NULL;
358     g_autofree char *result = NULL;
359 
360     if (!(host = cpuTestLoadXML(data->arch, data->host)) ||
361         !(cpu = cpuTestLoadXML(data->arch, data->name)))
362         return -1;
363 
364     if (!(migHost = virCPUCopyMigratable(data->arch, host)))
365         return -1;
366 
367     if (virCPUUpdate(host->arch, cpu, migHost) < 0)
368         return -1;
369 
370     result = g_strdup_printf("%s+%s", data->host, data->name);
371 
372     return cpuTestCompareXML(data->arch, cpu, result);
373 }
374 
375 
376 static int
cpuTestHasFeature(const void * arg)377 cpuTestHasFeature(const void *arg)
378 {
379     const struct data *data = arg;
380     g_autoptr(virCPUDef) host = NULL;
381     g_autoptr(virCPUData) hostData = NULL;
382     int result;
383 
384     if (!(host = cpuTestLoadXML(data->arch, data->host)))
385         return -1;
386 
387     if (cpuEncode(host->arch, host, NULL, &hostData,
388                   NULL, NULL, NULL, NULL) < 0)
389         return -1;
390 
391     result = virCPUCheckFeature(host->arch, host, data->name);
392 
393     if (data->result == result)
394         result = virCPUDataCheckFeature(hostData, data->name);
395 
396     if (data->result == -1)
397         virResetLastError();
398 
399     if (data->result != result) {
400         VIR_TEST_VERBOSE("\nExpected result %s, got %s",
401             cpuTestBoolWithErrorStr(data->result),
402             cpuTestBoolWithErrorStr(result));
403         /* Pad to line up with test name ... in virTestRun */
404         VIR_TEST_VERBOSE("%74s", "... ");
405         return -1;
406     }
407 
408     return 0;
409 }
410 
411 
412 typedef enum {
413     /* No JSON data from QEMU. */
414     JSON_NONE,
415     /* Only a reply from query-cpu-model-expansion QMP command. */
416     JSON_HOST,
417     /* Replies from both query-cpu-model-expansion and query-cpu-definitions
418      * QMP commands.
419      */
420     JSON_MODELS,
421     /* Same as JSON_MODELS, but the reply from query-cpu-definitions has to
422      * be parsed for providing the correct result. This happens when the
423      * CPU model detected by libvirt has non-empty unavailable-features array
424      * in query-cpu-definitions reply or when the CPU model detected from CPUID
425      * differs from the one we get from QEMU and we need to translate them for
426      * comparison. Such tests require QEMU driver to be enabled.
427      */
428     JSON_MODELS_REQUIRED,
429 } cpuTestCPUIDJson;
430 
431 #if WITH_QEMU
432 static virQEMUCaps *
cpuTestMakeQEMUCaps(const struct data * data)433 cpuTestMakeQEMUCaps(const struct data *data)
434 {
435     g_autoptr(virQEMUCaps) qemuCaps = NULL;
436     g_autoptr(qemuMonitorTest) testMon = NULL;
437     g_autoptr(qemuMonitorCPUModelInfo) model = NULL;
438     g_autoptr(virCPUDef) cpu = NULL;
439     bool fail_no_props = true;
440     g_autofree char *json = NULL;
441 
442     json = g_strdup_printf("%s/cputestdata/%s-cpuid-%s.json", abs_srcdir,
443                            virArchToString(data->arch), data->host);
444 
445     if (!(testMon = qemuMonitorTestNewFromFile(json, driver.xmlopt, true)))
446         return NULL;
447 
448     qemuMonitorTestAllowUnusedCommands(testMon);
449 
450     cpu = virCPUDefNew();
451 
452     cpu->model = g_strdup("host");
453 
454     if (ARCH_IS_S390(data->arch))
455         fail_no_props = false;
456 
457     if (qemuMonitorGetCPUModelExpansion(qemuMonitorTestGetMonitor(testMon),
458                                         QEMU_MONITOR_CPU_MODEL_EXPANSION_STATIC,
459                                         cpu, true, fail_no_props, &model) < 0)
460         return NULL;
461 
462     if (!(qemuCaps = virQEMUCapsNew()))
463         return NULL;
464 
465     virQEMUCapsSet(qemuCaps, QEMU_CAPS_KVM);
466     if (data->flags == JSON_MODELS ||
467         data->flags == JSON_MODELS_REQUIRED)
468         virQEMUCapsSet(qemuCaps, QEMU_CAPS_QUERY_CPU_DEFINITIONS);
469 
470     virQEMUCapsSetArch(qemuCaps, data->arch);
471     virQEMUCapsSetCPUModelInfo(qemuCaps, VIR_DOMAIN_VIRT_KVM, model);
472     model = NULL;
473 
474     if (virQEMUCapsProbeCPUDefinitionsTest(qemuCaps,
475                                            qemuMonitorTestGetMonitor(testMon)) < 0)
476         return NULL;
477 
478     return g_steal_pointer(&qemuCaps);
479 }
480 
481 
482 static int
cpuTestGetCPUModels(const struct data * data,virDomainCapsCPUModels ** models)483 cpuTestGetCPUModels(const struct data *data,
484                     virDomainCapsCPUModels **models)
485 {
486     g_autoptr(virQEMUCaps) qemuCaps = NULL;
487 
488     *models = NULL;
489 
490     if (data->flags != JSON_MODELS &&
491         data->flags != JSON_MODELS_REQUIRED)
492         return 0;
493 
494     if (!(qemuCaps = cpuTestMakeQEMUCaps(data)))
495         return -1;
496 
497     *models = virQEMUCapsGetCPUModels(qemuCaps, VIR_DOMAIN_VIRT_KVM, NULL, NULL);
498 
499     return 0;
500 }
501 
502 #else /* if WITH_QEMU */
503 
504 static int
cpuTestGetCPUModels(const struct data * data,virDomainCapsCPUModels ** models)505 cpuTestGetCPUModels(const struct data *data,
506                     virDomainCapsCPUModels **models)
507 {
508     *models = NULL;
509 
510     if (data->flags == JSON_MODELS_REQUIRED)
511         return EXIT_AM_SKIP;
512 
513     return 0;
514 }
515 
516 #endif
517 
518 
519 static int
cpuTestCPUID(bool guest,const void * arg)520 cpuTestCPUID(bool guest, const void *arg)
521 {
522     const struct data *data = arg;
523     g_autoptr(virCPUData) hostData = NULL;
524     g_autofree char *hostFile = NULL;
525     g_autofree char *host = NULL;
526     g_autoptr(virCPUDef) cpu = NULL;
527     g_autofree char *result = NULL;
528     g_autoptr(virDomainCapsCPUModels) models = NULL;
529 
530     hostFile = g_strdup_printf("%s/cputestdata/%s-cpuid-%s.xml", abs_srcdir,
531                                virArchToString(data->arch), data->host);
532 
533     if (virTestLoadFile(hostFile, &host) < 0 ||
534         !(hostData = virCPUDataParse(host)))
535         return -1;
536 
537     cpu = virCPUDefNew();
538     cpu->arch = hostData->arch;
539     if (guest) {
540         cpu->type = VIR_CPU_TYPE_GUEST;
541         cpu->match = VIR_CPU_MATCH_EXACT;
542         cpu->fallback = VIR_CPU_FALLBACK_FORBID;
543     } else {
544         cpu->type = VIR_CPU_TYPE_HOST;
545     }
546 
547     if (guest) {
548         int rc;
549 
550         rc = cpuTestGetCPUModels(data, &models);
551         if (rc != 0)
552             return rc;
553     }
554 
555     if (cpuDecode(cpu, hostData, models) < 0)
556         return -1;
557 
558     result = g_strdup_printf("cpuid-%s-%s", data->host, guest ? "guest" : "host");
559 
560     return cpuTestCompareXML(data->arch, cpu, result);
561 }
562 
563 
564 static int
cpuTestHostCPUID(const void * arg)565 cpuTestHostCPUID(const void *arg)
566 {
567     return cpuTestCPUID(false, arg);
568 }
569 
570 
571 static int
cpuTestGuestCPUID(const void * arg)572 cpuTestGuestCPUID(const void *arg)
573 {
574     return cpuTestCPUID(true, arg);
575 }
576 
577 
578 static int
cpuTestCompareSignature(const struct data * data,virCPUData * hostData)579 cpuTestCompareSignature(const struct data *data,
580                         virCPUData *hostData)
581 {
582     g_autofree char *result = NULL;
583     g_autofree char *sigStr = NULL;
584     unsigned long signature;
585     unsigned int family;
586     unsigned int model;
587     unsigned int stepping;
588 
589     signature = virCPUx86DataGetSignature(hostData, &family, &model, &stepping);
590 
591     result = g_strdup_printf("%s/cputestdata/%s-cpuid-%s.sig", abs_srcdir,
592                              virArchToString(data->arch), data->host);
593 
594     sigStr = g_strdup_printf("%1$06lx\n" "family:   %2$3u (0x%2$02x)\n"
595                              "model:    %3$3u (0x%3$02x)\n" "stepping: %4$3u (0x%4$02x)\n",
596                              signature, family, model, stepping);
597 
598     return virTestCompareToFile(sigStr, result);
599 }
600 
601 
602 static int
cpuTestCPUIDSignature(const void * arg)603 cpuTestCPUIDSignature(const void *arg)
604 {
605     const struct data *data = arg;
606     g_autoptr(virCPUData) hostData = NULL;
607     g_autofree char *hostFile = NULL;
608     g_autofree char *host = NULL;
609 
610     hostFile = g_strdup_printf("%s/cputestdata/%s-cpuid-%s.xml", abs_srcdir,
611                                virArchToString(data->arch), data->host);
612 
613     if (virTestLoadFile(hostFile, &host) < 0 ||
614         !(hostData = virCPUDataParse(host)))
615         return -1;
616 
617     return cpuTestCompareSignature(data, hostData);
618 }
619 
620 
621 static int
cpuTestUpdateLiveCompare(virArch arch,virCPUDef * actual,virCPUDef * expected)622 cpuTestUpdateLiveCompare(virArch arch,
623                          virCPUDef *actual,
624                          virCPUDef *expected)
625 {
626     size_t i, j;
627     int ret = 0;
628 
629     if (virCPUExpandFeatures(arch, actual) < 0 ||
630         virCPUExpandFeatures(arch, expected) < 0)
631         return -1;
632 
633     if (STRNEQ(actual->model, expected->model)) {
634         VIR_TEST_VERBOSE("Actual CPU model '%s', expected '%s'",
635                          actual->model, expected->model);
636         return -1;
637     }
638 
639     i = j = 0;
640     while (i < actual->nfeatures || j < expected->nfeatures) {
641         virCPUFeatureDef *featAct = NULL;
642         virCPUFeatureDef *featExp = NULL;
643         int cmp;
644 
645         if (i < actual->nfeatures)
646             featAct = actual->features + i;
647 
648         if (j < expected->nfeatures)
649             featExp = expected->features + j;
650 
651         /*
652          * Act < Exp => cmp < 0 (missing entry in Exp)
653          * Act = Exp => cmp = 0
654          * Act > Exp => cmp > 0 (missing entry in Act)
655          *
656          * NULL > name for any name != NULL
657          */
658         if (featAct && featExp)
659             cmp = strcmp(featAct->name, featExp->name);
660         else
661             cmp = featExp ? 1 : -1;
662 
663         if (cmp <= 0)
664             i++;
665         if (cmp >= 0)
666             j++;
667 
668         /* Possible combinations of cmp, featAct->policy, and featExp->policy:
669          *  cmp     Act     Exp     result
670          * ---------------------------------
671          *   0      dis     dis      ok
672          *   0      dis     req     missing
673          *   0      req     dis     extra
674          *   0      req     req      ok
675          * ---------------------------------
676          *   -      dis      X       ok     # ignoring extra disabled features
677          *   -      req      X      extra
678          * ---------------------------------
679          *   +       X      dis     extra
680          *   +       X      req     missing
681          */
682         if ((cmp == 0 &&
683              featAct->policy == VIR_CPU_FEATURE_DISABLE &&
684              featExp->policy == VIR_CPU_FEATURE_REQUIRE) ||
685             (cmp > 0 &&
686              featExp->policy == VIR_CPU_FEATURE_REQUIRE)) {
687             VIR_TEST_VERBOSE("Actual CPU lacks feature '%s'",
688                              featExp->name);
689             ret = -1;
690             continue;
691         }
692 
693         if ((cmp == 0 &&
694              featAct->policy == VIR_CPU_FEATURE_REQUIRE &&
695              featExp->policy == VIR_CPU_FEATURE_DISABLE) ||
696             (cmp < 0 &&
697              featAct->policy == VIR_CPU_FEATURE_REQUIRE) ||
698             (cmp > 0 &&
699              featExp->policy == VIR_CPU_FEATURE_DISABLE)) {
700             VIR_TEST_VERBOSE("Actual CPU has extra feature '%s'",
701                              cmp <= 0 ? featAct->name : featExp->name);
702             ret = -1;
703         }
704     }
705 
706     return ret;
707 }
708 
709 
710 static int
cpuTestUpdateLive(const void * arg)711 cpuTestUpdateLive(const void *arg)
712 {
713     const struct data *data = arg;
714     g_autofree char *cpuFile = NULL;
715     g_autoptr(virCPUDef) cpu = NULL;
716     g_autofree char *enabledFile = NULL;
717     g_autofree char *enabled = NULL;
718     g_autoptr(virCPUData) enabledData = NULL;
719     g_autofree char *disabledFile = NULL;
720     g_autofree char *disabled = NULL;
721     g_autoptr(virCPUData) disabledData = NULL;
722     g_autofree char *expectedFile = NULL;
723     g_autoptr(virCPUDef) expected = NULL;
724     g_autoptr(virDomainCapsCPUModels) hvModels = NULL;
725     g_autoptr(virDomainCapsCPUModels) models = NULL;
726 
727     cpuFile = g_strdup_printf("cpuid-%s-guest", data->host);
728     if (!(cpu = cpuTestLoadXML(data->arch, cpuFile)))
729         return -1;
730 
731     enabledFile = g_strdup_printf("%s/cputestdata/%s-cpuid-%s-enabled.xml",
732                                   abs_srcdir, virArchToString(data->arch), data->host);
733     if (virTestLoadFile(enabledFile, &enabled) < 0 ||
734         !(enabledData = virCPUDataParse(enabled)))
735         return -1;
736 
737     disabledFile = g_strdup_printf("%s/cputestdata/%s-cpuid-%s-disabled.xml",
738                                    abs_srcdir, virArchToString(data->arch), data->host);
739     if (virTestLoadFile(disabledFile, &disabled) < 0 ||
740         !(disabledData = virCPUDataParse(disabled)))
741         return -1;
742 
743     expectedFile = g_strdup_printf("cpuid-%s-json", data->host);
744     if (!(expected = cpuTestLoadXML(data->arch, expectedFile)))
745         return -1;
746 
747     /* In case the host CPU signature does not exactly match any CPU model in
748      * src/cpu_map, the CPU model we detect from CPUID may differ from the one
749      * we compute by asking QEMU. Since this test expands both CPU models and
750      * compares their features, we can try to translate the 'actual' CPU to
751      * use the CPU model from 'expected'.
752      */
753     if (STRNEQ(cpu->model, expected->model)) {
754         virDomainCapsCPUModel *hvModel;
755         char **blockers = NULL;
756         virDomainCapsCPUUsable usable = VIR_DOMCAPS_CPU_USABLE_UNKNOWN;
757         int rc;
758 
759         if (!(models = virDomainCapsCPUModelsNew(0)))
760             return -1;
761 
762         rc = cpuTestGetCPUModels(data, &hvModels);
763         if (rc != 0)
764             return rc;
765 
766         hvModel = virDomainCapsCPUModelsGet(hvModels, expected->model);
767 
768         if (hvModel) {
769             blockers = hvModel->blockers;
770             usable = hvModel->usable;
771         }
772 
773         if (virDomainCapsCPUModelsAdd(models, expected->model,
774                                       usable, blockers, false) < 0)
775             return -1;
776 
777         cpu->fallback = VIR_CPU_FALLBACK_ALLOW;
778         ignore_value(virCPUTranslate(data->arch, cpu, models));
779         cpu->fallback = VIR_CPU_FALLBACK_FORBID;
780     }
781 
782     if (virCPUUpdateLive(data->arch, cpu, enabledData, disabledData) < 0)
783         return -1;
784 
785     return cpuTestUpdateLiveCompare(data->arch, cpu, expected);
786 }
787 
788 
789 #if WITH_QEMU
790 static int
cpuTestJSONCPUID(const void * arg)791 cpuTestJSONCPUID(const void *arg)
792 {
793     const struct data *data = arg;
794     g_autoptr(virQEMUCaps) qemuCaps = NULL;
795     g_autoptr(virCPUDef) cpu = NULL;
796     g_autofree char *result = NULL;
797 
798     result = g_strdup_printf("cpuid-%s-json", data->host);
799 
800     if (!(qemuCaps = cpuTestMakeQEMUCaps(data)))
801         return -1;
802 
803     cpu = virCPUDefNew();
804     cpu->arch = data->arch;
805     cpu->type = VIR_CPU_TYPE_GUEST;
806     cpu->match = VIR_CPU_MATCH_EXACT;
807     cpu->fallback = VIR_CPU_FALLBACK_FORBID;
808 
809     if (virQEMUCapsInitCPUModel(qemuCaps, VIR_DOMAIN_VIRT_KVM, cpu, false) != 0)
810         return -1;
811 
812     return cpuTestCompareXML(data->arch, cpu, result);
813 }
814 
815 
816 static int
cpuTestJSONSignature(const void * arg)817 cpuTestJSONSignature(const void *arg)
818 {
819     const struct data *data = arg;
820     g_autoptr(virQEMUCaps) qemuCaps = NULL;
821     g_autoptr(virCPUData) hostData = NULL;
822     qemuMonitorCPUModelInfo *modelInfo;
823 
824     if (!(qemuCaps = cpuTestMakeQEMUCaps(data)))
825         return -1;
826 
827     modelInfo = virQEMUCapsGetCPUModelInfo(qemuCaps, VIR_DOMAIN_VIRT_KVM);
828     if (!(hostData = virQEMUCapsGetCPUModelX86Data(qemuCaps, modelInfo, false)))
829         return -1;
830 
831     return cpuTestCompareSignature(data, hostData);
832 }
833 #endif
834 
835 
836 static const char *model486_list[]   = { "486", NULL };
837 static const char *nomodel_list[]    = { "nomodel", NULL };
838 static const char *models_list[]     = { "qemu64", "core2duo", "Nehalem", NULL };
839 static const char *haswell_list[]    = { "SandyBridge", "Haswell", NULL };
840 static const char *ppc_models_list[] = { "POWER6", "POWER7", "POWER8", NULL };
841 
842 static virDomainCapsCPUModels *
cpuTestInitModels(const char ** list)843 cpuTestInitModels(const char **list)
844 {
845     virDomainCapsCPUModels *cpus;
846     const char **model;
847 
848     if (!(cpus = virDomainCapsCPUModelsNew(0)))
849         return NULL;
850 
851     for (model = list; *model; model++) {
852         if (virDomainCapsCPUModelsAdd(cpus, *model,
853                                       VIR_DOMCAPS_CPU_USABLE_UNKNOWN, NULL, false) < 0)
854             goto error;
855     }
856 
857     return cpus;
858 
859  error:
860     virObjectUnref(cpus);
861     return NULL;
862 }
863 
864 
865 static int
mymain(void)866 mymain(void)
867 {
868     virDomainCapsCPUModels *model486 = NULL;
869     virDomainCapsCPUModels *nomodel = NULL;
870     virDomainCapsCPUModels *models = NULL;
871     virDomainCapsCPUModels *haswell = NULL;
872     virDomainCapsCPUModels *ppc_models = NULL;
873     int ret = 0;
874 
875 #if WITH_QEMU
876     if (qemuTestDriverInit(&driver) < 0)
877         return EXIT_FAILURE;
878 
879     virEventRegisterDefaultImpl();
880 #endif
881 
882     if (!(model486 = cpuTestInitModels(model486_list)) ||
883         !(nomodel = cpuTestInitModels(nomodel_list)) ||
884         !(models = cpuTestInitModels(models_list)) ||
885         !(haswell = cpuTestInitModels(haswell_list)) ||
886         !(ppc_models = cpuTestInitModels(ppc_models_list))) {
887         ret = -1;
888         goto cleanup;
889     }
890 
891 #define DO_TEST(arch, api, name, host, cpu, \
892                 models, flags, result) \
893     do { \
894         struct data data = { \
895             arch, host, cpu, models, \
896             models == NULL ? NULL : #models, \
897             flags, result \
898         }; \
899         g_autofree char *testLabel = NULL; \
900  \
901         testLabel = g_strdup_printf("%s(%s): %s", #api, \
902                                     virArchToString(arch), name); \
903  \
904         virTestRunLog(&ret, testLabel, api, &data); \
905     } while (0)
906 
907 #define DO_TEST_COMPARE(arch, host, cpu, result) \
908     DO_TEST(arch, cpuTestCompare, \
909             host "/" cpu " (" #result ")", \
910             host, cpu, NULL, 0, result)
911 
912 #define DO_TEST_UPDATE_ONLY(arch, host, cpu) \
913     DO_TEST(arch, cpuTestUpdate, \
914             cpu " on " host, \
915             host, cpu, NULL, 0, 0)
916 
917 #define DO_TEST_UPDATE(arch, host, cpu, result) \
918     do { \
919         DO_TEST_UPDATE_ONLY(arch, host, cpu); \
920         DO_TEST_COMPARE(arch, host, host "+" cpu, result); \
921     } while (0)
922 
923 #define DO_TEST_BASELINE(arch, name, flags, result) \
924     do { \
925         const char *suffix = ""; \
926         g_autofree char *label = NULL; \
927         if ((flags) & VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES) \
928             suffix = " (expanded)"; \
929         if ((flags) & VIR_CONNECT_BASELINE_CPU_MIGRATABLE) \
930             suffix = " (migratable)"; \
931         label = g_strdup_printf("%s%s", name, suffix); \
932         DO_TEST(arch, cpuTestBaseline, label, NULL, \
933                 "baseline-" name, NULL, flags, result); \
934     } while (0)
935 
936 #define DO_TEST_HASFEATURE(arch, host, feature, result) \
937     DO_TEST(arch, cpuTestHasFeature, \
938             host "/" feature " (" #result ")", \
939             host, feature, NULL, 0, result)
940 
941 #define DO_TEST_GUESTCPU(arch, host, cpu, models, result) \
942     DO_TEST(arch, cpuTestGuestCPU, \
943             host "/" cpu " (" #models ")", \
944             host, cpu, models, 0, result)
945 
946 #if WITH_QEMU
947 # define DO_TEST_JSON(arch, host, json) \
948     do { \
949         if (json == JSON_MODELS) { \
950             DO_TEST(arch, cpuTestGuestCPUID, host, host, \
951                     NULL, NULL, 0, 0); \
952         } \
953         if (json != JSON_NONE) { \
954             DO_TEST(arch, cpuTestJSONCPUID, host, host, \
955                     NULL, NULL, json, 0); \
956             DO_TEST(arch, cpuTestJSONSignature, host, host, \
957                     NULL, NULL, 0, 0); \
958         } \
959     } while (0)
960 #else
961 # define DO_TEST_JSON(arch, host, json)
962 #endif
963 
964 #define DO_TEST_CPUID(arch, host, json) \
965     do { \
966         DO_TEST(arch, cpuTestHostCPUID, host, host, \
967                 NULL, NULL, 0, 0); \
968         DO_TEST(arch, cpuTestGuestCPUID, host, host, \
969                 NULL, NULL, json, 0); \
970         DO_TEST(arch, cpuTestCPUIDSignature, host, host, \
971                 NULL, NULL, 0, 0); \
972         DO_TEST_JSON(arch, host, json); \
973         if (json != JSON_NONE) { \
974             DO_TEST(arch, cpuTestUpdateLive, host, host, \
975                     NULL, NULL, json, 0); \
976         } \
977     } while (0)
978 
979     /* host to host comparison */
980     DO_TEST_COMPARE(VIR_ARCH_X86_64, "host", "host", VIR_CPU_COMPARE_IDENTICAL);
981     DO_TEST_COMPARE(VIR_ARCH_X86_64, "host", "host-better", VIR_CPU_COMPARE_INCOMPATIBLE);
982     DO_TEST_COMPARE(VIR_ARCH_X86_64, "host", "host-worse", VIR_CPU_COMPARE_SUPERSET);
983     DO_TEST_COMPARE(VIR_ARCH_X86_64, "host", "host-amd-fake", VIR_CPU_COMPARE_INCOMPATIBLE);
984     DO_TEST_COMPARE(VIR_ARCH_X86_64, "host", "host-incomp-arch", VIR_CPU_COMPARE_INCOMPATIBLE);
985     DO_TEST_COMPARE(VIR_ARCH_X86_64, "host", "host-no-vendor", VIR_CPU_COMPARE_IDENTICAL);
986     DO_TEST_COMPARE(VIR_ARCH_X86_64, "host-no-vendor", "host", VIR_CPU_COMPARE_INCOMPATIBLE);
987 
988     DO_TEST_COMPARE(VIR_ARCH_PPC64, "host", "host", VIR_CPU_COMPARE_IDENTICAL);
989     DO_TEST_COMPARE(VIR_ARCH_PPC64, "host", "host-better", VIR_CPU_COMPARE_INCOMPATIBLE);
990     DO_TEST_COMPARE(VIR_ARCH_PPC64, "host", "host-worse", VIR_CPU_COMPARE_INCOMPATIBLE);
991     DO_TEST_COMPARE(VIR_ARCH_PPC64, "host", "host-incomp-arch", VIR_CPU_COMPARE_INCOMPATIBLE);
992     DO_TEST_COMPARE(VIR_ARCH_PPC64, "host", "host-no-vendor", VIR_CPU_COMPARE_IDENTICAL);
993     DO_TEST_COMPARE(VIR_ARCH_PPC64, "host-no-vendor", "host", VIR_CPU_COMPARE_INCOMPATIBLE);
994 
995     /* guest to host comparison */
996     DO_TEST_COMPARE(VIR_ARCH_X86_64, "host", "bogus-model", VIR_CPU_COMPARE_ERROR);
997     DO_TEST_COMPARE(VIR_ARCH_X86_64, "host", "bogus-feature", VIR_CPU_COMPARE_ERROR);
998     DO_TEST_COMPARE(VIR_ARCH_X86_64, "host", "min", VIR_CPU_COMPARE_SUPERSET);
999     DO_TEST_COMPARE(VIR_ARCH_X86_64, "host", "pentium3", VIR_CPU_COMPARE_SUPERSET);
1000     DO_TEST_COMPARE(VIR_ARCH_X86_64, "host", "exact", VIR_CPU_COMPARE_SUPERSET);
1001     DO_TEST_COMPARE(VIR_ARCH_X86_64, "host", "exact-forbid", VIR_CPU_COMPARE_INCOMPATIBLE);
1002     DO_TEST_COMPARE(VIR_ARCH_X86_64, "host", "exact-forbid-extra", VIR_CPU_COMPARE_SUPERSET);
1003     DO_TEST_COMPARE(VIR_ARCH_X86_64, "host", "exact-disable", VIR_CPU_COMPARE_SUPERSET);
1004     DO_TEST_COMPARE(VIR_ARCH_X86_64, "host", "exact-disable2", VIR_CPU_COMPARE_SUPERSET);
1005     DO_TEST_COMPARE(VIR_ARCH_X86_64, "host", "exact-disable-extra", VIR_CPU_COMPARE_SUPERSET);
1006     DO_TEST_COMPARE(VIR_ARCH_X86_64, "host", "exact-require", VIR_CPU_COMPARE_SUPERSET);
1007     DO_TEST_COMPARE(VIR_ARCH_X86_64, "host", "exact-require-extra", VIR_CPU_COMPARE_INCOMPATIBLE);
1008     DO_TEST_COMPARE(VIR_ARCH_X86_64, "host", "exact-force", VIR_CPU_COMPARE_SUPERSET);
1009     DO_TEST_COMPARE(VIR_ARCH_X86_64, "host", "strict", VIR_CPU_COMPARE_INCOMPATIBLE);
1010     DO_TEST_COMPARE(VIR_ARCH_X86_64, "host", "strict-full", VIR_CPU_COMPARE_IDENTICAL);
1011     DO_TEST_COMPARE(VIR_ARCH_X86_64, "host", "strict-disable", VIR_CPU_COMPARE_IDENTICAL);
1012     DO_TEST_COMPARE(VIR_ARCH_X86_64, "host", "strict-force-extra", VIR_CPU_COMPARE_IDENTICAL);
1013     DO_TEST_COMPARE(VIR_ARCH_X86_64, "host", "guest", VIR_CPU_COMPARE_SUPERSET);
1014     DO_TEST_COMPARE(VIR_ARCH_X86_64, "host", "pentium3-amd", VIR_CPU_COMPARE_INCOMPATIBLE);
1015     DO_TEST_COMPARE(VIR_ARCH_X86_64, "host-amd", "pentium3-amd", VIR_CPU_COMPARE_SUPERSET);
1016     DO_TEST_COMPARE(VIR_ARCH_X86_64, "host-worse", "penryn-force", VIR_CPU_COMPARE_IDENTICAL);
1017     DO_TEST_COMPARE(VIR_ARCH_X86_64, "host-SandyBridge", "exact-force-Haswell", VIR_CPU_COMPARE_IDENTICAL);
1018 
1019     DO_TEST_COMPARE(VIR_ARCH_PPC64, "host", "guest-strict", VIR_CPU_COMPARE_IDENTICAL);
1020     DO_TEST_COMPARE(VIR_ARCH_PPC64, "host", "guest-exact", VIR_CPU_COMPARE_INCOMPATIBLE);
1021     DO_TEST_COMPARE(VIR_ARCH_PPC64, "host", "guest-legacy", VIR_CPU_COMPARE_IDENTICAL);
1022     DO_TEST_COMPARE(VIR_ARCH_PPC64, "host", "guest-legacy-incompatible", VIR_CPU_COMPARE_INCOMPATIBLE);
1023     DO_TEST_COMPARE(VIR_ARCH_PPC64, "host", "guest-legacy-bad", VIR_CPU_COMPARE_ERROR);
1024     DO_TEST_COMPARE(VIR_ARCH_PPC64, "host", "guest-compat-none", VIR_CPU_COMPARE_IDENTICAL);
1025     DO_TEST_COMPARE(VIR_ARCH_PPC64, "host", "guest-compat-valid", VIR_CPU_COMPARE_IDENTICAL);
1026     DO_TEST_COMPARE(VIR_ARCH_PPC64, "host", "guest-compat-bad", VIR_CPU_COMPARE_ERROR);
1027     DO_TEST_COMPARE(VIR_ARCH_PPC64, "host", "guest-compat-incompatible", VIR_CPU_COMPARE_INCOMPATIBLE);
1028 
1029     /* guest updates for migration
1030      * automatically compares host CPU with the result */
1031     DO_TEST_UPDATE(VIR_ARCH_X86_64, "host", "min", VIR_CPU_COMPARE_IDENTICAL);
1032     DO_TEST_UPDATE(VIR_ARCH_X86_64, "host", "pentium3", VIR_CPU_COMPARE_IDENTICAL);
1033     DO_TEST_UPDATE(VIR_ARCH_X86_64, "host", "guest", VIR_CPU_COMPARE_SUPERSET);
1034     DO_TEST_UPDATE(VIR_ARCH_X86_64, "host", "host-model", VIR_CPU_COMPARE_IDENTICAL);
1035     DO_TEST_UPDATE(VIR_ARCH_X86_64, "host", "host-model-nofallback", VIR_CPU_COMPARE_IDENTICAL);
1036     DO_TEST_UPDATE(VIR_ARCH_X86_64, "host-invtsc", "host-model", VIR_CPU_COMPARE_SUPERSET);
1037     DO_TEST_UPDATE_ONLY(VIR_ARCH_X86_64, "host", "host-passthrough");
1038     DO_TEST_UPDATE_ONLY(VIR_ARCH_X86_64, "host", "host-passthrough-features");
1039 
1040     DO_TEST_UPDATE(VIR_ARCH_PPC64, "host", "guest", VIR_CPU_COMPARE_IDENTICAL);
1041     DO_TEST_UPDATE(VIR_ARCH_PPC64, "host", "guest-nofallback", VIR_CPU_COMPARE_INCOMPATIBLE);
1042     DO_TEST_UPDATE(VIR_ARCH_PPC64, "host", "guest-legacy", VIR_CPU_COMPARE_IDENTICAL);
1043     DO_TEST_UPDATE(VIR_ARCH_PPC64, "host", "guest-legacy-incompatible", VIR_CPU_COMPARE_INCOMPATIBLE);
1044     DO_TEST_UPDATE(VIR_ARCH_PPC64, "host", "guest-legacy-bad", VIR_CPU_COMPARE_ERROR);
1045     DO_TEST_UPDATE(VIR_ARCH_PPC64, "host", "guest-compat-none", VIR_CPU_COMPARE_IDENTICAL);
1046     DO_TEST_UPDATE(VIR_ARCH_PPC64, "host", "guest-compat-valid", VIR_CPU_COMPARE_IDENTICAL);
1047     DO_TEST_UPDATE(VIR_ARCH_PPC64, "host", "guest-compat-bad", VIR_CPU_COMPARE_ERROR);
1048     DO_TEST_UPDATE(VIR_ARCH_PPC64, "host", "guest-compat-incompatible", VIR_CPU_COMPARE_INCOMPATIBLE);
1049 
1050     /* computing baseline CPUs */
1051     DO_TEST_BASELINE(VIR_ARCH_X86_64, "incompatible-vendors", 0, -1);
1052     DO_TEST_BASELINE(VIR_ARCH_X86_64, "no-vendor", 0, 0);
1053     DO_TEST_BASELINE(VIR_ARCH_X86_64, "some-vendors", 0, 0);
1054     DO_TEST_BASELINE(VIR_ARCH_X86_64, "1", 0, 0);
1055     DO_TEST_BASELINE(VIR_ARCH_X86_64, "2", 0, 0);
1056     DO_TEST_BASELINE(VIR_ARCH_X86_64, "3", 0, 0);
1057     DO_TEST_BASELINE(VIR_ARCH_X86_64, "3", VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES, 0);
1058     DO_TEST_BASELINE(VIR_ARCH_X86_64, "4", 0, 0);
1059     DO_TEST_BASELINE(VIR_ARCH_X86_64, "4", VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES, 0);
1060     DO_TEST_BASELINE(VIR_ARCH_X86_64, "5", 0, 0);
1061     DO_TEST_BASELINE(VIR_ARCH_X86_64, "5", VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES, 0);
1062     DO_TEST_BASELINE(VIR_ARCH_X86_64, "6", 0, 0);
1063     DO_TEST_BASELINE(VIR_ARCH_X86_64, "6", VIR_CONNECT_BASELINE_CPU_MIGRATABLE, 0);
1064     DO_TEST_BASELINE(VIR_ARCH_X86_64, "7", 0, 0);
1065     DO_TEST_BASELINE(VIR_ARCH_X86_64, "8", 0, 0);
1066 
1067     DO_TEST_BASELINE(VIR_ARCH_PPC64, "incompatible-vendors", 0, -1);
1068     DO_TEST_BASELINE(VIR_ARCH_PPC64, "no-vendor", 0, 0);
1069     DO_TEST_BASELINE(VIR_ARCH_PPC64, "incompatible-models", 0, -1);
1070     DO_TEST_BASELINE(VIR_ARCH_PPC64, "same-model", 0, 0);
1071     DO_TEST_BASELINE(VIR_ARCH_PPC64, "legacy", 0, -1);
1072 
1073     /* CPU features */
1074     DO_TEST_HASFEATURE(VIR_ARCH_X86_64, "host", "vmx", YES);
1075     DO_TEST_HASFEATURE(VIR_ARCH_X86_64, "host", "lm", YES);
1076     DO_TEST_HASFEATURE(VIR_ARCH_X86_64, "host", "sse4.1", YES);
1077     DO_TEST_HASFEATURE(VIR_ARCH_X86_64, "host", "3dnowext", NO);
1078     DO_TEST_HASFEATURE(VIR_ARCH_X86_64, "host", "skinit", NO);
1079     DO_TEST_HASFEATURE(VIR_ARCH_X86_64, "host", "foo", FAIL);
1080 
1081     /* computing guest data and decoding the data into a guest CPU XML */
1082     DO_TEST_GUESTCPU(VIR_ARCH_X86_64, "host", "guest", NULL, 0);
1083     DO_TEST_GUESTCPU(VIR_ARCH_X86_64, "host-better", "pentium3", NULL, 0);
1084     DO_TEST_GUESTCPU(VIR_ARCH_X86_64, "host-worse", "guest", NULL, 0);
1085     DO_TEST_GUESTCPU(VIR_ARCH_X86_64, "host", "strict-force-extra", NULL, 0);
1086     DO_TEST_GUESTCPU(VIR_ARCH_X86_64, "host", "penryn-force", NULL, 0);
1087     DO_TEST_GUESTCPU(VIR_ARCH_X86_64, "host", "guest", model486, 0);
1088     DO_TEST_GUESTCPU(VIR_ARCH_X86_64, "host", "guest", models, 0);
1089     DO_TEST_GUESTCPU(VIR_ARCH_X86_64, "host", "guest", nomodel, -1);
1090     DO_TEST_GUESTCPU(VIR_ARCH_X86_64, "host", "guest-nofallback", models, -1);
1091     DO_TEST_GUESTCPU(VIR_ARCH_X86_64, "host", "host+host-model", models, 0);
1092     DO_TEST_GUESTCPU(VIR_ARCH_X86_64, "host", "host+host-model-nofallback", models, -1);
1093     DO_TEST_GUESTCPU(VIR_ARCH_X86_64, "host-Haswell-noTSX", "Haswell", haswell, 0);
1094     DO_TEST_GUESTCPU(VIR_ARCH_X86_64, "host-Haswell-noTSX", "Haswell-noTSX", haswell, 0);
1095     DO_TEST_GUESTCPU(VIR_ARCH_X86_64, "host-Haswell-noTSX", "Haswell-noTSX-nofallback", haswell, -1);
1096     DO_TEST_GUESTCPU(VIR_ARCH_X86_64, "host-Haswell-noTSX", "Haswell-noTSX", NULL, 0);
1097 
1098     DO_TEST_GUESTCPU(VIR_ARCH_PPC64, "host", "guest", ppc_models, 0);
1099     DO_TEST_GUESTCPU(VIR_ARCH_PPC64, "host", "guest-nofallback", ppc_models, -1);
1100     DO_TEST_GUESTCPU(VIR_ARCH_PPC64, "host", "guest-legacy", ppc_models, 0);
1101     DO_TEST_GUESTCPU(VIR_ARCH_PPC64, "host", "guest-legacy-incompatible", ppc_models, -1);
1102     DO_TEST_GUESTCPU(VIR_ARCH_PPC64, "host", "guest-legacy-bad", ppc_models, -1);
1103 
1104     DO_TEST_CPUID(VIR_ARCH_X86_64, "A10-5800K", JSON_HOST);
1105     DO_TEST_CPUID(VIR_ARCH_X86_64, "Atom-D510", JSON_NONE);
1106     DO_TEST_CPUID(VIR_ARCH_X86_64, "Atom-N450", JSON_NONE);
1107     DO_TEST_CPUID(VIR_ARCH_X86_64, "Atom-P5362", JSON_MODELS_REQUIRED);
1108     DO_TEST_CPUID(VIR_ARCH_X86_64, "Core-i5-650", JSON_MODELS_REQUIRED);
1109     DO_TEST_CPUID(VIR_ARCH_X86_64, "Core-i5-2500", JSON_HOST);
1110     DO_TEST_CPUID(VIR_ARCH_X86_64, "Core-i5-2540M", JSON_MODELS);
1111     DO_TEST_CPUID(VIR_ARCH_X86_64, "Core-i5-4670T", JSON_HOST);
1112     DO_TEST_CPUID(VIR_ARCH_X86_64, "Core-i5-6600", JSON_HOST);
1113     DO_TEST_CPUID(VIR_ARCH_X86_64, "Core-i7-2600", JSON_HOST);
1114     DO_TEST_CPUID(VIR_ARCH_X86_64, "Core-i7-2600-xsaveopt", JSON_MODELS_REQUIRED);
1115     DO_TEST_CPUID(VIR_ARCH_X86_64, "Core-i7-3520M", JSON_NONE);
1116     DO_TEST_CPUID(VIR_ARCH_X86_64, "Core-i7-3740QM", JSON_HOST);
1117     DO_TEST_CPUID(VIR_ARCH_X86_64, "Core-i7-3770", JSON_HOST);
1118     DO_TEST_CPUID(VIR_ARCH_X86_64, "Core-i7-4600U", JSON_HOST);
1119     DO_TEST_CPUID(VIR_ARCH_X86_64, "Core-i7-4510U", JSON_HOST);
1120     DO_TEST_CPUID(VIR_ARCH_X86_64, "Core-i7-5600U", JSON_HOST);
1121     DO_TEST_CPUID(VIR_ARCH_X86_64, "Core-i7-5600U-arat", JSON_HOST);
1122     DO_TEST_CPUID(VIR_ARCH_X86_64, "Core-i7-5600U-ibrs", JSON_HOST);
1123     DO_TEST_CPUID(VIR_ARCH_X86_64, "Core-i7-7600U", JSON_MODELS);
1124     DO_TEST_CPUID(VIR_ARCH_X86_64, "Core-i7-7700", JSON_MODELS);
1125     DO_TEST_CPUID(VIR_ARCH_X86_64, "Core-i7-8550U", JSON_MODELS);
1126     DO_TEST_CPUID(VIR_ARCH_X86_64, "Core-i7-8700", JSON_MODELS);
1127     DO_TEST_CPUID(VIR_ARCH_X86_64, "Core2-E6850", JSON_HOST);
1128     DO_TEST_CPUID(VIR_ARCH_X86_64, "Core2-Q9500", JSON_NONE);
1129     DO_TEST_CPUID(VIR_ARCH_X86_64, "Hygon-C86-7185-32-core", JSON_HOST);
1130     DO_TEST_CPUID(VIR_ARCH_X86_64, "EPYC-7601-32-Core", JSON_HOST);
1131     DO_TEST_CPUID(VIR_ARCH_X86_64, "EPYC-7601-32-Core-ibpb", JSON_MODELS_REQUIRED);
1132     DO_TEST_CPUID(VIR_ARCH_X86_64, "EPYC-7502-32-Core", JSON_MODELS);
1133     DO_TEST_CPUID(VIR_ARCH_X86_64, "FX-8150", JSON_NONE);
1134     DO_TEST_CPUID(VIR_ARCH_X86_64, "Opteron-1352", JSON_NONE);
1135     DO_TEST_CPUID(VIR_ARCH_X86_64, "Opteron-2350", JSON_HOST);
1136     DO_TEST_CPUID(VIR_ARCH_X86_64, "Opteron-6234", JSON_HOST);
1137     DO_TEST_CPUID(VIR_ARCH_X86_64, "Opteron-6282", JSON_NONE);
1138     DO_TEST_CPUID(VIR_ARCH_X86_64, "Pentium-P6100", JSON_NONE);
1139     DO_TEST_CPUID(VIR_ARCH_X86_64, "Phenom-B95", JSON_HOST);
1140     DO_TEST_CPUID(VIR_ARCH_X86_64, "Ryzen-7-1800X-Eight-Core", JSON_HOST);
1141     DO_TEST_CPUID(VIR_ARCH_X86_64, "Ryzen-9-3900X-12-Core", JSON_MODELS);
1142     DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-5110", JSON_NONE);
1143     DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-E3-1225-v5", JSON_MODELS);
1144     DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-E3-1245-v5", JSON_MODELS);
1145     DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-E5-2609-v3", JSON_MODELS);
1146     DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-E5-2623-v4", JSON_MODELS);
1147     DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-E5-2630-v3", JSON_HOST);
1148     DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-E5-2630-v4", JSON_MODELS);
1149     DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-E5-2650", JSON_MODELS);
1150     DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-E5-2650-v3", JSON_HOST);
1151     DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-E5-2650-v4", JSON_MODELS);
1152     DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-E7-4820", JSON_HOST);
1153     DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-E7-4830", JSON_MODELS_REQUIRED);
1154     DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-E7-8890-v3", JSON_MODELS);
1155     DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-E7540", JSON_MODELS);
1156     DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-Gold-5115", JSON_MODELS);
1157     DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-Gold-6130", JSON_MODELS);
1158     DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-Gold-6148", JSON_HOST);
1159     DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-Platinum-8268", JSON_HOST);
1160     DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-Platinum-9242", JSON_MODELS);
1161     DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-W3520", JSON_HOST);
1162     DO_TEST_CPUID(VIR_ARCH_X86_64, "Xeon-X5460", JSON_NONE);
1163     DO_TEST_CPUID(VIR_ARCH_X86_64, "Ice-Lake-Server", JSON_MODELS);
1164     DO_TEST_CPUID(VIR_ARCH_X86_64, "Cooperlake", JSON_MODELS);
1165 
1166  cleanup:
1167 #if WITH_QEMU
1168     qemuTestDriverFree(&driver);
1169 #endif
1170 
1171     virObjectUnref(model486);
1172     virObjectUnref(nomodel);
1173     virObjectUnref(models);
1174     virObjectUnref(haswell);
1175     virObjectUnref(ppc_models);
1176 
1177     return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
1178 }
1179 
1180 VIR_TEST_MAIN(mymain)
1181