On 11/18/2025 10:25 AM, Ján Tomko wrote:
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 <nathanc@nvidia.com> --- 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 <jtomko@redhat.com>
Hi Jano, Thank you for reviewing and providing feedback on these patches. I have sent out the next revision. -Nathan