CPUMR3Db.cpp revision f2b0fba08946caa4699216915ed6cc13645f4693
eb3a3435bb6f3ad6a38085912929372669c498favboxsync * CPUM - CPU database part.
eb3a3435bb6f3ad6a38085912929372669c498favboxsync * Copyright (C) 2013 Oracle Corporation
eb3a3435bb6f3ad6a38085912929372669c498favboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
eb3a3435bb6f3ad6a38085912929372669c498favboxsync * available from http://www.virtualbox.org. This file is free software;
eb3a3435bb6f3ad6a38085912929372669c498favboxsync * you can redistribute it and/or modify it under the terms of the GNU
eb3a3435bb6f3ad6a38085912929372669c498favboxsync * General Public License (GPL) as published by the Free Software
eb3a3435bb6f3ad6a38085912929372669c498favboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
eb3a3435bb6f3ad6a38085912929372669c498favboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
eb3a3435bb6f3ad6a38085912929372669c498favboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
eb3a3435bb6f3ad6a38085912929372669c498favboxsync/*******************************************************************************
eb3a3435bb6f3ad6a38085912929372669c498favboxsync* Header Files *
eb3a3435bb6f3ad6a38085912929372669c498favboxsync*******************************************************************************/
eb3a3435bb6f3ad6a38085912929372669c498favboxsync/*******************************************************************************
eb3a3435bb6f3ad6a38085912929372669c498favboxsync* Structures and Typedefs *
eb3a3435bb6f3ad6a38085912929372669c498favboxsync*******************************************************************************/
eb3a3435bb6f3ad6a38085912929372669c498favboxsynctypedef struct CPUMDBENTRY
eb3a3435bb6f3ad6a38085912929372669c498favboxsync /** The CPU name. */
29e50fce8a16b6c8955f48b7d1e19cb7aa3694ddvboxsync const char *pszName;
eb3a3435bb6f3ad6a38085912929372669c498favboxsync /** The full CPU name. */
eb3a3435bb6f3ad6a38085912929372669c498favboxsync /** The CPU vendor (CPUMCPUVENDOR). */
29e50fce8a16b6c8955f48b7d1e19cb7aa3694ddvboxsync /** The CPU family. */
29e50fce8a16b6c8955f48b7d1e19cb7aa3694ddvboxsync /** The CPU model. */
4b783d68e6d569ab798901917ace422a4810edf0vboxsync /** The CPU stepping. */
29e50fce8a16b6c8955f48b7d1e19cb7aa3694ddvboxsync /** The microarchitecture. */
29e50fce8a16b6c8955f48b7d1e19cb7aa3694ddvboxsync /** Scalable bus frequency used for reporting other frequencies. */
29e50fce8a16b6c8955f48b7d1e19cb7aa3694ddvboxsync /** Flags (TBD). */
29e50fce8a16b6c8955f48b7d1e19cb7aa3694ddvboxsync /** The maximum physical address with of the CPU. This should correspond to
29e50fce8a16b6c8955f48b7d1e19cb7aa3694ddvboxsync * the value in CPUID leaf 0x80000008 when present. */
4b783d68e6d569ab798901917ace422a4810edf0vboxsync /** Pointer to an array of CPUID leaves. */
4b783d68e6d569ab798901917ace422a4810edf0vboxsync /** The number of CPUID leaves in the array paCpuIdLeaves points to. */
29e50fce8a16b6c8955f48b7d1e19cb7aa3694ddvboxsync /** The method used to deal with unknown CPUID leaves. */
c72f00ff9f31a65845a8722126d37708b61bb6aevboxsync /** The default unknown CPUID value. */
4b783d68e6d569ab798901917ace422a4810edf0vboxsync /** MSR mask. Several microarchitectures ignore higher bits of the */
29e50fce8a16b6c8955f48b7d1e19cb7aa3694ddvboxsync /** The number of ranges in the table pointed to b paMsrRanges. */
29e50fce8a16b6c8955f48b7d1e19cb7aa3694ddvboxsync /** MSR ranges for this CPU. */
29e50fce8a16b6c8955f48b7d1e19cb7aa3694ddvboxsync/*******************************************************************************
4b783d68e6d569ab798901917ace422a4810edf0vboxsync* Defined Constants And Macros *
f13fb2df3059d9304d27e4a594a0401ba9de4c91vboxsync*******************************************************************************/
c72f00ff9f31a65845a8722126d37708b61bb6aevboxsync/** @def NULL_ALONE
4b783d68e6d569ab798901917ace422a4810edf0vboxsync * For eliminating an unnecessary data dependency in standalone builds (for
4b783d68e6d569ab798901917ace422a4810edf0vboxsync * VBoxSVC). */
4b783d68e6d569ab798901917ace422a4810edf0vboxsync/** @def ZERO_ALONE
29e50fce8a16b6c8955f48b7d1e19cb7aa3694ddvboxsync * For eliminating an unnecessary data size dependency in standalone builds (for
29e50fce8a16b6c8955f48b7d1e19cb7aa3694ddvboxsync * VBoxSVC). */
f13fb2df3059d9304d27e4a594a0401ba9de4c91vboxsync/** @name Short macros for the MSR range entries.
f13fb2df3059d9304d27e4a594a0401ba9de4c91vboxsync * These are rather cryptic, but this is to reduce the attack on the right
f13fb2df3059d9304d27e4a594a0401ba9de4c91vboxsync/** Alias one MSR onto another (a_uTarget). */
f13fb2df3059d9304d27e4a594a0401ba9de4c91vboxsync RINT(a_uMsr, a_uMsr, kCpumMsrRdFn_MsrAlias, kCpumMsrWrFn_MsrAlias, 0, a_uTarget, 0, 0, a_szName)
f13fb2df3059d9304d27e4a594a0401ba9de4c91vboxsync/** Functions handles everything. */
c72f00ff9f31a65845a8722126d37708b61bb6aevboxsync#define MFN(a_uMsr, a_szName, a_enmRdFnSuff, a_enmWrFnSuff) \
f13fb2df3059d9304d27e4a594a0401ba9de4c91vboxsync RINT(a_uMsr, a_uMsr, kCpumMsrRdFn_##a_enmRdFnSuff, kCpumMsrWrFn_##a_enmWrFnSuff, 0, 0, 0, 0, a_szName)
f13fb2df3059d9304d27e4a594a0401ba9de4c91vboxsync/** Functions handles everything, with GP mask. */
f13fb2df3059d9304d27e4a594a0401ba9de4c91vboxsync#define MFG(a_uMsr, a_szName, a_enmRdFnSuff, a_enmWrFnSuff, a_fWrGpMask) \
f13fb2df3059d9304d27e4a594a0401ba9de4c91vboxsync RINT(a_uMsr, a_uMsr, kCpumMsrRdFn_##a_enmRdFnSuff, kCpumMsrWrFn_##a_enmWrFnSuff, 0, 0, 0, a_fWrGpMask, a_szName)
f13fb2df3059d9304d27e4a594a0401ba9de4c91vboxsync/** Function handlers, read-only. */
f13fb2df3059d9304d27e4a594a0401ba9de4c91vboxsync RINT(a_uMsr, a_uMsr, kCpumMsrRdFn_##a_enmRdFnSuff, kCpumMsrWrFn_ReadOnly, 0, 0, 0, UINT64_MAX, a_szName)
f13fb2df3059d9304d27e4a594a0401ba9de4c91vboxsync/** Function handlers, ignore all writes. */
f13fb2df3059d9304d27e4a594a0401ba9de4c91vboxsync RINT(a_uMsr, a_uMsr, kCpumMsrRdFn_##a_enmRdFnSuff, kCpumMsrWrFn_IgnoreWrite, 0, 0, UINT64_MAX, 0, a_szName)
f13fb2df3059d9304d27e4a594a0401ba9de4c91vboxsync/** Function handlers, with value. */
f13fb2df3059d9304d27e4a594a0401ba9de4c91vboxsync#define MFV(a_uMsr, a_szName, a_enmRdFnSuff, a_enmWrFnSuff, a_uValue) \
f13fb2df3059d9304d27e4a594a0401ba9de4c91vboxsync RINT(a_uMsr, a_uMsr, kCpumMsrRdFn_##a_enmRdFnSuff, kCpumMsrWrFn_##a_enmWrFnSuff, 0, a_uValue, 0, 0, a_szName)
f13fb2df3059d9304d27e4a594a0401ba9de4c91vboxsync/** Function handlers, with write ignore mask. */
f13fb2df3059d9304d27e4a594a0401ba9de4c91vboxsync#define MFW(a_uMsr, a_szName, a_enmRdFnSuff, a_enmWrFnSuff, a_fWrIgnMask) \
f13fb2df3059d9304d27e4a594a0401ba9de4c91vboxsync RINT(a_uMsr, a_uMsr, kCpumMsrRdFn_##a_enmRdFnSuff, kCpumMsrWrFn_##a_enmWrFnSuff, 0, 0, a_fWrIgnMask, 0, a_szName)
f13fb2df3059d9304d27e4a594a0401ba9de4c91vboxsync/** Function handlers, extended version. */
f13fb2df3059d9304d27e4a594a0401ba9de4c91vboxsync#define MFX(a_uMsr, a_szName, a_enmRdFnSuff, a_enmWrFnSuff, a_uValue, a_fWrIgnMask, a_fWrGpMask) \
c72f00ff9f31a65845a8722126d37708b61bb6aevboxsync RINT(a_uMsr, a_uMsr, kCpumMsrRdFn_##a_enmRdFnSuff, kCpumMsrWrFn_##a_enmWrFnSuff, 0, a_uValue, a_fWrIgnMask, a_fWrGpMask, a_szName)
f13fb2df3059d9304d27e4a594a0401ba9de4c91vboxsync/** Function handlers, with CPUMCPU storage variable. */
29e50fce8a16b6c8955f48b7d1e19cb7aa3694ddvboxsync#define MFS(a_uMsr, a_szName, a_enmRdFnSuff, a_enmWrFnSuff, a_CpumCpuMember) \
f13fb2df3059d9304d27e4a594a0401ba9de4c91vboxsync RINT(a_uMsr, a_uMsr, kCpumMsrRdFn_##a_enmRdFnSuff, kCpumMsrWrFn_##a_enmWrFnSuff, \
29e50fce8a16b6c8955f48b7d1e19cb7aa3694ddvboxsync RT_OFFSETOF(CPUMCPU, a_CpumCpuMember), 0, 0, 0, a_szName)
29e50fce8a16b6c8955f48b7d1e19cb7aa3694ddvboxsync/** Function handlers, with CPUMCPU storage variable, ignore mask and GP mask. */
29e50fce8a16b6c8955f48b7d1e19cb7aa3694ddvboxsync#define MFZ(a_uMsr, a_szName, a_enmRdFnSuff, a_enmWrFnSuff, a_CpumCpuMember, a_fWrIgnMask, a_fWrGpMask) \
29e50fce8a16b6c8955f48b7d1e19cb7aa3694ddvboxsync RINT(a_uMsr, a_uMsr, kCpumMsrRdFn_##a_enmRdFnSuff, kCpumMsrWrFn_##a_enmWrFnSuff, \
29e50fce8a16b6c8955f48b7d1e19cb7aa3694ddvboxsync RT_OFFSETOF(CPUMCPU, a_CpumCpuMember), 0, a_fWrIgnMask, a_fWrGpMask, a_szName)
4b783d68e6d569ab798901917ace422a4810edf0vboxsync/** Read-only fixed value. */
4b783d68e6d569ab798901917ace422a4810edf0vboxsync RINT(a_uMsr, a_uMsr, kCpumMsrRdFn_FixedValue, kCpumMsrWrFn_ReadOnly, 0, a_uValue, 0, UINT64_MAX, a_szName)
4b783d68e6d569ab798901917ace422a4810edf0vboxsync/** Read-only fixed value, ignores all writes. */
29e50fce8a16b6c8955f48b7d1e19cb7aa3694ddvboxsync RINT(a_uMsr, a_uMsr, kCpumMsrRdFn_FixedValue, kCpumMsrWrFn_IgnoreWrite, 0, a_uValue, UINT64_MAX, 0, a_szName)
eb3a3435bb6f3ad6a38085912929372669c498favboxsync/** Read fixed value, ignore writes outside GP mask. */
4b783d68e6d569ab798901917ace422a4810edf0vboxsync#define MVG(a_uMsr, a_szName, a_uValue, a_fWrGpMask) \
4b783d68e6d569ab798901917ace422a4810edf0vboxsync RINT(a_uMsr, a_uMsr, kCpumMsrRdFn_FixedValue, kCpumMsrWrFn_IgnoreWrite, 0, a_uValue, 0, a_fWrGpMask, a_szName)
4b783d68e6d569ab798901917ace422a4810edf0vboxsync/** Read fixed value, extended version with both GP and ignore masks. */
29e50fce8a16b6c8955f48b7d1e19cb7aa3694ddvboxsync#define MVX(a_uMsr, a_szName, a_uValue, a_fWrIgnMask, a_fWrGpMask) \
29e50fce8a16b6c8955f48b7d1e19cb7aa3694ddvboxsync RINT(a_uMsr, a_uMsr, kCpumMsrRdFn_FixedValue, kCpumMsrWrFn_IgnoreWrite, 0, a_uValue, a_fWrIgnMask, a_fWrGpMask, a_szName)
29e50fce8a16b6c8955f48b7d1e19cb7aa3694ddvboxsync/** The short form, no CPUM backing. */
29e50fce8a16b6c8955f48b7d1e19cb7aa3694ddvboxsync#define MSN(a_uMsr, a_szName, a_enmRdFnSuff, a_enmWrFnSuff, a_uInitOrReadValue, a_fWrIgnMask, a_fWrGpMask) \
eb3a3435bb6f3ad6a38085912929372669c498favboxsync RINT(a_uMsr, a_uMsr, kCpumMsrRdFn_##a_enmRdFnSuff, kCpumMsrWrFn_##a_enmWrFnSuff, 0, \
29e50fce8a16b6c8955f48b7d1e19cb7aa3694ddvboxsync a_uInitOrReadValue, a_fWrIgnMask, a_fWrGpMask, a_szName)
c72f00ff9f31a65845a8722126d37708b61bb6aevboxsync/** Range: Functions handles everything. */
c72f00ff9f31a65845a8722126d37708b61bb6aevboxsync#define RFN(a_uFirst, a_uLast, a_szName, a_enmRdFnSuff, a_enmWrFnSuff) \
29e50fce8a16b6c8955f48b7d1e19cb7aa3694ddvboxsync RINT(a_uFirst, a_uLast, kCpumMsrRdFn_##a_enmRdFnSuff, kCpumMsrWrFn_##a_enmWrFnSuff, 0, 0, 0, 0, a_szName)
29e50fce8a16b6c8955f48b7d1e19cb7aa3694ddvboxsync/** Range: Read fixed value, read-only. */
29e50fce8a16b6c8955f48b7d1e19cb7aa3694ddvboxsync#define RVO(a_uFirst, a_uLast, a_szName, a_uValue) \
c72f00ff9f31a65845a8722126d37708b61bb6aevboxsync RINT(a_uFirst, a_uLast, kCpumMsrRdFn_FixedValue, kCpumMsrWrFn_ReadOnly, 0, a_uValue, 0, UINT64_MAX, a_szName)
c72f00ff9f31a65845a8722126d37708b61bb6aevboxsync/** Range: Read fixed value, ignore writes. */
29e50fce8a16b6c8955f48b7d1e19cb7aa3694ddvboxsync#define RVI(a_uFirst, a_uLast, a_szName, a_uValue) \
29e50fce8a16b6c8955f48b7d1e19cb7aa3694ddvboxsync RINT(a_uFirst, a_uLast, kCpumMsrRdFn_FixedValue, kCpumMsrWrFn_IgnoreWrite, 0, a_uValue, UINT64_MAX, 0, a_szName)
eb3a3435bb6f3ad6a38085912929372669c498favboxsync/** Range: The short form, no CPUM backing. */
c72f00ff9f31a65845a8722126d37708b61bb6aevboxsync#define RSN(a_uFirst, a_uLast, a_szName, a_enmRdFnSuff, a_enmWrFnSuff, a_uInitOrReadValue, a_fWrIgnMask, a_fWrGpMask) \
c72f00ff9f31a65845a8722126d37708b61bb6aevboxsync RINT(a_uFirst, a_uLast, kCpumMsrRdFn_##a_enmRdFnSuff, kCpumMsrWrFn_##a_enmWrFnSuff, 0, \
eb3a3435bb6f3ad6a38085912929372669c498favboxsync a_uInitOrReadValue, a_fWrIgnMask, a_fWrGpMask, a_szName)
f13fb2df3059d9304d27e4a594a0401ba9de4c91vboxsync/** Internal form used by the macros. */
f13fb2df3059d9304d27e4a594a0401ba9de4c91vboxsync# define RINT(a_uFirst, a_uLast, a_enmRdFn, a_enmWrFn, a_offCpumCpu, a_uInitOrReadValue, a_fWrIgnMask, a_fWrGpMask, a_szName) \
29e50fce8a16b6c8955f48b7d1e19cb7aa3694ddvboxsync { a_uFirst, a_uLast, a_enmRdFn, a_enmWrFn, a_offCpumCpu, 0, a_uInitOrReadValue, a_fWrIgnMask, a_fWrGpMask, a_szName, \
eb3a3435bb6f3ad6a38085912929372669c498favboxsync { 0 }, { 0 }, { 0 }, { 0 } }
f13fb2df3059d9304d27e4a594a0401ba9de4c91vboxsync# define RINT(a_uFirst, a_uLast, a_enmRdFn, a_enmWrFn, a_offCpumCpu, a_uInitOrReadValue, a_fWrIgnMask, a_fWrGpMask, a_szName) \
f13fb2df3059d9304d27e4a594a0401ba9de4c91vboxsync { a_uFirst, a_uLast, a_enmRdFn, a_enmWrFn, a_offCpumCpu, 0, a_uInitOrReadValue, a_fWrIgnMask, a_fWrGpMask, a_szName }
#include "cpus/VIA_QuadCore_L4700_1_2_GHz.h"
#ifndef CPUM_DB_STANDALONE
static uint32_t cpumR3MsrRangesBinSearch(PCCPUMMSRRANGE paMsrRanges, uint32_t cMsrRanges, uint32_t uMsr)
if (!cMsrRanges)
if (i <= iStart)
if (i >= iLast)
if (i < cMsrRanges)
static PCPUMMSRRANGE cpumR3MsrRangesEnsureSpace(PVM pVM, PCPUMMSRRANGE *ppaMsrRanges, uint32_t cMsrRanges, uint32_t cNewRanges)
if (!pVM)
void *pvNew;
if (pVM)
return NULL;
if (!pvNew)
return NULL;
if (pVM)
return *ppaMsrRanges;
int cpumR3MsrRangesInsert(PVM pVM, PCPUMMSRRANGE *ppaMsrRanges, uint32_t *pcMsrRanges, PCCPUMMSRRANGE pNewRange)
if (pVM)
if ( cMsrRanges > 0
if (!paMsrRanges)
return VERR_NO_MEMORY;
if ( i >= cMsrRanges
if (!paMsrRanges)
return VERR_NO_MEMORY;
if (i < cMsrRanges)
if (!paMsrRanges)
return VERR_NO_MEMORY;
if (i < cMsrRanges)
while ( i < cMsrRanges
if (!paMsrRanges)
return VERR_NO_MEMORY;
if (i < cMsrRanges)
return VINF_SUCCESS;
int rc = cpumR3MsrRangesInsert(NULL /* pVM */, &pVM->cpum.s.GuestInfo.paMsrRangesR3, &pVM->cpum.s.GuestInfo.cMsrRanges,
&paRanges[i]);
return rc;
return VINF_SUCCESS;
MFZ(0x000002ff, "IA32_MTRR_DEF_TYPE", Ia32MtrrDefType, Ia32MtrrDefType, GuestMsrs.msr.MtrrDefType, 0, ~(uint64_t)0xc07),
MFN(0x00000400, "IA32_MCi_CTL_STATUS_ADDR_MISC", Ia32McCtlStatusAddrMiscN, Ia32McCtlStatusAddrMiscN),
MFX(0x0000002c, "P4_EBC_FREQUENCY_ID", IntelP4EbcFrequencyId, IntelP4EbcFrequencyId, 0xf12010f, UINT64_MAX, 0),
return rc;
int rc;
return rc;
return rc;
CPUMMICROARCH const enmMicroarch = CPUMR3CpuIdDetermineMicroarchEx(enmVendor, uFamily, uModel, uStepping);
if ( !pEntry
else if ( !pEntry
else if ( !pEntry
else if (!pEntry)
if (pEntry)
pEntry->pszName, CPUMR3CpuVendorName((CPUMCPUVENDOR)pEntry->enmVendor), pEntry->uFamily, pEntry->uModel,
if (!pEntry)
return VERR_CPUM_DB_CPU_NOT_FOUND;
return VERR_NO_MEMORY;
while (cLeft-- > 0)
return rc;
pCurMsr++;
return VINF_SUCCESS;
STAM_REL_REG(pVM, &pCpum->cMsrWritesToIgnoredBits, STAMTYPE_COUNTER, "/CPUM/MSR-Totals/WritesToIgnoredBits",
# ifdef VBOX_WITH_STATISTICS
STAMR3Register(pVM, &paRanges[i].cReads, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, szName, STAMUNIT_OCCURENCES, "RDMSR");
STAMR3Register(pVM, &paRanges[i].cWrites, STAMTYPE_COUNTER, STAMVISIBILITY_USED, szName, STAMUNIT_OCCURENCES, "WRMSR");
STAMR3Register(pVM, &paRanges[i].cGps, STAMTYPE_COUNTER, STAMVISIBILITY_USED, szName, STAMUNIT_OCCURENCES, "#GPs");
STAMR3Register(pVM, &paRanges[i].cIgnoredBits, STAMTYPE_COUNTER, STAMVISIBILITY_USED, szName, STAMUNIT_OCCURENCES, "WRMSR w/ ignored bits");
return VINF_SUCCESS;