/* * cputest.c: Test the libvirtd internal CPU APIs * * Copyright (C) 2010-2014 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see * . * * Author: Jiri Denemark */ #include #include #include #include #include #include #include #include "internal.h" #include "virxml.h" #include "viralloc.h" #include "virbuffer.h" #include "testutils.h" #include "cpu_conf.h" #include "cpu/cpu.h" #include "cpu/cpu_map.h" #include "virstring.h" #if WITH_QEMU && WITH_YAJL # include "testutilsqemu.h" # include "qemumonitortestutils.h" # include "qemu/qemu_monitor_json.h" #endif #define VIR_FROM_THIS VIR_FROM_CPU enum cpuTestBoolWithError { FAIL = -1, NO = 0, YES = 1 }; struct data { const char *arch; const char *host; const char *name; const char **models; const char *modelsName; unsigned int nmodels; const char *preferred; unsigned int flags; int result; }; #if WITH_QEMU && WITH_YAJL static virQEMUDriver driver; #endif static virCPUDefPtr cpuTestLoadXML(const char *arch, const char *name) { char *xml = NULL; xmlDocPtr doc = NULL; xmlXPathContextPtr ctxt = NULL; virCPUDefPtr cpu = NULL; if (virAsprintf(&xml, "%s/cputestdata/%s-%s.xml", abs_srcdir, arch, name) < 0) goto cleanup; if (!(doc = virXMLParseFileCtxt(xml, &ctxt))) goto cleanup; cpu = virCPUDefParseXML(ctxt->node, ctxt, VIR_CPU_TYPE_AUTO); cleanup: xmlXPathFreeContext(ctxt); xmlFreeDoc(doc); VIR_FREE(xml); return cpu; } static virCPUDefPtr * cpuTestLoadMultiXML(const char *arch, const char *name, unsigned int *count) { char *xml = NULL; xmlDocPtr doc = NULL; xmlXPathContextPtr ctxt = NULL; xmlNodePtr *nodes = NULL; virCPUDefPtr *cpus = NULL; int n; size_t i; if (virAsprintf(&xml, "%s/cputestdata/%s-%s.xml", abs_srcdir, arch, name) < 0) goto cleanup; if (!(doc = virXMLParseFileCtxt(xml, &ctxt))) goto cleanup; n = virXPathNodeSet("/cpuTest/cpu", ctxt, &nodes); if (n <= 0 || (VIR_ALLOC_N(cpus, n) < 0)) { fprintf(stderr, "\nNo /cpuTest/cpu elements found in %s\n", xml); goto cleanup; } for (i = 0; i < n; i++) { ctxt->node = nodes[i]; cpus[i] = virCPUDefParseXML(nodes[i], ctxt, VIR_CPU_TYPE_HOST); if (!cpus[i]) goto cleanup_cpus; } *count = n; cleanup: VIR_FREE(xml); VIR_FREE(nodes); xmlXPathFreeContext(ctxt); xmlFreeDoc(doc); return cpus; cleanup_cpus: for (i = 0; i < n; i++) virCPUDefFree(cpus[i]); VIR_FREE(cpus); goto cleanup; } static int cpuTestCompareXML(const char *arch, virCPUDef *cpu, const char *name, bool updateCPU) { char *xml = NULL; char *actual = NULL; int ret = -1; if (virAsprintf(&xml, "%s/cputestdata/%s-%s.xml", abs_srcdir, arch, name) < 0) goto cleanup; if (!(actual = virCPUDefFormat(cpu, NULL, updateCPU))) goto cleanup; if (virTestCompareToFile(actual, xml) < 0) goto cleanup; ret = 0; cleanup: VIR_FREE(xml); VIR_FREE(actual); return ret; } static const char * cpuTestCompResStr(virCPUCompareResult result) { switch (result) { case VIR_CPU_COMPARE_ERROR: return "ERROR"; case VIR_CPU_COMPARE_INCOMPATIBLE: return "INCOMPATIBLE"; case VIR_CPU_COMPARE_IDENTICAL: return "IDENTICAL"; case VIR_CPU_COMPARE_SUPERSET: return "SUPERSET"; case VIR_CPU_COMPARE_LAST: break; } return "unknown"; } static const char * cpuTestBoolWithErrorStr(enum cpuTestBoolWithError result) { switch (result) { case FAIL: return "FAIL"; case NO: return "NO"; case YES: return "YES"; } return "unknown"; } static int cpuTestCompare(const void *arg) { const struct data *data = arg; int ret = -1; virCPUDefPtr host = NULL; virCPUDefPtr cpu = NULL; virCPUCompareResult result; if (!(host = cpuTestLoadXML(data->arch, data->host)) || !(cpu = cpuTestLoadXML(data->arch, data->name))) goto cleanup; result = virCPUCompare(host->arch, host, cpu, false); if (data->result == VIR_CPU_COMPARE_ERROR) virResetLastError(); if (data->result != result) { VIR_TEST_VERBOSE("\nExpected result %s, got %s\n", cpuTestCompResStr(data->result), cpuTestCompResStr(result)); /* Pad to line up with test name ... in virTestRun */ VIR_TEST_VERBOSE("%74s", "... "); goto cleanup; } ret = 0; cleanup: virCPUDefFree(host); virCPUDefFree(cpu); return ret; } static int cpuTestGuestData(const void *arg) { const struct data *data = arg; int ret = -2; virCPUDefPtr host = NULL; virCPUDefPtr cpu = NULL; virCPUDefPtr guest = NULL; virCPUDataPtr guestData = NULL; virCPUCompareResult cmpResult; virBuffer buf = VIR_BUFFER_INITIALIZER; char *result = NULL; if (!(host = cpuTestLoadXML(data->arch, data->host)) || !(cpu = cpuTestLoadXML(data->arch, data->name))) goto cleanup; cmpResult = cpuGuestData(host, cpu, &guestData, NULL); if (cmpResult == VIR_CPU_COMPARE_ERROR || cmpResult == VIR_CPU_COMPARE_INCOMPATIBLE) { ret = -1; goto cleanup; } if (VIR_ALLOC(guest) < 0) goto cleanup; guest->arch = host->arch; guest->type = VIR_CPU_TYPE_GUEST; guest->match = VIR_CPU_MATCH_EXACT; guest->fallback = cpu->fallback; if (cpuDecode(guest, guestData, data->models, data->nmodels, data->preferred) < 0) { ret = -1; goto cleanup; } virBufferAsprintf(&buf, "%s+%s", data->host, data->name); if (data->nmodels) virBufferAsprintf(&buf, ",%s", data->modelsName); if (data->preferred) virBufferAsprintf(&buf, ",%s", data->preferred); virBufferAddLit(&buf, "-result"); if (virBufferError(&buf)) { virBufferFreeAndReset(&buf); goto cleanup; } result = virBufferContentAndReset(&buf); if (cpuTestCompareXML(data->arch, guest, result, false) < 0) goto cleanup; ret = 0; cleanup: VIR_FREE(result); cpuDataFree(guestData); virCPUDefFree(host); virCPUDefFree(cpu); virCPUDefFree(guest); if (ret == data->result) { /* We got the result we expected, whether it was * a success or a failure */ virResetLastError(); ret = 0; } else { VIR_TEST_VERBOSE("\nExpected result %d, got %d\n", data->result, ret); /* Pad to line up with test name ... in virTestRun */ VIR_TEST_VERBOSE("%74s", "... "); ret = -1; } return ret; } static int cpuTestBaseline(const void *arg) { const struct data *data = arg; int ret = -1; virCPUDefPtr *cpus = NULL; virCPUDefPtr baseline = NULL; unsigned int ncpus = 0; char *result = NULL; const char *suffix; size_t i; if (!(cpus = cpuTestLoadMultiXML(data->arch, data->name, &ncpus))) goto cleanup; baseline = cpuBaseline(cpus, ncpus, NULL, 0, data->flags); if (data->result < 0) { virResetLastError(); if (!baseline) { ret = 0; } else { VIR_TEST_VERBOSE("\n%-70s... ", "cpuBaseline was expected to fail but it succeeded"); } goto cleanup; } if (!baseline) goto cleanup; if (data->flags & VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES) suffix = "expanded"; else if (data->flags & VIR_CONNECT_BASELINE_CPU_MIGRATABLE) suffix = "migratable"; else suffix = "result"; if (virAsprintf(&result, "%s-%s", data->name, suffix) < 0) goto cleanup; if (cpuTestCompareXML(data->arch, baseline, result, false) < 0) goto cleanup; for (i = 0; i < ncpus; i++) { virCPUCompareResult cmp; cmp = virCPUCompare(cpus[i]->arch, cpus[i], baseline, false); if (cmp != VIR_CPU_COMPARE_SUPERSET && cmp != VIR_CPU_COMPARE_IDENTICAL) { VIR_TEST_VERBOSE("\nbaseline CPU is incompatible with CPU %zu\n", i); VIR_TEST_VERBOSE("%74s", "... "); ret = -1; goto cleanup; } } ret = 0; cleanup: if (cpus) { for (i = 0; i < ncpus; i++) virCPUDefFree(cpus[i]); VIR_FREE(cpus); } virCPUDefFree(baseline); VIR_FREE(result); return ret; } static int cpuTestUpdate(const void *arg) { const struct data *data = arg; int ret = -1; virCPUDefPtr host = NULL; virCPUDefPtr cpu = NULL; char *result = NULL; if (!(host = cpuTestLoadXML(data->arch, data->host)) || !(cpu = cpuTestLoadXML(data->arch, data->name))) goto cleanup; if (virCPUUpdate(host->arch, cpu, host) < 0) goto cleanup; if (virAsprintf(&result, "%s+%s", data->host, data->name) < 0) goto cleanup; ret = cpuTestCompareXML(data->arch, cpu, result, true); cleanup: virCPUDefFree(host); virCPUDefFree(cpu); VIR_FREE(result); return ret; } static int cpuTestHasFeature(const void *arg) { const struct data *data = arg; int ret = -1; virCPUDefPtr host = NULL; virCPUDataPtr hostData = NULL; int result; if (!(host = cpuTestLoadXML(data->arch, data->host))) goto cleanup; if (cpuEncode(host->arch, host, NULL, &hostData, NULL, NULL, NULL, NULL) < 0) goto cleanup; result = virCPUCheckFeature(host->arch, host, data->name); if (data->result == result) result = virCPUDataCheckFeature(hostData, data->name); if (data->result == -1) virResetLastError(); if (data->result != result) { VIR_TEST_VERBOSE("\nExpected result %s, got %s\n", cpuTestBoolWithErrorStr(data->result), cpuTestBoolWithErrorStr(result)); /* Pad to line up with test name ... in virTestRun */ VIR_TEST_VERBOSE("%74s", "... "); goto cleanup; } ret = 0; cleanup: cpuDataFree(hostData); virCPUDefFree(host); return ret; } static int cpuTestCPUID(bool guest, const void *arg) { const struct data *data = arg; int ret = -1; virCPUDataPtr hostData = NULL; char *hostFile = NULL; char *host = NULL; virCPUDefPtr cpu = NULL; char *result = NULL; if (virAsprintf(&hostFile, "%s/cputestdata/%s-cpuid-%s.xml", abs_srcdir, data->arch, data->host) < 0) goto cleanup; if (virTestLoadFile(hostFile, &host) < 0 || !(hostData = virCPUDataParse(host))) goto cleanup; if (VIR_ALLOC(cpu) < 0) goto cleanup; cpu->arch = hostData->arch; if (guest) { cpu->type = VIR_CPU_TYPE_GUEST; cpu->match = VIR_CPU_MATCH_EXACT; cpu->fallback = VIR_CPU_FALLBACK_FORBID; } else { cpu->type = VIR_CPU_TYPE_HOST; } if (cpuDecode(cpu, hostData, NULL, 0, NULL) < 0) goto cleanup; if (virAsprintf(&result, "cpuid-%s-%s", data->host, guest ? "guest" : "host") < 0) goto cleanup; ret = cpuTestCompareXML(data->arch, cpu, result, false); cleanup: VIR_FREE(hostFile); VIR_FREE(host); cpuDataFree(hostData); virCPUDefFree(cpu); VIR_FREE(result); return ret; } static int cpuTestHostCPUID(const void *arg) { return cpuTestCPUID(false, arg); } static int cpuTestGuestCPUID(const void *arg) { return cpuTestCPUID(true, arg); } #if WITH_QEMU && WITH_YAJL static int cpuTestJSONCPUID(const void *arg) { const struct data *data = arg; virCPUDataPtr cpuData = NULL; virCPUDefPtr cpu = NULL; qemuMonitorTestPtr testMon = NULL; char *json = NULL; char *result = NULL; int ret = -1; if (virAsprintf(&json, "%s/cputestdata/%s-cpuid-%s.json", abs_srcdir, data->arch, data->host) < 0 || virAsprintf(&result, "cpuid-%s-json", data->host) < 0) goto cleanup; if (!(testMon = qemuMonitorTestNewFromFile(json, driver.xmlopt, true))) goto cleanup; if (qemuMonitorJSONGetCPUx86Data(qemuMonitorTestGetMonitor(testMon), "feature-words", &cpuData) < 0) goto cleanup; if (VIR_ALLOC(cpu) < 0) goto cleanup; cpu->arch = cpuData->arch; cpu->type = VIR_CPU_TYPE_GUEST; cpu->match = VIR_CPU_MATCH_EXACT; cpu->fallback = VIR_CPU_FALLBACK_FORBID; if (cpuDecode(cpu, cpuData, NULL, 0, NULL) < 0) goto cleanup; ret = cpuTestCompareXML(data->arch, cpu, result, false); cleanup: qemuMonitorTestFree(testMon); cpuDataFree(cpuData); virCPUDefFree(cpu); VIR_FREE(result); VIR_FREE(json); return ret; } #endif static const char *model486[] = { "486" }; static const char *nomodel[] = { "nomodel" }; static const char *models[] = { "qemu64", "core2duo", "Nehalem" }; static const char *haswell[] = { "SandyBridge", "Haswell" }; static const char *ppc_models[] = { "POWER6", "POWER7", "POWER8" }; static int mymain(void) { int ret = 0; #if WITH_QEMU && WITH_YAJL if (qemuTestDriverInit(&driver) < 0) return EXIT_FAILURE; virEventRegisterDefaultImpl(); #endif #define DO_TEST(arch, api, name, host, cpu, \ models, nmodels, preferred, flags, result) \ do { \ struct data data = { \ arch, host, cpu, models, \ models == NULL ? NULL : #models, \ nmodels, preferred, flags, result \ }; \ char *testLabel; \ char *tmp; \ \ tmp = virTestLogContentAndReset(); \ VIR_FREE(tmp); \ \ if (virAsprintf(&testLabel, "%s(%s): %s", \ #api, arch, name) < 0) { \ ret = -1; \ break; \ } \ \ if (virTestRun(testLabel, api, &data) < 0) { \ if (virTestGetDebug()) { \ char *log; \ if ((log = virTestLogContentAndReset()) && \ strlen(log) > 0) \ VIR_TEST_DEBUG("\n%s\n", log); \ VIR_FREE(log); \ } \ ret = -1; \ } \ \ VIR_FREE(testLabel); \ } while (0) #define DO_TEST_COMPARE(arch, host, cpu, result) \ DO_TEST(arch, cpuTestCompare, \ host "/" cpu " (" #result ")", \ host, cpu, NULL, 0, NULL, 0, result) #define DO_TEST_UPDATE_ONLY(arch, host, cpu) \ DO_TEST(arch, cpuTestUpdate, \ cpu " on " host, \ host, cpu, NULL, 0, NULL, 0, 0) \ #define DO_TEST_UPDATE(arch, host, cpu, result) \ do { \ DO_TEST_UPDATE_ONLY(arch, host, cpu); \ DO_TEST_COMPARE(arch, host, host "+" cpu, result); \ } while (0) #define DO_TEST_BASELINE(arch, name, flags, result) \ do { \ const char *suffix = ""; \ char *label; \ if ((flags) & VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES) \ suffix = " (expanded)"; \ if ((flags) & VIR_CONNECT_BASELINE_CPU_MIGRATABLE) \ suffix = " (migratable)"; \ if (virAsprintf(&label, "%s%s", name, suffix) < 0) { \ ret = -1; \ } else { \ DO_TEST(arch, cpuTestBaseline, label, NULL, \ "baseline-" name, NULL, 0, NULL, flags, result); \ } \ VIR_FREE(label); \ } while (0) #define DO_TEST_HASFEATURE(arch, host, feature, result) \ DO_TEST(arch, cpuTestHasFeature, \ host "/" feature " (" #result ")", \ host, feature, NULL, 0, NULL, 0, result) #define DO_TEST_GUESTDATA(arch, host, cpu, models, preferred, result) \ DO_TEST(arch, cpuTestGuestData, \ host "/" cpu " (" #models ", pref=" #preferred ")", \ host, cpu, models, \ models == NULL ? 0 : sizeof(models) / sizeof(char *), \ preferred, 0, result) #if WITH_QEMU && WITH_YAJL # define DO_TEST_CPUID_JSON(arch, host, json) \ do { \ if (json) { \ DO_TEST(arch, cpuTestJSONCPUID, host, host, \ NULL, NULL, 0, NULL, 0, 0); \ } \ } while (0) #else # define DO_TEST_CPUID_JSON(arch, host, json) #endif #define DO_TEST_CPUID(arch, host, json) \ do { \ DO_TEST(arch, cpuTestHostCPUID, host, host, \ NULL, NULL, 0, NULL, 0, 0); \ DO_TEST(arch, cpuTestGuestCPUID, host, host, \ NULL, NULL, 0, NULL, 0, 0); \ DO_TEST_CPUID_JSON(arch, host, json); \ } while (0) /* host to host comparison */ DO_TEST_COMPARE("x86", "host", "host", VIR_CPU_COMPARE_IDENTICAL); DO_TEST_COMPARE("x86", "host", "host-better", VIR_CPU_COMPARE_INCOMPATIBLE); DO_TEST_COMPARE("x86", "host", "host-worse", VIR_CPU_COMPARE_SUPERSET); DO_TEST_COMPARE("x86", "host", "host-amd-fake", VIR_CPU_COMPARE_INCOMPATIBLE); DO_TEST_COMPARE("x86", "host", "host-incomp-arch", VIR_CPU_COMPARE_INCOMPATIBLE); DO_TEST_COMPARE("x86", "host", "host-no-vendor", VIR_CPU_COMPARE_IDENTICAL); DO_TEST_COMPARE("x86", "host-no-vendor", "host", VIR_CPU_COMPARE_INCOMPATIBLE); DO_TEST_COMPARE("ppc64", "host", "host", VIR_CPU_COMPARE_IDENTICAL); DO_TEST_COMPARE("ppc64", "host", "host-better", VIR_CPU_COMPARE_INCOMPATIBLE); DO_TEST_COMPARE("ppc64", "host", "host-worse", VIR_CPU_COMPARE_INCOMPATIBLE); DO_TEST_COMPARE("ppc64", "host", "host-incomp-arch", VIR_CPU_COMPARE_INCOMPATIBLE); DO_TEST_COMPARE("ppc64", "host", "host-no-vendor", VIR_CPU_COMPARE_IDENTICAL); DO_TEST_COMPARE("ppc64", "host-no-vendor", "host", VIR_CPU_COMPARE_INCOMPATIBLE); /* guest to host comparison */ DO_TEST_COMPARE("x86", "host", "bogus-model", VIR_CPU_COMPARE_ERROR); DO_TEST_COMPARE("x86", "host", "bogus-feature", VIR_CPU_COMPARE_ERROR); DO_TEST_COMPARE("x86", "host", "min", VIR_CPU_COMPARE_SUPERSET); DO_TEST_COMPARE("x86", "host", "pentium3", VIR_CPU_COMPARE_SUPERSET); DO_TEST_COMPARE("x86", "host", "exact", VIR_CPU_COMPARE_SUPERSET); DO_TEST_COMPARE("x86", "host", "exact-forbid", VIR_CPU_COMPARE_INCOMPATIBLE); DO_TEST_COMPARE("x86", "host", "exact-forbid-extra", VIR_CPU_COMPARE_SUPERSET); DO_TEST_COMPARE("x86", "host", "exact-disable", VIR_CPU_COMPARE_SUPERSET); DO_TEST_COMPARE("x86", "host", "exact-disable2", VIR_CPU_COMPARE_SUPERSET); DO_TEST_COMPARE("x86", "host", "exact-disable-extra", VIR_CPU_COMPARE_SUPERSET); DO_TEST_COMPARE("x86", "host", "exact-require", VIR_CPU_COMPARE_SUPERSET); DO_TEST_COMPARE("x86", "host", "exact-require-extra", VIR_CPU_COMPARE_INCOMPATIBLE); DO_TEST_COMPARE("x86", "host", "exact-force", VIR_CPU_COMPARE_SUPERSET); DO_TEST_COMPARE("x86", "host", "strict", VIR_CPU_COMPARE_INCOMPATIBLE); DO_TEST_COMPARE("x86", "host", "strict-full", VIR_CPU_COMPARE_IDENTICAL); DO_TEST_COMPARE("x86", "host", "strict-disable", VIR_CPU_COMPARE_IDENTICAL); DO_TEST_COMPARE("x86", "host", "strict-force-extra", VIR_CPU_COMPARE_IDENTICAL); DO_TEST_COMPARE("x86", "host", "guest", VIR_CPU_COMPARE_SUPERSET); DO_TEST_COMPARE("x86", "host", "pentium3-amd", VIR_CPU_COMPARE_INCOMPATIBLE); DO_TEST_COMPARE("x86", "host-amd", "pentium3-amd", VIR_CPU_COMPARE_SUPERSET); DO_TEST_COMPARE("x86", "host-worse", "penryn-force", VIR_CPU_COMPARE_IDENTICAL); DO_TEST_COMPARE("x86", "host-SandyBridge", "exact-force-Haswell", VIR_CPU_COMPARE_IDENTICAL); DO_TEST_COMPARE("ppc64", "host", "guest-strict", VIR_CPU_COMPARE_IDENTICAL); DO_TEST_COMPARE("ppc64", "host", "guest-exact", VIR_CPU_COMPARE_INCOMPATIBLE); DO_TEST_COMPARE("ppc64", "host", "guest-legacy", VIR_CPU_COMPARE_IDENTICAL); DO_TEST_COMPARE("ppc64", "host", "guest-legacy-incompatible", VIR_CPU_COMPARE_INCOMPATIBLE); DO_TEST_COMPARE("ppc64", "host", "guest-legacy-invalid", VIR_CPU_COMPARE_ERROR); DO_TEST_COMPARE("ppc64", "host", "guest-compat-none", VIR_CPU_COMPARE_IDENTICAL); DO_TEST_COMPARE("ppc64", "host", "guest-compat-valid", VIR_CPU_COMPARE_IDENTICAL); DO_TEST_COMPARE("ppc64", "host", "guest-compat-invalid", VIR_CPU_COMPARE_ERROR); DO_TEST_COMPARE("ppc64", "host", "guest-compat-incompatible", VIR_CPU_COMPARE_INCOMPATIBLE); /* guest updates for migration * automatically compares host CPU with the result */ DO_TEST_UPDATE("x86", "host", "min", VIR_CPU_COMPARE_IDENTICAL); DO_TEST_UPDATE("x86", "host", "pentium3", VIR_CPU_COMPARE_IDENTICAL); DO_TEST_UPDATE("x86", "host", "guest", VIR_CPU_COMPARE_SUPERSET); DO_TEST_UPDATE("x86", "host", "host-model", VIR_CPU_COMPARE_IDENTICAL); DO_TEST_UPDATE("x86", "host", "host-model-nofallback", VIR_CPU_COMPARE_IDENTICAL); DO_TEST_UPDATE("x86", "host-invtsc", "host-model", VIR_CPU_COMPARE_SUPERSET); DO_TEST_UPDATE_ONLY("x86", "host", "host-passthrough"); DO_TEST_UPDATE_ONLY("x86", "host", "host-passthrough-features"); DO_TEST_UPDATE("ppc64", "host", "guest", VIR_CPU_COMPARE_IDENTICAL); DO_TEST_UPDATE("ppc64", "host", "guest-nofallback", VIR_CPU_COMPARE_INCOMPATIBLE); DO_TEST_UPDATE("ppc64", "host", "guest-legacy", VIR_CPU_COMPARE_IDENTICAL); DO_TEST_UPDATE("ppc64", "host", "guest-legacy-incompatible", VIR_CPU_COMPARE_INCOMPATIBLE); DO_TEST_UPDATE("ppc64", "host", "guest-legacy-invalid", VIR_CPU_COMPARE_ERROR); DO_TEST_UPDATE("ppc64", "host", "guest-compat-none", VIR_CPU_COMPARE_IDENTICAL); DO_TEST_UPDATE("ppc64", "host", "guest-compat-valid", VIR_CPU_COMPARE_IDENTICAL); DO_TEST_UPDATE("ppc64", "host", "guest-compat-invalid", VIR_CPU_COMPARE_ERROR); DO_TEST_UPDATE("ppc64", "host", "guest-compat-incompatible", VIR_CPU_COMPARE_INCOMPATIBLE); /* computing baseline CPUs */ DO_TEST_BASELINE("x86", "incompatible-vendors", 0, -1); DO_TEST_BASELINE("x86", "no-vendor", 0, 0); DO_TEST_BASELINE("x86", "some-vendors", 0, 0); DO_TEST_BASELINE("x86", "1", 0, 0); DO_TEST_BASELINE("x86", "2", 0, 0); DO_TEST_BASELINE("x86", "3", 0, 0); DO_TEST_BASELINE("x86", "3", VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES, 0); DO_TEST_BASELINE("x86", "4", 0, 0); DO_TEST_BASELINE("x86", "4", VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES, 0); DO_TEST_BASELINE("x86", "5", 0, 0); DO_TEST_BASELINE("x86", "5", VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES, 0); DO_TEST_BASELINE("x86", "6", 0, 0); DO_TEST_BASELINE("x86", "6", VIR_CONNECT_BASELINE_CPU_MIGRATABLE, 0); DO_TEST_BASELINE("x86", "7", 0, 0); DO_TEST_BASELINE("x86", "8", 0, 0); DO_TEST_BASELINE("ppc64", "incompatible-vendors", 0, -1); DO_TEST_BASELINE("ppc64", "no-vendor", 0, 0); DO_TEST_BASELINE("ppc64", "incompatible-models", 0, -1); DO_TEST_BASELINE("ppc64", "same-model", 0, 0); DO_TEST_BASELINE("ppc64", "legacy", 0, -1); /* CPU features */ DO_TEST_HASFEATURE("x86", "host", "vmx", YES); DO_TEST_HASFEATURE("x86", "host", "lm", YES); DO_TEST_HASFEATURE("x86", "host", "sse4.1", YES); DO_TEST_HASFEATURE("x86", "host", "3dnowext", NO); DO_TEST_HASFEATURE("x86", "host", "skinit", NO); DO_TEST_HASFEATURE("x86", "host", "foo", FAIL); /* computing guest data and decoding the data into a guest CPU XML */ DO_TEST_GUESTDATA("x86", "host", "guest", NULL, NULL, 0); DO_TEST_GUESTDATA("x86", "host-better", "pentium3", NULL, NULL, 0); DO_TEST_GUESTDATA("x86", "host-worse", "guest", NULL, NULL, 0); DO_TEST_GUESTDATA("x86", "host", "strict-force-extra", NULL, NULL, 0); DO_TEST_GUESTDATA("x86", "host", "penryn-force", NULL, NULL, 0); DO_TEST_GUESTDATA("x86", "host", "guest", model486, NULL, 0); DO_TEST_GUESTDATA("x86", "host", "guest", models, NULL, 0); DO_TEST_GUESTDATA("x86", "host", "guest", nomodel, NULL, -1); DO_TEST_GUESTDATA("x86", "host", "guest-nofallback", models, NULL, /*-1*/ -2); DO_TEST_GUESTDATA("x86", "host", "host+host-model", models, NULL, 0); DO_TEST_GUESTDATA("x86", "host", "host+host-model-nofallback", models, NULL, /*-1*/ -2); DO_TEST_GUESTDATA("x86", "host-Haswell-noTSX", "Haswell", haswell, NULL, 0); DO_TEST_GUESTDATA("x86", "host-Haswell-noTSX", "Haswell-noTSX", haswell, NULL, 0); DO_TEST_GUESTDATA("x86", "host-Haswell-noTSX", "Haswell-noTSX-nofallback", haswell, NULL, /*-1*/ -2); DO_TEST_GUESTDATA("x86", "host-Haswell-noTSX", "Haswell-noTSX", NULL, NULL, 0); DO_TEST_GUESTDATA("ppc64", "host", "guest", ppc_models, NULL, 0); DO_TEST_GUESTDATA("ppc64", "host", "guest-nofallback", ppc_models, NULL, -1); DO_TEST_GUESTDATA("ppc64", "host", "guest-legacy", ppc_models, NULL, 0); DO_TEST_GUESTDATA("ppc64", "host", "guest-legacy-incompatible", ppc_models, NULL, -1); DO_TEST_GUESTDATA("ppc64", "host", "guest-legacy-invalid", ppc_models, NULL, -1); DO_TEST_CPUID("x86", "A10-5800K", true); DO_TEST_CPUID("x86", "Atom-D510", false); DO_TEST_CPUID("x86", "Atom-N450", false); DO_TEST_CPUID("x86", "Core-i5-2500", true); DO_TEST_CPUID("x86", "Core-i5-2540M", true); DO_TEST_CPUID("x86", "Core-i5-4670T", true); DO_TEST_CPUID("x86", "Core-i5-6600", true); DO_TEST_CPUID("x86", "Core-i7-2600", true); DO_TEST_CPUID("x86", "Core-i7-3520M", false); DO_TEST_CPUID("x86", "Core-i7-3740QM", true); DO_TEST_CPUID("x86", "Core-i7-3770", true); DO_TEST_CPUID("x86", "Core-i7-4600U", true); DO_TEST_CPUID("x86", "Core-i7-5600U", true); DO_TEST_CPUID("x86", "Core2-E6850", true); DO_TEST_CPUID("x86", "Core2-Q9500", false); DO_TEST_CPUID("x86", "FX-8150", false); DO_TEST_CPUID("x86", "Opteron-1352", false); DO_TEST_CPUID("x86", "Opteron-2350", true); DO_TEST_CPUID("x86", "Opteron-6234", true); DO_TEST_CPUID("x86", "Opteron-6282", false); DO_TEST_CPUID("x86", "Pentium-P6100", false); DO_TEST_CPUID("x86", "Phenom-B95", true); DO_TEST_CPUID("x86", "Xeon-5110", false); DO_TEST_CPUID("x86", "Xeon-E3-1245", true); DO_TEST_CPUID("x86", "Xeon-E5-2630", true); DO_TEST_CPUID("x86", "Xeon-E5-2650", true); DO_TEST_CPUID("x86", "Xeon-E7-4820", true); DO_TEST_CPUID("x86", "Xeon-W3520", true); DO_TEST_CPUID("x86", "Xeon-X5460", false); #if WITH_QEMU && WITH_YAJL qemuTestDriverFree(&driver); #endif return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; } VIRT_TEST_MAIN(mymain)