VirtualBox

Changeset 45531 in vbox for trunk


Ignore:
Timestamp:
Apr 13, 2013 9:01:30 AM (12 years ago)
Author:
vboxsync
Message:

VMMR0/HMVMXR0: Redo of VT-x event injection. Some STAM cleanup.
VMM: TRPM enhancements to include instruction-length information for software interrupts and exceptions (#BP, #OF).

Location:
trunk
Files:
12 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/vmm/trpm.h

    r45528 r45531  
    7373VMMDECL(RTGCUINT)   TRPMGetErrorCode(PVMCPU pVCpu);
    7474VMMDECL(RTGCUINTPTR) TRPMGetFaultAddress(PVMCPU pVCpu);
     75VMMDECL(uint8_t)    TRPMGetInstrLength(PVMCPU pVCpu);
    7576VMMDECL(int)        TRPMResetTrap(PVMCPU pVCpu);
    7677VMMDECL(int)        TRPMAssertTrap(PVMCPU pVCpu, uint8_t u8TrapNo, TRPMEVENT enmType);
     78VMMDECL(int)        TRPMAssertXcptPF(PVMCPU pVCpu, RTGCUINTPTR uCR2, RTGCUINT uErrorCode);
    7779VMMDECL(void)       TRPMSetErrorCode(PVMCPU pVCpu, RTGCUINT uErrorCode);
    7880VMMDECL(void)       TRPMSetFaultAddress(PVMCPU pVCpu, RTGCUINTPTR uCR2);
     81VMMDECL(void)       TRPMSetInstrLength(PVMCPU pVCpu, uint8_t cbInstr);
    7982VMMDECL(bool)       TRPMIsSoftwareInterrupt(PVMCPU pVCpu);
    8083VMMDECL(bool)       TRPMHasTrap(PVMCPU pVCpu);
    81 VMMDECL(int)        TRPMQueryTrapAll(PVMCPU pVCpu, uint8_t *pu8TrapNo, PTRPMEVENT pEnmType, PRTGCUINT puErrorCode, PRTGCUINTPTR puCR2);
     84VMMDECL(int)        TRPMQueryTrapAll(PVMCPU pVCpu, uint8_t *pu8TrapNo, PTRPMEVENT pEnmType, PRTGCUINT puErrorCode, PRTGCUINTPTR puCR2, uint8_t *pu8InstrLen);
    8285VMMDECL(void)       TRPMSaveTrap(PVMCPU pVCpu);
    8386VMMDECL(void)       TRPMRestoreTrap(PVMCPU pVCpu);
  • trunk/src/VBox/VMM/VMMAll/IEMAll.cpp

    r44528 r45531  
    75657565        RTGCUINT    uErrCode;
    75667566        RTGCPTR     uCr2;
    7567         int rc2 = TRPMQueryTrapAll(pVCpu, &u8TrapNo, &enmType, &uErrCode, &uCr2); AssertRC(rc2);
     7567        int rc2 = TRPMQueryTrapAll(pVCpu, &u8TrapNo, &enmType, &uErrCode, &uCr2, NULL /* pu8InstLen */); AssertRC(rc2);
    75687568        IEMInjectTrap(pVCpu, u8TrapNo, enmType, (uint16_t)uErrCode, uCr2);
    75697569        if (!IEM_VERIFICATION_ENABLED(pIemCpu))
  • trunk/src/VBox/VMM/VMMAll/TRPMAll.cpp

    r45528 r45531  
    5151 * @param   pEnmType                Where to store the trap type
    5252 */
    53 VMMDECL(int)  TRPMQueryTrap(PVMCPU pVCpu, uint8_t *pu8TrapNo, TRPMEVENT *pEnmType)
     53VMMDECL(int) TRPMQueryTrap(PVMCPU pVCpu, uint8_t *pu8TrapNo, TRPMEVENT *pEnmType)
    5454{
    5555    /*
     
    7878 * @param   pVCpu                   Pointer to the VMCPU.
    7979 */
    80 VMMDECL(uint8_t)  TRPMGetTrapNo(PVMCPU pVCpu)
     80VMMDECL(uint8_t) TRPMGetTrapNo(PVMCPU pVCpu)
    8181{
    8282    AssertMsg(pVCpu->trpm.s.uActiveVector != ~0U, ("No active trap!\n"));
     
    9494 * @param   pVCpu                   Pointer to the VMCPU.
    9595 */
    96 VMMDECL(RTGCUINT)  TRPMGetErrorCode(PVMCPU pVCpu)
     96VMMDECL(RTGCUINT) TRPMGetErrorCode(PVMCPU pVCpu)
    9797{
    9898    AssertMsg(pVCpu->trpm.s.uActiveVector != ~0U, ("No active trap!\n"));
     
    100100    switch (pVCpu->trpm.s.uActiveVector)
    101101    {
    102         case 0x0a:
    103         case 0x0b:
    104         case 0x0c:
    105         case 0x0d:
    106         case 0x0e:
    107         case 0x11:
    108         case 0x08:
     102        case X86_XCPT_TS:
     103        case X86_XCPT_NP:
     104        case X86_XCPT_SS:
     105        case X86_XCPT_GP:
     106        case X86_XCPT_PF:
     107        case X86_XCPT_AC:
     108        case X86_XCPT_DF:
    109109            break;
    110110        default:
     
    132132    return pVCpu->trpm.s.uActiveCR2;
    133133}
     134
     135
     136/**
     137 * Gets the instruction-length for the current trap (only relevant for software
     138 * interrupts and software exceptions #BP and #OF).
     139 *
     140 * The caller is responsible for making sure there is an active trap 0x0e when
     141 * making this request.
     142 *
     143 * @returns Fault address associated with the trap.
     144 * @param   pVCpu                   Pointer to the VMCPU.
     145 */
     146VMMDECL(uint8_t) TRPMGetInstrLength(PVMCPU pVCpu)
     147{
     148    AssertMsg(pVCpu->trpm.s.uActiveVector != ~0U, ("No active trap!\n"));
     149    return pVCpu->trpm.s.cbInstr;
     150}
     151
    134152
    135153
     
    173191 * @param   enmType             Trap type.
    174192 */
    175 VMMDECL(int)  TRPMAssertTrap(PVMCPU pVCpu, uint8_t u8TrapNo, TRPMEVENT enmType)
     193VMMDECL(int) TRPMAssertTrap(PVMCPU pVCpu, uint8_t u8TrapNo, TRPMEVENT enmType)
    176194{
    177195    Log2(("TRPMAssertTrap: u8TrapNo=%02x type=%d\n", u8TrapNo, enmType));
     
    190208    pVCpu->trpm.s.uActiveErrorCode            = ~(RTGCUINT)0;
    191209    pVCpu->trpm.s.uActiveCR2                  = 0xdeadface;
     210    pVCpu->trpm.s.cbInstr                     = UINT8_MAX;
     211    return VINF_SUCCESS;
     212}
     213
     214
     215/**
     216 * Assert a page-fault exception.
     217 *
     218 * The caller is responsible for making sure there is no active trap
     219 * when making this request.
     220 *
     221 * @returns VBox status code.
     222 * @param   pVCpu               Pointer to the VMCPU.
     223 * @param   uCR2                The new fault address.
     224 * @param   uErrorCode          The error code for the page-fault.
     225 */
     226VMMDECL(int) TRPMAssertXcptPF(PVMCPU pVCpu, RTGCUINTPTR uCR2, RTGCUINT uErrorCode)
     227{
     228    Log2(("TRPMAssertXcptPF: uCR2=%RGv uErrorCode=%RGv\n", uCR2, uErrorCode)); /** @todo RTGCUINT to be fixed. */
     229
     230    /*
     231     * Cannot assert a trap when one is already active.
     232     */
     233    if (pVCpu->trpm.s.uActiveVector != ~0U)
     234    {
     235        AssertMsgFailed(("CPU%d: Active trap %#x\n", pVCpu->idCpu, pVCpu->trpm.s.uActiveVector));
     236        return VERR_TRPM_ACTIVE_TRAP;
     237    }
     238
     239    pVCpu->trpm.s.uActiveVector               = X86_XCPT_PF;
     240    pVCpu->trpm.s.enmActiveType               = TRPM_TRAP;
     241    pVCpu->trpm.s.uActiveErrorCode            = uErrorCode;
     242    pVCpu->trpm.s.uActiveCR2                  = uCR2;
     243    pVCpu->trpm.s.cbInstr                     = UINT8_MAX;
    192244    return VINF_SUCCESS;
    193245}
     
    204256 * @param   uErrorCode          The new error code.
    205257 */
    206 VMMDECL(void)  TRPMSetErrorCode(PVMCPU pVCpu, RTGCUINT uErrorCode)
     258VMMDECL(void) TRPMSetErrorCode(PVMCPU pVCpu, RTGCUINT uErrorCode)
    207259{
    208260    Log2(("TRPMSetErrorCode: uErrorCode=%RGv\n", uErrorCode)); /** @todo RTGCUINT mess! */
     
    227279
    228280/**
    229  * Sets the error code of the current trap.
    230  * (This function is for use in trap handlers and such.)
     281 * Sets the fault address of the current #PF trap. (This function is for use in
     282 * trap handlers and such.)
    231283 *
    232284 * The caller is responsible for making sure there is an active trap 0e
     
    236288 * @param   uCR2                The new fault address (cr2 register).
    237289 */
    238 VMMDECL(void)  TRPMSetFaultAddress(PVMCPU pVCpu, RTGCUINTPTR uCR2)
     290VMMDECL(void) TRPMSetFaultAddress(PVMCPU pVCpu, RTGCUINTPTR uCR2)
    239291{
    240292    Log2(("TRPMSetFaultAddress: uCR2=%RGv\n", uCR2));
    241293    AssertMsg(pVCpu->trpm.s.uActiveVector != ~0U, ("No active trap!\n"));
    242     AssertMsg(pVCpu->trpm.s.uActiveVector == 0xe, ("Not trap 0e!\n"));
     294    AssertMsg(pVCpu->trpm.s.uActiveVector == X86_XCPT_PF, ("Not trap 0e!\n"));
    243295    pVCpu->trpm.s.uActiveCR2 = uCR2;
     296}
     297
     298
     299/**
     300 * Sets the instruction-length of the current trap (relevant for software
     301 * interrupts and software exceptions like #BP, #OF).
     302 *
     303 * The caller is responsible for making sure there is an active trap 0e
     304 * when making this request.
     305 *
     306 * @param   pVCpu               Pointer to the VMCPU.
     307 * @param   cbInstr             The instruction length.
     308 */
     309VMMDECL(void) TRPMSetInstrLength(PVMCPU pVCpu, uint8_t cbInstr)
     310{
     311    Log2(("TRPMSetInstrLength: cbInstr=%u\n", cbInstr));
     312    AssertMsg(pVCpu->trpm.s.uActiveVector != ~0U, ("No active trap!\n"));
     313    AssertMsg(   pVCpu->trpm.s.enmActiveType == TRPM_SOFTWARE_INT
     314              || (   pVCpu->trpm.s.enmActiveType == TRPM_TRAP
     315                  && (   pVCpu->trpm.s.uActiveVector == X86_XCPT_BP
     316                      || pVCpu->trpm.s.uActiveVector == X86_XCPT_OF)),
     317              ("Invalid trap type %#x\n", pVCpu->trpm.s.enmActiveType));
     318    pVCpu->trpm.s.cbInstr = cbInstr;
    244319}
    245320
     
    269344 * @param   pVCpu               Pointer to the VMCPU.
    270345 */
    271 VMMDECL(bool)  TRPMHasTrap(PVMCPU pVCpu)
     346VMMDECL(bool) TRPMHasTrap(PVMCPU pVCpu)
    272347{
    273348    return pVCpu->trpm.s.uActiveVector != ~0U;
     
    286361 *                                  ~0U is stored if the trap has no error code.
    287362 * @param   puCR2                   Where to store the CR2 associated with a trap 0E.
    288  */
    289 VMMDECL(int)  TRPMQueryTrapAll(PVMCPU pVCpu, uint8_t *pu8TrapNo, TRPMEVENT *pEnmType, PRTGCUINT puErrorCode, PRTGCUINTPTR puCR2)
     363 * @param   pu8InstrLen             Where to store the instruction-length
     364 *                                  associated with some traps.
     365 */
     366VMMDECL(int) TRPMQueryTrapAll(PVMCPU pVCpu, uint8_t *pu8TrapNo, TRPMEVENT *pEnmType, PRTGCUINT puErrorCode, PRTGCUINTPTR puCR2,
     367                               uint8_t *pu8InstrLen)
    290368{
    291369    /*
     
    303381    if (puCR2)
    304382        *puCR2          = pVCpu->trpm.s.uActiveCR2;
    305 
     383    if (pu8InstrLen)
     384        *pu8InstrLen    = pVCpu->trpm.s.cbInstr;
    306385    return VINF_SUCCESS;
    307386}
     
    323402    pVCpu->trpm.s.uSavedErrorCode     = pVCpu->trpm.s.uActiveErrorCode;
    324403    pVCpu->trpm.s.uSavedCR2           = pVCpu->trpm.s.uActiveCR2;
     404    pVCpu->trpm.s.cbSavedInstr        = pVCpu->trpm.s.cbInstr;
    325405}
    326406
     
    339419    pVCpu->trpm.s.uActiveErrorCode    = pVCpu->trpm.s.uSavedErrorCode;
    340420    pVCpu->trpm.s.uActiveCR2          = pVCpu->trpm.s.uSavedCR2;
     421    pVCpu->trpm.s.cbInstr             = pVCpu->trpm.s.cbSavedInstr;
    341422}
    342423
     
    788869    pVCpu->trpm.s.uActiveErrorCode         = 0xdeadbeef;
    789870    pVCpu->trpm.s.uActiveCR2               = 0xdeadface;
     871    pVCpu->trpm.s.cbInstr                  = UINT8_MAX;
    790872    return VINF_EM_RAW_GUEST_TRAP;
    791873}
     
    815897    pVCpu->trpm.s.uActiveErrorCode         = uErr;
    816898    pVCpu->trpm.s.uActiveCR2               = 0xdeadface;
     899    pVCpu->trpm.s.cbInstr                  = UINT8_MAX;
    817900    return VINF_EM_RAW_GUEST_TRAP;
    818901}
     
    843926    pVCpu->trpm.s.uActiveErrorCode         = uErr;
    844927    pVCpu->trpm.s.uActiveCR2               = uCR2;
     928    pVCpu->trpm.s.cbInstr                  = UINT8_MAX;
    845929    return VINF_EM_RAW_GUEST_TRAP;
    846930}
  • trunk/src/VBox/VMM/VMMR0/HMVMXR0.cpp

    r45519 r45531  
    55
    66/*
    7  * Copyright (C) 2012 Oracle Corporation
     7 * Copyright (C) 2012-2013 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    112112#define VMX_TRANSIENT_EXIT_INTERRUPTION_ERROR_CODE  RT_BIT(5)
    113113
    114 /*
     114/**
    115115 * Exception bitmap mask for real-mode guests (real-on-v86). We need to intercept all exceptions manually (except #PF).
    116116 * #NM is also handled spearetely, see hmR0VmxLoadGuestControlRegs(). #PF need not be intercepted even in real-mode if
     
    125125                                   | RT_BIT(X86_XCPT_XF))
    126126
    127 /* Maximum VM-instruction error number. */
     127/** Maximum VM-instruction error number. */
    128128#define VMX_INSTR_ERROR_MAX     28
    129129
     
    206206static void               hmR0VmxFlushVpid(PVM pVM, PVMCPU pVCpu, VMX_FLUSH_VPID enmFlush, RTGCPTR GCPtr);
    207207static int                hmR0VmxInjectEventVmcs(PVMCPU pVCpu, PCPUMCTX pMixedCtx, uint64_t u64IntrInfo,
    208                                                  uint32_t cbInstr, uint32_t u32ErrCode);
     208                                                 uint32_t cbInstr, uint32_t u32ErrCode, uint32_t *puIntrState);
    209209#if HC_ARCH_BITS == 32 && !defined(VBOX_WITH_HYBRID_32BIT_KERNEL)
    210210static int                hmR0VmxInitVmcsReadCache(PVM pVM, PVMCPU pVCpu);
     
    269269*   Global Variables                                                           *
    270270*******************************************************************************/
    271 /** @todo Move this to hm_vmx.h. */
    272271/**
    273272 * VM-exit handler.
     
    282281typedef DECLCALLBACK(int) FNVMEXITHANDLER(PVMCPU pVCpu, PCPUMCTX pMixedCtx, PVMXTRANSIENT pVmxTransient);
    283282/** Pointer to VM-exit handler. */
    284 typedef FNVMEXITHANDLER *PFNVMEXITHANDLER;
    285 
    286 static const PFNVMEXITHANDLER s_apfnVMExitHandlers[VMX_EXIT_MAX + 1] =
     283typedef FNVMEXITHANDLER *const PFNVMEXITHANDLER;
     284
     285/**
     286 * VMX_EXIT dispatch table.
     287 */
     288static const PFNVMEXITHANDLER g_apfnVMExitHandlers[VMX_EXIT_MAX + 1] =
    287289{
    288290 /* 00  VMX_EXIT_XCPT_NMI                */  hmR0VmxExitXcptNmi,
     
    348350};
    349351
    350 static const char* const s_apszVmxInstrErrors[VMX_INSTR_ERROR_MAX + 1] =
     352#ifdef VBOX_STRICT
     353static const char* const g_apszVmxInstrErrors[VMX_INSTR_ERROR_MAX + 1] =
    351354{
    352355    /*  0 */ "(Not Used)",
     
    380383    /* 28 */ "Invalid operand to INVEPT/INVVPID."
    381384};
    382 
     385#endif
    383386
    384387/**
     
    845848{
    846849    /* Setup the main VM exit handlers. */
    847     AssertCompile(VMX_EXIT_MAX + 1 == RT_ELEMENTS(s_apfnVMExitHandlers));
    848 #ifdef DEBUG
    849     for (unsigned i = 0; i < RT_ELEMENTS(s_apfnVMExitHandlers); i++)
    850         Assert(s_apfnVMExitHandlers[i]);
     850    AssertCompile(VMX_EXIT_MAX + 1 == RT_ELEMENTS(g_apfnVMExitHandlers));
     851#ifdef VBOX_STRICT
     852    for (unsigned i = 0; i < RT_ELEMENTS(g_apfnVMExitHandlers); i++)
     853        Assert(g_apfnVMExitHandlers[i]);
    851854#endif
    852855    return VINF_SUCCESS;
     
    24752478
    24762479/**
    2477  * Loads the guest's interruptibility-state ("interrupt shadow" as AMD calls it)
    2478  * into the guest-state area in the VMCS.
    2479  *
    2480  * @param   pVM         Pointer to the VM.
     2480 * Gets the guest's interruptibility-state ("interrupt shadow" as AMD calls it).
     2481 *
     2482 * @returns
    24812483 * @param   pVCpu       Pointer to the VMCPU.
    24822484 * @param   pMixedCtx   Pointer to the guest-CPU context. The data may be
     
    24852487 *
    24862488 * @remarks No-long-jump zone!!!
    2487  */
    2488 DECLINLINE(void) hmR0VmxLoadGuestIntrState(PVM pVM, PVMCPU pVCpu, PCPUMCTX pMixedCtx)
     2489 * @remarks Has side-effects with VMCPU_FF_INHIBIT_INTERRUPTS force-flag.
     2490 */
     2491DECLINLINE(uint32_t) hmR0VmxGetGuestIntrState(PVMCPU pVCpu, PCPUMCTX pMixedCtx)
    24892492{
    24902493    /*
     
    24962499    {
    24972500        /* If inhibition is active, RIP & RFLAGS should've been accessed (i.e. read previously from the VMCS or from ring-3). */
    2498         AssertMsg((pVCpu->hm.s.vmx.fUpdatedGuestState & (VMX_UPDATED_GUEST_RIP | VMX_UPDATED_GUEST_RFLAGS)),
    2499                   ("%#x\n", pVCpu->hm.s.vmx.fUpdatedGuestState));
     2501        AssertMsg((pVCpu->hm.s.vmx.fUpdatedGuestState & (VMX_UPDATED_GUEST_RIP | VMX_UPDATED_GUEST_RFLAGS))
     2502                   == (VMX_UPDATED_GUEST_RIP | VMX_UPDATED_GUEST_RFLAGS), ("%#x\n", pVCpu->hm.s.vmx.fUpdatedGuestState));
    25002503        if (pMixedCtx->rip != EMGetInhibitInterruptsPC(pVCpu))
    25012504        {
     
    25032506             * We can clear the inhibit force flag as even if we go back to the recompiler without executing guest code in
    25042507             * VT-x the flag's condition to be cleared is met and thus the cleared state is correct.
    2505              * hmR0VmxInjectPendingInterrupt() relies on us clearing this flag here.
    25062508             */
    25072509            VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
     
    25122514            uIntrState = VMX_VMCS_GUEST_INTERRUPTIBILITY_STATE_BLOCK_MOVSS;
    25132515    }
    2514 
    2515     Assert(!(uIntrState & 0xfffffff0));                             /* Bits 31:4 MBZ. */
     2516    return uIntrState;
     2517}
     2518
     2519
     2520/**
     2521 * Loads the guest's interruptibility-state into the guest-state area in the
     2522 * VMCS.
     2523 *
     2524 * @returns VBox status code.
     2525 * @param pVCpu         Pointer to the VMCPU.
     2526 * @param uIntrState    The interruptibility-state to set.
     2527 */
     2528DECLINLINE(int) hmR0VmxLoadGuestIntrState(PVMCPU pVCpu, uint32_t uIntrState)
     2529{
     2530    AssertMsg(!(uIntrState & 0xfffffff0), ("%#x\n", uIntrState));   /* Bits 31:4 MBZ. */
    25162531    Assert((uIntrState & 0x3) != 0x3);                              /* Block-by-STI and MOV SS cannot be simultaneously set. */
    25172532    int rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_INTERRUPTIBILITY_STATE, uIntrState);
    2518     AssertRC(rc);
     2533    AssertRCReturn(rc, rc);
     2534    return rc;
    25192535}
    25202536
     
    29963012        return VINF_SUCCESS;
    29973013
    2998 #ifdef DEBUG
     3014#ifdef VBOX_STRICT
    29993015    /* Validate. Intel spec. 26.3.1.1 "Checks on Guest Controls Registers, Debug Registers, MSRs" */
    30003016    if (pVCpu->hm.s.vmx.u32EntryCtls & VMX_VMCS_CTRL_ENTRY_CONTROLS_LOAD_DEBUG)
     
    30863102
    30873103
    3088 #ifdef DEBUG
    3089 /**
    3090  * Debug function to validate segment registers.
     3104#ifdef VBOX_STRICT
     3105/**
     3106 * Strict function to validate segment registers.
    30913107 */
    30923108static void hmR0VmxValidateSegmentRegs(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx)
     
    32473263    }
    32483264}
    3249 #endif /* DEBUG */
     3265#endif /* VBOX_STRICT */
    32503266
    32513267
     
    33143330 *
    33153331 * @remarks No-long-jump zone!!!
    3316  * @remarks Requires RFLAGS (for debug assertions).
    33173332 */
    33183333DECLINLINE(int) hmR0VmxLoadGuestSegmentRegs(PVM pVM, PVMCPU pVCpu, PCPUMCTX pCtx)
     
    33703385        AssertRCReturn(rc, rc);
    33713386
    3372 #ifdef DEBUG
     3387#ifdef VBOX_STRICT
    33733388        hmR0VmxValidateSegmentRegs(pVM, pVCpu, pCtx);
    33743389#endif
     
    37853800                Log(("InstrError         %#x\n", pVCpu->hm.s.vmx.lasterror.u32InstrError));
    37863801                if (pVCpu->hm.s.vmx.lasterror.u32InstrError <= VMX_INSTR_ERROR_MAX)
    3787                     Log(("InstrError Desc.  \"%s\"\n", s_apszVmxInstrErrors[pVCpu->hm.s.vmx.lasterror.u32InstrError]));
     3802                    Log(("InstrError Desc.  \"%s\"\n", g_apszVmxInstrErrors[pVCpu->hm.s.vmx.lasterror.u32InstrError]));
    37883803                else
    37893804                    Log(("InstrError Desc.    Range exceeded %u\n", VMX_INSTR_ERROR_MAX));
     
    41664181#endif
    41674182
    4168 #ifdef DEBUG
    4169     pCache->TestIn.HCPhysCpuPage= 0;
    4170     pCache->TestIn.HCPhysVmcs   = 0;
    4171     pCache->TestIn.pCache       = 0;
    4172     pCache->TestOut.HCPhysVmcs  = 0;
    4173     pCache->TestOut.pCache      = 0;
    4174     pCache->TestOut.pCtx        = 0;
    4175     pCache->TestOut.eflags      = 0;
     4183#ifdef VBOX_STRICT
     4184    pCache->TestIn.HCPhysCpuPage = 0;
     4185    pCache->TestIn.HCPhysVmcs    = 0;
     4186    pCache->TestIn.pCache        = 0;
     4187    pCache->TestOut.HCPhysVmcs   = 0;
     4188    pCache->TestOut.pCache       = 0;
     4189    pCache->TestOut.pCtx         = 0;
     4190    pCache->TestOut.eflags       = 0;
    41764191#endif
    41774192
     
    41954210#endif
    41964211
    4197 #ifdef DEBUG
    4198     AssertMsg(pCache->TestIn.HCPhysCpuPage== HCPhysCpuPage, ("%RHp vs %RHp\n", pCache->TestIn.HCPhysCpuPage, HCPhysCpuPage));
    4199     AssertMsg(pCache->TestIn.HCPhysVmcs   == pVCpu->hm.s.vmx.HCPhysVmcs, ("%RHp vs %RHp\n", pCache->TestIn.HCPhysVmcs,
    4200                                                                               pVCpu->hm.s.vmx.HCPhysVmcs));
    4201     AssertMsg(pCache->TestIn.HCPhysVmcs   == pCache->TestOut.HCPhysVmcs, ("%RHp vs %RHp\n", pCache->TestIn.HCPhysVmcs,
    4202                                                                           pCache->TestOut.HCPhysVmcs));
    4203     AssertMsg(pCache->TestIn.pCache       == pCache->TestOut.pCache, ("%RGv vs %RGv\n", pCache->TestIn.pCache,
    4204                                                                       pCache->TestOut.pCache));
    4205     AssertMsg(pCache->TestIn.pCache       == VM_RC_ADDR(pVM, &pVM->aCpus[pVCpu->idCpu].hm.s.vmx.VMCSCache),
     4212#ifdef VBOX_STRICT
     4213    AssertMsg(pCache->TestIn.HCPhysCpuPage == HCPhysCpuPage, ("%RHp vs %RHp\n", pCache->TestIn.HCPhysCpuPage, HCPhysCpuPage));
     4214    AssertMsg(pCache->TestIn.HCPhysVmcs    == pVCpu->hm.s.vmx.HCPhysVmcs, ("%RHp vs %RHp\n", pCache->TestIn.HCPhysVmcs,
     4215                                                                               pVCpu->hm.s.vmx.HCPhysVmcs));
     4216    AssertMsg(pCache->TestIn.HCPhysVmcs    == pCache->TestOut.HCPhysVmcs, ("%RHp vs %RHp\n", pCache->TestIn.HCPhysVmcs,
     4217                                                                           pCache->TestOut.HCPhysVmcs));
     4218    AssertMsg(pCache->TestIn.pCache        == pCache->TestOut.pCache, ("%RGv vs %RGv\n", pCache->TestIn.pCache,
     4219                                                                       pCache->TestOut.pCache));
     4220    AssertMsg(pCache->TestIn.pCache        == VM_RC_ADDR(pVM, &pVM->aCpus[pVCpu->idCpu].hm.s.vmx.VMCSCache),
    42064221              ("%RGv vs %RGv\n", pCache->TestIn.pCache, VM_RC_ADDR(pVM, &pVM->aCpus[pVCpu->idCpu].hm.s.vmx.VMCSCache)));
    4207     AssertMsg(pCache->TestIn.pCtx         == pCache->TestOut.pCtx, ("%RGv vs %RGv\n", pCache->TestIn.pCtx,
     4222    AssertMsg(pCache->TestIn.pCtx          == pCache->TestOut.pCtx, ("%RGv vs %RGv\n", pCache->TestIn.pCtx,
    42084223                                                                    pCache->TestOut.pCtx));
    42094224    Assert(!(pCache->TestOut.eflags & X86_EFL_IF));
     
    46394654 * Sets an event as a pending event to be injected into the guest.
    46404655 *
    4641  * @param   pVCpu           Pointer to the VMCPU.
    4642  * @param   u32IntrInfo     The VM-entry interruption-information field.
    4643  * @param   cbInstr         The VM-entry instruction length in bytes (for software
    4644  *                          interrupts, exceptions and privileged software
    4645  *                          exceptions).
    4646  * @param   u32ErrCode      The VM-entry exception error code.
    4647  */
    4648 DECLINLINE(void) hmR0VmxSetPendingEvent(PVMCPU pVCpu, uint32_t u32IntrInfo, uint32_t cbInstr, uint32_t u32ErrCode)
     4656 * @param   pVCpu               Pointer to the VMCPU.
     4657 * @param   u32IntrInfo         The VM-entry interruption-information field.
     4658 * @param   cbInstr             The VM-entry instruction length in bytes (for software
     4659 *                              interrupts, exceptions and privileged software
     4660 *                              exceptions).
     4661 * @param   u32ErrCode          The VM-entry exception error code.
     4662 * @param   GCPtrFaultAddress   The fault-address (CR2) in case it's a
     4663 *                              page-fault.
     4664 */
     4665DECLINLINE(void) hmR0VmxSetPendingEvent(PVMCPU pVCpu, uint32_t u32IntrInfo, uint32_t cbInstr, uint32_t u32ErrCode,
     4666                                        RTGCUINTPTR GCPtrFaultAddress)
    46494667{
    46504668    Assert(!pVCpu->hm.s.Event.fPending);
    4651     pVCpu->hm.s.Event.fPending    = true;
    4652     pVCpu->hm.s.Event.u64IntrInfo = u32IntrInfo;
    4653     pVCpu->hm.s.Event.u32ErrCode  = u32ErrCode;
    4654     pVCpu->hm.s.Event.cbInstr     = cbInstr;
     4669    pVCpu->hm.s.Event.fPending          = true;
     4670    pVCpu->hm.s.Event.u64IntrInfo       = u32IntrInfo;
     4671    pVCpu->hm.s.Event.u32ErrCode        = u32ErrCode;
     4672    pVCpu->hm.s.Event.cbInstr           = cbInstr;
     4673    pVCpu->hm.s.Event.GCPtrFaultAddress = GCPtrFaultAddress;
    46554674}
    46564675
     
    47504769                }
    47514770                hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INTR_INFO_FROM_EXIT_IDT_INFO(pVmxTransient->uIdtVectoringInfo),
    4752                                        0 /* cbInstr */,  u32ErrCode);
     4771                                       0 /* cbInstr */,  u32ErrCode, 0 /* GCPtrFaultAddress */);
    47534772                rc = VINF_SUCCESS;
    47544773                Log(("Pending event %#RX64 Err=%#RX32\n", pVCpu->hm.s.Event.u64IntrInfo, pVCpu->hm.s.Event.u32ErrCode));
     
    47624781                u32IntrInfo |= (VMX_EXIT_INTERRUPTION_INFO_TYPE_HW_XCPT << VMX_EXIT_INTERRUPTION_INFO_TYPE_SHIFT);
    47634782                u32IntrInfo |= VMX_EXIT_INTERRUPTION_INFO_ERROR_CODE_VALID;
    4764                 hmR0VmxSetPendingEvent(pVCpu, u32IntrInfo, 0 /* cbInstr */, 0 /* u32ErrCode */);
     4783                hmR0VmxSetPendingEvent(pVCpu, u32IntrInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
    47654784                rc = VINF_VMX_DOUBLE_FAULT;
    47664785                Log(("Pending #DF %#RX64 uIdt=%#x uExit=%#x\n", pVCpu->hm.s.Event.u64IntrInfo, uIdtVector, uExitVector));
     
    55395558
    55405559/**
     5560 * Converts any TRPM trap into a pending VMX event.
     5561 *
     5562 * @param   pVCpu           Pointer to the VMCPU.
     5563 */
     5564static void hmR0VmxUpdatePendingEvent(PVMCPU pVCpu, PCPUMCTX pMixedCtx)
     5565{
     5566    if (!TRPMHasTrap(pVCpu))
     5567        return;
     5568
     5569    uint8_t     uVector;
     5570    TRPMEVENT   enmTrpmEvent;
     5571    RTGCUINT    uErrCode;
     5572    RTGCUINTPTR GCPtrFaultAddress;
     5573    uint8_t     cbInstr;
     5574
     5575    int rc = TRPMQueryTrapAll(pVCpu, &uVector, &enmTrpmEvent, &uErrCode, &GCPtrFaultAddress, &cbInstr);
     5576    AssertRC(rc);
     5577
     5578    /* Refer Intel spec. 24.8.3 "VM-entry Controls for Event Injection" for the format of u32IntrInfo. */
     5579    uint32_t u32IntrInfo = uVector | (1 << VMX_EXIT_INTERRUPTION_INFO_VALID_SHIFT);
     5580    uint32_t u32ErrCode  = uErrCode;
     5581    if (enmTrpmEvent == TRPM_TRAP)
     5582    {
     5583        switch (uVector)
     5584        {
     5585            case X86_XCPT_BP:
     5586            case X86_XCPT_OF:
     5587            {
     5588                /* These exceptions must be delivered as software exceptions. They have no error codes associated with them. */
     5589                u32IntrInfo |= (VMX_EXIT_INTERRUPTION_INFO_TYPE_SW_XCPT << VMX_EXIT_INTERRUPTION_INFO_TYPE_SHIFT);
     5590                break;
     5591            }
     5592
     5593            case X86_XCPT_DF:
     5594            case X86_XCPT_TS:
     5595            case X86_XCPT_NP:
     5596            case X86_XCPT_SS:
     5597            case X86_XCPT_GP:
     5598            case X86_XCPT_PF:
     5599            case X86_XCPT_AC:
     5600                /* These exceptions must be delivered as hardware exceptions. They have error codes associated with
     5601                   them which VT-x/VMM pushes to the guest stack. */
     5602                u32IntrInfo |= VMX_EXIT_INTERRUPTION_INFO_ERROR_CODE_VALID;
     5603                /* no break! */
     5604            default:
     5605            {
     5606                u32IntrInfo |= (VMX_EXIT_INTERRUPTION_INFO_TYPE_HW_XCPT << VMX_EXIT_INTERRUPTION_INFO_TYPE_SHIFT);
     5607                if (uVector == X86_XCPT_PF)
     5608                    pMixedCtx->cr2 = TRPMGetFaultAddress(pVCpu);
     5609                break;
     5610            }
     5611        }
     5612    }
     5613    else if (enmTrpmEvent == TRPM_HARDWARE_INT)
     5614    {
     5615        if (uVector != X86_XCPT_NMI)
     5616            u32IntrInfo |= (VMX_EXIT_INTERRUPTION_INFO_TYPE_EXT_INT << VMX_EXIT_INTERRUPTION_INFO_TYPE_SHIFT);
     5617        else
     5618            u32IntrInfo |= (VMX_EXIT_INTERRUPTION_INFO_TYPE_NMI << VMX_EXIT_INTERRUPTION_INFO_TYPE_SHIFT);
     5619    }
     5620    else if (enmTrpmEvent == TRPM_SOFTWARE_INT)
     5621        u32IntrInfo |= (VMX_EXIT_INTERRUPTION_INFO_TYPE_SW_INT << VMX_EXIT_INTERRUPTION_INFO_TYPE_SHIFT);
     5622    else
     5623        AssertMsgFailed(("Invalid TRPM event type %d\n", enmTrpmEvent));
     5624
     5625    rc = TRPMResetTrap(pVCpu);
     5626    Log(("Converted TRPM trap: u32IntrInfo=%#RX32 enmTrpmEvent=%d cbInstr=%u u32ErrCode=%#RX32 GCPtrFaultAddress=%#RGv\n",
     5627         u32IntrInfo, enmTrpmEvent, u32ErrCode, GCPtrFaultAddress));
     5628    hmR0VmxSetPendingEvent(pVCpu, u32IntrInfo, cbInstr, u32ErrCode, GCPtrFaultAddress);
     5629}
     5630
     5631
     5632/**
    55415633 * Converts any pending VMX event into a TRPM trap. Typically used when leaving
    55425634 * VT-x to execute any instruction.
    55435635 *
    5544  * @param   pvCpu               Pointer to the VMCPU.
     5636 * @param   pvCpu           Pointer to the VMCPU.
    55455637 */
    55465638static void hmR0VmxUpdateTRPMTrap(PVMCPU pVCpu)
     
    55545646
    55555647        /* If a trap was already pending, we did something wrong! */
    5556         Assert(TRPMQueryTrap(pVCpu, NULL, NULL) == VERR_TRPM_NO_ACTIVE_TRAP);
    5557 
    5558         /* A page-fault exception during a page-fault would become a double-fault. */
    5559         AssertMsg(uVectorType != VMX_IDT_VECTORING_INFO_TYPE_HW_XCPT || uVector != X86_XCPT_PF,
    5560                   ("%#RX64 uVectorType=%#x uVector=%#x\n", pVCpu->hm.s.Event.u64IntrInfo, uVectorType, uVector));
     5648        Assert(TRPMQueryTrap(pVCpu, NULL /* pu8TrapNo */, NULL /* pEnmType */) == VERR_TRPM_NO_ACTIVE_TRAP);
    55615649
    55625650        TRPMEVENT enmTrapType;
     
    55805668                break;
    55815669        }
     5670
    55825671        Log(("Converting pending HM event to TRPM trap uVector=%#x enmTrapType=%d\n", uVector, enmTrapType));
     5672
    55835673        int rc = TRPMAssertTrap(pVCpu, uVector, enmTrapType);
    55845674        AssertRC(rc);
    55855675        if (fErrorCodeValid)
    55865676            TRPMSetErrorCode(pVCpu, uErrorCode);
    5587         AssertRC(rc);
     5677
     5678        /* A page-fault exception during a page-fault would become a double-fault. */
     5679        if (   uVectorType == VMX_IDT_VECTORING_INFO_TYPE_HW_XCPT
     5680            && uVector == X86_XCPT_PF)
     5681        {
     5682            TRPMSetFaultAddress(pVCpu, pVCpu->hm.s.Event.GCPtrFaultAddress);
     5683        }
     5684        else if (   uVectorType == VMX_IDT_VECTORING_INFO_TYPE_SW_INT
     5685                 || uVectorType == VMX_IDT_VECTORING_INFO_TYPE_SW_XCPT)
     5686        {
     5687            AssertMsg(   uVectorType == VMX_IDT_VECTORING_INFO_TYPE_SW_INT
     5688                      || (uVector == X86_XCPT_BP || uVector == X86_XCPT_OF),
     5689                      ("Invalid vector: uVector=%#x uVectorType=%#x\n", uVector, uVectorType));
     5690            TRPMSetInstrLength(pVCpu, pVCpu->hm.s.Event.cbInstr);
     5691        }
    55885692        pVCpu->hm.s.Event.fPending = false;
    55895693    }
     
    57305834
    57315835/**
    5732  * Injects any pending TRPM trap into the VM by updating the VMCS.
    5733  *
    5734  * @returns VBox status code (informational status code included).
    5735  * @param   pVM             Pointer to the VM.
     5836 * Sets the interrupt-window exiting control in the VMCS which instructs VT-x to
     5837 * cause a VM-exit as soon as the guest is in a state to receive interrupts.
     5838 *
     5839 * @returns VBox status code.
     5840 * @param pVCpu         Pointer to the VMCPU.
     5841 */
     5842DECLINLINE(void) hmR0VmxSetIntWindowExitVmcs(PVMCPU pVCpu)
     5843{
     5844    if (RT_LIKELY(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.msr.vmx_proc_ctls.n.allowed1 & VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_INT_WINDOW_EXIT))
     5845    {
     5846        /* Enable interrupt-window exiting if it's not in effect already. */
     5847        if (!(pVCpu->hm.s.vmx.u32ProcCtls & VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_INT_WINDOW_EXIT))
     5848        {
     5849            pVCpu->hm.s.vmx.u32ProcCtls |= VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_INT_WINDOW_EXIT;
     5850            int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC_CONTROLS, pVCpu->hm.s.vmx.u32ProcCtls);
     5851            AssertRC(rc);
     5852        }
     5853    } /* else we will deliver interrupts whenever the guest exits next and is in a state to receive events. */
     5854}
     5855
     5856
     5857/**
     5858 * Checks if there are any pending guest interrupts to be delivered and injects
     5859 * them into the VM by updating the VMCS.
     5860 *
     5861 * @returns VBox status code (informational status codes included).
    57365862 * @param   pVCpu           Pointer to the VMCPU.
    57375863 * @param   pMixedCtx       Pointer to the guest-CPU context. The data may be
     
    57395865 *                          before using them.
    57405866 */
    5741 static int hmR0VmxInjectTRPMTrap(PVM pVM, PVMCPU pVCpu, PCPUMCTX pMixedCtx)
    5742 {
    5743     if (!TRPMHasTrap(pVCpu))
    5744         return VINF_SUCCESS;
    5745 
    5746     uint8_t   u8Vector     = 0;
    5747     TRPMEVENT enmTrpmEvent = TRPM_SOFTWARE_INT;
    5748     RTGCUINT  uErrCode     = 0;
    5749 
    5750     int rc = TRPMQueryTrapAll(pVCpu, &u8Vector, &enmTrpmEvent, &uErrCode, NULL /* puCr2 */);
    5751     rc    |= TRPMResetTrap(pVCpu);
    5752     AssertRCReturn(rc, rc);
    5753 
    5754     /* Refer Intel spec. 24.8.3 "VM-entry Controls for Event Injection" for the format of u32IntrInfo. */
    5755     uint32_t u32IntrInfo = u8Vector | (1 << VMX_EXIT_INTERRUPTION_INFO_VALID_SHIFT);
    5756     if (enmTrpmEvent == TRPM_TRAP)
    5757     {
    5758         switch (u8Vector)
    5759         {
    5760             case X86_XCPT_BP:
    5761             case X86_XCPT_OF:
     5867static int hmR0VmxInjectEvent(PVMCPU pVCpu, PCPUMCTX pMixedCtx)
     5868{
     5869    /* Get the current interruptibility-state of the guest and then figure out what can be injected. */
     5870    uint32_t uIntrState  = hmR0VmxGetGuestIntrState(pVCpu, pMixedCtx);
     5871    const bool fBlockMovSS = (uIntrState & VMX_VMCS_GUEST_INTERRUPTIBILITY_STATE_BLOCK_MOVSS);
     5872    const bool fBlockSti   = (uIntrState & VMX_VMCS_GUEST_INTERRUPTIBILITY_STATE_BLOCK_STI);
     5873
     5874    int rc = VINF_SUCCESS;
     5875    if (pVCpu->hm.s.Event.fPending)     /* First, inject any pending HM events. */
     5876    {
     5877        uint32_t uIntrType = VMX_EXIT_INTERRUPTION_INFO_TYPE((uint32_t)pVCpu->hm.s.Event.u64IntrInfo);
     5878        bool fInject = true;
     5879        if (uIntrType == VMX_EXIT_INTERRUPTION_INFO_TYPE_EXT_INT)
     5880        {
     5881            rc = hmR0VmxSaveGuestRflags(pVCpu, pMixedCtx);
     5882            AssertRCReturn(rc, rc);
     5883            const bool fBlockInt = !(pMixedCtx->eflags.u32 & X86_EFL_IF);
     5884            if (   fBlockInt
     5885                || fBlockSti
     5886                || fBlockMovSS)
    57625887            {
    5763                 /* These exceptions must be delivered as software exceptions. They have no error codes associated with them. */
    5764                 u32IntrInfo |= (VMX_EXIT_INTERRUPTION_INFO_TYPE_SW_XCPT << VMX_EXIT_INTERRUPTION_INFO_TYPE_SHIFT);
    5765                 break;
     5888                fInject = false;
    57665889            }
    5767 
    5768             case X86_XCPT_DF:
    5769             case X86_XCPT_TS:
    5770             case X86_XCPT_NP:
    5771             case X86_XCPT_SS:
    5772             case X86_XCPT_GP:
    5773             case X86_XCPT_PF:
    5774             case X86_XCPT_AC:
    5775                 /* These exceptions must be delivered as hardware exceptions. They have error codes associated with
    5776                    them which VT-x/VMM pushes to the guest stack. */
    5777                 u32IntrInfo |= VMX_EXIT_INTERRUPTION_INFO_ERROR_CODE_VALID;
    5778                 /* no break! */
    5779             default:
     5890        }
     5891        else if (   uIntrType == VMX_EXIT_INTERRUPTION_INFO_TYPE_NMI
     5892                 && (   fBlockMovSS
     5893                     || fBlockSti))
     5894        {
     5895            /* On some CPUs block-by-STI also blocks NMIs. See Intel spec. 26.3.1.5 "Checks On Guest Non-Register State". */
     5896            fInject = false;
     5897        }
     5898
     5899        if (fInject)
     5900        {
     5901            Log(("Injecting pending event\n"));
     5902            rc = hmR0VmxInjectEventVmcs(pVCpu, pMixedCtx, pVCpu->hm.s.Event.u64IntrInfo, pVCpu->hm.s.Event.cbInstr,
     5903                                        pVCpu->hm.s.Event.u32ErrCode, &uIntrState);
     5904            AssertRCReturn(rc, rc);
     5905            pVCpu->hm.s.Event.fPending = false;
     5906        }
     5907    }                                                           /** @todo SMI. SMIs take priority over NMIs. */
     5908    else if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INTERRUPT_NMI))    /* NMI. NMIs take priority over regular interrupts . */
     5909    {
     5910        /* On some CPUs block-by-STI also blocks NMIs. See Intel spec. 26.3.1.5 "Checks On Guest Non-Register State". */
     5911        if (!fBlockMovSS && !fBlockSti)
     5912        {
     5913            Log(("Injecting NMI\n"));
     5914            RTGCUINTPTR uIntrInfo;
     5915            uIntrInfo  = X86_XCPT_NMI;
     5916            uIntrInfo |= (1 << VMX_EXIT_INTERRUPTION_INFO_VALID_SHIFT);
     5917            uIntrInfo |= (VMX_EXIT_INTERRUPTION_INFO_TYPE_NMI << VMX_EXIT_INTERRUPTION_INFO_TYPE_SHIFT);
     5918            rc = hmR0VmxInjectEventVmcs(pVCpu, pMixedCtx, uIntrInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, &uIntrState);
     5919            AssertRCReturn(rc, rc);
     5920            VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_NMI);
     5921        }
     5922        else
     5923            hmR0VmxSetIntWindowExitVmcs(pVCpu);
     5924    }
     5925    else if (VMCPU_FF_IS_PENDING(pVCpu, (VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC)))
     5926    {
     5927        /* Check if there are guest external interrupts (PIC/APIC) pending and inject them if the guest can receive them. */
     5928        rc = hmR0VmxSaveGuestRflags(pVCpu, pMixedCtx);
     5929        AssertRCReturn(rc, rc);
     5930        const bool fBlockInt = !(pMixedCtx->eflags.u32 & X86_EFL_IF);
     5931        if (   !fBlockInt
     5932            && !fBlockSti
     5933            && !fBlockMovSS)
     5934        {
     5935            uint8_t u8Interrupt = 0;
     5936            rc = PDMGetInterrupt(pVCpu, &u8Interrupt);
     5937            if (RT_SUCCESS(rc))
    57805938            {
    5781                 u32IntrInfo |= (VMX_EXIT_INTERRUPTION_INFO_TYPE_HW_XCPT << VMX_EXIT_INTERRUPTION_INFO_TYPE_SHIFT);
    5782                 break;
     5939                Log(("Injecting interrupt u8Interrupt=%#x\n", u8Interrupt));
     5940                uint32_t u32IntrInfo = u8Interrupt | (1 << VMX_EXIT_INTERRUPTION_INFO_VALID_SHIFT);
     5941                u32IntrInfo         |= (VMX_EXIT_INTERRUPTION_INFO_TYPE_EXT_INT << VMX_EXIT_INTERRUPTION_INFO_TYPE_SHIFT);
     5942                rc = hmR0VmxInjectEventVmcs(pVCpu, pMixedCtx, u32IntrInfo, 0 /* cbInstr */,  0 /* u32ErrCode */, &uIntrState);
    57835943            }
    5784         }
    5785     }
    5786     else if (enmTrpmEvent == TRPM_HARDWARE_INT)
    5787         u32IntrInfo |= (VMX_EXIT_INTERRUPTION_INFO_TYPE_EXT_INT << VMX_EXIT_INTERRUPTION_INFO_TYPE_SHIFT);
    5788     else if (enmTrpmEvent == TRPM_SOFTWARE_INT)
    5789         u32IntrInfo |= (VMX_EXIT_INTERRUPTION_INFO_TYPE_SW_INT << VMX_EXIT_INTERRUPTION_INFO_TYPE_SHIFT);
    5790     else
    5791         AssertMsgFailed(("Invalid TRPM event type %d\n", enmTrpmEvent));
    5792 
    5793     STAM_COUNTER_INC(&pVCpu->hm.s.StatIntInject);
    5794     return hmR0VmxInjectEventVmcs(pVCpu, pMixedCtx, u32IntrInfo, 0 /* cbInstr */, uErrCode);
    5795 }
    5796 
    5797 
    5798 /**
    5799  * Checks if there are any pending guest interrupts to be delivered and injects
    5800  * them into the VM by updating the VMCS.
    5801  *
    5802  * @returns VBox status code (informational status codes included).
    5803  * @param   pVM             Pointer to the VM.
     5944            else
     5945            {
     5946                /** @todo Does this actually happen? If not turn it into an assertion. */
     5947                Assert(!VMCPU_FF_IS_PENDING(pVCpu, (VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC)));
     5948                STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchGuestIrq);
     5949                rc = VINF_SUCCESS;
     5950            }
     5951        }
     5952        else
     5953            hmR0VmxSetIntWindowExitVmcs(pVCpu);
     5954    }
     5955
     5956    /*
     5957     * There's no need to clear the entry-interruption information field here if we're not injecting anything.
     5958     * VT-x clears the valid bit on every VM-exit. See Intel spec. 24.8.3 "VM-Entry Controls for Event Injection".
     5959     */
     5960    hmR0VmxLoadGuestIntrState(pVCpu, uIntrState);
     5961    return rc;
     5962}
     5963
     5964
     5965/**
     5966 * Sets an invalid-opcode (#UD) exception as pending-for-injection into the VM.
     5967 *
    58045968 * @param   pVCpu           Pointer to the VMCPU.
    58055969 * @param   pMixedCtx       Pointer to the guest-CPU context. The data may be
    58065970 *                          out-of-sync. Make sure to update the required fields
    58075971 *                          before using them.
    5808  *
    5809  * @remarks Must be called after hmR0VmxLoadGuestIntrState().
    5810  */
    5811 static int hmR0VmxInjectPendingInterrupt(PVM pVM, PVMCPU pVCpu, PCPUMCTX pMixedCtx)
    5812 {
    5813     /* First inject any pending HM interrupts. */
    5814     if (pVCpu->hm.s.Event.fPending)
    5815     {
    5816         Log(("Injecting pending event\n"));
    5817         int rc = hmR0VmxInjectEventVmcs(pVCpu, pMixedCtx, pVCpu->hm.s.Event.u64IntrInfo, pVCpu->hm.s.Event.cbInstr,
    5818                                         pVCpu->hm.s.Event.u32ErrCode);
    5819         AssertRCReturn(rc, rc);
    5820         pVCpu->hm.s.Event.fPending = false;
    5821         return rc;
    5822     }
    5823 
    5824     /** @todo SMI. SMIs take priority over NMIs. */
    5825 
    5826     /* NMI. NMIs take priority over regular interrupts . */
    5827     if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_NMI))
    5828     {
    5829         /* Construct an NMI interrupt and inject it into the VMCS. */
    5830         RTGCUINTPTR uIntrInfo;
    5831         uIntrInfo  = X86_XCPT_NMI;
    5832         uIntrInfo |= (1 << VMX_EXIT_INTERRUPTION_INFO_VALID_SHIFT);
    5833         uIntrInfo |= (VMX_EXIT_INTERRUPTION_INFO_TYPE_NMI << VMX_EXIT_INTERRUPTION_INFO_TYPE_SHIFT);
    5834         Log(("Injecting NMI\n"));
    5835         int rc = hmR0VmxInjectEventVmcs(pVCpu, pMixedCtx, uIntrInfo, 0 /* cbInstr */, 0 /* u32ErrCode */);
    5836         AssertRCReturn(rc, rc);
    5837         return rc;
    5838     }
    5839 
    5840     /* We need the guests's RFLAGS for sure from this point on, make sure it is updated. */
    5841     int rc = hmR0VmxSaveGuestRflags(pVCpu, pMixedCtx);
    5842     AssertRCReturn(rc, rc);
    5843 
    5844     /* If there isn't any active trap, check if we have pending interrupts and convert them to TRPM traps and deliver them. */
    5845     if (!TRPMHasTrap(pVCpu))
    5846     {
    5847         /* Check if there are guest external interrupts (PIC/APIC) pending. */
    5848         if (VMCPU_FF_IS_PENDING(pVCpu, (VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC)))
    5849         {
    5850             /*
    5851              * If the guest can receive interrupts now (interrupts enabled and no interrupt inhibition is active) convert
    5852              * the PDM interrupt into a TRPM event and inject it.
    5853              */
    5854             if (   (pMixedCtx->eflags.u32 & X86_EFL_IF)
    5855                 && !VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
    5856             {
    5857                 uint8_t u8Interrupt = 0;
    5858                 rc = PDMGetInterrupt(pVCpu, &u8Interrupt);
    5859                 if (RT_SUCCESS(rc))
    5860                 {
    5861                     Log(("PDMGetInterrupt: u8Interrupt=%#x\n", u8Interrupt));
    5862                     /* Convert pending interrupt from PIC/APIC into TRPM and handle it below. */
    5863                     rc = TRPMAssertTrap(pVCpu, u8Interrupt, TRPM_HARDWARE_INT);
    5864                     AssertRCReturn(rc, rc);
    5865                 }
    5866                 else
    5867                 {
    5868                     /** @todo Does this actually happen? If not turn it into an assertion. */
    5869                     Assert(!VMCPU_FF_IS_PENDING(pVCpu, (VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC)));
    5870                     STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchGuestIrq);
    5871                 }
    5872             }
    5873             else if (   !(pVCpu->hm.s.vmx.u32ProcCtls & VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_INT_WINDOW_EXIT)
    5874                      && (pVM->hm.s.vmx.msr.vmx_proc_ctls.n.allowed1 & VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_INT_WINDOW_EXIT))
    5875             {
    5876                 /* Instruct VT-x to cause an interrupt-window exit as soon as the guest is ready to receive interrupts again. */
    5877                 pVCpu->hm.s.vmx.u32ProcCtls |= VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_INT_WINDOW_EXIT;
    5878                 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC_CONTROLS, pVCpu->hm.s.vmx.u32ProcCtls);
    5879                 AssertRCReturn(rc, rc);
    5880             }
    5881             /* else we will deliver interrupts whenever the guest exits next and it's in a state to receive interrupts. */
    5882         }
    5883     }
    5884 
    5885     /* If interrupts can be delivered, inject it into the VM. */
    5886     if (   (pMixedCtx->eflags.u32 & X86_EFL_IF)
    5887         && !VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS)
    5888         && TRPMHasTrap(pVCpu))
    5889     {
    5890         Log(("Injecting TRPM trap\n"));
    5891         rc = hmR0VmxInjectTRPMTrap(pVM, pVCpu, pMixedCtx);
    5892         Assert(!TRPMHasTrap(pVCpu));
    5893         AssertRCReturn(rc, rc);
    5894     }
    5895 
    5896     /*
    5897      * There's no need to clear the entry-interruption information field here if we're not injecting anything. VT-x clears the
    5898      * valid bit on every VM-exit. See Intel spec. 24.8.3 "VM-Entry Controls for Event Injection".
    5899      */
    5900     return rc;
    5901 }
    5902 
    5903 /**
    5904  * Sets an invalid-opcode (#UD) exception as pending-for-injection into the VM.
     5972 */
     5973DECLINLINE(void) hmR0VmxSetPendingXcptUD(PVMCPU pVCpu, PCPUMCTX pMixedCtx)
     5974{
     5975    /* Refer Intel spec. 24.8.3 "VM-entry Controls for Event Injection" for the format of u32IntrInfo. */
     5976    uint32_t u32IntrInfo = X86_XCPT_UD | (1 << VMX_EXIT_INTERRUPTION_INFO_VALID_SHIFT);
     5977    STAM_COUNTER_INC(&pVCpu->hm.s.StatIntInject);
     5978    hmR0VmxSetPendingEvent(pVCpu, u32IntrInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
     5979}
     5980
     5981
     5982/**
     5983 * Sets a double-fault (#DF) exception as pending-for-injection into the VM.
     5984 *
     5985 * @param   pVCpu           Pointer to the VMCPU.
     5986 * @param   pMixedCtx       Pointer to the guest-CPU context. The data may be
     5987 *                          out-of-sync. Make sure to update the required fields
     5988 *                          before using them.
     5989 */
     5990DECLINLINE(void) hmR0VmxSetPendingXcptDF(PVMCPU pVCpu, PCPUMCTX pMixedCtx)
     5991{
     5992    /* Inject the double-fault. */
     5993    uint32_t u32IntrInfo = X86_XCPT_DF | (1 << VMX_EXIT_INTERRUPTION_INFO_VALID_SHIFT);
     5994    u32IntrInfo         |= (VMX_EXIT_INTERRUPTION_INFO_TYPE_HW_XCPT << VMX_EXIT_INTERRUPTION_INFO_TYPE_SHIFT);
     5995    u32IntrInfo         |= VMX_EXIT_INTERRUPTION_INFO_ERROR_CODE_VALID;
     5996    STAM_COUNTER_INC(&pVCpu->hm.s.StatIntInject);
     5997    hmR0VmxSetPendingEvent(pVCpu, u32IntrInfo,  0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
     5998}
     5999
     6000
     6001/**
     6002 * Injects a double-fault (#DF) exception into the VM.
    59056003 *
    59066004 * @returns VBox status code (informational status code included).
     
    59106008 *                          before using them.
    59116009 */
    5912 DECLINLINE(int) hmR0VmxSetPendingXcptUD(PVMCPU pVCpu, PCPUMCTX pMixedCtx)
    5913 {
    5914     /* Refer Intel spec. 24.8.3 "VM-entry Controls for Event Injection" for the format of u32IntrInfo. */
    5915     uint32_t u32IntrInfo = X86_XCPT_UD | (1 << VMX_EXIT_INTERRUPTION_INFO_VALID_SHIFT);
    5916     STAM_COUNTER_INC(&pVCpu->hm.s.StatIntInject);
    5917     hmR0VmxSetPendingEvent(pVCpu, u32IntrInfo, 0 /* cbInstr */, 0 /* u32ErrCode */);
    5918     return VINF_SUCCESS;
    5919 }
    5920 
    5921 
    5922 /**
    5923  * Sets a double-fault (#DF) exception as pending-for-injection into the VM.
    5924  *
    5925  * @param   pVCpu           Pointer to the VMCPU.
    5926  * @param   pMixedCtx       Pointer to the guest-CPU context. The data may be
    5927  *                          out-of-sync. Make sure to update the required fields
    5928  *                          before using them.
    5929  */
    5930 DECLINLINE(void) hmR0VmxSetPendingXcptDF(PVMCPU pVCpu, PCPUMCTX pMixedCtx)
     6010DECLINLINE(int) hmR0VmxInjectXcptDF(PVMCPU pVCpu, PCPUMCTX pMixedCtx, uint32_t *puIntrState)
    59316011{
    59326012    /* Inject the double-fault. */
     
    59356015    u32IntrInfo         |= VMX_EXIT_INTERRUPTION_INFO_ERROR_CODE_VALID;
    59366016    STAM_COUNTER_INC(&pVCpu->hm.s.StatIntInject);
    5937     hmR0VmxSetPendingEvent(pVCpu, u32IntrInfo,  0 /* cbInstr */, 0 /* u32ErrCode */);
    5938 }
    5939 
    5940 
    5941 /**
    5942  * Injects a double-fault (#DF) exception into the VM.
    5943  *
    5944  * @returns VBox status code (informational status code included).
     6017    return hmR0VmxInjectEventVmcs(pVCpu, pMixedCtx, u32IntrInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, puIntrState);
     6018}
     6019
     6020
     6021/**
     6022 * Sets a debug (#DB) exception as pending-for-injection into the VM.
     6023 *
    59456024 * @param   pVCpu           Pointer to the VMCPU.
    59466025 * @param   pMixedCtx       Pointer to the guest-CPU context. The data may be
     
    59486027 *                          before using them.
    59496028 */
    5950 DECLINLINE(int) hmR0VmxInjectXcptDF(PVMCPU pVCpu, PCPUMCTX pMixedCtx)
    5951 {
    5952     /* Inject the double-fault. */
    5953     uint32_t u32IntrInfo = X86_XCPT_DF | (1 << VMX_EXIT_INTERRUPTION_INFO_VALID_SHIFT);
    5954     u32IntrInfo         |= (VMX_EXIT_INTERRUPTION_INFO_TYPE_HW_XCPT << VMX_EXIT_INTERRUPTION_INFO_TYPE_SHIFT);
    5955     u32IntrInfo         |= VMX_EXIT_INTERRUPTION_INFO_ERROR_CODE_VALID;
    5956     STAM_COUNTER_INC(&pVCpu->hm.s.StatIntInject);
    5957     return hmR0VmxInjectEventVmcs(pVCpu, pMixedCtx, u32IntrInfo,  0 /* cbInstr */, 0 /* u32ErrCode */);
    5958 }
    5959 
    5960 
    5961 /**
    5962  * Sets a debug (#DB) exception as pending-for-injection into the VM.
    5963  *
    5964  * @returns VBox status code (informational status code included).
    5965  * @param   pVCpu           Pointer to the VMCPU.
    5966  * @param   pMixedCtx       Pointer to the guest-CPU context. The data may be
    5967  *                          out-of-sync. Make sure to update the required fields
    5968  *                          before using them.
    5969  */
    5970 DECLINLINE(int) hmR0VmxSetPendingXcptDB(PVMCPU pVCpu, PCPUMCTX pMixedCtx)
     6029DECLINLINE(void) hmR0VmxSetPendingXcptDB(PVMCPU pVCpu, PCPUMCTX pMixedCtx)
    59716030{
    59726031    /* Inject the debug-exception. */
     
    59746033    u32IntrInfo         |= (VMX_EXIT_INTERRUPTION_INFO_TYPE_HW_XCPT << VMX_EXIT_INTERRUPTION_INFO_TYPE_SHIFT);
    59756034    STAM_COUNTER_INC(&pVCpu->hm.s.StatIntInject);
    5976     hmR0VmxSetPendingEvent(pVCpu, u32IntrInfo, 0 /* cbInstr */, 0 /* u32ErrCode */);
    5977     return VINF_SUCCESS;
     6035    hmR0VmxSetPendingEvent(pVCpu, u32IntrInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
    59786036}
    59796037
     
    59826040 * Sets an overflow (#OF) exception as pending-for-injection into the VM.
    59836041 *
    5984  * @returns VBox status code (informational status code included).
    59856042 * @param   pVCpu           Pointer to the VMCPU.
    59866043 * @param   pMixedCtx       Pointer to the guest-CPU context. The data may be
     
    59906047 *                          stack.
    59916048 */
    5992 DECLINLINE(int) hmR0VmxSetPendingXcptOF(PVMCPU pVCpu, PCPUMCTX pMixedCtx, uint32_t cbInstr)
     6049DECLINLINE(void) hmR0VmxSetPendingXcptOF(PVMCPU pVCpu, PCPUMCTX pMixedCtx, uint32_t cbInstr)
    59936050{
    59946051    /* Inject the overflow exception. */
     
    59966053    u32IntrInfo         |= (VMX_EXIT_INTERRUPTION_INFO_TYPE_SW_INT << VMX_EXIT_INTERRUPTION_INFO_TYPE_SHIFT);
    59976054    STAM_COUNTER_INC(&pVCpu->hm.s.StatIntInject);
    5998     hmR0VmxSetPendingEvent(pVCpu, u32IntrInfo, cbInstr, 0 /* u32ErrCode */);
    5999     return VINF_SUCCESS;
     6055    hmR0VmxSetPendingEvent(pVCpu, u32IntrInfo, cbInstr, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
    60006056}
    60016057
     
    60116067 * @param   u32ErrorCode    The error code associated with the #GP.
    60126068 */
    6013 DECLINLINE(int) hmR0VmxInjectXcptGP(PVMCPU pVCpu, PCPUMCTX pMixedCtx, bool fErrorCodeValid, uint32_t u32ErrorCode)
     6069DECLINLINE(int) hmR0VmxInjectXcptGP(PVMCPU pVCpu, PCPUMCTX pMixedCtx, bool fErrorCodeValid, uint32_t u32ErrorCode,
     6070                                    uint32_t *puIntrState)
    60146071{
    60156072    /* Inject the general-protection fault. */
     
    60196076        u32IntrInfo |= VMX_EXIT_INTERRUPTION_INFO_ERROR_CODE_VALID;
    60206077    STAM_COUNTER_INC(&pVCpu->hm.s.StatIntInject);
    6021     return hmR0VmxInjectEventVmcs(pVCpu, pMixedCtx, u32IntrInfo, 0 /* cbInstr */, u32ErrorCode);
    6022 }
    6023 
    6024 
    6025 /**
    6026  * Injects a software interrupt (INTn) into the VM.
    6027  *
    6028  * @returns VBox status code (informational status code included).
     6078    return hmR0VmxInjectEventVmcs(pVCpu, pMixedCtx, u32IntrInfo, 0 /* cbInstr */, u32ErrorCode, puIntrState);
     6079}
     6080
     6081
     6082/**
     6083 * Sets a software interrupt (INTn) as pending-for-injection into the VM.
     6084 *
    60296085 * @param   pVCpu           Pointer to the VMCPU.
    60306086 * @param   pMixedCtx       Pointer to the guest-CPU context. The data may be
     
    60356091 *                          stack.
    60366092 */
    6037 DECLINLINE(int) hmR0VmxInjectIntN(PVMCPU pVCpu, PCPUMCTX pMixedCtx, uint16_t uVector, uint32_t cbInstr)
     6093DECLINLINE(void) hmR0VmxSetPendingIntN(PVMCPU pVCpu, PCPUMCTX pMixedCtx, uint16_t uVector, uint32_t cbInstr)
    60386094{
    60396095    /* Inject the INTn. */
     
    60416097    u32IntrInfo         |= (VMX_EXIT_INTERRUPTION_INFO_TYPE_SW_INT << VMX_EXIT_INTERRUPTION_INFO_TYPE_SHIFT);
    60426098    STAM_COUNTER_INC(&pVCpu->hm.s.StatIntInject);
    6043     hmR0VmxSetPendingEvent(pVCpu, u32IntrInfo, cbInstr, 0 /* u32ErrCode */);
    6044     return VINF_SUCCESS;
     6099    hmR0VmxSetPendingEvent(pVCpu, u32IntrInfo, cbInstr, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
    60456100}
    60466101
     
    60916146 *
    60926147 * @remarks No-long-jump zone!!!
     6148 * @remarks Requires CR0!
    60936149 */
    60946150static int hmR0VmxInjectEventVmcs(PVMCPU pVCpu, PCPUMCTX pMixedCtx, uint64_t u64IntrInfo, uint32_t cbInstr,
    6095                                   uint32_t u32ErrCode)
     6151                                  uint32_t u32ErrCode, uint32_t *puIntrState)
    60966152{
    60976153    /* Intel spec. 24.8.3 "VM-Entry Controls for Event Injection" specifies the interruption-information field to be 32-bits. */
    60986154    AssertMsg(u64IntrInfo >> 32 == 0, ("%#RX64\n", u64IntrInfo));
     6155    Assert(puIntrState);
    60996156    uint32_t u32IntrInfo = (uint32_t)u64IntrInfo;
     6157
     6158    const uint32_t uVector = VMX_EXIT_INTERRUPTION_INFO_VECTOR(u32IntrInfo);
     6159    const uint32_t uIntrType = VMX_EXIT_INTERRUPTION_INFO_TYPE(u32IntrInfo);
     6160
     6161    /* Cannot inject an NMI when block-by-MOV SS is in effect. */
     6162    Assert(   uIntrType != VMX_EXIT_INTERRUPTION_INFO_TYPE_NMI
     6163           || !((*puIntrState) & VMX_VMCS_GUEST_INTERRUPTIBILITY_STATE_BLOCK_MOVSS));
     6164
     6165    STAM_COUNTER_INC(&pVCpu->hm.s.paStatInjectedIrqsR0[uVector & MASK_INJECT_IRQ_STAT]);
    61006166
    61016167    /* We require CR0 to check if the guest is in real-mode. */
     
    61036169    AssertRCReturn(rc, rc);
    61046170
    6105     const uint32_t uVector = VMX_EXIT_INTERRUPTION_INFO_VECTOR(u32IntrInfo);
    61066171    STAM_COUNTER_INC(&pVCpu->hm.s.paStatInjectedIrqsR0[uVector & MASK_INJECT_IRQ_STAT]);
    61076172
     
    61356200                {
    61366201                    /* If we're injecting a #GP with no valid IDT entry, inject a double-fault. */
    6137                     return hmR0VmxInjectXcptDF(pVCpu, pMixedCtx);
     6202                    return hmR0VmxInjectXcptDF(pVCpu, pMixedCtx, puIntrState);
    61386203                }
    61396204
    61406205                /* If we're injecting an interrupt/exception with no valid IDT entry, inject a general-protection fault. */
    61416206                /* No error codes for exceptions in real-mode. See Intel spec. 20.1.4 "Interrupt and Exception Handling" */
    6142                 return hmR0VmxInjectXcptGP(pVCpu, pMixedCtx, false /* fErrCodeValid */, 0 /* u32ErrCode */);
     6207                return hmR0VmxInjectXcptGP(pVCpu, pMixedCtx, false /* fErrCodeValid */, 0 /* u32ErrCode */, puIntrState);
    61436208            }
    61446209
     
    61796244                                                | HM_CHANGED_GUEST_RFLAGS
    61806245                                                | HM_CHANGED_GUEST_RSP;
     6246
     6247                /* We're clearing interrupts, which means no block-by-STI interrupt-inhibition. */
     6248                if (*puIntrState & VMX_VMCS_GUEST_INTERRUPTIBILITY_STATE_BLOCK_STI)
     6249                {
     6250                    Assert(   uIntrType != VMX_EXIT_INTERRUPTION_INFO_TYPE_NMI
     6251                           && uIntrType != VMX_EXIT_INTERRUPTION_INFO_TYPE_EXT_INT);
     6252                    Log(("Clearing inhibition due to STI.\n"));
     6253                    *puIntrState &= ~VMX_VMCS_GUEST_INTERRUPTIBILITY_STATE_BLOCK_STI;
     6254                }
     6255                Log(("Injecting u32IntrInfo=%#x u32ErrCode=%#x instrlen=%#x\n", u32IntrInfo, u32ErrCode, cbInstr));
    61816256            }
    61826257            Assert(rc == VINF_SUCCESS || rc == VINF_EM_RESET);
     
    61996274    Assert(!(u32IntrInfo & 0x7ffff000));                                /* Bits 30:12 MBZ. */
    62006275    Log(("Injecting u32IntrInfo=%#x u32ErrCode=%#x instrlen=%#x\n", u32IntrInfo, u32ErrCode, cbInstr));
    6201 
    62026276    rc  = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, u32IntrInfo);
    62036277    if (VMX_EXIT_INTERRUPTION_INFO_ERROR_CODE_IS_VALID(u32IntrInfo))
     
    62056279    rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH, cbInstr);
    62066280    AssertRCReturn(rc, rc);
     6281
     6282    Assert(uIntrType != VMX_EXIT_INTERRUPTION_INFO_TYPE_SW_INT);
    62076283    return rc;
    62086284}
     
    64666542     * This is why this is done after all possible exits-to-ring-3 paths in this code.
    64676543     */
    6468     hmR0VmxLoadGuestIntrState(pVM, pVCpu, pMixedCtx);
    6469     rc = hmR0VmxInjectPendingInterrupt(pVM, pVCpu, pMixedCtx);
     6544    rc = hmR0VmxInjectEvent(pVCpu, pMixedCtx);
    64706545    AssertRCReturn(rc, rc);
    64716546    return rc;
     
    66626737    int          rc     = VERR_INTERNAL_ERROR_5;
    66636738    uint32_t     cLoops = 0;
     6739    hmR0VmxUpdatePendingEvent(pVCpu, pCtx);
    66646740
    66656741    for (;; cLoops++)
     
    67046780        STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatExit1, &pVCpu->hm.s.StatExit2, x);
    67056781        AssertMsg(VmxTransient.uExitReason <= VMX_EXIT_MAX, ("%#x\n", VmxTransient.uExitReason));
    6706         rc = (*s_apfnVMExitHandlers[VmxTransient.uExitReason])(pVCpu, pCtx, &VmxTransient);
     6782        rc = (*g_apfnVMExitHandlers[VmxTransient.uExitReason])(pVCpu, pCtx, &VmxTransient);
    67076783        STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExit2, x);
    67086784        if (rc != VINF_SUCCESS)
     
    68756951{
    68766952    VMX_VALIDATE_EXIT_HANDLER_PARAMS();
     6953    STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitXcptNmi, y3);
     6954
    68776955    int rc = hmR0VmxReadExitIntrInfoVmcs(pVCpu, pVmxTransient);
    68786956    AssertRCReturn(rc, rc);
     
    68836961
    68846962    if (uIntrType == VMX_EXIT_INTERRUPTION_INFO_TYPE_NMI)
     6963    {
     6964        STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitXcptNmi, y3);
    68856965        return VINF_EM_RAW_INTERRUPT;
     6966    }
    68866967
    68876968    /* If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly. */
    68886969    rc = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pMixedCtx, pVmxTransient);
    68896970    if (RT_UNLIKELY(rc == VINF_VMX_DOUBLE_FAULT))
     6971    {
     6972        STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitXcptNmi, y3);
    68906973        return VINF_SUCCESS;
     6974    }
    68916975    else if (RT_UNLIKELY(rc == VINF_EM_RESET))
     6976    {
     6977        STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitXcptNmi, y3);
    68926978        return rc;
     6979    }
    68936980
    68946981    uint32_t uExitIntrInfo = pVmxTransient->uExitIntrInfo;
     
    69357022                        AssertRCReturn(rc, rc);
    69367023                        hmR0VmxSetPendingEvent(pVCpu, VMX_VMCS_CTRL_ENTRY_IRQ_INFO_FROM_EXIT_INT_INFO(uExitIntrInfo),
    6937                                                pVmxTransient->cbInstr, pVmxTransient->uExitIntrErrorCode);
     7024                                               pVmxTransient->cbInstr, pVmxTransient->uExitIntrErrorCode,
     7025                                               0 /* GCPtrFaultAddress */);
    69387026                        AssertRCReturn(rc, rc);
    69397027                    }
     
    69577045        }
    69587046    }
     7047    STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitXcptNmi, y3);
    69597048    return rc;
    69607049}
     
    69747063    AssertRCReturn(rc, rc);
    69757064
    6976     /* Deliver the pending interrupt via hmR0VmxPreRunGuest()->hmR0VmxInjectPendingInterrupt() and resume guest execution. */
     7065    /* Deliver the pending interrupt via hmR0VmxPreRunGuest()->hmR0VmxInjectEvent() and resume guest execution. */
    69777066    STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIntWindow);
    69787067    return VINF_SUCCESS;
     
    75627651        }
    75637652    }
    7564 #ifdef DEBUG
     7653#ifdef VBOX_STRICT
    75657654    else
    75667655    {
     
    76377726    /*
    76387727     * The TPR has already been updated, see hmR0VMXPostRunGuest(). RIP is also updated as part of the VM-exit by VT-x. Update
    7639      * the threshold in the VMCS, deliver the pending interrupt via hmR0VmxPreRunGuest()->hmR0VmxInjectPendingInterrupt() and
     7728     * the threshold in the VMCS, deliver the pending interrupt via hmR0VmxPreRunGuest()->hmR0VmxInjectEvent() and
    76407729     * resume guest execution.
    76417730     */
     
    79278016
    79288017                        /* Set #DB to be injected into the VM and continue guest execution. */
    7929                         rc = hmR0VmxSetPendingXcptDB(pVCpu, pMixedCtx);
    7930                         AssertRCReturn(rc, rc);
     8018                        hmR0VmxSetPendingXcptDB(pVCpu, pMixedCtx);
    79318019                        break;
    79328020                    }
     
    82578345        uErrorCode |= X86_TRAP_PF_P;
    82588346
    8259     TRPMAssertTrap(pVCpu, X86_XCPT_PF, TRPM_TRAP);
    8260     TRPMSetErrorCode(pVCpu, uErrorCode);
    8261     TRPMSetFaultAddress(pVCpu, GCPhys);
     8347    TRPMAssertXcptPF(pVCpu, GCPhys, uErrorCode);
    82628348
    82638349    Log(("EPT violation %#x at %#RGv ErrorCode %#x CS:EIP=%04x:%#RX64\n", (uint32_t)pVmxTransient->uExitQualification, GCPhys,
     
    83078393    }
    83088394    hmR0VmxSetPendingEvent(pVCpu, VMX_VMCS_CTRL_ENTRY_IRQ_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntrInfo),
    8309                            pVmxTransient->cbInstr, pVmxTransient->uExitIntrErrorCode);
     8395                           pVmxTransient->cbInstr, pVmxTransient->uExitIntrErrorCode, 0 /* GCPtrFaultAddress */);
    83108396    return rc;
    83118397}
     
    83358421
    83368422        hmR0VmxSetPendingEvent(pVCpu, VMX_VMCS_CTRL_ENTRY_IRQ_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntrInfo),
    8337                                pVmxTransient->cbInstr, pVmxTransient->uExitIntrErrorCode);
     8423                               pVmxTransient->cbInstr, pVmxTransient->uExitIntrErrorCode, 0 /* GCPtrFaultAddress */);
    83388424    }
    83398425
     
    83868472        AssertRCReturn(rc,rc);
    83878473        hmR0VmxSetPendingEvent(pVCpu, VMX_VMCS_CTRL_ENTRY_IRQ_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntrInfo),
    8388                                pVmxTransient->cbInstr, pVmxTransient->uExitIntrErrorCode);
     8474                               pVmxTransient->cbInstr, pVmxTransient->uExitIntrErrorCode, 0 /* GCPtrFaultAddress */);
    83898475        return rc;
    83908476    }
     
    84268512    AssertRCReturn(rc, rc);
    84278513    hmR0VmxSetPendingEvent(pVCpu, VMX_VMCS_CTRL_ENTRY_IRQ_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntrInfo),
    8428                            pVmxTransient->cbInstr, 0 /* error code */);
     8514                           pVmxTransient->cbInstr, 0 /* error code */, 0 /* GCPtrFaultAddress */);
    84298515    STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestNM);
    84308516    return rc;
     
    84548540        Log(("#GP Gst: RIP %#RX64\n", pMixedCtx->rip));
    84558541        hmR0VmxSetPendingEvent(pVCpu, VMX_VMCS_CTRL_ENTRY_IRQ_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntrInfo),
    8456                                pVmxTransient->cbInstr, pVmxTransient->uExitIntrErrorCode);
     8542                               pVmxTransient->cbInstr, pVmxTransient->uExitIntrErrorCode, 0 /* GCPtrFaultAddress */);
    84578543        return rc;
    84588544#else
     
    86338719            {
    86348720                uint16_t uVector = pDis->Param1.uValue & 0xff;
    8635                 rc = hmR0VmxInjectIntN(pVCpu, pMixedCtx, uVector, pDis->cbInstr);
    8636                 AssertRCReturn(rc, rc);
     8721                hmR0VmxSetPendingIntN(pVCpu, pMixedCtx, uVector, pDis->cbInstr);
    86378722                STAM_COUNTER_INC(&pVCpu->hm.s.StatExitInt);
    86388723                break;
     
    86438728                if (pMixedCtx->eflags.Bits.u1OF)
    86448729                {
    8645                     rc = hmR0VmxSetPendingXcptOF(pVCpu, pMixedCtx, pDis->cbInstr);
     8730                    hmR0VmxSetPendingXcptOF(pVCpu, pMixedCtx, pDis->cbInstr);
    86468731                    STAM_COUNTER_INC(&pVCpu->hm.s.StatExitInt);
    86478732                }
     
    86838768       hmR0VmxCheckExitDueToEventDelivery(). */
    86848769    hmR0VmxSetPendingEvent(pVCpu, VMX_VMCS_CTRL_ENTRY_IRQ_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntrInfo),
    8685                            pVmxTransient->cbInstr, pVmxTransient->uExitIntrErrorCode);
     8770                           pVmxTransient->cbInstr, pVmxTransient->uExitIntrErrorCode, 0 /* GCPtrFaultAddress */);
    86868771    return VINF_SUCCESS;
    86878772}
     
    87088793            pMixedCtx->cr2 = pVmxTransient->uExitQualification;
    87098794            hmR0VmxSetPendingEvent(pVCpu, VMX_VMCS_CTRL_ENTRY_IRQ_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntrInfo),
    8710                                    pVmxTransient->cbInstr, pVmxTransient->uExitIntrErrorCode);
     8795                                   pVmxTransient->cbInstr, pVmxTransient->uExitIntrErrorCode, pMixedCtx->cr2);
    87118796        }
    87128797        else
     
    87538838#endif
    87548839
    8755     TRPMAssertTrap(pVCpu, X86_XCPT_PF, TRPM_TRAP);
    8756     TRPMSetFaultAddress(pVCpu, pVmxTransient->uExitQualification);
    8757     TRPMSetErrorCode(pVCpu, pVmxTransient->uExitIntrErrorCode);
    8758 
    87598840    rc = hmR0VmxSaveGuestState(pVCpu, pMixedCtx);
    87608841    AssertRCReturn(rc, rc);
     8842
     8843    TRPMAssertXcptPF(pVCpu, pVmxTransient->uExitQualification, (RTGCUINT)pVmxTransient->uExitIntrErrorCode);
    87618844
    87628845    /* Forward it to the trap handler first. */
     
    87878870            pMixedCtx->cr2 = pVmxTransient->uExitQualification;
    87888871            hmR0VmxSetPendingEvent(pVCpu, VMX_VMCS_CTRL_ENTRY_IRQ_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntrInfo),
    8789                                    pVmxTransient->cbInstr, uGstErrorCode);
     8872                                   pVmxTransient->cbInstr, uGstErrorCode, pMixedCtx->cr2);
    87908873        }
    87918874        else
  • trunk/src/VBox/VMM/VMMR0/HWSVMR0.cpp

    r45503 r45531  
    675675    {
    676676        uint8_t     u8Vector;
    677         rc = TRPMQueryTrapAll(pVCpu, &u8Vector, 0, 0, 0);
     677        rc = TRPMQueryTrapAll(pVCpu, &u8Vector, 0, NULL, NULL, NULL);
    678678        AssertRC(rc);
    679679    }
     
    693693
    694694        /* If a new event is pending, then dispatch it now. */
    695         rc = TRPMQueryTrapAll(pVCpu, &u8Vector, &enmType, &u32ErrorCode, 0);
     695        rc = TRPMQueryTrapAll(pVCpu, &u8Vector, &enmType, &u32ErrorCode, NULL, NULL);
    696696        AssertRC(rc);
    697697        Assert(pCtx->eflags.Bits.u1IF == 1 || enmType == TRPM_TRAP);
  • trunk/src/VBox/VMM/VMMR0/HWVMXR0.cpp

    r45517 r45531  
    11711171    {
    11721172        uint8_t u8Vector;
    1173         rc = TRPMQueryTrapAll(pVCpu, &u8Vector, 0, 0, 0);
     1173        rc = TRPMQueryTrapAll(pVCpu, &u8Vector, 0, NULL, NULL, NULL);
    11741174        AssertRC(rc);
    11751175    }
     
    11891189         * If a new event is pending, dispatch it now.
    11901190         */
    1191         rc = TRPMQueryTrapAll(pVCpu, &u8Vector, &enmType, &errCode, 0);
     1191        rc = TRPMQueryTrapAll(pVCpu, &u8Vector, &enmType, &errCode, NULL, NULL);
    11921192        AssertRC(rc);
    11931193        Assert(pCtx->eflags.Bits.u1IF == 1 || enmType == TRPM_TRAP);
  • trunk/src/VBox/VMM/VMMR3/EMRaw.cpp

    r45485 r45531  
    518518    RTGCUINT        uErrorCode;
    519519    RTGCUINTPTR     uCR2;
    520     int rc = TRPMQueryTrapAll(pVCpu, &u8TrapNo, &enmType, &uErrorCode, &uCR2);
     520    int rc = TRPMQueryTrapAll(pVCpu, &u8TrapNo, &enmType, &uErrorCode, &uCR2, NULL /* pu8InstrLen */);
    521521    if (RT_FAILURE(rc))
    522522    {
     
    754754    else
    755755    {
    756         rc = TRPMQueryTrapAll(pVCpu, &u8TrapNo, &enmType, &uErrorCode, &uCR2);
     756        rc = TRPMQueryTrapAll(pVCpu, &u8TrapNo, &enmType, &uErrorCode, &uCR2, NULL /* pu8InstrLen */);
    757757        if (RT_FAILURE(rc))
    758758        {
  • trunk/src/VBox/VMM/VMMR3/HM.cpp

    r45528 r45531  
    6767    EXIT_REASON(VMX_EXIT_IO_SMI_IRQ         ,  5, "I/O system-management interrupt (SMI)."),
    6868    EXIT_REASON(VMX_EXIT_SMI_IRQ            ,  6, "Other SMI."),
    69     EXIT_REASON(VMX_EXIT_IRQ_WINDOW         ,  7, "Interrupt window."),
     69    EXIT_REASON(VMX_EXIT_INT_WINDOW         ,  7, "Interrupt window."),
    7070    EXIT_REASON_NIL(),
    7171    EXIT_REASON(VMX_EXIT_TASK_SWITCH        ,  9, "Task switch."),
     
    111111    EXIT_REASON(VMX_EXIT_EPT_MISCONFIG      , 49, "EPT misconfiguration. An attempt to access memory with a guest-physical address encountered a misconfigured EPT paging-structure entry."),
    112112    EXIT_REASON(VMX_EXIT_INVEPT             , 50, "INVEPT. Guest software attempted to execute INVEPT."),
    113     EXIT_REASON(VMX_EXIT_RDTSCP             , 51, "Guest software attempted to execute RDTSCP."),
    114     EXIT_REASON(VMX_EXIT_PREEMPT_TIMER      , 52, "VMX-preemption timer expired. The preemption timer counted down to zero."),
     113    EXIT_REASON(VMX_EXIT_RDTSCP             , 51, "RDTSCP. Guest software attempted to execute RDTSCP."),
     114    EXIT_REASON(VMX_EXIT_PREEMPT_TIMER      , 52, "VMX-preemption timer expired."),
    115115    EXIT_REASON(VMX_EXIT_INVVPID            , 53, "INVVPID. Guest software attempted to execute INVVPID."),
    116116    EXIT_REASON(VMX_EXIT_WBINVD             , 54, "WBINVD. Guest software attempted to execute WBINVD."),
  • trunk/src/VBox/VMM/VMMR3/VMMGuruMeditation.cpp

    r44528 r45531  
    300300            RTGCUINT        uErrorCode = 0xdeadface;
    301301            RTGCUINTPTR     uCR2       = 0xdeadface;
    302             int rc2 = TRPMQueryTrapAll(pVCpu, &u8TrapNo, &enmType, &uErrorCode, &uCR2);
     302            uint8_t         cbInstr    = UINT8_MAX;
     303            int rc2 = TRPMQueryTrapAll(pVCpu, &u8TrapNo, &enmType, &uErrorCode, &uCR2, &cbInstr);
    303304            if (!HMIsEnabled(pVM))
    304305            {
    305306                if (RT_SUCCESS(rc2))
    306307                    pHlp->pfnPrintf(pHlp,
    307                                     "!! TRAP=%02x ERRCD=%RGv CR2=%RGv EIP=%RX32 Type=%d\n",
    308                                     u8TrapNo, uErrorCode, uCR2, uEIP, enmType);
     308                                    "!! TRAP=%02x ERRCD=%RGv CR2=%RGv EIP=%RX32 Type=%d cbInstr=%02x\n",
     309                                    u8TrapNo, uErrorCode, uCR2, uEIP, enmType, cbInstr);
    309310                else
    310311                    pHlp->pfnPrintf(pHlp,
     
    314315            else if (RT_SUCCESS(rc2))
    315316                pHlp->pfnPrintf(pHlp,
    316                                 "!! ACTIVE TRAP=%02x ERRCD=%RGv CR2=%RGv PC=%RGr Type=%d (Guest!)\n",
    317                                 u8TrapNo, uErrorCode, uCR2, CPUMGetGuestRIP(pVCpu), enmType);
     317                                "!! ACTIVE TRAP=%02x ERRCD=%RGv CR2=%RGv PC=%RGr Type=%d cbInstr=%02x (Guest!)\n",
     318                                u8TrapNo, uErrorCode, uCR2, CPUMGetGuestRIP(pVCpu), enmType, cbInstr);
    318319
    319320            /*
  • trunk/src/VBox/VMM/include/HMInternal.h

    r45517 r45531  
    734734        uint32_t                    u32Padding; /**< Explicit alignment padding. */
    735735        uint64_t                    u64IntrInfo;
     736        RTGCUINTPTR                 GCPtrFaultAddress;
    736737    } Event;
    737738
  • trunk/src/VBox/VMM/include/TRPMInternal.h

    r43872 r45531  
    234234    /** Previous trap vector # - for debugging. */
    235235    RTGCUINT                uPrevVector;
     236
     237    /** Instruction length for software interrupts and software exceptions (#BP,
     238     *  #OF) */
     239    uint8_t                 cbInstr;
     240
     241    /** Saved instruction length. */
     242    uint8_t                 cbSavedInstr;
     243
     244    /** Padding. */
     245    uint8_t                 au8Padding[2];
    236246} TRPMCPU;
    237247
  • trunk/src/VBox/VMM/include/TRPMInternal.mac

    r41943 r45531  
    8080    .uSavedCR2          RTGCPTR_RES 1
    8181    .uPrevVector        RTGCPTR_RES 1
     82    .cbInstr            resb 1
     83    .cbSavedInstr       resb 1
     84    .au8Padding         resb 2
    8285endstruc
    8386
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