Annotation of kernel/machdep/i386/pc_support/PCemulateREAL.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) 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.