VirtualBox

Changeset 75671 in vbox


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
Files:
6 edited

Legend:

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

    r75301 r75671  
    573573                /** 0x306 - Whether the injected events are subjected to event intercepts.  */
    574574                bool                    fInterceptEvents;
    575                 bool                    afPadding0[1];
     575                /** 0x307 - Whether blocking of NMI (or virtual-NMIs) was in effect in VMX non-root
     576                 *  mode before execution of IRET. */
     577                bool                    fNmiUnblockingIret;
    576578                /** 0x308 - Cache of the nested-guest current VMCS - R0 ptr. */
    577579                R0PTRTYPE(PVMXVVMCS)    pVmcsR0;
     
    756758AssertCompileMemberOffset(CPUMCTX, hwvirt.CPUM_UNION_NM(s.) vmx.fInVmxNonRootMode,      0x305);
    757759AssertCompileMemberOffset(CPUMCTX, hwvirt.CPUM_UNION_NM(s.) vmx.fInterceptEvents,       0x306);
     760AssertCompileMemberOffset(CPUMCTX, hwvirt.CPUM_UNION_NM(s.) vmx.fNmiUnblockingIret,     0x307);
    758761AssertCompileMemberOffset(CPUMCTX, hwvirt.CPUM_UNION_NM(s.) vmx.pVmcsR0,                0x308);
    759762AssertCompileMemberOffset(CPUMCTX, hwvirt.CPUM_UNION_NM(s.) vmx.pVmcsR3,                0x310);
  • trunk/include/VBox/vmm/hm_vmx.h

    r75611 r75671  
    41564156 * Returns whether or not the VM-exit is trap-like or fault-like.
    41574157 *
    4158  * @returns @c true if it's a trap-like VM-exit, @c false otehrwise.
     4158 * @returns @c true if it's a trap-like VM-exit, @c false otherwise.
    41594159 * @param   uExitReason     The VM-exit reason.
    41604160 *
    41614161 * @remarks Warning! This does not validate the VM-exit reason.
    41624162 */
    4163 DECLINLINE(bool) HMVmxIsTrapLikeVmexit(uint32_t uExitReason)
     4163DECLINLINE(bool) HMVmxIsVmexitTrapLike(uint32_t uExitReason)
    41644164{
    41654165    /*
     
    41884188    return false;
    41894189}
     4190
     4191
     4192/**
     4193 * Returns whether the VM-entry is vectoring or not given the VM-entry interruption
     4194 * information field.
     4195 *
     4196 * @returns @c true if the VM-entry is vectoring, @c false otherwise.
     4197 * @param   uEntryIntInfo   The VM-entry interruption information field.
     4198 */
     4199DECLINLINE(bool) HMVmxIsVmentryVectoring(uint32_t uEntryIntInfo)
     4200{
     4201    if (!VMX_ENTRY_INT_INFO_IS_VALID(uEntryIntInfo))
     4202        return false;
     4203    uint8_t const uIntInfoType = VMX_ENTRY_INT_INFO_TYPE(uEntryIntInfo);
     4204    switch (uIntInfoType)
     4205    {
     4206        case VMX_ENTRY_INT_INFO_TYPE_EXT_INT:
     4207        case VMX_ENTRY_INT_INFO_TYPE_NMI:
     4208        case VMX_ENTRY_INT_INFO_TYPE_HW_XCPT:
     4209        case VMX_ENTRY_INT_INFO_TYPE_SW_INT:
     4210        case VMX_ENTRY_INT_INFO_TYPE_PRIV_SW_XCPT:
     4211        case VMX_ENTRY_INT_INFO_TYPE_SW_XCPT:
     4212            return true;
     4213    }
     4214    return false;
     4215}
    41904216/** @} */
    41914217
  • trunk/include/VBox/vmm/vm.h

    r75646 r75671  
    546546/** VMX-preemption timer in effect. */
    547547#define VMCPU_FF_VMX_PREEMPT_TIMER          RT_BIT_64(VMCPU_FF_VMX_PREEMPT_TIMER_BIT)
    548 /** Bit number for VMCPU_FF_VMX_PREEMPT_TIMER. */
    549548#define VMCPU_FF_VMX_PREEMPT_TIMER_BIT      32
    550549/** Pending MTF (Monitor Trap Flag) event.  */
    551550#define VMCPU_FF_VMX_MTF                    RT_BIT_64(VMCPU_FF_VMX_MTF_BIT)
    552 /** The bit number for VMCPU_FF_VMX_MTF. */
    553551#define VMCPU_FF_VMX_MTF_BIT                33
    554552/** VMX APIC-write emulation pending.  */
    555553#define VMCPU_FF_VMX_APIC_WRITE             RT_BIT_64(VMCPU_FF_VMX_APIC_WRITE_BIT)
    556 /** The bit number for VMCPU_FF_VMX_UPDATE_VTPR. */
    557554#define VMCPU_FF_VMX_APIC_WRITE_BIT         34
    558555
  • 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);
  • trunk/src/VBox/VMM/testcase/tstVMStruct.h

    r75301 r75671  
    154154    GEN_CHECK_OFF(CPUMCTX, hwvirt.vmx.fInVmxNonRootMode);
    155155    GEN_CHECK_OFF(CPUMCTX, hwvirt.vmx.fInterceptEvents);
     156    GEN_CHECK_OFF(CPUMCTX, hwvirt.vmx.fNmiUnblockingIret);
    156157    GEN_CHECK_OFF(CPUMCTX, hwvirt.vmx.pVmcsR0);
    157158    GEN_CHECK_OFF(CPUMCTX, hwvirt.vmx.pVmcsR3);
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