Annotation of XNU/osfmk/i386/trap.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * The contents of this file constitute Original Code as defined in and
                      7:  * are subject to the Apple Public Source License Version 1.1 (the
                      8:  * "License").  You may not use this file except in compliance with the
                      9:  * License.  Please obtain a copy of the License at
                     10:  * http://www.apple.com/publicsource and read it before using this file.
                     11:  * 
                     12:  * This Original Code and all software distributed under the License are
                     13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     17:  * License for the specific language governing rights and limitations
                     18:  * under the License.
                     19:  * 
                     20:  * @APPLE_LICENSE_HEADER_END@
                     21:  */
                     22: /*
                     23:  * @OSF_COPYRIGHT@
                     24:  */
                     25: /* 
                     26:  * Mach Operating System
                     27:  * Copyright (c) 1991,1990,1989,1988 Carnegie Mellon University
                     28:  * All Rights Reserved.
                     29:  * 
                     30:  * Permission to use, copy, modify and distribute this software and its
                     31:  * documentation is hereby granted, provided that both the copyright
                     32:  * notice and this permission notice appear in all copies of the
                     33:  * software, derivative works or modified versions, and any portions
                     34:  * thereof, and that both notices appear in supporting documentation.
                     35:  * 
                     36:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
                     37:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
                     38:  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
                     39:  * 
                     40:  * Carnegie Mellon requests users of this software to return to
                     41:  * 
                     42:  *  Software Distribution Coordinator  or  [email protected]
                     43:  *  School of Computer Science
                     44:  *  Carnegie Mellon University
                     45:  *  Pittsburgh PA 15213-3890
                     46:  * 
                     47:  * any improvements or extensions that they make and grant Carnegie Mellon
                     48:  * the rights to redistribute these changes.
                     49:  */
                     50: /*
                     51:  */
                     52: /*
                     53:  * Hardware trap/fault handler.
                     54:  */
                     55: 
                     56: #include <cpus.h>
                     57: #include <fast_idle.h>
                     58: #include <mach_kdb.h>
                     59: #include <mach_kgdb.h>
                     60: #include <mach_kdp.h>
                     61: #include <mach_ldebug.h>
                     62: 
                     63: #include <types.h>
                     64: #include <i386/eflags.h>
                     65: #include <i386/trap.h>
                     66: #include <i386/pmap.h>
                     67: #include <i386/fpu.h>
                     68: 
                     69: #include <mach/exception.h>
                     70: #include <mach/kern_return.h>
                     71: #include <mach/vm_param.h>
                     72: #include <mach/i386/thread_status.h>
                     73: 
                     74: #include <vm/vm_kern.h>
                     75: #include <vm/vm_fault.h>
                     76: 
                     77: #include <kern/etap_macros.h>
                     78: #include <kern/kern_types.h>
                     79: #include <kern/ast.h>
                     80: #include <kern/thread.h>
                     81: #include <kern/task.h>
                     82: #include <kern/sched.h>
                     83: #include <kern/sched_prim.h>
                     84: #include <kern/exception.h>
                     85: #include <kern/spl.h>
                     86: #include <kern/misc_protos.h>
                     87: 
                     88: #if    MACH_KGDB
                     89: #include <kgdb/kgdb_defs.h>
                     90: #endif /* MACH_KGDB */
                     91: 
                     92: #include <i386/intel_read_fault.h>
                     93: 
                     94: #if     MACH_KGDB
                     95: #include <kgdb/kgdb_defs.h>
                     96: #endif  /* MACH_KGDB */
                     97: 
                     98: #if    MACH_KDB
                     99: #include <ddb/db_watch.h>
                    100: #include <ddb/db_run.h>
                    101: #include <ddb/db_break.h>
                    102: #include <ddb/db_trap.h>
                    103: #endif /* MACH_KDB */
                    104: 
                    105: #include <string.h>
                    106: 
                    107: #include <i386/io_emulate.h>
                    108: 
                    109: /*
                    110:  * Forward declarations
                    111:  */
                    112: extern void            user_page_fault_continue(
                    113:                                kern_return_t           kr);
                    114: 
                    115: extern boolean_t       v86_assist(
                    116:                                thread_t                thread,
                    117:                                struct i386_saved_state *regs);
                    118: 
                    119: extern boolean_t       check_io_fault(
                    120:                                struct i386_saved_state *regs);
                    121: 
                    122: extern int             inst_fetch(
                    123:                                int                     eip,
                    124:                                int                     cs);
                    125: 
                    126: #if    MACH_KDB
                    127: boolean_t      debug_all_traps_with_kdb = FALSE;
                    128: extern struct db_watchpoint *db_watchpoint_list;
                    129: extern boolean_t db_watchpoints_inserted;
                    130: extern boolean_t db_breakpoints_inserted;
                    131: 
                    132: void
                    133: thread_kdb_return(void)
                    134: {
                    135:        register thread_act_t   thr_act = current_act();
                    136:        register thread_t       cur_thr = current_thread();
                    137:        register struct i386_saved_state *regs = USER_REGS(thr_act);
                    138: 
                    139:        if (kdb_trap(regs->trapno, regs->err, regs)) {
                    140: #if            MACH_LDEBUG
                    141:                assert(cur_thr->mutex_count == 0); 
                    142: #endif         /* MACH_LDEBUG */
                    143:                check_simple_locks();
                    144:                thread_exception_return();
                    145:                /*NOTREACHED*/
                    146:        }
                    147: }
                    148: boolean_t let_ddb_vm_fault = FALSE;
                    149: 
                    150: #if    NCPUS > 1
                    151: extern int kdb_active[NCPUS];
                    152: #endif /* NCPUS > 1 */
                    153: 
                    154: #endif /* MACH_KDB */
                    155: 
                    156: void
                    157: user_page_fault_continue(
                    158:        kern_return_t   kr)
                    159: {
                    160:        register thread_act_t   thr_act = current_act();
                    161:        register thread_t       cur_thr = current_thread();
                    162:        register struct i386_saved_state *regs = USER_REGS(thr_act);
                    163: 
                    164:        if (kr == KERN_SUCCESS) {
                    165: #if    MACH_KDB
                    166:                if (!db_breakpoints_inserted) {
                    167:                        db_set_breakpoints();
                    168:                }
                    169:                if (db_watchpoint_list &&
                    170:                    db_watchpoints_inserted &&
                    171:                    (regs->err & T_PF_WRITE) &&
                    172:                    db_find_watchpoint(thr_act->map,
                    173:                                       (vm_offset_t)regs->cr2,
                    174:                                       regs))
                    175:                        kdb_trap(T_WATCHPOINT, 0, regs);
                    176: #endif /* MACH_KDB */
                    177:                thread_exception_return();
                    178:                /*NOTREACHED*/
                    179:        }
                    180: 
                    181: #if    MACH_KDB
                    182:        if (debug_all_traps_with_kdb &&
                    183:            kdb_trap(regs->trapno, regs->err, regs)) {
                    184: #if            MACH_LDEBUG
                    185:                assert(cur_thr->mutex_count == 0);
                    186: #endif         /* MACH_LDEBUG */
                    187:                check_simple_locks();
                    188:                thread_exception_return();
                    189:                /*NOTREACHED*/
                    190:        }
                    191: #endif /* MACH_KDB */
                    192: 
                    193:        i386_exception(EXC_BAD_ACCESS, kr, regs->cr2);
                    194:        /*NOTREACHED*/
                    195: }
                    196: 
                    197: /*
                    198:  * Fault recovery in copyin/copyout routines.
                    199:  */
                    200: struct recovery {
                    201:        int     fault_addr;
                    202:        int     recover_addr;
                    203: };
                    204: 
                    205: extern struct recovery recover_table[];
                    206: extern struct recovery recover_table_end[];
                    207: 
                    208: /*
                    209:  * Recovery from Successful fault in copyout does not
                    210:  * return directly - it retries the pte check, since
                    211:  * the 386 ignores write protection in kernel mode.
                    212:  */
                    213: extern struct recovery retry_table[];
                    214: extern struct recovery retry_table_end[];
                    215: 
                    216: char * trap_type[] = {TRAP_NAMES};
                    217: int    TRAP_TYPES = sizeof(trap_type)/sizeof(trap_type[0]);
                    218: 
                    219: /*
                    220:  * Trap from kernel mode.  Only page-fault errors are recoverable,
                    221:  * and then only in special circumstances.  All other errors are
                    222:  * fatal.  Return value indicates if trap was handled.
                    223:  */
                    224: boolean_t
                    225: kernel_trap(
                    226:        register struct i386_saved_state        *regs)
                    227: {
                    228:        int     exc;
                    229:        int     code;
                    230:        int     subcode;
                    231:        register int    type;
                    232:        vm_map_t        map;
                    233:        kern_return_t   result;
                    234:        register thread_t       thread;
                    235:        thread_act_t            thr_act;
                    236:        etap_data_t             probe_data;
                    237:        pt_entry_t              *pte;
                    238:        extern vm_offset_t      vm_last_phys;
                    239: 
                    240:        type = regs->trapno;
                    241:        code = regs->err;
                    242:        thread = current_thread();
                    243:        thr_act = current_act();
                    244: 
                    245:        ETAP_DATA_LOAD(probe_data[0], regs->trapno);
                    246:        ETAP_DATA_LOAD(probe_data[1], MACH_PORT_NULL);
                    247:        ETAP_DATA_LOAD(probe_data[2], MACH_PORT_NULL);
                    248:        ETAP_PROBE_DATA(ETAP_P_EXCEPTION,
                    249:                        0,
                    250:                        thread,
                    251:                        &probe_data,
                    252:                        ETAP_DATA_ENTRY*3);
                    253: 
                    254:        switch (type) {
                    255:            case T_PREEMPT:
                    256:                return (TRUE);
                    257: 
                    258:            case T_NO_FPU:
                    259:                fpnoextflt();
                    260:                return (TRUE);
                    261: 
                    262:            case T_FPU_FAULT:
                    263:                fpextovrflt();
                    264:                return (TRUE);
                    265: 
                    266:            case T_FLOATING_POINT_ERROR:
                    267:                fpexterrflt();
                    268:                return (TRUE);
                    269: 
                    270:            case T_PAGE_FAULT:
                    271:                /*
                    272:                 * If the current map is a submap of the kernel map,
                    273:                 * and the address is within that map, fault on that
                    274:                 * map.  If the same check is done in vm_fault
                    275:                 * (vm_map_lookup), we may deadlock on the kernel map
                    276:                 * lock.
                    277:                 */
                    278: #if    MACH_KDB
                    279:                mp_disable_preemption();
                    280:                if (db_active
                    281: #if    NCPUS > 1
                    282:                    && kdb_active[cpu_number()]
                    283: #endif /* NCPUS > 1 */
                    284:                    && !let_ddb_vm_fault) {
                    285:                        /*
                    286:                         * Force kdb to handle this one.
                    287:                         */
                    288:                        mp_enable_preemption();
                    289:                        return (FALSE);
                    290:                }
                    291:                mp_enable_preemption();
                    292: #endif /* MACH_KDB */
                    293:                subcode = regs->cr2;    /* get faulting address */
                    294: 
                    295:                if (subcode > LINEAR_KERNEL_ADDRESS) {
                    296:                    map = kernel_map;
                    297:                    subcode -= LINEAR_KERNEL_ADDRESS;
                    298:                } else if (thr_act == THR_ACT_NULL || thread == THREAD_NULL)
                    299:                    map = kernel_map;
                    300:                else {
                    301:                    map = thr_act->map;
                    302:                }
                    303: 
                    304: #if    MACH_KDB
                    305:                /*
                    306:                 * Check for watchpoint on kernel static data.
                    307:                 * vm_fault would fail in this case 
                    308:                 */
                    309:                if (map == kernel_map && 
                    310:                    db_watchpoint_list &&
                    311:                    db_watchpoints_inserted &&
                    312:                    (code & T_PF_WRITE) &&
                    313:                    (vm_offset_t)subcode < vm_last_phys &&
                    314:                    ((*(pte = pmap_pte(kernel_pmap, (vm_offset_t)subcode))) &
                    315:                     INTEL_PTE_WRITE) == 0) {
                    316:                        *pte = INTEL_PTE_VALID | INTEL_PTE_WRITE |
                    317:                               pa_to_pte(trunc_page((vm_offset_t)subcode) -
                    318:                                         VM_MIN_KERNEL_ADDRESS);
                    319:                        result = KERN_SUCCESS;
                    320:                } else
                    321: #endif /* MACH_KDB */
                    322:                {
                    323:                        /*
                    324:                         * Since the 386 ignores write protection in
                    325:                         * kernel mode, always try for write permission
                    326:                         * first.  If that fails and the fault was a
                    327:                         * read fault, retry with read permission.
                    328:                         */
                    329:                        result = vm_fault(map,
                    330:                                          trunc_page((vm_offset_t)subcode),
                    331:                                          VM_PROT_READ|VM_PROT_WRITE,
                    332:                                          FALSE);
                    333:                }
                    334: #if    MACH_KDB
                    335:                if (result == KERN_SUCCESS) {
                    336:                    /* Look for watchpoints */
                    337:                    if (db_watchpoint_list &&
                    338:                        db_watchpoints_inserted &&
                    339:                        (code & T_PF_WRITE) &&
                    340:                        db_find_watchpoint(map,
                    341:                                (vm_offset_t)subcode, regs))
                    342:                        kdb_trap(T_WATCHPOINT, 0, regs);
                    343:                }
                    344:                else
                    345: #endif /* MACH_KDB */
                    346:                if ((code & T_PF_WRITE) == 0 &&
                    347:                    result == KERN_PROTECTION_FAILURE)
                    348:                {
                    349:                    /*
                    350:                     *  Must expand vm_fault by hand,
                    351:                     *  so that we can ask for read-only access
                    352:                     *  but enter a (kernel)writable mapping.
                    353:                     */
                    354:                    result = intel_read_fault(map,
                    355:                                          trunc_page((vm_offset_t)subcode));
                    356:                }
                    357: 
                    358:                if (result == KERN_SUCCESS) {
                    359:                    /*
                    360:                     * Certain faults require that we back up
                    361:                     * the EIP.
                    362:                     */
                    363:                    register struct recovery *rp;
                    364: 
                    365:                    for (rp = retry_table; rp < retry_table_end; rp++) {
                    366:                        if (regs->eip == rp->fault_addr) {
                    367:                            regs->eip = rp->recover_addr;
                    368:                            break;
                    369:                        }
                    370:                    }
                    371:                    return (TRUE);
                    372:                }
                    373: 
                    374:                /* fall through */
                    375: 
                    376:            case T_GENERAL_PROTECTION:
                    377: 
                    378:                /*
                    379:                 * If there is a failure recovery address
                    380:                 * for this fault, go there.
                    381:                 */
                    382:                {
                    383:                    register struct recovery *rp;
                    384: 
                    385:                    for (rp = recover_table;
                    386:                         rp < recover_table_end;
                    387:                         rp++) {
                    388:                        if (regs->eip == rp->fault_addr) {
                    389:                            regs->eip = rp->recover_addr;
                    390:                            return (TRUE);
                    391:                        }
                    392:                    }
                    393:                }
                    394: 
                    395:                /*
                    396:                 * Check thread recovery address also -
                    397:                 * v86 assist uses it.
                    398:                 */
                    399:                if (thread->recover) {
                    400:                    regs->eip = thread->recover;
                    401:                    thread->recover = 0;
                    402:                    return (TRUE);
                    403:                }
                    404: 
                    405:                /*
                    406:                 * Unanticipated page-fault errors in kernel
                    407:                 * should not happen.
                    408:                 */
                    409:                /* fall through... */
                    410: 
                    411:            default:
                    412:                /*
                    413:                 * ...and return failure, so that locore can call into
                    414:                 * debugger.
                    415:                 */
                    416: #if  MACH_KDP
                    417:                kdp_i386_trap(type, regs, result, regs->cr2);
                    418: #endif
                    419:                return (FALSE);
                    420:        }
                    421:        return (TRUE);
                    422: }
                    423: 
                    424: /*
                    425:  * Called if both kernel_trap() and kdb_trap() fail.
                    426:  */
                    427: void
                    428: panic_trap(
                    429:        register struct i386_saved_state        *regs)
                    430: {
                    431:        int             code;
                    432:        register int    type;
                    433: 
                    434:        type = regs->trapno;
                    435:        code = regs->err;
                    436: 
                    437:        printf("trap type %d, code = %x, pc = %x\n",
                    438:                type, code, regs->eip);
                    439:        panic("trap");
                    440: }
                    441: 
                    442: 
                    443: /*
                    444:  *     Trap from user mode.
                    445:  */
                    446: void
                    447: user_trap(
                    448:        register struct i386_saved_state        *regs)
                    449: {
                    450:        int             exc;
                    451:        int             code;
                    452:        int             subcode;
                    453:        register int    type;
                    454:        vm_map_t        map;
                    455:        vm_prot_t       prot;
                    456:        kern_return_t   result;
                    457:        register thread_act_t thr_act = current_act();
                    458:        thread_t thread = (thr_act ? thr_act->thread : THREAD_NULL);
                    459:        boolean_t       kernel_act = thr_act->kernel_loaded;
                    460:        etap_data_t     probe_data;
                    461: 
                    462:        if (regs->efl & EFL_VM) {
                    463:            /*
                    464:             * If hardware assist can handle exception,
                    465:             * continue execution.
                    466:             */
                    467:            if (v86_assist(thread, regs))
                    468:                return;
                    469:        }
                    470: 
                    471:        type = regs->trapno;
                    472:        code = 0;
                    473:        subcode = 0;
                    474: 
                    475:        switch (type) {
                    476: 
                    477:            case T_DIVIDE_ERROR:
                    478:                exc = EXC_ARITHMETIC;
                    479:                code = EXC_I386_DIV;
                    480:                break;
                    481: 
                    482:            case T_DEBUG:
                    483: #if MACH_KDP
                    484:        /* Trap to KDP */
                    485:                kdp_raise_exception(EXC_BREAKPOINT, EXC_I386_BPTFLT, 0, regs);
                    486: #endif
                    487: #if     MACH_KGDB
                    488:                if (kgdb_user_trap(regs)) {
                    489:                        return;
                    490:                }
                    491: #endif
                    492: #if    MACH_KDB
                    493:                if (db_in_single_step()) {
                    494:                    if (kdb_trap(type, regs->err, regs))
                    495:                        return;
                    496:                }
                    497: #endif
                    498:                exc = EXC_BREAKPOINT;
                    499:                code = EXC_I386_SGL;
                    500:                break;
                    501: 
                    502:            case T_INT3:
                    503: 
                    504: #if    MACH_KDP
                    505:                kdp_raise_exception(EXC_BREAKPOINT, EXC_I386_BPTFLT, 0, regs);
                    506: #endif
                    507: #if     MACH_KGDB
                    508:                if (kgdb_user_trap(regs)) {
                    509:                        return;
                    510:                 }
                    511: #endif
                    512: #if    MACH_KDB
                    513:            {
                    514:                thread_act_t    curact = current_act();
                    515: 
                    516:                if (db_find_breakpoint_here(
                    517:                        (curact && !curact->kernel_loaded)?
                    518:                                curact->task: TASK_NULL,
                    519:                        regs->eip - 1)) {
                    520:                    if (kdb_trap(type, regs->err, regs))
                    521:                        return;
                    522:                }
                    523:            }
                    524: #endif
                    525:                exc = EXC_BREAKPOINT;
                    526:                code = EXC_I386_BPT;
                    527:                break;
                    528: 
                    529:            case T_OVERFLOW:
                    530:                exc = EXC_ARITHMETIC;
                    531:                code = EXC_I386_INTO;
                    532:                break;
                    533: 
                    534:            case T_OUT_OF_BOUNDS:
                    535:                exc = EXC_SOFTWARE;
                    536:                code = EXC_I386_BOUND;
                    537:                break;
                    538: 
                    539:            case T_INVALID_OPCODE:
                    540:                exc = EXC_BAD_INSTRUCTION;
                    541:                code = EXC_I386_INVOP;
                    542:                break;
                    543: 
                    544:            case T_NO_FPU:
                    545:            case 32:            /* XXX */
                    546:                fpnoextflt();
                    547:                return;
                    548: 
                    549:            case T_FPU_FAULT:
                    550:                fpextovrflt();
                    551:                return;
                    552: 
                    553:            case 10:            /* invalid TSS == iret with NT flag set */
                    554:                exc = EXC_BAD_INSTRUCTION;
                    555:                code = EXC_I386_INVTSSFLT;
                    556:                subcode = regs->err & 0xffff;
                    557:                break;
                    558: 
                    559:            case T_SEGMENT_NOT_PRESENT:
                    560:                exc = EXC_BAD_INSTRUCTION;
                    561:                code = EXC_I386_SEGNPFLT;
                    562:                subcode = regs->err & 0xffff;
                    563:                break;
                    564: 
                    565:            case T_STACK_FAULT:
                    566:                exc = EXC_BAD_INSTRUCTION;
                    567:                code = EXC_I386_STKFLT;
                    568:                subcode = regs->err & 0xffff;
                    569:                break;
                    570: 
                    571:            case T_GENERAL_PROTECTION:
                    572:                if (!(regs->efl & EFL_VM)) {
                    573:                    if (check_io_fault(regs))
                    574:                        return;
                    575:                }
                    576:                exc = EXC_BAD_INSTRUCTION;
                    577:                code = EXC_I386_GPFLT;
                    578:                subcode = regs->err & 0xffff;
                    579:                break;
                    580: 
                    581:            case T_PAGE_FAULT:
                    582:                subcode = regs->cr2;
                    583:                prot = VM_PROT_READ|VM_PROT_WRITE;
                    584:                if (kernel_act == FALSE) {
                    585:                        if (!(regs->err & T_PF_WRITE))
                    586:                                prot = VM_PROT_READ;
                    587:                        (void) user_page_fault_continue(vm_fault(thr_act->map,
                    588:                                trunc_page((vm_offset_t)subcode),
                    589:                                prot,
                    590:                                FALSE));
                    591:                        /* NOTREACHED */
                    592:                }
                    593:                else {
                    594:                        if (subcode > LINEAR_KERNEL_ADDRESS) {
                    595:                                map = kernel_map;
                    596:                                subcode -= LINEAR_KERNEL_ADDRESS;
                    597:                        }
                    598:                        result = vm_fault(thr_act->map,
                    599:                                trunc_page((vm_offset_t)subcode),
                    600:                                prot,
                    601:                                FALSE);
                    602:                        if (result != KERN_SUCCESS) {
                    603:                                /*
                    604:                                 * Must expand vm_fault by hand,
                    605:                                 * so that we can ask for read-only access
                    606:                                 * but enter a (kernel) writable mapping.
                    607:                                 */
                    608:                                result = intel_read_fault(thr_act->map,
                    609:                                        trunc_page((vm_offset_t)subcode));
                    610:                        }
                    611:                        user_page_fault_continue(result);
                    612:                        /*NOTREACHED*/
                    613:                }
                    614:                break;
                    615: 
                    616:            case T_FLOATING_POINT_ERROR:
                    617:                fpexterrflt();
                    618:                return;
                    619: 
                    620:            default:
                    621: #if     MACH_KGDB
                    622:                Debugger("Unanticipated user trap");
                    623:                return;
                    624: #endif  /* MACH_KGDB */
                    625: #if    MACH_KDB
                    626:                if (kdb_trap(type, regs->err, regs))
                    627:                    return;
                    628: #endif /* MACH_KDB */
                    629:                printf("user trap type %d, code = %x, pc = %x\n",
                    630:                       type, regs->err, regs->eip);
                    631:                panic("user trap");
                    632:                return;
                    633:        }
                    634: 
                    635: #if    MACH_KDB
                    636:        if (debug_all_traps_with_kdb &&
                    637:            kdb_trap(type, regs->err, regs))
                    638:                return;
                    639: #endif /* MACH_KDB */
                    640: 
                    641: #if    ETAP_EVENT_MONITOR
                    642:        if (thread != THREAD_NULL) {
                    643:                ETAP_DATA_LOAD(probe_data[0], regs->trapno);
                    644:                ETAP_DATA_LOAD(probe_data[1],
                    645:                               thr_act->exc_actions[exc].port);
                    646:                ETAP_DATA_LOAD(probe_data[2],
                    647:                               thr_act->task->exc_actions[exc].port);
                    648:                ETAP_PROBE_DATA(ETAP_P_EXCEPTION,
                    649:                                0,
                    650:                                thread,         
                    651:                                &probe_data,
                    652:                                ETAP_DATA_ENTRY*3);
                    653:        }
                    654: #endif /* ETAP_EVENT_MONITOR */
                    655: 
                    656:        i386_exception(exc, code, subcode);
                    657:        /*NOTREACHED*/
                    658: }
                    659: 
                    660: /*
                    661:  *     V86 mode assist for interrupt handling.
                    662:  */
                    663: boolean_t v86_assist_on = TRUE;
                    664: boolean_t v86_unsafe_ok = FALSE;
                    665: boolean_t v86_do_sti_cli = TRUE;
                    666: boolean_t v86_do_sti_immediate = FALSE;
                    667: 
                    668: #define        V86_IRET_PENDING 0x4000
                    669: 
                    670: int cli_count = 0;
                    671: int sti_count = 0;
                    672: 
                    673: boolean_t
                    674: v86_assist(
                    675:        thread_t                                thread,
                    676:        register struct i386_saved_state        *regs)
                    677: {
                    678:        register struct v86_assist_state *v86 = &thread->top_act->mact.pcb->ims.v86s;
                    679: 
                    680: /*
                    681:  * Build an 8086 address.  Use only when off is known to be 16 bits.
                    682:  */
                    683: #define        Addr8086(seg,off)       ((((seg) & 0xffff) << 4) + (off))
                    684: 
                    685: #define        EFL_V86_SAFE            (  EFL_OF | EFL_DF | EFL_TF \
                    686:                                 | EFL_SF | EFL_ZF | EFL_AF \
                    687:                                 | EFL_PF | EFL_CF )
                    688:        struct iret_32 {
                    689:                int             eip;
                    690:                int             cs;
                    691:                int             eflags;
                    692:        };
                    693:        struct iret_16 {
                    694:                unsigned short  ip;
                    695:                unsigned short  cs;
                    696:                unsigned short  flags;
                    697:        };
                    698:        union iret_struct {
                    699:                struct iret_32  iret_32;
                    700:                struct iret_16  iret_16;
                    701:        };
                    702: 
                    703:        struct int_vec {
                    704:                unsigned short  ip;
                    705:                unsigned short  cs;
                    706:        };
                    707: 
                    708:        if (!v86_assist_on)
                    709:            return FALSE;
                    710: 
                    711:        /*
                    712:         * If delayed STI pending, enable interrupts.
                    713:         * Turn off tracing if on only to delay STI.
                    714:         */
                    715:        if (v86->flags & V86_IF_PENDING) {
                    716:            v86->flags &= ~V86_IF_PENDING;
                    717:            v86->flags |=  EFL_IF;
                    718:            if ((v86->flags & EFL_TF) == 0)
                    719:                regs->efl &= ~EFL_TF;
                    720:        }
                    721: 
                    722:        if (regs->trapno == T_DEBUG) {
                    723: 
                    724:            if (v86->flags & EFL_TF) {
                    725:                /*
                    726:                 * Trace flag was also set - it has priority
                    727:                 */
                    728:                return FALSE;                   /* handle as single-step */
                    729:            }
                    730:            /*
                    731:             * Fall through to check for interrupts.
                    732:             */
                    733:        }
                    734:        else if (regs->trapno == T_GENERAL_PROTECTION) {
                    735:            /*
                    736:             * General protection error - must be an 8086 instruction
                    737:             * to emulate.
                    738:             */
                    739:            register int        eip;
                    740:            boolean_t   addr_32 = FALSE;
                    741:            boolean_t   data_32 = FALSE;
                    742:            int         io_port;
                    743: 
                    744:            /*
                    745:             * Set up error handler for bad instruction/data
                    746:             * fetches.
                    747:             */
                    748:            __asm__("movl $(addr_error), %0" : : "m" (thread->recover));
                    749: 
                    750:            eip = regs->eip;
                    751:            while (TRUE) {
                    752:                unsigned char   opcode;
                    753: 
                    754:                if (eip > 0xFFFF) {
                    755:                    thread->recover = 0;
                    756:                    return FALSE;       /* GP fault: IP out of range */
                    757:                }
                    758: 
                    759:                opcode = *(unsigned char *)Addr8086(regs->cs,eip);
                    760:                eip++;
                    761:                switch (opcode) {
                    762:                    case 0xf0:          /* lock */
                    763:                    case 0xf2:          /* repne */
                    764:                    case 0xf3:          /* repe */
                    765:                    case 0x2e:          /* cs */
                    766:                    case 0x36:          /* ss */
                    767:                    case 0x3e:          /* ds */
                    768:                    case 0x26:          /* es */
                    769:                    case 0x64:          /* fs */
                    770:                    case 0x65:          /* gs */
                    771:                        /* ignore prefix */
                    772:                        continue;
                    773: 
                    774:                    case 0x66:          /* data size */
                    775:                        data_32 = TRUE;
                    776:                        continue;
                    777: 
                    778:                    case 0x67:          /* address size */
                    779:                        addr_32 = TRUE;
                    780:                        continue;
                    781: 
                    782:                    case 0xe4:          /* inb imm */
                    783:                    case 0xe5:          /* inw imm */
                    784:                    case 0xe6:          /* outb imm */
                    785:                    case 0xe7:          /* outw imm */
                    786:                        io_port = *(unsigned char *)Addr8086(regs->cs, eip);
                    787:                        eip++;
                    788:                        goto do_in_out;
                    789: 
                    790:                    case 0xec:          /* inb dx */
                    791:                    case 0xed:          /* inw dx */
                    792:                    case 0xee:          /* outb dx */
                    793:                    case 0xef:          /* outw dx */
                    794:                    case 0x6c:          /* insb */
                    795:                    case 0x6d:          /* insw */
                    796:                    case 0x6e:          /* outsb */
                    797:                    case 0x6f:          /* outsw */
                    798:                        io_port = regs->edx & 0xffff;
                    799: 
                    800:                    do_in_out:
                    801:                        if (!data_32)
                    802:                            opcode |= 0x6600;   /* word IO */
                    803: 
                    804:                        switch (emulate_io(regs, opcode, io_port)) {
                    805:                            case EM_IO_DONE:
                    806:                                /* instruction executed */
                    807:                                break;
                    808:                            case EM_IO_RETRY:
                    809:                                /* port mapped, retry instruction */
                    810:                                thread->recover = 0;
                    811:                                return TRUE;
                    812:                            case EM_IO_ERROR:
                    813:                                /* port not mapped */
                    814:                                thread->recover = 0;
                    815:                                return FALSE;
                    816:                        }
                    817:                        break;
                    818: 
                    819:                    case 0xfa:          /* cli */
                    820:                        if (!v86_do_sti_cli) {
                    821:                            thread->recover = 0;
                    822:                            return (FALSE);
                    823:                        }
                    824: 
                    825:                        v86->flags &= ~EFL_IF;
                    826:                                        /* disable simulated interrupts */
                    827:                        cli_count++;
                    828:                        break;
                    829: 
                    830:                    case 0xfb:          /* sti */
                    831:                        if (!v86_do_sti_cli) {
                    832:                            thread->recover = 0;
                    833:                            return (FALSE);
                    834:                        }
                    835: 
                    836:                        if ((v86->flags & EFL_IF) == 0) {
                    837:                            if (v86_do_sti_immediate) {
                    838:                                    v86->flags |= EFL_IF;
                    839:                            } else {
                    840:                                    v86->flags |= V86_IF_PENDING;
                    841:                                    regs->efl |= EFL_TF;
                    842:                            }
                    843:                                        /* single step to set IF next inst. */
                    844:                        }
                    845:                        sti_count++;
                    846:                        break;
                    847: 
                    848:                    case 0x9c:          /* pushf */
                    849:                    {
                    850:                        int     flags;
                    851:                        vm_offset_t sp;
                    852:                        int     size;
                    853: 
                    854:                        flags = regs->efl;
                    855:                        if ((v86->flags & EFL_IF) == 0)
                    856:                            flags &= ~EFL_IF;
                    857: 
                    858:                        if ((v86->flags & EFL_TF) == 0)
                    859:                            flags &= ~EFL_TF;
                    860:                        else flags |= EFL_TF;
                    861: 
                    862:                        sp = regs->uesp;
                    863:                        if (!addr_32)
                    864:                            sp &= 0xffff;
                    865:                        else if (sp > 0xffff)
                    866:                            goto stack_error;
                    867:                        size = (data_32) ? 4 : 2;
                    868:                        if (sp < size)
                    869:                            goto stack_error;
                    870:                        sp -= size;
                    871:                        if (copyout((char *)&flags,
                    872:                                    (char *)Addr8086(regs->ss,sp),
                    873:                                    size))
                    874:                            goto addr_error;
                    875:                        if (addr_32)
                    876:                            regs->uesp = sp;
                    877:                        else
                    878:                            regs->uesp = (regs->uesp & 0xffff0000) | sp;
                    879:                        break;
                    880:                    }
                    881: 
                    882:                    case 0x9d:          /* popf */
                    883:                    {
                    884:                        vm_offset_t sp;
                    885:                        int     nflags;
                    886: 
                    887:                        sp = regs->uesp;
                    888:                        if (!addr_32)
                    889:                            sp &= 0xffff;
                    890:                        else if (sp > 0xffff)
                    891:                            goto stack_error;
                    892: 
                    893:                        if (data_32) {
                    894:                            if (sp > 0xffff - sizeof(int))
                    895:                                goto stack_error;
                    896:                            nflags = *(int *)Addr8086(regs->ss,sp);
                    897:                            sp += sizeof(int);
                    898:                        }
                    899:                        else {
                    900:                            if (sp > 0xffff - sizeof(short))
                    901:                                goto stack_error;
                    902:                            nflags = *(unsigned short *)
                    903:                                        Addr8086(regs->ss,sp);
                    904:                            sp += sizeof(short);
                    905:                        }
                    906:                        if (addr_32)
                    907:                            regs->uesp = sp;
                    908:                        else
                    909:                            regs->uesp = (regs->uesp & 0xffff0000) | sp;
                    910: 
                    911:                        if (v86->flags & V86_IRET_PENDING) {
                    912:                                v86->flags = nflags & (EFL_TF | EFL_IF);
                    913:                                v86->flags |= V86_IRET_PENDING;
                    914:                        } else {
                    915:                                v86->flags = nflags & (EFL_TF | EFL_IF);
                    916:                        }
                    917:                        regs->efl = (regs->efl & ~EFL_V86_SAFE)
                    918:                                     | (nflags & EFL_V86_SAFE);
                    919:                        break;
                    920:                    }
                    921:                    case 0xcf:          /* iret */
                    922:                    {
                    923:                        vm_offset_t sp;
                    924:                        int     nflags;
                    925:                        int     size;
                    926:                        union iret_struct iret_struct;
                    927: 
                    928:                        v86->flags &= ~V86_IRET_PENDING;
                    929:                        sp = regs->uesp;
                    930:                        if (!addr_32)
                    931:                            sp &= 0xffff;
                    932:                        else if (sp > 0xffff)
                    933:                            goto stack_error;
                    934: 
                    935:                        if (data_32) {
                    936:                            if (sp > 0xffff - sizeof(struct iret_32))
                    937:                                goto stack_error;
                    938:                            iret_struct.iret_32 =
                    939:                                *(struct iret_32 *) Addr8086(regs->ss,sp);
                    940:                            sp += sizeof(struct iret_32);
                    941:                        }
                    942:                        else {
                    943:                            if (sp > 0xffff - sizeof(struct iret_16))
                    944:                                goto stack_error;
                    945:                            iret_struct.iret_16 =
                    946:                                *(struct iret_16 *) Addr8086(regs->ss,sp);
                    947:                            sp += sizeof(struct iret_16);
                    948:                        }
                    949:                        if (addr_32)
                    950:                            regs->uesp = sp;
                    951:                        else
                    952:                            regs->uesp = (regs->uesp & 0xffff0000) | sp;
                    953: 
                    954:                        if (data_32) {
                    955:                            eip       = iret_struct.iret_32.eip;
                    956:                            regs->cs  = iret_struct.iret_32.cs & 0xffff;
                    957:                            nflags    = iret_struct.iret_32.eflags;
                    958:                        }
                    959:                        else {
                    960:                            eip       = iret_struct.iret_16.ip;
                    961:                            regs->cs  = iret_struct.iret_16.cs;
                    962:                            nflags    = iret_struct.iret_16.flags;
                    963:                        }
                    964: 
                    965:                        v86->flags = nflags & (EFL_TF | EFL_IF);
                    966:                        regs->efl = (regs->efl & ~EFL_V86_SAFE)
                    967:                                     | (nflags & EFL_V86_SAFE);
                    968:                        break;
                    969:                    }
                    970:                    default:
                    971:                        /*
                    972:                         * Instruction not emulated here.
                    973:                         */
                    974:                        thread->recover = 0;
                    975:                        return FALSE;
                    976:                }
                    977:                break;  /* exit from 'while TRUE' */
                    978:            }
                    979:            regs->eip = (regs->eip & 0xffff0000 | eip);
                    980:        }
                    981:        else {
                    982:            /*
                    983:             * Not a trap we handle.
                    984:             */
                    985:            thread->recover = 0;
                    986:            return FALSE;
                    987:        }
                    988: 
                    989:        if ((v86->flags & EFL_IF) && ((v86->flags & V86_IRET_PENDING)==0)) {
                    990: 
                    991:            struct v86_interrupt_table *int_table;
                    992:            int int_count;
                    993:            int vec;
                    994:            int i;
                    995: 
                    996:            int_table = (struct v86_interrupt_table *) v86->int_table;
                    997:            int_count = v86->int_count;
                    998: 
                    999:            vec = 0;
                   1000:            for (i = 0; i < int_count; int_table++, i++) {
                   1001:                if (!int_table->mask && int_table->count > 0) {
                   1002:                    int_table->count--;
                   1003:                    vec = int_table->vec;
                   1004:                    break;
                   1005:                }
                   1006:            }
                   1007:            if (vec != 0) {
                   1008:                /*
                   1009:                 * Take this interrupt
                   1010:                 */
                   1011:                vm_offset_t     sp;
                   1012:                struct iret_16 iret_16;
                   1013:                struct int_vec int_vec;
                   1014: 
                   1015:                sp = regs->uesp & 0xffff;
                   1016:                if (sp < sizeof(struct iret_16))
                   1017:                    goto stack_error;
                   1018:                sp -= sizeof(struct iret_16);
                   1019:                iret_16.ip = regs->eip;
                   1020:                iret_16.cs = regs->cs;
                   1021:                iret_16.flags = regs->efl & 0xFFFF;
                   1022:                if ((v86->flags & EFL_TF) == 0)
                   1023:                    iret_16.flags &= ~EFL_TF;
                   1024:                else iret_16.flags |= EFL_TF;
                   1025: 
                   1026:                (void) memcpy((char *) &int_vec, 
                   1027:                              (char *) (sizeof(struct int_vec) * vec),
                   1028:                              sizeof (struct int_vec));
                   1029:                if (copyout((char *)&iret_16,
                   1030:                            (char *)Addr8086(regs->ss,sp),
                   1031:                            sizeof(struct iret_16)))
                   1032:                    goto addr_error;
                   1033:                regs->uesp = (regs->uesp & 0xFFFF0000) | (sp & 0xffff);
                   1034:                regs->eip = int_vec.ip;
                   1035:                regs->cs  = int_vec.cs;
                   1036:                regs->efl  &= ~EFL_TF;
                   1037:                v86->flags &= ~(EFL_IF | EFL_TF);
                   1038:                v86->flags |= V86_IRET_PENDING;
                   1039:            }
                   1040:        }
                   1041: 
                   1042:        thread->recover = 0;
                   1043:        return TRUE;
                   1044: 
                   1045:        /*
                   1046:         *      On address error, report a page fault.
                   1047:         *      XXX report GP fault - we don`t save
                   1048:         *      the faulting address.
                   1049:         */
                   1050:     addr_error:
                   1051:        __asm__("addr_error:;");
                   1052:        thread->recover = 0;
                   1053:        return FALSE;
                   1054: 
                   1055:        /*
                   1056:         *      On stack address error, return stack fault (12).
                   1057:         */
                   1058:     stack_error:
                   1059:        thread->recover = 0;
                   1060:        regs->trapno = T_STACK_FAULT;
                   1061:        return FALSE;
                   1062: }
                   1063: 
                   1064: /*
                   1065:  * Handle AST traps for i386.
                   1066:  * Check for delayed floating-point exception from
                   1067:  * AT-bus machines.
                   1068:  */
                   1069: 
                   1070: extern void     log_thread_action (thread_t, char *);
                   1071: 
                   1072: void
                   1073: i386_astintr(int preemption)
                   1074: {
                   1075:        int             mycpu;
                   1076:        ast_t           mask = AST_ALL;
                   1077:        spl_t           s;
                   1078:        thread_t        self = current_thread();
                   1079: 
                   1080:        s = splsched();         /* block interrupts to check reasons */
                   1081:        mp_disable_preemption();
                   1082:        mycpu = cpu_number();
                   1083:        if (need_ast[mycpu] & AST_I386_FP) {
                   1084:            /*
                   1085:             * AST was for delayed floating-point exception -
                   1086:             * FP interrupt occured while in kernel.
                   1087:             * Turn off this AST reason and handle the FPU error.
                   1088:             */
                   1089: 
                   1090:            ast_off(AST_I386_FP);
                   1091:            mp_enable_preemption();
                   1092:            splx(s);
                   1093: 
                   1094:            fpexterrflt();
                   1095:        }
                   1096:        else {
                   1097:            /*
                   1098:             * Not an FPU trap.  Handle the AST.
                   1099:             * Interrupts are still blocked.
                   1100:             */
                   1101: 
                   1102:            if (preemption) {
                   1103: 
                   1104:            /*
                   1105:             * We don't want to process any AST if we were in
                   1106:             * kernel-mode and the current thread is in any
                   1107:             * funny state (waiting and/or suspended).
                   1108:             */
                   1109: 
                   1110:                thread_lock (self);
                   1111: 
                   1112:                if (thread_not_preemptable(self) || self->preempt) {
                   1113:                        ast_off(AST_URGENT);
                   1114:                        thread_unlock (self);
                   1115:                        mp_enable_preemption();
                   1116:                        splx(s);
                   1117:                        return;
                   1118:                }
                   1119:                else mask = AST_PREEMPT;
                   1120:                mp_enable_preemption();
                   1121: 
                   1122: /*
                   1123:                self->preempt = TH_NOT_PREEMPTABLE;
                   1124: */
                   1125: 
                   1126:                thread_unlock (self);
                   1127:            } else {
                   1128:                mp_enable_preemption();
                   1129:            }
                   1130: 
                   1131:            ast_taken(preemption, mask, s
                   1132: #if    FAST_IDLE
                   1133:                      ,NO_IDLE_THREAD
                   1134: #endif /* FAST_IDLE */
                   1135:                      );
                   1136: /*
                   1137:            self->preempt = TH_PREEMPTABLE;
                   1138: */
                   1139:        }
                   1140: }
                   1141: 
                   1142: /*
                   1143:  * Handle exceptions for i386.
                   1144:  *
                   1145:  * If we are an AT bus machine, we must turn off the AST for a
                   1146:  * delayed floating-point exception.
                   1147:  *
                   1148:  * If we are providing floating-point emulation, we may have
                   1149:  * to retrieve the real register values from the floating point
                   1150:  * emulator.
                   1151:  */
                   1152: void
                   1153: i386_exception(
                   1154:        int     exc,
                   1155:        int     code,
                   1156:        int     subcode)
                   1157: {
                   1158:        spl_t                   s;
                   1159:        exception_data_type_t   codes[EXCEPTION_CODE_MAX];
                   1160: 
                   1161:        /*
                   1162:         * Turn off delayed FPU error handling.
                   1163:         */
                   1164:        s = splsched();
                   1165:        mp_disable_preemption();
                   1166:        ast_off(AST_I386_FP);
                   1167:        mp_enable_preemption();
                   1168:        splx(s);
                   1169: 
                   1170:        codes[0] = code;                /* new exception interface */
                   1171:        codes[1] = subcode;
                   1172:        exception(exc, codes, 2);
                   1173:        /*NOTREACHED*/
                   1174: }
                   1175: 
                   1176: boolean_t
                   1177: check_io_fault(
                   1178:        struct i386_saved_state         *regs)
                   1179: {
                   1180:        int             eip, opcode, io_port;
                   1181:        boolean_t       data_16 = FALSE;
                   1182: 
                   1183:        /*
                   1184:         * Get the instruction.
                   1185:         */
                   1186:        eip = regs->eip;
                   1187: 
                   1188:        for (;;) {
                   1189:            opcode = inst_fetch(eip, regs->cs);
                   1190:            eip++;
                   1191:            switch (opcode) {
                   1192:                case 0x66:      /* data-size prefix */
                   1193:                    data_16 = TRUE;
                   1194:                    continue;
                   1195: 
                   1196:                case 0xf3:      /* rep prefix */
                   1197:                case 0x26:      /* es */
                   1198:                case 0x2e:      /* cs */
                   1199:                case 0x36:      /* ss */
                   1200:                case 0x3e:      /* ds */
                   1201:                case 0x64:      /* fs */
                   1202:                case 0x65:      /* gs */
                   1203:                    continue;
                   1204: 
                   1205:                case 0xE4:      /* inb imm */
                   1206:                case 0xE5:      /* inl imm */
                   1207:                case 0xE6:      /* outb imm */
                   1208:                case 0xE7:      /* outl imm */
                   1209:                    /* port is immediate byte */
                   1210:                    io_port = inst_fetch(eip, regs->cs);
                   1211:                    eip++;
                   1212:                    break;
                   1213: 
                   1214:                case 0xEC:      /* inb dx */
                   1215:                case 0xED:      /* inl dx */
                   1216:                case 0xEE:      /* outb dx */
                   1217:                case 0xEF:      /* outl dx */
                   1218:                case 0x6C:      /* insb */
                   1219:                case 0x6D:      /* insl */
                   1220:                case 0x6E:      /* outsb */
                   1221:                case 0x6F:      /* outsl */
                   1222:                    /* port is in DX register */
                   1223:                    io_port = regs->edx & 0xFFFF;
                   1224:                    break;
                   1225: 
                   1226:                default:
                   1227:                    return FALSE;
                   1228:            }
                   1229:            break;
                   1230:        }
                   1231: 
                   1232:        if (data_16)
                   1233:            opcode |= 0x6600;           /* word IO */
                   1234: 
                   1235:        switch (emulate_io(regs, opcode, io_port)) {
                   1236:            case EM_IO_DONE:
                   1237:                /* instruction executed */
                   1238:                regs->eip = eip;
                   1239:                return TRUE;
                   1240: 
                   1241:            case EM_IO_RETRY:
                   1242:                /* port mapped, retry instruction */
                   1243:                return TRUE;
                   1244: 
                   1245:            case EM_IO_ERROR:
                   1246:                /* port not mapped */
                   1247:                return FALSE;
                   1248:        }
                   1249:        return FALSE;
                   1250: }
                   1251: 
                   1252: void
                   1253: kernel_preempt_check (void)
                   1254: {
                   1255:        mp_disable_preemption();
                   1256:         if ((need_ast[cpu_number()] & AST_URGENT) &&
                   1257: #if    NCPUS > 1
                   1258:            get_interrupt_level() == 1
                   1259: #else  /* NCPUS > 1 */
                   1260:            get_interrupt_level() == 0
                   1261: #endif /* NCPUS > 1 */
                   1262:            ) {
                   1263:                mp_enable_preemption_no_check();
                   1264:                 __asm__ volatile ("     int     $0xff");
                   1265:         } else {
                   1266:                mp_enable_preemption_no_check();
                   1267:        }
                   1268: }
                   1269: 
                   1270: #if    MACH_KDB
                   1271: 
                   1272: extern void    db_i386_state(struct i386_saved_state *regs);
                   1273: 
                   1274: #include <ddb/db_output.h>
                   1275: 
                   1276: void 
                   1277: db_i386_state(
                   1278:        struct i386_saved_state *regs)
                   1279: {
                   1280:        db_printf("eip  %8x\n", regs->eip);
                   1281:        db_printf("trap %8x\n", regs->trapno);
                   1282:        db_printf("err  %8x\n", regs->err);
                   1283:        db_printf("efl  %8x\n", regs->efl);
                   1284:        db_printf("ebp  %8x\n", regs->ebp);
                   1285:        db_printf("esp  %8x\n", regs->esp);
                   1286:        db_printf("uesp %8x\n", regs->uesp);
                   1287:        db_printf("cs   %8x\n", regs->cs & 0xff);
                   1288:        db_printf("ds   %8x\n", regs->ds & 0xff);
                   1289:        db_printf("es   %8x\n", regs->es & 0xff);
                   1290:        db_printf("fs   %8x\n", regs->fs & 0xff);
                   1291:        db_printf("gs   %8x\n", regs->gs & 0xff);
                   1292:        db_printf("ss   %8x\n", regs->ss & 0xff);
                   1293:        db_printf("eax  %8x\n", regs->eax);
                   1294:        db_printf("ebx  %8x\n", regs->ebx);
                   1295:        db_printf("ecx  %8x\n", regs->ecx);
                   1296:        db_printf("edx  %8x\n", regs->edx);
                   1297:        db_printf("esi  %8x\n", regs->esi);
                   1298:        db_printf("edi  %8x\n", regs->edi);
                   1299: }
                   1300: 
                   1301: #endif /* MACH_KDB */

unix.superglobalmegacorp.com

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