plan 9 kernel history: overview | file list | diff list

1991/0705/power/trap.c (diff list | history)

power/trap.c on 1990/0227
1990/0227    
#include	"u.h" 
#include	"lib.h" 
#include	"mem.h" 
#include	"dat.h" 
#include	"fns.h" 
#include	"ureg.h" 
#include	"io.h" 
1990/0511    
#include	"errno.h" 
1990/0227    
 
/* 
 *  vme interrupt routines 
 */ 
void	(*vmevec[256])(int); 
 
void	noted(Ureg**); 
void	rfnote(Ureg**); 
 
#define	LSYS	0x01 
#define	LUSER	0x02 
/* 
 * CAUSE register 
 */ 
 
#define	EXCCODE(c)	((c>>2)&0x0F) 
#define	FPEXC		16 
 
char *excname[] = 
{ 
	"external interrupt", 
	"TLB modification", 
	"TLB miss (load or fetch)", 
	"TLB miss (store)", 
	"address error (load or fetch)", 
	"address error (store)", 
	"bus error (fetch)", 
	"bus error (data load or store)", 
	"system call", 
	"breakpoint", 
	"reserved instruction", 
	"coprocessor unusable", 
	"arithmetic overflow", 
	"undefined 13", 
	"undefined 14", 
1990/0901    
	"undefined 15",				/* used as sys call for debugger */ 
1990/0227    
	/* the following is made up */ 
	"floating point exception"		/* FPEXC */ 
}; 
char	*fpexcname(ulong); 
 
char *regname[]={ 
	"STATUS",	"PC", 
	"SP",		"CAUSE", 
	"BADADDR",	"TLBVIRT", 
	"HI",		"LO", 
	"R31",		"R30", 
	"R28",		"R27", 
	"R26",		"R25", 
	"R24",		"R23", 
	"R22",		"R21", 
	"R20",		"R19", 
	"R18",		"R17", 
	"R16",		"R15", 
	"R14",		"R13", 
	"R12",		"R11", 
	"R10",		"R9", 
	"R8",		"R7", 
	"R6",		"R5", 
	"R4",		"R3", 
	"R2",		"R1", 
}; 
 
long	ticks; 
 
void 
trap(Ureg *ur) 
{ 
	int ecode; 
	int user; 
	ulong x; 
	char buf[ERRLEN]; 
 
1990/1214    
	SET(x); 
1990/0227    
	ecode = EXCCODE(ur->cause); 
	user = ur->status&KUP; 
	if(u) 
		u->p->pc = ur->pc;		/* BUG */ 
1991/0705    
 
1990/0227    
	switch(ecode){ 
	case CINT: 
		if(u && u->p->state==Running){ 
			if(u->p->fpstate == FPactive) { 
				if(ur->cause & INTR3){	/* FP trap */ 
					x = clrfpintr(); 
					ecode = FPEXC; 
				} 
				savefpregs(&u->fpsave); 
				u->p->fpstate = FPinactive; 
				ur->status &= ~CU1; 
				if(ecode == FPEXC) 
					goto Default; 
			} 
1991/0209    
		} 
		intr(ur); 
1990/0227    
		break; 
 
	case CTLBM: 
	case CTLBL: 
	case CTLBS: 
		if(u == 0) 
1990/0802    
			panic("fault u==0 pc %lux addr %lux", ur->pc, ur->badvaddr); 
1990/0227    
		if(u->p->fpstate == FPactive) { 
			savefpregs(&u->fpsave); 
			u->p->fpstate = FPinactive; 
			ur->status &= ~CU1; 
		} 
		spllo(); 
		x = u->p->insyscall; 
		u->p->insyscall = 1; 
1990/1212    
		faultmips(ur, user, ecode); 
1990/0227    
		u->p->insyscall = x; 
		break; 
 
	case CCPU: 
1990/0722    
		if(u && u->p && u->p->fpstate == FPinit) { 
1991/0314    
			restfpregs(&initfp, u->fpsave.fpstatus); 
1990/0227    
			u->p->fpstate = FPactive; 
			ur->status |= CU1; 
			break; 
		} 
1990/0722    
		if(u && u->p && u->p->fpstate == FPinactive) { 
1991/0314    
			restfpregs(&u->fpsave, u->fpsave.fpstatus); 
1990/0227    
			u->p->fpstate = FPactive; 
			ur->status |= CU1; 
			break; 
		} 
1990/0722    
		goto Default; 
1990/0227    
 
	default: 
1990/0722    
		if(u && u->p && u->p->fpstate == FPactive){ 
			savefpregs(&u->fpsave); 
			u->p->fpstate = FPinactive; 
			ur->status &= ~CU1; 
		} 
1990/0227    
	Default: 
		/* 
1991/0705    
		 * This isn't good enough; can still deadlock because we may  
		 * hold print's locks in this processor. 
1990/0227    
		 */ 
		if(user){ 
			spllo(); 
			if(ecode == FPEXC) 
1990/1110    
				sprint(buf, "sys: fp: %s FCR31 %lux", fpexcname(x), x); 
1990/0227    
			else 
1991/0705    
				sprint(buf, "sys: %s pc=0x%lux", excname[ecode], ur->pc); 
1991/0425    
 
1990/0227    
			postnote(u->p, 1, buf, NDebug); 
		}else{ 
			print("%s %s pc=%lux\n", user? "user": "kernel", excname[ecode], ur->pc); 
			if(ecode == FPEXC) 
				print("fp: %s FCR31 %lux\n", fpexcname(x), x); 
			dumpregs(ur); 
			if(m->machno == 0) 
				spllo(); 
			exit(); 
		} 
	} 
1991/0705    
 
	if(user) { 
		if(u->p->procctl) 
			procctl(u->p); 
		if(u->nnote) 
			notify(ur); 
	} 
 
1990/0227    
	splhi(); 
	if(user && u && u->p->fpstate == FPinactive) { 
1991/0314    
		restfpregs(&u->fpsave, u->fpsave.fpstatus); 
1990/0227    
		u->p->fpstate = FPactive; 
		ur->status |= CU1; 
	} 
} 
 
