VirtualBox

Changeset 1134 in vbox for trunk/src/VBox/VMM


Ignore:
Timestamp:
Mar 1, 2007 1:40:02 PM (18 years ago)
Author:
vboxsync
Message:

Added CPUMGCCallV86Code.
PATM cleanup.

Location:
trunk/src/VBox/VMM
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/PATM/VMMAll/PATMAll.cpp

    r1129 r1134  
    455455
    456456/**
    457  * Checks if the illegal instruction was caused by a patched instruction
    458  *
    459  * @returns VBox status
    460  *
    461  * @param   pVM         The VM handle.
    462  * @param   pCtxCore    The relevant core context.
    463  */
    464 PATMDECL(int) PATMHandleIllegalInstrTrap(PVM pVM, PCPUMCTXCORE pRegFrame)
    465 {
    466     PPATMPATCHREC pRec;
    467     int rc;
    468 
    469     /* Very important check -> otherwise we have a security leak. */
    470     AssertReturn((pRegFrame->ss & X86_SEL_RPL) == 1, VERR_ACCESS_DENIED);
    471     Assert(PATMIsPatchGCAddr(pVM, (RTGCPTR)pRegFrame->eip));
    472 
    473     /* OP_ILLUD2 in PATM generated code? */
    474     if (CTXSUFF(pVM->patm.s.pGCState)->uPendingAction)
    475     {
    476         LogFlow(("PATMGC: Pending action %x at %VGv\n", CTXSUFF(pVM->patm.s.pGCState)->uPendingAction, pRegFrame->eip));
    477 
    478         /* Private PATM interface (@todo hack due to lack of anything generic). */
    479         /* Parameters:
    480          *  eax = Pending action (currently PATM_ACTION_LOOKUP_ADDRESS)
    481          *  ecx = PATM_ACTION_MAGIC
    482          */
    483         if (    (pRegFrame->eax & CTXSUFF(pVM->patm.s.pGCState)->uPendingAction)
    484             &&   pRegFrame->ecx == PATM_ACTION_MAGIC
    485            )
    486         {
    487             CTXSUFF(pVM->patm.s.pGCState)->uPendingAction = 0;
    488 
    489             switch (pRegFrame->eax)
    490             {
    491             case PATM_ACTION_LOOKUP_ADDRESS:
    492             {
    493                 /* Parameters:
    494                  *  edx = GC address to find
    495                  *  edi = PATCHJUMPTABLE ptr
    496                  */
    497                 AssertMsg(!pRegFrame->edi || PATMIsPatchGCAddr(pVM, (RTGCPTR)pRegFrame->edi), ("edx = %VGv\n", pRegFrame->edi));
    498 
    499                 Log(("PATMGC: lookup %VGv jump table=%VGv\n", pRegFrame->edx, pRegFrame->edi));
    500 
    501                 pRec = PATMQueryFunctionPatch(pVM, (RTGCPTR)(pRegFrame->edx));
    502                 if (pRec)
    503                 {
    504                     if (pRec->patch.uState == PATCH_ENABLED)
    505                     {
    506                         RTGCUINTPTR pRelAddr = pRec->patch.pPatchBlockOffset;   /* make it relative */
    507                         rc = PATMAddBranchToLookupCache(pVM, (RTGCPTR)pRegFrame->edi, (RTGCPTR)pRegFrame->edx, pRelAddr);
    508                         if (rc == VINF_SUCCESS)
    509                         {
    510                             pRegFrame->eip += PATM_ILLEGAL_INSTR_SIZE;
    511                             pRegFrame->eax = pRelAddr;
    512                             STAM_COUNTER_INC(&pVM->patm.s.StatFunctionFound);
    513                             return VINF_SUCCESS;
    514                         }
    515                         AssertFailed();
    516                     }
    517                     else
    518                     {
    519                         pRegFrame->eip += PATM_ILLEGAL_INSTR_SIZE;
    520                         pRegFrame->eax = 0;     /* make it fault */
    521                         STAM_COUNTER_INC(&pVM->patm.s.StatFunctionNotFound);
    522                         return VINF_SUCCESS;
    523                     }
    524                 }
    525                 else
    526                 {
    527 #if 0
    528                     if (pRegFrame->edx == 0x806eca98)
    529                     {
    530                         pRegFrame->eip += PATM_ILLEGAL_INSTR_SIZE;
    531                         pRegFrame->eax = 0;     /* make it fault */
    532                         STAM_COUNTER_INC(&pVM->patm.s.StatFunctionNotFound);
    533                         return VINF_SUCCESS;
    534                     }
    535 #endif
    536                     STAM_COUNTER_INC(&pVM->patm.s.StatFunctionNotFound);
    537                     return VINF_PATM_DUPLICATE_FUNCTION;
    538                 }
    539             }
    540 
    541             case PATM_ACTION_DISPATCH_PENDING_IRQ:
    542                 /* Parameters:
    543                  *  edi = GC address to jump to
    544                  */
    545                 Log(("PATMGC: Dispatch pending interrupt; eip=%VGv->%VGv\n", pRegFrame->eip, pRegFrame->edi));
    546 
    547                 /* Change EIP to the guest address the patch would normally jump to after setting IF. */
    548                 pRegFrame->eip = pRegFrame->edi;
    549 
    550                 Assert(pVM->patm.s.CTXSUFF(pGCState)->Restore.uFlags == (PATM_RESTORE_EAX|PATM_RESTORE_ECX|PATM_RESTORE_EDI));
    551                 Assert(pVM->patm.s.CTXSUFF(pGCState)->fPIF == 0);
    552 
    553                 pRegFrame->eax = pVM->patm.s.CTXSUFF(pGCState)->Restore.uEAX;
    554                 pRegFrame->ecx = pVM->patm.s.CTXSUFF(pGCState)->Restore.uECX;
    555                 pRegFrame->edi = pVM->patm.s.CTXSUFF(pGCState)->Restore.uEDI;
    556 
    557                 pVM->patm.s.CTXSUFF(pGCState)->Restore.uFlags = 0;
    558 
    559                 /* We are no longer executing PATM code; set PIF again. */
    560                 pVM->patm.s.CTXSUFF(pGCState)->fPIF = 1;
    561 
    562                 STAM_COUNTER_INC(&pVM->patm.s.StatCheckPendingIRQ);
    563 
    564                 /* The caller will call trpmGCExitTrap, which will dispatch pending interrupts for us. */
    565                 return VINF_SUCCESS;
    566 
    567             case PATM_ACTION_PENDING_IRQ_AFTER_IRET:
    568                 /* Parameters:
    569                  *  edi = GC address to jump to
    570                  */
    571                 Log(("PATMGC: Dispatch pending interrupt (iret); eip=%VGv->%VGv\n", pRegFrame->eip, pRegFrame->edi));
    572                 Assert(pVM->patm.s.CTXSUFF(pGCState)->Restore.uFlags == (PATM_RESTORE_EAX|PATM_RESTORE_ECX|PATM_RESTORE_EDI));
    573                 Assert(pVM->patm.s.CTXSUFF(pGCState)->fPIF == 0);
    574 
    575                 /* Change EIP to the guest address of the iret. */
    576                 pRegFrame->eip = pRegFrame->edi;
    577 
    578                 pRegFrame->eax = pVM->patm.s.CTXSUFF(pGCState)->Restore.uEAX;
    579                 pRegFrame->ecx = pVM->patm.s.CTXSUFF(pGCState)->Restore.uECX;
    580                 pRegFrame->edi = pVM->patm.s.CTXSUFF(pGCState)->Restore.uEDI;
    581                 pVM->patm.s.CTXSUFF(pGCState)->Restore.uFlags = 0;
    582 
    583                 /* We are no longer executing PATM code; set PIF again. */
    584                 pVM->patm.s.CTXSUFF(pGCState)->fPIF = 1;
    585 
    586                 return VINF_PATM_PENDING_IRQ_AFTER_IRET;
    587 
    588             case PATM_ACTION_DO_V86_IRET:
    589             {
    590                 Log(("PATMGC: Do iret to V86 code; eip=%VGv\n", pRegFrame->eip));
    591                 Assert(pVM->patm.s.CTXSUFF(pGCState)->Restore.uFlags == (PATM_RESTORE_EAX|PATM_RESTORE_ECX));
    592                 Assert(pVM->patm.s.CTXSUFF(pGCState)->fPIF == 0);
    593 
    594                 pRegFrame->eax = pVM->patm.s.CTXSUFF(pGCState)->Restore.uEAX;
    595                 pRegFrame->ecx = pVM->patm.s.CTXSUFF(pGCState)->Restore.uECX;
    596                 pVM->patm.s.CTXSUFF(pGCState)->Restore.uFlags = 0;
    597 
    598                 rc = EMInterpretIret(pVM, pRegFrame);
    599                 if (VBOX_SUCCESS(rc))
    600                 {
    601                     STAM_COUNTER_INC(&pVM->patm.s.StatEmulIret);
    602 
    603                     /* We are no longer executing PATM code; set PIF again. */
    604                     pVM->patm.s.CTXSUFF(pGCState)->fPIF = 1;
    605                 }
    606                 else
    607                     STAM_COUNTER_INC(&pVM->patm.s.StatEmulIretFailed);
    608                 return rc;
    609             }
    610 
    611 #ifdef DEBUG
    612             case PATM_ACTION_LOG_CLI:
    613                 Log(("PATMGC: CLI at %VGv (current IF=%d iopl=%d)\n", pRegFrame->eip, !!(pVM->patm.s.CTXSUFF(pGCState)->uVMFlags & X86_EFL_IF), X86_EFL_GET_IOPL(pVM->patm.s.CTXSUFF(pGCState)->uVMFlags) ));
    614                 pRegFrame->eip += PATM_ILLEGAL_INSTR_SIZE;
    615                 return VINF_SUCCESS;
    616 
    617             case PATM_ACTION_LOG_STI:
    618                 Log(("PATMGC: STI at %VGv (current IF=%d iopl=%d)\n", pRegFrame->eip, !!(pVM->patm.s.CTXSUFF(pGCState)->uVMFlags & X86_EFL_IF), X86_EFL_GET_IOPL(pVM->patm.s.CTXSUFF(pGCState)->uVMFlags) ));
    619                 pRegFrame->eip += PATM_ILLEGAL_INSTR_SIZE;
    620                 return VINF_SUCCESS;
    621 
    622             case PATM_ACTION_LOG_POPF_IF1:
    623                 Log(("PATMGC: POPF setting IF at %VGv (current IF=%d iopl=%d)\n", pRegFrame->eip, !!(pVM->patm.s.CTXSUFF(pGCState)->uVMFlags & X86_EFL_IF), X86_EFL_GET_IOPL(pVM->patm.s.CTXSUFF(pGCState)->uVMFlags)));
    624                 pRegFrame->eip += PATM_ILLEGAL_INSTR_SIZE;
    625                 return VINF_SUCCESS;
    626 
    627             case PATM_ACTION_LOG_POPF_IF0:
    628                 Log(("PATMGC: POPF at %VGv (current IF=%d iopl=%d)\n", pRegFrame->eip, !!(pVM->patm.s.CTXSUFF(pGCState)->uVMFlags & X86_EFL_IF), X86_EFL_GET_IOPL(pVM->patm.s.CTXSUFF(pGCState)->uVMFlags)));
    629                 pRegFrame->eip += PATM_ILLEGAL_INSTR_SIZE;
    630                 return VINF_SUCCESS;
    631 
    632             case PATM_ACTION_LOG_PUSHF:
    633                 Log(("PATMGC: PUSHF at %VGv (current IF=%d iopl=%d)\n", pRegFrame->eip, !!(pVM->patm.s.CTXSUFF(pGCState)->uVMFlags & X86_EFL_IF), X86_EFL_GET_IOPL(pVM->patm.s.CTXSUFF(pGCState)->uVMFlags) ));
    634                 pRegFrame->eip += PATM_ILLEGAL_INSTR_SIZE;
    635                 return VINF_SUCCESS;
    636 
    637             case PATM_ACTION_LOG_IF1:
    638                 Log(("PATMGC: IF=1 escape from %VGv\n", pRegFrame->eip));
    639                 pRegFrame->eip += PATM_ILLEGAL_INSTR_SIZE;
    640                 return VINF_SUCCESS;
    641 
    642             case PATM_ACTION_LOG_IRET:
    643             {
    644 #ifdef IN_GC
    645                 char    *pIretFrame = (char *)pRegFrame->edx;
    646                 uint32_t eip, selCS, uEFlags;
    647 
    648                 rc  = MMGCRamRead(pVM, &eip,     pIretFrame, 4);
    649                 rc |= MMGCRamRead(pVM, &selCS,   pIretFrame + 4, 4);
    650                 rc |= MMGCRamRead(pVM, &uEFlags, pIretFrame + 8, 4);
    651                 if (rc == VINF_SUCCESS)
    652                 {
    653                     if (    (uEFlags & X86_EFL_VM)
    654                         ||  (selCS & X86_SEL_RPL) == 3)
    655                     {
    656                         uint32_t selSS, esp;
    657 
    658                         rc |= MMGCRamRead(pVM, &esp,     pIretFrame + 12, 4);
    659                         rc |= MMGCRamRead(pVM, &selSS,   pIretFrame + 16, 4);
    660 
    661                         if (uEFlags & X86_EFL_VM)
    662                         {
    663                             uint32_t selDS, selES, selFS, selGS;
    664                             rc  = MMGCRamRead(pVM, &selES,   pIretFrame + 20, 4);
    665                             rc |= MMGCRamRead(pVM, &selDS,   pIretFrame + 24, 4);
    666                             rc |= MMGCRamRead(pVM, &selFS,   pIretFrame + 28, 4);
    667                             rc |= MMGCRamRead(pVM, &selGS,   pIretFrame + 32, 4);
    668                             if (rc == VINF_SUCCESS)
    669                             {
    670                                 Log(("PATMGC: IRET->VM stack frame: return address %04X:%VGv eflags=%08x ss:esp=%04X:%VGv\n", selCS, eip, uEFlags, selSS, esp));
    671                                 Log(("PATMGC: IRET->VM stack frame: DS=%04X ES=%04X FS=%04X GS=%04X\n", selDS, selES, selFS, selGS));
    672                             }
    673                         }
    674                         else
    675                             Log(("PATMGC: IRET stack frame: return address %04X:%VGv eflags=%08x ss:esp=%04X:%VGv\n", selCS, eip, uEFlags, selSS, esp));
    676                     }
    677                     else
    678                         Log(("PATMGC: IRET stack frame: return address %04X:%VGv eflags=%08x\n", selCS, eip, uEFlags));
    679                 }
    680 #endif
    681                 Log(("PATMGC: IRET from %VGv (IF->1) current eflags=%x\n", pRegFrame->eip, pVM->patm.s.CTXSUFF(pGCState)->uVMFlags));
    682                 pRegFrame->eip += PATM_ILLEGAL_INSTR_SIZE;
    683                 return VINF_SUCCESS;
    684             }
    685 
    686             case PATM_ACTION_LOG_RET:
    687                 Log(("PATMGC: RET to %VGv ESP=%VGv iopl=%d\n", pRegFrame->edx, pRegFrame->ebx, X86_EFL_GET_IOPL(pVM->patm.s.CTXSUFF(pGCState)->uVMFlags)));
    688                 pRegFrame->eip += PATM_ILLEGAL_INSTR_SIZE;
    689                 return VINF_SUCCESS;
    690 
    691             case PATM_ACTION_LOG_CALL:
    692                 Log(("PATMGC: CALL to %VGv return addr %VGv ESP=%VGv iopl=%d\n", pVM->patm.s.CTXSUFF(pGCState)->GCCallPatchTargetAddr, pVM->patm.s.CTXSUFF(pGCState)->GCCallReturnAddr, pRegFrame->edx, X86_EFL_GET_IOPL(pVM->patm.s.CTXSUFF(pGCState)->uVMFlags)));
    693                 pRegFrame->eip += PATM_ILLEGAL_INSTR_SIZE;
    694                 return VINF_SUCCESS;
    695 #endif
    696             default:
    697                 AssertFailed();
    698                 break;
    699             }
    700         }
    701         else
    702             AssertFailed();
    703         CTXSUFF(pVM->patm.s.pGCState)->uPendingAction = 0;
    704     }
    705     AssertMsgFailed(("Unexpected OP_ILLUD2 in patch code at %VGv (pending action %x)!!!!\n", pRegFrame->eip, CTXSUFF(pVM->patm.s.pGCState)->uPendingAction));
    706     return VINF_EM_RAW_EMULATE_INSTR;
    707 }
    708 
    709 /**
    710  * Checks if the int 3 was caused by a patched instruction
    711  *
    712  * @returns VBox status
    713  *
    714  * @param   pVM         The VM handle.
    715  * @param   pCtxCore    The relevant core context.
    716  */
    717 PATMDECL(int) PATMHandleInt3PatchTrap(PVM pVM, PCPUMCTXCORE pRegFrame)
    718 {
    719     PPATMPATCHREC pRec;
    720     int rc;
    721 
    722     Assert((pRegFrame->ss & X86_SEL_RPL) == 1);
    723 
    724     /* Int 3 in PATM generated code? (most common case) */
    725     if (PATMIsPatchGCAddr(pVM, (RTGCPTR)pRegFrame->eip))
    726     {
    727         /* @note hardcoded assumption about it being a single byte int 3 instruction. */
    728         pRegFrame->eip--;
    729         return VINF_PATM_PATCH_INT3;
    730     }
    731 
    732     /** @todo could use simple caching here to speed things up. */
    733     pRec = (PPATMPATCHREC)RTAvloGCPtrGet(&CTXSUFF(pVM->patm.s.PatchLookupTree)->PatchTree, (RTGCPTR)(pRegFrame->eip - 1));  /* eip is pointing to the instruction *after* 'int 3' already */
    734     if (pRec && pRec->patch.uState == PATCH_ENABLED)
    735     {
    736         if (pRec->patch.flags & PATMFL_INT3_REPLACEMENT_BLOCK)
    737         {
    738             Assert(pRec->patch.opcode == OP_CLI);
    739             /* This is a special cli block that was turned into an int 3 patch. We jump to the generated code manually. */
    740             pRegFrame->eip = (uint32_t)PATCHCODE_PTR_GC(&pRec->patch);
    741             STAM_COUNTER_INC(&pVM->patm.s.StatInt3BlockRun);
    742             return VINF_SUCCESS;
    743         }
    744         else
    745         if (pRec->patch.flags & PATMFL_INT3_REPLACEMENT)
    746         {
    747             uint32_t    size, cbOp;
    748             DISCPUSTATE cpu;
    749 
    750             /* eip is pointing to the instruction *after* 'int 3' already */
    751             pRegFrame->eip = pRegFrame->eip - 1;
    752 
    753             PATM_STAT_RUN_INC(&pRec->patch);
    754 
    755             Log(("PATMHandleInt3PatchTrap found int3 for %s at %VGv\n", patmGetInstructionString(pRec->patch.opcode, 0), pRegFrame->eip));
    756 
    757             switch(pRec->patch.opcode)
    758             {
    759             case OP_CPUID:
    760             case OP_IRET:
    761                 break;
    762 
    763             case OP_STR:
    764             case OP_SGDT:
    765             case OP_SLDT:
    766             case OP_SIDT:
    767             case OP_LSL:
    768             case OP_LAR:
    769             case OP_SMSW:
    770             case OP_VERW:
    771             case OP_VERR:
    772             default:
    773                 PATM_STAT_FAULT_INC(&pRec->patch);
    774                 pRec->patch.cTraps++;
    775                 return VINF_EM_RAW_EMULATE_INSTR;
    776             }
    777 
    778             cpu.mode = SELMIsSelector32Bit(pVM, pRegFrame->cs, 0) ? CPUMODE_32BIT : CPUMODE_16BIT;
    779             if(cpu.mode != CPUMODE_32BIT)
    780             {
    781                 AssertFailed();
    782                 return VINF_EM_RAW_EMULATE_INSTR;
    783             }
    784             rc = DISCoreOne(&cpu, (RTUINTPTR)&pRec->patch.aPrivInstr[0], &cbOp);
    785             if (VBOX_FAILURE(rc))
    786             {
    787                 Log(("DISCoreOne failed with %Vrc\n", rc));
    788                 PATM_STAT_FAULT_INC(&pRec->patch);
    789                 pRec->patch.cTraps++;
    790                 return VINF_EM_RAW_EMULATE_INSTR;
    791             }
    792 
    793             rc = EMInterpretInstructionCPU(pVM, &cpu, pRegFrame, 0 /* not relevant here */, &size);
    794             if (rc != VINF_SUCCESS)
    795             {
    796                 Log(("EMInterpretInstructionCPU failed with %Vrc\n", rc));
    797                 PATM_STAT_FAULT_INC(&pRec->patch);
    798                 pRec->patch.cTraps++;
    799                 return VINF_EM_RAW_EMULATE_INSTR;
    800             }
    801 
    802             pRegFrame->eip += cpu.opsize;
    803             return VINF_SUCCESS;
    804         }
    805     }
    806     return VERR_PATCH_NOT_FOUND;
    807 }
    808 
    809 /**
    810457 * Adds branch pair to the lookup cache of the particular branch instruction
    811458 *
     
    816463 * @param   pRelBranchPatch     Relative duplicated function address
    817464 */
    818 int PATMAddBranchToLookupCache(PVM pVM, RTGCPTR pJumpTableGC, RTGCPTR pBranchTarget, RTGCUINTPTR pRelBranchPatch)
     465PATMDECL(int) PATMAddBranchToLookupCache(PVM pVM, RTGCPTR pJumpTableGC, RTGCPTR pBranchTarget, RTGCUINTPTR pRelBranchPatch)
    819466{
    820467    PPATCHJUMPTABLE pJumpTable;
     
    872519}
    873520
     521
    874522/**
    875523 * Return the name of the patched instruction
  • trunk/src/VBox/VMM/PATM/VMMGC/PATMGC.cpp

    r730 r1134  
    3535#include <iprt/avl.h>
    3636#include "PATMInternal.h"
     37#include "PATMA.h"
    3738#include <VBox/vm.h>
    3839#include <VBox/dbg.h>
     40#include <VBox/dis.h>
     41#include <VBox/disopcode.h>
     42#include <VBox/em.h>
    3943#include <VBox/err.h>
    40 #include <VBox/em.h>
     44#include <VBox/selm.h>
    4145#include <VBox/log.h>
    4246#include <iprt/assert.h>
     
    141145    return VERR_PATCH_NOT_FOUND;
    142146}
     147
     148
     149/**
     150 * Checks if the illegal instruction was caused by a patched instruction
     151 *
     152 * @returns VBox status
     153 *
     154 * @param   pVM         The VM handle.
     155 * @param   pCtxCore    The relevant core context.
     156 */
     157PATMDECL(int) PATMGCHandleIllegalInstrTrap(PVM pVM, PCPUMCTXCORE pRegFrame)
     158{
     159    PPATMPATCHREC pRec;
     160    int rc;
     161
     162    /* Very important check -> otherwise we have a security leak. */
     163    AssertReturn((pRegFrame->ss & X86_SEL_RPL) == 1, VERR_ACCESS_DENIED);
     164    Assert(PATMIsPatchGCAddr(pVM, (RTGCPTR)pRegFrame->eip));
     165
     166    /* OP_ILLUD2 in PATM generated code? */
     167    if (CTXSUFF(pVM->patm.s.pGCState)->uPendingAction)
     168    {
     169        LogFlow(("PATMGC: Pending action %x at %VGv\n", CTXSUFF(pVM->patm.s.pGCState)->uPendingAction, pRegFrame->eip));
     170
     171        /* Private PATM interface (@todo hack due to lack of anything generic). */
     172        /* Parameters:
     173         *  eax = Pending action (currently PATM_ACTION_LOOKUP_ADDRESS)
     174         *  ecx = PATM_ACTION_MAGIC
     175         */
     176        if (    (pRegFrame->eax & CTXSUFF(pVM->patm.s.pGCState)->uPendingAction)
     177            &&   pRegFrame->ecx == PATM_ACTION_MAGIC
     178           )
     179        {
     180            CTXSUFF(pVM->patm.s.pGCState)->uPendingAction = 0;
     181
     182            switch (pRegFrame->eax)
     183            {
     184            case PATM_ACTION_LOOKUP_ADDRESS:
     185            {
     186                /* Parameters:
     187                 *  edx = GC address to find
     188                 *  edi = PATCHJUMPTABLE ptr
     189                 */
     190                AssertMsg(!pRegFrame->edi || PATMIsPatchGCAddr(pVM, (RTGCPTR)pRegFrame->edi), ("edx = %VGv\n", pRegFrame->edi));
     191
     192                Log(("PATMGC: lookup %VGv jump table=%VGv\n", pRegFrame->edx, pRegFrame->edi));
     193
     194                pRec = PATMQueryFunctionPatch(pVM, (RTGCPTR)(pRegFrame->edx));
     195                if (pRec)
     196                {
     197                    if (pRec->patch.uState == PATCH_ENABLED)
     198                    {
     199                        RTGCUINTPTR pRelAddr = pRec->patch.pPatchBlockOffset;   /* make it relative */
     200                        rc = PATMAddBranchToLookupCache(pVM, (RTGCPTR)pRegFrame->edi, (RTGCPTR)pRegFrame->edx, pRelAddr);
     201                        if (rc == VINF_SUCCESS)
     202                        {
     203                            pRegFrame->eip += PATM_ILLEGAL_INSTR_SIZE;
     204                            pRegFrame->eax = pRelAddr;
     205                            STAM_COUNTER_INC(&pVM->patm.s.StatFunctionFound);
     206                            return VINF_SUCCESS;
     207                        }
     208                        AssertFailed();
     209                    }
     210                    else
     211                    {
     212                        pRegFrame->eip += PATM_ILLEGAL_INSTR_SIZE;
     213                        pRegFrame->eax = 0;     /* make it fault */
     214                        STAM_COUNTER_INC(&pVM->patm.s.StatFunctionNotFound);
     215                        return VINF_SUCCESS;
     216                    }
     217                }
     218                else
     219                {
     220#if 0
     221                    if (pRegFrame->edx == 0x806eca98)
     222                    {
     223                        pRegFrame->eip += PATM_ILLEGAL_INSTR_SIZE;
     224                        pRegFrame->eax = 0;     /* make it fault */
     225                        STAM_COUNTER_INC(&pVM->patm.s.StatFunctionNotFound);
     226                        return VINF_SUCCESS;
     227                    }
     228#endif
     229                    STAM_COUNTER_INC(&pVM->patm.s.StatFunctionNotFound);
     230                    return VINF_PATM_DUPLICATE_FUNCTION;
     231                }
     232            }
     233
     234            case PATM_ACTION_DISPATCH_PENDING_IRQ:
     235                /* Parameters:
     236                 *  edi = GC address to jump to
     237                 */
     238                Log(("PATMGC: Dispatch pending interrupt; eip=%VGv->%VGv\n", pRegFrame->eip, pRegFrame->edi));
     239
     240                /* Change EIP to the guest address the patch would normally jump to after setting IF. */
     241                pRegFrame->eip = pRegFrame->edi;
     242
     243                Assert(pVM->patm.s.CTXSUFF(pGCState)->Restore.uFlags == (PATM_RESTORE_EAX|PATM_RESTORE_ECX|PATM_RESTORE_EDI));
     244                Assert(pVM->patm.s.CTXSUFF(pGCState)->fPIF == 0);
     245
     246                pRegFrame->eax = pVM->patm.s.CTXSUFF(pGCState)->Restore.uEAX;
     247                pRegFrame->ecx = pVM->patm.s.CTXSUFF(pGCState)->Restore.uECX;
     248                pRegFrame->edi = pVM->patm.s.CTXSUFF(pGCState)->Restore.uEDI;
     249
     250                pVM->patm.s.CTXSUFF(pGCState)->Restore.uFlags = 0;
     251
     252                /* We are no longer executing PATM code; set PIF again. */
     253                pVM->patm.s.CTXSUFF(pGCState)->fPIF = 1;
     254
     255                STAM_COUNTER_INC(&pVM->patm.s.StatCheckPendingIRQ);
     256
     257                /* The caller will call trpmGCExitTrap, which will dispatch pending interrupts for us. */
     258                return VINF_SUCCESS;
     259
     260            case PATM_ACTION_PENDING_IRQ_AFTER_IRET:
     261                /* Parameters:
     262                 *  edi = GC address to jump to
     263                 */
     264                Log(("PATMGC: Dispatch pending interrupt (iret); eip=%VGv->%VGv\n", pRegFrame->eip, pRegFrame->edi));
     265                Assert(pVM->patm.s.CTXSUFF(pGCState)->Restore.uFlags == (PATM_RESTORE_EAX|PATM_RESTORE_ECX|PATM_RESTORE_EDI));
     266                Assert(pVM->patm.s.CTXSUFF(pGCState)->fPIF == 0);
     267
     268                /* Change EIP to the guest address of the iret. */
     269                pRegFrame->eip = pRegFrame->edi;
     270
     271                pRegFrame->eax = pVM->patm.s.CTXSUFF(pGCState)->Restore.uEAX;
     272                pRegFrame->ecx = pVM->patm.s.CTXSUFF(pGCState)->Restore.uECX;
     273                pRegFrame->edi = pVM->patm.s.CTXSUFF(pGCState)->Restore.uEDI;
     274                pVM->patm.s.CTXSUFF(pGCState)->Restore.uFlags = 0;
     275
     276                /* We are no longer executing PATM code; set PIF again. */
     277                pVM->patm.s.CTXSUFF(pGCState)->fPIF = 1;
     278
     279                return VINF_PATM_PENDING_IRQ_AFTER_IRET;
     280
     281            case PATM_ACTION_DO_V86_IRET:
     282            {
     283                Log(("PATMGC: Do iret to V86 code; eip=%VGv\n", pRegFrame->eip));
     284                Assert(pVM->patm.s.CTXSUFF(pGCState)->Restore.uFlags == (PATM_RESTORE_EAX|PATM_RESTORE_ECX));
     285                Assert(pVM->patm.s.CTXSUFF(pGCState)->fPIF == 0);
     286
     287                pRegFrame->eax = pVM->patm.s.CTXSUFF(pGCState)->Restore.uEAX;
     288                pRegFrame->ecx = pVM->patm.s.CTXSUFF(pGCState)->Restore.uECX;
     289                pVM->patm.s.CTXSUFF(pGCState)->Restore.uFlags = 0;
     290
     291                rc = EMInterpretIret(pVM, pRegFrame);
     292                if (VBOX_SUCCESS(rc))
     293                {
     294                    STAM_COUNTER_INC(&pVM->patm.s.StatEmulIret);
     295
     296                    /* We are no longer executing PATM code; set PIF again. */
     297                    pVM->patm.s.CTXSUFF(pGCState)->fPIF = 1;
     298                    CPUMGCCallV86Code(pRegFrame);
     299                    /* does not return */
     300                }
     301                else
     302                    STAM_COUNTER_INC(&pVM->patm.s.StatEmulIretFailed);
     303                return rc;
     304            }
     305
     306#ifdef DEBUG
     307            case PATM_ACTION_LOG_CLI:
     308                Log(("PATMGC: CLI at %VGv (current IF=%d iopl=%d)\n", pRegFrame->eip, !!(pVM->patm.s.CTXSUFF(pGCState)->uVMFlags & X86_EFL_IF), X86_EFL_GET_IOPL(pVM->patm.s.CTXSUFF(pGCState)->uVMFlags) ));
     309                pRegFrame->eip += PATM_ILLEGAL_INSTR_SIZE;
     310                return VINF_SUCCESS;
     311
     312            case PATM_ACTION_LOG_STI:
     313                Log(("PATMGC: STI at %VGv (current IF=%d iopl=%d)\n", pRegFrame->eip, !!(pVM->patm.s.CTXSUFF(pGCState)->uVMFlags & X86_EFL_IF), X86_EFL_GET_IOPL(pVM->patm.s.CTXSUFF(pGCState)->uVMFlags) ));
     314                pRegFrame->eip += PATM_ILLEGAL_INSTR_SIZE;
     315                return VINF_SUCCESS;
     316
     317            case PATM_ACTION_LOG_POPF_IF1:
     318                Log(("PATMGC: POPF setting IF at %VGv (current IF=%d iopl=%d)\n", pRegFrame->eip, !!(pVM->patm.s.CTXSUFF(pGCState)->uVMFlags & X86_EFL_IF), X86_EFL_GET_IOPL(pVM->patm.s.CTXSUFF(pGCState)->uVMFlags)));
     319                pRegFrame->eip += PATM_ILLEGAL_INSTR_SIZE;
     320                return VINF_SUCCESS;
     321
     322            case PATM_ACTION_LOG_POPF_IF0:
     323                Log(("PATMGC: POPF at %VGv (current IF=%d iopl=%d)\n", pRegFrame->eip, !!(pVM->patm.s.CTXSUFF(pGCState)->uVMFlags & X86_EFL_IF), X86_EFL_GET_IOPL(pVM->patm.s.CTXSUFF(pGCState)->uVMFlags)));
     324                pRegFrame->eip += PATM_ILLEGAL_INSTR_SIZE;
     325                return VINF_SUCCESS;
     326
     327            case PATM_ACTION_LOG_PUSHF:
     328                Log(("PATMGC: PUSHF at %VGv (current IF=%d iopl=%d)\n", pRegFrame->eip, !!(pVM->patm.s.CTXSUFF(pGCState)->uVMFlags & X86_EFL_IF), X86_EFL_GET_IOPL(pVM->patm.s.CTXSUFF(pGCState)->uVMFlags) ));
     329                pRegFrame->eip += PATM_ILLEGAL_INSTR_SIZE;
     330                return VINF_SUCCESS;
     331
     332            case PATM_ACTION_LOG_IF1:
     333                Log(("PATMGC: IF=1 escape from %VGv\n", pRegFrame->eip));
     334                pRegFrame->eip += PATM_ILLEGAL_INSTR_SIZE;
     335                return VINF_SUCCESS;
     336
     337            case PATM_ACTION_LOG_IRET:
     338            {
     339                char    *pIretFrame = (char *)pRegFrame->edx;
     340                uint32_t eip, selCS, uEFlags;
     341
     342                rc  = MMGCRamRead(pVM, &eip,     pIretFrame, 4);
     343                rc |= MMGCRamRead(pVM, &selCS,   pIretFrame + 4, 4);
     344                rc |= MMGCRamRead(pVM, &uEFlags, pIretFrame + 8, 4);
     345                if (rc == VINF_SUCCESS)
     346                {
     347                    if (    (uEFlags & X86_EFL_VM)
     348                        ||  (selCS & X86_SEL_RPL) == 3)
     349                    {
     350                        uint32_t selSS, esp;
     351
     352                        rc |= MMGCRamRead(pVM, &esp,     pIretFrame + 12, 4);
     353                        rc |= MMGCRamRead(pVM, &selSS,   pIretFrame + 16, 4);
     354
     355                        if (uEFlags & X86_EFL_VM)
     356                        {
     357                            uint32_t selDS, selES, selFS, selGS;
     358                            rc  = MMGCRamRead(pVM, &selES,   pIretFrame + 20, 4);
     359                            rc |= MMGCRamRead(pVM, &selDS,   pIretFrame + 24, 4);
     360                            rc |= MMGCRamRead(pVM, &selFS,   pIretFrame + 28, 4);
     361                            rc |= MMGCRamRead(pVM, &selGS,   pIretFrame + 32, 4);
     362                            if (rc == VINF_SUCCESS)
     363                            {
     364                                Log(("PATMGC: IRET->VM stack frame: return address %04X:%VGv eflags=%08x ss:esp=%04X:%VGv\n", selCS, eip, uEFlags, selSS, esp));
     365                                Log(("PATMGC: IRET->VM stack frame: DS=%04X ES=%04X FS=%04X GS=%04X\n", selDS, selES, selFS, selGS));
     366                            }
     367                        }
     368                        else
     369                            Log(("PATMGC: IRET stack frame: return address %04X:%VGv eflags=%08x ss:esp=%04X:%VGv\n", selCS, eip, uEFlags, selSS, esp));
     370                    }
     371                    else
     372                        Log(("PATMGC: IRET stack frame: return address %04X:%VGv eflags=%08x\n", selCS, eip, uEFlags));
     373                }
     374                Log(("PATMGC: IRET from %VGv (IF->1) current eflags=%x\n", pRegFrame->eip, pVM->patm.s.CTXSUFF(pGCState)->uVMFlags));
     375                pRegFrame->eip += PATM_ILLEGAL_INSTR_SIZE;
     376                return VINF_SUCCESS;
     377            }
     378
     379            case PATM_ACTION_LOG_RET:
     380                Log(("PATMGC: RET to %VGv ESP=%VGv iopl=%d\n", pRegFrame->edx, pRegFrame->ebx, X86_EFL_GET_IOPL(pVM->patm.s.CTXSUFF(pGCState)->uVMFlags)));
     381                pRegFrame->eip += PATM_ILLEGAL_INSTR_SIZE;
     382                return VINF_SUCCESS;
     383
     384            case PATM_ACTION_LOG_CALL:
     385                Log(("PATMGC: CALL to %VGv return addr %VGv ESP=%VGv iopl=%d\n", pVM->patm.s.CTXSUFF(pGCState)->GCCallPatchTargetAddr, pVM->patm.s.CTXSUFF(pGCState)->GCCallReturnAddr, pRegFrame->edx, X86_EFL_GET_IOPL(pVM->patm.s.CTXSUFF(pGCState)->uVMFlags)));
     386                pRegFrame->eip += PATM_ILLEGAL_INSTR_SIZE;
     387                return VINF_SUCCESS;
     388#endif
     389            default:
     390                AssertFailed();
     391                break;
     392            }
     393        }
     394        else
     395            AssertFailed();
     396        CTXSUFF(pVM->patm.s.pGCState)->uPendingAction = 0;
     397    }
     398    AssertMsgFailed(("Unexpected OP_ILLUD2 in patch code at %VGv (pending action %x)!!!!\n", pRegFrame->eip, CTXSUFF(pVM->patm.s.pGCState)->uPendingAction));
     399    return VINF_EM_RAW_EMULATE_INSTR;
     400}
     401
     402/**
     403 * Checks if the int 3 was caused by a patched instruction
     404 *
     405 * @returns VBox status
     406 *
     407 * @param   pVM         The VM handle.
     408 * @param   pCtxCore    The relevant core context.
     409 */
     410PATMDECL(int) PATMHandleInt3PatchTrap(PVM pVM, PCPUMCTXCORE pRegFrame)
     411{
     412    PPATMPATCHREC pRec;
     413    int rc;
     414
     415    Assert((pRegFrame->ss & X86_SEL_RPL) == 1);
     416
     417    /* Int 3 in PATM generated code? (most common case) */
     418    if (PATMIsPatchGCAddr(pVM, (RTGCPTR)pRegFrame->eip))
     419    {
     420        /* @note hardcoded assumption about it being a single byte int 3 instruction. */
     421        pRegFrame->eip--;
     422        return VINF_PATM_PATCH_INT3;
     423    }
     424
     425    /** @todo could use simple caching here to speed things up. */
     426    pRec = (PPATMPATCHREC)RTAvloGCPtrGet(&CTXSUFF(pVM->patm.s.PatchLookupTree)->PatchTree, (RTGCPTR)(pRegFrame->eip - 1));  /* eip is pointing to the instruction *after* 'int 3' already */
     427    if (pRec && pRec->patch.uState == PATCH_ENABLED)
     428    {
     429        if (pRec->patch.flags & PATMFL_INT3_REPLACEMENT_BLOCK)
     430        {
     431            Assert(pRec->patch.opcode == OP_CLI);
     432            /* This is a special cli block that was turned into an int 3 patch. We jump to the generated code manually. */
     433            pRegFrame->eip = (uint32_t)PATCHCODE_PTR_GC(&pRec->patch);
     434            STAM_COUNTER_INC(&pVM->patm.s.StatInt3BlockRun);
     435            return VINF_SUCCESS;
     436        }
     437        else
     438        if (pRec->patch.flags & PATMFL_INT3_REPLACEMENT)
     439        {
     440            uint32_t    size, cbOp;
     441            DISCPUSTATE cpu;
     442
     443            /* eip is pointing to the instruction *after* 'int 3' already */
     444            pRegFrame->eip = pRegFrame->eip - 1;
     445
     446            PATM_STAT_RUN_INC(&pRec->patch);
     447
     448            Log(("PATMHandleInt3PatchTrap found int3 for %s at %VGv\n", patmGetInstructionString(pRec->patch.opcode, 0), pRegFrame->eip));
     449
     450            switch(pRec->patch.opcode)
     451            {
     452            case OP_CPUID:
     453            case OP_IRET:
     454                break;
     455
     456            case OP_STR:
     457            case OP_SGDT:
     458            case OP_SLDT:
     459            case OP_SIDT:
     460            case OP_LSL:
     461            case OP_LAR:
     462            case OP_SMSW:
     463            case OP_VERW:
     464            case OP_VERR:
     465            default:
     466                PATM_STAT_FAULT_INC(&pRec->patch);
     467                pRec->patch.cTraps++;
     468                return VINF_EM_RAW_EMULATE_INSTR;
     469            }
     470
     471            cpu.mode = SELMIsSelector32Bit(pVM, pRegFrame->cs, 0) ? CPUMODE_32BIT : CPUMODE_16BIT;
     472            if(cpu.mode != CPUMODE_32BIT)
     473            {
     474                AssertFailed();
     475                return VINF_EM_RAW_EMULATE_INSTR;
     476            }
     477            rc = DISCoreOne(&cpu, (RTUINTPTR)&pRec->patch.aPrivInstr[0], &cbOp);
     478            if (VBOX_FAILURE(rc))
     479            {
     480                Log(("DISCoreOne failed with %Vrc\n", rc));
     481                PATM_STAT_FAULT_INC(&pRec->patch);
     482                pRec->patch.cTraps++;
     483                return VINF_EM_RAW_EMULATE_INSTR;
     484            }
     485
     486            rc = EMInterpretInstructionCPU(pVM, &cpu, pRegFrame, 0 /* not relevant here */, &size);
     487            if (rc != VINF_SUCCESS)
     488            {
     489                Log(("EMInterpretInstructionCPU failed with %Vrc\n", rc));
     490                PATM_STAT_FAULT_INC(&pRec->patch);
     491                pRec->patch.cTraps++;
     492                return VINF_EM_RAW_EMULATE_INSTR;
     493            }
     494
     495            pRegFrame->eip += cpu.opsize;
     496            return VINF_SUCCESS;
     497        }
     498    }
     499    return VERR_PATCH_NOT_FOUND;
     500}
     501
  • trunk/src/VBox/VMM/VMMGC/CPUMGCA.asm

    r19 r1134  
    189189ENDPROC CPUMGCCallGuestTrapHandler
    190190
     191;/**
     192; * Performs an iret to V86 code
     193; * Assumes a trap stack frame has already been setup on the guest's stack!
     194; *
     195; * @param   pRegFrame   Original trap/interrupt context
     196; *
     197; * This function does not return!
     198; */
     199;CPUMGCDECL(void) CPUMGCCallV86Code(PCPUMCTXCORE pRegFrame);
     200align 16
     201BEGINPROC CPUMGCCallV86Code
     202    mov     ebp, [esp + 4]                  ; pRegFrame
     203
     204    ; construct iret stack frame
     205    push    dword [ebp + CPUMCTXCORE.gs]
     206    push    dword [ebp + CPUMCTXCORE.fs]
     207    push    dword [ebp + CPUMCTXCORE.ds]
     208    push    dword [ebp + CPUMCTXCORE.es]
     209    push    dword [ebp + CPUMCTXCORE.ss]
     210    push    dword [ebp + CPUMCTXCORE.esp]
     211    push    dword [ebp + CPUMCTXCORE.eflags]
     212    push    dword [ebp + CPUMCTXCORE.cs]
     213    push    dword [ebp + CPUMCTXCORE.eip]
     214
     215    ;
     216    ; enable WP
     217    ;
     218%ifdef ENABLE_WRITE_PROTECTION
     219    mov     eax, cr0
     220    or      eax, X86_CR0_WRITE_PROTECT
     221    mov     cr0, eax
     222%endif
     223
     224    ; restore CPU context (all except cs, eip, ss, esp, eflags, ds, es, fs & gs; which are restored or overwritten by iret)
     225    mov     eax, [ebp + CPUMCTXCORE.eax]
     226    mov     ebx, [ebp + CPUMCTXCORE.ebx]
     227    mov     ecx, [ebp + CPUMCTXCORE.ecx]
     228    mov     edx, [ebp + CPUMCTXCORE.edx]
     229    mov     esi, [ebp + CPUMCTXCORE.esi]
     230    mov     edi, [ebp + CPUMCTXCORE.edi]
     231    mov     ebp, [ebp + CPUMCTXCORE.ebp]
     232
     233    TRPM_NP_GP_HANDLER NAME(cpumGCHandleNPAndGP), CPUM_HANDLER_IRET
     234    iret
     235ENDPROC CPUMGCCallV86Code
    191236
    192237;;
  • trunk/src/VBox/VMM/VMMGC/TRPMGCHandlers.cpp

    r1089 r1134  
    363363        if (Cpu.pCurInstr->opcode == OP_ILLUD2)
    364364        {
    365             int rc = PATMHandleIllegalInstrTrap(pVM, pRegFrame);
     365            int rc = PATMGCHandleIllegalInstrTrap(pVM, pRegFrame);
    366366            if (rc == VINF_SUCCESS || rc == VINF_EM_RAW_EMULATE_INSTR || rc == VINF_PATM_DUPLICATE_FUNCTION || rc == VINF_PATM_PENDING_IRQ_AFTER_IRET)
    367367                return trpmGCExitTrap(pVM, rc, pRegFrame);
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette