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 <nath...@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