VirtualBox

Changeset 91120 in vbox


Ignore:
Timestamp:
Sep 6, 2021 12:03:23 PM (3 years ago)
Author:
vboxsync
Message:

VMM: Nested VMX: bugref:10092 VMX EPT and Unrestricted CFGM options, build EPT_VPID_CAPS MSR and exposing other EPT related bits.

Location:
trunk
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/vmm/hm_vmx.h

    r91101 r91120  
    16791679#define MSR_IA32_VMX_EPT_VPID_CAP_ADVEXITINFO_EPT               RT_BIT_64(22)
    16801680/** Supports supervisor shadow-stack control. */
    1681 #define MSR_IA32_VMX_EPT_VPID_CAP_SSS                           RT_BIT_64(23)
     1681#define MSR_IA32_VMX_EPT_VPID_CAP_SUPER_SHW_STACK               RT_BIT_64(23)
    16821682/** Supports single-context INVEPT type. */
    16831683#define MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_SINGLE_CONTEXT         RT_BIT_64(25)
     
    17241724#define VMX_BF_EPT_VPID_CAP_ADVEXITINFO_EPT_SHIFT               22
    17251725#define VMX_BF_EPT_VPID_CAP_ADVEXITINFO_EPT_MASK                UINT64_C(0x0000000000400000)
    1726 #define VMX_BF_EPT_VPID_CAP_SSS_SHIFT                           23
    1727 #define VMX_BF_EPT_VPID_CAP_SSS_MASK                            UINT64_C(0x0000000000800000)
     1726#define VMX_BF_EPT_VPID_CAP_SUPER_SHW_STACK_SHIFT               23
     1727#define VMX_BF_EPT_VPID_CAP_SUPER_SHW_STACK_MASK                UINT64_C(0x0000000000800000)
    17281728#define VMX_BF_EPT_VPID_CAP_RSVD_24_SHIFT                       24
    17291729#define VMX_BF_EPT_VPID_CAP_RSVD_24_MASK                        UINT64_C(0x0000000001000000)
     
    17501750RT_BF_ASSERT_COMPILE_CHECKS(VMX_BF_EPT_VPID_CAP_, UINT64_C(0), UINT64_MAX,
    17511751                            (RWX_X_ONLY, RSVD_1_5, PAGE_WALK_LENGTH_4, RSVD_7, EMT_UC, RSVD_9_13, EMT_WB, RSVD_15, PDE_2M,
    1752                              PDPTE_1G, RSVD_18_19, INVEPT, EPT_ACCESS_DIRTY, ADVEXITINFO_EPT, SSS, RSVD_24, INVEPT_SINGLE_CTX,
    1753                              INVEPT_ALL_CTX, RSVD_27_31, INVVPID, RSVD_33_39, INVVPID_INDIV_ADDR, INVVPID_SINGLE_CTX,
    1754                              INVVPID_ALL_CTX, INVVPID_SINGLE_CTX_RETAIN_GLOBALS, RSVD_44_63));
     1752                             PDPTE_1G, RSVD_18_19, INVEPT, EPT_ACCESS_DIRTY, ADVEXITINFO_EPT, SUPER_SHW_STACK, RSVD_24,
     1753                             INVEPT_SINGLE_CTX, INVEPT_ALL_CTX, RSVD_27_31, INVVPID, RSVD_33_39, INVVPID_INDIV_ADDR,
     1754                             INVVPID_SINGLE_CTX, INVVPID_ALL_CTX, INVVPID_SINGLE_CTX_RETAIN_GLOBALS, RSVD_44_63));
    17551755/** @} */
    17561756
  • trunk/src/VBox/VMM/VMMR3/CPUM.cpp

    r91044 r91120  
    17531753
    17541754    /* VPID and EPT Capabilities. */
     1755    if (pGuestFeatures->fVmxEpt)
    17551756    {
    17561757        /*
     
    17641765         * See Intel spec. 30.3 "VMX Instructions".
    17651766         */
    1766         uint8_t const fVpid = pGuestFeatures->fVmxVpid;
    1767         pGuestVmxMsrs->u64EptVpidCaps = RT_BF_MAKE(VMX_BF_EPT_VPID_CAP_INVVPID,                           fVpid)
    1768                                       | RT_BF_MAKE(VMX_BF_EPT_VPID_CAP_INVVPID_SINGLE_CTX,                fVpid & 1)
    1769                                       | RT_BF_MAKE(VMX_BF_EPT_VPID_CAP_INVVPID_ALL_CTX,                   fVpid & 1)
    1770                                       | RT_BF_MAKE(VMX_BF_EPT_VPID_CAP_INVVPID_SINGLE_CTX_RETAIN_GLOBALS, fVpid & 1);
     1767        uint64_t const uHostMsr = fIsNstGstHwExecAllowed ? pHostVmxMsrs->u64EptVpidCaps : UINT64_MAX;
     1768        uint8_t const  fVpid    = pGuestFeatures->fVmxVpid;
     1769
     1770        uint8_t const  fExecOnly         = RT_BF_GET(uHostMsr, VMX_BF_EPT_VPID_CAP_RWX_X_ONLY);
     1771        uint8_t const  fPml4             = RT_BF_GET(uHostMsr, VMX_BF_EPT_VPID_CAP_PAGE_WALK_LENGTH_4);
     1772        uint8_t const  fEptMemUc         = RT_BF_GET(uHostMsr, VMX_BF_EPT_VPID_CAP_EMT_UC);
     1773        uint8_t const  fEptMemWb         = RT_BF_GET(uHostMsr, VMX_BF_EPT_VPID_CAP_EMT_WB);
     1774        uint8_t const  f2MPage           = RT_BF_GET(uHostMsr, VMX_BF_EPT_VPID_CAP_PDE_2M);
     1775        uint8_t const  f1GPage           = RT_BF_GET(uHostMsr, VMX_BF_EPT_VPID_CAP_PDPTE_1G);
     1776        uint8_t const  fInvept           = RT_BF_GET(uHostMsr, VMX_BF_EPT_VPID_CAP_INVEPT);
     1777        uint8_t const  fEptAccDirty      = RT_BF_GET(uHostMsr, VMX_BF_EPT_VPID_CAP_EPT_ACCESS_DIRTY);
     1778        uint8_t const  fEptSingle        = RT_BF_GET(uHostMsr, VMX_BF_EPT_VPID_CAP_INVEPT_SINGLE_CTX);
     1779        uint8_t const  fEptAll           = RT_BF_GET(uHostMsr, VMX_BF_EPT_VPID_CAP_INVEPT_ALL_CTX);
     1780        uint8_t const  fVpidIndiv        = RT_BF_GET(uHostMsr, VMX_BF_EPT_VPID_CAP_INVVPID_INDIV_ADDR);
     1781        uint8_t const  fVpidSingle       = RT_BF_GET(uHostMsr, VMX_BF_EPT_VPID_CAP_INVVPID_SINGLE_CTX);
     1782        uint8_t const  fVpidAll          = RT_BF_GET(uHostMsr, VMX_BF_EPT_VPID_CAP_INVVPID_ALL_CTX);
     1783        uint8_t const  fVpidSingleGlobal = RT_BF_GET(uHostMsr, VMX_BF_EPT_VPID_CAP_INVVPID_SINGLE_CTX_RETAIN_GLOBALS);
     1784        pGuestVmxMsrs->u64EptVpidCaps = RT_BF_MAKE(VMX_BF_EPT_VPID_CAP_RWX_X_ONLY,                        fExecOnly)
     1785                                      | RT_BF_MAKE(VMX_BF_EPT_VPID_CAP_PAGE_WALK_LENGTH_4,                fPml4)
     1786                                      | RT_BF_MAKE(VMX_BF_EPT_VPID_CAP_EMT_UC,                            fEptMemUc)
     1787                                      | RT_BF_MAKE(VMX_BF_EPT_VPID_CAP_EMT_WB,                            fEptMemWb)
     1788                                      | RT_BF_MAKE(VMX_BF_EPT_VPID_CAP_PDE_2M,                            f2MPage)
     1789                                      | RT_BF_MAKE(VMX_BF_EPT_VPID_CAP_PDPTE_1G,                          f1GPage)
     1790                                      | RT_BF_MAKE(VMX_BF_EPT_VPID_CAP_INVEPT,                            fInvept)
     1791                                      | RT_BF_MAKE(VMX_BF_EPT_VPID_CAP_EPT_ACCESS_DIRTY,                  fEptAccDirty)
     1792                                      | RT_BF_MAKE(VMX_BF_EPT_VPID_CAP_ADVEXITINFO_EPT,                   0)
     1793                                      | RT_BF_MAKE(VMX_BF_EPT_VPID_CAP_SUPER_SHW_STACK,                   0)
     1794                                      | RT_BF_MAKE(VMX_BF_EPT_VPID_CAP_INVEPT_SINGLE_CTX,                 fEptSingle)
     1795                                      | RT_BF_MAKE(VMX_BF_EPT_VPID_CAP_INVEPT_ALL_CTX,                    fEptAll)
     1796                                      | RT_BF_MAKE(VMX_BF_EPT_VPID_CAP_INVVPID,                           fVpid)
     1797                                      | RT_BF_MAKE(VMX_BF_EPT_VPID_CAP_INVVPID_INDIV_ADDR,                fVpid & fVpidIndiv)
     1798                                      | RT_BF_MAKE(VMX_BF_EPT_VPID_CAP_INVVPID_SINGLE_CTX,                fVpid & fVpidSingle)
     1799                                      | RT_BF_MAKE(VMX_BF_EPT_VPID_CAP_INVVPID_ALL_CTX,                   fVpid & fVpidAll)
     1800                                      | RT_BF_MAKE(VMX_BF_EPT_VPID_CAP_INVVPID_SINGLE_CTX_RETAIN_GLOBALS, fVpid & fVpidSingleGlobal);
    17711801    }
    17721802
     
    19021932
    19031933    /*
     1934     * While it would be nice to check this earlier while initializing fNestedVmxEpt
     1935     * but we would not have enumearted host features then, so do it at least now.
     1936     */
     1937    if (   !pVM->cpum.s.HostFeatures.fNoExecute
     1938        && pVM->cpum.s.fNestedVmxEpt)
     1939    {
     1940        LogRel(("CPUM: Warning! EPT not exposed to the guest since NX isn't available on the host.\n"));
     1941        pVM->cpum.s.fNestedVmxEpt               = false;
     1942        pVM->cpum.s.fNestedVmxUnrestrictedGuest = false;
     1943    }
     1944
     1945    /*
    19041946     * Initialize the set of VMX features we emulate.
    19051947     *
     
    19141956    EmuFeat.fVmxNmiExit               = 1;
    19151957    EmuFeat.fVmxVirtNmi               = 1;
    1916     EmuFeat.fVmxPreemptTimer          = 0;  /* Currently disabled on purpose, see @bugref{9180#c108}. */
     1958    EmuFeat.fVmxPreemptTimer          = 0;  /* pVM->cpum.s.fNestedVmxPreemptTimer -- Currently disabled on purpose, see @bugref{9180#c108}. */
    19171959    EmuFeat.fVmxPostedInt             = 0;
    19181960    EmuFeat.fVmxIntWindowExit         = 1;
     
    19391981    EmuFeat.fVmxSecondaryExecCtls     = 1;
    19401982    EmuFeat.fVmxVirtApicAccess        = 1;
    1941     EmuFeat.fVmxEpt                   = 0;  /* Cannot be disabled if unrestricted guest is enabled. */
     1983    EmuFeat.fVmxEpt                   = pVM->cpum.s.fNestedVmxEpt;
    19421984    EmuFeat.fVmxDescTableExit         = 1;
    19431985    EmuFeat.fVmxRdtscp                = 1;
    19441986    EmuFeat.fVmxVirtX2ApicMode        = 0;
    1945     EmuFeat.fVmxVpid                  = 0;  /** @todo NSTVMX: enable this. */
     1987    EmuFeat.fVmxVpid                  = EmuFeat.fVmxEpt;
    19461988    EmuFeat.fVmxWbinvdExit            = 1;
    1947     EmuFeat.fVmxUnrestrictedGuest     = 0;
     1989    EmuFeat.fVmxUnrestrictedGuest     = pVM->cpum.s.fNestedVmxUnrestrictedGuest;
    19481990    EmuFeat.fVmxApicRegVirt           = 0;
    19491991    EmuFeat.fVmxVirtIntDelivery       = 0;
     
    20512093    pGuestFeat->fVmxEntryInjectSoftInt    = (pBaseFeat->fVmxEntryInjectSoftInt    & EmuFeat.fVmxEntryInjectSoftInt   );
    20522094
    2053     if (   !pVM->cpum.s.fNestedVmxPreemptTimer
    2054         || HMIsSubjectToVmxPreemptTimerErratum())
    2055     {
    2056         LogRel(("CPUM: Warning! VMX-preemption timer not exposed to guest due to forced CFGM setting or CPU erratum.\n"));
     2095    /* Don't expose VMX preemption timer if host is subject to VMX-preemption timer erratum. */
     2096    if (   pGuestFeat->fVmxPreemptTimer
     2097        && HMIsSubjectToVmxPreemptTimerErratum())
     2098    {
     2099        LogRel(("CPUM: Warning! VMX-preemption timer not exposed to guest due to host CPU erratum.\n"));
    20572100        pGuestFeat->fVmxPreemptTimer     = 0;
    20582101        pGuestFeat->fVmxSavePreemptTimer = 0;
    20592102    }
    20602103
    2061     /* Paranoia. */
     2104    /* Sanity checking. */
    20622105    if (!pGuestFeat->fVmxSecondaryExecCtls)
    20632106    {
     
    20832126        Assert(!pGuestFeat->fVmxUseTscScaling);
    20842127    }
     2128    else if (pGuestFeat->fVmxUnrestrictedGuest)
     2129    {
     2130        /* See footnote in Intel spec. 27.2 "Recording VM-Exit Information And Updating VM-entry Control Fields". */
     2131        Assert(pGuestFeat->fVmxExitSaveEferLma);
     2132        /* Unrestricted guest execution requires EPT. See Intel spec. 25.2.1.1 "VM-Execution Control Fields". */
     2133        Assert(pGuestFeat->fVmxEpt);
     2134    }
     2135
    20852136    if (!pGuestFeat->fVmxTertiaryExecCtls)
    20862137        Assert(!pGuestFeat->fVmxLoadIwKeyExit);
    2087     if (pGuestFeat->fVmxUnrestrictedGuest)
    2088     {
    2089         /* See footnote in Intel spec. 27.2 "Recording VM-Exit Information And Updating VM-entry Control Fields". */
    2090         Assert(pGuestFeat->fVmxExitSaveEferLma);
    2091     }
    20922138
    20932139    /*
  • trunk/src/VBox/VMM/VMMR3/CPUMR3CpuId.cpp

    r91043 r91120  
    41984198        rc = CFGMR3QueryBoolDef(pCpumCfg, "NestedHWVirt", &pConfig->fNestedHWVirt, false);
    41994199        AssertLogRelRCReturn(rc, rc);
    4200         if (   pConfig->fNestedHWVirt
    4201             && !fNestedPagingAndFullGuestExec)
    4202             return VMSetError(pVM, VERR_CPUM_INVALID_HWVIRT_CONFIG, RT_SRC_POS,
    4203                               "Cannot enable nested VT-x/AMD-V without nested-paging and unresricted guest execution!\n");
    4204 
    4205         /** @todo Think about enabling this later with NEM/KVM. */
    4206         if (   pConfig->fNestedHWVirt
    4207             && VM_IS_NEM_ENABLED(pVM))
    4208         {
    4209             LogRel(("CPUM: WARNING! Can't turn on nested VT-x/AMD-V when NEM is used!\n"));
    4210             pConfig->fNestedHWVirt = false;
    4211         }
    4212 
    4213         /** @cfgm{/CPUM/NestedVmxPreemptTimer, bool, true}
    4214          * Whether to expose the VMX-preemption timer feature to the guest (if also
    4215          * supported by the host hardware). The default is true, and when disabled will
    4216          * prevent exposing the VMX-preemption timer feature to the guest even if the host
    4217          * supports it.
    4218          */
    4219         rc = CFGMR3QueryBoolDef(pCpumCfg, "NestedVmxPreemptTimer", &pVM->cpum.s.fNestedVmxPreemptTimer, true);
    4220         AssertLogRelRCReturn(rc, rc);
     4200        if (pConfig->fNestedHWVirt)
     4201        {
     4202            if (!fNestedPagingAndFullGuestExec)
     4203                return VMSetError(pVM, VERR_CPUM_INVALID_HWVIRT_CONFIG, RT_SRC_POS,
     4204                                  "Cannot enable nested VT-x/AMD-V without nested-paging and unresricted guest execution!\n");
     4205
     4206            /** @todo Think about enabling this later with NEM/KVM. */
     4207            if (VM_IS_NEM_ENABLED(pVM))
     4208            {
     4209                LogRel(("CPUM: WARNING! Can't turn on nested VT-x/AMD-V when NEM is used!\n"));
     4210                pConfig->fNestedHWVirt = false;
     4211            }
     4212        }
     4213
     4214        if (pConfig->fNestedHWVirt)
     4215        {
     4216            /** @cfgm{/CPUM/NestedVmxPreemptTimer, bool, true}
     4217             * Whether to expose the VMX-preemption timer feature to the guest (if also
     4218             * supported by the host hardware). The default is true, and when disabled will
     4219             * prevent exposing the VMX-preemption timer feature to the guest even if the host
     4220             * supports it.
     4221             */
     4222            rc = CFGMR3QueryBoolDef(pCpumCfg, "NestedVmxPreemptTimer", &pVM->cpum.s.fNestedVmxPreemptTimer, true);
     4223            AssertLogRelRCReturn(rc, rc);
     4224
     4225            /** @cfgm{/CPUM/NestedVmxEpt, bool, true}
     4226             * Whether to expose the EPT feature to the guest. The default is false. When
     4227             * disabled will automatically prevent exposing features that rely on
     4228             */
     4229            rc = CFGMR3QueryBoolDef(pCpumCfg, "NestedVmxEpt", &pVM->cpum.s.fNestedVmxEpt, false);
     4230            AssertLogRelRCReturn(rc, rc);
     4231
     4232            /** @cfgm{/CPUM/NestedVmxUnrestrictedGuest, bool, true}
     4233             * Whether to expose the Unrestricted Guest feature to the guest. The default is
     4234             * false. When disabled will automatically prevent exposing features that rely on
     4235             * it.
     4236             */
     4237            rc = CFGMR3QueryBoolDef(pCpumCfg, "NestedVmxUnrestrictedGuest", &pVM->cpum.s.fNestedVmxUnrestrictedGuest, false);
     4238            AssertLogRelRCReturn(rc, rc);
     4239
     4240            if (    pVM->cpum.s.fNestedVmxUnrestrictedGuest
     4241                && !pVM->cpum.s.fNestedVmxEpt)
     4242            {
     4243                LogRel(("CPUM: WARNING! Can't expose \"Unrestricted Guest\" to the guest when EPT is not exposed!\n"));
     4244                pVM->cpum.s.fNestedVmxUnrestrictedGuest = false;
     4245            }
     4246        }
    42214247    }
    42224248
  • trunk/src/VBox/VMM/VMMR3/HM.cpp

    r91043 r91120  
    14331433    HMVMX_REPORT_MSR_CAP(fCaps, "EPT_ACCESS_DIRTY",                      MSR_IA32_VMX_EPT_VPID_CAP_EPT_ACCESS_DIRTY);
    14341434    HMVMX_REPORT_MSR_CAP(fCaps, "ADVEXITINFO_EPT",                       MSR_IA32_VMX_EPT_VPID_CAP_ADVEXITINFO_EPT);
    1435     HMVMX_REPORT_MSR_CAP(fCaps, "SSS",                                   MSR_IA32_VMX_EPT_VPID_CAP_SSS);
     1435    HMVMX_REPORT_MSR_CAP(fCaps, "SUPER_SHW_STACK",                       MSR_IA32_VMX_EPT_VPID_CAP_SUPER_SHW_STACK);
    14361436    HMVMX_REPORT_MSR_CAP(fCaps, "INVEPT_SINGLE_CONTEXT",                 MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_SINGLE_CONTEXT);
    14371437    HMVMX_REPORT_MSR_CAP(fCaps, "INVEPT_ALL_CONTEXTS",                   MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_ALL_CONTEXTS);
  • trunk/src/VBox/VMM/include/CPUMInternal.h

    r91037 r91120  
    362362    /** Nested VMX: Whether to expose VMX-preemption timer to the guest. */
    363363    bool                    fNestedVmxPreemptTimer;
    364     uint8_t                 abPadding1[3];
     364    /** Nested VMX: Whether to expose EPT to the guest. If this is disabled make sure
     365     *  to also disable fNestedVmxUnrestrictedGuest. */
     366    bool                    fNestedVmxEpt;
     367    /** Nested VMX: Whether to expose "unrestricted guest" to the guest. */
     368    bool                    fNestedVmxUnrestrictedGuest;
     369    uint8_t                 abPadding1[1];
    365370
    366371    /** Align to 64-byte boundary. */
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette