mirror of
https://git.suyu.dev/suyu/suyu.git
synced 2024-12-27 10:50:57 +01:00
common/x64: Use TSC clock rate from CPUID when available
The current method used to estimate the TSC is fairly accurate - within a few kHz - but the exact value can be extracted from CPUID if available.
This commit is contained in:
parent
770611fdf3
commit
b2ad4dd189
3 changed files with 19 additions and 1 deletions
|
@ -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,19 @@ 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.
|
||||
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;
|
||||
|
|
Loading…
Reference in a new issue