Index: trunk/src/VBox/VMM/VMMR3/HM.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMR3/HM.cpp	(revision 107798)
+++ trunk/src/VBox/VMM/VMMR3/HM.cpp	(revision 107801)
@@ -758,5 +758,5 @@
     }
 
-#if defined(RT_ARCH_AMD64) ||defined(RT_ARCH_X86)
+#if defined(RT_ARCH_AMD64) ||defined(RT_ARCH_X86) /* This section is duplicated in nemR3InitFinalizeSpecCtrl. */
     /*
      * Check if L1D flush is needed/possible.
Index: trunk/src/VBox/VMM/VMMR3/NEMR3.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMR3/NEMR3.cpp	(revision 107798)
+++ trunk/src/VBox/VMM/VMMR3/NEMR3.cpp	(revision 107801)
@@ -46,4 +46,5 @@
 #include "NEMInternal.h"
 #include <VBox/vmm/vm.h>
+#include <VBox/vmm/vmcc.h>
 #include <VBox/vmm/uvm.h>
 #include <VBox/err.h>
@@ -106,4 +107,12 @@
                                   "|VTimerInterrupt"
 #endif
+#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
+                                  "|IBPBOnVMExit"
+                                  "|IBPBOnVMEntry"
+                                  "|L1DFlushOnSched"
+                                  "|L1DFlushOnVMEntry"
+                                  "|MDSClearOnSched"
+                                  "|MDSClearOnVMEntry"
+#endif
                                   ,
                                   "" /* pszValidNodes */, "NEM" /* pszWho */, 0 /* uInstance */);
@@ -139,4 +148,53 @@
         pVCpu->nem.s.fTrapXcptGpForLovelyMesaDrv = f;
     }
+
+#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
+    /** @cfgm{/NEM/IBPBOnVMExit, bool}
+     * Costly paranoia setting. */
+    rc = CFGMR3QueryBoolDef(pCfgNem, "IBPBOnVMExit", &f, false);
+    AssertLogRelRCReturn(rc, rc);
+    VMCC_FOR_EACH_VMCPU_STMT(pVM, pVCpu->nem.s.fIbpbOnVmExit = f);
+
+    /** @cfgm{/NEM/IBPBOnVMEntry, bool}
+     * Costly paranoia setting. */
+    rc = CFGMR3QueryBoolDef(pCfgNem, "IBPBOnVMEntry", &f, false);
+    AssertLogRelRCReturn(rc, rc);
+    VMCC_FOR_EACH_VMCPU_STMT(pVM, pVCpu->nem.s.fIbpbOnVmEntry = f);
+
+    /** @cfgm{/NEM/L1DFlushOnSched, bool, true}
+     * CVE-2018-3646 workaround, ignored on CPUs that aren't affected. */
+    rc = CFGMR3QueryBoolDef(pCfgNem, "L1DFlushOnSched", &f, true);
+    AssertLogRelRCReturn(rc, rc);
+    VMCC_FOR_EACH_VMCPU_STMT(pVM, pVCpu->nem.s.fL1dFlushOnSched = f);
+
+    /** @cfgm{/NEM/L1DFlushOnVMEntry, bool}
+     * CVE-2018-3646 workaround, ignored on CPUs that aren't affected. */
+    rc = CFGMR3QueryBoolDef(pCfgNem, "L1DFlushOnVMEntry", &f, false);
+    AssertLogRelRCReturn(rc, rc);
+    VMCC_FOR_EACH_VMCPU_STMT(pVM, pVCpu->nem.s.fL1dFlushOnVmEntry = f);
+
+    /* Disable L1DFlushOnSched if L1DFlushOnVMEntry is enabled. */
+    PVMCPU const pVCpu0 = pVM->apCpusR3[0];
+    if (pVCpu0->nem.s.fL1dFlushOnVmEntry)
+        VMCC_FOR_EACH_VMCPU_STMT(pVM, pVCpu->nem.s.fL1dFlushOnSched = false);
+
+    /** @cfgm{/NEM/MDSClearOnSched, bool, true}
+     * CVE-2018-12126, CVE-2018-12130, CVE-2018-12127, CVE-2019-11091 workaround,
+     * ignored on CPUs that aren't affected. */
+    rc = CFGMR3QueryBoolDef(pCfgNem, "MDSClearOnSched", &f, true);
+    AssertLogRelRCReturn(rc, rc);
+    VMCC_FOR_EACH_VMCPU_STMT(pVM, pVCpu->nem.s.fMdsClearOnSched = f);
+
+    /** @cfgm{/NEM/MDSClearOnVmEntry, bool, false}
+     * CVE-2018-12126, CVE-2018-12130, CVE-2018-12127, CVE-2019-11091 workaround,
+     * ignored on CPUs that aren't affected. */
+    rc = CFGMR3QueryBoolDef(pCfgNem, "MDSClearOnVmEntry", &f, false);
+    AssertLogRelRCReturn(rc, rc);
+    VMCC_FOR_EACH_VMCPU_STMT(pVM, pVCpu->nem.s.fMdsClearOnVmEntry = f);
+
+    /* Disable MDSClearOnSched if MDSClearOnVmEntry is enabled. */
+    if (pVCpu0->nem.s.fMdsClearOnVmEntry)
+        VMCC_FOR_EACH_VMCPU_STMT(pVM, pVCpu->nem.s.fMdsClearOnSched = false);
+#endif /* VBOX_VMM_TARGET_X86 */
 
 #ifdef VBOX_VMM_TARGET_ARMV8
