Index: /trunk/include/VBox/gmm.h
===================================================================
--- /trunk/include/VBox/gmm.h	(revision 19453)
+++ /trunk/include/VBox/gmm.h	(revision 19454)
@@ -266,14 +266,14 @@
 GMMR0DECL(void) GMMR0InitPerVMData(PGVM pGVM);
 GMMR0DECL(void) GMMR0CleanupVM(PGVM pGVM);
-GMMR0DECL(int)  GMMR0InitialReservation(PVM pVM, unsigned idCpu, uint64_t cBasePages, uint32_t cShadowPages, uint32_t cFixedPages,
+GMMR0DECL(int)  GMMR0InitialReservation(PVM pVM, VMCPUID idCpu, uint64_t cBasePages, uint32_t cShadowPages, uint32_t cFixedPages,
                                         GMMOCPOLICY enmPolicy, GMMPRIORITY enmPriority);
-GMMR0DECL(int)  GMMR0UpdateReservation(PVM pVM, unsigned idCpu, uint64_t cBasePages, uint32_t cShadowPages, uint32_t cFixedPages);
-GMMR0DECL(int)  GMMR0AllocateHandyPages(PVM pVM, unsigned idCpu, uint32_t cPagesToUpdate, uint32_t cPagesToAlloc, PGMMPAGEDESC paPages);
-GMMR0DECL(int)  GMMR0AllocatePages(PVM pVM, unsigned idCpu, uint32_t cPages, PGMMPAGEDESC paPages, GMMACCOUNT enmAccount);
-GMMR0DECL(int)  GMMR0FreePages(PVM pVM, unsigned idCpu, uint32_t cPages, PGMMFREEPAGEDESC paPages, GMMACCOUNT enmAccount);
-GMMR0DECL(int)  GMMR0BalloonedPages(PVM pVM, unsigned idCpu, uint32_t cBalloonedPages, uint32_t cPagesToFree, PGMMFREEPAGEDESC paPages, bool fCompleted);
-GMMR0DECL(int)  GMMR0DeflatedBalloon(PVM pVM, unsigned idCpu, uint32_t cPages);
-GMMR0DECL(int)  GMMR0MapUnmapChunk(PVM pVM, unsigned idCpu, uint32_t idChunkMap, uint32_t idChunkUnmap, PRTR3PTR ppvR3);
-GMMR0DECL(int)  GMMR0SeedChunk(PVM pVM, unsigned idCpu, RTR3PTR pvR3);
+GMMR0DECL(int)  GMMR0UpdateReservation(PVM pVM, VMCPUID idCpu, uint64_t cBasePages, uint32_t cShadowPages, uint32_t cFixedPages);
+GMMR0DECL(int)  GMMR0AllocateHandyPages(PVM pVM, VMCPUID idCpu, uint32_t cPagesToUpdate, uint32_t cPagesToAlloc, PGMMPAGEDESC paPages);
+GMMR0DECL(int)  GMMR0AllocatePages(PVM pVM, VMCPUID idCpu, uint32_t cPages, PGMMPAGEDESC paPages, GMMACCOUNT enmAccount);
+GMMR0DECL(int)  GMMR0FreePages(PVM pVM, VMCPUID idCpu, uint32_t cPages, PGMMFREEPAGEDESC paPages, GMMACCOUNT enmAccount);
+GMMR0DECL(int)  GMMR0BalloonedPages(PVM pVM, VMCPUID idCpu, uint32_t cBalloonedPages, uint32_t cPagesToFree, PGMMFREEPAGEDESC paPages, bool fCompleted);
+GMMR0DECL(int)  GMMR0DeflatedBalloon(PVM pVM, VMCPUID idCpu, uint32_t cPages);
+GMMR0DECL(int)  GMMR0MapUnmapChunk(PVM pVM, VMCPUID idCpu, uint32_t idChunkMap, uint32_t idChunkUnmap, PRTR3PTR ppvR3);
+GMMR0DECL(int)  GMMR0SeedChunk(PVM pVM, VMCPUID idCpu, RTR3PTR pvR3);
 
 
@@ -296,5 +296,5 @@
 typedef GMMINITIALRESERVATIONREQ *PGMMINITIALRESERVATIONREQ;
 
-GMMR0DECL(int)  GMMR0InitialReservationReq(PVM pVM, unsigned idCpu, PGMMINITIALRESERVATIONREQ pReq);
+GMMR0DECL(int)  GMMR0InitialReservationReq(PVM pVM, VMCPUID idCpu, PGMMINITIALRESERVATIONREQ pReq);
 
 
@@ -314,5 +314,5 @@
 typedef GMMUPDATERESERVATIONREQ *PGMMUPDATERESERVATIONREQ;
 
-GMMR0DECL(int)  GMMR0UpdateReservationReq(PVM pVM, unsigned idCpu, PGMMUPDATERESERVATIONREQ pReq);
+GMMR0DECL(int)  GMMR0UpdateReservationReq(PVM pVM, VMCPUID idCpu, PGMMUPDATERESERVATIONREQ pReq);
 
 
@@ -335,5 +335,5 @@
 typedef GMMALLOCATEPAGESREQ *PGMMALLOCATEPAGESREQ;
 
-GMMR0DECL(int)  GMMR0AllocatePagesReq(PVM pVM, unsigned idCpu, PGMMALLOCATEPAGESREQ pReq);
+GMMR0DECL(int)  GMMR0AllocatePagesReq(PVM pVM, VMCPUID idCpu, PGMMALLOCATEPAGESREQ pReq);
 
 
@@ -356,5 +356,5 @@
 typedef GMMFREEPAGESREQ *PGMMFREEPAGESREQ;
 
-GMMR0DECL(int)  GMMR0FreePagesReq(PVM pVM, unsigned idCpu, PGMMFREEPAGESREQ pReq);
+GMMR0DECL(int)  GMMR0FreePagesReq(PVM pVM, VMCPUID idCpu, PGMMFREEPAGESREQ pReq);
 
 
@@ -379,5 +379,5 @@
 typedef GMMBALLOONEDPAGESREQ *PGMMBALLOONEDPAGESREQ;
 
-GMMR0DECL(int)  GMMR0BalloonedPagesReq(PVM pVM, unsigned idCpu, PGMMBALLOONEDPAGESREQ pReq);
+GMMR0DECL(int)  GMMR0BalloonedPagesReq(PVM pVM, VMCPUID idCpu, PGMMBALLOONEDPAGESREQ pReq);
 
 
@@ -400,5 +400,5 @@
 typedef GMMMAPUNMAPCHUNKREQ *PGMMMAPUNMAPCHUNKREQ;
 
-GMMR0DECL(int)  GMMR0MapUnmapChunkReq(PVM pVM, unsigned idCpu, PGMMMAPUNMAPCHUNKREQ pReq);
+GMMR0DECL(int)  GMMR0MapUnmapChunkReq(PVM pVM, VMCPUID idCpu, PGMMMAPUNMAPCHUNKREQ pReq);
 
 
Index: /trunk/include/VBox/gvmm.h
===================================================================
--- /trunk/include/VBox/gvmm.h	(revision 19453)
+++ /trunk/include/VBox/gvmm.h	(revision 19454)
@@ -83,8 +83,16 @@
     /** The number of calls to GVMMR0WakeUp. */
     uint64_t        cWakeUpCalls;
-    /** The number of times the EMT thread wasn't actually halted when GVMMR0WakeUp was called. */
+    /** The number of times the EMT thread wasn't actually halted when GVMMR0WakeUp
+     *  was called. */
     uint64_t        cWakeUpNotHalted;
-    /** The number of wake ups done during GVMMR0WakeUp (not counting the explicit one). */
+    /** The number of wake ups done during GVMMR0WakeUp (not counting the explicit
+     *  one). */
     uint64_t        cWakeUpWakeUps;
+
+    /** The number of calls to GVMMR0Poke. */
+    uint64_t        cPokeCalls;
+    /** The number of times the EMT thread wasn't actually busy when
+     *  GVMMR0Poke was called. */
+    uint64_t        cPokeNotBusy;
 
     /** The number of calls to GVMMR0SchedPoll. */
Index: /trunk/include/VBox/sup.h
===================================================================
--- /trunk/include/VBox/sup.h	(revision 19453)
+++ /trunk/include/VBox/sup.h	(revision 19454)
@@ -447,9 +447,9 @@
  * @returns error code specific to uFunction.
  * @param   pVMR0       Pointer to the Ring-0 (Host Context) mapping of the VM structure.
- * @param   idCpu       VMCPU id.
+ * @param   idCpu       The virtual CPU ID.
  * @param   uOperation  Operation to execute.
  * @param   pvArg       Argument.
  */
-SUPR3DECL(int) SUPCallVMMR0(PVMR0 pVMR0, unsigned idCpu, unsigned uOperation, void *pvArg);
+SUPR3DECL(int) SUPCallVMMR0(PVMR0 pVMR0, VMCPUID idCpu, unsigned uOperation, void *pvArg);
 
 /**
@@ -460,7 +460,7 @@
  * @param   pVMR0       The ring-0 VM handle.
  * @param   uOperation  The operation; only the SUP_VMMR0_DO_* ones are valid.
- * @param   idCpu       VMCPU id.
- */
-SUPR3DECL(int) SUPCallVMMR0Fast(PVMR0 pVMR0, unsigned uOperation, unsigned idCpu);
+ * @param   idCpu       The virtual CPU ID.
+ */
+SUPR3DECL(int) SUPCallVMMR0Fast(PVMR0 pVMR0, unsigned uOperation, VMCPUID idCpu);
 
 /**
@@ -473,5 +473,5 @@
  * @returns error code specific to uFunction.
  * @param   pVMR0       Pointer to the Ring-0 (Host Context) mapping of the VM structure.
- * @param   idCpu       VMCPU id.
+ * @param   idCpu       The virtual CPU ID.
  * @param   uOperation  Operation to execute.
  * @param   u64Arg      Constant argument.
@@ -480,5 +480,5 @@
  *                      limit on this, just below 4KB.
  */
-SUPR3DECL(int) SUPCallVMMR0Ex(PVMR0 pVMR0, unsigned idCpu, unsigned uOperation, uint64_t u64Arg, PSUPVMMR0REQHDR pReqHdr);
+SUPR3DECL(int) SUPCallVMMR0Ex(PVMR0 pVMR0, VMCPUID idCpu, unsigned uOperation, uint64_t u64Arg, PSUPVMMR0REQHDR pReqHdr);
 
 /**
Index: /trunk/include/VBox/vm.h
===================================================================
--- /trunk/include/VBox/vm.h	(revision 19453)
+++ /trunk/include/VBox/vm.h	(revision 19454)
@@ -106,4 +106,7 @@
     /** The native thread handle. */
     RTNATIVETHREAD          hNativeThread;
+    /** Which host CPU ID is this EMT running on.
+     * Only valid when in RC or HWACCMR0 with scheduling disabled. */
+    RTCPUID volatile        idHostCpu;
 
     /** Align the next bit on a 64-byte boundary.
@@ -114,5 +117,5 @@
      *          following it (to grow into and align the struct size).
      *   */
-    uint32_t                au32Alignment[HC_ARCH_BITS == 32 ? 8 : 4];
+    uint32_t                au32Alignment[HC_ARCH_BITS == 32 ? 7 : 3];
 
     /** CPUM part. */
Index: /trunk/include/VBox/vm.mac
===================================================================
--- /trunk/include/VBox/vm.mac	(revision 19453)
+++ /trunk/include/VBox/vm.mac	(revision 19454)
@@ -47,17 +47,17 @@
 ; This is part of  the VM structure.
 struc VM
-    .enmVMState         resd 1
-    .fGlobalForcedActions resd 1
-    .paVMPagesR3        RTR3PTR_RES 1
-    .pSession           RTR0PTR_RES 1
-    .pUVM               RTR3PTR_RES 1
-    .pVMR3              RTR3PTR_RES 1
-    .pVMR0              RTR0PTR_RES 1
-    .pVMRC              RTRCPTR_RES 1
-    .hSelf              resd 1
-    .cCPUs              resd 1
-    .cbSelf             resd 1
-    .offVMCPU           resd 1
-    .u32Reserved        resd 6
+    .enmVMState             resd 1
+    .fGlobalForcedActions   resd 1
+    .paVMPagesR3            RTR3PTR_RES 1
+    .pSession               RTR0PTR_RES 1
+    .pUVM                   RTR3PTR_RES 1
+    .pVMR3                  RTR3PTR_RES 1
+    .pVMR0                  RTR0PTR_RES 1
+    .pVMRC                  RTRCPTR_RES 1
+    .hSelf                  resd 1
+    .cCPUs                  resd 1
+    .cbSelf                 resd 1
+    .offVMCPU               resd 1
+    .u32Reserved            resd 6
 
     .pfnVMMGCGuestToHostAsmGuestCtx RTRCPTR_RES 1
@@ -65,38 +65,38 @@
     .pfnVMMGCGuestToHostAsm         RTRCPTR_RES 1
 
-    .uPadding1          RTHCPTR_RES 1
-    .uPadding2          RTHCPTR_RES 1
+    .uPadding1              RTHCPTR_RES 1
+    .uPadding2              RTHCPTR_RES 1
 
-    .fRawR3Enabled      resb 1
-    .fRawR0Enabled      resb 1
-    .fPATMEnabled       resb 1
-    .fCSAMEnabled       resb 1
-    .fHWACCMEnabled     resb 1
-    .fHwVirtExtForced   resb 1
-    .fPARAVEnabled      resb 1
+    .fRawR3Enabled          resb 1
+    .fRawR0Enabled          resb 1
+    .fPATMEnabled           resb 1
+    .fCSAMEnabled           resb 1
+    .fHWACCMEnabled         resb 1
+    .fHwVirtExtForced       resb 1
+    .fPARAVEnabled          resb 1
 
     alignb 8
 
-    .StatTotalQemuToGC  resb STAMPROFILEADV_size
-    .StatTotalGCToQemu  resb STAMPROFILEADV_size
-    .StatTotalInGC      resb STAMPROFILEADV_size
-    .StatTotalInQemu    resb STAMPROFILEADV_size
-    .StatSwitcherToGC   resb STAMPROFILEADV_size
-    .StatSwitcherToHC   resb STAMPROFILEADV_size
-    .StatSwitcherSaveRegs resb STAMPROFILEADV_size
-    .StatSwitcherSysEnter resb STAMPROFILEADV_size
-    .StatSwitcherDebug    resb STAMPROFILEADV_size
-    .StatSwitcherCR0      resb STAMPROFILEADV_size
-    .StatSwitcherCR4      resb STAMPROFILEADV_size
-    .StatSwitcherJmpCR3   resb STAMPROFILEADV_size
-    .StatSwitcherRstrRegs resb STAMPROFILEADV_size
-    .StatSwitcherLgdt     resb STAMPROFILEADV_size
-    .StatSwitcherLidt     resb STAMPROFILEADV_size
-    .StatSwitcherLldt     resb STAMPROFILEADV_size
-    .StatSwitcherTSS      resb STAMPROFILEADV_size
+    .StatTotalQemuToGC      resb STAMPROFILEADV_size
+    .StatTotalGCToQemu      resb STAMPROFILEADV_size
+    .StatTotalInGC          resb STAMPROFILEADV_size
+    .StatTotalInQemu        resb STAMPROFILEADV_size
+    .StatSwitcherToGC       resb STAMPROFILEADV_size
+    .StatSwitcherToHC       resb STAMPROFILEADV_size
+    .StatSwitcherSaveRegs   resb STAMPROFILEADV_size
+    .StatSwitcherSysEnter   resb STAMPROFILEADV_size
+    .StatSwitcherDebug      resb STAMPROFILEADV_size
+    .StatSwitcherCR0        resb STAMPROFILEADV_size
+    .StatSwitcherCR4        resb STAMPROFILEADV_size
+    .StatSwitcherJmpCR3     resb STAMPROFILEADV_size
+    .StatSwitcherRstrRegs   resb STAMPROFILEADV_size
+    .StatSwitcherLgdt       resb STAMPROFILEADV_size
+    .StatSwitcherLidt       resb STAMPROFILEADV_size
+    .StatSwitcherLldt       resb STAMPROFILEADV_size
+    .StatSwitcherTSS        resb STAMPROFILEADV_size
 
     alignb 64
-    .cpum                 resb 2048
-    .vmm                  resb 1024
+    .cpum                   resb 2048
+    .vmm                    resb 1024
 
 endstruc
@@ -105,17 +105,18 @@
 ; This is part of  the VMCPU structure.
 struc VMCPU
-    .fLocalForcedActions resd 1
-    .enmState            resd 1
-    .pUVCpu              RTR3PTR_RES 1
-    .pVMR3               RTR3PTR_RES 1
-    .pVMR0               RTR0PTR_RES 1
-    .pVMRC               RTRCPTR_RES 1
-    .idCpu               resd 1
+    .fLocalForcedActions    resd 1
+    .enmState               resd 1
+    .pUVCpu                 RTR3PTR_RES 1
+    .pVMR3                  RTR3PTR_RES 1
+    .pVMR0                  RTR0PTR_RES 1
+    .pVMRC                  RTRCPTR_RES 1
+    .idCpu                  resd 1
 
-    .hNativeThread       RTR0PTR_RES 1
+    .hNativeThread          RTR0PTR_RES 1
+    .idHostCpu              resd 1
 
     alignb 64
 
-    .cpum                resb 4096
+    .cpum                   resb 4096
 endstruc
 
Index: /trunk/include/VBox/vmm.h
===================================================================
--- /trunk/include/VBox/vmm.h	(revision 19453)
+++ /trunk/include/VBox/vmm.h	(revision 19454)
@@ -114,5 +114,5 @@
 VMMDECL(PVMCPU)      VMMGetCpu(PVM pVM);
 VMMDECL(PVMCPU)      VMMGetCpu0(PVM pVM);
-VMMDECL(PVMCPU)      VMMGetCpuById(PVM pVM, RTCPUID idCpu);
+VMMDECL(PVMCPU)      VMMGetCpuById(PVM pVM, VMCPUID idCpu);
 VMMDECL(uint32_t)    VMMGetSvnRev(void);
 VMMDECL(VMMSWITCHER) VMMGetSwitcher(PVM pVM);
@@ -298,6 +298,6 @@
 
 VMMR0DECL(int)      VMMR0EntryInt(PVM pVM, VMMR0OPERATION enmOperation, void *pvArg);
-VMMR0DECL(void)     VMMR0EntryFast(PVM pVM, unsigned idCpu, VMMR0OPERATION enmOperation);
-VMMR0DECL(int)      VMMR0EntryEx(PVM pVM, unsigned idCpu, VMMR0OPERATION enmOperation, PSUPVMMR0REQHDR pReq, uint64_t u64Arg, PSUPDRVSESSION);
+VMMR0DECL(void)     VMMR0EntryFast(PVM pVM, VMCPUID idCpu, VMMR0OPERATION enmOperation);
+VMMR0DECL(int)      VMMR0EntryEx(PVM pVM, VMCPUID idCpu, VMMR0OPERATION enmOperation, PSUPVMMR0REQHDR pReq, uint64_t u64Arg, PSUPDRVSESSION);
 VMMR0DECL(int)      VMMR0TermVM(PVM pVM, PGVM pGVM);
 VMMR0DECL(int)      VMMR0CallHost(PVM pVM, VMMCALLHOST enmOperation, uint64_t uArg);
Index: /trunk/src/VBox/Devices/Network/testcase/tstIntNet-1.cpp
===================================================================
--- /trunk/src/VBox/Devices/Network/testcase/tstIntNet-1.cpp	(revision 19453)
+++ /trunk/src/VBox/Devices/Network/testcase/tstIntNet-1.cpp	(revision 19454)
@@ -312,5 +312,5 @@
     SendReq.pSession = pSession;
     SendReq.hIf = hIf;
-    rc = SUPCallVMMR0Ex(NIL_RTR0PTR, 0 /* VPCU 0 */, VMMR0_DO_INTNET_IF_SEND, 0, &SendReq.Hdr);
+    rc = SUPCallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_IF_SEND, 0, &SendReq.Hdr);
     if (RT_FAILURE(rc))
     {
@@ -542,5 +542,5 @@
         WaitReq.hIf = hIf;
         WaitReq.cMillies = cMillies - (uint32_t)cElapsedMillies;
-        int rc = SUPCallVMMR0Ex(NIL_RTR0PTR, 0 /* VPCU 0 */, VMMR0_DO_INTNET_IF_WAIT, 0, &WaitReq.Hdr);
+        int rc = SUPCallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_IF_WAIT, 0, &WaitReq.Hdr);
         if (rc == VERR_TIMEOUT)
             break;
