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