VirtualBox

Changeset 87040 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Dec 4, 2020 6:28:01 AM (4 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
141724
Message:

VMM: Better fix for r141682 - Fix delivery of external interrupts when executing nested-guests. Fixes nested-guest SMP hangs described in bugref:9562#c18

Location:
trunk/src/VBox/VMM
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMAll/IEMAllCImplVmxInstr.cpp.h

    r84505 r87040  
    35283528             * If the interrupt is pending and we -do- need to acknowledge the interrupt
    35293529             * on VM-exit, postpone VM-exit till after the interrupt controller has been
    3530              * acknowledged that the interrupt has been consumed.
     3530             * acknowledged that the interrupt has been consumed. Callers would have to call
     3531             * us again after getting the vector (and ofc, with fIntPending with false).
    35313532             */
    35323533            return VINF_VMX_INTERCEPT_NOT_ACTIVE;
     
    35363537         * If the interrupt is no longer pending (i.e. it has been acknowledged) and the
    35373538         * "External interrupt exiting" and "Acknowledge interrupt on VM-exit" controls are
    3538          * all set, we cause the VM-exit now. We need to record the external interrupt that
    3539          * just occurred in the VM-exit interruption information field.
     3539         * all set, we need to record the vector of the external interrupt in the
     3540         * VM-exit interruption information field. Otherwise, mark this field as invalid.
    35403541         *
    35413542         * See Intel spec. 27.2.2 "Information for VM Exits Due to Vectored Events".
    35423543         */
     3544        uint32_t uExitIntInfo;
    35433545        if (pVmcs->u32ExitCtls & VMX_EXIT_CTLS_ACK_EXT_INT)
    35443546        {
    3545             bool const     fNmiUnblocking = pVCpu->cpum.GstCtx.hwvirt.vmx.fNmiUnblockingIret;
    3546             uint32_t const uExitIntInfo   = RT_BF_MAKE(VMX_BF_EXIT_INT_INFO_VECTOR,           uVector)
    3547                                           | RT_BF_MAKE(VMX_BF_EXIT_INT_INFO_TYPE,             VMX_EXIT_INT_INFO_TYPE_EXT_INT)
    3548                                           | RT_BF_MAKE(VMX_BF_EXIT_INT_INFO_NMI_UNBLOCK_IRET, fNmiUnblocking)
    3549                                           | RT_BF_MAKE(VMX_BF_EXIT_INT_INFO_VALID,            1);
    3550             iemVmxVmcsSetExitIntInfo(pVCpu, uExitIntInfo);
    3551             return iemVmxVmexit(pVCpu, VMX_EXIT_EXT_INT, 0 /* u64ExitQual */);
    3552         }
     3547            bool const fNmiUnblocking = pVCpu->cpum.GstCtx.hwvirt.vmx.fNmiUnblockingIret;
     3548            uExitIntInfo = RT_BF_MAKE(VMX_BF_EXIT_INT_INFO_VECTOR,           uVector)
     3549                         | RT_BF_MAKE(VMX_BF_EXIT_INT_INFO_TYPE,             VMX_EXIT_INT_INFO_TYPE_EXT_INT)
     3550                         | RT_BF_MAKE(VMX_BF_EXIT_INT_INFO_NMI_UNBLOCK_IRET, fNmiUnblocking)
     3551                         | RT_BF_MAKE(VMX_BF_EXIT_INT_INFO_VALID,            1);
     3552        }
     3553        else
     3554            uExitIntInfo = 0;
     3555        iemVmxVmcsSetExitIntInfo(pVCpu, uExitIntInfo);
     3556
     3557        /*
     3558         * Cause the VM-exit whether or not the vector has been stored
     3559         * in the VM-exit interruption-information field.
     3560         */
     3561        return iemVmxVmexit(pVCpu, VMX_EXIT_EXT_INT, 0 /* u64ExitQual */);
    35533562    }
    35543563
  • trunk/src/VBox/VMM/VMMR0/HMVMXR0.cpp

    r87034 r87040  
    89138913
    89148914            /*
    8915              * EFLAGS.IF does not control the blocking of external interrupts when
    8916              * "External interrupt exiting" set. Fixes nasty SMP hang while executing nested-guest
    8917              * VCPUs on spinlocks and aren't rescued by other VM-exits (like a preemption timer),
    8918              * see @bugref{9562#c18}.
     8915             * We must not check EFLAGS directly when executing a nested-guest, use
     8916             * CPUMIsGuestPhysIntrEnabled() instead as EFLAGS.IF does not control the blocking of
     8917             * external interrupts when "External interrupt exiting" is set. This fixes a nasty
     8918             * SMP hang while executing nested-guest VCPUs on spinlocks which aren't rescued by
     8919             * other VM-exits (like a preemption timer), see @bugref{9562#c18}.
    89198920             *
    8920              * See Intel spec. 25.4.1 "Event Blocking"
     8921             * See Intel spec. 25.4.1 "Event Blocking".
    89218922             */
     8923            if (CPUMIsGuestPhysIntrEnabled(pVCpu))
     8924            {
    89228925#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
    8923             if (    fIsNestedGuest
    8924                 &&  CPUMIsGuestVmxPinCtlsSet(pCtx, VMX_PIN_CTLS_EXT_INT_EXIT)
    8925                 && !CPUMIsGuestVmxExitCtlsSet(pCtx, VMX_EXIT_CTLS_ACK_EXT_INT))
    8926             {
    8927                 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitExtInt(pVCpu, 0 /* uVector */, true /* fIntPending */);
    8928                 Assert(rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE);
    8929                 return rcStrict;
    8930             }
     8926                if (   fIsNestedGuest
     8927                    && CPUMIsGuestVmxPinCtlsSet(pCtx, VMX_PIN_CTLS_EXT_INT_EXIT))
     8928                {
     8929                    VBOXSTRICTRC rcStrict = IEMExecVmxVmexitExtInt(pVCpu, 0 /* uVector */, true /* fIntPending */);
     8930                    Assert(rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE);
     8931                    return rcStrict;
     8932                }
    89318933#endif
    8932             if (pCtx->eflags.u32 & X86_EFL_IF)
    8933             {
    89348934                uint8_t u8Interrupt;
    89358935                rc = PDMGetInterrupt(pVCpu, &u8Interrupt);
     
    89388938#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
    89398939                    if (   fIsNestedGuest
    8940                         && CPUMIsGuestVmxPinCtlsSet(pCtx, VMX_PIN_CTLS_EXT_INT_EXIT)
    8941                         && CPUMIsGuestVmxExitCtlsSet(pCtx, VMX_EXIT_CTLS_ACK_EXT_INT))
     8940                        && CPUMIsGuestVmxPinCtlsSet(pCtx, VMX_PIN_CTLS_EXT_INT_EXIT))
    89428941                    {
    89438942                        VBOXSTRICTRC rcStrict = IEMExecVmxVmexitExtInt(pVCpu, u8Interrupt, false /* fIntPending */);
  • trunk/src/VBox/VMM/VMMR3/EM.cpp

    r82968 r87040  
    14981498#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
    14991499    /* Handle the "external interrupt" VM-exit intercept. */
    1500     if (    CPUMIsGuestVmxPinCtlsSet(&pVCpu->cpum.GstCtx, VMX_PIN_CTLS_EXT_INT_EXIT)
    1501         && !CPUMIsGuestVmxExitCtlsSet(&pVCpu->cpum.GstCtx, VMX_EXIT_CTLS_ACK_EXT_INT))
     1500    if (CPUMIsGuestVmxPinCtlsSet(&pVCpu->cpum.GstCtx, VMX_PIN_CTLS_EXT_INT_EXIT))
    15021501    {
    15031502        VBOXSTRICTRC rcStrict = IEMExecVmxVmexitExtInt(pVCpu, 0 /* uVector */, true /* fIntPending */);
  • trunk/src/VBox/VMM/VMMR3/TRPM.cpp

    r82968 r87040  
    379379        if (   CPUMIsGuestInVmxNonRootMode(pCtx)
    380380            && CPUMIsGuestVmxInterceptEvents(pCtx)
    381             && CPUMIsGuestVmxPinCtlsSet(pCtx, VMX_PIN_CTLS_EXT_INT_EXIT)
    382             && CPUMIsGuestVmxExitCtlsSet(pCtx, VMX_EXIT_CTLS_ACK_EXT_INT))
     381            && CPUMIsGuestVmxPinCtlsSet(pCtx, VMX_PIN_CTLS_EXT_INT_EXIT))
    383382        {
    384383            VBOXSTRICTRC rcStrict = IEMExecVmxVmexitExtInt(pVCpu, u8Interrupt, false /* fIntPending */);
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