Index: /trunk/include/VBox/tm.h
===================================================================
--- /trunk/include/VBox/tm.h	(revision 442)
+++ /trunk/include/VBox/tm.h	(revision 443)
@@ -202,4 +202,21 @@
 TMDECL(uint64_t) TMVirtualFromMilli(PVM pVM, uint64_t u64MilliTS);
 
+/**
+ * Gets the current warp drive percent.
+ * 
+ * @returns The warp drive percent.
+ * @param   pVM         The VM handle.
+ */
+TMDECL(uint32_t) TMVirtualGetWarpDrive(PVM pVM);
+
+/**
+ * Sets the warp drive percent of the virtual time.
+ * 
+ * @returns VBox status code.
+ * @param   pVM         The VM handle.
+ * @param   u32Percent  The new percentage. 100 means normal operation.
+ */
+TMDECL(int) TMVirtualSetWarpDrive(PVM pVM, uint32_t u32Percent);
+
 /** @} */
 
Index: /trunk/src/VBox/VMM/TM.cpp
===================================================================
--- /trunk/src/VBox/VMM/TM.cpp	(revision 442)
+++ /trunk/src/VBox/VMM/TM.cpp	(revision 443)
@@ -193,5 +193,23 @@
 
     /*
-     * Start the timer.
+     * Setup the warp drive.
+     */
+    rc = CFGMR3QueryU32(CFGMR3GetRoot(pVM), "WarpDrivePercentage", &pVM->tm.s.u32VirtualWarpDrivePercentage);
+    if (rc == VERR_CFGM_VALUE_NOT_FOUND)
+        pVM->tm.s.u32VirtualWarpDrivePercentage = 100;
+    else if (VBOX_FAILURE(rc))
+        return VMSetError(pVM, rc, RT_SRC_POS, 
+                          N_("Configuration error: Failed to querying uint32_t value \"WarpDrivePercent\". (%Vrc)"), rc); 
+    else if (   pVM->tm.s.u32VirtualWarpDrivePercentage < 2 
+             || pVM->tm.s.u32VirtualWarpDrivePercentage > 20000)
+        return VMSetError(pVM, VERR_INVALID_PARAMETER, RT_SRC_POS, 
+                          N_("Configuration error: \"WarpDrivePercent\" = %RI32 is not in the range 2..20000!"),
+                          pVM->tm.s.u32VirtualWarpDrivePercentage);
+    pVM->tm.s.fVirtualWarpDrive = pVM->tm.s.u32VirtualWarpDrivePercentage != 100;
+    if (pVM->tm.s.fVirtualWarpDrive)
+        LogRel(("TM: u32VirtualWarpDrivePercentage=%RI32\n", pVM->tm.s.u32VirtualWarpDrivePercentage));
+
+    /*
+     * Start the timer (guard against REM not yielding).
      */
     uint32_t u32Millies;
@@ -200,8 +218,6 @@
         u32Millies = 10;
     else if (VBOX_FAILURE(rc))
-    {
-        AssertMsgFailed(("Configuration error: Failed to query uint32_t value \"TimerMillies\", rc=%Vrc.\n", rc));
-        return rc;
-    }
+        return VMSetError(pVM, rc, RT_SRC_POS, 
+                          N_("Configuration error: Failed to query uint32_t value \"TimerMillies\", rc=%Vrc.\n"), rc);
     rc = RTTimerCreate(&pVM->tm.s.pTimer, u32Millies, tmR3TimerCallback, pVM);
     if (VBOX_FAILURE(rc))
Index: /trunk/src/VBox/VMM/TMInternal.h
===================================================================
--- /trunk/src/VBox/VMM/TMInternal.h	(revision 442)
+++ /trunk/src/VBox/VMM/TMInternal.h	(revision 443)
@@ -297,12 +297,17 @@
     uint64_t                    cTSCTicksPerSecond;
 
-    /** Padding to ensure that 64-bit values are equaly aligned everywhere. */
-    uint32_t                    uReserved;
     /** Virtual time ticking enabled indicator (bool). (TMCLOCK_VIRTUAL) */
     bool                        fVirtualTicking;
+    /** Virtual time is not running at 100%. */
+    bool                        fVirtualWarpDrive;
     /** Virtual timer synchronous time ticking enabled indicator (bool). (TMCLOCK_VIRTUAL_SYNC) */
     bool                        fVirtualSyncTicking;
     /** Virtual timer synchronous time catch-up active. */
     bool volatile               fVirtualSyncCatchUp;
+    /** WarpDrive percentage. 
+     * 100% is normal (fVirtualSyncNormal == true). When other than 100% we apply 
+     * this percentage to the raw time source for the period it's been valid in, 
+     * i.e. since u64VirtualWarpDriveStart. */
+    uint32_t                    u32VirtualWarpDrivePercentage;
 
     /** The offset of the virtual clock relative to it's timesource.
@@ -311,4 +316,7 @@
     /** The guest virtual time when fVirtualTicking is cleared. */
     uint64_t                    u64Virtual;
