Index: sys/dev/iommu/iommu_gas.h =================================================================== --- sys/dev/iommu/iommu_gas.h +++ sys/dev/iommu/iommu_gas.h @@ -50,7 +50,6 @@ #define IOMMU_MAP_ENTRY_MAP 0x0004 /* Busdma created, linked by dmamap_link */ #define IOMMU_MAP_ENTRY_UNMAPPED 0x0010 /* No backing pages */ -#define IOMMU_MAP_ENTRY_QI_NF 0x0020 /* qi task, do not free entry */ #define IOMMU_MAP_ENTRY_READ 0x1000 /* Read permitted */ #define IOMMU_MAP_ENTRY_WRITE 0x2000 /* Write permitted */ #define IOMMU_MAP_ENTRY_SNOOP 0x4000 /* Snoop */ Index: sys/x86/iommu/intel_ctx.c =================================================================== --- sys/x86/iommu/intel_ctx.c +++ sys/x86/iommu/intel_ctx.c @@ -875,18 +875,21 @@ domain = IODOM2DOM(entry->domain); unit = DOM2DMAR(domain); - if (unit->qi_enabled) { + + /* + * If "free" is false, then the IOTLB invalidation must be performed + * synchronously. Otherwise, the caller might free the entry before + * dmar_qi_task() is finished processing it. + */ + if (unit->qi_enabled && free) { DMAR_LOCK(unit); - dmar_qi_invalidate_locked(IODOM2DOM(entry->domain), - entry->start, entry->end - entry->start, &entry->gseq, - true); - if (!free) - entry->flags |= IOMMU_MAP_ENTRY_QI_NF; + 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 { - domain_flush_iotlb_sync(IODOM2DOM(entry->domain), - entry->start, entry->end - entry->start); + domain_flush_iotlb_sync(domain, entry->start, entry->end - + entry->start); dmar_domain_free_entry(entry, free); } } Index: sys/x86/iommu/intel_qi.c =================================================================== --- sys/x86/iommu/intel_qi.c +++ sys/x86/iommu/intel_qi.c @@ -362,8 +362,7 @@ break; TAILQ_REMOVE(&unit->tlb_flush_entries, entry, dmamap_link); DMAR_UNLOCK(unit); - dmar_domain_free_entry(entry, (entry->flags & - IOMMU_MAP_ENTRY_QI_NF) == 0); + dmar_domain_free_entry(entry, true); DMAR_LOCK(unit); } if (unit->inv_seq_waiters > 0)