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