@@ -882,5 +882,5 @@
              OpenReq.szNetwork, OpenReq.szTrunk);
     RTStrmFlush(g_pStdOut);
-    rc = SUPCallVMMR0Ex(NIL_RTR0PTR, 0 /* VPCU 0 */, VMMR0_DO_INTNET_OPEN, 0, &OpenReq.Hdr);
+    rc = SUPCallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_OPEN, 0, &OpenReq.Hdr);
     if (RT_SUCCESS(rc))
     {
@@ -898,5 +898,5 @@
         GetRing3BufferReq.hIf = OpenReq.hIf;
         GetRing3BufferReq.pRing3Buf = NULL;
-        rc = SUPCallVMMR0Ex(NIL_RTR0PTR, 0 /* VPCU 0 */, VMMR0_DO_INTNET_IF_GET_RING3_BUFFER, 0, &GetRing3BufferReq.Hdr);
+        rc = SUPCallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_IF_GET_RING3_BUFFER, 0, &GetRing3BufferReq.Hdr);
         if (RT_SUCCESS(rc))
         {
@@ -913,5 +913,5 @@
                 PromiscReq.hIf          = OpenReq.hIf;
                 PromiscReq.fPromiscuous = true;
-                rc = SUPCallVMMR0Ex(NIL_RTR0PTR, 0 /* VPCU 0 */, VMMR0_DO_INTNET_IF_SET_PROMISCUOUS_MODE, 0, &PromiscReq.Hdr);
+                rc = SUPCallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_IF_SET_PROMISCUOUS_MODE, 0, &PromiscReq.Hdr);
                 if (RT_SUCCESS(rc))
                     RTPrintf("tstIntNet-1: interface in promiscuous mode\n");
