Plan 9 from Bell Labs’s /usr/web/sources/extra/9hist/mtx/trap.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


## diffname mtx/trap.c 2001/0810
## diff -e /dev/null /n/emeliedump/2001/0810/sys/src/9/mtx/trap.c
0a
#include	"u.h"
#include	"../port/lib.h"
#include	"mem.h"
#include	"dat.h"
#include	"fns.h"
#include	"ureg.h"
#include	"io.h"
#include	"../port/error.h"

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	faultpower(Ureg *ur, ulong addr, int read);
void	kernfault(Ureg*, int);
void	syscall(Ureg* ureg);
void	noted(Ureg*, ulong);
void	reset(void);

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",
};

void
sethvec(int v, void (*r)(void))
{
	ulong *vp, pa, o;

	vp = KADDR(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));
}

void
sethvec2(int v, void (*r)(void))
{
	ulong *vp;

	vp = (ulong*)KADDR(v);
	vp[0] = (18<<26)|(PADDR(r))|2;	/* ba */
	dcflush(vp, sizeof(*vp));
}

void
trap(Ureg *ur)
{
	int ecode;
	static struct {int callsched;} c = {1};
	int user = (ur->srr1 & MSR_PR) != 0;
	char buf[ERRLEN];

	m->intrts = fastticks(nil);
	ecode = (ur->cause >> 8) & 0xff;

if(ur->status & MSR_RI == 0)
print("double fault?: ecode = %d\n", ecode);
	switch(ecode){
	case CEI:
		intr(ur);
		break;

	case CDEC:
		clockintr(ur);
		break;
	case CIMISS:
		faultpower(ur, ur->pc, 1);
		break;
	case CITLBE:
		faultpower(ur, ur->pc, 1);
		break;
	case CDMISS:
if(0) print("CDMISS: %lux %lux\n", m->epn, m->cmp1);
		faultpower(ur, m->dar, 1);
		break;
	case CDTLBE:
		faultpower(ur, m->dar, !(m->dsisr & (1<<25)));
		break;

	case CEMU:
		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);
		break;

	case CSYSCALL:
		syscall(ur);
		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:
		spllo();
		print("ecode = %d\n", ecode);
		if(ecode < 0 || ecode >= 0x1F)
			ecode = 0x1F;
		print("kernel %s pc=0x%lux\n", excname[ecode], ur->pc);
		dumpregs(ur);
		dumpstack();
		delay(100);
		reset();
	}

	splhi();
	if(user)
		notify(ur);
}

void
faultpower(Ureg *ureg, ulong addr, int read)
{
	int user, insyscall, n;
	char buf[ERRLEN];
	user = (ureg->srr1 & MSR_PR) != 0;
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);
	insyscall = up->insyscall;
	up->insyscall = 1;
	spllo();
	n = fault(addr, read);
	if(n < 0){
		if(!user){
			dumpregs(ureg);
			panic("fault: 0x%lux\n", addr);
		}
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);
		sprint(buf, "sys: trap: fault %s addr=0x%lux",
			read? "read" : "write", addr);
		postnote(up, 1, buf, NDebug);
	}
	up->insyscall = insyscall;
}

void
spurious(Ureg *ur, void *a)
{
	USED(a);
	print("SPURIOUS interrupt pc=0x%lux cause=0x%lux\n",
		ur->pc, ur->cause);
	panic("bad interrupt");
}

#define	LEV(n)	(((n)<<1)|1)
#define	IRQ(n)	(((n)<<1)|0)

Lock	veclock;

void
trapinit(void)
{
	int i;
	IMM *io;


	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 < 0x2000; i += 0x100)
		sethvec(i, trapvec);

	//sethvec(CEI<<8, intrvec);
	sethvec2(CIMISS<<8, itlbmiss);
	sethvec2(CDMISS<<8, dtlbmiss);
	sethvec2(CDTLBE<<8, dtlberror);
}

