Until now host-model CPU mode tried to enable all CPU features supported
by the host CPU even if QEMU/KVM did not support them. This caused a
number of issues and made host-model quite unreliable. Asking QEMU for
the CPU it can provide and the current host makes host-model much more
robust.
This commit fixes the following bugs:
https://bugzilla.redhat.com/show_bug.cgi?id=1018251
https://bugzilla.redhat.com/show_bug.cgi?id=1371617
https://bugzilla.redhat.com/show_bug.cgi?id=1372581
https://bugzilla.redhat.com/show_bug.cgi?id=1404627
https://bugzilla.redhat.com/show_bug.cgi?id=870071
In addition to that, the following bug should be mostly limited to cases
when an unsupported feature is explicitly requested:
https://bugzilla.redhat.com/show_bug.cgi?id=1335534
Signed-off-by: Jiri Denemark <jdenemar(a)redhat.com>
---
src/qemu/qemu_capabilities.c | 73 ++++++++++++++++++++++
.../domaincapsschemadata/qemu_2.9.0-tcg.x86_64.xml | 33 +++++++++-
tests/domaincapsschemadata/qemu_2.9.0.x86_64.xml | 11 +++-
3 files changed, 115 insertions(+), 2 deletions(-)
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index f115f1e23..bcfb6b694 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -3128,6 +3128,77 @@ virQEMUCapsInitCPUModelS390(virQEMUCapsPtr qemuCaps,
* -1 on error.
*/
static int
+virQEMUCapsInitCPUModelX86(virQEMUCapsPtr qemuCaps,
+ virDomainVirtType type,
+ virCPUDefPtr cpu)
+{
+ qemuMonitorCPUModelInfoPtr model;
+ virCPUDataPtr data = NULL;
+ unsigned long long sigFamily = 0;
+ unsigned long long sigModel = 0;
+ size_t nmodels = 0;
+ char **models = NULL;
+ int ret = -1;
+ size_t i;
+
+ if (type == VIR_DOMAIN_VIRT_KVM)
+ model = qemuCaps->kvmCPUModelInfo;
+ else
+ model = qemuCaps->tcgCPUModelInfo;
+
+ if (!model)
+ return 1;
+
+ if (!(data = virCPUDataNew(VIR_ARCH_X86_64)))
+ goto cleanup;
+
+ for (i = 0; i < model->nprops; i++) {
+ qemuMonitorCPUPropertyPtr prop = model->props + i;
+
+ switch (prop->type) {
+ case QEMU_MONITOR_CPU_PROPERTY_BOOLEAN:
+ if (prop->value.boolean &&
+ virCPUx86DataAddFeature(data, prop->name) < 0)
+ goto cleanup;
+ break;
+
+ case QEMU_MONITOR_CPU_PROPERTY_STRING:
+ if (STREQ(prop->name, "vendor") &&
+ virCPUx86DataSetVendor(data, prop->value.string) < 0)
+ goto cleanup;
+ break;
+
+ case QEMU_MONITOR_CPU_PROPERTY_ULL:
+ if (STREQ(prop->name, "family"))
+ sigFamily = prop->value.ull;
+ else if (STREQ(prop->name, "model"))
+ sigModel = prop->value.ull;
+ break;
+ }
+ }
+
+ if (virCPUx86DataSetSignature(data, sigFamily, sigModel) < 0)
+ goto cleanup;
+
+ if (virQEMUCapsGetCPUDefinitions(qemuCaps, type, &models, &nmodels) < 0
||
+ cpuDecode(cpu, data, (const char **) models, nmodels, NULL) < 0)
+ goto cleanup;
+
+ ret = 0;
+
+ cleanup:
+ virCPUDataFree(data);
+ virStringListFreeCount(models, nmodels);
+ return ret;
+}
+
+
+/**
+ * Returns 0 when host CPU model provided by QEMU was filled in qemuCaps,
+ * 1 when the caller should fall back to using virCapsPtr->host.cpu,
+ * -1 on error.
+ */
+static int
virQEMUCapsInitCPUModel(virQEMUCapsPtr qemuCaps,
virDomainVirtType type,
virCPUDefPtr cpu)
@@ -3136,6 +3207,8 @@ virQEMUCapsInitCPUModel(virQEMUCapsPtr qemuCaps,
if (ARCH_IS_S390(qemuCaps->arch))
ret = virQEMUCapsInitCPUModelS390(qemuCaps, type, cpu);
+ else if (ARCH_IS_X86(qemuCaps->arch))
+ ret = virQEMUCapsInitCPUModelX86(qemuCaps, type, cpu);
if (ret == 0)
cpu->fallback = VIR_CPU_FALLBACK_FORBID;
diff --git a/tests/domaincapsschemadata/qemu_2.9.0-tcg.x86_64.xml
b/tests/domaincapsschemadata/qemu_2.9.0-tcg.x86_64.xml
index 9b9dfec09..1827b1d6f 100644
--- a/tests/domaincapsschemadata/qemu_2.9.0-tcg.x86_64.xml
+++ b/tests/domaincapsschemadata/qemu_2.9.0-tcg.x86_64.xml
@@ -21,7 +21,38 @@
<cpu>
<mode name='host-passthrough' supported='no'/>
<mode name='host-model' supported='yes'>
- <model fallback='allow'>Broadwell</model>
+ <model fallback='forbid'>Opteron_G4</model>
+ <vendor>AMD</vendor>
+ <feature policy='require' name='acpi'/>
+ <feature policy='require' name='ss'/>
+ <feature policy='require' name='monitor'/>
+ <feature policy='require' name='movbe'/>
+ <feature policy='require' name='hypervisor'/>
+ <feature policy='require' name='arat'/>
+ <feature policy='require' name='fsgsbase'/>
+ <feature policy='require' name='bmi1'/>
+ <feature policy='require' name='smep'/>
+ <feature policy='require' name='bmi2'/>
+ <feature policy='require' name='erms'/>
+ <feature policy='require' name='mpx'/>
+ <feature policy='require' name='adx'/>
+ <feature policy='require' name='smap'/>
+ <feature policy='require' name='clflushopt'/>
+ <feature policy='require' name='pku'/>
+ <feature policy='require' name='ospke'/>
+ <feature policy='require' name='xsaveopt'/>
+ <feature policy='require' name='xgetbv1'/>
+ <feature policy='require' name='mmxext'/>
+ <feature policy='require' name='3dnowext'/>
+ <feature policy='require' name='3dnow'/>
+ <feature policy='require' name='cr8legacy'/>
+ <feature policy='disable' name='pclmuldq'/>
+ <feature policy='disable' name='avx'/>
+ <feature policy='disable' name='lahf_lm'/>
+ <feature policy='disable' name='misalignsse'/>
+ <feature policy='disable' name='3dnowprefetch'/>
+ <feature policy='disable' name='xop'/>
+ <feature policy='disable' name='fma4'/>
</mode>
<mode name='custom' supported='yes'>
<model usable='yes'>qemu64</model>
diff --git a/tests/domaincapsschemadata/qemu_2.9.0.x86_64.xml
b/tests/domaincapsschemadata/qemu_2.9.0.x86_64.xml
index 49722f91f..a7a2ecdea 100644
--- a/tests/domaincapsschemadata/qemu_2.9.0.x86_64.xml
+++ b/tests/domaincapsschemadata/qemu_2.9.0.x86_64.xml
@@ -21,7 +21,16 @@
<cpu>
<mode name='host-passthrough' supported='yes'/>
<mode name='host-model' supported='yes'>
- <model fallback='allow'>Broadwell</model>
+ <model fallback='forbid'>Skylake-Client</model>
+ <vendor>Intel</vendor>
+ <feature policy='require' name='ss'/>
+ <feature policy='require' name='vmx'/>
+ <feature policy='require' name='hypervisor'/>
+ <feature policy='require' name='clflushopt'/>
+ <feature policy='require' name='xsaves'/>
+ <feature policy='require' name='pdpe1gb'/>
+ <feature policy='disable' name='pclmuldq'/>
+ <feature policy='disable' name='lahf_lm'/>
</mode>
<mode name='custom' supported='yes'>
<model usable='yes'>qemu64</model>
--
2.11.1