FreeBSD/sys/i386/i386/pmap.c
/*
 *	Remove the given range of addresses from the specified map.
 *
 *	It is assumed that the start and end are properly
 *	rounded to the page size.
 */
Remove the given range of addresses from the specified map.
It is assumed that the start and end are properly
rounded to the page size.
Remove the given range of addresses from the specified map . It is assumed that the start and end are properly rounded to the page size .
void
pmap_remove(pmap_t pmap, vm_offset_t sva, vm_offset_t eva)
{
	vm_offset_t pdnxt;
	pd_entry_t ptpaddr;
	pt_entry_t *pte;
	struct spglist free;
	int anyvalid;
	if (pmap->pm_stats.resident_count == 0)
		return;
	anyvalid = 0;
	SLIST_INIT(&free);
	rw_wlock(&pvh_global_lock);
	sched_pin();
	PMAP_LOCK(pmap);
	if ((sva + PAGE_SIZE == eva) && 
	    ((pmap->pm_pdir[(sva >> PDRSHIFT)] & PG_PS) == 0)) {
		pmap_remove_page(pmap, sva, &free);
		goto out;
	}
	for (; sva < eva; sva = pdnxt) {
		u_int pdirindex;
		pdnxt = (sva + NBPDR) & ~PDRMASK;
		if (pdnxt < sva)
			pdnxt = eva;
		if (pmap->pm_stats.resident_count == 0)
			break;
		pdirindex = sva >> PDRSHIFT;
		ptpaddr = pmap->pm_pdir[pdirindex];
		if (ptpaddr == 0)
			continue;
		if ((ptpaddr & PG_PS) != 0) {
			if (sva + NBPDR == pdnxt && eva >= pdnxt) {
				if ((ptpaddr & PG_G) == 0)
					anyvalid = 1;
				pmap_remove_pde(pmap,
				    &pmap->pm_pdir[pdirindex], sva, &free);
				continue;
			} else if (!pmap_demote_pde(pmap,
			    &pmap->pm_pdir[pdirindex], sva)) {
				continue;
			}
		}
		if (pdnxt > eva)
			pdnxt = eva;
		for (pte = pmap_pte_quick(pmap, sva); sva != pdnxt; pte++,
		    sva += PAGE_SIZE) {
			if (*pte == 0)
				continue;
			if ((*pte & PG_G) == 0)
				anyvalid = 1;
			if (pmap_remove_pte(pmap, pte, sva, &free))
				break;
		}
	}
out:
	sched_unpin();
	if (anyvalid)
		pmap_invalidate_all(pmap);
	rw_wunlock(&pvh_global_lock);
	PMAP_UNLOCK(pmap);
	pmap_free_zero_pages(&free);
}
void pmap_remove ( pmap_t pmap , vm_offset_t sva , vm_offset_t eva ) { vm_offset_t pdnxt ; pd_entry_t ptpaddr ; pt_entry_t * pte ; struct spglist free ; int anyvalid ; if ( pmap -> pm_stats . resident_count == 0 ) return ; anyvalid = 0 ; SLIST_INIT ( & free ) ; rw_wlock ( & pvh_global_lock ) ; sched_pin ( ) ; PMAP_LOCK ( pmap ) ; if ( ( sva + PAGE_SIZE == eva ) && ( ( pmap -> pm_pdir [ ( sva >> PDRSHIFT ) ] & PG_PS ) == 0 ) ) { pmap_remove_page ( pmap , sva , & free ) ; goto out ; } for ( ; sva < eva ; sva = pdnxt ) { u_int pdirindex ; pdnxt = ( sva + NBPDR ) & ~ PDRMASK ; if ( pdnxt < sva ) pdnxt = eva ; if ( pmap -> pm_stats . resident_count == 0 ) break ; pdirindex = sva >> PDRSHIFT ; ptpaddr = pmap -> pm_pdir [ pdirindex ] ; if ( ptpaddr == 0 ) continue ; if ( ( ptpaddr & PG_PS ) != 0 ) { if ( sva + NBPDR == pdnxt && eva >= pdnxt ) { if ( ( ptpaddr & PG_G ) == 0 ) anyvalid = 1 ; pmap_remove_pde ( pmap , & pmap -> pm_pdir [ pdirindex ] , sva , & free ) ; continue ; } else if ( ! pmap_demote_pde ( pmap , & pmap -> pm_pdir [ pdirindex ] , sva ) ) { continue ; } } if ( pdnxt > eva ) pdnxt = eva ; for ( pte = pmap_pte_quick ( pmap , sva ) ; sva != pdnxt ; pte ++ , sva += PAGE_SIZE ) { if ( * pte == 0 ) continue ; if ( ( * pte & PG_G ) == 0 ) anyvalid = 1 ; if ( pmap_remove_pte ( pmap , pte , sva , & free ) ) break ; } } out : sched_unpin ( ) ; if ( anyvalid ) pmap_invalidate_all ( pmap ) ; rw_wunlock ( & pvh_global_lock ) ; PMAP_UNLOCK ( pmap ) ; pmap_free_zero_pages ( & free ) ; }
Remove the given range of addresses from the specified map.
Remove the given range of addresses from the specified map .
/*
	 * Perform an unsynchronized read.  This is, however, safe.
	 */ /*
	 * special handling of removing one page.  a very
	 * common operation and easy to short circuit some
	 * code.
	 */ /*
		 * Calculate index for next page table.
		 */ /*
		 * Weed out invalid mappings. Note: we assume that the page
		 * directory table is always allocated, and in kernel virtual.
		 */ /*
		 * Check for large page.
		 */ /*
			 * Are we removing the entire large page?  If not,
			 * demote the mapping and fall through.
			 */ /*
				 * The TLB entry for a PG_G mapping is
				 * invalidated by pmap_remove_pde().
				 */ /* The large page mapping was destroyed. */ /*
		 * Limit our scan to either the end of the va represented
		 * by the current page table page, or to the end of the
		 * range being removed.
		 */ /*
			 * The TLB entry for a PG_G mapping is invalidated
			 * by pmap_remove_pte().
			 */