Index: /trunk/include/VBox/pdmapi.h
===================================================================
--- /trunk/include/VBox/pdmapi.h	(revision 29520)
+++ /trunk/include/VBox/pdmapi.h	(revision 29521)
@@ -8,5 +8,5 @@
 
 /*
- * Copyright (C) 2006-2007 Oracle Corporation
+ * Copyright (C) 2006-2010 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -33,4 +33,5 @@
 #include <VBox/types.h>
 #include <VBox/sup.h>
+#include <VBox/pdmcommon.h>
 
 RT_C_DECLS_BEGIN
@@ -167,4 +168,29 @@
 VMMR0_INT_DECL(int) PDMR0DriverCallReqHandler(PVM pVM, PPDMDRIVERCALLREQHANDLERREQ pReq);
 
+/**
+ * Request buffer for PDMR0DeviceCallReqHandler / VMMR0_DO_PDM_DEVICE_CALL_REQ_HANDLER.
+ * @see PDMR0DeviceCallReqHandler.
+ */
+typedef struct PDMDEVICECALLREQHANDLERREQ
+{
+    /** The header. */
+    SUPVMMR0REQHDR          Hdr;
+    /** The device instance. */
+    PPDMDEVINSR0            pDevInsR0;
+    /** The request handler for the device. */
+    PFNPDMDEVREQHANDLERR0   pfnReqHandlerR0;
+    /** The operation. */
+    uint32_t                uOperation;
+    /** Explicit alignment padding. */
+    uint32_t                u32Alignment;
+    /** Optional 64-bit integer argument. */
+    uint64_t                u64Arg;
+} PDMDEVICECALLREQHANDLERREQ;
+/** Pointer to a PDMR0DeviceCallReqHandler /
+ * VMMR0_DO_PDM_DEVICE_CALL_REQ_HANDLER request buffer. */
+typedef PDMDEVICECALLREQHANDLERREQ *PPDMDEVICECALLREQHANDLERREQ;
+
+VMMR0_INT_DECL(int) PDMR0DeviceCallReqHandler(PVM pVM, PPDMDEVICECALLREQHANDLERREQ pReq);
+
 /** @} */
 
Index: /trunk/include/VBox/pdmcommon.h
===================================================================
--- /trunk/include/VBox/pdmcommon.h	(revision 29520)
+++ /trunk/include/VBox/pdmcommon.h	(revision 29521)
@@ -4,5 +4,5 @@
 
 /*
- * Copyright (C) 2006-2007 Oracle Corporation
+ * Copyright (C) 2006-2010 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -132,6 +132,19 @@
 typedef FNPDMDRVASYNCNOTIFY *PFNPDMDRVASYNCNOTIFY;
 
+
 /**
- * The ring-0 driver request handle.
+ * The ring-0 driver request handler.
+ *
+ * @returns VBox status code. PDMDevHlpCallR0 will return this.
+ * @param   pDevIns     The device instance (the ring-0 mapping).
+ * @param   uOperation  The operation.
+ * @param   u64Arg      Optional integer argument for the operation.
+ */
+typedef DECLCALLBACK(int) FNPDMDEVREQHANDLERR0(PPDMDEVINS pDevIns, uint32_t uOperation, uint64_t u64Arg);
+/** Ring-0 pointer to a FNPDMDEVREQHANDLERR0. */
+typedef R0PTRTYPE(FNPDMDEVREQHANDLERR0 *) PFNPDMDEVREQHANDLERR0;
+
+/**
+ * The ring-0 driver request handler.
  *
  * @returns VBox status code. PDMDrvHlpCallR0 will return this.
@@ -144,4 +157,5 @@
 typedef R0PTRTYPE(FNPDMDRVREQHANDLERR0 *) PFNPDMDRVREQHANDLERR0;
 
+
 /** @} */
 
Index: /trunk/include/VBox/pdmdev.h
===================================================================
--- /trunk/include/VBox/pdmdev.h	(revision 29520)
+++ /trunk/include/VBox/pdmdev.h	(revision 29521)
@@ -2995,4 +2995,30 @@
                                                            const char *pszSymPrefix, const char *pszSymList));
 
