Changeset View
Changeset View
Standalone View
Standalone View
head/sys/x86/iommu/intel_idpgtbl.c
Show First 20 Lines • Show All 493 Lines • ▼ Show 20 Lines | domain_map_buf_locked(struct dmar_domain *domain, iommu_gaddr_t base, | ||||
} | } | ||||
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 | ||||
domain_map_buf(struct dmar_domain *domain, iommu_gaddr_t base, iommu_gaddr_t size, | domain_map_buf(struct iommu_domain *iodom, iommu_gaddr_t base, | ||||
vm_page_t *ma, uint64_t pflags, int flags) | iommu_gaddr_t size, vm_page_t *ma, uint64_t eflags, int flags) | ||||
{ | { | ||||
struct dmar_domain *domain; | |||||
struct dmar_unit *unit; | struct dmar_unit *unit; | ||||
uint64_t pflags; | |||||
int error; | int error; | ||||
pflags = ((eflags & IOMMU_MAP_ENTRY_READ) != 0 ? DMAR_PTE_R : 0) | | |||||
((eflags & IOMMU_MAP_ENTRY_WRITE) != 0 ? DMAR_PTE_W : 0) | | |||||
((eflags & IOMMU_MAP_ENTRY_SNOOP) != 0 ? DMAR_PTE_SNP : 0) | | |||||
((eflags & IOMMU_MAP_ENTRY_TM) != 0 ? DMAR_PTE_TM : 0); | |||||
domain = (struct dmar_domain *)iodom; | |||||
unit = domain->dmar; | unit = domain->dmar; | ||||
KASSERT((domain->flags & DMAR_DOMAIN_IDMAP) == 0, | KASSERT((domain->iodom.flags & DMAR_DOMAIN_IDMAP) == 0, | ||||
("modifying idmap pagetable domain %p", domain)); | ("modifying idmap pagetable domain %p", domain)); | ||||
KASSERT((base & DMAR_PAGE_MASK) == 0, | KASSERT((base & DMAR_PAGE_MASK) == 0, | ||||
("non-aligned base %p %jx %jx", domain, (uintmax_t)base, | ("non-aligned base %p %jx %jx", domain, (uintmax_t)base, | ||||
(uintmax_t)size)); | (uintmax_t)size)); | ||||
KASSERT((size & DMAR_PAGE_MASK) == 0, | KASSERT((size & DMAR_PAGE_MASK) == 0, | ||||
("non-aligned size %p %jx %jx", domain, (uintmax_t)base, | ("non-aligned size %p %jx %jx", domain, (uintmax_t)base, | ||||
(uintmax_t)size)); | (uintmax_t)size)); | ||||
KASSERT(size > 0, ("zero size %p %jx %jx", domain, (uintmax_t)base, | KASSERT(size > 0, ("zero size %p %jx %jx", domain, (uintmax_t)base, | ||||
▲ Show 20 Lines • Show All 94 Lines • ▼ Show 20 Lines | domain_unmap_buf_locked(struct dmar_domain *domain, iommu_gaddr_t base, | ||||
vm_pindex_t idx; | vm_pindex_t idx; | ||||
iommu_gaddr_t pg_sz; | iommu_gaddr_t pg_sz; | ||||
int lvl; | int lvl; | ||||
DMAR_DOMAIN_ASSERT_PGLOCKED(domain); | DMAR_DOMAIN_ASSERT_PGLOCKED(domain); | ||||
if (size == 0) | if (size == 0) | ||||
return (0); | return (0); | ||||
KASSERT((domain->flags & DMAR_DOMAIN_IDMAP) == 0, | KASSERT((domain->iodom.flags & DMAR_DOMAIN_IDMAP) == 0, | ||||
("modifying idmap pagetable domain %p", domain)); | ("modifying idmap pagetable domain %p", domain)); | ||||
KASSERT((base & DMAR_PAGE_MASK) == 0, | KASSERT((base & DMAR_PAGE_MASK) == 0, | ||||
("non-aligned base %p %jx %jx", domain, (uintmax_t)base, | ("non-aligned base %p %jx %jx", domain, (uintmax_t)base, | ||||
(uintmax_t)size)); | (uintmax_t)size)); | ||||
KASSERT((size & DMAR_PAGE_MASK) == 0, | KASSERT((size & DMAR_PAGE_MASK) == 0, | ||||
("non-aligned size %p %jx %jx", domain, (uintmax_t)base, | ("non-aligned size %p %jx %jx", domain, (uintmax_t)base, | ||||
(uintmax_t)size)); | (uintmax_t)size)); | ||||
KASSERT(base < (1ULL << domain->agaw), | KASSERT(base < (1ULL << domain->agaw), | ||||
▲ Show 20 Lines • Show All 70 Lines • ▼ Show 20 Lines | 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->ref_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->iodom.flags |= DMAR_DOMAIN_PGTBL_INITED; | ||||
DMAR_UNLOCK(domain->dmar); | DMAR_UNLOCK(domain->dmar); | ||||
return (0); | return (0); | ||||
} | } | ||||
void | void | ||||
domain_free_pgtbl(struct dmar_domain *domain) | domain_free_pgtbl(struct dmar_domain *domain) | ||||
{ | { | ||||
vm_object_t obj; | vm_object_t obj; | ||||
vm_page_t m; | vm_page_t m; | ||||
obj = domain->pgtbl_obj; | obj = domain->pgtbl_obj; | ||||
if (obj == NULL) { | if (obj == NULL) { | ||||
KASSERT((domain->dmar->hw_ecap & DMAR_ECAP_PT) != 0 && | KASSERT((domain->dmar->hw_ecap & DMAR_ECAP_PT) != 0 && | ||||
(domain->flags & DMAR_DOMAIN_IDMAP) != 0, | (domain->iodom.flags & DMAR_DOMAIN_IDMAP) != 0, | ||||
("lost pagetable object domain %p", domain)); | ("lost pagetable object domain %p", domain)); | ||||
return; | return; | ||||
} | } | ||||
DMAR_DOMAIN_ASSERT_PGLOCKED(domain); | DMAR_DOMAIN_ASSERT_PGLOCKED(domain); | ||||
domain->pgtbl_obj = NULL; | domain->pgtbl_obj = NULL; | ||||
if ((domain->flags & DMAR_DOMAIN_IDMAP) != 0) { | if ((domain->iodom.flags & DMAR_DOMAIN_IDMAP) != 0) { | ||||
put_idmap_pgtbl(obj); | put_idmap_pgtbl(obj); | ||||
domain->flags &= ~DMAR_DOMAIN_IDMAP; | domain->iodom.flags &= ~DMAR_DOMAIN_IDMAP; | ||||
return; | return; | ||||
} | } | ||||
/* Obliterate ref_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->ref_count = 0; | m->ref_count = 0; | ||||
VM_OBJECT_WUNLOCK(obj); | VM_OBJECT_WUNLOCK(obj); | ||||
▲ Show 20 Lines • Show All 64 Lines • Show Last 20 Lines |