@@ -219,4 +277,50 @@
 
 
+#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
+/**
+ * Finalize configuration related to spectre and such.
+ *
+ * This can be called explicitly by the native code after it has seeded the
+ * necessary host information to CPUM, or/and it will be called by
+ * NEMR3InitAfterCPUM().
+ *
+ * @note This code is also duplicated in hmR3InitFinalizeR3().
+ */
+DECLHIDDEN(void) nemR3InitFinalizeSpecCtrl(PVM pVM)
+{
+    /*
+     * Check if L1D flush is needed/possible.
+     */
+    if (   !g_CpumHostFeatures.s.fFlushCmd
+        || g_CpumHostFeatures.s.enmMicroarch <  kCpumMicroarch_Intel_Core7_Nehalem
+        || g_CpumHostFeatures.s.enmMicroarch >= kCpumMicroarch_Intel_Core7_End
+        || g_CpumHostFeatures.s.fArchVmmNeedNotFlushL1d
+        || g_CpumHostFeatures.s.fArchRdclNo)
+        VMCC_FOR_EACH_VMCPU_STMT(pVM, pVCpu->nem.s.fL1dFlushOnSched = pVCpu->nem.s.fL1dFlushOnVmEntry = false);
+
+    /*
+     * Check if MDS flush is needed/possible.
+     * On atoms and knight family CPUs, we will only allow clearing on scheduling.
+     */
+    if (   !g_CpumHostFeatures.s.fMdsClear
+        || g_CpumHostFeatures.s.fArchMdsNo)
+        VMCC_FOR_EACH_VMCPU_STMT(pVM, pVCpu->nem.s.fMdsClearOnSched = pVCpu->nem.s.fMdsClearOnVmEntry = false);
+    else if (   (   g_CpumHostFeatures.s.enmMicroarch >=  kCpumMicroarch_Intel_Atom_Airmount
+                 && g_CpumHostFeatures.s.enmMicroarch <   kCpumMicroarch_Intel_Atom_End)
+             || (   g_CpumHostFeatures.s.enmMicroarch >=  kCpumMicroarch_Intel_Phi_KnightsLanding
+                 && g_CpumHostFeatures.s.enmMicroarch <   kCpumMicroarch_Intel_Phi_End))
+    {
+        PVMCPU const pVCpu0 = pVM->apCpusR3[0];
+        if (!pVCpu0->nem.s.fMdsClearOnSched)
+            VMCC_FOR_EACH_VMCPU_STMT(pVM, pVCpu->nem.s.fMdsClearOnSched = pVCpu->nem.s.fMdsClearOnVmEntry);
+        VMCC_FOR_EACH_VMCPU_STMT(pVM, pVCpu->nem.s.fMdsClearOnVmEntry = false);
+    }
+    else if (   g_CpumHostFeatures.s.enmMicroarch <  kCpumMicroarch_Intel_Core7_Nehalem
+             || g_CpumHostFeatures.s.enmMicroarch >= kCpumMicroarch_Intel_Core7_End)
+        VMCC_FOR_EACH_VMCPU_STMT(pVM, pVCpu->nem.s.fMdsClearOnSched = pVCpu->nem.s.fMdsClearOnVmEntry = false);
+}
+#endif
+
+
 /**
  * Perform initialization that depends on CPUM working.
@@ -235,4 +339,7 @@
          * Do native after-CPUM init.
          */
+#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
+        nemR3InitFinalizeSpecCtrl(pVM);
+#endif
 #ifdef VBOX_WITH_NATIVE_NEM
         rc = nemR3NativeInitAfterCPUM(pVM);
Index: trunk/src/VBox/VMM/VMMR3/NEMR3Native-darwin.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMR3/NEMR3Native-darwin.cpp	(revision 107798)
+++ trunk/src/VBox/VMM/VMMR3/NEMR3Native-darwin.cpp	(revision 107801)
@@ -3676,6 +3676,14 @@
 {
     TMNotifyStartOfExecution(pVM, pVCpu);
-
     Assert(!pVCpu->nem.s.fCtxChanged);
+
+    if (!(pVCpu->nem.s.fMdsClearOnVmEntry | pVCpu->nem.s.fMdsClearOnVmEntry))
+    { /* likely*/ }
+    else
+    {
+        uint16_t u16 = ASMGetDS();
+        __asm__ __volatile__("verw %0" : "=m" (u16) : "0" (u16));
+    }
+
     hv_return_t hrc;
     if (hv_vcpu_run_until) /** @todo Configur the deadline dynamically based on when the next timer triggers. */
Index: trunk/src/VBox/VMM/include/NEMInternal.h
===================================================================
--- trunk/src/VBox/VMM/include/NEMInternal.h	(revision 107798)
+++ trunk/src/VBox/VMM/include/NEMInternal.h	(revision 107801)
@@ -424,4 +424,18 @@
     /** Whether \#DE needs to be intercepted for GIM. */
     bool                        fGCMTrapXcptDE : 1;
+#ifdef VBOX_VMM_TARGET_X86
+    /** Set if indirect branch prediction barrier on VM exit. */
+    bool                        fIbpbOnVmExit : 1;
+    /** Set if indirect branch prediction barrier on VM entry. */
+    bool                        fIbpbOnVmEntry : 1;
+    /** Set if level 1 data cache should be flushed on VM entry. */
+    bool                        fL1dFlushOnVmEntry : 1;
+    /** Set if level 1 data cache should be flushed on EMT scheduling. */
+    bool                        fL1dFlushOnSched : 1;
+    /** Set if MDS related buffers should be cleared on VM entry. */
+    bool                        fMdsClearOnVmEntry : 1;
+    /** Set if MDS related buffers should be cleared on EMT scheduling. */
+    bool                        fMdsClearOnSched : 1;
+#endif
 
 #if defined(RT_OS_LINUX)