void
intrenable(int v, void (*r)(Ureg*, void*), void *arg, int, char *name)
{
	Handler *h;
	IMM *io;

	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;

	/*
	 * 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);
}

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 %ud %uld %ud\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 %ld\n", up->text, up->pid);
		if(ur->srr1 & MSR_PR == 0)
		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]);
}

static void
linkproc(void)
{
//print("linkproc %ulx\n", up);
	spllo();
	(*up->kpfun)(up->kparg);
	pexit("", 0);
}

void
kprocchild(Proc *p, void (*func)(void*), void *arg)
{
	p->sched.pc = (ulong)linkproc;
	p->sched.sp = (ulong)p->kstack+KSTACK;

	p->kpfun = func;
	p->kparg = arg;
}

int
isvalid_pc(ulong pc)
{
	return KERNPC(pc) && (pc&3) == 0;
}

void
dumplongs(char*, ulong*, int)
{
}

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|MSR_RI));
predawn = 1;
print("reset = %ulx\n", getmsr());
	delay(1000);
	// cause checkstop -> causes reset
	*(uchar*)(0xdeadbeef) = 0;
	*(ulong*)(0) = 0;
}

/*
 * 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
forkchild(Proc *p, Ureg *ur)
{
	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->r3 = 0;
	
	/* Things from bottom of syscall we never got to execute */
	p->psstate = 0;
	p->insyscall = 0;
}

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
 */
void
setregisters(Ureg *xp, char *pureg, char *uva, int n)
{
	ulong status;

	status = xp->status;
	memmove(pureg, uva, n);
	xp->status = status;
}

/* Give enough context in the ureg to produce a kernel stack for
 * a sleeping process
 */
void
setkernur(Ureg* ureg, Proc* p)
{
	ureg->pc = p->sched.pc;
	ureg->sp = p->sched.sp+4;
}

ulong
dbgpc(Proc *p)
{
	Ureg *ureg;

	ureg = p->dbgreg;
	if(ureg == 0)
		return 0;

	return ureg->pc;
}

/*
 *  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 lr =%lux\n", sysctab[scallnr], ureg->lr);
	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);
		print("scall %s lr =%lux\n", sysctab[scallnr], ureg->lr);
		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;

	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);
	}
}
.
## diffname mtx/trap.c 2001/0822
## diff -e /n/emeliedump/2001/0810/sys/src/9/mtx/trap.c /n/emeliedump/2001/0822/sys/src/9/mtx/trap.c
655a
	}else{
		/* failure: save the error buffer for errstr */
		kstrcpy(up->syserror, up->error, sizeof up->syserror);
.
## diffname mtx/trap.c 2001/0924
## diff -e /n/emeliedump/2001/0822/sys/src/9/mtx/trap.c /n/emeliedump/2001/0924/sys/src/9/mtx/trap.c
658c
		e = up->syserrstr;
		up->syserrstr = up->errstr;
		up->errstr = e;
.
620a
	char *e;
.
## diffname mtx/trap.c 2001/1121
## diff -e /n/emeliedump/2001/0924/sys/src/9/mtx/trap.c /n/emeliedump/2001/1121/sys/src/9/mtx/trap.c
816c
		sp = oureg-4*BY2WD-ERRMAX;
.
747,748c
	sp -= BY2WD+ERRMAX;
	memmove((char*)sp, up->note[0].msg, ERRMAX);
.
738c
	   !okaddr(sp-ERRMAX-4*BY2WD, sizeof(Ureg)+ERRMAX+4*BY2WD, 1)) {
.
712,713c
		if(l > ERRMAX-15)	/* " pc=0x12345678\0" */
			l = ERRMAX-15;
.
626,627c
//	if((ureg->srr1 & MSR_PR) == 0)
//		panic("syscall: srr1 0x%4.4uX\n", ureg->srr1);
.
517a
#endif
.
505a
#ifdef BLOG
.
460c
//		if(ur->srr1 & MSR_PR == 0)
.
378a
#endif
.
334a
#ifdef BLOG
.
329a
#endif
.
296a
#ifdef BLOG
.
291a
#endif
.
263a
#ifdef	BLOG
.
226,227c
	char buf[ERRMAX];

//	user = (ureg->srr1 & MSR_PR) != 0;
.
216c
*/
.
161c
/* if(ur->status & MSR_RI == 0)
.
159a
//	user = (ur->srr1 & MSR_PR) != 0;
.
155,156c
	int user;
	char buf[ERRMAX];
.
## diffname mtx/trap.c 2001/1122
## diff -e /n/emeliedump/2001/1121/sys/src/9/mtx/trap.c /n/emeliedump/2001/1122/sys/src/9/mtx/trap.c
636,637c
	if((ureg->srr1 & MSR_PR) == 0)
		panic("syscall: srr1 0x%4.4uX\n", ureg->srr1);
.
229c
	user = (ureg->srr1 & MSR_PR) != 0;
.
217d
186,191d
184a
*/
.
171a
/*
.
162c
if(ur->status & MSR_RI == 0)
.
160c
	user = (ur->srr1 & MSR_PR) != 0;
.
## diffname mtx/trap.c 2001/1207
## diff -e /n/emeliedump/2001/1122/sys/src/9/mtx/trap.c /n/emeliedump/2001/1207/sys/src/9/mtx/trap.c
453a
}

void
dumpstack(void)
{
	callwithureg(_dumpstack);
.
447c
			print("%.8lux=%.8lux ", l, v);
.
442a

	print("ktrace /kernel/path %.8lux %.8lux\n", ureg->pc, ureg->sp);
.
437a
	Ureg ureg;
	ureg.pc = getcallerpc(&fn);
	ureg.sp = (ulong)&fn;
	fn(&ureg);
}

void
_dumpstack(Ureg *ureg)
{
.
436c
callwithureg(void (*fn)(Ureg*))
.
434a
/*
 * Fill in enough of Ureg to get a stack trace, and call a function.
 * Used by debugging interface rdb.
 */
.
285,290d
278a
	putmsr(getmsr() & ~MSR_IP);
.
265,277d
263d
261d
258a
sethvec(int v, void (*r)(void))
{
	ulong *vp, pa, o;

	vp = KADDR(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));
}

