Index: /trunk/include/VBox/trpm.h
===================================================================
--- /trunk/include/VBox/trpm.h	(revision 396)
+++ /trunk/include/VBox/trpm.h	(revision 397)
@@ -451,4 +451,16 @@
 
 /**
+ * Dispatches an interrupt that arrived while we were in the guest context.
+ *
+ * It's assumes we're invoked with interrupts disabled.
+ * When this function returns, interrupts will be enabled.
+ *
+ * @param   pVM     The VM handle.
+ */
+TRPMR0DECL(void) TRPMR0DispatchHostInterrupt(PVM pVM);
+
+# ifndef VBOX_WITHOUT_IDT_PATCHING
+
+/**
  * Changes the VMMR0Entry() call frame and stack used by the IDT patch code
  * so that we'll dispatch an interrupt rather than returning directly to Ring-3
@@ -460,4 +472,6 @@
 TRPMR0DECL(void) TRPMR0SetupInterruptDispatcherFrame(PVM pVM, void *pvRet);
 
+# endif /* !VBOX_WITHOUT_IDT_PATCHING */
+
 /** @} */
 #endif
Index: /trunk/include/VBox/vmm.h
===================================================================
--- /trunk/include/VBox/vmm.h	(revision 396)
+++ /trunk/include/VBox/vmm.h	(revision 397)
@@ -345,7 +345,8 @@
 {
     /** Run guest context. */
-    VMMR0_DO_RUN_GC = 0,
+    VMMR0_DO_RAW_RUN = 0,
+    VMMR0_DO_RUN_GC = VMMR0_DO_RAW_RUN,
     /** Run guest code using the available hardware acceleration technology. */
-    VMMR0_HWACC_RUN_GUEST,
+    VMMR0_DO_HWACC_RUN,
     /** Call VMMR0 Per VM Init. */
     VMMR0_DO_VMMR0_INIT,
@@ -353,5 +354,5 @@
     VMMR0_DO_VMMR0_TERM,
     /** Setup the hardware accelerated raw-mode session. */
-    VMMR0_HWACC_SETUP_VM,
+    VMMR0_DO_HWACC_SETUP_VM,
     /** Calls function in the hypervisor.
      * The caller must setup the hypervisor context so the call will be performed.
@@ -378,4 +379,9 @@
     VMMR0_DO_SRV_END,
 
+    /** Official NOP that we use for profiling. */
+    VMMR0_DO_NOP,
+    /** Official call we use for testing Ring-0 APIs. */
+    VMMR0_DO_TESTS,
+
     /** The usual 32-bit type blow up. */
     VMMR0_DO_32BIT_HACK = 0x7fffffff
Index: /trunk/src/VBox/HostDrivers/Support/SUPDRVIOC.h
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/SUPDRVIOC.h	(revision 396)
+++ /trunk/src/VBox/HostDrivers/Support/SUPDRVIOC.h	(revision 397)
@@ -132,8 +132,10 @@
 #define SUP_IOCTL_SET_VM_FOR_FAST   SUP_CTL_CODE(20)
 
-/** Fast path IOCtl: VMMR0_DO_RUN_GC */
+/** Fast path IOCtl: VMMR0_DO_RAW_RUN */
 #define SUP_IOCTL_FAST_DO_RAW_RUN   SUP_CTL_CODE_FAST(64)
-/** Fast path IOCtl: VMMR0_HWACC_RUN_GUEST */
+/** Fast path IOCtl: VMMR0_DO_HWACC_RUN */
 #define SUP_IOCTL_FAST_DO_HWACC_RUN SUP_CTL_CODE_FAST(65)
+/** Just a NOP call for profiling the latency of a fast ioctl call to VMMR0. */
+#define SUP_IOCTL_FAST_DO_NOP       SUP_CTL_CODE_FAST(66)
 
 
Index: /trunk/src/VBox/HostDrivers/Support/SUPDRVShared.c
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/SUPDRVShared.c	(revision 396)
+++ /trunk/src/VBox/HostDrivers/Support/SUPDRVShared.c	(revision 397)
@@ -559,16 +559,36 @@
 int  VBOXCALL   supdrvIOCtlFast(unsigned uIOCtl, PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession)
 {
-    if (    !pSession->pVM
-        ||  pDevExt->pfnVMMR0Entry)
-        return VERR_INTERNAL_ERROR;
-    switch (uIOCtl)
-    {
-        case SUP_IOCTL_FAST_DO_RAW_RUN:
-            return pDevExt->pfnVMMR0Entry(pSession->pVM, VMMR0_DO_RUN_GC, NULL);
-        case SUP_IOCTL_FAST_DO_HWACC_RUN:
-            return pDevExt->pfnVMMR0Entry(pSession->pVM, VMMR0_HWACC_RUN_GUEST, NULL);
-        default:
-            return VERR_INTERNAL_ERROR;
-    }
+    /*
+     * Disable interrupts before invoking VMMR0Entry() because it ASSUMES
+     * that interrupts are disabled. (We check the two prereqs after doing
+     * this only to allow the compiler to optimize things better.)
+     */
+    RTCCUINTREG     uFlags = ASMGetFlags();
+    ASMIntDisable();
+
+    int rc;
+    if (RT_LIKELY(pSession->pVM && pDevExt->pfnVMMR0Entry))
+    {
+        switch (uIOCtl)
+        {
+            case SUP_IOCTL_FAST_DO_RAW_RUN:
+                rc = pDevExt->pfnVMMR0Entry(pSession->pVM, VMMR0_DO_RAW_RUN, NULL);
+                break;
+            case SUP_IOCTL_FAST_DO_HWACC_RUN:
+                rc = pDevExt->pfnVMMR0Entry(pSession->pVM, VMMR0_DO_HWACC_RUN, NULL);
+                break;
+            case SUP_IOCTL_FAST_DO_NOP:
+                rc = pDevExt->pfnVMMR0Entry(pSession->pVM, VMMR0_DO_NOP, NULL);
+                break;
+            default:
+                rc = VERR_INTERNAL_ERROR;
+                break;
+        }
+    }
+    else
+        rc = VERR_INTERNAL_ERROR;
+
+    ASMSetFlags(uFlags);
+    return rc;
 }
 #endif /* VBOX_WITHOUT_IDT_PATCHING */
Index: /trunk/src/VBox/HostDrivers/Support/SUPLib.cpp
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/SUPLib.cpp	(revision 396)
+++ /trunk/src/VBox/HostDrivers/Support/SUPLib.cpp	(revision 397)
@@ -381,14 +381,20 @@
 #ifndef VBOX_WITHOUT_IDT_PATCHING
     return g_pfnCallVMMR0(pVM, uOperation, pvArg);
+
 #else
-    if (uOperation == VMMR0_DO_RUN_GC)
+    if (uOperation == VMMR0_DO_RAW_RUN)
     {
         Assert(!pvArg);
         return suplibOSIOCtlFast(SUP_IOCTL_FAST_DO_RAW_RUN);
     }
-    if (uOperation == VMMR0_HWACC_RUN_GUEST)
+    if (uOperation == VMMR0_DO_HWACC_RUN)
     {
         Assert(!pvArg);
         return suplibOSIOCtlFast(SUP_IOCTL_FAST_DO_HWACC_RUN);
+    }
+    if (uOperation == VMMR0_DO_NOP)
+    {
+        Assert(!pvArg);
+        return suplibOSIOCtlFast(SUP_IOCTL_FAST_DO_NOP);
     }
     return SUPCallVMMR0Ex(pVM, uOperation, pvArg, pvArg ? sizeof(pvArg) : 0);
Index: /trunk/src/VBox/HostDrivers/Support/darwin/SUPDrv-darwin.cpp
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/darwin/SUPDrv-darwin.cpp	(revision 396)
+++ /trunk/src/VBox/HostDrivers/Support/darwin/SUPDrv-darwin.cpp	(revision 397)
@@ -430,6 +430,7 @@
      * the session and iCmd, and only returns a VBox status code.
      */
-    if (    iCmd == 1
-        ||  iCmd == 1)
+    if (    iCmd == SUP_IOCTL_FAST_DO_RAW_RUN
+        ||  iCmd == SUP_IOCTL_FAST_DO_HWACC_RUN
+        ||  iCmd == SUP_IOCTL_FAST_DO_NOP)
         return supdrvIOCtlFast(iCmd, &g_DevExt, pSession);
     return VBoxSupDrvIOCtlSlow(pSession, iCmd, pData, pProcess);
Index: /trunk/src/VBox/HostDrivers/Support/testcase/tstInt.cpp
===================================================================
--- /trunk/src/VBox/HostDrivers/Support/testcase/tstInt.cpp	(revision 396)
+++ /trunk/src/VBox/HostDrivers/Support/testcase/tstInt.cpp	(revision 397)
@@ -89,6 +89,10 @@
             for (int i = cIterations; i > 0; i--)
             {
-                rc = SUPCallVMMR0(&vm, 0xdeadbeef, NULL);
-                //RTPrintf("tstInt: SUPCallVMMR0 -> rc=%Vrc i=%d\n", rc, i);
+                rc = SUPCallVMMR0(&vm, VMMR0_DO_NOP, NULL);
+                if (rc != VINF_SUCCESS)
+                {
+                    RTPrintf("tstInt: SUPCallVMMR0 -> rc=%Vrc i=%d Expected VINF_SUCCESS!\n", rc, i);
+                    break;s
+                }
             }
             RTPrintf("tstInt: Performed SUPCallVMMR0 %d times (rc=%Vrc)\n", cIterations, rc);
Index: /trunk/src/VBox/VMM/HWACCM.cpp
===================================================================
--- /trunk/src/VBox/VMM/HWACCM.cpp	(revision 396)
+++ /trunk/src/VBox/VMM/HWACCM.cpp	(revision 397)
@@ -292,5 +292,5 @@
             pVM->hwaccm.s.fInitialized = true;
 
-            int rc = SUPCallVMMR0(pVM, VMMR0_HWACC_SETUP_VM, NULL);
+            int rc = SUPCallVMMR0(pVM, VMMR0_DO_HWACC_SETUP_VM, NULL);
             AssertRC(rc);
             if (rc == VINF_SUCCESS)
@@ -323,5 +323,5 @@
             pVM->hwaccm.s.fInitialized = true;
 
-            int rc = SUPCallVMMR0(pVM, VMMR0_HWACC_SETUP_VM, NULL);
+            int rc = SUPCallVMMR0(pVM, VMMR0_DO_HWACC_SETUP_VM, NULL);
             AssertRC(rc);
             if (rc == VINF_SUCCESS)
Index: /trunk/src/VBox/VMM/TRPMInternal.h
===================================================================
--- /trunk/src/VBox/VMM/TRPMInternal.h	(revision 396)
+++ /trunk/src/VBox/VMM/TRPMInternal.h	(revision 397)
@@ -179,4 +179,17 @@
 
 #ifdef IN_RING0
+
+/**
+ * Calls the interrupt gate as if we received an interrupt while in Ring-0.
+ *
+ * Returns with interrupts enabled.
+ *
+ * @param   uIP     The interrupt gate IP.
+ * @param   SelCS   The interrupt gate CS.
+ * @param   RSP     The interrupt gate RSP. ~0 if no stack switch should take place. (only AMD64)
+ */
+DECLASM(void) trpmR0DispatchHostInterrupt(RTR0UINTPTR uIP, RTSEL SelCS, RTR0UINTPTR RSP);
+
+# ifndef VBOX_WITHOUT_IDT_PATCHING
 /**
  * Code used for the dispatching of interrupts in HC.
@@ -184,4 +197,6 @@
  */
 DECLASM(int) trpmR0InterruptDispatcher(void);
+# endif /* !VBOX_WITHOUT_IDT_PATCHING */
+
 #endif
 
Index: /trunk/src/VBox/VMM/VMM.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMM.cpp	(revision 396)
+++ /trunk/src/VBox/VMM/VMM.cpp	(revision 397)
@@ -496,5 +496,5 @@
                     STAM_REG(pVM, &pVM->vmm.s.StatGCRetPatchPF,             STAMTYPE_COUNTER, "/VMM/GCRet/PatchPF",             STAMUNIT_OCCURENCES, "Number of VINF_PATM_PATCH_TRAP_PF returns.");
                     STAM_REG(pVM, &pVM->vmm.s.StatGCRetPatchGP,             STAMTYPE_COUNTER, "/VMM/GCRet/PatchGP",             STAMUNIT_OCCURENCES, "Number of VINF_PATM_PATCH_TRAP_GP returns.");
-                    STAM_REG(pVM, &pVM->vmm.s.StatGCRetPatchIretIRQ,        STAMTYPE_COUNTER, "/VMM/GCRet/PatchIret",           STAMUNIT_OCCURENCES, "Number of VINF_PATM_PENDING_IRQ_AFTER_IRET returns.");                    
+                    STAM_REG(pVM, &pVM->vmm.s.StatGCRetPatchIretIRQ,        STAMTYPE_COUNTER, "/VMM/GCRet/PatchIret",           STAMUNIT_OCCURENCES, "Number of VINF_PATM_PENDING_IRQ_AFTER_IRET returns.");
                     STAM_REG(pVM, &pVM->vmm.s.StatGCRetPageOverflow,        STAMTYPE_COUNTER, "/VMM/GCRet/InvlpgOverflow",      STAMUNIT_OCCURENCES, "Number of VERR_REM_FLUSHED_PAGES_OVERFLOW returns.");
                     STAM_REG(pVM, &pVM->vmm.s.StatGCRetRescheduleREM,       STAMTYPE_COUNTER, "/VMM/GCRet/ScheduleREM",         STAMUNIT_OCCURENCES, "Number of VINF_EM_RESCHEDULE_REM returns.");
@@ -1830,5 +1830,5 @@
             rc = VERR_GENERAL_FAILURE;
 #else
-            rc = SUPCallVMMR0(pVM, VMMR0_DO_RUN_GC, NULL);
+            rc = SUPCallVMMR0(pVM, VMMR0_DO_RAW_RUN, NULL);
 #endif
         } while (rc == VINF_EM_RAW_INTERRUPT_HYPER);
