Index: trunk/src/VBox/VMM/VMMR3/HM.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMR3/HM.cpp	(revision 70917)
+++ trunk/src/VBox/VMM/VMMR3/HM.cpp	(revision 70918)
@@ -51,4 +51,5 @@
 #include <VBox/vmm/csam.h>
 #include <VBox/vmm/selm.h>
+#include <VBox/vmm/nem.h>
 #ifdef VBOX_WITH_REM
 # include <VBox/vmm/rem.h>
@@ -394,8 +395,14 @@
  * Initializes the HM.
  *
- * This reads the config and check whether VT-x or AMD-V hardware is available
- * if configured to use it.  This is one of the very first components to be
- * initialized after CFGM, so that we can fall back to raw-mode early in the
- * initialization process.
+ * This is the very first component to really do init after CFGM so that we can
+ * establish the predominat execution engine for the VM prior to initializing
+ * other modules.  It takes care of NEM initialization if needed (HM disabled or
+ * not available in HW).
+ *
+ * If VT-x or AMD-V hardware isn't available, HM will try fall back on a native
+ * hypervisor API via NEM, and then back on raw-mode if that isn't available
+ * either.  The fallback to raw-mode will not happen if /HM/HMForced is set
+ * (like for guest using SMP or 64-bit as well as for complicated guest like OS
+ * X, OS/2 and others).
  *
  * Note that a lot of the set up work is done in ring-0 and thus postponed till
@@ -449,4 +456,6 @@
     rc = CFGMR3ValidateConfig(pCfgHm, "/HM/",
                               "HMForced"
+                              "|UseNEMInstead"
+                              "|FallbackToNEM"
                               "|EnableNestedPaging"
                               "|EnableUX"
@@ -492,4 +501,21 @@
 #endif /* !VBOX_WITH_RAW_MODE */
 
+    /** @cfgm{/HM/UseNEMInstead, bool, true}
+     * Don't use HM, use NEM instead. */
+    bool fUseNEMInstead = false;
+    rc = CFGMR3QueryBoolDef(pCfgHm, "UseNEMInstead", &fUseNEMInstead, false);
+    AssertRCReturn(rc, rc);
+    if (fUseNEMInstead && pVM->fHMEnabled)
+    {
+        LogRel(("HM: Setting fHMEnabled to false because fUseNEMInstead is set.\n"));
+        pVM->fHMEnabled = false;
+    }
+
+    /** @cfgm{/HM/FallbackToNEM, bool, true}
+     * Enables fallback on NEM. */
+    bool fFallbackToNEM = true;
+    rc = CFGMR3QueryBoolDef(pCfgHm, "FallbackToNEM", &fFallbackToNEM, true);
+    AssertRCReturn(rc, rc);
+
     /** @cfgm{/HM/EnableNestedPaging, bool, false}
      * Enables nested paging (aka extended page tables). */
@@ -643,5 +669,6 @@
             else if (fCaps & SUPVTCAPS_VT_X)
             {
-                rc = SUPR3QueryVTxSupported();
+                const char *pszWhy;
+                rc = SUPR3QueryVTxSupported(&pszWhy);
                 if (RT_SUCCESS(rc))
                 {
@@ -654,15 +681,24 @@
                 else
                 {
-#ifdef RT_OS_LINUX
-                    const char *pszMinReq = " Linux 2.6.13 or newer required!";
-#else
-                    const char *pszMinReq = "";
-#endif
-                    if (fHMForced)
-                        return VMSetError(pVM, rc, RT_SRC_POS, "The host kernel does not support VT-x.%s\n", pszMinReq);
-
-                    /* Fall back to raw-mode. */
-                    LogRel(("HM: HMR3Init: Falling back to raw-mode: The host kernel does not support VT-x.%s\n", pszMinReq));
+                    /*
+                     * Before failing, try fallback to NEM if we're allowed to do that.
+                     */
                     pVM->fHMEnabled = false;
+                    if (fFallbackToNEM)
+                    {
+                        LogRel(("HM: HMR3Init: Attempting fall back to NEM: The host kernel does not support VT-x - %s\n", pszWhy));
+                        int rc2 = NEMR3Init(pVM, true /*fFallback*/, fHMForced);
+                        if (   RT_SUCCESS(rc2)
+                            && pVM->fNEMActive)
+                            rc = VINF_SUCCESS;
+                    }
+                    if (RT_FAILURE(rc))
+                    {
+                        if (fHMForced)
+                            return VMSetError(pVM, rc, RT_SRC_POS, "The host kernel does not support VT-x: %s\n", pszWhy);
+
+                        /* Fall back to raw-mode. */
+                        LogRel(("HM: HMR3Init: Falling back to raw-mode: The host kernel does not support VT-x - %s\n", pszWhy));
+                    }
                 }
             }
@@ -738,16 +774,36 @@
 
                 default:
-                    pszMsg = NULL;
-                    break;
+                    return VMSetError(pVM, rc, RT_SRC_POS, "SUPR3QueryVTCaps failed with %Rrc", rc);
             }
-            if (fHMForced && pszMsg)
-                return VM_SET_ERROR(pVM, rc, pszMsg);
-            if (!pszMsg)
-                return VMSetError(pVM, rc, RT_SRC_POS, "SUPR3QueryVTCaps failed with %Rrc", rc);
-
-            /* Fall back to raw-mode. */
-            LogRel(("HM: HMR3Init: Falling back to raw-mode: %s\n", pszMsg));
+
+            /*
+             * Before failing, try fallback to NEM if we're allowed to do that.
+             */
             pVM->fHMEnabled = false;
+            if (fFallbackToNEM)
+            {
+                LogRel(("HM: HMR3Init: Attempting fall back to NEM: %s\n", pszMsg));
+                int rc2 = NEMR3Init(pVM, true /*fFallback*/, fHMForced);
+                if (   RT_SUCCESS(rc2)
+                    && pVM->fNEMActive)
+                    rc = VINF_SUCCESS;
+            }
+            if (RT_FAILURE(rc))
+            {
+                if (fHMForced)
+                    return VM_SET_ERROR(pVM, rc, pszMsg);
+
+                LogRel(("HM: HMR3Init: Falling back to raw-mode: %s\n", pszMsg));
+            }
         }
