* Clear the modify bits on the specified physical page. */
| 5785 | * Clear the modify bits on the specified physical page. |
| 5786 | */ |
| 5787 | void |
| 5788 | pmap_clear_modify(vm_page_t m) |
| 5789 | { |
| 5790 | struct md_page *pvh; |
| 5791 | struct rwlock *lock; |
| 5792 | pmap_t pmap; |
| 5793 | pv_entry_t next_pv, pv; |
| 5794 | pd_entry_t *l2, oldl2; |
| 5795 | pt_entry_t *l3, oldl3; |
| 5796 | vm_offset_t va; |
| 5797 | int md_gen, pvh_gen; |
| 5798 | |
| 5799 | KASSERT((m->oflags & VPO_UNMANAGED) == 0, |
| 5800 | ("pmap_clear_modify: page %p is not managed", m)); |
| 5801 | vm_page_assert_busied(m); |
| 5802 | |
| 5803 | if (!pmap_page_is_write_mapped(m)) |
| 5804 | return; |
| 5805 | pvh = (m->flags & PG_FICTITIOUS) != 0 ? &pv_dummy : page_to_pvh(m); |
| 5806 | lock = VM_PAGE_TO_PV_LIST_LOCK(m); |
| 5807 | rw_wlock(lock); |
| 5808 | restart: |
| 5809 | TAILQ_FOREACH_SAFE(pv, &pvh->pv_list, pv_next, next_pv) { |
| 5810 | pmap = PV_PMAP(pv); |
| 5811 | PMAP_ASSERT_STAGE1(pmap); |
| 5812 | if (!PMAP_TRYLOCK(pmap)) { |
| 5813 | pvh_gen = pvh->pv_gen; |
| 5814 | rw_wunlock(lock); |
| 5815 | PMAP_LOCK(pmap); |
| 5816 | rw_wlock(lock); |
| 5817 | if (pvh_gen != pvh->pv_gen) { |
| 5818 | PMAP_UNLOCK(pmap); |
| 5819 | goto restart; |
| 5820 | } |
| 5821 | } |
| 5822 | va = pv->pv_va; |
| 5823 | l2 = pmap_l2(pmap, va); |
| 5824 | oldl2 = pmap_load(l2); |
| 5825 | /* If oldl2 has ATTR_SW_DBM set, then it is also dirty. */ |
| 5826 | if ((oldl2 & ATTR_SW_DBM) != 0 && |
| 5827 | pmap_demote_l2_locked(pmap, l2, va, &lock) && |
| 5828 | (oldl2 & ATTR_SW_WIRED) == 0) { |
| 5829 | /* |
| 5830 | * Write protect the mapping to a single page so that |
| 5831 | * a subsequent write access may repromote. |
| 5832 | */ |
| 5833 | va += VM_PAGE_TO_PHYS(m) - (oldl2 & ~ATTR_MASK); |
| 5834 | l3 = pmap_l2_to_l3(l2, va); |
| 5835 | oldl3 = pmap_load(l3); |
| 5836 | while (!atomic_fcmpset_long(l3, &oldl3, |
| 5837 | (oldl3 & ~ATTR_SW_DBM) | ATTR_S1_AP(ATTR_S1_AP_RO))) |
| 5838 | cpu_spinwait(); |
| 5839 | vm_page_dirty(m); |
| 5840 | pmap_invalidate_page(pmap, va); |
| 5841 | } |
| 5842 | PMAP_UNLOCK(pmap); |
| 5843 | } |
| 5844 | TAILQ_FOREACH(pv, &m->md.pv_list, pv_next) { |
nothing calls this directly
no test coverage detected