From: Kasper Pedersen <kernel@kasperkp.dk>
To: john stultz <johnstul@us.ibm.com>
Cc: linux-kernel@vger.kernel.org,
Thomas Gleixner <tglx@linutronix.de>,
Ingo Molnar <mingo@redhat.com>, "H. Peter Anvin" <hpa@zytor.com>,
x86@kernel.org, Peter Zijlstra <a.p.zijlstra@chello.nl>,
Suresh Siddha <suresh.b.siddha@intel.com>
Subject: Re: x86: tsc: v2 make TSC calibration more immune to interrupts
Date: Wed, 20 Apr 2011 23:22:19 +0200 [thread overview]
Message-ID: <4DAF4E8B.6030506@kasperkp.dk> (raw)
In-Reply-To: <1303331280.2796.154.camel@work-vm>
When a SMI or plain interrupt occurs during the delayed part
of TSC calibration, and the SMI/irq handler is good and fast
so that is does not exceed SMI_TRESHOLD, tsc_khz can be a bit
off (10-30ppm).
We should not depend on interrupts being longer than 50000
clocks, so, in the refined calibration, always do the 5
tries, and use the best sample we get.
This should work always for any four periodic or rate-limited
interrupt sources. If we get 5 interrupts with 500ns gaps in
a row, behaviour should be as without this patch.
It is safe to use the first value that passes SMI_TRESHOLD
for the initial calibration: As long as tsc_khz is above
100MHz, SMI_TRESHOLD represents less than 1% of error.
The 8 additional samples costs us 28 microseconds in startup
time.
measurements:
On a 700MHz P3 I see t2-t1=~22000, and 31ppm error.
A Core2 is similar: http://n1.taur.dk/tscdeviat.png
(while mostly t2-t1=~1000, in about 1 of 3000 tests
I see t2-t1=~20000 for both machines.)
vmware ESX4 has t2-t1=~8000 and up.
v2: John Stulz suggested limiting best uncertainty to
where it is needed, saving ~170usec startup time.
Signed-off-by: Kasper Pedersen <kernel@kasperkp.dk>
---
arch/x86/kernel/tsc.c | 36 ++++++++++++++++++++++++------------
1 files changed, 24 insertions(+), 12 deletions(-)
diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c
index ffe5755..8dc813b 100644
--- a/arch/x86/kernel/tsc.c
+++ b/arch/x86/kernel/tsc.c
@@ -117,27 +117,39 @@ static int __init tsc_setup(char *str)
__setup("tsc=", tsc_setup);
-#define MAX_RETRIES 5
+#define BESTOF_SAMPLES 5
#define SMI_TRESHOLD 50000
/*
* Read TSC and the reference counters. Take care of SMI disturbance
*/
-static u64 tsc_read_refs(u64 *p, int hpet)
+static u64 tsc_read_refs(u64 *p, int hpet, int find_best)
{
- u64 t1, t2;
+ u64 t1, t2, tp, best_uncertainty, uncertainty, best_t2;
int i;
- for (i = 0; i < MAX_RETRIES; i++) {
+ best_uncertainty = SMI_TRESHOLD;
+ best_t2 = 0;
+ for (i = 0; i < BESTOF_SAMPLES; i++) {
t1 = get_cycles();
if (hpet)
- *p = hpet_readl(HPET_COUNTER) & 0xFFFFFFFF;
+ tp = hpet_readl(HPET_COUNTER) & 0xFFFFFFFF;
else
- *p = acpi_pm_read_early();
+ tp = acpi_pm_read_early();
t2 = get_cycles();
- if ((t2 - t1) < SMI_TRESHOLD)
- return t2;
+ uncertainty = t2 - t1;
+ if (uncertainty < best_uncertainty) {
+ best_uncertainty = uncertainty;
+ best_t2 = t2;
+ *p = tp;
+ if (!find_best)
+ break;
+ }
}
+ if (best_uncertainty < SMI_TRESHOLD)
+ return best_t2;
+
+ *p = tp;
return ULLONG_MAX;
}
@@ -455,9 +467,9 @@ unsigned long native_calibrate_tsc(void)
* read the end value.
*/
local_irq_save(flags);
- tsc1 = tsc_read_refs(&ref1, hpet);
+ tsc1 = tsc_read_refs(&ref1, hpet, 0);
tsc_pit_khz = pit_calibrate_tsc(latch, ms, loopmin);
- tsc2 = tsc_read_refs(&ref2, hpet);
+ tsc2 = tsc_read_refs(&ref2, hpet, 0);
local_irq_restore(flags);
/* Pick the lowest PIT TSC calibration so far */
@@ -928,11 +940,11 @@ static void tsc_refine_calibration_work(struct work_struct *work)
*/
hpet = is_hpet_enabled();
schedule_delayed_work(&tsc_irqwork, HZ);
- tsc_start = tsc_read_refs(&ref_start, hpet);
+ tsc_start = tsc_read_refs(&ref_start, hpet, 1);
return;
}
- tsc_stop = tsc_read_refs(&ref_stop, hpet);
+ tsc_stop = tsc_read_refs(&ref_stop, hpet, 1);
/* hpet or pmtimer available ? */
if (ref_start == ref_stop)
next prev parent reply other threads:[~2011-04-20 21:23 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-04-20 18:52 x86: tsc: make TSC calibration more immune to interrupts Kasper Pedersen
2011-04-20 19:15 ` john stultz
2011-04-20 19:44 ` Kasper Pedersen
2011-04-20 20:28 ` john stultz
2011-04-20 21:22 ` Kasper Pedersen [this message]
2011-04-20 22:39 ` x86: tsc: v2 " Josh Triplett
2011-04-21 2:19 ` john stultz
2011-04-21 4:32 ` Josh Triplett
2011-04-21 19:46 ` Kasper Pedersen
2011-04-23 1:38 ` john stultz
2011-04-21 19:52 ` x86: tsc: v3 " Kasper Pedersen
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=4DAF4E8B.6030506@kasperkp.dk \
--to=kernel@kasperkp.dk \
--cc=a.p.zijlstra@chello.nl \
--cc=hpa@zytor.com \
--cc=johnstul@us.ibm.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@redhat.com \
--cc=suresh.b.siddha@intel.com \
--cc=tglx@linutronix.de \
--cc=x86@kernel.org \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.