From adff345e1ec9a6f528731ae40168a76b8e7620e0 Mon Sep 17 00:00:00 2001 From: Martin Kletzander Date: Mon, 5 Jan 2015 17:03:58 +0100 Subject: [PATCH] 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 --- docs/formatdomain.html.in | 5 +- docs/schemas/domaincommon.rng | 67 +++++++------------ src/conf/cpu_conf.c | 53 +++++++-------- src/qemu/qemu_command.c | 21 ++++-- ...l2argv-cpu-host-passthrough-features.args} | 2 +- ...ml2argv-cpu-host-passthrough-features.xml} | 22 +----- tests/qemuxml2argvtest.c | 2 +- tests/qemuxml2xmltest.c | 1 + 8 files changed, 71 insertions(+), 102 deletions(-) rename tests/qemuxml2argvdata/{qemuxml2argv-cpu-host-passthrough-features-invalid.args => qemuxml2argv-cpu-host-passthrough-features.args} (91%) rename tests/qemuxml2argvdata/{qemuxml2argv-cpu-host-passthrough-features-invalid.xml => qemuxml2argv-cpu-host-passthrough-features.xml} (57%) diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 0df2b76ee4..0c3343e288 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -982,6 +982,7 @@
   <cpu mode='host-passthrough'/>
+    <feature policy='disable' name='lahf_lm'/>
   ...

