summaryrefslogtreecommitdiffstats
path: root/sys/amd64
diff options
context:
space:
mode:
authoralc <alc@FreeBSD.org>2009-07-06 18:43:42 +0000
committeralc <alc@FreeBSD.org>2009-07-06 18:43:42 +0000
commitc9ef1e01042ca2bf24cdc667b8706fa633692304 (patch)
tree7999744132a8c42bf992b2aa7b595626d4583faf /sys/amd64
parent19e5186727eceb4c07892bc93ebd663e5b022341 (diff)
downloadFreeBSD-src-c9ef1e01042ca2bf24cdc667b8706fa633692304.zip
FreeBSD-src-c9ef1e01042ca2bf24cdc667b8706fa633692304.tar.gz
When pmap_change_attr() changes the PAT setting on a kernel mapping, it has
to simultaneously change the PAT setting for the same pages within the direct map region. This may require the demotion of a 2MB page mapping and the allocation of a page table page. This revision gives the highest possible priority (VM_ALLOC_INTERRUPT) to this page allocation, so that pmap_change_attr() is less likely to fail. (In general, kernel page table page allocations have the highest priority, so this is not creating a new precedent.) (Demotion of 1GB page mappings within the direct map already specifies VM_ALLOC_INTERRUPT to vm_page_alloc(), so only pmap_demote_pde() must be changed.) Approved by: re (kib)
Diffstat (limited to 'sys/amd64')
-rw-r--r--sys/amd64/amd64/pmap.c14
1 files changed, 11 insertions, 3 deletions
diff --git a/sys/amd64/amd64/pmap.c b/sys/amd64/amd64/pmap.c
index eb09d41..5bf8b89 100644
--- a/sys/amd64/amd64/pmap.c
+++ b/sys/amd64/amd64/pmap.c
@@ -2218,11 +2218,19 @@ pmap_demote_pde(pmap_t pmap, pd_entry_t *pde, vm_offset_t va)
/*
* Invalidate the 2MB page mapping and return "failure" if the
* mapping was never accessed or the allocation of the new
- * page table page fails.
+ * page table page fails. If the 2MB page mapping belongs to
+ * the direct map region of the kernel's address space, then
+ * the page allocation request specifies the highest possible
+ * priority (VM_ALLOC_INTERRUPT). Otherwise, the priority is
+ * normal. Page table pages are preallocated for every other
+ * part of the kernel address space, so the direct map region
+ * is the only part of the kernel address space that must be
+ * handled here.
*/
if ((oldpde & PG_A) == 0 || (mpte = vm_page_alloc(NULL,
- pmap_pde_pindex(va), VM_ALLOC_NOOBJ | VM_ALLOC_NORMAL |
- VM_ALLOC_WIRED)) == NULL) {
+ pmap_pde_pindex(va), (va >= DMAP_MIN_ADDRESS && va <
+ DMAP_MAX_ADDRESS ? VM_ALLOC_INTERRUPT : VM_ALLOC_NORMAL) |
+ VM_ALLOC_NOOBJ | VM_ALLOC_WIRED)) == NULL) {
free = NULL;
pmap_remove_pde(pmap, pde, trunc_2mpage(va), &free);
pmap_invalidate_page(pmap, trunc_2mpage(va));
OpenPOWER on IntegriCloud