summaryrefslogtreecommitdiffstats
path: root/sys/amd64
diff options
context:
space:
mode:
authoralc <alc@FreeBSD.org>2008-06-01 07:36:59 +0000
committeralc <alc@FreeBSD.org>2008-06-01 07:36:59 +0000
commit061cc6f3ee167947a9dcbd736ad5a4db12e42265 (patch)
treeed697da7921f7a68f4bae5993967eadbd758c60c /sys/amd64
parent28d80fbb7a0b38fd6acd0beba42e1858ef18d9e2 (diff)
downloadFreeBSD-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.c8
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;
OpenPOWER on IntegriCloud