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

2001/0924/alphapc/trap.c (diff list | history)

1999/0415/sys/src/9/alphapc/trap.c:46,561999/0515/sys/src/9/alphapc/trap.c:46,51 (short | long)
1999/0415    
	if(user){ 
		up = m->proc; 
		up->dbgreg = ur; 
		if(up && up->fpstate == FPactive) { 
			up->fpstate = FPinactive; 
			savefpregs(&up->fpsave); 
			fpenab(0); 
		} 
	} 
	switch ((int)ur->type) { 
	case 1:	/* arith */ 
1999/0415/sys/src/9/alphapc/trap.c:82,961999/0515/sys/src/9/alphapc/trap.c:77,85
1999/0415    
		break; 
	} 
 
	splhi(); 
	if(!user) 
		return; 
                 
	notify(ur); 
	if(up->fpstate == FPinactive) { 
		fpenab(1); 
		restfpregs(&up->fpsave); 
		up->fpstate = FPactive; 
1999/0515    
	if(user && (up->procctl || up->nnote)){ 
		splhi(); 
		notify(ur); 
1999/0415    
	} 
} 
 
1999/0415/sys/src/9/alphapc/trap.c:500,5241999/0515/sys/src/9/alphapc/trap.c:489,512
1999/0415    
	up->dbgreg = aur; 
	ur->type = 5;		/* for debugging */ 
 
	if(up->fpstate == FPactive) { 
		up->fpsave.fpstatus = getfcr(); 
		up->fpstate = FPinit; 
		fpenab(0); 
1999/0515    
	up->scallnr = ur->r0; 
 
	if(up->scallnr == RFORK && up->fpstate == FPactive){ 
		savefpregs(&up->fpsave); 
		up->fpstate = FPinactive; 
//print("SR=%lux+", up->fpsave.fpstatus); 
1999/0415    
	} 
	spllo(); 
 
	if(up->procctl) 
		procctl(up); 
                 
	up->scallnr = ur->r0; 
	up->nerrlab = 0; 
	sp = ur->sp; 
1999/0515    
	up->nerrlab = 0; 
1999/0415    
	ret = -1; 
	if(waserror()) 
		goto error; 
 
	if(up->scallnr >= nsyscall){ 
		pprint("bad sys call %d pc %lux\n", up->scallnr, (ulong)ur->pc); 
1999/0515    
		pprint("bad sys call %d pc %lux\n", 
			up->scallnr, (ulong)ur->pc); 
1999/0415    
print("bad sys call %d pc %lux\n", up->scallnr, (ulong)ur->pc); 
		postnote(up, 1, "sys: bad sys call", NDebug); 
		error(Ebadarg); 
1999/0415/sys/src/9/alphapc/trap.c:525,5311999/0515/sys/src/9/alphapc/trap.c:513,520
1999/0415    
	} 
 
	if(sp & (BY2WD-1)){	/* XXX too weak? */ 
		pprint("odd sp in sys call pc %lux sp %lux\n", (ulong)ur->pc, (ulong)ur->sp); 
1999/0515    
		pprint("odd sp in sys call pc %lux sp %lux\n", 
			(ulong)ur->pc, (ulong)ur->sp); 
1999/0415    
		postnote(up, 1, "sys: odd stack", NDebug); 
		error(Ebadarg); 
	} 
1999/0415/sys/src/9/alphapc/trap.c:543,5521999/0515/sys/src/9/alphapc/trap.c:532,540
1999/0415    
	up->nerrlab = 0; 
	up->psstate = 0; 
	up->insyscall = 0; 
	if(up->scallnr == NOTED)				/* ugly hack */ 
1999/0515    
	if(up->scallnr == NOTED)			/* ugly hack */ 
1999/0415    
		noted(ur, &aur, *(ulong*)(sp+2*BY2WD));	/* doesn't return */ 
 
	splhi(); 
	if(up->scallnr!=RFORK && (up->procctl || up->nnote)){ 
		ur->r0 = ret;				/* load up for noted() */ 
		if(notify(ur)) 
1999/0415/sys/src/9/alphapc/trap.c:553,5611999/0515/sys/src/9/alphapc/trap.c:541,546
1999/0415    
			return ur->r0; 
	} 
 
	if(up->fpstate == FPinactive)		/* due to race with intr */ 
		up->fpstate = FPinit; 
                 
	return ret; 
} 
 
1999/0415/sys/src/9/alphapc/trap.c:605,6111999/0515/sys/src/9/alphapc/trap.c:590,595
1999/0415    
	ur = (Ureg*)up->dbgreg; 
	ur->usp = (ulong)sp; 
	ur->pc = entry; 
	up->fpsave.fpstatus = initfp.fpstatus; 
	return USTKTOP-BY2WD;			/* address of user-level clock */ 
} 
 
