Index: trunk/src/VBox/Devices/testcase/tstDevice.cpp
===================================================================
--- trunk/src/VBox/Devices/testcase/tstDevice.cpp	(revision 69162)
+++ trunk/src/VBox/Devices/testcase/tstDevice.cpp	(revision 69183)
@@ -22,4 +22,5 @@
 #define LOG_GROUP LOG_GROUP_DEFAULT /** @todo */
 #include <VBox/types.h>
+#include <VBox/sup.h>
 #include <VBox/version.h>
 #include <iprt/assert.h>
@@ -774,9 +775,10 @@
  * @returns VBox status code.
  * @param   pThis                   The device under test instance.
- * @param   pszR0Mod                The R0 module.
+ * @param   pszMod                  The module name.
+ * @param   enmModType              The module type if the module needs to be loaded.
  * @param   pszSymbol               The symbol to resolve.
  * @param   ppfn                    Where to store the value on success.
  */
-DECLHIDDEN(int) tstDevPdmLdrGetSymbol(PDEVDUTINT pThis, const char *pszMod, TSTDEVPDMMODTYPE enmModType,
+DECLHIDDEN(int) tstDevPdmLdrGetSymbol(PTSTDEVDUTINT pThis, const char *pszMod, TSTDEVPDMMODTYPE enmModType,
                                       const char *pszSymbol, PFNRT *ppfn)
 {
@@ -809,11 +811,17 @@
 
 
+static TSTDEVCFGITEM s_aTestcaseCfg[] =
+{
+    {"CtrlMemBufSize", TSTDEVCFGITEMTYPE_INTEGER, "0"  },
+    {NULL,             TSTDEVCFGITEMTYPE_INVALID, NULL }
+};
+
 static TSTDEVTESTCASEREG s_TestcaseDef =
 {
     "test",
     "Testcase during implementation",
-    "serial",
+    "nvme",
     0,
-    NULL,
+    &s_aTestcaseCfg[0],
     NULL,
 };
@@ -832,11 +840,19 @@
     {
         TSTDEVDUTINT Dut;
-        Dut.pTestcaseReg = &s_TestcaseDef;
-        Dut.enmCtx       = TSTDEVDUTCTX_R3;
+        Dut.pTestcaseReg    = &s_TestcaseDef;
+        Dut.enmCtx          = TSTDEVDUTCTX_R3;
+        Dut.pVm             = NULL;
+        Dut.SupSession.pDut = &Dut;
         RTListInit(&Dut.LstIoPorts);
         RTListInit(&Dut.LstTimers);
+        RTListInit(&Dut.LstMmHeap);
+        RTListInit(&Dut.LstPdmThreads);
+        RTListInit(&Dut.SupSession.LstSupSem);
         CFGMNODE Cfg;
         Cfg.pVmmCallbacks = &g_tstDevVmmCallbacks;
         Cfg.pDut = &Dut;
+
+        rc = RTCritSectRwInit(&Dut.CritSectLists);
+        AssertRC(rc);
 
         PPDMDEVINS pDevIns = (PPDMDEVINS)RTMemAllocZ(RT_OFFSETOF(PDMDEVINS, achInstanceData[pPdmDev->pReg->cbInstance]));
@@ -884,5 +900,5 @@
             rc = tstDevPdmLoadMod(argv[1], TSTDEVPDMMODTYPE_R3);
             if (RT_SUCCESS(rc))
-                rc = tstDevPdmDevCreate("serial");
+                rc = tstDevPdmDevCreate("nvme");
             else
                 rcExit = RTEXITCODE_FAILURE;
Index: trunk/src/VBox/Devices/testcase/tstDeviceInternal.h
===================================================================
--- trunk/src/VBox/Devices/testcase/tstDeviceInternal.h	(revision 69162)
+++ trunk/src/VBox/Devices/testcase/tstDeviceInternal.h	(revision 69183)
@@ -30,4 +30,5 @@
 #include <iprt/assert.h>
 #include <iprt/list.h>
+#include <iprt/semaphore.h>
 
 #include "tstDevicePlugin.h"
@@ -35,4 +36,8 @@
 
 RT_C_DECLS_BEGIN
+
+
+/** Converts PDM device instance to the device under test structure. */
+#define TSTDEV_PDMDEVINS_2_DUT(a_pDevIns) ((a_pDevIns)->Internal.s.pDut)
 
 /**
@@ -77,14 +82,25 @@
     /** Opaque user data - R0. */
     void                            *pvUserR0;
-    /** Out handler - R3. */
+    /** Out handler - R0. */
     PFNIOMIOPORTOUT                 pfnOutR0;
-    /** In handler - R3. */
+    /** In handler - R0. */
     PFNIOMIOPORTIN                  pfnInR0;
-    /** Out string handler - R3. */
+    /** Out string handler - R0. */
     PFNIOMIOPORTOUTSTRING           pfnOutStrR0;
-    /** In string handler - R3. */
+    /** In string handler - R0. */
     PFNIOMIOPORTINSTRING            pfnInStrR0;
 
-    /** @todo: RC */
+#ifdef TSTDEV_SUPPORTS_RC
+    /** Opaque user data - RC. */
+    void                            *pvUserRC;
+    /** Out handler - RC. */
+    PFNIOMIOPORTOUT                 pfnOutRC;
+    /** In handler - RC. */
+    PFNIOMIOPORTIN                  pfnInRC;
+    /** Out string handler - RC. */
+    PFNIOMIOPORTOUTSTRING           pfnOutStrRC;
+    /** In string handler - RC. */
+    PFNIOMIOPORTINSTRING            pfnInStrRC;
+#endif
 } RTDEVDUTIOPORT;
 /** Pointer to a registered I/O port handler. */
@@ -92,4 +108,46 @@
 /** Pointer to a const I/O port handler. */
 typedef const RTDEVDUTIOPORT *PCRTDEVDUTIOPORT;
+
+/**
+ * The Support Driver session state.
+ */
+typedef struct TSTDEVSUPDRVSESSION
+{
+    /** Pointer to the owning device under test instance. */
+    PTSTDEVDUTINT                   pDut;
+    /** List of event semaphores. */
+    RTLISTANCHOR                    LstSupSem;
+} TSTDEVSUPDRVSESSION;
+/** Pointer to the Support Driver session state. */
+typedef TSTDEVSUPDRVSESSION *PTSTDEVSUPDRVSESSION;
+
+/** Converts a Support Driver session handle to the internal state. */
+#define TSTDEV_PSUPDRVSESSION_2_PTSTDEVSUPDRVSESSION(a_pSession) ((PTSTDEVSUPDRVSESSION)(a_pSession))
+/** Converts the internal session state to a Support Driver session handle. */
+#define TSTDEV_PTSTDEVSUPDRVSESSION_2_PSUPDRVSESSION(a_pSession) ((PSUPDRVSESSION)(a_pSession))
+
+/**
+ * Support driver event semaphore.
+ */
+typedef struct TSTDEVSUPSEMEVENT
+{
+    /** Node for the event semaphore list. */
+    RTLISTNODE                      NdSupSem;
+    /** Flag whether this is multi event semaphore. */
+    bool                            fMulti;
+    /** Event smeaphore handles depending on the flag above. */
+    union
+    {
+        RTSEMEVENT                  hSemEvt;
+        RTSEMEVENTMULTI             hSemEvtMulti;
+    } u;
+} TSTDEVSUPSEMEVENT;
+/** Pointer to a support event semaphore state. */
+typedef TSTDEVSUPSEMEVENT *PTSTDEVSUPSEMEVENT;
+
+/** Converts a Support event semaphore handle to the internal state. */
+#define TSTDEV_SUPSEMEVENT_2_PTSTDEVSUPSEMEVENT(a_pSupSemEvt) ((PTSTDEVSUPSEMEVENT)(a_pSupSemEvt))
+/** Converts the internal session state to a Support event semaphore handle. */
+#define TSTDEV_PTSTDEVSUPSEMEVENT_2_SUPSEMEVENT(a_pSupSemEvt) ((SUPSEMEVENT)(a_pSupSemEvt))
 
 /**
@@ -111,4 +169,21 @@
 
 /**
+ * PCI region descriptor.
+ */
+typedef struct TSTDEVDUTPCIREGION
+{
+    /** Size of the region. */
+    RTGCPHYS                        cbRegion;
+    /** Address space type. */
+    PCIADDRESSSPACE                 enmType;
+    /** Region mapping callback. */
+    PFNPCIIOREGIONMAP               pfnRegionMap;
+} TSTDEVDUTPCIREGION;
+/** Pointer to a PCI region descriptor. */
+typedef TSTDEVDUTPCIREGION *PTSTDEVDUTPCIREGION;
+/** Pointer to a const PCI region descriptor. */
+typedef const TSTDEVDUTPCIREGION *PCTSTDEVDUTPCIREGION;
+
+/**
  * Device under test instance data.
  */
@@ -121,15 +196,51 @@
     /** Current device context. */
     TSTDEVDUTCTX                    enmCtx;
+    /** Critical section protecting the lists below. */
+    RTCRITSECTRW                    CritSectLists;
     /** List of registered I/O port handlers. */
     RTLISTANCHOR                    LstIoPorts;
     /** List of timers registered. */
     RTLISTANCHOR                    LstTimers;
+    /** List of registered MMIO regions. */
+    RTLISTANCHOR                    LstMmio;
+    /** List of MM Heap allocations. */
+    RTLISTANCHOR                    LstMmHeap;
+    /** List of PDM threads. */
+    RTLISTANCHOR                    LstPdmThreads;
+    /** The SUP session we emulate. */
+    TSTDEVSUPDRVSESSION             SupSession;
+    /** The VM state assoicated with this device. */
+    PVM                             pVm;
+    /** The registered PCI device instance if this is a PCI device. */
+    PPDMPCIDEV                      pPciDev;
+    /** PCI Region descriptors. */
+    TSTDEVDUTPCIREGION              aPciRegions[VBOX_PCI_NUM_REGIONS];
 } TSTDEVDUTINT;
-/** Pointer to the internal device under test instance data. */
-typedef TSTDEVDUTINT *PDEVDUTINT;
-
-DECLHIDDEN(int) tstDevPdmLdrGetSymbol(PDEVDUTINT pThis, const char *pszR0Mod, TSTDEVPDMMODTYPE enmModType,
+
+
+DECLHIDDEN(int) tstDevPdmLdrGetSymbol(PTSTDEVDUTINT pThis, const char *pszMod, TSTDEVPDMMODTYPE enmModType,
                                       const char *pszSymbol, PFNRT *ppfn);
 
+
+DECLINLINE(int) tstDevDutLockShared(PTSTDEVDUTINT pThis)
+{
+    return RTCritSectRwEnterShared(&pThis->CritSectLists);
+}
+
+DECLINLINE(int) tstDevDutUnlockShared(PTSTDEVDUTINT pThis)
+{
+    return RTCritSectRwLeaveShared(&pThis->CritSectLists);
+}
+
+DECLINLINE(int) tstDevDutLockExcl(PTSTDEVDUTINT pThis)
+{
+    return RTCritSectRwEnterExcl(&pThis->CritSectLists);
+}
+
+DECLINLINE(int) tstDevDutUnlockExcl(PTSTDEVDUTINT pThis)
+{
+    return RTCritSectRwLeaveExcl(&pThis->CritSectLists);
+}
+
 RT_C_DECLS_END
 
Index: trunk/src/VBox/Devices/testcase/tstDevicePdmDevHlp.cpp
===================================================================
--- trunk/src/VBox/Devices/testcase/tstDevicePdmDevHlp.cpp	(revision 69162)
+++ trunk/src/VBox/Devices/testcase/tstDevicePdmDevHlp.cpp	(revision 69183)
@@ -25,4 +25,5 @@
 #include <VBox/vmm/pdmpci.h>
 
+#include <iprt/assert.h>
 #include <iprt/mem.h>
 
@@ -125,5 +126,5 @@
              pDevIns->pReg->szName, pDevIns->iInstance, Port, cPorts, pvUser, pszOut, pszOut, pszIn, pszIn, pszOutStr, pszOutStr, pszInStr, pszInStr, pszDesc, pszDesc));
 
