02950 #include "../h/param.h" 02951 #include "../h/systm.h" 02952 #include "../h/dir.h" 02953 #include "../h/user.h" 02954 #include "../h/proc.h" 02955 #include "../h/reg.h" 02956 #include "../h/seg.h" 02957 02958 #define EBIT 1 /* user error bit in PS: C-bit */ 02959 #define SETD 0170011 /* SETD instruction */ 02960 #define SYS 0104400 /* sys (trap) instruction */ 02961 #define USER 020 /* user-mode flag added to dev */ 02962 #define MEMORY ((physadr)0177740) /* 11/70 "memory" subsystem */ 02963 02964 /* 02965 * Offsets of the user's registers relative to 02966 * the saved r0. See reg.h 02967 */ 02968 char regloc[9] = 02969 { 02970 R0, R1, R2, R3, R4, R5, R6, R7, RPS 02971 }; 02972 02973 /* 02974 * Called from l40.s or l45.s when a processor trap occurs. 02975 * The arguments are the words saved on the system stack 02976 * by the hardware and software during the trap processing. 02977 * Their order is dictated by the hardware and the details 02978 * of C's calling sequence. They are peculiar in that 02979 * this call is not 'by value' and changed user registers 02980 * get copied back on return. 02981 * dev is the kind of trap that occurred. 02982 */ 02983 trap(dev, sp, r1, nps, r0, pc, ps) 02984 int *pc; 02985 dev_t dev; 02986 { 02987 register i; 02988 register *a; 02989 register struct sysent *callp; 02990 int (*fetch)(); 02991 time_t syst; 02992 02993 syst = u.u_stime; 02994 u.u_fpsaved = 0; 02995 if ((ps&UMODE) == UMODE) 02996 dev |= USER; 02997 u.u_ar0 = &r0; 02998 switch(minor(dev)) { 02999 03000 /* 03001 * Trap not expected. 03002 * Usually a kernel mode bus error. 03003 * The numbers printed are used to 03004 * find the hardware PS/PC as follows. 03005 * (all numbers in octal 18 bits) 03006 * address_of_saved_ps = 03007 * (ka6*0100) + aps - 0140000; 03008 * address_of_saved_pc = 03009 * address_of_saved_ps - 2; 03010 */ 03011 default: 03012 printf("ka6 = %o\n", ka6->r[0]); 03013 printf("aps = %o\n", &ps); 03014 printf("pc = %o ps = %o\n", pc, ps); 03015 printf("trap type %o\n", dev); 03016 panic("trap"); 03017 03018 case 0+USER: /* bus error */ 03019 i = SIGBUS; 03020 break; 03021 03022 /* 03023 * If illegal instructions are not 03024 * being caught and the offending instruction 03025 * is a SETD, the trap is ignored. 03026 * This is because C produces a SETD at 03027 * the beginning of every program which 03028 * will trap on CPUs without 11/45 FPU. 03029 */ 03030 case 1+USER: /* illegal instruction */ 03031 if(fuiword((caddr_t)(pc-1)) == SETD && u.u_signal[SIGINS] == 0) 03032 goto out; 03033 i = SIGINS; 03034 break; 03035 03036 case 2+USER: /* bpt or trace */ 03037 i = SIGTRC; 03038 ps &= ~TBIT; 03039 break; 03040 03041 case 3+USER: /* iot */ 03042 i = SIGIOT; 03043 break; 03044 03045 case 5+USER: /* emt */ 03046 i = SIGEMT; 03047 break; 03048 03049 case 6+USER: /* sys call */ 03050 u.u_error = 0; 03051 ps &= ~EBIT; 03052 a = pc; 03053 callp = &sysent[fuiword((caddr_t)(a-1))&077]; 03054 if (callp == sysent) { /* indirect */ 03055 a = (int *)fuiword((caddr_t)(a)); 03056 pc++; 03057 i = fuword((caddr_t)a); 03058 a++; 03059 if ((i & ~077) != SYS) 03060 i = 077; /* illegal */ 03061 callp = &sysent[i&077]; 03062 fetch = fuword; 03063 } else { 03064 pc += callp->sy_narg - callp->sy_nrarg; 03065 fetch = fuiword; 03066 } 03067 for (i=0; isy_nrarg; i++) 03068 u.u_arg[i] = u.u_ar0[regloc[i]]; 03069 for(; isy_narg; i++) 03070 u.u_arg[i] = (*fetch)((caddr_t)a++); 03071 u.u_dirp = (caddr_t)u.u_arg[0]; 03072 u.u_r.r_val1 = u.u_ar0[R0]; 03073 u.u_r.r_val2 = u.u_ar0[R1]; 03074 u.u_ap = u.u_arg; 03075 if (save(u.u_qsav)) { 03076 if (u.u_error==0) 03077 u.u_error = EINTR; 03078 } else { 03079 (*callp->sy_call)(); 03080 } 03081 if(u.u_error) { 03082 ps |= EBIT; 03083 u.u_ar0[R0] = u.u_error; 03084 } else { 03085 u.u_ar0[R0] = u.u_r.r_val1; 03086 u.u_ar0[R1] = u.u_r.r_val2; 03087 } 03088 goto out; 03089 03090 /* 03091 * Since the floating exception is an 03092 * imprecise trap, a user generated 03093 * trap may actually come from kernel 03094 * mode. In this case, a signal is sent 03095 * to the current process to be picked 03096 * up later. 03097 */ 03098 case 8: /* floating exception */ 03099 stst(&u.u_fper); /* save error code */ 03100 psignal(u.u_procp, SIGFPT); 03101 return; 03102 03103 case 8+USER: 03104 i = SIGFPT; 03105 stst(&u.u_fper); 03106 break; 03107 03108 /* 03109 * If the user SP is below the stack segment, 03110 * grow the stack automatically. 03111 * This relies on the ability of the hardware 03112 * to restart a half executed instruction. 03113 * On the 11/40 this is not the case and 03114 * the routine backup/l40.s may fail. 03115 * The classic example is on the instruction 03116 * cmp -(sp),-(sp) 03117 */ 03118 case 9+USER: /* segmentation exception */ 03119 { 03120 int osp; 03121 03122 osp = sp; 03123 if(backup(u.u_ar0) == 0) 03124 if(grow((unsigned)osp)) 03125 goto out; 03126 i = SIGSEG; 03127 break; 03128 } 03129 03130 /* 03131 * The code here is a half-hearted 03132 * attempt to do something with all 03133 * of the 11/70 parity registers. 03134 * In fact, there is little that 03135 * can be done. 03136 */ 03137 case 10: 03138 case 10+USER: 03139 printf("parity\n"); 03140 if(cputype == 70) { 03141 for(i=0; i<4; i++) 03142 printf("%o ", MEMORY->r[i]); 03143 printf("\n"); 03144 MEMORY->r[2] = -1; 03145 if(dev & USER) { 03146 i = SIGBUS; 03147 break; 03148 } 03149 } 03150 panic("parity"); 03151 03152 /* 03153 * Allow process switch 03154 */ 03155 case USER+12: 03156 goto out; 03157 03158 /* 03159 * Locations 0-2 specify this style trap, since 03160 * DEC hardware often generates spurious 03161 * traps through location 0. This is a 03162 * symptom of hardware problems and may 03163 * represent a real interrupt that got 03164 * sent to the wrong place. Watch out 03165 * for hangs on disk completion if this message appears. 03166 */ 03167 case 15: 03168 case 15+USER: 03169 printf("Random interrupt ignored\n"); 03170 return; 03171 } 03172 psignal(u.u_procp, i); 03173 03174 out: 03175 if(issig()) { 03176 psig(); 03177 } 03178 curpri = setpri(u.u_procp); 03179 if (runrun) 03180 qswtch(); 03181 if(u.u_prof.pr_scale) 03182 addupc((caddr_t)pc, &u.u_prof, (int)(u.u_stime-syst)); 03183 if (u.u_fpsaved) 03184 restfp(&u.u_fps); 03185 } 03186 03187 /* 03188 * nonexistent system call-- set fatal error code. 03189 */ 03190 nosys() 03191 { 03192 u.u_error = EINVAL; 03193 } 03194 03195 /* 03196 * Ignored system call 03197 */ 03198 nullsys() 03199 { 03200 } 03201 03202 03203 03204 03205 03206 03207 03208 03209 03210 03211 03212 03213 03214 03215 03216 03217 03218 03219 03220 03221 03222 03223 03224 03225 03226 03227 03228 03229 03230 03231 03232 03233 03234 03235 03236 03237 03238 03239 03240 03241 03242 03243 03244 03245 03246 03247 03248 03249