diff options
Diffstat (limited to 'arch/x86/kernel/tsc_32.c')
-rw-r--r-- | arch/x86/kernel/tsc_32.c | 23 |
1 files changed, 18 insertions, 5 deletions
diff --git a/arch/x86/kernel/tsc_32.c b/arch/x86/kernel/tsc_32.c index 3d7e6e9fa6c2..e4790728b224 100644 --- a/arch/x86/kernel/tsc_32.c +++ b/arch/x86/kernel/tsc_32.c | |||
@@ -221,9 +221,9 @@ EXPORT_SYMBOL(recalibrate_cpu_khz); | |||
221 | * if the CPU frequency is scaled, TSC-based delays will need a different | 221 | * if the CPU frequency is scaled, TSC-based delays will need a different |
222 | * loops_per_jiffy value to function properly. | 222 | * loops_per_jiffy value to function properly. |
223 | */ | 223 | */ |
224 | static unsigned int ref_freq = 0; | 224 | static unsigned int ref_freq; |
225 | static unsigned long loops_per_jiffy_ref = 0; | 225 | static unsigned long loops_per_jiffy_ref; |
226 | static unsigned long cpu_khz_ref = 0; | 226 | static unsigned long cpu_khz_ref; |
227 | 227 | ||
228 | static int | 228 | static int |
229 | time_cpufreq_notifier(struct notifier_block *nb, unsigned long val, void *data) | 229 | time_cpufreq_notifier(struct notifier_block *nb, unsigned long val, void *data) |
@@ -283,15 +283,28 @@ core_initcall(cpufreq_tsc); | |||
283 | 283 | ||
284 | /* clock source code */ | 284 | /* clock source code */ |
285 | 285 | ||
286 | static unsigned long current_tsc_khz = 0; | 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 = { |