Implement "iommufdId" and "iommufdFd" attributes for "hostdev" devices that
can be used to specify associated iommufd object and fd for externally opening
the /dev/iommu and VFIO cdev, when launching a qemu VM.

Signed-off-by: Nathan Chen <nath...@nvidia.com>
---
 src/conf/domain_conf.c            | 31 +++++++++++++++++++++++++++++++
 src/conf/domain_conf.h            |  2 ++
 src/conf/domain_validate.c        | 14 ++++++++++++++
 src/conf/schemas/domaincommon.rng | 17 +++++++++++++++++
 src/qemu/qemu_command.c           |  2 ++
 5 files changed, 66 insertions(+)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 9330c47b7a..47b7e9acb1 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -13582,6 +13582,19 @@ virDomainVideoDefParseXML(virDomainXMLOption *xmlopt,
     return g_steal_pointer(&def);
 }
 
+static void
+virDomainHostdevDefIommufdParseXML(xmlXPathContextPtr ctxt,
+                                   char** iommufdId,
+                                   char** iommufdFd)
+{
+    g_autofree char *iommufdIdtmp = virXPathString("string(./iommufdId)", 
ctxt);
+    g_autofree char *iommufdFdtmp = virXPathString("string(./iommufdFd)", 
ctxt);
+    if (iommufdIdtmp)
+        *iommufdId = g_steal_pointer(&iommufdIdtmp);
+    if (iommufdFdtmp)
+        *iommufdFd = g_steal_pointer(&iommufdFdtmp);
+}
+
 static virDomainHostdevDef *
 virDomainHostdevDefParseXML(virDomainXMLOption *xmlopt,
                             xmlNodePtr node,
@@ -13656,6 +13669,8 @@ virDomainHostdevDefParseXML(virDomainXMLOption *xmlopt,
     if (virDomainNetTeamingInfoParseXML(ctxt, &def->teaming) < 0)
         goto error;
 
+    virDomainHostdevDefIommufdParseXML(ctxt, &def->iommufdId, &def->iommufdFd);
+
     return def;
 
  error:
@@ -21193,6 +21208,16 @@ 
virDomainHostdevDefCheckABIStability(virDomainHostdevDef *src,
         }
     }
 
+    if (src->iommufdId && dst->iommufdId) {
+        if (STRNEQ(src->iommufdId, dst->iommufdId))
+            return false;
+    }
+
+    if (src->iommufdFd && dst->iommufdFd) {
+        if (STRNEQ(src->iommufdFd, dst->iommufdFd))
+            return false;
+    }
+
     if (!virDomainDeviceInfoCheckABIStability(src->info, dst->info))
         return false;
 
@@ -27511,6 +27536,12 @@ virDomainHostdevDefFormat(virBuffer *buf,
     if (def->shareable)
         virBufferAddLit(buf, "<shareable/>\n");
 
+    if (def->iommufdId) {
+        virBufferAsprintf(buf, "<iommufdId>%s</iommufdId>\n", def->iommufdId);
+        if (def->iommufdFd)
+            virBufferAsprintf(buf, "<iommufdFd>%s</iommufdFd>\n", 
def->iommufdFd);
+    }
+
     virDomainDeviceInfoFormat(buf, def->info, flags | 
VIR_DOMAIN_DEF_FORMAT_ALLOW_BOOT
                                                     | 
VIR_DOMAIN_DEF_FORMAT_ALLOW_ROM);
 
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index ce447e9823..78507d78b7 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -375,6 +375,8 @@ struct _virDomainHostdevDef {
         virDomainHostdevCaps caps;
     } source;
     virDomainNetTeamingInfo *teaming;
+    char *iommufdId;
+    char *iommufdFd;
     virDomainDeviceInfo *info; /* Guest address */
 };
 
diff --git a/src/conf/domain_validate.c b/src/conf/domain_validate.c
index 88649ba0b9..292398b115 100644
--- a/src/conf/domain_validate.c
+++ b/src/conf/domain_validate.c
@@ -1401,6 +1401,20 @@ virDomainDefHostdevValidate(const virDomainDef *def)
                 ramfbEnabled = true;
             }
         }
+
+        /* Check for unsupported conditions:
+         * - A hostdev's iommufd fd number is defined but its iommufd id
+         * number is not
+         * - An iommu device is defined, iommufd is not defined,
+         * but a hostdev's iommufd id or fd are defined */
+        if ((!dev->iommufdId && dev->iommufdFd) ||
+            (def->iommu && def->niommus > 0 &&
+             !def->iommu[0]->iommufd &&
+             (dev->iommufdId || dev->iommufdFd))) {
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+                           _("Unsupported hostdev iommufd configuration"));
+            return -1;
+        }
     }
 
     return 0;
diff --git a/src/conf/schemas/domaincommon.rng 
b/src/conf/schemas/domaincommon.rng
index 41db338c71..6c1f901eb4 100644
--- a/src/conf/schemas/domaincommon.rng
+++ b/src/conf/schemas/domaincommon.rng
@@ -6442,6 +6442,12 @@
         <optional>
           <ref name="address"/>
         </optional>
+        <optional>
+          <ref name="iommufdId"/>
+        </optional>
+        <optional>
+          <ref name="iommufdFd"/>
+        </optional>
         <optional>
           <element name="readonly">
             <empty/>
@@ -7809,6 +7815,17 @@
     </element>
   </define>
 
+  <define name="iommufdId">
+    <element name="iommufdId">
+      <text/>
+    </element>
+  </define>
+  <define name="iommufdFd">
+    <element name="iommufdFd">
+      <text/>
+    </element>
+  </define>
+
   <define name="deviceBoot">
     <element name="boot">
       <attribute name="order">
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index d683d0eef7..3a8b71a00a 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -4724,6 +4724,8 @@ qemuBuildPCIHostdevDevProps(const virDomainDef *def,
                               "S:failover_pair_id", failover_pair_id,
                               "S:display", qemuOnOffAuto(pcisrc->display),
                               "B:ramfb", ramfb,
+                              "S:iommufd", dev->iommufdId,
+                              "S:fd", dev->iommufdFd,
                               NULL) < 0)
         return NULL;
 
-- 
2.43.0

Reply via email to