FreeBSD/sys/arm/arm/pmap-v6.c
/*
 *	Apply the given advice to the specified range of addresses within the
 *	given pmap.  Depending on the advice, clear the referenced and/or
 *	modified flags in each mapping and set the mapped page's dirty field.
 */
Apply the given advice to the specified range of addresses within the
given pmap.  Depending on the advice, clear the referenced and/or
modified flags in each mapping and set the mapped page's dirty field.
Apply the given advice to the specified range of addresses within the given pmap . Depending on the advice clear the referenced and / or modified flags in each mapping and set the mapped page ' s dirty field .
void
pmap_advise(pmap_t pmap, vm_offset_t sva, vm_offset_t eva, int advice)
{
	pt1_entry_t *pte1p, opte1;
	pt2_entry_t *pte2p, pte2;
	vm_offset_t pdnxt;
	vm_page_t m;
	boolean_t pv_lists_locked;
	if (advice != MADV_DONTNEED && advice != MADV_FREE)
		return;
	if (pmap_is_current(pmap))
		pv_lists_locked = FALSE;
	else {
		pv_lists_locked = TRUE;
resume:
		rw_wlock(&pvh_global_lock);
		sched_pin();
	}
	PMAP_LOCK(pmap);
	for (; sva < eva; sva = pdnxt) {
		pdnxt = pte1_trunc(sva + PTE1_SIZE);
		if (pdnxt < sva)
			pdnxt = eva;
		pte1p = pmap_pte1(pmap, sva);
		opte1 = pte1_load(pte1p);
		if (!pte1_is_valid(opte1)) 
			continue;
		else if (pte1_is_section(opte1)) {
			if (!pte1_is_managed(opte1))
				continue;
			if (!pv_lists_locked) {
				pv_lists_locked = TRUE;
				if (!rw_try_wlock(&pvh_global_lock)) {
					PMAP_UNLOCK(pmap);
					goto resume;
				}
				sched_pin();
			}
			if (!pmap_demote_pte1(pmap, pte1p, sva)) {
				continue;
			}
			if (!pte1_is_wired(opte1)) {
				pte2p = pmap_pte2_quick(pmap, sva);
				KASSERT(pte2_is_valid(pte2_load(pte2p)),
				    ("%s: invalid PTE2", __func__));
				pmap_remove_pte2(pmap, pte2p, sva, NULL);
			}
		}
		if (pdnxt > eva)
			pdnxt = eva;
		for (pte2p = pmap_pte2_quick(pmap, sva); sva != pdnxt; pte2p++,
		    sva += PAGE_SIZE) {
			pte2 = pte2_load(pte2p);
			if (!pte2_is_valid(pte2) || !pte2_is_managed(pte2))
				continue;
			else if (pte2_is_dirty(pte2)) {
				if (advice == MADV_DONTNEED) {
					m = PHYS_TO_VM_PAGE(pte2_pa(pte2));
					vm_page_dirty(m);
				}
				pte2_set_bit(pte2p, PTE2_NM);
				pte2_clear_bit(pte2p, PTE2_A);
			} else if ((pte2 & PTE2_A) != 0)
				pte2_clear_bit(pte2p, PTE2_A);
			else
				continue;
			pmap_tlb_flush(pmap, sva);
		}
	}
	if (pv_lists_locked) {
		sched_unpin();
		rw_wunlock(&pvh_global_lock);
	}
	PMAP_UNLOCK(pmap);
}
void pmap_advise ( pmap_t pmap , vm_offset_t sva , vm_offset_t eva , int advice ) { pt1_entry_t * pte1p , opte1 ; pt2_entry_t * pte2p , pte2 ; vm_offset_t pdnxt ; vm_page_t m ; boolean_t pv_lists_locked ; if ( advice != MADV_DONTNEED && advice != MADV_FREE ) return ; if ( pmap_is_current ( pmap ) ) pv_lists_locked = FALSE ; else { pv_lists_locked = TRUE ; resume : rw_wlock ( & pvh_global_lock ) ; sched_pin ( ) ; } PMAP_LOCK ( pmap ) ; for ( ; sva < eva ; sva = pdnxt ) { pdnxt = pte1_trunc ( sva + PTE1_SIZE ) ; if ( pdnxt < sva ) pdnxt = eva ; pte1p = pmap_pte1 ( pmap , sva ) ; opte1 = pte1_load ( pte1p ) ; if ( ! pte1_is_valid ( opte1 ) ) continue ; else if ( pte1_is_section ( opte1 ) ) { if ( ! pte1_is_managed ( opte1 ) ) continue ; if ( ! pv_lists_locked ) { pv_lists_locked = TRUE ; if ( ! rw_try_wlock ( & pvh_global_lock ) ) { PMAP_UNLOCK ( pmap ) ; goto resume ; } sched_pin ( ) ; } if ( ! pmap_demote_pte1 ( pmap , pte1p , sva ) ) { continue ; } if ( ! pte1_is_wired ( opte1 ) ) { pte2p = pmap_pte2_quick ( pmap , sva ) ; KASSERT ( pte2_is_valid ( pte2_load ( pte2p ) ) , ( " " , __func__ ) ) ; pmap_remove_pte2 ( pmap , pte2p , sva , NULL ) ; } } if ( pdnxt > eva ) pdnxt = eva ; for ( pte2p = pmap_pte2_quick ( pmap , sva ) ; sva != pdnxt ; pte2p ++ , sva += PAGE_SIZE ) { pte2 = pte2_load ( pte2p ) ; if ( ! pte2_is_valid ( pte2 ) || ! pte2_is_managed ( pte2 ) ) continue ; else if ( pte2_is_dirty ( pte2 ) ) { if ( advice == MADV_DONTNEED ) { m = PHYS_TO_VM_PAGE ( pte2_pa ( pte2 ) ) ; vm_page_dirty ( m ) ; } pte2_set_bit ( pte2p , PTE2_NM ) ; pte2_clear_bit ( pte2p , PTE2_A ) ; } else if ( ( pte2 & PTE2_A ) != 0 ) pte2_clear_bit ( pte2p , PTE2_A ) ; else continue ; pmap_tlb_flush ( pmap , sva ) ; } } if ( pv_lists_locked ) { sched_unpin ( ) ; rw_wunlock ( & pvh_global_lock ) ; } PMAP_UNLOCK ( pmap ) ; }
Apply the given advice to the specified range of addresses within the
      given pmap.
Apply the given advice to the specified range of addresses within the given pmap .
/* XXX */ /*
				 * The large page mapping was destroyed.
				 */ /*
			 * Unless the page mappings are wired, remove the
			 * mapping to a single page so that a subsequent
			 * access may repromote.  Since the underlying L2 page
			 * table is fully populated, this removal never
			 * frees a L2 page table page.
			 */ /*
					 * Future calls to pmap_is_modified()
					 * can be avoided by making the page
					 * dirty now.
					 */