Index: /trunk/include/VBox/pdmapi.h
===================================================================
--- /trunk/include/VBox/pdmapi.h	(revision 28424)
+++ /trunk/include/VBox/pdmapi.h	(revision 28425)
@@ -36,4 +36,5 @@
 
 #include <VBox/types.h>
+#include <VBox/sup.h>
 
 RT_C_DECLS_BEGIN
@@ -57,5 +58,5 @@
 VMMDECL(bool)   PDMVMMDevHeapIsEnabled(PVM pVM);
 
-#ifdef IN_RING3
+
 /** @defgroup grp_pdm_r3    The PDM Host Context Ring-3 API
  * @ingroup grp_pdm
@@ -129,14 +130,44 @@
 VMMR3DECL(void) PDMR3ReleaseOwnedLocks(PVM pVM);
 /** @} */
-#endif
 
 
-#ifdef IN_RC
-/** @defgroup grp_pdm_gc    The PDM Guest Context API
+
+/** @defgroup grp_pdm_rc    The PDM Raw-Mode Context API
  * @ingroup grp_pdm
  * @{
  */
 /** @} */
-#endif
+
+
+
+/** @defgroup grp_pdm_r0    The PDM Ring-0 Context API
+ * @ingroup grp_pdm
+ * @{
+ */
+
+/**
+ * Request buffer for PDMR0DriverCallReqHandler / VMMR0_DO_PDM_DRIVER_CALL_REQ_HANDLER.
+ * @see PDMR0DriverCallReqHandler.
+ */
+typedef struct PDMDRIVERCALLREQHANDLERREQ
+{
+    /** The header. */
+    SUPVMMR0REQHDR      Hdr;
+    /** The driver instance. */
+    PPDMDRVINSR0        pDrvInsR0;
+    /** The operation. */
+    uint32_t            uOperation;
+    /** Explicit alignment padding. */
+    uint32_t            u32Alignment;
+    /** Optional 64-bit integer argument. */
+    uint64_t            u64Arg;
+} PDMDRIVERCALLREQHANDLERREQ;
+/** Pointer to a PDMR0DriverCallReqHandler / VMMR0_DO_PDM_DRIVER_CALL_REQ_HANDLER
+ * request buffer. */
+typedef PDMDRIVERCALLREQHANDLERREQ *PPDMDRIVERCALLREQHANDLERREQ;
+
+VMMR0_INT_DECL(int) PDMR0DriverCallReqHandler(PVM pVM, PPDMDRIVERCALLREQHANDLERREQ pReq);
+
+/** @} */
 
 RT_C_DECLS_END
Index: /trunk/include/VBox/pdmcommon.h
===================================================================
--- /trunk/include/VBox/pdmcommon.h	(revision 28424)
+++ /trunk/include/VBox/pdmcommon.h	(revision 28425)
@@ -136,4 +136,16 @@
 typedef FNPDMDRVASYNCNOTIFY *PFNPDMDRVASYNCNOTIFY;
 
+/**
+ * The ring-0 driver request handle.
+ *
+ * @returns VBox status code. PDMDrvHlpCallR0 will return this.
+ * @param   pDrvIns     The driver instance (the ring-0 mapping).
+ * @param   uOperation  The operation.
+ * @param   u64Arg      Optional integer argument for the operation.
+ */
+typedef DECLCALLBACK(int) FNPDMDRVREQHANDLERR0(PPDMDRVINS pDrvIns, uint32_t uOperation, uint64_t u64Arg);
+/** Ring-0 pointer to a FNPDMDRVREQHANDLERR0. */
+typedef R0PTRTYPE(FNPDMDRVREQHANDLERR0 *) PFNPDMDRVREQHANDLERR0;
+
 /** @} */
 
Index: /trunk/include/VBox/pdmdrv.h
===================================================================
--- /trunk/include/VBox/pdmdrv.h	(revision 28424)
+++ /trunk/include/VBox/pdmdrv.h	(revision 28425)
@@ -403,5 +403,22 @@
 
 /** Converts a pointer to the PDMDRVINS::IBase to a pointer to PDMDRVINS. */
-#define PDMIBASE_2_PDMDRV(pInterface) ( (PPDMDRVINS)((char *)(pInterface) - RT_OFFSETOF(PDMDRVINS, IBase)) )
+#define PDMIBASE_2_PDMDRV(pInterface)   ( (PPDMDRVINS)((char *)(pInterface) - RT_OFFSETOF(PDMDRVINS, IBase)) )
+
+/** @def PDMDRVINS_2_RCPTR
+ * Converts a PDM Driver instance pointer a RC PDM Driver instance pointer.
+ */
+#define PDMDRVINS_2_RCPTR(pDrvIns)      ( (RCPTRTYPE(PPDMDRVINS))((RTGCUINTPTR)(pDrvIns)->pvInstanceDataRC - RT_OFFSETOF(PDMDRVINS, achInstanceData)) )
+
+/** @def PDMDRVINS_2_R3PTR
+ * Converts a PDM Driver instance pointer a R3 PDM Driver instance pointer.
+ */
+#define PDMDRVINS_2_R3PTR(pDrvIns)      ( (R3PTRTYPE(PPDMDRVINS))((RTHCUINTPTR)(pDrvIns)->pvInstanceDataR3 - RT_OFFSETOF(PDMDRVINS, achInstanceData)) )
+
+/** @def PDMDRVINS_2_R0PTR
+ * Converts a PDM Driver instance pointer a R0 PDM Driver instance pointer.
+ */
+#define PDMDRVINS_2_R0PTR(pDrvIns)      ( (R0PTRTYPE(PPDMDRVINS))((RTR0UINTPTR)(pDrvIns)->pvInstanceDataR0 - RT_OFFSETOF(PDMDRVINS, achInstanceData)) )
+
+
 
 /**
@@ -1160,4 +1177,26 @@
     DECLR3CALLBACKMEMBER(int, pfnCritSectInit,(PPDMDRVINS pDrvIns, PPDMCRITSECT pCritSect,
                                                RT_SRC_POS_DECL, const char *pszName));
+
+    /**
+     * Call the ring-0 request handler routine of the driver.
+     *
+     * For this to work, the driver must be ring-0 enabled and export a request
+     * handler function.  The name of the function must be the driver name in the
+     * PDMDRVREG struct prefixed with 'drvR0' and suffixed with 'ReqHandler'.  It
+     * shall take the exact same arguments as this function and be declared using
+     * PDMBOTHCBDECL.  See FNPDMDRVREQHANDLERR0.
+     *
+     * @returns VBox status code.
+     * @retval  VERR_SYMBOL_NOT_FOUND if the driver doesn't export the required
+     *          handler function.
+     * @retval  VERR_ACCESS_DENIED if the driver isn't ring-0 capable.
+     *
+     * @param   pDevIns             The device instance.
+     * @param   uOperation          The operation to perform.
+     * @param   u64Arg              64-bit integer argument.
+     * @thread  Any
+     */
+    DECLR3CALLBACKMEMBER(int, pfnCallR0,(PPDMDRVINS pDrvIns, uint32_t uOperation, uint64_t u64Arg));
+
     /** Just a safety precaution. */
     uint32_t                        u32TheEnd;
@@ -1526,4 +1565,12 @@
 }
 
+/**
+ * @copydoc PDMDRVHLP::pfnCallR0
+ */
+DECLINLINE(int) PDMDrvHlpCallR0(PPDMDRVINS pDrvIns, uint32_t uOperation, uint64_t u64Arg)
+{
+    return pDrvIns->pHlpR3->pfnCallR0(pDrvIns, uOperation, u64Arg);
+}
+
 
 /** Pointer to callbacks provided to the VBoxDriverRegister() call. */
Index: /trunk/include/VBox/vmm.h
===================================================================
--- /trunk/include/VBox/vmm.h	(revision 28424)
+++ /trunk/include/VBox/vmm.h	(revision 28425)
@@ -300,5 +300,5 @@
     /** Call GMMR0FreeLargePage(). */
     VMMR0_DO_GMM_FREE_LARGE_PAGE,
-    /** Call GMMR0QueryVMMMemoryStatsReq */
+    /** Call GMMR0QueryVMMMemoryStatsReq(). */
     VMMR0_DO_GMM_QUERY_VMM_MEM_STATS,
     /** Call GMMR0BalloonedPages(). */
@@ -319,4 +319,7 @@
     /** Query a GVMM or GMM configuration value. */
     VMMR0_DO_GCFGM_QUERY_VALUE,
+
+    /** Call PDMR0DriverCallReqHandler. */
+    VMMR0_DO_PDM_DRIVER_CALL_REQ_HANDLER,
 
     /** The start of the R0 service operations. */
Index: /trunk/src/VBox/VMM/PDMDriver.cpp
===================================================================
--- /trunk/src/VBox/VMM/PDMDriver.cpp	(revision 28424)
+++ /trunk/src/VBox/VMM/PDMDriver.cpp	(revision 28425)
@@ -1305,4 +1305,53 @@
 
 
+/** @interface_method_impl{PDMDRVHLP,pfnCallR0} */
+static DECLCALLBACK(int) pdmR3DrvHlp_CallR0(PPDMDRVINS pDrvIns, uint32_t uOperation, uint64_t u64Arg)
+{
+    PDMDRV_ASSERT_DRVINS(pDrvIns);
+    PVM pVM = pDrvIns->Internal.s.pVMR3;
+    LogFlow(("pdmR3DrvHlp_CallR0: caller='%s'/%d: uOperation=%#x u64Arg=%#RX64\n",
+             pDrvIns->pReg->szName, pDrvIns->iInstance, uOperation, u64Arg));
+
+    /*
+     * Lazy resolve the ring-0 entry point.
+     */
+    int rc = VINF_SUCCESS;
+    PFNPDMDRVREQHANDLERR0 pfnReqHandlerR0 = pDrvIns->Internal.s.pfnReqHandlerR0;
+    if (RT_UNLIKELY(pfnReqHandlerR0 == NIL_RTR0PTR))
+    {
+        if (pDrvIns->pReg->fFlags & PDM_DRVREG_FLAGS_R0)
+        {
+            char szSymbol[          sizeof("drvR0") + sizeof(pDrvIns->pReg->szName) + sizeof("ReqHandler")];
+            strcat(strcat(strcpy(szSymbol, "drvR0"),         pDrvIns->pReg->szName),         "ReqHandler");
+            rc = PDMR3LdrGetSymbolR0Lazy(pVM, pDrvIns->pReg->szR0Mod, szSymbol, &pfnReqHandlerR0);
+            if (RT_SUCCESS(rc))
+                pDrvIns->Internal.s.pfnReqHandlerR0 = pfnReqHandlerR0;
+            else
+                pfnReqHandlerR0 = NIL_RTR0PTR;
+        }
+        else
+            rc = VERR_ACCESS_DENIED;
+    }
+    if (RT_LIKELY(pfnReqHandlerR0 != NIL_RTR0PTR))
+    {
+        /*
+         * Make the ring-0 call.
+         */
+        PDMDRIVERCALLREQHANDLERREQ Req;
+        Req.Hdr.u32Magic    = SUPVMMR0REQHDR_MAGIC;
+        Req.Hdr.cbReq       = sizeof(Req);
+        Req.pDrvInsR0       = PDMDRVINS_2_R0PTR(pDrvIns);
+        Req.uOperation      = uOperation;
+        Req.u32Alignment    = 0;
+        Req.u64Arg          = u64Arg;
+        rc = SUPR3CallVMMR0Ex(pVM->pVMR0, NIL_VMCPUID, VMMR0_DO_PDM_DRIVER_CALL_REQ_HANDLER, 0, &Req.Hdr);
+    }
+
+    LogFlow(("pdmR3DrvHlp_CallR0: caller='%s'/%d: returns %Rrc\n", pDrvIns->pReg->szName,
+             pDrvIns->iInstance, rc));
+    return rc;
+}
+
+
 /**
  * The driver helper structure.
@@ -1343,4 +1392,5 @@
     pdmR3DrvHlp_LdrGetR0InterfaceSymbols,
     pdmR3DrvHlp_CritSectInit,
+    pdmR3DrvHlp_CallR0,
     PDM_DRVHLPR3_VERSION /* u32TheEnd */
 };
