[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <alpine.LFD.2.00.0903102107580.29264@localhost.localdomain>
Date: Tue, 10 Mar 2009 23:22:06 +0100 (CET)
From: Thomas Gleixner <tglx@...utronix.de>
To: Jesper Krogh <jesper@...gh.cc>
cc: Linus Torvalds <torvalds@...ux-foundation.org>,
john stultz <johnstul@...ibm.com>,
Linux Kernel Mailing List <linux-kernel@...r.kernel.org>,
Len Brown <len.brown@...el.com>, Ingo Molnar <mingo@...e.hu>
Subject: Re: Linux 2.6.29-rc6
Jesper,
On Tue, 10 Mar 2009, Jesper Krogh wrote:
> First boot:
> [ 0.000000] Fast TSC calibration using PIT
> [ 0.000000] tsc 34202223 tscmin 474069 tscmax 500664
> Second boot:
> Here I didnt get above messages.. http://krogh.cc/~jesper/dmesg-boot2.txt
> Third boot:
> [ 0.000000] Fast TSC calibration using PIT
> [ 0.000000] tsc 34199856 tscmin 470321 tscmax 502182
> Forth boot:
> [ 0.000000] Fast TSC calibration using PIT
> [ 0.000000] tsc 34202008 tscmin 475510 tscmax 501501
>
> The second one is really strange.. is'nt it?
No, there simply the fast PIT calibration failed and it dropped into
the slow path:
[ 0.000000] TSC: PIT calibration matches PMTIMER. 1 loops
[ 0.000000] Detected 2311.878 MHz processor.
But the variance of the third run is interesting:
avg = tsc / loops = 495650
avg - tscmin = 25329 (~ 10.9 us)
tscmax - avg = 6532 (~ 2.8 us)
While this is in the range which the PIT calibration code accepts the
resulting CPU frequency of this run is 2310.159 MHz which is way off
the result of the slow path in the 2nd run. The 1st and the 4th run
have significant high variance as well.
I run the same patch on a couple of test machines and all have
deviations from avg in the range of +/- 2 us and the calibration
result is stable and correct.
I have no idea what might cause the problem with your machine. PIT via
SMM emulation comes to mind :)
But we can use the tscmin/max method to figure out whether the fast
PIT result is reliable. See patch below. It should drop out into the
slow calibration path on every boot on your machine.
(tscmax - tscmin) / avg = 0.064 (result from third run)
On my test machines I get values below 0.02
While it's statistically not really correct we still can use that info
to catch cases like we see on your machines.
> While booting up I saw this one on the serial console..
> root@...d12:~# hwclock --systohc
> Cannot access the Hardware Clock via any known method.
> Use the --debug option to see the details of our search for an access method.
> root@...d12:~# hwclock --systohc --debug
> hwclock from util-linux-ng 2.13.1
> hwclock: Open of /dev/rtc failed, errno=2: No such file or directory.
> No usable clock interface found.
> Cannot access the Hardware Clock via any known method.
Can you provide your .config file please ?
Thanks,
tglx
--------->
Subject: x86: make TSC fast calibration more robust
From: Thomas Gleixner <tglx@...utronix.de>
Date: Tue, 10 Mar 2009 11:12:03 +0100
Check the min/max duration of each PIT loop against the resulting
average value and dismiss the fast calibration if it's larger than
2.5%. 2.5% is in the range of +/- 2us, which is a reasonable range
when we assume that a PIT read can easily take 1 us.
Signed-off-by: Thomas Gleixner <tglx@...utronix.de>
---
arch/x86/kernel/tsc.c | 30 +++++++++++++++++++++++++++---
1 file changed, 27 insertions(+), 3 deletions(-)
Index: linux-2.6/arch/x86/kernel/tsc.c
===================================================================
--- linux-2.6.orig/arch/x86/kernel/tsc.c
+++ linux-2.6/arch/x86/kernel/tsc.c
@@ -317,15 +317,22 @@ static unsigned long quick_pit_calibrate
if (pit_expect_msb(0xff)) {
int i;
- u64 t1, t2, delta;
+ u64 t1, t2, t3, delta;
unsigned char expect = 0xfe;
+ unsigned long tscmin = ULONG_MAX, tscmax = 0;
- t1 = get_cycles();
+ t1 = t2 = get_cycles();
for (i = 0; i < QUICK_PIT_ITERATIONS; i++, expect--) {
if (!pit_expect_msb(expect))
goto failed;
+ t3 = get_cycles();
+ delta = t3 - t2;
+ t2 = t3;
+ if ((unsigned long) delta < tscmin)
+ tscmin = (unsigned long) delta;
+ if ((unsigned long) delta > tscmax)
+ tscmax = (unsigned long) delta;
}
- t2 = get_cycles();
/*
* Make sure we can rely on the second TSC timestamp:
@@ -334,6 +341,23 @@ static unsigned long quick_pit_calibrate
goto failed;
/*
+ * Sanity check the min max values:
+ *
+ * We calculate the average tsc increment per loop
+ * step. Now we take the tscmin and tscmax value and
+ * check whether the deviation is inside an acceptable
+ * range.
+ */
+ delta = (t2 - t1);
+ do_div(delta, QUICK_PIT_ITERATIONS);
+ t3 = (unsigned long) delta;
+ delta = tscmax - tscmin;
+ delta *= 10000;
+ do_div(delta, t3);
+ /* Fail if the deviation is > 2.5 % */
+ if (delta > 250)
+ goto failed;
+ /*
* Ok, if we get here, then we've seen the
* MSB of the PIT decrement QUICK_PIT_ITERATIONS
* times, and each MSB had many hits, so we never
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists