Index: /trunk/include/VBox/iom.h
===================================================================
--- /trunk/include/VBox/iom.h	(revision 20086)
+++ /trunk/include/VBox/iom.h	(revision 20087)
@@ -269,4 +269,5 @@
 
 VMMR3DECL(void) IOMR3ReleaseOwnedLocks(PVM pVM);
+VMMR3DECL(PPDMCRITSECT) IOMR3GetCritSect(PVM pVM);
 
 /** @} */
Index: /trunk/include/VBox/pdmcritsect.h
===================================================================
--- /trunk/include/VBox/pdmcritsect.h	(revision 20086)
+++ /trunk/include/VBox/pdmcritsect.h	(revision 20087)
@@ -54,8 +54,4 @@
 #endif
 } PDMCRITSECT;
-/** Pointer to a PDM critical section. */
-typedef PDMCRITSECT *PPDMCRITSECT;
-/** Pointer to a const PDM critical section. */
-typedef const PDMCRITSECT *PCPDMCRITSECT;
 
 VMMR3DECL(int)      PDMR3CritSectInit(PVM pVM, PPDMCRITSECT pCritSect, const char *pszName);
@@ -69,4 +65,5 @@
 VMMDECL(bool)       PDMCritSectIsInitialized(PCPDMCRITSECT pCritSect);
 VMMDECL(uint32_t)   PDMCritSectGetRecursion(PCPDMCRITSECT pCritSect);
+VMMR3DECL(const char *) PDMR3CritSectName(PCPDMCRITSECT pCritSect);
 VMMR3DECL(int)      PDMR3CritSectScheduleExitEvent(PPDMCRITSECT pCritSect, RTSEMEVENT EventToSignal);
 VMMR3DECL(int)      PDMR3CritSectDelete(PPDMCRITSECT pCritSect);
Index: /trunk/include/VBox/pdmdev.h
===================================================================
--- /trunk/include/VBox/pdmdev.h	(revision 20086)
+++ /trunk/include/VBox/pdmdev.h	(revision 20087)
@@ -1303,7 +1303,7 @@
      */
     DECLR3CALLBACKMEMBER(void,    pfnSendSipi,(PPDMDEVINS pDevIns, VMCPUID idCpu, uint32_t uVector));
-    
-    /**
-     * Sends init IPI to given virtual CPU, should result in reset and 
+
+    /**
+     * Sends init IPI to given virtual CPU, should result in reset and
      * halting till SIPI.
      *
@@ -1951,9 +1951,11 @@
      * @param   enmClock            The clock to use on this timer.
      * @param   pfnCallback         Callback function.
+     * @param   pvUser              User argument for the callback.
+     * @param   fFlags              Flags, see TMTIMER_FLAGS_*.
      * @param   pszDesc             Pointer to description string which must stay around
      *                              until the timer is fully destroyed (i.e. a bit after TMTimerDestroy()).
      * @param   ppTimer             Where to store the timer on success.
      */
-    DECLR3CALLBACKMEMBER(int, pfnTMTimerCreate,(PPDMDEVINS pDevIns, TMCLOCK enmClock, PFNTMTIMERDEV pfnCallback, const char *pszDesc, PPTMTIMERR3 ppTimer));
+    DECLR3CALLBACKMEMBER(int, pfnTMTimerCreate,(PPDMDEVINS pDevIns, TMCLOCK enmClock, PFNTMTIMERDEV pfnCallback, void *pvUser, uint32_t fFlags, const char *pszDesc, PPTMTIMERR3 ppTimer));
 
     /**
@@ -3463,7 +3465,8 @@
  * @copydoc PDMDEVHLPR3::pfnTMTimerCreate
  */
-DECLINLINE(int) PDMDevHlpTMTimerCreate(PPDMDEVINS pDevIns, TMCLOCK enmClock, PFNTMTIMERDEV pfnCallback, const char *pszDesc, PPTMTIMERR3 ppTimer)
-{
-    return pDevIns->pDevHlpR3->pfnTMTimerCreate(pDevIns, enmClock, pfnCallback, pszDesc, ppTimer);
+DECLINLINE(int) PDMDevHlpTMTimerCreate(PPDMDEVINS pDevIns, TMCLOCK enmClock, PFNTMTIMERDEV pfnCallback, void *pvUser, uint32_t fFlags,
+                                       const char *pszDesc, PPTMTIMERR3 ppTimer)
+{
+    return pDevIns->pDevHlpR3->pfnTMTimerCreate(pDevIns, enmClock, pfnCallback, pvUser, fFlags, pszDesc, ppTimer);
 }
 
Index: /trunk/include/VBox/tm.h
===================================================================
--- /trunk/include/VBox/tm.h	(revision 20086)
+++ /trunk/include/VBox/tm.h	(revision 20087)
@@ -73,4 +73,15 @@
 
 
+/** @defgroup grp_tm_timer_flags Timer flags.
+ * @{ */
+/** Use the default critical section for the class of timers.
+ * Only devices have one at the moment. */
+#define TMTIMER_FLAGS_DEFAULT_CRIT_SECT 0
+/** No critical section needed or a custom one is set using
+ *  TMR3TimerSetCritSect(). */
+#define TMTIMER_FLAGS_NO_CRIT_SECT      RT_BIT_32(0)
+/** @} */
+
+
 VMMDECL(void)     TMNotifyStartOfExecution(PVMCPU pVCpu);
 VMMDECL(void)     TMNotifyEndOfExecution(PVMCPU pVCpu);
@@ -132,6 +143,7 @@
  * @param   pDevIns         Device instance of the device which registered the timer.
  * @param   pTimer          The timer handle.
- */
-typedef DECLCALLBACK(void) FNTMTIMERDEV(PPDMDEVINS pDevIns, PTMTIMER pTimer);
+ * @param   pvUser          User argument specified upon timer creation.
+ */
+typedef DECLCALLBACK(void) FNTMTIMERDEV(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser);
 /** Pointer to a device timer callback function. */
 typedef FNTMTIMERDEV *PFNTMTIMERDEV;
@@ -218,5 +230,5 @@
 VMMR3DECL(void)   TMR3Reset(PVM pVM);
 VMMR3DECL(int)    TMR3GetImportRC(PVM pVM, const char *pszSymbol, PRTRCPTR pRCPtrValue);
-VMMR3DECL(int)    TMR3TimerCreateDevice(PVM pVM, PPDMDEVINS pDevIns, TMCLOCK enmClock, PFNTMTIMERDEV pfnCallback, const char *pszDesc, PPTMTIMERR3 ppTimer);
+VMMR3DECL(int)    TMR3TimerCreateDevice(PVM pVM, PPDMDEVINS pDevIns, TMCLOCK enmClock, PFNTMTIMERDEV pfnCallback, void *pvUser, uint32_t fFlags, const char *pszDesc, PPTMTIMERR3 ppTimer);
 VMMR3DECL(int)    TMR3TimerCreateDriver(PVM pVM, PPDMDRVINS pDrvIns, TMCLOCK enmClock, PFNTMTIMERDRV pfnCallback, const char *pszDesc, PPTMTIMERR3 ppTimer);
 VMMR3DECL(int)    TMR3TimerCreateInternal(PVM pVM, TMCLOCK enmClock, PFNTMTIMERINT pfnCallback, void *pvUser, const char *pszDesc, PPTMTIMERR3 ppTimer);
@@ -227,4 +239,5 @@
 VMMR3DECL(int)    TMR3TimerSave(PTMTIMERR3 pTimer, PSSMHANDLE pSSM);
 VMMR3DECL(int)    TMR3TimerLoad(PTMTIMERR3 pTimer, PSSMHANDLE pSSM);
+VMMR3DECL(int)    TMR3TimerSetCritSect(PTMTIMERR3 pTimer, PPDMCRITSECT pCritSect);
 VMMR3DECL(void)   TMR3TimerQueuesDo(PVM pVM);
 VMMR3DECL(void)   TMR3VirtualSyncFF(PVM pVM, PVMCPU pVCpu);
Index: /trunk/include/VBox/types.h
===================================================================
--- /trunk/include/VBox/types.h	(revision 20086)
+++ /trunk/include/VBox/types.h	(revision 20087)
@@ -203,4 +203,9 @@
 /** Pointer to a pointer to a PDM Service Instance. */
 typedef PPDMSRVINS *PPPDMSRVINS;
+
+/** Pointer to a PDM critical section. */
+typedef union PDMCRITSECT *PPDMCRITSECT;
+/** Pointer to a const PDM critical section. */
+typedef const union PDMCRITSECT *PCPDMCRITSECT;
 
 /** R3 pointer to a timer. */
Index: /trunk/include/VBox/vusb.h
===================================================================
--- /trunk/include/VBox/vusb.h	(revision 20086)
+++ /trunk/include/VBox/vusb.h	(revision 20087)
@@ -779,4 +779,5 @@
 /**
  * USB Timer Interface.
+ * @todo r=bird: why is this code still here?
  */
 typedef struct VUSBITIMER
Index: /trunk/src/VBox/Devices/Audio/DevSB16.cpp
===================================================================
--- /trunk/src/VBox/Devices/Audio/DevSB16.cpp	(revision 20086)
+++ /trunk/src/VBox/Devices/Audio/DevSB16.cpp	(revision 20087)
@@ -280,7 +280,7 @@
 }
 #else  /* VBOX */
-static DECLCALLBACK(void) sb16Timer(PPDMDEVINS pDevIns, PTMTIMER pTimer)
-{
-    SB16State *s = PDMINS_2_DATA(pDevIns, SB16State *);
+static DECLCALLBACK(void) sb16Timer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvThis)
+{
+    SB16State *s = (SB16State *)pvThis;
     s->can_write = 1;
     PDMDevHlpISASetIrq(s->pDevIns, s->irq, 1);
@@ -1795,5 +1795,6 @@
      * Create timer, register & attach stuff.
      */
-    rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL, sb16Timer, "SB16 timer", &s->pTimer);
+    rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL, sb16Timer, s,
+                                TMTIMER_FLAGS_DEFAULT_CRIT_SECT, "SB16 timer", &s->pTimer);
     if (RT_FAILURE(rc))
         AssertMsgFailedReturn(("pfnTMTimerCreate -> %Rrc\n", rc), rc);
Index: /trunk/src/VBox/Devices/Graphics/DevVGA.cpp
===================================================================
--- /trunk/src/VBox/Devices/Graphics/DevVGA.cpp	(revision 20086)
+++ /trunk/src/VBox/Devices/Graphics/DevVGA.cpp	(revision 20087)
@@ -5071,7 +5071,7 @@
 
 
-static DECLCALLBACK(void) vgaTimerRefresh(PPDMDEVINS pDevIns, PTMTIMER pTimer)
-{
-    PVGASTATE pThis = PDMINS_2_DATA(pDevIns, PVGASTATE);
+static DECLCALLBACK(void) vgaTimerRefresh(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
+{
+    PVGASTATE pThis = (PVGASTATE)pvUser;
 
     if (pThis->pDrv)
@@ -5783,5 +5783,7 @@
      * Create the refresh timer.
      */
-    rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_REAL, vgaTimerRefresh, "VGA Refresh Timer", &pThis->RefreshTimer);
+    rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_REAL, vgaTimerRefresh,
+                                pThis, TMTIMER_FLAGS_DEFAULT_CRIT_SECT, /** @todo This needs to be fixed! We cannot take the I/O lock at this point! */
+                                "VGA Refresh Timer", &pThis->RefreshTimer);
     if (RT_FAILURE(rc))
         return rc;
Index: /trunk/src/VBox/Devices/Network/DevE1000.cpp
===================================================================
--- /trunk/src/VBox/Devices/Network/DevE1000.cpp	(revision 20086)
+++ /trunk/src/VBox/Devices/Network/DevE1000.cpp	(revision 20087)
@@ -2466,9 +2466,10 @@
  * @param   pDevIns     Pointer to device instance structure.
  * @param   pTimer      Pointer to the timer.
- * @thread  EMT
- */
-static DECLCALLBACK(void) e1kTxIntDelayTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer)
-{
-    E1KSTATE *pState = PDMINS_2_DATA(pDevIns, E1KSTATE *);
+ * @param   pvUser      NULL.
+ * @thread  EMT
+ */
+static DECLCALLBACK(void) e1kTxIntDelayTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
+{
+    E1KSTATE *pState = (E1KSTATE *)pvUser;
 
     if (RT_LIKELY(e1kMutexAcquire(pState, VERR_SEM_BUSY, RT_SRC_POS) == VINF_SUCCESS))
@@ -2491,9 +2492,10 @@
  * @param   pDevIns     Pointer to device instance structure.
  * @param   pTimer      Pointer to the timer.
- * @thread  EMT
- */
-static DECLCALLBACK(void) e1kTxAbsDelayTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer)
-{
-    E1KSTATE *pState = PDMINS_2_DATA(pDevIns, E1KSTATE *);
+ * @param   pvUser      NULL.
+ * @thread  EMT
+ */
+static DECLCALLBACK(void) e1kTxAbsDelayTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
+{
+    E1KSTATE *pState = (E1KSTATE *)pvUser;
 
     if (RT_LIKELY(e1kMutexAcquire(pState, VERR_SEM_BUSY, RT_SRC_POS) == VINF_SUCCESS))
@@ -2516,9 +2518,10 @@
  * @param   pDevIns     Pointer to device instance structure.
  * @param   pTimer      Pointer to the timer.
- * @thread  EMT
- */
-static DECLCALLBACK(void) e1kRxIntDelayTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer)
-{
-    E1KSTATE *pState = PDMINS_2_DATA(pDevIns, E1KSTATE *);
+ * @param   pvUser      NULL.
+ * @thread  EMT
+ */
+static DECLCALLBACK(void) e1kRxIntDelayTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
+{
+    E1KSTATE *pState = (E1KSTATE *)pvUser;
 
     if (RT_LIKELY(e1kMutexAcquire(pState, VERR_SEM_BUSY, RT_SRC_POS) == VINF_SUCCESS))
@@ -2539,9 +2542,10 @@
  * @param   pDevIns     Pointer to device instance structure.
  * @param   pTimer      Pointer to the timer.
- * @thread  EMT
- */
-static DECLCALLBACK(void) e1kRxAbsDelayTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer)
-{
-    E1KSTATE *pState = PDMINS_2_DATA(pDevIns, E1KSTATE *);
+ * @param   pvUser      NULL.
+ * @thread  EMT
+ */
+static DECLCALLBACK(void) e1kRxAbsDelayTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
+{
+    E1KSTATE *pState = (E1KSTATE *)pvUser;
 
     if (RT_LIKELY(e1kMutexAcquire(pState, VERR_SEM_BUSY, RT_SRC_POS) == VINF_SUCCESS))
@@ -2561,9 +2565,10 @@
  * @param   pDevIns     Pointer to device instance structure.
  * @param   pTimer      Pointer to the timer.
- * @thread  EMT
- */
-static DECLCALLBACK(void) e1kLateIntTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer)
-{
-    E1KSTATE *pState = PDMINS_2_DATA(pDevIns, E1KSTATE *);
+ * @param   pvUser      NULL.
+ * @thread  EMT
+ */
+static DECLCALLBACK(void) e1kLateIntTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
+{
+    E1KSTATE *pState = (E1KSTATE *)pvUser;
 
     STAM_PROFILE_ADV_START(&pState->StatLateIntTimer, a);
@@ -2587,9 +2592,10 @@
  * @param   pDevIns     Pointer to device instance structure.
  * @param   pTimer      Pointer to the timer.
- * @thread  EMT
- */
-static DECLCALLBACK(void) e1kLinkUpTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer)
-{
-    E1KSTATE *pState = PDMINS_2_DATA(pDevIns, E1KSTATE *);
+ * @param   pvUser      NULL.
+ * @thread  EMT
+ */
+static DECLCALLBACK(void) e1kLinkUpTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
+{
+    E1KSTATE *pState = (E1KSTATE *)pvUser;
 
     if (RT_LIKELY(e1kMutexAcquire(pState, VERR_SEM_BUSY, RT_SRC_POS) == VINF_SUCCESS))
@@ -4812,5 +4818,6 @@
 #ifdef E1K_USE_TX_TIMERS
     /* Create Transmit Interrupt Delay Timer */
-    rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL, e1kTxIntDelayTimer,
+    rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL, e1kTxIntDelayTimer, pState,
+                                TMTIMER_FLAGS_DEFAULT_CRIT_SECT, /** @todo check locking here. */
                                 "E1000 Transmit Interrupt Delay Timer", &pState->pTIDTimerR3);
     if (RT_FAILURE(rc))
@@ -4821,5 +4828,6 @@
 # ifndef E1K_NO_TAD
     /* Create Transmit Absolute Delay Timer */
-    rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL, e1kTxAbsDelayTimer,
+    rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL, e1kTxAbsDelayTimer, pState,
+                                TMTIMER_FLAGS_DEFAULT_CRIT_SECT, /** @todo check locking here. */
                                 "E1000 Transmit Absolute Delay Timer", &pState->pTADTimerR3);
     if (RT_FAILURE(rc))
@@ -4832,5 +4840,6 @@
 #ifdef E1K_USE_RX_TIMERS
     /* Create Receive Interrupt Delay Timer */
-    rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL, e1kRxIntDelayTimer,
+    rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL, e1kRxIntDelayTimer, pState,
+                                TMTIMER_FLAGS_DEFAULT_CRIT_SECT, /** @todo check locking here. */
                                 "E1000 Receive Interrupt Delay Timer", &pState->pRIDTimerR3);
     if (RT_FAILURE(rc))
@@ -4840,5 +4849,6 @@
 
     /* Create Receive Absolute Delay Timer */
-    rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL, e1kRxAbsDelayTimer,
+    rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL, e1kRxAbsDelayTimer, pState,
+                                TMTIMER_FLAGS_DEFAULT_CRIT_SECT, /** @todo check locking here. */
                                 "E1000 Receive Absolute Delay Timer", &pState->pRADTimerR3);
     if (RT_FAILURE(rc))
@@ -4849,5 +4859,6 @@
 
     /* Create Late Interrupt Timer */
-    rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL, e1kLateIntTimer,
+    rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL, e1kLateIntTimer, pState,
+                                TMTIMER_FLAGS_DEFAULT_CRIT_SECT, /** @todo check locking here. */
                                 "E1000 Late Interrupt Timer", &pState->pIntTimerR3);
     if (RT_FAILURE(rc))
@@ -4857,5 +4868,6 @@
 
     /* Create Link Up Timer */
-    rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL, e1kLinkUpTimer,
+    rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL, e1kLinkUpTimer, pState,
+                                TMTIMER_FLAGS_DEFAULT_CRIT_SECT, /** @todo check locking here. */
                                 "E1000 Link Up Timer", &pState->pLUTimer);
     if (RT_FAILURE(rc))
Index: /trunk/src/VBox/Devices/Network/DevINIP.cpp
===================================================================
--- /trunk/src/VBox/Devices/Network/DevINIP.cpp	(revision 20086)
+++ /trunk/src/VBox/Devices/Network/DevINIP.cpp	(revision 20087)
@@ -146,7 +146,7 @@
  * @param   pTimer      Pointer to timer.
  */
-static DECLCALLBACK(void) devINIPARPTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer)
-{
-    PDEVINTNETIP pThis = PDMINS_2_DATA(pDevIns, PDEVINTNETIP);
+static DECLCALLBACK(void) devINIPARPTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
+{
+    PDEVINTNETIP pThis = (PDEVINTNETIP)pvUser;
     LogFlow(("%s: pDevIns=%p pTimer=%p\n", __FUNCTION__, pDevIns, pTimer));
     lwip_etharp_tmr();
@@ -161,7 +161,7 @@
  * @param   pTimer      Pointer to timer.
  */
-static DECLCALLBACK(void) devINIPTCPFastTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer)
-{
-    PDEVINTNETIP pThis = PDMINS_2_DATA(pDevIns, PDEVINTNETIP);
+static DECLCALLBACK(void) devINIPTCPFastTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
+{
+    PDEVINTNETIP pThis = (PDEVINTNETIP)pvUser;
     LogFlow(("%s: pDevIns=%p pTimer=%p\n", __FUNCTION__, pDevIns, pTimer));
     lwip_tcp_fasttmr();
@@ -176,7 +176,7 @@
  * @param   pTimer      Pointer to timer.
  */
-static DECLCALLBACK(void) devINIPTCPSlowTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer)
-{
-    PDEVINTNETIP pThis = PDMINS_2_DATA(pDevIns, PDEVINTNETIP);
+static DECLCALLBACK(void) devINIPTCPSlowTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
+{
+    PDEVINTNETIP pThis = (PDEVINTNETIP)pvUser;
     LogFlow(("%s: pDevIns=%p pTimer=%p\n", __FUNCTION__, pDevIns, pTimer));
     lwip_tcp_slowtmr();
@@ -590,12 +590,15 @@
     lwip_pbuf_init();
     lwip_netif_init();
-    rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL, devINIPARPTimer, "lwIP ARP", &pThis->ARPTimer);
-    if (RT_FAILURE(rc))
-        goto out;
-    rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL, devINIPTCPFastTimer, "lwIP fast TCP", &pThis->TCPFastTimer);
+    rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL, devINIPARPTimer, pThis,
+                                TMTIMER_FLAGS_NO_CRIT_SECT, "lwIP ARP", &pThis->ARPTimer);
+    if (RT_FAILURE(rc))
+        goto out;
+    rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL, devINIPTCPFastTimer, pThis,
+                                TMTIMER_FLAGS_NO_CRIT_SECT, "lwIP fast TCP", &pThis->TCPFastTimer);
     if (RT_FAILURE(rc))
         goto out;
     TMTimerSetMillies(pThis->TCPFastTimer, TCP_FAST_INTERVAL);
