- Introduce a specific function, pmap_remove_kernel_pde, for removing

huge pages in the kernel's address space.  This works around several
   asserts from pmap_demote_pde_locked that did not apply and gave false
   warnings.

Discovered by:	pho
Reviewed by:	alc
Sponsored by:	EMC / Isilon Storage Division
This commit is contained in:
Jeff Roberson 2013-08-05 00:28:03 +00:00
parent 66bacd7e17
commit 2c0b86b48f
2 changed files with 78 additions and 4 deletions

View File

@ -2794,6 +2794,44 @@ pmap_demote_pde_locked(pmap_t pmap, pd_entry_t *pde, vm_offset_t va,
return (TRUE);
}
/*
* pmap_remove_kernel_pde: Remove a kernel superpage mapping.
*/
static void
pmap_remove_kernel_pde(pmap_t pmap, pd_entry_t *pde, vm_offset_t va)
{
pd_entry_t newpde;
vm_paddr_t mptepa;
vm_page_t mpte;
PMAP_LOCK_ASSERT(pmap, MA_OWNED);
mpte = pmap_lookup_pt_page(pmap, va);
if (mpte == NULL)
panic("pmap_remove_kernel_pde: Missing pt page.");
pmap_remove_pt_page(pmap, mpte);
mptepa = VM_PAGE_TO_PHYS(mpte);
newpde = mptepa | PG_M | PG_A | PG_RW | PG_V;
/*
* Initialize the page table page.
*/
pagezero((void *)PHYS_TO_DMAP(mptepa));
/*
* Demote the mapping.
*/
if (workaround_erratum383)
pmap_update_pde(pmap, va, pde, newpde);
else
pde_store(pde, newpde);
/*
* Invalidate a stale recursive mapping of the page table page.
*/
pmap_invalidate_page(pmap, (vm_offset_t)vtopte(va));
}
/*
* pmap_remove_pde: do the things to unmap a superpage in a process
*/
@ -2837,8 +2875,7 @@ pmap_remove_pde(pmap_t pmap, pd_entry_t *pdq, vm_offset_t sva,
}
}
if (pmap == kernel_pmap) {
if (!pmap_demote_pde_locked(pmap, pdq, sva, lockp))
panic("pmap_remove_pde: failed demotion");
pmap_remove_kernel_pde(pmap, pdq, sva);
} else {
mpte = pmap_lookup_pt_page(pmap, sva);
if (mpte != NULL) {

View File

@ -2772,6 +2772,44 @@ pmap_demote_pde(pmap_t pmap, pd_entry_t *pde, vm_offset_t va)
return (TRUE);
}
/*
* Removes a 2- or 4MB page mapping from the kernel pmap.
*/
static void
pmap_remove_kernel_pde(pmap_t pmap, pd_entry_t *pde, vm_offset_t va)
{
pd_entry_t newpde;
vm_paddr_t mptepa;
vm_page_t mpte;
PMAP_LOCK_ASSERT(pmap, MA_OWNED);
mpte = pmap_lookup_pt_page(pmap, va);
if (mpte == NULL)
panic("pmap_remove_kernel_pde: Missing pt page.");
pmap_remove_pt_page(pmap, mpte);
mptepa = VM_PAGE_TO_PHYS(mpte);
newpde = mptepa | PG_M | PG_A | PG_RW | PG_V;
/*
* Initialize the page table page.
*/
pagezero((void *)&KPTmap[i386_btop(trunc_4mpage(va))]);
/*
* Remove the mapping.
*/
if (workaround_erratum383)
pmap_update_pde(pmap, va, pde, newpde);
else
pmap_kenter_pde(va, newpde);
/*
* Invalidate the recursive mapping of the page table page.
*/
pmap_invalidate_page(pmap, (vm_offset_t)vtopte(va));
}
/*
* pmap_remove_pde: do the things to unmap a superpage in a process
*/
@ -2814,8 +2852,7 @@ pmap_remove_pde(pmap_t pmap, pd_entry_t *pdq, vm_offset_t sva,
}
}
if (pmap == kernel_pmap) {
if (!pmap_demote_pde(pmap, pdq, sva))
panic("pmap_remove_pde: failed demotion");
pmap_remove_kernel_pde(pmap, pdq, sva);
} else {
mpte = pmap_lookup_pt_page(pmap, sva);
if (mpte != NULL) {