Changeset View
Changeset View
Standalone View
Standalone View
sys/x86/iommu/intel_idpgtbl.c
Show First 20 Lines • Show All 386 Lines • ▼ Show 20 Lines | if (pte == NULL) { | ||||
/* | /* | ||||
* Prevent potential free while pgtbl_obj is | * Prevent potential free while pgtbl_obj is | ||||
* unlocked in the recursive call to | * unlocked in the recursive call to | ||||
* domain_pgtbl_map_pte(), if other thread did | * domain_pgtbl_map_pte(), if other thread did | ||||
* pte write and clean while the lock is | * pte write and clean while the lock is | ||||
* dropped. | * dropped. | ||||
*/ | */ | ||||
m->wire_count++; | m->ref_count++; | ||||
sfp = NULL; | sfp = NULL; | ||||
ptep = domain_pgtbl_map_pte(domain, base, lvl - 1, | ptep = domain_pgtbl_map_pte(domain, base, lvl - 1, | ||||
flags, &idx1, &sfp); | flags, &idx1, &sfp); | ||||
if (ptep == NULL) { | if (ptep == NULL) { | ||||
KASSERT(m->pindex != 0, | KASSERT(m->pindex != 0, | ||||
("loosing root page %p", domain)); | ("loosing root page %p", domain)); | ||||
m->wire_count--; | m->ref_count--; | ||||
dmar_pgfree(domain->pgtbl_obj, m->pindex, | dmar_pgfree(domain->pgtbl_obj, m->pindex, | ||||
flags); | flags); | ||||
return (NULL); | return (NULL); | ||||
} | } | ||||
dmar_pte_store(&ptep->pte, DMAR_PTE_R | DMAR_PTE_W | | dmar_pte_store(&ptep->pte, DMAR_PTE_R | DMAR_PTE_W | | ||||
VM_PAGE_TO_PHYS(m)); | VM_PAGE_TO_PHYS(m)); | ||||
dmar_flush_pte_to_ram(domain->dmar, ptep); | dmar_flush_pte_to_ram(domain->dmar, ptep); | ||||
sf_buf_page(sfp)->wire_count += 1; | sf_buf_page(sfp)->ref_count += 1; | ||||
m->wire_count--; | m->ref_count--; | ||||
dmar_unmap_pgtbl(sfp); | dmar_unmap_pgtbl(sfp); | ||||
/* Only executed once. */ | /* Only executed once. */ | ||||
goto retry; | goto retry; | ||||
} | } | ||||
} | } | ||||
pte += domain_pgtbl_pte_off(domain, base, lvl); | pte += domain_pgtbl_pte_off(domain, base, lvl); | ||||
return (pte); | return (pte); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 63 Lines • ▼ Show 20 Lines | if (pte == NULL) { | ||||
domain_unmap_buf_locked(domain, base1, base - base1, | domain_unmap_buf_locked(domain, base1, base - base1, | ||||
flags); | flags); | ||||
TD_PINNED_ASSERT; | TD_PINNED_ASSERT; | ||||
return (ENOMEM); | return (ENOMEM); | ||||
} | } | ||||
dmar_pte_store(&pte->pte, VM_PAGE_TO_PHYS(ma[pi]) | pflags | | dmar_pte_store(&pte->pte, VM_PAGE_TO_PHYS(ma[pi]) | pflags | | ||||
(superpage ? DMAR_PTE_SP : 0)); | (superpage ? DMAR_PTE_SP : 0)); | ||||
dmar_flush_pte_to_ram(domain->dmar, pte); | dmar_flush_pte_to_ram(domain->dmar, pte); | ||||
sf_buf_page(sf)->wire_count += 1; | sf_buf_page(sf)->ref_count += 1; | ||||
} | } | ||||
if (sf != NULL) | if (sf != NULL) | ||||
dmar_unmap_pgtbl(sf); | dmar_unmap_pgtbl(sf); | ||||
TD_PINNED_ASSERT; | TD_PINNED_ASSERT; | ||||
return (0); | return (0); | ||||
} | } | ||||
int | int | ||||
▲ Show 20 Lines • Show All 81 Lines • ▼ Show 20 Lines | domain_unmap_clear_pte(struct dmar_domain *domain, dmar_gaddr_t base, int lvl, | ||||
dmar_pte_clear(&pte->pte); | dmar_pte_clear(&pte->pte); | ||||
dmar_flush_pte_to_ram(domain->dmar, pte); | dmar_flush_pte_to_ram(domain->dmar, pte); | ||||
m = sf_buf_page(*sf); | m = sf_buf_page(*sf); | ||||
if (free_sf) { | if (free_sf) { | ||||
dmar_unmap_pgtbl(*sf); | dmar_unmap_pgtbl(*sf); | ||||
*sf = NULL; | *sf = NULL; | ||||
} | } | ||||
m->wire_count--; | m->ref_count--; | ||||
if (m->wire_count != 0) | if (m->ref_count != 0) | ||||
return; | return; | ||||
KASSERT(lvl != 0, | KASSERT(lvl != 0, | ||||
("lost reference (lvl) on root pg domain %p base %jx lvl %d", | ("lost reference (lvl) on root pg domain %p base %jx lvl %d", | ||||
domain, (uintmax_t)base, lvl)); | domain, (uintmax_t)base, lvl)); | ||||
KASSERT(m->pindex != 0, | KASSERT(m->pindex != 0, | ||||
("lost reference (idx) on root pg domain %p base %jx lvl %d", | ("lost reference (idx) on root pg domain %p base %jx lvl %d", | ||||
domain, (uintmax_t)base, lvl)); | domain, (uintmax_t)base, lvl)); | ||||
dmar_pgfree(domain->pgtbl_obj, m->pindex, flags); | dmar_pgfree(domain->pgtbl_obj, m->pindex, flags); | ||||
▲ Show 20 Lines • Show All 96 Lines • ▼ Show 20 Lines | KASSERT(domain->pgtbl_obj == NULL, | ||||
("already initialized %p", domain)); | ("already initialized %p", domain)); | ||||
domain->pgtbl_obj = vm_pager_allocate(OBJT_PHYS, NULL, | domain->pgtbl_obj = vm_pager_allocate(OBJT_PHYS, NULL, | ||||
IDX_TO_OFF(pglvl_max_pages(domain->pglvl)), 0, 0, NULL); | IDX_TO_OFF(pglvl_max_pages(domain->pglvl)), 0, 0, NULL); | ||||
DMAR_DOMAIN_PGLOCK(domain); | DMAR_DOMAIN_PGLOCK(domain); | ||||
m = dmar_pgalloc(domain->pgtbl_obj, 0, DMAR_PGF_WAITOK | | m = dmar_pgalloc(domain->pgtbl_obj, 0, DMAR_PGF_WAITOK | | ||||
DMAR_PGF_ZERO | DMAR_PGF_OBJL); | DMAR_PGF_ZERO | DMAR_PGF_OBJL); | ||||
/* No implicit free of the top level page table page. */ | /* No implicit free of the top level page table page. */ | ||||
m->wire_count = 1; | m->ref_count = 1; | ||||
DMAR_DOMAIN_PGUNLOCK(domain); | DMAR_DOMAIN_PGUNLOCK(domain); | ||||
DMAR_LOCK(domain->dmar); | DMAR_LOCK(domain->dmar); | ||||
domain->flags |= DMAR_DOMAIN_PGTBL_INITED; | domain->flags |= DMAR_DOMAIN_PGTBL_INITED; | ||||
DMAR_UNLOCK(domain->dmar); | DMAR_UNLOCK(domain->dmar); | ||||
return (0); | return (0); | ||||
} | } | ||||
void | void | ||||
Show All 13 Lines | domain_free_pgtbl(struct dmar_domain *domain) | ||||
domain->pgtbl_obj = NULL; | domain->pgtbl_obj = NULL; | ||||
if ((domain->flags & DMAR_DOMAIN_IDMAP) != 0) { | if ((domain->flags & DMAR_DOMAIN_IDMAP) != 0) { | ||||
put_idmap_pgtbl(obj); | put_idmap_pgtbl(obj); | ||||
domain->flags &= ~DMAR_DOMAIN_IDMAP; | domain->flags &= ~DMAR_DOMAIN_IDMAP; | ||||
return; | return; | ||||
} | } | ||||
/* Obliterate wire_counts */ | /* Obliterate ref_counts */ | ||||
VM_OBJECT_ASSERT_WLOCKED(obj); | VM_OBJECT_ASSERT_WLOCKED(obj); | ||||
for (m = vm_page_lookup(obj, 0); m != NULL; m = vm_page_next(m)) | for (m = vm_page_lookup(obj, 0); m != NULL; m = vm_page_next(m)) | ||||
m->wire_count = 0; | m->ref_count = 0; | ||||
VM_OBJECT_WUNLOCK(obj); | VM_OBJECT_WUNLOCK(obj); | ||||
vm_object_deallocate(obj); | vm_object_deallocate(obj); | ||||
} | } | ||||
static inline uint64_t | static inline uint64_t | ||||
domain_wait_iotlb_flush(struct dmar_unit *unit, uint64_t wt, int iro) | domain_wait_iotlb_flush(struct dmar_unit *unit, uint64_t wt, int iro) | ||||
{ | { | ||||
uint64_t iotlbr; | uint64_t iotlbr; | ||||
▲ Show 20 Lines • Show All 57 Lines • Show Last 20 Lines |