-    rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL, devINIPTCPSlowTimer, "lwIP slow TCP", &pThis->TCPSlowTimer);
+    rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL, devINIPTCPSlowTimer, pThis,
+                                TMTIMER_FLAGS_NO_CRIT_SECT, "lwIP slow TCP", &pThis->TCPSlowTimer);
     if (RT_FAILURE(rc))
         goto out;
Index: /trunk/src/VBox/Devices/Network/DevPCNet.cpp
===================================================================
--- /trunk/src/VBox/Devices/Network/DevPCNet.cpp	(revision 20086)
+++ /trunk/src/VBox/Devices/Network/DevPCNet.cpp	(revision 20087)
@@ -3802,16 +3802,9 @@
  * @thread  EMT
  */
-static DECLCALLBACK(void) pcnetTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer)
-{
-    PCNetState *pThis = PDMINS_2_DATA(pDevIns, PCNetState *);
-    int         rc;
-
+static DECLCALLBACK(void) pcnetTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
+{
+    PCNetState *pThis = (PCNetState *)pvUser;
     STAM_PROFILE_ADV_START(&pThis->StatTimer, a);
-    rc = PDMCritSectEnter(&pThis->CritSect, VERR_SEM_BUSY);
-    AssertReleaseRC(rc);
-
     pcnetPollTimer(pThis);
-
-    PDMCritSectLeave(&pThis->CritSect);
     STAM_PROFILE_ADV_STOP(&pThis->StatTimer, a);
 }
@@ -3825,8 +3818,9 @@
  * @thread  EMT
  */
-static DECLCALLBACK(void) pcnetTimerSoftInt(PPDMDEVINS pDevIns, PTMTIMER pTimer)
-{
-    PCNetState *pThis = PDMINS_2_DATA(pDevIns, PCNetState *);
-
+static DECLCALLBACK(void) pcnetTimerSoftInt(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
+{
+    PCNetState *pThis = (PCNetState *)pvUser;
+
+/** @todo why aren't we taking any critsect here?!? */
     pThis->aCSR[7] |= 0x0800; /* STINT */
     pcnetUpdateIrq(pThis);
@@ -3845,11 +3839,9 @@
  * @param   pTimer          The timer handle.
  */
-static DECLCALLBACK(void) pcnetTimerRestore(PPDMDEVINS pDevIns, PTMTIMER pTimer)
+static DECLCALLBACK(void) pcnetTimerRestore(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
 {
     PCNetState *pThis = PDMINS_2_DATA(pDevIns, PCNetState *);
-    int         rc = PDMCritSectEnter(&pThis->CritSect, VERR_SEM_BUSY);
-    AssertReleaseRC(rc);
-
-    rc = VERR_GENERAL_FAILURE;
+
+    int rc = VERR_GENERAL_FAILURE;
     if (pThis->cLinkDownReported <= PCNET_MAX_LINKDOWN_REPORTED)
         rc = TMTimerSetMillies(pThis->pTimerRestore, 1500);
@@ -3870,6 +3862,4 @@
         Log(("#%d pcnetTimerRestore: cLinkDownReported=%d, wait another 1500ms...\n",
              pDevIns->iInstance, pThis->cLinkDownReported));
-
-    PDMCritSectLeave(&pThis->CritSect);
 }
 
@@ -4678,5 +4668,5 @@
         pThis->cLinkDownReported = 0x10000;
         TMTimerStop(pThis->pTimerRestore);
-        pcnetTimerRestore(pDevIns, pThis->pTimerRestore);
+        pcnetTimerRestore(pDevIns, pThis->pTimerRestore, pThis);
     }
     if (pThis->pSharedMMIOR3)
@@ -4919,4 +4909,18 @@
     }
 
+    /*
+     * Initialize critical section.
+     * This must be done before register the critsect with the timer code, and also before
+     * attaching drivers or anything else that may call us back.
+     */
+    char szName[24];
+    RTStrPrintf(szName, sizeof(szName), "PCNet#%d", iInstance);
+    rc = PDMDevHlpCritSectInit(pDevIns, &pThis->CritSect, szName);
+    if (RT_FAILURE(rc))
+        return rc;
+
+    rc = RTSemEventCreate(&pThis->hEventOutOfRxSpace);
+    AssertRC(rc);
+
 #ifdef PCNET_NO_POLLING
     /*
@@ -4928,16 +4932,17 @@
     AssertLogRelMsgRCReturn(rc, ("PDMR3LdrGetSymbolRCLazy(EMInterpretInstruction) -> %Rrc\n", rc), rc);
 #else
-    rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL, pcnetTimer,
-                                "PCNet Poll Timer", &pThis->pTimerPollR3);
+    rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL, pcnetTimer, pThis,
+                                TMTIMER_FLAGS_NO_CRIT_SECT, "PCNet Poll Timer", &pThis->pTimerPollR3);
     if (RT_FAILURE(rc))
         return rc;
     pThis->pTimerPollR0 = TMTimerR0Ptr(pThis->pTimerPollR3);
     pThis->pTimerPollRC = TMTimerRCPtr(pThis->pTimerPollR3);
+    TMR3TimerSetCritSect(pThis->pTimerPollR3, &pThis->CritSect);
 #endif
     if (pThis->fAm79C973)
     {
         /* Software Interrupt timer */
-        rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL, pcnetTimerSoftInt,
-                                    "PCNet SoftInt Timer", &pThis->pTimerSoftIntR3);
+        rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL, pcnetTimerSoftInt, pThis, /** @todo r=bird: the locking here looks bogus now with SMP... */
+                                    TMTIMER_FLAGS_DEFAULT_CRIT_SECT, "PCNet SoftInt Timer", &pThis->pTimerSoftIntR3);
         if (RT_FAILURE(rc))
             return rc;
@@ -4945,8 +4950,9 @@
         pThis->pTimerSoftIntRC = TMTimerRCPtr(pThis->pTimerSoftIntR3);
     }
