3e5111
From 7667b332ec942112270da554ded58658a78860b9 Mon Sep 17 00:00:00 2001
3e5111
Message-Id: <7667b332ec942112270da554ded58658a78860b9@dist-git>
3e5111
From: =?UTF-8?q?J=C3=A1n=20Tomko?= <jtomko@redhat.com>
3e5111
Date: Fri, 9 Jun 2017 12:49:00 +0200
3e5111
Subject: [PATCH] Add virtio-related options to interfaces
3e5111
MIME-Version: 1.0
3e5111
Content-Type: text/plain; charset=UTF-8
3e5111
Content-Transfer-Encoding: 8bit
3e5111
3e5111
<interface type='user'>
3e5111
  <mac address='52:54:56:5a:5c:5e'/>
3e5111
  <model type='virtio'/>
3e5111
  <driver iommu='on' ats='on'/>
3e5111
</interface>
3e5111
3e5111
https://bugzilla.redhat.com/show_bug.cgi?id=1283251
3e5111
3e5111
Reviewed-by: Pavel Hrdina <phrdina@redhat.com>
3e5111
(cherry picked from commit fd518643402d8233ceffe4ef28279bcce53284f6)
3e5111
Signed-off-by: Ján Tomko <jtomko@redhat.com>
3e5111
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
3e5111
---
3e5111
 docs/formatdomain.html.in                          |  19 ++++
3e5111
 docs/schemas/domaincommon.rng                      |  12 ++
3e5111
 src/conf/domain_conf.c                             | 121 +++++++++++++++++++++
3e5111
 src/conf/domain_conf.h                             |  10 ++
3e5111
 .../qemuxml2argv-virtio-options.xml                |   1 +
3e5111
 5 files changed, 163 insertions(+)
3e5111
3e5111
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
3e5111
index e8a3367bac..23546daae9 100644
3e5111
--- a/docs/formatdomain.html.in
3e5111
+++ b/docs/formatdomain.html.in
3e5111
@@ -3448,6 +3448,19 @@
3e5111
       
3e5111
     
3e5111
 
3e5111
+    

Virtio-related options

3e5111
+
3e5111
+    

3e5111
+      QEMU's virtio devices have some attributes related to the virtio transport under
3e5111
+      the driver element:
3e5111
+      The iommu attribute enables the use of emulated IOMMU
3e5111
+      by the device. The attribute ats controls the Address
3e5111
+      Translation Service support for PCIe devices. This is needed to make use
3e5111
+      of IOTLB support (see IOMMU device).
3e5111
+      Possible values are on or off.
3e5111
+      Since 3.5.0
3e5111
+    

3e5111
+
3e5111
     

Controllers

3e5111
 
3e5111
     

3e5111
@@ -5139,6 +5152,12 @@ qemu-kvm -net nic,model=? /dev/null
3e5111
         In general you should leave this option alone, unless you
3e5111
         are very certain you know what you are doing.
3e5111
       
3e5111
+      
virtio options
3e5111
+      
3e5111
+        For virtio interfaces,
3e5111
+        Virtio-specific options can also be
3e5111
+        set. (Since 3.5.0)
3e5111
+      
3e5111
     
3e5111
     

3e5111
       Offloading options for the host and guest can be configured using
3e5111
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
3e5111
index 1b66362f17..9e68bbc52d 100644
3e5111
--- a/docs/schemas/domaincommon.rng
3e5111
+++ b/docs/schemas/domaincommon.rng
3e5111
@@ -2632,6 +2632,7 @@
3e5111
               </optional>
3e5111
             </group>
3e5111
           </choice>
3e5111
+          <ref name="virtioOptions"/>
3e5111
           <interleave>
3e5111
             <optional>
3e5111
               <element name='host'>
3e5111
@@ -4952,6 +4953,17 @@
3e5111
     </element>
3e5111
   </define>
3e5111
 
