[PATCH 4/6] conf: Introduce granule attribute for virtio-iommu

Michal Privoznik via Devel posted 6 patches 1 week, 4 days ago
There is a newer version of this series
[PATCH 4/6] conf: Introduce granule attribute for virtio-iommu
Posted by Michal Privoznik via Devel 1 week, 4 days ago
From: Michal Privoznik <mprivozn@redhat.com>

In PCI assignment scenario the virtio-iommu needs to know the
guest page size also known as granule. Expose it as an attribute
to the <driver/> element of a virtio-iommu.

This is possibly interesting only for aarch64 since it supports
virtio-iommu and also supports running guests with different page
size than the host.

Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
---
 docs/formatdomain.rst                         |  7 +++++
 src/conf/domain_conf.c                        | 30 ++++++++++++++++++-
 src/conf/domain_conf.h                        | 13 ++++++++
 src/conf/domain_validate.c                    |  9 ++++--
 src/conf/schemas/domaincommon.rng             | 11 +++++++
 src/libvirt_private.syms                      |  2 ++
 .../virtio-iommu-aarch64.aarch64-latest.xml   |  2 +-
 .../qemuxmlconfdata/virtio-iommu-aarch64.xml  |  2 +-
 8 files changed, 70 insertions(+), 6 deletions(-)

diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst
index 4b34a8a963..1dfe3915b5 100644
--- a/docs/formatdomain.rst
+++ b/docs/formatdomain.rst
@@ -9264,6 +9264,13 @@ Example:
       The ``pciBus`` attribute notes the index of the controller that an
       IOMMU device is attached to. (QEMU/KVM and ``smmuv3`` model only)
 
+   ``granule``
+      This allows to choose which granule will be used by default by the
+      virtio-iommu and is useful when running guests with different page size
+      than the host. Accepted values are: ``4K``, ``8K``, ``16K``, ``64K`` and
+      ``host`` (matches the host page size). :since:`Since 12.1.0` (QEMU/KVM
+      and ``virtio`` model only).
+
 The ``virtio`` IOMMU devices can further have ``address`` element as described
 in `Device addresses`_ (address has to by type of ``pci``).
 
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index d00a43e969..140333b1ec 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -1356,6 +1356,16 @@ VIR_ENUM_IMPL(virDomainIOMMUModel,
               "amd",
 );
 
+VIR_ENUM_IMPL(virDomainIOMMUGranuleMode,
+              VIR_DOMAIN_IOMMU_GRANULE_MODE_LAST,
+              "none",
+              "4K",
+              "8K",
+              "16K",
+              "64K",
+              "host",
+);
+
 VIR_ENUM_IMPL(virDomainVsockModel,
               VIR_DOMAIN_VSOCK_MODEL_LAST,
               "default",
@@ -14514,6 +14524,12 @@ virDomainIOMMUDefParseXML(virDomainXMLOption *xmlopt,
         if (virXMLPropInt(driver, "pciBus", 10, VIR_XML_PROP_NONE,
                           &iommu->pci_bus, -1) < 0)
             return NULL;
+
+        if (virXMLPropEnum(driver, "granule",
+                           virDomainIOMMUGranuleModeTypeFromString,
+                           VIR_XML_PROP_NONZERO, &iommu->granule_mode) < 0) {
+            return NULL;
+        }
     }
 
     if (virDomainDeviceInfoParseXML(xmlopt, node, ctxt,
@@ -16565,7 +16581,8 @@ virDomainIOMMUDefEquals(const virDomainIOMMUDef *a,
         a->eim != b->eim ||
         a->iotlb != b->iotlb ||
         a->aw_bits != b->aw_bits ||
-        a->dma_translation != b->dma_translation)
+        a->dma_translation != b->dma_translation ||
+        a->granule_mode != b->granule_mode)
         return false;
 
     if (a->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE &&
@@ -22320,6 +22337,13 @@ virDomainIOMMUDefCheckABIStability(virDomainIOMMUDef *src,
                        virTristateSwitchTypeToString(src->xtsup));
         return false;
     }
+    if (src->granule_mode != dst->granule_mode) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                       _("Target domain IOMMU device granule '%1$s' does not match source '%2$s'"),
+                       virDomainIOMMUGranuleModeTypeToString(dst->granule_mode),
+                       virDomainIOMMUGranuleModeTypeToString(src->granule_mode));
+        return false;
+    }
 
     return virDomainDeviceInfoCheckABIStability(&src->info, &dst->info);
 }
