Changeset 109008 in vbox
- Timestamp:
- Apr 16, 2025 8:59:36 PM (4 days ago)
- svn:sync-xref-src-repo-rev:
- 168536
- Location:
- trunk
- Files:
-
- 1 added
- 39 edited
- 3 copied
- 1 moved
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/vmm/cpum-armv8.h
r107929 r109008 166 166 167 167 168 /**169 * CPU database entry.170 */171 typedef struct CPUMDBENTRY172 {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 to192 * 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 200 168 /** @name Changed flags. 201 169 * These flags are used to keep track of which important register that -
trunk/include/VBox/vmm/cpum-x86-amd64.h
r108968 r109008 86 86 CPUMCPUIDFEATURE_32BIT_HACK = 0x7fffffff 87 87 } CPUMCPUIDFEATURE; 88 89 90 /**91 * Method used to deal with unknown CPUID leaves.92 * @remarks Used in patch code.93 */94 typedef enum CPUMUNKNOWNCPUID95 {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 = 0x7fffffff112 } 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 CPUMCPUID121 {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;131 88 132 89 … … 702 659 703 660 704 /**705 * CPU database entry.706 */707 typedef struct CPUMDBENTRY708 {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 to728 * 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 in742 * 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::fFlags754 * @{ */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 762 661 #ifndef VBOX_FOR_DTRACE_LIB 763 662 -
trunk/include/VBox/vmm/cpum.h
r108968 r109008 1570 1570 1571 1571 1572 /** 1573 * Method used to deal with unknown CPUID leaves on x86. 1574 */ 1575 typedef 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. */ 1595 typedef CPUMUNKNOWNCPUID *PCPUMUNKNOWNCPUID; 1596 1597 1598 /** 1599 * The register set returned by an x86 CPUID operation. 1600 */ 1601 typedef 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. */ 1609 typedef CPUMCPUID *PCPUMCPUID; 1610 /** Pointer to a const CPUID leaf. */ 1611 typedef const CPUMCPUID *PCCPUMCPUID; 1612 1572 1613 1573 1614 /** … … 1614 1655 1615 1656 1657 /** For identifying the extended database entry type. */ 1658 typedef 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 */ 1670 typedef 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. */ 1686 typedef 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 */ 1699 typedef 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. */ 1734 typedef CPUMDBENTRYX86 const *PCCPUMDBENTRYX86; 1735 1736 1737 /** 1738 * CPU database entry for ARM. 1739 */ 1740 typedef 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. */ 1760 typedef CPUMDBENTRYARM const *PCCPUMDBENTRYARM; 1761 1762 1616 1763 /* 1617 1764 * Include the target specific header. -
trunk/src/VBox/Main/include/SystemPropertiesImpl.h
r106061 r109008 36 36 #include "MediumFormatImpl.h" 37 37 #include "SystemPropertiesWrap.h" 38 39 #include <VBox/vmm/cpum.h> /* for CPUMDBENTRYTYPE */ 38 40 39 41 class CPUProfile; … … 168 170 HRESULT i_setDefaultFrontend(const com::Utf8Str &aDefaultFrontend); 169 171 172 HRESULT i_loadCPUProfilesFromVMM(const char *a_pszVMM, CPUMDBENTRYTYPE a_enmEntryType); 173 170 174 VirtualBox * const mParent; 171 175 … … 176 180 ComObjPtr<PlatformProperties> const m_platformProperties; /**< The host's platform properties. */ 177 181 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. */ 178 183 CPUProfileList_T m_llCPUProfiles; /**< List of loaded CPU profiles. */ 179 184 -
trunk/src/VBox/Main/src-server/CPUProfileImpl.cpp
r106061 r109008 68 68 69 69 /* 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; 80 86 81 87 HRESULT hrc = m_strName.assignEx(a_pDbEntry->pszName); … … 117 123 { 118 124 if ( m_enmArchitecture == a_enmArchitecture 119 || m_enmArchitecture == a_enmSecondaryArch) 125 || m_enmArchitecture == a_enmSecondaryArch 126 || a_enmArchitecture == CPUArchitecture_Any) 120 127 { 121 128 if (a_strNamePattern.isEmpty()) -
trunk/src/VBox/Main/src-server/SystemPropertiesImpl.cpp
r108641 r109008 65 65 , m(new settings::SystemProperties) 66 66 , m_fLoadedX86CPUProfiles(false) 67 , m_fLoadedArmCPUProfiles(false) 67 68 { 68 69 } … … 292 293 } 293 294 295 /** 296 * Helper for getCPUProfiles() that loads profiles from one VMM module. 297 */ 298 HRESULT 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 294 377 HRESULT SystemProperties::getCPUProfiles(CPUArchitecture_T aArchitecture, const com::Utf8Str &aNamePattern, 295 378 std::vector<ComPtr<ICPUProfile> > &aProfiles) … … 304 387 { 305 388 case CPUArchitecture_Any: 306 aArchitecture = CPUArchitecture_AMD64; 307 RT_FALL_THROUGH(); 389 fLoaded = m_fLoadedArmCPUProfiles && m_fLoadedX86CPUProfiles; 390 break; 391 308 392 case CPUArchitecture_AMD64: 309 393 enmSecondaryArch = CPUArchitecture_x86; … … 312 396 fLoaded = m_fLoadedX86CPUProfiles; 313 397 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 314 406 default: 315 407 return setError(E_INVALIDARG, tr("Invalid or unsupported architecture value: %d"), aArchitecture); … … 328 420 329 421 /* 330 * Translate the architecture to a VMM module handle.422 * Load AMD64 & X86 profiles from VBoxVMM.dll/so/dylib if requested and required. 331 423 */ 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) 334 429 { 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; 342 433 } 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) 346 442 { 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; 433 446 } 447 448 alockWrite.release(); 449 alock.acquire(); 434 450 } 435 451 if (SUCCEEDED(hrc)) -
trunk/src/VBox/VMM/Makefile.kmk
r108972 r109008 115 115 VMMR3/CPUMR3CpuId.cpp \ 116 116 VMMR3/CPUMR3Db.cpp \ 117 VMMR3/CPUMR3Msr-x86.cpp \ 117 118 VMMR3/CPUMDbg.cpp \ 118 119 VMMR3/DBGF.cpp \ … … 457 458 VMMAll/CPUMAllCpuId.cpp \ 458 459 VMMR3/CPUMR3CpuId-armv8.cpp \ 459 VMMR3/CPUMR3Db-armv8.cpp \ 460 VMMR3/CPUMR3Db.cpp \ 461 VMMR3/CPUMR3SysReg-armv8.cpp \ 460 462 VMMR3/DBGF.cpp \ 461 463 VMMR3/DBGFAddr.cpp \ … … 1120 1122 SSMStandalone_INCS = include 1121 1123 SSMStandalone_SOURCES = \ 1122 VMMR3/SSM.cpp \ 1123 VMMR3/CPUMR3Db.cpp 1124 VMMR3/SSM.cpp 1124 1125 endif # !VBOX_ONLY_BUILD 1125 1126 -
trunk/src/VBox/VMM/VMMR3/CPUMR3Db.cpp
r107854 r109008 5 5 6 6 /* 7 * Copyright (C) 2013-202 4Oracle and/or its affiliates.7 * Copyright (C) 2013-2025 Oracle and/or its affiliates. 8 8 * 9 9 * This file is part of VirtualBox base platform packages, as … … 42 42 #include <iprt/mem.h> 43 43 #include <iprt/string.h> 44 45 46 /********************************************************************************************************************************* 47 * Internal Functions * 48 *********************************************************************************************************************************/ 49 static int cpumDbPopulateInfoFromEntry(PCPUMINFO pInfo, PCCPUMDBENTRY pEntryCore, bool fHost); 44 50 45 51 … … 62 68 63 69 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 141 125 #endif 142 /** @} */143 144 #ifndef CPUM_DB_STANDALONE145 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 126 178 127 … … 191 140 static CPUMDBENTRY const * const g_apCpumDbEntries[] = 192 141 { 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 232 185 /** @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 */ 283 244 }; 284 245 … … 327 288 } 328 289 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)) 819 291 820 292 /** … … 934 406 } 935 407 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 */ 413 static 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 */ 522 static 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) 945 532 { 946 533 /* 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. 950 536 */ 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. Except976 for family, always match the closer with preference given to977 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 ( !pEntry992 || pEntry->uModel != uModel993 || pEntry->enmMicroarch != enmMicroarch994 || pEntry->uFamily != uFamily)995 pEntry = pCur;996 else if ( pCur->uStepping >= uStepping997 ? pCur->uStepping < pEntry->uStepping || pEntry->uStepping < uStepping998 : pCur->uStepping > pEntry->uStepping)999 pEntry = pCur;1000 }1001 else if ( !pEntry1002 || pEntry->enmMicroarch != enmMicroarch1003 || pEntry->uFamily != uFamily)1004 pEntry = pCur;1005 else if ( pCur->uModel >= uModel1006 ? pCur->uModel < pEntry->uModel || pEntry->uModel < uModel1007 : pCur->uModel > pEntry->uModel)1008 pEntry = pCur;1009 }1010 else if ( !pEntry1011 || pEntry->uFamily != uFamily)1012 pEntry = pCur;1013 /* Special march matching rules applies to intel family 06h. */1014 else if ( enmVendor == CPUMCPUVENDOR_INTEL1015 && uFamily == 61016 ? 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 first1021 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 else1033 {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 else1041 #else1042 pszName = g_apCpumDbEntries[0]->pszName; /* Just pick the first entry for non-x86 hosts. */1043 #endif1044 {1045 /*1046 * We're supposed to be emulating a specific CPU that is included in1047 * our CPU database. The CPUID tables needs to be copied onto the1048 * heap so the caller can modify them and so they can be freed like1049 * 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 537 pInfo->cCpuIdLeaves = pEntry->cCpuIdLeaves; 1064 538 if (pEntry->cCpuIdLeaves) … … 1080 554 1081 555 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) )); 1084 558 } 1085 559 … … 1098 572 while (cLeft-- > 0) 1099 573 { 1100 rc = cpumR3MsrRangesInsert(NULL /* pVM */, &paMsrs, &cMsrs, pCurMsr);574 int rc = cpumR3MsrRangesInsert(NULL /* pVM */, &paMsrs, &cMsrs, pCurMsr); 1101 575 if (RT_FAILURE(rc)) 1102 576 { … … 1111 585 pInfo->paMsrRangesR3 = paMsrs; 1112 586 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 1113 599 return VINF_SUCCESS; 1114 600 } 1115 601 1116 602 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++) 603 int 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")) 1174 620 { 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 1196 628 } 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.cpp 58652,70973 /branches/VBox-3.2/src/VBox/VMM/VMMR3/CPUMR3Db.cpp 66309,66318 /branches/VBox-4.0/src/VBox/VMM/VMMR3/CPUMR3Db.cpp 70873 /branches/VBox-4.1/src/VBox/VMM/VMMR3/CPUMR3Db.cpp 74233,78414,78691,81841,82127,85941,85944-85947,85949-85950,85953,86701,86728,87009 /branches/VBox-4.2/src/VBox/VMM/VMMR3/CPUMR3Db.cpp 86229-86230,86234,86529,91503-91504,91506-91508,91510,91514-91515,91521,108112,108114,108127 /branches/VBox-4.3/src/VBox/VMM/VMMR3/CPUMR3Db.cpp 89714,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.cpp 91223 /branches/VBox-5.0/src/VBox/VMM/VMMR3/CPUMR3Db.cpp 104938,104943,104950,104987-104988,104990,106453 /branches/VBox-5.1/src/VBox/VMM/VMMR3/CPUMR3Db.cpp 112367,116543,116550,116568,116573 /branches/VBox-5.2/src/VBox/VMM/VMMR3/CPUMR3Db.cpp 119536,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.cpp 130474-130475,130477,130479,131352 /branches/VBox-6.1/src/VBox/VMM/VMMR3/CPUMR3Db.cpp 141521,141567-141568,141588-141590,141592-141595,141652,141920,158257-158259 /branches/VBox-7.0/src/VBox/VMM/VMMR3/CPUMR3Db.cpp 156229,156768 /branches/aeichner/vbox-chromium-cleanup/src/VBox/VMM/VMMR3/CPUMR3Db.cpp 129818-129851,129853-129861,129871-129872,129876,129880,129882,130013-130015,130094-130095 /branches/andy/draganddrop/src/VBox/VMM/VMMR3/CPUMR3Db.cpp 90781-91268 /branches/andy/guestctrl20/src/VBox/VMM/VMMR3/CPUMR3Db.cpp 78916,78930 /branches/andy/pdmaudio/src/VBox/VMM/VMMR3/CPUMR3Db.cpp 94582,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.cpp 92692-94610 /branches/dsen/gui/src/VBox/VMM/VMMR3/CPUMR3Db.cpp 79076-79078,79089,79109-79110,79112-79113,79127-79130,79134,79141,79151,79155,79157-79159,79193,79197 /branches/dsen/gui2/src/VBox/VMM/VMMR3/CPUMR3Db.cpp 79224,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.cpp 79645-79692 /branches/dsen/gui4/src/VBox/VMM/VMMR3/CPUMR3Db.cpp 155183-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 43 43 #include <iprt/string.h> 44 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 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" 329 46 330 47 … … 816 533 } 817 534 818 #if defined(RT_ARCH_X86) || defined(RT_ARCH_AMD64)819 820 /**821 * Do we consider @a enmConsider a better match for @a enmTarget than822 * @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 than857 * @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_First883 || 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 heritage889 * - Core890 * - Atom891 *892 * Determin which of the three arguments are Atom marchs, because that's893 * 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 else928 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 getting948 * the CPUID bits from the real CPU and grabbing the closest matching949 * 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. Except976 for family, always match the closer with preference given to977 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 ( !pEntry992 || pEntry->uModel != uModel993 || pEntry->enmMicroarch != enmMicroarch994 || pEntry->uFamily != uFamily)995 pEntry = pCur;996 else if ( pCur->uStepping >= uStepping997 ? pCur->uStepping < pEntry->uStepping || pEntry->uStepping < uStepping998 : pCur->uStepping > pEntry->uStepping)999 pEntry = pCur;1000 }1001 else if ( !pEntry1002 || pEntry->enmMicroarch != enmMicroarch1003 || pEntry->uFamily != uFamily)1004 pEntry = pCur;1005 else if ( pCur->uModel >= uModel1006 ? pCur->uModel < pEntry->uModel || pEntry->uModel < uModel1007 : pCur->uModel > pEntry->uModel)1008 pEntry = pCur;1009 }1010 else if ( !pEntry1011 || pEntry->uFamily != uFamily)1012 pEntry = pCur;1013 /* Special march matching rules applies to intel family 06h. */1014 else if ( enmVendor == CPUMCPUVENDOR_INTEL1015 && uFamily == 61016 ? 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 first1021 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 else1033 {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 else1041 #else1042 pszName = g_apCpumDbEntries[0]->pszName; /* Just pick the first entry for non-x86 hosts. */1043 #endif1044 {1045 /*1046 * We're supposed to be emulating a specific CPU that is included in1047 * our CPU database. The CPUID tables needs to be copied onto the1048 * heap so the caller can modify them and so they can be freed like1049 * 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 else1075 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 535 1117 536 /** … … 1165 584 1166 585 1167 # 586 #ifdef VBOX_WITH_STATISTICS 1168 587 /* 1169 588 * Per range. … … 1195 614 STAMR3Register(pVM, &paRanges[i].cIgnoredBits, STAMTYPE_COUNTER, STAMVISIBILITY_USED, szName, STAMUNIT_OCCURENCES, "WRMSR w/ ignored bits"); 1196 615 } 1197 # 616 #endif /* VBOX_WITH_STATISTICS */ 1198 617 1199 618 return VINF_SUCCESS; 1200 619 } 1201 620 1202 #endif /* !CPUM_DB_STANDALONE */1203 -
Property svn:mergeinfo
set to (toggle deleted branches)
-
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.cpp 58652,70973 /branches/VBox-3.2/src/VBox/VMM/VMMR3/CPUMR3Db.cpp 66309,66318 /branches/VBox-4.0/src/VBox/VMM/VMMR3/CPUMR3Db.cpp 70873 /branches/VBox-4.1/src/VBox/VMM/VMMR3/CPUMR3Db.cpp 74233,78414,78691,81841,82127,85941,85944-85947,85949-85950,85953,86701,86728,87009 /branches/VBox-4.2/src/VBox/VMM/VMMR3/CPUMR3Db.cpp 86229-86230,86234,86529,91503-91504,91506-91508,91510,91514-91515,91521,108112,108114,108127 /branches/VBox-4.3/src/VBox/VMM/VMMR3/CPUMR3Db.cpp 89714,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.cpp 91223 /branches/VBox-5.0/src/VBox/VMM/VMMR3/CPUMR3Db.cpp 104938,104943,104950,104987-104988,104990,106453 /branches/VBox-5.1/src/VBox/VMM/VMMR3/CPUMR3Db.cpp 112367,116543,116550,116568,116573 /branches/VBox-5.2/src/VBox/VMM/VMMR3/CPUMR3Db.cpp 119536,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.cpp 130474-130475,130477,130479,131352 /branches/VBox-6.1/src/VBox/VMM/VMMR3/CPUMR3Db.cpp 141521,141567-141568,141588-141590,141592-141595,141652,141920,158257-158259 /branches/VBox-7.0/src/VBox/VMM/VMMR3/CPUMR3Db.cpp 156229,156768 /branches/aeichner/vbox-chromium-cleanup/src/VBox/VMM/VMMR3/CPUMR3Db.cpp 129818-129851,129853-129861,129871-129872,129876,129880,129882,130013-130015,130094-130095 /branches/andy/draganddrop/src/VBox/VMM/VMMR3/CPUMR3Db.cpp 90781-91268 /branches/andy/guestctrl20/src/VBox/VMM/VMMR3/CPUMR3Db.cpp 78916,78930 /branches/andy/pdmaudio/src/VBox/VMM/VMMR3/CPUMR3Db.cpp 94582,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.cpp 92692-94610 /branches/dsen/gui/src/VBox/VMM/VMMR3/CPUMR3Db.cpp 79076-79078,79089,79109-79110,79112-79113,79127-79130,79134,79141,79151,79155,79157-79159,79193,79197 /branches/dsen/gui2/src/VBox/VMM/VMMR3/CPUMR3Db.cpp 79224,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.cpp 79645-79692 /branches/dsen/gui4/src/VBox/VMM/VMMR3/CPUMR3Db.cpp 155183-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 1 1 /* $Id$ */ 2 2 /** @file 3 * CPUM - CPU database part.3 * CPUM - x86 MSR macros. 4 4 */ 5 5 … … 27 27 28 28 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 41 33 #endif 42 #include <iprt/mem.h>43 #include <iprt/string.h>44 45 46 /*********************************************************************************************************************************47 * Defined Constants And Macros *48 *********************************************************************************************************************************/49 /** @def NULL_ALONE50 * For eliminating an unnecessary data dependency in standalone builds (for51 * VBoxSVC). */52 /** @def ZERO_ALONE53 * For eliminating an unnecessary data size dependency in standalone builds (for54 * VBoxSVC). */55 #ifndef CPUM_DB_STANDALONE56 # define NULL_ALONE(a_aTable) a_aTable57 # define ZERO_ALONE(a_cTable) a_cTable58 #else59 # define NULL_ALONE(a_aTable) NULL60 # define ZERO_ALONE(a_cTable) 061 #endif62 63 34 64 35 /** @name Short macros for the MSR range entries. … … 142 113 /** @} */ 143 114 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 */ -
Property svn:mergeinfo
set to (toggle deleted branches)
-
trunk/src/VBox/VMM/VMMR3/CPUMR3SysReg-armv8.cpp
r109007 r109008 1 1 /* $Id$ */ 2 2 /** @file 3 * CPUM - CPU database part - ARMv8 specifics.3 * CPUM - ARMv8 System Registers Management. 4 4 */ 5 5 6 6 /* 7 * Copyright (C) 2023-202 4Oracle and/or its affiliates.7 * Copyright (C) 2023-2025 Oracle and/or its affiliates. 8 8 * 9 9 * This file is part of VirtualBox base platform packages, as … … 34 34 #include "CPUMInternal-armv8.h" 35 35 #include <VBox/vmm/vm.h> 36 #include <VBox/vmm/mm.h>37 36 38 37 #include <iprt/errcore.h> … … 40 39 #include <iprt/mem.h> 41 40 #include <iprt/string.h> 42 43 44 /*********************************************************************************************************************************45 * Defined Constants And Macros *46 *********************************************************************************************************************************/47 /** @def NULL_ALONE48 * For eliminating an unnecessary data dependency in standalone builds (for49 * VBoxSVC). */50 /** @def ZERO_ALONE51 * For eliminating an unnecessary data size dependency in standalone builds (for52 * VBoxSVC). */53 #ifndef CPUM_DB_STANDALONE54 # define NULL_ALONE(a_aTable) a_aTable55 # define ZERO_ALONE(a_cTable) a_cTable56 #else57 # define NULL_ALONE(a_aTable) NULL58 # define ZERO_ALONE(a_cTable) 059 #endif60 61 62 #ifndef CPUM_DB_STANDALONE63 64 /**65 * The database entries.66 *67 * 1. The first entry is special. It is the fallback for unknown68 * processors. Thus, it better be pretty representative.69 *70 * 2. The first entry for a CPU vendor is likewise important as it is71 * the default entry for that vendor.72 *73 * Generally we put the most recent CPUs first, since these tend to have the74 * most complicated and backwards compatible list of MSRs.75 */76 static CPUMDBENTRY const * const g_apCpumDbEntries[] =77 {78 NULL79 };80 81 82 /**83 * Returns the number of entries in the CPU database.84 *85 * @returns Number of entries.86 * @sa PFNCPUMDBGETENTRIES87 */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 PFNCPUMDBGETENTRYBYINDEX100 */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 PFNCPUMDBGETENTRYBYNAME114 */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 125 41 126 42 … … 395 311 } 396 312 397 #endif /* !CPUM_DB_STANDALONE */398 -
trunk/src/VBox/VMM/VMMR3/cpus/AMD_Athlon_64_3200.h
r106061 r109008 209 209 * Database entry for AMD Athlon(tm) 64 Processor 3200+. 210 210 */ 211 static CPUMDBENTRY const g_Entry_AMD_Athlon_64_3200 =211 static CPUMDBENTRYX86 const g_Entry_AMD_Athlon_64_3200 = 212 212 { 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 }, 216 221 /*.uFamily = */ 15, 217 222 /*.uModel = */ 4, 218 223 /*.uStepping = */ 8, 219 /*.enmMicroarch = */ kCpumMicroarch_AMD_K8_130nm,220 224 /*.uScalableBusFreq = */ CPUM_SBUSFREQ_UNKNOWN, 221 /*.fFlags = */ 0,222 225 /*.cMaxPhysAddrWidth= */ 40, 223 226 /*.fMxCsrMask = */ 0xffff, ///< @todo check. -
trunk/src/VBox/VMM/VMMR3/cpus/AMD_Athlon_64_X2_Dual_Core_4200.h
r106061 r109008 217 217 * Database entry for AMD Athlon(tm) 64 X2 Dual Core Processor 4200+. 218 218 */ 219 static CPUMDBENTRY const g_Entry_AMD_Athlon_64_X2_Dual_Core_4200 =219 static CPUMDBENTRYX86 const g_Entry_AMD_Athlon_64_X2_Dual_Core_4200 = 220 220 { 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 }, 224 229 /*.uFamily = */ 15, 225 230 /*.uModel = */ 75, 226 231 /*.uStepping = */ 2, 227 /*.enmMicroarch = */ kCpumMicroarch_AMD_K8_90nm_AMDV,228 232 /*.uScalableBusFreq = */ CPUM_SBUSFREQ_UNKNOWN, 229 /*.fFlags = */ 0,230 233 /*.cMaxPhysAddrWidth= */ 40, 231 234 /*.fMxCsrMask = */ 0xffff, -
trunk/src/VBox/VMM/VMMR3/cpus/AMD_FX_8150_Eight_Core.h
r106061 r109008 368 368 * Database entry for AMD FX(tm)-8150 Eight-Core Processor. 369 369 */ 370 static CPUMDBENTRY const g_Entry_AMD_FX_8150_Eight_Core =370 static CPUMDBENTRYX86 const g_Entry_AMD_FX_8150_Eight_Core = 371 371 { 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 }, 375 380 /*.uFamily = */ 21, 376 381 /*.uModel = */ 1, 377 382 /*.uStepping = */ 2, 378 /*.enmMicroarch = */ kCpumMicroarch_AMD_15h_Bulldozer,379 383 /*.uScalableBusFreq = */ CPUM_SBUSFREQ_UNKNOWN, 380 /*.fFlags = */ 0,381 384 /*.cMaxPhysAddrWidth= */ 48, 382 385 /*.fMxCsrMask = */ 0x2ffff, -
trunk/src/VBox/VMM/VMMR3/cpus/AMD_Phenom_II_X6_1100T.h
r106061 r109008 257 257 * Database entry for AMD Phenom(tm) II X6 1100T Processor. 258 258 */ 259 static CPUMDBENTRY const g_Entry_AMD_Phenom_II_X6_1100T =259 static CPUMDBENTRYX86 const g_Entry_AMD_Phenom_II_X6_1100T = 260 260 { 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 }, 264 269 /*.uFamily = */ 16, 265 270 /*.uModel = */ 10, 266 271 /*.uStepping = */ 0, 267 /*.enmMicroarch = */ kCpumMicroarch_AMD_K10,268 272 /*.uScalableBusFreq = */ CPUM_SBUSFREQ_UNKNOWN, 269 /*.fFlags = */ 0,270 273 /*.cMaxPhysAddrWidth= */ 48, 271 274 /*.fMxCsrMask = */ 0x2ffff, -
trunk/src/VBox/VMM/VMMR3/cpus/AMD_Ryzen_7_1800X_Eight_Core.h
r106061 r109008 5209 5209 * Database entry for AMD Ryzen 7 1800X Eight-Core Processor. 5210 5210 */ 5211 static CPUMDBENTRY const g_Entry_AMD_Ryzen_7_1800X_Eight_Core =5211 static CPUMDBENTRYX86 const g_Entry_AMD_Ryzen_7_1800X_Eight_Core = 5212 5212 { 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 }, 5216 5221 /*.uFamily = */ 23, 5217 5222 /*.uModel = */ 1, 5218 5223 /*.uStepping = */ 1, 5219 /*.enmMicroarch = */ kCpumMicroarch_AMD_Zen_Ryzen,5220 5224 /*.uScalableBusFreq = */ CPUM_SBUSFREQ_UNKNOWN, 5221 /*.fFlags = */ 0,5222 5225 /*.cMaxPhysAddrWidth= */ 48, 5223 5226 /*.fMxCsrMask = */ 0x0002ffff, -
trunk/src/VBox/VMM/VMMR3/cpus/Hygon_C86_7185_32_core.h
r106061 r109008 5209 5209 * Database entry for Hygon C86 7185 32-core Processor. 5210 5210 */ 5211 static CPUMDBENTRY const g_Entry_Hygon_C86_7185_32_core =5211 static CPUMDBENTRYX86 const g_Entry_Hygon_C86_7185_32_core = 5212 5212 { 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 }, 5216 5221 /*.uFamily = */ 24, 5217 5222 /*.uModel = */ 0, 5218 5223 /*.uStepping = */ 1, 5219 /*.enmMicroarch = */ kCpumMicroarch_Hygon_Dhyana,5220 5224 /*.uScalableBusFreq = */ CPUM_SBUSFREQ_UNKNOWN, 5221 /*.fFlags = */ 0,5222 5225 /*.cMaxPhysAddrWidth= */ 48, 5223 5226 /*.fMxCsrMask = */ 0x0002ffff, -
trunk/src/VBox/VMM/VMMR3/cpus/Intel_80186.h
r106061 r109008 60 60 * Database entry for Intel(R) 80186. 61 61 */ 62 static CPUMDBENTRY const g_Entry_Intel_80186 =62 static CPUMDBENTRYX86 const g_Entry_Intel_80186 = 63 63 { 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 }, 67 72 /*.uFamily = */ 2, 68 73 /*.uModel = */ 0, 69 74 /*.uStepping = */ 0, 70 /*.enmMicroarch = */ kCpumMicroarch_Intel_80186,71 75 /*.uScalableBusFreq = */ CPUM_SBUSFREQ_UNKNOWN, 72 /*.fFlags = */ CPUMDB_F_EXECUTE_ALL_IN_IEM,73 76 /*.cMaxPhysAddrWidth= */ 20, 74 77 /*.fMxCsrMask = */ 0, -
trunk/src/VBox/VMM/VMMR3/cpus/Intel_80286.h
r106061 r109008 60 60 * Database entry for Intel(R) 80286. 61 61 */ 62 static CPUMDBENTRY const g_Entry_Intel_80286 =62 static CPUMDBENTRYX86 const g_Entry_Intel_80286 = 63 63 { 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 }, 67 72 /*.uFamily = */ 2, 68 73 /*.uModel = */ 0, 69 74 /*.uStepping = */ 0, 70 /*.enmMicroarch = */ kCpumMicroarch_Intel_80286,71 75 /*.uScalableBusFreq = */ CPUM_SBUSFREQ_UNKNOWN, 72 /*.fFlags = */ CPUMDB_F_EXECUTE_ALL_IN_IEM,73 76 /*.cMaxPhysAddrWidth= */ 24, 74 77 /*.fMxCsrMask = */ 0, -
trunk/src/VBox/VMM/VMMR3/cpus/Intel_80386.h
r106061 r109008 60 60 * Database entry for Intel(R) 80386. 61 61 */ 62 static CPUMDBENTRY const g_Entry_Intel_80386 =62 static CPUMDBENTRYX86 const g_Entry_Intel_80386 = 63 63 { 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 }, 67 72 /*.uFamily = */ 3, 68 73 /*.uModel = */ 0, 69 74 /*.uStepping = */ 0, 70 /*.enmMicroarch = */ kCpumMicroarch_Intel_80386,71 75 /*.uScalableBusFreq = */ CPUM_SBUSFREQ_UNKNOWN, 72 /*.fFlags = */ CPUMDB_F_EXECUTE_ALL_IN_IEM,73 76 /*.cMaxPhysAddrWidth= */ 24, 74 77 /*.fMxCsrMask = */ 0, -
trunk/src/VBox/VMM/VMMR3/cpus/Intel_80486.h
r106061 r109008 58 58 * Database entry for Intel(R) 80486. 59 59 */ 60 static CPUMDBENTRY const g_Entry_Intel_80486 =60 static CPUMDBENTRYX86 const g_Entry_Intel_80486 = 61 61 { 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 }, 65 70 /*.uFamily = */ 4, 66 71 /*.uModel = */ 3, 67 72 /*.uStepping = */ 0, 68 /*.enmMicroarch = */ kCpumMicroarch_Intel_80486,69 73 /*.uScalableBusFreq = */ CPUM_SBUSFREQ_UNKNOWN, 70 /*.fFlags = */ 0,71 74 /*.cMaxPhysAddrWidth= */ 32, 72 75 /*.fMxCsrMask = */ 0, -
trunk/src/VBox/VMM/VMMR3/cpus/Intel_8086.h
r106061 r109008 60 60 * Database entry for Intel(R) 8086. 61 61 */ 62 static CPUMDBENTRY const g_Entry_Intel_8086 =62 static CPUMDBENTRYX86 const g_Entry_Intel_8086 = 63 63 { 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 }, 67 72 /*.uFamily = */ 2, 68 73 /*.uModel = */ 0, 69 74 /*.uStepping = */ 0, 70 /*.enmMicroarch = */ kCpumMicroarch_Intel_8086,71 75 /*.uScalableBusFreq = */ CPUM_SBUSFREQ_UNKNOWN, 72 /*.fFlags = */ CPUMDB_F_EXECUTE_ALL_IN_IEM,73 76 /*.cMaxPhysAddrWidth= */ 20, 74 77 /*.fMxCsrMask = */ 0, -
trunk/src/VBox/VMM/VMMR3/cpus/Intel_Atom_330_1_60GHz.h
r106061 r109008 195 195 * Database entry for Intel(R) Atom(TM) CPU 330 @ 1.60GHz. 196 196 */ 197 static CPUMDBENTRY const g_Entry_Intel_Atom_330_1_60GHz =197 static CPUMDBENTRYX86 const g_Entry_Intel_Atom_330_1_60GHz = 198 198 { 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 }, 202 207 /*.uFamily = */ 6, 203 208 /*.uModel = */ 28, 204 209 /*.uStepping = */ 2, 205 /*.enmMicroarch = */ kCpumMicroarch_Intel_Atom_Bonnell,206 210 /*.uScalableBusFreq = */ CPUM_SBUSFREQ_133MHZ, 207 /*.fFlags = */ 0,208 211 /*.cMaxPhysAddrWidth= */ 32, 209 212 /*.fMxCsrMask = */ 0xffff, -
trunk/src/VBox/VMM/VMMR3/cpus/Intel_Core2_T7600_2_33GHz.h
r106061 r109008 209 209 * Database entry for Intel(R) Core(TM)2 CPU T7600 @ 2.33GHz. 210 210 */ 211 static CPUMDBENTRY const g_Entry_Intel_Core2_T7600_2_33GHz =211 static CPUMDBENTRYX86 const g_Entry_Intel_Core2_T7600_2_33GHz = 212 212 { 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 }, 216 221 /*.uFamily = */ 6, 217 222 /*.uModel = */ 15, 218 223 /*.uStepping = */ 6, 219 /*.enmMicroarch = */ kCpumMicroarch_Intel_Core2_Merom,220 224 /*.uScalableBusFreq = */ CPUM_SBUSFREQ_167MHZ, 221 /*.fFlags = */ 0,222 225 /*.cMaxPhysAddrWidth= */ 36, 223 226 /*.fMxCsrMask = */ 0x0000ffff, -
trunk/src/VBox/VMM/VMMR3/cpus/Intel_Core2_X6800_2_93GHz.h
r106061 r109008 247 247 * Database entry for Intel(R) Core(TM)2 CPU X6800 @ 2.93GHz. 248 248 */ 249 static CPUMDBENTRY const g_Entry_Intel_Core2_X6800_2_93GHz =249 static CPUMDBENTRYX86 const g_Entry_Intel_Core2_X6800_2_93GHz = 250 250 { 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 }, 254 259 /*.uFamily = */ 6, 255 260 /*.uModel = */ 15, 256 261 /*.uStepping = */ 6, 257 /*.enmMicroarch = */ kCpumMicroarch_Intel_Core2_Merom,258 262 /*.uScalableBusFreq = */ CPUM_SBUSFREQ_267MHZ, 259 /*.fFlags = */ 0,260 263 /*.cMaxPhysAddrWidth= */ 36, 261 264 /*.fMxCsrMask = */ 0x0000ffff, -
trunk/src/VBox/VMM/VMMR3/cpus/Intel_Core_Duo_T2600_2_16GHz.h
r106061 r109008 209 209 * Database entry for Intel(R) Core(TM) Duo CPU T2600 @ 2.16GHz. 210 210 */ 211 static CPUMDBENTRY const g_Entry_Intel_Core_Duo_T2600_2_16GHz =211 static CPUMDBENTRYX86 const g_Entry_Intel_Core_Duo_T2600_2_16GHz = 212 212 { 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 }, 217 222 /*.uFamily = */ 6, 218 223 /*.uModel = */ 14, 219 224 /*.uStepping = */ 8, 220 /*.enmMicroarch = */ kCpumMicroarch_Intel_Core_Yonah,221 225 /*.uScalableBusFreq = */ CPUM_SBUSFREQ_167MHZ, 222 /*.fFlags = */ 0,223 226 /*.cMaxPhysAddrWidth= */ 32, 224 227 /*.fMxCsrMask = */ 0x0000ffff, -
trunk/src/VBox/VMM/VMMR3/cpus/Intel_Core_i5_3570.h
r106061 r109008 324 324 * Database entry for Intel(R) Core(TM) i5-3570 CPU @ 3.40GHz. 325 325 */ 326 static CPUMDBENTRY const g_Entry_Intel_Core_i5_3570 =326 static CPUMDBENTRYX86 const g_Entry_Intel_Core_i5_3570 = 327 327 { 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 }, 331 336 /*.uFamily = */ 6, 332 337 /*.uModel = */ 58, 333 338 /*.uStepping = */ 9, 334 /*.enmMicroarch = */ kCpumMicroarch_Intel_Core7_IvyBridge,335 339 /*.uScalableBusFreq = */ CPUM_SBUSFREQ_100MHZ, 336 /*.fFlags = */ 0,337 340 /*.cMaxPhysAddrWidth= */ 36, 338 341 /*.fMxCsrMask = */ 0xffff, -
trunk/src/VBox/VMM/VMMR3/cpus/Intel_Core_i7_2635QM.h
r106061 r109008 317 317 * Database entry for Intel(R) Core(TM) i7-2635QM CPU @ 2.00GHz. 318 318 */ 319 static CPUMDBENTRY const g_Entry_Intel_Core_i7_2635QM =319 static CPUMDBENTRYX86 const g_Entry_Intel_Core_i7_2635QM = 320 320 { 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 }, 324 329 /*.uFamily = */ 6, 325 330 /*.uModel = */ 42, 326 331 /*.uStepping = */ 7, 327 /*.enmMicroarch = */ kCpumMicroarch_Intel_Core7_SandyBridge,328 332 /*.uScalableBusFreq = */ CPUM_SBUSFREQ_100MHZ, 329 /*.fFlags = */ 0,330 333 /*.cMaxPhysAddrWidth= */ 36, 331 334 /*.fMxCsrMask = */ 0xffff, -
trunk/src/VBox/VMM/VMMR3/cpus/Intel_Core_i7_3820QM.h
r106061 r109008 366 366 * Database entry for Intel(R) Core(TM) i7-3820QM CPU @ 2.70GHz. 367 367 */ 368 static CPUMDBENTRY const g_Entry_Intel_Core_i7_3820QM =368 static CPUMDBENTRYX86 const g_Entry_Intel_Core_i7_3820QM = 369 369 { 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 }, 373 378 /*.uFamily = */ 6, 374 379 /*.uModel = */ 58, 375 380 /*.uStepping = */ 9, 376 /*.enmMicroarch = */ kCpumMicroarch_Intel_Core7_IvyBridge,377 381 /*.uScalableBusFreq = */ CPUM_SBUSFREQ_UNKNOWN, 378 /*.fFlags = */ 0,379 382 /*.cMaxPhysAddrWidth= */ 36, 380 383 /*.paCpuIdLeaves = */ NULL_ALONE(g_aCpuIdLeaves_Intel_Core_i7_3820QM), -
trunk/src/VBox/VMM/VMMR3/cpus/Intel_Core_i7_3960X.h
r106061 r109008 354 354 * Database entry for Intel(R) Core(TM) i7-3960X CPU @ 3.30GHz. 355 355 */ 356 static CPUMDBENTRY const g_Entry_Intel_Core_i7_3960X =356 static CPUMDBENTRYX86 const g_Entry_Intel_Core_i7_3960X = 357 357 { 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 }, 361 366 /*.uFamily = */ 6, 362 367 /*.uModel = */ 45, 363 368 /*.uStepping = */ 6, 364 /*.enmMicroarch = */ kCpumMicroarch_Intel_Core7_SandyBridge,365 369 /*.uScalableBusFreq = */ CPUM_SBUSFREQ_100MHZ, 366 /*.fFlags = */ 0,367 370 /*.cMaxPhysAddrWidth= */ 46, 368 371 /*.fMxCsrMask = */ 0xffff, -
trunk/src/VBox/VMM/VMMR3/cpus/Intel_Core_i7_5600U.h
r106061 r109008 353 353 * Database entry for Intel(R) Core(TM) i7-5600U CPU @ 2.60GHz. 354 354 */ 355 static CPUMDBENTRY const g_Entry_Intel_Core_i7_5600U =355 static CPUMDBENTRYX86 const g_Entry_Intel_Core_i7_5600U = 356 356 { 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 }, 360 365 /*.uFamily = */ 6, 361 366 /*.uModel = */ 61, 362 367 /*.uStepping = */ 4, 363 /*.enmMicroarch = */ kCpumMicroarch_Intel_Core7_Broadwell,364 368 /*.uScalableBusFreq = */ CPUM_SBUSFREQ_100MHZ, 365 /*.fFlags = */ 0,366 369 /*.cMaxPhysAddrWidth= */ 39, 367 370 /*.fMxCsrMask = */ 0xffff, -
trunk/src/VBox/VMM/VMMR3/cpus/Intel_Core_i7_6700K.h
r106061 r109008 495 495 * Database entry for Intel(R) Core(TM) i7-6700K CPU @ 4.00GHz. 496 496 */ 497 static CPUMDBENTRY const g_Entry_Intel_Core_i7_6700K =497 static CPUMDBENTRYX86 const g_Entry_Intel_Core_i7_6700K = 498 498 { 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 }, 502 507 /*.uFamily = */ 6, 503 508 /*.uModel = */ 94, 504 509 /*.uStepping = */ 3, 505 /*.enmMicroarch = */ kCpumMicroarch_Intel_Core7_Skylake,506 510 /*.uScalableBusFreq = */ CPUM_SBUSFREQ_100MHZ, 507 /*.fFlags = */ 0,508 511 /*.cMaxPhysAddrWidth= */ 39, 509 512 /*.fMxCsrMask = */ 0xffff, -
trunk/src/VBox/VMM/VMMR3/cpus/Intel_Pentium_4_3_00GHz.h
r106061 r109008 262 262 * Database entry for Intel(R) Pentium(R) 4 CPU 3.00GHz. 263 263 */ 264 static CPUMDBENTRY const g_Entry_Intel_Pentium_4_3_00GHz =264 static CPUMDBENTRYX86 const g_Entry_Intel_Pentium_4_3_00GHz = 265 265 { 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 }, 269 274 /*.uFamily = */ 15, 270 275 /*.uModel = */ 4, 271 276 /*.uStepping = */ 3, 272 /*.enmMicroarch = */ kCpumMicroarch_Intel_NB_Prescott2M,273 277 /*.uScalableBusFreq = */ CPUM_SBUSFREQ_UNKNOWN, 274 /*.fFlags = */ 0,275 278 /*.cMaxPhysAddrWidth= */ 36, 276 279 /*.fMxCsrMask = */ 0xffff, -
trunk/src/VBox/VMM/VMMR3/cpus/Intel_Pentium_M_processor_2_00GHz.h
r106061 r109008 201 201 * Database entry for Intel(R) Pentium(R) M processor 2.00GHz. 202 202 */ 203 static CPUMDBENTRY const g_Entry_Intel_Pentium_M_processor_2_00GHz =203 static CPUMDBENTRYX86 const g_Entry_Intel_Pentium_M_processor_2_00GHz = 204 204 { 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 }, 208 213 /*.uFamily = */ 6, 209 214 /*.uModel = */ 13, 210 215 /*.uStepping = */ 6, 211 /*.enmMicroarch = */ kCpumMicroarch_Intel_P6_M_Dothan,212 216 /*.uScalableBusFreq = */ CPUM_SBUSFREQ_UNKNOWN, 213 /*.fFlags = */ 0,214 217 /*.cMaxPhysAddrWidth= */ 32, 215 218 /*.fMxCsrMask = */ 0xffbf, ///< @todo check this -
trunk/src/VBox/VMM/VMMR3/cpus/Intel_Pentium_N3530_2_16GHz.h
r106061 r109008 250 250 * Database entry for Intel(R) Pentium(R) CPU N3530 @ 2.16GHz. 251 251 */ 252 static CPUMDBENTRY const g_Entry_Intel_Pentium_N3530_2_16GHz =252 static CPUMDBENTRYX86 const g_Entry_Intel_Pentium_N3530_2_16GHz = 253 253 { 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 }, 257 262 /*.uFamily = */ 6, 258 263 /*.uModel = */ 55, 259 264 /*.uStepping = */ 8, 260 /*.enmMicroarch = */ kCpumMicroarch_Intel_Atom_Silvermont,261 265 /*.uScalableBusFreq = */ CPUM_SBUSFREQ_267MHZ, 262 /*.fFlags = */ 0,263 266 /*.cMaxPhysAddrWidth= */ 36, 264 267 /*.fMxCsrMask = */ 0xffff, -
trunk/src/VBox/VMM/VMMR3/cpus/Intel_Xeon_X5482_3_20GHz.h
r106061 r109008 233 233 * Database entry for Intel(R) Xeon(R) CPU X5482 @ 3.20GHz. 234 234 */ 235 static CPUMDBENTRY const g_Entry_Intel_Xeon_X5482_3_20GHz =235 static CPUMDBENTRYX86 const g_Entry_Intel_Xeon_X5482_3_20GHz = 236 236 { 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 }, 240 245 /*.uFamily = */ 6, 241 246 /*.uModel = */ 23, 242 247 /*.uStepping = */ 6, 243 /*.enmMicroarch = */ kCpumMicroarch_Intel_Core2_Penryn,244 248 /*.uScalableBusFreq = */ CPUM_SBUSFREQ_400MHZ, 245 /*.fFlags = */ 0,246 249 /*.cMaxPhysAddrWidth= */ 38, 247 250 /*.fMxCsrMask = */ 0xffff, -
trunk/src/VBox/VMM/VMMR3/cpus/Quad_Core_AMD_Opteron_2384.h
r106061 r109008 255 255 * Database entry for Quad-Core AMD Opteron(tm) Processor 2384. 256 256 */ 257 static CPUMDBENTRY const g_Entry_Quad_Core_AMD_Opteron_2384 =257 static CPUMDBENTRYX86 const g_Entry_Quad_Core_AMD_Opteron_2384 = 258 258 { 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 }, 262 267 /*.uFamily = */ 16, 263 268 /*.uModel = */ 4, 264 269 /*.uStepping = */ 2, 265 /*.enmMicroarch = */ kCpumMicroarch_AMD_K10,266 270 /*.uScalableBusFreq = */ CPUM_SBUSFREQ_UNKNOWN, 267 /*.fFlags = */ 0,268 271 /*.cMaxPhysAddrWidth= */ 48, 269 272 /*.fMxCsrMask = */ 0x2ffff, -
trunk/src/VBox/VMM/VMMR3/cpus/VIA_QuadCore_L4700_1_2_GHz.h
r106061 r109008 389 389 * Database entry for VIA QuadCore L4700 @ 1.2+ GHz. 390 390 */ 391 static CPUMDBENTRY const g_Entry_VIA_QuadCore_L4700_1_2_GHz =391 static CPUMDBENTRYX86 const g_Entry_VIA_QuadCore_L4700_1_2_GHz = 392 392 { 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 }, 396 401 /*.uFamily = */ 6, 397 402 /*.uModel = */ 15, 398 403 /*.uStepping = */ 13, 399 /*.enmMicroarch = */ kCpumMicroarch_VIA_Isaiah,400 404 /*.uScalableBusFreq = */ CPUM_SBUSFREQ_267MHZ, /*??*/ 401 /*.fFlags = */ 0,402 405 /*.cMaxPhysAddrWidth= */ 36, 403 406 /*.fMxCsrMask = */ 0xffff, -
trunk/src/VBox/VMM/VMMR3/cpus/ZHAOXIN_KaiXian_KX_U5581_1_8GHz.h
r106061 r109008 402 402 * Database entry for ZHAOXIN KaiXian [email protected]. 403 403 */ 404 static CPUMDBENTRY const g_Entry_ZHAOXIN_KaiXian_KX_U5581_1_8GHz =404 static CPUMDBENTRYX86 const g_Entry_ZHAOXIN_KaiXian_KX_U5581_1_8GHz = 405 405 { 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 }, 409 414 /*.uFamily = */ 7, 410 415 /*.uModel = */ 11, 411 416 /*.uStepping = */ 5, 412 /*.enmMicroarch = */ kCpumMicroarch_Shanghai_Wudaokou,413 417 /*.uScalableBusFreq = */ CPUM_SBUSFREQ_UNKNOWN, 414 /*.fFlags = */ 0,415 418 /*.cMaxPhysAddrWidth= */ 40, 416 419 /*.fMxCsrMask = */ 0x0000ffff, -
trunk/src/VBox/VMM/tools/Makefile.kmk
r107227 r109008 71 71 VBoxCpuReport_SOURCES = \ 72 72 VBoxCpuReport.cpp \ 73 VBoxCpuReportMsrSup.cpp \74 73 ../VMMR3/CPUMR3CpuId.cpp \ 75 74 ../VMMAll/CPUMAllCpuId.cpp 76 VBoxCpuReport_SOURCES.linux = \ 75 76 VBoxCpuReport_SOURCES.amd64 = \ 77 VBoxCpuReport-x86.cpp \ 78 VBoxCpuReportMsrSup.cpp 79 VBoxCpuReport_SOURCES.x86 = \ 80 VBoxCpuReport-x86.cpp \ 81 VBoxCpuReportMsrSup.cpp 82 VBoxCpuReport_SOURCES.linux.amd64 = \ 77 83 VBoxCpuReportMsrLinux.cpp 78 VBoxCpuReport_DEFS.linux = VBCR_HAVE_PLATFORM_MSR_PROBER 84 VBoxCpuReport_SOURCES.linux.x86 = \ 85 VBoxCpuReportMsrLinux.cpp 86 VBoxCpuReport_DEFS.linux.amd64 = VBCR_HAVE_PLATFORM_MSR_PROBER 87 VBoxCpuReport_DEFS.linux.x86 = VBCR_HAVE_PLATFORM_MSR_PROBER 88 79 89 VBoxCpuReport_LIBS = \ 80 90 $(PATH_STAGE_LIB)/SUPR3Static$(VBOX_SUFF_LIB) \ -
trunk/src/VBox/VMM/tools/VBoxCpuReport-x86.cpp
r108997 r109008 1 1 /* $Id$ */ 2 2 /** @file 3 * VBoxCpuReport - Produces the basis for a CPU DB entry .3 * VBoxCpuReport - Produces the basis for a CPU DB entry, x86 specifics. 4 4 */ 5 5 … … 74 74 * Global Variables * 75 75 *********************************************************************************************************************************/ 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;80 76 /** Set if g_enmMicroarch indicates an Intel NetBurst CPU. */ 81 77 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 78 /** Whether to skip MSR collection. */ 87 static boolg_fNoMsrs = false;79 bool g_fNoMsrs = false; 88 80 89 81 /** Snooping info storage for vbCpuRepGuessScalableBusFrequencyName. */ … … 92 84 /** The MSR accessors interface. */ 93 85 static 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 141 86 142 87 … … 4413 4358 4414 4359 4415 static int probeMsrs(bool fHacking, const char *pszNameC, const char *pszCpuDesc, 4416 char *pszMsrMask, size_t cbMsrMask) 4360 int probeMsrs(bool fHacking, const char *pszNameC, const char *pszCpuDesc, char *pszMsrMask, size_t cbMsrMask) 4417 4361 { 4418 4362 /* Initialize the mask. */ … … 4594 4538 4595 4539 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 4616 4540 /** 4617 4541 * Takes a shot a the bus frequency name (last part). … … 4640 4564 4641 4565 4642 staticint produceCpuReport(void)4566 int produceCpuReport(void) 4643 4567 { 4644 4568 /* … … 4749 4673 { 4750 4674 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), 4752 4676 RTX86GetCpuModel(uEax, enmVendor == CPUMCPUVENDOR_INTEL), RTX86GetCpuStepping(uEax)); 4753 4677 pszCpuDesc = pszName = szNameC; … … 4836 4760 " * Database entry for %s.\n" 4837 4761 " */\n" 4838 "static CPUMDBENTRY const g_Entry_%s = \n"4762 "static CPUMDBENTRYX86 const g_Entry_%s = \n" 4839 4763 "{\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" 4843 4771 " /*.uFamily = */ %u,\n" 4844 4772 " /*.uModel = */ %u,\n" 4845 4773 " /*.uStepping = */ %u,\n" 4846 " /*.enmMicroarch = */ kCpumMicroarch_%s,\n"4847 4774 " /*.uScalableBusFreq = */ CPUM_SBUSFREQ_%s,\n" 4848 " /*.fFlags = */ 0,\n"4849 4775 " /*.cMaxPhysAddrWidth= */ %u,\n" 4850 4776 " /*.fMxCsrMask = */ %#010x,\n" … … 4865 4791 pszCpuDesc, 4866 4792 CPUMCpuVendorName(enmVendor), 4793 CPUMMicroarchName(enmMicroarch), 4794 4867 4795 RTX86GetCpuFamily(uEax), 4868 4796 RTX86GetCpuModel(uEax, enmVendor == CPUMCPUVENDOR_INTEL), 4869 4797 RTX86GetCpuStepping(uEax), 4870 CPUMMicroarchName(enmMicroarch),4871 4798 vbCpuRepGuessScalableBusFrequencyName(), 4872 4799 vbCpuRepGetPhysAddrWidth(), … … 4888 4815 } 4889 4816 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 enum4912 {4913 kCpuReportOp_Normal,4914 kCpuReportOp_MsrsOnly,4915 kCpuReportOp_MsrsHacking4916 } 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 31 31 *********************************************************************************************************************************/ 32 32 #include <iprt/asm.h> 33 #include <iprt/asm-amd64-x86.h>34 33 #include <iprt/buildconfig.h> 35 34 #include <iprt/ctype.h> 35 #include <iprt/errcore.h> 36 36 #include <iprt/file.h> 37 37 #include <iprt/getopt.h> … … 46 46 #include <iprt/time.h> 47 47 48 #include <VBox/err.h>49 48 #include <VBox/vmm/cpum.h> 50 49 #include <VBox/sup.h> … … 55 54 56 55 /********************************************************************************************************************************* 57 * Structures and Typedefs *58 *********************************************************************************************************************************/59 /** Write only register. */60 #define VBCPUREPMSR_F_WRITE_ONLY RT_BIT(0)61 62 typedef struct VBCPUREPMSR63 {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 /*********************************************************************************************************************************74 56 * Global Variables * 75 57 *********************************************************************************************************************************/ 58 /** The alternative report stream. */ 59 PRTSTREAM g_pReportOut; 60 /** The alternative debug stream. */ 61 PRTSTREAM g_pDebugOut; 76 62 /** The CPU vendor. Used by the MSR code. */ 77 staticCPUMCPUVENDOR g_enmVendor = CPUMCPUVENDOR_INVALID;63 CPUMCPUVENDOR g_enmVendor = CPUMCPUVENDOR_INVALID; 78 64 /** 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; 65 CPUMMICROARCH g_enmMicroarch = kCpumMicroarch_Invalid; 94 66 95 67 … … 141 113 142 114 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) 115 const char *vbCpuVendorToString(CPUMCPUVENDOR enmCpuVendor) 4597 116 { 4598 117 switch (enmCpuVendor) … … 4614 133 4615 134 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 else4749 {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 being4759 * that stdout is used while hacking the reporter and too much output is4760 * 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 szNameC4885 );4886 4887 return VINF_SUCCESS;4888 }4889 4890 4891 135 int main(int argc, char **argv) 4892 136 { … … 4900 144 static const RTGETOPTDEF s_aOptions[] = 4901 145 { 146 #if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86) 4902 147 { "--msrs-only", 'm', RTGETOPT_REQ_NOTHING }, 4903 148 { "--msrs-dev", 'd', RTGETOPT_REQ_NOTHING }, 4904 149 { "--no-msrs", 'n', RTGETOPT_REQ_NOTHING }, 150 #endif 4905 151 { "--output", 'o', RTGETOPT_REQ_STRING }, 4906 152 { "--log", 'l', RTGETOPT_REQ_STRING }, … … 4912 158 { 4913 159 kCpuReportOp_Normal, 160 #if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86) 4914 161 kCpuReportOp_MsrsOnly, 4915 162 kCpuReportOp_MsrsHacking 163 #else 164 kCpuReportOp_Dummy 165 #endif 4916 166 } enmOp = kCpuReportOp_Normal; 4917 167 g_pReportOut = NULL; … … 4926 176 switch (iOpt) 4927 177 { 178 #if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86) 4928 179 case 'm': 4929 180 enmOp = kCpuReportOp_MsrsOnly; … … 4937 188 g_fNoMsrs = true; 4938 189 break; 190 #endif 4939 191 4940 192 case 'o': … … 4947 199 4948 200 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); 4950 209 RTPrintf("Internal tool for gathering information to the VMM CPU database.\n"); 4951 210 return RTEXITCODE_SUCCESS; 211 } 4952 212 case 'V': 4953 213 RTPrintf("%sr%s\n", RTBldCfgVersion(), RTBldCfgRevisionStr()); … … 5008 268 rc = produceCpuReport(); 5009 269 break; 270 #if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86) 5010 271 case kCpuReportOp_MsrsOnly: 5011 272 case kCpuReportOp_MsrsHacking: 5012 273 rc = probeMsrs(enmOp == kCpuReportOp_MsrsHacking, NULL, NULL, NULL, 0); 5013 274 break; 275 #else 276 case kCpuReportOp_Dummy: 277 break; 278 #endif 5014 279 } 5015 280 -
trunk/src/VBox/VMM/tools/VBoxCpuReport.h
r106061 r109008 33 33 34 34 #include <VBox/sup.h> 35 #include <VBox/vmm/cpum.h> 36 #include <iprt/stream.h> 35 37 36 38 RT_C_DECLS_BEGIN … … 53 55 typedef VBCPUREPMSRACCESSORS *PVBCPUREPMSRACCESSORS; 54 56 57 extern PRTSTREAM g_pReportOut; 58 extern PRTSTREAM g_pDebugOut; 59 extern CPUMCPUVENDOR g_enmVendor; 60 extern CPUMMICROARCH g_enmMicroarch; 61 #if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86) 62 extern bool g_fNoMsrs; 63 #endif 64 55 65 extern void vbCpuRepDebug(const char *pszMsg, ...); 56 66 extern void vbCpuRepPrintf(const char *pszMsg, ...); 67 extern const char *vbCpuVendorToString(CPUMCPUVENDOR enmCpuVendor); 68 69 extern int produceCpuReport(void); /* arch specific */ 70 71 #if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86) 72 extern int probeMsrs(bool fHacking, const char *pszNameC, const char *pszCpuDesc, char *pszMsrMask, size_t cbMsrMask); 57 73 extern int VbCpuRepMsrProberInitSupDrv(PVBCPUREPMSRACCESSORS pMsrAccessors); 58 74 extern int VbCpuRepMsrProberInitPlatform(PVBCPUREPMSRACCESSORS pMsrAccessors); 75 #endif 59 76 60 77 RT_C_DECLS_END
Note:
See TracChangeset
for help on using the changeset viewer.