| plan 9 kernel history: overview | file list | diff list |
1991/0712/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 | 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) { | |
| 1991/01151 | int user, x; | |
| 1990/1223 | char buf[64]; | |
| 1990/1227 | ulong tbr; | |
| 1990/1223 | ||
| 1991/01151 | if(u) | |
| 1990/1223 | u->p->pc = ur->pc; /* BUG */ | |
| 1991/01151 | user = !(ur->psr&PSRPSUPER); tbr = (ur->tbr&0xFFF)>>4; if(tbr > 16){ /* interrupt */ if(u && u->p->state==Running){ if(u->p->fpstate == FPactive) { savefpregs(&u->fpsave); u->p->fpstate = FPinactive; ur->psr &= ~PSREF; } } switch(tbr-16){ case 15: /* asynch mem err */ faultasync(ur); break; case 14: /* counter 1 */ clock(ur); break; case 12: /* keyboard and mouse */ | |
| 1991/0604 | sccintr(); | |
| 1991/01151 | break; case 5: /* lance */ lanceintr(); break; default: goto Error; } | |
| 1990/1223 | }else{ | |
| 1991/01151 | switch(tbr){ case 1: /* instr. access */ case 9: /* data access */ if(u && u->p->fpstate==FPactive) { savefpregs(&u->fpsave); u->p->fpstate = FPinactive; ur->psr &= ~PSREF; } if(u){ x = u->p->insyscall; u->p->insyscall = 1; faultsparc(ur); u->p->insyscall = x; }else faultsparc(ur); goto Return; case 4: /* floating point disabled */ if(u && u->p){ if(u->p->fpstate == FPinit) restfpregs(&initfp); else if(u->p->fpstate == FPinactive) restfpregs(&u->fpsave); else break; u->p->fpstate = FPactive; ur->psr |= PSREF; return; } break; case 8: /* floating point exception */ clearfpintr(); break; default: break; } if(user){ spllo(); sprint(buf, "sys: trap: pc=0x%lux %s", ur->pc, excname(tbr)); if(tbr == 8) sprint(buf+strlen(buf), " FSR %lux", u->fpsave.fsr); postnote(u->p, 1, buf, NDebug); }else{ Error: print("kernel trap: %s pc=0x%lux\n", excname(tbr), ur->pc); dumpregs(ur); for(;;); } if(user && u->nnote) notify(ur); | |
| 1990/1223 | } | |
| 1991/01151 | Return: if(user && u && u->p->fpstate == FPinactive) { restfpregs(&u->fpsave); u->p->fpstate = FPactive; ur->psr |= PSREF; } | |
| 1990/1223 | } 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; | |
| 1991/0711 | int i; | |
| 1990/1223 | extern ulong etext; | |
| 1991/0711 | print("no dumpstack\n"); return; | |
| 1990/1223 | ||
| 1991/0711 | if(u){ i = 0; | |
| 1990/1223 | for(l=(ulong)&l; l<USERADDR+BY2PG; l+=4){ v = *(ulong*)l; if(KTZERO < v && v < (ulong)&etext) | |
| 1991/0711 | print("%lux=%lux ", l, v); ++i; if((i&7) == 0) print("\n"); | |
| 1990/1223 | } | |
| 1991/0711 | } | |
| 1990/1223 | } 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); | |
| 1991/0112 | if(u->nnote==0){ | |
| 1990/1223 | 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; | |
| 1991/0318 | memmove((Ureg*)sp, ur, sizeof(Ureg)); | |
| 1990/1223 | sp -= ERRLEN; | |
| 1991/0318 | memmove((char*)sp, u->note[0].msg, ERRLEN); | |
| 1990/1223 | 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; | |
| 1991/0112 | ur->npc = (ulong)u->notify+4; | |
| 1990/1223 | u->notified = 1; u->nnote--; | |
| 1991/0318 | memmove(&u->note[0], &u->note[1], u->nnote*sizeof(Note)); | |
| 1990/1223 | } 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; | |
| 1991/0318 | memmove(*urp, u->ureg, sizeof(Ureg)); | |
| 1991/0112 | (*urp)->r7 = -1; /* return error from the interrupted call */ | |
| 1990/1223 | unlock(&u->p->debug); splhi(); rfnote(urp); } #undef CHDIR /* BUG */ | |
| 1991/0710 | #include "/sys/src/libc/9syscall/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; | |
| 1991/0513 | Syscall sysbrk_, sysremove, syswstat, sysfwstat, sysnotify, sysnoted, sysalarm; | |
| 1990/1223 | Syscall *systab[]={ sysr1, syserrstr, sysbind, syschdir, sysclose, sysdup, | |
| 1991/0513 | sysalarm, | |
| 1990/1223 | 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) { | |
| 1991/0614 | int i; | |
| 1990/1223 | long ret; ulong sp; | |
| 1990/1226 | ulong r7; | |
| 1990/1223 | Ureg *ur; char *msg; ur = aur; | |
| 1991/0712 | if(ur->psr & PSRPSUPER) | |
| 1990/1223 | panic("recursive system call"); | |
| 1991/0711 | u->p->insyscall = 1; u->p->pc = ur->pc; | |
| 1991/01151 | ||
| 1990/1223 | /* * since the system call interface does not | |
| 1991/01151 | * guarantee anything about registers, | |
| 1990/1223 | */ | |
| 1991/01151 | if(u->p->fpstate == FPactive) { | |
| 1990/1223 | u->p->fpstate = FPinit; | |
| 1991/01151 | ur->psr &= ~PSREF; | |
| 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; | |
| 1991/0711 | } if(((ulong*)ur->pc)[-2] != 0x82206004){ /* new calling convention: look for ADD $-4, SP */ pprint("new system call linkage\n"); sp -= BY2WD; | |
| 1990/1223 | } | |
| 1991/0614 | if(sp<(USTKTOP-BY2PG) || sp>(USTKTOP-(2+MAXSYSARG)*BY2WD)) validaddr(sp, ((2+MAXSYSARG)*BY2WD), 0); | |
| 1990/1226 | ret = (*systab[r7])((ulong*)(sp+2*BY2WD)); | |
| 1991/0614 | poperror(); | |
| 1990/1223 | } | |
| 1990/1226 | ur->pc += 4; ur->npc = ur->pc+4; | |
| 1991/0614 | if(u->nerrlab){ | |
| 1991/0709 | print("bad error stack [%d]: %d extra\n", r7, u->nerrlab); | |
| 1991/0614 | for(i = 0; i < NERR; i++) print("sp=%lux pc=%lux\n", u->errlab[i].sp, u->errlab[i].pc); | |
| 1991/0709 | panic("error stack"); | |
| 1991/0614 | } | |
| 1990/1223 | 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 */ | |
| 1990/1223 | } | |