3e5111
+  <define name="virtioOptions">
3e5111
+    <optional>
3e5111
+      <attribute name="iommu">
3e5111
+        <ref name="virOnOff"/>
3e5111
+      </attribute>
3e5111
+      <attribute name="ats">
3e5111
+        <ref name="virOnOff"/>
3e5111
+      </attribute>
3e5111
+    </optional>
3e5111
+  </define>
3e5111
+
3e5111
   <define name="usbmaster">
3e5111
     <element name="master">
3e5111
       <attribute name="startport">
3e5111
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
3e5111
index 4652e1c72b..bba50cf3fd 100644
3e5111
--- a/src/conf/domain_conf.c
3e5111
+++ b/src/conf/domain_conf.c
3e5111
@@ -1112,6 +1112,46 @@ virDomainXMLOptionGetNamespace(virDomainXMLOptionPtr xmlopt)
3e5111
     return &xmlopt->ns;
3e5111
 }
3e5111
 
3e5111
+static int
3e5111
+virDomainVirtioOptionsParseXML(xmlXPathContextPtr ctxt,
3e5111
+                               virDomainVirtioOptionsPtr *virtio)
3e5111
+{
3e5111
+    char *str = NULL;
3e5111
+    int ret = -1;
3e5111
+    int val;
3e5111
+    virDomainVirtioOptionsPtr res;
3e5111
+
3e5111
+    if (VIR_ALLOC(*virtio) < 0)
3e5111
+        return -1;
3e5111
+
3e5111
+    res = *virtio;
3e5111
+
3e5111
+    if ((str = virXPathString("string(./driver/@iommu)", ctxt))) {
3e5111
+        if ((val = virTristateSwitchTypeFromString(str)) <= 0) {
3e5111
+            virReportError(VIR_ERR_XML_ERROR, "%s",
3e5111
+                           _("invalid iommu value"));
3e5111
+            goto cleanup;
3e5111
+        }
3e5111
+        res->iommu = val;
3e5111
+    }
3e5111
+    VIR_FREE(str);
3e5111
+
3e5111
+    if ((str = virXPathString("string(./driver/@ats)", ctxt))) {
3e5111
+        if ((val = virTristateSwitchTypeFromString(str)) <= 0) {
3e5111
+            virReportError(VIR_ERR_XML_ERROR, "%s",
3e5111
+                           _("invalid ats value"));
3e5111
+            goto cleanup;
3e5111
+        }
3e5111
+        res->ats = val;
3e5111
+    }
3e5111
+
3e5111
+    ret = 0;
3e5111
+
3e5111
+ cleanup:
3e5111
+    VIR_FREE(str);
3e5111
+    return ret;
3e5111
+}
3e5111
+
3e5111
 
3e5111
 virSaveCookieCallbacksPtr
3e5111
 virDomainXMLOptionGetSaveCookie(virDomainXMLOptionPtr xmlopt)
3e5111
@@ -1953,6 +1993,7 @@ virDomainNetDefClear(virDomainNetDefPtr def)
3e5111
     VIR_FREE(def->ifname);
3e5111
     VIR_FREE(def->ifname_guest);
3e5111
     VIR_FREE(def->ifname_guest_actual);
3e5111
+    VIR_FREE(def->virtio);
3e5111
 
3e5111
     virNetDevIPInfoClear(&def->guestIP);
3e5111
     virNetDevIPInfoClear(&def->hostIP);
3e5111
@@ -4313,6 +4354,28 @@ virDomainHostdevDefPostParse(virDomainHostdevDefPtr dev,
3e5111
 
3e5111
 
3e5111
 static int
3e5111
+virDomainCheckVirtioOptions(virDomainVirtioOptionsPtr virtio)
3e5111
+{
3e5111
+    if (!virtio)
3e5111
+        return 0;
3e5111
+
3e5111
+    if (virtio->iommu != VIR_TRISTATE_SWITCH_ABSENT) {
3e5111
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
3e5111
+                       _("iommu driver option is only supported "
3e5111
+                         "for virtio devices"));
3e5111
+        return -1;
3e5111
+    }
3e5111
+    if (virtio->ats != VIR_TRISTATE_SWITCH_ABSENT) {
3e5111
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
3e5111
+                       _("ats driver option is only supported "
3e5111
+                         "for virtio devices"));
3e5111
+        return -1;
3e5111
+    }
3e5111
+    return 0;
3e5111
+}
3e5111
+
3e5111
+
3e5111
+static int
3e5111
 virDomainDeviceDefPostParseInternal(virDomainDeviceDefPtr dev,
3e5111
                                     const virDomainDef *def,
3e5111
                                     virCapsPtr caps ATTRIBUTE_UNUSED,
3e5111
@@ -4410,6 +4473,13 @@ virDomainDeviceDefPostParseInternal(virDomainDeviceDefPtr dev,
3e5111
         }
3e5111
     }