@@ -1878,5 +1878,5 @@
             rc = VERR_GENERAL_FAILURE;
 #else
-            rc = SUPCallVMMR0(pVM, VMMR0_HWACC_RUN_GUEST, NULL);
+            rc = SUPCallVMMR0(pVM, VMMR0_DO_HWACC_RUN, NULL);
 #endif
         } while (rc == VINF_EM_RAW_INTERRUPT_HYPER);
@@ -1959,5 +1959,5 @@
             rc = VERR_GENERAL_FAILURE;
 #else
-            rc = SUPCallVMMR0(pVM, VMMR0_DO_RUN_GC, NULL);
+            rc = SUPCallVMMR0(pVM, VMMR0_DO_RAW_RUN, NULL);
 #endif
         } while (rc == VINF_EM_RAW_INTERRUPT_HYPER);
@@ -2013,5 +2013,5 @@
             rc = VERR_GENERAL_FAILURE;
 #else
-            rc = SUPCallVMMR0(pVM, VMMR0_DO_RUN_GC, NULL);
+            rc = SUPCallVMMR0(pVM, VMMR0_DO_RAW_RUN, NULL);
 #endif
         } while (rc == VINF_EM_RAW_INTERRUPT_HYPER);
@@ -2540,5 +2540,5 @@
     CPUMPushHyper(pVM, GCPtrEP);                /* what to call */
     CPUMSetHyperEIP(pVM, pVM->vmm.s.pfnGCCallTrampoline);