void 
1991/0209    
intr(Ureg *ur) 
1990/0227    
{ 
1991/0212    
	int i, any; 
1991/0316    
	uchar xxx; 
1991/0212    
	uchar pend, npend; 
1990/0227    
	long v; 
1991/0209    
	ulong cause; 
1991/0219    
	static int bogies; 
1990/0227    
 
1991/0425    
	m->intr++; 
1991/0209    
	cause = ur->cause&(INTR5|INTR4|INTR3|INTR2|INTR1); 
1990/0227    
	if(cause & (INTR2|INTR4)){ 
1991/0209    
		clock(ur); 
1990/0227    
		cause &= ~(INTR2|INTR4); 
	} 
	if(cause & INTR1){ 
		duartintr(); 
		cause &= ~INTR1; 
	} 
	if(cause & INTR5){ 
1991/0212    
		any = 0; 
1990/0227    
		if(!(*MPBERR1 & (1<<8))){ 
1990/0911    
			print("MP bus error %lux %lux\n", *MPBERR0, *MPBERR1); 
1990/0227    
			*MPBERR0 = 0; 
			i = *SBEADDR; 
1990/1214    
			USED(i); 
1991/0212    
			any = 1; 
1990/0227    
		} 
 
		/* 
		 *  directions from IO2 manual 
		 *  1. clear all IO2 masks 
		 */ 
1991/0212    
		*IO2CLRMASK = 0xff000000; 
1990/0227    
 
		/* 
		 *  2. wait for interrupt in progress 
		 */ 
		while(!(*INTPENDREG & (1<<5))) 
			; 
 
		/* 
		 *  3. read pending interrupts 
		 */ 
1991/0316    
		pend = SBCCREG->fintpending; 
		npend = pend; 
1990/0227    
 
		/* 
		 *  4. clear pending register 
		 */ 
		i = SBCCREG->flevel; 
1990/1214    
		USED(i); 
1991/0316    
 
		/* 
		 *  4a. attempt to fix problem 
		 */ 
		if(!(*INTPENDREG & (1<<5))) 
			print("pause again\n"); 
		while(!(*INTPENDREG & (1<<5))) 
			; 
		xxx = SBCCREG->fintpending; 
		if(xxx){ 
			print("new pend %ux\n", xxx); 
			npend = pend |= xxx; 
			i = SBCCREG->flevel; 
1991/0425    
			USED(i); 
1991/0316    
		} 
1990/0227    
 
		/* 
		 *  5a. process lance, scsi 
		 */ 
		if(pend & 1) { 
			v = INTVECREG->i[0].vec; 
1990/0907    
			if(!(v & (1<<12))){ 
				print("io2 mp bus error %d %lux %lux\n", 0, 
					*MPBERR0, *MPBERR1); 
				*MPBERR0 = 0; 
1991/0212    
				any = 1; 
1990/0907    
			} 
1990/0911    
			if(ioid < IO3R1){ 
1991/0212    
				if(!(v & 7)) 
					any = 1; 
1990/0907    
				if(!(v & (1<<2))) 
					lanceintr(); 
				if(!(v & (1<<1))) 
					lanceparity(); 
				if(!(v & (1<<0))) 
					print("SCSI interrupt\n"); 
1991/0212    
			}else{ 
				if(v & 7) 
					any = 1; 
1990/0907    
				if(v & (1<<2)) 
1990/0911    
					lanceintr(); 
1990/0907    
				if(v & (1<<1)) 
					print("SCSI 1 interrupt\n"); 
				if(v & (1<<0)) 
					print("SCSI 0 interrupt\n"); 
			} 
1990/0227    
		} 
		/* 
		 *  5b. process vme 
1991/0212    
		 *  i can guess your level 
1990/0227    
		 */ 
1991/0212    
		for(i=1; pend>>=1; i++){ 
1990/0227    
			if(pend & 1) { 
				v = INTVECREG->i[i].vec; 
1990/0907    
				if(!(v & (1<<12))){ 
1991/0212    
					print("io2 mp bus error %d %lux %lux\n", 
						i, *MPBERR0, *MPBERR1); 
1990/0907    
					*MPBERR0 = 0; 
				} 
1990/0227    
				v &= 0xff; 
				(*vmevec[v])(v); 
1991/0212    
				any = 1; 
1990/0227    
			} 
		} 
		/* 
1991/0212    
		 *  if nothing else, assume bus error 
		 */ 
1991/0219    
		if(!any && bogies++<100){ 
1991/0212    
			print("bogus intr lvl 5 pend %lux on %d\n", npend, m->machno); 
			delay(100); 
		} 
		/* 
1990/0227    
		 *  6. re-enable interrupts 
		 */ 
1991/0212    
		*IO2SETMASK = 0xff000000; 
1990/0227    
		cause &= ~INTR5; 
	} 
	if(cause) 
		panic("cause %lux %lux\n", u, cause); 
} 
 