void
.
157a
print("trap\n");
.
119,150d
## diffname mtx/trap.c 2001/1208
## diff -e /n/emeliedump/2001/1207/sys/src/9/mtx/trap.c /n/emeliedump/2001/1208/sys/src/9/mtx/trap.c
485,514d
471d
455c
		if(ur->srr1 & MSR_PR == 0)
.
388,405d
261a

	putmsr(getmsr() & ~MSR_IP);
.
260c
	for(i = 0x200; i < 0x2000; i += 0x100)
.
258c
	 * set all exceptions to trap, except reset
.
254,256d
206,207c
		sprint(buf, "sys: trap: fault %s addr=0x%lux", read? "read" : "write", addr);
.
184a
	}
.
182,183c

	if(user && (up->procctl || up->nnote)){
		splhi();
.
178,180c
		if(ecode < nelem(excname))
			panic("%s", excname[ecode]);
		panic("unknown trap/intr: %d\n", ecode);
.
172,176c
print("default\n");
		if(ecode <= nelem(excname) && user){
			spllo();
			sprint(buf, "sys: trap: %s", excname[ecode]);
			postnote(up, 1, buf, NDebug);
			break;
		}
.
170d
163,168c
			s = "floating point exception";
		else if(ur->status & (1<<18))
			s = "illegal instruction";
		else if(ur->status & (1<<17))
			s = "privileged instruction";
		else
			s = "undefined program exception";
		if(user){
			spllo();
			sprint(buf, "sys: trap: %s", s);
			postnote(up, 1, buf, NDebug);
			break;
		}
		dumpregs(ur);
		panic(s);
		break;
.
161a
print("program\n");
.
157a
print("syscall\n");
.
141,155d
138a
print("clock\n");
.
134a
print("intr\n");
.
125a
if(m->loopconst != 5000) print("XXX\n");
.
121,124c
	int ecode,user;
	char buf[ERRMAX], *s;
.
58,80c
	"reserved 10",
	"reserved 11",
	"reserved 12",
	"instruction address breakpoint",
	"system management interrupt",
.
52c
	"reserved A",
.
35d
## diffname mtx/trap.c 2001/1212
## diff -e /n/emeliedump/2001/1208/sys/src/9/mtx/trap.c /n/emeliedump/2001/1212/sys/src/9/mtx/trap.c
238c
	for(i = 0; i < 0x2000; i += 0x100)
.
236c
	 * set all exceptions to trap
.
150c
print("trap: default\n");
.
105,106d
## diffname mtx/trap.c 2001/1215
## diff -e /n/emeliedump/2001/1212/sys/src/9/mtx/trap.c /n/emeliedump/2001/1215/sys/src/9/mtx/trap.c
327,330c
*/
.
321,324d
319d
317c
/*	do {
.
310,313c

.
291,308c
	v = mpicintack();
	if(v == 0) {			/* 8259 */
.
289d
287d
285d
279d
268,276d
263,266d
255,259c
	h = &halloc.h[halloc.free++];
	h->next = halloc.ivec[v];
	halloc.ivec[v] = h;
.
253c
		panic("intrenable(%d)", v);
.
251d
247d
245d
201,205d
33a
Lock	veclock;

.
29c
	Handler	*ivec[MaxVectorPIC+1];
.
## diffname mtx/trap.c 2001/1218
## diff -e /n/emeliedump/2001/1215/sys/src/9/mtx/trap.c /n/emeliedump/2001/1218/sys/src/9/mtx/trap.c
273,291c
	if(up && up->state == Running)
	if(anyhigher())
	if(up->preempted == 0)
	if(!active.exiting){
		up->preempted = 1;
		sched();
		splhi();
		up->preempted = 0;
		return;
	}
.
270,271c
	/* 
	 *  preemptive scheduling.  to limit stack depth,
	 *  make sure process has a chance to return from
	 *  the current interrupt before being preempted a
	 *  second time.
.
268a
	if(ctl->eoi)
		ctl->eoi(vno);
.
260,267c
	if(ctl->isr)
		ctl->isr(vno);
	for(v = ctl; v != nil; v = v->next){
		if(v->f)
			v->f(ureg, v->a);
.
255,258c
	if(vno > nelem(vctl) || (ctl = vctl[vno]) == 0) {
		panic("spurious intr %d", vno);
		return;
	}
.
244,253c
	vno = mpicintack();
	if(vno == 0) {			/* 8259, wired through MPIC vec 0 */
		vno = i8259intack();
		mpiceoi(0);
	}
