/*#define HOWFAR*/ /*#define SYSCALLS */ /* @(#)trap.c 1.2 */ #include "sys/param.h" #include "sys/types.h" #include "sys/systm.h" #include "sys/dir.h" #include "sys/signal.h" #include "sys/user.h" #include "sys/errno.h" #include "sys/proc.h" #include "sys/reg.h" #include "sys/psl.h" #include "sys/trap.h" #ifdef mc68881 #include "sys/fptrap.h" #endif mc68881 #include "sys/seg.h" #include "sys/sysinfo.h" #ifndef VIRTUAL451 #include "sys/buserr.h" #endif #define EBIT 1 /* user error bit in PS: C-bit */ #define USER 0x1000 /* user-mode flag added to number */ #define NSYSENT 128 #ifdef SYSCALLS static char reserved[] = "reserved"; char *callnames[] = { /* 0 */ "indir", "exit", "fork", "read", /* 4 */ "write", "open", "close", "wait", /* 8 */ "creat", "link", "unlink", "exec", /* 12 */ "chdir", "time", "mknod", "chmod", /* 16 */ "chown", "break", "stat", "seek", /* 20 */ "getpid", "mount", "umount", "setuid", /* 24 */ "getuid", "stime", "ptrace", "alarm", /* 28 */ "fstat", "pause", "utime", "stty", /* 32 */ "gtty", "access", "nice", "sleep", /* 36 */ "sync", "kill", "csw", "setpgrp", /* 40 */ "tell", "dup", "pipe", "times", /* 44 */ "prof", "lock", "setgid", "getgid", /* 48 */ "sig", "msgsys", reserved, "acct", /* 52 */ "shmsys", "semsys", "ioctl", "phys", /* 56 */ "locking", "utssys", reserved, "exece", /* 60 */ "umask", "chroot", "fcntl", "ulimit", /* 64 */ "reboot", reserved, reserved, reserved, #ifdef UCB_NET /* 68 */ reserved, reserved, "select", "gethostname", /* 72 */ "sethostname", "socket", "accept", "connect", /* 76 */ "receive", "send", "socketaddr", "netreset", #else /* 68 */ reserved, reserved, reserved, reserved, /* 72 */ reserved, reserved, reserved, reserved, /* 76 */ reserved, reserved, reserved, reserved, #endif /* 80 */ reserved, reserved, reserved, reserved, /* 84 */ reserved, reserved, reserved, reserved, /* 88 */ reserved, reserved, reserved, reserved, /* 92 */ reserved, reserved, reserved, reserved, /* 96 */ reserved, reserved, reserved, reserved, /* 100 */ reserved, reserved, reserved, reserved, /* 104 */ reserved, reserved, reserved, reserved, /* 108 */ reserved, reserved, reserved, reserved, /* 112 */ reserved, reserved, reserved, reserved, /* 116 */ reserved, reserved, reserved, reserved, /* 120 */ reserved, reserved, reserved, reserved, /* 124 */ reserved, reserved, reserved, reserved }; #endif /* * Offsets of the user's registers relative to * the saved r0. See reg.h */ char regloc[8+8+1+1] = { R0, R1, R2, R3, R4, R5, R6, R7, AR0, AR1, AR2, AR3, AR4, AR5, AR6, SP, PC, RPS }; /* * Called from the trap handler when a processor trap occurs. */ trap(number, regs) short number; { register struct user *up; extern int parityno; register i; time_t syst; int retval; int *oldar0; #ifdef mc68881 /* MC68881 floating-point coprocessor */ extern short fp881; /* is there an MC68881? */ #endif mc68881 up = &u; retval = 0; syst = up->u_stime; #ifdef FLOAT /* sky floating point board */ up->u_fpsaved = 0; #endif oldar0 = up->u_ar0; up->u_ar0 = ®s; if (USERMODE(up->u_ar0[RPS])) number |= USER; #ifdef HOWFAR if (number != RESCHED && number != RESCHED+USER) { printf("trap number=0x%x ps=0x%x\n", number, up->u_ar0[RPS]&0xFFFF); showregs(1); } #endif /* * Handle parity specially to make it processor independent */ if (number==parityno || number==(parityno|USER)) { if ((i = parityerror()) == 0) { logparity((paddr_t)&up->u_ar0[PC]); goto out; } if (i > 0) { number = i | (number & USER); goto sw; } if (number & USER) { logparity((paddr_t)&up->u_ar0[PC]); i = SIGBUS; } else { if (nofault) { up->u_ar0 = oldar0; longjmp(nofault, -1); } showbus(); panic("kernel parity error"); } } else { sw: switch(number) { /* * Trap not expected. * Usually a kernel mode bus error. */ default: if ((number & USER) == 0) { panicstr = "trap"; /* fake it for printfs */ printf("\ntrap type %d\n", number); showregs(1); panic("unexpected kernel trap"); } case CHK + USER: /* CHK instruction */ case TRAPV + USER: /* TRAPV instruction */ case PRIVVIO + USER: /* Priviledge violation */ case L1010 + USER: /* Line 1010 emulator */ case L1111 + USER: /* Line 1111 emulator */ case TRAP4 + USER: case TRAP5 + USER: case TRAP6 + USER: case TRAP7 + USER: case TRAP8 + USER: case TRAP9 + USER: case TRAP10 + USER: case TRAP11 + USER: case TRAP12 + USER: case TRAP13 + USER: case TRAP14 + USER: case TRAP15 + USER: case ILLINST + USER: /* illegal instruction */ i = SIGILL; break; case DIVZERO + USER: /* zero divide */ i = SIGFPE; break; #ifdef mc68881 /* MC68881 floating-point coprocessor */ case FPBSUN + USER: /* Branch or Set on Unordered Condition */ case FPINEX + USER: /* Inexact Result */ case FPDZ + USER: /* Floating Point Divide by Zero */ case FPUNFL + USER: /* Underflow */ case FPOPERR + USER: /* Operand Error */ case FPOVFL + USER: /* Overflow */ case FPSNAN + USER: /* Signalling NAN (Not-A-Number) */ up->u_fpexc = number & 0xFF; i = SIGFPE; break; #endif mc68881 case TRCTRAP: /* trace out of kernel mode - */ up->u_ar0 = oldar0; return(retval); /* this is happens when a trap instruction */ /* is executed with the trace bit set */ case TRCTRAP + USER: /* trace */ case TRAP1 + USER: /* bpt - trap #1 */ i = SIGTRAP; up->u_ar0[RPS] &= ~PS_T; break; case TRAP2 + USER: /* iot - trap #2 */ i = SIGIOT; break; case TRAP3 + USER: /* emt - trap #3 */ i = SIGEMT; break; case SYSCALL + USER: /* sys call - trap #0 */ panic("syscall\n"); /* * Allow process switch */ case RESCHED + USER: case RESCHED: qswtch(); goto out; #ifdef VIRTUAL451 /* * If the user SP is below the stack segment * and within STACKGAP clicks of the bottom * of the stack segment, then grow the * stack automatically. */ case ADDRERR + USER: /* bus error - address error */ i = SIGBUS; retval = 1; trapaddr((struct buserr *)®s); break; case BUSERR + USER: /* memory management error - bus error */ if(pagein((int)(((struct buserr *)®s)->ber_faddr))) { up->u_ar0 = oldar0; return(0); } i = SIGSEGV; retval = 1; trapaddr((struct buserr *)®s); break; case ADDRERR: /* bus error - address error */ trapaddr((struct buserr *)®s); printf("kernel address error\n"); showbus(); panic("kernel memory management error"); case BUSERR: /* memory management error - bus error in kernel */ if (nofault) { up->u_ar0 = oldar0; longjmp(nofault, -1); } trapaddr((struct buserr *)®s); berdump((struct buserr *)®s); printf("kernel bus error\n"); showbus(); panic("kernel memory management error"); #else /* * If the user SP is below the stack segment, * grow the stack automatically. * This relies on the ability of the hardware * to restart a half executed instruction. * On the 68000 this is not the case and * the routine machdep/backup() will fail. */ case ADDRERR + USER: /* bus error - address error */ i = SIGBUS; retval = 1; trapaddr((struct buserr *)®s); break; case BUSERR + USER: /* memory management error - bus error */ if (i = backup(up->u_ar0)) if (grow((unsigned)(up->u_ar0[SP]+i))) goto out; i = SIGSEGV; retval = 1; trapaddr((struct buserr *)®s); break; case ADDRERR: /* kernel address error */ case BUSERR: /* kernel bus error */ if (nofault) longjmp(nofault, -1); trapaddr((struct buserr *)®s); showbus(); panic("kernel memory management error\n"); #endif /* * Unused trap vectors generate this trap type. * Reciept of this trap is a * symptom of hardware problems and may * represent a real interrupt that got * sent to the wrong place. Watch out * for hangs on disk completion if this message appears. */ case SPURINT: case SPURINT + USER: printf("\nRandom interrupt ignored\n"); up->u_ar0 = oldar0; return(retval); } } /* end else ... */ psignal(up->u_procp, i); out: if (up->u_procp->p_sig && issig()) psig(); if (up->u_prof.pr_scale) addupc((unsigned)up->u_ar0[PC], &up->u_prof, (int)(up->u_stime-syst)); #ifdef FLOAT /* sky floating point board */ if (up->u_fpinuse && up->u_fpsaved) restfp(); #endif #ifdef mc68881 /* MC68881 floating-point coprocessor */ if (fp881) fprest(); #endif mc68881 up->u_ar0 = oldar0; return(retval); } /* * process a system call */ syscall(regs) { register struct proc *pp; register struct user *up; register *regp, *argp; register i; int *oldar0; #ifdef mc68881 /* MC68881 floating-point coprocessor */ extern short fp881; /* is there an MC68881? */ #endif mc68881 up = &u; sysinfo.syscall++; up->u_error = 0; #ifdef FLOAT /* sky floating point board */ up->u_fpsaved = 0; #endif oldar0 = up->u_ar0; up->u_ar0 = regp = ®s; up->u_ap = argp = up->u_arg; i = regp[R0] & 0377; if (i >= NSYSENT) i = 0; argp[0] = regp[AR0]; argp[1] = regp[R1]; argp[2] = regp[AR1]; argp[3] = regp[R2]; argp[4] = regp[AR2]; argp[5] = regp[R3]; #ifdef SYSCALLS printf("***** %s: %x %x %x %x\n", callnames[i], argp[0], argp[1], argp[2], argp[3], argp[4], argp[5]); #endif up->u_dirp = (caddr_t)argp[0]; up->u_rval1 = 0; up->u_rval2 = regp[R1]; if (qsave(up->u_qsav)) { /* * restore registers not saved by qsave */ up = &u; regp = ®s; argp = up->u_arg; if (up->u_error==0) up->u_error = EINTR; } else { (*(sysent[i].sy_call))(); } if (up->u_error) { regp[R0] = up->u_error; regp[RPS] |= PS_C; /* carry bit */ if (++up->u_errcnt > 16) { up->u_errcnt = 0; runrun++; } #ifdef SYSCALLS printf(" syscall error = %d, pc = 0x%x\n", up->u_error, regp[PC]); #endif } else { #ifdef SYSCALLS printf(" syscall success, pc = 0x%x\n", regp[PC]); #endif regp[RPS] &= ~PS_C; /* carry bit */ regp[R0] = up->u_rval1; regp[R1] = up->u_rval2; } pp = up->u_procp; /* * Test if the trap instruction was executed with the * trace bit set (the trace trap was already ignored) * and set the trace signal to avoid missing the trace * on the trap instruction. */ pp->p_pri = (pp->p_cpu>>1) + (PUSER - NZERO) + pp->p_nice; curpri = pp->p_pri; if (pp->p_sig && issig()) psig(); up->u_ar0 = oldar0; if (runrun) qswtch(); #ifdef FLOAT /* sky floating point board */ if (up->u_fpinuse && up->u_fpsaved) restfp(); #endif #ifdef mc68881 /* MC68881 floating-point coprocessor */ if (fp881) fprest(); #endif mc68881 } /* * nonexistent system call-- signal bad system call. */ nosys() { psignal(u.u_procp, SIGSYS); } /* * Ignored system call */ nullsys() { } stray(addr) physadr addr; { logstray(addr); printf("stray interrupt at %x\n", addr); } /* * trapaddr - Save the info from a 68010 bus or address error. */ trapaddr(ap) register struct buserr *ap; { extern int cputype; if (cputype == 0) return; u.u_fcode = ap->ber_sstat; u.u_aaddr = ap->ber_faddr; u.u_ireg = ap->ber_iib; } /* * showbus - print out status on mmgt error */ showbus() { register struct user *up; up = &u; printf("vaddr = 0x%x paddr = 0x%x ireg = 0x%x fcode = 0x%x\n", up->u_aaddr, vtop((caddr_t)up->u_aaddr), up->u_ireg&0xFFFF, up->u_fcode&0xF); showregs(1); } /* * Show a processes registers */ showregs(mmuflg) int mmuflg; { register struct user *up; register int i, j; char command[DIRSIZ+1]; up = &u; #ifdef HOWFAR if (mmuflg) dumpmm(-1); #endif HOWFAR #ifdef lint dumpmm(mmuflg); #endif lint for (i=0; iu_comm[i]; if (j<=' ' || j>=0x7F) break; command[i] = j; } command[i] = 0; /* * separate prints in case up or u_procp trashed */ printf("pc = 0x%x sr = 0x%x up->u_procp = 0x%x", up->u_ar0[PC], up->u_ar0[RPS]&0xFFFF, up->u_procp); printf(" pid = %d exec = '%s'\n", up->u_procp->p_pid, command); for (i = 0; i < 16; i++) { printf("0x%x ", up->u_ar0[i]); if (i == 7 || i == 15) printf("\n"); } } #ifdef DUMPSTK #include #ifndef VIRTUAL451 #include #endif #include /* * dump the present contents of the stack */ dumpstack(ret) { register unsigned short *ip; ip = (unsigned short *)&ret; ip -= 4; printf("\n%x ", ip); while (ip < (unsigned short *)((int)&u+ctob(v.v_usize))) { if (((int)ip & 31) == 0) printf("\n%x ", ip); printf(" %x", *ip++); } printf("\n"); if (ret != 0) panic("**** ABORTING ****"); } /* * dump the present contents of the user stack */ dumpustack(max) unsigned max; { register unsigned short *ip, *jp; register unsigned i, n; ip = (unsigned short *)(u.u_ar0[SP] - 20); jp = ip + 64; if (jp < (unsigned short *)max) jp = (unsigned short *)max; if (jp > (unsigned short *)v.v_uend) jp = (unsigned short *)v.v_uend; printf("\n%x ", ip); while (ip < jp) { i = (fuword(ip++) >> 16) & 0xFFFF; if (((int)ip & 31) == 0) printf("\n%x ", ip); printf(" %x", i); } printf("\n"); } #endif