-    return SUPCallVMMR0(pVM, VMMR0_DO_RUN_GC, NULL);
+    return SUPCallVMMR0(pVM, VMMR0_DO_RAW_RUN, NULL);
 }
 
@@ -2574,5 +2574,5 @@
     CPUMPushHyper(pVM, GCPtrEP);                /* what to call */
     CPUMSetHyperEIP(pVM, pVM->vmm.s.pfnGCCallTrampoline);
-    rc = SUPCallVMMR0(pVM, VMMR0_DO_RUN_GC, NULL);
+    rc = SUPCallVMMR0(pVM, VMMR0_DO_RAW_RUN, NULL);
     bool fDump = false;
     if (rc != rcExpect)
@@ -2794,5 +2794,5 @@
         do
         {
-            rc = SUPCallVMMR0(pVM, VMMR0_DO_RUN_GC, NULL);
+            rc = SUPCallVMMR0(pVM, VMMR0_DO_RAW_RUN, NULL);
             if (VBOX_FAILURE(rc))
             {
@@ -2845,5 +2845,5 @@
 
             uint64_t TickThisStart = ASMReadTSC();
-            rc = SUPCallVMMR0(pVM, VMMR0_DO_RUN_GC, NULL);
+            rc = SUPCallVMMR0(pVM, VMMR0_DO_RAW_RUN, NULL);
             uint64_t TickThisElapsed = ASMReadTSC() - TickThisStart;
             if (VBOX_FAILURE(rc))
Index: /trunk/src/VBox/VMM/VMMR0/TRPMR0.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR0/TRPMR0.cpp	(revision 396)
+++ /trunk/src/VBox/VMM/VMMR0/TRPMR0.cpp	(revision 397)
@@ -35,4 +35,63 @@
 
 
+
+/**
+ * Dispatches an interrupt that arrived while we were in the guest context.
+ *
+ * It's assumes we're invoked with interrupts disabled.
+ * When this function returns, interrupts will be enabled.
+ *
+ * @param   pVM     The VM handle.
+ */
+TRPMR0DECL(void) TRPMR0DispatchHostInterrupt(PVM pVM)
+{
+    RTUINT uActiveVector = pVM->trpm.s.uActiveVector;
+    pVM->trpm.s.uActiveVector = ~0;
+    AssertMsgReturnVoid(uActiveVector < 256, ("uActiveVector=%#x is invalid! (More assertions to come, please enjoy!)\n", uActiveVector));
+
+    /*
+     * Get the handler pointer (16:32 ptr) / (16:48 ptr).
+     */
+    RTIDTR      Idtr;
+    ASMGetIDTR(&Idtr);
+#if HC_ARCH_BITS == 32
+    PVBOXIDTE   pIdte = &((PVBOXIDTE)Idtr.pIdt)[uActiveVector];
+#else
+    PVBOXIDTE   pIdte = &((PVBOXIDTE)Idtr.pIdt)[uActiveVector * 2];
+#endif
+    AssertMsgReturnVoid(pIdte->Gen.u1Present, ("The IDT entry (%d) is not present!\n", uActiveVector));
+    AssertMsgReturnVoid(    pIdte->Gen.u3Type1 == VBOX_IDTE_TYPE1
+                        ||  pIdte->Gen.u5Type2 == VBOX_IDTE_TYPE2_INT_32,
+                        ("The IDT entry (%d) is not 32-bit int gate! type1=%#x type2=%#x\n",
+                         uActiveVector, pIdte->Gen.u3Type1, pIdte->Gen.u5Type2));
+#if HC_ARCH_BITS == 32
+    RTFAR32   pfnHandler;
+    pfnHandler.off = (pIdte->Gen.u16OffsetHigh << 16) | pIdte->Gen.u16OffsetLow;
+    pfnHandler.sel = pIdte->Gen.u16SegSel;
+
+    const RTR0UINTREG uRSP = ~(RTR0UINTREG)0;
+
+#else /* 64-bit: */
+    RTFAR64   pfnHandler;
+    pfnHandler.off = (pIdte->Gen.u16OffsetHigh << 16) | pIdte->Gen.u16OffsetLow;
+    pfnHandler.off |= (uint64_t)(*(uint32_t *)(pIdte + 1)) << 32; //cleanup!
+    pfnHandler.sel = pIdte->Gen.u16SegSel;
+
+    RTR0UINTREG uRSP = ~(RTR0UINTREG)0;
+    if (pIdte->au32[1] & 0x7 /*IST*/)
+    {
+        /** @todo implement IST */
+    }
+
+#endif
+
+    /*
+     * Dispatch it.
+     */
+    trpmR0DispatchHostInterrupt(pfnHandler.off, pfnHandler.sel, uRSP);
+}
+
+#ifndef VBOX_WITHOUT_IDT_PATCHING
+
 /**
  * Changes the VMMR0Entry() call frame and stack used by the IDT patch code
@@ -47,10 +106,5 @@
     RTUINT uActiveVector = pVM->trpm.s.uActiveVector;
     pVM->trpm.s.uActiveVector = ~0;
-    if (uActiveVector >= 256)
-    {
-        AssertMsgFailed(("uActiveVector=%#x is invalid! (More assertions to come, please enjoy!)\n",
-                         uActiveVector));
-        return;
-    }
+    AssertMsgReturnVoid(uActiveVector < 256, ("uActiveVector=%#x is invalid! (More assertions to come, please enjoy!)\n", uActiveVector));
 
 #if HC_ARCH_BITS == 32
@@ -61,16 +115,9 @@
     ASMGetIDTR(&Idtr);
     PVBOXIDTE   pIdte = &((PVBOXIDTE)Idtr.pIdt)[uActiveVector];
-    if (!pIdte->Gen.u1Present)
-    {
-        AssertMsgFailed(("The IDT entry (%d) is not present!\n", uActiveVector));
-        return;
-    }
-    if (    pIdte->Gen.u3Type1 != VBOX_IDTE_TYPE1
-        &&  pIdte->Gen.u5Type2 != VBOX_IDTE_TYPE2_INT_32)
-    {
-        AssertMsgFailed(("The IDT entry (%d) is not 32-bit int gate! type1=%#x type2=%#x\n",
+    AssertMsgReturnVoid(pIdte->Gen.u1Present, ("The IDT entry (%d) is not present!\n", uActiveVector));
+    AssertMsgReturnVoid(    pIdte->Gen.u3Type1 == VBOX_IDTE_TYPE1
+                        &&  pIdte->Gen.u5Type2 == VBOX_IDTE_TYPE2_INT_32,
+                        ("The IDT entry (%d) is not 32-bit int gate! type1=%#x type2=%#x\n",
                          uActiveVector, pIdte->Gen.u3Type1, pIdte->Gen.u5Type2));
-        return;
-    }
 
     RTFAR32   pfnHandler;
@@ -110,16 +157,10 @@
     ASMGetIDTR(&Idtr);
     PVBOXIDTE   pIdte = &((PVBOXIDTE)Idtr.pIdt)[uActiveVector * 2];
-    if (!pIdte->Gen.u1Present)
-    {
-        AssertMsgFailed(("The IDT entry (%d) is not present!\n", uActiveVector));
-        return;
-    }
-    if (    pIdte->Gen.u3Type1 != VBOX_IDTE_TYPE1
-        &&  pIdte->Gen.u5Type2 != VBOX_IDTE_TYPE2_INT_32)
-    {
-        AssertMsgFailed(("The IDT entry (%d) is not 32-bit int gate! type1=%#x type2=%#x\n",
+
+    AssertMsgReturnVoid(pIdte->Gen.u1Present, ("The IDT entry (%d) is not present!\n", uActiveVector));
+    AssertMsgReturnVoid(    pIdte->Gen.u3Type1 == VBOX_IDTE_TYPE1
+                        &&  pIdte->Gen.u5Type2 == VBOX_IDTE_TYPE2_INT_32, /* == 64 */
+                        ("The IDT entry (%d) is not 64-bit int gate! type1=%#x type2=%#x\n",
                          uActiveVector, pIdte->Gen.u3Type1, pIdte->Gen.u5Type2));
-        return;
-    }
 
     RTFAR64   pfnHandler;
