Research V7 development
authorKen Thompson <ken@research.uucp>
Fri, 8 Jun 1979 20:44:40 +0000 (15:44 -0500)
committerKen Thompson <ken@research.uucp>
Fri, 8 Jun 1979 20:44:40 +0000 (15:44 -0500)
Work on file usr/sys/sys/trap.c

Synthesized-from: v7

usr/sys/sys/trap.c [new file with mode: 0644]

diff --git a/usr/sys/sys/trap.c b/usr/sys/sys/trap.c
new file mode 100644 (file)
index 0000000..b29229d
--- /dev/null
@@ -0,0 +1,251 @@
+#include "../h/param.h"
+#include "../h/systm.h"
+#include "../h/dir.h"
+#include "../h/user.h"
+#include "../h/proc.h"
+#include "../h/reg.h"
+#include "../h/seg.h"
+
+#define        EBIT    1               /* user error bit in PS: C-bit */
+#define        SETD    0170011         /* SETD instruction */
+#define        SYS     0104400         /* sys (trap) instruction */
+#define        USER    020             /* user-mode flag added to dev */
+#define        MEMORY  ((physadr)0177740) /* 11/70 "memory" subsystem */
+
+/*
+ * Offsets of the user's registers relative to
+ * the saved r0. See reg.h
+ */
+char   regloc[9] =
+{
+       R0, R1, R2, R3, R4, R5, R6, R7, RPS
+};
+
+/*
+ * Called from l40.s or l45.s when a processor trap occurs.
+ * The arguments are the words saved on the system stack
+ * by the hardware and software during the trap processing.
+ * Their order is dictated by the hardware and the details
+ * of C's calling sequence. They are peculiar in that
+ * this call is not 'by value' and changed user registers
+ * get copied back on return.
+ * dev is the kind of trap that occurred.
+ */
+trap(dev, sp, r1, nps, r0, pc, ps)
+int *pc;
+dev_t dev;
+{
+       register i;
+       register *a;
+       register struct sysent *callp;
+       int (*fetch)();
+       time_t syst;
+
+       syst = u.u_stime;
+       u.u_fpsaved = 0;
+       if ((ps&UMODE) == UMODE)
+               dev |= USER;
+       u.u_ar0 = &r0;
+       switch(minor(dev)) {
+
+       /*
+        * Trap not expected.
+        * Usually a kernel mode bus error.
+        * The numbers printed are used to
+        * find the hardware PS/PC as follows.
+        * (all numbers in octal 18 bits)
+        *      address_of_saved_ps =
+        *              (ka6*0100) + aps - 0140000;
+        *      address_of_saved_pc =
+        *              address_of_saved_ps - 2;
+        */
+       default:
+               printf("ka6 = %o\n", ka6->r[0]);
+               printf("aps = %o\n", &ps);
+               printf("pc = %o ps = %o\n", pc, ps);
+               printf("trap type %o\n", dev);
+               panic("trap");
+
+       case 0+USER: /* bus error */
+               i = SIGBUS;
+               break;
+
+       /*
+        * If illegal instructions are not
+        * being caught and the offending instruction
+        * is a SETD, the trap is ignored.
+        * This is because C produces a SETD at
+        * the beginning of every program which
+        * will trap on CPUs without 11/45 FPU.
+        */
+       case 1+USER: /* illegal instruction */
+               if(fuiword((caddr_t)(pc-1)) == SETD && u.u_signal[SIGINS] == 0)
+                       goto out;
+               i = SIGINS;
+               break;
+
+       case 2+USER: /* bpt or trace */
+               i = SIGTRC;
+               ps &= ~TBIT;
+               break;
+
+       case 3+USER: /* iot */
+               i = SIGIOT;
+               break;
+
+       case 5+USER: /* emt */
+               i = SIGEMT;
+               break;
+
+       case 6+USER: /* sys call */
+               u.u_error = 0;
+               ps &= ~EBIT;
+               a = pc;
+               callp = &sysent[fuiword((caddr_t)(a-1))&077];
+               if (callp == sysent) { /* indirect */
+                       a = (int *)fuiword((caddr_t)(a));
+                       pc++;
+                       i = fuword((caddr_t)a);
+                       a++;
+                       if ((i & ~077) != SYS)
+                               i = 077;        /* illegal */
+                       callp = &sysent[i&077];
+                       fetch = fuword;
+               } else {
+                       pc += callp->sy_narg - callp->sy_nrarg;
+                       fetch = fuiword;
+               }
+               for (i=0; i<callp->sy_nrarg; i++)
+                       u.u_arg[i] = u.u_ar0[regloc[i]];
+               for(; i<callp->sy_narg; i++)
+                       u.u_arg[i] = (*fetch)((caddr_t)a++);
+               u.u_dirp = (caddr_t)u.u_arg[0];
+               u.u_r.r_val1 = u.u_ar0[R0];
+               u.u_r.r_val2 = u.u_ar0[R1];
+               u.u_ap = u.u_arg;
+               if (save(u.u_qsav)) {
+                       if (u.u_error==0)
+                               u.u_error = EINTR;
+               } else {
+                       (*callp->sy_call)();
+               }
+               if(u.u_error) {
+                       ps |= EBIT;
+                       u.u_ar0[R0] = u.u_error;
+               } else {
+                       u.u_ar0[R0] = u.u_r.r_val1;
+                       u.u_ar0[R1] = u.u_r.r_val2;
+               }
+               goto out;
+
+       /*
+        * Since the floating exception is an
+        * imprecise trap, a user generated
+        * trap may actually come from kernel
+        * mode. In this case, a signal is sent
+        * to the current process to be picked
+        * up later.
+        */
+       case 8: /* floating exception */
+               stst(&u.u_fper);        /* save error code */
+               psignal(u.u_procp, SIGFPT);
+               return;
+
+       case 8+USER:
+               i = SIGFPT;
+               stst(&u.u_fper);
+               break;
+
+       /*
+        * 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 11/40 this is not the case and
+        * the routine backup/l40.s may fail.
+        * The classic example is on the instruction
+        *      cmp     -(sp),-(sp)
+        */
+       case 9+USER: /* segmentation exception */
+       {
+       int     osp;
+
+               osp = sp;
+               if(backup(u.u_ar0) == 0)
+                       if(grow((unsigned)osp))
+                               goto out;
+               i = SIGSEG;
+               break;
+       }
+
+       /*
+        * The code here is a half-hearted
+        * attempt to do something with all
+        * of the 11/70 parity registers.
+        * In fact, there is little that
+        * can be done.
+        */
+       case 10:
+       case 10+USER:
+               printf("parity\n");
+               if(cputype == 70) {
+                       for(i=0; i<4; i++)
+                               printf("%o ", MEMORY->r[i]);
+                       printf("\n");
+                       MEMORY->r[2] = -1;
+                       if(dev & USER) {
+                               i = SIGBUS;
+                               break;
+                       }
+               }
+               panic("parity");
+
+       /*
+        * Allow process switch
+        */
+       case USER+12:
+               goto out;
+
+       /*
+        * Locations 0-2 specify this style trap, since
+        * DEC hardware often generates spurious
+        * traps through location 0.  This 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 15:
+       case 15+USER:
+               printf("Random interrupt ignored\n");
+               return;
+       }
+       psignal(u.u_procp, i);
+
+out:
+       if(issig()) {
+               psig();
+       }
+       curpri = setpri(u.u_procp);
+       if (runrun)
+               qswtch();
+       if(u.u_prof.pr_scale)
+               addupc((caddr_t)pc, &u.u_prof, (int)(u.u_stime-syst));
+       if (u.u_fpsaved)
+               restfp(&u.u_fps);
+}
+
+/*
+ * nonexistent system call-- set fatal error code.
+ */
+nosys()
+{
+       u.u_error = EINVAL;
+}
+
+/*
+ * Ignored system call
+ */
+nullsys()
+{
+}