Index: trunk/src/VBox/VMM/VMMR0/HWSVMR0.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMR0/HWSVMR0.cpp	(revision 20330)
+++ trunk/src/VBox/VMM/VMMR0/HWSVMR0.cpp	(revision 20343)
@@ -1705,4 +1705,5 @@
             &&  pVM->hwaccm.s.fHasIoApic
             &&  !(errCode & X86_TRAP_PF_P)  /* not present */
+            &&  CPUMGetGuestCPL(pVCpu, CPUMCTX2CORE(pCtx)) == 0
             &&  !CPUMIsGuestInLongModeEx(pCtx))
         {
@@ -2334,4 +2335,64 @@
 }
 
+/**
+ * Emulate simple mov tpr instruction
+ *
+ * @returns VBox status code.
+ * @param   pVCpu       The VM CPU to operate on.
+ * @param   pDisState   Disassembly state
+ * @param   pCtx        CPU context
+ * @param   cbOp        Opcode size
+ */
+static int svmR0EmulateTprMov(PVMCPU pVCpu, DISCPUSTATE *pDisState, PCPUMCTX pCtx, unsigned cbOp)
+{
+    int rc;
+
+    if (pDisState->param1.flags == USE_DISPLACEMENT32)
+    {
+        /* write */
+        uint8_t u8Tpr;
+
+        /* Fetch the new TPR value */
+        if (pDisState->param2.flags == USE_REG_GEN32)
+        {
+            uint32_t val;
+
+            rc = DISFetchReg32(CPUMCTX2CORE(pCtx), pDisState->param2.base.reg_gen, &val);
+            AssertRC(rc);
+            u8Tpr = val >> 4;
+        }
+        else
+        if (pDisState->param2.flags == USE_IMMEDIATE32)
+        {
+            u8Tpr = (uint8_t)pDisState->param2.parval >> 4;
+        }
+        else
+            return VERR_EM_INTERPRETER;
+
+        rc = PDMApicSetTPR(pVCpu, u8Tpr);
+        AssertRC(rc);
+
+        pCtx->rip += cbOp;
+        return VINF_SUCCESS;
+    }
+    else
+    if (pDisState->param2.flags == USE_DISPLACEMENT32)
+    {
+        /* read */
+        bool    fPending;
+        uint8_t u8Tpr;
+
+        /* TPR caching in CR8 */
+        rc = PDMApicGetTPR(pVCpu, &u8Tpr, &fPending);
+        AssertRC(rc);
+
+        rc = DISWriteReg32(CPUMCTX2CORE(pCtx), pDisState->param1.base.reg_gen, u8Tpr << 4);
+        AssertRC(rc);
+
+        pCtx->rip += cbOp;
+        return VINF_SUCCESS;
+    }
+    return VERR_EM_INTERPRETER;
+}
 
 /**
@@ -2355,4 +2416,8 @@
         &&  Cpu.pCurInstr->opcode == OP_MOV)
     {
+        rc = svmR0EmulateTprMov(pVCpu, &Cpu, pCtx, cbOp);
+        if (rc != VINF_SUCCESS)
+            return rc;
+
         uint8_t szInstr[15];
         if (    cbOp == 10
@@ -2369,5 +2434,4 @@
              *
              */
-            RTGCPTR     oldEip = pCtx->eip;
             uint32_t    u32tpr = (uint32_t)Cpu.param2.parval;
 
@@ -2377,7 +2441,5 @@
              * it does, then we can safely use it ourselves.
              */
-            pCtx->eip += cbOp;
             rc = EMInterpretDisasOne(pVM, pVCpu, CPUMCTX2CORE(pCtx), &Cpu, &cbOp);
-            pCtx->eip = oldEip;
             if (    rc == VINF_SUCCESS
                 &&  Cpu.pCurInstr->opcode == OP_MOV
@@ -2410,5 +2472,4 @@
                 &&  cbOp == 6)
             {
-                RTGCPTR  oldEip   = pCtx->eip;
                 RTGCPTR  GCPtrTpr = (uint32_t)Cpu.param1.disp32;
                 uint32_t uMmioReg = Cpu.param2.base.reg_gen;
@@ -2419,7 +2480,5 @@
                  *   mov ecx, dword [fffe0080]        (5 bytes)
                  */
-                pCtx->eip += cbOp;
                 rc = EMInterpretDisasOne(pVM, pVCpu, CPUMCTX2CORE(pCtx), &Cpu, &cbOp);
-                pCtx->eip = oldEip;
                 if (    rc == VINF_SUCCESS
                     &&  Cpu.pCurInstr->opcode == OP_MOV
@@ -2453,5 +2512,5 @@
                     AssertRC(rc);
 
-                    Log(("Acceptable write candidate!\n"));
+                    Log(("Acceptable read/write candidate!\n"));
                     return VINF_SUCCESS;
                 }
@@ -2461,5 +2520,4 @@
                 &&  cbOp == 5)
             {
-                RTGCPTR  oldEip = pCtx->eip;
                 uint32_t uMmioReg = Cpu.param1.base.reg_gen;
 
@@ -2469,7 +2527,5 @@
                  *   shr eax, 4
                  */
-                pCtx->eip += cbOp;
                 rc = EMInterpretDisasOne(pVM, pVCpu, CPUMCTX2CORE(pCtx), &Cpu, &cbOp);
-                pCtx->eip = oldEip;
                 if (    rc == VINF_SUCCESS
                     &&  Cpu.pCurInstr->opcode == OP_SHR
@@ -2495,4 +2551,6 @@
             }
         }
+        /* Emulated successfully, so continue. */
+        return VINF_SUCCESS;
     }
     return VERR_ACCESS_DENIED;
