Index: trunk/src/VBox/VMM/VMMAll/IEMAllCImpl.cpp.h
===================================================================
--- trunk/src/VBox/VMM/VMMAll/IEMAllCImpl.cpp.h	(revision 74606)
+++ trunk/src/VBox/VMM/VMMAll/IEMAllCImpl.cpp.h	(revision 74607)
@@ -5719,5 +5719,5 @@
  *
  * @param   iCrReg          The CRx register to write (valid).
- * @param   iGReg           The general register to load the DRx value from.
+ * @param   iGReg           The general register to load the CRx value from.
  */
 IEM_CIMPL_DEF_2(iemCImpl_mov_Cd_Rd, uint8_t, iCrReg, uint8_t, iGReg)
@@ -5735,4 +5735,18 @@
     else
         uNewCrX = iemGRegFetchU32(pVCpu, iGReg);
+
+#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
+    if (IEM_VMX_IS_NON_ROOT_MODE(pVCpu))
+    {
+        if (iCrReg == 0)
+        {
+            IEM_CTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0);
+            VBOXSTRICTRC rcStrict = iemVmxVmexitInstrMovCr0Write(pVCpu, pVCpu->cpum.GstCtx.cr0, &uNewCrX, iGReg, cbInstr);
+            if (rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE)
+                return rcStrict;
+        }
+    }
+#endif
+
     return IEM_CIMPL_CALL_4(iemCImpl_load_CrX, iCrReg, uNewCrX, IEMACCESSCRX_MOV_CRX, iGReg);
 }
Index: trunk/src/VBox/VMM/VMMAll/IEMAllCImplVmxInstr.cpp.h
===================================================================
--- trunk/src/VBox/VMM/VMMAll/IEMAllCImplVmxInstr.cpp.h	(revision 74606)
+++ trunk/src/VBox/VMM/VMMAll/IEMAllCImplVmxInstr.cpp.h	(revision 74607)
@@ -1300,5 +1300,5 @@
  *
  * @param   pVCpu       The cross context virtual CPU structure.
- * @param   cbInstr     The VM-exit instruction length (in bytes).
+ * @param   cbInstr     The VM-exit instruction length in bytes.
  */
 DECL_FORCE_INLINE(void) iemVmxVmcsSetExitInstrLen(PVMCPU pVCpu, uint32_t cbInstr)
@@ -2645,5 +2645,5 @@
  * @param   pVCpu           The cross context virtual CPU structure.
  * @param   uExitReason     The VM-exit reason.
- * @param   cbInstr         The instruction length (in bytes).
+ * @param   cbInstr         The instruction length in bytes.
  */
 IEM_STATIC VBOXSTRICTRC iemVmxVmexitInstr(PVMCPU pVCpu, uint32_t uExitReason, uint8_t cbInstr)
@@ -2691,5 +2691,5 @@
  * @param   uExitReason     The VM-exit reason.
  * @param   uInstrid        The instruction identity (VMXINSTRID_XXX).
- * @param   cbInstr         The instruction length (in bytes).
+ * @param   cbInstr         The instruction length in bytes.
  *
  * @remarks Do not use this for INS/OUTS instruction.
@@ -2749,5 +2749,5 @@
  * @param   pVCpu           The cross context virtual CPU structure.
  * @param   GCPtrPage       The guest-linear address of the page being invalidated.
- * @param   cbInstr         The instruction length (in bytes).
+ * @param   cbInstr         The instruction length in bytes.
  */
 IEM_STATIC VBOXSTRICTRC iemVmxVmexitInstrInvlpg(PVMCPU pVCpu, RTGCPTR GCPtrPage, uint8_t cbInstr)
@@ -2776,5 +2776,5 @@
  *                          of a memory operand. For register operand, pass
  *                          NIL_RTGCPTR.
- * @param   cbInstr         The instruction length (in bytes).
+ * @param   cbInstr         The instruction length in bytes.
  */
 IEM_STATIC VBOXSTRICTRC iemVmxVmexitInstrLmsw(PVMCPU pVCpu, uint32_t uGuestCr0, uint16_t *pu16NewMsw, RTGCPTR GCPtrEffDst,
@@ -2864,5 +2864,5 @@
  *
  * @param   pVCpu           The cross context virtual CPU structure.
- * @param   cbInstr         The instruction length (in bytes).
+ * @param   cbInstr         The instruction length in bytes.
  */
 IEM_STATIC VBOXSTRICTRC iemVmxVmexitInstrClts(PVMCPU pVCpu, uint8_t cbInstr)
@@ -2905,4 +2905,58 @@
      * and may modify CR0.TS (subject to CR0 fixed bits in VMX operation).
      */
+    return VINF_VMX_INTERCEPT_NOT_ACTIVE;
+}
+
+
+/**
+ * VMX VM-exit handler for VM-exits due to 'Mov CR0, GReg' (CR0 write).
+ *
+ * @returns Strict VBox status code.
+ * @param   pVCpu           The cross context virtual CPU structure.
+ * @param   puNewCr0        Pointer to the new CR0 value. Will be updated if no
+ *                          VM-exit is triggered.
+ * @param   iGReg           The general register to load the CR0 value from.
+ * @param   cbInstr         The instruction length in bytes.
+ */
+IEM_STATIC VBOXSTRICTRC iemVmxVmexitInstrMovCr0Write(PVMCPU pVCpu, uint64_t uGuestCr0, uint64_t *puNewCr0, uint8_t iGReg,
+                                                     uint8_t cbInstr)
+{
+    PCVMXVVMCS pVmcs = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
+    Assert(pVmcs);
+    Assert(puNewCr0);
+
+    uint32_t const fGstHostMask = pVmcs->u64Cr0Mask.u;
+    uint32_t const fReadShadow  = pVmcs->u64Cr0ReadShadow.u;
+
+    /*
+     * For any CR0 bit owned by the host (in the CR0 guest/host mask), if the
+     * corresponding bits differ between the source operand and the read-shadow,
+     * we must cause a VM-exit.
+     *
+     * See Intel spec. 25.1.3 "Instructions That Cause VM Exits Conditionally".
+     */
+    if ((fReadShadow & fGstHostMask) != (*puNewCr0 & fGstHostMask))
+    {
+        Log2(("mov_Cr_Rd: Guest intercept -> VM-exit\n"));
+
+        VMXVEXITINFO ExitInfo;
+        RT_ZERO(ExitInfo);
+        ExitInfo.uReason = VMX_EXIT_MOV_CRX;
+        ExitInfo.cbInstr = cbInstr;
+
+        ExitInfo.u64Qual = RT_BF_MAKE(VMX_BF_EXIT_QUAL_CRX_REGISTER, 0) /* CR0 */
+                         | RT_BF_MAKE(VMX_BF_EXIT_QUAL_CRX_ACCESS,   VMX_EXIT_QUAL_CRX_ACCESS_WRITE)
+                         | RT_BF_MAKE(VMX_BF_EXIT_QUAL_CRX_GENREG,   iGReg);
+        return iemVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
+    }
+
+    /*
+     * If Mov-to-CR0 did not cause a VM-exit, any bits owned by the host must not
+     * be modified the instruction.
+     *
+     * See Intel Spec. 25.3 "Changes To Instruction Behavior In VMX Non-root Operation".
+     */
+    *puNewCr0 = (uGuestCr0 & fGstHostMask) | (*puNewCr0 & ~fGstHostMask);
+
     return VINF_VMX_INTERCEPT_NOT_ACTIVE;
 }
