📄 trap.c
字号:
#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"void noted(Ureg*, Ureg**, ulong);void rfnote(Ureg**);void kernfault(Ureg*, int);void illegal(Ureg *);void fen(Ureg *);char *regname[]={ "type", "a0", "a1", "a2", "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", "R8", "R9", "R10", "R11", "R12", "R13", "R14", "R15", "R19", "R20", "R21", "R22", "R23", "R24", "R25", "R26", "R27", "R28", "R30", "status", "PC", "R29", "R16", "R17", "R18",};static Lock vctllock;static Vctl *vctl[256];voidintrenable(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 = arch->intrenable(v); if(vno == -1){ iunlock(&vctllock); print("intrenable: couldn't enable irq %d, tbdf 0x%uX for %s\n", irq, tbdf, v->name); 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);}intintrdisable(int irq, void (*f)(Ureg *, void *), void *a, int tbdf, char *name){ Vctl **pv, *v; int vno; /* * For now, none of this will work with the APIC code, * there is no mapping between irq and vector as the IRQ * is pretty meaningless. */ if(arch->intrvecno == nil) return -1; vno = arch->intrvecno(irq); ilock(&vctllock); for(pv = &vctl[vno]; *pv != nil; pv = &((*pv)->next)){ if((*pv)->irq != irq) continue; if((*pv)->tbdf != tbdf) continue; if((*pv)->f != f) continue; if((*pv)->a != a) continue; if(strcmp((*pv)->name, name) != 0) continue; break; } assert(*pv != nil); v = *pv; *pv = (*pv)->next; /* Link out the entry */ if (vctl[vno] == nil && arch->intrdisable != nil) arch->intrdisable(irq); iunlock(&vctllock); xfree(v); return 0;}intirqallocread(char *buf, long n, vlong offset){ int vno; Vctl *v; long oldn; char str[11+1+KNAMELEN+1], *p; int m; if(n < 0 || offset < 0) error(Ebadarg); oldn = n; for(vno=0; vno<nelem(vctl); vno++){ for(v=vctl[vno]; v; v=v->next){ m = snprint(str, sizeof str, "%11d %11d %.*s\n", vno, v->irq, KNAMELEN, v->name); if(m <= offset) /* if do not want this, skip entry */ offset -= m; else{ /* skip offset bytes */ m -= offset; p = str+offset; offset = 0; /* write at most max(n,m) bytes */ if(m > n) m = n; memmove(buf, p, m); n -= m; buf += m; if(n == 0) return oldn; } } } return oldn - n;}typedef struct Mcheck Mcheck;struct Mcheck{ ulong len; ulong inprogress; ulong procoff; ulong sysoff; ulong code;};static char *smcheck(ulong code){ switch (code) { case 0x80: return "tag parity error"; case 0x82: return "tag control parity error"; case 0x84: return "generic hard error"; case 0x86: return "correctable ECC error"; case 0x88: return "uncorrectable ECC error"; case 0x8a: return "OS-specific PAL bugcheck"; case 0x90: return "callsys in kernel mode"; case 0x96: return "i-cache read retryable error"; case 0x98: return "processor detected hard error"; case 0x203: return "system detected uncorrectable ECC error"; case 0x205: return "parity error detected by CIA"; case 0x207: return "non-existent memory error"; case 0x209: return "PCI SERR detected"; case 0x20b: return "PCI data parity error detected"; case 0x20d: return "PCI address parity error detected"; case 0x20f: return "PCI master abort error"; case 0x211: return "PCI target abort error"; case 0x213: return "scatter/gather PTE invalid error"; case 0x215: return "flash ROM write error"; case 0x217: return "IOA timeout detected"; case 0x219: return "IOCHK#, EISA add-in board parity or other catastrophic error"; case 0x21b: return "EISA fail-safe timer timeout"; case 0x21d: return "EISA bus time-out"; case 0x21f: return "EISA software generated NMI"; case 0x221: return "unexpected ev5 IRQ[3] interrupt"; default: return "unknown mcheck"; }}voidmcheck(Ureg *ur, void *x){ Mcheck *m; uvlong *data; int i, col; m = x; data = x; iprint("panic: Machine Check @%lux: %s (%lux) len %lud\n", m, smcheck(m->code), m->code, m->len); iprint("proc offset %lux sys offset %lux\n", m->procoff, m->sysoff); for (i = 0, col = 0; i < m->len/8; i++) { iprint("%.3x: %.16llux%s", 8*i, data[i], (col == 2) ? "\n" : " "); if (col++ == 2) col = 0; } if(col != 2) print("\n"); print("\n"); dumpregs(ur); prflush(); firmware();}voidintr(Ureg *ur){ int i, vno; Vctl *ctl, *v; Mach *mach; vno = (ulong)ur->a1>>4; vno -= 0x80; if(vno < nelem(vctl) && (ctl = vctl[vno])){ if(ctl->isintr){ m->intr++; if(vno >= VectorPIC && vno <= MaxVectorPIC) m->lastintr = vno-VectorPIC; } if(ctl->isr) ctl->isr(vno); for(v = ctl; v != nil; v = v->next) { if(v->f) v->f(ur, v->a); } if(ctl->eoi) ctl->eoi(vno); if(ctl->isintr && up) preempted(); } else if(vno >= VectorPIC && vno <= MaxVectorPIC){ /* * An unknown interrupt. * Check for a default IRQ7. This can happen when * the IRQ input goes away before the acknowledge. * In this case, a 'default IRQ7' is generated, but * the corresponding bit in the ISR isn't set. * In fact, just ignore all such interrupts. */ iprint("cpu%d: spurious interrupt %d, last %d", m->machno, vno-VectorPIC, m->lastintr); for(i = 0; i < 32; i++){ if(!(active.machs & (1<<i))) continue; mach = MACHP(i); if(m->machno == mach->machno) continue; iprint(": cpu%d: last %d", mach->machno, mach->lastintr); } iprint("\n"); m->spuriousintr++; return; } else{ dumpregs(ur); print("unknown intr: %d\n", vno); /* */ }}voidtrap(Ureg *ur){ char buf[ERRMAX]; int clockintr, user, x; user = ur->status&UMODE; if(user){ up = m->proc; up->dbgreg = ur; } clockintr = 0; switch ((int)ur->type) { case 1: /* arith */ fptrap(ur); break; case 2: /* bad instr or FEN */ illegal(ur); break; case 3: /* intr */ m->intr++; switch ((int)ur->a0) { case 0: /* interprocessor */ panic("interprocessor intr"); break; case 1: /* clock */ clockintr = 1; clock(ur); break; case 2: /* machine check */ mcheck(ur, (void*)(KZERO|(ulong)ur->a2)); break; case 3: /* device */ intr(ur); break; case 4: /* perf counter */ panic("perf count"); break; default: panic("bad intr"); break; } break; case 4: /* memory fault */ if(up == 0) kernfault(ur, (ulong)ur->a1); x = up->insyscall; up->insyscall = 1; spllo(); faultalpha(ur); up->insyscall = x; break; case 6: /* alignment fault */ ur->pc -= 4; sprint(buf, "trap: unaligned addr 0x%lux", (ulong)ur->a0); fataltrap(ur, buf); break; default: /* cannot happen */ panic("bad trap type %d", (int)ur->type); break; } splhi(); /* delaysched set because we held a lock or because our quantum ended */ if(up && up->delaysched && clockintr){ sched(); splhi(); } if(user){ if(up->procctl || up->nnote) notify(ur); kexit(ur); }}voidtrapinit(void){ splhi(); wrent(0, intr0); wrent(1, arith); wrent(2, fault0); wrent(3, illegal0); wrent(4, unaligned); wrent(5, syscall0);}voidfataltrap(Ureg *ur, char *reason){ char buf[ERRMAX]; if(ur->status&UMODE) { spllo(); sprint(buf, "sys: %s", reason); postnote(up, 1, buf, NDebug); return; } print("kernel %s pc=%lux\n", reason, (ulong)ur->pc); dumpregs(ur); dumpstack(); if(m->machno == 0) spllo(); exit(1);}voidkernfault(Ureg *ur, int code){ Label l; char *s; splhi(); if (code == 0) s = "read"; else if (code == 1) s = "write"; else s = "ifetch"; print("panic: kfault %s VA=0x%lux\n", s, (ulong)ur->a0); print("u=0x%lux status=0x%lux pc=0x%lux sp=0x%lux\n", up, (ulong)ur->status, (ulong)ur->pc, (ulong)ur->sp); dumpregs(ur); l.sp = ur->sp; l.pc = ur->pc; dumpstack(); exit(1);}voiddumpregs(Ureg *ur){ int i, col; uvlong *l; if(up) print("registers for %s %ld\n", up->text, up->pid); else print("registers for kernel\n"); l = &ur->type; col = 0; for (i = 0; i < sizeof regname/sizeof(char*); i++, l++) { print("%-7s%.16llux%s", regname[i], *l, col == 2 ? "\n" : " "); if (col++ == 2) col = 0; } print("\n");}/* * Fill in enough of Ureg to get a stack trace, and call a function. * Used by debugging interface rdb. */static voidgetpcsp(ulong *pc, ulong *sp){ *pc = getcallerpc(&pc); *sp = (ulong)&pc-8;}voidcallwithureg(void (*fn)(Ureg*)){ Ureg ureg; getpcsp((ulong*)&ureg.pc, (ulong*)&ureg.sp); ureg.r26 = getcallerpc(&fn); fn(&ureg);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -