summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorDavid P. Reed <dpreed@reed.com>2007-05-02 21:27:20 +0400
committerAndi Kleen <andi@basil.nowhere.org>2007-05-02 21:27:20 +0400
commit4637a74cf2ac3a3696d385c8624d84de789d1bbe (patch)
tree358cd844b60771697d8cff6b85c5ab7db4b96deb /arch
parent9d016dd43b8df0228f1022f483f582eeb52d256e (diff)
downloadlinux-4637a74cf2ac3a3696d385c8624d84de789d1bbe.tar.xz
[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')
-rw-r--r--arch/x86_64/kernel/apic.c11
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)
static int __init calibrate_APIC_clock(void)
{
- int apic, apic_start, tsc, tsc_start;
+ unsigned apic, apic_start;
+ unsigned long tsc, tsc_start;
int result;
/*
* Put whatever arbitrary (but long enough) timeout
* value into the APIC clock, we just want to get the
* counter running for calibration.
*/
- __setup_APIC_LVTT(1000000000);
+ __setup_APIC_LVTT(4000000000);
apic_start = apic_read(APIC_TMCCT);
#ifdef CONFIG_X86_PM_TIMER
@@ -857,13 +858,13 @@ static int __init calibrate_APIC_clock(void)
} else
#endif
{
- rdtscl(tsc_start);
+ rdtscll(tsc_start);
do {
apic = apic_read(APIC_TMCCT);
- rdtscl(tsc);
+ rdtscll(tsc);
} while ((tsc - tsc_start) < TICK_COUNT &&
- (apic - apic_start) < TICK_COUNT);
+ (apic_start - apic) < TICK_COUNT);
result = (apic_start - apic) * 1000L * tsc_khz /
(tsc - tsc_start);