* Clear the modify bits on the specified physical page. */
| 5672 | * Clear the modify bits on the specified physical page. |
| 5673 | */ |
| 5674 | void |
| 5675 | pmap_clear_modify(vm_page_t m) |
| 5676 | { |
| 5677 | struct md_page *pvh; |
| 5678 | pv_entry_t next_pv, pv; |
| 5679 | pmap_t pmap; |
| 5680 | pt1_entry_t *pte1p, opte1; |
| 5681 | pt2_entry_t *pte2p, opte2; |
| 5682 | vm_offset_t va; |
| 5683 | |
| 5684 | KASSERT((m->oflags & VPO_UNMANAGED) == 0, |
| 5685 | ("%s: page %p is not managed", __func__, m)); |
| 5686 | vm_page_assert_busied(m); |
| 5687 | |
| 5688 | if (!pmap_page_is_write_mapped(m)) |
| 5689 | return; |
| 5690 | rw_wlock(&pvh_global_lock); |
| 5691 | sched_pin(); |
| 5692 | if ((m->flags & PG_FICTITIOUS) != 0) |
| 5693 | goto small_mappings; |
| 5694 | pvh = pa_to_pvh(VM_PAGE_TO_PHYS(m)); |
| 5695 | TAILQ_FOREACH_SAFE(pv, &pvh->pv_list, pv_next, next_pv) { |
| 5696 | va = pv->pv_va; |
| 5697 | pmap = PV_PMAP(pv); |
| 5698 | PMAP_LOCK(pmap); |
| 5699 | pte1p = pmap_pte1(pmap, va); |
| 5700 | opte1 = pte1_load(pte1p); |
| 5701 | if (!(opte1 & PTE1_RO)) { |
| 5702 | if (pmap_demote_pte1(pmap, pte1p, va) && |
| 5703 | !pte1_is_wired(opte1)) { |
| 5704 | /* |
| 5705 | * Write protect the mapping to a |
| 5706 | * single page so that a subsequent |
| 5707 | * write access may repromote. |
| 5708 | */ |
| 5709 | va += VM_PAGE_TO_PHYS(m) - pte1_pa(opte1); |
| 5710 | pte2p = pmap_pte2_quick(pmap, va); |
| 5711 | opte2 = pte2_load(pte2p); |
| 5712 | if ((opte2 & PTE2_V)) { |
| 5713 | pte2_set_bit(pte2p, PTE2_NM | PTE2_RO); |
| 5714 | vm_page_dirty(m); |
| 5715 | pmap_tlb_flush(pmap, va); |
| 5716 | } |
| 5717 | } |
| 5718 | } |
| 5719 | PMAP_UNLOCK(pmap); |
| 5720 | } |
| 5721 | small_mappings: |
| 5722 | TAILQ_FOREACH(pv, &m->md.pv_list, pv_next) { |
| 5723 | pmap = PV_PMAP(pv); |
| 5724 | PMAP_LOCK(pmap); |
| 5725 | pte1p = pmap_pte1(pmap, pv->pv_va); |
| 5726 | KASSERT(!pte1_is_section(pte1_load(pte1p)), ("%s: found" |
| 5727 | " a section in page %p's pv list", __func__, m)); |
| 5728 | pte2p = pmap_pte2_quick(pmap, pv->pv_va); |
| 5729 | if (pte2_is_dirty(pte2_load(pte2p))) { |
| 5730 | pte2_set_bit(pte2p, PTE2_NM); |
| 5731 | pmap_tlb_flush(pmap, pv->pv_va); |
nothing calls this directly
no test coverage detected