From: Linus Torvalds <torvalds@linux-foundation.org>
To: Larry Finger <Larry.Finger@lwfinger.net>
Cc: Thomas Gleixner <tglx@linutronix.de>,
LKML <linux-kernel@vger.kernel.org>,
"Rafael J. Wysocki" <rjw@sisk.pl>,
Alok Kataria <akataria@vmware.com>, Michael Buesch <mb@bu3sch.de>
Subject: Re: [PATCH] Fix TSC calibration issues
Date: Tue, 2 Sep 2008 21:00:24 -0700 (PDT) [thread overview]
Message-ID: <alpine.LFD.1.10.0809022056270.3259@nehalem.linux-foundation.org> (raw)
In-Reply-To: <48BDFBB6.3010106@lwfinger.net>
On Tue, 2 Sep 2008, Larry Finger wrote:
>
> I know that Linus has some problems with this patch, but FWIW it worked on my
> K6. The dmesg output is
>
> TSC: PIT calibration deviates from PMTIMER: 428809 214401.
> TSC: Using PIT calibration value
> Detected 428.809 MHz processor.
I don't have a problem with what the patch _does_ (I think all the added
sanity checking is good).
I just don't like how it makes the already rather complex and confusing
function about ten times _more_ complex and confusing. It needs splitting
up.
But we can split it up after-the-fact as well as before-the-fact.
Does this cleanup-patch (on _top_ of Thomas' patch) also work for you? It
should do exactly the same thing, except it splits up the TSC PIT
calibration into a function of its own.
But I may obviously have introduced some silly bug when cleaning it up,
so testing necessary..
Linus
---
arch/x86/kernel/tsc.c | 132 ++++++++++++++++++++++++++----------------------
1 files changed, 71 insertions(+), 61 deletions(-)
diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c
index ac79bd1..346cae5 100644
--- a/arch/x86/kernel/tsc.c
+++ b/arch/x86/kernel/tsc.c
@@ -122,15 +122,75 @@ static u64 tsc_read_refs(u64 *pm, u64 *hpet)
return ULLONG_MAX;
}
+/*
+ * Try to calibrate the TSC against the Programmable
+ * Interrupt Timer and return the frequency of the TSC
+ * in kHz.
+ *
+ * Return ULONG_MAX on failure to calibrate.
+ */
+static unsigned long pit_calibrate_tsc(void)
+{
+ u64 tsc, t1, t2, delta;
+ unsigned long tscmin, tscmax;
+ int pitcnt;
+
+ /* Set the Gate high, disable speaker */
+ outb((inb(0x61) & ~0x02) | 0x01, 0x61);
+
+ /*
+ * Setup CTC channel 2* for mode 0, (interrupt on terminal
+ * count mode), binary count. Set the latch register to 50ms
+ * (LSB then MSB) to begin countdown.
+ */
+ outb(0xb0, 0x43);
+ outb((CLOCK_TICK_RATE / (1000 / 50)) & 0xff, 0x42);
+ outb((CLOCK_TICK_RATE / (1000 / 50)) >> 8, 0x42);
+
+ tsc = t1 = t2 = get_cycles();
+
+ pitcnt = 0;
+ tscmax = 0;
+ tscmin = ULONG_MAX;
+ while ((inb(0x61) & 0x20) == 0) {
+ t2 = get_cycles();
+ delta = t2 - tsc;
+ tsc = t2;
+ if ((unsigned long) delta < tscmin)
+ tscmin = (unsigned int) delta;
+ if ((unsigned long) delta > tscmax)
+ tscmax = (unsigned int) delta;
+ pitcnt++;
+ }
+
+ /*
+ * Sanity checks:
+ *
+ * If we were not able to read the PIT more than 5000
+ * times, then we have been hit by a massive SMI
+ *
+ * If the maximum is 10 times larger than the minimum,
+ * then we got hit by an SMI as well.
+ */
+ if (pitcnt < 5000 || tscmax > 10 * tscmin)
+ return ULONG_MAX;
+
+ /* Calculate the PIT value */
+ delta = t2 - t1;
+ do_div(delta, 50);
+ return delta;
+}
+
+
/**
* native_calibrate_tsc - calibrate the tsc on boot
*/
unsigned long native_calibrate_tsc(void)
{
- u64 tsc1, tsc2, tr1, tr2, tsc, delta, pm1, pm2, hpet1, hpet2;
+ u64 tsc1, tsc2, delta, pm1, pm2, hpet1, hpet2;
unsigned long tsc_pit_min = ULONG_MAX, tsc_ref_min = ULONG_MAX;
- unsigned long flags, tscmin, tscmax;
- int hpet = is_hpet_enabled(), pitcnt, i;
+ unsigned long flags;
+ int hpet = is_hpet_enabled(), i;
/*
* Run 5 calibration loops to get the lowest frequency value
@@ -157,72 +217,22 @@ unsigned long native_calibrate_tsc(void)
* amount of time anyway.
*/
for (i = 0; i < 5; i++) {
-
- tscmin = ULONG_MAX;
- tscmax = 0;
- pitcnt = 0;
-
- local_irq_save(flags);
+ unsigned long tsc_pit_khz;
/*
* Read the start value and the reference count of
- * hpet/pmtimer when available:
+ * hpet/pmtimer when available. Then do the PIT
+ * calibration, which will take at least 50ms, and
+ * read the end value.
*/
+ local_irq_save(flags);
tsc1 = tsc_read_refs(&pm1, hpet ? &hpet1 : NULL);
-
- /* Set the Gate high, disable speaker */
- outb((inb(0x61) & ~0x02) | 0x01, 0x61);
-
- /*
- * Setup CTC channel 2* for mode 0, (interrupt on terminal
- * count mode), binary count. Set the latch register to 50ms
- * (LSB then MSB) to begin countdown.
- *
- * Some devices need a delay here.
- */
- outb(0xb0, 0x43);
- outb((CLOCK_TICK_RATE / (1000 / 50)) & 0xff, 0x42);
- outb((CLOCK_TICK_RATE / (1000 / 50)) >> 8, 0x42);
-
- tsc = tr1 = tr2 = get_cycles();
-
- while ((inb(0x61) & 0x20) == 0) {
- tr2 = get_cycles();
- delta = tr2 - tsc;
- tsc = tr2;
- if ((unsigned int) delta < tscmin)
- tscmin = (unsigned int) delta;
- if ((unsigned int) delta > tscmax)
- tscmax = (unsigned int) delta;
- pitcnt++;
- }
-
- /*
- * We waited at least 50ms above. Now read
- * pmtimer/hpet reference again
- */
+ tsc_pit_khz = pit_calibrate_tsc();
tsc2 = tsc_read_refs(&pm2, hpet ? &hpet2 : NULL);
-
local_irq_restore(flags);
- /*
- * Sanity checks:
- *
- * If we were not able to read the PIT more than 5000
- * times, then we have been hit by a massive SMI
- *
- * If the maximum is 10 times larger than the minimum,
- * then we got hit by an SMI as well.
- */
- if (pitcnt > 5000 && tscmax < 10 * tscmin) {
-
- /* Calculate the PIT value */
- delta = tr2 - tr1;
- do_div(delta, 50);
-
- /* We take the smallest value into account */
- tsc_pit_min = min(tsc_pit_min, (unsigned long) delta);
- }
+ /* Pick the lowest PIT TSC calibration so far */
+ tsc_pit_min = min(tsc_pit_min, tsc_pit_khz);
/* hpet or pmtimer available ? */
if (!hpet && !pm1 && !pm2)
next prev parent reply other threads:[~2008-09-03 4:01 UTC|newest]
Thread overview: 56+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-08-31 22:54 Regression in 2.6.27 caused by commit bfc0f59 Larry Finger
2008-09-01 11:14 ` Thomas Gleixner
2008-09-01 15:37 ` Larry Finger
2008-09-01 17:49 ` Thomas Gleixner
2008-09-01 17:44 ` Larry Finger
2008-09-01 18:31 ` Thomas Gleixner
2008-09-01 19:10 ` Linus Torvalds
2008-09-01 20:07 ` Thomas Gleixner
2008-09-01 21:30 ` Thomas Gleixner
2008-09-01 22:02 ` Linus Torvalds
2008-09-01 22:33 ` Thomas Gleixner
2008-09-01 22:56 ` Linus Torvalds
2008-09-01 23:24 ` Thomas Gleixner
2008-09-02 6:37 ` Andi Kleen
2008-09-02 12:21 ` Thomas Gleixner
2008-09-01 22:16 ` Linus Torvalds
2008-09-01 23:16 ` Thomas Gleixner
2008-09-02 3:18 ` Linus Torvalds
2008-09-02 3:35 ` Linus Torvalds
2008-09-02 4:54 ` Larry Finger
2008-09-02 9:17 ` Alan Cox
2008-09-02 12:15 ` Thomas Gleixner
2008-09-02 15:09 ` Linus Torvalds
2008-09-02 18:14 ` Thomas Gleixner
2008-09-02 18:41 ` Alok Kataria
2008-09-02 21:16 ` Thomas Gleixner
2008-09-02 18:42 ` Linus Torvalds
2008-09-02 21:13 ` Thomas Gleixner
2008-09-02 22:21 ` Linus Torvalds
2008-09-02 23:10 ` Thomas Gleixner
2008-09-03 1:49 ` Linus Torvalds
2008-09-02 22:54 ` [PATCH] Fix TSC calibration issues Thomas Gleixner
2008-09-03 2:14 ` Linus Torvalds
2008-09-03 9:11 ` Thomas Gleixner
2008-09-04 1:14 ` Alok Kataria
2008-09-04 2:56 ` Linus Torvalds
2008-09-04 3:16 ` Arjan van de Ven
2008-09-04 3:59 ` Linus Torvalds
2008-09-04 4:10 ` Arjan van de Ven
2008-09-04 4:20 ` Linus Torvalds
2008-09-04 4:27 ` Arjan van de Ven
2008-09-04 4:25 ` Willy Tarreau
2008-09-04 4:53 ` Linus Torvalds
2008-09-04 5:09 ` Willy Tarreau
2008-09-04 1:18 ` [PATCH] Change warning message in TSC calibration Alok Kataria
2008-09-03 2:51 ` [PATCH] Fix TSC calibration issues Larry Finger
2008-09-03 4:00 ` Linus Torvalds [this message]
2008-09-03 4:34 ` Larry Finger
2008-09-05 13:45 ` Regression in 2.6.27 caused by commit bfc0f59 Mark Lord
2008-09-02 17:17 ` Bill Davidsen
2008-09-01 19:36 ` Larry Finger
2008-09-01 20:09 ` Thomas Gleixner
2008-09-01 20:23 ` Larry Finger
2008-09-01 20:45 ` Thomas Gleixner
2008-09-01 18:42 ` Linus Torvalds
2008-09-01 19:08 ` Thomas Gleixner
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=alpine.LFD.1.10.0809022056270.3259@nehalem.linux-foundation.org \
--to=torvalds@linux-foundation.org \
--cc=Larry.Finger@lwfinger.net \
--cc=akataria@vmware.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mb@bu3sch.de \
--cc=rjw@sisk.pl \
--cc=tglx@linutronix.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Powered by JetHome