FreeBSD/sys/arm/arm/pmap-v6.c
/*
 *  Remove all pages from specified address space this aids process
 *  exit speeds. Also, this code is special cased for current process
 *  only, but can have the more generic (and slightly slower) mode enabled.
 *  This is much faster than pmap_remove in the case of running down
 *  an entire address space.
 */
Remove all pages from specified address space this aids process
exit speeds. Also, this code is special cased for current process
only, but can have the more generic (and slightly slower) mode enabled.
This is much faster than pmap_remove in the case of running down
an entire address space.
Remove all pages from specified address space this aids process exit speeds . Also this code is special cased for current process only but can have the more generic ( and slightly slower ) mode enabled . This is much faster than pmap_remove in the case of running down an entire address space .
void
pmap_remove_pages(pmap_t pmap)
{
	pt1_entry_t *pte1p, pte1;
	pt2_entry_t *pte2p, pte2;
	pv_entry_t pv;
	struct pv_chunk *pc, *npc;
	struct spglist free;
	int field, idx;
	int32_t bit;
	uint32_t inuse, bitmask;
	boolean_t allfree;
	KASSERT(pmap == vmspace_pmap(curthread->td_proc->p_vmspace),
	    ("%s: non-current pmap %p", __func__, pmap));
#if defined(SMP) && defined(INVARIANTS)
	{
		cpuset_t other_cpus;
		sched_pin();
		other_cpus = pmap->pm_active;
		CPU_CLR(PCPU_GET(cpuid), &other_cpus);
		sched_unpin();
		KASSERT(CPU_EMPTY(&other_cpus),
		    ("%s: pmap %p active on other cpus", __func__, pmap));
	}
#endif
	SLIST_INIT(&free);
	rw_wlock(&pvh_global_lock);
	PMAP_LOCK(pmap);
	sched_pin();
	TAILQ_FOREACH_SAFE(pc, &pmap->pm_pvchunk, pc_list, npc) {
		KASSERT(pc->pc_pmap == pmap, ("%s: wrong pmap %p %p",
		    __func__, pmap, pc->pc_pmap));
		allfree = TRUE;
		for (field = 0; field < _NPCM; field++) {
			inuse = (~(pc->pc_map[field])) & pc_freemask[field];
			while (inuse != 0) {
				bit = ffs(inuse) - 1;
				bitmask = 1UL << bit;
				idx = field * 32 + bit;
				pv = &pc->pc_pventry[idx];
				inuse &= ~bitmask;
				pte1p = pmap_pte1(pmap, pv->pv_va);
				pte1 = pte1_load(pte1p);
				if (pte1_is_section(pte1)) {
					if (pte1_is_wired(pte1))  {
						allfree = FALSE;
						continue;
					}
					pte1_clear(pte1p);
					pmap_remove_pte1_quick(pmap, pte1, pv,
					    &free);
				}
				else if (pte1_is_link(pte1)) {
					pte2p = pt2map_entry(pv->pv_va);
					pte2 = pte2_load(pte2p);
					if (!pte2_is_valid(pte2)) {
						printf("%s: pmap %p va %#x "
						    "pte2 %#x\n", __func__,
						    pmap, pv->pv_va, pte2);
						panic("bad pte2");
					}
					if (pte2_is_wired(pte2))   {
						allfree = FALSE;
						continue;
					}
					pte2_clear(pte2p);
					pmap_remove_pte2_quick(pmap, pte2, pv,
					    &free);
				} else {
					printf("%s: pmap %p va %#x pte1 %#x\n",
					    __func__, pmap, pv->pv_va, pte1);
					panic("bad pte1");
				}
				PV_STAT(pv_entry_frees++);
				PV_STAT(pv_entry_spare++);
				pv_entry_count--;
				pc->pc_map[field] |= bitmask;
			}
		}
		if (allfree) {
			TAILQ_REMOVE(&pmap->pm_pvchunk, pc, pc_list);
			free_pv_chunk(pc);
		}
	}
	tlb_flush_all_ng_local();
	sched_unpin();
	rw_wunlock(&pvh_global_lock);
	PMAP_UNLOCK(pmap);
	pmap_free_zero_pages(&free);
}
void pmap_remove_pages ( pmap_t pmap ) { pt1_entry_t * pte1p , pte1 ; pt2_entry_t * pte2p , pte2 ; pv_entry_t pv ; struct pv_chunk * pc , * npc ; struct spglist free ; int field , idx ; int32_t bit ; uint32_t inuse , bitmask ; boolean_t allfree ; KASSERT ( pmap == vmspace_pmap ( curthread -> td_proc -> p_vmspace ) , ( " " , __func__ , pmap ) ) ; #if defined ( SMP ) && defined ( INVARIANTS ) { cpuset_t other_cpus ; sched_pin ( ) ; other_cpus = pmap -> pm_active ; CPU_CLR ( PCPU_GET ( cpuid ) , & other_cpus ) ; sched_unpin ( ) ; KASSERT ( CPU_EMPTY ( & other_cpus ) , ( " " , __func__ , pmap ) ) ; } #endif SLIST_INIT ( & free ) ; rw_wlock ( & pvh_global_lock ) ; PMAP_LOCK ( pmap ) ; sched_pin ( ) ; TAILQ_FOREACH_SAFE ( pc , & pmap -> pm_pvchunk , pc_list , npc ) { KASSERT ( pc -> pc_pmap == pmap , ( " " , __func__ , pmap , pc -> pc_pmap ) ) ; allfree = TRUE ; for ( field = 0 ; field < _NPCM ; field ++ ) { inuse = ( ~ ( pc -> pc_map [ field ] ) ) & pc_freemask [ field ] ; while ( inuse != 0 ) { bit = ffs ( inuse ) - 1 ; bitmask = 1UL << bit ; idx = field * 32 + bit ; pv = & pc -> pc_pventry [ idx ] ; inuse &= ~ bitmask ; pte1p = pmap_pte1 ( pmap , pv -> pv_va ) ; pte1 = pte1_load ( pte1p ) ; if ( pte1_is_section ( pte1 ) ) { if ( pte1_is_wired ( pte1 ) ) { allfree = FALSE ; continue ; } pte1_clear ( pte1p ) ; pmap_remove_pte1_quick ( pmap , pte1 , pv , & free ) ; } else if ( pte1_is_link ( pte1 ) ) { pte2p = pt2map_entry ( pv -> pv_va ) ; pte2 = pte2_load ( pte2p ) ; if ( ! pte2_is_valid ( pte2 ) ) { printf ( " " " \n " , __func__ , pmap , pv -> pv_va , pte2 ) ; panic ( " " ) ; } if ( pte2_is_wired ( pte2 ) ) { allfree = FALSE ; continue ; } pte2_clear ( pte2p ) ; pmap_remove_pte2_quick ( pmap , pte2 , pv , & free ) ; } else { printf ( " \n " , __func__ , pmap , pv -> pv_va , pte1 ) ; panic ( " " ) ; } PV_STAT ( pv_entry_frees ++ ) ; PV_STAT ( pv_entry_spare ++ ) ; pv_entry_count -- ; pc -> pc_map [ field ] |= bitmask ; } } if ( allfree ) { TAILQ_REMOVE ( & pmap -> pm_pvchunk , pc , pc_list ) ; free_pv_chunk ( pc ) ; } } tlb_flush_all_ng_local ( ) ; sched_unpin ( ) ; rw_wunlock ( & pvh_global_lock ) ; PMAP_UNLOCK ( pmap ) ; pmap_free_zero_pages ( & free ) ; }
Remove all pages from specified address space this aids process
  exit speeds.
Remove all pages from specified address space this aids process exit speeds .
/*
	 * Assert that the given pmap is only active on the current
	 * CPU.  Unfortunately, we cannot block another CPU from
	 * activating the pmap while this function is executing.
	 */ /*
				 * Note that we cannot remove wired pages
				 * from a process' mapping at this time
				 */ /* Mark free */