char * 
fpexcname(ulong x) 
{ 
	static char *str[]={ 
		"inexact operation", 
		"underflow", 
		"overflow", 
		"division by zero", 
		"invalid operation", 
		"unimplemented operation", 
	}; 
	int i; 
 
	x >>= 12; 
	for(i=0; i<6; i++, x>>=1) 
		if(x & 1) 
			return str[i]; 
	return "no floating point exception"; 
} 
1990/03091    
 
1990/0227    
void 
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); 
		} 
} 
 
void 
dumpregs(Ureg *ur) 
{ 
	int i; 
	ulong *l; 
	int (*pr)(char*, ...); 
 
	if(u) 
		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]); 
} 
 
/* 
 * Call user, if necessary, with note 
 */ 
void 
notify(Ureg *ur) 
{ 
	ulong sp; 
 
	lock(&u->p->debug); 
	if(u->nnote==0){ 
		unlock(&u->p->debug); 
		return; 
	} 
	if(u->note[0].flag!=NUser && (u->notified || u->notify==0)){ 
		if(u->note[0].flag == NDebug) 
			pprint("suicide: %s\n", u->note[0].msg); 
    Die: 
		unlock(&u->p->debug); 
		pexit(u->note[0].msg, u->note[0].flag!=NDebug); 
	} 
	if(!u->notified){ 
		if(!u->notify) 
			goto Die; 
1991/0503    
		u->svstatus = ur->status; 
1990/0816    
		sp = ur->usp; 
1990/0227    
		sp -= sizeof(Ureg); 
1991/0705    
		if(waserror()){ 
			pprint("suicide: trap in notify\n"); 
			pexit("Suicide", 0); 
		} 
		validaddr((ulong)u->notify, 1, 0); 
		validaddr(sp-ERRLEN-3*BY2WD, sizeof(Ureg)+ERRLEN-3*BY2WD, 0); 
		poperror(); 
1990/0227    
		u->ureg = (void*)sp; 
1991/0318    
		memmove((Ureg*)sp, ur, sizeof(Ureg)); 
1990/0227    
		sp -= ERRLEN; 
1991/0318    
		memmove((char*)sp, u->note[0].msg, ERRLEN); 
1990/0227    
		sp -= 3*BY2WD; 
		*(ulong*)(sp+2*BY2WD) = sp+3*BY2WD;	/* arg 2 is string */ 
		*(ulong*)(sp+1*BY2WD) = (ulong)u->ureg;	/* arg 1 is ureg* */ 
		*(ulong*)(sp+0*BY2WD) = 0;		/* arg 0 is pc */ 
1990/0816    
		ur->usp = sp; 
1990/0227    
		ur->pc = (ulong)u->notify; 
		u->notified = 1; 
		u->nnote--; 
1991/0318    
		memmove(&u->note[0], &u->note[1], u->nnote*sizeof(Note)); 
1990/0227    
	} 
	unlock(&u->p->debug); 
} 
 