-    PDEVDUTINT pThis = pDevIns->Internal.s.pDut;
+    PTSTDEVDUTINT pThis = pDevIns->Internal.s.pDut;
     PRTDEVDUTIOPORT pIoPort;
     int rc = VERR_NOT_FOUND;
@@ -551,6 +552,6 @@
              pDevIns->pReg->szName, pDevIns->iInstance));
 
-    PSUPDRVSESSION pSession = 0;
-    AssertFailed();
+    PTSTDEVDUTINT pThis = TSTDEV_PDMDEVINS_2_DUT(pDevIns);
+    PSUPDRVSESSION pSession = TSTDEV_PTSTDEVSUPDRVSESSION_2_PSUPDRVSESSION(&pThis->SupSession);
 
     LogFlow(("pdmR3DevHlp_GetSupDrvSession: caller='%s'/%d: returns %#p\n", pDevIns->pReg->szName, pDevIns->iInstance, pSession));
@@ -703,6 +704,22 @@
     LogFlow(("pdmR3DevHlp_MMHeapAlloc: caller='%s'/%d: cb=%#x\n", pDevIns->pReg->szName, pDevIns->iInstance, cb));
 
+    PTSTDEVDUTINT pThis = TSTDEV_PDMDEVINS_2_DUT(pDevIns);
+
     void *pv = NULL;