@@ -1083,8 +1084,8 @@ 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 environment cannot be reproduced on different hardware. Thus, if you - hit any bugs, you are on your own. Neither model nor - feature elements are allowed in this mode. + hit any bugs, you are on your own. Further details of that CPU can + be changed using feature elements. In both host-model and host-passthrough diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 879e064250..85b3709759 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -4088,50 +4088,29 @@ --> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/conf/cpu_conf.c b/src/conf/cpu_conf.c index 3af0f443c1..31fb458839 100644 --- a/src/conf/cpu_conf.c +++ b/src/conf/cpu_conf.c @@ -1,7 +1,7 @@ /* * 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 * modify it under the terms of the GNU Lesser General Public @@ -366,12 +366,8 @@ virCPUDefParseXML(xmlNodePtr node, goto error; if (n > 0) { - if (!def->model && def->mode == VIR_CPU_MODE_HOST_PASSTHROUGH) { - /* silently ignore incorrectly formatted features generated - * by older libvirt */ - goto cleanup; - } - if (!def->model && def->mode != VIR_CPU_MODE_HOST_MODEL) { + if (!def->model && def->mode != VIR_CPU_MODE_HOST_MODEL && + def->mode != VIR_CPU_MODE_HOST_PASSTHROUGH) { virReportError(VIR_ERR_XML_ERROR, "%s", _("Non-empty feature list specified without " "CPU model")); @@ -623,6 +619,7 @@ virCPUDefFormatBuf(virBufferPtr buf, if (!def->model && def->mode != VIR_CPU_MODE_HOST_MODEL && + def->mode != VIR_CPU_MODE_HOST_PASSTHROUGH && def->nfeatures) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Non-empty feature list specified without CPU model")); @@ -663,30 +660,32 @@ virCPUDefFormatBuf(virBufferPtr buf, virBufferAddLit(buf, "/>\n"); } - for (i = 0; formatModel && i < def->nfeatures; i++) { - virCPUFeatureDefPtr feature = def->features + i; + if (formatModel || def->mode == VIR_CPU_MODE_HOST_PASSTHROUGH) { + for (i = 0; i < def->nfeatures; i++) { + virCPUFeatureDefPtr feature = def->features + i; - if (!feature->name) { - virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("Missing CPU feature name")); - return -1; - } + if (!feature->name) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("Missing CPU feature name")); + return -1; + } - if (def->type == VIR_CPU_TYPE_GUEST) { - const char *policy; + 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; + policy = virCPUFeaturePolicyTypeToString(feature->policy); + if (!policy) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Unexpected CPU feature policy %d"), + feature->policy); + return -1; + } + virBufferAsprintf(buf, "\n", + policy, feature->name); + } else { + virBufferAsprintf(buf, "\n", + feature->name); } - virBufferAsprintf(buf, "\n", - policy, feature->name); - } else { - virBufferAsprintf(buf, "\n", - feature->name); } } diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index 101b88af48..3346e95e1d 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -6115,6 +6115,7 @@ qemuBuildCpuModelArgStr(virQEMUDriverPtr driver, virCPUDefPtr host = NULL; virCPUDefPtr guest = NULL; virCPUDefPtr cpu = NULL; + virCPUDefPtr featCpu = NULL; size_t ncpus = 0; char **cpus = NULL; virCPUDataPtr data = NULL; @@ -6122,8 +6123,9 @@ qemuBuildCpuModelArgStr(virQEMUDriverPtr driver, virCPUCompareResult cmp; const char *preferred; virCapsPtr caps = NULL; - bool compareAgainstHost = (def->virtType == VIR_DOMAIN_VIRT_KVM || - def->cpu->mode != VIR_CPU_MODE_CUSTOM); + bool compareAgainstHost = ((def->virtType == VIR_DOMAIN_VIRT_KVM || + def->cpu->mode != VIR_CPU_MODE_CUSTOM) && + def->cpu->mode != VIR_CPU_MODE_HOST_PASSTHROUGH); if (!(caps = virQEMUDriverGetCapabilities(driver, false))) goto cleanup; @@ -6141,7 +6143,7 @@ qemuBuildCpuModelArgStr(virQEMUDriverPtr driver, if (!(cpu = virCPUDefCopy(def->cpu))) goto cleanup; - if (cpu->mode != VIR_CPU_MODE_CUSTOM && + if (cpu->mode == VIR_CPU_MODE_HOST_MODEL && !migrating && cpuUpdate(cpu, host) < 0) goto cleanup; @@ -6200,6 +6202,8 @@ qemuBuildCpuModelArgStr(virQEMUDriverPtr driver, if (ARCH_IS_PPC64(def->os.arch) && cpu->mode == VIR_CPU_MODE_HOST_MODEL) { virBufferAsprintf(buf, ",compat=%s", def->cpu->model); + } else { + featCpu = cpu; } } else { @@ -6225,18 +6229,21 @@ qemuBuildCpuModelArgStr(virQEMUDriverPtr driver, if (VIR_STRDUP(guest->model, cpu->model) < 0) goto cleanup; } - virBufferAdd(buf, guest->model, -1); if (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; - if (guest->features[i].policy == VIR_CPU_FEATURE_DISABLE) + if (featCpu->features[i].policy == VIR_CPU_FEATURE_DISABLE) sign = '-'; else sign = '+'; - virBufferAsprintf(buf, ",%c%s", sign, guest->features[i].name); + virBufferAsprintf(buf, ",%c%s", sign, featCpu->features[i].name); } } diff --git a/tests/qemuxml2argvdata/qemuxml2argv-cpu-host-passthrough-features-invalid.args b/tests/qemuxml2argvdata/qemuxml2argv-cpu-host-passthrough-features.args similarity index 91% rename from tests/qemuxml2argvdata/qemuxml2argv-cpu-host-passthrough-features-invalid.args rename to tests/qemuxml2argvdata/qemuxml2argv-cpu-host-passthrough-features.args index 18c1dce084..88a25bf432 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-cpu-host-passthrough-features-invalid.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-cpu-host-passthrough-features.args @@ -8,7 +8,7 @@ IO_DRV=none \ /usr/bin/qemu \ -S \ -M pc \ --cpu host \ +-cpu host,+abm,+ds,-invtsc \ -m 214 \ -smp 1 \ -nographic \ diff --git a/tests/qemuxml2argvdata/qemuxml2argv-cpu-host-passthrough-features-invalid.xml b/tests/qemuxml2argvdata/qemuxml2argv-cpu-host-passthrough-features.xml similarity index 57% rename from tests/qemuxml2argvdata/qemuxml2argv-cpu-host-passthrough-features-invalid.xml rename to tests/qemuxml2argvdata/qemuxml2argv-cpu-host-passthrough-features.xml index b5f532643d..e807dbdeff 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-cpu-host-passthrough-features-invalid.xml +++ b/tests/qemuxml2argvdata/qemuxml2argv-cpu-host-passthrough-features.xml @@ -15,26 +15,8 @@ - - - - - - - - - - - - - - - - - - - - + + destroy diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index bce88a84a9..1d0bd611d6 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -1524,7 +1524,7 @@ mymain(void) DO_TEST_FAILURE("shmem-small-size", QEMU_CAPS_PCIDEVICE, QEMU_CAPS_DEVICE, QEMU_CAPS_DEVICE_IVSHMEM); 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.caps); diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index e1ec514b1e..1166534d0e 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -184,6 +184,7 @@ mymain(void) DO_TEST("clock-localtime"); DO_TEST("cpu-kvmclock"); DO_TEST("cpu-host-kvmclock"); + DO_TEST("cpu-host-passthrough-features"); DO_TEST("clock-catchup"); DO_TEST("kvmclock"); DO_TEST("clock-timer-hyperv-rtc"); -- 2.39.5