Index: /trunk/include/VBox/sup.h
===================================================================
--- /trunk/include/VBox/sup.h	(revision 49633)
+++ /trunk/include/VBox/sup.h	(revision 49634)
@@ -161,4 +161,32 @@
 
 /**
+ * The result of a modification operation (SUPMSRPROBEROP_MODIFY or
+ * SUPMSRPROBEROP_MODIFY_FASTER).
+ */
+typedef struct SUPMSRPROBERMODIFYRESULT
+{
+    /** The MSR value prior to the modifications.  Valid if fBeforeGp is false */
+    uint64_t        uBefore;
+    /** The value that was written.  Valid if fBeforeGp is false */
+    uint64_t        uWritten;
+    /** The MSR value after the modifications. Valid if AfterGp is false. */
+    uint64_t        uAfter;
+    /** Set if we GPed reading the MSR before the modification. */
+    bool            fBeforeGp;
+    /** Set if we GPed while trying to write the modified value.
+     * This is set when fBeforeGp is true. */
+    bool            fModifyGp;
+    /** Set if we GPed while trying to read the MSR after the modification.
+     * This is set when fBeforeGp is true. */
+    bool            fAfterGp;
+    /** Set if we GPed while trying to restore the MSR after the modification.
+     * This is set when fBeforeGp is true. */
+    bool            fRestoreGp;
+    /** Structure size alignment padding. */
+    bool            afReserved[4];
+} SUPMSRPROBERMODIFYRESULT, *PSUPMSRPROBERMODIFYRESULT;
+
+
+/**
  * The CPU state.
  */
@@ -1295,4 +1323,63 @@
 SUPDECL(void)  SUPTracerFireProbe(struct VTGPROBELOC *pVtgProbeLoc, uintptr_t uArg0, uintptr_t uArg1, uintptr_t uArg2,
                                   uintptr_t uArg3, uintptr_t uArg4);
+
+
+/**
+ * Attempts to read the value of an MSR.
+ *
+ * @returns VBox status code.
+ * @param   uMsr                The MSR to read.
+ * @param   idCpu               The CPU to read it on, NIL_RTCPUID if it doesn't
+ *                              matter which CPU.
+ * @param   puValue             Where to return the value.
+ * @param   pfGp                Where to store the \#GP indicator for the read
+ *                              operation.
+ */
+SUPR3DECL(int) SUPR3MsrProberRead(uint32_t uMsr, RTCPUID idCpu, uint64_t *puValue, bool *pfGp);
+
+/**
+ * Attempts to write to an MSR.
+ *
+ * @returns VBox status code.
+ * @param   uMsr                The MSR to write to.
+ * @param   idCpu               The CPU to wrtie it on, NIL_RTCPUID if it
+ *                              doesn't matter which CPU.
+ * @param   uValue              The value to write.
+ * @param   pfGp                Where to store the \#GP indicator for the write
+ *                              operation.
+ */
+SUPR3DECL(int) SUPR3MsrProberWrite(uint32_t uMsr, RTCPUID idCpu, uint64_t uValue, bool *pfGp);
+
+/**
+ * Attempts to modify the value of an MSR.
+ *
+ * @returns VBox status code.
+ * @param   uMsr                The MSR to modify.
+ * @param   idCpu               The CPU to modify it on, NIL_RTCPUID if it
+ *                              doesn't matter which CPU.
+ * @param   fAndMask            The bits to keep in the current MSR value.
+ * @param   fOrMask             The bits to set before writing.
+ * @param   pResult             The result buffer.
+ */
+SUPR3DECL(int) SUPR3MsrProberModify(uint32_t uMsr, RTCPUID idCpu, uint64_t fAndMask, uint64_t fOrMask,
+                                    PSUPMSRPROBERMODIFYRESULT pResult);
+
+/**
+ * Attempts to modify the value of an MSR, extended version.
+ *
+ * @returns VBox status code.
+ * @param   uMsr                The MSR to modify.
+ * @param   idCpu               The CPU to modify it on, NIL_RTCPUID if it
+ *                              doesn't matter which CPU.
+ * @param   fAndMask            The bits to keep in the current MSR value.
+ * @param   fOrMask             The bits to set before writing.
+ * @param   fFaster             If set to @c true some cache/tlb invalidation is
+ *                              skipped, otherwise behave like
+ *                              SUPR3MsrProberModify.
+ * @param   pResult             The result buffer.
+ */
+SUPR3DECL(int) SUPR3MsrProberModifyEx(uint32_t uMsr, RTCPUID idCpu, uint64_t fAndMask, uint64_t fOrMask, bool fFaster,
+                                      PSUPMSRPROBERMODIFYRESULT pResult);
+
 /** @} */
 #endif /* IN_RING3 */
Index: /trunk/src/VBox/HostDrivers/Support/Makefile.kmk
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/Makefile.kmk	(revision 49633)
+++ /trunk/src/VBox/HostDrivers/Support/Makefile.kmk	(revision 49634)
@@ -83,4 +83,5 @@
 SUPR3_SOURCES       = \
 	SUPLib.cpp \
+	SUPLibLdr.cpp \
 	SUPLibSem.cpp \
 	SUPLibTracerA.asm \
Index: /trunk/src/VBox/HostDrivers/Support/SUPDrv.c
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/SUPDrv.c	(revision 49633)
+++ /trunk/src/VBox/HostDrivers/Support/SUPDrv.c	(revision 49634)
@@ -125,4 +125,5 @@
 static int                  supdrvIOCtl_CallServiceModule(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PSUPCALLSERVICE pReq);
 static int                  supdrvIOCtl_LoggerSettings(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PSUPLOGGERSETTINGS pReq);
+static int                  supdrvIOCtl_MsrProber(PSUPDRVDEVEXT pDevExt, PSUPMSRPROBER pReq);
 static int                  supdrvGipCreate(PSUPDRVDEVEXT pDevExt);
 static void                 supdrvGipDestroy(PSUPDRVDEVEXT pDevExt);
@@ -1891,4 +1892,17 @@
         }
 
+        case SUP_CTL_CODE_NO_SIZE(SUP_IOCTL_MSR_PROBER):
+        {
+            /* validate */
+            PSUPMSRPROBER pReq = (PSUPMSRPROBER)pReqHdr;
+            REQ_CHECK_SIZES(SUP_IOCTL_MSR_PROBER);
+            REQ_CHECK_EXPR(SUP_IOCTL_MSR_PROBER,
+                           pReq->u.In.enmOp > SUPMSRPROBEROP_INVALID && pReq->u.In.enmOp < SUPMSRPROBEROP_END);
+
+            pReqHdr->rc = supdrvIOCtl_MsrProber(pDevExt, pReq);
+            return 0;
+        }
+
+
         default:
             Log(("Unknown IOCTL %#lx\n", (long)uIOCtl));
@@ -5137,4 +5151,64 @@
 
 /**
+ * Implements the MSR prober operations.
+ *
+ * @returns VBox status code.
+ * @param   pDevExt     The device extension.
+ * @param   pReq        The request.
+ */
+static int supdrvIOCtl_MsrProber(PSUPDRVDEVEXT pDevExt, PSUPMSRPROBER pReq)
+{
+#ifdef SUPDRV_WITH_MSR_PROBER
+    RTCPUID const idCpu = pReq->u.In.idCpu == UINT32_MAX ? NIL_RTCPUID : pReq->u.In.idCpu;
+    int rc;
+
+    switch (pReq->u.In.enmOp)
+    {
+        case SUPMSRPROBEROP_READ:
+        {
+            uint64_t uValue;
+            rc = supdrvOSMsrProberRead(pReq->u.In.uMsr, idCpu, &uValue);
+            if (RT_SUCCESS(rc))
+            {
+                pReq->u.Out.uResults.Read.uValue = uValue;
+                pReq->u.Out.uResults.Read.fGp    = false;
+            }
+            else if (rc == VERR_ACCESS_DENIED)
+            {
+                pReq->u.Out.uResults.Read.uValue = 0;
+                pReq->u.Out.uResults.Read.fGp    = true;
+                rc  = VINF_SUCCESS;
+            }
+            break;
+        }
+
+        case SUPMSRPROBEROP_WRITE:
+            rc = supdrvOSMsrProberWrite(pReq->u.In.uMsr, idCpu, pReq->u.In.uArgs.Write.uToWrite);
+            if (RT_SUCCESS(rc))
+                pReq->u.Out.uResults.Write.fGp   = false;
+            else if (rc == VERR_ACCESS_DENIED)
+            {
+                pReq->u.Out.uResults.Read.fGp    = true;
+                rc  = VINF_SUCCESS;
+            }
+            break;
+
+        case SUPMSRPROBEROP_MODIFY:
+        case SUPMSRPROBEROP_MODIFY_FASTER:
+            rc = supdrvOSMsrProberModify(idCpu, pReq);
+            break;
+
+        default:
+            return VERR_INVALID_FUNCTION;
+    }
+    return rc;
+#else
+    return VERR_NOT_IMPLEMENTED;
+#endif
+}
+
+
+
+/**
  * Creates the GIP.
  *
Index: /trunk/src/VBox/HostDrivers/Support/SUPDrvIOC.h
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/SUPDrvIOC.h	(revision 49633)
+++ /trunk/src/VBox/HostDrivers/Support/SUPDrvIOC.h	(revision 49634)
@@ -102,5 +102,5 @@
 #define SUP_IOCTL_FAST_DO_RAW_RUN               SUP_CTL_CODE_FAST(64)
 /** Fast path IOCtl: VMMR0_DO_HM_RUN */
-#define SUP_IOCTL_FAST_DO_HM_RUN             SUP_CTL_CODE_FAST(65)
+#define SUP_IOCTL_FAST_DO_HM_RUN                SUP_CTL_CODE_FAST(65)
 /** Just a NOP call for profiling the latency of a fast ioctl call to VMMR0. */
 #define SUP_IOCTL_FAST_DO_NOP                   SUP_CTL_CODE_FAST(66)
@@ -194,5 +194,5 @@
  *          - Remove RTSpinlockReleaseNoInts.
  */
-#define SUPDRV_IOC_VERSION                              0x001a0005
+#define SUPDRV_IOC_VERSION                              0x001a0006
 
 /** SUP_IOCTL_COOKIE. */
@@ -1333,4 +1333,110 @@
 
 
+/** @name SUP_IOCTL_MSR_PROBER
+ * MSR probing interface, not available in normal builds.
+ *
+ * @{
+ */
+#define SUP_IOCTL_MSR_PROBER                        SUP_CTL_CODE_SIZE(34, SUP_IOCTL_MSR_PROBER_SIZE)
+#define SUP_IOCTL_MSR_PROBER_SIZE                   sizeof(SUPMSRPROBER)
+#define SUP_IOCTL_MSR_PROBER_SIZE_IN                sizeof(SUPMSRPROBER)
+#define SUP_IOCTL_MSR_PROBER_SIZE_OUT               sizeof(SUPMSRPROBER)
+
+typedef enum SUPMSRPROBEROP
+{
+    SUPMSRPROBEROP_INVALID = 0,                     /**< The customary invalid zero value. */
+    SUPMSRPROBEROP_READ,                            /**< Read an MSR. */
+    SUPMSRPROBEROP_WRITE,                           /**< Write a value to an MSR (use with care!). */
+    SUPMSRPROBEROP_MODIFY,                          /**< Read-modify-restore-flushall. */
+    SUPMSRPROBEROP_MODIFY_FASTER,                   /**< Read-modify-restore, skip the flushing. */
+    SUPMSRPROBEROP_END,                             /**< End of valid values. */
+    SUPMSRPROBEROP_32BIT_HACK = 0x7fffffff          /**< The customary 32-bit type hack. */
+} SUPMSRPROBEROP;
+
+typedef struct SUPMSRPROBER
+{
+    /** The header. */
+    SUPREQHDR               Hdr;
+
+    /** Input/output union. */
+    union
+    {
+        /** Inputs.  */
+        struct
+        {
+            /** The operation. */
+            SUPMSRPROBEROP          enmOp;
+            /** The MSR to test. */
+            uint32_t                uMsr;
+            /** The CPU to perform the operation on.
+             * Use UINT32_MAX to indicate that any CPU will do. */
+            uint32_t                idCpu;
+            /** Alignment padding. */
+            uint32_t                u32Padding;
+            /** Operation specific arguments. */
+            union
+            {
+                /* SUPMSRPROBEROP_READ takes no extra arguments. */
+
+                /** For SUPMSRPROBEROP_WRITE. */
+                struct
+                {
+                    /** The value to write. */
+                    uint64_t        uToWrite;
+                } Write;
+
+                /** For SUPMSRPROBEROP_MODIFY and SUPMSRPROBEROP_MODIFY_FASTER. */
+                struct
+                {
+                    /** The value to AND the current MSR value with to construct the value to
+                     *  write.  This applied first. */
+                    uint64_t        fAndMask;
+                    /** The value to OR the result of the above mentioned AND operation with
+                     * attempting to modify the MSR. */
+                    uint64_t        fOrMask;
+                } Modify;
+
+                /** Reserve space for the future.. */
+                uint64_t        auPadding[3];
+            } uArgs;
+        } In;
+
+        /** Outputs. */
+        struct
+        {
+            /** Operation specific results. */
+            union
+            {
+                /** For SUPMSRPROBEROP_READ. */
+                struct
+                {
+                    /** The value we've read. */
+                    uint64_t        uValue;
+                    /** Set if we GPed while reading it. */
+                    bool            fGp;
+                } Read;
+
+                /** For SUPMSRPROBEROP_WRITE. */
+                struct
+                {
+                    /** Set if we GPed while writing it. */
+                    bool            fGp;
+                } Write;
+
+                /** For SUPMSRPROBEROP_MODIFY and SUPMSRPROBEROP_MODIFY_FASTER. */
+                SUPMSRPROBERMODIFYRESULT Modify;
+
+                /** Size padding/aligning. */
+                uint64_t        auPadding[5];
+            } uResults;
+        } Out;
+    } u;
+} SUPMSRPROBER, *PSUPMSRPROBER;
+AssertCompileMemberAlignment(SUPMSRPROBER, u, 8);
+AssertCompileMemberAlignment(SUPMSRPROBER, u.In.uArgs, 8);
+AssertCompileMembersSameSizeAndOffset(SUPMSRPROBER, u.In, SUPMSRPROBER, u.Out);
+/** @} */
+
+
 #pragma pack()                          /* paranoia */
 
