## diffname bitsy/trap.c 2000/0902 ## diff -e /dev/null /n/emeliedump/2000/0902/sys/src/9/bitsy/trap.c 0a #include "u.h" #include "../port/lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "io.h" #include "ureg.h" #include "../port/error.h" /* * called in sysfile.c */ void evenaddr(ulong addr) { if(addr & 3){ postnote(up, 1, "sys: odd address", NDebug); error(Ebadarg); } } void exception(void) { } /* Give enough context in the ureg to produce a kernel stack for * a sleeping process */ void setkernur(Ureg *ureg, Proc *p) { USED(ureg, p); } /* * return the userpc the last exception happened at */ ulong userpc(void) { return 0; } /* 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) { USED(ureg, pureg, uva, n); } /* * this is the body for all kproc's */ static void linkproc(void) { spllo(); up->kpfun(up->kparg); } /* * setup stack and initial PC for a new kernel proc. This is architecture * dependent because of the starting stack location */ 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; } /* * Craft a return frame which will cause the child to pop out of * the scheduler in user mode with the return register zero. Set * pc to point to a l.s return function. */ void forkchild(Proc *p, Ureg *ureg) { USED(p, ureg); } /* * setup stack, initial PC, and any arch dependent regs for an execing user proc. */ long execregs(ulong entry, ulong ssize, ulong nargs) { ulong *sp; Ureg *ureg; sp = (ulong*)(USTKTOP - ssize); *--sp = nargs; ureg = up->dbgreg; ureg->r13 = (ulong)sp; ureg->pc = entry; return USTKTOP-BY2WD; /* address of user-level clock */ } /* * dump the processor stack for this process */ void dumpstack(void) { } ulong dbgpc(Proc *p) { USED(p); return 0; } . ## diffname bitsy/trap.c 2000/0929 ## diff -e /n/emeliedump/2000/0902/sys/src/9/bitsy/trap.c /n/emeliedump/2000/0929/sys/src/9/bitsy/trap.c 23c trapinit(void) { /* * exceptionvectors points to a prototype in l.s of the * exception vectors that save the regs and then call * trap(). The actual vectorrs are double mapped * to 0xffff0000 and to KZERO. We write them via * KZERO since a data access to them will cause an * exception. */ memmove((void*)KZERO, exceptionvectors, 2*4*8); wbflush(); } /* * here on all exceptions with registers saved */ void trap(Ureg *ureg) . 21a /* * set up for exceptioons */ . ## diffname bitsy/trap.c 2000/1001 ## diff -e /n/emeliedump/2000/0929/sys/src/9/bitsy/trap.c /n/emeliedump/2000/1001/sys/src/9/bitsy/trap.c 45a switch(ureg->type){ case PsrMfiq: /* fast interrupt */ panic("fiq can't happen"); break; case PsrMabt: /* fault */ case PsrMabt+1: /* fault */ panic("faults not implemented"); break; case PsrMund: /* undefined instruction */ panic("undefined instruction"); break; case PsrMirq: /* device interrupt */ break; case PsrMsvc: /* system call */ break; } . 40a * enable an interrupt and attach a function to i */ void intrenable(int irq, void (*f)(Ureg*, void*), void* a, char *name) { int vno; Vctl *v; v = xalloc(sizeof(Vctl)); v->irq = irq; v->f = f; v->a = a; strncpy(v->name, name, NAMELEN-1); v->name[NAMELEN-1] = 0; lock(&vctllock); v->next = vctl[irq]; vctl[irq] = v; unlock(&vctllock); } /* . 37a /* map in interrupt registers */ intrregs = mapspecial(INTRREGS, sizeof(*intrregs)); /* make all interrupts irq and disable all interrupts */ intrregs->iclr = 0; intrregs->icmr = 0; . 21a struct Intrregs *intrregs; typedef struct Vctl { Vctl* next; /* handlers on this vector */ char name[NAMELEN]; /* of driver */ int irq; void (*f)(Ureg*, void*); /* handler to call */ void* a; /* argument to call it with */ } Vctl; static Lock vctllock; static Vctl *vctl[32]; . 16,20c ulong icip; /* pending IRQs */ ulong icmr; /* IRQ mask */ ulong iclr; /* IRQ if bit == 0, FRIQ if 1 */ ulong iccr; /* control register */ ulong icfp; /* pending FIQs */ ulong dummy1[3] ulong icpr; /* pending interrupts */ }; . 10,14c struct Intrregs . ## diffname bitsy/trap.c 2000/1002 ## diff -e /n/emeliedump/2000/1001/sys/src/9/bitsy/trap.c /n/emeliedump/2000/1002/sys/src/9/bitsy/trap.c 202,203c Ureg *ureg; ureg = p->dbgreg; if(ureg == 0) return 0; return ureg->pc; } /* * called in sysfile.c */ void evenaddr(ulong addr) { if(addr & 3){ postnote(up, 1, "sys: odd address", NDebug); error(Ebadarg); } } /* * here on a hardware reset */ void reset(void) { . 198c /* * pc output by ps */ . 169c Ureg *cureg; p->sched.sp = (ulong)p->kstack+KSTACK-sizeof(Ureg); p->sched.pc = (ulong)forkret; cureg = (Ureg*)(p->sched.sp+2*BY2WD); memmove(cureg, ureg, sizeof(Ureg)); /* syscall returns 0 for child */ cureg->r0 = 0; /* Things from bottom of syscall which were never executed */ p->psstate = 0; p->insyscall = 0; . 138,139c static void . 123c Ureg *ureg; ureg = (Ureg*)up->dbgreg; return ureg->pc; . 114c ureg->pc = p->sched.pc; ureg->sp = p->sched.sp+4; . 107a /* * Call user, if necessary, with note. * Pass user the Ureg struct and the note on his stack. */ int notify(Ureg* ureg) { 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", ureg->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 = ureg->sp; sp -= sizeof(Ureg); if(!okaddr((ulong)up->notify, 1, 0) || !okaddr(sp-ERRLEN-4*BY2WD, sizeof(Ureg)+ERRLEN+4*BY2WD, 1)){ pprint("suicide: bad address in notify\n"); qunlock(&up->debug); pexit("Suicide", 0); } up->ureg = (void*)sp; memmove((Ureg*)sp, ureg, 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 */ *(ulong*)(sp+1*BY2WD) = (ulong)up->ureg; /* arg 1 is ureg* */ *(ulong*)(sp+0*BY2WD) = 0; /* arg 0 is pc */ ureg->sp = sp; ureg->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; } . 104a case NSAVE: if(!okaddr(nureg->pc, BY2WD, 0) || !okaddr(nureg->sp, BY2WD, 0)){ qunlock(&up->debug); pprint("suicide: trap in noted\n"); 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){ qunlock(&up->debug); pprint("suicide: %s\n", up->lastnote.msg); } else qunlock(&up->debug); pexit(up->lastnote.msg, up->lastnote.flag!=NDebug); . 103c } } /* * system calls */ #include "../port/systab.h" /* * Syscall is called directly from assembler without going through trap(). */ void syscall(Ureg* ureg) { ulong sp; long ret; int i, scallnr; if((ureg->psr & PsrMask) != PsrMusr) panic("syscall: cs 0x%4.4uX\n", ureg->psr); m->syscall++; up->insyscall = 1; up->pc = ureg->pc; up->dbgreg = ureg; scallnr = ureg->r0; up->scallnr = scallnr; spllo(); sp = ureg->sp; 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->r0 = ret; if(scallnr == NOTED) noted(ureg, *(ulong*)(sp+BY2WD)); if(scallnr != RFORK && (up->procctl || up->nnote)){ splhi(); notify(ureg); } } /* * 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); } /* don't let user change system flags */ nureg->psr = (ureg->psr & ~(PsrMask|PsrDfiq|PsrDirq)) | (nureg->psr & (PsrMask|PsrDfiq|PsrDirq)); memmove(ureg, nureg, sizeof(Ureg)); switch(arg0){ case NCONT: case NRSTR: if(!okaddr(nureg->pc, 1, 0) || !okaddr(nureg->sp, BY2WD, 0)){ qunlock(&up->debug); pprint("suicide: trap in noted\n"); pexit("Suicide", 0); } up->ureg = (Ureg*)(*(ulong*)(oureg-BY2WD)); qunlock(&up->debug); . 95d 91,92c default: panic("unknown trap"); . 85c * here on all exceptions other than syscall (SWI) . 80a intrregs->icmr |= 1<icip){ iprint("irq: %d\n", i); for(v = vctl[i]; v != nil; v = v->next) v->f(ureg, v->a); } . 89a int i; Vctl *v; iprint("trap %lux pc %lux psr %lux\n", ureg->type, ureg->pc, ureg->psr); . ## diffname bitsy/trap.c 2000/1007 ## diff -e /n/emeliedump/2000/1006/sys/src/9/bitsy/trap.c /n/emeliedump/2000/1007/sys/src/9/bitsy/trap.c 60a void trapdump(char *tag) { iprint("%s: icip %lux icmr %lux iclr %lux iccr %lux icfp %lux\n", tag, intrregs->icip, intrregs->icmr, intrregs->iclr, intrregs->iccr, intrregs->icfp); } . 53a /* use exception vectors at 0xFFFF0000 */ mappedIvecEnable(); /* set up the stacks for the interrupt modes */ setr13(PsrMfiq, m->sfiq); setr13(PsrMirq, m->sirq); setr13(PsrMabt, m->sabt); setr13(PsrMund, m->sund); . 43,51c /* set up the exception vectors */ vpage0 = (Vpage0*)EVECTORS; memmove(vpage0->vectors, vectors, sizeof(vpage0->vectors)); memmove(vpage0->vtable, vtable, sizeof(vpage0->vtable)); memset(vpage0->hole, 0, sizeof(vpage0->hole)); . 37a * Layout at virtual address 0. */ typedef struct Vpage0 { void (*vectors[8])(void); ulong vtable[8]; ulong hole[16]; } Vpage0; Vpage0 *vpage0; /* . 36a . ## diffname bitsy/trap.c 2000/1012 ## diff -e /n/emeliedump/2000/1007/sys/src/9/bitsy/trap.c /n/emeliedump/2000/1012/sys/src/9/bitsy/trap.c 138a } if(user && (up->procctl || up->nnote)){ splhi(); notify(ureg); . 127a case PsrMabt+1: /* data fault */ pc = ureg->pc - 8; va = getfar(); switch(getfsr() & 0xf){ case 0x0: panic("vector exception at %lux\n", pc); break; case 0x1: case 0x3: if(user){ snprint(buf, sizeof(buf), "sys: alignment: pc 0x%lux va 0x%lux\n", pc, va); postnote(up, 1, buf, NDebug); } else panic("kernel alignment: pc 0x%lux va 0x%lux", pc, va); break; case 0x2: panic("terminal exception at %lux\n", pc); break; case 0x4: case 0x6: case 0x8: case 0xa: case 0xc: case 0xe: panic("external abort at %lux\n", pc); break; case 0x5: case 0x7: /* translation fault, i.e., no pte entry */ faultarm(ureg, va, user, 0); break; case 0x9: case 0xb: /* domain fault, accessing something we shouldn't */ if(user){ sprint(buf, "sys: access violation: pc 0x%lux va 0x%lux\n", pc, va); postnote(up, 1, buf, NDebug); } else panic("kernel access violation: pc 0x%lux va 0x%lux\n", pc, va); break; case 0xd: case 0xf: /* permission error, copy on write or real permission error */ faultarm(ureg, va, user, 1); break; } break; . 125,126c case PsrMabt: /* prefetch fault */ iprint("prefetch abort at %lux\n", ureg->pc-4); faultarm(ureg, ureg->pc - 4, user, 1); . 119,120c user = (ureg->psr & PsrMask) == PsrMusr; . 117a int user; ulong pc, va; char buf[ERRLEN]; . 110a * called by trap to handle access faults */ static void faultarm(Ureg *ureg, ulong va, int user, int read) { int n, insyscall; char buf[ERRLEN]; insyscall = up->insyscall; up->insyscall = 1; n = fault(va, read); iprint("fault returns %d\n", n); if(n < 0){ if(!user){ dumpregs(ureg); panic("fault: 0x%lux\n", va); } sprint(buf, "sys: trap: fault %s va=0x%lux", read? "read" : "write", va); postnote(up, 1, buf, NDebug); } up->insyscall = insyscall; } /* . 86a void dumpregs(Ureg *ur) { iprint("r0 0x%.8lux r1 0x%.8lux r3 0x%.8lux r3 0x%.8lux\n", ur->r0, ur->r1, ur->r2, ur->r3); iprint("r4 0x%.8lux r5 0x%.8lux r6 0x%.8lux r7 0x%.8lux\n", ur->r4, ur->r5, ur->r6, ur->r7); iprint("r8 0x%.8lux r9 0x%.8lux r10 0x%.8lux r11 0x%.8lux\n", ur->r8, ur->r9, ur->r10, ur->r11); iprint("r12 0x%.8lux r13 0x%.8lux r14 0x%.8lux\n", ur->r12, ur->r13, ur->r14); iprint("type %.8lux psr %.8lux pc %.8lux\n", ur->type, ur->psr, ur->pc); } . ## diffname bitsy/trap.c 2000/1013 ## diff -e /n/emeliedump/2000/1012/sys/src/9/bitsy/trap.c /n/emeliedump/2000/1013/sys/src/9/bitsy/trap.c 288c qpanic("error stack"); . 252c qpanic("syscall: cs 0x%4.4uX\n", ureg->psr); . 218c qpanic("undefined instruction"); . 208c qpanic("kernel access violation: pc 0x%lux va 0x%lux\n", pc, va); . 194c qpanic("external abort at %lux\n", pc); . 186c qpanic("terminal exception at %lux\n", pc); . 183c qpanic("kernel alignment: pc 0x%lux va 0x%lux", pc, va); . 174c qpanic("vector exception at %lux\n", pc); . 171a iprint("data fault pc 0x%lux va 0x%lux fsr 0x%lux\n", pc, va, getfsr()); . 166c iprint("prefetch abort at 0x%lux\n", ureg->pc-4); . 163c qpanic("unknown trap"); . 139c qpanic("fault: 0x%lux\n", va); . 90c iprint("r0 0x%.8lux r1 0x%.8lux r2 0x%.8lux r3 0x%.8lux\n", . ## diffname bitsy/trap.c 2000/1014 ## diff -e /n/emeliedump/2000/1013/sys/src/9/bitsy/trap.c /n/emeliedump/2000/1014/sys/src/9/bitsy/trap.c 281a iprint("syscall retuns %d\n", ret); . 280a iprint("before syscall\n"); . 251a iprint("syscall in\n"); dumpregs(ureg); . 224d 209c qpanic("kernel access violation: pc 0x%lux va 0x%lux\n", ureg->pc, va); . 206c sprint(buf, "sys: access violation: pc 0x%lux va 0x%lux\n", ureg->pc, va); . 195c qpanic("external abort at %lux\n", ureg->pc); . 187c qpanic("terminal exception at %lux\n", ureg->pc); . 184c qpanic("kernel alignment: pc 0x%lux va 0x%lux", ureg->pc, va); . 181c ureg->pc, va); . 175c qpanic("vector exception at %lux\n", ureg->pc); . 172c iprint("data fault pc 0x%lux va 0x%lux fsr 0x%lux\n", ureg->pc, va, getfsr()); . 170d 166,167c iprint("prefetch abort at 0x%lux\n", ureg->pc); faultarm(ureg, ureg->pc, user, 1); . 160a /* * All interrupts/exceptions should be resumed at ureg->pc-4, * except for Data Abort which resumes at ureg->pc-8. */ if(ureg->type == (PsrMabt+1)) ureg->pc -= 8; else ureg->pc -= 4; . 157c ulong va; . 133a peekmmu(va); . ## diffname bitsy/trap.c 2000/1015 ## diff -e /n/emeliedump/2000/1014/sys/src/9/bitsy/trap.c /n/emeliedump/2000/1015/sys/src/9/bitsy/trap.c 302c panic("error stack"); . 294d 292d 264c panic("syscall: cs 0x%4.4uX\n", ureg->psr); . 261,262d 236a } . 235a } if(!found) iprint("interrupt %d with no handler\n", i); . 234c for(v = vctl[i]; v != nil; v = v->next){ found = 1; . 232c for(i = 0; i < 32; i++){ found = 0; . 229c panic("undefined instruction"); . 224c faultarm(ureg, va, user, 0); . 219c panic("kernel access violation: pc 0x%lux va 0x%lux\n", ureg->pc, va); . 210c faultarm(ureg, va, user, 1); . 205c panic("external abort at %lux\n", ureg->pc); . 197c panic("terminal exception at %lux\n", ureg->pc); . 194c panic("kernel alignment: pc 0x%lux va 0x%lux", ureg->pc, va); . 185c panic("vector exception at %lux\n", ureg->pc); . 182c //iprint("data fault pc 0x%lux(0x%lux) va 0x%lux fsr 0x%lux\n", ureg->pc, *(ulong*)(ureg->pc), va, getfsr()); . 177c //iprint("prefetch abort at 0x%lux\n", ureg->pc); . 174c panic("unknown trap"); . 155c int i, found; . 141a dumpregs(ureg); . 140c panic("fault: 0x%lux\n", va); . 136c //iprint("fault returns %d\n", n); . 134c //peekmmu(va); . ## diffname bitsy/trap.c 2000/1016 ## diff -e /n/emeliedump/2000/1015/sys/src/9/bitsy/trap.c /n/emeliedump/2000/1016/sys/src/9/bitsy/trap.c 573a print("execregs pc 0x%lux sp 0x%lux\n", ureg->pc, ureg->r13); . 571a memset(ureg, 0, 15*sizeof(ulong)); . 225c faultarm(ureg, va, user, inst & Lbit); . 211c faultarm(ureg, va, user, inst & Lbit); . 183c inst = *(ulong*)(ureg->pc); print("%d: data fault pc 0x%lux(0x%lux) va 0x%lux fsr 0x%lux\n", m->lastpid, ureg->pc, inst, va, getfsr()); . 178c print("%d: prefetch abort at 0x%lux\n", m->lastpid, ureg->pc); . 155a ulong inst; . 149a /* all Pabt+1 faults are caused by loads or stores. The Lbit of * the instruction distinquishes between them. */ enum { Lbit = 1<<20, /* load instruction */ }; . ## diffname bitsy/trap.c 2000/1018 ## diff -e /n/emeliedump/2000/1016/sys/src/9/bitsy/trap.c /n/emeliedump/2000/1018/sys/src/9/bitsy/trap.c 585c //print("%lud: EXECREGS pc 0x%lux sp 0x%lux\n", up->pid, ureg->pc, ureg->r13); . 558c cureg = (Ureg*)(p->sched.sp); . 554a //print("%lud setting up for forking child %lud\n", up->pid, p->pid); . 235c faultarm(ureg, va, user, !writetomem(inst)); . 230c panic("kernel access violation: pc 0x%lux va 0x%lux\n", ureg->pc, va); . 227c sprint(buf, "sys: access violation: pc 0x%lux va 0x%lux\n", ureg->pc, va); . 221c faultarm(ureg, va, user, !writetomem(inst)); . 193d 187d 181a if((user && (ureg->r13 & 0xf0000000)) || (ureg->psr & 0x10) != 0x10){ warnregs(ureg, "wierd ureg"); panic("bad ureg\n"); } . 157a /* loads and stores are distinguished by bit 20 */ if(inst & (1<<20)) return 0; return 1; } . 155,156c /* swap always write memory */ if((inst & 0x0FC00000) == 0x01000000) return 1; . 153c int writetomem(ulong inst) . 150,151c /* * returns 1 if the instruction writes memory, 0 otherwise . 142,144c // warnregs(ureg, "user fault"); sprint(buf, "sys: trap: fault %s va=0x%lux", read ? "read" : "write", va); . 139,140c warnregs(ureg, "kernel fault"); panic("fault: kernel accessing 0x%lux\n", va); . 136d 134d 98c seprint(p, e, "type %.8lux psr %.8lux pc %.8lux\n", ur->type, ur->psr, ur->pc); print("%s", buf); . 96c p = seprint(p, e, "r12 0x%.8lux r13 0x%.8lux r14 0x%.8lux\n", . 94c p = seprint(p, e, "r8 0x%.8lux r9 0x%.8lux r10 0x%.8lux r11 0x%.8lux\n", . 92c p = seprint(p, e, "r4 0x%.8lux r5 0x%.8lux r6 0x%.8lux r7 0x%.8lux\n", . 90c char buf[512]; char *e = buf+sizeof(buf); char *p; p = seprint(buf, e, "%s:\n", tag); p = seprint(p, e, "r0 0x%.8lux r1 0x%.8lux r2 0x%.8lux r3 0x%.8lux\n", . 88c warnregs(Ureg *ur, char *tag) . 82c print("%s: icip %lux icmr %lux iclr %lux iccr %lux icfp %lux\n", . ## diffname bitsy/trap.c 2000/1019 ## diff -e /n/emeliedump/2000/1018/sys/src/9/bitsy/trap.c /n/emeliedump/2000/1019/sys/src/9/bitsy/trap.c 275a out: . 261,273d 196,198c if(ureg->type == PsrMirq){ found = 0; va = intrregs->icip; for(v = vctl; v != nil; v = v->next){ if(v->irqbit & va){ v->f(ureg, v->a); found = 1; } } if(!found) print("unknown interrupt: %lux\n", intrregs->icip); goto out; . 179c int found; . 124,126c v->next = vctl; vctl = v; intrregs->icmr |= v->irqbit; . 117a v->irqbit = 1<pc); postnote(up, 1, buf, NDebug); }else{ warnregs(ureg, "undefined instruction"); panic("undefined instruction"); } . 104,105d 102c seprint(p, e, "r12 0x%.8lux r13 0x%.8lux r14 0x%.8lux\n", . 95a p = seprint(p, e, "type %.8lux psr %.8lux pc %.8lux\n", ur->type, ur->psr, ur->pc); . 91c char buf[1024]; . ## diffname bitsy/trap.c 2000/1026 ## diff -e /n/emeliedump/2000/1025/sys/src/9/bitsy/trap.c /n/emeliedump/2000/1026/sys/src/9/bitsy/trap.c 277a #endif . 271c sprint(buf, "undefined instruction: pc 0x%lux\n", . 269a #ifdef NOTDEF /* Inferno break handling, something for us? [SJM] */ if(*(ulong*)ureg->pc == BREAK && breakhandler) { int s; Proc *p; p = up; /* if (!waslo(ureg->psr) || (ureg->pc >= (ulong)splhi && ureg->pc < (ulong)islo)) p = 0; */ s = breakhandler(ureg, p); if(s == BrkSched) { c.callsched = 1; sched(); } else if(s == BrkNoSched) { c.callsched = 0; if(up) up->dbgreg = 0; return; } break; } /* End of Inferno break handling [SJM] */ #endif /* start of Inferno code [SJM] */ spllo(); if (waserror()) { warnregs(ureg, "floating point error"); panic("floating point error"); } if (!fpiarm(ureg)) { warnregs(ureg, "illegal instruction"); panic("illegal instruction"); } poperror(); /* end of Inferno code [SJM] */ #ifdef NOTDEF /* We'll see what we do with this later [SJM] */ . 38d 19d ## diffname bitsy/trap.c 2000/1027 ## diff -e /n/emeliedump/2000/1026/sys/src/9/bitsy/trap.c /n/emeliedump/2000/1027/sys/src/9/bitsy/trap.c 313c poperror(); /* end of Inferno code [SJM] */ . 297,308c if (user) { if (!fpiarm(ureg)) { sprint(buf, "undefined instruction: pc 0x%lux\n", ureg->pc); postnote(up, 1, buf, NDebug); } . 268,290d ## diffname bitsy/trap.c 2000/1028 ## diff -e /n/emeliedump/2000/1027/sys/src/9/bitsy/trap.c /n/emeliedump/2000/1028/sys/src/9/bitsy/trap.c 283d 275c x = spllo(); rv = fpiarm(ureg); splx(x); if (rv == 0) { . 269,273d 181c int user, x, rv; . ## diffname bitsy/trap.c 2000/1031 ## diff -e /n/emeliedump/2000/1028/sys/src/9/bitsy/trap.c /n/emeliedump/2000/1031/sys/src/9/bitsy/trap.c 624a callwithureg(_dumpstack); . 622a callwithureg(void (*fn)(Ureg*)) { Ureg ureg; ureg.pc = getcallerpc(&fn); ureg.sp = (ulong)&fn; fn(&ureg); } static void _dumpstack(Ureg *ureg) { ulong l, v, i; ulong *p; extern ulong etext; if(up == 0) return; print("ktrace /kernel/path %.8lux %.8lux\n", ureg->pc, ureg->sp); i = 0; for(l=(ulong)&l; l<(ulong)(up->kstack+KSTACK); l+=4){ v = *(ulong*)l; if(KTZERO < v && v < (ulong)&etext && (v&3)==0){ v -= 4; p = (ulong*)v; if((*p & 0x0f000000) == 0x0b000000) print("%.8lux=%.8lux ", l, v); } if(i == 4){ i = 0; print("\n"); } } if(i) print("\n"); } void . 620c * Fill in enough of Ureg to get a stack trace, and call a function. * Used by debugging interface rdb. . 364d 361,362c splhi(); if(scallnr != RFORK && (up->procctl || up->nnote)) . 289d 286,287c splhi(); if(user && (up->procctl || up->nnote)) . 94c p = seprint(p, e, "type 0x%.8lux psr 0x%.8lux pc 0x%.8lux\n", . ## diffname bitsy/trap.c 2000/1101 ## diff -e /n/emeliedump/2000/1031/sys/src/9/bitsy/trap.c /n/emeliedump/2000/1101/sys/src/9/bitsy/trap.c 648a i++; } . 647c if((*p & 0x0f000000) == 0x0b000000){ . ## diffname bitsy/trap.c 2000/1121 ## diff -e /n/emeliedump/2000/1101/sys/src/9/bitsy/trap.c /n/emeliedump/2000/1121/sys/src/9/bitsy/trap.c 242c panic("external abort 0x%ux pc 0x%lux addr 0x%lux\n", fsr, ureg->pc, va); . 220c fsr = getfsr() & 0xf; switch(fsr){ . 182c ulong va, fsr; . ## diffname bitsy/trap.c 2000/1122 ## diff -e /n/emeliedump/2000/1121/sys/src/9/bitsy/trap.c /n/emeliedump/2000/1122/sys/src/9/bitsy/trap.c 198a /* clear any gpio edge interrupt */ gpioregs->irqbit = va & 0xFFF; . 130a * enable an interrupt on gpio line. edge is encoded as follows */ void gpiointrenable(ulong bit, int edge, void (*f)(Ureg*, void*), void* a, char *name) { int irq; /* figure out which interrupt */ for(irq = 0; irq < 28; irq++) if((1<= 28) panic("gpiointrenable %lux", bit); if(irq > 11) irq = 11; /* it had better be input */ if(bit & gpioregs->direction) panic(""gpiointrenable %lux of output pin", bit); /* set edge register */ switch(edge){ case GPIOboth: gpioregs->rising |= bit; gpioregs->falling |= bit; break; case GPIOfalling: gpioregs->falling |= bit; break; case GPIOrising: gpioregs->rising |= bit; break; } intrenable(irq, f, a, name); } /* . ## diffname bitsy/trap.c 2000/1125 ## diff -e /n/emeliedump/2000/1122/sys/src/9/bitsy/trap.c /n/emeliedump/2000/1125/sys/src/9/bitsy/trap.c 149c panic("gpiointrenable %lux of output pin", bit); . ## diffname bitsy/trap.c 2000/1128 ## diff -e /n/emeliedump/2000/1125/sys/src/9/bitsy/trap.c /n/emeliedump/2000/1128/sys/src/9/bitsy/trap.c 239c gpioregs->edgestatus = va & 0xFFF; . ## diffname bitsy/trap.c 2000/1130 ## diff -e /n/emeliedump/2000/1128/sys/src/9/bitsy/trap.c /n/emeliedump/2000/1130/sys/src/9/bitsy/trap.c 331a } /* * here on irq's */ static void irq(Ureg *ur) { ulong va; int i; Vctl *v; va = intrregs->icip; for(i = 0; i < 32; i++){ if(((1<next){ v->f(ur, v->a); va &= ~(1<edgestatus; gpioregs->edgestatus = va; iprint("gpio intr %lux\n", va); for(i = 0; i < 27; i++){ if(((1<next){ v->f(ur, v->a); va &= ~(1<rising |= mask; . 158c gpioregs->falling |= mask; . 154,155c gpioregs->rising |= mask; gpioregs->falling |= mask; . 151c /* create a second level vctl for the gpio edge interrupt */ v = xalloc(sizeof(Vctl)); v->f = f; v->a = a; strncpy(v->name, name, NAMELEN-1); v->name[NAMELEN-1] = 0; lock(&vctllock); v->next = gpiovctl[bit]; gpiovctl[bit] = v; unlock(&vctllock); /* set edge register to enable interrupt */ . 147,149c /* the pin had better be configured as input */ if((1<direction) panic("gpiointrenable of output pin %d", bit); . 142,144c irq = bit; if(bit >= nelem(gpiovctl) || bit < 0) panic("gpiointrenable"); if(bit > 11) . 138,140c /* figure out which bit */ for(bit = 0; bit < 32; bit++) if((1<next = vctl[irq]; vctl[irq] = v; intrregs->icmr |= 1<= nelem(vctl) || irq < 0) panic("intrenable"); . 59a /* Set the doze function pointer to the moved _doze() routine */ doze = (void(*)(void))vpage0->doze; . 58c /* Move the twelve instructions of doze() to a cache-line boundary: */ memmove(vpage0->doze, _doze, 12*sizeof(long)); . 47a void (*doze)(void); static void irq(Ureg*); static void gpiointr(Ureg*, void*); . 44c /* Doze goes here because it needs to be on a cache-line boundary */ ulong doze[16]; . 34,35c static Lock vctllock; static Vctl *vctl[32]; static Vctl *gpiovctl[27]; static int gpioirqref[12]; . 27,29d 25d ## diffname bitsy/trap.c 2000/1205 ## diff -e /n/emeliedump/2000/1130/sys/src/9/bitsy/trap.c /n/emeliedump/2000/1205/sys/src/9/bitsy/trap.c 794,802d 379,380d 191c irqenable(irq, gpiointr, nil, "gpio edge"); . 189a /* point the irq to the gpio interrupt handler */ . 186c gpioregs->rising |= 1<falling |= 1<rising |= 1<falling |= 1<next = gpiovctl[which]; gpiovctl[which] = v; . 161,162c if((1<direction) panic("gpiointrenable of output pin %d", which); . 157c if(which > 11) . 154,155c /* from here down, it must be a GPIO edge interrupt */ irq = which; if(which >= nelem(gpiovctl) || which < 0) . 149,152c if(type == IRQ){ irqenable(which, f, a, name); return; } . 146c int irq; . 144c intrenable(int type, int which, IntrHandler *f, void* a, char *name) . 141c * enable an interrupt . 120c irqenable(int irq, IntrHandler *f, void* a, char *name) . 117c * enable an irq interrupt . ## diffname bitsy/trap.c 2000/1206 ## diff -e /n/emeliedump/2000/1205/sys/src/9/bitsy/trap.c /n/emeliedump/2000/1206/sys/src/9/bitsy/trap.c 409c panic("syscall: pc 0x%lux r14 0x%lux cs 0x%ux\n", ureg->pc, ureg->r14, ureg->psr); . ## diffname bitsy/trap.c 2000/1207 ## diff -e /n/emeliedump/2000/1206/sys/src/9/bitsy/trap.c /n/emeliedump/2000/1207/sys/src/9/bitsy/trap.c 742c print("ktrace /kernel/path %.8lux %.8lux %.8lux\n", ureg->pc, ureg->sp, ureg->r14); . 625a ureg->r14 = (ulong)sched; . 248a if(up != nil) rem = ((char*)ureg)-up->kstack; else rem = ((char*)ureg)-((char*)(MACHADDR+sizeof(Mach))); if(rem < 256) panic("trap %d bytes remaining", rem); . 247a int rem; . 84a /* turn off all gpio interrupts */ gpioregs->rising = 0; gpioregs->falling = 0; gpioregs->edgestatus = gpioregs->edgestatus; . ## diffname bitsy/trap.c 2001/0325 ## diff -e /n/emeliedump/2000/1207/sys/src/9/bitsy/trap.c /n/emeliedump/2001/0325/sys/src/9/bitsy/trap.c 89a /* allow all enabled interrupts to take processor out of sleep mode */ intrregs->iccr = 0; . 66,68d 63,64c /* relocate the doze routine to a cache line boundary in cached mem */ doze = xspanalloc(12*sizeof(long), 16, 0); memmove(doze, _doze, 12*sizeof(long)); . 46a /* * An cached line for the doze code */ . 41,43d ## diffname bitsy/trap.c 2001/0529 ## diff -e /n/emeliedump/2001/0325/sys/src/9/bitsy/trap.c /n/emeliedump/2001/0529/sys/src/9/bitsy/trap.c 614,615c sp -= BY2WD+ERRMAX; memmove((char*)sp, up->note[0].msg, ERRMAX); . 604c || !okaddr(sp-ERRMAX-4*BY2WD, sizeof(Ureg)+ERRMAX+4*BY2WD, 1)){ . 578,579c if(l > ERRMAX-15) /* " pc=0x12345678\0" */ l = ERRMAX-15; . 534c sp = oureg-4*BY2WD-ERRMAX; . 253c char buf[ERRMAX]; . 209c char buf[ERRMAX]; . 175,176c v->name = xalloc(strlen(name)+1); strcpy(v->name, name); . 136,137c v->name = xalloc(strlen(name)+1); strcpy(v->name, name); . 25c char *name; /* of driver, xallocated */ . ## diffname bitsy/trap.c 2001/0618 ## diff -e /n/emeliedump/2001/0529/sys/src/9/bitsy/trap.c /n/emeliedump/2001/0618/sys/src/9/bitsy/trap.c 755a } . 754c if(up == 0){ print("no current proc\n"); . 53c * set up for exceptions . 51a /* recover state after power suspend * NB: to help debugging bad suspend code, * I changed some prints below to iprints, * to avoid deadlocks when a panic is being * issued during the suspend/resume handler. */ void trapresume(void) { vpage0 = (Vpage0*)EVECTORS; memmove(vpage0->vectors, vectors, sizeof(vpage0->vectors)); memmove(vpage0->vtable, vtable, sizeof(vpage0->vtable)); wbflush(); mappedIvecEnable(); } . 21,22d 10,19c Intrregs *intrregs; . ## diffname bitsy/trap.c 2001/0620 ## diff -e /n/emeliedump/2001/0618/sys/src/9/bitsy/trap.c /n/emeliedump/2001/0620/sys/src/9/bitsy/trap.c 782c iprint("\n"); . 778c iprint("\n"); . 772c iprint("%.8lux=%.8lux ", l, v); . 760c iprint("no current proc\n"); . 428a } . 427c if((ureg->psr & PsrMask) != PsrMusr) { . 354d 342a /* look for floating point instructions to interpret */ . 341d 265,266c if(rem < 256) { dumpstack(); panic("trap %d bytes remaining, up = 0x%lux, ureg = 0x%lux, at pc 0x%lux", rem, up, ureg, ureg->pc); } . ## diffname bitsy/trap.c 2001/0621 ## diff -e /n/emeliedump/2001/0620/sys/src/9/bitsy/trap.c /n/emeliedump/2001/0621/sys/src/9/bitsy/trap.c 767c iprint("ktrace /kernel/path %.8lux %.8lux %.8lux\n", ureg->pc, ureg->sp, ureg->r14); . 124c iprint("%s", buf); . 101c iprint("%s: icip %lux icmr %lux iclr %lux iccr %lux icfp %lux\n", . ## diffname bitsy/trap.c 2001/0813 ## diff -e /n/emeliedump/2001/0621/sys/src/9/bitsy/trap.c /n/emeliedump/2001/0813/sys/src/9/bitsy/trap.c 215a if (up == nil) { warnregs(ureg, "kernel fault"); panic("fault: nil up in faultarm, accessing 0x%lux\n", va); } . ## diffname bitsy/trap.c 2001/0822 ## diff -e /n/emeliedump/2001/0813/sys/src/9/bitsy/trap.c /n/emeliedump/2001/0822/sys/src/9/bitsy/trap.c 464a }else{ /* failure: save the error buffer for errstr */ kstrcpy(up->syserror, up->error, sizeof up->syserror); . ## diffname bitsy/trap.c 2001/0924 ## diff -e /n/emeliedump/2001/0822/sys/src/9/bitsy/trap.c /n/emeliedump/2001/0924/sys/src/9/bitsy/trap.c 467c e = up->syserrstr; up->syserrstr = up->errstr; up->errstr = e; . 428a char *e; . ## diffname bitsy/trap.c 2002/0114 ## diff -e /n/emeliedump/2001/0924/sys/src/9/bitsy/trap.c /n/emeliedump/2002/0114/sys/src/9/bitsy/trap.c 435c panic("syscall: pc 0x%lux r14 0x%lux cs 0x%lux\n", ureg->pc, ureg->r14, ureg->psr); . 322c panic("external abort 0x%lux pc 0x%lux addr 0x%lux\n", fsr, ureg->pc, va); . ## diffname bitsy/trap.c 2002/0430 ## diff -e /n/emeliedump/2002/0114/sys/src/9/bitsy/trap.c /n/emeliedump/2002/0430/sys/src/9/bitsy/trap.c 70a hibernate = xspanalloc(8*sizeof(long), 16, 0); memmove(hibernate, _hibernate, 8*sizeof(long)); . 68c /* relocate the doze and hibernate routines * to a cache line boundary in cached mem */ . 36a void (*hibernate)(void); . 34c * A cached line for the doze and hibernate code . ## diffname bitsy/trap.c 2002/0518 ## diff -e /n/emeliedump/2002/0430/sys/src/9/bitsy/trap.c /n/emeliedump/2002/0518/sys/src/9/bitsy/trap.c 75a #endif . 73a #ifdef notdef . ## diffname bitsy/trap.c 2002/0604 ## diff -e /n/emeliedump/2002/0518/sys/src/9/bitsy/trap.c /n/emeliedump/2002/0604/sys/src/9/bitsy/trap.c 69,77d 33,38d ## diffname bitsy/trap.c 2002/0615 ## diff -e /n/emeliedump/2002/0604/sys/src/9/bitsy/trap.c /n/emeliedump/2002/0615/sys/src/9/bitsy/trap.c 681a pexit("kproc exiting", 0); . 199a * disable an interrupt */ void intrdisable(int type, int which, IntrHandler *f, void* a, char *name) { int irq; Vctl **vp, *v; if(type == IRQ){ irqdisable(which, f, a, name); return; } /* from here down, it must be a GPIO edge interrupt */ irq = which; if(which >= nelem(gpiovctl) || which < 0) panic("intrdisable"); if(which > 11) irq = 11; lock(&vctllock); for(vp = &gpiovctl[which]; v = *vp; vp = &v->next) if (v->f == f && v->a == a && strcmp(v->name, name) == 0){ break; } if (gpiovctl[which] == nil){ /* set edge register to enable interrupt */ switch(type){ case GPIOboth: print("intrdisable: gpio-rising+falling clear bit %d\n", which); gpioregs->rising &= ~(1<falling &= ~(1<falling &= ~(1<rising &= ~(1<next; }else print("intrdisable: which %d, name %s not enabled\n", which, name); unlock(&vctllock); /* disable the gpio interrupt handler if necessary */ if(--gpioirqref[irq] == 0){ print("intrdisable: inrqdisable gpiointr\n"); irqdisable(irq, gpiointr, nil, "gpio edge"); } free(v); } /* . 193c unlock(&vctllock); . 178d 169c v = malloc(sizeof(Vctl)); . 166c panic("intrenable of output pin %d", which); . 160c panic("intrenable"); . 156a print("intrenable %s, handler 0x%p\n", name, f); . 143a * disable an irq interrupt */ static void irqdisable(int irq, IntrHandler *f, void* a, char *name) { Vctl **vp, *v; if(irq >= nelem(vctl) || irq < 0) panic("intrdisable"); lock(&vctllock); for(vp = &vctl[irq]; v = *vp; vp = &v->next) if (v->f == f && v->a == a && strcmp(v->name, name) == 0){ print("irqdisable: remove %s\n", name); *vp = v->next; free(v); break; } if (v == nil) print("irqdisable: irq %d, name %s not enabled\n", irq, name); if (vctl[irq] == nil){ print("irqdisable: clear icmr bit %d\n", irq); intrregs->icmr &= ~(1<