134408Skarels /* 234408Skarels * Copyright (c) 1988 Regents of the University of California. 334408Skarels * All rights reserved. The Berkeley software License Agreement 434408Skarels * specifies the terms and conditions for redistribution. 534408Skarels * 6*43643Skarels * @(#)trap.c 7.9 (Berkeley) 06/24/90 734408Skarels */ 824012Ssam 925678Ssam #include "param.h" 1025678Ssam #include "systm.h" 1125678Ssam #include "user.h" 1225678Ssam #include "proc.h" 1325678Ssam #include "seg.h" 1425678Ssam #include "acct.h" 1525678Ssam #include "kernel.h" 1634408Skarels 1734408Skarels #include "psl.h" 1834408Skarels #include "reg.h" 1934408Skarels #include "pte.h" 2034408Skarels #include "mtpr.h" 2138404Smarc #ifdef KTRACE 2238404Smarc #include "ktrace.h" 2324012Ssam #endif 2424012Ssam 2525678Ssam #include "../tahoe/trap.h" 2625678Ssam 2724012Ssam #define USER 040 /* user-mode flag added to type */ 2824012Ssam 2925678Ssam struct sysent sysent[]; 3025678Ssam int nsysent; 3124012Ssam 3225678Ssam char *trap_type[] = { 3325678Ssam "Reserved addressing mode", /* T_RESADFLT */ 3425678Ssam "Privileged instruction", /* T_PRIVINFLT */ 3525678Ssam "Reserved operand", /* T_RESOPFLT */ 3625678Ssam "Breakpoint", /* T_BPTFLT */ 3725678Ssam 0, 3825678Ssam "Kernel call", /* T_SYSCALL */ 3925678Ssam "Arithmetic trap", /* T_ARITHTRAP */ 4025678Ssam "System forced exception", /* T_ASTFLT */ 4125678Ssam "Segmentation fault", /* T_SEGFLT */ 4225678Ssam "Protection fault", /* T_PROTFLT */ 4325678Ssam "Trace trap", /* T_TRCTRAP */ 4425678Ssam 0, 4525678Ssam "Page fault", /* T_PAGEFLT */ 4625678Ssam "Page table fault", /* T_TABLEFLT */ 4725678Ssam "Alignment fault", /* T_ALIGNFLT */ 4825678Ssam "Kernel stack not valid", /* T_KSPNOTVAL */ 4925678Ssam "Bus error", /* T_BUSERR */ 5038935Skarels "Kernel debugger request", /* T_KDBTRAP */ 5125678Ssam }; 5230176Ssam int TRAP_TYPES = sizeof (trap_type) / sizeof (trap_type[0]); 5325678Ssam 5424012Ssam /* 5524012Ssam * Called from the trap handler when a processor trap occurs. 5624012Ssam */ 5725678Ssam /*ARGSUSED*/ 5824012Ssam trap(sp, type, hfs, accmst, acclst, dbl, code, pc, psl) 5938935Skarels unsigned type, code; /* kdb assumes these are *not* registers */ 6024012Ssam { 6125678Ssam int r0, r1; /* must reserve space */ 6224012Ssam register int *locr0 = ((int *)&psl)-PS; 6324012Ssam register int i; 6438935Skarels unsigned ucode = code; 6524012Ssam register struct proc *p; 6624012Ssam struct timeval syst; 6724012Ssam 6825678Ssam #ifdef lint 6925678Ssam r0 = 0; r0 = r0; r1 = 0; r1 = r1; 7025678Ssam #endif 7124012Ssam syst = u.u_ru.ru_stime; 7224012Ssam if (USERMODE(locr0[PS])) { 7324012Ssam type |= USER; 7424012Ssam u.u_ar0 = locr0; 7524012Ssam } 7624012Ssam switch (type) { 7724012Ssam 7825678Ssam default: 7934402Skarels #ifdef KADB 8030176Ssam if (kdb_trap(&psl)) 8130176Ssam return; 8230176Ssam #endif 8325678Ssam printf("trap type %d, code = %x, pc = %x\n", type, code, pc); 8425678Ssam type &= ~USER; 8525678Ssam if (type < TRAP_TYPES && trap_type[type]) 8625678Ssam panic(trap_type[type]); 8725678Ssam else 8825678Ssam panic("trap"); 8925678Ssam /*NOTREACHED*/ 9024012Ssam 9125678Ssam case T_PROTFLT + USER: /* protection fault */ 9224012Ssam i = SIGBUS; 9324012Ssam break; 9424012Ssam 9524012Ssam case T_PRIVINFLT + USER: /* privileged instruction fault */ 9625678Ssam case T_RESADFLT + USER: /* reserved addressing fault */ 9725678Ssam case T_RESOPFLT + USER: /* resereved operand fault */ 9825678Ssam case T_ALIGNFLT + USER: /* unaligned data fault */ 9938935Skarels ucode = type &~ USER; 10024012Ssam i = SIGILL; 10124012Ssam break; 10224012Ssam 10325678Ssam case T_ASTFLT + USER: /* Allow process switch */ 10424012Ssam case T_ASTFLT: 10524012Ssam astoff(); 10624012Ssam if ((u.u_procp->p_flag & SOWEUPC) && u.u_prof.pr_scale) { 10724012Ssam addupc(pc, &u.u_prof, 1); 10824012Ssam u.u_procp->p_flag &= ~SOWEUPC; 10924012Ssam } 11024012Ssam goto out; 11124012Ssam 11224012Ssam case T_ARITHTRAP + USER: 11324012Ssam i = SIGFPE; 11424012Ssam break; 11524012Ssam 11624012Ssam /* 11724012Ssam * If the user SP is above the stack segment, 11824012Ssam * grow the stack automatically. 11924012Ssam */ 12024012Ssam case T_SEGFLT + USER: 12124012Ssam if (grow((unsigned)locr0[SP]) || grow(code)) 12224012Ssam goto out; 12324012Ssam i = SIGSEGV; 12424012Ssam break; 12524012Ssam 12625678Ssam case T_TABLEFLT: /* allow page table faults in kernel */ 12725678Ssam case T_TABLEFLT + USER: /* page table fault */ 12824012Ssam panic("ptable fault"); 12924012Ssam 13025678Ssam case T_PAGEFLT: /* allow page faults in kernel mode */ 13125678Ssam case T_PAGEFLT + USER: /* page fault */ 13225678Ssam pagein(code, 0); 13324012Ssam if (type == T_PAGEFLT) 13424012Ssam return; 13524012Ssam goto out; 13624012Ssam 13725678Ssam case T_BPTFLT + USER: /* bpt instruction fault */ 13825678Ssam case T_TRCTRAP + USER: /* trace trap */ 13924012Ssam locr0[PS] &= ~PSL_T; 14024012Ssam i = SIGTRAP; 14124012Ssam break; 14225678Ssam 14338935Skarels #ifdef notdef 14438935Skarels /* THIS CODE IS BOGUS- delete? (KSP not valid is unrecoverable) 14538935Skarels And what does KSPNOTVAL in user-mode mean? */ 14625746Ssam /* 14725746Ssam * For T_KSPNOTVAL and T_BUSERR, can not allow spl to 14825746Ssam * drop to 0 as clock could go off and we would end up 14925746Ssam * doing an rei to the interrupt stack at ipl 0 (a 15025746Ssam * reserved operand fault). Instead, we allow psignal 15125746Ssam * to post an ast, then return to user mode where we 15225746Ssam * will reenter the kernel on the kernel's stack and 15325746Ssam * can then service the signal. 15425746Ssam */ 15524012Ssam case T_KSPNOTVAL: 15625746Ssam if (noproc) 15725746Ssam panic("ksp not valid"); 15825746Ssam /* fall thru... */ 15924012Ssam case T_KSPNOTVAL + USER: 16025772Ssam printf("pid %d: ksp not valid\n", u.u_procp->p_pid); 16138935Skarels panic("ksp not valid - 2"); 16225746Ssam /* must insure valid kernel stack pointer? */ 16325746Ssam psignal(u.u_procp, SIGKILL); 16425746Ssam return; 16538935Skarels #endif 16624012Ssam 16725678Ssam case T_BUSERR + USER: 16838935Skarels i = SIGBUS; 16938935Skarels break; 17024012Ssam } 17138935Skarels trapsignal(i, ucode); 17224012Ssam out: 17324012Ssam p = u.u_procp; 17440716Skarels if (i = CURSIG(p)) 17540716Skarels psig(i); 17624012Ssam p->p_pri = p->p_usrpri; 17724012Ssam if (runrun) { 17824012Ssam /* 17924012Ssam * Since we are u.u_procp, clock will normally just change 18024012Ssam * our priority without moving us from one queue to another 18124012Ssam * (since the running process is not on a queue.) 18224012Ssam * If that happened after we setrq ourselves but before we 18324012Ssam * swtch()'ed, we might not be on the queue indicated by 18424012Ssam * our priority. 18524012Ssam */ 18629561Ssam (void) splclock(); 18724012Ssam setrq(p); 18824012Ssam u.u_ru.ru_nivcsw++; 18924012Ssam swtch(); 19040716Skarels if (i = CURSIG(p)) 19140716Skarels psig(i); 19224012Ssam } 19324012Ssam if (u.u_prof.pr_scale) { 19424012Ssam int ticks; 19524012Ssam struct timeval *tv = &u.u_ru.ru_stime; 19624012Ssam 19724012Ssam ticks = ((tv->tv_sec - syst.tv_sec) * 1000 + 19824012Ssam (tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000); 19924012Ssam if (ticks) 20024012Ssam addupc(locr0[PC], &u.u_prof, ticks); 20124012Ssam } 20224012Ssam curpri = p->p_pri; 20324012Ssam } 20424012Ssam 20524012Ssam /* 20625678Ssam * Called from locore when a system call occurs 20724012Ssam */ 20825678Ssam /*ARGSUSED*/ 20924012Ssam syscall(sp, type, hfs, accmst, acclst, dbl, code, pc, psl) 21025678Ssam unsigned code; 21124012Ssam { 21225678Ssam int r0, r1; /* must reserve space */ 21324012Ssam register int *locr0 = ((int *)&psl)-PS; 21425678Ssam register caddr_t params; 21525678Ssam register int i; 21624012Ssam register struct sysent *callp; 21738404Smarc register struct proc *p = u.u_procp; 21825678Ssam struct timeval syst; 21940716Skarels int error, opc; 220*43643Skarels int args[8], rval[2]; 22124012Ssam 22225678Ssam #ifdef lint 22325678Ssam r0 = 0; r0 = r0; r1 = 0; r1 = r1; 22425678Ssam #endif 22524012Ssam syst = u.u_ru.ru_stime; 22624012Ssam if (!USERMODE(locr0[PS])) 22724012Ssam panic("syscall"); 22824012Ssam u.u_ar0 = locr0; 22924012Ssam params = (caddr_t)locr0[FP] + NBPW; 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 */ 245*43643Skarels if (code == 0) { /* indir */ 246*43643Skarels code = fuword(params); 24724012Ssam params += NBPW; 24824012Ssam } 249*43643Skarels if (code >= nsysent) 250*43643Skarels callp = &sysent[0]; /* indir (illegal) */ 251*43643Skarels else 252*43643Skarels callp = &sysent[code]; 25325678Ssam if ((i = callp->sy_narg * sizeof (int)) && 254*43643Skarels (error = copyin(params, (caddr_t)args, (u_int)i)) != 0) { 25540716Skarels locr0[R0] = error; 25625678Ssam locr0[PS] |= PSL_C; /* carry bit */ 25740669Smarc #ifdef KTRACE 25840669Smarc if (KTRPOINT(p, KTR_SYSCALL)) 259*43643Skarels ktrsyscall(p->p_tracep, code, callp->sy_narg, args); 26040669Smarc #endif 26125678Ssam goto done; 26224012Ssam } 26340669Smarc #ifdef KTRACE 26440669Smarc if (KTRPOINT(p, KTR_SYSCALL)) 265*43643Skarels ktrsyscall(p->p_tracep, code, callp->sy_narg, args); 26640669Smarc #endif 267*43643Skarels rval[0] = 0; 268*43643Skarels rval[1] = locr0[R1]; 269*43643Skarels error = (*callp->sy_call)(u.u_procp, args, rval); 27040716Skarels if (error == ERESTART) 27140716Skarels pc = opc; 27240716Skarels else if (error != EJUSTRETURN) { 27340716Skarels if (error) { 27440716Skarels locr0[R0] = error; 27525678Ssam locr0[PS] |= PSL_C; /* carry bit */ 27625678Ssam } else { 27725678Ssam locr0[PS] &= ~PSL_C; /* clear carry bit */ 278*43643Skarels locr0[R0] = rval[0]; 279*43643Skarels locr0[R1] = rval[1]; 28025678Ssam } 28140716Skarels } 28240716Skarels /* else if (error == EJUSTRETURN) */ 28325678Ssam /* nothing to do */ 28424012Ssam done: 28540669Smarc /* 28640669Smarc * Reinitialize proc pointer `p' as it may be different 28740669Smarc * if this is a child returning from fork syscall. 28840669Smarc */ 28924012Ssam p = u.u_procp; 29040716Skarels if (i = CURSIG(p)) 29140716Skarels psig(i); 29224012Ssam p->p_pri = p->p_usrpri; 29324012Ssam if (runrun) { 29424012Ssam /* 29524012Ssam * Since we are u.u_procp, clock will normally just change 29624012Ssam * our priority without moving us from one queue to another 29724012Ssam * (since the running process is not on a queue.) 29824012Ssam * If that happened after we setrq ourselves but before we 29924012Ssam * swtch()'ed, we might not be on the queue indicated by 30024012Ssam * our priority. 30124012Ssam */ 30229561Ssam (void) splclock(); 30324012Ssam setrq(p); 30424012Ssam u.u_ru.ru_nivcsw++; 30524012Ssam swtch(); 30640716Skarels if (i = CURSIG(p)) 30740716Skarels psig(i); 30824012Ssam } 30924012Ssam if (u.u_prof.pr_scale) { 31024012Ssam int ticks; 31124012Ssam struct timeval *tv = &u.u_ru.ru_stime; 31224012Ssam 31324012Ssam ticks = ((tv->tv_sec - syst.tv_sec) * 1000 + 31424012Ssam (tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000); 31524012Ssam if (ticks) 31624012Ssam addupc(locr0[PC], &u.u_prof, ticks); 31724012Ssam } 31824012Ssam curpri = p->p_pri; 31940669Smarc #ifdef KTRACE 32040669Smarc if (KTRPOINT(p, KTR_SYSRET)) 321*43643Skarels ktrsysret(p->p_tracep, code, error, rval[0]); 32240669Smarc #endif 32324012Ssam } 324