diff options
Diffstat (limited to 'arch/x86/kernel/tsc_32.c')
-rw-r--r-- | arch/x86/kernel/tsc_32.c | 15 |
1 files changed, 14 insertions, 1 deletions
diff --git a/arch/x86/kernel/tsc_32.c b/arch/x86/kernel/tsc_32.c index f14cfd9d1f94..d7498b34c8e9 100644 --- a/arch/x86/kernel/tsc_32.c +++ b/arch/x86/kernel/tsc_32.c | |||
@@ -287,14 +287,27 @@ core_initcall(cpufreq_tsc); | |||
287 | /* clock source code */ | 287 | /* clock source code */ |
288 | 288 | ||
289 | static unsigned long current_tsc_khz = 0; | 289 | static unsigned long current_tsc_khz = 0; |
290 | static struct clocksource clocksource_tsc; | ||
290 | 291 | ||
292 | /* | ||
293 | * We compare the TSC to the cycle_last value in the clocksource | ||
294 | * structure to avoid a nasty time-warp issue. This can be observed in | ||
295 | * a very small window right after one CPU updated cycle_last under | ||
296 | * xtime lock and the other CPU reads a TSC value which is smaller | ||
297 | * than the cycle_last reference value due to a TSC which is slighty | ||
298 | * behind. This delta is nowhere else observable, but in that case it | ||
299 | * results in a forward time jump in the range of hours due to the | ||
300 | * unsigned delta calculation of the time keeping core code, which is | ||
301 | * necessary to support wrapping clocksources like pm timer. | ||
302 | */ | ||
291 | static cycle_t read_tsc(void) | 303 | static cycle_t read_tsc(void) |
292 | { | 304 | { |
293 | cycle_t ret; | 305 | cycle_t ret; |
294 | 306 | ||
295 | rdtscll(ret); | 307 | rdtscll(ret); |
296 | 308 | ||
297 | return ret; | 309 | return ret >= clocksource_tsc.cycle_last ? |
310 | ret : clocksource_tsc.cycle_last; | ||
298 | } | 311 | } |
299 | 312 | ||
300 | static struct clocksource clocksource_tsc = { | 313 | static struct clocksource clocksource_tsc = { |