Index: /trunk/src/VBox/VMM/HWACCM.cpp
===================================================================
--- /trunk/src/VBox/VMM/HWACCM.cpp	(revision 22240)
+++ /trunk/src/VBox/VMM/HWACCM.cpp	(revision 22241)
@@ -507,5 +507,7 @@
         HWACCM_REG_COUNTER(&pVCpu->hwaccm.s.StatTSCOffset,              "/HWACCM/CPU%d/TSC/Offset");
         HWACCM_REG_COUNTER(&pVCpu->hwaccm.s.StatTSCIntercept,           "/HWACCM/CPU%d/TSC/Intercept");
-
+        HWACCM_REG_COUNTER(&pVCpu->hwaccm.s.StatTSCInterceptOverFlow,   "/HWACCM/CPU%d/TSC/InterceptOverflow");
+        HWACCM_REG_COUNTER(&pVCpu->hwaccm.s.StatTSCOverFlow,            "/HWACCM/CPU%d/TSC/Overflow");
+        
         HWACCM_REG_COUNTER(&pVCpu->hwaccm.s.StatDRxArmed,               "/HWACCM/CPU%d/Debug/Armed");
         HWACCM_REG_COUNTER(&pVCpu->hwaccm.s.StatDRxContextSwitch,       "/HWACCM/CPU%d/Debug/ContextSwitch");
Index: /trunk/src/VBox/VMM/HWACCMInternal.h
===================================================================
--- /trunk/src/VBox/VMM/HWACCMInternal.h	(revision 22240)
+++ /trunk/src/VBox/VMM/HWACCMInternal.h	(revision 22241)
@@ -556,4 +556,9 @@
     /* Current ASID in use by the VM */
     RTUINT                      uCurrentASID;
+
+    /* Last seen TSC by the guest when in offsetted mode. */
+    uint64_t                    u64LastTSC;
+    /* Last use TSC offset value. (cached) */
+    uint64_t                    u64TSCOffset;
 
     struct
@@ -814,4 +819,6 @@
     STAMCOUNTER             StatTSCOffset;
     STAMCOUNTER             StatTSCIntercept;
+    STAMCOUNTER             StatTSCOverFlow;
+    STAMCOUNTER             StatTSCInterceptOverFlow;
 
     STAMCOUNTER             StatExitReasonNPF;
Index: /trunk/src/VBox/VMM/VMMR0/HWVMXR0.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR0/HWVMXR0.cpp	(revision 22240)
+++ /trunk/src/VBox/VMM/VMMR0/HWVMXR0.cpp	(revision 22241)
@@ -1808,12 +1808,26 @@
     if (TMCpuTickCanUseRealTSC(pVCpu, &u64TSCOffset))
     {
-        /* Note: VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_RDTSC_EXIT takes precedence over TSC_OFFSET */
-        rc = VMXWriteVMCS64(VMX_VMCS_CTRL_TSC_OFFSET_FULL, u64TSCOffset);
-        AssertRC(rc);
-
-        pVCpu->hwaccm.s.vmx.proc_ctls &= ~VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_RDTSC_EXIT;
-        rc = VMXWriteVMCS(VMX_VMCS_CTRL_PROC_EXEC_CONTROLS, pVCpu->hwaccm.s.vmx.proc_ctls);
-        AssertRC(rc);
-        STAM_COUNTER_INC(&pVCpu->hwaccm.s.StatTSCOffset);
+        uint64_t u64CurTSC = ASMReadTSC();
+        pVCpu->hwaccm.s.u64TSCOffset = u64TSCOffset;
+        if (u64CurTSC + u64TSCOffset >= pVCpu->hwaccm.s.u64LastTSC)
+        {
+            /* Note: VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_RDTSC_EXIT takes precedence over TSC_OFFSET */
+            rc = VMXWriteVMCS64(VMX_VMCS_CTRL_TSC_OFFSET_FULL, u64TSCOffset);
+            AssertRC(rc);
+
+            pVCpu->hwaccm.s.vmx.proc_ctls &= ~VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_RDTSC_EXIT;
+            rc = VMXWriteVMCS(VMX_VMCS_CTRL_PROC_EXEC_CONTROLS, pVCpu->hwaccm.s.vmx.proc_ctls);
+            AssertRC(rc);
+            STAM_COUNTER_INC(&pVCpu->hwaccm.s.StatTSCOffset);
+        }
+        else
+        {
+            /* Fall back to rdtsc emulation as we would otherwise pass decreasing tsc values to the guest. */
+            Log(("TSC %RX64 offset %RX64 time=%RX64 last=%RX64 (diff=%RX64, virt_tsc=%RX64)\n", u64CurTSC, u64TSCOffset, u64CurTSC + u64TSCOffset, pVCpu->hwaccm.s.u64LastTSC, pVCpu->hwaccm.s.u64LastTSC - u64CurTSC - u64TSCOffset, TMCpuTickGet(pVCpu)));
+            pVCpu->hwaccm.s.vmx.proc_ctls |= VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_RDTSC_EXIT;
+            rc = VMXWriteVMCS(VMX_VMCS_CTRL_PROC_EXEC_CONTROLS, pVCpu->hwaccm.s.vmx.proc_ctls);
+            AssertRC(rc);
+            STAM_COUNTER_INC(&pVCpu->hwaccm.s.StatTSCInterceptOverFlow);
+        }
     }
     else
@@ -2580,4 +2594,8 @@
     rc = pVCpu->hwaccm.s.vmx.pfnStartVM(pVCpu->hwaccm.s.fResumeVM, pCtx, &pVCpu->hwaccm.s.vmx.VMCSCache, pVM, pVCpu);
 #endif
+    /* Possibly the last TSC value seen by the guest (too high) (only when we're in tsc offset mode). */
+    if (!(pVCpu->hwaccm.s.vmx.proc_ctls & VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_RDTSC_EXIT))
+        pVCpu->hwaccm.s.u64LastTSC = ASMReadTSC() + pVCpu->hwaccm.s.u64TSCOffset - 0x1000 /* guestimate of world switch overhead */;
+
     TMNotifyEndOfExecution(pVCpu);
     VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STARTED);
@@ -3381,4 +3399,16 @@
         if (rc == VINF_SUCCESS)
         {
+            uint64_t u64CurrentTSC = (uint64_t)pCtx->edx << 32ULL;
+            u64CurrentTSC += pCtx->eax;
+
+            if (u64CurrentTSC < pVCpu->hwaccm.s.u64LastTSC)
+            {
+                STAM_COUNTER_INC(&pVCpu->hwaccm.s.StatTSCOverFlow);
+                Log(("invalid tsc %RX64 vs %RX64 (diff %RX64)\n", u64CurrentTSC, pVCpu->hwaccm.s.u64LastTSC, pVCpu->hwaccm.s.u64LastTSC - u64CurrentTSC));
+                pVCpu->hwaccm.s.u64LastTSC += 64;
+                pCtx->edx = (pVCpu->hwaccm.s.u64LastTSC >> 32ULL);
+                pCtx->eax = (pVCpu->hwaccm.s.u64LastTSC & 0xffffffff);
+            }
+
             /* Update EIP and continue execution. */
             Assert(cbInstr == 2);