.
242c
	int vno;
	Vctl *ctl, *v;
.
240c
intr(Ureg *ureg)
.
195,203d
186,187d
176d
150d
148d
130d
128d
125d
123d
120d
118d
115d
111,113c
	if(ur->status & MSR_RI == 0)
		print("double fault?: ecode = %d\n", ecode);

	switch(ecode) {
.
35a
static int
hwvecno(int irq, int tbdf)
{
	if(BUSTYPE(tbdf) == BusPCI) 	/* MPIC? */
		return irq;
	else
		return irq+VectorPIC;
}

void
intrenable(int irq, void (*f)(Ureg*, void*), void* a, int tbdf, char *name)
{
	int vno;
	Vctl *v;

	if(f == nil){
		print("intrenable: nil handler for %d, tbdf 0x%uX for %s\n",
			irq, tbdf, name);
		return;
	}

	v = xalloc(sizeof(Vctl));
	v->isintr = 1;
	v->irq = irq;
	v->tbdf = tbdf;
	v->f = f;
	v->a = a;
	strncpy(v->name, name, KNAMELEN-1);
	v->name[KNAMELEN-1] = 0;

	ilock(&vctllock);
	vno = hwintrenable(v);
	if(vno == -1){
		iunlock(&vctllock);
		print("intrenable: couldn't enable irq %d, tbdf 0x%uX for %s\n",
			irq, tbdf, v->name);
		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);
}

void
intrdisable(int irq, void (*f)(Ureg *, void *), void *a, int tbdf, char *name)
{
	Vctl **pv, *v;
	int vno;

	vno = hwvecno(irq, tbdf);
	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)
		hwintrdisable(v);
	iunlock(&vctllock);
	xfree(v);
}

.
34c
	irq = v->irq;
	if(BUSTYPE(v->tbdf) == BusPCI) {	/* MPIC? */
		if(irq > 15) {
			print("intrdisable: pci irq %d out of range\n", v->irq);
			return -1;
		}
		vec = irq;
		mpicdisable(vec);
	}
	else {
		if(irq > MaxIrqPIC) {
			print("intrdisable: irq %d out of range\n", v->irq);
			return -1;
		}
		vec = irq+VectorPIC;
		if(i8259disable(irq) == -1)
			return -1;
	}
	return vec;
}
.
29,32c
	int vec, irq;
.
27c
	irq = v->irq;
	if(BUSTYPE(v->tbdf) == BusPCI) {	/* MPIC? */
		if(irq > 15) {
			print("intrenable: pci irq %d out of range\n", v->irq);
			return -1;
		}
		vec = irq;
		mpicenable(vec, v);
	}
	else {
		if(irq > MaxIrqPIC) {
			print("intrenable: irq %d out of range\n", v->irq);
			return -1;
		}
		vec = irq+VectorPIC;
		if(i8259enable(v) == -1)
			return -1;
	}
	return vec;
}

static int
hwintrdisable(Vctl *v)
.
18,25c
	int vec, irq;
.
15,16c
static int
hwintrenable(Vctl *v)
.
12,13c
	i8259init();
	mpicenable(0, nil);	/* 8259 interrupts are routed through MPIC intr 0 */
}
.
10c
static Lock vctllock;
static Vctl *vctl[256];