-    AssertFailed();
+    PTSTDEVMMHEAPALLOC pHeapAlloc = (PTSTDEVMMHEAPALLOC)RTMemAllocZ(cb + sizeof(TSTDEVMMHEAPALLOC) - 1);
+    if (pHeapAlloc)
+    {
+        /* Poison */
+        memset(&pHeapAlloc->abAlloc[0], 0xfe, cb);
+        pHeapAlloc->cbAlloc       = cb;
+        pHeapAlloc->pVmmCallbacks = pDevIns->Internal.s.pVmmCallbacks;
+        pHeapAlloc->pDut          = pThis;
+
+        tstDevDutLockExcl(pThis);
+        RTListAppend(&pThis->LstMmHeap, &pHeapAlloc->NdMmHeap);
+        tstDevDutUnlockExcl(pThis);
+
+        pv = &pHeapAlloc->abAlloc[0];
+    }
 
     LogFlow(("pdmR3DevHlp_MMHeapAlloc: caller='%s'/%d: returns %p\n", pDevIns->pReg->szName, pDevIns->iInstance, pv));
@@ -717,6 +734,7 @@
     LogFlow(("pdmR3DevHlp_MMHeapAllocZ: caller='%s'/%d: cb=%#x\n", pDevIns->pReg->szName, pDevIns->iInstance, cb));
 
