Index: trunk/src/VBox/VMM/VMMR3/CPUM.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMR3/CPUM.cpp	(revision 91119)
+++ trunk/src/VBox/VMM/VMMR3/CPUM.cpp	(revision 91120)
@@ -1753,4 +1753,5 @@
 
     /* VPID and EPT Capabilities. */
+    if (pGuestFeatures->fVmxEpt)
     {
         /*
@@ -1764,9 +1765,38 @@
          * See Intel spec. 30.3 "VMX Instructions".
          */
-        uint8_t const fVpid = pGuestFeatures->fVmxVpid;
-        pGuestVmxMsrs->u64EptVpidCaps = RT_BF_MAKE(VMX_BF_EPT_VPID_CAP_INVVPID,                           fVpid)
-                                      | RT_BF_MAKE(VMX_BF_EPT_VPID_CAP_INVVPID_SINGLE_CTX,                fVpid & 1)
-                                      | RT_BF_MAKE(VMX_BF_EPT_VPID_CAP_INVVPID_ALL_CTX,                   fVpid & 1)
-                                      | RT_BF_MAKE(VMX_BF_EPT_VPID_CAP_INVVPID_SINGLE_CTX_RETAIN_GLOBALS, fVpid & 1);
+        uint64_t const uHostMsr = fIsNstGstHwExecAllowed ? pHostVmxMsrs->u64EptVpidCaps : UINT64_MAX;
+        uint8_t const  fVpid    = pGuestFeatures->fVmxVpid;
+
+        uint8_t const  fExecOnly         = RT_BF_GET(uHostMsr, VMX_BF_EPT_VPID_CAP_RWX_X_ONLY);
+        uint8_t const  fPml4             = RT_BF_GET(uHostMsr, VMX_BF_EPT_VPID_CAP_PAGE_WALK_LENGTH_4);
+        uint8_t const  fEptMemUc         = RT_BF_GET(uHostMsr, VMX_BF_EPT_VPID_CAP_EMT_UC);
+        uint8_t const  fEptMemWb         = RT_BF_GET(uHostMsr, VMX_BF_EPT_VPID_CAP_EMT_WB);
+        uint8_t const  f2MPage           = RT_BF_GET(uHostMsr, VMX_BF_EPT_VPID_CAP_PDE_2M);
+        uint8_t const  f1GPage           = RT_BF_GET(uHostMsr, VMX_BF_EPT_VPID_CAP_PDPTE_1G);
+        uint8_t const  fInvept           = RT_BF_GET(uHostMsr, VMX_BF_EPT_VPID_CAP_INVEPT);
+        uint8_t const  fEptAccDirty      = RT_BF_GET(uHostMsr, VMX_BF_EPT_VPID_CAP_EPT_ACCESS_DIRTY);
+        uint8_t const  fEptSingle        = RT_BF_GET(uHostMsr, VMX_BF_EPT_VPID_CAP_INVEPT_SINGLE_CTX);
+        uint8_t const  fEptAll           = RT_BF_GET(uHostMsr, VMX_BF_EPT_VPID_CAP_INVEPT_ALL_CTX);
+        uint8_t const  fVpidIndiv        = RT_BF_GET(uHostMsr, VMX_BF_EPT_VPID_CAP_INVVPID_INDIV_ADDR);
+        uint8_t const  fVpidSingle       = RT_BF_GET(uHostMsr, VMX_BF_EPT_VPID_CAP_INVVPID_SINGLE_CTX);
+        uint8_t const  fVpidAll          = RT_BF_GET(uHostMsr, VMX_BF_EPT_VPID_CAP_INVVPID_ALL_CTX);
+        uint8_t const  fVpidSingleGlobal = RT_BF_GET(uHostMsr, VMX_BF_EPT_VPID_CAP_INVVPID_SINGLE_CTX_RETAIN_GLOBALS);
+        pGuestVmxMsrs->u64EptVpidCaps = RT_BF_MAKE(VMX_BF_EPT_VPID_CAP_RWX_X_ONLY,                        fExecOnly)
+                                      | RT_BF_MAKE(VMX_BF_EPT_VPID_CAP_PAGE_WALK_LENGTH_4,                fPml4)
+                                      | RT_BF_MAKE(VMX_BF_EPT_VPID_CAP_EMT_UC,                            fEptMemUc)
+                                      | RT_BF_MAKE(VMX_BF_EPT_VPID_CAP_EMT_WB,                            fEptMemWb)
+                                      | RT_BF_MAKE(VMX_BF_EPT_VPID_CAP_PDE_2M,                            f2MPage)
+                                      | RT_BF_MAKE(VMX_BF_EPT_VPID_CAP_PDPTE_1G,                          f1GPage)
+                                      | RT_BF_MAKE(VMX_BF_EPT_VPID_CAP_INVEPT,                            fInvept)
+                                      | RT_BF_MAKE(VMX_BF_EPT_VPID_CAP_EPT_ACCESS_DIRTY,                  fEptAccDirty)
+                                      | RT_BF_MAKE(VMX_BF_EPT_VPID_CAP_ADVEXITINFO_EPT,                   0)
+                                      | RT_BF_MAKE(VMX_BF_EPT_VPID_CAP_SUPER_SHW_STACK,                   0)
+                                      | RT_BF_MAKE(VMX_BF_EPT_VPID_CAP_INVEPT_SINGLE_CTX,                 fEptSingle)
+                                      | RT_BF_MAKE(VMX_BF_EPT_VPID_CAP_INVEPT_ALL_CTX,                    fEptAll)
+                                      | RT_BF_MAKE(VMX_BF_EPT_VPID_CAP_INVVPID,                           fVpid)
+                                      | RT_BF_MAKE(VMX_BF_EPT_VPID_CAP_INVVPID_INDIV_ADDR,                fVpid & fVpidIndiv)
+                                      | RT_BF_MAKE(VMX_BF_EPT_VPID_CAP_INVVPID_SINGLE_CTX,                fVpid & fVpidSingle)
+                                      | RT_BF_MAKE(VMX_BF_EPT_VPID_CAP_INVVPID_ALL_CTX,                   fVpid & fVpidAll)
+                                      | RT_BF_MAKE(VMX_BF_EPT_VPID_CAP_INVVPID_SINGLE_CTX_RETAIN_GLOBALS, fVpid & fVpidSingleGlobal);
     }
 
