[libvirt PATCH 09/11] conf: Add iommufd fdgroup support

Pavel Hrdina via Devel posted 11 patches 4 days, 6 hours ago
[libvirt PATCH 09/11] conf: Add iommufd fdgroup support
Posted by Pavel Hrdina via Devel 4 days, 6 hours ago
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
Re: [libvirt PATCH 09/11] conf: Add iommufd fdgroup support
Posted by Peter Krempa via Devel 3 days, 14 hours ago
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>