Skip to content

Commit 386fa64

Browse files
LuBaolujoergroedel
authored andcommitted
arm-smmu-v3/sva: Add SVA domain support
Add support for SVA domain allocation and provide an SVA-specific iommu_domain_ops. This implementation is based on the existing SVA code. Possible cleanup and refactoring are left for incremental changes later. Signed-off-by: Lu Baolu <[email protected]> Reviewed-by: Jean-Philippe Brucker <[email protected]> Reviewed-by: Jason Gunthorpe <[email protected]> Tested-by: Zhangfei Gao <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Joerg Roedel <[email protected]>
1 parent eaca888 commit 386fa64

File tree

3 files changed

+90
-0
lines changed

3 files changed

+90
-0
lines changed

drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -549,3 +549,64 @@ void arm_smmu_sva_notifier_synchronize(void)
549549
*/
550550
mmu_notifier_synchronize();
551551
}
552+
553+
void arm_smmu_sva_remove_dev_pasid(struct iommu_domain *domain,
554+
struct device *dev, ioasid_t id)
555+
{
556+
struct mm_struct *mm = domain->mm;
557+
struct arm_smmu_bond *bond = NULL, *t;
558+
struct arm_smmu_master *master = dev_iommu_priv_get(dev);
559+
560+
mutex_lock(&sva_lock);
561+
list_for_each_entry(t, &master->bonds, list) {
562+
if (t->mm == mm) {
563+
bond = t;
564+
break;
565+
}
566+
}
567+
568+
if (!WARN_ON(!bond) && refcount_dec_and_test(&bond->refs)) {
569+
list_del(&bond->list);
570+
arm_smmu_mmu_notifier_put(bond->smmu_mn);
571+
kfree(bond);
572+
}
573+
mutex_unlock(&sva_lock);
574+
}
575+
576+
static int arm_smmu_sva_set_dev_pasid(struct iommu_domain *domain,
577+
struct device *dev, ioasid_t id)
578+
{
579+
int ret = 0;
580+
struct iommu_sva *handle;
581+
struct mm_struct *mm = domain->mm;
582+
583+
mutex_lock(&sva_lock);
584+
handle = __arm_smmu_sva_bind(dev, mm);
585+
if (IS_ERR(handle))
586+
ret = PTR_ERR(handle);
587+
mutex_unlock(&sva_lock);
588+
589+
return ret;
590+
}
591+
592+
static void arm_smmu_sva_domain_free(struct iommu_domain *domain)
593+
{
594+
kfree(domain);
595+
}
596+
597+
static const struct iommu_domain_ops arm_smmu_sva_domain_ops = {
598+
.set_dev_pasid = arm_smmu_sva_set_dev_pasid,
599+
.free = arm_smmu_sva_domain_free
600+
};
601+
602+
struct iommu_domain *arm_smmu_sva_domain_alloc(void)
603+
{
604+
struct iommu_domain *domain;
605+
606+
domain = kzalloc(sizeof(*domain), GFP_KERNEL);
607+
if (!domain)
608+
return NULL;
609+
domain->ops = &arm_smmu_sva_domain_ops;
610+
611+
return domain;
612+
}

drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2009,6 +2009,9 @@ static struct iommu_domain *arm_smmu_domain_alloc(unsigned type)
20092009
{
20102010
struct arm_smmu_domain *smmu_domain;
20112011

2012+
if (type == IOMMU_DOMAIN_SVA)
2013+
return arm_smmu_sva_domain_alloc();
2014+
20122015
if (type != IOMMU_DOMAIN_UNMANAGED &&
20132016
type != IOMMU_DOMAIN_DMA &&
20142017
type != IOMMU_DOMAIN_DMA_FQ &&
@@ -2838,6 +2841,17 @@ static int arm_smmu_def_domain_type(struct device *dev)
28382841
return 0;
28392842
}
28402843

2844+
static void arm_smmu_remove_dev_pasid(struct device *dev, ioasid_t pasid)
2845+
{
2846+
struct iommu_domain *domain;
2847+
2848+
domain = iommu_get_domain_for_dev_pasid(dev, pasid, IOMMU_DOMAIN_SVA);
2849+
if (WARN_ON(IS_ERR(domain)) || !domain)
2850+
return;
2851+
2852+
arm_smmu_sva_remove_dev_pasid(domain, dev, pasid);
2853+
}
2854+
28412855
static struct iommu_ops arm_smmu_ops = {
28422856
.capable = arm_smmu_capable,
28432857
.domain_alloc = arm_smmu_domain_alloc,
@@ -2846,6 +2860,7 @@ static struct iommu_ops arm_smmu_ops = {
28462860
.device_group = arm_smmu_device_group,
28472861
.of_xlate = arm_smmu_of_xlate,
28482862
.get_resv_regions = arm_smmu_get_resv_regions,
2863+
.remove_dev_pasid = arm_smmu_remove_dev_pasid,
28492864
.dev_enable_feat = arm_smmu_dev_enable_feature,
28502865
.dev_disable_feat = arm_smmu_dev_disable_feature,
28512866
.sva_bind = arm_smmu_sva_bind,

drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -758,6 +758,9 @@ struct iommu_sva *arm_smmu_sva_bind(struct device *dev, struct mm_struct *mm);
758758
void arm_smmu_sva_unbind(struct iommu_sva *handle);
759759
u32 arm_smmu_sva_get_pasid(struct iommu_sva *handle);
760760
void arm_smmu_sva_notifier_synchronize(void);
761+
struct iommu_domain *arm_smmu_sva_domain_alloc(void);
762+
void arm_smmu_sva_remove_dev_pasid(struct iommu_domain *domain,
763+
struct device *dev, ioasid_t id);
761764
#else /* CONFIG_ARM_SMMU_V3_SVA */
762765
static inline bool arm_smmu_sva_supported(struct arm_smmu_device *smmu)
763766
{
@@ -803,5 +806,16 @@ static inline u32 arm_smmu_sva_get_pasid(struct iommu_sva *handle)
803806
}
804807

805808
static inline void arm_smmu_sva_notifier_synchronize(void) {}
809+
810+
static inline struct iommu_domain *arm_smmu_sva_domain_alloc(void)
811+
{
812+
return NULL;
813+
}
814+
815+
static inline void arm_smmu_sva_remove_dev_pasid(struct iommu_domain *domain,
816+
struct device *dev,
817+
ioasid_t id)
818+
{
819+
}
806820
#endif /* CONFIG_ARM_SMMU_V3_SVA */
807821
#endif /* _ARM_SMMU_V3_H */

0 commit comments

Comments
 (0)