diff --git a/sys/amd64/amd64/pmap.c b/sys/amd64/amd64/pmap.c --- a/sys/amd64/amd64/pmap.c +++ b/sys/amd64/amd64/pmap.c @@ -9480,6 +9480,37 @@ MAPDEV_FLUSHCACHE)); } +/* + * Version of pmap_qenter intended to map device memory rather than real one. + * See pmap_qenter comments. + */ +void +pmap_qmapdev_attr(vm_offset_t sva, vm_pindex_t *pi, int count, + vm_memattr_t mode) +{ + pt_entry_t *endpte, oldpte, pa, *pte; + vm_pindex_t p; + int cache_bits; + + oldpte = 0; + pte = vtopte(sva); + endpte = pte + count; + cache_bits = pmap_cache_bits(kernel_pmap, mode, false); + while (pte < endpte) { + p = *pi++; + pa = IDX_TO_OFF(p) | cache_bits; + if ((*pte & (PG_FRAME | X86_PG_PTE_CACHE)) != pa) { + oldpte |= *pte; + pte_store(pte, pa | pg_g | pg_nx | X86_PG_A | + X86_PG_M | X86_PG_RW | X86_PG_V); + } + pte++; + } + if (__predict_false((oldpte & X86_PG_V) != 0)) + pmap_invalidate_range(kernel_pmap, sva, sva + count * + PAGE_SIZE); +} + void pmap_unmapdev(void *p, vm_size_t size) { diff --git a/sys/amd64/include/pmap.h b/sys/amd64/include/pmap.h --- a/sys/amd64/include/pmap.h +++ b/sys/amd64/include/pmap.h @@ -409,6 +409,7 @@ void *pmap_mapdev(vm_paddr_t, vm_size_t); void *pmap_mapdev_attr(vm_paddr_t, vm_size_t, int); void *pmap_mapdev_pciecfg(vm_paddr_t pa, vm_size_t size); +void pmap_qmapdev_attr(vm_offset_t, vm_pindex_t *, int, vm_memattr_t); bool pmap_not_in_di(void); bool pmap_page_is_mapped(vm_page_t m); void pmap_page_set_memattr(vm_page_t m, vm_memattr_t ma);