VirtualBox

Changeset 81806 in vbox


Ignore:
Timestamp:
Nov 12, 2019 2:49:30 PM (5 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
134597
Message:

VMM/HMVMXR0: Fix delivery of guest pending debug exception (BS bit) when the trap flag is used (or cleared).

File:
1 edited

Legend:

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

    r81791 r81806  
    50805080        AssertRC(rc);
    50815081
    5082         /*
    5083          * Setup pending debug exceptions if the guest is single-stepping using EFLAGS.TF.
    5084          *
    5085          * We must avoid setting any automatic debug exceptions delivery when single-stepping
    5086          * through the hypervisor debugger using EFLAGS.TF.
    5087          */
    5088         if (   !pVmxTransient->fIsNestedGuest
    5089             && !pVCpu->hm.s.fSingleInstruction
    5090             &&  fEFlags.Bits.u1TF)
    5091         {
    5092             /** @todo r=ramshankar: Warning!! We ASSUME EFLAGS.TF will not cleared on
    5093              *        premature trips to ring-3 esp since IEM does not yet handle it. */
    5094             rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, VMX_VMCS_GUEST_PENDING_DEBUG_XCPT_BS);
    5095             AssertRC(rc);
    5096         }
    5097         /* else: for nested-guest currently handling while merging controls. */
    5098 
    50995082        ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_RFLAGS);
    51005083        Log4Func(("eflags=%#RX32\n", fEFlags.u32));
     
    81568139
    81578140        /* Clear the events from the VMCS. */
    8158         int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, 0);
    8159         AssertRC(rc);
     8141        int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, 0);    AssertRC(rc);
     8142        rc     = VMXWriteVmcs32(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, 0);         AssertRC(rc);
    81608143    }
    81618144#ifdef VBOX_STRICT
     
    87408723    Assert(VMMRZCallRing3IsEnabled(pVCpu));
    87418724
    8742     bool const fBlockMovSS = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS);
    8743     bool const fBlockSti   = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI);
    8744 
    8745     Assert(!fBlockSti || !(ASMAtomicUoReadU64(&pVCpu->cpum.GstCtx.fExtrn) & CPUMCTX_EXTRN_RFLAGS));
    8746     Assert(!fBlockSti || pVCpu->cpum.GstCtx.eflags.Bits.u1IF);     /* Cannot set block-by-STI when interrupts are disabled. */
    8747     Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI));    /* We don't support block-by-SMI yet.*/
    8748     Assert(!TRPMHasTrap(pVCpu));
     8725#ifdef VBOX_STRICT
     8726    /*
     8727     * Verify guest-interruptibility state.
     8728     *
     8729     * We put this in a scoped block so we do not accidentally use fBlockSti or fBlockMovSS,
     8730     * since injecting an event may modify the interruptibility state and we must thus always
     8731     * use fIntrState.
     8732     */
     8733    {
     8734        bool const fBlockMovSS = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS);
     8735        bool const fBlockSti   = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI);
     8736        Assert(!fBlockSti || !(ASMAtomicUoReadU64(&pVCpu->cpum.GstCtx.fExtrn) & CPUMCTX_EXTRN_RFLAGS));
     8737        Assert(!fBlockSti || pVCpu->cpum.GstCtx.eflags.Bits.u1IF);     /* Cannot set block-by-STI when interrupts are disabled. */
     8738        Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI));    /* We don't support block-by-SMI yet.*/
     8739        Assert(!TRPMHasTrap(pVCpu));
     8740        NOREF(fBlockMovSS); NOREF(fBlockSti);
     8741    }
     8742#endif
    87498743
    87508744    VBOXSTRICTRC rcStrict = VINF_SUCCESS;
     
    87628756        if (uIntType == VMX_ENTRY_INT_INFO_TYPE_EXT_INT)
    87638757        {
    8764             bool const fBlockInt = !(pVCpu->cpum.GstCtx.eflags.u32 & X86_EFL_IF);
    8765             Assert(!fBlockInt);
    8766             Assert(!fBlockSti);
    8767             Assert(!fBlockMovSS);
     8758            Assert(pVCpu->cpum.GstCtx.eflags.u32 & X86_EFL_IF);
     8759            Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI));
     8760            Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS));
    87688761        }
    87698762        else if (uIntType == VMX_ENTRY_INT_INFO_TYPE_NMI)
    87708763        {
    8771             bool const fBlockNmi = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI);
    8772             Assert(!fBlockSti);
    8773             Assert(!fBlockMovSS);
    8774             Assert(!fBlockNmi);
     8764            Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI));
     8765            Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI));
     8766            Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS));
    87758767        }
    87768768#endif
     
    87948786
    87958787    /*
    8796      * Update the guest-interruptibility state.
     8788     * Deliver any pending debug exceptions if the guest is single-stepping using EFLAGS.TF and
     8789     * is an interrupt shadow (block-by-STI or block-by-MOV SS).
     8790     */
     8791    if (   (fIntrState & (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS))
     8792        && !pVmxTransient->fIsNestedGuest)
     8793    {
     8794        HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RFLAGS);
     8795
     8796        if (!pVCpu->hm.s.fSingleInstruction)
     8797        {
     8798            /*
     8799             * Set or clear the BS bit depending on whether the trap flag is active or not. We need
     8800             * to do both since we clear the BS bit from the VMCS while exiting to ring-3.
     8801             */
     8802            Assert(!DBGFIsStepping(pVCpu));
     8803            uint8_t const fTrapFlag = !!(pVCpu->cpum.GstCtx.eflags.u32 & X86_EFL_TF);
     8804            int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, fTrapFlag << VMX_BF_VMCS_PENDING_DBG_XCPT_BS_SHIFT);
     8805            AssertRC(rc);
     8806        }
     8807        else if (pVCpu->cpum.GstCtx.eflags.u32 & X86_EFL_TF)
     8808        {
     8809            /*
     8810             * We must not deliver a debug exception when single-stepping in the hypervisor debugger
     8811             * using EFLAGS.T. Instead, clear interrupt inhibition.
     8812             */
     8813            Assert(!(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_MONITOR_TRAP_FLAG));
     8814            fIntrState = 0;
     8815        }
     8816    }
     8817    /* else: for nested-guest currently handling while merging controls. */
     8818
     8819    /*
     8820     * Finally, update the guest-interruptibility state.
    87978821     *
    8798      * This is required for the real-on-v86 software interrupt injection case above, as well as
    8799      * updates to the guest state from ring-3 or IEM/REM.
     8822     * This is required for the real-on-v86 software interrupt injection, for
     8823     * pending debug exceptions as well as updates to the guest state from ring-3 (IEM).
    88008824     */
    88018825    int rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_INT_STATE, fIntrState);
     
    88108834
    88118835    Assert(rcStrict == VINF_SUCCESS || rcStrict == VINF_EM_RESET || (rcStrict == VINF_EM_DBG_STEPPED && fStepping));
    8812     NOREF(fBlockMovSS); NOREF(fBlockSti);
    88138836    return rcStrict;
    88148837}
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