-    void *pv = NULL;
-    AssertFailed();
+    void *pv = pdmR3DevHlp_MMHeapAlloc(pDevIns, cb);
+    if (VALID_PTR(pv))
+        memset(pv, 0, cb);
 
     LogFlow(("pdmR3DevHlp_MMHeapAllocZ: caller='%s'/%d: returns %p\n", pDevIns->pReg->szName, pDevIns->iInstance, pv));
@@ -728,8 +746,8 @@
 static DECLCALLBACK(void) pdmR3DevHlp_MMHeapFree(PPDMDEVINS pDevIns, void *pv)
 {
-    PDMDEV_ASSERT_DEVINS(pDevIns); RT_NOREF_PV(pDevIns);
+    PDMDEV_ASSERT_DEVINS(pDevIns);
     LogFlow(("pdmR3DevHlp_MMHeapFree: caller='%s'/%d: pv=%p\n", pDevIns->pReg->szName, pDevIns->iInstance, pv));
 
-    AssertFailed();
+    MMR3HeapFree(pv);
 
     LogFlow(("pdmR3DevHlp_MMHeapAlloc: caller='%s'/%d: returns void\n", pDevIns->pReg->szName, pDevIns->iInstance));
@@ -935,6 +953,6 @@
                           ("'%s'/%d: Invalid flags: %#x\n", pDevIns->pReg->szName, pDevIns->iInstance, fFlags),
                           VERR_INVALID_FLAGS);
-    int rc = VERR_NOT_IMPLEMENTED;
-    AssertFailed();
+    int rc = VINF_SUCCESS;
+    pDevIns->Internal.s.pDut->pPciDev = pPciDev;
 
     LogFlow(("pdmR3DevHlp_PCIRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
@@ -950,6 +968,5 @@
              pDevIns->pReg->szName, pDevIns->iInstance, pPciDev, pPciDev->uDevFn, pMsiReg, pMsiReg->cMsiVectors, pMsiReg->cMsixVectors));
 
-    int rc = VERR_NOT_IMPLEMENTED;
-    AssertFailed();
+    int rc = VERR_NOT_SUPPORTED; /** @todo */
 
     LogFlow(("pdmR3DevHlp_PCIRegisterMsi: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
@@ -966,6 +983,14 @@
              pDevIns->pReg->szName, pDevIns->iInstance, pPciDev, pPciDev->uDevFn, iRegion, cbRegion, enmType, pfnCallback));
 
