VirtualBox

Changeset 109008 in vbox


Ignore:
Timestamp:
Apr 16, 2025 8:59:36 PM (4 days ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
168536
Message:

VMM,Main: Working on ARM CPU profile support, which is neede/useful for getting info about the host CPU as well. The CPUDBENTRY typedef is used externally by Main, so we can't have two definitions of it, so left the bits that are common to both x86 and ARM in CPUDBENTRY and created sub-structures for each of the two targets/platforms. Also started reworking the VBoxCpuReport tool so we can use it on arm as well (much left to do there, though). jiraref:VBP-1598

Location:
trunk
Files:
1 added
39 edited
3 copied
1 moved

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/vmm/cpum-armv8.h

    r107929 r109008  
    166166
    167167
    168 /**
    169  * CPU database entry.
    170  */
    171 typedef struct CPUMDBENTRY
    172 {
    173     /** The CPU name. */
    174     const char     *pszName;
    175     /** The full CPU name. */
    176     const char     *pszFullName;
    177     /** The CPU vendor (CPUMCPUVENDOR). */
    178     uint8_t         enmVendor;
    179     /** The CPU family. */
    180     uint8_t         uFamily;
    181     /** The CPU model. */
    182     uint8_t         uModel;
    183     /** The CPU stepping. */
    184     uint8_t         uStepping;
    185     /** The microarchitecture. */
    186     CPUMMICROARCH   enmMicroarch;
    187     /** Scalable bus frequency used for reporting other frequencies. */
    188     uint64_t        uScalableBusFreq;
    189     /** Flags - CPUMDB_F_XXX. */
    190     uint32_t        fFlags;
    191     /** The maximum physical address with of the CPU.  This should correspond to
    192      * the value in CPUID leaf 0x80000008 when present. */
    193     uint8_t         cMaxPhysAddrWidth;
    194 } CPUMDBENTRY;
    195 /** Pointer to a const CPU database entry. */
    196 typedef CPUMDBENTRY const *PCCPUMDBENTRY;
    197 
    198 
    199 
    200168/** @name Changed flags.
    201169 * These flags are used to keep track of which important register that
  • trunk/include/VBox/vmm/cpum-x86-amd64.h

    r108968 r109008  
    8686    CPUMCPUIDFEATURE_32BIT_HACK = 0x7fffffff
    8787} CPUMCPUIDFEATURE;
    88 
    89 
    90 /**
    91  * Method used to deal with unknown CPUID leaves.
    92  * @remarks Used in patch code.
    93  */
    94 typedef enum CPUMUNKNOWNCPUID
    95 {
    96     /** Invalid zero value. */
    97     CPUMUNKNOWNCPUID_INVALID = 0,
    98     /** Use given default values (DefCpuId). */
    99     CPUMUNKNOWNCPUID_DEFAULTS,
    100     /** Return the last standard leaf.
    101      * Intel Sandy Bridge has been observed doing this. */
    102     CPUMUNKNOWNCPUID_LAST_STD_LEAF,
    103     /** Return the last standard leaf, with ecx observed.
    104      * Intel Sandy Bridge has been observed doing this. */
    105     CPUMUNKNOWNCPUID_LAST_STD_LEAF_WITH_ECX,
    106     /** The register values are passed thru unmodified. */
    107     CPUMUNKNOWNCPUID_PASSTHRU,
    108     /** End of valid value. */
    109     CPUMUNKNOWNCPUID_END,
    110     /** Ensure 32-bit type. */
    111     CPUMUNKNOWNCPUID_32BIT_HACK = 0x7fffffff
    112 } CPUMUNKNOWNCPUID;
    113 /** Pointer to unknown CPUID leaf method. */
    114 typedef CPUMUNKNOWNCPUID *PCPUMUNKNOWNCPUID;
    115 
    116 
    117 /**
    118  * The register set returned by a CPUID operation.
    119  */
    120 typedef struct CPUMCPUID
    121 {
    122     uint32_t uEax;
    123     uint32_t uEbx;
    124     uint32_t uEcx;
    125     uint32_t uEdx;
    126 } CPUMCPUID;
    127 /** Pointer to a CPUID leaf. */
    128 typedef CPUMCPUID *PCPUMCPUID;
    129 /** Pointer to a const CPUID leaf. */
    130 typedef const CPUMCPUID *PCCPUMCPUID;
    13188
    13289
     
    702659
    703660
    704 /**
    705  * CPU database entry.
    706  */
    707 typedef struct CPUMDBENTRY
    708 {
    709     /** The CPU name. */
    710     const char     *pszName;
    711     /** The full CPU name. */
    712     const char     *pszFullName;
    713     /** The CPU vendor (CPUMCPUVENDOR). */
    714     uint8_t         enmVendor;
    715     /** The CPU family. */
    716     uint8_t         uFamily;
    717     /** The CPU model. */
    718     uint8_t         uModel;
    719     /** The CPU stepping. */
    720     uint8_t         uStepping;
    721     /** The microarchitecture. */
    722     CPUMMICROARCH   enmMicroarch;
    723     /** Scalable bus frequency used for reporting other frequencies. */
    724     uint64_t        uScalableBusFreq;
    725     /** Flags - CPUMDB_F_XXX. */
    726     uint32_t        fFlags;
    727     /** The maximum physical address with of the CPU.  This should correspond to
    728      * the value in CPUID leaf 0x80000008 when present. */
    729     uint8_t         cMaxPhysAddrWidth;
    730     /** The MXCSR mask. */
    731     uint32_t        fMxCsrMask;
    732     /** Pointer to an array of CPUID leaves.  */
    733     PCCPUMCPUIDLEAF paCpuIdLeaves;
    734     /** The number of CPUID leaves in the array paCpuIdLeaves points to. */
    735     uint32_t        cCpuIdLeaves;
    736     /** The method used to deal with unknown CPUID leaves. */
    737     CPUMUNKNOWNCPUID enmUnknownCpuId;
    738     /** The default unknown CPUID value. */
    739     CPUMCPUID       DefUnknownCpuId;
    740 
    741     /** MSR mask.  Several microarchitectures ignore the higher bits of ECX in
    742      *  the RDMSR and WRMSR instructions. */
    743     uint32_t        fMsrMask;
    744 
    745     /** The number of ranges in the table pointed to b paMsrRanges. */
    746     uint32_t        cMsrRanges;
    747     /** MSR ranges for this CPU. */
    748     PCCPUMMSRRANGE  paMsrRanges;
    749 } CPUMDBENTRY;
    750 /** Pointer to a const CPU database entry. */
    751 typedef CPUMDBENTRY const *PCCPUMDBENTRY;
    752 
    753 /** @name CPUMDB_F_XXX - CPUDBENTRY::fFlags
    754  * @{ */
    755 /** Should execute all in IEM.
    756  * @todo Implement this - currently done in Main...  */
    757 #define CPUMDB_F_EXECUTE_ALL_IN_IEM         RT_BIT_32(0)
    758 /** @} */
    759 
    760 
    761 
    762661#ifndef VBOX_FOR_DTRACE_LIB
    763662
  • trunk/include/VBox/vmm/cpum.h

    r108968 r109008  
    15701570
    15711571
     1572/**
     1573 * Method used to deal with unknown CPUID leaves on x86.
     1574 */
     1575typedef enum CPUMUNKNOWNCPUID
     1576{
     1577    /** Invalid zero value. */
     1578    CPUMUNKNOWNCPUID_INVALID = 0,
     1579    /** Use given default values (DefCpuId). */
     1580    CPUMUNKNOWNCPUID_DEFAULTS,
     1581    /** Return the last standard leaf.
     1582     * Intel Sandy Bridge has been observed doing this. */
     1583    CPUMUNKNOWNCPUID_LAST_STD_LEAF,
     1584    /** Return the last standard leaf, with ecx observed.
     1585     * Intel Sandy Bridge has been observed doing this. */
     1586    CPUMUNKNOWNCPUID_LAST_STD_LEAF_WITH_ECX,
     1587    /** The register values are passed thru unmodified. */
     1588    CPUMUNKNOWNCPUID_PASSTHRU,
     1589    /** End of valid value. */
     1590    CPUMUNKNOWNCPUID_END,
     1591    /** Ensure 32-bit type. */
     1592    CPUMUNKNOWNCPUID_32BIT_HACK = 0x7fffffff
     1593} CPUMUNKNOWNCPUID;
     1594/** Pointer to unknown CPUID leaf method. */
     1595typedef CPUMUNKNOWNCPUID *PCPUMUNKNOWNCPUID;
     1596
     1597
     1598/**
     1599 * The register set returned by an x86 CPUID operation.
     1600 */
     1601typedef struct CPUMCPUID
     1602{
     1603    uint32_t uEax;
     1604    uint32_t uEbx;
     1605    uint32_t uEcx;
     1606    uint32_t uEdx;
     1607} CPUMCPUID;
     1608/** Pointer to a CPUID leaf. */
     1609typedef CPUMCPUID *PCPUMCPUID;
     1610/** Pointer to a const CPUID leaf. */
     1611typedef const CPUMCPUID *PCCPUMCPUID;
     1612
    15721613
    15731614/**
     
    16141655
    16151656
     1657/** For identifying the extended database entry type. */
     1658typedef enum CPUMDBENTRYTYPE
     1659{
     1660    CPUMDBENTRYTYPE_INVALID = 0,
     1661    CPUMDBENTRYTYPE_X86,
     1662    CPUMDBENTRYTYPE_ARM,
     1663    CPUMDBENTRYTYPE_END,
     1664    CPUMDBENTRYTYPE_32BIT_HACK = 0x7fffffff
     1665} CPUMDBENTRYTYPE;
     1666
     1667/**
     1668 * CPU database entry, common parts.
     1669 */
     1670typedef struct CPUMDBENTRY
     1671{
     1672    /** The CPU name. */
     1673    const char     *pszName;
     1674    /** The full CPU name. */
     1675    const char     *pszFullName;
     1676    /** The CPU vendor. */
     1677    CPUMCPUVENDOR   enmVendor;
     1678    /** The microarchitecture. */
     1679    CPUMMICROARCH   enmMicroarch;
     1680    /** Flags - CPUMDB_F_XXX. */
     1681    uint32_t        fFlags;
     1682    /** The database entry type. */
     1683    CPUMDBENTRYTYPE enmEntryType;
     1684} CPUMDBENTRY;
     1685/** Pointer to a const CPU database entry. */
     1686typedef CPUMDBENTRY const *PCCPUMDBENTRY;
     1687
     1688/** @name CPUMDB_F_XXX - CPUDBENTRY::fFlags
     1689 * @{ */
     1690/** Should execute all in IEM.
     1691 * @todo Implement this - currently done in Main...  */
     1692#define CPUMDB_F_EXECUTE_ALL_IN_IEM         RT_BIT_32(0)
     1693/** @} */
     1694
     1695
     1696/**
     1697 * CPU database entry for x86.
     1698 */
     1699typedef struct CPUMDBENTRYX86
     1700{
     1701    CPUMDBENTRY     Core;
     1702    /** The CPU family. */
     1703    uint8_t         uFamily;
     1704    /** The CPU model. */
     1705    uint8_t         uModel;
     1706    /** The CPU stepping. */
     1707    uint8_t         uStepping;
     1708    /** Scalable bus frequency used for reporting other frequencies. */
     1709    uint64_t        uScalableBusFreq;
     1710    /** The maximum physical address with of the CPU.  This should correspond to
     1711     * the value in CPUID leaf 0x80000008 when present. */
     1712    uint8_t         cMaxPhysAddrWidth;
     1713    /** The MXCSR mask. */
     1714    uint32_t        fMxCsrMask;
     1715    /** Pointer to an array of CPUID leaves.  */
     1716    PCCPUMCPUIDLEAF paCpuIdLeaves;
     1717    /** The number of CPUID leaves in the array paCpuIdLeaves points to. */
     1718    uint32_t        cCpuIdLeaves;
     1719    /** The method used to deal with unknown CPUID leaves. */
     1720    CPUMUNKNOWNCPUID enmUnknownCpuId;
     1721    /** The default unknown CPUID value. */
     1722    CPUMCPUID       DefUnknownCpuId;
     1723
     1724    /** MSR mask.  Several microarchitectures ignore the higher bits of ECX in
     1725     *  the RDMSR and WRMSR instructions. */
     1726    uint32_t        fMsrMask;
     1727
     1728    /** The number of ranges in the table pointed to b paMsrRanges. */
     1729    uint32_t        cMsrRanges;
     1730    /** MSR ranges for this CPU. */
     1731    struct CPUMMSRRANGE const *paMsrRanges;
     1732} CPUMDBENTRYX86;
     1733/** Pointer to a const X86 CPU database entry. */
     1734typedef CPUMDBENTRYX86 const *PCCPUMDBENTRYX86;
     1735
     1736
     1737/**
     1738 * CPU database entry for ARM.
     1739 */
     1740typedef struct CPUMDBENTRYARM
     1741{
     1742    /** The common parts. */
     1743    CPUMDBENTRY     Core;
     1744
     1745    /** The CPU family. */
     1746    uint8_t         uFamily;
     1747    /** The CPU model. */
     1748    uint8_t         uModel;
     1749    /** The CPU stepping. */
     1750    uint8_t         uStepping;
     1751    /** Scalable bus frequency used for reporting other frequencies. */
     1752    uint64_t        uScalableBusFreq;
     1753    /** The maximum physical address with of the CPU.  This should correspond to
     1754     * the value in CPUID leaf 0x80000008 when present. */
     1755    uint8_t         cMaxPhysAddrWidth;
     1756
     1757    /** @todo lots more to be added here... */
     1758} CPUMDBENTRYARM;
     1759/** Pointer to a const ARM CPU database entry. */
     1760typedef CPUMDBENTRYARM const *PCCPUMDBENTRYARM;
     1761
     1762
    16161763/*
    16171764 * Include the target specific header.
  • trunk/src/VBox/Main/include/SystemPropertiesImpl.h

    r106061 r109008  
    3636#include "MediumFormatImpl.h"
    3737#include "SystemPropertiesWrap.h"
     38
     39#include <VBox/vmm/cpum.h> /* for CPUMDBENTRYTYPE */
    3840
    3941class CPUProfile;
     
    168170    HRESULT i_setDefaultFrontend(const com::Utf8Str &aDefaultFrontend);
    169171
     172    HRESULT i_loadCPUProfilesFromVMM(const char *a_pszVMM, CPUMDBENTRYTYPE a_enmEntryType);
     173
    170174    VirtualBox * const  mParent;
    171175
     
    176180    ComObjPtr<PlatformProperties> const m_platformProperties;       /**< The host's platform properties. */
    177181    bool                                m_fLoadedX86CPUProfiles;    /**< Set if we've loaded the x86 and AMD64 CPU profiles. */
     182    bool                                m_fLoadedArmCPUProfiles;    /**< Set if we've loaded the ARM CPU profiles. */
    178183    CPUProfileList_T                    m_llCPUProfiles;            /**< List of loaded CPU profiles. */
    179184
  • trunk/src/VBox/Main/src-server/CPUProfileImpl.cpp

    r106061 r109008  
    6868
    6969    /* Determin x86 or AMD64 by scanning the CPUID leaves for the long mode feature bit: */
    70     m_enmArchitecture = CPUArchitecture_x86;
    71     uint32_t iLeaf = a_pDbEntry->cCpuIdLeaves;
    72     while (iLeaf-- > 0)
    73         if (a_pDbEntry->paCpuIdLeaves[iLeaf].uLeaf <= UINT32_C(0x80000001))
    74         {
    75             if (   a_pDbEntry->paCpuIdLeaves[iLeaf].uLeaf == UINT32_C(0x80000001)
    76                 && (a_pDbEntry->paCpuIdLeaves[iLeaf].uEdx & X86_CPUID_EXT_FEATURE_EDX_LONG_MODE))
    77                 m_enmArchitecture = CPUArchitecture_AMD64;
    78             break;
    79         }
     70    if (a_pDbEntry->enmEntryType == CPUMDBENTRYTYPE_X86)
     71    {
     72        m_enmArchitecture = CPUArchitecture_x86;
     73        PCCPUMDBENTRYX86 const pDbEntryX86 = (PCCPUMDBENTRYX86)a_pDbEntry;
     74        uint32_t iLeaf = pDbEntryX86->cCpuIdLeaves;
     75        while (iLeaf-- > 0)
     76            if (pDbEntryX86->paCpuIdLeaves[iLeaf].uLeaf <= UINT32_C(0x80000001))
     77            {
     78                if (   pDbEntryX86->paCpuIdLeaves[iLeaf].uLeaf == UINT32_C(0x80000001)
     79                    && (pDbEntryX86->paCpuIdLeaves[iLeaf].uEdx & X86_CPUID_EXT_FEATURE_EDX_LONG_MODE))
     80                    m_enmArchitecture = CPUArchitecture_AMD64;
     81                break;
     82            }
     83    }
     84    else if (a_pDbEntry->enmEntryType == CPUMDBENTRYTYPE_ARM)
     85        m_enmArchitecture = CPUArchitecture_ARMv8_64;
    8086
    8187    HRESULT hrc = m_strName.assignEx(a_pDbEntry->pszName);
     
    117123{
    118124    if (   m_enmArchitecture == a_enmArchitecture
    119         || m_enmArchitecture == a_enmSecondaryArch)
     125        || m_enmArchitecture == a_enmSecondaryArch
     126        || a_enmArchitecture == CPUArchitecture_Any)
    120127    {
    121128        if (a_strNamePattern.isEmpty())
  • trunk/src/VBox/Main/src-server/SystemPropertiesImpl.cpp

    r108641 r109008  
    6565    , m(new settings::SystemProperties)
    6666    , m_fLoadedX86CPUProfiles(false)
     67    , m_fLoadedArmCPUProfiles(false)
    6768{
    6869}
     
    292293}
    293294
     295/**
     296 * Helper for getCPUProfiles() that loads profiles from one VMM module.
     297 */
     298HRESULT SystemProperties::i_loadCPUProfilesFromVMM(const char *a_pszVMM, CPUMDBENTRYTYPE a_enmEntryType)
     299{
     300    HRESULT hrc;
     301    char szPath[RTPATH_MAX];
     302    int vrc = RTPathAppPrivateArch(szPath, sizeof(szPath));
     303    if (RT_SUCCESS(vrc))
     304        vrc = RTPathAppend(szPath, sizeof(szPath), a_pszVMM);
     305    if (RT_SUCCESS(vrc))
     306        vrc = RTStrCat(szPath, sizeof(szPath), RTLdrGetSuff());
     307    if (RT_SUCCESS(vrc))
     308    {
     309        RTLDRMOD hMod = NIL_RTLDRMOD;
     310        vrc = RTLdrLoad(szPath, &hMod);
     311        if (RT_SUCCESS(vrc))
     312        {
     313            /*
     314             * Resolve the CPUMDb APIs we need.
     315             */
     316            PFNCPUMDBGETENTRIES      pfnGetEntries
     317                = (PFNCPUMDBGETENTRIES)RTLdrGetFunction(hMod, "CPUMR3DbGetEntries");
     318            PFNCPUMDBGETENTRYBYINDEX pfnGetEntryByIndex
     319                = (PFNCPUMDBGETENTRYBYINDEX)RTLdrGetFunction(hMod, "CPUMR3DbGetEntryByIndex");
     320            if (pfnGetEntries && pfnGetEntryByIndex)
     321            {
     322                size_t const cExistingProfiles = m_llCPUProfiles.size();
     323
     324                /*
     325                 * Instantate the profiles.
     326                 */
     327                hrc = S_OK;
     328                uint32_t const cEntries = pfnGetEntries();
     329                for (uint32_t i = 0; i < cEntries; i++)
     330                {
     331                    PCCPUMDBENTRY pDbEntry = pfnGetEntryByIndex(i);
     332                    AssertBreakStmt(pDbEntry, hrc = setError(E_UNEXPECTED, "CPUMR3DbGetEntryByIndex failed for %i", i));
     333                    if (pDbEntry->enmEntryType == a_enmEntryType)
     334                    {
     335                        ComObjPtr<CPUProfile> ptrProfile;
     336                        hrc = ptrProfile.createObject();
     337                        if (SUCCEEDED(hrc))
     338                        {
     339                            hrc = ptrProfile->initFromDbEntry(pDbEntry);
     340                            if (SUCCEEDED(hrc))
     341                            {
     342                                try
     343                                {
     344                                    m_llCPUProfiles.push_back(ptrProfile);
     345                                    continue;
     346                                }
     347                                catch (std::bad_alloc &)
     348                                {
     349                                    hrc = E_OUTOFMEMORY;
     350                                }
     351                            }
     352                        }
     353                        break;
     354                    }
     355                }
     356
     357                /*
     358                 * If we fail, drop the profiles we added to the list.
     359                 */
     360                if (FAILED(hrc))
     361                    m_llCPUProfiles.resize(cExistingProfiles);
     362            }
     363            else
     364                hrc = setErrorVrc(VERR_SYMBOL_NOT_FOUND,
     365                                  tr("'%s' is missing symbols: CPUMR3DbGetEntries, CPUMR3DbGetEntryByIndex"), szPath);
     366            RTLdrClose(hMod);
     367        }
     368        else
     369            hrc = setErrorVrc(vrc, tr("Failed to construct load '%s': %Rrc"), szPath, vrc);
     370    }
     371    else
     372        hrc = setErrorVrc(vrc, tr("Failed to construct path to the VMM DLL/Dylib/SharedObject: %Rrc"), vrc);
     373    return hrc;
     374}
     375
     376
    294377HRESULT SystemProperties::getCPUProfiles(CPUArchitecture_T aArchitecture, const com::Utf8Str &aNamePattern,
    295378                                         std::vector<ComPtr<ICPUProfile> > &aProfiles)
     
    304387    {
    305388        case CPUArchitecture_Any:
    306             aArchitecture = CPUArchitecture_AMD64;
    307             RT_FALL_THROUGH();
     389            fLoaded = m_fLoadedArmCPUProfiles && m_fLoadedX86CPUProfiles;
     390            break;
     391
    308392        case CPUArchitecture_AMD64:
    309393            enmSecondaryArch = CPUArchitecture_x86;
     
    312396            fLoaded = m_fLoadedX86CPUProfiles;
    313397            break;
     398
     399        case CPUArchitecture_ARMv8_64:
     400            enmSecondaryArch = CPUArchitecture_ARMv8_32;
     401            RT_FALL_THROUGH();
     402        case CPUArchitecture_ARMv8_32:
     403            fLoaded = m_fLoadedArmCPUProfiles;
     404            break;
     405
    314406        default:
    315407            return setError(E_INVALIDARG, tr("Invalid or unsupported architecture value: %d"), aArchitecture);
     
    328420
    329421        /*
    330          * Translate the architecture to a VMM module handle.
     422         * Load AMD64 & X86 profiles from VBoxVMM.dll/so/dylib if requested and required.
    331423         */
    332         const char *pszVMM;
    333         switch (aArchitecture)
     424        hrc = S_OK;
     425        if (   (   aArchitecture == CPUArchitecture_Any
     426                || aArchitecture == CPUArchitecture_AMD64
     427                || aArchitecture == CPUArchitecture_x86)
     428            && !m_fLoadedX86CPUProfiles)
    334429        {
    335             case CPUArchitecture_AMD64:
    336             case CPUArchitecture_x86:
    337                 pszVMM = "VBoxVMM";
    338                 fLoaded = m_fLoadedX86CPUProfiles;
    339                 break;
    340             default:
    341                 AssertFailedReturn(E_INVALIDARG);
     430            hrc = i_loadCPUProfilesFromVMM("VBoxVMM", CPUMDBENTRYTYPE_X86);
     431            if (SUCCEEDED(hrc))
     432                m_fLoadedX86CPUProfiles = true;
    342433        }
    343         if (fLoaded)
    344             hrc = S_OK;
    345         else
     434
     435        /*
     436         * Load ARM profiles from VBoxVMM.dll/so/dylib if requested and required.
     437         */
     438        if (   (   aArchitecture == CPUArchitecture_Any
     439                || aArchitecture == CPUArchitecture_ARMv8_64
     440                || aArchitecture == CPUArchitecture_ARMv8_32)
     441            && !m_fLoadedArmCPUProfiles)
    346442        {
    347             char szPath[RTPATH_MAX];
    348             int vrc = RTPathAppPrivateArch(szPath, sizeof(szPath));
    349             if (RT_SUCCESS(vrc))
    350                 vrc = RTPathAppend(szPath, sizeof(szPath), pszVMM);
    351             if (RT_SUCCESS(vrc))
    352                 vrc = RTStrCat(szPath, sizeof(szPath), RTLdrGetSuff());
    353             if (RT_SUCCESS(vrc))
    354             {
    355                 RTLDRMOD hMod = NIL_RTLDRMOD;
    356                 vrc = RTLdrLoad(szPath, &hMod);
    357                 if (RT_SUCCESS(vrc))
    358                 {
    359                     /*
    360                      * Resolve the CPUMDb APIs we need.
    361                      */
    362                     PFNCPUMDBGETENTRIES      pfnGetEntries
    363                         = (PFNCPUMDBGETENTRIES)RTLdrGetFunction(hMod, "CPUMR3DbGetEntries");
    364                     PFNCPUMDBGETENTRYBYINDEX pfnGetEntryByIndex
    365                         = (PFNCPUMDBGETENTRYBYINDEX)RTLdrGetFunction(hMod, "CPUMR3DbGetEntryByIndex");
    366                     if (pfnGetEntries && pfnGetEntryByIndex)
    367                     {
    368                         size_t const cExistingProfiles = m_llCPUProfiles.size();
    369 
    370                         /*
    371                          * Instantate the profiles.
    372                          */
    373                         hrc = S_OK;
    374                         uint32_t const cEntries = pfnGetEntries();
    375                         for (uint32_t i = 0; i < cEntries; i++)
    376                         {
    377                             PCCPUMDBENTRY pDbEntry = pfnGetEntryByIndex(i);
    378                             AssertBreakStmt(pDbEntry, hrc = setError(E_UNEXPECTED, "CPUMR3DbGetEntryByIndex failed for %i", i));
    379 
    380                             ComObjPtr<CPUProfile> ptrProfile;
    381                             hrc = ptrProfile.createObject();
    382                             if (SUCCEEDED(hrc))
    383                             {
    384                                 hrc = ptrProfile->initFromDbEntry(pDbEntry);
    385                                 if (SUCCEEDED(hrc))
    386                                 {
    387                                     try
    388                                     {
    389                                         m_llCPUProfiles.push_back(ptrProfile);
    390                                         continue;
    391                                     }
    392                                     catch (std::bad_alloc &)
    393                                     {
    394                                         hrc = E_OUTOFMEMORY;
    395                                     }
    396                                 }
    397                             }
    398                             break;
    399                         }
    400 
    401                         /*
    402                          * On success update the flag and retake the read lock.
    403                          * If we fail, drop the profiles we added to the list.
    404                          */
    405                         if (SUCCEEDED(hrc))
    406                         {
    407                             switch (aArchitecture)
    408                             {
    409                                 case CPUArchitecture_AMD64:
    410                                 case CPUArchitecture_x86:
    411                                     m_fLoadedX86CPUProfiles = true;
    412                                     break;
    413                                 default:
    414                                     AssertFailedStmt(hrc = E_INVALIDARG);
    415                             }
    416 
    417                             alockWrite.release();
    418                             alock.acquire();
    419                         }
    420                         else
    421                             m_llCPUProfiles.resize(cExistingProfiles);
    422                     }
    423                     else
    424                         hrc = setErrorVrc(VERR_SYMBOL_NOT_FOUND,
    425                                           tr("'%s' is missing symbols: CPUMR3DbGetEntries, CPUMR3DbGetEntryByIndex"), szPath);
    426                     RTLdrClose(hMod);
    427                 }
    428                 else
    429                     hrc = setErrorVrc(vrc, tr("Failed to construct load '%s': %Rrc"), szPath, vrc);
    430             }
    431             else
    432                 hrc = setErrorVrc(vrc, tr("Failed to construct path to the VMM DLL/Dylib/SharedObject: %Rrc"), vrc);
     443            hrc = i_loadCPUProfilesFromVMM("VBoxVMMArm", CPUMDBENTRYTYPE_ARM);
     444            if (SUCCEEDED(hrc))
     445                m_fLoadedArmCPUProfiles = true;
    433446        }
     447
     448        alockWrite.release();
     449        alock.acquire();
    434450    }
    435451    if (SUCCEEDED(hrc))
  • trunk/src/VBox/VMM/Makefile.kmk

    r108972 r109008  
    115115        VMMR3/CPUMR3CpuId.cpp \
    116116        VMMR3/CPUMR3Db.cpp \
     117        VMMR3/CPUMR3Msr-x86.cpp \
    117118        VMMR3/CPUMDbg.cpp \
    118119        VMMR3/DBGF.cpp \
     
    457458        VMMAll/CPUMAllCpuId.cpp \
    458459        VMMR3/CPUMR3CpuId-armv8.cpp \
    459         VMMR3/CPUMR3Db-armv8.cpp \
     460        VMMR3/CPUMR3Db.cpp \
     461        VMMR3/CPUMR3SysReg-armv8.cpp \
    460462        VMMR3/DBGF.cpp \
    461463        VMMR3/DBGFAddr.cpp \
     
    11201122 SSMStandalone_INCS    = include
    11211123 SSMStandalone_SOURCES = \
    1122         VMMR3/SSM.cpp \
    1123         VMMR3/CPUMR3Db.cpp
     1124        VMMR3/SSM.cpp
    11241125endif # !VBOX_ONLY_BUILD
    11251126
  • trunk/src/VBox/VMM/VMMR3/CPUMR3Db.cpp

    r107854 r109008  
    55
    66/*
    7  * Copyright (C) 2013-2024 Oracle and/or its affiliates.
     7 * Copyright (C) 2013-2025 Oracle and/or its affiliates.
    88 *
    99 * This file is part of VirtualBox base platform packages, as
     
    4242#include <iprt/mem.h>
    4343#include <iprt/string.h>
     44
     45
     46/*********************************************************************************************************************************
     47*   Internal Functions                                                                                                           *
     48*********************************************************************************************************************************/
     49static int cpumDbPopulateInfoFromEntry(PCPUMINFO pInfo, PCCPUMDBENTRY pEntryCore, bool fHost);
    4450
    4551
     
    6268
    6369
    64 /** @name Short macros for the MSR range entries.
    65  *
    66  * These are rather cryptic, but this is to reduce the attack on the right
    67  * margin.
    68  *
    69  * @{ */
    70 /** Alias one MSR onto another (a_uTarget). */
    71 #define MAL(a_uMsr, a_szName, a_uTarget) \
    72     RINT(a_uMsr, a_uMsr, kCpumMsrRdFn_MsrAlias, kCpumMsrWrFn_MsrAlias, 0, a_uTarget, 0, 0, a_szName)
    73 /** Functions handles everything. */
    74 #define MFN(a_uMsr, a_szName, a_enmRdFnSuff, a_enmWrFnSuff) \
    75     RINT(a_uMsr, a_uMsr, kCpumMsrRdFn_##a_enmRdFnSuff, kCpumMsrWrFn_##a_enmWrFnSuff, 0, 0, 0, 0, a_szName)
    76 /** Functions handles everything, with GP mask. */
    77 #define MFG(a_uMsr, a_szName, a_enmRdFnSuff, a_enmWrFnSuff, a_fWrGpMask) \
    78     RINT(a_uMsr, a_uMsr, kCpumMsrRdFn_##a_enmRdFnSuff, kCpumMsrWrFn_##a_enmWrFnSuff, 0, 0, 0, a_fWrGpMask, a_szName)
    79 /** Function handlers, read-only. */
    80 #define MFO(a_uMsr, a_szName, a_enmRdFnSuff) \
    81     RINT(a_uMsr, a_uMsr, kCpumMsrRdFn_##a_enmRdFnSuff, kCpumMsrWrFn_ReadOnly, 0, 0, 0, UINT64_MAX, a_szName)
    82 /** Function handlers, ignore all writes. */
    83 #define MFI(a_uMsr, a_szName, a_enmRdFnSuff) \
    84     RINT(a_uMsr, a_uMsr, kCpumMsrRdFn_##a_enmRdFnSuff, kCpumMsrWrFn_IgnoreWrite, 0, 0, UINT64_MAX, 0, a_szName)
    85 /** Function handlers, with value. */
    86 #define MFV(a_uMsr, a_szName, a_enmRdFnSuff, a_enmWrFnSuff, a_uValue) \
    87     RINT(a_uMsr, a_uMsr, kCpumMsrRdFn_##a_enmRdFnSuff, kCpumMsrWrFn_##a_enmWrFnSuff, 0, a_uValue, 0, 0, a_szName)
    88 /** Function handlers, with write ignore mask. */
    89 #define MFW(a_uMsr, a_szName, a_enmRdFnSuff, a_enmWrFnSuff, a_fWrIgnMask) \
    90     RINT(a_uMsr, a_uMsr, kCpumMsrRdFn_##a_enmRdFnSuff, kCpumMsrWrFn_##a_enmWrFnSuff, 0, 0, a_fWrIgnMask, 0, a_szName)
    91 /** Function handlers, extended version. */
    92 #define MFX(a_uMsr, a_szName, a_enmRdFnSuff, a_enmWrFnSuff, a_uValue, a_fWrIgnMask, a_fWrGpMask) \
    93     RINT(a_uMsr, a_uMsr, kCpumMsrRdFn_##a_enmRdFnSuff, kCpumMsrWrFn_##a_enmWrFnSuff, 0, a_uValue, a_fWrIgnMask, a_fWrGpMask, a_szName)
    94 /** Function handlers, with CPUMCPU storage variable. */
    95 #define MFS(a_uMsr, a_szName, a_enmRdFnSuff, a_enmWrFnSuff, a_CpumCpuMember) \
    96     RINT(a_uMsr, a_uMsr, kCpumMsrRdFn_##a_enmRdFnSuff, kCpumMsrWrFn_##a_enmWrFnSuff, \
    97          RT_OFFSETOF(CPUMCPU, a_CpumCpuMember), 0, 0, 0, a_szName)
    98 /** Function handlers, with CPUMCPU storage variable, ignore mask and GP mask. */
    99 #define MFZ(a_uMsr, a_szName, a_enmRdFnSuff, a_enmWrFnSuff, a_CpumCpuMember, a_fWrIgnMask, a_fWrGpMask) \
    100     RINT(a_uMsr, a_uMsr, kCpumMsrRdFn_##a_enmRdFnSuff, kCpumMsrWrFn_##a_enmWrFnSuff, \
    101          RT_OFFSETOF(CPUMCPU, a_CpumCpuMember), 0, a_fWrIgnMask, a_fWrGpMask, a_szName)
    102 /** Read-only fixed value. */
    103 #define MVO(a_uMsr, a_szName, a_uValue) \
    104     RINT(a_uMsr, a_uMsr, kCpumMsrRdFn_FixedValue, kCpumMsrWrFn_ReadOnly, 0, a_uValue, 0, UINT64_MAX, a_szName)
    105 /** Read-only fixed value, ignores all writes. */
    106 #define MVI(a_uMsr, a_szName, a_uValue) \
    107     RINT(a_uMsr, a_uMsr, kCpumMsrRdFn_FixedValue, kCpumMsrWrFn_IgnoreWrite, 0, a_uValue, UINT64_MAX, 0, a_szName)
    108 /** Read fixed value, ignore writes outside GP mask. */
    109 #define MVG(a_uMsr, a_szName, a_uValue, a_fWrGpMask) \
    110     RINT(a_uMsr, a_uMsr, kCpumMsrRdFn_FixedValue, kCpumMsrWrFn_IgnoreWrite, 0, a_uValue, 0, a_fWrGpMask, a_szName)
    111 /** Read fixed value, extended version with both GP and ignore masks. */
    112 #define MVX(a_uMsr, a_szName, a_uValue, a_fWrIgnMask, a_fWrGpMask) \
    113     RINT(a_uMsr, a_uMsr, kCpumMsrRdFn_FixedValue, kCpumMsrWrFn_IgnoreWrite, 0, a_uValue, a_fWrIgnMask, a_fWrGpMask, a_szName)
    114 /** The short form, no CPUM backing. */
    115 #define MSN(a_uMsr, a_szName, a_enmRdFnSuff, a_enmWrFnSuff, a_uInitOrReadValue, a_fWrIgnMask, a_fWrGpMask) \
    116     RINT(a_uMsr, a_uMsr, kCpumMsrRdFn_##a_enmRdFnSuff, kCpumMsrWrFn_##a_enmWrFnSuff, 0, \
    117          a_uInitOrReadValue, a_fWrIgnMask, a_fWrGpMask, a_szName)
    118 
    119 /** Range: Functions handles everything. */
    120 #define RFN(a_uFirst, a_uLast, a_szName, a_enmRdFnSuff, a_enmWrFnSuff) \
    121     RINT(a_uFirst, a_uLast, kCpumMsrRdFn_##a_enmRdFnSuff, kCpumMsrWrFn_##a_enmWrFnSuff, 0, 0, 0, 0, a_szName)
    122 /** Range: Read fixed value, read-only. */
    123 #define RVO(a_uFirst, a_uLast, a_szName, a_uValue) \
    124     RINT(a_uFirst, a_uLast, kCpumMsrRdFn_FixedValue, kCpumMsrWrFn_ReadOnly, 0, a_uValue, 0, UINT64_MAX, a_szName)
    125 /** Range: Read fixed value, ignore writes. */
    126 #define RVI(a_uFirst, a_uLast, a_szName, a_uValue) \
    127     RINT(a_uFirst, a_uLast, kCpumMsrRdFn_FixedValue, kCpumMsrWrFn_IgnoreWrite, 0, a_uValue, UINT64_MAX, 0, a_szName)
    128 /** Range: The short form, no CPUM backing. */
    129 #define RSN(a_uFirst, a_uLast, a_szName, a_enmRdFnSuff, a_enmWrFnSuff, a_uInitOrReadValue, a_fWrIgnMask, a_fWrGpMask) \
    130     RINT(a_uFirst, a_uLast, kCpumMsrRdFn_##a_enmRdFnSuff, kCpumMsrWrFn_##a_enmWrFnSuff, 0, \
    131          a_uInitOrReadValue, a_fWrIgnMask, a_fWrGpMask, a_szName)
    132 
    133 /** Internal form used by the macros. */
    134 #ifdef VBOX_WITH_STATISTICS
    135 # define RINT(a_uFirst, a_uLast, a_enmRdFn, a_enmWrFn, a_offCpumCpu, a_uInitOrReadValue, a_fWrIgnMask, a_fWrGpMask, a_szName) \
    136     { a_uFirst, a_uLast, a_enmRdFn, a_enmWrFn, a_offCpumCpu, 0, a_uInitOrReadValue, a_fWrIgnMask, a_fWrGpMask, a_szName, \
    137       { 0 }, { 0 }, { 0 }, { 0 } }
    138 #else
    139 # define RINT(a_uFirst, a_uLast, a_enmRdFn, a_enmWrFn, a_offCpumCpu, a_uInitOrReadValue, a_fWrIgnMask, a_fWrGpMask, a_szName) \
    140     { a_uFirst, a_uLast, a_enmRdFn, a_enmWrFn, a_offCpumCpu, 0, a_uInitOrReadValue, a_fWrIgnMask, a_fWrGpMask, a_szName }
     70/*********************************************************************************************************************************
     71*   Global Variables                                                                                                             *
     72*********************************************************************************************************************************/
     73/*
     74 * Include the X86 profiles.
     75 */
     76#if defined(VBOX_VMM_TARGET_X86)
     77
     78# include "CPUMR3Msr-x86.h" /* MSR macros needed by the profiles. */
     79
     80# include "cpus/Intel_Core_i7_6700K.h"
     81# include "cpus/Intel_Core_i7_5600U.h"
     82# include "cpus/Intel_Core_i7_3960X.h"
     83# include "cpus/Intel_Core_i5_3570.h"
     84# include "cpus/Intel_Core_i7_2635QM.h"
     85# include "cpus/Intel_Xeon_X5482_3_20GHz.h"
     86# include "cpus/Intel_Core2_X6800_2_93GHz.h"
     87# include "cpus/Intel_Core2_T7600_2_33GHz.h"
     88# include "cpus/Intel_Core_Duo_T2600_2_16GHz.h"
     89# include "cpus/Intel_Pentium_M_processor_2_00GHz.h"
     90# include "cpus/Intel_Pentium_4_3_00GHz.h"
     91# include "cpus/Intel_Pentium_N3530_2_16GHz.h"
     92# include "cpus/Intel_Atom_330_1_60GHz.h"
     93# include "cpus/Intel_80486.h"
     94# include "cpus/Intel_80386.h"
     95# include "cpus/Intel_80286.h"
     96# include "cpus/Intel_80186.h"
     97# include "cpus/Intel_8086.h"
     98
     99# include "cpus/AMD_Ryzen_7_1800X_Eight_Core.h"
     100# include "cpus/AMD_FX_8150_Eight_Core.h"
     101# include "cpus/AMD_Phenom_II_X6_1100T.h"
     102# include "cpus/Quad_Core_AMD_Opteron_2384.h"
     103# include "cpus/AMD_Athlon_64_X2_Dual_Core_4200.h"
     104# include "cpus/AMD_Athlon_64_3200.h"
     105
     106# include "cpus/VIA_QuadCore_L4700_1_2_GHz.h"
     107
     108# include "cpus/ZHAOXIN_KaiXian_KX_U5581_1_8GHz.h"
     109
     110# include "cpus/Hygon_C86_7185_32_core.h"
     111
     112#endif  /* VBOX_VMM_TARGET_X86 */
     113
     114
     115/*
     116 * Include the ARM profiles.
     117 *
     118 * Note! We include these when on ARM64 hosts regardless of the VMM target, so
     119 *       we can get more info about the host CPU.
     120 */
     121#if defined(VBOX_VMM_TARGET_ARMV8) || defined(RT_ARCH_ARM64)
     122
     123# include "cpus/ARM_Apple_M1.h"
     124
    141125#endif
    142 /** @} */
    143 
    144 #ifndef CPUM_DB_STANDALONE
    145 
    146 #include "cpus/Intel_Core_i7_6700K.h"
    147 #include "cpus/Intel_Core_i7_5600U.h"
    148 #include "cpus/Intel_Core_i7_3960X.h"
    149 #include "cpus/Intel_Core_i5_3570.h"
    150 #include "cpus/Intel_Core_i7_2635QM.h"
    151 #include "cpus/Intel_Xeon_X5482_3_20GHz.h"
    152 #include "cpus/Intel_Core2_X6800_2_93GHz.h"
    153 #include "cpus/Intel_Core2_T7600_2_33GHz.h"
    154 #include "cpus/Intel_Core_Duo_T2600_2_16GHz.h"
    155 #include "cpus/Intel_Pentium_M_processor_2_00GHz.h"
    156 #include "cpus/Intel_Pentium_4_3_00GHz.h"
    157 #include "cpus/Intel_Pentium_N3530_2_16GHz.h"
    158 #include "cpus/Intel_Atom_330_1_60GHz.h"
    159 #include "cpus/Intel_80486.h"
    160 #include "cpus/Intel_80386.h"
    161 #include "cpus/Intel_80286.h"
    162 #include "cpus/Intel_80186.h"
    163 #include "cpus/Intel_8086.h"
    164 
    165 #include "cpus/AMD_Ryzen_7_1800X_Eight_Core.h"
    166 #include "cpus/AMD_FX_8150_Eight_Core.h"
    167 #include "cpus/AMD_Phenom_II_X6_1100T.h"
    168 #include "cpus/Quad_Core_AMD_Opteron_2384.h"
    169 #include "cpus/AMD_Athlon_64_X2_Dual_Core_4200.h"
    170 #include "cpus/AMD_Athlon_64_3200.h"
    171 
    172 #include "cpus/VIA_QuadCore_L4700_1_2_GHz.h"
    173 
    174 #include "cpus/ZHAOXIN_KaiXian_KX_U5581_1_8GHz.h"
    175 
    176 #include "cpus/Hygon_C86_7185_32_core.h"
    177126
    178127
     
    191140static CPUMDBENTRY const * const g_apCpumDbEntries[] =
    192141{
    193 #ifdef VBOX_CPUDB_Intel_Core_i7_6700K_h
    194     &g_Entry_Intel_Core_i7_6700K,
    195 #endif
    196 #ifdef VBOX_CPUDB_Intel_Core_i7_5600U_h
    197     &g_Entry_Intel_Core_i7_5600U,
    198 #endif
    199 #ifdef VBOX_CPUDB_Intel_Core_i5_3570_h
    200     &g_Entry_Intel_Core_i5_3570,
    201 #endif
    202 #ifdef VBOX_CPUDB_Intel_Core_i7_3960X_h
    203     &g_Entry_Intel_Core_i7_3960X,
    204 #endif
    205 #ifdef VBOX_CPUDB_Intel_Core_i7_2635QM_h
    206     &g_Entry_Intel_Core_i7_2635QM,
    207 #endif
    208 #ifdef VBOX_CPUDB_Intel_Pentium_N3530_2_16GHz_h
    209     &g_Entry_Intel_Pentium_N3530_2_16GHz,
    210 #endif
    211 #ifdef VBOX_CPUDB_Intel_Atom_330_1_60GHz_h
    212     &g_Entry_Intel_Atom_330_1_60GHz,
    213 #endif
    214 #ifdef VBOX_CPUDB_Intel_Pentium_M_processor_2_00GHz_h
    215     &g_Entry_Intel_Pentium_M_processor_2_00GHz,
    216 #endif
    217 #ifdef VBOX_CPUDB_Intel_Xeon_X5482_3_20GHz_h
    218     &g_Entry_Intel_Xeon_X5482_3_20GHz,
    219 #endif
    220 #ifdef VBOX_CPUDB_Intel_Core2_X6800_2_93GHz_h
    221     &g_Entry_Intel_Core2_X6800_2_93GHz,
    222 #endif
    223 #ifdef VBOX_CPUDB_Intel_Core2_T7600_2_33GHz_h
    224     &g_Entry_Intel_Core2_T7600_2_33GHz,
    225 #endif
    226 #ifdef VBOX_CPUDB_Intel_Core_Duo_T2600_2_16GHz_h
    227     &g_Entry_Intel_Core_Duo_T2600_2_16GHz,
    228 #endif
    229 #ifdef VBOX_CPUDB_Intel_Pentium_4_3_00GHz_h
    230     &g_Entry_Intel_Pentium_4_3_00GHz,
    231 #endif
     142#if defined(VBOX_VMM_TARGET_X86)
     143    /*
     144     * X86 profiles:
     145     */
     146# ifdef VBOX_CPUDB_Intel_Core_i7_6700K_h
     147    &g_Entry_Intel_Core_i7_6700K.Core,
     148# endif
     149# ifdef VBOX_CPUDB_Intel_Core_i7_5600U_h
     150    &g_Entry_Intel_Core_i7_5600U.Core,
     151# endif
     152# ifdef VBOX_CPUDB_Intel_Core_i5_3570_h
     153    &g_Entry_Intel_Core_i5_3570.Core,
     154# endif
     155# ifdef VBOX_CPUDB_Intel_Core_i7_3960X_h
     156    &g_Entry_Intel_Core_i7_3960X.Core,
     157# endif
     158# ifdef VBOX_CPUDB_Intel_Core_i7_2635QM_h
     159    &g_Entry_Intel_Core_i7_2635QM.Core,
     160# endif
     161# ifdef VBOX_CPUDB_Intel_Pentium_N3530_2_16GHz_h
     162    &g_Entry_Intel_Pentium_N3530_2_16GHz.Core,
     163# endif
     164# ifdef VBOX_CPUDB_Intel_Atom_330_1_60GHz_h
     165    &g_Entry_Intel_Atom_330_1_60GHz.Core,
     166# endif
     167# ifdef VBOX_CPUDB_Intel_Pentium_M_processor_2_00GHz_h
     168    &g_Entry_Intel_Pentium_M_processor_2_00GHz.Core,
     169# endif
     170# ifdef VBOX_CPUDB_Intel_Xeon_X5482_3_20GHz_h
     171    &g_Entry_Intel_Xeon_X5482_3_20GHz.Core,
     172# endif
     173# ifdef VBOX_CPUDB_Intel_Core2_X6800_2_93GHz_h
     174    &g_Entry_Intel_Core2_X6800_2_93GHz.Core,
     175# endif
     176# ifdef VBOX_CPUDB_Intel_Core2_T7600_2_33GHz_h
     177    &g_Entry_Intel_Core2_T7600_2_33GHz.Core,
     178# endif
     179# ifdef VBOX_CPUDB_Intel_Core_Duo_T2600_2_16GHz_h
     180    &g_Entry_Intel_Core_Duo_T2600_2_16GHz.Core,
     181# endif
     182# ifdef VBOX_CPUDB_Intel_Pentium_4_3_00GHz_h
     183    &g_Entry_Intel_Pentium_4_3_00GHz.Core,
     184# endif
    232185/** @todo pentium, pentium mmx, pentium pro, pentium II, pentium III */
    233 #ifdef VBOX_CPUDB_Intel_80486_h
    234     &g_Entry_Intel_80486,
    235 #endif
    236 #ifdef VBOX_CPUDB_Intel_80386_h
    237     &g_Entry_Intel_80386,
    238 #endif
    239 #ifdef VBOX_CPUDB_Intel_80286_h
    240     &g_Entry_Intel_80286,
    241 #endif
    242 #ifdef VBOX_CPUDB_Intel_80186_h
    243     &g_Entry_Intel_80186,
    244 #endif
    245 #ifdef VBOX_CPUDB_Intel_8086_h
    246     &g_Entry_Intel_8086,
    247 #endif
    248 
    249 #ifdef VBOX_CPUDB_AMD_Ryzen_7_1800X_Eight_Core_h
    250     &g_Entry_AMD_Ryzen_7_1800X_Eight_Core,
    251 #endif
    252 #ifdef VBOX_CPUDB_AMD_FX_8150_Eight_Core_h
    253     &g_Entry_AMD_FX_8150_Eight_Core,
    254 #endif
    255 #ifdef VBOX_CPUDB_AMD_Phenom_II_X6_1100T_h
    256     &g_Entry_AMD_Phenom_II_X6_1100T,
    257 #endif
    258 #ifdef VBOX_CPUDB_Quad_Core_AMD_Opteron_2384_h
    259     &g_Entry_Quad_Core_AMD_Opteron_2384,
    260 #endif
    261 #ifdef VBOX_CPUDB_AMD_Athlon_64_X2_Dual_Core_4200_h
    262     &g_Entry_AMD_Athlon_64_X2_Dual_Core_4200,
    263 #endif
    264 #ifdef VBOX_CPUDB_AMD_Athlon_64_3200_h
    265     &g_Entry_AMD_Athlon_64_3200,
    266 #endif
    267 
    268 #ifdef VBOX_CPUDB_ZHAOXIN_KaiXian_KX_U5581_1_8GHz_h
    269     &g_Entry_ZHAOXIN_KaiXian_KX_U5581_1_8GHz,
    270 #endif
    271 
    272 #ifdef VBOX_CPUDB_VIA_QuadCore_L4700_1_2_GHz_h
    273     &g_Entry_VIA_QuadCore_L4700_1_2_GHz,
    274 #endif
    275 
    276 #ifdef VBOX_CPUDB_NEC_V20_h
    277     &g_Entry_NEC_V20,
    278 #endif
    279 
    280 #ifdef VBOX_CPUDB_Hygon_C86_7185_32_core_h
    281     &g_Entry_Hygon_C86_7185_32_core,
    282 #endif
     186# ifdef VBOX_CPUDB_Intel_80486_h
     187    &g_Entry_Intel_80486.Core,
     188# endif
     189# ifdef VBOX_CPUDB_Intel_80386_h
     190    &g_Entry_Intel_80386.Core,
     191# endif
     192# ifdef VBOX_CPUDB_Intel_80286_h
     193    &g_Entry_Intel_80286.Core,
     194# endif
     195# ifdef VBOX_CPUDB_Intel_80186_h
     196    &g_Entry_Intel_80186.Core,
     197# endif
     198# ifdef VBOX_CPUDB_Intel_8086_h
     199    &g_Entry_Intel_8086.Core,
     200# endif
     201
     202# ifdef VBOX_CPUDB_AMD_Ryzen_7_1800X_Eight_Core_h
     203    &g_Entry_AMD_Ryzen_7_1800X_Eight_Core.Core,
     204# endif
     205# ifdef VBOX_CPUDB_AMD_FX_8150_Eight_Core_h
     206    &g_Entry_AMD_FX_8150_Eight_Core.Core,
     207# endif
     208# ifdef VBOX_CPUDB_AMD_Phenom_II_X6_1100T_h
     209    &g_Entry_AMD_Phenom_II_X6_1100T.Core,
     210# endif
     211# ifdef VBOX_CPUDB_Quad_Core_AMD_Opteron_2384_h
     212    &g_Entry_Quad_Core_AMD_Opteron_2384.Core,
     213# endif
     214# ifdef VBOX_CPUDB_AMD_Athlon_64_X2_Dual_Core_4200_h
     215    &g_Entry_AMD_Athlon_64_X2_Dual_Core_4200.Core,
     216# endif
     217# ifdef VBOX_CPUDB_AMD_Athlon_64_3200_h
     218    &g_Entry_AMD_Athlon_64_3200.Core,
     219# endif
     220
     221# ifdef VBOX_CPUDB_ZHAOXIN_KaiXian_KX_U5581_1_8GHz_h
     222    &g_Entry_ZHAOXIN_KaiXian_KX_U5581_1_8GHz.Core,
     223# endif
     224
     225# ifdef VBOX_CPUDB_VIA_QuadCore_L4700_1_2_GHz_h
     226    &g_Entry_VIA_QuadCore_L4700_1_2_GHz.Core,
     227# endif
     228
     229# ifdef VBOX_CPUDB_NEC_V20_h
     230    &g_Entry_NEC_V20.Core,
     231# endif
     232
     233# ifdef VBOX_CPUDB_Hygon_C86_7185_32_core_h
     234    &g_Entry_Hygon_C86_7185_32_core.Core,
     235# endif
     236#endif /* VBOX_VMM_TARGET_X86 */
     237
     238#if defined(VBOX_VMM_TARGET_ARMV8) || defined(RT_ARCH_ARM64)
     239    /*
     240     * ARM profiles:
     241     */
     242    &g_Entry_ARM_Apple_M1.Core,
     243#endif /* VBOX_VMM_TARGET_ARMV8 || RT_ARCH_ARM64 */
    283244};
    284245
     
    327288}
    328289
    329 
    330 
    331 /**
    332  * Binary search used by cpumR3MsrRangesInsert and has some special properties
    333  * wrt to mismatches.
    334  *
    335  * @returns Insert location.
    336  * @param   paMsrRanges         The MSR ranges to search.
    337  * @param   cMsrRanges          The number of MSR ranges.
    338  * @param   uMsr                What to search for.
    339  */
    340 static uint32_t cpumR3MsrRangesBinSearch(PCCPUMMSRRANGE paMsrRanges, uint32_t cMsrRanges, uint32_t uMsr)
    341 {
    342     if (!cMsrRanges)
    343         return 0;
    344 
    345     uint32_t iStart = 0;
    346     uint32_t iLast  = cMsrRanges - 1;
    347     for (;;)
    348     {
    349         uint32_t i = iStart + (iLast - iStart + 1) / 2;
    350         if (   uMsr >= paMsrRanges[i].uFirst
    351             && uMsr <= paMsrRanges[i].uLast)
    352             return i;
    353         if (uMsr < paMsrRanges[i].uFirst)
    354         {
    355             if (i <= iStart)
    356                 return i;
    357             iLast = i - 1;
    358         }
    359         else
    360         {
    361             if (i >= iLast)
    362             {
    363                 if (i < cMsrRanges)
    364                     i++;
    365                 return i;
    366             }
    367             iStart = i + 1;
    368         }
    369     }
    370 }
    371 
    372 
    373 /**
    374  * Ensures that there is space for at least @a cNewRanges in the table,
    375  * reallocating the table if necessary.
    376  *
    377  * @returns Pointer to the MSR ranges on success, NULL on failure.  On failure
    378  *          @a *ppaMsrRanges is freed and set to NULL.
    379  * @param   pVM             The cross context VM structure.  If NULL,
    380  *                          use the process heap, otherwise the VM's hyper heap.
    381  * @param   ppaMsrRanges    The variable pointing to the ranges (input/output).
    382  * @param   cMsrRanges      The current number of ranges.
    383  * @param   cNewRanges      The number of ranges to be added.
    384  */
    385 static PCPUMMSRRANGE cpumR3MsrRangesEnsureSpace(PVM pVM, PCPUMMSRRANGE *ppaMsrRanges, uint32_t cMsrRanges, uint32_t cNewRanges)
    386 {
    387     if (  cMsrRanges + cNewRanges
    388         > RT_ELEMENTS(pVM->cpum.s.GuestInfo.aMsrRanges) + (pVM ? 0 : 128 /* Catch too many MSRs in CPU reporter! */))
    389     {
    390         LogRel(("CPUM: Too many MSR ranges! %#x, max %#x\n",
    391                 cMsrRanges + cNewRanges, RT_ELEMENTS(pVM->cpum.s.GuestInfo.aMsrRanges)));
    392         return NULL;
    393     }
    394     if (pVM)
    395     {
    396         Assert(cMsrRanges == pVM->cpum.s.GuestInfo.cMsrRanges);
    397         Assert(*ppaMsrRanges == pVM->cpum.s.GuestInfo.aMsrRanges);
    398     }
    399     else
    400     {
    401         if (cMsrRanges + cNewRanges > RT_ALIGN_32(cMsrRanges, 16))
    402         {
    403 
    404             uint32_t const cNew = RT_ALIGN_32(cMsrRanges + cNewRanges, 16);
    405             void *pvNew = RTMemRealloc(*ppaMsrRanges, cNew * sizeof(**ppaMsrRanges));
    406             if (pvNew)
    407                 *ppaMsrRanges = (PCPUMMSRRANGE)pvNew;
    408             else
    409             {
    410                 RTMemFree(*ppaMsrRanges);
    411                 *ppaMsrRanges = NULL;
    412                 return NULL;
    413             }
    414         }
    415     }
    416 
    417     return *ppaMsrRanges;
    418 }
    419 
    420 
    421 /**
    422  * Inserts a new MSR range in into an sorted MSR range array.
    423  *
    424  * If the new MSR range overlaps existing ranges, the existing ones will be
    425  * adjusted/removed to fit in the new one.
    426  *
    427  * @returns VBox status code.
    428  * @retval  VINF_SUCCESS
    429  * @retval  VERR_NO_MEMORY
    430  *
    431  * @param   pVM             The cross context VM structure.  If NULL,
    432  *                          use the process heap, otherwise the VM's hyper heap.
    433  * @param   ppaMsrRanges    The variable pointing to the ranges (input/output).
    434  *                          Must be NULL if using the hyper heap.
    435  * @param   pcMsrRanges     The variable holding number of ranges. Must be NULL
    436  *                          if using the hyper heap.
    437  * @param   pNewRange       The new range.
    438  */
    439 int cpumR3MsrRangesInsert(PVM pVM, PCPUMMSRRANGE *ppaMsrRanges, uint32_t *pcMsrRanges, PCCPUMMSRRANGE pNewRange)
    440 {
    441     Assert(pNewRange->uLast >= pNewRange->uFirst);
    442     Assert(pNewRange->enmRdFn > kCpumMsrRdFn_Invalid && pNewRange->enmRdFn < kCpumMsrRdFn_End);
    443     Assert(pNewRange->enmWrFn > kCpumMsrWrFn_Invalid && pNewRange->enmWrFn < kCpumMsrWrFn_End);
    444 
    445     /*
    446      * Validate and use the VM's MSR ranges array if we are using the hyper heap.
    447      */
    448     if (pVM)
    449     {
    450         AssertReturn(!ppaMsrRanges, VERR_INVALID_PARAMETER);
    451         AssertReturn(!pcMsrRanges,  VERR_INVALID_PARAMETER);
    452         AssertReturn(pVM->cpum.s.GuestInfo.paMsrRangesR3 == pVM->cpum.s.GuestInfo.aMsrRanges, VERR_INTERNAL_ERROR_3);
    453 
    454         ppaMsrRanges = &pVM->cpum.s.GuestInfo.paMsrRangesR3;
    455         pcMsrRanges  = &pVM->cpum.s.GuestInfo.cMsrRanges;
    456     }
    457     else
    458     {
    459         AssertReturn(ppaMsrRanges, VERR_INVALID_POINTER);
    460         AssertReturn(pcMsrRanges, VERR_INVALID_POINTER);
    461     }
    462 
    463     uint32_t        cMsrRanges  = *pcMsrRanges;
    464     PCPUMMSRRANGE   paMsrRanges = *ppaMsrRanges;
    465 
    466     /*
    467      * Optimize the linear insertion case where we add new entries at the end.
    468      */
    469     if (   cMsrRanges > 0
    470         && paMsrRanges[cMsrRanges - 1].uLast < pNewRange->uFirst)
    471     {
    472         paMsrRanges = cpumR3MsrRangesEnsureSpace(pVM, ppaMsrRanges, cMsrRanges, 1);
    473         if (!paMsrRanges)
    474             return VERR_NO_MEMORY;
    475         paMsrRanges[cMsrRanges] = *pNewRange;
    476         *pcMsrRanges += 1;
    477     }
    478     else
    479     {
    480         uint32_t i = cpumR3MsrRangesBinSearch(paMsrRanges, cMsrRanges, pNewRange->uFirst);
    481         Assert(i == cMsrRanges || pNewRange->uFirst <= paMsrRanges[i].uLast);
    482         Assert(i == 0 || pNewRange->uFirst > paMsrRanges[i - 1].uLast);
    483 
    484         /*
    485          * Adding an entirely new entry?
    486          */
    487         if (   i >= cMsrRanges
    488             || pNewRange->uLast < paMsrRanges[i].uFirst)
    489         {
    490             paMsrRanges = cpumR3MsrRangesEnsureSpace(pVM, ppaMsrRanges, cMsrRanges, 1);
    491             if (!paMsrRanges)
    492                 return VERR_NO_MEMORY;
    493             if (i < cMsrRanges)
    494                 memmove(&paMsrRanges[i + 1], &paMsrRanges[i], (cMsrRanges - i) * sizeof(paMsrRanges[0]));
    495             paMsrRanges[i] = *pNewRange;
    496             *pcMsrRanges += 1;
    497         }
    498         /*
    499          * Replace existing entry?
    500          */
    501         else if (   pNewRange->uFirst == paMsrRanges[i].uFirst
    502                  && pNewRange->uLast  == paMsrRanges[i].uLast)
    503             paMsrRanges[i] = *pNewRange;
    504         /*
    505          * Splitting an existing entry?
    506          */
    507         else if (   pNewRange->uFirst > paMsrRanges[i].uFirst
    508                  && pNewRange->uLast  < paMsrRanges[i].uLast)
    509         {
    510             paMsrRanges = cpumR3MsrRangesEnsureSpace(pVM, ppaMsrRanges, cMsrRanges, 2);
    511             if (!paMsrRanges)
    512                 return VERR_NO_MEMORY;
    513             Assert(i < cMsrRanges);
    514             memmove(&paMsrRanges[i + 2], &paMsrRanges[i], (cMsrRanges - i) * sizeof(paMsrRanges[0]));
    515             paMsrRanges[i + 1] = *pNewRange;
    516             paMsrRanges[i + 2] = paMsrRanges[i];
    517             paMsrRanges[i    ].uLast  = pNewRange->uFirst - 1;
    518             paMsrRanges[i + 2].uFirst = pNewRange->uLast  + 1;
    519             *pcMsrRanges += 2;
    520         }
    521         /*
    522          * Complicated scenarios that can affect more than one range.
    523          *
    524          * The current code does not optimize memmove calls when replacing
    525          * one or more existing ranges, because it's tedious to deal with and
    526          * not expected to be a frequent usage scenario.
    527          */
    528         else
    529         {
    530             /* Adjust start of first match? */
    531             if (   pNewRange->uFirst <= paMsrRanges[i].uFirst
    532                 && pNewRange->uLast  <  paMsrRanges[i].uLast)
    533                 paMsrRanges[i].uFirst = pNewRange->uLast + 1;
    534             else
    535             {
    536                 /* Adjust end of first match? */
    537                 if (pNewRange->uFirst > paMsrRanges[i].uFirst)
    538                 {
    539                     Assert(paMsrRanges[i].uLast >= pNewRange->uFirst);
    540                     paMsrRanges[i].uLast = pNewRange->uFirst - 1;
    541                     i++;
    542                 }
    543                 /* Replace the whole first match (lazy bird). */
    544                 else
    545                 {
    546                     if (i + 1 < cMsrRanges)
    547                         memmove(&paMsrRanges[i], &paMsrRanges[i + 1], (cMsrRanges - i - 1) * sizeof(paMsrRanges[0]));
    548                     cMsrRanges = *pcMsrRanges -= 1;
    549                 }
    550 
    551                 /* Do the new range affect more ranges? */
    552                 while (   i < cMsrRanges
    553                        && pNewRange->uLast >= paMsrRanges[i].uFirst)
    554                 {
    555                     if (pNewRange->uLast < paMsrRanges[i].uLast)
    556                     {
    557                         /* Adjust the start of it, then we're done. */
    558                         paMsrRanges[i].uFirst = pNewRange->uLast + 1;
    559                         break;
    560                     }
    561 
    562                     /* Remove it entirely. */
    563                     if (i + 1 < cMsrRanges)
    564                         memmove(&paMsrRanges[i], &paMsrRanges[i + 1], (cMsrRanges - i - 1) * sizeof(paMsrRanges[0]));
    565                     cMsrRanges = *pcMsrRanges -= 1;
    566                 }
    567             }
    568 
    569             /* Now, perform a normal insertion. */
    570             paMsrRanges = cpumR3MsrRangesEnsureSpace(pVM, ppaMsrRanges, cMsrRanges, 1);
    571             if (!paMsrRanges)
    572                 return VERR_NO_MEMORY;
    573             if (i < cMsrRanges)
    574                 memmove(&paMsrRanges[i + 1], &paMsrRanges[i], (cMsrRanges - i) * sizeof(paMsrRanges[0]));
    575             paMsrRanges[i] = *pNewRange;
    576             *pcMsrRanges += 1;
    577         }
    578     }
    579 
    580     return VINF_SUCCESS;
    581 }
    582 
    583 
    584 /**
    585  * Reconciles CPUID info with MSRs (selected ones).
    586  *
    587  * @returns VBox status code.
    588  * @param   pVM                 The cross context VM structure.
    589  * @param   fForceFlushCmd      Make sure MSR_IA32_FLUSH_CMD is present.
    590  * @param   fForceSpecCtrl      Make sure MSR_IA32_SPEC_CTRL is present.
    591  */
    592 DECLHIDDEN(int) cpumR3MsrReconcileWithCpuId(PVM pVM, bool fForceFlushCmd, bool fForceSpecCtrl)
    593 {
    594     PCCPUMMSRRANGE apToAdd[10];
    595     uint32_t       cToAdd = 0;
    596 
    597     /*
    598      * The IA32_FLUSH_CMD MSR was introduced in MCUs for CVS-2018-3646 and associates.
    599      */
    600     if (   pVM->cpum.s.GuestFeatures.fFlushCmd
    601         || fForceFlushCmd)
    602     {
    603         static CPUMMSRRANGE const s_FlushCmd =
    604         {
    605             /*.uFirst =*/       MSR_IA32_FLUSH_CMD,
    606             /*.uLast =*/        MSR_IA32_FLUSH_CMD,
    607             /*.enmRdFn =*/      kCpumMsrRdFn_WriteOnly,
    608             /*.enmWrFn =*/      kCpumMsrWrFn_Ia32FlushCmd,
    609             /*.offCpumCpu =*/   UINT16_MAX,
    610             /*.fReserved =*/    0,
    611             /*.uValue =*/       0,
    612             /*.fWrIgnMask =*/   0,
    613             /*.fWrGpMask =*/    ~MSR_IA32_FLUSH_CMD_F_L1D,
    614             /*.szName = */      "IA32_FLUSH_CMD"
    615         };
    616         apToAdd[cToAdd++] = &s_FlushCmd;
    617     }
    618 
    619     /*
    620      * The IA32_PRED_CMD MSR was introduced in MCUs for CVS-2018-3646 and associates.
    621      */
    622     if (   pVM->cpum.s.GuestFeatures.fIbpb
    623         /** @todo || pVM->cpum.s.GuestFeatures.fSbpb*/)
    624     {
    625         static CPUMMSRRANGE const s_PredCmd =
    626         {
    627             /*.uFirst =*/       MSR_IA32_PRED_CMD,
    628             /*.uLast =*/        MSR_IA32_PRED_CMD,
    629             /*.enmRdFn =*/      kCpumMsrRdFn_WriteOnly,
    630             /*.enmWrFn =*/      kCpumMsrWrFn_Ia32PredCmd,
    631             /*.offCpumCpu =*/   UINT16_MAX,
    632             /*.fReserved =*/    0,
    633             /*.uValue =*/       0,
    634             /*.fWrIgnMask =*/   0,
    635             /*.fWrGpMask =*/    ~MSR_IA32_PRED_CMD_F_IBPB,
    636             /*.szName = */      "IA32_PRED_CMD"
    637         };
    638         apToAdd[cToAdd++] = &s_PredCmd;
    639     }
    640 
    641     /*
    642      * The IA32_SPEC_CTRL MSR was introduced in MCUs for CVS-2018-3646 and associates.
    643      */
    644     if (   pVM->cpum.s.GuestFeatures.fSpecCtrlMsr
    645         || fForceSpecCtrl)
    646     {
    647         static CPUMMSRRANGE const s_SpecCtrl =
    648         {
    649             /*.uFirst =*/       MSR_IA32_SPEC_CTRL,
    650             /*.uLast =*/        MSR_IA32_SPEC_CTRL,
    651             /*.enmRdFn =*/      kCpumMsrRdFn_Ia32SpecCtrl,
    652             /*.enmWrFn =*/      kCpumMsrWrFn_Ia32SpecCtrl,
    653             /*.offCpumCpu =*/   UINT16_MAX,
    654             /*.fReserved =*/    0,
    655             /*.uValue =*/       0,
    656             /*.fWrIgnMask =*/   0,
    657             /*.fWrGpMask =*/    0,
    658             /*.szName = */      "IA32_SPEC_CTRL"
    659         };
    660         apToAdd[cToAdd++] = &s_SpecCtrl;
    661     }
    662 
    663     /*
    664      * The MSR_IA32_ARCH_CAPABILITIES was introduced in various spectre MCUs, or at least
    665      * documented in relation to such.
    666      */
    667     if (pVM->cpum.s.GuestFeatures.fArchCap)
    668     {
    669         static CPUMMSRRANGE const s_ArchCaps =
    670         {
    671             /*.uFirst =*/       MSR_IA32_ARCH_CAPABILITIES,
    672             /*.uLast =*/        MSR_IA32_ARCH_CAPABILITIES,
    673             /*.enmRdFn =*/      kCpumMsrRdFn_Ia32ArchCapabilities,
    674             /*.enmWrFn =*/      kCpumMsrWrFn_ReadOnly,
    675             /*.offCpumCpu =*/   UINT16_MAX,
    676             /*.fReserved =*/    0,
    677             /*.uValue =*/       0,
    678             /*.fWrIgnMask =*/   0,
    679             /*.fWrGpMask =*/    UINT64_MAX,
    680             /*.szName = */      "IA32_ARCH_CAPABILITIES"
    681         };
    682         apToAdd[cToAdd++] = &s_ArchCaps;
    683     }
    684 
    685     /*
    686      * Do the adding.
    687      */
    688     Assert(cToAdd <= RT_ELEMENTS(apToAdd));
    689     for (uint32_t i = 0; i < cToAdd; i++)
    690     {
    691         PCCPUMMSRRANGE pRange = apToAdd[i];
    692         Assert(pRange->uFirst == pRange->uLast);
    693         if (!cpumLookupMsrRange(pVM, pRange->uFirst))
    694         {
    695             LogRel(("CPUM: MSR/CPUID reconciliation insert: %#010x %s\n", pRange->uFirst, pRange->szName));
    696             int rc = cpumR3MsrRangesInsert(NULL /* pVM */, &pVM->cpum.s.GuestInfo.paMsrRangesR3,
    697                                            &pVM->cpum.s.GuestInfo.cMsrRanges, pRange);
    698             AssertRCReturn(rc, rc);
    699         }
    700     }
    701     return VINF_SUCCESS;
    702 }
    703 
    704 
    705 /**
    706  * Worker for cpumR3MsrApplyFudge that applies one table.
    707  *
    708  * @returns VBox status code.
    709  * @param   pVM                 The cross context VM structure.
    710  * @param   paRanges            Array of MSRs to fudge.
    711  * @param   cRanges             Number of MSRs in the array.
    712  */
    713 static int cpumR3MsrApplyFudgeTable(PVM pVM, PCCPUMMSRRANGE paRanges, size_t cRanges)
    714 {
    715     for (uint32_t i = 0; i < cRanges; i++)
    716         if (!cpumLookupMsrRange(pVM, paRanges[i].uFirst))
    717         {
    718             LogRel(("CPUM: MSR fudge: %#010x %s\n", paRanges[i].uFirst, paRanges[i].szName));
    719             int rc = cpumR3MsrRangesInsert(NULL /* pVM */, &pVM->cpum.s.GuestInfo.paMsrRangesR3, &pVM->cpum.s.GuestInfo.cMsrRanges,
    720                                            &paRanges[i]);
    721             if (RT_FAILURE(rc))
    722                 return rc;
    723         }
    724     return VINF_SUCCESS;
    725 }
    726 
    727 
    728 /**
    729  * Fudges the MSRs that guest are known to access in some odd cases.
    730  *
    731  * A typical example is a VM that has been moved between different hosts where
    732  * for instance the cpu vendor differs.
    733  *
    734  * Another example is older CPU profiles (e.g. Atom Bonnet) for newer CPUs (e.g.
    735  * Atom Silvermont), where features reported thru CPUID aren't present in the
    736  * MSRs (e.g. AMD64_TSC_AUX).
    737  *
    738  *
    739  * @returns VBox status code.
    740  * @param   pVM                 The cross context VM structure.
    741  */
    742 int cpumR3MsrApplyFudge(PVM pVM)
    743 {
    744     /*
    745      * Basic.
    746      */
    747     static CPUMMSRRANGE const s_aFudgeMsrs[] =
    748     {
    749         MFO(0x00000000, "IA32_P5_MC_ADDR",          Ia32P5McAddr),
    750         MFX(0x00000001, "IA32_P5_MC_TYPE",          Ia32P5McType,   Ia32P5McType,   0, 0, UINT64_MAX),
    751         MVO(0x00000017, "IA32_PLATFORM_ID",         0),
    752         MFN(0x0000001b, "IA32_APIC_BASE",           Ia32ApicBase,   Ia32ApicBase),
    753         MVI(0x0000008b, "BIOS_SIGN",                0),
    754         MFX(0x000000fe, "IA32_MTRRCAP",             Ia32MtrrCap,    ReadOnly,       0x508, 0, 0),
    755         MFX(0x00000179, "IA32_MCG_CAP",             Ia32McgCap,     ReadOnly,       0x005, 0, 0),
    756         MFX(0x0000017a, "IA32_MCG_STATUS",          Ia32McgStatus,  Ia32McgStatus,  0, ~(uint64_t)UINT32_MAX, 0),
    757         MFN(0x000001a0, "IA32_MISC_ENABLE",         Ia32MiscEnable, Ia32MiscEnable),
    758         MFN(0x000001d9, "IA32_DEBUGCTL",            Ia32DebugCtl,   Ia32DebugCtl),
    759         MFO(0x000001db, "P6_LAST_BRANCH_FROM_IP",   P6LastBranchFromIp),
    760         MFO(0x000001dc, "P6_LAST_BRANCH_TO_IP",     P6LastBranchToIp),
    761         MFO(0x000001dd, "P6_LAST_INT_FROM_IP",      P6LastIntFromIp),
    762         MFO(0x000001de, "P6_LAST_INT_TO_IP",        P6LastIntToIp),
    763         MFS(0x00000277, "IA32_PAT",                 Ia32Pat, Ia32Pat, Guest.msrPAT),
    764         MFZ(0x000002ff, "IA32_MTRR_DEF_TYPE",       Ia32MtrrDefType, Ia32MtrrDefType, GuestMsrs.msr.MtrrDefType, 0, ~(uint64_t)0xc07),
    765         MFN(0x00000400, "IA32_MCi_CTL_STATUS_ADDR_MISC", Ia32McCtlStatusAddrMiscN, Ia32McCtlStatusAddrMiscN),
    766     };
    767     int rc = cpumR3MsrApplyFudgeTable(pVM, &s_aFudgeMsrs[0], RT_ELEMENTS(s_aFudgeMsrs));
    768     AssertLogRelRCReturn(rc, rc);
    769 
    770     /*
    771      * XP might mistake opterons and other newer CPUs for P4s.
    772      */
    773     if (pVM->cpum.s.GuestFeatures.uFamily >= 0xf)
    774     {
    775         static CPUMMSRRANGE const s_aP4FudgeMsrs[] =
    776         {
    777             MFX(0x0000002c, "P4_EBC_FREQUENCY_ID", IntelP4EbcFrequencyId, IntelP4EbcFrequencyId, 0xf12010f, UINT64_MAX, 0),
    778         };
    779         rc = cpumR3MsrApplyFudgeTable(pVM, &s_aP4FudgeMsrs[0], RT_ELEMENTS(s_aP4FudgeMsrs));
    780         AssertLogRelRCReturn(rc, rc);
    781     }
    782 
    783     if (pVM->cpum.s.GuestFeatures.fRdTscP)
    784     {
    785         static CPUMMSRRANGE const s_aRdTscPFudgeMsrs[] =
    786         {
    787             MFX(0xc0000103, "AMD64_TSC_AUX", Amd64TscAux, Amd64TscAux, 0, 0, ~(uint64_t)UINT32_MAX),
    788         };
    789         rc = cpumR3MsrApplyFudgeTable(pVM, &s_aRdTscPFudgeMsrs[0], RT_ELEMENTS(s_aRdTscPFudgeMsrs));
    790         AssertLogRelRCReturn(rc, rc);
    791     }
    792 
    793     /*
    794      * Windows 10 incorrectly writes to MSR_IA32_TSX_CTRL without checking
    795      * CPUID.ARCH_CAP(EAX=7h,ECX=0):EDX[bit 29] or the MSR feature bits in
    796      * MSR_IA32_ARCH_CAPABILITIES[bit 7], see @bugref{9630}.
    797      * Ignore writes to this MSR and return 0 on reads.
    798      *
    799      * Windows 11 24H2 incorrectly reads MSR_IA32_MCU_OPT_CTRL without
    800      * checking CPUID.ARCH_CAP(EAX=7h,ECX=0).EDX[bit 9] or the MSR feature
    801      * bits in MSR_IA32_ARCH_CAPABILITIES[bit 18], see @bugref{10794}.
    802      * Ignore wrties to this MSR and return 0 on reads.
    803      */
    804     if (pVM->cpum.s.GuestFeatures.fArchCap)
    805     {
    806         static CPUMMSRRANGE const s_aTsxCtrl[] =
    807         {
    808             MVI(MSR_IA32_TSX_CTRL, "IA32_TSX_CTRL", 0),
    809             MVI(MSR_IA32_MCU_OPT_CTRL, "IA32_MCU_OPT_CTRL", 0),
    810         };
    811         rc = cpumR3MsrApplyFudgeTable(pVM, &s_aTsxCtrl[0], RT_ELEMENTS(s_aTsxCtrl));
    812         AssertLogRelRCReturn(rc, rc);
    813     }
    814 
    815     return rc;
    816 }
    817 
    818 #if defined(RT_ARCH_X86) || defined(RT_ARCH_AMD64)
     290#if defined(VBOX_VMM_TARGET_X86) && (defined(RT_ARCH_X86) || defined(RT_ARCH_AMD64))
    819291
    820292/**
     
    934406}
    935407
    936 #endif /* RT_ARCH_X86 || RT_ARCH_AMD64 */
    937 
    938 int cpumR3DbGetCpuInfo(const char *pszName, PCPUMINFO pInfo)
    939 {
    940     CPUMDBENTRY const *pEntry = NULL;
    941     int                rc;
    942 
    943     if (!strcmp(pszName, "host"))
    944 #if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
     408
     409/**
     410 * X86 version of helper that picks a DB entry for the host and merges it with
     411 * available info in the @a pInfo structure.
     412 */
     413static int cpumR3DbCreateHostEntry(PCPUMINFO pInfo)
     414{
     415    /*
     416     * Create a CPU database entry for the host CPU.  This means getting
     417     * the CPUID bits from the real CPU and grabbing the closest matching
     418     * database entry for MSRs.
     419     */
     420    int rc = CPUMR3CpuIdDetectUnknownLeafMethod(&pInfo->enmUnknownCpuIdMethod, &pInfo->DefCpuId);
     421    if (RT_FAILURE(rc))
     422        return rc;
     423    rc = CPUMCpuIdCollectLeavesFromX86Host(&pInfo->paCpuIdLeavesR3, &pInfo->cCpuIdLeaves);
     424    if (RT_FAILURE(rc))
     425        return rc;
     426    pInfo->fMxCsrMask = CPUMR3DeterminHostMxCsrMask();
     427
     428    /* Lookup database entry for MSRs. */
     429    CPUMCPUVENDOR const enmVendor    = CPUMCpuIdDetectX86VendorEx(pInfo->paCpuIdLeavesR3[0].uEax,
     430                                                                  pInfo->paCpuIdLeavesR3[0].uEbx,
     431                                                                  pInfo->paCpuIdLeavesR3[0].uEcx,
     432                                                                  pInfo->paCpuIdLeavesR3[0].uEdx);
     433    uint32_t      const uStd1Eax     = pInfo->paCpuIdLeavesR3[1].uEax;
     434    uint8_t       const uFamily      = RTX86GetCpuFamily(uStd1Eax);
     435    uint8_t       const uModel       = RTX86GetCpuModel(uStd1Eax, enmVendor == CPUMCPUVENDOR_INTEL);
     436    uint8_t       const uStepping    = RTX86GetCpuStepping(uStd1Eax);
     437    CPUMMICROARCH const enmMicroarch = CPUMCpuIdDetermineX86MicroarchEx(enmVendor, uFamily, uModel, uStepping);
     438
     439    PCCPUMDBENTRYX86    pEntry = NULL;
     440    for (unsigned i = 0; i < RT_ELEMENTS(g_apCpumDbEntries); i++)
     441    {
     442        CPUMDBENTRY const * const pCurCore = g_apCpumDbEntries[i];
     443        if (   (CPUMCPUVENDOR)pCurCore->enmVendor == enmVendor
     444            && pCurCore->enmEntryType == CPUMDBENTRYTYPE_X86)
     445        {
     446            CPUMDBENTRYX86 const * const pCur = (CPUMDBENTRYX86 const *)pCurCore;
     447
     448            /* Match against Family, Microarch, model and stepping.  Except
     449               for family, always match the closer with preference given to
     450               the later/older ones. */
     451            if (pCur->uFamily == uFamily)
     452            {
     453                if (pCur->Core.enmMicroarch == enmMicroarch)
     454                {
     455                    if (pCur->uModel == uModel)
     456                    {
     457                        if (pCur->uStepping == uStepping)
     458                        {
     459                            /* Perfect match. */
     460                            pEntry = pCur;
     461                            break;
     462                        }
     463
     464                        if (   !pEntry
     465                            || pEntry->uModel            != uModel
     466                            || pEntry->Core.enmMicroarch != enmMicroarch
     467                            || pEntry->uFamily           != uFamily)
     468                            pEntry = pCur;
     469                        else if (  pCur->uStepping >= uStepping
     470                                 ? pCur->uStepping < pEntry->uStepping || pEntry->uStepping < uStepping
     471                                 : pCur->uStepping > pEntry->uStepping)
     472                                 pEntry = pCur;
     473                    }
     474                    else if (   !pEntry
     475                             || pEntry->Core.enmMicroarch != enmMicroarch
     476                             || pEntry->uFamily           != uFamily)
     477                        pEntry = pCur;
     478                    else if (  pCur->uModel >= uModel
     479                             ? pCur->uModel < pEntry->uModel || pEntry->uModel < uModel
     480                             : pCur->uModel > pEntry->uModel)
     481                        pEntry = pCur;
     482                }
     483                else if (   !pEntry
     484                         || pEntry->uFamily != uFamily)
     485                    pEntry = pCur;
     486                /* Special march matching rules applies to intel family 06h. */
     487                else if (     enmVendor == CPUMCPUVENDOR_INTEL
     488                           && uFamily   == 6
     489                         ? cpumR3DbIsBetterIntelFam06Match(pCur->Core.enmMicroarch, enmMicroarch, pEntry->Core.enmMicroarch)
     490                         : cpumR3DbIsBetterMarchMatch(pCur->Core.enmMicroarch, enmMicroarch, pEntry->Core.enmMicroarch))
     491                    pEntry = pCur;
     492            }
     493            /* We don't do closeness matching on family, we use the first
     494               entry for the CPU vendor instead. (P4 workaround.) */
     495            else if (!pEntry)
     496                pEntry = pCur;
     497        }
     498    }
     499
     500    if (pEntry)
     501        LogRel(("CPUM: Matched host CPU %s %#x/%#x/%#x %s with CPU DB entry '%s' (%s %#x/%#x/%#x %s)\n",
     502                CPUMCpuVendorName(enmVendor), uFamily, uModel, uStepping, CPUMMicroarchName(enmMicroarch),
     503                pEntry->Core.pszName,  CPUMCpuVendorName(pEntry->Core.enmVendor), pEntry->uFamily, pEntry->uModel,
     504                pEntry->uStepping, CPUMMicroarchName(pEntry->Core.enmMicroarch) ));
     505    else
     506    {
     507        pEntry = (CPUMDBENTRYX86 const *)g_apCpumDbEntries[0];
     508        LogRel(("CPUM: No matching processor database entry %s %#x/%#x/%#x %s, falling back on '%s'\n",
     509                CPUMCpuVendorName(enmVendor), uFamily, uModel, uStepping, CPUMMicroarchName(enmMicroarch),
     510                pEntry->Core.pszName));
     511    }
     512
     513    return cpumDbPopulateInfoFromEntry(pInfo, &pEntry->Core, true /*fHost*/);
     514}
     515
     516#endif /* VBOX_VMM_TARGET_X86 && (RT_ARCH_AMD64 || RT_ARCH_X86) */
     517
     518
     519/**
     520 * Helper that populates the CPUMINFO structure from DB entry.
     521 */
     522static int cpumDbPopulateInfoFromEntry(PCPUMINFO pInfo, PCCPUMDBENTRY pEntryCore, bool fHost)
     523{
     524#ifdef VBOX_VMM_TARGET_X86
     525    /*
     526     * X86.
     527     */
     528    AssertReturn(pEntryCore->enmEntryType == CPUMDBENTRYTYPE_X86, VERR_INTERNAL_ERROR_3);
     529    PCCPUMDBENTRYX86 const pEntry = (PCCPUMDBENTRYX86)pEntryCore;
     530
     531    if (!fHost)
    945532    {
    946533        /*
    947          * Create a CPU database entry for the host CPU.  This means getting
    948          * the CPUID bits from the real CPU and grabbing the closest matching
    949          * database entry for MSRs.
     534         * The CPUID tables needs to be copied onto the heap so the caller can
     535         * modify them and so they can be freed like in the host case.
    950536         */
    951         rc = CPUMR3CpuIdDetectUnknownLeafMethod(&pInfo->enmUnknownCpuIdMethod, &pInfo->DefCpuId);
    952         if (RT_FAILURE(rc))
    953             return rc;
    954         rc = CPUMCpuIdCollectLeavesFromX86Host(&pInfo->paCpuIdLeavesR3, &pInfo->cCpuIdLeaves);
    955         if (RT_FAILURE(rc))
    956             return rc;
    957         pInfo->fMxCsrMask = CPUMR3DeterminHostMxCsrMask();
    958 
    959         /* Lookup database entry for MSRs. */
    960         CPUMCPUVENDOR const enmVendor    = CPUMCpuIdDetectX86VendorEx(pInfo->paCpuIdLeavesR3[0].uEax,
    961                                                                       pInfo->paCpuIdLeavesR3[0].uEbx,
    962                                                                       pInfo->paCpuIdLeavesR3[0].uEcx,
    963                                                                       pInfo->paCpuIdLeavesR3[0].uEdx);
    964         uint32_t      const uStd1Eax     = pInfo->paCpuIdLeavesR3[1].uEax;
    965         uint8_t       const uFamily      = RTX86GetCpuFamily(uStd1Eax);
    966         uint8_t       const uModel       = RTX86GetCpuModel(uStd1Eax, enmVendor == CPUMCPUVENDOR_INTEL);
    967         uint8_t       const uStepping    = RTX86GetCpuStepping(uStd1Eax);
    968         CPUMMICROARCH const enmMicroarch = CPUMCpuIdDetermineX86MicroarchEx(enmVendor, uFamily, uModel, uStepping);
    969 
    970         for (unsigned i = 0; i < RT_ELEMENTS(g_apCpumDbEntries); i++)
    971         {
    972             CPUMDBENTRY const *pCur = g_apCpumDbEntries[i];
    973             if ((CPUMCPUVENDOR)pCur->enmVendor == enmVendor)
    974             {
    975                 /* Match against Family, Microarch, model and stepping.  Except
    976                    for family, always match the closer with preference given to
    977                    the later/older ones. */
    978                 if (pCur->uFamily == uFamily)
    979                 {
    980                     if (pCur->enmMicroarch == enmMicroarch)
    981                     {
    982                         if (pCur->uModel == uModel)
    983                         {
    984                             if (pCur->uStepping == uStepping)
    985                             {
    986                                 /* Perfect match. */
    987                                 pEntry = pCur;
    988                                 break;
    989                             }
    990 
    991                             if (   !pEntry
    992                                 || pEntry->uModel       != uModel
    993                                 || pEntry->enmMicroarch != enmMicroarch
    994                                 || pEntry->uFamily      != uFamily)
    995                                 pEntry = pCur;
    996                             else if (  pCur->uStepping >= uStepping
    997                                      ? pCur->uStepping < pEntry->uStepping || pEntry->uStepping < uStepping
    998                                      : pCur->uStepping > pEntry->uStepping)
    999                                      pEntry = pCur;
    1000                         }
    1001                         else if (   !pEntry
    1002                                  || pEntry->enmMicroarch != enmMicroarch
    1003                                  || pEntry->uFamily      != uFamily)
    1004                             pEntry = pCur;
    1005                         else if (  pCur->uModel >= uModel
    1006                                  ? pCur->uModel < pEntry->uModel || pEntry->uModel < uModel
    1007                                  : pCur->uModel > pEntry->uModel)
    1008                             pEntry = pCur;
    1009                     }
    1010                     else if (   !pEntry
    1011                              || pEntry->uFamily != uFamily)
    1012                         pEntry = pCur;
    1013                     /* Special march matching rules applies to intel family 06h. */
    1014                     else if (     enmVendor == CPUMCPUVENDOR_INTEL
    1015                                && uFamily   == 6
    1016                              ? cpumR3DbIsBetterIntelFam06Match(pCur->enmMicroarch, enmMicroarch, pEntry->enmMicroarch)
    1017                              : cpumR3DbIsBetterMarchMatch(pCur->enmMicroarch, enmMicroarch, pEntry->enmMicroarch))
    1018                         pEntry = pCur;
    1019                 }
    1020                 /* We don't do closeness matching on family, we use the first
    1021                    entry for the CPU vendor instead. (P4 workaround.) */
    1022                 else if (!pEntry)
    1023                     pEntry = pCur;
    1024             }
    1025         }
    1026 
    1027         if (pEntry)
    1028             LogRel(("CPUM: Matched host CPU %s %#x/%#x/%#x %s with CPU DB entry '%s' (%s %#x/%#x/%#x %s)\n",
    1029                     CPUMCpuVendorName(enmVendor), uFamily, uModel, uStepping, CPUMMicroarchName(enmMicroarch),
    1030                     pEntry->pszName,  CPUMCpuVendorName((CPUMCPUVENDOR)pEntry->enmVendor), pEntry->uFamily, pEntry->uModel,
    1031                     pEntry->uStepping, CPUMMicroarchName(pEntry->enmMicroarch) ));
    1032         else
    1033         {
    1034             pEntry = g_apCpumDbEntries[0];
    1035             LogRel(("CPUM: No matching processor database entry %s %#x/%#x/%#x %s, falling back on '%s'\n",
    1036                     CPUMCpuVendorName(enmVendor), uFamily, uModel, uStepping, CPUMMicroarchName(enmMicroarch),
    1037                     pEntry->pszName));
    1038         }
    1039     }
    1040     else
    1041 #else
    1042         pszName = g_apCpumDbEntries[0]->pszName; /* Just pick the first entry for non-x86 hosts. */
    1043 #endif
    1044     {
    1045         /*
    1046          * We're supposed to be emulating a specific CPU that is included in
    1047          * our CPU database.  The CPUID tables needs to be copied onto the
    1048          * heap so the caller can modify them and so they can be freed like
    1049          * in the host case above.
    1050          */
    1051         for (unsigned i = 0; i < RT_ELEMENTS(g_apCpumDbEntries); i++)
    1052             if (!strcmp(pszName, g_apCpumDbEntries[i]->pszName))
    1053             {
    1054                 pEntry = g_apCpumDbEntries[i];
    1055                 break;
    1056             }
    1057         if (!pEntry)
    1058         {
    1059             LogRel(("CPUM: Cannot locate any CPU by the name '%s'\n", pszName));
    1060             return VERR_CPUM_DB_CPU_NOT_FOUND;
    1061         }
    1062 
    1063537        pInfo->cCpuIdLeaves = pEntry->cCpuIdLeaves;
    1064538        if (pEntry->cCpuIdLeaves)
     
    1080554
    1081555        LogRel(("CPUM: Using CPU DB entry '%s' (%s %#x/%#x/%#x %s)\n",
    1082                 pEntry->pszName, CPUMCpuVendorName((CPUMCPUVENDOR)pEntry->enmVendor),
    1083                 pEntry->uFamily, pEntry->uModel, pEntry->uStepping, CPUMMicroarchName(pEntry->enmMicroarch) ));
     556                pEntry->Core.pszName, CPUMCpuVendorName(pEntry->Core.enmVendor),
     557                pEntry->uFamily, pEntry->uModel, pEntry->uStepping, CPUMMicroarchName(pEntry->Core.enmMicroarch) ));
    1084558    }
    1085559
     
    1098572    while (cLeft-- > 0)
    1099573    {
    1100         rc = cpumR3MsrRangesInsert(NULL /* pVM */, &paMsrs, &cMsrs, pCurMsr);
     574        int rc = cpumR3MsrRangesInsert(NULL /* pVM */, &paMsrs, &cMsrs, pCurMsr);
    1101575        if (RT_FAILURE(rc))
    1102576        {
     
    1111585    pInfo->paMsrRangesR3   = paMsrs;
    1112586    pInfo->cMsrRanges      = cMsrs;
     587
     588#elif defined(VBOX_VMM_TARGET_ARMV8)
     589    /*
     590     * ARM.
     591     */
     592    AssertReturn(pEntryCore->enmEntryType == CPUMDBENTRYTYPE_ARM, VERR_INTERNAL_ERROR_3);
     593    PCCPUMDBENTRYARM const pEntry = (PCCPUMDBENTRYARM)pEntryCore;
     594    RT_NOREF(pInfo, pEntry, fHost);
     595
     596#else
     597# error "port me"
     598#endif
    1113599    return VINF_SUCCESS;
    1114600}
    1115601
    1116602
    1117 /**
    1118  * Insert an MSR range into the VM.
    1119  *
    1120  * If the new MSR range overlaps existing ranges, the existing ones will be
    1121  * adjusted/removed to fit in the new one.
    1122  *
    1123  * @returns VBox status code.
    1124  * @param   pVM                 The cross context VM structure.
    1125  * @param   pNewRange           Pointer to the MSR range being inserted.
    1126  */
    1127 VMMR3DECL(int) CPUMR3MsrRangesInsert(PVM pVM, PCCPUMMSRRANGE pNewRange)
    1128 {
    1129     AssertReturn(pVM, VERR_INVALID_PARAMETER);
    1130     AssertReturn(pNewRange, VERR_INVALID_PARAMETER);
    1131 
    1132     return cpumR3MsrRangesInsert(pVM, NULL /* ppaMsrRanges */, NULL /* pcMsrRanges */, pNewRange);
    1133 }
    1134 
    1135 
    1136 /**
    1137  * Register statistics for the MSRs.
    1138  *
    1139  * This must not be called before the MSRs have been finalized and moved to the
    1140  * hyper heap.
    1141  *
    1142  * @returns VBox status code.
    1143  * @param   pVM                 The cross context VM structure.
    1144  */
    1145 int cpumR3MsrRegStats(PVM pVM)
    1146 {
    1147     /*
    1148      * Global statistics.
    1149      */
    1150     PCPUM pCpum = &pVM->cpum.s;
    1151     STAM_REL_REG(pVM, &pCpum->cMsrReads,                STAMTYPE_COUNTER,   "/CPUM/MSR-Totals/Reads",
    1152                  STAMUNIT_OCCURENCES, "All RDMSRs making it to CPUM.");
    1153     STAM_REL_REG(pVM, &pCpum->cMsrReadsRaiseGp,         STAMTYPE_COUNTER,   "/CPUM/MSR-Totals/ReadsRaisingGP",
    1154                  STAMUNIT_OCCURENCES, "RDMSR raising #GPs, except unknown MSRs.");
    1155     STAM_REL_REG(pVM, &pCpum->cMsrReadsUnknown,         STAMTYPE_COUNTER,   "/CPUM/MSR-Totals/ReadsUnknown",
    1156                  STAMUNIT_OCCURENCES, "RDMSR on unknown MSRs (raises #GP).");
    1157     STAM_REL_REG(pVM, &pCpum->cMsrWrites,               STAMTYPE_COUNTER,   "/CPUM/MSR-Totals/Writes",
    1158                  STAMUNIT_OCCURENCES, "All WRMSRs making it to CPUM.");
    1159     STAM_REL_REG(pVM, &pCpum->cMsrWritesRaiseGp,        STAMTYPE_COUNTER,   "/CPUM/MSR-Totals/WritesRaisingGP",
    1160                  STAMUNIT_OCCURENCES, "WRMSR raising #GPs, except unknown MSRs.");
    1161     STAM_REL_REG(pVM, &pCpum->cMsrWritesToIgnoredBits,  STAMTYPE_COUNTER,   "/CPUM/MSR-Totals/WritesToIgnoredBits",
    1162                  STAMUNIT_OCCURENCES, "Writing of ignored bits.");
    1163     STAM_REL_REG(pVM, &pCpum->cMsrWritesUnknown,        STAMTYPE_COUNTER,   "/CPUM/MSR-Totals/WritesUnknown",
    1164                  STAMUNIT_OCCURENCES, "WRMSR on unknown MSRs (raises #GP).");
    1165 
    1166 
    1167 # ifdef VBOX_WITH_STATISTICS
    1168     /*
    1169      * Per range.
    1170      */
    1171     PCPUMMSRRANGE   paRanges = pVM->cpum.s.GuestInfo.paMsrRangesR3;
    1172     uint32_t        cRanges  = pVM->cpum.s.GuestInfo.cMsrRanges;
    1173     for (uint32_t i = 0; i < cRanges; i++)
     603int cpumR3DbGetCpuInfo(const char *pszName, PCPUMINFO pInfo)
     604{
     605#ifdef VBOX_VMM_TARGET_X86
     606    CPUMDBENTRYTYPE const enmEntryType = CPUMDBENTRYTYPE_X86;
     607#elif defined(VBOX_VMM_TARGET_ARMV8)
     608    CPUMDBENTRYTYPE const enmEntryType = CPUMDBENTRYTYPE_ARM;
     609#else
     610# error "port me"
     611#endif
     612
     613    /*
     614     * Deal with the dynamic 'host' entry first.
     615     *
     616     * If we're not on a matchin host, we just pick the first entry in the
     617     * table and proceed as if this was specified by the caller (configured).
     618     */
     619    if (!strcmp(pszName, "host"))
    1174620    {
    1175         char    szName[160];
    1176         ssize_t cchName;
    1177 
    1178         if (paRanges[i].uFirst == paRanges[i].uLast)
    1179             cchName = RTStrPrintf(szName, sizeof(szName), "/CPUM/MSRs/%#010x-%s",
    1180                                   paRanges[i].uFirst, paRanges[i].szName);
    1181         else
    1182             cchName = RTStrPrintf(szName, sizeof(szName), "/CPUM/MSRs/%#010x-%#010x-%s",
    1183                                   paRanges[i].uFirst, paRanges[i].uLast, paRanges[i].szName);
    1184 
    1185         RTStrCopy(&szName[cchName], sizeof(szName) - cchName, "-reads");
    1186         STAMR3Register(pVM, &paRanges[i].cReads, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, szName, STAMUNIT_OCCURENCES, "RDMSR");
    1187 
    1188         RTStrCopy(&szName[cchName], sizeof(szName) - cchName, "-writes");
    1189         STAMR3Register(pVM, &paRanges[i].cWrites, STAMTYPE_COUNTER, STAMVISIBILITY_USED, szName, STAMUNIT_OCCURENCES, "WRMSR");
    1190 
    1191         RTStrCopy(&szName[cchName], sizeof(szName) - cchName, "-GPs");
    1192         STAMR3Register(pVM, &paRanges[i].cGps, STAMTYPE_COUNTER, STAMVISIBILITY_USED, szName, STAMUNIT_OCCURENCES, "#GPs");
    1193 
    1194         RTStrCopy(&szName[cchName], sizeof(szName) - cchName, "-ign-bits-writes");
    1195         STAMR3Register(pVM, &paRanges[i].cIgnoredBits, STAMTYPE_COUNTER, STAMVISIBILITY_USED, szName, STAMUNIT_OCCURENCES, "WRMSR w/ ignored bits");
     621#if (defined(VBOX_VMM_TARGET_X86) && (defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86))) \
     622 || (defined(VBOX_VMM_TARGET_ARMV8) && defined(RT_ARCH_ARM64) && 0)
     623        return cpumR3DbCreateHostEntry(pInfo);
     624#else
     625        Assert(g_apCpumDbEntries[0]->enmEntryType == enmEntryType);
     626        pszName = g_apCpumDbEntries[0]->pszName; /* Just pick the first entry for non-x86 hosts. */
     627#endif
    1196628    }
    1197 # endif /* VBOX_WITH_STATISTICS */
    1198 
    1199     return VINF_SUCCESS;
    1200 }
    1201 
    1202 #endif /* !CPUM_DB_STANDALONE */
    1203 
     629
     630    /*
     631     * We're supposed to be emulating a specific CPU from the database.
     632     */
     633    for (unsigned i = 0; i < RT_ELEMENTS(g_apCpumDbEntries); i++)
     634        if (   g_apCpumDbEntries[i]->enmEntryType == enmEntryType
     635            && !strcmp(pszName, g_apCpumDbEntries[i]->pszName))
     636            return cpumDbPopulateInfoFromEntry(pInfo, g_apCpumDbEntries[i], false /*fHost*/);
     637    LogRel(("CPUM: Cannot locate any CPU by the name '%s'\n", pszName));
     638    return VERR_CPUM_DB_CPU_NOT_FOUND;
     639}
     640
  • trunk/src/VBox/VMM/VMMR3/CPUMR3Msr-x86.cpp

    • Property svn:mergeinfo set to (toggle deleted branches)
      /branches/VBox-3.0/src/VBox/VMM/VMMR3/CPUMR3Db.cpp58652,​70973
      /branches/VBox-3.2/src/VBox/VMM/VMMR3/CPUMR3Db.cpp66309,​66318
      /branches/VBox-4.0/src/VBox/VMM/VMMR3/CPUMR3Db.cpp70873
      /branches/VBox-4.1/src/VBox/VMM/VMMR3/CPUMR3Db.cpp74233,​78414,​78691,​81841,​82127,​85941,​85944-85947,​85949-85950,​85953,​86701,​86728,​87009
      /branches/VBox-4.2/src/VBox/VMM/VMMR3/CPUMR3Db.cpp86229-86230,​86234,​86529,​91503-91504,​91506-91508,​91510,​91514-91515,​91521,​108112,​108114,​108127
      /branches/VBox-4.3/src/VBox/VMM/VMMR3/CPUMR3Db.cpp89714,​91223,​93628-93629,​94066,​94839,​94897,​95154,​95164,​95167,​95295,​95338,​95353-95354,​95356,​95367,​95451,​95475,​95477,​95480,​95507,​95640,​95659,​95661,​95663,​98913-98914
      /branches/VBox-4.3/trunk/src/VBox/VMM/VMMR3/CPUMR3Db.cpp91223
      /branches/VBox-5.0/src/VBox/VMM/VMMR3/CPUMR3Db.cpp104938,​104943,​104950,​104987-104988,​104990,​106453
      /branches/VBox-5.1/src/VBox/VMM/VMMR3/CPUMR3Db.cpp112367,​116543,​116550,​116568,​116573
      /branches/VBox-5.2/src/VBox/VMM/VMMR3/CPUMR3Db.cpp119536,​120083,​120099,​120213,​120221,​120239,​123597-123598,​123600-123601,​123755,​124263,​124273,​124277-124279,​124284-124286,​124288-124290,​125768,​125779-125780,​125812,​127158-127159,​127162-127167,​127180
      /branches/VBox-6.0/src/VBox/VMM/VMMR3/CPUMR3Db.cpp130474-130475,​130477,​130479,​131352
      /branches/VBox-6.1/src/VBox/VMM/VMMR3/CPUMR3Db.cpp141521,​141567-141568,​141588-141590,​141592-141595,​141652,​141920,​158257-158259
      /branches/VBox-7.0/src/VBox/VMM/VMMR3/CPUMR3Db.cpp156229,​156768
      /branches/aeichner/vbox-chromium-cleanup/src/VBox/VMM/VMMR3/CPUMR3Db.cpp129818-129851,​129853-129861,​129871-129872,​129876,​129880,​129882,​130013-130015,​130094-130095
      /branches/andy/draganddrop/src/VBox/VMM/VMMR3/CPUMR3Db.cpp90781-91268
      /branches/andy/guestctrl20/src/VBox/VMM/VMMR3/CPUMR3Db.cpp78916,​78930
      /branches/andy/pdmaudio/src/VBox/VMM/VMMR3/CPUMR3Db.cpp94582,​94641,​94654,​94688,​94778,​94783,​94816,​95197,​95215-95216,​95250,​95279,​95505-95506,​95543,​95694,​96323,​96470-96471,​96582,​96587,​96802-96803,​96817,​96904,​96967,​96999,​97020-97021,​97025,​97050,​97099
      /branches/bird/hardenedwindows/src/VBox/VMM/VMMR3/CPUMR3Db.cpp92692-94610
      /branches/dsen/gui/src/VBox/VMM/VMMR3/CPUMR3Db.cpp79076-79078,​79089,​79109-79110,​79112-79113,​79127-79130,​79134,​79141,​79151,​79155,​79157-79159,​79193,​79197
      /branches/dsen/gui2/src/VBox/VMM/VMMR3/CPUMR3Db.cpp79224,​79228,​79233,​79235,​79258,​79262-79263,​79273,​79341,​79345,​79354,​79357,​79387-79388,​79559-79569,​79572-79573,​79578,​79581-79582,​79590-79591,​79598-79599,​79602-79603,​79605-79606,​79632,​79635,​79637,​79644
      /branches/dsen/gui3/src/VBox/VMM/VMMR3/CPUMR3Db.cpp79645-79692
      /branches/dsen/gui4/src/VBox/VMM/VMMR3/CPUMR3Db.cpp155183-155185,​155187,​155198,​155200-155201,​155205,​155228,​155235,​155243,​155248,​155282,​155285,​155287-155288,​155311,​155316,​155336,​155342,​155344,​155437-155438,​155441,​155443,​155488,​155509-155513,​155526-155527,​155559,​155572,​155576-155577,​155592-155593
    r108997 r109008  
    4343#include <iprt/string.h>
    4444
    45 
    46 /*********************************************************************************************************************************
    47 *   Defined Constants And Macros                                                                                                 *
    48 *********************************************************************************************************************************/
    49 /** @def NULL_ALONE
    50  * For eliminating an unnecessary data dependency in standalone builds (for
    51  * VBoxSVC). */
    52 /** @def ZERO_ALONE
    53  * For eliminating an unnecessary data size dependency in standalone builds (for
    54  * VBoxSVC). */
    55 #ifndef CPUM_DB_STANDALONE
    56 # define NULL_ALONE(a_aTable)    a_aTable
    57 # define ZERO_ALONE(a_cTable)    a_cTable
    58 #else
    59 # define NULL_ALONE(a_aTable)    NULL
    60 # define ZERO_ALONE(a_cTable)    0
    61 #endif
    62 
    63 
    64 /** @name Short macros for the MSR range entries.
    65  *
    66  * These are rather cryptic, but this is to reduce the attack on the right
    67  * margin.
    68  *
    69  * @{ */
    70 /** Alias one MSR onto another (a_uTarget). */
    71 #define MAL(a_uMsr, a_szName, a_uTarget) \
    72     RINT(a_uMsr, a_uMsr, kCpumMsrRdFn_MsrAlias, kCpumMsrWrFn_MsrAlias, 0, a_uTarget, 0, 0, a_szName)
    73 /** Functions handles everything. */
    74 #define MFN(a_uMsr, a_szName, a_enmRdFnSuff, a_enmWrFnSuff) \
    75     RINT(a_uMsr, a_uMsr, kCpumMsrRdFn_##a_enmRdFnSuff, kCpumMsrWrFn_##a_enmWrFnSuff, 0, 0, 0, 0, a_szName)
    76 /** Functions handles everything, with GP mask. */
    77 #define MFG(a_uMsr, a_szName, a_enmRdFnSuff, a_enmWrFnSuff, a_fWrGpMask) \
    78     RINT(a_uMsr, a_uMsr, kCpumMsrRdFn_##a_enmRdFnSuff, kCpumMsrWrFn_##a_enmWrFnSuff, 0, 0, 0, a_fWrGpMask, a_szName)
    79 /** Function handlers, read-only. */
    80 #define MFO(a_uMsr, a_szName, a_enmRdFnSuff) \
    81     RINT(a_uMsr, a_uMsr, kCpumMsrRdFn_##a_enmRdFnSuff, kCpumMsrWrFn_ReadOnly, 0, 0, 0, UINT64_MAX, a_szName)
    82 /** Function handlers, ignore all writes. */
    83 #define MFI(a_uMsr, a_szName, a_enmRdFnSuff) \
    84     RINT(a_uMsr, a_uMsr, kCpumMsrRdFn_##a_enmRdFnSuff, kCpumMsrWrFn_IgnoreWrite, 0, 0, UINT64_MAX, 0, a_szName)
    85 /** Function handlers, with value. */
    86 #define MFV(a_uMsr, a_szName, a_enmRdFnSuff, a_enmWrFnSuff, a_uValue) \
    87     RINT(a_uMsr, a_uMsr, kCpumMsrRdFn_##a_enmRdFnSuff, kCpumMsrWrFn_##a_enmWrFnSuff, 0, a_uValue, 0, 0, a_szName)
    88 /** Function handlers, with write ignore mask. */
    89 #define MFW(a_uMsr, a_szName, a_enmRdFnSuff, a_enmWrFnSuff, a_fWrIgnMask) \
    90     RINT(a_uMsr, a_uMsr, kCpumMsrRdFn_##a_enmRdFnSuff, kCpumMsrWrFn_##a_enmWrFnSuff, 0, 0, a_fWrIgnMask, 0, a_szName)
    91 /** Function handlers, extended version. */
    92 #define MFX(a_uMsr, a_szName, a_enmRdFnSuff, a_enmWrFnSuff, a_uValue, a_fWrIgnMask, a_fWrGpMask) \
    93     RINT(a_uMsr, a_uMsr, kCpumMsrRdFn_##a_enmRdFnSuff, kCpumMsrWrFn_##a_enmWrFnSuff, 0, a_uValue, a_fWrIgnMask, a_fWrGpMask, a_szName)
    94 /** Function handlers, with CPUMCPU storage variable. */
    95 #define MFS(a_uMsr, a_szName, a_enmRdFnSuff, a_enmWrFnSuff, a_CpumCpuMember) \
    96     RINT(a_uMsr, a_uMsr, kCpumMsrRdFn_##a_enmRdFnSuff, kCpumMsrWrFn_##a_enmWrFnSuff, \
    97          RT_OFFSETOF(CPUMCPU, a_CpumCpuMember), 0, 0, 0, a_szName)
    98 /** Function handlers, with CPUMCPU storage variable, ignore mask and GP mask. */
    99 #define MFZ(a_uMsr, a_szName, a_enmRdFnSuff, a_enmWrFnSuff, a_CpumCpuMember, a_fWrIgnMask, a_fWrGpMask) \
    100     RINT(a_uMsr, a_uMsr, kCpumMsrRdFn_##a_enmRdFnSuff, kCpumMsrWrFn_##a_enmWrFnSuff, \
    101          RT_OFFSETOF(CPUMCPU, a_CpumCpuMember), 0, a_fWrIgnMask, a_fWrGpMask, a_szName)
    102 /** Read-only fixed value. */
    103 #define MVO(a_uMsr, a_szName, a_uValue) \
    104     RINT(a_uMsr, a_uMsr, kCpumMsrRdFn_FixedValue, kCpumMsrWrFn_ReadOnly, 0, a_uValue, 0, UINT64_MAX, a_szName)
    105 /** Read-only fixed value, ignores all writes. */
    106 #define MVI(a_uMsr, a_szName, a_uValue) \
    107     RINT(a_uMsr, a_uMsr, kCpumMsrRdFn_FixedValue, kCpumMsrWrFn_IgnoreWrite, 0, a_uValue, UINT64_MAX, 0, a_szName)
    108 /** Read fixed value, ignore writes outside GP mask. */
    109 #define MVG(a_uMsr, a_szName, a_uValue, a_fWrGpMask) \
    110     RINT(a_uMsr, a_uMsr, kCpumMsrRdFn_FixedValue, kCpumMsrWrFn_IgnoreWrite, 0, a_uValue, 0, a_fWrGpMask, a_szName)
    111 /** Read fixed value, extended version with both GP and ignore masks. */
    112 #define MVX(a_uMsr, a_szName, a_uValue, a_fWrIgnMask, a_fWrGpMask) \
    113     RINT(a_uMsr, a_uMsr, kCpumMsrRdFn_FixedValue, kCpumMsrWrFn_IgnoreWrite, 0, a_uValue, a_fWrIgnMask, a_fWrGpMask, a_szName)
    114 /** The short form, no CPUM backing. */
    115 #define MSN(a_uMsr, a_szName, a_enmRdFnSuff, a_enmWrFnSuff, a_uInitOrReadValue, a_fWrIgnMask, a_fWrGpMask) \
    116     RINT(a_uMsr, a_uMsr, kCpumMsrRdFn_##a_enmRdFnSuff, kCpumMsrWrFn_##a_enmWrFnSuff, 0, \
    117          a_uInitOrReadValue, a_fWrIgnMask, a_fWrGpMask, a_szName)
    118 
    119 /** Range: Functions handles everything. */
    120 #define RFN(a_uFirst, a_uLast, a_szName, a_enmRdFnSuff, a_enmWrFnSuff) \
    121     RINT(a_uFirst, a_uLast, kCpumMsrRdFn_##a_enmRdFnSuff, kCpumMsrWrFn_##a_enmWrFnSuff, 0, 0, 0, 0, a_szName)
    122 /** Range: Read fixed value, read-only. */
    123 #define RVO(a_uFirst, a_uLast, a_szName, a_uValue) \
    124     RINT(a_uFirst, a_uLast, kCpumMsrRdFn_FixedValue, kCpumMsrWrFn_ReadOnly, 0, a_uValue, 0, UINT64_MAX, a_szName)
    125 /** Range: Read fixed value, ignore writes. */
    126 #define RVI(a_uFirst, a_uLast, a_szName, a_uValue) \
    127     RINT(a_uFirst, a_uLast, kCpumMsrRdFn_FixedValue, kCpumMsrWrFn_IgnoreWrite, 0, a_uValue, UINT64_MAX, 0, a_szName)
    128 /** Range: The short form, no CPUM backing. */
    129 #define RSN(a_uFirst, a_uLast, a_szName, a_enmRdFnSuff, a_enmWrFnSuff, a_uInitOrReadValue, a_fWrIgnMask, a_fWrGpMask) \
    130     RINT(a_uFirst, a_uLast, kCpumMsrRdFn_##a_enmRdFnSuff, kCpumMsrWrFn_##a_enmWrFnSuff, 0, \
    131          a_uInitOrReadValue, a_fWrIgnMask, a_fWrGpMask, a_szName)
    132 
    133 /** Internal form used by the macros. */
    134 #ifdef VBOX_WITH_STATISTICS
    135 # define RINT(a_uFirst, a_uLast, a_enmRdFn, a_enmWrFn, a_offCpumCpu, a_uInitOrReadValue, a_fWrIgnMask, a_fWrGpMask, a_szName) \
    136     { a_uFirst, a_uLast, a_enmRdFn, a_enmWrFn, a_offCpumCpu, 0, a_uInitOrReadValue, a_fWrIgnMask, a_fWrGpMask, a_szName, \
    137       { 0 }, { 0 }, { 0 }, { 0 } }
    138 #else
    139 # define RINT(a_uFirst, a_uLast, a_enmRdFn, a_enmWrFn, a_offCpumCpu, a_uInitOrReadValue, a_fWrIgnMask, a_fWrGpMask, a_szName) \
    140     { a_uFirst, a_uLast, a_enmRdFn, a_enmWrFn, a_offCpumCpu, 0, a_uInitOrReadValue, a_fWrIgnMask, a_fWrGpMask, a_szName }
    141 #endif
    142 /** @} */
    143 
    144 #ifndef CPUM_DB_STANDALONE
    145 
    146 #include "cpus/Intel_Core_i7_6700K.h"
    147 #include "cpus/Intel_Core_i7_5600U.h"
    148 #include "cpus/Intel_Core_i7_3960X.h"
    149 #include "cpus/Intel_Core_i5_3570.h"
    150 #include "cpus/Intel_Core_i7_2635QM.h"
    151 #include "cpus/Intel_Xeon_X5482_3_20GHz.h"
    152 #include "cpus/Intel_Core2_X6800_2_93GHz.h"
    153 #include "cpus/Intel_Core2_T7600_2_33GHz.h"
    154 #include "cpus/Intel_Core_Duo_T2600_2_16GHz.h"
    155 #include "cpus/Intel_Pentium_M_processor_2_00GHz.h"
    156 #include "cpus/Intel_Pentium_4_3_00GHz.h"
    157 #include "cpus/Intel_Pentium_N3530_2_16GHz.h"
    158 #include "cpus/Intel_Atom_330_1_60GHz.h"
    159 #include "cpus/Intel_80486.h"
    160 #include "cpus/Intel_80386.h"
    161 #include "cpus/Intel_80286.h"
    162 #include "cpus/Intel_80186.h"
    163 #include "cpus/Intel_8086.h"
    164 
    165 #include "cpus/AMD_Ryzen_7_1800X_Eight_Core.h"
    166 #include "cpus/AMD_FX_8150_Eight_Core.h"
    167 #include "cpus/AMD_Phenom_II_X6_1100T.h"
    168 #include "cpus/Quad_Core_AMD_Opteron_2384.h"
    169 #include "cpus/AMD_Athlon_64_X2_Dual_Core_4200.h"
    170 #include "cpus/AMD_Athlon_64_3200.h"
    171 
    172 #include "cpus/VIA_QuadCore_L4700_1_2_GHz.h"
    173 
    174 #include "cpus/ZHAOXIN_KaiXian_KX_U5581_1_8GHz.h"
    175 
    176 #include "cpus/Hygon_C86_7185_32_core.h"
    177 
    178 
    179 /**
    180  * The database entries.
    181  *
    182  * 1. The first entry is special.  It is the fallback for unknown
    183  *    processors.  Thus, it better be pretty representative.
    184  *
    185  * 2. The first entry for a CPU vendor is likewise important as it is
    186  *    the default entry for that vendor.
    187  *
    188  * Generally we put the most recent CPUs first, since these tend to have the
    189  * most complicated and backwards compatible list of MSRs.
    190  */
    191 static CPUMDBENTRY const * const g_apCpumDbEntries[] =
    192 {
    193 #ifdef VBOX_CPUDB_Intel_Core_i7_6700K_h
    194     &g_Entry_Intel_Core_i7_6700K,
    195 #endif
    196 #ifdef VBOX_CPUDB_Intel_Core_i7_5600U_h
    197     &g_Entry_Intel_Core_i7_5600U,
    198 #endif
    199 #ifdef VBOX_CPUDB_Intel_Core_i5_3570_h
    200     &g_Entry_Intel_Core_i5_3570,
    201 #endif
    202 #ifdef VBOX_CPUDB_Intel_Core_i7_3960X_h
    203     &g_Entry_Intel_Core_i7_3960X,
    204 #endif
    205 #ifdef VBOX_CPUDB_Intel_Core_i7_2635QM_h
    206     &g_Entry_Intel_Core_i7_2635QM,
    207 #endif
    208 #ifdef VBOX_CPUDB_Intel_Pentium_N3530_2_16GHz_h
    209     &g_Entry_Intel_Pentium_N3530_2_16GHz,
    210 #endif
    211 #ifdef VBOX_CPUDB_Intel_Atom_330_1_60GHz_h
    212     &g_Entry_Intel_Atom_330_1_60GHz,
    213 #endif
    214 #ifdef VBOX_CPUDB_Intel_Pentium_M_processor_2_00GHz_h
    215     &g_Entry_Intel_Pentium_M_processor_2_00GHz,
    216 #endif
    217 #ifdef VBOX_CPUDB_Intel_Xeon_X5482_3_20GHz_h
    218     &g_Entry_Intel_Xeon_X5482_3_20GHz,
    219 #endif
    220 #ifdef VBOX_CPUDB_Intel_Core2_X6800_2_93GHz_h
    221     &g_Entry_Intel_Core2_X6800_2_93GHz,
    222 #endif
    223 #ifdef VBOX_CPUDB_Intel_Core2_T7600_2_33GHz_h
    224     &g_Entry_Intel_Core2_T7600_2_33GHz,
    225 #endif
    226 #ifdef VBOX_CPUDB_Intel_Core_Duo_T2600_2_16GHz_h
    227     &g_Entry_Intel_Core_Duo_T2600_2_16GHz,
    228 #endif
    229 #ifdef VBOX_CPUDB_Intel_Pentium_4_3_00GHz_h
    230     &g_Entry_Intel_Pentium_4_3_00GHz,
    231 #endif
    232 /** @todo pentium, pentium mmx, pentium pro, pentium II, pentium III */
    233 #ifdef VBOX_CPUDB_Intel_80486_h
    234     &g_Entry_Intel_80486,
    235 #endif
    236 #ifdef VBOX_CPUDB_Intel_80386_h
    237     &g_Entry_Intel_80386,
    238 #endif
    239 #ifdef VBOX_CPUDB_Intel_80286_h
    240     &g_Entry_Intel_80286,
    241 #endif
    242 #ifdef VBOX_CPUDB_Intel_80186_h
    243     &g_Entry_Intel_80186,
    244 #endif
    245 #ifdef VBOX_CPUDB_Intel_8086_h
    246     &g_Entry_Intel_8086,
    247 #endif
    248 
    249 #ifdef VBOX_CPUDB_AMD_Ryzen_7_1800X_Eight_Core_h
    250     &g_Entry_AMD_Ryzen_7_1800X_Eight_Core,
    251 #endif
    252 #ifdef VBOX_CPUDB_AMD_FX_8150_Eight_Core_h
    253     &g_Entry_AMD_FX_8150_Eight_Core,
    254 #endif
    255 #ifdef VBOX_CPUDB_AMD_Phenom_II_X6_1100T_h
    256     &g_Entry_AMD_Phenom_II_X6_1100T,
    257 #endif
    258 #ifdef VBOX_CPUDB_Quad_Core_AMD_Opteron_2384_h
    259     &g_Entry_Quad_Core_AMD_Opteron_2384,
    260 #endif
    261 #ifdef VBOX_CPUDB_AMD_Athlon_64_X2_Dual_Core_4200_h
    262     &g_Entry_AMD_Athlon_64_X2_Dual_Core_4200,
    263 #endif
    264 #ifdef VBOX_CPUDB_AMD_Athlon_64_3200_h
    265     &g_Entry_AMD_Athlon_64_3200,
    266 #endif
    267 
    268 #ifdef VBOX_CPUDB_ZHAOXIN_KaiXian_KX_U5581_1_8GHz_h
    269     &g_Entry_ZHAOXIN_KaiXian_KX_U5581_1_8GHz,
    270 #endif
    271 
    272 #ifdef VBOX_CPUDB_VIA_QuadCore_L4700_1_2_GHz_h
    273     &g_Entry_VIA_QuadCore_L4700_1_2_GHz,
    274 #endif
    275 
    276 #ifdef VBOX_CPUDB_NEC_V20_h
    277     &g_Entry_NEC_V20,
    278 #endif
    279 
    280 #ifdef VBOX_CPUDB_Hygon_C86_7185_32_core_h
    281     &g_Entry_Hygon_C86_7185_32_core,
    282 #endif
    283 };
    284 
    285 
    286 /**
    287  * Returns the number of entries in the CPU database.
    288  *
    289  * @returns Number of entries.
    290  * @sa      PFNCPUMDBGETENTRIES
    291  */
    292 VMMR3DECL(uint32_t)         CPUMR3DbGetEntries(void)
    293 {
    294     return RT_ELEMENTS(g_apCpumDbEntries);
    295 }
    296 
    297 
    298 /**
    299  * Returns CPU database entry for the given index.
    300  *
    301  * @returns Pointer the CPU database entry, NULL if index is out of bounds.
    302  * @param   idxCpuDb            The index (0..CPUMR3DbGetEntries).
    303  * @sa      PFNCPUMDBGETENTRYBYINDEX
    304  */
    305 VMMR3DECL(PCCPUMDBENTRY)    CPUMR3DbGetEntryByIndex(uint32_t idxCpuDb)
    306 {
    307     AssertReturn(idxCpuDb < RT_ELEMENTS(g_apCpumDbEntries), NULL);
    308     return g_apCpumDbEntries[idxCpuDb];
    309 }
    310 
    311 
    312 /**
    313  * Returns CPU database entry with the given name.
    314  *
    315  * @returns Pointer the CPU database entry, NULL if not found.
    316  * @param   pszName             The name of the profile to return.
    317  * @sa      PFNCPUMDBGETENTRYBYNAME
    318  */
    319 VMMR3DECL(PCCPUMDBENTRY)    CPUMR3DbGetEntryByName(const char *pszName)
    320 {
    321     AssertPtrReturn(pszName, NULL);
    322     AssertReturn(*pszName, NULL);
    323     for (size_t i = 0; i < RT_ELEMENTS(g_apCpumDbEntries); i++)
    324         if (strcmp(g_apCpumDbEntries[i]->pszName, pszName) == 0)
    325             return g_apCpumDbEntries[i];
    326     return NULL;
    327 }
    328 
     45#include "CPUMR3Msr-x86.h"
    32946
    33047
     
    816533}
    817534
    818 #if defined(RT_ARCH_X86) || defined(RT_ARCH_AMD64)
    819 
    820 /**
    821  * Do we consider @a enmConsider a better match for @a enmTarget than
    822  * @a enmFound?
    823  *
    824  * Only called when @a enmConsider isn't exactly what we're looking for.
    825  *
    826  * @returns true/false.
    827  * @param   enmConsider         The new microarch to consider.
    828  * @param   enmTarget           The target microarch.
    829  * @param   enmFound            The best microarch match we've found thus far.
    830  */
    831 DECLINLINE(bool) cpumR3DbIsBetterMarchMatch(CPUMMICROARCH enmConsider, CPUMMICROARCH enmTarget, CPUMMICROARCH enmFound)
    832 {
    833     Assert(enmConsider != enmTarget);
    834 
    835     /*
    836      * If we've got an march match, don't bother with enmConsider.
    837      */
    838     if (enmFound == enmTarget)
    839         return false;
    840 
    841     /*
    842      * Found is below: Pick 'consider' if it's closer to the target or above it.
    843      */
    844     if (enmFound < enmTarget)
    845         return enmConsider > enmFound;
    846 
    847     /*
    848      * Found is above: Pick 'consider' if it's also above (paranoia: or equal)
    849      *                 and but closer to the target.
    850      */
    851     return enmConsider >= enmTarget && enmConsider < enmFound;
    852 }
    853 
    854 
    855 /**
    856  * Do we consider @a enmConsider a better match for @a enmTarget than
    857  * @a enmFound?
    858  *
    859  * Only called for intel family 06h CPUs.
    860  *
    861  * @returns true/false.
    862  * @param   enmConsider         The new microarch to consider.
    863  * @param   enmTarget           The target microarch.
    864  * @param   enmFound            The best microarch match we've found thus far.
    865  */
    866 static bool cpumR3DbIsBetterIntelFam06Match(CPUMMICROARCH enmConsider, CPUMMICROARCH enmTarget, CPUMMICROARCH enmFound)
    867 {
    868     /* Check intel family 06h claims. */
    869     AssertReturn(enmConsider >= kCpumMicroarch_Intel_P6_Core_Atom_First && enmConsider <= kCpumMicroarch_Intel_P6_Core_Atom_End,
    870                  false);
    871     AssertReturn(   (enmTarget >= kCpumMicroarch_Intel_P6_Core_Atom_First && enmTarget <= kCpumMicroarch_Intel_P6_Core_Atom_End)
    872                  || enmTarget == kCpumMicroarch_Intel_Unknown,
    873                  false);
    874 
    875     /* Put matches out of the way. */
    876     if (enmConsider == enmTarget)
    877         return true;
    878     if (enmFound == enmTarget)
    879         return false;
    880 
    881     /* If found isn't a family 06h march, whatever we're considering must be a better choice. */
    882     if (   enmFound < kCpumMicroarch_Intel_P6_Core_Atom_First
    883         || enmFound > kCpumMicroarch_Intel_P6_Core_Atom_End)
    884         return true;
    885 
    886     /*
    887      * The family 06h stuff is split into three categories:
    888      *      - Common P6 heritage
    889      *      - Core
    890      *      - Atom
    891      *
    892      * Determin which of the three arguments are Atom marchs, because that's
    893      * all we need to make the right choice.
    894      */
    895     bool const fConsiderAtom = enmConsider >= kCpumMicroarch_Intel_Atom_First;
    896     bool const fTargetAtom   = enmTarget   >= kCpumMicroarch_Intel_Atom_First;
    897     bool const fFoundAtom    = enmFound    >= kCpumMicroarch_Intel_Atom_First;
    898 
    899     /*
    900      * Want atom:
    901      */
    902     if (fTargetAtom)
    903     {
    904         /* Pick the atom if we've got one of each.*/
    905         if (fConsiderAtom != fFoundAtom)
    906             return fConsiderAtom;
    907         /* If we haven't got any atoms under consideration, pick a P6 or the earlier core.
    908            Note! Not entirely sure Dothan is the best choice, but it'll do for now. */
    909         if (!fConsiderAtom)
    910         {
    911             if (enmConsider > enmFound)
    912                 return enmConsider <= kCpumMicroarch_Intel_P6_M_Dothan;
    913             return enmFound > kCpumMicroarch_Intel_P6_M_Dothan;
    914         }
    915         /* else: same category, default comparison rules. */
    916         Assert(fConsiderAtom && fFoundAtom);
    917     }
    918     /*
    919      * Want non-atom:
    920      */
    921     /* Pick the non-atom if we've got one of each. */
    922     else if (fConsiderAtom != fFoundAtom)
    923         return fFoundAtom;
    924     /* If we've only got atoms under consideration, pick the older one just to pick something. */
    925     else if (fConsiderAtom)
    926         return enmConsider < enmFound;
    927     else
    928         Assert(!fConsiderAtom && !fFoundAtom);
    929 
    930     /*
    931      * Same basic category.  Do same compare as caller.
    932      */
    933     return cpumR3DbIsBetterMarchMatch(enmConsider, enmTarget, enmFound);
    934 }
    935 
    936 #endif /* RT_ARCH_X86 || RT_ARCH_AMD64 */
    937 
    938 int cpumR3DbGetCpuInfo(const char *pszName, PCPUMINFO pInfo)
    939 {
    940     CPUMDBENTRY const *pEntry = NULL;
    941     int                rc;
    942 
    943     if (!strcmp(pszName, "host"))
    944 #if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
    945     {
    946         /*
    947          * Create a CPU database entry for the host CPU.  This means getting
    948          * the CPUID bits from the real CPU and grabbing the closest matching
    949          * database entry for MSRs.
    950          */
    951         rc = CPUMR3CpuIdDetectUnknownLeafMethod(&pInfo->enmUnknownCpuIdMethod, &pInfo->DefCpuId);
    952         if (RT_FAILURE(rc))
    953             return rc;
    954         rc = CPUMCpuIdCollectLeavesFromX86Host(&pInfo->paCpuIdLeavesR3, &pInfo->cCpuIdLeaves);
    955         if (RT_FAILURE(rc))
    956             return rc;
    957         pInfo->fMxCsrMask = CPUMR3DeterminHostMxCsrMask();
    958 
    959         /* Lookup database entry for MSRs. */
    960         CPUMCPUVENDOR const enmVendor    = CPUMCpuIdDetectX86VendorEx(pInfo->paCpuIdLeavesR3[0].uEax,
    961                                                                       pInfo->paCpuIdLeavesR3[0].uEbx,
    962                                                                       pInfo->paCpuIdLeavesR3[0].uEcx,
    963                                                                       pInfo->paCpuIdLeavesR3[0].uEdx);
    964         uint32_t      const uStd1Eax     = pInfo->paCpuIdLeavesR3[1].uEax;
    965         uint8_t       const uFamily      = RTX86GetCpuFamily(uStd1Eax);
    966         uint8_t       const uModel       = RTX86GetCpuModel(uStd1Eax, enmVendor == CPUMCPUVENDOR_INTEL);
    967         uint8_t       const uStepping    = RTX86GetCpuStepping(uStd1Eax);
    968         CPUMMICROARCH const enmMicroarch = CPUMCpuIdDetermineX86MicroarchEx(enmVendor, uFamily, uModel, uStepping);
    969 
    970         for (unsigned i = 0; i < RT_ELEMENTS(g_apCpumDbEntries); i++)
    971         {
    972             CPUMDBENTRY const *pCur = g_apCpumDbEntries[i];
    973             if ((CPUMCPUVENDOR)pCur->enmVendor == enmVendor)
    974             {
    975                 /* Match against Family, Microarch, model and stepping.  Except
    976                    for family, always match the closer with preference given to
    977                    the later/older ones. */
    978                 if (pCur->uFamily == uFamily)
    979                 {
    980                     if (pCur->enmMicroarch == enmMicroarch)
    981                     {
    982                         if (pCur->uModel == uModel)
    983                         {
    984                             if (pCur->uStepping == uStepping)
    985                             {
    986                                 /* Perfect match. */
    987                                 pEntry = pCur;
    988                                 break;
    989                             }
    990 
    991                             if (   !pEntry
    992                                 || pEntry->uModel       != uModel
    993                                 || pEntry->enmMicroarch != enmMicroarch
    994                                 || pEntry->uFamily      != uFamily)
    995                                 pEntry = pCur;
    996                             else if (  pCur->uStepping >= uStepping
    997                                      ? pCur->uStepping < pEntry->uStepping || pEntry->uStepping < uStepping
    998                                      : pCur->uStepping > pEntry->uStepping)
    999                                      pEntry = pCur;
    1000                         }
    1001                         else if (   !pEntry
    1002                                  || pEntry->enmMicroarch != enmMicroarch
    1003                                  || pEntry->uFamily      != uFamily)
    1004                             pEntry = pCur;
    1005                         else if (  pCur->uModel >= uModel
    1006                                  ? pCur->uModel < pEntry->uModel || pEntry->uModel < uModel
    1007                                  : pCur->uModel > pEntry->uModel)
    1008                             pEntry = pCur;
    1009                     }
    1010                     else if (   !pEntry
    1011                              || pEntry->uFamily != uFamily)
    1012                         pEntry = pCur;
    1013                     /* Special march matching rules applies to intel family 06h. */
    1014                     else if (     enmVendor == CPUMCPUVENDOR_INTEL
    1015                                && uFamily   == 6
    1016                              ? cpumR3DbIsBetterIntelFam06Match(pCur->enmMicroarch, enmMicroarch, pEntry->enmMicroarch)
    1017                              : cpumR3DbIsBetterMarchMatch(pCur->enmMicroarch, enmMicroarch, pEntry->enmMicroarch))
    1018                         pEntry = pCur;
    1019                 }
    1020                 /* We don't do closeness matching on family, we use the first
    1021                    entry for the CPU vendor instead. (P4 workaround.) */
    1022                 else if (!pEntry)
    1023                     pEntry = pCur;
    1024             }
    1025         }
    1026 
    1027         if (pEntry)
    1028             LogRel(("CPUM: Matched host CPU %s %#x/%#x/%#x %s with CPU DB entry '%s' (%s %#x/%#x/%#x %s)\n",
    1029                     CPUMCpuVendorName(enmVendor), uFamily, uModel, uStepping, CPUMMicroarchName(enmMicroarch),
    1030                     pEntry->pszName,  CPUMCpuVendorName((CPUMCPUVENDOR)pEntry->enmVendor), pEntry->uFamily, pEntry->uModel,
    1031                     pEntry->uStepping, CPUMMicroarchName(pEntry->enmMicroarch) ));
    1032         else
    1033         {
    1034             pEntry = g_apCpumDbEntries[0];
    1035             LogRel(("CPUM: No matching processor database entry %s %#x/%#x/%#x %s, falling back on '%s'\n",
    1036                     CPUMCpuVendorName(enmVendor), uFamily, uModel, uStepping, CPUMMicroarchName(enmMicroarch),
    1037                     pEntry->pszName));
    1038         }
    1039     }
    1040     else
    1041 #else
    1042         pszName = g_apCpumDbEntries[0]->pszName; /* Just pick the first entry for non-x86 hosts. */
    1043 #endif
    1044     {
    1045         /*
    1046          * We're supposed to be emulating a specific CPU that is included in
    1047          * our CPU database.  The CPUID tables needs to be copied onto the
    1048          * heap so the caller can modify them and so they can be freed like
    1049          * in the host case above.
    1050          */
    1051         for (unsigned i = 0; i < RT_ELEMENTS(g_apCpumDbEntries); i++)
    1052             if (!strcmp(pszName, g_apCpumDbEntries[i]->pszName))
    1053             {
    1054                 pEntry = g_apCpumDbEntries[i];
    1055                 break;
    1056             }
    1057         if (!pEntry)
    1058         {
    1059             LogRel(("CPUM: Cannot locate any CPU by the name '%s'\n", pszName));
    1060             return VERR_CPUM_DB_CPU_NOT_FOUND;
    1061         }
    1062 
    1063         pInfo->cCpuIdLeaves = pEntry->cCpuIdLeaves;
    1064         if (pEntry->cCpuIdLeaves)
    1065         {
    1066             /* Must allocate a multiple of 16 here, matching cpumR3CpuIdEnsureSpace. */
    1067             size_t cbExtra = sizeof(pEntry->paCpuIdLeaves[0]) * (RT_ALIGN(pEntry->cCpuIdLeaves, 16) - pEntry->cCpuIdLeaves);
    1068             pInfo->paCpuIdLeavesR3 = (PCPUMCPUIDLEAF)RTMemDupEx(pEntry->paCpuIdLeaves,
    1069                                                                 sizeof(pEntry->paCpuIdLeaves[0]) * pEntry->cCpuIdLeaves,
    1070                                                                 cbExtra);
    1071             if (!pInfo->paCpuIdLeavesR3)
    1072                 return VERR_NO_MEMORY;
    1073         }
    1074         else
    1075             pInfo->paCpuIdLeavesR3 = NULL;
    1076 
    1077         pInfo->enmUnknownCpuIdMethod = pEntry->enmUnknownCpuId;
    1078         pInfo->DefCpuId              = pEntry->DefUnknownCpuId;
    1079         pInfo->fMxCsrMask            = pEntry->fMxCsrMask;
    1080 
    1081         LogRel(("CPUM: Using CPU DB entry '%s' (%s %#x/%#x/%#x %s)\n",
    1082                 pEntry->pszName, CPUMCpuVendorName((CPUMCPUVENDOR)pEntry->enmVendor),
    1083                 pEntry->uFamily, pEntry->uModel, pEntry->uStepping, CPUMMicroarchName(pEntry->enmMicroarch) ));
    1084     }
    1085 
    1086     pInfo->fMsrMask             = pEntry->fMsrMask;
    1087     pInfo->iFirstExtCpuIdLeaf   = 0; /* Set by caller. */
    1088     pInfo->uScalableBusFreq     = pEntry->uScalableBusFreq;
    1089 
    1090     /*
    1091      * Copy the MSR range.
    1092      */
    1093     uint32_t        cMsrs   = 0;
    1094     PCPUMMSRRANGE   paMsrs  = NULL;
    1095 
    1096     PCCPUMMSRRANGE  pCurMsr = pEntry->paMsrRanges;
    1097     uint32_t        cLeft   = pEntry->cMsrRanges;
    1098     while (cLeft-- > 0)
    1099     {
    1100         rc = cpumR3MsrRangesInsert(NULL /* pVM */, &paMsrs, &cMsrs, pCurMsr);
    1101         if (RT_FAILURE(rc))
    1102         {
    1103             Assert(!paMsrs); /* The above function frees this. */
    1104             RTMemFree(pInfo->paCpuIdLeavesR3);
    1105             pInfo->paCpuIdLeavesR3 = NULL;
    1106             return rc;
    1107         }
    1108         pCurMsr++;
    1109     }
    1110 
    1111     pInfo->paMsrRangesR3   = paMsrs;
    1112     pInfo->cMsrRanges      = cMsrs;
    1113     return VINF_SUCCESS;
    1114 }
    1115 
    1116535
    1117536/**
     
    1165584
    1166585
    1167 # ifdef VBOX_WITH_STATISTICS
     586#ifdef VBOX_WITH_STATISTICS
    1168587    /*
    1169588     * Per range.
     
    1195614        STAMR3Register(pVM, &paRanges[i].cIgnoredBits, STAMTYPE_COUNTER, STAMVISIBILITY_USED, szName, STAMUNIT_OCCURENCES, "WRMSR w/ ignored bits");
    1196615    }
    1197 # endif /* VBOX_WITH_STATISTICS */
     616#endif /* VBOX_WITH_STATISTICS */
    1198617
    1199618    return VINF_SUCCESS;
    1200619}
    1201620
    1202 #endif /* !CPUM_DB_STANDALONE */
    1203 
  • trunk/src/VBox/VMM/VMMR3/CPUMR3Msr-x86.h

    • Property svn:mergeinfo set to (toggle deleted branches)
      /branches/VBox-3.0/src/VBox/VMM/VMMR3/CPUMR3Db.cpp58652,​70973
      /branches/VBox-3.2/src/VBox/VMM/VMMR3/CPUMR3Db.cpp66309,​66318
      /branches/VBox-4.0/src/VBox/VMM/VMMR3/CPUMR3Db.cpp70873
      /branches/VBox-4.1/src/VBox/VMM/VMMR3/CPUMR3Db.cpp74233,​78414,​78691,​81841,​82127,​85941,​85944-85947,​85949-85950,​85953,​86701,​86728,​87009
      /branches/VBox-4.2/src/VBox/VMM/VMMR3/CPUMR3Db.cpp86229-86230,​86234,​86529,​91503-91504,​91506-91508,​91510,​91514-91515,​91521,​108112,​108114,​108127
      /branches/VBox-4.3/src/VBox/VMM/VMMR3/CPUMR3Db.cpp89714,​91223,​93628-93629,​94066,​94839,​94897,​95154,​95164,​95167,​95295,​95338,​95353-95354,​95356,​95367,​95451,​95475,​95477,​95480,​95507,​95640,​95659,​95661,​95663,​98913-98914
      /branches/VBox-4.3/trunk/src/VBox/VMM/VMMR3/CPUMR3Db.cpp91223
      /branches/VBox-5.0/src/VBox/VMM/VMMR3/CPUMR3Db.cpp104938,​104943,​104950,​104987-104988,​104990,​106453
      /branches/VBox-5.1/src/VBox/VMM/VMMR3/CPUMR3Db.cpp112367,​116543,​116550,​116568,​116573
      /branches/VBox-5.2/src/VBox/VMM/VMMR3/CPUMR3Db.cpp119536,​120083,​120099,​120213,​120221,​120239,​123597-123598,​123600-123601,​123755,​124263,​124273,​124277-124279,​124284-124286,​124288-124290,​125768,​125779-125780,​125812,​127158-127159,​127162-127167,​127180
      /branches/VBox-6.0/src/VBox/VMM/VMMR3/CPUMR3Db.cpp130474-130475,​130477,​130479,​131352
      /branches/VBox-6.1/src/VBox/VMM/VMMR3/CPUMR3Db.cpp141521,​141567-141568,​141588-141590,​141592-141595,​141652,​141920,​158257-158259
      /branches/VBox-7.0/src/VBox/VMM/VMMR3/CPUMR3Db.cpp156229,​156768
      /branches/aeichner/vbox-chromium-cleanup/src/VBox/VMM/VMMR3/CPUMR3Db.cpp129818-129851,​129853-129861,​129871-129872,​129876,​129880,​129882,​130013-130015,​130094-130095
      /branches/andy/draganddrop/src/VBox/VMM/VMMR3/CPUMR3Db.cpp90781-91268
      /branches/andy/guestctrl20/src/VBox/VMM/VMMR3/CPUMR3Db.cpp78916,​78930
      /branches/andy/pdmaudio/src/VBox/VMM/VMMR3/CPUMR3Db.cpp94582,​94641,​94654,​94688,​94778,​94783,​94816,​95197,​95215-95216,​95250,​95279,​95505-95506,​95543,​95694,​96323,​96470-96471,​96582,​96587,​96802-96803,​96817,​96904,​96967,​96999,​97020-97021,​97025,​97050,​97099
      /branches/bird/hardenedwindows/src/VBox/VMM/VMMR3/CPUMR3Db.cpp92692-94610
      /branches/dsen/gui/src/VBox/VMM/VMMR3/CPUMR3Db.cpp79076-79078,​79089,​79109-79110,​79112-79113,​79127-79130,​79134,​79141,​79151,​79155,​79157-79159,​79193,​79197
      /branches/dsen/gui2/src/VBox/VMM/VMMR3/CPUMR3Db.cpp79224,​79228,​79233,​79235,​79258,​79262-79263,​79273,​79341,​79345,​79354,​79357,​79387-79388,​79559-79569,​79572-79573,​79578,​79581-79582,​79590-79591,​79598-79599,​79602-79603,​79605-79606,​79632,​79635,​79637,​79644
      /branches/dsen/gui3/src/VBox/VMM/VMMR3/CPUMR3Db.cpp79645-79692
      /branches/dsen/gui4/src/VBox/VMM/VMMR3/CPUMR3Db.cpp155183-155185,​155187,​155198,​155200-155201,​155205,​155228,​155235,​155243,​155248,​155282,​155285,​155287-155288,​155311,​155316,​155336,​155342,​155344,​155437-155438,​155441,​155443,​155488,​155509-155513,​155526-155527,​155559,​155572,​155576-155577,​155592-155593
    r108997 r109008  
    11/* $Id$ */
    22/** @file
    3  * CPUM - CPU database part.
     3 * CPUM - x86 MSR macros.
    44 */
    55
     
    2727
    2828
    29 /*********************************************************************************************************************************
    30 *   Header Files                                                                                                                 *
    31 *********************************************************************************************************************************/
    32 #define LOG_GROUP LOG_GROUP_CPUM
    33 #include <VBox/vmm/cpum.h>
    34 #include "CPUMInternal.h"
    35 #include <VBox/vmm/vm.h>
    36 #include <VBox/vmm/mm.h>
    37 
    38 #include <VBox/err.h>
    39 #if !defined(RT_ARCH_ARM64)
    40 # include <iprt/asm-amd64-x86.h>
     29#ifndef VMM_INCLUDED_SRC_VMMR3_CPUMR3Msr_x86_h
     30#define VMM_INCLUDED_SRC_VMMR3_CPUMR3Msr_x86_h
     31#ifndef RT_WITHOUT_PRAGMA_ONCE
     32# pragma once
    4133#endif
    42 #include <iprt/mem.h>
    43 #include <iprt/string.h>
    44 
    45 
    46 /*********************************************************************************************************************************
    47 *   Defined Constants And Macros                                                                                                 *
    48 *********************************************************************************************************************************/
    49 /** @def NULL_ALONE
    50  * For eliminating an unnecessary data dependency in standalone builds (for
    51  * VBoxSVC). */
    52 /** @def ZERO_ALONE
    53  * For eliminating an unnecessary data size dependency in standalone builds (for
    54  * VBoxSVC). */
    55 #ifndef CPUM_DB_STANDALONE
    56 # define NULL_ALONE(a_aTable)    a_aTable
    57 # define ZERO_ALONE(a_cTable)    a_cTable
    58 #else
    59 # define NULL_ALONE(a_aTable)    NULL
    60 # define ZERO_ALONE(a_cTable)    0
    61 #endif
    62 
    6334
    6435/** @name Short macros for the MSR range entries.
     
    142113/** @} */
    143114
    144 #ifndef CPUM_DB_STANDALONE
    145 
    146 #include "cpus/Intel_Core_i7_6700K.h"
    147 #include "cpus/Intel_Core_i7_5600U.h"
    148 #include "cpus/Intel_Core_i7_3960X.h"
    149 #include "cpus/Intel_Core_i5_3570.h"
    150 #include "cpus/Intel_Core_i7_2635QM.h"
    151 #include "cpus/Intel_Xeon_X5482_3_20GHz.h"
    152 #include "cpus/Intel_Core2_X6800_2_93GHz.h"
    153 #include "cpus/Intel_Core2_T7600_2_33GHz.h"
    154 #include "cpus/Intel_Core_Duo_T2600_2_16GHz.h"
    155 #include "cpus/Intel_Pentium_M_processor_2_00GHz.h"
    156 #include "cpus/Intel_Pentium_4_3_00GHz.h"
    157 #include "cpus/Intel_Pentium_N3530_2_16GHz.h"
    158 #include "cpus/Intel_Atom_330_1_60GHz.h"
    159 #include "cpus/Intel_80486.h"
    160 #include "cpus/Intel_80386.h"
    161 #include "cpus/Intel_80286.h"
    162 #include "cpus/Intel_80186.h"
    163 #include "cpus/Intel_8086.h"
    164 
    165 #include "cpus/AMD_Ryzen_7_1800X_Eight_Core.h"
    166 #include "cpus/AMD_FX_8150_Eight_Core.h"
    167 #include "cpus/AMD_Phenom_II_X6_1100T.h"
    168 #include "cpus/Quad_Core_AMD_Opteron_2384.h"
    169 #include "cpus/AMD_Athlon_64_X2_Dual_Core_4200.h"
    170 #include "cpus/AMD_Athlon_64_3200.h"
    171 
    172 #include "cpus/VIA_QuadCore_L4700_1_2_GHz.h"
    173 
    174 #include "cpus/ZHAOXIN_KaiXian_KX_U5581_1_8GHz.h"
    175 
    176 #include "cpus/Hygon_C86_7185_32_core.h"
    177 
    178 
    179 /**
    180  * The database entries.
    181  *
    182  * 1. The first entry is special.  It is the fallback for unknown
    183  *    processors.  Thus, it better be pretty representative.
    184  *
    185  * 2. The first entry for a CPU vendor is likewise important as it is
    186  *    the default entry for that vendor.
    187  *
    188  * Generally we put the most recent CPUs first, since these tend to have the
    189  * most complicated and backwards compatible list of MSRs.
    190  */
    191 static CPUMDBENTRY const * const g_apCpumDbEntries[] =
    192 {
    193 #ifdef VBOX_CPUDB_Intel_Core_i7_6700K_h
    194     &g_Entry_Intel_Core_i7_6700K,
    195 #endif
    196 #ifdef VBOX_CPUDB_Intel_Core_i7_5600U_h
    197     &g_Entry_Intel_Core_i7_5600U,
    198 #endif
    199 #ifdef VBOX_CPUDB_Intel_Core_i5_3570_h
    200     &g_Entry_Intel_Core_i5_3570,
    201 #endif
    202 #ifdef VBOX_CPUDB_Intel_Core_i7_3960X_h
    203     &g_Entry_Intel_Core_i7_3960X,
    204 #endif
    205 #ifdef VBOX_CPUDB_Intel_Core_i7_2635QM_h
    206     &g_Entry_Intel_Core_i7_2635QM,
    207 #endif
    208 #ifdef VBOX_CPUDB_Intel_Pentium_N3530_2_16GHz_h
    209     &g_Entry_Intel_Pentium_N3530_2_16GHz,
    210 #endif
    211 #ifdef VBOX_CPUDB_Intel_Atom_330_1_60GHz_h
    212     &g_Entry_Intel_Atom_330_1_60GHz,
    213 #endif
    214 #ifdef VBOX_CPUDB_Intel_Pentium_M_processor_2_00GHz_h
    215     &g_Entry_Intel_Pentium_M_processor_2_00GHz,
    216 #endif
    217 #ifdef VBOX_CPUDB_Intel_Xeon_X5482_3_20GHz_h
    218     &g_Entry_Intel_Xeon_X5482_3_20GHz,
    219 #endif
    220 #ifdef VBOX_CPUDB_Intel_Core2_X6800_2_93GHz_h
    221     &g_Entry_Intel_Core2_X6800_2_93GHz,
    222 #endif
    223 #ifdef VBOX_CPUDB_Intel_Core2_T7600_2_33GHz_h
    224     &g_Entry_Intel_Core2_T7600_2_33GHz,
    225 #endif
    226 #ifdef VBOX_CPUDB_Intel_Core_Duo_T2600_2_16GHz_h
    227     &g_Entry_Intel_Core_Duo_T2600_2_16GHz,
    228 #endif
    229 #ifdef VBOX_CPUDB_Intel_Pentium_4_3_00GHz_h
    230     &g_Entry_Intel_Pentium_4_3_00GHz,
    231 #endif
    232 /** @todo pentium, pentium mmx, pentium pro, pentium II, pentium III */
    233 #ifdef VBOX_CPUDB_Intel_80486_h
    234     &g_Entry_Intel_80486,
    235 #endif
    236 #ifdef VBOX_CPUDB_Intel_80386_h
    237     &g_Entry_Intel_80386,
    238 #endif
    239 #ifdef VBOX_CPUDB_Intel_80286_h
    240     &g_Entry_Intel_80286,
    241 #endif
    242 #ifdef VBOX_CPUDB_Intel_80186_h
    243     &g_Entry_Intel_80186,
    244 #endif
    245 #ifdef VBOX_CPUDB_Intel_8086_h
    246     &g_Entry_Intel_8086,
    247 #endif
    248 
    249 #ifdef VBOX_CPUDB_AMD_Ryzen_7_1800X_Eight_Core_h
    250     &g_Entry_AMD_Ryzen_7_1800X_Eight_Core,
    251 #endif
    252 #ifdef VBOX_CPUDB_AMD_FX_8150_Eight_Core_h
    253     &g_Entry_AMD_FX_8150_Eight_Core,
    254 #endif
    255 #ifdef VBOX_CPUDB_AMD_Phenom_II_X6_1100T_h
    256     &g_Entry_AMD_Phenom_II_X6_1100T,
    257 #endif
    258 #ifdef VBOX_CPUDB_Quad_Core_AMD_Opteron_2384_h
    259     &g_Entry_Quad_Core_AMD_Opteron_2384,
    260 #endif
    261 #ifdef VBOX_CPUDB_AMD_Athlon_64_X2_Dual_Core_4200_h
    262     &g_Entry_AMD_Athlon_64_X2_Dual_Core_4200,
    263 #endif
    264 #ifdef VBOX_CPUDB_AMD_Athlon_64_3200_h
    265     &g_Entry_AMD_Athlon_64_3200,
    266 #endif
    267 
    268 #ifdef VBOX_CPUDB_ZHAOXIN_KaiXian_KX_U5581_1_8GHz_h
    269     &g_Entry_ZHAOXIN_KaiXian_KX_U5581_1_8GHz,
    270 #endif
    271 
    272 #ifdef VBOX_CPUDB_VIA_QuadCore_L4700_1_2_GHz_h
    273     &g_Entry_VIA_QuadCore_L4700_1_2_GHz,
    274 #endif
    275 
    276 #ifdef VBOX_CPUDB_NEC_V20_h
    277     &g_Entry_NEC_V20,
    278 #endif
    279 
    280 #ifdef VBOX_CPUDB_Hygon_C86_7185_32_core_h
    281     &g_Entry_Hygon_C86_7185_32_core,
    282 #endif
    283 };
    284 
    285 
    286 /**
    287  * Returns the number of entries in the CPU database.
    288  *
    289  * @returns Number of entries.
    290  * @sa      PFNCPUMDBGETENTRIES
    291  */
    292 VMMR3DECL(uint32_t)         CPUMR3DbGetEntries(void)
    293 {
    294     return RT_ELEMENTS(g_apCpumDbEntries);
    295 }
    296 
    297 
    298 /**
    299  * Returns CPU database entry for the given index.
    300  *
    301  * @returns Pointer the CPU database entry, NULL if index is out of bounds.
    302  * @param   idxCpuDb            The index (0..CPUMR3DbGetEntries).
    303  * @sa      PFNCPUMDBGETENTRYBYINDEX
    304  */
    305 VMMR3DECL(PCCPUMDBENTRY)    CPUMR3DbGetEntryByIndex(uint32_t idxCpuDb)
    306 {
    307     AssertReturn(idxCpuDb < RT_ELEMENTS(g_apCpumDbEntries), NULL);
    308     return g_apCpumDbEntries[idxCpuDb];
    309 }
    310 
    311 
    312 /**
    313  * Returns CPU database entry with the given name.
    314  *
    315  * @returns Pointer the CPU database entry, NULL if not found.
    316  * @param   pszName             The name of the profile to return.
    317  * @sa      PFNCPUMDBGETENTRYBYNAME
    318  */
    319 VMMR3DECL(PCCPUMDBENTRY)    CPUMR3DbGetEntryByName(const char *pszName)
    320 {
    321     AssertPtrReturn(pszName, NULL);
    322     AssertReturn(*pszName, NULL);
    323     for (size_t i = 0; i < RT_ELEMENTS(g_apCpumDbEntries); i++)
    324         if (strcmp(g_apCpumDbEntries[i]->pszName, pszName) == 0)
    325             return g_apCpumDbEntries[i];
    326     return NULL;
    327 }
    328 
    329 
    330 
    331 /**
    332  * Binary search used by cpumR3MsrRangesInsert and has some special properties
    333  * wrt to mismatches.
    334  *
    335  * @returns Insert location.
    336  * @param   paMsrRanges         The MSR ranges to search.
    337  * @param   cMsrRanges          The number of MSR ranges.
    338  * @param   uMsr                What to search for.
    339  */
    340 static uint32_t cpumR3MsrRangesBinSearch(PCCPUMMSRRANGE paMsrRanges, uint32_t cMsrRanges, uint32_t uMsr)
    341 {
    342     if (!cMsrRanges)
    343         return 0;
    344 
    345     uint32_t iStart = 0;
    346     uint32_t iLast  = cMsrRanges - 1;
    347     for (;;)
    348     {
    349         uint32_t i = iStart + (iLast - iStart + 1) / 2;
    350         if (   uMsr >= paMsrRanges[i].uFirst
    351             && uMsr <= paMsrRanges[i].uLast)
    352             return i;
    353         if (uMsr < paMsrRanges[i].uFirst)
    354         {
    355             if (i <= iStart)
    356                 return i;
    357             iLast = i - 1;
    358         }
    359         else
    360         {
    361             if (i >= iLast)
    362             {
    363                 if (i < cMsrRanges)
    364                     i++;
    365                 return i;
    366             }
    367             iStart = i + 1;
    368         }
    369     }
    370 }
    371 
    372 
    373 /**
    374  * Ensures that there is space for at least @a cNewRanges in the table,
    375  * reallocating the table if necessary.
    376  *
    377  * @returns Pointer to the MSR ranges on success, NULL on failure.  On failure
    378  *          @a *ppaMsrRanges is freed and set to NULL.
    379  * @param   pVM             The cross context VM structure.  If NULL,
    380  *                          use the process heap, otherwise the VM's hyper heap.
    381  * @param   ppaMsrRanges    The variable pointing to the ranges (input/output).
    382  * @param   cMsrRanges      The current number of ranges.
    383  * @param   cNewRanges      The number of ranges to be added.
    384  */
    385 static PCPUMMSRRANGE cpumR3MsrRangesEnsureSpace(PVM pVM, PCPUMMSRRANGE *ppaMsrRanges, uint32_t cMsrRanges, uint32_t cNewRanges)
    386 {
    387     if (  cMsrRanges + cNewRanges
    388         > RT_ELEMENTS(pVM->cpum.s.GuestInfo.aMsrRanges) + (pVM ? 0 : 128 /* Catch too many MSRs in CPU reporter! */))
    389     {
    390         LogRel(("CPUM: Too many MSR ranges! %#x, max %#x\n",
    391                 cMsrRanges + cNewRanges, RT_ELEMENTS(pVM->cpum.s.GuestInfo.aMsrRanges)));
    392         return NULL;
    393     }
    394     if (pVM)
    395     {
    396         Assert(cMsrRanges == pVM->cpum.s.GuestInfo.cMsrRanges);
    397         Assert(*ppaMsrRanges == pVM->cpum.s.GuestInfo.aMsrRanges);
    398     }
    399     else
    400     {
    401         if (cMsrRanges + cNewRanges > RT_ALIGN_32(cMsrRanges, 16))
    402         {
    403 
    404             uint32_t const cNew = RT_ALIGN_32(cMsrRanges + cNewRanges, 16);
    405             void *pvNew = RTMemRealloc(*ppaMsrRanges, cNew * sizeof(**ppaMsrRanges));
    406             if (pvNew)
    407                 *ppaMsrRanges = (PCPUMMSRRANGE)pvNew;
    408             else
    409             {
    410                 RTMemFree(*ppaMsrRanges);
    411                 *ppaMsrRanges = NULL;
    412                 return NULL;
    413             }
    414         }
    415     }
    416 
    417     return *ppaMsrRanges;
    418 }
    419 
    420 
    421 /**
    422  * Inserts a new MSR range in into an sorted MSR range array.
    423  *
    424  * If the new MSR range overlaps existing ranges, the existing ones will be
    425  * adjusted/removed to fit in the new one.
    426  *
    427  * @returns VBox status code.
    428  * @retval  VINF_SUCCESS
    429  * @retval  VERR_NO_MEMORY
    430  *
    431  * @param   pVM             The cross context VM structure.  If NULL,
    432  *                          use the process heap, otherwise the VM's hyper heap.
    433  * @param   ppaMsrRanges    The variable pointing to the ranges (input/output).
    434  *                          Must be NULL if using the hyper heap.
    435  * @param   pcMsrRanges     The variable holding number of ranges. Must be NULL
    436  *                          if using the hyper heap.
    437  * @param   pNewRange       The new range.
    438  */
    439 int cpumR3MsrRangesInsert(PVM pVM, PCPUMMSRRANGE *ppaMsrRanges, uint32_t *pcMsrRanges, PCCPUMMSRRANGE pNewRange)
    440 {
    441     Assert(pNewRange->uLast >= pNewRange->uFirst);
    442     Assert(pNewRange->enmRdFn > kCpumMsrRdFn_Invalid && pNewRange->enmRdFn < kCpumMsrRdFn_End);
    443     Assert(pNewRange->enmWrFn > kCpumMsrWrFn_Invalid && pNewRange->enmWrFn < kCpumMsrWrFn_End);
    444 
    445     /*
    446      * Validate and use the VM's MSR ranges array if we are using the hyper heap.
    447      */
    448     if (pVM)
    449     {
    450         AssertReturn(!ppaMsrRanges, VERR_INVALID_PARAMETER);
    451         AssertReturn(!pcMsrRanges,  VERR_INVALID_PARAMETER);
    452         AssertReturn(pVM->cpum.s.GuestInfo.paMsrRangesR3 == pVM->cpum.s.GuestInfo.aMsrRanges, VERR_INTERNAL_ERROR_3);
    453 
    454         ppaMsrRanges = &pVM->cpum.s.GuestInfo.paMsrRangesR3;
    455         pcMsrRanges  = &pVM->cpum.s.GuestInfo.cMsrRanges;
    456     }
    457     else
    458     {
    459         AssertReturn(ppaMsrRanges, VERR_INVALID_POINTER);
    460         AssertReturn(pcMsrRanges, VERR_INVALID_POINTER);
    461     }
    462 
    463     uint32_t        cMsrRanges  = *pcMsrRanges;
    464     PCPUMMSRRANGE   paMsrRanges = *ppaMsrRanges;
    465 
    466     /*
    467      * Optimize the linear insertion case where we add new entries at the end.
    468      */
    469     if (   cMsrRanges > 0
    470         && paMsrRanges[cMsrRanges - 1].uLast < pNewRange->uFirst)
    471     {
    472         paMsrRanges = cpumR3MsrRangesEnsureSpace(pVM, ppaMsrRanges, cMsrRanges, 1);
    473         if (!paMsrRanges)
    474             return VERR_NO_MEMORY;
    475         paMsrRanges[cMsrRanges] = *pNewRange;
    476         *pcMsrRanges += 1;
    477     }
    478     else
    479     {
    480         uint32_t i = cpumR3MsrRangesBinSearch(paMsrRanges, cMsrRanges, pNewRange->uFirst);
    481         Assert(i == cMsrRanges || pNewRange->uFirst <= paMsrRanges[i].uLast);
    482         Assert(i == 0 || pNewRange->uFirst > paMsrRanges[i - 1].uLast);
    483 
    484         /*
    485          * Adding an entirely new entry?
    486          */
    487         if (   i >= cMsrRanges
    488             || pNewRange->uLast < paMsrRanges[i].uFirst)
    489         {
    490             paMsrRanges = cpumR3MsrRangesEnsureSpace(pVM, ppaMsrRanges, cMsrRanges, 1);
    491             if (!paMsrRanges)
    492                 return VERR_NO_MEMORY;
    493             if (i < cMsrRanges)
    494                 memmove(&paMsrRanges[i + 1], &paMsrRanges[i], (cMsrRanges - i) * sizeof(paMsrRanges[0]));
    495             paMsrRanges[i] = *pNewRange;
    496             *pcMsrRanges += 1;
    497         }
    498         /*
    499          * Replace existing entry?
    500          */
    501         else if (   pNewRange->uFirst == paMsrRanges[i].uFirst
    502                  && pNewRange->uLast  == paMsrRanges[i].uLast)
    503             paMsrRanges[i] = *pNewRange;
    504         /*
    505          * Splitting an existing entry?
    506          */
    507         else if (   pNewRange->uFirst > paMsrRanges[i].uFirst
    508                  && pNewRange->uLast  < paMsrRanges[i].uLast)
    509         {
    510             paMsrRanges = cpumR3MsrRangesEnsureSpace(pVM, ppaMsrRanges, cMsrRanges, 2);
    511             if (!paMsrRanges)
    512                 return VERR_NO_MEMORY;
    513             Assert(i < cMsrRanges);
    514             memmove(&paMsrRanges[i + 2], &paMsrRanges[i], (cMsrRanges - i) * sizeof(paMsrRanges[0]));
    515             paMsrRanges[i + 1] = *pNewRange;
    516             paMsrRanges[i + 2] = paMsrRanges[i];
    517             paMsrRanges[i    ].uLast  = pNewRange->uFirst - 1;
    518             paMsrRanges[i + 2].uFirst = pNewRange->uLast  + 1;
    519             *pcMsrRanges += 2;
    520         }
    521         /*
    522          * Complicated scenarios that can affect more than one range.
    523          *
    524          * The current code does not optimize memmove calls when replacing
    525          * one or more existing ranges, because it's tedious to deal with and
    526          * not expected to be a frequent usage scenario.
    527          */
    528         else
    529         {
    530             /* Adjust start of first match? */
    531             if (   pNewRange->uFirst <= paMsrRanges[i].uFirst
    532                 && pNewRange->uLast  <  paMsrRanges[i].uLast)
    533                 paMsrRanges[i].uFirst = pNewRange->uLast + 1;
    534             else
    535             {
    536                 /* Adjust end of first match? */
    537                 if (pNewRange->uFirst > paMsrRanges[i].uFirst)
    538                 {
    539                     Assert(paMsrRanges[i].uLast >= pNewRange->uFirst);
    540                     paMsrRanges[i].uLast = pNewRange->uFirst - 1;
    541                     i++;
    542                 }
    543                 /* Replace the whole first match (lazy bird). */
    544                 else
    545                 {
    546                     if (i + 1 < cMsrRanges)
    547                         memmove(&paMsrRanges[i], &paMsrRanges[i + 1], (cMsrRanges - i - 1) * sizeof(paMsrRanges[0]));
    548                     cMsrRanges = *pcMsrRanges -= 1;
    549                 }
    550 
    551                 /* Do the new range affect more ranges? */
    552                 while (   i < cMsrRanges
    553                        && pNewRange->uLast >= paMsrRanges[i].uFirst)
    554                 {
    555                     if (pNewRange->uLast < paMsrRanges[i].uLast)
    556                     {
    557                         /* Adjust the start of it, then we're done. */
    558                         paMsrRanges[i].uFirst = pNewRange->uLast + 1;
    559                         break;
    560                     }
    561 
    562                     /* Remove it entirely. */
    563                     if (i + 1 < cMsrRanges)
    564                         memmove(&paMsrRanges[i], &paMsrRanges[i + 1], (cMsrRanges - i - 1) * sizeof(paMsrRanges[0]));
    565                     cMsrRanges = *pcMsrRanges -= 1;
    566                 }
    567             }
    568 
    569             /* Now, perform a normal insertion. */
    570             paMsrRanges = cpumR3MsrRangesEnsureSpace(pVM, ppaMsrRanges, cMsrRanges, 1);
    571             if (!paMsrRanges)
    572                 return VERR_NO_MEMORY;
    573             if (i < cMsrRanges)
    574                 memmove(&paMsrRanges[i + 1], &paMsrRanges[i], (cMsrRanges - i) * sizeof(paMsrRanges[0]));
    575             paMsrRanges[i] = *pNewRange;
    576             *pcMsrRanges += 1;
    577         }
    578     }
    579 
    580     return VINF_SUCCESS;
    581 }
    582 
    583 
    584 /**
    585  * Reconciles CPUID info with MSRs (selected ones).
    586  *
    587  * @returns VBox status code.
    588  * @param   pVM                 The cross context VM structure.
    589  * @param   fForceFlushCmd      Make sure MSR_IA32_FLUSH_CMD is present.
    590  * @param   fForceSpecCtrl      Make sure MSR_IA32_SPEC_CTRL is present.
    591  */
    592 DECLHIDDEN(int) cpumR3MsrReconcileWithCpuId(PVM pVM, bool fForceFlushCmd, bool fForceSpecCtrl)
    593 {
    594     PCCPUMMSRRANGE apToAdd[10];
    595     uint32_t       cToAdd = 0;
    596 
    597     /*
    598      * The IA32_FLUSH_CMD MSR was introduced in MCUs for CVS-2018-3646 and associates.
    599      */
    600     if (   pVM->cpum.s.GuestFeatures.fFlushCmd
    601         || fForceFlushCmd)
    602     {
    603         static CPUMMSRRANGE const s_FlushCmd =
    604         {
    605             /*.uFirst =*/       MSR_IA32_FLUSH_CMD,
    606             /*.uLast =*/        MSR_IA32_FLUSH_CMD,
    607             /*.enmRdFn =*/      kCpumMsrRdFn_WriteOnly,
    608             /*.enmWrFn =*/      kCpumMsrWrFn_Ia32FlushCmd,
    609             /*.offCpumCpu =*/   UINT16_MAX,
    610             /*.fReserved =*/    0,
    611             /*.uValue =*/       0,
    612             /*.fWrIgnMask =*/   0,
    613             /*.fWrGpMask =*/    ~MSR_IA32_FLUSH_CMD_F_L1D,
    614             /*.szName = */      "IA32_FLUSH_CMD"
    615         };
    616         apToAdd[cToAdd++] = &s_FlushCmd;
    617     }
    618 
    619     /*
    620      * The IA32_PRED_CMD MSR was introduced in MCUs for CVS-2018-3646 and associates.
    621      */
    622     if (   pVM->cpum.s.GuestFeatures.fIbpb
    623         /** @todo || pVM->cpum.s.GuestFeatures.fSbpb*/)
    624     {
    625         static CPUMMSRRANGE const s_PredCmd =
    626         {
    627             /*.uFirst =*/       MSR_IA32_PRED_CMD,
    628             /*.uLast =*/        MSR_IA32_PRED_CMD,
    629             /*.enmRdFn =*/      kCpumMsrRdFn_WriteOnly,
    630             /*.enmWrFn =*/      kCpumMsrWrFn_Ia32PredCmd,
    631             /*.offCpumCpu =*/   UINT16_MAX,
    632             /*.fReserved =*/    0,
    633             /*.uValue =*/       0,
    634             /*.fWrIgnMask =*/   0,
    635             /*.fWrGpMask =*/    ~MSR_IA32_PRED_CMD_F_IBPB,
    636             /*.szName = */      "IA32_PRED_CMD"
    637         };
    638         apToAdd[cToAdd++] = &s_PredCmd;
    639     }
    640 
    641     /*
    642      * The IA32_SPEC_CTRL MSR was introduced in MCUs for CVS-2018-3646 and associates.
    643      */
    644     if (   pVM->cpum.s.GuestFeatures.fSpecCtrlMsr
    645         || fForceSpecCtrl)
    646     {
    647         static CPUMMSRRANGE const s_SpecCtrl =
    648         {
    649             /*.uFirst =*/       MSR_IA32_SPEC_CTRL,
    650             /*.uLast =*/        MSR_IA32_SPEC_CTRL,
    651             /*.enmRdFn =*/      kCpumMsrRdFn_Ia32SpecCtrl,
    652             /*.enmWrFn =*/      kCpumMsrWrFn_Ia32SpecCtrl,
    653             /*.offCpumCpu =*/   UINT16_MAX,
    654             /*.fReserved =*/    0,
    655             /*.uValue =*/       0,
    656             /*.fWrIgnMask =*/   0,
    657             /*.fWrGpMask =*/    0,
    658             /*.szName = */      "IA32_SPEC_CTRL"
    659         };
    660         apToAdd[cToAdd++] = &s_SpecCtrl;
    661     }
    662 
    663     /*
    664      * The MSR_IA32_ARCH_CAPABILITIES was introduced in various spectre MCUs, or at least
    665      * documented in relation to such.
    666      */
    667     if (pVM->cpum.s.GuestFeatures.fArchCap)
    668     {
    669         static CPUMMSRRANGE const s_ArchCaps =
    670         {
    671             /*.uFirst =*/       MSR_IA32_ARCH_CAPABILITIES,
    672             /*.uLast =*/        MSR_IA32_ARCH_CAPABILITIES,
    673             /*.enmRdFn =*/      kCpumMsrRdFn_Ia32ArchCapabilities,
    674             /*.enmWrFn =*/      kCpumMsrWrFn_ReadOnly,
    675             /*.offCpumCpu =*/   UINT16_MAX,
    676             /*.fReserved =*/    0,
    677             /*.uValue =*/       0,
    678             /*.fWrIgnMask =*/   0,
    679             /*.fWrGpMask =*/    UINT64_MAX,
    680             /*.szName = */      "IA32_ARCH_CAPABILITIES"
    681         };
    682         apToAdd[cToAdd++] = &s_ArchCaps;
    683     }
    684 
    685     /*
    686      * Do the adding.
    687      */
    688     Assert(cToAdd <= RT_ELEMENTS(apToAdd));
    689     for (uint32_t i = 0; i < cToAdd; i++)
    690     {
    691         PCCPUMMSRRANGE pRange = apToAdd[i];
    692         Assert(pRange->uFirst == pRange->uLast);
    693         if (!cpumLookupMsrRange(pVM, pRange->uFirst))
    694         {
    695             LogRel(("CPUM: MSR/CPUID reconciliation insert: %#010x %s\n", pRange->uFirst, pRange->szName));
    696             int rc = cpumR3MsrRangesInsert(NULL /* pVM */, &pVM->cpum.s.GuestInfo.paMsrRangesR3,
    697                                            &pVM->cpum.s.GuestInfo.cMsrRanges, pRange);
    698             AssertRCReturn(rc, rc);
    699         }
    700     }
    701     return VINF_SUCCESS;
    702 }
    703 
    704 
    705 /**
    706  * Worker for cpumR3MsrApplyFudge that applies one table.
    707  *
    708  * @returns VBox status code.
    709  * @param   pVM                 The cross context VM structure.
    710  * @param   paRanges            Array of MSRs to fudge.
    711  * @param   cRanges             Number of MSRs in the array.
    712  */
    713 static int cpumR3MsrApplyFudgeTable(PVM pVM, PCCPUMMSRRANGE paRanges, size_t cRanges)
    714 {
    715     for (uint32_t i = 0; i < cRanges; i++)
    716         if (!cpumLookupMsrRange(pVM, paRanges[i].uFirst))
    717         {
    718             LogRel(("CPUM: MSR fudge: %#010x %s\n", paRanges[i].uFirst, paRanges[i].szName));
    719             int rc = cpumR3MsrRangesInsert(NULL /* pVM */, &pVM->cpum.s.GuestInfo.paMsrRangesR3, &pVM->cpum.s.GuestInfo.cMsrRanges,
    720                                            &paRanges[i]);
    721             if (RT_FAILURE(rc))
    722                 return rc;
    723         }
    724     return VINF_SUCCESS;
    725 }
    726 
    727 
    728 /**
    729  * Fudges the MSRs that guest are known to access in some odd cases.
    730  *
    731  * A typical example is a VM that has been moved between different hosts where
    732  * for instance the cpu vendor differs.
    733  *
    734  * Another example is older CPU profiles (e.g. Atom Bonnet) for newer CPUs (e.g.
    735  * Atom Silvermont), where features reported thru CPUID aren't present in the
    736  * MSRs (e.g. AMD64_TSC_AUX).
    737  *
    738  *
    739  * @returns VBox status code.
    740  * @param   pVM                 The cross context VM structure.
    741  */
    742 int cpumR3MsrApplyFudge(PVM pVM)
    743 {
    744     /*
    745      * Basic.
    746      */
    747     static CPUMMSRRANGE const s_aFudgeMsrs[] =
    748     {
    749         MFO(0x00000000, "IA32_P5_MC_ADDR",          Ia32P5McAddr),
    750         MFX(0x00000001, "IA32_P5_MC_TYPE",          Ia32P5McType,   Ia32P5McType,   0, 0, UINT64_MAX),
    751         MVO(0x00000017, "IA32_PLATFORM_ID",         0),
    752         MFN(0x0000001b, "IA32_APIC_BASE",           Ia32ApicBase,   Ia32ApicBase),
    753         MVI(0x0000008b, "BIOS_SIGN",                0),
    754         MFX(0x000000fe, "IA32_MTRRCAP",             Ia32MtrrCap,    ReadOnly,       0x508, 0, 0),
    755         MFX(0x00000179, "IA32_MCG_CAP",             Ia32McgCap,     ReadOnly,       0x005, 0, 0),
    756         MFX(0x0000017a, "IA32_MCG_STATUS",          Ia32McgStatus,  Ia32McgStatus,  0, ~(uint64_t)UINT32_MAX, 0),
    757         MFN(0x000001a0, "IA32_MISC_ENABLE",         Ia32MiscEnable, Ia32MiscEnable),
    758         MFN(0x000001d9, "IA32_DEBUGCTL",            Ia32DebugCtl,   Ia32DebugCtl),
    759         MFO(0x000001db, "P6_LAST_BRANCH_FROM_IP",   P6LastBranchFromIp),
    760         MFO(0x000001dc, "P6_LAST_BRANCH_TO_IP",     P6LastBranchToIp),
    761         MFO(0x000001dd, "P6_LAST_INT_FROM_IP",      P6LastIntFromIp),
    762         MFO(0x000001de, "P6_LAST_INT_TO_IP",        P6LastIntToIp),
    763         MFS(0x00000277, "IA32_PAT",                 Ia32Pat, Ia32Pat, Guest.msrPAT),
    764         MFZ(0x000002ff, "IA32_MTRR_DEF_TYPE",       Ia32MtrrDefType, Ia32MtrrDefType, GuestMsrs.msr.MtrrDefType, 0, ~(uint64_t)0xc07),
    765         MFN(0x00000400, "IA32_MCi_CTL_STATUS_ADDR_MISC", Ia32McCtlStatusAddrMiscN, Ia32McCtlStatusAddrMiscN),
    766     };
    767     int rc = cpumR3MsrApplyFudgeTable(pVM, &s_aFudgeMsrs[0], RT_ELEMENTS(s_aFudgeMsrs));
    768     AssertLogRelRCReturn(rc, rc);
    769 
    770     /*
    771      * XP might mistake opterons and other newer CPUs for P4s.
    772      */
    773     if (pVM->cpum.s.GuestFeatures.uFamily >= 0xf)
    774     {
    775         static CPUMMSRRANGE const s_aP4FudgeMsrs[] =
    776         {
    777             MFX(0x0000002c, "P4_EBC_FREQUENCY_ID", IntelP4EbcFrequencyId, IntelP4EbcFrequencyId, 0xf12010f, UINT64_MAX, 0),
    778         };
    779         rc = cpumR3MsrApplyFudgeTable(pVM, &s_aP4FudgeMsrs[0], RT_ELEMENTS(s_aP4FudgeMsrs));
    780         AssertLogRelRCReturn(rc, rc);
    781     }
    782 
    783     if (pVM->cpum.s.GuestFeatures.fRdTscP)
    784     {
    785         static CPUMMSRRANGE const s_aRdTscPFudgeMsrs[] =
    786         {
    787             MFX(0xc0000103, "AMD64_TSC_AUX", Amd64TscAux, Amd64TscAux, 0, 0, ~(uint64_t)UINT32_MAX),
    788         };
    789         rc = cpumR3MsrApplyFudgeTable(pVM, &s_aRdTscPFudgeMsrs[0], RT_ELEMENTS(s_aRdTscPFudgeMsrs));
    790         AssertLogRelRCReturn(rc, rc);
    791     }
    792 
    793     /*
    794      * Windows 10 incorrectly writes to MSR_IA32_TSX_CTRL without checking
    795      * CPUID.ARCH_CAP(EAX=7h,ECX=0):EDX[bit 29] or the MSR feature bits in
    796      * MSR_IA32_ARCH_CAPABILITIES[bit 7], see @bugref{9630}.
    797      * Ignore writes to this MSR and return 0 on reads.
    798      *
    799      * Windows 11 24H2 incorrectly reads MSR_IA32_MCU_OPT_CTRL without
    800      * checking CPUID.ARCH_CAP(EAX=7h,ECX=0).EDX[bit 9] or the MSR feature
    801      * bits in MSR_IA32_ARCH_CAPABILITIES[bit 18], see @bugref{10794}.
    802      * Ignore wrties to this MSR and return 0 on reads.
    803      */
    804     if (pVM->cpum.s.GuestFeatures.fArchCap)
    805     {
    806         static CPUMMSRRANGE const s_aTsxCtrl[] =
    807         {
    808             MVI(MSR_IA32_TSX_CTRL, "IA32_TSX_CTRL", 0),
    809             MVI(MSR_IA32_MCU_OPT_CTRL, "IA32_MCU_OPT_CTRL", 0),
    810         };
    811         rc = cpumR3MsrApplyFudgeTable(pVM, &s_aTsxCtrl[0], RT_ELEMENTS(s_aTsxCtrl));
    812         AssertLogRelRCReturn(rc, rc);
    813     }
    814 
    815     return rc;
    816 }
    817 
    818 #if defined(RT_ARCH_X86) || defined(RT_ARCH_AMD64)
    819 
    820 /**
    821  * Do we consider @a enmConsider a better match for @a enmTarget than
    822  * @a enmFound?
    823  *
    824  * Only called when @a enmConsider isn't exactly what we're looking for.
    825  *
    826  * @returns true/false.
    827  * @param   enmConsider         The new microarch to consider.
    828  * @param   enmTarget           The target microarch.
    829  * @param   enmFound            The best microarch match we've found thus far.
    830  */
    831 DECLINLINE(bool) cpumR3DbIsBetterMarchMatch(CPUMMICROARCH enmConsider, CPUMMICROARCH enmTarget, CPUMMICROARCH enmFound)
    832 {
    833     Assert(enmConsider != enmTarget);
    834 
    835     /*
    836      * If we've got an march match, don't bother with enmConsider.
    837      */
    838     if (enmFound == enmTarget)
    839         return false;
    840 
    841     /*
    842      * Found is below: Pick 'consider' if it's closer to the target or above it.
    843      */
    844     if (enmFound < enmTarget)
    845         return enmConsider > enmFound;
    846 
    847     /*
    848      * Found is above: Pick 'consider' if it's also above (paranoia: or equal)
    849      *                 and but closer to the target.
    850      */
    851     return enmConsider >= enmTarget && enmConsider < enmFound;
    852 }
    853 
    854 
    855 /**
    856  * Do we consider @a enmConsider a better match for @a enmTarget than
    857  * @a enmFound?
    858  *
    859  * Only called for intel family 06h CPUs.
    860  *
    861  * @returns true/false.
    862  * @param   enmConsider         The new microarch to consider.
    863  * @param   enmTarget           The target microarch.
    864  * @param   enmFound            The best microarch match we've found thus far.
    865  */
    866 static bool cpumR3DbIsBetterIntelFam06Match(CPUMMICROARCH enmConsider, CPUMMICROARCH enmTarget, CPUMMICROARCH enmFound)
    867 {
    868     /* Check intel family 06h claims. */
    869     AssertReturn(enmConsider >= kCpumMicroarch_Intel_P6_Core_Atom_First && enmConsider <= kCpumMicroarch_Intel_P6_Core_Atom_End,
    870                  false);
    871     AssertReturn(   (enmTarget >= kCpumMicroarch_Intel_P6_Core_Atom_First && enmTarget <= kCpumMicroarch_Intel_P6_Core_Atom_End)
    872                  || enmTarget == kCpumMicroarch_Intel_Unknown,
    873                  false);
    874 
    875     /* Put matches out of the way. */
    876     if (enmConsider == enmTarget)
    877         return true;
    878     if (enmFound == enmTarget)
    879         return false;
    880 
    881     /* If found isn't a family 06h march, whatever we're considering must be a better choice. */
    882     if (   enmFound < kCpumMicroarch_Intel_P6_Core_Atom_First
    883         || enmFound > kCpumMicroarch_Intel_P6_Core_Atom_End)
    884         return true;
    885 
    886     /*
    887      * The family 06h stuff is split into three categories:
    888      *      - Common P6 heritage
    889      *      - Core
    890      *      - Atom
    891      *
    892      * Determin which of the three arguments are Atom marchs, because that's
    893      * all we need to make the right choice.
    894      */
    895     bool const fConsiderAtom = enmConsider >= kCpumMicroarch_Intel_Atom_First;
    896     bool const fTargetAtom   = enmTarget   >= kCpumMicroarch_Intel_Atom_First;
    897     bool const fFoundAtom    = enmFound    >= kCpumMicroarch_Intel_Atom_First;
    898 
    899     /*
    900      * Want atom:
    901      */
    902     if (fTargetAtom)
    903     {
    904         /* Pick the atom if we've got one of each.*/
    905         if (fConsiderAtom != fFoundAtom)
    906             return fConsiderAtom;
    907         /* If we haven't got any atoms under consideration, pick a P6 or the earlier core.
    908            Note! Not entirely sure Dothan is the best choice, but it'll do for now. */
    909         if (!fConsiderAtom)
    910         {
    911             if (enmConsider > enmFound)
    912                 return enmConsider <= kCpumMicroarch_Intel_P6_M_Dothan;
    913             return enmFound > kCpumMicroarch_Intel_P6_M_Dothan;
    914         }
    915         /* else: same category, default comparison rules. */
    916         Assert(fConsiderAtom && fFoundAtom);
    917     }
    918     /*
    919      * Want non-atom:
    920      */
    921     /* Pick the non-atom if we've got one of each. */
    922     else if (fConsiderAtom != fFoundAtom)
    923         return fFoundAtom;
    924     /* If we've only got atoms under consideration, pick the older one just to pick something. */
    925     else if (fConsiderAtom)
    926         return enmConsider < enmFound;
    927     else
    928         Assert(!fConsiderAtom && !fFoundAtom);
    929 
    930     /*
    931      * Same basic category.  Do same compare as caller.
    932      */
    933     return cpumR3DbIsBetterMarchMatch(enmConsider, enmTarget, enmFound);
    934 }
    935 
    936 #endif /* RT_ARCH_X86 || RT_ARCH_AMD64 */
    937 
    938 int cpumR3DbGetCpuInfo(const char *pszName, PCPUMINFO pInfo)
    939 {
    940     CPUMDBENTRY const *pEntry = NULL;
    941     int                rc;
    942 
    943     if (!strcmp(pszName, "host"))
    944 #if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
    945     {
    946         /*
    947          * Create a CPU database entry for the host CPU.  This means getting
    948          * the CPUID bits from the real CPU and grabbing the closest matching
    949          * database entry for MSRs.
    950          */
    951         rc = CPUMR3CpuIdDetectUnknownLeafMethod(&pInfo->enmUnknownCpuIdMethod, &pInfo->DefCpuId);
    952         if (RT_FAILURE(rc))
    953             return rc;
    954         rc = CPUMCpuIdCollectLeavesFromX86Host(&pInfo->paCpuIdLeavesR3, &pInfo->cCpuIdLeaves);
    955         if (RT_FAILURE(rc))
    956             return rc;
    957         pInfo->fMxCsrMask = CPUMR3DeterminHostMxCsrMask();
    958 
    959         /* Lookup database entry for MSRs. */
    960         CPUMCPUVENDOR const enmVendor    = CPUMCpuIdDetectX86VendorEx(pInfo->paCpuIdLeavesR3[0].uEax,
    961                                                                       pInfo->paCpuIdLeavesR3[0].uEbx,
    962                                                                       pInfo->paCpuIdLeavesR3[0].uEcx,
    963                                                                       pInfo->paCpuIdLeavesR3[0].uEdx);
    964         uint32_t      const uStd1Eax     = pInfo->paCpuIdLeavesR3[1].uEax;
    965         uint8_t       const uFamily      = RTX86GetCpuFamily(uStd1Eax);
    966         uint8_t       const uModel       = RTX86GetCpuModel(uStd1Eax, enmVendor == CPUMCPUVENDOR_INTEL);
    967         uint8_t       const uStepping    = RTX86GetCpuStepping(uStd1Eax);
    968         CPUMMICROARCH const enmMicroarch = CPUMCpuIdDetermineX86MicroarchEx(enmVendor, uFamily, uModel, uStepping);
    969 
    970         for (unsigned i = 0; i < RT_ELEMENTS(g_apCpumDbEntries); i++)
    971         {
    972             CPUMDBENTRY const *pCur = g_apCpumDbEntries[i];
    973             if ((CPUMCPUVENDOR)pCur->enmVendor == enmVendor)
    974             {
    975                 /* Match against Family, Microarch, model and stepping.  Except
    976                    for family, always match the closer with preference given to
    977                    the later/older ones. */
    978                 if (pCur->uFamily == uFamily)
    979                 {
    980                     if (pCur->enmMicroarch == enmMicroarch)
    981                     {
    982                         if (pCur->uModel == uModel)
    983                         {
    984                             if (pCur->uStepping == uStepping)
    985                             {
    986                                 /* Perfect match. */
    987                                 pEntry = pCur;
    988                                 break;
    989                             }
    990 
    991                             if (   !pEntry
    992                                 || pEntry->uModel       != uModel
    993                                 || pEntry->enmMicroarch != enmMicroarch
    994                                 || pEntry->uFamily      != uFamily)
    995                                 pEntry = pCur;
    996                             else if (  pCur->uStepping >= uStepping
    997                                      ? pCur->uStepping < pEntry->uStepping || pEntry->uStepping < uStepping
    998                                      : pCur->uStepping > pEntry->uStepping)
    999                                      pEntry = pCur;
    1000                         }
    1001                         else if (   !pEntry
    1002                                  || pEntry->enmMicroarch != enmMicroarch
    1003                                  || pEntry->uFamily      != uFamily)
    1004                             pEntry = pCur;
    1005                         else if (  pCur->uModel >= uModel
    1006                                  ? pCur->uModel < pEntry->uModel || pEntry->uModel < uModel
    1007                                  : pCur->uModel > pEntry->uModel)
    1008                             pEntry = pCur;
    1009                     }
    1010                     else if (   !pEntry
    1011                              || pEntry->uFamily != uFamily)
    1012                         pEntry = pCur;
    1013                     /* Special march matching rules applies to intel family 06h. */
    1014                     else if (     enmVendor == CPUMCPUVENDOR_INTEL
    1015                                && uFamily   == 6
    1016                              ? cpumR3DbIsBetterIntelFam06Match(pCur->enmMicroarch, enmMicroarch, pEntry->enmMicroarch)
    1017                              : cpumR3DbIsBetterMarchMatch(pCur->enmMicroarch, enmMicroarch, pEntry->enmMicroarch))
    1018                         pEntry = pCur;
    1019                 }
    1020                 /* We don't do closeness matching on family, we use the first
    1021                    entry for the CPU vendor instead. (P4 workaround.) */
    1022                 else if (!pEntry)
    1023                     pEntry = pCur;
    1024             }
    1025         }
    1026 
    1027         if (pEntry)
    1028             LogRel(("CPUM: Matched host CPU %s %#x/%#x/%#x %s with CPU DB entry '%s' (%s %#x/%#x/%#x %s)\n",
    1029                     CPUMCpuVendorName(enmVendor), uFamily, uModel, uStepping, CPUMMicroarchName(enmMicroarch),
    1030                     pEntry->pszName,  CPUMCpuVendorName((CPUMCPUVENDOR)pEntry->enmVendor), pEntry->uFamily, pEntry->uModel,
    1031                     pEntry->uStepping, CPUMMicroarchName(pEntry->enmMicroarch) ));
    1032         else
    1033         {
    1034             pEntry = g_apCpumDbEntries[0];
    1035             LogRel(("CPUM: No matching processor database entry %s %#x/%#x/%#x %s, falling back on '%s'\n",
    1036                     CPUMCpuVendorName(enmVendor), uFamily, uModel, uStepping, CPUMMicroarchName(enmMicroarch),
    1037                     pEntry->pszName));
    1038         }
    1039     }
    1040     else
    1041 #else
    1042         pszName = g_apCpumDbEntries[0]->pszName; /* Just pick the first entry for non-x86 hosts. */
    1043 #endif
    1044     {
    1045         /*
    1046          * We're supposed to be emulating a specific CPU that is included in
    1047          * our CPU database.  The CPUID tables needs to be copied onto the
    1048          * heap so the caller can modify them and so they can be freed like
    1049          * in the host case above.
    1050          */
    1051         for (unsigned i = 0; i < RT_ELEMENTS(g_apCpumDbEntries); i++)
    1052             if (!strcmp(pszName, g_apCpumDbEntries[i]->pszName))
    1053             {
    1054                 pEntry = g_apCpumDbEntries[i];
    1055                 break;
    1056             }
    1057         if (!pEntry)
    1058         {
    1059             LogRel(("CPUM: Cannot locate any CPU by the name '%s'\n", pszName));
    1060             return VERR_CPUM_DB_CPU_NOT_FOUND;
    1061         }
    1062 
    1063         pInfo->cCpuIdLeaves = pEntry->cCpuIdLeaves;
    1064         if (pEntry->cCpuIdLeaves)
    1065         {
    1066             /* Must allocate a multiple of 16 here, matching cpumR3CpuIdEnsureSpace. */
    1067             size_t cbExtra = sizeof(pEntry->paCpuIdLeaves[0]) * (RT_ALIGN(pEntry->cCpuIdLeaves, 16) - pEntry->cCpuIdLeaves);
    1068             pInfo->paCpuIdLeavesR3 = (PCPUMCPUIDLEAF)RTMemDupEx(pEntry->paCpuIdLeaves,
    1069                                                                 sizeof(pEntry->paCpuIdLeaves[0]) * pEntry->cCpuIdLeaves,
    1070                                                                 cbExtra);
    1071             if (!pInfo->paCpuIdLeavesR3)
    1072                 return VERR_NO_MEMORY;
    1073         }
    1074         else
    1075             pInfo->paCpuIdLeavesR3 = NULL;
    1076 
    1077         pInfo->enmUnknownCpuIdMethod = pEntry->enmUnknownCpuId;
    1078         pInfo->DefCpuId              = pEntry->DefUnknownCpuId;
    1079         pInfo->fMxCsrMask            = pEntry->fMxCsrMask;
    1080 
    1081         LogRel(("CPUM: Using CPU DB entry '%s' (%s %#x/%#x/%#x %s)\n",
    1082                 pEntry->pszName, CPUMCpuVendorName((CPUMCPUVENDOR)pEntry->enmVendor),
    1083                 pEntry->uFamily, pEntry->uModel, pEntry->uStepping, CPUMMicroarchName(pEntry->enmMicroarch) ));
    1084     }
    1085 
    1086     pInfo->fMsrMask             = pEntry->fMsrMask;
    1087     pInfo->iFirstExtCpuIdLeaf   = 0; /* Set by caller. */
    1088     pInfo->uScalableBusFreq     = pEntry->uScalableBusFreq;
    1089 
    1090     /*
    1091      * Copy the MSR range.
    1092      */
    1093     uint32_t        cMsrs   = 0;
    1094     PCPUMMSRRANGE   paMsrs  = NULL;
    1095 
    1096     PCCPUMMSRRANGE  pCurMsr = pEntry->paMsrRanges;
    1097     uint32_t        cLeft   = pEntry->cMsrRanges;
    1098     while (cLeft-- > 0)
    1099     {
    1100         rc = cpumR3MsrRangesInsert(NULL /* pVM */, &paMsrs, &cMsrs, pCurMsr);
    1101         if (RT_FAILURE(rc))
    1102         {
    1103             Assert(!paMsrs); /* The above function frees this. */
    1104             RTMemFree(pInfo->paCpuIdLeavesR3);
    1105             pInfo->paCpuIdLeavesR3 = NULL;
    1106             return rc;
    1107         }
    1108         pCurMsr++;
    1109     }
    1110 
    1111     pInfo->paMsrRangesR3   = paMsrs;
    1112     pInfo->cMsrRanges      = cMsrs;
    1113     return VINF_SUCCESS;
    1114 }
    1115 
    1116 
    1117 /**
    1118  * Insert an MSR range into the VM.
    1119  *
    1120  * If the new MSR range overlaps existing ranges, the existing ones will be
    1121  * adjusted/removed to fit in the new one.
    1122  *
    1123  * @returns VBox status code.
    1124  * @param   pVM                 The cross context VM structure.
    1125  * @param   pNewRange           Pointer to the MSR range being inserted.
    1126  */
    1127 VMMR3DECL(int) CPUMR3MsrRangesInsert(PVM pVM, PCCPUMMSRRANGE pNewRange)
    1128 {
    1129     AssertReturn(pVM, VERR_INVALID_PARAMETER);
    1130     AssertReturn(pNewRange, VERR_INVALID_PARAMETER);
    1131 
    1132     return cpumR3MsrRangesInsert(pVM, NULL /* ppaMsrRanges */, NULL /* pcMsrRanges */, pNewRange);
    1133 }
    1134 
    1135 
    1136 /**
    1137  * Register statistics for the MSRs.
    1138  *
    1139  * This must not be called before the MSRs have been finalized and moved to the
    1140  * hyper heap.
    1141  *
    1142  * @returns VBox status code.
    1143  * @param   pVM                 The cross context VM structure.
    1144  */
    1145 int cpumR3MsrRegStats(PVM pVM)
    1146 {
    1147     /*
    1148      * Global statistics.
    1149      */
    1150     PCPUM pCpum = &pVM->cpum.s;
    1151     STAM_REL_REG(pVM, &pCpum->cMsrReads,                STAMTYPE_COUNTER,   "/CPUM/MSR-Totals/Reads",
    1152                  STAMUNIT_OCCURENCES, "All RDMSRs making it to CPUM.");
    1153     STAM_REL_REG(pVM, &pCpum->cMsrReadsRaiseGp,         STAMTYPE_COUNTER,   "/CPUM/MSR-Totals/ReadsRaisingGP",
    1154                  STAMUNIT_OCCURENCES, "RDMSR raising #GPs, except unknown MSRs.");
    1155     STAM_REL_REG(pVM, &pCpum->cMsrReadsUnknown,         STAMTYPE_COUNTER,   "/CPUM/MSR-Totals/ReadsUnknown",
    1156                  STAMUNIT_OCCURENCES, "RDMSR on unknown MSRs (raises #GP).");
    1157     STAM_REL_REG(pVM, &pCpum->cMsrWrites,               STAMTYPE_COUNTER,   "/CPUM/MSR-Totals/Writes",
    1158                  STAMUNIT_OCCURENCES, "All WRMSRs making it to CPUM.");
    1159     STAM_REL_REG(pVM, &pCpum->cMsrWritesRaiseGp,        STAMTYPE_COUNTER,   "/CPUM/MSR-Totals/WritesRaisingGP",
    1160                  STAMUNIT_OCCURENCES, "WRMSR raising #GPs, except unknown MSRs.");
    1161     STAM_REL_REG(pVM, &pCpum->cMsrWritesToIgnoredBits,  STAMTYPE_COUNTER,   "/CPUM/MSR-Totals/WritesToIgnoredBits",
    1162                  STAMUNIT_OCCURENCES, "Writing of ignored bits.");
    1163     STAM_REL_REG(pVM, &pCpum->cMsrWritesUnknown,        STAMTYPE_COUNTER,   "/CPUM/MSR-Totals/WritesUnknown",
    1164                  STAMUNIT_OCCURENCES, "WRMSR on unknown MSRs (raises #GP).");
    1165 
    1166 
    1167 # ifdef VBOX_WITH_STATISTICS
    1168     /*
    1169      * Per range.
    1170      */
    1171     PCPUMMSRRANGE   paRanges = pVM->cpum.s.GuestInfo.paMsrRangesR3;
    1172     uint32_t        cRanges  = pVM->cpum.s.GuestInfo.cMsrRanges;
    1173     for (uint32_t i = 0; i < cRanges; i++)
    1174     {
    1175         char    szName[160];
    1176         ssize_t cchName;
    1177 
    1178         if (paRanges[i].uFirst == paRanges[i].uLast)
    1179             cchName = RTStrPrintf(szName, sizeof(szName), "/CPUM/MSRs/%#010x-%s",
    1180                                   paRanges[i].uFirst, paRanges[i].szName);
    1181         else
    1182             cchName = RTStrPrintf(szName, sizeof(szName), "/CPUM/MSRs/%#010x-%#010x-%s",
    1183                                   paRanges[i].uFirst, paRanges[i].uLast, paRanges[i].szName);
    1184 
    1185         RTStrCopy(&szName[cchName], sizeof(szName) - cchName, "-reads");
    1186         STAMR3Register(pVM, &paRanges[i].cReads, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, szName, STAMUNIT_OCCURENCES, "RDMSR");
    1187 
    1188         RTStrCopy(&szName[cchName], sizeof(szName) - cchName, "-writes");
    1189         STAMR3Register(pVM, &paRanges[i].cWrites, STAMTYPE_COUNTER, STAMVISIBILITY_USED, szName, STAMUNIT_OCCURENCES, "WRMSR");
    1190 
    1191         RTStrCopy(&szName[cchName], sizeof(szName) - cchName, "-GPs");
    1192         STAMR3Register(pVM, &paRanges[i].cGps, STAMTYPE_COUNTER, STAMVISIBILITY_USED, szName, STAMUNIT_OCCURENCES, "#GPs");
    1193 
    1194         RTStrCopy(&szName[cchName], sizeof(szName) - cchName, "-ign-bits-writes");
    1195         STAMR3Register(pVM, &paRanges[i].cIgnoredBits, STAMTYPE_COUNTER, STAMVISIBILITY_USED, szName, STAMUNIT_OCCURENCES, "WRMSR w/ ignored bits");
    1196     }
    1197 # endif /* VBOX_WITH_STATISTICS */
    1198 
    1199     return VINF_SUCCESS;
    1200 }
    1201 
    1202 #endif /* !CPUM_DB_STANDALONE */
    1203 
     115#endif /* !VMM_INCLUDED_SRC_VMMR3_CPUMR3Msr_x86_h */
  • trunk/src/VBox/VMM/VMMR3/CPUMR3SysReg-armv8.cpp

    r109007 r109008  
    11/* $Id$ */
    22/** @file
    3  * CPUM - CPU database part - ARMv8 specifics.
     3 * CPUM - ARMv8 System Registers Management.
    44 */
    55
    66/*
    7  * Copyright (C) 2023-2024 Oracle and/or its affiliates.
     7 * Copyright (C) 2023-2025 Oracle and/or its affiliates.
    88 *
    99 * This file is part of VirtualBox base platform packages, as
     
    3434#include "CPUMInternal-armv8.h"
    3535#include <VBox/vmm/vm.h>
    36 #include <VBox/vmm/mm.h>
    3736
    3837#include <iprt/errcore.h>
     
    4039#include <iprt/mem.h>
    4140#include <iprt/string.h>
    42 
    43 
    44 /*********************************************************************************************************************************
    45 *   Defined Constants And Macros                                                                                                 *
    46 *********************************************************************************************************************************/
    47 /** @def NULL_ALONE
    48  * For eliminating an unnecessary data dependency in standalone builds (for
    49  * VBoxSVC). */
    50 /** @def ZERO_ALONE
    51  * For eliminating an unnecessary data size dependency in standalone builds (for
    52  * VBoxSVC). */
    53 #ifndef CPUM_DB_STANDALONE
    54 # define NULL_ALONE(a_aTable)    a_aTable
    55 # define ZERO_ALONE(a_cTable)    a_cTable
    56 #else
    57 # define NULL_ALONE(a_aTable)    NULL
    58 # define ZERO_ALONE(a_cTable)    0
    59 #endif
    60 
    61 
    62 #ifndef CPUM_DB_STANDALONE
    63 
    64 /**
    65  * The database entries.
    66  *
    67  * 1. The first entry is special.  It is the fallback for unknown
    68  *    processors.  Thus, it better be pretty representative.
    69  *
    70  * 2. The first entry for a CPU vendor is likewise important as it is
    71  *    the default entry for that vendor.
    72  *
    73  * Generally we put the most recent CPUs first, since these tend to have the
    74  * most complicated and backwards compatible list of MSRs.
    75  */
    76 static CPUMDBENTRY const * const g_apCpumDbEntries[] =
    77 {
    78     NULL
    79 };
    80 
    81 
    82 /**
    83  * Returns the number of entries in the CPU database.
    84  *
    85  * @returns Number of entries.
    86  * @sa      PFNCPUMDBGETENTRIES
    87  */
    88 VMMR3DECL(uint32_t)         CPUMR3DbGetEntries(void)
    89 {
    90     return RT_ELEMENTS(g_apCpumDbEntries);
    91 }
    92 
    93 
    94 /**
    95  * Returns CPU database entry for the given index.
    96  *
    97  * @returns Pointer the CPU database entry, NULL if index is out of bounds.
    98  * @param   idxCpuDb            The index (0..CPUMR3DbGetEntries).
    99  * @sa      PFNCPUMDBGETENTRYBYINDEX
    100  */
    101 VMMR3DECL(PCCPUMDBENTRY)    CPUMR3DbGetEntryByIndex(uint32_t idxCpuDb)
    102 {
    103     AssertReturn(idxCpuDb < RT_ELEMENTS(g_apCpumDbEntries), NULL);
    104     return g_apCpumDbEntries[idxCpuDb];
    105 }
    106 
    107 
    108 /**
    109  * Returns CPU database entry with the given name.
    110  *
    111  * @returns Pointer the CPU database entry, NULL if not found.
    112  * @param   pszName             The name of the profile to return.
    113  * @sa      PFNCPUMDBGETENTRYBYNAME
    114  */
    115 VMMR3DECL(PCCPUMDBENTRY)    CPUMR3DbGetEntryByName(const char *pszName)
    116 {
    117     AssertPtrReturn(pszName, NULL);
    118     AssertReturn(*pszName, NULL);
    119     for (size_t i = 0; i < RT_ELEMENTS(g_apCpumDbEntries); i++)
    120         if (strcmp(g_apCpumDbEntries[i]->pszName, pszName) == 0)
    121             return g_apCpumDbEntries[i];
    122     return NULL;
    123 }
    124 
    12541
    12642
     
    395311}
    396312
    397 #endif /* !CPUM_DB_STANDALONE */
    398 
  • trunk/src/VBox/VMM/VMMR3/cpus/AMD_Athlon_64_3200.h

    r106061 r109008  
    209209 * Database entry for AMD Athlon(tm) 64 Processor 3200+.
    210210 */
    211 static CPUMDBENTRY const g_Entry_AMD_Athlon_64_3200 =
     211static CPUMDBENTRYX86 const g_Entry_AMD_Athlon_64_3200 =
    212212{
    213     /*.pszName          = */ "AMD Athlon 64 3200+",
    214     /*.pszFullName      = */ "AMD Athlon(tm) 64 Processor 3200+",
    215     /*.enmVendor        = */ CPUMCPUVENDOR_AMD,
     213    {
     214        /*.pszName      = */ "AMD Athlon 64 3200+",
     215        /*.pszFullName  = */ "AMD Athlon(tm) 64 Processor 3200+",
     216        /*.enmVendor    = */ CPUMCPUVENDOR_AMD,
     217        /*.enmMicroarch = */ kCpumMicroarch_AMD_K8_130nm,
     218        /*.fFlags       = */ 0,
     219        /*.enmEntryType = */ CPUMDBENTRYTYPE_X86,
     220    },
    216221    /*.uFamily          = */ 15,
    217222    /*.uModel           = */ 4,
    218223    /*.uStepping        = */ 8,
    219     /*.enmMicroarch     = */ kCpumMicroarch_AMD_K8_130nm,
    220224    /*.uScalableBusFreq = */ CPUM_SBUSFREQ_UNKNOWN,
    221     /*.fFlags           = */ 0,
    222225    /*.cMaxPhysAddrWidth= */ 40,
    223226    /*.fMxCsrMask       = */ 0xffff, ///< @todo check.
  • trunk/src/VBox/VMM/VMMR3/cpus/AMD_Athlon_64_X2_Dual_Core_4200.h

    r106061 r109008  
    217217 * Database entry for AMD Athlon(tm) 64 X2 Dual Core Processor 4200+.
    218218 */
    219 static CPUMDBENTRY const g_Entry_AMD_Athlon_64_X2_Dual_Core_4200 =
     219static CPUMDBENTRYX86 const g_Entry_AMD_Athlon_64_X2_Dual_Core_4200 =
    220220{
    221     /*.pszName          = */ "AMD Athlon 64 X2 Dual Core 4200+",
    222     /*.pszFullName      = */ "AMD Athlon(tm) 64 X2 Dual Core Processor 4200+",
    223     /*.enmVendor        = */ CPUMCPUVENDOR_AMD,
     221    {
     222        /*.pszName      = */ "AMD Athlon 64 X2 Dual Core 4200+",
     223        /*.pszFullName  = */ "AMD Athlon(tm) 64 X2 Dual Core Processor 4200+",
     224        /*.enmVendor    = */ CPUMCPUVENDOR_AMD,
     225        /*.enmMicroarch = */ kCpumMicroarch_AMD_K8_90nm_AMDV,
     226        /*.fFlags       = */ 0,
     227        /*.enmEntryType = */ CPUMDBENTRYTYPE_X86,
     228    },
    224229    /*.uFamily          = */ 15,
    225230    /*.uModel           = */ 75,
    226231    /*.uStepping        = */ 2,
    227     /*.enmMicroarch     = */ kCpumMicroarch_AMD_K8_90nm_AMDV,
    228232    /*.uScalableBusFreq = */ CPUM_SBUSFREQ_UNKNOWN,
    229     /*.fFlags           = */ 0,
    230233    /*.cMaxPhysAddrWidth= */ 40,
    231234    /*.fMxCsrMask       = */ 0xffff,
  • trunk/src/VBox/VMM/VMMR3/cpus/AMD_FX_8150_Eight_Core.h

    r106061 r109008  
    368368 * Database entry for AMD FX(tm)-8150 Eight-Core Processor.
    369369 */
    370 static CPUMDBENTRY const g_Entry_AMD_FX_8150_Eight_Core =
     370static CPUMDBENTRYX86 const g_Entry_AMD_FX_8150_Eight_Core =
    371371{
    372     /*.pszName          = */ "AMD FX-8150 Eight-Core",
    373     /*.pszFullName      = */ "AMD FX(tm)-8150 Eight-Core Processor",
    374     /*.enmVendor        = */ CPUMCPUVENDOR_AMD,
     372    {
     373        /*.pszName      = */ "AMD FX-8150 Eight-Core",
     374        /*.pszFullName  = */ "AMD FX(tm)-8150 Eight-Core Processor",
     375        /*.enmVendor    = */ CPUMCPUVENDOR_AMD,
     376        /*.enmMicroarch = */ kCpumMicroarch_AMD_15h_Bulldozer,
     377        /*.fFlags       = */ 0,
     378        /*.enmEntryType = */ CPUMDBENTRYTYPE_X86,
     379    },
    375380    /*.uFamily          = */ 21,
    376381    /*.uModel           = */ 1,
    377382    /*.uStepping        = */ 2,
    378     /*.enmMicroarch     = */ kCpumMicroarch_AMD_15h_Bulldozer,
    379383    /*.uScalableBusFreq = */ CPUM_SBUSFREQ_UNKNOWN,
    380     /*.fFlags           = */ 0,
    381384    /*.cMaxPhysAddrWidth= */ 48,
    382385    /*.fMxCsrMask       = */ 0x2ffff,
  • trunk/src/VBox/VMM/VMMR3/cpus/AMD_Phenom_II_X6_1100T.h

    r106061 r109008  
    257257 * Database entry for AMD Phenom(tm) II X6 1100T Processor.
    258258 */
    259 static CPUMDBENTRY const g_Entry_AMD_Phenom_II_X6_1100T =
     259static CPUMDBENTRYX86 const g_Entry_AMD_Phenom_II_X6_1100T =
    260260{
    261     /*.pszName          = */ "AMD Phenom II X6 1100T",
    262     /*.pszFullName      = */ "AMD Phenom(tm) II X6 1100T Processor",
    263     /*.enmVendor        = */ CPUMCPUVENDOR_AMD,
     261    {
     262        /*.pszName      = */ "AMD Phenom II X6 1100T",
     263        /*.pszFullName  = */ "AMD Phenom(tm) II X6 1100T Processor",
     264        /*.enmVendor    = */ CPUMCPUVENDOR_AMD,
     265        /*.enmMicroarch = */ kCpumMicroarch_AMD_K10,
     266        /*.fFlags       = */ 0,
     267        /*.enmEntryType = */ CPUMDBENTRYTYPE_X86,
     268    },
    264269    /*.uFamily          = */ 16,
    265270    /*.uModel           = */ 10,
    266271    /*.uStepping        = */ 0,
    267     /*.enmMicroarch     = */ kCpumMicroarch_AMD_K10,
    268272    /*.uScalableBusFreq = */ CPUM_SBUSFREQ_UNKNOWN,
    269     /*.fFlags           = */ 0,
    270273    /*.cMaxPhysAddrWidth= */ 48,
    271274    /*.fMxCsrMask       = */ 0x2ffff,
  • trunk/src/VBox/VMM/VMMR3/cpus/AMD_Ryzen_7_1800X_Eight_Core.h

    r106061 r109008  
    52095209 * Database entry for AMD Ryzen 7 1800X Eight-Core Processor.
    52105210 */
    5211 static CPUMDBENTRY const g_Entry_AMD_Ryzen_7_1800X_Eight_Core =
     5211static CPUMDBENTRYX86 const g_Entry_AMD_Ryzen_7_1800X_Eight_Core =
    52125212{
    5213     /*.pszName          = */ "AMD Ryzen 7 1800X Eight-Core",
    5214     /*.pszFullName      = */ "AMD Ryzen 7 1800X Eight-Core Processor",
    5215     /*.enmVendor        = */ CPUMCPUVENDOR_AMD,
     5213    {
     5214        /*.pszName      = */ "AMD Ryzen 7 1800X Eight-Core",
     5215        /*.pszFullName  = */ "AMD Ryzen 7 1800X Eight-Core Processor",
     5216        /*.enmVendor    = */ CPUMCPUVENDOR_AMD,
     5217        /*.enmMicroarch = */ kCpumMicroarch_AMD_Zen_Ryzen,
     5218        /*.fFlags       = */ 0,
     5219        /*.enmEntryType = */ CPUMDBENTRYTYPE_X86,
     5220    },
    52165221    /*.uFamily          = */ 23,
    52175222    /*.uModel           = */ 1,
    52185223    /*.uStepping        = */ 1,
    5219     /*.enmMicroarch     = */ kCpumMicroarch_AMD_Zen_Ryzen,
    52205224    /*.uScalableBusFreq = */ CPUM_SBUSFREQ_UNKNOWN,
    5221     /*.fFlags           = */ 0,
    52225225    /*.cMaxPhysAddrWidth= */ 48,
    52235226    /*.fMxCsrMask       = */ 0x0002ffff,
  • trunk/src/VBox/VMM/VMMR3/cpus/Hygon_C86_7185_32_core.h

    r106061 r109008  
    52095209 * Database entry for Hygon C86 7185 32-core Processor.
    52105210 */
    5211 static CPUMDBENTRY const g_Entry_Hygon_C86_7185_32_core =
     5211static CPUMDBENTRYX86 const g_Entry_Hygon_C86_7185_32_core =
    52125212{
    5213     /*.pszName          = */ "Hygon C86 7185 32-core",
    5214     /*.pszFullName      = */ "Hygon C86 7185 32-core Processor",
    5215     /*.enmVendor        = */ CPUMCPUVENDOR_HYGON,
     5213    {
     5214        /*.pszName      = */ "Hygon C86 7185 32-core",
     5215        /*.pszFullName  = */ "Hygon C86 7185 32-core Processor",
     5216        /*.enmVendor    = */ CPUMCPUVENDOR_HYGON,
     5217        /*.enmMicroarch = */ kCpumMicroarch_Hygon_Dhyana,
     5218        /*.fFlags       = */ 0,
     5219        /*.enmEntryType = */ CPUMDBENTRYTYPE_X86,
     5220    },
    52165221    /*.uFamily          = */ 24,
    52175222    /*.uModel           = */ 0,
    52185223    /*.uStepping        = */ 1,
    5219     /*.enmMicroarch     = */ kCpumMicroarch_Hygon_Dhyana,
    52205224    /*.uScalableBusFreq = */ CPUM_SBUSFREQ_UNKNOWN,
    5221     /*.fFlags           = */ 0,
    52225225    /*.cMaxPhysAddrWidth= */ 48,
    52235226    /*.fMxCsrMask       = */ 0x0002ffff,
  • trunk/src/VBox/VMM/VMMR3/cpus/Intel_80186.h

    r106061 r109008  
    6060 * Database entry for Intel(R) 80186.
    6161 */
    62 static CPUMDBENTRY const g_Entry_Intel_80186 =
     62static CPUMDBENTRYX86 const g_Entry_Intel_80186 =
    6363{
    64     /*.pszName          = */ "Intel 80186",
    65     /*.pszFullName      = */ "Intel(R) 80186",
    66     /*.enmVendor        = */ CPUMCPUVENDOR_INTEL,
     64    {
     65        /*.pszName      = */ "Intel 80186",
     66        /*.pszFullName  = */ "Intel(R) 80186",
     67        /*.enmVendor    = */ CPUMCPUVENDOR_INTEL,
     68        /*.enmMicroarch = */ kCpumMicroarch_Intel_80186,
     69        /*.fFlags       = */ CPUMDB_F_EXECUTE_ALL_IN_IEM,
     70        /*.enmEntryType = */ CPUMDBENTRYTYPE_X86,
     71    },
    6772    /*.uFamily          = */ 2,
    6873    /*.uModel           = */ 0,
    6974    /*.uStepping        = */ 0,
    70     /*.enmMicroarch     = */ kCpumMicroarch_Intel_80186,
    7175    /*.uScalableBusFreq = */ CPUM_SBUSFREQ_UNKNOWN,
    72     /*.fFlags           = */ CPUMDB_F_EXECUTE_ALL_IN_IEM,
    7376    /*.cMaxPhysAddrWidth= */ 20,
    7477    /*.fMxCsrMask       = */ 0,
  • trunk/src/VBox/VMM/VMMR3/cpus/Intel_80286.h

    r106061 r109008  
    6060 * Database entry for Intel(R) 80286.
    6161 */
    62 static CPUMDBENTRY const g_Entry_Intel_80286 =
     62static CPUMDBENTRYX86 const g_Entry_Intel_80286 =
    6363{
    64     /*.pszName          = */ "Intel 80286",
    65     /*.pszFullName      = */ "Intel(R) 80286",
    66     /*.enmVendor        = */ CPUMCPUVENDOR_INTEL,
     64    {
     65        /*.pszName      = */ "Intel 80286",
     66        /*.pszFullName  = */ "Intel(R) 80286",
     67        /*.enmVendor    = */ CPUMCPUVENDOR_INTEL,
     68        /*.enmMicroarch = */ kCpumMicroarch_Intel_80286,
     69        /*.fFlags       = */ CPUMDB_F_EXECUTE_ALL_IN_IEM,
     70        /*.enmEntryType = */ CPUMDBENTRYTYPE_X86,
     71    },
    6772    /*.uFamily          = */ 2,
    6873    /*.uModel           = */ 0,
    6974    /*.uStepping        = */ 0,
    70     /*.enmMicroarch     = */ kCpumMicroarch_Intel_80286,
    7175    /*.uScalableBusFreq = */ CPUM_SBUSFREQ_UNKNOWN,
    72     /*.fFlags           = */ CPUMDB_F_EXECUTE_ALL_IN_IEM,
    7376    /*.cMaxPhysAddrWidth= */ 24,
    7477    /*.fMxCsrMask       = */ 0,
  • trunk/src/VBox/VMM/VMMR3/cpus/Intel_80386.h

    r106061 r109008  
    6060 * Database entry for Intel(R) 80386.
    6161 */
    62 static CPUMDBENTRY const g_Entry_Intel_80386 =
     62static CPUMDBENTRYX86 const g_Entry_Intel_80386 =
    6363{
    64     /*.pszName          = */ "Intel 80386",
    65     /*.pszFullName      = */ "Intel(R) 80386",
    66     /*.enmVendor        = */ CPUMCPUVENDOR_INTEL,
     64    {
     65        /*.pszName      = */ "Intel 80386",
     66        /*.pszFullName  = */ "Intel(R) 80386",
     67        /*.enmVendor    = */ CPUMCPUVENDOR_INTEL,
     68        /*.enmMicroarch = */ kCpumMicroarch_Intel_80386,
     69        /*.fFlags       = */ CPUMDB_F_EXECUTE_ALL_IN_IEM,
     70        /*.enmEntryType = */ CPUMDBENTRYTYPE_X86,
     71    },
    6772    /*.uFamily          = */ 3,
    6873    /*.uModel           = */ 0,
    6974    /*.uStepping        = */ 0,
    70     /*.enmMicroarch     = */ kCpumMicroarch_Intel_80386,
    7175    /*.uScalableBusFreq = */ CPUM_SBUSFREQ_UNKNOWN,
    72     /*.fFlags           = */ CPUMDB_F_EXECUTE_ALL_IN_IEM,
    7376    /*.cMaxPhysAddrWidth= */ 24,
    7477    /*.fMxCsrMask       = */ 0,
  • trunk/src/VBox/VMM/VMMR3/cpus/Intel_80486.h

    r106061 r109008  
    5858 * Database entry for Intel(R) 80486.
    5959 */
    60 static CPUMDBENTRY const g_Entry_Intel_80486 =
     60static CPUMDBENTRYX86 const g_Entry_Intel_80486 =
    6161{
    62     /*.pszName          = */ "Intel 80486",
    63     /*.pszFullName      = */ "Intel(R) 80486DX2",
    64     /*.enmVendor        = */ CPUMCPUVENDOR_INTEL,
     62    {
     63        /*.pszName      = */ "Intel 80486",
     64        /*.pszFullName  = */ "Intel(R) 80486DX2",
     65        /*.enmVendor    = */ CPUMCPUVENDOR_INTEL,
     66        /*.enmMicroarch = */ kCpumMicroarch_Intel_80486,
     67        /*.fFlags       = */ 0,
     68        /*.enmEntryType = */ CPUMDBENTRYTYPE_X86,
     69    },
    6570    /*.uFamily          = */ 4,
    6671    /*.uModel           = */ 3,
    6772    /*.uStepping        = */ 0,
    68     /*.enmMicroarch     = */ kCpumMicroarch_Intel_80486,
    6973    /*.uScalableBusFreq = */ CPUM_SBUSFREQ_UNKNOWN,
    70     /*.fFlags           = */ 0,
    7174    /*.cMaxPhysAddrWidth= */ 32,
    7275    /*.fMxCsrMask       = */ 0,
  • trunk/src/VBox/VMM/VMMR3/cpus/Intel_8086.h

    r106061 r109008  
    6060 * Database entry for Intel(R) 8086.
    6161 */
    62 static CPUMDBENTRY const g_Entry_Intel_8086 =
     62static CPUMDBENTRYX86 const g_Entry_Intel_8086 =
    6363{
    64     /*.pszName          = */ "Intel 8086",
    65     /*.pszFullName      = */ "Intel(R) 8086",
    66     /*.enmVendor        = */ CPUMCPUVENDOR_INTEL,
     64    {
     65        /*.pszName      = */ "Intel 8086",
     66        /*.pszFullName  = */ "Intel(R) 8086",
     67        /*.enmVendor    = */ CPUMCPUVENDOR_INTEL,
     68        /*.enmMicroarch = */ kCpumMicroarch_Intel_8086,
     69        /*.fFlags       = */ CPUMDB_F_EXECUTE_ALL_IN_IEM,
     70        /*.enmEntryType = */ CPUMDBENTRYTYPE_X86,
     71    },
    6772    /*.uFamily          = */ 2,
    6873    /*.uModel           = */ 0,
    6974    /*.uStepping        = */ 0,
    70     /*.enmMicroarch     = */ kCpumMicroarch_Intel_8086,
    7175    /*.uScalableBusFreq = */ CPUM_SBUSFREQ_UNKNOWN,
    72     /*.fFlags           = */ CPUMDB_F_EXECUTE_ALL_IN_IEM,
    7376    /*.cMaxPhysAddrWidth= */ 20,
    7477    /*.fMxCsrMask       = */ 0,
  • trunk/src/VBox/VMM/VMMR3/cpus/Intel_Atom_330_1_60GHz.h

    r106061 r109008  
    195195 * Database entry for Intel(R) Atom(TM) CPU  330   @ 1.60GHz.
    196196 */
    197 static CPUMDBENTRY const g_Entry_Intel_Atom_330_1_60GHz =
     197static CPUMDBENTRYX86 const g_Entry_Intel_Atom_330_1_60GHz =
    198198{
    199     /*.pszName          = */ "Intel Atom 330 1.60GHz",
    200     /*.pszFullName      = */ "Intel(R) Atom(TM) CPU  330   @ 1.60GHz",
    201     /*.enmVendor        = */ CPUMCPUVENDOR_INTEL,
     199    {
     200        /*.pszName      = */ "Intel Atom 330 1.60GHz",
     201        /*.pszFullName  = */ "Intel(R) Atom(TM) CPU  330   @ 1.60GHz",
     202        /*.enmVendor    = */ CPUMCPUVENDOR_INTEL,
     203        /*.enmMicroarch = */ kCpumMicroarch_Intel_Atom_Bonnell,
     204        /*.fFlags       = */ 0,
     205        /*.enmEntryType = */ CPUMDBENTRYTYPE_X86,
     206    },
    202207    /*.uFamily          = */ 6,
    203208    /*.uModel           = */ 28,
    204209    /*.uStepping        = */ 2,
    205     /*.enmMicroarch     = */ kCpumMicroarch_Intel_Atom_Bonnell,
    206210    /*.uScalableBusFreq = */ CPUM_SBUSFREQ_133MHZ,
    207     /*.fFlags           = */ 0,
    208211    /*.cMaxPhysAddrWidth= */ 32,
    209212    /*.fMxCsrMask       = */ 0xffff,
  • trunk/src/VBox/VMM/VMMR3/cpus/Intel_Core2_T7600_2_33GHz.h

    r106061 r109008  
    209209 * Database entry for Intel(R) Core(TM)2 CPU         T7600  @ 2.33GHz.
    210210 */
    211 static CPUMDBENTRY const g_Entry_Intel_Core2_T7600_2_33GHz =
     211static CPUMDBENTRYX86 const g_Entry_Intel_Core2_T7600_2_33GHz =
    212212{
    213     /*.pszName          = */ "Intel Core2 T7600 2.33GHz",
    214     /*.pszFullName      = */ "Intel(R) Core(TM)2 CPU         T7600  @ 2.33GHz",
    215     /*.enmVendor        = */ CPUMCPUVENDOR_INTEL,
     213    {
     214        /*.pszName      = */ "Intel Core2 T7600 2.33GHz",
     215        /*.pszFullName  = */ "Intel(R) Core(TM)2 CPU         T7600  @ 2.33GHz",
     216        /*.enmVendor    = */ CPUMCPUVENDOR_INTEL,
     217        /*.enmMicroarch = */ kCpumMicroarch_Intel_Core2_Merom,
     218        /*.fFlags       = */ 0,
     219        /*.enmEntryType = */ CPUMDBENTRYTYPE_X86,
     220    },
    216221    /*.uFamily          = */ 6,
    217222    /*.uModel           = */ 15,
    218223    /*.uStepping        = */ 6,
    219     /*.enmMicroarch     = */ kCpumMicroarch_Intel_Core2_Merom,
    220224    /*.uScalableBusFreq = */ CPUM_SBUSFREQ_167MHZ,
    221     /*.fFlags           = */ 0,
    222225    /*.cMaxPhysAddrWidth= */ 36,
    223226    /*.fMxCsrMask       = */ 0x0000ffff,
  • trunk/src/VBox/VMM/VMMR3/cpus/Intel_Core2_X6800_2_93GHz.h

    r106061 r109008  
    247247 * Database entry for Intel(R) Core(TM)2 CPU         X6800  @ 2.93GHz.
    248248 */
    249 static CPUMDBENTRY const g_Entry_Intel_Core2_X6800_2_93GHz =
     249static CPUMDBENTRYX86 const g_Entry_Intel_Core2_X6800_2_93GHz =
    250250{
    251     /*.pszName          = */ "Intel Core2 X6800 2.93GHz",
    252     /*.pszFullName      = */ "Intel(R) Core(TM)2 CPU         X6800  @ 2.93GHz",
    253     /*.enmVendor        = */ CPUMCPUVENDOR_INTEL,
     251    {
     252        /*.pszName      = */ "Intel Core2 X6800 2.93GHz",
     253        /*.pszFullName  = */ "Intel(R) Core(TM)2 CPU         X6800  @ 2.93GHz",
     254        /*.enmVendor    = */ CPUMCPUVENDOR_INTEL,
     255        /*.enmMicroarch = */ kCpumMicroarch_Intel_Core2_Merom,
     256        /*.fFlags       = */ 0,
     257        /*.enmEntryType = */ CPUMDBENTRYTYPE_X86,
     258    },
    254259    /*.uFamily          = */ 6,
    255260    /*.uModel           = */ 15,
    256261    /*.uStepping        = */ 6,
    257     /*.enmMicroarch     = */ kCpumMicroarch_Intel_Core2_Merom,
    258262    /*.uScalableBusFreq = */ CPUM_SBUSFREQ_267MHZ,
    259     /*.fFlags           = */ 0,
    260263    /*.cMaxPhysAddrWidth= */ 36,
    261264    /*.fMxCsrMask       = */ 0x0000ffff,
  • trunk/src/VBox/VMM/VMMR3/cpus/Intel_Core_Duo_T2600_2_16GHz.h

    r106061 r109008  
    209209 * Database entry for Intel(R) Core(TM) Duo CPU      T2600  @ 2.16GHz.
    210210 */
    211 static CPUMDBENTRY const g_Entry_Intel_Core_Duo_T2600_2_16GHz =
     211static CPUMDBENTRYX86 const g_Entry_Intel_Core_Duo_T2600_2_16GHz =
    212212{
    213     /*.pszName          = */ "Intel Core Duo T2600 2.16GHz",
    214     /*.pszFullName      = */ "Genuine Intel(R) CPU           T2600  @ 2.16GHz",
    215 //    /*.pszFullName      = */ "Intel(R) Core(TM) Duo CPU      T2600  @ 2.16GHz",
    216     /*.enmVendor        = */ CPUMCPUVENDOR_INTEL,
     213    {
     214        /*.pszName      = */ "Intel Core Duo T2600 2.16GHz",
     215        /*.pszFullName  = */ "Genuine Intel(R) CPU           T2600  @ 2.16GHz",
     216    //    /*.pszFullName  = */ "Intel(R) Core(TM) Duo CPU      T2600  @ 2.16GHz",
     217        /*.enmVendor    = */ CPUMCPUVENDOR_INTEL,
     218        /*.enmMicroarch = */ kCpumMicroarch_Intel_Core_Yonah,
     219        /*.fFlags       = */ 0,
     220        /*.enmEntryType = */ CPUMDBENTRYTYPE_X86,
     221    },
    217222    /*.uFamily          = */ 6,
    218223    /*.uModel           = */ 14,
    219224    /*.uStepping        = */ 8,
    220     /*.enmMicroarch     = */ kCpumMicroarch_Intel_Core_Yonah,
    221225    /*.uScalableBusFreq = */ CPUM_SBUSFREQ_167MHZ,
    222     /*.fFlags           = */ 0,
    223226    /*.cMaxPhysAddrWidth= */ 32,
    224227    /*.fMxCsrMask       = */ 0x0000ffff,
  • trunk/src/VBox/VMM/VMMR3/cpus/Intel_Core_i5_3570.h

    r106061 r109008  
    324324 * Database entry for Intel(R) Core(TM) i5-3570 CPU @ 3.40GHz.
    325325 */
    326 static CPUMDBENTRY const g_Entry_Intel_Core_i5_3570 =
     326static CPUMDBENTRYX86 const g_Entry_Intel_Core_i5_3570 =
    327327{
    328     /*.pszName          = */ "Intel Core i5-3570",
    329     /*.pszFullName      = */ "Intel(R) Core(TM) i5-3570 CPU @ 3.40GHz",
    330     /*.enmVendor        = */ CPUMCPUVENDOR_INTEL,
     328    {
     329        /*.pszName      = */ "Intel Core i5-3570",
     330        /*.pszFullName  = */ "Intel(R) Core(TM) i5-3570 CPU @ 3.40GHz",
     331        /*.enmVendor    = */ CPUMCPUVENDOR_INTEL,
     332        /*.enmMicroarch = */ kCpumMicroarch_Intel_Core7_IvyBridge,
     333        /*.fFlags       = */ 0,
     334        /*.enmEntryType = */ CPUMDBENTRYTYPE_X86,
     335    },
    331336    /*.uFamily          = */ 6,
    332337    /*.uModel           = */ 58,
    333338    /*.uStepping        = */ 9,
    334     /*.enmMicroarch     = */ kCpumMicroarch_Intel_Core7_IvyBridge,
    335339    /*.uScalableBusFreq = */ CPUM_SBUSFREQ_100MHZ,
    336     /*.fFlags           = */ 0,
    337340    /*.cMaxPhysAddrWidth= */ 36,
    338341    /*.fMxCsrMask       = */ 0xffff,
  • trunk/src/VBox/VMM/VMMR3/cpus/Intel_Core_i7_2635QM.h

    r106061 r109008  
    317317 * Database entry for Intel(R) Core(TM) i7-2635QM CPU @ 2.00GHz.
    318318 */
    319 static CPUMDBENTRY const g_Entry_Intel_Core_i7_2635QM =
     319static CPUMDBENTRYX86 const g_Entry_Intel_Core_i7_2635QM =
    320320{
    321     /*.pszName          = */ "Intel Core i7-2635QM",
    322     /*.pszFullName      = */ "Intel(R) Core(TM) i7-2635QM CPU @ 2.00GHz",
    323     /*.enmVendor        = */ CPUMCPUVENDOR_INTEL,
     321    {
     322        /*.pszName      = */ "Intel Core i7-2635QM",
     323        /*.pszFullName  = */ "Intel(R) Core(TM) i7-2635QM CPU @ 2.00GHz",
     324        /*.enmVendor    = */ CPUMCPUVENDOR_INTEL,
     325        /*.enmMicroarch = */ kCpumMicroarch_Intel_Core7_SandyBridge,
     326        /*.fFlags       = */ 0,
     327        /*.enmEntryType = */ CPUMDBENTRYTYPE_X86,
     328    },
    324329    /*.uFamily          = */ 6,
    325330    /*.uModel           = */ 42,
    326331    /*.uStepping        = */ 7,
    327     /*.enmMicroarch     = */ kCpumMicroarch_Intel_Core7_SandyBridge,
    328332    /*.uScalableBusFreq = */ CPUM_SBUSFREQ_100MHZ,
    329     /*.fFlags           = */ 0,
    330333    /*.cMaxPhysAddrWidth= */ 36,
    331334    /*.fMxCsrMask       = */ 0xffff,
  • trunk/src/VBox/VMM/VMMR3/cpus/Intel_Core_i7_3820QM.h

    r106061 r109008  
    366366 * Database entry for Intel(R) Core(TM) i7-3820QM CPU @ 2.70GHz.
    367367 */
    368 static CPUMDBENTRY const g_Entry_Intel_Core_i7_3820QM =
     368static CPUMDBENTRYX86 const g_Entry_Intel_Core_i7_3820QM =
    369369{
    370     /*.pszName          = */ "Intel Core i7-3820QM",
    371     /*.pszFullName      = */ "Intel(R) Core(TM) i7-3820QM CPU @ 2.70GHz",
    372     /*.enmVendor        = */ CPUMCPUVENDOR_INTEL,
     370    {
     371        /*.pszName      = */ "Intel Core i7-3820QM",
     372        /*.pszFullName  = */ "Intel(R) Core(TM) i7-3820QM CPU @ 2.70GHz",
     373        /*.enmVendor    = */ CPUMCPUVENDOR_INTEL,
     374        /*.enmMicroarch = */ kCpumMicroarch_Intel_Core7_IvyBridge,
     375        /*.fFlags       = */ 0,
     376        /*.enmEntryType = */ CPUMDBENTRYTYPE_X86,
     377    },
    373378    /*.uFamily          = */ 6,
    374379    /*.uModel           = */ 58,
    375380    /*.uStepping        = */ 9,
    376     /*.enmMicroarch     = */ kCpumMicroarch_Intel_Core7_IvyBridge,
    377381    /*.uScalableBusFreq = */ CPUM_SBUSFREQ_UNKNOWN,
    378     /*.fFlags           = */ 0,
    379382    /*.cMaxPhysAddrWidth= */ 36,
    380383    /*.paCpuIdLeaves    = */ NULL_ALONE(g_aCpuIdLeaves_Intel_Core_i7_3820QM),
  • trunk/src/VBox/VMM/VMMR3/cpus/Intel_Core_i7_3960X.h

    r106061 r109008  
    354354 * Database entry for Intel(R) Core(TM) i7-3960X CPU @ 3.30GHz.
    355355 */
    356 static CPUMDBENTRY const g_Entry_Intel_Core_i7_3960X =
     356static CPUMDBENTRYX86 const g_Entry_Intel_Core_i7_3960X =
    357357{
    358     /*.pszName          = */ "Intel Core i7-3960X",
    359     /*.pszFullName      = */ "Intel(R) Core(TM) i7-3960X CPU @ 3.30GHz",
    360     /*.enmVendor        = */ CPUMCPUVENDOR_INTEL,
     358    {
     359        /*.pszName      = */ "Intel Core i7-3960X",
     360        /*.pszFullName  = */ "Intel(R) Core(TM) i7-3960X CPU @ 3.30GHz",
     361        /*.enmVendor    = */ CPUMCPUVENDOR_INTEL,
     362        /*.enmMicroarch = */ kCpumMicroarch_Intel_Core7_SandyBridge,
     363        /*.fFlags       = */ 0,
     364        /*.enmEntryType = */ CPUMDBENTRYTYPE_X86,
     365    },
    361366    /*.uFamily          = */ 6,
    362367    /*.uModel           = */ 45,
    363368    /*.uStepping        = */ 6,
    364     /*.enmMicroarch     = */ kCpumMicroarch_Intel_Core7_SandyBridge,
    365369    /*.uScalableBusFreq = */ CPUM_SBUSFREQ_100MHZ,
    366     /*.fFlags           = */ 0,
    367370    /*.cMaxPhysAddrWidth= */ 46,
    368371    /*.fMxCsrMask       = */ 0xffff,
  • trunk/src/VBox/VMM/VMMR3/cpus/Intel_Core_i7_5600U.h

    r106061 r109008  
    353353 * Database entry for Intel(R) Core(TM) i7-5600U CPU @ 2.60GHz.
    354354 */
    355 static CPUMDBENTRY const g_Entry_Intel_Core_i7_5600U =
     355static CPUMDBENTRYX86 const g_Entry_Intel_Core_i7_5600U =
    356356{
    357     /*.pszName          = */ "Intel Core i7-5600U",
    358     /*.pszFullName      = */ "Intel(R) Core(TM) i7-5600U CPU @ 2.60GHz",
    359     /*.enmVendor        = */ CPUMCPUVENDOR_INTEL,
     357    {
     358        /*.pszName      = */ "Intel Core i7-5600U",
     359        /*.pszFullName  = */ "Intel(R) Core(TM) i7-5600U CPU @ 2.60GHz",
     360        /*.enmVendor    = */ CPUMCPUVENDOR_INTEL,
     361        /*.enmMicroarch = */ kCpumMicroarch_Intel_Core7_Broadwell,
     362        /*.fFlags       = */ 0,
     363        /*.enmEntryType = */ CPUMDBENTRYTYPE_X86,
     364    },
    360365    /*.uFamily          = */ 6,
    361366    /*.uModel           = */ 61,
    362367    /*.uStepping        = */ 4,
    363     /*.enmMicroarch     = */ kCpumMicroarch_Intel_Core7_Broadwell,
    364368    /*.uScalableBusFreq = */ CPUM_SBUSFREQ_100MHZ,
    365     /*.fFlags           = */ 0,
    366369    /*.cMaxPhysAddrWidth= */ 39,
    367370    /*.fMxCsrMask       = */ 0xffff,
  • trunk/src/VBox/VMM/VMMR3/cpus/Intel_Core_i7_6700K.h

    r106061 r109008  
    495495 * Database entry for Intel(R) Core(TM) i7-6700K CPU @ 4.00GHz.
    496496 */
    497 static CPUMDBENTRY const g_Entry_Intel_Core_i7_6700K =
     497static CPUMDBENTRYX86 const g_Entry_Intel_Core_i7_6700K =
    498498{
    499     /*.pszName          = */ "Intel Core i7-6700K",
    500     /*.pszFullName      = */ "Intel(R) Core(TM) i7-6700K CPU @ 4.00GHz",
    501     /*.enmVendor        = */ CPUMCPUVENDOR_INTEL,
     499    {
     500        /*.pszName      = */ "Intel Core i7-6700K",
     501        /*.pszFullName  = */ "Intel(R) Core(TM) i7-6700K CPU @ 4.00GHz",
     502        /*.enmVendor    = */ CPUMCPUVENDOR_INTEL,
     503        /*.enmMicroarch = */ kCpumMicroarch_Intel_Core7_Skylake,
     504        /*.fFlags       = */ 0,
     505        /*.enmEntryType = */ CPUMDBENTRYTYPE_X86,
     506    },
    502507    /*.uFamily          = */ 6,
    503508    /*.uModel           = */ 94,
    504509    /*.uStepping        = */ 3,
    505     /*.enmMicroarch     = */ kCpumMicroarch_Intel_Core7_Skylake,
    506510    /*.uScalableBusFreq = */ CPUM_SBUSFREQ_100MHZ,
    507     /*.fFlags           = */ 0,
    508511    /*.cMaxPhysAddrWidth= */ 39,
    509512    /*.fMxCsrMask       = */ 0xffff,
  • trunk/src/VBox/VMM/VMMR3/cpus/Intel_Pentium_4_3_00GHz.h

    r106061 r109008  
    262262 * Database entry for Intel(R) Pentium(R) 4 CPU 3.00GHz.
    263263 */
    264 static CPUMDBENTRY const g_Entry_Intel_Pentium_4_3_00GHz =
     264static CPUMDBENTRYX86 const g_Entry_Intel_Pentium_4_3_00GHz =
    265265{
    266     /*.pszName          = */ "Intel Pentium 4 3.00GHz",
    267     /*.pszFullName      = */ "Intel(R) Pentium(R) 4 CPU 3.00GHz",
    268     /*.enmVendor        = */ CPUMCPUVENDOR_INTEL,
     266    {
     267        /*.pszName      = */ "Intel Pentium 4 3.00GHz",
     268        /*.pszFullName  = */ "Intel(R) Pentium(R) 4 CPU 3.00GHz",
     269        /*.enmVendor    = */ CPUMCPUVENDOR_INTEL,
     270        /*.enmMicroarch = */ kCpumMicroarch_Intel_NB_Prescott2M,
     271        /*.fFlags       = */ 0,
     272        /*.enmEntryType = */ CPUMDBENTRYTYPE_X86,
     273    },
    269274    /*.uFamily          = */ 15,
    270275    /*.uModel           = */ 4,
    271276    /*.uStepping        = */ 3,
    272     /*.enmMicroarch     = */ kCpumMicroarch_Intel_NB_Prescott2M,
    273277    /*.uScalableBusFreq = */ CPUM_SBUSFREQ_UNKNOWN,
    274     /*.fFlags           = */ 0,
    275278    /*.cMaxPhysAddrWidth= */ 36,
    276279    /*.fMxCsrMask       = */ 0xffff,
  • trunk/src/VBox/VMM/VMMR3/cpus/Intel_Pentium_M_processor_2_00GHz.h

    r106061 r109008  
    201201 * Database entry for Intel(R) Pentium(R) M processor 2.00GHz.
    202202 */
    203 static CPUMDBENTRY const g_Entry_Intel_Pentium_M_processor_2_00GHz =
     203static CPUMDBENTRYX86 const g_Entry_Intel_Pentium_M_processor_2_00GHz =
    204204{
    205     /*.pszName          = */ "Intel Pentium M processor 2.00GHz",
    206     /*.pszFullName      = */ "Intel(R) Pentium(R) M processor 2.00GHz",
    207     /*.enmVendor        = */ CPUMCPUVENDOR_INTEL,
     205    {
     206        /*.pszName      = */ "Intel Pentium M processor 2.00GHz",
     207        /*.pszFullName  = */ "Intel(R) Pentium(R) M processor 2.00GHz",
     208        /*.enmVendor    = */ CPUMCPUVENDOR_INTEL,
     209        /*.enmMicroarch = */ kCpumMicroarch_Intel_P6_M_Dothan,
     210        /*.fFlags       = */ 0,
     211        /*.enmEntryType = */ CPUMDBENTRYTYPE_X86,
     212    },
    208213    /*.uFamily          = */ 6,
    209214    /*.uModel           = */ 13,
    210215    /*.uStepping        = */ 6,
    211     /*.enmMicroarch     = */ kCpumMicroarch_Intel_P6_M_Dothan,
    212216    /*.uScalableBusFreq = */ CPUM_SBUSFREQ_UNKNOWN,
    213     /*.fFlags           = */ 0,
    214217    /*.cMaxPhysAddrWidth= */ 32,
    215218    /*.fMxCsrMask       = */ 0xffbf, ///< @todo check this
  • trunk/src/VBox/VMM/VMMR3/cpus/Intel_Pentium_N3530_2_16GHz.h

    r106061 r109008  
    250250 * Database entry for Intel(R) Pentium(R) CPU  N3530  @ 2.16GHz.
    251251 */
    252 static CPUMDBENTRY const g_Entry_Intel_Pentium_N3530_2_16GHz =
     252static CPUMDBENTRYX86 const g_Entry_Intel_Pentium_N3530_2_16GHz =
    253253{
    254     /*.pszName          = */ "Intel Pentium N3530 2.16GHz",
    255     /*.pszFullName      = */ "Intel(R) Pentium(R) CPU  N3530  @ 2.16GHz",
    256     /*.enmVendor        = */ CPUMCPUVENDOR_INTEL,
     254    {
     255        /*.pszName      = */ "Intel Pentium N3530 2.16GHz",
     256        /*.pszFullName  = */ "Intel(R) Pentium(R) CPU  N3530  @ 2.16GHz",
     257        /*.enmVendor    = */ CPUMCPUVENDOR_INTEL,
     258        /*.enmMicroarch = */ kCpumMicroarch_Intel_Atom_Silvermont,
     259        /*.fFlags       = */ 0,
     260        /*.enmEntryType = */ CPUMDBENTRYTYPE_X86,
     261    },
    257262    /*.uFamily          = */ 6,
    258263    /*.uModel           = */ 55,
    259264    /*.uStepping        = */ 8,
    260     /*.enmMicroarch     = */ kCpumMicroarch_Intel_Atom_Silvermont,
    261265    /*.uScalableBusFreq = */ CPUM_SBUSFREQ_267MHZ,
    262     /*.fFlags           = */ 0,
    263266    /*.cMaxPhysAddrWidth= */ 36,
    264267    /*.fMxCsrMask       = */ 0xffff,
  • trunk/src/VBox/VMM/VMMR3/cpus/Intel_Xeon_X5482_3_20GHz.h

    r106061 r109008  
    233233 * Database entry for Intel(R) Xeon(R) CPU           X5482  @ 3.20GHz.
    234234 */
    235 static CPUMDBENTRY const g_Entry_Intel_Xeon_X5482_3_20GHz =
     235static CPUMDBENTRYX86 const g_Entry_Intel_Xeon_X5482_3_20GHz =
    236236{
    237     /*.pszName          = */ "Intel Xeon X5482 3.20GHz",
    238     /*.pszFullName      = */ "Intel(R) Xeon(R) CPU           X5482  @ 3.20GHz",
    239     /*.enmVendor        = */ CPUMCPUVENDOR_INTEL,
     237    {
     238        /*.pszName      = */ "Intel Xeon X5482 3.20GHz",
     239        /*.pszFullName  = */ "Intel(R) Xeon(R) CPU           X5482  @ 3.20GHz",
     240        /*.enmVendor    = */ CPUMCPUVENDOR_INTEL,
     241        /*.enmMicroarch = */ kCpumMicroarch_Intel_Core2_Penryn,
     242        /*.fFlags       = */ 0,
     243        /*.enmEntryType = */ CPUMDBENTRYTYPE_X86,
     244    },
    240245    /*.uFamily          = */ 6,
    241246    /*.uModel           = */ 23,
    242247    /*.uStepping        = */ 6,
    243     /*.enmMicroarch     = */ kCpumMicroarch_Intel_Core2_Penryn,
    244248    /*.uScalableBusFreq = */ CPUM_SBUSFREQ_400MHZ,
    245     /*.fFlags           = */ 0,
    246249    /*.cMaxPhysAddrWidth= */ 38,
    247250    /*.fMxCsrMask       = */ 0xffff,
  • trunk/src/VBox/VMM/VMMR3/cpus/Quad_Core_AMD_Opteron_2384.h

    r106061 r109008  
    255255 * Database entry for Quad-Core AMD Opteron(tm) Processor 2384.
    256256 */
    257 static CPUMDBENTRY const g_Entry_Quad_Core_AMD_Opteron_2384 =
     257static CPUMDBENTRYX86 const g_Entry_Quad_Core_AMD_Opteron_2384 =
    258258{
    259     /*.pszName          = */ "Quad-Core AMD Opteron 2384",
    260     /*.pszFullName      = */ "Quad-Core AMD Opteron(tm) Processor 2384",
    261     /*.enmVendor        = */ CPUMCPUVENDOR_AMD,
     259    {
     260        /*.pszName      = */ "Quad-Core AMD Opteron 2384",
     261        /*.pszFullName  = */ "Quad-Core AMD Opteron(tm) Processor 2384",
     262        /*.enmVendor    = */ CPUMCPUVENDOR_AMD,
     263        /*.enmMicroarch = */ kCpumMicroarch_AMD_K10,
     264        /*.fFlags       = */ 0,
     265        /*.enmEntryType = */ CPUMDBENTRYTYPE_X86,
     266    },
    262267    /*.uFamily          = */ 16,
    263268    /*.uModel           = */ 4,
    264269    /*.uStepping        = */ 2,
    265     /*.enmMicroarch     = */ kCpumMicroarch_AMD_K10,
    266270    /*.uScalableBusFreq = */ CPUM_SBUSFREQ_UNKNOWN,
    267     /*.fFlags           = */ 0,
    268271    /*.cMaxPhysAddrWidth= */ 48,
    269272    /*.fMxCsrMask       = */ 0x2ffff,
  • trunk/src/VBox/VMM/VMMR3/cpus/VIA_QuadCore_L4700_1_2_GHz.h

    r106061 r109008  
    389389 * Database entry for VIA QuadCore L4700 @ 1.2+ GHz.
    390390 */
    391 static CPUMDBENTRY const g_Entry_VIA_QuadCore_L4700_1_2_GHz =
     391static CPUMDBENTRYX86 const g_Entry_VIA_QuadCore_L4700_1_2_GHz =
    392392{
    393     /*.pszName          = */ "VIA QuadCore L4700 1.2+ GHz",
    394     /*.pszFullName      = */ "VIA QuadCore L4700 @ 1.2+ GHz",
    395     /*.enmVendor        = */ CPUMCPUVENDOR_VIA,
     393    {
     394        /*.pszName      = */ "VIA QuadCore L4700 1.2+ GHz",
     395        /*.pszFullName  = */ "VIA QuadCore L4700 @ 1.2+ GHz",
     396        /*.enmVendor    = */ CPUMCPUVENDOR_VIA,
     397        /*.enmMicroarch = */ kCpumMicroarch_VIA_Isaiah,
     398        /*.fFlags       = */ 0,
     399        /*.enmEntryType = */ CPUMDBENTRYTYPE_X86,
     400    },
    396401    /*.uFamily          = */ 6,
    397402    /*.uModel           = */ 15,
    398403    /*.uStepping        = */ 13,
    399     /*.enmMicroarch     = */ kCpumMicroarch_VIA_Isaiah,
    400404    /*.uScalableBusFreq = */ CPUM_SBUSFREQ_267MHZ, /*??*/
    401     /*.fFlags           = */ 0,
    402405    /*.cMaxPhysAddrWidth= */ 36,
    403406    /*.fMxCsrMask       = */ 0xffff,
  • trunk/src/VBox/VMM/VMMR3/cpus/ZHAOXIN_KaiXian_KX_U5581_1_8GHz.h

    r106061 r109008  
    402402 * Database entry for ZHAOXIN KaiXian [email protected].
    403403 */
    404 static CPUMDBENTRY const g_Entry_ZHAOXIN_KaiXian_KX_U5581_1_8GHz =
     404static CPUMDBENTRYX86 const g_Entry_ZHAOXIN_KaiXian_KX_U5581_1_8GHz =
    405405{
    406     /*.pszName          = */ "ZHAOXIN KaiXian KX-U5581 1.8GHz",
    407     /*.pszFullName      = */ "ZHAOXIN KaiXian [email protected]",
    408     /*.enmVendor        = */ CPUMCPUVENDOR_SHANGHAI,
     406    {
     407        /*.pszName      = */ "ZHAOXIN KaiXian KX-U5581 1.8GHz",
     408        /*.pszFullName  = */ "ZHAOXIN KaiXian [email protected]",
     409        /*.enmVendor    = */ CPUMCPUVENDOR_SHANGHAI,
     410        /*.enmMicroarch = */ kCpumMicroarch_Shanghai_Wudaokou,
     411        /*.fFlags       = */ 0,
     412        /*.enmEntryType = */ CPUMDBENTRYTYPE_X86,
     413    },
    409414    /*.uFamily          = */ 7,
    410415    /*.uModel           = */ 11,
    411416    /*.uStepping        = */ 5,
    412     /*.enmMicroarch     = */ kCpumMicroarch_Shanghai_Wudaokou,
    413417    /*.uScalableBusFreq = */ CPUM_SBUSFREQ_UNKNOWN,
    414     /*.fFlags           = */ 0,
    415418    /*.cMaxPhysAddrWidth= */ 40,
    416419    /*.fMxCsrMask       = */ 0x0000ffff,
  • trunk/src/VBox/VMM/tools/Makefile.kmk

    r107227 r109008  
    7171VBoxCpuReport_SOURCES   = \
    7272        VBoxCpuReport.cpp \
    73         VBoxCpuReportMsrSup.cpp \
    7473        ../VMMR3/CPUMR3CpuId.cpp \
    7574        ../VMMAll/CPUMAllCpuId.cpp
    76 VBoxCpuReport_SOURCES.linux = \
     75
     76VBoxCpuReport_SOURCES.amd64 = \
     77        VBoxCpuReport-x86.cpp \
     78        VBoxCpuReportMsrSup.cpp
     79VBoxCpuReport_SOURCES.x86 = \
     80        VBoxCpuReport-x86.cpp \
     81        VBoxCpuReportMsrSup.cpp
     82VBoxCpuReport_SOURCES.linux.amd64 = \
    7783        VBoxCpuReportMsrLinux.cpp
    78 VBoxCpuReport_DEFS.linux    = VBCR_HAVE_PLATFORM_MSR_PROBER
     84VBoxCpuReport_SOURCES.linux.x86 = \
     85        VBoxCpuReportMsrLinux.cpp
     86VBoxCpuReport_DEFS.linux.amd64 = VBCR_HAVE_PLATFORM_MSR_PROBER
     87VBoxCpuReport_DEFS.linux.x86   = VBCR_HAVE_PLATFORM_MSR_PROBER
     88
    7989VBoxCpuReport_LIBS      = \
    8090        $(PATH_STAGE_LIB)/SUPR3Static$(VBOX_SUFF_LIB) \
  • trunk/src/VBox/VMM/tools/VBoxCpuReport-x86.cpp

    r108997 r109008  
    11/* $Id$ */
    22/** @file
    3  * VBoxCpuReport - Produces the basis for a CPU DB entry.
     3 * VBoxCpuReport - Produces the basis for a CPU DB entry, x86 specifics.
    44 */
    55
     
    7474*   Global Variables                                                                                                             *
    7575*********************************************************************************************************************************/
    76 /** The CPU vendor.  Used by the MSR code. */
    77 static CPUMCPUVENDOR    g_enmVendor = CPUMCPUVENDOR_INVALID;
    78 /** The CPU microarchitecture.  Used by the MSR code. */
    79 static CPUMMICROARCH    g_enmMicroarch = kCpumMicroarch_Invalid;
    8076/** Set if g_enmMicroarch indicates an Intel NetBurst CPU. */
    8177static bool             g_fIntelNetBurst = false;
    82 /** The alternative report stream. */
    83 static PRTSTREAM        g_pReportOut;
    84 /** The alternative debug stream. */
    85 static PRTSTREAM        g_pDebugOut;
    8678/** Whether to skip MSR collection.   */
    87 static bool             g_fNoMsrs = false;
     79bool                    g_fNoMsrs = false;
    8880
    8981/** Snooping info storage for vbCpuRepGuessScalableBusFrequencyName. */
     
    9284/** The MSR accessors interface. */
    9385static VBCPUREPMSRACCESSORS g_MsrAcc;
    94 
    95 
    96 
    97 void vbCpuRepDebug(const char *pszMsg, ...)
    98 {
    99     va_list va;
    100 
    101     /* Always print a copy of the report to standard error. */
    102     va_start(va, pszMsg);
    103     RTStrmPrintfV(g_pStdErr, pszMsg, va);
    104     va_end(va);
    105     RTStrmFlush(g_pStdErr);
    106 
    107     /* Alternatively, also print to a log file. */
    108     if (g_pDebugOut)
    109     {
    110         va_start(va, pszMsg);
    111         RTStrmPrintfV(g_pDebugOut, pszMsg, va);
    112         va_end(va);
    113         RTStrmFlush(g_pDebugOut);
    114     }
    115 
    116     /* Give the output device a chance to write / display it. */
    117     RTThreadSleep(1);
    118 }
    119 
    120 
    121 void vbCpuRepPrintf(const char *pszMsg, ...)
    122 {
    123     va_list va;
    124 
    125     /* Output to report file, if requested. */
    126     if (g_pReportOut)
    127     {
    128         va_start(va, pszMsg);
    129         RTStrmPrintfV(g_pReportOut, pszMsg, va);
    130         va_end(va);
    131         RTStrmFlush(g_pReportOut);
    132     }
    133 
    134     /* Always print a copy of the report to standard out. */
    135     va_start(va, pszMsg);
    136     RTStrmPrintfV(g_pStdOut, pszMsg, va);
    137     va_end(va);
    138     RTStrmFlush(g_pStdOut);
    139 }
    140 
    14186
    14287
     
    44134358
    44144359
    4415 static int probeMsrs(bool fHacking, const char *pszNameC, const char *pszCpuDesc,
    4416                      char *pszMsrMask, size_t cbMsrMask)
     4360int probeMsrs(bool fHacking, const char *pszNameC, const char *pszCpuDesc, char *pszMsrMask, size_t cbMsrMask)
    44174361{
    44184362    /* Initialize the mask. */
     
    45944538
    45954539
    4596 static const char *cpuVendorToString(CPUMCPUVENDOR enmCpuVendor)
    4597 {
    4598     switch (enmCpuVendor)
    4599     {
    4600         case CPUMCPUVENDOR_INTEL:       return "Intel";
    4601         case CPUMCPUVENDOR_AMD:         return "AMD";
    4602         case CPUMCPUVENDOR_VIA:         return "VIA";
    4603         case CPUMCPUVENDOR_CYRIX:       return "Cyrix";
    4604         case CPUMCPUVENDOR_SHANGHAI:    return "Shanghai";
    4605         case CPUMCPUVENDOR_HYGON:       return "Hygon";
    4606         case CPUMCPUVENDOR_APPLE:       return "Apple";
    4607         case CPUMCPUVENDOR_INVALID:
    4608         case CPUMCPUVENDOR_UNKNOWN:
    4609         case CPUMCPUVENDOR_32BIT_HACK:
    4610             break;
    4611     }
    4612     return "invalid-cpu-vendor";
    4613 }
    4614 
    4615 
    46164540/**
    46174541 * Takes a shot a the bus frequency name (last part).
     
    46404564
    46414565
    4642 static int produceCpuReport(void)
     4566int produceCpuReport(void)
    46434567{
    46444568    /*
     
    47494673    {
    47504674        ASMCpuIdExSlow(1, 0, 0, 0, &uEax, &uEbx, &uEcx, &uEdx);
    4751         RTStrPrintf(szNameC, sizeof(szNameC), "%s_%u_%u_%u", cpuVendorToString(enmVendor), RTX86GetCpuFamily(uEax),
     4675        RTStrPrintf(szNameC, sizeof(szNameC), "%s_%u_%u_%u", vbCpuVendorToString(enmVendor), RTX86GetCpuFamily(uEax),
    47524676                    RTX86GetCpuModel(uEax, enmVendor == CPUMCPUVENDOR_INTEL), RTX86GetCpuStepping(uEax));
    47534677        pszCpuDesc = pszName = szNameC;
     
    48364760                   " * Database entry for %s.\n"
    48374761                   " */\n"
    4838                    "static CPUMDBENTRY const g_Entry_%s = \n"
     4762                   "static CPUMDBENTRYX86 const g_Entry_%s = \n"
    48394763                   "{\n"
    4840                    "    /*.pszName          = */ \"%s\",\n"
    4841                    "    /*.pszFullName      = */ \"%s\",\n"
    4842                    "    /*.enmVendor        = */ CPUMCPUVENDOR_%s,\n"
     4764                   "    {\n"
     4765                   "        /*.pszName          = */ \"%s\",\n"
     4766                   "        /*.pszFullName      = */ \"%s\",\n"
     4767                   "        /*.enmVendor        = */ CPUMCPUVENDOR_%s,\n"
     4768                   "        /*.enmMicroarch     = */ kCpumMicroarch_%s,\n"
     4769                   "        /*.fFlags           = */ 0,\n"
     4770                   "    },\n"
    48434771                   "    /*.uFamily          = */ %u,\n"
    48444772                   "    /*.uModel           = */ %u,\n"
    48454773                   "    /*.uStepping        = */ %u,\n"
    4846                    "    /*.enmMicroarch     = */ kCpumMicroarch_%s,\n"
    48474774                   "    /*.uScalableBusFreq = */ CPUM_SBUSFREQ_%s,\n"
    4848                    "    /*.fFlags           = */ 0,\n"
    48494775                   "    /*.cMaxPhysAddrWidth= */ %u,\n"
    48504776                   "    /*.fMxCsrMask       = */ %#010x,\n"
     
    48654791                   pszCpuDesc,
    48664792                   CPUMCpuVendorName(enmVendor),
     4793                   CPUMMicroarchName(enmMicroarch),
     4794
    48674795                   RTX86GetCpuFamily(uEax),
    48684796                   RTX86GetCpuModel(uEax, enmVendor == CPUMCPUVENDOR_INTEL),
    48694797                   RTX86GetCpuStepping(uEax),
    4870                    CPUMMicroarchName(enmMicroarch),
    48714798                   vbCpuRepGuessScalableBusFrequencyName(),
    48724799                   vbCpuRepGetPhysAddrWidth(),
     
    48884815}
    48894816
    4890 
    4891 int main(int argc, char **argv)
    4892 {
    4893     int rc = RTR3InitExe(argc, &argv, 0 /*fFlags*/);
    4894     if (RT_FAILURE(rc))
    4895         return RTMsgInitFailure(rc);
    4896 
    4897     /*
    4898      * Argument parsing?
    4899      */
    4900     static const RTGETOPTDEF s_aOptions[] =
    4901     {
    4902         { "--msrs-only", 'm', RTGETOPT_REQ_NOTHING },
    4903         { "--msrs-dev",  'd', RTGETOPT_REQ_NOTHING },
    4904         { "--no-msrs",   'n', RTGETOPT_REQ_NOTHING },
    4905         { "--output",    'o', RTGETOPT_REQ_STRING  },
    4906         { "--log",       'l', RTGETOPT_REQ_STRING  },
    4907     };
    4908     RTGETOPTSTATE State;
    4909     RTGetOptInit(&State, argc, argv, &s_aOptions[0], RT_ELEMENTS(s_aOptions), 1, RTGETOPTINIT_FLAGS_OPTS_FIRST);
    4910 
    4911     enum
    4912     {
    4913         kCpuReportOp_Normal,
    4914         kCpuReportOp_MsrsOnly,
    4915         kCpuReportOp_MsrsHacking
    4916     } enmOp = kCpuReportOp_Normal;
    4917     g_pReportOut = NULL;
    4918     g_pDebugOut  = NULL;
    4919     const char *pszOutput   = NULL;
    4920     const char *pszDebugOut = NULL;
    4921 
    4922     int iOpt;
    4923     RTGETOPTUNION ValueUnion;
    4924     while ((iOpt = RTGetOpt(&State, &ValueUnion)) != 0)
    4925     {
    4926         switch (iOpt)
    4927         {
    4928             case 'm':
    4929                 enmOp = kCpuReportOp_MsrsOnly;
    4930                 break;
    4931 
    4932             case 'd':
    4933                 enmOp = kCpuReportOp_MsrsHacking;
    4934                 break;
    4935 
    4936             case 'n':
    4937                 g_fNoMsrs = true;
    4938                 break;
    4939 
    4940             case 'o':
    4941                 pszOutput = ValueUnion.psz;
    4942                 break;
    4943 
    4944             case 'l':
    4945                 pszDebugOut = ValueUnion.psz;
    4946                 break;
    4947 
    4948             case 'h':
    4949                 RTPrintf("Usage: VBoxCpuReport [-m|--msrs-only] [-d|--msrs-dev] [-n|--no-msrs] [-h|--help] [-V|--version] [-o filename.h] [-l debug.log]\n");
    4950                 RTPrintf("Internal tool for gathering information to the VMM CPU database.\n");
    4951                 return RTEXITCODE_SUCCESS;
    4952             case 'V':
    4953                 RTPrintf("%sr%s\n", RTBldCfgVersion(), RTBldCfgRevisionStr());
    4954                 return RTEXITCODE_SUCCESS;
    4955             default:
    4956                 return RTGetOptPrintError(iOpt, &ValueUnion);
    4957         }
    4958     }
    4959 
    4960     /*
    4961      * Open the alternative debug log stream.
    4962      */
    4963     if (pszDebugOut)
    4964     {
    4965         if (RTFileExists(pszDebugOut) && !RTSymlinkExists(pszDebugOut))
    4966         {
    4967             char szOld[RTPATH_MAX];
    4968             rc = RTStrCopy(szOld, sizeof(szOld), pszDebugOut);
    4969             if (RT_SUCCESS(rc))
    4970                 rc = RTStrCat(szOld, sizeof(szOld), ".old");
    4971             if (RT_SUCCESS(rc))
    4972                 RTFileRename(pszDebugOut, szOld, RTFILEMOVE_FLAGS_REPLACE);
    4973         }
    4974         rc = RTStrmOpen(pszDebugOut, "w", &g_pDebugOut);
    4975         if (RT_FAILURE(rc))
    4976         {
    4977             RTMsgError("Error opening '%s': %Rrc", pszDebugOut, rc);
    4978             g_pDebugOut = NULL;
    4979         }
    4980     }
    4981 
    4982     /*
    4983      * Do the requested job.
    4984      */
    4985     rc = VERR_INTERNAL_ERROR;
    4986     switch (enmOp)
    4987     {
    4988         case kCpuReportOp_Normal:
    4989             /* switch output file. */
    4990             if (pszOutput)
    4991             {
    4992                 if (RTFileExists(pszOutput) && !RTSymlinkExists(pszOutput))
    4993                 {
    4994                     char szOld[RTPATH_MAX];
    4995                     rc = RTStrCopy(szOld, sizeof(szOld), pszOutput);
    4996                     if (RT_SUCCESS(rc))
    4997                         rc = RTStrCat(szOld, sizeof(szOld), ".old");
    4998                     if (RT_SUCCESS(rc))
    4999                         RTFileRename(pszOutput, szOld, RTFILEMOVE_FLAGS_REPLACE);
    5000                 }
    5001                 rc = RTStrmOpen(pszOutput, "w", &g_pReportOut);
    5002                 if (RT_FAILURE(rc))
    5003                 {
    5004                     RTMsgError("Error opening '%s': %Rrc", pszOutput, rc);
    5005                     break;
    5006                 }
    5007             }
    5008             rc = produceCpuReport();
    5009             break;
    5010         case kCpuReportOp_MsrsOnly:
    5011         case kCpuReportOp_MsrsHacking:
    5012             rc = probeMsrs(enmOp == kCpuReportOp_MsrsHacking, NULL, NULL, NULL, 0);
    5013             break;
    5014     }
    5015 
    5016     /*
    5017      * Close the output files.
    5018      */
    5019     if (g_pReportOut)
    5020     {
    5021         RTStrmClose(g_pReportOut);
    5022         g_pReportOut = NULL;
    5023     }
    5024 
    5025     if (g_pDebugOut)
    5026     {
    5027         RTStrmClose(g_pDebugOut);
    5028         g_pDebugOut = NULL;
    5029     }
    5030 
    5031     return RT_SUCCESS(rc) ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE;
    5032 }
    5033 
  • trunk/src/VBox/VMM/tools/VBoxCpuReport.cpp

    r107650 r109008  
    3131*********************************************************************************************************************************/
    3232#include <iprt/asm.h>
    33 #include <iprt/asm-amd64-x86.h>
    3433#include <iprt/buildconfig.h>
    3534#include <iprt/ctype.h>
     35#include <iprt/errcore.h>
    3636#include <iprt/file.h>
    3737#include <iprt/getopt.h>
     
    4646#include <iprt/time.h>
    4747
    48 #include <VBox/err.h>
    4948#include <VBox/vmm/cpum.h>
    5049#include <VBox/sup.h>
     
    5554
    5655/*********************************************************************************************************************************
    57 *   Structures and Typedefs                                                                                                      *
    58 *********************************************************************************************************************************/
    59 /** Write only register. */
    60 #define VBCPUREPMSR_F_WRITE_ONLY      RT_BIT(0)
    61 
    62 typedef struct VBCPUREPMSR
    63 {
    64     /** The first MSR register number. */
    65     uint32_t        uMsr;
    66     /** Flags (MSRREPORT_F_XXX). */
    67     uint32_t        fFlags;
    68     /** The value we read, unless write-only.  */
    69     uint64_t        uValue;
    70 } VBCPUREPMSR;
    71 
    72 
    73 /*********************************************************************************************************************************
    7456*   Global Variables                                                                                                             *
    7557*********************************************************************************************************************************/
     58/** The alternative report stream. */
     59PRTSTREAM        g_pReportOut;
     60/** The alternative debug stream. */
     61PRTSTREAM        g_pDebugOut;
    7662/** The CPU vendor.  Used by the MSR code. */
    77 static CPUMCPUVENDOR    g_enmVendor = CPUMCPUVENDOR_INVALID;
     63CPUMCPUVENDOR    g_enmVendor = CPUMCPUVENDOR_INVALID;
    7864/** The CPU microarchitecture.  Used by the MSR code. */
    79 static CPUMMICROARCH    g_enmMicroarch = kCpumMicroarch_Invalid;
    80 /** Set if g_enmMicroarch indicates an Intel NetBurst CPU. */
    81 static bool             g_fIntelNetBurst = false;
    82 /** The alternative report stream. */
    83 static PRTSTREAM        g_pReportOut;
    84 /** The alternative debug stream. */
    85 static PRTSTREAM        g_pDebugOut;
    86 /** Whether to skip MSR collection.   */
    87 static bool             g_fNoMsrs = false;
    88 
    89 /** Snooping info storage for vbCpuRepGuessScalableBusFrequencyName. */
    90 static uint64_t         g_uMsrIntelP6FsbFrequency = UINT64_MAX;
    91 
    92 /** The MSR accessors interface. */
    93 static VBCPUREPMSRACCESSORS g_MsrAcc;
     65CPUMMICROARCH    g_enmMicroarch = kCpumMicroarch_Invalid;
    9466
    9567
     
    141113
    142114
    143 static int vbCpuRepMsrsAddOne(VBCPUREPMSR **ppaMsrs, uint32_t *pcMsrs,
    144                               uint32_t uMsr, uint64_t uValue, uint32_t fFlags)
    145 {
    146     /*
    147      * Grow the array?
    148      */
    149     uint32_t cMsrs = *pcMsrs;
    150     if ((cMsrs % 64) == 0)
    151     {
    152         void *pvNew = RTMemRealloc(*ppaMsrs, (cMsrs + 64) * sizeof(**ppaMsrs));
    153         if (!pvNew)
    154         {
    155             RTMemFree(*ppaMsrs);
    156             *ppaMsrs = NULL;
    157             *pcMsrs  = 0;
    158             return VERR_NO_MEMORY;
    159         }
    160         *ppaMsrs = (VBCPUREPMSR *)pvNew;
    161     }
    162 
    163     /*
    164      * Add it.
    165      */
    166     VBCPUREPMSR *pEntry = *ppaMsrs + cMsrs;
    167     pEntry->uMsr   = uMsr;
    168     pEntry->fFlags = fFlags;
    169     pEntry->uValue = uValue;
    170     *pcMsrs = cMsrs + 1;
    171 
    172     return VINF_SUCCESS;
    173 }
    174 
    175 
    176 /**
    177  * Returns the max physical address width as a number of bits.
    178  *
    179  * @returns Bit count.
    180  */
    181 static uint8_t vbCpuRepGetPhysAddrWidth(void)
    182 {
    183     uint8_t  cMaxWidth;
    184     if (!ASMHasCpuId())
    185         cMaxWidth = 32;
    186     else
    187     {
    188         uint32_t cMaxExt = ASMCpuId_EAX(0x80000000);
    189         if (RTX86IsValidExtRange(cMaxExt)&& cMaxExt >= 0x80000008)
    190             cMaxWidth = ASMCpuId_EAX(0x80000008) & 0xff;
    191         else if (   RTX86IsValidStdRange(ASMCpuId_EAX(0))
    192                  && (ASMCpuId_EDX(1) & X86_CPUID_FEATURE_EDX_PSE36))
    193             cMaxWidth = 36;
    194         else
    195             cMaxWidth = 32;
    196     }
    197     return cMaxWidth;
    198 }
    199 
    200 
    201 static bool vbCpuRepSupportsPae(void)
    202 {
    203     return ASMHasCpuId()
    204         && RTX86IsValidStdRange(ASMCpuId_EAX(0))
    205         && (ASMCpuId_EDX(1) & X86_CPUID_FEATURE_EDX_PAE);
    206 }
    207 
    208 
    209 static bool vbCpuRepSupportsLongMode(void)
    210 {
    211     return ASMHasCpuId()
    212         && RTX86IsValidExtRange(ASMCpuId_EAX(0x80000000))
    213         && (ASMCpuId_EDX(0x80000001) & X86_CPUID_EXT_FEATURE_EDX_LONG_MODE);
    214 }
    215 
    216 
    217 static bool vbCpuRepSupportsNX(void)
    218 {
    219     return ASMHasCpuId()
    220         && RTX86IsValidExtRange(ASMCpuId_EAX(0x80000000))
    221         && (ASMCpuId_EDX(0x80000001) & X86_CPUID_EXT_FEATURE_EDX_NX);
    222 }
    223 
    224 
    225 static bool vbCpuRepSupportsX2Apic(void)
    226 {
    227     return ASMHasCpuId()
    228         && RTX86IsValidStdRange(ASMCpuId_EAX(0))
    229         && (ASMCpuId_ECX(1) & X86_CPUID_FEATURE_ECX_X2APIC);
    230 }
    231 
    232 
    233 
    234 #if 0 /* unused */
    235 static bool msrProberWrite(uint32_t uMsr, uint64_t uValue)
    236 {
    237     bool fGp;
    238     int rc = g_MsrAcc.pfnMsrWrite(uMsr, NIL_RTCPUID, uValue, &fGp);
    239     AssertRC(rc);
    240     return RT_SUCCESS(rc) && !fGp;
    241 }
    242 #endif
    243 
    244 
    245 static bool msrProberRead(uint32_t uMsr, uint64_t *puValue)
    246 {
    247     *puValue = 0;
    248     bool fGp;
    249     int rc = g_MsrAcc.pfnMsrProberRead(uMsr, NIL_RTCPUID, puValue, &fGp);
    250     AssertRC(rc);
    251     return RT_SUCCESS(rc) && !fGp;
    252 }
    253 
    254 
    255 /** Tries to modify the register by writing the original value to it. */
    256 static bool msrProberModifyNoChange(uint32_t uMsr)
    257 {
    258     SUPMSRPROBERMODIFYRESULT Result;
    259     int rc = g_MsrAcc.pfnMsrProberModify(uMsr, NIL_RTCPUID, UINT64_MAX, 0, &Result);
    260     return RT_SUCCESS(rc)
    261         && !Result.fBeforeGp
    262         && !Result.fModifyGp
    263         && !Result.fAfterGp
    264         && !Result.fRestoreGp;
    265 }
    266 
    267 
    268 /** Tries to modify the register by writing zero to it. */
    269 static bool msrProberModifyZero(uint32_t uMsr)
    270 {
    271     SUPMSRPROBERMODIFYRESULT Result;
    272     int rc = g_MsrAcc.pfnMsrProberModify(uMsr, NIL_RTCPUID, 0, 0, &Result);
    273     return RT_SUCCESS(rc)
    274         && !Result.fBeforeGp
    275         && !Result.fModifyGp
    276         && !Result.fAfterGp
    277         && !Result.fRestoreGp;
    278 }
    279 
    280 
    281 /**
    282  * Tries to modify each bit in the MSR and see if we can make it change.
    283  *
    284  * @returns VBox status code.
    285  * @param   uMsr                The MSR.
    286  * @param   pfIgnMask           The ignore mask to update.
    287  * @param   pfGpMask            The GP mask to update.
    288  * @param   fSkipMask           Mask of bits to skip.
    289  */
    290 static int msrProberModifyBitChanges(uint32_t uMsr, uint64_t *pfIgnMask, uint64_t *pfGpMask, uint64_t fSkipMask)
    291 {
    292     for (unsigned iBit = 0; iBit < 64; iBit++)
    293     {
    294         uint64_t fBitMask = RT_BIT_64(iBit);
    295         if (fBitMask & fSkipMask)
    296             continue;
    297 
    298         /* Set it. */
    299         SUPMSRPROBERMODIFYRESULT ResultSet;
    300         int rc = g_MsrAcc.pfnMsrProberModify(uMsr, NIL_RTCPUID, ~fBitMask, fBitMask, &ResultSet);
    301         if (RT_FAILURE(rc))
    302             return RTMsgErrorRc(rc, "pfnMsrProberModify(%#x,,%#llx,%#llx,): %Rrc", uMsr, ~fBitMask, fBitMask, rc);
    303 
    304         /* Clear it. */
    305         SUPMSRPROBERMODIFYRESULT ResultClear;
    306         rc = g_MsrAcc.pfnMsrProberModify(uMsr, NIL_RTCPUID, ~fBitMask, 0, &ResultClear);
    307         if (RT_FAILURE(rc))
    308             return RTMsgErrorRc(rc, "pfnMsrProberModify(%#x,,%#llx,%#llx,): %Rrc", uMsr, ~fBitMask, 0, rc);
    309 
    310         if (ResultSet.fModifyGp || ResultClear.fModifyGp)
    311             *pfGpMask |= fBitMask;
    312         else if (   (   ((ResultSet.uBefore   ^ ResultSet.uAfter)   & fBitMask) == 0
    313                      && !ResultSet.fBeforeGp
    314                      && !ResultSet.fAfterGp)
    315                  && (   ((ResultClear.uBefore ^ ResultClear.uAfter) & fBitMask) == 0
    316                      && !ResultClear.fBeforeGp
    317                      && !ResultClear.fAfterGp) )
    318             *pfIgnMask |= fBitMask;
    319     }
    320 
    321     return VINF_SUCCESS;
    322 }
    323 
    324 
    325 #if 0 /* currently unused */
    326 /**
    327  * Tries to modify one bit.
    328  *
    329  * @retval  -2 on API error.
    330  * @retval  -1 on \#GP.
    331  * @retval  0 if ignored.
    332  * @retval  1 if it changed.
    333  *
    334  * @param   uMsr                The MSR.
    335  * @param   iBit                The bit to try modify.
    336  */
    337 static int msrProberModifyBit(uint32_t uMsr, unsigned iBit)
    338 {
    339     uint64_t fBitMask = RT_BIT_64(iBit);
    340 
    341     /* Set it. */
    342     SUPMSRPROBERMODIFYRESULT ResultSet;
    343     int rc = g_MsrAcc.pfnMsrProberModify(uMsr, NIL_RTCPUID, ~fBitMask, fBitMask, &ResultSet);
    344     if (RT_FAILURE(rc))
    345         return RTMsgErrorRc(-2, "pfnMsrProberModify(%#x,,%#llx,%#llx,): %Rrc", uMsr, ~fBitMask, fBitMask, rc);
    346 
    347     /* Clear it. */
    348     SUPMSRPROBERMODIFYRESULT ResultClear;
    349     rc = g_MsrAcc.pfnMsrProberModify(uMsr, NIL_RTCPUID, ~fBitMask, 0, &ResultClear);
    350     if (RT_FAILURE(rc))
    351         return RTMsgErrorRc(-2, "pfnMsrProberModify(%#x,,%#llx,%#llx,): %Rrc", uMsr, ~fBitMask, 0, rc);
    352 
    353     if (ResultSet.fModifyGp || ResultClear.fModifyGp)
    354         return -1;
    355 
    356     if (   (   ((ResultSet.uBefore   ^ ResultSet.uAfter)   & fBitMask) != 0
    357             && !ResultSet.fBeforeGp
    358             && !ResultSet.fAfterGp)
    359         || (   ((ResultClear.uBefore ^ ResultClear.uAfter) & fBitMask) != 0
    360             && !ResultClear.fBeforeGp
    361             && !ResultClear.fAfterGp) )
    362         return 1;
    363 
    364     return 0;
    365 }
    366 #endif
    367 
    368 
    369 /**
    370  * Tries to do a simple AND+OR change and see if we \#GP or not.
    371  *
    372  * @retval  @c true if successfully modified.
    373  * @retval  @c false if \#GP or other error.
    374  *
    375  * @param   uMsr                The MSR.
    376  * @param   fAndMask            The AND mask.
    377  * @param   fOrMask             The OR mask.
    378  */
    379 static bool msrProberModifySimpleGp(uint32_t uMsr, uint64_t fAndMask, uint64_t fOrMask)
    380 {
    381     SUPMSRPROBERMODIFYRESULT Result;
    382     int rc = g_MsrAcc.pfnMsrProberModify(uMsr, NIL_RTCPUID, fAndMask, fOrMask, &Result);
    383     if (RT_FAILURE(rc))
    384     {
    385         RTMsgError("g_MsrAcc.pfnMsrProberModify(%#x,,%#llx,%#llx,): %Rrc", uMsr, fAndMask, fOrMask, rc);
    386         return false;
    387     }
    388     return !Result.fBeforeGp
    389         && !Result.fModifyGp
    390         && !Result.fAfterGp
    391         && !Result.fRestoreGp;
    392 }
    393 
    394 
    395 
    396 
    397 /**
    398  * Combination of the basic tests.
    399  *
    400  * @returns VBox status code.
    401  * @param   uMsr                The MSR.
    402  * @param   fSkipMask           Mask of bits to skip.
    403  * @param   pfReadOnly          Where to return read-only status.
    404  * @param   pfIgnMask           Where to return the write ignore mask.  Need not
    405  *                              be initialized.
    406  * @param   pfGpMask            Where to return the write GP mask.  Need not
    407  *                              be initialized.
    408  */
    409 static int msrProberModifyBasicTests(uint32_t uMsr, uint64_t fSkipMask, bool *pfReadOnly, uint64_t *pfIgnMask, uint64_t *pfGpMask)
    410 {
    411     if (msrProberModifyNoChange(uMsr))
    412     {
    413         *pfReadOnly = false;
    414         *pfIgnMask  = 0;
    415         *pfGpMask  = 0;
    416         return msrProberModifyBitChanges(uMsr, pfIgnMask, pfGpMask, fSkipMask);
    417     }
    418 
    419     *pfReadOnly = true;
    420     *pfIgnMask  = 0;
    421     *pfGpMask   = UINT64_MAX;
    422     return VINF_SUCCESS;
    423 }
    424 
    425 
    426 
    427 /**
    428  * Determines for the MSR AND mask.
    429  *
    430  * Older CPUs doesn't necessiarly implement all bits of the MSR register number.
    431  * So, we have to approximate how many are used so we don't get an overly large
    432  * and confusing set of MSRs when probing.
    433  *
    434  * @returns The mask.
    435  */
    436 static uint32_t determineMsrAndMask(void)
    437 {
    438 #define VBCPUREP_MASK_TEST_MSRS     7
    439     static uint32_t const s_aMsrs[VBCPUREP_MASK_TEST_MSRS] =
    440     {
    441         /* Try a bunch of mostly read only registers: */
    442         MSR_P5_MC_TYPE, MSR_IA32_PLATFORM_ID, MSR_IA32_MTRR_CAP, MSR_IA32_MCG_CAP, MSR_IA32_CR_PAT,
    443         /* Then some which aren't supposed to be present on any CPU: */
    444         0x00000015, 0x00000019,
    445     };
    446 
    447     /* Get the base values. */
    448     uint64_t auBaseValues[VBCPUREP_MASK_TEST_MSRS];
    449     for (unsigned i = 0; i < RT_ELEMENTS(s_aMsrs); i++)
    450     {
    451         if (!msrProberRead(s_aMsrs[i], &auBaseValues[i]))
    452             auBaseValues[i] = UINT64_MAX;
    453         //vbCpuRepDebug("Base: %#x -> %#llx\n", s_aMsrs[i], auBaseValues[i]);
    454     }
    455 
    456     /* Do the probing. */
    457     unsigned iBit;
    458     for (iBit = 31; iBit > 8; iBit--)
    459     {
    460         uint64_t fMsrOrMask = RT_BIT_64(iBit);
    461         for (unsigned iTest = 0; iTest <= 64 && fMsrOrMask < UINT32_MAX; iTest++)
    462         {
    463             for (unsigned i = 0; i < RT_ELEMENTS(s_aMsrs); i++)
    464             {
    465                 uint64_t uValue;
    466                 if (!msrProberRead(s_aMsrs[i] | fMsrOrMask, &uValue))
    467                     uValue = UINT64_MAX;
    468                 if (uValue != auBaseValues[i])
    469                 {
    470                     uint32_t fMsrMask = iBit >= 31 ? UINT32_MAX : RT_BIT_32(iBit + 1) - 1;
    471                     vbCpuRepDebug("MSR AND mask: quit on iBit=%u uMsr=%#x (%#x) %llx != %llx => fMsrMask=%#x\n",
    472                                   iBit, s_aMsrs[i] | (uint32_t)fMsrOrMask, s_aMsrs[i], uValue, auBaseValues[i], fMsrMask);
    473                     return fMsrMask;
    474                 }
    475             }
    476 
    477             /* Advance. */
    478             if (iBit <= 6)
    479                 fMsrOrMask += RT_BIT_64(iBit);
    480             else if (iBit <= 11)
    481                 fMsrOrMask += RT_BIT_64(iBit) * 33;
    482             else if (iBit <= 16)
    483                 fMsrOrMask += RT_BIT_64(iBit) * 1025;
    484             else if (iBit <= 22)
    485                 fMsrOrMask += RT_BIT_64(iBit) * 65537;
    486             else
    487                 fMsrOrMask += RT_BIT_64(iBit) * 262145;
    488         }
    489     }
    490 
    491     uint32_t fMsrMask = RT_BIT_32(iBit + 1) - 1;
    492     vbCpuRepDebug("MSR AND mask: less that %u bits that matters?!? => fMsrMask=%#x\n", iBit + 1, fMsrMask);
    493     return fMsrMask;
    494 }
    495 
    496 
    497 static int findMsrs(VBCPUREPMSR **ppaMsrs, uint32_t *pcMsrs, uint32_t fMsrMask)
    498 {
    499     /*
    500      * Gather them.
    501      */
    502     static struct { uint32_t uFirst, cMsrs; } const s_aRanges[] =
    503     {
    504         { 0x00000000, 0x00042000 },
    505         { 0x10000000, 0x00001000 },
    506         { 0x20000000, 0x00001000 },
    507         { 0x40000000, 0x00012000 },
    508         { 0x80000000, 0x00012000 },
    509         { 0xc0000000, 0x00022000 }, /* Had some trouble here on solaris with the tstVMM setup. */
    510     };
    511 
    512     *pcMsrs  = 0;
    513     *ppaMsrs = NULL;
    514 
    515     for (unsigned i = 0; i < RT_ELEMENTS(s_aRanges); i++)
    516     {
    517         uint32_t uMsr  = s_aRanges[i].uFirst;
    518         if ((uMsr & fMsrMask) != uMsr)
    519             continue;
    520         uint32_t cLeft = s_aRanges[i].cMsrs;
    521         while (cLeft-- > 0 && (uMsr & fMsrMask) == uMsr)
    522         {
    523             if ((uMsr & 0xfff) == 0)
    524             {
    525                 vbCpuRepDebug("testing %#x...\n", uMsr);
    526                 RTThreadSleep(22);
    527             }
    528 #if 0
    529             else if (uMsr >= 0x00003170 && uMsr <= 0xc0000090)
    530             {
    531                 vbCpuRepDebug("testing %#x...\n", uMsr);
    532                 RTThreadSleep(250);
    533             }
    534 #endif
    535             /* Skip 0xc0011012..13 as it seems to be bad for our health (Phenom II X6 1100T). */
    536             /* Ditto for 0x0000002ff (MSR_IA32_MTRR_DEF_TYPE) on AMD (Ryzen 7 1800X). */
    537             /* Ditto for 0x0000002a (EBL_CR_POWERON) and 0x00000277 (MSR_IA32_CR_PAT) on Intel (Atom 330). */
    538             /* And more of the same for 0x280 on Intel Pentium III. */
    539             if (   ((uMsr >= 0xc0011012 && uMsr <= 0xc0011013) && (g_enmVendor == CPUMCPUVENDOR_AMD || g_enmVendor == CPUMCPUVENDOR_HYGON))
    540                 || (   uMsr == 0x2ff
    541                     && (g_enmVendor == CPUMCPUVENDOR_AMD || g_enmVendor == CPUMCPUVENDOR_HYGON)
    542                     && g_enmMicroarch >= kCpumMicroarch_AMD_Zen_First)
    543                 || (   (uMsr == 0x2a || uMsr == 0x277)
    544                     && g_enmVendor == CPUMCPUVENDOR_INTEL
    545                     && g_enmMicroarch == kCpumMicroarch_Intel_Atom_Bonnell)
    546                 || (   (uMsr == 0x280)
    547                     && g_enmMicroarch == kCpumMicroarch_Intel_P6_III))
    548                 vbCpuRepDebug("Skipping %#x\n", uMsr);
    549             else
    550             {
    551                 /* Read probing normally does it. */
    552                 uint64_t uValue = 0;
    553                 bool     fGp    = true;
    554                 int rc = g_MsrAcc.pfnMsrProberRead(uMsr, NIL_RTCPUID, &uValue, &fGp);
    555                 if (RT_FAILURE(rc))
    556                 {
    557                     RTMemFree(*ppaMsrs);
    558                     *ppaMsrs = NULL;
    559                     return RTMsgErrorRc(rc, "pfnMsrProberRead failed on %#x: %Rrc\n", uMsr, rc);
    560                 }
    561 
    562                 uint32_t fFlags;
    563                 if (!fGp)
    564                     fFlags = 0;
    565                 /* VIA/Shanghai HACK - writing to 0x0000317e on a quad core make the core unresponsive. */
    566                 else if (uMsr == 0x0000317e && (g_enmVendor == CPUMCPUVENDOR_VIA || g_enmVendor == CPUMCPUVENDOR_SHANGHAI))
    567                 {
    568                     uValue = 0;
    569                     fFlags = VBCPUREPMSR_F_WRITE_ONLY;
    570                     fGp    = *pcMsrs == 0
    571                           || (*ppaMsrs)[*pcMsrs - 1].uMsr != 0x0000317d
    572                           || (*ppaMsrs)[*pcMsrs - 1].fFlags != VBCPUREPMSR_F_WRITE_ONLY;
    573                 }
    574                 else
    575                 {
    576                     /* Is it a write only register? */
    577 #if 0
    578                     if (uMsr >= 0x00003170 && uMsr <= 0xc0000090)
    579                     {
    580                         vbCpuRepDebug("test writing %#x...\n", uMsr);
    581                         RTThreadSleep(250);
    582                     }
    583 #endif
    584                     fGp = true;
    585                     rc = g_MsrAcc.pfnMsrProberWrite(uMsr, NIL_RTCPUID, 0, &fGp);
    586                     if (RT_FAILURE(rc))
    587                     {
    588                         RTMemFree(*ppaMsrs);
    589                         *ppaMsrs = NULL;
    590                         return RTMsgErrorRc(rc, "pfnMsrProberWrite failed on %#x: %Rrc\n", uMsr, rc);
    591                     }
    592                     uValue = 0;
    593                     fFlags = VBCPUREPMSR_F_WRITE_ONLY;
    594 
    595                     /*
    596                      * Tweaks.  On Intel CPUs we've got trouble detecting
    597                      * IA32_BIOS_UPDT_TRIG (0x00000079), so we have to add it manually here.
    598                      * Ditto on AMD with PATCH_LOADER (0xc0010020).
    599                      */
    600                     if (   uMsr == 0x00000079
    601                         && fGp
    602                         && g_enmMicroarch >= kCpumMicroarch_Intel_P6_Core_Atom_First
    603                         && g_enmMicroarch <= kCpumMicroarch_Intel_End)
    604                         fGp = false;
    605                     if (   uMsr == 0xc0010020
    606                         && fGp
    607                         && g_enmMicroarch >= kCpumMicroarch_AMD_K8_First
    608                         && g_enmMicroarch <= kCpumMicroarch_AMD_End)
    609                         fGp = false;
    610                 }
    611 
    612                 if (!fGp)
    613                 {
    614                     /* Add it. */
    615                     rc = vbCpuRepMsrsAddOne(ppaMsrs, pcMsrs, uMsr, uValue, fFlags);
    616                     if (RT_FAILURE(rc))
    617                         return RTMsgErrorRc(rc, "Out of memory (uMsr=%#x).\n", uMsr);
    618                     if (   (g_enmVendor != CPUMCPUVENDOR_VIA && g_enmVendor != CPUMCPUVENDOR_SHANGHAI)
    619                         || uValue
    620                         || fFlags)
    621                         vbCpuRepDebug("%#010x: uValue=%#llx fFlags=%#x\n", uMsr, uValue, fFlags);
    622                 }
    623             }
    624 
    625             uMsr++;
    626         }
    627     }
    628 
    629     return VINF_SUCCESS;
    630 }
    631 
    632 /**
    633  * Get the name of the specified MSR, if we know it and can handle it.
    634  *
    635  * Do _NOT_ add any new names here without ALSO at the SAME TIME making sure it
    636  * is handled correctly by the PROBING CODE and REPORTED correctly!!
    637  *
    638  * @returns Pointer to name if handled, NULL if not yet explored.
    639  * @param   uMsr                The MSR in question.
    640  */
    641 static const char *getMsrNameHandled(uint32_t uMsr)
    642 {
    643     /** @todo figure out where NCU_EVENT_CORE_MASK might be... */
    644     switch (uMsr)
    645     {
    646         case 0x00000000: return "IA32_P5_MC_ADDR";
    647         case 0x00000001: return "IA32_P5_MC_TYPE";
    648         case 0x00000006:
    649             if (g_enmMicroarch >= kCpumMicroarch_Intel_First && g_enmMicroarch <= kCpumMicroarch_Intel_P6_Core_Atom_First)
    650                 return NULL; /* TR4 / cache tag on Pentium, but that's for later. */
    651             return "IA32_MONITOR_FILTER_LINE_SIZE";
    652         //case 0x0000000e: return "P?_TR12"; /* K6-III docs */
    653         case 0x00000010: return "IA32_TIME_STAMP_COUNTER";
    654         case 0x00000017: return "IA32_PLATFORM_ID";
    655         case 0x00000018: return "P6_UNK_0000_0018"; /* P6_M_Dothan. */
    656         case 0x0000001b: return "IA32_APIC_BASE";
    657         case 0x00000021: return "C2_UNK_0000_0021"; /* Core2_Penryn */
    658         case 0x0000002a: return g_fIntelNetBurst ? "P4_EBC_HARD_POWERON" : "EBL_CR_POWERON";
    659         case 0x0000002b: return g_fIntelNetBurst ? "P4_EBC_SOFT_POWERON" : NULL;
    660         case 0x0000002c: return g_fIntelNetBurst ? "P4_EBC_FREQUENCY_ID" : NULL;
    661         case 0x0000002e: return "I7_UNK_0000_002e"; /* SandyBridge, IvyBridge. */
    662         case 0x0000002f: return "P6_UNK_0000_002f"; /* P6_M_Dothan. */
    663         case 0x00000032: return "P6_UNK_0000_0032"; /* P6_M_Dothan. */
    664         case 0x00000033: return "TEST_CTL";
    665         case 0x00000034: return CPUMMICROARCH_IS_INTEL_CORE7(g_enmMicroarch)
    666                              || CPUMMICROARCH_IS_INTEL_SILVERMONT_PLUS(g_enmMicroarch)
    667                               ? "MSR_SMI_COUNT" : "P6_UNK_0000_0034"; /* P6_M_Dothan. */
    668         case 0x00000035: return CPUMMICROARCH_IS_INTEL_CORE7(g_enmMicroarch) ? "MSR_CORE_THREAD_COUNT" : "P6_UNK_0000_0035"; /* P6_M_Dothan. */
    669         case 0x00000036: return "I7_UNK_0000_0036"; /* SandyBridge, IvyBridge. */
    670         case 0x00000039: return "C2_UNK_0000_0039"; /* Core2_Penryn */
    671         case 0x0000003a: return "IA32_FEATURE_CONTROL";
    672         case 0x0000003b: return "P6_UNK_0000_003b"; /* P6_M_Dothan. */
    673         case 0x0000003e: return "I7_UNK_0000_003e"; /* SandyBridge, IvyBridge. */
    674         case 0x0000003f: return "P6_UNK_0000_003f"; /* P6_M_Dothan. */
    675         case 0x00000040: return g_enmMicroarch >= kCpumMicroarch_Intel_Core_Yonah ? "MSR_LASTBRANCH_0_FROM_IP" : "MSR_LASTBRANCH_0";
    676         case 0x00000041: return g_enmMicroarch >= kCpumMicroarch_Intel_Core_Yonah ? "MSR_LASTBRANCH_1_FROM_IP" : "MSR_LASTBRANCH_1";
    677         case 0x00000042: return g_enmMicroarch >= kCpumMicroarch_Intel_Core_Yonah ? "MSR_LASTBRANCH_2_FROM_IP" : "MSR_LASTBRANCH_2";
    678         case 0x00000043: return g_enmMicroarch >= kCpumMicroarch_Intel_Core_Yonah ? "MSR_LASTBRANCH_3_FROM_IP" : "MSR_LASTBRANCH_3";
    679         case 0x00000044: return g_enmMicroarch >= kCpumMicroarch_Intel_Core_Yonah ? "MSR_LASTBRANCH_4_FROM_IP" : "MSR_LASTBRANCH_4";
    680         case 0x00000045: return g_enmMicroarch >= kCpumMicroarch_Intel_Core_Yonah ? "MSR_LASTBRANCH_5_FROM_IP" : "MSR_LASTBRANCH_5";
    681         case 0x00000046: return g_enmMicroarch >= kCpumMicroarch_Intel_Core_Yonah ? "MSR_LASTBRANCH_6_FROM_IP" : "MSR_LASTBRANCH_6";
    682         case 0x00000047: return g_enmMicroarch >= kCpumMicroarch_Intel_Core_Yonah ? "MSR_LASTBRANCH_7_FROM_IP" : "MSR_LASTBRANCH_7";
    683         case 0x00000048: return "MSR_LASTBRANCH_8"; /*??*/
    684         case 0x00000049: return "MSR_LASTBRANCH_9"; /*??*/
    685         case 0x0000004a: return "P6_UNK_0000_004a"; /* P6_M_Dothan. */
    686         case 0x0000004b: return "P6_UNK_0000_004b"; /* P6_M_Dothan. */
    687         case 0x0000004c: return "P6_UNK_0000_004c"; /* P6_M_Dothan. */
    688         case 0x0000004d: return "P6_UNK_0000_004d"; /* P6_M_Dothan. */
    689         case 0x0000004e: return "P6_UNK_0000_004e"; /* P6_M_Dothan. */
    690         case 0x0000004f: return "P6_UNK_0000_004f"; /* P6_M_Dothan. */
    691         case 0x00000050: return "P6_UNK_0000_0050"; /* P6_M_Dothan. */
    692         case 0x00000051: return "P6_UNK_0000_0051"; /* P6_M_Dothan. */
    693         case 0x00000052: return "P6_UNK_0000_0052"; /* P6_M_Dothan. */
    694         case 0x00000053: return "P6_UNK_0000_0053"; /* P6_M_Dothan. */
    695         case 0x00000054: return "P6_UNK_0000_0054"; /* P6_M_Dothan. */
    696         case 0x00000060: return "MSR_LASTBRANCH_0_TO_IP"; /* Core2_Penryn */
    697         case 0x00000061: return "MSR_LASTBRANCH_1_TO_IP"; /* Core2_Penryn */
    698         case 0x00000062: return "MSR_LASTBRANCH_2_TO_IP"; /* Core2_Penryn */
    699         case 0x00000063: return "MSR_LASTBRANCH_3_TO_IP"; /* Core2_Penryn */
    700         case 0x00000064: return "MSR_LASTBRANCH_4_TO_IP"; /* Atom? */
    701         case 0x00000065: return "MSR_LASTBRANCH_5_TO_IP";
    702         case 0x00000066: return "MSR_LASTBRANCH_6_TO_IP";
    703         case 0x00000067: return "MSR_LASTBRANCH_7_TO_IP";
    704         case 0x0000006c: return "P6_UNK_0000_006c"; /* P6_M_Dothan. */
    705         case 0x0000006d: return "P6_UNK_0000_006d"; /* P6_M_Dothan. */
    706         case 0x0000006e: return "P6_UNK_0000_006e"; /* P6_M_Dothan. */
    707         case 0x0000006f: return "P6_UNK_0000_006f"; /* P6_M_Dothan. */
    708         case 0x00000079: return "IA32_BIOS_UPDT_TRIG";
    709         case 0x00000080: return "P4_UNK_0000_0080";
    710         case 0x00000088: return "BBL_CR_D0";
    711         case 0x00000089: return "BBL_CR_D1";
    712         case 0x0000008a: return "BBL_CR_D2";
    713         case 0x0000008b: return g_enmVendor == CPUMCPUVENDOR_AMD || g_enmVendor == CPUMCPUVENDOR_HYGON ? "AMD_K8_PATCH_LEVEL"
    714                               : g_fIntelNetBurst ? "IA32_BIOS_SIGN_ID" : "BBL_CR_D3|BIOS_SIGN";
    715         case 0x0000008c: return "P6_UNK_0000_008c"; /* P6_M_Dothan. */
    716         case 0x0000008d: return "P6_UNK_0000_008d"; /* P6_M_Dothan. */
    717         case 0x0000008e: return "P6_UNK_0000_008e"; /* P6_M_Dothan. */
    718         case 0x0000008f: return "P6_UNK_0000_008f"; /* P6_M_Dothan. */
    719         case 0x00000090: return "P6_UNK_0000_0090"; /* P6_M_Dothan. */
    720         case 0x0000009b: return "IA32_SMM_MONITOR_CTL";
    721         case 0x000000a8: return "C2_EMTTM_CR_TABLES_0";
    722         case 0x000000a9: return "C2_EMTTM_CR_TABLES_1";
    723         case 0x000000aa: return "C2_EMTTM_CR_TABLES_2";
    724         case 0x000000ab: return "C2_EMTTM_CR_TABLES_3";
    725         case 0x000000ac: return "C2_EMTTM_CR_TABLES_4";
    726         case 0x000000ad: return "C2_EMTTM_CR_TABLES_5";
    727         case 0x000000ae: return "P6_UNK_0000_00ae"; /* P6_M_Dothan. */
    728         case 0x000000c1: return "IA32_PMC0";
    729         case 0x000000c2: return "IA32_PMC1";
    730         case 0x000000c3: return "IA32_PMC2";
    731         case 0x000000c4: return "IA32_PMC3";
    732         /* PMC4+ first seen on SandyBridge. The earlier cut off is just to be
    733            on the safe side as we must avoid P6_M_Dothan and possibly others. */
    734         case 0x000000c5: return g_enmMicroarch >= kCpumMicroarch_Intel_Core7_First ? "IA32_PMC4" : NULL;
    735         case 0x000000c6: return g_enmMicroarch >= kCpumMicroarch_Intel_Core7_First ? "IA32_PMC5" : NULL;
    736         case 0x000000c7: return g_enmMicroarch >= kCpumMicroarch_Intel_Core7_First ? "IA32_PMC6" : "P6_UNK_0000_00c7"; /* P6_M_Dothan. */
    737         case 0x000000c8: return g_enmMicroarch >= kCpumMicroarch_Intel_Core7_First ? "IA32_PMC7" : NULL;
    738         case 0x000000cd: return "MSR_FSB_FREQ"; /* P6_M_Dothan. */
    739         case 0x000000ce: return g_enmMicroarch >= kCpumMicroarch_Intel_Core7_First ? "IA32_PLATFORM_INFO" : "P6_UNK_0000_00ce"; /* P6_M_Dothan. */
    740         case 0x000000cf: return "C2_UNK_0000_00cf"; /* Core2_Penryn. */
    741         case 0x000000e0: return "C2_UNK_0000_00e0"; /* Core2_Penryn. */
    742         case 0x000000e1: return "C2_UNK_0000_00e1"; /* Core2_Penryn. */
    743         case 0x000000e2: return "MSR_PKG_CST_CONFIG_CONTROL";
    744         case 0x000000e3: return "C2_SMM_CST_MISC_INFO"; /* Core2_Penryn. */
    745         case 0x000000e4: return "MSR_PMG_IO_CAPTURE_BASE";
    746         case 0x000000e5: return "C2_UNK_0000_00e5"; /* Core2_Penryn. */
    747         case 0x000000e7: return "IA32_MPERF";
    748         case 0x000000e8: return "IA32_APERF";
    749         case 0x000000ee: return "C1_EXT_CONFIG"; /* Core2_Penryn. msrtool lists it for Core1 as well. */
    750         case 0x000000fe: return "IA32_MTRRCAP";
    751         case 0x00000102: return "I7_IB_UNK_0000_0102"; /* IvyBridge. */
    752         case 0x00000103: return "I7_IB_UNK_0000_0103"; /* IvyBridge. */
    753         case 0x00000104: return "I7_IB_UNK_0000_0104"; /* IvyBridge. */
    754         case 0x00000116: return "BBL_CR_ADDR";
    755         case 0x00000118: return "BBL_CR_DECC";
    756         case 0x00000119: return "BBL_CR_CTL";
    757         case 0x0000011a: return "BBL_CR_TRIG";
    758         case 0x0000011b: return "P6_UNK_0000_011b"; /* P6_M_Dothan. */
    759         case 0x0000011c: return "C2_UNK_0000_011c"; /* Core2_Penryn. */
    760         case 0x0000011e: return "BBL_CR_CTL3";
    761         case 0x00000120: return "SILV_UNK_0000_0120"; /* Silvermont */
    762         case 0x00000130: return g_enmMicroarch == kCpumMicroarch_Intel_Core7_Westmere
    763                              || g_enmMicroarch == kCpumMicroarch_Intel_Core7_Nehalem
    764                               ? "CPUID1_FEATURE_MASK" : NULL;
    765         case 0x00000131: return g_enmMicroarch == kCpumMicroarch_Intel_Core7_Westmere
    766                              || g_enmMicroarch == kCpumMicroarch_Intel_Core7_Nehalem
    767                               ? "CPUID80000001_FEATURE_MASK" : "P6_UNK_0000_0131" /* P6_M_Dothan. */;
    768         case 0x00000132: return g_enmMicroarch >= kCpumMicroarch_Intel_Core7_SandyBridge
    769                               ? "CPUID1_FEATURE_MASK" : NULL;
    770         case 0x00000133: return g_enmMicroarch >= kCpumMicroarch_Intel_Core7_SandyBridge
    771                               ? "CPUIDD_01_FEATURE_MASK" : NULL;
    772         case 0x00000134: return g_enmMicroarch >= kCpumMicroarch_Intel_Core7_SandyBridge
    773                               ? "CPUID80000001_FEATURE_MASK" : NULL;
    774         case 0x0000013c: return "I7_SB_AES_NI_CTL"; /* SandyBridge. Bit 0 is lock bit, bit 1 disables AES-NI. */
    775         case 0x00000140: return "I7_IB_UNK_0000_0140"; /* IvyBridge. */
    776         case 0x00000142: return "I7_IB_UNK_0000_0142"; /* IvyBridge. */
    777         case 0x0000014e: return "P6_UNK_0000_014e"; /* P6_M_Dothan. */
    778         case 0x0000014f: return "P6_UNK_0000_014f"; /* P6_M_Dothan. */
    779         case 0x00000150: return "P6_UNK_0000_0150"; /* P6_M_Dothan. */
    780         case 0x00000151: return "P6_UNK_0000_0151"; /* P6_M_Dothan. */
    781         case 0x00000154: return "P6_UNK_0000_0154"; /* P6_M_Dothan. */
    782         case 0x0000015b: return "P6_UNK_0000_015b"; /* P6_M_Dothan. */
    783         case 0x0000015e: return "C2_UNK_0000_015e"; /* Core2_Penryn. */
    784         case 0x0000015f: return "C1_DTS_CAL_CTRL"; /* Core2_Penryn. msrtool only docs this for core1! */
    785         case 0x00000174: return "IA32_SYSENTER_CS";
    786         case 0x00000175: return "IA32_SYSENTER_ESP";
    787         case 0x00000176: return "IA32_SYSENTER_EIP";
    788         case 0x00000179: return "IA32_MCG_CAP";
    789         case 0x0000017a: return "IA32_MCG_STATUS";
    790         case 0x0000017b: return "IA32_MCG_CTL";
    791         case 0x0000017f: return "I7_SB_ERROR_CONTROL"; /* SandyBridge. */
    792         case 0x00000180: return g_fIntelNetBurst ? "MSR_MCG_RAX"       : NULL;
    793         case 0x00000181: return g_fIntelNetBurst ? "MSR_MCG_RBX"       : NULL;
    794         case 0x00000182: return g_fIntelNetBurst ? "MSR_MCG_RCX"       : NULL;
    795         case 0x00000183: return g_fIntelNetBurst ? "MSR_MCG_RDX"       : NULL;
    796         case 0x00000184: return g_fIntelNetBurst ? "MSR_MCG_RSI"       : NULL;
    797         case 0x00000185: return g_fIntelNetBurst ? "MSR_MCG_RDI"       : NULL;
    798         case 0x00000186: return g_fIntelNetBurst ? "MSR_MCG_RBP"       : "IA32_PERFEVTSEL0";
    799         case 0x00000187: return g_fIntelNetBurst ? "MSR_MCG_RSP"       : "IA32_PERFEVTSEL1";
    800         case 0x00000188: return g_fIntelNetBurst ? "MSR_MCG_RFLAGS"    : "IA32_PERFEVTSEL2";
    801         case 0x00000189: return g_fIntelNetBurst ? "MSR_MCG_RIP"       : "IA32_PERFEVTSEL3";
    802         case 0x0000018a: return g_fIntelNetBurst ? "MSR_MCG_MISC"      : "IA32_PERFEVTSEL4";
    803         case 0x0000018b: return g_fIntelNetBurst ? "MSR_MCG_RESERVED1" : "IA32_PERFEVTSEL5";
    804         case 0x0000018c: return g_fIntelNetBurst ? "MSR_MCG_RESERVED2" : "IA32_PERFEVTSEL6";
    805         case 0x0000018d: return g_fIntelNetBurst ? "MSR_MCG_RESERVED3" : "IA32_PERFEVTSEL7";
    806         case 0x0000018e: return g_fIntelNetBurst ? "MSR_MCG_RESERVED4" : "IA32_PERFEVTSEL8";
    807         case 0x0000018f: return g_fIntelNetBurst ? "MSR_MCG_RESERVED5" : "IA32_PERFEVTSEL9";
    808         case 0x00000190: return g_fIntelNetBurst ? "MSR_MCG_R8"        : NULL;
    809         case 0x00000191: return g_fIntelNetBurst ? "MSR_MCG_R9"        : NULL;
    810         case 0x00000192: return g_fIntelNetBurst ? "MSR_MCG_R10"       : NULL;
    811         case 0x00000193: return g_fIntelNetBurst ? "MSR_MCG_R11"       : "C2_UNK_0000_0193";
    812         case 0x00000194: return g_fIntelNetBurst ? "MSR_MCG_R12"       : "CLOCK_FLEX_MAX";
    813         case 0x00000195: return g_fIntelNetBurst ? "MSR_MCG_R13"       : NULL;
    814         case 0x00000196: return g_fIntelNetBurst ? "MSR_MCG_R14"       : NULL;
    815         case 0x00000197: return g_fIntelNetBurst ? "MSR_MCG_R15"       : NULL;
    816         case 0x00000198: return "IA32_PERF_STATUS";
    817         case 0x00000199: return "IA32_PERF_CTL";
    818         case 0x0000019a: return "IA32_CLOCK_MODULATION";
    819         case 0x0000019b: return "IA32_THERM_INTERRUPT";
    820         case 0x0000019c: return "IA32_THERM_STATUS";
    821         case 0x0000019d: return "IA32_THERM2_CTL";
    822         case 0x0000019e: return "P6_UNK_0000_019e"; /* P6_M_Dothan. */
    823         case 0x0000019f: return "P6_UNK_0000_019f"; /* P6_M_Dothan. */
    824         case 0x000001a0: return "IA32_MISC_ENABLE";
    825         case 0x000001a1: return g_fIntelNetBurst ? "MSR_PLATFORM_BRV" : "P6_UNK_0000_01a1" /* P6_M_Dothan. */;
    826         case 0x000001a2: return g_fIntelNetBurst ? "P4_UNK_0000_01a2" : "I7_MSR_TEMPERATURE_TARGET" /* SandyBridge, IvyBridge. */;
    827         case 0x000001a4: return "I7_UNK_0000_01a4"; /* SandyBridge, IvyBridge. */
    828         case 0x000001a6: return "I7_MSR_OFFCORE_RSP_0";
    829         case 0x000001a7: return "I7_MSR_OFFCORE_RSP_1";
    830         case 0x000001a8: return "I7_UNK_0000_01a8"; /* SandyBridge, IvyBridge. */
    831         case 0x000001aa: return CPUMMICROARCH_IS_INTEL_CORE7(g_enmMicroarch) ? "MSR_MISC_PWR_MGMT" : "P6_PIC_SENS_CFG" /* Pentium M. */;
    832         case 0x000001ad: return "I7_MSR_TURBO_RATIO_LIMIT"; /* SandyBridge+, Silvermount+ */
    833         case 0x000001ae: return "P6_UNK_0000_01ae"; /* P6_M_Dothan. */
    834         case 0x000001af: return "P6_UNK_0000_01af"; /* P6_M_Dothan. */
    835         case 0x000001b0: return "IA32_ENERGY_PERF_BIAS";
    836         case 0x000001b1: return "IA32_PACKAGE_THERM_STATUS";
    837         case 0x000001b2: return "IA32_PACKAGE_THERM_INTERRUPT";
    838         case 0x000001bf: return "C2_UNK_0000_01bf"; /* Core2_Penryn. */
    839         case 0x000001c6: return "I7_UNK_0000_01c6"; /* SandyBridge*/
    840         case 0x000001c8: return g_enmMicroarch >= kCpumMicroarch_Intel_Core7_Nehalem ? "MSR_LBR_SELECT" : NULL;
    841         case 0x000001c9: return    g_enmMicroarch >= kCpumMicroarch_Intel_Core_Yonah
    842                                 && g_enmMicroarch <= kCpumMicroarch_Intel_P6_Core_Atom_End
    843                               ? "MSR_LASTBRANCH_TOS" : NULL /* Pentium M Dothan seems to have something else here. */;
    844         case 0x000001d3: return "P6_UNK_0000_01d3"; /* P6_M_Dothan. */
    845         case 0x000001d7: return g_fIntelNetBurst ? "MSR_LER_FROM_LIP" : NULL;
    846         case 0x000001d8: return g_fIntelNetBurst ? "MSR_LER_TO_LIP"   : NULL;
    847         case 0x000001d9: return "IA32_DEBUGCTL";
    848         case 0x000001da: return g_fIntelNetBurst ? "MSR_LASTBRANCH_TOS" : NULL;
    849         case 0x000001db: return g_fIntelNetBurst ? "P6_LASTBRANCH_0" : "P6_LAST_BRANCH_FROM_IP"; /* Not exclusive to P6, also AMD. */
    850         case 0x000001dc: return g_fIntelNetBurst ? "P6_LASTBRANCH_1" : "P6_LAST_BRANCH_TO_IP";
    851         case 0x000001dd: return g_fIntelNetBurst ? "P6_LASTBRANCH_2" : "P6_LAST_INT_FROM_IP";
    852         case 0x000001de: return g_fIntelNetBurst ? "P6_LASTBRANCH_3" : "P6_LAST_INT_TO_IP";
    853         case 0x000001e0: return "MSR_ROB_CR_BKUPTMPDR6";
    854         case 0x000001e1: return "I7_SB_UNK_0000_01e1";
    855         case 0x000001ef: return "I7_SB_UNK_0000_01ef";
    856         case 0x000001f0: return "I7_VLW_CAPABILITY"; /* SandyBridge.  Bit 1 is A20M and was implemented incorrectly (AAJ49). */
    857         case 0x000001f2: return "IA32_SMRR_PHYSBASE";
    858         case 0x000001f3: return "IA32_SMRR_PHYSMASK";
    859         case 0x000001f8: return "IA32_PLATFORM_DCA_CAP";
    860         case 0x000001f9: return "IA32_CPU_DCA_CAP";
    861         case 0x000001fa: return "IA32_DCA_0_CAP";
    862         case 0x000001fc: return "I7_MSR_POWER_CTL";
    863 
    864         case 0x00000200: return "IA32_MTRR_PHYS_BASE0";
    865         case 0x00000202: return "IA32_MTRR_PHYS_BASE1";
    866         case 0x00000204: return "IA32_MTRR_PHYS_BASE2";
    867         case 0x00000206: return "IA32_MTRR_PHYS_BASE3";
    868         case 0x00000208: return "IA32_MTRR_PHYS_BASE4";
    869         case 0x0000020a: return "IA32_MTRR_PHYS_BASE5";
    870         case 0x0000020c: return "IA32_MTRR_PHYS_BASE6";
    871         case 0x0000020e: return "IA32_MTRR_PHYS_BASE7";
    872         case 0x00000210: return "IA32_MTRR_PHYS_BASE8";
    873         case 0x00000212: return "IA32_MTRR_PHYS_BASE9";
    874         case 0x00000214: return "IA32_MTRR_PHYS_BASE10";
    875         case 0x00000216: return "IA32_MTRR_PHYS_BASE11";
    876         case 0x00000218: return "IA32_MTRR_PHYS_BASE12";
    877         case 0x0000021a: return "IA32_MTRR_PHYS_BASE13";
    878         case 0x0000021c: return "IA32_MTRR_PHYS_BASE14";
    879         case 0x0000021e: return "IA32_MTRR_PHYS_BASE15";
    880 
    881         case 0x00000201: return "IA32_MTRR_PHYS_MASK0";
    882         case 0x00000203: return "IA32_MTRR_PHYS_MASK1";
    883         case 0x00000205: return "IA32_MTRR_PHYS_MASK2";
    884         case 0x00000207: return "IA32_MTRR_PHYS_MASK3";
    885         case 0x00000209: return "IA32_MTRR_PHYS_MASK4";
    886         case 0x0000020b: return "IA32_MTRR_PHYS_MASK5";
    887         case 0x0000020d: return "IA32_MTRR_PHYS_MASK6";
    888         case 0x0000020f: return "IA32_MTRR_PHYS_MASK7";
    889         case 0x00000211: return "IA32_MTRR_PHYS_MASK8";
    890         case 0x00000213: return "IA32_MTRR_PHYS_MASK9";
    891         case 0x00000215: return "IA32_MTRR_PHYS_MASK10";
    892         case 0x00000217: return "IA32_MTRR_PHYS_MASK11";
    893         case 0x00000219: return "IA32_MTRR_PHYS_MASK12";
    894         case 0x0000021b: return "IA32_MTRR_PHYS_MASK13";
    895         case 0x0000021d: return "IA32_MTRR_PHYS_MASK14";
    896         case 0x0000021f: return "IA32_MTRR_PHYS_MASK15";
    897 
    898         case 0x00000250: return "IA32_MTRR_FIX64K_00000";
    899         case 0x00000258: return "IA32_MTRR_FIX16K_80000";
    900         case 0x00000259: return "IA32_MTRR_FIX16K_A0000";
    901         case 0x00000268: return "IA32_MTRR_FIX4K_C0000";
    902         case 0x00000269: return "IA32_MTRR_FIX4K_C8000";
    903         case 0x0000026a: return "IA32_MTRR_FIX4K_D0000";
    904         case 0x0000026b: return "IA32_MTRR_FIX4K_D8000";
    905         case 0x0000026c: return "IA32_MTRR_FIX4K_E0000";
    906         case 0x0000026d: return "IA32_MTRR_FIX4K_E8000";
    907         case 0x0000026e: return "IA32_MTRR_FIX4K_F0000";
    908         case 0x0000026f: return "IA32_MTRR_FIX4K_F8000";
    909         case 0x00000277: return "IA32_PAT";
    910         case 0x00000280: return "IA32_MC0_CTL2";
    911         case 0x00000281: return "IA32_MC1_CTL2";
    912         case 0x00000282: return "IA32_MC2_CTL2";
    913         case 0x00000283: return "IA32_MC3_CTL2";
    914         case 0x00000284: return "IA32_MC4_CTL2";
    915         case 0x00000285: return "IA32_MC5_CTL2";
    916         case 0x00000286: return "IA32_MC6_CTL2";
    917         case 0x00000287: return "IA32_MC7_CTL2";
    918         case 0x00000288: return "IA32_MC8_CTL2";
    919         case 0x00000289: return "IA32_MC9_CTL2";
    920         case 0x0000028a: return "IA32_MC10_CTL2";
    921         case 0x0000028b: return "IA32_MC11_CTL2";
    922         case 0x0000028c: return "IA32_MC12_CTL2";
    923         case 0x0000028d: return "IA32_MC13_CTL2";
    924         case 0x0000028e: return "IA32_MC14_CTL2";
    925         case 0x0000028f: return "IA32_MC15_CTL2";
    926         case 0x00000290: return "IA32_MC16_CTL2";
    927         case 0x00000291: return "IA32_MC17_CTL2";
    928         case 0x00000292: return "IA32_MC18_CTL2";
    929         case 0x00000293: return "IA32_MC19_CTL2";
    930         case 0x00000294: return "IA32_MC20_CTL2";
    931         case 0x00000295: return "IA32_MC21_CTL2";
    932         //case 0x00000296: return "IA32_MC22_CTL2";
    933         //case 0x00000297: return "IA32_MC23_CTL2";
    934         //case 0x00000298: return "IA32_MC24_CTL2";
    935         //case 0x00000299: return "IA32_MC25_CTL2";
    936         //case 0x0000029a: return "IA32_MC26_CTL2";
    937         //case 0x0000029b: return "IA32_MC27_CTL2";
    938         //case 0x0000029c: return "IA32_MC28_CTL2";
    939         //case 0x0000029d: return "IA32_MC29_CTL2";
    940         //case 0x0000029e: return "IA32_MC30_CTL2";
    941         //case 0x0000029f: return "IA32_MC31_CTL2";
    942         case 0x000002e0: return "I7_SB_NO_EVICT_MODE"; /* (Bits 1 & 0 are said to have something to do with no-evict cache mode used during early boot.) */
    943         case 0x000002e6: return "I7_IB_UNK_0000_02e6"; /* IvyBridge */
    944         case 0x000002e7: return "I7_IB_UNK_0000_02e7"; /* IvyBridge */
    945         case 0x000002ff: return "IA32_MTRR_DEF_TYPE";
    946         case 0x00000300: return g_fIntelNetBurst ? "P4_MSR_BPU_COUNTER0"   : "I7_SB_UNK_0000_0300" /* SandyBridge */;
    947         case 0x00000301: return g_fIntelNetBurst ? "P4_MSR_BPU_COUNTER1"   : NULL;
    948         case 0x00000302: return g_fIntelNetBurst ? "P4_MSR_BPU_COUNTER2"   : NULL;
    949         case 0x00000303: return g_fIntelNetBurst ? "P4_MSR_BPU_COUNTER3"   : NULL;
    950         case 0x00000304: return g_fIntelNetBurst ? "P4_MSR_MS_COUNTER0"    : NULL;
    951         case 0x00000305: return g_fIntelNetBurst ? "P4_MSR_MS_COUNTER1"    : "I7_SB_UNK_0000_0305" /* SandyBridge, IvyBridge */;
    952         case 0x00000306: return g_fIntelNetBurst ? "P4_MSR_MS_COUNTER2"    : NULL;
    953         case 0x00000307: return g_fIntelNetBurst ? "P4_MSR_MS_COUNTER3"    : NULL;
    954         case 0x00000308: return g_fIntelNetBurst ? "P4_MSR_FLAME_COUNTER0" : NULL;
    955         case 0x00000309: return g_fIntelNetBurst ? "P4_MSR_FLAME_COUNTER1" : "IA32_FIXED_CTR0";
    956         case 0x0000030a: return g_fIntelNetBurst ? "P4_MSR_FLAME_COUNTER2" : "IA32_FIXED_CTR1";
    957         case 0x0000030b: return g_fIntelNetBurst ? "P4_MSR_FLAME_COUNTER3" : "IA32_FIXED_CTR2";
    958         case 0x0000030c: return g_fIntelNetBurst ? "P4_MSR_IQ_COUNTER0" : NULL;
    959         case 0x0000030d: return g_fIntelNetBurst ? "P4_MSR_IQ_COUNTER1" : NULL;
    960         case 0x0000030e: return g_fIntelNetBurst ? "P4_MSR_IQ_COUNTER2" : NULL;
    961         case 0x0000030f: return g_fIntelNetBurst ? "P4_MSR_IQ_COUNTER3" : NULL;
    962         case 0x00000310: return g_fIntelNetBurst ? "P4_MSR_IQ_COUNTER4" : NULL;
    963         case 0x00000311: return g_fIntelNetBurst ? "P4_MSR_IQ_COUNTER5" : NULL;
    964         case 0x00000345: return "IA32_PERF_CAPABILITIES";
    965         case 0x00000360: return g_fIntelNetBurst ? "P4_MSR_BPU_CCCR0"   : NULL;
    966         case 0x00000361: return g_fIntelNetBurst ? "P4_MSR_BPU_CCCR1"   : NULL;
    967         case 0x00000362: return g_fIntelNetBurst ? "P4_MSR_BPU_CCCR2"   : NULL;
    968         case 0x00000363: return g_fIntelNetBurst ? "P4_MSR_BPU_CCCR3"   : NULL;
    969         case 0x00000364: return g_fIntelNetBurst ? "P4_MSR_MS_CCCR0"    : NULL;
    970         case 0x00000365: return g_fIntelNetBurst ? "P4_MSR_MS_CCCR1"    : NULL;
    971         case 0x00000366: return g_fIntelNetBurst ? "P4_MSR_MS_CCCR2"    : NULL;
    972         case 0x00000367: return g_fIntelNetBurst ? "P4_MSR_MS_CCCR3"    : NULL;
    973         case 0x00000368: return g_fIntelNetBurst ? "P4_MSR_FLAME_CCCR0" : NULL;
    974         case 0x00000369: return g_fIntelNetBurst ? "P4_MSR_FLAME_CCCR1" : NULL;
    975         case 0x0000036a: return g_fIntelNetBurst ? "P4_MSR_FLAME_CCCR2" : NULL;
    976         case 0x0000036b: return g_fIntelNetBurst ? "P4_MSR_FLAME_CCCR3" : NULL;
    977         case 0x0000036c: return g_fIntelNetBurst ? "P4_MSR_IQ_CCCR0"    : NULL;
    978         case 0x0000036d: return g_fIntelNetBurst ? "P4_MSR_IQ_CCCR1"    : NULL;
    979         case 0x0000036e: return g_fIntelNetBurst ? "P4_MSR_IQ_CCCR2"    : NULL;
    980         case 0x0000036f: return g_fIntelNetBurst ? "P4_MSR_IQ_CCCR3"    : NULL;
    981         case 0x00000370: return g_fIntelNetBurst ? "P4_MSR_IQ_CCCR4"    : NULL;
    982         case 0x00000371: return g_fIntelNetBurst ? "P4_MSR_IQ_CCCR5"    : NULL;
    983         case 0x0000038d: return "IA32_FIXED_CTR_CTRL";
    984         case 0x0000038e: return "IA32_PERF_GLOBAL_STATUS";
    985         case 0x0000038f: return "IA32_PERF_GLOBAL_CTRL";
    986         case 0x00000390: return "IA32_PERF_GLOBAL_OVF_CTRL";
    987         case 0x00000391: return "I7_UNC_PERF_GLOBAL_CTRL";             /* S,H,X */
    988         case 0x00000392: return "I7_UNC_PERF_GLOBAL_STATUS";           /* S,H,X */
    989         case 0x00000393: return "I7_UNC_PERF_GLOBAL_OVF_CTRL";         /* X. ASSUMING this is the same on sandybridge and later. */
    990         case 0x00000394: return g_enmMicroarch < kCpumMicroarch_Intel_Core7_SandyBridge ? "I7_UNC_PERF_FIXED_CTR"  /* X */    : "I7_UNC_PERF_FIXED_CTR_CTRL"; /* >= S,H */
    991         case 0x00000395: return g_enmMicroarch < kCpumMicroarch_Intel_Core7_SandyBridge ? "I7_UNC_PERF_FIXED_CTR_CTRL" /* X*/ : "I7_UNC_PERF_FIXED_CTR";      /* >= S,H */
    992         case 0x00000396: return g_enmMicroarch < kCpumMicroarch_Intel_Core7_SandyBridge ? "I7_UNC_ADDR_OPCODE_MATCH" /* X */  : "I7_UNC_CBO_CONFIG";          /* >= S,H */
    993         case 0x00000397: return g_enmMicroarch < kCpumMicroarch_Intel_Core7_SandyBridge ? NULL                                : "I7_SB_UNK_0000_0397";
    994         case 0x0000039c: return "I7_SB_MSR_PEBS_NUM_ALT";
    995         case 0x000003a0: return g_fIntelNetBurst ? "P4_MSR_BSU_ESCR0"   : NULL;
    996         case 0x000003a1: return g_fIntelNetBurst ? "P4_MSR_BSU_ESCR1"   : NULL;
    997         case 0x000003a2: return g_fIntelNetBurst ? "P4_MSR_FSB_ESCR0"   : NULL;
    998         case 0x000003a3: return g_fIntelNetBurst ? "P4_MSR_FSB_ESCR1"   : NULL;
    999         case 0x000003a4: return g_fIntelNetBurst ? "P4_MSR_FIRM_ESCR0"  : NULL;
    1000         case 0x000003a5: return g_fIntelNetBurst ? "P4_MSR_FIRM_ESCR1"  : NULL;
    1001         case 0x000003a6: return g_fIntelNetBurst ? "P4_MSR_FLAME_ESCR0" : NULL;
    1002         case 0x000003a7: return g_fIntelNetBurst ? "P4_MSR_FLAME_ESCR1" : NULL;
    1003         case 0x000003a8: return g_fIntelNetBurst ? "P4_MSR_DAC_ESCR0"   : NULL;
    1004         case 0x000003a9: return g_fIntelNetBurst ? "P4_MSR_DAC_ESCR1"   : NULL;
    1005         case 0x000003aa: return g_fIntelNetBurst ? "P4_MSR_MOB_ESCR0"   : NULL;
    1006         case 0x000003ab: return g_fIntelNetBurst ? "P4_MSR_MOB_ESCR1"   : NULL;
    1007         case 0x000003ac: return g_fIntelNetBurst ? "P4_MSR_PMH_ESCR0"   : NULL;
    1008         case 0x000003ad: return g_fIntelNetBurst ? "P4_MSR_PMH_ESCR1"   : NULL;
    1009         case 0x000003ae: return g_fIntelNetBurst ? "P4_MSR_SAAT_ESCR0"  : NULL;
    1010         case 0x000003af: return g_fIntelNetBurst ? "P4_MSR_SAAT_ESCR1"  : NULL;
    1011         case 0x000003b0: return g_fIntelNetBurst ? "P4_MSR_U2L_ESCR0" : g_enmMicroarch < kCpumMicroarch_Intel_Core7_SandyBridge ? "I7_UNC_PMC0" /* X */               : "I7_UNC_ARB_PERF_CTR0";       /* >= S,H */
    1012         case 0x000003b1: return g_fIntelNetBurst ? "P4_MSR_U2L_ESCR1" : g_enmMicroarch < kCpumMicroarch_Intel_Core7_SandyBridge ? "I7_UNC_PMC1" /* X */               : "I7_UNC_ARB_PERF_CTR1";       /* >= S,H */
    1013         case 0x000003b2: return g_fIntelNetBurst ? "P4_MSR_BPU_ESCR0" : g_enmMicroarch < kCpumMicroarch_Intel_Core7_SandyBridge ? "I7_UNC_PMC2" /* X */               : "I7_UNC_ARB_PERF_EVT_SEL0";   /* >= S,H */
    1014         case 0x000003b3: return g_fIntelNetBurst ? "P4_MSR_BPU_ESCR1" : g_enmMicroarch < kCpumMicroarch_Intel_Core7_SandyBridge ? "I7_UNC_PMC3" /* X */               : "I7_UNC_ARB_PERF_EVT_SEL1";   /* >= S,H */
    1015         case 0x000003b4: return g_fIntelNetBurst ? "P4_MSR_IS_ESCR0"    : "I7_UNC_PMC4";
    1016         case 0x000003b5: return g_fIntelNetBurst ? "P4_MSR_IS_ESCR1"    : "I7_UNC_PMC5";
    1017         case 0x000003b6: return g_fIntelNetBurst ? "P4_MSR_ITLB_ESCR0"  : "I7_UNC_PMC6";
    1018         case 0x000003b7: return g_fIntelNetBurst ? "P4_MSR_ITLB_ESCR1"  : "I7_UNC_PMC7";
    1019         case 0x000003b8: return g_fIntelNetBurst ? "P4_MSR_CRU_ESCR0"   : NULL;
    1020         case 0x000003b9: return g_fIntelNetBurst ? "P4_MSR_CRU_ESCR1"   : NULL;
    1021         case 0x000003ba: return g_fIntelNetBurst ? "P4_MSR_IQ_ESCR0"    : NULL;
    1022         case 0x000003bb: return g_fIntelNetBurst ? "P4_MSR_IQ_ESCR1"    : NULL;
    1023         case 0x000003bc: return g_fIntelNetBurst ? "P4_MSR_RAT_ESCR0"   : NULL;
    1024         case 0x000003bd: return g_fIntelNetBurst ? "P4_MSR_RAT_ESCR1"   : NULL;
    1025         case 0x000003be: return g_fIntelNetBurst ? "P4_MSR_SSU_ESCR0"   : NULL;
    1026         case 0x000003c0: return g_fIntelNetBurst ? "P4_MSR_MS_ESCR0"    : "I7_UNC_PERF_EVT_SEL0";
    1027         case 0x000003c1: return g_fIntelNetBurst ? "P4_MSR_MS_ESCR1"    : "I7_UNC_PERF_EVT_SEL1";
    1028         case 0x000003c2: return g_fIntelNetBurst ? "P4_MSR_TBPU_ESCR0"  : "I7_UNC_PERF_EVT_SEL2";
    1029         case 0x000003c3: return g_fIntelNetBurst ? "P4_MSR_TBPU_ESCR1"  : "I7_UNC_PERF_EVT_SEL3";
    1030         case 0x000003c4: return g_fIntelNetBurst ? "P4_MSR_TC_ESCR0"    : "I7_UNC_PERF_EVT_SEL4";
    1031         case 0x000003c5: return g_fIntelNetBurst ? "P4_MSR_TC_ESCR1"    : "I7_UNC_PERF_EVT_SEL5";
    1032         case 0x000003c6: return g_fIntelNetBurst ? NULL                 : "I7_UNC_PERF_EVT_SEL6";
    1033         case 0x000003c7: return g_fIntelNetBurst ? NULL                 : "I7_UNC_PERF_EVT_SEL7";
    1034         case 0x000003c8: return g_fIntelNetBurst ? "P4_MSR_IX_ESCR0"    : NULL;
    1035         case 0x000003c9: return g_fIntelNetBurst ? "P4_MSR_IX_ESCR0"    : NULL;
    1036         case 0x000003ca: return g_fIntelNetBurst ? "P4_MSR_ALF_ESCR0"   : NULL;
    1037         case 0x000003cb: return g_fIntelNetBurst ? "P4_MSR_ALF_ESCR1"   : NULL;
    1038         case 0x000003cc: return g_fIntelNetBurst ? "P4_MSR_CRU_ESCR2"   : NULL;
    1039         case 0x000003cd: return g_fIntelNetBurst ? "P4_MSR_CRU_ESCR3"   : NULL;
    1040         case 0x000003e0: return g_fIntelNetBurst ? "P4_MSR_CRU_ESCR4"   : NULL;
    1041         case 0x000003e1: return g_fIntelNetBurst ? "P4_MSR_CRU_ESCR5"   : NULL;
    1042         case 0x000003f0: return g_fIntelNetBurst ? "P4_MSR_TC_PRECISE_EVENT" : NULL;
    1043         case 0x000003f1: return "IA32_PEBS_ENABLE";
    1044         case 0x000003f2: return g_fIntelNetBurst ? "P4_MSR_PEBS_MATRIX_VERT" : "IA32_PEBS_ENABLE";
    1045         case 0x000003f3: return g_fIntelNetBurst ? "P4_UNK_0000_03f3" : NULL;
    1046         case 0x000003f4: return g_fIntelNetBurst ? "P4_UNK_0000_03f4" : NULL;
    1047         case 0x000003f5: return g_fIntelNetBurst ? "P4_UNK_0000_03f5" : NULL;
    1048         case 0x000003f6: return g_fIntelNetBurst ? "P4_UNK_0000_03f6" : "I7_MSR_PEBS_LD_LAT";
    1049         case 0x000003f7: return g_fIntelNetBurst ? "P4_UNK_0000_03f7" : "I7_MSR_PEBS_LD_LAT";
    1050         case 0x000003f8: return g_fIntelNetBurst ? "P4_UNK_0000_03f8" : "I7_MSR_PKG_C3_RESIDENCY";
    1051         case 0x000003f9: return "I7_MSR_PKG_C6_RESIDENCY";
    1052         case 0x000003fa: return "I7_MSR_PKG_C7_RESIDENCY";
    1053         case 0x000003fc: return "I7_MSR_CORE_C3_RESIDENCY";
    1054         case 0x000003fd: return "I7_MSR_CORE_C6_RESIDENCY";
    1055         case 0x000003fe: return "I7_MSR_CORE_C7_RESIDENCY";
    1056         case 0x00000478: return g_enmMicroarch == kCpumMicroarch_Intel_Core2_Penryn ? "CPUID1_FEATURE_MASK" : NULL;
    1057         case 0x00000480: return "IA32_VMX_BASIC";
    1058         case 0x00000481: return "IA32_VMX_PINBASED_CTLS";
    1059         case 0x00000482: return "IA32_VMX_PROCBASED_CTLS";
    1060         case 0x00000483: return "IA32_VMX_EXIT_CTLS";
    1061         case 0x00000484: return "IA32_VMX_ENTRY_CTLS";
    1062         case 0x00000485: return "IA32_VMX_MISC";
    1063         case 0x00000486: return "IA32_VMX_CR0_FIXED0";
    1064         case 0x00000487: return "IA32_VMX_CR0_FIXED1";
    1065         case 0x00000488: return "IA32_VMX_CR4_FIXED0";
    1066         case 0x00000489: return "IA32_VMX_CR4_FIXED1";
    1067         case 0x0000048a: return "IA32_VMX_VMCS_ENUM";
    1068         case 0x0000048b: return "IA32_VMX_PROCBASED_CTLS2";
    1069         case 0x0000048c: return "IA32_VMX_EPT_VPID_CAP";
    1070         case 0x0000048d: return "IA32_VMX_TRUE_PINBASED_CTLS";
    1071         case 0x0000048e: return "IA32_VMX_TRUE_PROCBASED_CTLS";
    1072         case 0x0000048f: return "IA32_VMX_TRUE_EXIT_CTLS";
    1073         case 0x00000490: return "IA32_VMX_TRUE_ENTRY_CTLS";
    1074         case 0x00000491: return "IA32_VMX_VMFUNC";
    1075         case 0x000004c1: return "IA32_A_PMC0";
    1076         case 0x000004c2: return "IA32_A_PMC1";
    1077         case 0x000004c3: return "IA32_A_PMC2";
    1078         case 0x000004c4: return "IA32_A_PMC3";
    1079         case 0x000004c5: return "IA32_A_PMC4";
    1080         case 0x000004c6: return "IA32_A_PMC5";
    1081         case 0x000004c7: return "IA32_A_PMC6";
    1082         case 0x000004c8: return "IA32_A_PMC7";
    1083         case 0x000004f8: return "C2_UNK_0000_04f8"; /* Core2_Penryn. */
    1084         case 0x000004f9: return "C2_UNK_0000_04f9"; /* Core2_Penryn. */
    1085         case 0x000004fa: return "C2_UNK_0000_04fa"; /* Core2_Penryn. */
    1086         case 0x000004fb: return "C2_UNK_0000_04fb"; /* Core2_Penryn. */
    1087         case 0x000004fc: return "C2_UNK_0000_04fc"; /* Core2_Penryn. */
    1088         case 0x000004fd: return "C2_UNK_0000_04fd"; /* Core2_Penryn. */
    1089         case 0x000004fe: return "C2_UNK_0000_04fe"; /* Core2_Penryn. */
    1090         case 0x000004ff: return "C2_UNK_0000_04ff"; /* Core2_Penryn. */
    1091         case 0x00000502: return "I7_SB_UNK_0000_0502";
    1092         case 0x00000590: return "C2_UNK_0000_0590"; /* Core2_Penryn. */
    1093         case 0x00000591: return "C2_UNK_0000_0591"; /* Core2_Penryn. */
    1094         case 0x000005a0: return "C2_PECI_CTL"; /* Core2_Penryn. */
    1095         case 0x000005a1: return "C2_UNK_0000_05a1"; /* Core2_Penryn. */
    1096         case 0x00000600: return "IA32_DS_AREA";
    1097         case 0x00000601: return "I7_SB_MSR_VR_CURRENT_CONFIG"; /* SandyBridge, IvyBridge. */
    1098         case 0x00000602: return "I7_IB_UNK_0000_0602";
    1099         case 0x00000603: return "I7_SB_MSR_VR_MISC_CONFIG"; /* SandyBridge, IvyBridge. */
    1100         case 0x00000604: return "I7_IB_UNK_0000_0602";
    1101         case 0x00000606: return "I7_SB_MSR_RAPL_POWER_UNIT"; /* SandyBridge, IvyBridge. */
    1102         case 0x00000609: return "I7_SB_UNK_0000_0609";  /* SandyBridge (non EP). */
    1103         case 0x0000060a: return "I7_SB_MSR_PKGC3_IRTL"; /* SandyBridge, IvyBridge. */
    1104         case 0x0000060b: return "I7_SB_MSR_PKGC6_IRTL"; /* SandyBridge, IvyBridge. */
    1105         case 0x0000060c: return "I7_SB_MSR_PKGC7_IRTL"; /* SandyBridge, IvyBridge. */
    1106         case 0x0000060d: return "I7_SB_MSR_PKG_C2_RESIDENCY"; /* SandyBridge, IvyBridge. */
    1107         case 0x00000610: return "I7_SB_MSR_PKG_POWER_LIMIT";
    1108         case 0x00000611: return "I7_SB_MSR_PKG_ENERGY_STATUS";
    1109         case 0x00000613: return "I7_SB_MSR_PKG_PERF_STATUS";
    1110         case 0x00000614: return "I7_SB_MSR_PKG_POWER_INFO";
    1111         case 0x00000618: return "I7_SB_MSR_DRAM_POWER_LIMIT";
    1112         case 0x00000619: return "I7_SB_MSR_DRAM_ENERGY_STATUS";
    1113         case 0x0000061b: return "I7_SB_MSR_DRAM_PERF_STATUS";
    1114         case 0x0000061c: return "I7_SB_MSR_DRAM_POWER_INFO";
    1115         case 0x00000638: return "I7_SB_MSR_PP0_POWER_LIMIT";
    1116         case 0x00000639: return "I7_SB_MSR_PP0_ENERGY_STATUS";
    1117         case 0x0000063a: return "I7_SB_MSR_PP0_POLICY";
    1118         case 0x0000063b: return "I7_SB_MSR_PP0_PERF_STATUS";
    1119         case 0x00000640: return "I7_HW_MSR_PP0_POWER_LIMIT";
    1120         case 0x00000641: return "I7_HW_MSR_PP0_ENERGY_STATUS";
    1121         case 0x00000642: return "I7_HW_MSR_PP0_POLICY";
    1122         case 0x00000648: return "I7_IB_MSR_CONFIG_TDP_NOMINAL";
    1123         case 0x00000649: return "I7_IB_MSR_CONFIG_TDP_LEVEL1";
    1124         case 0x0000064a: return "I7_IB_MSR_CONFIG_TDP_LEVEL2";
    1125         case 0x0000064b: return "I7_IB_MSR_CONFIG_TDP_CONTROL";
    1126         case 0x0000064c: return "I7_IB_MSR_TURBO_ACTIVATION_RATIO";
    1127         case 0x00000660: return "SILV_CORE_C1_RESIDENCY";
    1128         case 0x00000661: return "SILV_UNK_0000_0661";
    1129         case 0x00000662: return "SILV_UNK_0000_0662";
    1130         case 0x00000663: return "SILV_UNK_0000_0663";
    1131         case 0x00000664: return "SILV_UNK_0000_0664";
    1132         case 0x00000665: return "SILV_UNK_0000_0665";
    1133         case 0x00000666: return "SILV_UNK_0000_0666";
    1134         case 0x00000667: return "SILV_UNK_0000_0667";
    1135         case 0x00000668: return "SILV_UNK_0000_0668";
    1136         case 0x00000669: return "SILV_UNK_0000_0669";
    1137         case 0x0000066a: return "SILV_UNK_0000_066a";
    1138         case 0x0000066b: return "SILV_UNK_0000_066b";
    1139         case 0x0000066c: return "SILV_UNK_0000_066c";
    1140         case 0x0000066d: return "SILV_UNK_0000_066d";
    1141         case 0x0000066e: return "SILV_UNK_0000_066e";
    1142         case 0x0000066f: return "SILV_UNK_0000_066f";
    1143         case 0x00000670: return "SILV_UNK_0000_0670";
    1144         case 0x00000671: return "SILV_UNK_0000_0671";
    1145         case 0x00000672: return "SILV_UNK_0000_0672";
    1146         case 0x00000673: return "SILV_UNK_0000_0673";
    1147         case 0x00000674: return "SILV_UNK_0000_0674";
    1148         case 0x00000675: return "SILV_UNK_0000_0675";
    1149         case 0x00000676: return "SILV_UNK_0000_0676";
    1150         case 0x00000677: return "SILV_UNK_0000_0677";
    1151 
    1152         case 0x00000680: return "MSR_LASTBRANCH_0_FROM_IP";
    1153         case 0x00000681: return "MSR_LASTBRANCH_1_FROM_IP";
    1154         case 0x00000682: return "MSR_LASTBRANCH_2_FROM_IP";
    1155         case 0x00000683: return "MSR_LASTBRANCH_3_FROM_IP";
    1156         case 0x00000684: return "MSR_LASTBRANCH_4_FROM_IP";
    1157         case 0x00000685: return "MSR_LASTBRANCH_5_FROM_IP";
    1158         case 0x00000686: return "MSR_LASTBRANCH_6_FROM_IP";
    1159         case 0x00000687: return "MSR_LASTBRANCH_7_FROM_IP";
    1160         case 0x00000688: return "MSR_LASTBRANCH_8_FROM_IP";
    1161         case 0x00000689: return "MSR_LASTBRANCH_9_FROM_IP";
    1162         case 0x0000068a: return "MSR_LASTBRANCH_10_FROM_IP";
    1163         case 0x0000068b: return "MSR_LASTBRANCH_11_FROM_IP";
    1164         case 0x0000068c: return "MSR_LASTBRANCH_12_FROM_IP";
    1165         case 0x0000068d: return "MSR_LASTBRANCH_13_FROM_IP";
    1166         case 0x0000068e: return "MSR_LASTBRANCH_14_FROM_IP";
    1167         case 0x0000068f: return "MSR_LASTBRANCH_15_FROM_IP";
    1168         case 0x000006c0: return "MSR_LASTBRANCH_0_TO_IP";
    1169         case 0x000006c1: return "MSR_LASTBRANCH_1_TO_IP";
    1170         case 0x000006c2: return "MSR_LASTBRANCH_2_TO_IP";
    1171         case 0x000006c3: return "MSR_LASTBRANCH_3_TO_IP";
    1172         case 0x000006c4: return "MSR_LASTBRANCH_4_TO_IP";
    1173         case 0x000006c5: return "MSR_LASTBRANCH_5_TO_IP";
    1174         case 0x000006c6: return "MSR_LASTBRANCH_6_TO_IP";
    1175         case 0x000006c7: return "MSR_LASTBRANCH_7_TO_IP";
    1176         case 0x000006c8: return "MSR_LASTBRANCH_8_TO_IP";
    1177         case 0x000006c9: return "MSR_LASTBRANCH_9_TO_IP";
    1178         case 0x000006ca: return "MSR_LASTBRANCH_10_TO_IP";
    1179         case 0x000006cb: return "MSR_LASTBRANCH_11_TO_IP";
    1180         case 0x000006cc: return "MSR_LASTBRANCH_12_TO_IP";
    1181         case 0x000006cd: return "MSR_LASTBRANCH_13_TO_IP";
    1182         case 0x000006ce: return "MSR_LASTBRANCH_14_TO_IP";
    1183         case 0x000006cf: return "MSR_LASTBRANCH_15_TO_IP";
    1184         case 0x000006e0: return "IA32_TSC_DEADLINE";
    1185 
    1186         case 0x00000768: return "SILV_UNK_0000_0768";
    1187         case 0x00000769: return "SILV_UNK_0000_0769";
    1188         case 0x0000076a: return "SILV_UNK_0000_076a";
    1189         case 0x0000076b: return "SILV_UNK_0000_076b";
    1190         case 0x0000076c: return "SILV_UNK_0000_076c";
    1191         case 0x0000076d: return "SILV_UNK_0000_076d";
    1192         case 0x0000076e: return "SILV_UNK_0000_076e";
    1193 
    1194         case 0x00000c80: return g_enmMicroarch >= kCpumMicroarch_Intel_Core7_IvyBridge ? "IA32_DEBUG_INTERFACE" : NULL; /* Mentioned in an intel dataskit called 4th-gen-core-family-desktop-vol-1-datasheet.pdf. */
    1195         case 0x00000c81: return g_enmMicroarch >= kCpumMicroarch_Intel_Core7_IvyBridge ? "I7_IB_UNK_0000_0c81"  : NULL; /* Probably related to IA32_DEBUG_INTERFACE... */
    1196         case 0x00000c82: return g_enmMicroarch >= kCpumMicroarch_Intel_Core7_IvyBridge ? "I7_IB_UNK_0000_0c82"  : NULL; /* Probably related to IA32_DEBUG_INTERFACE... */
    1197         case 0x00000c83: return g_enmMicroarch >= kCpumMicroarch_Intel_Core7_IvyBridge ? "I7_IB_UNK_0000_0c83"  : NULL; /* Probably related to IA32_DEBUG_INTERFACE... */
    1198 
    1199         /* 0x1000..0x1004 seems to have been used by IBM 386 and 486 clones too. */
    1200         case 0x00001000: return "P6_DEBUG_REGISTER_0";
    1201         case 0x00001001: return "P6_DEBUG_REGISTER_1";
    1202         case 0x00001002: return "P6_DEBUG_REGISTER_2";
    1203         case 0x00001003: return "P6_DEBUG_REGISTER_3";
    1204         case 0x00001004: return "P6_DEBUG_REGISTER_4";
    1205         case 0x00001005: return "P6_DEBUG_REGISTER_5";
    1206         case 0x00001006: return "P6_DEBUG_REGISTER_6";
    1207         case 0x00001007: return "P6_DEBUG_REGISTER_7";
    1208         case 0x0000103f: return "P6_UNK_0000_103f"; /* P6_M_Dothan. */
    1209         case 0x000010cd: return "P6_UNK_0000_10cd"; /* P6_M_Dothan. */
    1210 
    1211         case 0x00001107: return "VIA_UNK_0000_1107";
    1212         case 0x0000110f: return "VIA_UNK_0000_110f";
    1213         case 0x00001153: return "VIA_UNK_0000_1153";
    1214         case 0x00001200: return "VIA_UNK_0000_1200";
    1215         case 0x00001201: return "VIA_UNK_0000_1201";
    1216         case 0x00001202: return "VIA_UNK_0000_1202";
    1217         case 0x00001203: return "VIA_UNK_0000_1203";
    1218         case 0x00001204: return "VIA_UNK_0000_1204";
    1219         case 0x00001205: return "VIA_UNK_0000_1205";
    1220         case 0x00001206: return "VIA_ALT_VENDOR_EBX";
    1221         case 0x00001207: return "VIA_ALT_VENDOR_ECDX";
    1222         case 0x00001208: return "VIA_UNK_0000_1208";
    1223         case 0x00001209: return "VIA_UNK_0000_1209";
    1224         case 0x0000120a: return "VIA_UNK_0000_120a";
    1225         case 0x0000120b: return "VIA_UNK_0000_120b";
    1226         case 0x0000120c: return "VIA_UNK_0000_120c";
    1227         case 0x0000120d: return "VIA_UNK_0000_120d";
    1228         case 0x0000120e: return "VIA_UNK_0000_120e";
    1229         case 0x0000120f: return "VIA_UNK_0000_120f";
    1230         case 0x00001210: return "VIA_UNK_0000_1210";
    1231         case 0x00001211: return "VIA_UNK_0000_1211";
    1232         case 0x00001212: return "VIA_UNK_0000_1212";
    1233         case 0x00001213: return "VIA_UNK_0000_1213";
    1234         case 0x00001214: return "VIA_UNK_0000_1214";
    1235         case 0x00001220: return "VIA_UNK_0000_1220";
    1236         case 0x00001221: return "VIA_UNK_0000_1221";
    1237         case 0x00001230: return "VIA_UNK_0000_1230";
    1238         case 0x00001231: return "VIA_UNK_0000_1231";
    1239         case 0x00001232: return "VIA_UNK_0000_1232";
    1240         case 0x00001233: return "VIA_UNK_0000_1233";
    1241         case 0x00001234: return "VIA_UNK_0000_1234";
    1242         case 0x00001235: return "VIA_UNK_0000_1235";
    1243         case 0x00001236: return "VIA_UNK_0000_1236";
    1244         case 0x00001237: return "VIA_UNK_0000_1237";
    1245         case 0x00001238: return "VIA_UNK_0000_1238";
    1246         case 0x00001239: return "VIA_UNK_0000_1239";
    1247         case 0x00001240: return "VIA_UNK_0000_1240";
    1248         case 0x00001241: return "VIA_UNK_0000_1241";
    1249         case 0x00001243: return "VIA_UNK_0000_1243";
    1250         case 0x00001245: return "VIA_UNK_0000_1245";
    1251         case 0x00001246: return "VIA_UNK_0000_1246";
    1252         case 0x00001247: return "VIA_UNK_0000_1247";
    1253         case 0x00001248: return "VIA_UNK_0000_1248";
    1254         case 0x00001249: return "VIA_UNK_0000_1249";
    1255         case 0x0000124a: return "VIA_UNK_0000_124a";
    1256 
    1257         case 0x00001301: return "VIA_UNK_0000_1301";
    1258         case 0x00001302: return "VIA_UNK_0000_1302";
    1259         case 0x00001303: return "VIA_UNK_0000_1303";
    1260         case 0x00001304: return "VIA_UNK_0000_1304";
    1261         case 0x00001305: return "VIA_UNK_0000_1305";
    1262         case 0x00001306: return "VIA_UNK_0000_1306";
    1263         case 0x00001307: return "VIA_UNK_0000_1307";
    1264         case 0x00001308: return "VIA_UNK_0000_1308";
    1265         case 0x00001309: return "VIA_UNK_0000_1309";
    1266         case 0x0000130d: return "VIA_UNK_0000_130d";
    1267         case 0x0000130e: return "VIA_UNK_0000_130e";
    1268         case 0x00001312: return "VIA_UNK_0000_1312";
    1269         case 0x00001315: return "VIA_UNK_0000_1315";
    1270         case 0x00001317: return "VIA_UNK_0000_1317";
    1271         case 0x00001318: return "VIA_UNK_0000_1318";
    1272         case 0x0000131a: return "VIA_UNK_0000_131a";
    1273         case 0x0000131b: return "VIA_UNK_0000_131b";
    1274         case 0x00001402: return "VIA_UNK_0000_1402";
    1275         case 0x00001403: return "VIA_UNK_0000_1403";
    1276         case 0x00001404: return "VIA_UNK_0000_1404";
    1277         case 0x00001405: return "VIA_UNK_0000_1405";
    1278         case 0x00001406: return "VIA_UNK_0000_1406";
    1279         case 0x00001407: return "VIA_UNK_0000_1407";
    1280         case 0x00001410: return "VIA_UNK_0000_1410";
    1281         case 0x00001411: return "VIA_UNK_0000_1411";
    1282         case 0x00001412: return "VIA_UNK_0000_1412";
    1283         case 0x00001413: return "VIA_UNK_0000_1413";
    1284         case 0x00001414: return "VIA_UNK_0000_1414";
    1285         case 0x00001415: return "VIA_UNK_0000_1415";
    1286         case 0x00001416: return "VIA_UNK_0000_1416";
    1287         case 0x00001417: return "VIA_UNK_0000_1417";
    1288         case 0x00001418: return "VIA_UNK_0000_1418";
    1289         case 0x00001419: return "VIA_UNK_0000_1419";
    1290         case 0x0000141a: return "VIA_UNK_0000_141a";
    1291         case 0x0000141b: return "VIA_UNK_0000_141b";
    1292         case 0x0000141c: return "VIA_UNK_0000_141c";
    1293         case 0x0000141d: return "VIA_UNK_0000_141d";
    1294         case 0x0000141e: return "VIA_UNK_0000_141e";
    1295         case 0x0000141f: return "VIA_UNK_0000_141f";
    1296         case 0x00001420: return "VIA_UNK_0000_1420";
    1297         case 0x00001421: return "VIA_UNK_0000_1421";
    1298         case 0x00001422: return "VIA_UNK_0000_1422";
    1299         case 0x00001423: return "VIA_UNK_0000_1423";
    1300         case 0x00001424: return "VIA_UNK_0000_1424";
    1301         case 0x00001425: return "VIA_UNK_0000_1425";
    1302         case 0x00001426: return "VIA_UNK_0000_1426";
    1303         case 0x00001427: return "VIA_UNK_0000_1427";
    1304         case 0x00001428: return "VIA_UNK_0000_1428";
    1305         case 0x00001429: return "VIA_UNK_0000_1429";
    1306         case 0x0000142a: return "VIA_UNK_0000_142a";
    1307         case 0x0000142b: return "VIA_UNK_0000_142b";
    1308         case 0x0000142c: return "VIA_UNK_0000_142c";
    1309         case 0x0000142d: return "VIA_UNK_0000_142d";
    1310         case 0x0000142e: return "VIA_UNK_0000_142e";
    1311         case 0x0000142f: return "VIA_UNK_0000_142f";
    1312         case 0x00001434: return "VIA_UNK_0000_1434";
    1313         case 0x00001435: return "VIA_UNK_0000_1435";
    1314         case 0x00001436: return "VIA_UNK_0000_1436";
    1315         case 0x00001437: return "VIA_UNK_0000_1437";
    1316         case 0x00001438: return "VIA_UNK_0000_1438";
    1317         case 0x0000143a: return "VIA_UNK_0000_143a";
    1318         case 0x0000143c: return "VIA_UNK_0000_143c";
    1319         case 0x0000143d: return "VIA_UNK_0000_143d";
    1320         case 0x00001440: return "VIA_UNK_0000_1440";
    1321         case 0x00001441: return "VIA_UNK_0000_1441";
    1322         case 0x00001442: return "VIA_UNK_0000_1442";
    1323         case 0x00001449: return "VIA_UNK_0000_1449";
    1324         case 0x00001450: return "VIA_UNK_0000_1450";
    1325         case 0x00001451: return "VIA_UNK_0000_1451";
    1326         case 0x00001452: return "VIA_UNK_0000_1452";
    1327         case 0x00001453: return "VIA_UNK_0000_1453";
    1328         case 0x00001460: return "VIA_UNK_0000_1460";
    1329         case 0x00001461: return "VIA_UNK_0000_1461";
    1330         case 0x00001462: return "VIA_UNK_0000_1462";
    1331         case 0x00001463: return "VIA_UNK_0000_1463";
    1332         case 0x00001465: return "VIA_UNK_0000_1465";
    1333         case 0x00001466: return "VIA_UNK_0000_1466";
    1334         case 0x00001470: return "VIA_UNK_0000_1470";
    1335         case 0x00001471: return "VIA_UNK_0000_1471";
    1336         case 0x00001480: return "VIA_UNK_0000_1480";
    1337         case 0x00001481: return "VIA_UNK_0000_1481";
    1338         case 0x00001482: return "VIA_UNK_0000_1482";
    1339         case 0x00001483: return "VIA_UNK_0000_1483";
    1340         case 0x00001484: return "VIA_UNK_0000_1484";
    1341         case 0x00001485: return "VIA_UNK_0000_1485";
    1342         case 0x00001486: return "VIA_UNK_0000_1486";
    1343         case 0x00001490: return "VIA_UNK_0000_1490";
    1344         case 0x00001491: return "VIA_UNK_0000_1491";
    1345         case 0x00001492: return "VIA_UNK_0000_1492";
    1346         case 0x00001493: return "VIA_UNK_0000_1493";
    1347         case 0x00001494: return "VIA_UNK_0000_1494";
    1348         case 0x00001495: return "VIA_UNK_0000_1495";
    1349         case 0x00001496: return "VIA_UNK_0000_1496";
    1350         case 0x00001497: return "VIA_UNK_0000_1497";
    1351         case 0x00001498: return "VIA_UNK_0000_1498";
    1352         case 0x00001499: return "VIA_UNK_0000_1499";
    1353         case 0x0000149a: return "VIA_UNK_0000_149a";
    1354         case 0x0000149b: return "VIA_UNK_0000_149b";
    1355         case 0x0000149c: return "VIA_UNK_0000_149c";
    1356         case 0x0000149f: return "VIA_UNK_0000_149f";
    1357         case 0x00001523: return "VIA_UNK_0000_1523";
    1358 
    1359         case 0x00002000: return g_enmVendor == CPUMCPUVENDOR_INTEL ? "P6_CR0" : NULL;
    1360         case 0x00002002: return g_enmVendor == CPUMCPUVENDOR_INTEL ? "P6_CR2" : NULL;
    1361         case 0x00002003: return g_enmVendor == CPUMCPUVENDOR_INTEL ? "P6_CR3" : NULL;
    1362         case 0x00002004: return g_enmVendor == CPUMCPUVENDOR_INTEL ? "P6_CR4" : NULL;
    1363         case 0x0000203f: return g_enmVendor == CPUMCPUVENDOR_INTEL ? "P6_UNK_0000_203f" /* P6_M_Dothan. */ : NULL;
    1364         case 0x000020cd: return g_enmVendor == CPUMCPUVENDOR_INTEL ? "P6_UNK_0000_20cd" /* P6_M_Dothan. */ : NULL;
    1365         case 0x0000303f: return g_enmVendor == CPUMCPUVENDOR_INTEL ? "P6_UNK_0000_303f" /* P6_M_Dothan. */ : NULL;
    1366         case 0x000030cd: return g_enmVendor == CPUMCPUVENDOR_INTEL ? "P6_UNK_0000_30cd" /* P6_M_Dothan. */ : NULL;
    1367 
    1368         case 0x0000317a: return "VIA_UNK_0000_317a";
    1369         case 0x0000317b: return "VIA_UNK_0000_317b";
    1370         case 0x0000317d: return "VIA_UNK_0000_317d";
    1371         case 0x0000317e: return "VIA_UNK_0000_317e";
    1372         case 0x0000317f: return "VIA_UNK_0000_317f";
    1373         case 0x80000198: return "VIA_UNK_8000_0198";
    1374 
    1375         case 0xc0000080: return "AMD64_EFER";
    1376         case 0xc0000081: return "AMD64_STAR";
    1377         case 0xc0000082: return "AMD64_STAR64";
    1378         case 0xc0000083: return "AMD64_STARCOMPAT";
    1379         case 0xc0000084: return "AMD64_SYSCALL_FLAG_MASK";
    1380         case 0xc0000100: return "AMD64_FS_BASE";
    1381         case 0xc0000101: return "AMD64_GS_BASE";
    1382         case 0xc0000102: return "AMD64_KERNEL_GS_BASE";
    1383         case 0xc0000103: return "AMD64_TSC_AUX";
    1384         case 0xc0000104: return "AMD_15H_TSC_RATE";
    1385         case 0xc0000105: return "AMD_15H_LWP_CFG";      /* Only Family 15h? */
    1386         case 0xc0000106: return "AMD_15H_LWP_CBADDR";   /* Only Family 15h? */
    1387         case 0xc0000408: return "AMD_10H_MC4_MISC1";
    1388         case 0xc0000409: return "AMD_10H_MC4_MISC2";
    1389         case 0xc000040a: return "AMD_10H_MC4_MISC3";
    1390         case 0xc000040b: return "AMD_10H_MC4_MISC4";
    1391         case 0xc000040c: return "AMD_10H_MC4_MISC5";
    1392         case 0xc000040d: return "AMD_10H_MC4_MISC6";
    1393         case 0xc000040e: return "AMD_10H_MC4_MISC7";
    1394         case 0xc000040f: return "AMD_10H_MC4_MISC8";
    1395         case 0xc0010000: return "AMD_K8_PERF_CTL_0";
    1396         case 0xc0010001: return "AMD_K8_PERF_CTL_1";
    1397         case 0xc0010002: return "AMD_K8_PERF_CTL_2";
    1398         case 0xc0010003: return "AMD_K8_PERF_CTL_3";
    1399         case 0xc0010004: return "AMD_K8_PERF_CTR_0";
    1400         case 0xc0010005: return "AMD_K8_PERF_CTR_1";
    1401         case 0xc0010006: return "AMD_K8_PERF_CTR_2";
    1402         case 0xc0010007: return "AMD_K8_PERF_CTR_3";
    1403         case 0xc0010010: return "AMD_K8_SYS_CFG";
    1404         case 0xc0010015: return "AMD_K8_HW_CFG";
    1405         case 0xc0010016: return "AMD_K8_IORR_BASE_0";
    1406         case 0xc0010017: return "AMD_K8_IORR_MASK_0";
    1407         case 0xc0010018: return "AMD_K8_IORR_BASE_1";
    1408         case 0xc0010019: return "AMD_K8_IORR_MASK_1";
    1409         case 0xc001001a: return "AMD_K8_TOP_MEM";
    1410         case 0xc001001d: return "AMD_K8_TOP_MEM2";
    1411         case 0xc001001e: return "AMD_K8_MANID";
    1412         case 0xc001001f: return "AMD_K8_NB_CFG1";
    1413         case 0xc0010020: return "AMD_K8_PATCH_LOADER";
    1414         case 0xc0010021: return "AMD_K8_UNK_c001_0021";
    1415         case 0xc0010022: return "AMD_K8_MC_XCPT_REDIR";
    1416         case 0xc0010028: return "AMD_K8_UNK_c001_0028";
    1417         case 0xc0010029: return "AMD_K8_UNK_c001_0029";
    1418         case 0xc001002a: return "AMD_K8_UNK_c001_002a";
    1419         case 0xc001002b: return "AMD_K8_UNK_c001_002b";
    1420         case 0xc001002c: return "AMD_K8_UNK_c001_002c";
    1421         case 0xc001002d: return "AMD_K8_UNK_c001_002d";
    1422         case 0xc0010030: return "AMD_K8_CPU_NAME_0";
    1423         case 0xc0010031: return "AMD_K8_CPU_NAME_1";
    1424         case 0xc0010032: return "AMD_K8_CPU_NAME_2";
    1425         case 0xc0010033: return "AMD_K8_CPU_NAME_3";
    1426         case 0xc0010034: return "AMD_K8_CPU_NAME_4";
    1427         case 0xc0010035: return "AMD_K8_CPU_NAME_5";
    1428         case 0xc001003e: return "AMD_K8_HTC";
    1429         case 0xc001003f: return "AMD_K8_STC";
    1430         case 0xc0010041: return "AMD_K8_FIDVID_CTL";
    1431         case 0xc0010042: return "AMD_K8_FIDVID_STATUS";
    1432         case 0xc0010043: return "AMD_K8_THERMTRIP_STATUS"; /* BDKG says it was removed in K8 revision C.*/
    1433         case 0xc0010044: return "AMD_K8_MC_CTL_MASK_0";
    1434         case 0xc0010045: return "AMD_K8_MC_CTL_MASK_1";
    1435         case 0xc0010046: return "AMD_K8_MC_CTL_MASK_2";
    1436         case 0xc0010047: return "AMD_K8_MC_CTL_MASK_3";
    1437         case 0xc0010048: return "AMD_K8_MC_CTL_MASK_4";
    1438         case 0xc0010049: return "AMD_K8_MC_CTL_MASK_5";
    1439         case 0xc001004a: return "AMD_K8_MC_CTL_MASK_6";
    1440         //case 0xc001004b: return "AMD_K8_MC_CTL_MASK_7";
    1441         case 0xc0010050: return "AMD_K8_SMI_ON_IO_TRAP_0";
    1442         case 0xc0010051: return "AMD_K8_SMI_ON_IO_TRAP_1";
    1443         case 0xc0010052: return "AMD_K8_SMI_ON_IO_TRAP_2";
    1444         case 0xc0010053: return "AMD_K8_SMI_ON_IO_TRAP_3";
    1445         case 0xc0010054: return "AMD_K8_SMI_ON_IO_TRAP_CTL_STS";
    1446         case 0xc0010055: return "AMD_K8_INT_PENDING_MSG";
    1447         case 0xc0010056: return "AMD_K8_SMI_TRIGGER_IO_CYCLE";
    1448         case 0xc0010057: return "AMD_10H_UNK_c001_0057";
    1449         case 0xc0010058: return "AMD_10H_MMIO_CFG_BASE_ADDR";
    1450         case 0xc0010059: return "AMD_10H_TRAP_CTL?"; /* Undocumented, only one google hit. */
    1451         case 0xc001005a: return "AMD_10H_UNK_c001_005a";
    1452         case 0xc001005b: return "AMD_10H_UNK_c001_005b";
    1453         case 0xc001005c: return "AMD_10H_UNK_c001_005c";
    1454         case 0xc001005d: return "AMD_10H_UNK_c001_005d";
    1455         case 0xc0010060: return "AMD_K8_BIST_RESULT";   /* BDKG says it as introduced with revision F. */
    1456         case 0xc0010061: return "AMD_10H_P_ST_CUR_LIM";
    1457         case 0xc0010062: return "AMD_10H_P_ST_CTL";
    1458         case 0xc0010063: return "AMD_10H_P_ST_STS";
    1459         case 0xc0010064: return "AMD_10H_P_ST_0";
    1460         case 0xc0010065: return "AMD_10H_P_ST_1";
    1461         case 0xc0010066: return "AMD_10H_P_ST_2";
    1462         case 0xc0010067: return "AMD_10H_P_ST_3";
    1463         case 0xc0010068: return "AMD_10H_P_ST_4";
    1464         case 0xc0010069: return "AMD_10H_P_ST_5";
    1465         case 0xc001006a: return "AMD_10H_P_ST_6";
    1466         case 0xc001006b: return "AMD_10H_P_ST_7";
    1467         case 0xc0010070: return "AMD_10H_COFVID_CTL";
    1468         case 0xc0010071: return "AMD_10H_COFVID_STS";
    1469         case 0xc0010073: return "AMD_10H_C_ST_IO_BASE_ADDR";
    1470         case 0xc0010074: return "AMD_10H_CPU_WD_TMR_CFG";
    1471         // case 0xc0010075: return "AMD_15H_APML_TDP_LIM";
    1472         // case 0xc0010077: return "AMD_15H_CPU_PWR_IN_TDP";
    1473         // case 0xc0010078: return "AMD_15H_PWR_AVG_PERIOD";
    1474         // case 0xc0010079: return "AMD_15H_DRAM_CTR_CMD_THR";
    1475         // case 0xc0010080: return "AMD_16H_FSFM_ACT_CNT_0";
    1476         // case 0xc0010081: return "AMD_16H_FSFM_REF_CNT_0";
    1477         case 0xc0010111: return "AMD_K8_SMM_BASE";
    1478         case 0xc0010112: return "AMD_K8_SMM_ADDR";
    1479         case 0xc0010113: return "AMD_K8_SMM_MASK";
    1480         case 0xc0010114: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_90nm_AMDV ? "AMD_K8_VM_CR"          : "AMD_K8_UNK_c001_0114";
    1481         case 0xc0010115: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_90nm      ? "AMD_K8_IGNNE"          : "AMD_K8_UNK_c001_0115";
    1482         case 0xc0010116: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_90nm      ? "AMD_K8_SMM_CTL"        : "AMD_K8_UNK_c001_0116";
    1483         case 0xc0010117: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_90nm_AMDV ? "AMD_K8_VM_HSAVE_PA"    : "AMD_K8_UNK_c001_0117";
    1484         case 0xc0010118: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_90nm_AMDV ? "AMD_10H_VM_LOCK_KEY"   : "AMD_K8_UNK_c001_0118";
    1485         case 0xc0010119: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_90nm      ? "AMD_10H_SSM_LOCK_KEY"  : "AMD_K8_UNK_c001_0119";
    1486         case 0xc001011a: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_90nm      ? "AMD_10H_LOCAL_SMI_STS" : "AMD_K8_UNK_c001_011a";
    1487         case 0xc001011b: return "AMD_K8_UNK_c001_011b";
    1488         case 0xc001011c: return "AMD_K8_UNK_c001_011c";
    1489         case 0xc0010140: return "AMD_10H_OSVW_ID_LEN";
    1490         case 0xc0010141: return "AMD_10H_OSVW_STS";
    1491         case 0xc0010200: return "AMD_K8_PERF_CTL_0";
    1492         case 0xc0010202: return "AMD_K8_PERF_CTL_1";
    1493         case 0xc0010204: return "AMD_K8_PERF_CTL_2";
    1494         case 0xc0010206: return "AMD_K8_PERF_CTL_3";
    1495         case 0xc0010208: return "AMD_K8_PERF_CTL_4";
    1496         case 0xc001020a: return "AMD_K8_PERF_CTL_5";
    1497         //case 0xc001020c: return "AMD_K8_PERF_CTL_6";
    1498         //case 0xc001020e: return "AMD_K8_PERF_CTL_7";
    1499         case 0xc0010201: return "AMD_K8_PERF_CTR_0";
    1500         case 0xc0010203: return "AMD_K8_PERF_CTR_1";
    1501         case 0xc0010205: return "AMD_K8_PERF_CTR_2";
    1502         case 0xc0010207: return "AMD_K8_PERF_CTR_3";
    1503         case 0xc0010209: return "AMD_K8_PERF_CTR_4";
    1504         case 0xc001020b: return "AMD_K8_PERF_CTR_5";
    1505         //case 0xc001020d: return "AMD_K8_PERF_CTR_6";
    1506         //case 0xc001020f: return "AMD_K8_PERF_CTR_7";
    1507         case 0xc0010230: return "AMD_16H_L2I_PERF_CTL_0";
    1508         case 0xc0010232: return "AMD_16H_L2I_PERF_CTL_1";
    1509         case 0xc0010234: return "AMD_16H_L2I_PERF_CTL_2";
    1510         case 0xc0010236: return "AMD_16H_L2I_PERF_CTL_3";
    1511         //case 0xc0010238: return "AMD_16H_L2I_PERF_CTL_4";
    1512         //case 0xc001023a: return "AMD_16H_L2I_PERF_CTL_5";
    1513         //case 0xc001030c: return "AMD_16H_L2I_PERF_CTL_6";
    1514         //case 0xc001023e: return "AMD_16H_L2I_PERF_CTL_7";
    1515         case 0xc0010231: return "AMD_16H_L2I_PERF_CTR_0";
    1516         case 0xc0010233: return "AMD_16H_L2I_PERF_CTR_1";
    1517         case 0xc0010235: return "AMD_16H_L2I_PERF_CTR_2";
    1518         case 0xc0010237: return "AMD_16H_L2I_PERF_CTR_3";
    1519         //case 0xc0010239: return "AMD_16H_L2I_PERF_CTR_4";
    1520         //case 0xc001023b: return "AMD_16H_L2I_PERF_CTR_5";
    1521         //case 0xc001023d: return "AMD_16H_L2I_PERF_CTR_6";
    1522         //case 0xc001023f: return "AMD_16H_L2I_PERF_CTR_7";
    1523         case 0xc0010240: return "AMD_15H_NB_PERF_CTL_0";
    1524         case 0xc0010242: return "AMD_15H_NB_PERF_CTL_1";
    1525         case 0xc0010244: return "AMD_15H_NB_PERF_CTL_2";
    1526         case 0xc0010246: return "AMD_15H_NB_PERF_CTL_3";
    1527         //case 0xc0010248: return "AMD_15H_NB_PERF_CTL_4";
    1528         //case 0xc001024a: return "AMD_15H_NB_PERF_CTL_5";
    1529         //case 0xc001024c: return "AMD_15H_NB_PERF_CTL_6";
    1530         //case 0xc001024e: return "AMD_15H_NB_PERF_CTL_7";
    1531         case 0xc0010241: return "AMD_15H_NB_PERF_CTR_0";
    1532         case 0xc0010243: return "AMD_15H_NB_PERF_CTR_1";
    1533         case 0xc0010245: return "AMD_15H_NB_PERF_CTR_2";
    1534         case 0xc0010247: return "AMD_15H_NB_PERF_CTR_3";
    1535         //case 0xc0010249: return "AMD_15H_NB_PERF_CTR_4";
    1536         //case 0xc001024b: return "AMD_15H_NB_PERF_CTR_5";
    1537         //case 0xc001024d: return "AMD_15H_NB_PERF_CTR_6";
    1538         //case 0xc001024f: return "AMD_15H_NB_PERF_CTR_7";
    1539         case 0xc0011000: return "AMD_K7_MCODE_CTL";
    1540         case 0xc0011001: return "AMD_K7_APIC_CLUSTER_ID"; /* Mentioned in BKDG (r3.00) for fam16h when describing EBL_CR_POWERON. */
    1541         case 0xc0011002: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_First ? "AMD_K8_CPUID_CTL_STD07" : NULL;
    1542         case 0xc0011003: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_First ? "AMD_K8_CPUID_CTL_STD06" : NULL;
    1543         case 0xc0011004: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_First ? "AMD_K8_CPUID_CTL_STD01" : NULL;
    1544         case 0xc0011005: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_First ? "AMD_K8_CPUID_CTL_EXT01" : NULL;
    1545         case 0xc0011006: return "AMD_K7_DEBUG_STS?";
    1546         case 0xc0011007: return "AMD_K7_BH_TRACE_BASE?";
    1547         case 0xc0011008: return "AMD_K7_BH_TRACE_PTR?";
    1548         case 0xc0011009: return "AMD_K7_BH_TRACE_LIM?";
    1549         case 0xc001100a: return "AMD_K7_HDT_CFG?";
    1550         case 0xc001100b: return "AMD_K7_FAST_FLUSH_COUNT?";
    1551         case 0xc001100c: return "AMD_K7_NODE_ID";
    1552         case 0xc001100d: return "AMD_K8_LOGICAL_CPUS_NUM?";
    1553         case 0xc001100e: return "AMD_K8_WRMSR_BP?";
    1554         case 0xc001100f: return "AMD_K8_WRMSR_BP_MASK?";
    1555         case 0xc0011010: return "AMD_K8_BH_TRACE_CTL?";
    1556         case 0xc0011011: return "AMD_K8_BH_TRACE_USRD?";
    1557         case 0xc0011012: return "AMD_K7_UNK_c001_1012";
    1558         case 0xc0011013: return "AMD_K7_UNK_c001_1013";
    1559         case 0xc0011014: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_First ? "AMD_K8_XCPT_BP_RIP?" : "AMD_K7_MOBIL_DEBUG?";
    1560         case 0xc0011015: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_First ? "AMD_K8_XCPT_BP_RIP_MASK?" : NULL;
    1561         case 0xc0011016: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_First ? "AMD_K8_COND_HDT_VAL?" : NULL;
    1562         case 0xc0011017: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_First ? "AMD_K8_COND_HDT_VAL_MASK?" : NULL;
    1563         case 0xc0011018: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_First ? "AMD_K8_XCPT_BP_CTL?" : NULL;
    1564         case 0xc0011019: return g_enmMicroarch >= kCpumMicroarch_AMD_15h_Piledriver ? "AMD_16H_DR1_ADDR_MASK" : NULL;
    1565         case 0xc001101a: return g_enmMicroarch >= kCpumMicroarch_AMD_15h_Piledriver ? "AMD_16H_DR2_ADDR_MASK" : NULL;
    1566         case 0xc001101b: return g_enmMicroarch >= kCpumMicroarch_AMD_15h_Piledriver ? "AMD_16H_DR3_ADDR_MASK" : NULL;
    1567         case 0xc001101d: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_First ? "AMD_K8_NB_BIST?" : NULL;
    1568         case 0xc001101e: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_First ? "AMD_K8_THERMTRIP_2?" : NULL;
    1569         case 0xc001101f: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_First ? "AMD_K8_NB_CFG?" : NULL;
    1570         case 0xc0011020: return "AMD_K7_LS_CFG";
    1571         case 0xc0011021: return "AMD_K7_IC_CFG";
    1572         case 0xc0011022: return "AMD_K7_DC_CFG";
    1573         case 0xc0011023: return CPUMMICROARCH_IS_AMD_FAM_15H(g_enmMicroarch) ? "AMD_15H_CU_CFG" : "AMD_K7_BU_CFG";
    1574         case 0xc0011024: return "AMD_K7_DEBUG_CTL_2?";
    1575         case 0xc0011025: return "AMD_K7_DR0_DATA_MATCH?";
    1576         case 0xc0011026: return "AMD_K7_DR0_DATA_MATCH?";
    1577         case 0xc0011027: return "AMD_K7_DR0_ADDR_MASK";
    1578         case 0xc0011028: return g_enmMicroarch >= kCpumMicroarch_AMD_15h_First ? "AMD_15H_FP_CFG"
    1579                               : CPUMMICROARCH_IS_AMD_FAM_10H(g_enmMicroarch)   ? "AMD_10H_UNK_c001_1028"
    1580                               : NULL;
    1581         case 0xc0011029: return g_enmMicroarch >= kCpumMicroarch_AMD_15h_First ? "AMD_15H_DC_CFG"
    1582                               : CPUMMICROARCH_IS_AMD_FAM_10H(g_enmMicroarch)   ? "AMD_10H_UNK_c001_1029"
    1583                               : NULL;
    1584         case 0xc001102a: return CPUMMICROARCH_IS_AMD_FAM_15H(g_enmMicroarch)   ? "AMD_15H_CU_CFG2"
    1585                               : CPUMMICROARCH_IS_AMD_FAM_10H(g_enmMicroarch) || g_enmMicroarch > kCpumMicroarch_AMD_15h_End
    1586                               ? "AMD_10H_BU_CFG2" /* 10h & 16h */ : NULL;
    1587         case 0xc001102b: return CPUMMICROARCH_IS_AMD_FAM_15H(g_enmMicroarch)   ? "AMD_15H_CU_CFG3" : NULL;
    1588         case 0xc001102c: return CPUMMICROARCH_IS_AMD_FAM_15H(g_enmMicroarch)   ? "AMD_15H_EX_CFG" : NULL;
    1589         case 0xc001102d: return CPUMMICROARCH_IS_AMD_FAM_15H(g_enmMicroarch)   ? "AMD_15H_LS_CFG2" : NULL;
    1590         case 0xc0011030: return "AMD_10H_IBS_FETCH_CTL";
    1591         case 0xc0011031: return "AMD_10H_IBS_FETCH_LIN_ADDR";
    1592         case 0xc0011032: return "AMD_10H_IBS_FETCH_PHYS_ADDR";
    1593         case 0xc0011033: return "AMD_10H_IBS_OP_EXEC_CTL";
    1594         case 0xc0011034: return "AMD_10H_IBS_OP_RIP";
    1595         case 0xc0011035: return "AMD_10H_IBS_OP_DATA";
    1596         case 0xc0011036: return "AMD_10H_IBS_OP_DATA2";
    1597         case 0xc0011037: return "AMD_10H_IBS_OP_DATA3";
    1598         case 0xc0011038: return "AMD_10H_IBS_DC_LIN_ADDR";
    1599         case 0xc0011039: return "AMD_10H_IBS_DC_PHYS_ADDR";
    1600         case 0xc001103a: return "AMD_10H_IBS_CTL";
    1601         case 0xc001103b: return "AMD_14H_IBS_BR_TARGET";
    1602 
    1603         case 0xc0011040: return "AMD_15H_UNK_c001_1040";
    1604         case 0xc0011041: return "AMD_15H_UNK_c001_1041";
    1605         case 0xc0011042: return "AMD_15H_UNK_c001_1042";
    1606         case 0xc0011043: return "AMD_15H_UNK_c001_1043";
    1607         case 0xc0011044: return "AMD_15H_UNK_c001_1044";
    1608         case 0xc0011045: return "AMD_15H_UNK_c001_1045";
    1609         case 0xc0011046: return "AMD_15H_UNK_c001_1046";
    1610         case 0xc0011047: return "AMD_15H_UNK_c001_1047";
    1611         case 0xc0011048: return "AMD_15H_UNK_c001_1048";
    1612         case 0xc0011049: return "AMD_15H_UNK_c001_1049";
    1613         case 0xc001104a: return "AMD_15H_UNK_c001_104a";
    1614         case 0xc001104b: return "AMD_15H_UNK_c001_104b";
    1615         case 0xc001104c: return "AMD_15H_UNK_c001_104c";
    1616         case 0xc001104d: return "AMD_15H_UNK_c001_104d";
    1617         case 0xc001104e: return "AMD_15H_UNK_c001_104e";
    1618         case 0xc001104f: return "AMD_15H_UNK_c001_104f";
    1619         case 0xc0011050: return "AMD_15H_UNK_c001_1050";
    1620         case 0xc0011051: return "AMD_15H_UNK_c001_1051";
    1621         case 0xc0011052: return "AMD_15H_UNK_c001_1052";
    1622         case 0xc0011053: return "AMD_15H_UNK_c001_1053";
    1623         case 0xc0011054: return "AMD_15H_UNK_c001_1054";
    1624         case 0xc0011055: return "AMD_15H_UNK_c001_1055";
    1625         case 0xc0011056: return "AMD_15H_UNK_c001_1056";
    1626         case 0xc0011057: return "AMD_15H_UNK_c001_1057";
    1627         case 0xc0011058: return "AMD_15H_UNK_c001_1058";
    1628         case 0xc0011059: return "AMD_15H_UNK_c001_1059";
    1629         case 0xc001105a: return "AMD_15H_UNK_c001_105a";
    1630         case 0xc001105b: return "AMD_15H_UNK_c001_105b";
    1631         case 0xc001105c: return "AMD_15H_UNK_c001_105c";
    1632         case 0xc001105d: return "AMD_15H_UNK_c001_105d";
    1633         case 0xc001105e: return "AMD_15H_UNK_c001_105e";
    1634         case 0xc001105f: return "AMD_15H_UNK_c001_105f";
    1635         case 0xc0011060: return "AMD_15H_UNK_c001_1060";
    1636         case 0xc0011061: return "AMD_15H_UNK_c001_1061";
    1637         case 0xc0011062: return "AMD_15H_UNK_c001_1062";
    1638         case 0xc0011063: return "AMD_15H_UNK_c001_1063";
    1639         case 0xc0011064: return "AMD_15H_UNK_c001_1064";
    1640         case 0xc0011065: return "AMD_15H_UNK_c001_1065";
    1641         case 0xc0011066: return "AMD_15H_UNK_c001_1066";
    1642         case 0xc0011067: return "AMD_15H_UNK_c001_1067";
    1643         case 0xc0011068: return "AMD_15H_UNK_c001_1068";
    1644         case 0xc0011069: return "AMD_15H_UNK_c001_1069";
    1645         case 0xc001106a: return "AMD_15H_UNK_c001_106a";
    1646         case 0xc001106b: return "AMD_15H_UNK_c001_106b";
    1647         case 0xc001106c: return "AMD_15H_UNK_c001_106c";
    1648         case 0xc001106d: return "AMD_15H_UNK_c001_106d";
    1649         case 0xc001106e: return "AMD_15H_UNK_c001_106e";
    1650         case 0xc001106f: return "AMD_15H_UNK_c001_106f";
    1651         case 0xc0011070: return "AMD_15H_UNK_c001_1070"; /* coreboot defines this, but with a numerical name. */
    1652         case 0xc0011071: return "AMD_15H_UNK_c001_1071";
    1653         case 0xc0011072: return "AMD_15H_UNK_c001_1072";
    1654         case 0xc0011073: return "AMD_15H_UNK_c001_1073";
    1655         case 0xc0011080: return "AMD_15H_UNK_c001_1080";
    1656     }
    1657 
    1658     /*
    1659      * Uncore stuff on Sandy. Putting it here to avoid ugly microarch checks for each register.
    1660      * Note! These are found on model 42 (2a) but not 45 (2d), the latter is the EP variant.
    1661      */
    1662     if (g_enmMicroarch == kCpumMicroarch_Intel_Core7_SandyBridge)
    1663         switch (uMsr)
    1664         {
    1665             case 0x00000700: return "MSR_UNC_CBO_0_PERFEVTSEL0";
    1666             case 0x00000701: return "MSR_UNC_CBO_0_PERFEVTSEL1";
    1667             case 0x00000702: return "MSR_UNC_CBO_0_PERFEVTSEL2?";
    1668             case 0x00000703: return "MSR_UNC_CBO_0_PERFEVTSEL3?";
    1669             case 0x00000704: return "MSR_UNC_CBO_0_UNK_4";
    1670             case 0x00000705: return "MSR_UNC_CBO_0_UNK_5";
    1671             case 0x00000706: return "MSR_UNC_CBO_0_PER_CTR0";
    1672             case 0x00000707: return "MSR_UNC_CBO_0_PER_CTR1";
    1673             case 0x00000708: return "MSR_UNC_CBO_0_PER_CTR2?";
    1674             case 0x00000709: return "MSR_UNC_CBO_0_PER_CTR3?";
    1675             case 0x00000710: return "MSR_UNC_CBO_1_PERFEVTSEL0";
    1676             case 0x00000711: return "MSR_UNC_CBO_1_PERFEVTSEL1";
    1677             case 0x00000712: return "MSR_UNC_CBO_1_PERFEVTSEL2?";
    1678             case 0x00000713: return "MSR_UNC_CBO_1_PERFEVTSEL3?";
    1679             case 0x00000714: return "MSR_UNC_CBO_1_UNK_4";
    1680             case 0x00000715: return "MSR_UNC_CBO_1_UNK_5";
    1681             case 0x00000716: return "MSR_UNC_CBO_1_PER_CTR0";
    1682             case 0x00000717: return "MSR_UNC_CBO_1_PER_CTR1";
    1683             case 0x00000718: return "MSR_UNC_CBO_1_PER_CTR2?";
    1684             case 0x00000719: return "MSR_UNC_CBO_1_PER_CTR3?";
    1685             case 0x00000720: return "MSR_UNC_CBO_2_PERFEVTSEL0";
    1686             case 0x00000721: return "MSR_UNC_CBO_2_PERFEVTSEL1";
    1687             case 0x00000722: return "MSR_UNC_CBO_2_PERFEVTSEL2?";
    1688             case 0x00000723: return "MSR_UNC_CBO_2_PERFEVTSEL3?";
    1689             case 0x00000724: return "MSR_UNC_CBO_2_UNK_4";
    1690             case 0x00000725: return "MSR_UNC_CBO_2_UNK_5";
    1691             case 0x00000726: return "MSR_UNC_CBO_2_PER_CTR0";
    1692             case 0x00000727: return "MSR_UNC_CBO_2_PER_CTR1";
    1693             case 0x00000728: return "MSR_UNC_CBO_2_PER_CTR2?";
    1694             case 0x00000729: return "MSR_UNC_CBO_2_PER_CTR3?";
    1695             case 0x00000730: return "MSR_UNC_CBO_3_PERFEVTSEL0";
    1696             case 0x00000731: return "MSR_UNC_CBO_3_PERFEVTSEL1";
    1697             case 0x00000732: return "MSR_UNC_CBO_3_PERFEVTSEL2?";
    1698             case 0x00000733: return "MSR_UNC_CBO_3_PERFEVTSEL3?";
    1699             case 0x00000734: return "MSR_UNC_CBO_3_UNK_4";
    1700             case 0x00000735: return "MSR_UNC_CBO_3_UNK_5";
    1701             case 0x00000736: return "MSR_UNC_CBO_3_PER_CTR0";
    1702             case 0x00000737: return "MSR_UNC_CBO_3_PER_CTR1";
    1703             case 0x00000738: return "MSR_UNC_CBO_3_PER_CTR2?";
    1704             case 0x00000739: return "MSR_UNC_CBO_3_PER_CTR3?";
    1705             case 0x00000740: return "MSR_UNC_CBO_4_PERFEVTSEL0?";
    1706             case 0x00000741: return "MSR_UNC_CBO_4_PERFEVTSEL1?";
    1707             case 0x00000742: return "MSR_UNC_CBO_4_PERFEVTSEL2?";
    1708             case 0x00000743: return "MSR_UNC_CBO_4_PERFEVTSEL3?";
    1709             case 0x00000744: return "MSR_UNC_CBO_4_UNK_4";
    1710             case 0x00000745: return "MSR_UNC_CBO_4_UNK_5";
    1711             case 0x00000746: return "MSR_UNC_CBO_4_PER_CTR0?";
    1712             case 0x00000747: return "MSR_UNC_CBO_4_PER_CTR1?";
    1713             case 0x00000748: return "MSR_UNC_CBO_4_PER_CTR2?";
    1714             case 0x00000749: return "MSR_UNC_CBO_4_PER_CTR3?";
    1715 
    1716         }
    1717 
    1718     /*
    1719      * Bunch of unknown sandy bridge registers.  They might seem like the
    1720      * nehalem based xeon stuff, but the layout doesn't match.  I bet it's the
    1721      * same kind of registes though (i.e. uncore (UNC)).
    1722      *
    1723      * Kudos to Intel for keeping these a secret!  Many thanks guys!!
    1724      */
    1725     if (g_enmMicroarch == kCpumMicroarch_Intel_Core7_SandyBridge)
    1726         switch (uMsr)
    1727         {
    1728             case 0x00000a00: return "I7_SB_UNK_0000_0a00"; case 0x00000a01: return "I7_SB_UNK_0000_0a01";
    1729             case 0x00000a02: return "I7_SB_UNK_0000_0a02";
    1730             case 0x00000c00: return "I7_SB_UNK_0000_0c00"; case 0x00000c01: return "I7_SB_UNK_0000_0c01";
    1731             case 0x00000c06: return "I7_SB_UNK_0000_0c06"; case 0x00000c08: return "I7_SB_UNK_0000_0c08";
    1732             case 0x00000c09: return "I7_SB_UNK_0000_0c09"; case 0x00000c10: return "I7_SB_UNK_0000_0c10";
    1733             case 0x00000c11: return "I7_SB_UNK_0000_0c11"; case 0x00000c14: return "I7_SB_UNK_0000_0c14";
    1734             case 0x00000c15: return "I7_SB_UNK_0000_0c15"; case 0x00000c16: return "I7_SB_UNK_0000_0c16";
    1735             case 0x00000c17: return "I7_SB_UNK_0000_0c17"; case 0x00000c24: return "I7_SB_UNK_0000_0c24";
    1736             case 0x00000c30: return "I7_SB_UNK_0000_0c30"; case 0x00000c31: return "I7_SB_UNK_0000_0c31";
    1737             case 0x00000c32: return "I7_SB_UNK_0000_0c32"; case 0x00000c33: return "I7_SB_UNK_0000_0c33";
    1738             case 0x00000c34: return "I7_SB_UNK_0000_0c34"; case 0x00000c35: return "I7_SB_UNK_0000_0c35";
    1739             case 0x00000c36: return "I7_SB_UNK_0000_0c36"; case 0x00000c37: return "I7_SB_UNK_0000_0c37";
    1740             case 0x00000c38: return "I7_SB_UNK_0000_0c38"; case 0x00000c39: return "I7_SB_UNK_0000_0c39";
    1741             case 0x00000d04: return "I7_SB_UNK_0000_0d04";
    1742             case 0x00000d10: return "I7_SB_UNK_0000_0d10"; case 0x00000d11: return "I7_SB_UNK_0000_0d11";
    1743             case 0x00000d12: return "I7_SB_UNK_0000_0d12"; case 0x00000d13: return "I7_SB_UNK_0000_0d13";
    1744             case 0x00000d14: return "I7_SB_UNK_0000_0d14"; case 0x00000d15: return "I7_SB_UNK_0000_0d15";
    1745             case 0x00000d16: return "I7_SB_UNK_0000_0d16"; case 0x00000d17: return "I7_SB_UNK_0000_0d17";
    1746             case 0x00000d18: return "I7_SB_UNK_0000_0d18"; case 0x00000d19: return "I7_SB_UNK_0000_0d19";
    1747             case 0x00000d24: return "I7_SB_UNK_0000_0d24";
    1748             case 0x00000d30: return "I7_SB_UNK_0000_0d30"; case 0x00000d31: return "I7_SB_UNK_0000_0d31";
    1749             case 0x00000d32: return "I7_SB_UNK_0000_0d32"; case 0x00000d33: return "I7_SB_UNK_0000_0d33";
    1750             case 0x00000d34: return "I7_SB_UNK_0000_0d34"; case 0x00000d35: return "I7_SB_UNK_0000_0d35";
    1751             case 0x00000d36: return "I7_SB_UNK_0000_0d36"; case 0x00000d37: return "I7_SB_UNK_0000_0d37";
    1752             case 0x00000d38: return "I7_SB_UNK_0000_0d38"; case 0x00000d39: return "I7_SB_UNK_0000_0d39";
    1753             case 0x00000d44: return "I7_SB_UNK_0000_0d44";
    1754             case 0x00000d50: return "I7_SB_UNK_0000_0d50"; case 0x00000d51: return "I7_SB_UNK_0000_0d51";
    1755             case 0x00000d52: return "I7_SB_UNK_0000_0d52"; case 0x00000d53: return "I7_SB_UNK_0000_0d53";
    1756             case 0x00000d54: return "I7_SB_UNK_0000_0d54"; case 0x00000d55: return "I7_SB_UNK_0000_0d55";
    1757             case 0x00000d56: return "I7_SB_UNK_0000_0d56"; case 0x00000d57: return "I7_SB_UNK_0000_0d57";
    1758             case 0x00000d58: return "I7_SB_UNK_0000_0d58"; case 0x00000d59: return "I7_SB_UNK_0000_0d59";
    1759             case 0x00000d64: return "I7_SB_UNK_0000_0d64";
    1760             case 0x00000d70: return "I7_SB_UNK_0000_0d70"; case 0x00000d71: return "I7_SB_UNK_0000_0d71";
    1761             case 0x00000d72: return "I7_SB_UNK_0000_0d72"; case 0x00000d73: return "I7_SB_UNK_0000_0d73";
    1762             case 0x00000d74: return "I7_SB_UNK_0000_0d74"; case 0x00000d75: return "I7_SB_UNK_0000_0d75";
    1763             case 0x00000d76: return "I7_SB_UNK_0000_0d76"; case 0x00000d77: return "I7_SB_UNK_0000_0d77";
    1764             case 0x00000d78: return "I7_SB_UNK_0000_0d78"; case 0x00000d79: return "I7_SB_UNK_0000_0d79";
    1765             case 0x00000d84: return "I7_SB_UNK_0000_0d84";
    1766             case 0x00000d90: return "I7_SB_UNK_0000_0d90"; case 0x00000d91: return "I7_SB_UNK_0000_0d91";
    1767             case 0x00000d92: return "I7_SB_UNK_0000_0d92"; case 0x00000d93: return "I7_SB_UNK_0000_0d93";
    1768             case 0x00000d94: return "I7_SB_UNK_0000_0d94"; case 0x00000d95: return "I7_SB_UNK_0000_0d95";
    1769             case 0x00000d96: return "I7_SB_UNK_0000_0d96"; case 0x00000d97: return "I7_SB_UNK_0000_0d97";
    1770             case 0x00000d98: return "I7_SB_UNK_0000_0d98"; case 0x00000d99: return "I7_SB_UNK_0000_0d99";
    1771             case 0x00000da4: return "I7_SB_UNK_0000_0da4";
    1772             case 0x00000db0: return "I7_SB_UNK_0000_0db0"; case 0x00000db1: return "I7_SB_UNK_0000_0db1";
    1773             case 0x00000db2: return "I7_SB_UNK_0000_0db2"; case 0x00000db3: return "I7_SB_UNK_0000_0db3";
    1774             case 0x00000db4: return "I7_SB_UNK_0000_0db4"; case 0x00000db5: return "I7_SB_UNK_0000_0db5";
    1775             case 0x00000db6: return "I7_SB_UNK_0000_0db6"; case 0x00000db7: return "I7_SB_UNK_0000_0db7";
    1776             case 0x00000db8: return "I7_SB_UNK_0000_0db8"; case 0x00000db9: return "I7_SB_UNK_0000_0db9";
    1777         }
    1778 
    1779     /*
    1780      * Ditto for ivy bridge (observed on the i5-3570).  There are some haswell
    1781      * and sandybridge related docs on registers in this ares, but either
    1782      * things are different for ivy or they're very incomplete.  Again, kudos
    1783      * to intel!
    1784      */
    1785     if (g_enmMicroarch == kCpumMicroarch_Intel_Core7_IvyBridge)
    1786         switch (uMsr)
    1787         {
    1788             case 0x00000700: return "I7_IB_UNK_0000_0700"; case 0x00000701: return "I7_IB_UNK_0000_0701";
    1789             case 0x00000702: return "I7_IB_UNK_0000_0702"; case 0x00000703: return "I7_IB_UNK_0000_0703";
    1790             case 0x00000704: return "I7_IB_UNK_0000_0704"; case 0x00000705: return "I7_IB_UNK_0000_0705";
    1791             case 0x00000706: return "I7_IB_UNK_0000_0706"; case 0x00000707: return "I7_IB_UNK_0000_0707";
    1792             case 0x00000708: return "I7_IB_UNK_0000_0708"; case 0x00000709: return "I7_IB_UNK_0000_0709";
    1793             case 0x00000710: return "I7_IB_UNK_0000_0710"; case 0x00000711: return "I7_IB_UNK_0000_0711";
    1794             case 0x00000712: return "I7_IB_UNK_0000_0712"; case 0x00000713: return "I7_IB_UNK_0000_0713";
    1795             case 0x00000714: return "I7_IB_UNK_0000_0714"; case 0x00000715: return "I7_IB_UNK_0000_0715";
    1796             case 0x00000716: return "I7_IB_UNK_0000_0716"; case 0x00000717: return "I7_IB_UNK_0000_0717";
    1797             case 0x00000718: return "I7_IB_UNK_0000_0718"; case 0x00000719: return "I7_IB_UNK_0000_0719";
    1798             case 0x00000720: return "I7_IB_UNK_0000_0720"; case 0x00000721: return "I7_IB_UNK_0000_0721";
    1799             case 0x00000722: return "I7_IB_UNK_0000_0722"; case 0x00000723: return "I7_IB_UNK_0000_0723";
    1800             case 0x00000724: return "I7_IB_UNK_0000_0724"; case 0x00000725: return "I7_IB_UNK_0000_0725";
    1801             case 0x00000726: return "I7_IB_UNK_0000_0726"; case 0x00000727: return "I7_IB_UNK_0000_0727";
    1802             case 0x00000728: return "I7_IB_UNK_0000_0728"; case 0x00000729: return "I7_IB_UNK_0000_0729";
    1803             case 0x00000730: return "I7_IB_UNK_0000_0730"; case 0x00000731: return "I7_IB_UNK_0000_0731";
    1804             case 0x00000732: return "I7_IB_UNK_0000_0732"; case 0x00000733: return "I7_IB_UNK_0000_0733";
    1805             case 0x00000734: return "I7_IB_UNK_0000_0734"; case 0x00000735: return "I7_IB_UNK_0000_0735";
    1806             case 0x00000736: return "I7_IB_UNK_0000_0736"; case 0x00000737: return "I7_IB_UNK_0000_0737";
    1807             case 0x00000738: return "I7_IB_UNK_0000_0738"; case 0x00000739: return "I7_IB_UNK_0000_0739";
    1808             case 0x00000740: return "I7_IB_UNK_0000_0740"; case 0x00000741: return "I7_IB_UNK_0000_0741";
    1809             case 0x00000742: return "I7_IB_UNK_0000_0742"; case 0x00000743: return "I7_IB_UNK_0000_0743";
    1810             case 0x00000744: return "I7_IB_UNK_0000_0744"; case 0x00000745: return "I7_IB_UNK_0000_0745";
    1811             case 0x00000746: return "I7_IB_UNK_0000_0746"; case 0x00000747: return "I7_IB_UNK_0000_0747";
    1812             case 0x00000748: return "I7_IB_UNK_0000_0748"; case 0x00000749: return "I7_IB_UNK_0000_0749";
    1813 
    1814         }
    1815     return NULL;
    1816 }
    1817 
    1818 
    1819 /**
    1820  * Gets the name of an MSR.
    1821  *
    1822  * This may return a static buffer, so the content should only be considered
    1823  * valid until the next time this function is called!.
    1824  *
    1825  * @returns MSR name.
    1826  * @param   uMsr                The MSR in question.
    1827  */
    1828 static const char *getMsrName(uint32_t uMsr)
    1829 {
    1830     const char *pszReadOnly = getMsrNameHandled(uMsr);
    1831     if (pszReadOnly)
    1832         return pszReadOnly;
    1833 
    1834     /*
    1835      * This MSR needs looking into, return a TODO_XXXX_XXXX name.
    1836      */
    1837     static char s_szBuf[32];
    1838     RTStrPrintf(s_szBuf, sizeof(s_szBuf), "TODO_%04x_%04x", RT_HI_U16(uMsr), RT_LO_U16(uMsr));
    1839     return s_szBuf;
    1840 }
    1841 
    1842 
    1843 
    1844 /**
    1845  * Gets the name of an MSR range.
    1846  *
    1847  * This may return a static buffer, so the content should only be considered
    1848  * valid until the next time this function is called!.
    1849  *
    1850  * @returns MSR name.
    1851  * @param   uMsr                The first MSR in the range.
    1852  */
    1853 static const char *getMsrRangeName(uint32_t uMsr)
    1854 {
    1855     switch (uMsr)
    1856     {
    1857         case 0x00000040:
    1858             return g_enmMicroarch >= kCpumMicroarch_Intel_Core_Yonah ? "MSR_LASTBRANCH_n_FROM_IP" : "MSR_LASTBRANCH_n";
    1859         case 0x00000060:
    1860             if (g_enmMicroarch >= kCpumMicroarch_Intel_Core_Yonah)
    1861                 return "MSR_LASTBRANCH_n_TO_IP";
    1862             break;
    1863 
    1864         case 0x000003f8:
    1865         case 0x000003f9:
    1866         case 0x000003fa:
    1867             return "I7_MSR_PKG_Cn_RESIDENCY";
    1868         case 0x000003fc:
    1869         case 0x000003fd:
    1870         case 0x000003fe:
    1871             return "I7_MSR_CORE_Cn_RESIDENCY";
    1872 
    1873         case 0x00000400:
    1874             return "IA32_MCi_CTL_STATUS_ADDR_MISC";
    1875 
    1876         case 0x00000680:
    1877             return "MSR_LASTBRANCH_n_FROM_IP";
    1878         case 0x000006c0:
    1879             return "MSR_LASTBRANCH_n_TO_IP";
    1880 
    1881         case 0x00000800: case 0x00000801: case 0x00000802: case 0x00000803:
    1882         case 0x00000804: case 0x00000805: case 0x00000806: case 0x00000807:
    1883         case 0x00000808: case 0x00000809: case 0x0000080a: case 0x0000080b:
    1884         case 0x0000080c: case 0x0000080d: case 0x0000080e: case 0x0000080f:
    1885             return "IA32_X2APIC_n";
    1886     }
    1887 
    1888     static char s_szBuf[96];
    1889     const char *pszReadOnly = getMsrNameHandled(uMsr);
    1890     if (pszReadOnly)
    1891     {
    1892         /*
    1893          * Replace the last char with 'n'.
    1894          */
    1895         RTStrCopy(s_szBuf, sizeof(s_szBuf), pszReadOnly);
    1896         size_t off = strlen(s_szBuf);
    1897         if (off > 0)
    1898             off--;
    1899         if (off + 1 < sizeof(s_szBuf))
    1900         {
    1901             s_szBuf[off] = 'n';
    1902             s_szBuf[off + 1] = '\0';
    1903         }
    1904     }
    1905     else
    1906     {
    1907         /*
    1908          * This MSR needs looking into, return a TODO_XXXX_XXXX_n name.
    1909          */
    1910         RTStrPrintf(s_szBuf, sizeof(s_szBuf), "TODO_%04x_%04x_n", RT_HI_U16(uMsr), RT_LO_U16(uMsr));
    1911     }
    1912     return s_szBuf;
    1913 }
    1914 
    1915 
    1916 /**
    1917  * Returns the function name for MSRs that have one or two.
    1918  *
    1919  * @returns Function name if applicable, NULL if not.
    1920  * @param   uMsr            The MSR in question.
    1921  * @param   pfTakesValue    Whether this MSR function takes a value or not.
    1922  *                          Optional.
    1923  */
    1924 static const char *getMsrFnName(uint32_t uMsr, bool *pfTakesValue)
    1925 {
    1926     bool fTmp;
    1927     if (!pfTakesValue)
    1928         pfTakesValue = &fTmp;
    1929 
    1930     *pfTakesValue = false;
    1931 
    1932     switch (uMsr)
    1933     {
    1934         case 0x00000000: return "Ia32P5McAddr";
    1935         case 0x00000001: return "Ia32P5McType";
    1936         case 0x00000006:
    1937             if (g_enmMicroarch >= kCpumMicroarch_Intel_First && g_enmMicroarch <= kCpumMicroarch_Intel_P6_Core_Atom_First)
    1938                 return NULL; /* TR4 / cache tag on Pentium, but that's for later. */
    1939             return "Ia32MonitorFilterLineSize";
    1940         case 0x00000010: return "Ia32TimestampCounter";
    1941         case 0x00000017: *pfTakesValue = true; return "Ia32PlatformId";
    1942         case 0x0000001b: return "Ia32ApicBase";
    1943         case 0x0000002a: *pfTakesValue = true; return g_fIntelNetBurst ? "IntelP4EbcHardPowerOn" : "IntelEblCrPowerOn";
    1944         case 0x0000002b: *pfTakesValue = true; return g_fIntelNetBurst ? "IntelP4EbcSoftPowerOn" : NULL;
    1945         case 0x0000002c: *pfTakesValue = true; return g_fIntelNetBurst ? "IntelP4EbcFrequencyId" : NULL;
    1946         //case 0x00000033: return "IntelTestCtl";
    1947         case 0x00000034: return CPUMMICROARCH_IS_INTEL_CORE7(g_enmMicroarch)
    1948                              || CPUMMICROARCH_IS_INTEL_SILVERMONT_PLUS(g_enmMicroarch)
    1949                               ? "IntelI7SmiCount" : NULL;
    1950         case 0x00000035: return CPUMMICROARCH_IS_INTEL_CORE7(g_enmMicroarch) ? "IntelI7CoreThreadCount" : NULL;
    1951         case 0x0000003a: return "Ia32FeatureControl";
    1952 
    1953         case 0x00000040:
    1954         case 0x00000041:
    1955         case 0x00000042:
    1956         case 0x00000043:
    1957         case 0x00000044:
    1958         case 0x00000045:
    1959         case 0x00000046:
    1960         case 0x00000047:
    1961             return "IntelLastBranchFromToN";
    1962 
    1963         case 0x0000008b: return g_enmVendor == CPUMCPUVENDOR_AMD || g_enmVendor == CPUMCPUVENDOR_HYGON
    1964                               ? "AmdK8PatchLevel" : "Ia32BiosSignId";
    1965         case 0x0000009b: return "Ia32SmmMonitorCtl";
    1966 
    1967         case 0x000000a8:
    1968         case 0x000000a9:
    1969         case 0x000000aa:
    1970         case 0x000000ab:
    1971         case 0x000000ac:
    1972         case 0x000000ad:
    1973             *pfTakesValue = true;
    1974             return "IntelCore2EmttmCrTablesN";
    1975 
    1976         case 0x000000c1:
    1977         case 0x000000c2:
    1978         case 0x000000c3:
    1979         case 0x000000c4:
    1980             return "Ia32PmcN";
    1981         case 0x000000c5:
    1982         case 0x000000c6:
    1983         case 0x000000c7:
    1984         case 0x000000c8:
    1985             if (g_enmMicroarch >= kCpumMicroarch_Intel_Core7_First)
    1986                 return "Ia32PmcN";
    1987             return NULL;
    1988 
    1989         case 0x000000cd: *pfTakesValue = true; return "IntelP6FsbFrequency";
    1990         case 0x000000ce: return CPUMMICROARCH_IS_INTEL_CORE7(g_enmMicroarch)  ? "IntelPlatformInfo" : NULL;
    1991         case 0x000000e2: return "IntelPkgCStConfigControl";
    1992         case 0x000000e3: return "IntelCore2SmmCStMiscInfo";
    1993         case 0x000000e4: return "IntelPmgIoCaptureBase";
    1994         case 0x000000e7: return "Ia32MPerf";
    1995         case 0x000000e8: return "Ia32APerf";
    1996         case 0x000000ee: return "IntelCore1ExtConfig";
    1997         case 0x000000fe: *pfTakesValue = true; return "Ia32MtrrCap";
    1998         case 0x00000119: *pfTakesValue = true; return "IntelBblCrCtl";
    1999         case 0x0000011e: *pfTakesValue = true; return "IntelBblCrCtl3";
    2000 
    2001         case 0x00000130: return g_enmMicroarch == kCpumMicroarch_Intel_Core7_Westmere
    2002                              || g_enmMicroarch == kCpumMicroarch_Intel_Core7_Nehalem
    2003                               ? "IntelCpuId1FeatureMaskEcdx" : NULL;
    2004         case 0x00000131: return g_enmMicroarch == kCpumMicroarch_Intel_Core7_Westmere
    2005                              || g_enmMicroarch == kCpumMicroarch_Intel_Core7_Nehalem
    2006                               ? "IntelCpuId80000001FeatureMaskEcdx" : NULL;
    2007         case 0x00000132: return g_enmMicroarch >= kCpumMicroarch_Intel_Core7_SandyBridge
    2008                               ? "IntelCpuId1FeatureMaskEax" : NULL;
    2009         case 0x00000133: return g_enmMicroarch >= kCpumMicroarch_Intel_Core7_SandyBridge
    2010                               ? "IntelCpuId1FeatureMaskEcdx" : NULL;
    2011         case 0x00000134: return g_enmMicroarch >= kCpumMicroarch_Intel_Core7_SandyBridge
    2012                               ? "IntelCpuId80000001FeatureMaskEcdx" : NULL;
    2013         case 0x0000013c: return "IntelI7SandyAesNiCtl";
    2014         case 0x0000015f: return "IntelCore1DtsCalControl";
    2015         case 0x00000174: return "Ia32SysEnterCs";
    2016         case 0x00000175: return "Ia32SysEnterEsp";
    2017         case 0x00000176: return "Ia32SysEnterEip";
    2018         case 0x00000179: *pfTakesValue = true; return "Ia32McgCap";
    2019         case 0x0000017a: return "Ia32McgStatus";
    2020         case 0x0000017b: return "Ia32McgCtl";
    2021         case 0x0000017f: return "IntelI7SandyErrorControl"; /* SandyBridge. */
    2022         case 0x00000186: return "Ia32PerfEvtSelN";
    2023         case 0x00000187: return "Ia32PerfEvtSelN";
    2024         case 0x00000193: return /*g_fIntelNetBurst ? NULL :*/ NULL /* Core2_Penryn. */;
    2025         case 0x00000194: if (g_fIntelNetBurst) break;   *pfTakesValue = true; return "IntelFlexRatio";
    2026         case 0x00000198: *pfTakesValue = true; return "Ia32PerfStatus";
    2027         case 0x00000199: *pfTakesValue = true; return "Ia32PerfCtl";
    2028         case 0x0000019a: *pfTakesValue = true; return "Ia32ClockModulation";
    2029         case 0x0000019b: *pfTakesValue = true; return "Ia32ThermInterrupt";
    2030         case 0x0000019c: *pfTakesValue = true; return "Ia32ThermStatus";
    2031         case 0x0000019d: *pfTakesValue = true; return "Ia32Therm2Ctl";
    2032         case 0x000001a0: *pfTakesValue = true; return "Ia32MiscEnable";
    2033         case 0x000001a2: *pfTakesValue = true; return "IntelI7TemperatureTarget";
    2034         case 0x000001a6: return "IntelI7MsrOffCoreResponseN";
    2035         case 0x000001a7: return "IntelI7MsrOffCoreResponseN";
    2036         case 0x000001aa: return CPUMMICROARCH_IS_INTEL_CORE7(g_enmMicroarch) ? "IntelI7MiscPwrMgmt" : NULL /*"P6PicSensCfg"*/;
    2037         case 0x000001ad: *pfTakesValue = true; return "IntelI7TurboRatioLimit"; /* SandyBridge+, Silvermount+ */
    2038         case 0x000001c8: return g_enmMicroarch >= kCpumMicroarch_Intel_Core7_Nehalem ? "IntelI7LbrSelect" : NULL;
    2039         case 0x000001c9: return    g_enmMicroarch >= kCpumMicroarch_Intel_Core_Yonah
    2040                                 && g_enmMicroarch <= kCpumMicroarch_Intel_P6_Core_Atom_End
    2041                               ? "IntelLastBranchTos" : NULL /* Pentium M Dothan seems to have something else here. */;
    2042         case 0x000001d7: return g_fIntelNetBurst ? "P6LastIntFromIp" : NULL;
    2043         case 0x000001d8: return g_fIntelNetBurst ? "P6LastIntToIp"   : NULL;
    2044         case 0x000001d9: return "Ia32DebugCtl";
    2045         case 0x000001da: return g_fIntelNetBurst ? "IntelLastBranchTos" : NULL;
    2046         case 0x000001db: return g_fIntelNetBurst ? "IntelLastBranchFromToN" : "P6LastBranchFromIp";
    2047         case 0x000001dc: return g_fIntelNetBurst ? "IntelLastBranchFromToN" : "P6LastBranchToIp";
    2048         case 0x000001dd: return g_fIntelNetBurst ? "IntelLastBranchFromToN" : "P6LastIntFromIp";
    2049         case 0x000001de: return g_fIntelNetBurst ? "IntelLastBranchFromToN" : "P6LastIntToIp";
    2050         case 0x000001f0: return "IntelI7VirtualLegacyWireCap"; /* SandyBridge. */
    2051         case 0x000001f2: return "Ia32SmrrPhysBase";
    2052         case 0x000001f3: return "Ia32SmrrPhysMask";
    2053         case 0x000001f8: return "Ia32PlatformDcaCap";
    2054         case 0x000001f9: return "Ia32CpuDcaCap";
    2055         case 0x000001fa: return "Ia32Dca0Cap";
    2056         case 0x000001fc: return "IntelI7PowerCtl";
    2057 
    2058         case 0x00000200: case 0x00000202: case 0x00000204: case 0x00000206:
    2059         case 0x00000208: case 0x0000020a: case 0x0000020c: case 0x0000020e:
    2060         case 0x00000210: case 0x00000212: case 0x00000214: case 0x00000216:
    2061         case 0x00000218: case 0x0000021a: case 0x0000021c: case 0x0000021e:
    2062             return "Ia32MtrrPhysBaseN";
    2063         case 0x00000201: case 0x00000203: case 0x00000205: case 0x00000207:
    2064         case 0x00000209: case 0x0000020b: case 0x0000020d: case 0x0000020f:
    2065         case 0x00000211: case 0x00000213: case 0x00000215: case 0x00000217:
    2066         case 0x00000219: case 0x0000021b: case 0x0000021d: case 0x0000021f:
    2067             return "Ia32MtrrPhysMaskN";
    2068         case 0x00000250:
    2069         case 0x00000258: case 0x00000259:
    2070         case 0x00000268: case 0x00000269: case 0x0000026a: case 0x0000026b:
    2071         case 0x0000026c: case 0x0000026d: case 0x0000026e: case 0x0000026f:
    2072             return "Ia32MtrrFixed";
    2073         case 0x00000277: *pfTakesValue = true; return "Ia32Pat";
    2074 
    2075         case 0x00000280: case 0x00000281:  case 0x00000282: case 0x00000283:
    2076         case 0x00000284: case 0x00000285:  case 0x00000286: case 0x00000287:
    2077         case 0x00000288: case 0x00000289:  case 0x0000028a: case 0x0000028b:
    2078         case 0x0000028c: case 0x0000028d:  case 0x0000028e: case 0x0000028f:
    2079         case 0x00000290: case 0x00000291:  case 0x00000292: case 0x00000293:
    2080         case 0x00000294: case 0x00000295:  //case 0x00000296: case 0x00000297:
    2081         //case 0x00000298: case 0x00000299:  case 0x0000029a: case 0x0000029b:
    2082         //case 0x0000029c: case 0x0000029d:  case 0x0000029e: case 0x0000029f:
    2083             return "Ia32McNCtl2";
    2084 
    2085         case 0x000002ff: return "Ia32MtrrDefType";
    2086         //case 0x00000305: return g_fIntelNetBurst ? TODO : NULL;
    2087         case 0x00000309: return g_fIntelNetBurst ? NULL /** @todo P4 */ : "Ia32FixedCtrN";
    2088         case 0x0000030a: return g_fIntelNetBurst ? NULL /** @todo P4 */ : "Ia32FixedCtrN";
    2089         case 0x0000030b: return g_fIntelNetBurst ? NULL /** @todo P4 */ : "Ia32FixedCtrN";
    2090         case 0x00000345: *pfTakesValue = true; return "Ia32PerfCapabilities";
    2091         /* Note! Lots of P4 MSR 0x00000360..0x00000371. */
    2092         case 0x0000038d: return "Ia32FixedCtrCtrl";
    2093         case 0x0000038e: *pfTakesValue = true; return "Ia32PerfGlobalStatus";
    2094         case 0x0000038f: return "Ia32PerfGlobalCtrl";
    2095         case 0x00000390: return "Ia32PerfGlobalOvfCtrl";
    2096         case 0x00000391: return "IntelI7UncPerfGlobalCtrl";             /* S,H,X */
    2097         case 0x00000392: return "IntelI7UncPerfGlobalStatus";           /* S,H,X */
    2098         case 0x00000393: return "IntelI7UncPerfGlobalOvfCtrl";          /* X. ASSUMING this is the same on sandybridge and later. */
    2099         case 0x00000394: return g_enmMicroarch < kCpumMicroarch_Intel_Core7_SandyBridge ? "IntelI7UncPerfFixedCtr"  /* X */   : "IntelI7UncPerfFixedCtrCtrl"; /* >= S,H */
    2100         case 0x00000395: return g_enmMicroarch < kCpumMicroarch_Intel_Core7_SandyBridge ? "IntelI7UncPerfFixedCtrCtrl" /* X*/ : "IntelI7UncPerfFixedCtr";     /* >= S,H */
    2101         case 0x00000396: return g_enmMicroarch < kCpumMicroarch_Intel_Core7_SandyBridge ? "IntelI7UncAddrOpcodeMatch" /* X */ : "IntelI7UncCBoxConfig";       /* >= S,H */
    2102         case 0x0000039c: return "IntelI7SandyPebsNumAlt";
    2103          /* Note! Lots of P4 MSR 0x000003a0..0x000003e1. */
    2104         case 0x000003b0: return g_fIntelNetBurst ? NULL : g_enmMicroarch < kCpumMicroarch_Intel_Core7_SandyBridge ? "IntelI7UncPmcN" /* X */            : "IntelI7UncArbPerfCtrN";      /* >= S,H */
    2105         case 0x000003b1: return g_fIntelNetBurst ? NULL : g_enmMicroarch < kCpumMicroarch_Intel_Core7_SandyBridge ? "IntelI7UncPmcN" /* X */            : "IntelI7UncArbPerfCtrN";      /* >= S,H */
    2106         case 0x000003b2: return g_fIntelNetBurst ? NULL : g_enmMicroarch < kCpumMicroarch_Intel_Core7_SandyBridge ? "IntelI7UncPmcN" /* X */            : "IntelI7UncArbPerfEvtSelN";   /* >= S,H */
    2107         case 0x000003b3: return g_fIntelNetBurst ? NULL : g_enmMicroarch < kCpumMicroarch_Intel_Core7_SandyBridge ? "IntelI7UncPmcN" /* X */            : "IntelI7UncArbPerfEvtSelN";   /* >= S,H */
    2108         case 0x000003b4: case 0x000003b5: case 0x000003b6: case 0x000003b7:
    2109             return g_fIntelNetBurst ? NULL : "IntelI7UncPmcN";
    2110         case 0x000003c0: case 0x000003c1: case 0x000003c2: case 0x000003c3:
    2111         case 0x000003c4: case 0x000003c5: case 0x000003c6: case 0x000003c7:
    2112             return g_fIntelNetBurst ? NULL : "IntelI7UncPerfEvtSelN";
    2113         case 0x000003f1: return "Ia32PebsEnable";
    2114         case 0x000003f6: return g_fIntelNetBurst ? NULL /*??*/ : "IntelI7PebsLdLat";
    2115         case 0x000003f8: return g_fIntelNetBurst ? NULL : "IntelI7PkgCnResidencyN";
    2116         case 0x000003f9: return "IntelI7PkgCnResidencyN";
    2117         case 0x000003fa: return "IntelI7PkgCnResidencyN";
    2118         case 0x000003fc: return "IntelI7CoreCnResidencyN";
    2119         case 0x000003fd: return "IntelI7CoreCnResidencyN";
    2120         case 0x000003fe: return "IntelI7CoreCnResidencyN";
    2121 
    2122         case 0x00000478: return g_enmMicroarch == kCpumMicroarch_Intel_Core2_Penryn ? "IntelCpuId1FeatureMaskEcdx" : NULL;
    2123         case 0x00000480: *pfTakesValue = true; return "Ia32VmxBasic";
    2124         case 0x00000481: *pfTakesValue = true; return "Ia32VmxPinbasedCtls";
    2125         case 0x00000482: *pfTakesValue = true; return "Ia32VmxProcbasedCtls";
    2126         case 0x00000483: *pfTakesValue = true; return "Ia32VmxExitCtls";
    2127         case 0x00000484: *pfTakesValue = true; return "Ia32VmxEntryCtls";
    2128         case 0x00000485: *pfTakesValue = true; return "Ia32VmxMisc";
    2129         case 0x00000486: *pfTakesValue = true; return "Ia32VmxCr0Fixed0";
    2130         case 0x00000487: *pfTakesValue = true; return "Ia32VmxCr0Fixed1";
    2131         case 0x00000488: *pfTakesValue = true; return "Ia32VmxCr4Fixed0";
    2132         case 0x00000489: *pfTakesValue = true; return "Ia32VmxCr4Fixed1";
    2133         case 0x0000048a: *pfTakesValue = true; return "Ia32VmxVmcsEnum";
    2134         case 0x0000048b: *pfTakesValue = true; return "Ia32VmxProcBasedCtls2";
    2135         case 0x0000048c: *pfTakesValue = true; return "Ia32VmxEptVpidCap";
    2136         case 0x0000048d: *pfTakesValue = true; return "Ia32VmxTruePinbasedCtls";
    2137         case 0x0000048e: *pfTakesValue = true; return "Ia32VmxTrueProcbasedCtls";
    2138         case 0x0000048f: *pfTakesValue = true; return "Ia32VmxTrueExitCtls";
    2139         case 0x00000490: *pfTakesValue = true; return "Ia32VmxTrueEntryCtls";
    2140         case 0x00000491: *pfTakesValue = true; return "Ia32VmxVmFunc";
    2141 
    2142         case 0x000004c1:
    2143         case 0x000004c2:
    2144         case 0x000004c3:
    2145         case 0x000004c4:
    2146         case 0x000004c5:
    2147         case 0x000004c6:
    2148         case 0x000004c7:
    2149         case 0x000004c8:
    2150             return "Ia32PmcN";
    2151 
    2152         case 0x000005a0: return "IntelCore2PeciControl"; /* Core2_Penryn. */
    2153 
    2154         case 0x00000600: return "Ia32DsArea";
    2155         case 0x00000601: *pfTakesValue = true; return "IntelI7SandyVrCurrentConfig";
    2156         case 0x00000603: *pfTakesValue = true; return "IntelI7SandyVrMiscConfig";
    2157         case 0x00000606: *pfTakesValue = true; return "IntelI7SandyRaplPowerUnit";
    2158         case 0x0000060a: *pfTakesValue = true; return "IntelI7SandyPkgCnIrtlN";
    2159         case 0x0000060b: *pfTakesValue = true; return "IntelI7SandyPkgCnIrtlN";
    2160         case 0x0000060c: *pfTakesValue = true; return "IntelI7SandyPkgCnIrtlN";
    2161         case 0x0000060d: *pfTakesValue = true; return "IntelI7SandyPkgC2Residency";
    2162 
    2163         case 0x00000610: *pfTakesValue = true; return "IntelI7RaplPkgPowerLimit";
    2164         case 0x00000611: *pfTakesValue = true; return "IntelI7RaplPkgEnergyStatus";
    2165         case 0x00000613: *pfTakesValue = true; return "IntelI7RaplPkgPerfStatus";
    2166         case 0x00000614: *pfTakesValue = true; return "IntelI7RaplPkgPowerInfo";
    2167         case 0x00000618: *pfTakesValue = true; return "IntelI7RaplDramPowerLimit";
    2168         case 0x00000619: *pfTakesValue = true; return "IntelI7RaplDramEnergyStatus";
    2169         case 0x0000061b: *pfTakesValue = true; return "IntelI7RaplDramPerfStatus";
    2170         case 0x0000061c: *pfTakesValue = true; return "IntelI7RaplDramPowerInfo";
    2171         case 0x00000638: *pfTakesValue = true; return "IntelI7RaplPp0PowerLimit";
    2172         case 0x00000639: *pfTakesValue = true; return "IntelI7RaplPp0EnergyStatus";
    2173         case 0x0000063a: *pfTakesValue = true; return "IntelI7RaplPp0Policy";
    2174         case 0x0000063b: *pfTakesValue = true; return "IntelI7RaplPp0PerfStatus";
    2175         case 0x00000640: *pfTakesValue = true; return "IntelI7RaplPp1PowerLimit";
    2176         case 0x00000641: *pfTakesValue = true; return "IntelI7RaplPp1EnergyStatus";
    2177         case 0x00000642: *pfTakesValue = true; return "IntelI7RaplPp1Policy";
    2178         case 0x00000648: *pfTakesValue = true; return "IntelI7IvyConfigTdpNominal";
    2179         case 0x00000649: *pfTakesValue = true; return "IntelI7IvyConfigTdpLevel1";
    2180         case 0x0000064a: *pfTakesValue = true; return "IntelI7IvyConfigTdpLevel2";
    2181         case 0x0000064b: return "IntelI7IvyConfigTdpControl";
    2182         case 0x0000064c: return "IntelI7IvyTurboActivationRatio";
    2183 
    2184         case 0x00000660: return "IntelAtSilvCoreC1Recidency";
    2185 
    2186         case 0x00000680: case 0x00000681: case 0x00000682: case 0x00000683:
    2187         case 0x00000684: case 0x00000685: case 0x00000686: case 0x00000687:
    2188         case 0x00000688: case 0x00000689: case 0x0000068a: case 0x0000068b:
    2189         case 0x0000068c: case 0x0000068d: case 0x0000068e: case 0x0000068f:
    2190         //case 0x00000690: case 0x00000691: case 0x00000692: case 0x00000693:
    2191         //case 0x00000694: case 0x00000695: case 0x00000696: case 0x00000697:
    2192         //case 0x00000698: case 0x00000699: case 0x0000069a: case 0x0000069b:
    2193         //case 0x0000069c: case 0x0000069d: case 0x0000069e: case 0x0000069f:
    2194             return "IntelLastBranchFromN";
    2195         case 0x000006c0: case 0x000006c1: case 0x000006c2: case 0x000006c3:
    2196         case 0x000006c4: case 0x000006c5: case 0x000006c6: case 0x000006c7:
    2197         case 0x000006c8: case 0x000006c9: case 0x000006ca: case 0x000006cb:
    2198         case 0x000006cc: case 0x000006cd: case 0x000006ce: case 0x000006cf:
    2199         //case 0x000006d0: case 0x000006d1: case 0x000006d2: case 0x000006d3:
    2200         //case 0x000006d4: case 0x000006d5: case 0x000006d6: case 0x000006d7:
    2201         //case 0x000006d8: case 0x000006d9: case 0x000006da: case 0x000006db:
    2202         //case 0x000006dc: case 0x000006dd: case 0x000006de: case 0x000006df:
    2203             return "IntelLastBranchToN";
    2204         case 0x000006e0: return "Ia32TscDeadline"; /** @todo detect this correctly! */
    2205 
    2206         case 0x00000c80: return g_enmMicroarch > kCpumMicroarch_Intel_Core7_Nehalem ? "Ia32DebugInterface" : NULL;
    2207 
    2208         case 0xc0000080: return "Amd64Efer";
    2209         case 0xc0000081: return "Amd64SyscallTarget";
    2210         case 0xc0000082: return "Amd64LongSyscallTarget";
    2211         case 0xc0000083: return "Amd64CompSyscallTarget";
    2212         case 0xc0000084: return "Amd64SyscallFlagMask";
    2213         case 0xc0000100: return "Amd64FsBase";
    2214         case 0xc0000101: return "Amd64GsBase";
    2215         case 0xc0000102: return "Amd64KernelGsBase";
    2216         case 0xc0000103: return "Amd64TscAux";
    2217         case 0xc0000104: return "AmdFam15hTscRate";
    2218         case 0xc0000105: return "AmdFam15hLwpCfg";
    2219         case 0xc0000106: return "AmdFam15hLwpCbAddr";
    2220         case 0xc0000408: return "AmdFam10hMc4MiscN";
    2221         case 0xc0000409: return "AmdFam10hMc4MiscN";
    2222         case 0xc000040a: return "AmdFam10hMc4MiscN";
    2223         case 0xc000040b: return "AmdFam10hMc4MiscN";
    2224         case 0xc000040c: return "AmdFam10hMc4MiscN";
    2225         case 0xc000040d: return "AmdFam10hMc4MiscN";
    2226         case 0xc000040e: return "AmdFam10hMc4MiscN";
    2227         case 0xc000040f: return "AmdFam10hMc4MiscN";
    2228         case 0xc0010000: return "AmdK8PerfCtlN";
    2229         case 0xc0010001: return "AmdK8PerfCtlN";
    2230         case 0xc0010002: return "AmdK8PerfCtlN";
    2231         case 0xc0010003: return "AmdK8PerfCtlN";
    2232         case 0xc0010004: return "AmdK8PerfCtrN";
    2233         case 0xc0010005: return "AmdK8PerfCtrN";
    2234         case 0xc0010006: return "AmdK8PerfCtrN";
    2235         case 0xc0010007: return "AmdK8PerfCtrN";
    2236         case 0xc0010010: *pfTakesValue = true; return "AmdK8SysCfg";
    2237         case 0xc0010015: return "AmdK8HwCr";
    2238         case 0xc0010016: case 0xc0010018: return "AmdK8IorrBaseN";
    2239         case 0xc0010017: case 0xc0010019: return "AmdK8IorrMaskN";
    2240         case 0xc001001a: case 0xc001001d: return "AmdK8TopOfMemN";
    2241         case 0xc001001f: return "AmdK8NbCfg1";
    2242         case 0xc0010020: return "AmdK8PatchLoader";
    2243         case 0xc0010022: return "AmdK8McXcptRedir";
    2244         case 0xc0010030: case 0xc0010031: case 0xc0010032:
    2245         case 0xc0010033: case 0xc0010034: case 0xc0010035:
    2246             return "AmdK8CpuNameN";
    2247         case 0xc001003e: *pfTakesValue = true; return "AmdK8HwThermalCtrl";
    2248         case 0xc001003f: return "AmdK8SwThermalCtrl";
    2249         case 0xc0010041: *pfTakesValue = true; return "AmdK8FidVidControl";
    2250         case 0xc0010042: *pfTakesValue = true; return "AmdK8FidVidStatus";
    2251         case 0xc0010044: case 0xc0010045: case 0xc0010046: case 0xc0010047:
    2252         case 0xc0010048: case 0xc0010049: case 0xc001004a: //case 0xc001004b:
    2253             return "AmdK8McCtlMaskN";
    2254         case 0xc0010050: case 0xc0010051: case 0xc0010052: case 0xc0010053:
    2255             return "AmdK8SmiOnIoTrapN";
    2256         case 0xc0010054: return "AmdK8SmiOnIoTrapCtlSts";
    2257         case 0xc0010055: return "AmdK8IntPendingMessage";
    2258         case 0xc0010056: return "AmdK8SmiTriggerIoCycle";
    2259         case 0xc0010058: return "AmdFam10hMmioCfgBaseAddr";
    2260         case 0xc0010059: return "AmdFam10hTrapCtlMaybe";
    2261         case 0xc0010061: *pfTakesValue = true; return "AmdFam10hPStateCurLimit";
    2262         case 0xc0010062: *pfTakesValue = true; return "AmdFam10hPStateControl";
    2263         case 0xc0010063: *pfTakesValue = true; return "AmdFam10hPStateStatus";
    2264         case 0xc0010064: case 0xc0010065: case 0xc0010066: case 0xc0010067:
    2265         case 0xc0010068: case 0xc0010069: case 0xc001006a: case 0xc001006b:
    2266             *pfTakesValue = true; return "AmdFam10hPStateN";
    2267         case 0xc0010070: *pfTakesValue = true; return "AmdFam10hCofVidControl";
    2268         case 0xc0010071: *pfTakesValue = true; return "AmdFam10hCofVidStatus";
    2269         case 0xc0010073: return "AmdFam10hCStateIoBaseAddr";
    2270         case 0xc0010074: return "AmdFam10hCpuWatchdogTimer";
    2271         // case 0xc0010075: return "AmdFam15hApmlTdpLimit";
    2272         // case 0xc0010077: return "AmdFam15hCpuPowerInTdp";
    2273         // case 0xc0010078: return "AmdFam15hPowerAveragingPeriod";
    2274         // case 0xc0010079: return "AmdFam15hDramCtrlCmdThrottle";
    2275         // case 0xc0010080: return "AmdFam16hFreqSensFeedbackMonActCnt0";
    2276         // case 0xc0010081: return "AmdFam16hFreqSensFeedbackMonRefCnt0";
    2277         case 0xc0010111: return "AmdK8SmmBase";     /** @todo probably misdetected ign/gp due to locking */
    2278         case 0xc0010112: return "AmdK8SmmAddr";     /** @todo probably misdetected ign/gp due to locking */
    2279         case 0xc0010113: return "AmdK8SmmMask";     /** @todo probably misdetected ign/gp due to locking */
    2280         case 0xc0010114: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_90nm_AMDV ? "AmdK8VmCr" : NULL;        /** @todo probably misdetected due to locking */
    2281         case 0xc0010115: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_90nm      ? "AmdK8IgnNe" : NULL;
    2282         case 0xc0010116: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_90nm      ? "AmdK8SmmCtl" : NULL;
    2283         case 0xc0010117: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_90nm_AMDV ? "AmdK8VmHSavePa" : NULL;   /** @todo probably misdetected due to locking */
    2284         case 0xc0010118: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_90nm_AMDV ? "AmdFam10hVmLockKey" : NULL;
    2285         case 0xc0010119: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_90nm      ? "AmdFam10hSmmLockKey" : NULL; /* Not documented by BKDG, found in netbsd patch. */
    2286         case 0xc001011a: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_90nm      ? "AmdFam10hLocalSmiStatus" : NULL;
    2287         case 0xc0010140: *pfTakesValue = true; return "AmdFam10hOsVisWrkIdLength";
    2288         case 0xc0010141: *pfTakesValue = true; return "AmdFam10hOsVisWrkStatus";
    2289         case 0xc0010200: case 0xc0010202: case 0xc0010204: case 0xc0010206:
    2290         case 0xc0010208: case 0xc001020a: //case 0xc001020c: case 0xc001020e:
    2291             return "AmdK8PerfCtlN";
    2292         case 0xc0010201: case 0xc0010203: case 0xc0010205: case 0xc0010207:
    2293         case 0xc0010209: case 0xc001020b: //case 0xc001020d: case 0xc001020f:
    2294             return "AmdK8PerfCtrN";
    2295         case 0xc0010230: case 0xc0010232: case 0xc0010234: case 0xc0010236:
    2296         //case 0xc0010238: case 0xc001023a: case 0xc001030c: case 0xc001023e:
    2297             return "AmdFam16hL2IPerfCtlN";
    2298         case 0xc0010231: case 0xc0010233: case 0xc0010235: case 0xc0010237:
    2299         //case 0xc0010239: case 0xc001023b: case 0xc001023d: case 0xc001023f:
    2300             return "AmdFam16hL2IPerfCtrN";
    2301         case 0xc0010240: case 0xc0010242: case 0xc0010244: case 0xc0010246:
    2302         //case 0xc0010248: case 0xc001024a: case 0xc001024c: case 0xc001024e:
    2303             return "AmdFam15hNorthbridgePerfCtlN";
    2304         case 0xc0010241: case 0xc0010243: case 0xc0010245: case 0xc0010247:
    2305         //case 0xc0010249: case 0xc001024b: case 0xc001024d: case 0xc001024f:
    2306             return "AmdFam15hNorthbridgePerfCtrN";
    2307         case 0xc0011000: *pfTakesValue = true; return "AmdK7MicrocodeCtl";
    2308         case 0xc0011001: *pfTakesValue = true; return "AmdK7ClusterIdMaybe";
    2309         case 0xc0011002: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_First ? "AmdK8CpuIdCtlStd07hEbax" : NULL;
    2310         case 0xc0011003: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_First ? "AmdK8CpuIdCtlStd06hEcx"  : NULL;
    2311         case 0xc0011004: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_First ? "AmdK8CpuIdCtlStd01hEdcx" : NULL;
    2312         case 0xc0011005: return g_enmMicroarch >= kCpumMicroarch_AMD_K8_First ? "AmdK8CpuIdCtlExt01hEdcx" : NULL;
    2313         case 0xc0011006: return "AmdK7DebugStatusMaybe";
    2314         case 0xc0011007: return "AmdK7BHTraceBaseMaybe";
    2315         case 0xc0011008: return "AmdK7BHTracePtrMaybe";
    2316         case 0xc0011009: return "AmdK7BHTraceLimitMaybe";
    2317         case 0xc001100a: return "AmdK7HardwareDebugToolCfgMaybe";
    2318         case 0xc001100b: return "AmdK7FastFlushCountMaybe";
    2319         case 0xc001100c: return "AmdK7NodeId"; /** @todo dunno if this was there is K7 already. Kinda doubt it. */
    2320         case 0xc0011019: return g_enmMicroarch >= kCpumMicroarch_AMD_15h_Piledriver ? "AmdK7DrXAddrMaskN" : NULL;
    2321         case 0xc001101a: return g_enmMicroarch >= kCpumMicroarch_AMD_15h_Piledriver ? "AmdK7DrXAddrMaskN" : NULL;
    2322         case 0xc001101b: return g_enmMicroarch >= kCpumMicroarch_AMD_15h_Piledriver ? "AmdK7DrXAddrMaskN" : NULL;
    2323         case 0xc0011020: return "AmdK7LoadStoreCfg";
    2324         case 0xc0011021: return "AmdK7InstrCacheCfg";
    2325         case 0xc0011022: return "AmdK7DataCacheCfg";
    2326         case 0xc0011023: return CPUMMICROARCH_IS_AMD_FAM_15H(g_enmMicroarch) ? "AmdFam15hCombUnitCfg" : "AmdK7BusUnitCfg";
    2327         case 0xc0011024: return "AmdK7DebugCtl2Maybe";
    2328         case 0xc0011025: return "AmdK7Dr0DataMatchMaybe";
    2329         case 0xc0011026: return "AmdK7Dr0DataMaskMaybe";
    2330         case 0xc0011027: return "AmdK7DrXAddrMaskN";
    2331         case 0xc0011028: return g_enmMicroarch >= kCpumMicroarch_AMD_15h_First ? "AmdFam15hFpuCfg" : NULL;
    2332         case 0xc0011029: return g_enmMicroarch >= kCpumMicroarch_AMD_15h_First ? "AmdFam15hDecoderCfg" : NULL;
    2333         case 0xc001102a: return CPUMMICROARCH_IS_AMD_FAM_15H(g_enmMicroarch)   ? "AmdFam15hCombUnitCfg2"
    2334                               : CPUMMICROARCH_IS_AMD_FAM_10H(g_enmMicroarch) || g_enmMicroarch > kCpumMicroarch_AMD_15h_End
    2335                               ? "AmdFam10hBusUnitCfg2" /* 10h & 16h */ : NULL;
    2336         case 0xc001102b: return CPUMMICROARCH_IS_AMD_FAM_15H(g_enmMicroarch)   ? "AmdFam15hCombUnitCfg3" : NULL;
    2337         case 0xc001102c: return CPUMMICROARCH_IS_AMD_FAM_15H(g_enmMicroarch)   ? "AmdFam15hExecUnitCfg" : NULL;
    2338         case 0xc001102d: return CPUMMICROARCH_IS_AMD_FAM_15H(g_enmMicroarch)   ? "AmdFam15hLoadStoreCfg2" : NULL;
    2339         case 0xc0011030: return "AmdFam10hIbsFetchCtl";
    2340         case 0xc0011031: return "AmdFam10hIbsFetchLinAddr";
    2341         case 0xc0011032: return "AmdFam10hIbsFetchPhysAddr";
    2342         case 0xc0011033: return "AmdFam10hIbsOpExecCtl";
    2343         case 0xc0011034: return "AmdFam10hIbsOpRip";
    2344         case 0xc0011035: return "AmdFam10hIbsOpData";
    2345         case 0xc0011036: return "AmdFam10hIbsOpData2";
    2346         case 0xc0011037: return "AmdFam10hIbsOpData3";
    2347         case 0xc0011038: return "AmdFam10hIbsDcLinAddr";
    2348         case 0xc0011039: return "AmdFam10hIbsDcPhysAddr";
    2349         case 0xc001103a: return "AmdFam10hIbsCtl";
    2350         case 0xc001103b: return "AmdFam14hIbsBrTarget";
    2351     }
    2352     return NULL;
    2353 }
    2354 
    2355 
    2356 /**
    2357  * Names CPUMCPU variables that MSRs corresponds to.
    2358  *
    2359  * @returns The variable name @a uMsr corresponds to, NULL if no variable.
    2360  * @param   uMsr                The MSR in question.
    2361  */
    2362 static const char *getMsrCpumCpuVarName(uint32_t uMsr)
    2363 {
    2364     switch (uMsr)
    2365     {
    2366         case 0x00000250: return "GuestMsrs.msr.MtrrFix64K_00000";
    2367         case 0x00000258: return "GuestMsrs.msr.MtrrFix16K_80000";
    2368         case 0x00000259: return "GuestMsrs.msr.MtrrFix16K_A0000";
    2369         case 0x00000268: return "GuestMsrs.msr.MtrrFix4K_C0000";
    2370         case 0x00000269: return "GuestMsrs.msr.MtrrFix4K_C8000";
    2371         case 0x0000026a: return "GuestMsrs.msr.MtrrFix4K_D0000";
    2372         case 0x0000026b: return "GuestMsrs.msr.MtrrFix4K_D8000";
    2373         case 0x0000026c: return "GuestMsrs.msr.MtrrFix4K_E0000";
    2374         case 0x0000026d: return "GuestMsrs.msr.MtrrFix4K_E8000";
    2375         case 0x0000026e: return "GuestMsrs.msr.MtrrFix4K_F0000";
    2376         case 0x0000026f: return "GuestMsrs.msr.MtrrFix4K_F8000";
    2377         case 0x00000277: return "Guest.msrPAT";
    2378         case 0x000002ff: return "GuestMsrs.msr.MtrrDefType";
    2379     }
    2380     return NULL;
    2381 }
    2382 
    2383 
    2384 /**
    2385  * Checks whether the MSR should read as zero for some reason.
    2386  *
    2387  * @returns true if the register should read as zero, false if not.
    2388  * @param   uMsr                The MSR.
    2389  */
    2390 static bool doesMsrReadAsZero(uint32_t uMsr)
    2391 {
    2392     switch (uMsr)
    2393     {
    2394         case 0x00000088: return true; // "BBL_CR_D0" - RAZ until understood/needed.
    2395         case 0x00000089: return true; // "BBL_CR_D1" - RAZ until understood/needed.
    2396         case 0x0000008a: return true; // "BBL_CR_D2" - RAZ until understood/needed.
    2397 
    2398         /* Non-zero, but unknown register. */
    2399         case 0x0000004a:
    2400         case 0x0000004b:
    2401         case 0x0000004c:
    2402         case 0x0000004d:
    2403         case 0x0000004e:
    2404         case 0x0000004f:
    2405         case 0x00000050:
    2406         case 0x00000051:
    2407         case 0x00000052:
    2408         case 0x00000053:
    2409         case 0x00000054:
    2410         case 0x0000008c:
    2411         case 0x0000008d:
    2412         case 0x0000008e:
    2413         case 0x0000008f:
    2414         case 0x00000090:
    2415         case 0xc0011011:
    2416             return true;
    2417     }
    2418 
    2419     return false;
    2420 }
    2421 
    2422 
    2423 /**
    2424  * Gets the skip mask for the given MSR.
    2425  *
    2426  * @returns Skip mask (0 means skipping nothing).
    2427  * @param   uMsr                The MSR.
    2428  */
    2429 static uint64_t getGenericSkipMask(uint32_t uMsr)
    2430 {
    2431     switch (uMsr)
    2432     {
    2433         case 0x0000013c: return 3; /* AES-NI lock bit ++. */
    2434 
    2435         case 0x000001f2: return UINT64_C(0xfffff00f); /* Ia32SmrrPhysBase - Only writable in SMM. */
    2436         case 0x000001f3: return UINT64_C(0xfffff800); /* Ia32SmrrPhysMask - Only writable in SMM. */
    2437 
    2438         /* these two have lock bits. */
    2439         case 0x0000064b: return UINT64_C(0x80000003);
    2440         case 0x0000064c: return UINT64_C(0x800000ff);
    2441 
    2442         case 0xc0010015: return 1; /* SmmLock bit */
    2443 
    2444         /* SmmLock effect: */
    2445         case 0xc0010111: return UINT32_MAX;
    2446         case 0xc0010112: return UINT64_C(0xfffe0000) | ((RT_BIT_64(vbCpuRepGetPhysAddrWidth()) - 1) & ~(uint64_t)UINT32_MAX);
    2447         case 0xc0010113: return UINT64_C(0xfffe773f) | ((RT_BIT_64(vbCpuRepGetPhysAddrWidth()) - 1) & ~(uint64_t)UINT32_MAX);
    2448         case 0xc0010116: return 0x1f;
    2449 
    2450         case 0xc0010114: return RT_BIT_64(3) /* SVM lock */ | RT_BIT_64(4) /* SvmeDisable */;
    2451 
    2452         /* Canonical */
    2453         case 0xc0011034:
    2454         case 0xc0011038:
    2455         case 0xc001103b:
    2456             return UINT64_C(0xffff800000000000);
    2457 
    2458         case 0x00000060: case 0x00000061: case 0x00000062: case 0x00000063:
    2459         case 0x00000064: case 0x00000065: case 0x00000066: case 0x00000067:
    2460         case 0x00000040: case 0x00000041: case 0x00000042: case 0x00000043:
    2461         case 0x00000044: case 0x00000045: case 0x00000046: case 0x00000047:
    2462         case 0x00000600:
    2463             if (g_enmMicroarch >= kCpumMicroarch_Intel_Core2_First)
    2464                 return UINT64_C(0xffff800000000000);
    2465             break;
    2466 
    2467 
    2468         /* Write only bits. */
    2469         case 0xc0010041: return RT_BIT_64(16); /* FIDVID_CTL.InitFidVid */
    2470 
    2471         /* Time counters - fudge them to avoid incorrect ignore masks. */
    2472         case 0x00000010:
    2473         case 0x000000e7:
    2474         case 0x000000e8:
    2475             return RT_BIT_32(29) - 1;
    2476     }
    2477     return 0;
    2478 }
    2479 
    2480 
    2481 
    2482 
    2483 /** queryMsrWriteBadness return values. */
    2484 typedef enum
    2485 {
    2486     /** . */
    2487     VBCPUREPBADNESS_MOSTLY_HARMLESS = 0,
    2488     /** Not a problem if accessed with care. */
    2489     VBCPUREPBADNESS_MIGHT_BITE,
    2490     /** Worse than a bad james bond villain. */
    2491     VBCPUREPBADNESS_BOND_VILLAIN
    2492 } VBCPUREPBADNESS;
    2493 
    2494 
    2495 /**
    2496  * Backlisting and graylisting of MSRs which may cause tripple faults.
    2497  *
    2498  * @returns Badness factor.
    2499  * @param   uMsr                The MSR in question.
    2500  */
    2501 static VBCPUREPBADNESS queryMsrWriteBadness(uint32_t uMsr)
    2502 {
    2503     /** @todo Having trouble in the 0xc0010247,0xc0011006,?? region on Bulldozer. */
    2504     /** @todo Having trouble in the 0xc001100f,0xc001100d,?? region on Opteron
    2505      *        2384. */
    2506 
    2507     switch (uMsr)
    2508     {
    2509         case 0x00000050:
    2510         case 0x00000051:
    2511         case 0x00000052:
    2512         case 0x00000053:
    2513         case 0x00000054:
    2514 
    2515         case 0x00001006:
    2516         case 0x00001007:
    2517             return VBCPUREPBADNESS_BOND_VILLAIN;
    2518 
    2519         case 0x0000120e:
    2520         case 0x00001233:
    2521         case 0x00001239:
    2522         case 0x00001249:
    2523         case 0x0000124a:
    2524         case 0x00001404:
    2525         case 0x00001405:
    2526         case 0x00001413:
    2527         case 0x0000142c: /* Caused rip to be set to 297 or some such weirdness... */
    2528         case 0x0000142e:
    2529         case 0x00001435:
    2530         case 0x00001436:
    2531         case 0x00001438:
    2532         case 0x0000317f:
    2533             if (g_enmVendor == CPUMCPUVENDOR_VIA || g_enmVendor == CPUMCPUVENDOR_SHANGHAI)
    2534                 return VBCPUREPBADNESS_BOND_VILLAIN;
    2535             break;
    2536 
    2537         case 0xc0010010:
    2538         case 0xc0010016:
    2539         case 0xc0010017:
    2540         case 0xc0010018:
    2541         case 0xc0010019:
    2542         case 0xc001001a:
    2543         case 0xc001001d:
    2544 
    2545         case 0xc0010058: /* MMIO Configuration Base Address on AMD Zen CPUs. */
    2546             if (CPUMMICROARCH_IS_AMD_FAM_ZEN(g_enmMicroarch))
    2547                 return VBCPUREPBADNESS_BOND_VILLAIN;
    2548             break;
    2549 
    2550         case 0xc0010064: /* P-state fequency, voltage, ++. */
    2551         case 0xc0010065: /* P-state fequency, voltage, ++. */
    2552         case 0xc0010066: /* P-state fequency, voltage, ++. */
    2553         case 0xc0010067: /* P-state fequency, voltage, ++. */
    2554         case 0xc0010068: /* P-state fequency, voltage, ++. */
    2555         case 0xc0010069: /* P-state fequency, voltage, ++. */
    2556         case 0xc001006a: /* P-state fequency, voltage, ++. */
    2557         case 0xc001006b: /* P-state fequency, voltage, ++. */
    2558         case 0xc0010070: /* COFVID Control. */
    2559         case 0xc001101e:
    2560         case 0xc0011021: /* IC_CFG (instruction cache configuration) */
    2561         case 0xc0011023: /* CU_CFG (combined unit configuration) */
    2562         case 0xc001102c: /* EX_CFG (execution unit configuration) */
    2563             return VBCPUREPBADNESS_BOND_VILLAIN;
    2564 
    2565         case 0xc0011012:
    2566             if (CPUMMICROARCH_IS_AMD_FAM_0FH(g_enmMicroarch))
    2567                 return VBCPUREPBADNESS_MIGHT_BITE;
    2568             break;
    2569 
    2570         /* KVM MSRs that are unsafe to touch. */
    2571         case 0x00000011: /* KVM */
    2572         case 0x00000012: /* KVM */
    2573             return VBCPUREPBADNESS_BOND_VILLAIN;
    2574 
    2575         /*
    2576          * The TSC is tricky -- writing it isn't a problem, but if we put back the original
    2577          * value, we'll throw it out of whack. If we're on an SMP OS that uses the TSC for timing,
    2578          * we'll likely kill it, especially if we can't do the modification very quickly.
    2579          */
    2580         case 0x00000010: /* IA32_TIME_STAMP_COUNTER */
    2581             if (!g_MsrAcc.fAtomic)
    2582                 return VBCPUREPBADNESS_BOND_VILLAIN;
    2583             break;
    2584 
    2585         /*
    2586          * The following MSRs are not safe to modify in a typical OS if we can't do it atomically,
    2587          * i.e. read/modify/restore without allowing any other code to execute. Everything related
    2588          * to syscalls will blow up in our face if we go back to userland with modified MSRs.
    2589          */
    2590 //        case 0x0000001b: /* IA32_APIC_BASE */
    2591         case 0xc0000081: /* MSR_K6_STAR */
    2592         case 0xc0000082: /* AMD64_STAR64 */
    2593         case 0xc0000083: /* AMD64_STARCOMPAT */
    2594         case 0xc0000084: /* AMD64_SYSCALL_FLAG_MASK */
    2595         case 0xc0000100: /* AMD64_FS_BASE */
    2596         case 0xc0000101: /* AMD64_GS_BASE */
    2597         case 0xc0000102: /* AMD64_KERNEL_GS_BASE */
    2598             if (!g_MsrAcc.fAtomic)
    2599                 return VBCPUREPBADNESS_MIGHT_BITE;
    2600             break;
    2601 
    2602         case 0x000001a0: /* IA32_MISC_ENABLE */
    2603         case 0x00000199: /* IA32_PERF_CTL */
    2604             return VBCPUREPBADNESS_MIGHT_BITE;
    2605 
    2606         case 0x000005a0: /* C2_PECI_CTL */
    2607         case 0x000005a1: /* C2_UNK_0000_05a1 */
    2608             if (g_enmVendor == CPUMCPUVENDOR_INTEL)
    2609                 return VBCPUREPBADNESS_MIGHT_BITE;
    2610             break;
    2611 
    2612         case 0x00002000: /* P6_CR0. */
    2613         case 0x00002003: /* P6_CR3. */
    2614         case 0x00002004: /* P6_CR4. */
    2615             if (g_enmVendor == CPUMCPUVENDOR_INTEL)
    2616                 return VBCPUREPBADNESS_MIGHT_BITE;
    2617             break;
    2618         case 0xc0000080: /* MSR_K6_EFER */
    2619             return VBCPUREPBADNESS_MIGHT_BITE;
    2620     }
    2621     return VBCPUREPBADNESS_MOSTLY_HARMLESS;
    2622 }
    2623 
    2624 
    2625 /**
    2626  * Checks if this might be a VIA/Shanghai dummy register.
    2627  *
    2628  * @returns true if it's a dummy, false if it isn't.
    2629  * @param   uMsr                The MSR.
    2630  * @param   uValue              The value.
    2631  * @param   fFlags              The flags.
    2632  */
    2633 static bool isMsrViaShanghaiDummy(uint32_t uMsr, uint64_t uValue, uint32_t fFlags)
    2634 {
    2635     if (g_enmVendor != CPUMCPUVENDOR_VIA && g_enmVendor != CPUMCPUVENDOR_SHANGHAI)
    2636         return false;
    2637 
    2638     if (uValue)
    2639         return false;
    2640 
    2641     if (fFlags)
    2642         return false;
    2643 
    2644     switch (uMsr)
    2645     {
    2646         case 0x00000010:
    2647         case 0x0000001b:
    2648         case 0x000000c1:
    2649         case 0x000000c2:
    2650         case 0x0000011e:
    2651         case 0x00000186:
    2652         case 0x00000187:
    2653         //case 0x00000200 ... (mtrrs will be detected)
    2654             return false;
    2655 
    2656         case 0xc0000080:
    2657         case 0xc0000081:
    2658         case 0xc0000082:
    2659         case 0xc0000083:
    2660             if (vbCpuRepSupportsLongMode())
    2661                 return false;
    2662             break;
    2663     }
    2664 
    2665     if (uMsr >= 0x00001200 && uMsr <= 0x00003fff && queryMsrWriteBadness(uMsr) != VBCPUREPBADNESS_MOSTLY_HARMLESS)
    2666         return false;
    2667 
    2668     if (   !msrProberModifyNoChange(uMsr)
    2669         && !msrProberModifyZero(uMsr))
    2670         return false;
    2671 
    2672     uint64_t fIgnMask  = 0;
    2673     uint64_t fGpMask   = 0;
    2674     int rc = msrProberModifyBitChanges(uMsr, &fIgnMask, &fGpMask, 0);
    2675     if (RT_FAILURE(rc))
    2676         return false;
    2677 
    2678     if (fIgnMask != UINT64_MAX)
    2679         return false;
    2680     if (fGpMask != 0)
    2681         return false;
    2682 
    2683     return true;
    2684 }
    2685 
    2686 
    2687 /**
    2688  * Adjusts the ignore and GP masks for MSRs which contains canonical addresses.
    2689  *
    2690  * @param   uMsr                The MSR.
    2691  * @param   pfIgn               Pointer to the ignore mask.
    2692  * @param   pfGp                Pointer to the GP mask.
    2693  */
    2694 static void adjustCanonicalIgnAndGpMasks(uint32_t uMsr, uint64_t *pfIgn, uint64_t *pfGp)
    2695 {
    2696     RT_NOREF1(pfIgn);
    2697     if (!vbCpuRepSupportsLongMode())
    2698         return;
    2699     switch (uMsr)
    2700     {
    2701         case 0x00000175:
    2702         case 0x00000176:
    2703         case 0x000001da:
    2704         case 0x000001db:
    2705         case 0x000001dc:
    2706         case 0x000001de:
    2707         case 0x00000600:
    2708             if (*pfGp == UINT64_C(0xffff800000000000))
    2709                 *pfGp = 0;
    2710             break;
    2711         case 0x000001dd:
    2712             if (*pfGp == UINT64_C(0x7fff800000000000) || *pfGp == UINT64_C(0xffff800000000000)) /* why is the top bit writable? */
    2713                 *pfGp = 0;
    2714             break;
    2715 
    2716         case 0xc0000082:
    2717         case 0xc0000083:
    2718         case 0xc0000100:
    2719         case 0xc0000101:
    2720         case 0xc0000102:
    2721             *pfGp = 0;
    2722             break;
    2723     }
    2724 }
    2725 
    2726 
    2727 
    2728 /**
    2729  * Prints a 64-bit value in the best way.
    2730  *
    2731  * @param   uValue              The value.
    2732  */
    2733 static void printMsrValueU64(uint64_t uValue)
    2734 {
    2735     if (uValue == 0)
    2736         vbCpuRepPrintf(", 0");
    2737     else if (uValue == UINT16_MAX)
    2738         vbCpuRepPrintf(", UINT16_MAX");
    2739     else if (uValue == UINT32_MAX)
    2740         vbCpuRepPrintf(", UINT32_MAX");
    2741     else if (uValue == UINT64_MAX)
    2742         vbCpuRepPrintf(", UINT64_MAX");
    2743     else if (uValue == UINT64_C(0xffffffff00000000))
    2744         vbCpuRepPrintf(", ~(uint64_t)UINT32_MAX");
    2745     else if (uValue <= (UINT32_MAX >> 1))
    2746         vbCpuRepPrintf(", %#llx", uValue);
    2747     else if (uValue <= UINT32_MAX)
    2748         vbCpuRepPrintf(", UINT32_C(%#llx)", uValue);
    2749     else
    2750         vbCpuRepPrintf(", UINT64_C(%#llx)", uValue);
    2751 }
    2752 
    2753 
    2754 /**
    2755  * Prints the newline after an MSR line has been printed.
    2756  *
    2757  * This is used as a hook to slow down the output and make sure the remote
    2758  * terminal or/and output file has received the last update before we go and
    2759  * crash probing the next MSR.
    2760  */
    2761 static void printMsrNewLine(void)
    2762 {
    2763     vbCpuRepPrintf("\n");
    2764 #if 1
    2765     RTThreadSleep(8);
    2766 #endif
    2767 }
    2768 
    2769 static int printMsrWriteOnly(uint32_t uMsr, const char *pszWrFnName, const char *pszAnnotation)
    2770 {
    2771     if (!pszWrFnName)
    2772         pszWrFnName = "IgnoreWrite";
    2773     vbCpuRepPrintf(pszAnnotation
    2774                    ? "    MFN(%#010x, \"%s\", WriteOnly, %s), /* %s */"
    2775                    : "    MFN(%#010x, \"%s\", WriteOnly, %s),",
    2776                    uMsr, getMsrName(uMsr), pszWrFnName, pszAnnotation);
    2777     printMsrNewLine();
    2778     return VINF_SUCCESS;
    2779 }
    2780 
    2781 
    2782 static int printMsrValueReadOnly(uint32_t uMsr, uint64_t uValue, const char *pszAnnotation)
    2783 {
    2784     vbCpuRepPrintf("    MVO(%#010x, \"%s\"", uMsr, getMsrName(uMsr));
    2785     printMsrValueU64(uValue);
    2786     vbCpuRepPrintf("),");
    2787     if (pszAnnotation)
    2788         vbCpuRepPrintf(" /* %s */", pszAnnotation);
    2789     printMsrNewLine();
    2790     return VINF_SUCCESS;
    2791 }
    2792 
    2793 
    2794 
    2795 static int printMsrValueIgnoreWritesNamed(uint32_t uMsr, uint64_t uValue, const char *pszName, const char *pszAnnotation)
    2796 {
    2797     vbCpuRepPrintf("    MVI(%#010x, \"%s\"", uMsr, pszName);
    2798     printMsrValueU64(uValue);
    2799     vbCpuRepPrintf("),");
    2800     if (pszAnnotation)
    2801         vbCpuRepPrintf(" /* %s */", pszAnnotation);
    2802     printMsrNewLine();
    2803     return VINF_SUCCESS;
    2804 }
    2805 
    2806 
    2807 static int printMsrValueIgnoreWrites(uint32_t uMsr, uint64_t uValue, const char *pszAnnotation)
    2808 {
    2809     return printMsrValueIgnoreWritesNamed(uMsr, uValue, getMsrName(uMsr), pszAnnotation);
    2810 }
    2811 
    2812 
    2813 static int printMsrValueExtended(uint32_t uMsr, uint64_t uValue, uint64_t fIgnMask, uint64_t fGpMask,
    2814                                   const char *pszAnnotation)
    2815 {
    2816     vbCpuRepPrintf("    MVX(%#010x, \"%s\"", uMsr, getMsrName(uMsr));
    2817     printMsrValueU64(uValue);
    2818     printMsrValueU64(fIgnMask);
    2819     printMsrValueU64(fGpMask);
    2820     vbCpuRepPrintf("),");
    2821     if (pszAnnotation)
    2822         vbCpuRepPrintf(" /* %s */", pszAnnotation);
    2823     printMsrNewLine();
    2824     return VINF_SUCCESS;
    2825 }
    2826 
    2827 
    2828 static int printMsrRangeValueReadOnly(uint32_t uMsr, uint32_t uLast, uint64_t uValue, const char *pszAnnotation)
    2829 {
    2830     vbCpuRepPrintf("    RVO(%#010x, %#010x, \"%s\"", uMsr, uLast, getMsrRangeName(uMsr));
    2831     printMsrValueU64(uValue);
    2832     vbCpuRepPrintf("),");
    2833     if (pszAnnotation)
    2834         vbCpuRepPrintf(" /* %s */", pszAnnotation);
    2835     printMsrNewLine();
    2836     return VINF_SUCCESS;
    2837 }
    2838 
    2839 
    2840 static int printMsrRangeValueIgnoreWritesNamed(uint32_t uMsr, uint32_t uLast, uint64_t uValue, const char *pszName, const char *pszAnnotation)
    2841 {
    2842     vbCpuRepPrintf("    RVI(%#010x, %#010x, \"%s\"", uMsr, uLast, pszName);
    2843     printMsrValueU64(uValue);
    2844     vbCpuRepPrintf("),");
    2845     if (pszAnnotation)
    2846         vbCpuRepPrintf(" /* %s */", pszAnnotation);
    2847     printMsrNewLine();
    2848     return VINF_SUCCESS;
    2849 }
    2850 
    2851 
    2852 static int printMsrRangeValueIgnoreWrites(uint32_t uMsr, uint32_t uLast, uint64_t uValue, const char *pszAnnotation)
    2853 {
    2854     return printMsrRangeValueIgnoreWritesNamed(uMsr, uLast, uValue, getMsrRangeName(uMsr), pszAnnotation);
    2855 }
    2856 
    2857 
    2858 static int printMsrFunction(uint32_t uMsr, const char *pszRdFnName, const char *pszWrFnName, const char *pszAnnotation)
    2859 {
    2860     if (!pszRdFnName)
    2861         pszRdFnName = getMsrFnName(uMsr, NULL);
    2862     if (!pszWrFnName)
    2863         pszWrFnName = pszRdFnName;
    2864     vbCpuRepPrintf("    MFN(%#010x, \"%s\", %s, %s),", uMsr, getMsrName(uMsr), pszRdFnName, pszWrFnName);
    2865     if (pszAnnotation)
    2866         vbCpuRepPrintf(" /* %s */", pszAnnotation);
    2867     printMsrNewLine();
    2868     return VINF_SUCCESS;
    2869 }
    2870 
    2871 
    2872 static int printMsrFunctionReadOnly(uint32_t uMsr, const char *pszRdFnName, const char *pszAnnotation)
    2873 {
    2874     if (!pszRdFnName)
    2875         pszRdFnName = getMsrFnName(uMsr, NULL);
    2876     vbCpuRepPrintf("    MFO(%#010x, \"%s\", %s),", uMsr, getMsrName(uMsr), pszRdFnName);
    2877     if (pszAnnotation)
    2878         vbCpuRepPrintf(" /* %s */", pszAnnotation);
    2879     printMsrNewLine();
    2880     return VINF_SUCCESS;
    2881 }
    2882 
    2883 
    2884 static int printMsrFunctionIgnoreWrites(uint32_t uMsr, const char *pszRdFnName, const char *pszAnnotation)
    2885 {
    2886     if (!pszRdFnName)
    2887         pszRdFnName = getMsrFnName(uMsr, NULL);
    2888     vbCpuRepPrintf("    MFI(%#010x, \"%s\", %s),", uMsr, getMsrName(uMsr), pszRdFnName);
    2889     if (pszAnnotation)
    2890         vbCpuRepPrintf(" /* %s */", pszAnnotation);
    2891     printMsrNewLine();
    2892     return VINF_SUCCESS;
    2893 }
    2894 
    2895 
    2896 static int printMsrFunctionIgnoreMask(uint32_t uMsr, const char *pszRdFnName, const char *pszWrFnName,
    2897                                       uint64_t fIgnMask, const char *pszAnnotation)
    2898 {
    2899     if (!pszRdFnName)
    2900         pszRdFnName = getMsrFnName(uMsr, NULL);
    2901     if (!pszWrFnName)
    2902         pszWrFnName = pszRdFnName;
    2903     vbCpuRepPrintf("    MFW(%#010x, \"%s\", %s, %s", uMsr, getMsrName(uMsr), pszRdFnName, pszWrFnName);
    2904     printMsrValueU64(fIgnMask);
    2905     vbCpuRepPrintf("),");
    2906     if (pszAnnotation)
    2907         vbCpuRepPrintf(" /* %s */", pszAnnotation);
    2908     printMsrNewLine();
    2909     return VINF_SUCCESS;
    2910 }
    2911 
    2912 
    2913 static int printMsrFunctionExtended(uint32_t uMsr, const char *pszRdFnName, const char *pszWrFnName, uint64_t uValue,
    2914                                     uint64_t fIgnMask, uint64_t fGpMask, const char *pszAnnotation)
    2915 {
    2916     if (!pszRdFnName)
    2917         pszRdFnName = getMsrFnName(uMsr, NULL);
    2918     if (!pszWrFnName)
    2919         pszWrFnName = pszRdFnName;
    2920     vbCpuRepPrintf("    MFX(%#010x, \"%s\", %s, %s", uMsr, getMsrName(uMsr), pszRdFnName, pszWrFnName);
    2921     printMsrValueU64(uValue);
    2922     printMsrValueU64(fIgnMask);
    2923     printMsrValueU64(fGpMask);
    2924     vbCpuRepPrintf("),");
    2925     if (pszAnnotation)
    2926         vbCpuRepPrintf(" /* %s */", pszAnnotation);
    2927     printMsrNewLine();
    2928     return VINF_SUCCESS;
    2929 }
    2930 
    2931 
    2932 static int printMsrFunctionExtendedIdxVal(uint32_t uMsr, const char *pszRdFnName, const char *pszWrFnName, uint64_t uValue,
    2933                                           uint64_t fIgnMask, uint64_t fGpMask, const char *pszAnnotation)
    2934 {
    2935     if (!pszRdFnName)
    2936         pszRdFnName = getMsrFnName(uMsr, NULL);
    2937     if (!pszWrFnName)
    2938         pszWrFnName = pszRdFnName;
    2939     vbCpuRepPrintf("    MFX(%#010x, \"%s\", %s, %s, %#x", uMsr, getMsrName(uMsr), pszRdFnName, pszWrFnName, uValue);
    2940     printMsrValueU64(fIgnMask);
    2941     printMsrValueU64(fGpMask);
    2942     vbCpuRepPrintf("),");
    2943     if (pszAnnotation)
    2944         vbCpuRepPrintf(" /* %s */", pszAnnotation);
    2945     printMsrNewLine();
    2946     return VINF_SUCCESS;
    2947 }
    2948 
    2949 
    2950 static int printMsrFunctionCpumCpu(uint32_t uMsr, const char *pszRdFnName, const char *pszWrFnName,
    2951                                    const char *pszCpumCpuStorage, const char *pszAnnotation)
    2952 {
    2953     if (!pszRdFnName)
    2954         pszRdFnName = getMsrFnName(uMsr, NULL);
    2955     if (!pszWrFnName)
    2956         pszWrFnName = pszRdFnName;
    2957     if (!pszCpumCpuStorage)
    2958         pszCpumCpuStorage = getMsrCpumCpuVarName(uMsr);
    2959     if (!pszCpumCpuStorage)
    2960         return RTMsgErrorRc(VERR_NOT_FOUND, "Missing CPUMCPU member for %#s (%#x)\n", getMsrName(uMsr), uMsr);
    2961     vbCpuRepPrintf("    MFS(%#010x, \"%s\", %s, %s, %s),", uMsr, getMsrName(uMsr), pszRdFnName, pszWrFnName, pszCpumCpuStorage);
    2962     if (pszAnnotation)
    2963         vbCpuRepPrintf(" /* %s */", pszAnnotation);
    2964     printMsrNewLine();
    2965     return VINF_SUCCESS;
    2966 }
    2967 
    2968 
    2969 static int printMsrFunctionCpumCpuEx(uint32_t uMsr, const char *pszRdFnName, const char *pszWrFnName,
    2970                                      const char *pszCpumCpuStorage, uint64_t fIgnMask, uint64_t fGpMask,
    2971                                      const char *pszAnnotation)
    2972 {
    2973     if (!pszRdFnName)
    2974         pszRdFnName = getMsrFnName(uMsr, NULL);
    2975     if (!pszWrFnName)
    2976         pszWrFnName = pszRdFnName;
    2977     if (!pszCpumCpuStorage)
    2978         pszCpumCpuStorage = getMsrCpumCpuVarName(uMsr);
    2979     if (!pszCpumCpuStorage)
    2980         return RTMsgErrorRc(VERR_NOT_FOUND, "Missing CPUMCPU member for %#s (%#x)\n", getMsrName(uMsr), uMsr);
    2981     vbCpuRepPrintf("    MFZ(%#010x, \"%s\", %s, %s, %s", uMsr, getMsrName(uMsr), pszRdFnName, pszWrFnName, pszCpumCpuStorage);
    2982     printMsrValueU64(fIgnMask);
    2983     printMsrValueU64(fGpMask);
    2984     vbCpuRepPrintf("),");
    2985     if (pszAnnotation)
    2986         vbCpuRepPrintf(" /* %s */", pszAnnotation);
    2987     printMsrNewLine();
    2988     return VINF_SUCCESS;
    2989 }
    2990 
    2991 
    2992 static int printMsrRangeFunction(uint32_t uMsr, uint32_t uLast, const char *pszRdFnName, const char *pszWrFnName,
    2993                                  const char *pszAnnotation)
    2994 {
    2995     if (!pszRdFnName)
    2996         pszRdFnName = getMsrFnName(uMsr, NULL);
    2997     if (!pszWrFnName)
    2998         pszWrFnName = pszRdFnName;
    2999     vbCpuRepPrintf("    RFN(%#010x, %#010x, \"%s\", %s, %s),", uMsr, uLast, getMsrRangeName(uMsr), pszRdFnName, pszWrFnName);
    3000     if (pszAnnotation)
    3001         vbCpuRepPrintf(" /* %s */", pszAnnotation);
    3002     printMsrNewLine();
    3003     return VINF_SUCCESS;
    3004 }
    3005 
    3006 
    3007 static int printMsrRangeFunctionEx(uint32_t uMsr, uint32_t uLast, const char *pszRdFnName, const char *pszWrFnName,
    3008                                    uint64_t uValue, uint64_t fIgnMask, uint64_t fGpMask, const char *pszAnnotation)
    3009 {
    3010     if (!pszRdFnName)
    3011         pszRdFnName = getMsrFnName(uMsr, NULL);
    3012     if (!pszWrFnName)
    3013         pszWrFnName = pszRdFnName;
    3014     vbCpuRepPrintf("    RSN(%#010x, %#010x, \"%s\", %s, %s", uMsr, uLast, getMsrRangeName(uMsr), pszRdFnName, pszWrFnName);
    3015     printMsrValueU64(uValue);
    3016     printMsrValueU64(fIgnMask);
    3017     printMsrValueU64(fGpMask);
    3018     vbCpuRepPrintf("),");
    3019     if (pszAnnotation)
    3020         vbCpuRepPrintf(" /* %s */", pszAnnotation);
    3021     printMsrNewLine();
    3022     return VINF_SUCCESS;
    3023 }
    3024 
    3025 
    3026 static int printMsrRangeFunctionExIdxVal(uint32_t uMsr, uint32_t uLast, const char *pszRdFnName, const char *pszWrFnName,
    3027                                          uint64_t uValue, uint64_t fIgnMask, uint64_t fGpMask, const char *pszAnnotation)
    3028 {
    3029     if (!pszRdFnName)
    3030         pszRdFnName = getMsrFnName(uMsr, NULL);
    3031     if (!pszWrFnName)
    3032         pszWrFnName = pszRdFnName;
    3033     vbCpuRepPrintf("    RSN(%#010x, %#010x, \"%s\", %s, %s, %#x",
    3034                    uMsr, uLast, getMsrRangeName(uMsr), pszRdFnName, pszWrFnName, uValue);
    3035     printMsrValueU64(fIgnMask);
    3036     printMsrValueU64(fGpMask);
    3037     vbCpuRepPrintf("),");
    3038     if (pszAnnotation)
    3039         vbCpuRepPrintf(" /* %s */", pszAnnotation);
    3040     printMsrNewLine();
    3041     return VINF_SUCCESS;
    3042 }
    3043 
    3044 
    3045 static int printMsrAlias(uint32_t uMsr, uint32_t uTarget, const char *pszAnnotation)
    3046 {
    3047     vbCpuRepPrintf("    MAL(%#010x, \"%s\", %#010x),", uMsr, getMsrName(uMsr), uTarget);
    3048     if (pszAnnotation)
    3049         vbCpuRepPrintf(" /* %s */", pszAnnotation);
    3050     printMsrNewLine();
    3051     return VINF_SUCCESS;
    3052 }
    3053 
    3054 
    3055 
    3056 static const char *annotateValue(uint64_t uValue)
    3057 {
    3058     static char s_szBuf[40];
    3059     if (uValue <= UINT32_MAX)
    3060         RTStrPrintf(s_szBuf, sizeof(s_szBuf), "value=%#llx", uValue);
    3061     else
    3062         RTStrPrintf(s_szBuf, sizeof(s_szBuf), "value=%#x`%08x", RT_HI_U32(uValue), RT_LO_U32(uValue));
    3063     return s_szBuf;
    3064 }
    3065 
    3066 
    3067 static const char *annotateValueExtra(const char *pszExtra, uint64_t uValue)
    3068 {
    3069     static char s_szBuf[40];
    3070     if (uValue <= UINT32_MAX)
    3071         RTStrPrintf(s_szBuf, sizeof(s_szBuf), "%s value=%#llx", pszExtra, uValue);
    3072     else
    3073         RTStrPrintf(s_szBuf, sizeof(s_szBuf), "%s value=%#x`%08x", pszExtra, RT_HI_U32(uValue), RT_LO_U32(uValue));
    3074     return s_szBuf;
    3075 }
    3076 
    3077 
    3078 static const char *annotateIfMissingBits(uint64_t uValue, uint64_t fBits)
    3079 {
    3080     static char s_szBuf[80];
    3081     if ((uValue & fBits) == fBits)
    3082         return annotateValue(uValue);
    3083     RTStrPrintf(s_szBuf, sizeof(s_szBuf), "XXX: Unexpected value %#llx - wanted bits %#llx to be set.", uValue, fBits);
    3084     return s_szBuf;
    3085 }
    3086 
    3087 
    3088 static int reportMsr_Generic(uint32_t uMsr, uint32_t fFlags, uint64_t uValue)
    3089 {
    3090     int         rc;
    3091     bool        fTakesValue = false;
    3092     const char *pszFnName   = getMsrFnName(uMsr, &fTakesValue);
    3093 
    3094     if (fFlags & VBCPUREPMSR_F_WRITE_ONLY)
    3095         rc = printMsrWriteOnly(uMsr, pszFnName, NULL);
    3096     else
    3097     {
    3098         bool    fReadAsZero = doesMsrReadAsZero(uMsr);
    3099         fTakesValue = fTakesValue && !fReadAsZero;
    3100 
    3101 
    3102         switch (queryMsrWriteBadness(uMsr))
    3103         {
    3104             /* This is what we're here for... */
    3105             case VBCPUREPBADNESS_MOSTLY_HARMLESS:
    3106             {
    3107                 if (   msrProberModifyNoChange(uMsr)
    3108                     || msrProberModifyZero(uMsr))
    3109                 {
    3110                     uint64_t fSkipMask = getGenericSkipMask(uMsr);
    3111                     uint64_t fIgnMask  = 0;
    3112                     uint64_t fGpMask   = 0;
    3113                     rc = msrProberModifyBitChanges(uMsr, &fIgnMask, &fGpMask, fSkipMask);
    3114                     if (RT_FAILURE(rc))
    3115                         return rc;
    3116                     adjustCanonicalIgnAndGpMasks(uMsr, &fIgnMask, &fGpMask);
    3117 
    3118                     if (pszFnName)
    3119                     {
    3120                         if (fGpMask == 0 && fIgnMask == UINT64_MAX && !fTakesValue)
    3121                             rc = printMsrFunctionIgnoreWrites(uMsr, pszFnName, annotateValue(uValue));
    3122                         else if (fGpMask == 0 && fIgnMask == 0 && (!fTakesValue || uValue == 0))
    3123                             rc = printMsrFunction(uMsr, pszFnName, pszFnName, annotateValue(uValue));
    3124                         else
    3125                             rc = printMsrFunctionExtended(uMsr, pszFnName, pszFnName, fTakesValue ? uValue : 0,
    3126                                                           fIgnMask, fGpMask, annotateValue(uValue));
    3127                     }
    3128                     else if (fGpMask == 0 && fIgnMask == UINT64_MAX)
    3129                         rc = printMsrValueIgnoreWrites(uMsr, fReadAsZero ? 0 : uValue, fReadAsZero ? annotateValue(uValue) : NULL);
    3130                     else
    3131                         rc = printMsrValueExtended(uMsr, fReadAsZero ? 0 : uValue, fIgnMask, fGpMask,
    3132                                                    fReadAsZero ? annotateValue(uValue) : NULL);
    3133                 }
    3134                 /* Most likely read-only. */
    3135                 else if (pszFnName && !fTakesValue)
    3136                     rc = printMsrFunctionReadOnly(uMsr, pszFnName, annotateValue(uValue));
    3137                 else if (pszFnName)
    3138                     rc = printMsrFunctionExtended(uMsr, pszFnName, "ReadOnly", uValue, 0, 0, annotateValue(uValue));
    3139                 else if (fReadAsZero)
    3140                     rc = printMsrValueReadOnly(uMsr, 0, annotateValue(uValue));
    3141                 else
    3142                     rc = printMsrValueReadOnly(uMsr, uValue, NULL);
    3143                 break;
    3144             }
    3145 
    3146             /* These should have special handling, so just do a simple
    3147                write back same value check to see if it's writable. */
    3148             case VBCPUREPBADNESS_MIGHT_BITE:
    3149                 if (msrProberModifyNoChange(uMsr))
    3150                 {
    3151                     if (pszFnName && !fTakesValue)
    3152                         rc = printMsrFunction(uMsr, pszFnName, pszFnName, annotateValueExtra("Might bite.", uValue));
    3153                     else if (pszFnName)
    3154                         rc = printMsrFunctionExtended(uMsr, pszFnName, pszFnName, uValue, 0, 0,
    3155                                                       annotateValueExtra("Might bite.", uValue));
    3156                     else if (fReadAsZero)
    3157                         rc = printMsrValueIgnoreWrites(uMsr, 0, annotateValueExtra("Might bite.", uValue));
    3158                     else
    3159                         rc = printMsrValueIgnoreWrites(uMsr, uValue, "Might bite.");
    3160                 }
    3161                 else if (pszFnName && !fTakesValue)
    3162                     rc = printMsrFunctionReadOnly(uMsr, pszFnName, annotateValueExtra("Might bite.", uValue));
    3163                 else if (pszFnName)
    3164                     rc = printMsrFunctionExtended(uMsr, pszFnName, "ReadOnly", uValue, 0, UINT64_MAX,
    3165                                                   annotateValueExtra("Might bite.", uValue));
    3166                 else if (fReadAsZero)
    3167                     rc = printMsrValueReadOnly(uMsr, 0, annotateValueExtra("Might bite.", uValue));
    3168                 else
    3169                     rc = printMsrValueReadOnly(uMsr, uValue, "Might bite.");
    3170                 break;
    3171 
    3172 
    3173             /* Don't try anything with these guys. */
    3174             case VBCPUREPBADNESS_BOND_VILLAIN:
    3175             default:
    3176                 if (pszFnName && !fTakesValue)
    3177                     rc = printMsrFunction(uMsr, pszFnName, pszFnName, annotateValueExtra("Villain?", uValue));
    3178                 else if (pszFnName)
    3179                     rc = printMsrFunctionExtended(uMsr, pszFnName, pszFnName, uValue, 0, 0,
    3180                                                   annotateValueExtra("Villain?", uValue));
    3181                 else if (fReadAsZero)
    3182                     rc = printMsrValueIgnoreWrites(uMsr, 0, annotateValueExtra("Villain?", uValue));
    3183                 else
    3184                     rc = printMsrValueIgnoreWrites(uMsr, uValue, "Villain?");
    3185                 break;
    3186         }
    3187     }
    3188 
    3189     return rc;
    3190 }
    3191 
    3192 
    3193 static int reportMsr_GenRangeFunctionEx(VBCPUREPMSR const *paMsrs, uint32_t cMsrs, uint32_t cMax, const char *pszRdWrFnName,
    3194                                         uint32_t uMsrBase, bool fEarlyEndOk, bool fNoIgnMask, uint64_t fSkipMask, uint32_t *pidxLoop)
    3195 {
    3196     uint32_t uMsr   = paMsrs[0].uMsr;
    3197     uint32_t iRange = uMsr - uMsrBase;
    3198     Assert(cMax > iRange);
    3199     cMax -= iRange;
    3200 
    3201     /* Resolve default function name. */
    3202     if (!pszRdWrFnName)
    3203     {
    3204         pszRdWrFnName = getMsrFnName(uMsr, NULL);
    3205         if (!pszRdWrFnName)
    3206             return RTMsgErrorRc(VERR_INVALID_PARAMETER, "uMsr=%#x no function name\n", uMsr);
    3207     }
    3208 
    3209     /* Figure the possible register count. */
    3210     if (cMax > cMsrs)
    3211         cMax = cMsrs;
    3212     uint32_t cRegs = 1;
    3213     while (   cRegs < cMax
    3214            && paMsrs[cRegs].uMsr == uMsr + cRegs)
    3215         cRegs++;
    3216 
    3217     /* Probe the first register and check that the others exhibit
    3218        the same characteristics. */
    3219     bool     fReadOnly0;
    3220     uint64_t fIgnMask0, fGpMask0;
    3221     int rc = msrProberModifyBasicTests(uMsr, fSkipMask, &fReadOnly0, &fIgnMask0, &fGpMask0);
    3222     if (RT_FAILURE(rc))
    3223         return rc;
    3224 
    3225     const char *pszAnnotation = NULL;
    3226     for (uint32_t i = 1; i < cRegs; i++)
    3227     {
    3228         bool     fReadOnlyN;
    3229         uint64_t fIgnMaskN, fGpMaskN;
    3230         rc = msrProberModifyBasicTests(paMsrs[i].uMsr, fSkipMask, &fReadOnlyN, &fIgnMaskN, &fGpMaskN);
    3231         if (RT_FAILURE(rc))
    3232             return rc;
    3233         if (   fReadOnlyN != fReadOnly0
    3234             || (fIgnMaskN != fIgnMask0 && !fNoIgnMask)
    3235             || fGpMaskN   != fGpMask0)
    3236         {
    3237             if (!fEarlyEndOk && !isMsrViaShanghaiDummy(uMsr, paMsrs[i].uValue, paMsrs[i].fFlags))
    3238             {
    3239                 vbCpuRepDebug("MSR %s (%#x) range ended unexpectedly early on %#x: ro=%d ign=%#llx/%#llx gp=%#llx/%#llx [N/0]\n",
    3240                               getMsrNameHandled(uMsr), uMsr, paMsrs[i].uMsr,
    3241                               fReadOnlyN, fReadOnly0, fIgnMaskN, fIgnMask0, fGpMaskN, fGpMask0);
    3242                 pszAnnotation = "XXX: The range ended earlier than expected!";
    3243             }
    3244             cRegs = i;
    3245             break;
    3246         }
    3247     }
    3248 
    3249     /*
    3250      * Report the range (or single MSR as it might be).
    3251      */
    3252     *pidxLoop += cRegs - 1;
    3253 
    3254     if (fNoIgnMask)
    3255         fIgnMask0 = 0;
    3256     bool fSimple = fIgnMask0 == 0
    3257                 && (fGpMask0 == 0 || (fGpMask0 == UINT64_MAX && fReadOnly0))
    3258                 && iRange == 0;
    3259     if (cRegs == 1)
    3260         return printMsrFunctionExtendedIdxVal(uMsr, pszRdWrFnName, fReadOnly0 ? "ReadOnly" : pszRdWrFnName,
    3261                                               iRange, fIgnMask0, fGpMask0,
    3262                                               pszAnnotation ? pszAnnotation : annotateValue(paMsrs[0].uValue));
    3263     if (fSimple)
    3264         return printMsrRangeFunction(uMsr, uMsr + cRegs - 1,
    3265                                      pszRdWrFnName, fReadOnly0 ? "ReadOnly" : pszRdWrFnName, pszAnnotation);
    3266 
    3267     return printMsrRangeFunctionExIdxVal(uMsr, uMsr + cRegs - 1, pszRdWrFnName, fReadOnly0 ? "ReadOnly" : pszRdWrFnName,
    3268                                          iRange /*uValue*/, fIgnMask0, fGpMask0, pszAnnotation);
    3269 }
    3270 
    3271 
    3272 static int reportMsr_GenRangeFunction(VBCPUREPMSR const *paMsrs, uint32_t cMsrs, uint32_t cMax, const char *pszRdWrFnName,
    3273                                       uint32_t *pidxLoop)
    3274 {
    3275     return reportMsr_GenRangeFunctionEx(paMsrs, cMsrs, cMax, pszRdWrFnName, paMsrs[0].uMsr, false /*fEarlyEndOk*/, false /*fNoIgnMask*/,
    3276                                         getGenericSkipMask(paMsrs[0].uMsr), pidxLoop);
    3277 }
    3278 
    3279 
    3280 /**
    3281  * Generic report for an MSR implemented by functions, extended version.
    3282  *
    3283  * @returns VBox status code.
    3284  * @param   uMsr            The MSR.
    3285  * @param   pszRdWrFnName   The read/write function name, optional.
    3286  * @param   uValue          The MSR range value.
    3287  * @param   fSkipMask       Mask of bits to skip.
    3288  * @param   fNoGpMask       Mask of bits to remove from the GP mask after
    3289  *                          probing
    3290  * @param   pszAnnotate     Annotation.
    3291  */
    3292 static int reportMsr_GenFunctionEx(uint32_t uMsr, const char *pszRdWrFnName, uint32_t uValue,
    3293                                    uint64_t fSkipMask, uint64_t fNoGpMask, const char *pszAnnotate)
    3294 {
    3295     /* Resolve default function name. */
    3296     if (!pszRdWrFnName)
    3297     {
    3298         pszRdWrFnName = getMsrFnName(uMsr, NULL);
    3299         if (!pszRdWrFnName)
    3300             return RTMsgErrorRc(VERR_INVALID_PARAMETER, "uMsr=%#x no function name\n", uMsr);
    3301     }
    3302 
    3303     /* Probe the register and report. */
    3304     uint64_t fIgnMask = 0;
    3305     uint64_t fGpMask  = 0;
    3306     int rc = msrProberModifyBitChanges(uMsr, &fIgnMask, &fGpMask, fSkipMask);
    3307     if (RT_SUCCESS(rc))
    3308     {
    3309         fGpMask &= ~fNoGpMask;
    3310 
    3311         if (fGpMask == UINT64_MAX && uValue == 0 && !msrProberModifyZero(uMsr))
    3312             rc = printMsrFunctionReadOnly(uMsr, pszRdWrFnName, pszAnnotate);
    3313         else if (fIgnMask == UINT64_MAX && fGpMask == 0 && uValue == 0)
    3314             rc = printMsrFunctionIgnoreWrites(uMsr, pszRdWrFnName, pszAnnotate);
    3315         else if (fIgnMask != 0 && fGpMask == 0 && uValue == 0)
    3316             rc = printMsrFunctionIgnoreMask(uMsr, pszRdWrFnName, NULL, fIgnMask, pszAnnotate);
    3317         else if (fIgnMask == 0 && fGpMask == 0 && uValue == 0)
    3318             rc = printMsrFunction(uMsr, pszRdWrFnName, NULL, pszAnnotate);
    3319         else
    3320             rc = printMsrFunctionExtended(uMsr, pszRdWrFnName, NULL, uValue, fIgnMask, fGpMask, pszAnnotate);
    3321     }
    3322     return rc;
    3323 }
    3324 
    3325 
    3326 /**
    3327  * Reports a VIA/Shanghai dummy range.
    3328  *
    3329  * @returns VBox status code.
    3330  * @param   paMsrs              Pointer to the first MSR.
    3331  * @param   cMsrs               The number of MSRs in the array @a paMsr.
    3332  * @param   pidxLoop            Index variable that should be advanced to the
    3333  *                              last MSR entry in the range.
    3334  */
    3335 static int reportMsr_ViaShanghaiDummyRange(VBCPUREPMSR const *paMsrs, uint32_t cMsrs, uint32_t *pidxLoop)
    3336 {
    3337     /* Figure how many. */
    3338     uint32_t uMsr  = paMsrs[0].uMsr;
    3339     uint32_t cRegs = 1;
    3340     while (   cRegs < cMsrs
    3341            && paMsrs[cRegs].uMsr == uMsr + cRegs
    3342            && isMsrViaShanghaiDummy(paMsrs[cRegs].uMsr, paMsrs[cRegs].uValue, paMsrs[cRegs].fFlags))
    3343     {
    3344         cRegs++;
    3345         if (!(cRegs % 0x80))
    3346             vbCpuRepDebug("VIA dummy detection %#llx..%#llx (%#x regs)...\n", uMsr, uMsr + cRegs - 1, cRegs);
    3347     }
    3348 
    3349     /* Advance. */
    3350     *pidxLoop += cRegs - 1;
    3351 
    3352     /* Report it/them. */
    3353     char szName[80];
    3354     if (cRegs == 1)
    3355     {
    3356         RTStrPrintf(szName, sizeof(szName), "ZERO_%04x_%04x", RT_HI_U16(uMsr), RT_LO_U16(uMsr));
    3357         return printMsrValueIgnoreWritesNamed(uMsr, 0, szName, NULL);
    3358     }
    3359 
    3360     uint32_t uMsrLast = uMsr +  cRegs - 1;
    3361     RTStrPrintf(szName, sizeof(szName), "ZERO_%04x_%04x_THRU_%04x_%04x",
    3362                 RT_HI_U16(uMsr), RT_LO_U16(uMsr), RT_HI_U16(uMsrLast), RT_LO_U16(uMsrLast));
    3363     return printMsrRangeValueIgnoreWritesNamed(uMsr, uMsrLast, 0, szName, NULL);
    3364 }
    3365 
    3366 
    3367 /**
    3368  * Special function for reporting the IA32_APIC_BASE register, as it seems to be
    3369  * causing trouble on newer systems.
    3370  *
    3371  * @returns
    3372  * @param   uMsr                The MSR number.
    3373  * @param   uValue              The value.
    3374  */
    3375 static int reportMsr_Ia32ApicBase(uint32_t uMsr, uint64_t uValue)
    3376 {
    3377     /* Trouble with the generic treatment of both the "APIC Global Enable" and
    3378        "Enable x2APIC mode" bits on an i7-3820QM running OS X 10.8.5.  */
    3379     uint64_t fSkipMask = RT_BIT_64(11);
    3380     if (vbCpuRepSupportsX2Apic())
    3381         fSkipMask |= RT_BIT_64(10);
    3382     /* For some reason, twiddling this bit kills a Tualatin PIII-S. */
    3383     if (g_enmMicroarch == kCpumMicroarch_Intel_P6_III)
    3384         fSkipMask |= RT_BIT(9);
    3385 
    3386     /* If the OS uses the APIC, we have to be super careful. */
    3387     if (!g_MsrAcc.fAtomic)
    3388         fSkipMask |= UINT64_C(0x0000000ffffff000);
    3389 
    3390     /** @todo This makes the host unstable on a AMD Ryzen 1800X CPU, skip everything for now.
    3391      * Figure out exactly what causes the issue.
    3392      */
    3393     if (   g_enmMicroarch >= kCpumMicroarch_AMD_Zen_First
    3394         && g_enmMicroarch >= kCpumMicroarch_AMD_Zen_End)
    3395         fSkipMask |= UINT64_C(0xffffffffffffffff);
    3396 
    3397     return reportMsr_GenFunctionEx(uMsr, "Ia32ApicBase", uValue, fSkipMask, 0, NULL);
    3398 }
    3399 
    3400 
    3401 /**
    3402  * Special function for reporting the IA32_MISC_ENABLE register, as it seems to
    3403  * be causing trouble on newer systems.
    3404  *
    3405  * @returns
    3406  * @param   uMsr                The MSR number.
    3407  * @param   uValue              The value.
    3408  */
    3409 static int reportMsr_Ia32MiscEnable(uint32_t uMsr, uint64_t uValue)
    3410 {
    3411     uint64_t fSkipMask = 0;
    3412 
    3413     if (   (   g_enmMicroarch >= kCpumMicroarch_Intel_Core7_Broadwell
    3414             && g_enmMicroarch <= kCpumMicroarch_Intel_Core7_End)
    3415         || (   g_enmMicroarch >= kCpumMicroarch_Intel_Atom_Airmount
    3416             && g_enmMicroarch <= kCpumMicroarch_Intel_Atom_End)
    3417        )
    3418     {
    3419         vbCpuRepPrintf("WARNING: IA32_MISC_ENABLE probing needs hacking on this CPU!\n");
    3420         RTThreadSleep(128);
    3421     }
    3422 
    3423     /* If the OS is using MONITOR/MWAIT we'd better not disable it! */
    3424     if (!g_MsrAcc.fAtomic)
    3425         fSkipMask |= RT_BIT(18);
    3426 
    3427     /* The no execute related flag is deadly if clear.  */
    3428     if (   !(uValue & MSR_IA32_MISC_ENABLE_XD_DISABLE)
    3429         && (   g_enmMicroarch <  kCpumMicroarch_Intel_First
    3430             || g_enmMicroarch >= kCpumMicroarch_Intel_Core_Yonah
    3431             || vbCpuRepSupportsNX() ) )
    3432         fSkipMask |= MSR_IA32_MISC_ENABLE_XD_DISABLE;
    3433 
    3434     uint64_t fIgnMask = 0;
    3435     uint64_t fGpMask  = 0;
    3436     int rc = msrProberModifyBitChanges(uMsr, &fIgnMask, &fGpMask, fSkipMask);
    3437     if (RT_SUCCESS(rc))
    3438         rc = printMsrFunctionExtended(uMsr, "Ia32MiscEnable", "Ia32MiscEnable", uValue,
    3439                                       fIgnMask, fGpMask, annotateValue(uValue));
    3440     return rc;
    3441 }
    3442 
    3443 
    3444 /**
    3445  * Verifies that MTRR type field works correctly in the given MSR.
    3446  *
    3447  * @returns VBox status code (failure if bad MSR behavior).
    3448  * @param   uMsr                The MSR.
    3449  * @param   iBit                The first bit of the type field (8-bit wide).
    3450  * @param   cExpected           The number of types expected - PAT=8, MTRR=7.
    3451  */
    3452 static int msrVerifyMtrrTypeGPs(uint32_t uMsr, uint32_t iBit, uint32_t cExpected)
    3453 {
    3454     uint32_t uEndTypes = 0;
    3455     while (uEndTypes < 255)
    3456     {
    3457         bool fGp = !msrProberModifySimpleGp(uMsr, ~(UINT64_C(0xff) << iBit), (uint64_t)uEndTypes << iBit);
    3458         if (!fGp && (uEndTypes == 2 || uEndTypes == 3))
    3459             return RTMsgErrorRc(VERR_INVALID_PARAMETER, "MTRR types %u does not cause a GP as it should. (msr %#x)\n",
    3460                                 uEndTypes, uMsr);
    3461         if (fGp && uEndTypes != 2 && uEndTypes != 3)
    3462             break;
    3463         uEndTypes++;
    3464     }
    3465     if (uEndTypes != cExpected)
    3466         return RTMsgErrorRc(VERR_INVALID_PARAMETER, "MTRR types detected to be %#x (msr %#x). Expected %#x.\n",
    3467                             uEndTypes, uMsr, cExpected);
    3468     return VINF_SUCCESS;
    3469 }
    3470 
    3471 
    3472 /**
    3473  * Deals with the variable MTRR MSRs.
    3474  *
    3475  * @returns VBox status code.
    3476  * @param   paMsrs              Pointer to the first variable MTRR MSR (200h).
    3477  * @param   cMsrs               The number of MSRs in the array @a paMsr.
    3478  * @param   pidxLoop            Index variable that should be advanced to the
    3479  *                              last MTRR MSR entry.
    3480  */
    3481 static int reportMsr_Ia32MtrrPhysBaseMaskN(VBCPUREPMSR const *paMsrs, uint32_t cMsrs, uint32_t *pidxLoop)
    3482 {
    3483     uint32_t uMsr = paMsrs[0].uMsr;
    3484 
    3485     /* Count them. */
    3486     uint32_t cRegs = 1;
    3487     while (   cRegs < cMsrs
    3488            && paMsrs[cRegs].uMsr == uMsr + cRegs
    3489            && !isMsrViaShanghaiDummy(paMsrs[cRegs].uMsr, paMsrs[cRegs].uValue, paMsrs[cRegs].fFlags) )
    3490         cRegs++;
    3491     if (cRegs & 1)
    3492         return RTMsgErrorRc(VERR_INVALID_PARAMETER, "MTRR variable MSR range is odd: cRegs=%#x\n", cRegs);
    3493     if (cRegs > 0x20)
    3494         return RTMsgErrorRc(VERR_INVALID_PARAMETER, "MTRR variable MSR range is too large: cRegs=%#x\n", cRegs);
    3495 
    3496     /* Find a disabled register that we can play around with. */
    3497     uint32_t iGuineaPig;
    3498     for (iGuineaPig = 0; iGuineaPig < cRegs; iGuineaPig += 2)
    3499         if (!(paMsrs[iGuineaPig + 1].uValue & RT_BIT_32(11)))
    3500             break;
    3501     if (iGuineaPig >= cRegs)
    3502         iGuineaPig = cRegs - 2;
    3503     vbCpuRepDebug("iGuineaPig=%#x -> %#x\n", iGuineaPig, uMsr + iGuineaPig);
    3504 
    3505     /* Probe the base.  */
    3506     uint64_t fIgnBase = 0;
    3507     uint64_t fGpBase  = 0;
    3508     int rc = msrProberModifyBitChanges(uMsr + iGuineaPig, &fIgnBase, &fGpBase, 0);
    3509     if (RT_FAILURE(rc))
    3510         return rc;
    3511     rc = msrVerifyMtrrTypeGPs(uMsr + iGuineaPig, 0, 7);
    3512     if (RT_FAILURE(rc))
    3513         return rc;
    3514     vbCpuRepDebug("fIgnBase=%#llx fGpBase=%#llx\n", fIgnBase, fGpBase);
    3515 
    3516     /* Probing the mask is relatively straight forward. */
    3517     uint64_t fIgnMask = 0;
    3518     uint64_t fGpMask  = 0;
    3519     rc = msrProberModifyBitChanges(uMsr + iGuineaPig + 1, &fIgnMask, &fGpMask, 0x800); /* enabling it may cause trouble */
    3520     if (RT_FAILURE(rc))
    3521         return rc;
    3522     vbCpuRepDebug("fIgnMask=%#llx fGpMask=%#llx\n", fIgnMask, fGpMask);
    3523 
    3524     /* Validate that the whole range subscribes to the apprimately same GP rules. */
    3525     for (uint32_t i = 0; i < cRegs; i += 2)
    3526     {
    3527         uint64_t fSkipBase = ~fGpBase;
    3528         uint64_t fSkipMask = ~fGpMask;
    3529         if (!(paMsrs[i + 1].uValue & RT_BIT_32(11)))
    3530             fSkipBase = fSkipMask = 0;
    3531         fSkipBase |= 0x7;           /* Always skip the type. */
    3532         fSkipMask |= RT_BIT_32(11); /* Always skip the enable bit. */
    3533 
    3534         vbCpuRepDebug("i=%#x fSkipBase=%#llx fSkipMask=%#llx\n", i, fSkipBase, fSkipMask);
    3535 
    3536         if (!(paMsrs[i + 1].uValue & RT_BIT_32(11)))
    3537         {
    3538             rc = msrVerifyMtrrTypeGPs(uMsr + iGuineaPig, 0, 7);
    3539             if (RT_FAILURE(rc))
    3540                 return rc;
    3541         }
    3542 
    3543         uint64_t fIgnBaseN = 0;
    3544         uint64_t fGpBaseN  = 0;
    3545         rc = msrProberModifyBitChanges(uMsr + i, &fIgnBaseN, &fGpBaseN, fSkipBase);
    3546         if (RT_FAILURE(rc))
    3547             return rc;
    3548 
    3549         if (   fIgnBaseN != (fIgnBase & ~fSkipBase)
    3550             || fGpBaseN  != (fGpBase  & ~fSkipBase) )
    3551             return RTMsgErrorRc(VERR_INVALID_PARAMETER,
    3552                                 "MTRR PHYS BASE register %#x behaves differently from %#x: ign=%#llx/%#llx gp=%#llx/%#llx (fSkipBase=%#llx)\n",
    3553                                 uMsr + i, uMsr + iGuineaPig,
    3554                                 fIgnBaseN, fIgnBase & ~fSkipBase, fGpBaseN, fGpBase & ~fSkipBase, fSkipBase);
    3555 
    3556         uint64_t fIgnMaskN = 0;
    3557         uint64_t fGpMaskN  = 0;
    3558         rc = msrProberModifyBitChanges(uMsr + i + 1, &fIgnMaskN, &fGpMaskN, fSkipMask);
    3559         if (RT_FAILURE(rc))
    3560             return rc;
    3561         if (   fIgnMaskN != (fIgnMask & ~fSkipMask)
    3562             || fGpMaskN  != (fGpMask  & ~fSkipMask) )
    3563             return RTMsgErrorRc(VERR_INVALID_PARAMETER,
    3564                                 "MTRR PHYS MASK register %#x behaves differently from %#x: ign=%#llx/%#llx gp=%#llx/%#llx (fSkipMask=%#llx)\n",
    3565                                 uMsr + i + 1, uMsr + iGuineaPig + 1,
    3566                                 fIgnMaskN, fIgnMask & ~fSkipMask, fGpMaskN, fGpMask & ~fSkipMask, fSkipMask);
    3567     }
    3568 
    3569     /* Print the whole range. */
    3570     fGpBase &= ~(uint64_t)0x7; /* Valid type bits, see msrVerifyMtrrTypeGPs(). */
    3571     for (uint32_t i = 0; i < cRegs; i += 2)
    3572     {
    3573         printMsrFunctionExtendedIdxVal(uMsr + i,     "Ia32MtrrPhysBaseN", NULL, i / 2, fIgnBase, fGpBase,
    3574                                        annotateValue(paMsrs[i].uValue));
    3575         printMsrFunctionExtendedIdxVal(uMsr + i + 1, "Ia32MtrrPhysMaskN", NULL, i / 2, fIgnMask, fGpMask,
    3576                                        annotateValue(paMsrs[i + 1].uValue));
    3577     }
    3578 
    3579     *pidxLoop += cRegs - 1;
    3580     return VINF_SUCCESS;
    3581 }
    3582 
    3583 
    3584 /**
    3585  * Deals with fixed MTRR and PAT MSRs, checking the 8 memory type fields.
    3586  *
    3587  * @returns VBox status code.
    3588  * @param   uMsr                The MSR.
    3589  */
    3590 static int reportMsr_Ia32MtrrFixedOrPat(uint32_t uMsr)
    3591 {
    3592     /* Had a spot of trouble on an old macbook pro with core2 duo T9900 (penryn)
    3593        running 64-bit win81pe. Not giving PAT such a scrutiny fixes it. */
    3594     /* This hangs the host on a AMD Ryzen 1800X CPU */
    3595     if (   uMsr != 0x00000277
    3596         || (  g_enmVendor == CPUMCPUVENDOR_INTEL
    3597             ? g_enmMicroarch >= kCpumMicroarch_Intel_Core7_First
    3598             : g_enmVendor == CPUMCPUVENDOR_AMD || g_enmVendor == CPUMCPUVENDOR_HYGON
    3599             ? (   g_enmMicroarch != kCpumMicroarch_AMD_K8_90nm_AMDV
    3600                && !CPUMMICROARCH_IS_AMD_FAM_ZEN(g_enmMicroarch))
    3601             : true) )
    3602     {
    3603         /* Every 8 bytes is a type, check the type ranges one by one. */
    3604         for (uint32_t iBit = 0; iBit < 64; iBit += 8)
    3605         {
    3606             int rc = msrVerifyMtrrTypeGPs(uMsr, iBit, 7 + (uMsr == 0x00000277));
    3607             if (RT_FAILURE(rc))
    3608                 return rc;
    3609         }
    3610     }
    3611 
    3612     return printMsrFunctionCpumCpu(uMsr, NULL, NULL, NULL, NULL);
    3613 }
    3614 
    3615 
    3616 /**
    3617  * Deals with IA32_MTRR_DEF_TYPE.
    3618  *
    3619  * @returns VBox status code.
    3620  * @param   uMsr                The MSR.
    3621  */
    3622 static int reportMsr_Ia32MtrrDefType(uint32_t uMsr)
    3623 {
    3624     uint64_t fGpMask  = 0;
    3625     uint64_t fIgnMask = 0;
    3626     if (g_enmMicroarch == kCpumMicroarch_AMD_K8_90nm_AMDV)
    3627     {
    3628         /* Problematic CPU! Fake it for now. */
    3629         fGpMask = ~(uint64_t)0xc07;
    3630         fIgnMask = 0;
    3631     }
    3632     else
    3633     {
    3634         int rc = msrVerifyMtrrTypeGPs(uMsr, 0, 7);
    3635         if (RT_FAILURE(rc))
    3636             return rc;
    3637 
    3638         rc = msrProberModifyBitChanges(uMsr, &fIgnMask, &fGpMask, 0x7);
    3639         if (RT_FAILURE(rc))
    3640             return rc;
    3641         Assert(!(fGpMask & 7)); Assert(!(fIgnMask & 7));
    3642     }
    3643 
    3644     return printMsrFunctionCpumCpuEx(uMsr, NULL, NULL, NULL, fIgnMask, fGpMask, NULL);
    3645 }
    3646 
    3647 
    3648 /**
    3649  * Deals with the Machine Check (MC) MSRs in the 400h+ area.
    3650  *
    3651  * @returns VBox status code.
    3652  * @param   paMsrs              Pointer to the first MC MSR (400h).
    3653  * @param   cMsrs               The number of MSRs in the array @a paMsr.
    3654  * @param   pidxLoop            Index variable that should be advanced to the
    3655  *                              last MC MSR entry.
    3656  */
    3657 static int reportMsr_Ia32McCtlStatusAddrMiscN(VBCPUREPMSR const *paMsrs, uint32_t cMsrs, uint32_t *pidxLoop)
    3658 {
    3659     uint32_t uMsr = paMsrs[0].uMsr;
    3660 
    3661     /* Count them. */
    3662     uint32_t cRegs = 1;
    3663     uint32_t cDetectedRegs = 1;
    3664     while (   cDetectedRegs < cMsrs
    3665            && (   paMsrs[cDetectedRegs].uMsr == uMsr + cRegs
    3666                || (cRegs & 3) == 2 /* ADDR may or may not be there, depends on STATUS and CPU. */
    3667                || (cRegs & 3) == 3 /* MISC may or may not be there, depends on STATUS and CPU. */
    3668                || cRegs == 0x13 /* MC4_MISC may not be there, depends on CPU. */
    3669                || cRegs == 0x14 /* MC5_CTL may not be there, depends on CPU. */)
    3670            && cRegs < 0x7f )
    3671     {
    3672         if (paMsrs[cDetectedRegs].uMsr == uMsr + cRegs)
    3673             cDetectedRegs++;
    3674         cRegs++;
    3675     }
    3676 
    3677     /** aeichner: An AMD Ryzen 7 1800X CPU triggers this and I'm too lazy to check the correctness in detail. */
    3678     if (   (cRegs & 3)
    3679         && !CPUMMICROARCH_IS_AMD_FAM_ZEN(g_enmMicroarch))
    3680         return RTMsgErrorRc(VERR_INVALID_PARAMETER, "MC MSR range is odd: cRegs=%#x\n", cRegs);
    3681 
    3682     /* Just report them.  We don't bother probing here as the CTL format
    3683        and such seems to be a lot of work to test correctly and changes between
    3684        cpu generations.  */
    3685     *pidxLoop += cDetectedRegs - 1;
    3686     return printMsrRangeFunction(uMsr, uMsr + cRegs - 1, "Ia32McCtlStatusAddrMiscN", NULL, NULL);
    3687 }
    3688 
    3689 
    3690 
    3691 /**
    3692  * Deals with the X2APIC msrs.
    3693  *
    3694  * @returns VBox status code.
    3695  * @param   paMsrs              Pointer to the first X2APIC MSR.
    3696  * @param   cMsrs               The number of MSRs in the array @a paMsr.
    3697  * @param   pidxLoop            Index variable that should be advanced to the
    3698  *                              last X2APIC MSR entry.
    3699  */
    3700 static int reportMsr_GenX2Apic(VBCPUREPMSR const *paMsrs, uint32_t cMsrs, uint32_t *pidxLoop)
    3701 {
    3702     /* Advance. */
    3703     uint32_t cRegs = 1;
    3704     while (   cRegs < cMsrs
    3705            && paMsrs[cRegs].uMsr <= 0x8ff)
    3706         cRegs++;
    3707     *pidxLoop += cRegs - 1;
    3708 
    3709     /* Just emit an X2APIC range. */
    3710     return printMsrRangeFunction(0x800, 0x8ff, "Ia32X2ApicN", NULL, NULL);
    3711 }
    3712 
    3713 
    3714 /**
    3715  * Deals carefully with the EFER register.
    3716  *
    3717  * @returns VBox status code.
    3718  * @param   uMsr                The MSR number.
    3719  * @param   uValue              The current value.
    3720  */
    3721 static int reportMsr_Amd64Efer(uint32_t uMsr, uint64_t uValue)
    3722 {
    3723     uint64_t fSkipMask = 0;
    3724     if (vbCpuRepSupportsLongMode())
    3725     {
    3726         fSkipMask |= MSR_K6_EFER_LME;
    3727         if (!g_MsrAcc.fAtomic && (uValue & MSR_K6_EFER_SCE))
    3728             fSkipMask |= MSR_K6_EFER_SCE;
    3729     }
    3730     if (   (uValue & MSR_K6_EFER_NXE)
    3731         || vbCpuRepSupportsNX())
    3732         fSkipMask |= MSR_K6_EFER_NXE;
    3733 
    3734     /* NetBurst prescott 2MB (model 4) hung or triple faulted here.  The extra
    3735        sleep or something seemed to help for some screwed up reason. */
    3736     if (g_fIntelNetBurst)
    3737     {
    3738         // This doesn't matter:
    3739         //fSkipMask |= MSR_K6_EFER_SCE;
    3740         //if (vbCpuRepSupportsLongMode())
    3741         //    fSkipMask |= MSR_K6_EFER_LMA;
    3742         //vbCpuRepDebug("EFER - netburst workaround - ignore SCE & LMA (fSkipMask=%#llx)\n", fSkipMask);
    3743 
    3744         vbCpuRepDebug("EFER - netburst sleep fudge - fSkipMask=%#llx\n", fSkipMask);
    3745         RTThreadSleep(1000);
    3746     }
    3747 
    3748     return reportMsr_GenFunctionEx(uMsr, NULL, uValue, fSkipMask, MSR_K6_EFER_LMA, NULL);
    3749 }
    3750 
    3751 
    3752 /**
    3753  * Deals with the MC4_MISCn (n >= 1) range and the following reserved MSRs.
    3754  *
    3755  * @returns VBox status code.
    3756  * @param   paMsrs              Pointer to the first MSR.
    3757  * @param   cMsrs               The number of MSRs in the array @a paMsr.
    3758  * @param   pidxLoop            Index variable that should be advanced to the
    3759  *                              last MSR entry in the range.
    3760  */
    3761 static int reportMsr_AmdFam10hMc4MiscN(VBCPUREPMSR const *paMsrs, uint32_t cMsrs, uint32_t *pidxLoop)
    3762 {
    3763     /* Count registers. */
    3764     uint32_t cRegs = 1;
    3765     while (   cRegs < cMsrs
    3766            && cRegs < 8
    3767            && paMsrs[cRegs].uMsr == paMsrs[0].uMsr + cRegs)
    3768         cRegs++;
    3769 
    3770     /* Probe & report used MSRs. */
    3771     uint64_t fIgnMask = 0;
    3772     uint64_t fGpMask  = 0;
    3773     uint32_t cUsed    = 0;
    3774     while (cUsed < cRegs)
    3775     {
    3776         uint64_t fIgnMaskN = 0;
    3777         uint64_t fGpMaskN  = 0;
    3778         int rc = msrProberModifyBitChanges(paMsrs[cUsed].uMsr, &fIgnMaskN, &fGpMaskN, 0);
    3779         if (RT_FAILURE(rc))
    3780             return rc;
    3781         if (fIgnMaskN == UINT64_MAX || fGpMaskN == UINT64_MAX)
    3782             break;
    3783         if (cUsed == 0)
    3784         {
    3785             fIgnMask = fIgnMaskN;
    3786             fGpMask  = fGpMaskN;
    3787         }
    3788         else if (   fIgnMaskN != fIgnMask
    3789                  || fGpMaskN  != fGpMask)
    3790             return RTMsgErrorRc(VERR_NOT_EQUAL, "AmdFam16hMc4MiscN mismatch: fIgn=%#llx/%#llx fGp=%#llx/%#llx uMsr=%#x\n",
    3791                                 fIgnMaskN, fIgnMask, fGpMaskN, fGpMask, paMsrs[cUsed].uMsr);
    3792         cUsed++;
    3793     }
    3794     if (cUsed > 0)
    3795         printMsrRangeFunctionEx(paMsrs[0].uMsr, paMsrs[cUsed - 1].uMsr, "AmdFam10hMc4MiscN", NULL, 0, fIgnMask, fGpMask, NULL);
    3796 
    3797     /* Probe & report reserved MSRs. */
    3798     uint32_t cReserved = 0;
    3799     while (cUsed + cReserved < cRegs)
    3800     {
    3801         fIgnMask = fGpMask = 0;
    3802         int rc = msrProberModifyBitChanges(paMsrs[cUsed + cReserved].uMsr, &fIgnMask, &fGpMask, 0);
    3803         if (RT_FAILURE(rc))
    3804             return rc;
    3805         if ((fIgnMask != UINT64_MAX && fGpMask != UINT64_MAX) || paMsrs[cUsed + cReserved].uValue)
    3806             return RTMsgErrorRc(VERR_NOT_EQUAL,
    3807                                 "Unexpected reserved AmdFam16hMc4MiscN: fIgn=%#llx fGp=%#llx uMsr=%#x uValue=%#llx\n",
    3808                                 fIgnMask, fGpMask, paMsrs[cUsed + cReserved].uMsr, paMsrs[cUsed + cReserved].uValue);
    3809         cReserved++;
    3810     }
    3811     if (cReserved > 0 && fIgnMask == UINT64_MAX)
    3812         printMsrRangeValueIgnoreWrites(paMsrs[cUsed].uMsr, paMsrs[cUsed + cReserved - 1].uMsr, 0, NULL);
    3813     else if (cReserved > 0 && fGpMask == UINT64_MAX)
    3814         printMsrRangeValueReadOnly(paMsrs[cUsed].uMsr, paMsrs[cUsed + cReserved - 1].uMsr, 0, NULL);
    3815 
    3816     *pidxLoop += cRegs - 1;
    3817     return VINF_SUCCESS;
    3818 }
    3819 
    3820 
    3821 /**
    3822  * Deals with the AMD PERF_CTL range.
    3823  *
    3824  * @returns VBox status code.
    3825  * @param   paMsrs              Pointer to the first MSR.
    3826  * @param   cMsrs               The number of MSRs in the array @a paMsr.
    3827  * @param   pidxLoop            Index variable that should be advanced to the
    3828  *                              last MSR entry in the range.
    3829  */
    3830 static int reportMsr_AmdK8PerfCtlN(VBCPUREPMSR const *paMsrs, uint32_t cMsrs, uint32_t *pidxLoop)
    3831 {
    3832     uint32_t uMsr = paMsrs[0].uMsr;
    3833     Assert(uMsr == 0xc0010000);
    3834 
    3835     /* Family 15h (bulldozer +) aliases these registers sparsely onto c001020x. */
    3836     if (CPUMMICROARCH_IS_AMD_FAM_15H(g_enmMicroarch))
    3837     {
    3838         for (uint32_t i = 0; i < 4; i++)
    3839             printMsrAlias(uMsr + i, 0xc0010200 + i * 2, NULL);
    3840         *pidxLoop += 3;
    3841     }
    3842     else
    3843         return reportMsr_GenRangeFunction(paMsrs, cMsrs, 4, "AmdK8PerfCtlN", pidxLoop);
    3844     return VINF_SUCCESS;
    3845 }
    3846 
    3847 
    3848 /**
    3849  * Deals with the AMD PERF_CTR range.
    3850  *
    3851  * @returns VBox status code.
    3852  * @param   paMsrs              Pointer to the first MSR.
    3853  * @param   cMsrs               The number of MSRs in the array @a paMsr.
    3854  * @param   pidxLoop            Index variable that should be advanced to the
    3855  *                              last MSR entry in the range.
    3856  */
    3857 static int reportMsr_AmdK8PerfCtrN(VBCPUREPMSR const *paMsrs, uint32_t cMsrs, uint32_t *pidxLoop)
    3858 {
    3859     uint32_t uMsr = paMsrs[0].uMsr;
    3860     Assert(uMsr == 0xc0010004);
    3861 
    3862     /* Family 15h (bulldozer +) aliases these registers sparsely onto c001020x. */
    3863     if (CPUMMICROARCH_IS_AMD_FAM_15H(g_enmMicroarch))
    3864     {
    3865         for (uint32_t i = 0; i < 4; i++)
    3866             printMsrAlias(uMsr + i, 0xc0010201 + i * 2, NULL);
    3867         *pidxLoop += 3;
    3868     }
    3869     else
    3870         return reportMsr_GenRangeFunction(paMsrs, cMsrs, 4, "AmdK8PerfCtrN", pidxLoop);
    3871     return VINF_SUCCESS;
    3872 }
    3873 
    3874 
    3875 /**
    3876  * Deals carefully with the SYS_CFG register.
    3877  *
    3878  * @returns VBox status code.
    3879  * @param   uMsr                The MSR number.
    3880  * @param   uValue              The current value.
    3881  */
    3882 static int reportMsr_AmdK8SysCfg(uint32_t uMsr, uint64_t uValue)
    3883 {
    3884     uint64_t fSkipMask = 0;
    3885 
    3886     /* Bit 21 (MtrrTom2En) is marked reserved in family 0fh, while in family
    3887        10h BKDG this changes (as does the document style).  Testing this bit
    3888        causes bulldozer running win64 to restart, thus this special treatment. */
    3889     if (g_enmMicroarch >= kCpumMicroarch_AMD_K10)
    3890         fSkipMask |= RT_BIT(21);
    3891 
    3892     /* Turns out there are more killer bits here, at least on Opteron 2384.
    3893        Skipping all known bits. */
    3894     if (g_enmMicroarch >= kCpumMicroarch_AMD_K8_90nm_AMDV /* Not sure when introduced - harmless? */)
    3895         fSkipMask |= RT_BIT(22); /* Tom2ForceMemTypeWB */
    3896     if (g_enmMicroarch >= kCpumMicroarch_AMD_K8_First)
    3897         fSkipMask |= RT_BIT(21); /* MtrrTom2En */
    3898     if (g_enmMicroarch >= kCpumMicroarch_AMD_K8_First)
    3899         fSkipMask |= RT_BIT(20); /* MtrrVarDramEn*/
    3900     if (g_enmMicroarch >= kCpumMicroarch_AMD_K8_First)
    3901         fSkipMask |= RT_BIT(19); /* MtrrFixDramModEn */
    3902     if (g_enmMicroarch >= kCpumMicroarch_AMD_K8_First)
    3903         fSkipMask |= RT_BIT(18); /* MtrrFixDramEn */
    3904     if (g_enmMicroarch >= kCpumMicroarch_AMD_K8_First)
    3905         fSkipMask |= RT_BIT(17); /* SysUcLockEn */
    3906     if (g_enmMicroarch >= kCpumMicroarch_AMD_K8_First)
    3907         fSkipMask |= RT_BIT(16); /* ChgToDirtyDis */
    3908     if (g_enmMicroarch >= kCpumMicroarch_AMD_K8_First && g_enmMicroarch < kCpumMicroarch_AMD_15h_First)
    3909         fSkipMask |= RT_BIT(10); /* SetDirtyEnO */
    3910     if (g_enmMicroarch >= kCpumMicroarch_AMD_K8_First && g_enmMicroarch < kCpumMicroarch_AMD_15h_First)
    3911         fSkipMask |= RT_BIT(9);  /* SetDirtyEnS */
    3912     if (   CPUMMICROARCH_IS_AMD_FAM_0FH(g_enmMicroarch)
    3913         || CPUMMICROARCH_IS_AMD_FAM_10H(g_enmMicroarch))
    3914         fSkipMask |= RT_BIT(8);  /* SetDirtyEnE */
    3915     if (   CPUMMICROARCH_IS_AMD_FAM_0FH(g_enmMicroarch)
    3916         || CPUMMICROARCH_IS_AMD_FAM_11H(g_enmMicroarch) )
    3917         fSkipMask |= RT_BIT(7)   /* SysVicLimit */
    3918                   |  RT_BIT(6)   /* SysVicLimit */
    3919                   |  RT_BIT(5)   /* SysVicLimit */
    3920                   |  RT_BIT(4)   /* SysAckLimit */
    3921                   |  RT_BIT(3)   /* SysAckLimit */
    3922                   |  RT_BIT(2)   /* SysAckLimit */
    3923                   |  RT_BIT(1)   /* SysAckLimit */
    3924                   |  RT_BIT(0)   /* SysAckLimit */;
    3925 
    3926     return reportMsr_GenFunctionEx(uMsr, NULL, uValue, fSkipMask, 0, annotateValue(uValue));
    3927 }
    3928 
    3929 
    3930 /**
    3931  * Deals carefully with the HWCR register.
    3932  *
    3933  * @returns VBox status code.
    3934  * @param   uMsr                The MSR number.
    3935  * @param   uValue              The current value.
    3936  */
    3937 static int reportMsr_AmdK8HwCr(uint32_t uMsr, uint64_t uValue)
    3938 {
    3939     uint64_t fSkipMask = 0;
    3940 
    3941     /* Trouble on Opteron 2384, skip some of the known bits. */
    3942     if (g_enmMicroarch >= kCpumMicroarch_AMD_K10 && !CPUMMICROARCH_IS_AMD_FAM_11H(g_enmMicroarch))
    3943         fSkipMask |= /*RT_BIT(10)*/ 0  /* MonMwaitUserEn */
    3944                   |  RT_BIT(9);  /* MonMwaitDis */
    3945     fSkipMask |= RT_BIT(8);      /* #IGNNE port emulation */
    3946     if (   CPUMMICROARCH_IS_AMD_FAM_0FH(g_enmMicroarch)
    3947         || CPUMMICROARCH_IS_AMD_FAM_11H(g_enmMicroarch) )
    3948         fSkipMask |= RT_BIT(7)   /* DisLock */
    3949                   |  RT_BIT(6);  /* FFDis (TLB flush filter) */
    3950     fSkipMask |= RT_BIT(4);      /* INVD to WBINVD */
    3951     fSkipMask |= RT_BIT(3);      /* TLBCACHEDIS */
    3952     if (   CPUMMICROARCH_IS_AMD_FAM_0FH(g_enmMicroarch)
    3953         || CPUMMICROARCH_IS_AMD_FAM_10H(g_enmMicroarch)
    3954         || CPUMMICROARCH_IS_AMD_FAM_11H(g_enmMicroarch) )
    3955         fSkipMask |= RT_BIT(1);  /* SLOWFENCE */
    3956     fSkipMask |= RT_BIT(0);      /* SMMLOCK */
    3957 
    3958     return reportMsr_GenFunctionEx(uMsr, NULL, uValue, fSkipMask, 0, annotateValue(uValue));
    3959 }
    3960 
    3961 
    3962 /**
    3963  * Deals carefully with a IORRBasei register.
    3964  *
    3965  * @returns VBox status code.
    3966  * @param   uMsr                The MSR number.
    3967  * @param   uValue              The current value.
    3968  */
    3969 static int reportMsr_AmdK8IorrBaseN(uint32_t uMsr, uint64_t uValue)
    3970 {
    3971     /* Skip know bits here, as harm seems to come from messing with them. */
    3972     uint64_t fSkipMask = RT_BIT(4) | RT_BIT(3);
    3973     fSkipMask |= (RT_BIT_64(vbCpuRepGetPhysAddrWidth()) - 1) & X86_PAGE_4K_BASE_MASK;
    3974     return reportMsr_GenFunctionEx(uMsr, NULL, (uMsr - 0xc0010016) / 2, fSkipMask, 0, annotateValue(uValue));
    3975 }
    3976 
    3977 
    3978 /**
    3979  * Deals carefully with a IORRMaski register.
    3980  *
    3981  * @returns VBox status code.
    3982  * @param   uMsr                The MSR number.
    3983  * @param   uValue              The current value.
    3984  */
    3985 static int reportMsr_AmdK8IorrMaskN(uint32_t uMsr, uint64_t uValue)
    3986 {
    3987     /* Skip know bits here, as harm seems to come from messing with them. */
    3988     uint64_t fSkipMask = RT_BIT(11);
    3989     fSkipMask |= (RT_BIT_64(vbCpuRepGetPhysAddrWidth()) - 1) & X86_PAGE_4K_BASE_MASK;
    3990     return reportMsr_GenFunctionEx(uMsr, NULL, (uMsr - 0xc0010017) / 2, fSkipMask, 0, annotateValue(uValue));
    3991 }
    3992 
    3993 
    3994 /**
    3995  * Deals carefully with a IORRMaski register.
    3996  *
    3997  * @returns VBox status code.
    3998  * @param   uMsr                The MSR number.
    3999  * @param   uValue              The current value.
    4000  */
    4001 static int reportMsr_AmdK8TopMemN(uint32_t uMsr, uint64_t uValue)
    4002 {
    4003     /* Skip know bits here, as harm seems to come from messing with them. */
    4004     uint64_t fSkipMask = (RT_BIT_64(vbCpuRepGetPhysAddrWidth()) - 1) & ~(RT_BIT_64(23) - 1);
    4005     return reportMsr_GenFunctionEx(uMsr, NULL, uMsr == 0xc001001d, fSkipMask, 0, annotateValue(uValue));
    4006 }
    4007 
    4008 
    4009 /**
    4010  * Deals with the AMD P-state config range.
    4011  *
    4012  * @returns VBox status code.
    4013  * @param   paMsrs              Pointer to the first MSR.
    4014  * @param   cMsrs               The number of MSRs in the array @a paMsr.
    4015  * @param   pidxLoop            Index variable that should be advanced to the
    4016  *                              last MSR entry in the range.
    4017  */
    4018 static int reportMsr_AmdFam10hPStateN(VBCPUREPMSR const *paMsrs, uint32_t cMsrs, uint32_t *pidxLoop)
    4019 {
    4020     uint32_t uMsr = paMsrs[0].uMsr;
    4021     AssertRelease(uMsr == 0xc0010064);
    4022 
    4023     /* Count them. */
    4024     uint32_t cRegs = 1;
    4025     while (   cRegs < 8
    4026            && cRegs < cMsrs
    4027            && paMsrs[cRegs].uMsr == uMsr + cRegs)
    4028         cRegs++;
    4029 
    4030     /* Figure out which bits we should skip when probing.  This is based on
    4031        specs and may need adjusting for real life when handy. */
    4032     uint64_t fSkipMask = RT_BIT_64(63);             /* PstateEn */
    4033     fSkipMask |= RT_BIT_64(41) | RT_BIT_64(40);     /* IddDiv */
    4034     fSkipMask |= UINT64_C(0x000000ff00000000);      /* IddValue */
    4035     if (CPUMMICROARCH_IS_AMD_FAM_10H(g_enmMicroarch))
    4036         fSkipMask |= UINT32_C(0xfe000000);          /* NbVid - Northbridge VID */
    4037     if (   CPUMMICROARCH_IS_AMD_FAM_10H(g_enmMicroarch)
    4038         || CPUMMICROARCH_IS_AMD_FAM_15H(g_enmMicroarch))
    4039         fSkipMask |= RT_BIT_32(22);                 /* NbDid or NbPstate. */
    4040     if (g_enmMicroarch >= kCpumMicroarch_AMD_15h_Piledriver) /* ?? - listed in 10-1Fh model BDKG as well asFam16h */
    4041         fSkipMask |= RT_BIT_32(16);                 /* CpuVid[7] */
    4042     fSkipMask |= UINT32_C(0x0000fe00);              /* CpuVid[6:0] */
    4043     fSkipMask |= UINT32_C(0x000001c0);              /* CpuDid */
    4044     fSkipMask |= UINT32_C(0x0000003f);              /* CpuFid */
    4045 
    4046     /* Probe and report them one by one since we're passing values instead of
    4047        register indexes to the functions. */
    4048     for (uint32_t i = 0; i < cRegs; i++)
    4049     {
    4050         uint64_t fIgnMask = 0;
    4051         uint64_t fGpMask = 0;
    4052         int rc = msrProberModifyBitChanges(uMsr + i, &fIgnMask, &fGpMask, fSkipMask);
    4053         if (RT_FAILURE(rc))
    4054             return rc;
    4055         printMsrFunctionExtended(uMsr + i, "AmdFam10hPStateN", NULL, paMsrs[i].uValue, fIgnMask, fGpMask,
    4056                                  annotateValue(paMsrs[i].uValue));
    4057     }
    4058 
    4059     /* Advance. */
    4060     *pidxLoop += cRegs - 1;
    4061     return VINF_SUCCESS;
    4062 }
    4063 
    4064 
    4065 /**
    4066  * Deals carefully with a COFVID control register.
    4067  *
    4068  * @returns VBox status code.
    4069  * @param   uMsr                The MSR number.
    4070  * @param   uValue              The current value.
    4071  */
    4072 static int reportMsr_AmdFam10hCofVidControl(uint32_t uMsr, uint64_t uValue)
    4073 {
    4074     /* Skip know bits here, as harm seems to come from messing with them. */
    4075     uint64_t fSkipMask = 0;
    4076     if (CPUMMICROARCH_IS_AMD_FAM_10H(g_enmMicroarch))
    4077         fSkipMask |= UINT32_C(0xfe000000);          /* NbVid - Northbridge VID */
    4078     else if (g_enmMicroarch >= kCpumMicroarch_AMD_15h_First) /* Listed in preliminary Fam16h BDKG. */
    4079         fSkipMask |= UINT32_C(0xff000000);          /* NbVid - Northbridge VID - includes bit 24 for Fam15h and Fam16h. Odd... */
    4080     if (   CPUMMICROARCH_IS_AMD_FAM_10H(g_enmMicroarch)
    4081         || g_enmMicroarch >= kCpumMicroarch_AMD_15h_First) /* Listed in preliminary Fam16h BDKG. */
    4082         fSkipMask |= RT_BIT_32(22);                 /* NbDid or NbPstate. */
    4083     if (g_enmMicroarch >= kCpumMicroarch_AMD_15h_Piledriver) /* ?? - listed in 10-1Fh model BDKG as well asFam16h */
    4084         fSkipMask |= RT_BIT_32(20);                 /* CpuVid[7] */
    4085     fSkipMask |= UINT32_C(0x00070000);              /* PstatId */
    4086     fSkipMask |= UINT32_C(0x0000fe00);              /* CpuVid[6:0] */
    4087     fSkipMask |= UINT32_C(0x000001c0);              /* CpuDid */
    4088     fSkipMask |= UINT32_C(0x0000003f);              /* CpuFid */
    4089 
    4090     return reportMsr_GenFunctionEx(uMsr, NULL, uValue, fSkipMask, 0, annotateValue(uValue));
    4091 }
    4092 
    4093 
    4094 /**
    4095  * Deals with the AMD [|L2I_|NB_]PERF_CT[LR] mixed ranges.
    4096  *
    4097  * Mixed here refers to the control and counter being in mixed in pairs as
    4098  * opposed to them being two separate parallel arrays like in the 0xc0010000
    4099  * area.
    4100  *
    4101  * @returns VBox status code.
    4102  * @param   paMsrs              Pointer to the first MSR.
    4103  * @param   cMsrs               The number of MSRs in the array @a paMsr.
    4104  * @param   cMax                The max number of MSRs (not counters).
    4105  * @param   pidxLoop            Index variable that should be advanced to the
    4106  *                              last MSR entry in the range.
    4107  */
    4108 static int reportMsr_AmdGenPerfMixedRange(VBCPUREPMSR const *paMsrs, uint32_t cMsrs, uint32_t cMax, uint32_t *pidxLoop)
    4109 {
    4110     uint32_t uMsr = paMsrs[0].uMsr;
    4111 
    4112     /* Count them. */
    4113     uint32_t cRegs = 1;
    4114     while (   cRegs < cMax
    4115            && cRegs < cMsrs
    4116            && paMsrs[cRegs].uMsr == uMsr + cRegs)
    4117         cRegs++;
    4118     if (cRegs & 1)
    4119         return RTMsgErrorRc(VERR_INVALID_PARAMETER, "PERF range at %#x is odd: cRegs=%#x\n", uMsr, cRegs);
    4120 
    4121     /* Report them as individual entries, using default names and such. */
    4122     for (uint32_t i = 0; i < cRegs; i++)
    4123     {
    4124         uint64_t fIgnMask = 0;
    4125         uint64_t fGpMask  = 0;
    4126         int rc = msrProberModifyBitChanges(uMsr + i, &fIgnMask, &fGpMask, 0);
    4127         if (RT_FAILURE(rc))
    4128             return rc;
    4129         printMsrFunctionExtendedIdxVal(uMsr + i, NULL, NULL, i / 2, fIgnMask, fGpMask, annotateValue(paMsrs[i].uValue));
    4130     }
    4131 
    4132     /* Advance. */
    4133     *pidxLoop += cRegs - 1;
    4134     return VINF_SUCCESS;
    4135 }
    4136 
    4137 
    4138 /**
    4139  * Deals carefully with a LS_CFG register.
    4140  *
    4141  * @returns VBox status code.
    4142  * @param   uMsr                The MSR number.
    4143  * @param   uValue              The current value.
    4144  */
    4145 static int reportMsr_AmdK7InstrCacheCfg(uint32_t uMsr, uint64_t uValue)
    4146 {
    4147     /* Skip know bits here, as harm seems to come from messing with them. */
    4148     uint64_t fSkipMask = RT_BIT_64(9) /* DIS_SPEC_TLB_RLD */;
    4149     if (CPUMMICROARCH_IS_AMD_FAM_10H(g_enmMicroarch))
    4150         fSkipMask |= RT_BIT_64(14); /* DIS_IND */
    4151     if (CPUMMICROARCH_IS_AMD_FAM_16H(g_enmMicroarch))
    4152         fSkipMask |= RT_BIT_64(26); /* DIS_WIDEREAD_PWR_SAVE */
    4153     if (CPUMMICROARCH_IS_AMD_FAM_15H(g_enmMicroarch))
    4154     {
    4155         fSkipMask |= 0x1e;          /* DisIcWayFilter */
    4156         fSkipMask |= RT_BIT_64(39); /* DisLoopPredictor */
    4157         fSkipMask |= RT_BIT_64(27); /* Unknown killer bit, possibly applicable to other microarchs. */
    4158         fSkipMask |= RT_BIT_64(28); /* Unknown killer bit, possibly applicable to other microarchs. */
    4159     }
    4160     return reportMsr_GenFunctionEx(uMsr, NULL, uValue, fSkipMask, 0, annotateValue(uValue));
    4161 }
    4162 
    4163 
    4164 /**
    4165  * Deals carefully with a CU_CFG register.
    4166  *
    4167  * @returns VBox status code.
    4168  * @param   uMsr                The MSR number.
    4169  * @param   uValue              The current value.
    4170  */
    4171 static int reportMsr_AmdFam15hCombUnitCfg(uint32_t uMsr, uint64_t uValue)
    4172 {
    4173     /* Skip know bits here, as harm seems to come from messing with them. */
    4174     uint64_t fSkipMask = RT_BIT_64(23) /* L2WayLock  */
    4175                        | RT_BIT_64(22) /* L2FirstLockWay */
    4176                        | RT_BIT_64(21) /* L2FirstLockWay */
    4177                        | RT_BIT_64(20) /* L2FirstLockWay */
    4178                        | RT_BIT_64(19) /* L2FirstLockWay */
    4179                        | RT_BIT_64(10) /* DcacheAggressivePriority */;
    4180     fSkipMask |= RT_BIT_64(46) | RT_BIT_64(45); /* Killer field. Seen bit 46 set, 45 clear. Messing with either means reboot/BSOD. */
    4181     return reportMsr_GenFunctionEx(uMsr, NULL, uValue, fSkipMask, 0, annotateValue(uValue));
    4182 }
    4183 
    4184 
    4185 /**
    4186  * Deals carefully with a EX_CFG register.
    4187  *
    4188  * @returns VBox status code.
    4189  * @param   uMsr                The MSR number.
    4190  * @param   uValue              The current value.
    4191  */
    4192 static int reportMsr_AmdFam15hExecUnitCfg(uint32_t uMsr, uint64_t uValue)
    4193 {
    4194     /* Skip know bits here, as harm seems to come from messing with them. */
    4195     uint64_t fSkipMask = RT_BIT_64(54) /* LateSbzResync  */;
    4196     fSkipMask |= RT_BIT_64(35); /* Undocumented killer bit. */
    4197     return reportMsr_GenFunctionEx(uMsr, NULL, uValue, fSkipMask, 0, annotateValue(uValue));
    4198 }
    4199 
    4200 
    4201 
    4202 static int produceMsrReport(VBCPUREPMSR *paMsrs, uint32_t cMsrs)
    4203 {
    4204     vbCpuRepDebug("produceMsrReport\n");
    4205     RTThreadSleep(500);
    4206 
    4207     for (uint32_t i = 0; i < cMsrs; i++)
    4208     {
    4209         uint32_t    uMsr       = paMsrs[i].uMsr;
    4210         uint32_t    fFlags     = paMsrs[i].fFlags;
    4211         uint64_t    uValue     = paMsrs[i].uValue;
    4212         int         rc;
    4213 #if 0
    4214         //if (uMsr < 0x00000000)
    4215         //    continue;
    4216         if (uMsr >= 0x00000277)
    4217         {
    4218             vbCpuRepDebug("produceMsrReport: uMsr=%#x (%s)...\n", uMsr, getMsrNameHandled(uMsr));
    4219             RTThreadSleep(1000);
    4220         }
    4221 #endif
    4222         /*
    4223          * Deal with write only regs first to avoid having to avoid them all the time.
    4224          */
    4225         if (fFlags & VBCPUREPMSR_F_WRITE_ONLY)
    4226         {
    4227             if (uMsr == 0x00000079)
    4228                 rc = printMsrWriteOnly(uMsr, NULL, NULL);
    4229             else
    4230                 rc = reportMsr_Generic(uMsr, fFlags, uValue);
    4231         }
    4232         /*
    4233          * VIA implement MSRs in a interesting way, so we have to select what we
    4234          * want to handle there to avoid making the code below unreadable.
    4235          */
    4236         /** @todo r=klaus check if Shanghai CPUs really are behaving the same */
    4237         else if (isMsrViaShanghaiDummy(uMsr, uValue, fFlags))
    4238             rc = reportMsr_ViaShanghaiDummyRange(&paMsrs[i], cMsrs - i, &i);
    4239         /*
    4240          * This shall be sorted by uMsr as much as possible.
    4241          */
    4242         else if (uMsr == 0x00000000 && (g_enmVendor == CPUMCPUVENDOR_AMD || g_enmVendor == CPUMCPUVENDOR_HYGON) && g_enmMicroarch >= kCpumMicroarch_AMD_K8_First)
    4243             rc = printMsrAlias(uMsr, 0x00000402, NULL);
    4244         else if (uMsr == 0x00000001 && (g_enmVendor == CPUMCPUVENDOR_AMD || g_enmVendor == CPUMCPUVENDOR_HYGON) && g_enmMicroarch >= kCpumMicroarch_AMD_K8_First)
    4245             rc = printMsrAlias(uMsr, 0x00000401, NULL); /** @todo not 101% correct on Fam15h and later, 0xc0010015[McstatusWrEn] effect differs. */
    4246         else if (uMsr == 0x0000001b)
    4247             rc = reportMsr_Ia32ApicBase(uMsr, uValue);
    4248         else if (uMsr == 0x00000040 && g_enmMicroarch <= kCpumMicroarch_Intel_P6_M_Dothan)
    4249             rc = reportMsr_GenRangeFunction(&paMsrs[i], cMsrs - i, 8 /*cMax*/, "IntelLastBranchFromToN", &i);
    4250         else if (uMsr == 0x00000040)
    4251             rc = reportMsr_GenRangeFunctionEx(&paMsrs[i], cMsrs - i, 8 /*cMax*/, "IntelLastBranchToN", uMsr, false,
    4252                                               true, getGenericSkipMask(uMsr), &i);
    4253         else if (uMsr == 0x00000060 && g_enmMicroarch >= kCpumMicroarch_Intel_Core_Yonah)
    4254             rc = reportMsr_GenRangeFunctionEx(&paMsrs[i], cMsrs - i, 8 /*cMax*/, "IntelLastBranchFromN", uMsr, false,
    4255                                               true, getGenericSkipMask(uMsr), &i);
    4256         else if (uMsr == 0x000000c1)
    4257             rc = reportMsr_GenRangeFunction(&paMsrs[i], cMsrs - i,
    4258                                             g_enmMicroarch >= kCpumMicroarch_Intel_Core7_First ? 8 : 4 /*cMax*/,
    4259                                             NULL, &i);
    4260         else if (uMsr == 0x00000186 && !g_fIntelNetBurst)
    4261             rc = reportMsr_GenRangeFunction(&paMsrs[i], cMsrs - i, 8 /*cMax*/, "Ia32PerfEvtSelN", &i);
    4262         else if (uMsr == 0x000001a0)
    4263             rc = reportMsr_Ia32MiscEnable(uMsr, uValue);
    4264         else if (uMsr >= 0x000001a6 && uMsr <= 0x000001a7)
    4265             rc = reportMsr_GenRangeFunction(&paMsrs[i], cMsrs - i, 2 /*cMax*/, "IntelI7MsrOffCoreResponseN", &i);
    4266         else if (uMsr == 0x000001db && g_fIntelNetBurst)
    4267             rc = reportMsr_GenRangeFunction(&paMsrs[i], cMsrs - i, 4 /*cMax*/, "IntelLastBranchFromToN", &i);
    4268         else if (uMsr == 0x00000200)
    4269             rc = reportMsr_Ia32MtrrPhysBaseMaskN(&paMsrs[i], cMsrs - i, &i);
    4270         else if (uMsr >= 0x00000250 && uMsr <= 0x00000279)
    4271             rc = reportMsr_Ia32MtrrFixedOrPat(uMsr);
    4272         else if (uMsr >= 0x00000280 && uMsr <= 0x00000295)
    4273             rc = reportMsr_GenRangeFunctionEx(&paMsrs[i], cMsrs - i, 22 /*cMax*/, NULL, 0x00000280, true /*fEarlyEndOk*/, false, 0, &i);
    4274         else if (uMsr == 0x000002ff)
    4275             rc = reportMsr_Ia32MtrrDefType(uMsr);
    4276         else if (uMsr >= 0x00000309 && uMsr <= 0x0000030b && !g_fIntelNetBurst)
    4277             rc = reportMsr_GenRangeFunctionEx(&paMsrs[i], cMsrs - i, 3 /*cMax*/, NULL, 0x00000309, true /*fEarlyEndOk*/, false, 0, &i);
    4278         else if ((uMsr == 0x000003f8 || uMsr == 0x000003fc || uMsr == 0x0000060a) && !g_fIntelNetBurst)
    4279             rc = reportMsr_GenRangeFunctionEx(&paMsrs[i], cMsrs - i, 4, NULL, uMsr - 3, true, false, 0, &i);
    4280         else if ((uMsr == 0x000003f9 || uMsr == 0x000003fd || uMsr == 0x0000060b) && !g_fIntelNetBurst)
    4281             rc = reportMsr_GenRangeFunctionEx(&paMsrs[i], cMsrs - i, 8, NULL, uMsr - 6, true, false, 0, &i);
    4282         else if ((uMsr == 0x000003fa || uMsr == 0x000003fe || uMsr == 0x0000060c) && !g_fIntelNetBurst)
    4283             rc = reportMsr_GenRangeFunctionEx(&paMsrs[i], cMsrs - i, 8, NULL, uMsr - 7, true, false, 0, &i);
    4284         else if (uMsr >= 0x00000400 && uMsr <= 0x00000477)
    4285             rc = reportMsr_Ia32McCtlStatusAddrMiscN(&paMsrs[i], cMsrs - i, &i);
    4286         else if (uMsr == 0x000004c1)
    4287             rc = reportMsr_GenRangeFunction(&paMsrs[i], cMsrs - i, 8, NULL, &i);
    4288         else if (uMsr == 0x00000680 || uMsr == 0x000006c0)
    4289             rc = reportMsr_GenRangeFunctionEx(&paMsrs[i], cMsrs - i, 16, NULL, uMsr, false, false,
    4290                                               g_fIntelNetBurst
    4291                                               ? UINT64_C(0xffffffffffffff00) /* kludge */
    4292                                               : UINT64_C(0xffff800000000000), &i);
    4293         else if (uMsr >= 0x00000800 && uMsr <= 0x000008ff)
    4294             rc = reportMsr_GenX2Apic(&paMsrs[i], cMsrs - i, &i);
    4295         else if (uMsr == 0x00002000 && g_enmVendor == CPUMCPUVENDOR_INTEL)
    4296             rc = reportMsr_GenFunctionEx(uMsr, "IntelP6CrN", 0, X86_CR0_PE | X86_CR0_PG, 0,
    4297                                          annotateIfMissingBits(uValue, X86_CR0_PE | X86_CR0_PE | X86_CR0_ET));
    4298         else if (uMsr == 0x00002002 && g_enmVendor == CPUMCPUVENDOR_INTEL)
    4299             rc = reportMsr_GenFunctionEx(uMsr, "IntelP6CrN", 2, 0, 0, annotateValue(uValue));
    4300         else if (uMsr == 0x00002003 && g_enmVendor == CPUMCPUVENDOR_INTEL)
    4301         {
    4302             uint64_t fCr3Mask = (RT_BIT_64(vbCpuRepGetPhysAddrWidth()) - 1) & (X86_CR3_PAE_PAGE_MASK | X86_CR3_AMD64_PAGE_MASK);
    4303             if (!vbCpuRepSupportsPae())
    4304                 fCr3Mask &= X86_CR3_PAGE_MASK | X86_CR3_AMD64_PAGE_MASK;
    4305             rc = reportMsr_GenFunctionEx(uMsr, "IntelP6CrN", 3, fCr3Mask, 0, annotateValue(uValue));
    4306         }
    4307         else if (uMsr == 0x00002004 && g_enmVendor == CPUMCPUVENDOR_INTEL)
    4308             rc = reportMsr_GenFunctionEx(uMsr, "IntelP6CrN", 4,
    4309                                          X86_CR4_PSE | X86_CR4_PAE | X86_CR4_MCE | X86_CR4_SMXE, 0,
    4310                                          annotateValue(uValue));
    4311         else if (uMsr == 0xc0000080)
    4312             rc = reportMsr_Amd64Efer(uMsr, uValue);
    4313         else if (uMsr >= 0xc0000408 && uMsr <= 0xc000040f)
    4314             rc = reportMsr_AmdFam10hMc4MiscN(&paMsrs[i], cMsrs - i, &i);
    4315         else if (uMsr == 0xc0010000 && (g_enmVendor == CPUMCPUVENDOR_AMD || g_enmVendor == CPUMCPUVENDOR_HYGON))
    4316             rc = reportMsr_AmdK8PerfCtlN(&paMsrs[i], cMsrs - i, &i);
    4317         else if (uMsr == 0xc0010004 && (g_enmVendor == CPUMCPUVENDOR_AMD || g_enmVendor == CPUMCPUVENDOR_HYGON))
    4318             rc = reportMsr_AmdK8PerfCtrN(&paMsrs[i], cMsrs - i, &i);
    4319         else if (uMsr == 0xc0010010 && (g_enmVendor == CPUMCPUVENDOR_AMD || g_enmVendor == CPUMCPUVENDOR_HYGON))
    4320             rc = reportMsr_AmdK8SysCfg(uMsr, uValue);
    4321         else if (uMsr == 0xc0010015 && (g_enmVendor == CPUMCPUVENDOR_AMD || g_enmVendor == CPUMCPUVENDOR_HYGON))
    4322             rc = reportMsr_AmdK8HwCr(uMsr, uValue);
    4323         else if ((uMsr == 0xc0010016 || uMsr == 0xc0010018) && (g_enmVendor == CPUMCPUVENDOR_AMD || g_enmVendor == CPUMCPUVENDOR_HYGON))
    4324             rc = reportMsr_AmdK8IorrBaseN(uMsr, uValue);
    4325         else if ((uMsr == 0xc0010017 || uMsr == 0xc0010019) && (g_enmVendor == CPUMCPUVENDOR_AMD || g_enmVendor == CPUMCPUVENDOR_HYGON))
    4326             rc = reportMsr_AmdK8IorrMaskN(uMsr, uValue);
    4327         else if ((uMsr == 0xc001001a || uMsr == 0xc001001d) && (g_enmVendor == CPUMCPUVENDOR_AMD || g_enmVendor == CPUMCPUVENDOR_HYGON))
    4328             rc = reportMsr_AmdK8TopMemN(uMsr, uValue);
    4329         else if (uMsr == 0xc0010030 && (g_enmVendor == CPUMCPUVENDOR_AMD || g_enmVendor == CPUMCPUVENDOR_HYGON))
    4330             rc = reportMsr_GenRangeFunction(&paMsrs[i], cMsrs - i, 6, "AmdK8CpuNameN", &i);
    4331         else if (uMsr >= 0xc0010044 && uMsr <= 0xc001004a && (g_enmVendor == CPUMCPUVENDOR_AMD || g_enmVendor == CPUMCPUVENDOR_HYGON))
    4332             rc = reportMsr_GenRangeFunctionEx(&paMsrs[i], cMsrs - i, 7, "AmdK8McCtlMaskN", 0xc0010044, true /*fEarlyEndOk*/, false, 0, &i);
    4333         else if (uMsr == 0xc0010050 && (g_enmVendor == CPUMCPUVENDOR_AMD || g_enmVendor == CPUMCPUVENDOR_HYGON))
    4334             rc = reportMsr_GenRangeFunction(&paMsrs[i], cMsrs - i, 4, "AmdK8SmiOnIoTrapN", &i);
    4335         else if (uMsr == 0xc0010064 && (g_enmVendor == CPUMCPUVENDOR_AMD || g_enmVendor == CPUMCPUVENDOR_HYGON))
    4336             rc = reportMsr_AmdFam10hPStateN(&paMsrs[i], cMsrs - i, &i);
    4337         else if (uMsr == 0xc0010070 && (g_enmVendor == CPUMCPUVENDOR_AMD || g_enmVendor == CPUMCPUVENDOR_HYGON))
    4338             rc = reportMsr_AmdFam10hCofVidControl(uMsr, uValue);
    4339         else if ((uMsr == 0xc0010118 || uMsr == 0xc0010119) && getMsrFnName(uMsr, NULL) && (g_enmVendor == CPUMCPUVENDOR_AMD || g_enmVendor == CPUMCPUVENDOR_HYGON))
    4340             rc = printMsrFunction(uMsr, NULL, NULL, annotateValue(uValue)); /* RAZ, write key. */
    4341         else if (uMsr == 0xc0010200 && (g_enmVendor == CPUMCPUVENDOR_AMD || g_enmVendor == CPUMCPUVENDOR_HYGON))
    4342             rc = reportMsr_AmdGenPerfMixedRange(&paMsrs[i], cMsrs - i, 12, &i);
    4343         else if (uMsr == 0xc0010230 && (g_enmVendor == CPUMCPUVENDOR_AMD || g_enmVendor == CPUMCPUVENDOR_HYGON))
    4344             rc = reportMsr_AmdGenPerfMixedRange(&paMsrs[i], cMsrs - i, 8, &i);
    4345         else if (uMsr == 0xc0010240 && (g_enmVendor == CPUMCPUVENDOR_AMD || g_enmVendor == CPUMCPUVENDOR_HYGON))
    4346             rc = reportMsr_AmdGenPerfMixedRange(&paMsrs[i], cMsrs - i, 8, &i);
    4347         else if (uMsr == 0xc0011019 && g_enmMicroarch >= kCpumMicroarch_AMD_15h_Piledriver && (g_enmVendor == CPUMCPUVENDOR_AMD || g_enmVendor == CPUMCPUVENDOR_HYGON))
    4348             rc = reportMsr_GenRangeFunctionEx(&paMsrs[i], cMsrs - i, 3, "AmdK7DrXAddrMaskN", 0xc0011019 - 1,
    4349                                               false /*fEarlyEndOk*/, false /*fNoIgnMask*/, 0, &i);
    4350         else if (uMsr == 0xc0011021 && (g_enmVendor == CPUMCPUVENDOR_AMD || g_enmVendor == CPUMCPUVENDOR_HYGON))
    4351             rc = reportMsr_AmdK7InstrCacheCfg(uMsr, uValue);
    4352         else if (uMsr == 0xc0011023 && CPUMMICROARCH_IS_AMD_FAM_15H(g_enmMicroarch))
    4353             rc = reportMsr_AmdFam15hCombUnitCfg(uMsr, uValue);
    4354         else if (uMsr == 0xc0011027 && (g_enmVendor == CPUMCPUVENDOR_AMD || g_enmVendor == CPUMCPUVENDOR_HYGON))
    4355             rc = reportMsr_GenRangeFunctionEx(&paMsrs[i], cMsrs - i, 1, "AmdK7DrXAddrMaskN", 0xc0011027,
    4356                                               false /*fEarlyEndOk*/, false /*fNoIgnMask*/, 0, &i);
    4357         else if (uMsr == 0xc001102c && CPUMMICROARCH_IS_AMD_FAM_15H(g_enmMicroarch))
    4358             rc = reportMsr_AmdFam15hExecUnitCfg(uMsr, uValue);
    4359         /* generic handling. */
    4360         else
    4361             rc = reportMsr_Generic(uMsr, fFlags, uValue);
    4362 
    4363         if (RT_FAILURE(rc))
    4364             return rc;
    4365 
    4366         /*
    4367          *  A little ugly snooping.
    4368          */
    4369         if (uMsr == 0x000000cd && !(fFlags & VBCPUREPMSR_F_WRITE_ONLY))
    4370             g_uMsrIntelP6FsbFrequency = uValue;
    4371     }
    4372 
    4373     return VINF_SUCCESS;
    4374 }
    4375 
    4376 
    4377 /**
    4378  * Custom MSR hacking & probing.
    4379  *
    4380  * Called when the '-d' option is given.
    4381  *
    4382  * @returns VBox status code.
    4383  */
    4384 static int hackingMsrs(void)
    4385 {
    4386 #if 0
    4387     vbCpuRepDebug("\nhackingMsrs:\n"); RTStrmFlush(g_pDebugOut); RTThreadSleep(2000);
    4388 
    4389     uint32_t uMsr = 0xc0000081;
    4390     vbCpuRepDebug("%#x: msrProberModifyNoChange -> %RTbool\n", uMsr, msrProberModifyNoChange(uMsr));
    4391     RTThreadSleep(3000);
    4392 
    4393     vbCpuRepDebug("%#x: msrProberModifyBit 30 -> %d\n", uMsr, msrProberModifyBit(uMsr, 30));
    4394     RTThreadSleep(3000);
    4395 
    4396     vbCpuRepDebug("%#x: msrProberModifyZero -> %RTbool\n", uMsr, msrProberModifyZero(uMsr));
    4397     RTThreadSleep(3000);
    4398 
    4399     for (uint32_t i = 0; i < 63; i++)
    4400     {
    4401         vbCpuRepDebug("%#x: bit=%02u -> %d\n", msrProberModifyBit(uMsr, i));
    4402         RTThreadSleep(500);
    4403     }
    4404 #else
    4405 
    4406     uint32_t uMsr = 0xc0010010;
    4407     uint64_t uValue = 0;
    4408     msrProberRead(uMsr, &uValue);
    4409     reportMsr_AmdK8SysCfg(uMsr, uValue);
    4410 #endif
    4411     return VINF_SUCCESS;
    4412 }
    4413 
    4414 
    4415 static int probeMsrs(bool fHacking, const char *pszNameC, const char *pszCpuDesc,
    4416                      char *pszMsrMask, size_t cbMsrMask)
    4417 {
    4418     /* Initialize the mask. */
    4419     if (pszMsrMask && cbMsrMask)
    4420         RTStrCopy(pszMsrMask, cbMsrMask, "UINT32_MAX /** @todo */");
    4421 
    4422     /*
    4423      * Are MSRs supported by the CPU?
    4424      */
    4425     if (   !RTX86IsValidStdRange(ASMCpuId_EAX(0))
    4426         || !(ASMCpuId_EDX(1) & X86_CPUID_FEATURE_EDX_MSR) )
    4427     {
    4428         vbCpuRepDebug("Skipping MSR probing, CPUID indicates there isn't any MSR support.\n");
    4429         return VINF_SUCCESS;
    4430     }
    4431     if (g_fNoMsrs)
    4432     {
    4433         vbCpuRepDebug("Skipping MSR probing (--no-msr).\n");
    4434         return VINF_SUCCESS;
    4435     }
    4436 
    4437     /*
    4438      * First try the the support library (also checks if we can really read MSRs).
    4439      */
    4440     int rc = VbCpuRepMsrProberInitSupDrv(&g_MsrAcc);
    4441     if (RT_FAILURE(rc))
    4442     {
    4443 #ifdef VBCR_HAVE_PLATFORM_MSR_PROBER
    4444         /* Next try a platform-specific interface. */
    4445         rc = VbCpuRepMsrProberInitPlatform(&g_MsrAcc);
    4446 #endif
    4447         if (RT_FAILURE(rc))
    4448         {
    4449             vbCpuRepDebug("warning: Unable to initialize any MSR access interface (%Rrc), skipping MSR detection.\n", rc);
    4450             return VINF_SUCCESS;
    4451         }
    4452     }
    4453 
    4454     uint64_t uValue;
    4455     bool     fGp;
    4456     rc = g_MsrAcc.pfnMsrProberRead(MSR_IA32_TSC, NIL_RTCPUID, &uValue, &fGp);
    4457     if (RT_FAILURE(rc))
    4458     {
    4459         vbCpuRepDebug("warning: MSR probing not supported by the support driver (%Rrc), skipping MSR detection.\n", rc);
    4460         return VINF_SUCCESS;
    4461     }
    4462     vbCpuRepDebug("MSR_IA32_TSC: %#llx fGp=%RTbool\n", uValue, fGp);
    4463     rc = g_MsrAcc.pfnMsrProberRead(0xdeadface, NIL_RTCPUID, &uValue, &fGp);
    4464     vbCpuRepDebug("0xdeadface: %#llx fGp=%RTbool rc=%Rrc\n", uValue, fGp, rc);
    4465 
    4466     /*
    4467      * Initialize globals we use.
    4468      */
    4469     uint32_t uEax, uEbx, uEcx, uEdx;
    4470     ASMCpuIdExSlow(0, 0, 0, 0, &uEax, &uEbx, &uEcx, &uEdx);
    4471     if (!RTX86IsValidStdRange(uEax))
    4472         return RTMsgErrorRc(VERR_NOT_SUPPORTED, "Invalid std CPUID range: %#x\n", uEax);
    4473     g_enmVendor = CPUMCpuIdDetectX86VendorEx(uEax, uEbx, uEcx, uEdx);
    4474 
    4475     ASMCpuIdExSlow(1, 0, 0, 0, &uEax, &uEbx, &uEcx, &uEdx);
    4476     g_enmMicroarch = CPUMCpuIdDetermineX86MicroarchEx(g_enmVendor,
    4477                                                       RTX86GetCpuFamily(uEax),
    4478                                                       RTX86GetCpuModel(uEax, g_enmVendor == CPUMCPUVENDOR_INTEL),
    4479                                                       RTX86GetCpuStepping(uEax));
    4480     g_fIntelNetBurst = CPUMMICROARCH_IS_INTEL_NETBURST(g_enmMicroarch);
    4481 
    4482     /*
    4483      * Do the probing.
    4484      */
    4485     if (fHacking)
    4486         rc = hackingMsrs();
    4487     else
    4488     {
    4489         /* Determine the MSR mask. */
    4490         uint32_t fMsrMask = determineMsrAndMask();
    4491         if (fMsrMask == UINT32_MAX)
    4492             RTStrCopy(pszMsrMask, cbMsrMask, "UINT32_MAX");
    4493         else
    4494             RTStrPrintf(pszMsrMask, cbMsrMask, "UINT32_C(%#x)", fMsrMask);
    4495 
    4496         /* Detect MSR. */
    4497         VBCPUREPMSR    *paMsrs;
    4498         uint32_t        cMsrs;
    4499         rc = findMsrs(&paMsrs, &cMsrs, fMsrMask);
    4500         if (RT_FAILURE(rc))
    4501             return rc;
    4502 
    4503         /* Probe the MSRs and spit out the database table. */
    4504         vbCpuRepPrintf("\n"
    4505                        "#ifndef CPUM_DB_STANDALONE\n"
    4506                        "/**\n"
    4507                        " * MSR ranges for %s.\n"
    4508                        " */\n"
    4509                        "static CPUMMSRRANGE const g_aMsrRanges_%s[] =\n{\n",
    4510                        pszCpuDesc,
    4511                        pszNameC);
    4512         rc = produceMsrReport(paMsrs, cMsrs);
    4513         vbCpuRepPrintf("};\n"
    4514                        "#endif /* !CPUM_DB_STANDALONE */\n"
    4515                        "\n"
    4516                        );
    4517 
    4518         RTMemFree(paMsrs);
    4519         paMsrs = NULL;
    4520     }
    4521     if (g_MsrAcc.pfnTerm)
    4522         g_MsrAcc.pfnTerm();
    4523     RT_ZERO(g_MsrAcc);
    4524     return rc;
    4525 }
    4526 
    4527 
    4528 static int produceCpuIdArray(const char *pszNameC, const char *pszCpuDesc)
    4529 {
    4530     /*
    4531      * Collect the data.
    4532      */
    4533     PCPUMCPUIDLEAF  paLeaves;
    4534     uint32_t        cLeaves;
    4535     int rc = CPUMCpuIdCollectLeavesFromX86Host(&paLeaves, &cLeaves);
    4536     if (RT_FAILURE(rc))
    4537         return RTMsgErrorRc(rc, "CPUMR3CollectCpuIdInfo failed: %Rrc\n", rc);
    4538 
    4539     /*
    4540      * Dump the array.
    4541      */
    4542     vbCpuRepPrintf("\n"
    4543                    "#ifndef CPUM_DB_STANDALONE\n"
    4544                    "/**\n"
    4545                    " * CPUID leaves for %s.\n"
    4546                    " */\n"
    4547                    "static CPUMCPUIDLEAF const g_aCpuIdLeaves_%s[] =\n{\n",
    4548                    pszCpuDesc,
    4549                    pszNameC);
    4550     for (uint32_t i = 0; i < cLeaves; i++)
    4551     {
    4552         vbCpuRepPrintf("    { %#010x, %#010x, ", paLeaves[i].uLeaf, paLeaves[i].uSubLeaf);
    4553         if (paLeaves[i].fSubLeafMask == UINT32_MAX)
    4554             vbCpuRepPrintf("UINT32_MAX, ");
    4555         else
    4556             vbCpuRepPrintf("%#010x, ", paLeaves[i].fSubLeafMask);
    4557         vbCpuRepPrintf("%#010x, %#010x, %#010x, %#010x, ",
    4558                      paLeaves[i].uEax, paLeaves[i].uEbx, paLeaves[i].uEcx, paLeaves[i].uEdx);
    4559         if (paLeaves[i].fFlags == 0)
    4560             vbCpuRepPrintf("0 },\n");
    4561         else
    4562         {
    4563             vbCpuRepPrintf("0");
    4564             uint32_t fFlags = paLeaves[i].fFlags;
    4565             if (paLeaves[i].fFlags & CPUMCPUIDLEAF_F_INTEL_TOPOLOGY_SUBLEAVES)
    4566             {
    4567                 vbCpuRepPrintf(" | CPUMCPUIDLEAF_F_INTEL_TOPOLOGY_SUBLEAVES");
    4568                 fFlags &= ~CPUMCPUIDLEAF_F_INTEL_TOPOLOGY_SUBLEAVES;
    4569             }
    4570             if (paLeaves[i].fFlags & CPUMCPUIDLEAF_F_CONTAINS_APIC_ID)
    4571             {
    4572                 vbCpuRepPrintf(" | CPUMCPUIDLEAF_F_CONTAINS_APIC_ID");
    4573                 fFlags &= ~CPUMCPUIDLEAF_F_CONTAINS_APIC_ID;
    4574             }
    4575             if (paLeaves[i].fFlags & CPUMCPUIDLEAF_F_CONTAINS_APIC)
    4576             {
    4577                 vbCpuRepPrintf(" | CPUMCPUIDLEAF_F_CONTAINS_APIC");
    4578                 fFlags &= ~CPUMCPUIDLEAF_F_CONTAINS_APIC;
    4579             }
    4580             if (fFlags)
    4581             {
    4582                 RTMemFree(paLeaves);
    4583                 return RTMsgErrorRc(rc, "Unknown CPUID flags %#x\n", fFlags);
    4584             }
    4585             vbCpuRepPrintf(" },\n");
    4586         }
    4587     }
    4588     vbCpuRepPrintf("};\n"
    4589                    "#endif /* !CPUM_DB_STANDALONE */\n"
    4590                    "\n");
    4591     RTMemFree(paLeaves);
    4592     return VINF_SUCCESS;
    4593 }
    4594 
    4595 
    4596 static const char *cpuVendorToString(CPUMCPUVENDOR enmCpuVendor)
     115const char *vbCpuVendorToString(CPUMCPUVENDOR enmCpuVendor)
    4597116{
    4598117    switch (enmCpuVendor)
     
    4614133
    4615134
    4616 /**
    4617  * Takes a shot a the bus frequency name (last part).
    4618  *
    4619  * @returns Name suffix.
    4620  */
    4621 static const char *vbCpuRepGuessScalableBusFrequencyName(void)
    4622 {
    4623     if (CPUMMICROARCH_IS_INTEL_CORE7(g_enmMicroarch))
    4624         return g_enmMicroarch >= kCpumMicroarch_Intel_Core7_SandyBridge ? "100MHZ" : "133MHZ";
    4625 
    4626     if (g_uMsrIntelP6FsbFrequency != UINT64_MAX)
    4627         switch (g_uMsrIntelP6FsbFrequency & 0x7)
    4628         {
    4629             case 5: return "100MHZ";
    4630             case 1: return "133MHZ";
    4631             case 3: return "167MHZ";
    4632             case 2: return "200MHZ";
    4633             case 0: return "267MHZ";
    4634             case 4: return "333MHZ";
    4635             case 6: return "400MHZ";
    4636         }
    4637 
    4638     return "UNKNOWN";
    4639 }
    4640 
    4641 
    4642 static int produceCpuReport(void)
    4643 {
    4644     /*
    4645      * Figure the cpu vendor.
    4646      */
    4647     if (!ASMHasCpuId())
    4648         return RTMsgErrorRc(VERR_NOT_SUPPORTED, "No CPUID support.\n");
    4649     uint32_t uEax, uEbx, uEcx, uEdx;
    4650     ASMCpuIdExSlow(0, 0, 0, 0, &uEax, &uEbx, &uEcx, &uEdx);
    4651     if (!RTX86IsValidStdRange(uEax))
    4652         return RTMsgErrorRc(VERR_NOT_SUPPORTED, "Invalid std CPUID range: %#x\n", uEax);
    4653 
    4654     CPUMCPUVENDOR enmVendor = CPUMCpuIdDetectX86VendorEx(uEax, uEbx, uEcx, uEdx);
    4655     if (enmVendor == CPUMCPUVENDOR_UNKNOWN)
    4656         return RTMsgErrorRc(VERR_NOT_IMPLEMENTED, "Unknown CPU vendor: %.4s%.4s%.4s\n", &uEbx, &uEdx, &uEcx);
    4657     vbCpuRepDebug("CPU Vendor: %s - %.4s%.4s%.4s\n", CPUMCpuVendorName(enmVendor), &uEbx, &uEdx, &uEcx);
    4658 
    4659     /*
    4660      * Determine the micro arch.
    4661      */
    4662     ASMCpuIdExSlow(1, 0, 0, 0, &uEax, &uEbx, &uEcx, &uEdx);
    4663     CPUMMICROARCH enmMicroarch = CPUMCpuIdDetermineX86MicroarchEx(enmVendor,
    4664                                                                   RTX86GetCpuFamily(uEax),
    4665                                                                   RTX86GetCpuModel(uEax, enmVendor == CPUMCPUVENDOR_INTEL),
    4666                                                                   RTX86GetCpuStepping(uEax));
    4667 
    4668     /*
    4669      * Generate a name.
    4670      */
    4671     char  szName[16*3+1];
    4672     char  szNameC[16*3+1];
    4673     char  szNameRaw[16*3+1];
    4674     char *pszName    = szName;
    4675     char *pszCpuDesc = (char *)"";
    4676 
    4677     ASMCpuIdExSlow(0x80000000, 0, 0, 0, &uEax, &uEbx, &uEcx, &uEdx);
    4678     if (RTX86IsValidExtRange(uEax) && uEax >= UINT32_C(0x80000004))
    4679     {
    4680         /* Get the raw name and strip leading spaces. */
    4681         ASMCpuIdExSlow(0x80000002, 0, 0, 0, &szNameRaw[0 +  0], &szNameRaw[4 +  0], &szNameRaw[8 +  0], &szNameRaw[12 +  0]);
    4682         ASMCpuIdExSlow(0x80000003, 0, 0, 0, &szNameRaw[0 + 16], &szNameRaw[4 + 16], &szNameRaw[8 + 16], &szNameRaw[12 + 16]);
    4683         ASMCpuIdExSlow(0x80000004, 0, 0, 0, &szNameRaw[0 + 32], &szNameRaw[4 + 32], &szNameRaw[8 + 32], &szNameRaw[12 + 32]);
    4684         szNameRaw[48] = '\0';
    4685         pszCpuDesc = RTStrStrip(szNameRaw);
    4686         vbCpuRepDebug("Name2: %s\n", pszCpuDesc);
    4687 
    4688         /* Reduce the name. */
    4689         pszName = strcpy(szName, pszCpuDesc);
    4690 
    4691         static const char * const s_apszSuffixes[] =
    4692         {
    4693             "CPU @",
    4694         };
    4695         for (uint32_t i = 0; i < RT_ELEMENTS(s_apszSuffixes); i++)
    4696         {
    4697             char *pszHit = strstr(pszName, s_apszSuffixes[i]);
    4698             if (pszHit)
    4699                 RT_BZERO(pszHit, strlen(pszHit));
    4700         }
    4701 
    4702         static const char * const s_apszWords[] =
    4703         {
    4704             "(TM)", "(tm)", "(R)", "(r)", "Processor", "CPU", "@",
    4705         };
    4706         for (uint32_t i = 0; i < RT_ELEMENTS(s_apszWords); i++)
    4707         {
    4708             const char *pszWord = s_apszWords[i];
    4709             size_t      cchWord = strlen(pszWord);
    4710             char       *pszHit;
    4711             while ((pszHit = strstr(pszName, pszWord)) != NULL)
    4712                 memset(pszHit, ' ', cchWord);
    4713         }
    4714 
    4715         RTStrStripR(pszName);
    4716         for (char *psz = pszName; *psz; psz++)
    4717             if (RT_C_IS_BLANK(*psz))
    4718             {
    4719                 size_t cchBlanks = 1;
    4720                 while (RT_C_IS_BLANK(psz[cchBlanks]))
    4721                     cchBlanks++;
    4722                 *psz = ' ';
    4723                 if (cchBlanks > 1)
    4724                     memmove(psz + 1, psz + cchBlanks, strlen(psz + cchBlanks) + 1);
    4725             }
    4726         pszName = RTStrStripL(pszName);
    4727         vbCpuRepDebug("Name: %s\n", pszName);
    4728 
    4729         /* Make it C/C++ acceptable. */
    4730         strcpy(szNameC, pszName);
    4731         unsigned offDst = 0;
    4732         for (unsigned offSrc = 0; ; offSrc++)
    4733         {
    4734             char ch = szNameC[offSrc];
    4735             if (!RT_C_IS_ALNUM(ch) && ch != '_' && ch != '\0')
    4736                 ch = '_';
    4737             if (ch == '_' && offDst > 0 && szNameC[offDst - 1] == '_')
    4738                 offDst--;
    4739             szNameC[offDst++] = ch;
    4740             if (!ch)
    4741                 break;
    4742         }
    4743         while (offDst > 1 && szNameC[offDst - 1] == '_')
    4744             szNameC[--offDst] = '\0';
    4745 
    4746         vbCpuRepDebug("NameC: %s\n", szNameC);
    4747     }
    4748     else
    4749     {
    4750         ASMCpuIdExSlow(1, 0, 0, 0, &uEax, &uEbx, &uEcx, &uEdx);
    4751         RTStrPrintf(szNameC, sizeof(szNameC), "%s_%u_%u_%u", cpuVendorToString(enmVendor), RTX86GetCpuFamily(uEax),
    4752                     RTX86GetCpuModel(uEax, enmVendor == CPUMCPUVENDOR_INTEL), RTX86GetCpuStepping(uEax));
    4753         pszCpuDesc = pszName = szNameC;
    4754         vbCpuRepDebug("Name/NameC: %s\n", szNameC);
    4755     }
    4756 
    4757     /*
    4758      * Print a file header, if we're not outputting to stdout (assumption being
    4759      * that stdout is used while hacking the reporter and too much output is
    4760      * unwanted).
    4761      */
    4762     if (g_pReportOut)
    4763     {
    4764         RTTIMESPEC Now;
    4765         char       szNow[64];
    4766         RTTimeSpecToString(RTTimeNow(&Now), szNow, sizeof(szNow));
    4767         char *pchDot = strchr(szNow, '.');
    4768         if (pchDot)
    4769             strcpy(pchDot, "Z");
    4770 
    4771         vbCpuRepPrintf("/* $" "Id" "$ */\n"
    4772                        "/** @file\n"
    4773                        " * CPU database entry \"%s\".\n"
    4774                        " * Generated at %s by VBoxCpuReport v%sr%s on %s.%s.\n"
    4775                        " */\n"
    4776                        "\n"
    4777                        "/*\n"
    4778                        " * Copyright (C) 2013-" VBOX_C_YEAR " Oracle and/or its affiliates.\n"
    4779                        " *\n"
    4780                        " * This file is part of VirtualBox base platform packages, as\n"
    4781                        " * available from https://www.virtualbox.org.\n"
    4782                        " *\n"
    4783                        " * This program is free software; you can redistribute it and/or\n"
    4784                        " * modify it under the terms of the GNU General Public License\n"
    4785                        " * as published by the Free Software Foundation, in version 3 of the\n"
    4786                        " * License.\n"
    4787                        " *\n"
    4788                        " * This program is distributed in the hope that it will be useful, but\n"
    4789                        " * WITHOUT ANY WARRANTY; without even the implied warranty of\n"
    4790                        " * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\n"
    4791                        " * General Public License for more details.\n"
    4792                        " *\n"
    4793                        " * You should have received a copy of the GNU General Public License\n"
    4794                        " * along with this program; if not, see <https://www.gnu.org/licenses>.\n"
    4795                        " *\n"
    4796                        " * SPDX-License-Identifier: GPL-3.0-only\n"
    4797                        " */\n"
    4798                        "\n"
    4799                        "#ifndef VBOX_CPUDB_%s_h\n"
    4800                        "#define VBOX_CPUDB_%s_h\n"
    4801                        "#ifndef RT_WITHOUT_PRAGMA_ONCE\n"
    4802                        "# pragma once\n"
    4803                        "#endif\n"
    4804                        "\n",
    4805                        pszName,
    4806                        szNow, RTBldCfgVersion(), RTBldCfgRevisionStr(), RTBldCfgTarget(), RTBldCfgTargetArch(),
    4807                        szNameC, szNameC);
    4808     }
    4809 
    4810     /*
    4811      * Extract CPUID based data.
    4812      */
    4813     int rc = produceCpuIdArray(szNameC, pszCpuDesc);
    4814     if (RT_FAILURE(rc))
    4815         return rc;
    4816 
    4817     CPUMUNKNOWNCPUID enmUnknownMethod;
    4818     CPUMCPUID        DefUnknown;
    4819     rc = CPUMR3CpuIdDetectUnknownLeafMethod(&enmUnknownMethod, &DefUnknown);
    4820     if (RT_FAILURE(rc))
    4821         return RTMsgErrorRc(rc, "CPUMR3DetectCpuIdUnknownMethod failed: %Rrc\n", rc);
    4822     vbCpuRepDebug("enmUnknownMethod=%s\n", CPUMR3CpuIdUnknownLeafMethodName(enmUnknownMethod));
    4823 
    4824     /*
    4825      * Do the MSRs, if we can.
    4826      */
    4827     char szMsrMask[64];
    4828     probeMsrs(false /*fHacking*/, szNameC, pszCpuDesc, szMsrMask, sizeof(szMsrMask));
    4829 
    4830     /*
    4831      * Emit the CPUMDBENTRY record.
    4832      */
    4833     ASMCpuIdExSlow(1, 0, 0, 0, &uEax, &uEbx, &uEcx, &uEdx);
    4834     vbCpuRepPrintf("\n"
    4835                    "/**\n"
    4836                    " * Database entry for %s.\n"
    4837                    " */\n"
    4838                    "static CPUMDBENTRY const g_Entry_%s = \n"
    4839                    "{\n"
    4840                    "    /*.pszName          = */ \"%s\",\n"
    4841                    "    /*.pszFullName      = */ \"%s\",\n"
    4842                    "    /*.enmVendor        = */ CPUMCPUVENDOR_%s,\n"
    4843                    "    /*.uFamily          = */ %u,\n"
    4844                    "    /*.uModel           = */ %u,\n"
    4845                    "    /*.uStepping        = */ %u,\n"
    4846                    "    /*.enmMicroarch     = */ kCpumMicroarch_%s,\n"
    4847                    "    /*.uScalableBusFreq = */ CPUM_SBUSFREQ_%s,\n"
    4848                    "    /*.fFlags           = */ 0,\n"
    4849                    "    /*.cMaxPhysAddrWidth= */ %u,\n"
    4850                    "    /*.fMxCsrMask       = */ %#010x,\n"
    4851                    "    /*.paCpuIdLeaves    = */ NULL_ALONE(g_aCpuIdLeaves_%s),\n"
    4852                    "    /*.cCpuIdLeaves     = */ ZERO_ALONE(RT_ELEMENTS(g_aCpuIdLeaves_%s)),\n"
    4853                    "    /*.enmUnknownCpuId  = */ CPUMUNKNOWNCPUID_%s,\n"
    4854                    "    /*.DefUnknownCpuId  = */ { %#010x, %#010x, %#010x, %#010x },\n"
    4855                    "    /*.fMsrMask         = */ %s,\n"
    4856                    "    /*.cMsrRanges       = */ ZERO_ALONE(RT_ELEMENTS(g_aMsrRanges_%s)),\n"
    4857                    "    /*.paMsrRanges      = */ NULL_ALONE(g_aMsrRanges_%s),\n"
    4858                    "};\n"
    4859                    "\n"
    4860                    "#endif /* !VBOX_CPUDB_%s_h */\n"
    4861                    "\n",
    4862                    pszCpuDesc,
    4863                    szNameC,
    4864                    pszName,
    4865                    pszCpuDesc,
    4866                    CPUMCpuVendorName(enmVendor),
    4867                    RTX86GetCpuFamily(uEax),
    4868                    RTX86GetCpuModel(uEax, enmVendor == CPUMCPUVENDOR_INTEL),
    4869                    RTX86GetCpuStepping(uEax),
    4870                    CPUMMicroarchName(enmMicroarch),
    4871                    vbCpuRepGuessScalableBusFrequencyName(),
    4872                    vbCpuRepGetPhysAddrWidth(),
    4873                    CPUMR3DeterminHostMxCsrMask(),
    4874                    szNameC,
    4875                    szNameC,
    4876                    CPUMR3CpuIdUnknownLeafMethodName(enmUnknownMethod),
    4877                    DefUnknown.uEax,
    4878                    DefUnknown.uEbx,
    4879                    DefUnknown.uEcx,
    4880                    DefUnknown.uEdx,
    4881                    szMsrMask,
    4882                    szNameC,
    4883                    szNameC,
    4884                    szNameC
    4885                    );
    4886 
    4887     return VINF_SUCCESS;
    4888 }
    4889 
    4890 
    4891135int main(int argc, char **argv)
    4892136{
     
    4900144    static const RTGETOPTDEF s_aOptions[] =
    4901145    {
     146#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
    4902147        { "--msrs-only", 'm', RTGETOPT_REQ_NOTHING },
    4903148        { "--msrs-dev",  'd', RTGETOPT_REQ_NOTHING },
    4904149        { "--no-msrs",   'n', RTGETOPT_REQ_NOTHING },
     150#endif
    4905151        { "--output",    'o', RTGETOPT_REQ_STRING  },
    4906152        { "--log",       'l', RTGETOPT_REQ_STRING  },
     
    4912158    {
    4913159        kCpuReportOp_Normal,
     160#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
    4914161        kCpuReportOp_MsrsOnly,
    4915162        kCpuReportOp_MsrsHacking
     163#else
     164        kCpuReportOp_Dummy
     165#endif
    4916166    } enmOp = kCpuReportOp_Normal;
    4917167    g_pReportOut = NULL;
     
    4926176        switch (iOpt)
    4927177        {
     178#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
    4928179            case 'm':
    4929180                enmOp = kCpuReportOp_MsrsOnly;
     
    4937188                g_fNoMsrs = true;
    4938189                break;
     190#endif
    4939191
    4940192            case 'o':
     
    4947199
    4948200            case 'h':
    4949                 RTPrintf("Usage: VBoxCpuReport [-m|--msrs-only] [-d|--msrs-dev] [-n|--no-msrs] [-h|--help] [-V|--version] [-o filename.h] [-l debug.log]\n");
     201            {
     202#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
     203                const char * const pszArchOps = "[-m|--msrs-only] [-d|--msrs-dev] [-n|--no-msrs] ";
     204#else
     205                const char * const pszArchOps = "";
     206#endif
     207                RTPrintf("Usage: VBoxCpuReport %s[-h|--help] [-V|--version] [-o filename.h] [-l debug.log]\n",
     208                         pszArchOps);
    4950209                RTPrintf("Internal tool for gathering information to the VMM CPU database.\n");
    4951210                return RTEXITCODE_SUCCESS;
     211            }
    4952212            case 'V':
    4953213                RTPrintf("%sr%s\n", RTBldCfgVersion(), RTBldCfgRevisionStr());
     
    5008268            rc = produceCpuReport();
    5009269            break;
     270#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
    5010271        case kCpuReportOp_MsrsOnly:
    5011272        case kCpuReportOp_MsrsHacking:
    5012273            rc = probeMsrs(enmOp == kCpuReportOp_MsrsHacking, NULL, NULL, NULL, 0);
    5013274            break;
     275#else
     276        case kCpuReportOp_Dummy:
     277            break;
     278#endif
    5014279    }
    5015280
  • trunk/src/VBox/VMM/tools/VBoxCpuReport.h

    r106061 r109008  
    3333
    3434#include <VBox/sup.h>
     35#include <VBox/vmm/cpum.h>
     36#include <iprt/stream.h>
    3537
    3638RT_C_DECLS_BEGIN
     
    5355typedef VBCPUREPMSRACCESSORS *PVBCPUREPMSRACCESSORS;
    5456
     57extern PRTSTREAM        g_pReportOut;
     58extern PRTSTREAM        g_pDebugOut;
     59extern CPUMCPUVENDOR    g_enmVendor;
     60extern CPUMMICROARCH    g_enmMicroarch;
     61#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
     62extern bool             g_fNoMsrs;
     63#endif
     64
    5565extern void vbCpuRepDebug(const char *pszMsg, ...);
    5666extern void vbCpuRepPrintf(const char *pszMsg, ...);
     67extern const char *vbCpuVendorToString(CPUMCPUVENDOR enmCpuVendor);
     68
     69extern int  produceCpuReport(void); /* arch specific */
     70
     71#if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
     72extern int  probeMsrs(bool fHacking, const char *pszNameC, const char *pszCpuDesc, char *pszMsrMask, size_t cbMsrMask);
    5773extern int  VbCpuRepMsrProberInitSupDrv(PVBCPUREPMSRACCESSORS pMsrAccessors);
    5874extern int  VbCpuRepMsrProberInitPlatform(PVBCPUREPMSRACCESSORS pMsrAccessors);
     75#endif
    5976
    6077RT_C_DECLS_END
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