From: Pavel Hrdina <phrdina@redhat.com>
This will allow management applications running libvirt without
necessary permissions to pass FD for /dev/iommu with per-process
locked memory accounting enabled.
Kernel uses per-user locked memory accounting by default which may
cause error while starting multiple VMs with host devices using IOMMUFD.
Signed-off-by: Pavel Hrdina <phrdina@redhat.com>
---
docs/formatdomain.rst | 8 +++++++-
src/conf/domain_conf.c | 7 +++++++
src/conf/domain_conf.h | 1 +
src/conf/domain_validate.c | 16 ++++++++++++++++
src/conf/schemas/domaincommon.rng | 3 +++
tests/genericxml2xmlindata/iommufd.xml | 2 +-
6 files changed, 35 insertions(+), 2 deletions(-)
diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst
index f6096b2b9b..412b2b4ddd 100644
--- a/docs/formatdomain.rst
+++ b/docs/formatdomain.rst
@@ -1389,7 +1389,7 @@ Host Device IOMMUFD
<domain>
...
- <iommufd enabled='yes'/>
+ <iommufd enabled='yes' fdgroup='iommu'/>
...
</domain>
@@ -1403,6 +1403,12 @@ Host Device IOMMUFD
This controls IOMMUFD usage for all host devices, each device can change this
global default by setting ``iommufd`` attribute for ``driver`` element.
+ Optional ``fdgroup`` attribute can be used together with
+ ``virDomainFDAssociate()`` to pass /dev/iommu FD instead of letting
+ libvirt to open it. Caller is responsible for setting per-process locked
+ memory accounting otherwise starting multiple VMs with host devices using
+ IOMMUFD may fail.
+
Resource partitioning
---------------------
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 950c755ad9..71488a0840 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -4242,6 +4242,8 @@ void virDomainDefFree(virDomainDef *def)
g_free(def->kvm_features);
g_free(def->tcg_features);
+ g_free(def->iommufd_fdgroup);
+
virBlkioDeviceArrayClear(def->blkio.devices,
def->blkio.ndevices);
g_free(def->blkio.devices);
@@ -19905,6 +19907,8 @@ virDomainDefIommufdParse(virDomainDef *def,
if (virXMLPropTristateBool(nodes[0], "enabled", VIR_XML_PROP_REQUIRED, &def->iommufd) < 0)
return -1;
+ def->iommufd_fdgroup = virXMLPropString(nodes[0], "fdgroup");
+
return 0;
}
@@ -28212,6 +28216,9 @@ virDomainDefIommufdFormat(virBuffer *buf,
virBufferAsprintf(&attrBuf, " enabled='%s'",
virTristateBoolTypeToString(def->iommufd));
+ if (def->iommufd_fdgroup)
+ virBufferAsprintf(&attrBuf, " fdgroup='%s'", def->iommufd_fdgroup);
+
virXMLFormatElement(buf, "iommufd", &attrBuf, NULL);
}
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index f7e2eb6f5e..75acfc46bf 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -3245,6 +3245,7 @@ struct _virDomainDef {
virDomainFeatureTCG *tcg_features;
virTristateBool iommufd;
+ char *iommufd_fdgroup;
bool tseg_specified;
unsigned long long tseg_size;
diff --git a/src/conf/domain_validate.c b/src/conf/domain_validate.c
index 7e3da84767..a49156061f 100644
--- a/src/conf/domain_validate.c
+++ b/src/conf/domain_validate.c
@@ -2003,6 +2003,19 @@ virDomainDefValidateThrottleGroups(const virDomainDef *def)
}
+static int
+virDomainDefValidateIommufd(const virDomainDef *def)
+{
+ if (def->iommufd == VIR_TRISTATE_BOOL_NO && def->iommufd_fdgroup) {
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
+ _("Setting 'fdgroup' when 'iommufd' is disabled is not supported."));
+ return -1;
+ }
+
+ return 0;
+}
+
+
static int
virDomainDefValidateInternal(const virDomainDef *def,
virDomainXMLOption *xmlopt)
@@ -2064,6 +2077,9 @@ virDomainDefValidateInternal(const virDomainDef *def,
if (virDomainDefValidateThrottleGroups(def) < 0)
return -1;
+ if (virDomainDefValidateIommufd(def) < 0)
+ return -1;
+
return 0;
}
diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng
index 0436ec8edc..db1dcd3bb7 100644
--- a/src/conf/schemas/domaincommon.rng
+++ b/src/conf/schemas/domaincommon.rng
@@ -1377,6 +1377,9 @@
<attribute name="enabled">
<ref name="virYesNo"/>
</attribute>
+ <optional>
+ <attribute name="fdgroup"/>
+ </optional>
</element>
</define>
diff --git a/tests/genericxml2xmlindata/iommufd.xml b/tests/genericxml2xmlindata/iommufd.xml
index 63ea839383..10d59ca548 100644
--- a/tests/genericxml2xmlindata/iommufd.xml
+++ b/tests/genericxml2xmlindata/iommufd.xml
@@ -4,7 +4,7 @@
<memory unit='KiB'>219136</memory>
<currentMemory unit='KiB'>219136</currentMemory>
<vcpu placement='static'>1</vcpu>
- <iommufd enabled='yes'/>
+ <iommufd enabled='yes' fdgroup='iommu'/>
<os>
<type arch='i686' machine='pc'>hvm</type>
<boot dev='hd'/>
--
2.53.0
On Thu, Mar 19, 2026 at 17:36:55 +0100, Pavel Hrdina via Devel wrote: > From: Pavel Hrdina <phrdina@redhat.com> > > This will allow management applications running libvirt without > necessary permissions to pass FD for /dev/iommu with per-process > locked memory accounting enabled. > > Kernel uses per-user locked memory accounting by default which may > cause error while starting multiple VMs with host devices using IOMMUFD. > > Signed-off-by: Pavel Hrdina <phrdina@redhat.com> > --- > docs/formatdomain.rst | 8 +++++++- > src/conf/domain_conf.c | 7 +++++++ > src/conf/domain_conf.h | 1 + > src/conf/domain_validate.c | 16 ++++++++++++++++ > src/conf/schemas/domaincommon.rng | 3 +++ > tests/genericxml2xmlindata/iommufd.xml | 2 +- > 6 files changed, 35 insertions(+), 2 deletions(-) > > diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst > index f6096b2b9b..412b2b4ddd 100644 > --- a/docs/formatdomain.rst > +++ b/docs/formatdomain.rst > @@ -1389,7 +1389,7 @@ Host Device IOMMUFD > > <domain> > ... > - <iommufd enabled='yes'/> > + <iommufd enabled='yes' fdgroup='iommu'/> > ... > </domain> > > @@ -1403,6 +1403,12 @@ Host Device IOMMUFD > This controls IOMMUFD usage for all host devices, each device can change this > global default by setting ``iommufd`` attribute for ``driver`` element. > > + Optional ``fdgroup`` attribute can be used together with > + ``virDomainFDAssociate()`` to pass /dev/iommu FD instead of letting Consider linking the API docs: `virDomainFDAssociate() <html/libvirt-libvirt-domain.html#virDomainFDAssociate>`__ > + libvirt to open it. Caller is responsible for setting per-process locked > + memory accounting otherwise starting multiple VMs with host devices using > + IOMMUFD may fail. > + > Resource partitioning > --------------------- > > diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c > index 950c755ad9..71488a0840 100644 > --- a/src/conf/domain_conf.c > +++ b/src/conf/domain_conf.c > @@ -4242,6 +4242,8 @@ void virDomainDefFree(virDomainDef *def) > g_free(def->kvm_features); > g_free(def->tcg_features); > > + g_free(def->iommufd_fdgroup); > + > virBlkioDeviceArrayClear(def->blkio.devices, > def->blkio.ndevices); > g_free(def->blkio.devices); > @@ -19905,6 +19907,8 @@ virDomainDefIommufdParse(virDomainDef *def, > if (virXMLPropTristateBool(nodes[0], "enabled", VIR_XML_PROP_REQUIRED, &def->iommufd) < 0) > return -1; > > + def->iommufd_fdgroup = virXMLPropString(nodes[0], "fdgroup"); > + > return 0; > } > > @@ -28212,6 +28216,9 @@ virDomainDefIommufdFormat(virBuffer *buf, > virBufferAsprintf(&attrBuf, " enabled='%s'", > virTristateBoolTypeToString(def->iommufd)); > > + if (def->iommufd_fdgroup) > + virBufferAsprintf(&attrBuf, " fdgroup='%s'", def->iommufd_fdgroup); User originating XML values *must* be formatted using virBufferEscapeString (which doesn't require the NULL check). > + > virXMLFormatElement(buf, "iommufd", &attrBuf, NULL); Reviewed-by: Peter Krempa <pkrempa@redhat.com>
© 2016 - 2026 Red Hat, Inc.