Skip to content

Commit deda9a7

Browse files
LuBaolujoergroedel
authored andcommitted
iommu/vt-d: Remove intel_svm_dev
The intel_svm_dev data structure used in the sva implementation for the Intel IOMMU driver stores information about a device attached to an SVA domain. It is a duplicate of dev_pasid_info that serves the same purpose. Replace intel_svm_dev with dev_pasid_info and clean up the use of intel_svm_dev. 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-11-baolu.lu@linux.intel.com Signed-off-by: Joerg Roedel <jroedel@suse.de>
1 parent 4f609db commit deda9a7

File tree

3 files changed

+42
-110
lines changed

3 files changed

+42
-110
lines changed

drivers/iommu/intel/iommu.c

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4387,11 +4387,8 @@ static void intel_iommu_remove_dev_pasid(struct device *dev, ioasid_t pasid)
43874387
* notification. Before consolidating that code into iommu core, let
43884388
* the intel sva code handle it.
43894389
*/
4390-
if (domain->type == IOMMU_DOMAIN_SVA) {
4391-
intel_svm_remove_dev_pasid(dev, pasid);
4392-
cache_tag_unassign_domain(dmar_domain, dev, pasid);
4393-
goto out_tear_down;
4394-
}
4390+
if (domain->type == IOMMU_DOMAIN_SVA)
4391+
intel_svm_remove_dev_pasid(domain);
43954392

43964393
spin_lock_irqsave(&dmar_domain->lock, flags);
43974394
list_for_each_entry(curr, &dmar_domain->dev_pasids, link_domain) {

drivers/iommu/intel/iommu.h

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -649,6 +649,7 @@ struct dmar_domain {
649649
struct list_head s2_link;
650650
};
651651
};
652+
struct intel_svm *svm;
652653

653654
struct iommu_domain domain; /* generic domain data structure for
654655
iommu core */
@@ -1149,23 +1150,13 @@ int intel_svm_finish_prq(struct intel_iommu *iommu);
11491150
void intel_svm_page_response(struct device *dev, struct iopf_fault *evt,
11501151
struct iommu_page_response *msg);
11511152
struct iommu_domain *intel_svm_domain_alloc(void);
1152-
void intel_svm_remove_dev_pasid(struct device *dev, ioasid_t pasid);
1153+
void intel_svm_remove_dev_pasid(struct iommu_domain *domain);
11531154
void intel_drain_pasid_prq(struct device *dev, u32 pasid);
11541155

1155-
struct intel_svm_dev {
1156-
struct list_head list;
1157-
struct rcu_head rcu;
1158-
struct device *dev;
1159-
struct intel_iommu *iommu;
1160-
u16 did;
1161-
u16 sid, qdep;
1162-
};
1163-
11641156
struct intel_svm {
11651157
struct mmu_notifier notifier;
11661158
struct mm_struct *mm;
11671159
u32 pasid;
1168-
struct list_head devs;
11691160
struct dmar_domain *domain;
11701161
};
11711162
#else
@@ -1176,7 +1167,7 @@ static inline struct iommu_domain *intel_svm_domain_alloc(void)
11761167
return NULL;
11771168
}
11781169

1179-
static inline void intel_svm_remove_dev_pasid(struct device *dev, ioasid_t pasid)
1170+
static inline void intel_svm_remove_dev_pasid(struct iommu_domain *domain)
11801171
{
11811172
}
11821173
#endif

drivers/iommu/intel/svm.c

Lines changed: 37 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -43,23 +43,6 @@ static void *pasid_private_find(ioasid_t pasid)
4343
return xa_load(&pasid_private_array, pasid);
4444
}
4545

