Index: /trunk/src/VBox/HostDrivers/Support/SUPDrv.cpp
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/SUPDrv.cpp	(revision 86511)
+++ /trunk/src/VBox/HostDrivers/Support/SUPDrv.cpp	(revision 86512)
@@ -1813,4 +1813,6 @@
                                    ("SUP_IOCTL_LDR_LOAD: offPrevEnd %#lx cbImageBits %#lx\n", (long)i, (long)offPrevEnd, (long)pReq->u.In.cbImageBits));
             }
+            REQ_CHECK_EXPR_FMT(!(pReq->u.In.fFlags & ~SUPLDRLOAD_F_VALID_MASK),
+                               ("SUP_IOCTL_LDR_LOAD: fFlags=%#x\n", (unsigned)pReq->u.In.fFlags));
 
             /* execute */
@@ -5134,4 +5136,5 @@
     pImage->cUsage          = 1;
     pImage->pDevExt         = pDevExt;
+    pImage->pImageImport    = NULL;
     pImage->uMagic          = SUPDRVLDRIMAGE_MAGIC;
     memcpy(pImage->szName, pReq->u.In.szName, cchName + 1);
@@ -5295,4 +5298,5 @@
     PSUPDRVLDRUSAGE pUsage;
     PSUPDRVLDRIMAGE pImage;
+    PSUPDRVLDRIMAGE pImageImport;
     int             rc;
     SUPDRV_CHECK_SMAP_SETUP();
@@ -5342,4 +5346,27 @@
         supdrvLdrUnlock(pDevExt);
         return supdrvLdrLoadError(VERR_PERMISSION_DENIED, pReq, "Loader is locked down");
+    }
+
+    /*
+     * If the new image is a dependant of VMMR0.r0, resolve it via the
+     * caller's usage list and make sure it's in ready state.
+     */
+    pImageImport = NULL;
+    if (pReq->u.In.fFlags & SUPLDRLOAD_F_DEP_VMMR0)
+    {
+        PSUPDRVLDRUSAGE pUsageDependency = pSession->pLdrUsage;
+        while (pUsageDependency && pUsageDependency->pImage->pvImage != pDevExt->pvVMMR0)
+            pUsageDependency = pUsageDependency->pNext;
+        if (!pUsageDependency || !pDevExt->pvVMMR0)
+        {
+            supdrvLdrUnlock(pDevExt);
+            return supdrvLdrLoadError(VERR_MODULE_NOT_FOUND, pReq, "VMMR0.r0 not loaded by session");
+        }
+        pImageImport = pUsageDependency->pImage;
+        if (pImageImport->uState != SUP_IOCTL_LDR_LOAD)
+        {
+            supdrvLdrUnlock(pDevExt);
+            return supdrvLdrLoadError(VERR_MODULE_NOT_FOUND, pReq, "VMMR0.r0 is not ready (state %#x)", pImageImport->uState);
+        }
     }
 
