2 #include "../port/lib.h"
8 #include "../port/error.h"
10 void noted(Ureg*, Ureg**, ulong);
12 void kernfault(Ureg*, int);
27 "R30", "status", "PC",
33 static Vctl *vctl[256];
36 intrenable(int irq, void (*f)(Ureg*, void*), void* a, int tbdf, char *name)
42 print("intrenable: nil handler for %d, tbdf 0x%uX for %s\n",
47 v = xalloc(sizeof(Vctl));
53 strncpy(v->name, name, KNAMELEN-1);
54 v->name[KNAMELEN-1] = 0;
57 vno = arch->intrenable(v);
60 print("intrenable: couldn't enable irq %d, tbdf 0x%uX for %s\n",
66 if(vctl[vno]->isr != v->isr || vctl[vno]->eoi != v->eoi)
67 panic("intrenable: handler: %s %s %#p %#p %#p %#p",
68 vctl[vno]->name, v->name,
69 vctl[vno]->isr, v->isr, vctl[vno]->eoi, v->eoi);
77 intrdisable(int irq, void (*f)(Ureg *, void *), void *a, int tbdf, char *name)
83 * For now, none of this will work with the APIC code,
84 * there is no mapping between irq and vector as the IRQ
85 * is pretty meaningless.
87 if(arch->intrvecno == nil)
89 vno = arch->intrvecno(irq);
91 for(pv = &vctl[vno]; *pv != nil; pv = &((*pv)->next)){
94 if((*pv)->tbdf != tbdf)
100 if(strcmp((*pv)->name, name) != 0)
107 *pv = (*pv)->next; /* Link out the entry */
109 if (vctl[vno] == nil && arch->intrdisable != nil)
110 arch->intrdisable(irq);
117 irqallocread(char *buf, long n, vlong offset)
122 char str[11+1+KNAMELEN+1], *p;
125 if(n < 0 || offset < 0)
129 for(vno=0; vno<nelem(vctl); vno++){
130 for(v=vctl[vno]; v; v=v->next){
131 m = snprint(str, sizeof str, "%11d %11d %.*s\n", vno, v->irq, KNAMELEN, v->name);
132 if(m <= offset) /* if do not want this, skip entry */
135 /* skip offset bytes */
140 /* write at most max(n,m) bytes */
155 typedef struct Mcheck Mcheck;
169 case 0x80: return "tag parity error";
170 case 0x82: return "tag control parity error";
171 case 0x84: return "generic hard error";
172 case 0x86: return "correctable ECC error";
173 case 0x88: return "uncorrectable ECC error";
174 case 0x8a: return "OS-specific PAL bugcheck";
175 case 0x90: return "callsys in kernel mode";
176 case 0x96: return "i-cache read retryable error";
177 case 0x98: return "processor detected hard error";
179 case 0x203: return "system detected uncorrectable ECC error";
180 case 0x205: return "parity error detected by CIA";
181 case 0x207: return "non-existent memory error";
182 case 0x209: return "PCI SERR detected";
183 case 0x20b: return "PCI data parity error detected";
184 case 0x20d: return "PCI address parity error detected";
185 case 0x20f: return "PCI master abort error";
186 case 0x211: return "PCI target abort error";
187 case 0x213: return "scatter/gather PTE invalid error";
188 case 0x215: return "flash ROM write error";
189 case 0x217: return "IOA timeout detected";
190 case 0x219: return "IOCHK#, EISA add-in board parity or other catastrophic error";
191 case 0x21b: return "EISA fail-safe timer timeout";
192 case 0x21d: return "EISA bus time-out";
193 case 0x21f: return "EISA software generated NMI";
194 case 0x221: return "unexpected ev5 IRQ[3] interrupt";
195 default: return "unknown mcheck";
200 mcheck(Ureg *ur, void *x)
208 iprint("panic: Machine Check @%#p: %s (%lux) len %lud\n",
209 m, smcheck(m->code), m->code, m->len);
210 iprint("proc offset %lux sys offset %lux\n", m->procoff, m->sysoff);
211 for (i = 0, col = 0; i < m->len/8; i++) {
212 iprint("%.3x: %.16llux%s", 8*i, data[i], (col == 2) ? "\n" : " ");
231 vno = (ulong)ur->a1>>4;
233 if(vno < nelem(vctl) && (ctl = vctl[vno])){
236 if(vno >= VectorPIC && vno <= MaxVectorPIC)
237 m->lastintr = vno-VectorPIC;
242 for(v = ctl; v != nil; v = v->next) {
250 if(ctl->isintr && up)
253 else if(vno >= VectorPIC && vno <= MaxVectorPIC){
255 * An unknown interrupt.
256 * Check for a default IRQ7. This can happen when
257 * the IRQ input goes away before the acknowledge.
258 * In this case, a 'default IRQ7' is generated, but
259 * the corresponding bit in the ISR isn't set.
260 * In fact, just ignore all such interrupts.
262 iprint("cpu%d: spurious interrupt %d, last %d",
263 m->machno, vno-VectorPIC, m->lastintr);
264 for(i = 0; i < 32; i++){
265 if(!(active.machs & (1<<i)))
268 if(m->machno == mach->machno)
270 iprint(": cpu%d: last %d", mach->machno, mach->lastintr);
278 print("unknown intr: %d\n", vno); /* */
286 int clockintr, user, x;
288 user = ur->status&UMODE;
295 switch ((int)ur->type) {
299 case 2: /* bad instr or FEN */
305 switch ((int)ur->a0) {
306 case 0: /* interprocessor */
307 panic("interprocessor intr");
313 case 2: /* machine check */
314 mcheck(ur, (void*)(KZERO|(ulong)ur->a2));
319 case 4: /* perf counter */
328 case 4: /* memory fault */
330 kernfault(ur, (ulong)ur->a1);
338 case 6: /* alignment fault */
340 sprint(buf, "trap: unaligned addr 0x%lux", (ulong)ur->a0);
343 default: /* cannot happen */
344 panic("bad trap type %d", (int)ur->type);
350 /* delaysched set because we held a lock or because our quantum ended */
351 if(up && up->delaysched && clockintr){
357 if(up->procctl || up->nnote)
376 fataltrap(Ureg *ur, char *reason)
380 if(ur->status&UMODE) {
382 sprint(buf, "sys: %s", reason);
383 postnote(up, 1, buf, NDebug);
386 print("kernel %s pc=%lux\n", reason, (ulong)ur->pc);
395 kernfault(Ureg *ur, int code)
407 print("panic: kfault %s VA=0x%lux\n", s, (ulong)ur->a0);
408 print("u=%#p status=0x%lux pc=0x%lux sp=0x%lux\n",
409 up, (ulong)ur->status, (ulong)ur->pc, (ulong)ur->sp);
424 print("registers for %s %ld\n", up->text, up->pid);
426 print("registers for kernel\n");
430 for (i = 0; i < sizeof regname/sizeof(char*); i++, l++) {
431 print("%-7s%.16llux%s", regname[i], *l, col == 2 ? "\n" : " ");
440 * Fill in enough of Ureg to get a stack trace, and call a function.
441 * Used by debugging interface rdb.
444 getpcsp(ulong *pc, ulong *sp)
446 *pc = getcallerpc(&pc);
451 callwithureg(void (*fn)(Ureg*))
455 getpcsp((ulong*)&ureg.pc, (ulong*)&ureg.sp);
456 ureg.r26 = getcallerpc(&fn);
461 _dumpstack(Ureg *ureg)
463 ulong l, sl, el, v, i, instr, op;
474 sl = (ulong)up->kstack;
477 if(l > el || l < sl){
483 print("ktrace /kernel/path %.8lux %.8lux %.8lux\n", (ulong)ureg->pc, (ulong)ureg->sp, (ulong)ureg->r26);
488 if(KTZERO < v && v < (ulong)&etext && (v&3) == 0){
494 if(op == 26 || op == 52){
495 print("%lux=%lux ", l, v);
511 callwithureg(_dumpstack);
530 if(up->fpstate == FPactive){
531 savefpregs(&up->fpsave);
532 up->fpstate = FPinactive;
534 up->fpstate |= FPillegal;
537 if(strncmp(n->msg, "sys:", 4) == 0) {
539 if(l > ERRMAX-15) /* " pc=0x12345678\0" */
542 sprint(n->msg+l, " pc=0x%lux", (ulong)ur->pc);
545 if(n->flag != NUser && (up->notified || up->notify==0)) {
546 if(n->flag == NDebug)
547 pprint("suicide: %s\n", n->msg);
549 pexit(n->msg, n->flag!=NDebug);
560 pexit(n->msg, n->flag!=NDebug);
562 sp = ur->usp & ~(BY2V-1);
565 if(!okaddr((ulong)up->notify, BY2WD, 0)
566 || !okaddr(sp-ERRMAX-6*BY2WD, sizeof(Ureg)+ERRMAX-6*BY2WD, 1)) {
567 pprint("suicide: bad address or sp in notify\n");
568 print("suicide: bad address or sp in notify\n");
573 memmove((Ureg*)sp, ur, sizeof(Ureg));
574 *(Ureg**)(sp-BY2WD) = up->ureg; /* word under Ureg is old up->ureg */
575 up->ureg = (void*)sp;
576 sp -= 2*BY2WD+ERRMAX;
577 memmove((char*)sp, up->note[0].msg, ERRMAX);
579 *(ulong*)(sp+3*BY2WD) = sp+4*BY2WD; /* arg 2 is string */
580 ur->r0 = (ulong)up->ureg; /* arg 1 (R0) is ureg* */
581 *(ulong*)(sp+2*BY2WD) = (ulong)up->ureg; /* arg 1 0(FP) is ureg* */
582 *(ulong*)(sp+0*BY2WD) = 0; /* arg 0 is pc */
584 ur->pc = (ulong)up->notify;
587 memmove(&up->lastnote, &up->note[0], sizeof(Note));
588 memmove(&up->note[0], &up->note[1], up->nnote*sizeof(Note));
596 * Check that status is OK to return from note.
599 validstatus(ulong kstatus, ulong ustatus)
601 if((kstatus & 7) != (ustatus & 7))
603 if((ustatus&UMODE) != UMODE)
609 * Return user to state before notify()
612 noted(Ureg *kur, Ureg **urp, ulong arg0)
618 if(arg0!=NRSTR && !up->notified) {
620 pprint("call to noted() when not notified\n");
621 print("call to noted() when not notified\n");
626 up->fpstate &= ~FPillegal;
631 if((oureg & (BY2V-1))
632 || !okaddr((ulong)oureg-BY2WD, BY2WD+sizeof(Ureg), 0)){
633 pprint("bad ureg in noted or call to noted() when not notified\n");
634 print("bad ureg in noted or call to noted() when not notified\n");
639 if(!validstatus(kur->status, nur->status)) {
641 pprint("bad noted ureg status %lux\n", (ulong)nur->status);
642 print("bad noted ureg status %lux\n", (ulong)nur->status);
646 memmove(*urp, up->ureg, sizeof(Ureg));
650 if(!okaddr(nur->pc, BY2WD, 0) || !okaddr(nur->usp, BY2WD, 0)){
651 pprint("suicide: trap in noted\n");
652 print("suicide: trap in noted\n");
656 up->ureg = (Ureg*)(*(ulong*)(oureg-BY2WD));
663 if(!okaddr(nur->pc, BY2WD, 0) || !okaddr(nur->usp, BY2WD, 0)){
664 pprint("suicide: trap in noted\n");
665 print("suicide: trap in noted\n");
670 sp = oureg-4*BY2WD-ERRMAX;
673 ((ulong*)sp)[1] = oureg; /* arg 1 0(FP) is ureg* */
674 ((ulong*)sp)[0] = 0; /* arg 0 is pc */
675 (*urp)->r0 = oureg; /* arg 1 is ureg* */
680 pprint("unknown noted arg 0x%lux\n", arg0);
681 print("unknown noted arg 0x%lux\n", arg0);
682 up->lastnote.flag = NDebug;
686 if(up->lastnote.flag == NDebug)
687 pprint("suicide: %s\n", up->lastnote.msg);
689 pexit(up->lastnote.msg, up->lastnote.flag!=NDebug);
693 #include "../port/systab.h"
711 ur->type = 5; /* for debugging */
714 up->scallnr = ur->r0;
716 if(scallnr == RFORK && up->fpstate == FPactive){
717 savefpregs(&up->fpsave);
718 up->fpstate = FPinactive;
719 //print("SR=%lux+", up->fpsave.fpstatus);
727 if(scallnr >= nsyscall || systab[scallnr] == nil){
728 pprint("bad sys call %d pc %lux\n", up->scallnr, (ulong)ur->pc);
729 postnote(up, 1, "sys: bad sys call", NDebug);
733 if(sp & (BY2WD-1)){ /* XXX too weak? */
734 pprint("odd sp in sys call pc %lux sp %lux\n",
735 (ulong)ur->pc, (ulong)ur->sp);
736 postnote(up, 1, "sys: odd stack", NDebug);
740 if(sp<(USTKTOP-BY2PG) || sp>(USTKTOP-sizeof(Sargs)))
741 validaddr(sp, sizeof(Sargs), 0);
743 up->s = *((Sargs*)(sp+2*BY2WD));
744 up->psstate = sysctab[scallnr];
745 ret = systab[scallnr](up->s.args);
748 /* failure: save the error buffer for errstr */
750 up->syserrstr = up->errstr;
754 print("bad errstack [%uld]: %d extra\n", scallnr, up->nerrlab);
755 for(i = 0; i < NERR; i++)
756 print("sp=%lux pc=%lux\n",
757 up->errlab[i].sp, up->errlab[i].pc);
758 panic("error stack");
764 if(scallnr == NOTED) /* ugly hack */
765 noted(ur, &aur, *(ulong*)(sp+2*BY2WD)); /* doesn't return */
767 if(scallnr!=RFORK && (up->procctl || up->nnote)){
768 ur->r0 = ret; /* load up for noted() */
777 forkchild(Proc *p, Ureg *ur)
781 p->sched.sp = (ulong)p->kstack+KSTACK-(4*BY2WD+sizeof(Ureg));
782 p->sched.pc = (ulong)forkret;
784 cur = (Ureg*)(p->sched.sp+4*BY2WD);
785 memmove(cur, ur, sizeof(Ureg));
787 /* Things from bottom of syscall we never got to execute */
797 up->kpfun(up->kparg);
798 pexit("kproc exiting", 0);
802 kprocchild(Proc *p, void (*func)(void*), void *arg)
804 p->sched.pc = (ulong)linkproc;
805 p->sched.sp = (ulong)p->kstack+KSTACK;
812 execregs(ulong entry, ulong ssize, ulong nargs)
817 sp = (ulong*)(USTKTOP - ssize);
820 ur = (Ureg*)up->dbgreg;
823 return USTKTOP-BY2WD; /* address of user-level clock */
831 ur = (Ureg*)up->dbgreg;
835 /* This routine must save the values of registers the user is not permitted to write
836 * from devproc and then restore the saved values before returning
839 setregisters(Ureg *xp, char *pureg, char *uva, int n)
844 memmove(pureg, uva, n);
848 /* Give enough context in the ureg to produce a kernel stack for
852 setkernur(Ureg *xp, Proc *p)
854 xp->pc = p->sched.pc;
855 xp->sp = p->sched.sp;
856 xp->r26 = (ulong)sched;
874 switch ((int)ur->a0) {
875 case 0: /* breakpoint */
877 fataltrap(ur, "breakpoint");
880 fataltrap(ur, "trap: bugchk");
882 case 2: /* gentrap */
883 fataltrap(ur, "trap: gentrap");
889 fataltrap(ur, "trap: illegal instruction");
892 panic("illegal illegal %d", (int)ur->a0);
904 up->fpstate = FPactive;
905 //print("EI=%lux+", initfp.fpstatus);
909 restfpregs(&up->fpsave);
910 up->fpstate = FPactive;
911 //print("EIA=%lux+", up->fpsave.fpstatus);
915 fataltrap(ur, "trap: floating enable"); /* should never happen */