## 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; inintr) 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<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; ikpfun)(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(); .