1*25678Ssam /* trap.c 1.2 86/01/05 */ 224012Ssam 3*25678Ssam #include "../tahoe/psl.h" 4*25678Ssam #include "../tahoe/reg.h" 5*25678Ssam #include "../tahoe/pte.h" 6*25678Ssam #include "../tahoe/mtpr.h" 724012Ssam 8*25678Ssam #include "param.h" 9*25678Ssam #include "systm.h" 10*25678Ssam #include "dir.h" 11*25678Ssam #include "user.h" 12*25678Ssam #include "proc.h" 13*25678Ssam #include "seg.h" 14*25678Ssam #include "acct.h" 15*25678Ssam #include "kernel.h" 16*25678Ssam #define SYSCALLTRACE 1724012Ssam #ifdef SYSCALLTRACE 1824012Ssam #include "../sys/syscalls.c" 1924012Ssam #endif 2024012Ssam 21*25678Ssam #include "../tahoe/trap.h" 22*25678Ssam 2324012Ssam #define USER 040 /* user-mode flag added to type */ 2424012Ssam 25*25678Ssam struct sysent sysent[]; 26*25678Ssam int nsysent; 2724012Ssam 28*25678Ssam char *trap_type[] = { 29*25678Ssam "Reserved addressing mode", /* T_RESADFLT */ 30*25678Ssam "Privileged instruction", /* T_PRIVINFLT */ 31*25678Ssam "Reserved operand", /* T_RESOPFLT */ 32*25678Ssam "Breakpoint", /* T_BPTFLT */ 33*25678Ssam 0, 34*25678Ssam "Kernel call", /* T_SYSCALL */ 35*25678Ssam "Arithmetic trap", /* T_ARITHTRAP */ 36*25678Ssam "System forced exception", /* T_ASTFLT */ 37*25678Ssam "Segmentation fault", /* T_SEGFLT */ 38*25678Ssam "Protection fault", /* T_PROTFLT */ 39*25678Ssam "Trace trap", /* T_TRCTRAP */ 40*25678Ssam 0, 41*25678Ssam "Page fault", /* T_PAGEFLT */ 42*25678Ssam "Page table fault", /* T_TABLEFLT */ 43*25678Ssam "Alignment fault", /* T_ALIGNFLT */ 44*25678Ssam "Kernel stack not valid", /* T_KSPNOTVAL */ 45*25678Ssam "Bus error", /* T_BUSERR */ 46*25678Ssam }; 47*25678Ssam #define TRAP_TYPES (sizeof (trap_type) / sizeof (trap_type[0])) 48*25678Ssam 4924012Ssam /* 5024012Ssam * Called from the trap handler when a processor trap occurs. 5124012Ssam */ 52*25678Ssam /*ARGSUSED*/ 5324012Ssam trap(sp, type, hfs, accmst, acclst, dbl, code, pc, psl) 54*25678Ssam unsigned type, code; 5524012Ssam { 56*25678Ssam 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 62*25678Ssam #ifdef lint 63*25678Ssam r0 = 0; r0 = r0; r1 = 0; r1 = r1; 64*25678Ssam #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 72*25678Ssam default: 73*25678Ssam printf("trap type %d, code = %x, pc = %x\n", type, code, pc); 74*25678Ssam type &= ~USER; 75*25678Ssam if (type < TRAP_TYPES && trap_type[type]) 76*25678Ssam panic(trap_type[type]); 77*25678Ssam else 78*25678Ssam panic("trap"); 79*25678Ssam /*NOTREACHED*/ 8024012Ssam 81*25678Ssam case T_PROTFLT + USER: /* protection fault */ 8224012Ssam i = SIGBUS; 8324012Ssam break; 8424012Ssam 8524012Ssam case T_PRIVINFLT + USER: /* privileged instruction fault */ 86*25678Ssam case T_RESADFLT + USER: /* reserved addressing fault */ 87*25678Ssam case T_RESOPFLT + USER: /* resereved operand fault */ 88*25678Ssam case T_ALIGNFLT + USER: /* unaligned data fault */ 8924012Ssam u.u_code = type &~ USER; 9024012Ssam i = SIGILL; 9124012Ssam break; 9224012Ssam 93*25678Ssam 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 117*25678Ssam case T_TABLEFLT: /* allow page table faults in kernel */ 118*25678Ssam case T_TABLEFLT + USER: /* page table fault */ 11924012Ssam panic("ptable fault"); 12024012Ssam 121*25678Ssam case T_PAGEFLT: /* allow page faults in kernel mode */ 122*25678Ssam case T_PAGEFLT + USER: /* page fault */ 12324012Ssam i = u.u_error; 124*25678Ssam pagein(code, 0); 12524012Ssam u.u_error = i; 12624012Ssam if (type == T_PAGEFLT) 12724012Ssam return; 12824012Ssam goto out; 12924012Ssam 130*25678Ssam case T_BPTFLT + USER: /* bpt instruction fault */ 131*25678Ssam case T_TRCTRAP + USER: /* trace trap */ 13224012Ssam locr0[PS] &= ~PSL_T; 13324012Ssam i = SIGTRAP; 13424012Ssam break; 135*25678Ssam 13624012Ssam case T_KSPNOTVAL: 13724012Ssam case T_KSPNOTVAL + USER: 13824012Ssam i = SIGKILL; /* There is nothing to do but to kill the 13924012Ssam * process.. */ 14024012Ssam printf("KSP NOT VALID.\n"); 14124012Ssam break; 14224012Ssam 143*25678Ssam case T_BUSERR + USER: 144*25678Ssam i = SIGBUS; 145*25678Ssam u.u_code = code; 146*25678Ssam break; 14724012Ssam } 14824012Ssam psignal(u.u_procp, i); 14924012Ssam out: 15024012Ssam p = u.u_procp; 15124012Ssam if (p->p_cursig || ISSIG(p)) 15224012Ssam psig(); 15324012Ssam p->p_pri = p->p_usrpri; 15424012Ssam if (runrun) { 15524012Ssam /* 15624012Ssam * Since we are u.u_procp, clock will normally just change 15724012Ssam * our priority without moving us from one queue to another 15824012Ssam * (since the running process is not on a queue.) 15924012Ssam * If that happened after we setrq ourselves but before we 16024012Ssam * swtch()'ed, we might not be on the queue indicated by 16124012Ssam * our priority. 16224012Ssam */ 16324012Ssam (void) spl8(); 16424012Ssam setrq(p); 16524012Ssam u.u_ru.ru_nivcsw++; 16624012Ssam swtch(); 16724012Ssam } 16824012Ssam if (u.u_prof.pr_scale) { 16924012Ssam int ticks; 17024012Ssam struct timeval *tv = &u.u_ru.ru_stime; 17124012Ssam 17224012Ssam ticks = ((tv->tv_sec - syst.tv_sec) * 1000 + 17324012Ssam (tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000); 17424012Ssam if (ticks) 17524012Ssam addupc(locr0[PC], &u.u_prof, ticks); 17624012Ssam } 17724012Ssam curpri = p->p_pri; 17824012Ssam } 17924012Ssam 18024012Ssam #ifdef SYSCALLTRACE 181*25678Ssam int syscalltrace = 0; 18224012Ssam #endif 18324012Ssam 18424012Ssam /* 185*25678Ssam * Called from locore when a system call occurs 18624012Ssam */ 187*25678Ssam /*ARGSUSED*/ 18824012Ssam syscall(sp, type, hfs, accmst, acclst, dbl, code, pc, psl) 189*25678Ssam unsigned code; 19024012Ssam { 191*25678Ssam int r0, r1; /* must reserve space */ 19224012Ssam register int *locr0 = ((int *)&psl)-PS; 193*25678Ssam register caddr_t params; 194*25678Ssam register int i; 19524012Ssam register struct sysent *callp; 19624012Ssam register struct proc *p; 197*25678Ssam struct timeval syst; 19824012Ssam int opc; 19924012Ssam 200*25678Ssam #ifdef lint 201*25678Ssam r0 = 0; r0 = r0; r1 = 0; r1 = r1; 202*25678Ssam #endif 20324012Ssam syst = u.u_ru.ru_stime; 20424012Ssam if (!USERMODE(locr0[PS])) 20524012Ssam panic("syscall"); 20624012Ssam u.u_ar0 = locr0; 207*25678Ssam if (code == 139) { /* 4.2 COMPATIBILTY XXX */ 208*25678Ssam osigcleanup(); /* 4.2 COMPATIBILTY XXX */ 209*25678Ssam goto done; /* 4.2 COMPATIBILTY XXX */ 21024012Ssam } 21124012Ssam params = (caddr_t)locr0[FP] + NBPW; 21224012Ssam u.u_error = 0; 213*25678Ssam /* BEGIN GROT */ 214*25678Ssam /* 215*25678Ssam * Try to reconstruct pc, assuming code 216*25678Ssam * is an immediate constant 217*25678Ssam */ 21824012Ssam opc = pc - 2; /* short literal */ 21924012Ssam if (code > 0x3f) { 220*25678Ssam opc--; /* byte immediate */ 22124012Ssam if (code > 0x7f) { 222*25678Ssam opc--; /* word immediate */ 22324012Ssam if (code > 0x7fff) 22424012Ssam opc -= 2; /* long immediate */ 22524012Ssam } 22624012Ssam } 227*25678Ssam /* END GROT */ 22824012Ssam callp = (code >= nsysent) ? &sysent[63] : &sysent[code]; 22924012Ssam if (callp == sysent) { 23024012Ssam i = fuword(params); 23124012Ssam params += NBPW; 232*25678Ssam callp = (code >= nsysent) ? &sysent[63] : &sysent[code]; 23324012Ssam } 234*25678Ssam if ((i = callp->sy_narg * sizeof (int)) && 235*25678Ssam (u.u_error = copyin(params, (caddr_t)u.u_arg, (u_int)i)) != 0) { 236*25678Ssam locr0[R0] = u.u_error; 237*25678Ssam locr0[PS] |= PSL_C; /* carry bit */ 238*25678Ssam goto done; 23924012Ssam } 24024012Ssam u.u_r.r_val1 = 0; 241*25678Ssam u.u_r.r_val2 = locr0[R1]; 24224012Ssam if (setjmp(&u.u_qsave)) { 243*25678Ssam if (u.u_error == 0 && u.u_eosys != RESTARTSYS) 24424012Ssam u.u_error = EINTR; 24524012Ssam } else { 246*25678Ssam u.u_eosys = NORMALRETURN; 24724012Ssam #ifdef SYSCALLTRACE 24824012Ssam if (syscalltrace) { 24924012Ssam register int i; 25024012Ssam char *cp; 25124012Ssam 25224012Ssam if (code >= nsysent) 25324012Ssam printf("0x%x", code); 25424012Ssam else 25524012Ssam printf("%s", syscallnames[code]); 25624012Ssam cp = "("; 25724012Ssam for (i= 0; i < callp->sy_narg; i++) { 25824012Ssam printf("%s%x", cp, u.u_arg[i]); 25924012Ssam cp = ", "; 26024012Ssam } 26124012Ssam if (i) 26224012Ssam putchar(')', 0); 26324012Ssam putchar('\n', 0); 26424012Ssam } 26524012Ssam #endif 266*25678Ssam (*callp->sy_call)(); 26724012Ssam } 268*25678Ssam if (u.u_eosys == NORMALRETURN) { 269*25678Ssam if (u.u_error) { 270*25678Ssam locr0[R0] = u.u_error; 271*25678Ssam locr0[PS] |= PSL_C; /* carry bit */ 272*25678Ssam } else { 273*25678Ssam locr0[PS] &= ~PSL_C; /* clear carry bit */ 274*25678Ssam locr0[R0] = u.u_r.r_val1; 275*25678Ssam locr0[R1] = u.u_r.r_val2; 276*25678Ssam } 277*25678Ssam } else if (u.u_eosys == RESTARTSYS) 27824012Ssam pc = opc; 279*25678Ssam /* else if (u.u_eosys == JUSTRETURN) */ 280*25678Ssam /* nothing to do */ 28124012Ssam done: 28224012Ssam p = u.u_procp; 28324012Ssam if (p->p_cursig || ISSIG(p)) 28424012Ssam psig(); 28524012Ssam p->p_pri = p->p_usrpri; 28624012Ssam if (runrun) { 28724012Ssam /* 28824012Ssam * Since we are u.u_procp, clock will normally just change 28924012Ssam * our priority without moving us from one queue to another 29024012Ssam * (since the running process is not on a queue.) 29124012Ssam * If that happened after we setrq ourselves but before we 29224012Ssam * swtch()'ed, we might not be on the queue indicated by 29324012Ssam * our priority. 29424012Ssam */ 29524012Ssam (void) spl8(); 29624012Ssam setrq(p); 29724012Ssam u.u_ru.ru_nivcsw++; 29824012Ssam swtch(); 29924012Ssam } 30024012Ssam if (u.u_prof.pr_scale) { 30124012Ssam int ticks; 30224012Ssam struct timeval *tv = &u.u_ru.ru_stime; 30324012Ssam 30424012Ssam ticks = ((tv->tv_sec - syst.tv_sec) * 1000 + 30524012Ssam (tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000); 30624012Ssam if (ticks) 30724012Ssam addupc(locr0[PC], &u.u_prof, ticks); 30824012Ssam } 30924012Ssam curpri = p->p_pri; 31024012Ssam } 31124012Ssam 31224012Ssam /* 31324012Ssam * nonexistent system call-- signal process (may want to handle it) 31424012Ssam * flag error if process won't see signal immediately 31524012Ssam * Q: should we do that all the time ?? 31624012Ssam */ 31724012Ssam nosys() 31824012Ssam { 319*25678Ssam 32024012Ssam if (u.u_signal[SIGSYS] == SIG_IGN || u.u_signal[SIGSYS] == SIG_HOLD) 32124012Ssam u.u_error = EINVAL; 32224012Ssam psignal(u.u_procp, SIGSYS); 32324012Ssam } 32424012Ssam 325*25678Ssam #ifdef notdef 32624012Ssam /* 32724012Ssam * Ignored system call 32824012Ssam */ 32924012Ssam nullsys() 33024012Ssam { 33124012Ssam 33224012Ssam } 333*25678Ssam #endif 334