x86: Fix serialization in pit_expect_msb()

Wei Chong Tan reported a fast-PIT-calibration corner-case:

| pit_expect_msb() is vulnerable to SMI disturbance corner case
| in some platforms which causes /proc/cpuinfo to show wrong
| CPU MHz value when quick_pit_calibrate() jumps to success
| section.

I think that the real issue isn't even an SMI - but the fact
that in the very last iteration of the loop, there's no
serializing instruction _after_ the last 'rdtsc'. So even in
the absense of SMI's, we do have a situation where the cycle
counter was read without proper serialization.

The last check should be done outside the outer loop, since
_inside_ the outer loop, we'll be testing that the PIT has
the right MSB value has the right value in the next iteration.

So only the _last_ iteration is special, because that's the one
that will not check the PIT MSB value any more, and because the
final 'get_cycles()' isn't serialized.

In other words:

- I'd like to move the PIT MSB check to after the last
iteration, rather than in every iteration

- I think we should comment on the fact that it's also a
serializing instruction and so 'fences in' the TSC read.

Here's a suggested replacement.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Reported-by: "Tan, Wei Chong" <wei.chong.tan@intel.com>
Tested-by: "Tan, Wei Chong" <wei.chong.tan@intel.com>
LKML-Reference: <B28277FD4E0F9247A3D55704C440A140D5D683F3@pgsmsx504.gar.corp.intel.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>

authored by Linus Torvalds and committed by Ingo Molnar b6e61eef f4b9a988

+22 -7
+22 -7
arch/x86/kernel/tsc.c
··· 275 275 * use the TSC value at the transitions to calculate a pretty 276 276 * good value for the TSC frequencty. 277 277 */ 278 + static inline int pit_verify_msb(unsigned char val) 279 + { 280 + /* Ignore LSB */ 281 + inb(0x42); 282 + return inb(0x42) == val; 283 + } 284 + 278 285 static inline int pit_expect_msb(unsigned char val, u64 *tscp, unsigned long *deltap) 279 286 { 280 287 int count; 281 288 u64 tsc = 0; 282 289 283 290 for (count = 0; count < 50000; count++) { 284 - /* Ignore LSB */ 285 - inb(0x42); 286 - if (inb(0x42) != val) 291 + if (!pit_verify_msb(val)) 287 292 break; 288 293 tsc = get_cycles(); 289 294 } ··· 341 336 * to do that is to just read back the 16-bit counter 342 337 * once from the PIT. 343 338 */ 344 - inb(0x42); 345 - inb(0x42); 339 + pit_verify_msb(0); 346 340 347 341 if (pit_expect_msb(0xff, &tsc, &d1)) { 348 342 for (i = 1; i <= MAX_QUICK_PIT_ITERATIONS; i++) { ··· 352 348 * Iterate until the error is less than 500 ppm 353 349 */ 354 350 delta -= tsc; 355 - if (d1+d2 < delta >> 11) 356 - goto success; 351 + if (d1+d2 >= delta >> 11) 352 + continue; 353 + 354 + /* 355 + * Check the PIT one more time to verify that 356 + * all TSC reads were stable wrt the PIT. 357 + * 358 + * This also guarantees serialization of the 359 + * last cycle read ('d2') in pit_expect_msb. 360 + */ 361 + if (!pit_verify_msb(0xfe - i)) 362 + break; 363 + goto success; 357 364 } 358 365 } 359 366 printk("Fast TSC calibration failed\n");