@@ -928,5 +928,5 @@
                 ActiveReq.hIf = OpenReq.hIf;
                 ActiveReq.fActive = true;
-                rc = SUPCallVMMR0Ex(NIL_RTR0PTR, 0 /* VPCU 0 */, VMMR0_DO_INTNET_IF_SET_ACTIVE, 0, &ActiveReq.Hdr);
+                rc = SUPCallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_IF_SET_ACTIVE, 0, &ActiveReq.Hdr);
                 if (RT_SUCCESS(rc))
                 {
Index: /trunk/src/VBox/HostDrivers/Support/SUPDrv.c
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/SUPDrv.c	(revision 19453)
+++ /trunk/src/VBox/HostDrivers/Support/SUPDrv.c	(revision 19454)
@@ -150,6 +150,6 @@
 
 #ifdef RT_WITH_W64_UNWIND_HACK
-DECLASM(int)    supdrvNtWrapVMMR0EntryEx(PFNRT pfnVMMR0EntryEx, PVM pVM, unsigned idCpu, unsigned uOperation, PSUPVMMR0REQHDR pReq, uint64_t u64Arg, PSUPDRVSESSION pSession);
-DECLASM(int)    supdrvNtWrapVMMR0EntryFast(PFNRT pfnVMMR0EntryFast, PVM pVM, unsigned idCpu, unsigned uOperation);
+DECLASM(int)    supdrvNtWrapVMMR0EntryEx(PFNRT pfnVMMR0EntryEx, PVM pVM, VMCPUID idCpu, unsigned uOperation, PSUPVMMR0REQHDR pReq, uint64_t u64Arg, PSUPDRVSESSION pSession);
+DECLASM(int)    supdrvNtWrapVMMR0EntryFast(PFNRT pfnVMMR0EntryFast, PVM pVM, VMCPUID idCpu, unsigned uOperation);
 DECLASM(void)   supdrvNtWrapObjDestructor(PFNRT pfnDestruction, void *pvObj, void *pvUser1, void *pvUser2);
 DECLASM(void *) supdrvNtWrapQueryFactoryInterface(PFNRT pfnQueryFactoryInterface, struct SUPDRVFACTORY const *pSupDrvFactory, PSUPDRVSESSION pSession, const char *pszInterfaceUuid);
@@ -927,5 +927,5 @@
  * @param   pSession    Session data.
  */
-int VBOXCALL supdrvIOCtlFast(uintptr_t uIOCtl, unsigned idCpu, PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession)
+int VBOXCALL supdrvIOCtlFast(uintptr_t uIOCtl, VMCPUID idCpu, PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession)
 {
     /*
Index: /trunk/src/VBox/HostDrivers/Support/SUPDrvInternal.h
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/SUPDrvInternal.h	(revision 19453)
+++ /trunk/src/VBox/HostDrivers/Support/SUPDrvInternal.h	(revision 19454)
@@ -568,7 +568,7 @@
     DECLR0CALLBACKMEMBER(int,       pfnVMMR0EntryInt, (PVM pVM, unsigned uOperation, void *pvArg));
     /** VMMR0EntryFast() pointer. */
-    DECLR0CALLBACKMEMBER(void,      pfnVMMR0EntryFast, (PVM pVM, unsigned idCpu, unsigned uOperation));
+    DECLR0CALLBACKMEMBER(void,      pfnVMMR0EntryFast, (PVM pVM, VMCPUID idCpu, unsigned uOperation));
     /** VMMR0EntryEx() pointer. */
-    DECLR0CALLBACKMEMBER(int,       pfnVMMR0EntryEx, (PVM pVM, unsigned idCpu, unsigned uOperation, PSUPVMMR0REQHDR pReq, uint64_t u64Arg, PSUPDRVSESSION pSession));
+    DECLR0CALLBACKMEMBER(int,       pfnVMMR0EntryEx, (PVM pVM, VMCPUID idCpu, unsigned uOperation, PSUPVMMR0REQHDR pReq, uint64_t u64Arg, PSUPDRVSESSION pSession));
 
     /** Linked list of loaded code. */
@@ -625,5 +625,5 @@
 *******************************************************************************/
 int  VBOXCALL   supdrvIOCtl(uintptr_t uIOCtl, PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PSUPREQHDR pReqHdr);
-int  VBOXCALL   supdrvIOCtlFast(uintptr_t uIOCtl, unsigned idCpu, PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession);
+int  VBOXCALL   supdrvIOCtlFast(uintptr_t uIOCtl, VMCPUID idCpu, PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession);
 int  VBOXCALL   supdrvIDC(uintptr_t uIOCtl, PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PSUPDRVIDCREQHDR pReqHdr);
 int  VBOXCALL   supdrvInitDevExt(PSUPDRVDEVEXT pDevExt);
Index: /trunk/src/VBox/HostDrivers/Support/SUPLib.cpp
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/SUPLib.cpp	(revision 19453)
+++ /trunk/src/VBox/HostDrivers/Support/SUPLib.cpp	(revision 19454)
@@ -568,5 +568,5 @@
 
 
-SUPR3DECL(int) SUPCallVMMR0Fast(PVMR0 pVMR0, unsigned uOperation, unsigned idCpu)
+SUPR3DECL(int) SUPCallVMMR0Fast(PVMR0 pVMR0, unsigned uOperation, VMCPUID idCpu)
 {
     if (RT_LIKELY(uOperation == SUP_VMMR0_DO_RAW_RUN))
@@ -582,5 +582,5 @@
 
 
-SUPR3DECL(int) SUPCallVMMR0Ex(PVMR0 pVMR0, unsigned idCpu, unsigned uOperation, uint64_t u64Arg, PSUPVMMR0REQHDR pReqHdr)
+SUPR3DECL(int) SUPCallVMMR0Ex(PVMR0 pVMR0, VMCPUID idCpu, unsigned uOperation, uint64_t u64Arg, PSUPVMMR0REQHDR pReqHdr)
 {
     /*
@@ -645,5 +645,5 @@
 
 
-SUPR3DECL(int) SUPCallVMMR0(PVMR0 pVMR0, unsigned idCpu, unsigned uOperation, void *pvArg)
+SUPR3DECL(int) SUPCallVMMR0(PVMR0 pVMR0, VMCPUID idCpu, unsigned uOperation, void *pvArg)
 {
     /*
Index: /trunk/src/VBox/NetworkServices/DHCP/VBoxNetDHCP.cpp
===================================================================
--- /trunk/src/VBox/NetworkServices/DHCP/VBoxNetDHCP.cpp	(revision 19453)
+++ /trunk/src/VBox/NetworkServices/DHCP/VBoxNetDHCP.cpp	(revision 19454)
@@ -577,5 +577,5 @@
         CloseReq.hIf = m_hIf;
         m_hIf = INTNET_HANDLE_INVALID;
-        int rc = SUPCallVMMR0Ex(NIL_RTR0PTR, 0 /* VPCU 0 */, VMMR0_DO_INTNET_IF_CLOSE, 0, &CloseReq.Hdr);
+        int rc = SUPCallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_IF_CLOSE, 0, &CloseReq.Hdr);
         AssertRC(rc);
     }
@@ -907,5 +907,5 @@
      */
     debugPrint(2, false, "attempting to open/create network \"%s\"...", OpenReq.szNetwork);
-    rc = SUPCallVMMR0Ex(NIL_RTR0PTR, 0 /* VPCU 0 */, VMMR0_DO_INTNET_OPEN, 0, &OpenReq.Hdr);
+    rc = SUPCallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_OPEN, 0, &OpenReq.Hdr);
     if (RT_SUCCESS(rc))
     {
@@ -922,5 +922,5 @@
         GetRing3BufferReq.hIf = m_hIf;
         GetRing3BufferReq.pRing3Buf = NULL;
-        rc = SUPCallVMMR0Ex(NIL_RTR0PTR, 0 /* VPCU 0 */, VMMR0_DO_INTNET_IF_GET_RING3_BUFFER, 0, &GetRing3BufferReq.Hdr);
+        rc = SUPCallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_IF_GET_RING3_BUFFER, 0, &GetRing3BufferReq.Hdr);
         if (RT_SUCCESS(rc))
         {
@@ -939,5 +939,5 @@
             ActiveReq.hIf = m_hIf;
             ActiveReq.fActive = true;
-            rc = SUPCallVMMR0Ex(NIL_RTR0PTR, 0 /* VPCU 0 */, VMMR0_DO_INTNET_IF_SET_ACTIVE, 0, &ActiveReq.Hdr);
+            rc = SUPCallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_IF_SET_ACTIVE, 0, &ActiveReq.Hdr);
             if (RT_SUCCESS(rc))
                 return 0;
