Annotation of kernel/machdep/i386/trap.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
                      7:  * Reserved.  This file contains Original Code and/or Modifications of
                      8:  * Original Code as defined in and that are subject to the Apple Public
                      9:  * Source License Version 1.1 (the "License").  You may not use this file
                     10:  * except in compliance with the License.  Please obtain a copy of the
                     11:  * License at http://www.apple.com/publicsource and read it before using
                     12:  * this file.
                     13:  * 
                     14:  * The Original Code and all software distributed under the License are
                     15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     19:  * License for the specific language governing rights and limitations
                     20:  * under the License.
                     21:  * 
                     22:  * @APPLE_LICENSE_HEADER_END@
                     23:  */
                     24: 
                     25: /*
                     26:  * Copyright (c) 1992 NeXT Computer, Inc.
                     27:  *
                     28:  * Intel386 Family:    Trap handlers.
                     29:  *
                     30:  * HISTORY
                     31:  *
                     32:  * 13 April 1992 ? at NeXT
                     33:  *     Created.
                     34:  */
                     35:  
                     36: #import <gdb.h>
                     37: 
                     38: #import <mach/mach_types.h>
                     39: #import <mach/exception.h>
                     40: 
                     41: #import <kern/syscall_sw.h>
                     42: #import <kern/kdp.h>
                     43: 
                     44: #import <vm/vm_kern.h>
                     45: 
                     46: #import <machdep/i386/trap.h>
                     47: #import <machdep/i386/machdep_call.h>
                     48: #import <machdep/i386/cpu_inline.h>
                     49: #import <machdep/i386/fp_exported.h>
                     50: #import <machdep/i386/sel_inline.h>
                     51: #import <machdep/i386/err_inline.h>
                     52: 
                     53: #import <sys/kernel.h>
                     54: #import <sys/systm.h>
                     55: #import <sys/proc.h>
                     56: #import <sys/user.h>
                     57: #import <sys/syslog.h>
                     58: 
                     59: #define N_BACKTRACE            4       // number of backtrace frames to print
                     60: 
                     61: static
                     62: void
                     63: kernel_debug_trap(
                     64:        thread_saved_state_t    *saved_state
                     65: );
                     66: static
                     67: kern_return_t
                     68: kernel_pagefault(
                     69:        vm_offset_t             address,
                     70:        except_frame_t          *frame
                     71: );
                     72: static
                     73: boolean_t
                     74: kernel_try_recover(
                     75:        except_frame_t          *frame
                     76: );
                     77: static
                     78: void
                     79: kernel_recover_thread(
                     80:        thread_saved_state_t    *saved_state
                     81: );
                     82: 
                     83: void
                     84: _i386_backtrace(
                     85:        void                    *frame,
                     86:        int                     nframes
                     87: );
                     88: 
                     89: void
                     90: user_trap(
                     91:     thread_saved_state_t       *state
                     92: )
                     93: {
                     94:     except_frame_t             *frame = &state->frame;
                     95:     int                                trapno;
                     96:     thread_t                   thread;
                     97:     int                                _exception, code = 0, subcode = 0;
                     98:     vm_offset_t                        va;
                     99:     kern_return_t              result;
                    100:     int                                uerror;
                    101:     struct proc                        *p;
                    102:     struct timeval             syst;
                    103:     
                    104:     thread = current_thread();
                    105:     trapno = state->trapno;
                    106:     
                    107:     if (p = current_proc())
                    108:        syst = p->p_stats->p_ru.ru_stime;
                    109:     
                    110:     switch (trapno) {
                    111: 
                    112:     case T_ZERO_DIVIDE:
                    113:        _exception      = EXC_ARITHMETIC;
                    114:        code            = EXC_I386_ZERO_DIVIDE;
                    115:        break;
                    116:        
                    117:     case T_DEBUG:
                    118:        _exception      = EXC_BREAKPOINT;
                    119:        code            = EXC_I386_DEBUG;
                    120:        break;
                    121:        
                    122:     case T_BREAKPOINT:
                    123:        _exception      = EXC_BREAKPOINT;
                    124:        code            = EXC_I386_BREAKPOINT;
                    125:        break;
                    126:        
                    127:     case T_OVERFLOW:
                    128:        _exception      = EXC_SOFTWARE;
                    129:        code            = EXC_I386_OVERFLOW;
                    130:        break;
                    131:        
                    132:     case T_BOUNDS_CHECK:
                    133:        _exception      = EXC_SOFTWARE;
                    134:        code            = EXC_I386_BOUNDS_CHECK;
                    135:        break;
                    136:        
                    137:     case T_INVALID_OPCODE:
                    138:        _exception      = EXC_BAD_INSTRUCTION;
                    139:        code            = EXC_I386_INVALID_OPCODE;
                    140:        break;
                    141:        
                    142:     case T_NOEXTENSION:
                    143:        fp_noextension(state);
                    144:        goto out;
                    145:        
                    146:     case T_SEGMENT_NOTPRESENT:
                    147:        _exception      = EXC_BAD_INSTRUCTION;
                    148:        code            = EXC_I386_SEGMENT_NOTPRESENT;
                    149:        subcode         = err_to_error_code(frame->err);
                    150:        break;
                    151:        
                    152:     case T_STACK_EXCEPTION:
                    153:        _exception      = EXC_BAD_INSTRUCTION;
                    154:        code            = EXC_I386_STACK_EXCEPTION;
                    155:        subcode         = err_to_error_code(frame->err);
                    156:        break;
                    157:        
                    158:     case T_GENERAL_PROTECTION:
                    159:        _exception      = EXC_BAD_INSTRUCTION;
                    160:        code            = EXC_I386_GENERAL_PROTECTION;
                    161:        subcode         = err_to_error_code(frame->err);
                    162:        break;
                    163:        
                    164:     case T_PAGE_FAULT:
                    165:        va = cr2();
                    166:        result = vm_fault(thread->task->map, trunc_page(va),
                    167:                            frame->err.pgfault.wrtflt?
                    168:                                VM_PROT_READ | VM_PROT_WRITE:
                    169:                                VM_PROT_READ,
                    170:                            FALSE, 0);
                    171:        if (result == KERN_SUCCESS)
                    172:            goto out;
                    173: 
                    174:        _exception      = EXC_BAD_ACCESS;
                    175:        code            = result;
                    176:        subcode         = va;
                    177:        break;
                    178:     
                    179:     case T_EXTENSION_FAULT:
                    180:        fp_extension_fault(state);
                    181:        goto out;
                    182:        
                    183:     case T_ALIGNMENT_CHECK:
                    184:        _exception      = EXC_SOFTWARE;
                    185:        code            = EXC_I386_ALIGNMENT_CHECK;
                    186:        break;
                    187:        
                    188:     default:
                    189:        _exception      = EXC_BAD_INSTRUCTION;
                    190:        code            = trapno;
                    191:        break;
                    192:     }
                    193: 
                    194:     exception(_exception, code, subcode);
                    195:     /* NOTREACHED */
                    196:                            
                    197: out:
                    198:     if (p && (p->p_flag & P_PROFIL)) {
                    199:        int             ticks;
                    200:        struct timeval  *tv = &p->p_stats->p_ru.ru_stime;
                    201:                        
                    202:        ticks = ((tv->tv_sec - syst.tv_sec) * 1000 +
                    203:                    (tv->tv_usec - syst.tv_usec) / 1000) / (tick / 1000);
                    204:        if (ticks)
                    205:            addupc_task(p, frame->eip, ticks);
                    206:     }
                    207: 
                    208:     thread_exception_return();
                    209:     /* NOTREACHED */
                    210: }
                    211: 
                    212: void
                    213: kernel_trap(
                    214:     thread_saved_state_t       *state
                    215: )
                    216: {
                    217:     except_frame_t             *frame = &state->frame;
                    218:     int                                trapno;
                    219:     vm_offset_t                        va;
                    220:     int                                _exception, code = 0, subcode = 0;
                    221:     kern_return_t              result;
                    222:     int                                uerror;
                    223:     
                    224:     trapno = state->trapno;
                    225:     
                    226:     switch (trapno) {
                    227: 
                    228:     case T_NOEXTENSION:
                    229:        /* ignore exception */;
                    230:        return;
                    231:        
                    232:     case T_EXTENSION_FAULT:
                    233:        fp_kernel_extension_fault(state);
                    234:        return;
                    235:        
                    236:     case T_DEBUG:
                    237:     case T_BREAKPOINT:
                    238:        kernel_debug_trap(state);
                    239:        return;
                    240:        
                    241:     case T_PAGE_FAULT:
                    242:        va = cr2();
                    243:        
                    244:        if (va >= KERNEL_LINEAR_BASE)
                    245:            result = kernel_pagefault(va, frame);
                    246:        else
                    247:            result = vm_fault(current_task()->map, trunc_page(va),
                    248:                                frame->err.pgfault.wrtflt?
                    249:                                    VM_PROT_READ | VM_PROT_WRITE:
                    250:                                    VM_PROT_READ,
                    251:                                FALSE, 0);
                    252: 
                    253:        if (result == KERN_SUCCESS)
                    254:            return;
                    255:     
                    256:        if (kernel_try_recover(frame))
                    257:            return;
                    258:            
                    259:        if (va < KERNEL_LINEAR_BASE) {
                    260:            /*
                    261:             * This can happen on return to user mode
                    262:             * when a private thread LDT contains
                    263:             * unallocated virtual memory.  Send an
                    264:             * exception RPC, after carefully piecing
                    265:             * the thread state back together.
                    266:             */
                    267:            kernel_recover_thread(state);
                    268: 
                    269:            _exception          = EXC_BAD_ACCESS;
                    270:            code                = result;
                    271:            subcode             = va;
                    272:            exception_from_kernel(_exception, code, subcode);
                    273:            thread_exception_return();
                    274:            /* NOTREACHED */
                    275:        }
                    276:        break;
                    277:        
                    278:     case T_GENERAL_PROTECTION:
                    279:     case T_SEGMENT_NOTPRESENT:
                    280:     case T_STACK_EXCEPTION:
                    281:        if (frame->err.normal.tbl == ERR_LDT) {
                    282:            /*
                    283:             * This can happen on return to user mode
                    284:             * when one of the segment registers refers
                    285:             * to a descriptor that is invalid for some
                    286:             * reason or another.  Send an exception RPC,
                    287:             * after carefully piecing the thread state
                    288:             * back together.
                    289:             */
                    290:            kernel_recover_thread(state);
                    291: 
                    292:            _exception  = EXC_BAD_INSTRUCTION;
                    293:            code        = trapno;
                    294:            subcode     = err_to_error_code(frame->err);
                    295:            exception_from_kernel(_exception, code, subcode);
                    296:            thread_exception_return();
                    297:            /* NOTREACHED */
                    298:        }
                    299:        break;
                    300:        
                    301:     case T_INVALID_TSS:
                    302:        if ((frame->eflags & EFL_NT) != 0) {
                    303:            /*
                    304:             * This can happen on return to user mode
                    305:             * when a thread managed to set the NT flag
                    306:             * and then entered the kernel through a call
                    307:             * gate.  The fix is to redo the IRET, since
                    308:             * the NT flag cannot be set at this point (we
                    309:             * just came through a trap gate to get here).
                    310:             */
                    311:             kernel_recover_thread(state);
                    312:             thread_exception_return();
                    313:             /* NOTREACHED */
                    314:        }
                    315:        break;
                    316:     }
                    317:     
                    318:     if (kernel_try_recover(frame))
                    319:        return;   
                    320: 
                    321: #if    GDB
                    322:     DoSafeAlert("Kernel Trap", "", FALSE);
                    323:     printf("unexpected kernel trap %x eip %x\n", trapno, frame->eip);
                    324:     switch (trapno) {
                    325:     
                    326:     case T_ZERO_DIVIDE:
                    327:        _exception = EXC_ARITHMETIC;
                    328:        code = EXC_I386_ZERO_DIVIDE;
                    329:        break;
                    330:     
                    331:     case T_OVERFLOW:
                    332:        _exception = EXC_SOFTWARE;
                    333:        code = EXC_I386_OVERFLOW;
                    334:        break;
                    335:     
                    336:     case T_BOUNDS_CHECK:
                    337:        _exception = EXC_ARITHMETIC;
                    338:        code = EXC_I386_BOUNDS_CHECK;
                    339:        break;
                    340:     
                    341:     case T_INVALID_OPCODE:
                    342:        _exception = EXC_BAD_INSTRUCTION;
                    343:        code = EXC_I386_INVALID_OPCODE;
                    344:        break;
                    345:     
                    346:     case T_SEGMENT_NOTPRESENT:
                    347:        _exception = EXC_BAD_INSTRUCTION;
                    348:        code = EXC_I386_SEGMENT_NOTPRESENT;
                    349:        subcode = err_to_error_code(frame->err);
                    350:        break;
                    351:     
                    352:     case T_STACK_EXCEPTION:
                    353:        _exception = EXC_BAD_INSTRUCTION;
                    354:        code = EXC_I386_STACK_EXCEPTION;
                    355:        subcode = err_to_error_code(frame->err);
                    356:        break;
                    357:     
                    358:     case T_GENERAL_PROTECTION:
                    359:        _exception = EXC_BAD_INSTRUCTION;
                    360:        code = EXC_I386_GENERAL_PROTECTION;
                    361:        subcode = err_to_error_code(frame->err);
                    362:        break;
                    363:        
                    364:     case T_PAGE_FAULT:
                    365:        _exception = EXC_BAD_ACCESS;
                    366:        code = result;
                    367:        subcode = va;
                    368:        break;
                    369:     
                    370:     case T_ALIGNMENT_CHECK:
                    371:        _exception = EXC_SOFTWARE;
                    372:        code = EXC_I386_ALIGNMENT_CHECK;
                    373:        break;
                    374:        
                    375:     default:
                    376:        _exception = EXC_BAD_INSTRUCTION;
                    377:        code = trapno;
                    378:        break;
                    379:     }
                    380: 
                    381:     _i386_backtrace(state->regs.ebp, N_BACKTRACE);
                    382: 
                    383:     kdp_raise_exception(_exception, code, subcode, state);
                    384:     DoRestore();
                    385:     panic("continued after kernel trap");
                    386: #else
                    387:     printf("unexpected kernel trap %x eip %x\n", trapno, frame->eip);
                    388:     panic("kernel trap");
                    389: #endif
                    390: }
                    391: 
                    392: static
                    393: kern_return_t
                    394: kernel_pagefault(
                    395:     vm_offset_t                        va,
                    396:     except_frame_t             *frame
                    397: )
                    398: {
                    399:     thread_t                   thread = current_thread();
                    400:     vm_map_t                   map;
                    401:     kern_return_t              result;
                    402: 
                    403:     if (thread == THREAD_NULL)
                    404:        map = kernel_map;
                    405:     else {
                    406:        map = thread->task->map;
                    407:        if (vm_map_pmap(map) != kernel_pmap)
                    408:            map = kernel_map;
                    409:     }
                    410: 
                    411:     result = vm_fault(map, trunc_page(va - KERNEL_LINEAR_BASE),
                    412:                        frame->err.pgfault.wrtflt?
                    413:                            VM_PROT_READ | VM_PROT_WRITE:
                    414:                            VM_PROT_READ,
                    415:                        FALSE, 0);
                    416: 
                    417:     return (result);
                    418: }
                    419: 
                    420: static
                    421: void
                    422: kernel_debug_trap(
                    423:     thread_saved_state_t       *state
                    424: )
                    425: {
                    426:     except_frame_t             *frame = &state->frame;
                    427:     int                                code;
                    428:     dr6_t                      debug = (dr6_t) { 0 };
                    429:     extern void                        unix_syscall_(void),
                    430:                                mach_kernel_trap_(void),
                    431:                                machdep_call_(void);
                    432:     
                    433:     // Clear debug status
                    434:     set_dr6(debug);
                    435:     
                    436:     if (state->trapno == T_DEBUG) {
                    437:        if (    frame->eip == (unsigned int)unix_syscall_       ||
                    438:                frame->eip == (unsigned int)mach_kernel_trap_   ||
                    439:                frame->eip == (unsigned int)machdep_call_       ) {
                    440:            current_thread()->pcb->trace = TRUE;
                    441:            frame->eflags &= ~EFL_TF;
                    442:            return;
                    443:        }
                    444:        code = EXC_I386_DEBUG;
                    445:     }
                    446:     else
                    447:        code = EXC_I386_BREAKPOINT;
                    448: 
                    449: #if    GDB
                    450:     kdp_raise_exception(EXC_BREAKPOINT, code, 0, state);
                    451: #else
                    452:     panic("kernel debug trap");
                    453: #endif
                    454: }
                    455: 
                    456: static
                    457: boolean_t
                    458: kernel_try_recover(
                    459:     except_frame_t     *frame
                    460: )
                    461: {
                    462:     vm_offset_t                recover = current_thread()->recover;
                    463:                                
                    464:     if (recover != 0) {
                    465:         frame->eip = recover;
                    466:        frame->cs = KCS_SEL;
                    467:        frame->eflags &= ~EFL_DF;
                    468:     }
                    469:     else
                    470:        return (FALSE);
                    471:        
                    472:     current_thread()->recover = 0;
                    473:     
                    474:     return (TRUE);
                    475: }
                    476: 
                    477: static
                    478: void
                    479: kernel_recover_thread(
                    480:     thread_saved_state_t       *state
                    481: )
                    482: {
                    483:     thread_saved_state_t       *user_regs = USER_REGS(current_thread());
                    484:     vm_offset_t                        stack_ptr = (vm_offset_t)&state->frame.esp;
                    485: 
                    486:     user_regs->frame.err = state->frame.err;
                    487:     
                    488:     if (stack_ptr > (vm_offset_t)&user_regs->regs.ds) {
                    489: 
                    490:        user_regs->regs.eax = state->regs.eax;
                    491:        user_regs->regs.ecx = state->regs.ecx;
                    492:        user_regs->regs.edx = state->regs.edx;
                    493:        user_regs->regs.ebx = state->regs.ebx;
                    494:        user_regs->regs.ebp = state->regs.ebp;
                    495:        user_regs->regs.esi = state->regs.esi;
                    496:        user_regs->regs.edi = state->regs.edi;
                    497:        
                    498:        user_regs->regs.ds = state->regs.ds;
                    499:        user_regs->regs.es = state->regs.es;
                    500:        user_regs->regs.fs = state->regs.fs;
                    501:        user_regs->regs.gs = state->regs.gs;
                    502:     }
                    503:     else if (stack_ptr > (vm_offset_t)&user_regs->regs.es) {
                    504:        user_regs->regs.es = state->regs.es;
                    505:        user_regs->regs.fs = state->regs.fs;
                    506:        user_regs->regs.gs = state->regs.gs;
                    507:     }
                    508:     else if (stack_ptr > (vm_offset_t)&user_regs->regs.fs) {
                    509:        user_regs->regs.fs = state->regs.fs;
                    510:        user_regs->regs.gs = state->regs.gs;
                    511:     }
                    512:     else if (stack_ptr > (vm_offset_t)&user_regs->regs.gs)
                    513:        user_regs->regs.gs = state->regs.gs;
                    514: }
                    515: 
                    516: static inline
                    517: void
                    518: check_for_trace(
                    519:     thread_saved_state_t       *state
                    520: )
                    521: {
                    522:     thread_t                   thread = current_thread();
                    523:     
                    524:     if (thread->pcb->trace) {
                    525:        thread->pcb->trace = FALSE;
                    526:        state->frame.eflags |= EFL_TF;
                    527:     }
                    528: }
                    529: 
                    530: void
                    531: machdep_call(
                    532:     thread_saved_state_t       *state
                    533: )
                    534: {
                    535:     except_frame_t             *frame = &state->frame;
                    536:     regs_t                     *regs = &state->regs;
                    537:     int                                trapno, nargs;
                    538:     machdep_call_t             *entry;
                    539:     
                    540:     check_for_trace(state);
                    541:     
                    542:     trapno = regs->eax;
                    543:     if (trapno < 0 || trapno >= machdep_call_count) {
                    544:        regs->eax = (unsigned int)kern_invalid();
                    545: 
                    546:        thread_exception_return();
                    547:        /* NOTREACHED */
                    548:     }
                    549:     
                    550:     entry = &machdep_call_table[trapno];
                    551:     nargs = entry->nargs;
                    552: 
                    553:     if (nargs > 0) {
                    554:        int                     args[nargs];
                    555: 
                    556:        if (copyin(frame->esp + sizeof (int),
                    557:                    args,
                    558:                    nargs * sizeof (int))) {
                    559: 
                    560:            regs->eax = KERN_INVALID_ADDRESS;
                    561: 
                    562:            thread_exception_return();
                    563:            /* NOTREACHED */
                    564:        }
                    565: 
                    566:        asm volatile("
                    567:            1:
                    568:            mov (%2),%%eax;
                    569:            pushl %%eax;
                    570:            sub $4,%2;
                    571:            dec %1;
                    572:            jne 1b;
                    573:            mov %3,%%eax;
                    574:            call *%%eax;
                    575:            mov %%eax,%0"
                    576:            
                    577:            : "=r" (regs->eax)
                    578:            : "r" (nargs),
                    579:                "r" (&args[nargs - 1]),
                    580:                "g" (entry->routine)
                    581:            : "ax", "cx", "dx", "sp");
                    582:     }
                    583:     else
                    584:        regs->eax = (unsigned int)(*entry->routine)();
                    585: 
                    586:     thread_exception_return();
                    587:     /* NOTREACHED */
                    588: }
                    589: 
                    590: void
                    591: mach_kernel_trap(
                    592:     thread_saved_state_t       *state
                    593: )
                    594: {
                    595:     except_frame_t             *frame = &state->frame;
                    596:     regs_t                     *regs = &state->regs;
                    597:     int                                trapno, nargs;
                    598:     mach_trap_t                        *entry;
                    599:     
                    600:     check_for_trace(state);
                    601:     
                    602:     trapno = -(int)regs->eax;
                    603:     if (trapno < 0 || trapno >= mach_trap_count) {
                    604:        regs->eax = (unsigned int)kern_invalid();
                    605: 
                    606:        thread_exception_return();
                    607:        /* NOTREACHED */
                    608:     }
                    609:     
                    610:     entry = &mach_trap_table[trapno];
                    611:     nargs = entry->mach_trap_arg_count;
                    612: 
                    613:     if (nargs > 0) {
                    614:        int                     args[nargs];
                    615: 
                    616:        if (copyin(frame->esp + sizeof (int),
                    617:                    args,
                    618:                    nargs * sizeof (int))) {
                    619: 
                    620:            exception(EXC_BAD_ACCESS,
                    621:                        KERN_INVALID_ADDRESS,
                    622:                        frame->esp + sizeof (int));
                    623:            /* NOTREACHED */
                    624:        }
                    625: 
                    626:        asm volatile("
                    627:            1:
                    628:            mov (%2),%%eax;
                    629:            pushl %%eax;
                    630:            sub $4,%2;
                    631:            dec %1;
                    632:            jne 1b;
                    633:            mov %3,%%eax;
                    634:            call *%%eax;
                    635:            mov %%eax,%0"
                    636:            
                    637:            : "=r" (regs->eax)
                    638:            : "r" (nargs),
                    639:                "r" (&args[nargs - 1]),
                    640:                "g" (entry->mach_trap_function)
                    641:            : "ax", "cx", "dx", "sp");
                    642:     }
                    643:     else
                    644:        regs->eax = (unsigned int)(*entry->mach_trap_function)();
                    645: 
                    646:     thread_exception_return();
                    647:     /* NOTREACHED */
                    648: }
                    649: 
                    650: void
                    651: unix_syscall(
                    652:     thread_saved_state_t       *state
                    653: )
                    654: {
                    655:     except_frame_t             *frame = &state->frame;
                    656:     regs_t                     *regs = &state->regs;
                    657:     thread_t                   thread = current_thread();
                    658:     struct uthread             *uthread;
                    659:     struct sysent              *callp;
                    660:     struct proc                        *p;
                    661:     struct timeval             syst;
                    662:     int                                nargs, error = 0;
                    663:     unsigned short             code;
                    664:     caddr_t                    params;
                    665:        int rval[2];
                    666:     
                    667:     check_for_trace(state);
                    668: 
                    669:     uthread = thread->_uthread;
                    670:     uthread->uu_ar0 = (int *)state;
                    671:     if (p = current_proc())    
                    672:        syst = p->p_stats->p_ru.ru_stime;
                    673:     
                    674:     code = regs->eax;
                    675:     params = (caddr_t)frame->esp + sizeof (int);
                    676:     callp = (code >= nsysent) ? &sysent[63] : &sysent[code];
                    677:     if (callp == sysent) {
                    678:        code = fuword(params);
                    679:        params += sizeof (int);
                    680:        callp = (code >= nsysent) ? &sysent[63] : &sysent[code];
                    681:     }
                    682:     
                    683:     if ((nargs = (callp->sy_narg * sizeof (int))) &&
                    684:            (error = copyin(params, (caddr_t)uthread->uu_arg, nargs)) != 0) {
                    685:        regs->eax = error;
                    686:        frame->eflags |= EFL_CF;
                    687:        thread_exception_return();
                    688:        /* NOTREACHED */
                    689:     }
                    690:     
                    691:     rval[0] = 0;
                    692:     rval[1] = regs->edx;
                    693: 
                    694:        error = (*(callp->sy_call))(p, (caddr_t)uthread->uu_arg, rval);
                    695:        
                    696:        if (error == ERESTART) {
                    697:                state->frame.eip -= 7;
                    698:        }
                    699:        else if (error != EJUSTRETURN) {
                    700:                if (error) {
                    701:            state->regs.eax = error;
                    702:            state->frame.eflags |= EFL_CF;      /* carry bit */
                    703:                } else { /* (not error) */
                    704:            state->regs.eax = rval[0];
                    705:            state->regs.edx = rval[1];
                    706:            state->frame.eflags &= ~EFL_CF;
                    707:                } 
                    708:        }
                    709:        /* else  (error == EJUSTRETURN) { nothing } */
                    710: 
                    711:     thread_exception_return();
                    712:     /* NOTREACHED */
                    713:        
                    714: }
                    715: 
                    716: 
                    717: void
                    718: check_for_ast(
                    719:     thread_saved_state_t       *state
                    720: )
                    721: {
                    722:     thread_t                   thread = current_thread();
                    723:     struct proc                        *p = current_proc();
                    724: 
                    725:     while (TRUE) {
                    726:        ast_t                   reasons;
                    727:        int                     mycpu = cpu_number();
                    728:        int                                     signum;
                    729: 
                    730:        cli();          // disable interrupts
                    731:        
                    732:        reasons = ast_needed(mycpu);    
                    733: 
                    734:        if (p) {                    
                    735:            if ((p->p_flag & P_OWEUPC) && (p->p_flag & P_PROFIL)) {
                    736:                addupc_task(p, state->frame.eip, 1);
                    737:                p->p_flag &= ~P_OWEUPC;
                    738:            }
                    739:            
                    740:            ast_off(mycpu, AST_UNIX);
                    741:            
                    742:            if (CHECK_SIGNALS(p, thread, thread->_uthread)) {
                    743:                        signum = issignal(p);
                    744:                        if (signum)
                    745:                                postsig(signum);
                    746:                        cli();
                    747:            }
                    748:        }
                    749: 
                    750:        ast_off(mycpu, reasons);
                    751: 
                    752:        if (thread_should_halt(thread))
                    753:            thread_halt_self();
                    754:        else
                    755:        if ((reasons & AST_BLOCK) ||
                    756:                csw_needed(thread, current_processor())) {
                    757:                p->p_stats->p_ru.ru_nivcsw++;
                    758:            thread_block_with_continuation(thread_exception_return);
                    759:        }
                    760:        else
                    761:        if (reasons & AST_FP_EXTEN)
                    762:            fp_ast(thread);
                    763:        else
                    764:            break;
                    765:     }
                    766: }
                    767: 
                    768: typedef struct _cframe_t {
                    769:     struct _cframe_t   *prev;
                    770:     unsigned           caller;
                    771:     unsigned           args[0];
                    772: } cframe_t;
                    773: 
                    774: 
                    775: #define MAX_FRAME_DELTA                65536
                    776: 
                    777: void
                    778: _i386_backtrace(
                    779:     void                       *_frame,
                    780:     int                                nframes
                    781: )
                    782: {
                    783:        cframe_t        *frame = (cframe_t *)_frame;
                    784:        int i;
                    785: 
                    786:        for (i=0; i<nframes; i++) {
                    787:            if ((vm_offset_t)frame < VM_MIN_KERNEL_ADDRESS ||
                    788:                (vm_offset_t)frame > VM_MAX_KERNEL_ADDRESS) {
                    789:                goto invalid;
                    790:            }
                    791:            safe_prf("frame %x called by %x ",
                    792:                frame, frame->caller);
                    793:            safe_prf("args %x %x %x %x\n",
                    794:                frame->args[0], frame->args[1],
                    795:                frame->args[2], frame->args[3]);
                    796:            if ((frame->prev < frame) ||        /* wrong direction */
                    797:                ((frame->prev - frame) > MAX_FRAME_DELTA)) {
                    798:                goto invalid;
                    799:            }
                    800:            frame = frame->prev;
                    801:        }
                    802:        return;
                    803: invalid:
                    804:        safe_prf("invalid frame pointer %x\n",frame->prev);
                    805: }

unix.superglobalmegacorp.com

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