Index: /trunk/src/VBox/HostDrivers/Support/SUPDrvInternal.h
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/SUPDrvInternal.h	(revision 49633)
+++ /trunk/src/VBox/HostDrivers/Support/SUPDrvInternal.h	(revision 49634)
@@ -209,4 +209,20 @@
     (   VALID_PTR(pDevExt)\
      && pDevExt->u32Cookie == BIRD)
+
+
+/** @def SUPDRV_WITH_MSR_PROBER
+ * Enables the SUP_IOCTL_MSR_PROBER function.
+ * By default, only enabled in DEBUG builds as it's a sensitive feature.
+ */
+#if defined(DEBUG) && !defined(SUPDRV_WITH_MSR_PROBER) && !defined(SUPDRV_WITHOUT_MSR_PROBER)
+# define SUPDRV_WITH_MSR_PROBER
+#endif
+
+/** @def SUPDRV_WITHOUT_MSR_PROBER
+ * Executive overide for disabling the SUP_IOCTL_MSR_PROBER function.
+ */
+#ifdef SUPDRV_WITHOUT_MSR_PROBER
+# undef SUPDRV_WITH_MSR_PROBER
+#endif
 
 
@@ -685,4 +701,53 @@
 
 
+#ifdef SUPDRV_WITH_MSR_PROBER
+
+/**
+ * Tries to read an MSR.
+ *
+ * @returns One of the listed VBox status codes.
+ * @retval  VINF_SUCCESS if read successfully, value in *puValue.
+ * @retval  VERR_ACCESS_DENIED if we couldn't read it (GP).
+ * @retval  VERR_NOT_SUPPORTED if not supported.
+ *
+ * @param   uMsr                The MSR to read from.
+ * @param   idCpu               The CPU to read the MSR on. NIL_RTCPUID
+ *                              indicates any suitable CPU.
+ * @param   puValue             Where to return the value.
+ */
+int VBOXCALL    supdrvOSMsrProberRead(uint32_t uMsr, RTCPUID idCpu, uint64_t *puValue);
+
+/**
+ * Tries to write an MSR.
+ *
+ * @returns One of the listed VBox status codes.
+ * @retval  VINF_SUCCESS if written successfully.
+ * @retval  VERR_ACCESS_DENIED if we couldn't write the value to it (GP).
+ * @retval  VERR_NOT_SUPPORTED if not supported.
+ *
+ * @param   uMsr                The MSR to write to.
+ * @param   idCpu               The CPU to write the MSR on. NIL_RTCPUID
+ *                              indicates any suitable CPU.
+ * @param   uValue              The value to write.
+ */
+int VBOXCALL    supdrvOSMsrProberWrite(uint32_t uMsr, RTCPUID idCpu, uint64_t uValue);
+
+/**
+ * Tries to modify an MSR value.
+ *
+ * @returns One of the listed VBox status codes.
+ * @retval  VINF_SUCCESS if succeeded.
+ * @retval  VERR_NOT_SUPPORTED if not supported.
+ *
+ * @param   idCpu               The CPU to modify the MSR on. NIL_RTCPUID
+ *                              indicates any suitable CPU.
+ * @param   pReq                The request packet with input arguments and
+ *                              where to store the results.
+ */
+int VBOXCALL    supdrvOSMsrProberModify(RTCPUID idCpu, PSUPMSRPROBER pReq);
+
+#endif /* SUPDRV_WITH_MSR_PROBER */
+
+
 /*******************************************************************************
 *   Shared Functions                                                           *
Index: /trunk/src/VBox/HostDrivers/Support/SUPLib.cpp
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/SUPLib.cpp	(revision 49633)
+++ /trunk/src/VBox/HostDrivers/Support/SUPLib.cpp	(revision 49634)
@@ -68,6 +68,6 @@
 #include <iprt/x86.h>
 
+#include "SUPDrvIOC.h"
 #include "SUPLibInternal.h"
-#include "SUPDrvIOC.h"
 
 
@@ -117,5 +117,5 @@
 DECLEXPORT(PSUPGLOBALINFOPAGE)  g_pSUPGlobalInfoPage;
 /** Address of the ring-0 mapping of the GIP. */
-static PSUPGLOBALINFOPAGE       g_pSUPGlobalInfoPageR0;
+PSUPGLOBALINFOPAGE              g_pSUPGlobalInfoPageR0;
 /** The physical address of the GIP. */
 static RTHCPHYS                 g_HCPhysSUPGlobalInfoPage = NIL_RTHCPHYS;
@@ -128,5 +128,5 @@
 PSUPDRVSESSION                  g_pSession;
 /** R0 SUP Functions used for resolving referenced to the SUPR0 module. */
-static PSUPQUERYFUNCS           g_pFunctions;
+PSUPQUERYFUNCS                  g_pSupFunctions;
 
 /** VMMR0 Load Address. */
@@ -135,5 +135,5 @@
 static bool                     g_fSupportsPageAllocNoKernel = true;
 /** Fake mode indicator. (~0 at first, 0 or 1 after first test) */
-static uint32_t                 g_u32FakeMode = ~0;
+uint32_t                        g_uSupFakeMode = ~0;
 
 
@@ -248,13 +248,13 @@
      * we haven't ported the support driver to.
      */
-    if (g_u32FakeMode == ~0U)
+    if (g_uSupFakeMode == ~0U)
     {
         const char *psz = RTEnvGet("VBOX_SUPLIB_FAKE");
         if (psz && !strcmp(psz, "fake"))
-            ASMAtomicCmpXchgU32(&g_u32FakeMode, 1, ~0U);
+            ASMAtomicCmpXchgU32(&g_uSupFakeMode, 1, ~0U);
         else
-            ASMAtomicCmpXchgU32(&g_u32FakeMode, 0, ~0U);
-    }
-    if (RT_UNLIKELY(g_u32FakeMode))
+            ASMAtomicCmpXchgU32(&g_uSupFakeMode, 0, ~0U);
+    }
+    if (RT_UNLIKELY(g_uSupFakeMode))
         return supInitFake(ppSession);
 
@@ -353,5 +353,5 @@
                     g_u32SessionCookie  = CookieReq.u.Out.u32SessionCookie;
                     g_pSession          = CookieReq.u.Out.pSession;
-                    g_pFunctions        = pFuncsReq;
+                    g_pSupFunctions  = pFuncsReq;
                     if (ppSession)
                         *ppSession = CookieReq.u.Out.pSession;
@@ -505,10 +505,10 @@
 
     /* fake r0 functions. */
-    g_pFunctions = (PSUPQUERYFUNCS)RTMemAllocZ(SUP_IOCTL_QUERY_FUNCS_SIZE(RT_ELEMENTS(s_aFakeFunctions)));
-    if (g_pFunctions)
-    {
-        g_pFunctions->u.Out.cFunctions = RT_ELEMENTS(s_aFakeFunctions);
-        memcpy(&g_pFunctions->u.Out.aFunctions[0], &s_aFakeFunctions[0], sizeof(s_aFakeFunctions));
-        g_pSession = (PSUPDRVSESSION)(void *)g_pFunctions;
+    g_pSupFunctions = (PSUPQUERYFUNCS)RTMemAllocZ(SUP_IOCTL_QUERY_FUNCS_SIZE(RT_ELEMENTS(s_aFakeFunctions)));
+    if (g_pSupFunctions)
+    {
+        g_pSupFunctions->u.Out.cFunctions = RT_ELEMENTS(s_aFakeFunctions);
+        memcpy(&g_pSupFunctions->u.Out.aFunctions[0], &s_aFakeFunctions[0], sizeof(s_aFakeFunctions));
+        g_pSession = (PSUPDRVSESSION)(void *)g_pSupFunctions;
         if (ppSession)
             *ppSession = g_pSession;
@@ -524,6 +524,6 @@
         }
 
-        RTMemFree(g_pFunctions);
-        g_pFunctions = NULL;
+        RTMemFree(g_pSupFunctions);
+        g_pSupFunctions = NULL;
     }
     return VERR_NO_MEMORY;