@@ -1902,4 +1932,16 @@
 
     /*
+     * While it would be nice to check this earlier while initializing fNestedVmxEpt
+     * but we would not have enumearted host features then, so do it at least now.
+     */
+    if (   !pVM->cpum.s.HostFeatures.fNoExecute
+        && pVM->cpum.s.fNestedVmxEpt)
+    {
+        LogRel(("CPUM: Warning! EPT not exposed to the guest since NX isn't available on the host.\n"));
+        pVM->cpum.s.fNestedVmxEpt               = false;
+        pVM->cpum.s.fNestedVmxUnrestrictedGuest = false;
+    }
+
+    /*
      * Initialize the set of VMX features we emulate.
      *
@@ -1914,5 +1956,5 @@
     EmuFeat.fVmxNmiExit               = 1;
     EmuFeat.fVmxVirtNmi               = 1;
-    EmuFeat.fVmxPreemptTimer          = 0;  /* Currently disabled on purpose, see @bugref{9180#c108}. */
+    EmuFeat.fVmxPreemptTimer          = 0;  /* pVM->cpum.s.fNestedVmxPreemptTimer -- Currently disabled on purpose, see @bugref{9180#c108}. */
     EmuFeat.fVmxPostedInt             = 0;
     EmuFeat.fVmxIntWindowExit         = 1;
@@ -1939,11 +1981,11 @@
     EmuFeat.fVmxSecondaryExecCtls     = 1;
     EmuFeat.fVmxVirtApicAccess        = 1;
-    EmuFeat.fVmxEpt                   = 0;  /* Cannot be disabled if unrestricted guest is enabled. */
+    EmuFeat.fVmxEpt                   = pVM->cpum.s.fNestedVmxEpt;
     EmuFeat.fVmxDescTableExit         = 1;
     EmuFeat.fVmxRdtscp                = 1;
     EmuFeat.fVmxVirtX2ApicMode        = 0;
-    EmuFeat.fVmxVpid                  = 0;  /** @todo NSTVMX: enable this. */
+    EmuFeat.fVmxVpid                  = EmuFeat.fVmxEpt;
     EmuFeat.fVmxWbinvdExit            = 1;
-    EmuFeat.fVmxUnrestrictedGuest     = 0;
+    EmuFeat.fVmxUnrestrictedGuest     = pVM->cpum.s.fNestedVmxUnrestrictedGuest;
     EmuFeat.fVmxApicRegVirt           = 0;
     EmuFeat.fVmxVirtIntDelivery       = 0;
