On a Wednesday in 2025, Nathan Chen via Devel wrote:
Introduce support for "pciBus" driver attribute for
"smmuv3" IOMMU model. The "pciBus" attribute indicates
the index of the controller that a smmuv3 IOMMU device
is attached to, and differentiates the device-pluggable
arm-smmuv3 model from the virt-machine-associated smmuv3
model.

Signed-off-by: Nathan Chen <[email protected]>
---
docs/formatdomain.rst             |  4 ++
src/conf/domain_conf.c            | 16 +++++++
src/conf/domain_conf.h            |  1 +
src/conf/domain_validate.c        | 28 ++++++++++--
src/conf/schemas/domaincommon.rng |  5 ++
src/qemu/qemu_command.c           | 76 ++++++++++++++++++++++++++++---
6 files changed, 121 insertions(+), 9 deletions(-)

diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst
index 4c245f41a9..a181462d13 100644
--- a/docs/formatdomain.rst
+++ b/docs/formatdomain.rst
@@ -9238,6 +9238,10 @@ Example:
      Enable x2APIC mode. Useful for higher number of guest CPUs.
      :since:`Since 11.5.0` (QEMU/KVM and ``amd`` model only)

+   ``pciBus``
+      The ``pciBus`` attribute notes the index of the controller that an
+      IOMMU device is attached to. (QEMU/KVM and ``smmuv3`` 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/schemas/domaincommon.rng 
b/src/conf/schemas/domaincommon.rng
index ae3fa95904..9afc679258 100644
--- a/src/conf/schemas/domaincommon.rng
+++ b/src/conf/schemas/domaincommon.rng
@@ -6322,6 +6322,11 @@
                <ref name="virOnOff"/>
              </attribute>
            </optional>
+            <optional>
+              <attribute name="pciBus">
+                <data type="unsignedInt"/>
+              </attribute>
+            </optional>
          </element>
        </optional>
        <optional>
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 97fe4267ec..ad749afc41 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -6239,6 +6239,62 @@ qemuBuildBootCommandLine(virCommand *cmd,
}


+static virJSONValue *
+qemuBuildPCINestedSmmuv3DevProps(const virDomainDef *def,
+                                 const virDomainIOMMUDef *iommu,
+                                 size_t id)
+{
+    g_autoptr(virJSONValue) props = NULL;
+    g_autofree char *bus = NULL;
+    g_autofree char *smmuv3_id = NULL;
+    size_t i;
+

+    for (i = 0; i < def->ncontrollers; i++) {
+        virDomainControllerDef *cont = def->controllers[i];
+        if (cont->idx == iommu->pci_bus) {
+            if (cont->type == VIR_DOMAIN_CONTROLLER_TYPE_PCI) {
+                const char *alias = cont->info.alias;
+
+                if (!alias)
+                    return NULL;
+
+                if (virDomainDeviceAliasIsUserAlias(alias)) {
+                    if (cont->model == VIR_DOMAIN_CONTROLLER_MODEL_PCI_ROOT &&
+                        iommu->pci_bus == 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;
+            }
+        }
+    }

This duplicates parts of 'qemuBuildDeviceAddressPCIGetBus'

+
+    if (!bus) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                        _("Could not find a suitable controller for smmuv3."));
+        return NULL;
+    }
+
+    smmuv3_id = g_strdup_printf("smmuv3.%zu", id);
+
+    if (virJSONValueObjectAdd(&props,
+                              "s:driver", "arm-smmuv3",
+                              "s:primary-bus", bus,
+                              "s:id", smmuv3_id,
+                              NULL) < 0)
+        return NULL;
+
+    return g_steal_pointer(&props);
+}
+
+
static int
qemuBuildIOMMUCommandLine(virCommand *cmd,
                          const virDomainDef *def,
@@ -6286,9 +6342,6 @@ qemuBuildIOMMUCommandLine(virCommand *cmd,
                return -1;

            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:
            if (virJSONValueObjectAdd(&wrapperProps,
@@ -6318,6 +6371,17 @@ qemuBuildIOMMUCommandLine(virCommand *cmd,

            return 0;

+        case VIR_DOMAIN_IOMMU_MODEL_SMMUV3:
+            if (iommu->pci_bus >= 0) {
+                if (!(props = qemuBuildPCINestedSmmuv3DevProps(def, iommu, i)))
+                    return -1;
+                if (qemuBuildDeviceCommandlineFromJSON(cmd, props, def, qemuCaps) 
< 0)
+                    return -1;
+                break;
+            } else {
+                return 0;
+            }

No need for the else branch.

+
        case VIR_DOMAIN_IOMMU_MODEL_LAST:
        default:
            virReportEnumRangeError(virDomainIOMMUModel, iommu->model);
@@ -10822,15 +10886,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;
+

Formatting the IOMMU devices after the controllers makes sense, but
should be in a separate patch.

    if (qemuBuildMemoryDeviceCommandLine(cmd, cfg, def, priv) < 0)
        return NULL;


Reviewed-by: Ján Tomko <[email protected]>

Jano

Attachment: signature.asc
Description: PGP signature

Reply via email to