Index: trunk/src/VBox/VMM/VMMR0/HMVMXR0.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMR0/HMVMXR0.cpp	(revision 45616)
+++ trunk/src/VBox/VMM/VMMR0/HMVMXR0.cpp	(revision 45617)
@@ -2806,8 +2806,9 @@
                     | X86_CR0_CD    /* Bit ignored on VM-entry and VM-exit. Don't let the guest modify the host CR0.CD */
                     | X86_CR0_NW;   /* Bit ignored on VM-entry and VM-exit. Don't let the guest modify the host CR0.NW */
-
-        /* We don't need to intercept changes to CR0.PE with unrestricted guests. */
         if (pVM->hm.s.vmx.fUnrestrictedGuest)
             u64CR0Mask &= ~X86_CR0_PE;
+        /* Enable this later. */
+        /* if (pVM->hm.s.fNestedPaging)
+            u64CR0Mask &= ~X86_CR0_WP; */
 
         /* If the guest FPU state is active, don't need to VM-exit on writes to FPU related bits in CR0. */
@@ -2835,5 +2836,5 @@
     if (pVCpu->hm.s.fContextUseFlags & HM_CHANGED_GUEST_CR3)
     {
-        uint64_t u64GuestCR3 = 0;
+        RTGCPHYS GCPhysGuestCR3 = NIL_RTGCPHYS;
         if (pVM->hm.s.fNestedPaging)
         {
@@ -2874,5 +2875,5 @@
                 /* The guest's view of its CR3 is unblemished with Nested Paging when the guest is using paging or we
                    have Unrestricted Execution to handle the guest when it's not using paging. */
-                u64GuestCR3 = pCtx->cr3;
+                GCPhysGuestCR3 = pCtx->cr3;
             }
             else
@@ -2891,5 +2892,5 @@
                 AssertRCReturn(rc, rc);
 
-                u64GuestCR3 = GCPhys;
+                GCPhysGuestCR3 = GCPhys;
             }
         }
@@ -2897,9 +2898,9 @@
         {
             /* Non-nested paging case, just use the hypervisor's CR3. */
-            u64GuestCR3 = PGMGetHyperCR3(pVCpu);
-        }
-
-        Log(("Load: VMX_VMCS_GUEST_CR3=%#RX64\n", u64GuestCR3));
-        rc = VMXWriteVmcsGstN(VMX_VMCS_GUEST_CR3, u64GuestCR3);
+            GCPhysGuestCR3 = PGMGetHyperCR3(pVCpu);
+        }
+
+        Log(("Load: VMX_VMCS_GUEST_CR3=%#RGv\n", GCPhysGuestCR3));
+        rc = VMXWriteVmcsGstN(VMX_VMCS_GUEST_CR3, GCPhysGuestCR3);
         AssertRCReturn(rc, rc);
 
@@ -2912,5 +2913,6 @@
     if (pVCpu->hm.s.fContextUseFlags & HM_CHANGED_GUEST_CR4)
     {
-        uint64_t u64GuestCR4 = pCtx->cr4;
+        uint32_t u64GuestCR4 = pCtx->cr4;
+        Assert(!(pCtx->cr4 >> 32));
 
         /* The guest's view of its CR4 is unblemished. */
@@ -3057,4 +3059,5 @@
         Assert(fInterceptDB == false);      /* If we are not single stepping in DBGF, there is no need to intercept #DB. */
 
+
     /*
      * If the guest is using its DRx registers and the host DRx does not yet contain the guest DRx values,
@@ -3062,25 +3065,30 @@
      * The same for the hypervisor DRx registers, priority is for the guest here.
      */
-    if (    (pCtx->dr[7] & (X86_DR7_ENABLED_MASK | X86_DR7_GD))
-        && !CPUMIsGuestDebugStateActive(pVCpu))
-    {
-        /* Save the host and load the guest debug registers. This will make the guest debug state active. */
-        rc = CPUMR0LoadGuestDebugState(pVM, pVCpu, pCtx, true /* include DR6 */);
-        AssertRC(rc);
+    if (pCtx->dr[7] & (X86_DR7_ENABLED_MASK | X86_DR7_GD))
+    {
+        if (!CPUMIsGuestDebugStateActive(pVCpu))
+        {
+            rc = CPUMR0LoadGuestDebugState(pVM, pVCpu, pCtx, true /* include DR6 */);
+            AssertRC(rc);
+            STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxArmed);
+        }
         Assert(CPUMIsGuestDebugStateActive(pVCpu));
         Assert(fInterceptMovDRx == false);
-        STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxArmed);
-    }
-    else if (    CPUMGetHyperDR7(pVCpu) & (X86_DR7_ENABLED_MASK | X86_DR7_GD)
-             && !CPUMIsHyperDebugStateActive(pVCpu))
-    {
-        /* Save the host and load the hypervisor debug registers. This will make the hyper debug state active. */
-        rc = CPUMR0LoadHyperDebugState(pVM, pVCpu, pCtx, true /* include DR6 */);
-        AssertRC(rc);
+    }
+    else if (CPUMGetHyperDR7(pVCpu) & (X86_DR7_ENABLED_MASK | X86_DR7_GD))
+    {
+        if (!CPUMIsHyperDebugStateActive(pVCpu))
+        {
+            rc = CPUMR0LoadHyperDebugState(pVM, pVCpu, pCtx, true /* include DR6 */);
+            AssertRC(rc);
+        }
         Assert(CPUMIsHyperDebugStateActive(pVCpu));
         fInterceptMovDRx = true;
     }
