* pmap_remove_pde: do the things to unmap a superpage in a process */
| 5845 | * pmap_remove_pde: do the things to unmap a superpage in a process |
| 5846 | */ |
| 5847 | static int |
| 5848 | pmap_remove_pde(pmap_t pmap, pd_entry_t *pdq, vm_offset_t sva, |
| 5849 | struct spglist *free, struct rwlock **lockp) |
| 5850 | { |
| 5851 | struct md_page *pvh; |
| 5852 | pd_entry_t oldpde; |
| 5853 | vm_offset_t eva, va; |
| 5854 | vm_page_t m, mpte; |
| 5855 | pt_entry_t PG_G, PG_A, PG_M, PG_RW; |
| 5856 | |
| 5857 | PG_G = pmap_global_bit(pmap); |
| 5858 | PG_A = pmap_accessed_bit(pmap); |
| 5859 | PG_M = pmap_modified_bit(pmap); |
| 5860 | PG_RW = pmap_rw_bit(pmap); |
| 5861 | |
| 5862 | PMAP_LOCK_ASSERT(pmap, MA_OWNED); |
| 5863 | KASSERT((sva & PDRMASK) == 0, |
| 5864 | ("pmap_remove_pde: sva is not 2mpage aligned")); |
| 5865 | oldpde = pte_load_clear(pdq); |
| 5866 | if (oldpde & PG_W) |
| 5867 | pmap->pm_stats.wired_count -= NBPDR / PAGE_SIZE; |
| 5868 | if ((oldpde & PG_G) != 0) |
| 5869 | pmap_invalidate_pde_page(kernel_pmap, sva, oldpde); |
| 5870 | pmap_resident_count_dec(pmap, NBPDR / PAGE_SIZE); |
| 5871 | if (oldpde & PG_MANAGED) { |
| 5872 | CHANGE_PV_LIST_LOCK_TO_PHYS(lockp, oldpde & PG_PS_FRAME); |
| 5873 | pvh = pa_to_pvh(oldpde & PG_PS_FRAME); |
| 5874 | pmap_pvh_free(pvh, pmap, sva); |
| 5875 | eva = sva + NBPDR; |
| 5876 | for (va = sva, m = PHYS_TO_VM_PAGE(oldpde & PG_PS_FRAME); |
| 5877 | va < eva; va += PAGE_SIZE, m++) { |
| 5878 | if ((oldpde & (PG_M | PG_RW)) == (PG_M | PG_RW)) |
| 5879 | vm_page_dirty(m); |
| 5880 | if (oldpde & PG_A) |
| 5881 | vm_page_aflag_set(m, PGA_REFERENCED); |
| 5882 | if (TAILQ_EMPTY(&m->md.pv_list) && |
| 5883 | TAILQ_EMPTY(&pvh->pv_list)) |
| 5884 | vm_page_aflag_clear(m, PGA_WRITEABLE); |
| 5885 | pmap_delayed_invl_page(m); |
| 5886 | } |
| 5887 | } |
| 5888 | if (pmap == kernel_pmap) { |
| 5889 | pmap_remove_kernel_pde(pmap, pdq, sva); |
| 5890 | } else { |
| 5891 | mpte = pmap_remove_pt_page(pmap, sva); |
| 5892 | if (mpte != NULL) { |
| 5893 | KASSERT(mpte->valid == VM_PAGE_BITS_ALL, |
| 5894 | ("pmap_remove_pde: pte page not promoted")); |
| 5895 | pmap_resident_count_dec(pmap, 1); |
| 5896 | KASSERT(mpte->ref_count == NPTEPG, |
| 5897 | ("pmap_remove_pde: pte page ref count error")); |
| 5898 | mpte->ref_count = 0; |
| 5899 | pmap_add_delayed_free_list(mpte, free, FALSE); |
| 5900 | } |
| 5901 | } |
| 5902 | return (pmap_unuse_pt(pmap, sva, *pmap_pdpe(pmap, sva), free)); |
| 5903 | } |
| 5904 |
no test coverage detected