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: }

Defined functions

nosys defined in line 395; used 37 times
syscall defined in line 321; used 1 times
trap defined in line 52; used 2 times

Defined variables

savhasmap defined in line 30; used 1 times

Defined macros

SETD defined in line 154; used 1 times
Last modified: 1999-09-14
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 4915
Valid CSS Valid XHTML 1.0 Strict