Index: /trunk/include/VBox/vmm/cpumctx.h
===================================================================
--- /trunk/include/VBox/vmm/cpumctx.h	(revision 74752)
+++ /trunk/include/VBox/vmm/cpumctx.h	(revision 74753)
@@ -654,6 +654,11 @@
                 uint32_t                uIoBitmapR3;
 #endif
-                /** 0x388 - Padding. */
-                uint8_t             abPadding[0x3f0 - 0x388];
+                /** 0x388 - Guest TSC timestamp of the first PAUSE instruction that is considered to
+                 *  be the first in a loop. */
+                uint64_t                uFirstPauseLoopTick;
+                /** 0x390 - Guest TSC timestamp of the previous PAUSE instruction. */
+                uint64_t                uPrevPauseTick;
+                /** 0x398 - Padding. */
+                uint8_t             abPadding[0x3f0 - 0x398];
             } vmx;
         } CPUM_UNION_NM(s);
@@ -759,4 +764,6 @@
 AssertCompileMemberOffset(CPUMCTX, hwvirt.CPUM_UNION_NM(s.) vmx.pvIoBitmapR0,           0x378);
 AssertCompileMemberOffset(CPUMCTX, hwvirt.CPUM_UNION_NM(s.) vmx.pvIoBitmapR3,           0x380);
+AssertCompileMemberOffset(CPUMCTX, hwvirt.CPUM_UNION_NM(s.) vmx.uFirstPauseLoopTick,    0x388);
+AssertCompileMemberOffset(CPUMCTX, hwvirt.CPUM_UNION_NM(s.) vmx.uPrevPauseTick,         0x390);
 AssertCompileMemberAlignment(CPUMCTX, hwvirt.CPUM_UNION_NM(s.) vmx.pVmcsR0,           8);
 AssertCompileMemberAlignment(CPUMCTX, hwvirt.CPUM_UNION_NM(s.) vmx.pShadowVmcsR0,     8);
Index: /trunk/src/VBox/VMM/VMMAll/IEMAllCImplVmxInstr.cpp.h
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/IEMAllCImplVmxInstr.cpp.h	(revision 74752)
+++ /trunk/src/VBox/VMM/VMMAll/IEMAllCImplVmxInstr.cpp.h	(revision 74753)
@@ -3539,4 +3539,78 @@
 
 /**
+ * VMX VM-exit handler for VM-exits due to MWAIT.
+ *
+ * @returns VBox strict status code.
+ * @param   pVCpu               The cross context virtual CPU structure.
+ * @param   fMonitorHwArmed     Whether the address-range monitor hardware is armed.
+ * @param   cbInstr             The instruction length in bytes.
+ */
+IEM_STATIC VBOXSTRICTRC iemVmxVmexitInstrMwait(PVMCPU pVCpu, bool fMonitorHwArmed, uint8_t cbInstr)
+{
+    VMXVEXITINFO ExitInfo;
+    RT_ZERO(ExitInfo);
+    ExitInfo.uReason = VMX_EXIT_MWAIT;
+    ExitInfo.cbInstr = cbInstr;
+    ExitInfo.u64Qual = fMonitorHwArmed;
+    return iemVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
+}
+
+
+/**
+ * VMX VM-exit handler for VM-exits due to PAUSE.
+ *
+ * @returns VBox strict status code.
+ * @param   pVCpu               The cross context virtual CPU structure.
+ * @param   cbInstr             The instruction length in bytes.
+ */
+IEM_STATIC VBOXSTRICTRC iemVmxVmexitInstrPause(PVMCPU pVCpu, uint8_t cbInstr)
+{
+    PCVMXVVMCS pVmcs = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
+    Assert(pVmcs);
+
+    /*
+     * The PAUSE VM-exit is controlled by the "PAUSE exiting" control and the
+     * "PAUSE-loop exiting" control.
+     *
+     * The PLE-Gap is the maximum number of TSC ticks between two successive executions of
+     * the PAUSE instruction before we cause a VM-exit. The PLE-Window is the maximum amount
+     * of TSC ticks the guest is allowed to execute in a pause loop before we must cause
+     * a VM-exit.
+     *
+     * See Intel spec. 24.6.13 "Controls for PAUSE-Loop Exiting".
+     * See Intel spec. 25.1.3 "Instructions That Cause VM Exits Conditionally".
+     */
+    bool fIntercept = false;
+    if (pVmcs->u32ProcCtls & VMX_PROC_CTLS_PAUSE_EXIT)
+        fIntercept = true;
+    else if (pVmcs->u32ProcCtls2 & VMX_PROC_CTLS2_PAUSE_LOOP_EXIT)
+    {
+        IEM_CTX_IMPORT_RET(pVCpu, CPUMCTX_EXTRN_HWVIRT);
+
+        uint64_t      *puFirstPauseLoopTick = &pVCpu->cpum.GstCtx.hwvirt.vmx.uFirstPauseLoopTick;
+        uint64_t const uPrevPauseTick       = pVCpu->cpum.GstCtx.hwvirt.vmx.uPrevPauseTick;
+        uint32_t const uPleGap              = pVmcs->u32PleGap;
+        uint32_t const uPleWindow           = pVmcs->u32PleWindow;
+        uint64_t const uTick                = TMCpuTickGet(pVCpu);
+        if (uTick - uPrevPauseTick > uPleGap)
+            *puFirstPauseLoopTick = uTick;
+        else if (uTick - *puFirstPauseLoopTick > uPleWindow)
+            fIntercept = true;
+    }
+
+    if (fIntercept)
+    {
+        VMXVEXITINFO ExitInfo;
+        RT_ZERO(ExitInfo);
+        ExitInfo.uReason = VMX_EXIT_PAUSE;
+        ExitInfo.cbInstr = cbInstr;
+        return iemVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
+    }
+
+    return VINF_VMX_INTERCEPT_NOT_ACTIVE;
+}
+
+
+/**
  * VMX VM-exit handler for VM-exits due to task switches.
  *
@@ -3715,23 +3789,4 @@
 
     return VINF_VMX_INTERCEPT_NOT_ACTIVE;
-}
-
-
-/**
- * VMX VM-exit handler for VM-exits due to MWAIT instruction.
- *
- * @returns VBox strict status code.
- * @param   pVCpu               The cross context virtual CPU structure.
- * @param   fMonitorHwArmed     Whether the address-range monitor hardware is armed.
- * @param   cbInstr             The instruction length in bytes.
- */
-IEM_STATIC VBOXSTRICTRC iemVmxVmexitInstrMwait(PVMCPU pVCpu, bool fMonitorHwArmed, uint8_t cbInstr)
-{
-    VMXVEXITINFO ExitInfo;
-    RT_ZERO(ExitInfo);
-    ExitInfo.uReason = VMX_EXIT_MWAIT;
-    ExitInfo.cbInstr = cbInstr;
-    ExitInfo.u64Qual = fMonitorHwArmed;
-    return iemVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
 }
 
