@@ -159,9 +159,14 @@ static unsigned long calc_pmtimer_ref(u64 deltatsc, u64 pm1, u64 pm2)
159
159
return (unsigned long ) deltatsc ;
160
160
}
161
161
162
- #define CAL_MS 50
162
+ #define CAL_MS 10
163
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
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
176
* Return ULONG_MAX on failure to calibrate.
172
177
*/
173
- static unsigned long pit_calibrate_tsc (void )
178
+ static unsigned long pit_calibrate_tsc (u32 latch , unsigned long ms , int loopmin )
174
179
{
175
180
u64 tsc , t1 , t2 , delta ;
176
181
unsigned long tscmin , tscmax ;
@@ -185,8 +190,8 @@ static unsigned long pit_calibrate_tsc(void)
185
190
* (LSB then MSB) to begin countdown.
186
191
*/
187
192
outb (0xb0 , 0x43 );
188
- outb (CAL_LATCH & 0xff , 0x42 );
189
- outb (CAL_LATCH >> 8 , 0x42 );
193
+ outb (latch & 0xff , 0x42 );
194
+ outb (latch >> 8 , 0x42 );
190
195
191
196
tsc = t1 = t2 = get_cycles ();
192
197
@@ -207,18 +212,18 @@ static unsigned long pit_calibrate_tsc(void)
207
212
/*
208
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
216
* times, then we have been hit by a massive SMI
212
217
*
213
218
* If the maximum is 10 times larger than the minimum,
214
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
222
return ULONG_MAX ;
218
223
219
224
/* Calculate the PIT value */
220
225
delta = t2 - t1 ;
221
- do_div (delta , CAL_MS );
226
+ do_div (delta , ms );
222
227
return delta ;
223
228
}
224
229
@@ -230,8 +235,8 @@ unsigned long native_calibrate_tsc(void)
230
235
{
231
236
u64 tsc1 , tsc2 , delta , ref1 , ref2 ;
232
237
unsigned long tsc_pit_min = ULONG_MAX , tsc_ref_min = ULONG_MAX ;
233
- unsigned long flags ;
234
- int hpet = is_hpet_enabled (), i ;
238
+ unsigned long flags , latch , ms ;
239
+ int hpet = is_hpet_enabled (), i , loopmin ;
235
240
236
241
/*
237
242
* Run 5 calibration loops to get the lowest frequency value
@@ -257,7 +262,13 @@ unsigned long native_calibrate_tsc(void)
257
262
* calibration delay loop as we have to wait for a certain
258
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
272
unsigned long tsc_pit_khz ;
262
273
263
274
/*
@@ -268,7 +279,7 @@ unsigned long native_calibrate_tsc(void)
268
279
*/
269
280
local_irq_save (flags );
270
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
283
tsc2 = tsc_read_refs (& ref2 , hpet );
273
284
local_irq_restore (flags );
274
285
@@ -290,6 +301,35 @@ unsigned long native_calibrate_tsc(void)
290
301
tsc2 = calc_pmtimer_ref (tsc2 , ref1 , ref2 );
291
302
292
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
349
/* The alternative source failed as well, disable TSC */
310
350
if (tsc_ref_min == ULONG_MAX ) {
311
351
printk (KERN_WARNING "TSC: HPET/PMTIMER calibration "
312
- "failed due to SMI disturbance .\n" );
352
+ "failed.\n" );
313
353
return 0 ;
314
354
}
315
355
@@ -328,37 +368,18 @@ unsigned long native_calibrate_tsc(void)
328
368
329
369
/* The alternative source failed, use the PIT calibration value */
330
370
if (tsc_ref_min == ULONG_MAX ) {
331
- printk (KERN_WARNING "TSC: HPET/PMTIMER calibration failed due "
332
- "to SMI disturbance. Using PIT calibration\n" );
371
+ printk (KERN_WARNING "TSC: HPET/PMTIMER calibration failed. "
372
+ "Using PIT calibration\n" );
333
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
377
* The calibration values differ too much. In doubt, we use
359
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
383
printk (KERN_INFO "TSC: Using PIT calibration value\n" );
363
384
return tsc_pit_min ;
364
385
}
0 commit comments