diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 81060d6730..9ccae54e04 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -2063,6 +2063,7 @@ </kvm> <xen> <e820_host state='on'/> + <passthrough state='on' mode='share_pt'/> </xen> <pvspinlock state='on'/> <gic version='2'/> @@ -2260,6 +2261,12 @@ on, off 6.3.0 + + passthrough + Enable IOMMU mappings allowing PCI passthrough) + on, off; mode - optional string sync_pt or share_pt + 6.3.0 +
pmu
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index 2b5f844658..a6f6e8ab83 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -6349,6 +6349,18 @@ + + + + + + + (sync_pt|share_pt) + + + + + diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index dabbceb265..9f3362c934 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -209,7 +209,15 @@ VIR_ENUM_IMPL(virDomainKVM, VIR_ENUM_IMPL(virDomainXen, VIR_DOMAIN_XEN_LAST, - "e820_host" + "e820_host", + "passthrough", +); + +VIR_ENUM_IMPL(virDomainXenPassthroughMode, + VIR_DOMAIN_XEN_PASSTHROUGH_MODE_LAST, + "default", + "sync_pt", + "share_pt", ); VIR_ENUM_IMPL(virDomainMsrsUnknown, @@ -21182,6 +21190,8 @@ virDomainDefParseXML(xmlDocPtr xml, if (def->features[VIR_DOMAIN_FEATURE_XEN] == VIR_TRISTATE_SWITCH_ON) { int feature; int value; + g_autofree char *ptval = NULL; + if ((n = virXPathNodeSet("./features/xen/*", ctxt, &nodes)) < 0) goto error; @@ -21194,28 +21204,54 @@ virDomainDefParseXML(xmlDocPtr xml, goto error; } + if (!(tmp = virXMLPropString(nodes[i], "state"))) { + virReportError(VIR_ERR_XML_ERROR, + _("missing 'state' attribute for " + "Xen feature '%s'"), + nodes[i]->name); + goto error; + } + + if ((value = virTristateSwitchTypeFromString(tmp)) < 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("invalid value of state argument " + "for Xen feature '%s'"), + nodes[i]->name); + goto error; + } + + VIR_FREE(tmp); + def->xen_features[feature] = value; + switch ((virDomainXen) feature) { case VIR_DOMAIN_XEN_E820_HOST: - if (!(tmp = virXMLPropString(nodes[i], "state"))) { - virReportError(VIR_ERR_XML_ERROR, - _("missing 'state' attribute for " - "Xen feature '%s'"), - nodes[i]->name); - goto error; - } - - if ((value = virTristateSwitchTypeFromString(tmp)) < 0) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("invalid value of state argument " - "for Xen feature '%s'"), - nodes[i]->name); - goto error; - } - - VIR_FREE(tmp); - def->xen_features[feature] = value; break; + case VIR_DOMAIN_XEN_PASSTHROUGH: + if (value != VIR_TRISTATE_SWITCH_ON) + break; + + if ((ptval = virXMLPropString(nodes[i], "mode"))) { + int mode = virDomainXenPassthroughModeTypeFromString(ptval); + + if (mode < 0) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unsupported mode '%s' for Xen passthrough feature"), + ptval); + goto error; + } + + if (mode != VIR_DOMAIN_XEN_PASSTHROUGH_MODE_SYNC_PT && + mode != VIR_DOMAIN_XEN_PASSTHROUGH_MODE_SHARE_PT) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("'mode' attribute for Xen feature " + "'passthrough' must be 'sync_pt' or 'share_pt'")); + goto error; + } + def->xen_passthrough_mode = mode; + } + break; + /* coverity[dead_error_begin] */ case VIR_DOMAIN_XEN_LAST: break; @@ -23400,18 +23436,28 @@ virDomainDefFeaturesCheckABIStability(virDomainDefPtr src, /* xen */ if (src->features[VIR_DOMAIN_FEATURE_XEN] == VIR_TRISTATE_SWITCH_ON) { for (i = 0; i < VIR_DOMAIN_XEN_LAST; i++) { + if (src->xen_features[i] != dst->xen_features[i]) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("State of Xen feature '%s' differs: " + "source: '%s', destination: '%s'"), + virDomainXenTypeToString(i), + virTristateSwitchTypeToString(src->xen_features[i]), + virTristateSwitchTypeToString(dst->xen_features[i])); + return false; + } switch ((virDomainXen) i) { case VIR_DOMAIN_XEN_E820_HOST: - if (src->xen_features[i] != dst->xen_features[i]) { + break; + + case VIR_DOMAIN_XEN_PASSTHROUGH: + if (src->xen_passthrough_mode != dst->xen_passthrough_mode) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("State of Xen feature '%s' differs: " + _("'mode' of Xen passthrough feature differs: " "source: '%s', destination: '%s'"), - virDomainXenTypeToString(i), - virTristateSwitchTypeToString(src->xen_features[i]), - virTristateSwitchTypeToString(dst->xen_features[i])); + virDomainXenPassthroughModeTypeToString(src->xen_passthrough_mode), + virDomainXenPassthroughModeTypeToString(dst->xen_passthrough_mode)); return false; } - break; /* coverity[dead_error_begin] */ @@ -29047,13 +29093,30 @@ virDomainDefFormatFeatures(virBufferPtr buf, virBufferAddLit(&childBuf, "\n"); virBufferAdjustIndent(&childBuf, 2); for (j = 0; j < VIR_DOMAIN_XEN_LAST; j++) { + if (def->xen_features[j] == VIR_TRISTATE_SWITCH_ABSENT) + continue; + + virBufferAsprintf(&childBuf, "<%s state='%s'", + virDomainXenTypeToString(j), + virTristateSwitchTypeToString( + def->xen_features[j])); + switch ((virDomainXen) j) { case VIR_DOMAIN_XEN_E820_HOST: - if (def->xen_features[j]) - virBufferAsprintf(&childBuf, "<%s state='%s'/>\n", - virDomainXenTypeToString(j), - virTristateSwitchTypeToString( - def->xen_features[j])); + virBufferAddLit(&childBuf, "/>\n"); + break; + case VIR_DOMAIN_XEN_PASSTHROUGH: + if (def->xen_features[j] != VIR_TRISTATE_SWITCH_ON) { + virBufferAddLit(&childBuf, "/>\n"); + break; + } + if (def->xen_passthrough_mode == VIR_DOMAIN_XEN_PASSTHROUGH_MODE_SYNC_PT || + def->xen_passthrough_mode == VIR_DOMAIN_XEN_PASSTHROUGH_MODE_SHARE_PT) { + virBufferEscapeString(&childBuf, " mode='%s'/>\n", + virDomainXenPassthroughModeTypeToString(def->xen_passthrough_mode)); + } else { + virBufferAddLit(&childBuf, "/>\n"); + } break; /* coverity[dead_error_begin] */ diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index fde88b7389..bfd1bbb532 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1862,10 +1862,19 @@ typedef enum { typedef enum { VIR_DOMAIN_XEN_E820_HOST = 0, + VIR_DOMAIN_XEN_PASSTHROUGH, VIR_DOMAIN_XEN_LAST } virDomainXen; +typedef enum { + VIR_DOMAIN_XEN_PASSTHROUGH_MODE_DEFAULT = 0, + VIR_DOMAIN_XEN_PASSTHROUGH_MODE_SYNC_PT, + VIR_DOMAIN_XEN_PASSTHROUGH_MODE_SHARE_PT, + + VIR_DOMAIN_XEN_PASSTHROUGH_MODE_LAST +} virDomainXenPassthroughMode; + typedef enum { VIR_DOMAIN_CAPABILITIES_POLICY_DEFAULT = 0, VIR_DOMAIN_CAPABILITIES_POLICY_ALLOW, @@ -2492,6 +2501,7 @@ struct _virDomainDef { int kvm_features[VIR_DOMAIN_KVM_LAST]; int msrs_features[VIR_DOMAIN_MSRS_LAST]; int xen_features[VIR_DOMAIN_XEN_LAST]; + int xen_passthrough_mode; unsigned int hyperv_spinlocks; int hyperv_stimer_direct; virGICVersion gic_version; @@ -3538,6 +3548,7 @@ VIR_ENUM_DECL(virDomainGraphicsVNCSharePolicy); VIR_ENUM_DECL(virDomainHyperv); VIR_ENUM_DECL(virDomainKVM); VIR_ENUM_DECL(virDomainXen); +VIR_ENUM_DECL(virDomainXenPassthroughMode); VIR_ENUM_DECL(virDomainMsrsUnknown); VIR_ENUM_DECL(virDomainRNGModel); VIR_ENUM_DECL(virDomainRNGBackend);