diff options
Diffstat (limited to 'src/VBox/VMM/VMMAll/CPUMAllMsrs.cpp')
-rw-r--r-- | src/VBox/VMM/VMMAll/CPUMAllMsrs.cpp | 214 |
1 files changed, 146 insertions, 68 deletions
diff --git a/src/VBox/VMM/VMMAll/CPUMAllMsrs.cpp b/src/VBox/VMM/VMMAll/CPUMAllMsrs.cpp index 9e1a40cce..c34a3d471 100644 --- a/src/VBox/VMM/VMMAll/CPUMAllMsrs.cpp +++ b/src/VBox/VMM/VMMAll/CPUMAllMsrs.cpp @@ -181,6 +181,21 @@ static DECLCALLBACK(int) cpumMsrWr_Ia32TimestampCounter(PVMCPU pVCpu, uint32_t i /** @callback_method_impl{FNCPUMRDMSR} */ +static DECLCALLBACK(int) cpumMsrRd_Ia32PlatformId(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue) +{ + uint64_t uValue = pRange->uValue; + if (uValue & 0x1f00) + { + /* Max allowed bus ratio present. */ + /** @todo Implement scaled BUS frequency. */ + } + + *puValue = uValue; + return VINF_SUCCESS; +} + + +/** @callback_method_impl{FNCPUMRDMSR} */ static DECLCALLBACK(int) cpumMsrRd_Ia32ApicBase(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue) { PVM pVM = pVCpu->CTX_SUFF(pVM); @@ -713,8 +728,20 @@ static DECLCALLBACK(int) cpumMsrWr_Ia32PerfEvtSelN(PVMCPU pVCpu, uint32_t idMsr, /** @callback_method_impl{FNCPUMRDMSR} */ static DECLCALLBACK(int) cpumMsrRd_Ia32PerfStatus(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue) { - /** @todo implement IA32_PERFSTATUS. */ - *puValue = pRange->uValue; + uint64_t uValue = pRange->uValue; + + /* Always provide the max bus ratio for now. XNU expects it. */ + uValue &= ~((UINT64_C(0x1f) << 40) | RT_BIT_64(46)); + + PVM pVM = pVCpu->CTX_SUFF(pVM); + uint64_t uScalableBusHz = CPUMGetGuestScalableBusFrequency(pVM); + uint64_t uTscHz = TMCpuTicksPerSecond(pVM); + uint8_t uTscRatio = (uint8_t)((uTscHz + uScalableBusHz / 2) / uScalableBusHz); + if (uTscRatio > 0x1f) + uTscRatio = 0x1f; + uValue |= (uint64_t)uTscRatio << 40; + + *puValue = uValue; return VINF_SUCCESS; } @@ -1493,6 +1520,18 @@ static DECLCALLBACK(int) cpumMsrWr_IntelEblCrPowerOn(PVMCPU pVCpu, uint32_t idMs /** @callback_method_impl{FNCPUMRDMSR} */ +static DECLCALLBACK(int) cpumMsrRd_IntelI7CoreThreadCount(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue) +{ + /* Note! According to cpuid_set_info in XNU (10.7.0), Westmere CPU only + have a 4-bit core count. */ + uint16_t cCores = pVCpu->CTX_SUFF(pVM)->cCpus; + uint16_t cThreads = cCores; /** @todo hyper-threading. */ + *puValue = RT_MAKE_U32(cThreads, cCores); + return VINF_SUCCESS; +} + + +/** @callback_method_impl{FNCPUMRDMSR} */ static DECLCALLBACK(int) cpumMsrRd_IntelP4EbcHardPowerOn(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue) { /** @todo P4 hard power on config */ @@ -1529,8 +1568,57 @@ static DECLCALLBACK(int) cpumMsrWr_IntelP4EbcSoftPowerOn(PVMCPU pVCpu, uint32_t /** @callback_method_impl{FNCPUMRDMSR} */ static DECLCALLBACK(int) cpumMsrRd_IntelP4EbcFrequencyId(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue) { - /** @todo P4 bus frequency config */ - *puValue = pRange->uValue; + uint64_t uValue; + PVM pVM = pVCpu->CTX_SUFF(pVM); + uint64_t uScalableBusHz = CPUMGetGuestScalableBusFrequency(pVM); + if (pVM->cpum.s.GuestFeatures.uModel >= 2) + { + if (uScalableBusHz <= CPUM_SBUSFREQ_100MHZ && pVM->cpum.s.GuestFeatures.uModel <= 2) + { + uScalableBusHz = CPUM_SBUSFREQ_100MHZ; + uValue = 0; + } + else if (uScalableBusHz <= CPUM_SBUSFREQ_133MHZ) + { + uScalableBusHz = CPUM_SBUSFREQ_133MHZ; + uValue = 1; + } + else if (uScalableBusHz <= CPUM_SBUSFREQ_167MHZ) + { + uScalableBusHz = CPUM_SBUSFREQ_167MHZ; + uValue = 3; + } + else if (uScalableBusHz <= CPUM_SBUSFREQ_200MHZ) + { + uScalableBusHz = CPUM_SBUSFREQ_200MHZ; + uValue = 2; + } + else if (uScalableBusHz <= CPUM_SBUSFREQ_267MHZ && pVM->cpum.s.GuestFeatures.uModel > 2) + { + uScalableBusHz = CPUM_SBUSFREQ_267MHZ; + uValue = 0; + } + else + { + uScalableBusHz = CPUM_SBUSFREQ_333MHZ; + uValue = 6; + } + uValue <<= 16; + + uint64_t uTscHz = TMCpuTicksPerSecond(pVM); + uint8_t uTscRatio = (uint8_t)((uTscHz + uScalableBusHz / 2) / uScalableBusHz); + uValue |= (uint32_t)uTscRatio << 24; + + uValue |= pRange->uValue & ~UINT64_C(0xff0f0000); + } + else + { + /* Probably more stuff here, but intel doesn't want to tell us. */ + uValue = pRange->uValue; + uValue &= ~(RT_BIT_64(21) | RT_BIT_64(22) | RT_BIT_64(23)); /* 100 MHz is only documented value */ + } + + *puValue = uValue; return VINF_SUCCESS; } @@ -1544,66 +1632,61 @@ static DECLCALLBACK(int) cpumMsrWr_IntelP4EbcFrequencyId(PVMCPU pVCpu, uint32_t /** @callback_method_impl{FNCPUMRDMSR} */ -static DECLCALLBACK(int) cpumMsrRd_IntelPlatformInfo100MHz(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue) +static DECLCALLBACK(int) cpumMsrRd_IntelP6FsbFrequency(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue) { - PVM pVM = pVCpu->CTX_SUFF(pVM); + /* Convert the scalable bus frequency to the encoding in the intel manual (for core+). */ + uint64_t uScalableBusHz = CPUMGetGuestScalableBusFrequency(pVCpu->CTX_SUFF(pVM)); + if (uScalableBusHz <= CPUM_SBUSFREQ_100MHZ) + *puValue = 5; + else if (uScalableBusHz <= CPUM_SBUSFREQ_133MHZ) + *puValue = 1; + else if (uScalableBusHz <= CPUM_SBUSFREQ_167MHZ) + *puValue = 3; + else if (uScalableBusHz <= CPUM_SBUSFREQ_200MHZ) + *puValue = 2; + else if (uScalableBusHz <= CPUM_SBUSFREQ_267MHZ) + *puValue = 0; + else if (uScalableBusHz <= CPUM_SBUSFREQ_333MHZ) + *puValue = 4; + else /*if (uScalableBusHz <= CPUM_SBUSFREQ_400MHZ)*/ + *puValue = 6; - /* Just indicate a fixed TSC, no turbo boost, no programmable anything. */ - uint64_t uTscHz = TMCpuTicksPerSecond(pVM); - uint8_t uTsc100MHz = (uint8_t)(uTscHz / UINT32_C(100000000)); - *puValue = ((uint32_t)uTsc100MHz << 8) /* TSC invariant frequency. */ - | ((uint64_t)uTsc100MHz << 40); /* The max turbo frequency. */ - - /* Ivy bridge has a minimum operating ratio as well. */ - if (true) /** @todo detect sandy bridge. */ - *puValue |= (uint64_t)uTsc100MHz << 48; + *puValue |= pRange->uValue & ~UINT64_C(0x7); return VINF_SUCCESS; } /** @callback_method_impl{FNCPUMRDMSR} */ -static DECLCALLBACK(int) cpumMsrRd_IntelPlatformInfo133MHz(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue) +static DECLCALLBACK(int) cpumMsrRd_IntelPlatformInfo(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue) { /* Just indicate a fixed TSC, no turbo boost, no programmable anything. */ - uint64_t uTscHz = TMCpuTicksPerSecond(pVCpu->CTX_SUFF(pVM)); - uint8_t uTsc133MHz = (uint8_t)(uTscHz / UINT32_C(133333333)); - *puValue = ((uint32_t)uTsc133MHz << 8) /* TSC invariant frequency. */ - | ((uint64_t)uTsc133MHz << 40); /* The max turbo frequency. */ - return VINF_SUCCESS; -} + PVM pVM = pVCpu->CTX_SUFF(pVM); + uint64_t uScalableBusHz = CPUMGetGuestScalableBusFrequency(pVM); + uint64_t uTscHz = TMCpuTicksPerSecond(pVM); + uint8_t uTscRatio = (uint8_t)((uTscHz + uScalableBusHz / 2) / uScalableBusHz); + uint64_t uValue = ((uint32_t)uTscRatio << 8) /* TSC invariant frequency. */ + | ((uint64_t)uTscRatio << 40); /* The max turbo frequency. */ - -/** @callback_method_impl{FNCPUMRDMSR} */ -static DECLCALLBACK(int) cpumMsrRd_IntelFlexRatio100MHz(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue) -{ - uint64_t uValue = pRange->uValue & ~UINT64_C(0x1ff00); - - uint64_t uTscHz = TMCpuTicksPerSecond(pVCpu->CTX_SUFF(pVM)); - uint8_t uTsc100MHz = (uint8_t)(uTscHz / UINT32_C(100000000)); - uValue |= (uint32_t)uTsc100MHz << 8; + /* Ivy bridge has a minimum operating ratio as well. */ + if (true) /** @todo detect sandy bridge. */ + uValue |= (uint64_t)uTscRatio << 48; *puValue = uValue; return VINF_SUCCESS; } -/** @callback_method_impl{FNCPUMWRMSR} */ -static DECLCALLBACK(int) cpumMsrWr_IntelFlexRatio100MHz(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue) -{ - /** @todo implement writing MSR_FLEX_RATIO. */ - return VINF_SUCCESS; -} - - /** @callback_method_impl{FNCPUMRDMSR} */ -static DECLCALLBACK(int) cpumMsrRd_IntelFlexRatio133MHz(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue) +static DECLCALLBACK(int) cpumMsrRd_IntelFlexRatio(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue) { uint64_t uValue = pRange->uValue & ~UINT64_C(0x1ff00); - uint64_t uTscHz = TMCpuTicksPerSecond(pVCpu->CTX_SUFF(pVM)); - uint8_t uTsc133MHz = (uint8_t)(uTscHz / UINT32_C(133333333)); - uValue |= (uint32_t)uTsc133MHz << 8; + PVM pVM = pVCpu->CTX_SUFF(pVM); + uint64_t uScalableBusHz = CPUMGetGuestScalableBusFrequency(pVM); + uint64_t uTscHz = TMCpuTicksPerSecond(pVM); + uint8_t uTscRatio = (uint8_t)((uTscHz + uScalableBusHz / 2) / uScalableBusHz); + uValue |= (uint32_t)uTscRatio << 8; *puValue = uValue; return VINF_SUCCESS; @@ -1611,7 +1694,7 @@ static DECLCALLBACK(int) cpumMsrRd_IntelFlexRatio133MHz(PVMCPU pVCpu, uint32_t i /** @callback_method_impl{FNCPUMWRMSR} */ -static DECLCALLBACK(int) cpumMsrWr_IntelFlexRatio133MHz(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue) +static DECLCALLBACK(int) cpumMsrWr_IntelFlexRatio(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue) { /** @todo implement writing MSR_FLEX_RATIO. */ return VINF_SUCCESS; @@ -4308,6 +4391,7 @@ static const PFNCPUMRDMSR g_aCpumRdMsrFns[kCpumMsrRdFn_End] = cpumMsrRd_Ia32P5McAddr, cpumMsrRd_Ia32P5McType, cpumMsrRd_Ia32TimestampCounter, + cpumMsrRd_Ia32PlatformId, cpumMsrRd_Ia32ApicBase, cpumMsrRd_Ia32FeatureControl, cpumMsrRd_Ia32BiosSignId, @@ -4384,13 +4468,13 @@ static const PFNCPUMRDMSR g_aCpumRdMsrFns[kCpumMsrRdFn_End] = cpumMsrRd_Amd64TscAux, cpumMsrRd_IntelEblCrPowerOn, + cpumMsrRd_IntelI7CoreThreadCount, cpumMsrRd_IntelP4EbcHardPowerOn, cpumMsrRd_IntelP4EbcSoftPowerOn, cpumMsrRd_IntelP4EbcFrequencyId, - cpumMsrRd_IntelPlatformInfo100MHz, - cpumMsrRd_IntelPlatformInfo133MHz, - cpumMsrRd_IntelFlexRatio100MHz, - cpumMsrRd_IntelFlexRatio133MHz, + cpumMsrRd_IntelP6FsbFrequency, + cpumMsrRd_IntelPlatformInfo, + cpumMsrRd_IntelFlexRatio, cpumMsrRd_IntelPkgCStConfigControl, cpumMsrRd_IntelPmgIoCaptureBase, cpumMsrRd_IntelLastBranchFromToN, @@ -4626,8 +4710,7 @@ static const PFNCPUMWRMSR g_aCpumWrMsrFns[kCpumMsrWrFn_End] = cpumMsrWr_IntelP4EbcHardPowerOn, cpumMsrWr_IntelP4EbcSoftPowerOn, cpumMsrWr_IntelP4EbcFrequencyId, - cpumMsrWr_IntelFlexRatio100MHz, - cpumMsrWr_IntelFlexRatio133MHz, + cpumMsrWr_IntelFlexRatio, cpumMsrWr_IntelPkgCStConfigControl, cpumMsrWr_IntelPmgIoCaptureBase, cpumMsrWr_IntelLastBranchFromToN, @@ -4999,6 +5082,7 @@ int cpumR3MsrStrictInitChecks(void) CPUM_ASSERT_RD_MSR_FN(Ia32P5McAddr); CPUM_ASSERT_RD_MSR_FN(Ia32P5McType); CPUM_ASSERT_RD_MSR_FN(Ia32TimestampCounter); + CPUM_ASSERT_RD_MSR_FN(Ia32PlatformId); CPUM_ASSERT_RD_MSR_FN(Ia32ApicBase); CPUM_ASSERT_RD_MSR_FN(Ia32FeatureControl); CPUM_ASSERT_RD_MSR_FN(Ia32BiosSignId); @@ -5074,13 +5158,13 @@ int cpumR3MsrStrictInitChecks(void) CPUM_ASSERT_RD_MSR_FN(Amd64TscAux); CPUM_ASSERT_RD_MSR_FN(IntelEblCrPowerOn); + CPUM_ASSERT_RD_MSR_FN(IntelI7CoreThreadCount); CPUM_ASSERT_RD_MSR_FN(IntelP4EbcHardPowerOn); CPUM_ASSERT_RD_MSR_FN(IntelP4EbcSoftPowerOn); CPUM_ASSERT_RD_MSR_FN(IntelP4EbcFrequencyId); - CPUM_ASSERT_RD_MSR_FN(IntelPlatformInfo100MHz); - CPUM_ASSERT_RD_MSR_FN(IntelPlatformInfo133MHz); - CPUM_ASSERT_RD_MSR_FN(IntelFlexRatio100MHz); - CPUM_ASSERT_RD_MSR_FN(IntelFlexRatio133MHz); + CPUM_ASSERT_RD_MSR_FN(IntelP6FsbFrequency); + CPUM_ASSERT_RD_MSR_FN(IntelPlatformInfo); + CPUM_ASSERT_RD_MSR_FN(IntelFlexRatio); CPUM_ASSERT_RD_MSR_FN(IntelPkgCStConfigControl); CPUM_ASSERT_RD_MSR_FN(IntelPmgIoCaptureBase); CPUM_ASSERT_RD_MSR_FN(IntelLastBranchFromToN); @@ -5305,8 +5389,7 @@ int cpumR3MsrStrictInitChecks(void) CPUM_ASSERT_WR_MSR_FN(IntelP4EbcHardPowerOn); CPUM_ASSERT_WR_MSR_FN(IntelP4EbcSoftPowerOn); CPUM_ASSERT_WR_MSR_FN(IntelP4EbcFrequencyId); - CPUM_ASSERT_WR_MSR_FN(IntelFlexRatio100MHz); - CPUM_ASSERT_WR_MSR_FN(IntelFlexRatio133MHz); + CPUM_ASSERT_WR_MSR_FN(IntelFlexRatio); CPUM_ASSERT_WR_MSR_FN(IntelPkgCStConfigControl); CPUM_ASSERT_WR_MSR_FN(IntelPmgIoCaptureBase); CPUM_ASSERT_WR_MSR_FN(IntelLastBranchFromToN); @@ -5452,25 +5535,20 @@ int cpumR3MsrStrictInitChecks(void) /** - * Gets the bus frequency. + * Gets the scalable bus frequency. * * The bus frequency is used as a base in several MSRs that gives the CPU and * other frequency ratios. * - * @returns Bus frequency in Hz. + * @returns Scalable bus frequency in Hz. Will not return CPUM_SBUSFREQ_UNKNOWN. * @param pVM Pointer to the shared VM structure. */ -VMMDECL(uint64_t) CPUMGetGuestBusFrequency(PVM pVM) +VMMDECL(uint64_t) CPUMGetGuestScalableBusFrequency(PVM pVM) { - if (CPUMMICROARCH_IS_INTEL_CORE7(pVM->cpum.s.GuestFeatures.enmMicroarch)) - { - return pVM->cpum.s.GuestFeatures.enmMicroarch >= kCpumMicroarch_Intel_Core7_SandyBridge - ? UINT64_C(100000000) /* 100MHz */ - : UINT64_C(133333333); /* 133MHz */ - } - - /* 133MHz */ - return UINT64_C(133333333); + uint64_t uFreq = pVM->cpum.s.GuestInfo.uScalableBusFreq; + if (uFreq == CPUM_SBUSFREQ_UNKNOWN) + uFreq = CPUM_SBUSFREQ_100MHZ; + return uFreq; } |