git: c25156347083 - main - x86/iommu: Correct a recent change to iommu_domain_unload_entry()

From: Alan Cox <alc_at_FreeBSD.org>
Date: Tue, 26 Jul 2022 06:08:09 UTC
The branch main has been updated by alc:

URL: https://cgit.FreeBSD.org/src/commit/?id=c251563470831c34cf53242936425a0d4d995edf

commit c251563470831c34cf53242936425a0d4d995edf
Author:     Alan Cox <alc@FreeBSD.org>
AuthorDate: 2022-07-26 04:53:15 +0000
Commit:     Alan Cox <alc@FreeBSD.org>
CommitDate: 2022-07-26 06:07:21 +0000

    x86/iommu: Correct a recent change to iommu_domain_unload_entry()
    
    Correct 8bc367384745.  When iommu_domain_unload_entry() performs a
    synchronous IOTLB invalidation, it must call dmar_domain_free_entry()
    to remove the entry from the domain's RB_TREE.
    
    Push down the acquisition and release of the DMAR lock into the
    recently introduced function dmar_qi_invalidate_sync_locked() and
    remove the _locked suffix.
    
    MFC with:       8bc367384745
---
 sys/x86/iommu/intel_ctx.c  | 7 ++++---
 sys/x86/iommu/intel_dmar.h | 4 ++--
 sys/x86/iommu/intel_qi.c   | 9 ++++++---
 3 files changed, 12 insertions(+), 8 deletions(-)

diff --git a/sys/x86/iommu/intel_ctx.c b/sys/x86/iommu/intel_ctx.c
index 5e13f020264b..936cf8bb7632 100644
--- a/sys/x86/iommu/intel_ctx.c
+++ b/sys/x86/iommu/intel_ctx.c
@@ -883,17 +883,18 @@ iommu_domain_unload_entry(struct iommu_map_entry *entry, bool free,
 	 * dmar_qi_task() is finished processing it.
 	 */
 	if (unit->qi_enabled) {
-		DMAR_LOCK(unit);
 		if (free) {
+			DMAR_LOCK(unit);
 			dmar_qi_invalidate_locked(domain, entry->start,
 			    entry->end - entry->start, &entry->gseq, true);
 			TAILQ_INSERT_TAIL(&unit->tlb_flush_entries, entry,
 			    dmamap_link);
+			DMAR_UNLOCK(unit);
 		} else {
-			dmar_qi_invalidate_sync_locked(domain, entry->start,
+			dmar_qi_invalidate_sync(domain, entry->start,
 			    entry->end - entry->start, cansleep);
+			dmar_domain_free_entry(entry, false);
 		}
-		DMAR_UNLOCK(unit);
 	} else {
 		domain_flush_iotlb_sync(domain, entry->start, entry->end -
 		    entry->start);
diff --git a/sys/x86/iommu/intel_dmar.h b/sys/x86/iommu/intel_dmar.h
index 0f811d760bb7..06cecdf704ff 100644
--- a/sys/x86/iommu/intel_dmar.h
+++ b/sys/x86/iommu/intel_dmar.h
@@ -251,8 +251,8 @@ int dmar_init_qi(struct dmar_unit *unit);
 void dmar_fini_qi(struct dmar_unit *unit);
 void dmar_qi_invalidate_locked(struct dmar_domain *domain, iommu_gaddr_t start,
     iommu_gaddr_t size, struct iommu_qi_genseq *psec, bool emit_wait);
-void dmar_qi_invalidate_sync_locked(struct dmar_domain *domain,
-    iommu_gaddr_t start, iommu_gaddr_t size, bool cansleep);
+void dmar_qi_invalidate_sync(struct dmar_domain *domain, iommu_gaddr_t start,
+    iommu_gaddr_t size, bool cansleep);
 void dmar_qi_invalidate_ctx_glob_locked(struct dmar_unit *unit);
 void dmar_qi_invalidate_iotlb_glob_locked(struct dmar_unit *unit);
 void dmar_qi_invalidate_iec_glob(struct dmar_unit *unit);
diff --git a/sys/x86/iommu/intel_qi.c b/sys/x86/iommu/intel_qi.c
index 174cf9ea19a8..32f01a2787b0 100644
--- a/sys/x86/iommu/intel_qi.c
+++ b/sys/x86/iommu/intel_qi.c
@@ -243,14 +243,17 @@ dmar_qi_invalidate_locked(struct dmar_domain *domain, iommu_gaddr_t base,
 }
 
 void
-dmar_qi_invalidate_sync_locked(struct dmar_domain *domain, iommu_gaddr_t base,
+dmar_qi_invalidate_sync(struct dmar_domain *domain, iommu_gaddr_t base,
     iommu_gaddr_t size, bool cansleep)
 {
+	struct dmar_unit *unit;
 	struct iommu_qi_genseq gseq;
 
-	DMAR_ASSERT_LOCKED(domain->dmar);
+	unit = domain->dmar;
+	DMAR_LOCK(unit);
 	dmar_qi_invalidate_locked(domain, base, size, &gseq, true);
-	dmar_qi_wait_for_seq(domain->dmar, &gseq, !cansleep);
+	dmar_qi_wait_for_seq(unit, &gseq, !cansleep);
+	DMAR_UNLOCK(unit);
 }
 
 void