/* 
 * Return user to state before notify() 
 */ 
void 
noted(Ureg **urp) 
{ 
1991/0503    
	Ureg *nur; 
 
	nur = u->ureg; 
1991/0602    
	if(waserror()){ 
		pprint("suicide: trap in noted\n"); 
		pexit("Suicide", 0); 
	} 
1991/0503    
	validaddr(nur->pc, 1, 0); 
	validaddr(nur->usp, BY2WD, 0); 
1991/0602    
	poperror(); 
1991/0503    
	if(nur->status!=u->svstatus){ 
		pprint("bad noted ureg status %ux\n", nur->status); 
		pexit("Suicide", 0); 
	} 
1990/0227    
	lock(&u->p->debug); 
1990/0619    
	if(!u->notified){ 
		unlock(&u->p->debug); 
		return; 
	} 
1990/0227    
	u->notified = 0; 
1991/0318    
	memmove(*urp, u->ureg, sizeof(Ureg)); 
1990/1113    
	(*urp)->r1 = -1;	/* return error from the interrupted call */ 
1990/0227    
	unlock(&u->p->debug); 
	splhi(); 
	rfnote(urp); 
} 
 
 
#undef	CHDIR	/* BUG */ 
1990/1122    
#include "/sys/src/libc/mips9sys/sys.h" 
1990/0227    
 
typedef long Syscall(ulong*); 
1990/11211    
Syscall sysbind, sysbrk_, syschdir, sysclose, syscreate, sysdeath; 
1990/0227    
Syscall	sysdup, syserrstr, sysexec, sysexits, sysfork, sysforkpgrp; 
1990/11211    
Syscall	sysfstat, sysfwstat, sysgetpid, sysmount, sysnoted; 
1990/0227    
Syscall	sysnotify, sysopen, syspipe, sysr1, sysread, sysremove, sysseek; 
1991/0705    
Syscall syssleep, sysstat, syswait, syswrite, syswstat, sysalarm, syssegbrk; 
Syscall syssegattach, syssegdetach, syssegfree, syssegflush; 
 
1990/0227    
Syscall *systab[]={ 
	[SYSR1]		sysr1, 
1990/11211    
	[ERRSTR]	syserrstr, 
1990/0227    
	[BIND]		sysbind, 
	[CHDIR]		syschdir, 
	[CLOSE]		sysclose, 
	[DUP]		sysdup, 
1991/0513    
	[ALARM]		sysalarm, 
1990/0227    
	[EXEC]		sysexec, 
	[EXITS]		sysexits, 
	[FORK]		sysfork, 
	[FORKPGRP]	sysforkpgrp, 
	[FSTAT]		sysfstat, 
1991/0705    
	[SEGBRK]	syssegbrk, 
1990/0227    
	[MOUNT]		sysmount, 
	[OPEN]		sysopen, 
	[READ]		sysread, 
	[SEEK]		sysseek, 
	[SLEEP]		syssleep, 
	[STAT]		sysstat, 
	[WAIT]		syswait, 
	[WRITE]		syswrite, 
	[PIPE]		syspipe, 
	[CREATE]	syscreate, 
1990/11211    
	[___USERSTR___]	sysdeath, 
1990/0227    
	[BRK_]		sysbrk_, 
	[REMOVE]	sysremove, 
	[WSTAT]		syswstat, 
	[FWSTAT]	sysfwstat, 
	[NOTIFY]	sysnotify, 
	[NOTED]		sysnoted, 
1991/0705    
	[SEGATTACH]	syssegattach, 
	[SEGDETACH]	syssegdetach, 
	[SEGFREE]	syssegfree, 
	[SEGFLUSH]	syssegflush, 
1990/0227    
}; 
 
