[PATCH v2 1/3] qemu: add IOMMU model smmuv3Dev

Nathan Chen via Devel posted 3 patches 4 months, 1 week ago
[PATCH v2 1/3] qemu: add IOMMU model smmuv3Dev
Posted by Nathan Chen via Devel 4 months, 1 week ago
Introduce support for "smmuv3Dev" IOMMU model and
its "parentIdx" driver attribute. The "parentIdx"
attribute indicates the index of the controller that a
smmuv3Dev IOMMU device is attached to.

Signed-off-by: Nathan Chen <nathanc@nvidia.com>
---
 docs/formatdomain.rst             |  9 +++-
 src/conf/domain_conf.c            | 17 ++++++++
 src/conf/domain_conf.h            |  2 +
 src/conf/domain_validate.c        | 26 +++++++++--
 src/conf/schemas/domaincommon.rng |  6 +++
 src/qemu/qemu_command.c           | 72 +++++++++++++++++++++++++++++--
 src/qemu/qemu_domain_address.c    |  2 +
 src/qemu/qemu_validate.c          | 16 +++++++
 8 files changed, 141 insertions(+), 9 deletions(-)

diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst
index f50dce477f..6a62291600 100644
--- a/docs/formatdomain.rst
+++ b/docs/formatdomain.rst
@@ -9161,8 +9161,9 @@ Example:
 ``model``
    Supported values are ``intel`` (for Q35 guests) ``smmuv3``
    (:since:`since 5.5.0`, for ARM virt guests), ``virtio``
-   (:since:`since 8.3.0`, for Q35 and ARM virt guests) and
-   ``amd`` (:since:`since 11.5.0`).
+   (:since:`since 8.3.0`, for Q35 and ARM virt guests),
+   ``amd`` (:since:`since 11.5.0`), and ``smmuv3Dev`` (for
+   ARM virt guests).
 
 ``driver``
    The ``driver`` subelement can be used to configure additional options, some
@@ -9212,6 +9213,10 @@ Example:
       Enable x2APIC mode. Useful for higher number of guest CPUs.
       :since:`Since 11.5.0` (QEMU/KVM and ``amd`` model only)
 
