1 /* trap.c 3.6 10/02/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 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 i = SIGILL; 51 break; 52 53 case RESCHED + USER: /* Allow process switch */ 54 goto out; 55 56 case ARITHTRAP + USER: 57 i = SIGFPE; 58 break; 59 60 /* 61 * If the user SP is above the stack segment, 62 * grow the stack automatically. 63 */ 64 case SEGFLT + USER: /* segmentation exception */ 65 if(grow((unsigned)locr0[SP]) || grow(code)) 66 goto out; 67 i = SIGSEGV; 68 break; 69 70 case TABLEFLT: /* allow page table faults in kernel mode */ 71 case TABLEFLT + USER: /* page table fault */ 72 panic("page table fault"); 73 74 case PAGEFLT: /* allow page faults in kernel mode */ 75 case PAGEFLT + USER: /* page fault */ 76 i = u.u_error; 77 pagein(code); /* bring in page containing virtual addr */ 78 u.u_error = i; 79 /* 80 if (type == PAGEFLT) 81 */ 82 return; 83 /* 84 goto out; 85 */ 86 87 case BPTFLT + USER: /* bpt instruction fault */ 88 case TRCTRAP + USER: /* trace trap */ 89 locr0[PS] &= ~PSL_T; /* turn off trace bit */ 90 i = SIGTRAP; 91 break; 92 93 case XFCFLT + USER: /* xfc instruction fault */ 94 i = SIGEMT; 95 break; 96 97 case COMPATFLT + USER: /* compatibility mode fault */ 98 u.u_cfcode = code; 99 i = SIGILL; 100 break; 101 } 102 psignal(u.u_procp, i); 103 out: 104 p = u.u_procp; 105 if (p->p_cursig || ISSIG(p)) 106 psig(); 107 p->p_pri = p->p_usrpri; 108 if (runrun) { 109 /* 110 * Since we are u.u_procp, clock will normally just change 111 * our priority without moving us from one queue to another 112 * (since the running process is not on a queue.) 113 * If that happened after we setrq ourselves but before we 114 * swtch()'ed, we might not be on the queue indicated by 115 * our priority. 116 */ 117 spl6(); 118 setrq(p); 119 swtch(); 120 } 121 if (u.u_prof.pr_scale && (syst -= u.u_vm.vm_stime)) 122 addupc((caddr_t)locr0[PC], &u.u_prof, (int)-syst); 123 curpri = p->p_pri; 124 } 125 126 /* 127 * Called from the trap handler when a system call occurs 128 */ 129 /*ARGSUSED*/ 130 syscall(sp, type, code, pc, psl) 131 unsigned code; 132 { 133 register int *locr0 = ((int *)&psl)-PS; 134 register caddr_t params; /* known to be r10 below */ 135 register int i; /* known to be r9 below */ 136 register struct sysent *callp; 137 register struct proc *p; 138 time_t syst; 139 int opc; 140 141 syst = u.u_vm.vm_stime; 142 if (!USERMODE(locr0[PS])) 143 panic("syscall"); 144 u.u_ar0 = locr0; 145 params = (caddr_t)locr0[AP] + NBPW; 146 u.u_error = 0; 147 opc = pc - 2; 148 if (code > 63) 149 opc -= 2; 150 callp = &sysent[code&0177]; 151 if (callp == sysent) { 152 i = fuword(params); 153 params += NBPW; 154 callp = &sysent[i&0177]; 155 } 156 if (i = callp->sy_narg * sizeof (int)) { 157 asm("prober $3,r9,(r10)"); /* GROT */ 158 asm("bnequ ok"); /* GROT */ 159 u.u_error = EFAULT; /* GROT */ 160 goto bad; /* GROT */ 161 asm("ok:"); /* GROT */ 162 asm("movc3 r9,(r10),_u+U_ARG"); /* GROT */ 163 } 164 u.u_ap = u.u_arg; 165 u.u_dirp = (caddr_t)u.u_arg[0]; 166 u.u_r.r_val1 = 0; 167 u.u_r.r_val2 = locr0[R1]; 168 if (setjmp(u.u_qsav)) { 169 if (u.u_error == 0 && u.u_eosys == JUSTRETURN) 170 u.u_error = EINTR; 171 } else { 172 u.u_eosys = JUSTRETURN; 173 (*(callp->sy_call))(); 174 } 175 locr0[PS] &= ~PSL_C; 176 if (u.u_eosys == RESTARTSYS) 177 pc = opc; 178 else if (u.u_eosys == SIMULATERTI) 179 dorti(); 180 else if (u.u_error) { 181 bad: 182 locr0[R0] = u.u_error; 183 locr0[PS] |= PSL_C; /* carry bit */ 184 } else { 185 locr0[R0] = u.u_r.r_val1; 186 locr0[R1] = u.u_r.r_val2; 187 } 188 p = u.u_procp; 189 if (p->p_cursig || ISSIG(p)) 190 psig(); 191 p->p_pri = p->p_usrpri; 192 if (runrun) { 193 /* 194 * Since we are u.u_procp, clock will normally just change 195 * our priority without moving us from one queue to another 196 * (since the running process is not on a queue.) 197 * If that happened after we setrq ourselves but before we 198 * swtch()'ed, we might not be on the queue indicated by 199 * our priority. 200 */ 201 spl6(); 202 setrq(p); 203 swtch(); 204 } 205 if (u.u_prof.pr_scale && (syst -= u.u_vm.vm_stime)) 206 addupc((caddr_t)locr0[PC], &u.u_prof, (int)-syst); 207 curpri = p->p_pri; 208 } 209 210 /* 211 * nonexistent system call-- set fatal error code. 212 */ 213 nosys() 214 { 215 216 u.u_error = 100; 217 } 218 219 /* 220 * Ignored system call 221 */ 222 nullsys() 223 { 224 225 } 226