Index: /trunk/src/VBox/VMM/VMMR0/HMSVMR0.cpp
===================================================================
--- /trunk/src/VBox/VMM/VMMR0/HMSVMR0.cpp	(revision 73110)
+++ /trunk/src/VBox/VMM/VMMR0/HMSVMR0.cpp	(revision 73111)
@@ -175,13 +175,4 @@
     } while (0)
 #endif
-
-/** Macro which updates interrupt shadow for the current RIP.  */
-#define HMSVM_UPDATE_INTR_SHADOW(a_pVCpu) \
-    do { \
-        /* Update interrupt shadow. */ \
-        if (   VMCPU_FF_IS_PENDING((a_pVCpu), VMCPU_FF_INHIBIT_INTERRUPTS) \
-            && (a_pVCpu)->cpum.GstCtx.rip != EMGetInhibitInterruptsPC((a_pVCpu))) \
-            VMCPU_FF_CLEAR((a_pVCpu), VMCPU_FF_INHIBIT_INTERRUPTS); \
-    } while (0)
 
 /** Macro for upgrading a @a a_rc to VINF_EM_DBG_STEPPED after emulating an
@@ -6034,61 +6025,19 @@
 
 /**
- * Advances the guest RIP making use of the CPU's NRIP_SAVE feature if
- * supported, otherwise advances the RIP by the number of bytes specified in
- * @a cb.
- *
- * @param   pVCpu       The cross context virtual CPU structure.
- * @param   cb          RIP increment value in bytes when the CPU doesn't support
- *                      NRIP_SAVE.
- */
-DECLINLINE(void) hmR0SvmAdvanceRipHwAssist(PVMCPU pVCpu, uint32_t cb)
-{
-    PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
-    bool const fSupportsNextRipSave = hmR0SvmSupportsNextRipSave(pVCpu);
-    if (fSupportsNextRipSave)
-    {
-        PCSVMVMCB pVmcb = hmR0SvmGetCurrentVmcb(pVCpu);
-        Assert(pVmcb);
-        Assert(!(pCtx->fExtrn & CPUMCTX_EXTRN_RIP));
-        Assert(pVmcb->ctrl.u64NextRIP - pCtx->rip == cb);
-        pCtx->rip = pVmcb->ctrl.u64NextRIP;
-    }
-    else
-        pCtx->rip += cb;
-
-    HMSVM_UPDATE_INTR_SHADOW(pVCpu);
-}
-
-
-/**
- * Gets the length of the current instruction when the CPU supports the NRIP_SAVE
- * feature.
- *
- * @returns The current instruction length in bytes.
- * @param   pVCpu       The cross context virtual CPU structure.
- *
- * @remarks Requires the NRIP_SAVE feature to be supported by the CPU.
- */
-DECLINLINE(uint8_t) hmR0SvmGetInstrLength(PVMCPU pVCpu)
-{
-    Assert(hmR0SvmSupportsNextRipSave(pVCpu));
-    PCSVMVMCB pVmcb = hmR0SvmGetCurrentVmcb(pVCpu);
-    return pVmcb->ctrl.u64NextRIP - pVCpu->cpum.GstCtx.rip;
-}
-
-
-/**
- * Advances the guest RIP by the number of bytes specified in @a cb. This does
- * not make use of any hardware features to determine the instruction length.
+ * Advances the guest RIP by the number of bytes specified in @a cb.
  *
  * @param   pVCpu       The cross context virtual CPU structure.
  * @param   cb          RIP increment value in bytes.
  */
-DECLINLINE(void) hmR0SvmAdvanceRipDumb(PVMCPU pVCpu, uint32_t cb)
-{
-    pVCpu->cpum.GstCtx.rip += cb;
-    HMSVM_UPDATE_INTR_SHADOW(pVCpu);
-}
-#undef HMSVM_UPDATE_INTR_SHADOW
+DECLINLINE(void) hmR0SvmAdvanceRip(PVMCPU pVCpu, uint32_t cb)
+{
+    PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
+    pCtx->rip += cb;
+
+    /* Update interrupt shadow. */
+    if (   VMCPU_FF_IS_PENDING(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS)
+        && pCtx->rip != EMGetInhibitInterruptsPC(pVCpu))
+        VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
+}
 
 
@@ -6139,5 +6088,6 @@
     {
         HMSVM_CPUMCTX_IMPORT_STATE(pVCpu, IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK);
-        uint8_t const cbInstr = hmR0SvmGetInstrLength(pVCpu);
+        PCSVMVMCB     pVmcb   = hmR0SvmGetCurrentVmcb(pVCpu);
+        uint8_t const cbInstr = pVmcb->ctrl.u64NextRIP - pVCpu->cpum.GstCtx.rip;
         rcStrict = IEMExecDecodedWbinvd(pVCpu, cbInstr);
     }
