| plan 9 kernel history: overview | file list | diff list |
1992/0711/gnot/trap.c (diff list | history)
| 1992/0711/sys/src/9/gnot/trap.c:1,385 – 1992/0714/sys/src/9/gnot/trap.c:1,385 (short | long | prev | next) | ||
| 1990/03091 | #include "u.h" | |
| 1992/0321 | #include "../port/lib.h" | |
| 1990/03091 | #include "mem.h" #include "dat.h" #include "fns.h" #include "ureg.h" #include "io.h" | |
| 1992/0111 | #include "../port/error.h" | |
| 1990/03091 | ||
| 1991/0717 | void noted(Ureg*, ulong); | |
| 1991/0503 | void rfnote(Ureg*); | |
| 1990/03091 | char *regname[]={ "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", "A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", }; long ticks; char *trapname[]={ "reset isp", "reset ipc", "bus error", "address error", "illegal instruction", "zero divide", "chk, chk2 instruction", | |
| 1991/1218 | "trapcc instruction", | |
| 1990/03091 | "privilege violation", "trace", "line 1010 emulator", "line 1111 emulator", "reserved", | |
| 1991/1218 | "coprocessor protocol violation", | |
| 1990/03091 | "format error", "uninitialized interrupt", "unassigned 0x40", "unassigned 0x44", "unassigned 0x48", "unassigned 0x4C", "unassigned 0x50", "unassigned 0x54", "unassigned 0x58", "unassigned 0x5C", "spurious interrupt", "level 1 autovector (tac)", "level 2 autovector (port)", "level 3 autovector (incon)", "level 4 autovector (mouse)", "level 5 autovector (uart)", "level 6 autovector (sync)", "level 7 autovector", }; | |
| 1991/12171 | char *fptrapname[]={ | |
| 1991/1218 | [49-49] "inexact result", [50-49] "divide by zero", [51-49] "underflow", [52-49] "operand error", [53-49] "overflow", [54-49] "signaling NaN", | |
| 1991/12171 | }; | |
| 1990/03091 | char* | |
| 1991/1113 | excname(unsigned vo, ulong pc) | |
| 1990/03091 | { static char buf[32]; /* BUG: not reentrant! */ vo &= 0x0FFF; vo >>= 2; | |
| 1991/1113 | if(vo < sizeof trapname/sizeof(char*)){ /* special case, and pc will be o.k. */ if(vo==4 && *(ushort*)pc==0x4848) return "breakpoint"; | |
| 1991/1218 | sprint(buf, "trap: %s", trapname[vo]); return buf; | |
| 1991/1113 | } | |
| 1991/1218 | if(49<=vo && vo<=54){ sprint(buf, "fp: %s", fptrapname[vo-49]); return buf; } | |
| 1990/03091 | sprint(buf, "offset 0x%ux", vo<<2); return buf; } void trap(Ureg *ur) { int user; char buf[64]; user = !(ur->sr&SUPER); | |
| 1991/1112 | if(u) { | |
| 1990/03091 | u->p->pc = ur->pc; /* BUG */ | |
| 1991/1112 | u->dbgreg = ur; } | |
| 1990/03091 | if(user){ | |
| 1991/1218 | sprint(buf, "sys: %s", excname(ur->vo, ur->pc)); | |
| 1990/03091 | postnote(u->p, 1, buf, NDebug); }else{ | |
| 1991/1113 | print("kernel trap %s pc=0x%lux\n", excname(ur->vo, ur->pc), ur->pc); | |
| 1990/03091 | dumpregs(ur); exit(); } | |
| 1991/0705 | ||
| 1991/1112 | if(user) notify(ur); | |
| 1990/03091 | } void dumpstack(void) { ulong l, v; extern ulong etext; if(u) for(l=(ulong)&l; l<USERADDR+BY2PG; l+=4){ v = *(ulong*)l; if(KTZERO < v && v < (ulong)&etext) print("%lux=%lux\n", l, v); } } void dumpregs(Ureg *ur) { int i; ulong *l; if(u) print("registers for %s %d\n", u->p->text, u->p->pid); else print("registers for kernel\n"); print("SR=%ux PC=%lux VO=%lux, USP=%lux\n", ur->sr, ur->pc, ur->vo, ur->usp); l = &ur->r0; 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]); } /* * Call user, if necessary, with note */ | |
| 1992/0108 | int | |
| 1990/03091 | notify(Ureg *ur) { | |
| 1992/0124 | int l, sent; | |
| 1991/1114 | ulong s, sp; | |
| 1991/1218 | Note *n; | |
| 1990/03091 | ||
| 1991/1112 | if(u->p->procctl) procctl(u->p); | |
| 1992/0108 | if(u->nnote == 0) return 0; | |
| 1991/1112 | ||
| 1991/1114 | s = spllo(); | |
| 1991/1216 | qlock(&u->p->debug); | |
| 1991/0727 | u->p->notepending = 0; | |
| 1991/1218 | n = &u->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 && (u->notified || u->notify==0)){ | |
| 1990/03091 |
| |
| 1992/0714 | if(n->flag == NDebug) | |
| 1991/1218 | pprint("suicide: %s\n", n->msg); | |
| 1990/03091 | Die: | |
| 1991/1216 | qunlock(&u->p->debug); | |
| 1991/1218 | pexit(n->msg, n->flag!=NDebug); | |
| 1990/03091 | } | |
| 1992/0124 | sent = 0; | |
| 1990/03091 | if(!u->notified){ if(!u->notify) goto Die; | |
| 1992/0124 | sent = 1; | |
| 1991/0503 | u->svvo = ur->vo; u->svsr = ur->sr; | |
| 1990/0816 | sp = ur->usp; | |
| 1990/03091 | sp -= sizeof(Ureg); | |
| 1992/0616 | if(!okaddr((ulong)u->notify, 1, 0) || !okaddr(sp-ERRLEN-3*BY2WD, sizeof(Ureg)+ERRLEN-3*BY2WD, 0)){ pprint("suicide: bad address in notify\n"); | |
| 1991/1216 | qunlock(&u->p->debug); | |
| 1991/0722 | pexit("Suicide", 0); } | |
| 1990/03091 | u->ureg = (void*)sp; | |
| 1991/0318 | memmove((Ureg*)sp, ur, sizeof(Ureg)); | |
| 1990/03091 | sp -= ERRLEN; | |
| 1991/0318 | memmove((char*)sp, u->note[0].msg, ERRLEN); | |
| 1990/03091 | sp -= 3*BY2WD; *(ulong*)(sp+2*BY2WD) = sp+3*BY2WD; /* arg 2 is string */ *(ulong*)(sp+1*BY2WD) = (ulong)u->ureg; /* arg 1 is ureg* */ *(ulong*)(sp+0*BY2WD) = 0; /* arg 0 is pc */ | |
| 1990/0816 | ur->usp = sp; | |
| 1990/03091 | ur->pc = (ulong)u->notify; | |
| 1991/0719 | ur->vo = 0x0080; /* pretend we're returning from syscall */ | |
| 1990/03091 | u->notified = 1; u->nnote--; | |
| 1991/0717 | memmove(&u->lastnote, &u->note[0], sizeof(Note)); | |
| 1991/0318 | memmove(&u->note[0], &u->note[1], u->nnote*sizeof(Note)); | |
| 1990/03091 | } | |
| 1991/1216 | qunlock(&u->p->debug); | |
| 1991/1114 | splx(s); | |
| 1992/0124 | return sent; | |
| 1990/03091 | } /* * Return user to state before notify() */ void | |
| 1991/0717 | noted(Ureg *ur, ulong arg0) | |
| 1990/03091 | { | |
| 1991/0503 | Ureg *nur; nur = u->ureg; if(nur->sr!=u->svsr || nur->vo!=u->svvo){ pprint("bad noted ureg sr %ux vo %ux\n", nur->sr, nur->vo); | |
| 1991/0814 | Die: | |
| 1991/0503 | pexit("Suicide", 0); } | |
| 1991/1216 | qlock(&u->p->debug); | |
| 1990/0619 | if(!u->notified){ | |
| 1991/1216 | qunlock(&u->p->debug); | |
| 1991/0814 | pprint("call to noted() when not notified\n"); goto Die; | |
| 1990/0619 | } | |
| 1990/03091 | u->notified = 0; | |
| 1991/0503 | memmove(ur, u->ureg, sizeof(Ureg)); | |
| 1991/0717 | switch(arg0){ case NCONT: | |
| 1992/0616 | if(!okaddr(nur->pc, 1, 0) || !okaddr(nur->usp, BY2WD, 0)){ | |
| 1991/0814 | pprint("suicide: trap in noted\n"); | |
| 1991/1216 | qunlock(&u->p->debug); | |
| 1991/0814 | goto Die; } | |
| 1991/0717 | splhi(); | |
| 1991/1216 | qunlock(&u->p->debug); | |
| 1991/0717 | rfnote(ur); break; /* never returns */ default: pprint("unknown noted arg 0x%lux\n", arg0); u->lastnote.flag = NDebug; /* fall through */ | |
| 1991/0718 | case NDFLT: | |
| 1991/0717 | if(u->lastnote.flag == NDebug) pprint("suicide: %s\n", u->lastnote.msg); | |
| 1991/1216 | qunlock(&u->p->debug); | |
| 1991/0717 | pexit(u->lastnote.msg, u->lastnote.flag!=NDebug); } | |
| 1990/03091 | } | |
| 1991/0731 | #include "../port/systab.h" | |
| 1990/03091 | long syscall(Ureg *aur) { long ret; ulong sp; Ureg *ur; u->p->insyscall = 1; ur = aur; | |
| 1991/1112 | u->dbgreg = aur; | |
| 1990/0312 | u->p->pc = ur->pc; | |
| 1990/03091 | if(ur->sr & SUPER) panic("recursive system call"); /* * since the system call interface does not | |
| 1990/08163 | * guarantee anything about registers, but the fpcr is more than * just a register... BUG | |
| 1990/03091 | */ | |
| 1990/08163 | splhi(); fpsave(&u->fpsave); if(u->p->fpstate==FPactive || u->fpsave.type){ | |
| 1990/0905 | fprestore(&initfp); | |
| 1990/08163 | u->p->fpstate = FPinit; m->fpstate = FPinit; | |
| 1990/03091 | } | |
| 1990/08163 | spllo(); | |
| 1991/1108 | if(u->p->procctl) procctl(u->p); | |
| 1992/06271 | u->scallnr = ur->r0; | |
| 1990/03091 | sp = ur->usp; u->nerrlab = 0; ret = -1; | |
| 1990/0511 | if(!waserror()){ | |
| 1992/06271 | if(u->scallnr >= sizeof systab/sizeof systab[0]){ pprint("bad sys call number %d pc %lux\n", u->scallnr, ur->pc); | |
| 1992/0625 | postnote(u->p, 1, "sys: bad sys call", NDebug); | |
| 1990/11211 | error(Ebadarg); | |
| 1990/0511 | } | |
| 1992/0625 | ||
| 1990/0511 | if(sp & (BY2WD-1)){ | |
| 1992/0625 | pprint("odd sp in sys call pc %lux sp %lux\n", ur->pc, ur->sp); postnote(u->p, 1, "sys: odd stack", NDebug); error(Ebadarg); | |
| 1990/0511 | } | |
| 1992/0625 | if(sp<(USTKTOP-BY2PG) || sp>(USTKTOP-sizeof(Sargs))) validaddr(sp, sizeof(Sargs), 0); | |
| 1992/0701 | u->s = *((Sargs*)(sp+1*BY2WD)); | |
| 1992/06271 | u->p->psstate = sysctab[u->scallnr]; | |
| 1992/0625 | ||
| 1992/06271 | ret = (*systab[u->scallnr])(u->s.args); | |
| 1991/0614 | poperror(); | |
| 1990/0511 | } | |
| 1991/0705 | ||
| 1991/1108 | u->nerrlab = 0; | |
| 1990/03091 | u->p->insyscall = 0; | |
| 1991/0926 | u->p->psstate = 0; | |
| 1991/0705 | ||
| 1992/06271 | if(u->scallnr == NOTED) /* ugly hack */ | |
| 1991/0717 | noted(aur, *(ulong*)(sp+BY2WD)); /* doesn't return */ | |
| 1991/1114 | splhi(); | |
| 1992/06271 | if(u->scallnr!=RFORK && (u->p->procctl || u->nnote)){ | |
| 1990/03091 | ur->r0 = ret; notify(ur); } return ret; } | |
| 1991/1214 | long execregs(ulong entry, ulong ssize, ulong nargs) | |
| 1990/1226 | { | |
| 1991/1214 | ulong *sp; sp = (ulong*)(USTKTOP - ssize); *--sp = nargs; ((Ureg*)UREGADDR)->usp = (ulong)sp; | |
| 1990/1226 | ((Ureg*)UREGADDR)->pc = entry; | |
| 1991/1214 | return USTKTOP-BY2WD; /* address of user-level clock */ | |
| 1991/1112 | } | |
| 1992/0120 | ulong userpc(void) { return ((Ureg*)UREGADDR)->pc; } | |
| 1991/1112 | /* This routine must save the values of registers the user is not permitted to write * from devproc and the restore the saved values before returning */ void setregisters(Ureg *xp, char *pureg, char *uva, int n) { ushort sr; ulong magic; ushort vo; char microstate[UREGVARSZ]; sr = xp->sr; vo = xp->vo; magic = xp->magic; memmove(microstate, xp->microstate, UREGVARSZ); memmove(pureg, uva, n); xp->sr = (sr&0xff00) |(xp->sr&0xff); xp->vo = vo; xp->magic = magic; memmove(xp->microstate, microstate, UREGVARSZ); | |
| 1990/03091 | } | |