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