Index: /trunk/src/VBox/VMM/VMMR0/HMSVMR0.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR0/HMSVMR0.cpp	(revision 68261)
+++ /trunk/src/VBox/VMM/VMMR0/HMSVMR0.cpp	(revision 68262)
@@ -4165,9 +4165,14 @@
 
     /* Re-check the nested-guest condition here as we may be transitioning from the normal
-       execution loop into the nested-guest. */
+       execution loop into the nested-guest, hence this is not placed in the 'else' part above. */
     if (rc == VINF_SVM_VMRUN)
+    {
         rc = hmR0SvmRunGuestCodeNested(pVM, pVCpu, pCtx, &cLoops);
+        if (rc == VINF_SVM_VMEXIT)
+            rc = VINF_SUCCESS;
+    }
 #endif
 
+    /* Fixup error codes. */
     if (rc == VERR_EM_INTERPRETER)
         rc = VINF_EM_RAW_EMULATE_INSTR;
@@ -4183,4 +4188,25 @@
 
 #ifdef VBOX_WITH_NESTED_HWVIRT
+/**
+ * Determines whether an IOIO intercept is active for the nested-guest or not.
+ *
+ * @param   pvIoBitmap      Pointer to the nested-guest IO bitmap.
+ * @param   pIoExitInfo     Pointer to the SVMIOIOEXITINFO.
+ */
+static bool hmR0SvmIsIoInterceptActive(void *pvIoBitmap, PSVMIOIOEXITINFO pIoExitInfo)
+{
+    const uint16_t    u16Port       = pIoExitInfo->n.u16Port;
+    const SVMIOIOTYPE enmIoType     = (SVMIOIOTYPE)pIoExitInfo->n.u1Type;
+    const uint8_t     cbReg         = (pIoExitInfo->u >> SVM_IOIO_OP_SIZE_SHIFT) & 7;
+    const uint8_t     cAddrSizeBits = (pIoExitInfo->u >> SVM_IOIO_ADDR_SIZE_SHIFT) << 4;
+    const uint8_t     iEffSeg       = pIoExitInfo->n.u3SEG;
+    const bool        fRep          = pIoExitInfo->n.u1REP;
+    const bool        fStrIo        = pIoExitInfo->n.u1STR;
+
+    return HMSvmIsIOInterceptActive(pvIoBitmap, u16Port, enmIoType, cbReg, cAddrSizeBits, iEffSeg, fRep, fStrIo,
+                                    NULL /* pIoExitInfo */);
+}
+
+
 /**
  * Handles a nested-guest \#VMEXIT (for all EXITCODE values except
@@ -4217,11 +4243,6 @@
                 void *pvIoBitmap = pCtx->hwvirt.svm.CTX_SUFF(pvIoBitmap);
                 SVMIOIOEXITINFO IoExitInfo;
-                IoExitInfo.u = (uint32_t)pVmcbNstGst->ctrl.u64ExitInfo1;
-                bool const fIntercept = HMSvmIsIOInterceptActive(pvIoBitmap, IoExitInfo.n.u16Port,
-                                                                 (SVMIOIOTYPE)IoExitInfo.n.u1Type,
-                                                                 (IoExitInfo.u >> SVM_IOIO_OP_SIZE_SHIFT) & 7,
-                                                                 (IoExitInfo.u >> SVM_IOIO_ADDR_SIZE_SHIFT) << 4,
-                                                                 IoExitInfo.n.u3SEG, IoExitInfo.n.u1REP, IoExitInfo.n.u1STR,
-                                                                 NULL /* pIoExitInfo */);
+                IoExitInfo.u = pVmcbNstGst->ctrl.u64ExitInfo1;
+                bool const fIntercept = hmR0SvmIsIoInterceptActive(pvIoBitmap, &IoExitInfo);
                 if (fIntercept)
                     return hmR0SvmExecVmexit(pVCpu, pCtx);
@@ -5404,4 +5425,27 @@
 
 /**
+ * Performs an SVM world-switch (VMRUN, \#VMEXIT) updating PGM and HM internals.
+ *
+ * @returns VBox status code.
+ * @param   pVCpu       The cross context virtual CPU structure.
+ * @param   pCtx        The guest-CPU context.
+ */
+static int hmR0SvmNstGstWorldSwitch(PVMCPU pVCpu, PCPUMCTX pCtx)
+{
+    /** @todo What about informing PGM about CR0.WP? */
+    PGMFlushTLB(pVCpu, pCtx->cr3, true /* fGlobal */);
+
+    /* Inform CPUM (recompiler), can later be removed. */
+    CPUMSetChangedFlags(pVCpu, CPUM_CHANGED_ALL);
+
+    /*
+     * Inform PGM about paging mode changes.
+     * We include X86_CR0_PE because PGM doesn't handle paged-real mode yet.
+     */
+    return PGMChangeMode(pVCpu, pCtx->cr0 | X86_CR0_PE, pCtx->cr4, pCtx->msrEFER);
+}
+
+
+/**
  * Performs a \#VMEXIT that happens during VMRUN emulation in hmR0SvmExecVmrun.
  *
@@ -5448,10 +5492,14 @@
      * Clear our cache of the nested-guest VMCB controls.
      */
-    PSVMVMCBCTRL pVmcbCtrl = &pVmcbNstGst->ctrl;
-    memset(pVmcbCtrl, 0, sizeof(*pVmcbCtrl));
+    PSVMVMCBCTRL pVmcbNstGstCtrl = &pVmcbNstGst->ctrl;
+    memset(pVmcbNstGstCtrl, 0, sizeof(*pVmcbNstGstCtrl));
     Assert(!CPUMIsGuestInSvmNestedHwVirtMode(pCtx));
 
     if (RT_SUCCESS(rc))
-        return VINF_SVM_VMEXIT;
+    {
+        rc = hmR0SvmNstGstWorldSwitch(pVCpu, pCtx);
+        if (rc == VINF_SUCCESS)
+            rc = VINF_SVM_VMEXIT;
+    }
 
     Log(("hmR0SvmExecVmexit: Failed to write guest-VMCB at %#RGp\n", GCPhysVmcb));
@@ -5732,13 +5780,5 @@
         pCtx->hwvirt.svm.fGif = 1;
 
-        /*
-         * Inform PGM about paging mode changes.
-         * We include X86_CR0_PE because PGM doesn't handle paged-real mode yet.
-         */
-        /** @todo What about informing PGM about CR0.WP? */
-        PGMFlushTLB(pVCpu, pCtx->cr3, true /* fGlobal */);
-
-        int rc = PGMChangeMode(pVCpu, pVmcbNstGstState->u64CR0 | X86_CR0_PE, pVmcbNstGstState->u64CR4, pCtx->msrEFER);
-        return rc;
+        return hmR0SvmNstGstWorldSwitch(pVCpu, pCtx);
     }
 
