* Clear the modify bits on the specified physical page. */
| 8809 | * Clear the modify bits on the specified physical page. |
| 8810 | */ |
| 8811 | void |
| 8812 | pmap_clear_modify(vm_page_t m) |
| 8813 | { |
| 8814 | struct md_page *pvh; |
| 8815 | pmap_t pmap; |
| 8816 | pv_entry_t next_pv, pv; |
| 8817 | pd_entry_t oldpde, *pde; |
| 8818 | pt_entry_t *pte, PG_M, PG_RW; |
| 8819 | struct rwlock *lock; |
| 8820 | vm_offset_t va; |
| 8821 | int md_gen, pvh_gen; |
| 8822 | |
| 8823 | KASSERT((m->oflags & VPO_UNMANAGED) == 0, |
| 8824 | ("pmap_clear_modify: page %p is not managed", m)); |
| 8825 | vm_page_assert_busied(m); |
| 8826 | |
| 8827 | if (!pmap_page_is_write_mapped(m)) |
| 8828 | return; |
| 8829 | pvh = (m->flags & PG_FICTITIOUS) != 0 ? &pv_dummy : |
| 8830 | pa_to_pvh(VM_PAGE_TO_PHYS(m)); |
| 8831 | lock = VM_PAGE_TO_PV_LIST_LOCK(m); |
| 8832 | rw_wlock(lock); |
| 8833 | restart: |
| 8834 | TAILQ_FOREACH_SAFE(pv, &pvh->pv_list, pv_next, next_pv) { |
| 8835 | pmap = PV_PMAP(pv); |
| 8836 | if (!PMAP_TRYLOCK(pmap)) { |
| 8837 | pvh_gen = pvh->pv_gen; |
| 8838 | rw_wunlock(lock); |
| 8839 | PMAP_LOCK(pmap); |
| 8840 | rw_wlock(lock); |
| 8841 | if (pvh_gen != pvh->pv_gen) { |
| 8842 | PMAP_UNLOCK(pmap); |
| 8843 | goto restart; |
| 8844 | } |
| 8845 | } |
| 8846 | PG_M = pmap_modified_bit(pmap); |
| 8847 | PG_RW = pmap_rw_bit(pmap); |
| 8848 | va = pv->pv_va; |
| 8849 | pde = pmap_pde(pmap, va); |
| 8850 | oldpde = *pde; |
| 8851 | /* If oldpde has PG_RW set, then it also has PG_M set. */ |
| 8852 | if ((oldpde & PG_RW) != 0 && |
| 8853 | pmap_demote_pde_locked(pmap, pde, va, &lock) && |
| 8854 | (oldpde & PG_W) == 0) { |
| 8855 | /* |
| 8856 | * Write protect the mapping to a single page so that |
| 8857 | * a subsequent write access may repromote. |
| 8858 | */ |
| 8859 | va += VM_PAGE_TO_PHYS(m) - (oldpde & PG_PS_FRAME); |
| 8860 | pte = pmap_pde_to_pte(pde, va); |
| 8861 | atomic_clear_long(pte, PG_M | PG_RW); |
| 8862 | vm_page_dirty(m); |
| 8863 | pmap_invalidate_page(pmap, va); |
| 8864 | } |
| 8865 | PMAP_UNLOCK(pmap); |
| 8866 | } |
| 8867 | TAILQ_FOREACH(pv, &m->md.pv_list, pv_next) { |
| 8868 | pmap = PV_PMAP(pv); |
nothing calls this directly
no test coverage detected