diff options
author | alc <alc@FreeBSD.org> | 2008-06-01 07:36:59 +0000 |
---|---|---|
committer | alc <alc@FreeBSD.org> | 2008-06-01 07:36:59 +0000 |
commit | 061cc6f3ee167947a9dcbd736ad5a4db12e42265 (patch) | |
tree | ed697da7921f7a68f4bae5993967eadbd758c60c /sys/amd64 | |
parent | 28d80fbb7a0b38fd6acd0beba42e1858ef18d9e2 (diff) | |
download | FreeBSD-src-061cc6f3ee167947a9dcbd736ad5a4db12e42265.zip FreeBSD-src-061cc6f3ee167947a9dcbd736ad5a4db12e42265.tar.gz |
Correct an error in pmap_promote_pde() that may result in an errant
promotion within the kernel's address space. Specifically,
pmap_promote_pde() is only called when the page table page (PTP) that
is referenced by the given PDE has a full "use count", i.e., its
wire_count is 512. Although this guarantees for a user address space
that all 512 PTEs in the PTP hold valid mappings, the same is not true
of the kernel's address space. A kernel PTP always has a use count of
512 regardless of the state of the PTEs. Therefore,
pmap_promote_pde() should not assume (or assert) that the first PTE in
the PTP is valid.
Diffstat (limited to 'sys/amd64')
-rw-r--r-- | sys/amd64/amd64/pmap.c | 8 |
1 files changed, 3 insertions, 5 deletions
diff --git a/sys/amd64/amd64/pmap.c b/sys/amd64/amd64/pmap.c index 28cf203..0f2f0c1 100644 --- a/sys/amd64/amd64/pmap.c +++ b/sys/amd64/amd64/pmap.c @@ -2775,22 +2775,20 @@ pmap_promote_pde(pmap_t pmap, pd_entry_t *pde, vm_offset_t va) PMAP_LOCK_ASSERT(pmap, MA_OWNED); firstpte = (pt_entry_t *)PHYS_TO_DMAP(*pde & PG_FRAME); - KASSERT((*firstpte & PG_V) != 0, - ("pmap_promote_pde: firstpte is missing PG_V")); - if ((*firstpte & PG_A) == 0) { + newpde = *firstpte; + if ((newpde & (PG_A | PG_V)) != (PG_A | PG_V)) { pmap_pde_p_failures++; CTR2(KTR_PMAP, "pmap_promote_pde: failure for va %#lx" " in pmap %p", va, pmap); return; } - pa = *firstpte & PG_PS_FRAME; - newpde = *firstpte; if ((newpde & (PG_M | PG_RW)) == PG_RW) newpde &= ~PG_RW; /* * Check all the ptes before promotion */ + pa = newpde & PG_PS_FRAME; for (pte = firstpte; pte < firstpte + NPTEPG; pte++) { retry: oldpte = *pte; |