-    rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL, pcnetTimerRestore,
-                                "PCNet Restore Timer", &pThis->pTimerRestore);
+    rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL, pcnetTimerRestore, pThis,
+                                TMTIMER_FLAGS_NO_CRIT_SECT, "PCNet Restore Timer", &pThis->pTimerRestore);
     if (RT_FAILURE(rc))
         return rc;
+    TMR3TimerSetCritSect(pThis->pTimerRestore, &pThis->CritSect);
 
     rc = PDMDevHlpSSMRegister(pDevIns, pDevIns->pDevReg->szDeviceName, iInstance,
@@ -4956,17 +4962,4 @@
     if (RT_FAILURE(rc))
         return rc;
-
-    /*
-     * Initialize critical section.
-     * This must of course be done before attaching drivers or anything else which can call us back.
-     */
-    char szName[24];
-    RTStrPrintf(szName, sizeof(szName), "PCNet#%d", iInstance);
-    rc = PDMDevHlpCritSectInit(pDevIns, &pThis->CritSect, szName);
-    if (RT_FAILURE(rc))
-        return rc;
-
-    rc = RTSemEventCreate(&pThis->hEventOutOfRxSpace);
-    AssertRC(rc);
 
     /*
Index: /trunk/src/VBox/Devices/PC/DevACPI.cpp
===================================================================
--- /trunk/src/VBox/Devices/PC/DevACPI.cpp	(revision 20086)
+++ /trunk/src/VBox/Devices/PC/DevACPI.cpp	(revision 20087)
@@ -1068,7 +1068,7 @@
 }
 
-static DECLCALLBACK(void) acpiTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer)
-{
-    ACPIState *s = PDMINS_2_DATA(pDevIns, ACPIState *);
+static DECLCALLBACK(void) acpiTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
+{
+    ACPIState *s = (ACPIState *)pvUser;
 
     Log(("acpi: pm timer sts %#x (%d), en %#x (%d)\n",
@@ -1320,5 +1320,5 @@
                             : 0;
                     break;
-               
+
                 case SYSTEM_INFO_INDEX_CPU0_STATUS:
                 case SYSTEM_INFO_INDEX_CPU1_STATUS:
@@ -1933,5 +1933,6 @@
     }
 
-    rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL_SYNC, acpiTimer, "ACPI Timer", &s->tsR3);
+    rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL_SYNC, acpiTimer, dev,
+                                TMTIMER_FLAGS_DEFAULT_CRIT_SECT, "ACPI Timer", &s->tsR3);
     if (RT_FAILURE(rc))
     {
Index: /trunk/src/VBox/Devices/PC/DevAPIC.cpp
===================================================================
--- /trunk/src/VBox/Devices/PC/DevAPIC.cpp	(revision 20086)
+++ /trunk/src/VBox/Devices/PC/DevAPIC.cpp	(revision 20087)
@@ -1296,26 +1296,17 @@
 
 #ifdef IN_RING3
-#ifndef VBOX
+# ifndef VBOX
 static void apic_timer(void *opaque)
 {
     APICState *s = opaque;
-#else /* VBOX */
-static DECLCALLBACK(void) apicTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer)
+# else /* VBOX */
+static DECLCALLBACK(void) apicTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
 {
     APICDeviceInfo *dev = PDMINS_2_DATA(pDevIns, APICDeviceInfo *);
-    APICState *s = getLapic(dev);
-    if (s->pTimerR3 != pTimer)
-    {
-        for (uint32_t iCpu = 0; iCpu < dev->cCpus; iCpu++)
-        {
-            s = getLapicById(dev, iCpu);
-            if (s->pTimerR3 == pTimer)
-                break;
-        }
-        Assert(s->pTimerR3 == pTimer);
-    }
+    APICState *s = (APICState *)pvUser;
+    Assert(s->pTimerR3 == pTimer);
 
     APIC_LOCK_VOID(dev, VERR_INTERNAL_ERROR);
-#endif /* VBOX */
+# endif /* VBOX */
 
     if (!(s->lvt[APIC_LVT_TIMER] & APIC_LVT_MASKED)) {
@@ -1325,7 +1316,7 @@
     apic_timer_update(dev, s, s->next_time);
 
-#ifdef VBOX
+# ifdef VBOX
     APIC_UNLOCK(dev);
-#endif
+# endif
 }
 #endif /* IN_RING3 */
@@ -2407,10 +2398,11 @@
     for (i = 0, apic = LAPIC_BASE(pThis); i < cCpus; i++)
     {
-        rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL_SYNC, apicTimer,
-                                    "APIC Timer", &apic->pTimerR3);
+        rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL_SYNC, apicTimer, apic,
+                                    TMTIMER_FLAGS_NO_CRIT_SECT, "APIC Timer", &apic->pTimerR3);
         if (RT_FAILURE(rc))
             return rc;
         apic->pTimerR0 = TMTimerR0Ptr(apic->pTimerR3);
         apic->pTimerRC = TMTimerRCPtr(apic->pTimerR3);
