VirtualBox

Changeset 74753 in vbox for trunk/src/VBox/VMM


Ignore:
Timestamp:
Oct 11, 2018 9:01:28 AM (6 years ago)
Author:
vboxsync
Message:

VMM/IEM: Nested VMX: bugref:9180 VM-exit bits; Implemented pause and pause-loop exiting.

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

Legend:

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

    r74751 r74753  
    35393539
    35403540/**
     3541 * VMX VM-exit handler for VM-exits due to MWAIT.
     3542 *
     3543 * @returns VBox strict status code.
     3544 * @param   pVCpu               The cross context virtual CPU structure.
     3545 * @param   fMonitorHwArmed     Whether the address-range monitor hardware is armed.
     3546 * @param   cbInstr             The instruction length in bytes.
     3547 */
     3548IEM_STATIC VBOXSTRICTRC iemVmxVmexitInstrMwait(PVMCPU pVCpu, bool fMonitorHwArmed, uint8_t cbInstr)
     3549{
     3550    VMXVEXITINFO ExitInfo;
     3551    RT_ZERO(ExitInfo);
     3552    ExitInfo.uReason = VMX_EXIT_MWAIT;
     3553    ExitInfo.cbInstr = cbInstr;
     3554    ExitInfo.u64Qual = fMonitorHwArmed;
     3555    return iemVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
     3556}
     3557
     3558
     3559/**
     3560 * VMX VM-exit handler for VM-exits due to PAUSE.
     3561 *
     3562 * @returns VBox strict status code.
     3563 * @param   pVCpu               The cross context virtual CPU structure.
     3564 * @param   cbInstr             The instruction length in bytes.
     3565 */
     3566IEM_STATIC VBOXSTRICTRC iemVmxVmexitInstrPause(PVMCPU pVCpu, uint8_t cbInstr)
     3567{
     3568    PCVMXVVMCS pVmcs = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
     3569    Assert(pVmcs);
     3570
     3571    /*
     3572     * The PAUSE VM-exit is controlled by the "PAUSE exiting" control and the
     3573     * "PAUSE-loop exiting" control.
     3574     *
     3575     * The PLE-Gap is the maximum number of TSC ticks between two successive executions of
     3576     * the PAUSE instruction before we cause a VM-exit. The PLE-Window is the maximum amount
     3577     * of TSC ticks the guest is allowed to execute in a pause loop before we must cause
     3578     * a VM-exit.
     3579     *
     3580     * See Intel spec. 24.6.13 "Controls for PAUSE-Loop Exiting".
     3581     * See Intel spec. 25.1.3 "Instructions That Cause VM Exits Conditionally".
     3582     */
     3583    bool fIntercept = false;
     3584    if (pVmcs->u32ProcCtls & VMX_PROC_CTLS_PAUSE_EXIT)
     3585        fIntercept = true;
     3586    else if (pVmcs->u32ProcCtls2 & VMX_PROC_CTLS2_PAUSE_LOOP_EXIT)
     3587    {
     3588        IEM_CTX_IMPORT_RET(pVCpu, CPUMCTX_EXTRN_HWVIRT);
     3589
     3590        uint64_t      *puFirstPauseLoopTick = &pVCpu->cpum.GstCtx.hwvirt.vmx.uFirstPauseLoopTick;
     3591        uint64_t const uPrevPauseTick       = pVCpu->cpum.GstCtx.hwvirt.vmx.uPrevPauseTick;
     3592        uint32_t const uPleGap              = pVmcs->u32PleGap;
     3593        uint32_t const uPleWindow           = pVmcs->u32PleWindow;
     3594        uint64_t const uTick                = TMCpuTickGet(pVCpu);
     3595        if (uTick - uPrevPauseTick > uPleGap)
     3596            *puFirstPauseLoopTick = uTick;
     3597        else if (uTick - *puFirstPauseLoopTick > uPleWindow)
     3598            fIntercept = true;
     3599    }
     3600
     3601    if (fIntercept)
     3602    {
     3603        VMXVEXITINFO ExitInfo;
     3604        RT_ZERO(ExitInfo);
     3605        ExitInfo.uReason = VMX_EXIT_PAUSE;
     3606        ExitInfo.cbInstr = cbInstr;
     3607        return iemVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
     3608    }
     3609
     3610    return VINF_VMX_INTERCEPT_NOT_ACTIVE;
     3611}
     3612
     3613
     3614/**
    35413615 * VMX VM-exit handler for VM-exits due to task switches.
    35423616 *
     
    37153789
    37163790    return VINF_VMX_INTERCEPT_NOT_ACTIVE;
    3717 }
    3718 
    3719 
    3720 /**
    3721  * VMX VM-exit handler for VM-exits due to MWAIT instruction.
    3722  *
    3723  * @returns VBox strict status code.
    3724  * @param   pVCpu               The cross context virtual CPU structure.
    3725  * @param   fMonitorHwArmed     Whether the address-range monitor hardware is armed.
    3726  * @param   cbInstr             The instruction length in bytes.
    3727  */
    3728 IEM_STATIC VBOXSTRICTRC iemVmxVmexitInstrMwait(PVMCPU pVCpu, bool fMonitorHwArmed, uint8_t cbInstr)
    3729 {
    3730     VMXVEXITINFO ExitInfo;
    3731     RT_ZERO(ExitInfo);
    3732     ExitInfo.uReason = VMX_EXIT_MWAIT;
    3733     ExitInfo.cbInstr = cbInstr;
    3734     ExitInfo.u64Qual = fMonitorHwArmed;
    3735     return iemVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
    37363791}
    37373792
     
    70517106}
    70527107
     7108
     7109/**
     7110 * Implements VMX's implementation of PAUSE.
     7111 */
     7112IEM_CIMPL_DEF_0(iemCImpl_vmx_pause)
     7113{
     7114    if (IEM_VMX_IS_NON_ROOT_MODE(pVCpu))
     7115    {
     7116        VBOXSTRICTRC rcStrict = iemVmxVmexitInstrPause(pVCpu, cbInstr);
     7117        if (rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE)
     7118            return rcStrict;
     7119    }
     7120
     7121    /*
     7122     * Outside VMX non-root operation or if the PAUSE instruction does not cause
     7123     * a VM-exit, the instruction operates normally.
     7124     */
     7125    iemRegAddToRipAndClearRF(pVCpu, cbInstr);
     7126    return VINF_SUCCESS;
     7127}
     7128
    70537129#endif  /* VBOX_WITH_NESTED_HWVIRT_VMX */
    70547130
  • trunk/src/VBox/VMM/VMMAll/IEMAllInstructionsOneByte.cpp.h

    r74661 r74753  
    44554455    {
    44564456        IEMOP_MNEMONIC(pause, "pause");
     4457#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
     4458        if (IEM_GET_GUEST_CPU_FEATURES(pVCpu)->fVmx)
     4459            return IEM_MC_DEFER_TO_CIMPL_0(iemCImpl_vmx_pause);
     4460#endif
    44574461#ifdef VBOX_WITH_NESTED_HWVIRT_SVM
    44584462        if (IEM_GET_GUEST_CPU_FEATURES(pVCpu)->fSvm)
  • trunk/src/VBox/VMM/VMMR3/CPUM.cpp

    r74660 r74753  
    31893189        pHlp->pfnPrintf(pHlp, "  fInVmxNonRootMode          = %RTbool\n",   pCtx->hwvirt.vmx.fInVmxNonRootMode);
    31903190        pHlp->pfnPrintf(pHlp, "  fInterceptEvents           = %RTbool\n",   pCtx->hwvirt.vmx.fInterceptEvents);
     3191        pHlp->pfnPrintf(pHlp, "  uFirstPauseLoopTick        = %RX64\n",     pCtx->hwvirt.vmx.uFirstPauseLoopTick);
     3192        pHlp->pfnPrintf(pHlp, "  uPrevPauseTick             = %RX64\n",     pCtx->hwvirt.vmx.uPrevPauseTick);
    31913193
    31923194        /** @todo NSTVMX: Dump remaining/new fields. */
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