@@ -574,5 +574,5 @@
 {
     /* fake */
-    if (RT_UNLIKELY(g_u32FakeMode))
+    if (RT_UNLIKELY(g_uSupFakeMode))
 #ifdef RT_ARCH_AMD64
         return SUPPAGINGMODE_AMD64_GLOBAL_NX;
@@ -640,5 +640,5 @@
 
     /* fake */
-    if (RT_UNLIKELY(g_u32FakeMode))
+    if (RT_UNLIKELY(g_uSupFakeMode))
         return supCallVMMR0ExFake(pVMR0, uOperation, u64Arg, pReqHdr);
 
@@ -731,5 +731,5 @@
 SUPR3DECL(int) SUPR3SetVMForFastIOCtl(PVMR0 pVMR0)
 {
-    if (RT_UNLIKELY(g_u32FakeMode))
+    if (RT_UNLIKELY(g_uSupFakeMode))
         return VINF_SUCCESS;
 
@@ -755,5 +755,5 @@
 
     /* fake */
-    if (RT_UNLIKELY(g_u32FakeMode))
+    if (RT_UNLIKELY(g_uSupFakeMode))
         return VERR_NOT_SUPPORTED;
 
@@ -956,5 +956,5 @@
 
     /* fake */
-    if (RT_UNLIKELY(g_u32FakeMode))
+    if (RT_UNLIKELY(g_uSupFakeMode))
     {
         RTHCPHYS    Phys = (uintptr_t)pvStart + PAGE_SIZE * 1024;
@@ -1017,5 +1017,5 @@
 
     /* fake */
-    if (RT_UNLIKELY(g_u32FakeMode))
+    if (RT_UNLIKELY(g_uSupFakeMode))
         return VINF_SUCCESS;
 
@@ -1072,5 +1072,5 @@
 
     /* fake */
-    if (RT_UNLIKELY(g_u32FakeMode))
+    if (RT_UNLIKELY(g_uSupFakeMode))
     {
         void *pv = RTMemPageAllocZ(cPages * PAGE_SIZE);
@@ -1165,5 +1165,5 @@
 
     /* fake */
-    if (RT_UNLIKELY(g_u32FakeMode))
+    if (RT_UNLIKELY(g_uSupFakeMode))
         return VERR_NOT_SUPPORTED;
 
@@ -1202,5 +1202,5 @@
 
     /* fake */
-    if (RT_UNLIKELY(g_u32FakeMode))
+    if (RT_UNLIKELY(g_uSupFakeMode))
         return RTMemProtect((uint8_t *)pvR3 + off, cb, fProt);
 
@@ -1242,5 +1242,5 @@
 
     /* fake */
-    if (RT_UNLIKELY(g_u32FakeMode))
+    if (RT_UNLIKELY(g_uSupFakeMode))
     {
         RTMemPageFree(pvPages, cPages * PAGE_SIZE);
@@ -1291,5 +1291,5 @@
 
     /* fake */
-    if (RT_UNLIKELY(g_u32FakeMode))
+    if (RT_UNLIKELY(g_uSupFakeMode))
     {
         void *pv = RTMemPageAllocZ(cPages * PAGE_SIZE);
@@ -1340,5 +1340,5 @@
 
     /* fake */
-    if (RT_UNLIKELY(g_u32FakeMode))
+    if (RT_UNLIKELY(g_uSupFakeMode))
     {
         RTMemPageFree(pv, cPages * PAGE_SIZE);
@@ -1375,5 +1375,5 @@
 
     /* fake */
-    if (RT_UNLIKELY(g_u32FakeMode))
+    if (RT_UNLIKELY(g_uSupFakeMode))
     {
         *ppvPages = RTMemPageAllocZ((size_t)cPages * PAGE_SIZE);
@@ -1443,5 +1443,5 @@
 
     /* fake */
-    if (RT_UNLIKELY(g_u32FakeMode))
+    if (RT_UNLIKELY(g_uSupFakeMode))
     {
         RTMemPageFree(pv, cPages * PAGE_SIZE);
@@ -1596,549 +1596,4 @@
 
 
-SUPR3DECL(int) SUPR3LoadModule(const char *pszFilename, const char *pszModule, void **ppvImageBase, PRTERRINFO pErrInfo)
-{
-    /*
-     * Check that the module can be trusted.
-     */
-    int rc = SUPR3HardenedVerifyPlugIn(pszFilename, pErrInfo);
-    if (RT_SUCCESS(rc))
-    {
-        rc = supLoadModule(pszFilename, pszModule, NULL, ppvImageBase);
-        if (RT_FAILURE(rc))
-            RTErrInfoSetF(pErrInfo, rc, "SUPR3LoadModule: supLoadModule returned %Rrc", rc);
-    }
-    return rc;
-}
-
-
-SUPR3DECL(int) SUPR3LoadServiceModule(const char *pszFilename, const char *pszModule,
-                                      const char *pszSrvReqHandler, void **ppvImageBase)
-{
-    AssertPtrReturn(pszSrvReqHandler, VERR_INVALID_PARAMETER);
-
-    /*
-     * Check that the module can be trusted.
-     */
-    int rc = SUPR3HardenedVerifyPlugIn(pszFilename, NULL /*pErrInfo*/);
-    if (RT_SUCCESS(rc))
-        rc = supLoadModule(pszFilename, pszModule, pszSrvReqHandler, ppvImageBase);
-    else
-        LogRel(("SUPR3LoadServiceModule: Verification of \"%s\" failed, rc=%Rrc\n", rc));
-    return rc;
-}
-
-
-/**
- * Resolve an external symbol during RTLdrGetBits().
- *
- * @returns VBox status code.
- * @param   hLdrMod         The loader module handle.
- * @param   pszModule       Module name.
- * @param   pszSymbol       Symbol name, NULL if uSymbol should be used.
- * @param   uSymbol         Symbol ordinal, ~0 if pszSymbol should be used.
- * @param   pValue          Where to store the symbol value (address).
- * @param   pvUser          User argument.
- */
-static DECLCALLBACK(int) supLoadModuleResolveImport(RTLDRMOD hLdrMod, const char *pszModule,
-                                                    const char *pszSymbol, unsigned uSymbol, RTUINTPTR *pValue, void *pvUser)
-{
-    NOREF(hLdrMod); NOREF(pvUser); NOREF(uSymbol);
-    AssertPtr(pValue);
-    AssertPtr(pvUser);
-
-    /*
-     * Only SUPR0 and VMMR0.r0
-     */
-    if (    pszModule
-        &&  *pszModule
-        &&  strcmp(pszModule, "VBoxDrv.sys")
-        &&  strcmp(pszModule, "VMMR0.r0"))
-    {
-        AssertMsgFailed(("%s is importing from %s! (expected 'SUPR0.dll' or 'VMMR0.r0', case-sensitive)\n", pvUser, pszModule));
-        return VERR_SYMBOL_NOT_FOUND;
-    }
-
-    /*
-     * No ordinals.
-     */
-    if (pszSymbol < (const char*)0x10000)
-    {
-        AssertMsgFailed(("%s is importing by ordinal (ord=%d)\n", pvUser, (int)(uintptr_t)pszSymbol));
-        return VERR_SYMBOL_NOT_FOUND;
-    }
-
-    /*
-     * Lookup symbol.
-     */
-    /** @todo is this actually used??? */
-    /* skip the 64-bit ELF import prefix first. */
-    if (!strncmp(pszSymbol, RT_STR_TUPLE("SUPR0$")))
-        pszSymbol += sizeof("SUPR0$") - 1;
-
-    /*
-     * Check the VMMR0.r0 module if loaded.
-     */
-    /** @todo call the SUPR3LoadModule caller.... */
-    /** @todo proper reference counting and such. */
-    if (g_pvVMMR0 != NIL_RTR0PTR)
-    {
-        void *pvValue;
-        if (!SUPR3GetSymbolR0((void *)g_pvVMMR0, pszSymbol, &pvValue))
-        {
-            *pValue = (uintptr_t)pvValue;
-            return VINF_SUCCESS;
-        }
-    }
-
-    /* iterate the function table. */
-    int c = g_pFunctions->u.Out.cFunctions;
-    PSUPFUNC pFunc = &g_pFunctions->u.Out.aFunctions[0];
-    while (c-- > 0)
-    {
-        if (!strcmp(pFunc->szName, pszSymbol))
-        {
-            *pValue = (uintptr_t)pFunc->pfn;
-            return VINF_SUCCESS;
-        }
-        pFunc++;
-    }
-
-    /*
-     * The GIP.
-     */
-    if (    pszSymbol
-        &&  g_pSUPGlobalInfoPage
-        &&  g_pSUPGlobalInfoPageR0
-        &&  !strcmp(pszSymbol, "g_SUPGlobalInfoPage")
-       )
-    {
-        *pValue = (uintptr_t)g_pSUPGlobalInfoPageR0;
-        return VINF_SUCCESS;
-    }
-
-    /*
-     * Symbols that are undefined by convention.
-     */
-#ifdef RT_OS_SOLARIS
-    static const char * const s_apszConvSyms[] =
-    {
-        "", "mod_getctl",
-        "", "mod_install",
-        "", "mod_remove",
-        "", "mod_info",
-        "", "mod_miscops",
-    };
-    for (unsigned i = 0; i < RT_ELEMENTS(s_apszConvSyms); i += 2)
-    {
-        if (   !RTStrCmp(s_apszConvSyms[i],     pszModule)
-            && !RTStrCmp(s_apszConvSyms[i + 1], pszSymbol))
-        {
-            *pValue = ~(uintptr_t)0;
-            return VINF_SUCCESS;
-        }
-    }
-#endif
-
-    /*
-     * Despair.
-     */
-    c = g_pFunctions->u.Out.cFunctions;
-    pFunc = &g_pFunctions->u.Out.aFunctions[0];
-    while (c-- > 0)
-    {
-        RTAssertMsg2Weak("%d: %s\n", g_pFunctions->u.Out.cFunctions - c, pFunc->szName);
-        pFunc++;
-    }
-
-    AssertLogRelMsgFailed(("%s is importing %s which we couldn't find\n", pvUser, pszSymbol));
-    if (g_u32FakeMode)
-    {
-        *pValue = 0xdeadbeef;
-        return VINF_SUCCESS;
-    }
-    return VERR_SYMBOL_NOT_FOUND;
-}
-
-
-/** Argument package for supLoadModuleCalcSizeCB. */
-typedef struct SUPLDRCALCSIZEARGS
-{
-    size_t          cbStrings;
-    uint32_t        cSymbols;
-    size_t          cbImage;
-} SUPLDRCALCSIZEARGS, *PSUPLDRCALCSIZEARGS;
-
-/**
- * Callback used to calculate the image size.
- * @return VINF_SUCCESS
- */
-static DECLCALLBACK(int) supLoadModuleCalcSizeCB(RTLDRMOD hLdrMod, const char *pszSymbol, unsigned uSymbol, RTUINTPTR Value, void *pvUser)
-{
-    PSUPLDRCALCSIZEARGS pArgs = (PSUPLDRCALCSIZEARGS)pvUser;
-    if (    pszSymbol != NULL
-        &&  *pszSymbol
-        &&  Value <= pArgs->cbImage)
-    {
-        pArgs->cSymbols++;
-        pArgs->cbStrings += strlen(pszSymbol) + 1;
-    }
-    NOREF(hLdrMod); NOREF(uSymbol);
-    return VINF_SUCCESS;
-}
-
-
-/** Argument package for supLoadModuleCreateTabsCB. */
-typedef struct SUPLDRCREATETABSARGS
-{
-    size_t          cbImage;
-    PSUPLDRSYM      pSym;
-    char           *pszBase;
-    char           *psz;
-} SUPLDRCREATETABSARGS, *PSUPLDRCREATETABSARGS;
-
-/**
- * Callback used to calculate the image size.
- * @return VINF_SUCCESS
- */
-static DECLCALLBACK(int) supLoadModuleCreateTabsCB(RTLDRMOD hLdrMod, const char *pszSymbol, unsigned uSymbol, RTUINTPTR Value, void *pvUser)
-{
-    PSUPLDRCREATETABSARGS pArgs = (PSUPLDRCREATETABSARGS)pvUser;
-    if (    pszSymbol != NULL
-        &&  *pszSymbol
-        &&  Value <= pArgs->cbImage)
-    {
-        pArgs->pSym->offSymbol = (uint32_t)Value;
-        pArgs->pSym->offName = pArgs->psz - pArgs->pszBase;
-        pArgs->pSym++;
-
-        size_t cbCopy = strlen(pszSymbol) + 1;
-        memcpy(pArgs->psz, pszSymbol, cbCopy);
-        pArgs->psz += cbCopy;
-    }
-    NOREF(hLdrMod); NOREF(uSymbol);
-    return VINF_SUCCESS;
-}
-
-
-/**
- * Worker for SUPR3LoadModule().
- *
- * @returns VBox status code.
- * @param   pszFilename     Name of the VMMR0 image file
- */
-static int supLoadModule(const char *pszFilename, const char *pszModule, const char *pszSrvReqHandler, void **ppvImageBase)
-{
-    int rc;
-
-    /*
-     * Validate input.
-     */
-    AssertPtrReturn(pszFilename, VERR_INVALID_PARAMETER);
-    AssertPtrReturn(pszModule, VERR_INVALID_PARAMETER);
-    AssertPtrReturn(ppvImageBase, VERR_INVALID_PARAMETER);
-    AssertReturn(strlen(pszModule) < RT_SIZEOFMEMB(SUPLDROPEN, u.In.szName), VERR_FILENAME_TOO_LONG);
-    char szAbsFilename[RT_SIZEOFMEMB(SUPLDROPEN, u.In.szFilename)];
-    rc = RTPathAbs(pszFilename, szAbsFilename, sizeof(szAbsFilename));
-    if (RT_FAILURE(rc))
-        return rc;
-    pszFilename = szAbsFilename;
-
-    const bool fIsVMMR0 = !strcmp(pszModule, "VMMR0.r0");
-    AssertReturn(!pszSrvReqHandler || !fIsVMMR0, VERR_INTERNAL_ERROR);
-    *ppvImageBase = NULL;
-
-    /*
-     * Open image file and figure its size.
-     */
-    RTLDRMOD hLdrMod;
-    rc = RTLdrOpen(pszFilename, 0, RTLDRARCH_HOST, &hLdrMod);
-    if (!RT_SUCCESS(rc))
-    {
-        LogRel(("SUP: RTLdrOpen failed for %s (%s)\n", pszModule, pszFilename, rc));
-        return rc;
-    }
-
-    SUPLDRCALCSIZEARGS CalcArgs;
-    CalcArgs.cbStrings = 0;
-    CalcArgs.cSymbols = 0;
-    CalcArgs.cbImage = RTLdrSize(hLdrMod);
-    rc = RTLdrEnumSymbols(hLdrMod, 0, NULL, 0, supLoadModuleCalcSizeCB, &CalcArgs);
-    if (RT_SUCCESS(rc))
-    {
-        const uint32_t  offSymTab = RT_ALIGN_32(CalcArgs.cbImage, 8);
-        const uint32_t  offStrTab = offSymTab + CalcArgs.cSymbols * sizeof(SUPLDRSYM);
-        const uint32_t  cbImageWithTabs = RT_ALIGN_32(offStrTab + CalcArgs.cbStrings, 8);
-
-        /*
-         * Open the R0 image.
-         */
-        SUPLDROPEN OpenReq;
-        OpenReq.Hdr.u32Cookie = g_u32Cookie;
-        OpenReq.Hdr.u32SessionCookie = g_u32SessionCookie;
-        OpenReq.Hdr.cbIn = SUP_IOCTL_LDR_OPEN_SIZE_IN;
-        OpenReq.Hdr.cbOut = SUP_IOCTL_LDR_OPEN_SIZE_OUT;
-        OpenReq.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
-        OpenReq.Hdr.rc = VERR_INTERNAL_ERROR;
-        OpenReq.u.In.cbImageWithTabs = cbImageWithTabs;
-        OpenReq.u.In.cbImageBits = (uint32_t)CalcArgs.cbImage;
-        strcpy(OpenReq.u.In.szName, pszModule);
-        strcpy(OpenReq.u.In.szFilename, pszFilename);
-        if (!g_u32FakeMode)
-        {
-            rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_LDR_OPEN, &OpenReq, SUP_IOCTL_LDR_OPEN_SIZE);
-            if (RT_SUCCESS(rc))
-                rc = OpenReq.Hdr.rc;
-        }
-        else
-        {
-            OpenReq.u.Out.fNeedsLoading = true;
-            OpenReq.u.Out.pvImageBase = 0xef423420;
-        }
-        *ppvImageBase = (void *)OpenReq.u.Out.pvImageBase;
-        if (    RT_SUCCESS(rc)
-            &&  OpenReq.u.Out.fNeedsLoading)
-        {
-            /*
-             * We need to load it.
-             * Allocate memory for the image bits.
-             */
-            PSUPLDRLOAD pLoadReq = (PSUPLDRLOAD)RTMemTmpAlloc(SUP_IOCTL_LDR_LOAD_SIZE(cbImageWithTabs));
-            if (pLoadReq)
-            {
-                /*
-                 * Get the image bits.
-                 */
-                rc = RTLdrGetBits(hLdrMod, &pLoadReq->u.In.abImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase,
-                                  supLoadModuleResolveImport, (void *)pszModule);
-
-                if (RT_SUCCESS(rc))
-                {
-                    /*
-                     * Get the entry points.
-                     */
-                    RTUINTPTR VMMR0EntryInt = 0;
-                    RTUINTPTR VMMR0EntryFast = 0;
-                    RTUINTPTR VMMR0EntryEx = 0;
-                    RTUINTPTR SrvReqHandler = 0;
-                    RTUINTPTR ModuleInit = 0;
-                    RTUINTPTR ModuleTerm = 0;
-                    if (fIsVMMR0)
-                    {
-                        rc = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.abImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase, "VMMR0EntryInt", &VMMR0EntryInt);
-                        if (RT_SUCCESS(rc))
-                            rc = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.abImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase, "VMMR0EntryFast", &VMMR0EntryFast);
-                        if (RT_SUCCESS(rc))
-                            rc = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.abImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase, "VMMR0EntryEx", &VMMR0EntryEx);
-                    }
-                    else if (pszSrvReqHandler)
-                        rc = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.abImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase, pszSrvReqHandler, &SrvReqHandler);
-                    if (RT_SUCCESS(rc))
-                    {
-                        int rc2 = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.abImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase, "ModuleInit", &ModuleInit);
-                        if (RT_FAILURE(rc2))
-                            ModuleInit = 0;
-
-                        rc2 = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.abImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase, "ModuleTerm", &ModuleTerm);
-                        if (RT_FAILURE(rc2))
-                            ModuleTerm = 0;
-                    }
-                    if (RT_SUCCESS(rc))
-                    {
-                        /*
-                         * Create the symbol and string tables.
-                         */
-                        SUPLDRCREATETABSARGS CreateArgs;
-                        CreateArgs.cbImage = CalcArgs.cbImage;
-                        CreateArgs.pSym    = (PSUPLDRSYM)&pLoadReq->u.In.abImage[offSymTab];
-                        CreateArgs.pszBase =     (char *)&pLoadReq->u.In.abImage[offStrTab];
-                        CreateArgs.psz     = CreateArgs.pszBase;
-                        rc = RTLdrEnumSymbols(hLdrMod, 0, NULL, 0, supLoadModuleCreateTabsCB, &CreateArgs);
-                        if (RT_SUCCESS(rc))
-                        {
-                            AssertRelease((size_t)(CreateArgs.psz - CreateArgs.pszBase) <= CalcArgs.cbStrings);
-                            AssertRelease((size_t)(CreateArgs.pSym - (PSUPLDRSYM)&pLoadReq->u.In.abImage[offSymTab]) <= CalcArgs.cSymbols);
-
-                            /*
-                             * Upload the image.
-                             */
-                            pLoadReq->Hdr.u32Cookie = g_u32Cookie;
-                            pLoadReq->Hdr.u32SessionCookie = g_u32SessionCookie;
-                            pLoadReq->Hdr.cbIn = SUP_IOCTL_LDR_LOAD_SIZE_IN(cbImageWithTabs);
-                            pLoadReq->Hdr.cbOut = SUP_IOCTL_LDR_LOAD_SIZE_OUT;
-                            pLoadReq->Hdr.fFlags = SUPREQHDR_FLAGS_MAGIC | SUPREQHDR_FLAGS_EXTRA_IN;
-                            pLoadReq->Hdr.rc = VERR_INTERNAL_ERROR;
-
-                            pLoadReq->u.In.pfnModuleInit              = (RTR0PTR)ModuleInit;
-                            pLoadReq->u.In.pfnModuleTerm              = (RTR0PTR)ModuleTerm;
-                            if (fIsVMMR0)
-                            {
-                                pLoadReq->u.In.eEPType                = SUPLDRLOADEP_VMMR0;
-                                pLoadReq->u.In.EP.VMMR0.pvVMMR0       = OpenReq.u.Out.pvImageBase;
-                                pLoadReq->u.In.EP.VMMR0.pvVMMR0EntryInt = (RTR0PTR)VMMR0EntryInt;
-                                pLoadReq->u.In.EP.VMMR0.pvVMMR0EntryFast= (RTR0PTR)VMMR0EntryFast;
-                                pLoadReq->u.In.EP.VMMR0.pvVMMR0EntryEx  = (RTR0PTR)VMMR0EntryEx;
-                            }
-                            else if (pszSrvReqHandler)
-                            {
-                                pLoadReq->u.In.eEPType                = SUPLDRLOADEP_SERVICE;
-                                pLoadReq->u.In.EP.Service.pfnServiceReq = (RTR0PTR)SrvReqHandler;
-                                pLoadReq->u.In.EP.Service.apvReserved[0] = NIL_RTR0PTR;
-                                pLoadReq->u.In.EP.Service.apvReserved[1] = NIL_RTR0PTR;
-                                pLoadReq->u.In.EP.Service.apvReserved[2] = NIL_RTR0PTR;
-                            }
-                            else
-                                pLoadReq->u.In.eEPType                = SUPLDRLOADEP_NOTHING;
-                            pLoadReq->u.In.offStrTab                  = offStrTab;
-                            pLoadReq->u.In.cbStrTab                   = (uint32_t)CalcArgs.cbStrings;
-                            AssertRelease(pLoadReq->u.In.cbStrTab == CalcArgs.cbStrings);
-                            pLoadReq->u.In.cbImageBits                = (uint32_t)CalcArgs.cbImage;
-                            pLoadReq->u.In.offSymbols                 = offSymTab;
-                            pLoadReq->u.In.cSymbols                   = CalcArgs.cSymbols;
-                            pLoadReq->u.In.cbImageWithTabs            = cbImageWithTabs;
-                            pLoadReq->u.In.pvImageBase                = OpenReq.u.Out.pvImageBase;
-                            if (!g_u32FakeMode)
-                            {
-                                rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_LDR_LOAD, pLoadReq, SUP_IOCTL_LDR_LOAD_SIZE(cbImageWithTabs));
-                                if (RT_SUCCESS(rc))
-                                    rc = pLoadReq->Hdr.rc;
-                                else
-                                    LogRel(("SUP: SUP_IOCTL_LDR_LOAD ioctl for %s (%s) failed rc=%Rrc\n", pszModule, pszFilename, rc));
-                            }
-                            else
-                                rc = VINF_SUCCESS;
-                            if (    RT_SUCCESS(rc)
-                                ||  rc == VERR_ALREADY_LOADED /* A competing process. */
-                               )
-                            {
-                                LogRel(("SUP: Loaded %s (%s) at %#p - ModuleInit at %RTptr and ModuleTerm at %RTptr%s\n",
-                                        pszModule, pszFilename, OpenReq.u.Out.pvImageBase, ModuleInit, ModuleTerm,
-                                        OpenReq.u.Out.fNativeLoader ? " using the native ring-0 loader" : ""));
-                                if (fIsVMMR0)
-                                {
-                                    g_pvVMMR0 = OpenReq.u.Out.pvImageBase;
-                                    LogRel(("SUP: VMMR0EntryEx located at %RTptr, VMMR0EntryFast at %RTptr and VMMR0EntryInt at %RTptr\n",
-                                            VMMR0EntryEx, VMMR0EntryFast, VMMR0EntryInt));
-                                }
-#ifdef RT_OS_WINDOWS
-                                LogRel(("SUP: windbg> .reload /f %s=%#p\n", pszFilename, OpenReq.u.Out.pvImageBase));
-#endif
-
-                                RTMemTmpFree(pLoadReq);
-                                RTLdrClose(hLdrMod);
-                                return VINF_SUCCESS;
-                            }
-                            else
-                                LogRel(("SUP: Loading failed for %s (%s) rc=%Rrc\n", pszModule, pszFilename, rc));
-                        }
-                        else
-                            LogRel(("SUP: RTLdrEnumSymbols failed for %s (%s) rc=%Rrc\n", pszModule, pszFilename, rc));
-                    }
-                    else
-                        LogRel(("SUP: Failed to get entry points for %s (%s) rc=%Rrc\n", pszModule, pszFilename, rc));
-                }
-                else
-                    LogRel(("SUP: RTLdrGetBits failed for %s (%s). rc=%Rrc\n", pszModule, pszFilename, rc));
-                RTMemTmpFree(pLoadReq);
-            }
-            else
-            {
-                AssertMsgFailed(("failed to allocated %u bytes for SUPLDRLOAD_IN structure!\n", SUP_IOCTL_LDR_LOAD_SIZE(cbImageWithTabs)));
-                rc = VERR_NO_TMP_MEMORY;
-            }
-        }
-        else if (RT_SUCCESS(rc))
-        {
-            if (fIsVMMR0)
-                g_pvVMMR0 = OpenReq.u.Out.pvImageBase;
-            LogRel(("SUP: Opened %s (%s) at %#p.\n", pszModule, pszFilename, OpenReq.u.Out.pvImageBase,
-                    OpenReq.u.Out.fNativeLoader ? " loaded by the native ring-0 loader" : ""));
-#ifdef RT_OS_WINDOWS
-            LogRel(("SUP: windbg> .reload /f %s=%#p\n", pszFilename, OpenReq.u.Out.pvImageBase));
-#endif
-        }
-    }
-    RTLdrClose(hLdrMod);
-    return rc;
-}
-
-
-SUPR3DECL(int) SUPR3FreeModule(void *pvImageBase)
-{
-    /* fake */
-    if (RT_UNLIKELY(g_u32FakeMode))
-    {
-        g_pvVMMR0 = NIL_RTR0PTR;
-        return VINF_SUCCESS;
-    }
-
-    /*
-     * Free the requested module.
-     */
-    SUPLDRFREE Req;
-    Req.Hdr.u32Cookie = g_u32Cookie;
-    Req.Hdr.u32SessionCookie = g_u32SessionCookie;
-    Req.Hdr.cbIn = SUP_IOCTL_LDR_FREE_SIZE_IN;
-    Req.Hdr.cbOut = SUP_IOCTL_LDR_FREE_SIZE_OUT;
-    Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
-    Req.Hdr.rc = VERR_INTERNAL_ERROR;
-    Req.u.In.pvImageBase = (RTR0PTR)pvImageBase;
-    int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_LDR_FREE, &Req, SUP_IOCTL_LDR_FREE_SIZE);
-    if (RT_SUCCESS(rc))
-        rc = Req.Hdr.rc;
-    if (    RT_SUCCESS(rc)
-        &&  (RTR0PTR)pvImageBase == g_pvVMMR0)
-        g_pvVMMR0 = NIL_RTR0PTR;
-    return rc;
-}
-
-
-SUPR3DECL(int) SUPR3GetSymbolR0(void *pvImageBase, const char *pszSymbol, void **ppvValue)
-{
-    *ppvValue = NULL;
-
-    /* fake */
-    if (RT_UNLIKELY(g_u32FakeMode))
-    {
-        *ppvValue = (void *)(uintptr_t)0xdeadf00d;
-        return VINF_SUCCESS;
-    }
-
-    /*
-     * Do ioctl.
-     */
-    SUPLDRGETSYMBOL Req;
-    Req.Hdr.u32Cookie = g_u32Cookie;
-    Req.Hdr.u32SessionCookie = g_u32SessionCookie;
-    Req.Hdr.cbIn = SUP_IOCTL_LDR_GET_SYMBOL_SIZE_IN;
-    Req.Hdr.cbOut = SUP_IOCTL_LDR_GET_SYMBOL_SIZE_OUT;
-    Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
-    Req.Hdr.rc = VERR_INTERNAL_ERROR;
-    Req.u.In.pvImageBase = (RTR0PTR)pvImageBase;
-    size_t cchSymbol = strlen(pszSymbol);
-    if (cchSymbol >= sizeof(Req.u.In.szSymbol))
-        return VERR_SYMBOL_NOT_FOUND;
-    memcpy(Req.u.In.szSymbol, pszSymbol, cchSymbol + 1);
-    int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_LDR_GET_SYMBOL, &Req, SUP_IOCTL_LDR_GET_SYMBOL_SIZE);
-    if (RT_SUCCESS(rc))
-        rc = Req.Hdr.rc;
-    if (RT_SUCCESS(rc))
-        *ppvValue = (void *)Req.u.Out.pvSymbol;
-    return rc;
-}
-
-
-SUPR3DECL(int) SUPR3LoadVMM(const char *pszFilename)
-{
-    void *pvImageBase;
-    return SUPR3LoadModule(pszFilename, "VMMR0.r0", &pvImageBase, NULL /*pErrInfo*/);
-}
-
-
-SUPR3DECL(int) SUPR3UnloadVMM(void)
-{
-    return SUPR3FreeModule((void*)g_pvVMMR0);
-}
-
-
 SUPR3DECL(int) SUPR3GipGetPhys(PRTHCPHYS pHCPhys)
 {
@@ -2150,156 +1605,4 @@
     *pHCPhys = NIL_RTHCPHYS;
     return VERR_WRONG_ORDER;
-}
-
-
-/**
- * Worker for SUPR3HardenedLdrLoad and SUPR3HardenedLdrLoadAppPriv.
- *
- * @returns iprt status code.
- * @param   pszFilename     The full file name.
- * @param   phLdrMod        Where to store the handle to the loaded module.
- * @param   fFlags          See RTLDFLAGS_.
- * @param   pErrInfo        Where to return extended error information.
- *                          Optional.
- *
- */
-static int supR3HardenedLdrLoadIt(const char *pszFilename, PRTLDRMOD phLdrMod, uint32_t fFlags, PRTERRINFO pErrInfo)
-{
-#ifdef VBOX_WITH_HARDENING
-    /*
-     * Verify the image file.
-     */
-    int rc = supR3HardenedVerifyFixedFile(pszFilename, false /* fFatal */);
-    if (RT_FAILURE(rc))
-    {
-        LogRel(("supR3HardenedLdrLoadIt: Verification of \"%s\" failed, rc=%Rrc\n", pszFilename, rc));
-        return RTErrInfoSet(pErrInfo, rc, "supR3HardenedVerifyFixedFile failed");
-    }
-#endif
-
-    /*
-     * Try load it.
-     */
-    return RTLdrLoadEx(pszFilename, phLdrMod, fFlags, pErrInfo);
-}
-
-
-SUPR3DECL(int) SUPR3HardenedLdrLoad(const char *pszFilename, PRTLDRMOD phLdrMod, uint32_t fFlags, PRTERRINFO pErrInfo)
-{
-    /*
-     * Validate input.
-     */
-    RTErrInfoClear(pErrInfo);
-    AssertPtrReturn(pszFilename, VERR_INVALID_POINTER);
-    AssertPtrReturn(phLdrMod, VERR_INVALID_POINTER);
-    *phLdrMod = NIL_RTLDRMOD;
-    AssertReturn(RTPathHavePath(pszFilename), VERR_INVALID_PARAMETER);
-
-    /*
-     * Add the default extension if it's missing.
-     */
-    if (!RTPathHasSuffix(pszFilename))
-    {
-        const char *pszSuff = RTLdrGetSuff();
-        size_t      cchSuff = strlen(pszSuff);
-        size_t      cchFilename = strlen(pszFilename);
-        char       *psz = (char *)alloca(cchFilename + cchSuff + 1);
-        AssertReturn(psz, VERR_NO_TMP_MEMORY);
-        memcpy(psz, pszFilename, cchFilename);
-        memcpy(psz + cchFilename, pszSuff, cchSuff + 1);
-        pszFilename = psz;
-    }
-
-    /*
-     * Pass it on to the common library loader.
-     */
-    return supR3HardenedLdrLoadIt(pszFilename, phLdrMod, fFlags, pErrInfo);
-}
-
-
-SUPR3DECL(int) SUPR3HardenedLdrLoadAppPriv(const char *pszFilename, PRTLDRMOD phLdrMod, uint32_t fFlags, PRTERRINFO pErrInfo)
-{
-    LogFlow(("SUPR3HardenedLdrLoadAppPriv: pszFilename=%p:{%s} phLdrMod=%p fFlags=%08x pErrInfo=%p\n", pszFilename, pszFilename, phLdrMod, fFlags, pErrInfo));
-
-    /*
-     * Validate input.
-     */
-    RTErrInfoClear(pErrInfo);
-    AssertPtrReturn(phLdrMod, VERR_INVALID_PARAMETER);
-    *phLdrMod = NIL_RTLDRMOD;
-    AssertPtrReturn(pszFilename, VERR_INVALID_PARAMETER);
-    AssertMsgReturn(!RTPathHavePath(pszFilename), ("%s\n", pszFilename), VERR_INVALID_PARAMETER);
-
-    /*
-     * Check the filename.
-     */
-    size_t cchFilename = strlen(pszFilename);
-    AssertMsgReturn(cchFilename < (RTPATH_MAX / 4) * 3, ("%zu\n", cchFilename), VERR_INVALID_PARAMETER);
-
-    const char *pszExt = "";
-    size_t cchExt = 0;
-    if (!RTPathHasSuffix(pszFilename))
-    {
-        pszExt = RTLdrGetSuff();
-        cchExt = strlen(pszExt);
-    }
-
-    /*
-     * Construct the private arch path and check if the file exists.
-     */
-    char szPath[RTPATH_MAX];
-    int rc = RTPathAppPrivateArch(szPath, sizeof(szPath) - 1 - cchExt - cchFilename);
-    AssertRCReturn(rc, rc);
-
-    char *psz = strchr(szPath, '\0');
-    *psz++ = RTPATH_SLASH;
-    memcpy(psz, pszFilename, cchFilename);
-    psz += cchFilename;
-    memcpy(psz, pszExt, cchExt + 1);
-
-    if (!RTPathExists(szPath))
-    {
-        LogRel(("SUPR3HardenedLdrLoadAppPriv: \"%s\" not found\n", szPath));
-        return VERR_FILE_NOT_FOUND;
-    }
-
-    /*
-     * Pass it on to SUPR3HardenedLdrLoad.
-     */
-    rc = SUPR3HardenedLdrLoad(szPath, phLdrMod, fFlags, pErrInfo);
-
-    LogFlow(("SUPR3HardenedLdrLoadAppPriv: returns %Rrc\n", rc));
-    return rc;
-}
-
-
-SUPR3DECL(int) SUPR3HardenedLdrLoadPlugIn(const char *pszFilename, PRTLDRMOD phLdrMod, PRTERRINFO pErrInfo)
-{
-    /*
-     * Validate input.
-     */
-    RTErrInfoClear(pErrInfo);
-    AssertPtrReturn(phLdrMod, VERR_INVALID_PARAMETER);
-    *phLdrMod = NIL_RTLDRMOD;
-    AssertPtrReturn(pszFilename, VERR_INVALID_PARAMETER);
-    AssertReturn(RTPathStartsWithRoot(pszFilename), VERR_INVALID_PARAMETER);
-
-#ifdef VBOX_WITH_HARDENING
-    /*
-     * Verify the image file.
-     */
-    int rc = supR3HardenedVerifyFile(pszFilename, RTHCUINTPTR_MAX, pErrInfo);
-    if (RT_FAILURE(rc))
-    {
-        if (!RTErrInfoIsSet(pErrInfo))
-            LogRel(("supR3HardenedVerifyFile: Verification of \"%s\" failed, rc=%Rrc\n", pszFilename, rc));
-        return rc;
-    }
-#endif
-
-    /*
-     * Try load it.
-     */
-    return RTLdrLoadEx(pszFilename, phLdrMod, RTLDRLOAD_FLAGS_LOCAL, pErrInfo);
 }
 
