home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / unixen.tar / unixen / PDP-11 / Bug_Fixes / V7_on11-34 / trap.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-02-27  |  7.4 KB  |  363 lines

  1. /*
  2.  *    @(#)trap.c    1.6    (Chemeng) 11/7/83
  3.  */
  4. #include <sys/param.h>
  5. #include <sys/systm.h>
  6. #include <sys/dir.h>
  7. #include <sys/user.h>
  8. #include <sys/proc.h>
  9. #include <sys/reg.h>
  10. #include <sys/seg.h>
  11. #include <sys/sysinfo.h>
  12. #ifdef    SHARE
  13. #include <sys/lnode.h>
  14. #include <sys/share.h>
  15. #endif    SHARE
  16.  
  17. #define EBIT    1        /* user error bit in PS: C-bit */
  18. #define SETD    0170011     /* SETD instruction */
  19. #define SYS    0104400     /* sys (trap) instruction */
  20. #define USER    020        /* user-mode flag added to dev */
  21. #define MEMORY    ((physadr)0177740) /* 11/70 "memory" subsystem */
  22. #ifdef    PDP11_60
  23. #define CPU_ERR ((int *)0177766) /* 11/60 cpu error register */
  24. #endif
  25.  
  26.  
  27. int    callshare;        /* Set when time to reschedule */
  28.  
  29. /*
  30.  * Offsets of the user's registers relative to
  31.  * the saved r0. See reg.h
  32.  */
  33. char    regloc[9] =
  34. {
  35.     R0, R1, R2, R3, R4, R5, R6, R7, RPS
  36. };
  37.  
  38. /*
  39.  * In case of segmentation violations SP is stored
  40.  * in backsp to allow modification by the instruction
  41.  * backup routine.
  42.  */
  43. int    backsp;
  44.  
  45. /*
  46.  * Called from l40.s or l45.s when a processor trap occurs.
  47.  * The arguments are the words saved on the system stack
  48.  * by the hardware and software during the trap processing.
  49.  * Their order is dictated by the hardware and the details
  50.  * of C's calling sequence. They are peculiar in that
  51.  * this call is not 'by value' and changed user registers
  52.  * get copied back on return.
  53.  * dev is the kind of trap that occurred.
  54.  */
  55. trap(dev, sp, r1, nps, r0, pc, ps)
  56. int *pc;
  57. dev_t dev;
  58. {
  59.     register i;
  60.     register union {
  61.         int *ip;
  62.         struct proc *pp;
  63.     } a;
  64.     register struct sysent *callp;
  65.     int (*fetch)();
  66.     time_t syst;
  67.     extern char *panicstr;
  68.  
  69.     syst = u.u_stime;
  70. #if    FPU
  71.     u.u_fpsaved = 0;
  72. #endif
  73.     if ((ps&UMODE) == UMODE)
  74.         dev |= USER;
  75.     u.u_ar0 = &r0;
  76.     switch(minor(dev)) {
  77.  
  78.     /*
  79.      * Trap not expected.
  80.      * Usually a kernel mode bus error.
  81.      * The numbers printed are used to
  82.      * find the hardware PS/PC as follows.
  83.      * (all numbers in octal 18 bits)
  84.      *    address_of_saved_ps =
  85.      *        (ka6*0100) + aps - 0140000;
  86.      *    address_of_saved_pc =
  87.      *        address_of_saved_ps - 2;
  88.      *
  89.      *    Trap 0:
  90.      *        Illegal instruction
  91.      *        Bus Error
  92.      *        Stack Limit
  93.      *        Illegal Internal Address
  94.      *        Microbreak (!?)
  95.      */
  96. #ifdef    PDP11_60
  97.     case 0:
  98.         panicstr = (char *)1;
  99.         printf("cer %o\n", *CPU_ERR);
  100.         goto panic_trap;
  101. #endif
  102.  
  103.     default:
  104.         panicstr = (char *)1;
  105.     panic_trap:
  106.         printf("ka6 = %o\n", ka6->r[0]);
  107. #if    BIG_UNIX
  108.         printf("ka5 = %o\n", *((int *)ka6 - 1) );
  109. #endif
  110.         printf("aps = %o\n", &ps);
  111.         printf("pc = %o ps = %o\n", pc, ps);
  112.         printf("trap type %o\n", dev);
  113.         panic("trap");
  114.  
  115.     case 0+USER: /* bus error */
  116.         i = SIGBUS;
  117.         break;
  118.  
  119.     /*
  120.      * If illegal instructions are not
  121.      * being caught and the offending instruction
  122.      * is a SETD, the trap is ignored.
  123.      * This is because C produces a SETD at
  124.      * the beginning of every program which
  125.      * will trap on CPUs without 11/45 FPU.
  126.      */
  127.     case 1+USER: /* illegal instruction */
  128.         if(fuiword((caddr_t)(pc-1)) == SETD && u.u_signal[SIGINS] == 0)
  129.             goto out;
  130.         i = SIGINS;
  131.         break;
  132.  
  133.     case 2+USER: /* bpt or trace */
  134.         i = SIGTRC;
  135.         ps &= ~TBIT;
  136.         break;
  137.  
  138.     case 3+USER: /* iot */
  139.         i = SIGIOT;
  140.         break;
  141.  
  142. #ifdef    PDP11_60
  143.     case 4:     /* power fail */
  144.     case 4+USER:
  145.         panicstr = (char *)1;
  146.         printf("power fail\n");
  147.         goto panic_trap;
  148. #endif
  149.  
  150.     case 5+USER: /* emt */
  151. #if OVERLAY
  152.         if(u.u_ovdata.uo_ovbase != 0 && r0 <= 7 && r0 > 0)
  153.         {
  154.             ps &= ~EBIT;
  155.             save(u.u_qsav);
  156.             u.u_ovdata.uo_curov = r0;
  157.             estabur(u.u_tsize,u.u_dsize,u.u_ssize,u.u_sep,RO);
  158.             goto out;
  159.         }
  160.         else
  161.             i = SIGEMT;
  162. #else
  163.         i = SIGEMT;
  164. #endif OVERLAY
  165.         break;
  166.  
  167.     case 6+USER: /* sys call */
  168.         sysinfo.syscall++;
  169. #ifdef    SHARE
  170.         u.u_procp->p_lnode->l_cost += shprm.sh_syscall;
  171. #ifdef    SHDEBUG
  172.         shcnt.sc_syscall++;
  173. #endif    SHDEBUG
  174. #endif    SHARE
  175.         u.u_error = 0;
  176.         ps &= ~EBIT;
  177.         a.ip = pc;
  178.         callp = &sysent[fuiword((caddr_t)(a.ip-1))&077];
  179.         if (callp == sysent) { /* indirect */
  180.             a.ip = (int *)fuiword((caddr_t)(a.ip));
  181.             pc++;
  182.             i = fuword((caddr_t)a.ip);
  183.             a.ip++;
  184.             if ((i & ~077) != SYS)
  185.                 i = 0;        /* illegal */
  186.             callp = &sysent[i&077];
  187.             fetch = fuword;
  188.         } else {
  189.             pc += callp->sy_narg - callp->sy_nrarg;
  190.             fetch = fuiword;
  191.         }
  192.         for (i=0; i<callp->sy_nrarg; i++)
  193.             u.u_arg[i] = u.u_ar0[regloc[i]];
  194.         for(; i<callp->sy_narg; i++)
  195.             u.u_arg[i] = (*fetch)((caddr_t)a.ip++);
  196.         u.u_dirp = (caddr_t)u.u_arg[0];
  197.         u.u_r.r_val1 = u.u_ar0[R0];
  198.         u.u_r.r_val2 = u.u_ar0[R1];
  199.         u.u_ap = u.u_arg;
  200.         if (save(u.u_qsav)) {
  201.             if (u.u_error==0)
  202.                 u.u_error = EINTR;
  203.         } else {
  204.             (*callp->sy_call)();
  205.         }
  206.         if(u.u_error) {
  207.             ps |= EBIT;
  208.             u.u_ar0[R0] = u.u_error;
  209.         } else {
  210.             u.u_ar0[R0] = u.u_r.r_val1;
  211.             u.u_ar0[R1] = u.u_r.r_val2;
  212.         }
  213.         goto out;
  214.  
  215. #if    FPU | PDP11_40
  216.     /*
  217.      * Since the floating exception is an
  218.      * imprecise trap, a user generated
  219.      * trap may actually come from kernel
  220.      * mode. In this case, a signal is sent
  221.      * to the current process to be picked
  222.      * up later.
  223.      */
  224.     case 8: /* floating exception */
  225. #if    ! PDP11_40
  226.         stst(&u.u_fper);    /* save error code */
  227. #endif    ! PDP11_40
  228.         psignal(u.u_procp, SIGFPT);
  229.         return;
  230.  
  231.     case 8+USER:
  232.         i = SIGFPT;
  233. #if    ! PDP11_40
  234.         stst(&u.u_fper);
  235. #endif    ! PDP11_40
  236.         break;
  237. #endif    FPU | PDP11_40
  238.  
  239.     /*
  240.      * If the user SP is below the stack segment,
  241.      * grow the stack automatically.
  242.      * This relies on the ability of the hardware
  243.      * to restart a half executed instruction.
  244.      * On the 11/40 this is not the case and
  245.      * the routine backup/l40.s may fail.
  246.      * The classic example is on the instruction
  247.      *    cmp    -(sp),-(sp)
  248.      */
  249.     case 9+USER: /* segmentation exception */
  250.     {
  251.         backsp = sp;
  252.         if(backup(u.u_ar0) == 0)
  253.             if(grow((unsigned)backsp))
  254.                 goto out;
  255.         i = SIGSEG;
  256.         break;
  257.     }
  258.  
  259.     /*
  260.      * The code here is a half-hearted
  261.      * attempt to do something with all
  262.      * of the 11/70 parity registers.
  263.      * In fact, there is little that
  264.      * can be done.
  265.      */
  266.     case 10:
  267.     case 10+USER:
  268.         if ((dev & USER) == 0)
  269.             panicstr = (char *)1;
  270.         printf("\nmemory parity\n");
  271. #if    PDP11_23 | PDP11_34 | PDP11_40
  272.         a.ip = MEMPARCSR;
  273.         while ( (i = *a.ip++) >= 0 ) ;
  274.         /* We may get a bus error if we run out of regs */
  275.         printf("address = %o000\n", (i>>3)&0774 );
  276. #endif    PDP11_23 | PDP11_34 | PDP11_40
  277. #if    PDP11_70
  278.         for(i=0; i<4; i++)
  279.             printf("%o ", MEMORY->r[i]);
  280.         printf("\n");
  281.         MEMORY->r[2] = -1;
  282. #endif    PDP11_70
  283.         if (dev & USER) {
  284.             i = SIGKIL;
  285.             uprints("\nMemory parity\n");
  286.             break;
  287.         }
  288.         panic("parity");
  289.  
  290.     /*
  291.      * Allow process switch
  292.      */
  293.     case USER+12:
  294. #ifdef    SHARE
  295.         if (callshare) {
  296.             callshare = 0;
  297.             share();
  298.         }
  299. #endif    SHARE
  300.         goto out;
  301.  
  302.     /*
  303.      * Locations 0-2 specify this style trap, since
  304.      * DEC hardware often generates spurious
  305.      * traps through location 0.  This is a
  306.      * symptom of hardware problems and may
  307.      * represent a real interrupt that got
  308.      * sent to the wrong place.  Watch out
  309.      * for hangs on disk completion if this message appears.
  310.      */
  311.     case 15:
  312.     case 15+USER:
  313.         printf("Interrupt at 0 ignored\n");
  314.         return;
  315.     }
  316.     psignal(u.u_procp, i);
  317.  
  318. out:
  319.     a.pp = u.u_procp;
  320.     if (a.pp->p_sig && issig()) {
  321.         psig();
  322.     }
  323. #ifndef SHARE
  324.     curpri = setpri(a.pp);
  325. #else
  326.     curpri = a.pp->p_pri = (a.pp->p_cpu >> 1) + PUSER +
  327.                 a.pp->p_nice - NZERO
  328. #ifndef SHDEBUG
  329.                 + a.pp->p_lnode->l_nice;
  330. #else
  331.                 ;
  332. #endif
  333. #endif    SHARE
  334.     while (a.pp->p_flag & SHALT)
  335.         sleep((caddr_t)a.pp, PSLEP);
  336.     if (runrun)
  337.     {
  338.         sysinfo.preempt++;
  339.         qswtch();
  340.     }
  341.     if(u.u_prof.pr_scale)
  342.         addupc((caddr_t)pc, &u.u_prof, (int)(u.u_stime-syst));
  343. #if    FPU
  344.     if (u.u_fpsaved)
  345.         restfp(&u.u_fps);
  346. #endif    FPU
  347. }
  348.  
  349. /*
  350.  * nonexistent system call-- set fatal error code.
  351.  */
  352. nosys()
  353. {
  354.     u.u_error = EINVAL;
  355. }
  356.  
  357. /*
  358.  * Ignored system call
  359.  */
  360. nullsys()
  361. {
  362. }
  363.