void
hwintrinit(void)
.
## diffname mtx/trap.c 2002/0108
## diff -e /n/emeliedump/2001/1218/sys/src/9/mtx/trap.c /n/emeliedump/2002/0108/sys/src/9/mtx/trap.c
285c
			panic("fault: 0x%lux", addr);
.
233a
	case CISI:
		faultpower(ur, ur->pc, 1);
		break;
	case CDSI:
		dsisr = getdsisr();
		if(dsisr & BIT(6))
			faultpower(ur, getdar(), 0);
		else
			faultpower(ur, getdar(), 1);
		break;
.
213a
	ulong dsisr;
.
## diffname mtx/trap.c 2002/0109
## diff -e /n/emeliedump/2002/0108/sys/src/9/mtx/trap.c /n/emeliedump/2002/0109/sys/src/9/mtx/trap.c
350a
else print("non-pic %d\n", vno);
.
34a
print("add pic intr %d\n", irq);
.
26a
print("add PCI intr %d\n", irq);
.
## diffname mtx/trap.c 2002/0110
## diff -e /n/emeliedump/2002/0109/sys/src/9/mtx/trap.c /n/emeliedump/2002/0110/sys/src/9/mtx/trap.c
353d
36d
27d
## diffname mtx/trap.c 2002/0111
## diff -e /n/emeliedump/2002/0110/sys/src/9/mtx/trap.c /n/emeliedump/2002/0111/sys/src/9/mtx/trap.c
297a
dumpregs(ureg);
print("last ecode %x\n", lastecode);
.
274a
lastecode = ecode;
.
210a
static int lastecode;

.
## diffname mtx/trap.c 2002/0112
## diff -e /n/emeliedump/2002/0111/sys/src/9/mtx/trap.c /n/emeliedump/2002/0112/sys/src/9/mtx/trap.c
658a

.
657d
654,655c
	/* restoreureg must execute at high IPL */
	splhi();
	if(scallnr!=RFORK)
.
595,597d
593c
	int i, scallnr;
.
591c
	ulong sp;
.
584,586c
/* TODO: make this trap a separate asm entry point, like on other RISC architectures */
.
512a
	ureg->srr1 &= ~MSR_FP;
.
408a
void
fpoff(Proc *p)
{
	Ureg *ur;

	ur = p->dbgreg;
	ur->srr1 &= ~MSR_FP;
}

.
302d
282d
279,280c
	/* restoreureg must execute at high IPL */
	splhi();
	if(user)
.
277d
235a
		return;		/* syscall() calls notify itself, don't do it again */
	case CFPU:
		if(!user || up == nil) {
			dumpregs(ur);
			panic("floating point in kernel");
		}
		switch(up->fpstate){
		case FPinit:
			fprestore(&initfp);
			up->fpstate = FPactive;
			break;
		case FPinactive:
			fprestore(&up->fpsave);
			up->fpstate = FPactive;
			break;
		default:
			panic("fpstate");
		}
		ur->srr1 |= MSR_FP;
.
234a
		if(!user)
			panic("syscall in kernel: srr1 0x%4.4uX\n", ur->srr1);
.
211,212d
149d
146d
## diffname mtx/trap.c 2002/0114
## diff -e /n/emeliedump/2002/0112/sys/src/9/mtx/trap.c /n/emeliedump/2002/0114/sys/src/9/mtx/trap.c
232c
			panic("syscall in kernel: srr1 0x%4.4luX\n", ur->srr1);
.
## diffname mtx/trap.c 2002/0116
## diff -e /n/emeliedump/2002/0114/sys/src/9/mtx/trap.c /n/emeliedump/2002/0116/sys/src/9/mtx/trap.c
455c
	print("ktrace /kernel/path %.8lux %.8lux %.8lux\n", ureg->pc, ureg->sp, ureg->lr);
.
317d
## diffname mtx/trap.c 2002/0117
## diff -e /n/emeliedump/2002/0116/sys/src/9/mtx/trap.c /n/emeliedump/2002/0117/sys/src/9/mtx/trap.c
748a
print("notify: usp %lux\n", ur->usp);
.
722a
print("notify: old usp %lux\n", ur->usp);
.
318a
dumpregs(ureg);
.
## diffname mtx/trap.c 2002/0119
## diff -e /n/emeliedump/2002/0117/sys/src/9/mtx/trap.c /n/emeliedump/2002/0119/sys/src/9/mtx/trap.c
767a
print("noted %d\n", arg0);
.
677a
	if(up->fpstate == FPinactive)
		ureg->srr1 &= ~MSR_FP;