+        /// @todo TMTimerSetCritSect(apic->pTimerR3, pThis->pApicHlpR3->pfnGetCritSect(..));
         apic++;
     }
Index: /trunk/src/VBox/Devices/PC/DevPit-i8254.cpp
===================================================================
--- /trunk/src/VBox/Devices/PC/DevPit-i8254.cpp	(revision 20086)
+++ /trunk/src/VBox/Devices/PC/DevPit-i8254.cpp	(revision 20087)
@@ -809,9 +809,9 @@
  * @param   pDevIns         Device instance of the device which registered the timer.
  * @param   pTimer          The timer handle.
- */
-static DECLCALLBACK(void) pitTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer)
-{
-    PITState *pThis = PDMINS_2_DATA(pDevIns, PITState *);
-    PITChannelState *s = &pThis->channels[0];
+ * @param   pvUser          Pointer to the PIT channel state.
+ */
+static DECLCALLBACK(void) pitTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
+{
+    PITChannelState *s = (PITChannelState *)pvUser;
     STAM_PROFILE_ADV_START(&s->CTX_SUFF(pPit)->StatPITHandler, a);
     Log(("pitTimer\n"));
@@ -994,5 +994,6 @@
      * Create timer, register I/O Ports and save state.
      */
-    rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL_SYNC, pitTimer, "i8254 Programmable Interval Timer",
+    rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL_SYNC, pitTimer, &pThis->channels[0],
+                                TMTIMER_FLAGS_DEFAULT_CRIT_SECT, "i8254 Programmable Interval Timer",
                                 &pThis->channels[0].pTimerR3);
     if (RT_FAILURE(rc))
Index: /trunk/src/VBox/Devices/PC/DevRTC.cpp
===================================================================
--- /trunk/src/VBox/Devices/PC/DevRTC.cpp	(revision 20086)
+++ /trunk/src/VBox/Devices/PC/DevRTC.cpp	(revision 20087)
@@ -73,7 +73,7 @@
 PDMBOTHCBDECL(int) rtcIOPortRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb);
 PDMBOTHCBDECL(int) rtcIOPortWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb);
-PDMBOTHCBDECL(void) rtcTimerPeriodic(PPDMDEVINS pDevIns, PTMTIMER pTimer);
-PDMBOTHCBDECL(void) rtcTimerSecond(PPDMDEVINS pDevIns, PTMTIMER pTimer);
-PDMBOTHCBDECL(void) rtcTimerSecond2(PPDMDEVINS pDevIns, PTMTIMER pTimer);
+PDMBOTHCBDECL(void) rtcTimerPeriodic(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser);
+PDMBOTHCBDECL(void) rtcTimerSecond(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser);
+PDMBOTHCBDECL(void) rtcTimerSecond2(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser);
 __END_DECLS
 #endif /* !VBOX_DEVICE_STRUCT_TESTCASE */
