提交 adff345e 编写于 作者: M Martin Kletzander

qemu: Allow enabling/disabling features with host-passthrough

QEMU supports feature specification with -cpu host and we just skip
using that.  Since QEMU developers themselves would like to use this
feature, this patch modifies the code to work.

Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1178850Signed-off-by: NMartin Kletzander <mkletzan@redhat.com>
上级 f7a30375
...@@ -982,6 +982,7 @@ ...@@ -982,6 +982,7 @@
<pre> <pre>
&lt;cpu mode='host-passthrough'/&gt; &lt;cpu mode='host-passthrough'/&gt;
&lt;feature policy='disable' name='lahf_lm'/&gt;
...</pre> ...</pre>
<p> <p>
...@@ -1083,8 +1084,8 @@ ...@@ -1083,8 +1084,8 @@
the same as the host CPU even in the aspects that libvirt does not the same as the host CPU even in the aspects that libvirt does not
understand. Though the downside of this mode is that the guest understand. Though the downside of this mode is that the guest
environment cannot be reproduced on different hardware. Thus, if you environment cannot be reproduced on different hardware. Thus, if you
hit any bugs, you are on your own. Neither <code>model</code> nor hit any bugs, you are on your own. Further details of that CPU can
<code>feature</code> elements are allowed in this mode.</dd> be changed using <code>feature</code> elements.</dd>
</dl> </dl>
In both <code>host-model</code> and <code>host-passthrough</code> In both <code>host-model</code> and <code>host-passthrough</code>
......
...@@ -4088,50 +4088,29 @@ ...@@ -4088,50 +4088,29 @@
--> -->
<define name="cpu"> <define name="cpu">
<element name="cpu"> <element name="cpu">
<choice> <optional>
<group> <ref name="cpuMode"/>
<interleave> </optional>
<optional> <optional>
<ref name="cpuTopology"/> <ref name="cpuMatch"/>
</optional> </optional>
<optional> <interleave>
<ref name="cpuNuma"/> <optional>
</optional> <ref name="cpuModel"/>
</interleave> </optional>
</group> <optional>
<group> <ref name="cpuVendor"/>
<ref name="cpuMode"/> </optional>
<interleave> <optional>
<optional> <ref name="cpuTopology"/>
<ref name="cpuModel"/> </optional>
</optional> <zeroOrMore>
<optional> <ref name="cpuFeature"/>
<ref name="cpuNuma"/> </zeroOrMore>
</optional> <optional>
</interleave> <ref name="cpuNuma"/>
</group> </optional>
<group> </interleave>
<optional>
<ref name="cpuMode"/>
</optional>
<ref name="cpuMatch"/>
<interleave>
<ref name="cpuModel"/>
<optional>
<ref name="cpuVendor"/>
</optional>
<optional>
<ref name="cpuTopology"/>
</optional>
<zeroOrMore>
<ref name="cpuFeature"/>
</zeroOrMore>
<optional>
<ref name="cpuNuma"/>
</optional>
</interleave>
</group>
</choice>
</element> </element>
</define> </define>
......
/* /*
* cpu_conf.c: CPU XML handling * cpu_conf.c: CPU XML handling
* *
* Copyright (C) 2009-2014 Red Hat, Inc. * Copyright (C) 2009-2015 Red Hat, Inc.
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
...@@ -366,12 +366,8 @@ virCPUDefParseXML(xmlNodePtr node, ...@@ -366,12 +366,8 @@ virCPUDefParseXML(xmlNodePtr node,
goto error; goto error;
if (n > 0) { if (n > 0) {
if (!def->model && def->mode == VIR_CPU_MODE_HOST_PASSTHROUGH) { if (!def->model && def->mode != VIR_CPU_MODE_HOST_MODEL &&
/* silently ignore incorrectly formatted features generated def->mode != VIR_CPU_MODE_HOST_PASSTHROUGH) {
* by older libvirt */
goto cleanup;
}
if (!def->model && def->mode != VIR_CPU_MODE_HOST_MODEL) {
virReportError(VIR_ERR_XML_ERROR, "%s", virReportError(VIR_ERR_XML_ERROR, "%s",
_("Non-empty feature list specified without " _("Non-empty feature list specified without "
"CPU model")); "CPU model"));
...@@ -623,6 +619,7 @@ virCPUDefFormatBuf(virBufferPtr buf, ...@@ -623,6 +619,7 @@ virCPUDefFormatBuf(virBufferPtr buf,
if (!def->model && if (!def->model &&
def->mode != VIR_CPU_MODE_HOST_MODEL && def->mode != VIR_CPU_MODE_HOST_MODEL &&
def->mode != VIR_CPU_MODE_HOST_PASSTHROUGH &&
def->nfeatures) { def->nfeatures) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Non-empty feature list specified without CPU model")); _("Non-empty feature list specified without CPU model"));
...@@ -663,30 +660,32 @@ virCPUDefFormatBuf(virBufferPtr buf, ...@@ -663,30 +660,32 @@ virCPUDefFormatBuf(virBufferPtr buf,
virBufferAddLit(buf, "/>\n"); virBufferAddLit(buf, "/>\n");
} }
for (i = 0; formatModel && i < def->nfeatures; i++) { if (formatModel || def->mode == VIR_CPU_MODE_HOST_PASSTHROUGH) {
virCPUFeatureDefPtr feature = def->features + i; for (i = 0; i < def->nfeatures; i++) {
virCPUFeatureDefPtr feature = def->features + i;
if (!feature->name) { if (!feature->name) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s", virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("Missing CPU feature name")); _("Missing CPU feature name"));
return -1; return -1;
} }
if (def->type == VIR_CPU_TYPE_GUEST) { if (def->type == VIR_CPU_TYPE_GUEST) {
const char *policy; const char *policy;
policy = virCPUFeaturePolicyTypeToString(feature->policy); policy = virCPUFeaturePolicyTypeToString(feature->policy);
if (!policy) { if (!policy) {
virReportError(VIR_ERR_INTERNAL_ERROR, virReportError(VIR_ERR_INTERNAL_ERROR,
_("Unexpected CPU feature policy %d"), _("Unexpected CPU feature policy %d"),
feature->policy); feature->policy);
return -1; return -1;
}
virBufferAsprintf(buf, "<feature policy='%s' name='%s'/>\n",
policy, feature->name);
} else {
virBufferAsprintf(buf, "<feature name='%s'/>\n",
feature->name);
} }
virBufferAsprintf(buf, "<feature policy='%s' name='%s'/>\n",
policy, feature->name);
} else {
virBufferAsprintf(buf, "<feature name='%s'/>\n",
feature->name);
} }
} }
......
...@@ -6115,6 +6115,7 @@ qemuBuildCpuModelArgStr(virQEMUDriverPtr driver, ...@@ -6115,6 +6115,7 @@ qemuBuildCpuModelArgStr(virQEMUDriverPtr driver,
virCPUDefPtr host = NULL; virCPUDefPtr host = NULL;
virCPUDefPtr guest = NULL; virCPUDefPtr guest = NULL;
virCPUDefPtr cpu = NULL; virCPUDefPtr cpu = NULL;
virCPUDefPtr featCpu = NULL;
size_t ncpus = 0; size_t ncpus = 0;
char **cpus = NULL; char **cpus = NULL;
virCPUDataPtr data = NULL; virCPUDataPtr data = NULL;
...@@ -6122,8 +6123,9 @@ qemuBuildCpuModelArgStr(virQEMUDriverPtr driver, ...@@ -6122,8 +6123,9 @@ qemuBuildCpuModelArgStr(virQEMUDriverPtr driver,
virCPUCompareResult cmp; virCPUCompareResult cmp;
const char *preferred; const char *preferred;
virCapsPtr caps = NULL; virCapsPtr caps = NULL;
bool compareAgainstHost = (def->virtType == VIR_DOMAIN_VIRT_KVM || bool compareAgainstHost = ((def->virtType == VIR_DOMAIN_VIRT_KVM ||
def->cpu->mode != VIR_CPU_MODE_CUSTOM); def->cpu->mode != VIR_CPU_MODE_CUSTOM) &&
def->cpu->mode != VIR_CPU_MODE_HOST_PASSTHROUGH);
if (!(caps = virQEMUDriverGetCapabilities(driver, false))) if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
goto cleanup; goto cleanup;
...@@ -6141,7 +6143,7 @@ qemuBuildCpuModelArgStr(virQEMUDriverPtr driver, ...@@ -6141,7 +6143,7 @@ qemuBuildCpuModelArgStr(virQEMUDriverPtr driver,
if (!(cpu = virCPUDefCopy(def->cpu))) if (!(cpu = virCPUDefCopy(def->cpu)))
goto cleanup; goto cleanup;
if (cpu->mode != VIR_CPU_MODE_CUSTOM && if (cpu->mode == VIR_CPU_MODE_HOST_MODEL &&
!migrating && !migrating &&
cpuUpdate(cpu, host) < 0) cpuUpdate(cpu, host) < 0)
goto cleanup; goto cleanup;
...@@ -6200,6 +6202,8 @@ qemuBuildCpuModelArgStr(virQEMUDriverPtr driver, ...@@ -6200,6 +6202,8 @@ qemuBuildCpuModelArgStr(virQEMUDriverPtr driver,
if (ARCH_IS_PPC64(def->os.arch) && if (ARCH_IS_PPC64(def->os.arch) &&
cpu->mode == VIR_CPU_MODE_HOST_MODEL) { cpu->mode == VIR_CPU_MODE_HOST_MODEL) {
virBufferAsprintf(buf, ",compat=%s", def->cpu->model); virBufferAsprintf(buf, ",compat=%s", def->cpu->model);
} else {
featCpu = cpu;
} }
} else { } else {
...@@ -6225,18 +6229,21 @@ qemuBuildCpuModelArgStr(virQEMUDriverPtr driver, ...@@ -6225,18 +6229,21 @@ qemuBuildCpuModelArgStr(virQEMUDriverPtr driver,
if (VIR_STRDUP(guest->model, cpu->model) < 0) if (VIR_STRDUP(guest->model, cpu->model) < 0)
goto cleanup; goto cleanup;
} }
virBufferAdd(buf, guest->model, -1); virBufferAdd(buf, guest->model, -1);
if (guest->vendor_id) if (guest->vendor_id)
virBufferAsprintf(buf, ",vendor=%s", guest->vendor_id); virBufferAsprintf(buf, ",vendor=%s", guest->vendor_id);
for (i = 0; i < guest->nfeatures; i++) { featCpu = guest;
}
if (featCpu) {
for (i = 0; i < featCpu->nfeatures; i++) {
char sign; char sign;
if (guest->features[i].policy == VIR_CPU_FEATURE_DISABLE) if (featCpu->features[i].policy == VIR_CPU_FEATURE_DISABLE)
sign = '-'; sign = '-';
else else
sign = '+'; sign = '+';
virBufferAsprintf(buf, ",%c%s", sign, guest->features[i].name); virBufferAsprintf(buf, ",%c%s", sign, featCpu->features[i].name);
} }
} }
......
...@@ -8,7 +8,7 @@ IO_DRV=none \ ...@@ -8,7 +8,7 @@ IO_DRV=none \
/usr/bin/qemu \ /usr/bin/qemu \
-S \ -S \
-M pc \ -M pc \
-cpu host \ -cpu host,+abm,+ds,-invtsc \
-m 214 \ -m 214 \
-smp 1 \ -smp 1 \
-nographic \ -nographic \
......
...@@ -15,26 +15,8 @@ ...@@ -15,26 +15,8 @@
</os> </os>
<cpu mode='host-passthrough'> <cpu mode='host-passthrough'>
<feature policy='require' name='abm'/> <feature policy='require' name='abm'/>
<feature policy='require' name='pdpe1gb'/> <feature policy='force' name='ds'/>
<feature policy='require' name='rdrand'/> <feature policy='disable' name='invtsc'/>
<feature policy='require' name='f16c'/>
<feature policy='require' name='osxsave'/>
<feature policy='require' name='pdcm'/>
<feature policy='require' name='xtpr'/>
<feature policy='require' name='tm2'/>
<feature policy='require' name='est'/>
<feature policy='require' name='smx'/>
<feature policy='require' name='vmx'/>
<feature policy='require' name='ds_cpl'/>
<feature policy='require' name='monitor'/>
<feature policy='require' name='dtes64'/>
<feature policy='require' name='pbe'/>
<feature policy='require' name='tm'/>
<feature policy='require' name='ht'/>
<feature policy='require' name='ss'/>
<feature policy='require' name='acpi'/>
<feature policy='require' name='ds'/>
<feature policy='require' name='vme'/>
</cpu> </cpu>
<clock offset='utc'/> <clock offset='utc'/>
<on_poweroff>destroy</on_poweroff> <on_poweroff>destroy</on_poweroff>
......
...@@ -1524,7 +1524,7 @@ mymain(void) ...@@ -1524,7 +1524,7 @@ mymain(void)
DO_TEST_FAILURE("shmem-small-size", QEMU_CAPS_PCIDEVICE, DO_TEST_FAILURE("shmem-small-size", QEMU_CAPS_PCIDEVICE,
QEMU_CAPS_DEVICE, QEMU_CAPS_DEVICE_IVSHMEM); QEMU_CAPS_DEVICE, QEMU_CAPS_DEVICE_IVSHMEM);
DO_TEST_PARSE_ERROR("shmem-msi-only", NONE); DO_TEST_PARSE_ERROR("shmem-msi-only", NONE);
DO_TEST("cpu-host-passthrough-features-invalid", QEMU_CAPS_KVM, QEMU_CAPS_CPU_HOST); DO_TEST("cpu-host-passthrough-features", QEMU_CAPS_KVM, QEMU_CAPS_CPU_HOST);
virObjectUnref(driver.config); virObjectUnref(driver.config);
virObjectUnref(driver.caps); virObjectUnref(driver.caps);
......
...@@ -184,6 +184,7 @@ mymain(void) ...@@ -184,6 +184,7 @@ mymain(void)
DO_TEST("clock-localtime"); DO_TEST("clock-localtime");
DO_TEST("cpu-kvmclock"); DO_TEST("cpu-kvmclock");
DO_TEST("cpu-host-kvmclock"); DO_TEST("cpu-host-kvmclock");
DO_TEST("cpu-host-passthrough-features");
DO_TEST("clock-catchup"); DO_TEST("clock-catchup");
DO_TEST("kvmclock"); DO_TEST("kvmclock");
DO_TEST("clock-timer-hyperv-rtc"); DO_TEST("clock-timer-hyperv-rtc");
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册