@@ -56,6 +56,49 @@ static void remove_pdom_dev_pasid(struct protection_domain *pdom,
5656 }
5757}
5858
59+ static void sva_arch_invalidate_secondary_tlbs (struct mmu_notifier * mn ,
60+ struct mm_struct * mm ,
61+ unsigned long start , unsigned long end )
62+ {
63+ struct pdom_dev_data * pdom_dev_data ;
64+ struct protection_domain * sva_pdom ;
65+ unsigned long flags ;
66+
67+ sva_pdom = container_of (mn , struct protection_domain , mn );
68+
69+ spin_lock_irqsave (& sva_pdom -> lock , flags );
70+
71+ for_each_pdom_dev_data (pdom_dev_data , sva_pdom ) {
72+ amd_iommu_dev_flush_pasid_pages (pdom_dev_data -> dev_data ,
73+ pdom_dev_data -> pasid ,
74+ start , end - start );
75+ }
76+
77+ spin_unlock_irqrestore (& sva_pdom -> lock , flags );
78+ }
79+
80+ static void sva_mn_release (struct mmu_notifier * mn , struct mm_struct * mm )
81+ {
82+ struct pdom_dev_data * pdom_dev_data , * next ;
83+ struct protection_domain * sva_pdom ;
84+ unsigned long flags ;
85+
86+ sva_pdom = container_of (mn , struct protection_domain , mn );
87+
88+ spin_lock_irqsave (& sva_pdom -> lock , flags );
89+
90+ /* Assume dev_data_list contains same PASID with different devices */
91+ for_each_pdom_dev_data_safe (pdom_dev_data , next , sva_pdom )
92+ remove_dev_pasid (pdom_dev_data );
93+
94+ spin_unlock_irqrestore (& sva_pdom -> lock , flags );
95+ }
96+
97+ static const struct mmu_notifier_ops sva_mn = {
98+ .arch_invalidate_secondary_tlbs = sva_arch_invalidate_secondary_tlbs ,
99+ .release = sva_mn_release ,
100+ };
101+
59102int iommu_sva_set_dev_pasid (struct iommu_domain * domain ,
60103 struct device * dev , ioasid_t pasid )
61104{
@@ -120,3 +163,40 @@ void amd_iommu_remove_dev_pasid(struct device *dev, ioasid_t pasid)
120163
121164 spin_unlock_irqrestore (& sva_pdom -> lock , flags );
122165}
166+
167+ static void iommu_sva_domain_free (struct iommu_domain * domain )
168+ {
169+ struct protection_domain * sva_pdom = to_pdomain (domain );
170+
171+ if (sva_pdom -> mn .ops )
172+ mmu_notifier_unregister (& sva_pdom -> mn , domain -> mm );
173+
174+ amd_iommu_domain_free (domain );
175+ }
176+
177+ static const struct iommu_domain_ops amd_sva_domain_ops = {
178+ .set_dev_pasid = iommu_sva_set_dev_pasid ,
179+ .free = iommu_sva_domain_free
180+ };
181+
182+ struct iommu_domain * amd_iommu_domain_alloc_sva (struct device * dev ,
183+ struct mm_struct * mm )
184+ {
185+ struct protection_domain * pdom ;
186+ int ret ;
187+
188+ pdom = protection_domain_alloc (IOMMU_DOMAIN_SVA );
189+ if (!pdom )
190+ return ERR_PTR (- ENOMEM );
191+
192+ pdom -> domain .ops = & amd_sva_domain_ops ;
193+ pdom -> mn .ops = & sva_mn ;
194+
195+ ret = mmu_notifier_register (& pdom -> mn , mm );
196+ if (ret ) {
197+ protection_domain_free (pdom );
198+ return ERR_PTR (ret );
199+ }
200+
201+ return & pdom -> domain ;
202+ }
0 commit comments