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

1999/0127/mpc/trap.c (diff list | history)

1999/0121/sys/src/9/mpc/trap.c:131,1331999/0122/sys/src/9/mpc/trap.c:131,146 (short | long)
1999/0121    
{ 
	USED(v, r, arg); 
} 
1999/0122    
 
void 
reset(void) 
{ 
	IMM *io; 
 
	io = m->iomem; 
	io->plprcrk = KEEP_ALIVE_KEY;	// unlock 
	io->plprcr |= IBIT(24);		// enable checkstop reset 
	putmsr(getmsr() & ~MSR_ME); 
	// cause checkstop -> causes reset 
	*(ulong*)(0) = 0; 
} 
1999/0122/sys/src/9/mpc/trap.c:3,751999/0123/sys/src/9/mpc/trap.c:3,441 (short | long)
1999/0121    
#include	"mem.h" 
#include	"dat.h" 
#include	"fns.h" 
#include	"io.h" 
#include	"ureg.h" 
1999/0123    
#include	"io.h" 
1999/0121    
#include	"../port/error.h" 
 
/* Give enough context in the ureg to produce a kernel stack for 
 * a sleeping process 
 */ 
1999/0123    
enum  
{ 
	Maxhandler=	32+16,		/* max number of interrupt handlers */ 
}; 
 
typedef struct Handler	Handler; 
struct Handler 
{ 
	void	(*r)(Ureg*, void*); 
	void	*arg; 
	Handler	*next; 
	int	edge; 
	int	nintr; 
	ulong	ticks; 
	int	maxtick; 
}; 
 
struct 
{ 
	Handler	*ivec[128]; 
	Handler	h[Maxhandler]; 
	int	free; 
} halloc; 
 
void	kernfault(Ureg*, int); 
 
char *excname[] = 
{ 
	"reserved 0", 
	"system reset", 
	"machine check", 
	"data access", 
	"instruction access", 
	"external interrupt", 
	"alignment", 
	"program exception", 
	"floating-point unavailable", 
	"decrementer", 
	"i/o controller interface error", 
	"reserved B", 
	"system call", 
	"trace trap", 
	"floating point assist", 
	"reserved F", 
	"software emulation", 
	"ITLB miss", 
	"DTLB miss", 
	"ITLB error", 
	"DTLB error", 
	"reserved 15", 
	"reserved 16", 
	"reserved 17", 
	"reserved 18", 
	"reserved 19", 
	"reserved 1A", 
	"reserved 1B", 
	"data breakpoint", 
	"instruction breakpoint", 
	"peripheral breakpoint", 
	"development port", 
	/* the following are made up on a program exception */ 
	"floating point exception",		/* 20: FPEXC */ 
	"illegal instruction",	/* 21 */ 
	"privileged instruction",	/* 22 */ 
	"trap",	/* 23 */ 
	"illegal operation",	/* 24 */ 
	"breakpoint",	/* 25 */ 
}; 
 
char *fpcause[] = 
{ 
	"inexact operation", 
	"division by zero", 
	"underflow", 
	"overflow", 
	"invalid operation", 
}; 
char	*fpexcname(Ureg*, ulong, char*); 
#define FPEXPMASK	0xfff80300		/* Floating exception bits in fpscr */ 
 
 
char *regname[]={ 
	"CAUSE",	"SRR1", 
	"PC",		"GOK", 
	"LR",		"CR", 
	"XER",	"CTR", 
	"R0",		"R1", 
	"R2",		"R3", 
	"R4",		"R5", 
	"R6",		"R7", 
	"R8",		"R9", 
	"R10",	"R11", 
	"R12",	"R13", 
	"R14",	"R15", 
	"R16",	"R17", 
	"R18",	"R19", 
	"R20",	"R21", 
	"R22",	"R23", 
	"R24",	"R25", 
	"R26",	"R27", 
	"R28",	"R29", 
	"R30",	"R31", 
}; 
 
1999/0121    
void 
setkernur(Ureg* ureg, Proc* p) 
1999/0123    
sethvec(int v, void (*r)(void)) 
1999/0121    
{ 
	ureg->pc = p->sched.pc; 
	ureg->sp = p->sched.sp+4; 
1999/0123    
	ulong *vp, pa, o; 
 
	vp = (ulong*)(0xfff00000+v); 
	vp[0] = 0x7c1043a6;	/* MOVW R0, SPR(SPRG0) */ 
	vp[1] = 0x7c0802a6;	/* MOVW LR, R0 */ 
	vp[2] = 0x7c1243a6;	/* MOVW R0, SPR(SPRG2) */ 
	pa = PADDR(r); 
	o = pa >> 25; 
	if(o != 0 && o != 0x7F){ 
		/* a branch too far */ 
		vp[3] = (15<<26)|(pa>>16);	/* MOVW $r&~0xFFFF, R0 */ 
		vp[4] = (24<<26)|(pa&0xFFFF);	/* OR $r&0xFFFF, R0 */ 
		vp[5] = 0x7c0803a6;	/* MOVW	R0, LR */ 
		vp[6] = 0x4e800021;	/* BL (LR) */ 
	}else 
		vp[3] = (18<<26)|(pa&0x3FFFFFC)|3;	/* bla */ 
	dcflush(vp, 8*sizeof(ulong)); 
1999/0121    
} 
 
/* This routine must save the values of registers the user is not permitted to write 
 * from devproc and then restore the saved values before returning 
 */ 
void 
setregisters(Ureg* ureg, char* pureg, char* uva, int n) 
1999/0123    
sethvec2(int v, void (*r)(void)) 
1999/0121    
{ 
	USED(ureg, pureg, uva, n); 
	panic("not done"); 
1999/0123    
	ulong *vp; 
 
	vp = (ulong*)KADDR(v); 
	vp[0] = (18<<26)|(PADDR(r))|2;	/* ba */ 
	dcflush(vp, sizeof(*vp)); 
1999/0121    
} 
 
void 
dumpregs(Ureg* ureg) 
1999/0123    
trap(Ureg *ur) 
1999/0121    
{ 
	USED(ureg); 
	panic("not done"); 
1999/0123    
	int ecode; 
	static struct {int callsched;} c = {1}; 
 
	ecode = (ur->cause >> 8) & 0xff; 
	if(ecode < 0 || ecode >= 0x1F) 
		ecode = 0x1F; 
	switch(ecode){ 
	case CEI: 
		intr(ur); 
		break; 
 
	case CDEC: 
		clockintr(ur); 
		break; 
 
	case CMCHECK: 
	case CDSI: 
	case CISI: 
	case CIMISS: 
	case CDMISS: 
	case CITLBE: 
	case CDTLBE: 
		goto Default; 
		break; 
 
	case CEMU: 
		print("pc=#%lux op=#%8.8lux\n", ur->pc, *(ulong*)ur->pc); 
		goto Default; 
		break; 
 
	case CPROG: 
		if(ur->status & (1<<19)) 
			ecode = 0x20; 
		if(ur->status & (1<<18)) 
			ecode = 0x21; 
		if(ur->status & (1<<17)) 
			ecode = 0x22; 
		goto Default; 
 
	Default: 
	default: 
		print("kernel %s pc=0x%lux\n", excname[ecode], ur->pc); 
		dumpregs(ur); 
		dumpstack(); 
		if(m->machno == 0) 
			spllo(); 
		exit(1); 
	} 
 
	splhi(); 
1999/0121    
} 
 
void 
dumpstack(void) 
1999/0123    
spurious(Ureg *ur, void *a) 
1999/0121    
{ 
	panic("not done"); 
1999/0123    
	USED(a); 
	print("SPURIOUS interrupt pc=0x%lux cause=0x%lux\n", 
		ur->pc, ur->cause); 
	panic("bad interrupt"); 
1999/0121    
} 
 
ulong 
userpc(void) 
1999/0123    
#define	LEV(n)	(((n)<<1)|1) 
#define	IRQ(n)	(((n)<<1)|0) 
 
Lock	veclock; 
 
void 
trapinit(void) 
1999/0121    
{ 
	Ureg *ureg; 
1999/0123    
	int i; 
	IMM *io; 
1999/0121    
 
	ureg = (Ureg*)up->dbgreg; 
	return ureg->pc; 
1999/0123    
 
	io = m->iomem; 
	io->sypcr &= ~(1<<3);	/* disable watchdog (821/823) */ 
	io->simask = 0;	/* mask all */ 
	io->siel = ~0;	/* edge sensitive, wake on all */ 
	io->cicr = 0;	/* disable CPM interrupts */ 
	io->cipr = ~0;	/* clear all interrupts */ 
	io->cimr = 0;	/* mask all events */ 
	io->cicr = (0xE1<<16)|(CPIClevel<<13)|(0x1F<<8); 
	io->cicr |= 1 << 7;	/* enable */ 
	io->tbscr = 1;	/* TBE */ 
	io->simask |= 1<<(31-LEV(CPIClevel));	/* CPM's level */ 
	eieio(); 
	putdec(~0); 
 
	/* 
	 * set all exceptions to trap 
	 */ 
	for(i = 0x0; i < 0x3000; i += 0x100) 
		sethvec(i, trapvec); 
 
	//sethvec(CEI<<8, intrvec); 
	//sethvec2(CIMISS<<8, itlbmiss); 
	//sethvec2(CDMISS<<8, dtlbmiss); 
1999/0121    
} 
 
