diff options
author | David P. Reed <dpreed@reed.com> | 2007-05-02 13:27:20 -0400 |
---|---|---|
committer | Andi Kleen <andi@basil.nowhere.org> | 2007-05-02 13:27:20 -0400 |
commit | 4637a74cf2ac3a3696d385c8624d84de789d1bbe (patch) | |
tree | 358cd844b60771697d8cff6b85c5ab7db4b96deb /arch/x86_64 | |
parent | 9d016dd43b8df0228f1022f483f582eeb52d256e (diff) |
[PATCH] x86-64: Avoid overflows during apic timer calibration
- Use 64bit TSC calculations to avoid handling overflow
- Use 32bit unsigned arithmetic for the APIC timer. This
way overflows are handled correctly.
- Fix exit check of loop to account for apic timer counting down
Signed-off-by: dpreed@reed.com
Signed-off-by: Andi Kleen <ak@suse.de>
Diffstat (limited to 'arch/x86_64')
-rw-r--r-- | arch/x86_64/kernel/apic.c | 11 |
1 files changed, 6 insertions, 5 deletions
diff --git a/arch/x86_64/kernel/apic.c b/arch/x86_64/kernel/apic.c index 943ec4d1bd8e..d198f7d82e5a 100644 --- a/arch/x86_64/kernel/apic.c +++ b/arch/x86_64/kernel/apic.c | |||
@@ -839,14 +839,15 @@ static void setup_APIC_timer(unsigned int clocks) | |||
839 | 839 | ||
840 | static int __init calibrate_APIC_clock(void) | 840 | static int __init calibrate_APIC_clock(void) |
841 | { | 841 | { |
842 | int apic, apic_start, tsc, tsc_start; | 842 | unsigned apic, apic_start; |
843 | unsigned long tsc, tsc_start; | ||
843 | int result; | 844 | int result; |
844 | /* | 845 | /* |
845 | * Put whatever arbitrary (but long enough) timeout | 846 | * Put whatever arbitrary (but long enough) timeout |
846 | * value into the APIC clock, we just want to get the | 847 | * value into the APIC clock, we just want to get the |
847 | * counter running for calibration. | 848 | * counter running for calibration. |
848 | */ | 849 | */ |
849 | __setup_APIC_LVTT(1000000000); | 850 | __setup_APIC_LVTT(4000000000); |
850 | 851 | ||
851 | apic_start = apic_read(APIC_TMCCT); | 852 | apic_start = apic_read(APIC_TMCCT); |
852 | #ifdef CONFIG_X86_PM_TIMER | 853 | #ifdef CONFIG_X86_PM_TIMER |
@@ -857,13 +858,13 @@ static int __init calibrate_APIC_clock(void) | |||
857 | } else | 858 | } else |
858 | #endif | 859 | #endif |
859 | { | 860 | { |
860 | rdtscl(tsc_start); | 861 | rdtscll(tsc_start); |
861 | 862 | ||
862 | do { | 863 | do { |
863 | apic = apic_read(APIC_TMCCT); | 864 | apic = apic_read(APIC_TMCCT); |
864 | rdtscl(tsc); | 865 | rdtscll(tsc); |
865 | } while ((tsc - tsc_start) < TICK_COUNT && | 866 | } while ((tsc - tsc_start) < TICK_COUNT && |
866 | (apic - apic_start) < TICK_COUNT); | 867 | (apic_start - apic) < TICK_COUNT); |
867 | 868 | ||
868 | result = (apic_start - apic) * 1000L * tsc_khz / | 869 | result = (apic_start - apic) * 1000L * tsc_khz / |
869 | (tsc - tsc_start); | 870 | (tsc - tsc_start); |