1 /* 2 * Copyright (c) 1982, 1986, 1990 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.10 (Berkeley) 06/25/90 7 */ 8 9 #include "psl.h" 10 #include "reg.h" 11 #include "pte.h" 12 13 #include "param.h" 14 #include "systm.h" 15 #include "user.h" 16 #include "assym.s" 17 #include "proc.h" 18 #include "seg.h" 19 #include "trap.h" 20 #include "acct.h" 21 #include "kernel.h" 22 #ifdef KTRACE 23 #include "ktrace.h" 24 #endif 25 26 #include "mtpr.h" 27 28 #define USER 040 /* user-mode flag added to type */ 29 30 struct sysent sysent[]; 31 int nsysent; 32 33 char *trap_type[] = { 34 "Reserved addressing mode", 35 "Privileged instruction", 36 "Reserved operand", 37 "Breakpoint", 38 "Xfc trap", 39 "Syscall trap", 40 "Arithmetic fault", 41 "Ast trap", 42 "Segmentation fault", 43 "Protection fault", 44 "Trace trap", 45 "Compatibility mode trap", 46 "Page fault", 47 "Page table fault", 48 "Kernel debugger trap", 49 }; 50 int TRAP_TYPES = (sizeof trap_type / sizeof trap_type[0]); 51 52 /* 53 * Called from the trap handler when a processor trap occurs. 54 */ 55 /*ARGSUSED*/ 56 trap(sp, type, code, pc, psl) 57 int sp, type; 58 unsigned code; 59 int pc, psl; 60 { 61 register int *locr0 = ((int *)&psl)-PS; 62 register int i; 63 unsigned ucode = code; 64 register struct proc *p; 65 struct timeval syst; 66 67 syst = u.u_ru.ru_stime; 68 if (USERMODE(locr0[PS])) { 69 type |= USER; 70 u.u_ar0 = locr0; 71 } 72 switch (type) { 73 74 default: 75 #ifdef KADB 76 if (kdb_trap(&psl)) 77 return; 78 #endif 79 printf("trap type %d, code = %x, pc = %x\n", type, code, pc); 80 type &= ~USER; 81 if ((unsigned)type < TRAP_TYPES) 82 panic(trap_type[type]); 83 panic("trap"); 84 85 case T_PROTFLT+USER: /* protection fault */ 86 i = SIGBUS; 87 break; 88 89 case T_PRIVINFLT+USER: /* privileged instruction fault */ 90 case T_RESADFLT+USER: /* reserved addressing fault */ 91 case T_RESOPFLT+USER: /* reserved operand fault */ 92 ucode = type &~ USER; 93 i = SIGILL; 94 break; 95 96 case T_ASTFLT+USER: 97 astoff(); 98 if ((u.u_procp->p_flag & SOWEUPC) && u.u_prof.pr_scale) { 99 addupc(pc, &u.u_prof, 1); 100 u.u_procp->p_flag &= ~SOWEUPC; 101 } 102 goto out; 103 104 case T_ARITHTRAP+USER: 105 i = SIGFPE; 106 break; 107 108 /* 109 * If the user SP is above the stack segment, 110 * grow the stack automatically. 111 */ 112 case T_SEGFLT+USER: 113 if (grow((unsigned)locr0[SP]) || grow(code)) 114 goto out; 115 i = SIGSEGV; 116 break; 117 118 case T_TABLEFLT: /* allow page table faults in kernel mode */ 119 case T_TABLEFLT+USER: /* page table fault */ 120 panic("ptable fault"); 121 122 case T_PAGEFLT: /* allow page faults in kernel mode */ 123 case T_PAGEFLT+USER: /* page fault */ 124 pagein(code, 0); 125 if (type == T_PAGEFLT) 126 return; 127 goto out; 128 129 case T_BPTFLT+USER: /* bpt instruction fault */ 130 case T_TRCTRAP+USER: /* trace trap */ 131 locr0[PS] &= ~PSL_T; 132 i = SIGTRAP; 133 break; 134 135 case T_XFCFLT+USER: /* xfc instruction fault */ 136 i = SIGEMT; 137 break; 138 139 case T_COMPATFLT+USER: /* compatibility mode fault */ 140 u.u_acflag |= ACOMPAT; 141 i = SIGILL; 142 break; 143 } 144 trapsignal(i, ucode); 145 out: 146 p = u.u_procp; 147 if (i = CURSIG(p)) 148 psig(i); 149 p->p_pri = p->p_usrpri; 150 if (runrun) { 151 /* 152 * Since we are u.u_procp, clock will normally just change 153 * our priority without moving us from one queue to another 154 * (since the running process is not on a queue.) 155 * If that happened after we setrq ourselves but before we 156 * swtch()'ed, we might not be on the queue indicated by 157 * our priority. 158 */ 159 (void) splclock(); 160 setrq(p); 161 u.u_ru.ru_nivcsw++; 162 swtch(); 163 if (i = CURSIG(p)) 164 psig(i); 165 } 166 if (u.u_prof.pr_scale) { 167 int ticks; 168 struct timeval *tv = &u.u_ru.ru_stime; 169 170 ticks = ((tv->tv_sec - syst.tv_sec) * 1000 + 171 (tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000); 172 if (ticks) 173 addupc(locr0[PC], &u.u_prof, ticks); 174 } 175 curpri = p->p_pri; 176 } 177 178 /* 179 * Called from the trap handler when a system call occurs 180 */ 181 /*ARGSUSED*/ 182 syscall(sp, type, code, pc, psl) 183 unsigned code; 184 { 185 register int *locr0 = ((int *)&psl)-PS; 186 register caddr_t params; /* known to be r10 below */ 187 register int i; /* known to be r9 below */ 188 register struct sysent *callp; 189 register struct proc *p = u.u_procp; 190 int error, opc; 191 struct args { 192 int i[8]; 193 } args; 194 int rval[2]; 195 struct timeval syst; 196 197 syst = u.u_ru.ru_stime; 198 if (!USERMODE(locr0[PS])) 199 panic("syscall"); 200 u.u_ar0 = locr0; 201 params = (caddr_t)locr0[AP] + NBPW; 202 opc = pc - 2; 203 if (code > 63) 204 opc -= 2; 205 if (code == 0) { /* indir */ 206 code = fuword(params); 207 params += NBPW; 208 } 209 if (code >= nsysent) 210 callp = &sysent[0]; /* indir (illegal) */ 211 else 212 callp = &sysent[code]; 213 if ((i = callp->sy_narg * sizeof (int)) && 214 (error = copyin(params, (caddr_t)&args, (u_int)i)) != 0) { 215 locr0[R0] = error; 216 locr0[PS] |= PSL_C; /* carry bit */ 217 #ifdef KTRACE 218 if (KTRPOINT(p, KTR_SYSCALL)) 219 ktrsyscall(p->p_tracep, code, callp->sy_narg, args.i); 220 #endif 221 goto done; 222 } 223 #ifdef KTRACE 224 if (KTRPOINT(p, KTR_SYSCALL)) 225 ktrsyscall(p->p_tracep, code, callp->sy_narg, args.i); 226 #endif 227 rval[0] = 0; 228 rval[1] = locr0[R1]; 229 error = (*callp->sy_call)(u.u_procp, &args, rval); 230 if (error == ERESTART) 231 pc = opc; 232 else if (error != EJUSTRETURN) { 233 if (error) { 234 locr0[R0] = error; 235 locr0[PS] |= PSL_C; /* carry bit */ 236 } else { 237 locr0[R0] = rval[0]; 238 locr0[R1] = rval[1]; 239 locr0[PS] &= ~PSL_C; 240 } 241 } 242 /* else if (error == EJUSTRETURN) */ 243 /* nothing to do */ 244 done: 245 /* 246 * Reinitialize proc pointer `p' as it may be different 247 * if this is a child returning from fork syscall. 248 */ 249 p = u.u_procp; 250 if (i = CURSIG(p)) 251 psig(i); 252 p->p_pri = p->p_usrpri; 253 if (runrun) { 254 /* 255 * Since we are u.u_procp, clock will normally just change 256 * our priority without moving us from one queue to another 257 * (since the running process is not on a queue.) 258 * If that happened after we setrq ourselves but before we 259 * swtch()'ed, we might not be on the queue indicated by 260 * our priority. 261 */ 262 (void) splclock(); 263 setrq(p); 264 u.u_ru.ru_nivcsw++; 265 swtch(); 266 if (i = CURSIG(p)) 267 psig(i); 268 } 269 if (u.u_prof.pr_scale) { 270 int ticks; 271 struct timeval *tv = &u.u_ru.ru_stime; 272 273 ticks = ((tv->tv_sec - syst.tv_sec) * 1000 + 274 (tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000); 275 if (ticks) 276 addupc(locr0[PC], &u.u_prof, ticks); 277 } 278 curpri = p->p_pri; 279 #ifdef KTRACE 280 if (KTRPOINT(p, KTR_SYSRET)) 281 ktrsysret(p->p_tracep, code, error, rval[0]); 282 #endif 283 } 284