+    }
+    /*
+     * If NEM is supposed to be used instead, initialize it instead.
+     */
+    else if (fUseNEMInstead)
+    {
+        rc = NEMR3Init(pVM, false /*fFallback*/, fHMForced);
+        if (RT_FAILURE(rc))
+            return rc;
     }
 
Index: trunk/src/VBox/VMM/VMMR3/NEMR3.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMR3/NEMR3.cpp	(revision 70918)
+++ trunk/src/VBox/VMM/VMMR3/NEMR3.cpp	(revision 70918)
@@ -0,0 +1,211 @@
+/* $Id$ */
+/** @file
+ * NEM - Native execution manager.
+ */
+
+/*
+ * Copyright (C) 2018 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+/** @page pg_nem NEM - Native Execution Manager.
+ *
+ * Later.
+ *
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#define LOG_GROUP LOG_GROUP_NEM
+#include <VBox/vmm/nem.h>
+#include "NEMInternal.h"
+#include <VBox/vmm/vm.h>
+
+
+
+/**
+ * Basic init and configuration reading.
+ *
+ * Always call NEMR3Term after calling this.
+ *
+ * @returns VBox status code.
+ * @param   pVM         The VM handle.
+ */
+VMMR3_INT_DECL(int) NEMR3InitConfig(PVM pVM)
+{
+    LogFlow(("NEMR3Init\n"));
+
+    /*
+     * Assert alignment and sizes.
+     */
+    AssertCompileMemberAlignment(VM, nem.s, 64);
+    AssertCompile(sizeof(pVM->nem.s) <= sizeof(pVM->nem.padding));
+
+    /*
+     * Initialize state info so NEMR3Term will always be happy.
+     * No returning prior to setting magics!
+     */
+    pVM->nem.s.u32Magic = NEM_MAGIC;
+    for (VMCPUID iCpu = 0; iCpu < pVM->cCpus; iCpu++)
+        pVM->aCpus[iCpu].nem.s.u32Magic = NEMCPU_MAGIC;
+
+    /*
+     * Read configuration.
+     */
+    PCFGMNODE pCfgNem = CFGMR3GetChild(CFGMR3GetRoot(pVM), "NEM/");
+
+    /*
+     * Validate the NEM settings.
+     */
+    int rc = CFGMR3ValidateConfig(pCfgNem,
+                                  "/NEM/",
+                                  "Enabled",
+                                  "" /* pszValidNodes */, "NEM" /* pszWho */, 0 /* uInstance */);
+    if (RT_FAILURE(rc))
+        return rc;
+
+    /** @cfgm{/NEM/NEMEnabled, bool, true}
+     * Whether NEM is enabled. */
+    rc = CFGMR3QueryBoolDef(pCfgNem, "Enabled", &pVM->nem.s.fEnabled, true);
+    AssertLogRelRCReturn(rc, rc);
+
+    return VINF_SUCCESS;
+}
+
+
+/**
+ * This is called by HMR3Init() when HM cannot be used.
+ *
+ * Sets VM::fNEMActive if we can use a native hypervisor API to execute the VM.
+ *
+ * @returns VBox status code.
+ * @param   pVM         The VM handle.
+ * @param   fFallback   Whether this is a fallback call.  Cleared if the VM is
+ *                      configured to use NEM instead of HM.
+ * @param   fForced     Whether /HM/HMForced was set.  If set and we fail to
+ *                      enable NEM, we'll return a failure status code.
+ *                      Otherwise we'll assume HMR3Init falls back on raw-mode.
+ */
+VMMR3_INT_DECL(int) NEMR3Init(PVM pVM, bool fFallback, bool fForced)
+{
+    Assert(!pVM->fNEMActive);
+    int rc;
+    if (pVM->nem.s.fEnabled)
+    {
+#ifdef VBOX_WITH_NATIVE_NEM
+        rc = nemR3NativeInit(pVM, fFallback, fForced);
+#else
+        RT_NOREF(fFallback);
+        rc = VINF_SUCCESS;
+#endif
+        if (RT_SUCCESS(rc))
+        {
+            if (pVM->fNEMActive)
+                LogRel(("NEM: NEMR3Init: Active.\n"));
+            else
+            {
+                LogRel(("NEM: NEMR3Init: Not available.\n"));
+                if (fForced)
+                    rc = VERR_NEM_NOT_AVAILABLE;
+            }
+        }
+        else
+            LogRel(("NEM: NEMR3Init: Native init failed: %Rrc.\n", rc));
+    }
+    else
+    {
+        LogRel(("NEM: NEMR3Init: Disabled.\n"));
+        rc = fForced ? VERR_NEM_NOT_ENABLED : VINF_SUCCESS;
+    }
+    return rc;
+}
+
+
+/**
+ * Called when a init phase has completed.
+ *
+ * @returns VBox status code.
+ * @param   pVM                 The cross context VM structure.
+ * @param   enmWhat             The phase that completed.
+ */
+VMMR3_INT_DECL(int) NEMR3InitCompleted(PVM pVM, VMINITCOMPLETED enmWhat)
+{
+    int rc = VINF_SUCCESS;
+#ifdef VBOX_WITH_NATIVE_NEM
+    if (pVM->fNEMActive)
+        rc = nemR3NativeInitCompleted(pVM, enmWhat);
+#else
+    RT_NOREF(pVM, enmWhat);
+#endif
+    return rc;
+}
+
+
+/**
+ *
+ * @returns VBox status code.
+ * @param   pVM         The VM handle.
+ */
+VMMR3_INT_DECL(int) NEMR3Term(PVM pVM)
+{
+    AssertReturn(pVM->nem.s.u32Magic == NEM_MAGIC, VERR_WRONG_ORDER);
+    for (VMCPUID iCpu = 0; iCpu < pVM->cCpus; iCpu++)
+        AssertReturn(pVM->aCpus[iCpu].nem.s.u32Magic == NEMCPU_MAGIC, VERR_WRONG_ORDER);
+
+    /* Do native termination. */
+    int rc = VINF_SUCCESS;
+#ifdef VBOX_WITH_NATIVE_NEM
+    if (pVM->fNEMActive)
+        rc = nemR3NativeTerm(pVM);
+#endif
+
+    /* Mark it as terminated. */
+    for (VMCPUID iCpu = 0; iCpu < pVM->cCpus; iCpu++)
+        pVM->aCpus[iCpu].nem.s.u32Magic = NEMCPU_MAGIC_DEAD;
+    pVM->nem.s.u32Magic = NEM_MAGIC_DEAD;
+    return rc;
+}
+
+
+/**
+ * The VM is being reset.
+ *
+ * @param   pVM     The cross context VM structure.
+ */
+VMMR3_INT_DECL(void) NEMR3Reset(PVM pVM)
+{
+#ifdef VBOX_WITH_NATIVE_NEM
+    if (pVM->fNEMActive)
+        nemR3NativeReset(pVM);
+#else
+    RT_NOREF(pVM);
+#endif
+}
+
+
+/**
+ * Resets a virtual CPU.
+ *
+ * Used to bring up secondary CPUs on SMP as well as CPU hot plugging.
+ *
+ * @param   pVCpu   The cross context virtual CPU structure to reset.
+ */
+VMMR3_INT_DECL(void) NEMR3ResetCpu(PVMCPU pVCpu)
+{
+#ifdef VBOX_WITH_NATIVE_NEM
+    if (pVCpu->pVMR3->fNEMActive)
+        nemR3NativeResetCpu(pVCpu);
+#else
+    RT_NOREF(pVCpu);
+#endif
+}
+
Index: trunk/src/VBox/VMM/VMMR3/NEMR3Native-win.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMR3/NEMR3Native-win.cpp	(revision 70918)
+++ trunk/src/VBox/VMM/VMMR3/NEMR3Native-win.cpp	(revision 70918)
@@ -0,0 +1,60 @@
+/* $Id$ */
+/** @file
+ * NEM - Native execution manager, native ring-3 Windows backend.
+ */
+
+/*
+ * Copyright (C) 2018 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+
+/*********************************************************************************************************************************
+*   Header Files                                                                                                                 *
+*********************************************************************************************************************************/
+#define LOG_GROUP LOG_GROUP_NEM
+#include <VBox/vmm/nem.h>
+#include "NEMInternal.h"
+#include <VBox/vmm/vm.h>
+
+
+
+int nemR3NativeInit(PVM pVM, bool fFallback, bool fForced)
+{
+    NOREF(pVM); NOREF(fFallback); NOREF(fForced);
+    return VINF_SUCCESS;
+}
+
+
+int nemR3NativeInitCompleted(PVM pVM, VMINITCOMPLETED enmWhat)
+{
+    NOREF(pVM); NOREF(enmWhat);
+    return VINF_SUCCESS;
+}
+
+
+int nemR3NativeTerm(PVM pVM)
+{
+    NOREF(pVM);
+    return VINF_SUCCESS;
+}
+
+
+void nemR3NativeReset(PVM pVM)
+{
+    NOREF(pVM);
+}
+
+
+void nemR3NativeResetCpu(PVMCPU pVCpu)
+{
+    NOREF(pVCpu);
+}
+
Index: trunk/src/VBox/VMM/VMMR3/VM.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMR3/VM.cpp	(revision 70917)
+++ trunk/src/VBox/VMM/VMMR3/VM.cpp	(revision 70918)
@@ -61,4 +61,5 @@
 # include <VBox/vmm/rem.h>
 #endif
