2650: #
2651: #include "../param.h"
2652: #include "../systm.h"
2653: #include "../user.h"
2654: #include "../proc.h"
2655: #include "../reg.h"
2656: #include "../seg.h"
2657: 
2658: #define EBIT    1               /* user error bit in PS: C-bit */
2659: #define UMODE   0170000         /* user-mode bits in PS word */
2660: #define SETD    0170011         /* SETD instruction */
2661: #define SYS     0104400         /* sys (trap) instruction */
2662: #define USER    020             /* user-mode flag added to dev */
2663: 
2664: /*
2665:  * structure of the system entry table (sysent.c)
2666:  */
2667: struct sysent   {
2668:         int     count;          /* argument count */
2669:         int     (*call)();      /* name of handler */
2670: } sysent[64];
2671: /* ---------------------------       */
2672: 
2673: /*
2674:  * Offsets of the user's registers relative to
2675:  * the saved r0. See reg.h
2676:  */
2677: char    regloc[9]
2678: {
2679:         R0, R1, R2, R3, R4, R5, R6, R7, RPS
2680: };
2681: /* ---------------------------       */
2682: 
2683: /*
2684:  * Called from l40.s or l45.s when a processor trap occurs.
2685:  * The arguments are the words saved on the system stack
2686:  * by the hardware and software during the trap processing.
2687:  * Their order is dictated by the hardware and the details
2688:  * of C's calling sequence. They are peculiar in that
2689:  * this call is not 'by value' and changed user registers
2690:  * get copied back on return.
2691:  * dev is the kind of trap that occurred.
2692:  */
2693: trap(dev, sp, r1, nps, r0, pc, ps)
2694: {
2695:         register i, a;
2696:         register struct sysent *callp;
2697: 
2698:         savfp();
2699:         if ((ps&UMODE) == UMODE)
2700:                 dev =| USER;
2701:         u.u_ar0 = &r0;
2702:         switch(dev) {
2703: 
2704:         /*
2705:          * Trap not expected.
2706:          * Usually a kernel mode bus error.
2707:          * The numbers printed are used to
2708:          * find the hardware PS/PC as follows.
2709:          * (all numbers in octal 18 bits)
2710:          *      address_of_saved_ps =
2711:          *              (ka6*0100) + aps - 0140000;
2712:          *      address_of_saved_pc =
2713:          *              address_of_saved_ps - 2;
2714:          */
2715:         default:
2716:                 printf("ka6 = %o\n", *ka6);
2717:                 printf("aps = %o\n", &ps);
2718:                 printf("trap type %o\n", dev);
2719:                 panic("trap");
2720: 
2721:         case 0+USER: /* bus error */
2722:                 i = SIGBUS;
2723:                 break;
2724: 
2725:         /*
2726:          * If illegal instructions are not
2727:          * being caught and the offending instruction
2728:          * is a SETD, the trap is ignored.
2729:          * This is because C produces a SETD at
2730:          * the beginning of every program which
2731:          * will trap on CPUs without 11/45 FPU.
2732:          */
2733:         case 1+USER: /* illegal instruction */
2734:                 if(fuiword(pc-2) == SETD && u.u_signal[SIGINS] == 0)
2735:                         goto out;
2736:                 i = SIGINS;
2737:                 break;
2738: 
2739:         case 2+USER: /* bpt or trace */
2740:                 i = SIGTRC;
2741:                 break;
2742: 
2743:         case 3+USER: /* iot */
2744:                 i = SIGIOT;
2745:                 break;
2746: 
2747:         case 5+USER: /* emt */
2748:                 i = SIGEMT;
2749:                 break;
2750: 
2751:         case 6+USER: /* sys call */
2752:                 u.u_error = 0;
2753:                 ps =& ~EBIT;
2754:                 callp = &sysent[fuiword(pc-2)&077];
2755:                 if (callp == sysent) { /* indirect */
2756:                         a = fuiword(pc);
2757:                         pc =+ 2;
2758:                         i = fuword(a);
2759:                         if ((i & ~077) != SYS)
2760:                                 i = 077;        /* illegal */
2761:                         callp = &sysent[i&077];
2762:                         for(i=0; i<callp->count; i++)
2763:                                 u.u_arg[i] = fuword(a =+ 2);
2764:                 } else {
2765:                         for(i=0; i<callp->count; i++) {
2766:                                 u.u_arg[i] = fuiword(pc);
2767:                                 pc =+ 2;
2768:                         }
2769:                 }
2770:                 u.u_dirp = u.u_arg[0];
2771:                 trap1(callp->call);
2772:                 if(u.u_intflg)
2773:                         u.u_error = EINTR;
2774:                 if(u.u_error < 100) {
2775:                         if(u.u_error) {
2776:                                 ps =| EBIT;
2777:                                 r0 = u.u_error;
2778:                         }
2779:                         goto out;
2780:                 }
2781:                 i = SIGSYS;
2782:                 break;
2783: 
2784:         /*
2785:          * Since the floating exception is an
2786:          * imprecise trap, a user generated
2787:          * trap may actually come from kernel
2788:          * mode. In this case, a signal is sent
2789:          * to the current process to be picked
2790:          * up later.
2791:          */
2792:         case 8: /* floating exception */
2793:                 psignal(u.u_procp, SIGFPT);
2794:                 return;
2795: 
2796:         case 8+USER:
2797:                 i = SIGFPT;
2798:                 break;
2799: 
2800:         /*
2801:          * If the user SP is below the stack segment,
2802:          * grow the stack automatically.
2803:          * This relies on the ability of the hardware
2804:          * to restart a half executed instruction.
2805:          * On the 11/40 this is not the case and
2806:          * the routine backup/l40.s may fail.
2807:          * The classic example is on the instruction
2808:          *      cmp     -(sp),-(sp)
2809:          */
2810:         case 9+USER: /* segmentation exception */
2811:                 a = sp;
2812:                 if(backup(u.u_ar0) == 0)
2813:                 if(grow(a))
2814:                         goto out;
2815:                 i = SIGSEG;
2816:                 break;
2817:         }
2818:         psignal(u.u_procp, i);
2819: 
2820: out:
2821:         if(issig())
2822:                 psig();
2823:         setpri(u.u_procp);
2824: }
2825: /* ---------------------------       */
2826: 
2827: /*
2828:  * Call the system-entry routine f (out of the
2829:  * sysent table). This is a subroutine for trap, and
2830:  * not in-line, because if a signal occurs
2831:  * during processing, an (abnormal) return is simulated from
2832:  * the last caller to savu(qsav); if this took place
2833:  * inside of trap, it wouldn't have a chance to clean up.
2834:  *
2835:  * If this occurs, the return takes place without
2836:  * clearing u_intflg; if it's still set, trap
2837:  * marks an error which means that a system
2838:  * call (like read on a typewriter) got interrupted
2839:  * by a signal.
2840:  */
2841: trap1(f)
2842: int (*f)();
2843: {
2844: 
2845:         u.u_intflg = 1;
2846:         savu(u.u_qsav);
2847:         (*f)();
2848:         u.u_intflg = 0;
2849: }
2850: 
2851: /* ---------------------------       */
2852: /*
2853:  * nonexistent system call-- set fatal error code.
2854:  */
2855: nosys()
2856: {
2857:         u.u_error = 100;
2858: }
2859: /* ---------------------------       */
2860: 
2861: /*
2862:  * Ignored system call
2863:  */
2864: nullsys()
2865: {
2866: }
2867: /* ---------------------------       */