-    int rc = VERR_NOT_IMPLEMENTED;
-    AssertFailed();
+    AssertLogRelMsgReturn(iRegion < VBOX_PCI_NUM_REGIONS,
+                          ("Region %u exceeds maximum region index %u\n", iRegion, VBOX_PCI_NUM_REGIONS),
+                          VERR_INVALID_PARAMETER);
+
+    int rc = VINF_SUCCESS;
+    PTSTDEVDUTINT pThis = TSTDEV_PDMDEVINS_2_DUT(pDevIns);
+    PTSTDEVDUTPCIREGION pRegion = &pThis->aPciRegions[iRegion];
+    pRegion->cbRegion     = cbRegion;
+    pRegion->enmType      = enmType;
+    pRegion->pfnRegionMap = pfnCallback;
 
     LogFlow(("pdmR3DevHlp_PCIIORegionRegister: caller='%s'/%d: returns %Rrc\n", pDevIns->pReg->szName, pDevIns->iInstance, rc));
@@ -1489,7 +1514,8 @@
 {
     PDMDEV_ASSERT_DEVINS(pDevIns);
-    AssertFailed();
+    PTSTDEVDUTINT pThis = TSTDEV_PDMDEVINS_2_DUT(pDevIns);
+    PVM pVM = pThis->pVm;
     LogFlow(("pdmR3DevHlp_GetVM: caller='%s'/%d: returns %p\n", pDevIns->pReg->szName, pDevIns->iInstance, NULL));
-    return NULL;
+    return pVM;
 }
 