+#include <VBox/vmm/nem.h>
 #include <VBox/vmm/apic.h>
 #include <VBox/vmm/tm.h>
@@ -925,7 +926,9 @@
     /*
      * Init all R3 components, the order here might be important.
-     * HM shall be initialized first!
-     */
-    rc = HMR3Init(pVM);
+     * NEM and HM shall be initialized first!
+     */
+    rc = NEMR3InitConfig(pVM);
+    if (RT_SUCCESS(rc))
+        rc = HMR3Init(pVM);
     if (RT_SUCCESS(rc))
     {
@@ -1076,5 +1079,5 @@
         AssertRC(rc2);
     }
-
+    NEMR3Term(pVM);
 
     LogFlow(("vmR3InitRing3: returns %Rrc\n", rc));
@@ -1168,4 +1171,6 @@
     if (RT_SUCCESS(rc))
         rc = HMR3InitCompleted(pVM, enmWhat);
+    if (RT_SUCCESS(rc))
+        rc = NEMR3InitCompleted(pVM, enmWhat);
     if (RT_SUCCESS(rc))
         rc = PGMR3InitCompleted(pVM, enmWhat);
@@ -2516,4 +2521,6 @@
         rc = HMR3Term(pVM);
         AssertRC(rc);
+        rc = NEMR3Term(pVM);
+        AssertRC(rc);
         rc = PGMR3Term(pVM);
         AssertRC(rc);