@@ -6170,5 +6120,6 @@
     {
         HMSVM_CPUMCTX_IMPORT_STATE(pVCpu, IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK);
-        uint8_t const cbInstr = hmR0SvmGetInstrLength(pVCpu);
+        PCSVMVMCB     pVmcb   = hmR0SvmGetCurrentVmcb(pVCpu);
+        uint8_t const cbInstr = pVmcb->ctrl.u64NextRIP - pVCpu->cpum.GstCtx.rip;
         rcStrict = IEMExecDecodedInvd(pVCpu, cbInstr);
     }
@@ -6206,5 +6157,6 @@
         if (fSupportsNextRipSave)
         {
-            uint8_t const cbInstr = hmR0SvmGetInstrLength(pVCpu);
+            PCSVMVMCB     pVmcb   = hmR0SvmGetCurrentVmcb(pVCpu);
+            uint8_t const cbInstr = pVmcb->ctrl.u64NextRIP - pVCpu->cpum.GstCtx.rip;
             rcStrict = IEMExecDecodedCpuid(pVCpu, cbInstr);
         }
@@ -6254,5 +6206,6 @@
     {
         HMSVM_CPUMCTX_IMPORT_STATE(pVCpu, IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK | CPUMCTX_EXTRN_CR4);
-        uint8_t const cbInstr = hmR0SvmGetInstrLength(pVCpu);
+        PCSVMVMCB     pVmcb   = hmR0SvmGetCurrentVmcb(pVCpu);
+        uint8_t const cbInstr = pVmcb->ctrl.u64NextRIP - pVCpu->cpum.GstCtx.rip;
         rcStrict = IEMExecDecodedRdtsc(pVCpu, cbInstr);
     }
@@ -6286,7 +6239,7 @@
     if (fSupportsNextRipSave)
     {
-        HMSVM_CPUMCTX_IMPORT_STATE(pVCpu, IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK | CPUMCTX_EXTRN_CR4
-                                        | CPUMCTX_EXTRN_TSC_AUX);
-        uint8_t const cbInstr = hmR0SvmGetInstrLength(pVCpu);
+        HMSVM_CPUMCTX_IMPORT_STATE(pVCpu, IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK | CPUMCTX_EXTRN_CR4 | CPUMCTX_EXTRN_TSC_AUX);
+        PCSVMVMCB     pVmcb   = hmR0SvmGetCurrentVmcb(pVCpu);
+        uint8_t const cbInstr = pVmcb->ctrl.u64NextRIP - pVCpu->cpum.GstCtx.rip;
         rcStrict = IEMExecDecodedRdtscp(pVCpu, cbInstr);
     }
@@ -6321,5 +6274,6 @@
     {
         HMSVM_CPUMCTX_IMPORT_STATE(pVCpu, IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK | CPUMCTX_EXTRN_CR4);
-        uint8_t const cbInstr = hmR0SvmGetInstrLength(pVCpu);
+        PCSVMVMCB     pVmcb   = hmR0SvmGetCurrentVmcb(pVCpu);
+        uint8_t const cbInstr = pVmcb->ctrl.u64NextRIP - pVCpu->cpum.GstCtx.rip;
         rcStrict = IEMExecDecodedRdpmc(pVCpu, cbInstr);
     }
@@ -6355,5 +6309,5 @@
     {
         HMSVM_CPUMCTX_IMPORT_STATE(pVCpu, IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
-        PCSVMVMCB pVmcb = hmR0SvmGetCurrentVmcb(pVCpu);
+        PCSVMVMCB     pVmcb     = hmR0SvmGetCurrentVmcb(pVCpu);
         uint8_t const cbInstr   = pVmcb->ctrl.u64NextRIP - pVCpu->cpum.GstCtx.rip;
         RTGCPTR const GCPtrPage = pVmcb->ctrl.u64ExitInfo1;
@@ -6388,5 +6342,6 @@
     {
         HMSVM_CPUMCTX_IMPORT_STATE(pVCpu, IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK);
-        uint8_t const cbInstr = hmR0SvmGetInstrLength(pVCpu);
+        PCSVMVMCB     pVmcb   = hmR0SvmGetCurrentVmcb(pVCpu);
+        uint8_t const cbInstr = pVmcb->ctrl.u64NextRIP - pVCpu->cpum.GstCtx.rip;
         rcStrict = IEMExecDecodedHlt(pVCpu, cbInstr);
     }
@@ -6408,6 +6363,7 @@
     }
     HMSVM_CHECK_SINGLE_STEP(pVCpu, rcStrict);
+    STAM_COUNTER_INC(&pVCpu->hm.s.StatExitHlt);
     if (rcStrict != VINF_SUCCESS)
-         STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchHltToR3);
+        STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchHltToR3);
     return VBOXSTRICTRC_VAL(rcStrict);;
 }
