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

1990/0315/gnot/trap.c (diff list | history)

gnot/trap.c on 1990/03091
1990/03091    
#include	"u.h" 
#include	"lib.h" 
#include	"mem.h" 
#include	"dat.h" 
#include	"fns.h" 
#include	"ureg.h" 
#include	"io.h" 
 
void	notify(Ureg*); 
void	noted(Ureg**); 
void	rfnote(Ureg**); 
 
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", 
	"cptrapcc, trapcc, trapv instruction", 
	"privilege violation", 
	"trace", 
	"line 1010 emulator", 
	"line 1111 emulator", 
	"reserved", 
	"coprocessor protocol violation", 
	"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", 
}; 
 
char* 
excname(unsigned vo) 
{ 
	static char buf[32];	/* BUG: not reentrant! */ 
 
	vo &= 0x0FFF; 
	vo >>= 2; 
	if(vo < sizeof trapname/sizeof(char*)) 
		return trapname[vo]; 
	sprint(buf, "offset 0x%ux", vo<<2); 
	return buf; 
} 
 
void 
trap(Ureg *ur) 
{ 
	int user; 
	char buf[64]; 
 
	user = !(ur->sr&SUPER); 
 
	if(u) 
		u->p->pc = ur->pc;		/* BUG */ 
	if(user){ 
		sprint(buf, "pc=%lux trap: %s", ur->pc, excname(ur->vo)); 
		postnote(u->p, 1, buf, NDebug); 
	}else{ 
		print("kernel trap vo=%ux pc=%lux\n", ur->vo, ur->pc); 
		dumpregs(ur); 
		exit(); 
	} 
	if(user && u->nnote) 
		notify(ur); 
} 
 
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]); 
	dumpstack(); 
} 
 
/* 
 * 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; 
		#ifdef asdfasdf 
		sp = ur->sp; 
		sp -= sizeof(Ureg); 
		u->ureg = (void*)sp; 
		memcpy((Ureg*)sp, ur, sizeof(Ureg)); 
		sp -= ERRLEN; 
		memcpy((char*)sp, u->note[0].msg, ERRLEN); 
		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 */ 
		ur->sp = sp; 
		ur->pc = (ulong)u->notify; 
		u->notified = 1; 
		u->nnote--; 
		memcpy(&u->note[0], &u->note[1], u->nnote*sizeof(Note)); 
		#endif 
		panic("notify"); 
	} 
	unlock(&u->p->debug); 
} 
 
/* 
 * Return user to state before notify() 
 */ 
void 
noted(Ureg **urp) 
{ 
	#ifdef asdfasdf 
	lock(&u->p->debug); 
	u->notified = 0; 
	memcpy(*urp, u->ureg, sizeof(Ureg)); 
	unlock(&u->p->debug); 
	splhi(); 
	rfnote(urp); 
	#endif 
	panic("noted"); 
} 
 
#undef	CHDIR	/* BUG */ 
#include "/sys/src/libc/680209sys/sys.h" 
 
typedef long Syscall(ulong*); 
Syscall	sysr1, sysfork, sysexec, sysgetpid, syssleep, sysexits, syslasterr, syswait; 
Syscall	sysopen, sysclose, sysread, syswrite, sysseek, syserrstr, sysaccess, sysstat, sysfstat; 
Syscall sysdup, syschdir, sysforkpgrp, sysbind, sysmount, syspipe, syscreate, sysuserstr; 
Syscall	sysbrk_, sysremove, syswstat, sysfwstat; 
 
Syscall *systab[]={ 
	sysr1, 
	sysaccess, 
	sysbind, 
	syschdir, 
	sysclose, 
	sysdup, 
	syserrstr, 
	sysexec, 
	sysexits, 
	sysfork, 
	sysforkpgrp, 
	sysfstat, 
	syslasterr, 
	sysmount, 
	sysopen, 
	sysread, 
	sysseek, 
	syssleep, 
	sysstat, 
	syswait, 
	syswrite, 
	syspipe, 
	syscreate, 
	sysuserstr, 
	sysbrk_, 
	sysremove, 
	syswstat, 
	sysfwstat, 
}; 
 
long 
syscall(Ureg *aur) 
{ 
	long ret; 
	ulong sp; 
	ulong r0; 
	Ureg *ur; 
 
	u->p->insyscall = 1; 
	ur = aur; 
1990/0312    
	u->p->pc = ur->pc; 
1990/03091    
	if(ur->sr & SUPER) 
		panic("recursive system call"); 
#ifdef asdf 
	/* 
	 * since the system call interface does not 
	 * guarantee anything about registers 
	 */ 
	if(u->p->fpstate == FPactive) { 
		u->p->fpstate = FPinit;		/* BUG */ 
		ur->status &= ~CU1; 
	} 
#endif 
	r0 = ur->r0; 
	sp = ur->usp; 
	if(r0 >= sizeof systab/BY2WD) 
		panic("syscall %d\n", r0); 
	if(sp & (BY2WD-1)) 
		panic("syscall odd sp"); 
	if(sp<(USTKTOP-BY2PG) || sp>(USTKTOP-4*BY2WD)) 
		validaddr(sp, 4*BY2WD, 0); 
 
	u->nerrlab = 0; 
	ret = -1; 
	if(!waserror()) 
		ret = (*systab[r0])((ulong*)(sp+BY2WD)); 
	u->nerrlab = 0; 
	u->p->insyscall = 0; 
	if(r0 == NOTED)	/* ugly hack */ 
		noted(&aur);	/* doesn't return */ 
	if(u->nnote){ 
		ur->r0 = ret; 
		notify(ur); 
	} 
	return ret; 
} 
 
void 
error(Chan *c, int code) 
{ 
	if(c){ 
		u->error.type = c->type; 
		u->error.dev = c->dev; 
	}else{ 
		u->error.type = 0; 
		u->error.dev = 0; 
	} 
	u->error.code = code; 
	nexterror(); 
} 
 
void 
nexterror(void) 
{ 
	gotolabel(&u->errlab[--u->nerrlab]); 
} 


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