| plan 9 kernel history: overview | file list | diff list |
1990/1226/ss/trap.c (diff list | history)
| ss/trap.c on 1990/1223 | ||
| 1990/1223 | #include "u.h" #include "lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "ureg.h" #include "io.h" #include "errno.h" void notify(Ureg*); void noted(Ureg**); void rfnote(Ureg**); | |
| 1990/1226 | extern void traplink(void); extern void syslink(void); | |
| 1990/1223 | long ticks; char *trapname[]={ | |
| 1990/1226 | "reset", "instruction access exception", | |
| 1990/1223 | "illegal instruction", | |
| 1990/1226 | "privileged instruction", "fp disabled", "window overflow", "window underflow", "unaligned address", "fp exception", "data access exception", "tag overflow", | |
| 1990/1223 | }; char* | |
| 1990/1226 | excname(ulong tbr) | |
| 1990/1223 | { static char buf[32]; /* BUG: not reentrant! */ | |
| 1990/1226 | tbr &= 0xFFF; tbr >>= 4; if(tbr < sizeof trapname/sizeof(char*)) return trapname[tbr]; if(tbr == 36) return "cp disabled"; if(tbr == 40) return "cp exception"; if(tbr >= 128) sprint(buf, "trap instruction %d", tbr-128); else if(17<=tbr && tbr<=31) sprint(buf, "interrupt level %d", tbr-16); else sprint(buf, "unknown trap %d", tbr); | |
| 1990/1223 | return buf; } void trap(Ureg *ur) { int user; char buf[64]; | |
| 1990/1226 | user = !(ur->psr&PSRPSUPER); /* if(u) | |
| 1990/1223 | u->p->pc = ur->pc; /* BUG */ if(user){ | |
| 1990/1226 | print("user trap: %s pc=0x%lux\n", excname(ur->tbr), ur->pc); dumpregs(ur); for(;;); sprint(buf, "sys: trap: pc=0x%lux %s", ur->pc, excname(ur->tbr)); | |
| 1990/1223 | postnote(u->p, 1, buf, NDebug); }else{ | |
| 1990/1226 | print("kernel trap: %s pc=0x%lux\n", excname(ur->tbr), ur->pc); | |
| 1990/1223 | dumpregs(ur); | |
| 1990/1226 | for(;;); | |
| 1990/1223 | exit(); } if(user && u->nnote) notify(ur); } void | |
| 1990/1226 | trapinit(void) { int i; long t, a; a = ((ulong)traplink-TRAPS)>>2; a += 0x40000000; /* CALL traplink(SB) */ t = TRAPS; for(i=0; i<256; i++){ *(ulong*)t = a; /* CALL traplink(SB) */ *(ulong*)(t+4) = 0xa7480000; /* MOVW PSR, R19 */ a -= 16/4; t += 16; } /* * Vector 128 goes directly to syslink */ t = TRAPS+128*16; a = ((ulong)syslink-t)>>2; a += 0x40000000; *(ulong*)t = a; /* CALL syscall(SB) */ *(ulong*)(t+4) = 0xa7480000; /* MOVW PSR, R19 */ puttbr(TRAPS); } void | |
| 1990/1223 | 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"); | |
| 1990/1226 | print("PSR=%ux PC=%lux TBR=%lux\n", ur->psr, ur->pc, ur->tbr); | |
| 1990/1223 | l = &ur->r0; | |
| 1990/1226 | for(i=0; i<32; i+=2, l+=2) print("R%d\t%.8lux\tR%d\t%.8lux\n", i, l[0], i+1, l[1]); | |
| 1990/1223 | 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; sp = ur->usp; sp -= sizeof(Ureg); u->ureg = (void*)sp; memcpy((Ureg*)sp, ur, sizeof(Ureg)); sp -= ERRLEN; memcpy((char*)sp, u->note[0].msg, ERRLEN); 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 */ ur->usp = sp; ur->pc = (ulong)u->notify; u->notified = 1; u->nnote--; memcpy(&u->note[0], &u->note[1], u->nnote*sizeof(Note)); } unlock(&u->p->debug); } /* * Return user to state before notify() */ void noted(Ureg **urp) { lock(&u->p->debug); if(!u->notified){ unlock(&u->p->debug); return; } u->notified = 0; memcpy(*urp, u->ureg, sizeof(Ureg)); unlock(&u->p->debug); splhi(); rfnote(urp); } #undef CHDIR /* BUG */ | |
| 1990/1226 | #include "/sys/src/libc/sparc9sys/sys.h" | |
| 1990/1223 | typedef long Syscall(ulong*); Syscall sysr1, sysfork, sysexec, sysgetpid, syssleep, sysexits, sysdeath, syswait; Syscall sysopen, sysclose, sysread, syswrite, sysseek, syserrstr, sysaccess, sysstat, sysfstat; Syscall sysdup, syschdir, sysforkpgrp, sysbind, sysmount, syspipe, syscreate; Syscall sysbrk_, sysremove, syswstat, sysfwstat, sysnotify, sysnoted; Syscall *systab[]={ sysr1, syserrstr, sysbind, syschdir, sysclose, sysdup, sysdeath, sysexec, sysexits, sysfork, sysforkpgrp, sysfstat, sysdeath, sysmount, sysopen, sysread, sysseek, syssleep, sysstat, syswait, syswrite, syspipe, syscreate, sysdeath, sysbrk_, sysremove, syswstat, sysfwstat, sysnotify, sysnoted, sysdeath, /* sysfilsys */ }; long syscall(Ureg *aur) { long ret; ulong sp; | |
| 1990/1226 | ulong r7; | |
| 1990/1223 | Ureg *ur; char *msg; u->p->insyscall = 1; ur = aur; u->p->pc = ur->pc; | |
| 1990/1226 | if(ur->psr & PSRPSUPER) | |
| 1990/1223 | panic("recursive system call"); | |
| 1990/1226 | #ifdef asdf | |
| 1990/1223 | /* * since the system call interface does not * guarantee anything about registers, but the fpcr is more than * just a register... BUG */ fpsave(&u->fpsave); if(u->p->fpstate==FPactive || u->fpsave.type){ fprestore(&initfp); u->p->fpstate = FPinit; m->fpstate = FPinit; } | |
| 1990/1226 | #endif | |
| 1990/1223 | spllo(); | |
| 1990/1226 | r7 = ur->r7; | |
| 1990/1223 | sp = ur->usp; u->nerrlab = 0; ret = -1; if(!waserror()){ | |
| 1990/1226 | if(r7 >= sizeof systab/BY2WD){ pprint("bad sys call number %d pc %lux\n", r7, ((Ureg*)UREGADDR)->pc); | |
| 1990/1223 | msg = "sys: bad sys call"; Bad: postnote(u->p, 1, msg, NDebug); error(Ebadarg); } if(sp & (BY2WD-1)){ pprint("odd sp in sys call pc %lux sp %lux\n", ((Ureg*)UREGADDR)->pc, ((Ureg*)UREGADDR)->sp); msg = "sys: odd stack"; goto Bad; } if(sp<(USTKTOP-BY2PG) || sp>(USTKTOP-5*BY2WD)) validaddr(sp, 5*BY2WD, 0); | |
| 1990/1226 | ret = (*systab[r7])((ulong*)(sp+2*BY2WD)); | |
| 1990/1223 | } | |
| 1990/1226 | ur->pc += 4; ur->npc = ur->pc+4; | |
| 1990/1223 | u->nerrlab = 0; u->p->insyscall = 0; | |
| 1990/1226 | if(r7 == NOTED) /* ugly hack */ | |
| 1990/1223 | noted(&aur); /* doesn't return */ if(u->nnote){ | |
| 1990/1226 | ur->r7 = ret; | |
| 1990/1223 | notify(ur); } return ret; | |
| 1990/1226 | } void execpc(ulong entry) { ((Ureg*)UREGADDR)->pc = entry - 4; /* syscall advances it */ ((Ureg*)UREGADDR)->npc = entry; | |
| 1990/1223 | } #include "errstr.h" void error(int code) { strncpy(u->error, errstrtab[code], NAMELEN); nexterror(); } void errors(char *err) { strncpy(u->error, err, NAMELEN); nexterror(); } void nexterror(void) { gotolabel(&u->errlab[--u->nerrlab]); } | |