1*34402Skarels /* trap.c 1.8 88/05/21 */ 224012Ssam 325678Ssam #include "../tahoe/psl.h" 425678Ssam #include "../tahoe/reg.h" 525678Ssam #include "../tahoe/pte.h" 625678Ssam #include "../tahoe/mtpr.h" 724012Ssam 825678Ssam #include "param.h" 925678Ssam #include "systm.h" 1025678Ssam #include "dir.h" 1125678Ssam #include "user.h" 1225678Ssam #include "proc.h" 1325678Ssam #include "seg.h" 1425678Ssam #include "acct.h" 1525678Ssam #include "kernel.h" 1625678Ssam #define SYSCALLTRACE 1724012Ssam #ifdef SYSCALLTRACE 1824012Ssam #include "../sys/syscalls.c" 1924012Ssam #endif 2024012Ssam 2125678Ssam #include "../tahoe/trap.h" 2225678Ssam 2324012Ssam #define USER 040 /* user-mode flag added to type */ 2424012Ssam 2525678Ssam struct sysent sysent[]; 2625678Ssam int nsysent; 2724012Ssam 2825678Ssam char *trap_type[] = { 2925678Ssam "Reserved addressing mode", /* T_RESADFLT */ 3025678Ssam "Privileged instruction", /* T_PRIVINFLT */ 3125678Ssam "Reserved operand", /* T_RESOPFLT */ 3225678Ssam "Breakpoint", /* T_BPTFLT */ 3325678Ssam 0, 3425678Ssam "Kernel call", /* T_SYSCALL */ 3525678Ssam "Arithmetic trap", /* T_ARITHTRAP */ 3625678Ssam "System forced exception", /* T_ASTFLT */ 3725678Ssam "Segmentation fault", /* T_SEGFLT */ 3825678Ssam "Protection fault", /* T_PROTFLT */ 3925678Ssam "Trace trap", /* T_TRCTRAP */ 4025678Ssam 0, 4125678Ssam "Page fault", /* T_PAGEFLT */ 4225678Ssam "Page table fault", /* T_TABLEFLT */ 4325678Ssam "Alignment fault", /* T_ALIGNFLT */ 4425678Ssam "Kernel stack not valid", /* T_KSPNOTVAL */ 4525678Ssam "Bus error", /* T_BUSERR */ 4630176Ssam "Kernel debugger trap", /* T_KDBTRAP */ 4725678Ssam }; 4830176Ssam int TRAP_TYPES = sizeof (trap_type) / sizeof (trap_type[0]); 4925678Ssam 5024012Ssam /* 5124012Ssam * Called from the trap handler when a processor trap occurs. 5224012Ssam */ 5325678Ssam /*ARGSUSED*/ 5424012Ssam trap(sp, type, hfs, accmst, acclst, dbl, code, pc, psl) 5525678Ssam unsigned type, code; 5624012Ssam { 5725678Ssam int r0, r1; /* must reserve space */ 5824012Ssam register int *locr0 = ((int *)&psl)-PS; 5924012Ssam register int i; 6024012Ssam register struct proc *p; 6124012Ssam struct timeval syst; 6224012Ssam 6325678Ssam #ifdef lint 6425678Ssam r0 = 0; r0 = r0; r1 = 0; r1 = r1; 6525678Ssam #endif 6624012Ssam syst = u.u_ru.ru_stime; 6724012Ssam if (USERMODE(locr0[PS])) { 6824012Ssam type |= USER; 6924012Ssam u.u_ar0 = locr0; 7024012Ssam } 7124012Ssam switch (type) { 7224012Ssam 7325678Ssam default: 74*34402Skarels #ifdef KADB 7530176Ssam if (kdb_trap(&psl)) 7630176Ssam return; 7730176Ssam #endif 7825678Ssam printf("trap type %d, code = %x, pc = %x\n", type, code, pc); 7925678Ssam type &= ~USER; 8025678Ssam if (type < TRAP_TYPES && trap_type[type]) 8125678Ssam panic(trap_type[type]); 8225678Ssam else 8325678Ssam panic("trap"); 8425678Ssam /*NOTREACHED*/ 8524012Ssam 8625678Ssam case T_PROTFLT + USER: /* protection fault */ 8724012Ssam i = SIGBUS; 8824012Ssam break; 8924012Ssam 9024012Ssam case T_PRIVINFLT + USER: /* privileged instruction fault */ 9125678Ssam case T_RESADFLT + USER: /* reserved addressing fault */ 9225678Ssam case T_RESOPFLT + USER: /* resereved operand fault */ 9325678Ssam case T_ALIGNFLT + USER: /* unaligned data fault */ 9424012Ssam u.u_code = type &~ USER; 9524012Ssam i = SIGILL; 9624012Ssam break; 9724012Ssam 9825678Ssam case T_ASTFLT + USER: /* Allow process switch */ 9924012Ssam case T_ASTFLT: 10024012Ssam astoff(); 10124012Ssam if ((u.u_procp->p_flag & SOWEUPC) && u.u_prof.pr_scale) { 10224012Ssam addupc(pc, &u.u_prof, 1); 10324012Ssam u.u_procp->p_flag &= ~SOWEUPC; 10424012Ssam } 10524012Ssam goto out; 10624012Ssam 10724012Ssam case T_ARITHTRAP + USER: 10824012Ssam u.u_code = code; 10924012Ssam i = SIGFPE; 11024012Ssam break; 11124012Ssam 11224012Ssam /* 11324012Ssam * If the user SP is above the stack segment, 11424012Ssam * grow the stack automatically. 11524012Ssam */ 11624012Ssam case T_SEGFLT + USER: 11724012Ssam if (grow((unsigned)locr0[SP]) || grow(code)) 11824012Ssam goto out; 11924012Ssam i = SIGSEGV; 12024012Ssam break; 12124012Ssam 12225678Ssam case T_TABLEFLT: /* allow page table faults in kernel */ 12325678Ssam case T_TABLEFLT + USER: /* page table fault */ 12424012Ssam panic("ptable fault"); 12524012Ssam 12625678Ssam case T_PAGEFLT: /* allow page faults in kernel mode */ 12725678Ssam case T_PAGEFLT + USER: /* page fault */ 12824012Ssam i = u.u_error; 12925678Ssam pagein(code, 0); 13024012Ssam u.u_error = i; 13124012Ssam if (type == T_PAGEFLT) 13224012Ssam return; 13324012Ssam goto out; 13424012Ssam 13525678Ssam case T_BPTFLT + USER: /* bpt instruction fault */ 13625678Ssam case T_TRCTRAP + USER: /* trace trap */ 13724012Ssam locr0[PS] &= ~PSL_T; 13824012Ssam i = SIGTRAP; 13924012Ssam break; 14025678Ssam 14125746Ssam /* 14225746Ssam * For T_KSPNOTVAL and T_BUSERR, can not allow spl to 14325746Ssam * drop to 0 as clock could go off and we would end up 14425746Ssam * doing an rei to the interrupt stack at ipl 0 (a 14525746Ssam * reserved operand fault). Instead, we allow psignal 14625746Ssam * to post an ast, then return to user mode where we 14725746Ssam * will reenter the kernel on the kernel's stack and 14825746Ssam * can then service the signal. 14925746Ssam */ 15024012Ssam case T_KSPNOTVAL: 15125746Ssam if (noproc) 15225746Ssam panic("ksp not valid"); 15325746Ssam /* fall thru... */ 15424012Ssam case T_KSPNOTVAL + USER: 15525772Ssam printf("pid %d: ksp not valid\n", u.u_procp->p_pid); 15625746Ssam /* must insure valid kernel stack pointer? */ 15725746Ssam psignal(u.u_procp, SIGKILL); 15825746Ssam return; 15924012Ssam 16025678Ssam case T_BUSERR + USER: 16125678Ssam u.u_code = code; 16225746Ssam psignal(u.u_procp, SIGBUS); 16325746Ssam return; 16424012Ssam } 16524012Ssam psignal(u.u_procp, i); 16624012Ssam out: 16724012Ssam p = u.u_procp; 16824012Ssam if (p->p_cursig || ISSIG(p)) 16924012Ssam psig(); 17024012Ssam p->p_pri = p->p_usrpri; 17124012Ssam if (runrun) { 17224012Ssam /* 17324012Ssam * Since we are u.u_procp, clock will normally just change 17424012Ssam * our priority without moving us from one queue to another 17524012Ssam * (since the running process is not on a queue.) 17624012Ssam * If that happened after we setrq ourselves but before we 17724012Ssam * swtch()'ed, we might not be on the queue indicated by 17824012Ssam * our priority. 17924012Ssam */ 18029561Ssam (void) splclock(); 18124012Ssam setrq(p); 18224012Ssam u.u_ru.ru_nivcsw++; 18324012Ssam swtch(); 18424012Ssam } 18524012Ssam if (u.u_prof.pr_scale) { 18624012Ssam int ticks; 18724012Ssam struct timeval *tv = &u.u_ru.ru_stime; 18824012Ssam 18924012Ssam ticks = ((tv->tv_sec - syst.tv_sec) * 1000 + 19024012Ssam (tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000); 19124012Ssam if (ticks) 19224012Ssam addupc(locr0[PC], &u.u_prof, ticks); 19324012Ssam } 19424012Ssam curpri = p->p_pri; 19524012Ssam } 19624012Ssam 19724012Ssam #ifdef SYSCALLTRACE 19825678Ssam int syscalltrace = 0; 19924012Ssam #endif 20024012Ssam 20124012Ssam /* 20225678Ssam * Called from locore when a system call occurs 20324012Ssam */ 20425678Ssam /*ARGSUSED*/ 20524012Ssam syscall(sp, type, hfs, accmst, acclst, dbl, code, pc, psl) 20625678Ssam unsigned code; 20724012Ssam { 20825678Ssam int r0, r1; /* must reserve space */ 20924012Ssam register int *locr0 = ((int *)&psl)-PS; 21025678Ssam register caddr_t params; 21125678Ssam register int i; 21224012Ssam register struct sysent *callp; 21324012Ssam register struct proc *p; 21425678Ssam struct timeval syst; 21524012Ssam int opc; 21624012Ssam 21725678Ssam #ifdef lint 21825678Ssam r0 = 0; r0 = r0; r1 = 0; r1 = r1; 21925678Ssam #endif 22024012Ssam syst = u.u_ru.ru_stime; 22124012Ssam if (!USERMODE(locr0[PS])) 22224012Ssam panic("syscall"); 22324012Ssam u.u_ar0 = locr0; 22425678Ssam if (code == 139) { /* 4.2 COMPATIBILTY XXX */ 22525678Ssam osigcleanup(); /* 4.2 COMPATIBILTY XXX */ 22625678Ssam goto done; /* 4.2 COMPATIBILTY XXX */ 22724012Ssam } 22824012Ssam params = (caddr_t)locr0[FP] + NBPW; 22924012Ssam u.u_error = 0; 23025678Ssam /* BEGIN GROT */ 23125678Ssam /* 23225678Ssam * Try to reconstruct pc, assuming code 23325678Ssam * is an immediate constant 23425678Ssam */ 23524012Ssam opc = pc - 2; /* short literal */ 23624012Ssam if (code > 0x3f) { 23725678Ssam opc--; /* byte immediate */ 23824012Ssam if (code > 0x7f) { 23925678Ssam opc--; /* word immediate */ 24024012Ssam if (code > 0x7fff) 24124012Ssam opc -= 2; /* long immediate */ 24224012Ssam } 24324012Ssam } 24425678Ssam /* END GROT */ 24524012Ssam callp = (code >= nsysent) ? &sysent[63] : &sysent[code]; 24624012Ssam if (callp == sysent) { 24724012Ssam i = fuword(params); 24824012Ssam params += NBPW; 24925678Ssam callp = (code >= nsysent) ? &sysent[63] : &sysent[code]; 25024012Ssam } 25125678Ssam if ((i = callp->sy_narg * sizeof (int)) && 25225678Ssam (u.u_error = copyin(params, (caddr_t)u.u_arg, (u_int)i)) != 0) { 25325678Ssam locr0[R0] = u.u_error; 25425678Ssam locr0[PS] |= PSL_C; /* carry bit */ 25525678Ssam goto done; 25624012Ssam } 25724012Ssam u.u_r.r_val1 = 0; 25825678Ssam u.u_r.r_val2 = locr0[R1]; 25924012Ssam if (setjmp(&u.u_qsave)) { 26025678Ssam if (u.u_error == 0 && u.u_eosys != RESTARTSYS) 26124012Ssam u.u_error = EINTR; 26224012Ssam } else { 26325678Ssam u.u_eosys = NORMALRETURN; 26424012Ssam #ifdef SYSCALLTRACE 26524012Ssam if (syscalltrace) { 26630297Ssam register int a; 26724012Ssam char *cp; 26824012Ssam 26924012Ssam if (code >= nsysent) 27024012Ssam printf("0x%x", code); 27124012Ssam else 27224012Ssam printf("%s", syscallnames[code]); 27324012Ssam cp = "("; 27430297Ssam for (a = 0; a < callp->sy_narg; a++) { 27530297Ssam printf("%s%x", cp, u.u_arg[a]); 27624012Ssam cp = ", "; 27724012Ssam } 27830297Ssam if (a) 27930297Ssam printf(")"); 28030297Ssam printf("\n"); 28124012Ssam } 28224012Ssam #endif 28325678Ssam (*callp->sy_call)(); 28424012Ssam } 28525678Ssam if (u.u_eosys == NORMALRETURN) { 28625678Ssam if (u.u_error) { 28725678Ssam locr0[R0] = u.u_error; 28825678Ssam locr0[PS] |= PSL_C; /* carry bit */ 28925678Ssam } else { 29025678Ssam locr0[PS] &= ~PSL_C; /* clear carry bit */ 29125678Ssam locr0[R0] = u.u_r.r_val1; 29225678Ssam locr0[R1] = u.u_r.r_val2; 29325678Ssam } 29425678Ssam } else if (u.u_eosys == RESTARTSYS) 29524012Ssam pc = opc; 29625678Ssam /* else if (u.u_eosys == JUSTRETURN) */ 29725678Ssam /* nothing to do */ 29824012Ssam done: 29924012Ssam p = u.u_procp; 30024012Ssam if (p->p_cursig || ISSIG(p)) 30124012Ssam psig(); 30224012Ssam p->p_pri = p->p_usrpri; 30324012Ssam if (runrun) { 30424012Ssam /* 30524012Ssam * Since we are u.u_procp, clock will normally just change 30624012Ssam * our priority without moving us from one queue to another 30724012Ssam * (since the running process is not on a queue.) 30824012Ssam * If that happened after we setrq ourselves but before we 30924012Ssam * swtch()'ed, we might not be on the queue indicated by 31024012Ssam * our priority. 31124012Ssam */ 31229561Ssam (void) splclock(); 31324012Ssam setrq(p); 31424012Ssam u.u_ru.ru_nivcsw++; 31524012Ssam swtch(); 31624012Ssam } 31724012Ssam if (u.u_prof.pr_scale) { 31824012Ssam int ticks; 31924012Ssam struct timeval *tv = &u.u_ru.ru_stime; 32024012Ssam 32124012Ssam ticks = ((tv->tv_sec - syst.tv_sec) * 1000 + 32224012Ssam (tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000); 32324012Ssam if (ticks) 32424012Ssam addupc(locr0[PC], &u.u_prof, ticks); 32524012Ssam } 32624012Ssam curpri = p->p_pri; 32724012Ssam } 32824012Ssam 32924012Ssam /* 33024012Ssam * nonexistent system call-- signal process (may want to handle it) 33124012Ssam * flag error if process won't see signal immediately 33224012Ssam * Q: should we do that all the time ?? 33324012Ssam */ 33424012Ssam nosys() 33524012Ssam { 33625678Ssam 33724012Ssam if (u.u_signal[SIGSYS] == SIG_IGN || u.u_signal[SIGSYS] == SIG_HOLD) 33824012Ssam u.u_error = EINVAL; 33924012Ssam psignal(u.u_procp, SIGSYS); 34024012Ssam } 34124012Ssam 34225678Ssam #ifdef notdef 34324012Ssam /* 34424012Ssam * Ignored system call 34524012Ssam */ 34624012Ssam nullsys() 34724012Ssam { 34824012Ssam 34924012Ssam } 35025678Ssam #endif 351