aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86_64/kernel/time.c
diff options
context:
space:
mode:
authorJoerg Roedel <joerg.roedel@amd.com>2007-05-02 13:27:06 -0400
committerAndi Kleen <andi@basil.nowhere.org>2007-05-02 13:27:06 -0400
commit6b37f5a20c0e5c334c010a587058354215433e92 (patch)
treede875cded9229b46f94a10aa2c1379060247280e /arch/x86_64/kernel/time.c
parentfbc16f2c2a0e16dbd75ac85d3b6db97f92b642ba (diff)
[PATCH] x86-64: fix cpu MHz reporting on constant_tsc cpus
This patch fixes the reporting of cpu_mhz in /proc/cpuinfo on CPUs with a constant TSC rate and a kernel with disabled cpufreq. Signed-off-by: Mark Langsdorf <mark.langsdorf@amd.com> Signed-off-by: Joerg Roedel <joerg.roedel@amd.com> Signed-off-by: Andi Kleen <ak@suse.de> arch/x86_64/kernel/apic.c | 2 - arch/x86_64/kernel/time.c | 58 +++++++++++++++++++++++++++++++++++++++--- arch/x86_64/kernel/tsc.c | 12 +++++--- arch/x86_64/kernel/tsc_sync.c | 2 - include/asm-x86_64/proto.h | 1 5 files changed, 65 insertions(+), 10 deletions(-)
Diffstat (limited to 'arch/x86_64/kernel/time.c')
-rw-r--r--arch/x86_64/kernel/time.c58
1 files changed, 55 insertions, 3 deletions
diff --git a/arch/x86_64/kernel/time.c b/arch/x86_64/kernel/time.c
index 811b8f987b50..5f862e216a42 100644
--- a/arch/x86_64/kernel/time.c
+++ b/arch/x86_64/kernel/time.c
@@ -43,6 +43,7 @@
43#include <asm/apic.h> 43#include <asm/apic.h>
44#include <asm/hpet.h> 44#include <asm/hpet.h>
45#include <asm/mpspec.h> 45#include <asm/mpspec.h>
46#include <asm/nmi.h>
46 47
47static char *timename = NULL; 48static char *timename = NULL;
48 49
@@ -249,6 +250,51 @@ static unsigned long get_cmos_time(void)
249 return mktime(year, mon, day, hour, min, sec); 250 return mktime(year, mon, day, hour, min, sec);
250} 251}
251 252
253/* calibrate_cpu is used on systems with fixed rate TSCs to determine
254 * processor frequency */
255#define TICK_COUNT 100000000
256static unsigned int __init tsc_calibrate_cpu_khz(void)
257{
258 int tsc_start, tsc_now;
259 int i, no_ctr_free;
260 unsigned long evntsel3 = 0, pmc3 = 0, pmc_now = 0;
261 unsigned long flags;
262
263 for (i = 0; i < 4; i++)
264 if (avail_to_resrv_perfctr_nmi_bit(i))
265 break;
266 no_ctr_free = (i == 4);
267 if (no_ctr_free) {
268 i = 3;
269 rdmsrl(MSR_K7_EVNTSEL3, evntsel3);
270 wrmsrl(MSR_K7_EVNTSEL3, 0);
271 rdmsrl(MSR_K7_PERFCTR3, pmc3);
272 } else {
273 reserve_perfctr_nmi(MSR_K7_PERFCTR0 + i);
274 reserve_evntsel_nmi(MSR_K7_EVNTSEL0 + i);
275 }
276 local_irq_save(flags);
277 /* start meauring cycles, incrementing from 0 */
278 wrmsrl(MSR_K7_PERFCTR0 + i, 0);
279 wrmsrl(MSR_K7_EVNTSEL0 + i, 1 << 22 | 3 << 16 | 0x76);
280 rdtscl(tsc_start);
281 do {
282 rdmsrl(MSR_K7_PERFCTR0 + i, pmc_now);
283 tsc_now = get_cycles_sync();
284 } while ((tsc_now - tsc_start) < TICK_COUNT);
285
286 local_irq_restore(flags);
287 if (no_ctr_free) {
288 wrmsrl(MSR_K7_EVNTSEL3, 0);
289 wrmsrl(MSR_K7_PERFCTR3, pmc3);
290 wrmsrl(MSR_K7_EVNTSEL3, evntsel3);
291 } else {
292 release_perfctr_nmi(MSR_K7_PERFCTR0 + i);
293 release_evntsel_nmi(MSR_K7_EVNTSEL0 + i);
294 }
295
296 return pmc_now * tsc_khz / (tsc_now - tsc_start);
297}
252 298
253/* 299/*
254 * pit_calibrate_tsc() uses the speaker output (channel 2) of 300 * pit_calibrate_tsc() uses the speaker output (channel 2) of
@@ -336,14 +382,20 @@ void __init time_init(void)
336 if (hpet_use_timer) { 382 if (hpet_use_timer) {
337 /* set tick_nsec to use the proper rate for HPET */ 383 /* set tick_nsec to use the proper rate for HPET */
338 tick_nsec = TICK_NSEC_HPET; 384 tick_nsec = TICK_NSEC_HPET;
339 cpu_khz = hpet_calibrate_tsc(); 385 tsc_khz = hpet_calibrate_tsc();
340 timename = "HPET"; 386 timename = "HPET";
341 } else { 387 } else {
342 pit_init(); 388 pit_init();
343 cpu_khz = pit_calibrate_tsc(); 389 tsc_khz = pit_calibrate_tsc();
344 timename = "PIT"; 390 timename = "PIT";
345 } 391 }
346 392
393 cpu_khz = tsc_khz;
394 if (cpu_has(&boot_cpu_data, X86_FEATURE_CONSTANT_TSC) &&
395 boot_cpu_data.x86_vendor == X86_VENDOR_AMD &&
396 boot_cpu_data.x86 == 16)
397 cpu_khz = tsc_calibrate_cpu_khz();
398
347 if (unsynchronized_tsc()) 399 if (unsynchronized_tsc())
348 mark_tsc_unstable(); 400 mark_tsc_unstable();
349 401
@@ -352,7 +404,7 @@ void __init time_init(void)
352 else 404 else
353 vgetcpu_mode = VGETCPU_LSL; 405 vgetcpu_mode = VGETCPU_LSL;
354 406
355 set_cyc2ns_scale(cpu_khz); 407 set_cyc2ns_scale(tsc_khz);
356 printk(KERN_INFO "time.c: Detected %d.%03d MHz processor.\n", 408 printk(KERN_INFO "time.c: Detected %d.%03d MHz processor.\n",
357 cpu_khz / 1000, cpu_khz % 1000); 409 cpu_khz / 1000, cpu_khz % 1000);
358 init_tsc_clocksource(); 410 init_tsc_clocksource();