diff options
-rw-r--r-- | arch/x86/kernel/tsc_32.c | 15 | ||||
-rw-r--r-- | arch/x86/kernel/tsc_64.c | 23 |
2 files changed, 34 insertions, 4 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 = { |
diff --git a/arch/x86/kernel/tsc_64.c b/arch/x86/kernel/tsc_64.c index 947554ddabb6..01fc9f0c39e2 100644 --- a/arch/x86/kernel/tsc_64.c +++ b/arch/x86/kernel/tsc_64.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <asm/hpet.h> | 11 | #include <asm/hpet.h> |
12 | #include <asm/timex.h> | 12 | #include <asm/timex.h> |
13 | #include <asm/timer.h> | 13 | #include <asm/timer.h> |
14 | #include <asm/vgtod.h> | ||
14 | 15 | ||
15 | static int notsc __initdata = 0; | 16 | static int notsc __initdata = 0; |
16 | 17 | ||
@@ -290,18 +291,34 @@ int __init notsc_setup(char *s) | |||
290 | 291 | ||
291 | __setup("notsc", notsc_setup); | 292 | __setup("notsc", notsc_setup); |
292 | 293 | ||
294 | static struct clocksource clocksource_tsc; | ||
293 | 295 | ||
294 | /* clock source code: */ | 296 | /* |
297 | * We compare the TSC to the cycle_last value in the clocksource | ||
298 | * structure to avoid a nasty time-warp. This can be observed in a | ||
299 | * very small window right after one CPU updated cycle_last under | ||
300 | * xtime/vsyscall_gtod lock and the other CPU reads a TSC value which | ||
301 | * is smaller than the cycle_last reference value due to a TSC which | ||
302 | * is slighty behind. This delta is nowhere else observable, but in | ||
303 | * that case it results in a forward time jump in the range of hours | ||
304 | * due to the unsigned delta calculation of the time keeping core | ||
305 | * code, which is necessary to support wrapping clocksources like pm | ||
306 | * timer. | ||
307 | */ | ||
295 | static cycle_t read_tsc(void) | 308 | static cycle_t read_tsc(void) |
296 | { | 309 | { |
297 | cycle_t ret = (cycle_t)get_cycles(); | 310 | cycle_t ret = (cycle_t)get_cycles(); |
298 | return ret; | 311 | |
312 | return ret >= clocksource_tsc.cycle_last ? | ||
313 | ret : clocksource_tsc.cycle_last; | ||
299 | } | 314 | } |
300 | 315 | ||
301 | static cycle_t __vsyscall_fn vread_tsc(void) | 316 | static cycle_t __vsyscall_fn vread_tsc(void) |
302 | { | 317 | { |
303 | cycle_t ret = (cycle_t)vget_cycles(); | 318 | cycle_t ret = (cycle_t)vget_cycles(); |
304 | return ret; | 319 | |
320 | return ret >= __vsyscall_gtod_data.clock.cycle_last ? | ||
321 | ret : __vsyscall_gtod_data.clock.cycle_last; | ||
305 | } | 322 | } |
306 | 323 | ||
307 | static struct clocksource clocksource_tsc = { | 324 | static struct clocksource clocksource_tsc = { |