儲存庫 vbox 的更動 75884
- 時間撮記:
- 2018-12-3 上午04:28:51 (6 年 以前)
- 檔案:
-
- 修改 1 筆資料
圖例:
- 未更動
- 新增
- 刪除
-
trunk/src/VBox/VMM/VMMAll/IEMAllCImplVmxInstr.cpp.h
r75735 r75884 1633 1633 1634 1634 /** 1635 * Calculates the current VMX-preemption timer value. 1636 * 1637 * @param pVCpu The cross context virtual CPU structure. 1638 */ 1639 IEM_STATIC uint32_t iemVmxCalcPreemptTimer(PVMCPU pVCpu) 1640 { 1641 PCVMXVVMCS pVmcs = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs); 1642 Assert(pVmcs); 1643 1644 /* 1645 * Assume the following: 1646 * PreemptTimerShift = 5 1647 * VmcsPreemptTimer = 2 (i.e. need to decrement by 1 every 2 * RT_BIT(5) = 20000 TSC ticks) 1648 * VmentryTick = 50000 (TSC at time of VM-entry) 1649 * 1650 * CurTick Delta PreemptTimerVal 1651 * ---------------------------------- 1652 * 60000 10000 2 1653 * 80000 30000 1 1654 * 90000 40000 0 -> VM-exit. 1655 * 1656 * If Delta >= VmcsPreemptTimer * RT_BIT(PreemptTimerShift) cause a VMX-preemption timer VM-exit. 1657 * The saved VMX-preemption timer value is calculated as follows: 1658 * PreemptTimerVal = VmcsPreemptTimer - (Delta / (VmcsPreemptTimer * RT_BIT(PreemptTimerShift))) 1659 * E.g.: 1660 * Delta = 10000 1661 * Tmp = 10000 / (2 * 10000) = 0.5 1662 * NewPt = 2 - 0.5 = 2 1663 * Delta = 30000 1664 * Tmp = 30000 / (2 * 10000) = 1.5 1665 * NewPt = 2 - 1.5 = 1 1666 * Delta = 40000 1667 * Tmp = 40000 / 20000 = 2 1668 * NewPt = 2 - 2 = 0 1669 */ 1670 uint64_t const uCurTick = TMCpuTickGetNoCheck(pVCpu); 1671 uint64_t const uVmentryTick = pVCpu->cpum.GstCtx.hwvirt.vmx.uVmentryTick; 1672 uint64_t const uDelta = uCurTick - uVmentryTick; 1673 uint32_t const uVmcsPreemptVal = pVmcs->u32PreemptTimer; 1674 uint32_t const uPreemptTimer = uVmcsPreemptVal 1675 - ASMDivU64ByU32RetU32(uDelta, uVmcsPreemptVal * RT_BIT(VMX_V_PREEMPT_TIMER_SHIFT)); 1676 return uPreemptTimer; 1677 } 1678 1679 1680 /** 1635 1681 * Saves guest segment registers, GDTR, IDTR, LDTR, TR as part of VM-exit. 1636 1682 * … … 1791 1837 } 1792 1838 1793 /* Save VMX-preemption timer value. */ 1794 if (pVmcs->u32ExitCtls & VMX_EXIT_CTLS_SAVE_PREEMPT_TIMER) 1795 { 1796 uint32_t uPreemptTimer; 1797 if (uExitReason == VMX_EXIT_PREEMPT_TIMER) 1798 uPreemptTimer = 0; 1799 else 1800 { 1801 /* 1802 * Assume the following: 1803 * PreemptTimerShift = 5 1804 * VmcsPreemptTimer = 2 (i.e. need to decrement by 1 every 2 * RT_BIT(5) = 20000 TSC ticks) 1805 * VmentryTick = 50000 (TSC at time of VM-entry) 1806 * 1807 * CurTick Delta PreemptTimerVal 1808 * ---------------------------------- 1809 * 60000 10000 2 1810 * 80000 30000 1 1811 * 90000 40000 0 -> VM-exit. 1812 * 1813 * If Delta >= VmcsPreemptTimer * RT_BIT(PreemptTimerShift) cause a VMX-preemption timer VM-exit. 1814 * The saved VMX-preemption timer value is calculated as follows: 1815 * PreemptTimerVal = VmcsPreemptTimer - (Delta / (VmcsPreemptTimer * RT_BIT(PreemptTimerShift))) 1816 * E.g.: 1817 * Delta = 10000 1818 * Tmp = 10000 / (2 * 10000) = 0.5 1819 * NewPt = 2 - 0.5 = 2 1820 * Delta = 30000 1821 * Tmp = 30000 / (2 * 10000) = 1.5 1822 * NewPt = 2 - 1.5 = 1 1823 * Delta = 40000 1824 * Tmp = 40000 / 20000 = 2 1825 * NewPt = 2 - 2 = 0 1826 */ 1827 uint64_t const uCurTick = TMCpuTickGetNoCheck(pVCpu); 1828 uint64_t const uVmentryTick = pVCpu->cpum.GstCtx.hwvirt.vmx.uVmentryTick; 1829 uint64_t const uDelta = uCurTick - uVmentryTick; 1830 uint32_t const uVmcsPreemptVal = pVmcs->u32PreemptTimer; 1831 uPreemptTimer = uVmcsPreemptVal - ASMDivU64ByU32RetU32(uDelta, uVmcsPreemptVal * RT_BIT(VMX_V_PREEMPT_TIMER_SHIFT)); 1832 } 1833 1834 pVmcs->u32PreemptTimer = uPreemptTimer; 1835 } 1836 1839 /* 1840 * Save the VMX-preemption timer value back into the VMCS if the feature is enabled. 1841 * 1842 * For VMX-preemption timer VM-exits, we should have already written back 0 if the 1843 * feature is supported back into the VMCS, and thus there is nothing further to do here. 1844 */ 1845 if ( uExitReason != VMX_EXIT_PREEMPT_TIMER 1846 && (pVmcs->u32ExitCtls & VMX_EXIT_CTLS_SAVE_PREEMPT_TIMER)) 1847 pVmcs->u32PreemptTimer = iemVmxCalcPreemptTimer(pVCpu); 1837 1848 1838 1849 /* PDPTEs. */ … … 3726 3737 IEM_STATIC VBOXSTRICTRC iemVmxVmexitPreemptTimer(PVMCPU pVCpu) 3727 3738 { 3728 P CVMXVVMCS pVmcs = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);3739 PVMXVVMCS pVmcs = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs); 3729 3740 Assert(pVmcs); 3730 Assert(pVmcs->u32PinCtls & VMX_PIN_CTLS_PREEMPT_TIMER); 3731 NOREF(pVmcs); 3732 3733 iemVmxVmcsSetExitQual(pVCpu, 0); 3734 return iemVmxVmexit(pVCpu, VMX_EXIT_PREEMPT_TIMER); 3741 3742 /* Check if the guest has enabled VMX-preemption timers in the first place. */ 3743 if (pVmcs->u32PinCtls & VMX_PIN_CTLS_PREEMPT_TIMER) 3744 { 3745 /* 3746 * Calculate the current VMX-preemption timer value. 3747 * Only if the value has reached zero, we cause the VM-exit. 3748 */ 3749 uint32_t uPreemptTimer = iemVmxCalcPreemptTimer(pVCpu); 3750 if (!uPreemptTimer) 3751 { 3752 /* Save the VMX-preemption timer value (of 0) back in to the VMCS if the CPU supports this feature. */ 3753 if (pVmcs->u32ExitCtls & VMX_EXIT_CTLS_SAVE_PREEMPT_TIMER) 3754 pVmcs->u32PreemptTimer = 0; 3755 3756 /* Cause the VMX-preemption timer VM-exit. The VM-exit qualification MBZ. */ 3757 iemVmxVmcsSetExitQual(pVCpu, 0); 3758 return iemVmxVmexit(pVCpu, VMX_EXIT_PREEMPT_TIMER); 3759 } 3760 } 3761 3762 return VINF_VMX_INTERCEPT_NOT_ACTIVE; 3735 3763 } 3736 3764
注意:
瀏覽 TracChangeset
來幫助您使用更動檢視器