VirtualBox

Changeset 52066 in vbox


Ignore:
Timestamp:
Jul 17, 2014 7:02:33 AM (11 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
95068
Message:

VMM: Fixed potential bug in AMD-V NMI injection when interrupt shadowing is in effect, renamed INHIBIT_NMIS to BLOCK_NMIS to match Intel specs.

Location:
trunk
Files:
5 edited

Legend:

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

    r52041 r52066  
    405405/** Inhibit interrupts pending. See EMGetInhibitInterruptsPC(). */
    406406#define VMCPU_FF_INHIBIT_INTERRUPTS         RT_BIT_32(24)
    407 /** Inhibit non-maskable interrupts. */
    408 #define VMCPU_FF_INHIBIT_NMIS               RT_BIT_32(25)
     407/** Block injection of non-maskable interrupts to the guest. */
     408#define VMCPU_FF_BLOCK_NMIS                 RT_BIT_32(25)
    409409#ifdef VBOX_WITH_RAW_MODE
    410410/** CSAM needs to scan the page that's being executed */
  • trunk/src/VBox/VMM/VMMAll/IEMAllCImpl.cpp.h

    r52041 r52066  
    29902990{
    29912991    /*
    2992      * First, clear NMI inhibition before causing any exceptions.
     2992     * First, clear NMI blocking, if any, before causing any exceptions.
    29932993     */
    29942994    PVMCPU pVCpu = IEMCPU_TO_VMCPU(pIemCpu);
    2995     VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_NMIS);
     2995    VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_BLOCK_NMIS);
    29962996
    29972997    /*
  • trunk/src/VBox/VMM/VMMR0/HMSVMR0.cpp

    r52044 r52066  
    25752575    bool const fIntShadow = RT_BOOL(hmR0SvmGetGuestIntrShadow(pVCpu, pCtx));
    25762576    bool const fBlockInt  = !(pCtx->eflags.u32 & X86_EFL_IF);
    2577     bool const fBlockNmi  = RT_BOOL(VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_INHIBIT_NMIS));
     2577    bool const fBlockNmi  = RT_BOOL(VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_BLOCK_NMIS));
    25782578    PSVMVMCB pVmcb        = (PSVMVMCB)pVCpu->hm.s.svm.pvVmcb;
    25792579
     
    30033003
    30043004    /*
    3005      * If we are injecting an NMI, we must set VMCPU_FF_INHIBIT_NMIS only when we are going to execute
     3005     * If we are injecting an NMI, we must set VMCPU_FF_BLOCK_NMIS only when we are going to execute
    30063006     * guest code for certain (no exits to ring-3). Otherwise, we could re-read the flag on re-entry into
    30073007     * AMD-V and conclude that NMI inhibition is active when we have not even delivered the NMI.
     
    30143014        SVMEVENT Event;
    30153015        Event.u = pVCpu->hm.s.Event.u64IntInfo;
    3016         if (   Event.n.u1Valid
    3017             && Event.n.u3Type == SVM_EVENT_NMI
    3018             && Event.n.u8Vector == X86_XCPT_NMI)
    3019         {
    3020             VMCPU_FF_SET(pVCpu, VMCPU_FF_INHIBIT_NMIS);
     3016        if (    Event.n.u1Valid
     3017            &&  Event.n.u3Type == SVM_EVENT_NMI
     3018            &&  Event.n.u8Vector == X86_XCPT_NMI
     3019            && !VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_BLOCK_NMIS))
     3020        {
     3021            VMCPU_FF_SET(pVCpu, VMCPU_FF_BLOCK_NMIS);
    30213022        }
    30223023    }
     
    49154916
    49164917    PSVMVMCB pVmcb = (PSVMVMCB)pVCpu->hm.s.svm.pvVmcb;
    4917     pVmcb->ctrl.IntCtrl.n.u1VIrqValid  = 0;  /* No virtual interrupts pending, we'll inject the current one before reentry. */
     4918    pVmcb->ctrl.IntCtrl.n.u1VIrqValid  = 0;  /* No virtual interrupts pending, we'll inject the current one/NMI before reentry. */
    49184919    pVmcb->ctrl.IntCtrl.n.u8VIrqVector = 0;
    4919 
    4920     /* Clear NMI inhibition, if it's active. */
    4921     if (VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_INHIBIT_NMIS))
    4922     {
    4923         hmR0SvmClearIretIntercept(pVmcb);
    4924         VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_NMIS);
    4925     }
    49264920
    49274921    /* Indicate that we no longer need to #VMEXIT when the guest is ready to receive interrupts/NMIs, it is now ready. */
     
    49994993    HMSVM_VALIDATE_EXIT_HANDLER_PARAMS();
    50004994
    5001     /* Clear NMI inhibition. */
    5002     VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_NMIS);
     4995    /* Clear NMI blocking. */
     4996    VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_BLOCK_NMIS);
    50034997
    50044998    /* Indicate that we no longer need to #VMEXIT when the guest is ready to receive NMIs, it is now ready. */
  • trunk/src/VBox/VMM/VMMR0/HMVMXR0.cpp

    r52065 r52066  
    35243524
    35253525    /*
    3526      * NMIs to the guest are inhibited until the guest executes an IRET. We only
    3527      * bother with virtual-NMI blocking when we have support for virtual NMIs in the
    3528      * CPU, otherwise setting this would block host-NMIs and IRET will not clear the
    3529      * blocking.
     3526     * NMIs to the guest are blocked after an NMI is injected until the guest executes an IRET. We only
     3527     * bother with virtual-NMI blocking when we have support for virtual NMIs in the CPU, otherwise
     3528     * setting this would block host-NMIs and IRET will not clear the blocking.
    35303529     *
    35313530     * See Intel spec. 26.6.1 "Interruptibility state". See @bugref{7445}.
    35323531     */
    3533     if (   VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_INHIBIT_NMIS)
     3532    if (   VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_BLOCK_NMIS)
    35343533        && (pVCpu->hm.s.vmx.u32PinCtls & VMX_VMCS_CTRL_PIN_EXEC_VIRTUAL_NMI))
    35353534    {
     
    58315830                 * See Intel spec. 30.7.1.2 "Resuming Guest Software after Handling an Exception". See @bugref{7445}.
    58325831                 */
    5833                 Assert(VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_INHIBIT_NMIS));
    5834                 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_NMIS);
     5832                Assert(VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_BLOCK_NMIS));
     5833                VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_BLOCK_NMIS);
    58355834                enmReflect = VMXREFLECTXCPT_XCPT;
    58365835            }
     
    59155914    {
    59165915        /*
    5917          * Execution of IRET caused this fault when NMI blocking was in effect. We need to reset the block-by-NMI field so
    5918          * that NMIs remain blocked until the IRET execution is completed.
     5916         * Execution of IRET caused this fault when NMI blocking was in effect (i.e we're in the guest NMI handler).
     5917         * We need to reset the block-by-NMI field so that NMIs remain blocked until the IRET execution is completed.
    59195918         * See Intel spec. 30.7.1.2 "Resuming guest software after handling an exception".
    59205919         */
    5921         if (!VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_INHIBIT_NMIS))
    5922             VMCPU_FF_SET(pVCpu, VMCPU_FF_INHIBIT_NMIS);
     5920        if (!VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_BLOCK_NMIS))
     5921            VMCPU_FF_SET(pVCpu, VMCPU_FF_BLOCK_NMIS);
    59235922    }
    59245923
     
    61276126        if (VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
    61286127            VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
    6129         if (VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_INHIBIT_NMIS))
    6130             VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_NMIS);
     6128
     6129        if (VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_BLOCK_NMIS))
     6130            VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_BLOCK_NMIS);
    61316131    }
    61326132    else
     
    61456145
    61466146        if (uIntrState & VMX_VMCS_GUEST_INTERRUPTIBILITY_STATE_BLOCK_NMI)
    6147             VMCPU_FF_SET(pVCpu, VMCPU_FF_INHIBIT_NMIS);
    6148         else if (VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_INHIBIT_NMIS))
    6149             VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_NMIS);
     6147        {
     6148            if (!VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_BLOCK_NMIS))
     6149                VMCPU_FF_SET(pVCpu, VMCPU_FF_BLOCK_NMIS);
     6150        }
     6151        else if (VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_BLOCK_NMIS))
     6152            VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_BLOCK_NMIS);
    61506153    }
    61516154}
     
    99329935    }
    99339936
    9934     Assert(!VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_INHIBIT_NMIS));
     9937    Assert(!VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_BLOCK_NMIS));
    99359938
    99369939    /*
  • trunk/src/recompiler/VBoxRecompiler.c

    r52041 r52066  
    22392239    /* Update the inhibit NMI mask. */
    22402240    pVM->rem.s.Env.hflags2 &= ~HF2_NMI_MASK;
    2241     if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_NMIS))
     2241    if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_BLOCK_NMIS))
    22422242        pVM->rem.s.Env.hflags2 |= HF2_NMI_MASK;
    22432243
     
    27332733    if (pVM->rem.s.Env.hflags2 & HF2_NMI_MASK)
    27342734    {
    2735         Log(("Settings VMCPU_FF_INHIBIT_NMIS at %RGv (REM)\n", (RTGCPTR)pCtx->rip));
    2736         VMCPU_FF_SET(pVCpu, VMCPU_FF_INHIBIT_NMIS);
    2737     }
    2738     else if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_NMIS))
    2739     {
    2740         Log(("Clearing VMCPU_FF_INHIBIT_NMIS at %RGv (REM)\n", (RTGCPTR)pCtx->rip));
    2741         VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_NMIS);
     2735        Log(("Settings VMCPU_FF_BLOCK_NMIS at %RGv (REM)\n", (RTGCPTR)pCtx->rip));
     2736        VMCPU_FF_SET(pVCpu, VMCPU_FF_BLOCK_NMIS);
     2737    }
     2738    else if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_BLOCK_NMIS))
     2739    {
     2740        Log(("Clearing VMCPU_FF_BLOCK_NMIS at %RGv (REM)\n", (RTGCPTR)pCtx->rip));
     2741        VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_BLOCK_NMIS);
    27422742    }
    27432743
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