FreeBSD/sys/arm/arm/pmap-v6.c
/*
 *  Clear the write and modified bits in each of the given page's mappings.
 */
Clear the write and modified bits in each of the given page's mappings.
Clear the write and modified bits in each of the given page ' s mappings .
void
pmap_remove_write(vm_page_t m)
{
	struct md_page *pvh;
	pv_entry_t next_pv, pv;
	pmap_t pmap;
	pt1_entry_t *pte1p;
	pt2_entry_t *pte2p, opte2;
	vm_offset_t va;
	KASSERT((m->oflags & VPO_UNMANAGED) == 0,
	    ("%s: page %p is not managed", __func__, m));
	VM_OBJECT_ASSERT_WLOCKED(m->object);
	if (!vm_page_xbusied(m) && (m->aflags & PGA_WRITEABLE) == 0)
		return;
	rw_wlock(&pvh_global_lock);
	sched_pin();
	if ((m->flags & PG_FICTITIOUS) != 0)
		goto small_mappings;
	pvh = pa_to_pvh(VM_PAGE_TO_PHYS(m));
	TAILQ_FOREACH_SAFE(pv, &pvh->pv_list, pv_next, next_pv) {
		va = pv->pv_va;
		pmap = PV_PMAP(pv);
		PMAP_LOCK(pmap);
		pte1p = pmap_pte1(pmap, va);
		if (!(pte1_load(pte1p) & PTE1_RO))
			(void)pmap_demote_pte1(pmap, pte1p, va);
		PMAP_UNLOCK(pmap);
	}
small_mappings:
	TAILQ_FOREACH(pv, &m->md.pv_list, pv_next) {
		pmap = PV_PMAP(pv);
		PMAP_LOCK(pmap);
		pte1p = pmap_pte1(pmap, pv->pv_va);
		KASSERT(!pte1_is_section(pte1_load(pte1p)), ("%s: found"
		    " a section in page %p's pv list", __func__, m));
		pte2p = pmap_pte2_quick(pmap, pv->pv_va);
		opte2 = pte2_load(pte2p);
		if (!(opte2 & PTE2_RO)) {
			pte2_store(pte2p, opte2 | PTE2_RO | PTE2_NM);
			if (pte2_is_dirty(opte2))
				vm_page_dirty(m);
			pmap_tlb_flush(pmap, pv->pv_va);
		}
		PMAP_UNLOCK(pmap);
	}
	vm_page_aflag_clear(m, PGA_WRITEABLE);
	sched_unpin();
	rw_wunlock(&pvh_global_lock);
}
void pmap_remove_write ( vm_page_t m ) { struct md_page * pvh ; pv_entry_t next_pv , pv ; pmap_t pmap ; pt1_entry_t * pte1p ; pt2_entry_t * pte2p , opte2 ; vm_offset_t va ; KASSERT ( ( m -> oflags & VPO_UNMANAGED ) == 0 , ( " " , __func__ , m ) ) ; VM_OBJECT_ASSERT_WLOCKED ( m -> object ) ; if ( ! vm_page_xbusied ( m ) && ( m -> aflags & PGA_WRITEABLE ) == 0 ) return ; rw_wlock ( & pvh_global_lock ) ; sched_pin ( ) ; if ( ( m -> flags & PG_FICTITIOUS ) != 0 ) goto small_mappings ; pvh = pa_to_pvh ( VM_PAGE_TO_PHYS ( m ) ) ; TAILQ_FOREACH_SAFE ( pv , & pvh -> pv_list , pv_next , next_pv ) { va = pv -> pv_va ; pmap = PV_PMAP ( pv ) ; PMAP_LOCK ( pmap ) ; pte1p = pmap_pte1 ( pmap , va ) ; if ( ! ( pte1_load ( pte1p ) & PTE1_RO ) ) ( void ) pmap_demote_pte1 ( pmap , pte1p , va ) ; PMAP_UNLOCK ( pmap ) ; } small_mappings : TAILQ_FOREACH ( pv , & m -> md . pv_list , pv_next ) { pmap = PV_PMAP ( pv ) ; PMAP_LOCK ( pmap ) ; pte1p = pmap_pte1 ( pmap , pv -> pv_va ) ; KASSERT ( ! pte1_is_section ( pte1_load ( pte1p ) ) , ( " " " " , __func__ , m ) ) ; pte2p = pmap_pte2_quick ( pmap , pv -> pv_va ) ; opte2 = pte2_load ( pte2p ) ; if ( ! ( opte2 & PTE2_RO ) ) { pte2_store ( pte2p , opte2 | PTE2_RO | PTE2_NM ) ; if ( pte2_is_dirty ( opte2 ) ) vm_page_dirty ( m ) ; pmap_tlb_flush ( pmap , pv -> pv_va ) ; } PMAP_UNLOCK ( pmap ) ; } vm_page_aflag_clear ( m , PGA_WRITEABLE ) ; sched_unpin ( ) ; rw_wunlock ( & pvh_global_lock ) ; }
Clear the write and modified bits in each of the given page's mappings.
Clear the write and modified bits in each of the given page ' s mappings .
/*
	 * If the page is not exclusive busied, then PGA_WRITEABLE cannot be
	 * set by another thread while the object is locked.  Thus,
	 * if PGA_WRITEABLE is clear, no page table entries need updating.
	 */