* pmap_remove_pte: do the things to unmap a page in a process * * Returns true if this was the last PTE in the PT (and possibly the last PT in * the PD, and possibly the last PD in the segmap), in which case... * * 1) the TLB has been invalidated for the whole PT's span (at least), * already, to ensure that MipsDoTLBMiss does not attempt to follow a * dangling pointer into a freed pag
| 1759 | * entry, PD, and PT all remain in place). |
| 1760 | */ |
| 1761 | static int |
| 1762 | pmap_remove_pte(struct pmap *pmap, pt_entry_t *ptq, vm_offset_t va, |
| 1763 | pd_entry_t pde) |
| 1764 | { |
| 1765 | pt_entry_t oldpte; |
| 1766 | vm_page_t m; |
| 1767 | vm_paddr_t pa; |
| 1768 | |
| 1769 | rw_assert(&pvh_global_lock, RA_WLOCKED); |
| 1770 | PMAP_LOCK_ASSERT(pmap, MA_OWNED); |
| 1771 | |
| 1772 | /* |
| 1773 | * Write back all cache lines from the page being unmapped. |
| 1774 | */ |
| 1775 | mips_dcache_wbinv_range_index(va, PAGE_SIZE); |
| 1776 | |
| 1777 | oldpte = *ptq; |
| 1778 | if (is_kernel_pmap(pmap)) |
| 1779 | *ptq = PTE_G; |
| 1780 | else |
| 1781 | *ptq = 0; |
| 1782 | |
| 1783 | if (pte_test(&oldpte, PTE_W)) |
| 1784 | pmap->pm_stats.wired_count -= 1; |
| 1785 | |
| 1786 | pmap->pm_stats.resident_count -= 1; |
| 1787 | |
| 1788 | if (pte_test(&oldpte, PTE_MANAGED)) { |
| 1789 | pa = TLBLO_PTE_TO_PA(oldpte); |
| 1790 | m = PHYS_TO_VM_PAGE(pa); |
| 1791 | if (pte_test(&oldpte, PTE_D)) { |
| 1792 | KASSERT(!pte_test(&oldpte, PTE_RO), |
| 1793 | ("%s: modified page not writable: va: %p, pte: %#jx", |
| 1794 | __func__, (void *)va, (uintmax_t)oldpte)); |
| 1795 | vm_page_dirty(m); |
| 1796 | } |
| 1797 | if (m->md.pv_flags & PV_TABLE_REF) |
| 1798 | vm_page_aflag_set(m, PGA_REFERENCED); |
| 1799 | m->md.pv_flags &= ~PV_TABLE_REF; |
| 1800 | |
| 1801 | pmap_remove_entry(pmap, m, va); |
| 1802 | } |
| 1803 | return (pmap_unuse_pt(pmap, va, pde)); |
| 1804 | } |
| 1805 | |
| 1806 | /* |
| 1807 | * Remove a single page from a process address space |
no test coverage detected