Changeset 1134 in vbox for trunk/src/VBox/VMM
- Timestamp:
- Mar 1, 2007 1:40:02 PM (18 years ago)
- Location:
- trunk/src/VBox/VMM
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/PATM/VMMAll/PATMAll.cpp
r1129 r1134 455 455 456 456 /** 457 * Checks if the illegal instruction was caused by a patched instruction458 *459 * @returns VBox status460 *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_MAGIC482 */483 if ( (pRegFrame->eax & CTXSUFF(pVM->patm.s.pGCState)->uPendingAction)484 && pRegFrame->ecx == PATM_ACTION_MAGIC485 )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 find495 * edi = PATCHJUMPTABLE ptr496 */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 else518 {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 else526 {527 #if 0528 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 #endif536 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 to544 */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 to570 */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 else607 STAM_COUNTER_INC(&pVM->patm.s.StatEmulIretFailed);608 return rc;609 }610 611 #ifdef DEBUG612 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_GC645 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 else675 Log(("PATMGC: IRET stack frame: return address %04X:%VGv eflags=%08x ss:esp=%04X:%VGv\n", selCS, eip, uEFlags, selSS, esp));676 }677 else678 Log(("PATMGC: IRET stack frame: return address %04X:%VGv eflags=%08x\n", selCS, eip, uEFlags));679 }680 #endif681 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 #endif696 default:697 AssertFailed();698 break;699 }700 }701 else702 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 instruction711 *712 * @returns VBox status713 *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 else745 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 /**810 457 * Adds branch pair to the lookup cache of the particular branch instruction 811 458 * … … 816 463 * @param pRelBranchPatch Relative duplicated function address 817 464 */ 818 intPATMAddBranchToLookupCache(PVM pVM, RTGCPTR pJumpTableGC, RTGCPTR pBranchTarget, RTGCUINTPTR pRelBranchPatch)465 PATMDECL(int) PATMAddBranchToLookupCache(PVM pVM, RTGCPTR pJumpTableGC, RTGCPTR pBranchTarget, RTGCUINTPTR pRelBranchPatch) 819 466 { 820 467 PPATCHJUMPTABLE pJumpTable; … … 872 519 } 873 520 521 874 522 /** 875 523 * Return the name of the patched instruction -
trunk/src/VBox/VMM/PATM/VMMGC/PATMGC.cpp
r730 r1134 35 35 #include <iprt/avl.h> 36 36 #include "PATMInternal.h" 37 #include "PATMA.h" 37 38 #include <VBox/vm.h> 38 39 #include <VBox/dbg.h> 40 #include <VBox/dis.h> 41 #include <VBox/disopcode.h> 42 #include <VBox/em.h> 39 43 #include <VBox/err.h> 40 #include <VBox/ em.h>44 #include <VBox/selm.h> 41 45 #include <VBox/log.h> 42 46 #include <iprt/assert.h> … … 141 145 return VERR_PATCH_NOT_FOUND; 142 146 } 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 */ 157 PATMDECL(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 */ 410 PATMDECL(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 189 189 ENDPROC CPUMGCCallGuestTrapHandler 190 190 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); 200 align 16 201 BEGINPROC 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 235 ENDPROC CPUMGCCallV86Code 191 236 192 237 ;; -
trunk/src/VBox/VMM/VMMGC/TRPMGCHandlers.cpp
r1089 r1134 363 363 if (Cpu.pCurInstr->opcode == OP_ILLUD2) 364 364 { 365 int rc = PATM HandleIllegalInstrTrap(pVM, pRegFrame);365 int rc = PATMGCHandleIllegalInstrTrap(pVM, pRegFrame); 366 366 if (rc == VINF_SUCCESS || rc == VINF_EM_RAW_EMULATE_INSTR || rc == VINF_PATM_DUPLICATE_FUNCTION || rc == VINF_PATM_PENDING_IRQ_AFTER_IRET) 367 367 return trpmGCExitTrap(pVM, rc, pRegFrame);
Note:
See TracChangeset
for help on using the changeset viewer.