@@ -2322,5 +1625,5 @@
 
     /* fake */
-    if (RT_UNLIKELY(g_u32FakeMode))
+    if (RT_UNLIKELY(g_uSupFakeMode))
         return VINF_SUCCESS;
 
@@ -2350,5 +1653,5 @@
 {
     /* fake */
-    if (RT_UNLIKELY(g_u32FakeMode))
+    if (RT_UNLIKELY(g_uSupFakeMode))
         return VINF_SUCCESS;
 
@@ -2375,5 +1678,5 @@
 {
     /* fake */
-    if (RT_UNLIKELY(g_u32FakeMode))
+    if (RT_UNLIKELY(g_uSupFakeMode))
         return VINF_SUCCESS;
 
@@ -2398,5 +1701,5 @@
 {
     /* fake */
-    if (RT_UNLIKELY(g_u32FakeMode))
+    if (RT_UNLIKELY(g_uSupFakeMode))
     {
         *piRetVal = -1;
@@ -2624,5 +1927,5 @@
      * Fake out.
      */
-    if (RT_UNLIKELY(g_u32FakeMode))
+    if (RT_UNLIKELY(g_uSupFakeMode))
         return VINF_SUCCESS;
 
@@ -2708,5 +2011,5 @@
      * Fake out.
      */
-    if (RT_UNLIKELY(g_u32FakeMode))
+    if (RT_UNLIKELY(g_uSupFakeMode))
         return VINF_SUCCESS;
 
@@ -2742,2 +2045,90 @@
 }
 
+
+SUPR3DECL(int) SUPR3MsrProberRead(uint32_t uMsr, RTCPUID idCpu, uint64_t *puValue, bool *pfGp)
+{
+    SUPMSRPROBER  Req;
+    Req.Hdr.u32Cookie           = g_u32Cookie;
+    Req.Hdr.u32SessionCookie    = g_u32SessionCookie;
+    Req.Hdr.cbIn                = SUP_IOCTL_MSR_PROBER_SIZE_IN;
+    Req.Hdr.cbOut               = SUP_IOCTL_MSR_PROBER_SIZE_OUT;
+    Req.Hdr.fFlags              = SUPREQHDR_FLAGS_DEFAULT;
+    Req.Hdr.rc                  = VERR_INTERNAL_ERROR;
+
+    Req.u.In.enmOp              = SUPMSRPROBEROP_READ;
+    Req.u.In.uMsr               = uMsr;
+    Req.u.In.idCpu              = idCpu == NIL_RTCPUID ? UINT32_MAX : idCpu;
+
+    int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_MSR_PROBER, &Req, SUP_IOCTL_MSR_PROBER_SIZE);
+    if (RT_SUCCESS(rc))
+        rc = Req.Hdr.rc;
+    if (RT_SUCCESS(rc))
+    {
+        if (puValue)
+            *puValue = Req.u.Out.uResults.Read.uValue;
+        if (pfGp)
+            *pfGp    = Req.u.Out.uResults.Read.fGp;
+    }
+
+    return rc;
+}
+
+
+SUPR3DECL(int) SUPR3MsrProberWrite(uint32_t uMsr, RTCPUID idCpu, uint64_t uValue, bool *pfGp)
+{
+    SUPMSRPROBER  Req;
+    Req.Hdr.u32Cookie           = g_u32Cookie;
+    Req.Hdr.u32SessionCookie    = g_u32SessionCookie;
+    Req.Hdr.cbIn                = SUP_IOCTL_MSR_PROBER_SIZE_IN;
+    Req.Hdr.cbOut               = SUP_IOCTL_MSR_PROBER_SIZE_OUT;
+    Req.Hdr.fFlags              = SUPREQHDR_FLAGS_DEFAULT;
+    Req.Hdr.rc                  = VERR_INTERNAL_ERROR;
+
+    Req.u.In.enmOp                  = SUPMSRPROBEROP_WRITE;
+    Req.u.In.uMsr                   = uMsr;
+    Req.u.In.idCpu                  = idCpu == NIL_RTCPUID ? UINT32_MAX : idCpu;
+    Req.u.In.uArgs.Write.uToWrite   = uValue;
+
+    int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_MSR_PROBER, &Req, SUP_IOCTL_MSR_PROBER_SIZE);
+    if (RT_SUCCESS(rc))
+        rc = Req.Hdr.rc;
+    if (RT_SUCCESS(rc) && pfGp)
+        *pfGp = Req.u.Out.uResults.Write.fGp;
+
+    return rc;
+}
+
+
+SUPR3DECL(int) SUPR3MsrProberModify(uint32_t uMsr, RTCPUID idCpu, uint64_t fAndMask, uint64_t fOrMask,
+                                    PSUPMSRPROBERMODIFYRESULT pResult)
+{
+    return SUPR3MsrProberModifyEx(uMsr, idCpu, fAndMask, fOrMask, false /*fFaster*/, pResult);
+}
+
+
+SUPR3DECL(int) SUPR3MsrProberModifyEx(uint32_t uMsr, RTCPUID idCpu, uint64_t fAndMask, uint64_t fOrMask, bool fFaster,
+                                      PSUPMSRPROBERMODIFYRESULT pResult)
+{
+    SUPMSRPROBER  Req;
+    Req.Hdr.u32Cookie           = g_u32Cookie;
+    Req.Hdr.u32SessionCookie    = g_u32SessionCookie;
+    Req.Hdr.cbIn                = SUP_IOCTL_MSR_PROBER_SIZE_IN;
+    Req.Hdr.cbOut               = SUP_IOCTL_MSR_PROBER_SIZE_OUT;
+    Req.Hdr.fFlags              = SUPREQHDR_FLAGS_DEFAULT;
+    Req.Hdr.rc                  = VERR_INTERNAL_ERROR;
+
+    Req.u.In.enmOp                  = fFaster ? SUPMSRPROBEROP_MODIFY_FASTER : SUPMSRPROBEROP_MODIFY;
+    Req.u.In.uMsr                   = uMsr;
+    Req.u.In.idCpu                  = idCpu == NIL_RTCPUID ? UINT32_MAX : idCpu;
+    Req.u.In.uArgs.Modify.fAndMask  = fAndMask;
+    Req.u.In.uArgs.Modify.fOrMask   = fOrMask;
+
+    int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_MSR_PROBER, &Req, SUP_IOCTL_MSR_PROBER_SIZE);
+    if (RT_SUCCESS(rc))
+        rc = Req.Hdr.rc;
+    if (RT_SUCCESS(rc))
+        *pResult = Req.u.Out.uResults.Modify;
+
+    return rc;
+}
+
Index: /trunk/src/VBox/HostDrivers/Support/SUPLibInternal.h
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/SUPLibInternal.h	(revision 49633)
+++ /trunk/src/VBox/HostDrivers/Support/SUPLibInternal.h	(revision 49634)
@@ -280,7 +280,12 @@
 *   Global Variables                                                           *
 *******************************************************************************/
