1
0
mirror of https://gitlab.com/libvirt/libvirt.git synced 2025-02-02 13:47:13 +03:00

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=1178850

Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
This commit is contained in:
Martin Kletzander 2015-01-05 17:03:58 +01:00
parent f7a30375bd
commit adff345e1e
8 changed files with 72 additions and 103 deletions

View File

@ -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 @@
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>

View File

@ -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>

View File

@ -1,7 +1,7 @@
/* /*
* 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,
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,
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,
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;
}
if (def->type == VIR_CPU_TYPE_GUEST) {
const char *policy;
policy = virCPUFeaturePolicyTypeToString(feature->policy);
if (!policy) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Unexpected CPU feature policy %d"),
feature->policy);
return -1; return -1;
} }
virBufferAsprintf(buf, "<feature policy='%s' name='%s'/>\n",
policy, feature->name); if (def->type == VIR_CPU_TYPE_GUEST) {
} else { const char *policy;
virBufferAsprintf(buf, "<feature name='%s'/>\n",
feature->name); policy = virCPUFeaturePolicyTypeToString(feature->policy);
if (!policy) {
virReportError(VIR_ERR_INTERNAL_ERROR,
_("Unexpected CPU feature policy %d"),
feature->policy);
return -1;
}
virBufferAsprintf(buf, "<feature policy='%s' name='%s'/>\n",
policy, feature->name);
} else {
virBufferAsprintf(buf, "<feature name='%s'/>\n",
feature->name);
}
} }
} }

View File

@ -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,
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,
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,
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,
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);
} }
} }

View File

@ -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 \

View File

@ -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>

View File

@ -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);

View File

@ -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");