ulong 
dbgpc(Proc *p) 
1999/0123    
void 
intrenable(int v, void (*r)(Ureg*, void*), void *arg, int) 
1999/0121    
{ 
	Ureg *ureg; 
1999/0123    
	Handler *h; 
	IMM *io; 
1999/0121    
 
	ureg = p->dbgreg; 
	if(ureg == 0) 
		return 0; 
1999/0123    
	if(halloc.free >= Maxhandler) 
		panic("out of interrupt handlers"); 
	v -= VectorPIC; 
	if(v < 0 || v >= nelem(halloc.ivec)) 
		panic("intrenable(%d)", v+VectorPIC); 
	ilock(&veclock); 
	if(v < VectorCPIC || (h = halloc.ivec[v]) == nil){ 
		h = &halloc.h[halloc.free++]; 
		h->next = halloc.ivec[v]; 
		halloc.ivec[v] = h; 
	} 
	h->r = r; 
	h->arg = arg; 
1999/0121    
 
	return ureg->pc; 
1999/0123    
	/* 
	 * enable corresponding interrupt in SIU/CPM 
	 */ 
 
	eieio(); 
	io = m->iomem; 
	if(v >= VectorCPIC){ 
		v -= VectorCPIC; 
		io->cimr |= 1<<(v&0x1F); 
	} 
	else if(v >= VectorIRQ) 
		io->simask |= 1<<(31-IRQ(v&7)); 
	else 
		io->simask |= 1<<(31-LEV(v)); 
	eieio(); 
	iunlock(&veclock); 
1999/0121    
} 
 
1999/0123    
/* 
 * called directly by l.s:/intrvec 
 */ 
void 
intr(Ureg *ur) 
{ 
	int b, v; 
	IMM *io; 
	Handler *h; 
	long t0; 
 
	ur->cause &= ~0xff; 
	io = m->iomem; 
	b = io->sivec>>2; 
	v = b>>1; 
	if(b & 1) { 
		if(v == CPIClevel){ 
			io->civr = 1; 
			eieio(); 
			v = VectorCPIC+(io->civr>>11); 
		} 
	}else 
		v += VectorIRQ; 
	ur->cause |= v; 
	h = halloc.ivec[v]; 
	if(h == nil){ 
		print("unknown interrupt %d pc=0x%lux\n", v, ur->pc); 
		uartwait(); 
		return; 
	} 
	if(h->edge){ 
		io->sipend |= 1<<(31-b); 
		eieio(); 
	} 
	/* 
	 *  call the interrupt handlers 
	 */ 
	do { 
		h->nintr++; 
		t0 = getdec(); 
		(*h->r)(ur, h->arg); 
		t0 -= getdec(); 
		h->ticks += t0; 
		if(h->maxtick < t0) 
			h->maxtick = t0; 
		h = h->next; 
	} while(h != nil); 
	if(v >= VectorCPIC) 
		io->cisr |= 1<<(v-VectorCPIC); 
	eieio(); 
} 
 
int 
intrstats(char *buf, int bsize) 
{ 
	Handler *h; 
	int i, n; 
 
	n = 0; 
	for(i=0; i<nelem(halloc.ivec) && n < bsize; i++) 
		if((h = halloc.ivec[i]) != nil && h->nintr) 
			n += snprint(buf+n, bsize-n, "%3d %lud %lud %lud\n", i, h->nintr, h->ticks, h->maxtick); 
	return n; 
} 
 
char* 
fpexcname(Ureg *ur, ulong fpscr, char *buf) 
{ 
	int i; 
	char *s; 
	ulong fppc; 
 
	fppc = ur->pc; 
	s = 0; 
	fpscr >>= 3;		/* trap enable bits */ 
	fpscr &= (fpscr>>22);	/* anded with exceptions */ 
	for(i=0; i<5; i++) 
		if(fpscr & (1<<i)) 
			s = fpcause[i]; 
	if(s == 0) 
		return "no floating point exception"; 
	sprint(buf, "%s fppc=0x%lux", s, fppc); 
	return buf; 
} 
 
#define KERNPC(x)	(KTZERO<(ulong)(x)&&(ulong)(x)<(ulong)etext) 
 
void 
kernfault(Ureg *ur, int code) 
{ 
	Label l; 
 
	print("panic: kfault %s dar=0x%lux\n", excname[code], getdar()); 
	print("u=0x%lux status=0x%lux pc=0x%lux sp=0x%lux\n", 
				up, ur->status, ur->pc, ur->sp); 
	dumpregs(ur); 
	l.sp = ur->sp; 
	l.pc = ur->pc; 
	dumpstack(); 
	for(;;) 
		sched(); 
} 
 
void 
dumpstack(void) 
{ 
	ulong l, v; 
	int i; 
 
	if(up == 0) 
		return; 
	i = 0; 
	for(l=(ulong)&l; l<(ulong)(up->kstack+KSTACK); l+=4){ 
		v = *(ulong*)l; 
		if(KTZERO < v && v < (ulong)etext){ 
			print("%lux=%lux, ", l, v); 
			if(i++ == 4){ 
				print("\n"); 
				i = 0; 
			} 
		} 
	} 
} 
 
void 
dumpregs(Ureg *ur) 
{ 
	int i; 
	ulong *l; 
	if(up) { 
		print("registers for %s %d\n", up->text, up->pid); 
		if(ur->usp < (ulong)up->kstack || 
		   ur->usp > (ulong)up->kstack+KSTACK) 
			print("invalid stack ptr\n"); 
	} 
	else 
		print("registers for kernel\n"); 
 
	print("dsisr\t%.8lux\tdar\t%.8lux\n", getdsisr(), getdar()); 
	l = &ur->cause; 
	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]); 
} 
 
1999/0121    
static void 
linkproc(void) 
{ 
	spllo(); 
	up->kpfun(up->kparg); 
1999/0123    
	(*up->kpfun)(up->kparg); 
	pexit("", 0); 
1999/0121    
} 
 
void 
kprocchild(Proc* p, void (*func)(void*), void* arg) 
1999/0123    
kprocchild(Proc *p, void (*func)(void*), void *arg) 
1999/0121    
{ 
	p->sched.pc = (ulong)linkproc; 
	p->sched.sp = (ulong)p->kstack+KSTACK; 
1999/0122/sys/src/9/mpc/trap.c:78,891999/0123/sys/src/9/mpc/trap.c:444,473
1999/0121    
	p->kparg = arg; 
} 
 
1999/0123    
int 
isvalid_pc(ulong pc) 
{ 
	return KERNPC(pc) && (pc&3) == 0; 
} 
 
1999/0121    
void 
forkchild(Proc *p, Ureg *ureg) 
1999/0123    
dumplongs(char*, ulong*, int) 
1999/0121    
{ 
	USED(p, ureg); 
} 
 
1999/0123    
void 
reset(void) 
{ 
	IMM *io; 
 
	io = m->iomem; 
	io->plprcrk = KEEP_ALIVE_KEY;	// unlock 
	io->plprcr |= IBIT(24);		// enable checkstop reset 
	putmsr(getmsr() & ~MSR_ME); 
	// cause checkstop -> causes reset 
	*(ulong*)(0) = 0; 
} 
 
1999/0121    
/* 
 * called in sysfile.c 
 */ 
1999/0122/sys/src/9/mpc/trap.c:112,1461999/0123/sys/src/9/mpc/trap.c:496,566
1999/0121    
} 
 
void 
trap(Ureg *ur) 
1999/0123    
forkchild(Proc *p, Ureg *ur) 
1999/0121    
{ 
	USED(ur); 
1999/0123    
	Ureg *cur; 
 
	p->sched.sp = (ulong)p->kstack+KSTACK-UREGSIZE; 
	p->sched.pc = (ulong)forkret; 
 
	cur = (Ureg*)(p->sched.sp+2*BY2WD); 
	memmove(cur, ur, sizeof(Ureg)); 
 
	cur->pc += 4; 
 
	/* Things from bottom of syscall we never got to execute */ 
	p->psstate = 0; 
	p->insyscall = 0; 
1999/0121    
} 
 
/* 
 * called directly by l.s:/intrvec 
1999/0123    
ulong 
userpc(void) 
{ 
	Ureg *ureg; 
 
	ureg = (Ureg*)up->dbgreg; 
	return ureg->pc; 
} 
 
 
// need to be in l.s 
void 
forkret(void) 
{ 
	panic("forkret"); 
} 
/* This routine must save the values of registers the user is not  
 * permitted to write from devproc and then restore the saved values  
 * before returning 
1999/0121    
 */ 
void 
intr(Ureg *ur) 
1999/0123    
setregisters(Ureg *xp, char *pureg, char *uva, int n) 
1999/0121    
{ 
	USED(ur); 
1999/0123    
	ulong status; 
 
	status = xp->status; 
	memmove(pureg, uva, n); 
	xp->status = status; 
1999/0121    
} 
 
1999/0123    
/* Give enough context in the ureg to produce a kernel stack for 
 * a sleeping process 
 */ 
1999/0121    
void 
intrenable(int v, void (*r)(Ureg*, void*), void *arg, int) 
1999/0123    
setkernur(Ureg* ureg, Proc* p) 
1999/0121    
{ 
	USED(v, r, arg); 
1999/0123    
	ureg->pc = p->sched.pc; 
	ureg->sp = p->sched.sp+4; 
1999/0121    
} 
1999/0122    
 
void 
reset(void) 
1999/0123    
ulong 
dbgpc(Proc *p) 
1999/0122    
{ 
	IMM *io; 
1999/0123    
	Ureg *ureg; 
1999/0122    
 
	io = m->iomem; 
	io->plprcrk = KEEP_ALIVE_KEY;	// unlock 
	io->plprcr |= IBIT(24);		// enable checkstop reset 
	putmsr(getmsr() & ~MSR_ME); 
	// cause checkstop -> causes reset 
	*(ulong*)(0) = 0; 
1999/0123    
	ureg = p->dbgreg; 
	if(ureg == 0) 
		return 0; 
 
	return ureg->pc; 
1999/0122    
} 
1999/0123/sys/src/9/mpc/trap.c:31,361999/0127/sys/src/9/mpc/trap.c:31,37 (short | long)
1999/0123    
	int	free; 
} halloc; 
 
1999/0127    
void	faultpower(Ureg *ur, ulong addr, int read); 
1999/0123    
void	kernfault(Ureg*, int); 
 
