Skip to content

Commit 886f816

Browse files
LuBaolujoergroedel
authored andcommitted
iommu/vt-d: Remove struct intel_svm
The struct intel_svm was used for keeping attached devices info for sva domain. Since sva domain is a kind of iommu_domain, the struct dmar_domain should centralize all info of a sva domain, including the info of attached devices. Therefore, retire struct intel_svm and clean up the code. Besides, register mmu notifier callback in domain_alloc_sva() callback which allows the memory management notifier lifetime to follow the lifetime of the iommu_domain. Call mmu_notifier_put() in the domain free and defer the real free to the mmu free_notifier callback. Co-developed-by: Tina Zhang <tina.zhang@intel.com> Signed-off-by: Tina Zhang <tina.zhang@intel.com> Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com> Reviewed-by: Kevin Tian <kevin.tian@intel.com> Link: https://lore.kernel.org/r/20240416080656.60968-13-baolu.lu@linux.intel.com Signed-off-by: Joerg Roedel <jroedel@suse.de>
1 parent 6544250 commit 886f816

File tree

3 files changed

+37
-99
lines changed

3 files changed

+37
-99
lines changed

drivers/iommu/intel/iommu.c

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3683,8 +3683,6 @@ static struct iommu_domain *intel_iommu_domain_alloc(unsigned type)
36833683
return domain;
36843684
case IOMMU_DOMAIN_IDENTITY:
36853685
return &si_domain->domain;
3686-
case IOMMU_DOMAIN_SVA:
3687-
return intel_svm_domain_alloc();
36883686
default:
36893687
return NULL;
36903688
}
@@ -4382,14 +4380,6 @@ static void intel_iommu_remove_dev_pasid(struct device *dev, ioasid_t pasid)
43824380
goto out_tear_down;
43834381
dmar_domain = to_dmar_domain(domain);
43844382