@@ -979,5 +979,5 @@
         WaitReq.hIf = m_hIf;
         WaitReq.cMillies = 2000; /* 2 secs - the sleep is for some reason uninterruptible... */  /** @todo fix interruptability in SrvIntNet! */
-        int rc = SUPCallVMMR0Ex(NIL_RTR0PTR, 0 /* VPCU 0 */, VMMR0_DO_INTNET_IF_WAIT, 0, &WaitReq.Hdr);
+        int rc = SUPCallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_IF_WAIT, 0, &WaitReq.Hdr);
         if (RT_FAILURE(rc))
         {
Index: /trunk/src/VBox/NetworkServices/NetLib/VBoxNetInt.cpp
===================================================================
--- /trunk/src/VBox/NetworkServices/NetLib/VBoxNetInt.cpp	(revision 19453)
+++ /trunk/src/VBox/NetworkServices/NetLib/VBoxNetInt.cpp	(revision 19454)
@@ -21,5 +21,5 @@
     SendReq.pSession     = pSession;
     SendReq.hIf          = hIf;
-    return SUPCallVMMR0Ex(NIL_RTR0PTR, VMMR0_DO_INTNET_IF_SEND, 0, &SendReq.Hdr);
+    return SUPCallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_IF_SEND, 0, &SendReq.Hdr);
 }
 
Index: /trunk/src/VBox/NetworkServices/NetLib/VBoxNetIntIf.cpp
===================================================================
--- /trunk/src/VBox/NetworkServices/NetLib/VBoxNetIntIf.cpp	(revision 19453)
+++ /trunk/src/VBox/NetworkServices/NetLib/VBoxNetIntIf.cpp	(revision 19454)
@@ -49,5 +49,5 @@
     SendReq.pSession     = pSession;
     SendReq.hIf          = hIf;
-    return SUPCallVMMR0Ex(NIL_RTR0PTR, 0 /* VPCU 0 */, VMMR0_DO_INTNET_IF_SEND, 0, &SendReq.Hdr);
+    return SUPCallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_INTNET_IF_SEND, 0, &SendReq.Hdr);
 }
 
Index: /trunk/src/VBox/VMM/PDMDriver.cpp
===================================================================
--- /trunk/src/VBox/VMM/PDMDriver.cpp	(revision 19453)
+++ /trunk/src/VBox/VMM/PDMDriver.cpp	(revision 19454)
@@ -949,5 +949,5 @@
     if (    uOperation >= VMMR0_DO_SRV_START
         &&  uOperation <  VMMR0_DO_SRV_END)
-        rc = SUPCallVMMR0Ex(pDrvIns->Internal.s.pVM->pVMR0, 0 /* idCpu not relevant */, uOperation, 0, (PSUPVMMR0REQHDR)pvArg);
+        rc = SUPCallVMMR0Ex(pDrvIns->Internal.s.pVM->pVMR0, NIL_VMCPUID, uOperation, 0, (PSUPVMMR0REQHDR)pvArg);
     else
     {
Index: /trunk/src/VBox/VMM/STAM.cpp
===================================================================
--- /trunk/src/VBox/VMM/STAM.cpp	(revision 19453)
+++ /trunk/src/VBox/VMM/STAM.cpp	(revision 19454)
@@ -195,4 +195,6 @@
     { RT_UOFFSETOF(GVMMSTATS, SchedVM.cWakeUpNotHalted),  STAMTYPE_U64_RESET, STAMUNIT_CALLS, "/GVMM/VM/WakeUpNotHalted", "The number of times the EMT thread wasn't actually halted when GVMMR0WakeUp was called." },
     { RT_UOFFSETOF(GVMMSTATS, SchedVM.cWakeUpWakeUps),    STAMTYPE_U64_RESET, STAMUNIT_CALLS, "/GVMM/VM/WakeUpWakeUps", "The number of wake ups done during GVMMR0WakeUp (not counting the explicit one)." },
+    { RT_UOFFSETOF(GVMMSTATS, SchedVM.cPokeCalls),        STAMTYPE_U64_RESET, STAMUNIT_CALLS, "/GVMM/VM/PokeCalls", "The number of calls to GVMMR0Poke." },
+    { RT_UOFFSETOF(GVMMSTATS, SchedVM.cPokeNotBusy),      STAMTYPE_U64_RESET, STAMUNIT_CALLS, "/GVMM/VM/PokeNotBusy", "The number of times the EMT thread wasn't actually busy when GVMMR0Poke was called." },
     { RT_UOFFSETOF(GVMMSTATS, SchedVM.cPollCalls),        STAMTYPE_U64_RESET, STAMUNIT_CALLS, "/GVMM/VM/PollCalls", "The number of calls to GVMMR0SchedPoll." },
     { RT_UOFFSETOF(GVMMSTATS, SchedVM.cPollHalts),        STAMTYPE_U64_RESET, STAMUNIT_CALLS, "/GVMM/VM/PollHalts", "The number of times the EMT has halted in a GVMMR0SchedPoll call." },
@@ -207,4 +209,6 @@
     { RT_UOFFSETOF(GVMMSTATS, SchedSum.cWakeUpNotHalted), STAMTYPE_U64_RESET, STAMUNIT_CALLS, "/GVMM/Sum/WakeUpNotHalted", "The number of times the EMT thread wasn't actually halted when GVMMR0WakeUp was called." },
     { RT_UOFFSETOF(GVMMSTATS, SchedSum.cWakeUpWakeUps),   STAMTYPE_U64_RESET, STAMUNIT_CALLS, "/GVMM/Sum/WakeUpWakeUps", "The number of wake ups done during GVMMR0WakeUp (not counting the explicit one)." },
+    { RT_UOFFSETOF(GVMMSTATS, SchedSum.cPokeCalls),       STAMTYPE_U64_RESET, STAMUNIT_CALLS, "/GVMM/Sum/PokeCalls", "The number of calls to GVMMR0Poke." },
+    { RT_UOFFSETOF(GVMMSTATS, SchedSum.cPokeNotBusy),     STAMTYPE_U64_RESET, STAMUNIT_CALLS, "/GVMM/Sum/PokeNotBusy", "The number of times the EMT thread wasn't actually busy when GVMMR0Poke was called." },
     { RT_UOFFSETOF(GVMMSTATS, SchedSum.cPollCalls),       STAMTYPE_U64_RESET, STAMUNIT_CALLS, "/GVMM/Sum/PollCalls", "The number of calls to GVMMR0SchedPoll." },
     { RT_UOFFSETOF(GVMMSTATS, SchedSum.cPollHalts),       STAMTYPE_U64_RESET, STAMUNIT_CALLS, "/GVMM/Sum/PollHalts", "The number of times the EMT has halted in a GVMMR0SchedPoll call." },
@@ -754,5 +758,5 @@
         GVMMReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
         GVMMReq.pSession = pVM->pSession;
-        rc = VMMR3CallR0(pVM, VMMR0_DO_GVMM_RESET_STATISTICS, 0, &GVMMReq.Hdr);
+        rc = SUPCallVMMR0Ex(pVM->pVMR0, NIL_VMCPUID, VMMR0_DO_GVMM_RESET_STATISTICS, 0, &GVMMReq.Hdr);
     }
 
