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

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

1991/1214/sys/src/9/gnot/trap.c:1,3601991/1216/sys/src/9/gnot/trap.c:1,360 (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", 
	"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* 
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"; 
1990/03091    
		return trapname[vo]; 
1991/1113    
	} 
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/1113    
		sprint(buf, "sys: %s pc=0x%lux", excname(ur->vo, ur->pc), 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 
notify(Ureg *ur) 
{ 
1991/1114    
	ulong s, sp; 
1990/03091    
 
1991/1112    
	if(u->p->procctl) 
		procctl(u->p); 
	if(u->nnote==0) 
1990/03091    
		return; 
1991/1112    
 
1991/1114    
	s = spllo(); 
1991/1112    
	lock(&u->p->debug); 
1991/1216    
	qlock(&u->p->debug); 
1991/0727    
	u->p->notepending = 0; 
1990/03091    
	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); 
1991/1216    
		qunlock(&u->p->debug); 
1990/03091    
		pexit(u->note[0].msg, u->note[0].flag!=NDebug); 
	} 
	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"); 
			unlock(&u->p->debug); 
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    
	} 
	unlock(&u->p->debug); 
1991/1216    
	qunlock(&u->p->debug); 
1991/1114    
	splx(s); 
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); 
	} 
1990/03091    
	lock(&u->p->debug); 
1991/1216    
	qlock(&u->p->debug); 
1990/0619    
	if(!u->notified){ 
		unlock(&u->p->debug); 
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"); 
			unlock(&u->p->debug); 
1991/1216    
			qunlock(&u->p->debug); 
1991/0814    
			goto Die; 
		} 
		validaddr(nur->pc, 1, 0); 
		validaddr(nur->usp, BY2WD, 0); 
		poperror(); 
1991/0717    
		splhi(); 
		unlock(&u->p->debug); 
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); 
		unlock(&u->p->debug); 
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)