Index: /trunk/include/VBox/vmm/hm_svm.h
===================================================================
--- /trunk/include/VBox/vmm/hm_svm.h	(revision 68360)
+++ /trunk/include/VBox/vmm/hm_svm.h	(revision 68361)
@@ -968,4 +968,5 @@
  *  operation during execution of the nested-guest, restored on \#VMEXIT.
  */
+#pragma pack(1)
 typedef struct SVMNESTEDVMCBCACHE
 {
@@ -982,4 +983,7 @@
     /** Cache of exception intercepts. */
     uint32_t            u32InterceptXcpt;
+    /** Alignment. */
+    uint32_t            u32Padding0;
+
     /** Cache of control intercepts. */
     uint64_t            u64InterceptCtrl;
@@ -990,4 +994,6 @@
     /** Cache of the VMCB clean bits. */
     uint64_t            u64VmcbCleanBits;
+    /** Cache of the TLB control. */
+    SVMTLBCTRL          TLBCtrl;
     /** Cache of V_INTR_MASKING bit. */
     bool                fVIntrMasking;
@@ -1003,6 +1009,9 @@
      *  processing. */
     bool                fExitCodeAndInfoUpdated;
+    /** Alignment. */
+    bool                afPadding0[4];
     /** @} */
 } SVMNESTEDVMCBCACHE;
+#pragma pack()
 /** Pointer to the SVMNESTEDVMCBCACHE structure. */
 typedef SVMNESTEDVMCBCACHE *PSVMNESTEDVMCBCACHE;
@@ -1010,4 +1019,6 @@
 typedef const SVMNESTEDVMCBCACHE *PCSVMNESTEDVMCBCACHE;
 /** @} */
+AssertCompileMemberAlignment(SVMNESTEDVMCBCACHE, fVIntrMasking, 8);
+AssertCompileSizeAlignment(SVMNESTEDVMCBCACHE, 8);
 
 #ifdef IN_RING0
Index: /trunk/src/VBox/VMM/VMMAll/HMSVMAll.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMAll/HMSVMAll.cpp	(revision 68360)
+++ /trunk/src/VBox/VMM/VMMAll/HMSVMAll.cpp	(revision 68361)
@@ -361,4 +361,5 @@
         pVmcbCtrl->u64MSRPMPhysAddr         = pNstGstVmcbCache->u64MSRPMPhysAddr;
         pVmcbCtrl->IntCtrl.n.u1VIntrMasking = pNstGstVmcbCache->fVIntrMasking;
+        pVmcbCtrl->TLBCtrl                  = pNstGstVmcbCache->TLBCtrl;
         pNstGstVmcbCache->fValid = false;
     }
Index: /trunk/src/VBox/VMM/VMMR0/HMSVMR0.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR0/HMSVMR0.cpp	(revision 68360)
+++ /trunk/src/VBox/VMM/VMMR0/HMSVMR0.cpp	(revision 68361)
@@ -409,5 +409,5 @@
 
     /*
-     * Ensure each VCPU scheduled on this CPU gets a new VPID on resume. See @bugref{6255}.
+     * Ensure each VCPU scheduled on this CPU gets a new ASID on resume. See @bugref{6255}.
      */
     ++pCpu->cTlbFlushes;
@@ -877,10 +877,11 @@
  * Flushes the appropriate tagged-TLB entries.
  *
