1*25746Ssam /* trap.c 1.3 86/01/07 */ 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 */ 4625678Ssam }; 4725678Ssam #define TRAP_TYPES (sizeof (trap_type) / sizeof (trap_type[0])) 4825678Ssam 4924012Ssam /* 5024012Ssam * Called from the trap handler when a processor trap occurs. 5124012Ssam */ 5225678Ssam /*ARGSUSED*/ 5324012Ssam trap(sp, type, hfs, accmst, acclst, dbl, code, pc, psl) 5425678Ssam unsigned type, code; 5524012Ssam { 5625678Ssam int r0, r1; /* must reserve space */ 5724012Ssam register int *locr0 = ((int *)&psl)-PS; 5824012Ssam register int i; 5924012Ssam register struct proc *p; 6024012Ssam struct timeval syst; 6124012Ssam 6225678Ssam #ifdef lint 6325678Ssam r0 = 0; r0 = r0; r1 = 0; r1 = r1; 6425678Ssam #endif 6524012Ssam syst = u.u_ru.ru_stime; 6624012Ssam if (USERMODE(locr0[PS])) { 6724012Ssam type |= USER; 6824012Ssam u.u_ar0 = locr0; 6924012Ssam } 7024012Ssam switch (type) { 7124012Ssam 7225678Ssam default: 7325678Ssam printf("trap type %d, code = %x, pc = %x\n", type, code, pc); 7425678Ssam type &= ~USER; 7525678Ssam if (type < TRAP_TYPES && trap_type[type]) 7625678Ssam panic(trap_type[type]); 7725678Ssam else 7825678Ssam panic("trap"); 7925678Ssam /*NOTREACHED*/ 8024012Ssam 8125678Ssam case T_PROTFLT + USER: /* protection fault */ 8224012Ssam i = SIGBUS; 8324012Ssam break; 8424012Ssam 8524012Ssam case T_PRIVINFLT + USER: /* privileged instruction fault */ 8625678Ssam case T_RESADFLT + USER: /* reserved addressing fault */ 8725678Ssam case T_RESOPFLT + USER: /* resereved operand fault */ 8825678Ssam case T_ALIGNFLT + USER: /* unaligned data fault */ 8924012Ssam u.u_code = type &~ USER; 9024012Ssam i = SIGILL; 9124012Ssam break; 9224012Ssam 9325678Ssam case T_ASTFLT + USER: /* Allow process switch */ 9424012Ssam case T_ASTFLT: 9524012Ssam astoff(); 9624012Ssam if ((u.u_procp->p_flag & SOWEUPC) && u.u_prof.pr_scale) { 9724012Ssam addupc(pc, &u.u_prof, 1); 9824012Ssam u.u_procp->p_flag &= ~SOWEUPC; 9924012Ssam } 10024012Ssam goto out; 10124012Ssam 10224012Ssam case T_ARITHTRAP + USER: 10324012Ssam u.u_code = code; 10424012Ssam i = SIGFPE; 10524012Ssam break; 10624012Ssam 10724012Ssam /* 10824012Ssam * If the user SP is above the stack segment, 10924012Ssam * grow the stack automatically. 11024012Ssam */ 11124012Ssam case T_SEGFLT + USER: 11224012Ssam if (grow((unsigned)locr0[SP]) || grow(code)) 11324012Ssam goto out; 11424012Ssam i = SIGSEGV; 11524012Ssam break; 11624012Ssam 11725678Ssam case T_TABLEFLT: /* allow page table faults in kernel */ 11825678Ssam case T_TABLEFLT + USER: /* page table fault */ 11924012Ssam panic("ptable fault"); 12024012Ssam 12125678Ssam case T_PAGEFLT: /* allow page faults in kernel mode */ 12225678Ssam case T_PAGEFLT + USER: /* page fault */ 12324012Ssam i = u.u_error; 12425678Ssam pagein(code, 0); 12524012Ssam u.u_error = i; 12624012Ssam if (type == T_PAGEFLT) 12724012Ssam return; 12824012Ssam goto out; 12924012Ssam 13025678Ssam case T_BPTFLT + USER: /* bpt instruction fault */ 13125678Ssam case T_TRCTRAP + USER: /* trace trap */ 13224012Ssam locr0[PS] &= ~PSL_T; 13324012Ssam i = SIGTRAP; 13424012Ssam break; 13525678Ssam 136*25746Ssam /* 137*25746Ssam * For T_KSPNOTVAL and T_BUSERR, can not allow spl to 138*25746Ssam * drop to 0 as clock could go off and we would end up 139*25746Ssam * doing an rei to the interrupt stack at ipl 0 (a 140*25746Ssam * reserved operand fault). Instead, we allow psignal 141*25746Ssam * to post an ast, then return to user mode where we 142*25746Ssam * will reenter the kernel on the kernel's stack and 143*25746Ssam * can then service the signal. 144*25746Ssam */ 14524012Ssam case T_KSPNOTVAL: 146*25746Ssam if (noproc) 147*25746Ssam panic("ksp not valid"); 148*25746Ssam /* fall thru... */ 14924012Ssam case T_KSPNOTVAL + USER: 150*25746Ssam printf("pid %d: ksp not valid\n", u.u._procp->p_pid); 151*25746Ssam /* must insure valid kernel stack pointer? */ 152*25746Ssam psignal(u.u_procp, SIGKILL); 153*25746Ssam return; 15424012Ssam 15525678Ssam case T_BUSERR + USER: 15625678Ssam u.u_code = code; 157*25746Ssam psignal(u.u_procp, SIGBUS); 158*25746Ssam return; 15924012Ssam } 16024012Ssam psignal(u.u_procp, i); 16124012Ssam out: 16224012Ssam p = u.u_procp; 16324012Ssam if (p->p_cursig || ISSIG(p)) 16424012Ssam psig(); 16524012Ssam p->p_pri = p->p_usrpri; 16624012Ssam if (runrun) { 16724012Ssam /* 16824012Ssam * Since we are u.u_procp, clock will normally just change 16924012Ssam * our priority without moving us from one queue to another 17024012Ssam * (since the running process is not on a queue.) 17124012Ssam * If that happened after we setrq ourselves but before we 17224012Ssam * swtch()'ed, we might not be on the queue indicated by 17324012Ssam * our priority. 17424012Ssam */ 17524012Ssam (void) spl8(); 17624012Ssam setrq(p); 17724012Ssam u.u_ru.ru_nivcsw++; 17824012Ssam swtch(); 17924012Ssam } 18024012Ssam if (u.u_prof.pr_scale) { 18124012Ssam int ticks; 18224012Ssam struct timeval *tv = &u.u_ru.ru_stime; 18324012Ssam 18424012Ssam ticks = ((tv->tv_sec - syst.tv_sec) * 1000 + 18524012Ssam (tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000); 18624012Ssam if (ticks) 18724012Ssam addupc(locr0[PC], &u.u_prof, ticks); 18824012Ssam } 18924012Ssam curpri = p->p_pri; 19024012Ssam } 19124012Ssam 19224012Ssam #ifdef SYSCALLTRACE 19325678Ssam int syscalltrace = 0; 19424012Ssam #endif 19524012Ssam 19624012Ssam /* 19725678Ssam * Called from locore when a system call occurs 19824012Ssam */ 19925678Ssam /*ARGSUSED*/ 20024012Ssam syscall(sp, type, hfs, accmst, acclst, dbl, code, pc, psl) 20125678Ssam unsigned code; 20224012Ssam { 20325678Ssam int r0, r1; /* must reserve space */ 20424012Ssam register int *locr0 = ((int *)&psl)-PS; 20525678Ssam register caddr_t params; 20625678Ssam register int i; 20724012Ssam register struct sysent *callp; 20824012Ssam register struct proc *p; 20925678Ssam struct timeval syst; 21024012Ssam int opc; 21124012Ssam 21225678Ssam #ifdef lint 21325678Ssam r0 = 0; r0 = r0; r1 = 0; r1 = r1; 21425678Ssam #endif 21524012Ssam syst = u.u_ru.ru_stime; 21624012Ssam if (!USERMODE(locr0[PS])) 21724012Ssam panic("syscall"); 21824012Ssam u.u_ar0 = locr0; 21925678Ssam if (code == 139) { /* 4.2 COMPATIBILTY XXX */ 22025678Ssam osigcleanup(); /* 4.2 COMPATIBILTY XXX */ 22125678Ssam goto done; /* 4.2 COMPATIBILTY XXX */ 22224012Ssam } 22324012Ssam params = (caddr_t)locr0[FP] + NBPW; 22424012Ssam u.u_error = 0; 22525678Ssam /* BEGIN GROT */ 22625678Ssam /* 22725678Ssam * Try to reconstruct pc, assuming code 22825678Ssam * is an immediate constant 22925678Ssam */ 23024012Ssam opc = pc - 2; /* short literal */ 23124012Ssam if (code > 0x3f) { 23225678Ssam opc--; /* byte immediate */ 23324012Ssam if (code > 0x7f) { 23425678Ssam opc--; /* word immediate */ 23524012Ssam if (code > 0x7fff) 23624012Ssam opc -= 2; /* long immediate */ 23724012Ssam } 23824012Ssam } 23925678Ssam /* END GROT */ 24024012Ssam callp = (code >= nsysent) ? &sysent[63] : &sysent[code]; 24124012Ssam if (callp == sysent) { 24224012Ssam i = fuword(params); 24324012Ssam params += NBPW; 24425678Ssam callp = (code >= nsysent) ? &sysent[63] : &sysent[code]; 24524012Ssam } 24625678Ssam if ((i = callp->sy_narg * sizeof (int)) && 24725678Ssam (u.u_error = copyin(params, (caddr_t)u.u_arg, (u_int)i)) != 0) { 24825678Ssam locr0[R0] = u.u_error; 24925678Ssam locr0[PS] |= PSL_C; /* carry bit */ 25025678Ssam goto done; 25124012Ssam } 25224012Ssam u.u_r.r_val1 = 0; 25325678Ssam u.u_r.r_val2 = locr0[R1]; 25424012Ssam if (setjmp(&u.u_qsave)) { 25525678Ssam if (u.u_error == 0 && u.u_eosys != RESTARTSYS) 25624012Ssam u.u_error = EINTR; 25724012Ssam } else { 25825678Ssam u.u_eosys = NORMALRETURN; 25924012Ssam #ifdef SYSCALLTRACE 26024012Ssam if (syscalltrace) { 26124012Ssam register int i; 26224012Ssam char *cp; 26324012Ssam 26424012Ssam if (code >= nsysent) 26524012Ssam printf("0x%x", code); 26624012Ssam else 26724012Ssam printf("%s", syscallnames[code]); 26824012Ssam cp = "("; 26924012Ssam for (i= 0; i < callp->sy_narg; i++) { 27024012Ssam printf("%s%x", cp, u.u_arg[i]); 27124012Ssam cp = ", "; 27224012Ssam } 27324012Ssam if (i) 27424012Ssam putchar(')', 0); 27524012Ssam putchar('\n', 0); 27624012Ssam } 27724012Ssam #endif 27825678Ssam (*callp->sy_call)(); 27924012Ssam } 28025678Ssam if (u.u_eosys == NORMALRETURN) { 28125678Ssam if (u.u_error) { 28225678Ssam locr0[R0] = u.u_error; 28325678Ssam locr0[PS] |= PSL_C; /* carry bit */ 28425678Ssam } else { 28525678Ssam locr0[PS] &= ~PSL_C; /* clear carry bit */ 28625678Ssam locr0[R0] = u.u_r.r_val1; 28725678Ssam locr0[R1] = u.u_r.r_val2; 28825678Ssam } 28925678Ssam } else if (u.u_eosys == RESTARTSYS) 29024012Ssam pc = opc; 29125678Ssam /* else if (u.u_eosys == JUSTRETURN) */ 29225678Ssam /* nothing to do */ 29324012Ssam done: 29424012Ssam p = u.u_procp; 29524012Ssam if (p->p_cursig || ISSIG(p)) 29624012Ssam psig(); 29724012Ssam p->p_pri = p->p_usrpri; 29824012Ssam if (runrun) { 29924012Ssam /* 30024012Ssam * Since we are u.u_procp, clock will normally just change 30124012Ssam * our priority without moving us from one queue to another 30224012Ssam * (since the running process is not on a queue.) 30324012Ssam * If that happened after we setrq ourselves but before we 30424012Ssam * swtch()'ed, we might not be on the queue indicated by 30524012Ssam * our priority. 30624012Ssam */ 30724012Ssam (void) spl8(); 30824012Ssam setrq(p); 30924012Ssam u.u_ru.ru_nivcsw++; 31024012Ssam swtch(); 31124012Ssam } 31224012Ssam if (u.u_prof.pr_scale) { 31324012Ssam int ticks; 31424012Ssam struct timeval *tv = &u.u_ru.ru_stime; 31524012Ssam 31624012Ssam ticks = ((tv->tv_sec - syst.tv_sec) * 1000 + 31724012Ssam (tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000); 31824012Ssam if (ticks) 31924012Ssam addupc(locr0[PC], &u.u_prof, ticks); 32024012Ssam } 32124012Ssam curpri = p->p_pri; 32224012Ssam } 32324012Ssam 32424012Ssam /* 32524012Ssam * nonexistent system call-- signal process (may want to handle it) 32624012Ssam * flag error if process won't see signal immediately 32724012Ssam * Q: should we do that all the time ?? 32824012Ssam */ 32924012Ssam nosys() 33024012Ssam { 33125678Ssam 33224012Ssam if (u.u_signal[SIGSYS] == SIG_IGN || u.u_signal[SIGSYS] == SIG_HOLD) 33324012Ssam u.u_error = EINVAL; 33424012Ssam psignal(u.u_procp, SIGSYS); 33524012Ssam } 33624012Ssam 33725678Ssam #ifdef notdef 33824012Ssam /* 33924012Ssam * Ignored system call 34024012Ssam */ 34124012Ssam nullsys() 34224012Ssam { 34324012Ssam 34424012Ssam } 34525678Ssam #endif 346