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.8 (Berkeley) 05/29/90 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 request", /* 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; /* kdb assumes these are *not* registers */ 60 { 61 int r0, r1; /* must reserve space */ 62 register int *locr0 = ((int *)&psl)-PS; 63 register int i; 64 unsigned ucode = code; 65 register struct proc *p; 66 struct timeval syst; 67 68 #ifdef lint 69 r0 = 0; r0 = r0; r1 = 0; r1 = r1; 70 #endif 71 syst = u.u_ru.ru_stime; 72 if (USERMODE(locr0[PS])) { 73 type |= USER; 74 u.u_ar0 = locr0; 75 } 76 switch (type) { 77 78 default: 79 #ifdef KADB 80 if (kdb_trap(&psl)) 81 return; 82 #endif 83 printf("trap type %d, code = %x, pc = %x\n", type, code, pc); 84 type &= ~USER; 85 if (type < TRAP_TYPES && trap_type[type]) 86 panic(trap_type[type]); 87 else 88 panic("trap"); 89 /*NOTREACHED*/ 90 91 case T_PROTFLT + USER: /* protection fault */ 92 i = SIGBUS; 93 break; 94 95 case T_PRIVINFLT + USER: /* privileged instruction fault */ 96 case T_RESADFLT + USER: /* reserved addressing fault */ 97 case T_RESOPFLT + USER: /* resereved operand fault */ 98 case T_ALIGNFLT + USER: /* unaligned data fault */ 99 ucode = type &~ USER; 100 i = SIGILL; 101 break; 102 103 case T_ASTFLT + USER: /* Allow process switch */ 104 case T_ASTFLT: 105 astoff(); 106 if ((u.u_procp->p_flag & SOWEUPC) && u.u_prof.pr_scale) { 107 addupc(pc, &u.u_prof, 1); 108 u.u_procp->p_flag &= ~SOWEUPC; 109 } 110 goto out; 111 112 case T_ARITHTRAP + USER: 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 #ifdef notdef 146 /* THIS CODE IS BOGUS- delete? (KSP not valid is unrecoverable) 147 And what does KSPNOTVAL in user-mode mean? */ 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 panic("ksp not valid - 2"); 164 /* must insure valid kernel stack pointer? */ 165 psignal(u.u_procp, SIGKILL); 166 return; 167 #endif 168 169 case T_BUSERR + USER: 170 i = SIGBUS; 171 break; 172 } 173 trapsignal(i, ucode); 174 out: 175 p = u.u_procp; 176 if (i = CURSIG(p)) 177 psig(i); 178 p->p_pri = p->p_usrpri; 179 if (runrun) { 180 /* 181 * Since we are u.u_procp, clock will normally just change 182 * our priority without moving us from one queue to another 183 * (since the running process is not on a queue.) 184 * If that happened after we setrq ourselves but before we 185 * swtch()'ed, we might not be on the queue indicated by 186 * our priority. 187 */ 188 (void) splclock(); 189 setrq(p); 190 u.u_ru.ru_nivcsw++; 191 swtch(); 192 if (i = CURSIG(p)) 193 psig(i); 194 } 195 if (u.u_prof.pr_scale) { 196 int ticks; 197 struct timeval *tv = &u.u_ru.ru_stime; 198 199 ticks = ((tv->tv_sec - syst.tv_sec) * 1000 + 200 (tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000); 201 if (ticks) 202 addupc(locr0[PC], &u.u_prof, ticks); 203 } 204 curpri = p->p_pri; 205 } 206 207 /* 208 * Called from locore when a system call occurs 209 */ 210 /*ARGSUSED*/ 211 syscall(sp, type, hfs, accmst, acclst, dbl, code, pc, psl) 212 unsigned code; 213 { 214 int r0, r1; /* must reserve space */ 215 register int *locr0 = ((int *)&psl)-PS; 216 register caddr_t params; 217 register int i; 218 register struct sysent *callp; 219 register struct proc *p = u.u_procp; 220 struct timeval syst; 221 int error, opc; 222 223 #ifdef lint 224 r0 = 0; r0 = r0; r1 = 0; r1 = r1; 225 #endif 226 syst = u.u_ru.ru_stime; 227 if (!USERMODE(locr0[PS])) 228 panic("syscall"); 229 u.u_ar0 = locr0; 230 params = (caddr_t)locr0[FP] + NBPW; 231 u.u_error = 0; 232 /* BEGIN GROT */ 233 /* 234 * Try to reconstruct pc, assuming code 235 * is an immediate constant 236 */ 237 opc = pc - 2; /* short literal */ 238 if (code > 0x3f) { 239 opc--; /* byte immediate */ 240 if (code > 0x7f) { 241 opc--; /* word immediate */ 242 if (code > 0x7fff) 243 opc -= 2; /* long immediate */ 244 } 245 } 246 /* END GROT */ 247 callp = (code >= nsysent) ? &sysent[63] : &sysent[code]; 248 if (callp == sysent) { 249 i = fuword(params); 250 params += NBPW; 251 callp = (code >= nsysent) ? &sysent[63] : &sysent[code]; 252 } 253 if ((i = callp->sy_narg * sizeof (int)) && 254 (error = copyin(params, (caddr_t)u.u_arg, (u_int)i)) != 0) { 255 locr0[R0] = error; 256 locr0[PS] |= PSL_C; /* carry bit */ 257 #ifdef KTRACE 258 if (KTRPOINT(p, KTR_SYSCALL)) 259 ktrsyscall(p->p_tracep, code, callp->sy_narg); 260 #endif 261 goto done; 262 } 263 #ifdef KTRACE 264 if (KTRPOINT(p, KTR_SYSCALL)) 265 ktrsyscall(p->p_tracep, code, callp->sy_narg); 266 #endif 267 u.u_r.r_val1 = 0; 268 u.u_r.r_val2 = locr0[R1]; 269 error = (*callp->sy_call)(u.u_procp, u.u_ap, &u.u_r.r_val1); 270 error = u.u_error; /* XXX */ 271 if (error == ERESTART) 272 pc = opc; 273 else if (error != EJUSTRETURN) { 274 if (error) { 275 locr0[R0] = error; 276 locr0[PS] |= PSL_C; /* carry bit */ 277 } else { 278 locr0[PS] &= ~PSL_C; /* clear carry bit */ 279 locr0[R0] = u.u_r.r_val1; 280 locr0[R1] = u.u_r.r_val2; 281 } 282 } 283 /* else if (error == EJUSTRETURN) */ 284 /* nothing to do */ 285 done: 286 /* 287 * Reinitialize proc pointer `p' as it may be different 288 * if this is a child returning from fork syscall. 289 */ 290 p = u.u_procp; 291 if (i = CURSIG(p)) 292 psig(i); 293 p->p_pri = p->p_usrpri; 294 if (runrun) { 295 /* 296 * Since we are u.u_procp, clock will normally just change 297 * our priority without moving us from one queue to another 298 * (since the running process is not on a queue.) 299 * If that happened after we setrq ourselves but before we 300 * swtch()'ed, we might not be on the queue indicated by 301 * our priority. 302 */ 303 (void) splclock(); 304 setrq(p); 305 u.u_ru.ru_nivcsw++; 306 swtch(); 307 if (i = CURSIG(p)) 308 psig(i); 309 } 310 if (u.u_prof.pr_scale) { 311 int ticks; 312 struct timeval *tv = &u.u_ru.ru_stime; 313 314 ticks = ((tv->tv_sec - syst.tv_sec) * 1000 + 315 (tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000); 316 if (ticks) 317 addupc(locr0[PC], &u.u_prof, ticks); 318 } 319 curpri = p->p_pri; 320 #ifdef KTRACE 321 if (KTRPOINT(p, KTR_SYSRET)) 322 ktrsysret(p->p_tracep, code); 323 #endif 324 } 325