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;
}