[PATCH v5 20/27] iommu: Add ops->domain_alloc_sva()
Michael Shavit
mshavit at google.com
Tue Mar 19 08:09:27 PDT 2024
On Tue, Mar 5, 2024 at 7:44 AM Jason Gunthorpe <jgg at nvidia.com> wrote:
>
> Make a new op that receives the device and the mm_struct that the SVA
> domain should be created for. Unlike domain_alloc_paging() the dev
> argument is never NULL here.
>
> This allows drivers to fully initialize the SVA domain and allocate the
> mmu_notifier during allocation. It allows the notifier lifetime to follow
> the lifetime of the iommu_domain.
>
> Since we have only one call site, upgrade the new op to return ERR_PTR
> instead of NULL.
>
> Change SMMUv3 to use the new op.
>
> Tested-by: Nicolin Chen <nicolinc at nvidia.com>
> Signed-off-by: Jason Gunthorpe <jgg at nvidia.com>
> ---
> drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c | 11 +++++++----
> drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 2 +-
> drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h | 6 +++++-
> drivers/iommu/iommu-sva.c | 4 ++--
> drivers/iommu/iommu.c | 12 +++++++++---
> include/linux/iommu.h | 3 +++
> 6 files changed, 27 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
> index d633316f2e45bc..30b1cf587efffb 100644
> --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
> +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c
> @@ -662,17 +662,20 @@ static const struct iommu_domain_ops arm_smmu_sva_domain_ops = {
> .free = arm_smmu_sva_domain_free
> };
>
> -struct iommu_domain *arm_smmu_sva_domain_alloc(unsigned type)
> +struct iommu_domain *arm_smmu_sva_domain_alloc(struct device *dev,
> + struct mm_struct *mm)
> {
> + struct arm_smmu_master *master = dev_iommu_priv_get(dev);
> + struct arm_smmu_device *smmu = master->smmu;
> struct arm_smmu_domain *smmu_domain;
>
> - if (type != IOMMU_DOMAIN_SVA)
> - return ERR_PTR(-EOPNOTSUPP);
> -
> smmu_domain = arm_smmu_domain_alloc();
> if (IS_ERR(smmu_domain))
> return ERR_CAST(smmu_domain);
> +
> + smmu_domain->domain.type = IOMMU_DOMAIN_SVA;
> smmu_domain->domain.ops = &arm_smmu_sva_domain_ops;
> + smmu_domain->smmu = smmu;
>
> return &smmu_domain->domain;
> }
> diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
> index 6d15fe3a160acf..a255a02a5fc8a9 100644
> --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
> +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
> @@ -3311,8 +3311,8 @@ static struct iommu_ops arm_smmu_ops = {
> .identity_domain = &arm_smmu_identity_domain,
> .blocked_domain = &arm_smmu_blocked_domain,
> .capable = arm_smmu_capable,
> - .domain_alloc = arm_smmu_sva_domain_alloc,
> .domain_alloc_paging = arm_smmu_domain_alloc_paging,
> + .domain_alloc_sva = arm_smmu_sva_domain_alloc,
> .probe_device = arm_smmu_probe_device,
> .release_device = arm_smmu_release_device,
> .device_group = arm_smmu_device_group,
> diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
> index c47e07d695bef2..f62bd2ef36a18d 100644
> --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
> +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h
> @@ -793,7 +793,8 @@ int arm_smmu_master_enable_sva(struct arm_smmu_master *master);
> int arm_smmu_master_disable_sva(struct arm_smmu_master *master);
> bool arm_smmu_master_iopf_supported(struct arm_smmu_master *master);
> void arm_smmu_sva_notifier_synchronize(void);
> -struct iommu_domain *arm_smmu_sva_domain_alloc(unsigned int type);
> +struct iommu_domain *arm_smmu_sva_domain_alloc(struct device *dev,
> + struct mm_struct *mm);
> void arm_smmu_sva_remove_dev_pasid(struct iommu_domain *domain,
> struct device *dev, ioasid_t id);
> #else /* CONFIG_ARM_SMMU_V3_SVA */
> @@ -839,5 +840,8 @@ static inline void arm_smmu_sva_remove_dev_pasid(struct iommu_domain *domain,
> ioasid_t id)
> {
> }
> +
> +#define arm_smmu_sva_domain_alloc NULL
> +
> #endif /* CONFIG_ARM_SMMU_V3_SVA */
> #endif /* _ARM_SMMU_V3_H */
> diff --git a/drivers/iommu/iommu-sva.c b/drivers/iommu/iommu-sva.c
> index 65814cbc840200..aa20ee6a1d8ae7 100644
> --- a/drivers/iommu/iommu-sva.c
> +++ b/drivers/iommu/iommu-sva.c
> @@ -108,8 +108,8 @@ struct iommu_sva *iommu_sva_bind_device(struct device *dev, struct mm_struct *mm
>
> /* Allocate a new domain and set it on device pasid. */
> domain = iommu_sva_domain_alloc(dev, mm);
> - if (!domain) {
> - ret = -ENOMEM;
> + if (IS_ERR(domain)) {
> + ret = PTR_ERR(domain);
> goto out_free_handle;
> }
>
> diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
> index d14413916f93a0..f9a2b8363ad941 100644
> --- a/drivers/iommu/iommu.c
> +++ b/drivers/iommu/iommu.c
> @@ -3629,9 +3629,15 @@ struct iommu_domain *iommu_sva_domain_alloc(struct device *dev,
> const struct iommu_ops *ops = dev_iommu_ops(dev);
> struct iommu_domain *domain;
>
> - domain = ops->domain_alloc(IOMMU_DOMAIN_SVA);
> - if (!domain)
> - return NULL;
> + if (ops->domain_alloc_sva) {
> + domain = ops->domain_alloc_sva(dev, mm);
> + if (IS_ERR(domain))
> + return domain;
> + } else {
> + domain = ops->domain_alloc(IOMMU_DOMAIN_SVA);
> + if (!domain)
> + return ERR_PTR(-ENOMEM);
> + }
>
> domain->type = IOMMU_DOMAIN_SVA;
> mmgrab(mm);
> diff --git a/include/linux/iommu.h b/include/linux/iommu.h
> index 5e27cb3a3be99b..0274044f1fb084 100644
> --- a/include/linux/iommu.h
> +++ b/include/linux/iommu.h
> @@ -419,6 +419,7 @@ static inline int __iommu_copy_struct_from_user_array(
> * Upon failure, ERR_PTR must be returned.
> * @domain_alloc_paging: Allocate an iommu_domain that can be used for
> * UNMANAGED, DMA, and DMA_FQ domain types.
> + * @domain_alloc_sva: Allocate an iommu_domain for Shared Virtual Addressing.
> * @probe_device: Add device to iommu driver handling
> * @release_device: Remove device from iommu driver handling
> * @probe_finalize: Do final setup work after the device is added to an IOMMU
> @@ -459,6 +460,8 @@ struct iommu_ops {
> struct device *dev, u32 flags, struct iommu_domain *parent,
> const struct iommu_user_data *user_data);
> struct iommu_domain *(*domain_alloc_paging)(struct device *dev);
> + struct iommu_domain *(*domain_alloc_sva)(struct device *dev,
> + struct mm_struct *mm);
>
> struct iommu_device *(*probe_device)(struct device *dev);
> void (*release_device)(struct device *dev);
> --
> 2.43.2
>
Reviewed-by: Michael Shavit <mshavit at google.com>
More information about the linux-arm-kernel
mailing list