Index: head/sys/amd64/amd64/pmap.c =================================================================== --- head/sys/amd64/amd64/pmap.c +++ head/sys/amd64/amd64/pmap.c @@ -637,7 +637,8 @@ static pv_entry_t pmap_pvh_remove(struct md_page *pvh, pmap_t pmap, vm_offset_t va); -static int pmap_change_attr_locked(vm_offset_t va, vm_size_t size, int mode); +static int pmap_change_attr_locked(vm_offset_t va, vm_size_t size, int mode, + bool noflush); static boolean_t pmap_demote_pde(pmap_t pmap, pd_entry_t *pde, vm_offset_t va); static boolean_t pmap_demote_pde_locked(pmap_t pmap, pd_entry_t *pde, vm_offset_t va, struct rwlock **lockp); @@ -7098,8 +7099,8 @@ * routine is intended to be used for mapping device memory, * NOT real memory. */ -void * -pmap_mapdev_attr(vm_paddr_t pa, vm_size_t size, int mode) +static void * +pmap_mapdev_internal(vm_paddr_t pa, vm_size_t size, int mode, bool noflush) { struct pmap_preinit_mapping *ppim; vm_offset_t va, offset; @@ -7142,7 +7143,10 @@ */ if (pa < dmaplimit && pa + size <= dmaplimit) { va = PHYS_TO_DMAP(pa); - if (!pmap_change_attr(va, size, mode)) + PMAP_LOCK(kernel_pmap); + i = pmap_change_attr_locked(va, size, mode, noflush); + PMAP_UNLOCK(kernel_pmap); + if (!i) return ((void *)(va + offset)); } va = kva_alloc(size); @@ -7152,22 +7156,37 @@ for (tmpsize = 0; tmpsize < size; tmpsize += PAGE_SIZE) pmap_kenter_attr(va + tmpsize, pa + tmpsize, mode); pmap_invalidate_range(kernel_pmap, va, va + tmpsize); - pmap_invalidate_cache_range(va, va + tmpsize); + if (!noflush) + pmap_invalidate_cache_range(va, va + tmpsize); return ((void *)(va + offset)); } void * +pmap_mapdev_attr(vm_paddr_t pa, vm_size_t size, int mode) +{ + + return (pmap_mapdev_internal(pa, size, mode, false)); +} + +void * pmap_mapdev(vm_paddr_t pa, vm_size_t size) { - return (pmap_mapdev_attr(pa, size, PAT_UNCACHEABLE)); + return (pmap_mapdev_internal(pa, size, PAT_UNCACHEABLE, false)); } void * +pmap_mapdev_pciecfg(vm_paddr_t pa, vm_size_t size) +{ + + return (pmap_mapdev_internal(pa, size, PAT_UNCACHEABLE, true)); +} + +void * pmap_mapbios(vm_paddr_t pa, vm_size_t size) { - return (pmap_mapdev_attr(pa, size, PAT_WRITE_BACK)); + return (pmap_mapdev_internal(pa, size, PAT_WRITE_BACK, false)); } void @@ -7306,13 +7325,13 @@ int error; PMAP_LOCK(kernel_pmap); - error = pmap_change_attr_locked(va, size, mode); + error = pmap_change_attr_locked(va, size, mode, false); PMAP_UNLOCK(kernel_pmap); return (error); } static int -pmap_change_attr_locked(vm_offset_t va, vm_size_t size, int mode) +pmap_change_attr_locked(vm_offset_t va, vm_size_t size, int mode, bool noflush) { vm_offset_t base, offset, tmpva; vm_paddr_t pa_start, pa_end, pa_end1; @@ -7429,7 +7448,7 @@ /* Run ended, update direct map. */ error = pmap_change_attr_locked( PHYS_TO_DMAP(pa_start), - pa_end - pa_start, mode); + pa_end - pa_start, mode, noflush); if (error != 0) break; /* Start physical address run. */ @@ -7459,7 +7478,7 @@ /* Run ended, update direct map. */ error = pmap_change_attr_locked( PHYS_TO_DMAP(pa_start), - pa_end - pa_start, mode); + pa_end - pa_start, mode, noflush); if (error != 0) break; /* Start physical address run. */ @@ -7487,7 +7506,7 @@ /* Run ended, update direct map. */ error = pmap_change_attr_locked( PHYS_TO_DMAP(pa_start), - pa_end - pa_start, mode); + pa_end - pa_start, mode, noflush); if (error != 0) break; /* Start physical address run. */ @@ -7502,7 +7521,7 @@ pa_end1 = MIN(pa_end, dmaplimit); if (pa_start != pa_end1) error = pmap_change_attr_locked(PHYS_TO_DMAP(pa_start), - pa_end1 - pa_start, mode); + pa_end1 - pa_start, mode, noflush); } /* @@ -7511,7 +7530,8 @@ */ if (changed) { pmap_invalidate_range(kernel_pmap, base, tmpva); - pmap_invalidate_cache_range(base, tmpva); + if (!noflush) + pmap_invalidate_cache_range(base, tmpva); } return (error); } Index: head/sys/amd64/include/pmap.h =================================================================== --- head/sys/amd64/include/pmap.h +++ head/sys/amd64/include/pmap.h @@ -430,6 +430,7 @@ void *pmap_mapbios(vm_paddr_t, vm_size_t); 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); boolean_t pmap_page_is_mapped(vm_page_t m); void pmap_page_set_memattr(vm_page_t m, vm_memattr_t ma); void pmap_pinit_pml4(vm_page_t); Index: head/sys/amd64/pci/pci_cfgreg.c =================================================================== --- head/sys/amd64/pci/pci_cfgreg.c +++ head/sys/amd64/pci/pci_cfgreg.c @@ -271,7 +271,7 @@ base); /* XXX: We should make sure this really fits into the direct map. */ - pcie_base = (vm_offset_t)pmap_mapdev(base, (maxbus + 1) << 20); + pcie_base = (vm_offset_t)pmap_mapdev_pciecfg(base, (maxbus + 1) << 20); pcie_minbus = minbus; pcie_maxbus = maxbus; cfgmech = CFGMECH_PCIE;