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