Commit 45738bdd authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] ppc64: fix sched_clock, from Paul Mackerras:

From: Anton Blanchard <anton@samba.org>

Currently the sched_clock implementation for PPC64 is bogus.  It just reads
the timebase register, which counts at some fixed rate, typically around
100MHz.  This patch adds code to calculate a suitable multiplier from the
timebase frequency, and use that in sched_clock().
parent eabb2c77
...@@ -91,6 +91,9 @@ unsigned tb_to_us; ...@@ -91,6 +91,9 @@ unsigned tb_to_us;
unsigned long processor_freq; unsigned long processor_freq;
spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED; spinlock_t rtc_lock = SPIN_LOCK_UNLOCKED;
unsigned long tb_to_ns_scale;
unsigned long tb_to_ns_shift;
struct gettimeofday_struct do_gtod; struct gettimeofday_struct do_gtod;
extern unsigned long wall_jiffies; extern unsigned long wall_jiffies;
...@@ -313,11 +316,13 @@ int timer_interrupt(struct pt_regs * regs) ...@@ -313,11 +316,13 @@ int timer_interrupt(struct pt_regs * regs)
/* /*
* Scheduler clock - returns current time in nanosec units. * Scheduler clock - returns current time in nanosec units.
* *
* This is wrong, but my CPUs run at 1GHz, so nyer nyer. * Note: mulhdu(a, b) (multiply high double unsigned) returns
* the high 64 bits of a * b, i.e. (a * b) >> 64, where a and b
* are 64-bit unsigned numbers.
*/ */
unsigned long long sched_clock(void) unsigned long long sched_clock(void)
{ {
return get_tb(); return mulhdu(get_tb(), tb_to_ns_scale) << tb_to_ns_shift;
} }
/* /*
...@@ -473,9 +478,30 @@ void __init time_init(void) ...@@ -473,9 +478,30 @@ void __init time_init(void)
/* This function is only called on the boot processor */ /* This function is only called on the boot processor */
unsigned long flags; unsigned long flags;
struct rtc_time tm; struct rtc_time tm;
struct div_result res;
unsigned long scale, shift;
ppc_md.calibrate_decr(); ppc_md.calibrate_decr();
/*
* Compute scale factor for sched_clock.
* The calibrate_decr() function has set tb_ticks_per_sec,
* which is the timebase frequency.
* We compute 1e9 * 2^64 / tb_ticks_per_sec and interpret
* the 128-bit result as a 64.64 fixed-point number.
* We then shift that number right until it is less than 1.0,
* giving us the scale factor and shift count to use in
* sched_clock().
*/
div128_by_32(1000000000, 0, tb_ticks_per_sec, &res);
scale = res.result_low;
for (shift = 0; res.result_high != 0; ++shift) {
scale = (scale >> 1) | (res.result_high << 63);
res.result_high >>= 1;
}
tb_to_ns_scale = scale;
tb_to_ns_shift = shift;
#ifdef CONFIG_PPC_ISERIES #ifdef CONFIG_PPC_ISERIES
if (!piranha_simulator) if (!piranha_simulator)
#endif #endif
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment