]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
iommu/arm-smmu-v3: Implement IOMMU_HWPT_ALLOC_NEST_PARENT
authorJason Gunthorpe <jgg@nvidia.com>
Thu, 31 Oct 2024 00:20:50 +0000 (21:20 -0300)
committerWill Deacon <will@kernel.org>
Tue, 5 Nov 2024 10:24:17 +0000 (10:24 +0000)
For SMMUv3 the parent must be a S2 domain, which can be composed
into a IOMMU_DOMAIN_NESTED.

In future the S2 parent will also need a VMID linked to the VIOMMU and
even to KVM.

Reviewed-by: Nicolin Chen <nicolinc@nvidia.com>
Tested-by: Nicolin Chen <nicolinc@nvidia.com>
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Reviewed-by: Jerry Snitselaar <jsnitsel@redhat.com>
Reviewed-by: Mostafa Saleh <smostafa@google.com>
Reviewed-by: Donald Dutile <ddutile@redhat.com>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
Link: https://lore.kernel.org/r/6-v4-9e99b76f3518+3a8-smmuv3_nesting_jgg@nvidia.com
Signed-off-by: Will Deacon <will@kernel.org>
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c

index 996774d461aea20708c34a760f4d82a4ccfb68ca..80847fa386fcd2b94e98adabfc48803a0033700c 100644 (file)
@@ -3114,7 +3114,8 @@ arm_smmu_domain_alloc_user(struct device *dev, u32 flags,
                           const struct iommu_user_data *user_data)
 {
        struct arm_smmu_master *master = dev_iommu_priv_get(dev);
-       const u32 PAGING_FLAGS = IOMMU_HWPT_ALLOC_DIRTY_TRACKING;
+       const u32 PAGING_FLAGS = IOMMU_HWPT_ALLOC_DIRTY_TRACKING |
+                                IOMMU_HWPT_ALLOC_NEST_PARENT;
        struct arm_smmu_domain *smmu_domain;
        int ret;
 
@@ -3127,6 +3128,14 @@ arm_smmu_domain_alloc_user(struct device *dev, u32 flags,
        if (IS_ERR(smmu_domain))
                return ERR_CAST(smmu_domain);
 
+       if (flags & IOMMU_HWPT_ALLOC_NEST_PARENT) {
+               if (!(master->smmu->features & ARM_SMMU_FEAT_NESTING)) {
+                       ret = -EOPNOTSUPP;
+                       goto err_free;
+               }
+               smmu_domain->stage = ARM_SMMU_DOMAIN_S2;
+       }
+
        smmu_domain->domain.type = IOMMU_DOMAIN_UNMANAGED;
        smmu_domain->domain.ops = arm_smmu_ops.default_domain_ops;
        ret = arm_smmu_domain_finalise(smmu_domain, master->smmu, flags);