1*24012Ssam /* trap.c 4.10 84/02/09 */ 2*24012Ssam 3*24012Ssam #include "../machine/psl.h" 4*24012Ssam #include "../machine/reg.h" 5*24012Ssam #include "../machine/pte.h" 6*24012Ssam 7*24012Ssam #include "../h/param.h" 8*24012Ssam #include "../h/systm.h" 9*24012Ssam #include "../h/dir.h" 10*24012Ssam #include "../h/user.h" 11*24012Ssam #include "../h/proc.h" 12*24012Ssam #include "../h/seg.h" 13*24012Ssam #include "../machine/trap.h" 14*24012Ssam #include "../h/acct.h" 15*24012Ssam #include "../h/kernel.h" 16*24012Ssam #include "../machine/mtpr.h" 17*24012Ssam #ifdef SYSCALLTRACE 18*24012Ssam #include "../sys/syscalls.c" 19*24012Ssam #endif 20*24012Ssam #include "../machine/fp_in_krnl.h" 21*24012Ssam 22*24012Ssam #define USER 040 /* user-mode flag added to type */ 23*24012Ssam 24*24012Ssam struct sysent sysent[]; 25*24012Ssam int nsysent; 26*24012Ssam 27*24012Ssam /* 28*24012Ssam * Called from the trap handler when a processor trap occurs. 29*24012Ssam */ 30*24012Ssam trap(sp, type, hfs, accmst, acclst, dbl, code, pc, psl) 31*24012Ssam unsigned code; 32*24012Ssam { 33*24012Ssam /* Next 2 dummy variables MUST BE the first local */ 34*24012Ssam /* variables; leaving place for registers 0 and 1 */ 35*24012Ssam /* which are not preserved by the 'cct' */ 36*24012Ssam 37*24012Ssam int dumm1; /* register 1 */ 38*24012Ssam int dumm0; /* register 0 */ 39*24012Ssam register dumm3; /* register 12 is the 1'st register variable */ 40*24012Ssam /* in TAHOE (register 11 in VAX) */ 41*24012Ssam 42*24012Ssam register int *locr0 = ((int *)&psl)-PS; 43*24012Ssam register int i; 44*24012Ssam register struct proc *p; 45*24012Ssam struct timeval syst; 46*24012Ssam char *typename; 47*24012Ssam 48*24012Ssam syst = u.u_ru.ru_stime; 49*24012Ssam if (USERMODE(locr0[PS])) { 50*24012Ssam type |= USER; 51*24012Ssam u.u_ar0 = locr0; 52*24012Ssam } 53*24012Ssam switch (type) { 54*24012Ssam 55*24012Ssam default: switch (type) { 56*24012Ssam case T_RESADFLT: 57*24012Ssam typename = "reserved addressing mode";break; 58*24012Ssam case T_PRIVINFLT: 59*24012Ssam typename = "illegal opcode";break; 60*24012Ssam case T_RESOPFLT: 61*24012Ssam typename = "reserved operand";break; 62*24012Ssam case T_BPTFLT: 63*24012Ssam typename = "breakpoint";break; 64*24012Ssam case T_SYSCALL: 65*24012Ssam typename = "kernel call";break; 66*24012Ssam case T_ARITHTRAP: 67*24012Ssam typename = "arithmetic exception";break; 68*24012Ssam case T_ASTFLT: 69*24012Ssam typename = "system forced exception";break; 70*24012Ssam case T_SEGFLT: 71*24012Ssam typename = "limit fault";break; 72*24012Ssam case T_PROTFLT: 73*24012Ssam typename = "illegal access type";break; 74*24012Ssam case T_TRCTRAP: 75*24012Ssam typename = "trace trap";break; 76*24012Ssam case T_PAGEFLT: 77*24012Ssam typename = "page fault";break; 78*24012Ssam case T_TABLEFLT: 79*24012Ssam typename = "page table fault";break; 80*24012Ssam case T_ALIGNFLT: 81*24012Ssam typename = "alignment fault";break; 82*24012Ssam case T_KSPNOTVAL: 83*24012Ssam typename = "kernel stack not valid";break; 84*24012Ssam } 85*24012Ssam printf("System trap (%s), code = %x, pc = %x\n", 86*24012Ssam typename, code, pc); 87*24012Ssam panic("trap"); 88*24012Ssam 89*24012Ssam case T_PROTFLT + USER: /* protection fault */ 90*24012Ssam i = SIGBUS; 91*24012Ssam break; 92*24012Ssam 93*24012Ssam case T_PRIVINFLT + USER: /* privileged instruction fault */ 94*24012Ssam case T_RESADFLT + USER: /* reserved addressing fault */ 95*24012Ssam case T_RESOPFLT + USER: /* resereved operand fault */ 96*24012Ssam case T_ALIGNFLT + USER: /* unaligned data fault */ 97*24012Ssam u.u_code = type &~ USER; 98*24012Ssam i = SIGILL; 99*24012Ssam break; 100*24012Ssam 101*24012Ssam case T_ASTFLT + USER: /* Allow process switch */ 102*24012Ssam case T_ASTFLT: 103*24012Ssam astoff(); 104*24012Ssam if ((u.u_procp->p_flag & SOWEUPC) && u.u_prof.pr_scale) { 105*24012Ssam addupc(pc, &u.u_prof, 1); 106*24012Ssam u.u_procp->p_flag &= ~SOWEUPC; 107*24012Ssam } 108*24012Ssam goto out; 109*24012Ssam 110*24012Ssam case T_ARITHTRAP + USER: 111*24012Ssam u.u_code = code; 112*24012Ssam i = SIGFPE; 113*24012Ssam break; 114*24012Ssam 115*24012Ssam /* 116*24012Ssam * If the user SP is above the stack segment, 117*24012Ssam * grow the stack automatically. 118*24012Ssam */ 119*24012Ssam case T_SEGFLT + USER: 120*24012Ssam if (grow((unsigned)locr0[SP]) || grow(code)) 121*24012Ssam goto out; 122*24012Ssam i = SIGSEGV; 123*24012Ssam break; 124*24012Ssam 125*24012Ssam case T_TABLEFLT: /* allow page table faults in kernel mode */ 126*24012Ssam case T_TABLEFLT + USER: /* page table fault */ 127*24012Ssam panic("ptable fault"); 128*24012Ssam 129*24012Ssam case T_PAGEFLT: /* allow page faults in kernel mode */ 130*24012Ssam case T_PAGEFLT + USER: /* page fault */ 131*24012Ssam i = u.u_error; 132*24012Ssam if(fastreclaim(code) == 0) 133*24012Ssam pagein(code, 0); 134*24012Ssam u.u_error = i; 135*24012Ssam if (type == T_PAGEFLT) 136*24012Ssam return; 137*24012Ssam goto out; 138*24012Ssam 139*24012Ssam case T_BPTFLT + USER: /* bpt instruction fault */ 140*24012Ssam case T_TRCTRAP + USER: /* trace trap */ 141*24012Ssam locr0[PS] &= ~PSL_T; 142*24012Ssam i = SIGTRAP; 143*24012Ssam break; 144*24012Ssam case T_KSPNOTVAL: 145*24012Ssam case T_KSPNOTVAL + USER: 146*24012Ssam i = SIGKILL; /* There is nothing to do but to kill the 147*24012Ssam * process.. */ 148*24012Ssam printf("KSP NOT VALID.\n"); 149*24012Ssam break; 150*24012Ssam 151*24012Ssam } 152*24012Ssam psignal(u.u_procp, i); 153*24012Ssam out: 154*24012Ssam p = u.u_procp; 155*24012Ssam if (p->p_cursig || ISSIG(p)) 156*24012Ssam psig(); 157*24012Ssam p->p_pri = p->p_usrpri; 158*24012Ssam if (runrun) { 159*24012Ssam /* 160*24012Ssam * Since we are u.u_procp, clock will normally just change 161*24012Ssam * our priority without moving us from one queue to another 162*24012Ssam * (since the running process is not on a queue.) 163*24012Ssam * If that happened after we setrq ourselves but before we 164*24012Ssam * swtch()'ed, we might not be on the queue indicated by 165*24012Ssam * our priority. 166*24012Ssam */ 167*24012Ssam (void) spl8(); 168*24012Ssam setrq(p); 169*24012Ssam u.u_ru.ru_nivcsw++; 170*24012Ssam swtch(); 171*24012Ssam } 172*24012Ssam if (u.u_prof.pr_scale) { 173*24012Ssam int ticks; 174*24012Ssam struct timeval *tv = &u.u_ru.ru_stime; 175*24012Ssam 176*24012Ssam ticks = ((tv->tv_sec - syst.tv_sec) * 1000 + 177*24012Ssam (tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000); 178*24012Ssam if (ticks) 179*24012Ssam addupc(locr0[PC], &u.u_prof, ticks); 180*24012Ssam } 181*24012Ssam curpri = p->p_pri; 182*24012Ssam } 183*24012Ssam 184*24012Ssam #ifdef SYSCALLTRACE 185*24012Ssam int syscalltrace = 0; 186*24012Ssam #endif 187*24012Ssam 188*24012Ssam /* 189*24012Ssam * Called from the trap handler when a system call occurs 190*24012Ssam */ 191*24012Ssam syscall(sp, type, hfs, accmst, acclst, dbl, code, pc, psl) 192*24012Ssam unsigned code; 193*24012Ssam { 194*24012Ssam /* Next 2 dummy variables MUST BE the first local */ 195*24012Ssam /* variables; leaving place for registers 0 and 1 */ 196*24012Ssam /* which are not preserved by the 'cct' */ 197*24012Ssam 198*24012Ssam int dumm1; /* register 1 */ 199*24012Ssam int dumm0; /* register 0 */ 200*24012Ssam register dumm3; /* register 12 is the 1'st register variable */ 201*24012Ssam /* in TAHOE (register 11 in VAX) */ 202*24012Ssam 203*24012Ssam register int *locr0 = ((int *)&psl)-PS; 204*24012Ssam register caddr_t params; /* known to be r10 below */ 205*24012Ssam register int i; /* known to be r9 below */ 206*24012Ssam register struct sysent *callp; 207*24012Ssam register struct proc *p; 208*24012Ssam struct timeval syst; 209*24012Ssam int opc; 210*24012Ssam 211*24012Ssam syst = u.u_ru.ru_stime; 212*24012Ssam if (!USERMODE(locr0[PS])) 213*24012Ssam panic("syscall"); 214*24012Ssam u.u_ar0 = locr0; 215*24012Ssam if (code == 139) { /* XXX */ 216*24012Ssam sigcleanup(); /* XXX */ 217*24012Ssam goto done; /* XXX */ 218*24012Ssam } 219*24012Ssam params = (caddr_t)locr0[FP] + NBPW; 220*24012Ssam u.u_error = 0; 221*24012Ssam /*------ DIRTY CODE !!!!!!!!!---------*/ 222*24012Ssam /* try to reconstruct pc, assuming code is an immediate constant */ 223*24012Ssam opc = pc - 2; /* short literal */ 224*24012Ssam if (code > 0x3f) { 225*24012Ssam opc--; /* byte immediate */ 226*24012Ssam if (code > 0x7f) { 227*24012Ssam opc--; /* word immediate */ 228*24012Ssam if (code > 0x7fff) 229*24012Ssam opc -= 2; /* long immediate */ 230*24012Ssam } 231*24012Ssam } 232*24012Ssam /*------------------------------------*/ 233*24012Ssam callp = (code >= nsysent) ? &sysent[63] : &sysent[code]; 234*24012Ssam if (callp == sysent) { 235*24012Ssam i = fuword(params); 236*24012Ssam params += NBPW; 237*24012Ssam callp = (code >= nsysent) ? &sysent[63] : &sysent[code]; 238*24012Ssam } 239*24012Ssam if (i = callp->sy_narg * sizeof (int)) { 240*24012Ssam asm("prober $1,(r10),r9"); /* GROT */ 241*24012Ssam asm("bnequ ok"); /* GROT */ 242*24012Ssam u.u_error = EFAULT; /* GROT */ 243*24012Ssam goto bad; /* GROT */ 244*24012Ssam asm("ok:"); /* GROT */ 245*24012Ssam bcopy(params,u.u_arg,i); 246*24012Ssam } 247*24012Ssam u.u_ap = u.u_arg; 248*24012Ssam u.u_dirp = (caddr_t)u.u_arg[0]; 249*24012Ssam u.u_r.r_val1 = 0; 250*24012Ssam u.u_r.r_val2 = locr0[R1]; /*------------ CHECK again */ 251*24012Ssam if (setjmp(&u.u_qsave)) { 252*24012Ssam if (u.u_error == 0 && u.u_eosys == JUSTRETURN) 253*24012Ssam u.u_error = EINTR; 254*24012Ssam } else { 255*24012Ssam u.u_eosys = JUSTRETURN; 256*24012Ssam #ifdef SYSCALLTRACE 257*24012Ssam if (syscalltrace) { 258*24012Ssam register int i; 259*24012Ssam char *cp; 260*24012Ssam 261*24012Ssam if (code >= nsysent) 262*24012Ssam printf("0x%x", code); 263*24012Ssam else 264*24012Ssam printf("%s", syscallnames[code]); 265*24012Ssam cp = "("; 266*24012Ssam for (i= 0; i < callp->sy_narg; i++) { 267*24012Ssam printf("%s%x", cp, u.u_arg[i]); 268*24012Ssam cp = ", "; 269*24012Ssam } 270*24012Ssam if (i) 271*24012Ssam putchar(')', 0); 272*24012Ssam putchar('\n', 0); 273*24012Ssam } 274*24012Ssam #endif 275*24012Ssam 276*24012Ssam (*(callp->sy_call))(); 277*24012Ssam } 278*24012Ssam if (u.u_eosys == RESTARTSYS) 279*24012Ssam pc = opc; 280*24012Ssam else if (u.u_error) { 281*24012Ssam bad: 282*24012Ssam locr0[R0] = u.u_error; 283*24012Ssam locr0[PS] |= PSL_C; /* carry bit */ 284*24012Ssam } else { 285*24012Ssam locr0[PS] &= ~PSL_C; /* clear carry bit */ 286*24012Ssam locr0[R0] = u.u_r.r_val1; 287*24012Ssam locr0[R1] = u.u_r.r_val2; 288*24012Ssam } 289*24012Ssam done: 290*24012Ssam p = u.u_procp; 291*24012Ssam if (p->p_cursig || ISSIG(p)) 292*24012Ssam psig(); 293*24012Ssam p->p_pri = p->p_usrpri; 294*24012Ssam if (runrun) { 295*24012Ssam /* 296*24012Ssam * Since we are u.u_procp, clock will normally just change 297*24012Ssam * our priority without moving us from one queue to another 298*24012Ssam * (since the running process is not on a queue.) 299*24012Ssam * If that happened after we setrq ourselves but before we 300*24012Ssam * swtch()'ed, we might not be on the queue indicated by 301*24012Ssam * our priority. 302*24012Ssam */ 303*24012Ssam (void) spl8(); 304*24012Ssam setrq(p); 305*24012Ssam u.u_ru.ru_nivcsw++; 306*24012Ssam swtch(); 307*24012Ssam } 308*24012Ssam if (u.u_prof.pr_scale) { 309*24012Ssam int ticks; 310*24012Ssam struct timeval *tv = &u.u_ru.ru_stime; 311*24012Ssam 312*24012Ssam ticks = ((tv->tv_sec - syst.tv_sec) * 1000 + 313*24012Ssam (tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000); 314*24012Ssam if (ticks) 315*24012Ssam addupc(locr0[PC], &u.u_prof, ticks); 316*24012Ssam } 317*24012Ssam curpri = p->p_pri; 318*24012Ssam } 319*24012Ssam 320*24012Ssam /* 321*24012Ssam * nonexistent system call-- signal process (may want to handle it) 322*24012Ssam * flag error if process won't see signal immediately 323*24012Ssam * Q: should we do that all the time ?? 324*24012Ssam */ 325*24012Ssam nosys() 326*24012Ssam { 327*24012Ssam if (u.u_signal[SIGSYS] == SIG_IGN || u.u_signal[SIGSYS] == SIG_HOLD) 328*24012Ssam u.u_error = EINVAL; 329*24012Ssam psignal(u.u_procp, SIGSYS); 330*24012Ssam } 331*24012Ssam 332*24012Ssam /* 333*24012Ssam * Ignored system call 334*24012Ssam */ 335*24012Ssam nullsys() 336*24012Ssam { 337*24012Ssam 338*24012Ssam } 339*24012Ssam 340*24012Ssam fpemulate(hfsreg,acc_most,acc_least,dbl,op_most,op_least,opcode,pc,psl) 341*24012Ssam { 342*24012Ssam /* 343*24012Ssam * Emulate the F.P. 'opcode'. Update psl flags as necessary. 344*24012Ssam * If all OK, set 'opcode' to 0, else to the F.P. exception #. 345*24012Ssam * Not all parameter longwords are relevant - depends on opcode. 346*24012Ssam * 347*24012Ssam * The entry mask is set so ALL registers are saved - courtesy of 348*24012Ssam * locore.s. This enables F.P. opcodes to change 'user' registers 349*24012Ssam * before return. 350*24012Ssam */ 351*24012Ssam 352*24012Ssam /* WARNING!!!! THIS CODE MUST NOT PRODUCE ANY FLOATING POINT EXCEPTIONS. */ 353*24012Ssam 354*24012Ssam /* Next 2 dummy variables MUST BE the first local */ 355*24012Ssam /* variables; leaving place for registers 0 and 1 */ 356*24012Ssam /* which are not preserved by the 'cct' */ 357*24012Ssam 358*24012Ssam int dumm1; /* register 1 */ 359*24012Ssam int dumm0; /* register 0 */ 360*24012Ssam register dumm3; /* register 12 is the 1'st register variable */ 361*24012Ssam /* in TAHOE (register 11 in VAX) */ 362*24012Ssam 363*24012Ssam register int *locr0 = ((int *)&psl)-PS; /* R11 */ 364*24012Ssam int hfs = 0; /* returned data about exceptions */ 365*24012Ssam float (*f_proc)(); /* fp procedure to be called. */ 366*24012Ssam double (*d_proc)(); /* fp procedure to be called. */ 367*24012Ssam int dest_type; /* float or double. */ 368*24012Ssam union{ 369*24012Ssam float ff; /* float result. */ 370*24012Ssam int fi; 371*24012Ssam }f_res; 372*24012Ssam union{ 373*24012Ssam double dd; /* double result. */ 374*24012Ssam int di[2] ; 375*24012Ssam }d_res; 376*24012Ssam extern float Kcvtlf(), Kaddf(), Ksubf(), Kmulf(), Kdivf(); 377*24012Ssam extern double Kcvtld(), Kaddd(), Ksubd(), Kmuld(), Kdivd(); 378*24012Ssam extern float Ksinf(), Kcosf(), Katanf(), Klogf(), Ksqrtf(), Kexpf(); 379*24012Ssam 380*24012Ssam 381*24012Ssam 382*24012Ssam switch(opcode & 0x0FF){ 383*24012Ssam 384*24012Ssam case CVLF: f_proc = Kcvtlf; dest_type = FLOAT; 385*24012Ssam locr0[PS] &= ~PSL_DBL;break; /* clear double bit */ 386*24012Ssam case CVLD: d_proc = Kcvtld; dest_type = DOUBLE; 387*24012Ssam locr0[PS] |= PSL_DBL; break; /* turn on double bit */ 388*24012Ssam case ADDF: f_proc = Kaddf; dest_type = FLOAT; 389*24012Ssam break; 390*24012Ssam case ADDD: d_proc = Kaddd; dest_type = DOUBLE; 391*24012Ssam break; 392*24012Ssam case SUBF: f_proc = Ksubf; dest_type = FLOAT; 393*24012Ssam break; 394*24012Ssam case SUBD: d_proc = Ksubd; dest_type = DOUBLE; 395*24012Ssam break; 396*24012Ssam case MULF: f_proc = Kmulf; dest_type = FLOAT; 397*24012Ssam break; 398*24012Ssam case MULD: d_proc = Kmuld; dest_type = DOUBLE; 399*24012Ssam break; 400*24012Ssam case DIVF: f_proc = Kdivf; dest_type = FLOAT; 401*24012Ssam break; 402*24012Ssam case DIVD: d_proc = Kdivd; dest_type = DOUBLE; 403*24012Ssam break; 404*24012Ssam case SINF: f_proc = Ksinf; dest_type = FLOAT; 405*24012Ssam break; 406*24012Ssam case COSF: f_proc = Kcosf; dest_type = FLOAT; 407*24012Ssam break; 408*24012Ssam case ATANF: f_proc = Katanf; dest_type = FLOAT; 409*24012Ssam break; 410*24012Ssam case LOGF: f_proc = Klogf; dest_type = FLOAT; 411*24012Ssam break; 412*24012Ssam case SQRTF: f_proc = Ksqrtf; dest_type = FLOAT; 413*24012Ssam break; 414*24012Ssam case EXPF: f_proc = Kexpf; dest_type = FLOAT; 415*24012Ssam break; 416*24012Ssam } 417*24012Ssam 418*24012Ssam switch(dest_type){ 419*24012Ssam 420*24012Ssam case FLOAT: 421*24012Ssam f_res.ff = (*f_proc)(acc_most,acc_least,op_most,op_least,&hfs); 422*24012Ssam 423*24012Ssam if (f_res.fi == 0 ) locr0[PS] |= PSL_Z; 424*24012Ssam if (f_res.fi < 0 ) locr0[PS] |= PSL_N; 425*24012Ssam break; 426*24012Ssam case DOUBLE: 427*24012Ssam d_res.dd = (*d_proc)(acc_most,acc_least,op_most,op_least,&hfs); 428*24012Ssam if ((d_res.di[0] == 0) && (d_res.di[1] == 0)) 429*24012Ssam locr0[PS] |= PSL_Z; 430*24012Ssam if (d_res.di[0] < 0 ) locr0[PS] |= PSL_N; 431*24012Ssam break; 432*24012Ssam } 433*24012Ssam 434*24012Ssam if (hfs & HFS_OVF){ 435*24012Ssam locr0[PS] |= PSL_V; /* turn on overflow bit */ 436*24012Ssam /* if (locr0[PS] & PSL_IV) { /* overflow elabled? */ 437*24012Ssam opcode = OVF_EXC; 438*24012Ssam u.u_error = (hfs & HFS_DOM) ? EDOM : ERANGE; 439*24012Ssam return; 440*24012Ssam /*}*/ 441*24012Ssam } 442*24012Ssam else if (hfs & HFS_UNDF){ 443*24012Ssam if (locr0[PS] & PSL_FU){ /* underflow elabled? */ 444*24012Ssam opcode = UNDF_EXC; 445*24012Ssam u.u_error = (hfs & HFS_DOM) ? EDOM : ERANGE; 446*24012Ssam return; 447*24012Ssam } 448*24012Ssam } 449*24012Ssam else if (hfs & HFS_DIVZ){ 450*24012Ssam opcode = DIV0_EXC; 451*24012Ssam return; 452*24012Ssam } 453*24012Ssam else if (hfs & HFS_DOM) 454*24012Ssam u.u_error = EDOM; 455*24012Ssam else if (hfs & HFS_RANGE) 456*24012Ssam u.u_error = ERANGE; 457*24012Ssam 458*24012Ssam switch(dest_type){ 459*24012Ssam case FLOAT: 460*24012Ssam if ((hfs & HFS_OVF) || (hfs & HFS_UNDF)) { 461*24012Ssam f_res.ff = 0.0; 462*24012Ssam locr0[PS] |= PSL_Z; 463*24012Ssam } 464*24012Ssam mvtofacc(f_res.ff, &acc_most); 465*24012Ssam break; 466*24012Ssam case DOUBLE: 467*24012Ssam if ((hfs & HFS_OVF) || (hfs & HFS_UNDF)) { 468*24012Ssam d_res.dd = 0.0; 469*24012Ssam locr0[PS] |= PSL_Z; 470*24012Ssam } 471*24012Ssam mvtodacc(d_res.di[0], d_res.di[1], &acc_most); 472*24012Ssam break; 473*24012Ssam } 474*24012Ssam opcode=0; 475*24012Ssam } 476