From owner-p4-projects@FreeBSD.ORG Tue Apr 11 17:23:39 2006 Return-Path: X-Original-To: p4-projects@freebsd.org Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 720E716A47C; Tue, 11 Apr 2006 17:23:39 +0000 (UTC) X-Original-To: perforce@freebsd.org Delivered-To: perforce@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 1DD1916A44A for ; Tue, 11 Apr 2006 17:23:39 +0000 (UTC) (envelope-from alc@freebsd.org) Received: from repoman.freebsd.org (repoman.freebsd.org [216.136.204.115]) by mx1.FreeBSD.org (Postfix) with ESMTP id B48E843D48 for ; Tue, 11 Apr 2006 17:23:38 +0000 (GMT) (envelope-from alc@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.13.1/8.13.1) with ESMTP id k3BHNcgH032115 for ; Tue, 11 Apr 2006 17:23:38 GMT (envelope-from alc@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.13.1/8.13.1/Submit) id k3BHNc1h032112 for perforce@freebsd.org; Tue, 11 Apr 2006 17:23:38 GMT (envelope-from alc@freebsd.org) Date: Tue, 11 Apr 2006 17:23:38 GMT Message-Id: <200604111723.k3BHNc1h032112@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to alc@freebsd.org using -f From: Alan Cox To: Perforce Change Reviews Cc: Subject: PERFORCE change 95000 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 11 Apr 2006 17:23:39 -0000 http://perforce.freebsd.org/chv.cgi?CH=95000 Change 95000 by alc@alc_home on 2006/04/11 17:23:10 IF user/alc/superpages Catch up with the change to pmap_remove_pages()'s parameters. Clean up code. Avoid kernel pmap page table page leaks on promotion of kernel pages. Affected files ... .. //depot/projects/superpages/src/sys/amd64/amd64/pmap.c#15 integrate Differences ... ==== //depot/projects/superpages/src/sys/amd64/amd64/pmap.c#15 (text+ko) ==== @@ -208,6 +208,8 @@ static pv_entry_t get_pv_entry(pmap_t locked_pmap); static void pmap_clear_ptes(vm_page_t m, long bit); +static boolean_t pmap_demote_pde(pmap_t pmap, pd_entry_t *pde, vm_offset_t va); +static void pmap_promote_pde(pmap_t pmap, pd_entry_t *pde, reservation_t reserv); static boolean_t pmap_protect_pde(pmap_t pmap, pd_entry_t *pde, vm_offset_t sva); static int pmap_remove_pde(pmap_t pmap, pd_entry_t *pdq, vm_offset_t sva); static int pmap_remove_pte(pmap_t pmap, pt_entry_t *ptq, @@ -227,9 +229,6 @@ static int pmap_unuse_pt(pmap_t, vm_offset_t, pd_entry_t); static vm_offset_t pmap_kmem_choose(vm_offset_t addr); -static void mach_promote(pmap_t pmap, pd_entry_t *pde, reservation_t reserv); -static boolean_t pmap_demote(pmap_t pmap, pd_entry_t *pde, vm_offset_t va); - CTASSERT(1 << PDESHIFT == sizeof(pd_entry_t)); CTASSERT(1 << PTESHIFT == sizeof(pt_entry_t)); @@ -1291,7 +1290,7 @@ * normal 4K page. */ if (pd != 0 && (*pd & (PG_PS | PG_V)) == (PG_PS | PG_V)) { - if (!pmap_demote(pmap, pd, va)) { + if (!pmap_demote_pde(pmap, pd, va)) { /* * Invalidation of the 2MB page mapping may have caused * the deallocation of the underlying PD page. @@ -1500,7 +1499,7 @@ pmap->pm_stats.resident_count--; pde = pmap_pde(pmap, va); if ((*pde & PG_PS) != 0 && - !pmap_demote(pmap, pde, va)) { + !pmap_demote_pde(pmap, pde, va)) { /* * All mappings within the same 2mpage were * destroyed and pv was freed. @@ -1796,13 +1795,19 @@ if (sva + NBPDR == va_next && eva >= va_next) { DPRINTF(("pmap_remove: superpage at %lx to destroy.\n", sva)); + + /* + * The TLB entry for a PG_G mapping is + * invalidated by pmap_remove_pde(). + */ + if ((ptpaddr & PG_G) == 0) + anyvalid = 1; pmap_remove_pde(pmap, pde, sva); - anyvalid = 1; continue; } else { DPRINTF(("pmap_remove: superpage at %lx to demote !!!\n", sva)); - if (!pmap_demote(pmap, pde, sva)) { + if (!pmap_demote_pde(pmap, pde, sva)) { anyvalid = 1; /* XXX */ continue; } @@ -1878,7 +1883,7 @@ pde = pmap_pde(pmap, pv->pv_va); if (*pde & PG_PS) { DPRINTF(("pmap_remove_all: superpage to demote !!!\n")); - if (!pmap_demote(pmap, pde, pv->pv_va)) { + if (!pmap_demote_pde(pmap, pde, pv->pv_va)) { /* * All mappings within the same 2mpage were * destroyed and pv was freed. @@ -2017,7 +2022,7 @@ anychanged = 1; continue; } else { - if (!pmap_demote(pmap, pde, sva)) { + if (!pmap_demote_pde(pmap, pde, sva)) { anychanged = 1; /* XXX */ continue; } @@ -2262,7 +2267,7 @@ m->reserv->refcnt == NBPDR / PAGE_SIZE) { DPRINTF(("%s: pmap %p va %lx XXX\n", __func__, pmap, va)); KASSERT(m->object->flags & OBJ_SUPERPAGES, ("pmap_enter: xxx")); - mach_promote(pmap, pmap_pde(pmap, va), m->reserv); + pmap_promote_pde(pmap, pmap_pde(pmap, va), m->reserv); } vm_page_unlock_queues(); @@ -2392,7 +2397,7 @@ DPRINTF(("%s: pmap %p va %lx XXX\n", __func__, pmap, va)); KASSERT(m->object->flags & OBJ_SUPERPAGES, ("pmap_enter_quick: xxx")); - mach_promote(pmap, pmap_pde(pmap, va), m->reserv); + pmap_promote_pde(pmap, pmap_pde(pmap, va), m->reserv); } out: PMAP_UNLOCK(pmap); @@ -2799,24 +2804,11 @@ npv = TAILQ_NEXT(pv, pv_plist); continue; } - if (sva <= trunc_2mpage(pv->pv_va) && - eva >= round_2mpage(pv->pv_va + 1)) { - DPRINTF(("pmap_remove_pages: superpage at %lx to destroy.\n", - trunc_2mpage(pv->pv_va))); - pmap_remove_pde(pmap, pde, trunc_2mpage(pv->pv_va)); - npv = TAILQ_FIRST(&pmap->pm_pvlist); - continue; - } - DPRINTF(("pmap_remove_pages: superpage at %lx to demote !!!\n", - pv->pv_va)); - if (!pmap_demote(pmap, pde, pv->pv_va)) { - /* - * All mappings within the same 2mpage were - * destroyed and pv was freed. - */ - npv = TAILQ_FIRST(&pmap->pm_pvlist); - continue; - } + DPRINTF(("pmap_remove_pages: superpage at %lx to destroy.\n", + trunc_2mpage(pv->pv_va))); + pmap_remove_pde(pmap, pde, trunc_2mpage(pv->pv_va)); + npv = TAILQ_FIRST(&pmap->pm_pvlist); + continue; } #ifdef PMAP_REMOVE_PAGES_CURPROC_ONLY @@ -2970,7 +2962,7 @@ if (*pde & PG_PS) { DPRINTF(("pmap_clear_ptes: superpage to demote !!!\n")); if ((*pde & bit) == 0 || - !pmap_demote(pmap, pde, pv->pv_va)) { + !pmap_demote_pde(pmap, pde, pv->pv_va)) { /* * All mappings within the same 2mpage were * destroyed and pv was freed. @@ -3267,7 +3259,7 @@ #define COMPATIBLE_PTE(a,b) ((a & COMPATIBLE_PTE_MASK) == (b & COMPATIBLE_PTE_MASK)) static void -mach_promote(pmap_t pmap, pd_entry_t *pde, reservation_t reserv) +pmap_promote_pde(pmap_t pmap, pd_entry_t *pde, reservation_t reserv) { vm_paddr_t pa; pt_entry_t *pte, *first_pte, flags; @@ -3287,8 +3279,9 @@ pa += PAGE_SIZE; page_pa = PHYS_TO_VM_PAGE(*pte & PG_FRAME); - KASSERT(page_pa->reserv,("mach_promote: page has no reservation")); - KASSERT(page_pa->reserv == reserv,("mach_promote: reservation mismatch")); + KASSERT(page_pa->reserv,("pmap_promote_pde: page has no reservation")); + KASSERT(page_pa->reserv == reserv, + ("pmap_promote_pde: reservation mismatch")); if ((*pte & PG_V) == 0 || !COMPATIBLE_PTE(*pte, flags)) return; @@ -3306,15 +3299,10 @@ /* Invalidate old TLB entries */ pmap_invalidate_all(pmap); - /* - * XXX - * - * File system corruption occurs if pte pages belonging to the - * kernel pmap are freed. - */ - if (pmap != kernel_pmap) { + /* This leaks up to nkpt kernel pmap page table pages. XXX */ + if (pmap != kernel_pmap || tofree->wire_count == NPTEPG) { KASSERT(tofree->wire_count == NPTEPG, - ("pmap_promote: pte page wire count error")); + ("pmap_promote_pde: pte page wire count error")); tofree->wire_count = 0; vm_page_free(tofree); atomic_subtract_int(&cnt.v_wire_count, 1); @@ -3324,35 +3312,35 @@ } static boolean_t -pmap_demote(pmap_t pmap, pd_entry_t *pde0, vm_offset_t va) +pmap_demote_pde(pmap_t pmap, pd_entry_t *pde, vm_offset_t va) { pd_entry_t save_pde_value, new_pte_value ; pt_entry_t *pte_page_va, *new_pte_va; vm_paddr_t pte_page_pa; vm_page_t pte_page; - KASSERT((*pde0 & PG_PS) != 0, - ("pmap_demote: not a superpage, impossible to demote")); + KASSERT((*pde & PG_PS) != 0, + ("pmap_demote_pde: not a superpage, impossible to demote")); /* STEP 1 * Allocate the PTE page */ if ((pte_page = vm_page_alloc(NULL, pmap_pde_pindex(va), VM_ALLOC_NOOBJ | VM_ALLOC_NORMAL | VM_ALLOC_WIRED)) == NULL) { - pmap_remove_pde(pmap, pde0, trunc_2mpage(va)); + pmap_remove_pde(pmap, pde, trunc_2mpage(va)); pmap_invalidate_all(pmap); return (FALSE); } pte_page->wire_count += NPTEPG - 1; KASSERT(pte_page->wire_count == NPTEPG, - ("pmap_demote: page table page %p has wire count %d", + ("pmap_demote_pde: page table page %p has wire count %d", pte_page, pte_page->wire_count)); if (pmap != kernel_pmap) pmap->pm_stats.resident_count++; pte_page_pa = VM_PAGE_TO_PHYS(pte_page); pte_page_va = (vm_offset_t *) PHYS_TO_DMAP(pte_page_pa); - pte_page_pa |= PG_U | PG_RW | PG_V | PG_A | PG_M; + pte_page_pa |= PG_M | PG_A | (*pde & PG_U) | PG_RW | PG_V; repeat: @@ -3360,7 +3348,7 @@ * Save the value of the pde entry * Define the value of the first pte entry */ - save_pde_value = *pde0; + save_pde_value = *pde; /* STEP 3 * Fill the PTE page with the physical address of the base pages @@ -3378,7 +3366,7 @@ * If not, assign the new pde value. * If yes, repeat the pte assignment loop. */ - if (!atomic_cmpset_long(pde0, save_pde_value, pte_page_pa)) + if (!atomic_cmpset_long(pde, save_pde_value, pte_page_pa)) goto repeat; /*