1 /* trap.c 3.5 06/07/80 */ 2 3 4 #include "../h/param.h" 5 #include "../h/systm.h" 6 #include "../h/dir.h" 7 #include "../h/user.h" 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 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\n", type, code); 41 #ifdef ERNIE 42 asm("halt"); 43 #endif 44 panic("trap"); 45 46 case PROTFLT + USER: /* protection fault */ 47 i = SIGBUS; 48 break; 49 50 case PRIVINFLT + USER: /* privileged instruction fault */ 51 case RESADFLT + USER: /* reserved addressing fault */ 52 case RESOPFLT + USER: /* resereved operand fault */ 53 i = SIGILL; 54 break; 55 56 case RESCHED + USER: /* Allow process switch */ 57 goto out; 58 59 case ARITHTRAP + USER: 60 i = SIGFPE; 61 break; 62 63 /* 64 * If the user SP is above the stack segment, 65 * grow the stack automatically. 66 */ 67 case SEGFLT + USER: /* segmentation exception */ 68 if(grow((unsigned)locr0[SP]) || grow(code)) 69 goto out; 70 i = SIGSEGV; 71 break; 72 73 case TABLEFLT: /* allow page table faults in kernel mode */ 74 case TABLEFLT + USER: /* page table fault */ 75 panic("page table fault"); 76 77 case PAGEFLT: /* allow page faults in kernel mode */ 78 case PAGEFLT + USER: /* page fault */ 79 i = u.u_error; 80 pagein(code); /* bring in page containing virtual addr */ 81 u.u_error = i; 82 /* 83 if (type == PAGEFLT) 84 */ 85 return; 86 /* 87 goto out; 88 */ 89 90 case BPTFLT + USER: /* bpt instruction fault */ 91 case TRCTRAP + USER: /* trace trap */ 92 locr0[PS] &= ~PSL_T; /* turn off trace bit */ 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_cfcode = 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 spl6(); 121 setrq(p); 122 swtch(); 123 } 124 if (u.u_prof.pr_scale && (syst -= u.u_vm.vm_stime)) 125 addupc((caddr_t)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 spl6(); 205 setrq(p); 206 swtch(); 207 } 208 if (u.u_prof.pr_scale && (syst -= u.u_vm.vm_stime)) 209 addupc((caddr_t)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