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

1991/1218/gnot/trap.c (diff list | history)

1991/1218/sys/src/9/gnot/trap.c:1,3831992/0108/sys/src/9/gnot/trap.c:1,383 (short | long | prev | next)
1990/03091    
#include	"u.h" 
#include	"lib.h" 
#include	"mem.h" 
#include	"dat.h" 
#include	"fns.h" 
#include	"ureg.h" 
#include	"io.h" 
1990/0513    
#include	"errno.h" 
1990/03091    
 
void	notify(Ureg*); 
1991/0717    
void	noted(Ureg*, ulong); 
1991/0503    
void	rfnote(Ureg*); 
1990/03091    
 
char *regname[]={ 
	"R0", 
	"R1", 
	"R2", 
	"R3", 
	"R4", 
	"R5", 
	"R6", 
	"R7", 
	"A0", 
	"A1", 
	"A2", 
	"A3", 
	"A4", 
	"A5", 
	"A6", 
	"A7", 
}; 
 
long	ticks; 
 
char *trapname[]={ 
	"reset isp", 
	"reset ipc", 
	"bus error", 
	"address error", 
	"illegal instruction", 
	"zero divide", 
	"chk, chk2 instruction", 
1991/1218    
	"trapcc instruction", 
1990/03091    
	"privilege violation", 
	"trace", 
	"line 1010 emulator", 
	"line 1111 emulator", 
	"reserved", 
1991/1218    
	"coprocessor protocol violation", 
1990/03091    
	"format error", 
	"uninitialized interrupt", 
	"unassigned 0x40", 
	"unassigned 0x44", 
	"unassigned 0x48", 
	"unassigned 0x4C", 
	"unassigned 0x50", 
	"unassigned 0x54", 
	"unassigned 0x58", 
	"unassigned 0x5C", 
	"spurious interrupt", 
	"level 1 autovector (tac)", 
	"level 2 autovector (port)", 
	"level 3 autovector (incon)", 
	"level 4 autovector (mouse)", 
	"level 5 autovector (uart)", 
	"level 6 autovector (sync)", 
	"level 7 autovector", 
}; 
 
1991/12171    
char *fptrapname[]={ 
1991/1218    
[49-49]	"inexact result", 
[50-49]	"divide by zero", 
[51-49]	"underflow", 
[52-49]	"operand error", 
[53-49]	"overflow", 
[54-49]	"signaling NaN", 
1991/12171    
}; 
 
1990/03091    
char* 
1991/1113    
excname(unsigned vo, ulong pc) 
1990/03091    
{ 
	static char buf[32];	/* BUG: not reentrant! */ 
 
	vo &= 0x0FFF; 
	vo >>= 2; 
1991/1113    
	if(vo < sizeof trapname/sizeof(char*)){ 
		/* special case, and pc will be o.k. */ 
		if(vo==4 && *(ushort*)pc==0x4848) 
			return "breakpoint"; 
1991/1218    
		sprint(buf, "trap: %s", trapname[vo]); 
		return buf; 
1991/1113    
	} 
1991/1218    
	if(49<=vo && vo<=54){ 
		sprint(buf, "fp: %s", fptrapname[vo-49]); 
		return buf; 
	} 
1990/03091    
	sprint(buf, "offset 0x%ux", vo<<2); 
	return buf; 
} 
 
void 
trap(Ureg *ur) 
{ 
	int user; 
	char buf[64]; 
 
	user = !(ur->sr&SUPER); 
 
1991/1112    
	if(u) { 
1990/03091    
		u->p->pc = ur->pc;		/* BUG */ 
1991/1112    
		u->dbgreg = ur; 
	} 
1990/03091    
	if(user){ 
1991/1218    
		sprint(buf, "sys: %s", excname(ur->vo, ur->pc)); 
1990/03091    
		postnote(u->p, 1, buf, NDebug); 
	}else{ 
1991/1113    
		print("kernel trap %s pc=0x%lux\n", excname(ur->vo, ur->pc), ur->pc); 
1990/03091    
		dumpregs(ur); 
		exit(); 
	} 
1991/0705    
 
1991/1112    
	if(user) 
		notify(ur); 
1990/03091    
} 
 
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; 
 
	if(u) 
		print("registers for %s %d\n", u->p->text, u->p->pid); 
	else 
		print("registers for kernel\n"); 
	print("SR=%ux PC=%lux VO=%lux, USP=%lux\n", ur->sr, ur->pc, ur->vo, ur->usp); 
	l = &ur->r0; 
	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 
