]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
iommu/arm-smmu-v3: Replace arm_vsmmu_alloc with arm_vsmmu_init
authorNicolin Chen <nicolinc@nvidia.com>
Sat, 14 Jun 2025 06:35:22 +0000 (23:35 -0700)
committerJason Gunthorpe <jgg@nvidia.com>
Thu, 19 Jun 2025 18:43:29 +0000 (15:43 -0300)
To ease the for-driver iommufd APIs, get_viommu_size and viommu_init ops
are introduced.

Sanitize the inputs and report the size of struct arm_vsmmu on success, in
arm_smmu_get_viommu_size().

Place the type sanity at the last, becase there will be soon an impl level
get_viommu_size op, which will require the same sanity tests prior. It can
simply insert a piece of code in front of the IOMMU_VIOMMU_TYPE_ARM_SMMUV3
sanity.

The core will ensure the viommu_type is set to the core vIOMMU object, and
pass in the same dev pointer, so arm_vsmmu_init() won't need to repeat the
same sanity tests but to simply init the arm_vsmmu struct.

Remove the arm_vsmmu_alloc, completing the replacement.

Link: https://patch.msgid.link/r/64e4b4c33acd26e1bd676e077be80e00fb63f17c.1749882255.git.nicolinc@nvidia.com
Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Reviewed-by: Pranjal Shrivastava <praan@google.com>
Acked-by: Will Deacon <will@kernel.org>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h

index e4fd8d522af8824554c2c7666a6318072d7f70e0..9f59c95a254cc84129bf67c980f97656b946323a 100644 (file)
@@ -382,25 +382,14 @@ static const struct iommufd_viommu_ops arm_vsmmu_ops = {
        .cache_invalidate = arm_vsmmu_cache_invalidate,
 };
 
-struct iommufd_viommu *arm_vsmmu_alloc(struct device *dev,
-                                      struct iommu_domain *parent,
-                                      struct iommufd_ctx *ictx,
-                                      unsigned int viommu_type)
+size_t arm_smmu_get_viommu_size(struct device *dev,
+                               enum iommu_viommu_type viommu_type)
 {
-       struct arm_smmu_device *smmu =
-               iommu_get_iommu_dev(dev, struct arm_smmu_device, iommu);
        struct arm_smmu_master *master = dev_iommu_priv_get(dev);
-       struct arm_smmu_domain *s2_parent = to_smmu_domain(parent);
-       struct arm_vsmmu *vsmmu;
-
-       if (viommu_type != IOMMU_VIOMMU_TYPE_ARM_SMMUV3)
-               return ERR_PTR(-EOPNOTSUPP);
+       struct arm_smmu_device *smmu = master->smmu;
 
        if (!(smmu->features & ARM_SMMU_FEAT_NESTING))
-               return ERR_PTR(-EOPNOTSUPP);
-
-       if (s2_parent->smmu != master->smmu)
-               return ERR_PTR(-EINVAL);
+               return 0;
 
        /*
         * FORCE_SYNC is not set with FEAT_NESTING. Some study of the exact HW
@@ -408,7 +397,7 @@ struct iommufd_viommu *arm_vsmmu_alloc(struct device *dev,
         * any change to remove this.
         */
        if (WARN_ON(smmu->options & ARM_SMMU_OPT_CMDQ_FORCE_SYNC))
-               return ERR_PTR(-EOPNOTSUPP);
+               return 0;
 
        /*
         * Must support some way to prevent the VM from bypassing the cache
@@ -420,19 +409,32 @@ struct iommufd_viommu *arm_vsmmu_alloc(struct device *dev,
         */
        if (!arm_smmu_master_canwbs(master) &&
            !(smmu->features & ARM_SMMU_FEAT_S2FWB))
-               return ERR_PTR(-EOPNOTSUPP);
+               return 0;
 
-       vsmmu = iommufd_viommu_alloc(ictx, struct arm_vsmmu, core,
-                                    &arm_vsmmu_ops);
-       if (IS_ERR(vsmmu))
-               return ERR_CAST(vsmmu);
+       if (viommu_type != IOMMU_VIOMMU_TYPE_ARM_SMMUV3)
+               return 0;
+
+       return VIOMMU_STRUCT_SIZE(struct arm_vsmmu, core);
+}
+
+int arm_vsmmu_init(struct iommufd_viommu *viommu,
+                  struct iommu_domain *parent_domain)
+{
+       struct arm_vsmmu *vsmmu = container_of(viommu, struct arm_vsmmu, core);
+       struct arm_smmu_device *smmu =
+               container_of(viommu->iommu_dev, struct arm_smmu_device, iommu);
+       struct arm_smmu_domain *s2_parent = to_smmu_domain(parent_domain);
+
+       if (s2_parent->smmu != smmu)
+               return -EINVAL;
 
        vsmmu->smmu = smmu;
        vsmmu->s2_parent = s2_parent;
        /* FIXME Move VMID allocation from the S2 domain allocation to here */
        vsmmu->vmid = s2_parent->s2_cfg.vmid;
 
-       return &vsmmu->core;
+       viommu->ops = &arm_vsmmu_ops;
+       return 0;
 }
 
 int arm_vmaster_report_event(struct arm_smmu_vmaster *vmaster, u64 *evt)
index 10cc6dc26b7b7c36b937dd2cec929b57682d764f..181d07bc1a9d4faaa465ea998aa21033613f6725 100644 (file)
@@ -3688,7 +3688,8 @@ static struct iommu_ops arm_smmu_ops = {
        .get_resv_regions       = arm_smmu_get_resv_regions,
        .page_response          = arm_smmu_page_response,
        .def_domain_type        = arm_smmu_def_domain_type,
-       .viommu_alloc           = arm_vsmmu_alloc,
+       .get_viommu_size        = arm_smmu_get_viommu_size,
+       .viommu_init            = arm_vsmmu_init,
        .user_pasid_table       = 1,
        .pgsize_bitmap          = -1UL, /* Restricted during device attach */
        .owner                  = THIS_MODULE,
index ea41d790463ed3cf6fc16aa2f1bd4f1e10a4eb9c..bb39af84e6b0a3f1a0273eea2445e07a4bdebd1f 100644 (file)
@@ -1034,18 +1034,19 @@ struct arm_vsmmu {
 
 #if IS_ENABLED(CONFIG_ARM_SMMU_V3_IOMMUFD)
 void *arm_smmu_hw_info(struct device *dev, u32 *length, u32 *type);
-struct iommufd_viommu *arm_vsmmu_alloc(struct device *dev,
-                                      struct iommu_domain *parent,
-                                      struct iommufd_ctx *ictx,
-                                      unsigned int viommu_type);
+size_t arm_smmu_get_viommu_size(struct device *dev,
+                               enum iommu_viommu_type viommu_type);
+int arm_vsmmu_init(struct iommufd_viommu *viommu,
+                  struct iommu_domain *parent_domain);
 int arm_smmu_attach_prepare_vmaster(struct arm_smmu_attach_state *state,
                                    struct arm_smmu_nested_domain *nested_domain);
 void arm_smmu_attach_commit_vmaster(struct arm_smmu_attach_state *state);
 void arm_smmu_master_clear_vmaster(struct arm_smmu_master *master);
 int arm_vmaster_report_event(struct arm_smmu_vmaster *vmaster, u64 *evt);
 #else
+#define arm_smmu_get_viommu_size NULL
 #define arm_smmu_hw_info NULL
-#define arm_vsmmu_alloc NULL
+#define arm_vsmmu_init NULL
 
 static inline int
 arm_smmu_attach_prepare_vmaster(struct arm_smmu_attach_state *state,