+    /**
+     * Call the ring-0 request handler routine of the device.
+     *
+     * For this to work, the device must be ring-0 enabled and export a request
+     * handler function.  The name of the function must be the device name in
+     * the PDMDRVREG struct prefixed with 'drvR0' and suffixed with
+     * 'ReqHandler'.  The device name will be captialized.  It shall take the
+     * exact same arguments as this function and be declared using
+     * PDMBOTHCBDECL. See FNPDMDEVREQHANDLERR0.
+     *
+     * Unlike PDMDrvHlpCallR0, this is current unsuitable for more than a call
+     * or two as the handler address will be resolved on each invocation.  This
+     * is the reason for the EMT only restriction as well.
+     *
+     * @returns VBox status code.
+     * @retval  VERR_SYMBOL_NOT_FOUND if the device doesn't export the required
+     *          handler function.
+     * @retval  VERR_ACCESS_DENIED if the device isn't ring-0 capable.
+     *
+     * @param   pDevIns             The device instance.
+     * @param   uOperation          The operation to perform.
+     * @param   u64Arg              64-bit integer argument.
+     * @thread  EMT
+     */
+    DECLR3CALLBACKMEMBER(int, pfnCallR0,(PPDMDEVINS pDevIns, uint32_t uOperation, uint64_t u64Arg));
+
     /** Space reserved for future members.
      * @{ */
@@ -3564,4 +3590,28 @@
                         || !PDM_VERSION_ARE_COMPATIBLE((pDevIns)->pHlpR3->u32Version, PDM_DEVHLPR3_VERSION) )) \
             return VERR_VERSION_MISMATCH; \
+    } while (0)
+
+/**
+ * Wrapper around CFGMR3ValidateConfig for the root config for use in the
+ * constructor - returns on failure.
+ *
+ * This should be invoked after having initialized the instance data
+ * sufficiently for the correct operation of the destructor.  The destructor is
+ * always called!
+ *
+ * @param   pDevIns             Pointer to the PDM device instance.
+ * @param   pszValidValues      Patterns describing the valid value names.  See
+ *                              RTStrSimplePatternMultiMatch for details on the
+ *                              pattern syntax.
+ * @param   pszValidNodes       Patterns describing the valid node (key) names.
+ *                              Pass empty string if no valid nodess.
+ */
+#define PDMDEV_VALIDATE_CONFIG_RETURN(pDevIns, pszValidValues, pszValidNodes) \
+    do \
+    { \
+        int rcValCfg = CFGMR3ValidateConfig((pDevIns)->pCfg, "/", pszValidValues, pszValidNodes, \
+                                            (pDevIns)->pReg->szName, (pDevIns)->iInstance); \
+        if (RT_FAILURE(rcValCfg)) \
+            return rcValCfg; \
     } while (0)
 
@@ -4289,4 +4339,12 @@
 }
 
+/**
+ * @copydoc PDMDEVHLP::pfnCallR0
+ */
+DECLINLINE(int) PDMDevHlpCallR0(PPDMDEVINS pDevIns, uint32_t uOperation, uint64_t u64Arg)
+{
+    return pDevIns->pHlpR3->pfnCallR0(pDevIns, uOperation, u64Arg);
+}
+
 #endif /* IN_RING3 */
 
Index: /trunk/include/VBox/pdmdrv.h
===================================================================
--- /trunk/include/VBox/pdmdrv.h	(revision 29520)
+++ /trunk/include/VBox/pdmdrv.h	(revision 29521)
@@ -1162,5 +1162,5 @@
      *
      * @returns VBox status code.
-     * @param   pDevIns             The device instance.
+     * @param   pDrvIns             The driver instance.
      * @param   pCritSect           Pointer to the critical section.
      * @param   RT_SRC_POS_DECL     Use RT_SRC_POS.
@@ -1179,7 +1179,8 @@
      * 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.
+     * PDMDRVREG struct prefixed with 'drvR0' and suffixed with 'ReqHandler'.
+     * The driver name will be capitalized.  It shall take the exact same
+     * arguments as this function and be declared using PDMBOTHCBDECL.  See
+     * FNPDMDRVREQHANDLERR0.
      *
      * @returns VBox status code.
@@ -1188,5 +1189,5 @@
      * @retval  VERR_ACCESS_DENIED if the driver isn't ring-0 capable.
      *
-     * @param   pDevIns             The device instance.
+     * @param   pDrvIns             The driver instance.
      * @param   uOperation          The operation to perform.
      * @param   u64Arg              64-bit integer argument.
