x86_64: fix cpu MHz reporting on constant_tsc cpus
PATCH 1/1 x86_64: fix cpu MHz reporting on constant_tsc cpus
From: Mark Langsdorf <[email protected]>
From: Joerg Roedel <[email protected]>
This patch fixes the reporting of cpu_mhz in /proc/cpuinfo on CPUs with a constant TSC rate and a kernel with disabled cpufreq.
Signature · 3 lines
Joerg Roedel Operating System Research Center AMD Saxony LLC & Co. KG
arch/x86_64/kernel/apic.c +1 -1
@@ -839,7 +839,7 @@ static int __init calibrate_APIC_clock(void) }while ((tsc - tsc_start) <TICK_COUNT && (apic - apic_start) <TICK_COUNT ); - result = (apic_start - apic) *1000L * cpu_khz / + result = (apic_start - apic) *1000L * tsc_khz / (tsc - tsc_start); }printk ("result %d\n" , result);
arch/x86_64/kernel/nmi.c +10 -9
@@ -168,7 +168,7 @@ void release_evntsel_nmi(unsigned int msr)clear_bit (counter, &__get_cpu_var (evntsel_nmi_owner)); } -static __cpuinit inline int nmi_known_cpu (void ) +__cpuinit inline int nmi_known_cpu (void ) {switch (boot_cpu_data.x86_vendor) {case X86_VENDOR_AMD :
@@ -225,8 +225,8 @@ static unsigned int adjust_for_32bit_ctr(unsigned int hz)* 32nd bit should be 1, for 33.. to be 1. * Find the appropriate nmi_hz */ -if ((((u64 )cpu_khz *1000 ) / retval) >0x7fffffffULL ) { - retval = ((u64 )cpu_khz *1000 ) /0x7fffffffUL +1 ; +if ((((u64 )tsc_khz *1000 ) / retval) >0x7fffffffULL ) { + retval = ((u64 )tsc_khz *1000 ) /0x7fffffffUL +1 ; }return retval; }
@@ -493,7 +493,7 @@ static int setup_k7_watchdog(void)/* setup the timer */ wrmsr (evntsel_msr, evntsel,0 ); -wrmsrl (perfctr_msr, -((u64 )cpu_khz *1000 / nmi_hz)); +wrmsrl (perfctr_msr, -((u64 )tsc_khz *1000 / nmi_hz));apic_write (APIC_LVTPC ,APIC_DM_NMI ); evntsel |=K7_EVNTSEL_ENABLE ;wrmsr (evntsel_msr, evntsel,0 );
@@ -601,7 +601,7 @@ static int setup_p4_watchdog(void)wrmsr (evntsel_msr, evntsel,0 );wrmsr (cccr_msr, cccr_val,0 ); -wrmsrl (perfctr_msr, -((u64 )cpu_khz *1000 / nmi_hz)); +wrmsrl (perfctr_msr, -((u64 )tsc_khz *1000 / nmi_hz));apic_write (APIC_LVTPC ,APIC_DM_NMI ); cccr_val |=P4_CCCR_ENABLE ;wrmsr (cccr_msr, cccr_val,0 );
@@ -671,7 +671,7 @@ static int setup_intel_arch_watchdog(void)wrmsr (evntsel_msr, evntsel,0 ); nmi_hz =adjust_for_32bit_ctr (nmi_hz); -wrmsr (perfctr_msr, (u32)(-((u64 )cpu_khz *1000 / nmi_hz)),0 ); +wrmsr (perfctr_msr, (u32)(-((u64 )tsc_khz *1000 / nmi_hz)),0 );apic_write (APIC_LVTPC ,APIC_DM_NMI ); evntsel |=ARCH_PERFMON_EVENTSEL0_ENABLE ;
@@ -894,7 +894,7 @@ int __kprobes nmi_watchdog_tick(struct pt_regs * regs, unsigned reason)apic_write (APIC_LVTPC ,APIC_DM_NMI );/* start the cycle over again */ wrmsrl (wd->perfctr_msr, - -((u64 )cpu_khz *1000 / nmi_hz)); + -((u64 )tsc_khz *1000 / nmi_hz)); }else if (wd->perfctr_msr ==MSR_ARCH_PERFMON_PERFCTR0 ) {/* * ArchPerfom/Core Duo needs to re-unmask
@@ -903,11 +903,11 @@ int __kprobes nmi_watchdog_tick(struct pt_regs * regs, unsigned reason)apic_write (APIC_LVTPC ,APIC_DM_NMI );/* ARCH_PERFMON has 32 bit counter writes */ wrmsr (wd->perfctr_msr, - (u32)(-((u64 )cpu_khz *1000 / nmi_hz)),0 ); + (u32)(-((u64 )tsc_khz *1000 / nmi_hz)),0 ); }else {/* start the cycle over again */ wrmsrl (wd->perfctr_msr, - -((u64 )cpu_khz *1000 / nmi_hz)); + -((u64 )tsc_khz *1000 / nmi_hz)); } rc =1 ; }else if (nmi_watchdog ==NMI_IO_APIC ) {
@@ -1003,6 +1003,7 @@ void __trigger_all_cpu_backtrace(void) }EXPORT_SYMBOL (nmi_active); +EXPORT_SYMBOL (nmi_known_cpu);EXPORT_SYMBOL (nmi_watchdog);EXPORT_SYMBOL (avail_to_resrv_perfctr_nmi);EXPORT_SYMBOL (avail_to_resrv_perfctr_nmi_bit);
arch/x86_64/kernel/setup.c +0 -0
arch/x86_64/kernel/time.c +55 -3
87 lines not on this page · raw message
arch/x86_64/kernel/tsc.c +7 -5
@@ -13,6 +13,8 @@ static int notsc __initdata = 0;unsigned int cpu_khz;/* TSC clocks / usec, not used here */ EXPORT_SYMBOL (cpu_khz); +unsigned int tsc_khz; +EXPORT_SYMBOL (tsc_khz);static unsigned int cyc2ns_scale__read_mostly ;
@@ -77,7 +79,7 @@ static void handle_cpufreq_delayed_get(struct work_struct *v)static unsigned int ref_freq =0 ;static unsigned long loops_per_jiffy_ref =0 ; -static unsigned long cpu_khz_ref =0 ; +static unsigned long tsc_khz_ref =0 ;static int time_cpufreq_notifier (struct notifier_block *nb,unsigned long val,void *data)
@@ -99,7 +101,7 @@ static int time_cpufreq_notifier(struct notifier_block *nb, unsigned long val,if (!ref_freq) { ref_freq = freq->old; loops_per_jiffy_ref = *lpj; - cpu_khz_ref = cpu_khz; + tsc_khz_ref = tsc_khz; } if ((val == CPUFREQ_PRECHANGE && freq->old < freq->new) || (val == CPUFREQ_POSTCHANGE && freq->old > freq->new) ||
@@ -107,12 +109,12 @@ static int time_cpufreq_notifier(struct notifier_block *nb, unsigned long val, *lpj =cpufreq_scale (loops_per_jiffy_ref, ref_freq, freq->new); - cpu_khz =cpufreq_scale (cpu_khz_ref, ref_freq, freq->new); + tsc_khz =cpufreq_scale (tsc_khz_ref, ref_freq, freq->new);if (!(freq->flags &CPUFREQ_CONST_LOOPS ))mark_tsc_unstable (); } -set_cyc2ns_scale (cpu_khz_ref); +set_cyc2ns_scale (tsc_khz_ref);return 0 ; }
@@ -213,7 +215,7 @@ EXPORT_SYMBOL_GPL(mark_tsc_unstable);void __init init_tsc_clocksource (void ) {if (!notsc) { - clocksource_tsc.mult =clocksource_khz2mult (cpu_khz, + clocksource_tsc.mult =clocksource_khz2mult (tsc_khz, clocksource_tsc.shift);if (check_tsc_unstable ()) clocksource_tsc.rating =0 ;
arch/x86_64/kernel/tsc_sync.c +1 -1
@@ -50,7 +50,7 @@ static __cpuinit void check_tsc_warp(void)/* * The measurement runs for 20 msecs: */ - end = start + cpu_khz *20ULL ; + end = start + tsc_khz *20ULL ; now = start;for (i =0 ; ; i++) {
include/asm-x86_64/nmi.h +1 -0
@@ -46,6 +46,7 @@ extern int unknown_nmi_panic;extern int nmi_watchdog_enabled;extern int check_nmi_watchdog (void ); +extern int nmi_known_cpu (void );extern int avail_to_resrv_perfctr_nmi_bit (unsigned int );extern int avail_to_resrv_perfctr_nmi (unsigned int );extern int reserve_perfctr_nmi (unsigned int );
include/asm-x86_64/proto.h +1 -0
@@ -93,6 +93,7 @@ extern unsigned long table_start, table_end;extern int exception_trace;extern unsigned cpu_khz; +extern unsigned tsc_khz;extern void no_iommu_init (void );extern int force_iommu, no_iommu;
Quoted 9 lines · Joerg Roedel
From: Mark Langsdorf <[email protected]>
From: Joerg Roedel <[email protected]>This patch fixes the reporting of
cpu_mhzin/proc/cpuinfoon CPUs with a constant TSC rate and a kernel with disabled cpufreq.Signed-off-by Mark Langsdorf <[email protected]>Signed-off-by Joerg Roedel <[email protected]>
+ cpu_khz = tsc_khz;
+ if (cpu_has(&boot_cpu_data, X86_FEATURE_CONSTANT_TSC) &&
+ nmi_known_cpu()) {
+ cpu_khz = tsc_calibrate_cpu_khz();
+ }
I don't think this will do the right thing on Intel CPUs of which tsc_calibrate_cpu_khz() knows nothing about.
-Andi
Quoted 18 lines · Andi Kleen
Quoted 9 lines · Joerg Roedel
From: Mark Langsdorf <[email protected]>
From: Joerg Roedel <[email protected]>This patch fixes the reporting of
cpu_mhzin/proc/cpuinfoon CPUs with a constant TSC rate and a kernel with disabled cpufreq.Signed-off-by Mark Langsdorf <[email protected]>Signed-off-by Joerg Roedel <[email protected]>arch/x86_64/kernel/time.c +5
-0+ cpu_khz = tsc_khz; +if (cpu_has (&boot_cpu_data,X86_FEATURE_CONSTANT_TSC ) && +nmi_known_cpu ()) { + cpu_khz =tsc_calibrate_cpu_khz (); + }
Quoted 2 lines
I don't think this will do the right thing on Intel CPUs of which
tsc_calibrate_cpu_khz()knows nothing about.
Yes. You are right. I will fix that and send a new version. Thanks for the review.
Joerg
Signature · 3 lines
Joerg Roedel Operating System Research Center AMD Saxony LLC & Co. KG
Quoted 4 lines
Yes. You are right. I will fix that and send a new version. Thanks for the review.
I already fixed it up and fixed some other bugs. The changes to tsc_khz in nmi.c were wrong because the performance counters don't tick at tsc frequency.
-Andi