- * @param    pVCpu      The cross context virtual CPU structure.
- */
-static void hmR0SvmFlushTaggedTlb(PVMCPU pVCpu)
-{
-    PVM pVM              = pVCpu->CTX_SUFF(pVM);
-    PSVMVMCB pVmcb       = pVCpu->hm.s.svm.pVmcb;
+ * @param   pVCpu   The cross context virtual CPU structure.
+ * @param   pCtx    Pointer to the guest-CPU or nested-guest-CPU context.
+ * @param   pVmcb   Pointer to the VM control block.
+ */
+static void hmR0SvmFlushTaggedTlb(PVMCPU pVCpu, PCPUMCTX pCtx, PSVMVMCB pVmcb)
+{
+    PVM pVM               = pVCpu->CTX_SUFF(pVM);
     PHMGLOBALCPUINFO pCpu = hmR0GetCurrentCpu();
 
@@ -911,5 +912,21 @@
     }
 
+#ifdef VBOX_WITH_NESTED_HWVIRT
+    /*
+     * Only if the nested hypervisor says it does not need to flush anything in the TLB,
+     * can we possibly apply it on the host. Otherwise, the nested-guest TLB flush setting
+     * should be used and then the host settings be added on top.
+     */
+    if (CPUMIsGuestInSvmNestedHwVirtMode(pCtx))
+    {
+        PCSVMNESTEDVMCBCACHE pVmcbNstGstCache = &pVCpu->hm.s.svm.NstGstVmcbCache;
+        if (pVmcbNstGstCache->TLBCtrl.n.u8TLBFlush == SVM_TLB_FLUSH_NOTHING)
+            pVmcb->ctrl.TLBCtrl.n.u8TLBFlush = SVM_TLB_FLUSH_NOTHING;
+        else
+            pVmcb->ctrl.TLBCtrl.n.u8TLBFlush = pVmcbNstGstCache->TLBCtrl.n.u8TLBFlush;
+    }
+#else
     pVmcb->ctrl.TLBCtrl.n.u8TLBFlush = SVM_TLB_FLUSH_NOTHING;
+#endif
 
     if (pVM->hm.s.svm.fAlwaysFlushTLB)
@@ -941,7 +958,7 @@
             if (pCpu->uCurrentAsid >= pVM->hm.s.uMaxAsid)
             {
-                pCpu->uCurrentAsid        = 1;      /* Wraparound at 1; host uses 0 */
-                pCpu->cTlbFlushes++;                /* All VCPUs that run on this host CPU must use a new VPID. */
-                fHitASIDLimit             = true;
+                pCpu->uCurrentAsid = 1;      /* Wraparound at 1; host uses 0 */
+                pCpu->cTlbFlushes++;         /* All VCPUs that run on this host CPU must use a new ASID. */
+                fHitASIDLimit      = true;
 
                 if (pVM->hm.s.svm.u32Features & X86_CPUID_SVM_FEATURE_EDX_FLUSH_BY_ASID)
@@ -990,4 +1007,8 @@
         pVmcb->ctrl.u64VmcbCleanBits &= ~HMSVM_VMCB_CLEAN_ASID;
     }
+
+#ifdef VBOX_WITH_NESTED_HWVIRT
+    Assert(pVmcb->ctrl.TLBCtrl.n.u8TLBFlush != SVM_TLB_FLUSH_NOTHING);
+#endif
 
     AssertMsg(pVCpu->hm.s.idLastCpu == pCpu->idCpu,
@@ -2015,4 +2036,5 @@
     pNstGstVmcbCache->u64VmcbCleanBits  = pVmcbNstGstCtrl->u64VmcbCleanBits;
     pNstGstVmcbCache->fVIntrMasking     = pVmcbNstGstCtrl->IntCtrl.n.u1VIntrMasking;
+    pNstGstVmcbCache->TLBCtrl           = pVmcbNstGstCtrl->TLBCtrl;
     pNstGstVmcbCache->fValid            = true;
 }
@@ -3129,23 +3151,23 @@
     Log4Func(("\n"));
 
-    bool const fIntShadow = hmR0SvmIsIntrShadowActive(pVCpu, pCtx);
-    bool const fBlockInt  = !(pCtx->eflags.u32 & X86_EFL_IF);
-    bool const fBlockNmi  = VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_BLOCK_NMIS);
 #ifdef VBOX_WITH_NESTED_HWVIRT
-    bool const fGlobalIF  = pCtx->hwvirt.svm.fGif
+    bool const fGif       = pCtx->hwvirt.svm.fGif;
 #else
-    bool const fGlobalIF  = true;
+    bool const fGif       = true;
 #endif
-    PSVMVMCB pVmcb        = pVCpu->hm.s.svm.pVmcb;
-
-    SVMEVENT Event;
-    Event.u = 0;
-
-    /*
-     * If the global interrupt flag (GIF) isn't set, even NMIs are blocked.
-     * Only relevant when SVM capability is exposed to the guest.
-     */
-    if (fGlobalIF)
-    {
+    /*
+     * If the global interrupt flag (GIF) isn't set, even NMIs and other events are blocked.
+     * See AMD spec. Table 15-10. "Effect of the GIF on Interrupt Handling".
+     */
+    if (fGif)
+    {
+        bool const fIntShadow = hmR0SvmIsIntrShadowActive(pVCpu, pCtx);
+        bool const fBlockInt  = !(pCtx->eflags.u32 & X86_EFL_IF);
+        bool const fBlockNmi  = VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_BLOCK_NMIS);
+        PSVMVMCB pVmcb        = pVCpu->hm.s.svm.pVmcb;
+
+        SVMEVENT Event;
+        Event.u = 0;
+
         /** @todo SMI. SMIs take priority over NMIs. */
         if (VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_INTERRUPT_NMI))   /* NMI. NMIs take priority over regular interrupts. */
