~kris/9p

9hist

dbced7d071fa7b8d606d09d934700802eaa09c88 — David du Colombier 33 years ago d439b1d
Plan 9 from Bell Labs 1992-11-29
6 files changed, 116 insertions(+), 127 deletions(-)

M power/dat.h
M power/debugger.c
M power/fns.h
M power/fptrap.c
M power/l.s
M power/trap.c
M power/dat.h => power/dat.h +4 -0
@@ 109,6 109,10 @@ struct Mach
	int	load;
	int	intr;
	int	ledval;			/* value last written to LED */
ulong cause;
ulong status;
ulong ur;
ulong sp;

	int	stack[1];
};

M power/debugger.c => power/debugger.c +1 -0
@@ 143,6 143,7 @@ printinfo(void)
		l = (ulong)(mp->proc);
		dprint("mach[%d]->proc/	%lux\r\n", i, l);
		dprint("mach[%d]->splpc/	%lux\r\n", i, mp->splpc);

		if(l & KZERO){
			p = (Proc*)l;
			l = (ulong)(p->upage);

M power/fns.h => power/fns.h +1 -1
@@ 24,7 24,7 @@ ulong	fcr31(void);
void	firmware(int);
void	flushmmu(void);
#define	flushpage(s)	icflush((void*)(s), BY2PG)
int	fptrap(Ureg*, ulong);
void	fptrap(Ureg*);
void	gettlb(int, ulong*);
ulong	gettlbvirt(int);
void	gotopc(ulong);

M power/fptrap.c => power/fptrap.c +21 -16
@@ 24,30 24,32 @@ enum	/* op */
static int	fpunimp(ulong);
static ulong	branch(Ureg*, ulong);

int
fptrap(Ureg *ur, ulong fcr31)
void
fptrap(Ureg *ur)
{
	ulong iw, npc;

	if((fcr31&(1<<17)) == 0)
		return 0;
	if((u->fpsave.fpstatus&(1<<17)) == 0)
		return;

	if(ur->cause & (1<<31))
		iw = *(ulong*)(ur->pc+4);
	else
		iw = *(ulong*)ur->pc;
	if(fpunimp(iw)){
		if(ur->cause & (1<<31)){
			npc = branch(ur, fcr31);
			if(npc)
				ur->pc = npc;
			else
				return 0;
		}else
			ur->pc += 4;
		u->fpsave.fpstatus = fcr31 & ~(1<<17);
		return 1;

	if(fpunimp(iw) == 0)
		return;

	if(ur->cause & (1<<31)){
		npc = branch(ur, u->fpsave.fpstatus);
		if(npc == 0)
			return;
		ur->pc = npc;
	}
	return 0;
	else
		ur->pc += 4;

	u->fpsave.fpstatus = u->fpsave.fpstatus & ~(1<<17);
}

static void


@@ 56,6 58,7 @@ unpack(FPsave *f, int fmt, int reg, int *sign, int *exp)
	*sign = 1;
	if(f->fpreg[reg] & 0x80000000)
		*sign = -1;

	switch(fmt){
	case 0:
		*exp = ((f->fpreg[reg]>>23)&0xFF) - ((1<<7)-2);


@@ 162,6 165,8 @@ fpunimp(ulong iw)
	}
	if(ed <= -(maxe-4)){	/* guess: underflow */
		zeroreg(&u->fpsave, fmt, fd, sd);
		/* Set underflow exception and sticky */
		u->fpsave.fpstatus |= (1<<3)|(1<<13);
		return 1;
	}
	return 0;

M power/l.s => power/l.s +10 -1
@@ 350,7 350,7 @@ wasuser:
	SUBU	$(UREGADDR-2*BY2WD-USERADDR), SP, R(USER)
	MOVW	$MPID, R1
	MOVB	3(R1), R1
	MOVW	$MACHADDR, R(MACH)		/* locn of mach 0 */
	MOVW	$MACHADDR, R(MACH)		/* locn of &mach[0] */
	AND	$7, R1
	SLL	$PGSHIFT, R1
	ADDU	R1, R(MACH)			/* add offset for mach # */


@@ 488,10 488,19 @@ TEXT	rfnote(SB), $0
	JMP	restore
	
TEXT	clrfpintr(SB), $0

	MOVW	M(STATUS), R3
	OR	$CU1, R3
	MOVW	R3, M(STATUS)
	WAIT

	MOVW	FCR31, R1
	MOVW	R1, R2
	AND	$~(0x3F<<12), R2
	MOVW	R2, FCR31

	AND	$~CU1, R3
	MOVW	R3, M(STATUS)
	RET

TEXT	savefpregs(SB), $0

M power/trap.c => power/trap.c +79 -109
@@ 7,23 7,10 @@
#include	"io.h"
#include	"../port/error.h"

/*
 *  vme interrupt routines
 */
void	(*vmevec[256])(int);

void	noted(Ureg**, ulong);
void	rfnote(Ureg**);

#define	LSYS	0x01
#define	LUSER	0x02
/*
 * CAUSE register
 */

#define	EXCCODE(c)	((c>>2)&0x0F)
#define	FPEXC		16

char *excname[] =
{
	"trap: external interrupt",


@@ 42,10 29,18 @@ char *excname[] =
	"trap: undefined 13",
	"trap: undefined 14",
	"trap: undefined 15",			/* used as sys call for debugger */
	/* the following is made up */
	"trap: floating point exception"	/* FPEXC */
};

char *fpcause[] =
{
	"inexact operation",
	"underflow",
	"overflow",
	"division by zero",
	"invalid operation",
};
char	*fpexcname(Ureg*, ulong, char*);
#define FPEXPMASK	(0x3f<<12)		/* Floating exception bits in fcr31 */

char *regname[]={
	"STATUS",	"PC",


@@ 69,91 64,65 @@ char *regname[]={
	"R2",		"R1",
};

long	ticks;

void
trap(Ureg *ur)
{
	int ecode;
	int user, cop, x;
	ulong fcr31;
	int user, cop, x, fpchk;
	char buf[2*ERRLEN], buf1[ERRLEN], *fpexcep;
*LED=~1;
	ecode = EXCCODE(ur->cause);
	LEDON(ecode);

	ecode = (ur->cause>>2)&0xf;
	user = ur->status&KUP;
	if(u)
	if(user)
		u->dbgreg = ur;
*LED=~2;

	fpchk = 0;
	if(u && u->p->fpstate == FPactive) {
		savefpregs(&u->fpsave);
		if((ur->status&CU1) == 0)		/* Paranoid */
			panic("FPactive but no CU1");
		u->p->fpstate = FPinactive;
		ur->status &= ~CU1;
		savefpregs(&u->fpsave);
		fptrap(ur);
		fpchk = 1;
	}
*LED=~3;

	switch(ecode){
	case CINT:
*LED=~4;
		if(ur->cause&INTR3) {			/* FP trap */
*LED=~5;
			if(u == 0 || u->p->fpstate != FPinactive)
				panic("fp intr3 no u or not inactive pc=%lux", ur->pc);

			fcr31 = clrfpintr();
			if(user == 0)
				panic("kernel floating point trap pc=%lux", ur->pc);
*LED=~6;

			clrfpintr();
			ur->cause &= ~INTR3;
			if(!fptrap(ur, fcr31)) {
				intr(ur);
				spllo();
				fpexcep	= fpexcname(ur, fcr31, buf1);
				sprint(buf, "sys: fp: %s", fpexcep);
				postnote(u->p, 1, buf, NDebug);
				break;
			}
*LED=~7;
		}
		intr(ur);
*LED=~8;
		break;

	case CTLBM:
	case CTLBL:
	case CTLBS:
*LED=~9;
		if(u == 0)
			panic("fault u==0 pc %lux addr %lux", ur->pc, ur->badvaddr);
*LED=~10;

		spllo();
		x = u->p->insyscall;
		u->p->insyscall = 1;
		faultmips(ur, user, ecode);
		u->p->insyscall = x;
*LED=~11;
		break;

	case CCPU:
*LED=~12;
		cop = (ur->cause>>28)&3;
		if(u && cop == 1) {
		if(user && u && cop == 1) {
			if(u->p->fpstate == FPinit) {
				restfpregs(&initfp, u->fpsave.fpstatus);
				u->p->fpstate = FPactive;
				ur->status |= CU1;
				u->p->fpstate = FPinactive;
				fcr31 = u->fpsave.fpstatus;
				u->fpsave = initfp;
				u->fpsave.fpstatus = fcr31;
				break;
			}
			if(u->p->fpstate == FPinactive) {
				restfpregs(&u->fpsave, u->fpsave.fpstatus);
				u->p->fpstate = FPactive;
				ur->status |= CU1;
			if(u->p->fpstate == FPinactive)
				break;
			}
		}
*LED=~13;
		/* Fallthrough */

	default:


@@ 170,22 139,27 @@ trap(Ureg *ur)
			spllo();
		exit(1);
	}
*LED=~14;

	splhi();
	if(user) {
*LED=~15;
		notify(ur);
*LED=~16;
		if(u->p->fpstate == FPinactive) {
			restfpregs(&u->fpsave, u->fpsave.fpstatus);
			u->p->fpstate = FPactive;
			ur->status |= CU1;
	if(fpchk) {
		fcr31 = u->fpsave.fpstatus;
		if((fcr31>>12) & ((fcr31>>7)|0x20) & 0x3f) {
			spllo();
			fpexcep	= fpexcname(ur, fcr31, buf1);
			sprint(buf, "sys: fp: %s", fpexcep);
			postnote(u->p, 1, buf, NDebug);
		}
*LED=~17;
	}
*LED=~0;
	LEDOFF(ecode);

	splhi();
	if(!user)
		return;

	notify(ur);
	if(u->p->fpstate == FPinactive) {
		restfpregs(&u->fpsave, u->fpsave.fpstatus&~FPEXPMASK);
		u->p->fpstate = FPactive;
		ur->status |= CU1;
	}
}

void


@@ 320,7 294,7 @@ intr(Ureg *ur)
		cause &= ~INTR5;
	}

	if(cause & (INTR2|INTR4)){
	if(cause & (INTR2|INTR4)) {
		LEDON(LEDclock);
		clock(ur);
		LEDOFF(LEDclock);


@@ 334,13 308,6 @@ intr(Ureg *ur)
char*
fpexcname(Ureg *ur, ulong fcr31, char *buf)
{
	static char *str[]={
		"inexact operation",
		"underflow",
		"overflow",
		"division by zero",
		"invalid operation",
	};
	int i;
	char *s;
	ulong fppc;


@@ 356,10 323,11 @@ fpexcname(Ureg *ur, ulong fcr31, char *buf)
		fcr31 &= (fcr31>>5);	/* anded with exceptions */
		for(i=0; i<5; i++)
			if(fcr31 & (1<<i))
				s = str[i];
				s = fpcause[i];
	}
	if(s == 0)
		return "no floating point exception";

	sprint(buf, "%s fppc=0x%lux", s, fppc);
	return buf;
}


@@ 370,14 338,16 @@ dumpstack(void)
	ulong l, v;
	extern ulong etext;

	if(u)
		for(l=(ulong)&l; l<USERADDR+BY2PG; l+=4){
			v = *(ulong*)l;
			if(KTZERO < v && v < (ulong)&etext){
				print("%lux=%lux\n", l, v);
				delay(100);
			}
	if(u == 0)
		return;

	for(l=(ulong)&l; l<USERADDR+BY2PG; l+=4){
		v = *(ulong*)l;
		if(KTZERO < v && v < (ulong)&etext){
			print("%lux=%lux\n", l, v);
			delay(100);
		}
	}
}

void


@@ 390,6 360,7 @@ dumpregs(Ureg *ur)
		print("registers for %s %d\n", u->p->text, u->p->pid);
	else
		print("registers for kernel\n");

	l = &ur->status;
	for(i=0; i<sizeof regname/sizeof(char*); i+=2, l+=2){
		print("%s\t%.8lux\t%s\t%.8lux\n", regname[i], l[0], regname[i+1], l[1]);


@@ 397,14 368,11 @@ dumpregs(Ureg *ur)
	}
}

/*
 * Call user, if necessary, with note
 */
int
notify(Ureg *ur)
{
	int l, sent;
	ulong s, sp;
	int l;
	ulong sp;
	Note *n;

	if(u->p->procctl)


@@ 412,11 380,11 @@ notify(Ureg *ur)
	if(u->nnote == 0)
		return 0;

	s = spllo();
	spllo();
	qlock(&u->p->debug);
	u->p->notepending = 0;
	n = &u->note[0];
	if(strncmp(n->msg, "sys:", 4) == 0){
	if(strncmp(n->msg, "sys:", 4) == 0) {
		l = strlen(n->msg);
		if(l > ERRLEN-15)	/* " pc=0x12345678\0" */
			l = ERRLEN-15;


@@ 424,7 392,7 @@ notify(Ureg *ur)
		sprint(n->msg+l, " pc=0x%lux", ur->pc);
	}

	if(n->flag!=NUser && (u->notified || u->notify==0)){
	if(n->flag != NUser && (u->notified || u->notify==0)) {
		if(n->flag == NDebug)
			pprint("suicide: %s\n", n->msg);



@@ 434,7 402,7 @@ notify(Ureg *ur)

	if(u->notified) {
		qunlock(&u->p->debug);
		splx(s);
		splhi();
		return 0;
	}
		


@@ 443,15 411,15 @@ notify(Ureg *ur)
		pexit(n->msg, n->flag!=NDebug);
	}
	u->svstatus = ur->status;
	sp = ur->usp;
	sp -= sizeof(Ureg);
	sp = ur->usp - sizeof(Ureg);

	if(sp&0x3 || !okaddr((ulong)u->notify, 1, 0)
	|| !okaddr(sp-ERRLEN-3*BY2WD, sizeof(Ureg)+ERRLEN-3*BY2WD, 0)){
	if(sp&0x3 || !okaddr((ulong)u->notify, BY2WD, 0)
	|| !okaddr(sp-ERRLEN-3*BY2WD, sizeof(Ureg)+ERRLEN-3*BY2WD, 1)) {
		pprint("suicide: bad address or sp in notify\n");
		qunlock(&u->p->debug);
		pexit("Suicide", 0);
	}

	u->ureg = (void*)sp;
	memmove((Ureg*)sp, ur, sizeof(Ureg));
	sp -= ERRLEN;


@@ 469,7 437,7 @@ notify(Ureg *ur)
	memmove(&u->note[0], &u->note[1], u->nnote*sizeof(Note));

	qunlock(&u->p->debug);
	splx(s);
	splhi();
	return 1;
}



@@ 482,32 450,30 @@ noted(Ureg **urp, ulong arg0)
	Ureg *nur;

	nur = u->ureg;
	if(nur->status!=u->svstatus){
	if(nur->status!=u->svstatus) {
		pprint("bad noted ureg status %lux\n", nur->status);
    Die:
		pexit("Suicide", 0);
	}
	qlock(&u->p->debug);
	if(!u->notified){
	if(!u->notified) {
		qunlock(&u->p->debug);
		pprint("call to noted() when not notified\n");
		goto Die;
		pexit("Suicide", 0);
	}
	u->notified = 0;
	memmove(*urp, u->ureg, sizeof(Ureg));
	(*urp)->r1 = u->svr1;
	switch(arg0){
	switch(arg0) {
	case NCONT:
		if(!okaddr(nur->pc, 1, 0) || !okaddr(nur->usp, BY2WD, 0)){
			pprint("suicide: trap in noted\n");
			qunlock(&u->p->debug);
			goto Die;
			pexit("Suicide", 0);
		}
		splhi();
		qunlock(&u->p->debug);
		rfnote(urp);
		break;
		/* never returns */

	default:
		pprint("unknown noted arg 0x%lux\n", arg0);


@@ 546,10 512,13 @@ syscall(Ureg *aur)
	 * smash them.  but we must save fpstatus.
	 */
	if(p->fpstate == FPactive) {
		if((ur->status&CU1) == 0)
			panic("syscall: FPactive but no CU1");
		u->fpsave.fpstatus = fcr31();
		p->fpstate = FPinit;
		ur->status &= ~CU1;
	}

	spllo();

	if(p->procctl)


@@ 587,6 556,7 @@ syscall(Ureg *aur)
	p->insyscall = 0;
	if(u->scallnr == NOTED)				/* ugly hack */
		noted(&aur, *(ulong*)(sp+BY2WD));	/* doesn't return */

	splhi();
	if(u->scallnr!=RFORK && (p->procctl || u->nnote)){
		ur->r1 = ret;			/* load up for noted() */