@@ -28645,6 +28669,10 @@ virDomainIOMMUDefFormat(virBuffer *buf,
         virBufferAsprintf(&driverAttrBuf, " pciBus='%d'",
                           iommu->pci_bus);
     }
+    if (iommu->granule_mode != VIR_DOMAIN_IOMMU_GRANULE_MODE_NONE) {
+        virBufferAsprintf(&driverAttrBuf, " granule='%s'",
+                          virDomainIOMMUGranuleModeTypeToString(iommu->granule_mode));
+    }
 
     virXMLFormatElement(&childBuf, "driver", &driverAttrBuf, NULL);
 
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 83d49969d3..8ea620a738 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -3050,6 +3050,17 @@ typedef enum {
     VIR_DOMAIN_IOMMU_MODEL_LAST
 } virDomainIOMMUModel;
 
+typedef enum {
+    VIR_DOMAIN_IOMMU_GRANULE_MODE_NONE = 0,
+    VIR_DOMAIN_IOMMU_GRANULE_MODE_4K,
+    VIR_DOMAIN_IOMMU_GRANULE_MODE_8K,
+    VIR_DOMAIN_IOMMU_GRANULE_MODE_16K,
+    VIR_DOMAIN_IOMMU_GRANULE_MODE_64K,
+    VIR_DOMAIN_IOMMU_GRANULE_MODE_HOST,
+
+    VIR_DOMAIN_IOMMU_GRANULE_MODE_LAST
+} virDomainIOMMUGranuleMode;
+
 struct _virDomainIOMMUDef {
     virDomainIOMMUModel model;
     virTristateSwitch intremap;
@@ -3062,6 +3073,7 @@ struct _virDomainIOMMUDef {
     virTristateSwitch dma_translation;
     virTristateSwitch xtsup;
     virTristateSwitch pt;
+    virDomainIOMMUGranuleMode granule_mode;
 };
 
 typedef enum {
@@ -4443,6 +4455,7 @@ VIR_ENUM_DECL(virDomainMemoryBackingModel);
 VIR_ENUM_DECL(virDomainMemorySource);
 VIR_ENUM_DECL(virDomainMemoryAllocation);
 VIR_ENUM_DECL(virDomainIOMMUModel);
+VIR_ENUM_DECL(virDomainIOMMUGranuleMode);
 VIR_ENUM_DECL(virDomainVsockModel);
 VIR_ENUM_DECL(virDomainCryptoModel);
 VIR_ENUM_DECL(virDomainCryptoType);
diff --git a/src/conf/domain_validate.c b/src/conf/domain_validate.c
index 440f23d726..fd28526159 100644
--- a/src/conf/domain_validate.c
+++ b/src/conf/domain_validate.c
@@ -3194,7 +3194,8 @@ virDomainIOMMUDefValidate(const virDomainIOMMUDef *iommu)
             iommu->aw_bits != 0 ||
             iommu->dma_translation != VIR_TRISTATE_SWITCH_ABSENT ||
             iommu->xtsup != VIR_TRISTATE_SWITCH_ABSENT ||
-            iommu->pt != VIR_TRISTATE_SWITCH_ABSENT) {
+            iommu->pt != VIR_TRISTATE_SWITCH_ABSENT ||
+            iommu->granule_mode != VIR_DOMAIN_IOMMU_GRANULE_MODE_NONE) {
             virReportError(VIR_ERR_XML_ERROR,
                            _("iommu model '%1$s' doesn't support some additional attributes"),
                            virDomainIOMMUModelTypeToString(iommu->model));
@@ -3226,7 +3227,8 @@ virDomainIOMMUDefValidate(const virDomainIOMMUDef *iommu)
             iommu->eim != VIR_TRISTATE_SWITCH_ABSENT ||
             iommu->aw_bits != 0 ||
             iommu->dma_translation != VIR_TRISTATE_SWITCH_ABSENT ||
-            iommu->pci_bus >= 0) {
+            iommu->pci_bus >= 0 ||
+            iommu->granule_mode != VIR_DOMAIN_IOMMU_GRANULE_MODE_NONE) {
             virReportError(VIR_ERR_XML_ERROR,
                            _("iommu model '%1$s' doesn't support some additional attributes"),
                            virDomainIOMMUModelTypeToString(iommu->model));
@@ -3237,7 +3239,8 @@ virDomainIOMMUDefValidate(const virDomainIOMMUDef *iommu)
     case VIR_DOMAIN_IOMMU_MODEL_INTEL:
         if (iommu->pt != VIR_TRISTATE_SWITCH_ABSENT ||
             iommu->xtsup != VIR_TRISTATE_SWITCH_ABSENT ||
-            iommu->pci_bus >= 0) {
+            iommu->pci_bus >= 0 ||
+            iommu->granule_mode != VIR_DOMAIN_IOMMU_GRANULE_MODE_NONE) {
             virReportError(VIR_ERR_XML_ERROR,
                            _("iommu model '%1$s' doesn't support some additional attributes"),
                            virDomainIOMMUModelTypeToString(iommu->model));
diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng
index 114dd3f96f..175e735a99 100644
--- a/src/conf/schemas/domaincommon.rng
+++ b/src/conf/schemas/domaincommon.rng
@@ -6329,6 +6329,17 @@
                 <data type="unsignedInt"/>
               </attribute>
             </optional>
+            <optional>
+              <attribute name="granule">
+                <choice>
+                  <value>4K</value>
+                  <value>8K</value>
+                  <value>16K</value>
+                  <value>64K</value>
+                  <value>host</value>
+                </choice>
+              </attribute>
+            </optional>
           </element>
         </optional>
         <optional>
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 6bffd2eb6d..d34b65a415 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -499,6 +499,8 @@ virDomainIOMMUDefEquals;
 virDomainIOMMUDefFind;
 virDomainIOMMUDefFree;
 virDomainIOMMUDefNew;
+virDomainIOMMUGranuleModeTypeFromString;
+virDomainIOMMUGranuleModeTypeToString;
 virDomainIOMMUModelTypeFromString;
 virDomainIOMMUModelTypeToString;
 virDomainIOThreadIDAdd;
diff --git a/tests/qemuxmlconfdata/virtio-iommu-aarch64.aarch64-latest.xml b/tests/qemuxmlconfdata/virtio-iommu-aarch64.aarch64-latest.xml
index 4ae628ab5a..709a24f796 100644
--- a/tests/qemuxmlconfdata/virtio-iommu-aarch64.aarch64-latest.xml
+++ b/tests/qemuxmlconfdata/virtio-iommu-aarch64.aarch64-latest.xml
@@ -29,7 +29,7 @@
     <audio id='1' type='none'/>
     <memballoon model='none'/>
     <iommu model='virtio'>
-      <driver aw_bits='48'/>
+      <driver aw_bits='48' granule='64K'/>
       <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x0'/>
     </iommu>
   </devices>
diff --git a/tests/qemuxmlconfdata/virtio-iommu-aarch64.xml b/tests/qemuxmlconfdata/virtio-iommu-aarch64.xml
index 96e5ea05ae..bf8bc58211 100644
--- a/tests/qemuxmlconfdata/virtio-iommu-aarch64.xml
+++ b/tests/qemuxmlconfdata/virtio-iommu-aarch64.xml
@@ -14,7 +14,7 @@
     <controller type='usb' model='none'/>
     <memballoon model='none'/>
     <iommu model='virtio'>
-      <driver aw_bits='48'/>
+      <driver aw_bits='48' granule='64K'/>
     </iommu>
   </devices>
 </domain>
-- 
2.52.0
Re: [PATCH 4/6] conf: Introduce granule attribute for virtio-iommu
Posted by Peter Krempa via Devel 1 week, 4 days ago
On Wed, Jan 21, 2026 at 17:27:20 +0100, Michal Privoznik via Devel wrote:
> From: Michal Privoznik <mprivozn@redhat.com>
> 
> In PCI assignment scenario the virtio-iommu needs to know the
> guest page size also known as granule. Expose it as an attribute

^^^^

> to the <driver/> element of a virtio-iommu.
> 
> This is possibly interesting only for aarch64 since it supports
> virtio-iommu and also supports running guests with different page
> size than the host.
> 
> Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
> ---
>  docs/formatdomain.rst                         |  7 +++++
>  src/conf/domain_conf.c                        | 30 ++++++++++++++++++-
>  src/conf/domain_conf.h                        | 13 ++++++++
>  src/conf/domain_validate.c                    |  9 ++++--
>  src/conf/schemas/domaincommon.rng             | 11 +++++++
>  src/libvirt_private.syms                      |  2 ++
>  .../virtio-iommu-aarch64.aarch64-latest.xml   |  2 +-
>  .../qemuxmlconfdata/virtio-iommu-aarch64.xml  |  2 +-
>  8 files changed, 70 insertions(+), 6 deletions(-)
> 
> diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst
> index 4b34a8a963..1dfe3915b5 100644
> --- a/docs/formatdomain.rst
> +++ b/docs/formatdomain.rst
> @@ -9264,6 +9264,13 @@ Example:
>        The ``pciBus`` attribute notes the index of the controller that an
>        IOMMU device is attached to. (QEMU/KVM and ``smmuv3`` model only)
>  
> +   ``granule``
> +      This allows to choose which granule will be used by default by the

Put the above explanation also here.

> +      virtio-iommu and is useful when running guests with different page size
> +      than the host. Accepted values are: ``4K``, ``8K``, ``16K``, ``64K`` and

Since this is supposed to mean page size you should use the lowercase
'k' for kilo? Or perhaps directly kiB ?

> +      ``host`` (matches the host page size). :since:`Since 12.1.0` (QEMU/KVM
> +      and ``virtio`` model only).
> +
>  The ``virtio`` IOMMU devices can further have ``address`` element as described
>  in `Device addresses`_ (address has to by type of ``pci``).
Re: [PATCH 4/6] conf: Introduce granule attribute for virtio-iommu
Posted by Michal Prívozník via Devel 1 week, 3 days ago
On 1/21/26 18:04, Peter Krempa wrote:
> On Wed, Jan 21, 2026 at 17:27:20 +0100, Michal Privoznik via Devel wrote:
>> From: Michal Privoznik <mprivozn@redhat.com>
>>
>> In PCI assignment scenario the virtio-iommu needs to know the
>> guest page size also known as granule. Expose it as an attribute
> 
> ^^^^
> 
>> to the <driver/> element of a virtio-iommu.
>>
>> This is possibly interesting only for aarch64 since it supports
>> virtio-iommu and also supports running guests with different page
>> size than the host.
>>
>> Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
>> ---
>>  docs/formatdomain.rst                         |  7 +++++
>>  src/conf/domain_conf.c                        | 30 ++++++++++++++++++-
>>  src/conf/domain_conf.h                        | 13 ++++++++
>>  src/conf/domain_validate.c                    |  9 ++++--
>>  src/conf/schemas/domaincommon.rng             | 11 +++++++
>>  src/libvirt_private.syms                      |  2 ++
>>  .../virtio-iommu-aarch64.aarch64-latest.xml   |  2 +-
>>  .../qemuxmlconfdata/virtio-iommu-aarch64.xml  |  2 +-
>>  8 files changed, 70 insertions(+), 6 deletions(-)
>>
>> diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst
>> index 4b34a8a963..1dfe3915b5 100644
>> --- a/docs/formatdomain.rst
>> +++ b/docs/formatdomain.rst
>> @@ -9264,6 +9264,13 @@ Example:
>>        The ``pciBus`` attribute notes the index of the controller that an
>>        IOMMU device is attached to. (QEMU/KVM and ``smmuv3`` model only)
>>  
>> +   ``granule``
>> +      This allows to choose which granule will be used by default by the
> 
> Put the above explanation also here.
> 
>> +      virtio-iommu and is useful when running guests with different page size
>> +      than the host. Accepted values are: ``4K``, ``8K``, ``16K``, ``64K`` and
> 
> Since this is supposed to mean page size you should use the lowercase
> 'k' for kilo? Or perhaps directly kiB ?

I wondered about that. But let's enumerate our possibilities.

1) <driver granule='4k'/>
2) <driver granule='4096'/>
3) <driver granule='4' unit='KiB'/>
4) <driver granule='4' granuleUnit='KiB'/>
5) <driver>
     <granule unit='KiB'>4</granule>
   </driver>