@@ -3211,6 +3233,5 @@
 
 /**
- * Injects any pending events into the guest if the guest is in a state to
- * receive them.
+ * Injects any pending events into the guest or nested-guest.
  *
  * @param   pVCpu       The cross context virtual CPU structure.
@@ -3224,5 +3245,13 @@
 
     bool const fIntShadow = hmR0SvmIsIntrShadowActive(pVCpu, pCtx);
+
+    /*
+     * When executing the nested-guest, we avoid assertions on whether the
+     * event injection is valid purely based on EFLAGS, as V_INTR_MASKING
+     * affects the interpretation of interruptibility (see CPUMCanSvmNstGstTakePhysIntr).
+     */
+#ifndef VBOX_WITH_NESTED_HWVIRT
     bool const fBlockInt  = !(pCtx->eflags.u32 & X86_EFL_IF);
+#endif
 
     if (pVCpu->hm.s.Event.fPending)                                /* First, inject any pending HM events. */
@@ -3230,6 +3259,7 @@
         SVMEVENT Event;
         Event.u = pVCpu->hm.s.Event.u64IntInfo;
-
         Assert(Event.n.u1Valid);
+
+#ifndef VBOX_WITH_NESTED_HWVIRT
         if (Event.n.u3Type == SVM_EVENT_EXTERNAL_IRQ)
         {
@@ -3240,4 +3270,5 @@
             Assert(!fIntShadow);
         NOREF(fBlockInt);
+#endif
 
         Log4(("Injecting pending HM event\n"));
@@ -3253,5 +3284,10 @@
     }
 
-    /* Update the guest interrupt shadow in the VMCB. */
+    /*
+     * Update the guest interrupt shadow in the guest or nested-guest VMCB.
+     *
+     * For nested-guests: We need to update it too for the scenario where IEM executes
+     * the nested-guest but execution later continues here with an interrupt shadow active.
+     */
     pVmcb->ctrl.u64IntShadow = !!fIntShadow;
 }
@@ -3814,4 +3850,5 @@
     /* The TLB flushing would've already been setup by the nested-hypervisor. */
     ASMAtomicWriteBool(&pVCpu->hm.s.fCheckedTLBFlush, true);    /* Used for TLB flushing, set this across the world switch. */
+    hmR0SvmFlushTaggedTlb(pVCpu, pCtx, pVmcbNstGst);
     Assert(hmR0GetCurrentCpu()->idCpu == pVCpu->hm.s.idLastCpu);
 
@@ -3924,5 +3961,5 @@
     /* Flush the appropriate tagged-TLB entries. */
     ASMAtomicWriteBool(&pVCpu->hm.s.fCheckedTLBFlush, true);    /* Used for TLB flushing, set this across the world switch. */
-    hmR0SvmFlushTaggedTlb(pVCpu);
+    hmR0SvmFlushTaggedTlb(pVCpu, pCtx, pVmcb);
     Assert(hmR0GetCurrentCpu()->idCpu == pVCpu->hm.s.idLastCpu);
 
@@ -5742,4 +5779,7 @@
     HMSvmNstGstVmExitNotify(pVCpu, pVmcbNstGst);
 
+    Log4(("hmR0SvmExecVmexit: uExitCode=%#RX64 uExitInfo1=%#RX64 uExitInfo2=%#RX64\n", pVmcbNstGst->ctrl.u64ExitCode,
+          pVmcbNstGst->ctrl.u64ExitInfo1, pVmcbNstGst->ctrl.u64ExitInfo2));
+
     /*
      * Write the nested-guest VMCB back to nested-guest memory.
@@ -5760,4 +5800,5 @@
      */
     pVCpu->hm.s.svm.NstGstVmcbCache.fVmrunEmulatedInR0 = false;
+    HMCPU_CF_SET(pVCpu, HM_CHANGED_ALL_GUEST);
 
     if (RT_SUCCESS(rc))
@@ -5766,7 +5807,10 @@
         if (rc == VINF_SUCCESS)
             rc = VINF_SVM_VMEXIT;
-    }
-
-    Log(("hmR0SvmExecVmexit: Failed to write guest-VMCB at %#RGp\n", GCPhysVmcb));
+
+        Log4(("hmR0SvmExecVmexit: #VMEXIT success! rc=%d\n", rc));
+    }
+    else
+        Log(("hmR0SvmExecVmexit: Failed to write guest-VMCB at %#RGp, rc=%d\n", GCPhysVmcb, rc));
+
     return rc;
 }
@@ -5886,5 +5930,5 @@
         if (RT_FAILURE(rc))
         {
-            Log(("iemSvmVmrun: EFER invalid uOldEfer=%#RX64 -> #VMEXIT\n", pVmcbNstGstState->u64EFER));
+            Log(("hmR0SvmExecVmrun: EFER invalid uOldEfer=%#RX64 -> #VMEXIT\n", pVmcbNstGstState->u64EFER));
             pVmcbNstGstCtrl->u64ExitCode = SVM_EXIT_INVALID;
             return hmR0SvmExecVmexit(pVCpu, pCtx);