Index: trunk/src/VBox/Devices/testcase/tstDeviceSUP.cpp
===================================================================
--- trunk/src/VBox/Devices/testcase/tstDeviceSUP.cpp	(revision 69183)
+++ trunk/src/VBox/Devices/testcase/tstDeviceSUP.cpp	(revision 69183)
@@ -0,0 +1,250 @@
+/* $Id$ */
+/** @file
+ * tstDevice - Test framework for PDM devices/drivers, SUP library exports.
+ */
+
+/*
+ * Copyright (C) 2017 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.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#define LOG_GROUP LOG_GROUP_DEFAULT /** @todo */
+#include <VBox/sup.h>
+
+#include <iprt/mem.h>
+#include <iprt/semaphore.h>
+
+#include "tstDeviceInternal.h"
+
+/*********************************************************************************************************************************
+*   Defined Constants And Macros                                                                                                 *
+*********************************************************************************************************************************/
+
+
+
+/*********************************************************************************************************************************
+*   Structures and Typedefs                                                                                                      *
+*********************************************************************************************************************************/
+
+
+
+/*********************************************************************************************************************************
+*   Global Variables                                                                                                             *
+*********************************************************************************************************************************/
+
+
+
+/*********************************************************************************************************************************
+*   Internal Functions                                                                                                           *
+*********************************************************************************************************************************/
+
+SUPR3DECL(int) SUPR3HardenedLdrLoadAppPriv(const char *pszFilename, PRTLDRMOD phLdrMod, uint32_t fFlags, PRTERRINFO pErrInfo)
+{
+    RT_NOREF(fFlags, pErrInfo);
+    int rc = VINF_SUCCESS;
+
+    if (!RTStrCmp(pszFilename, "VBoxVMM"))
+        rc = RTLdrLoad("tstDeviceVBoxVMMStubs", phLdrMod);
+    else
+    {
+        /* Implement loading of any missing libraries here. */
+        AssertFailed();
+        rc = VERR_NOT_FOUND;
+    }
+
+    return rc;
+}
+
+
+SUPDECL(int) SUPSemEventCreate(PSUPDRVSESSION pSession, PSUPSEMEVENT phEvent)
+{
+    PTSTDEVSUPDRVSESSION pThis = TSTDEV_PSUPDRVSESSION_2_PTSTDEVSUPDRVSESSION(pSession);
+    int rc = VINF_SUCCESS;
+    PTSTDEVSUPSEMEVENT pSupSem = (PTSTDEVSUPSEMEVENT)RTMemAllocZ(sizeof(TSTDEVSUPSEMEVENT));
+
+    if (VALID_PTR(pSupSem))
+    {
+        pSupSem->fMulti = false;
+        rc = RTSemEventCreate(&pSupSem->u.hSemEvt);
+        if (RT_SUCCESS(rc))
+        {
+            RTListAppend(&pThis->LstSupSem, &pSupSem->NdSupSem);
+            *phEvent = TSTDEV_PTSTDEVSUPSEMEVENT_2_SUPSEMEVENT(pSupSem);
+        }
+        else
+            RTMemFree(pSupSem);
+    }
+    else
+        rc = VERR_NO_MEMORY;
+
+    return rc;
+}
+
+SUPDECL(int) SUPSemEventClose(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent)
+{
+    PTSTDEVSUPDRVSESSION pThis = TSTDEV_PSUPDRVSESSION_2_PTSTDEVSUPDRVSESSION(pSession);
+    PTSTDEVSUPSEMEVENT pSupSem = TSTDEV_SUPSEMEVENT_2_PTSTDEVSUPSEMEVENT(hEvent);
+
+    PTSTDEVSUPSEMEVENT pIt;
+    RTListForEach(&pThis->LstSupSem, pIt, TSTDEVSUPSEMEVENT, NdSupSem)
+    {
+        if (pIt == pSupSem)
+        {
+            AssertReturn(!pSupSem->fMulti, VERR_INVALID_HANDLE);
+            RTListNodeRemove(&pSupSem->NdSupSem);
+            RTSemEventDestroy(pSupSem->u.hSemEvt);
+            RTMemFree(pSupSem);
+            return VINF_OBJECT_DESTROYED;
+        }
+    }
+
+    AssertFailed();
+    return VERR_INVALID_HANDLE;
+}
+
+SUPDECL(int) SUPSemEventSignal(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent)
+{
+    RT_NOREF(pSession);
+    PTSTDEVSUPSEMEVENT pSupSem = TSTDEV_SUPSEMEVENT_2_PTSTDEVSUPSEMEVENT(hEvent);
+    AssertReturn(!pSupSem->fMulti, VERR_INVALID_HANDLE);
+
+    return RTSemEventSignal(pSupSem->u.hSemEvt);
+}
+
+SUPDECL(int) SUPSemEventWait(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent, uint32_t cMillies)
+{
+    RT_NOREF(pSession);
+    PTSTDEVSUPSEMEVENT pSupSem = TSTDEV_SUPSEMEVENT_2_PTSTDEVSUPSEMEVENT(hEvent);
+    AssertReturn(!pSupSem->fMulti, VERR_INVALID_HANDLE);
+
+    return RTSemEventWait(pSupSem->u.hSemEvt, cMillies);
+}
+
+SUPDECL(int) SUPSemEventWaitNoResume(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent, uint32_t cMillies)
+{
+    RT_NOREF(pSession);
+    PTSTDEVSUPSEMEVENT pSupSem = TSTDEV_SUPSEMEVENT_2_PTSTDEVSUPSEMEVENT(hEvent);
+    AssertReturn(!pSupSem->fMulti, VERR_INVALID_HANDLE);
+
+    return RTSemEventWaitNoResume(pSupSem->u.hSemEvt, cMillies);
+}
+
+SUPDECL(int) SUPSemEventWaitNsAbsIntr(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent, uint64_t uNsTimeout)
+{
+    RT_NOREF(pSession);
+    PTSTDEVSUPSEMEVENT pSupSem = TSTDEV_SUPSEMEVENT_2_PTSTDEVSUPSEMEVENT(hEvent);
+    AssertReturn(!pSupSem->fMulti, VERR_INVALID_HANDLE);
+
+#if 0
+    return RTSemEventWaitEx(pSupSem->u.hSemEvt,
+                            RTSEMWAIT_FLAGS_INTERRUPTIBLE | RTSEMWAIT_FLAGS_ABSOLUTE | RTSEMWAIT_FLAGS_NANOSECS,
+                            uNsTimeout);
+#else
+    RT_NOREF(uNsTimeout);
+    AssertFailed();
+    return VERR_NOT_IMPLEMENTED;
+#endif
+}
+
+SUPDECL(int) SUPSemEventWaitNsRelIntr(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent, uint64_t cNsTimeout)
+{
+    RT_NOREF(pSession);
+    PTSTDEVSUPSEMEVENT pSupSem = TSTDEV_SUPSEMEVENT_2_PTSTDEVSUPSEMEVENT(hEvent);
+    AssertReturn(!pSupSem->fMulti, VERR_INVALID_HANDLE);
+
+#if 0
+    return RTSemEventWaitEx(pSupSem->u.hSemEvt,
+                            RTSEMWAIT_FLAGS_INTERRUPTIBLE | RTSEMWAIT_FLAGS_RELATIVE | RTSEMWAIT_FLAGS_NANOSECS,
+                            cNsTimeout);
+#else
+    RT_NOREF(cNsTimeout);
+    AssertFailed();
+    return VERR_NOT_IMPLEMENTED;
+#endif
+}
+
+SUPDECL(uint32_t) SUPSemEventGetResolution(PSUPDRVSESSION pSession)
+{
+    RT_NOREF(pSession);
+#if 0
+    return RTSemEventGetResolution();
+#else
+    AssertFailed();
+    return 0;
+#endif
+}
+
+SUPDECL(int) SUPSemEventMultiCreate(PSUPDRVSESSION pSession, PSUPSEMEVENTMULTI phEventMulti)
+{
+    RT_NOREF(pSession, phEventMulti);
+    AssertFailed();
+    return VERR_NOT_IMPLEMENTED;
+}
+
+SUPDECL(int) SUPSemEventMultiClose(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti)
+{
+    RT_NOREF(pSession, hEventMulti);
+    AssertFailed();
+    return VERR_NOT_IMPLEMENTED;
+}
+
+SUPDECL(int) SUPSemEventMultiSignal(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti)
+{
+    RT_NOREF(pSession, hEventMulti);
+    AssertFailed();
+    return VERR_NOT_IMPLEMENTED;
+}
+
+SUPDECL(int) SUPSemEventMultiReset(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti)
+{
+    RT_NOREF(pSession, hEventMulti);
+    AssertFailed();
+    return VERR_NOT_IMPLEMENTED;
+}
+
+SUPDECL(int) SUPSemEventMultiWait(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti, uint32_t cMillies)
+{
+    RT_NOREF(pSession, hEventMulti, cMillies);
+    AssertFailed();
+    return VERR_NOT_IMPLEMENTED;
+}
+
+SUPDECL(int) SUPSemEventMultiWaitNoResume(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti, uint32_t cMillies)
+{
+    RT_NOREF(pSession, hEventMulti, cMillies);
+    AssertFailed();
+    return VERR_NOT_IMPLEMENTED;
+}
+
+SUPDECL(int) SUPSemEventMultiWaitNsAbsIntr(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti, uint64_t uNsTimeout)
+{
+    RT_NOREF(pSession, hEventMulti, uNsTimeout);
+    AssertFailed();
+    return VERR_NOT_IMPLEMENTED;
+}
+
+SUPDECL(int) SUPSemEventMultiWaitNsRelIntr(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti, uint64_t cNsTimeout)
+{
+    RT_NOREF(pSession, hEventMulti, cNsTimeout);
+    AssertFailed();
+    return VERR_NOT_IMPLEMENTED;
+}
+
+SUPDECL(uint32_t) SUPSemEventMultiGetResolution(PSUPDRVSESSION pSession)
+{
+    RT_NOREF(pSession);
+    AssertFailed();
+    return 0;
+}
+
Index: trunk/src/VBox/Devices/testcase/tstDeviceVMM.cpp
===================================================================
--- trunk/src/VBox/Devices/testcase/tstDeviceVMM.cpp	(revision 69162)
+++ trunk/src/VBox/Devices/testcase/tstDeviceVMM.cpp	(revision 69183)
@@ -24,4 +24,6 @@
 #include <VBox/version.h>
 #include <VBox/vmm/pdmpci.h>