@@ -5520,4 +5547,12 @@
     if (RT_SUCCESS(rc))
     {
+        /* Increase the usage counter of any import image. */
+        if (pImageImport)
+        {
+            pImageImport->cUsage++;
+            pImage->pImageImport = pImageImport;
+        }
+
+        /* Done! */
         SUPR0Printf("vboxdrv: %RKv %s\n", pImage->pvImage, pImage->szName);
         pReq->u.Out.uErrorMagic = 0;
@@ -5592,4 +5627,6 @@
     rc = VINF_SUCCESS;
     pImage = pUsage->pImage;
+    Log(("SUP_IOCTL_LDR_FREE: pImage=%p %s cUsage=%d r3=%d r0=%u\n",
+         pImage, pImage->szName, pImage->cUsage, pUsage->cRing3Usage, pUsage->cRing0Usage));
     if (pImage->cUsage <= 1 || pUsage->cRing3Usage + pUsage->cRing0Usage <= 1)
     {
@@ -5991,92 +6028,114 @@
 static void supdrvLdrFree(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage)
 {
-    PSUPDRVLDRIMAGE pImagePrev;
-    LogFlow(("supdrvLdrFree: pImage=%p\n", pImage));
-
-    /*
-     * Warn if we're releasing images while the image loader interface is
-     * locked down -- we won't be able to reload them!
-     */
-    if (pDevExt->fLdrLockedDown)
-        Log(("supdrvLdrFree: Warning: unloading '%s' image, while loader interface is locked down!\n", pImage->szName));
-
-    /* find it - arg. should've used doubly linked list. */
-    Assert(pDevExt->pLdrImages);
-    pImagePrev = NULL;
-    if (pDevExt->pLdrImages != pImage)
-    {
-        pImagePrev = pDevExt->pLdrImages;
-        while (pImagePrev->pNext != pImage)
-            pImagePrev = pImagePrev->pNext;
-        Assert(pImagePrev->pNext == pImage);
-    }
-
-    /* unlink */
-    if (pImagePrev)
-        pImagePrev->pNext = pImage->pNext;
-    else
-        pDevExt->pLdrImages = pImage->pNext;
-
-    /* check if this is VMMR0.r0 unset its entry point pointers. */
-    if (pDevExt->pvVMMR0 == pImage->pvImage)
-        supdrvLdrUnsetVMMR0EPs(pDevExt);
-
-    /* check for objects with destructors in this image. (Shouldn't happen.) */
-    if (pDevExt->pObjs)
-    {
-        unsigned        cObjs = 0;
-        PSUPDRVOBJ      pObj;
-        RTSpinlockAcquire(pDevExt->Spinlock);
-        for (pObj = pDevExt->pObjs; pObj; pObj = pObj->pNext)
-            if (RT_UNLIKELY((uintptr_t)pObj->pfnDestructor - (uintptr_t)pImage->pvImage < pImage->cbImageBits))
-            {
-                pObj->pfnDestructor = NULL;
-                cObjs++;
-            }
-        RTSpinlockRelease(pDevExt->Spinlock);
-        if (cObjs)
-            OSDBGPRINT(("supdrvLdrFree: Image '%s' has %d dangling objects!\n", pImage->szName, cObjs));
-    }
-
-    /* call termination function if fully loaded. */
-    if (    pImage->pfnModuleTerm
-        &&  pImage->uState == SUP_IOCTL_LDR_LOAD)
-    {
-        LogFlow(("supdrvIOCtl_LdrLoad: calling pfnModuleTerm=%p\n", pImage->pfnModuleTerm));
-        pDevExt->hLdrTermThread = RTThreadNativeSelf();
-        pImage->pfnModuleTerm(pImage);
-        pDevExt->hLdrTermThread = NIL_RTNATIVETHREAD;
-    }
-
-    /* Inform the tracing component. */
-    supdrvTracerModuleUnloading(pDevExt, pImage);
-
-    /* Do native unload if appropriate, then inform the native code about the
-       unloading (mainly for non-native loading case). */
-    if (pImage->fNative)
-        supdrvOSLdrUnload(pDevExt, pImage);
-    supdrvOSLdrNotifyUnloaded(pDevExt, pImage);
-
-    /* free the image */
-    pImage->uMagic  = SUPDRVLDRIMAGE_MAGIC_DEAD;
-    pImage->cUsage  = 0;
-    pImage->pDevExt = NULL;
-    pImage->pNext   = NULL;
-    pImage->uState  = SUP_IOCTL_LDR_FREE;
+    unsigned cLoops;
+    for (cLoops = 0; ; cLoops++)
+    {
+        PSUPDRVLDRIMAGE pImagePrev;
+        PSUPDRVLDRIMAGE pImageImport;
+        LogFlow(("supdrvLdrFree: pImage=%p %s [loop %u]\n", pImage, pImage->szName, cLoops));
+        AssertBreak(cLoops < 2);
+
+        /*
+         * Warn if we're releasing images while the image loader interface is
+         * locked down -- we won't be able to reload them!
+         */
+        if (pDevExt->fLdrLockedDown)
+            Log(("supdrvLdrFree: Warning: unloading '%s' image, while loader interface is locked down!\n", pImage->szName));
+
+        /* find it - arg. should've used doubly linked list. */
+        Assert(pDevExt->pLdrImages);
+        pImagePrev = NULL;
+        if (pDevExt->pLdrImages != pImage)
+        {
+            pImagePrev = pDevExt->pLdrImages;
+            while (pImagePrev->pNext != pImage)
+                pImagePrev = pImagePrev->pNext;
+            Assert(pImagePrev->pNext == pImage);
+        }
+
+        /* unlink */
+        if (pImagePrev)
+            pImagePrev->pNext = pImage->pNext;
+        else
+            pDevExt->pLdrImages = pImage->pNext;
+
+        /* check if this is VMMR0.r0 unset its entry point pointers. */
+        if (pDevExt->pvVMMR0 == pImage->pvImage)
+            supdrvLdrUnsetVMMR0EPs(pDevExt);
+
+        /* check for objects with destructors in this image. (Shouldn't happen.) */
+        if (pDevExt->pObjs)
+        {
+            unsigned        cObjs = 0;
+            PSUPDRVOBJ      pObj;
+            RTSpinlockAcquire(pDevExt->Spinlock);
+            for (pObj = pDevExt->pObjs; pObj; pObj = pObj->pNext)
+                if (RT_UNLIKELY((uintptr_t)pObj->pfnDestructor - (uintptr_t)pImage->pvImage < pImage->cbImageBits))
+                {
+                    pObj->pfnDestructor = NULL;
+                    cObjs++;
+                }
+            RTSpinlockRelease(pDevExt->Spinlock);
+            if (cObjs)
+                OSDBGPRINT(("supdrvLdrFree: Image '%s' has %d dangling objects!\n", pImage->szName, cObjs));
+        }
+
+        /* call termination function if fully loaded. */
+        if (    pImage->pfnModuleTerm
+            &&  pImage->uState == SUP_IOCTL_LDR_LOAD)
+        {
+            LogFlow(("supdrvIOCtl_LdrLoad: calling pfnModuleTerm=%p\n", pImage->pfnModuleTerm));
+            pDevExt->hLdrTermThread = RTThreadNativeSelf();
+            pImage->pfnModuleTerm(pImage);
+            pDevExt->hLdrTermThread = NIL_RTNATIVETHREAD;
+        }
+
+        /* Inform the tracing component. */
+        supdrvTracerModuleUnloading(pDevExt, pImage);
+
+        /* Do native unload if appropriate, then inform the native code about the
+           unloading (mainly for non-native loading case). */
+        if (pImage->fNative)
+            supdrvOSLdrUnload(pDevExt, pImage);
+        supdrvOSLdrNotifyUnloaded(pDevExt, pImage);
+
+        /* free the image */
+        pImage->uMagic  = SUPDRVLDRIMAGE_MAGIC_DEAD;
+        pImage->cUsage  = 0;
+        pImage->pDevExt = NULL;
+        pImage->pNext   = NULL;
+        pImage->uState  = SUP_IOCTL_LDR_FREE;
 #ifdef SUPDRV_USE_MEMOBJ_FOR_LDR_IMAGE
-    RTR0MemObjFree(pImage->hMemObjImage, true /*fMappings*/);
-    pImage->hMemObjImage = NIL_RTR0MEMOBJ;
+        RTR0MemObjFree(pImage->hMemObjImage, true /*fMappings*/);
+        pImage->hMemObjImage = NIL_RTR0MEMOBJ;
 #else
-    RTMemExecFree(pImage->pvImageAlloc, pImage->cbImageBits + 31);
-    pImage->pvImageAlloc = NULL;
+        RTMemExecFree(pImage->pvImageAlloc, pImage->cbImageBits + 31);
+        pImage->pvImageAlloc = NULL;
 #endif
-    pImage->pvImage = NULL;
-    RTMemFree(pImage->pachStrTab);
-    pImage->pachStrTab = NULL;
-    RTMemFree(pImage->paSymbols);
-    pImage->paSymbols = NULL;
-    RTMemFree(pImage->paSegments);
-    pImage->paSegments = NULL;
-    RTMemFree(pImage);
+        pImage->pvImage = NULL;
+        RTMemFree(pImage->pachStrTab);
+        pImage->pachStrTab = NULL;
+        RTMemFree(pImage->paSymbols);
+        pImage->paSymbols = NULL;
+        RTMemFree(pImage->paSegments);
+        pImage->paSegments = NULL;
+
+        pImageImport = pImage->pImageImport;
+        pImage->pImageImport = NULL;
+
+        RTMemFree(pImage);
+
+        /*
+         * Deal with any import image.
+         */
+        if (!pImageImport)
+            break;
+        if (pImageImport->cUsage > 1)
+        {
+            pImageImport->cUsage--;
+            break;
+        }
+        pImage = pImageImport;
+    }
 }
 
Index: /trunk/src/VBox/HostDrivers/Support/SUPDrvIOC.h
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/SUPDrvIOC.h	(revision 86511)
+++ /trunk/src/VBox/HostDrivers/Support/SUPDrvIOC.h	(revision 86512)
@@ -222,7 +222,6 @@
  * @todo Pending work on next major version change:
  *          - Nothing.
- * @note 0x002f0000 is used by 6.0. The next version number must be 0x00300000.
- */
-#define SUPDRV_IOC_VERSION                              0x002e0000
+ */
+#define SUPDRV_IOC_VERSION                              0x00300000
 
 /** SUP_IOCTL_COOKIE. */
@@ -482,4 +481,6 @@
             /** Size of image data in achImage. */
             uint32_t        cbImageWithEverything;
+            /** Flags (SUPLDRLOAD_F_XXX). */
+            uint32_t        fFlags;
             /** The image data. */
             uint8_t         abImage[1];
@@ -499,4 +500,8 @@
  * @remarks The value is choosen to be an unlikely init and term address. */
 #define SUPLDRLOAD_ERROR_MAGIC      UINT64_C(0xabcdefef0feddcb9)
+/** The module depends on VMMR0. */
+#define SUPLDRLOAD_F_DEP_VMMR0      RT_BIT_32(0)
+/** Valid flag mask. */
+#define SUPLDRLOAD_F_VALID_MASK     UINT32_C(0x00000001)
 /** @} */
 
Index: /trunk/src/VBox/HostDrivers/Support/SUPDrvInternal.h
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/SUPDrvInternal.h	(revision 86511)
+++ /trunk/src/VBox/HostDrivers/Support/SUPDrvInternal.h	(revision 86512)
@@ -373,4 +373,6 @@
     /** Pointer to the device extension. */
     struct SUPDRVDEVEXT            *pDevExt;
+    /** Image (VMMR0.r0) containing functions/data that this one uses. */
+    struct SUPDRVLDRIMAGE          *pImageImport;
 #ifdef RT_OS_WINDOWS
     /** The section object for the loaded image (fNative=true). */
@@ -558,5 +560,5 @@
      * This takes care of its own locking in an IRQ safe manner. */
     RTHANDLETABLE                   hHandleTable;
-    /** Load usage records. (protected by SUPDRVDEVEXT::mtxLdr) */
+    /** Load usage records (LIFO!). (protected by SUPDRVDEVEXT::mtxLdr) */
     PSUPDRVLDRUSAGE volatile        pLdrUsage;
 
Index: /trunk/src/VBox/HostDrivers/Support/SUPLibLdr.cpp
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/SUPLibLdr.cpp	(revision 86511)
+++ /trunk/src/VBox/HostDrivers/Support/SUPLibLdr.cpp	(revision 86512)
@@ -125,4 +125,5 @@
     const char *pszModule;
     PRTERRINFO  pErrInfo;
+    uint32_t    fLoadReq;               /**< SUPLDRLOAD_F_XXX */
 } SUPLDRRESIMPARGS, *PSUPLDRRESIMPARGS;
 
@@ -187,6 +188,4 @@
      * Check the VMMR0.r0 module if loaded.
      */
-    /** @todo call the SUPR3LoadModule caller.... */
-    /** @todo proper reference counting and such. */
     if (g_pvVMMR0 != NIL_RTR0PTR)
     {
@@ -195,4 +194,5 @@
         {
             *pValue = (uintptr_t)pvValue;
+            pArgs->fLoadReq |= SUPLDRLOAD_F_DEP_VMMR0;
             return VINF_SUCCESS;
         }
@@ -519,5 +519,5 @@
      * Get the image bits.
      */
-    SUPLDRRESIMPARGS Args = { pszModule, pErrInfo };
+    SUPLDRRESIMPARGS Args = { pszModule, pErrInfo, 0 };
     int rc = RTLdrGetBits(hLdrMod, &pLoadReq->u.In.abImage[0], uImageBase, supLoadModuleResolveImport, &Args);
     if (RT_FAILURE(rc))
@@ -659,4 +659,5 @@
     pLoadReq->u.In.cbImageWithEverything      = cbImageWithEverything;
     pLoadReq->u.In.pvImageBase                = uImageBase;
+    pLoadReq->u.In.fFlags                     = Args.fLoadReq;
     if (!g_uSupFakeMode)
     {
