summaryrefslogtreecommitdiffstats
path: root/sys/i386
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2016-11-11 20:31:23 +0000
committerkib <kib@FreeBSD.org>2016-11-11 20:31:23 +0000
commit9182987ec694666c49c220c7c01d8cbe8bcbf2c8 (patch)
tree2f3394763db6924a35d6c3e6617a69d89bffee0a /sys/i386
parentb367d5d01363c09d5c8ab0725ec4990c635e6e0a (diff)
downloadFreeBSD-src-9182987ec694666c49c220c7c01d8cbe8bcbf2c8.zip
FreeBSD-src-9182987ec694666c49c220c7c01d8cbe8bcbf2c8.tar.gz
MFC r308029:
Handle pmap_enter() over an existing 4/2M page in KVA on i386.
Diffstat (limited to 'sys/i386')
-rw-r--r--sys/i386/i386/pmap.c32
1 files changed, 22 insertions, 10 deletions
diff --git a/sys/i386/i386/pmap.c b/sys/i386/i386/pmap.c
index dad505a..c0929d7 100644
--- a/sys/i386/i386/pmap.c
+++ b/sys/i386/i386/pmap.c
@@ -3466,11 +3466,14 @@ pmap_enter(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot,
PMAP_LOCK(pmap);
sched_pin();
- /*
- * In the case that a page table page is not
- * resident, we are creating it here.
- */
+ pde = pmap_pde(pmap, va);
if (va < VM_MAXUSER_ADDRESS) {
+ /*
+ * va is for UVA.
+ * In the case that a page table page is not resident,
+ * we are creating it here. pmap_allocpte() handles
+ * demotion.
+ */
mpte = pmap_allocpte(pmap, va, flags);
if (mpte == NULL) {
KASSERT((flags & PMAP_ENTER_NOSLEEP) != 0,
@@ -3480,19 +3483,28 @@ pmap_enter(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot,
PMAP_UNLOCK(pmap);
return (KERN_RESOURCE_SHORTAGE);
}
+ } else {
+ /*
+ * va is for KVA, so pmap_demote_pde() will never fail
+ * to install a page table page. PG_V is also
+ * asserted by pmap_demote_pde().
+ */
+ KASSERT(pde != NULL && (*pde & PG_V) != 0,
+ ("KVA %#x invalid pde pdir %#jx", va,
+ (uintmax_t)pmap->pm_pdir[PTDPTDI]));
+ if ((*pde & PG_PS) != 0)
+ pmap_demote_pde(pmap, pde, va);
}
-
- pde = pmap_pde(pmap, va);
- if ((*pde & PG_PS) != 0)
- panic("pmap_enter: attempted pmap_enter on 4MB page");
pte = pmap_pte_quick(pmap, va);
/*
- * Page Directory table entry not valid, we need a new PT page
+ * Page Directory table entry is not valid, which should not
+ * happen. We should have either allocated the page table
+ * page or demoted the existing mapping above.
*/
if (pte == NULL) {
panic("pmap_enter: invalid page directory pdir=%#jx, va=%#x",
- (uintmax_t)pmap->pm_pdir[PTDPTDI], va);
+ (uintmax_t)pmap->pm_pdir[PTDPTDI], va);
}
pa = VM_PAGE_TO_PHYS(m);
OpenPOWER on IntegriCloud