diff options
author | Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com> | 2009-01-27 22:51:09 -0500 |
---|---|---|
committer | H. Peter Anvin <hpa@linux.intel.com> | 2009-01-29 20:06:03 -0500 |
commit | 754ef0cd65faac4840ada4362bda322d9a811fbf (patch) | |
tree | ecbefbee7ab44bd915a2e2cceeebab2ac7a382ef /arch/x86/kernel | |
parent | 5ee810072175042775e39bdd3eaaa68884c27805 (diff) |
x86: fix debug message of CPU clock speed
Impact: Fixes incorrect printk
LOCAL APIC is corrected by PM-Timer, when SMI occurred while LOCAL APIC is calibrated.
In this case, LOCAL APIC debug message(Boot with apic=debug) is displayed correctly,
however, CPU clock speed debug message is displayed wrongly .
When SMI occured on my machine, which has 1.6GHz CPU, CPU clock speed is displayed
3622.0205 MHz as follow.
CPU0: Intel(R) Xeon(R) CPU 5110 @ 1.60GHz stepping 06
Using local APIC timer interrupts.
calibrating APIC timer ...
... lapic delta = 3773130
... PM timer delta = 812434
APIC calibration not consistent with PM Timer: 226ms instead of 100ms
APIC delta adjusted to PM-Timer: 1662420 (3773130)
..... delta 1662420
..... mult: 71411249
..... calibration result: 265987
..... CPU clock speed is 3622.0205 MHz. =====> here
..... host bus clock speed is 265.0987 MHz.
This patch fixes to displaying CPU clock speed correctly as follow.
CPU0: Intel(R) Xeon(R) CPU 5110 @ 1.60GHz stepping 06
Using local APIC timer interrupts.
calibrating APIC timer ...
... lapic delta = 3773131
... PM timer delta = 812434
APIC calibration not consistent with PM Timer: 226ms instead of 100ms
APIC delta adjusted to PM-Timer: 1662420 (3773131)
TSC delta adjusted to PM-Timer: 159592409 (362220564)
..... delta 1662420
..... mult: 71411249
..... calibration result: 265987
..... CPU clock speed is 1595.0924 MHz.
..... host bus clock speed is 265.0987 MHz.
Signed-off-by: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com>
Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
Diffstat (limited to 'arch/x86/kernel')
-rw-r--r-- | arch/x86/kernel/apic.c | 47 |
1 files changed, 30 insertions, 17 deletions
diff --git a/arch/x86/kernel/apic.c b/arch/x86/kernel/apic.c index 4b6df2469fe3..7bcd746d704c 100644 --- a/arch/x86/kernel/apic.c +++ b/arch/x86/kernel/apic.c | |||
@@ -535,7 +535,8 @@ static void __init lapic_cal_handler(struct clock_event_device *dev) | |||
535 | } | 535 | } |
536 | } | 536 | } |
537 | 537 | ||
538 | static int __init calibrate_by_pmtimer(long deltapm, long *delta) | 538 | static int __init |
539 | calibrate_by_pmtimer(long deltapm, long *delta, long *deltatsc) | ||
539 | { | 540 | { |
540 | const long pm_100ms = PMTMR_TICKS_PER_SEC / 10; | 541 | const long pm_100ms = PMTMR_TICKS_PER_SEC / 10; |
541 | const long pm_thresh = pm_100ms / 100; | 542 | const long pm_thresh = pm_100ms / 100; |
@@ -557,18 +558,29 @@ static int __init calibrate_by_pmtimer(long deltapm, long *delta) | |||
557 | if (deltapm > (pm_100ms - pm_thresh) && | 558 | if (deltapm > (pm_100ms - pm_thresh) && |
558 | deltapm < (pm_100ms + pm_thresh)) { | 559 | deltapm < (pm_100ms + pm_thresh)) { |
559 | apic_printk(APIC_VERBOSE, "... PM timer result ok\n"); | 560 | apic_printk(APIC_VERBOSE, "... PM timer result ok\n"); |
560 | } else { | 561 | return 0; |
561 | res = (((u64)deltapm) * mult) >> 22; | 562 | } |
562 | do_div(res, 1000000); | 563 | |
563 | pr_warning("APIC calibration not consistent " | 564 | res = (((u64)deltapm) * mult) >> 22; |
564 | "with PM Timer: %ldms instead of 100ms\n", | 565 | do_div(res, 1000000); |
565 | (long)res); | 566 | pr_warning("APIC calibration not consistent " |
566 | /* Correct the lapic counter value */ | 567 | "with PM Timer: %ldms instead of 100ms\n",(long)res); |
567 | res = (((u64)(*delta)) * pm_100ms); | 568 | |
569 | /* Correct the lapic counter value */ | ||
570 | res = (((u64)(*delta)) * pm_100ms); | ||
571 | do_div(res, deltapm); | ||
572 | pr_info("APIC delta adjusted to PM-Timer: " | ||
573 | "%lu (%ld)\n", (unsigned long)res, *delta); | ||
574 | *delta = (long)res; | ||
575 | |||
576 | /* Correct the tsc counter value */ | ||
577 | if (cpu_has_tsc) { | ||
578 | res = (((u64)(*deltatsc)) * pm_100ms); | ||
568 | do_div(res, deltapm); | 579 | do_div(res, deltapm); |
569 | pr_info("APIC delta adjusted to PM-Timer: " | 580 | apic_printk(APIC_VERBOSE, "TSC delta adjusted to " |
570 | "%lu (%ld)\n", (unsigned long)res, *delta); | 581 | "PM-Timer: %lu (%ld) \n", |
571 | *delta = (long)res; | 582 | (unsigned long)res, *deltatsc); |
583 | *deltatsc = (long)res; | ||
572 | } | 584 | } |
573 | 585 | ||
574 | return 0; | 586 | return 0; |
@@ -579,7 +591,7 @@ static int __init calibrate_APIC_clock(void) | |||
579 | struct clock_event_device *levt = &__get_cpu_var(lapic_events); | 591 | struct clock_event_device *levt = &__get_cpu_var(lapic_events); |
580 | void (*real_handler)(struct clock_event_device *dev); | 592 | void (*real_handler)(struct clock_event_device *dev); |
581 | unsigned long deltaj; | 593 | unsigned long deltaj; |
582 | long delta; | 594 | long delta, deltatsc; |
583 | int pm_referenced = 0; | 595 | int pm_referenced = 0; |
584 | 596 | ||
585 | local_irq_disable(); | 597 | local_irq_disable(); |
@@ -609,9 +621,11 @@ static int __init calibrate_APIC_clock(void) | |||
609 | delta = lapic_cal_t1 - lapic_cal_t2; | 621 | delta = lapic_cal_t1 - lapic_cal_t2; |
610 | apic_printk(APIC_VERBOSE, "... lapic delta = %ld\n", delta); | 622 | apic_printk(APIC_VERBOSE, "... lapic delta = %ld\n", delta); |
611 | 623 | ||
624 | deltatsc = (long)(lapic_cal_tsc2 - lapic_cal_tsc1); | ||
625 | |||
612 | /* we trust the PM based calibration if possible */ | 626 | /* we trust the PM based calibration if possible */ |
613 | pm_referenced = !calibrate_by_pmtimer(lapic_cal_pm2 - lapic_cal_pm1, | 627 | pm_referenced = !calibrate_by_pmtimer(lapic_cal_pm2 - lapic_cal_pm1, |
614 | &delta); | 628 | &delta, &deltatsc); |
615 | 629 | ||
616 | /* Calculate the scaled math multiplication factor */ | 630 | /* Calculate the scaled math multiplication factor */ |
617 | lapic_clockevent.mult = div_sc(delta, TICK_NSEC * LAPIC_CAL_LOOPS, | 631 | lapic_clockevent.mult = div_sc(delta, TICK_NSEC * LAPIC_CAL_LOOPS, |
@@ -629,11 +643,10 @@ static int __init calibrate_APIC_clock(void) | |||
629 | calibration_result); | 643 | calibration_result); |
630 | 644 | ||
631 | if (cpu_has_tsc) { | 645 | if (cpu_has_tsc) { |
632 | delta = (long)(lapic_cal_tsc2 - lapic_cal_tsc1); | ||
633 | apic_printk(APIC_VERBOSE, "..... CPU clock speed is " | 646 | apic_printk(APIC_VERBOSE, "..... CPU clock speed is " |
634 | "%ld.%04ld MHz.\n", | 647 | "%ld.%04ld MHz.\n", |
635 | (delta / LAPIC_CAL_LOOPS) / (1000000 / HZ), | 648 | (deltatsc / LAPIC_CAL_LOOPS) / (1000000 / HZ), |
636 | (delta / LAPIC_CAL_LOOPS) % (1000000 / HZ)); | 649 | (deltatsc / LAPIC_CAL_LOOPS) % (1000000 / HZ)); |
637 | } | 650 | } |
638 | 651 | ||
639 | apic_printk(APIC_VERBOSE, "..... host bus clock speed is " | 652 | apic_printk(APIC_VERBOSE, "..... host bus clock speed is " |