1992/0108    
int 
1990/03091    
notify(Ureg *ur) 
{ 
1991/1218    
	int l; 
1991/1114    
	ulong s, sp; 
1991/1218    
	Note *n; 
1990/03091    
 
1991/1112    
	if(u->p->procctl) 
		procctl(u->p); 
	if(u->nnote==0) 
1990/03091    
		return; 
1992/0108    
	if(u->nnote == 0) 
		return 0; 
1991/1112    
 
1991/1114    
	s = spllo(); 
1991/1216    
	qlock(&u->p->debug); 
1991/0727    
	u->p->notepending = 0; 
1991/1218    
	n = &u->note[0]; 
	if(strncmp(n->msg, "sys:", 4) == 0){ 
		l = strlen(n->msg); 
		if(l > ERRLEN-15)	/* " pc=0x12345678\0" */ 
			l = ERRLEN-15; 
		sprint(n->msg+l, " pc=0x%.8lux", ur->pc); 
	} 
	if(n->flag!=NUser && (u->notified || u->notify==0)){ 
1990/03091    
		if(u->note[0].flag == NDebug) 
1991/1218    
			pprint("suicide: %s\n", n->msg); 
1990/03091    
    Die: 
1991/1216    
		qunlock(&u->p->debug); 
1991/1218    
		pexit(n->msg, n->flag!=NDebug); 
1990/03091    
	} 
	if(!u->notified){ 
		if(!u->notify) 
			goto Die; 
1991/0503    
		u->svvo = ur->vo; 
		u->svsr = ur->sr; 
1990/0816    
		sp = ur->usp; 
1990/03091    
		sp -= sizeof(Ureg); 
1991/0722    
		if(waserror()){ 
			pprint("suicide: trap in notify\n"); 
1991/1216    
			qunlock(&u->p->debug); 
1991/0722    
			pexit("Suicide", 0); 
		} 
		validaddr((ulong)u->notify, 1, 0); 
		validaddr(sp-ERRLEN-3*BY2WD, sizeof(Ureg)+ERRLEN-3*BY2WD, 0); 
		poperror(); 
1990/03091    
		u->ureg = (void*)sp; 
1991/0318    
		memmove((Ureg*)sp, ur, sizeof(Ureg)); 
1990/03091    
		sp -= ERRLEN; 
1991/0318    
		memmove((char*)sp, u->note[0].msg, ERRLEN); 
1990/03091    
		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/03091    
		ur->pc = (ulong)u->notify; 
1991/0719    
		ur->vo = 0x0080;	/* pretend we're returning from syscall */ 
1990/03091    
		u->notified = 1; 
		u->nnote--; 
1991/0717    
		memmove(&u->lastnote, &u->note[0], sizeof(Note)); 
1991/0318    
		memmove(&u->note[0], &u->note[1], u->nnote*sizeof(Note)); 
1990/03091    
	} 
1991/1216    
	qunlock(&u->p->debug); 
1991/1114    
	splx(s); 
1992/0108    
	return 1; 
1990/03091    
} 
 
/* 
 * Return user to state before notify() 
 */ 
void 
1991/0717    
noted(Ureg *ur, ulong arg0) 
1990/03091    
{ 
1991/0503    
	Ureg *nur; 
 
	nur = u->ureg; 
	if(nur->sr!=u->svsr || nur->vo!=u->svvo){ 
		pprint("bad noted ureg sr %ux vo %ux\n", nur->sr, nur->vo); 
1991/0814    
    Die: 
1991/0503    
		pexit("Suicide", 0); 
	} 
1991/1216    
	qlock(&u->p->debug); 
1990/0619    
	if(!u->notified){ 
1991/1216    
		qunlock(&u->p->debug); 
1991/0814    
		pprint("call to noted() when not notified\n"); 
		goto Die; 
1990/0619    
	} 
1990/03091    
	u->notified = 0; 
1991/0503    
	memmove(ur, u->ureg, sizeof(Ureg)); 
1991/0717    
	switch(arg0){ 
	case NCONT: 
1991/0814    
		if(waserror()){ 
			pprint("suicide: trap in noted\n"); 
1991/1216    
			qunlock(&u->p->debug); 
1991/0814    
			goto Die; 
		} 
		validaddr(nur->pc, 1, 0); 
		validaddr(nur->usp, BY2WD, 0); 
		poperror(); 
1991/0717    
		splhi(); 
1991/1216    
		qunlock(&u->p->debug); 
1991/0717    
		rfnote(ur); 
		break; 
		/* never returns */ 
 
	default: 
		pprint("unknown noted arg 0x%lux\n", arg0); 
		u->lastnote.flag = NDebug; 
		/* fall through */ 
		 
1991/0718    
	case NDFLT: 
1991/0717    
		if(u->lastnote.flag == NDebug) 
			pprint("suicide: %s\n", u->lastnote.msg); 
1991/1216    
		qunlock(&u->p->debug); 
1991/0717    
		pexit(u->lastnote.msg, u->lastnote.flag!=NDebug); 
	} 
1990/03091    
} 
 
