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