FreeBSD/sys/i386/i386/pmap.c
/*
 *	Insert the given physical page (p) at
 *	the specified virtual address (v) in the
 *	target physical map with the protection requested.
 *
 *	If specified, the page will be wired down, meaning
 *	that the related pte can not be reclaimed.
 *
 *	NB:  This is the only routine which MAY NOT lazy-evaluate
 *	or lose information.  That is, this routine must actually
 *	insert this page into the given map NOW.
 */
Insert the given physical page (p) at
the specified virtual address (v) in the
target physical map with the protection requested.

If specified, the page will be wired down, meaning
that the related pte can not be reclaimed.

This is the only routine which MAY NOT lazy-evaluate
or lose information.  That is, this routine must actually
insert this page into the given map NOW.
Insert the given physical page ( p ) at the specified virtual address ( v ) in the target physical map with the protection requested . If specified the page will be wired down meaning that the related pte can not be reclaimed . This is the only routine which MAY NOT lazy - evaluate or lose information . That is this routine must actually insert this page into the given map NOW .
int
pmap_enter(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot,
    u_int flags, int8_t psind)
{
	pd_entry_t *pde;
	pt_entry_t *pte;
	pt_entry_t newpte, origpte;
	pv_entry_t pv;
	vm_paddr_t opa, pa;
	vm_page_t mpte, om;
	boolean_t invlva, wired;
	va = trunc_page(va);
	mpte = NULL;
	wired = (flags & PMAP_ENTER_WIRED) != 0;
	KASSERT(va <= VM_MAX_KERNEL_ADDRESS, ("pmap_enter: toobig"));
	KASSERT(va < UPT_MIN_ADDRESS || va >= UPT_MAX_ADDRESS,
	    ("pmap_enter: invalid to pmap_enter page table pages (va: 0x%x)",
	    va));
	if ((m->oflags & VPO_UNMANAGED) == 0 && !vm_page_xbusied(m))
		VM_OBJECT_ASSERT_LOCKED(m->object);
	rw_wlock(&pvh_global_lock);
	PMAP_LOCK(pmap);
	sched_pin();
	if (va < VM_MAXUSER_ADDRESS) {
		mpte = pmap_allocpte(pmap, va, flags);
		if (mpte == NULL) {
			KASSERT((flags & PMAP_ENTER_NOSLEEP) != 0,
			    ("pmap_allocpte failed with sleep allowed"));
			sched_unpin();
			rw_wunlock(&pvh_global_lock);
			PMAP_UNLOCK(pmap);
			return (KERN_RESOURCE_SHORTAGE);
		}
	}
	pde = pmap_pde(pmap, va);
	if ((*pde & PG_PS) != 0)
		panic("pmap_enter: attempted pmap_enter on 4MB page");
	pte = pmap_pte_quick(pmap, va);
	if (pte == NULL) {
		panic("pmap_enter: invalid page directory pdir=%#jx, va=%#x",
			(uintmax_t)pmap->pm_pdir[PTDPTDI], va);
	}
	pa = VM_PAGE_TO_PHYS(m);
	om = NULL;
	origpte = *pte;
	opa = origpte & PG_FRAME;
	if (origpte && (opa == pa)) {
		if (wired && ((origpte & PG_W) == 0))
			pmap->pm_stats.wired_count++;
		else if (!wired && (origpte & PG_W))
			pmap->pm_stats.wired_count--;
		if (mpte)
			mpte->wire_count--;
		if (origpte & PG_MANAGED) {
			om = m;
			pa |= PG_MANAGED;
		}
		goto validate;
	} 
	pv = NULL;
	if (opa) {
		if (origpte & PG_W)
			pmap->pm_stats.wired_count--;
		if (origpte & PG_MANAGED) {
			om = PHYS_TO_VM_PAGE(opa);
			pv = pmap_pvh_remove(&om->md, pmap, va);
		}
		if (mpte != NULL) {
			mpte->wire_count--;
			KASSERT(mpte->wire_count > 0,
			    ("pmap_enter: missing reference to page table page,"
			     " va: 0x%x", va));
		}
	} else
		pmap->pm_stats.resident_count++;
	if ((m->oflags & VPO_UNMANAGED) == 0) {
		KASSERT(va < kmi.clean_sva || va >= kmi.clean_eva,
		    ("pmap_enter: managed mapping within the clean submap"));
		if (pv == NULL)
			pv = get_pv_entry(pmap, FALSE);
		pv->pv_va = va;
		TAILQ_INSERT_TAIL(&m->md.pv_list, pv, pv_next);
		pa |= PG_MANAGED;
	} else if (pv != NULL)
		free_pv_entry(pmap, pv);
	if (wired)
		pmap->pm_stats.wired_count++;
validate:
	newpte = (pt_entry_t)(pa | pmap_cache_bits(m->md.pat_mode, 0) | PG_V);
	if ((prot & VM_PROT_WRITE) != 0) {
		newpte |= PG_RW;
		if ((newpte & PG_MANAGED) != 0)
			vm_page_aflag_set(m, PGA_WRITEABLE);
	}
#if defined(PAE) || defined(PAE_TABLES)
	if ((prot & VM_PROT_EXECUTE) == 0)
		newpte |= pg_nx;
#endif
	if (wired)
		newpte |= PG_W;
	if (va < VM_MAXUSER_ADDRESS)
		newpte |= PG_U;
	if (pmap == kernel_pmap)
		newpte |= pgeflag;
	if ((origpte & ~(PG_M|PG_A)) != newpte) {
		newpte |= PG_A;
		if ((flags & VM_PROT_WRITE) != 0)
			newpte |= PG_M;
		if (origpte & PG_V) {
			invlva = FALSE;
			origpte = pte_load_store(pte, newpte);
			if (origpte & PG_A) {
				if (origpte & PG_MANAGED)
					vm_page_aflag_set(om, PGA_REFERENCED);
				if (opa != VM_PAGE_TO_PHYS(m))
					invlva = TRUE;
#if defined(PAE) || defined(PAE_TABLES)
				if ((origpte & PG_NX) == 0 &&
				    (newpte & PG_NX) != 0)
					invlva = TRUE;
#endif
			}
			if ((origpte & (PG_M | PG_RW)) == (PG_M | PG_RW)) {
				if ((origpte & PG_MANAGED) != 0)
					vm_page_dirty(om);
				if ((prot & VM_PROT_WRITE) == 0)
					invlva = TRUE;
			}
			if ((origpte & PG_MANAGED) != 0 &&
			    TAILQ_EMPTY(&om->md.pv_list) &&
			    ((om->flags & PG_FICTITIOUS) != 0 ||
			    TAILQ_EMPTY(&pa_to_pvh(opa)->pv_list)))
				vm_page_aflag_clear(om, PGA_WRITEABLE);
			if (invlva)
				pmap_invalidate_page(pmap, va);
		} else
			pte_store(pte, newpte);
	}
	if ((mpte == NULL || mpte->wire_count == NPTEPG) &&
	    pg_ps_enabled && (m->flags & PG_FICTITIOUS) == 0 &&
	    vm_reserv_level_iffullpop(m) == 0)
		pmap_promote_pde(pmap, pde, va);
	sched_unpin();
	rw_wunlock(&pvh_global_lock);
	PMAP_UNLOCK(pmap);
	return (KERN_SUCCESS);
}
int pmap_enter ( pmap_t pmap , vm_offset_t va , vm_page_t m , vm_prot_t prot , u_int flags , int8_t psind ) { pd_entry_t * pde ; pt_entry_t * pte ; pt_entry_t newpte , origpte ; pv_entry_t pv ; vm_paddr_t opa , pa ; vm_page_t mpte , om ; boolean_t invlva , wired ; va = trunc_page ( va ) ; mpte = NULL ; wired = ( flags & PMAP_ENTER_WIRED ) != 0 ; KASSERT ( va <= VM_MAX_KERNEL_ADDRESS , ( " " ) ) ; KASSERT ( va < UPT_MIN_ADDRESS || va >= UPT_MAX_ADDRESS , ( " " , va ) ) ; if ( ( m -> oflags & VPO_UNMANAGED ) == 0 && ! vm_page_xbusied ( m ) ) VM_OBJECT_ASSERT_LOCKED ( m -> object ) ; rw_wlock ( & pvh_global_lock ) ; PMAP_LOCK ( pmap ) ; sched_pin ( ) ; if ( va < VM_MAXUSER_ADDRESS ) { mpte = pmap_allocpte ( pmap , va , flags ) ; if ( mpte == NULL ) { KASSERT ( ( flags & PMAP_ENTER_NOSLEEP ) != 0 , ( " " ) ) ; sched_unpin ( ) ; rw_wunlock ( & pvh_global_lock ) ; PMAP_UNLOCK ( pmap ) ; return ( KERN_RESOURCE_SHORTAGE ) ; } } pde = pmap_pde ( pmap , va ) ; if ( ( * pde & PG_PS ) != 0 ) panic ( " " ) ; pte = pmap_pte_quick ( pmap , va ) ; if ( pte == NULL ) { panic ( " " , ( uintmax_t ) pmap -> pm_pdir [ PTDPTDI ] , va ) ; } pa = VM_PAGE_TO_PHYS ( m ) ; om = NULL ; origpte = * pte ; opa = origpte & PG_FRAME ; if ( origpte && ( opa == pa ) ) { if ( wired && ( ( origpte & PG_W ) == 0 ) ) pmap -> pm_stats . wired_count ++ ; else if ( ! wired && ( origpte & PG_W ) ) pmap -> pm_stats . wired_count -- ; if ( mpte ) mpte -> wire_count -- ; if ( origpte & PG_MANAGED ) { om = m ; pa |= PG_MANAGED ; } goto validate ; } pv = NULL ; if ( opa ) { if ( origpte & PG_W ) pmap -> pm_stats . wired_count -- ; if ( origpte & PG_MANAGED ) { om = PHYS_TO_VM_PAGE ( opa ) ; pv = pmap_pvh_remove ( & om -> md , pmap , va ) ; } if ( mpte != NULL ) { mpte -> wire_count -- ; KASSERT ( mpte -> wire_count > 0 , ( " " " " , va ) ) ; } } else pmap -> pm_stats . resident_count ++ ; if ( ( m -> oflags & VPO_UNMANAGED ) == 0 ) { KASSERT ( va < kmi . clean_sva || va >= kmi . clean_eva , ( " " ) ) ; if ( pv == NULL ) pv = get_pv_entry ( pmap , FALSE ) ; pv -> pv_va = va ; TAILQ_INSERT_TAIL ( & m -> md . pv_list , pv , pv_next ) ; pa |= PG_MANAGED ; } else if ( pv != NULL ) free_pv_entry ( pmap , pv ) ; if ( wired ) pmap -> pm_stats . wired_count ++ ; validate : newpte = ( pt_entry_t ) ( pa | pmap_cache_bits ( m -> md . pat_mode , 0 ) | PG_V ) ; if ( ( prot & VM_PROT_WRITE ) != 0 ) { newpte |= PG_RW ; if ( ( newpte & PG_MANAGED ) != 0 ) vm_page_aflag_set ( m , PGA_WRITEABLE ) ; } #if defined ( PAE ) || defined ( PAE_TABLES ) if ( ( prot & VM_PROT_EXECUTE ) == 0 ) newpte |= pg_nx ; #endif if ( wired ) newpte |= PG_W ; if ( va < VM_MAXUSER_ADDRESS ) newpte |= PG_U ; if ( pmap == kernel_pmap ) newpte |= pgeflag ; if ( ( origpte & ~ ( PG_M | PG_A ) ) != newpte ) { newpte |= PG_A ; if ( ( flags & VM_PROT_WRITE ) != 0 ) newpte |= PG_M ; if ( origpte & PG_V ) { invlva = FALSE ; origpte = pte_load_store ( pte , newpte ) ; if ( origpte & PG_A ) { if ( origpte & PG_MANAGED ) vm_page_aflag_set ( om , PGA_REFERENCED ) ; if ( opa != VM_PAGE_TO_PHYS ( m ) ) invlva = TRUE ; #if defined ( PAE ) || defined ( PAE_TABLES ) if ( ( origpte & PG_NX ) == 0 && ( newpte & PG_NX ) != 0 ) invlva = TRUE ; #endif } if ( ( origpte & ( PG_M | PG_RW ) ) == ( PG_M | PG_RW ) ) { if ( ( origpte & PG_MANAGED ) != 0 ) vm_page_dirty ( om ) ; if ( ( prot & VM_PROT_WRITE ) == 0 ) invlva = TRUE ; } if ( ( origpte & PG_MANAGED ) != 0 && TAILQ_EMPTY ( & om -> md . pv_list ) && ( ( om -> flags & PG_FICTITIOUS ) != 0 || TAILQ_EMPTY ( & pa_to_pvh ( opa ) -> pv_list ) ) ) vm_page_aflag_clear ( om , PGA_WRITEABLE ) ; if ( invlva ) pmap_invalidate_page ( pmap , va ) ; } else pte_store ( pte , newpte ) ; } if ( ( mpte == NULL || mpte -> wire_count == NPTEPG ) && pg_ps_enabled && ( m -> flags & PG_FICTITIOUS ) == 0 && vm_reserv_level_iffullpop ( m ) == 0 ) pmap_promote_pde ( pmap , pde , va ) ; sched_unpin ( ) ; rw_wunlock ( & pvh_global_lock ) ; PMAP_UNLOCK ( pmap ) ; return ( KERN_SUCCESS ) ; }
Insert the given physical page (p) at
      the specified virtual address (v) in the
      target physical map with the protection requested.
Insert the given physical page ( p ) at the specified virtual address ( v ) in the target physical map with the protection requested .
/*
	 * In the case that a page table page is not
	 * resident, we are creating it here.
	 */ /*
	 * Page Directory table entry not valid, we need a new PT page
	 */ /*
	 * Mapping has not changed, must be protection or wiring change.
	 */ /*
		 * Wiring change, just update stats. We don't worry about
		 * wiring PT pages as they remain resident as long as there
		 * are valid mappings in them. Hence, if a user page is wired,
		 * the PT page will be also.
		 */ /*
		 * Remove extra pte reference
		 */ /*
	 * Mapping has changed, invalidate old range and fall through to
	 * handle validating new mapping.
	 */ /*
	 * Enter on the PV list if part of our managed memory.
	 */ /*
	 * Increment counters
	 */ /*
	 * Now validate mapping with desired protection/wiring.
	 */ /*
	 * if the mapping or permission bits are different, we need
	 * to update the pte.
	 */ /*
	 * If both the page table page and the reservation are fully
	 * populated, then attempt promotion.
	 */