Annotation of kernel/machdep/i386/pc_support/PCemulatePROT.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:  * Protected mode emulation.
        !            29:  *
        !            30:  * HISTORY
        !            31:  *
        !            32:  * 8 Apr 1993 ? at NeXT
        !            33:  *     Created.
        !            34:  */
        !            35: 
        !            36: #import <mach/mach_types.h>
        !            37: 
        !            38: #import <architecture/i386/sel.h>
        !            39: #import <architecture/i386/table.h>
        !            40: 
        !            41: #import <machdep/i386/trap.h>
        !            42: #import <machdep/i386/desc_inline.h>
        !            43: #import <machdep/i386/err_inline.h>
        !            44: 
        !            45: #import "PCprivate.h"
        !            46: #import "PCmiscInline.h"
        !            47: #import "PCtaskInline.h"
        !            48: 
        !            49: static __inline__
        !            50: boolean_t
        !            51: fetch_LDT_entry(
        !            52:     thread_t           thread,
        !            53:     unsigned int       index,
        !            54:     ldt_entry_t                *desc
        !            55: )
        !            56: {
        !            57:     PCshared_t         shared = threadPCShared(thread);
        !            58:     unsigned int       byte_index = index * sizeof (ldt_entry_t);
        !            59:     
        !            60:     if (shared->LDT.length <= byte_index)
        !            61:        return (FALSE);
        !            62:        
        !            63:     return (fetch8Byte(thread, shared->LDT.address + byte_index, desc));
        !            64: }
        !            65: 
        !            66: static __inline__
        !            67: boolean_t
        !            68: fetch_IDT_entry(
        !            69:     thread_t           thread,
        !            70:     unsigned int       index,
        !            71:     idt_entry_t                *desc
        !            72: )
        !            73: {
        !            74:     PCshared_t         shared = threadPCShared(thread);
        !            75:     unsigned int       byte_index = index * sizeof (ldt_entry_t);
        !            76:     
        !            77:     if (shared->IDT.length <= byte_index)
        !            78:        return (FALSE);
        !            79:        
        !            80:     return (fetch8Byte(thread, shared->IDT.address + byte_index, desc));
        !            81: }
        !            82: 
        !            83: static
        !            84: boolean_t
        !            85: fetch_desc(
        !            86:     thread_t           thread,
        !            87:     sel_t              sel,
        !            88:     dt_entry_t         *desc
        !            89: )
        !            90: {
        !            91:     if (sel.ti != SEL_LDT)
        !            92:        return (FALSE);
        !            93:        
        !            94:     return (fetch_LDT_entry(thread, sel.index, (ldt_entry_t *)desc));
        !            95: }
        !            96: 
        !            97: static __inline__
        !            98: vm_offset_t
        !            99: segment_base(
        !           100:     data_desc_t                *desc
        !           101: )
        !           102: {
        !           103:     conv_base_t                _base = { 0 };
        !           104:     
        !           105:     _base.fields.base00 = desc->base00;
        !           106:     _base.fields.base16 = desc->base16;
        !           107:     _base.fields.base24 = desc->base24;
        !           108:     
        !           109:     return (_base.word);
        !           110: }
        !           111: 
        !           112: static __inline__
        !           113: boolean_t
        !           114: fetch_segment_4byte(
        !           115:     thread_t           thread,
        !           116:     data_desc_t                *desc,
        !           117:     vm_offset_t                offset,
        !           118:     boolean_t          offsz,
        !           119:     unsigned int       *data
        !           120: )
        !           121: {
        !           122:     vm_offset_t                base = segment_base(desc);
        !           123: 
        !           124:     if (!offsz)
        !           125:        offset &= 0xffff;
        !           126:        
        !           127:     return (fetch4Byte(thread, base + offset, data));
        !           128: }
        !           129: 
        !           130: static
        !           131: boolean_t __inline__
        !           132: fetch_segment(
        !           133:     thread_t           thread,
        !           134:     data_desc_t                *desc,
        !           135:     vm_offset_t                offset,
        !           136:     boolean_t          offsz,
        !           137:     void               *data,
        !           138:     unsigned int       length
        !           139: )
        !           140: {
        !           141: #define sdata          ((unsigned short *)data)
        !           142:     vm_offset_t                base = segment_base(desc);
        !           143:     unsigned int       offmsk;
        !           144:     
        !           145:     if (offsz)
        !           146:        offmsk = 0xffffffff;
        !           147:     else
        !           148:        offmsk = 0xffff;
        !           149: 
        !           150:     thread->recover = (vm_offset_t)&&fault;
        !           151:     
        !           152:     while (length > 0) {
        !           153:        offset &= offmsk;
        !           154: 
        !           155:        asm volatile(
        !           156:            "movw %%fs:%1,%0"
        !           157:                    : "=q" (*sdata)
        !           158:                    : "m" (*(unsigned short *)(base + offset)));
        !           159:                    
        !           160:        sdata++; offset += sizeof (*sdata); length -= sizeof (*sdata);
        !           161:     }
        !           162:     
        !           163:     thread->recover = 0;
        !           164:     return (TRUE);
        !           165:     
        !           166: fault:
        !           167:     thread->recover = 0;
        !           168:     return (FALSE);
        !           169: 
        !           170: #undef sdata
        !           171: }
        !           172: 
        !           173: static __inline__
        !           174: boolean_t
        !           175: store_segment(
        !           176:     thread_t           thread,
        !           177:     data_desc_t                *desc,
        !           178:     vm_offset_t                offset,
        !           179:     boolean_t          offsz,
        !           180:     void               *data,
        !           181:     unsigned int       length
        !           182: )
        !           183: {
        !           184: #define sdata          ((unsigned short *)data)
        !           185:     vm_offset_t                base = segment_base(desc);
        !           186:     unsigned int       offmsk;
        !           187:     
        !           188:     if (offsz)
        !           189:        offmsk = 0xffffffff;
        !           190:     else
        !           191:        offmsk = 0xffff;
        !           192: 
        !           193:     thread->recover = (vm_offset_t)&&fault;
        !           194:     
        !           195:     while (length > 0) {
        !           196:        offset &= offmsk;
        !           197: 
        !           198:        asm volatile(
        !           199:            "movw %0,%%fs:%1"
        !           200:                    :
        !           201:                    : "r" (*sdata), "m" (*(unsigned short *)(base + offset)));
        !           202:                    
        !           203:        sdata++; offset += sizeof (*sdata); length -= sizeof (*sdata);
        !           204:     }
        !           205:     
        !           206:     thread->recover = 0;
        !           207:     return (TRUE);
        !           208:     
        !           209: fault:
        !           210:     thread->recover = 0;
        !           211:     return (FALSE);
        !           212: 
        !           213: #undef sdata
        !           214: }
        !           215: 
        !           216: static
        !           217: boolean_t
        !           218: handle_bop(
        !           219:     thread_t                   thread,
        !           220:     thread_saved_state_t       *state
        !           221: )
        !           222: {
        !           223:     PCcontext_t                context = threadPCContext(thread);
        !           224:     code_desc_t                code;
        !           225:     data_desc_t                stack;
        !           226:     unsigned int       inst;
        !           227:     unsigned char      bbyte;
        !           228:     
        !           229:     if (!fetch_desc(thread, state->frame.cs, (dt_entry_t *)&code))
        !           230:        return (FALSE);
        !           231:     
        !           232:     if (!fetch_segment_4byte(
        !           233:                        thread,
        !           234:                        (data_desc_t *)&code, state->frame.eip, code.opsz,
        !           235:                        &inst))
        !           236:        return (FALSE);
        !           237:        
        !           238:     if (*(unsigned short *)&inst != 0xC4C4)
        !           239:        return (FALSE);
        !           240:        
        !           241:     bbyte = *((unsigned char *)&inst + 2);
        !           242:        
        !           243:     if (bbyte == 0xFE) {
        !           244:        PCcancelTimers(context);
        !           245:        
        !           246:        context->callHandler = PC_HANDLE_EXIT;
        !           247:        
        !           248:        PCcallMonitor(thread, state);
        !           249:        /* NOTREACHED */
        !           250:     }
        !           251:     else if (bbyte == 0xFA) {
        !           252:        PCbopFA_t       args;
        !           253: 
        !           254:        if (!fetch_desc(thread, state->frame.ss, (dt_entry_t *)&stack))
        !           255:            return (FALSE);
        !           256:        
        !           257:        if (!fetch_segment(
        !           258:                        thread,
        !           259:                        &stack, state->frame.esp, stack.stksz,
        !           260:                        &args, sizeof (args)))
        !           261:            return (FALSE);
        !           262:            
        !           263:        return (PCbopFA(thread, state, &args));
        !           264:     }
        !           265:     else if (bbyte == 0xFC) {
        !           266:        PCbopFC_t       args;
        !           267: 
        !           268:        if (!fetch_desc(thread, state->frame.ss, (dt_entry_t *)&stack))
        !           269:            return (FALSE);
        !           270:        
        !           271:        if (!fetch_segment(
        !           272:                        thread,
        !           273:                        &stack, state->frame.esp, stack.stksz,
        !           274:                        &args, sizeof (args)))
        !           275:            return (FALSE);
        !           276:            
        !           277:        return (PCbopFC(thread, state, &args));
        !           278:        /* NOTREACHED */
        !           279:     }
        !           280:     else if (bbyte == 0xFD) {
        !           281:        PCbopFD_t       args;
        !           282: 
        !           283:        if (!fetch_desc(thread, state->frame.ss, (dt_entry_t *)&stack))
        !           284:            return (FALSE);
        !           285:        
        !           286:        if (!fetch_segment(
        !           287:                        thread,
        !           288:                        &stack, state->frame.esp, stack.stksz,
        !           289:                        &args, sizeof (args)))
        !           290:            return (FALSE);
        !           291:            
        !           292:        PCbopFD(thread, state, &args);
        !           293:        /* NOTREACHED */
        !           294:     }  
        !           295:     else {
        !           296:        context->trapNum = bbyte;
        !           297:        context->callHandler = PC_HANDLE_BOP;
        !           298:        
        !           299:        PCcallMonitor(thread, state);
        !           300:        /* NOTREACHED */
        !           301:     }
        !           302: }
        !           303: 
        !           304: static
        !           305: boolean_t
        !           306: emulate_CLI(
        !           307:     thread_t                   thread,
        !           308:     thread_saved_state_t       *state,
        !           309:     code_desc_t                        *desc
        !           310: )
        !           311: {
        !           312:     PCcontext_t                context = threadPCContext(thread);
        !           313: 
        !           314:     if (desc->opsz)    
        !           315:        state->frame.eip += 1;
        !           316:     else
        !           317:        (unsigned short)state->frame.eip += 1;
        !           318:        
        !           319:     context->IF_flag = FALSE;
        !           320:     
        !           321:     return (TRUE);
        !           322: }
        !           323: 
        !           324: static
        !           325: boolean_t
        !           326: emulate_STI(
        !           327:     thread_t                   thread,
        !           328:     thread_saved_state_t       *state,
        !           329:     code_desc_t                        *desc
        !           330: )
        !           331: {
        !           332:     PCcontext_t                context = threadPCContext(thread);
        !           333: 
        !           334:     if (desc->opsz)    
        !           335:        state->frame.eip += 1;
        !           336:     else
        !           337:        (unsigned short)state->frame.eip += 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
        !           349: boolean_t
        !           350: push_frame16_err_code(
        !           351:     thread_t                   thread,
        !           352:     thread_saved_state_t       *state,
        !           353:     boolean_t                  IF_flag,
        !           354:     err_code_t                 err
        !           355: )
        !           356: {
        !           357:     struct {
        !           358:        unsigned short  err;
        !           359:        unsigned short  ip;
        !           360:        sel_t           cs;
        !           361:        unsigned short  flags;
        !           362:     }                          frame;    
        !           363:     data_desc_t                        stack;
        !           364:        
        !           365:     if (!fetch_desc(thread, state->frame.ss, (dt_entry_t *)&stack))
        !           366:        return (FALSE);         /* not possible */
        !           367:        
        !           368:     frame.err = err_to_error_code(err);
        !           369: 
        !           370:     frame.ip = state->frame.eip;
        !           371:     frame.cs = state->frame.cs;
        !           372:     
        !           373:     frame.flags = state->frame.eflags;
        !           374:     if (IF_flag)
        !           375:        frame.flags |= EFL_IF;
        !           376:     else
        !           377:        frame.flags &= ~EFL_IF;
        !           378:        
        !           379:     if (!store_segment(
        !           380:                    thread,
        !           381:                    &stack,
        !           382:                    state->frame.esp - sizeof (frame), stack.stksz,
        !           383:                    &frame, sizeof (frame)))
        !           384:        return (FALSE);
        !           385: 
        !           386:     if (stack.stksz)
        !           387:        state->frame.esp -= sizeof (frame);
        !           388:     else 
        !           389:        (unsigned short)state->frame.esp -= sizeof (frame);
        !           390:     
        !           391:     return (TRUE);
        !           392: }
        !           393: 
        !           394: static
        !           395: boolean_t
        !           396: push_frame16(
        !           397:     thread_t                   thread,
        !           398:     thread_saved_state_t       *state,
        !           399:     boolean_t                  IF_flag
        !           400: )
        !           401: {
        !           402:     struct {
        !           403:        unsigned short  ip;
        !           404:        sel_t           cs;
        !           405:        unsigned short  flags;
        !           406:     }                          frame;    
        !           407:     data_desc_t                        stack;
        !           408:        
        !           409:     if (!fetch_desc(thread, state->frame.ss, (dt_entry_t *)&stack))
        !           410:        return (FALSE);         /* not possible */
        !           411: 
        !           412:     frame.ip = state->frame.eip;
        !           413:     frame.cs = state->frame.cs;
        !           414:     
        !           415:     frame.flags = state->frame.eflags;
        !           416:     if (IF_flag)
        !           417:        frame.flags |= EFL_IF;
        !           418:     else
        !           419:        frame.flags &= ~EFL_IF;
        !           420:        
        !           421:     if (!store_segment(
        !           422:                    thread,
        !           423:                    &stack,
        !           424:                    state->frame.esp - sizeof (frame), stack.stksz,
        !           425:                    &frame, sizeof (frame)))
        !           426:        return (FALSE);
        !           427: 
        !           428:     if (stack.stksz)
        !           429:        state->frame.esp -= sizeof (frame);
        !           430:     else 
        !           431:        (unsigned short)state->frame.esp -= sizeof (frame);
        !           432:     
        !           433:     return (TRUE);
        !           434: }
        !           435: 
        !           436: static
        !           437: boolean_t
        !           438: push_frame32_err_code(
        !           439:     thread_t                   thread,
        !           440:     thread_saved_state_t       *state,
        !           441:     boolean_t                  IF_flag,
        !           442:     err_code_t                 err
        !           443: )
        !           444: {
        !           445:     struct {
        !           446:        err_code_t      err;
        !           447:        unsigned int    eip;
        !           448:        sel_t           cs;
        !           449:        unsigned short          :16;
        !           450:        unsigned int    eflags;
        !           451:     }                          frame;    
        !           452:     data_desc_t                        stack;
        !           453:        
        !           454:     if (!fetch_desc(thread, state->frame.ss, (dt_entry_t *)&stack))
        !           455:        return (FALSE);         /* not possible */
        !           456:        
        !           457:     frame.err = err;
        !           458: 
        !           459:     frame.eip = state->frame.eip;
        !           460:     frame.cs = state->frame.cs;
        !           461:     
        !           462:     frame.eflags = state->frame.eflags;
        !           463:     if (IF_flag)
        !           464:        frame.eflags |= EFL_IF;
        !           465:     else
        !           466:        frame.eflags &= ~EFL_IF;
        !           467: 
        !           468:     if (!store_segment(
        !           469:                    thread,
        !           470:                    &stack,
        !           471:                    state->frame.esp - sizeof (frame), stack.stksz,
        !           472:                    &frame, sizeof (frame)))
        !           473:        return (FALSE);
        !           474: 
        !           475:     if (stack.stksz)
        !           476:        state->frame.esp -= sizeof (frame);
        !           477:     else 
        !           478:        (unsigned short)state->frame.esp -= sizeof (frame);
        !           479:     
        !           480:     return (TRUE);
        !           481: }
        !           482: 
        !           483: static
        !           484: boolean_t
        !           485: push_frame32(
        !           486:     thread_t                   thread,
        !           487:     thread_saved_state_t       *state,
        !           488:     boolean_t                  IF_flag
        !           489: )
        !           490: {
        !           491:     struct {
        !           492:        unsigned int    eip;
        !           493:        sel_t           cs;
        !           494:        unsigned short          :16;
        !           495:        unsigned int    eflags;
        !           496:     }                          frame;    
        !           497:     data_desc_t                        stack;
        !           498:        
        !           499:     if (!fetch_desc(thread, state->frame.ss, (dt_entry_t *)&stack))
        !           500:        return (FALSE);         /* not possible */
        !           501: 
        !           502:     frame.eip = state->frame.eip;
        !           503:     frame.cs = state->frame.cs;
        !           504:     
        !           505:     frame.eflags = state->frame.eflags;
        !           506:     if (IF_flag)
        !           507:        frame.eflags |= EFL_IF;
        !           508:     else
        !           509:        frame.eflags &= ~EFL_IF;
        !           510:        
        !           511:     if (!store_segment(
        !           512:                    thread,
        !           513:                    &stack,
        !           514:                    state->frame.esp - sizeof (frame), stack.stksz,
        !           515:                    &frame, sizeof (frame)))
        !           516:        return (FALSE);
        !           517:        
        !           518:     if (stack.stksz)
        !           519:        state->frame.esp -= sizeof (frame);
        !           520:     else 
        !           521:        (unsigned short)state->frame.esp -= sizeof (frame);
        !           522:     
        !           523:     return (TRUE);
        !           524: }
        !           525: 
        !           526: static __inline__
        !           527: void
        !           528: enter_gate(
        !           529:     except_frame_t     *frame,
        !           530:     trap_gate_t                *gate,
        !           531:     boolean_t          preserve_trace
        !           532: )
        !           533: {
        !           534:     conv_offset_t              _offset = { 0 };
        !           535:     
        !           536:     _offset.fields.offset00 = gate->offset00;
        !           537:     _offset.fields.offset16 = gate->offset16;
        !           538:     
        !           539:     frame->eip = _offset.word;
        !           540:     frame->cs = gate->seg;
        !           541: 
        !           542:     if (!preserve_trace)       
        !           543:        frame->eflags &= ~EFL_TF;
        !           544: }
        !           545: 
        !           546: static
        !           547: boolean_t
        !           548: emulate_exception(
        !           549:     thread_t                   thread,
        !           550:     thread_saved_state_t       *state,
        !           551:     int                                trapno,
        !           552:     err_code_t                 err,
        !           553:     boolean_t                  inhibit_err_code
        !           554: )
        !           555: {
        !           556:     PCcontext_t                        context;
        !           557:     trap_gate_t                        gate;
        !           558:     boolean_t                  is_intr, is_32bit;
        !           559:     code_desc_t                        code;
        !           560:     
        !           561:     context = threadPCContext(thread);
        !           562:     
        !           563:     if (!fetch_IDT_entry(thread, trapno, (idt_entry_t *)&gate))
        !           564:        return (FALSE);         /* GP(trapno*8+2+EXT) */
        !           565: 
        !           566:     switch (gate.type) {
        !           567:        
        !           568:     case DESC_INTR_GATE:
        !           569:        is_32bit = TRUE;
        !           570:        is_intr = TRUE;
        !           571:        break;
        !           572:     
        !           573:     case DESC_TRAP_GATE:
        !           574:        is_32bit = TRUE;
        !           575:        is_intr = FALSE;
        !           576:        break;
        !           577:        
        !           578:     case 0x06:
        !           579:        is_32bit = FALSE;
        !           580:        is_intr = TRUE;
        !           581:        break;
        !           582:        
        !           583:     case 0x07:
        !           584:        is_32bit = FALSE;
        !           585:        is_intr = FALSE;
        !           586:        break;
        !           587:        
        !           588:     default:
        !           589:        return (FALSE);         /* GP(trapno*8+2+EXT) */
        !           590:     }
        !           591:        
        !           592:     if (!gate.present)
        !           593:        return (FALSE);         /* NP(trapno*8+2+EXT) */
        !           594:        
        !           595:     if (!fetch_desc(thread, gate.seg, (dt_entry_t *)&code))
        !           596:        return (FALSE);         /* GP(selector+EXT) */
        !           597:        
        !           598:     if ((code.type & 0x18) != 0x18) // if (!code)
        !           599:        return (FALSE);         /* GP(selector+EXT) */
        !           600:        
        !           601:     if (!code.present)
        !           602:        return (FALSE);         /* NP(selector+EXT) */
        !           603:        
        !           604:     if (inhibit_err_code || (trapno < 8) || trapno == 16 || (trapno > 17)) {
        !           605:        if (is_32bit) {
        !           606:            if (!push_frame32(thread, state, context->IF_flag))
        !           607:                return (FALSE);
        !           608:        }
        !           609:        else {
        !           610:            if (!push_frame16(thread, state, context->IF_flag))
        !           611:                return (FALSE);
        !           612:        }
        !           613:     }
        !           614:     else
        !           615:     {
        !           616:        if (is_32bit) {
        !           617:            if (!push_frame32_err_code(thread, state, context->IF_flag, err))
        !           618:                return (FALSE);
        !           619:        }
        !           620:        else {
        !           621:            if (!push_frame16_err_code(thread, state, context->IF_flag, err))
        !           622:                return (FALSE);
        !           623:        }
        !           624:     }
        !           625: 
        !           626: #define preserveTrace ((context->debugOptions & PC_DEBUG_PRESERVE_TRACE) != 0)
        !           627:     enter_gate(&state->frame, &gate, preserveTrace);
        !           628: #undef preserveTrace
        !           629:     
        !           630:     if (is_intr)
        !           631:        context->IF_flag = FALSE;
        !           632: 
        !           633:     return (TRUE);
        !           634: }
        !           635: 
        !           636: static
        !           637: boolean_t
        !           638: handle_exception(
        !           639:     thread_t                   thread,
        !           640:     thread_saved_state_t       *state
        !           641: )
        !           642: {
        !           643:     PCshared_t                 shared;
        !           644:     PCcontext_t                        context;
        !           645:     
        !           646:     shared = threadPCShared(thread);
        !           647:     context = currentContext(shared);
        !           648:     
        !           649:     if (maskIsSet(&shared->faultMask, state->trapno)) {
        !           650:        context->trapNum = state->trapno;
        !           651:        context->errCode = err_to_error_code(state->frame.err);
        !           652:        context->callHandler = PC_HANDLE_FAULT;
        !           653:        
        !           654:        PCcallMonitor(thread, state);
        !           655:        /* NOTREACHED */
        !           656:     }
        !           657:        
        !           658:     if (!emulate_exception(
        !           659:                        thread,
        !           660:                        state, state->trapno, state->frame.err,
        !           661:                        FALSE))
        !           662:        return (FALSE);
        !           663:     
        !           664:     return (TRUE);
        !           665: }
        !           666: 
        !           667: static
        !           668: boolean_t
        !           669: emulate_INTn(
        !           670:     thread_t                   thread,
        !           671:     thread_saved_state_t       *state,
        !           672:     code_desc_t                        *desc,
        !           673:     unsigned int               inst
        !           674: )
        !           675: {
        !           676:     PCshared_t                 shared;
        !           677:     PCcontext_t                        context;
        !           678:     unsigned char              trapno;
        !           679:     err_code_t                 err = { 0 };
        !           680: 
        !           681:     shared = threadPCShared(thread);
        !           682:     context = currentContext(shared);
        !           683:     
        !           684:     trapno = *((unsigned char *)&inst + 1);
        !           685:        
        !           686:     if (maskIsSet(&shared->intNMask, trapno)) {
        !           687:        context->trapNum = trapno;
        !           688:        context->errCode = 0;
        !           689:        if (trapno <= 7)
        !           690:            context->callHandler = PC_HANDLE_FAULT;
        !           691:        else
        !           692:            context->callHandler = PC_HANDLE_INTN;
        !           693:        
        !           694:        PCcallMonitor(thread, state);
        !           695:        /* NOTREACHED */
        !           696:     }
        !           697: 
        !           698:     if (desc->opsz)    
        !           699:        state->frame.eip += 2;
        !           700:     else
        !           701:        (unsigned short)state->frame.eip += 2;
        !           702:     
        !           703:     if (!emulate_exception(thread, state, trapno, err, TRUE)) {
        !           704:        if (desc->opsz) 
        !           705:            state->frame.eip -= 2;
        !           706:        else
        !           707:            (unsigned short)state->frame.eip -= 2;
        !           708:        return (FALSE);
        !           709:     }
        !           710:     
        !           711:     return (TRUE);
        !           712: }
        !           713: 
        !           714: static
        !           715: boolean_t
        !           716: emulate_instruction(
        !           717:     thread_t                   thread,
        !           718:     thread_saved_state_t       *state
        !           719: )
        !           720: {
        !           721:     code_desc_t                code;
        !           722:     unsigned int       inst;
        !           723:     unsigned char      ibyte;
        !           724:     
        !           725:     if (!fetch_desc(thread, state->frame.cs, (dt_entry_t *)&code))
        !           726:        return (FALSE);
        !           727:        
        !           728:     if (!fetch_segment_4byte(
        !           729:                        thread,
        !           730:                        (data_desc_t *)&code, state->frame.eip, code.opsz,
        !           731:                        &inst))
        !           732:        return (FALSE);
        !           733:        
        !           734:     ibyte = *(unsigned char *)&inst;
        !           735:        
        !           736:     if (ibyte == 0xCD)
        !           737:        return (emulate_INTn(thread, state, &code, inst));
        !           738:        
        !           739:     if (ibyte == 0xFA)
        !           740:        return (emulate_CLI(thread, state, &code));
        !           741:        
        !           742:     if (ibyte == 0xFB)
        !           743:        return (emulate_STI(thread, state, &code));
        !           744:        
        !           745:     return (FALSE);
        !           746: }
        !           747: 
        !           748: boolean_t
        !           749: PCemulatePROT(
        !           750:     thread_t                   thread,
        !           751:     thread_saved_state_t       *state
        !           752: )
        !           753: {
        !           754:     if (state->trapno == T_GENERAL_PROTECTION) {
        !           755:        if (!emulate_instruction(thread,state))
        !           756:            return handle_exception(thread, state);
        !           757:        else
        !           758:            return TRUE;
        !           759:     }
        !           760:     else
        !           761:     if (state->trapno == T_INVALID_OPCODE) {
        !           762:        if (!handle_bop(thread, state))
        !           763:            return handle_exception(thread, state);
        !           764:        else
        !           765:            return TRUE;
        !           766:     }
        !           767:     else
        !           768:        return handle_exception(thread, state);
        !           769: }

unix.superglobalmegacorp.com

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