From: Nathan Chen <[email protected]>

Implement a new iommufd attribute under hostdevs' PCI
subsystem driver that can be used to specify associated
iommufd object when launching a qemu VM.

Signed-off-by: Ján Tomko <[email protected]>
Signed-off-by: Nathan Chen <[email protected]>
---
 docs/formatdomain.rst           |  7 +++++
 src/conf/device_conf.c          | 11 ++++++++
 src/conf/device_conf.h          |  1 +
 src/conf/schemas/basictypes.rng |  5 ++++
 src/qemu/qemu_command.c         | 46 +++++++++++++++++++++++++++++++++
 5 files changed, 70 insertions(+)

diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst
index 1467fc7e10..c8f827d460 100644
--- a/docs/formatdomain.rst
+++ b/docs/formatdomain.rst
@@ -4907,6 +4907,13 @@ or:
    found is "problematic" in some way, the generic vfio-pci driver
    similarly be forced.
 
+   The ``<driver>`` element's ``iommufd`` attribute is used to specify
+   using the iommufd interface to propagate DMA mappings to the kernel,
+   instead of VFIO alone. When the attribute is present, an iommufd
+   object will be created by the resulting qemu command. Libvirt will
+   open the /dev/iommu and VFIO device cdev, passing the associated
+   file descriptor numbers to the qemu command.
+
    (Note: :since:`Since 1.0.5`, the ``name`` attribute has been
    described to be used to select the type of PCI device assignment
    ("vfio", "kvm", or "xen"), but those values have been mostly
diff --git a/src/conf/device_conf.c b/src/conf/device_conf.c
index c278b81652..d68232a4f4 100644
--- a/src/conf/device_conf.c
+++ b/src/conf/device_conf.c
@@ -67,6 +67,11 @@ virDeviceHostdevPCIDriverInfoParseXML(xmlNodePtr node,
         return -1;
     }
 
+    if (virXMLPropTristateBool(node, "iommufd",
+                               VIR_XML_PROP_NONE,
+                               &driver->iommufd) < 0)
+        return -1;
+
     driver->model = virXMLPropString(node, "model");
     return 0;
 }
@@ -93,6 +98,12 @@ virDeviceHostdevPCIDriverInfoFormat(virBuffer *buf,
 
     virBufferEscapeString(&driverAttrBuf, " model='%s'", driver->model);
 
+    if (driver->iommufd == VIR_TRISTATE_BOOL_YES) {
+        virBufferAddLit(&driverAttrBuf, " iommufd='yes'");
+    } else if (driver->iommufd == VIR_TRISTATE_BOOL_NO) {
+        virBufferAddLit(&driverAttrBuf, " iommufd='no'");
+    }
+
     virXMLFormatElement(buf, "driver", &driverAttrBuf, NULL);
     return 0;
 }
diff --git a/src/conf/device_conf.h b/src/conf/device_conf.h
index e570f51824..116b959143 100644
--- a/src/conf/device_conf.h
+++ b/src/conf/device_conf.h
@@ -47,6 +47,7 @@ VIR_ENUM_DECL(virDeviceHostdevPCIDriverName);
 struct _virDeviceHostdevPCIDriverInfo {
     virDeviceHostdevPCIDriverName name;
     char *model;
+    virTristateBool iommufd;
 };
 
 typedef enum {
diff --git a/src/conf/schemas/basictypes.rng b/src/conf/schemas/basictypes.rng
index 5689170fad..381e0ac24f 100644
--- a/src/conf/schemas/basictypes.rng
+++ b/src/conf/schemas/basictypes.rng
@@ -673,6 +673,11 @@
           <ref name="genericName"/>
         </attribute>
       </optional>
+      <optional>
+        <attribute name="iommufd">
+          <ref name="virYesNo"/>
+        </attribute>
+      </optional>
       <empty/>
     </element>
   </define>
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 98229d7cf9..98e4469c25 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -4760,6 +4760,7 @@ qemuBuildPCIHostdevDevProps(const virDomainDef *def,
     g_autofree char *host = virPCIDeviceAddressAsString(&pcisrc->addr);
     const char *failover_pair_id = NULL;
     const char *driver = NULL;
+    const char *iommufdId = NULL;
     /* 'ramfb' property must be omitted unless it's to be enabled */
     bool ramfb = pcisrc->ramfb == VIR_TRISTATE_SWITCH_ON;
 
@@ -4793,6 +4794,9 @@ qemuBuildPCIHostdevDevProps(const virDomainDef *def,
         teaming->persistent)
         failover_pair_id = teaming->persistent;
 
+    if (pcisrc->driver.iommufd == VIR_TRISTATE_BOOL_YES)
+        iommufdId = "iommufd0";
+
     if (virJSONValueObjectAdd(&props,
                               "s:driver", driver,
                               "s:host", host,
@@ -4801,6 +4805,7 @@ qemuBuildPCIHostdevDevProps(const virDomainDef *def,
                               "S:failover_pair_id", failover_pair_id,
                               "S:display", qemuOnOffAuto(pcisrc->display),
                               "B:ramfb", ramfb,
+                              "S:iommufd", iommufdId,
                               NULL) < 0)
         return NULL;
 
@@ -5320,6 +5325,44 @@ qemuBuildHostdevCommandLine(virCommand *cmd,
 }
 
 
+static int
+qemuBuildIOMMUFDCommandLine(virCommand *cmd,
+                            const virDomainDef *def)
+{
+    size_t i;
+
+    for (i = 0; i < def->nhostdevs; i++) {
+        virDomainHostdevDef *hostdev = def->hostdevs[i];
+        virDomainHostdevSubsys *subsys = &hostdev->source.subsys;
+        g_autoptr(virJSONValue) props = NULL;
+
+        if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
+            continue;
+
+        if (subsys->type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
+            continue;
+
+        if (hostdev->info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_UNASSIGNED)
+            continue;
+
+        if (subsys->u.pci.driver.iommufd != VIR_TRISTATE_BOOL_YES)
+            continue;
+
+        if (qemuMonitorCreateObjectProps(&props, "iommufd",
+                                         "iommufd0",
+                                         NULL) < 0)
+            return -1;
+
+        if (qemuBuildObjectCommandlineFromJSON(cmd, props) < 0)
+            return -1;
+
+        break;
+    }
+
+    return 0;
+}
+
+
 static int
 qemuBuildMonitorCommandLine(virCommand *cmd,
                             qemuDomainObjPrivate *priv)
@@ -10932,6 +10975,9 @@ qemuBuildCommandLine(virDomainObj *vm,
     if (qemuBuildRedirdevCommandLine(cmd, def, qemuCaps) < 0)
         return NULL;
 
+    if (qemuBuildIOMMUFDCommandLine(cmd, def) < 0)
+        return NULL;
+
     if (qemuBuildHostdevCommandLine(cmd, def, qemuCaps) < 0)
         return NULL;
 
-- 
2.43.0

Reply via email to