@@ -127,4 +168,9 @@
     pfnHandler.off |= (uint64_t)(*(uint32_t *)(pIdte + 1)) << 32; //cleanup!
     pfnHandler.sel = pIdte->Gen.u16SegSel;
+
+    if (pIdte->au32[1] & 0x7 /*IST*/)
+    {
+        /** @todo implement IST */
+    }
 
     /*
@@ -150,2 +196,4 @@
 //    dprintf(("Interrupt: %04x:%08x vector %d\n", pfnHandler.sel, pfnHandler.off, uActiveVector));
 }
+
+#endif /* !VBOX_WITHOUT_IDT_PATCHING */
Index: /trunk/src/VBox/VMM/VMMR0/TRPMR0A.asm
===================================================================
--- /trunk/src/VBox/VMM/VMMR0/TRPMR0A.asm	(revision 396)
+++ /trunk/src/VBox/VMM/VMMR0/TRPMR0A.asm	(revision 397)
@@ -24,7 +24,88 @@
 ;*******************************************************************************
 %include "VBox/asmdefs.mac"
+%include "VBox/x86.mac"
 
 
 BEGINCODE
+    align 16
+
+;;
+; Calls the interrupt gate as if we received an interrupt while in Ring-0.
+;
+; Returns with interrupts enabled.
+;
+; @param   uIP     x86:[ebp+8]   msc:rcx  gcc:rdi  The interrupt gate IP.
+; @param   SelCS   x86:[ebp+12]  msc:dx   gcc:si   The interrupt gate CS.
+; @param   RSP                   msc:r8   gcc:rdx  The interrupt gate RSP. ~0 if no stack switch should take place. (only AMD64)
+;DECLASM(void) trpmR0DispatchHostInterrupt(RTR0UINTPTR uIP, RTSEL SelCS, RTR0UINTPTR RSP);
+BEGINPROC trpmR0DispatchHostInterrupt
+    push    xBP
+    mov     xBP, xSP
+
+%ifdef __AMD64__
+    mov     rax, rsp
+    and     rsp, 15h                    ; align the stack. (do it unconditionally saves some jump mess)
+
+    ; switch stack?
+% ifdef ASM_CALL64_MSC
+    cmp     r8, 0ffffffffffffffffh
+    je      .no_stack_switch
+    mov     rsp, r8
+% else
+    cmp     rdx, 0ffffffffffffffffh
+    je      .no_stack_switch
+    mov     rsp, rdx
+% endif
+.no_stack_switch:
+
+    ; create the iret frame
+    push    0                           ; SS
+    push    rax                         ; RSP
+    pushfd                              ; RFLAGS
+    and     dword [rsp], ~X86_EFL_IF
+    push    cs                          ; CS
+    mov     rax, .return                ; RIP
+    push    rax
+
+    ; create the retf frame
+% ifdef ASM_CALL64_MSC
+    movzx   rdx, dx
+    push    rdx
+    push    rcx
+% else
+    movzx   rdi, di
+    push    rdi
+    push    rsi
+% endif
+
+    ; dispatch it!
+    db 048h
+    retf
+
+%else ; 32-bit:
+    mov     ecx, [ebp + 8]              ; uIP
+    movzx   edx, word [ebp + 12]        ; SelCS
+
+    ; create the iret frame
+    pushfd                              ; EFLAGS
+    and     dword [esp], ~X86_EFL_IF
+    push    cs                          ; CS
+    push    .return                     ; EIP
+
+    ; create the retf frame
+    push    edx
+    push    ecx
+
+    ; dispatch it!
+    retf
+%endif
+.return:
+
+    leave
+    ret
+ENDPROC trpmR0DispatchHostInterrupt
+
+
+%ifndef VBOX_WITHOUT_IDT_PATCHING
 
     align 16