+
+#include <iprt/mem.h>
 
 #include "tstDeviceInternal.h"
@@ -274,7 +276,34 @@
 static DECLCALLBACK(int) tstDevVmm_CFGMR3QueryString(PCFGMNODE pNode, const char *pszName, char *pszString, size_t cchString)
 {
-    RT_NOREF(pNode, pszName, pszString, cchString);
-    AssertFailed();
-    return VERR_NOT_IMPLEMENTED;
+    if (!pNode)
+        return VERR_CFGM_NO_PARENT;
+
+    PCTSTDEVCFGITEM pCfgItem;
+    int rc = tstDev_CfgmR3ResolveItem(pNode->pDut->pTestcaseReg->paDevCfg, pszName, &pCfgItem);
+    if (RT_SUCCESS(rc))
+    {
+        switch (pCfgItem->enmType)
+        {
+            case TSTDEVCFGITEMTYPE_STRING:
+            {
+                size_t cchVal = strlen(pCfgItem->pszVal);
+                if (cchString <= cchVal + 1)
+                    memcpy(pszString, pCfgItem->pszVal, cchVal);
+                else
+                    rc = VERR_CFGM_NOT_ENOUGH_SPACE;
+                break;
+            }
+            case TSTDEVCFGITEMTYPE_INTEGER:
+            case TSTDEVCFGITEMTYPE_BYTES:
+            default:
+                rc = VERR_CFGM_IPE_1;
+                AssertMsgFailed(("Invalid value type %d\n", pCfgItem->enmType));
+                break;
+        }
+    }
+    else
+        rc = VERR_CFGM_VALUE_NOT_FOUND;
+
+    return rc;
 }
 