@@ -553,8 +553,9 @@
  * @param   pDevIns         Device instance of the device which registered the timer.
  * @param   pTimer          The timer handle.
- */
-PDMBOTHCBDECL(void) rtcTimerPeriodic(PPDMDEVINS pDevIns, PTMTIMER pTimer)
-{
-    rtc_periodic_timer(PDMINS_2_DATA(pDevIns, RTCState *));
+ * @param   pvUser          Pointer to the RTC state.
+ */
+PDMBOTHCBDECL(void) rtcTimerPeriodic(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
+{
+    rtc_periodic_timer((RTCState *)pvUser);
 }
 
@@ -565,8 +566,9 @@
  * @param   pDevIns         Device instance of the device which registered the timer.
  * @param   pTimer          The timer handle.
- */
-PDMBOTHCBDECL(void) rtcTimerSecond(PPDMDEVINS pDevIns, PTMTIMER pTimer)
-{
-    rtc_update_second(PDMINS_2_DATA(pDevIns, RTCState *));
+ * @param   pvUser          Pointer to the RTC state.
+ */
+PDMBOTHCBDECL(void) rtcTimerSecond(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
+{
+    rtc_update_second((RTCState *)pvUser);
 }
 
@@ -577,8 +579,9 @@
  * @param   pDevIns         Device instance of the device which registered the timer.
  * @param   pTimer          The timer handle.
- */
-PDMBOTHCBDECL(void) rtcTimerSecond2(PPDMDEVINS pDevIns, PTMTIMER pTimer)
-{
-    rtc_update_second2(PDMINS_2_DATA(pDevIns, RTCState *));
+ * @param   pvUser          Pointer to the RTC state.
+ */
+PDMBOTHCBDECL(void) rtcTimerSecond2(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
+{
+    rtc_update_second2((RTCState *)pvUser);
 }
 
@@ -869,5 +872,7 @@
      * Create timers, arm them, register I/O Ports and save state.
      */
-    rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL_SYNC, rtcTimerPeriodic, "MC146818 RTC/CMOS - Periodic", &pThis->pPeriodicTimerR3);
+    rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL_SYNC, rtcTimerPeriodic, pThis,
+                                TMTIMER_FLAGS_DEFAULT_CRIT_SECT, "MC146818 RTC/CMOS - Periodic",
+                                &pThis->pPeriodicTimerR3);
     if (RT_FAILURE(rc))
         return rc;
@@ -875,5 +880,7 @@
     pThis->pPeriodicTimerRC = TMTimerRCPtr(pThis->pPeriodicTimerR3);
 
-    rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL_SYNC, rtcTimerSecond,   "MC146818 RTC/CMOS - Second", &pThis->pSecondTimerR3);
+    rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL_SYNC, rtcTimerSecond, pThis,
+                                TMTIMER_FLAGS_DEFAULT_CRIT_SECT, "MC146818 RTC/CMOS - Second",
+                                &pThis->pSecondTimerR3);
     if (RT_FAILURE(rc))
         return rc;
@@ -881,5 +888,7 @@
     pThis->pSecondTimerRC = TMTimerRCPtr(pThis->pSecondTimerR3);
 
-    rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL_SYNC, rtcTimerSecond2,  "MC146818 RTC/CMOS - Second2", &pThis->pSecondTimer2R3);
+    rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL_SYNC, rtcTimerSecond2, pThis,
+                                TMTIMER_FLAGS_DEFAULT_CRIT_SECT, "MC146818 RTC/CMOS - Second2",
+                                &pThis->pSecondTimer2R3);
     if (RT_FAILURE(rc))
         return rc;
Index: /trunk/src/VBox/Devices/Storage/fdc.c
===================================================================
--- /trunk/src/VBox/Devices/Storage/fdc.c	(revision 20086)
+++ /trunk/src/VBox/Devices/Storage/fdc.c	(revision 20087)
@@ -2343,7 +2343,7 @@
 
 #ifdef VBOX
-static DECLCALLBACK(void) fdc_timer (PPDMDEVINS pDevIns, PTMTIMER pTimer)
-{
-    fdctrl_t *fdctrl = PDMINS_2_DATA (pDevIns, fdctrl_t *);
+static DECLCALLBACK(void) fdc_timer (PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser)
+{
+    fdctrl_t *fdctrl = (fdctrl_t *)pvUser;
     fdctrl_result_timer (fdctrl);
 }
@@ -2849,5 +2849,6 @@
      * Create the FDC timer.
      */
-    rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL, fdc_timer, "FDC Timer", &fdctrl->result_timer);
+    rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL, fdc_timer, fdctrl,
+                                TMTIMER_FLAGS_DEFAULT_CRIT_SECT, "FDC Timer", &fdctrl->result_timer);
     if (RT_FAILURE (rc))
         return rc;
Index: /trunk/src/VBox/VMM/IOM.cpp
===================================================================
--- /trunk/src/VBox/VMM/IOM.cpp	(revision 20086)
+++ /trunk/src/VBox/VMM/IOM.cpp	(revision 20087)
@@ -1654,4 +1654,16 @@
     while (PDMCritSectIsOwner(&pVM->iom.s.EmtLock))
         PDMCritSectLeave(&pVM->iom.s.EmtLock);
+}
+
+
+/**
+ * For TM only!
+ *
+ * @returns Pointer to the critical section.
+ * @param   pVM                 The VM handle.
+ */
+VMMR3DECL(PPDMCRITSECT) IOMR3GetCritSect(PVM pVM)
+{
+    return &pVM->iom.s.EmtLock;
 }
 
Index: /trunk/src/VBox/VMM/PDMCritSect.cpp
===================================================================
--- /trunk/src/VBox/VMM/PDMCritSect.cpp	(revision 20086)
+++ /trunk/src/VBox/VMM/PDMCritSect.cpp	(revision 20087)
@@ -351,4 +351,20 @@
 
 /**
+ * Gets the name of the critical section.
+ *
+ *
+ * @returns Pointer to the critical section name (read only) on success,
+ *          NULL on failure (invalid critical section).
+ * @param   pCritSect           The critical section.
+ */
+VMMR3DECL(const char *) PDMR3CritSectName(PCPDMCRITSECT pCritSect)
+{
+    AssertPtrReturn(pCritSect, NULL);
+    AssertReturn(pCritSect->s.Core.u32Magic == RTCRITSECT_MAGIC, NULL);
+    return pCritSect->s.pszName;
+}
+
+
+/**
  * Schedule a event semaphore for signalling upon critsect exit.
  *
Index: /trunk/src/VBox/VMM/PDMDevHlp.cpp
===================================================================
--- /trunk/src/VBox/VMM/PDMDevHlp.cpp	(revision 20086)
+++ /trunk/src/VBox/VMM/PDMDevHlp.cpp	(revision 20087)
@@ -381,12 +381,13 @@
 
 /** @copydoc PDMDEVHLPR3::pfnTMTimerCreate */