long 
syscall(Ureg *aur) 
{ 
	long ret; 
	ulong sp; 
	ulong r1; 
	Ureg *ur; 
1990/0511    
	char *msg; 
1990/0227    
 
1991/0425    
	m->syscall++; 
1990/0227    
	u->p->insyscall = 1; 
	ur = aur; 
1990/0310    
	u->p->pc = ur->pc;		/* BUG */ 
1990/0901    
	ur->cause = 15<<2;		/* for debugging: system call is undef 15; 
1990/0227    
	/* 
	 * since the system call interface does not 
1991/0314    
	 * guarantee anything about registers, we can 
	 * smash them.  but we must save fpstatus. 
1990/0227    
	 */ 
	if(u->p->fpstate == FPactive) { 
1991/0314    
		u->fpsave.fpstatus = fcr31(); 
1990/0722    
		u->p->fpstate = FPinit; 
1990/0227    
		ur->status &= ~CU1; 
	} 
	spllo(); 
1991/0705    
 
	if(u->p->procctl) 
		procctl(u->p); 
 
1990/0227    
	r1 = ur->r1; 
	sp = ur->sp; 
	u->nerrlab = 0; 
	ret = -1; 
1990/0511    
	if(!waserror()){ 
		if(r1 >= sizeof systab/BY2WD){ 
			pprint("bad sys call number %d pc %lux\n", r1, ((Ureg*)UREGADDR)->pc); 
1990/1110    
			msg = "sys: bad sys call"; 
1990/0511    
	    Bad: 
			postnote(u->p, 1, msg, NDebug); 
1990/11211    
			error(Ebadarg); 
1990/0511    
		} 
		if(sp & (BY2WD-1)){ 
			pprint("odd sp in sys call pc %lux sp %lux\n", ((Ureg*)UREGADDR)->pc, ((Ureg*)UREGADDR)->sp); 
1990/1110    
			msg = "sys: odd stack"; 
1990/0511    
			goto Bad; 
		} 
1991/0625    
		if(((ulong*)ur->pc)[-2] != 0x23bdfffc)	/* new calling convention: look for ADD $-4, SP */ 
			sp -= BY2WD; 
1990/11211    
		if(sp<(USTKTOP-BY2PG) || sp>(USTKTOP-5*BY2WD)) 
			validaddr(sp, 5*BY2WD, 0); 
1990/0227    
		ret = (*systab[r1])((ulong*)(sp+2*BY2WD)); 
1990/0511    
	} 
1990/0227    
	ur->pc += 4; 
	u->nerrlab = 0; 
1991/0705    
	 
	if(u->p->procctl) 
		procctl(u->p); 
 
1990/0227    
	splhi(); 
1990/03091    
	u->p->insyscall = 0; 
1990/0227    
	if(r1 == NOTED)	/* ugly hack */ 
		noted(&aur);	/* doesn't return */ 
	if(u->nnote){ 
		ur->r1 = ret; 
		notify(ur); 
	} 
1991/0705    
 
1990/0227    
	return ret; 
} 
 
1990/1226    
void 
execpc(ulong entry) 
{ 
	((Ureg*)UREGADDR)->pc = entry - 4;		/* syscall advances it */ 
} 
 
1990/11211    
#include "errstr.h" 
 
1990/0227    
void 
1990/11211    
error(int code) 
1990/0227    
{ 
1991/0115    
	strncpy(u->error, errstrtab[code], ERRLEN); 
1990/11211    
	nexterror(); 
} 
 
void 
errors(char *err) 
{ 
1991/0322    
	strncpy(u->error, err, ERRLEN); 
1990/0227    
	nexterror(); 
} 
 
void 
nexterror(void) 
{ 
	gotolabel(&u->errlab[--u->nerrlab]); 
} 
 
void 
novme(int v) 
{ 
	static count = 0; 
 
	print("vme intr 0x%.2x\n", v); 
	count++; 
	if(count >= 10) 
		panic("too many vme intr"); 
} 
 
void 
setvmevec(int v, void (*f)(int)) 
{ 
	void (*g)(int); 
 
	v &= 0xff; 
	g = vmevec[v]; 
	if(g && g != novme) 
		print("second setvmevec to 0x%.2x\n", v); 
	vmevec[v] = f; 
} 


source code copyright © 1990-2005 Lucent Technologies; see license
Plan 9 distribution
comments to russ cox (rsc@swtch.com)