Handle pmap_enter() over an existing 4/2M page in KVA on i386.

The userspace case was already handled by pmap_allocpte().  For kernel
VA, page table page must exist, and demote cannot fail, so we need to
just call pmap_demote_pde().  Also note that due to the machine AS
layout, promotions in the KVA on i386 are highly unlikely, so this
change is mostly for completeness.

Reviewed by:	alc, markj
Tested by:	pho
Sponsored by:	The FreeBSD Foundation
MFC after:	2 weeks
Differential revision:	https://reviews.freebsd.org/D8323
This commit is contained in:
kib 2016-10-28 11:53:22 +00:00
parent bdd259c16e
commit 9cc20ad665

View File

@ -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);