#include "sys/param.h"#include "sys/config.h"#include "sys/mmu.h"#include "sys/types.h"#include "sys/sysmacros.h"#include "sys/systm.h"#include "sys/sysinfo.h"#include "sys/callo.h"#include "sys/dir.h"#include "sys/signal.h"#include "sys/user.h"#include "sys/proc.h"#include "sys/text.h"#include "sys/ipc.h"#include "sys/shm.h"#include "sys/psl.h"#include "sys/var.h"#include "sys/seg.h"#include "sys/context.h"#include "sys/map.h"#include "sys/errno.h"#include "sys/scat.h"typedef int	mem_t;short	segoff;		/* mmu segment offset */extern struct shmid_ds	*shm_shmem[];	/* ptrs to attached segments */extern struct shmpt_ds	shm_pte[];	/* segment attach points */extern struct shminfo	shminfo;	/* shared memory info structure *//* #define DUMPMM *//* #define HOWFAR *//* #define TRACEALL *//* * Load the user hardware page map. */sureg(){	register struct user *up;	register struct phys *ph;	register struct shmid_ds *sp;	register short *addr;	register a, i, j, page;	struct text *tp;	struct proc *p;	up = &u;	p = up->u_procp;	tp = p->p_textp;#ifdef HOWFARprintf("sureg:p_addr=0x%x, tsize=%d dsize=%d ssize=%d\n",	p->p_addr, up->u_ptsize, up->u_pdsize, up->u_pssize);#endif	SEG1_1 = 1;	/* SEG2_0 = 1; */	clearmmu();	addr = (short *)vtoseg(v.v_ustart);	if (tp != NULL) {		page = tp->x_caddr + segoff;		/* map a max of NPAGEPERSEG (256) 512-byte pages per segment */		for (i = up->u_ptsize; i > 0; i -= a) {			a = min(NPAGEPERSEG, (unsigned)i);			setmmu((short *)((int)addr | ACCSEG), page);			setmmu((short *)((int)addr | ACCLIM),				((up->u_xrw==RO)?ASRO:ASRW) | ((256-a) & 0xFF));			page += a;			addr = (short *)((long)addr + (1 << SEGSHIFT));		}		addr=(short *)vtoseg(ctob(stoc(ctos(btoc(v.v_ustart)+up->u_ptsize))));	} else		if (up->u_ptsize != 0)			addr = (short *)((long)addr +				ctob(stoc(ctos(up->u_ptsize))));		/* set up data segment */	page = p->p_addr + v.v_usize + segoff;	/* map a max of NPAGEPERSEG (256) 512-byte pages per segment */	for (i = up->u_pdsize; i > 0; i -= a) {		a = min(NPAGEPERSEG, (unsigned)i);		setmmu((short *)((int)addr | ACCSEG), page);		setmmu((short *)((int)addr | ACCLIM), ASRW | ((256-a) & 0xFF));		page += a;		addr = (short *)((long)addr + (1 << SEGSHIFT));	}		/* set up stack segment */	addr = (short *)(vtoseg(v.v_uend));	page += up->u_pssize;		/* stack is right after data */	for (i = up->u_pssize; i > 0; i -= a) {		addr = (short *)((long)addr - (1 << SEGSHIFT));		a = min(NPAGEPERSEG, (unsigned)i);		page -= NPAGEPERSEG;		setmmu((short *)((int)addr | ACCSEG), page);		setmmu((short *)((int)addr | ACCLIM), ASRWS | (a-1));	}		/* set up phys() */	for (ph = &u.u_phys[0]; ph < &u.u_phys[v.v_phys]; ph++) {	    if (ph->u_phsize) {		page = (ph->u_phpaddr >> PAGESHIFT) + segoff;		addr = (short *)vtoseg(ph->u_phladdr);		for (i = ph->u_phsize; i > 0; i -= a) {			a = min(NPAGEPERSEG, (unsigned)i);			/* if ((getmmu(vtoseg(addr)|ACCLIM)&PROTMASK) == ASINVAL) { */			if ((getmmu((short *)((int)addr | ACCLIM))&PROTMASK) == ASINVAL) {				setmmu((short *)((int)addr | ACCSEG), page);				setmmu((short *)((int)addr | ACCLIM), ASRW | ((256-a) & 0xFF));			}			page += a;			addr = (short *)((long)addr + (1 << SEGSHIFT));		    }		/*dumpmm1(1);	/**** DEBUG ****/	    }	}		/* set up shared memory */	for (i = (p - proc) * shminfo.shmseg; /* index of first shm_shmem[] */	     i < ((p - proc) + 1) * shminfo.shmseg; i++) {		sp = shm_shmem[i];		if (sp == NULL)			/* no more shared mem segments this process */			continue;		/* shm_scat is starting physical click number */		page = sp->shm_scat + segoff;		addr = (short *)vtoseg(shm_pte[i].shm_segbeg);		for (j = btoc(sp->shm_segsz); j > 0; j -= a) {			a = min(NPAGEPERSEG, (unsigned)j);			if ((getmmu((short *)((int)addr | ACCLIM))&PROTMASK) == ASINVAL) {				setmmu((short *)((int)addr | ACCSEG), page);				setmmu((short *)((int)addr | ACCLIM),						ASRW | ((256-a) & 0xFF));			}			page += a;			addr = (short *)((long)addr + (1 << SEGSHIFT));		}	}	}setmmu(addr, data)register short *addr;register data;{	int s;#ifdef TRACEALL#ifdef HOWFARif (data != ASINVAL)if (((int)addr & ACCSEG) == ACCSEG)	printf("setmmu:addr=0x%x, data=0x%x (0x%x)\n", addr, data, data<<9);else	printf("setmmu:addr=0x%x prot=0x%x, length=0x%x (%d)\n",		addr, data & PROTMASK, data, 256 - (data & 0xFF));#endif#endif	s = spl7();	SETUP_1 = 1;	*addr = data;	SETUP_0 = 1;	splx(s);}getmmu(addr)register short *addr;{	register data;	int s;	s = spl7();	SETUP_1 = 1;	data = *addr;	SETUP_0 = 1;	splx(s);	data &= 0xFFF;#ifdef TRACEALL#ifdef HOWFARif (((int)addr & ACCSEG) == ACCSEG)	printf("getmmu:addr=0x%x, data=0x%x (0x%x)\n", addr, data, data<<9);else	printf("getmmu:addr=0x%x prot=0x%x, length=0x%x (%d)\n",		addr, data & PROTMASK, data, 256 - (data & 0xFF));#endif#endif	return(data);}clearmmu(){	register data = 0xC00;		/* ASINVAL (d7) */	register inc = 0x20000;		/* address increment (d6) */	register s = 0;			/* saved priority (d5) */	register short i = 32-1;	/* loop counter (d4) */	register char *addr = (char *)0x8000;	/* address ACCLIM (a5) */#ifdef lint	*addr = (char)i;	*addr = (char)inc;	*addr = (char)data;#endif	s = spl7();	SETUP_1 = 1;	asm("loop:");	asm("	movw	d7,a5@");	asm("	addl	d6,a5");	asm("	movw	d7,a5@");	asm("	addl	d6,a5");	asm("	movw	d7,a5@");	asm("	addl	d6,a5");	asm("	movw	d7,a5@");	asm("	addl	d6,a5");	asm("	dbra	d4,loop");	SETUP_0 = 1;	splx(s);}/* * In V7, Set up software prototype segmentation * registers to implement the 3 pseudo * text,data,stack segment sizes passed * as arguments. * The argument sep specifies if the * text and data+stack segments are to * be separated. * The last argument determines whether the text * segment is read-write or read-only. * * u.u_ptsize etc replace the proto entries on the pdp11.  They * are used by sureg to set up the page map. *//* ARGSUSED */estabur(nt, nd, ns, sep, xrw)unsigned nt, nd, ns;{#ifdef HOWFARprintf("estabur:nt=%d nd=%d ns=%d rw=%d\n", nt, nd, ns, xrw);#endif	if (verureg(nt, nd, ns, xrw))		return(-1);	sureg();	return(0);}/* * verify user registers can be set up */verureg(nt, nd, ns, xrw)register unsigned nt;unsigned nd, ns;{	register int s;	/*	 * check for sufficient number of segment registers	 */	if (ctos(nt) + ctos(nd) + ctos(ns) > ctos(btoc(v.v_uend-v.v_ustart)))		goto bad;	s = nd + ns + v.v_usize;	if (nt == 0) {			/* non shared text */		if (s > maxmem)			goto bad;	} else {			/* shared text */		if (nt + s <= maxmem)	/* text+data can fit in largest hole */			goto ok;		goto bad;	}ok:	u.u_ptsize = nt;	/* essentially these pass args to sureg */	u.u_pdsize = nd;	u.u_pssize = ns;	u.u_xrw = xrw;	return(0);bad:#ifdef HOWFARprintf("verureg failure:nt=%d  nd=%d  ns=%d\n", nt, nd, ns);#endif	u.u_error = ENOMEM;	return(-1);}#ifdef DUMPMMchar *mmu_codes[] = {	"UNPREDICT-0",		/* 0 */	"UNPREDICT-1",		/* 1 */	"UNPREDICT-2",		/* 2 */	"UNDEFINED",		/* 3 */	"RO stack",		/* 4 */	"RO",			/* 5 */	"RW stack",		/* 6 */	"RW",			/* 7 */	"UNPREDICT-8",		/* 8 */	"IO",			/* 9 */	"UNPREDICT-A",		/* A */	"UNPREDICT-B",		/* B */	"INVALID",		/* C */	"UNPREDICT-D",		/* D */	"UNPREDICT-E",		/* E */	"SPIO",			/* F */};/* * dumpmm(system) *	dump the memory management registers *	if system is non-zero, also dump system registers */dumpmm(system)int system;{	printf("p_addr=0x%x tsize=0x%x dsize=0x%x ssize=0x%x\n",		u.u_procp->p_addr, u.u_ptsize, u.u_pdsize, u.u_pssize);	if (system)		dumpmm1(0);	dumpmm1(1);}dumpmm1(space){	register i, addr, prot, j, len;	printf("Context %d mmu registers\n", space);	printf("seg  logical physical  (clicks)  permission\n");	for (i = 0; i < 128; i++) {		if (space == 0)			SEG1_0 = 1;		else			SEG1_1 = 1;		/* SEG2_0 = 1; */		addr = getmmu((i << SEGSHIFT) | ACCSEG);		prot = getmmu((i << SEGSHIFT) | ACCLIM);		if ((prot & PROTMASK) == ASINVAL)			continue;		addr -= segoff;		len = prot & 0xFF;		if (prot & 0x100) {		/* data or stack segment */			j = i << SEGSHIFT;			len = 256 - len;			printf("0x%x  0x%x-0x%x 0x%x-0x%x (%d) %s\n", i, j,				j+ctob(len), addr, addr+len, len,				mmu_codes[(prot&PROTMASK)>>8]);		} else {			len++;			j = (i+1) << SEGSHIFT;			addr += NPAGEPERSEG;			printf("0x%x  0x%x-0x%x 0x%x-0x%x (%d) %s\n", i,				j-ctob(len), j, addr-len, addr, len,				mmu_codes[(prot&PROTMASK)>>8]);		}	}}#endif DUMPMM/* * check the size of a process */chksize(nt, nd, ns)register unsigned nt, nd, ns;{	if (nt + nd + ns + v.v_usize < maxmem )		return(0);	u.u_error = ENOMEM;	return(1);}