@@ -66,2 +147,4 @@
 ENDPROC   trpmR0InterruptDispatcher
 
+%endif ; !VBOX_WITHOUT_IDT_PATCHING
+
Index: /trunk/src/VBox/VMM/VMMR0/VMMR0.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR0/VMMR0.cpp	(revision 396)
+++ /trunk/src/VBox/VMM/VMMR0/VMMR0.cpp	(revision 397)
@@ -413,5 +413,5 @@
          * These calls return whatever the GC returns.
          */
-        case VMMR0_DO_RUN_GC:
+        case VMMR0_DO_RAW_RUN:
         {
             /* Safety precaution as VMX disables the switcher. */
@@ -447,5 +447,9 @@
                 case VINF_EM_RAW_INTERRUPT:
                 case VINF_EM_RAW_INTERRUPT_HYPER:
+#ifdef VBOX_WITHOUT_IDT_PATCHING
+                    TRPMR0DispatchHostInterrupt(pVM);
+#else
                     TRPMR0SetupInterruptDispatcherFrame(pVM, (char*)&pVM - sizeof(pVM));
+#endif
                     return rc;
             }
@@ -457,5 +461,5 @@
          * Run guest code using the available hardware acceleration technology.
          */
-        case VMMR0_HWACC_RUN_GUEST:
+        case VMMR0_DO_HWACC_RUN:
         {
             int rc;
@@ -501,5 +505,5 @@
          * Setup the hardware accelerated raw-mode session.
          */
-        case VMMR0_HWACC_SETUP_VM:
+        case VMMR0_DO_HWACC_SETUP_VM:
             return HWACCMR0SetupVMX(pVM);
 
@@ -590,32 +594,17 @@
 #endif /* !__L4__ */
 
-#ifdef DEBUG
-        /*
-         * For testing purposes only.
-         */
-        case 0xdeadbeef:
-        {
-            LogCom(("VMMR0Entry: !debug testing! 0xdeadbeef!\n"));
-            #if 0
-            void *pv;
-            void *pvPhys;
-
-            /* alloc cont memory */
-            int rc = SUPR0ContAlloc(pVM->pSession, 0x1fff, &pv, &pvPhys);
-            LogCom(("VMMR0Entry: ContAlloc: rc=%d pv=%p pvPhys=%p\n", rc, pv, pvPhys));
-            if (!VBOX_SUCCESS(rc))
-               return rc;
-            /* touch */
-            ((char*)pv)[0x1000] = ((char*)pv)[0] = 'f';
-            /* free */
-            rc = SUPR0ContFree(pVM->pSession, pv);
-            LogCom(("VMMR0Entry: ContFree: rc=%d\n", rc));
-            if (!VBOX_SUCCESS(rc))
-                return rc;
-            #endif
-            /* successful return - consistent with release builds. */
-            return VERR_NOT_SUPPORTED;
-        }
-#endif
+        /*
+         * For profiling.
+         */
+        case VMMR0_DO_NOP:
+            return VINF_SUCCESS;
+
+        /*
+         * For testing Ring-0 APIs invoked in this environment.
+         */
+        case VMMR0_DO_TESTS:
+            /** @todo make new test */
+            return VINF_SUCCESS;
+
 
         default:
