Index: /trunk/include/VBox/pdmdev.h
===================================================================
--- /trunk/include/VBox/pdmdev.h	(revision 24743)
+++ /trunk/include/VBox/pdmdev.h	(revision 24744)
@@ -2408,5 +2408,5 @@
 
     /**
-     * Set up asynchronous handling of a suspend or power off notification.
+     * Set up asynchronous handling of a suspend, reset or power off notification.
      *
      * This shall only be called when getting the notification.  It must be called
Index: /trunk/include/VBox/pdmdrv.h
===================================================================
--- /trunk/include/VBox/pdmdrv.h	(revision 24743)
+++ /trunk/include/VBox/pdmdrv.h	(revision 24744)
@@ -698,5 +698,5 @@
 
     /**
-     * Set up asynchronous handling of a suspend or power off notification.
+     * Set up asynchronous handling of a suspend, reset or power off notification.
      *
      * This shall only be called when getting the notification.  It must be called
Index: /trunk/include/VBox/pdmusb.h
===================================================================
--- /trunk/include/VBox/pdmusb.h	(revision 24743)
+++ /trunk/include/VBox/pdmusb.h	(revision 24744)
@@ -575,5 +575,5 @@
 
     /**
-     * Set up asynchronous handling of a suspend or power off notification.
+     * Set up asynchronous handling of a suspend, reset or power off notification.
      *
      * This shall only be called when getting the notification.  It must be called
Index: /trunk/src/VBox/VMM/PDM.cpp
===================================================================
--- /trunk/src/VBox/VMM/PDM.cpp	(revision 24743)
+++ /trunk/src/VBox/VMM/PDM.cpp	(revision 24744)
@@ -1039,9 +1039,121 @@
 
 
-
-
-/**
- * This function will notify all the devices and their
- * attached drivers about the VM now being reset.
+/**
+ * Worker for PDMR3Reset that deals with one driver.
+ *
+ * @param   pDrvIns             The driver instance.
+ * @param   pcAsync             The asynchronous reset notification counter.
+ * @param   pszDeviceName       The parent device name.
+ * @param   iDevInstance        The parent device instance number.
+ * @param   iLun                The parent LUN number.
+ */
+DECLINLINE(bool) pdmR3ResetDrv(PPDMDRVINS pDrvIns, unsigned *pcAsync,
+                               const char *pszDeviceName, uint32_t iDevInstance, uint32_t iLun)
+{
+    if (!pDrvIns->Internal.s.fVMReset)
+    {
+        pDrvIns->Internal.s.fVMReset = true;
+        if (pDrvIns->pDrvReg->pfnReset)
+        {
+            if (!pDrvIns->Internal.s.pfnAsyncNotify)
+            {
+                LogFlow(("PDMR3Reset: Notifying - driver '%s'/%d on LUN#%d of device '%s'/%d\n",
+                         pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, iLun, pszDeviceName, iDevInstance));
+                pDrvIns->pDrvReg->pfnReset(pDrvIns);
+                if (pDrvIns->Internal.s.pfnAsyncNotify)
+                    LogFlow(("PDMR3Reset: Async notification started - driver '%s'/%d on LUN#%d of device '%s'/%d\n",
+                             pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, iLun, pszDeviceName, iDevInstance));
+            }
+            else if (pDrvIns->Internal.s.pfnAsyncNotify(pDrvIns))
+            {
+                pDrvIns->Internal.s.pfnAsyncNotify = false;
+                LogFlow(("PDMR3Reset: Async notification completed - driver '%s'/%d on LUN#%d of device '%s'/%d\n",
+                         pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, iLun, pszDeviceName, iDevInstance));
+            }
+            if (pDrvIns->Internal.s.pfnAsyncNotify)
+            {
+                pDrvIns->Internal.s.fVMReset = false;
+                (*pcAsync)++;
+                return false;
+            }
+        }
+    }
+    return true;
+}
+
+
+/**
+ * Worker for PDMR3Reset that deals with one USB device instance.
+ *
+ * @param   pUsbIns             The USB device instance.
+ * @param   pcAsync             The asynchronous reset notification counter.
+ */
+DECLINLINE(void) pdmR3ResetUsb(PPDMUSBINS pUsbIns, unsigned *pcAsync)
+{
+    if (!pUsbIns->Internal.s.fVMReset)
+    {
+        pUsbIns->Internal.s.fVMReset = true;
+        if (pUsbIns->pUsbReg->pfnVMReset)
+        {
+            if (!pUsbIns->Internal.s.pfnAsyncNotify)
+            {
+                LogFlow(("PDMR3Reset: Notifying - device '%s'/%d\n", pUsbIns->pUsbReg->szDeviceName, pUsbIns->iInstance));
+                pUsbIns->pUsbReg->pfnVMReset(pUsbIns);
+                if (pUsbIns->Internal.s.pfnAsyncNotify)
+                    LogFlow(("PDMR3Reset: Async notification started - device '%s'/%d\n", pUsbIns->pUsbReg->szDeviceName, pUsbIns->iInstance));
+            }
+            else if (pUsbIns->Internal.s.pfnAsyncNotify(pUsbIns))
+            {
+                LogFlow(("PDMR3Reset: Async notification completed - device '%s'/%d\n", pUsbIns->pUsbReg->szDeviceName, pUsbIns->iInstance));
+                pUsbIns->Internal.s.pfnAsyncNotify = NULL;
+            }
+            if (pUsbIns->Internal.s.pfnAsyncNotify)
+            {
+                pUsbIns->Internal.s.fVMReset = false;
+                (*pcAsync)++;
+            }
+        }
+    }
+}
+
+
+/**
+ * Worker for PDMR3Reset that deals with one device instance.
+ *
+ * @param   pDevIns             The device instance.
+ * @param   pcAsync             The asynchronous reset notification counter.
+ */
+DECLINLINE(void) pdmR3ResetDev(PPDMDEVINS pDevIns, unsigned *pcAsync)
+{
+    if (!(pDevIns->Internal.s.fIntFlags & PDMDEVINSINT_FLAGS_RESET))
+    {
+        pDevIns->Internal.s.fIntFlags |= PDMDEVINSINT_FLAGS_RESET;
+        if (pDevIns->pDevReg->pfnReset)
+        {
+            if (!pDevIns->Internal.s.pfnAsyncNotify)
+            {
+                LogFlow(("PDMR3Reset: Notifying - device '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
+                pDevIns->pDevReg->pfnReset(pDevIns);
+                if (pDevIns->Internal.s.pfnAsyncNotify)
+                    LogFlow(("PDMR3Reset: Async notification started - device '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
+            }
+            else if (pDevIns->Internal.s.pfnAsyncNotify(pDevIns))
+            {
+                LogFlow(("PDMR3Reset: Async notification completed - device '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
+                pDevIns->Internal.s.pfnAsyncNotify = NULL;
+            }
+            if (pDevIns->Internal.s.pfnAsyncNotify)
+            {
+                pDevIns->Internal.s.fIntFlags &= ~PDMDEVINSINT_FLAGS_RESET;
+                (*pcAsync)++;
+            }
+        }
+    }
+}
+
+
+/**
+ * This function will notify all the devices and their attached drivers about
+ * the VM now being reset.
  *
  * @param   pVM     VM Handle.
@@ -1050,4 +1162,79 @@
 {
     LogFlow(("PDMR3Reset:\n"));
+
+    /*
+     * Clear all the reset flags.
+     */
+    for (PPDMDEVINS pDevIns = pVM->pdm.s.pDevInstances; pDevIns; pDevIns = pDevIns->Internal.s.pNextR3)
+    {
+        pDevIns->Internal.s.fIntFlags &= ~PDMDEVINSINT_FLAGS_RESET;
+        for (PPDMLUN pLun = pDevIns->Internal.s.pLunsR3; pLun; pLun = pLun->pNext)
+            for (PPDMDRVINS pDrvIns = pLun->pTop; pDrvIns; pDrvIns = pDrvIns->Internal.s.pDown)
+                pDrvIns->Internal.s.fVMReset = false;
+    }
+#ifdef VBOX_WITH_USB
+    for (PPDMUSBINS pUsbIns = pVM->pdm.s.pUsbInstances; pUsbIns; pUsbIns = pUsbIns->Internal.s.pNext)
+    {
+        pUsbIns->Internal.s.fVMReset = false;
+        for (PPDMLUN pLun = pUsbIns->Internal.s.pLuns; pLun; pLun = pLun->pNext)
+            for (PPDMDRVINS pDrvIns = pLun->pTop; pDrvIns; pDrvIns = pDrvIns->Internal.s.pDown)
+                pDrvIns->Internal.s.fVMReset = false;
+    }
+#endif
+
+    /*
+     * The outer loop repeats until there are no more async requests.
+     */
+    unsigned cAsync;
+    for (unsigned iLoop = 0; ; iLoop++)
+    {
+        /*
+         * Iterate thru the device instances and USB device instances,
+         * processing the drivers associated with those.
+         */
+        cAsync = 0;
+        for (PPDMDEVINS pDevIns = pVM->pdm.s.pDevInstances; pDevIns; pDevIns = pDevIns->Internal.s.pNextR3)
+        {
+            unsigned const cAsyncStart = cAsync;
+
+            if (cAsync == cAsyncStart)
+                for (PPDMLUN pLun = pDevIns->Internal.s.pLunsR3; pLun; pLun = pLun->pNext)
+                    for (PPDMDRVINS pDrvIns = pLun->pTop; pDrvIns; pDrvIns = pDrvIns->Internal.s.pDown)
+                        if (!pdmR3ResetDrv(pDrvIns, &cAsync, pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pLun->iLun))
+                            break;
+
+                        if (cAsync == cAsyncStart)
+                pdmR3ResetDev(pDevIns, &cAsync);
+        }
+
+#ifdef VBOX_WITH_USB
+        for (PPDMUSBINS pUsbIns = pVM->pdm.s.pUsbInstances; pUsbIns; pUsbIns = pUsbIns->Internal.s.pNext)
+        {
+            unsigned const cAsyncStart = cAsync;
+
+            for (PPDMLUN pLun = pUsbIns->Internal.s.pLuns; pLun; pLun = pLun->pNext)
+                for (PPDMDRVINS pDrvIns = pLun->pTop; pDrvIns; pDrvIns = pDrvIns->Internal.s.pDown)
+                    if (!pdmR3ResetDrv(pDrvIns, &cAsync, pUsbIns->pUsbReg->szDeviceName, pUsbIns->iInstance, pLun->iLun))
+                        break;
+
+            if (cAsync == cAsyncStart)
+                pdmR3ResetUsb(pUsbIns, &cAsync);
+        }
+#endif
+        if (!cAsync)
+            break;
+
+        /*
+         * Process requests.
+         */
+        /** @todo This is utterly nuts and completely unsafe... will get back to it in a
+         *        bit I hope... */
+        int rc = VMR3AsyncPdmNotificationWaitU(&pVM->pUVM->aCpus[0]);
+        AssertReleaseMsg(rc == VINF_SUCCESS, ("%Rrc\n", rc));
+        rc = VMR3ReqProcessU(pVM->pUVM, VMCPUID_ANY);
+        AssertReleaseMsg(rc == VINF_SUCCESS, ("%Rrc\n", rc));
+        rc = VMR3ReqProcessU(pVM->pUVM, 0/*idDstCpu*/);
+        AssertReleaseMsg(rc == VINF_SUCCESS, ("%Rrc\n", rc));
+    }
 
     /*
@@ -1063,49 +1250,4 @@
     }
     VM_FF_CLEAR(pVM, VM_FF_PDM_DMA);
-
-    /*
-     * Iterate the device instances.
-     * The attached drivers are processed first.
-     */
-    for (PPDMDEVINS pDevIns = pVM->pdm.s.pDevInstances; pDevIns; pDevIns = pDevIns->Internal.s.pNextR3)
-    {
-        for (PPDMLUN pLun = pDevIns->Internal.s.pLunsR3; pLun; pLun = pLun->pNext)
-            /** @todo Inverse the order here? */
-            for (PPDMDRVINS pDrvIns = pLun->pTop; pDrvIns; pDrvIns = pDrvIns->Internal.s.pDown)
-                if (pDrvIns->pDrvReg->pfnReset)
-                {
-                    LogFlow(("PDMR3Reset: Notifying - driver '%s'/%d on LUN#%d of device '%s'/%d\n",
-                             pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, pLun->iLun, pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
-                    pDrvIns->pDrvReg->pfnReset(pDrvIns);
-                }
-
-        if (pDevIns->pDevReg->pfnReset)
-        {
-            LogFlow(("PDMR3Reset: Notifying - device '%s'/%d\n",
-                     pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
-            pDevIns->pDevReg->pfnReset(pDevIns);
-        }
-    }
-
-#ifdef VBOX_WITH_USB
-    for (PPDMUSBINS pUsbIns = pVM->pdm.s.pUsbInstances; pUsbIns; pUsbIns = pUsbIns->Internal.s.pNext)
-    {
-        for (PPDMLUN pLun = pUsbIns->Internal.s.pLuns; pLun; pLun = pLun->pNext)
-            for (PPDMDRVINS pDrvIns = pLun->pTop; pDrvIns; pDrvIns = pDrvIns->Internal.s.pDown)
-                if (pDrvIns->pDrvReg->pfnReset)
-                {
-                    LogFlow(("PDMR3Reset: Notifying - driver '%s'/%d on LUN#%d of usb device '%s'/%d\n",
-                             pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, pLun->iLun, pUsbIns->pUsbReg->szDeviceName, pUsbIns->iInstance));
-                    pDrvIns->pDrvReg->pfnReset(pDrvIns);
-                }
-
-        if (pUsbIns->pUsbReg->pfnVMReset)
-        {
-            LogFlow(("PDMR3Reset: Notifying - device '%s'/%d\n",
-                     pUsbIns->pUsbReg->szDeviceName, pUsbIns->iInstance));
-            pUsbIns->pUsbReg->pfnVMReset(pUsbIns);
-        }
-    }
-#endif
 
     LogFlow(("PDMR3Reset: returns void\n"));
Index: /trunk/src/VBox/VMM/PDMDevHlp.cpp
===================================================================
--- /trunk/src/VBox/VMM/PDMDevHlp.cpp	(revision 24743)
+++ /trunk/src/VBox/VMM/PDMDevHlp.cpp	(revision 24744)
@@ -2340,9 +2340,11 @@
     AssertStmt(pfnAsyncNotify, rc = VERR_INVALID_PARAMETER);
     AssertStmt(!pDevIns->Internal.s.pfnAsyncNotify, rc = VERR_WRONG_ORDER);
-    AssertStmt(pDevIns->Internal.s.fIntFlags & PDMDEVINSINT_FLAGS_SUSPENDED, rc = VERR_WRONG_ORDER);
+    AssertStmt(pDevIns->Internal.s.fIntFlags & (PDMDEVINSINT_FLAGS_SUSPENDED | PDMDEVINSINT_FLAGS_RESET), rc = VERR_WRONG_ORDER);
     VMSTATE enmVMState = VMR3GetState(pDevIns->Internal.s.pVMR3);
     AssertStmt(   enmVMState == VMSTATE_SUSPENDING
                || enmVMState == VMSTATE_SUSPENDING_EXT_LS
                || enmVMState == VMSTATE_SUSPENDING_LS
+               || enmVMState == VMSTATE_RESETTING
+               || enmVMState == VMSTATE_RESETTING_LS
                || enmVMState == VMSTATE_POWERING_OFF
                || enmVMState == VMSTATE_POWERING_OFF_LS,
@@ -2367,4 +2369,6 @@
         || enmVMState == VMSTATE_SUSPENDING_EXT_LS
         || enmVMState == VMSTATE_SUSPENDING_LS
+        || enmVMState == VMSTATE_RESETTING
+        || enmVMState == VMSTATE_RESETTING_LS
         || enmVMState == VMSTATE_POWERING_OFF
         || enmVMState == VMSTATE_POWERING_OFF_LS)
Index: /trunk/src/VBox/VMM/PDMDriver.cpp
===================================================================
--- /trunk/src/VBox/VMM/PDMDriver.cpp	(revision 24743)
+++ /trunk/src/VBox/VMM/PDMDriver.cpp	(revision 24744)
@@ -1029,9 +1029,11 @@
     AssertStmt(pfnAsyncNotify, rc = VERR_INVALID_PARAMETER);
     AssertStmt(!pDrvIns->Internal.s.pfnAsyncNotify, rc = VERR_WRONG_ORDER);
-    AssertStmt(pDrvIns->Internal.s.fVMSuspended, rc = VERR_WRONG_ORDER);
+    AssertStmt(pDrvIns->Internal.s.fVMSuspended || pDrvIns->Internal.s.fVMReset, rc = VERR_WRONG_ORDER);
     VMSTATE enmVMState = VMR3GetState(pDrvIns->Internal.s.pVM);
     AssertStmt(   enmVMState == VMSTATE_SUSPENDING
                || enmVMState == VMSTATE_SUSPENDING_EXT_LS
                || enmVMState == VMSTATE_SUSPENDING_LS
+               || enmVMState == VMSTATE_RESETTING
+               || enmVMState == VMSTATE_RESETTING_LS
                || enmVMState == VMSTATE_POWERING_OFF
                || enmVMState == VMSTATE_POWERING_OFF_LS,
@@ -1056,4 +1058,6 @@
         || enmVMState == VMSTATE_SUSPENDING_EXT_LS
         || enmVMState == VMSTATE_SUSPENDING_LS
+        || enmVMState == VMSTATE_RESETTING
+        || enmVMState == VMSTATE_RESETTING_LS
         || enmVMState == VMSTATE_POWERING_OFF
         || enmVMState == VMSTATE_POWERING_OFF_LS)
Index: /trunk/src/VBox/VMM/PDMInternal.h
===================================================================
--- /trunk/src/VBox/VMM/PDMInternal.h	(revision 24743)
+++ /trunk/src/VBox/VMM/PDMInternal.h	(revision 24744)
@@ -142,4 +142,6 @@
  * a failure (already resumed/powered-on devices are suspended). */
 #define PDMDEVINSINT_FLAGS_SUSPENDED     RT_BIT_32(1)
+/** Indicates that the device has been reset already.  Used by PDMR3Reset. */
+#define PDMDEVINSINT_FLAGS_RESET         RT_BIT_32(2)
 /** @} */
 
@@ -178,7 +180,9 @@
     /** The port number that we're connected to. */
     uint32_t                        iPort;
-    /** Indicates that the driver hasn't been powered on or resumed.
+    /** Indicates that the USB device hasn't been powered on or resumed.
      * See PDMDEVINSINT_FLAGS_SUSPENDED. */
     bool                            fVMSuspended;
+    /** Indicates that the USB device has been reset. */
+    bool                            fVMReset;
     /** Pointer to the asynchronous notification callback set while in
      * FNPDMDEVSUSPEND or FNPDMDEVPOWEROFF. */
@@ -210,4 +214,6 @@
      * See PDMDEVINSINT_FLAGS_SUSPENDED. */
     bool                            fVMSuspended;
+    /** Indicates that the driver has been reset already. */
+    bool                            fVMReset;
     /** Pointer to the asynchronous notification callback set while in
      * PDMUSBREG::pfnVMSuspend or PDMUSBREG::pfnVMPowerOff. */