4385-
/*
4386-
* The SVA implementation needs to handle its own stuffs like the mm
4387-
* notification. Before consolidating that code into iommu core, let
4388-
* the intel sva code handle it.
4389-
*/
4390-
if (domain->type == IOMMU_DOMAIN_SVA)
4391-
intel_svm_remove_dev_pasid(domain);
4392-
43934383
spin_lock_irqsave(&dmar_domain->lock, flags);
43944384
list_for_each_entry(curr, &dmar_domain->dev_pasids, link_domain) {
43954385
if (curr->dev == dev && curr->pasid == pasid) {
@@ -4624,6 +4614,7 @@ const struct iommu_ops intel_iommu_ops = {
46244614
.hw_info = intel_iommu_hw_info,
46254615
.domain_alloc = intel_iommu_domain_alloc,
46264616
.domain_alloc_user = intel_iommu_domain_alloc_user,
4617+
.domain_alloc_sva = intel_svm_domain_alloc,
46274618
.probe_device = intel_iommu_probe_device,
46284619
.probe_finalize = intel_iommu_probe_finalize,
46294620
.release_device = intel_iommu_release_device,

drivers/iommu/intel/iommu.h

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -648,8 +648,12 @@ struct dmar_domain {
648648
/* link to parent domain siblings */
649649
struct list_head s2_link;
650650
};
651+
652+
/* SVA domain */
653+
struct {
654+
struct mmu_notifier notifier;
655+
};
651656
};
652-
struct intel_svm *svm;
653657

654658
struct iommu_domain domain; /* generic domain data structure for
655659
iommu core */
@@ -1149,26 +1153,16 @@ int intel_svm_enable_prq(struct intel_iommu *iommu);
11491153
int intel_svm_finish_prq(struct intel_iommu *iommu);
11501154
void intel_svm_page_response(struct device *dev, struct iopf_fault *evt,
11511155
struct iommu_page_response *msg);
1152-
struct iommu_domain *intel_svm_domain_alloc(void);
1153-
void intel_svm_remove_dev_pasid(struct iommu_domain *domain);
1156+
struct iommu_domain *intel_svm_domain_alloc(struct device *dev,
1157+
struct mm_struct *mm);
11541158
void intel_drain_pasid_prq(struct device *dev, u32 pasid);
1155-
1156-
struct intel_svm {
1157-
struct mmu_notifier notifier;
1158-
struct mm_struct *mm;
1159-
u32 pasid;
1160-
struct dmar_domain *domain;
1161-
};
11621159
#else
11631160
static inline void intel_svm_check(struct intel_iommu *iommu) {}
11641161
static inline void intel_drain_pasid_prq(struct device *dev, u32 pasid) {}
1165-
static inline struct iommu_domain *intel_svm_domain_alloc(void)
1166-
{
1167-
return NULL;
1168-
}
1169-
1170-
static inline void intel_svm_remove_dev_pasid(struct iommu_domain *domain)
1162+
static inline struct iommu_domain *intel_svm_domain_alloc(struct device *dev,
1163+
struct mm_struct *mm)
11711164
{
1165+
return ERR_PTR(-ENODEV);
11721166
}
11731167
#endif
11741168

drivers/iommu/intel/svm.c

Lines changed: 26 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -26,23 +26,6 @@
2626

2727
static irqreturn_t prq_event_thread(int irq, void *d);
2828

29-
static DEFINE_XARRAY_ALLOC(pasid_private_array);
30-
static int pasid_private_add(ioasid_t pasid, void *priv)
31-
{
32-
return xa_alloc(&pasid_private_array, &pasid, priv,
33-
XA_LIMIT(pasid, pasid), GFP_ATOMIC);
34-
}
35-
36-
static void pasid_private_remove(ioasid_t pasid)
37-
{
38-
xa_erase(&pasid_private_array, pasid);
39-
}
40-
41-
static void *pasid_private_find(ioasid_t pasid)
42-
{
43-
return xa_load(&pasid_private_array, pasid);
44-
}
45-
4629
int intel_svm_enable_prq(struct intel_iommu *iommu)
4730
{
4831
struct iopf_queue *iopfq;
@@ -156,10 +139,9 @@ static void intel_arch_invalidate_secondary_tlbs(struct mmu_notifier *mn,
156139
struct mm_struct *mm,
157140
unsigned long start, unsigned long end)
158141
{
159-
struct intel_svm *svm = container_of(mn, struct intel_svm, notifier);
160-
struct dmar_domain *domain = svm->domain;
142+
struct dmar_domain *domain = container_of(mn, struct dmar_domain, notifier);
161143

162-
if (start == 0 && end == -1UL) {
144+
if (start == 0 && end == ULONG_MAX) {
163145
cache_tag_flush_all(domain);
164146
return;
165147
}
@@ -174,8 +156,7 @@ static void intel_arch_invalidate_secondary_tlbs(struct mmu_notifier *mn,
174156

175157
static void intel_mm_release(struct mmu_notifier *mn, struct mm_struct *mm)
176158
{
177-
struct intel_svm *svm = container_of(mn, struct intel_svm, notifier);
178-
struct dmar_domain *domain = svm->domain;
159+
struct dmar_domain *domain = container_of(mn, struct dmar_domain, notifier);
179160
struct dev_pasid_info *dev_pasid;
180161
struct device_domain_info *info;
181162
unsigned long flags;
@@ -202,9 +183,15 @@ static void intel_mm_release(struct mmu_notifier *mn, struct mm_struct *mm)
202183

203184
}
204185

186+
static void intel_mm_free_notifier(struct mmu_notifier *mn)
187+
{
188+
kfree(container_of(mn, struct dmar_domain, notifier));
189+
}
190+
205191
static const struct mmu_notifier_ops intel_mmuops = {
206192
.release = intel_mm_release,
207193
.arch_invalidate_secondary_tlbs = intel_arch_invalidate_secondary_tlbs,
194+
.free_notifier = intel_mm_free_notifier,
208195
};
209196

210197
static int intel_svm_set_dev_pasid(struct iommu_domain *domain,
@@ -215,40 +202,13 @@ static int intel_svm_set_dev_pasid(struct iommu_domain *domain,
215202
struct intel_iommu *iommu = info->iommu;
216203
struct mm_struct *mm = domain->mm;
217204
struct dev_pasid_info *dev_pasid;
218-
struct intel_svm *svm;
219205
unsigned long sflags;
220206
unsigned long flags;
221207
int ret = 0;
222208

223-
svm = pasid_private_find(pasid);
224-
if (!svm) {
225-
svm = kzalloc(sizeof(*svm), GFP_KERNEL);
226-
if (!svm)
227-
return -ENOMEM;
228-
229-
svm->pasid = pasid;
230-
svm->mm = mm;
231-
232-
svm->notifier.ops = &intel_mmuops;
233-
svm->domain = to_dmar_domain(domain);
234-
ret = mmu_notifier_register(&svm->notifier, mm);
235-
if (ret) {
236-
kfree(svm);
237-
return ret;
238-
}
239-
240-
ret = pasid_private_add(svm->pasid, svm);
241-
if (ret) {
242-
mmu_notifier_unregister(&svm->notifier, mm);
243-
kfree(svm);
244-
return ret;
245-
}
246-
}
247-
248-
dmar_domain->svm = svm;
249209
dev_pasid = kzalloc(sizeof(*dev_pasid), GFP_KERNEL);
250210
if (!dev_pasid)
251-
goto free_svm;
211+
return -ENOMEM;
252212

253213
dev_pasid->dev = dev;
254214
dev_pasid->pasid = pasid;
@@ -274,30 +234,10 @@ static int intel_svm_set_dev_pasid(struct iommu_domain *domain,
274234
cache_tag_unassign_domain(to_dmar_domain(domain), dev, pasid);
275235
free_dev_pasid:
276236
kfree(dev_pasid);
277-
free_svm:
278-
if (list_empty(&dmar_domain->dev_pasids)) {
279-
mmu_notifier_unregister(&svm->notifier, mm);
280-
pasid_private_remove(pasid);
281-
kfree(svm);
282-
}
283237

284238
return ret;
285239
}
286240

287-
void intel_svm_remove_dev_pasid(struct iommu_domain *domain)
288-
{
289-
struct dmar_domain *dmar_domain = to_dmar_domain(domain);
290-
struct intel_svm *svm = dmar_domain->svm;
291-
struct mm_struct *mm = domain->mm;
292-
293-
if (list_empty(&dmar_domain->dev_pasids)) {
294-
if (svm->notifier.ops)
295-
mmu_notifier_unregister(&svm->notifier, mm);
296-
pasid_private_remove(svm->pasid);
297-
kfree(svm);
298-
}
299-
}
300-
301241
/* Page request queue descriptor */
302242
struct page_req_dsc {
303243
union {
@@ -611,27 +551,40 @@ void intel_svm_page_response(struct device *dev, struct iopf_fault *evt,
611551

612552
static void intel_svm_domain_free(struct iommu_domain *domain)
613553
{
614-
kfree(to_dmar_domain(domain));
554+
struct dmar_domain *dmar_domain = to_dmar_domain(domain);
555+
556+
/* dmar_domain free is deferred to the mmu free_notifier callback. */
557+
mmu_notifier_put(&dmar_domain->notifier);
615558
}
616559

617560
static const struct iommu_domain_ops intel_svm_domain_ops = {
618561
.set_dev_pasid = intel_svm_set_dev_pasid,
619562
.free = intel_svm_domain_free
620563
};
621564

622-
struct iommu_domain *intel_svm_domain_alloc(void)
565+
struct iommu_domain *intel_svm_domain_alloc(struct device *dev,
566+
struct mm_struct *mm)
623567
{
624568
struct dmar_domain *domain;
569+
int ret;
625570

626571
domain = kzalloc(sizeof(*domain), GFP_KERNEL);
627572
if (!domain)
628-
return NULL;
573+
return ERR_PTR(-ENOMEM);
574+
629575
domain->domain.ops = &intel_svm_domain_ops;
630576
domain->use_first_level = true;
631577
INIT_LIST_HEAD(&domain->dev_pasids);
632578
INIT_LIST_HEAD(&domain->cache_tags);
633579
spin_lock_init(&domain->cache_lock);
634580
spin_lock_init(&domain->lock);
635581

582+
domain->notifier.ops = &intel_mmuops;
583+
ret = mmu_notifier_register(&domain->notifier, mm);
584+
if (ret) {
585+
kfree(domain);
586+
return ERR_PTR(ret);
587+
}
588+
636589
return &domain->domain;
637590
}

0 commit comments

Comments
 (0)