+   ``parentIdx``
+      The ``parentIdx`` attribute notes the index of the controller that an
+      IOMMU device is attached to. (QEMU/KVM and ``smmuv3Dev`` 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 281846dfbe..6d1adb831d 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -1353,6 +1353,7 @@ VIR_ENUM_IMPL(virDomainIOMMUModel,
               "smmuv3",
               "virtio",
               "amd",
+              "smmuv3Dev",
 );
 
 VIR_ENUM_IMPL(virDomainVsockModel,
@@ -2813,6 +2814,8 @@ virDomainIOMMUDefNew(void)
 
     iommu = g_new0(virDomainIOMMUDef, 1);
 
+    iommu->parent_idx = -1;
+
     return g_steal_pointer(&iommu);
 }
 
@@ -14439,6 +14442,10 @@ virDomainIOMMUDefParseXML(virDomainXMLOption *xmlopt,
         if (virXMLPropTristateSwitch(driver, "passthrough", VIR_XML_PROP_NONE,
                                      &iommu->pt) < 0)
             return NULL;
+
+        if (virXMLPropInt(driver, "parentIdx", 10, VIR_XML_PROP_NONE,
+                          &iommu->parent_idx, -1) < 0)
+            return NULL;
     }
 
     if (virDomainDeviceInfoParseXML(xmlopt, node, ctxt,
@@ -22092,6 +22099,12 @@ virDomainIOMMUDefCheckABIStability(virDomainIOMMUDef *src,
                        dst->aw_bits, src->aw_bits);
         return false;
     }
+    if (src->parent_idx != dst->parent_idx) {
+        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                       _("Target domain IOMMU device parent_idx value '%1$d' does not match source '%2$d'"),
+                       dst->parent_idx, src->parent_idx);
+        return false;
+    }
     if (src->dma_translation != dst->dma_translation) {
         virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                        _("Target domain IOMMU device dma translation '%1$s' does not match source '%2$s'"),
@@ -28409,6 +28422,10 @@ virDomainIOMMUDefFormat(virBuffer *buf,
         virBufferAsprintf(&driverAttrBuf, " xtsup='%s'",
                           virTristateSwitchTypeToString(iommu->xtsup));
     }
+    if (iommu->parent_idx >= 0) {
+        virBufferAsprintf(&driverAttrBuf, " parentIdx='%d'",
+                          iommu->parent_idx);
+    }
 
     virXMLFormatElement(&childBuf, "driver", &driverAttrBuf, NULL);
 
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 39807b5fe3..1d0c94a00a 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -3039,6 +3039,7 @@ typedef enum {
     VIR_DOMAIN_IOMMU_MODEL_SMMUV3,
     VIR_DOMAIN_IOMMU_MODEL_VIRTIO,
     VIR_DOMAIN_IOMMU_MODEL_AMD,
+    VIR_DOMAIN_IOMMU_MODEL_SMMUV3_DEV,
 
     VIR_DOMAIN_IOMMU_MODEL_LAST
 } virDomainIOMMUModel;
@@ -3050,6 +3051,7 @@ struct _virDomainIOMMUDef {
     virTristateSwitch eim;
     virTristateSwitch iotlb;
     unsigned int aw_bits;
+    int parent_idx;
     virDomainDeviceInfo info;
     virTristateSwitch dma_translation;
     virTristateSwitch xtsup;
diff --git a/src/conf/domain_validate.c b/src/conf/domain_validate.c
index 93a2bc9b01..8a599fdbc6 100644
--- a/src/conf/domain_validate.c
+++ b/src/conf/domain_validate.c
@@ -3108,7 +3108,8 @@ virDomainIOMMUDefValidate(const virDomainIOMMUDef *iommu)
             iommu->eim != VIR_TRISTATE_SWITCH_ABSENT ||
             iommu->iotlb != VIR_TRISTATE_SWITCH_ABSENT ||
             iommu->aw_bits != 0 ||
-            iommu->dma_translation != VIR_TRISTATE_SWITCH_ABSENT) {
+            iommu->dma_translation != VIR_TRISTATE_SWITCH_ABSENT ||
+            iommu->parent_idx != -1) {
             virReportError(VIR_ERR_XML_ERROR,
                            _("iommu model '%1$s' doesn't support additional attributes"),
                            virDomainIOMMUModelTypeToString(iommu->model));
@@ -3120,7 +3121,8 @@ virDomainIOMMUDefValidate(const virDomainIOMMUDef *iommu)
         if (iommu->caching_mode != VIR_TRISTATE_SWITCH_ABSENT ||
             iommu->eim != VIR_TRISTATE_SWITCH_ABSENT ||
             iommu->aw_bits != 0 ||
-            iommu->dma_translation != VIR_TRISTATE_SWITCH_ABSENT) {
+            iommu->dma_translation != VIR_TRISTATE_SWITCH_ABSENT ||
+            iommu->parent_idx != -1) {
             virReportError(VIR_ERR_XML_ERROR,
                            _("iommu model '%1$s' doesn't support some additional attributes"),
                            virDomainIOMMUModelTypeToString(iommu->model));
@@ -3130,7 +3132,24 @@ virDomainIOMMUDefValidate(const virDomainIOMMUDef *iommu)
 
     case VIR_DOMAIN_IOMMU_MODEL_INTEL:
         if (iommu->pt != VIR_TRISTATE_SWITCH_ABSENT ||
-            iommu->xtsup != VIR_TRISTATE_SWITCH_ABSENT) {
+            iommu->xtsup != VIR_TRISTATE_SWITCH_ABSENT ||
+            iommu->parent_idx != -1) {
+            virReportError(VIR_ERR_XML_ERROR,
+                           _("iommu model '%1$s' doesn't support some additional attributes"),
+                           virDomainIOMMUModelTypeToString(iommu->model));
+            return -1;
+        }
+        break;
+
+    case VIR_DOMAIN_IOMMU_MODEL_SMMUV3_DEV:
+        if (iommu->intremap != VIR_TRISTATE_SWITCH_ABSENT ||
+            iommu->caching_mode != VIR_TRISTATE_SWITCH_ABSENT ||
+            iommu->eim != VIR_TRISTATE_SWITCH_ABSENT ||
+            iommu->iotlb != VIR_TRISTATE_SWITCH_ABSENT ||
+            iommu->aw_bits != 0 ||
+            iommu->dma_translation != VIR_TRISTATE_SWITCH_ABSENT ||
+            iommu->xtsup != VIR_TRISTATE_SWITCH_ABSENT ||
+            iommu->pt != VIR_TRISTATE_SWITCH_ABSENT) {
             virReportError(VIR_ERR_XML_ERROR,
                            _("iommu model '%1$s' doesn't support some additional attributes"),
                            virDomainIOMMUModelTypeToString(iommu->model));
@@ -3155,6 +3174,7 @@ virDomainIOMMUDefValidate(const virDomainIOMMUDef *iommu)
 
     case VIR_DOMAIN_IOMMU_MODEL_VIRTIO:
     case VIR_DOMAIN_IOMMU_MODEL_AMD:
+    case VIR_DOMAIN_IOMMU_MODEL_SMMUV3_DEV:
     case VIR_DOMAIN_IOMMU_MODEL_LAST:
         break;
     }
diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng
index b9230a35b4..26880b6db2 100644
--- a/src/conf/schemas/domaincommon.rng
+++ b/src/conf/schemas/domaincommon.rng
@@ -6266,6 +6266,7 @@
           <value>smmuv3</value>
           <value>virtio</value>
           <value>amd</value>
+          <value>smmuv3Dev</value>
         </choice>
       </attribute>
       <interleave>
@@ -6311,6 +6312,11 @@
                 <ref name="virOnOff"/>
               </attribute>
             </optional>
+            <optional>
+              <attribute name="parentIdx">
+                <data type="unsignedInt"/>
+              </attribute>
+            </optional>
           </element>
         </optional>
         <optional>
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 031f09b7a5..e789e8cf2c 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -6294,6 +6294,62 @@ qemuBuildBootCommandLine(virCommand *cmd,
 }
 
 
+static virJSONValue *
+qemuBuildPCISmmuv3DevDevProps(const virDomainDef *def,
+                              const virDomainIOMMUDef *iommu)
+{
+    g_autoptr(virJSONValue) props = NULL;
+    g_autofree char *bus = NULL;
+    size_t i;
+    bool contIsPHB = false;
+
+    for (i = 0; i < def->ncontrollers; i++) {
+        virDomainControllerDef *cont = def->controllers[i];
+        if (cont->idx == iommu->parent_idx) {
+            if (cont->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI) {
+                const char *alias = cont->info.alias;
+                contIsPHB = virDomainControllerIsPSeriesPHB(cont);
+
+                if (!alias)
+                    return NULL;
+
+                if (virDomainDeviceAliasIsUserAlias(alias)) {
+                    if (cont->model == VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT &&
+                        iommu->parent_idx <= 0) {
+                        if (qemuDomainSupportsPCIMultibus(def))
+                            bus = g_strdup("pci.0");
+                        else
+                            bus = g_strdup("pci");
+                    } else if (cont->model == VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT) {
+                        bus = g_strdup("pcie.0");
+                    }
+                } else {
+                    bus = g_strdup(alias);
+                }
+                break;
+            }
+        }
+    }
+
+    if (!bus)
+        return NULL;
+
+    if (contIsPHB && iommu->parent_idx > 0) {
+        char *temp_bus = g_strdup_printf("%s.0", bus);
+        g_free(bus);
+        bus = temp_bus;
+    }
+
+    if (virJSONValueObjectAdd(&props,
+                              "s:driver", "arm-smmuv3",
+                              "s:primary-bus", bus,
+                              NULL) < 0)
+        return NULL;
+
+    return g_steal_pointer(&props);
+}
+
+
 static int
 qemuBuildIOMMUCommandLine(virCommand *cmd,
                           const virDomainDef *def,
@@ -6342,7 +6398,6 @@ qemuBuildIOMMUCommandLine(virCommand *cmd,
         return 0;
 
     case VIR_DOMAIN_IOMMU_MODEL_SMMUV3:
-        /* There is no -device for SMMUv3, so nothing to be done here */
         return 0;
 
     case VIR_DOMAIN_IOMMU_MODEL_AMD:
@@ -6373,6 +6428,14 @@ qemuBuildIOMMUCommandLine(virCommand *cmd,
 
         return 0;
 
+    case VIR_DOMAIN_IOMMU_MODEL_SMMUV3_DEV:
+        if (!(props = qemuBuildPCISmmuv3DevDevProps(def, iommu)))
+            return -1;
+        if (qemuBuildDeviceCommandlineFromJSON(cmd, props, def, qemuCaps) < 0)
+            return -1;
+
+        return 0;
+
     case VIR_DOMAIN_IOMMU_MODEL_LAST:
     default:
         virReportEnumRangeError(virDomainIOMMUModel, iommu->model);
@@ -7206,6 +7269,7 @@ qemuBuildMachineCommandLine(virCommand *cmd,
         case VIR_DOMAIN_IOMMU_MODEL_INTEL:
         case VIR_DOMAIN_IOMMU_MODEL_VIRTIO:
         case VIR_DOMAIN_IOMMU_MODEL_AMD:
+        case VIR_DOMAIN_IOMMU_MODEL_SMMUV3_DEV:
             /* These IOMMUs are formatted in qemuBuildIOMMUCommandLine */
             break;
 
@@ -10860,15 +10924,15 @@ qemuBuildCommandLine(virDomainObj *vm,
     if (qemuBuildBootCommandLine(cmd, def) < 0)
         return NULL;
 
-    if (qemuBuildIOMMUCommandLine(cmd, def, qemuCaps) < 0)
-        return NULL;
-
     if (qemuBuildGlobalControllerCommandLine(cmd, def) < 0)
         return NULL;
 
     if (qemuBuildControllersCommandLine(cmd, def, qemuCaps) < 0)
         return NULL;
 
+    if (qemuBuildIOMMUCommandLine(cmd, def, qemuCaps) < 0)
+        return NULL;
+
     if (qemuBuildMemoryDeviceCommandLine(cmd, cfg, def, priv) < 0)
         return NULL;
 
diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c
index 96a9ca9b14..06bf4fab32 100644
--- a/src/qemu/qemu_domain_address.c
+++ b/src/qemu/qemu_domain_address.c
@@ -952,6 +952,7 @@ qemuDomainDeviceCalculatePCIConnectFlags(virDomainDeviceDef *dev,
 
             case VIR_DOMAIN_IOMMU_MODEL_INTEL:
             case VIR_DOMAIN_IOMMU_MODEL_SMMUV3:
+            case VIR_DOMAIN_IOMMU_MODEL_SMMUV3_DEV:
             case VIR_DOMAIN_IOMMU_MODEL_LAST:
                 /* These are not PCI devices */
                 return 0;
@@ -2378,6 +2379,7 @@ qemuDomainAssignDevicePCISlots(virDomainDef *def,
 
         case VIR_DOMAIN_IOMMU_MODEL_INTEL:
         case VIR_DOMAIN_IOMMU_MODEL_SMMUV3:
+        case VIR_DOMAIN_IOMMU_MODEL_SMMUV3_DEV:
         case VIR_DOMAIN_IOMMU_MODEL_LAST:
             /* These are not PCI devices */
             break;
diff --git a/src/qemu/qemu_validate.c b/src/qemu/qemu_validate.c
index c7ecb467a3..aac004c544 100644
--- a/src/qemu/qemu_validate.c
+++ b/src/qemu/qemu_validate.c
@@ -5414,6 +5414,22 @@ qemuValidateDomainDeviceDefIOMMU(const virDomainIOMMUDef *iommu,
         }
         break;
 
+    case VIR_DOMAIN_IOMMU_MODEL_SMMUV3_DEV:
+        if (!qemuDomainIsARMVirt(def)) {
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                           _("IOMMU device: '%1$s' is only supported with ARM Virt machines"),
+                           virDomainIOMMUModelTypeToString(iommu->model));
+            return -1;
+        }
+        // TODO: Check for pluggable device SMMUv3 qemu capability
+        if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_MACHINE_VIRT_IOMMU)) {
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                           _("IOMMU device: '%1$s' is not supported with this QEMU binary"),
+                           virDomainIOMMUModelTypeToString(iommu->model));
+            return -1;
+        }
+        break;
+
     case VIR_DOMAIN_IOMMU_MODEL_LAST:
     default:
         virReportEnumRangeError(virDomainIOMMUModel, iommu->model);
-- 
2.43.0
Re: [PATCH v2 1/3] qemu: add IOMMU model smmuv3Dev
Posted by Ján Tomko via Devel 4 months ago
On a Wednesday in 2025, Nathan Chen via Devel wrote:
>Introduce support for "smmuv3Dev" IOMMU model and
>its "parentIdx" driver attribute. The "parentIdx"
>attribute indicates the index of the controller that a
>smmuv3Dev IOMMU device is attached to.
>
>Signed-off-by: Nathan Chen <nathanc@nvidia.com>
>---
> docs/formatdomain.rst             |  9 +++-
> src/conf/domain_conf.c            | 17 ++++++++
> src/conf/domain_conf.h            |  2 +
> src/conf/domain_validate.c        | 26 +++++++++--
> src/conf/schemas/domaincommon.rng |  6 +++
> src/qemu/qemu_command.c           | 72 +++++++++++++++++++++++++++++--
> src/qemu/qemu_domain_address.c    |  2 +
> src/qemu/qemu_validate.c          | 16 +++++++
> 8 files changed, 141 insertions(+), 9 deletions(-)
>
>diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst
>index f50dce477f..6a62291600 100644
>--- a/docs/formatdomain.rst
>+++ b/docs/formatdomain.rst
>@@ -9161,8 +9161,9 @@ Example:
> ``model``
>    Supported values are ``intel`` (for Q35 guests) ``smmuv3``
>    (:since:`since 5.5.0`, for ARM virt guests), ``virtio``
>-   (:since:`since 8.3.0`, for Q35 and ARM virt guests) and
>-   ``amd`` (:since:`since 11.5.0`).
>+   (:since:`since 8.3.0`, for Q35 and ARM virt guests),
>+   ``amd`` (:since:`since 11.5.0`), and ``smmuv3Dev`` (for
>+   ARM virt guests).
>
> ``driver``
>    The ``driver`` subelement can be used to configure additional options, some
>@@ -9212,6 +9213,10 @@ Example:
>       Enable x2APIC mode. Useful for higher number of guest CPUs.
>       :since:`Since 11.5.0` (QEMU/KVM and ``amd`` model only)
>
>+   ``parentIdx``
>+      The ``parentIdx`` attribute notes the index of the controller that an
>+      IOMMU device is attached to. (QEMU/KVM and ``smmuv3Dev`` 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 281846dfbe..6d1adb831d 100644
>--- a/src/conf/domain_conf.c
>+++ b/src/conf/domain_conf.c
>@@ -1353,6 +1353,7 @@ VIR_ENUM_IMPL(virDomainIOMMUModel,
>               "smmuv3",
>               "virtio",
>               "amd",
>+              "smmuv3Dev",

Is a separate device model necessary here?

The 'smmuv3' model is already there and the presence of the
parentIdx/pciBus attribute specifies whether -machine or -device should
be used.

> );
>
> VIR_ENUM_IMPL(virDomainVsockModel,
>@@ -2813,6 +2814,8 @@ virDomainIOMMUDefNew(void)
>
>     iommu = g_new0(virDomainIOMMUDef, 1);
>
>+    iommu->parent_idx = -1;
>+
>     return g_steal_pointer(&iommu);
> }
>
>@@ -14439,6 +14442,10 @@ virDomainIOMMUDefParseXML(virDomainXMLOption *xmlopt,
>         if (virXMLPropTristateSwitch(driver, "passthrough", VIR_XML_PROP_NONE,
>                                      &iommu->pt) < 0)
>             return NULL;
>+
>+        if (virXMLPropInt(driver, "parentIdx", 10, VIR_XML_PROP_NONE,

To me, parentIdx somehow implies that this is also a PCI controller.

Jano

>+                          &iommu->parent_idx, -1) < 0)
>+            return NULL;
>     }
>
>     if (virDomainDeviceInfoParseXML(xmlopt, node, ctxt,
Re: [PATCH v2 1/3] qemu: add IOMMU model smmuv3Dev
Posted by Daniel P. Berrangé via Devel 4 months ago
On Wed, Oct 01, 2025 at 05:23:46PM -0700, Nathan Chen via Devel wrote:
> Introduce support for "smmuv3Dev" IOMMU model and
> its "parentIdx" driver attribute. The "parentIdx"
> attribute indicates the index of the controller that a
> smmuv3Dev IOMMU device is attached to.
> 
> Signed-off-by: Nathan Chen <nathanc@nvidia.com>
> ---
>  docs/formatdomain.rst             |  9 +++-
>  src/conf/domain_conf.c            | 17 ++++++++
>  src/conf/domain_conf.h            |  2 +
>  src/conf/domain_validate.c        | 26 +++++++++--
>  src/conf/schemas/domaincommon.rng |  6 +++
>  src/qemu/qemu_command.c           | 72 +++++++++++++++++++++++++++++--
>  src/qemu/qemu_domain_address.c    |  2 +
>  src/qemu/qemu_validate.c          | 16 +++++++
>  8 files changed, 141 insertions(+), 9 deletions(-)


> @@ -9212,6 +9213,10 @@ Example:
>        Enable x2APIC mode. Useful for higher number of guest CPUs.
>        :since:`Since 11.5.0` (QEMU/KVM and ``amd`` model only)
>  
> +   ``parentIdx``
> +      The ``parentIdx`` attribute notes the index of the controller that an
> +      IOMMU device is attached to. (QEMU/KVM and ``smmuv3Dev`` model only)
> +

In the individual devices, for the <address> element we use 'bus' to refer
to the index of the PCI controller. I wonder if we shouldn't keep that
terminology similar, such that we get a 'pciBus' attribute instead
of 'parentIdx'. eg 

  <iommu .... pciBus='2'/>



With regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|
Re: [PATCH v2 1/3] qemu: add IOMMU model smmuv3Dev
Posted by Daniel P. Berrangé via Devel 4 months ago
On Wed, Oct 01, 2025 at 05:23:46PM -0700, Nathan Chen via Devel wrote:
> Introduce support for "smmuv3Dev" IOMMU model and
> its "parentIdx" driver attribute. The "parentIdx"
> attribute indicates the index of the controller that a
> smmuv3Dev IOMMU device is attached to.
> 
> Signed-off-by: Nathan Chen <nathanc@nvidia.com>
> ---
>  docs/formatdomain.rst             |  9 +++-
>  src/conf/domain_conf.c            | 17 ++++++++
>  src/conf/domain_conf.h            |  2 +
>  src/conf/domain_validate.c        | 26 +++++++++--
>  src/conf/schemas/domaincommon.rng |  6 +++
>  src/qemu/qemu_command.c           | 72 +++++++++++++++++++++++++++++--
>  src/qemu/qemu_domain_address.c    |  2 +
>  src/qemu/qemu_validate.c          | 16 +++++++
>  8 files changed, 141 insertions(+), 9 deletions(-)

> diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
> index 031f09b7a5..e789e8cf2c 100644
> --- a/src/qemu/qemu_command.c
> +++ b/src/qemu/qemu_command.c
> @@ -6294,6 +6294,62 @@ qemuBuildBootCommandLine(virCommand *cmd,
>  }
>  
>  
> +static virJSONValue *
> +qemuBuildPCISmmuv3DevDevProps(const virDomainDef *def,
> +                              const virDomainIOMMUDef *iommu)
> +{
> +    g_autoptr(virJSONValue) props = NULL;
> +    g_autofree char *bus = NULL;
> +    size_t i;
> +    bool contIsPHB = false;
> +
> +    for (i = 0; i < def->ncontrollers; i++) {
> +        virDomainControllerDef *cont = def->controllers[i];
> +        if (cont->idx == iommu->parent_idx) {
> +            if (cont->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI) {
> +                const char *alias = cont->info.alias;
> +                contIsPHB = virDomainControllerIsPSeriesPHB(cont);

IIUC,  PSeries PHB is an ppc64 device, while SMMUv3 is a aarch64
device. Given your validation check in qemu_validate.c, this
combination of "IsPHB==true" and SMMUv3 seems like an impossible
situation that doesn't need to be chedcked for and thus....

> +
> +                if (!alias)
> +                    return NULL;
> +
> +                if (virDomainDeviceAliasIsUserAlias(alias)) {
> +                    if (cont->model == VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT &&
> +                        iommu->parent_idx <= 0) {
> +                        if (qemuDomainSupportsPCIMultibus(def))
> +                            bus = g_strdup("pci.0");
> +                        else
> +                            bus = g_strdup("pci");
> +                    } else if (cont->model == VIR_DOMAIN_CONTROLLER_MODEL_PCIE_ROOT) {
> +                        bus = g_strdup("pcie.0");
> +                    }
> +                } else {
> +                    bus = g_strdup(alias);
> +                }
> +                break;
> +            }
> +        }
> +    }
> +
> +    if (!bus)
> +        return NULL;

This needs to be calling virReportError I think, since no earlier code
path has already blocked this scenario ?

> +
> +    if (contIsPHB && iommu->parent_idx > 0) {
> +        char *temp_bus = g_strdup_printf("%s.0", bus);
> +        g_free(bus);
> +        bus = temp_bus;
> +    }

...this if {} block should be dead code.

> +
> +    if (virJSONValueObjectAdd(&props,
> +                              "s:driver", "arm-smmuv3",
> +                              "s:primary-bus", bus,
> +                              NULL) < 0)
> +        return NULL;
> +
> +    return g_steal_pointer(&props);
> +}

With regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|