.
430c
	if(ur != nil)
		ur->srr1 &= ~MSR_FP;
.
297,298c
	if(user) {
		notify(ureg);
		if(up->fpstate == FPinactive)
			ureg->srr1 &= ~MSR_FP;
	}
.
289c
		dumpregs(ureg);
.
279c
		dumpregs(ureg);
.
269c
		else if(ureg->status & (1<<17))
.
267c
		else if(ureg->status & (1<<18))
.
265c
		if(ureg->status & (1<<19))
.
262c
			faultpower(ureg, getdar(), 1);
.
260c
			faultpower(ureg, getdar(), 0);
.
255c
		faultpower(ureg, ureg->pc, 1);
.
252c
		ureg->srr1 |= MSR_FP;
.
237c
			dumpregs(ureg);
.
232,233c
			panic("syscall in kernel: srr1 0x%4.4luX\n", ureg->srr1);
		syscall(ureg);
.
228c
		clockintr(ureg);
.
225c
		intr(ureg);
.
220c
	if(ureg->status & MSR_RI == 0)
.
217,218c
	ecode = (ureg->cause >> 8) & 0xff;
	user = (ureg->srr1 & MSR_PR) != 0;
	if(user)
		up->dbgreg = ureg;
.
213c
	int ecode, user;
.
210c
trap(Ureg *ureg)
.
## diffname mtx/trap.c 2002/0122
## diff -e /n/emeliedump/2002/0119/sys/src/9/mtx/trap.c /n/emeliedump/2002/0122/sys/src/9/mtx/trap.c
776d
487a
print("ur %lux\n", ur);
.
466a
//delay(1);
.
452c
static void
.
447,448c

	getpcsp((ulong*)&ureg.pc, (ulong*)&ureg.sp);
	ureg.lr = getcallerpc(&fn);
.
442a

static void
getpcsp(ulong *pc, ulong *sp)
{
	*pc = getcallerpc(&pc);
	*sp = (ulong)&pc-4;
}

.
324d
319a
			_dumpstack(ureg);
.
147a
static void _dumpstack(Ureg*);
.
146c
void	syscall(Ureg*);
.
## diffname mtx/trap.c 2002/0123
## diff -e /n/emeliedump/2002/0122/sys/src/9/mtx/trap.c /n/emeliedump/2002/0123/sys/src/9/mtx/trap.c
321c
//			_dumpstack(ureg);
.
## diffname mtx/trap.c 2002/0124
## diff -e /n/emeliedump/2002/0123/sys/src/9/mtx/trap.c /n/emeliedump/2002/0124/sys/src/9/mtx/trap.c
771d
744d
499d
496a

.
477d
473c
	for(; l < el; l += 4){
.
470d
468c
	l = (ulong)&l;
	if(up == 0){
		el = (ulong)m+BY2PG;
		sl = el-KSTACK;
	}
	else{
		sl = (ulong)up->kstack;
		el = sl + KSTACK;
	}
	if(l > el || l < sl){
		el = (ulong)m+BY2PG;
		sl = el-KSTACK;
	}
	if(l > el || l < sl)
.
465c
	ulong l, sl, el, v;
.
430,439d
321d
316d
## diffname mtx/trap.c 2002/0417
## diff -e /n/emeliedump/2002/0124/sys/src/9/mtx/trap.c /n/emeliedump/2002/0417/sys/src/9/mtx/trap.c
670c
		print("bad errstack [%uld]: %d extra\n", scallnr, up->nerrlab);
.
649c
		if(scallnr >= nsyscall || systab[scallnr] == nil){
.
641,642c
	up->scallnr = ureg->r3;
.
633c
	ulong sp, scallnr;
.
631d
629a
	int i;
.
## diffname mtx/trap.c 2002/0822
## diff -e /n/emeliedump/2002/0417/sys/src/9/mtx/trap.c /n/emeliedump/2002/0822/sys/src/9/mtx/trap.c
217d
## diffname mtx/trap.c 2003/0301
## diff -e /n/emeliedump/2002/0822/sys/src/9/mtx/trap.c /n/emeliedump/2003/0301/sys/src/9/mtx/trap.c
389,404c
	preempted();
.

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to [email protected].