3e5111
 
3e5111
+    if (dev->type == VIR_DOMAIN_DEVICE_NET) {
3e5111
+        virDomainNetDefPtr net = dev->data.net;
3e5111
+        if (STRNEQ_NULLABLE(net->model, "virtio") &&
3e5111
+            virDomainCheckVirtioOptions(net->virtio) < 0)
3e5111
+            return -1;
3e5111
+    }
3e5111
+
3e5111
     return 0;
3e5111
 }
3e5111
 
3e5111
@@ -5208,6 +5278,24 @@ virDomainDefValidate(virDomainDefPtr def,
3e5111
 }
3e5111
 
3e5111
 
3e5111
+static void
3e5111
+virDomainVirtioOptionsFormat(virBufferPtr buf,
3e5111
+                             virDomainVirtioOptionsPtr virtio)
3e5111
+{
3e5111
+    if (!virtio)
3e5111
+        return;
3e5111
+
3e5111
+    if (virtio->iommu != VIR_TRISTATE_SWITCH_ABSENT) {
3e5111
+        virBufferAsprintf(buf, " iommu='%s'",
3e5111
+                          virTristateSwitchTypeToString(virtio->iommu));
3e5111
+    }
3e5111
+    if (virtio->ats != VIR_TRISTATE_SWITCH_ABSENT) {
3e5111
+        virBufferAsprintf(buf, " ats='%s'",
3e5111
+                          virTristateSwitchTypeToString(virtio->ats));
3e5111
+    }
3e5111
+}
3e5111
+
3e5111
+
3e5111
 /* Generate a string representation of a device address
3e5111
  * @info address Device address to stringify
3e5111
  */
3e5111
@@ -10354,6 +10442,9 @@ virDomainNetDefParseXML(virDomainXMLOptionPtr xmlopt,
3e5111
             goto error;
3e5111
     }
3e5111
 
3e5111
+    if (virDomainVirtioOptionsParseXML(ctxt, &def->virtio) < 0)
3e5111
+        goto error;
3e5111
+
3e5111
  cleanup:
3e5111
     ctxt->node = oldnode;
3e5111
     VIR_FREE(macaddr);
3e5111
@@ -18979,6 +19070,30 @@ virDomainDeviceInfoCheckABIStability(virDomainDeviceInfoPtr src,
3e5111
 
3e5111
 
3e5111
 static bool
3e5111
+virDomainVirtioOptionsCheckABIStability(virDomainVirtioOptionsPtr src,
3e5111
+                                        virDomainVirtioOptionsPtr dst)
3e5111
+{
3e5111
+    if (src->iommu != dst->iommu) {
3e5111
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
3e5111
+                       _("Target device iommu option '%s' does not "
3e5111
+                         "match source '%s'"),
3e5111
+                       virTristateSwitchTypeToString(dst->iommu),
3e5111
+                       virTristateSwitchTypeToString(src->iommu));
3e5111
+        return false;
3e5111
+    }
3e5111
+    if (src->ats != dst->ats) {
3e5111
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
3e5111
+                       _("Target device ats option '%s' does not "
3e5111
+                         "match source '%s'"),
3e5111
+                       virTristateSwitchTypeToString(dst->ats),
3e5111
+                       virTristateSwitchTypeToString(src->ats));
3e5111
+        return false;
3e5111
+    }
3e5111
+    return true;
3e5111
+}
3e5111
+
3e5111
+
3e5111
+static bool
3e5111
 virDomainDiskDefCheckABIStability(virDomainDiskDefPtr src,
3e5111
                                   virDomainDiskDefPtr dst)