Index: /trunk/include/VBox/vmm.h
===================================================================
--- /trunk/include/VBox/vmm.h	(revision 29520)
+++ /trunk/include/VBox/vmm.h	(revision 29521)
@@ -4,5 +4,5 @@
 
 /*
- * Copyright (C) 2006-2007 Oracle Corporation
+ * Copyright (C) 2006-2010 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -322,4 +322,6 @@
     /** Call PDMR0DriverCallReqHandler. */
     VMMR0_DO_PDM_DRIVER_CALL_REQ_HANDLER,
+    /** Call PDMR0DeviceCallReqHandler. */
+    VMMR0_DO_PDM_DEVICE_CALL_REQ_HANDLER,
 
     /** The start of the R0 service operations. */
Index: /trunk/src/VBox/VMM/PDMDevHlp.cpp
===================================================================
--- /trunk/src/VBox/VMM/PDMDevHlp.cpp	(revision 29520)
+++ /trunk/src/VBox/VMM/PDMDevHlp.cpp	(revision 29521)
@@ -36,4 +36,5 @@
 #include <iprt/asm.h>
 #include <iprt/assert.h>
+#include <iprt/ctype.h>
 #include <iprt/string.h>
 #include <iprt/thread.h>
@@ -1847,4 +1848,53 @@
 
     LogFlow(("pdmR3DevHlp_PDMLdrGetR0InterfaceSymbols: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName,
+             pDevIns->iInstance, rc));
+    return rc;
+}
+
+
+/** @interface_method_impl{PDMDEVHLP,pfnCallR0} */
+static DECLCALLBACK(int) pdmR3DevHlp_CallR0(PPDMDEVINS pDevIns, uint32_t uOperation, uint64_t u64Arg)
+{
+    PDMDEV_ASSERT_DEVINS(pDevIns);
+    PVM pVM = pDevIns->Internal.s.pVMR3;
+    VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3);
+    LogFlow(("pdmR3DevHlp_CallR0: caller='%s'/%d: uOperation=%#x u64Arg=%#RX64\n",
+             pDevIns->pReg->szName, pDevIns->iInstance, uOperation, u64Arg));
+
+    /*
+     * Resolve the ring-0 entry point.  There is not need to remember this like
+     * we do for drivers since this is mainly for construction time hacks and
+     * other things that aren't performance critical.
+     */
+    int rc;
+    if (pDevIns->pReg->fFlags & PDM_DEVREG_FLAGS_R0)
+    {
+        char szSymbol[          sizeof("devR0") + sizeof(pDevIns->pReg->szName) + sizeof("ReqHandler")];
+        strcat(strcat(strcpy(szSymbol, "devR0"),         pDevIns->pReg->szName),         "ReqHandler");
+        szSymbol[sizeof("devR0") - 1] = RT_C_TO_UPPER(szSymbol[sizeof("devR0") - 1]);
+
+        PFNPDMDRVREQHANDLERR0 pfnReqHandlerR0;
+        rc = PDMR3LdrGetSymbolR0Lazy(pVM, pDevIns->pReg->szR0Mod, szSymbol, &pfnReqHandlerR0);
+        if (RT_SUCCESS(rc))
+        {
+            /*
+             * Make the ring-0 call.
+             */
+            PDMDEVICECALLREQHANDLERREQ Req;
+            Req.Hdr.u32Magic    = SUPVMMR0REQHDR_MAGIC;
+            Req.Hdr.cbReq       = sizeof(Req);
+            Req.pDevInsR0       = PDMDEVINS_2_R0PTR(pDevIns);
+            Req.pfnReqHandlerR0 = pfnReqHandlerR0;
+            Req.uOperation      = uOperation;
+            Req.u32Alignment    = 0;
+            Req.u64Arg          = u64Arg;
+            rc = SUPR3CallVMMR0Ex(pVM->pVMR0, NIL_VMCPUID, VMMR0_DO_PDM_DEVICE_CALL_REQ_HANDLER, 0, &Req.Hdr);
+        }
+        else
+            pfnReqHandlerR0 = NIL_RTR0PTR;
+    }
+    else
+        rc = VERR_ACCESS_DENIED;
+    LogFlow(("pdmR3DevHlp_CallR0: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName,
              pDevIns->iInstance, rc));
     return rc;
@@ -2928,4 +2978,5 @@
     pdmR3DevHlp_LdrGetRCInterfaceSymbols,
     pdmR3DevHlp_LdrGetR0InterfaceSymbols,
+    pdmR3DevHlp_CallR0,
     0,
     0,
@@ -3123,4 +3174,5 @@
     pdmR3DevHlp_LdrGetRCInterfaceSymbols,
     pdmR3DevHlp_LdrGetR0InterfaceSymbols,
