|
|
1.1 ! root 1: /* (lgl- ! 2: * COHERENT Version 4.0 ! 3: * Copyright (c) 1982, 1992. ! 4: * An unpublished work by Mark Williams Company, Chicago. ! 5: * All rights reserved. ! 6: -lgl) */ ! 7: #include <sys/coherent.h> ! 8: #include <sys/reg.h> ! 9: #include <sys/systab.h> ! 10: #include <errno.h> ! 11: #include <sys/proc.h> ! 12: #include <sys/seg.h> ! 13: #include <signal.h> ! 14: ! 15: /* opcodes recognized, and partially emulated, in gp fault handler */ ! 16: #define READ_CR0 1 ! 17: #define WRITE_CR0 2 ! 18: #define READ_CR2 3 ! 19: #define READ_CR3 4 ! 20: #define WRITE_CR3 5 ! 21: #define HALT 6 ! 22: #define IRET 7 ! 23: #define READ_DR0 8 ! 24: #define READ_DR1 9 ! 25: #define READ_DR2 10 ! 26: #define READ_DR3 11 ! 27: #define READ_DR6 12 ! 28: #define READ_DR7 13 ! 29: #define WRITE_DR0 14 ! 30: #define WRITE_DR1 15 ! 31: #define WRITE_DR2 16 ! 32: #define WRITE_DR3 17 ! 33: #define WRITE_DR6 18 ! 34: #define WRITE_DR7 19 ! 35: ! 36: #define ENTER_OP 0xC8 /* Opcode for 'enter' instruction. */ ! 37: #define IRET_RETRY_LIM 10 ! 38: #define RESUME_FLAG 0x10000 /* RF bit in PSW */ ! 39: #define TRAP_FLAG 0x00100 /* TF bit in PSW */ ! 40: ! 41: extern unsigned char selkcopy(); ! 42: extern unsigned int DR0,DR1,DR2,DR3,DR7; ! 43: static int trap_op(); ! 44: ! 45: /* ! 46: * Macro RDUMP does register dump, followed by final message. ! 47: * ! 48: * Callable only from within trap() or one of its cousins. ! 49: */ ! 50: #define RDUMP() { \ ! 51: printf("\neax=%x ebx=%x ecx=%x edx=%x\n", eax, ebx, ecx, edx); \ ! 52: printf("esi=%x edi=%x ebp=%x esp=%x\n", esi, edi, ebp, esp); \ ! 53: printf("cs=%x ds=%x es=%x ss=%x fs=%x gs=%x\n", \ ! 54: cs&0xffff, ds&0xffff, es&0xffff, ss&0xffff, fs&0xffff, gs&0xffff); \ ! 55: printf("err #%d eip=%x uesp=%x cmd=%s\n", err, eip, uesp, u.u_comm); \ ! 56: printf("efl=%x ", efl); } ! 57: /* end RDUMP */ ! 58: ! 59: /* ! 60: * Debug only - display 64 words of stack traceback. ! 61: */ ! 62: #define SDUMP(frame) { \ ! 63: int *ip = frame, i; \ ! 64: for (i=0;i < 32;i++) { \ ! 65: if ((i % 8)==0) \ ! 66: putchar('\n'); \ ! 67: printf("%x ", *ip++); \ ! 68: } \ ! 69: putchar('\n'); \ ! 70: } ! 71: /* end SDUMP */ ! 72: ! 73: /* ! 74: * Global symbols from kernel text. ! 75: */ ! 76: extern unsigned int _Idle; ! 77: extern unsigned int __xtrap_break__; ! 78: extern unsigned int __xtrap_off__; ! 79: extern unsigned int __xtrap_on__; ! 80: extern unsigned int sig32; ! 81: extern unsigned int syc32; ! 82: ! 83: /* ! 84: * iret_flt is set when first bad iret is detected. ! 85: */ ! 86: static int iret_flt; ! 87: ! 88: /* ! 89: * Trap handler. ! 90: * The arguments are the registers, ! 91: * saved on the stack by machine code. This call ! 92: * is different from most C calls in that the registers ! 93: * get copied back; if you change a "trap" parameter then ! 94: * the machine register will be altered when the trap is ! 95: * dismissed. ! 96: * ! 97: * Argument "trapno" is the return eip for the code calling tsave(). ! 98: */ ! 99: trap(gs, fs, es, ds, edi, esi, ebp, esp, ebx, edx, ecx, eax, trapno, err, ! 100: eip, cs, efl, uesp, ss) ! 101: char *eip; ! 102: { ! 103: register struct systab *stp; ! 104: register int callnum; ! 105: register int sigcode; ! 106: extern int trapcode; ! 107: extern *mmdata[], mminit; ! 108: cseg_t *pp; ! 109: register SEG *segp; ! 110: int splo, datahi; ! 111: unsigned int txtlo, txthi; ! 112: unsigned char opcode; /* Opcode we trapped on. */ ! 113: unsigned short e_arg; /* Argument to 'enter' opcode. */ ! 114: unsigned long newsp; /* Anticipated value for stack pointer. */ ! 115: unsigned int cr2 = 0; ! 116: unsigned int cpl = cs & SEG_PL; ! 117: ! 118: /* ! 119: * Avoid sign extension confusion on 286 ds ! 120: */ ! 121: if (ds == (SEG_286_UD | R_USR)) ! 122: uesp = (unsigned short)uesp; ! 123: ! 124: if (err==SINMI) { ! 125: printf("Parity error\n"); ! 126: RDUMP(); ! 127: panic("..."); ! 128: } ! 129: ! 130: /* ! 131: * Expect this to never happen! ! 132: */ ! 133: if (SELF->p_flags & PFKERN) { ! 134: panic("pid%d: kernel process trap: err=%x, ip=%x ax=%d", ! 135: SELF->p_pid, err, eip, eax); ! 136: } ! 137: ! 138: T_HAL(0x4000, printf("T%d ", err)); ! 139: sigcode = 0; ! 140: ! 141: u.u_regl = &gs; /* hook in register set for consave/conrest */ ! 142: ! 143: switch (err) { ! 144: case SIOSYS: ! 145: /* ! 146: * 286 System call. ! 147: */ ! 148: sigcode = oldsys(); ! 149: break; ! 150: case SISYS: ! 151: /* ! 152: * 386 System call. ! 153: */ ! 154: u.u_error = 0; ! 155: callnum = eax; ! 156: ! 157: T_PIGGY(4, printf("{%d}", callnum)); ! 158: ! 159: if (callnum < NMICALL) ! 160: stp = sysitab + callnum; ! 161: else if ( callnum == COHCALL ) ! 162: stp = &cohcall; ! 163: else if ( ((callnum&0xFF)==0x28) && ((callnum>>8)<=H28CALL) ) ! 164: stp = h28itab + ((callnum>>8) - 1); ! 165: else { ! 166: sigcode = SIGSYS; ! 167: goto trapend; ! 168: } ! 169: ! 170: ukcopy(uesp+sizeof(long),u.u_args, stp->s_nargs*sizeof(long)); ! 171: if (u.u_error) { ! 172: sigcode = SIGSYS; ! 173: goto trapend; ! 174: } ! 175: ! 176: u.u_io.io_seg = IOUSR; ! 177: if (envsave(&u.u_sigenv)) { ! 178: u.u_error = EINTR; ! 179: } else { ! 180: eax = (*stp->s_func)(u.u_args[0], ! 181: u.u_args[1], ! 182: u.u_args[2], ! 183: u.u_args[3], ! 184: u.u_args[4], ! 185: u.u_args[5]); ! 186: edx = u.u_rval2; ! 187: } ! 188: ! 189: efl &= ~MFCBIT; /* clear carry flag in return efl */ ! 190: if (u.u_error) { ! 191: eax = u.u_error; ! 192: efl |= MFCBIT; ! 193: } ! 194: break; ! 195: /* ! 196: * Trap. ! 197: */ ! 198: case SIDIV: ! 199: sigcode = SIGFPE; ! 200: break; ! 201: ! 202: case SISST: ! 203: sigcode = SIGTRAP; ! 204: break; ! 205: ! 206: case SIBPT: ! 207: sigcode = SIGTRAP; ! 208: break; ! 209: ! 210: case SIOVF: ! 211: sigcode = SIGEMT; ! 212: break; ! 213: ! 214: case SIBND: ! 215: /* ! 216: * Bound ! 217: */ ! 218: sigcode = SIGIOT; ! 219: break; ! 220: ! 221: case SIOP: ! 222: /* ! 223: * Invalid opcode ! 224: */ ! 225: if (cpl < 2) { ! 226: int *ip = (int *)eip; ! 227: ! 228: RDUMP(); ! 229: printf("(eip)=%x %x %x ", ip[0], ip[1], ip[2]); ! 230: panic("Invalid Opcode"); ! 231: } ! 232: sigcode = SIGILL; ! 233: break; ! 234: ! 235: #if 0 ! 236: case SIXNP: ! 237: /* ! 238: * Processor extension not available ! 239: */ ! 240: if (int11() & 2) /* NDP present */ ! 241: ndpNewOwner(); ! 242: else ! 243: sigcode = SIGFPE; ! 244: break; ! 245: #endif ! 246: ! 247: case SIDBL: ! 248: /* ! 249: * Double exception ! 250: */ ! 251: panic("double exception: cs=%x ip=%x", cs, eip); ! 252: sigcode = SIGSEGV; ! 253: break; ! 254: ! 255: case SIXS: ! 256: /* ! 257: * Processor extension segment overrun ! 258: */ ! 259: sigcode = SIGSEGV; ! 260: break; ! 261: ! 262: case SITS: ! 263: /* ! 264: * Invalid task state segment ! 265: */ ! 266: panic("invalid tss: cs=%x ip=%x", cs, eip); ! 267: sigcode = SIGSEGV; ! 268: break; ! 269: ! 270: case SINP: ! 271: /* ! 272: * Segment not present ! 273: */ ! 274: sigcode = SIGSEGV; ! 275: break; ! 276: ! 277: case SISS: ! 278: /* ! 279: * Stack segment overrun/not present ! 280: */ ! 281: sigcode = SIGKILL; ! 282: break; ! 283: default: ! 284: RDUMP(); ! 285: panic("Fatal Trap"); ! 286: } ! 287: ! 288: trapend: ! 289: /* ! 290: * Send user a signal. ! 291: * If not a breakpoint, do console register dump. ! 292: */ ! 293: if (sigcode) { ! 294: if (sigcode != SIGTRAP) { ! 295: RDUMP(); ! 296: printf("sigcode=#%d User Trap\n", sigcode); ! 297: } ! 298: sendsig(sigcode, SELF); ! 299: } ! 300: } ! 301: ! 302: /* ! 303: * trap_op() ! 304: * ! 305: * Look at the trapped instruction. ! 306: * If it's one of a select few, recognize and return the type. ! 307: * Otherwise, return 0. ! 308: * ! 309: * This could be fancier, but all we want to look for is: ! 310: * (for CRx and DRx, second operand is limited to %eax). ! 311: * 0F 20 C0 READ_CR0 ! 312: * 0F 22 C0 WRITE_CR0 ! 313: * 0F 20 D0 READ_CR2 ! 314: * 0F 20 D8 READ_CR3 ! 315: * 0F 22 D8 WRITE_CR3 ! 316: * CF IRET ! 317: * F4 HALT ! 318: * 0F 23 C0 WRITE_DR0 ! 319: * 0F 23 C8 WRITE_DR1 ! 320: * 0F 23 D0 WRITE_DR2 ! 321: * 0F 23 D8 WRITE_DR3 ! 322: * 0F 23 F0 WRITE_DR6 ! 323: * 0F 23 F8 WRITE_DR7 ! 324: * 0F 21 C0 READ_DR0 ! 325: * 0F 21 C8 READ_DR1 ! 326: * 0F 21 D0 READ_DR2 ! 327: * 0F 21 D8 READ_DR3 ! 328: * 0F 21 F0 READ_DR6 ! 329: * 0F 21 F8 READ_DR7 ! 330: */ ! 331: static int ! 332: trap_op(cs,eip) ! 333: unsigned int cs, eip; ! 334: { ! 335: int ret = 0; ! 336: ! 337: switch (selkcopy(cs,eip)) { ! 338: case 0x0F: ! 339: switch (selkcopy(cs,eip+1)) { ! 340: case 0x20: ! 341: switch (selkcopy(cs,eip+2)) { ! 342: case 0xC0: ! 343: ret = READ_CR0; ! 344: break; ! 345: case 0xD0: ! 346: ret = READ_CR2; ! 347: break; ! 348: case 0xD8: ! 349: ret = READ_CR3; ! 350: break; ! 351: } ! 352: break; ! 353: case 0x21: ! 354: switch (selkcopy(cs,eip+2)) { ! 355: case 0xC0: ! 356: ret = READ_DR0; ! 357: break; ! 358: case 0xC8: ! 359: ret = READ_DR1; ! 360: break; ! 361: case 0xD0: ! 362: ret = READ_DR2; ! 363: break; ! 364: case 0xD8: ! 365: ret = READ_DR3; ! 366: break; ! 367: case 0xF0: ! 368: ret = READ_DR6; ! 369: break; ! 370: case 0xF8: ! 371: ret = READ_DR7; ! 372: break; ! 373: } ! 374: break; ! 375: case 0x22: ! 376: switch (selkcopy(cs,eip+2)) { ! 377: case 0xC0: ! 378: ret = WRITE_CR0; ! 379: break; ! 380: case 0xD8: ! 381: ret = WRITE_CR3; ! 382: break; ! 383: } ! 384: break; ! 385: case 0x23: ! 386: switch (selkcopy(cs,eip+2)) { ! 387: case 0xC0: ! 388: ret = WRITE_DR0; ! 389: break; ! 390: case 0xC8: ! 391: ret = WRITE_DR1; ! 392: break; ! 393: case 0xD0: ! 394: ret = WRITE_DR2; ! 395: break; ! 396: case 0xD8: ! 397: ret = WRITE_DR3; ! 398: break; ! 399: case 0xF0: ! 400: ret = WRITE_DR6; ! 401: break; ! 402: case 0xF8: ! 403: ret = WRITE_DR7; ! 404: break; ! 405: } ! 406: break; ! 407: } ! 408: break; ! 409: case 0xF4: ! 410: ret = HALT; ! 411: break; ! 412: case 0xCF: ! 413: ret = IRET; ! 414: break; ! 415: } ! 416: return ret; ! 417: } ! 418: ! 419: /* ! 420: * Kernel debugger. ! 421: * ! 422: * Runs in ring 0. ! 423: */ ! 424: __debug_ker__(gs, fs, es, ds, edi, esi, ebp, esp, ebx, edx, ecx, eax, trapno, ! 425: err, eip, cs, efl, uesp, ss) ! 426: { ! 427: unsigned int dr6 = read_dr6(); ! 428: unsigned cpl = cs & SEG_PL; ! 429: int do_rdump = 1; ! 430: ! 431: if (dr6 & 0xf) { /* report breakpoint exception(s) */ ! 432: printf("Breakpoint "); ! 433: if (dr6 & 1) ! 434: printf("DR0=%x ", DR0); ! 435: if (dr6 & 2) ! 436: printf("DR1=%x ", DR1); ! 437: if (dr6 & 4) ! 438: printf("DR2=%x ", DR2); ! 439: if (dr6 & 8) ! 440: printf("DR3=%x ", DR3); ! 441: printf("DR7=%x\n", DR7); ! 442: } ! 443: if (dr6 & 0xf000) { /* report other debug exception(s) */ ! 444: if (dr6 & 0x8000) ! 445: printf("Switch to debugged task\n"); ! 446: if (dr6 & 0x4000) { ! 447: /* Single Step */ ! 448: switch(cpl) { ! 449: /* ! 450: * If user code trapped, send signal ! 451: * and suppress console register dump. ! 452: */ ! 453: case DPL_1: ! 454: /* ! 455: * Turn off single-stepping when entering ! 456: * Ring 1. ! 457: */ ! 458: if (eip == &syc32 || eip == &sig32) { ! 459: do_rdump = 0; ! 460: } else { ! 461: printf("/nefl=%x No single stepping the kernel.\n", efl); ! 462: SDUMP(uesp); ! 463: } ! 464: efl &= ~TRAP_FLAG; ! 465: break; ! 466: case DPL_3: ! 467: do_rdump = 0; ! 468: T_HAL(0x20000, printf("Kernel SSTEP eip=%x efl=%x ", eip, efl)); ! 469: sendsig(SIGTRAP, SELF); ! 470: break; ! 471: } ! 472: } ! 473: if (dr6 & 0x2000) { ! 474: printf("ICE in use\n"); ! 475: eip += 3; ! 476: } ! 477: } ! 478: if (do_rdump) { ! 479: RDUMP(); ! 480: } ! 481: write_dr6(0); ! 482: efl |= RESUME_FLAG; ! 483: return; ! 484: } ! 485: ! 486: /* ! 487: * General protection fault handler. ! 488: * Entered via a ring 0 gate. ! 489: */ ! 490: gpfault(gs, fs, es, ds, edi, esi, ebp, esp, ebx, edx, ecx, eax, trapno, err, ! 491: eip, cs, efl, uesp, ss) ! 492: char *eip; ! 493: { ! 494: unsigned cpl = cs & SEG_PL; ! 495: ! 496: /* ! 497: * Switch on CPL of code that trapped. ! 498: */ ! 499: switch(cpl) { ! 500: case DPL_0: ! 501: /* ! 502: * Ring 0 should not gp fault. ! 503: */ ! 504: RDUMP(); ! 505: T_HAL(0x1000, SDUMP(&uesp)); ! 506: T_HAL(0x1000, SDUMP(*((&uesp) + 2))); ! 507: panic("System GP Fault from Ring 0"); ! 508: break; ! 509: case DPL_1: ! 510: /* ! 511: * If ring 1 faulted on a valid request, emulate the ! 512: * request while running in ring 0. ! 513: */ ! 514: switch(trap_op(cs,eip)) { ! 515: case READ_CR0: ! 516: eax = read_cr0(); ! 517: eip += 3; ! 518: break; ! 519: #if 0 ! 520: case WRITE_CR0: ! 521: if (eax & 4) ! 522: setfpe(0); ! 523: else ! 524: setfpe(1); ! 525: eip += 3; ! 526: break; ! 527: #endif ! 528: case READ_CR2: ! 529: eax = read_cr2(); ! 530: eip += 3; ! 531: break; ! 532: case READ_CR3: ! 533: eax = read_cr3(); ! 534: eip += 3; ! 535: break; ! 536: #if 0 ! 537: case WRITE_CR3: ! 538: mmuupdnR0(); ! 539: eip += 3; ! 540: break; ! 541: #endif ! 542: case IRET: ! 543: /* ! 544: * Some CPU's wrongly generate GP faults on IRET ! 545: * from inner ring to ring 3. ! 546: * Fix is to retry the instruction a few times. ! 547: */ ! 548: if (!iret_flt) { ! 549: iret_flt = 1; ! 550: printf("CPU Bug: " ! 551: "Spurious GP Fault on Iret to Ring 3.\n"); ! 552: } ! 553: break; ! 554: case READ_DR0: ! 555: eax = read_dr0(); ! 556: eip += 3; ! 557: break; ! 558: case READ_DR1: ! 559: eax = read_dr1(); ! 560: eip += 3; ! 561: break; ! 562: case READ_DR2: ! 563: eax = read_dr2(); ! 564: eip += 3; ! 565: break; ! 566: case READ_DR3: ! 567: eax = read_dr3(); ! 568: eip += 3; ! 569: break; ! 570: case READ_DR6: ! 571: eax = read_dr6(); ! 572: eip += 3; ! 573: break; ! 574: case READ_DR7: ! 575: eax = read_dr7(); ! 576: eip += 3; ! 577: break; ! 578: case WRITE_DR0: ! 579: write_dr0(eax); ! 580: eip += 3; ! 581: break; ! 582: case WRITE_DR1: ! 583: write_dr1(eax); ! 584: eip += 3; ! 585: break; ! 586: case WRITE_DR2: ! 587: write_dr2(eax); ! 588: eip += 3; ! 589: break; ! 590: case WRITE_DR3: ! 591: write_dr3(eax); ! 592: eip += 3; ! 593: break; ! 594: case WRITE_DR6: ! 595: write_dr6(eax); ! 596: eip += 3; ! 597: break; ! 598: case WRITE_DR7: ! 599: write_dr7(eax); ! 600: eip += 3; ! 601: break; ! 602: #if 0 ! 603: case WRITE_DR7: ! 604: /* ! 605: * Expect breakpoint info in globals DR0-3,DR7. ! 606: */ ! 607: printf("Setting DR0=%x DR1=%x DR2=%x DR3=%x DR7=%x\n", ! 608: DR0, DR1, DR2, DR3, DR7); ! 609: write_dr0(DR0); ! 610: write_dr1(DR1); ! 611: write_dr2(DR2); ! 612: write_dr3(DR3); ! 613: write_dr7(DR7); ! 614: eip += 3; ! 615: break; ! 616: #endif ! 617: default: ! 618: if (eip >= &__xtrap_on__ && eip < &__xtrap_off__) { ! 619: SET_U_ERROR(EFAULT, "copy gp"); ! 620: eip = &__xtrap_break__; ! 621: } else { ! 622: RDUMP(); ! 623: T_HAL(0x1000, SDUMP(uesp)); ! 624: panic("System GP Fault from Ring 1"); ! 625: } ! 626: } ! 627: goto gpdone; ! 628: break; ! 629: case DPL_2: ! 630: /* ! 631: * Nothing should be running in Ring 2. ! 632: */ ! 633: case DPL_3: ! 634: /* ! 635: * Ring 3 gp fault means errant user process. ! 636: */ ! 637: RDUMP(); ! 638: printf("User GP Violation\n"); ! 639: sendsig(SIGSEGV, SELF); ! 640: break; ! 641: } ! 642: gpdone: ! 643: return; ! 644: } ! 645: ! 646: /* ! 647: * User debugger. ! 648: * ! 649: * Runs in ring 1. ! 650: */ ! 651: __debug_usr__(gs, fs, es, ds, edi, esi, ebp, esp, ebx, edx, ecx, eax, trapno, ! 652: err, eip, cs, efl, uesp, ss) ! 653: { ! 654: unsigned int dr6 = read_dr6(); ! 655: unsigned cpl = cs & SEG_PL; ! 656: int do_rdump = 1; ! 657: ! 658: if (dr6 & 0xf) { /* report breakpoint exception(s) */ ! 659: printf("Breakpoint "); ! 660: if (dr6 & 1) ! 661: printf("DR0=%x ", DR0); ! 662: if (dr6 & 2) ! 663: printf("DR1=%x ", DR1); ! 664: if (dr6 & 4) ! 665: printf("DR2=%x ", DR2); ! 666: if (dr6 & 8) ! 667: printf("DR3=%x ", DR3); ! 668: printf("DR7=%x\n", DR7); ! 669: } ! 670: if (dr6 & 0xf000) { /* report other debug exception(s) */ ! 671: if (dr6 & 0x8000) ! 672: printf("Switch to debugged task\n"); ! 673: if (dr6 & 0x4000) { ! 674: /* Single Step */ ! 675: switch(cpl) { ! 676: /* ! 677: * If user code trapped, send signal ! 678: * and suppress console register dump. ! 679: */ ! 680: case DPL_1: ! 681: /* ! 682: * Turn off single-stepping when entering ! 683: * Ring 1. ! 684: */ ! 685: if (eip == &syc32 || eip == &sig32) { ! 686: do_rdump = 0; ! 687: } else { ! 688: printf("/nefl=%x No single stepping the kernel.\n", efl); ! 689: SDUMP(uesp); ! 690: } ! 691: efl &= ~TRAP_FLAG; ! 692: break; ! 693: case DPL_3: ! 694: do_rdump = 0; ! 695: T_HAL(0x20000, printf("User SSTEP eip=%x efl=%x ", eip, efl)); ! 696: sendsig(SIGTRAP, SELF); ! 697: break; ! 698: } ! 699: } ! 700: if (dr6 & 0x2000) { ! 701: printf("ICE in use\n"); ! 702: eip += 3; ! 703: } ! 704: } ! 705: if (do_rdump) { ! 706: RDUMP(); ! 707: } ! 708: write_dr6(0); ! 709: efl |= RESUME_FLAG; ! 710: return; ! 711: } ! 712: ! 713: irqblab(gs, fs, es, ds, edi, esi, ebp, esp, ebx, edx, ecx, eax, trapno, ! 714: err, eip, cs, efl, uesp, ss) ! 715: { ! 716: puts("*ip="); ! 717: print32(eip); ! 718: puts(" *err="); ! 719: print32(err); ! 720: if ((err & 0xff) == 0x40) { ! 721: int irqno = (err >> 8) & 0xFF; ! 722: print8(irqno); ! 723: } else if (err == 2) { ! 724: puts("NMI "); ! 725: } ! 726: } ! 727: ! 728: pagefault(gs, fs, es, ds, edi, esi, ebp, esp, ebx, edx, ecx, eax, trapno, err, ! 729: eip, cs, efl, uesp, ss) ! 730: char *eip; ! 731: { ! 732: register struct systab *stp; ! 733: register int callnum; ! 734: register int sigcode; ! 735: extern int trapcode; ! 736: extern *mmdata[], mminit; ! 737: cseg_t *pp; ! 738: register SEG *segp; ! 739: int splo, datahi; ! 740: unsigned int txtlo, txthi; ! 741: unsigned char opcode; /* Opcode we trapped on. */ ! 742: unsigned short e_arg; /* Argument to 'enter' opcode. */ ! 743: unsigned long newsp; /* Anticipated value for stack pointer. */ ! 744: unsigned int cr2 = 0; ! 745: unsigned int cpl = cs & SEG_PL; ! 746: ! 747: /* ! 748: * Avoid sign extension confusion on 286 ds ! 749: */ ! 750: if (ds == (SEG_286_UD | R_USR)) ! 751: uesp = (unsigned short)uesp; ! 752: ! 753: /* ! 754: * Expect this to never happen! ! 755: */ ! 756: if (SELF->p_flags&PFKERN) { ! 757: panic("pid%d: kernel process trap: err=%x, ip=%x ax=%d", ! 758: SELF->p_pid, err, eip, eax); ! 759: } ! 760: ! 761: T_HAL(0x4000, printf("T%d ", err)); ! 762: sigcode = 0; ! 763: ! 764: u.u_regl = &gs; /* hook in register set for consave/conrest */ ! 765: ! 766: { ! 767: /* ! 768: * Page fault ! 769: */ ! 770: cr2 = read_cr2(); ! 771: if (cpl < 2) { ! 772: /* ! 773: * If page fault during Ring 1 copy service routine, ! 774: * such as kucopy or ukcopy, set u_error and abort ! 775: * the copy, but don't send signal to the user. ! 776: */ ! 777: if (eip >= &__xtrap_on__ && eip < &__xtrap_off__) { ! 778: T_HAL(0x1000, printf("copy trapped ")); ! 779: SET_U_ERROR(EFAULT, "copy service"); ! 780: eip = &__xtrap_break__; ! 781: goto pf_end; ! 782: } else { ! 783: printf("&uesp=>"); ! 784: SDUMP(&uesp); ! 785: #if 0 ! 786: printf("*(&uesp + 2)=>"); ! 787: SDUMP(*((&uesp) + 2)); ! 788: #endif ! 789: printf("cr2=%x", cr2); ! 790: RDUMP(); ! 791: panic("Kernel Page Fault"); ! 792: } ! 793: } ! 794: ! 795: /* Check for stack underflow. */ ! 796: ! 797: /* ! 798: * I think 'splo' is being calculated in a bass-ackwards way, ! 799: * and that 'datahi' is just wrong, but I'm not certain, ! 800: * so the fixes are #if 0'd out. -piggy ! 801: * ! 802: * I'll take out the 0 some day and test these changes. ! 803: */ ! 804: segp = u.u_segl[SISTACK].sr_segp; ! 805: #if 0 ! 806: splo = u.u_segl[SISTACK].sr_base - segp->s_size; ! 807: datahi = u.u_segl[SIPDATA].sr_base + u.u_segl[SIPDATA].sr_size; ! 808: #else ! 809: splo = (XMODE_286) ? ISP_286 : ISP_386; ! 810: splo -= segp->s_size; ! 811: datahi = u.u_segl[SIPDATA].sr_size; ! 812: #endif /* 0 */ ! 813: ! 814: /* ! 815: * Catch bad function pointer here - don't want to restart ! 816: * the user instruction and get runaway segv's. ! 817: * ! 818: * For 286 executables, eip starts at 0, but cs points to ! 819: * descriptor SEG_286_UII which adds 0x400000 (UII_BASE). ! 820: */ ! 821: txtlo = u.u_segl[SISTEXT].sr_base; ! 822: if (XMODE_286) ! 823: txtlo -= UII_BASE; ! 824: txthi = txtlo + u.u_segl[SISTEXT].sr_size; ! 825: if (eip < txtlo || eip > txthi) { ! 826: T_HAL(0x1000, printf("Bad eip, txtlo=%x txthi=%x\n", ! 827: txtlo, txthi)); ! 828: goto bad_pf; ! 829: } ! 830: ! 831: /* ! 832: * If we trapped on an 'enter' instruction, the stack ! 833: * pointer (uesp) has not yet been decremented. In ! 834: * order to correctly process such a stack overflow, ! 835: * we must look at the _expected_ value for uesp. ! 836: * NB: We COPY uesp, because that arg gets loaded back ! 837: * into the real esp--when we return from the trap the ! 838: * enter instruction will decrement the esp. ! 839: */ ! 840: newsp = uesp; ! 841: opcode = selkcopy(cs, eip); ! 842: if (ENTER_OP == opcode) { ! 843: e_arg = (selkcopy(cs, eip+2)<<8) + selkcopy(cs, eip+1); ! 844: newsp -= e_arg; ! 845: } ! 846: ! 847: if (cr2 <= splo ! 848: && newsp <= splo ! 849: && newsp > datahi ! 850: && btoc(datahi) < btocrd(splo)) { ! 851: pp = c_extend(segp->s_vmem, btoc(segp->s_size)); ! 852: if (pp==0) { ! 853: T_HAL(0x1000, printf("c_extend(%x,%x)=0 ", ! 854: segp->s_vmem, btoc(segp->s_size))); ! 855: goto bad_pf; ! 856: } ! 857: ! 858: segp->s_vmem = pp; ! 859: segp->s_size += NBPC; ! 860: if (sproto(0)==0) { ! 861: T_HAL(0x1000, printf("sproto(0)=0 ")); ! 862: goto bad_pf; ! 863: } ! 864: ! 865: segload(); ! 866: goto pf_end; ! 867: } ! 868: ! 869: /* ! 870: * Catch bad data pointer here - don't want to restart ! 871: * the user instruction and get runaway segv's. ! 872: */ ! 873: { ! 874: T_HAL(0x1000, printf("Bad data, splo=%x datahi=%x\n", ! 875: splo, datahi)); ! 876: } ! 877: ! 878: bad_pf: ! 879: /* ! 880: * User generated unacceptable page fault. ! 881: */ ! 882: sigcode = SIGSEGV; ! 883: printf("\ncr2=%x ", cr2); ! 884: } ! 885: ! 886: pf_end: ! 887: /* ! 888: * Send user a signal. ! 889: * If not a breakpoint, do console register dump. ! 890: */ ! 891: if (sigcode) { ! 892: RDUMP(); ! 893: printf("sigcode=#%d User Page Fault\n", sigcode); ! 894: sendsig(sigcode, SELF); ! 895: } ! 896: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.