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:
parent
f7a30375bd
commit
adff345e1e
@ -982,6 +982,7 @@
|
|||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
<cpu mode='host-passthrough'/>
|
<cpu mode='host-passthrough'/>
|
||||||
|
<feature policy='disable' name='lahf_lm'/>
|
||||||
...</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>
|
||||||
|
@ -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>
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 @@
|
|||||||
</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)
|
|||||||
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)
|
|||||||
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");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user