1999/0415/sys/src/9/alphapc/trap.c:683,7001999/0515/sys/src/9/alphapc/trap.c:667,686
1999/0415    
void 
fen(Ureg *ur) 
{ 
	ulong fpcr; 
                 
	if ((ur->status&UMODE) && up) { 
		if(up->fpstate == FPinit) { 
1999/0515    
	if(up){ 
		switch(up->fpstate){ 
		case FPinit: 
			restfpregs(&initfp); 
1999/0415    
			up->fpstate = FPactive; 
			fpcr = up->fpsave.fpstatus; 
			up->fpsave = initfp; 
			up->fpsave.fpstatus = fpcr; 
			fpenab(1); 
1999/0515    
//print("EI=%lux+", initfp.fpstatus); 
			return; 
 
		case FPinactive: 
1999/0415    
			restfpregs(&up->fpsave); 
1999/0515    
			up->fpstate = FPactive; 
//print("EIA=%lux+", up->fpsave.fpstatus); 
1999/0415    
			return; 
		} 
	} 
	fataltrap(ur, "trap: floating enable");		/* should never happen */ 
1999/0515    
	fataltrap(ur, "trap: floating enable");	/* should never happen */ 
1999/0415    
} 
1999/0515/sys/src/9/alphapc/trap.c:41,461999/0701/sys/src/9/alphapc/trap.c:41,47 (short | long)
1999/0415    
	char buf[ERRLEN]; 
	int user, x; 
 
1999/0701    
	m->intrts = fastticks(nil); 
1999/0415    
	user = ur->status&UMODE; 
 
	if(user){ 
1999/0701/sys/src/9/alphapc/trap.c:280,2852000/0108/sys/src/9/alphapc/trap.c:280,294 (short | long)
1999/0415    
} 
 
void 
2000/0108    
callwithureg(void (*fn)(Ureg*)) 
{ 
	Ureg ureg; 
	ureg.pc = getcallerpc(&fn); 
	ureg.sp = (ulong)&fn; 
	fn(&ureg); 
} 
 
void 
1999/0415    
dumpregs(Ureg *ur) 
{ 
	int i, col; 
2000/0108/sys/src/9/alphapc/trap.c:35,892000/0125/sys/src/9/alphapc/trap.c:35,40 (short | long)
1999/0415    
	arch->intrenable(irq, f, a, tbdf); 
} 
 
void 
trap(Ureg *ur) 
{ 
	char buf[ERRLEN]; 
	int user, x; 
                 
1999/0701    
	m->intrts = fastticks(nil); 
1999/0415    
	user = ur->status&UMODE; 
                 
	if(user){ 
		up = m->proc; 
		up->dbgreg = ur; 
	} 
	switch ((int)ur->type) { 
	case 1:	/* arith */ 
		fptrap(ur); 
		break; 
	case 2:	/* bad instr or FEN */ 
		illegal(ur); 
		break; 
	case 3:	/* intr */ 
		intr(ur); 
		break; 
	case 4:	/* memory fault */ 
		if(up == 0) 
			kernfault(ur, (ulong)ur->a1); 
                 
		x = up->insyscall; 
		up->insyscall = 1; 
		spllo(); 
		faultalpha(ur); 
		up->insyscall = x; 
		break; 
	case 6:	/* alignment fault */ 
		ur->pc -= 4; 
		sprint(buf, "trap: unaligned addr 0x%lux", (ulong)ur->a0); 
		fataltrap(ur, buf); 
		break; 
	default:	/* cannot happen */ 
		panic("bad trap type %d", (int)ur->type); 
		break; 
	} 
                 
1999/0515    
	if(user && (up->procctl || up->nnote)){ 
		splhi(); 
		notify(ur); 
1999/0415    
	} 
} 
                 
typedef struct Mcheck Mcheck; 
struct Mcheck 
{ 
2000/0108/sys/src/9/alphapc/trap.c:149,1812000/0125/sys/src/9/alphapc/trap.c:100,189
1999/0415    
} 
 
void 
intr(Ureg *ur) 
2000/0125    
trap(Ureg *ur) 
1999/0415    
{ 
	m->intr++; 
	switch ((int)ur->a0) { 
	case 0:	/* interprocessor */ 
		panic("interprocessor intr"); 
2000/0125    
	char buf[ERRLEN]; 
	int user, x; 
 
	m->intrts = fastticks(nil); 
	user = ur->status&UMODE; 
 
	if(user){ 
		up = m->proc; 
		up->dbgreg = ur; 
	} 
	switch ((int)ur->type) { 
	case 1:	/* arith */ 
		fptrap(ur); 
1999/0415    
		break; 
	case 1:	/* clock */ 
		clock(ur); 
2000/0125    
	case 2:	/* bad instr or FEN */ 
		illegal(ur); 
1999/0415    
		break; 
	case 2:	/* machine check */ 
		mcheck((void*)(KZERO|(ulong)ur->a2)); 
2000/0125    
 
	case 3:	/* intr */ 
		m->intr++; 
		switch ((int)ur->a0) { 
		case 0:	/* interprocessor */ 
			panic("interprocessor intr"); 
			break; 
		case 1:	/* clock */ 
			clock(ur); 
			break; 
		case 2:	/* machine check */ 
			mcheck((void*)(KZERO|(ulong)ur->a2)); 
			break; 
		case 3:	/* device */ 
			arch->intr(ur); 
			/*  
			 *  preemptive scheduling.  to limit stack depth, 
			 *  make sure process has a chance to return from 
			 *  the current interrupt before being preempted a 
			 *  second time. 
			 */ 
			if(up && up->state == Running) 
			if(anyhigher()) 
			if(up->preempted == 0) 
			if(!active.exiting){ 
				up->preempted = 1; 
				sched(); 
				splhi(); 
				up->preempted = 0; 
				return; 
			} 
			break; 
		case 4:	/* perf counter */ 
			panic("perf count"); 
			break; 
		default: 
			panic("bad intr"); 
			break; 
		} 
1999/0415    
		break; 
	case 3:	/* device */ 
		arch->intr(ur); 
2000/0125    
 
	case 4:	/* memory fault */ 
		if(up == 0) 
			kernfault(ur, (ulong)ur->a1); 
 
		x = up->insyscall; 
		up->insyscall = 1; 
		spllo(); 
		faultalpha(ur); 
		up->insyscall = x; 
1999/0415    
		break; 
	case 4:	/* perf counter */ 
		panic("perf count"); 
2000/0125    
	case 6:	/* alignment fault */ 
		ur->pc -= 4; 
		sprint(buf, "trap: unaligned addr 0x%lux", (ulong)ur->a0); 
		fataltrap(ur, buf); 
1999/0415    
		break; 
	default: 
		panic("bad intr"); 
2000/0125    
	default:	/* cannot happen */ 
		panic("bad trap type %d", (int)ur->type); 
1999/0415    
		break; 
	} 
 
	/* preemptive scheduling */ 
	if(up && up->state == Running && anyhigher()) 
		sched(); 
2000/0125    
	if(user && (up->procctl || up->nnote)){ 
		splhi(); 
		notify(ur); 
	} 
1999/0415    
} 
 
void 
2000/0108/sys/src/9/alphapc/trap.c:250,2552000/0125/sys/src/9/alphapc/trap.c:258,265
1999/0415    
		el = sl + KSTACK; 
	} 
	if(l > el || l < sl){ 
2000/0125    
		iprint("dumpstack: l %lux sl %lux el %lux m %lux up %lux\n", 
			l, sl, el, m, up); 
1999/0415    
		el = (ulong)m+BY2PG; 
		sl = el-KSTACK; 
	} 
2000/0125/sys/src/9/alphapc/trap.c:29,402000/0401/sys/src/9/alphapc/trap.c:29,117 (short | long)
1999/0415    
	"R18", 
}; 
 
2000/0401    
static Lock vctllock; 
static Vctl *vctl[256]; 
 
1999/0415    
void 
intrenable(int irq, void (*f)(Ureg*, void*), void* a, int tbdf) 
2000/0401    
intrenable(int irq, void (*f)(Ureg*, void*), void* a, int tbdf, char *name) 
1999/0415    
{ 
	arch->intrenable(irq, f, a, tbdf); 
2000/0401    
	int vno; 
	Vctl *v, *p; 
 
	v = xalloc(sizeof(Vctl)); 
	v->isintr = 1; 
	v->irq = irq; 
	v->tbdf = tbdf; 
	v->f = f; 
	v->a = a; 
	strncpy(v->name, name, NAMELEN-1); 
	v->name[NAMELEN-1] = 0; 
 
	ilock(&vctllock); 
	vno = arch->intrenable(v); 
	if(vno == -1){ 
		iunlock(&vctllock); 
		print("intrenable: couldn't enable irq %d, tbdf 0x%uX for %s\n", 
			irq, tbdf, v->name); 
		if(p=vctl[vno]){ 
			print("intrenable: irq %d is already used by", irq); 
			for(; p; p=p->next) 
				print(" %s", p->name); 
			print("\n"); 
		} 
		xfree(v); 
		return; 
	} 
	if(vctl[vno]){ 
		if(vctl[vno]->isr != v->isr || vctl[vno]->eoi != v->eoi) 
			panic("intrenable: handler: %s %s %luX %luX %luX %luX\n", 
				vctl[vno]->name, v->name, 
				vctl[vno]->isr, v->isr, vctl[vno]->eoi, v->eoi); 
		v->next = vctl[vno]; 
	} 
	vctl[vno] = v; 
	iunlock(&vctllock); 
1999/0415    
} 
 
2000/0401    
int 
irqallocread(char *buf, long n, vlong offset) 
{ 
	int vno; 
	Vctl *v; 
	long oldn; 
	char str[11+1+NAMELEN+1], *p; 
	int m; 
 
	if(n < 0 || offset < 0) 
		error(Ebadarg); 
 
	oldn = n; 
	for(vno=0; vno<nelem(vctl); vno++){ 
		for(v=vctl[vno]; v; v=v->next){ 
			m = snprint(str, sizeof str, "%11d %11d %.*s\n", vno, v->irq, NAMELEN, v->name); 
			if(m <= offset)	/* if do not want this, skip entry */ 
				offset -= m; 
			else{ 
				/* skip offset bytes */ 
				m -= offset; 
				p = str+offset; 
				offset = 0; 
 
				/* write at most max(n,m) bytes */ 
				if(m > n) 
					m = n; 
				memmove(buf, p, m); 
				n -= m; 
				buf += m; 
 
				if(n == 0) 
					return oldn; 
			}	 
		} 
	} 
	return oldn - n; 
} 
 
1999/0415    
typedef struct Mcheck Mcheck; 
struct Mcheck 
{ 
2000/0125/sys/src/9/alphapc/trap.c:100,1052000/0401/sys/src/9/alphapc/trap.c:177,255
1999/0415    
} 
 
void 
2000/0401    
intr(Ureg *ur) 
{ 
	int i, vno; 
	Vctl *ctl, *v; 
	Mach *mach; 
 
	vno = (ulong)ur->a1>>4; 
	vno -= 0x80; 
	if(vno < nelem(vctl) && (ctl = vctl[vno])){ 
		if(ctl->isintr){ 
			m->intr++; 
			if(vno >= VectorPIC && vno <= MaxVectorPIC) 
				m->lastintr = vno-VectorPIC; 
		} 
 
		if(ctl->isr) 
			ctl->isr(vno); 
		for(v = ctl; v != nil; v = v->next) { 
			if(v->f) 
				v->f(ur, v->a); 
		} 
 
		if(ctl->eoi) 
			ctl->eoi(vno); 
 
		/*  
		 *  preemptive scheduling.  to limit stack depth, 
		 *  make sure process has a chance to return from 
		 *  the current interrupt before being preempted a 
		 *  second time. 
		 */ 
		if(ctl->isintr) 
		if(up && up->state == Running) 
		if(anyhigher()) 
		if(up->preempted == 0) 
		if(!active.exiting){ 
			up->preempted = 1; 
			sched(); 
			splhi(); 
			up->preempted = 0; 
			return; 
		} 
	} 
	else if(vno >= VectorPIC && vno <= MaxVectorPIC){ 
		/* 
		 * An unknown interrupt. 
		 * Check for a default IRQ7. This can happen when 
		 * the IRQ input goes away before the acknowledge. 
		 * In this case, a 'default IRQ7' is generated, but 
		 * the corresponding bit in the ISR isn't set. 
		 * In fact, just ignore all such interrupts. 
		 */ 
		iprint("cpu%d: spurious interrupt %d, last %d", 
			m->machno, vno-VectorPIC, m->lastintr); 
		for(i = 0; i < 32; i++){ 
			if(!(active.machs & (1<<i))) 
				continue; 
			mach = MACHP(i); 
			if(m->machno == mach->machno) 
				continue; 
			iprint(": cpu%d: last %d", mach->machno, mach->lastintr); 
		} 
		iprint("\n"); 
		m->spuriousintr++; 
		return; 
	} 
	else{ 
		dumpregs(ur); 
		panic("unknown intr: %d\n", vno); /* */ 
	} 
} 
 
void 
2000/0125    
trap(Ureg *ur) 
1999/0415    
{ 
2000/0125    
	char buf[ERRLEN]; 
2000/0125/sys/src/9/alphapc/trap.c:133,1552000/0401/sys/src/9/alphapc/trap.c:283,289
2000/0125    
			mcheck((void*)(KZERO|(ulong)ur->a2)); 
			break; 
		case 3:	/* device */ 
			arch->intr(ur); 
			/*  
			 *  preemptive scheduling.  to limit stack depth, 
			 *  make sure process has a chance to return from 
			 *  the current interrupt before being preempted a 
			 *  second time. 
			 */ 
			if(up && up->state == Running) 
			if(anyhigher()) 
			if(up->preempted == 0) 
			if(!active.exiting){ 
				up->preempted = 1; 
				sched(); 
				splhi(); 
				up->preempted = 0; 
				return; 
			} 
2000/0401    
			intr(ur); 
2000/0125    
			break; 
		case 4:	/* perf counter */ 
			panic("perf count"); 
2000/0401/sys/src/9/alphapc/trap.c:44,512001/0727/sys/src/9/alphapc/trap.c:44,51 (short | long)
2000/0401    
	v->tbdf = tbdf; 
	v->f = f; 
	v->a = a; 
	strncpy(v->name, name, NAMELEN-1); 
	v->name[NAMELEN-1] = 0; 
2001/0727    
	strncpy(v->name, name, KNAMELEN-1); 
	v->name[KNAMELEN-1] = 0; 
2000/0401    
 
	ilock(&vctllock); 
	vno = arch->intrenable(v); 
2000/0401/sys/src/9/alphapc/trap.c:79,852001/0727/sys/src/9/alphapc/trap.c:79,85
2000/0401    
	int vno; 
	Vctl *v; 
	long oldn; 
	char str[11+1+NAMELEN+1], *p; 
2001/0727    
	char str[11+1+KNAMELEN+1], *p; 
2000/0401    
	int m; 
 
	if(n < 0 || offset < 0) 
2000/0401/sys/src/9/alphapc/trap.c:88,942001/0727/sys/src/9/alphapc/trap.c:88,94
2000/0401    
	oldn = n; 
	for(vno=0; vno<nelem(vctl); vno++){ 
		for(v=vctl[vno]; v; v=v->next){ 
			m = snprint(str, sizeof str, "%11d %11d %.*s\n", vno, v->irq, NAMELEN, v->name); 
2001/0727    
			m = snprint(str, sizeof str, "%11d %11d %.*s\n", vno, v->irq, KNAMELEN, v->name); 
2000/0401    
			if(m <= offset)	/* if do not want this, skip entry */ 
				offset -= m; 
			else{ 
2000/0401/sys/src/9/alphapc/trap.c:252,2582001/0727/sys/src/9/alphapc/trap.c:252,258
2000/0401    
void 
2000/0125    
trap(Ureg *ur) 
1999/0415    
{ 
2000/0125    
	char buf[ERRLEN]; 
2001/0727    
	char buf[ERRMAX]; 
2000/0125    
	int user, x; 
 
	m->intrts = fastticks(nil); 
2000/0401/sys/src/9/alphapc/trap.c:335,3412001/0727/sys/src/9/alphapc/trap.c:335,341
1999/0415    
void 
fataltrap(Ureg *ur, char *reason) 
{ 
	char buf[ERRLEN]; 
2001/0727    
	char buf[ERRMAX]; 
1999/0415    
 
	if(ur->status&UMODE) { 
		spllo(); 
2000/0401/sys/src/9/alphapc/trap.c:474,4812001/0727/sys/src/9/alphapc/trap.c:474,481
1999/0415    
	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; 
2001/0727    
		if(l > ERRMAX-15)	/* " pc=0x12345678\0" */ 
			l = ERRMAX-15; 
1999/0415    
 
		sprint(n->msg+l, " pc=0x%lux", (ulong)ur->pc); 
	} 
2000/0401/sys/src/9/alphapc/trap.c:501,5072001/0727/sys/src/9/alphapc/trap.c:501,507
1999/0415    
	sp -= sizeof(Ureg); 
 
	if(!okaddr((ulong)up->notify, BY2WD, 0) 
	|| !okaddr(sp-ERRLEN-6*BY2WD, sizeof(Ureg)+ERRLEN-6*BY2WD, 1)) { 
2001/0727    
	|| !okaddr(sp-ERRMAX-6*BY2WD, sizeof(Ureg)+ERRMAX-6*BY2WD, 1)) { 
1999/0415    
		pprint("suicide: bad address or sp in notify\n"); 
print("suicide: bad address or sp in notify\n"); 
		qunlock(&up->debug); 
2000/0401/sys/src/9/alphapc/trap.c:511,5182001/0727/sys/src/9/alphapc/trap.c:511,518
1999/0415    
	memmove((Ureg*)sp, ur, sizeof(Ureg)); 
	*(Ureg**)(sp-BY2WD) = up->ureg;	/* word under Ureg is old up->ureg */ 
	up->ureg = (void*)sp; 
	sp -= 2*BY2WD+ERRLEN; 
	memmove((char*)sp, up->note[0].msg, ERRLEN); 
2001/0727    
	sp -= 2*BY2WD+ERRMAX; 
	memmove((char*)sp, up->note[0].msg, ERRMAX); 
1999/0415    
	sp -= 4*BY2WD; 
	*(ulong*)(sp+3*BY2WD) = sp+4*BY2WD;	/* arg 2 is string */ 
	ur->r0 = (ulong)up->ureg;		/* arg 1 (R0) is ureg* */ 
2000/0401/sys/src/9/alphapc/trap.c:603,6092001/0727/sys/src/9/alphapc/trap.c:603,609
1999/0415    
			pexit("Suicide", 0); 
		} 
		qunlock(&up->debug); 
		sp = oureg-4*BY2WD-ERRLEN; 
2001/0727    
		sp = oureg-4*BY2WD-ERRMAX; 
1999/0415    
		splhi(); 
		(*urp)->sp = sp; 
		((ulong*)sp)[1] = oureg;	/* arg 1 0(FP) is ureg* */ 
2001/0727/sys/src/9/alphapc/trap.c:245,2512001/0728/sys/src/9/alphapc/trap.c:245,251 (short | long)
2000/0401    
	} 
	else{ 
		dumpregs(ur); 
		panic("unknown intr: %d\n", vno); /* */ 
2001/0728    
		print("unknown intr: %d\n", vno); /* */ 
2000/0401    
	} 
} 
 
2001/0727/sys/src/9/alphapc/trap.c:375,3822001/0728/sys/src/9/alphapc/trap.c:375,425
1999/0415    
} 
 
void 
dumpstack(void) 
2001/0728    
dumpregs(Ureg *ur) 
1999/0415    
{ 
2001/0728    
	int i, col; 
	uvlong *l; 
 
	if(up) 
		print("registers for %s %ld\n", up->text, up->pid); 
	else 
		print("registers for kernel\n"); 
 
	l = &ur->type; 
	col = 0; 
	for (i = 0; i < sizeof regname/sizeof(char*); i++, l++) { 
		print("%-7s%.16llux%s", regname[i], *l, col == 2 ? "\n" : "     "); 
		if (col++ == 2) 
			col = 0; 
	} 
	print("\n"); 
} 
 
 
/* 
 * Fill in enough of Ureg to get a stack trace, and call a function. 
 * Used by debugging interface rdb. 
 */ 
static void 
getpcsp(ulong *pc, ulong *sp) 
{ 
	*pc = getcallerpc(&pc); 
	*sp = (ulong)&pc-8; 
} 
 
void 
callwithureg(void (*fn)(Ureg*)) 
{ 
	Ureg ureg; 
 
	getpcsp((ulong*)&ureg.pc, (ulong*)&ureg.sp); 
	ureg.r26 = getcallerpc(&fn); 
	fn(&ureg); 
} 
 
void 
_dumpstack(Ureg *ureg) 
{ 
1999/0415    
	ulong l, sl, el, v, i, instr, op; 
	extern ulong etext; 
 
2001/0727/sys/src/9/alphapc/trap.c:392,4062001/0728/sys/src/9/alphapc/trap.c:435,446
1999/0415    
		el = sl + KSTACK; 
	} 
	if(l > el || l < sl){ 
2000/0125    
		iprint("dumpstack: l %lux sl %lux el %lux m %lux up %lux\n", 
			l, sl, el, m, up); 
1999/0415    
		el = (ulong)m+BY2PG; 
		sl = el-KSTACK; 
	} 
	iprint("dumpstack: l %lux sl %lux el %lux m %lux\n", l, sl, el, m); 
	if(l > el || l < sl){ 
2001/0728    
	if(l > el || l < sl) 
1999/0415    
		return; 
	} 
2001/0728    
	print("ktrace /kernel/path %.8lux %.8lux %.8lux\n", (ulong)ureg->pc, (ulong)ureg->sp, (ulong)ureg->r26); 
1999/0415    
 
	i = 0; 
	for(; l<el; l+=8){ 
2001/0727/sys/src/9/alphapc/trap.c:412,4592001/0728/sys/src/9/alphapc/trap.c:452,474
1999/0415    
			instr = *(ulong*)v; 
			op = (instr>>26); 
			if(op == 26 || op == 52){ 
				iprint("%lux ", v); 
2001/0728    
				print("%lux=%lux ", l, v); 
1999/0415    
				i++; 
			} 
		} 
		if(i == 8){ 
2001/0728    
		if(i == 4){ 
1999/0415    
			i = 0; 
			iprint("\n"); 
2001/0728    
			print("\n"); 
1999/0415    
		} 
	} 
2001/0728    
	if(i) 
		print("\n"); 
1999/0415    
} 
 
void 
2000/0108    
callwithureg(void (*fn)(Ureg*)) 
2001/0728    
dumpstack(void) 
2000/0108    
{ 
	Ureg ureg; 
	ureg.pc = getcallerpc(&fn); 
	ureg.sp = (ulong)&fn; 
	fn(&ureg); 
} 
                 
void 
1999/0415    
dumpregs(Ureg *ur) 
{ 
	int i, col; 
	uvlong *l; 
                 
	spllo(); 
	prflush();  
	if(up) 
		iprint("registers for %s %d\n", up->text, up->pid); 
	else 
		iprint("registers for kernel\n"); 
                 
	l = &ur->type; 
	col = 0; 
	for (i = 0; i < sizeof regname/sizeof(char*); i++, l++) { 
		iprint("%-7s%.16llux%s", regname[i], *l, col == 2 ? "\n" : "     "); 
		if (col++ == 2) 
			col = 0; 
	} 
	iprint("\n"); 
//	prflush(); 
2001/0728    
	callwithureg(_dumpstack); 
1999/0415    
} 
 
int 
2001/0728/sys/src/9/alphapc/trap.c:157,1632001/0803/sys/src/9/alphapc/trap.c:157,163 (short | long)
1999/0415    
} 
 
void 
mcheck(void *x) 
2001/0803    
mcheck(Ureg *ur, void *x) 
1999/0415    
{ 
	Mcheck *m; 
	uvlong *data; 
2001/0728/sys/src/9/alphapc/trap.c:173,1782001/0803/sys/src/9/alphapc/trap.c:173,183
1999/0415    
		if (col++ == 2) 
			col = 0; 
	} 
2001/0803    
	if(col != 2) 
		print("\n"); 
	print("\n"); 
	dumpregs(ur); 
	prflush(); 
1999/0415    
	firmware(); 
} 
 
2001/0728/sys/src/9/alphapc/trap.c:280,2862001/0803/sys/src/9/alphapc/trap.c:285,291
2000/0125    
			clock(ur); 
			break; 
		case 2:	/* machine check */ 
			mcheck((void*)(KZERO|(ulong)ur->a2)); 
2001/0803    
			mcheck(ur, (void*)(KZERO|(ulong)ur->a2)); 
2000/0125    
			break; 
		case 3:	/* device */ 
2000/0401    
			intr(ur); 
2001/0803/sys/src/9/alphapc/trap.c:703,7082001/0822/sys/src/9/alphapc/trap.c:703,710 (short | long)
1999/0415    
	poperror(); 
 
error: 
2001/0822    
	/* failure: save the error buffer for errstr */ 
	kstrcpy(up->syserror, up->error, sizeof up->syserror); 
1999/0415    
	up->nerrlab = 0; 
	up->psstate = 0; 
	up->insyscall = 0; 
2001/0822/sys/src/9/alphapc/trap.c:651,6562001/0924/sys/src/9/alphapc/trap.c:651,657 (short | long)
1999/0415    
long 
syscall(Ureg *aur) 
{ 
2001/0924    
	char *e; 
1999/0415    
	long ret; 
	ulong sp; 
	Ureg *ur; 
2001/0822/sys/src/9/alphapc/trap.c:704,7102001/0924/sys/src/9/alphapc/trap.c:705,714
1999/0415    
 
error: 
2001/0822    
	/* failure: save the error buffer for errstr */ 
	kstrcpy(up->syserror, up->error, sizeof up->syserror); 
2001/0924    
	e = up->syserrstr; 
	up->syserrstr = up->errstr; 
	up->errstr = e; 
 
1999/0415    
	up->nerrlab = 0; 
	up->psstate = 0; 
	up->insyscall = 0; 
2001/0924/sys/src/9/alphapc/trap.c:73,782001/1023/sys/src/9/alphapc/trap.c:73,109 (short | long)
2000/0401    
	iunlock(&vctllock); 
1999/0415    
} 
 
2001/1023    
void 
intrdisable(int irq, void (*f)(Ureg *, void *), void *a, int tbdf, char *name) 
{ 
	Vctl **pv, *v; 
	int vno; 
 
	/* 
	 * For now, none of this will work with the APIC code, 
	 * there is no mapping between irq and vector as the IRQ 
	 * is pretty meaningless. 
	 */ 
	if(arch->intrvecno == nil) 
		return; 
	vno = arch->intrvecno(irq); 
	ilock(&vctllock); 
	pv = &vctl[vno]; 
	while (*pv &&  
		  ((*pv)->irq != irq || (*pv)->tbdf != tbdf || (*pv)->f != f || (*pv)->a != a || 
		   strcmp((*pv)->name, name))) 
		pv = &((*pv)->next); 
	assert(*pv); 
 
	v = *pv; 
	*pv = (*pv)->next;	/* Link out the entry */ 
	 
	if (vctl[vno] == nil && arch->intrdisable != nil) 
		arch->intrdisable(irq); 
	iunlock(&vctllock); 
	xfree(v); 
} 
 
2000/0401    
int 
irqallocread(char *buf, long n, vlong offset) 
{ 
2001/1023/sys/src/9/alphapc/trap.c:196,2062001/1121/sys/src/9/alphapc/trap.c:196,206 (short | long)
1999/0415    
 
	m = x; 
	data = x; 
	iprint("panic: Machine Check @%lux: %s (%lux) len %d\n", 
2001/1121    
	iprint("panic: Machine Check @%lux: %s (%lux) len %lud\n", 
1999/0415    
			m, smcheck(m->code), m->code, m->len); 
	iprint("proc offset %lux sys offset %lux\n", m->procoff, m->sysoff); 
	for (i = 0, col = 0; i < m->len/8; i++) { 
		iprint("%.3lux: %.16llux%s", 8*i, data[i], (col == 2) ? "\n" : "    "); 
2001/1121    
		iprint("%.3x: %.16llux%s", 8*i, data[i], (col == 2) ? "\n" : "    "); 
1999/0415    
		if (col++ == 2) 
			col = 0; 
	} 
2001/1121/sys/src/9/alphapc/trap.c:682,6912002/0417/sys/src/9/alphapc/trap.c:682,693 (short | long)
1999/0415    
long 
syscall(Ureg *aur) 
{ 
2002/0417    
	int i; 
2001/0924    
	char *e; 
1999/0415    
	long ret; 
	ulong sp; 
	Ureg *ur; 
2002/0417    
	ulong scallnr; 
1999/0415    
 
	m->syscall++; 
	up = m->proc; 
2001/1121/sys/src/9/alphapc/trap.c:695,7032002/0417/sys/src/9/alphapc/trap.c:697,706
1999/0415    
	up->dbgreg = aur; 
	ur->type = 5;		/* for debugging */ 
 
2002/0417    
	scallnr = ur->r0; 
1999/0515    
	up->scallnr = ur->r0; 
 
	if(up->scallnr == RFORK && up->fpstate == FPactive){ 
2002/0417    
	if(scallnr == RFORK && up->fpstate == FPactive){ 
1999/0515    
		savefpregs(&up->fpsave); 
		up->fpstate = FPinactive; 
//print("SR=%lux+", up->fpsave.fpstatus); 
2001/1121/sys/src/9/alphapc/trap.c:707,7522002/0417/sys/src/9/alphapc/trap.c:710,757
1999/0415    
	sp = ur->sp; 
1999/0515    
	up->nerrlab = 0; 
1999/0415    
	ret = -1; 
	if(waserror()) 
		goto error; 
2002/0417    
	if(!waserror()) { 
		if(scallnr >= nsyscall || systab[scallnr] == nil){ 
			pprint("bad sys call %d pc %lux\n", up->scallnr, (ulong)ur->pc); 
			postnote(up, 1, "sys: bad sys call", NDebug); 
			error(Ebadarg); 
		} 
1999/0415    
 
	if(up->scallnr >= nsyscall){ 
1999/0515    
		pprint("bad sys call %d pc %lux\n", 
			up->scallnr, (ulong)ur->pc); 
1999/0415    
print("bad sys call %d pc %lux\n", up->scallnr, (ulong)ur->pc); 
		postnote(up, 1, "sys: bad sys call", NDebug); 
		error(Ebadarg); 
	} 
2002/0417    
		if(sp & (BY2WD-1)){	/* XXX too weak? */ 
			pprint("odd sp in sys call pc %lux sp %lux\n", 
				(ulong)ur->pc, (ulong)ur->sp); 
			postnote(up, 1, "sys: odd stack", NDebug); 
			error(Ebadarg); 
		} 
1999/0415    
 
	if(sp & (BY2WD-1)){	/* XXX too weak? */ 
1999/0515    
		pprint("odd sp in sys call pc %lux sp %lux\n", 
			(ulong)ur->pc, (ulong)ur->sp); 
1999/0415    
		postnote(up, 1, "sys: odd stack", NDebug); 
		error(Ebadarg); 
2002/0417    
		if(sp<(USTKTOP-BY2PG) || sp>(USTKTOP-sizeof(Sargs))) 
			validaddr(sp, sizeof(Sargs), 0); 
 
		up->s = *((Sargs*)(sp+2*BY2WD)); 
		up->psstate = sysctab[scallnr]; 
		ret = systab[scallnr](up->s.args); 
		poperror(); 
	}else{ 
		/* failure: save the error buffer for errstr */ 
		e = up->syserrstr; 
		up->syserrstr = up->errstr; 
		up->errstr = e; 
1999/0415    
	} 
2002/0417    
	if(up->nerrlab){ 
		print("bad errstack [%uld]: %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"); 
	} 
1999/0415    
 
	if(sp<(USTKTOP-BY2PG) || sp>(USTKTOP-sizeof(Sargs))) 
		validaddr(sp, sizeof(Sargs), 0); 
                 
	up->s = *((Sargs*)(sp+2*BY2WD)); 
	up->psstate = sysctab[up->scallnr]; 
                 
	ret = (*systab[up->scallnr])(up->s.args); 
	poperror(); 
                 
error: 
2001/0822    
	/* failure: save the error buffer for errstr */ 
2001/0924    
	e = up->syserrstr; 
	up->syserrstr = up->errstr; 
	up->errstr = e; 
                 
1999/0415    
	up->nerrlab = 0; 
	up->psstate = 0; 
	up->insyscall = 0; 
1999/0515    
	if(up->scallnr == NOTED)			/* ugly hack */ 
2002/0417    
	if(scallnr == NOTED)			/* ugly hack */ 
1999/0415    
		noted(ur, &aur, *(ulong*)(sp+2*BY2WD));	/* doesn't return */ 
 
	if(up->scallnr!=RFORK && (up->procctl || up->nnote)){ 
2002/0417    
	if(scallnr!=RFORK && (up->procctl || up->nnote)){ 
1999/0415    
		ur->r0 = ret;				/* load up for noted() */ 
		if(notify(ur)) 
			return ur->r0; 
2002/0417/sys/src/9/alphapc/trap.c:782,7872002/0615/sys/src/9/alphapc/trap.c:782,788 (short | long)
1999/0415    
{ 
	spllo(); 
	up->kpfun(up->kparg); 
2002/0615    
	pexit("kproc exiting", 0); 
1999/0415    
} 
 
void 
2002/0615/sys/src/9/alphapc/trap.c:291,2972002/0822/sys/src/9/alphapc/trap.c:291,296 (short | long)
2001/0727    
	char buf[ERRMAX]; 
2000/0125    
	int user, x; 
 
	m->intrts = fastticks(nil); 
	user = ur->status&UMODE; 
 
	if(user){ 
2002/0822/sys/src/9/alphapc/trap.c:521,5262002/0824/sys/src/9/alphapc/trap.c:521,533 (short | long)
1999/0415    
	spllo(); 
	qlock(&up->debug); 
	up->notepending = 0; 
2002/0824    
 
	if(up->fpstate == FPactive){ 
		savefpregs(&up->fpsave); 
		up->fpstate = FPinactive; 
	} 
	up->fpstate |= FPillegal; 
 
1999/0415    
	n = &up->note[0]; 
	if(strncmp(n->msg, "sys:", 4) == 0) { 
		l = strlen(n->msg); 
2002/0822/sys/src/9/alphapc/trap.c:610,6152002/0824/sys/src/9/alphapc/trap.c:617,624
1999/0415    
		pexit("Suicide", 0); 
	} 
	up->notified = 0; 
2002/0824    
 
	up->fpstate &= ~FPillegal; 
1999/0415    
 
	nur = up->ureg; 
 
2002/0824/sys/src/9/alphapc/trap.c:238,2602003/0301/sys/src/9/alphapc/trap.c:238,245 (short | long)
2000/0401    
		if(ctl->eoi) 
			ctl->eoi(vno); 
 
		/*  
		 *  preemptive scheduling.  to limit stack depth, 
		 *  make sure process has a chance to return from 
		 *  the current interrupt before being preempted a 
		 *  second time. 
		 */ 
		if(ctl->isintr) 
		if(up && up->state == Running) 
		if(anyhigher()) 
		if(up->preempted == 0) 
		if(!active.exiting){ 
			up->preempted = 1; 
			sched(); 
			splhi(); 
			up->preempted = 0; 
			return; 
		} 
2003/0301    
			preempted(); 
2000/0401    
	} 
	else if(vno >= VectorPIC && vno <= MaxVectorPIC){ 
		/* 


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