Annotation of kernel/machdep/i386/pc_support/PCemulateREAL.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) 1993 NeXT Computer, Inc.
        !            27:  *
        !            28:  * PC support Real mode emulation.
        !            29:  *
        !            30:  * HISTORY
        !            31:  *
        !            32:  * 23 Mar 1993 ? at NeXT
        !            33:  *     Created.
        !            34:  */
        !            35: 
        !            36: #import <mach/mach_types.h>
        !            37: 
        !            38: #import <architecture/i386/sel.h>
        !            39: #import <machdep/i386/trap.h>
        !            40: #import <machdep/i386/err_inline.h>
        !            41: 
        !            42: #import "PCprivate.h"
        !            43: #import "PCmiscInline.h"
        !            44: #import "PCtaskInline.h"
        !            45: 
        !            46: struct inst_prefix {
        !            47:     unsigned int       opnd    :1,
        !            48:                        addr    :1;
        !            49: };
        !            50: 
        !            51: static __inline__
        !            52: vm_offset_t
        !            53: segment_base(
        !            54:     sel_t              sel
        !            55: )
        !            56: {
        !            57:     return ((*(unsigned short *)&sel) << 4);
        !            58: }
        !            59: 
        !            60: static __inline__
        !            61: fetch_segment_byte(
        !            62:     thread_t           thread,
        !            63:     sel_t              sel,
        !            64:     unsigned short     offset,
        !            65:     unsigned char      *data
        !            66: )
        !            67: {
        !            68:     vm_offset_t                base = segment_base(sel);
        !            69:     
        !            70:     return (fetchByte(thread, base + offset, data));
        !            71: }
        !            72: 
        !            73: static __inline__
        !            74: fetch_segment_2byte(
        !            75:     thread_t           thread,
        !            76:     sel_t              sel,
        !            77:     unsigned short     offset,
        !            78:     unsigned short     *data
        !            79: )
        !            80: {
        !            81:     vm_offset_t                base = segment_base(sel);
        !            82:     
        !            83:     return (fetch2Byte(thread, base + offset, data));
        !            84: }
        !            85: 
        !            86: static __inline__
        !            87: store_segment_2byte(
        !            88:     thread_t           thread,
        !            89:     sel_t              sel,
        !            90:     unsigned short     offset,
        !            91:     unsigned short     data
        !            92: )
        !            93: {
        !            94:     vm_offset_t                base = segment_base(sel);
        !            95:     
        !            96:     return (store2Byte(thread, base + offset, data));
        !            97: }
        !            98: 
        !            99: static __inline__
        !           100: fetch_segment_4byte(
        !           101:     thread_t           thread,
        !           102:     sel_t              sel,
        !           103:     unsigned short     offset,
        !           104:     unsigned int       *data
        !           105: )
        !           106: {
        !           107:     vm_offset_t                base = segment_base(sel);
        !           108:     
        !           109:     return (fetch4Byte(thread, base + offset, data));
        !           110: }
        !           111: 
        !           112: static __inline__
        !           113: store_segment_4byte(
        !           114:     thread_t           thread,
        !           115:     sel_t              sel,
        !           116:     unsigned short     offset,
        !           117:     unsigned int       data
        !           118: )
        !           119: {
        !           120:     vm_offset_t                base = segment_base(sel);
        !           121:     
        !           122:     return (store4Byte(thread, base + offset, data));
        !           123: }
        !           124: 
        !           125: static __inline__
        !           126: boolean_t
        !           127: fetch_segment(
        !           128:     thread_t           thread,
        !           129:     sel_t              sel,
        !           130:     unsigned short     offset,
        !           131:     void               *data,
        !           132:     unsigned int       length
        !           133: )
        !           134: {
        !           135: #define sdata          ((unsigned short *)data)
        !           136:     vm_offset_t                base = segment_base(sel);
        !           137: 
        !           138:     thread->recover = (vm_offset_t)&&fault;
        !           139:     
        !           140:     while (length > 0) {
        !           141:        asm volatile(
        !           142:            "movw %%fs:%1,%0"
        !           143:                    : "=q" (*sdata)
        !           144:                    : "m" (*(unsigned short *)(base + offset)));
        !           145:        
        !           146:        sdata++; offset += sizeof (*sdata); length -= sizeof (*sdata);
        !           147:     }
        !           148: 
        !           149:     thread->recover = 0;
        !           150:     return (TRUE);
        !           151:     
        !           152: fault:
        !           153:     thread->recover = 0;
        !           154:     return (FALSE);
        !           155: #undef sdata
        !           156: }
        !           157: 
        !           158: static __inline__
        !           159: boolean_t
        !           160: store_segment(
        !           161:     thread_t           thread,
        !           162:     sel_t              sel,
        !           163:     unsigned short     offset,
        !           164:     void               *data,
        !           165:     unsigned int       length
        !           166: )
        !           167: {
        !           168: #define sdata          ((unsigned short *)data)
        !           169:     vm_offset_t                base = segment_base(sel);
        !           170: 
        !           171:     thread->recover = (vm_offset_t)&&fault;
        !           172:     
        !           173:     while (length > 0) {
        !           174:        asm volatile(
        !           175:            "movw %0,%%fs:%1"
        !           176:                    :
        !           177:                    : "r" (*sdata), "m" (*(unsigned short *)(base + offset)));
        !           178:        
        !           179:        sdata++; offset += sizeof (*sdata); length -= sizeof (*sdata);
        !           180:     }
        !           181: 
        !           182:     thread->recover = 0;
        !           183:     return (TRUE);
        !           184:     
        !           185: fault:
        !           186:     thread->recover = 0;
        !           187:     return (FALSE);
        !           188: #undef sdata
        !           189: }
        !           190: 
        !           191: static
        !           192: boolean_t
        !           193: handle_bop(
        !           194:     thread_t                   thread,
        !           195:     thread_saved_state_t       *state
        !           196: )
        !           197: {
        !           198:     PCcontext_t                context = threadPCContext(thread);
        !           199:     unsigned int       inst;
        !           200:     unsigned char      bbyte;
        !           201:     
        !           202:     if (!fetch_segment_4byte(
        !           203:                        thread,
        !           204:                        state->frame.cs, state->frame.eip,
        !           205:                        &inst))
        !           206:        return (FALSE);
        !           207:        
        !           208:     if (*(unsigned short *)&inst != 0xC4C4)
        !           209:        return (FALSE);
        !           210:        
        !           211:     bbyte = *((unsigned char *)&inst + 2);
        !           212:        
        !           213:     if (bbyte == 0xFE) {
        !           214:        PCcancelTimers(context);
        !           215: 
        !           216:        context->callHandler = PC_HANDLE_EXIT;
        !           217:        
        !           218:        PCcallMonitor(thread, state);
        !           219:        /* NOTREACHED */
        !           220:     }
        !           221:     else if (bbyte == 0xFA) {
        !           222:        PCbopFA_t       args;
        !           223:        
        !           224:        if (!fetch_segment(
        !           225:                        thread,
        !           226:                        state->frame.ss, state->frame.esp,
        !           227:                        &args, sizeof (args)))
        !           228:            return (FALSE);
        !           229:        
        !           230:        return (PCbopFA(thread, state, &args));
        !           231:        /* NOTREACHED */
        !           232:     }
        !           233:     else if (bbyte == 0xFC) {
        !           234:        PCbopFC_t       args;
        !           235:        
        !           236:        if (!fetch_segment(
        !           237:                        thread,
        !           238:                        state->frame.ss, state->frame.esp,
        !           239:                        &args, sizeof (args)))
        !           240:            return (FALSE);
        !           241:        
        !           242:        return (PCbopFC(thread, state, &args));
        !           243:        /* NOTREACHED */
        !           244:     }
        !           245:     else if (bbyte == 0xFD) {
        !           246:        PCbopFD_t       args;
        !           247:        
        !           248:        if (!fetch_segment(
        !           249:                        thread,
        !           250:                        state->frame.ss, state->frame.esp,
        !           251:                        &args, sizeof (args)))
        !           252:            return (FALSE);
        !           253:        
        !           254:        PCbopFD(thread, state, &args);
        !           255:        /* NOTREACHED */
        !           256:     }
        !           257:     else {
        !           258:        context->trapNum = bbyte;
        !           259:        context->callHandler = PC_HANDLE_BOP;
        !           260:        
        !           261:        PCcallMonitor(thread, state);
        !           262:        /* NOTREACHED */
        !           263:     }
        !           264: }
        !           265:                        
        !           266: static __inline__
        !           267: boolean_t
        !           268: fetch_inst(
        !           269:     thread_t                   thread,
        !           270:     thread_saved_state_t       *state,
        !           271:     int                                *offset,
        !           272:     unsigned char              *inst,
        !           273:     struct inst_prefix         *prefix
        !           274: )
        !           275: {
        !           276:     sel_t              cs;
        !           277:     unsigned short     ip;
        !           278:     unsigned char      ibyte;
        !           279:     int                        n;
        !           280: 
        !           281:     cs = state->frame.cs;      
        !           282:     ip = state->frame.eip;
        !           283:     
        !           284:     for (n = 0; n < 15; n++) { // a reasonable limit
        !           285:        if (!fetch_segment_byte(thread, cs, ip + n, &ibyte))
        !           286:            break;
        !           287: 
        !           288:        switch (ibyte) {
        !           289: 
        !           290:        case 0x66:      // Operand-size prefix
        !           291:            prefix->opnd = TRUE;
        !           292:            break;
        !           293:            
        !           294:        case 0xf0:      // LOCK prefix
        !           295:            break;
        !           296:            
        !           297:        default:
        !           298:            *offset = (ip + n) - ip;
        !           299:            *inst = ibyte - 0x90;
        !           300:            
        !           301:            return (TRUE);
        !           302:        }
        !           303:     }
        !           304:     
        !           305:     return (FALSE);
        !           306: }
        !           307: 
        !           308: static
        !           309: boolean_t
        !           310: emulate_CLI(
        !           311:     thread_t                   thread,
        !           312:     thread_saved_state_t       *state,
        !           313:     int                                offset,
        !           314:     struct inst_prefix         prefix
        !           315: )
        !           316: {
        !           317:     PCcontext_t                context = threadPCContext(thread);
        !           318:     
        !           319:     (unsigned short)state->frame.eip += (offset + 1);
        !           320:        
        !           321:     context->IF_flag = FALSE;
        !           322:     
        !           323:     return (TRUE);
        !           324: }
        !           325: 
        !           326: static
        !           327: boolean_t
        !           328: emulate_STI(
        !           329:     thread_t                   thread,
        !           330:     thread_saved_state_t       *state,
        !           331:     int                                offset,
        !           332:     struct inst_prefix         prefix
        !           333: )
        !           334: {
        !           335:     PCcontext_t                context = threadPCContext(thread);
        !           336:        
        !           337:     (unsigned short)state->frame.eip += (offset + 1);
        !           338:        
        !           339:     if (!context->IF_flag) {
        !           340:        context->IF_flag = TRUE;
        !           341: 
        !           342:        context->pendingCallbacks |= (context->runOptions & PC_RUN_IF_SET);
        !           343:     }
        !           344:     
        !           345:     return (TRUE);
        !           346: }
        !           347: 
        !           348: static boolean_t       emulate_PUSHFD(
        !           349:                                    thread_t                    thread,
        !           350:                                    thread_saved_state_t        *state,
        !           351:                                    int                         offset,
        !           352:                                    struct inst_prefix          prefix);
        !           353: 
        !           354: static
        !           355: boolean_t
        !           356: emulate_PUSHF(
        !           357:     thread_t                   thread,
        !           358:     thread_saved_state_t       *state,
        !           359:     int                                offset,
        !           360:     struct inst_prefix         prefix
        !           361: )
        !           362: {
        !           363:     PCcontext_t                        context;
        !           364:     struct {
        !           365:        unsigned short  flags;
        !           366:     }                          frame;
        !           367:     
        !           368:     if (prefix.opnd)
        !           369:        return (emulate_PUSHFD(thread, state, offset, prefix));
        !           370: 
        !           371:     context = threadPCContext(thread);
        !           372:        
        !           373:     frame.flags = state->frame.eflags;
        !           374:     if (context->IF_flag)
        !           375:        frame.flags |= EFL_IF;
        !           376:     else
        !           377:        frame.flags &= ~EFL_IF;
        !           378:        
        !           379:     frame.flags |= (context->X_flags & (EFL_NT | EFL_IOPL));
        !           380:                                    
        !           381:     if (!store_segment_2byte(
        !           382:                            thread, 
        !           383:                            state->frame.ss, state->frame.esp - sizeof (frame),
        !           384:                            frame.flags))
        !           385:        return (FALSE);
        !           386:        
        !           387:     (unsigned short)state->frame.eip += (offset + 1);
        !           388:     
        !           389:     (unsigned short)state->frame.esp -= sizeof (frame);
        !           390: 
        !           391:     return (TRUE);     
        !           392: }
        !           393: 
        !           394: static
        !           395: boolean_t
        !           396: emulate_PUSHFD(
        !           397:     thread_t                   thread,
        !           398:     thread_saved_state_t       *state,
        !           399:     int                                offset,
        !           400:     struct inst_prefix         prefix
        !           401: )
        !           402: {
        !           403:     PCcontext_t                        context;
        !           404:     struct {
        !           405:        unsigned int    eflags;
        !           406:     }                          frame;
        !           407: 
        !           408:     context = threadPCContext(thread);
        !           409:     
        !           410:     frame.eflags = state->frame.eflags;
        !           411:     if (context->IF_flag)
        !           412:        frame.eflags |= EFL_IF;
        !           413:     else
        !           414:        frame.eflags &= ~EFL_IF;
        !           415:        
        !           416:     frame.eflags |= (context->X_flags & (EFL_NT | EFL_IOPL));
        !           417:                                    
        !           418:     if (!store_segment_4byte(
        !           419:                            thread, 
        !           420:                            state->frame.ss, state->frame.esp - sizeof (frame),
        !           421:                            frame.eflags))
        !           422:        return (FALSE);
        !           423:        
        !           424:     (unsigned short)state->frame.eip += (offset + 1);
        !           425:     
        !           426:     (unsigned short)state->frame.esp -= sizeof (frame);
        !           427: 
        !           428:     return (TRUE);     
        !           429: }
        !           430: 
        !           431: static boolean_t       emulate_POPFD(
        !           432:                                    thread_t                    thread,
        !           433:                                    thread_saved_state_t        *state,
        !           434:                                    int                         offset,
        !           435:                                    struct inst_prefix          prefix);
        !           436: 
        !           437: static
        !           438: boolean_t
        !           439: emulate_POPF(
        !           440:     thread_t                   thread,
        !           441:     thread_saved_state_t       *state,
        !           442:     int                                offset,
        !           443:     struct inst_prefix         prefix
        !           444: )
        !           445: {
        !           446:     PCcontext_t                        context;
        !           447:     struct {
        !           448:        unsigned short  flags;
        !           449:     }                          frame;
        !           450:     
        !           451:     if (prefix.opnd)
        !           452:        return (emulate_POPFD(thread, state, offset, prefix));
        !           453: 
        !           454:     context = threadPCContext(thread);
        !           455:                                
        !           456:     if (!fetch_segment_2byte(
        !           457:                            thread, 
        !           458:                            state->frame.ss, state->frame.esp,
        !           459:                            &frame.flags))
        !           460:        return (FALSE);
        !           461:        
        !           462:     if ((context->debugOptions & PC_DEBUG_PRESERVE_TRACE) != 0)
        !           463:        frame.flags |= (state->frame.eflags & EFL_TF);
        !           464:     (unsigned short)state->frame.eflags = frame.flags;
        !           465:     state->frame.eflags &= ~( EFL_NT | EFL_IOPL | EFL_CLR );
        !           466:     state->frame.eflags |=  ( EFL_VM | EFL_IF | EFL_SET );
        !           467:     
        !           468:     (unsigned short)state->frame.eip += (offset + 1);
        !           469:     (unsigned short)state->frame.esp += sizeof (frame);
        !           470:     
        !           471:     context->X_flags = (frame.flags & (EFL_NT | EFL_IOPL));
        !           472:        
        !           473:     if (frame.flags & EFL_IF) {
        !           474:        if (!context->IF_flag)
        !           475:            context->pendingCallbacks |= (context->runOptions & PC_RUN_IF_SET);
        !           476: 
        !           477:        context->IF_flag = TRUE;
        !           478:     }
        !           479:     else
        !           480:        context->IF_flag = FALSE;
        !           481:     
        !           482:     return (TRUE);
        !           483: }
        !           484: 
        !           485: static
        !           486: boolean_t
        !           487: emulate_POPFD(
        !           488:     thread_t                   thread,
        !           489:     thread_saved_state_t       *state,
        !           490:     int                                offset,
        !           491:     struct inst_prefix         prefix
        !           492: )
        !           493: {
        !           494:     PCcontext_t                        context;
        !           495:     struct {
        !           496:        unsigned long   eflags;
        !           497:     }                          frame;
        !           498: 
        !           499:     context = threadPCContext(thread);
        !           500:                                
        !           501:     if (!fetch_segment_4byte(
        !           502:                            thread, 
        !           503:                            state->frame.ss, state->frame.esp,
        !           504:                            &frame.eflags))
        !           505:        return (FALSE);
        !           506:        
        !           507:     if ((context->debugOptions & PC_DEBUG_PRESERVE_TRACE) != 0)
        !           508:        frame.eflags |= (state->frame.eflags & EFL_TF);
        !           509:     state->frame.eflags = frame.eflags;
        !           510:     state->frame.eflags &= ~( EFL_NT | EFL_IOPL | EFL_CLR );
        !           511:     state->frame.eflags |=  ( EFL_VM | EFL_IF | EFL_SET );
        !           512:     
        !           513:     (unsigned short)state->frame.eip += (offset + 1);
        !           514:     (unsigned short)state->frame.esp += sizeof (frame);
        !           515:     
        !           516:     context->X_flags = (frame.eflags & (EFL_NT | EFL_IOPL));
        !           517:        
        !           518:     if (frame.eflags & EFL_IF) {
        !           519:        if (!context->IF_flag)
        !           520:            context->pendingCallbacks |= (context->runOptions & PC_RUN_IF_SET);
        !           521: 
        !           522:        context->IF_flag = TRUE;
        !           523:     }
        !           524:     else
        !           525:        context->IF_flag = FALSE;
        !           526:     
        !           527:     return (TRUE);
        !           528: }
        !           529: 
        !           530: static boolean_t       emulate_IRETD(
        !           531:                                    thread_t                    thread,
        !           532:                                    thread_saved_state_t        *state,
        !           533:                                    int                         offset,
        !           534:                                    struct inst_prefix          prefix);
        !           535: 
        !           536: static
        !           537: boolean_t
        !           538: emulate_IRET(
        !           539:     thread_t                   thread,
        !           540:     thread_saved_state_t       *state,
        !           541:     int                                offset,
        !           542:     struct inst_prefix         prefix
        !           543: )
        !           544: {
        !           545:     PCcontext_t                        context;
        !           546:     struct {
        !           547:        unsigned short  ip;
        !           548:        sel_t           cs;
        !           549:        unsigned short  flags;
        !           550:     }                          frame;
        !           551:     
        !           552:     if (prefix.opnd)
        !           553:        return (emulate_IRETD(thread, state, offset, prefix));
        !           554: 
        !           555:     context = threadPCContext(thread);
        !           556:                                
        !           557:     if (!fetch_segment(
        !           558:                    thread,
        !           559:                    state->frame.ss, state->frame.esp,
        !           560:                    &frame, sizeof (frame)))
        !           561:        return (FALSE);
        !           562:        
        !           563:     (unsigned short)state->frame.eip = frame.ip;
        !           564:     state->frame.cs = frame.cs;
        !           565: 
        !           566:     if ((context->debugOptions & PC_DEBUG_PRESERVE_TRACE) != 0)
        !           567:        frame.flags |= (state->frame.eflags & EFL_TF);
        !           568:     (unsigned short)state->frame.eflags = frame.flags;
        !           569:     state->frame.eflags &= ~( EFL_NT | EFL_IOPL | EFL_CLR );
        !           570:     state->frame.eflags |=  ( EFL_VM | EFL_IF | EFL_SET );
        !           571:     
        !           572:     (unsigned short)state->frame.esp += sizeof (frame);
        !           573:     
        !           574:     context->X_flags = (frame.flags & (EFL_NT | EFL_IOPL));
        !           575:        
        !           576:     if (frame.flags & EFL_IF) {
        !           577:        if (!context->IF_flag)
        !           578:            context->pendingCallbacks |= (context->runOptions & PC_RUN_IF_SET);
        !           579: 
        !           580:        context->IF_flag = TRUE;
        !           581:     }
        !           582:     else
        !           583:        context->IF_flag = FALSE;
        !           584:     
        !           585:     return (TRUE);
        !           586: }
        !           587: 
        !           588: static
        !           589: boolean_t
        !           590: emulate_IRETD(
        !           591:     thread_t                   thread,
        !           592:     thread_saved_state_t       *state,
        !           593:     int                                offset,
        !           594:     struct inst_prefix         prefix
        !           595: )
        !           596: {
        !           597:     PCcontext_t                        context;
        !           598:     struct {
        !           599:        unsigned long   eip;
        !           600:        sel_t           cs;
        !           601:        unsigned long   eflags;
        !           602:     }                          frame;
        !           603: 
        !           604:     context = threadPCContext(thread);
        !           605:         
        !           606:     if (!fetch_segment(
        !           607:                    thread,
        !           608:                    state->frame.ss, state->frame.esp,
        !           609:                    &frame, sizeof (frame)))
        !           610:        return (FALSE);
        !           611:        
        !           612:     state->frame.eip = frame.eip;
        !           613:     state->frame.cs = frame.cs;
        !           614:        
        !           615:     if ((context->debugOptions & PC_DEBUG_PRESERVE_TRACE) != 0)
        !           616:        frame.eflags |= (state->frame.eflags & EFL_TF);
        !           617:     state->frame.eflags = frame.eflags;
        !           618:     state->frame.eflags &= ~( EFL_NT | EFL_IOPL | EFL_CLR );
        !           619:     state->frame.eflags |=  ( EFL_VM | EFL_IF | EFL_SET );
        !           620:     
        !           621:     (unsigned short)state->frame.esp += sizeof (frame);
        !           622:     
        !           623:     context->X_flags = (frame.eflags & (EFL_NT | EFL_IOPL));
        !           624:        
        !           625:     if (frame.eflags & EFL_IF) {
        !           626:        if (!context->IF_flag)
        !           627:            context->pendingCallbacks |= (context->runOptions & PC_RUN_IF_SET);
        !           628: 
        !           629:        context->IF_flag = TRUE;
        !           630:     }
        !           631:     else
        !           632:        context->IF_flag = FALSE;
        !           633:     
        !           634:     return (TRUE);
        !           635: }
        !           636: 
        !           637: static
        !           638: boolean_t
        !           639: emulate_exception(
        !           640:     thread_t                   thread,
        !           641:     thread_saved_state_t       *state,
        !           642:     int                                trapno
        !           643: )
        !           644: {
        !           645:     PCcontext_t                        context;
        !           646:     struct {
        !           647:        unsigned short  ip;
        !           648:        sel_t           cs;
        !           649:        unsigned short  flags;
        !           650:     }                          frame;
        !           651:     struct {
        !           652:        unsigned short  ip;
        !           653:        sel_t           cs;
        !           654:     }                          vector;
        !           655: 
        !           656:     context = threadPCContext(thread);
        !           657:     
        !           658:     frame.ip = state->frame.eip;
        !           659:     frame.cs = state->frame.cs;
        !           660:     
        !           661:     frame.flags = state->frame.eflags;
        !           662:     if (context->IF_flag)
        !           663:        frame.flags |= EFL_IF;
        !           664:     else
        !           665:        frame.flags &= ~EFL_IF;
        !           666:        
        !           667:     frame.flags |= (context->X_flags & (EFL_NT | EFL_IOPL));
        !           668:     
        !           669:     if (!store_segment(
        !           670:                    thread,
        !           671:                    state->frame.ss, state->frame.esp - sizeof (frame),
        !           672:                    &frame, sizeof (frame)))
        !           673:        return (FALSE);
        !           674:        
        !           675:     if (!fetch4Byte(thread, (trapno << 2), (unsigned long *)&vector))
        !           676:        return (FALSE);
        !           677:        
        !           678:     (unsigned short)state->frame.esp -= sizeof (frame);
        !           679:        
        !           680:     state->frame.eip = vector.ip;
        !           681:     state->frame.cs = vector.cs;
        !           682:        
        !           683:     context->IF_flag = FALSE;
        !           684:     
        !           685:     if ((context->debugOptions & PC_DEBUG_PRESERVE_TRACE) == 0)
        !           686:        state->frame.eflags &= ~EFL_TF;
        !           687:     
        !           688:     return (TRUE);
        !           689: }
        !           690: 
        !           691: static
        !           692: boolean_t
        !           693: emulate_INTn(
        !           694:     thread_t                   thread,
        !           695:     thread_saved_state_t       *state,
        !           696:     int                                offset,
        !           697:     struct inst_prefix         prefix
        !           698: )
        !           699: {
        !           700:     PCshared_t                 shared;
        !           701:     PCcontext_t                        context;
        !           702:     unsigned char              trapno;
        !           703: 
        !           704:     shared = threadPCShared(thread);
        !           705:     context = currentContext(shared);
        !           706: 
        !           707:     if (!fetch_segment_byte(
        !           708:                            thread, 
        !           709:                            state->frame.cs, state->frame.eip + offset + 1,
        !           710:                            &trapno))
        !           711:        return (FALSE);
        !           712:        
        !           713:     if (maskIsSet(&shared->intNMask, trapno)) {
        !           714:        context->trapNum = trapno;
        !           715:        context->errCode = 0;
        !           716:        if (trapno <= 7)
        !           717:            context->callHandler = PC_HANDLE_FAULT;
        !           718:        else
        !           719:            context->callHandler = PC_HANDLE_INTN;
        !           720:        
        !           721:        PCcallMonitor(thread, state);
        !           722:        /* NOTREACHED */
        !           723:     }
        !           724:        
        !           725:     (unsigned short)state->frame.eip += (offset + 2);
        !           726:        
        !           727:     if (!emulate_exception(thread, state, trapno)) {
        !           728:        (unsigned short)state->frame.eip -= (offset + 2);
        !           729:        return (FALSE);
        !           730:     }
        !           731:     
        !           732:     return (TRUE);
        !           733: }
        !           734: 
        !           735: static
        !           736: boolean_t
        !           737: handle_exception(
        !           738:     thread_t                   thread,
        !           739:     thread_saved_state_t       *state
        !           740: )
        !           741: {
        !           742:     PCshared_t                 shared;
        !           743:     PCcontext_t                        context;
        !           744:     
        !           745:     shared = threadPCShared(thread);
        !           746:     context = currentContext(shared);
        !           747:     
        !           748:     if (maskIsSet(&shared->faultMask, state->trapno)) {
        !           749:        context->trapNum = state->trapno;
        !           750:        context->errCode = err_to_error_code(state->frame.err);
        !           751:        context->callHandler = PC_HANDLE_FAULT;
        !           752:        
        !           753:        PCcallMonitor(thread, state);
        !           754:        /* NOTREACHED */
        !           755:     }
        !           756:        
        !           757:     if (!emulate_exception(thread, state, state->trapno))
        !           758:        return (FALSE);
        !           759:     
        !           760:     return (TRUE);
        !           761: }
        !           762: 
        !           763: #define none   0
        !           764: #define STI    emulate_STI
        !           765: #define CLI    emulate_CLI
        !           766: #define PUSHF  emulate_PUSHF
        !           767: #define POPF   emulate_POPF
        !           768: #define IRET   emulate_IRET
        !           769: #define INTn   emulate_INTn
        !           770: 
        !           771: static
        !           772: boolean_t (*inst_table[256])() =
        !           773: {
        !           774:     /* 90 */ none, /* 91 */ none, /* 92 */ none, /* 93 */ none, 
        !           775:     /* 94 */ none, /* 95 */ none, /* 96 */ none, /* 97 */ none, 
        !           776:     /* 98 */ none, /* 99 */ none, /* 9A */ none, /* 9B */ none, 
        !           777:     /* 9C */PUSHF, /* 9D */ POPF, /* 9E */ none, /* 9F */ none, 
        !           778:     /* A0 */ none, /* A1 */ none, /* A2 */ none, /* A3 */ none, 
        !           779:     /* A4 */ none, /* A5 */ none, /* A6 */ none, /* A7 */ none, 
        !           780:     /* A8 */ none, /* A9 */ none, /* AA */ none, /* AB */ none, 
        !           781:     /* AC */ none, /* AD */ none, /* AE */ none, /* AF */ none, 
        !           782:     /* B0 */ none, /* B1 */ none, /* B2 */ none, /* B3 */ none, 
        !           783:     /* B4 */ none, /* B5 */ none, /* B6 */ none, /* B7 */ none, 
        !           784:     /* B8 */ none, /* B9 */ none, /* BA */ none, /* BB */ none, 
        !           785:     /* BC */ none, /* BD */ none, /* BE */ none, /* BF */ none, 
        !           786:     /* C0 */ none, /* C1 */ none, /* C2 */ none, /* C3 */ none, 
        !           787:     /* C4 */ none, /* C5 */ none, /* C6 */ none, /* C7 */ none, 
        !           788:     /* C8 */ none, /* C9 */ none, /* CA */ none, /* CB */ none, 
        !           789:     /* CC */ none, /* CD */ INTn, /* CE */ none, /* CF */ IRET, 
        !           790:     /* D0 */ none, /* D1 */ none, /* D2 */ none, /* D3 */ none, 
        !           791:     /* D4 */ none, /* D5 */ none, /* D6 */ none, /* D7 */ none, 
        !           792:     /* D8 */ none, /* D9 */ none, /* DA */ none, /* DB */ none, 
        !           793:     /* DC */ none, /* DD */ none, /* DE */ none, /* DF */ none, 
        !           794:     /* E0 */ none, /* E1 */ none, /* E2 */ none, /* E3 */ none, 
        !           795:     /* E4 */ none, /* E5 */ none, /* E6 */ none, /* E7 */ none, 
        !           796:     /* E8 */ none, /* E9 */ none, /* EA */ none, /* EB */ none, 
        !           797:     /* EC */ none, /* ED */ none, /* EE */ none, /* EF */ none, 
        !           798:     /* F0 */ none, /* F1 */ none, /* F2 */ none, /* F3 */ none, 
        !           799:     /* F4 */ none, /* F5 */ none, /* F6 */ none, /* F7 */ none, 
        !           800:     /* F8 */ none, /* F9 */ none, /* FA */  CLI, /* FB */  STI, 
        !           801:     /* FC */ none, /* FD */ none, /* FE */ none, /* FF */ none, 
        !           802: };
        !           803: 
        !           804: static
        !           805: boolean_t
        !           806: emulate_instruction(
        !           807:     thread_t                   thread,
        !           808:     thread_saved_state_t       *state
        !           809: )
        !           810: {
        !           811:     int                                offset;
        !           812:     unsigned char              inst;
        !           813:     struct inst_prefix         prefix = { 0 };
        !           814:     boolean_t                  (*emul)();
        !           815: 
        !           816:     return (
        !           817:        fetch_inst(thread, state, &offset, &inst, &prefix)      &&
        !           818:        (emul = inst_table[inst]) != 0                          &&
        !           819:        (*emul)(thread, state, offset, prefix));
        !           820: }
        !           821: 
        !           822: boolean_t
        !           823: PCemulateREAL(
        !           824:     thread_t                   thread,
        !           825:     thread_saved_state_t       *state
        !           826: )
        !           827: {
        !           828:     if (state->trapno == T_GENERAL_PROTECTION) {
        !           829:        if (!emulate_instruction(thread,state))
        !           830:            return handle_exception(thread, state);
        !           831:        else
        !           832:            return TRUE;
        !           833:     }
        !           834:     else
        !           835:     if (state->trapno == T_INVALID_OPCODE) {
        !           836:        if (!handle_bop(thread, state))
        !           837:            return handle_exception(thread, state);
        !           838:        else
        !           839:            return TRUE;
        !           840:     }
        !           841:     else
        !           842:        return handle_exception(thread, state);
        !           843: }

unix.superglobalmegacorp.com

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