error = ENOMEM;
error = KERN_RESOURCE_SHORTAGE;
pmap_enter(pmap, va, pa, prot, flags)	struct pmap *pmap;	vaddr_t va;	paddr_t pa;	vm_prot_t prot;	int flags;{	pt_entry_t *ptes, opte, npte;	struct vm_page *ptp;	struct pv_head *pvh;	struct pv_entry *pve;	int bank, off, error;	boolean_t wired = (flags & PMAP_WIRED) != 0;#ifdef DIAGNOSTIC	/* sanity check: totally out of range? */	if (va >= VM_MAX_KERNEL_ADDRESS)		panic("pmap_enter: too big");	if (va == (vaddr_t) PDP_BASE || va == (vaddr_t) APDP_BASE)		panic("pmap_enter: trying to map over PDP/APDP!");	/* sanity check: kernel PTPs should already have been pre-allocated */	if (va >= VM_MIN_KERNEL_ADDRESS &&	    !pmap_valid_entry(pmap->pm_pdir[pdei(va)]))		panic("pmap_enter: missing kernel PTP!");#endif	/* get lock */	PMAP_MAP_TO_HEAD_LOCK();	/*	 * map in ptes and get a pointer to our PTP (unless we are the kernel)	 */	ptes = pmap_map_ptes(pmap);		/* locks pmap */	if (pmap == pmap_kernel()) {		ptp = NULL;	} else {		ptp = pmap_get_ptp(pmap, pdei(va));		if (ptp == NULL) {			if (flags & PMAP_CANFAIL) {				return ENOMEM;			}			panic("pmap_enter: get ptp failed");		}	}	opte = ptes[i386_btop(va)];		/* old PTE */	/*	 * is there currently a valid mapping at our VA?	 */	if (pmap_valid_entry(opte)) {		/*		 * first, update pm_stats.  resident count will not		 * change since we are replacing/changing a valid		 * mapping.  wired count might change...		 */		if (wired && (opte & PG_W) == 0)			pmap->pm_stats.wired_count++;		else if (!wired && (opte & PG_W) != 0)			pmap->pm_stats.wired_count--;		/*		 * is the currently mapped PA the same as the one we		 * want to map?		 */		if ((opte & PG_FRAME) == pa) {			/* if this is on the PVLIST, sync R/M bit */			if (opte & PG_PVLIST) {				bank = vm_physseg_find(atop(pa), &off);#ifdef DIAGNOSTIC				if (bank == -1)					panic("pmap_enter: same pa PG_PVLIST "					      "mapping with unmanaged page "					      "pa = 0x%lx (0x%lx)", pa,					      atop(pa));#endif				pvh = &vm_physmem[bank].pmseg.pvhead[off];				simple_lock(&pvh->pvh_lock);				vm_physmem[bank].pmseg.attrs[off] |= opte;				simple_unlock(&pvh->pvh_lock);			} else {				pvh = NULL;	/* ensure !PG_PVLIST */			}			goto enter_now;		}		/*		 * changing PAs: we must remove the old one first		 */		/*		 * if current mapping is on a pvlist,		 * remove it (sync R/M bits)		 */		if (opte & PG_PVLIST) {			bank = vm_physseg_find(atop(opte & PG_FRAME), &off);#ifdef DIAGNOSTIC			if (bank == -1)				panic("pmap_enter: PG_PVLIST mapping with "				      "unmanaged page "				      "pa = 0x%lx (0x%lx)", pa, atop(pa));#endif			pvh = &vm_physmem[bank].pmseg.pvhead[off];			simple_lock(&pvh->pvh_lock);			pve = pmap_remove_pv(pvh, pmap, va);			vm_physmem[bank].pmseg.attrs[off] |= opte;			simple_unlock(&pvh->pvh_lock);		} else {			pve = NULL;		}	} else {	/* opte not valid */		pve = NULL;		pmap->pm_stats.resident_count++;		if (wired)			pmap->pm_stats.wired_count++;		if (ptp)			ptp->wire_count++;      /* count # of valid entrys */	}	/*	 * at this point pm_stats has been updated.   pve is either NULL	 * or points to a now-free pv_entry structure (the latter case is	 * if we called pmap_remove_pv above).	 *	 * if this entry is to be on a pvlist, enter it now.	 */	bank = vm_physseg_find(atop(pa), &off);	if (pmap_initialized && bank != -1) {		pvh = &vm_physmem[bank].pmseg.pvhead[off];		if (pve == NULL) {			pve = pmap_alloc_pv(pmap, ALLOCPV_NEED);			if (pve == NULL) {				if (flags & PMAP_CANFAIL) {					error = ENOMEM;					goto out;				}				panic("pmap_enter: no pv entries available");			}		}		/* lock pvh when adding */		pmap_enter_pv(pvh, pve, pmap, va, ptp);	} else {		/* new mapping is not PG_PVLIST.   free pve if we've got one */		pvh = NULL;		/* ensure !PG_PVLIST */		if (pve)			pmap_free_pv(pmap, pve);	}enter_now:	/*	 * at this point pvh is !NULL if we want the PG_PVLIST bit set	 */	npte = pa | protection_codes[prot] | PG_V;	if (pvh)		npte |= PG_PVLIST;	if (wired)		npte |= PG_W;	if (va < VM_MAXUSER_ADDRESS)		npte |= PG_u;	else if (va < VM_MAX_ADDRESS)		npte |= (PG_u | PG_RW);	/* XXXCDC: no longer needed? */	if (pmap == pmap_kernel())		npte |= pmap_pg_g;	ptes[i386_btop(va)] = npte;		/* zap! */	if ((opte & ~(PG_M|PG_U)) != npte && pmap_is_curpmap(pmap))		pmap_update_pg(va);	error = 0;out:	pmap_unmap_ptes(pmap);	PMAP_MAP_TO_HEAD_UNLOCK();	return error;}