Change the handling of fictitious pages by pmap_page_set_memattr() on

amd64 and i386.  Essentially, fictitious pages provide a mechanism for
creating aliases for either normal or device-backed pages.  Therefore,
pmap_page_set_memattr() on a fictitious page needn't update the direct
map or flush the cache.  Such actions are the responsibility of the
"primary" instance of the page or the device driver that "owns" the
physical address.  For example, these actions are already performed by
pmap_mapdev().

The device pager needn't restore the memory attributes on a fictitious
page before releasing it.  It's now pointless.

Add pmap_page_set_memattr() to the Xen pmap.

Approved by:	re (kib)
This commit is contained in:
Alan Cox 2009-07-19 21:40:19 +00:00
parent 7ac5806bfb
commit 9861cbc6ca
4 changed files with 34 additions and 19 deletions

View File

@ -4381,9 +4381,12 @@ pmap_page_set_memattr(vm_page_t m, vm_memattr_t ma)
m->md.pat_mode = 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)) m->md.pat_mode))
panic("memory attribute change on the direct map failed"); panic("memory attribute change on the direct map failed");
} }

View File

@ -4466,12 +4466,13 @@ pmap_page_set_memattr(vm_page_t m, vm_memattr_t ma)
m->md.pat_mode = ma; m->md.pat_mode = ma;
/* /*
* Flush CPU caches to make sure any data isn't cached that shouldn't * If "m" is a normal page, flush it from the cache.
* be, etc.
*/ */
/* If "Self Snoop" is supported, do nothing. */ if ((m->flags & PG_FICTITIOUS) == 0) {
if (!(cpu_feature & CPUID_SS)) /* If "Self Snoop" is supported, do nothing. */
pmap_invalidate_cache(); if (!(cpu_feature & CPUID_SS))
pmap_invalidate_cache();
}
} }
int int

View File

@ -3921,6 +3921,25 @@ pmap_unmapdev(vm_offset_t va, vm_size_t size)
kmem_free(kernel_map, base, 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 int
pmap_change_attr(va, size, mode) pmap_change_attr(va, size, mode)
vm_offset_t va; vm_offset_t va;

View File

@ -305,7 +305,8 @@ dev_pager_haspage(object, pindex, before, after)
/* /*
* Create a fictitious page with the specified physical address and memory * 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 static vm_page_t
dev_pager_getfake(vm_paddr_t paddr, vm_memattr_t memattr) 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". */ /* Fictitious pages don't use "segind". */
m->flags = PG_FICTITIOUS; m->flags = PG_FICTITIOUS;
/* Fictitious pages don't use "order" or "pool". */ /* Fictitious pages don't use "order" or "pool". */
pmap_page_init(m);
m->oflags = VPO_BUSY; m->oflags = VPO_BUSY;
m->wire_count = 1; m->wire_count = 1;
if (memattr != VM_MEMATTR_DEFAULT) pmap_page_set_memattr(m, memattr);
pmap_page_set_memattr(m, memattr);
return (m); return (m);
} }
@ -334,9 +333,6 @@ dev_pager_putfake(vm_page_t m)
if (!(m->flags & PG_FICTITIOUS)) if (!(m->flags & PG_FICTITIOUS))
panic("dev_pager_putfake: bad page"); 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); 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)) if (!(m->flags & PG_FICTITIOUS))
panic("dev_pager_updatefake: bad page"); 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; m->phys_addr = paddr;
if (memattr != VM_MEMATTR_DEFAULT) pmap_page_set_memattr(m, memattr);
pmap_page_set_memattr(m, memattr);
} }