-extern DECLHIDDEN(uint32_t)     g_u32Cookie;
-extern DECLHIDDEN(uint32_t)     g_u32SessionCookie;
-extern DECLHIDDEN(SUPLIBDATA)   g_supLibData;
+extern DECLHIDDEN(uint32_t)             g_u32Cookie;
+extern DECLHIDDEN(uint32_t)             g_u32SessionCookie;
+extern DECLHIDDEN(SUPLIBDATA)           g_supLibData;
+extern DECLHIDDEN(uint32_t)             g_uSupFakeMode;
+extern DECLHIDDEN(PSUPGLOBALINFOPAGE)   g_pSUPGlobalInfoPageR0;
+#ifdef ___SUPDrvIOC_h___
+extern DECLHIDDEN(PSUPQUERYFUNCS)       g_pSupFunctions;
+#endif
 
 
Index: /trunk/src/VBox/HostDrivers/Support/SUPLibLdr.cpp
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/SUPLibLdr.cpp	(revision 49634)
+++ /trunk/src/VBox/HostDrivers/Support/SUPLibLdr.cpp	(revision 49634)
@@ -0,0 +1,798 @@
+/* $Id$ */
+/** @file
+ * VirtualBox Support Library - Loader related bits.
+ */
+
+/*
+ * Copyright (C) 2006-2013 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ *
+ * The contents of this file may alternatively be used under the terms
+ * of the Common Development and Distribution License Version 1.0
+ * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
+ * VirtualBox OSE distribution, in which case the provisions of the
+ * CDDL are applicable instead of those of the GPL.
+ *
+ * You may elect to license modified versions of this file under the
+ * terms and conditions of either the GPL or the CDDL or both.
+ */
+
+/** @page   pg_sup          SUP - The Support Library
+ *
+ * The support library is responsible for providing facilities to load
+ * VMM Host Ring-0 code, to call Host VMM Ring-0 code from Ring-3 Host
+ * code, to pin down physical memory, and more.
+ *
+ * The VMM Host Ring-0 code can be combined in the support driver if
+ * permitted by kernel module license policies. If it is not combined
+ * it will be externalized in a .r0 module that will be loaded using
+ * the IPRT loader.
+ *
+ * The Ring-0 calling is done thru a generic SUP interface which will
+ * transfer an argument set and call a predefined entry point in the Host
+ * VMM Ring-0 code.
+ *
+ * See @ref grp_sup "SUP - Support APIs" for API details.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#define LOG_GROUP LOG_GROUP_SUP
+#include <VBox/sup.h>
+#include <VBox/err.h>
+#include <VBox/param.h>
+#include <VBox/log.h>
+#include <VBox/VBoxTpG.h>
+
+#include <iprt/assert.h>
+#include <iprt/alloc.h>
+#include <iprt/alloca.h>
+#include <iprt/ldr.h>
+#include <iprt/asm.h>
+#include <iprt/mp.h>
+#include <iprt/cpuset.h>
+#include <iprt/thread.h>
+#include <iprt/process.h>
+#include <iprt/path.h>
+#include <iprt/string.h>
+#include <iprt/env.h>
+#include <iprt/rand.h>
+#include <iprt/x86.h>
+
+#include "SUPDrvIOC.h"
+#include "SUPLibInternal.h"
+
+
+/*******************************************************************************
+*   Defined Constants And Macros                                               *
+*******************************************************************************/
+/** R0 VMM module name. */
+#define VMMR0_NAME      "VMMR0"
+
+
+/*******************************************************************************
+*   Structures and Typedefs                                                    *
+*******************************************************************************/
+typedef DECLCALLBACK(int) FNCALLVMMR0(PVMR0 pVMR0, unsigned uOperation, void *pvArg);
+typedef FNCALLVMMR0 *PFNCALLVMMR0;
+
+
+/*******************************************************************************
+*   Global Variables                                                           *
+*******************************************************************************/
+/** VMMR0 Load Address. */
+static RTR0PTR                  g_pvVMMR0 = NIL_RTR0PTR;
+
+
+/*******************************************************************************
+*   Internal Functions                                                         *
+*******************************************************************************/
+static int supLoadModule(const char *pszFilename, const char *pszModule, const char *pszSrvReqHandler, void **ppvImageBase);
+static DECLCALLBACK(int) supLoadModuleResolveImport(RTLDRMOD hLdrMod, const char *pszModule, const char *pszSymbol, unsigned uSymbol, RTUINTPTR *pValue, void *pvUser);
+
+
+SUPR3DECL(int) SUPR3LoadModule(const char *pszFilename, const char *pszModule, void **ppvImageBase, PRTERRINFO pErrInfo)
+{
+    /*
+     * Check that the module can be trusted.
+     */
+    int rc = SUPR3HardenedVerifyPlugIn(pszFilename, pErrInfo);
+    if (RT_SUCCESS(rc))
+    {
+        rc = supLoadModule(pszFilename, pszModule, NULL, ppvImageBase);
+        if (RT_FAILURE(rc))
+            RTErrInfoSetF(pErrInfo, rc, "SUPR3LoadModule: supLoadModule returned %Rrc", rc);
+    }
+    return rc;
+}
+
+
+SUPR3DECL(int) SUPR3LoadServiceModule(const char *pszFilename, const char *pszModule,
+                                      const char *pszSrvReqHandler, void **ppvImageBase)
+{
+    AssertPtrReturn(pszSrvReqHandler, VERR_INVALID_PARAMETER);
+
+    /*
+     * Check that the module can be trusted.
+     */
+    int rc = SUPR3HardenedVerifyPlugIn(pszFilename, NULL /*pErrInfo*/);
+    if (RT_SUCCESS(rc))
+        rc = supLoadModule(pszFilename, pszModule, pszSrvReqHandler, ppvImageBase);
+    else
+        LogRel(("SUPR3LoadServiceModule: Verification of \"%s\" failed, rc=%Rrc\n", rc));
+    return rc;
+}
+
+
+/**
+ * Resolve an external symbol during RTLdrGetBits().
+ *
+ * @returns VBox status code.
+ * @param   hLdrMod         The loader module handle.
+ * @param   pszModule       Module name.
+ * @param   pszSymbol       Symbol name, NULL if uSymbol should be used.
+ * @param   uSymbol         Symbol ordinal, ~0 if pszSymbol should be used.
+ * @param   pValue          Where to store the symbol value (address).
+ * @param   pvUser          User argument.
+ */
+static DECLCALLBACK(int) supLoadModuleResolveImport(RTLDRMOD hLdrMod, const char *pszModule,
+                                                    const char *pszSymbol, unsigned uSymbol, RTUINTPTR *pValue, void *pvUser)
+{
+    NOREF(hLdrMod); NOREF(pvUser); NOREF(uSymbol);
+    AssertPtr(pValue);
+    AssertPtr(pvUser);
+
+    /*
+     * Only SUPR0 and VMMR0.r0
+     */
+    if (    pszModule
+        &&  *pszModule
+        &&  strcmp(pszModule, "VBoxDrv.sys")
+        &&  strcmp(pszModule, "VMMR0.r0"))
+    {
+        AssertMsgFailed(("%s is importing from %s! (expected 'SUPR0.dll' or 'VMMR0.r0', case-sensitive)\n", pvUser, pszModule));
+        return VERR_SYMBOL_NOT_FOUND;
+    }
+
+    /*
+     * No ordinals.
+     */
+    if (pszSymbol < (const char*)0x10000)
+    {
+        AssertMsgFailed(("%s is importing by ordinal (ord=%d)\n", pvUser, (int)(uintptr_t)pszSymbol));
+        return VERR_SYMBOL_NOT_FOUND;
+    }
+
+    /*
+     * Lookup symbol.
+     */
+    /** @todo is this actually used??? */
+    /* skip the 64-bit ELF import prefix first. */
+    if (!strncmp(pszSymbol, RT_STR_TUPLE("SUPR0$")))
+        pszSymbol += sizeof("SUPR0$") - 1;
+
+    /*
+     * Check the VMMR0.r0 module if loaded.
+     */
+    /** @todo call the SUPR3LoadModule caller.... */
+    /** @todo proper reference counting and such. */
+    if (g_pvVMMR0 != NIL_RTR0PTR)
+    {
+        void *pvValue;
+        if (!SUPR3GetSymbolR0((void *)g_pvVMMR0, pszSymbol, &pvValue))
+        {
+            *pValue = (uintptr_t)pvValue;
+            return VINF_SUCCESS;
+        }
+    }
+
+    /* iterate the function table. */
+    int c = g_pSupFunctions->u.Out.cFunctions;
+    PSUPFUNC pFunc = &g_pSupFunctions->u.Out.aFunctions[0];
+    while (c-- > 0)
+    {
+        if (!strcmp(pFunc->szName, pszSymbol))
+        {
+            *pValue = (uintptr_t)pFunc->pfn;
+            return VINF_SUCCESS;
+        }
+        pFunc++;
+    }
+
+    /*
+     * The GIP.
+     */
+    if (    pszSymbol
+        &&  g_pSUPGlobalInfoPage
+        &&  g_pSUPGlobalInfoPageR0
+        &&  !strcmp(pszSymbol, "g_SUPGlobalInfoPage")
+       )
+    {
+        *pValue = (uintptr_t)g_pSUPGlobalInfoPageR0;
+        return VINF_SUCCESS;
+    }
+
+    /*
+     * Symbols that are undefined by convention.
+     */
+#ifdef RT_OS_SOLARIS
+    static const char * const s_apszConvSyms[] =
+    {
+        "", "mod_getctl",
+        "", "mod_install",
+        "", "mod_remove",
+        "", "mod_info",
+        "", "mod_miscops",
+    };
+    for (unsigned i = 0; i < RT_ELEMENTS(s_apszConvSyms); i += 2)
+    {
+        if (   !RTStrCmp(s_apszConvSyms[i],     pszModule)
+            && !RTStrCmp(s_apszConvSyms[i + 1], pszSymbol))
+        {
+            *pValue = ~(uintptr_t)0;
+            return VINF_SUCCESS;
+        }
+    }
+#endif
+
+    /*
+     * Despair.
+     */
+    c = g_pSupFunctions->u.Out.cFunctions;
+    pFunc = &g_pSupFunctions->u.Out.aFunctions[0];
+    while (c-- > 0)
+    {
+        RTAssertMsg2Weak("%d: %s\n", g_pSupFunctions->u.Out.cFunctions - c, pFunc->szName);
+        pFunc++;
+    }
+
+    AssertLogRelMsgFailed(("%s is importing %s which we couldn't find\n", pvUser, pszSymbol));
+    if (g_uSupFakeMode)
+    {
+        *pValue = 0xdeadbeef;
+        return VINF_SUCCESS;
+    }
+    return VERR_SYMBOL_NOT_FOUND;
+}
+
+
+/** Argument package for supLoadModuleCalcSizeCB. */
+typedef struct SUPLDRCALCSIZEARGS
+{
+    size_t          cbStrings;
+    uint32_t        cSymbols;
+    size_t          cbImage;
+} SUPLDRCALCSIZEARGS, *PSUPLDRCALCSIZEARGS;
+
+/**
+ * Callback used to calculate the image size.
+ * @return VINF_SUCCESS
+ */
+static DECLCALLBACK(int) supLoadModuleCalcSizeCB(RTLDRMOD hLdrMod, const char *pszSymbol, unsigned uSymbol, RTUINTPTR Value, void *pvUser)
+{
+    PSUPLDRCALCSIZEARGS pArgs = (PSUPLDRCALCSIZEARGS)pvUser;
+    if (    pszSymbol != NULL
+        &&  *pszSymbol
+        &&  Value <= pArgs->cbImage)
+    {
+        pArgs->cSymbols++;
+        pArgs->cbStrings += strlen(pszSymbol) + 1;
+    }
+    NOREF(hLdrMod); NOREF(uSymbol);
+    return VINF_SUCCESS;
+}
+
+
+/** Argument package for supLoadModuleCreateTabsCB. */
+typedef struct SUPLDRCREATETABSARGS
+{
+    size_t          cbImage;
+    PSUPLDRSYM      pSym;
+    char           *pszBase;
+    char           *psz;
+} SUPLDRCREATETABSARGS, *PSUPLDRCREATETABSARGS;
+
+/**
+ * Callback used to calculate the image size.
+ * @return VINF_SUCCESS
+ */
+static DECLCALLBACK(int) supLoadModuleCreateTabsCB(RTLDRMOD hLdrMod, const char *pszSymbol, unsigned uSymbol, RTUINTPTR Value, void *pvUser)
+{
+    PSUPLDRCREATETABSARGS pArgs = (PSUPLDRCREATETABSARGS)pvUser;
+    if (    pszSymbol != NULL
+        &&  *pszSymbol
+        &&  Value <= pArgs->cbImage)
+    {
+        pArgs->pSym->offSymbol = (uint32_t)Value;
+        pArgs->pSym->offName = pArgs->psz - pArgs->pszBase;
+        pArgs->pSym++;
+
+        size_t cbCopy = strlen(pszSymbol) + 1;
+        memcpy(pArgs->psz, pszSymbol, cbCopy);
+        pArgs->psz += cbCopy;
+    }
+    NOREF(hLdrMod); NOREF(uSymbol);
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * Worker for SUPR3LoadModule().
+ *
+ * @returns VBox status code.
+ * @param   pszFilename     Name of the VMMR0 image file
+ */
+static int supLoadModule(const char *pszFilename, const char *pszModule, const char *pszSrvReqHandler, void **ppvImageBase)
+{
+    int rc;
+
+    /*
+     * Validate input.
+     */
+    AssertPtrReturn(pszFilename, VERR_INVALID_PARAMETER);
+    AssertPtrReturn(pszModule, VERR_INVALID_PARAMETER);
+    AssertPtrReturn(ppvImageBase, VERR_INVALID_PARAMETER);
+    AssertReturn(strlen(pszModule) < RT_SIZEOFMEMB(SUPLDROPEN, u.In.szName), VERR_FILENAME_TOO_LONG);
+    char szAbsFilename[RT_SIZEOFMEMB(SUPLDROPEN, u.In.szFilename)];
+    rc = RTPathAbs(pszFilename, szAbsFilename, sizeof(szAbsFilename));
+    if (RT_FAILURE(rc))
+        return rc;
+    pszFilename = szAbsFilename;
+
+    const bool fIsVMMR0 = !strcmp(pszModule, "VMMR0.r0");
+    AssertReturn(!pszSrvReqHandler || !fIsVMMR0, VERR_INTERNAL_ERROR);
+    *ppvImageBase = NULL;
+
+    /*
+     * Open image file and figure its size.
+     */
+    RTLDRMOD hLdrMod;
+    rc = RTLdrOpen(pszFilename, 0, RTLDRARCH_HOST, &hLdrMod);
+    if (!RT_SUCCESS(rc))
+    {
+        LogRel(("SUP: RTLdrOpen failed for %s (%s)\n", pszModule, pszFilename, rc));
+        return rc;
+    }
+
+    SUPLDRCALCSIZEARGS CalcArgs;
+    CalcArgs.cbStrings = 0;
+    CalcArgs.cSymbols = 0;
+    CalcArgs.cbImage = RTLdrSize(hLdrMod);
+    rc = RTLdrEnumSymbols(hLdrMod, 0, NULL, 0, supLoadModuleCalcSizeCB, &CalcArgs);
+    if (RT_SUCCESS(rc))
+    {
+        const uint32_t  offSymTab = RT_ALIGN_32(CalcArgs.cbImage, 8);
+        const uint32_t  offStrTab = offSymTab + CalcArgs.cSymbols * sizeof(SUPLDRSYM);
+        const uint32_t  cbImageWithTabs = RT_ALIGN_32(offStrTab + CalcArgs.cbStrings, 8);
+
+        /*
+         * Open the R0 image.
+         */
+        SUPLDROPEN OpenReq;
+        OpenReq.Hdr.u32Cookie = g_u32Cookie;
+        OpenReq.Hdr.u32SessionCookie = g_u32SessionCookie;
+        OpenReq.Hdr.cbIn = SUP_IOCTL_LDR_OPEN_SIZE_IN;
+        OpenReq.Hdr.cbOut = SUP_IOCTL_LDR_OPEN_SIZE_OUT;
+        OpenReq.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
+        OpenReq.Hdr.rc = VERR_INTERNAL_ERROR;
+        OpenReq.u.In.cbImageWithTabs = cbImageWithTabs;
+        OpenReq.u.In.cbImageBits = (uint32_t)CalcArgs.cbImage;
+        strcpy(OpenReq.u.In.szName, pszModule);
+        strcpy(OpenReq.u.In.szFilename, pszFilename);
+        if (!g_uSupFakeMode)
+        {
+            rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_LDR_OPEN, &OpenReq, SUP_IOCTL_LDR_OPEN_SIZE);
+            if (RT_SUCCESS(rc))
+                rc = OpenReq.Hdr.rc;
+        }
+        else
+        {
+            OpenReq.u.Out.fNeedsLoading = true;
+            OpenReq.u.Out.pvImageBase = 0xef423420;
+        }
+        *ppvImageBase = (void *)OpenReq.u.Out.pvImageBase;
+        if (    RT_SUCCESS(rc)
+            &&  OpenReq.u.Out.fNeedsLoading)
+        {
+            /*
+             * We need to load it.
+             * Allocate memory for the image bits.
+             */
+            PSUPLDRLOAD pLoadReq = (PSUPLDRLOAD)RTMemTmpAlloc(SUP_IOCTL_LDR_LOAD_SIZE(cbImageWithTabs));
+            if (pLoadReq)
+            {
+                /*
+                 * Get the image bits.
+                 */
+                rc = RTLdrGetBits(hLdrMod, &pLoadReq->u.In.abImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase,
+                                  supLoadModuleResolveImport, (void *)pszModule);
+
+                if (RT_SUCCESS(rc))
+                {
+                    /*
+                     * Get the entry points.
+                     */
+                    RTUINTPTR VMMR0EntryInt = 0;
+                    RTUINTPTR VMMR0EntryFast = 0;
+                    RTUINTPTR VMMR0EntryEx = 0;
+                    RTUINTPTR SrvReqHandler = 0;
+                    RTUINTPTR ModuleInit = 0;
+                    RTUINTPTR ModuleTerm = 0;
+                    if (fIsVMMR0)
+                    {
+                        rc = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.abImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase, "VMMR0EntryInt", &VMMR0EntryInt);
+                        if (RT_SUCCESS(rc))
+                            rc = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.abImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase, "VMMR0EntryFast", &VMMR0EntryFast);
+                        if (RT_SUCCESS(rc))
+                            rc = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.abImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase, "VMMR0EntryEx", &VMMR0EntryEx);
+                    }
+                    else if (pszSrvReqHandler)
+                        rc = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.abImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase, pszSrvReqHandler, &SrvReqHandler);
+                    if (RT_SUCCESS(rc))
+                    {
+                        int rc2 = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.abImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase, "ModuleInit", &ModuleInit);
+                        if (RT_FAILURE(rc2))
+                            ModuleInit = 0;
+
+                        rc2 = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.abImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase, "ModuleTerm", &ModuleTerm);
+                        if (RT_FAILURE(rc2))
+                            ModuleTerm = 0;
+                    }
+                    if (RT_SUCCESS(rc))
+                    {
+                        /*
+                         * Create the symbol and string tables.
+                         */
+                        SUPLDRCREATETABSARGS CreateArgs;
+                        CreateArgs.cbImage = CalcArgs.cbImage;
+                        CreateArgs.pSym    = (PSUPLDRSYM)&pLoadReq->u.In.abImage[offSymTab];
+                        CreateArgs.pszBase =     (char *)&pLoadReq->u.In.abImage[offStrTab];
+                        CreateArgs.psz     = CreateArgs.pszBase;
+                        rc = RTLdrEnumSymbols(hLdrMod, 0, NULL, 0, supLoadModuleCreateTabsCB, &CreateArgs);
+                        if (RT_SUCCESS(rc))
+                        {
+                            AssertRelease((size_t)(CreateArgs.psz - CreateArgs.pszBase) <= CalcArgs.cbStrings);
+                            AssertRelease((size_t)(CreateArgs.pSym - (PSUPLDRSYM)&pLoadReq->u.In.abImage[offSymTab]) <= CalcArgs.cSymbols);
+
+                            /*
+                             * Upload the image.
+                             */
+                            pLoadReq->Hdr.u32Cookie = g_u32Cookie;
+                            pLoadReq->Hdr.u32SessionCookie = g_u32SessionCookie;
+                            pLoadReq->Hdr.cbIn = SUP_IOCTL_LDR_LOAD_SIZE_IN(cbImageWithTabs);
+                            pLoadReq->Hdr.cbOut = SUP_IOCTL_LDR_LOAD_SIZE_OUT;
+                            pLoadReq->Hdr.fFlags = SUPREQHDR_FLAGS_MAGIC | SUPREQHDR_FLAGS_EXTRA_IN;
+                            pLoadReq->Hdr.rc = VERR_INTERNAL_ERROR;
+
+                            pLoadReq->u.In.pfnModuleInit              = (RTR0PTR)ModuleInit;
+                            pLoadReq->u.In.pfnModuleTerm              = (RTR0PTR)ModuleTerm;
+                            if (fIsVMMR0)
+                            {
+                                pLoadReq->u.In.eEPType                = SUPLDRLOADEP_VMMR0;
+                                pLoadReq->u.In.EP.VMMR0.pvVMMR0       = OpenReq.u.Out.pvImageBase;
+                                pLoadReq->u.In.EP.VMMR0.pvVMMR0EntryInt = (RTR0PTR)VMMR0EntryInt;
+                                pLoadReq->u.In.EP.VMMR0.pvVMMR0EntryFast= (RTR0PTR)VMMR0EntryFast;
+                                pLoadReq->u.In.EP.VMMR0.pvVMMR0EntryEx  = (RTR0PTR)VMMR0EntryEx;
+                            }
+                            else if (pszSrvReqHandler)
+                            {
+                                pLoadReq->u.In.eEPType                = SUPLDRLOADEP_SERVICE;
+                                pLoadReq->u.In.EP.Service.pfnServiceReq = (RTR0PTR)SrvReqHandler;
+                                pLoadReq->u.In.EP.Service.apvReserved[0] = NIL_RTR0PTR;
+                                pLoadReq->u.In.EP.Service.apvReserved[1] = NIL_RTR0PTR;
+                                pLoadReq->u.In.EP.Service.apvReserved[2] = NIL_RTR0PTR;
+                            }
+                            else
+                                pLoadReq->u.In.eEPType                = SUPLDRLOADEP_NOTHING;
+                            pLoadReq->u.In.offStrTab                  = offStrTab;
+                            pLoadReq->u.In.cbStrTab                   = (uint32_t)CalcArgs.cbStrings;
+                            AssertRelease(pLoadReq->u.In.cbStrTab == CalcArgs.cbStrings);
+                            pLoadReq->u.In.cbImageBits                = (uint32_t)CalcArgs.cbImage;
+                            pLoadReq->u.In.offSymbols                 = offSymTab;
+                            pLoadReq->u.In.cSymbols                   = CalcArgs.cSymbols;
+                            pLoadReq->u.In.cbImageWithTabs            = cbImageWithTabs;
+                            pLoadReq->u.In.pvImageBase                = OpenReq.u.Out.pvImageBase;
+                            if (!g_uSupFakeMode)
+                            {
+                                rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_LDR_LOAD, pLoadReq, SUP_IOCTL_LDR_LOAD_SIZE(cbImageWithTabs));
+                                if (RT_SUCCESS(rc))
+                                    rc = pLoadReq->Hdr.rc;
+                                else
+                                    LogRel(("SUP: SUP_IOCTL_LDR_LOAD ioctl for %s (%s) failed rc=%Rrc\n", pszModule, pszFilename, rc));
+                            }
+                            else
+                                rc = VINF_SUCCESS;
+                            if (    RT_SUCCESS(rc)
+                                ||  rc == VERR_ALREADY_LOADED /* A competing process. */
+                               )
+                            {
+                                LogRel(("SUP: Loaded %s (%s) at %#p - ModuleInit at %RTptr and ModuleTerm at %RTptr%s\n",
+                                        pszModule, pszFilename, OpenReq.u.Out.pvImageBase, ModuleInit, ModuleTerm,
+                                        OpenReq.u.Out.fNativeLoader ? " using the native ring-0 loader" : ""));
+                                if (fIsVMMR0)
+                                {
+                                    g_pvVMMR0 = OpenReq.u.Out.pvImageBase;
+                                    LogRel(("SUP: VMMR0EntryEx located at %RTptr, VMMR0EntryFast at %RTptr and VMMR0EntryInt at %RTptr\n",
+                                            VMMR0EntryEx, VMMR0EntryFast, VMMR0EntryInt));
+                                }
+#ifdef RT_OS_WINDOWS
+                                LogRel(("SUP: windbg> .reload /f %s=%#p\n", pszFilename, OpenReq.u.Out.pvImageBase));
+#endif
+
+                                RTMemTmpFree(pLoadReq);
+                                RTLdrClose(hLdrMod);
+                                return VINF_SUCCESS;
+                            }
+                            else
+                                LogRel(("SUP: Loading failed for %s (%s) rc=%Rrc\n", pszModule, pszFilename, rc));
+                        }
+                        else
+                            LogRel(("SUP: RTLdrEnumSymbols failed for %s (%s) rc=%Rrc\n", pszModule, pszFilename, rc));
+                    }
+                    else
+                        LogRel(("SUP: Failed to get entry points for %s (%s) rc=%Rrc\n", pszModule, pszFilename, rc));
+                }
+                else
+                    LogRel(("SUP: RTLdrGetBits failed for %s (%s). rc=%Rrc\n", pszModule, pszFilename, rc));
+                RTMemTmpFree(pLoadReq);
+            }
+            else
+            {
+                AssertMsgFailed(("failed to allocated %u bytes for SUPLDRLOAD_IN structure!\n", SUP_IOCTL_LDR_LOAD_SIZE(cbImageWithTabs)));
+                rc = VERR_NO_TMP_MEMORY;
+            }
+        }
+        else if (RT_SUCCESS(rc))
+        {
+            if (fIsVMMR0)
+                g_pvVMMR0 = OpenReq.u.Out.pvImageBase;
+            LogRel(("SUP: Opened %s (%s) at %#p.\n", pszModule, pszFilename, OpenReq.u.Out.pvImageBase,
+                    OpenReq.u.Out.fNativeLoader ? " loaded by the native ring-0 loader" : ""));
+#ifdef RT_OS_WINDOWS
+            LogRel(("SUP: windbg> .reload /f %s=%#p\n", pszFilename, OpenReq.u.Out.pvImageBase));
+#endif
+        }
+    }
+    RTLdrClose(hLdrMod);
+    return rc;
+}
+
+
+SUPR3DECL(int) SUPR3FreeModule(void *pvImageBase)
+{
+    /* fake */
+    if (RT_UNLIKELY(g_uSupFakeMode))
+    {
+        g_pvVMMR0 = NIL_RTR0PTR;
+        return VINF_SUCCESS;
+    }
+
+    /*
+     * Free the requested module.
+     */
+    SUPLDRFREE Req;
+    Req.Hdr.u32Cookie = g_u32Cookie;
+    Req.Hdr.u32SessionCookie = g_u32SessionCookie;
+    Req.Hdr.cbIn = SUP_IOCTL_LDR_FREE_SIZE_IN;
+    Req.Hdr.cbOut = SUP_IOCTL_LDR_FREE_SIZE_OUT;
+    Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
+    Req.Hdr.rc = VERR_INTERNAL_ERROR;
+    Req.u.In.pvImageBase = (RTR0PTR)pvImageBase;
+    int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_LDR_FREE, &Req, SUP_IOCTL_LDR_FREE_SIZE);
+    if (RT_SUCCESS(rc))
+        rc = Req.Hdr.rc;
+    if (    RT_SUCCESS(rc)
+        &&  (RTR0PTR)pvImageBase == g_pvVMMR0)
+        g_pvVMMR0 = NIL_RTR0PTR;
+    return rc;
+}
+
+
+SUPR3DECL(int) SUPR3GetSymbolR0(void *pvImageBase, const char *pszSymbol, void **ppvValue)
+{
+    *ppvValue = NULL;
+
+    /* fake */
+    if (RT_UNLIKELY(g_uSupFakeMode))
+    {
+        *ppvValue = (void *)(uintptr_t)0xdeadf00d;
+        return VINF_SUCCESS;
+    }
+
+    /*
+     * Do ioctl.
+     */
+    SUPLDRGETSYMBOL Req;
+    Req.Hdr.u32Cookie = g_u32Cookie;
+    Req.Hdr.u32SessionCookie = g_u32SessionCookie;
+    Req.Hdr.cbIn = SUP_IOCTL_LDR_GET_SYMBOL_SIZE_IN;
+    Req.Hdr.cbOut = SUP_IOCTL_LDR_GET_SYMBOL_SIZE_OUT;
+    Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;
+    Req.Hdr.rc = VERR_INTERNAL_ERROR;
+    Req.u.In.pvImageBase = (RTR0PTR)pvImageBase;
+    size_t cchSymbol = strlen(pszSymbol);
+    if (cchSymbol >= sizeof(Req.u.In.szSymbol))
+        return VERR_SYMBOL_NOT_FOUND;
+    memcpy(Req.u.In.szSymbol, pszSymbol, cchSymbol + 1);
+    int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_LDR_GET_SYMBOL, &Req, SUP_IOCTL_LDR_GET_SYMBOL_SIZE);
+    if (RT_SUCCESS(rc))
+        rc = Req.Hdr.rc;
+    if (RT_SUCCESS(rc))
+        *ppvValue = (void *)Req.u.Out.pvSymbol;
+    return rc;
+}
+
+
+SUPR3DECL(int) SUPR3LoadVMM(const char *pszFilename)
+{
+    void *pvImageBase;
+    return SUPR3LoadModule(pszFilename, "VMMR0.r0", &pvImageBase, NULL /*pErrInfo*/);
+}
+
+
+SUPR3DECL(int) SUPR3UnloadVMM(void)
+{
+    return SUPR3FreeModule((void*)g_pvVMMR0);
+}
+
+
+/**
+ * Worker for SUPR3HardenedLdrLoad and SUPR3HardenedLdrLoadAppPriv.
+ *
+ * @returns iprt status code.
+ * @param   pszFilename     The full file name.
+ * @param   phLdrMod        Where to store the handle to the loaded module.
+ * @param   fFlags          See RTLDFLAGS_.
+ * @param   pErrInfo        Where to return extended error information.
+ *                          Optional.
+ *
+ */
+static int supR3HardenedLdrLoadIt(const char *pszFilename, PRTLDRMOD phLdrMod, uint32_t fFlags, PRTERRINFO pErrInfo)
+{
+#ifdef VBOX_WITH_HARDENING
+    /*
+     * Verify the image file.
+     */
+    int rc = supR3HardenedVerifyFixedFile(pszFilename, false /* fFatal */);
+    if (RT_FAILURE(rc))
+    {
+        LogRel(("supR3HardenedLdrLoadIt: Verification of \"%s\" failed, rc=%Rrc\n", pszFilename, rc));
+        return RTErrInfoSet(pErrInfo, rc, "supR3HardenedVerifyFixedFile failed");
+    }
+#endif
+
+    /*
+     * Try load it.
+     */
+    return RTLdrLoadEx(pszFilename, phLdrMod, fFlags, pErrInfo);
+}
+
+
+SUPR3DECL(int) SUPR3HardenedLdrLoad(const char *pszFilename, PRTLDRMOD phLdrMod, uint32_t fFlags, PRTERRINFO pErrInfo)
+{
+    /*
+     * Validate input.
+     */
+    RTErrInfoClear(pErrInfo);
+    AssertPtrReturn(pszFilename, VERR_INVALID_POINTER);
+    AssertPtrReturn(phLdrMod, VERR_INVALID_POINTER);
+    *phLdrMod = NIL_RTLDRMOD;
+    AssertReturn(RTPathHavePath(pszFilename), VERR_INVALID_PARAMETER);
+
+    /*
+     * Add the default extension if it's missing.
+     */
+    if (!RTPathHasSuffix(pszFilename))
+    {
+        const char *pszSuff = RTLdrGetSuff();
+        size_t      cchSuff = strlen(pszSuff);
+        size_t      cchFilename = strlen(pszFilename);
+        char       *psz = (char *)alloca(cchFilename + cchSuff + 1);
+        AssertReturn(psz, VERR_NO_TMP_MEMORY);
+        memcpy(psz, pszFilename, cchFilename);
+        memcpy(psz + cchFilename, pszSuff, cchSuff + 1);
+        pszFilename = psz;
+    }
+
+    /*
+     * Pass it on to the common library loader.
+     */
+    return supR3HardenedLdrLoadIt(pszFilename, phLdrMod, fFlags, pErrInfo);
+}
+
+
+SUPR3DECL(int) SUPR3HardenedLdrLoadAppPriv(const char *pszFilename, PRTLDRMOD phLdrMod, uint32_t fFlags, PRTERRINFO pErrInfo)
+{
+    LogFlow(("SUPR3HardenedLdrLoadAppPriv: pszFilename=%p:{%s} phLdrMod=%p fFlags=%08x pErrInfo=%p\n", pszFilename, pszFilename, phLdrMod, fFlags, pErrInfo));
+
+    /*
+     * Validate input.
+     */
+    RTErrInfoClear(pErrInfo);
+    AssertPtrReturn(phLdrMod, VERR_INVALID_PARAMETER);
+    *phLdrMod = NIL_RTLDRMOD;
+    AssertPtrReturn(pszFilename, VERR_INVALID_PARAMETER);
+    AssertMsgReturn(!RTPathHavePath(pszFilename), ("%s\n", pszFilename), VERR_INVALID_PARAMETER);
+
+    /*
+     * Check the filename.
+     */
+    size_t cchFilename = strlen(pszFilename);
+    AssertMsgReturn(cchFilename < (RTPATH_MAX / 4) * 3, ("%zu\n", cchFilename), VERR_INVALID_PARAMETER);
+
+    const char *pszExt = "";
+    size_t cchExt = 0;
+    if (!RTPathHasSuffix(pszFilename))
+    {
+        pszExt = RTLdrGetSuff();
+        cchExt = strlen(pszExt);
+    }
+
+    /*
+     * Construct the private arch path and check if the file exists.
+     */
+    char szPath[RTPATH_MAX];
+    int rc = RTPathAppPrivateArch(szPath, sizeof(szPath) - 1 - cchExt - cchFilename);
+    AssertRCReturn(rc, rc);
+
+    char *psz = strchr(szPath, '\0');
+    *psz++ = RTPATH_SLASH;
+    memcpy(psz, pszFilename, cchFilename);
+    psz += cchFilename;
+    memcpy(psz, pszExt, cchExt + 1);
+
+    if (!RTPathExists(szPath))
+    {
+        LogRel(("SUPR3HardenedLdrLoadAppPriv: \"%s\" not found\n", szPath));
+        return VERR_FILE_NOT_FOUND;
+    }
+
+    /*
+     * Pass it on to SUPR3HardenedLdrLoad.
+     */
+    rc = SUPR3HardenedLdrLoad(szPath, phLdrMod, fFlags, pErrInfo);
+
+    LogFlow(("SUPR3HardenedLdrLoadAppPriv: returns %Rrc\n", rc));
+    return rc;
+}
+
+
+SUPR3DECL(int) SUPR3HardenedLdrLoadPlugIn(const char *pszFilename, PRTLDRMOD phLdrMod, PRTERRINFO pErrInfo)
+{
+    /*
+     * Validate input.
+     */
+    RTErrInfoClear(pErrInfo);
+    AssertPtrReturn(phLdrMod, VERR_INVALID_PARAMETER);
+    *phLdrMod = NIL_RTLDRMOD;
+    AssertPtrReturn(pszFilename, VERR_INVALID_PARAMETER);
+    AssertReturn(RTPathStartsWithRoot(pszFilename), VERR_INVALID_PARAMETER);
+
+#ifdef VBOX_WITH_HARDENING
+    /*
+     * Verify the image file.
+     */
+    int rc = supR3HardenedVerifyFile(pszFilename, RTHCUINTPTR_MAX, pErrInfo);
+    if (RT_FAILURE(rc))
+    {
+        if (!RTErrInfoIsSet(pErrInfo))
+            LogRel(("supR3HardenedVerifyFile: Verification of \"%s\" failed, rc=%Rrc\n", pszFilename, rc));
+        return rc;
+    }
+#endif
+
+    /*
+     * Try load it.
+     */
+    return RTLdrLoadEx(pszFilename, phLdrMod, RTLDRLOAD_FLAGS_LOCAL, pErrInfo);
+}
+
+
Index: /trunk/src/VBox/HostDrivers/Support/darwin/SUPDrv-darwin.cpp
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/darwin/SUPDrv-darwin.cpp	(revision 49633)
+++ /trunk/src/VBox/HostDrivers/Support/darwin/SUPDrv-darwin.cpp	(revision 49634)
@@ -943,4 +943,30 @@
 
 
+#ifdef SUPDRV_WITH_MSR_PROBER
+
+int VBOXCALL    supdrvOSMsrProberRead(uint32_t uMsr, RTCPUID idCpu, uint64_t *puValue)
+{
+    NOREF(uMsr); NOREF(idCpu); NOREF(puValue);
+    return VERR_NOT_SUPPORTED;
+}
+
+
+int VBOXCALL    supdrvOSMsrProberWrite(uint32_t uMsr, RTCPUID idCpu, uint64_t uValue)
+{
+    NOREF(uMsr); NOREF(idCpu); NOREF(uValue);
+    return VERR_NOT_SUPPORTED;
+}
+
+
+int VBOXCALL    supdrvOSMsrProberModify(RTCPUID idCpu, PSUPMSRPROBER pReq)
+{
+    NOREF(idCpu); NOREF(pReq);
+    return VERR_NOT_SUPPORTED;
+}
+
+#endif /* SUPDRV_WITH_MSR_PROBER */
+
+
+
 /**
  * Converts an IPRT error code to a darwin error code.
Index: /trunk/src/VBox/HostDrivers/Support/freebsd/SUPDrv-freebsd.c
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/freebsd/SUPDrv-freebsd.c	(revision 49633)
+++ /trunk/src/VBox/HostDrivers/Support/freebsd/SUPDrv-freebsd.c	(revision 49634)
@@ -552,4 +552,29 @@
 
 
+#ifdef SUPDRV_WITH_MSR_PROBER
+
+int VBOXCALL    supdrvOSMsrProberRead(uint32_t uMsr, RTCPUID idCpu, uint64_t *puValue)
+{
+    NOREF(uMsr); NOREF(idCpu); NOREF(puValue);
+    return VERR_NOT_SUPPORTED;
+}
+
+
+int VBOXCALL    supdrvOSMsrProberWrite(uint32_t uMsr, RTCPUID idCpu, uint64_t uValue)
+{
+    NOREF(uMsr); NOREF(idCpu); NOREF(uValue);
+    return VERR_NOT_SUPPORTED;
+}
+
+
+int VBOXCALL    supdrvOSMsrProberModify(RTCPUID idCpu, PSUPMSRPROBER pReq)
+{
+    NOREF(idCpu); NOREF(pReq);
+    return VERR_NOT_SUPPORTED;
+}
+
+#endif /* SUPDRV_WITH_MSR_PROBER */
+
+
 SUPR0DECL(int) SUPR0Printf(const char *pszFormat, ...)
 {
Index: /trunk/src/VBox/HostDrivers/Support/linux/SUPDrv-linux.c
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/linux/SUPDrv-linux.c	(revision 49633)
+++ /trunk/src/VBox/HostDrivers/Support/linux/SUPDrv-linux.c	(revision 49634)
@@ -60,4 +60,10 @@
 # include <linux/platform_device.h>
 #endif
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)) && defined(SUPDRV_WITH_MSR_PROBER)
+# define SUPDRV_LINUX_HAS_SAFE_MSR_API
+# include <asm/msr.h>
+# include <iprt/asm-amd64-x86.h>
+#endif
+
 
 
@@ -853,4 +859,129 @@
 
 
+#ifdef SUPDRV_WITH_MSR_PROBER
+
+int VBOXCALL    supdrvOSMsrProberRead(uint32_t uMsr, RTCPUID idCpu, uint64_t *puValue)
+{
+# ifdef SUPDRV_LINUX_HAS_SAFE_MSR_API
+    uint32_t u32Low, u32High;
+    int rc;
+
+    if (idCpu == NIL_RTCPUID)
+        idCpu = RTMpCpuId();
+    else if (!RTMpIsCpuOnline(idCpu))
+        return VERR_CPU_OFFLINE;
+    rc = rdmsr_safe_on_cpu(idCpu, uMsr, &u32Low, &u32High);
+    if (rc >= 0)
+    {
+        *puValue = RT_MAKE_U64(u32Low, u32High);
+        return VINF_SUCCESS;
+    }
+    return VERR_ACCESS_DENIED;
+# else
+    return VERR_NOT_SUPPORTED;
+# endif
+}
+
+
+int VBOXCALL    supdrvOSMsrProberWrite(uint32_t uMsr, RTCPUID idCpu, uint64_t uValue)
+{
+# ifdef SUPDRV_LINUX_HAS_SAFE_MSR_API
+    int rc;
+
+    if (idCpu == NIL_RTCPUID)
+        idCpu = RTMpCpuId();
+    else if (!RTMpIsCpuOnline(idCpu))
+        return VERR_CPU_OFFLINE;
+    rc = wrmsr_safe_on_cpu(idCpu, uMsr, RT_LODWORD(uValue), RT_HIDWORD(uValue));
+    if (rc >= 0)
+        return VINF_SUCCESS;
+    return VERR_ACCESS_DENIED;
+# else
+    return VERR_NOT_SUPPORTED;
+# endif
+}
+
+# ifdef SUPDRV_LINUX_HAS_SAFE_MSR_API
+/**
+ * Worker for supdrvOSMsrProberModify.
+ */
+static DECLCALLBACK(void) supdrvOsMsrProberModifyOnCpu(RTCPUID idCpu, void *pvUser1, void *pvUser2)
+{
+    PSUPMSRPROBER               pReq    = (PSUPMSRPROBER)pvUser1;
+    register uint32_t           uMsr    = pReq->u.In.uMsr;
+    bool const                  fFaster = pReq->u.In.enmOp == SUPMSRPROBEROP_MODIFY_FASTER;
+    uint64_t                    uBefore;
+    uint64_t                    uWritten;
+    uint64_t                    uAfter;
+    int                         rcBefore, rcWrite, rcAfter, rcRestore;
+    RTCCUINTREG                 fOldFlags;
+
+    /* Initialize result variables. */
+    uBefore = uWritten = uAfter    = 0;
+    rcWrite = rcAfter  = rcRestore = -EIO;
+
+    /*
+     * Do the job.
+     */
+    fOldFlags = ASMIntDisableFlags();
+    ASMCompilerBarrier(); /* paranoia */
+    if (!fFaster)
+        ASMWriteBackAndInvalidateCaches();
+
+    rcBefore = rdmsrl_safe(uMsr, &uBefore);
+    if (rcBefore >= 0)
+    {
+        register uint64_t uRestore = uBefore;
+        uWritten  = uRestore;
+        uWritten &= pReq->u.In.uArgs.Modify.fAndMask;
+        uWritten |= pReq->u.In.uArgs.Modify.fOrMask;
+
+        rcWrite   = wrmsr_safe(uMsr, RT_LODWORD(uWritten), RT_HIDWORD(uWritten));
+        rcAfter   = rdmsrl_safe(uMsr, &uAfter);
+        rcRestore = wrmsr_safe(uMsr, RT_LODWORD(uRestore), RT_HIDWORD(uRestore));
+
+        if (!fFaster)
+        {
+            ASMWriteBackAndInvalidateCaches();
+            ASMReloadCR3();
+            ASMNopPause();
+        }
+    }
+
+    ASMCompilerBarrier(); /* paranoia */
+    ASMSetFlags(fOldFlags);
+
+    /*
+     * Write out the results.
+     */
+    pReq->u.Out.uResults.Modify.uBefore    = uBefore;
+    pReq->u.Out.uResults.Modify.uWritten   = uWritten;
+    pReq->u.Out.uResults.Modify.uAfter     = uAfter;
+    pReq->u.Out.uResults.Modify.fBeforeGp  = rcBefore  < 0;
+    pReq->u.Out.uResults.Modify.fModifyGp  = rcWrite   < 0;
+    pReq->u.Out.uResults.Modify.fAfterGp   = rcAfter   < 0;
+    pReq->u.Out.uResults.Modify.fRestoreGp = rcRestore < 0;
+    RT_ZERO(pReq->u.Out.uResults.Modify.afReserved);
+}
+
+# endif
+
+
+int VBOXCALL    supdrvOSMsrProberModify(RTCPUID idCpu, PSUPMSRPROBER pReq)
+{
+# ifdef SUPDRV_LINUX_HAS_SAFE_MSR_API
+    if (idCpu == NIL_RTCPUID)
+        idCpu = RTMpCpuId();
+    else if (!RTMpIsCpuOnline(idCpu))
+        return VERR_CPU_OFFLINE;
+    return RTMpOnSpecific(idCpu, supdrvOsMsrProberModifyOnCpu, pReq, NULL);
+# else
+    return VERR_NOT_SUPPORTED;
+# endif
+}
+
+#endif /* SUPDRV_WITH_MSR_PROBER */
+
+
 /**
  * Converts a supdrv error code to an linux error code.
Index: /trunk/src/VBox/HostDrivers/Support/os2/SUPDrv-os2.cpp
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/os2/SUPDrv-os2.cpp	(revision 49633)
+++ /trunk/src/VBox/HostDrivers/Support/os2/SUPDrv-os2.cpp	(revision 49634)
@@ -421,4 +421,29 @@
 
 
+#ifdef SUPDRV_WITH_MSR_PROBER
+
+int VBOXCALL    supdrvOSMsrProberRead(uint32_t uMsr, RTCPUID idCpu, uint64_t *puValue)
+{
+    NOREF(uMsr); NOREF(idCpu); NOREF(puValue);
+    return VERR_NOT_SUPPORTED;
+}
+
+
+int VBOXCALL    supdrvOSMsrProberWrite(uint32_t uMsr, RTCPUID idCpu, uint64_t uValue)
+{
+    NOREF(uMsr); NOREF(idCpu); NOREF(uValue);
+    return VERR_NOT_SUPPORTED;
+}
+
+
+int VBOXCALL    supdrvOSMsrProberModify(RTCPUID idCpu, PSUPMSRPROBER pReq)
+{
+    NOREF(idCpu); NOREF(pReq);
+    return VERR_NOT_SUPPORTED;
+}
+
+#endif /* SUPDRV_WITH_MSR_PROBER */
+
+
 /**
  * Callback for writing to the log buffer.
Index: /trunk/src/VBox/HostDrivers/Support/solaris/SUPDrv-solaris.c
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/solaris/SUPDrv-solaris.c	(revision 49633)
+++ /trunk/src/VBox/HostDrivers/Support/solaris/SUPDrv-solaris.c	(revision 49634)
@@ -1189,4 +1189,29 @@
 
 
+#ifdef SUPDRV_WITH_MSR_PROBER
+
+int VBOXCALL    supdrvOSMsrProberRead(uint32_t uMsr, RTCPUID idCpu, uint64_t *puValue)
+{
+    NOREF(uMsr); NOREF(idCpu); NOREF(puValue);
+    return VERR_NOT_SUPPORTED;
+}
+
+
+int VBOXCALL    supdrvOSMsrProberWrite(uint32_t uMsr, RTCPUID idCpu, uint64_t uValue)
+{
+    NOREF(uMsr); NOREF(idCpu); NOREF(uValue);
+    return VERR_NOT_SUPPORTED;
+}
+
+
+int VBOXCALL    supdrvOSMsrProberModify(RTCPUID idCpu, PSUPMSRPROBER pReq)
+{
+    NOREF(idCpu); NOREF(pReq);
+    return VERR_NOT_SUPPORTED;
+}
+
+#endif /* SUPDRV_WITH_MSR_PROBER */
+
+
 RTDECL(int) SUPR0Printf(const char *pszFormat, ...)
 {
Index: /trunk/src/VBox/HostDrivers/Support/win/SUPDrv-win.cpp
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/win/SUPDrv-win.cpp	(revision 49633)
+++ /trunk/src/VBox/HostDrivers/Support/win/SUPDrv-win.cpp	(revision 49634)
@@ -1035,4 +1035,29 @@
 
 
+#ifdef SUPDRV_WITH_MSR_PROBER
+
+int VBOXCALL    supdrvOSMsrProberRead(uint32_t uMsr, RTCPUID idCpu, uint64_t *puValue)
+{
+    NOREF(uMsr); NOREF(idCpu); NOREF(puValue);
+    return VERR_NOT_SUPPORTED;
+}
+
+
+int VBOXCALL    supdrvOSMsrProberWrite(uint32_t uMsr, RTCPUID idCpu, uint64_t uValue)
+{
+    NOREF(uMsr); NOREF(idCpu); NOREF(uValue);
+    return VERR_NOT_SUPPORTED;
+}
+
+
+int VBOXCALL    supdrvOSMsrProberModify(RTCPUID idCpu, PSUPMSRPROBER pReq)
+{
+    NOREF(idCpu); NOREF(pReq);
+    return VERR_NOT_SUPPORTED;
+}
+
+#endif /* SUPDRV_WITH_MSR_PROBER */
+
+
 /**
  * Converts an IPRT error code to an nt status code.
Index: /trunk/src/VBox/Runtime/VBox/VBoxRTDeps.cpp
===================================================================
--- /trunk/src/VBox/Runtime/VBox/VBoxRTDeps.cpp	(revision 49633)
+++ /trunk/src/VBox/Runtime/VBox/VBoxRTDeps.cpp	(revision 49634)
@@ -55,4 +55,5 @@
     (PFNRT)SUPR3Init,
     (PFNRT)SUPR3PageAllocEx,
+    (PFNRT)SUPR3LoadVMM,
     (PFNRT)SUPSemEventCreate,
     (PFNRT)SUPTracerFireProbe,
