Index: sys/amd64/amd64/pmap.c =================================================================== --- sys/amd64/amd64/pmap.c +++ sys/amd64/amd64/pmap.c @@ -383,8 +383,6 @@ static u_int64_t DMPDPphys; /* phys addr of direct mapped level 3 */ static int ndmpdpphys; /* number of DMPDPphys pages */ -static vm_paddr_t KERNend; /* phys addr of end of bootstrap data */ - /* * pmap_mapdev support pre initialization (i.e. console) */ @@ -1331,6 +1329,9 @@ return (pg_nx); } +static int kern_promoted_end; /* Last index of the kernel page table + page shadowed by pre-promoted pde. */ + static void create_pagetables(vm_paddr_t *firstaddr) { @@ -1396,10 +1397,12 @@ KPTphys = allocpages(firstaddr, nkpt); KPDphys = allocpages(firstaddr, nkpdpe); - /* Fill in the underlying page table pages */ - /* XXX not fully used, underneath 2M pages */ + /* + * Fill in the underlying page table pages. Only used when + * PTmap mappings are demoted. + */ pt_p = (pt_entry_t *)KPTphys; - for (i = 0; ptoa(i) < *firstaddr; i++) + for (i = 0; ptoa(i) < round_2mpage(*firstaddr); i++) pt_p[i] = ptoa(i) | X86_PG_V | pg_g | bootaddr_rwx(ptoa(i)); /* Now map the page tables at their location within PTmap */ @@ -1407,13 +1410,16 @@ for (i = 0; i < nkpt; i++) pd_p[i] = (KPTphys + ptoa(i)) | X86_PG_RW | X86_PG_V; - /* Map from zero to end of allocations under 2M pages */ - /* This replaces some of the KPTphys entries above */ - for (i = 0; (i << PDRSHIFT) < *firstaddr; i++) + /* + * Map from zero to end of allocations under 2M pages. + * This replaces some of the KPTphys entries above. + */ + kern_promoted_end = *firstaddr; + for (i = 0; (i << PDRSHIFT) < kern_promoted_end; i++) /* Preset PG_M and PG_A because demotion expects it. */ pd_p[i] = (i << PDRSHIFT) | X86_PG_V | PG_PS | pg_g | X86_PG_M | X86_PG_A | bootaddr_rwx(i << PDRSHIFT); - + kern_promoted_end = i; /* * Because we map the physical blocks in 2M pages, adjust firstaddr * to record the physical blocks we've actually mapped into kernel @@ -1506,8 +1512,7 @@ u_long res; int i; - KERNend = *firstaddr; - res = atop(KERNend - (vm_paddr_t)kernphys); + res = atop(*firstaddr - (vm_paddr_t)kernphys); if (!pti) pg_g = X86_PG_G; @@ -1750,7 +1755,7 @@ mpte->pindex = pmap_pde_pindex(KERNBASE) + i; mpte->phys_addr = KPTphys + (i << PAGE_SHIFT); mpte->wire_count = 1; - if (i << PDRSHIFT < KERNend && + if (i < kern_promoted_end && pmap_insert_pt_page(kernel_pmap, mpte)) panic("pmap_init: pmap_insert_pt_page failed"); } @@ -4553,10 +4558,9 @@ /* * If the page table page is new, initialize it. */ - if (mpte->wire_count == 1) { - mpte->wire_count = NPTEPG; + if ((oldpde & PG_PROMOTED) == 0) pmap_fill_ptp(firstpte, newpte); - } + KASSERT((*firstpte & PG_FRAME) == (newpte & PG_FRAME), ("pmap_demote_pde: firstpte and newpte map different physical" " addresses"));