VirtualBox

Changeset 57555 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Aug 27, 2015 10:11:18 AM (10 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
102373
Message:

VMM/HMVMXR0: Don't lose interrupt-window exiting due to unrelated exits to ring-3.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMR0/HMVMXR0.cpp

    r57514 r57555  
    337337static void               hmR0VmxFlushEpt(PVMCPU pVCpu, VMXFLUSHEPT enmFlush);
    338338static void               hmR0VmxFlushVpid(PVM pVM, PVMCPU pVCpu, VMXFLUSHVPID enmFlush, RTGCPTR GCPtr);
     339static void               hmR0VmxClearIntNmiWindowsVmcs(PVMCPU pVCpu);
    339340static int                hmR0VmxInjectEventVmcs(PVMCPU pVCpu, PCPUMCTX pMixedCtx, uint64_t u64IntInfo, uint32_t cbInstr,
    340341                                                 uint32_t u32ErrCode, RTGCUINTREG GCPtrFaultAddress,
     
    68106811
    68116812/**
    6812  * Converts any pending HM event into a TRPM trap. Typically used when leaving
    6813  * VT-x to execute any instruction.
     6813 * Converts the pending HM event into a TRPM trap.
    68146814 *
    68156815 * @param   pvCpu           Pointer to the VMCPU.
     
    68736873        TRPMSetInstrLength(pVCpu, pVCpu->hm.s.Event.cbInstr);
    68746874    }
     6875
     6876    /* Clear the pending event from the VMCS. */
     6877#ifdef VBOX_STRICT
     6878    uint32_t u32EntryInfo;
     6879    rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, &u32EntryInfo);
     6880    AssertRC(rc);
     6881    Assert(VMX_ENTRY_INTERRUPTION_INFO_IS_VALID(u32EntryInfo));
     6882#endif
     6883    rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, 0);        AssertRC(rc);
     6884    rc = VMXWriteVmcs32(VMX_VMCS_GUEST_PENDING_DEBUG_EXCEPTIONS, 0);        AssertRC(rc);
     6885
     6886    /* We're now done converting the pending event. */
    68756887    pVCpu->hm.s.Event.fPending = false;
    68766888}
     
    71077119        Assert(!pVCpu->hm.s.Event.fPending);
    71087120    }
     7121
     7122    /* Clear interrupt-window and NMI-window controls as we re-evaluate it when we return from ring-3. */
     7123    hmR0VmxClearIntNmiWindowsVmcs(pVCpu);
    71097124
    71107125    /* If we're emulating an instruction, we shouldn't have any TRPM traps pending
     
    73117326static void hmR0VmxEvaluatePendingEvent(PVMCPU pVCpu, PCPUMCTX pMixedCtx)
    73127327{
    7313     Assert(!pVCpu->hm.s.Event.fPending);
    7314 
    73157328    /* Get the current interruptibility-state of the guest and then figure out what can be injected. */
    73167329    uint32_t const uIntrState = hmR0VmxGetGuestIntrState(pVCpu, pMixedCtx);
     
    73327345    {
    73337346        /* On some CPUs block-by-STI also blocks NMIs. See Intel spec. 26.3.1.5 "Checks On Guest Non-Register State". */
    7334         if (   !fBlockNmi
     7347        if (   !pVCpu->hm.s.Event.fPending
     7348            && !fBlockNmi
    73357349            && !fBlockSti
    73367350            && !fBlockMovSS)
     
    73567370        AssertRC(rc);
    73577371        bool const fBlockInt = !(pMixedCtx->eflags.u32 & X86_EFL_IF);
    7358         if (   !fBlockInt
     7372        if (   !pVCpu->hm.s.Event.fPending
     7373            && !fBlockInt
    73597374            && !fBlockSti
    73607375            && !fBlockMovSS)
     
    74357450    {
    74367451        /*
    7437          * Clear any interrupt-window exiting control if we're going to inject an interrupt. Saves one extra
    7438          * VM-exit in situations where we previously setup interrupt-window exiting but got other VM-exits and
    7439          * ended up enabling interrupts outside VT-x.
     7452         * Do -not- clear any interrupt-window exiting control here. We might have an interrupt
     7453         * pending even while injecting an event and in this case, we want a VM-exit as soon as
     7454         * the guest is ready for the next interrupt, see @bugref{6208#c45}.
     7455         *
     7456         * See Intel spec. 26.6.5 "Interrupt-Window Exiting and Virtual-Interrupt Delivery".
    74407457         */
    7441         uint32_t uIntType = VMX_EXIT_INTERRUPTION_INFO_TYPE(pVCpu->hm.s.Event.u64IntInfo);
    7442         if (   (pVCpu->hm.s.vmx.u32ProcCtls & VMX_VMCS_CTRL_PROC_EXEC_INT_WINDOW_EXIT)
    7443             && uIntType == VMX_EXIT_INTERRUPTION_INFO_TYPE_EXT_INT)
    7444         {
    7445             Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.VmxProcCtls.n.allowed1 & VMX_VMCS_CTRL_PROC_EXEC_INT_WINDOW_EXIT);
    7446             hmR0VmxClearIntWindowExitVmcs(pVCpu);
    7447         }
    7448 
     7458        uint32_t const uIntType = VMX_EXIT_INTERRUPTION_INFO_TYPE(pVCpu->hm.s.Event.u64IntInfo);
    74497459#ifdef VBOX_STRICT
    74507460        if (uIntType == VMX_EXIT_INTERRUPTION_INFO_TYPE_EXT_INT)
     
    74747484        fBlockSti   = RT_BOOL(uIntrState & VMX_VMCS_GUEST_INTERRUPTIBILITY_STATE_BLOCK_STI);
    74757485
    7476 #ifdef VBOX_WITH_STATISTICS
    74777486        if (uIntType == VMX_EXIT_INTERRUPTION_INFO_TYPE_EXT_INT)
    74787487            STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectInterrupt);
    74797488        else
    74807489            STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectXcpt);
    7481 #endif
    74827490    }
    74837491
     
    79207928 * @remarks No-long-jump zone!!!
    79217929 */
    7922 static void hmR0VmxClearEventVmcs(PVMCPU pVCpu)
     7930static void hmR0VmxClearIntNmiWindowsVmcs(PVMCPU pVCpu)
    79237931{
    79247932    int rc;
     
    79307938    if (pVCpu->hm.s.vmx.u32ProcCtls & VMX_VMCS_CTRL_PROC_EXEC_NMI_WINDOW_EXIT)
    79317939        hmR0VmxClearNmiWindowExitVmcs(pVCpu);
    7932 
    7933     if (!pVCpu->hm.s.Event.fPending)
    7934         return;
    7935 
    7936 #ifdef VBOX_STRICT
    7937     uint32_t u32EntryInfo;
    7938     rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, &u32EntryInfo);
    7939     AssertRC(rc);
    7940     Assert(VMX_ENTRY_INTERRUPTION_INFO_IS_VALID(u32EntryInfo));
    7941 #endif
    7942 
    7943     rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, 0);
    7944     AssertRC(rc);
    7945 
    7946     rc = VMXWriteVmcs32(VMX_VMCS_GUEST_PENDING_DEBUG_EXCEPTIONS, 0);
    7947     AssertRC(rc);
    7948 
    7949     /* We deliberately don't clear "hm.s.Event.fPending" here, it's taken
    7950        care of in hmR0VmxExitToRing3() converting the pending event to TRPM. */
    79517940}
    79527941
     
    84008389    if (TRPMHasTrap(pVCpu))
    84018390        hmR0VmxTrpmTrapToPendingEvent(pVCpu);
    8402     else if (!pVCpu->hm.s.Event.fPending)
    8403         hmR0VmxEvaluatePendingEvent(pVCpu, pMixedCtx);
     8391    hmR0VmxEvaluatePendingEvent(pVCpu, pMixedCtx);
    84048392
    84058393    /*
     
    84468434            || VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_HM_TO_R3_MASK & ~(VMCPU_FF_TIMER | VMCPU_FF_PDM_CRITSECT))) )
    84478435    {
    8448         hmR0VmxClearEventVmcs(pVCpu);
    84498436        ASMSetFlags(pVmxTransient->fEFlags);
    84508437        VMMRZCallRing3Enable(pVCpu);
     
    84558442    if (RTThreadPreemptIsPending(NIL_RTTHREAD))
    84568443    {
    8457         hmR0VmxClearEventVmcs(pVCpu);
    84588444        ASMSetFlags(pVmxTransient->fEFlags);
    84598445        VMMRZCallRing3Enable(pVCpu);
Note: See TracChangeset for help on using the changeset viewer.

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