3e5111
 {
3e5111
@@ -19137,6 +19252,10 @@ virDomainNetDefCheckABIStability(virDomainNetDefPtr src,
3e5111
         return false;
3e5111
     }
3e5111
 
3e5111
+    if (src->virtio && dst->virtio &&
3e5111
+        !virDomainVirtioOptionsCheckABIStability(src->virtio, dst->virtio))
3e5111
+        return false;
3e5111
+
3e5111
     if (!virDomainDeviceInfoCheckABIStability(&src->info, &dst->info))
3e5111
         return false;
3e5111
 
3e5111
@@ -22074,6 +22193,8 @@ virDomainVirtioNetDriverFormat(char **outstr,
3e5111
         virBufferAsprintf(&buf, " rx_queue_size='%u'",
3e5111
                           def->driver.virtio.rx_queue_size);
3e5111
 
3e5111
+    virDomainVirtioOptionsFormat(&buf, def->virtio);
3e5111
+
3e5111
     if (virBufferCheckError(&buf) < 0)
3e5111
         return -1;
3e5111
 
3e5111
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
3e5111
index e6c20a9e1e..603d35bd50 100644
3e5111
--- a/src/conf/domain_conf.h
3e5111
+++ b/src/conf/domain_conf.h
3e5111
@@ -156,6 +156,9 @@ typedef virDomainTPMDef *virDomainTPMDefPtr;
3e5111
 typedef struct _virDomainIOMMUDef virDomainIOMMUDef;
3e5111
 typedef virDomainIOMMUDef *virDomainIOMMUDefPtr;
3e5111
 
3e5111
+typedef struct _virDomainVirtioOptions virDomainVirtioOptions;
3e5111
+typedef virDomainVirtioOptions *virDomainVirtioOptionsPtr;
3e5111
+
3e5111
 /* Flags for the 'type' field in virDomainDeviceDef */
3e5111
 typedef enum {
3e5111
     VIR_DOMAIN_DEVICE_NONE = 0,
3e5111
@@ -1040,6 +1043,7 @@ struct _virDomainNetDef {
3e5111
     int linkstate;
3e5111
     unsigned int mtu;
3e5111
     virNetDevCoalescePtr coalesce;
3e5111
+    virDomainVirtioOptionsPtr virtio;
3e5111
 };
3e5111
 
3e5111
 typedef enum {
3e5111
@@ -2215,6 +2219,12 @@ struct _virDomainIOMMUDef {
3e5111
     virTristateSwitch eim;
3e5111
     virTristateSwitch iotlb;
3e5111
 };
3e5111
+
3e5111
+struct _virDomainVirtioOptions {
3e5111
+    virTristateSwitch iommu;
3e5111
+    virTristateSwitch ats;
3e5111
+};
3e5111
+
3e5111
 /*
3e5111
  * Guest VM main configuration
3e5111
  *
3e5111
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-virtio-options.xml b/tests/qemuxml2argvdata/qemuxml2argv-virtio-options.xml
3e5111
index c88cf649b1..3357bc6d1b 100644
3e5111
--- a/tests/qemuxml2argvdata/qemuxml2argv-virtio-options.xml
3e5111
+++ b/tests/qemuxml2argvdata/qemuxml2argv-virtio-options.xml
3e5111
@@ -47,6 +47,7 @@
3e5111
     <interface type='user'>
3e5111
       <mac address='52:54:56:58:5a:5c'/>
3e5111
       <model type='virtio'/>
3e5111
+      <driver iommu='on' ats='on'/>
3e5111
       <address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/>
3e5111
     </interface>
3e5111
     <input type='mouse' bus='virtio'>
3e5111
-- 
3e5111
2.13.1
3e5111