1991/0731    
#include "../port/systab.h" 
1990/03091    
 
long 
syscall(Ureg *aur) 
{ 
1991/0614    
	int i; 
1990/03091    
	long ret; 
	ulong sp; 
	ulong r0; 
	Ureg *ur; 
1990/0513    
	char *msg; 
1990/03091    
 
	u->p->insyscall = 1; 
	ur = aur; 
1991/1112    
	u->dbgreg = aur; 
1990/0312    
	u->p->pc = ur->pc; 
1990/03091    
	if(ur->sr & SUPER) 
		panic("recursive system call"); 
	/* 
	 * since the system call interface does not 
1990/08163    
	 * guarantee anything about registers, but the fpcr is more than 
	 * just a register...  BUG 
1990/03091    
	 */ 
1990/08163    
	splhi(); 
	fpsave(&u->fpsave); 
	if(u->p->fpstate==FPactive || u->fpsave.type){ 
1990/0905    
		fprestore(&initfp); 
1990/08163    
		u->p->fpstate = FPinit; 
		m->fpstate = FPinit; 
1990/03091    
	} 
1990/08163    
	spllo(); 
1991/1108    
 
	if(u->p->procctl) 
		procctl(u->p); 
 
1990/03091    
	r0 = ur->r0; 
	sp = ur->usp; 
 
	u->nerrlab = 0; 
	ret = -1; 
1990/0511    
	if(!waserror()){ 
1991/0731    
		if(r0 >= sizeof systab/sizeof systab[0]){ 
1990/0513    
			pprint("bad sys call number %d pc %lux\n", r0, ((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)){ 
1991/0705    
			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/0614    
		if(sp<(USTKTOP-BY2PG) || sp>(USTKTOP-(1+MAXSYSARG)*BY2WD)) 
			validaddr(sp, (1+MAXSYSARG)*BY2WD, 0); 
1991/0926    
		u->p->psstate = sysctab[r0]; 
1990/0515    
		ret = (*systab[r0])((ulong*)(sp+BY2WD)); 
1991/0614    
		poperror(); 
1990/0511    
	} 
1991/0705    
 
1991/1108    
	u->nerrlab = 0; 
1990/03091    
	u->p->insyscall = 0; 
1991/0926    
	u->p->psstate = 0; 
1991/0705    
 
	if(r0 == NOTED)		/* ugly hack */ 
1991/0717    
		noted(aur, *(ulong*)(sp+BY2WD));	/* doesn't return */ 
1991/1114    
	splhi(); 
	if(r0!=FORK && (u->p->procctl || u->nnote)){ 
1990/03091    
		ur->r0 = ret; 
		notify(ur); 
	} 
	return ret; 
} 
 
1991/1214    
long 
execregs(ulong entry, ulong ssize, ulong nargs) 
1990/1226    
{ 
1991/1214    
	ulong *sp; 
 
	sp = (ulong*)(USTKTOP - ssize); 
	*--sp = nargs; 
	((Ureg*)UREGADDR)->usp = (ulong)sp; 
1990/1226    
	((Ureg*)UREGADDR)->pc = entry; 
1991/1214    
	return USTKTOP-BY2WD;			/* address of user-level clock */ 
1991/1112    
} 
 
/* This routine must save the values of registers the user is not permitted to write 
 * from devproc and the restore the saved values before returning 
 */ 
void 
setregisters(Ureg *xp, char *pureg, char *uva, int n) 
{ 
	ushort sr; 
	ulong magic; 
	ushort vo; 
	char microstate[UREGVARSZ]; 
 
	sr = xp->sr; 
	vo = xp->vo; 
	magic = xp->magic; 
	memmove(microstate, xp->microstate, UREGVARSZ); 
 
	memmove(pureg, uva, n); 
 
	xp->sr = (sr&0xff00) |(xp->sr&0xff); 
	xp->vo = vo; 
	xp->magic = magic; 
	memmove(xp->microstate, microstate, UREGVARSZ); 
1990/03091    
} 


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