@@ -1766,5 +1770,5 @@
         Req.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
         Req.pSession = pVM->pSession;
-        int rc = VMMR3CallR0(pVM, VMMR0_DO_GVMM_QUERY_STATISTICS, 0, &Req.Hdr);
+        int rc = SUPCallVMMR0Ex(pVM->pVMR0, NIL_VMCPUID, VMMR0_DO_GVMM_QUERY_STATISTICS, 0, &Req.Hdr);
         if (RT_SUCCESS(rc))
             pUVM->stam.s.GVMMStats = Req.Stats;
Index: /trunk/src/VBox/VMM/VM.cpp
===================================================================
--- /trunk/src/VBox/VMM/VM.cpp	(revision 19453)
+++ /trunk/src/VBox/VMM/VM.cpp	(revision 19454)
@@ -517,5 +517,5 @@
     CreateVMReq.pVMR3           = NULL;
     CreateVMReq.cCpus           = cCpus;
-    rc = SUPCallVMMR0Ex(NIL_RTR0PTR, 0 /* VCPU 0 */, VMMR0_DO_GVMM_CREATE_VM, 0, &CreateVMReq.Hdr);
+    rc = SUPCallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, VMMR0_DO_GVMM_CREATE_VM, 0, &CreateVMReq.Hdr);
     if (RT_SUCCESS(rc))
     {
Index: /trunk/src/VBox/VMM/VMMR0/GMMR0.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR0/GMMR0.cpp	(revision 19453)
+++ /trunk/src/VBox/VMM/VMMR0/GMMR0.cpp	(revision 19454)
@@ -1048,5 +1048,5 @@
  * @thread  The creator thread / EMT.
  */
-GMMR0DECL(int) GMMR0InitialReservation(PVM pVM, unsigned idCpu, uint64_t cBasePages, uint32_t cShadowPages, uint32_t cFixedPages,
+GMMR0DECL(int) GMMR0InitialReservation(PVM pVM, VMCPUID idCpu, uint64_t cBasePages, uint32_t cShadowPages, uint32_t cFixedPages,
                                        GMMOCPOLICY enmPolicy, GMMPRIORITY enmPriority)
 {
@@ -1059,9 +1059,8 @@
     PGMM pGMM;
     GMM_GET_VALID_INSTANCE(pGMM, VERR_INTERNAL_ERROR);
-    PGVM pGVM = GVMMR0ByVM(pVM);
-    if (RT_UNLIKELY(!pGVM))
-        return VERR_INVALID_PARAMETER;
-    if (RT_UNLIKELY(pGVM->aCpus[idCpu].hEMT != RTThreadNativeSelf()))
-        return VERR_NOT_OWNER;
+    PGVM pGVM;
+    int rc = GVMMR0ByVMAndEMT(pVM, idCpu, &pGVM);
+    if (RT_FAILURE(rc))
+        return rc;
 
     AssertReturn(cBasePages, VERR_INVALID_PARAMETER);
@@ -1071,5 +1070,5 @@
     AssertReturn(enmPriority > GMMPRIORITY_INVALID && enmPriority < GMMPRIORITY_END, VERR_INVALID_PARAMETER);
 
-    int rc = RTSemFastMutexRequest(pGMM->Mtx);
+    rc = RTSemFastMutexRequest(pGMM->Mtx);
     AssertRC(rc);
 
@@ -1115,5 +1114,5 @@
  * @param   pReq            The request packet.
  */
-GMMR0DECL(int) GMMR0InitialReservationReq(PVM pVM, unsigned idCpu, PGMMINITIALRESERVATIONREQ pReq)
+GMMR0DECL(int) GMMR0InitialReservationReq(PVM pVM, VMCPUID idCpu, PGMMINITIALRESERVATIONREQ pReq)
 {
     /*
@@ -1144,5 +1143,5 @@
  * @thread  EMT.
  */
-GMMR0DECL(int) GMMR0UpdateReservation(PVM pVM, unsigned idCpu, uint64_t cBasePages, uint32_t cShadowPages, uint32_t cFixedPages)
+GMMR0DECL(int) GMMR0UpdateReservation(PVM pVM, VMCPUID idCpu, uint64_t cBasePages, uint32_t cShadowPages, uint32_t cFixedPages)
 {
     LogFlow(("GMMR0UpdateReservation: pVM=%p cBasePages=%#llx cShadowPages=%#x cFixedPages=%#x\n",
@@ -1154,9 +1153,8 @@
     PGMM pGMM;
     GMM_GET_VALID_INSTANCE(pGMM, VERR_INTERNAL_ERROR);
-    PGVM pGVM = GVMMR0ByVM(pVM);
-    if (RT_UNLIKELY(!pGVM))
-        return VERR_INVALID_PARAMETER;
-    if (RT_UNLIKELY(pGVM->aCpus[idCpu].hEMT != RTThreadNativeSelf()))
-        return VERR_NOT_OWNER;
+    PGVM pGVM;
+    int rc = GVMMR0ByVMAndEMT(pVM, idCpu, &pGVM);
+    if (RT_FAILURE(rc))
+        return rc;
 
     AssertReturn(cBasePages, VERR_INVALID_PARAMETER);
@@ -1164,5 +1162,5 @@
     AssertReturn(cFixedPages, VERR_INVALID_PARAMETER);
 
-    int rc = RTSemFastMutexRequest(pGMM->Mtx);
+    rc = RTSemFastMutexRequest(pGMM->Mtx);
     AssertRC(rc);
 
@@ -1207,5 +1205,5 @@
  * @param   pReq            The request packet.
  */
-GMMR0DECL(int) GMMR0UpdateReservationReq(PVM pVM, unsigned idCpu, PGMMUPDATERESERVATIONREQ pReq)
+GMMR0DECL(int) GMMR0UpdateReservationReq(PVM pVM, VMCPUID idCpu, PGMMUPDATERESERVATIONREQ pReq)
 {
     /*
@@ -1851,5 +1849,5 @@
  * @thread  EMT.
  */
-GMMR0DECL(int) GMMR0AllocateHandyPages(PVM pVM, unsigned idCpu, uint32_t cPagesToUpdate, uint32_t cPagesToAlloc, PGMMPAGEDESC paPages)
+GMMR0DECL(int) GMMR0AllocateHandyPages(PVM pVM, VMCPUID idCpu, uint32_t cPagesToUpdate, uint32_t cPagesToAlloc, PGMMPAGEDESC paPages)
 {
     LogFlow(("GMMR0AllocateHandyPages: pVM=%p cPagesToUpdate=%#x cPagesToAlloc=%#x paPages=%p\n",
@@ -1862,9 +1860,8 @@
     PGMM pGMM;
     GMM_GET_VALID_INSTANCE(pGMM, VERR_INTERNAL_ERROR);
-    PGVM pGVM = GVMMR0ByVM(pVM);
-    if (RT_UNLIKELY(!pGVM))
-        return VERR_INVALID_PARAMETER;
-    if (RT_UNLIKELY(pGVM->aCpus[idCpu].hEMT != RTThreadNativeSelf()))
-        return VERR_NOT_OWNER;
+    PGVM pGVM;
+    int rc = GVMMR0ByVMAndEMT(pVM, idCpu, &pGVM);
+    if (RT_FAILURE(rc))
+        return rc;
 
     AssertPtrReturn(paPages, VERR_INVALID_PARAMETER);
@@ -1898,5 +1895,5 @@
     }
 
-    int rc = RTSemFastMutexRequest(pGMM->Mtx);
+    rc = RTSemFastMutexRequest(pGMM->Mtx);
     AssertRC(rc);
 
@@ -2034,5 +2031,5 @@
  * @thread  EMT.
  */
-GMMR0DECL(int) GMMR0AllocatePages(PVM pVM, unsigned idCpu, uint32_t cPages, PGMMPAGEDESC paPages, GMMACCOUNT enmAccount)
+GMMR0DECL(int) GMMR0AllocatePages(PVM pVM, VMCPUID idCpu, uint32_t cPages, PGMMPAGEDESC paPages, GMMACCOUNT enmAccount)
 {
     LogFlow(("GMMR0AllocatePages: pVM=%p cPages=%#x paPages=%p enmAccount=%d\n", pVM, cPages, paPages, enmAccount));
@@ -2043,9 +2040,8 @@
     PGMM pGMM;
     GMM_GET_VALID_INSTANCE(pGMM, VERR_INTERNAL_ERROR);
-    PGVM pGVM = GVMMR0ByVM(pVM);
-    if (RT_UNLIKELY(!pGVM))
-        return VERR_INVALID_PARAMETER;
-    if (RT_UNLIKELY(pGVM->aCpus[idCpu].hEMT != RTThreadNativeSelf()))
-        return VERR_NOT_OWNER;
+    PGVM pGVM;
+    int rc = GVMMR0ByVMAndEMT(pVM, idCpu, &pGVM);
+    if (RT_FAILURE(rc))
+        return rc;
 
     AssertPtrReturn(paPages, VERR_INVALID_PARAMETER);
@@ -2066,5 +2062,5 @@
     }
 
-    int rc = RTSemFastMutexRequest(pGMM->Mtx);
+    rc = RTSemFastMutexRequest(pGMM->Mtx);
     AssertRC(rc);
 
@@ -2104,5 +2100,5 @@
  * @param   pReq            The request packet.
  */
-GMMR0DECL(int) GMMR0AllocatePagesReq(PVM pVM, unsigned idCpu, PGMMALLOCATEPAGESREQ pReq)
+GMMR0DECL(int) GMMR0AllocatePagesReq(PVM pVM, VMCPUID idCpu, PGMMALLOCATEPAGESREQ pReq)
 {
     /*
@@ -2430,5 +2426,5 @@
  * @thread  EMT.
  */
-GMMR0DECL(int) GMMR0FreePages(PVM pVM, unsigned idCpu, uint32_t cPages, PGMMFREEPAGEDESC paPages, GMMACCOUNT enmAccount)
+GMMR0DECL(int) GMMR0FreePages(PVM pVM, VMCPUID idCpu, uint32_t cPages, PGMMFREEPAGEDESC paPages, GMMACCOUNT enmAccount)
 {
     LogFlow(("GMMR0FreePages: pVM=%p cPages=%#x paPages=%p enmAccount=%d\n", pVM, cPages, paPages, enmAccount));
@@ -2439,9 +2435,8 @@
     PGMM pGMM;
     GMM_GET_VALID_INSTANCE(pGMM, VERR_INTERNAL_ERROR);
-    PGVM pGVM = GVMMR0ByVM(pVM);
-    if (RT_UNLIKELY(!pGVM))
-        return VERR_INVALID_PARAMETER;
-    if (RT_UNLIKELY(pGVM->aCpus[idCpu].hEMT != RTThreadNativeSelf()))
-        return VERR_NOT_OWNER;
+    PGVM pGVM;
+    int rc = GVMMR0ByVMAndEMT(pVM, idCpu, &pGVM);
+    if (RT_FAILURE(rc))
+        return rc;
 
     AssertPtrReturn(paPages, VERR_INVALID_PARAMETER);
@@ -2457,5 +2452,5 @@
      * Take the semaphore and call the worker function.
      */
-    int rc = RTSemFastMutexRequest(pGMM->Mtx);
+    rc = RTSemFastMutexRequest(pGMM->Mtx);
     AssertRC(rc);
 
@@ -2476,5 +2471,5 @@
  * @param   pReq            The request packet.
  */
-GMMR0DECL(int) GMMR0FreePagesReq(PVM pVM, unsigned idCpu, PGMMFREEPAGESREQ pReq)
+GMMR0DECL(int) GMMR0FreePagesReq(PVM pVM, VMCPUID idCpu, PGMMFREEPAGESREQ pReq)
 {
     /*
@@ -2518,5 +2513,5 @@
  * @thread  EMT.
  */
-GMMR0DECL(int) GMMR0BalloonedPages(PVM pVM, unsigned idCpu, uint32_t cBalloonedPages, uint32_t cPagesToFree, PGMMFREEPAGEDESC paPages, bool fCompleted)
+GMMR0DECL(int) GMMR0BalloonedPages(PVM pVM, VMCPUID idCpu, uint32_t cBalloonedPages, uint32_t cPagesToFree, PGMMFREEPAGEDESC paPages, bool fCompleted)
 {
     LogFlow(("GMMR0BalloonedPages: pVM=%p cBalloonedPages=%#x cPagestoFree=%#x paPages=%p enmAccount=%d fCompleted=%RTbool\n",
@@ -2528,9 +2523,8 @@
     PGMM pGMM;
     GMM_GET_VALID_INSTANCE(pGMM, VERR_INTERNAL_ERROR);
-    PGVM pGVM = GVMMR0ByVM(pVM);
-    if (RT_UNLIKELY(!pGVM))
-        return VERR_INVALID_PARAMETER;
-    if (RT_UNLIKELY(pGVM->aCpus[idCpu].hEMT != RTThreadNativeSelf()))
-        return VERR_NOT_OWNER;
+    PGVM pGVM;
+    int rc = GVMMR0ByVMAndEMT(pVM, idCpu, &pGVM);
+    if (RT_FAILURE(rc))
+        return rc;
 
     AssertPtrReturn(paPages, VERR_INVALID_PARAMETER);
@@ -2546,5 +2540,5 @@
      * Take the sempahore and do some more validations.
      */
-    int rc = RTSemFastMutexRequest(pGMM->Mtx);
+    rc = RTSemFastMutexRequest(pGMM->Mtx);
     AssertRC(rc);
     if (pGVM->gmm.s.Allocated.cBasePages >= cPagesToFree)
@@ -2604,5 +2598,5 @@
  * @param   pReq            The request packet.
  */
-GMMR0DECL(int) GMMR0BalloonedPagesReq(PVM pVM, unsigned idCpu, PGMMBALLOONEDPAGESREQ pReq)
+GMMR0DECL(int) GMMR0BalloonedPagesReq(PVM pVM, VMCPUID idCpu, PGMMBALLOONEDPAGESREQ pReq)
 {
     /*
@@ -2633,5 +2627,5 @@
  * @thread  EMT.
  */
-GMMR0DECL(int) GMMR0DeflatedBalloon(PVM pVM, unsigned idCpu, uint32_t cPages)
+GMMR0DECL(int) GMMR0DeflatedBalloon(PVM pVM, VMCPUID idCpu, uint32_t cPages)
 {
     LogFlow(("GMMR0DeflatedBalloon: pVM=%p cPages=%#x\n", pVM, cPages));
@@ -2642,9 +2636,8 @@
     PGMM pGMM;
     GMM_GET_VALID_INSTANCE(pGMM, VERR_INTERNAL_ERROR);
-    PGVM pGVM = GVMMR0ByVM(pVM);
-    if (RT_UNLIKELY(!pGVM))
-        return VERR_INVALID_PARAMETER;
-    if (RT_UNLIKELY(pGVM->aCpus[idCpu].hEMT != RTThreadNativeSelf()))
-        return VERR_NOT_OWNER;
+    PGVM pGVM;
+    int rc = GVMMR0ByVMAndEMT(pVM, idCpu, &pGVM);
+    if (RT_FAILURE(rc))
+        return rc;
 
     AssertMsgReturn(cPages < RT_BIT(32 - PAGE_SHIFT), ("%#x\n", cPages), VERR_INVALID_PARAMETER);
@@ -2653,5 +2646,5 @@
      * Take the sempahore and do some more validations.
      */
-    int rc = RTSemFastMutexRequest(pGMM->Mtx);
+    rc = RTSemFastMutexRequest(pGMM->Mtx);
     AssertRC(rc);
 
@@ -2824,5 +2817,5 @@
  * @thread  EMT
  */
-GMMR0DECL(int) GMMR0MapUnmapChunk(PVM pVM, unsigned idCpu, uint32_t idChunkMap, uint32_t idChunkUnmap, PRTR3PTR ppvR3)
+GMMR0DECL(int) GMMR0MapUnmapChunk(PVM pVM, VMCPUID idCpu, uint32_t idChunkMap, uint32_t idChunkUnmap, PRTR3PTR ppvR3)
 {
     LogFlow(("GMMR0MapUnmapChunk: pVM=%p idChunkMap=%#x idChunkUnmap=%#x ppvR3=%p\n",
@@ -2834,9 +2827,8 @@
     PGMM pGMM;
     GMM_GET_VALID_INSTANCE(pGMM, VERR_INTERNAL_ERROR);
-    PGVM pGVM = GVMMR0ByVM(pVM);
-    if (RT_UNLIKELY(!pGVM))
-        return VERR_INVALID_PARAMETER;
-    if (RT_UNLIKELY(pGVM->aCpus[idCpu].hEMT != RTThreadNativeSelf()))
-        return VERR_NOT_OWNER;
+    PGVM pGVM;
+    int rc = GVMMR0ByVMAndEMT(pVM, idCpu, &pGVM);
+    if (RT_FAILURE(rc))
+        return rc;
 
     AssertCompile(NIL_GMM_CHUNKID == 0);
@@ -2862,5 +2854,5 @@
      * it it's limits, so, no problem here.
      */
-    int rc = RTSemFastMutexRequest(pGMM->Mtx);
+    rc = RTSemFastMutexRequest(pGMM->Mtx);
     AssertRC(rc);
 
@@ -2909,5 +2901,5 @@
  * @param   pReq            The request packet.
  */
-GMMR0DECL(int)  GMMR0MapUnmapChunkReq(PVM pVM, unsigned idCpu, PGMMMAPUNMAPCHUNKREQ pReq)
+GMMR0DECL(int)  GMMR0MapUnmapChunkReq(PVM pVM, VMCPUID idCpu, PGMMMAPUNMAPCHUNKREQ pReq)
 {
     /*
@@ -2933,5 +2925,5 @@
  * @param   pvR3            Pointer to the chunk size memory block to lock down.
  */
-GMMR0DECL(int) GMMR0SeedChunk(PVM pVM, unsigned idCpu, RTR3PTR pvR3)
+GMMR0DECL(int) GMMR0SeedChunk(PVM pVM, VMCPUID idCpu, RTR3PTR pvR3)
 {
     /*
@@ -2940,9 +2932,8 @@
     PGMM pGMM;
     GMM_GET_VALID_INSTANCE(pGMM, VERR_INTERNAL_ERROR);
-    PGVM pGVM = GVMMR0ByVM(pVM);
-    if (RT_UNLIKELY(!pGVM))
-        return VERR_INVALID_PARAMETER;
-    if (RT_UNLIKELY(pGVM->aCpus[idCpu].hEMT != RTThreadNativeSelf()))
-        return VERR_NOT_OWNER;
+    PGVM pGVM;
+    int rc = GVMMR0ByVMAndEMT(pVM, idCpu, &pGVM);
+    if (RT_FAILURE(rc))
+        return rc;
 
     AssertPtrReturn(pvR3, VERR_INVALID_POINTER);
@@ -2959,5 +2950,5 @@
      */
     RTR0MEMOBJ MemObj;
-    int rc = RTR0MemObjLockUser(&MemObj, pvR3, GMM_CHUNK_SIZE, NIL_RTR0PROCESS);
+    rc = RTR0MemObjLockUser(&MemObj, pvR3, GMM_CHUNK_SIZE, NIL_RTR0PROCESS);
     if (RT_SUCCESS(rc))
     {
Index: /trunk/src/VBox/VMM/VMMR0/GVMMR0.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR0/GVMMR0.cpp	(revision 19453)
+++ /trunk/src/VBox/VMM/VMMR0/GVMMR0.cpp	(revision 19454)
@@ -58,4 +58,5 @@
 #include <iprt/mem.h>
 #include <iprt/memobj.h>
+#include <iprt/mp.h>
 
 
@@ -1516,5 +1517,4 @@
 
     PGVMCPU pCurGVCpu = &pGVM->aCpus[idCpu];
-    Assert(idCpu < pGVM->cCpus);
     Assert(!pCurGVCpu->gvmm.s.u64HaltExpire);
 
@@ -1579,5 +1579,4 @@
 DECLINLINE(int) gvmmR0SchedWakeUpOne(PGVM pGVM, PGVMCPU pGVCpu)
 {
-    int rc;
     pGVM->gvmm.s.StatsSched.cWakeUpCalls++;
 
@@ -1591,4 +1590,5 @@
      */
 /** @todo we can optimize some of that by means of the pVCpu->enmState now. */
+    int rc;
     if (pGVCpu->gvmm.s.u64HaltExpire)
     {
@@ -1669,10 +1669,15 @@
 DECLINLINE(int) gvmmR0SchedPokeOne(PGVM pGVM, PVMCPU pVCpu)
 {
-    if (pVCpu->enmState != VMCPUSTATE_STARTED_EXEC)
+    pGVM->gvmm.s.StatsSched.cPokeCalls++;
+
+    RTCPUID idHostCpu = pVCpu->idHostCpu;
+    if (    idHostCpu == NIL_RTCPUID
+        ||  VMCPU_GET_STATE(pVCpu) != VMCPUSTATE_STARTED_EXEC)
+    {
+        pGVM->gvmm.s.StatsSched.cPokeNotBusy++;
         return VINF_GVM_NOT_BUSY_IN_GC;
-
-    /** @todo do the actual poking, need to get the current cpu id from HWACC or
-     *        somewhere and then call RTMpPokeCpu(). */
-
+    }
+
+    RTMpPokeCpu(idHostCpu);
     return VINF_SUCCESS;
 }
@@ -1899,4 +1904,7 @@
             pStats->SchedSum.cWakeUpNotHalted  += pGVM->gvmm.s.StatsSched.cWakeUpNotHalted;
             pStats->SchedSum.cWakeUpWakeUps    += pGVM->gvmm.s.StatsSched.cWakeUpWakeUps;
+
+            pStats->SchedSum.cPokeCalls        += pGVM->gvmm.s.StatsSched.cPokeCalls;
+            pStats->SchedSum.cPokeNotBusy      += pGVM->gvmm.s.StatsSched.cPokeNotBusy;
 
             pStats->SchedSum.cPollCalls        += pGVM->gvmm.s.StatsSched.cPollCalls;
@@ -1970,4 +1978,6 @@
         MAYBE_RESET_FIELD(cWakeUpNotHalted);
         MAYBE_RESET_FIELD(cWakeUpWakeUps);
+        MAYBE_RESET_FIELD(cPokeCalls);
+        MAYBE_RESET_FIELD(cPokeNotBusy);
         MAYBE_RESET_FIELD(cPollCalls);
         MAYBE_RESET_FIELD(cPollHalts);
@@ -2009,4 +2019,6 @@
                 MAYBE_RESET_FIELD(cWakeUpNotHalted);
                 MAYBE_RESET_FIELD(cWakeUpWakeUps);
+                MAYBE_RESET_FIELD(cPokeCalls);
+                MAYBE_RESET_FIELD(cPokeNotBusy);
                 MAYBE_RESET_FIELD(cPollCalls);
                 MAYBE_RESET_FIELD(cPollHalts);
Index: /trunk/src/VBox/VMM/VMMR0/VMMR0.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR0/VMMR0.cpp	(revision 19453)
+++ /trunk/src/VBox/VMM/VMMR0/VMMR0.cpp	(revision 19454)
@@ -526,12 +526,10 @@
  * @param   pVM             The VM to operate on.
  *                          The return code is stored in pVM->vmm.s.iLastGZRc.
- * @param   idCpu           VMCPU id.
+ * @param   idCpu           The Virtual CPU ID of the calling EMT.
  * @param   enmOperation    Which operation to execute.
  * @remarks Assume called with interrupts _enabled_.
  */
-VMMR0DECL(void) VMMR0EntryFast(PVM pVM, unsigned idCpu, VMMR0OPERATION enmOperation)
-{
-    PVMCPU pVCpu = &pVM->aCpus[idCpu];
-
+VMMR0DECL(void) VMMR0EntryFast(PVM pVM, VMCPUID idCpu, VMMR0OPERATION enmOperation)
+{
     if (RT_UNLIKELY(idCpu >= pVM->cCPUs))
     {
@@ -539,4 +537,5 @@
         return;
     }
+    PVMCPU pVCpu = &pVM->aCpus[idCpu];
 
     switch (enmOperation)
@@ -552,6 +551,6 @@
             {
                 RTCCUINTREG uFlags = ASMIntDisableFlags();
-                int rc;
-                bool fVTxDisabled;
+                int         rc;
+                bool        fVTxDisabled;
 
                 if (RT_UNLIKELY(pVM->cCPUs > 1))
@@ -577,8 +576,14 @@
                 }
 
+                ASMAtomicWriteU32(&pVCpu->idHostCpu, RTMpCpuId());
+                VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STARTED_EXEC);
+
                 TMNotifyStartOfExecution(pVCpu);
                 rc = pVM->vmm.s.pfnHostToGuestR0(pVM);
                 pVM->vmm.s.iLastGZRc = rc;
                 TMNotifyEndOfExecution(pVCpu);
+
+                VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STARTED);
+                ASMAtomicWriteU32(&pVCpu->idHostCpu, NIL_RTCPUID);
 
                 /* Re-enable VT-x if previously turned off. */
@@ -614,5 +619,4 @@
         {
             int rc;
-            PVMCPU pVCpu = &pVM->aCpus[idCpu];
 
             STAM_COUNTER_INC(&pVM->vmm.s.StatRunRC);
@@ -621,4 +625,6 @@
             RTCCUINTREG uFlags = ASMIntDisableFlags();
 #endif
+            ASMAtomicWriteU32(&pVCpu->idHostCpu, NIL_RTCPUID);
+
             if (!HWACCMR0SuspendPending())
             {
@@ -637,4 +643,6 @@
             }
             pVM->vmm.s.iLastGZRc = rc;
+
+            ASMAtomicWriteU32(&pVCpu->idHostCpu, NIL_RTCPUID);
 #ifndef RT_OS_WINDOWS /** @todo check other hosts */
             ASMSetFlags(uFlags);
@@ -694,5 +702,6 @@
  * @returns VBox status code.
  * @param   pVM             The VM to operate on.
- * @param   idCpu           VMCPU id.
+ * @param   idCpu           Virtual CPU ID argument. Must be NIL_VMCPUID if pVM
+ *                          is NIL_RTR0PTR, and may be NIL_VMCPUID if it isn't
  * @param   enmOperation    Which operation to execute.
  * @param   pReqHdr         This points to a SUPVMMR0REQHDR packet. Optional.
@@ -702,5 +711,5 @@
  * @remarks Assume called with interrupts _enabled_.
  */
-static int vmmR0EntryExWorker(PVM pVM, unsigned idCpu, VMMR0OPERATION enmOperation, PSUPVMMR0REQHDR pReqHdr, uint64_t u64Arg, PSUPDRVSESSION pSession)
+static int vmmR0EntryExWorker(PVM pVM, VMCPUID idCpu, VMMR0OPERATION enmOperation, PSUPVMMR0REQHDR pReqHdr, uint64_t u64Arg, PSUPDRVSESSION pSession)
 {
     /*
@@ -724,10 +733,16 @@
         }
 
-        if (RT_UNLIKELY(idCpu >= pVM->cCPUs))
+        if (RT_UNLIKELY(idCpu >= pVM->cCPUs && idCpu != NIL_VMCPUID))
         {
-            SUPR0Printf("vmmR0EntryExWorker: Invalid idCpu (%d vs cCPUs=%d\n", idCpu, pVM->cCPUs);
+            SUPR0Printf("vmmR0EntryExWorker: Invalid idCpu (%u vs cCPUs=%u)\n", idCpu, pVM->cCPUs);
             return VERR_INVALID_PARAMETER;
         }
     }
+    else if (RT_UNLIKELY(idCpu != NIL_VMCPUID))
+    {
+        SUPR0Printf("vmmR0EntryExWorker: Invalid idCpu=%u\n", idCpu);
+        return VERR_INVALID_PARAMETER;
+    }
+
 
     switch (enmOperation)
@@ -737,5 +752,5 @@
          */
         case VMMR0_DO_GVMM_CREATE_VM:
-            if (pVM || u64Arg)
+            if (pVM || u64Arg || idCpu != NIL_VMCPUID)
                 return VERR_INVALID_PARAMETER;
             return GVMMR0CreateVMReq((PGVMMCREATEVMREQ)pReqHdr);
@@ -817,5 +832,5 @@
 
         /*
-         * Switch to GC to execute Hypervisor function.
+         * Switch to RC to execute Hypervisor function.
          */
         case VMMR0_DO_CALL_HYPERVISOR:
@@ -855,4 +870,6 @@
          */
         case VMMR0_DO_PGM_ALLOCATE_HANDY_PAGES:
+            if (idCpu == NIL_VMCPUID)
+                return VERR_INVALID_CPU_ID;
             return PGMR0PhysAllocateHandyPages(pVM, &pVM->aCpus[idCpu]);
 
@@ -907,5 +924,5 @@
         case VMMR0_DO_GCFGM_QUERY_VALUE:
         {
-            if (pVM || !pReqHdr || u64Arg)
+            if (pVM || !pReqHdr || u64Arg || idCpu != NIL_VMCPUID)
                 return VERR_INVALID_PARAMETER;
             PGCFGMVALUEREQ pReq = (PGCFGMVALUEREQ)pReqHdr;
@@ -935,5 +952,5 @@
         {
             PINTNETOPENREQ pReq = (PINTNETOPENREQ)pReqHdr;
-            if (u64Arg || !pReq || !vmmR0IsValidSession(pVM, pReq->pSession, pSession))
+            if (u64Arg || !pReq || !vmmR0IsValidSession(pVM, pReq->pSession, pSession) || idCpu != NIL_VMCPUID)
                 return VERR_INVALID_PARAMETER;
             if (!g_pIntNet)
@@ -943,5 +960,5 @@
 
         case VMMR0_DO_INTNET_IF_CLOSE:
-            if (u64Arg || !pReqHdr || !vmmR0IsValidSession(pVM, ((PINTNETIFCLOSEREQ)pReqHdr)->pSession, pSession))
+            if (u64Arg || !pReqHdr || !vmmR0IsValidSession(pVM, ((PINTNETIFCLOSEREQ)pReqHdr)->pSession, pSession) || idCpu != NIL_VMCPUID)
                 return VERR_INVALID_PARAMETER;
             if (!g_pIntNet)
@@ -950,5 +967,5 @@
 
         case VMMR0_DO_INTNET_IF_GET_RING3_BUFFER:
-            if (u64Arg || !pReqHdr || !vmmR0IsValidSession(pVM, ((PINTNETIFGETRING3BUFFERREQ)pReqHdr)->pSession, pSession))
+            if (u64Arg || !pReqHdr || !vmmR0IsValidSession(pVM, ((PINTNETIFGETRING3BUFFERREQ)pReqHdr)->pSession, pSession) || idCpu != NIL_VMCPUID)
                 return VERR_INVALID_PARAMETER;
             if (!g_pIntNet)
@@ -957,5 +974,5 @@
 
         case VMMR0_DO_INTNET_IF_SET_PROMISCUOUS_MODE:
-            if (u64Arg || !pReqHdr || !vmmR0IsValidSession(pVM, ((PINTNETIFSETPROMISCUOUSMODEREQ)pReqHdr)->pSession, pSession))
+            if (u64Arg || !pReqHdr || !vmmR0IsValidSession(pVM, ((PINTNETIFSETPROMISCUOUSMODEREQ)pReqHdr)->pSession, pSession) || idCpu != NIL_VMCPUID)
                 return VERR_INVALID_PARAMETER;
             if (!g_pIntNet)
@@ -964,5 +981,5 @@
 
         case VMMR0_DO_INTNET_IF_SET_MAC_ADDRESS:
-            if (u64Arg || !pReqHdr || !vmmR0IsValidSession(pVM, ((PINTNETIFSETMACADDRESSREQ)pReqHdr)->pSession, pSession))
+            if (u64Arg || !pReqHdr || !vmmR0IsValidSession(pVM, ((PINTNETIFSETMACADDRESSREQ)pReqHdr)->pSession, pSession) || idCpu != NIL_VMCPUID)
                 return VERR_INVALID_PARAMETER;
             if (!g_pIntNet)
@@ -971,5 +988,5 @@
 
         case VMMR0_DO_INTNET_IF_SET_ACTIVE:
-            if (u64Arg || !pReqHdr || !vmmR0IsValidSession(pVM, ((PINTNETIFSETACTIVEREQ)pReqHdr)->pSession, pSession))
+            if (u64Arg || !pReqHdr || !vmmR0IsValidSession(pVM, ((PINTNETIFSETACTIVEREQ)pReqHdr)->pSession, pSession) || idCpu != NIL_VMCPUID)
                 return VERR_INVALID_PARAMETER;
             if (!g_pIntNet)
@@ -978,5 +995,5 @@
 
         case VMMR0_DO_INTNET_IF_SEND:
-            if (u64Arg || !pReqHdr || !vmmR0IsValidSession(pVM, ((PINTNETIFSENDREQ)pReqHdr)->pSession, pSession))
+            if (u64Arg || !pReqHdr || !vmmR0IsValidSession(pVM, ((PINTNETIFSENDREQ)pReqHdr)->pSession, pSession) || idCpu != NIL_VMCPUID)
                 return VERR_INVALID_PARAMETER;
             if (!g_pIntNet)
@@ -985,5 +1002,5 @@
 
         case VMMR0_DO_INTNET_IF_WAIT:
-            if (u64Arg || !pReqHdr || !vmmR0IsValidSession(pVM, ((PINTNETIFWAITREQ)pReqHdr)->pSession, pSession))
+            if (u64Arg || !pReqHdr || !vmmR0IsValidSession(pVM, ((PINTNETIFWAITREQ)pReqHdr)->pSession, pSession) || idCpu != NIL_VMCPUID)
                 return VERR_INVALID_PARAMETER;
             if (!g_pIntNet)
@@ -1008,4 +1025,6 @@
 #if HC_ARCH_BITS == 32 && defined(VBOX_WITH_64_BITS_GUESTS) && !defined(VBOX_WITH_HYBRID_32BIT_KERNEL)
         case VMMR0_DO_TEST_SWITCHER3264:
+            if (idCpu == NIL_VMCPUID)
+                return VERR_INVALID_CPU_ID;
             return HWACCMR0TestSwitcher3264(pVM);
 #endif
@@ -1027,5 +1046,5 @@
 {
     PVM                 pVM;
-    unsigned            idCpu;
+    VMCPUID             idCpu;
     VMMR0OPERATION      enmOperation;
     PSUPVMMR0REQHDR     pReq;
@@ -1058,5 +1077,6 @@
  * @returns VBox status code.
  * @param   pVM             The VM to operate on.
- * @param   idCpu           VMCPU id.
+ * @param   idCpu           Virtual CPU ID argument. Must be NIL_VMCPUID if pVM
+ *                          is NIL_RTR0PTR, and may be NIL_VMCPUID if it isn't
  * @param   enmOperation    Which operation to execute.
  * @param   pReq            This points to a SUPVMMR0REQHDR packet. Optional.
@@ -1065,5 +1085,5 @@
  * @remarks Assume called with interrupts _enabled_.
  */
-VMMR0DECL(int) VMMR0EntryEx(PVM pVM, unsigned idCpu, VMMR0OPERATION enmOperation, PSUPVMMR0REQHDR pReq, uint64_t u64Arg, PSUPDRVSESSION pSession)
+VMMR0DECL(int) VMMR0EntryEx(PVM pVM, VMCPUID idCpu, VMMR0OPERATION enmOperation, PSUPVMMR0REQHDR pReq, uint64_t u64Arg, PSUPDRVSESSION pSession)
 {
     /*
@@ -1072,5 +1092,6 @@
      */
     if (    VALID_PTR(pVM)
-        &&  pVM->pVMR0)
+        &&  pVM->pVMR0
+        &&  idCpu < pVM->cCPUs)
     {
         switch (enmOperation)
Index: /trunk/src/VBox/VMM/testcase/tstGlobalConfig.cpp
===================================================================
--- /trunk/src/VBox/VMM/testcase/tstGlobalConfig.cpp	(revision 19453)
+++ /trunk/src/VBox/VMM/testcase/tstGlobalConfig.cpp	(revision 19454)
@@ -107,5 +107,5 @@
     {
         Req.pSession = pSession;
-        rc = SUPCallVMMR0Ex(NIL_RTR0PTR, 0 /* VCPU 0 */, enmOp, 0, &Req.Hdr);
+        rc = SUPCallVMMR0Ex(NIL_RTR0PTR, NIL_VMCPUID, enmOp, 0, &Req.Hdr);
         if (RT_SUCCESS(rc))
         {