+    pdmR3DevHlp_CallR0,
     0,
     0,
Index: /trunk/src/VBox/VMM/PDMDriver.cpp
===================================================================
--- /trunk/src/VBox/VMM/PDMDriver.cpp	(revision 29520)
+++ /trunk/src/VBox/VMM/PDMDriver.cpp	(revision 29521)
@@ -33,9 +33,10 @@
 #include <VBox/log.h>
 #include <iprt/assert.h>
+#include <iprt/asm.h>
+#include <iprt/ctype.h>
+#include <iprt/mem.h>
 #include <iprt/thread.h>
+#include <iprt/path.h>
 #include <iprt/string.h>
-#include <iprt/asm.h>
-#include <iprt/alloc.h>
-#include <iprt/path.h>
 
 
@@ -1319,4 +1320,6 @@
             char szSymbol[          sizeof("drvR0") + sizeof(pDrvIns->pReg->szName) + sizeof("ReqHandler")];
             strcat(strcat(strcpy(szSymbol, "drvR0"),         pDrvIns->pReg->szName),         "ReqHandler");
+            szSymbol[sizeof("drvR0") - 1] = RT_C_TO_UPPER(szSymbol[sizeof("drvR0") - 1]);
+
             rc = PDMR3LdrGetSymbolR0Lazy(pVM, pDrvIns->pReg->szR0Mod, szSymbol, &pfnReqHandlerR0);
             if (RT_SUCCESS(rc))
Index: /trunk/src/VBox/VMM/PDMInternal.h
===================================================================
--- /trunk/src/VBox/VMM/PDMInternal.h	(revision 29520)
+++ /trunk/src/VBox/VMM/PDMInternal.h	(revision 29521)
@@ -5,5 +5,5 @@
 
 /*
- * Copyright (C) 2006-2007 Oracle Corporation
+ * Copyright (C) 2006-2010 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
Index: /trunk/src/VBox/VMM/VMMR0/PDMR0Device.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR0/PDMR0Device.cpp	(revision 29520)
+++ /trunk/src/VBox/VMM/VMMR0/PDMR0Device.cpp	(revision 29521)
@@ -718,5 +718,5 @@
 
 /**
- * The Raw-Mode Context Driver Helper Callbacks.
+ * The Ring-0 Context Driver Helper Callbacks.
  */
 extern DECLEXPORT(const PDMDRVHLPR0) g_pdmR0DrvHlp =
@@ -809,2 +809,30 @@
     }
 }
+
+
+/**
+ * PDMDevHlpCallR0 helper.
+ *
+ * @returns See PFNPDMDEVREQHANDLERR0.
+ * @param   pVM                 The VM handle (for validation).
+ * @param   pReq                The request buffer.
+ */
+VMMR0_INT_DECL(int) PDMR0DeviceCallReqHandler(PVM pVM, PPDMDEVICECALLREQHANDLERREQ 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);
+
+    PPDMDEVINS pDevIns = pReq->pDevInsR0;
+    AssertPtrReturn(pDevIns, VERR_INVALID_POINTER);
+    AssertReturn(pDevIns->Internal.s.pVMR0 == pVM, VERR_INVALID_PARAMETER);
+
+    PFNPDMDEVREQHANDLERR0 pfnReqHandlerR0 = pReq->pfnReqHandlerR0;
+    AssertPtrReturn(pfnReqHandlerR0, VERR_INVALID_POINTER);
+
+    return pfnReqHandlerR0(pDevIns, pReq->uOperation, pReq->u64Arg);
+}
+
Index: /trunk/src/VBox/VMM/VMMR0/VMMR0.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR0/VMMR0.cpp	(revision 29520)
+++ /trunk/src/VBox/VMM/VMMR0/VMMR0.cpp	(revision 29521)
@@ -5,5 +5,5 @@
 
 /*
- * Copyright (C) 2006-2007 Oracle Corporation
+ * Copyright (C) 2006-2010 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -1015,4 +1015,11 @@
         }
 
+        case VMMR0_DO_PDM_DEVICE_CALL_REQ_HANDLER:
+        {
+            if (!pVM || !pReqHdr || u64Arg || idCpu != NIL_VMCPUID)
+                return VERR_INVALID_PARAMETER;
+            return PDMR0DeviceCallReqHandler(pVM, (PPDMDEVICECALLREQHANDLERREQ)pReqHdr);
+        }
+
         /*
          * Requests to the internal networking service.
