Index: trunk/src/VBox/HostDrivers/Support/SUPDrv.cpp
===================================================================
--- trunk/src/VBox/HostDrivers/Support/SUPDrv.cpp	(revision 54648)
+++ trunk/src/VBox/HostDrivers/Support/SUPDrv.cpp	(revision 54650)
@@ -159,4 +159,5 @@
     { "SUPR0ContAlloc",                         (void *)SUPR0ContAlloc },
     { "SUPR0ContFree",                          (void *)SUPR0ContFree },
+    { "SUPR0ChangeCR4",                         (void *)SUPR0ChangeCR4 },
     { "SUPR0EnableVTx",                         (void *)SUPR0EnableVTx },
     { "SUPR0SuspendVTxOnCpu",                   (void *)SUPR0SuspendVTxOnCpu },
@@ -3668,4 +3669,32 @@
 
 /**
+ * Change CR4 and take care of the kernel CR4 shadow if applicable.
+ *
+ * CR4 shadow handling is required for Linux >= 4.0. Calling this function
+ * instead of ASMSetCR4() is only necessary for semi-permanent CR4 changes
+ * for code with interrupts enabled.
+ *
+ * @returns the old CR4 value.
+ *
+ * @param   fOrMask         bits to be set in CR4.
+ * @param   fAndMask        bits to be cleard in CR4.
+ *
+ * @remarks Must be called with preemption/interrupts disabled.
+ */
+SUPR0DECL(RTCCUINTREG) SUPR0ChangeCR4(RTCCUINTREG fOrMask, RTCCUINTREG fAndMask)
+{
+#ifdef RT_OS_LINUX
+    return supdrvOSChangeCR4(fOrMask, fAndMask);
+#else
+    RTCCUINTREG uOld = ASMReadCR4();
+    RTCCUINTREG uNew = (uOld & fAndMask) | fOrMask;
+    if (uNew != uOld)
+        ASMSetCR4(uNew);
+    return uOld;
+#endif
+}
+
+
+/**
  * Enables or disabled hardware virtualization extensions using native OS APIs.
  *
Index: trunk/src/VBox/HostDrivers/Support/SUPDrvIOC.h
===================================================================
--- trunk/src/VBox/HostDrivers/Support/SUPDrvIOC.h	(revision 54648)
+++ trunk/src/VBox/HostDrivers/Support/SUPDrvIOC.h	(revision 54650)
@@ -215,5 +215,5 @@
  *          - (nothing)
  */
-#define SUPDRV_IOC_VERSION                              0x001f0003
+#define SUPDRV_IOC_VERSION                              0x001f0004
 
 /** SUP_IOCTL_COOKIE. */
Index: trunk/src/VBox/HostDrivers/Support/SUPDrvInternal.h
===================================================================
--- trunk/src/VBox/HostDrivers/Support/SUPDrvInternal.h	(revision 54648)
+++ trunk/src/VBox/HostDrivers/Support/SUPDrvInternal.h	(revision 54650)
@@ -808,4 +808,5 @@
 bool VBOXCALL   supdrvOSAreTscDeltasInSync(void);
 int  VBOXCALL   supdrvOSEnableVTx(bool fEnabled);
+RTCCUINTREG VBOXCALL supdrvOSChangeCR4(RTCCUINTREG fOrMask, RTCCUINTREG fAndMask);
 bool VBOXCALL   supdrvOSSuspendVTxOnCpu(void);
 void VBOXCALL   supdrvOSResumeVTxOnCpu(bool fSuspended);
Index: trunk/src/VBox/HostDrivers/Support/SUPLib.cpp
===================================================================
--- trunk/src/VBox/HostDrivers/Support/SUPLib.cpp	(revision 54648)
+++ trunk/src/VBox/HostDrivers/Support/SUPLib.cpp	(revision 54650)
@@ -280,5 +280,5 @@
         CookieReq.u.In.u32ReqVersion = SUPDRV_IOC_VERSION;
         const uint32_t uMinVersion = (SUPDRV_IOC_VERSION & 0xffff0000) == 0x001f0000
-                                   ? 0x001f0003
+                                   ? 0x001f0004
                                    : SUPDRV_IOC_VERSION & 0xffff0000;
         CookieReq.u.In.u32MinVersion = uMinVersion;
