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