From: Nathan Chen <nathanc@nvidia.com>
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 <jtomko@redhat.com>
Signed-off-by: Nathan Chen <nathanc@nvidia.com>
---
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 04ef319a73..08fc3f3944 100644
--- a/docs/formatdomain.rst
+++ b/docs/formatdomain.rst
@@ -4920,6 +4920,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 0de0a79b46..5274b33d17 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -4761,6 +4761,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;
@@ -4794,6 +4795,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,
@@ -4802,6 +4806,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;
@@ -5321,6 +5326,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)
@@ -10933,6 +10976,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
On Fri, Jan 16, 2026 at 05:39:31PM -0800, Nathan Chen via Devel wrote: > From: Nathan Chen <nathanc@nvidia.com> > > 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 <jtomko@redhat.com> > Signed-off-by: Nathan Chen <nathanc@nvidia.com> > --- > 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 04ef319a73..08fc3f3944 100644 > --- a/docs/formatdomain.rst > +++ b/docs/formatdomain.rst > @@ -4920,6 +4920,13 @@ or: > found is "problematic" in some way, the generic vfio-pci driver > similarly be forced. We should add :since:`Since 12.1.0 (QEMU and KVM only)` > + 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. I would rephrase this paragraph to something like this: :since:`Since 12.1.0 (QEMU and KVM only), the ``iommufd`` element can be used to enable IOMMUFD backend for VFIO device. This provides interface to propagate DMA mappings to kernel for assigned devices. Libvirt will open the /dev/iommu and VFIO device cdev and pass associated file descriptors to QEMU. Pavel
On 1/19/2026 5:17 AM, Pavel Hrdina wrote: > On Fri, Jan 16, 2026 at 05:39:31PM -0800, Nathan Chen via Devel wrote: >> From: Nathan Chen<nathanc@nvidia.com> >> >> 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<jtomko@redhat.com> >> Signed-off-by: Nathan Chen<nathanc@nvidia.com> >> --- >> 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 04ef319a73..08fc3f3944 100644 >> --- a/docs/formatdomain.rst >> +++ b/docs/formatdomain.rst >> @@ -4920,6 +4920,13 @@ or: >> found is "problematic" in some way, the generic vfio-pci driver >> similarly be forced. > We should add :since:`Since 12.1.0 (QEMU and KVM only)` > >> + 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. > I would rephrase this paragraph to something like this: > > :since:`Since 12.1.0 (QEMU and KVM only), the ``iommufd`` element can > be used to enable IOMMUFD backend for VFIO device. This provides > interface to propagate DMA mappings to kernel for assigned devices. > Libvirt will open the /dev/iommu and VFIO device cdev and pass > associated file descriptors to QEMU. Got it, thanks for the feedback. Nathan
© 2016 - 2026 Red Hat, Inc.