]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
conf: add xen hypervisor feature 'passthrough'
authorJim Fehlig <jfehlig@suse.com>
Wed, 15 Apr 2020 22:34:54 +0000 (16:34 -0600)
committerJim Fehlig <jfehlig@suse.com>
Tue, 21 Apr 2020 15:18:58 +0000 (09:18 -0600)
'passthrough' is Xen-Specific guest configuration option new to Xen 4.13
that enables IOMMU mappings for a guest and hence whether it supports PCI
passthrough. The default is disabled. See the xl.cfg(5) man page and
xen.git commit babde47a3fe for more details.

The default state of disabled prevents hotlugging PCI devices. However,
if the guest configuration contains a PCI passthrough device at time of
creation, libxl will automatically enable 'passthrough' and subsequent
hotplugging of PCI devices will also be possible. It is not possible to
unconditionally enable 'passthrough' since it would introduce a migration
incompatibility due to guest ABI change. Instead, introduce another Xen
hypervisor feature that can be used to enable guest PCI passthrough

  <features>
    <xen>
      <passthrough state='on'/>
    </xen>
  </features>

To allow finer control over how IOMMU maps to guest P2M table, the
passthrough element also supports a 'mode' attribute with values
restricted to snyc_pt and share_pt, similar to xl.cfg(5) 'passthrough'
setting .

Signed-off-by: Jim Fehlig <jfehlig@suse.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
docs/formatdomain.html.in
docs/schemas/domaincommon.rng
src/conf/domain_conf.c
src/conf/domain_conf.h

index 81060d673053d7898fd53e6a2de41bc635f7a98c..9ccae54e04347e7d61517ed19a0972f2365767d5 100644 (file)
   &lt;/kvm&gt;
   &lt;xen&gt;
     &lt;e820_host state='on'/&gt;
+    &lt;passthrough state='on' mode='share_pt'/&gt;
   &lt;/xen&gt;
   &lt;pvspinlock state='on'/&gt;
   &lt;gic version='2'/&gt;
           <td>on, off</td>
           <td><span class="since">6.3.0</span></td>
         </tr>
+        <tr>
+          <td>passthrough</td>
+          <td>Enable IOMMU mappings allowing PCI passthrough)</td>
+          <td>on, off; mode - optional string sync_pt or share_pt</td>
+          <td><span class="since">6.3.0</span></td>
+        </tr>
       </table>
       </dd>
       <dt><code>pmu</code></dt>
index 2b5f8446588de6ba1d82260ed8a6d2049708a85f..a6f6e8ab835ab8bc911d9d3968e17b32acbdc9e5 100644 (file)
             <ref name="featurestate"/>
           </element>
         </optional>
+        <optional>
+          <element name="passthrough">
+            <ref name="featurestate"/>
+            <optional>
+              <attribute name="mode">
+                <data type="string">
+                  <param name='pattern'>(sync_pt|share_pt)</param>
+                </data>
+              </attribute>
+            </optional>
+          </element>
+        </optional>
       </interleave>
     </element>
   </define>
index dabbceb26561f1aa021dc6763d0256c987beb453..9f3362c9346637444f0221c88173351588b9e433 100644 (file)
@@ -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,27 +21204,53 @@ 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;
-                    }
+                    break;
 
-                    if ((value = virTristateSwitchTypeFromString(tmp)) < 0) {
+            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,
-                                       _("invalid value of state argument "
-                                         "for Xen feature '%s'"),
-                                       nodes[i]->name);
+                                       _("unsupported mode '%s' for Xen passthrough feature"),
+                                       ptval);
                         goto error;
                     }
 
-                    VIR_FREE(tmp);
-                    def->xen_features[feature] = value;
-                    break;
+                    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:
@@ -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, "<xen>\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] */
index fde88b7389ddd46063624250a391a8cf5360329a..bfd1bbb53258840169853914dc7b6f2523a3cc15 100644 (file)
@@ -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);