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