Index: trunk/src/VBox/HostDrivers/Support/linux/SUPDrv-linux.c
===================================================================
--- trunk/src/VBox/HostDrivers/Support/linux/SUPDrv-linux.c	(revision 54648)
+++ trunk/src/VBox/HostDrivers/Support/linux/SUPDrv-linux.c	(revision 54650)
@@ -69,6 +69,6 @@
 # define SUPDRV_LINUX_HAS_SAFE_MSR_API
 # include <asm/msr.h>
-# include <iprt/asm-amd64-x86.h>
-#endif
+#endif
+#include <iprt/asm-amd64-x86.h>
 
 
@@ -823,4 +823,24 @@
 
 
+RTCCUINTREG VBOXCALL supdrvOSChangeCR4(RTCCUINTREG fOrMask, RTCCUINTREG fAndMask)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 20, 0)
+    RTCCUINTREG uOld = this_cpu_read(cpu_tlbstate.cr4);
+    RTCCUINTREG uNew = (uOld & fAndMask) | fOrMask;
+    if (uNew != uOld)
+    {
+        this_cpu_write(cpu_tlbstate.cr4, uNew);
+        __write_cr4(uNew);
+    }
+#else
+    RTCCUINTREG uOld = ASMGetCR4();
+    RTCCUINTREG uNew = (uOld & fAndMask) | fOrMask;
+    if (uNew != uOld)
+        ASMSetCR4(uNew);
+#endif
+    return uOld;
+}
+
+
 void VBOXCALL supdrvOSCleanupSession(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession)
 {
Index: trunk/src/VBox/Runtime/r0drv/linux/the-linux-kernel.h
===================================================================
--- trunk/src/VBox/Runtime/r0drv/linux/the-linux-kernel.h	(revision 54648)
+++ trunk/src/VBox/Runtime/r0drv/linux/the-linux-kernel.h	(revision 54650)
@@ -141,4 +141,9 @@
 #endif
 
+/* for cr4_init_shadow() / cpu_tlbstate. */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 20, 0)
+# include <asm/tlbflush.h>
+#endif
+
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)
 # ifndef page_to_pfn
Index: trunk/src/VBox/VMM/VMMR0/HMVMXR0.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMR0/HMVMXR0.cpp	(revision 54648)
+++ trunk/src/VBox/VMM/VMMR0/HMVMXR0.cpp	(revision 54650)
@@ -773,12 +773,11 @@
 
     /* Enable the VMX bit in CR4 if necessary. */
-    RTCCUINTREG uCr4 = ASMGetCR4();
-    if (!(uCr4 & X86_CR4_VMXE))
-        ASMSetCR4(uCr4 | X86_CR4_VMXE);
+    RTCCUINTREG uOldCr4 = SUPR0ChangeCR4(X86_CR4_VMXE, ~0);
 
     /* Enter VMX root mode. */
     int rc = VMXEnable(HCPhysCpuPage);
-    if (RT_FAILURE(rc))
-        ASMSetCR4(uCr4);
+    if (   RT_FAILURE(rc)
+        && !(uOldCr4 & X86_CR4_VMXE))
+        SUPR0ChangeCR4(0, ~X86_CR4_VMXE);
 
     /* Restore interrupts. */
@@ -808,5 +807,5 @@
         /* Exit VMX root mode and clear the VMX bit in CR4. */
         VMXDisable();
-        ASMSetCR4(uHostCR4 & ~X86_CR4_VMXE);
+        SUPR0ChangeCR4(0, ~X86_CR4_VMXE);
         rc = VINF_SUCCESS;
     }
@@ -5216,5 +5215,5 @@
     VMXDisable();
 
-    ASMSetCR4(ASMGetCR4() & ~X86_CR4_VMXE);
+    SUPR0ChangeCR4(0, ~X86_CR4_VMXE);
 
     CPUMSetHyperESP(pVCpu, VMMGetStackRC(pVCpu));
@@ -5231,5 +5230,5 @@
     /** @todo replace with hmR0VmxEnterRootMode() and hmR0VmxLeaveRootMode(). */
     /* Make sure the VMX instructions don't cause #UD faults. */
-    ASMSetCR4(ASMGetCR4() | X86_CR4_VMXE);
+    SUPR0ChangeCR4(X86_CR4_VMXE, ~0);
 
     /* Re-enter VMX Root Mode */
@@ -5237,5 +5236,5 @@
     if (RT_FAILURE(rc2))
     {
-        ASMSetCR4(ASMGetCR4() & ~X86_CR4_VMXE);
+        SUPR0ChangeCR4(0, ~X86_CR4_VMXE);
         ASMSetFlags(uOldEflags);
         return rc2;
