git: 5639dde5edc9 - stable/13 - x86/iommu: Correct a recent change to iommu_domain_unload_entry()

From: Doug Moore <dougm_at_FreeBSD.org>
Date: Mon, 08 Aug 2022 07:08:07 UTC
The branch stable/13 has been updated by dougm:

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

commit 5639dde5edc9b2bd0502f55bce2e07af2ddb01c7
Author:     Alan Cox <alc@FreeBSD.org>
AuthorDate: 2022-07-26 04:53:15 +0000
Commit:     Doug Moore <dougm@FreeBSD.org>
CommitDate: 2022-08-08 07:07:20 +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
    
    (cherry picked from commit c251563470831c34cf53242936425a0d4d995edf)
---
 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 1bb923f33d86..98dfed7aaa17 100644
--- a/sys/x86/iommu/intel_ctx.c
+++ b/sys/x86/iommu/intel_ctx.c
@@ -879,17 +879,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 21e626257a0d..2840646f89a6 100644
--- a/sys/x86/iommu/intel_dmar.h
+++ b/sys/x86/iommu/intel_dmar.h
@@ -250,8 +250,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