diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 33cec1e6dd..6ebf19ae57 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -1490,7 +1490,7 @@ ...
-<cpu mode='host-passthrough'>
+<cpu mode='host-passthrough' migratable='off'>
   <cache mode='passthrough'/>
   <feature policy='disable' name='lahf_lm'/>
 ...
@@ -1639,7 +1639,17 @@ using host-passthrough is dangerous if the source and destination hosts are not identical in both hardware, QEMU version, microcode version and configuration. If such a migration is attempted then the guest may - hang or crash upon resuming execution on the destination host. + hang or crash upon resuming execution on the destination host. + Depending on hypervisor version the virtual CPU may or may not + contain features which may block migration even to an identical host. + Since 6.5.0 optional + migratable attribute may be used to explicitly request + such features to be removed from (on) or kept in + (off) the virtual CPU. This attribute does not make + migration to another host safer: even with + migratable='on' migration will be dangerous unless both + hosts are identical as described above. + Both host-model and host-passthrough modes diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 6727cd743b..19242a9a32 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -5469,6 +5469,11 @@ + + + + + diff --git a/src/conf/cpu_conf.c b/src/conf/cpu_conf.c index 25648a946c..b40737e407 100644 --- a/src/conf/cpu_conf.c +++ b/src/conf/cpu_conf.c @@ -243,6 +243,7 @@ virCPUDefCopyWithoutModel(const virCPUDef *cpu) copy->cores = cpu->cores; copy->threads = cpu->threads; copy->arch = cpu->arch; + copy->migratable = cpu->migratable; if (cpu->cache) { if (VIR_ALLOC(copy->cache) < 0) @@ -333,6 +334,7 @@ virCPUDefParseXML(xmlXPathContextPtr ctxt, g_autofree char *fallback = NULL; g_autofree char *vendor_id = NULL; g_autofree char *tscScaling = NULL; + g_autofree char *migratable = NULL; virHostCPUTscInfoPtr tsc = NULL; *cpu = NULL; @@ -386,6 +388,26 @@ virCPUDefParseXML(xmlXPathContextPtr ctxt, def->mode = VIR_CPU_MODE_CUSTOM; } + if ((migratable = virXMLPropString(ctxt->node, "migratable"))) { + int val; + + if (def->mode != VIR_CPU_MODE_HOST_PASSTHROUGH) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Attribute migratable is only allowed for " + "host-passthrough CPU")); + return -1; + } + + if ((val = virTristateSwitchTypeFromString(migratable)) < 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Invalid value in migratable attribute: '%s'"), + migratable); + return -1; + } + + def->migratable = val; + } + if (def->type == VIR_CPU_TYPE_GUEST) { g_autofree char *match = virXMLPropString(ctxt->node, "match"); g_autofree char *check = NULL; @@ -698,6 +720,11 @@ virCPUDefFormatBufFull(virBufferPtr buf, virBufferAsprintf(&attributeBuf, " check='%s'", virCPUCheckTypeToString(def->check)); } + + if (def->mode == VIR_CPU_MODE_HOST_PASSTHROUGH && def->migratable) { + virBufferAsprintf(&attributeBuf, " migratable='%s'", + virTristateSwitchTypeToString(def->migratable)); + } } /* Format children */ diff --git a/src/conf/cpu_conf.h b/src/conf/cpu_conf.h index a95d56d017..24c51e3a63 100644 --- a/src/conf/cpu_conf.h +++ b/src/conf/cpu_conf.h @@ -141,6 +141,7 @@ struct _virCPUDef { virCPUFeatureDefPtr features; virCPUCacheDefPtr cache; virHostCPUTscInfoPtr tsc; + virTristateSwitch migratable; /* for host-passthrough mode */ }; virCPUDefPtr virCPUDefNew(void);