FreeBSD/sys/arm/arm/pmap-v4.c
/*
 *      Routine:        pmap_remove_all
 *      Function:
 *              Removes this physical page from
 *              all physical maps in which it resides.
 *              Reflects back modify bits to the pager.
 *
 *      Notes:
 *              Original versions of this routine were very
 *              inefficient because they iteratively called
 *              pmap_remove (slow...)
 */
pmap_remove_all
Function:
Removes this physical page from
all physical maps in which it resides.
Reflects back modify bits to the pager.

Original versions of this routine were very
inefficient because they iteratively called
pmap_remove (slow...)
pmap_remove_all Function : Removes this physical page from all physical maps in which it resides . Reflects back modify bits to the pager . Original versions of this routine were very inefficient because they iteratively called pmap_remove ( slow ... )
void
pmap_remove_all(vm_page_t m)
{
	pv_entry_t pv;
	pt_entry_t *ptep;
	struct l2_bucket *l2b;
	boolean_t flush = FALSE;
	pmap_t curpm;
	int flags = 0;
	KASSERT((m->oflags & VPO_UNMANAGED) == 0,
	    ("pmap_remove_all: page %p is not managed", m));
	if (TAILQ_EMPTY(&m->md.pv_list))
		return;
	rw_wlock(&pvh_global_lock);
	pmap_clearbit(m, PVF_WRITE);
	curpm = vmspace_pmap(curproc->p_vmspace);
	while ((pv = TAILQ_FIRST(&m->md.pv_list)) != NULL) {
		if (flush == FALSE && (pv->pv_pmap == curpm ||
		    pv->pv_pmap == kernel_pmap))
			flush = TRUE;
		PMAP_LOCK(pv->pv_pmap);
		if (pmap_is_current(pv->pv_pmap)) {
			cpu_dcache_inv_range(pv->pv_va, PAGE_SIZE);
			if (pmap_has_valid_mapping(pv->pv_pmap, pv->pv_va))
				cpu_l2cache_inv_range(pv->pv_va, PAGE_SIZE);
		}
		if (pv->pv_flags & PVF_UNMAN) {
			m->md.pv_kva = pv->pv_va;
		} else {
			l2b = pmap_get_l2_bucket(pv->pv_pmap, pv->pv_va);
			KASSERT(l2b != NULL, ("No l2 bucket"));
			ptep = &l2b->l2b_kva[l2pte_index(pv->pv_va)];
			*ptep = 0;
			PTE_SYNC_CURRENT(pv->pv_pmap, ptep);
			pmap_free_l2_bucket(pv->pv_pmap, l2b, 1);
			pv->pv_pmap->pm_stats.resident_count--;
			flags |= pv->pv_flags;
		}
		pmap_nuke_pv(m, pv->pv_pmap, pv);
		PMAP_UNLOCK(pv->pv_pmap);
		pmap_free_pv_entry(pv);
	}
	if (flush) {
		if (PV_BEEN_EXECD(flags))
			pmap_tlb_flushID(curpm);
		else
			pmap_tlb_flushD(curpm);
	}
	vm_page_aflag_clear(m, PGA_WRITEABLE);
	rw_wunlock(&pvh_global_lock);
}
void pmap_remove_all ( vm_page_t m ) { pv_entry_t pv ; pt_entry_t * ptep ; struct l2_bucket * l2b ; boolean_t flush = FALSE ; pmap_t curpm ; int flags = 0 ; KASSERT ( ( m -> oflags & VPO_UNMANAGED ) == 0 , ( " " , m ) ) ; if ( TAILQ_EMPTY ( & m -> md . pv_list ) ) return ; rw_wlock ( & pvh_global_lock ) ; pmap_clearbit ( m , PVF_WRITE ) ; curpm = vmspace_pmap ( curproc -> p_vmspace ) ; while ( ( pv = TAILQ_FIRST ( & m -> md . pv_list ) ) != NULL ) { if ( flush == FALSE && ( pv -> pv_pmap == curpm || pv -> pv_pmap == kernel_pmap ) ) flush = TRUE ; PMAP_LOCK ( pv -> pv_pmap ) ; if ( pmap_is_current ( pv -> pv_pmap ) ) { cpu_dcache_inv_range ( pv -> pv_va , PAGE_SIZE ) ; if ( pmap_has_valid_mapping ( pv -> pv_pmap , pv -> pv_va ) ) cpu_l2cache_inv_range ( pv -> pv_va , PAGE_SIZE ) ; } if ( pv -> pv_flags & PVF_UNMAN ) { m -> md . pv_kva = pv -> pv_va ; } else { l2b = pmap_get_l2_bucket ( pv -> pv_pmap , pv -> pv_va ) ; KASSERT ( l2b != NULL , ( " " ) ) ; ptep = & l2b -> l2b_kva [ l2pte_index ( pv -> pv_va ) ] ; * ptep = 0 ; PTE_SYNC_CURRENT ( pv -> pv_pmap , ptep ) ; pmap_free_l2_bucket ( pv -> pv_pmap , l2b , 1 ) ; pv -> pv_pmap -> pm_stats . resident_count -- ; flags |= pv -> pv_flags ; } pmap_nuke_pv ( m , pv -> pv_pmap , pv ) ; PMAP_UNLOCK ( pv -> pv_pmap ) ; pmap_free_pv_entry ( pv ) ; } if ( flush ) { if ( PV_BEEN_EXECD ( flags ) ) pmap_tlb_flushID ( curpm ) ; else pmap_tlb_flushD ( curpm ) ; } vm_page_aflag_clear ( m , PGA_WRITEABLE ) ; rw_wunlock ( & pvh_global_lock ) ; }
Routine:        pmap_remove_all
      Function:
              Removes this physical page from
              all physical maps in which it resides.
Routine : pmap_remove_all Function : Removes this physical page from all physical maps in which it resides .
/*
	 * XXX This call shouldn't exist.  Iterating over the PV list twice,
	 * once in pmap_clearbit() and again below, is both unnecessary and
	 * inefficient.  The below code should itself write back the cache
	 * entry before it destroys the mapping.
	 */ /*
		 * Cached contents were written-back in pmap_clearbit(),
		 * but we still have to invalidate the cache entry to make
		 * sure stale data are not retrieved when another page will be
		 * mapped under this virtual address.
		 */ /* remove the pv entry, but do not remove the mapping
			 * and remember this is a kernel mapped page
			 */ /* remove the mapping and pv entry */