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