* pmap_remove_l2: Do the things to unmap a level 2 superpage. */
| 2851 | * pmap_remove_l2: Do the things to unmap a level 2 superpage. |
| 2852 | */ |
| 2853 | static int |
| 2854 | pmap_remove_l2(pmap_t pmap, pt_entry_t *l2, vm_offset_t sva, |
| 2855 | pd_entry_t l1e, struct spglist *free, struct rwlock **lockp) |
| 2856 | { |
| 2857 | struct md_page *pvh; |
| 2858 | pt_entry_t old_l2; |
| 2859 | vm_offset_t eva, va; |
| 2860 | vm_page_t m, ml3; |
| 2861 | |
| 2862 | PMAP_LOCK_ASSERT(pmap, MA_OWNED); |
| 2863 | KASSERT((sva & L2_OFFSET) == 0, ("pmap_remove_l2: sva is not aligned")); |
| 2864 | old_l2 = pmap_load_clear(l2); |
| 2865 | KASSERT((old_l2 & ATTR_DESCR_MASK) == L2_BLOCK, |
| 2866 | ("pmap_remove_l2: L2e %lx is not a block mapping", old_l2)); |
| 2867 | |
| 2868 | /* |
| 2869 | * Since a promotion must break the 4KB page mappings before making |
| 2870 | * the 2MB page mapping, a pmap_invalidate_page() suffices. |
| 2871 | */ |
| 2872 | pmap_invalidate_page(pmap, sva); |
| 2873 | |
| 2874 | if (old_l2 & ATTR_SW_WIRED) |
| 2875 | pmap->pm_stats.wired_count -= L2_SIZE / PAGE_SIZE; |
| 2876 | pmap_resident_count_dec(pmap, L2_SIZE / PAGE_SIZE); |
| 2877 | if (old_l2 & ATTR_SW_MANAGED) { |
| 2878 | CHANGE_PV_LIST_LOCK_TO_PHYS(lockp, old_l2 & ~ATTR_MASK); |
| 2879 | pvh = pa_to_pvh(old_l2 & ~ATTR_MASK); |
| 2880 | pmap_pvh_free(pvh, pmap, sva); |
| 2881 | eva = sva + L2_SIZE; |
| 2882 | for (va = sva, m = PHYS_TO_VM_PAGE(old_l2 & ~ATTR_MASK); |
| 2883 | va < eva; va += PAGE_SIZE, m++) { |
| 2884 | if (pmap_pte_dirty(pmap, old_l2)) |
| 2885 | vm_page_dirty(m); |
| 2886 | if (old_l2 & ATTR_AF) |
| 2887 | vm_page_aflag_set(m, PGA_REFERENCED); |
| 2888 | if (TAILQ_EMPTY(&m->md.pv_list) && |
| 2889 | TAILQ_EMPTY(&pvh->pv_list)) |
| 2890 | vm_page_aflag_clear(m, PGA_WRITEABLE); |
| 2891 | } |
| 2892 | } |
| 2893 | if (pmap == kernel_pmap) { |
| 2894 | pmap_remove_kernel_l2(pmap, l2, sva); |
| 2895 | } else { |
| 2896 | ml3 = pmap_remove_pt_page(pmap, sva); |
| 2897 | if (ml3 != NULL) { |
| 2898 | KASSERT(ml3->valid == VM_PAGE_BITS_ALL, |
| 2899 | ("pmap_remove_l2: l3 page not promoted")); |
| 2900 | pmap_resident_count_dec(pmap, 1); |
| 2901 | KASSERT(ml3->ref_count == NL3PG, |
| 2902 | ("pmap_remove_l2: l3 page ref count error")); |
| 2903 | ml3->ref_count = 0; |
| 2904 | pmap_add_delayed_free_list(ml3, free, FALSE); |
| 2905 | } |
| 2906 | } |
| 2907 | return (pmap_unuse_pt(pmap, sva, l1e, free)); |
| 2908 | } |
| 2909 | |
| 2910 | /* |
no test coverage detected