diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 3581c2d72349b4c7f1940014f53a50b6c6c6a801..ad9451e8f86c35955095b118281d48192b42cbab 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -2348,7 +2348,8 @@ int virQEMUCapsAddCPUDefinitions(virQEMUCapsPtr qemuCaps, virDomainVirtType type, const char **name, - size_t count) + size_t count, + virDomainCapsCPUUsable usable) { size_t i; virDomainCapsCPUModelsPtr cpus = NULL; @@ -2369,8 +2370,7 @@ virQEMUCapsAddCPUDefinitions(virQEMUCapsPtr qemuCaps, } for (i = 0; i < count; i++) { - if (virDomainCapsCPUModelsAdd(cpus, name[i], -1, - VIR_DOMCAPS_CPU_USABLE_UNKNOWN) < 0) + if (virDomainCapsCPUModelsAdd(cpus, name[i], -1, usable) < 0) return -1; } @@ -2786,9 +2786,14 @@ virQEMUCapsProbeQMPCPUDefinitions(virQEMUCapsPtr qemuCaps, qemuCaps->kvmCPUModels = models; for (i = 0; i < ncpus; i++) { - if (virDomainCapsCPUModelsAddSteal(models, - &cpus[i]->name, - VIR_DOMCAPS_CPU_USABLE_UNKNOWN) < 0) + virDomainCapsCPUUsable usable = VIR_DOMCAPS_CPU_USABLE_UNKNOWN; + + if (cpus[i]->usable == VIR_TRISTATE_BOOL_YES) + usable = VIR_DOMCAPS_CPU_USABLE_YES; + else if (cpus[i]->usable == VIR_TRISTATE_BOOL_NO) + usable = VIR_DOMCAPS_CPU_USABLE_NO; + + if (virDomainCapsCPUModelsAddSteal(models, &cpus[i]->name, usable) < 0) goto cleanup; } @@ -3099,14 +3104,23 @@ virQEMUCapsLoadCPUModels(virQEMUCapsPtr qemuCaps, qemuCaps->tcgCPUModels = cpus; for (i = 0; i < n; i++) { + int usable = VIR_DOMCAPS_CPU_USABLE_UNKNOWN; + + if ((str = virXMLPropString(nodes[i], "usable")) && + (usable = virDomainCapsCPUUsableTypeFromString(str)) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("unknown value '%s' in attribute 'usable'"), str); + goto cleanup; + } + VIR_FREE(str); + if (!(str = virXMLPropString(nodes[i], "name"))) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("missing cpu name in QEMU capabilities cache")); goto cleanup; } - if (virDomainCapsCPUModelsAddSteal(cpus, &str, - VIR_DOMCAPS_CPU_USABLE_UNKNOWN) < 0) + if (virDomainCapsCPUModelsAddSteal(cpus, &str, usable) < 0) goto cleanup; } @@ -3385,8 +3399,15 @@ virQEMUCapsFormatCPUModels(virQEMUCapsPtr qemuCaps, return; for (i = 0; i < cpus->nmodels; i++) { + virDomainCapsCPUModelPtr cpu = cpus->models + i; + virBufferAsprintf(buf, "\n", cpus->models[i].name); + virBufferEscapeString(buf, "name='%s'", cpu->name); + if (cpu->usable) { + virBufferAsprintf(buf, " usable='%s'", + virDomainCapsCPUUsableTypeToString(cpu->usable)); + } + virBufferAddLit(buf, "/>\n"); } } diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index 6d57ffb7cafcb0ca722a43dd116734314218bb1a..b3175a5211e24f45b3b812aed6918afec8790642 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -433,7 +433,8 @@ unsigned int virQEMUCapsGetKVMVersion(virQEMUCapsPtr qemuCaps); int virQEMUCapsAddCPUDefinitions(virQEMUCapsPtr qemuCaps, virDomainVirtType type, const char **name, - size_t count); + size_t count, + virDomainCapsCPUUsable usable); int virQEMUCapsGetCPUDefinitions(virQEMUCapsPtr qemuCaps, virDomainVirtType type, char ***names, diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h index 100730bae45db05033f01b21f71072cf3c86a10b..f1ddb6c12586d0855f589d6bf18ece1d260b1794 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -916,6 +916,7 @@ typedef struct _qemuMonitorCPUDefInfo qemuMonitorCPUDefInfo; typedef qemuMonitorCPUDefInfo *qemuMonitorCPUDefInfoPtr; struct _qemuMonitorCPUDefInfo { + virTristateBool usable; char *name; }; diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c index 03a5e1e4d7efa731890deb4714110a36ca4cf76b..81e86412d45ae3a1c20e07c31358f01c49272dc0 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -4916,6 +4916,24 @@ qemuMonitorJSONGetCPUDefinitions(qemuMonitorPtr mon, if (VIR_STRDUP(cpu->name, tmp) < 0) goto cleanup; + + if (virJSONValueObjectHasKey(child, "unavailable-features")) { + virJSONValuePtr blockers; + + blockers = virJSONValueObjectGetArray(child, + "unavailable-features"); + if (!blockers) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("unavailable-features in query-cpu-definitions " + "reply data was not an array")); + goto cleanup; + } + + if (virJSONValueArraySize(blockers) > 0) + cpu->usable = VIR_TRISTATE_BOOL_NO; + else + cpu->usable = VIR_TRISTATE_BOOL_YES; + } } ret = n; diff --git a/tests/domaincapsschemadata/qemu_2.8.0-tcg.x86_64.xml b/tests/domaincapsschemadata/qemu_2.8.0-tcg.x86_64.xml index fe598e98b3c4833699720b953b4909cf86172019..dd9285311cdfb23327a06ab23c9932d4eaf6fca6 100644 --- a/tests/domaincapsschemadata/qemu_2.8.0-tcg.x86_64.xml +++ b/tests/domaincapsschemadata/qemu_2.8.0-tcg.x86_64.xml @@ -24,35 +24,35 @@ Broadwell - qemu64 - qemu32 - phenom - pentium3 - pentium2 - pentium - n270 - kvm64 - kvm32 - coreduo - core2duo - athlon - Westmere - Skylake-Client - SandyBridge - Penryn - Opteron_G5 - Opteron_G4 - Opteron_G3 - Opteron_G2 - Opteron_G1 - Nehalem - IvyBridge - Haswell - Haswell-noTSX - Conroe - Broadwell - Broadwell-noTSX - 486 + qemu64 + qemu32 + phenom + pentium3 + pentium2 + pentium + n270 + kvm64 + kvm32 + coreduo + core2duo + athlon + Westmere + Skylake-Client + SandyBridge + Penryn + Opteron_G5 + Opteron_G4 + Opteron_G3 + Opteron_G2 + Opteron_G1 + Nehalem + IvyBridge + Haswell + Haswell-noTSX + Conroe + Broadwell + Broadwell-noTSX + 486 diff --git a/tests/domaincapsschemadata/qemu_2.8.0.x86_64.xml b/tests/domaincapsschemadata/qemu_2.8.0.x86_64.xml index 7b8f90ee325f9e651b9b1dfcbe25a8d1fdb23ce6..4c5fffcad4c0c7f0e9223bf08df22d91b6d52772 100644 --- a/tests/domaincapsschemadata/qemu_2.8.0.x86_64.xml +++ b/tests/domaincapsschemadata/qemu_2.8.0.x86_64.xml @@ -24,35 +24,35 @@ Broadwell - qemu64 - qemu32 - phenom - pentium3 - pentium2 - pentium - n270 - kvm64 - kvm32 - coreduo - core2duo - athlon - Westmere - Skylake-Client - SandyBridge - Penryn - Opteron_G5 - Opteron_G4 - Opteron_G3 - Opteron_G2 - Opteron_G1 - Nehalem - IvyBridge - Haswell - Haswell-noTSX - Conroe - Broadwell - Broadwell-noTSX - 486 + qemu64 + qemu32 + phenom + pentium3 + pentium2 + pentium + n270 + kvm64 + kvm32 + coreduo + core2duo + athlon + Westmere + Skylake-Client + SandyBridge + Penryn + Opteron_G5 + Opteron_G4 + Opteron_G3 + Opteron_G2 + Opteron_G1 + Nehalem + IvyBridge + Haswell + Haswell-noTSX + Conroe + Broadwell + Broadwell-noTSX + 486 diff --git a/tests/qemucapabilitiesdata/caps_2.8.0.x86_64.xml b/tests/qemucapabilitiesdata/caps_2.8.0.x86_64.xml index 7113269bf55e59a723116d6eed39fb92322c851b..e487c40509458f14740d68acac203854c6408bd8 100644 --- a/tests/qemucapabilitiesdata/caps_2.8.0.x86_64.xml +++ b/tests/qemucapabilitiesdata/caps_2.8.0.x86_64.xml @@ -200,66 +200,66 @@ 0 (v2.8.0-rc1-dirty) x86_64 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/qemumonitorjsontest.c b/tests/qemumonitorjsontest.c index f729b2eda00e94561d5c65817c38e9d531053a50..ff88d1f87fb86e105610ee8ad97cc617aeddd64c 100644 --- a/tests/qemumonitorjsontest.c +++ b/tests/qemumonitorjsontest.c @@ -432,10 +432,12 @@ testQemuMonitorJSONGetCPUDefinitions(const void *data) " \"name\": \"qemu64\" " " }, " " { " - " \"name\": \"Opteron_G4\" " + " \"name\": \"Opteron_G4\", " + " \"unavailable-features\": [\"vme\"]" " }, " " { " - " \"name\": \"Westmere\" " + " \"name\": \"Westmere\", " + " \"unavailable-features\": []" " } " " ]" "}") < 0) @@ -451,7 +453,7 @@ testQemuMonitorJSONGetCPUDefinitions(const void *data) goto cleanup; } -#define CHECK(i, wantname) \ +#define CHECK_FULL(i, wantname, Usable) \ do { \ if (STRNEQ(cpus[i]->name, (wantname))) { \ virReportError(VIR_ERR_INTERNAL_ERROR, \ @@ -459,13 +461,28 @@ testQemuMonitorJSONGetCPUDefinitions(const void *data) cpus[i]->name, (wantname)); \ goto cleanup; \ } \ + if (cpus[i]->usable != (Usable)) { \ + virReportError(VIR_ERR_INTERNAL_ERROR, \ + "%s: expecting usable flag %d, got %d", \ + cpus[i]->name, Usable, cpus[i]->usable); \ + goto cleanup; \ + } \ } while (0) +#define CHECK(i, wantname) \ + CHECK_FULL(i, wantname, VIR_TRISTATE_BOOL_ABSENT) + +#define CHECK_USABLE(i, wantname, usable) \ + CHECK_FULL(i, wantname, \ + usable ? VIR_TRISTATE_BOOL_YES : VIR_TRISTATE_BOOL_NO) + CHECK(0, "qemu64"); - CHECK(1, "Opteron_G4"); - CHECK(2, "Westmere"); + CHECK_USABLE(1, "Opteron_G4", false); + CHECK_USABLE(2, "Westmere", true); #undef CHECK +#undef CHECK_USABLE +#undef CHECK_FULL ret = 0; diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 8f37ee5375f5b345276590b7bbad9e0de1521fad..8d1bdb710374fee8ac41f65b2a306d447a555e92 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -303,31 +303,39 @@ testAddCPUModels(virQEMUCapsPtr caps, bool skipLegacy) if (ARCH_IS_X86(arch)) { if (virQEMUCapsAddCPUDefinitions(caps, VIR_DOMAIN_VIRT_KVM, x86Models, - ARRAY_CARDINALITY(x86Models)) < 0 || + ARRAY_CARDINALITY(x86Models), + VIR_DOMCAPS_CPU_USABLE_UNKNOWN) < 0 || virQEMUCapsAddCPUDefinitions(caps, VIR_DOMAIN_VIRT_QEMU, x86Models, - ARRAY_CARDINALITY(x86Models)) < 0) + ARRAY_CARDINALITY(x86Models), + VIR_DOMCAPS_CPU_USABLE_UNKNOWN) < 0) return -1; if (!skipLegacy) { if (virQEMUCapsAddCPUDefinitions(caps, VIR_DOMAIN_VIRT_KVM, x86LegacyModels, - ARRAY_CARDINALITY(x86LegacyModels)) < 0 || + ARRAY_CARDINALITY(x86LegacyModels), + VIR_DOMCAPS_CPU_USABLE_UNKNOWN) < 0 || virQEMUCapsAddCPUDefinitions(caps, VIR_DOMAIN_VIRT_QEMU, x86LegacyModels, - ARRAY_CARDINALITY(x86LegacyModels)) < 0) + ARRAY_CARDINALITY(x86LegacyModels), + VIR_DOMCAPS_CPU_USABLE_UNKNOWN) < 0) return -1; } } else if (ARCH_IS_ARM(arch)) { if (virQEMUCapsAddCPUDefinitions(caps, VIR_DOMAIN_VIRT_KVM, armModels, - ARRAY_CARDINALITY(armModels)) < 0 || + ARRAY_CARDINALITY(armModels), + VIR_DOMCAPS_CPU_USABLE_UNKNOWN) < 0 || virQEMUCapsAddCPUDefinitions(caps, VIR_DOMAIN_VIRT_QEMU, armModels, - ARRAY_CARDINALITY(armModels)) < 0) + ARRAY_CARDINALITY(armModels), + VIR_DOMCAPS_CPU_USABLE_UNKNOWN) < 0) return -1; } else if (ARCH_IS_PPC64(arch)) { if (virQEMUCapsAddCPUDefinitions(caps, VIR_DOMAIN_VIRT_KVM, ppc64Models, - ARRAY_CARDINALITY(ppc64Models)) < 0 || + ARRAY_CARDINALITY(ppc64Models), + VIR_DOMCAPS_CPU_USABLE_UNKNOWN) < 0 || virQEMUCapsAddCPUDefinitions(caps, VIR_DOMAIN_VIRT_QEMU, ppc64Models, - ARRAY_CARDINALITY(ppc64Models)) < 0) + ARRAY_CARDINALITY(ppc64Models), + VIR_DOMCAPS_CPU_USABLE_UNKNOWN) < 0) return -1; }