| plan 9 kernel history: overview | file list | diff list |
1991/0513/gnot/trap.c (diff list | history)
| gnot/trap.c on 1990/03091 | ||
| 1990/03091 | #include "u.h" #include "lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "ureg.h" #include "io.h" | |
| 1990/0513 | #include "errno.h" | |
| 1990/03091 | void notify(Ureg*); | |
| 1991/0503 | void noted(Ureg*); 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", "cptrapcc, trapcc, trapv instruction", "privilege violation", "trace", "line 1010 emulator", "line 1111 emulator", "reserved", "coprocessor protocol violation", "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", }; char* excname(unsigned vo) { static char buf[32]; /* BUG: not reentrant! */ vo &= 0x0FFF; vo >>= 2; if(vo < sizeof trapname/sizeof(char*)) return trapname[vo]; sprint(buf, "offset 0x%ux", vo<<2); return buf; } void trap(Ureg *ur) { int user; char buf[64]; user = !(ur->sr&SUPER); if(u) u->p->pc = ur->pc; /* BUG */ if(user){ | |
| 1990/1127 | sprint(buf, "sys: trap: pc=0x%lux %s", ur->pc, excname(ur->vo)); | |
| 1990/03091 | postnote(u->p, 1, buf, NDebug); }else{ | |
| 1990/1127 | print("kernel trap vo=0x%ux pc=0x%lux\n", ur->vo, ur->pc); | |
| 1990/03091 | dumpregs(ur); exit(); } if(user && u->nnote) notify(ur); } 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]); dumpstack(); } /* * Call user, if necessary, with note */ void notify(Ureg *ur) { ulong sp; lock(&u->p->debug); if(u->nnote==0){ unlock(&u->p->debug); return; } if(u->note[0].flag!=NUser && (u->notified || u->notify==0)){ if(u->note[0].flag == NDebug) pprint("suicide: %s\n", u->note[0].msg); Die: unlock(&u->p->debug); pexit(u->note[0].msg, u->note[0].flag!=NDebug); } if(!u->notified){ if(!u->notify) goto Die; | |
| 1991/0503 | u->svvo = ur->vo; u->svsr = ur->sr; | |
| 1990/0816 | sp = ur->usp; | |
| 1990/03091 | sp -= sizeof(Ureg); 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; u->notified = 1; u->nnote--; | |
| 1991/0318 | memmove(&u->note[0], &u->note[1], u->nnote*sizeof(Note)); | |
| 1990/03091 | } unlock(&u->p->debug); } /* * Return user to state before notify() */ void | |
| 1991/0503 | noted(Ureg *ur) | |
| 1990/03091 | { | |
| 1991/0503 | Ureg *nur; nur = u->ureg; validaddr(nur->pc, 1, 0); validaddr(nur->usp, BY2WD, 0); if(nur->sr!=u->svsr || nur->vo!=u->svvo){ pprint("bad noted ureg sr %ux vo %ux\n", nur->sr, nur->vo); pexit("Suicide", 0); } | |
| 1990/03091 | lock(&u->p->debug); | |
| 1990/0619 | if(!u->notified){ unlock(&u->p->debug); return; } | |
| 1990/03091 | u->notified = 0; | |
| 1991/0503 | memmove(ur, u->ureg, sizeof(Ureg)); | |
| 1990/03091 | unlock(&u->p->debug); splhi(); | |
| 1991/0503 | rfnote(ur); | |
| 1990/03091 | } #undef CHDIR /* BUG */ #include "/sys/src/libc/680209sys/sys.h" typedef long Syscall(ulong*); | |
| 1990/11211 | Syscall sysr1, sysfork, sysexec, sysgetpid, syssleep, sysexits, sysdeath, syswait; | |
| 1990/03091 | Syscall sysopen, sysclose, sysread, syswrite, sysseek, syserrstr, sysaccess, sysstat, sysfstat; | |
| 1990/11211 | Syscall sysdup, syschdir, sysforkpgrp, sysbind, sysmount, syspipe, syscreate; | |
| 1991/0513 | Syscall sysbrk_, sysremove, syswstat, sysfwstat, sysnotify, sysnoted, sysalarm; | |
| 1990/03091 | Syscall *systab[]={ sysr1, | |
| 1990/11211 | syserrstr, | |
| 1990/03091 | sysbind, syschdir, sysclose, sysdup, | |
| 1991/0513 | sysalarm, | |
| 1990/03091 | sysexec, sysexits, sysfork, sysforkpgrp, sysfstat, | |
| 1990/11211 | sysdeath, | |
| 1990/03091 | sysmount, sysopen, sysread, sysseek, syssleep, sysstat, syswait, syswrite, syspipe, syscreate, | |
| 1990/11211 | sysdeath, | |
| 1990/03091 | sysbrk_, sysremove, syswstat, sysfwstat, | |
| 1990/08141 | sysnotify, sysnoted, | |
| 1990/11211 | sysdeath, /* sysfilsys */ | |
| 1990/03091 | }; long syscall(Ureg *aur) { long ret; ulong sp; ulong r0; Ureg *ur; | |
| 1990/0513 | char *msg; | |
| 1990/03091 | u->p->insyscall = 1; ur = 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(); | |
| 1990/03091 | r0 = ur->r0; sp = ur->usp; u->nerrlab = 0; ret = -1; | |
| 1990/0511 | if(!waserror()){ | |
| 1990/0513 | if(r0 >= sizeof systab/BY2WD){ pprint("bad sys call number %d pc %lux\n", r0, ((Ureg*)UREGADDR)->pc); | |
| 1990/1110 | msg = "sys: bad sys call"; | |
| 1990/0511 | Bad: postnote(u->p, 1, msg, NDebug); | |
| 1990/11211 | error(Ebadarg); | |
| 1990/0511 | } if(sp & (BY2WD-1)){ pprint("odd sp in sys call pc %lux sp %lux\n", ((Ureg*)UREGADDR)->pc, ((Ureg*)UREGADDR)->sp); | |
| 1990/1110 | msg = "sys: odd stack"; | |
| 1990/0511 | goto Bad; } | |
| 1990/11211 | if(sp<(USTKTOP-BY2PG) || sp>(USTKTOP-5*BY2WD)) validaddr(sp, 5*BY2WD, 0); | |
| 1990/0515 | ret = (*systab[r0])((ulong*)(sp+BY2WD)); | |
| 1990/0511 | } | |
| 1990/03091 | u->nerrlab = 0; u->p->insyscall = 0; if(r0 == NOTED) /* ugly hack */ | |
| 1991/0503 | noted(aur); /* doesn't return */ | |
| 1990/03091 | if(u->nnote){ ur->r0 = ret; notify(ur); } return ret; } | |
| 1990/1226 | void execpc(ulong entry) { ((Ureg*)UREGADDR)->pc = entry; } | |
| 1990/11211 | #include "errstr.h" | |
| 1990/03091 | void | |
| 1990/11211 | error(int code) | |
| 1990/03091 | { | |
| 1991/0115 | strncpy(u->error, errstrtab[code], ERRLEN); | |
| 1990/03091 | nexterror(); } | |
| 1990/11211 | void errors(char *err) { | |
| 1991/0322 | strncpy(u->error, err, ERRLEN); | |
| 1990/11211 | nexterror(); } | |
| 1990/03091 | void nexterror(void) { gotolabel(&u->errlab[--u->nerrlab]); } | |