Index: /trunk/src/VBox/VMM/PDMInternal.h
===================================================================
--- /trunk/src/VBox/VMM/PDMInternal.h	(revision 28424)
+++ /trunk/src/VBox/VMM/PDMInternal.h	(revision 28425)
@@ -246,4 +246,6 @@
     /** Configuration handle to the instance node. */
     R3PTRTYPE(PCFGMNODE)            pCfgHandle;
+    /** Pointer to the ring-0 request handler function. */
+    PFNPDMDRVREQHANDLERR0           pfnReqHandlerR0;
 } PDMDRVINSINT;
 
Index: /trunk/src/VBox/VMM/VMMR0/PDMR0Driver.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR0/PDMR0Driver.cpp	(revision 28425)
+++ /trunk/src/VBox/VMM/VMMR0/PDMR0Driver.cpp	(revision 28425)
@@ -0,0 +1,61 @@
+/* $Id$ */
+/** @file
+ * PDM - Pluggable Device and Driver Manager, R0 Driver parts.
+ */
+
+/*
+ * Copyright (C) 2010 Sun Microsystems, Inc.
+ *
+ * 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.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
+ * Clara, CA 95054 USA or visit http://www.sun.com if you need
+ * additional information or have any questions.
+ */
+
+/*******************************************************************************
+*   Header Files                                                               *
+*******************************************************************************/
+#define LOG_GROUP LOG_GROUP_PDM_DRIVER
+#include "PDMInternal.h"
+#include <VBox/pdm.h>
+#include <VBox/vm.h>
+
+#include <VBox/log.h>
+#include <VBox/err.h>
+#include <iprt/assert.h>
+
+
+
+/**
+ * PDMDrvHlpCallR0 helper.
+ *
+ * @returns See PFNPDMDRVREQHANDLERR0.
+ * @param   pVM                 The VM handle (for validation).
+ * @param   pReq                The request buffer.
+ */
+VMMR0_INT_DECL(int) PDMR0DriverCallReqHandler(PVM pVM, PPDMDRIVERCALLREQHANDLERREQ pReq)
+{
+    /*
+     * Validate input and make the call.
+     */
+    AssertPtrReturn(pVM, VERR_INVALID_POINTER);
+    AssertPtrReturn(pReq, VERR_INVALID_POINTER);
+    AssertMsgReturn(pReq->Hdr.cbReq == sizeof(*pReq), ("%#x != %#x\n", pReq->Hdr.cbReq, sizeof(*pReq)), VERR_INVALID_PARAMETER);
+
+    PPDMDRVINS pDrvIns = pReq->pDrvInsR0;
+    AssertPtrReturn(pDrvIns, VERR_INVALID_POINTER);
+    AssertReturn(pDrvIns->Internal.s.pVMR0 == pVM, VERR_INVALID_PARAMETER);
+
+    PFNPDMDRVREQHANDLERR0 pfnReqHandlerR0 = pDrvIns->Internal.s.pfnReqHandlerR0;
+    AssertPtrReturn(pfnReqHandlerR0, VERR_INVALID_POINTER);
+
+    return pfnReqHandlerR0(pDrvIns, pReq->uOperation, pReq->u64Arg);
+}
+
Index: /trunk/src/VBox/VMM/VMMR0/VMMR0.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR0/VMMR0.cpp	(revision 28424)
+++ /trunk/src/VBox/VMM/VMMR0/VMMR0.cpp	(revision 28425)
@@ -28,4 +28,5 @@
 #include <VBox/trpm.h>
 #include <VBox/cpum.h>
+#include <VBox/pdmapi.h>
 #include <VBox/pgm.h>
 #include <VBox/stam.h>
@@ -824,5 +825,4 @@
         /*
          * Attempt to enable hwacc mode and check the current setting.
-         *
          */
         case VMMR0_DO_HWACC_ENABLE:
@@ -980,4 +980,13 @@
         }
 
+        /*
+         * PDM Wrappers.
+         */
+        case VMMR0_DO_PDM_DRIVER_CALL_REQ_HANDLER:
+        {
+            if (!pVM || !pReqHdr || u64Arg || idCpu != NIL_VMCPUID)
+                return VERR_INVALID_PARAMETER;
+            return PDMR0DriverCallReqHandler(pVM, (PPDMDRIVERCALLREQHANDLERREQ)pReqHdr);
+        }
 
         /*
