Index: trunk/src/VBox/VMM/VMMAll/HMAll.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMAll/HMAll.cpp	(revision 65989)
+++ trunk/src/VBox/VMM/VMMAll/HMAll.cpp	(revision 66000)
@@ -558,17 +558,4 @@
 
 
-
-/**
- * SVM nested-guest \#VMEXIT handler.
- * 
- * @param   pVCpu       The cross context virtual CPU structure. 
- * @param   uExitCode   The exit reason.
- */
-VMM_INT_DECL(void) HMNstGstSvmVmExit(PVMCPU pVCpu, uint64_t uExitCode)
-{
-    RT_NOREF2(pVCpu, uExitCode);
-}
-
-
 /**
  * VMX nested-guest VM-exit handler.
Index: trunk/src/VBox/VMM/VMMAll/HMSVMAll.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMAll/HMSVMAll.cpp	(revision 65989)
+++ trunk/src/VBox/VMM/VMMAll/HMSVMAll.cpp	(revision 66000)
@@ -126,8 +126,7 @@
 /**
  * Performs the operations necessary that are part of the vmmcall instruction
- * execution for AMD-V.
+ * execution in the guest.
  *
  * @returns Strict VBox status code (i.e. informational status codes too).
- *
  * @retval  VINF_SUCCESS on successful handling, no \#UD needs to be thrown,
  *          update RIP and eflags.RF depending on @a pfUpdatedRipAndRF and
@@ -173,2 +172,65 @@
 }
 
+
+/**
+ * Performs the operations necessary that are part of the vmrun instruction
+ * execution in the guest.
+ *
+ * @returns Strict VBox status code (i.e. informational status codes too).
+ *
+ * @param   pVCpu               The cross context virtual CPU structure.
+ * @param   pCtx                Pointer to the guest-CPU context.
+ */
+VMM_INT_DECL(VBOXSTRICTRC) HMSvmVmrun(PVMCPU pVCpu, PCPUMCTX pCtx)
+{
+    RT_NOREF2(pVCpu, pCtx);
+
+    return VERR_NOT_IMPLEMENTED;
+}
+
+
+/**
+ * SVM nested-guest \#VMEXIT handler.
+ *
+ * @returns Strict VBox status code.
+ * @param   pVCpu       The cross context virtual CPU structure.
+ * @param   pCtx        The guest-CPU context.
+ * @param   uExitCode   The exit reason.
+ * @param   uExitInfo1  The exit info. 1 field.
+ * @param   uExitInfo1  The exit info. 2 field.
+ */
+VMM_INT_DECL(VBOXSTRICTRC) HMSvmNstGstVmExit(PVMCPU pVCpu, PCPUMCTX pCtx, int64_t iExitCode, uint64_t uExitInfo1,
+                                             uint64_t uExitInfo2)
+{
+    if (   CPUMIsGuestInNestedHwVirtMode(pCtx)
+        || iExitCode == SVM_EXIT_INVALID)
+    {
+        RT_NOREF(pVCpu);
+
+        pCtx->hwvirt.svm.fGif = 0;
+
+        /** @todo implement #VMEXIT. */
+
+        return VINF_SUCCESS;
+    }
+    else
+        Log(("HMNstGstSvmVmExit: Not in SVM guest mode! uExitCode=%RI64 uExitInfo1=%RU64 uExitInfo2=%RU64\n", iExitCode,
+             uExitInfo1, uExitInfo2));
+
+    return VERR_SVM_IPE_5;
+}
+
+
+/**
+ * Peforms the functions of a VMRUN instruction.
+ *
+ * @returns Strict VBox status code.
+ * @param   pVCpu       The cross context virtual CPU structure.
+ * @param   pCtx        The guest-CPU context.
+ */
+VMM_INT_DECL(VBOXSTRICTRC) HMSvmVmRun(PVMCPU pVCpu, PCPUMCTX pCtx)
+{
+    RT_NOREF2(pVCpu, pCtx);
+    return VERR_NOT_IMPLEMENTED;
+}
+
Index: trunk/src/VBox/VMM/VMMAll/IEMAll.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMAll/IEMAll.cpp	(revision 65989)
+++ trunk/src/VBox/VMM/VMMAll/IEMAll.cpp	(revision 66000)
@@ -14954,4 +14954,17 @@
 #ifdef VBOX_WITH_NESTED_HWVIRT
 /**
+ * Checks if IEM is in the process of delivering an event (interrupt or
+ * exception).
+ *
+ * @returns true if it's raising an interrupt or exception, false otherwise.
+ * @param   pVCpu       The cross context virtual CPU structure.
+ */
+VMM_INT_DECL(bool) IEMIsRaisingIntOrXcpt(PVMCPU pVCpu)
+{
+    return pVCpu->iem.s.cXcptRecursions > 0;
+}
+
+
+/**
  * Interface for HM and EM to emulate the STGI instruction.
  *  
Index: trunk/src/VBox/VMM/VMMAll/IEMAllCImpl.cpp.h
===================================================================
--- trunk/src/VBox/VMM/VMMAll/IEMAllCImpl.cpp.h	(revision 65989)
+++ trunk/src/VBox/VMM/VMMAll/IEMAllCImpl.cpp.h	(revision 66000)
@@ -5877,15 +5877,55 @@
 #ifdef VBOX_WITH_NESTED_HWVIRT
 /**
+ * Implements 'VMRUN'.
+ */
+IEM_CIMPL_DEF_0(iemCImpl_vmrun)
+{
+    PCPUMCTX pCtx = IEM_GET_CTX(pVCpu);
+    IEM_SVM_INSTR_COMMON_CHECKS(pVCpu, vmload);
+
+    RTGCPHYS const GCPhysVmcb = pVCpu->iem.s.enmEffAddrMode == IEMMODE_64BIT ? pCtx->rax : pCtx->eax;
+    if (   (GCPhysVmcb & X86_PAGE_4K_OFFSET_MASK)
+        || !PGMPhysIsGCPhysNormal(pVCpu->CTX_SUFF(pVM), GCPhysVmcb))
+    {
+        Log(("vmrun: VMCB physaddr (%#RGp) not valid -> #GP(0)\n", GCPhysVmcb));
+        return iemRaiseGeneralProtectionFault0(pVCpu);
+    }
+
+#ifndef IN_RC
+    if (IEM_IS_SVM_CTRL_INTERCEPT_SET(pVCpu, SVM_CTRL_INTERCEPT_VMRUN))
+    {
+        Log(("vmrun: Guest intercept -> VMexit\n"));
+        return HMSvmNstGstVmExit(pVCpu, pCtx, SVM_EXIT_VMMCALL, 0 /* uExitInfo1 */, 0 /* uExitInfo2 */);
+    }
+#endif
+
+    /** @todo think - I probably need to map both the HSAVE area page and the
+     *        guest VMCB via iemMemPageMap here and do the copying? */
+    pCtx->hwvirt.svm.GCPhysNstGstVmcb = GCPhysVmcb;
+    void *pvVmcb;
+    PGMPAGEMAPLOCK PgLockVmcb;
+    VBOXSTRICTRC rcStrict = iemMemPageMap(pVCpu, GCPhysVmcb, IEM_ACCESS_DATA_RW, &pvVmcb, &PgLockVmcb);
+    if (rcStrict == VINF_SUCCESS)
+        return HMSvmVmrun(pVCpu, pCtx);
+    RT_NOREF(cbInstr);
+    return rcStrict;
+}
+
+
+/**
  * Implements 'VMMCALL'.
  */
 IEM_CIMPL_DEF_0(iemCImpl_vmmcall)
 {
-    /*
-     * We do not check for presence of SVM/AMD-V here as the KVM GIM provider
-     * might patch in an invalid vmmcall instruction with an Intel vmcall
-     * instruction.
-     */
+    PCPUMCTX pCtx = IEM_GET_CTX(pVCpu);
+#ifndef IN_RC
+    if (IEM_IS_SVM_CTRL_INTERCEPT_SET(pVCpu, SVM_CTRL_INTERCEPT_VMMCALL))
+    {
+        Log(("vmrun: Guest intercept -> VMexit\n"));
+        return HMSvmNstGstVmExit(pVCpu, pCtx, SVM_EXIT_VMMCALL, 0 /* uExitInfo1 */, 0 /* uExitInfo2 */);
+    }
+#endif
+
     bool fUpdatedRipAndRF;
-    PCPUMCTX pCtx = IEM_GET_CTX(pVCpu);
     VBOXSTRICTRC rcStrict = HMSvmVmmcall(pVCpu, pCtx, &fUpdatedRipAndRF);
     if (RT_SUCCESS(rcStrict))
@@ -5911,13 +5951,13 @@
     {
         Log(("vmload: Guest intercept -> VMexit\n"));
-        HMNstGstSvmVmExit(pVCpu, SVM_EXIT_VMLOAD);
-        return VINF_EM_RESCHEDULE;
+        return HMSvmNstGstVmExit(pVCpu, pCtx, SVM_EXIT_VMLOAD, 0 /* uExitInfo1 */, 0 /* uExitInfo2 */);
     }
 #endif
 
     RTGCPHYS const GCPhysVmcb = pVCpu->iem.s.enmEffAddrMode == IEMMODE_64BIT ? pCtx->rax : pCtx->eax;
-    if (GCPhysVmcb & X86_PAGE_4K_OFFSET_MASK)
-    {
-        Log(("vmload: VMCB physaddr (%#RGp) not 4K aligned -> #GP(0)\n", GCPhysVmcb));
+    if (   (GCPhysVmcb & X86_PAGE_4K_OFFSET_MASK)
+        || !PGMPhysIsGCPhysNormal(pVCpu->CTX_SUFF(pVM), GCPhysVmcb))
+    {
+        Log(("vmload: VMCB physaddr (%#RGp) not valid -> #GP(0)\n", GCPhysVmcb));
         return iemRaiseGeneralProtectionFault0(pVCpu);
     }
@@ -5962,13 +6002,13 @@
     {
         Log(("vmsave: Guest intercept -> VMexit\n"));
-        HMNstGstSvmVmExit(pVCpu, SVM_EXIT_VMSAVE);
-        return VINF_EM_RESCHEDULE;
+        return HMSvmNstGstVmExit(pVCpu, pCtx, SVM_EXIT_VMSAVE, 0 /* uExitInfo1 */, 0 /* uExitInfo2 */);
     }
 #endif
 
     RTGCPHYS const GCPhysVmcb = pVCpu->iem.s.enmEffAddrMode == IEMMODE_64BIT ? pCtx->rax : pCtx->eax;
-    if (GCPhysVmcb & X86_PAGE_4K_OFFSET_MASK)
-    {
-        Log(("vmsave: VMCB physaddr (%#RGp) not 4K aligned -> #GP(0)\n", GCPhysVmcb));
+    if (   (GCPhysVmcb & X86_PAGE_4K_OFFSET_MASK)
+        || !PGMPhysIsGCPhysNormal(pVCpu->CTX_SUFF(pVM), GCPhysVmcb))
+    {
+        Log(("vmsave: VMCB physaddr (%#RGp) not valid -> #GP(0)\n", GCPhysVmcb));
         return iemRaiseGeneralProtectionFault0(pVCpu);
     }
@@ -6013,6 +6053,5 @@
     {
         Log(("clgi: Guest intercept -> VMexit\n"));
-        HMNstGstSvmVmExit(pVCpu, SVM_EXIT_CLGI);
-        return VINF_EM_RESCHEDULE;
+        return HMSvmNstGstVmExit(pVCpu, pCtx, SVM_EXIT_CLGI, 0 /* uExitInfo1 */, 0 /* uExitInfo2 */);
     }
 #endif
@@ -6035,6 +6074,5 @@
     {
         Log2(("stgi: Guest intercept -> VMexit\n"));
-        HMNstGstSvmVmExit(pVCpu, SVM_EXIT_STGI);
-        return VINF_EM_RESCHEDULE;
+        return HMSvmNstGstVmExit(pVCpu, pCtx, SVM_EXIT_STGI, 0 /* uExitInfo1 */, 0 /* uExitInfo2 */);
     }
 #endif
@@ -6057,6 +6095,5 @@
     {
         Log2(("invlpga: Guest intercept -> VMexit\n"));
-        HMNstGstSvmVmExit(pVCpu, SVM_EXIT_INVLPGA);
-        return VINF_EM_RESCHEDULE;
+        return HMSvmNstGstVmExit(pVCpu, pCtx, SVM_EXIT_INVLPGA, 0 /* uExitInfo1 */, 0 /* uExitInfo2 */);
     }
 #endif
Index: trunk/src/VBox/VMM/VMMAll/IEMAllInstructionsTwoByte0f.cpp.h
===================================================================
--- trunk/src/VBox/VMM/VMMAll/IEMAllInstructionsTwoByte0f.cpp.h	(revision 65989)
+++ trunk/src/VBox/VMM/VMMAll/IEMAllInstructionsTwoByte0f.cpp.h	(revision 66000)
@@ -439,58 +439,64 @@
 
 
+#ifdef VBOX_WITH_NESTED_HWVIRT
+/** Opcode 0x0f 0x01 0xd8. */
+FNIEMOP_DEF(iemOp_Grp7_Amd_vmrun)
+{
+    IEMOP_MNEMONIC(vmrun, "vmrun");
+    return IEM_MC_DEFER_TO_CIMPL_0(iemCImpl_vmrun);
+}
+
+/** Opcode 0x0f 0x01 0xd9. */
+FNIEMOP_DEF(iemOp_Grp7_Amd_vmmcall)
+{
+    IEMOP_MNEMONIC(vmmcall, "vmmcall");
+    return IEM_MC_DEFER_TO_CIMPL_0(iemCImpl_vmmcall);
+}
+
+
+/** Opcode 0x0f 0x01 0xda. */
+FNIEMOP_DEF(iemOp_Grp7_Amd_vmload)
+{
+    IEMOP_MNEMONIC(vmload, "vmload");
+    return IEM_MC_DEFER_TO_CIMPL_0(iemCImpl_vmload);
+}
+
+
+/** Opcode 0x0f 0x01 0xdb. */
+FNIEMOP_DEF(iemOp_Grp7_Amd_vmsave)
+{
+    IEMOP_MNEMONIC(vmsave, "vmsave");
+    return IEM_MC_DEFER_TO_CIMPL_0(iemCImpl_vmsave);
+}
+
+
+/** Opcode 0x0f 0x01 0xdc. */
+FNIEMOP_DEF(iemOp_Grp7_Amd_stgi)
+{
+    IEMOP_MNEMONIC(stgi, "stgi");
+    return IEM_MC_DEFER_TO_CIMPL_0(iemCImpl_stgi);
+}
+
+
+/** Opcode 0x0f 0x01 0xdd. */
+FNIEMOP_DEF(iemOp_Grp7_Amd_clgi)
+{
+    IEMOP_MNEMONIC(clgi, "clgi");
+    return IEM_MC_DEFER_TO_CIMPL_0(iemCImpl_clgi);
+}
+
+
+/** Opcode 0x0f 0x01 0xdf. */
+FNIEMOP_DEF(iemOp_Grp7_Amd_invlpga)
+{
+    IEMOP_MNEMONIC(invlpga, "invlpga");
+    return IEM_MC_DEFER_TO_CIMPL_0(iemCImpl_invlpga);
+}
+#else
 /** Opcode 0x0f 0x01 0xd8. */
 FNIEMOP_UD_STUB(iemOp_Grp7_Amd_vmrun);
 
-#ifdef VBOX_WITH_NESTED_HWVIRT
-/** Opcode 0x0f 0x01 0xd9. */
-FNIEMOP_DEF(iemOp_Grp7_Amd_vmmcall)
-{
-    IEMOP_MNEMONIC(vmmcall, "vmmcall");
-    return IEM_MC_DEFER_TO_CIMPL_0(iemCImpl_vmmcall);
-}
-
-
-/** Opcode 0x0f 0x01 0xda. */
-FNIEMOP_DEF(iemOp_Grp7_Amd_vmload)
-{
-    IEMOP_MNEMONIC(vmload, "vmload");
-    return IEM_MC_DEFER_TO_CIMPL_0(iemCImpl_vmload);
-}
-
-
-/** Opcode 0x0f 0x01 0xdb. */
-FNIEMOP_DEF(iemOp_Grp7_Amd_vmsave)
-{
-    IEMOP_MNEMONIC(vmsave, "vmsave");
-    return IEM_MC_DEFER_TO_CIMPL_0(iemCImpl_vmsave);
-}
-
-
-/** Opcode 0x0f 0x01 0xdc. */
-FNIEMOP_DEF(iemOp_Grp7_Amd_stgi)
-{
-    IEMOP_MNEMONIC(stgi, "stgi");
-    return IEM_MC_DEFER_TO_CIMPL_0(iemCImpl_stgi);
-}
-
-
-/** Opcode 0x0f 0x01 0xdd. */
-FNIEMOP_DEF(iemOp_Grp7_Amd_clgi)
-{
-    IEMOP_MNEMONIC(clgi, "clgi");
-    return IEM_MC_DEFER_TO_CIMPL_0(iemCImpl_clgi);
-}
-
-
-/** Opcode 0x0f 0x01 0xdf. */
-FNIEMOP_DEF(iemOp_Grp7_Amd_invlpga)
-{
-    IEMOP_MNEMONIC(invlpga, "invlpga");
-    return IEM_MC_DEFER_TO_CIMPL_0(iemCImpl_invlpga);
-}
-#else
 /** Opcode 0x0f 0x01 0xd9. */
 FNIEMOP_UD_STUB(iemOp_Grp7_Amd_vmmcall);
-
 /** Opcode 0x0f 0x01 0xda. */
 FNIEMOP_UD_STUB(iemOp_Grp7_Amd_vmload);
Index: trunk/src/VBox/VMM/include/CPUMInternal.mac
===================================================================
--- trunk/src/VBox/VMM/include/CPUMInternal.mac	(revision 65989)
+++ trunk/src/VBox/VMM/include/CPUMInternal.mac	(revision 66000)
@@ -239,4 +239,6 @@
     .Guest.hwvirt.svm.u16InterceptWrDRx   resw    1
     .Guest.hwvirt.svm.fGif                resb    1
+    .Guest.hwvirt.svm.abPadding           resb    3
+    .Guest.hwvirt.svm.GCPhysNstGstVmcb    resq    1
     alignb 64
 
@@ -510,4 +512,6 @@
     .Hyper.hwvirt.svm.u16InterceptWrDRx   resw    1
     .Hyper.hwvirt.svm.fGif                resb    1
+    .Hyper.hwvirt.svm.abPadding           resb    3
+    .Hyper.hwvirt.svm.GCPhysNstGstVmcb    resq    1
     alignb 64
 