46-
static struct intel_svm_dev *
47-
svm_lookup_device_by_dev(struct intel_svm *svm, struct device *dev)
48-
{
49-
struct intel_svm_dev *sdev = NULL, *t;
50-
51-
rcu_read_lock();
52-
list_for_each_entry_rcu(t, &svm->devs, list) {
53-
if (t->dev == dev) {
54-
sdev = t;
55-
break;
56-
}
57-
}
58-
rcu_read_unlock();
59-
60-
return sdev;
61-
}
62-
6346
int intel_svm_enable_prq(struct intel_iommu *iommu)
6447
{
6548
struct iopf_queue *iopfq;
@@ -192,7 +175,10 @@ static void intel_arch_invalidate_secondary_tlbs(struct mmu_notifier *mn,
192175
static void intel_mm_release(struct mmu_notifier *mn, struct mm_struct *mm)
193176
{
194177
struct intel_svm *svm = container_of(mn, struct intel_svm, notifier);
195-
struct intel_svm_dev *sdev;
178+
struct dmar_domain *domain = svm->domain;
179+
struct dev_pasid_info *dev_pasid;
180+
struct device_domain_info *info;
181+
unsigned long flags;
196182

197183
/* This might end up being called from exit_mmap(), *before* the page
198184
* tables are cleared. And __mmu_notifier_release() will delete us from
@@ -206,11 +192,13 @@ static void intel_mm_release(struct mmu_notifier *mn, struct mm_struct *mm)
206192
* page) so that we end up taking a fault that the hardware really
207193
* *has* to handle gracefully without affecting other processes.
208194
*/
209-
rcu_read_lock();
210-
list_for_each_entry_rcu(sdev, &svm->devs, list)
211-
intel_pasid_tear_down_entry(sdev->iommu, sdev->dev,
212-
svm->pasid, true);
213-
rcu_read_unlock();
195+
spin_lock_irqsave(&domain->lock, flags);
196+
list_for_each_entry(dev_pasid, &domain->dev_pasids, link_domain) {
197+
info = dev_iommu_priv_get(dev_pasid->dev);
198+
intel_pasid_tear_down_entry(info->iommu, dev_pasid->dev,
199+
dev_pasid->pasid, true);
200+
}
201+
spin_unlock_irqrestore(&domain->lock, flags);
214202

215203
}
216204

@@ -219,47 +207,17 @@ static const struct mmu_notifier_ops intel_mmuops = {
219207
.arch_invalidate_secondary_tlbs = intel_arch_invalidate_secondary_tlbs,
220208
};
221209

222-
static int pasid_to_svm_sdev(struct device *dev, unsigned int pasid,
223-
struct intel_svm **rsvm,
224-
struct intel_svm_dev **rsdev)
225-
{
226-
struct intel_svm_dev *sdev = NULL;
227-
struct intel_svm *svm;
228-
229-
if (pasid == IOMMU_PASID_INVALID || pasid >= PASID_MAX)
230-
return -EINVAL;
231-
232-
svm = pasid_private_find(pasid);
233-
if (IS_ERR(svm))
234-
return PTR_ERR(svm);
235-
236-
if (!svm)
237-
goto out;
238-
239-
/*
240-
* If we found svm for the PASID, there must be at least one device
241-
* bond.
242-
*/
243-
if (WARN_ON(list_empty(&svm->devs)))
244-
return -EINVAL;
245-
sdev = svm_lookup_device_by_dev(svm, dev);
246-
247-
out:
248-
*rsvm = svm;
249-
*rsdev = sdev;
250-
251-
return 0;
252-
}
253-
254210
static int intel_svm_set_dev_pasid(struct iommu_domain *domain,
255211
struct device *dev, ioasid_t pasid)
256212
{
257213
struct device_domain_info *info = dev_iommu_priv_get(dev);
214+
struct dmar_domain *dmar_domain = to_dmar_domain(domain);
258215
struct intel_iommu *iommu = info->iommu;
259216
struct mm_struct *mm = domain->mm;
260-
struct intel_svm_dev *sdev;
217+
struct dev_pasid_info *dev_pasid;
261218
struct intel_svm *svm;
262219
unsigned long sflags;
220+
unsigned long flags;
263221
int ret = 0;
264222

265223
svm = pasid_private_find(pasid);
@@ -270,7 +228,6 @@ static int intel_svm_set_dev_pasid(struct iommu_domain *domain,
270228

271229
svm->pasid = pasid;
272230
svm->mm = mm;
273-
INIT_LIST_HEAD_RCU(&svm->devs);
274231

275232
svm->notifier.ops = &intel_mmuops;
276233
svm->domain = to_dmar_domain(domain);
@@ -288,25 +245,17 @@ static int intel_svm_set_dev_pasid(struct iommu_domain *domain,
288245
}
289246
}
290247

291-
sdev = kzalloc(sizeof(*sdev), GFP_KERNEL);
292-
if (!sdev) {
293-
ret = -ENOMEM;
248+
dmar_domain->svm = svm;
249+
dev_pasid = kzalloc(sizeof(*dev_pasid), GFP_KERNEL);
250+
if (!dev_pasid)
294251
goto free_svm;
295-
}
296252

297-
sdev->dev = dev;
298-
sdev->iommu = iommu;
299-
sdev->did = FLPT_DEFAULT_DID;
300-
sdev->sid = PCI_DEVID(info->bus, info->devfn);
301-
if (info->ats_enabled) {
302-
sdev->qdep = info->ats_qdep;
303-
if (sdev->qdep >= QI_DEV_EIOTLB_MAX_INVS)
304-
sdev->qdep = 0;
305-
}
253+
dev_pasid->dev = dev;
254+
dev_pasid->pasid = pasid;
306255

307256
ret = cache_tag_assign_domain(to_dmar_domain(domain), dev, pasid);
308257
if (ret)
309-
goto free_sdev;
258+
goto free_dev_pasid;
310259

311260
/* Setup the pasid table: */
312261
sflags = cpu_feature_enabled(X86_FEATURE_LA57) ? PASID_FLAG_FL5LP : 0;
@@ -315,16 +264,18 @@ static int intel_svm_set_dev_pasid(struct iommu_domain *domain,
315264
if (ret)
316265
goto unassign_tag;
317266

318-
list_add_rcu(&sdev->list, &svm->devs);
267+
spin_lock_irqsave(&dmar_domain->lock, flags);
268+
list_add(&dev_pasid->link_domain, &dmar_domain->dev_pasids);
269+
spin_unlock_irqrestore(&dmar_domain->lock, flags);
319270

320271
return 0;
321272

322273
unassign_tag:
323274
cache_tag_unassign_domain(to_dmar_domain(domain), dev, pasid);
324-
free_sdev:
325-
kfree(sdev);
275+
free_dev_pasid:
276+
kfree(dev_pasid);
326277
free_svm:
327-
if (list_empty(&svm->devs)) {
278+
if (list_empty(&dmar_domain->dev_pasids)) {
328279
mmu_notifier_unregister(&svm->notifier, mm);
329280
pasid_private_remove(pasid);
330281
kfree(svm);
@@ -333,26 +284,17 @@ static int intel_svm_set_dev_pasid(struct iommu_domain *domain,
333284
return ret;
334285
}
335286

336-
void intel_svm_remove_dev_pasid(struct device *dev, u32 pasid)
287+
void intel_svm_remove_dev_pasid(struct iommu_domain *domain)
337288
{
338-
struct intel_svm_dev *sdev;
339-
struct intel_svm *svm;
340-
struct mm_struct *mm;
341-
342-
if (pasid_to_svm_sdev(dev, pasid, &svm, &sdev))
343-
return;
344-
mm = svm->mm;
345-
346-
if (sdev) {
347-
list_del_rcu(&sdev->list);
348-
kfree_rcu(sdev, rcu);
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;
349292

350-
if (list_empty(&svm->devs)) {
351-
if (svm->notifier.ops)
352-
mmu_notifier_unregister(&svm->notifier, mm);
353-
pasid_private_remove(svm->pasid);
354-
kfree(svm);
355-
}
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);
356298
}
357299
}
358300

@@ -686,8 +628,10 @@ struct iommu_domain *intel_svm_domain_alloc(void)
686628
return NULL;
687629
domain->domain.ops = &intel_svm_domain_ops;
688630
domain->use_first_level = true;
631+
INIT_LIST_HEAD(&domain->dev_pasids);
689632
INIT_LIST_HEAD(&domain->cache_tags);
690633
spin_lock_init(&domain->cache_lock);
634+
spin_lock_init(&domain->lock);
691635

692636
return &domain->domain;
693637
}

0 commit comments

Comments
 (0)