[RFC PATCH 1/5] conf: Add a nestedSmmuv3 IOMMU model

Nathan Chen via Devel posted 5 patches 1 week, 3 days ago
[RFC PATCH 1/5] conf: Add a nestedSmmuv3 IOMMU model
Posted by Nathan Chen via Devel 1 week, 3 days ago
Add support for specifying "nestedSmmuv3" as the IOMMU model. In the following
commits, when the "nestedSmmuv3" IOMMU model is parsed from the VM definition,
PXB controllers and "nestedSmmuv3" devices will be auto-added to the VM
definition and VFIO devices will be routed to PXB controllers based on their
association with host SMMU nodes. The auto-added "nestedSmmuv3" devices will
each be attached to a PXB controller so that VFIO devices with unique host
SMMU node associations are attached to unique PXB controllers.

Signed-off-by: Nathan Chen <nathanc@nvidia.com>
---
 docs/formatdomain.rst             |  5 +++--
 src/conf/domain_conf.c            |  1 +
 src/conf/domain_conf.h            |  1 +
 src/conf/domain_validate.c        |  2 ++
 src/conf/schemas/domaincommon.rng |  1 +
 src/qemu/qemu_command.c           |  6 +++++-
 src/qemu/qemu_domain_address.c    |  2 ++
 src/qemu/qemu_validate.c          | 15 +++++++++++++++
 8 files changed, 30 insertions(+), 3 deletions(-)

diff --git a/docs/formatdomain.rst b/docs/formatdomain.rst
index 60bee8bd4f..63bb565991 100644
--- a/docs/formatdomain.rst
+++ b/docs/formatdomain.rst
@@ -8729,8 +8729,9 @@ Example:
    ...
 
 ``model``