@@ -371,6 +400,14 @@
 static DECLCALLBACK(void) tstDevVmm_MMR3HeapFree(void *pv)
 {
-    RT_NOREF(pv);
-    AssertFailed();
+    PTSTDEVMMHEAPALLOC pHeapAlloc = (PTSTDEVMMHEAPALLOC)((uint8_t *)pv - RT_OFFSETOF(TSTDEVMMHEAPALLOC, abAlloc[0]));
+    PTSTDEVDUTINT pThis = pHeapAlloc->pDut;
+
+    tstDevDutLockExcl(pThis);
+    RTListNodeRemove(&pHeapAlloc->NdMmHeap);
+    tstDevDutUnlockExcl(pThis);
+
+    /* Poison */
+    memset(&pHeapAlloc->abAlloc[0], 0xfc, pHeapAlloc->cbAlloc);
+    RTMemFree(pHeapAlloc);
 }
 
Index: trunk/src/VBox/Devices/testcase/tstDeviceVMMInternal.h
===================================================================
--- trunk/src/VBox/Devices/testcase/tstDeviceVMMInternal.h	(revision 69162)
+++ trunk/src/VBox/Devices/testcase/tstDeviceVMMInternal.h	(revision 69183)
@@ -162,8 +162,36 @@
 {
     /** Pointer to the callback table. */
-    PCTSTDEVVMMCALLBACKS pVmmCallbacks;
-    /** @todo: */
+    PCTSTDEVVMMCALLBACKS            pVmmCallbacks;
+    /** Pointer to the device under test. */
+    PTSTDEVDUTINT                   pDut;
+    /** Node for the list of PDM threads. */
+    RTLISTNODE                      NdPdmThreads;
 } PDMTHREADINT;
 AssertCompile(sizeof(PDMTHREADINT) <= 64);
+
+/**
+ * MM Heap allocation.
+ */
+typedef struct TSTDEVMMHEAPALLOC
+{
+    /** Node for the list of allocations. */
+    RTLISTNODE                      NdMmHeap;
+    /** Pointer to the callback table. */
+    PCTSTDEVVMMCALLBACKS            pVmmCallbacks;
+    /** Pointer to the device under test the allocation was made for. */
+    PTSTDEVDUTINT                   pDut;
+    /** Size of the allocation. */
+    size_t                          cbAlloc;
+    /** Align the next member on a 16byte boundary. */
+    size_t                          uAlignment0;
+    /** Start of the real allocation. */
+    uint8_t                         abAlloc[RT_FLEXIBLE_ARRAY];
+} TSTDEVMMHEAPALLOC;
+/** Pointer to a MM Heap allocation. */
+typedef TSTDEVMMHEAPALLOC *PTSTDEVMMHEAPALLOC;
+/** Pointer to a const MM Heap allocation. */
+typedef const TSTDEVMMHEAPALLOC *PCTSTDEVMMHEAPALLOC;
+
+AssertCompileMemberAlignment(TSTDEVMMHEAPALLOC, abAlloc, HC_ARCH_BITS == 64 ? 16 : 8);
 
 #if 0
Index: trunk/src/VBox/Devices/testcase/tstDeviceVMMStubs.cpp
===================================================================
--- trunk/src/VBox/Devices/testcase/tstDeviceVMMStubs.cpp	(revision 69162)
+++ trunk/src/VBox/Devices/testcase/tstDeviceVMMStubs.cpp	(revision 69183)
@@ -614,5 +614,6 @@
 VMMR3DECL(void) MMR3HeapFree(void *pv)
 {
-    RTMemFree(pv); /** @todo */
+    PTSTDEVMMHEAPALLOC pHeapAlloc = (PTSTDEVMMHEAPALLOC)((uint8_t *)pv - RT_OFFSETOF(TSTDEVMMHEAPALLOC, abAlloc[0]));
+    pHeapAlloc->pVmmCallbacks->pfnMMR3HeapFree(pv);
 }
 
