git: 938cac4bdf17 - stable/14 - dmar: on unmap, postpone freeing page table pages after the invalidation is done
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sat, 05 Oct 2024 07:11:36 UTC
The branch stable/14 has been updated by kib: URL: https://cgit.FreeBSD.org/src/commit/?id=938cac4bdf17188644512d5bbaba6768940fc423 commit 938cac4bdf17188644512d5bbaba6768940fc423 Author: Konstantin Belousov <kib@FreeBSD.org> AuthorDate: 2024-09-25 03:54:44 +0000 Commit: Konstantin Belousov <kib@FreeBSD.org> CommitDate: 2024-10-05 07:08:56 +0000 dmar: on unmap, postpone freeing page table pages after the invalidation is done (cherry picked from commit 3848dc4fe6f37cbcfaea29eb94fa560a503f60ab) --- sys/x86/iommu/intel_idpgtbl.c | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/sys/x86/iommu/intel_idpgtbl.c b/sys/x86/iommu/intel_idpgtbl.c index 9dc7a2d58b3f..e1b89571971b 100644 --- a/sys/x86/iommu/intel_idpgtbl.c +++ b/sys/x86/iommu/intel_idpgtbl.c @@ -69,7 +69,8 @@ #include <x86/iommu/intel_dmar.h> static int dmar_unmap_buf_locked(struct dmar_domain *domain, - iommu_gaddr_t base, iommu_gaddr_t size, int flags); + iommu_gaddr_t base, iommu_gaddr_t size, int flags, + struct iommu_map_entry *entry); /* * The cache of the identity mapping page tables for the DMARs. Using @@ -387,7 +388,8 @@ retry: static int dmar_map_buf_locked(struct dmar_domain *domain, iommu_gaddr_t base, - iommu_gaddr_t size, vm_page_t *ma, uint64_t pflags, int flags) + iommu_gaddr_t size, vm_page_t *ma, uint64_t pflags, int flags, + struct iommu_map_entry *entry) { iommu_pte_t *pte; struct sf_buf *sf; @@ -447,7 +449,7 @@ dmar_map_buf_locked(struct dmar_domain *domain, iommu_gaddr_t base, if (sf != NULL) iommu_unmap_pgtbl(sf); dmar_unmap_buf_locked(domain, base1, base - base1, - flags); + flags, entry); TD_PINNED_ASSERT; return (ENOMEM); } @@ -518,7 +520,8 @@ dmar_map_buf(struct iommu_domain *iodom, struct iommu_map_entry *entry, KASSERT((flags & ~IOMMU_PGF_WAITOK) == 0, ("invalid flags %x", flags)); DMAR_DOMAIN_PGLOCK(domain); - error = dmar_map_buf_locked(domain, base, size, ma, pflags, flags); + error = dmar_map_buf_locked(domain, base, size, ma, pflags, flags, + entry); DMAR_DOMAIN_PGUNLOCK(domain); if (error != 0) return (error); @@ -536,11 +539,11 @@ dmar_map_buf(struct iommu_domain *iodom, struct iommu_map_entry *entry, static void dmar_unmap_clear_pte(struct dmar_domain *domain, iommu_gaddr_t base, int lvl, int flags, iommu_pte_t *pte, - struct sf_buf **sf, bool free_fs); + struct sf_buf **sf, struct iommu_map_entry *entry, bool free_fs); static void dmar_free_pgtbl_pde(struct dmar_domain *domain, iommu_gaddr_t base, - int lvl, int flags) + int lvl, int flags, struct iommu_map_entry *entry) { struct sf_buf *sf; iommu_pte_t *pde; @@ -548,12 +551,14 @@ dmar_free_pgtbl_pde(struct dmar_domain *domain, iommu_gaddr_t base, sf = NULL; pde = dmar_pgtbl_map_pte(domain, base, lvl, flags, &idx, &sf); - dmar_unmap_clear_pte(domain, base, lvl, flags, pde, &sf, true); + dmar_unmap_clear_pte(domain, base, lvl, flags, pde, &sf, + entry, true); } static void dmar_unmap_clear_pte(struct dmar_domain *domain, iommu_gaddr_t base, int lvl, - int flags, iommu_pte_t *pte, struct sf_buf **sf, bool free_sf) + int flags, iommu_pte_t *pte, struct sf_buf **sf, + struct iommu_map_entry *entry, bool free_sf) { vm_page_t m; @@ -572,8 +577,8 @@ dmar_unmap_clear_pte(struct dmar_domain *domain, iommu_gaddr_t base, int lvl, KASSERT(m->pindex != 0, ("lost reference (idx) on root pg domain %p base %jx lvl %d", domain, (uintmax_t)base, lvl)); - iommu_pgfree(domain->pgtbl_obj, m->pindex, flags, NULL); - dmar_free_pgtbl_pde(domain, base, lvl - 1, flags); + iommu_pgfree(domain->pgtbl_obj, m->pindex, flags, entry); + dmar_free_pgtbl_pde(domain, base, lvl - 1, flags, entry); } /* @@ -581,7 +586,7 @@ dmar_unmap_clear_pte(struct dmar_domain *domain, iommu_gaddr_t base, int lvl, */ static int dmar_unmap_buf_locked(struct dmar_domain *domain, iommu_gaddr_t base, - iommu_gaddr_t size, int flags) + iommu_gaddr_t size, int flags, struct iommu_map_entry *entry) { iommu_pte_t *pte; struct sf_buf *sf; @@ -632,7 +637,7 @@ dmar_unmap_buf_locked(struct dmar_domain *domain, iommu_gaddr_t base, if ((pte->pte & DMAR_PTE_SP) != 0 || lvl == domain->pglvl - 1) { dmar_unmap_clear_pte(domain, base, lvl, - flags, pte, &sf, false); + flags, pte, &sf, entry, false); break; } } @@ -662,7 +667,7 @@ dmar_unmap_buf(struct iommu_domain *iodom, struct iommu_map_entry *entry, DMAR_DOMAIN_PGLOCK(domain); error = dmar_unmap_buf_locked(domain, entry->start, entry->end - - entry->start, flags); + entry->start, flags, entry); DMAR_DOMAIN_PGUNLOCK(domain); return (error); }