+    /** When the Warp drive was started or last adjusted.
+     * Only valid when fVirtualWarpDrive is set. */
+    uint64_t                    u64VirtualWarpDriveStart;
 
     /** The offset of the virtual timer synchronous clock (TMCLOCK_VIRTUAL_SYNC) relative
@@ -319,6 +327,6 @@
     /** The guest virtual timer synchronous time when fVirtualSyncTicking is cleared. */
     uint64_t                    u64VirtualSync;
-    /** How many precent faster the clock should advance when catch-up is active. */
-    uint32_t                    u32VirtualSyncCatchupPrecentage;
+    /** How many percent faster the clock should advance when catch-up is active. */
+    uint32_t                    u32VirtualSyncCatchupPercentage;
     /** When to stop catch-up. */
     uint32_t                    u32VirtualSyncCatchupStopThreashold;
Index: /trunk/src/VBox/VMM/VMMAll/TMAllVirtual.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/TMAllVirtual.cpp	(revision 442)
+++ /trunk/src/VBox/VMM/VMMAll/TMAllVirtual.cpp	(revision 443)
@@ -40,4 +40,51 @@
 
 
+/*******************************************************************************
+*   Internal Functions                                                         *
+*******************************************************************************/
+static DECLCALLBACK(int) tmVirtualSetWarpDrive(PVM pVM, uint32_t u32Percent);
+
+
+
+/**
+ * Get the time when we're not running at 100%
+ * 
+ * @returns The timestamp.
+ * @param   pVM     The VM handle.
+ */
+uint64_t tmVirtualGetRawNonNormal(PVM pVM)
+{
+    /* 
+     * Recalculate the RTTimeNanoTS() value for the period where 
+     * warp drive has been enabled.
+     */
+    uint64_t u64 = RTTimeNanoTS();
+    u64 -= pVM->tm.s.u64VirtualWarpDriveStart;
+    u64 *= pVM->tm.s.u32VirtualWarpDrivePercentage;
+    u64 /= 100;
+    u64 += pVM->tm.s.u64VirtualWarpDriveStart;
+
+    /* 
+     * Now we apply the virtual time offset. 
+     * (Which is the negate RTTimeNanoTS() value for when the virtual machine 
+     * started if it had been running continuously without any suspends.)
+     */
+    u64 -= pVM->tm.s.u64VirtualOffset;
+    return u64;
+}
+
+
+/**
+ * Get the raw virtual time.
+ * 
+ * @returns The current time stamp. 
+ * @param   pVM     The VM handle.
+ */
+DECLINLINE(uint64_t) tmVirtualGetRaw(PVM pVM)
+{
+    if (RT_LIKELY(!pVM->tm.s.fVirtualWarpDrive))
+        return RTTimeNanoTS() - pVM->tm.s.u64VirtualOffset;
+    return tmVirtualGetRawNonNormal(pVM);
+}
 
 
@@ -59,5 +106,5 @@
     {
         STAM_COUNTER_INC(&pVM->tm.s.StatVirtualGet);
-        u64 = RTTimeNanoTS() - pVM->tm.s.u64VirtualOffset;
+        u64 = tmVirtualGetRaw(pVM);
 
         /*
@@ -102,5 +149,5 @@
          */
         Assert(pVM->tm.s.fVirtualTicking);
-        u64 = RTTimeNanoTS() - pVM->tm.s.u64VirtualOffset;
+        u64 = tmVirtualGetRaw(pVM);
         if (    !VM_FF_ISSET(pVM, VM_FF_TIMER)
             &&  pVM->tm.s.CTXALLSUFF(paTimerQueues)[TMCLOCK_VIRTUAL].u64Expire <= u64)
@@ -145,5 +192,5 @@
             if (!(u64Delta >> 32))
             {
-                uint32_t u32Sub = ASMDivU64ByU32RetU32(ASMMult2xU32RetU64((uint32_t)u64Delta, pVM->tm.s.u32VirtualSyncCatchupPrecentage),
+                uint32_t u32Sub = ASMDivU64ByU32RetU32(ASMMult2xU32RetU64((uint32_t)u64Delta, pVM->tm.s.u32VirtualSyncCatchupPercentage),
                                                        100);
                 if (u32Sub < (uint32_t)u64Delta)
@@ -223,5 +270,6 @@
     {
         STAM_COUNTER_INC(&pVM->tm.s.StatVirtualResume);
-        pVM->tm.s.u64VirtualOffset = RTTimeNanoTS() - pVM->tm.s.u64Virtual;
+        pVM->tm.s.u64VirtualWarpDriveStart = RTTimeNanoTS();
+        pVM->tm.s.u64VirtualOffset = pVM->tm.s.u64VirtualWarpDriveStart - pVM->tm.s.u64Virtual;
         pVM->tm.s.fVirtualTicking = true;
         pVM->tm.s.fVirtualSyncTicking = true;
@@ -251,5 +299,5 @@
 #ifndef TM_CONTINUOUS_TIME
         STAM_COUNTER_INC(&pVM->tm.s.StatVirtualPause);
-        pVM->tm.s.u64Virtual = RTTimeNanoTS() - pVM->tm.s.u64VirtualOffset;
+        pVM->tm.s.u64Virtual = tmVirtualGetRaw(pVM);
         pVM->tm.s.fVirtualSyncTicking = false;
         pVM->tm.s.fVirtualTicking = false;
@@ -260,4 +308,82 @@
     AssertFailed();
     return VERR_INTERNAL_ERROR;
+}
+
+
+/**
+ * Gets the current warp drive percent.
+ * 
+ * @returns The warp drive percent.
+ * @param   pVM         The VM handle.
+ */
+TMDECL(uint32_t) TMVirtualGetWarpDrive(PVM pVM)
+{
+    return pVM->tm.s.u32VirtualWarpDrivePercentage;
+}
+
+
+/**
+ * Sets the warp drive percent of the virtual time.
+ * 
+ * @returns VBox status code.
+ * @param   pVM         The VM handle.
+ * @param   u32Percent  The new percentage. 100 means normal operation.
+ */
+TMDECL(int) TMVirtualSetWarpDrive(PVM pVM, uint32_t u32Percent)
+{
+#ifdef IN_RING3
+    PVMREQ pReq;
+    int rc = VMR3ReqCall(pVM, &pReq, RT_INDEFINITE_WAIT, (PFNRT)tmVirtualSetWarpDrive, 2, pVM, u32Percent);
+    if (VBOX_SUCCESS(rc))
+        rc = pReq->iStatus;
+    VMR3ReqFree(pReq);
+    return rc;
+#else
+
+    return tmVirtualSetWarpDrive(pVM, u32Percent);
+#endif 
+}
+
+
+/**
+ * EMT worker for tmVirtualSetWarpDrive.
+ * 
+ * @returns VBox status code.
+ * @param   pVM         The VM handle.
+ * @param   u32Percent  See TMVirtualSetWarpDrive().
+ * @internal
+ */
+static DECLCALLBACK(int) tmVirtualSetWarpDrive(PVM pVM, uint32_t u32Percent)
+{
+    /*
+     * Validate it.
+     */
+    AssertMsgReturn(u32Percent >= 2 && u32Percent <= 20000, 
+                    ("%RX32 is not between 2 and 20000 (inclusive).\n", u32Percent), 
+                    VERR_INVALID_PARAMETER);
+
+    /* 
+     * If the time is running we'll have to pause it before we can change
+     * the warp drive settings.
+     */
+    bool fPaused = pVM->tm.s.fVirtualTicking;
+    if (fPaused)
+    {
+        int rc = TMVirtualPause(pVM);
+        AssertRCReturn(rc, rc);
+    }
+
+    pVM->tm.s.u32VirtualWarpDrivePercentage = u32Percent;
+    pVM->tm.s.fVirtualWarpDrive = u32Percent != 100;
+    LogRel(("TM: u32VirtualWarpDrivePercentage=%RI32 fVirtualWarpDrive=%RTbool\n", 
+            pVM->tm.s.u32VirtualWarpDrivePercentage, pVM->tm.s.fVirtualWarpDrive));
+
+    if (fPaused)
+    {
+        int rc = TMVirtualResume(pVM);
+        AssertRCReturn(rc, rc);
+    }
+
+    return VINF_SUCCESS;
 }
 
Index: /trunk/src/VBox/VMM/testcase/tstVMStructGC.cpp
===================================================================
--- /trunk/src/VBox/VMM/testcase/tstVMStructGC.cpp	(revision 442)
+++ /trunk/src/VBox/VMM/testcase/tstVMStructGC.cpp	(revision 443)
@@ -408,10 +408,12 @@
     GEN_CHECK_OFF(TM, u64TSC);
     GEN_CHECK_OFF(TM, cTSCTicksPerSecond);
-    GEN_CHECK_OFF(TM, uReserved);
     GEN_CHECK_OFF(TM, fVirtualTicking);
+    GEN_CHECK_OFF(TM, fVirtualWarpDrive);
+    GEN_CHECK_OFF(TM, u32VirtualWarpDrivePercentage);
     GEN_CHECK_OFF(TM, u64VirtualOffset);
     GEN_CHECK_OFF(TM, u64Virtual);
+    GEN_CHECK_OFF(TM, u64VirtualWarpDriveStart);
     GEN_CHECK_OFF(TM, u64VirtualSync);
-    GEN_CHECK_OFF(TM, u32VirtualSyncCatchupPrecentage);
+    GEN_CHECK_OFF(TM, u32VirtualSyncCatchupPercentage);
     GEN_CHECK_OFF(TM, u32VirtualSyncCatchupStopThreashold);
     GEN_CHECK_OFF(TM, u64VirtualSyncCatchupStartTreashold);
