trap.c

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; icount; i++) 2763 u.u_arg[i] = fuword(a =+ 2); 2764 } else { 2765 for(i=0; icount; 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 /* ------------------------ */ 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899