-   Supported values are ``intel`` (for Q35 guests) ``smmuv3``
-   (:since:`since 5.5.0`, for ARM virt guests), and ``virtio``
+   Supported values are ``intel`` (for Q35 guests), ``smmuv3``
+   (:since:`since 5.5.0`, for ARM virt guests), ``nestedSmmuv3``
+   (for ARM virt guests), and ``virtio``
    (:since:`since 8.3.0`, for Q35 and ARM virt guests).
 
 ``driver``
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 4ad8289b89..c1092551e0 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -1349,6 +1349,7 @@ VIR_ENUM_IMPL(virDomainIOMMUModel,
               "intel",
               "smmuv3",
               "virtio",
+              "nestedSmmuv3",
 );
 
 VIR_ENUM_IMPL(virDomainVsockModel,
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index a187ab4083..f8ab1b7d2f 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -2944,6 +2944,7 @@ typedef enum {
     VIR_DOMAIN_IOMMU_MODEL_INTEL,
     VIR_DOMAIN_IOMMU_MODEL_SMMUV3,
     VIR_DOMAIN_IOMMU_MODEL_VIRTIO,
+    VIR_DOMAIN_IOMMU_MODEL_NESTED_SMMUV3,
 
     VIR_DOMAIN_IOMMU_MODEL_LAST
 } virDomainIOMMUModel;
diff --git a/src/conf/domain_validate.c b/src/conf/domain_validate.c
index 1034bb57f5..c8b7b701bf 100644
--- a/src/conf/domain_validate.c
+++ b/src/conf/domain_validate.c
@@ -3001,6 +3001,7 @@ virDomainIOMMUDefValidate(const virDomainIOMMUDef *iommu)
 {
     switch (iommu->model) {
     case VIR_DOMAIN_IOMMU_MODEL_SMMUV3:
+    case VIR_DOMAIN_IOMMU_MODEL_NESTED_SMMUV3:
     case VIR_DOMAIN_IOMMU_MODEL_VIRTIO:
         if (iommu->intremap != VIR_TRISTATE_SWITCH_ABSENT ||
             iommu->caching_mode != VIR_TRISTATE_SWITCH_ABSENT ||
@@ -3022,6 +3023,7 @@ virDomainIOMMUDefValidate(const virDomainIOMMUDef *iommu)
 
     switch (iommu->model) {
     case VIR_DOMAIN_IOMMU_MODEL_SMMUV3:
+    case VIR_DOMAIN_IOMMU_MODEL_NESTED_SMMUV3:
     case VIR_DOMAIN_IOMMU_MODEL_INTEL:
         if (iommu->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE) {
             virReportError(VIR_ERR_XML_ERROR,
diff --git a/src/conf/schemas/domaincommon.rng b/src/conf/schemas/domaincommon.rng
index b3fdbf7ffb..de6a1e5c7e 100644
--- a/src/conf/schemas/domaincommon.rng
+++ b/src/conf/schemas/domaincommon.rng
@@ -6144,6 +6144,7 @@
           <value>intel</value>
           <value>smmuv3</value>
           <value>virtio</value>
+          <value>nestedSmmuv3</value>
         </choice>
       </attribute>
       <interleave>
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index dcb9c4934e..6629addace 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -6063,6 +6063,9 @@ qemuBuildIOMMUCommandLine(virCommand *cmd,
         /* There is no -device for SMMUv3, so nothing to be done here */
         return 0;
 
+    case VIR_DOMAIN_IOMMU_MODEL_NESTED_SMMUV3:
+        return 0;
+
     case VIR_DOMAIN_IOMMU_MODEL_LAST:
     default:
         virReportEnumRangeError(virDomainIOMMUModel, iommu->model);
@@ -6885,7 +6888,8 @@ qemuBuildMachineCommandLine(virCommand *cmd,
         case VIR_DOMAIN_IOMMU_MODEL_VIRTIO:
             /* These IOMMUs are formatted in qemuBuildIOMMUCommandLine */
             break;
-
+        case VIR_DOMAIN_IOMMU_MODEL_NESTED_SMMUV3:
+            break;
         case VIR_DOMAIN_IOMMU_MODEL_LAST:
         default:
             virReportEnumRangeError(virDomainIOMMUModel, def->iommu->model);
diff --git a/src/qemu/qemu_domain_address.c b/src/qemu/qemu_domain_address.c
index 970ae3949d..51f4bbd6eb 100644
--- a/src/qemu/qemu_domain_address.c
+++ b/src/qemu/qemu_domain_address.c
@@ -943,6 +943,7 @@ qemuDomainDeviceCalculatePCIConnectFlags(virDomainDeviceDef *dev,
 
             case VIR_DOMAIN_IOMMU_MODEL_INTEL:
             case VIR_DOMAIN_IOMMU_MODEL_SMMUV3:
+            case VIR_DOMAIN_IOMMU_MODEL_NESTED_SMMUV3:
             case VIR_DOMAIN_IOMMU_MODEL_LAST:
                 /* These are not PCI devices */
                 return 0;
@@ -2367,6 +2368,7 @@ qemuDomainAssignDevicePCISlots(virDomainDef *def,
 
         case VIR_DOMAIN_IOMMU_MODEL_INTEL:
         case VIR_DOMAIN_IOMMU_MODEL_SMMUV3:
+        case VIR_DOMAIN_IOMMU_MODEL_NESTED_SMMUV3:
         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 aaa056379e..9f07ffe4a3 100644
--- a/src/qemu/qemu_validate.c
+++ b/src/qemu/qemu_validate.c
@@ -5104,6 +5104,21 @@ qemuValidateDomainDeviceDefIOMMU(const virDomainIOMMUDef *iommu,
         }
         break;
 
+    case VIR_DOMAIN_IOMMU_MODEL_NESTED_SMMUV3:
+        if (!qemuDomainIsARMVirt(def)) {
+            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
+                           _("IOMMU device: '%1$s' is only supported with ARM Virt machines"),
+                           virDomainIOMMUModelTypeToString(iommu->model));
+            return -1;
+        }
+        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.34.1