Skip to content

Commit 8430fd3

Browse files
LuBaolujoergroedel
authored andcommitted
iommu/vt-d: Acquiring lock in pasid manipulation helpers
The iommu->lock is used to protect the per-IOMMU pasid directory table and pasid table. Move the spinlock acquisition/release into the helpers to make the code self-contained. Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com> Reviewed-by: Kevin Tian <kevin.tian@intel.com> Link: https://lore.kernel.org/r/20220706025524.2904370-8-baolu.lu@linux.intel.com Signed-off-by: Joerg Roedel <jroedel@suse.de>
1 parent 2c3262f commit 8430fd3

3 files changed

Lines changed: 55 additions & 53 deletions

File tree

drivers/iommu/intel/iommu.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2489,7 +2489,6 @@ static int domain_add_dev_info(struct dmar_domain *domain, struct device *dev)
24892489
}
24902490

24912491
/* Setup the PASID entry for requests without PASID: */
2492-
spin_lock(&iommu->lock);
24932492
if (hw_pass_through && domain_type_is_si(domain))
24942493
ret = intel_pasid_setup_pass_through(iommu, domain,
24952494
dev, PASID_RID2PASID);
@@ -2499,7 +2498,6 @@ static int domain_add_dev_info(struct dmar_domain *domain, struct device *dev)
24992498
else
25002499
ret = intel_pasid_setup_second_level(iommu, domain,
25012500
dev, PASID_RID2PASID);
2502-
spin_unlock(&iommu->lock);
25032501
if (ret) {
25042502
dev_err(dev, "Setup RID2PASID failed\n");
25052503
dmar_remove_one_dev_info(dev);

drivers/iommu/intel/pasid.c

Lines changed: 55 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -450,17 +450,17 @@ void intel_pasid_tear_down_entry(struct intel_iommu *iommu, struct device *dev,
450450
struct pasid_entry *pte;
451451
u16 did, pgtt;
452452

453+
spin_lock(&iommu->lock);
453454
pte = intel_pasid_get_entry(dev, pasid);
454-
if (WARN_ON(!pte))
455-
return;
456-
457-
if (!pasid_pte_is_present(pte))
455+
if (WARN_ON(!pte) || !pasid_pte_is_present(pte)) {
456+
spin_unlock(&iommu->lock);
458457
return;
458+
}
459459

460460
did = pasid_get_domain_id(pte);
461461
pgtt = pasid_pte_get_pgtt(pte);
462-
463462
intel_pasid_clear_entry(dev, pasid, fault_ignore);
463+
spin_unlock(&iommu->lock);
464464

465465
if (!ecap_coherent(iommu->ecap))
466466
clflush_cache_range(pte, sizeof(*pte));
@@ -496,22 +496,6 @@ static void pasid_flush_caches(struct intel_iommu *iommu,
496496
}
497497
}
498498

499-
static inline int pasid_enable_wpe(struct pasid_entry *pte)
500-
{
501-
#ifdef CONFIG_X86
502-
unsigned long cr0 = read_cr0();
503-
504-
/* CR0.WP is normally set but just to be sure */
505-
if (unlikely(!(cr0 & X86_CR0_WP))) {
506-
pr_err_ratelimited("No CPU write protect!\n");
507-
return -EINVAL;
508-
}
509-
#endif
510-
pasid_set_wpe(pte);
511-
512-
return 0;
513-
};
514-
515499
/*
516500
* Set up the scalable mode pasid table entry for first only
517501
* translation type.
@@ -528,39 +512,52 @@ int intel_pasid_setup_first_level(struct intel_iommu *iommu,
528512
return -EINVAL;
529513
}
530514

531-
pte = intel_pasid_get_entry(dev, pasid);
532-
if (WARN_ON(!pte))
515+
if (flags & PASID_FLAG_SUPERVISOR_MODE) {
516+
#ifdef CONFIG_X86
517+
unsigned long cr0 = read_cr0();
518+
519+
/* CR0.WP is normally set but just to be sure */
520+
if (unlikely(!(cr0 & X86_CR0_WP))) {
521+
pr_err("No CPU write protect!\n");
522+
return -EINVAL;
523+
}
524+
#endif
525+
if (!ecap_srs(iommu->ecap)) {
526+
pr_err("No supervisor request support on %s\n",
527+
iommu->name);
528+
return -EINVAL;
529+
}
530+
}
531+
532+
if ((flags & PASID_FLAG_FL5LP) && !cap_5lp_support(iommu->cap)) {
533+
pr_err("No 5-level paging support for first-level on %s\n",
534+
iommu->name);
533535
return -EINVAL;
536+
}
534537

535-
/* Caller must ensure PASID entry is not in use. */
536-
if (pasid_pte_is_present(pte))
538+
spin_lock(&iommu->lock);
539+
pte = intel_pasid_get_entry(dev, pasid);
540+
if (!pte) {
541+
spin_unlock(&iommu->lock);
542+
return -ENODEV;
543+
}
544+
545+
if (pasid_pte_is_present(pte)) {
546+
spin_unlock(&iommu->lock);
537547
return -EBUSY;
548+
}
538549

