pmap->pm_stats.resident_count++;
pmap_enter(pmap, v, p, prot, flags)	pmap_t	pmap;	vaddr_t	v;	paddr_t	p;	vm_prot_t prot;	int flags;{	struct	pv_entry *pv, *tmp;	int	i, s, newpte, oldpte, *patch, index = 0; /* XXX gcc */#ifdef PMAPDEBUG	boolean_t wired = (flags & PMAP_WIRED) != 0;#endif#ifdef PMAPDEBUGif (startpmapdebug)	printf("pmap_enter: pmap %p v %lx p %lx prot %x wired %d flags %x\n",		    pmap, v, p, prot, wired, flags);#endif	RECURSESTART;	/* Find addess of correct pte */	if (v & KERNBASE) {		patch = (int *)Sysmap;		i = (v - KERNBASE) >> VAX_PGSHIFT;		newpte = (p>>VAX_PGSHIFT)|(prot&VM_PROT_WRITE?PG_KW:PG_KR);	} else {		if (v < 0x40000000) {			patch = (int *)pmap->pm_p0br;			i = (v >> VAX_PGSHIFT);			if (i >= (pmap->pm_p0lr & ~AST_MASK))				panic("P0 too small in pmap_enter");			patch = (int *)pmap->pm_p0br;			newpte = (p >> VAX_PGSHIFT) |			    (prot & VM_PROT_WRITE ? PG_RW : PG_RO);		} else {			patch = (int *)pmap->pm_p1br;			i = (v - 0x40000000) >> VAX_PGSHIFT;			if (i < pmap->pm_p1lr)				panic("pmap_enter: must expand P1");			if (v < pmap->pm_stack)				pmap->pm_stack = v;			newpte = (p >> VAX_PGSHIFT) |			    (prot & VM_PROT_WRITE ? PG_RW : PG_RO);		}		/*		 * Check if a pte page must be mapped in.		 */		index = ((u_int)&patch[i] - (u_int)pmap->pm_p0br) >> PGSHIFT;#ifdef DIAGNOSTIC		if ((index < 0) || (index >= NPTEPGS))			panic("pmap_enter: bad index %d", index);#endif		if (pmap->pm_refcnt[index] == 0) {			vaddr_t ptaddr = trunc_page((vaddr_t)&patch[i]);			paddr_t phys;			struct vm_page *pg;#ifdef DEBUG			if (kvtopte(&patch[i])->pg_pfn)				panic("pmap_enter: refcnt == 0");#endif			/*			 * It seems to be legal to sleep here to wait for			 * pages; at least some other ports do so.			 */			for (;;) {				pg = uvm_pagealloc(NULL, 0, NULL, 0);				if (pg != NULL)					break;				if (flags & PMAP_CANFAIL) {					RECURSEEND;					return (ENOMEM);				}				panic("pmap_enter: no free pages");			}			phys = VM_PAGE_TO_PHYS(pg);			bzero((caddr_t)(phys|KERNBASE), NBPG);			pmap_kenter_pa(ptaddr, phys,			    VM_PROT_READ|VM_PROT_WRITE);			pmap_update(pmap_kernel());		}	}	if (flags & PMAP_WIRED)		newpte |= PG_W;	oldpte = patch[i] & ~(PG_V|PG_M);	pv = pv_table + (p >> PGSHIFT);	/* wiring change? */	if (newpte == (oldpte | PG_W)) {		patch[i] |= PG_W; /* Just wiring change */		RECURSEEND;		return (0);	}	/* mapping unchanged? just return. */	if (newpte == oldpte) {		RECURSEEND;		return (0);	}	/* Changing mapping? */	oldpte &= PG_FRAME;	if ((newpte & PG_FRAME) != oldpte) {		/*		 * Mapped before? Remove it then.		 */		if (oldpte) {			RECURSEEND;			rensa(oldpte >> LTOHPS, (struct pte *)&patch[i]);			RECURSESTART;		} else if (pmap != pmap_kernel())				pmap->pm_refcnt[index]++; /* New mapping */		s = splimp();		if (pv->pv_pte == 0) {			pv->pv_pte = (struct pte *) & patch[i];			pv->pv_pmap = pmap;		} else {			tmp = get_pventry();			tmp->pv_pte = (struct pte *)&patch[i];			tmp->pv_pmap = pmap;			tmp->pv_next = pv->pv_next;			pv->pv_next = tmp;		}		splx(s);	} else {		/* No mapping change, just flush the TLB; necessary? */		mtpr(0, PR_TBIA);	}	pmap->pm_stats.resident_count++;	if (flags & VM_PROT_READ) {		pv->pv_attr |= PG_V;		newpte |= PG_V;	}	if (flags & VM_PROT_WRITE)		pv->pv_attr |= PG_M;	if (flags & PMAP_WIRED)		newpte |= PG_V; /* Not allowed to be invalid */	patch[i] = newpte;	patch[i+1] = newpte+1;	patch[i+2] = newpte+2;	patch[i+3] = newpte+3;	patch[i+4] = newpte+4;	patch[i+5] = newpte+5;	patch[i+6] = newpte+6;	patch[i+7] = newpte+7;	RECURSEEND;#ifdef DEBUG	if (pmap != pmap_kernel())		if (pmap->pm_refcnt[index] > VAX_NBPG/sizeof(struct pte))			panic("pmap_enter: refcnt %d", pmap->pm_refcnt[index]);#endif	if (pventries < 10)		more_pventries();	mtpr(0, PR_TBIA); /* Always; safety belt */	return (0);}