Changeset 75135 in vbox for trunk/src/VBox/VMM/VMMAll
- Timestamp:
- Oct 29, 2018 4:27:39 AM (6 years ago)
- Location:
- trunk/src/VBox/VMM/VMMAll
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMAll/IEMAll.cpp
r74901 r75135 118 118 #include <VBox/dis.h> 119 119 #include <VBox/disopcode.h> 120 #include <iprt/asm-math.h> 120 121 #include <iprt/assert.h> 121 122 #include <iprt/string.h> -
trunk/src/VBox/VMM/VMMAll/IEMAllCImplVmxInstr.cpp.h
r74934 r75135 2154 2154 } 2155 2155 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 2157 2201 2158 2202 /* PDPTEs. */ … … 4930 4974 4931 4975 /** 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 switching4939 * 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 interrupts4945 * 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.u1IF4955 && !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 /**4966 4976 * Checks host-state as part of VM-entry. 4967 4977 * … … 5885 5895 5886 5896 /** 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 */ 5902 IEM_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 /** 5887 5922 * Performs event injection (if any) as part of VM-entry. 5888 5923 * … … 6091 6126 pVCpu->cpum.GstCtx.hwvirt.vmx.fInVmxNonRootMode = true; 6092 6127 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); 6105 6143 6106 6144 /* Now that we've switched page tables, we can inject events if any. */
Note:
See TracChangeset
for help on using the changeset viewer.