char *excname[] = 
1999/0123/sys/src/9/mpc/trap.c:161,1741999/0127/sys/src/9/mpc/trap.c:162,176
1999/0123    
		clockintr(ur); 
		break; 
 
	case CMCHECK: 
	case CDSI: 
	case CISI: 
	case CIMISS: 
	case CDMISS: 
	case CITLBE: 
1999/0127    
		faultpower(ur, ur->pc, 1); 
		break; 
	case CDMISS: 
		faultpower(ur, getdepn(), 1); 
		break; 
1999/0123    
	case CDTLBE: 
		goto Default; 
1999/0127    
		faultpower(ur, getdar(), !(getdsisr() & (1<<25))); 
1999/0123    
		break; 
 
	case CEMU: 
1999/0123/sys/src/9/mpc/trap.c:176,1811999/0127/sys/src/9/mpc/trap.c:178,191
1999/0123    
		goto Default; 
		break; 
 
1999/0127    
	case CSYSCALL: 
		spllo(); 
		print("syscall!\n"); 
		dumpregs(ur); 
		delay(100); 
		splhi(); 
		break; 
 
1999/0123    
	case CPROG: 
		if(ur->status & (1<<19)) 
			ecode = 0x20; 
1999/0123/sys/src/9/mpc/trap.c:190,1971999/0127/sys/src/9/mpc/trap.c:200,206
1999/0123    
		print("kernel %s pc=0x%lux\n", excname[ecode], ur->pc); 
		dumpregs(ur); 
		dumpstack(); 
		if(m->machno == 0) 
			spllo(); 
1999/0127    
		spllo(); 
1999/0123    
		exit(1); 
	} 
 
1999/0123/sys/src/9/mpc/trap.c:199,2041999/0127/sys/src/9/mpc/trap.c:208,238
1999/0121    
} 
 
void 
1999/0127    
faultpower(Ureg *ureg, ulong addr, int read) 
{ 
	int user, insyscall, n; 
	char buf[ERRLEN]; 
 
	user = (ureg->srr1 & MSR_PR) != 0; 
print("fault: pc = %ux, addr = %ux read = %d user = %d stack=%ux\n", ureg->pc, addr, read, user, &ureg); 
	insyscall = up->insyscall; 
	up->insyscall = 1; 
	spllo(); 
	n = fault(addr, read); 
	if(n < 0){ 
		if(!user){ 
			dumpregs(ureg); 
			panic("fault: 0x%lux\n", addr); 
		} 
		sprint(buf, "sys: trap: fault %s addr=0x%lux", 
			read? "read" : "write", addr); 
		postnote(up, 1, buf, NDebug); 
	} 
	up->insyscall = insyscall; 
	splhi(); 
} 
 
void 
1999/0123    
spurious(Ureg *ur, void *a) 
1999/0121    
{ 
1999/0123    
	USED(a); 
1999/0123/sys/src/9/mpc/trap.c:413,4201999/0127/sys/src/9/mpc/trap.c:447,454
1999/0123    
	ulong *l; 
	if(up) { 
		print("registers for %s %d\n", up->text, up->pid); 
		if(ur->usp < (ulong)up->kstack || 
		   ur->usp > (ulong)up->kstack+KSTACK) 
1999/0127    
		if(ur->srr1 & MSR_PR == 0) 
		if(ur->usp < (ulong)up->kstack || ur->usp > (ulong)up->kstack+KSTACK) 
1999/0123    
			print("invalid stack ptr\n"); 
	} 
	else 
1999/0123/sys/src/9/mpc/trap.c:429,4341999/0127/sys/src/9/mpc/trap.c:463,469
1999/0121    
static void 
linkproc(void) 
{ 
1999/0127    
print("linkproc %ux\n", up); 
1999/0121    
	spllo(); 
1999/0123    
	(*up->kpfun)(up->kparg); 
	pexit("", 0); 
1999/0127/sys/src/9/mpc/trap.c:33,381999/0128/sys/src/9/mpc/trap.c:33,39 (short | long)
1999/0123    
 
1999/0127    
void	faultpower(Ureg *ur, ulong addr, int read); 
1999/0123    
void	kernfault(Ureg*, int); 
1999/0128    
void	syscall(Ureg* ureg); 
1999/0123    
 
char *excname[] = 
{ 
1999/0127/sys/src/9/mpc/trap.c:179,1891999/0128/sys/src/9/mpc/trap.c:180,186
1999/0123    
		break; 
 
1999/0127    
	case CSYSCALL: 
		spllo(); 
		print("syscall!\n"); 
		dumpregs(ur); 
		delay(100); 
		splhi(); 
1999/0128    
		syscall(ur); 
1999/0127    
		break; 
 
1999/0123    
	case CPROG: 
1999/0127/sys/src/9/mpc/trap.c:214,2201999/0128/sys/src/9/mpc/trap.c:211,217
1999/0127    
	char buf[ERRLEN]; 
 
	user = (ureg->srr1 & MSR_PR) != 0; 
print("fault: pc = %ux, addr = %ux read = %d user = %d stack=%ux\n", ureg->pc, addr, read, user, &ureg); 
1999/0128    
//print("fault: pc = %ux, addr = %ux read = %d user = %d stack=%ux\n", ureg->pc, addr, read, user, &ureg); 
1999/0127    
	insyscall = up->insyscall; 
	up->insyscall = 1; 
	spllo(); 
1999/0127/sys/src/9/mpc/trap.c:229,2351999/0128/sys/src/9/mpc/trap.c:226,231
1999/0127    
		postnote(up, 1, buf, NDebug); 
	} 
	up->insyscall = insyscall; 
	splhi(); 
} 
 
void 
1999/0127/sys/src/9/mpc/trap.c:540,5481999/0128/sys/src/9/mpc/trap.c:536,543
1999/0123    
 
	cur = (Ureg*)(p->sched.sp+2*BY2WD); 
	memmove(cur, ur, sizeof(Ureg)); 
                 
	cur->pc += 4; 
                 
1999/0128    
	cur->r3 = 0; 
	 
1999/0123    
	/* Things from bottom of syscall we never got to execute */ 
	p->psstate = 0; 
	p->insyscall = 0; 
1999/0127/sys/src/9/mpc/trap.c:558,5691999/0128/sys/src/9/mpc/trap.c:553,558
1999/0123    
} 
 
 
// need to be in l.s 
void 
forkret(void) 
{ 
	panic("forkret"); 
} 
/* This routine must save the values of registers the user is not  
 * permitted to write from devproc and then restore the saved values  
 * before returning 
1999/0127/sys/src/9/mpc/trap.c:598,6011999/0128/sys/src/9/mpc/trap.c:587,664
1999/0123    
		return 0; 
 
	return ureg->pc; 
1999/0128    
} 
 
/* 
 *  system calls 
 */ 
#include "../port/systab.h" 
 
/* 
 *  Syscall should be called directly from assembler without going through trap(). 
 */ 
void 
syscall(Ureg* ureg) 
{ 
	ulong	sp; 
	long	ret; 
	int	i, scallnr; 
 
	if((ureg->srr1 & MSR_PR) == 0) 
		panic("syscall: srr1 0x%4.4uX\n", ureg->srr1); 
 
	m->syscall++; 
	up->insyscall = 1; 
	up->pc = ureg->pc; 
	up->dbgreg = ureg; 
 
	scallnr = ureg->r3; 
//print("scall %s\n", sysctab[scallnr]); 
	up->scallnr = scallnr; 
	spllo(); 
 
	sp = ureg->usp; 
	up->nerrlab = 0; 
	ret = -1; 
	if(!waserror()){ 
		if(scallnr >= nsyscall){ 
			pprint("bad sys call number %d pc %lux\n", scallnr, ureg->pc); 
			postnote(up, 1, "sys: bad sys call", NDebug); 
			error(Ebadarg); 
		} 
 
		if(sp<(USTKTOP-BY2PG) || sp>(USTKTOP-sizeof(Sargs)-BY2WD)) 
			validaddr(sp, sizeof(Sargs)+BY2WD, 0); 
 
		up->s = *((Sargs*)(sp+BY2WD)); 
		up->psstate = sysctab[scallnr]; 
 
		ret = systab[scallnr](up->s.args); 
		poperror(); 
	} 
	if(up->nerrlab){ 
		print("bad errstack [%d]: %d extra\n", scallnr, up->nerrlab); 
		for(i = 0; i < NERR; i++) 
			print("sp=%lux pc=%lux\n", up->errlab[i].sp, up->errlab[i].pc); 
		panic("error stack"); 
	} 
 
	up->insyscall = 0; 
	up->psstate = 0; 
 
	/* 
	 *  Put return value in frame.  On the x86 the syscall is 
	 *  just another trap and the return value from syscall is 
	 *  ignored.  On other machines the return value is put into 
	 *  the results register by caller of syscall. 
	 */ 
	ureg->r3 = ret; 
//print("ret = %d\n", ret); 
//	if(scallnr == NOTED) 
//		noted(ureg, *(ulong*)(sp+BY2WD)); 
 
//	if(scallnr!=RFORK && (up->procctl || up->nnote)){ 
//		splhi(); 
//		notify(ureg); 
//	} 
1999/0122    
} 
1999/0128/sys/src/9/mpc/trap.c:34,391999/0508/sys/src/9/mpc/trap.c:34,40 (short | long)
1999/0127    
void	faultpower(Ureg *ur, ulong addr, int read); 
1999/0123    
void	kernfault(Ureg*, int); 
1999/0128    
void	syscall(Ureg* ureg); 
1999/0508    
void	noted(Ureg*, ulong); 
1999/0123    
 
