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.14 (Berkeley) 09/23/93 7 */ 8 9 #include "sys/param.h" 10 #include "sys/systm.h" 11 #include "sys/user.h" 12 #include "sys/proc.h" 13 #include "sys/seg.h" 14 #include "sys/acct.h" 15 #include "sys/kernel.h" 16 17 #include "../include/psl.h" 18 #include "../include/reg.h" 19 #include "../include/pte.h" 20 #include "../include/mtpr.h" 21 #ifdef KTRACE 22 #include "sys/ktrace.h" 23 #endif 24 25 #include "../include/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 & P_OWEUPC) && u.u_prof.pr_scale) { 107 addupc(pc, &u.u_prof, 1); 108 u.u_procp->p_flag &= ~P_OWEUPC; 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 pagein(code, 0); 133 if (type == T_PAGEFLT) 134 return; 135 goto out; 136 137 case T_BPTFLT + USER: /* bpt instruction fault */ 138 case T_TRCTRAP + USER: /* trace trap */ 139 locr0[PS] &= ~PSL_T; 140 i = SIGTRAP; 141 break; 142 143 #ifdef notdef 144 /* THIS CODE IS BOGUS- delete? (KSP not valid is unrecoverable) 145 And what does KSPNOTVAL in user-mode mean? */ 146 /* 147 * For T_KSPNOTVAL and T_BUSERR, can not allow spl to 148 * drop to 0 as clock could go off and we would end up 149 * doing an rei to the interrupt stack at ipl 0 (a 150 * reserved operand fault). Instead, we allow psignal 151 * to post an ast, then return to user mode where we 152 * will reenter the kernel on the kernel's stack and 153 * can then service the signal. 154 */ 155 case T_KSPNOTVAL: 156 if (noproc) 157 panic("ksp not valid"); 158 /* fall thru... */ 159 case T_KSPNOTVAL + USER: 160 printf("pid %d: ksp not valid\n", u.u_procp->p_pid); 161 panic("ksp not valid - 2"); 162 /* must insure valid kernel stack pointer? */ 163 psignal(u.u_procp, SIGKILL); 164 return; 165 #endif 166 167 case T_BUSERR + USER: 168 i = SIGBUS; 169 break; 170 } 171 trapsignal(i, ucode); 172 out: 173 p = u.u_procp; 174 if (i = CURSIG(p)) 175 postsig(i); 176 p->p_priority = p->p_usrpri; 177 if (runrun) { 178 /* 179 * Since we are u.u_procp, clock will normally just change 180 * our priority without moving us from one queue to another 181 * (since the running process is not on a queue.) 182 * If that happened after we put ourselves on the run queue 183 * but before we Xswitch()'ed, we might not be on the queue 184 * indicated by our priority. 185 */ 186 (void) splclock(); 187 setrunqueue(p); 188 u.u_ru.ru_nivcsw++; 189 Xswitch(); 190 if (i = CURSIG(p)) 191 postsig(i); 192 } 193 if (u.u_prof.pr_scale) { 194 int ticks; 195 struct timeval *tv = &u.u_ru.ru_stime; 196 197 ticks = ((tv->tv_sec - syst.tv_sec) * 1000 + 198 (tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000); 199 if (ticks) 200 addupc(locr0[PC], &u.u_prof, ticks); 201 } 202 curpriority = p->p_priority; 203 } 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 error, opc; 220 struct args { 221 int i[8]; 222 } args; 223 int rval[2]; 224 225 #ifdef lint 226 r0 = 0; r0 = r0; r1 = 0; r1 = r1; 227 #endif 228 syst = u.u_ru.ru_stime; 229 if (!USERMODE(locr0[PS])) 230 panic("syscall"); 231 u.u_ar0 = locr0; 232 params = (caddr_t)locr0[FP] + NBPW; 233 /* BEGIN GROT */ 234 /* 235 * Try to reconstruct pc, assuming code 236 * is an immediate constant 237 */ 238 opc = pc - 2; /* short literal */ 239 if (code > 0x3f) { 240 opc--; /* byte immediate */ 241 if (code > 0x7f) { 242 opc--; /* word immediate */ 243 if (code > 0x7fff) 244 opc -= 2; /* long immediate */ 245 } 246 } 247 /* END GROT */ 248 if (code == 0) { /* indir */ 249 code = fuword(params); 250 params += NBPW; 251 } 252 if (code >= nsysent) 253 callp = &sysent[0]; /* indir (illegal) */ 254 else 255 callp = &sysent[code]; 256 if ((i = callp->sy_narg * sizeof (int)) && 257 (error = copyin(params, (caddr_t)&args, (u_int)i)) != 0) { 258 locr0[R0] = error; 259 locr0[PS] |= PSL_C; /* carry bit */ 260 #ifdef KTRACE 261 if (KTRPOINT(p, KTR_SYSCALL)) 262 ktrsyscall(p->p_tracep, code, callp->sy_narg, args.i); 263 #endif 264 goto done; 265 } 266 #ifdef KTRACE 267 if (KTRPOINT(p, KTR_SYSCALL)) 268 ktrsyscall(p->p_tracep, code, callp->sy_narg, args.i); 269 #endif 270 rval[0] = 0; 271 rval[1] = locr0[R1]; 272 error = (*callp->sy_call)(u.u_procp, &args, rval); 273 if (error == ERESTART) 274 pc = opc; 275 else if (error != EJUSTRETURN) { 276 if (error) { 277 locr0[R0] = error; 278 locr0[PS] |= PSL_C; /* carry bit */ 279 } else { 280 locr0[PS] &= ~PSL_C; /* clear carry bit */ 281 locr0[R0] = rval[0]; 282 locr0[R1] = rval[1]; 283 } 284 } 285 /* else if (error == EJUSTRETURN) */ 286 /* nothing to do */ 287 done: 288 /* 289 * Reinitialize proc pointer `p' as it may be different 290 * if this is a child returning from fork syscall. 291 */ 292 p = u.u_procp; 293 if (i = CURSIG(p)) 294 postsig(i); 295 p->p_priority = p->p_usrpri; 296 if (runrun) { 297 /* 298 * Since we are u.u_procp, clock will normally just change 299 * our priority without moving us from one queue to another 300 * (since the running process is not on a queue.) 301 * If that happened after we put ourselves on the run queue 302 * but before we Xswitch()'ed, we might not be on the queue 303 * indicated by our priority. 304 */ 305 (void) splclock(); 306 setrunqueue(p); 307 u.u_ru.ru_nivcsw++; 308 Xswitch(); 309 if (i = CURSIG(p)) 310 postsig(i); 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 curpriority = p->p_priority; 322 #ifdef KTRACE 323 if (KTRPOINT(p, KTR_SYSRET)) 324 ktrsysret(p->p_tracep, code, error, rval[0]); 325 #endif 326 } 327