1 /* trap.c 4.12 82/03/31 */ 2 3 #include "../h/param.h" 4 #include "../h/systm.h" 5 #include "../h/dir.h" 6 #include "../h/user.h" 7 #include "assym.s" 8 #include "../h/proc.h" 9 #include "../h/reg.h" 10 #include "../h/seg.h" 11 #include "../h/trap.h" 12 #include "../h/psl.h" 13 #include "../h/pte.h" 14 #include "../h/inline.h" 15 #include "../h/mtpr.h" 16 17 #define USER 040 /* user-mode flag added to type */ 18 19 struct sysent sysent[128]; 20 21 /* 22 * Called from the trap handler when a processor trap occurs. 23 */ 24 /*ARGSUSED*/ 25 trap(sp, type, code, pc, psl) 26 unsigned code; 27 { 28 register int *locr0 = ((int *)&psl)-PS; 29 register int i; 30 register struct proc *p; 31 time_t syst; 32 33 syst = u.u_vm.vm_stime; 34 if (USERMODE(locr0[PS])) { 35 type |= USER; 36 u.u_ar0 = locr0; 37 } 38 switch (type) { 39 40 default: 41 printf("trap type %d, code = %x, pc = %x\n", type, code, pc); 42 panic("trap"); 43 44 case PROTFLT + USER: /* protection fault */ 45 i = SIGBUS; 46 break; 47 48 case PRIVINFLT + USER: /* privileged instruction fault */ 49 case RESADFLT + USER: /* reserved addressing fault */ 50 case RESOPFLT + USER: /* resereved operand fault */ 51 u.u_code = type &~ USER; 52 i = SIGILL; 53 break; 54 55 case ASTFLT + USER: /* Allow process switch */ 56 astoff(); 57 if ((u.u_procp->p_flag & SOWEUPC) && u.u_prof.pr_scale) { 58 addupc(pc, &u.u_prof, 1); 59 u.u_procp->p_flag &= ~SOWEUPC; 60 } 61 goto out; 62 63 case ARITHTRAP + USER: 64 u.u_code = code; 65 i = SIGFPE; 66 break; 67 68 /* 69 * If the user SP is above the stack segment, 70 * grow the stack automatically. 71 */ 72 case SEGFLT + USER: 73 if (grow((unsigned)locr0[SP]) || grow(code)) 74 goto out; 75 i = SIGSEGV; 76 break; 77 78 case TABLEFLT: /* allow page table faults in kernel mode */ 79 case TABLEFLT + USER: /* page table fault */ 80 panic("ptable fault"); 81 82 case PAGEFLT: /* allow page faults in kernel mode */ 83 case PAGEFLT + USER: /* page fault */ 84 i = u.u_error; 85 pagein(code); 86 u.u_error = i; 87 if (type == PAGEFLT) 88 return; 89 goto out; 90 91 case BPTFLT + USER: /* bpt instruction fault */ 92 case TRCTRAP + USER: /* trace trap */ 93 locr0[PS] &= ~PSL_T; 94 i = SIGTRAP; 95 break; 96 97 case XFCFLT + USER: /* xfc instruction fault */ 98 i = SIGEMT; 99 break; 100 101 case COMPATFLT + USER: /* compatibility mode fault */ 102 u.u_code = code; 103 i = SIGILL; 104 break; 105 } 106 psignal(u.u_procp, i); 107 out: 108 p = u.u_procp; 109 if (p->p_cursig || ISSIG(p)) 110 psig(); 111 p->p_pri = p->p_usrpri; 112 if (runrun) { 113 /* 114 * Since we are u.u_procp, clock will normally just change 115 * our priority without moving us from one queue to another 116 * (since the running process is not on a queue.) 117 * If that happened after we setrq ourselves but before we 118 * swtch()'ed, we might not be on the queue indicated by 119 * our priority. 120 */ 121 (void) spl6(); 122 setrq(p); 123 swtch(); 124 } 125 if (u.u_prof.pr_scale && (syst -= u.u_vm.vm_stime)) 126 addupc(locr0[PC], &u.u_prof, (int)-syst); 127 curpri = p->p_pri; 128 } 129 130 /* 131 * Called from the trap handler when a system call occurs 132 */ 133 /*ARGSUSED*/ 134 syscall(sp, type, code, pc, psl) 135 unsigned code; 136 { 137 register int *locr0 = ((int *)&psl)-PS; 138 register caddr_t params; /* known to be r10 below */ 139 register int i; /* known to be r9 below */ 140 register struct sysent *callp; 141 register struct proc *p; 142 time_t syst; 143 int opc; 144 145 syst = u.u_vm.vm_stime; 146 if (!USERMODE(locr0[PS])) 147 panic("syscall"); 148 u.u_ar0 = locr0; 149 params = (caddr_t)locr0[AP] + NBPW; 150 u.u_error = 0; 151 opc = pc - 2; 152 if (code > 63) 153 opc -= 2; 154 callp = &sysent[code&0177]; 155 if (callp == sysent) { 156 i = fuword(params); 157 params += NBPW; 158 callp = &sysent[i&0177]; 159 } 160 if (i = callp->sy_narg * sizeof (int)) { 161 asm("prober $3,r9,(r10)"); /* GROT */ 162 asm("bnequ ok"); /* GROT */ 163 u.u_error = EFAULT; /* GROT */ 164 goto bad; /* GROT */ 165 asm("ok:"); /* GROT */ 166 asm("movc3 r9,(r10),_u+U_ARG"); /* GROT */ 167 } 168 u.u_ap = u.u_arg; 169 u.u_dirp = (caddr_t)u.u_arg[0]; 170 u.u_r.r_val1 = 0; 171 u.u_r.r_val2 = locr0[R1]; 172 if (setjmp(u.u_qsav)) { 173 if (u.u_error == 0 && u.u_eosys == JUSTRETURN) 174 u.u_error = EINTR; 175 } else { 176 u.u_eosys = JUSTRETURN; 177 (*(callp->sy_call))(); 178 } 179 locr0[PS] &= ~PSL_C; 180 if (u.u_eosys == RESTARTSYS) 181 pc = opc; 182 else if (u.u_eosys == SIMULATERTI) 183 dorti(); 184 else if (u.u_error) { 185 bad: 186 locr0[R0] = u.u_error; 187 locr0[PS] |= PSL_C; /* carry bit */ 188 } else { 189 locr0[R0] = u.u_r.r_val1; 190 locr0[R1] = u.u_r.r_val2; 191 } 192 p = u.u_procp; 193 if (p->p_cursig || ISSIG(p)) 194 psig(); 195 p->p_pri = p->p_usrpri; 196 if (runrun) { 197 /* 198 * Since we are u.u_procp, clock will normally just change 199 * our priority without moving us from one queue to another 200 * (since the running process is not on a queue.) 201 * If that happened after we setrq ourselves but before we 202 * swtch()'ed, we might not be on the queue indicated by 203 * our priority. 204 */ 205 (void) spl6(); 206 setrq(p); 207 swtch(); 208 } 209 if (u.u_prof.pr_scale && (syst -= u.u_vm.vm_stime)) 210 addupc(locr0[PC], &u.u_prof, (int)-syst); 211 curpri = p->p_pri; 212 } 213 214 /* 215 * nonexistent system call-- set fatal error code. 216 */ 217 nosys() 218 { 219 220 u.u_error = 100; 221 } 222