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.1 (Berkeley) 6/5/86 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) splclock(); 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: if (code >= nsysent) 209: callp = &sysent[0]; /* indir (illegal) */ 210: else { 211: callp = &sysent[code]; 212: if (callp == sysent) { /* indir */ 213: i = fuword(params); 214: params += NBPW; 215: if ((unsigned)i >= nsysent) 216: callp = &sysent[0]; 217: else 218: callp = &sysent[i]; 219: } 220: } 221: if ((i = callp->sy_narg * sizeof (int)) && 222: (u.u_error = copyin(params, (caddr_t)u.u_arg, (u_int)i)) != 0) { 223: locr0[R0] = u.u_error; 224: locr0[PS] |= PSL_C; /* carry bit */ 225: goto done; 226: } 227: u.u_r.r_val1 = 0; 228: u.u_r.r_val2 = locr0[R1]; 229: if (setjmp(&u.u_qsave)) { 230: if (u.u_error == 0 && u.u_eosys != RESTARTSYS) 231: u.u_error = EINTR; 232: } else { 233: u.u_eosys = NORMALRETURN; 234: #ifdef SYSCALLTRACE 235: if (syscalltrace) { 236: register int i; 237: char *cp; 238: 239: if (code >= nsysent) 240: printf("0x%x", code); 241: else 242: printf("%s", syscallnames[code]); 243: cp = "("; 244: for (i= 0; i < callp->sy_narg; i++) { 245: printf("%s%x", cp, u.u_arg[i]); 246: cp = ", "; 247: } 248: if (i) 249: putchar(')', 0); 250: putchar('\n', 0); 251: } 252: #endif 253: (*(callp->sy_call))(); 254: } 255: if (u.u_eosys == NORMALRETURN) { 256: if (u.u_error) { 257: locr0[R0] = u.u_error; 258: locr0[PS] |= PSL_C; /* carry bit */ 259: } else { 260: locr0[R0] = u.u_r.r_val1; 261: locr0[R1] = u.u_r.r_val2; 262: locr0[PS] &= ~PSL_C; 263: } 264: } else if (u.u_eosys == RESTARTSYS) 265: pc = opc; 266: /* else if (u.u_eosys == JUSTRETURN) */ 267: /* nothing to do */ 268: done: 269: p = u.u_procp; 270: if (p->p_cursig || ISSIG(p)) 271: psig(); 272: p->p_pri = p->p_usrpri; 273: if (runrun) { 274: /* 275: * Since we are u.u_procp, clock will normally just change 276: * our priority without moving us from one queue to another 277: * (since the running process is not on a queue.) 278: * If that happened after we setrq ourselves but before we 279: * swtch()'ed, we might not be on the queue indicated by 280: * our priority. 281: */ 282: (void) splclock(); 283: setrq(p); 284: u.u_ru.ru_nivcsw++; 285: swtch(); 286: } 287: if (u.u_prof.pr_scale) { 288: int ticks; 289: struct timeval *tv = &u.u_ru.ru_stime; 290: 291: ticks = ((tv->tv_sec - syst.tv_sec) * 1000 + 292: (tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000); 293: if (ticks) 294: addupc(locr0[PC], &u.u_prof, ticks); 295: } 296: curpri = p->p_pri; 297: } 298: 299: /* 300: * nonexistent system call-- signal process (may want to handle it) 301: * flag error if process won't see signal immediately 302: * Q: should we do that all the time ?? 303: */ 304: nosys() 305: { 306: if (u.u_signal[SIGSYS] == SIG_IGN || u.u_signal[SIGSYS] == SIG_HOLD) 307: u.u_error = EINVAL; 308: psignal(u.u_procp, SIGSYS); 309: }