diff --git a/0001-tests-Check-default-GIC-version-for-aarch64-virt-TCG.patch b/0001-tests-Check-default-GIC-version-for-aarch64-virt-TCG.patch index 3a94b1b..381e6cb 100644 --- a/0001-tests-Check-default-GIC-version-for-aarch64-virt-TCG.patch +++ b/0001-tests-Check-default-GIC-version-for-aarch64-virt-TCG.patch @@ -17,7 +17,7 @@ Signed-off-by: Andrea Bolognani diff --git a/tests/qemuxml2argvdata/qemuxml2argv-aarch64-gic-none-tcg.args b/tests/qemuxml2argvdata/qemuxml2argv-aarch64-gic-none-tcg.args new file mode 100644 -index 0000000..975a014 +index 000000000..975a01481 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-aarch64-gic-none-tcg.args @@ -0,0 +1,19 @@ @@ -42,7 +42,7 @@ index 0000000..975a014 +-boot c diff --git a/tests/qemuxml2argvdata/qemuxml2argv-aarch64-gic-none-tcg.xml b/tests/qemuxml2argvdata/qemuxml2argv-aarch64-gic-none-tcg.xml new file mode 100644 -index 0000000..0aa33db +index 000000000..0aa33dbec --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-aarch64-gic-none-tcg.xml @@ -0,0 +1,17 @@ @@ -64,10 +64,10 @@ index 0000000..0aa33db + + diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c -index 41461ea..a630c3b 100644 +index cc4fb91cd..362b140ac 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c -@@ -2247,6 +2247,9 @@ mymain(void) +@@ -2250,6 +2250,9 @@ mymain(void) DO_TEST_GIC("aarch64-gic-none-both", GIC_BOTH, QEMU_CAPS_KVM, QEMU_CAPS_MACHINE_OPT, QEMU_CAPS_MACH_VIRT_GIC_VERSION); @@ -79,7 +79,7 @@ index 41461ea..a630c3b 100644 DO_TEST_GIC("aarch64-gic-default", GIC_NONE, diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-aarch64-gic-none-tcg.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-aarch64-gic-none-tcg.xml new file mode 100644 -index 0000000..69510e2 +index 000000000..69510e281 --- /dev/null +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-aarch64-gic-none-tcg.xml @@ -0,0 +1,25 @@ @@ -109,7 +109,7 @@ index 0000000..69510e2 + + diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c -index eae999d..aae632a 100644 +index eae999dd6..aae632afe 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -1073,6 +1073,7 @@ mymain(void) diff --git a/0002-qemu-Use-GICv2-for-aarch64-virt-TCG-guests.patch b/0002-qemu-Use-GICv2-for-aarch64-virt-TCG-guests.patch index 5206dc4..d46b273 100644 --- a/0002-qemu-Use-GICv2-for-aarch64-virt-TCG-guests.patch +++ b/0002-qemu-Use-GICv2-for-aarch64-virt-TCG-guests.patch @@ -16,7 +16,7 @@ Signed-off-by: Andrea Bolognani 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c -index 589eb18..891f825 100644 +index 589eb1889..891f8258a 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -2527,6 +2527,24 @@ qemuDomainDefEnableDefaultFeatures(virDomainDefPtr def, @@ -58,7 +58,7 @@ index 589eb18..891f825 100644 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-aarch64-gic-none-tcg.args b/tests/qemuxml2argvdata/qemuxml2argv-aarch64-gic-none-tcg.args -index 975a014..52b6996 100644 +index 975a01481..52b699696 100644 --- a/tests/qemuxml2argvdata/qemuxml2argv-aarch64-gic-none-tcg.args +++ b/tests/qemuxml2argvdata/qemuxml2argv-aarch64-gic-none-tcg.args @@ -7,7 +7,7 @@ QEMU_AUDIO_DRV=none \ @@ -71,7 +71,7 @@ index 975a014..52b6996 100644 -m 1024 \ -smp 1,sockets=1,cores=1,threads=1 \ diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-aarch64-gic-none-tcg.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-aarch64-gic-none-tcg.xml -index 69510e2..a0cd0b7 100644 +index 69510e281..a0cd0b768 100644 --- a/tests/qemuxml2xmloutdata/qemuxml2xmlout-aarch64-gic-none-tcg.xml +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-aarch64-gic-none-tcg.xml @@ -9,7 +9,7 @@ diff --git a/0003-gic-Remove-VIR_GIC_VERSION_DEFAULT.patch b/0003-gic-Remove-VIR_GIC_VERSION_DEFAULT.patch index ed115c0..569842c 100644 --- a/0003-gic-Remove-VIR_GIC_VERSION_DEFAULT.patch +++ b/0003-gic-Remove-VIR_GIC_VERSION_DEFAULT.patch @@ -15,10 +15,10 @@ Signed-off-by: Andrea Bolognani 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c -index 64d2d71..188e273 100644 +index 2d1328cf9..5feddc523 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c -@@ -7317,9 +7317,9 @@ qemuBuildMachineCommandLine(virCommandPtr cmd, +@@ -7321,9 +7321,9 @@ qemuBuildMachineCommandLine(virCommandPtr cmd, goto cleanup; } @@ -32,7 +32,7 @@ index 64d2d71..188e273 100644 QEMU_CAPS_MACH_VIRT_GIC_VERSION)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c -index 891f825..4a127ce 100644 +index 891f8258a..4a127cedf 100644 --- a/src/qemu/qemu_domain.c +++ b/src/qemu/qemu_domain.c @@ -2560,12 +2560,11 @@ qemuDomainDefEnableDefaultFeatures(virDomainDefPtr def, @@ -52,7 +52,7 @@ index 891f825..4a127ce 100644 } diff --git a/src/util/virgic.h b/src/util/virgic.h -index 1c9efd6..2d77fdd 100644 +index 1c9efd60f..2d77fdd45 100644 --- a/src/util/virgic.h +++ b/src/util/virgic.h @@ -35,9 +35,6 @@ typedef enum { diff --git a/0004-daemon-Don-t-run-if-in-a-Fedora-live-environment.patch b/0004-daemon-Don-t-run-if-in-a-Fedora-live-VM.patch similarity index 82% rename from 0004-daemon-Don-t-run-if-in-a-Fedora-live-environment.patch rename to 0004-daemon-Don-t-run-if-in-a-Fedora-live-VM.patch index f56268c..76e9673 100644 --- a/0004-daemon-Don-t-run-if-in-a-Fedora-live-environment.patch +++ b/0004-daemon-Don-t-run-if-in-a-Fedora-live-VM.patch @@ -1,5 +1,3 @@ -From d76701a6abf42d2e2cd94a6ef33f83965432bb21 Mon Sep 17 00:00:00 2001 -Message-Id: From: Cole Robinson Date: Tue, 30 May 2017 18:35:04 -0400 Subject: [PATCH] daemon: Don't run if in a Fedora live VM @@ -14,14 +12,12 @@ of the livecd running in a VM https://bugzilla.redhat.com/show_bug.cgi?id=1146232 Not upstream, will likely need some kind of different permanent solution - -Signed-off-by: Cole Robinson --- daemon/libvirtd.service.in | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/daemon/libvirtd.service.in b/daemon/libvirtd.service.in -index 899abdf..7836e94 100644 +index fbaf02f3b..86ee988fa 100644 --- a/daemon/libvirtd.service.in +++ b/daemon/libvirtd.service.in @@ -16,6 +16,12 @@ After=local-fs.target @@ -37,6 +33,3 @@ index 899abdf..7836e94 100644 [Service] Type=notify --- -2.9.4 - diff --git a/0005-Revert-qemu-propagate-bridge-MTU-into-qemu-host_mtu-.patch b/0005-Revert-qemu-propagate-bridge-MTU-into-qemu-host_mtu-.patch new file mode 100644 index 0000000..c21fa4b --- /dev/null +++ b/0005-Revert-qemu-propagate-bridge-MTU-into-qemu-host_mtu-.patch @@ -0,0 +1,198 @@ +From: Laine Stump +Date: Thu, 18 May 2017 14:16:27 -0400 +Subject: [PATCH] Revert "qemu: propagate bridge MTU into qemu "host_mtu" + option" + +This reverts commit 2841e675. + +It turns out that adding the host_mtu field to the PCI capabilities in +the guest bumps the length of PCI capabilities beyond the 32 byte +boundary, so the virtio-net device gets 64 bytes of ioport space +instead of 32, which offsets the address of all the other following +devices. Migration doesn't work very well when the location and length +of PCI capabilities of devices is changed between source and +destination. + +This means that we need to make sure that the absence/presence of +host_mtu on the qemu commandline always matches between source and +destination, which means that we need to make setting of host_mtu an +opt-in thing (it can't happen automatically when the bridge being used +has a non-default MTU, which is what commit 2841e675 implemented). + +I do want to re-implement this feature with an +setting, but probably won't backport that to any stable branches, so +I'm first reverting the original commit, and that revert can be pushed +to the few releases that have been made since the original (3.1.0 - +3.3.0) + +Resolves: https://bugzilla.redhat.com/1449346 +(cherry picked from commit 77780a29edace958a1f931d3281b962be4f5290e) +(cherry picked from commit a2f5e87dceb1725c16cd4df17a4b7381ecf65901) +--- + src/qemu/qemu_command.c | 32 ++++++++++---------------------- + src/qemu/qemu_command.h | 3 +-- + src/qemu/qemu_hotplug.c | 5 ++--- + src/qemu/qemu_interface.c | 5 ++--- + src/qemu/qemu_interface.h | 3 +-- + 5 files changed, 16 insertions(+), 32 deletions(-) + +diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c +index 5feddc523..3abfe7b55 100644 +--- a/src/qemu/qemu_command.c ++++ b/src/qemu/qemu_command.c +@@ -3629,8 +3629,7 @@ qemuBuildNicDevStr(virDomainDefPtr def, + int vlan, + unsigned int bootindex, + size_t vhostfdSize, +- virQEMUCapsPtr qemuCaps, +- unsigned int mtu) ++ virQEMUCapsPtr qemuCaps) + { + virBuffer buf = VIR_BUFFER_INITIALIZER; + const char *nic = net->model; +@@ -3754,23 +3753,13 @@ qemuBuildNicDevStr(virDomainDefPtr def, + virBufferAsprintf(&buf, ",rx_queue_size=%u", net->driver.virtio.rx_queue_size); + } + +- if (usingVirtio && mtu) { +- if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_NET_HOST_MTU)) { +- +- virBufferAsprintf(&buf, ",host_mtu=%u", mtu); +- +- } else { +- /* log an error if mtu was requested specifically for this +- * interface, otherwise, if it's just what was reported by +- * the attached network, ignore it. +- */ +- if (net->mtu) { +- virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", +- _("setting MTU is not supported with " +- "this QEMU binary")); +- goto error; +- } ++ if (usingVirtio && net->mtu) { ++ if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_VIRTIO_NET_HOST_MTU)) { ++ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", ++ _("setting MTU is not supported with this QEMU binary")); ++ goto error; + } ++ virBufferAsprintf(&buf, ",host_mtu=%u", net->mtu); + } + + if (vlan == -1) +@@ -8213,7 +8202,7 @@ qemuBuildVhostuserCommandLine(virQEMUDriverPtr driver, + VIR_FREE(netdev); + + if (!(nic = qemuBuildNicDevStr(def, net, -1, bootindex, +- queues, qemuCaps, net->mtu))) { ++ queues, qemuCaps))) { + virReportError(VIR_ERR_INTERNAL_ERROR, + "%s", _("Error generating NIC -device string")); + goto error; +@@ -8259,7 +8248,6 @@ qemuBuildInterfaceCommandLine(virQEMUDriverPtr driver, + virDomainNetType actualType = virDomainNetGetActualType(net); + virNetDevBandwidthPtr actualBandwidth; + size_t i; +- unsigned int mtu = net->mtu; + + + if (!bootindex) +@@ -8314,7 +8302,7 @@ qemuBuildInterfaceCommandLine(virQEMUDriverPtr driver, + memset(tapfd, -1, tapfdSize * sizeof(tapfd[0])); + + if (qemuInterfaceBridgeConnect(def, driver, net, +- tapfd, &tapfdSize, &mtu) < 0) ++ tapfd, &tapfdSize) < 0) + goto cleanup; + break; + +@@ -8494,7 +8482,7 @@ qemuBuildInterfaceCommandLine(virQEMUDriverPtr driver, + } + if (qemuDomainSupportsNicdev(def, net)) { + if (!(nic = qemuBuildNicDevStr(def, net, vlan, bootindex, +- vhostfdSize, qemuCaps, mtu))) ++ vhostfdSize, qemuCaps))) + goto cleanup; + virCommandAddArgList(cmd, "-device", nic, NULL); + } else { +diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h +index 7da92c8c9..09cb00ee9 100644 +--- a/src/qemu/qemu_command.h ++++ b/src/qemu/qemu_command.h +@@ -101,8 +101,7 @@ char *qemuBuildNicDevStr(virDomainDefPtr def, + int vlan, + unsigned int bootindex, + size_t vhostfdSize, +- virQEMUCapsPtr qemuCaps, +- unsigned int mtu); ++ virQEMUCapsPtr qemuCaps); + + char *qemuDeviceDriveHostAlias(virDomainDiskDefPtr disk); + +diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c +index f133d04a8..2a4159560 100644 +--- a/src/qemu/qemu_hotplug.c ++++ b/src/qemu/qemu_hotplug.c +@@ -968,7 +968,6 @@ qemuDomainAttachNetDevice(virQEMUDriverPtr driver, + bool charDevPlugged = false; + bool netdevPlugged = false; + bool hostPlugged = false; +- unsigned int mtu = net->mtu; + + /* preallocate new slot for device */ + if (VIR_REALLOC_N(vm->def->nets, vm->def->nnets + 1) < 0) +@@ -1025,7 +1024,7 @@ qemuDomainAttachNetDevice(virQEMUDriverPtr driver, + goto cleanup; + memset(vhostfd, -1, sizeof(*vhostfd) * vhostfdSize); + if (qemuInterfaceBridgeConnect(vm->def, driver, net, +- tapfd, &tapfdSize, &mtu) < 0) ++ tapfd, &tapfdSize) < 0) + goto cleanup; + iface_connected = true; + if (qemuInterfaceOpenVhostNet(vm->def, net, priv->qemuCaps, +@@ -1239,7 +1238,7 @@ qemuDomainAttachNetDevice(virQEMUDriverPtr driver, + VIR_FORCE_CLOSE(vhostfd[i]); + + if (!(nicstr = qemuBuildNicDevStr(vm->def, net, vlan, 0, +- queueSize, priv->qemuCaps, mtu))) ++ queueSize, priv->qemuCaps))) + goto try_remove; + + qemuDomainObjEnterMonitor(driver, vm); +diff --git a/src/qemu/qemu_interface.c b/src/qemu/qemu_interface.c +index c5dca60f1..ce448d243 100644 +--- a/src/qemu/qemu_interface.c ++++ b/src/qemu/qemu_interface.c +@@ -503,8 +503,7 @@ qemuInterfaceBridgeConnect(virDomainDefPtr def, + virQEMUDriverPtr driver, + virDomainNetDefPtr net, + int *tapfd, +- size_t *tapfdSize, +- unsigned int *mtu) ++ size_t *tapfdSize) + { + const char *brname; + int ret = -1; +@@ -545,7 +544,7 @@ qemuInterfaceBridgeConnect(virDomainDefPtr def, + def->uuid, tunpath, tapfd, *tapfdSize, + virDomainNetGetActualVirtPortProfile(net), + virDomainNetGetActualVlan(net), +- net->mtu, mtu, ++ 0, NULL, + tap_create_flags) < 0) { + virDomainAuditNetDevice(def, net, tunpath, false); + goto cleanup; +diff --git a/src/qemu/qemu_interface.h b/src/qemu/qemu_interface.h +index ba74ac2cf..a7faa0b3d 100644 +--- a/src/qemu/qemu_interface.h ++++ b/src/qemu/qemu_interface.h +@@ -51,8 +51,7 @@ int qemuInterfaceBridgeConnect(virDomainDefPtr def, + virQEMUDriverPtr driver, + virDomainNetDefPtr net, + int *tapfd, +- size_t *tapfdSize, +- unsigned int *mtu) ++ size_t *tapfdSize) + ATTRIBUTE_NONNULL(2); + + int qemuInterfaceOpenVhostNet(virDomainDefPtr def, diff --git a/0006-cpu-Introduce-virCPUCopyMigratable.patch b/0006-cpu-Introduce-virCPUCopyMigratable.patch new file mode 100644 index 0000000..02d0787 --- /dev/null +++ b/0006-cpu-Introduce-virCPUCopyMigratable.patch @@ -0,0 +1,145 @@ +From: Jiri Denemark +Date: Wed, 29 Mar 2017 14:45:44 +0200 +Subject: [PATCH] cpu: Introduce virCPUCopyMigratable + +This new internal API makes a copy of virCPUDef while removing all +features which would block migration. It uses cpu_map.xml as a database +of such features, which should only be used as a fallback when we cannot +get the data from a hypervisor. The main goal of this API is to decouple +this filtering from virCPUUpdate so that the hypervisor driver can +filter the features according to the hypervisor. + +Signed-off-by: Jiri Denemark +(cherry picked from commit 05e91c79f19e0be96526098d58a3498dac3f8529) +--- + src/cpu/cpu.c | 31 +++++++++++++++++++++++++++++++ + src/cpu/cpu.h | 8 ++++++++ + src/cpu/cpu_x86.c | 25 +++++++++++++++++++++++++ + src/libvirt_private.syms | 1 + + 4 files changed, 65 insertions(+) + +diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c +index 93647a2ed..8a407ac18 100644 +--- a/src/cpu/cpu.c ++++ b/src/cpu/cpu.c +@@ -1130,3 +1130,34 @@ virCPUExpandFeatures(virArch arch, + VIR_DEBUG("nfeatures=%zu", cpu->nfeatures); + return 0; + } ++ ++ ++/** ++ * virCPUCopyMigratable: ++ * ++ * @arch: CPU architecture ++ * @cpu: CPU definition to be copied ++ * ++ * Makes a copy of @cpu with all features which would block migration removed. ++ * If this doesn't make sense for a given architecture, the function returns a ++ * plain copy of @cpu (i.e., a copy with no features removed). ++ * ++ * Returns the copy of the CPU or NULL on error. ++ */ ++virCPUDefPtr ++virCPUCopyMigratable(virArch arch, ++ virCPUDefPtr cpu) ++{ ++ struct cpuArchDriver *driver; ++ ++ VIR_DEBUG("arch=%s, cpu=%p, model=%s", ++ virArchToString(arch), cpu, NULLSTR(cpu->model)); ++ ++ if (!(driver = cpuGetSubDriver(arch))) ++ return NULL; ++ ++ if (driver->copyMigratable) ++ return driver->copyMigratable(cpu); ++ else ++ return virCPUDefCopy(cpu); ++} +diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h +index 8c238ad55..352445c40 100644 +--- a/src/cpu/cpu.h ++++ b/src/cpu/cpu.h +@@ -118,6 +118,9 @@ typedef int + typedef int + (*virCPUArchExpandFeatures)(virCPUDefPtr cpu); + ++typedef virCPUDefPtr ++(*virCPUArchCopyMigratable)(virCPUDefPtr cpu); ++ + struct cpuArchDriver { + const char *name; + const virArch *arch; +@@ -138,6 +141,7 @@ struct cpuArchDriver { + virCPUArchTranslate translate; + virCPUArchConvertLegacy convertLegacy; + virCPUArchExpandFeatures expandFeatures; ++ virCPUArchCopyMigratable copyMigratable; + }; + + +@@ -254,6 +258,10 @@ int + virCPUExpandFeatures(virArch arch, + virCPUDefPtr cpu); + ++virCPUDefPtr ++virCPUCopyMigratable(virArch arch, ++ virCPUDefPtr cpu); ++ + /* virCPUDataFormat and virCPUDataParse are implemented for unit tests only and + * have no real-life usage + */ +diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c +index 48648a7f4..a771b251e 100644 +--- a/src/cpu/cpu_x86.c ++++ b/src/cpu/cpu_x86.c +@@ -2903,6 +2903,30 @@ virCPUx86ExpandFeatures(virCPUDefPtr cpu) + } + + ++static virCPUDefPtr ++virCPUx86CopyMigratable(virCPUDefPtr cpu) ++{ ++ virCPUDefPtr copy; ++ virCPUx86MapPtr map; ++ ++ if (!(map = virCPUx86GetMap())) ++ return NULL; ++ ++ if (!(copy = virCPUDefCopyWithoutModel(cpu))) ++ return NULL; ++ ++ if (virCPUDefCopyModelFilter(copy, cpu, false, ++ x86FeatureIsMigratable, map) < 0) ++ goto error; ++ ++ return copy; ++ ++ error: ++ virCPUDefFree(copy); ++ return NULL; ++} ++ ++ + int + virCPUx86DataAddCPUID(virCPUDataPtr cpuData, + const virCPUx86CPUID *cpuid) +@@ -2978,4 +3002,5 @@ struct cpuArchDriver cpuDriverX86 = { + .getModels = virCPUx86GetModels, + .translate = virCPUx86Translate, + .expandFeatures = virCPUx86ExpandFeatures, ++ .copyMigratable = virCPUx86CopyMigratable, + }; +diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms +index b551cb86a..dc6db3b28 100644 +--- a/src/libvirt_private.syms ++++ b/src/libvirt_private.syms +@@ -1016,6 +1016,7 @@ virCPUCheckFeature; + virCPUCompare; + virCPUCompareXML; + virCPUConvertLegacy; ++virCPUCopyMigratable; + virCPUDataCheckFeature; + virCPUDataFormat; + virCPUDataFree; diff --git a/0007-qemu-Move-common-code-in-virQEMUCapsInitCPUModel-one.patch b/0007-qemu-Move-common-code-in-virQEMUCapsInitCPUModel-one.patch new file mode 100644 index 0000000..ed4cfe6 --- /dev/null +++ b/0007-qemu-Move-common-code-in-virQEMUCapsInitCPUModel-one.patch @@ -0,0 +1,78 @@ +From: Jiri Denemark +Date: Thu, 30 Mar 2017 13:50:44 +0200 +Subject: [PATCH] qemu: Move common code in virQEMUCapsInitCPUModel one layer + up + +Signed-off-by: Jiri Denemark +(cherry picked from commit d84b93fad51b190238e18b1daac82ea6e28869e9) +--- + src/qemu/qemu_capabilities.c | 25 ++++++++++--------------- + 1 file changed, 10 insertions(+), 15 deletions(-) + +diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c +index b1245ad5d..1a15750a3 100644 +--- a/src/qemu/qemu_capabilities.c ++++ b/src/qemu/qemu_capabilities.c +@@ -3111,17 +3111,11 @@ virQEMUCapsCPUFilterFeatures(const char *name, + */ + static int + virQEMUCapsInitCPUModelS390(virQEMUCapsPtr qemuCaps, +- virDomainVirtType type, ++ qemuMonitorCPUModelInfoPtr modelInfo, + virCPUDefPtr cpu) + { +- qemuMonitorCPUModelInfoPtr modelInfo; + size_t i; + +- if (type == VIR_DOMAIN_VIRT_KVM) +- modelInfo = qemuCaps->kvmCPUModelInfo; +- else +- modelInfo = qemuCaps->tcgCPUModelInfo; +- + if (!modelInfo) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("missing host CPU model info from QEMU capabilities " +@@ -3163,9 +3157,9 @@ virQEMUCapsInitCPUModelS390(virQEMUCapsPtr qemuCaps, + static int + virQEMUCapsInitCPUModelX86(virQEMUCapsPtr qemuCaps, + virDomainVirtType type, ++ qemuMonitorCPUModelInfoPtr model, + virCPUDefPtr cpu) + { +- qemuMonitorCPUModelInfoPtr model; + virCPUDataPtr data = NULL; + unsigned long long sigFamily = 0; + unsigned long long sigModel = 0; +@@ -3174,11 +3168,6 @@ virQEMUCapsInitCPUModelX86(virQEMUCapsPtr qemuCaps, + int ret = -1; + size_t i; + +- if (type == VIR_DOMAIN_VIRT_KVM) +- model = qemuCaps->kvmCPUModelInfo; +- else +- model = qemuCaps->tcgCPUModelInfo; +- + if (!model) + return 1; + +@@ -3239,12 +3228,18 @@ virQEMUCapsInitCPUModel(virQEMUCapsPtr qemuCaps, + virDomainVirtType type, + virCPUDefPtr cpu) + { ++ qemuMonitorCPUModelInfoPtr model; + int ret = 1; + ++ if (type == VIR_DOMAIN_VIRT_KVM) ++ model = qemuCaps->kvmCPUModelInfo; ++ else ++ model = qemuCaps->tcgCPUModelInfo; ++ + if (ARCH_IS_S390(qemuCaps->arch)) +- ret = virQEMUCapsInitCPUModelS390(qemuCaps, type, cpu); ++ ret = virQEMUCapsInitCPUModelS390(qemuCaps, model, cpu); + else if (ARCH_IS_X86(qemuCaps->arch)) +- ret = virQEMUCapsInitCPUModelX86(qemuCaps, type, cpu); ++ ret = virQEMUCapsInitCPUModelX86(qemuCaps, type, model, cpu); + + if (ret == 0) + cpu->fallback = VIR_CPU_FALLBACK_FORBID; diff --git a/0008-qemu-Add-migratable-parameter-to-virQEMUCapsInitCPUM.patch b/0008-qemu-Add-migratable-parameter-to-virQEMUCapsInitCPUM.patch new file mode 100644 index 0000000..32c57ed --- /dev/null +++ b/0008-qemu-Add-migratable-parameter-to-virQEMUCapsInitCPUM.patch @@ -0,0 +1,139 @@ +From: Jiri Denemark +Date: Wed, 29 Mar 2017 13:33:50 +0200 +Subject: [PATCH] qemu: Add migratable parameter to virQEMUCapsInitCPUModel + +The caller can ask for a migratable CPU model by passing true for the +new parameter. + +Signed-off-by: Jiri Denemark +(cherry picked from commit 00e0cbcb567a57c7b5a145d7fd3fb662779f6bec) +--- + src/qemu/qemu_capabilities.c | 36 +++++++++++++++++++++++++----------- + src/qemu/qemu_capspriv.h | 3 ++- + tests/cputest.c | 2 +- + 3 files changed, 28 insertions(+), 13 deletions(-) + +diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c +index 1a15750a3..b8e4e47b6 100644 +--- a/src/qemu/qemu_capabilities.c ++++ b/src/qemu/qemu_capabilities.c +@@ -3112,7 +3112,8 @@ virQEMUCapsCPUFilterFeatures(const char *name, + static int + virQEMUCapsInitCPUModelS390(virQEMUCapsPtr qemuCaps, + qemuMonitorCPUModelInfoPtr modelInfo, +- virCPUDefPtr cpu) ++ virCPUDefPtr cpu, ++ bool migratable) + { + size_t i; + +@@ -3140,8 +3141,12 @@ virQEMUCapsInitCPUModelS390(virQEMUCapsPtr qemuCaps, + + if (VIR_STRDUP(feature->name, prop->name) < 0) + return -1; +- feature->policy = prop->value.boolean ? VIR_CPU_FEATURE_REQUIRE +- : VIR_CPU_FEATURE_DISABLE; ++ ++ if (!prop->value.boolean || ++ (migratable && prop->migratable == VIR_TRISTATE_BOOL_NO)) ++ feature->policy = VIR_CPU_FEATURE_DISABLE; ++ else ++ feature->policy = VIR_CPU_FEATURE_REQUIRE; + cpu->nfeatures++; + } + +@@ -3158,7 +3163,8 @@ static int + virQEMUCapsInitCPUModelX86(virQEMUCapsPtr qemuCaps, + virDomainVirtType type, + qemuMonitorCPUModelInfoPtr model, +- virCPUDefPtr cpu) ++ virCPUDefPtr cpu, ++ bool migratable) + { + virCPUDataPtr data = NULL; + unsigned long long sigFamily = 0; +@@ -3179,9 +3185,13 @@ virQEMUCapsInitCPUModelX86(virQEMUCapsPtr qemuCaps, + + switch (prop->type) { + case QEMU_MONITOR_CPU_PROPERTY_BOOLEAN: +- if (prop->value.boolean && +- virCPUx86DataAddFeature(data, prop->name) < 0) ++ if (!prop->value.boolean || ++ (migratable && prop->migratable == VIR_TRISTATE_BOOL_NO)) ++ continue; ++ ++ if (virCPUx86DataAddFeature(data, prop->name) < 0) + goto cleanup; ++ + break; + + case QEMU_MONITOR_CPU_PROPERTY_STRING: +@@ -3220,13 +3230,14 @@ virQEMUCapsInitCPUModelX86(virQEMUCapsPtr qemuCaps, + + /** + * 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 when the caller should fall back to other methods + * -1 on error. + */ + int + virQEMUCapsInitCPUModel(virQEMUCapsPtr qemuCaps, + virDomainVirtType type, +- virCPUDefPtr cpu) ++ virCPUDefPtr cpu, ++ bool migratable) + { + qemuMonitorCPUModelInfoPtr model; + int ret = 1; +@@ -3236,10 +3247,13 @@ virQEMUCapsInitCPUModel(virQEMUCapsPtr qemuCaps, + else + model = qemuCaps->tcgCPUModelInfo; + ++ if (migratable && model && !model->migratability) ++ return 1; ++ + if (ARCH_IS_S390(qemuCaps->arch)) +- ret = virQEMUCapsInitCPUModelS390(qemuCaps, model, cpu); ++ ret = virQEMUCapsInitCPUModelS390(qemuCaps, model, cpu, migratable); + else if (ARCH_IS_X86(qemuCaps->arch)) +- ret = virQEMUCapsInitCPUModelX86(qemuCaps, type, model, cpu); ++ ret = virQEMUCapsInitCPUModelX86(qemuCaps, type, model, cpu, migratable); + + if (ret == 0) + cpu->fallback = VIR_CPU_FALLBACK_FORBID; +@@ -3268,7 +3282,7 @@ virQEMUCapsInitHostCPUModel(virQEMUCapsPtr qemuCaps, + cpu->match = VIR_CPU_MATCH_EXACT; + cpu->fallback = VIR_CPU_FALLBACK_ALLOW; + +- if ((rc = virQEMUCapsInitCPUModel(qemuCaps, type, cpu)) < 0) { ++ if ((rc = virQEMUCapsInitCPUModel(qemuCaps, type, cpu, false)) < 0) { + goto error; + } else if (rc == 1) { + VIR_DEBUG("No host CPU model info from QEMU; probing host CPU directly"); +diff --git a/src/qemu/qemu_capspriv.h b/src/qemu/qemu_capspriv.h +index 61ccd4517..1baaaf334 100644 +--- a/src/qemu/qemu_capspriv.h ++++ b/src/qemu/qemu_capspriv.h +@@ -81,7 +81,8 @@ virQEMUCapsInitHostCPUModel(virQEMUCapsPtr qemuCaps, + int + virQEMUCapsInitCPUModel(virQEMUCapsPtr qemuCaps, + virDomainVirtType type, +- virCPUDefPtr cpu); ++ virCPUDefPtr cpu, ++ bool migratable); + + void + virQEMUCapsSetCPUModelInfo(virQEMUCapsPtr qemuCaps, +diff --git a/tests/cputest.c b/tests/cputest.c +index 3d3e43f16..8c07cf4f6 100644 +--- a/tests/cputest.c ++++ b/tests/cputest.c +@@ -709,7 +709,7 @@ cpuTestJSONCPUID(const void *arg) + cpu->match = VIR_CPU_MATCH_EXACT; + cpu->fallback = VIR_CPU_FALLBACK_FORBID; + +- if (virQEMUCapsInitCPUModel(qemuCaps, VIR_DOMAIN_VIRT_KVM, cpu) != 0) ++ if (virQEMUCapsInitCPUModel(qemuCaps, VIR_DOMAIN_VIRT_KVM, cpu, false) != 0) + goto cleanup; + + ret = cpuTestCompareXML(data->arch, cpu, result, false); diff --git a/0009-qemu-Introduce-virQEMUCapsSetHostModel.patch b/0009-qemu-Introduce-virQEMUCapsSetHostModel.patch new file mode 100644 index 0000000..6f3ac92 --- /dev/null +++ b/0009-qemu-Introduce-virQEMUCapsSetHostModel.patch @@ -0,0 +1,47 @@ +From: Jiri Denemark +Date: Fri, 7 Apr 2017 17:03:38 +0200 +Subject: [PATCH] qemu: Introduce virQEMUCapsSetHostModel + +A simple helper as a complement to virQEMUCapsGetHostModel. + +Signed-off-by: Jiri Denemark +(cherry picked from commit bffc3b9fe501ff122ad81ddf42ecdb69f70ff70a) +--- + src/qemu/qemu_capabilities.c | 17 +++++++++++++---- + 1 file changed, 13 insertions(+), 4 deletions(-) + +diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c +index b8e4e47b6..f6020b86d 100644 +--- a/src/qemu/qemu_capabilities.c ++++ b/src/qemu/qemu_capabilities.c +@@ -2419,6 +2419,18 @@ virQEMUCapsGetHostModel(virQEMUCapsPtr qemuCaps, + } + + ++static void ++virQEMUCapsSetHostModel(virQEMUCapsPtr qemuCaps, ++ virDomainVirtType type, ++ virCPUDefPtr cpu) ++{ ++ if (type == VIR_DOMAIN_VIRT_KVM) ++ qemuCaps->kvmCPUModel = cpu; ++ else ++ qemuCaps->tcgCPUModel = cpu; ++} ++ ++ + bool + virQEMUCapsIsCPUModeSupported(virQEMUCapsPtr qemuCaps, + virCapsPtr caps, +@@ -3295,10 +3307,7 @@ virQEMUCapsInitHostCPUModel(virQEMUCapsPtr qemuCaps, + goto error; + } + +- if (type == VIR_DOMAIN_VIRT_KVM) +- qemuCaps->kvmCPUModel = cpu; +- else +- qemuCaps->tcgCPUModel = cpu; ++ virQEMUCapsSetHostModel(qemuCaps, type, cpu); + + cleanup: + virCPUDefFree(hostCPU); diff --git a/0010-qemu-Move-qemuCaps-CPU-data-copying-into-a-separate-.patch b/0010-qemu-Move-qemuCaps-CPU-data-copying-into-a-separate-.patch new file mode 100644 index 0000000..044ecaa --- /dev/null +++ b/0010-qemu-Move-qemuCaps-CPU-data-copying-into-a-separate-.patch @@ -0,0 +1,70 @@ +From: Jiri Denemark +Date: Fri, 7 Apr 2017 17:40:31 +0200 +Subject: [PATCH] qemu: Move qemuCaps CPU data copying into a separate function + +This introduces virQEMUCapsHostCPUDataCopy which will later be +refactored a bit and called twice from virQEMUCapsNewCopy. + +Signed-off-by: Jiri Denemark +(cherry picked from commit 8be4346ca5ae4b568b3e8ce3de9cf46f2e94b416) +--- + src/qemu/qemu_capabilities.c | 39 +++++++++++++++++++++++++-------------- + 1 file changed, 25 insertions(+), 14 deletions(-) + +diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c +index f6020b86d..d17e0e8b8 100644 +--- a/src/qemu/qemu_capabilities.c ++++ b/src/qemu/qemu_capabilities.c +@@ -2082,6 +2082,30 @@ virQEMUCapsNew(void) + } + + ++static int ++virQEMUCapsHostCPUDataCopy(virQEMUCapsPtr dst, ++ virQEMUCapsPtr src) ++{ ++ if (src->kvmCPUModel && ++ !(dst->kvmCPUModel = virCPUDefCopy(src->kvmCPUModel))) ++ return -1; ++ ++ if (src->tcgCPUModel && ++ !(dst->tcgCPUModel = virCPUDefCopy(src->tcgCPUModel))) ++ return -1; ++ ++ if (src->kvmCPUModelInfo && ++ !(dst->kvmCPUModelInfo = qemuMonitorCPUModelInfoCopy(src->kvmCPUModelInfo))) ++ return -1; ++ ++ if (src->tcgCPUModelInfo && ++ !(dst->tcgCPUModelInfo = qemuMonitorCPUModelInfoCopy(src->tcgCPUModelInfo))) ++ return -1; ++ ++ return 0; ++} ++ ++ + virQEMUCapsPtr virQEMUCapsNewCopy(virQEMUCapsPtr qemuCaps) + { + virQEMUCapsPtr ret = virQEMUCapsNew(); +@@ -2119,20 +2143,7 @@ virQEMUCapsPtr virQEMUCapsNewCopy(virQEMUCapsPtr qemuCaps) + goto error; + } + +- if (qemuCaps->kvmCPUModel && +- !(ret->kvmCPUModel = virCPUDefCopy(qemuCaps->kvmCPUModel))) +- goto error; +- +- if (qemuCaps->tcgCPUModel && +- !(ret->tcgCPUModel = virCPUDefCopy(qemuCaps->tcgCPUModel))) +- goto error; +- +- if (qemuCaps->kvmCPUModelInfo && +- !(ret->kvmCPUModelInfo = qemuMonitorCPUModelInfoCopy(qemuCaps->kvmCPUModelInfo))) +- goto error; +- +- if (qemuCaps->tcgCPUModelInfo && +- !(ret->tcgCPUModelInfo = qemuMonitorCPUModelInfoCopy(qemuCaps->tcgCPUModelInfo))) ++ if (virQEMUCapsHostCPUDataCopy(ret, qemuCaps) < 0) + goto error; + + if (VIR_ALLOC_N(ret->machineTypes, qemuCaps->nmachineTypes) < 0) diff --git a/0011-qemu-Introduce-virQEMUCapsHostCPUDataClear.patch b/0011-qemu-Introduce-virQEMUCapsHostCPUDataClear.patch new file mode 100644 index 0000000..7d74043 --- /dev/null +++ b/0011-qemu-Introduce-virQEMUCapsHostCPUDataClear.patch @@ -0,0 +1,67 @@ +From: Jiri Denemark +Date: Fri, 7 Apr 2017 17:43:59 +0200 +Subject: [PATCH] qemu: Introduce virQEMUCapsHostCPUDataClear + +To keep freeing of host CPU data in one place. + +Signed-off-by: Jiri Denemark +(cherry picked from commit b0605e848724c5dc478382398b734398abff674c) +--- + src/qemu/qemu_capabilities.c | 30 +++++++++++++++++------------- + 1 file changed, 17 insertions(+), 13 deletions(-) + +diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c +index d17e0e8b8..2da53a60b 100644 +--- a/src/qemu/qemu_capabilities.c ++++ b/src/qemu/qemu_capabilities.c +@@ -2106,6 +2106,21 @@ virQEMUCapsHostCPUDataCopy(virQEMUCapsPtr dst, + } + + ++static void ++virQEMUCapsHostCPUDataClear(virQEMUCapsPtr qemuCaps) ++{ ++ qemuMonitorCPUModelInfoFree(qemuCaps->kvmCPUModelInfo); ++ qemuMonitorCPUModelInfoFree(qemuCaps->tcgCPUModelInfo); ++ qemuCaps->kvmCPUModelInfo = NULL; ++ qemuCaps->tcgCPUModelInfo = NULL; ++ ++ virCPUDefFree(qemuCaps->kvmCPUModel); ++ virCPUDefFree(qemuCaps->tcgCPUModel); ++ qemuCaps->kvmCPUModel = NULL; ++ qemuCaps->tcgCPUModel = NULL; ++} ++ ++ + virQEMUCapsPtr virQEMUCapsNewCopy(virQEMUCapsPtr qemuCaps) + { + virQEMUCapsPtr ret = virQEMUCapsNew(); +@@ -2192,10 +2207,7 @@ void virQEMUCapsDispose(void *obj) + + VIR_FREE(qemuCaps->gicCapabilities); + +- qemuMonitorCPUModelInfoFree(qemuCaps->kvmCPUModelInfo); +- qemuMonitorCPUModelInfoFree(qemuCaps->tcgCPUModelInfo); +- virCPUDefFree(qemuCaps->kvmCPUModel); +- virCPUDefFree(qemuCaps->tcgCPUModel); ++ virQEMUCapsHostCPUDataClear(qemuCaps); + } + + void +@@ -4068,15 +4080,7 @@ virQEMUCapsReset(virQEMUCapsPtr qemuCaps) + VIR_FREE(qemuCaps->gicCapabilities); + qemuCaps->ngicCapabilities = 0; + +- qemuMonitorCPUModelInfoFree(qemuCaps->kvmCPUModelInfo); +- qemuMonitorCPUModelInfoFree(qemuCaps->tcgCPUModelInfo); +- qemuCaps->kvmCPUModelInfo = NULL; +- qemuCaps->tcgCPUModelInfo = NULL; +- +- virCPUDefFree(qemuCaps->kvmCPUModel); +- virCPUDefFree(qemuCaps->tcgCPUModel); +- qemuCaps->kvmCPUModel = NULL; +- qemuCaps->tcgCPUModel = NULL; ++ virQEMUCapsHostCPUDataClear(qemuCaps); + } + + diff --git a/0012-qemu-Move-qemuCaps-host-CPU-data-in-a-struct.patch b/0012-qemu-Move-qemuCaps-host-CPU-data-in-a-struct.patch new file mode 100644 index 0000000..b5a32dd --- /dev/null +++ b/0012-qemu-Move-qemuCaps-host-CPU-data-in-a-struct.patch @@ -0,0 +1,342 @@ +From: Jiri Denemark +Date: Fri, 7 Apr 2017 18:15:26 +0200 +Subject: [PATCH] qemu: Move qemuCaps host CPU data in a struct + +We need to store several CPU related data structure for both KVM and +TCG. So instead of keeping two different copies of everything let's +make a virQEMUCapsHostCPUData struct and use it twice. + +Signed-off-by: Jiri Denemark +(cherry picked from commit b0a84ffb7f38f990120c231cfb74956a0ed10d95) +--- + src/qemu/qemu_capabilities.c | 168 +++++++++++++++++++++---------------------- + 1 file changed, 82 insertions(+), 86 deletions(-) + +diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c +index 2da53a60b..bbb234538 100644 +--- a/src/qemu/qemu_capabilities.c ++++ b/src/qemu/qemu_capabilities.c +@@ -373,6 +373,19 @@ struct virQEMUCapsMachineType { + unsigned int maxCpus; + bool hotplugCpus; + }; ++ ++typedef struct _virQEMUCapsHostCPUData virQEMUCapsHostCPUData; ++typedef virQEMUCapsHostCPUData *virQEMUCapsHostCPUDataPtr; ++struct _virQEMUCapsHostCPUData { ++ /* Only the "info" part is stored in the capabilities cache, the rest is ++ * re-computed from other fields and external data sources everytime we ++ * probe QEMU or load the cache. ++ */ ++ qemuMonitorCPUModelInfoPtr info; ++ /* Host CPU definition reported in domain capabilities. */ ++ virCPUDefPtr reported; ++}; ++ + /* + * Update the XML parser/formatter when adding more + * information to this struct so that it gets cached +@@ -407,15 +420,8 @@ struct _virQEMUCaps { + size_t ngicCapabilities; + virGICCapability *gicCapabilities; + +- qemuMonitorCPUModelInfoPtr kvmCPUModelInfo; +- qemuMonitorCPUModelInfoPtr tcgCPUModelInfo; +- +- /* Anything below is not stored in the cache since the values are +- * re-computed from the other fields or external data sources every +- * time we probe QEMU or load the results from the cache. +- */ +- virCPUDefPtr kvmCPUModel; +- virCPUDefPtr tcgCPUModel; ++ virQEMUCapsHostCPUData kvmCPU; ++ virQEMUCapsHostCPUData tcgCPU; + }; + + struct virQEMUCapsSearchData { +@@ -2083,23 +2089,15 @@ virQEMUCapsNew(void) + + + static int +-virQEMUCapsHostCPUDataCopy(virQEMUCapsPtr dst, +- virQEMUCapsPtr src) ++virQEMUCapsHostCPUDataCopy(virQEMUCapsHostCPUDataPtr dst, ++ virQEMUCapsHostCPUDataPtr src) + { +- if (src->kvmCPUModel && +- !(dst->kvmCPUModel = virCPUDefCopy(src->kvmCPUModel))) ++ if (src->info && ++ !(dst->info = qemuMonitorCPUModelInfoCopy(src->info))) + return -1; + +- if (src->tcgCPUModel && +- !(dst->tcgCPUModel = virCPUDefCopy(src->tcgCPUModel))) +- return -1; +- +- if (src->kvmCPUModelInfo && +- !(dst->kvmCPUModelInfo = qemuMonitorCPUModelInfoCopy(src->kvmCPUModelInfo))) +- return -1; +- +- if (src->tcgCPUModelInfo && +- !(dst->tcgCPUModelInfo = qemuMonitorCPUModelInfoCopy(src->tcgCPUModelInfo))) ++ if (src->reported && ++ !(dst->reported = virCPUDefCopy(src->reported))) + return -1; + + return 0; +@@ -2107,17 +2105,12 @@ virQEMUCapsHostCPUDataCopy(virQEMUCapsPtr dst, + + + static void +-virQEMUCapsHostCPUDataClear(virQEMUCapsPtr qemuCaps) ++virQEMUCapsHostCPUDataClear(virQEMUCapsHostCPUDataPtr cpuData) + { +- qemuMonitorCPUModelInfoFree(qemuCaps->kvmCPUModelInfo); +- qemuMonitorCPUModelInfoFree(qemuCaps->tcgCPUModelInfo); +- qemuCaps->kvmCPUModelInfo = NULL; +- qemuCaps->tcgCPUModelInfo = NULL; +- +- virCPUDefFree(qemuCaps->kvmCPUModel); +- virCPUDefFree(qemuCaps->tcgCPUModel); +- qemuCaps->kvmCPUModel = NULL; +- qemuCaps->tcgCPUModel = NULL; ++ qemuMonitorCPUModelInfoFree(cpuData->info); ++ virCPUDefFree(cpuData->reported); ++ ++ memset(cpuData, 0, sizeof(*cpuData)); + } + + +@@ -2158,7 +2151,8 @@ virQEMUCapsPtr virQEMUCapsNewCopy(virQEMUCapsPtr qemuCaps) + goto error; + } + +- if (virQEMUCapsHostCPUDataCopy(ret, qemuCaps) < 0) ++ if (virQEMUCapsHostCPUDataCopy(&ret->kvmCPU, &qemuCaps->kvmCPU) < 0 || ++ virQEMUCapsHostCPUDataCopy(&ret->tcgCPU, &qemuCaps->tcgCPU) < 0) + goto error; + + if (VIR_ALLOC_N(ret->machineTypes, qemuCaps->nmachineTypes) < 0) +@@ -2207,7 +2201,8 @@ void virQEMUCapsDispose(void *obj) + + VIR_FREE(qemuCaps->gicCapabilities); + +- virQEMUCapsHostCPUDataClear(qemuCaps); ++ virQEMUCapsHostCPUDataClear(&qemuCaps->kvmCPU); ++ virQEMUCapsHostCPUDataClear(&qemuCaps->tcgCPU); + } + + void +@@ -2431,14 +2426,24 @@ virQEMUCapsGetCPUDefinitions(virQEMUCapsPtr qemuCaps, + } + + ++static virQEMUCapsHostCPUDataPtr ++virQEMUCapsGetHostCPUData(virQEMUCapsPtr qemuCaps, ++ virDomainVirtType type) ++{ ++ if (type == VIR_DOMAIN_VIRT_KVM) ++ return &qemuCaps->kvmCPU; ++ else ++ return &qemuCaps->tcgCPU; ++} ++ ++ + virCPUDefPtr + virQEMUCapsGetHostModel(virQEMUCapsPtr qemuCaps, + virDomainVirtType type) + { +- if (type == VIR_DOMAIN_VIRT_KVM) +- return qemuCaps->kvmCPUModel; +- else +- return qemuCaps->tcgCPUModel; ++ virQEMUCapsHostCPUDataPtr cpuData = virQEMUCapsGetHostCPUData(qemuCaps, type); ++ ++ return cpuData->reported; + } + + +@@ -2447,10 +2452,9 @@ virQEMUCapsSetHostModel(virQEMUCapsPtr qemuCaps, + virDomainVirtType type, + virCPUDefPtr cpu) + { +- if (type == VIR_DOMAIN_VIRT_KVM) +- qemuCaps->kvmCPUModel = cpu; +- else +- qemuCaps->tcgCPUModel = cpu; ++ virQEMUCapsHostCPUDataPtr cpuData = virQEMUCapsGetHostCPUData(qemuCaps, type); ++ ++ cpuData->reported = cpu; + } + + +@@ -2841,24 +2845,28 @@ virQEMUCapsProbeQMPHostCPU(virQEMUCapsPtr qemuCaps, + qemuMonitorPtr mon, + bool tcg) + { +- qemuMonitorCPUModelInfoPtr *modelInfo; ++ qemuMonitorCPUModelInfoPtr modelInfo = NULL; + qemuMonitorCPUModelInfoPtr nonMigratable = NULL; + virHashTablePtr hash = NULL; + const char *model; + qemuMonitorCPUModelExpansionType type; ++ virDomainVirtType virtType; ++ virQEMUCapsHostCPUDataPtr cpuData; + int ret = -1; + + if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_QUERY_CPU_MODEL_EXPANSION)) + return 0; + + if (tcg || !virQEMUCapsGet(qemuCaps, QEMU_CAPS_KVM)) { +- modelInfo = &qemuCaps->tcgCPUModelInfo; ++ virtType = VIR_DOMAIN_VIRT_QEMU; + model = "max"; + } else { +- modelInfo = &qemuCaps->kvmCPUModelInfo; ++ virtType = VIR_DOMAIN_VIRT_KVM; + model = "host"; + } + ++ cpuData = virQEMUCapsGetHostCPUData(qemuCaps, virtType); ++ + /* Some x86_64 features defined in cpu_map.xml use spelling which differ + * from the one preferred by QEMU. Static expansion would give us only the + * preferred spelling, thus we need to do a full expansion on the result of +@@ -2869,14 +2877,14 @@ virQEMUCapsProbeQMPHostCPU(virQEMUCapsPtr qemuCaps, + else + type = QEMU_MONITOR_CPU_MODEL_EXPANSION_STATIC; + +- if (qemuMonitorGetCPUModelExpansion(mon, type, model, true, modelInfo) < 0) +- return -1; ++ if (qemuMonitorGetCPUModelExpansion(mon, type, model, true, &modelInfo) < 0) ++ goto cleanup; + + /* Try to check migratability of each feature. */ +- if (*modelInfo && ++ if (modelInfo && + qemuMonitorGetCPUModelExpansion(mon, type, model, false, + &nonMigratable) < 0) +- goto error; ++ goto cleanup; + + if (nonMigratable) { + qemuMonitorCPUPropertyPtr prop; +@@ -2884,12 +2892,12 @@ virQEMUCapsProbeQMPHostCPU(virQEMUCapsPtr qemuCaps, + size_t i; + + if (!(hash = virHashCreate(0, NULL))) +- goto error; ++ goto cleanup; + +- for (i = 0; i < (*modelInfo)->nprops; i++) { +- prop = (*modelInfo)->props + i; ++ for (i = 0; i < modelInfo->nprops; i++) { ++ prop = modelInfo->props + i; + if (virHashAddEntry(hash, prop->name, prop) < 0) +- goto error; ++ goto cleanup; + } + + for (i = 0; i < nonMigratable->nprops; i++) { +@@ -2907,21 +2915,18 @@ virQEMUCapsProbeQMPHostCPU(virQEMUCapsPtr qemuCaps, + } + } + +- (*modelInfo)->migratability = true; ++ modelInfo->migratability = true; + } + ++ VIR_STEAL_PTR(cpuData->info, modelInfo); + ret = 0; + + cleanup: + virHashFree(hash); + qemuMonitorCPUModelInfoFree(nonMigratable); ++ qemuMonitorCPUModelInfoFree(modelInfo); + + return ret; +- +- error: +- qemuMonitorCPUModelInfoFree(*modelInfo); +- *modelInfo = NULL; +- goto cleanup; + } + + struct tpmTypeToCaps { +@@ -3274,21 +3279,19 @@ virQEMUCapsInitCPUModel(virQEMUCapsPtr qemuCaps, + virCPUDefPtr cpu, + bool migratable) + { +- qemuMonitorCPUModelInfoPtr model; ++ virQEMUCapsHostCPUDataPtr cpuData = virQEMUCapsGetHostCPUData(qemuCaps, type); + int ret = 1; + +- if (type == VIR_DOMAIN_VIRT_KVM) +- model = qemuCaps->kvmCPUModelInfo; +- else +- model = qemuCaps->tcgCPUModelInfo; +- +- if (migratable && model && !model->migratability) ++ if (migratable && cpuData->info && !cpuData->info->migratability) + return 1; + +- if (ARCH_IS_S390(qemuCaps->arch)) +- ret = virQEMUCapsInitCPUModelS390(qemuCaps, model, cpu, migratable); +- else if (ARCH_IS_X86(qemuCaps->arch)) +- ret = virQEMUCapsInitCPUModelX86(qemuCaps, type, model, cpu, migratable); ++ if (ARCH_IS_S390(qemuCaps->arch)) { ++ ret = virQEMUCapsInitCPUModelS390(qemuCaps, cpuData->info, ++ cpu, migratable); ++ } else if (ARCH_IS_X86(qemuCaps->arch)) { ++ ret = virQEMUCapsInitCPUModelX86(qemuCaps, type, cpuData->info, ++ cpu, migratable); ++ } + + if (ret == 0) + cpu->fallback = VIR_CPU_FALLBACK_FORBID; +@@ -3348,10 +3351,9 @@ virQEMUCapsSetCPUModelInfo(virQEMUCapsPtr qemuCaps, + virDomainVirtType type, + qemuMonitorCPUModelInfoPtr modelInfo) + { +- if (type == VIR_DOMAIN_VIRT_KVM) +- qemuCaps->kvmCPUModelInfo = modelInfo; +- else +- qemuCaps->tcgCPUModelInfo = modelInfo; ++ virQEMUCapsHostCPUDataPtr cpuData = virQEMUCapsGetHostCPUData(qemuCaps, type); ++ ++ cpuData->info = modelInfo; + } + + +@@ -3810,18 +3812,11 @@ virQEMUCapsFormatHostCPUModelInfo(virQEMUCapsPtr qemuCaps, + virBufferPtr buf, + virDomainVirtType type) + { +- qemuMonitorCPUModelInfoPtr model; +- const char *typeStr; ++ virQEMUCapsHostCPUDataPtr cpuData = virQEMUCapsGetHostCPUData(qemuCaps, type); ++ qemuMonitorCPUModelInfoPtr model = cpuData->info; ++ const char *typeStr = type == VIR_DOMAIN_VIRT_KVM ? "kvm" : "tcg"; + size_t i; + +- if (type == VIR_DOMAIN_VIRT_KVM) { +- typeStr = "kvm"; +- model = qemuCaps->kvmCPUModelInfo; +- } else { +- typeStr = "tcg"; +- model = qemuCaps->tcgCPUModelInfo; +- } +- + if (!model) + return; + +@@ -4080,7 +4075,8 @@ virQEMUCapsReset(virQEMUCapsPtr qemuCaps) + VIR_FREE(qemuCaps->gicCapabilities); + qemuCaps->ngicCapabilities = 0; + +- virQEMUCapsHostCPUDataClear(qemuCaps); ++ virQEMUCapsHostCPUDataClear(&qemuCaps->kvmCPU); ++ virQEMUCapsHostCPUDataClear(&qemuCaps->tcgCPU); + } + + diff --git a/0013-qemu-Prepare-qemuCaps-for-multiple-host-CPU-defs.patch b/0013-qemu-Prepare-qemuCaps-for-multiple-host-CPU-defs.patch new file mode 100644 index 0000000..708dbd0 --- /dev/null +++ b/0013-qemu-Prepare-qemuCaps-for-multiple-host-CPU-defs.patch @@ -0,0 +1,119 @@ +From: Jiri Denemark +Date: Tue, 11 Apr 2017 11:14:30 +0200 +Subject: [PATCH] qemu: Prepare qemuCaps for multiple host CPU defs + +Soon we will need to store multiple host CPU definitions in +virQEMUCapsHostCPUData and qemuCaps users will want to request the one +they need. This patch introduces virQEMUCapsHostCPUType enum which will +be used for specifying the requested CPU definition. + +Signed-off-by: Jiri Denemark +(cherry picked from commit 1fe517c68df92eb7f379fa87cb0d29d566aad6f4) +--- + src/qemu/qemu_capabilities.c | 16 ++++++++++++---- + src/qemu/qemu_capabilities.h | 10 +++++++++- + src/qemu/qemu_command.c | 3 ++- + src/qemu/qemu_process.c | 6 ++++-- + 4 files changed, 27 insertions(+), 8 deletions(-) + +diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c +index bbb234538..a6324a398 100644 +--- a/src/qemu/qemu_capabilities.c ++++ b/src/qemu/qemu_capabilities.c +@@ -2439,11 +2439,17 @@ virQEMUCapsGetHostCPUData(virQEMUCapsPtr qemuCaps, + + virCPUDefPtr + virQEMUCapsGetHostModel(virQEMUCapsPtr qemuCaps, +- virDomainVirtType type) ++ virDomainVirtType type, ++ virQEMUCapsHostCPUType cpuType) + { + virQEMUCapsHostCPUDataPtr cpuData = virQEMUCapsGetHostCPUData(qemuCaps, type); + +- return cpuData->reported; ++ switch (cpuType) { ++ case VIR_QEMU_CAPS_HOST_CPU_REPORTED: ++ return cpuData->reported; ++ } ++ ++ return NULL; + } + + +@@ -2472,7 +2478,8 @@ virQEMUCapsIsCPUModeSupported(virQEMUCapsPtr qemuCaps, + virQEMUCapsGuestIsNative(caps->host.arch, qemuCaps->arch); + + case VIR_CPU_MODE_HOST_MODEL: +- return !!virQEMUCapsGetHostModel(qemuCaps, type); ++ return !!virQEMUCapsGetHostModel(qemuCaps, type, ++ VIR_QEMU_CAPS_HOST_CPU_REPORTED); + + case VIR_CPU_MODE_CUSTOM: + if (type == VIR_DOMAIN_VIRT_KVM) +@@ -5456,7 +5463,8 @@ virQEMUCapsFillDomainCPUCaps(virCapsPtr caps, + + if (virQEMUCapsIsCPUModeSupported(qemuCaps, caps, domCaps->virttype, + VIR_CPU_MODE_HOST_MODEL)) { +- virCPUDefPtr cpu = virQEMUCapsGetHostModel(qemuCaps, domCaps->virttype); ++ virCPUDefPtr cpu = virQEMUCapsGetHostModel(qemuCaps, domCaps->virttype, ++ VIR_QEMU_CAPS_HOST_CPU_REPORTED); + domCaps->cpu.hostModel = virCPUDefCopy(cpu); + } + +diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h +index d44682f2a..88e27855b 100644 +--- a/src/qemu/qemu_capabilities.h ++++ b/src/qemu/qemu_capabilities.h +@@ -449,8 +449,16 @@ int virQEMUCapsGetCPUDefinitions(virQEMUCapsPtr qemuCaps, + virDomainVirtType type, + char ***names, + size_t *count); ++ ++typedef enum { ++ /* Host CPU definition reported in domain capabilities. */ ++ VIR_QEMU_CAPS_HOST_CPU_REPORTED, ++} virQEMUCapsHostCPUType; ++ + virCPUDefPtr virQEMUCapsGetHostModel(virQEMUCapsPtr qemuCaps, +- virDomainVirtType type); ++ virDomainVirtType type, ++ virQEMUCapsHostCPUType cpuType); ++ + bool virQEMUCapsIsCPUModeSupported(virQEMUCapsPtr qemuCaps, + virCapsPtr caps, + virDomainVirtType type, +diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c +index 3abfe7b55..311edd13e 100644 +--- a/src/qemu/qemu_command.c ++++ b/src/qemu/qemu_command.c +@@ -6879,7 +6879,8 @@ qemuBuildCpuCommandLine(virCommandPtr cmd, + if (def->cpu->mode == VIR_CPU_MODE_CUSTOM) + cpuDef = def->cpu; + else if (def->cpu->mode == VIR_CPU_MODE_HOST_PASSTHROUGH) +- cpuDef = virQEMUCapsGetHostModel(qemuCaps, def->virtType); ++ cpuDef = virQEMUCapsGetHostModel(qemuCaps, def->virtType, ++ VIR_QEMU_CAPS_HOST_CPU_REPORTED); + + if (cpuDef) { + int svm = virCPUCheckFeature(def->os.arch, cpuDef, "svm"); +diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c +index 26a668d27..07a88a3a7 100644 +--- a/src/qemu/qemu_process.c ++++ b/src/qemu/qemu_process.c +@@ -5299,12 +5299,14 @@ qemuProcessUpdateGuestCPU(virDomainDefPtr def, + + if (def->cpu->check == VIR_CPU_CHECK_PARTIAL && + virCPUCompare(caps->host.arch, +- virQEMUCapsGetHostModel(qemuCaps, def->virtType), ++ virQEMUCapsGetHostModel(qemuCaps, def->virtType, ++ VIR_QEMU_CAPS_HOST_CPU_REPORTED), + def->cpu, true) < 0) + return -1; + + if (virCPUUpdate(def->os.arch, def->cpu, +- virQEMUCapsGetHostModel(qemuCaps, def->virtType)) < 0) ++ virQEMUCapsGetHostModel(qemuCaps, def->virtType, ++ VIR_QEMU_CAPS_HOST_CPU_REPORTED)) < 0) + goto cleanup; + + if (virQEMUCapsGetCPUDefinitions(qemuCaps, def->virtType, diff --git a/0014-qemu-Pass-migratable-host-CPU-model-to-virCPUUpdate.patch b/0014-qemu-Pass-migratable-host-CPU-model-to-virCPUUpdate.patch new file mode 100644 index 0000000..6e51b37 --- /dev/null +++ b/0014-qemu-Pass-migratable-host-CPU-model-to-virCPUUpdate.patch @@ -0,0 +1,210 @@ +From: Jiri Denemark +Date: Wed, 29 Mar 2017 15:31:17 +0200 +Subject: [PATCH] qemu: Pass migratable host CPU model to virCPUUpdate + +We already know from QEMU which CPU features will block migration. Let's +use this information to make a migratable copy of the host CPU model and +use it for updating guest CPU specification. This will allow us to drop +feature filtering from virCPUUpdate where it was just a hack. + +Signed-off-by: Jiri Denemark +(cherry picked from commit 56bd7edcb5dc878beffb80d4e6a9cfb812378ded) +--- + src/qemu/qemu_capabilities.c | 57 +++++++++++++++++++++++++++++++++++++------- + src/qemu/qemu_capabilities.h | 2 ++ + src/qemu/qemu_process.c | 2 +- + tests/cputest.c | 7 +++++- + 4 files changed, 57 insertions(+), 11 deletions(-) + +diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c +index a6324a398..7fc577546 100644 +--- a/src/qemu/qemu_capabilities.c ++++ b/src/qemu/qemu_capabilities.c +@@ -384,6 +384,8 @@ struct _virQEMUCapsHostCPUData { + qemuMonitorCPUModelInfoPtr info; + /* Host CPU definition reported in domain capabilities. */ + virCPUDefPtr reported; ++ /* Migratable host CPU definition used for updating guest CPU. */ ++ virCPUDefPtr migratable; + }; + + /* +@@ -2100,6 +2102,10 @@ virQEMUCapsHostCPUDataCopy(virQEMUCapsHostCPUDataPtr dst, + !(dst->reported = virCPUDefCopy(src->reported))) + return -1; + ++ if (src->migratable && ++ !(dst->migratable = virCPUDefCopy(src->migratable))) ++ return -1; ++ + return 0; + } + +@@ -2109,6 +2115,7 @@ virQEMUCapsHostCPUDataClear(virQEMUCapsHostCPUDataPtr cpuData) + { + qemuMonitorCPUModelInfoFree(cpuData->info); + virCPUDefFree(cpuData->reported); ++ virCPUDefFree(cpuData->migratable); + + memset(cpuData, 0, sizeof(*cpuData)); + } +@@ -2447,6 +2454,9 @@ virQEMUCapsGetHostModel(virQEMUCapsPtr qemuCaps, + switch (cpuType) { + case VIR_QEMU_CAPS_HOST_CPU_REPORTED: + return cpuData->reported; ++ ++ case VIR_QEMU_CAPS_HOST_CPU_MIGRATABLE: ++ return cpuData->migratable; + } + + return NULL; +@@ -2456,11 +2466,13 @@ virQEMUCapsGetHostModel(virQEMUCapsPtr qemuCaps, + static void + virQEMUCapsSetHostModel(virQEMUCapsPtr qemuCaps, + virDomainVirtType type, +- virCPUDefPtr cpu) ++ virCPUDefPtr reported, ++ virCPUDefPtr migratable) + { + virQEMUCapsHostCPUDataPtr cpuData = virQEMUCapsGetHostCPUData(qemuCaps, type); + +- cpuData->reported = cpu; ++ cpuData->reported = reported; ++ cpuData->migratable = migratable; + } + + +@@ -3307,26 +3319,39 @@ virQEMUCapsInitCPUModel(virQEMUCapsPtr qemuCaps, + } + + ++static virCPUDefPtr ++virQEMUCapsNewHostCPUModel(void) ++{ ++ virCPUDefPtr cpu; ++ ++ if (VIR_ALLOC(cpu) < 0) ++ return NULL; ++ ++ cpu->type = VIR_CPU_TYPE_GUEST; ++ cpu->mode = VIR_CPU_MODE_CUSTOM; ++ cpu->match = VIR_CPU_MATCH_EXACT; ++ cpu->fallback = VIR_CPU_FALLBACK_ALLOW; ++ ++ return cpu; ++} ++ ++ + void + virQEMUCapsInitHostCPUModel(virQEMUCapsPtr qemuCaps, + virCapsPtr caps, + virDomainVirtType type) + { + virCPUDefPtr cpu = NULL; ++ virCPUDefPtr migCPU = NULL; + virCPUDefPtr hostCPU = NULL; + int rc; + + if (!caps || !virQEMUCapsGuestIsNative(caps->host.arch, qemuCaps->arch)) + return; + +- if (VIR_ALLOC(cpu) < 0) ++ if (!(cpu = virQEMUCapsNewHostCPUModel())) + goto error; + +- cpu->type = VIR_CPU_TYPE_GUEST; +- cpu->mode = VIR_CPU_MODE_CUSTOM; +- cpu->match = VIR_CPU_MATCH_EXACT; +- cpu->fallback = VIR_CPU_FALLBACK_ALLOW; +- + if ((rc = virQEMUCapsInitCPUModel(qemuCaps, type, cpu, false)) < 0) { + goto error; + } else if (rc == 1) { +@@ -3340,7 +3365,20 @@ virQEMUCapsInitHostCPUModel(virQEMUCapsPtr qemuCaps, + goto error; + } + +- virQEMUCapsSetHostModel(qemuCaps, type, cpu); ++ if (!(migCPU = virQEMUCapsNewHostCPUModel())) ++ goto error; ++ ++ if ((rc = virQEMUCapsInitCPUModel(qemuCaps, type, migCPU, true)) < 0) { ++ goto error; ++ } else if (rc == 1) { ++ VIR_DEBUG("CPU migratability not provided by QEMU"); ++ ++ virCPUDefFree(migCPU); ++ if (!(migCPU = virCPUCopyMigratable(qemuCaps->arch, cpu))) ++ goto error; ++ } ++ ++ virQEMUCapsSetHostModel(qemuCaps, type, cpu, migCPU); + + cleanup: + virCPUDefFree(hostCPU); +@@ -3348,6 +3386,7 @@ virQEMUCapsInitHostCPUModel(virQEMUCapsPtr qemuCaps, + + error: + virCPUDefFree(cpu); ++ virCPUDefFree(migCPU); + virResetLastError(); + goto cleanup; + } +diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h +index 88e27855b..31818c940 100644 +--- a/src/qemu/qemu_capabilities.h ++++ b/src/qemu/qemu_capabilities.h +@@ -453,6 +453,8 @@ int virQEMUCapsGetCPUDefinitions(virQEMUCapsPtr qemuCaps, + typedef enum { + /* Host CPU definition reported in domain capabilities. */ + VIR_QEMU_CAPS_HOST_CPU_REPORTED, ++ /* Migratable host CPU definition used for updating guest CPU. */ ++ VIR_QEMU_CAPS_HOST_CPU_MIGRATABLE, + } virQEMUCapsHostCPUType; + + virCPUDefPtr virQEMUCapsGetHostModel(virQEMUCapsPtr qemuCaps, +diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c +index 07a88a3a7..e67736638 100644 +--- a/src/qemu/qemu_process.c ++++ b/src/qemu/qemu_process.c +@@ -5306,7 +5306,7 @@ qemuProcessUpdateGuestCPU(virDomainDefPtr def, + + if (virCPUUpdate(def->os.arch, def->cpu, + virQEMUCapsGetHostModel(qemuCaps, def->virtType, +- VIR_QEMU_CAPS_HOST_CPU_REPORTED)) < 0) ++ VIR_QEMU_CAPS_HOST_CPU_MIGRATABLE)) < 0) + goto cleanup; + + if (virQEMUCapsGetCPUDefinitions(qemuCaps, def->virtType, +diff --git a/tests/cputest.c b/tests/cputest.c +index 8c07cf4f6..efa891dc1 100644 +--- a/tests/cputest.c ++++ b/tests/cputest.c +@@ -393,6 +393,7 @@ cpuTestUpdate(const void *arg) + const struct data *data = arg; + int ret = -1; + virCPUDefPtr host = NULL; ++ virCPUDefPtr migHost = NULL; + virCPUDefPtr cpu = NULL; + char *result = NULL; + +@@ -400,7 +401,10 @@ cpuTestUpdate(const void *arg) + !(cpu = cpuTestLoadXML(data->arch, data->name))) + goto cleanup; + +- if (virCPUUpdate(host->arch, cpu, host) < 0) ++ if (!(migHost = virCPUCopyMigratable(data->arch, host))) ++ goto cleanup; ++ ++ if (virCPUUpdate(host->arch, cpu, migHost) < 0) + goto cleanup; + + if (virAsprintf(&result, "%s+%s", data->host, data->name) < 0) +@@ -411,6 +415,7 @@ cpuTestUpdate(const void *arg) + cleanup: + virCPUDefFree(host); + virCPUDefFree(cpu); ++ virCPUDefFree(migHost); + VIR_FREE(result); + return ret; + } diff --git a/0015-cpu-Drop-feature-filtering-from-virCPUUpdate.patch b/0015-cpu-Drop-feature-filtering-from-virCPUUpdate.patch new file mode 100644 index 0000000..212999a --- /dev/null +++ b/0015-cpu-Drop-feature-filtering-from-virCPUUpdate.patch @@ -0,0 +1,49 @@ +From: Jiri Denemark +Date: Wed, 29 Mar 2017 15:00:21 +0200 +Subject: [PATCH] cpu: Drop feature filtering from virCPUUpdate + +Because of the changes done in the previous commit, @host is already a +migratable CPU and there's no need to do any additional filtering. + +Signed-off-by: Jiri Denemark +(cherry picked from commit 232d87c7dd081d126a079fb45178e0be096cc680) +--- + src/cpu/cpu_x86.c | 9 +++------ + 1 file changed, 3 insertions(+), 6 deletions(-) + +diff --git a/src/cpu/cpu_x86.c b/src/cpu/cpu_x86.c +index a771b251e..53359ff9b 100644 +--- a/src/cpu/cpu_x86.c ++++ b/src/cpu/cpu_x86.c +@@ -2549,8 +2549,7 @@ x86Baseline(virCPUDefPtr *cpus, + + static int + x86UpdateHostModel(virCPUDefPtr guest, +- const virCPUDef *host, +- virCPUx86MapPtr map) ++ const virCPUDef *host) + { + virCPUDefPtr updated = NULL; + size_t i; +@@ -2559,11 +2558,9 @@ x86UpdateHostModel(virCPUDefPtr guest, + if (!(updated = virCPUDefCopyWithoutModel(host))) + goto cleanup; + +- /* Remove non-migratable features by default */ + updated->type = VIR_CPU_TYPE_GUEST; + updated->mode = VIR_CPU_MODE_CUSTOM; +- if (virCPUDefCopyModelFilter(updated, host, true, +- x86FeatureIsMigratable, map) < 0) ++ if (virCPUDefCopyModel(updated, host, true) < 0) + goto cleanup; + + if (guest->vendor_id) { +@@ -2627,7 +2624,7 @@ virCPUx86Update(virCPUDefPtr guest, + + if (guest->mode == VIR_CPU_MODE_HOST_MODEL || + guest->match == VIR_CPU_MATCH_MINIMUM) +- ret = x86UpdateHostModel(guest, host, map); ++ ret = x86UpdateHostModel(guest, host); + else + ret = 0; + diff --git a/0016-cpu-Introduce-virCPUGetHostIsSupported.patch b/0016-cpu-Introduce-virCPUGetHostIsSupported.patch new file mode 100644 index 0000000..c4d616c --- /dev/null +++ b/0016-cpu-Introduce-virCPUGetHostIsSupported.patch @@ -0,0 +1,74 @@ +From: Jiri Denemark +Date: Tue, 11 Apr 2017 20:45:07 +0200 +Subject: [PATCH] cpu: Introduce virCPUGetHostIsSupported + +Sometimes we want to call virCPUGetHost only when it is implemented for +a given architecture to avoid logging expected and possibly misleading +errors. The new virCPUGetHostIsSupported API may be used to guard such +calls to virCPUGetHost. + +Signed-off-by: Jiri Denemark +(cherry picked from commit bf1a881715c905c67f7d38dcd5bd6c2afbff1f9b) +--- + src/cpu/cpu.c | 20 ++++++++++++++++++++ + src/cpu/cpu.h | 3 +++ + src/libvirt_private.syms | 1 + + 3 files changed, 24 insertions(+) + +diff --git a/src/cpu/cpu.c b/src/cpu/cpu.c +index 8a407ac18..702b14dbb 100644 +--- a/src/cpu/cpu.c ++++ b/src/cpu/cpu.c +@@ -358,6 +358,26 @@ virCPUDataFree(virCPUDataPtr data) + + + /** ++ * virCPUGetHostIsSupported: ++ * ++ * @arch: CPU architecture ++ * ++ * Check whether virCPUGetHost is supported for @arch. ++ * ++ * Returns true if virCPUGetHost is supported, false otherwise. ++ */ ++bool ++virCPUGetHostIsSupported(virArch arch) ++{ ++ struct cpuArchDriver *driver; ++ ++ VIR_DEBUG("arch=%s", virArchToString(arch)); ++ ++ return (driver = cpuGetSubDriver(arch)) && driver->getHost; ++} ++ ++ ++/** + * virCPUGetHost: + * + * @arch: CPU architecture +diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h +index 352445c40..c6ca111e9 100644 +--- a/src/cpu/cpu.h ++++ b/src/cpu/cpu.h +@@ -183,6 +183,9 @@ virCPUDataNew(virArch arch); + void + virCPUDataFree(virCPUDataPtr data); + ++bool ++virCPUGetHostIsSupported(virArch arch); ++ + virCPUDefPtr + virCPUGetHost(virArch arch, + virCPUType type, +diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms +index dc6db3b28..2d8a9ddec 100644 +--- a/src/libvirt_private.syms ++++ b/src/libvirt_private.syms +@@ -1024,6 +1024,7 @@ virCPUDataNew; + virCPUDataParse; + virCPUExpandFeatures; + virCPUGetHost; ++virCPUGetHostIsSupported; + virCPUGetModels; + virCPUProbeHost; + virCPUTranslate; diff --git a/0017-qemu-Use-more-data-for-comparing-CPUs.patch b/0017-qemu-Use-more-data-for-comparing-CPUs.patch new file mode 100644 index 0000000..751ae11 --- /dev/null +++ b/0017-qemu-Use-more-data-for-comparing-CPUs.patch @@ -0,0 +1,164 @@ +From: Jiri Denemark +Date: Tue, 11 Apr 2017 20:46:05 +0200 +Subject: [PATCH] qemu: Use more data for comparing CPUs + +With QEMU older than 2.9.0 libvirt uses CPUID instruction to determine +what CPU features are supported on the host. This was later used when +checking compatibility of guest CPUs. Since QEMU 2.9.0 we ask QEMU for +the host CPU data. But the two methods we use usually provide disjoint +sets of CPU features because QEMU/KVM does not support all features +provided by the host CPU and on the other hand it can enable some +feature even if the host CPU does not support them. + +So if there is a domain which requires a CPU features disabled by +QEMU/KVM, libvirt will refuse to start it with QEMU > 2.9.0 as its guest +CPU is incompatible with the host CPU data we got from QEMU. But such +domain would happily start on older QEMU (of course, the features would +be missing the guest CPU). To fix this regression, we need to combine +both CPU feature sets when checking guest CPU compatibility. + +https://bugzilla.redhat.com/show_bug.cgi?id=1439933 + +Signed-off-by: Jiri Denemark +(cherry picked from commit 5b4a6adb5ca24a6cb91cdc55c31506fb278d3a91) +--- + src/qemu/qemu_capabilities.c | 35 +++++++++++++++++++++++++++++++++-- + src/qemu/qemu_capabilities.h | 4 ++++ + src/qemu/qemu_process.c | 2 +- + 3 files changed, 38 insertions(+), 3 deletions(-) + +diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c +index 7fc577546..01bd4750c 100644 +--- a/src/qemu/qemu_capabilities.c ++++ b/src/qemu/qemu_capabilities.c +@@ -386,6 +386,10 @@ struct _virQEMUCapsHostCPUData { + virCPUDefPtr reported; + /* Migratable host CPU definition used for updating guest CPU. */ + virCPUDefPtr migratable; ++ /* CPU definition with features detected by libvirt using virCPUGetHost ++ * combined with features reported by QEMU. This is used for backward ++ * compatible comparison between a guest CPU and a host CPU. */ ++ virCPUDefPtr full; + }; + + /* +@@ -2106,6 +2110,10 @@ virQEMUCapsHostCPUDataCopy(virQEMUCapsHostCPUDataPtr dst, + !(dst->migratable = virCPUDefCopy(src->migratable))) + return -1; + ++ if (src->full && ++ !(dst->full = virCPUDefCopy(src->full))) ++ return -1; ++ + return 0; + } + +@@ -2116,6 +2124,7 @@ virQEMUCapsHostCPUDataClear(virQEMUCapsHostCPUDataPtr cpuData) + qemuMonitorCPUModelInfoFree(cpuData->info); + virCPUDefFree(cpuData->reported); + virCPUDefFree(cpuData->migratable); ++ virCPUDefFree(cpuData->full); + + memset(cpuData, 0, sizeof(*cpuData)); + } +@@ -2457,6 +2466,11 @@ virQEMUCapsGetHostModel(virQEMUCapsPtr qemuCaps, + + case VIR_QEMU_CAPS_HOST_CPU_MIGRATABLE: + return cpuData->migratable; ++ ++ case VIR_QEMU_CAPS_HOST_CPU_FULL: ++ /* 'full' is non-NULL only if we have data from both QEMU and ++ * virCPUGetHost */ ++ return cpuData->full ? cpuData->full : cpuData->reported; + } + + return NULL; +@@ -2467,12 +2481,14 @@ static void + virQEMUCapsSetHostModel(virQEMUCapsPtr qemuCaps, + virDomainVirtType type, + virCPUDefPtr reported, +- virCPUDefPtr migratable) ++ virCPUDefPtr migratable, ++ virCPUDefPtr full) + { + virQEMUCapsHostCPUDataPtr cpuData = virQEMUCapsGetHostCPUData(qemuCaps, type); + + cpuData->reported = reported; + cpuData->migratable = migratable; ++ cpuData->full = full; + } + + +@@ -3344,6 +3360,8 @@ virQEMUCapsInitHostCPUModel(virQEMUCapsPtr qemuCaps, + virCPUDefPtr cpu = NULL; + virCPUDefPtr migCPU = NULL; + virCPUDefPtr hostCPU = NULL; ++ virCPUDefPtr fullCPU = NULL; ++ size_t i; + int rc; + + if (!caps || !virQEMUCapsGuestIsNative(caps->host.arch, qemuCaps->arch)) +@@ -3363,6 +3381,18 @@ virQEMUCapsInitHostCPUModel(virQEMUCapsPtr qemuCaps, + virQEMUCapsCPUFilterFeatures, + qemuCaps) < 0) + goto error; ++ } else if (type == VIR_DOMAIN_VIRT_KVM && ++ virCPUGetHostIsSupported(qemuCaps->arch)) { ++ if (!(fullCPU = virCPUGetHost(qemuCaps->arch, VIR_CPU_TYPE_GUEST, ++ NULL, NULL, 0))) ++ goto error; ++ ++ for (i = 0; i < cpu->nfeatures; i++) { ++ if (cpu->features[i].policy == VIR_CPU_FEATURE_REQUIRE && ++ virCPUDefUpdateFeature(fullCPU, cpu->features[i].name, ++ VIR_CPU_FEATURE_REQUIRE) < 0) ++ goto error; ++ } + } + + if (!(migCPU = virQEMUCapsNewHostCPUModel())) +@@ -3378,7 +3408,7 @@ virQEMUCapsInitHostCPUModel(virQEMUCapsPtr qemuCaps, + goto error; + } + +- virQEMUCapsSetHostModel(qemuCaps, type, cpu, migCPU); ++ virQEMUCapsSetHostModel(qemuCaps, type, cpu, migCPU, fullCPU); + + cleanup: + virCPUDefFree(hostCPU); +@@ -3387,6 +3417,7 @@ virQEMUCapsInitHostCPUModel(virQEMUCapsPtr qemuCaps, + error: + virCPUDefFree(cpu); + virCPUDefFree(migCPU); ++ virCPUDefFree(fullCPU); + virResetLastError(); + goto cleanup; + } +diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h +index 31818c940..4e9561c0a 100644 +--- a/src/qemu/qemu_capabilities.h ++++ b/src/qemu/qemu_capabilities.h +@@ -455,6 +455,10 @@ typedef enum { + VIR_QEMU_CAPS_HOST_CPU_REPORTED, + /* Migratable host CPU definition used for updating guest CPU. */ + VIR_QEMU_CAPS_HOST_CPU_MIGRATABLE, ++ /* CPU definition with features detected by libvirt using virCPUGetHost ++ * combined with features reported by QEMU. This is used for backward ++ * compatible comparison between a guest CPU and a host CPU. */ ++ VIR_QEMU_CAPS_HOST_CPU_FULL, + } virQEMUCapsHostCPUType; + + virCPUDefPtr virQEMUCapsGetHostModel(virQEMUCapsPtr qemuCaps, +diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c +index e67736638..992a7174b 100644 +--- a/src/qemu/qemu_process.c ++++ b/src/qemu/qemu_process.c +@@ -5300,7 +5300,7 @@ qemuProcessUpdateGuestCPU(virDomainDefPtr def, + if (def->cpu->check == VIR_CPU_CHECK_PARTIAL && + virCPUCompare(caps->host.arch, + virQEMUCapsGetHostModel(qemuCaps, def->virtType, +- VIR_QEMU_CAPS_HOST_CPU_REPORTED), ++ VIR_QEMU_CAPS_HOST_CPU_FULL), + def->cpu, true) < 0) + return -1; + diff --git a/libvirt.spec b/libvirt.spec index b077b15..6124d5d 100644 --- a/libvirt.spec +++ b/libvirt.spec @@ -227,7 +227,7 @@ Summary: Library providing a simple virtualization API Name: libvirt Version: 3.2.1 -Release: 3%{?dist}%{?extra_release} +Release: 4%{?dist}%{?extra_release} License: LGPLv2+ Group: Development/Libraries BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root @@ -244,7 +244,22 @@ Patch0002: 0002-qemu-Use-GICv2-for-aarch64-virt-TCG-guests.patch Patch0003: 0003-gic-Remove-VIR_GIC_VERSION_DEFAULT.patch # Don't run libvirtd in live environment, to avoid network collision (bz # #1146232) -Patch0004: 0004-daemon-Don-t-run-if-in-a-Fedora-live-environment.patch +Patch0004: 0004-daemon-Don-t-run-if-in-a-Fedora-live-VM.patch +# Fix resuming qemu VMs suspended before libvirt 3.2.0 +Patch0005: 0005-Revert-qemu-propagate-bridge-MTU-into-qemu-host_mtu-.patch +# Fix issues with AMD CPU models, and some others +Patch0006: 0006-cpu-Introduce-virCPUCopyMigratable.patch +Patch0007: 0007-qemu-Move-common-code-in-virQEMUCapsInitCPUModel-one.patch +Patch0008: 0008-qemu-Add-migratable-parameter-to-virQEMUCapsInitCPUM.patch +Patch0009: 0009-qemu-Introduce-virQEMUCapsSetHostModel.patch +Patch0010: 0010-qemu-Move-qemuCaps-CPU-data-copying-into-a-separate-.patch +Patch0011: 0011-qemu-Introduce-virQEMUCapsHostCPUDataClear.patch +Patch0012: 0012-qemu-Move-qemuCaps-host-CPU-data-in-a-struct.patch +Patch0013: 0013-qemu-Prepare-qemuCaps-for-multiple-host-CPU-defs.patch +Patch0014: 0014-qemu-Pass-migratable-host-CPU-model-to-virCPUUpdate.patch +Patch0015: 0015-cpu-Drop-feature-filtering-from-virCPUUpdate.patch +Patch0016: 0016-cpu-Introduce-virCPUGetHostIsSupported.patch +Patch0017: 0017-qemu-Use-more-data-for-comparing-CPUs.patch Requires: libvirt-daemon = %{version}-%{release} Requires: libvirt-daemon-config-network = %{version}-%{release} @@ -2077,6 +2092,10 @@ exit 0 %changelog +* Wed Jul 12 2017 Cole Robinson - 3.2.1-4 +- Fix resuming qemu VMs suspended before libvirt 3.2.0 +- Fix issues with AMD CPU models, and some others + * Wed May 31 2017 Cole Robinson - 3.2.1-3 - Tweak condition for not starting in live environment (bz #1146232)