VirtualBox

Changeset 75671 in vbox for trunk/src/VBox/VMM/VMMAll


Ignore:
Timestamp:
Nov 22, 2018 3:08:24 PM (6 years ago)
Author:
vboxsync
Message:

VMM: Nested VMX: bugref:9180 Implement NMI-unblocking due to IRET for VM-exits. Implemented restoring blocking of NMI when VM-entry fails while checking/loading guest-state. Fixed loading blocking by NMI during VM-entry.

Location:
trunk/src/VBox/VMM/VMMAll
Files:
2 edited

Legend:

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

    r75631 r75671  
    38473847     * See Intel spec. 6.7.1 "Handling Multiple NMIs".
    38483848     */
    3849     VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_BLOCK_NMIS);
     3849    bool const fBlockingNmi = VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_BLOCK_NMIS);
     3850    if (fBlockingNmi)
     3851        VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_BLOCK_NMIS);
     3852
     3853#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
     3854    /*
     3855     * Record whether NMIs (or virtual-NMIs) were unblocked by execution of this
     3856     * IRET instruction. We need to provide this information as part of some VM-exits.
     3857     *
     3858     * See Intel spec. 27.2.2 "Information for VM Exits Due to Vectored Events".
     3859     */
     3860    if (IEM_VMX_IS_NON_ROOT_MODE(pVCpu))
     3861        pVCpu->cpum.GstCtx.hwvirt.vmx.fNmiUnblockingIret = fBlockingNmi;
     3862#endif
    38503863
    38513864    /*
  • trunk/src/VBox/VMM/VMMAll/IEMAllCImplVmxInstr.cpp.h

    r75638 r75671  
    15621562     *     interrupts until the completion of the current VMLAUNCH/VMRESUME
    15631563     *     instruction. Interrupt inhibition for any nested-guest instruction
    1564      *     will be set later while loading the guest-interruptibility state.
     1564     *     is supplied by the guest-interruptibility state VMCS field and will
     1565     *     be set up as part of loading the guest state.
    15651566     *
    15661567     *   - VMCPU_FF_BLOCK_NMIS needs to be cached as VM-exits caused before
    1567      *     successful VM-entry needs to continue blocking NMIs if it was in effect
    1568      *     during VM-entry.
     1568     *     successful VM-entry (due to invalid guest-state) need to continue
     1569     *     blocking NMIs if it was in effect before VM-entry.
    15691570     *
    15701571     *   - MTF need not be preserved as it's used only in VMX non-root mode and
    1571      *     is supplied on VM-entry through the VM-execution controls.
     1572     *     is supplied through the VM-execution controls.
    15721573     *
    1573      * The remaining FFs (e.g. timers, APIC updates) must stay in place so that
     1574     * The remaining FFs (e.g. timers, APIC updates) can stay in place so that
    15741575     * we will be able to generate interrupts that may cause VM-exits for
    15751576     * the nested-guest.
    15761577     */
    15771578    pVCpu->cpum.GstCtx.hwvirt.fLocalForcedActions = pVCpu->fLocalForcedActions & VMCPU_FF_BLOCK_NMIS;
    1578 
    1579     if (VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS | VMCPU_FF_BLOCK_NMIS))
    1580         VMCPU_FF_CLEAR_MASK(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS | VMCPU_FF_BLOCK_NMIS);
    15811579}
    15821580
     
    17541752    /* Interruptibility-state. */
    17551753    pVmcs->u32GuestIntrState = 0;
    1756     if (pVmcs->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI)
    1757     { /** @todo NSTVMX: Virtual-NMI blocking. */ }
    1758     else if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_BLOCK_NMIS))
     1754    if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_BLOCK_NMIS))
    17591755        pVmcs->u32GuestIntrState |= VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI;
    17601756
     
    17731769        &&  uExitReason != VMX_EXIT_SMI
    17741770        &&  uExitReason != VMX_EXIT_ERR_MACHINE_CHECK
    1775         && !HMVmxIsTrapLikeVmexit(uExitReason))
     1771        && !HMVmxIsVmexitTrapLike(uExitReason))
    17761772    {
    17771773        /** @todo NSTVMX: also must exclude VM-exits caused by debug exceptions when
     
    23672363    pVCpu->cpum.GstCtx.rflags.u = X86_EFL_1;
    23682364
    2369     /* Update non-register state. */
    2370     iemVmxVmexitRestoreForceFlags(pVCpu);
    2371 
    23722365    /* Clear address range monitoring. */
    23732366    EMMonitorWaitClear(pVCpu);
     
    27952788            return iemVmxAbort(pVCpu, VMXABORT_SAVE_GUEST_MSRS);
    27962789    }
     2790    else
     2791    {
     2792        /* Restore force-flags that may or may not have been cleared as part of the failed VM-entry. */
     2793        iemVmxVmexitRestoreForceFlags(pVCpu);
     2794    }
    27972795
    27982796    /*
     
    37553753        if (pVmcs->u32ExitCtls & VMX_EXIT_CTLS_ACK_EXT_INT)
    37563754        {
    3757             uint8_t  const fNmiUnblocking = 0;  /** @todo NSTVMX: Implement NMI-unblocking due to IRET. */
     3755            uint8_t  const fNmiUnblocking = pVCpu->cpum.GstCtx.hwvirt.vmx.fNmiUnblockingIret;
    37583756            uint32_t const uExitIntInfo   = RT_BF_MAKE(VMX_BF_EXIT_INT_INFO_VECTOR,           uVector)
    37593757                                          | RT_BF_MAKE(VMX_BF_EXIT_INT_INFO_TYPE,             VMX_EXIT_INT_INFO_TYPE_EXT_INT)
     
    39233921        }
    39243922
    3925         uint8_t  const fNmiUnblocking = 0;  /** @todo NSTVMX: Implement NMI-unblocking due to IRET. */
     3923        uint8_t  const fNmiUnblocking = pVCpu->cpum.GstCtx.hwvirt.vmx.fNmiUnblockingIret;
    39263924        uint8_t  const fErrCodeValid  = (fFlags & IEM_XCPT_FLAGS_ERR);
    39273925        uint8_t  const uIntInfoType   = iemVmxGetEventType(uVector, fFlags);
     
    67876785    PCVMXVVMCS pVmcs = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
    67886786    uint32_t const uEntryIntInfo = pVmcs->u32EntryIntInfo;
    6789     if (VMX_ENTRY_INT_INFO_IS_VALID(uEntryIntInfo))
    6790     {
    6791         /** @todo NSTVMX: Pending debug exceptions. */
    6792         Assert(!(pVmcs->u64GuestPendingDbgXcpt.u));
    6793 
    6794         if (pVmcs->u32GuestIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI)
    6795         {
    6796             /** @todo NSTVMX: Virtual-NMIs doesn't affect NMI blocking in the normal sense.
    6797              *        We probably need a different force flag for virtual-NMI
    6798              *        pending/blocking. */
    6799             Assert(!(pVmcs->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI));
    6800             VMCPU_FF_SET(pVCpu, VMCPU_FF_BLOCK_NMIS);
    6801         }
    6802         else
    6803             Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_BLOCK_NMIS));
    6804 
     6787    if (!HMVmxIsVmentryVectoring(uEntryIntInfo))
     6788    {
    68056789        if (pVmcs->u32GuestIntrState & (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS))
    68066790            EMSetInhibitInterruptsPC(pVCpu, pVCpu->cpum.GstCtx.rip);
     
    68106794        /* SMI blocking is irrelevant. We don't support SMIs yet. */
    68116795    }
     6796    else
     6797    {
     6798        /* When the VM-entry is not vectoring, there is no blocking by STI or Mov-SS. */
     6799        if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
     6800            VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
     6801    }
     6802
     6803    /* NMI blocking. */
     6804    if (   (pVmcs->u32GuestIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI)
     6805        && !VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_BLOCK_NMIS))
     6806        VMCPU_FF_SET(pVCpu, VMCPU_FF_BLOCK_NMIS);
     6807
     6808    /** @todo NSTVMX: Pending debug exceptions. */
     6809    Assert(!(pVmcs->u64GuestPendingDbgXcpt.u));
    68126810
    68136811    /* Loading PDPTEs will be taken care when we switch modes. We don't support EPT yet. */
     
    70487046                if (RT_SUCCESS(rc))
    70497047                {
    7050                     /* Save the guest force-flags as VM-exits can occur from this point on. */
    7051                     iemVmxVmentrySaveForceFlags(pVCpu);
    7052 
    70537048                    /* Initialize the VM-exit qualification field as it MBZ for VM-exits where it isn't specified. */
    70547049                    iemVmxVmcsSetExitQual(pVCpu, 0);
     7050
     7051                    /*
     7052                     * Blocking of NMIs need to be restored if VM-entry fails due to invalid-guest state.
     7053                     * So we save the required force flags here (currently only VMCPU_FF_BLOCK_NMI) so we
     7054                     * can restore it on VM-exit when required.
     7055                     */
     7056                    iemVmxVmentrySaveForceFlags(pVCpu);
    70557057
    70567058                    rc = iemVmxVmentryCheckGuestState(pVCpu, pszInstr);
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