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 #ifdef DEBUG 48 dprintf(DALLTRAPS, "%d. trap",u.u_procp->p_pid); 49 dprintf(DALLTRAPS, "\npc:%x cs:%x ds:%x eflags:%x isp %x\n", 50 frame.tf_eip, frame.tf_cs, frame.tf_ds, frame.tf_eflags, 51 frame.tf_isp); 52 dprintf(DALLTRAPS, "edi %x esi %x ebp %x ebx %x esp %x\n", 53 frame.tf_edi, frame.tf_esi, frame.tf_ebp, 54 frame.tf_ebx, frame.tf_esp); 55 dprintf(DALLTRAPS, "edx %x ecx %x eax %x\n", 56 frame.tf_edx, frame.tf_ecx, frame.tf_eax); 57 dprintf(DALLTRAPS|DPAUSE, "ec %x type %x cr0 %x cr2 %x cpl %x \n", 58 frame.tf_err, frame.tf_trapno, rcr0(), rcr2(), cpl); 59 #endif 60 61 locr0[tEFLAGS] &= ~PSL_NT; /* clear nested trap XXX */ 62 if(nofault && frame.tf_trapno != 0xc) 63 { locr0[tEIP] = nofault; return;} 64 65 syst = u.u_ru.ru_stime; 66 if (ISPL(locr0[tCS]) == SEL_UPL) { 67 type |= USER; 68 u.u_ar0 = locr0; 69 } 70 switch (type) { 71 72 default: 73 bit_sucker: 74 #ifdef KDB 75 if (kdb_trap(&psl)) 76 return; 77 #endif 78 printf("trap type %d, code = %x, pc = %x cs = %x, eflags = %x\n", type, code, pc, frame.tf_cs, frame.tf_eflags); 79 type &= ~USER; 80 panic("trap"); 81 /*NOTREACHED*/ 82 83 case T_SEGNPFLT + USER: 84 case T_PROTFLT + USER: /* protection fault */ 85 u.u_code = code + BUS_SEGM_FAULT ; 86 i = SIGBUS; 87 break; 88 89 case T_PRIVINFLT + USER: /* privileged instruction fault */ 90 case T_RESADFLT + USER: /* reserved addressing fault */ 91 case T_RESOPFLT + USER: /* reserved operand fault */ 92 case T_FPOPFLT + USER: /* coprocessor operand fault */ 93 u.u_code = type &~ USER; 94 i = SIGILL; 95 break; 96 97 case T_ASTFLT + USER: /* Allow process switch */ 98 case T_ASTFLT: 99 astoff(); 100 if ((u.u_procp->p_flag & SOWEUPC) && u.u_prof.pr_scale) { 101 addupc(pc, &u.u_prof, 1); 102 u.u_procp->p_flag &= ~SOWEUPC; 103 } 104 goto out; 105 106 case T_DNA + USER: 107 u.u_code = FPE_FPU_NP_TRAP; 108 i = SIGFPE; 109 break; 110 111 case T_BOUND + USER: 112 u.u_code = FPE_SUBRNG_TRAP; 113 i = SIGFPE; 114 break; 115 116 case T_OFLOW + USER: 117 u.u_code = FPE_INTOVF_TRAP; 118 i = SIGFPE; 119 break; 120 121 case T_DIVIDE + USER: 122 u.u_code = FPE_INTDIV_TRAP; 123 i = SIGFPE; 124 break; 125 126 case T_ARITHTRAP + USER: 127 u.u_code = code; 128 i = SIGFPE; 129 break; 130 131 /* 132 * If the user SP is above the stack segment, 133 * grow the stack automatically. 134 */ 135 case T_STKFLT + USER: 136 case T_SEGFLT + USER: 137 if (grow((unsigned)locr0[tESP]) /*|| grow(code)*/) 138 goto out; 139 u.u_code = code; 140 i = SIGSEGV; 141 break; 142 143 case T_TABLEFLT: /* allow page table faults in kernel */ 144 case T_TABLEFLT + USER: /* page table fault */ 145 panic("ptable fault"); 146 147 case T_PAGEFLT: /* allow page faults in kernel mode */ 148 case T_PAGEFLT + USER: /* page fault */ 149 { register u_int vp; 150 struct pte *pte; 151 152 if(u.u_procp->p_pid == 2) goto bit_sucker; 153 #define PGEX_P 0x01 154 if (rcr2() >= &Sysbase || code & PGEX_P) { 155 u.u_code = code + BUS_PAGE_FAULT; 156 i = SIGBUS; 157 break; 158 } else { 159 vp = btop((int)rcr2()); 160 if (vp >= dptov(u.u_procp, u.u_procp->p_dsize) 161 && vp < sptov(u.u_procp, u.u_procp->p_ssize-1)){ 162 if (grow((unsigned)locr0[tESP]) 163 || grow(rcr2())) 164 goto out; 165 else if (nofault) { 166 locr0[tEIP] = nofault; 167 return; 168 } 169 #ifdef DEBUG 170 pg("didnt "); 171 printf("\npc:%x cs:%x ds:%x eflags:%x isp %x\n", 172 frame.tf_eip, frame.tf_cs, frame.tf_ds, frame.tf_eflags, 173 frame.tf_isp); 174 printf("edi %x esi %x ebp %x ebx %x esp %x\n", 175 frame.tf_edi, frame.tf_esi, frame.tf_ebp, 176 frame.tf_ebx, frame.tf_esp); 177 printf("edx %x ecx %x eax %x\n", 178 frame.tf_edx, frame.tf_ecx, frame.tf_eax); 179 printf("ec %x type %x cr0 %x cr2 %x cpl %x \n", 180 frame.tf_err, frame.tf_trapno, rcr0(), rcr2(), cpl); 181 #endif 182 i = SIGSEGV; 183 break; 184 } 185 i = u.u_error; 186 pagein(rcr2(), 0); 187 u.u_error = i; 188 if (type == T_PAGEFLT) return; 189 190 if(nofault) { 191 locr0[tEIP] = nofault; 192 return; 193 } 194 goto out; 195 } 196 } 197 198 case T_TRCTRAP: /* trace trap -- someone single stepping lcall's */ 199 locr0[tEFLAGS] &= ~PSL_T; 200 /* Q: how do we turn it on again? */ 201 return; 202 203 case T_BPTFLT + USER: /* bpt instruction fault */ 204 case T_TRCTRAP + USER: /* trace trap */ 205 locr0[tEFLAGS] &= ~PSL_T; 206 i = SIGTRAP; 207 break; 208 209 /* 210 * For T_KSPNOTVAL and T_BUSERR, can not allow spl to 211 * drop to 0 as clock could go off and we would end up 212 * doing an rei to the interrupt stack at ipl 0 (a 213 * reserved operand fault). Instead, we allow psignal 214 * to post an ast, then return to user mode where we 215 * will reenter the kernel on the kernel's stack and 216 * can then service the signal. 217 */ 218 case T_KSPNOTVAL: 219 if (noproc) 220 panic("ksp not valid"); 221 /* fall thru... */ 222 case T_KSPNOTVAL + USER: 223 printf("pid %d: ksp not valid\n", u.u_procp->p_pid); 224 /* must insure valid kernel stack pointer? */ 225 psignal(u.u_procp, SIGKILL); 226 return; 227 228 case T_BUSERR + USER: 229 u.u_code = code; 230 psignal(u.u_procp, SIGBUS); 231 return; 232 } 233 psignal(u.u_procp, i); 234 out: 235 p = u.u_procp; 236 237 if (p->p_cursig || ISSIG(p)) 238 psig(1); 239 p->p_pri = p->p_usrpri; 240 if (runrun) { 241 /* 242 * Since we are u.u_procp, clock will normally just change 243 * our priority without moving us from one queue to another 244 * (since the running process is not on a queue.) 245 * If that happened after we setrq ourselves but before we 246 * swtch()'ed, we might not be on the queue indicated by 247 * our priority. 248 */ 249 (void) splclock(); 250 setrq(p); 251 u.u_ru.ru_nivcsw++; 252 swtch(); 253 } 254 if (u.u_prof.pr_scale) { 255 int ticks; 256 struct timeval *tv = &u.u_ru.ru_stime; 257 258 ticks = ((tv->tv_sec - syst.tv_sec) * 1000 + 259 (tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000); 260 if (ticks) 261 addupc(pc, &u.u_prof, ticks); 262 } 263 curpri = p->p_pri; 264 #undef type 265 #undef code 266 #undef pc 267 } 268 269 /* 270 * Called from locore when a system call occurs 271 */ 272 /*ARGSUSED*/ 273 syscall(frame) 274 struct syscframe frame; 275 #define code frame.sf_eax /* note: written over! */ 276 #define pc frame.sf_eip 277 { 278 register int *locr0 = ((int *)&frame)/*-PS*/; 279 register caddr_t params; 280 register int i; 281 register struct sysent *callp; 282 register struct proc *p; 283 struct timeval syst; 284 int opc; 285 286 #ifdef lint 287 r0 = 0; r0 = r0; r1 = 0; r1 = r1; 288 #endif 289 syst = u.u_ru.ru_stime; 290 if (ISPL(locr0[sCS]) != SEL_UPL) 291 { 292 printf("\npc:%x cs:%x eflags:%x\n", 293 frame.sf_eip, frame.sf_cs, frame.sf_eflags); 294 printf("edi %x esi %x ebp %x ebx %x esp %x\n", 295 frame.sf_edi, frame.sf_esi, frame.sf_ebp, 296 frame.sf_ebx, frame.sf_esp); 297 printf("edx %x ecx %x eax %x\n", frame.sf_edx, frame.sf_ecx, frame.sf_eax); 298 printf("cr0 %x cr2 %x cpl %x \n", rcr0(), rcr2(), cpl); 299 panic("syscall"); 300 } 301 u.u_ar0 = locr0; 302 params = (caddr_t)locr0[sESP] + NBPW ; 303 u.u_error = 0; 304 /* 305 * Reconstruct pc, assuming lcall $X,y is 7 bytes, as it is always. 306 */ 307 opc = pc - 7; 308 callp = (code >= nsysent) ? &sysent[63] : &sysent[code]; 309 if (callp == sysent) { 310 i = fuword(params); 311 params += NBPW; 312 callp = (code >= nsysent) ? &sysent[63] : &sysent[code]; 313 } 314 /*dprintf(DALLSYSC,"%d. call %d\n", u.u_procp->p_pid, code);*/ 315 if ((i = callp->sy_narg * sizeof (int)) && 316 (u.u_error = copyin(params, (caddr_t)u.u_arg, (u_int)i)) != 0) { 317 locr0[sEAX] = u.u_error; 318 locr0[sEFLAGS] |= PSL_C; /* carry bit */ 319 goto done; 320 } 321 u.u_r.r_val1 = 0; 322 u.u_r.r_val2 = locr0[sEDX]; 323 if (setjmp(&u.u_qsave)) { 324 if (u.u_error == 0 && u.u_eosys != RESTARTSYS) 325 u.u_error = EINTR; 326 } else { 327 u.u_eosys = NORMALRETURN; 328 (*callp->sy_call)(); 329 } 330 if (u.u_eosys == NORMALRETURN) { 331 if (u.u_error) { 332 /*dprintf(DSYSFAIL,"%d. fail %d %d\n",u.u_procp->p_pid, code, u.u_error);*/ 333 locr0[sEAX] = u.u_error; 334 locr0[sEFLAGS] |= PSL_C; /* carry bit */ 335 } else { 336 locr0[sEFLAGS] &= ~PSL_C; /* clear carry bit */ 337 locr0[sEAX] = u.u_r.r_val1; 338 locr0[sEDX] = u.u_r.r_val2; 339 } 340 } else if (u.u_eosys == RESTARTSYS) 341 pc = opc; 342 /* else if (u.u_eosys == JUSTRETURN) */ 343 /* nothing to do */ 344 done: 345 p = u.u_procp; 346 if (p->p_cursig || ISSIG(p)) 347 psig(0); 348 p->p_pri = p->p_usrpri; 349 if (runrun) { 350 /* 351 * Since we are u.u_procp, clock will normally just change 352 * our priority without moving us from one queue to another 353 * (since the running process is not on a queue.) 354 * If that happened after we setrq ourselves but before we 355 * swtch()'ed, we might not be on the queue indicated by 356 * our priority. 357 */ 358 (void) splclock(); 359 setrq(p); 360 u.u_ru.ru_nivcsw++; 361 swtch(); 362 } 363 if (u.u_prof.pr_scale) { 364 int ticks; 365 struct timeval *tv = &u.u_ru.ru_stime; 366 367 ticks = ((tv->tv_sec - syst.tv_sec) * 1000 + 368 (tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000); 369 if (ticks) 370 addupc(opc, &u.u_prof, ticks); 371 } 372 curpri = p->p_pri; 373 } 374 375 /* 376 * nonexistent system call-- signal process (may want to handle it) 377 * flag error if process won't see signal immediately 378 * Q: should we do that all the time ?? 379 */ 380 nosys() 381 { 382 383 if (u.u_signal[SIGSYS] == SIG_IGN || u.u_signal[SIGSYS] == SIG_HOLD) 384 u.u_error = EINVAL; 385 psignal(u.u_procp, SIGSYS); 386 } 387 388 /* 389 * Ignored system call 390 */ 391 nullsys() 392 { 393 394 } 395