* Remove the specified range of addresses from the L3 page table that is * identified by the given L2 entry. */
| 2947 | * identified by the given L2 entry. |
| 2948 | */ |
| 2949 | static void |
| 2950 | pmap_remove_l3_range(pmap_t pmap, pd_entry_t l2e, vm_offset_t sva, |
| 2951 | vm_offset_t eva, struct spglist *free, struct rwlock **lockp) |
| 2952 | { |
| 2953 | struct md_page *pvh; |
| 2954 | struct rwlock *new_lock; |
| 2955 | pt_entry_t *l3, old_l3; |
| 2956 | vm_offset_t va; |
| 2957 | vm_page_t l3pg, m; |
| 2958 | |
| 2959 | PMAP_LOCK_ASSERT(pmap, MA_OWNED); |
| 2960 | KASSERT(rounddown2(sva, L2_SIZE) + L2_SIZE == roundup2(eva, L2_SIZE), |
| 2961 | ("pmap_remove_l3_range: range crosses an L3 page table boundary")); |
| 2962 | l3pg = sva < VM_MAXUSER_ADDRESS ? PHYS_TO_VM_PAGE(l2e & ~ATTR_MASK) : |
| 2963 | NULL; |
| 2964 | va = eva; |
| 2965 | for (l3 = pmap_l2_to_l3(&l2e, sva); sva != eva; l3++, sva += L3_SIZE) { |
| 2966 | if (!pmap_l3_valid(pmap_load(l3))) { |
| 2967 | if (va != eva) { |
| 2968 | pmap_invalidate_range(pmap, va, sva); |
| 2969 | va = eva; |
| 2970 | } |
| 2971 | continue; |
| 2972 | } |
| 2973 | old_l3 = pmap_load_clear(l3); |
| 2974 | if ((old_l3 & ATTR_SW_WIRED) != 0) |
| 2975 | pmap->pm_stats.wired_count--; |
| 2976 | pmap_resident_count_dec(pmap, 1); |
| 2977 | if ((old_l3 & ATTR_SW_MANAGED) != 0) { |
| 2978 | m = PHYS_TO_VM_PAGE(old_l3 & ~ATTR_MASK); |
| 2979 | if (pmap_pte_dirty(pmap, old_l3)) |
| 2980 | vm_page_dirty(m); |
| 2981 | if ((old_l3 & ATTR_AF) != 0) |
| 2982 | vm_page_aflag_set(m, PGA_REFERENCED); |
| 2983 | new_lock = PHYS_TO_PV_LIST_LOCK(VM_PAGE_TO_PHYS(m)); |
| 2984 | if (new_lock != *lockp) { |
| 2985 | if (*lockp != NULL) { |
| 2986 | /* |
| 2987 | * Pending TLB invalidations must be |
| 2988 | * performed before the PV list lock is |
| 2989 | * released. Otherwise, a concurrent |
| 2990 | * pmap_remove_all() on a physical page |
| 2991 | * could return while a stale TLB entry |
| 2992 | * still provides access to that page. |
| 2993 | */ |
| 2994 | if (va != eva) { |
| 2995 | pmap_invalidate_range(pmap, va, |
| 2996 | sva); |
| 2997 | va = eva; |
| 2998 | } |
| 2999 | rw_wunlock(*lockp); |
| 3000 | } |
| 3001 | *lockp = new_lock; |
| 3002 | rw_wlock(*lockp); |
| 3003 | } |
| 3004 | pmap_pvh_free(&m->md, pmap, sva); |
| 3005 | if (TAILQ_EMPTY(&m->md.pv_list) && |
| 3006 | (m->flags & PG_FICTITIOUS) == 0) { |
no test coverage detected