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: /* --------------------------- */