VirtualBox

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


Ignore:
Timestamp:
Oct 29, 2018 4:27:39 AM (6 years ago)
Author:
vboxsync
Message:

VMM: Nested VMX: bugref:9180 Setup VMX preemption timer, remove verbose comment later if needed.

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

Legend:

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

    r74901 r75135  
    118118#include <VBox/dis.h>
    119119#include <VBox/disopcode.h>
     120#include <iprt/asm-math.h>
    120121#include <iprt/assert.h>
    121122#include <iprt/string.h>
  • trunk/src/VBox/VMM/VMMAll/IEMAllCImplVmxInstr.cpp.h

    r74934 r75135  
    21542154    }
    21552155
    2156     /** @todo NSTVMX: Save VMX preemption timer value. */
     2156    /* Save VMX-preemption timer value. */
     2157    if (pVmcs->u32ExitCtls & VMX_EXIT_CTLS_SAVE_PREEMPT_TIMER)
     2158    {
     2159        uint32_t uPreemptTimer;
     2160        if (uExitReason == VMX_EXIT_PREEMPT_TIMER)
     2161            uPreemptTimer = 0;
     2162        else
     2163        {
     2164            /*
     2165             * Assume the following:
     2166             * PreemptTimerShift = 5
     2167             * VmcsPreemptTimer  = 2 (i.e. need to decrement by 1 every 2 * RT_BIT(5) = 20000 TSC ticks)
     2168             * VmentryTick       = 50000 (TSC at time of VM-entry)
     2169             *
     2170             * CurTick   Delta    PreemptTimerVal
     2171             * ----------------------------------
     2172             *  60000    10000    2
     2173             *  80000    30000    1
     2174             *  90000    40000    0  -> VM-exit.
     2175             *
     2176             * If Delta >= VmcsPreemptTimer * RT_BIT(PreemptTimerShift) cause a VMX-preemption timer VM-exit.
     2177             *
     2178             * The saved VMX-preemption timer value is calculated as follows:
     2179             * PreemptTimerVal = VmcsPreemptTimer - (Delta / (VmcsPreemptTimer * RT_BIT(PreemptTimerShift)))
     2180             * E.g.:
     2181             *  Delta  = 10000
     2182             *    Tmp    = 10000 / (2 * 10000) = 0.5
     2183             *    NewPt  = 2 - 0.5 = 2
     2184             *  Delta  = 30000
     2185             *    Tmp    = 30000 / (2 * 10000) = 1.5
     2186             *    NewPt  = 2 - 1.5 = 1
     2187             *  Delta  = 40000
     2188             *    Tmp    = 40000 / 20000 = 2
     2189             *    NewPt  = 2 - 2 = 0
     2190             */
     2191            uint64_t const uCurTick        = TMCpuTickGetNoCheck(pVCpu);
     2192            uint64_t const uVmentryTick    = pVCpu->cpum.GstCtx.hwvirt.vmx.uVmentryTick;
     2193            uint64_t const uDelta          = uCurTick - uVmentryTick;
     2194            uint32_t const uVmcsPreemptVal = pVmcs->u32PreemptTimer;
     2195            uPreemptTimer = uVmcsPreemptVal - ASMDivU64ByU32RetU32(uDelta, uVmcsPreemptVal * RT_BIT(VMX_V_PREEMPT_TIMER_SHIFT));
     2196        }
     2197
     2198        pVmcs->u32PreemptTimer = uPreemptTimer;
     2199    }
     2200
    21572201
    21582202    /* PDPTEs. */
     
    49304974
    49314975/**
    4932  * Checks if an interrupt-window exiting occurs immediately as part of VM-entry.
    4933  *
    4934  * @returns VBox status code.
    4935  * @param   pVCpu           The cross context virtual CPU structure.
    4936  * @param   pszInstr        The VMX instruction name (for logging purposes).
    4937  *
    4938  * @remarks This must be called after loading the guest-state and switching
    4939  *          page-tables as part of VM-entry!
    4940  */
    4941 IEM_STATIC int iemVmxVmentryCheckIntWindowExit(PVMCPU pVCpu, const char *pszInstr)
    4942 {
    4943     /*
    4944      * An interrupt-window exit occurs immediately after VM-entry if interrupts
    4945      * are enabled and the interrupt-window exit control is set.
    4946      *
    4947      * See Intel spec. 25.2 "Other Causes Of VM Exits".
    4948      * See Intel spec. 26.6.5 "Interrupt-Window Exiting and Virtual-Interrupt Delivery".
    4949      */
    4950     PCVMXVVMCS pVmcs = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
    4951     Assert(pVmcs);
    4952 
    4953     if (   (pVmcs->u32ProcCtls & VMX_PROC_CTLS_INT_WINDOW_EXIT)
    4954         &&  pVCpu->cpum.GstCtx.eflags.Bits.u1IF
    4955         && !VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
    4956     {
    4957         Log(("%s: Interrupt-window detected during VM-entry -> VM-exit\n", pszInstr));
    4958         return iemVmxVmexitIntWindow(pVCpu);
    4959     }
    4960 
    4961     return VINF_VMX_INTERCEPT_NOT_ACTIVE;
    4962 }
    4963 
    4964 
    4965 /**
    49664976 * Checks host-state as part of VM-entry.
    49674977 *
     
    58855895
    58865896/**
     5897 * Set up the VMX-preemption timer.
     5898 *
     5899 * @param   pVCpu       The cross context virtual CPU structure.
     5900 * @param   pszInstr    The VMX instruction name (for logging purposes).
     5901 */
     5902IEM_STATIC void iemVmxVmentrySetupPreemptTimer(PVMCPU pVCpu, const char *pszInstr)
     5903{
     5904    PCVMXVVMCS pVmcs = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
     5905    Assert(pVmcs);
     5906    if (pVmcs->u32PinCtls & VMX_PIN_CTLS_PREEMPT_TIMER)
     5907    {
     5908        uint64_t const uVmentryTick = TMCpuTickGetNoCheck(pVCpu);
     5909        pVCpu->cpum.GstCtx.hwvirt.vmx.uVmentryTick = uVmentryTick;
     5910        VMCPU_FF_SET(pVCpu, VMCPU_FF_VMX_PREEMPT_TIMER);
     5911
     5912        Log(("%s: VM-entry set up VMX-preemption timer at %#RX64\n", pszInstr, uVmentryTick));
     5913    }
     5914    else
     5915        Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_VMX_PREEMPT_TIMER));
     5916
     5917    NOREF(pszInstr);
     5918}
     5919
     5920
     5921/**
    58875922 * Performs event injection (if any) as part of VM-entry.
    58885923 *
     
    60916126                                pVCpu->cpum.GstCtx.hwvirt.vmx.fInVmxNonRootMode = true;
    60926127
    6093                                 /** The priority of potential VM-exits during VM-entry is important. */
    6094                                 /** @todo NSTVMX: Any debug trap exceptions must be handled here. */
    6095                                 /** @todo NSTVMX: VMX preemption timer exiting. */
    6096                                 /** @todo NSTVMX: TPR thresholding exiting. */
    6097                                 /** @todo NSTVMX: NMI-window exiting. */
    6098 
    6099                                 /* Check premature interrupt-window exiting. */
    6100                                 rc = iemVmxVmentryCheckIntWindowExit(pVCpu, pszInstr);
    6101                                 if (rc != VINF_VMX_INTERCEPT_NOT_ACTIVE)
    6102                                     return rc;
    6103 
    6104                                 /** @todo NSTVMX: Pending MTF exiting. */
     6128                                /*
     6129                                 * The priority of potential VM-exits during VM-entry is important.
     6130                                 * The priorities are listed from highest to lowest as follows:
     6131                                 *
     6132                                 * 1. Debug exceptions.
     6133                                 * 2. VMX-preemption timer.
     6134                                 * 3. NMI-window exit.
     6135                                 * 4. NMI injection.
     6136                                 * 5. Interrupt-window exit.
     6137                                 * 6. Interrupt injection.
     6138                                 * 7. MTF exit.
     6139                                 */
     6140
     6141                                /* Setup the VMX-preemption timer. */
     6142                                iemVmxVmentrySetupPreemptTimer(pVCpu, pszInstr);
    61056143
    61066144                                /* Now that we've switched page tables, we can inject events if any. */
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