char *excname[] = 
{ 
1999/0128/sys/src/9/mpc/trap.c:373,3791999/0508/sys/src/9/mpc/trap.c:374,380
1999/0123    
	n = 0; 
	for(i=0; i<nelem(halloc.ivec) && n < bsize; i++) 
		if((h = halloc.ivec[i]) != nil && h->nintr) 
			n += snprint(buf+n, bsize-n, "%3d %lud %lud %lud\n", i, h->nintr, h->ticks, h->maxtick); 
1999/0508    
			n += snprint(buf+n, bsize-n, "%3d %ud %uld %ud\n", i, h->nintr, h->ticks, h->maxtick); 
1999/0123    
	return n; 
} 
 
1999/0128/sys/src/9/mpc/trap.c:442,4481999/0508/sys/src/9/mpc/trap.c:443,449
1999/0123    
	int i; 
	ulong *l; 
	if(up) { 
		print("registers for %s %d\n", up->text, up->pid); 
1999/0508    
		print("registers for %s %ld\n", up->text, up->pid); 
1999/0127    
		if(ur->srr1 & MSR_PR == 0) 
		if(ur->usp < (ulong)up->kstack || ur->usp > (ulong)up->kstack+KSTACK) 
1999/0123    
			print("invalid stack ptr\n"); 
1999/0128/sys/src/9/mpc/trap.c:459,4651999/0508/sys/src/9/mpc/trap.c:460,466
1999/0121    
static void 
linkproc(void) 
{ 
1999/0127    
print("linkproc %ux\n", up); 
1999/0508    
print("linkproc %ulx\n", up); 
1999/0121    
	spllo(); 
1999/0123    
	(*up->kpfun)(up->kparg); 
	pexit("", 0); 
1999/0128/sys/src/9/mpc/trap.c:653,6641999/0508/sys/src/9/mpc/trap.c:654,810
1999/0128    
	 *  the results register by caller of syscall. 
	 */ 
	ureg->r3 = ret; 
//print("ret = %d\n", ret); 
//	if(scallnr == NOTED) 
//		noted(ureg, *(ulong*)(sp+BY2WD)); 
 
//	if(scallnr!=RFORK && (up->procctl || up->nnote)){ 
//		splhi(); 
//		notify(ureg); 
//	} 
1999/0508    
	if(scallnr == NOTED) 
		noted(ureg, *(ulong*)(sp+BY2WD)); 
 
	if(scallnr!=RFORK && (up->procctl || up->nnote)){ 
		splhi(); 
		notify(ureg); 
	} 
} 
/* 
 *  Call user, if necessary, with note. 
 *  Pass user the Ureg struct and the note on his stack. 
 */ 
int 
notify(Ureg* ur) 
{ 
	int l; 
	ulong s, sp; 
	Note *n; 
 
	if(up->procctl) 
		procctl(up); 
	if(up->nnote == 0) 
		return 0; 
 
	s = spllo(); 
	qlock(&up->debug); 
	up->notepending = 0; 
	n = &up->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 && (up->notified || up->notify==0)){ 
		if(n->flag == NDebug) 
			pprint("suicide: %s\n", n->msg); 
		qunlock(&up->debug); 
		pexit(n->msg, n->flag!=NDebug); 
	} 
 
	if(up->notified) { 
		qunlock(&up->debug); 
		splhi(); 
		return 0; 
	} 
 
	if(!up->notify) { 
		qunlock(&up->debug); 
		pexit(n->msg, n->flag!=NDebug); 
	} 
	sp = ur->usp & ~(BY2V-1); 
	sp -= sizeof(Ureg); 
 
	if(!okaddr((ulong)up->notify, BY2WD, 0) || 
	   !okaddr(sp-ERRLEN-4*BY2WD, sizeof(Ureg)+ERRLEN+4*BY2WD, 1)) { 
		pprint("suicide: bad address or sp in notify\n"); 
		qunlock(&up->debug); 
		pexit("Suicide", 0); 
	} 
 
	memmove((Ureg*)sp, ur, sizeof(Ureg)); 
	*(Ureg**)(sp-BY2WD) = up->ureg;	/* word under Ureg is old up->ureg */ 
	up->ureg = (void*)sp; 
	sp -= BY2WD+ERRLEN; 
	memmove((char*)sp, up->note[0].msg, ERRLEN); 
	sp -= 3*BY2WD; 
	*(ulong*)(sp+2*BY2WD) = sp+3*BY2WD;	/* arg 2 is string */ 
	ur->r1 = (long)up->ureg;		/* arg 1 is ureg* */ 
	((ulong*)sp)[1] = (ulong)up->ureg;	/* arg 1 0(FP) is ureg* */ 
	((ulong*)sp)[0] = 0;			/* arg 0 is pc */ 
	ur->usp = sp; 
	ur->pc = (ulong)up->notify; 
	up->notified = 1; 
	up->nnote--; 
	memmove(&up->lastnote, &up->note[0], sizeof(Note)); 
	memmove(&up->note[0], &up->note[1], up->nnote*sizeof(Note)); 
 
	qunlock(&up->debug); 
	splx(s); 
	return 1; 
} 
 
 
/* 
 *   Return user to state before notify() 
 */ 
void 
noted(Ureg* ureg, ulong arg0) 
{ 
	Ureg *nureg; 
	ulong oureg, sp; 
 
	qlock(&up->debug); 
	if(arg0!=NRSTR && !up->notified) { 
		qunlock(&up->debug); 
		pprint("call to noted() when not notified\n"); 
		pexit("Suicide", 0); 
	} 
	up->notified = 0; 
 
	nureg = up->ureg;	/* pointer to user returned Ureg struct */ 
 
	/* sanity clause */ 
	oureg = (ulong)nureg; 
	if(!okaddr((ulong)oureg-BY2WD, BY2WD+sizeof(Ureg), 0)){ 
		pprint("bad ureg in noted or call to noted when not notified\n"); 
		qunlock(&up->debug); 
		pexit("Suicide", 0); 
	} 
 
	memmove(ureg, nureg, sizeof(Ureg)); 
 
	switch(arg0){ 
	case NCONT: 
	case NRSTR: 
		if(!okaddr(nureg->pc, 1, 0) || !okaddr(nureg->usp, BY2WD, 0)){ 
			pprint("suicide: trap in noted\n"); 
			qunlock(&up->debug); 
			pexit("Suicide", 0); 
		} 
		up->ureg = (Ureg*)(*(ulong*)(oureg-BY2WD)); 
		qunlock(&up->debug); 
		break; 
 
	case NSAVE: 
		if(!okaddr(nureg->pc, BY2WD, 0) 
		|| !okaddr(nureg->usp, BY2WD, 0)){ 
			pprint("suicide: trap in noted\n"); 
			qunlock(&up->debug); 
			pexit("Suicide", 0); 
		} 
		qunlock(&up->debug); 
		sp = oureg-4*BY2WD-ERRLEN; 
		splhi(); 
		ureg->sp = sp; 
		((ulong*)sp)[1] = oureg;	/* arg 1 0(FP) is ureg* */ 
		((ulong*)sp)[0] = 0;		/* arg 0 is pc */ 
		break; 
 
	default: 
		pprint("unknown noted arg 0x%lux\n", arg0); 
		up->lastnote.flag = NDebug; 
		/* fall through */ 
		 
	case NDFLT: 
		if(up->lastnote.flag == NDebug) 
			pprint("suicide: %s\n", up->lastnote.msg); 
		qunlock(&up->debug); 
		pexit(up->lastnote.msg, up->lastnote.flag!=NDebug); 
	} 
1999/0122    
} 
1999/0508/sys/src/9/mpc/trap.c:212,2181999/0608/sys/src/9/mpc/trap.c:212,218 (short | long)
1999/0127    
	char buf[ERRLEN]; 
 
	user = (ureg->srr1 & MSR_PR) != 0; 
1999/0128    
//print("fault: pc = %ux, addr = %ux read = %d user = %d stack=%ux\n", ureg->pc, addr, read, user, &ureg); 
1999/0608    
//print("fault: pid=%d pc = %ux, addr = %ux read = %d user = %d stack=%ux\n", up->pid, ureg->pc, addr, read, user, &ureg); 
1999/0127    
	insyscall = up->insyscall; 
	up->insyscall = 1; 
	spllo(); 
1999/0508/sys/src/9/mpc/trap.c:222,2271999/0608/sys/src/9/mpc/trap.c:222,228
1999/0127    
			dumpregs(ureg); 
			panic("fault: 0x%lux\n", addr); 
		} 
1999/0608    
print("sys: trap: fault %s addr=0x%lux\n", read? "read" : "write", addr); 
1999/0127    
		sprint(buf, "sys: trap: fault %s addr=0x%lux", 
			read? "read" : "write", addr); 
		postnote(up, 1, buf, NDebug); 
1999/0508/sys/src/9/mpc/trap.c:674,6791999/0608/sys/src/9/mpc/trap.c:675,682
1999/0508    
	ulong s, sp; 
	Note *n; 
 
1999/0608    
print("***notify\n"); 
 
1999/0508    
	if(up->procctl) 
		procctl(up); 
	if(up->nnote == 0) 
1999/0508/sys/src/9/mpc/trap.c:749,7541999/0608/sys/src/9/mpc/trap.c:752,758
1999/0508    
	Ureg *nureg; 
	ulong oureg, sp; 
 