@@ -2051,13 +2093,14 @@
     pGuestFeat->fVmxEntryInjectSoftInt    = (pBaseFeat->fVmxEntryInjectSoftInt    & EmuFeat.fVmxEntryInjectSoftInt   );
 
-    if (   !pVM->cpum.s.fNestedVmxPreemptTimer
-        || HMIsSubjectToVmxPreemptTimerErratum())
-    {
-        LogRel(("CPUM: Warning! VMX-preemption timer not exposed to guest due to forced CFGM setting or CPU erratum.\n"));
+    /* Don't expose VMX preemption timer if host is subject to VMX-preemption timer erratum. */
+    if (   pGuestFeat->fVmxPreemptTimer
+        && HMIsSubjectToVmxPreemptTimerErratum())
+    {
+        LogRel(("CPUM: Warning! VMX-preemption timer not exposed to guest due to host CPU erratum.\n"));
         pGuestFeat->fVmxPreemptTimer     = 0;
         pGuestFeat->fVmxSavePreemptTimer = 0;
     }
 
-    /* Paranoia. */
+    /* Sanity checking. */
     if (!pGuestFeat->fVmxSecondaryExecCtls)
     {
@@ -2083,11 +2126,14 @@
         Assert(!pGuestFeat->fVmxUseTscScaling);
     }
+    else if (pGuestFeat->fVmxUnrestrictedGuest)
+    {
+        /* See footnote in Intel spec. 27.2 "Recording VM-Exit Information And Updating VM-entry Control Fields". */
+        Assert(pGuestFeat->fVmxExitSaveEferLma);
+        /* Unrestricted guest execution requires EPT. See Intel spec. 25.2.1.1 "VM-Execution Control Fields". */
+        Assert(pGuestFeat->fVmxEpt);
+    }
+
     if (!pGuestFeat->fVmxTertiaryExecCtls)
         Assert(!pGuestFeat->fVmxLoadIwKeyExit);
-    if (pGuestFeat->fVmxUnrestrictedGuest)
-    {
-        /* See footnote in Intel spec. 27.2 "Recording VM-Exit Information And Updating VM-entry Control Fields". */
-        Assert(pGuestFeat->fVmxExitSaveEferLma);
-    }
 
     /*
Index: trunk/src/VBox/VMM/VMMR3/CPUMR3CpuId.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMR3/CPUMR3CpuId.cpp	(revision 91119)
+++ trunk/src/VBox/VMM/VMMR3/CPUMR3CpuId.cpp	(revision 91120)
@@ -4198,25 +4198,51 @@
         rc = CFGMR3QueryBoolDef(pCpumCfg, "NestedHWVirt", &pConfig->fNestedHWVirt, false);
         AssertLogRelRCReturn(rc, rc);
-        if (   pConfig->fNestedHWVirt
-            && !fNestedPagingAndFullGuestExec)
-            return VMSetError(pVM, VERR_CPUM_INVALID_HWVIRT_CONFIG, RT_SRC_POS,
-                              "Cannot enable nested VT-x/AMD-V without nested-paging and unresricted guest execution!\n");
-
-        /** @todo Think about enabling this later with NEM/KVM. */
-        if (   pConfig->fNestedHWVirt
-            && VM_IS_NEM_ENABLED(pVM))
-        {
-            LogRel(("CPUM: WARNING! Can't turn on nested VT-x/AMD-V when NEM is used!\n"));
-            pConfig->fNestedHWVirt = false;
-        }
-
-        /** @cfgm{/CPUM/NestedVmxPreemptTimer, bool, true}
-         * Whether to expose the VMX-preemption timer feature to the guest (if also
-         * supported by the host hardware). The default is true, and when disabled will
-         * prevent exposing the VMX-preemption timer feature to the guest even if the host
-         * supports it.
-         */
-        rc = CFGMR3QueryBoolDef(pCpumCfg, "NestedVmxPreemptTimer", &pVM->cpum.s.fNestedVmxPreemptTimer, true);
-        AssertLogRelRCReturn(rc, rc);
+        if (pConfig->fNestedHWVirt)
+        {
+            if (!fNestedPagingAndFullGuestExec)
+                return VMSetError(pVM, VERR_CPUM_INVALID_HWVIRT_CONFIG, RT_SRC_POS,
+                                  "Cannot enable nested VT-x/AMD-V without nested-paging and unresricted guest execution!\n");
+
+            /** @todo Think about enabling this later with NEM/KVM. */
+            if (VM_IS_NEM_ENABLED(pVM))
+            {
+                LogRel(("CPUM: WARNING! Can't turn on nested VT-x/AMD-V when NEM is used!\n"));
+                pConfig->fNestedHWVirt = false;
+            }
+        }
+
+        if (pConfig->fNestedHWVirt)
+        {
+            /** @cfgm{/CPUM/NestedVmxPreemptTimer, bool, true}
+             * Whether to expose the VMX-preemption timer feature to the guest (if also
+             * supported by the host hardware). The default is true, and when disabled will
+             * prevent exposing the VMX-preemption timer feature to the guest even if the host
+             * supports it.
+             */
+            rc = CFGMR3QueryBoolDef(pCpumCfg, "NestedVmxPreemptTimer", &pVM->cpum.s.fNestedVmxPreemptTimer, true);
+            AssertLogRelRCReturn(rc, rc);
+
+            /** @cfgm{/CPUM/NestedVmxEpt, bool, true}
+             * Whether to expose the EPT feature to the guest. The default is false. When
+             * disabled will automatically prevent exposing features that rely on
+             */
+            rc = CFGMR3QueryBoolDef(pCpumCfg, "NestedVmxEpt", &pVM->cpum.s.fNestedVmxEpt, false);
+            AssertLogRelRCReturn(rc, rc);
+
+            /** @cfgm{/CPUM/NestedVmxUnrestrictedGuest, bool, true}
+             * Whether to expose the Unrestricted Guest feature to the guest. The default is
+             * false. When disabled will automatically prevent exposing features that rely on
+             * it.
+             */
+            rc = CFGMR3QueryBoolDef(pCpumCfg, "NestedVmxUnrestrictedGuest", &pVM->cpum.s.fNestedVmxUnrestrictedGuest, false);
+            AssertLogRelRCReturn(rc, rc);
+
+            if (    pVM->cpum.s.fNestedVmxUnrestrictedGuest
+                && !pVM->cpum.s.fNestedVmxEpt)
+            {
+                LogRel(("CPUM: WARNING! Can't expose \"Unrestricted Guest\" to the guest when EPT is not exposed!\n"));
+                pVM->cpum.s.fNestedVmxUnrestrictedGuest = false;
+            }
+        }
     }
 
