1 /* trap.c 1.7 86/12/15 */ 2 3 #include "../tahoe/psl.h" 4 #include "../tahoe/reg.h" 5 #include "../tahoe/pte.h" 6 #include "../tahoe/mtpr.h" 7 8 #include "param.h" 9 #include "systm.h" 10 #include "dir.h" 11 #include "user.h" 12 #include "proc.h" 13 #include "seg.h" 14 #include "acct.h" 15 #include "kernel.h" 16 #define SYSCALLTRACE 17 #ifdef SYSCALLTRACE 18 #include "../sys/syscalls.c" 19 #endif 20 21 #include "../tahoe/trap.h" 22 23 #define USER 040 /* user-mode flag added to type */ 24 25 struct sysent sysent[]; 26 int nsysent; 27 28 char *trap_type[] = { 29 "Reserved addressing mode", /* T_RESADFLT */ 30 "Privileged instruction", /* T_PRIVINFLT */ 31 "Reserved operand", /* T_RESOPFLT */ 32 "Breakpoint", /* T_BPTFLT */ 33 0, 34 "Kernel call", /* T_SYSCALL */ 35 "Arithmetic trap", /* T_ARITHTRAP */ 36 "System forced exception", /* T_ASTFLT */ 37 "Segmentation fault", /* T_SEGFLT */ 38 "Protection fault", /* T_PROTFLT */ 39 "Trace trap", /* T_TRCTRAP */ 40 0, 41 "Page fault", /* T_PAGEFLT */ 42 "Page table fault", /* T_TABLEFLT */ 43 "Alignment fault", /* T_ALIGNFLT */ 44 "Kernel stack not valid", /* T_KSPNOTVAL */ 45 "Bus error", /* T_BUSERR */ 46 "Kernel debugger trap", /* T_KDBTRAP */ 47 }; 48 int TRAP_TYPES = sizeof (trap_type) / sizeof (trap_type[0]); 49 50 /* 51 * Called from the trap handler when a processor trap occurs. 52 */ 53 /*ARGSUSED*/ 54 trap(sp, type, hfs, accmst, acclst, dbl, code, pc, psl) 55 unsigned type, code; 56 { 57 int r0, r1; /* must reserve space */ 58 register int *locr0 = ((int *)&psl)-PS; 59 register int i; 60 register struct proc *p; 61 struct timeval syst; 62 63 #ifdef lint 64 r0 = 0; r0 = r0; r1 = 0; r1 = r1; 65 #endif 66 syst = u.u_ru.ru_stime; 67 if (USERMODE(locr0[PS])) { 68 type |= USER; 69 u.u_ar0 = locr0; 70 } 71 switch (type) { 72 73 default: 74 #ifdef KDB 75 if (kdb_trap(&psl)) 76 return; 77 #endif 78 printf("trap type %d, code = %x, pc = %x\n", type, code, pc); 79 type &= ~USER; 80 if (type < TRAP_TYPES && trap_type[type]) 81 panic(trap_type[type]); 82 else 83 panic("trap"); 84 /*NOTREACHED*/ 85 86 case T_PROTFLT + USER: /* protection fault */ 87 i = SIGBUS; 88 break; 89 90 case T_PRIVINFLT + USER: /* privileged instruction fault */ 91 case T_RESADFLT + USER: /* reserved addressing fault */ 92 case T_RESOPFLT + USER: /* resereved operand fault */ 93 case T_ALIGNFLT + USER: /* unaligned data fault */ 94 u.u_code = type &~ USER; 95 i = SIGILL; 96 break; 97 98 case T_ASTFLT + USER: /* Allow process switch */ 99 case T_ASTFLT: 100 astoff(); 101 if ((u.u_procp->p_flag & SOWEUPC) && u.u_prof.pr_scale) { 102 addupc(pc, &u.u_prof, 1); 103 u.u_procp->p_flag &= ~SOWEUPC; 104 } 105 goto out; 106 107 case T_ARITHTRAP + USER: 108 u.u_code = code; 109 i = SIGFPE; 110 break; 111 112 /* 113 * If the user SP is above the stack segment, 114 * grow the stack automatically. 115 */ 116 case T_SEGFLT + USER: 117 if (grow((unsigned)locr0[SP]) || grow(code)) 118 goto out; 119 i = SIGSEGV; 120 break; 121 122 case T_TABLEFLT: /* allow page table faults in kernel */ 123 case T_TABLEFLT + USER: /* page table fault */ 124 panic("ptable fault"); 125 126 case T_PAGEFLT: /* allow page faults in kernel mode */ 127 case T_PAGEFLT + USER: /* page fault */ 128 i = u.u_error; 129 pagein(code, 0); 130 u.u_error = i; 131 if (type == T_PAGEFLT) 132 return; 133 goto out; 134 135 case T_BPTFLT + USER: /* bpt instruction fault */ 136 case T_TRCTRAP + USER: /* trace trap */ 137 locr0[PS] &= ~PSL_T; 138 i = SIGTRAP; 139 break; 140 141 /* 142 * For T_KSPNOTVAL and T_BUSERR, can not allow spl to 143 * drop to 0 as clock could go off and we would end up 144 * doing an rei to the interrupt stack at ipl 0 (a 145 * reserved operand fault). Instead, we allow psignal 146 * to post an ast, then return to user mode where we 147 * will reenter the kernel on the kernel's stack and 148 * can then service the signal. 149 */ 150 case T_KSPNOTVAL: 151 if (noproc) 152 panic("ksp not valid"); 153 /* fall thru... */ 154 case T_KSPNOTVAL + USER: 155 printf("pid %d: ksp not valid\n", u.u_procp->p_pid); 156 /* must insure valid kernel stack pointer? */ 157 psignal(u.u_procp, SIGKILL); 158 return; 159 160 case T_BUSERR + USER: 161 u.u_code = code; 162 psignal(u.u_procp, SIGBUS); 163 return; 164 } 165 psignal(u.u_procp, i); 166 out: 167 p = u.u_procp; 168 if (p->p_cursig || ISSIG(p)) 169 psig(); 170 p->p_pri = p->p_usrpri; 171 if (runrun) { 172 /* 173 * Since we are u.u_procp, clock will normally just change 174 * our priority without moving us from one queue to another 175 * (since the running process is not on a queue.) 176 * If that happened after we setrq ourselves but before we 177 * swtch()'ed, we might not be on the queue indicated by 178 * our priority. 179 */ 180 (void) splclock(); 181 setrq(p); 182 u.u_ru.ru_nivcsw++; 183 swtch(); 184 } 185 if (u.u_prof.pr_scale) { 186 int ticks; 187 struct timeval *tv = &u.u_ru.ru_stime; 188 189 ticks = ((tv->tv_sec - syst.tv_sec) * 1000 + 190 (tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000); 191 if (ticks) 192 addupc(locr0[PC], &u.u_prof, ticks); 193 } 194 curpri = p->p_pri; 195 } 196 197 #ifdef SYSCALLTRACE 198 int syscalltrace = 0; 199 #endif 200 201 /* 202 * Called from locore when a system call occurs 203 */ 204 /*ARGSUSED*/ 205 syscall(sp, type, hfs, accmst, acclst, dbl, code, pc, psl) 206 unsigned code; 207 { 208 int r0, r1; /* must reserve space */ 209 register int *locr0 = ((int *)&psl)-PS; 210 register caddr_t params; 211 register int i; 212 register struct sysent *callp; 213 register struct proc *p; 214 struct timeval syst; 215 int opc; 216 217 #ifdef lint 218 r0 = 0; r0 = r0; r1 = 0; r1 = r1; 219 #endif 220 syst = u.u_ru.ru_stime; 221 if (!USERMODE(locr0[PS])) 222 panic("syscall"); 223 u.u_ar0 = locr0; 224 if (code == 139) { /* 4.2 COMPATIBILTY XXX */ 225 osigcleanup(); /* 4.2 COMPATIBILTY XXX */ 226 goto done; /* 4.2 COMPATIBILTY XXX */ 227 } 228 params = (caddr_t)locr0[FP] + NBPW; 229 u.u_error = 0; 230 /* BEGIN GROT */ 231 /* 232 * Try to reconstruct pc, assuming code 233 * is an immediate constant 234 */ 235 opc = pc - 2; /* short literal */ 236 if (code > 0x3f) { 237 opc--; /* byte immediate */ 238 if (code > 0x7f) { 239 opc--; /* word immediate */ 240 if (code > 0x7fff) 241 opc -= 2; /* long immediate */ 242 } 243 } 244 /* END GROT */ 245 callp = (code >= nsysent) ? &sysent[63] : &sysent[code]; 246 if (callp == sysent) { 247 i = fuword(params); 248 params += NBPW; 249 callp = (code >= nsysent) ? &sysent[63] : &sysent[code]; 250 } 251 if ((i = callp->sy_narg * sizeof (int)) && 252 (u.u_error = copyin(params, (caddr_t)u.u_arg, (u_int)i)) != 0) { 253 locr0[R0] = u.u_error; 254 locr0[PS] |= PSL_C; /* carry bit */ 255 goto done; 256 } 257 u.u_r.r_val1 = 0; 258 u.u_r.r_val2 = locr0[R1]; 259 if (setjmp(&u.u_qsave)) { 260 if (u.u_error == 0 && u.u_eosys != RESTARTSYS) 261 u.u_error = EINTR; 262 } else { 263 u.u_eosys = NORMALRETURN; 264 #ifdef SYSCALLTRACE 265 if (syscalltrace) { 266 register int a; 267 char *cp; 268 269 if (code >= nsysent) 270 printf("0x%x", code); 271 else 272 printf("%s", syscallnames[code]); 273 cp = "("; 274 for (a = 0; a < callp->sy_narg; a++) { 275 printf("%s%x", cp, u.u_arg[a]); 276 cp = ", "; 277 } 278 if (a) 279 printf(")"); 280 printf("\n"); 281 } 282 #endif 283 (*callp->sy_call)(); 284 } 285 if (u.u_eosys == NORMALRETURN) { 286 if (u.u_error) { 287 locr0[R0] = u.u_error; 288 locr0[PS] |= PSL_C; /* carry bit */ 289 } else { 290 locr0[PS] &= ~PSL_C; /* clear carry bit */ 291 locr0[R0] = u.u_r.r_val1; 292 locr0[R1] = u.u_r.r_val2; 293 } 294 } else if (u.u_eosys == RESTARTSYS) 295 pc = opc; 296 /* else if (u.u_eosys == JUSTRETURN) */ 297 /* nothing to do */ 298 done: 299 p = u.u_procp; 300 if (p->p_cursig || ISSIG(p)) 301 psig(); 302 p->p_pri = p->p_usrpri; 303 if (runrun) { 304 /* 305 * Since we are u.u_procp, clock will normally just change 306 * our priority without moving us from one queue to another 307 * (since the running process is not on a queue.) 308 * If that happened after we setrq ourselves but before we 309 * swtch()'ed, we might not be on the queue indicated by 310 * our priority. 311 */ 312 (void) splclock(); 313 setrq(p); 314 u.u_ru.ru_nivcsw++; 315 swtch(); 316 } 317 if (u.u_prof.pr_scale) { 318 int ticks; 319 struct timeval *tv = &u.u_ru.ru_stime; 320 321 ticks = ((tv->tv_sec - syst.tv_sec) * 1000 + 322 (tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000); 323 if (ticks) 324 addupc(locr0[PC], &u.u_prof, ticks); 325 } 326 curpri = p->p_pri; 327 } 328 329 /* 330 * nonexistent system call-- signal process (may want to handle it) 331 * flag error if process won't see signal immediately 332 * Q: should we do that all the time ?? 333 */ 334 nosys() 335 { 336 337 if (u.u_signal[SIGSYS] == SIG_IGN || u.u_signal[SIGSYS] == SIG_HOLD) 338 u.u_error = EINVAL; 339 psignal(u.u_procp, SIGSYS); 340 } 341 342 #ifdef notdef 343 /* 344 * Ignored system call 345 */ 346 nullsys() 347 { 348 349 } 350 #endif 351