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