@@ -7051,4 +7106,25 @@
 }
 
+
+/**
+ * Implements VMX's implementation of PAUSE.
+ */
+IEM_CIMPL_DEF_0(iemCImpl_vmx_pause)
+{
+    if (IEM_VMX_IS_NON_ROOT_MODE(pVCpu))
+    {
+        VBOXSTRICTRC rcStrict = iemVmxVmexitInstrPause(pVCpu, cbInstr);
+        if (rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE)
+            return rcStrict;
+    }
+
+    /*
+     * Outside VMX non-root operation or if the PAUSE instruction does not cause
+     * a VM-exit, the instruction operates normally.
+     */
+    iemRegAddToRipAndClearRF(pVCpu, cbInstr);
+    return VINF_SUCCESS;
+}
+
 #endif  /* VBOX_WITH_NESTED_HWVIRT_VMX */
 
Index: /trunk/src/VBox/VMM/VMMAll/IEMAllInstructionsOneByte.cpp.h
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/IEMAllInstructionsOneByte.cpp.h	(revision 74752)
+++ /trunk/src/VBox/VMM/VMMAll/IEMAllInstructionsOneByte.cpp.h	(revision 74753)
@@ -4455,4 +4455,8 @@
     {
         IEMOP_MNEMONIC(pause, "pause");
+#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
+        if (IEM_GET_GUEST_CPU_FEATURES(pVCpu)->fVmx)
+            return IEM_MC_DEFER_TO_CIMPL_0(iemCImpl_vmx_pause);
+#endif
 #ifdef VBOX_WITH_NESTED_HWVIRT_SVM
         if (IEM_GET_GUEST_CPU_FEATURES(pVCpu)->fSvm)
Index: /trunk/src/VBox/VMM/VMMR3/CPUM.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR3/CPUM.cpp	(revision 74752)
+++ /trunk/src/VBox/VMM/VMMR3/CPUM.cpp	(revision 74753)
@@ -3189,4 +3189,6 @@
         pHlp->pfnPrintf(pHlp, "  fInVmxNonRootMode          = %RTbool\n",   pCtx->hwvirt.vmx.fInVmxNonRootMode);
         pHlp->pfnPrintf(pHlp, "  fInterceptEvents           = %RTbool\n",   pCtx->hwvirt.vmx.fInterceptEvents);
+        pHlp->pfnPrintf(pHlp, "  uFirstPauseLoopTick        = %RX64\n",     pCtx->hwvirt.vmx.uFirstPauseLoopTick);
+        pHlp->pfnPrintf(pHlp, "  uPrevPauseTick             = %RX64\n",     pCtx->hwvirt.vmx.uPrevPauseTick);
 
         /** @todo NSTVMX: Dump remaining/new fields. */
