aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/kernel/tsc.c95
1 files changed, 58 insertions, 37 deletions
diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c
index 52284d31fc9..da033b5b3e1 100644
--- a/arch/x86/kernel/tsc.c
+++ b/arch/x86/kernel/tsc.c
@@ -159,9 +159,14 @@ static unsigned long calc_pmtimer_ref(u64 deltatsc, u64 pm1, u64 pm2)
159 return (unsigned long) deltatsc; 159 return (unsigned long) deltatsc;
160} 160}
161 161
162#define CAL_MS 50 162#define CAL_MS 10
163#define CAL_LATCH (CLOCK_TICK_RATE / (1000 / CAL_MS)) 163#define CAL_LATCH (CLOCK_TICK_RATE / (1000 / CAL_MS))
164#define CAL_PIT_LOOPS 5000 164#define CAL_PIT_LOOPS 1000
165
166#define CAL2_MS 50
167#define CAL2_LATCH (CLOCK_TICK_RATE / (1000 / CAL2_MS))
168#define CAL2_PIT_LOOPS 5000
169
165 170
166/* 171/*
167 * Try to calibrate the TSC against the Programmable 172 * Try to calibrate the TSC against the Programmable
@@ -170,7 +175,7 @@ static unsigned long calc_pmtimer_ref(u64 deltatsc, u64 pm1, u64 pm2)
170 * 175 *
171 * Return ULONG_MAX on failure to calibrate. 176 * Return ULONG_MAX on failure to calibrate.
172 */ 177 */
173static unsigned long pit_calibrate_tsc(void) 178static unsigned long pit_calibrate_tsc(u32 latch, unsigned long ms, int loopmin)
174{ 179{
175 u64 tsc, t1, t2, delta; 180 u64 tsc, t1, t2, delta;
176 unsigned long tscmin, tscmax; 181 unsigned long tscmin, tscmax;
@@ -185,8 +190,8 @@ static unsigned long pit_calibrate_tsc(void)
185 * (LSB then MSB) to begin countdown. 190 * (LSB then MSB) to begin countdown.
186 */ 191 */
187 outb(0xb0, 0x43); 192 outb(0xb0, 0x43);
188 outb(CAL_LATCH & 0xff, 0x42); 193 outb(latch & 0xff, 0x42);
189 outb(CAL_LATCH >> 8, 0x42); 194 outb(latch >> 8, 0x42);
190 195
191 tsc = t1 = t2 = get_cycles(); 196 tsc = t1 = t2 = get_cycles();
192 197
@@ -207,18 +212,18 @@ static unsigned long pit_calibrate_tsc(void)
207 /* 212 /*
208 * Sanity checks: 213 * Sanity checks:
209 * 214 *
210 * If we were not able to read the PIT more than PIT_MIN_LOOPS 215 * If we were not able to read the PIT more than loopmin
211 * times, then we have been hit by a massive SMI 216 * times, then we have been hit by a massive SMI
212 * 217 *
213 * If the maximum is 10 times larger than the minimum, 218 * If the maximum is 10 times larger than the minimum,
214 * then we got hit by an SMI as well. 219 * then we got hit by an SMI as well.
215 */ 220 */
216 if (pitcnt < CAL_PIT_LOOPS || tscmax > 10 * tscmin) 221 if (pitcnt < loopmin || tscmax > 10 * tscmin)
217 return ULONG_MAX; 222 return ULONG_MAX;
218 223
219 /* Calculate the PIT value */ 224 /* Calculate the PIT value */
220 delta = t2 - t1; 225 delta = t2 - t1;
221 do_div(delta, CAL_MS); 226 do_div(delta, ms);
222 return delta; 227 return delta;
223} 228}
224 229
@@ -230,8 +235,8 @@ unsigned long native_calibrate_tsc(void)
230{ 235{
231 u64 tsc1, tsc2, delta, ref1, ref2; 236 u64 tsc1, tsc2, delta, ref1, ref2;
232 unsigned long tsc_pit_min = ULONG_MAX, tsc_ref_min = ULONG_MAX; 237 unsigned long tsc_pit_min = ULONG_MAX, tsc_ref_min = ULONG_MAX;
233 unsigned long flags; 238 unsigned long flags, latch, ms;
234 int hpet = is_hpet_enabled(), i; 239 int hpet = is_hpet_enabled(), i, loopmin;
235 240
236 /* 241 /*
237 * Run 5 calibration loops to get the lowest frequency value 242 * Run 5 calibration loops to get the lowest frequency value
@@ -257,7 +262,13 @@ unsigned long native_calibrate_tsc(void)
257 * calibration delay loop as we have to wait for a certain 262 * calibration delay loop as we have to wait for a certain
258 * amount of time anyway. 263 * amount of time anyway.
259 */ 264 */
260 for (i = 0; i < 5; i++) { 265
266 /* Preset PIT loop values */
267 latch = CAL_LATCH;
268 ms = CAL_MS;
269 loopmin = CAL_PIT_LOOPS;
270
271 for (i = 0; i < 3; i++) {
261 unsigned long tsc_pit_khz; 272 unsigned long tsc_pit_khz;
262 273
263 /* 274 /*
@@ -268,7 +279,7 @@ unsigned long native_calibrate_tsc(void)
268 */ 279 */
269 local_irq_save(flags); 280 local_irq_save(flags);
270 tsc1 = tsc_read_refs(&ref1, hpet); 281 tsc1 = tsc_read_refs(&ref1, hpet);
271 tsc_pit_khz = pit_calibrate_tsc(); 282 tsc_pit_khz = pit_calibrate_tsc(latch, ms, loopmin);
272 tsc2 = tsc_read_refs(&ref2, hpet); 283 tsc2 = tsc_read_refs(&ref2, hpet);
273 local_irq_restore(flags); 284 local_irq_restore(flags);
274 285
@@ -290,6 +301,35 @@ unsigned long native_calibrate_tsc(void)
290 tsc2 = calc_pmtimer_ref(tsc2, ref1, ref2); 301 tsc2 = calc_pmtimer_ref(tsc2, ref1, ref2);
291 302
292 tsc_ref_min = min(tsc_ref_min, (unsigned long) tsc2); 303 tsc_ref_min = min(tsc_ref_min, (unsigned long) tsc2);
304
305 /* Check the reference deviation */
306 delta = ((u64) tsc_pit_min) * 100;
307 do_div(delta, tsc_ref_min);
308
309 /*
310 * If both calibration results are inside a 10% window
311 * then we can be sure, that the calibration
312 * succeeded. We break out of the loop right away. We
313 * use the reference value, as it is more precise.
314 */
315 if (delta >= 90 && delta <= 110) {
316 printk(KERN_INFO
317 "TSC: PIT calibration matches %s. %d loops\n",
318 hpet ? "HPET" : "PMTIMER", i + 1);
319 return tsc_ref_min;
320 }
321
322 /*
323 * Check whether PIT failed more than once. This
324 * happens in virtualized environments. We need to
325 * give the virtual PC a slightly longer timeframe for
326 * the HPET/PMTIMER to make the result precise.
327 */
328 if (i == 1 && tsc_pit_min == ULONG_MAX) {
329 latch = CAL2_LATCH;
330 ms = CAL2_MS;
331 loopmin = CAL2_PIT_LOOPS;
332 }
293 } 333 }
294 334
295 /* 335 /*
@@ -309,7 +349,7 @@ unsigned long native_calibrate_tsc(void)
309 /* The alternative source failed as well, disable TSC */ 349 /* The alternative source failed as well, disable TSC */
310 if (tsc_ref_min == ULONG_MAX) { 350 if (tsc_ref_min == ULONG_MAX) {
311 printk(KERN_WARNING "TSC: HPET/PMTIMER calibration " 351 printk(KERN_WARNING "TSC: HPET/PMTIMER calibration "
312 "failed due to SMI disturbance.\n"); 352 "failed.\n");
313 return 0; 353 return 0;
314 } 354 }
315 355
@@ -328,37 +368,18 @@ unsigned long native_calibrate_tsc(void)
328 368
329 /* The alternative source failed, use the PIT calibration value */ 369 /* The alternative source failed, use the PIT calibration value */
330 if (tsc_ref_min == ULONG_MAX) { 370 if (tsc_ref_min == ULONG_MAX) {
331 printk(KERN_WARNING "TSC: HPET/PMTIMER calibration failed due " 371 printk(KERN_WARNING "TSC: HPET/PMTIMER calibration failed. "
332 "to SMI disturbance. Using PIT calibration\n"); 372 "Using PIT calibration\n");
333 return tsc_pit_min; 373 return tsc_pit_min;
334 } 374 }
335 375
336 /* Check the reference deviation */
337 delta = ((u64) tsc_pit_min) * 100;
338 do_div(delta, tsc_ref_min);
339
340 /*
341 * If both calibration results are inside a 5% window, the we
342 * use the lower frequency of those as it is probably the
343 * closest estimate.
344 */
345 if (delta >= 95 && delta <= 105) {
346 printk(KERN_INFO "TSC: PIT calibration confirmed by %s.\n",
347 hpet ? "HPET" : "PMTIMER");
348 printk(KERN_INFO "TSC: using %s calibration value\n",
349 tsc_pit_min <= tsc_ref_min ? "PIT" :
350 hpet ? "HPET" : "PMTIMER");
351 return tsc_pit_min <= tsc_ref_min ? tsc_pit_min : tsc_ref_min;
352 }
353
354 printk(KERN_WARNING "TSC: PIT calibration deviates from %s: %lu %lu.\n",
355 hpet ? "HPET" : "PMTIMER", tsc_pit_min, tsc_ref_min);
356
357 /* 376 /*
358 * The calibration values differ too much. In doubt, we use 377 * The calibration values differ too much. In doubt, we use
359 * the PIT value as we know that there are PMTIMERs around 378 * the PIT value as we know that there are PMTIMERs around
360 * running at double speed. 379 * running at double speed. At least we let the user know:
361 */ 380 */
381 printk(KERN_WARNING "TSC: PIT calibration deviates from %s: %lu %lu.\n",
382 hpet ? "HPET" : "PMTIMER", tsc_pit_min, tsc_ref_min);
362 printk(KERN_INFO "TSC: Using PIT calibration value\n"); 383 printk(KERN_INFO "TSC: Using PIT calibration value\n");
363 return tsc_pit_min; 384 return tsc_pit_min;
364} 385}