Index: trunk/src/VBox/VMM/VMMR3/HM.cpp
===================================================================
--- trunk/src/VBox/VMM/VMMR3/HM.cpp	(revision 91119)
+++ trunk/src/VBox/VMM/VMMR3/HM.cpp	(revision 91120)
@@ -1433,5 +1433,5 @@
     HMVMX_REPORT_MSR_CAP(fCaps, "EPT_ACCESS_DIRTY",                      MSR_IA32_VMX_EPT_VPID_CAP_EPT_ACCESS_DIRTY);
     HMVMX_REPORT_MSR_CAP(fCaps, "ADVEXITINFO_EPT",                       MSR_IA32_VMX_EPT_VPID_CAP_ADVEXITINFO_EPT);
-    HMVMX_REPORT_MSR_CAP(fCaps, "SSS",                                   MSR_IA32_VMX_EPT_VPID_CAP_SSS);
+    HMVMX_REPORT_MSR_CAP(fCaps, "SUPER_SHW_STACK",                       MSR_IA32_VMX_EPT_VPID_CAP_SUPER_SHW_STACK);
     HMVMX_REPORT_MSR_CAP(fCaps, "INVEPT_SINGLE_CONTEXT",                 MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_SINGLE_CONTEXT);
     HMVMX_REPORT_MSR_CAP(fCaps, "INVEPT_ALL_CONTEXTS",                   MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_ALL_CONTEXTS);
Index: trunk/src/VBox/VMM/include/CPUMInternal.h
===================================================================
--- trunk/src/VBox/VMM/include/CPUMInternal.h	(revision 91119)
+++ trunk/src/VBox/VMM/include/CPUMInternal.h	(revision 91120)
@@ -362,5 +362,10 @@
     /** Nested VMX: Whether to expose VMX-preemption timer to the guest. */
     bool                    fNestedVmxPreemptTimer;
-    uint8_t                 abPadding1[3];
+    /** Nested VMX: Whether to expose EPT to the guest. If this is disabled make sure
+     *  to also disable fNestedVmxUnrestrictedGuest. */
+    bool                    fNestedVmxEpt;
+    /** Nested VMX: Whether to expose "unrestricted guest" to the guest. */
+    bool                    fNestedVmxUnrestrictedGuest;
+    uint8_t                 abPadding1[1];
 
     /** Align to 64-byte boundary. */