-static DECLCALLBACK(int) pdmR3DevHlp_TMTimerCreate(PPDMDEVINS pDevIns, TMCLOCK enmClock, PFNTMTIMERDEV pfnCallback, const char *pszDesc, PPTMTIMERR3 ppTimer)
+static DECLCALLBACK(int) pdmR3DevHlp_TMTimerCreate(PPDMDEVINS pDevIns, TMCLOCK enmClock, PFNTMTIMERDEV pfnCallback, void *pvUser, uint32_t fFlags, const char *pszDesc, PPTMTIMERR3 ppTimer)
 {
     PDMDEV_ASSERT_DEVINS(pDevIns);
     VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
-    LogFlow(("pdmR3DevHlp_TMTimerCreate: caller='%s'/%d: enmClock=%d pfnCallback=%p pszDesc=%p:{%s} ppTimer=%p\n",
-             pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, enmClock, pfnCallback, pszDesc, pszDesc, ppTimer));
-
-    int rc = TMR3TimerCreateDevice(pDevIns->Internal.s.pVMR3, pDevIns, enmClock, pfnCallback, pszDesc, ppTimer);
+    LogFlow(("pdmR3DevHlp_TMTimerCreate: caller='%s'/%d: enmClock=%d pfnCallback=%p pvUser=%p fFlags=%#x pszDesc=%p:{%s} ppTimer=%p\n",
+             pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, enmClock, pfnCallback, pvUser, fFlags, pszDesc, pszDesc, ppTimer));
+
+
+    int rc = TMR3TimerCreateDevice(pDevIns->Internal.s.pVMR3, pDevIns, enmClock, pfnCallback, pvUser, fFlags, pszDesc, ppTimer);
 
     LogFlow(("pdmR3DevHlp_TMTimerCreate: caller='%s'/%d: returns %Rrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
Index: /trunk/src/VBox/VMM/TM.cpp
===================================================================
--- /trunk/src/VBox/VMM/TM.cpp	(revision 20086)
+++ /trunk/src/VBox/VMM/TM.cpp	(revision 20087)
@@ -1206,4 +1206,6 @@
     pTimer->offNext         = 0;
     pTimer->offPrev         = 0;
+    pTimer->pvUser          = NULL;
+    pTimer->pCritSect       = NULL;
     pTimer->pszDesc         = pszDesc;
 
@@ -1233,10 +1235,14 @@
  * @param   enmClock        The clock to use on this timer.
  * @param   pfnCallback     Callback function.
+ * @param   pvUser          The user argument to the callback.
+ * @param   fFlags          Timer creation flags, see grp_tm_timer_flags.
  * @param   pszDesc         Pointer to description string which must stay around
  *                          until the timer is fully destroyed (i.e. a bit after TMTimerDestroy()).
  * @param   ppTimer         Where to store the timer on success.
  */
-VMMR3DECL(int) TMR3TimerCreateDevice(PVM pVM, PPDMDEVINS pDevIns, TMCLOCK enmClock, PFNTMTIMERDEV pfnCallback, const char *pszDesc, PPTMTIMERR3 ppTimer)
-{
+VMMR3DECL(int) TMR3TimerCreateDevice(PVM pVM, PPDMDEVINS pDevIns, TMCLOCK enmClock, PFNTMTIMERDEV pfnCallback, void *pvUser, uint32_t fFlags, const char *pszDesc, PPTMTIMERR3 ppTimer)
+{
+    AssertReturn(!(fFlags & ~(TMTIMER_FLAGS_NO_CRIT_SECT)), VERR_INVALID_PARAMETER);
+
     /*
      * Allocate and init stuff.
@@ -1248,4 +1254,7 @@
         (*ppTimer)->u.Dev.pfnTimer  = pfnCallback;
         (*ppTimer)->u.Dev.pDevIns   = pDevIns;
+        (*ppTimer)->pvUser          = pvUser;
+        if (fFlags & TMTIMER_FLAGS_DEFAULT_CRIT_SECT)
+            (*ppTimer)->pCritSect   = IOMR3GetCritSect(pVM);
         Log(("TM: Created device timer %p clock %d callback %p '%s'\n", (*ppTimer), enmClock, pfnCallback, pszDesc));
     }
@@ -1308,5 +1317,5 @@
         pTimer->enmType             = TMTIMERTYPE_INTERNAL;
         pTimer->u.Internal.pfnTimer = pfnCallback;
-        pTimer->u.Internal.pvUser   = pvUser;
+        pTimer->pvUser              = pvUser;
         *ppTimer = pTimer;
         Log(("TM: Created internal timer %p clock %d callback %p '%s'\n", pTimer, enmClock, pfnCallback, pszDesc));
@@ -1339,5 +1348,5 @@
         pTimer->enmType             = TMTIMERTYPE_EXTERNAL;
         pTimer->u.External.pfnTimer = pfnCallback;
-        pTimer->u.External.pvUser   = pvUser;
+        pTimer->pvUser              = pvUser;
         Log(("TM: Created external timer %p clock %d callback %p '%s'\n", pTimer, enmClock, pfnCallback, pszDesc));
         return pTimer;
@@ -1799,6 +1808,9 @@
     while (pNext && pNext->u64Expire <= u64Now)
     {
-        PTMTIMER pTimer = pNext;
+        PTMTIMER        pTimer    = pNext;
         pNext = TMTIMER_GET_NEXT(pTimer);
+        PPDMCRITSECT    pCritSect = pTimer->pCritSect;
+        if (pCritSect)
+            PDMCritSectEnter(pCritSect, VERR_INTERNAL_ERROR);
         Log2(("tmR3TimerQueueRun: %p:{.enmState=%s, .enmClock=%d, .enmType=%d, u64Expire=%llx (now=%llx) .pszDesc=%s}\n",
               pTimer, tmTimerState(pTimer->enmState), pTimer->enmClock, pTimer->enmType, pTimer->u64Expire, u64Now, pTimer->pszDesc));
@@ -1825,21 +1837,14 @@
             /* fire */
             TM_SET_STATE(pTimer, TMTIMERSTATE_EXPIRED_DELIVER);
-//            tmUnlock(pVM);
             switch (pTimer->enmType)
             {
-                case TMTIMERTYPE_DEV:
-//                    iomLock(pVM);
-                    pTimer->u.Dev.pfnTimer(pTimer->u.Dev.pDevIns, pTimer);
-//                    iomUnlock(pVM);
-                    break;
-
-                case TMTIMERTYPE_DRV:       pTimer->u.Drv.pfnTimer(pTimer->u.Drv.pDrvIns, pTimer); break;
-                case TMTIMERTYPE_INTERNAL:  pTimer->u.Internal.pfnTimer(pVM, pTimer, pTimer->u.Internal.pvUser); break;
-                case TMTIMERTYPE_EXTERNAL:  pTimer->u.External.pfnTimer(pTimer->u.External.pvUser); break;
+                case TMTIMERTYPE_DEV:       pTimer->u.Dev.pfnTimer(pTimer->u.Dev.pDevIns, pTimer, pTimer->pvUser); break;
+                case TMTIMERTYPE_DRV:       pTimer->u.Drv.pfnTimer(pTimer->u.Drv.pDrvIns, pTimer /*, pTimer->pvUser*/); break;
+                case TMTIMERTYPE_INTERNAL:  pTimer->u.Internal.pfnTimer(pVM, pTimer, pTimer->pvUser); break;
+                case TMTIMERTYPE_EXTERNAL:  pTimer->u.External.pfnTimer(pTimer->pvUser); break;
                 default:
                     AssertMsgFailed(("Invalid timer type %d (%s)\n", pTimer->enmType, pTimer->pszDesc));
                     break;
             }
-//            tmLock(pVM);
 
             /* change the state if it wasn't changed already in the handler. */
@@ -1847,4 +1852,6 @@
             Log2(("tmR3TimerQueueRun: new state %s\n", tmTimerState(pTimer->enmState)));
         }
+        if (pCritSect)
+            PDMCritSectLeave(pCritSect);
     } /* run loop */
 }
@@ -2002,8 +2009,8 @@
             switch (pTimer->enmType)
             {
-                case TMTIMERTYPE_DEV:       pTimer->u.Dev.pfnTimer(pTimer->u.Dev.pDevIns, pTimer); break;
-                case TMTIMERTYPE_DRV:       pTimer->u.Drv.pfnTimer(pTimer->u.Drv.pDrvIns, pTimer); break;
-                case TMTIMERTYPE_INTERNAL:  pTimer->u.Internal.pfnTimer(pVM, pTimer, pTimer->u.Internal.pvUser); break;
-                case TMTIMERTYPE_EXTERNAL:  pTimer->u.External.pfnTimer(pTimer->u.External.pvUser); break;
+                case TMTIMERTYPE_DEV:       pTimer->u.Dev.pfnTimer(pTimer->u.Dev.pDevIns, pTimer, pTimer->pvUser); break;
+                case TMTIMERTYPE_DRV:       pTimer->u.Drv.pfnTimer(pTimer->u.Drv.pDrvIns, pTimer /*, pTimer->pvUser*/); break;
+                case TMTIMERTYPE_INTERNAL:  pTimer->u.Internal.pfnTimer(pVM, pTimer, pTimer->pvUser); break;
+                case TMTIMERTYPE_EXTERNAL:  pTimer->u.External.pfnTimer(pTimer->pvUser); break;
                 default:
                     AssertMsgFailed(("Invalid timer type %d (%s)\n", pTimer->enmType, pTimer->pszDesc));
@@ -2311,4 +2318,46 @@
 
 /**
+ * Associates a critical section with a timer.
+ *
+ * The critical section will be entered prior to doing the timer call back, thus
+ * avoiding potential races between the timer thread and other threads trying to
+ * stop or adjust the timer expiration while it's being delivered. The timer
+ * thread will leave the critical section when the timer callback returns.
+ *
+ * In strict builds, ownership of the critical section will be asserted by
+ * TMTimerSet and TMTimerStop.
+ *
+ * @retval  VINF_SUCCESS on success.
+ * @retval  VERR_INVALID_HANDLE if the timer handle is NULL or invalid
+ *          (asserted).
+ * @retval  VERR_INVALID_PARAMETER if pCritSect is NULL or has an invalid magic
+ *          (asserted).
+ * @retval  VERR_ALREADY_EXISTS if a critical section was already associated
+ *          with the timer (asserted).
+ * @retval  VERR_INVALID_STATE if the timer isn't stopped.
+ *
+ * @param   pTimer          The timer handle.
+ * @param   pCritSect       The critical section. The caller must make sure this
+ *                          is around for the life time of the timer.
+ *
+ * @thread  Any, but the caller is responsible for making sure the timer is not
+ *          active.
+ */
+VMMR3DECL(int) TMR3TimerSetCritSect(PTMTIMERR3 pTimer, PPDMCRITSECT pCritSect)
+{
+    AssertPtrReturn(pTimer, VERR_INVALID_HANDLE);
+    AssertPtrReturn(pCritSect, VERR_INVALID_PARAMETER);
+    const char *pszName = PDMR3CritSectName(pCritSect); /* exploited for validation */
+    AssertReturn(pszName, VERR_INVALID_PARAMETER);
+    AssertReturn(!pTimer->pCritSect, VERR_ALREADY_EXISTS);
+    AssertReturn(pTimer->enmState == TMTIMERSTATE_STOPPED, VERR_INVALID_STATE);
+    LogFlow(("pTimer=%p (%s) pCritSect=%p (%s)\n", pTimer, pTimer->pszDesc, pCritSect, pszName));
+
+    pTimer->pCritSect = pCritSect;
+    return VINF_SUCCESS;
+}
+
+
+/**
  * Get the real world UTC time adjusted for VM lag.
  *
Index: /trunk/src/VBox/VMM/TMInternal.h
===================================================================
--- /trunk/src/VBox/VMM/TMInternal.h	(revision 20086)
+++ /trunk/src/VBox/VMM/TMInternal.h	(revision 20087)
@@ -153,6 +153,4 @@
             /** Callback. */
             R3PTRTYPE(PFNTMTIMERINT)    pfnTimer;
-            /** User argument. */
-            RTR3PTR                     pvUser;
         } Internal;
 
@@ -162,6 +160,4 @@
             /** Callback. */
             R3PTRTYPE(PFNTMTIMEREXT)    pfnTimer;
-            /** User data. */
-            RTR3PTR                     pvUser;
         } External;
     } u;