@@ -4862,5 +4916,5 @@
  * @returns Strict VBox status code.
  * @param   pVCpu           The cross context virtual CPU structure.
- * @param   cbInstr         The instruction length.
+ * @param   cbInstr         The instruction length in bytes.
  * @param   uInstrId        The instruction identity (VMXINSTRID_VMLAUNCH or
  *                          VMXINSTRID_VMRESUME).
@@ -5139,5 +5193,5 @@
  * @returns Strict VBox status code.
  * @param   pVCpu           The cross context virtual CPU structure.
- * @param   cbInstr         The instruction length.
+ * @param   cbInstr         The instruction length in bytes.
  * @param   pu64Dst         Where to write the VMCS value (only updated when
  *                          VINF_SUCCESS is returned).
@@ -5245,5 +5299,5 @@
  * @returns Strict VBox status code.
  * @param   pVCpu           The cross context virtual CPU structure.
- * @param   cbInstr         The instruction length.
+ * @param   cbInstr         The instruction length in bytes.
  * @param   pu64Dst         Where to store the VMCS field's value.
  * @param   u64FieldEnc     The VMCS field encoding.
@@ -5271,5 +5325,5 @@
  * @returns Strict VBox status code.
  * @param   pVCpu           The cross context virtual CPU structure.
- * @param   cbInstr         The instruction length.
+ * @param   cbInstr         The instruction length in bytes.
  * @param   pu32Dst         Where to store the VMCS field's value.
  * @param   u32FieldEnc     The VMCS field encoding.
@@ -5299,5 +5353,5 @@
  * @returns Strict VBox status code.
  * @param   pVCpu           The cross context virtual CPU structure.
- * @param   cbInstr         The instruction length.
+ * @param   cbInstr         The instruction length in bytes.
  * @param   iEffSeg         The effective segment register to use with @a u64Val.
  *                          Pass UINT8_MAX if it is a register access.
@@ -5352,5 +5406,5 @@
  * @returns Strict VBox status code.
  * @param   pVCpu           The cross context virtual CPU structure.
- * @param   cbInstr         The instruction length.
+ * @param   cbInstr         The instruction length in bytes.
  * @param   iEffSeg         The effective segment register to use with @a u64Val.
  *                          Pass UINT8_MAX if it is a register access.
@@ -5502,5 +5556,5 @@
  * @returns Strict VBox status code.
  * @param   pVCpu           The cross context virtual CPU structure.
- * @param   cbInstr         The instruction length.
+ * @param   cbInstr         The instruction length in bytes.
  * @param   iEffSeg         The effective segment register to use with @a GCPtrVmcs.
  * @param   GCPtrVmcs       The linear address of the VMCS pointer.
@@ -5616,5 +5670,5 @@
  * @returns Strict VBox status code.
  * @param   pVCpu           The cross context virtual CPU structure.
- * @param   cbInstr         The instruction length.
+ * @param   cbInstr         The instruction length in bytes.
  * @param   iEffSeg         The effective segment register to use with @a GCPtrVmcs.
  * @param   GCPtrVmcs       The linear address of where to store the current VMCS
@@ -5668,5 +5722,5 @@
  * @returns Strict VBox status code.
  * @param   pVCpu           The cross context virtual CPU structure.
- * @param   cbInstr         The instruction length.
+ * @param   cbInstr         The instruction length in bytes.
  * @param   GCPtrVmcs       The linear address of the current VMCS pointer.
  * @param   pExitInfo       Pointer to the VM-exit information struct. Optional, can
@@ -5803,5 +5857,5 @@
  * @returns Strict VBox status code.
  * @param   pVCpu           The cross context virtual CPU structure.
- * @param   cbInstr         The instruction length.
+ * @param   cbInstr         The instruction length in bytes.
  * @param   iEffSeg         The effective segment register to use with @a
  *                          GCPtrVmxon.
