Browse Source
Merge pull request #8543 from BreadFish64/use_tsc_from_caps
common/x64: Use TSC clock rate from CPUID when available
pull/15/merge
bunnei
3 years ago
committed by
GitHub
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with
22 additions and
1 deletions
-
src/common/wall_clock.cpp
-
src/common/x64/cpu_detect.cpp
-
src/common/x64/cpu_detect.h
|
|
|
@ -67,7 +67,7 @@ std::unique_ptr<WallClock> CreateBestMatchingClock(u64 emulated_cpu_frequency, |
|
|
|
const auto& caps = GetCPUCaps(); |
|
|
|
u64 rtsc_frequency = 0; |
|
|
|
if (caps.invariant_tsc) { |
|
|
|
rtsc_frequency = EstimateRDTSCFrequency(); |
|
|
|
rtsc_frequency = caps.tsc_frequency ? caps.tsc_frequency : EstimateRDTSCFrequency(); |
|
|
|
} |
|
|
|
|
|
|
|
// Fallback to StandardWallClock if the hardware TSC does not have the precision greater than:
|
|
|
|
|
|
|
|
@ -161,6 +161,22 @@ static CPUCaps Detect() { |
|
|
|
caps.invariant_tsc = Common::Bit<8>(cpu_id[3]); |
|
|
|
} |
|
|
|
|
|
|
|
if (max_std_fn >= 0x15) { |
|
|
|
__cpuid(cpu_id, 0x15); |
|
|
|
caps.tsc_crystal_ratio_denominator = cpu_id[0]; |
|
|
|
caps.tsc_crystal_ratio_numerator = cpu_id[1]; |
|
|
|
caps.crystal_frequency = cpu_id[2]; |
|
|
|
// Some CPU models might not return a crystal frequency.
|
|
|
|
// The CPU model can be detected to use the values from turbostat
|
|
|
|
// https://github.com/torvalds/linux/blob/master/tools/power/x86/turbostat/turbostat.c#L5569
|
|
|
|
// but it's easier to just estimate the TSC tick rate for these cases.
|
|
|
|
if (caps.tsc_crystal_ratio_denominator) { |
|
|
|
caps.tsc_frequency = static_cast<u64>(caps.crystal_frequency) * |
|
|
|
caps.tsc_crystal_ratio_numerator / |
|
|
|
caps.tsc_crystal_ratio_denominator; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (max_std_fn >= 0x16) { |
|
|
|
__cpuid(cpu_id, 0x16); |
|
|
|
caps.base_frequency = cpu_id[0]; |
|
|
|
|
|
|
|
@ -30,6 +30,11 @@ struct CPUCaps { |
|
|
|
u32 max_frequency; |
|
|
|
u32 bus_frequency; |
|
|
|
|
|
|
|
u32 tsc_crystal_ratio_denominator; |
|
|
|
u32 tsc_crystal_ratio_numerator; |
|
|
|
u32 crystal_frequency; |
|
|
|
u64 tsc_frequency; // Derived from the above three values |
|
|
|
|
|
|
|
bool sse : 1; |
|
|
|
bool sse2 : 1; |
|
|
|
bool sse3 : 1; |
|
|
|
|