1717#include <asm/time.h>
1818#include <asm/delay.h>
1919#include <asm/hypervisor.h>
20+ #include <asm/nmi.h>
2021
2122unsigned int __read_mostly cpu_khz ; /* TSC clocks / usec, not used here */
2223EXPORT_SYMBOL (cpu_khz );
@@ -852,6 +853,60 @@ static void __init init_tsc_clocksource(void)
852853 clocksource_register (& clocksource_tsc );
853854}
854855
856+ #ifdef CONFIG_X86_64
857+ /*
858+ * calibrate_cpu is used on systems with fixed rate TSCs to determine
859+ * processor frequency
860+ */
861+ #define TICK_COUNT 100000000
862+ static unsigned long __init calibrate_cpu (void )
863+ {
864+ int tsc_start , tsc_now ;
865+ int i , no_ctr_free ;
866+ unsigned long evntsel3 = 0 , pmc3 = 0 , pmc_now = 0 ;
867+ unsigned long flags ;
868+
869+ for (i = 0 ; i < 4 ; i ++ )
870+ if (avail_to_resrv_perfctr_nmi_bit (i ))
871+ break ;
872+ no_ctr_free = (i == 4 );
873+ if (no_ctr_free ) {
874+ WARN (1 , KERN_WARNING "Warning: AMD perfctrs busy ... "
875+ "cpu_khz value may be incorrect.\n" );
876+ i = 3 ;
877+ rdmsrl (MSR_K7_EVNTSEL3 , evntsel3 );
878+ wrmsrl (MSR_K7_EVNTSEL3 , 0 );
879+ rdmsrl (MSR_K7_PERFCTR3 , pmc3 );
880+ } else {
881+ reserve_perfctr_nmi (MSR_K7_PERFCTR0 + i );
882+ reserve_evntsel_nmi (MSR_K7_EVNTSEL0 + i );
883+ }
884+ local_irq_save (flags );
885+ /* start measuring cycles, incrementing from 0 */
886+ wrmsrl (MSR_K7_PERFCTR0 + i , 0 );
887+ wrmsrl (MSR_K7_EVNTSEL0 + i , 1 << 22 | 3 << 16 | 0x76 );
888+ rdtscl (tsc_start );
889+ do {
890+ rdmsrl (MSR_K7_PERFCTR0 + i , pmc_now );
891+ tsc_now = get_cycles ();
892+ } while ((tsc_now - tsc_start ) < TICK_COUNT );
893+
894+ local_irq_restore (flags );
895+ if (no_ctr_free ) {
896+ wrmsrl (MSR_K7_EVNTSEL3 , 0 );
897+ wrmsrl (MSR_K7_PERFCTR3 , pmc3 );
898+ wrmsrl (MSR_K7_EVNTSEL3 , evntsel3 );
899+ } else {
900+ release_perfctr_nmi (MSR_K7_PERFCTR0 + i );
901+ release_evntsel_nmi (MSR_K7_EVNTSEL0 + i );
902+ }
903+
904+ return pmc_now * tsc_khz / (tsc_now - tsc_start );
905+ }
906+ #else
907+ static inline unsigned long calibrate_cpu (void ) { return cpu_khz ; }
908+ #endif
909+
855910void __init tsc_init (void )
856911{
857912 u64 lpj ;
@@ -870,11 +925,9 @@ void __init tsc_init(void)
870925 return ;
871926 }
872927
873- #ifdef CONFIG_X86_64
874928 if (cpu_has (& boot_cpu_data , X86_FEATURE_CONSTANT_TSC ) &&
875929 (boot_cpu_data .x86_vendor == X86_VENDOR_AMD ))
876930 cpu_khz = calibrate_cpu ();
877- #endif
878931
879932 printk ("Detected %lu.%03lu MHz processor.\n" ,
880933 (unsigned long )cpu_khz / 1000 ,
0 commit comments