1 /* trap.c 1.2 86/01/05 */ 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 case T_KSPNOTVAL: 137 case T_KSPNOTVAL + USER: 138 i = SIGKILL; /* There is nothing to do but to kill the 139 * process.. */ 140 printf("KSP NOT VALID.\n"); 141 break; 142 143 case T_BUSERR + USER: 144 i = SIGBUS; 145 u.u_code = code; 146 break; 147 } 148 psignal(u.u_procp, i); 149 out: 150 p = u.u_procp; 151 if (p->p_cursig || ISSIG(p)) 152 psig(); 153 p->p_pri = p->p_usrpri; 154 if (runrun) { 155 /* 156 * Since we are u.u_procp, clock will normally just change 157 * our priority without moving us from one queue to another 158 * (since the running process is not on a queue.) 159 * If that happened after we setrq ourselves but before we 160 * swtch()'ed, we might not be on the queue indicated by 161 * our priority. 162 */ 163 (void) spl8(); 164 setrq(p); 165 u.u_ru.ru_nivcsw++; 166 swtch(); 167 } 168 if (u.u_prof.pr_scale) { 169 int ticks; 170 struct timeval *tv = &u.u_ru.ru_stime; 171 172 ticks = ((tv->tv_sec - syst.tv_sec) * 1000 + 173 (tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000); 174 if (ticks) 175 addupc(locr0[PC], &u.u_prof, ticks); 176 } 177 curpri = p->p_pri; 178 } 179 180 #ifdef SYSCALLTRACE 181 int syscalltrace = 0; 182 #endif 183 184 /* 185 * Called from locore when a system call occurs 186 */ 187 /*ARGSUSED*/ 188 syscall(sp, type, hfs, accmst, acclst, dbl, code, pc, psl) 189 unsigned code; 190 { 191 int r0, r1; /* must reserve space */ 192 register int *locr0 = ((int *)&psl)-PS; 193 register caddr_t params; 194 register int i; 195 register struct sysent *callp; 196 register struct proc *p; 197 struct timeval syst; 198 int opc; 199 200 #ifdef lint 201 r0 = 0; r0 = r0; r1 = 0; r1 = r1; 202 #endif 203 syst = u.u_ru.ru_stime; 204 if (!USERMODE(locr0[PS])) 205 panic("syscall"); 206 u.u_ar0 = locr0; 207 if (code == 139) { /* 4.2 COMPATIBILTY XXX */ 208 osigcleanup(); /* 4.2 COMPATIBILTY XXX */ 209 goto done; /* 4.2 COMPATIBILTY XXX */ 210 } 211 params = (caddr_t)locr0[FP] + NBPW; 212 u.u_error = 0; 213 /* BEGIN GROT */ 214 /* 215 * Try to reconstruct pc, assuming code 216 * is an immediate constant 217 */ 218 opc = pc - 2; /* short literal */ 219 if (code > 0x3f) { 220 opc--; /* byte immediate */ 221 if (code > 0x7f) { 222 opc--; /* word immediate */ 223 if (code > 0x7fff) 224 opc -= 2; /* long immediate */ 225 } 226 } 227 /* END GROT */ 228 callp = (code >= nsysent) ? &sysent[63] : &sysent[code]; 229 if (callp == sysent) { 230 i = fuword(params); 231 params += NBPW; 232 callp = (code >= nsysent) ? &sysent[63] : &sysent[code]; 233 } 234 if ((i = callp->sy_narg * sizeof (int)) && 235 (u.u_error = copyin(params, (caddr_t)u.u_arg, (u_int)i)) != 0) { 236 locr0[R0] = u.u_error; 237 locr0[PS] |= PSL_C; /* carry bit */ 238 goto done; 239 } 240 u.u_r.r_val1 = 0; 241 u.u_r.r_val2 = locr0[R1]; 242 if (setjmp(&u.u_qsave)) { 243 if (u.u_error == 0 && u.u_eosys != RESTARTSYS) 244 u.u_error = EINTR; 245 } else { 246 u.u_eosys = NORMALRETURN; 247 #ifdef SYSCALLTRACE 248 if (syscalltrace) { 249 register int i; 250 char *cp; 251 252 if (code >= nsysent) 253 printf("0x%x", code); 254 else 255 printf("%s", syscallnames[code]); 256 cp = "("; 257 for (i= 0; i < callp->sy_narg; i++) { 258 printf("%s%x", cp, u.u_arg[i]); 259 cp = ", "; 260 } 261 if (i) 262 putchar(')', 0); 263 putchar('\n', 0); 264 } 265 #endif 266 (*callp->sy_call)(); 267 } 268 if (u.u_eosys == NORMALRETURN) { 269 if (u.u_error) { 270 locr0[R0] = u.u_error; 271 locr0[PS] |= PSL_C; /* carry bit */ 272 } else { 273 locr0[PS] &= ~PSL_C; /* clear carry bit */ 274 locr0[R0] = u.u_r.r_val1; 275 locr0[R1] = u.u_r.r_val2; 276 } 277 } else if (u.u_eosys == RESTARTSYS) 278 pc = opc; 279 /* else if (u.u_eosys == JUSTRETURN) */ 280 /* nothing to do */ 281 done: 282 p = u.u_procp; 283 if (p->p_cursig || ISSIG(p)) 284 psig(); 285 p->p_pri = p->p_usrpri; 286 if (runrun) { 287 /* 288 * Since we are u.u_procp, clock will normally just change 289 * our priority without moving us from one queue to another 290 * (since the running process is not on a queue.) 291 * If that happened after we setrq ourselves but before we 292 * swtch()'ed, we might not be on the queue indicated by 293 * our priority. 294 */ 295 (void) spl8(); 296 setrq(p); 297 u.u_ru.ru_nivcsw++; 298 swtch(); 299 } 300 if (u.u_prof.pr_scale) { 301 int ticks; 302 struct timeval *tv = &u.u_ru.ru_stime; 303 304 ticks = ((tv->tv_sec - syst.tv_sec) * 1000 + 305 (tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000); 306 if (ticks) 307 addupc(locr0[PC], &u.u_prof, ticks); 308 } 309 curpri = p->p_pri; 310 } 311 312 /* 313 * nonexistent system call-- signal process (may want to handle it) 314 * flag error if process won't see signal immediately 315 * Q: should we do that all the time ?? 316 */ 317 nosys() 318 { 319 320 if (u.u_signal[SIGSYS] == SIG_IGN || u.u_signal[SIGSYS] == SIG_HOLD) 321 u.u_error = EINVAL; 322 psignal(u.u_procp, SIGSYS); 323 } 324 325 #ifdef notdef 326 /* 327 * Ignored system call 328 */ 329 nullsys() 330 { 331 332 } 333 #endif 334