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