@@ -2804,4 +2811,5 @@
         EMR3Reset(pVM);
         HMR3Reset(pVM);                 /* This must come *after* PATM, CSAM, CPUM, SELM and TRPM. */
+        NEMR3Reset(pVM);
 
         /*
@@ -2907,4 +2915,5 @@
         EMR3Reset(pVM);
         HMR3Reset(pVM);                 /* This must come *after* PATM, CSAM, CPUM, SELM and TRPM. */
+        NEMR3Reset(pVM);
 
         /*
@@ -4632,4 +4641,5 @@
     EMR3ResetCpu(pVCpu);
     HMR3ResetCpu(pVCpu);
+    NEMR3ResetCpu(pVCpu);
     return VINF_EM_WAIT_SIPI;
 }
Index: trunk/src/VBox/VMM/VMMR3/VMM.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMR3/VMM.cpp	(revision 70917)
+++ trunk/src/VBox/VMM/VMMR3/VMM.cpp	(revision 70918)
@@ -112,4 +112,5 @@
 #include <VBox/vmm/gim.h>
 #include <VBox/vmm/mm.h>
+#include <VBox/vmm/nem.h>
 #include <VBox/vmm/iom.h>
 #include <VBox/vmm/trpm.h>
@@ -1494,4 +1495,5 @@
     EMR3ResetCpu(pVCpu);
     HMR3ResetCpu(pVCpu);
+    NEMR3ResetCpu(pVCpu);
 
     /* This will trickle up on the target EMT. */
