FreeBSD/sys/arm64/arm64/pmap.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)
{
	pmap_t pmap;
	struct rwlock *lock;
	pv_entry_t pv;
	pt_entry_t oldpte, *pte;
	int lvl, md_gen;
	KASSERT((m->oflags & VPO_UNMANAGED) == 0,
	    ("pmap_remove_write: page %p is not managed", m));
	VM_OBJECT_ASSERT_WLOCKED(m->object);
	if (!vm_page_xbusied(m) && (m->aflags & PGA_WRITEABLE) == 0)
		return;
	rw_rlock(&pvh_global_lock);
	lock = VM_PAGE_TO_PV_LIST_LOCK(m);
retry_pv_loop:
	rw_wlock(lock);
	TAILQ_FOREACH(pv, &m->md.pv_list, pv_next) {
		pmap = PV_PMAP(pv);
		if (!PMAP_TRYLOCK(pmap)) {
			md_gen = m->md.pv_gen;
			rw_wunlock(lock);
			PMAP_LOCK(pmap);
			rw_wlock(lock);
			if (md_gen != m->md.pv_gen) {
				PMAP_UNLOCK(pmap);
				rw_wunlock(lock);
				goto retry_pv_loop;
			}
		}
		pte = pmap_pte(pmap, pv->pv_va, &lvl);
retry:
		oldpte = pmap_load(pte);
		if ((oldpte & ATTR_AP_RW_BIT) == ATTR_AP(ATTR_AP_RW)) {
			if (!atomic_cmpset_long(pte, oldpte,
			    oldpte | ATTR_AP(ATTR_AP_RO)))
				goto retry;
			if ((oldpte & ATTR_AF) != 0)
				vm_page_dirty(m);
			pmap_invalidate_page(pmap, pv->pv_va);
		}
		PMAP_UNLOCK(pmap);
	}
	rw_wunlock(lock);
	vm_page_aflag_clear(m, PGA_WRITEABLE);
	rw_runlock(&pvh_global_lock);
}
void pmap_remove_write ( vm_page_t m ) { pmap_t pmap ; struct rwlock * lock ; pv_entry_t pv ; pt_entry_t oldpte , * pte ; int lvl , md_gen ; KASSERT ( ( m -> oflags & VPO_UNMANAGED ) == 0 , ( " " , m ) ) ; VM_OBJECT_ASSERT_WLOCKED ( m -> object ) ; if ( ! vm_page_xbusied ( m ) && ( m -> aflags & PGA_WRITEABLE ) == 0 ) return ; rw_rlock ( & pvh_global_lock ) ; lock = VM_PAGE_TO_PV_LIST_LOCK ( m ) ; retry_pv_loop : rw_wlock ( lock ) ; TAILQ_FOREACH ( pv , & m -> md . pv_list , pv_next ) { pmap = PV_PMAP ( pv ) ; if ( ! PMAP_TRYLOCK ( pmap ) ) { md_gen = m -> md . pv_gen ; rw_wunlock ( lock ) ; PMAP_LOCK ( pmap ) ; rw_wlock ( lock ) ; if ( md_gen != m -> md . pv_gen ) { PMAP_UNLOCK ( pmap ) ; rw_wunlock ( lock ) ; goto retry_pv_loop ; } } pte = pmap_pte ( pmap , pv -> pv_va , & lvl ) ; retry : oldpte = pmap_load ( pte ) ; if ( ( oldpte & ATTR_AP_RW_BIT ) == ATTR_AP ( ATTR_AP_RW ) ) { if ( ! atomic_cmpset_long ( pte , oldpte , oldpte | ATTR_AP ( ATTR_AP_RO ) ) ) goto retry ; if ( ( oldpte & ATTR_AF ) != 0 ) vm_page_dirty ( m ) ; pmap_invalidate_page ( pmap , pv -> pv_va ) ; } PMAP_UNLOCK ( pmap ) ; } rw_wunlock ( lock ) ; vm_page_aflag_clear ( m , PGA_WRITEABLE ) ; rw_runlock ( & 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.
	 */