1 /* 2 * 386 Trap and System call handleing 3 */ 4 5 #include "../i386/psl.h" 6 #include "../i386/reg.h" 7 #include "../i386/pte.h" 8 #include "../i386/segments.h" 9 #include "../i386/frame.h" 10 11 #include "param.h" 12 #include "systm.h" 13 #include "dir.h" 14 #include "user.h" 15 #include "proc.h" 16 #include "seg.h" 17 #include "acct.h" 18 #include "kernel.h" 19 #include "vm.h" 20 #include "cmap.h" 21 22 #include "../i386/trap.h" 23 24 #define USER 040 /* user-mode flag added to type */ 25 26 struct sysent sysent[]; 27 int nsysent; 28 #include "dbg.h" 29 /* 30 * Called from the trap handler when a processor trap occurs. 31 */ 32 unsigned *rcr2(), Sysbase; 33 extern short cpl; 34 /*ARGSUSED*/ 35 trap(frame) 36 struct trapframe frame; 37 #define type frame.tf_trapno 38 #define code frame.tf_err 39 #define pc frame.tf_eip 40 { 41 register int *locr0 = ((int *)&frame)/*-PS*/; 42 register int i; 43 register struct proc *p; 44 struct timeval syst; 45 extern int nofault; 46 47 dprintf(DALLTRAPS, "%d. trap",u.u_procp->p_pid); 48 dprintf(DALLTRAPS, "\npc:%x cs:%x ds:%x eflags:%x isp %x\n", 49 frame.tf_eip, frame.tf_cs, frame.tf_ds, frame.tf_eflags, 50 frame.tf_isp); 51 dprintf(DALLTRAPS, "edi %x esi %x ebp %x ebx %x esp %x\n", 52 frame.tf_edi, frame.tf_esi, frame.tf_ebp, 53 frame.tf_ebx, frame.tf_esp); 54 dprintf(DALLTRAPS, "edx %x ecx %x eax %x\n", 55 frame.tf_edx, frame.tf_ecx, frame.tf_eax); 56 dprintf(DALLTRAPS|DPAUSE, "ec %x type %x cr0 %x cr2 %x cpl %x \n", 57 frame.tf_err, frame.tf_trapno, rcr0(), rcr2(), cpl); 58 59 locr0[tEFLAGS] &= ~PSL_NT; /* clear nested trap */ 60 if(nofault && frame.tf_trapno != 0xc) 61 { locr0[tEIP] = nofault; return;} 62 63 syst = u.u_ru.ru_stime; 64 if (ISPL(locr0[tCS]) == SEL_UPL) { 65 type |= USER; 66 u.u_ar0 = locr0; 67 } 68 switch (type) { 69 70 default: 71 #ifdef KDB 72 if (kdb_trap(&psl)) 73 return; 74 #endif 75 printf("trap type %d, code = %x, pc = %x cs = %x, eflags = %x\n", type, code, pc, frame.tf_cs, frame.tf_eflags); 76 type &= ~USER; 77 panic("trap"); 78 /*NOTREACHED*/ 79 80 case T_PROTFLT + USER: /* protection fault */ 81 i = SIGBUS; 82 break; 83 84 case T_PRIVINFLT + USER: /* privileged instruction fault */ 85 case T_RESADFLT + USER: /* reserved addressing fault */ 86 case T_RESOPFLT + USER: /* resereved operand fault */ 87 u.u_code = type &~ USER; 88 i = SIGILL; 89 break; 90 91 case T_ASTFLT + USER: /* Allow process switch */ 92 case T_ASTFLT: 93 astoff(); 94 if ((u.u_procp->p_flag & SOWEUPC) && u.u_prof.pr_scale) { 95 addupc(pc, &u.u_prof, 1); 96 u.u_procp->p_flag &= ~SOWEUPC; 97 } 98 goto out; 99 100 case T_ARITHTRAP + USER: 101 case T_DIVIDE + USER: 102 u.u_code = code; 103 i = SIGFPE; 104 break; 105 106 /* 107 * If the user SP is above the stack segment, 108 * grow the stack automatically. 109 */ 110 case T_STKFLT + USER: 111 case T_SEGFLT + USER: 112 if (grow((unsigned)locr0[tESP]) /*|| grow(code)*/) 113 goto out; 114 xxx: 115 i = SIGSEGV; 116 break; 117 118 case T_TABLEFLT: /* allow page table faults in kernel */ 119 case T_TABLEFLT + USER: /* page table fault */ 120 panic("ptable fault"); 121 122 case T_PAGEFLT: /* allow page faults in kernel mode */ 123 case T_PAGEFLT + USER: /* page fault */ 124 { register u_int vp; 125 struct pte *pte; 126 127 if (rcr2() >= &Sysbase) goto xxx; 128 vp = btop((int)rcr2()); 129 if (vp >= dptov(u.u_procp, u.u_procp->p_dsize) && 130 vp < sptov(u.u_procp, u.u_procp->p_ssize-1)) { 131 if (grow((unsigned)locr0[tESP]) || grow(rcr2())) 132 goto out; 133 else { 134 if(nofault) { locr0[tEIP] = nofault; return;} 135 printf("didnt"); 136 i = SIGSEGV; 137 break; 138 } 139 } 140 i = u.u_error; 141 pagein(rcr2(), 0); 142 u.u_error = i; 143 if (type == T_PAGEFLT) 144 return; 145 if(nofault) { locr0[tEIP] = nofault; return;} 146 goto out; 147 } 148 149 case T_BPTFLT + USER: /* bpt instruction fault */ 150 case T_TRCTRAP + USER: /* trace trap */ 151 locr0[tEFLAGS] &= ~PSL_T; 152 i = SIGTRAP; 153 break; 154 155 /* 156 * For T_KSPNOTVAL and T_BUSERR, can not allow spl to 157 * drop to 0 as clock could go off and we would end up 158 * doing an rei to the interrupt stack at ipl 0 (a 159 * reserved operand fault). Instead, we allow psignal 160 * to post an ast, then return to user mode where we 161 * will reenter the kernel on the kernel's stack and 162 * can then service the signal. 163 */ 164 case T_KSPNOTVAL: 165 if (noproc) 166 panic("ksp not valid"); 167 /* fall thru... */ 168 case T_KSPNOTVAL + USER: 169 printf("pid %d: ksp not valid\n", u.u_procp->p_pid); 170 /* must insure valid kernel stack pointer? */ 171 psignal(u.u_procp, SIGKILL); 172 return; 173 174 case T_BUSERR + USER: 175 u.u_code = code; 176 psignal(u.u_procp, SIGBUS); 177 return; 178 } 179 psignal(u.u_procp, i); 180 out: 181 p = u.u_procp; 182 183 if(p->p_cursig) 184 printf("out cursig %x flg %x sig %x ign %x msk %x\n", 185 p->p_cursig, 186 p->p_flag, p->p_sig, p->p_sigignore, p->p_sigmask); 187 188 if (p->p_cursig || ISSIG(p)) 189 psig(1); 190 p->p_pri = p->p_usrpri; 191 if (runrun) { 192 /* 193 * Since we are u.u_procp, clock will normally just change 194 * our priority without moving us from one queue to another 195 * (since the running process is not on a queue.) 196 * If that happened after we setrq ourselves but before we 197 * swtch()'ed, we might not be on the queue indicated by 198 * our priority. 199 */ 200 (void) splclock(); 201 setrq(p); 202 u.u_ru.ru_nivcsw++; 203 swtch(); 204 } 205 if (u.u_prof.pr_scale) { 206 int ticks; 207 struct timeval *tv = &u.u_ru.ru_stime; 208 209 ticks = ((tv->tv_sec - syst.tv_sec) * 1000 + 210 (tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000); 211 if (ticks) 212 addupc(pc, &u.u_prof, ticks); 213 } 214 curpri = p->p_pri; 215 #undef type 216 #undef code 217 #undef pc 218 } 219 220 /* 221 * Called from locore when a system call occurs 222 */ 223 int fuckup; 224 /*ARGSUSED*/ 225 syscall(frame) 226 struct syscframe frame; 227 #define code frame.sf_eax /* note: written over! */ 228 #define pc frame.sf_eip 229 { 230 register int *locr0 = ((int *)&frame)/*-PS*/; 231 register caddr_t params; 232 register int i; 233 register struct sysent *callp; 234 register struct proc *p; 235 struct timeval syst; 236 int opc; 237 238 #ifdef lint 239 r0 = 0; r0 = r0; r1 = 0; r1 = r1; 240 #endif 241 syst = u.u_ru.ru_stime; 242 if (ISPL(locr0[sCS]) != SEL_UPL) 243 panic("syscall"); 244 u.u_ar0 = locr0; 245 svfpsp(); 246 params = (caddr_t)locr0[sESP] + NBPW ; 247 u.u_error = 0; 248 /* 249 * Reconstruct pc, assuming lcall $X,y is 7 bytes, as it is always. 250 */ 251 opc = pc - 7; 252 callp = (code >= nsysent) ? &sysent[63] : &sysent[code]; 253 if (callp == sysent) { 254 i = fuword(params); 255 params += NBPW; 256 callp = (code >= nsysent) ? &sysent[63] : &sysent[code]; 257 } 258 /*dprintf(DALLSYSC,"%d. call %d\n", u.u_procp->p_pid, code);*/ 259 if ((i = callp->sy_narg * sizeof (int)) && 260 (u.u_error = copyin(params, (caddr_t)u.u_arg, (u_int)i)) != 0) { 261 locr0[sEAX] = u.u_error; 262 locr0[sEFLAGS] |= PSL_C; /* carry bit */ 263 goto done; 264 } 265 u.u_r.r_val1 = 0; 266 u.u_r.r_val2 = locr0[sEDX]; 267 if (setjmp(&u.u_qsave)) { 268 if (u.u_error == 0 && u.u_eosys != RESTARTSYS) 269 u.u_error = EINTR; 270 } else { 271 u.u_eosys = NORMALRETURN; 272 (*callp->sy_call)(); 273 } 274 /*rsfpsp();*/ 275 if (u.u_eosys == NORMALRETURN) { 276 if (u.u_error) { 277 /*dprintf(DSYSFAIL,"%d. fail %d %d\n",u.u_procp->p_pid, code, u.u_error);*/ 278 locr0[sEAX] = u.u_error; 279 locr0[sEFLAGS] |= PSL_C; /* carry bit */ 280 } else { 281 locr0[sEFLAGS] &= ~PSL_C; /* clear carry bit */ 282 locr0[sEAX] = u.u_r.r_val1; 283 locr0[sEDX] = u.u_r.r_val2; 284 } 285 } else if (u.u_eosys == RESTARTSYS) 286 pc = opc; 287 /* else if (u.u_eosys == JUSTRETURN) */ 288 /* nothing to do */ 289 done: 290 p = u.u_procp; 291 if (p->p_cursig || ISSIG(p)) 292 psig(0); 293 p->p_pri = p->p_usrpri; 294 if (runrun) { 295 /* 296 * Since we are u.u_procp, clock will normally just change 297 * our priority without moving us from one queue to another 298 * (since the running process is not on a queue.) 299 * If that happened after we setrq ourselves but before we 300 * swtch()'ed, we might not be on the queue indicated by 301 * our priority. 302 */ 303 (void) splclock(); 304 setrq(p); 305 u.u_ru.ru_nivcsw++; 306 swtch(); 307 } 308 if (u.u_prof.pr_scale) { 309 int ticks; 310 struct timeval *tv = &u.u_ru.ru_stime; 311 312 ticks = ((tv->tv_sec - syst.tv_sec) * 1000 + 313 (tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000); 314 if (ticks) 315 addupc(opc, &u.u_prof, ticks); 316 } 317 curpri = p->p_pri; 318 } 319 320 /* 321 * nonexistent system call-- signal process (may want to handle it) 322 * flag error if process won't see signal immediately 323 * Q: should we do that all the time ?? 324 */ 325 nosys() 326 { 327 328 if (u.u_signal[SIGSYS] == SIG_IGN || u.u_signal[SIGSYS] == SIG_HOLD) 329 u.u_error = EINVAL; 330 psignal(u.u_procp, SIGSYS); 331 } 332 333 #ifdef notdef 334 /* 335 * Ignored system call 336 */ 337 nullsys() 338 { 339 340 } 341 #endif 342