@@ -6422,15 +6378,13 @@
 
     /*
-     * SVM unfortunately does not provide us with any segment override prefix information.
-     *
-     * If the instruction length supplied by the CPU is 3 bytes, we can be certain that no
+     * If the instruction length is supplied by the CPU is 3 bytes, we can be certain that no
      * segment override prefix is present (and thus use the default segment DS). Otherwise, a
      * segment override prefix or other prefixes might be used, in which case we fallback to
-     * IEMExecOne() to handle it.
+     * IEMExecOne() to figure out.
      */
     VBOXSTRICTRC  rcStrict;
-    bool const    fSupportsNextRipSave = hmR0SvmSupportsNextRipSave(pVCpu);
-    uint8_t const cbInstr              = fSupportsNextRipSave ? hmR0SvmGetInstrLength(pVCpu) : 0;
-    if (cbInstr == 3)
+    PCSVMVMCB     pVmcb   = hmR0SvmGetCurrentVmcb(pVCpu);
+    uint8_t const cbInstr = hmR0SvmSupportsNextRipSave(pVCpu) ? pVmcb->ctrl.u64NextRIP - pVCpu->cpum.GstCtx.rip : 0;
+    if (cbInstr)
     {
         HMSVM_CPUMCTX_IMPORT_STATE(pVCpu, IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK | CPUMCTX_EXTRN_DS);
@@ -6466,5 +6420,6 @@
     {
         HMSVM_CPUMCTX_IMPORT_STATE(pVCpu, IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK);
-        uint8_t const cbInstr = hmR0SvmGetInstrLength(pVCpu);
+        PCSVMVMCB     pVmcb   = hmR0SvmGetCurrentVmcb(pVCpu);
+        uint8_t const cbInstr = pVmcb->ctrl.u64NextRIP - pVCpu->cpum.GstCtx.rip;
         rcStrict = IEMExecDecodedMwait(pVCpu, cbInstr);
     }
@@ -6545,5 +6500,5 @@
         if (fMovCRx)
         {
-            HMSVM_CPUMCTX_IMPORT_STATE(pVCpu, IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK | CPUMCTX_EXTRN_CR3 | CPUMCTX_EXTRN_CR4
+            HMSVM_CPUMCTX_IMPORT_STATE(pVCpu, IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK | CPUMCTX_EXTRN_CR_MASK
                                             | CPUMCTX_EXTRN_APIC_TPR);
             uint8_t const cbInstr = pVmcb->ctrl.u64NextRIP - pCtx->rip;
@@ -6689,5 +6644,6 @@
          *  can ask for what it needs instead of using CPUMCTX_EXTRN_ALL_MSRS. */
         HMSVM_CPUMCTX_IMPORT_STATE(pVCpu, IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK | CPUMCTX_EXTRN_ALL_MSRS);
-        rcStrict = IEMExecDecodedRdmsr(pVCpu, pVmcb->ctrl.u64NextRIP - pCtx->rip);
+        uint8_t const cbInstr = pVmcb->ctrl.u64NextRIP - pVCpu->cpum.GstCtx.rip;
+        rcStrict = IEMExecDecodedRdmsr(pVCpu, cbInstr);
     }
     else
@@ -6731,17 +6687,32 @@
      * We utilitize the LSTAR MSR for patching.
      */
+    bool const fSupportsNextRipSave = hmR0SvmSupportsNextRipSave(pVCpu);
     if (   pVCpu->CTX_SUFF(pVM)->hm.s.fTPRPatchingActive
         && idMsr == MSR_K8_LSTAR)
     {
+        unsigned cbInstr;
+        if (fSupportsNextRipSave)
+            cbInstr = pVmcb->ctrl.u64NextRIP - pVCpu->cpum.GstCtx.rip;
+        else
+        {
+            PDISCPUSTATE pDis = &pVCpu->hm.s.DisState;
+            int rc = EMInterpretDisasCurrent(pVCpu->CTX_SUFF(pVM), pVCpu, pDis, &cbInstr);
+            if (   rc == VINF_SUCCESS
+                && pDis->pCurInstr->uOpcode == OP_WRMSR)
+                Assert(cbInstr > 0);
+            else
+                cbInstr = 0;
+        }
+
+        /* Our patch code uses LSTAR for TPR caching for 32-bit guests. */
         if ((pCtx->eax & 0xff) != pSvmTransient->u8GuestTpr)
         {
-            /* Our patch code uses LSTAR for TPR caching for 32-bit guests. */
-            int rc2 = APICSetTpr(pVCpu, pCtx->eax & 0xff);
-            AssertRC(rc2);
+            int rc = APICSetTpr(pVCpu, pCtx->eax & 0xff);
+            AssertRCReturn(rc, rc);
             ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_APIC_TPR);
         }
 
         int rc = VINF_SUCCESS;
-        hmR0SvmAdvanceRipHwAssist(pVCpu, 2);
+        hmR0SvmAdvanceRip(pVCpu, cbInstr);
         HMSVM_CHECK_SINGLE_STEP(pVCpu, rc);
         return rc;
@@ -6752,5 +6723,4 @@
      */
     VBOXSTRICTRC rcStrict;
-    bool const fSupportsNextRipSave = hmR0SvmSupportsNextRipSave(pVCpu);
     if (fSupportsNextRipSave)
     {
@@ -6759,5 +6729,6 @@
          * clear the applicable extern flags. */
         HMSVM_CPUMCTX_IMPORT_STATE(pVCpu, IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK | CPUMCTX_EXTRN_ALL_MSRS);
-        rcStrict = IEMExecDecodedWrmsr(pVCpu, pVmcb->ctrl.u64NextRIP - pCtx->rip);
+        uint8_t const cbInstr = pVmcb->ctrl.u64NextRIP - pVCpu->cpum.GstCtx.rip;
+        rcStrict = IEMExecDecodedWrmsr(pVCpu, cbInstr);
     }
     else
@@ -7385,4 +7356,21 @@
     if (EMAreHypercallInstructionsEnabled(pVCpu))
     {
+        unsigned cbInstr;
+        if (hmR0SvmSupportsNextRipSave(pVCpu))
+        {
+            PCSVMVMCB pVmcb = hmR0SvmGetCurrentVmcb(pVCpu);
+            cbInstr = pVmcb->ctrl.u64NextRIP - pVCpu->cpum.GstCtx.rip;
+        }
+        else
+        {
+            PDISCPUSTATE pDis = &pVCpu->hm.s.DisState;
+            int rc = EMInterpretDisasCurrent(pVCpu->CTX_SUFF(pVM), pVCpu, pDis, &cbInstr);
+            if (   rc == VINF_SUCCESS
+                && pDis->pCurInstr->uOpcode == OP_VMMCALL)
+                Assert(cbInstr > 0);
+            else
+                cbInstr = 0;
+        }
+
         VBOXSTRICTRC rcStrict = GIMHypercall(pVCpu, &pVCpu->cpum.GstCtx);
         if (RT_SUCCESS(rcStrict))
@@ -7391,5 +7379,5 @@
                of say VINF_GIM_R3_HYPERCALL. */
             if (rcStrict == VINF_SUCCESS)
-                hmR0SvmAdvanceRipHwAssist(pVCpu, 3 /* cbInstr */);
+                hmR0SvmAdvanceRip(pVCpu, cbInstr);
 
             return VBOXSTRICTRC_VAL(rcStrict);
@@ -7410,7 +7398,27 @@
 {
     HMSVM_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pSvmTransient);
-    hmR0SvmAdvanceRipHwAssist(pVCpu, 2);
+
+    VBOXSTRICTRC rcStrict;
+    unsigned cbInstr;
+    bool const fSupportsNextRipSave = hmR0SvmSupportsNextRipSave(pVCpu);
+    if (fSupportsNextRipSave)
+    {
+        PCSVMVMCB pVmcb = hmR0SvmGetCurrentVmcb(pVCpu);
+        cbInstr = pVmcb->ctrl.u64NextRIP - pVCpu->cpum.GstCtx.rip;
+    }
+    else
+    {
+        PDISCPUSTATE pDis = &pVCpu->hm.s.DisState;
+        int rc = EMInterpretDisasCurrent(pVCpu->CTX_SUFF(pVM), pVCpu, pDis, &cbInstr);
+        if (   rc == VINF_SUCCESS
+            && pDis->pCurInstr->uOpcode == OP_PAUSE)
+            Assert(cbInstr > 0);
+        else
+            cbInstr = 0;
+    }
+
     /** @todo The guest has likely hit a contended spinlock. We might want to
      *        poke a schedule different guest VCPU. */
+    hmR0SvmAdvanceRip(pVCpu, cbInstr);
     return VINF_EM_RAW_INTERRUPT;
 }
@@ -7615,5 +7623,5 @@
         {
             /* #UD #VMEXIT does not have valid NRIP information, manually advance RIP. See @bugref{7270#c170}. */
-            hmR0SvmAdvanceRipDumb(pVCpu, cbInstr);
+            hmR0SvmAdvanceRip(pVCpu, cbInstr);
             rc = VINF_SUCCESS;
             HMSVM_CHECK_SINGLE_STEP(pVCpu, rc);
@@ -7660,6 +7668,6 @@
         PVM       pVM  = pVCpu->CTX_SUFF(pVM);
         PDISSTATE pDis = &pVCpu->hm.s.DisState;
-        unsigned  cbOp;
-        int rc = EMInterpretDisasCurrent(pVM, pVCpu, pDis, &cbOp);
+        unsigned  cbInstr;
+        int rc = EMInterpretDisasCurrent(pVM, pVCpu, pDis, &cbInstr);
         if (RT_SUCCESS(rc))
         {
@@ -7667,5 +7675,5 @@
             rc = PDMIsaSetIrq(pVCpu->CTX_SUFF(pVM), 13 /* u8Irq */, 1 /* u8Level */, 0 /* uTagSrc */);
             if (RT_SUCCESS(rc))
-                pCtx->rip += cbOp;
+                hmR0SvmAdvanceRip(pVCpu, cbInstr);
         }
         else
@@ -7846,6 +7854,6 @@
     if (fSupportsNextRipSave)
     {
-        HMSVM_CPUMCTX_IMPORT_STATE(pVCpu, IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK | fImport);
-        uint8_t const cbInstr = hmR0SvmGetInstrLength(pVCpu);
+        PCSVMVMCB     pVmcb   = hmR0SvmGetCurrentVmcb(pVCpu);
+        uint8_t const cbInstr = pVmcb->ctrl.u64NextRIP - pVCpu->cpum.GstCtx.rip;
         rcStrict = IEMExecDecodedClgi(pVCpu, cbInstr);
     }
@@ -7888,6 +7896,5 @@
     if (fSupportsNextRipSave)
     {
-        HMSVM_CPUMCTX_IMPORT_STATE(pVCpu, IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK | fImport);
-        uint8_t const cbInstr = hmR0SvmGetInstrLength(pVCpu);
+        uint8_t const cbInstr = pVmcb->ctrl.u64NextRIP - pVCpu->cpum.GstCtx.rip;
         rcStrict = IEMExecDecodedStgi(pVCpu, cbInstr);
     }
@@ -7931,6 +7938,5 @@
     if (fSupportsNextRipSave)
     {
-        HMSVM_CPUMCTX_IMPORT_STATE(pVCpu, IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK | fImport);
-        uint8_t const cbInstr = hmR0SvmGetInstrLength(pVCpu);
+        uint8_t const cbInstr = pVmcb->ctrl.u64NextRIP - pVCpu->cpum.GstCtx.rip;
         rcStrict = IEMExecDecodedVmload(pVCpu, cbInstr);
     }
@@ -7975,6 +7981,5 @@
     if (fSupportsNextRipSave)
     {
-        HMSVM_CPUMCTX_IMPORT_STATE(pVCpu, IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK);
-        uint8_t const cbInstr = hmR0SvmGetInstrLength(pVCpu);
+        uint8_t const cbInstr = pVmcb->ctrl.u64NextRIP - pVCpu->cpum.GstCtx.rip;
         rcStrict = IEMExecDecodedVmsave(pVCpu, cbInstr);
     }
@@ -8006,6 +8011,6 @@
     if (fSupportsNextRipSave)
     {
-        HMSVM_CPUMCTX_IMPORT_STATE(pVCpu, IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK);
-        uint8_t const cbInstr = hmR0SvmGetInstrLength(pVCpu);
+        PCSVMVMCB     pVmcb   = hmR0SvmGetCurrentVmcb(pVCpu);
+        uint8_t const cbInstr = pVmcb->ctrl.u64NextRIP - pVCpu->cpum.GstCtx.rip;
         rcStrict = IEMExecDecodedInvlpga(pVCpu, cbInstr);
     }
@@ -8041,5 +8046,6 @@
     if (fSupportsNextRipSave)
     {
-        uint8_t const cbInstr = hmR0SvmGetInstrLength(pVCpu);
+        PCSVMVMCB     pVmcb   = hmR0SvmGetCurrentVmcb(pVCpu);
+        uint8_t const cbInstr = pVmcb->ctrl.u64NextRIP - pVCpu->cpum.GstCtx.rip;
         rcStrict = IEMExecDecodedVmrun(pVCpu, cbInstr);
     }