539550
pasid_clear_entry(pte);
540551

541552
/* Setup the first level page table pointer: */
542553
pasid_set_flptr(pte, (u64)__pa(pgd));
543554
if (flags & PASID_FLAG_SUPERVISOR_MODE) {
544-
if (!ecap_srs(iommu->ecap)) {
545-
pr_err("No supervisor request support on %s\n",
546-
iommu->name);
547-
return -EINVAL;
548-
}
549555
pasid_set_sre(pte);
550-
if (pasid_enable_wpe(pte))
551-
return -EINVAL;
552-
556+
pasid_set_wpe(pte);
553557
}
554558

555-
if (flags & PASID_FLAG_FL5LP) {
556-
if (cap_5lp_support(iommu->cap)) {
557-
pasid_set_flpm(pte, 1);
558-
} else {
559-
pr_err("No 5-level paging support for first-level\n");
560-
pasid_clear_entry(pte);
561-
return -EINVAL;
562-
}
563-
}
559+
if (flags & PASID_FLAG_FL5LP)
560+
pasid_set_flpm(pte, 1);
564561

565562
if (flags & PASID_FLAG_PAGE_SNOOP)
566563
pasid_set_pgsnp(pte);
@@ -572,6 +569,8 @@ int intel_pasid_setup_first_level(struct intel_iommu *iommu,
572569
/* Setup Present and PASID Granular Transfer Type: */
573570
pasid_set_translation_type(pte, PASID_ENTRY_PGTT_FL_ONLY);
574571
pasid_set_present(pte);
572+
spin_unlock(&iommu->lock);
573+
575574
pasid_flush_caches(iommu, pte, pasid, did);
576575

577576
return 0;
@@ -629,15 +628,17 @@ int intel_pasid_setup_second_level(struct intel_iommu *iommu,
629628
pgd_val = virt_to_phys(pgd);
630629
did = domain->iommu_did[iommu->seq_id];
631630

631+
spin_lock(&iommu->lock);
632632
pte = intel_pasid_get_entry(dev, pasid);
633633
if (!pte) {
634-
dev_err(dev, "Failed to get pasid entry of PASID %d\n", pasid);
634+
spin_unlock(&iommu->lock);
635635
return -ENODEV;
636636
}
637637

638-
/* Caller must ensure PASID entry is not in use. */
639-
if (pasid_pte_is_present(pte))
638+
if (pasid_pte_is_present(pte)) {
639+
spin_unlock(&iommu->lock);
640640
return -EBUSY;
641+
}
641642

642643
pasid_clear_entry(pte);
643644
pasid_set_domain_id(pte, did);
@@ -654,6 +655,8 @@ int intel_pasid_setup_second_level(struct intel_iommu *iommu,
654655
if (pasid != PASID_RID2PASID)
655656
pasid_set_sre(pte);
656657
pasid_set_present(pte);
658+
spin_unlock(&iommu->lock);
659+
657660
pasid_flush_caches(iommu, pte, pasid, did);
658661

659662
return 0;
@@ -669,15 +672,17 @@ int intel_pasid_setup_pass_through(struct intel_iommu *iommu,
669672
u16 did = FLPT_DEFAULT_DID;
670673
struct pasid_entry *pte;
671674

675+
spin_lock(&iommu->lock);
672676
pte = intel_pasid_get_entry(dev, pasid);
673677
if (!pte) {
674-
dev_err(dev, "Failed to get pasid entry of PASID %d\n", pasid);
678+
spin_unlock(&iommu->lock);
675679
return -ENODEV;
676680
}
677681

678-
/* Caller must ensure PASID entry is not in use. */
679-
if (pasid_pte_is_present(pte))
682+
if (pasid_pte_is_present(pte)) {
683+
spin_unlock(&iommu->lock);
680684
return -EBUSY;
685+
}
681686

682687
pasid_clear_entry(pte);
683688
pasid_set_domain_id(pte, did);
@@ -692,6 +697,8 @@ int intel_pasid_setup_pass_through(struct intel_iommu *iommu,
692697
*/
693698
pasid_set_sre(pte);
694699
pasid_set_present(pte);
700+
spin_unlock(&iommu->lock);
701+
695702
pasid_flush_caches(iommu, pte, pasid, did);
696703

697704
return 0;

drivers/iommu/intel/svm.c

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -394,11 +394,8 @@ static struct iommu_sva *intel_svm_bind_mm(struct intel_iommu *iommu,
394394
sflags = (flags & SVM_FLAG_SUPERVISOR_MODE) ?
395395
PASID_FLAG_SUPERVISOR_MODE : 0;
396396
sflags |= cpu_feature_enabled(X86_FEATURE_LA57) ? PASID_FLAG_FL5LP : 0;
397-
spin_lock(&iommu->lock);
398397
ret = intel_pasid_setup_first_level(iommu, dev, mm->pgd, mm->pasid,
399398
FLPT_DEFAULT_DID, sflags);
400-
spin_unlock(&iommu->lock);
401-
402399
if (ret)
403400
goto free_sdev;
404401

0 commit comments

Comments
 (0)