diff --git a/sys/amd64/amd64/pmap.c b/sys/amd64/amd64/pmap.c index 5bf8b890e103..fce2818759b1 100644 --- a/sys/amd64/amd64/pmap.c +++ b/sys/amd64/amd64/pmap.c @@ -614,6 +614,7 @@ pmap_page_init(vm_page_t m) { TAILQ_INIT(&m->md.pv_list); + m->md.pat_mode = PAT_WRITE_BACK; } /* @@ -1120,7 +1121,8 @@ pmap_qenter(vm_offset_t sva, vm_page_t *ma, int count) endpte = pte + count; while (pte < endpte) { oldpte |= *pte; - pte_store(pte, VM_PAGE_TO_PHYS(*ma) | PG_G | PG_RW | PG_V); + pte_store(pte, VM_PAGE_TO_PHYS(*ma) | PG_G | + pmap_cache_bits((*ma)->md.pat_mode, 0) | PG_RW | PG_V); pte++; ma++; } @@ -3025,7 +3027,7 @@ pmap_enter(pmap_t pmap, vm_offset_t va, vm_prot_t access, vm_page_t m, /* * Now validate mapping with desired protection/wiring. */ - newpte = (pt_entry_t)(pa | PG_V); + newpte = (pt_entry_t)(pa | pmap_cache_bits(m->md.pat_mode, 0) | PG_V); if ((prot & VM_PROT_WRITE) != 0) { newpte |= PG_RW; vm_page_flag_set(m, PG_WRITEABLE); @@ -3110,7 +3112,8 @@ pmap_enter_pde(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot) " in pmap %p", va, pmap); return (FALSE); } - newpde = VM_PAGE_TO_PHYS(m) | PG_PS | PG_V; + newpde = VM_PAGE_TO_PHYS(m) | pmap_cache_bits(m->md.pat_mode, 1) | + PG_PS | PG_V; if ((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0) { newpde |= PG_MANAGED; @@ -3292,7 +3295,7 @@ pmap_enter_quick_locked(pmap_t pmap, vm_offset_t va, vm_page_t m, */ pmap->pm_stats.resident_count++; - pa = VM_PAGE_TO_PHYS(m); + pa = VM_PAGE_TO_PHYS(m) | pmap_cache_bits(m->md.pat_mode, 0); if ((prot & VM_PROT_EXECUTE) == 0) pa |= pg_nx; @@ -3333,6 +3336,7 @@ pmap_object_init_pt(pmap_t pmap, vm_offset_t addr, vm_object_t object, pd_entry_t *pde; vm_paddr_t pa, ptepa; vm_page_t p, pdpg; + int pat_mode; VM_OBJECT_LOCK_ASSERT(object, MA_OWNED); KASSERT(object->type == OBJT_DEVICE, @@ -3343,6 +3347,7 @@ pmap_object_init_pt(pmap_t pmap, vm_offset_t addr, vm_object_t object, p = vm_page_lookup(object, pindex); KASSERT(p->valid == VM_PAGE_BITS_ALL, ("pmap_object_init_pt: invalid page %p", p)); + pat_mode = p->md.pat_mode; /* * Abort the mapping if the first page is not physically @@ -3354,21 +3359,28 @@ pmap_object_init_pt(pmap_t pmap, vm_offset_t addr, vm_object_t object, /* * Skip the first page. Abort the mapping if the rest of - * the pages are not physically contiguous. + * the pages are not physically contiguous or have differing + * memory attributes. */ p = TAILQ_NEXT(p, listq); for (pa = ptepa + PAGE_SIZE; pa < ptepa + size; pa += PAGE_SIZE) { KASSERT(p->valid == VM_PAGE_BITS_ALL, ("pmap_object_init_pt: invalid page %p", p)); - if (pa != VM_PAGE_TO_PHYS(p)) + if (pa != VM_PAGE_TO_PHYS(p) || + pat_mode != p->md.pat_mode) return; p = TAILQ_NEXT(p, listq); } - /* Map using 2MB pages. */ + /* + * Map using 2MB pages. Since "ptepa" is 2M aligned and + * "size" is a multiple of 2M, adding the PAT setting to "pa" + * will not affect the termination of this loop. + */ PMAP_LOCK(pmap); - for (pa = ptepa; pa < ptepa + size; pa += NBPDR) { + for (pa = ptepa | pmap_cache_bits(pat_mode, 1); pa < ptepa + + size; pa += NBPDR) { pdpg = pmap_allocpde(pmap, addr, M_NOWAIT); if (pdpg == NULL) { /* @@ -4372,6 +4384,23 @@ pmap_demote_pdpe(pmap_t pmap, pdp_entry_t *pdpe, vm_offset_t va) return (TRUE); } +/* + * Sets the memory attribute for the specified page. + */ +void +pmap_page_set_memattr(vm_page_t m, vm_memattr_t ma) +{ + + m->md.pat_mode = ma; + + /* + * Update the direct mapping and flush the cache. + */ + if (pmap_change_attr(PHYS_TO_DMAP(VM_PAGE_TO_PHYS(m)), PAGE_SIZE, + m->md.pat_mode)) + panic("memory attribute change on the direct map failed"); +} + /* * Changes the specified virtual address range's memory type to that given by * the parameter "mode". The specified virtual address range must be diff --git a/sys/amd64/include/pmap.h b/sys/amd64/include/pmap.h index b428a5273219..11a5628082f4 100644 --- a/sys/amd64/include/pmap.h +++ b/sys/amd64/include/pmap.h @@ -233,6 +233,7 @@ struct pv_chunk; struct md_page { TAILQ_HEAD(,pv_entry) pv_list; + int pat_mode; }; /* @@ -299,6 +300,7 @@ extern vm_paddr_t dump_avail[]; extern vm_offset_t virtual_avail; extern vm_offset_t virtual_end; +#define pmap_page_get_memattr(m) ((vm_memattr_t)(m)->md.pat_mode) #define pmap_unmapbios(va, sz) pmap_unmapdev((va), (sz)) void pmap_bootstrap(vm_paddr_t *); @@ -312,6 +314,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); 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_unmapdev(vm_offset_t, vm_size_t); void pmap_invalidate_page(pmap_t, vm_offset_t); void pmap_invalidate_range(pmap_t, vm_offset_t, vm_offset_t); diff --git a/sys/amd64/include/vm.h b/sys/amd64/include/vm.h index 4796dbc4cacc..4065a3605077 100644 --- a/sys/amd64/include/vm.h +++ b/sys/amd64/include/vm.h @@ -32,14 +32,14 @@ #include -/* Cache control options. */ -#define VM_CACHE_UNCACHEABLE ((vm_cache_mode_t)PAT_UNCACHEABLE) -#define VM_CACHE_WRITE_COMBINING ((vm_cache_mode_t)PAT_WRITE_COMBINING) -#define VM_CACHE_WRITE_THROUGH ((vm_cache_mode_t)PAT_WRITE_THROUGH) -#define VM_CACHE_WRITE_PROTECTED ((vm_cache_mode_t)PAT_WRITE_PROTECTED) -#define VM_CACHE_WRITE_BACK ((vm_cache_mode_t)PAT_WRITE_BACK) -#define VM_CACHE_UNCACHED ((vm_cache_mode_t)PAT_UNCACHED) +/* Memory attributes. */ +#define VM_MEMATTR_UNCACHEABLE ((vm_memattr_t)PAT_UNCACHEABLE) +#define VM_MEMATTR_WRITE_COMBINING ((vm_memattr_t)PAT_WRITE_COMBINING) +#define VM_MEMATTR_WRITE_THROUGH ((vm_memattr_t)PAT_WRITE_THROUGH) +#define VM_MEMATTR_WRITE_PROTECTED ((vm_memattr_t)PAT_WRITE_PROTECTED) +#define VM_MEMATTR_WRITE_BACK ((vm_memattr_t)PAT_WRITE_BACK) +#define VM_MEMATTR_UNCACHED ((vm_memattr_t)PAT_UNCACHED) -#define VM_CACHE_DEFAULT VM_CACHE_WRITE_BACK +#define VM_MEMATTR_DEFAULT VM_MEMATTR_WRITE_BACK #endif /* !_MACHINE_VM_H_ */ diff --git a/sys/arm/include/pmap.h b/sys/arm/include/pmap.h index 6cda62b40f7d..8ee7bac27e23 100644 --- a/sys/arm/include/pmap.h +++ b/sys/arm/include/pmap.h @@ -75,7 +75,10 @@ #endif +#define pmap_page_get_memattr(m) VM_MEMATTR_DEFAULT #define pmap_page_is_mapped(m) (!TAILQ_EMPTY(&(m)->md.pv_list)) +#define pmap_page_set_memattr(m, ma) (void)0 + /* * Pmap stuff */ diff --git a/sys/arm/include/vm.h b/sys/arm/include/vm.h index 8effe7861e82..7ec2d9e692a9 100644 --- a/sys/arm/include/vm.h +++ b/sys/arm/include/vm.h @@ -29,7 +29,7 @@ #ifndef _MACHINE_VM_H_ #define _MACHINE_VM_H_ -/* Cache control is not (yet) implemented. */ -#define VM_CACHE_DEFAULT 0 +/* Memory attribute configuration is not (yet) implemented. */ +#define VM_MEMATTR_DEFAULT 0 #endif /* !_MACHINE_VM_H_ */ diff --git a/sys/i386/i386/pmap.c b/sys/i386/i386/pmap.c index d16632ae3377..adcbd8385d7e 100644 --- a/sys/i386/i386/pmap.c +++ b/sys/i386/i386/pmap.c @@ -559,6 +559,7 @@ pmap_page_init(vm_page_t m) { TAILQ_INIT(&m->md.pv_list); + m->md.pat_mode = PAT_WRITE_BACK; } #ifdef PAE @@ -569,7 +570,7 @@ pmap_pdpt_allocf(uma_zone_t zone, int bytes, u_int8_t *flags, int wait) /* Inform UMA that this allocator uses kernel_map/object. */ *flags = UMA_SLAB_KERNEL; return ((void *)kmem_alloc_contig(kernel_map, bytes, wait, 0x0ULL, - 0xffffffffULL, 1, 0, VM_CACHE_DEFAULT)); + 0xffffffffULL, 1, 0, VM_MEMATTR_DEFAULT)); } #endif @@ -1210,7 +1211,8 @@ pmap_qenter(vm_offset_t sva, vm_page_t *ma, int count) endpte = pte + count; while (pte < endpte) { oldpte |= *pte; - pte_store(pte, VM_PAGE_TO_PHYS(*ma) | pgeflag | PG_RW | PG_V); + pte_store(pte, VM_PAGE_TO_PHYS(*ma) | pgeflag | + pmap_cache_bits((*ma)->md.pat_mode, 0) | PG_RW | PG_V); pte++; ma++; } @@ -3132,7 +3134,7 @@ pmap_enter(pmap_t pmap, vm_offset_t va, vm_prot_t access, vm_page_t m, /* * Now validate mapping with desired protection/wiring. */ - newpte = (pt_entry_t)(pa | PG_V); + newpte = (pt_entry_t)(pa | pmap_cache_bits(m->md.pat_mode, 0) | PG_V); if ((prot & VM_PROT_WRITE) != 0) { newpte |= PG_RW; vm_page_flag_set(m, PG_WRITEABLE); @@ -3214,7 +3216,8 @@ pmap_enter_pde(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot) " in pmap %p", va, pmap); return (FALSE); } - newpde = VM_PAGE_TO_PHYS(m) | PG_PS | PG_V; + newpde = VM_PAGE_TO_PHYS(m) | pmap_cache_bits(m->md.pat_mode, 1) | + PG_PS | PG_V; if ((m->flags & (PG_FICTITIOUS | PG_UNMANAGED)) == 0) { newpde |= PG_MANAGED; @@ -3399,7 +3402,7 @@ pmap_enter_quick_locked(pmap_t pmap, vm_offset_t va, vm_page_t m, */ pmap->pm_stats.resident_count++; - pa = VM_PAGE_TO_PHYS(m); + pa = VM_PAGE_TO_PHYS(m) | pmap_cache_bits(m->md.pat_mode, 0); #ifdef PAE if ((prot & VM_PROT_EXECUTE) == 0) pa |= pg_nx; @@ -3442,6 +3445,7 @@ pmap_object_init_pt(pmap_t pmap, vm_offset_t addr, vm_object_t object, pd_entry_t *pde; vm_paddr_t pa, ptepa; vm_page_t p; + int pat_mode; VM_OBJECT_LOCK_ASSERT(object, MA_OWNED); KASSERT(object->type == OBJT_DEVICE, @@ -3453,6 +3457,7 @@ pmap_object_init_pt(pmap_t pmap, vm_offset_t addr, vm_object_t object, p = vm_page_lookup(object, pindex); KASSERT(p->valid == VM_PAGE_BITS_ALL, ("pmap_object_init_pt: invalid page %p", p)); + pat_mode = p->md.pat_mode; /* * Abort the mapping if the first page is not physically @@ -3464,21 +3469,28 @@ pmap_object_init_pt(pmap_t pmap, vm_offset_t addr, vm_object_t object, /* * Skip the first page. Abort the mapping if the rest of - * the pages are not physically contiguous. + * the pages are not physically contiguous or have differing + * memory attributes. */ p = TAILQ_NEXT(p, listq); for (pa = ptepa + PAGE_SIZE; pa < ptepa + size; pa += PAGE_SIZE) { KASSERT(p->valid == VM_PAGE_BITS_ALL, ("pmap_object_init_pt: invalid page %p", p)); - if (pa != VM_PAGE_TO_PHYS(p)) + if (pa != VM_PAGE_TO_PHYS(p) || + pat_mode != p->md.pat_mode) return; p = TAILQ_NEXT(p, listq); } - /* Map using 2/4MB pages. */ + /* + * Map using 2/4MB pages. Since "ptepa" is 2/4M aligned and + * "size" is a multiple of 2/4M, adding the PAT setting to + * "pa" will not affect the termination of this loop. + */ PMAP_LOCK(pmap); - for (pa = ptepa; pa < ptepa + size; pa += NBPDR) { + for (pa = ptepa | pmap_cache_bits(pat_mode, 1); pa < ptepa + + size; pa += NBPDR) { pde = pmap_pde(pmap, addr); if (*pde == 0) { pde_store(pde, pa | PG_PS | PG_M | PG_A | @@ -3696,7 +3708,8 @@ pmap_zero_page(vm_page_t m) if (*sysmaps->CMAP2) panic("pmap_zero_page: CMAP2 busy"); sched_pin(); - *sysmaps->CMAP2 = PG_V | PG_RW | VM_PAGE_TO_PHYS(m) | PG_A | PG_M; + *sysmaps->CMAP2 = PG_V | PG_RW | VM_PAGE_TO_PHYS(m) | PG_A | PG_M | + pmap_cache_bits(m->md.pat_mode, 0); invlcaddr(sysmaps->CADDR2); pagezero(sysmaps->CADDR2); *sysmaps->CMAP2 = 0; @@ -3718,9 +3731,10 @@ pmap_zero_page_area(vm_page_t m, int off, int size) sysmaps = &sysmaps_pcpu[PCPU_GET(cpuid)]; mtx_lock(&sysmaps->lock); if (*sysmaps->CMAP2) - panic("pmap_zero_page: CMAP2 busy"); + panic("pmap_zero_page_area: CMAP2 busy"); sched_pin(); - *sysmaps->CMAP2 = PG_V | PG_RW | VM_PAGE_TO_PHYS(m) | PG_A | PG_M; + *sysmaps->CMAP2 = PG_V | PG_RW | VM_PAGE_TO_PHYS(m) | PG_A | PG_M | + pmap_cache_bits(m->md.pat_mode, 0); invlcaddr(sysmaps->CADDR2); if (off == 0 && size == PAGE_SIZE) pagezero(sysmaps->CADDR2); @@ -3742,9 +3756,10 @@ pmap_zero_page_idle(vm_page_t m) { if (*CMAP3) - panic("pmap_zero_page: CMAP3 busy"); + panic("pmap_zero_page_idle: CMAP3 busy"); sched_pin(); - *CMAP3 = PG_V | PG_RW | VM_PAGE_TO_PHYS(m) | PG_A | PG_M; + *CMAP3 = PG_V | PG_RW | VM_PAGE_TO_PHYS(m) | PG_A | PG_M | + pmap_cache_bits(m->md.pat_mode, 0); invlcaddr(CADDR3); pagezero(CADDR3); *CMAP3 = 0; @@ -3771,8 +3786,10 @@ pmap_copy_page(vm_page_t src, vm_page_t dst) sched_pin(); invlpg((u_int)sysmaps->CADDR1); invlpg((u_int)sysmaps->CADDR2); - *sysmaps->CMAP1 = PG_V | VM_PAGE_TO_PHYS(src) | PG_A; - *sysmaps->CMAP2 = PG_V | PG_RW | VM_PAGE_TO_PHYS(dst) | PG_A | PG_M; + *sysmaps->CMAP1 = PG_V | VM_PAGE_TO_PHYS(src) | PG_A | + pmap_cache_bits(src->md.pat_mode, 0); + *sysmaps->CMAP2 = PG_V | PG_RW | VM_PAGE_TO_PHYS(dst) | PG_A | PG_M | + pmap_cache_bits(dst->md.pat_mode, 0); bcopy(sysmaps->CADDR1, sysmaps->CADDR2, PAGE_SIZE); *sysmaps->CMAP1 = 0; *sysmaps->CMAP2 = 0; @@ -4437,6 +4454,22 @@ pmap_unmapdev(vm_offset_t va, vm_size_t size) kmem_free(kernel_map, base, size); } +/* + * Sets the memory attribute for the specified page. + */ +void +pmap_page_set_memattr(vm_page_t m, vm_memattr_t ma) +{ + + m->md.pat_mode = ma; + + /* + * Flush CPU caches to make sure any data isn't cached that shouldn't + * be, etc. + */ + pmap_invalidate_cache(); +} + int pmap_change_attr(vm_offset_t va, vm_size_t size, int mode) { diff --git a/sys/i386/include/pmap.h b/sys/i386/include/pmap.h index d19c3a9ff3ba..42c5d2e68e63 100644 --- a/sys/i386/include/pmap.h +++ b/sys/i386/include/pmap.h @@ -389,6 +389,7 @@ struct pv_chunk; struct md_page { TAILQ_HEAD(,pv_entry) pv_list; + int pat_mode; }; struct pmap { @@ -458,6 +459,7 @@ extern char *ptvmmap; /* poor name! */ extern vm_offset_t virtual_avail; extern vm_offset_t virtual_end; +#define pmap_page_get_memattr(m) ((vm_memattr_t)(m)->md.pat_mode) #define pmap_unmapbios(va, sz) pmap_unmapdev((va), (sz)) void pmap_bootstrap(vm_paddr_t); @@ -470,6 +472,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); 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_unmapdev(vm_offset_t, vm_size_t); pt_entry_t *pmap_pte(pmap_t, vm_offset_t) __pure2; void pmap_set_pg(void); diff --git a/sys/i386/include/vm.h b/sys/i386/include/vm.h index 4796dbc4cacc..4065a3605077 100644 --- a/sys/i386/include/vm.h +++ b/sys/i386/include/vm.h @@ -32,14 +32,14 @@ #include -/* Cache control options. */ -#define VM_CACHE_UNCACHEABLE ((vm_cache_mode_t)PAT_UNCACHEABLE) -#define VM_CACHE_WRITE_COMBINING ((vm_cache_mode_t)PAT_WRITE_COMBINING) -#define VM_CACHE_WRITE_THROUGH ((vm_cache_mode_t)PAT_WRITE_THROUGH) -#define VM_CACHE_WRITE_PROTECTED ((vm_cache_mode_t)PAT_WRITE_PROTECTED) -#define VM_CACHE_WRITE_BACK ((vm_cache_mode_t)PAT_WRITE_BACK) -#define VM_CACHE_UNCACHED ((vm_cache_mode_t)PAT_UNCACHED) +/* Memory attributes. */ +#define VM_MEMATTR_UNCACHEABLE ((vm_memattr_t)PAT_UNCACHEABLE) +#define VM_MEMATTR_WRITE_COMBINING ((vm_memattr_t)PAT_WRITE_COMBINING) +#define VM_MEMATTR_WRITE_THROUGH ((vm_memattr_t)PAT_WRITE_THROUGH) +#define VM_MEMATTR_WRITE_PROTECTED ((vm_memattr_t)PAT_WRITE_PROTECTED) +#define VM_MEMATTR_WRITE_BACK ((vm_memattr_t)PAT_WRITE_BACK) +#define VM_MEMATTR_UNCACHED ((vm_memattr_t)PAT_UNCACHED) -#define VM_CACHE_DEFAULT VM_CACHE_WRITE_BACK +#define VM_MEMATTR_DEFAULT VM_MEMATTR_WRITE_BACK #endif /* !_MACHINE_VM_H_ */ diff --git a/sys/i386/xen/pmap.c b/sys/i386/xen/pmap.c index ed4300fe3c6c..9a9a1b4e9a19 100644 --- a/sys/i386/xen/pmap.c +++ b/sys/i386/xen/pmap.c @@ -605,6 +605,7 @@ pmap_page_init(vm_page_t m) { TAILQ_INIT(&m->md.pv_list); + m->md.pat_mode = PAT_WRITE_BACK; } #if defined(PAE) && !defined(XEN) @@ -615,7 +616,7 @@ pmap_pdpt_allocf(uma_zone_t zone, int bytes, u_int8_t *flags, int wait) /* Inform UMA that this allocator uses kernel_map/object. */ *flags = UMA_SLAB_KERNEL; return ((void *)kmem_alloc_contig(kernel_map, bytes, wait, 0x0ULL, - 0xffffffffULL, 1, 0, VM_CACHE_DEFAULT)); + 0xffffffffULL, 1, 0, VM_MEMATTR_DEFAULT)); } #endif diff --git a/sys/ia64/include/pmap.h b/sys/ia64/include/pmap.h index 49ffe91ccaa9..c6b975477a7c 100644 --- a/sys/ia64/include/pmap.h +++ b/sys/ia64/include/pmap.h @@ -118,7 +118,9 @@ extern vm_offset_t virtual_end; extern uint64_t pmap_vhpt_base[]; extern int pmap_vhpt_log2size; +#define pmap_page_get_memattr(m) VM_MEMATTR_DEFAULT #define pmap_page_is_mapped(m) (!TAILQ_EMPTY(&(m)->md.pv_list)) +#define pmap_page_set_memattr(m, ma) (void)0 #define pmap_mapbios(pa, sz) pmap_mapdev(pa, sz) #define pmap_unmapbios(va, sz) pmap_unmapdev(va, sz) diff --git a/sys/ia64/include/vm.h b/sys/ia64/include/vm.h index bbc8a6ca14a8..717677159ec7 100644 --- a/sys/ia64/include/vm.h +++ b/sys/ia64/include/vm.h @@ -32,13 +32,13 @@ #include #include -/* Cache control options. */ -#define VM_CACHE_WRITE_BACK ((vm_cache_mode_t)PTE_MA_WB) -#define VM_CACHE_UNCACHEABLE ((vm_cache_mode_t)PTE_MA_UC) -#define VM_CACHE_UNCACHEABLE_EXPORTED ((vm_cache_mode_t)PTE_MA_UCE) -#define VM_CACHE_WRITE_COMBINING ((vm_cache_mode_t)PTE_MA_WC) -#define VM_CACHE_NATPAGE ((vm_cache_mode_t)PTE_MA_NATPAGE) +/* Memory attributes. */ +#define VM_MEMATTR_WRITE_BACK ((vm_memattr_t)PTE_MA_WB) +#define VM_MEMATTR_UNCACHEABLE ((vm_memattr_t)PTE_MA_UC) +#define VM_MEMATTR_UNCACHEABLE_EXPORTED ((vm_memattr_t)PTE_MA_UCE) +#define VM_MEMATTR_WRITE_COMBINING ((vm_memattr_t)PTE_MA_WC) +#define VM_MEMATTR_NATPAGE ((vm_memattr_t)PTE_MA_NATPAGE) -#define VM_CACHE_DEFAULT VM_CACHE_WRITE_BACK +#define VM_MEMATTR_DEFAULT VM_MEMATTR_WRITE_BACK #endif /* !_MACHINE_VM_H_ */ diff --git a/sys/kern/kern_mbuf.c b/sys/kern/kern_mbuf.c index f266fd5d3244..04cf1ff82c32 100644 --- a/sys/kern/kern_mbuf.c +++ b/sys/kern/kern_mbuf.c @@ -356,7 +356,7 @@ mbuf_jumbo_alloc(uma_zone_t zone, int bytes, u_int8_t *flags, int wait) /* Inform UMA that this allocator uses kernel_map/object. */ *flags = UMA_SLAB_KERNEL; return ((void *)kmem_alloc_contig(kernel_map, bytes, wait, - (vm_paddr_t)0, ~(vm_paddr_t)0, 1, 0, VM_CACHE_DEFAULT)); + (vm_paddr_t)0, ~(vm_paddr_t)0, 1, 0, VM_MEMATTR_DEFAULT)); } /* diff --git a/sys/mips/include/pmap.h b/sys/mips/include/pmap.h index 2979f3b741c5..4546cffd0a79 100644 --- a/sys/mips/include/pmap.h +++ b/sys/mips/include/pmap.h @@ -155,7 +155,9 @@ extern vm_paddr_t mips_wired_tlb_physmem_start; extern vm_paddr_t mips_wired_tlb_physmem_end; extern u_int need_wired_tlb_page_pool; +#define pmap_page_get_memattr(m) VM_MEMATTR_DEFAULT #define pmap_page_is_mapped(m) (!TAILQ_EMPTY(&(m)->md.pv_list)) +#define pmap_page_set_memattr(m, ma) (void)0 void pmap_bootstrap(void); void *pmap_mapdev(vm_offset_t, vm_size_t); diff --git a/sys/mips/include/vm.h b/sys/mips/include/vm.h index 9270d50c9f9a..c0aa55c850d0 100644 --- a/sys/mips/include/vm.h +++ b/sys/mips/include/vm.h @@ -31,10 +31,10 @@ #include -/* Cache control options. */ -#define VM_CACHE_UNCACHED ((vm_cache_mode_t)PTE_UNCACHED) -#define VM_CACHE_CACHEABLE_NONCOHERENT ((vm_cache_mode_t)PTE_CACHE) +/* Memory attributes. */ +#define VM_MEMATTR_UNCACHED ((vm_memattr_t)PTE_UNCACHED) +#define VM_MEMATTR_CACHEABLE_NONCOHERENT ((vm_memattr_t)PTE_CACHE) -#define VM_CACHE_DEFAULT VM_CACHE_CACHEABLE_NONCOHERENT +#define VM_MEMATTR_DEFAULT VM_MEMATTR_CACHEABLE_NONCOHERENT #endif /* !_MACHINE_VM_H_ */ diff --git a/sys/powerpc/include/pmap.h b/sys/powerpc/include/pmap.h index 42bc4099526e..d4fce7fef910 100644 --- a/sys/powerpc/include/pmap.h +++ b/sys/powerpc/include/pmap.h @@ -113,7 +113,9 @@ struct md_page { struct pvo_head mdpg_pvoh; }; +#define pmap_page_get_memattr(m) VM_MEMATTR_DEFAULT #define pmap_page_is_mapped(m) (!LIST_EMPTY(&(m)->md.mdpg_pvoh)) +#define pmap_page_set_memattr(m, ma) (void)0 #else @@ -143,7 +145,9 @@ struct md_page { TAILQ_HEAD(, pv_entry) pv_list; }; +#define pmap_page_get_memattr(m) VM_MEMATTR_DEFAULT #define pmap_page_is_mapped(m) (!TAILQ_EMPTY(&(m)->md.pv_list)) +#define pmap_page_set_memattr(m, ma) (void)0 #endif /* AIM */ diff --git a/sys/powerpc/include/vm.h b/sys/powerpc/include/vm.h index 20d2c88b4f99..f8f77f0088af 100644 --- a/sys/powerpc/include/vm.h +++ b/sys/powerpc/include/vm.h @@ -31,10 +31,12 @@ #include -/* Cache control options. */ -#define VM_CACHE_INHIBIT ((vm_cache_mode_t)PTE_I) -#define VM_CACHE_WRITE_THROUGH ((vm_cache_mode_t)PTE_W) +/* Memory attributes. */ +#define VM_MEMATTR_CACHING_INHIBIT ((vm_memattr_t)PTE_I) +#define VM_MEMATTR_GUARD ((vm_memattr_t)PTE_G) +#define VM_MEMATTR_MEMORY_COHERENCE ((vm_memattr_t)PTE_M) +#define VM_MEMATTR_WRITE_THROUGH ((vm_memattr_t)PTE_W) -#define VM_CACHE_DEFAULT 0 +#define VM_MEMATTR_DEFAULT 0 #endif /* !_MACHINE_VM_H_ */ diff --git a/sys/sparc64/include/pmap.h b/sys/sparc64/include/pmap.h index 9b85101e6657..91c2a51eb64b 100644 --- a/sys/sparc64/include/pmap.h +++ b/sys/sparc64/include/pmap.h @@ -77,6 +77,9 @@ struct pmap { #define PMAP_TRYLOCK(pmap) mtx_trylock(&(pmap)->pm_mtx) #define PMAP_UNLOCK(pmap) mtx_unlock(&(pmap)->pm_mtx) +#define pmap_page_get_memattr(m) VM_MEMATTR_DEFAULT +#define pmap_page_set_memattr(m, ma) (void)0 + void pmap_bootstrap(void); vm_paddr_t pmap_kextract(vm_offset_t va); void pmap_kenter(vm_offset_t va, vm_page_t m); diff --git a/sys/sparc64/include/vm.h b/sys/sparc64/include/vm.h index 8effe7861e82..7ec2d9e692a9 100644 --- a/sys/sparc64/include/vm.h +++ b/sys/sparc64/include/vm.h @@ -29,7 +29,7 @@ #ifndef _MACHINE_VM_H_ #define _MACHINE_VM_H_ -/* Cache control is not (yet) implemented. */ -#define VM_CACHE_DEFAULT 0 +/* Memory attribute configuration is not (yet) implemented. */ +#define VM_MEMATTR_DEFAULT 0 #endif /* !_MACHINE_VM_H_ */ diff --git a/sys/sun4v/include/pmap.h b/sys/sun4v/include/pmap.h index 3390e99c6846..90ae4c455604 100644 --- a/sys/sun4v/include/pmap.h +++ b/sys/sun4v/include/pmap.h @@ -106,7 +106,9 @@ typedef struct pv_entry { TAILQ_ENTRY(pv_entry) pv_plist; } *pv_entry_t; +#define pmap_page_get_memattr(m) VM_MEMATTR_DEFAULT #define pmap_page_is_mapped(m) (!TAILQ_EMPTY(&(m)->md.pv_list)) +#define pmap_page_set_memattr(m, ma) (void)0 void pmap_bootstrap(vm_offset_t ekva); vm_paddr_t pmap_kextract(vm_offset_t va); diff --git a/sys/sun4v/include/vm.h b/sys/sun4v/include/vm.h index 8effe7861e82..7ec2d9e692a9 100644 --- a/sys/sun4v/include/vm.h +++ b/sys/sun4v/include/vm.h @@ -29,7 +29,7 @@ #ifndef _MACHINE_VM_H_ #define _MACHINE_VM_H_ -/* Cache control is not (yet) implemented. */ -#define VM_CACHE_DEFAULT 0 +/* Memory attribute configuration is not (yet) implemented. */ +#define VM_MEMATTR_DEFAULT 0 #endif /* !_MACHINE_VM_H_ */ diff --git a/sys/vm/device_pager.c b/sys/vm/device_pager.c index 69d6dcabf23c..7993405c080e 100644 --- a/sys/vm/device_pager.c +++ b/sys/vm/device_pager.c @@ -70,9 +70,9 @@ static struct mtx dev_pager_mtx; static uma_zone_t fakepg_zone; -static vm_page_t dev_pager_getfake(vm_paddr_t); +static vm_page_t dev_pager_getfake(vm_paddr_t, vm_memattr_t); static void dev_pager_putfake(vm_page_t); -static void dev_pager_updatefake(vm_page_t, vm_paddr_t); +static void dev_pager_updatefake(vm_page_t, vm_paddr_t, vm_memattr_t); struct pagerops devicepagerops = { .pgo_init = dev_pager_init, @@ -210,7 +210,8 @@ dev_pager_getpages(object, m, count, reqpage) { vm_pindex_t offset; vm_paddr_t paddr; - vm_page_t page; + vm_page_t m_paddr, page; + vm_memattr_t memattr; struct cdev *dev; int i, ret; int prot; @@ -222,6 +223,7 @@ dev_pager_getpages(object, m, count, reqpage) dev = object->handle; page = m[reqpage]; offset = page->pindex; + memattr = object->memattr; VM_OBJECT_UNLOCK(object); csw = dev_refthread(dev); if (csw == NULL) @@ -235,14 +237,20 @@ dev_pager_getpages(object, m, count, reqpage) KASSERT(ret == 0, ("dev_pager_getpage: map function returns error")); td->td_fpop = fpop; dev_relthread(dev); - + /* If "paddr" is a real page, perform a sanity check on "memattr". */ + if ((m_paddr = vm_phys_paddr_to_vm_page(paddr)) != NULL && + pmap_page_get_memattr(m_paddr) != memattr) { + memattr = pmap_page_get_memattr(m_paddr); + printf( + "WARNING: A device driver has set \"memattr\" inconsistently.\n"); + } if ((page->flags & PG_FICTITIOUS) != 0) { /* * If the passed in reqpage page is a fake page, update it with * the new physical address. */ VM_OBJECT_LOCK(object); - dev_pager_updatefake(page, paddr); + dev_pager_updatefake(page, paddr, memattr); if (count > 1) { vm_page_lock_queues(); for (i = 0; i < count; i++) { @@ -256,7 +264,7 @@ dev_pager_getpages(object, m, count, reqpage) * Replace the passed in reqpage page with our own fake page and * free up the all of the original pages. */ - page = dev_pager_getfake(paddr); + page = dev_pager_getfake(paddr, memattr); VM_OBJECT_LOCK(object); TAILQ_INSERT_TAIL(&object->un_pager.devp.devp_pglist, page, pageq); vm_page_lock_queues(); @@ -296,47 +304,56 @@ dev_pager_haspage(object, pindex, before, after) } /* - * Instantiate a fictitious page. Unlike physical memory pages, only - * the machine-independent fields must be initialized. + * Create a fictitious page with the specified physical address and memory + * attribute. */ static vm_page_t -dev_pager_getfake(paddr) - vm_paddr_t paddr; +dev_pager_getfake(vm_paddr_t paddr, vm_memattr_t memattr) { vm_page_t m; - m = uma_zalloc(fakepg_zone, M_WAITOK); - - m->flags = PG_FICTITIOUS; - m->oflags = VPO_BUSY; - /* Fictitious pages don't use "act_count". */ - m->dirty = 0; - m->busy = 0; - m->queue = PQ_NONE; - m->object = NULL; - - m->wire_count = 1; - m->hold_count = 0; + m = uma_zalloc(fakepg_zone, M_WAITOK | M_ZERO); m->phys_addr = paddr; - + /* Fictitious pages don't use "segind". */ + m->flags = PG_FICTITIOUS; + /* Fictitious pages don't use "order" or "pool". */ + pmap_page_init(m); + m->oflags = VPO_BUSY; + m->wire_count = 1; + if (memattr != VM_MEMATTR_DEFAULT) + pmap_page_set_memattr(m, memattr); return (m); } +/* + * Release a fictitious page. + */ static void -dev_pager_putfake(m) - vm_page_t m; +dev_pager_putfake(vm_page_t m) { + if (!(m->flags & PG_FICTITIOUS)) panic("dev_pager_putfake: bad page"); + /* Restore the default memory attribute to "phys_addr". */ + if (pmap_page_get_memattr(m) != VM_MEMATTR_DEFAULT) + pmap_page_set_memattr(m, VM_MEMATTR_DEFAULT); uma_zfree(fakepg_zone, m); } +/* + * Update the given fictitious page to the specified physical address and + * memory attribute. + */ static void -dev_pager_updatefake(m, paddr) - vm_page_t m; - vm_paddr_t paddr; +dev_pager_updatefake(vm_page_t m, vm_paddr_t paddr, vm_memattr_t memattr) { + if (!(m->flags & PG_FICTITIOUS)) panic("dev_pager_updatefake: bad page"); + /* Restore the default memory attribute before changing "phys_addr". */ + if (pmap_page_get_memattr(m) != VM_MEMATTR_DEFAULT) + pmap_page_set_memattr(m, VM_MEMATTR_DEFAULT); m->phys_addr = paddr; + if (memattr != VM_MEMATTR_DEFAULT) + pmap_page_set_memattr(m, memattr); } diff --git a/sys/vm/pmap.h b/sys/vm/pmap.h index 486855c18bf5..22d61181b3cd 100644 --- a/sys/vm/pmap.h +++ b/sys/vm/pmap.h @@ -79,10 +79,16 @@ struct pmap_statistics { }; typedef struct pmap_statistics *pmap_statistics_t; +/* + * Each machine dependent implementation is expected to provide: + * + * vm_memattr_t pmap_page_get_memattr(vm_page_t); + * boolean_t pmap_page_is_mapped(vm_page_t); + * void pmap_page_set_memattr(vm_page_t, vm_memattr_t); + */ #include #ifdef _KERNEL -struct proc; struct thread; /* diff --git a/sys/vm/vm.h b/sys/vm/vm.h index 832c335676aa..9159e93b3657 100644 --- a/sys/vm/vm.h +++ b/sys/vm/vm.h @@ -64,10 +64,10 @@ #include /* - * The exact set of cache control codes is machine dependent. However, every - * machine is required to define VM_CACHE_DEFAULT. + * The exact set of memory attributes is machine dependent. However, every + * machine is required to define VM_MEMATTR_DEFAULT. */ -typedef char vm_cache_mode_t; /* cache control codes */ +typedef char vm_memattr_t; /* memory attribute codes */ typedef char vm_inherit_t; /* inheritance codes */ diff --git a/sys/vm/vm_contig.c b/sys/vm/vm_contig.c index d2b67039fd8c..7358cb0cca81 100644 --- a/sys/vm/vm_contig.c +++ b/sys/vm/vm_contig.c @@ -194,7 +194,8 @@ vm_page_release_contig(vm_page_t m, vm_pindex_t count) * before they are mapped. */ static vm_offset_t -contigmapping(vm_map_t map, vm_size_t size, vm_page_t m, int flags) +contigmapping(vm_map_t map, vm_size_t size, vm_page_t m, vm_memattr_t memattr, + int flags) { vm_object_t object = kernel_object; vm_offset_t addr, tmp_addr; @@ -210,6 +211,8 @@ contigmapping(vm_map_t map, vm_size_t size, vm_page_t m, int flags) vm_map_unlock(map); VM_OBJECT_LOCK(object); for (tmp_addr = addr; tmp_addr < addr + size; tmp_addr += PAGE_SIZE) { + if (memattr != VM_MEMATTR_DEFAULT) + pmap_page_set_memattr(m, memattr); vm_page_insert(m, object, OFF_TO_IDX(tmp_addr - VM_MIN_KERNEL_ADDRESS)); if ((flags & M_ZERO) && (m->flags & PG_ZERO) == 0) @@ -236,7 +239,7 @@ contigmalloc( void *ret; ret = (void *)kmem_alloc_contig(kernel_map, size, flags, low, high, - alignment, boundary, VM_CACHE_DEFAULT); + alignment, boundary, VM_MEMATTR_DEFAULT); if (ret != NULL) malloc_type_allocated(type, round_page(size)); return (ret); @@ -245,7 +248,7 @@ contigmalloc( vm_offset_t kmem_alloc_contig(vm_map_t map, vm_size_t size, int flags, vm_paddr_t low, vm_paddr_t high, unsigned long alignment, unsigned long boundary, - vm_cache_mode_t mode) + vm_memattr_t memattr) { vm_offset_t ret; vm_page_t pages; @@ -256,8 +259,7 @@ kmem_alloc_contig(vm_map_t map, vm_size_t size, int flags, vm_paddr_t low, npgs = size >> PAGE_SHIFT; tries = 0; retry: - pages = vm_phys_alloc_contig(npgs, low, high, alignment, boundary, - mode); + pages = vm_phys_alloc_contig(npgs, low, high, alignment, boundary); if (pages == NULL) { if (tries < ((flags & M_NOWAIT) != 0 ? 1 : 3)) { vm_page_lock_queues(); @@ -282,7 +284,7 @@ kmem_alloc_contig(vm_map_t map, vm_size_t size, int flags, vm_paddr_t low, } ret = 0; } else { - ret = contigmapping(map, size, pages, flags); + ret = contigmapping(map, size, pages, memattr, flags); if (ret == 0) vm_page_release_contig(pages, npgs); } diff --git a/sys/vm/vm_extern.h b/sys/vm/vm_extern.h index ec21a3a471c0..53f76947ee85 100644 --- a/sys/vm/vm_extern.h +++ b/sys/vm/vm_extern.h @@ -43,7 +43,7 @@ int kernacc(void *, int, int); vm_offset_t kmem_alloc(vm_map_t, vm_size_t); vm_offset_t kmem_alloc_contig(vm_map_t map, vm_size_t size, int flags, vm_paddr_t low, vm_paddr_t high, unsigned long alignment, - unsigned long boundary, vm_cache_mode_t mode); + unsigned long boundary, vm_memattr_t memattr); vm_offset_t kmem_alloc_nofault(vm_map_t, vm_size_t); vm_offset_t kmem_alloc_wait(vm_map_t, vm_size_t); void kmem_free(vm_map_t, vm_offset_t, vm_size_t); diff --git a/sys/vm/vm_object.c b/sys/vm/vm_object.c index 3b3124c9e84e..10d58e7d1d33 100644 --- a/sys/vm/vm_object.c +++ b/sys/vm/vm_object.c @@ -222,6 +222,7 @@ _vm_object_allocate(objtype_t type, vm_pindex_t size, vm_object_t object) object->size = size; object->generation = 1; object->ref_count = 1; + object->memattr = VM_MEMATTR_DEFAULT; object->flags = 0; object->uip = NULL; object->charge = 0; @@ -290,6 +291,36 @@ vm_object_clear_flag(vm_object_t object, u_short bits) object->flags &= ~bits; } +/* + * Sets the default memory attribute for the specified object. Pages + * that are allocated to this object are by default assigned this memory + * attribute. + * + * Presently, this function must be called before any pages are allocated + * to the object. In the future, this requirement may be relaxed for + * "default" and "swap" objects. + */ +int +vm_object_set_memattr(vm_object_t object, vm_memattr_t memattr) +{ + + VM_OBJECT_LOCK_ASSERT(object, MA_OWNED); + switch (object->type) { + case OBJT_DEFAULT: + case OBJT_DEVICE: + case OBJT_PHYS: + case OBJT_SWAP: + case OBJT_VNODE: + if (!TAILQ_EMPTY(&object->memq)) + return (KERN_FAILURE); + break; + case OBJT_DEAD: + return (KERN_INVALID_ARGUMENT); + } + object->memattr = memattr; + return (KERN_SUCCESS); +} + void vm_object_pip_add(vm_object_t object, short i) { diff --git a/sys/vm/vm_object.h b/sys/vm/vm_object.h index bf88cfd6c405..0e57aca8ee82 100644 --- a/sys/vm/vm_object.h +++ b/sys/vm/vm_object.h @@ -92,6 +92,7 @@ struct vm_object { int generation; /* generation ID */ int ref_count; /* How many refs?? */ int shadow_count; /* how many objects that this is a shadow for */ + vm_memattr_t memattr; /* default memory attribute for pages */ objtype_t type; /* type of pager */ u_short flags; /* see below */ u_short pg_color; /* (c) color of first page in obj */ @@ -213,6 +214,7 @@ void vm_object_page_remove (vm_object_t, vm_pindex_t, vm_pindex_t, boolean_t); boolean_t vm_object_populate(vm_object_t, vm_pindex_t, vm_pindex_t); void vm_object_reference (vm_object_t); void vm_object_reference_locked(vm_object_t); +int vm_object_set_memattr(vm_object_t object, vm_memattr_t memattr); void vm_object_shadow (vm_object_t *, vm_ooffset_t *, vm_size_t); void vm_object_split(vm_map_entry_t); void vm_object_sync(vm_object_t, vm_ooffset_t, vm_size_t, boolean_t, diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c index 7148fdc0b760..b9c4ebc74ae1 100644 --- a/sys/vm/vm_page.c +++ b/sys/vm/vm_page.c @@ -1109,12 +1109,15 @@ vm_page_alloc(vm_object_t object, vm_pindex_t pindex, int req) */ KASSERT(m != NULL, ("vm_page_alloc: missing page")); - KASSERT(m->queue == PQ_NONE, ("vm_page_alloc: page %p has unexpected queue %d", - m, m->queue)); + KASSERT(m->queue == PQ_NONE, + ("vm_page_alloc: page %p has unexpected queue %d", m, m->queue)); KASSERT(m->wire_count == 0, ("vm_page_alloc: page %p is wired", m)); KASSERT(m->hold_count == 0, ("vm_page_alloc: page %p is held", m)); KASSERT(m->busy == 0, ("vm_page_alloc: page %p is busy", m)); KASSERT(m->dirty == 0, ("vm_page_alloc: page %p is dirty", m)); + KASSERT(pmap_page_get_memattr(m) == VM_MEMATTR_DEFAULT, + ("vm_page_alloc: page %p has unexpected memattr %d", m, + pmap_page_get_memattr(m))); if ((m->flags & PG_CACHED) != 0) { KASSERT(m->valid != 0, ("vm_page_alloc: cached page %p is invalid", m)); @@ -1157,9 +1160,11 @@ vm_page_alloc(vm_object_t object, vm_pindex_t pindex, int req) m->act_count = 0; mtx_unlock(&vm_page_queue_free_mtx); - if ((req & VM_ALLOC_NOOBJ) == 0) + if (object != NULL) { + if (object->memattr != VM_MEMATTR_DEFAULT) + pmap_page_set_memattr(m, object->memattr); vm_page_insert(m, object, pindex); - else + } else m->pindex = pindex; /* @@ -1415,6 +1420,16 @@ vm_page_free_toq(vm_page_t m) m->flags &= ~PG_ZERO; vm_page_enqueue(PQ_HOLD, m); } else { + /* + * Restore the default memory attribute to the page. + */ + if (pmap_page_get_memattr(m) != VM_MEMATTR_DEFAULT) + pmap_page_set_memattr(m, VM_MEMATTR_DEFAULT); + + /* + * Insert the page into the physical memory allocator's + * cache/free page queues. + */ mtx_lock(&vm_page_queue_free_mtx); m->flags |= PG_FREE; cnt.v_free_count++; @@ -1663,6 +1678,12 @@ vm_page_cache(vm_page_t m) object->resident_page_count--; object->generation++; + /* + * Restore the default memory attribute to the page. + */ + if (pmap_page_get_memattr(m) != VM_MEMATTR_DEFAULT) + pmap_page_set_memattr(m, VM_MEMATTR_DEFAULT); + /* * Insert the page into the object's collection of cached pages * and the physical memory allocator's cache/free page queues. diff --git a/sys/vm/vm_phys.c b/sys/vm/vm_phys.c index 58e71d05ffb1..a2454621a435 100644 --- a/sys/vm/vm_phys.c +++ b/sys/vm/vm_phys.c @@ -588,7 +588,7 @@ vm_phys_zero_pages_idle(void) */ vm_page_t vm_phys_alloc_contig(unsigned long npages, vm_paddr_t low, vm_paddr_t high, - unsigned long alignment, unsigned long boundary, vm_cache_mode_t mode) + unsigned long alignment, unsigned long boundary) { struct vm_freelist *fl; struct vm_phys_seg *seg; @@ -698,6 +698,9 @@ vm_phys_alloc_contig(unsigned long npages, vm_paddr_t low, vm_paddr_t high, ("vm_phys_alloc_contig: page %p is busy", m)); KASSERT(m->dirty == 0, ("vm_phys_alloc_contig: page %p is dirty", m)); + KASSERT(pmap_page_get_memattr(m) == VM_MEMATTR_DEFAULT, + ("vm_phys_alloc_contig: page %p has unexpected memattr %d", + m, pmap_page_get_memattr(m))); if ((m->flags & PG_CACHED) != 0) { m->valid = 0; m_object = m->object; diff --git a/sys/vm/vm_phys.h b/sys/vm/vm_phys.h index 483ab918acd9..0e012c322973 100644 --- a/sys/vm/vm_phys.h +++ b/sys/vm/vm_phys.h @@ -43,7 +43,7 @@ void vm_phys_add_page(vm_paddr_t pa); vm_page_t vm_phys_alloc_contig(unsigned long npages, vm_paddr_t low, vm_paddr_t high, - unsigned long alignment, unsigned long boundary, vm_cache_mode_t mode); + unsigned long alignment, unsigned long boundary); vm_page_t vm_phys_alloc_pages(int pool, int order); vm_paddr_t vm_phys_bootstrap_alloc(vm_size_t size, unsigned long alignment); void vm_phys_free_pages(vm_page_t m, int order);