Annotation of coherent/b/STREAMS/i386/trap.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.