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