VirtualBox

Changeset 70944 in vbox


Ignore:
Timestamp:
Feb 9, 2018 10:09:03 PM (7 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
120787
Message:

VMM/NEM: More code.

Location:
trunk/src/VBox/VMM
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMR3/NEMR3Native-win.cpp

    r70942 r70944  
    3030#endif
    3131#include <sysinfoapi.h>
     32#include <debugapi.h>
     33#include <errhandlingapi.h>
    3234#include <fileapi.h>
    33 #include <errhandlingapi.h>
    3435#include <winerror.h> /* no api header for this. */
    3536
     
    120121# define WHvSetVirtualProcessorRegisters            g_pfnWHvSetVirtualProcessorRegisters
    121122#endif
     123
     124
     125
     126/**
     127 * Worker for nemR3NativeInit that gets the hypervisor capabilities.
     128 *
     129 * @returns VBox status code.
     130 * @param   pVM                 The cross context VM structure.
     131 * @param   pErrInfo            Where to always return error info.
     132 */
     133static int nemR3NativeInitCheckCapabilities(PVM pVM, PRTERRINFO pErrInfo)
     134{
     135#define NEM_LOG_REL_CAP_EX(a_szField, a_szFmt, a_Value)     LogRel(("NEM: %-38s= " a_szFmt "\n", a_szField, a_Value))
     136#define NEM_LOG_REL_CAP_SUB_EX(a_szField, a_szFmt, a_Value) LogRel(("NEM:   %36s: " a_szFmt "\n", a_szField, a_Value))
     137#define NEM_LOG_REL_CAP_SUB(a_szField, a_Value)             NEM_LOG_REL_CAP_SUB_EX(a_szField, "%d", a_Value)
     138
     139    /*
     140     * Is the hypervisor present with the desired capability?
     141     *
     142     * In build 17083 this translates into:
     143     *      - CPUID[0x00000001].HVP is set
     144     *      - CPUID[0x40000000] == "Microsoft Hv"
     145     *      - CPUID[0x40000001].eax == "Hv#1"
     146     *      - CPUID[0x40000003].ebx[12] is set.
     147     *      - VidGetExoPartitionProperty(INVALID_HANDLE_VALUE, 0x60000, &Ignored) returns
     148     *        a non-zero value.
     149     */
     150    /**
     151     * @todo Someone (MS) please explain weird API design:
     152     *   1. Caps.CapabilityCode duplication,
     153     *   2. No output size.
     154     */
     155    WHV_CAPABILITY Caps;
     156    RT_ZERO(Caps);
     157    SetLastError(0);
     158    HRESULT hrc = WHvGetCapability(WHvCapabilityCodeHypervisorPresent, &Caps, sizeof(Caps));
     159    DWORD   rcWin = GetLastError();
     160    if (FAILED(hrc))
     161        return RTErrInfoSetF(pErrInfo, VERR_NEM_INIT_FAILED, "WHvGetCapability/WHvCapabilityCodeHypervisorPresent failed: %Rhrc", hrc);
     162    if (!Caps.HypervisorPresent)
     163    {
     164        if (!RTPathExists(RTPATH_NT_PASSTHRU_PREFIX "Device\\VidExo"))
     165            return RTErrInfoSetF(pErrInfo, VERR_NEM_NOT_AVAILABLE,
     166                                 "WHvCapabilityCodeHypervisorPresent is FALSE! Make sure you have enabled the 'Windows Hypervisor Platform' feature.");
     167        return RTErrInfoSetF(pErrInfo, VERR_NEM_NOT_AVAILABLE, "WHvCapabilityCodeHypervisorPresent is FALSE! (%u)", rcWin);
     168    }
     169    LogRel(("NEM: WHvCapabilityCodeHypervisorPresent is TRUE, so this might work...\n"));
     170
     171
     172    /*
     173     * Check what extended VM exits are supported.
     174     */
     175    RT_ZERO(Caps);
     176    hrc = WHvGetCapability(WHvCapabilityCodeExtendedVmExits, &Caps, sizeof(Caps));
     177    if (FAILED(hrc))
     178        return RTErrInfoSetF(pErrInfo, VERR_NEM_INIT_FAILED, "WHvGetCapability/WHvCapabilityCodeExtendedVmExits failed: %Rhrc", hrc);
     179    NEM_LOG_REL_CAP_EX("WHvCapabilityCodeExtendedVmExits", "%'#018RX64", Caps.ExtendedVmExits.AsUINT64);
     180    pVM->nem.s.fExtendedMsrExit   = RT_BOOL(Caps.ExtendedVmExits.X64MsrExit);
     181    pVM->nem.s.fExtendedCpuIdExit = RT_BOOL(Caps.ExtendedVmExits.X64CpuidExit);
     182    pVM->nem.s.fExtendedXcptExit  = RT_BOOL(Caps.ExtendedVmExits.ExceptionExit);
     183    NEM_LOG_REL_CAP_SUB("fExtendedMsrExit",   pVM->nem.s.fExtendedMsrExit);
     184    NEM_LOG_REL_CAP_SUB("fExtendedCpuIdExit", pVM->nem.s.fExtendedCpuIdExit);
     185    NEM_LOG_REL_CAP_SUB("fExtendedXcptExit",  pVM->nem.s.fExtendedXcptExit);
     186    if (Caps.ExtendedVmExits.AsUINT64 & ~(uint64_t)7)
     187        LogRel(("NEM: Warning! Unknown VM exit definitions: %#RX64\n", Caps.ExtendedVmExits.AsUINT64));
     188    /** @todo RECHECK: WHV_EXTENDED_VM_EXITS typedef. */
     189
     190    /*
     191     * Check features in case they end up defining any.
     192     */
     193    RT_ZERO(Caps);
     194    hrc = WHvGetCapability(WHvCapabilityCodeFeatures, &Caps, sizeof(Caps));
     195    if (FAILED(hrc))
     196        return RTErrInfoSetF(pErrInfo, VERR_NEM_INIT_FAILED, "WHvGetCapability/WHvCapabilityCodeFeatures failed: %Rhrc", hrc);
     197    if (Caps.Features.AsUINT64 & ~(uint64_t)0)
     198        LogRel(("NEM: Warning! Unknown feature definitions: %#RX64\n", Caps.Features.AsUINT64));
     199    /** @todo RECHECK: WHV_CAPABILITY_FEATURES typedef. */
     200
     201    /*
     202     * Check that the CPU vendor is supported.
     203     */
     204    RT_ZERO(Caps);
     205    hrc = WHvGetCapability(WHvCapabilityCodeProcessorVendor, &Caps, sizeof(Caps));
     206    if (FAILED(hrc))
     207        return RTErrInfoSetF(pErrInfo, VERR_NEM_INIT_FAILED, "WHvGetCapability/WHvCapabilityCodeProcessorVendor failed: %Rhrc", hrc);
     208    switch (Caps.ProcessorVendor)
     209    {
     210        /** @todo RECHECK: WHV_PROCESSOR_VENDOR typedef. */
     211        case WHvProcessorVendorIntel:
     212            NEM_LOG_REL_CAP_EX("WHvCapabilityCodeProcessorVendor", "%d - Intel", Caps.ProcessorVendor);
     213            pVM->nem.s.enmCpuVendor = CPUMCPUVENDOR_INTEL;
     214            break;
     215        case WHvProcessorVendorAmd:
     216            NEM_LOG_REL_CAP_EX("WHvCapabilityCodeProcessorVendor", "%d - AMD", Caps.ProcessorVendor);
     217            pVM->nem.s.enmCpuVendor = CPUMCPUVENDOR_AMD;
     218            break;
     219        default:
     220            NEM_LOG_REL_CAP_EX("WHvCapabilityCodeProcessorVendor", "%d", Caps.ProcessorVendor);
     221            return RTErrInfoSetF(pErrInfo, VERR_NEM_INIT_FAILED, "Unknown processor vendor: %d", Caps.ProcessorVendor);
     222    }
     223
     224    /*
     225     * CPU features, guessing these are virtual CPU features?
     226     */
     227    RT_ZERO(Caps);
     228    hrc = WHvGetCapability(WHvCapabilityCodeProcessorFeatures, &Caps, sizeof(Caps));
     229    if (FAILED(hrc))
     230        return RTErrInfoSetF(pErrInfo, VERR_NEM_INIT_FAILED, "WHvGetCapability/WHvCapabilityCodeProcessorFeatures failed: %Rhrc", hrc);
     231    NEM_LOG_REL_CAP_EX("WHvCapabilityCodeProcessorFeatures", "%'#018RX64", Caps.ProcessorFeatures.AsUINT64);
     232#define NEM_LOG_REL_CPU_FEATURE(a_Field)    NEM_LOG_REL_CAP_SUB(#a_Field, Caps.ProcessorFeatures.a_Field)
     233    NEM_LOG_REL_CPU_FEATURE(Sse3Support);
     234    NEM_LOG_REL_CPU_FEATURE(LahfSahfSupport);
     235    NEM_LOG_REL_CPU_FEATURE(Ssse3Support);
     236    NEM_LOG_REL_CPU_FEATURE(Sse4_1Support);
     237    NEM_LOG_REL_CPU_FEATURE(Sse4_2Support);
     238    NEM_LOG_REL_CPU_FEATURE(Sse4aSupport);
     239    NEM_LOG_REL_CPU_FEATURE(XopSupport);
     240    NEM_LOG_REL_CPU_FEATURE(PopCntSupport);
     241    NEM_LOG_REL_CPU_FEATURE(Cmpxchg16bSupport);
     242    NEM_LOG_REL_CPU_FEATURE(Altmovcr8Support);
     243    NEM_LOG_REL_CPU_FEATURE(LzcntSupport);
     244    NEM_LOG_REL_CPU_FEATURE(MisAlignSseSupport);
     245    NEM_LOG_REL_CPU_FEATURE(MmxExtSupport);
     246    NEM_LOG_REL_CPU_FEATURE(Amd3DNowSupport);
     247    NEM_LOG_REL_CPU_FEATURE(ExtendedAmd3DNowSupport);
     248    NEM_LOG_REL_CPU_FEATURE(Page1GbSupport);
     249    NEM_LOG_REL_CPU_FEATURE(AesSupport);
     250    NEM_LOG_REL_CPU_FEATURE(PclmulqdqSupport);
     251    NEM_LOG_REL_CPU_FEATURE(PcidSupport);
     252    NEM_LOG_REL_CPU_FEATURE(Fma4Support);
     253    NEM_LOG_REL_CPU_FEATURE(F16CSupport);
     254    NEM_LOG_REL_CPU_FEATURE(RdRandSupport);
     255    NEM_LOG_REL_CPU_FEATURE(RdWrFsGsSupport);
     256    NEM_LOG_REL_CPU_FEATURE(SmepSupport);
     257    NEM_LOG_REL_CPU_FEATURE(EnhancedFastStringSupport);
     258    NEM_LOG_REL_CPU_FEATURE(Bmi1Support);
     259    NEM_LOG_REL_CPU_FEATURE(Bmi2Support);
     260    /* two reserved bits here, see below */
     261    NEM_LOG_REL_CPU_FEATURE(MovbeSupport);
     262    NEM_LOG_REL_CPU_FEATURE(Npiep1Support);
     263    NEM_LOG_REL_CPU_FEATURE(DepX87FPUSaveSupport);
     264    NEM_LOG_REL_CPU_FEATURE(RdSeedSupport);
     265    NEM_LOG_REL_CPU_FEATURE(AdxSupport);
     266    NEM_LOG_REL_CPU_FEATURE(IntelPrefetchSupport);
     267    NEM_LOG_REL_CPU_FEATURE(SmapSupport);
     268    NEM_LOG_REL_CPU_FEATURE(HleSupport);
     269    NEM_LOG_REL_CPU_FEATURE(RtmSupport);
     270    NEM_LOG_REL_CPU_FEATURE(RdtscpSupport);
     271    NEM_LOG_REL_CPU_FEATURE(ClflushoptSupport);
     272    NEM_LOG_REL_CPU_FEATURE(ClwbSupport);
     273    NEM_LOG_REL_CPU_FEATURE(ShaSupport);
     274    NEM_LOG_REL_CPU_FEATURE(X87PointersSavedSupport);
     275#undef NEM_LOG_REL_CPU_FEATURE
     276    if (Caps.ProcessorFeatures.AsUINT64 & (~(RT_BIT_64(43) - 1) | RT_BIT_64(27) | RT_BIT_64(28)))
     277        LogRel(("NEM: Warning! Unknown CPU features: %#RX64\n", Caps.ProcessorFeatures.AsUINT64));
     278    pVM->nem.s.uCpuFeatures.u64 = Caps.ProcessorFeatures.AsUINT64;
     279    /** @todo RECHECK: WHV_PROCESSOR_FEATURES typedef. */
     280
     281    /*
     282     * The cache line flush size.
     283     */
     284    RT_ZERO(Caps);
     285    hrc = WHvGetCapability(WHvCapabilityCodeProcessorClFlushSize, &Caps, sizeof(Caps));
     286    if (FAILED(hrc))
     287        return RTErrInfoSetF(pErrInfo, VERR_NEM_INIT_FAILED, "WHvGetCapability/WHvCapabilityCodeProcessorClFlushSize failed: %Rhrc", hrc);
     288    NEM_LOG_REL_CAP_EX("WHvCapabilityCodeProcessorClFlushSize", "2^%u", Caps.ProcessorClFlushSize);
     289
     290    /*
     291     * See if they've added more properties that we're not aware of.
     292     */
     293    /** @todo RECHECK: WHV_CAPABILITY_CODE typedef. */
     294    if (!IsDebuggerPresent()) /* Too noisy when in debugger, so skip. */
     295    {
     296        static const struct
     297        {
     298            uint32_t iMin, iMax; } s_aUnknowns[] =
     299        {
     300            { 0x0003, 0x000f },
     301            { 0x1003, 0x100f },
     302            { 0x2000, 0x200f },
     303            { 0x3000, 0x300f },
     304            { 0x4000, 0x400f },
     305        };
     306        for (uint32_t j = 0; j < RT_ELEMENTS(s_aUnknowns); j++)
     307            for (uint32_t i = s_aUnknowns[j].iMin; i <= s_aUnknowns[j].iMax; i++)
     308            {
     309                RT_ZERO(Caps);
     310                hrc = WHvGetCapability((WHV_CAPABILITY_CODE)i, &Caps, sizeof(Caps));
     311                if (SUCCEEDED(hrc))
     312                    LogRel(("NEM: Warning! Unknown capability %#x returning: %.*Rhxs\n", i, sizeof(Caps), &Caps));
     313            }
     314    }
     315
     316#undef NEM_LOG_REL_CAP_EX
     317#undef NEM_LOG_REL_CAP_SUB_EX
     318#undef NEM_LOG_REL_CAP_SUB
     319    return VINF_SUCCESS;
     320}
    122321
    123322
     
    224423
    225424                                /*
    226                                  * Check if the hypervisor API is present.
     425                                 * Check the capabilties of the hypervisor, starting with whether it's present.
    227426                                 */
    228                                 /** @todo Someone (MS) please explain weird API design:
    229                                  *   1. Caps.CapabilityCode duplication,
    230                                  *   2. No output size.
    231                                  */
    232                                 WHV_CAPABILITY Caps;
    233                                 RT_ZERO(Caps);
    234                                 SetLastError(0);
    235                                 HRESULT hrc = WHvGetCapability(WHvCapabilityCodeHypervisorPresent, &Caps, sizeof(Caps));
    236                                 DWORD   rcWin = GetLastError();
    237                                 if (FAILED(hrc))
    238                                     rc = RTErrInfoSetF(pErrInfo, VERR_NEM_INIT_FAILED,
    239                                                        "WHvGetCapability/WHvCapabilityCodeHypervisorPresent failed: %Rhrc", hrc);
    240                                 else if (!Caps.HypervisorPresent)
     427                                rc = nemR3NativeInitCheckCapabilities(pVM, pErrInfo);
     428                                if (RT_SUCCESS(rc))
    241429                                {
    242                                     if (!RTPathExists(RTPATH_NT_PASSTHRU_PREFIX "Device\\VidExo"))
    243                                         rc = RTErrInfoSetF(pErrInfo, VERR_NEM_NOT_AVAILABLE,
    244                                                            "WHvCapabilityCodeHypervisorPresent is FALSE! Make sure you have enabled the 'Windows Hypervisor Platform' feature.");
    245                                     else
    246                                         rc = RTErrInfoSetF(pErrInfo, VERR_NEM_NOT_AVAILABLE,
    247                                                            "WHvCapabilityCodeHypervisorPresent is FALSE! (%u)", rcWin);
    248                                 }
    249                                 else
    250                                 {
    251                                     /*
    252                                      * .
    253                                      */
    254                                     LogRel(("NEM: WHvCapabilityCodeHypervisorPresent is TRUE, so this might work...\n"));
    255 
    256430                                    rc = RTErrInfoAddF(pErrInfo, VERR_NOT_IMPLEMENTED, "lazy bugger isn't done yet");
    257431                                }
  • trunk/src/VBox/VMM/include/NEMInternal.h

    r70918 r70944  
    2222#include <VBox/types.h>
    2323#include <VBox/vmm/nem.h>
     24#include <VBox/vmm/cpum.h> /* For CPUMCPUVENDOR. */
    2425#include <VBox/vmm/stam.h>
    2526#include <VBox/vmm/vmapi.h>
     
    4445    /** Set if enabled. */
    4546    bool                        fEnabled;
     47#ifdef RT_OS_WINDOWS
     48    /** WHvRunVpExitReasonX64Cpuid is supported. */
     49    bool                        fExtendedMsrExit;
     50    /** WHvRunVpExitReasonX64MsrAccess is supported. */
     51    bool                        fExtendedCpuIdExit;
     52    /** WHvRunVpExitReasonException is supported. */
     53    bool                        fExtendedXcptExit;
     54    /** The reported CPU vendor.   */
     55    CPUMCPUVENDOR               enmCpuVendor;
     56    /** Explicit padding. */
     57    uint32_t                    u32Padding1;
     58    /** The result of WHvCapabilityCodeProcessorFeatures. */
     59    union
     60    {
     61        /** 64-bit view. */
     62        uint64_t                u64;
     63# ifdef _WINHVAPIDEFS_H_
     64        /** Interpreed features. */
     65        WHV_PROCESSOR_FEATURES  u;
     66# endif
     67    } uCpuFeatures;
     68#endif
    4669
    4770} NEM;
Note: See TracChangeset for help on using the changeset viewer.

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