* pmap_remove_pte: do the things to unmap a page in a process */
| 5906 | * pmap_remove_pte: do the things to unmap a page in a process |
| 5907 | */ |
| 5908 | static int |
| 5909 | pmap_remove_pte(pmap_t pmap, pt_entry_t *ptq, vm_offset_t va, |
| 5910 | pd_entry_t ptepde, struct spglist *free, struct rwlock **lockp) |
| 5911 | { |
| 5912 | struct md_page *pvh; |
| 5913 | pt_entry_t oldpte, PG_A, PG_M, PG_RW; |
| 5914 | vm_page_t m; |
| 5915 | |
| 5916 | PG_A = pmap_accessed_bit(pmap); |
| 5917 | PG_M = pmap_modified_bit(pmap); |
| 5918 | PG_RW = pmap_rw_bit(pmap); |
| 5919 | |
| 5920 | PMAP_LOCK_ASSERT(pmap, MA_OWNED); |
| 5921 | oldpte = pte_load_clear(ptq); |
| 5922 | if (oldpte & PG_W) |
| 5923 | pmap->pm_stats.wired_count -= 1; |
| 5924 | pmap_resident_count_dec(pmap, 1); |
| 5925 | if (oldpte & PG_MANAGED) { |
| 5926 | m = PHYS_TO_VM_PAGE(oldpte & PG_FRAME); |
| 5927 | if ((oldpte & (PG_M | PG_RW)) == (PG_M | PG_RW)) |
| 5928 | vm_page_dirty(m); |
| 5929 | if (oldpte & PG_A) |
| 5930 | vm_page_aflag_set(m, PGA_REFERENCED); |
| 5931 | CHANGE_PV_LIST_LOCK_TO_VM_PAGE(lockp, m); |
| 5932 | pmap_pvh_free(&m->md, pmap, va); |
| 5933 | if (TAILQ_EMPTY(&m->md.pv_list) && |
| 5934 | (m->flags & PG_FICTITIOUS) == 0) { |
| 5935 | pvh = pa_to_pvh(VM_PAGE_TO_PHYS(m)); |
| 5936 | if (TAILQ_EMPTY(&pvh->pv_list)) |
| 5937 | vm_page_aflag_clear(m, PGA_WRITEABLE); |
| 5938 | } |
| 5939 | pmap_delayed_invl_page(m); |
| 5940 | } |
| 5941 | return (pmap_unuse_pt(pmap, va, ptepde, free)); |
| 5942 | } |
| 5943 | |
| 5944 | /* |
| 5945 | * Remove a single page from a process address space |
no test coverage detected