From: Marc-Aurel Zent mzent@codeweavers.com
--- programs/wineboot/wineboot.c | 111 ++++++++++++----------------------- 1 file changed, 36 insertions(+), 75 deletions(-)
diff --git a/programs/wineboot/wineboot.c b/programs/wineboot/wineboot.c index e7869eb64f4..a19046a6439 100644 --- a/programs/wineboot/wineboot.c +++ b/programs/wineboot/wineboot.c @@ -245,90 +245,51 @@ static void initialize_xstate_features(struct _KUSER_SHARED_DATA *data) static UINT64 read_tsc_frequency( BOOL has_rdtscp ) { UINT64 freq = 0; + LONGLONG time0, time1, tsc0, tsc1, tsc2, tsc3, freq0, freq1, error; + unsigned int aux; + UINT retries = 50; + int regs[4];
-/* FIXME: Intel provides TSC freq in some CPUID but it's been slightly broken, - fix it properly and test it on real Intel hardware */ - -#if 0 - int regs[4], cpuid_level, tmp; - UINT64 denom, numer; - - __cpuid( regs, 0 ); - tmp = regs[2]; - regs[2] = regs[3]; - regs[3] = tmp; - - /* only available on some intel CPUs */ - if (memcmp( regs + 1, "GenuineIntel", 12 )) freq = 0; - else if ((cpuid_level = regs[0]) < 0x15) freq = 0; - else + do { - __cpuid( regs, 0x15 ); - if (!(denom = regs[0]) || !(numer = regs[1])) freq = 0; + if (has_rdtscp) + { + tsc0 = __rdtscp( &aux ); + time0 = RtlGetSystemTimePrecise(); + tsc1 = __rdtscp( &aux ); + Sleep( 1 ); + tsc2 = __rdtscp( &aux ); + time1 = RtlGetSystemTimePrecise(); + tsc3 = __rdtscp( &aux ); + } else { - if ((freq = regs[2])) freq = freq * numer / denom; - else if (cpuid_level >= 0x16) - { - __cpuid( regs, 0x16 ); /* eax is base freq in MHz */ - freq = regs[0] * (UINT64)1000000; - } - else freq = 0; + tsc0 = __rdtsc(); __cpuid( regs, 0 ); + time0 = RtlGetSystemTimePrecise(); + tsc1 = __rdtsc(); __cpuid( regs, 0 ); + Sleep(1); + tsc2 = __rdtsc(); __cpuid( regs, 0 ); + time1 = RtlGetSystemTimePrecise(); + tsc3 = __rdtsc(); __cpuid( regs, 0 ); }
- if (!freq) WARN( "Failed to read TSC frequency from CPUID, falling back to calibration.\n" ); - else TRACE( "TSC frequency read from CPUID, found %I64u Hz\n", freq ); + freq0 = (tsc2 - tsc0) * 10000000 / (time1 - time0); + freq1 = (tsc3 - tsc1) * 10000000 / (time1 - time0); + error = llabs( (freq1 - freq0) * 1000000 / min( freq1, freq0 ) ); } -#endif + while (error > 500 && --retries);
- if (freq == 0) + if (!retries) { - LONGLONG time0, time1, tsc0, tsc1, tsc2, tsc3, freq0, freq1, error; - unsigned int aux; - UINT retries = 50; - int regs[4]; - - do - { - if (has_rdtscp) - { - tsc0 = __rdtscp( &aux ); - time0 = RtlGetSystemTimePrecise(); - tsc1 = __rdtscp( &aux ); - Sleep( 1 ); - tsc2 = __rdtscp( &aux ); - time1 = RtlGetSystemTimePrecise(); - tsc3 = __rdtscp( &aux ); - } - else - { - tsc0 = __rdtsc(); __cpuid( regs, 0 ); - time0 = RtlGetSystemTimePrecise(); - tsc1 = __rdtsc(); __cpuid( regs, 0 ); - Sleep(1); - tsc2 = __rdtsc(); __cpuid( regs, 0 ); - time1 = RtlGetSystemTimePrecise(); - tsc3 = __rdtsc(); __cpuid( regs, 0 ); - } - - freq0 = (tsc2 - tsc0) * 10000000 / (time1 - time0); - freq1 = (tsc3 - tsc1) * 10000000 / (time1 - time0); - error = llabs( (freq1 - freq0) * 1000000 / min( freq1, freq0 ) ); - } - while (error > 500 && --retries); - - if (!retries) - { - FIXME( "TSC frequency calibration failed, unstable TSC?"); - FIXME( "time0 %I64u ns, time1 %I64u ns\n", time0 * 100, time1 * 100 ); - FIXME( "tsc2 - tsc0 %I64u, tsc3 - tsc1 %I64u\n", tsc2 - tsc0, tsc3 - tsc1 ); - FIXME( "freq0 %I64u Hz, freq2 %I64u Hz, error %I64u ppm\n", freq0, freq1, error ); - } - else - { - freq = (freq0 + freq1) / 2; - TRACE( "TSC frequency calibration complete, found %I64u Hz\n", freq ); - } + FIXME( "TSC frequency calibration failed, unstable TSC?"); + FIXME( "time0 %I64u ns, time1 %I64u ns\n", time0 * 100, time1 * 100 ); + FIXME( "tsc2 - tsc0 %I64u, tsc3 - tsc1 %I64u\n", tsc2 - tsc0, tsc3 - tsc1 ); + FIXME( "freq0 %I64u Hz, freq2 %I64u Hz, error %I64u ppm\n", freq0, freq1, error ); + } + else + { + freq = (freq0 + freq1) / 2; + TRACE( "TSC frequency calibration complete, found %I64u Hz\n", freq ); }
return freq;