# 2.11BSD#431 - /usr/src/sys/pdp/trap.c

##### Functions

    nosys             X
    syscall           X
    trap              X

##### Variables

    regloc            X

##### Macros

    SETD              X

       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

- in /usr/src/sys/sys/init_sysent.c line 16, 83, 110, 118, 161, 173-188(12), 194-204(6), 218-229(6), 236-242(3), 249-257(4), 270

syscall defined in line 321; used 1 times

- in /usr/src/sys/pdp/mch_trap.s line 186

trap defined in line 52; used 2 times

- in /usr/src/sys/pdp/mch_trap.s line 110, 247

#### Defined variables

regloc defined in line 37; used 7 times

- in /usr/src/sys/pdp/mch_backup.s line 38, 65, 98, 208
- in /usr/src/sys/pdp/mch_fpsim.s line 78, 224
- in /usr/src/sys/sys/sys_process.c line 157

savhasmap defined in line 30; used 1 times

- in line 110

#### Defined macros

SETD defined in line 154; used 1 times

- in line 155

Last modified: 1999-09-14 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 1217 |