1: /* 2: * Copyright (c) 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 1.6 (2.11BSD) 1999/9/13 7: */ 8: 9: #include "param.h" 10: #include "../machine/psl.h" 11: #include "../machine/reg.h" 12: #include "../machine/seg.h" 13: #include "../machine/trap.h" 14: #include "../machine/iopage.h" 15: 16: #include "signalvar.h" 17: #include "systm.h" 18: #include "user.h" 19: #include "proc.h" 20: #include "vm.h" 21: 22: extern int fpp, kdj11; 23: 24: #ifdef INET 25: extern int netoff; 26: #endif 27: 28: #ifdef DIAGNOSTIC 29: extern int hasmap; 30: static int savhasmap; 31: #endif 32: 33: /* 34: * Offsets of the user's registers relative to 35: * the saved r0. See sys/reg.h. 36: */ 37: char regloc[] = { 38: R0, R1, R2, R3, R4, R5, R6, R7, RPS 39: }; 40: 41: /* 42: * Called from mch.s when a processor trap occurs. 43: * The arguments are the words saved on the system stack 44: * by the hardware and software during the trap processing. 45: * Their order is dictated by the hardware and the details 46: * of C's calling sequence. They are peculiar in that 47: * this call is not 'by value' and changed user registers 48: * get copied back on return. 49: * Dev is the kind of trap that occurred. 50: */ 51: /*ARGSUSED*/ 52: trap(dev, sp, r1, ov, nps, r0, pc, ps) 53: dev_t dev; 54: caddr_t sp, pc; 55: int r1, ov, nps, r0, ps; 56: { 57: extern int _ovno; 58: static int once_thru = 0; 59: register int i; 60: register struct proc *p; 61: time_t syst; 62: mapinfo kernelmap; 63: 64: #ifdef UCB_METER 65: cnt.v_trap++; 66: #endif 67: /* 68: * In order to stop the system from destroying 69: * kernel data space any further, allow only one 70: * fatal trap. After once_thru is set, any 71: * futher traps will be handled by looping in place. 72: */ 73: if (once_thru) { 74: (void) _splhigh(); 75: for(;;); 76: } 77: 78: if (USERMODE(ps)) 79: dev |= USER; 80: else 81: #ifdef INET 82: if (SUPVMODE(ps)) 83: dev |= SUPV; 84: else 85: #endif 86: savemap(kernelmap); /* guarantee normal kernel mapping */ 87: syst = u.u_ru.ru_stime; 88: p = u.u_procp; 89: u.u_fpsaved = 0; 90: u.u_ar0 = &r0; 91: switch(minor(dev)) { 92: 93: /* 94: * Trap not expected. Usually a kernel mode bus error. The numbers 95: * printed are used to find the hardware PS/PC as follows. (all 96: * numbers in octal 18 bits) 97: * address_of_saved_ps = 98: * (ka6*0100) + aps - 0140000; 99: * address_of_saved_pc = 100: * address_of_saved_ps - 2; 101: */ 102: default: 103: once_thru = 1; 104: #ifdef DIAGNOSTIC 105: /* 106: * Clear hasmap if we attempt to sync the fs. 107: * Else it might fail if we faulted with a mapped 108: * buffer. 109: */ 110: savhasmap = hasmap; 111: hasmap = 0; 112: #endif 113: i = splhigh(); 114: printf("ka6 %o aps %o\npc %o ps %o\nov %d\n", *ka6, &ps, 115: pc, ps, ov); 116: if ((cputype == 70) || (cputype == 44)) 117: printf("cpuerr %o\n", *CPUERR); 118: printf("trap type %o\n", dev); 119: splx(i); 120: panic("trap"); 121: /*NOTREACHED*/ 122: 123: case T_BUSFLT + USER: 124: i = SIGBUS; 125: break; 126: 127: case T_INSTRAP + USER: 128: #if defined(FPSIM) || defined(GENERIC) 129: /* 130: * If no floating point hardware is present, see if the 131: * offending instruction was a floating point instruction ... 132: */ 133: if (fpp == 0) { 134: i = fptrap(); 135: #ifdef UCB_METER 136: if (i != SIGILL) { 137: cnt.v_fpsim++; 138: } 139: #endif 140: if (i == 0) 141: goto out; 142: if (i == SIGTRAP) 143: ps &= ~PSL_T; 144: u.u_code = u.u_fperr.f_fec; 145: break; 146: } 147: #endif 148: /* 149: * If illegal instructions are not being caught and the 150: * offending instruction is a SETD, the trap is ignored. 151: * This is because C produces a SETD at the beginning of 152: * every program which will trap on CPUs without an FP-11. 153: */ 154: #define SETD 0170011 /* SETD instruction */ 155: if(fuiword((caddr_t)(pc-2)) == SETD && u.u_signal[SIGILL] == 0) 156: goto out; 157: i = SIGILL; 158: u.u_code = ILL_RESAD_FAULT; /* it's simplest to lie */ 159: break; 160: 161: case T_BPTTRAP + USER: 162: i = SIGTRAP; 163: ps &= ~PSL_T; 164: break; 165: 166: case T_IOTTRAP + USER: 167: i = SIGIOT; 168: break; 169: 170: case T_EMTTRAP + USER: 171: i = SIGEMT; 172: break; 173: 174: /* 175: * Since the floating exception is an imprecise trap, a user 176: * generated trap may actually come from kernel mode. In this 177: * case, a signal is sent to the current process to be picked 178: * up later. 179: */ 180: #ifdef INET 181: case T_ARITHTRAP+SUPV: 182: #endif 183: case T_ARITHTRAP: 184: case T_ARITHTRAP + USER: 185: i = SIGFPE; 186: stst(&u.u_fperr); /* save error code and address */ 187: u.u_code = u.u_fperr.f_fec; 188: break; 189: 190: /* 191: * If the user SP is below the stack segment, grow the stack 192: * automatically. This relies on the ability of the hardware 193: * to restart a half executed instruction. On the 11/40 this 194: * is not the case and the routine backup/mch.s may fail. 195: * The classic example is on the instruction 196: * cmp -(sp),-(sp) 197: * 198: * The KDJ-11 (11/53,73,83,84,93,94) handles the trap when doing 199: * a double word store differently than the other pdp-11s. When 200: * doing: 201: * setl 202: * movfi fr0,-(sp) 203: * and the stack segment becomes invalid part way thru then the 204: * trap is generated (as expected) BUT 'sp' IS NOT LEFT DECREMENTED! 205: * The 'grow' routine sees that SP is still within the (valid) stack 206: * segment and does not extend the stack, resulting in a 'segmentation 207: * violation' rather than a successfull floating to long store. 208: * The "fix" is to pretend that SP is 4 bytes lower than it really 209: * is (for KDJ-11 systems only) when calling 'grow'. 210: */ 211: case T_SEGFLT + USER: 212: { 213: caddr_t osp; 214: 215: osp = sp; 216: if (kdj11) 217: osp -= 4; 218: if (backup(u.u_ar0) == 0) 219: if (!(u.u_sigstk.ss_flags & SA_ONSTACK) && 220: grow((u_int)osp)) 221: goto out; 222: i = SIGSEGV; 223: break; 224: } 225: 226: /* 227: * The code here is a half-hearted attempt to do something with 228: * all of the PDP11 parity registers. In fact, there is little 229: * that can be done. 230: */ 231: case T_PARITYFLT: 232: case T_PARITYFLT + USER: 233: #ifdef INET 234: case T_PARITYFLT + SUPV: 235: #endif 236: printf("parity\n"); 237: if ((cputype == 70) || (cputype == 44)) { 238: for(i = 0; i < 4; i++) 239: printf("%o ", MEMERRLO[i]); 240: printf("\n"); 241: MEMERRLO[2] = MEMERRLO[2]; 242: if (dev & USER) { 243: i = SIGBUS; 244: break; 245: } 246: } 247: panic("parity"); 248: /*NOTREACHED*/ 249: 250: /* 251: * Allow process switch 252: */ 253: case T_SWITCHTRAP + USER: 254: goto out; 255: #ifdef INET 256: case T_BUSFLT+SUPV: 257: case T_INSTRAP+SUPV: 258: case T_BPTTRAP+SUPV: 259: case T_IOTTRAP+SUPV: 260: case T_EMTTRAP+SUPV: 261: case T_PIRQ+SUPV: 262: case T_SEGFLT+SUPV: 263: case T_SYSCALL+SUPV: 264: case T_SWITCHTRAP+SUPV: 265: case T_ZEROTRAP+SUPV: 266: case T_RANDOMTRAP+SUPV: 267: i = splhigh(); 268: if (!netoff) { 269: netoff = 1; 270: savestate(); 271: } 272: printf("Unexpected net trap (%o)\n", dev-SUPV); 273: printf("ka6 %o aps %o\n", *ka6, &ps); 274: printf("pc %o ps %o\n", pc, ps); 275: splx(i); 276: panic("net crashed"); 277: /*NOTREACHED*/ 278: #endif 279: 280: /* 281: * Whenever possible, locations 0-2 specify this style trap, since 282: * DEC hardware often generates spurious traps through location 0. 283: * This is a symptom of hardware problems and may represent a real 284: * interrupt that got sent to the wrong place. Watch out for hangs 285: * on disk completion if this message appears. Uninitialized 286: * interrupt vectors may be set to trap here also. 287: */ 288: case T_ZEROTRAP: 289: case T_ZEROTRAP + USER: 290: printf("Trap to 0: "); 291: /*FALL THROUGH*/ 292: case T_RANDOMTRAP: /* generated by autoconfig */ 293: case T_RANDOMTRAP + USER: 294: printf("Random intr ignored\n"); 295: if (!(dev & USER)) 296: restormap(kernelmap); 297: return; 298: } 299: psignal(p, i); 300: out: 301: while (i = CURSIG(p)) 302: postsig(i); 303: curpri = setpri(p); 304: if (runrun) { 305: setrq(u.u_procp); 306: u.u_ru.ru_nivcsw++; 307: swtch(); 308: } 309: if (u.u_prof.pr_scale) 310: addupc(pc, &u.u_prof, (int) (u.u_ru.ru_stime - syst)); 311: if (u.u_fpsaved) 312: restfp(&u.u_fps); 313: } 314: 315: /* 316: * Called from mch.s when a system call occurs. dev, ov and nps are 317: * unused, but are necessitated by the values of the R[0-7] ... constants 318: * in sys/reg.h (which, in turn, are defined by trap's stack frame). 319: */ 320: /*ARGSUSED*/ 321: syscall(dev, sp, r1, ov, nps, r0, pc, ps) 322: dev_t dev; 323: caddr_t sp, pc; 324: int r1, ov, nps, r0, ps; 325: { 326: extern int nsysent; 327: register int code; 328: register struct sysent *callp; 329: time_t syst; 330: register caddr_t opc; /* original pc for restarting syscalls */ 331: int i; 332: 333: #ifdef UCB_METER 334: cnt.v_syscall++; 335: #endif 336: 337: syst = u.u_ru.ru_stime; 338: u.u_fpsaved = 0; 339: u.u_ar0 = &r0; 340: u.u_error = 0; 341: opc = pc - 2; /* opc now points at syscall */ 342: code = fuiword((caddr_t)opc) & 0377; /* bottom 8 bits are index */ 343: if (code >= nsysent) 344: callp = &sysent[0]; /* indir (illegal) */ 345: else 346: callp = &sysent[code]; 347: if (callp->sy_narg) 348: copyin(sp+2, (caddr_t)u.u_arg, callp->sy_narg*NBPW); 349: u.u_r.r_val1 = 0; 350: u.u_r.r_val2 = r1; 351: if (setjmp(&u.u_qsave) == 0) 352: { 353: (*callp->sy_call)(); 354: #ifdef DIAGNOSTIC 355: if (hasmap) 356: panic("hasmap"); 357: #endif 358: } 359: switch (u.u_error) 360: { 361: case 0: 362: ps &= ~PSL_C; 363: r0 = u.u_r.r_val1; 364: r1 = u.u_r.r_val2; 365: break; 366: case ERESTART: 367: pc = opc; 368: break; 369: case EJUSTRETURN: 370: break; 371: default: 372: ps |= PSL_C; 373: r0 = u.u_error; 374: break; 375: } 376: while (i = CURSIG(u.u_procp)) 377: postsig(i); 378: curpri = setpri(u.u_procp); 379: if (runrun) { 380: setrq(u.u_procp); 381: u.u_ru.ru_nivcsw++; 382: swtch(); 383: } 384: if (u.u_prof.pr_scale) 385: addupc(pc, &u.u_prof, (int)(u.u_ru.ru_stime - syst)); 386: if (u.u_fpsaved) 387: restfp(&u.u_fps); 388: } 389: 390: /* 391: * nonexistent system call-- signal process (may want to handle it) 392: * flag error if process won't see signal immediately 393: * Q: should we do that all the time ?? 394: */ 395: nosys() 396: { 397: if (u.u_signal[SIGSYS] == SIG_IGN || u.u_signal[SIGSYS] == SIG_HOLD) 398: u.u_error = EINVAL; 399: psignal(u.u_procp, SIGSYS); 400: }