1 /* 2 * Copyright (c) 1982, 1986 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.2 (Berkeley) 02/21/87 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 "dir.h" 16 #include "user.h" 17 #include "assym.s" 18 #include "proc.h" 19 #include "seg.h" 20 #include "trap.h" 21 #include "acct.h" 22 #include "kernel.h" 23 #ifdef SYSCALLTRACE 24 #include "../sys/syscalls.c" 25 #endif 26 27 #include "mtpr.h" 28 29 #define USER 040 /* user-mode flag added to type */ 30 31 struct sysent sysent[]; 32 int nsysent; 33 34 char *trap_type[] = { 35 "Reserved addressing mode", 36 "Privileged instruction", 37 "Reserved operand", 38 "Breakpoint", 39 "Xfc trap", 40 "Syscall trap", 41 "Arithmetic fault", 42 "Ast trap", 43 "Segmentation fault", 44 "Protection fault", 45 "Trace trap", 46 "Compatibility mode trap", 47 "Page fault", 48 "Page table fault", 49 "Kernel debugger trap", 50 }; 51 int TRAP_TYPES = (sizeof trap_type / sizeof trap_type[0]); 52 53 /* 54 * Called from the trap handler when a processor trap occurs. 55 */ 56 /*ARGSUSED*/ 57 trap(sp, type, code, pc, psl) 58 int sp, type; 59 unsigned code; 60 int pc, psl; 61 { 62 register int *locr0 = ((int *)&psl)-PS; 63 register int i; 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 KDB 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: /* resereved operand fault */ 92 u.u_code = 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 u.u_code = code; 106 i = SIGFPE; 107 break; 108 109 /* 110 * If the user SP is above the stack segment, 111 * grow the stack automatically. 112 */ 113 case T_SEGFLT+USER: 114 if (grow((unsigned)locr0[SP]) || grow(code)) 115 goto out; 116 i = SIGSEGV; 117 break; 118 119 case T_TABLEFLT: /* allow page table faults in kernel mode */ 120 case T_TABLEFLT+USER: /* page table fault */ 121 panic("ptable fault"); 122 123 case T_PAGEFLT: /* allow page faults in kernel mode */ 124 case T_PAGEFLT+USER: /* page fault */ 125 i = u.u_error; 126 pagein(code, 0); 127 u.u_error = i; 128 if (type == T_PAGEFLT) 129 return; 130 goto out; 131 132 case T_BPTFLT+USER: /* bpt instruction fault */ 133 case T_TRCTRAP+USER: /* trace trap */ 134 locr0[PS] &= ~PSL_T; 135 i = SIGTRAP; 136 break; 137 138 case T_XFCFLT+USER: /* xfc instruction fault */ 139 i = SIGEMT; 140 break; 141 142 case T_COMPATFLT+USER: /* compatibility mode fault */ 143 u.u_acflag |= ACOMPAT; 144 u.u_code = code; 145 i = SIGILL; 146 break; 147 } 148 psignal(u.u_procp, i); 149 out: 150 p = u.u_procp; 151 if (p->p_cursig || ISSIG(p)) 152 psig(); 153 p->p_pri = p->p_usrpri; 154 if (runrun) { 155 /* 156 * Since we are u.u_procp, clock will normally just change 157 * our priority without moving us from one queue to another 158 * (since the running process is not on a queue.) 159 * If that happened after we setrq ourselves but before we 160 * swtch()'ed, we might not be on the queue indicated by 161 * our priority. 162 */ 163 (void) splclock(); 164 setrq(p); 165 u.u_ru.ru_nivcsw++; 166 swtch(); 167 } 168 if (u.u_prof.pr_scale) { 169 int ticks; 170 struct timeval *tv = &u.u_ru.ru_stime; 171 172 ticks = ((tv->tv_sec - syst.tv_sec) * 1000 + 173 (tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000); 174 if (ticks) 175 addupc(locr0[PC], &u.u_prof, ticks); 176 } 177 curpri = p->p_pri; 178 } 179 180 #ifdef SYSCALLTRACE 181 int syscalltrace = 0; 182 #endif 183 /* 184 * Called from the trap handler when a system call occurs 185 */ 186 /*ARGSUSED*/ 187 syscall(sp, type, code, pc, psl) 188 unsigned code; 189 { 190 register int *locr0 = ((int *)&psl)-PS; 191 register caddr_t params; /* known to be r10 below */ 192 register int i; /* known to be r9 below */ 193 register struct sysent *callp; 194 register struct proc *p; 195 int opc; 196 struct timeval syst; 197 198 syst = u.u_ru.ru_stime; 199 if (!USERMODE(locr0[PS])) 200 panic("syscall"); 201 u.u_ar0 = locr0; 202 if (code == 139) { /* XXX 4.2 COMPATIBILITY */ 203 osigcleanup(); /* XXX 4.2 COMPATIBILITY */ 204 goto done; /* XXX 4.2 COMPATIBILITY */ 205 } /* XXX 4.2 COMPATIBILITY */ 206 params = (caddr_t)locr0[AP] + NBPW; 207 u.u_error = 0; 208 opc = pc - 2; 209 if (code > 63) 210 opc -= 2; 211 if (code >= nsysent) 212 callp = &sysent[0]; /* indir (illegal) */ 213 else { 214 callp = &sysent[code]; 215 if (callp == sysent) { /* indir */ 216 i = fuword(params); 217 params += NBPW; 218 if ((unsigned)i >= nsysent) 219 callp = &sysent[0]; 220 else 221 callp = &sysent[i]; 222 } 223 } 224 if ((i = callp->sy_narg * sizeof (int)) && 225 (u.u_error = copyin(params, (caddr_t)u.u_arg, (u_int)i)) != 0) { 226 locr0[R0] = u.u_error; 227 locr0[PS] |= PSL_C; /* carry bit */ 228 goto done; 229 } 230 u.u_r.r_val1 = 0; 231 u.u_r.r_val2 = locr0[R1]; 232 if (setjmp(&u.u_qsave)) { 233 if (u.u_error == 0 && u.u_eosys != RESTARTSYS) 234 u.u_error = EINTR; 235 } else { 236 u.u_eosys = NORMALRETURN; 237 #ifdef SYSCALLTRACE 238 if (syscalltrace) { 239 register int i; 240 char *cp; 241 242 if (code >= nsysent) 243 printf("0x%x", code); 244 else 245 printf("%s", syscallnames[code]); 246 cp = "("; 247 for (i= 0; i < callp->sy_narg; i++) { 248 printf("%s%x", cp, u.u_arg[i]); 249 cp = ", "; 250 } 251 if (i) 252 putchar(')', 0); 253 putchar('\n', 0); 254 } 255 #endif 256 (*(callp->sy_call))(); 257 } 258 if (u.u_eosys == NORMALRETURN) { 259 if (u.u_error) { 260 locr0[R0] = u.u_error; 261 locr0[PS] |= PSL_C; /* carry bit */ 262 } else { 263 locr0[R0] = u.u_r.r_val1; 264 locr0[R1] = u.u_r.r_val2; 265 locr0[PS] &= ~PSL_C; 266 } 267 } else if (u.u_eosys == RESTARTSYS) 268 pc = opc; 269 /* else if (u.u_eosys == JUSTRETURN) */ 270 /* nothing to do */ 271 done: 272 p = u.u_procp; 273 if (p->p_cursig || ISSIG(p)) 274 psig(); 275 p->p_pri = p->p_usrpri; 276 if (runrun) { 277 /* 278 * Since we are u.u_procp, clock will normally just change 279 * our priority without moving us from one queue to another 280 * (since the running process is not on a queue.) 281 * If that happened after we setrq ourselves but before we 282 * swtch()'ed, we might not be on the queue indicated by 283 * our priority. 284 */ 285 (void) splclock(); 286 setrq(p); 287 u.u_ru.ru_nivcsw++; 288 swtch(); 289 } 290 if (u.u_prof.pr_scale) { 291 int ticks; 292 struct timeval *tv = &u.u_ru.ru_stime; 293 294 ticks = ((tv->tv_sec - syst.tv_sec) * 1000 + 295 (tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000); 296 if (ticks) 297 addupc(locr0[PC], &u.u_prof, ticks); 298 } 299 curpri = p->p_pri; 300 } 301 302 /* 303 * nonexistent system call-- signal process (may want to handle it) 304 * flag error if process won't see signal immediately 305 * Q: should we do that all the time ?? 306 */ 307 nosys() 308 { 309 if (u.u_signal[SIGSYS] == SIG_IGN || u.u_signal[SIGSYS] == SIG_HOLD) 310 u.u_error = EINVAL; 311 psignal(u.u_procp, SIGSYS); 312 } 313