Annotation of XNU/osfmk/i386/trap.c, revision 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.