Problem with 3 is that 'unit' is not specific enough and if we ever want
to invent a new attribute that'd accept units, we're cooked. 4) is more
descriptive but I'm not a big fan of it either. That leaves us with 2)
where the unit is bytes, or 5) which is the most future proof IMO.

Michal
Re: [PATCH 4/6] conf: Introduce granule attribute for virtio-iommu
Posted by Peter Krempa via Devel 1 week, 3 days ago
On Thu, Jan 22, 2026 at 12:00:55 +0100, Michal Prívozník wrote:
> On 1/21/26 18:04, Peter Krempa wrote:
> > On Wed, Jan 21, 2026 at 17:27:20 +0100, Michal Privoznik via Devel wrote:
> >> From: Michal Privoznik <mprivozn@redhat.com>
> >>
> >> In PCI assignment scenario the virtio-iommu needs to know the
> >> guest page size also known as granule. Expose it as an attribute
> > 
> > ^^^^
> > 
> >> to the <driver/> element of a virtio-iommu.
> >>
> >> This is possibly interesting only for aarch64 since it supports
> >> virtio-iommu and also supports running guests with different page
> >> size than the host.
> >>
> >> Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
> >> ---
> >>  docs/formatdomain.rst                         |  7 +++++
> >>  src/conf/domain_conf.c                        | 30 ++++++++++++++++++-
> >>  src/conf/domain_conf.h                        | 13 ++++++++
> >>  src/conf/domain_validate.c                    |  9 ++++--
> >>  src/conf/schemas/domaincommon.rng             | 11 +++++++
> >>  src/libvirt_private.syms                      |  2 ++
> >>  .../virtio-iommu-aarch64.aarch64-latest.xml   |  2 +-
> >>  .../qemuxmlconfdata/virtio-iommu-aarch64.xml  |  2 +-
> >>  8 files changed, 70 insertions(+), 6 deletions(-)
> >>
> >> diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst
> >> index 4b34a8a963..1dfe3915b5 100644
> >> --- a/docs/formatdomain.rst
> >> +++ b/docs/formatdomain.rst
> >> @@ -9264,6 +9264,13 @@ Example:
> >>        The ``pciBus`` attribute notes the index of the controller that an
> >>        IOMMU device is attached to. (QEMU/KVM and ``smmuv3`` model only)
> >>  
> >> +   ``granule``
> >> +      This allows to choose which granule will be used by default by the
> > 
> > Put the above explanation also here.
> > 
> >> +      virtio-iommu and is useful when running guests with different page size
> >> +      than the host. Accepted values are: ``4K``, ``8K``, ``16K``, ``64K`` and
> > 
> > Since this is supposed to mean page size you should use the lowercase
> > 'k' for kilo? Or perhaps directly kiB ?
> 
> I wondered about that. But let's enumerate our possibilities.
> 
> 1) <driver granule='4k'/>
> 2) <driver granule='4096'/>
> 3) <driver granule='4' unit='KiB'/>
> 4) <driver granule='4' granuleUnit='KiB'/>
> 5) <driver>
>      <granule unit='KiB'>4</granule>
>    </driver>
> 
> Problem with 3 is that 'unit' is not specific enough and if we ever want
> to invent a new attribute that'd accept units, we're cooked. 4) is more
> descriptive but I'm not a big fan of it either. That leaves us with 2)
> where the unit is bytes, or 5) which is the most future proof IMO.

I'm not a fan of the value being content and unit being attribute. You
also need to be able to use the 'host' mode which doesn't represent well
as a number.

Internally we can do 'host' as an extra bool, but also we don't really
need to be able (for now) represent the full scale of numbers, but that
can be handled by validation.

I'd consider:

 <driver>
   <granule mode='host'/>

     or

   <granule size='4' unit='KiB'/>
 </driver>
Re: [PATCH 4/6] conf: Introduce granule attribute for virtio-iommu
Posted by Michal Prívozník via Devel 1 week, 2 days ago
On 1/22/26 16:13, Peter Krempa wrote:

> 
> I'd consider:
> 
>  <driver>
>    <granule mode='host'/>
> 
>      or
> 
>    <granule size='4' unit='KiB'/>
>  </driver>
> 

Fair enough. Let me post v2.

Michal