* pmap_remove_pde: do the things to unmap a superpage in a process */
| 2969 | * pmap_remove_pde: do the things to unmap a superpage in a process |
| 2970 | */ |
| 2971 | static void |
| 2972 | pmap_remove_pde(pmap_t pmap, pd_entry_t *pdq, vm_offset_t sva, |
| 2973 | struct spglist *free) |
| 2974 | { |
| 2975 | struct md_page *pvh; |
| 2976 | pd_entry_t oldpde; |
| 2977 | vm_offset_t eva, va; |
| 2978 | vm_page_t m, mpte; |
| 2979 | |
| 2980 | PMAP_LOCK_ASSERT(pmap, MA_OWNED); |
| 2981 | KASSERT((sva & PDRMASK) == 0, |
| 2982 | ("pmap_remove_pde: sva is not 4mpage aligned")); |
| 2983 | oldpde = pte_load_clear(pdq); |
| 2984 | if (oldpde & PG_W) |
| 2985 | pmap->pm_stats.wired_count -= NBPDR / PAGE_SIZE; |
| 2986 | |
| 2987 | /* |
| 2988 | * Machines that don't support invlpg, also don't support |
| 2989 | * PG_G. |
| 2990 | */ |
| 2991 | if ((oldpde & PG_G) != 0) |
| 2992 | pmap_invalidate_pde_page(kernel_pmap, sva, oldpde); |
| 2993 | |
| 2994 | pmap->pm_stats.resident_count -= NBPDR / PAGE_SIZE; |
| 2995 | if (oldpde & PG_MANAGED) { |
| 2996 | pvh = pa_to_pvh(oldpde & PG_PS_FRAME); |
| 2997 | pmap_pvh_free(pvh, pmap, sva); |
| 2998 | eva = sva + NBPDR; |
| 2999 | for (va = sva, m = PHYS_TO_VM_PAGE(oldpde & PG_PS_FRAME); |
| 3000 | va < eva; va += PAGE_SIZE, m++) { |
| 3001 | if ((oldpde & (PG_M | PG_RW)) == (PG_M | PG_RW)) |
| 3002 | vm_page_dirty(m); |
| 3003 | if (oldpde & PG_A) |
| 3004 | vm_page_aflag_set(m, PGA_REFERENCED); |
| 3005 | if (TAILQ_EMPTY(&m->md.pv_list) && |
| 3006 | TAILQ_EMPTY(&pvh->pv_list)) |
| 3007 | vm_page_aflag_clear(m, PGA_WRITEABLE); |
| 3008 | } |
| 3009 | } |
| 3010 | if (pmap == kernel_pmap) { |
| 3011 | pmap_remove_kernel_pde(pmap, pdq, sva); |
| 3012 | } else { |
| 3013 | mpte = pmap_remove_pt_page(pmap, sva); |
| 3014 | if (mpte != NULL) { |
| 3015 | KASSERT(mpte->valid == VM_PAGE_BITS_ALL, |
| 3016 | ("pmap_remove_pde: pte page not promoted")); |
| 3017 | pmap->pm_stats.resident_count--; |
| 3018 | KASSERT(mpte->ref_count == NPTEPG, |
| 3019 | ("pmap_remove_pde: pte page ref count error")); |
| 3020 | mpte->ref_count = 0; |
| 3021 | pmap_add_delayed_free_list(mpte, free, FALSE); |
| 3022 | } |
| 3023 | } |
| 3024 | } |
| 3025 | |
| 3026 | /* |
| 3027 | * pmap_remove_pte: do the things to unmap a page in a process |
no test coverage detected