Implement iommufdId attribute for hostdev devices that
can be used to specify associated iommufd object when
launching a qemu VM.
Signed-off-by: Nathan Chen <nathanc(a)nvidia.com>
---
docs/formatdomain.rst | 9 +++++++++
src/conf/domain_conf.c | 20 ++++++++++++++++++++
src/conf/domain_conf.h | 1 +
src/conf/schemas/domaincommon.rng | 9 +++++++++
src/qemu/qemu_command.c | 14 ++++++++++++++
5 files changed, 53 insertions(+)
diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst
index 2558df18ef..e2b9be16c9 100644
--- a/docs/formatdomain.rst
+++ b/docs/formatdomain.rst
@@ -4581,6 +4581,7 @@ or:
</source>
<boot order='1'/>
<rom bar='on' file='/etc/fake/boot.bin'/>
+ <iommufdId>iommufd0</iommufdId>
</hostdev>
</devices>
...
@@ -4829,6 +4830,14 @@ or:
device; if PCI ROM loading is disabled through this attribute, attempts to
tweak the loading process further using the ``bar`` or ``file`` attributes
will be rejected. :since:`Since 4.3.0 (QEMU and KVM only)`.
+``iommufdId``
+ The ``iommufdId`` element is used to specify using the iommufd interface to
+ propagate DMA mappings to the kernel, instead of legacy VFIO. When the
+ element is present, an iommufd object with its ID specified by ``iommufdId``
+ 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.
+
``address``
The ``address`` element for USB devices has a ``bus`` and ``device``
attribute to specify the USB bus and device number the device appears at on
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 5ea4d6424b..38d8f2998a 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -13581,6 +13581,15 @@ virDomainVideoDefParseXML(virDomainXMLOption *xmlopt,
return g_steal_pointer(&def);
}
+static void
+virDomainHostdevDefIommufdParseXML(xmlXPathContextPtr ctxt,
+ char** iommufdId)
+{
+ g_autofree char *iommufdIdtmp = virXPathString("string(./iommufdId)",
ctxt);
+ if (iommufdIdtmp)
+ *iommufdId = g_steal_pointer(&iommufdIdtmp);
+}
+
static virDomainHostdevDef *
virDomainHostdevDefParseXML(virDomainXMLOption *xmlopt,
xmlNodePtr node,
@@ -13655,6 +13664,8 @@ virDomainHostdevDefParseXML(virDomainXMLOption *xmlopt,
if (virDomainNetTeamingInfoParseXML(ctxt, &def->teaming) < 0)
goto error;
+ virDomainHostdevDefIommufdParseXML(ctxt, &def->iommufdId);
+
return def;
error:
@@ -21195,6 +21206,11 @@ virDomainHostdevDefCheckABIStability(virDomainHostdevDef *src,
}
}
+ if (src->iommufdId && dst->iommufdId) {
+ if (STRNEQ(src->iommufdId, dst->iommufdId))
+ return false;
+ }
+
if (!virDomainDeviceInfoCheckABIStability(src->info, dst->info))
return false;
@@ -27554,6 +27570,10 @@ virDomainHostdevDefFormat(virBuffer *buf,
if (def->shareable)
virBufferAddLit(buf, "<shareable/>\n");
+ if (def->iommufdId) {
+ virBufferAsprintf(buf, "<iommufdId>%s</iommufdId>\n",
def->iommufdId);
+ }
+
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 edb18632f3..367e7686f1 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -375,6 +375,7 @@ struct _virDomainHostdevDef {
virDomainHostdevCaps caps;
} source;
virDomainNetTeamingInfo *teaming;
+ char *iommufdId;
virDomainDeviceInfo *info; /* Guest address */
};
diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng
index fd19f115f7..662f12c4f1 100644
--- a/src/conf/schemas/domaincommon.rng
+++ b/src/conf/schemas/domaincommon.rng
@@ -6507,6 +6507,9 @@
<optional>
<ref name="address"/>
</optional>
+ <optional>
+ <ref name="iommufdId"/>
+ </optional>
<optional>
<element name="readonly">
<empty/>
@@ -7761,6 +7764,12 @@
</element>
</define>
+ <define name="iommufdId">
+ <element name="iommufdId">
+ <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 cecd0661ca..6b3e2ffd0d 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -4846,6 +4846,7 @@ qemuBuildPCIHostdevDevProps(const virDomainDef *def,
"S:failover_pair_id", failover_pair_id,
"S:display", qemuOnOffAuto(pcisrc->display),
"B:ramfb", ramfb,
+ "S:iommufd", dev->iommufdId,
NULL) < 0)
return NULL;
@@ -5225,6 +5226,8 @@ qemuBuildHostdevCommandLine(virCommand *cmd,
virQEMUCaps *qemuCaps)
{
size_t i;
+ g_autoptr(virJSONValue) props = NULL;
+ int iommufd = 0;
for (i = 0; i < def->nhostdevs; i++) {
virDomainHostdevDef *hostdev = def->hostdevs[i];
@@ -5234,6 +5237,17 @@ qemuBuildHostdevCommandLine(virCommand *cmd,
g_autofree char *vhostfdName = NULL;
int vhostfd = -1;
+ if (hostdev->iommufdId && iommufd == 0) {
+ iommufd = 1;
+ if (qemuMonitorCreateObjectProps(&props, "iommufd",
+ hostdev->iommufdId,
+ NULL) < 0)
+ return -1;
+
+ if (qemuBuildObjectCommandlineFromJSON(cmd, props) < 0)
+ return -1;
+ }
+
if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
continue;
--
2.43.0