1999/0608    
print("***noted\n"); 
1999/0508    
	qlock(&up->debug); 
	if(arg0!=NRSTR && !up->notified) { 
		qunlock(&up->debug); 
1999/0608/sys/src/9/mpc/trap.c:152,1571999/0701/sys/src/9/mpc/trap.c:152,158 (short | long)
1999/0123    
	int ecode; 
	static struct {int callsched;} c = {1}; 
 
1999/0701    
	m->intrts = fastticks(nil); 
1999/0123    
	ecode = (ur->cause >> 8) & 0xff; 
	if(ecode < 0 || ecode >= 0x1F) 
		ecode = 0x1F; 
1999/0701/sys/src/9/mpc/trap.c:676,6821999/0921/sys/src/9/mpc/trap.c:676,682 (short | long)
1999/0508    
	ulong s, sp; 
	Note *n; 
 
1999/0608    
print("***notify\n"); 
1999/0921    
print("***notify %ld\n", up->pid); 
1999/0608    
 
1999/0508    
	if(up->procctl) 
		procctl(up); 
1999/0921/sys/src/9/mpc/trap.c:462,4681999/1027/sys/src/9/mpc/trap.c:462,468 (short | long)
1999/0121    
static void 
linkproc(void) 
{ 
1999/0508    
print("linkproc %ulx\n", up); 
1999/1027    
//print("linkproc %ulx\n", up); 
1999/0121    
	spllo(); 
1999/0123    
	(*up->kpfun)(up->kparg); 
	pexit("", 0); 
1999/0921/sys/src/9/mpc/trap.c:676,6821999/1027/sys/src/9/mpc/trap.c:676,682
1999/0508    
	ulong s, sp; 
	Note *n; 
 
1999/0921    
print("***notify %ld\n", up->pid); 
1999/1027    
//print("***notify %ld\n", up->pid); 
1999/0608    
 
1999/0508    
	if(up->procctl) 
		procctl(up); 
1999/0921/sys/src/9/mpc/trap.c:753,7591999/1027/sys/src/9/mpc/trap.c:753,759
1999/0508    
	Ureg *nureg; 
	ulong oureg, sp; 
 
1999/0608    
print("***noted\n"); 
1999/1027    
//print("***noted\n"); 
1999/0508    
	qlock(&up->debug); 
	if(arg0!=NRSTR && !up->notified) { 
		qunlock(&up->debug); 
1999/1027/sys/src/9/mpc/trap.c:35,402000/0516/sys/src/9/mpc/trap.c:35,41 (short | long)
1999/0123    
void	kernfault(Ureg*, int); 
1999/0128    
void	syscall(Ureg* ureg); 
1999/0508    
void	noted(Ureg*, ulong); 
2000/0516    
void	reset(void); 
1999/0123    
 
char *excname[] = 
{ 
1999/1027/sys/src/9/mpc/trap.c:119,1252000/0516/sys/src/9/mpc/trap.c:120,126
1999/0121    
{ 
1999/0123    
	ulong *vp, pa, o; 
 
	vp = (ulong*)(0xfff00000+v); 
2000/0516    
	vp = KADDR(v); 
1999/0123    
	vp[0] = 0x7c1043a6;	/* MOVW R0, SPR(SPRG0) */ 
	vp[1] = 0x7c0802a6;	/* MOVW LR, R0 */ 
	vp[2] = 0x7c1243a6;	/* MOVW R0, SPR(SPRG2) */ 
1999/1027/sys/src/9/mpc/trap.c:151,1612000/0516/sys/src/9/mpc/trap.c:152,165
1999/0121    
{ 
1999/0123    
	int ecode; 
	static struct {int callsched;} c = {1}; 
2000/0516    
	int user = (ur->srr1 & MSR_PR) != 0; 
	char buf[ERRLEN]; 
1999/0123    
 
1999/0701    
	m->intrts = fastticks(nil); 
1999/0123    
	ecode = (ur->cause >> 8) & 0xff; 
	if(ecode < 0 || ecode >= 0x1F) 
		ecode = 0x1F; 
2000/0516    
 
if(ur->status & MSR_RI == 0) 
print("double fault?: ecode = %d\n", ecode); 
1999/0123    
	switch(ecode){ 
	case CEI: 
		intr(ur); 
1999/1027/sys/src/9/mpc/trap.c:164,1842000/0516/sys/src/9/mpc/trap.c:168,191
1999/0123    
	case CDEC: 
		clockintr(ur); 
		break; 
                 
	case CIMISS: 
2000/0516    
		faultpower(ur, ur->pc, 1); 
		break; 
1999/0123    
	case CITLBE: 
1999/0127    
		faultpower(ur, ur->pc, 1); 
		break; 
	case CDMISS: 
		faultpower(ur, getdepn(), 1); 
2000/0516    
if(0) print("CDMISS: %lux %lux\n", m->epn, m->cmp1); 
		faultpower(ur, m->dar, 1); 
1999/0127    
		break; 
1999/0123    
	case CDTLBE: 
1999/0127    
		faultpower(ur, getdar(), !(getdsisr() & (1<<25))); 
2000/0516    
		faultpower(ur, m->dar, !(m->dsisr & (1<<25))); 
1999/0123    
		break; 
 
	case CEMU: 
		print("pc=#%lux op=#%8.8lux\n", ur->pc, *(ulong*)ur->pc); 
		goto Default; 
2000/0516    
		print("CEMU: pc=#%lux op=#%8.8lux\n", ur->pc, *(ulong*)ur->pc); 
		sprint(buf, "sys: trap: illegal op addr=0x%lux", ur->pc); 
		postnote(up, 1, buf, NDebug); 
1999/0123    
		break; 
 
1999/0127    
	case CSYSCALL: 
1999/1027/sys/src/9/mpc/trap.c:196,2092000/0516/sys/src/9/mpc/trap.c:203,222
1999/0123    
 
	Default: 
	default: 
2000/0516    
		spllo(); 
		print("ecode = %d\n", ecode); 
		if(ecode < 0 || ecode >= 0x1F) 
			ecode = 0x1F; 
1999/0123    
		print("kernel %s pc=0x%lux\n", excname[ecode], ur->pc); 
		dumpregs(ur); 
		dumpstack(); 
1999/0127    
		spllo(); 
1999/0123    
		exit(1); 
2000/0516    
		delay(100); 
		reset(); 
1999/0123    
	} 
 
	splhi(); 
2000/0516    
	if(user) 
		notify(ur); 
1999/0121    
} 
 
void 
1999/1027/sys/src/9/mpc/trap.c:211,2192000/0516/sys/src/9/mpc/trap.c:224,231
1999/0127    
{ 
	int user, insyscall, n; 
	char buf[ERRLEN]; 
                 
	user = (ureg->srr1 & MSR_PR) != 0; 
1999/0608    
//print("fault: pid=%d pc = %ux, addr = %ux read = %d user = %d stack=%ux\n", up->pid, ureg->pc, addr, read, user, &ureg); 
2000/0516    
if(0)print("fault: pid=%ld pc = %lux, addr = %lux read = %d user = %d stack=%ulx\n", up->pid, ureg->pc, addr, read, user, &ureg); 
1999/0127    
	insyscall = up->insyscall; 
	up->insyscall = 1; 
	spllo(); 
1999/1027/sys/src/9/mpc/trap.c:223,2292000/0516/sys/src/9/mpc/trap.c:235,242
1999/0127    
			dumpregs(ureg); 
			panic("fault: 0x%lux\n", addr); 
		} 
1999/0608    
print("sys: trap: fault %s addr=0x%lux\n", read? "read" : "write", addr); 
2000/0516    
print("fault: pid=%ld pc = %lux, addr = %lux read = %d user = %d stack=%ulx\n", up->pid, ureg->pc, addr, read, user, &ureg); 
dumpregs(ureg); 
1999/0127    
		sprint(buf, "sys: trap: fault %s addr=0x%lux", 
			read? "read" : "write", addr); 
		postnote(up, 1, buf, NDebug); 
1999/1027/sys/src/9/mpc/trap.c:269,2802000/0516/sys/src/9/mpc/trap.c:282,294
1999/0123    
	/* 
	 * set all exceptions to trap 
	 */ 
	for(i = 0x0; i < 0x3000; i += 0x100) 
2000/0516    
	for(i = 0x0; i < 0x2000; i += 0x100) 
1999/0123    
		sethvec(i, trapvec); 
 
	//sethvec(CEI<<8, intrvec); 
	//sethvec2(CIMISS<<8, itlbmiss); 
	//sethvec2(CDMISS<<8, dtlbmiss); 
2000/0516    
	sethvec2(CIMISS<<8, itlbmiss); 
	sethvec2(CDMISS<<8, dtlbmiss); 
	sethvec2(CDTLBE<<8, dtlberror); 
1999/0121    
} 
 
1999/0123    
void 
1999/1027/sys/src/9/mpc/trap.c:315,3232000/0516/sys/src/9/mpc/trap.c:329,334
1999/0123    
	iunlock(&veclock); 
1999/0121    
} 
 
1999/0123    
/* 
 * called directly by l.s:/intrvec 
 */ 
void 
intr(Ureg *ur) 
{ 
1999/1027/sys/src/9/mpc/trap.c:497,5042000/0516/sys/src/9/mpc/trap.c:508,519
1999/0123    
	io = m->iomem; 
	io->plprcrk = KEEP_ALIVE_KEY;	// unlock 
	io->plprcr |= IBIT(24);		// enable checkstop reset 
	putmsr(getmsr() & ~MSR_ME); 
2000/0516    
	putmsr(getmsr() & ~(MSR_ME|MSR_RI)); 
predawn = 1; 
print("reset = %ulx\n", getmsr()); 
	delay(1000); 
1999/0123    
	// cause checkstop -> causes reset 
2000/0516    
	*(uchar*)(0xdeadbeef) = 0; 
1999/0123    
	*(ulong*)(0) = 0; 
} 
 
1999/1027/sys/src/9/mpc/trap.c:616,6222000/0516/sys/src/9/mpc/trap.c:631,637
1999/0128    
	up->dbgreg = ureg; 
 
	scallnr = ureg->r3; 
//print("scall %s\n", sysctab[scallnr]); 
2000/0516    
//print("scall %s lr =%lux\n", sysctab[scallnr], ureg->lr); 
1999/0128    
	up->scallnr = scallnr; 
	spllo(); 
 
1999/1027/sys/src/9/mpc/trap.c:676,6832000/0516/sys/src/9/mpc/trap.c:691,696
1999/0508    
	ulong s, sp; 
	Note *n; 
 
1999/1027    
//print("***notify %ld\n", up->pid); 
1999/0608    
                 
1999/0508    
	if(up->procctl) 
		procctl(up); 
	if(up->nnote == 0) 
1999/1027/sys/src/9/mpc/trap.c:753,7592000/0516/sys/src/9/mpc/trap.c:766,771
1999/0508    
	Ureg *nureg; 
	ulong oureg, sp; 
 
1999/1027    
//print("***noted\n"); 
1999/0508    
	qlock(&up->debug); 
	if(arg0!=NRSTR && !up->notified) { 
		qunlock(&up->debug); 
2000/0516/sys/src/9/mpc/trap.c:656,6612000/0617/sys/src/9/mpc/trap.c:656,662 (short | long)
1999/0128    
	} 
	if(up->nerrlab){ 
		print("bad errstack [%d]: %d extra\n", scallnr, up->nerrlab); 
2000/0617    
		print("scall %s lr =%lux\n", sysctab[scallnr], ureg->lr); 
1999/0128    
		for(i = 0; i < NERR; i++) 
			print("sp=%lux pc=%lux\n", up->errlab[i].sp, up->errlab[i].pc); 
		panic("error stack"); 
2000/0617/sys/src/9/mpc/trap.c:1,8282001/0527/sys/src/9/mpc/trap.c:0 (short | long)
Deleted.
rsc Mon Mar 7 10:28:47 2005
1999/0121    
#include	"u.h" 
#include	"../port/lib.h" 
#include	"mem.h" 
#include	"dat.h" 
#include	"fns.h" 
#include	"ureg.h" 
1999/0123    
#include	"io.h" 
1999/0121    
#include	"../port/error.h" 
                 
1999/0123    
enum  
{ 
	Maxhandler=	32+16,		/* max number of interrupt handlers */ 
}; 
                 
typedef struct Handler	Handler; 
struct Handler 
{ 
	void	(*r)(Ureg*, void*); 
	void	*arg; 
	Handler	*next; 
	int	edge; 
	int	nintr; 
	ulong	ticks; 
	int	maxtick; 
}; 
                 
struct 
{ 
	Handler	*ivec[128]; 
	Handler	h[Maxhandler]; 
	int	free; 
} halloc; 
                 
1999/0127    
void	faultpower(Ureg *ur, ulong addr, int read); 
1999/0123    
void	kernfault(Ureg*, int); 
1999/0128    
void	syscall(Ureg* ureg); 
1999/0508    
void	noted(Ureg*, ulong); 
2000/0516    
void	reset(void); 
1999/0123    
                 
char *excname[] = 
{ 
	"reserved 0", 
	"system reset", 
	"machine check", 
	"data access", 
	"instruction access", 
	"external interrupt", 
	"alignment", 
	"program exception", 
	"floating-point unavailable", 
	"decrementer", 
	"i/o controller interface error", 
	"reserved B", 
	"system call", 
	"trace trap", 
	"floating point assist", 
	"reserved F", 
	"software emulation", 
	"ITLB miss", 
	"DTLB miss", 
	"ITLB error", 
	"DTLB error", 
	"reserved 15", 
	"reserved 16", 
	"reserved 17", 
	"reserved 18", 
	"reserved 19", 
	"reserved 1A", 
	"reserved 1B", 
	"data breakpoint", 
	"instruction breakpoint", 
	"peripheral breakpoint", 
	"development port", 
	/* the following are made up on a program exception */ 
	"floating point exception",		/* 20: FPEXC */ 
	"illegal instruction",	/* 21 */ 
	"privileged instruction",	/* 22 */ 
	"trap",	/* 23 */ 
	"illegal operation",	/* 24 */ 
	"breakpoint",	/* 25 */ 
}; 
                 
char *fpcause[] = 
{ 
	"inexact operation", 
	"division by zero", 
	"underflow", 
	"overflow", 
	"invalid operation", 
}; 
char	*fpexcname(Ureg*, ulong, char*); 
#define FPEXPMASK	0xfff80300		/* Floating exception bits in fpscr */ 
                 
                 
char *regname[]={ 
	"CAUSE",	"SRR1", 
	"PC",		"GOK", 
	"LR",		"CR", 
	"XER",	"CTR", 
	"R0",		"R1", 
	"R2",		"R3", 
	"R4",		"R5", 
	"R6",		"R7", 
	"R8",		"R9", 
	"R10",	"R11", 
	"R12",	"R13", 
	"R14",	"R15", 
	"R16",	"R17", 
	"R18",	"R19", 
	"R20",	"R21", 
	"R22",	"R23", 
	"R24",	"R25", 
	"R26",	"R27", 
	"R28",	"R29", 
	"R30",	"R31", 
}; 
                 
1999/0121    
void 
1999/0123    
sethvec(int v, void (*r)(void)) 
1999/0121    
{ 
1999/0123    
	ulong *vp, pa, o; 
                 
2000/0516    
	vp = KADDR(v); 
1999/0123    
	vp[0] = 0x7c1043a6;	/* MOVW R0, SPR(SPRG0) */ 
	vp[1] = 0x7c0802a6;	/* MOVW LR, R0 */ 
	vp[2] = 0x7c1243a6;	/* MOVW R0, SPR(SPRG2) */ 
	pa = PADDR(r); 
	o = pa >> 25; 
	if(o != 0 && o != 0x7F){ 
		/* a branch too far */ 
		vp[3] = (15<<26)|(pa>>16);	/* MOVW $r&~0xFFFF, R0 */ 
		vp[4] = (24<<26)|(pa&0xFFFF);	/* OR $r&0xFFFF, R0 */ 
		vp[5] = 0x7c0803a6;	/* MOVW	R0, LR */ 
		vp[6] = 0x4e800021;	/* BL (LR) */ 
	}else 
		vp[3] = (18<<26)|(pa&0x3FFFFFC)|3;	/* bla */ 
	dcflush(vp, 8*sizeof(ulong)); 
1999/0121    
} 
                 
void 
1999/0123    
sethvec2(int v, void (*r)(void)) 
1999/0121    
{ 
1999/0123    
	ulong *vp; 
                 
	vp = (ulong*)KADDR(v); 
	vp[0] = (18<<26)|(PADDR(r))|2;	/* ba */ 
	dcflush(vp, sizeof(*vp)); 
1999/0121    
} 
                 
void 
1999/0123    
trap(Ureg *ur) 
1999/0121    
{ 
1999/0123    
	int ecode; 
	static struct {int callsched;} c = {1}; 
2000/0516    
	int user = (ur->srr1 & MSR_PR) != 0; 
	char buf[ERRLEN]; 
1999/0123    
                 
1999/0701    
	m->intrts = fastticks(nil); 
1999/0123    
	ecode = (ur->cause >> 8) & 0xff; 
2000/0516    
                 
if(ur->status & MSR_RI == 0) 
print("double fault?: ecode = %d\n", ecode); 
1999/0123    
	switch(ecode){ 
	case CEI: 
		intr(ur); 
		break; 
                 
	case CDEC: 
		clockintr(ur); 
		break; 
	case CIMISS: 
2000/0516    
		faultpower(ur, ur->pc, 1); 
		break; 
1999/0123    
	case CITLBE: 
1999/0127    
		faultpower(ur, ur->pc, 1); 
		break; 
	case CDMISS: 
2000/0516    
if(0) print("CDMISS: %lux %lux\n", m->epn, m->cmp1); 
		faultpower(ur, m->dar, 1); 
1999/0127    
		break; 
1999/0123    
	case CDTLBE: 
2000/0516    
		faultpower(ur, m->dar, !(m->dsisr & (1<<25))); 
1999/0123    
		break; 
                 
	case CEMU: 
2000/0516    
		print("CEMU: pc=#%lux op=#%8.8lux\n", ur->pc, *(ulong*)ur->pc); 
		sprint(buf, "sys: trap: illegal op addr=0x%lux", ur->pc); 
		postnote(up, 1, buf, NDebug); 
1999/0123    
		break; 
                 
1999/0127    
	case CSYSCALL: 
1999/0128    
		syscall(ur); 
1999/0127    
		break; 
                 
1999/0123    
	case CPROG: 
		if(ur->status & (1<<19)) 
			ecode = 0x20; 
		if(ur->status & (1<<18)) 
			ecode = 0x21; 
		if(ur->status & (1<<17)) 
			ecode = 0x22; 
		goto Default; 
                 
	Default: 
	default: 
2000/0516    
		spllo(); 
		print("ecode = %d\n", ecode); 
		if(ecode < 0 || ecode >= 0x1F) 
			ecode = 0x1F; 
1999/0123    
		print("kernel %s pc=0x%lux\n", excname[ecode], ur->pc); 
		dumpregs(ur); 
		dumpstack(); 
2000/0516    
		delay(100); 
		reset(); 
1999/0123    
	} 
                 
	splhi(); 
2000/0516    
	if(user) 
		notify(ur); 
1999/0121    
} 
                 
void 
1999/0127    
faultpower(Ureg *ureg, ulong addr, int read) 
{ 
	int user, insyscall, n; 
	char buf[ERRLEN]; 
	user = (ureg->srr1 & MSR_PR) != 0; 
2000/0516    
if(0)print("fault: pid=%ld pc = %lux, addr = %lux read = %d user = %d stack=%ulx\n", up->pid, ureg->pc, addr, read, user, &ureg); 
1999/0127    
	insyscall = up->insyscall; 
	up->insyscall = 1; 
	spllo(); 
	n = fault(addr, read); 
	if(n < 0){ 
		if(!user){ 
			dumpregs(ureg); 
			panic("fault: 0x%lux\n", addr); 
		} 
2000/0516    
print("fault: pid=%ld pc = %lux, addr = %lux read = %d user = %d stack=%ulx\n", up->pid, ureg->pc, addr, read, user, &ureg); 
dumpregs(ureg); 
1999/0127    
		sprint(buf, "sys: trap: fault %s addr=0x%lux", 
			read? "read" : "write", addr); 
		postnote(up, 1, buf, NDebug); 
	} 
	up->insyscall = insyscall; 
} 
                 
void 
1999/0123    
spurious(Ureg *ur, void *a) 
1999/0121    
{ 
1999/0123    
	USED(a); 
	print("SPURIOUS interrupt pc=0x%lux cause=0x%lux\n", 
		ur->pc, ur->cause); 
	panic("bad interrupt"); 
1999/0121    
} 
                 
1999/0123    
#define	LEV(n)	(((n)<<1)|1) 
#define	IRQ(n)	(((n)<<1)|0) 
                 
Lock	veclock; 
                 
void 
trapinit(void) 
1999/0121    
{ 
1999/0123    
	int i; 
	IMM *io; 
1999/0121    
                 
1999/0123    
                 
	io = m->iomem; 
	io->sypcr &= ~(1<<3);	/* disable watchdog (821/823) */ 
	io->simask = 0;	/* mask all */ 
	io->siel = ~0;	/* edge sensitive, wake on all */ 
	io->cicr = 0;	/* disable CPM interrupts */ 
	io->cipr = ~0;	/* clear all interrupts */ 
	io->cimr = 0;	/* mask all events */ 
	io->cicr = (0xE1<<16)|(CPIClevel<<13)|(0x1F<<8); 
	io->cicr |= 1 << 7;	/* enable */ 
	io->tbscr = 1;	/* TBE */ 
	io->simask |= 1<<(31-LEV(CPIClevel));	/* CPM's level */ 
	eieio(); 
	putdec(~0); 
                 
	/* 
	 * set all exceptions to trap 
	 */ 
2000/0516    
	for(i = 0x0; i < 0x2000; i += 0x100) 
1999/0123    
		sethvec(i, trapvec); 
                 
	//sethvec(CEI<<8, intrvec); 
2000/0516    
	sethvec2(CIMISS<<8, itlbmiss); 
	sethvec2(CDMISS<<8, dtlbmiss); 
	sethvec2(CDTLBE<<8, dtlberror); 
1999/0121    
} 
                 
1999/0123    
void 
intrenable(int v, void (*r)(Ureg*, void*), void *arg, int) 
1999/0121    
{ 
1999/0123    
	Handler *h; 
	IMM *io; 
1999/0121    
                 
1999/0123    
	if(halloc.free >= Maxhandler) 
		panic("out of interrupt handlers"); 
	v -= VectorPIC; 
	if(v < 0 || v >= nelem(halloc.ivec)) 
		panic("intrenable(%d)", v+VectorPIC); 
	ilock(&veclock); 
	if(v < VectorCPIC || (h = halloc.ivec[v]) == nil){ 
		h = &halloc.h[halloc.free++]; 
		h->next = halloc.ivec[v]; 
		halloc.ivec[v] = h; 
	} 
	h->r = r; 
	h->arg = arg; 
1999/0121    
                 
1999/0123    
	/* 
	 * enable corresponding interrupt in SIU/CPM 
	 */ 
                 
	eieio(); 
	io = m->iomem; 
	if(v >= VectorCPIC){ 
		v -= VectorCPIC; 
		io->cimr |= 1<<(v&0x1F); 
	} 
	else if(v >= VectorIRQ) 
		io->simask |= 1<<(31-IRQ(v&7)); 
	else 
		io->simask |= 1<<(31-LEV(v)); 
	eieio(); 
	iunlock(&veclock); 
1999/0121    
} 
                 
1999/0123    
void 
intr(Ureg *ur) 
{ 
	int b, v; 
	IMM *io; 
	Handler *h; 
	long t0; 
                 
	ur->cause &= ~0xff; 
	io = m->iomem; 
	b = io->sivec>>2; 
	v = b>>1; 
	if(b & 1) { 
		if(v == CPIClevel){ 
			io->civr = 1; 
			eieio(); 
			v = VectorCPIC+(io->civr>>11); 
		} 
	}else 
		v += VectorIRQ; 
	ur->cause |= v; 
	h = halloc.ivec[v]; 
	if(h == nil){ 
		print("unknown interrupt %d pc=0x%lux\n", v, ur->pc); 
		uartwait(); 
		return; 
	} 
	if(h->edge){ 
		io->sipend |= 1<<(31-b); 
		eieio(); 
	} 
	/* 
	 *  call the interrupt handlers 
	 */ 
	do { 
		h->nintr++; 
		t0 = getdec(); 
		(*h->r)(ur, h->arg); 
		t0 -= getdec(); 
		h->ticks += t0; 
		if(h->maxtick < t0) 
			h->maxtick = t0; 
		h = h->next; 
	} while(h != nil); 
	if(v >= VectorCPIC) 
		io->cisr |= 1<<(v-VectorCPIC); 
	eieio(); 
} 
                 
int 
intrstats(char *buf, int bsize) 
{ 
	Handler *h; 
	int i, n; 
                 
	n = 0; 
	for(i=0; i<nelem(halloc.ivec) && n < bsize; i++) 
		if((h = halloc.ivec[i]) != nil && h->nintr) 
1999/0508    
			n += snprint(buf+n, bsize-n, "%3d %ud %uld %ud\n", i, h->nintr, h->ticks, h->maxtick); 
1999/0123    
	return n; 
} 
                 
char* 
fpexcname(Ureg *ur, ulong fpscr, char *buf) 
{ 
	int i; 
	char *s; 
	ulong fppc; 
                 
	fppc = ur->pc; 
	s = 0; 
	fpscr >>= 3;		/* trap enable bits */ 
	fpscr &= (fpscr>>22);	/* anded with exceptions */ 
	for(i=0; i<5; i++) 
		if(fpscr & (1<<i)) 
			s = fpcause[i]; 
	if(s == 0) 
		return "no floating point exception"; 
	sprint(buf, "%s fppc=0x%lux", s, fppc); 
	return buf; 
} 
                 
#define KERNPC(x)	(KTZERO<(ulong)(x)&&(ulong)(x)<(ulong)etext) 
                 
void 
kernfault(Ureg *ur, int code) 
{ 
	Label l; 
                 
	print("panic: kfault %s dar=0x%lux\n", excname[code], getdar()); 
	print("u=0x%lux status=0x%lux pc=0x%lux sp=0x%lux\n", 
				up, ur->status, ur->pc, ur->sp); 
	dumpregs(ur); 
	l.sp = ur->sp; 
	l.pc = ur->pc; 
	dumpstack(); 
	for(;;) 
		sched(); 
} 
                 
void 
dumpstack(void) 
{ 
	ulong l, v; 
	int i; 
                 
	if(up == 0) 
		return; 
	i = 0; 
	for(l=(ulong)&l; l<(ulong)(up->kstack+KSTACK); l+=4){ 
		v = *(ulong*)l; 
		if(KTZERO < v && v < (ulong)etext){ 
			print("%lux=%lux, ", l, v); 
			if(i++ == 4){ 
				print("\n"); 
				i = 0; 
			} 
		} 
	} 
} 
                 
void 
dumpregs(Ureg *ur) 
{ 
	int i; 
	ulong *l; 
	if(up) { 
1999/0508    
		print("registers for %s %ld\n", up->text, up->pid); 
1999/0127    
		if(ur->srr1 & MSR_PR == 0) 
		if(ur->usp < (ulong)up->kstack || ur->usp > (ulong)up->kstack+KSTACK) 
1999/0123    
			print("invalid stack ptr\n"); 
	} 
	else 
		print("registers for kernel\n"); 
                 
	print("dsisr\t%.8lux\tdar\t%.8lux\n", getdsisr(), getdar()); 
	l = &ur->cause; 
	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]); 
} 
                 
1999/0121    
static void 
linkproc(void) 
{ 
1999/1027    
//print("linkproc %ulx\n", up); 
1999/0121    
	spllo(); 
1999/0123    
	(*up->kpfun)(up->kparg); 
	pexit("", 0); 
1999/0121    
} 
                 
void 
1999/0123    
kprocchild(Proc *p, void (*func)(void*), void *arg) 
1999/0121    
{ 
	p->sched.pc = (ulong)linkproc; 
	p->sched.sp = (ulong)p->kstack+KSTACK; 
                 
	p->kpfun = func; 
	p->kparg = arg; 
} 
                 
1999/0123    
int 
isvalid_pc(ulong pc) 
{ 
	return KERNPC(pc) && (pc&3) == 0; 
} 
                 
1999/0121    
void 
1999/0123    
dumplongs(char*, ulong*, int) 
1999/0121    
{ 
} 
                 
1999/0123    
void 
reset(void) 
{ 
	IMM *io; 
                 
	io = m->iomem; 
	io->plprcrk = KEEP_ALIVE_KEY;	// unlock 
	io->plprcr |= IBIT(24);		// enable checkstop reset 
2000/0516    
	putmsr(getmsr() & ~(MSR_ME|MSR_RI)); 
predawn = 1; 
print("reset = %ulx\n", getmsr()); 
	delay(1000); 
1999/0123    
	// cause checkstop -> causes reset 
2000/0516    
	*(uchar*)(0xdeadbeef) = 0; 
1999/0123    
	*(ulong*)(0) = 0; 
} 
                 
1999/0121    
/* 
 * called in sysfile.c 
 */ 
void 
evenaddr(ulong addr) 
{ 
	if(addr & 3){ 
		postnote(up, 1, "sys: odd address", NDebug); 
		error(Ebadarg); 
	} 
} 
                 
long 
execregs(ulong entry, ulong ssize, ulong nargs) 
{ 
	ulong *sp; 
	Ureg *ureg; 
                 
	sp = (ulong*)(USTKTOP - ssize); 
	*--sp = nargs; 
                 
	ureg = up->dbgreg; 
	ureg->usp = (ulong)sp; 
	ureg->pc = entry; 
	return USTKTOP-BY2WD;		/* address of user-level clock */ 
} 
                 
void 
1999/0123    
forkchild(Proc *p, Ureg *ur) 
1999/0121    
{ 
1999/0123    
	Ureg *cur; 
                 
	p->sched.sp = (ulong)p->kstack+KSTACK-UREGSIZE; 
	p->sched.pc = (ulong)forkret; 
                 
	cur = (Ureg*)(p->sched.sp+2*BY2WD); 
	memmove(cur, ur, sizeof(Ureg)); 
1999/0128    
	cur->r3 = 0; 
	                 
1999/0123    
	/* Things from bottom of syscall we never got to execute */ 
	p->psstate = 0; 
	p->insyscall = 0; 
1999/0121    
} 
                 
1999/0123    
ulong 
userpc(void) 
{ 
	Ureg *ureg; 
                 
	ureg = (Ureg*)up->dbgreg; 
	return ureg->pc; 
} 
                 
                 
/* This routine must save the values of registers the user is not  
 * permitted to write from devproc and then restore the saved values  
 * before returning 
1999/0121    
 */ 
void 
1999/0123    
setregisters(Ureg *xp, char *pureg, char *uva, int n) 
1999/0121    
{ 
1999/0123    
	ulong status; 
                 
	status = xp->status; 
	memmove(pureg, uva, n); 
	xp->status = status; 
1999/0121    
} 
                 
1999/0123    
/* Give enough context in the ureg to produce a kernel stack for 
 * a sleeping process 
 */ 
1999/0121    
void 
1999/0123    
setkernur(Ureg* ureg, Proc* p) 
1999/0121    
{ 
1999/0123    
	ureg->pc = p->sched.pc; 
	ureg->sp = p->sched.sp+4; 
1999/0121    
} 
1999/0122    
                 
1999/0123    
ulong 
dbgpc(Proc *p) 
1999/0122    
{ 
1999/0123    
	Ureg *ureg; 
1999/0122    
                 
1999/0123    
	ureg = p->dbgreg; 
	if(ureg == 0) 
		return 0; 
                 
	return ureg->pc; 
1999/0128    
} 
                 
/* 
 *  system calls 
 */ 
#include "../port/systab.h" 
                 
/* 
 *  Syscall should be called directly from assembler without going through trap(). 
 */ 
void 
syscall(Ureg* ureg) 
{ 
	ulong	sp; 
	long	ret; 
	int	i, scallnr; 
                 
	if((ureg->srr1 & MSR_PR) == 0) 
		panic("syscall: srr1 0x%4.4uX\n", ureg->srr1); 
                 
	m->syscall++; 
	up->insyscall = 1; 
	up->pc = ureg->pc; 
	up->dbgreg = ureg; 
                 
	scallnr = ureg->r3; 
2000/0516    
//print("scall %s lr =%lux\n", sysctab[scallnr], ureg->lr); 
1999/0128    
	up->scallnr = scallnr; 
	spllo(); 
                 
	sp = ureg->usp; 
	up->nerrlab = 0; 
	ret = -1; 
	if(!waserror()){ 
		if(scallnr >= nsyscall){ 
			pprint("bad sys call number %d pc %lux\n", scallnr, ureg->pc); 
			postnote(up, 1, "sys: bad sys call", NDebug); 
			error(Ebadarg); 
		} 
                 
		if(sp<(USTKTOP-BY2PG) || sp>(USTKTOP-sizeof(Sargs)-BY2WD)) 
			validaddr(sp, sizeof(Sargs)+BY2WD, 0); 
                 
		up->s = *((Sargs*)(sp+BY2WD)); 
		up->psstate = sysctab[scallnr]; 
                 
		ret = systab[scallnr](up->s.args); 
		poperror(); 
	} 
	if(up->nerrlab){ 
		print("bad errstack [%d]: %d extra\n", scallnr, up->nerrlab); 
2000/0617    
		print("scall %s lr =%lux\n", sysctab[scallnr], ureg->lr); 
1999/0128    
		for(i = 0; i < NERR; i++) 
			print("sp=%lux pc=%lux\n", up->errlab[i].sp, up->errlab[i].pc); 
		panic("error stack"); 
	} 
                 
	up->insyscall = 0; 
	up->psstate = 0; 
                 
	/* 
	 *  Put return value in frame.  On the x86 the syscall is 
	 *  just another trap and the return value from syscall is 
	 *  ignored.  On other machines the return value is put into 
	 *  the results register by caller of syscall. 
	 */ 
	ureg->r3 = ret; 
                 
1999/0508    
	if(scallnr == NOTED) 
		noted(ureg, *(ulong*)(sp+BY2WD)); 
                 
	if(scallnr!=RFORK && (up->procctl || up->nnote)){ 
		splhi(); 
		notify(ureg); 
	} 
} 
/* 
 *  Call user, if necessary, with note. 
 *  Pass user the Ureg struct and the note on his stack. 
 */ 
int 
notify(Ureg* ur) 
{ 
	int l; 
	ulong s, sp; 
	Note *n; 
                 
	if(up->procctl) 
		procctl(up); 
	if(up->nnote == 0) 
		return 0; 
                 
	s = spllo(); 
	qlock(&up->debug); 
	up->notepending = 0; 
	n = &up->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 && (up->notified || up->notify==0)){ 
		if(n->flag == NDebug) 
			pprint("suicide: %s\n", n->msg); 
		qunlock(&up->debug); 
		pexit(n->msg, n->flag!=NDebug); 
	} 
                 
	if(up->notified) { 
		qunlock(&up->debug); 
		splhi(); 
		return 0; 
	} 
                 
	if(!up->notify) { 
		qunlock(&up->debug); 
		pexit(n->msg, n->flag!=NDebug); 
	} 
	sp = ur->usp & ~(BY2V-1); 
	sp -= sizeof(Ureg); 
                 
	if(!okaddr((ulong)up->notify, BY2WD, 0) || 
	   !okaddr(sp-ERRLEN-4*BY2WD, sizeof(Ureg)+ERRLEN+4*BY2WD, 1)) { 
		pprint("suicide: bad address or sp in notify\n"); 
		qunlock(&up->debug); 
		pexit("Suicide", 0); 
	} 
                 
	memmove((Ureg*)sp, ur, sizeof(Ureg)); 
	*(Ureg**)(sp-BY2WD) = up->ureg;	/* word under Ureg is old up->ureg */ 
	up->ureg = (void*)sp; 
	sp -= BY2WD+ERRLEN; 
	memmove((char*)sp, up->note[0].msg, ERRLEN); 
	sp -= 3*BY2WD; 
	*(ulong*)(sp+2*BY2WD) = sp+3*BY2WD;	/* arg 2 is string */ 
	ur->r1 = (long)up->ureg;		/* arg 1 is ureg* */ 
	((ulong*)sp)[1] = (ulong)up->ureg;	/* arg 1 0(FP) is ureg* */ 
	((ulong*)sp)[0] = 0;			/* arg 0 is pc */ 
	ur->usp = sp; 
	ur->pc = (ulong)up->notify; 
	up->notified = 1; 
	up->nnote--; 
	memmove(&up->lastnote, &up->note[0], sizeof(Note)); 
	memmove(&up->note[0], &up->note[1], up->nnote*sizeof(Note)); 
                 
	qunlock(&up->debug); 
	splx(s); 
	return 1; 
} 
                 
                 
/* 
 *   Return user to state before notify() 
 */ 
void 
noted(Ureg* ureg, ulong arg0) 
{ 
	Ureg *nureg; 
	ulong oureg, sp; 
                 
	qlock(&up->debug); 
	if(arg0!=NRSTR && !up->notified) { 
		qunlock(&up->debug); 
		pprint("call to noted() when not notified\n"); 
		pexit("Suicide", 0); 
	} 
	up->notified = 0; 
                 
	nureg = up->ureg;	/* pointer to user returned Ureg struct */ 
                 
	/* sanity clause */ 
	oureg = (ulong)nureg; 
	if(!okaddr((ulong)oureg-BY2WD, BY2WD+sizeof(Ureg), 0)){ 
		pprint("bad ureg in noted or call to noted when not notified\n"); 
		qunlock(&up->debug); 
		pexit("Suicide", 0); 
	} 
                 
	memmove(ureg, nureg, sizeof(Ureg)); 
                 
	switch(arg0){ 
	case NCONT: 
	case NRSTR: 
		if(!okaddr(nureg->pc, 1, 0) || !okaddr(nureg->usp, BY2WD, 0)){ 
			pprint("suicide: trap in noted\n"); 
			qunlock(&up->debug); 
			pexit("Suicide", 0); 
		} 
		up->ureg = (Ureg*)(*(ulong*)(oureg-BY2WD)); 
		qunlock(&up->debug); 
		break; 
                 
	case NSAVE: 
		if(!okaddr(nureg->pc, BY2WD, 0) 
		|| !okaddr(nureg->usp, BY2WD, 0)){ 
			pprint("suicide: trap in noted\n"); 
			qunlock(&up->debug); 
			pexit("Suicide", 0); 
		} 
		qunlock(&up->debug); 
		sp = oureg-4*BY2WD-ERRLEN; 
		splhi(); 
		ureg->sp = sp; 
		((ulong*)sp)[1] = oureg;	/* arg 1 0(FP) is ureg* */ 
		((ulong*)sp)[0] = 0;		/* arg 0 is pc */ 
		break; 
                 
	default: 
		pprint("unknown noted arg 0x%lux\n", arg0); 
		up->lastnote.flag = NDebug; 
		/* fall through */ 
		                 
	case NDFLT: 
		if(up->lastnote.flag == NDebug) 
			pprint("suicide: %s\n", up->lastnote.msg); 
		qunlock(&up->debug); 
		pexit(up->lastnote.msg, up->lastnote.flag!=NDebug); 
	} 
1999/0122    
} 


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