|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1988 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) 5/21/88 ! 7: */ ! 8: ! 9: #include "param.h" ! 10: #include "systm.h" ! 11: #include "dir.h" ! 12: #include "user.h" ! 13: #include "proc.h" ! 14: #include "seg.h" ! 15: #include "acct.h" ! 16: #include "kernel.h" ! 17: ! 18: #include "psl.h" ! 19: #include "reg.h" ! 20: #include "pte.h" ! 21: #include "mtpr.h" ! 22: ! 23: #define SYSCALLTRACE ! 24: #ifdef SYSCALLTRACE ! 25: #include "../sys/syscalls.c" ! 26: #endif ! 27: ! 28: #include "../tahoe/trap.h" ! 29: ! 30: #define USER 040 /* user-mode flag added to type */ ! 31: ! 32: struct sysent sysent[]; ! 33: int nsysent; ! 34: ! 35: char *trap_type[] = { ! 36: "Reserved addressing mode", /* T_RESADFLT */ ! 37: "Privileged instruction", /* T_PRIVINFLT */ ! 38: "Reserved operand", /* T_RESOPFLT */ ! 39: "Breakpoint", /* T_BPTFLT */ ! 40: 0, ! 41: "Kernel call", /* T_SYSCALL */ ! 42: "Arithmetic trap", /* T_ARITHTRAP */ ! 43: "System forced exception", /* T_ASTFLT */ ! 44: "Segmentation fault", /* T_SEGFLT */ ! 45: "Protection fault", /* T_PROTFLT */ ! 46: "Trace trap", /* T_TRCTRAP */ ! 47: 0, ! 48: "Page fault", /* T_PAGEFLT */ ! 49: "Page table fault", /* T_TABLEFLT */ ! 50: "Alignment fault", /* T_ALIGNFLT */ ! 51: "Kernel stack not valid", /* T_KSPNOTVAL */ ! 52: "Bus error", /* T_BUSERR */ ! 53: "Kernel debugger trap", /* T_KDBTRAP */ ! 54: }; ! 55: int TRAP_TYPES = sizeof (trap_type) / sizeof (trap_type[0]); ! 56: ! 57: /* ! 58: * Called from the trap handler when a processor trap occurs. ! 59: */ ! 60: /*ARGSUSED*/ ! 61: trap(sp, type, hfs, accmst, acclst, dbl, code, pc, psl) ! 62: unsigned type, code; ! 63: { ! 64: int r0, r1; /* must reserve space */ ! 65: register int *locr0 = ((int *)&psl)-PS; ! 66: register int i; ! 67: register struct proc *p; ! 68: struct timeval syst; ! 69: ! 70: #ifdef lint ! 71: r0 = 0; r0 = r0; r1 = 0; r1 = r1; ! 72: #endif ! 73: syst = u.u_ru.ru_stime; ! 74: if (USERMODE(locr0[PS])) { ! 75: type |= USER; ! 76: u.u_ar0 = locr0; ! 77: } ! 78: switch (type) { ! 79: ! 80: default: ! 81: #ifdef KADB ! 82: if (kdb_trap(&psl)) ! 83: return; ! 84: #endif ! 85: printf("trap type %d, code = %x, pc = %x\n", type, code, pc); ! 86: type &= ~USER; ! 87: if (type < TRAP_TYPES && trap_type[type]) ! 88: panic(trap_type[type]); ! 89: else ! 90: panic("trap"); ! 91: /*NOTREACHED*/ ! 92: ! 93: case T_PROTFLT + USER: /* protection fault */ ! 94: i = SIGBUS; ! 95: break; ! 96: ! 97: case T_PRIVINFLT + USER: /* privileged instruction fault */ ! 98: case T_RESADFLT + USER: /* reserved addressing fault */ ! 99: case T_RESOPFLT + USER: /* resereved operand fault */ ! 100: case T_ALIGNFLT + USER: /* unaligned data fault */ ! 101: u.u_code = type &~ USER; ! 102: i = SIGILL; ! 103: break; ! 104: ! 105: case T_ASTFLT + USER: /* Allow process switch */ ! 106: case T_ASTFLT: ! 107: astoff(); ! 108: if ((u.u_procp->p_flag & SOWEUPC) && u.u_prof.pr_scale) { ! 109: addupc(pc, &u.u_prof, 1); ! 110: u.u_procp->p_flag &= ~SOWEUPC; ! 111: } ! 112: goto out; ! 113: ! 114: case T_ARITHTRAP + USER: ! 115: u.u_code = code; ! 116: i = SIGFPE; ! 117: break; ! 118: ! 119: /* ! 120: * If the user SP is above the stack segment, ! 121: * grow the stack automatically. ! 122: */ ! 123: case T_SEGFLT + USER: ! 124: if (grow((unsigned)locr0[SP]) || grow(code)) ! 125: goto out; ! 126: i = SIGSEGV; ! 127: break; ! 128: ! 129: case T_TABLEFLT: /* allow page table faults in kernel */ ! 130: case T_TABLEFLT + USER: /* page table fault */ ! 131: panic("ptable fault"); ! 132: ! 133: case T_PAGEFLT: /* allow page faults in kernel mode */ ! 134: case T_PAGEFLT + USER: /* page fault */ ! 135: i = u.u_error; ! 136: pagein(code, 0); ! 137: u.u_error = i; ! 138: if (type == T_PAGEFLT) ! 139: return; ! 140: goto out; ! 141: ! 142: case T_BPTFLT + USER: /* bpt instruction fault */ ! 143: case T_TRCTRAP + USER: /* trace trap */ ! 144: locr0[PS] &= ~PSL_T; ! 145: i = SIGTRAP; ! 146: break; ! 147: ! 148: /* ! 149: * For T_KSPNOTVAL and T_BUSERR, can not allow spl to ! 150: * drop to 0 as clock could go off and we would end up ! 151: * doing an rei to the interrupt stack at ipl 0 (a ! 152: * reserved operand fault). Instead, we allow psignal ! 153: * to post an ast, then return to user mode where we ! 154: * will reenter the kernel on the kernel's stack and ! 155: * can then service the signal. ! 156: */ ! 157: case T_KSPNOTVAL: ! 158: if (noproc) ! 159: panic("ksp not valid"); ! 160: /* fall thru... */ ! 161: case T_KSPNOTVAL + USER: ! 162: printf("pid %d: ksp not valid\n", u.u_procp->p_pid); ! 163: /* must insure valid kernel stack pointer? */ ! 164: psignal(u.u_procp, SIGKILL); ! 165: return; ! 166: ! 167: case T_BUSERR + USER: ! 168: u.u_code = code; ! 169: psignal(u.u_procp, SIGBUS); ! 170: return; ! 171: } ! 172: psignal(u.u_procp, i); ! 173: out: ! 174: p = u.u_procp; ! 175: if (p->p_cursig || ISSIG(p)) ! 176: psig(); ! 177: p->p_pri = p->p_usrpri; ! 178: if (runrun) { ! 179: /* ! 180: * Since we are u.u_procp, clock will normally just change ! 181: * our priority without moving us from one queue to another ! 182: * (since the running process is not on a queue.) ! 183: * If that happened after we setrq ourselves but before we ! 184: * swtch()'ed, we might not be on the queue indicated by ! 185: * our priority. ! 186: */ ! 187: (void) splclock(); ! 188: setrq(p); ! 189: u.u_ru.ru_nivcsw++; ! 190: swtch(); ! 191: } ! 192: if (u.u_prof.pr_scale) { ! 193: int ticks; ! 194: struct timeval *tv = &u.u_ru.ru_stime; ! 195: ! 196: ticks = ((tv->tv_sec - syst.tv_sec) * 1000 + ! 197: (tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000); ! 198: if (ticks) ! 199: addupc(locr0[PC], &u.u_prof, ticks); ! 200: } ! 201: curpri = p->p_pri; ! 202: } ! 203: ! 204: #ifdef SYSCALLTRACE ! 205: int syscalltrace = 0; ! 206: #endif ! 207: ! 208: /* ! 209: * Called from locore when a system call occurs ! 210: */ ! 211: /*ARGSUSED*/ ! 212: syscall(sp, type, hfs, accmst, acclst, dbl, code, pc, psl) ! 213: unsigned code; ! 214: { ! 215: int r0, r1; /* must reserve space */ ! 216: register int *locr0 = ((int *)&psl)-PS; ! 217: register caddr_t params; ! 218: register int i; ! 219: register struct sysent *callp; ! 220: register struct proc *p; ! 221: struct timeval syst; ! 222: int opc; ! 223: ! 224: #ifdef lint ! 225: r0 = 0; r0 = r0; r1 = 0; r1 = r1; ! 226: #endif ! 227: syst = u.u_ru.ru_stime; ! 228: if (!USERMODE(locr0[PS])) ! 229: panic("syscall"); ! 230: u.u_ar0 = locr0; ! 231: if (code == 139) { /* 4.2 COMPATIBILTY XXX */ ! 232: osigcleanup(); /* 4.2 COMPATIBILTY XXX */ ! 233: goto done; /* 4.2 COMPATIBILTY XXX */ ! 234: } ! 235: params = (caddr_t)locr0[FP] + NBPW; ! 236: u.u_error = 0; ! 237: /* BEGIN GROT */ ! 238: /* ! 239: * Try to reconstruct pc, assuming code ! 240: * is an immediate constant ! 241: */ ! 242: opc = pc - 2; /* short literal */ ! 243: if (code > 0x3f) { ! 244: opc--; /* byte immediate */ ! 245: if (code > 0x7f) { ! 246: opc--; /* word immediate */ ! 247: if (code > 0x7fff) ! 248: opc -= 2; /* long immediate */ ! 249: } ! 250: } ! 251: /* END GROT */ ! 252: callp = (code >= nsysent) ? &sysent[63] : &sysent[code]; ! 253: if (callp == sysent) { ! 254: i = fuword(params); ! 255: params += NBPW; ! 256: callp = (code >= nsysent) ? &sysent[63] : &sysent[code]; ! 257: } ! 258: if ((i = callp->sy_narg * sizeof (int)) && ! 259: (u.u_error = copyin(params, (caddr_t)u.u_arg, (u_int)i)) != 0) { ! 260: locr0[R0] = u.u_error; ! 261: locr0[PS] |= PSL_C; /* carry bit */ ! 262: goto done; ! 263: } ! 264: u.u_r.r_val1 = 0; ! 265: u.u_r.r_val2 = locr0[R1]; ! 266: if (setjmp(&u.u_qsave)) { ! 267: if (u.u_error == 0 && u.u_eosys != RESTARTSYS) ! 268: u.u_error = EINTR; ! 269: } else { ! 270: u.u_eosys = NORMALRETURN; ! 271: #ifdef SYSCALLTRACE ! 272: if (syscalltrace) { ! 273: register int a; ! 274: char *cp; ! 275: ! 276: if (code >= nsysent) ! 277: printf("0x%x", code); ! 278: else ! 279: printf("%s", syscallnames[code]); ! 280: cp = "("; ! 281: for (a = 0; a < callp->sy_narg; a++) { ! 282: printf("%s%x", cp, u.u_arg[a]); ! 283: cp = ", "; ! 284: } ! 285: if (a) ! 286: printf(")"); ! 287: printf("\n"); ! 288: } ! 289: #endif ! 290: (*callp->sy_call)(); ! 291: } ! 292: if (u.u_eosys == NORMALRETURN) { ! 293: if (u.u_error) { ! 294: locr0[R0] = u.u_error; ! 295: locr0[PS] |= PSL_C; /* carry bit */ ! 296: } else { ! 297: locr0[PS] &= ~PSL_C; /* clear carry bit */ ! 298: locr0[R0] = u.u_r.r_val1; ! 299: locr0[R1] = u.u_r.r_val2; ! 300: } ! 301: } else if (u.u_eosys == RESTARTSYS) ! 302: pc = opc; ! 303: /* else if (u.u_eosys == JUSTRETURN) */ ! 304: /* nothing to do */ ! 305: done: ! 306: p = u.u_procp; ! 307: if (p->p_cursig || ISSIG(p)) ! 308: psig(); ! 309: p->p_pri = p->p_usrpri; ! 310: if (runrun) { ! 311: /* ! 312: * Since we are u.u_procp, clock will normally just change ! 313: * our priority without moving us from one queue to another ! 314: * (since the running process is not on a queue.) ! 315: * If that happened after we setrq ourselves but before we ! 316: * swtch()'ed, we might not be on the queue indicated by ! 317: * our priority. ! 318: */ ! 319: (void) splclock(); ! 320: setrq(p); ! 321: u.u_ru.ru_nivcsw++; ! 322: swtch(); ! 323: } ! 324: if (u.u_prof.pr_scale) { ! 325: int ticks; ! 326: struct timeval *tv = &u.u_ru.ru_stime; ! 327: ! 328: ticks = ((tv->tv_sec - syst.tv_sec) * 1000 + ! 329: (tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000); ! 330: if (ticks) ! 331: addupc(locr0[PC], &u.u_prof, ticks); ! 332: } ! 333: curpri = p->p_pri; ! 334: } ! 335: ! 336: /* ! 337: * nonexistent system call-- signal process (may want to handle it) ! 338: * flag error if process won't see signal immediately ! 339: * Q: should we do that all the time ?? ! 340: */ ! 341: nosys() ! 342: { ! 343: ! 344: if (u.u_signal[SIGSYS] == SIG_IGN || u.u_signal[SIGSYS] == SIG_HOLD) ! 345: u.u_error = EINVAL; ! 346: psignal(u.u_procp, SIGSYS); ! 347: } ! 348: ! 349: #ifdef notdef ! 350: /* ! 351: * Ignored system call ! 352: */ ! 353: nullsys() ! 354: { ! 355: ! 356: } ! 357: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.