1 /* 2 * Copyright (c) 1982 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 6.6 (Berkeley) 06/08/85 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 #ifdef notdef 48 "Page fault", 49 "Page table fault", 50 #endif 51 }; 52 #define 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, code, pc, psl) 59 int sp, type; 60 unsigned code; 61 int pc, psl; 62 { 63 register int *locr0 = ((int *)&psl)-PS; 64 register int i; 65 register struct proc *p; 66 struct timeval syst; 67 68 syst = u.u_ru.ru_stime; 69 if (USERMODE(locr0[PS])) { 70 type |= USER; 71 u.u_ar0 = locr0; 72 } 73 switch (type) { 74 75 default: 76 printf("trap type %d, code = %x, pc = %x\n", type, code, pc); 77 type &= ~USER; 78 if ((unsigned)type < TRAP_TYPES) 79 panic(trap_type[type]); 80 panic("trap"); 81 82 case T_PROTFLT+USER: /* protection fault */ 83 i = SIGBUS; 84 break; 85 86 case T_PRIVINFLT+USER: /* privileged instruction fault */ 87 case T_RESADFLT+USER: /* reserved addressing fault */ 88 case T_RESOPFLT+USER: /* resereved operand fault */ 89 u.u_code = type &~ USER; 90 i = SIGILL; 91 break; 92 93 case T_ASTFLT+USER: 94 astoff(); 95 if ((u.u_procp->p_flag & SOWEUPC) && u.u_prof.pr_scale) { 96 addupc(pc, &u.u_prof, 1); 97 u.u_procp->p_flag &= ~SOWEUPC; 98 } 99 goto out; 100 101 case T_ARITHTRAP+USER: 102 u.u_code = code; 103 i = SIGFPE; 104 break; 105 106 /* 107 * If the user SP is above the stack segment, 108 * grow the stack automatically. 109 */ 110 case T_SEGFLT+USER: 111 if (grow((unsigned)locr0[SP]) || grow(code)) 112 goto out; 113 i = SIGSEGV; 114 break; 115 116 case T_TABLEFLT: /* allow page table faults in kernel mode */ 117 case T_TABLEFLT+USER: /* page table fault */ 118 panic("ptable fault"); 119 120 case T_PAGEFLT: /* allow page faults in kernel mode */ 121 case T_PAGEFLT+USER: /* page fault */ 122 i = u.u_error; 123 pagein(code, 0); 124 u.u_error = i; 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 u.u_code = code; 142 i = SIGILL; 143 break; 144 } 145 psignal(u.u_procp, i); 146 out: 147 p = u.u_procp; 148 if (p->p_cursig || ISSIG(p)) 149 psig(); 150 p->p_pri = p->p_usrpri; 151 if (runrun) { 152 /* 153 * Since we are u.u_procp, clock will normally just change 154 * our priority without moving us from one queue to another 155 * (since the running process is not on a queue.) 156 * If that happened after we setrq ourselves but before we 157 * swtch()'ed, we might not be on the queue indicated by 158 * our priority. 159 */ 160 (void) spl6(); 161 setrq(p); 162 u.u_ru.ru_nivcsw++; 163 swtch(); 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 curpri = p->p_pri; 175 } 176 177 #ifdef SYSCALLTRACE 178 int syscalltrace = 0; 179 #endif 180 /* 181 * Called from the trap handler when a system call occurs 182 */ 183 /*ARGSUSED*/ 184 syscall(sp, type, code, pc, psl) 185 unsigned code; 186 { 187 register int *locr0 = ((int *)&psl)-PS; 188 register caddr_t params; /* known to be r10 below */ 189 register int i; /* known to be r9 below */ 190 register struct sysent *callp; 191 register struct proc *p; 192 int opc; 193 struct timeval syst; 194 195 syst = u.u_ru.ru_stime; 196 if (!USERMODE(locr0[PS])) 197 panic("syscall"); 198 u.u_ar0 = locr0; 199 if (code == 139) { /* XXX 4.2 COMPATIBILITY */ 200 osigcleanup(); /* XXX 4.2 COMPATIBILITY */ 201 goto done; /* XXX 4.2 COMPATIBILITY */ 202 } /* XXX 4.2 COMPATIBILITY */ 203 params = (caddr_t)locr0[AP] + NBPW; 204 u.u_error = 0; 205 opc = pc - 2; 206 if (code > 63) 207 opc -= 2; 208 callp = (code >= nsysent) ? &sysent[63] : &sysent[code]; 209 if (callp == sysent) { 210 i = fuword(params); 211 params += NBPW; 212 callp = ((unsigned)i >= nsysent) ? &sysent[63] : &sysent[i]; 213 } 214 if ((i = callp->sy_narg * sizeof (int)) && 215 (u.u_error = copyin(params, (caddr_t)u.u_arg, (u_int)i)) != 0) { 216 locr0[R0] = u.u_error; 217 locr0[PS] |= PSL_C; /* carry bit */ 218 goto done; 219 } 220 u.u_r.r_val1 = 0; 221 u.u_r.r_val2 = locr0[R1]; 222 if (setjmp(&u.u_qsave)) { 223 if (u.u_error == 0 && u.u_eosys != RESTARTSYS) 224 u.u_error = EINTR; 225 } else { 226 u.u_eosys = NORMALRETURN; 227 #ifdef SYSCALLTRACE 228 if (syscalltrace) { 229 register int i; 230 char *cp; 231 232 if (code >= nsysent) 233 printf("0x%x", code); 234 else 235 printf("%s", syscallnames[code]); 236 cp = "("; 237 for (i= 0; i < callp->sy_narg; i++) { 238 printf("%s%x", cp, u.u_arg[i]); 239 cp = ", "; 240 } 241 if (i) 242 putchar(')', 0); 243 putchar('\n', 0); 244 } 245 #endif 246 (*(callp->sy_call))(); 247 } 248 if (u.u_eosys == NORMALRETURN) { 249 if (u.u_error) { 250 locr0[R0] = u.u_error; 251 locr0[PS] |= PSL_C; /* carry bit */ 252 } else { 253 locr0[R0] = u.u_r.r_val1; 254 locr0[R1] = u.u_r.r_val2; 255 locr0[PS] &= ~PSL_C; 256 } 257 } else if (u.u_eosys == RESTARTSYS) 258 pc = opc; 259 /* else if (u.u_eosys == JUSTRETURN) */ 260 /* nothing to do */ 261 done: 262 p = u.u_procp; 263 if (p->p_cursig || ISSIG(p)) 264 psig(); 265 p->p_pri = p->p_usrpri; 266 if (runrun) { 267 /* 268 * Since we are u.u_procp, clock will normally just change 269 * our priority without moving us from one queue to another 270 * (since the running process is not on a queue.) 271 * If that happened after we setrq ourselves but before we 272 * swtch()'ed, we might not be on the queue indicated by 273 * our priority. 274 */ 275 (void) spl6(); 276 setrq(p); 277 u.u_ru.ru_nivcsw++; 278 swtch(); 279 } 280 if (u.u_prof.pr_scale) { 281 int ticks; 282 struct timeval *tv = &u.u_ru.ru_stime; 283 284 ticks = ((tv->tv_sec - syst.tv_sec) * 1000 + 285 (tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000); 286 if (ticks) 287 addupc(locr0[PC], &u.u_prof, ticks); 288 } 289 curpri = p->p_pri; 290 } 291 292 /* 293 * nonexistent system call-- signal process (may want to handle it) 294 * flag error if process won't see signal immediately 295 * Q: should we do that all the time ?? 296 */ 297 nosys() 298 { 299 if (u.u_signal[SIGSYS] == SIG_IGN || u.u_signal[SIGSYS] == SIG_HOLD) 300 u.u_error = EINVAL; 301 psignal(u.u_procp, SIGSYS); 302 } 303