@@ -176,4 +172,9 @@
     /** Timer relative offset to the previous timer in the chain. */
     int32_t                 offPrev;
+
+    /** User argument. */
+    RTR3PTR                 pvUser;
+    /** The critical section associated with the lock. */
+    R3PTRTYPE(PPDMCRITSECT) pCritSect;
 
     /** Pointer to the next timer in the list of created or free timers. (TM::pTimers or TM::pFree) */
Index: /trunk/src/VBox/VMM/testcase/tstVMStructGC.cpp
===================================================================
--- /trunk/src/VBox/VMM/testcase/tstVMStructGC.cpp	(revision 20086)
+++ /trunk/src/VBox/VMM/testcase/tstVMStructGC.cpp	(revision 20087)
@@ -839,11 +839,11 @@
     GEN_CHECK_OFF(TMTIMER, u.Drv.pDrvIns);
     GEN_CHECK_OFF(TMTIMER, u.Internal.pfnTimer);
-    GEN_CHECK_OFF(TMTIMER, u.Internal.pvUser);
     GEN_CHECK_OFF(TMTIMER, u.External.pfnTimer);
-    GEN_CHECK_OFF(TMTIMER, u.External.pvUser);
     GEN_CHECK_OFF(TMTIMER, enmState);
     GEN_CHECK_OFF(TMTIMER, offScheduleNext);
     GEN_CHECK_OFF(TMTIMER, offNext);
     GEN_CHECK_OFF(TMTIMER, offPrev);
+    GEN_CHECK_OFF(TMTIMER, pvUser);
+    GEN_CHECK_OFF(TMTIMER, pCritSect);
     GEN_CHECK_OFF(TMTIMER, pBigNext);
     GEN_CHECK_OFF(TMTIMER, pBigPrev);
