diff --git a/sys/amd64/amd64/pmap.c b/sys/amd64/amd64/pmap.c index 99f55cbca146..265d77db27bc 100644 --- a/sys/amd64/amd64/pmap.c +++ b/sys/amd64/amd64/pmap.c @@ -4381,9 +4381,12 @@ 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 "m" is a normal page, update its direct mapping. This update + * can be relied upon to perform any cache operations that are + * required for data coherence. */ - if (pmap_change_attr(PHYS_TO_DMAP(VM_PAGE_TO_PHYS(m)), PAGE_SIZE, + if ((m->flags & PG_FICTITIOUS) == 0 && + 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"); } diff --git a/sys/i386/i386/pmap.c b/sys/i386/i386/pmap.c index 6103fd59bf03..b973d0d50098 100644 --- a/sys/i386/i386/pmap.c +++ b/sys/i386/i386/pmap.c @@ -4466,12 +4466,13 @@ 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. + * If "m" is a normal page, flush it from the cache. */ - /* If "Self Snoop" is supported, do nothing. */ - if (!(cpu_feature & CPUID_SS)) - pmap_invalidate_cache(); + if ((m->flags & PG_FICTITIOUS) == 0) { + /* If "Self Snoop" is supported, do nothing. */ + if (!(cpu_feature & CPUID_SS)) + pmap_invalidate_cache(); + } } int diff --git a/sys/i386/xen/pmap.c b/sys/i386/xen/pmap.c index 9a9a1b4e9a19..051685ac24a6 100644 --- a/sys/i386/xen/pmap.c +++ b/sys/i386/xen/pmap.c @@ -3921,6 +3921,25 @@ 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; + + /* + * If "m" is a normal page, flush it from the cache. + */ + if ((m->flags & PG_FICTITIOUS) == 0) { + /* If "Self Snoop" is supported, do nothing. */ + if (!(cpu_feature & CPUID_SS)) + pmap_invalidate_cache(); + } +} + int pmap_change_attr(va, size, mode) vm_offset_t va; diff --git a/sys/vm/device_pager.c b/sys/vm/device_pager.c index 7993405c080e..0d762de07052 100644 --- a/sys/vm/device_pager.c +++ b/sys/vm/device_pager.c @@ -305,7 +305,8 @@ dev_pager_haspage(object, pindex, before, after) /* * Create a fictitious page with the specified physical address and memory - * attribute. + * attribute. The memory attribute is the only the machine-dependent aspect + * of a fictitious page that must be initialized. */ static vm_page_t dev_pager_getfake(vm_paddr_t paddr, vm_memattr_t memattr) @@ -317,11 +318,9 @@ dev_pager_getfake(vm_paddr_t paddr, vm_memattr_t memattr) /* 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); + pmap_page_set_memattr(m, memattr); return (m); } @@ -334,9 +333,6 @@ 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); } @@ -350,10 +346,6 @@ 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); + pmap_page_set_memattr(m, memattr); }