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 <nathanc(a)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