-    else
-        Assert(fInterceptMovDRx == false);  /* No need to intercept MOV DRx if DBGF is not active nor the guest is debugging. */
+    else if (!CPUMIsGuestDebugStateActive(pVCpu))
+    {
+        /* For the first time we would need to intercept MOV DRx accesses even when the guest debug state isn't active. */
+        fInterceptMovDRx = true;
+    }
 
     /* Update the exception bitmap regarding intercepting #DB generated by the guest. */
@@ -7228,9 +7236,11 @@
 {
     VMX_VALIDATE_EXIT_HANDLER_PARAMS();
+    PVM pVM = pVCpu->CTX_SUFF(pVM);
+    Assert(!pVM->hm.s.fNestedPaging);
+
     int rc = hmR0VmxReadExitQualificationVmcs(pVCpu, pVmxTransient);
     rc    |= hmR0VmxSaveGuestControlRegs(pVCpu, pMixedCtx);
     AssertRCReturn(rc, rc);
 
-    PVM pVM = pVCpu->CTX_SUFF(pVM);
     VBOXSTRICTRC rc2 = EMInterpretInvlpg(pVM, pVCpu, CPUMCTX2CORE(pMixedCtx), pVmxTransient->uExitQualification);
     rc = VBOXSTRICTRC_VAL(rc2);
@@ -7241,5 +7251,4 @@
         AssertMsg(rc == VERR_EM_INTERPRETER, ("hmR0VmxExitInvlpg: EMInterpretInvlpg %#RGv failed with %Rrc\n",
                                               pVmxTransient->uExitQualification, rc));
-        rc = VERR_EM_INTERPRETER;
     }
     STAM_COUNTER_INC(&pVCpu->hm.s.StatExitInvlpg);
@@ -8219,6 +8228,4 @@
         && !CPUMIsHyperDebugStateActive(pVCpu))
     {
-        Assert(!CPUMIsGuestDebugStateActive(pVCpu));
-
         /* Don't intercept MOV DRx. */
         pVCpu->hm.s.vmx.u32ProcCtls &= ~VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_MOV_DR_EXIT;
@@ -8244,6 +8251,4 @@
     }
 
-    /** @todo clear VMX_VMCS_CTRL_PROC_EXEC_CONTROLS_MOV_DR_EXIT after the first
-     *        time and restore DRx registers afterwards */
     /*
      * EMInterpretDRx[Write|Read]() calls CPUMIsGuestIn64BitCode() which requires EFER, CS. EFER is always up-to-date, see
@@ -8879,6 +8884,6 @@
     AssertRCReturn(rc, rc);
 
-    Log(("#PF: cr2=%#RGv cs:rip=%#04x:%#RGv uErrCode %#RX32\n", pVmxTransient->uExitQualification, pMixedCtx->cs.Sel,
-         pMixedCtx->rip, pVmxTransient->uExitIntrErrorCode));
+    Log(("#PF: cr2=%#RGv cs:rip=%#04x:%#RGv uErrCode %#RX32 cr3=%#RGv\n", pVmxTransient->uExitQualification, pMixedCtx->cs.Sel,
+         pMixedCtx->rip, pVmxTransient->uExitIntrErrorCode, pMixedCtx->cr3));
 
     TRPMAssertXcptPF(pVCpu, pVmxTransient->uExitQualification, (RTGCUINT)pVmxTransient->uExitIntrErrorCode);
