aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorLin Ming <ming.m.lin@intel.com>2009-11-17 00:49:50 -0500
committerThomas Gleixner <tglx@linutronix.de>2009-11-17 05:52:34 -0500
commit0696b711e4be45fa104c12329f617beb29c03f78 (patch)
tree96292fdc4ab443d6218077d363548532df6cbd8b /arch
parenta9366e61b03f55a6e009e687ad10e706714c9907 (diff)
timekeeping: Fix clock_gettime vsyscall time warp
Since commit 0a544198 "timekeeping: Move NTP adjusted clock multiplier to struct timekeeper" the clock multiplier of vsyscall is updated with the unmodified clock multiplier of the clock source and not with the NTP adjusted multiplier of the timekeeper. This causes user space observerable time warps: new CLOCK-warp maximum: 120 nsecs, 00000025c337c537 -> 00000025c337c4bf Add a new argument "mult" to update_vsyscall() and hand in the timekeeping internal NTP adjusted multiplier. Signed-off-by: Lin Ming <ming.m.lin@intel.com> Cc: "Zhang Yanmin" <yanmin_zhang@linux.intel.com> Cc: Martin Schwidefsky <schwidefsky@de.ibm.com> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Cc: Tony Luck <tony.luck@intel.com> LKML-Reference: <1258436990.17765.83.camel@minggr.sh.intel.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'arch')
-rw-r--r--arch/ia64/kernel/time.c4
-rw-r--r--arch/powerpc/kernel/time.c5
-rw-r--r--arch/s390/kernel/time.c3
-rw-r--r--arch/x86/kernel/vsyscall_64.c5
4 files changed, 10 insertions, 7 deletions
diff --git a/arch/ia64/kernel/time.c b/arch/ia64/kernel/time.c
index 4990495d7531..a35c661e5e89 100644
--- a/arch/ia64/kernel/time.c
+++ b/arch/ia64/kernel/time.c
@@ -473,7 +473,7 @@ void update_vsyscall_tz(void)
473{ 473{
474} 474}
475 475
476void update_vsyscall(struct timespec *wall, struct clocksource *c) 476void update_vsyscall(struct timespec *wall, struct clocksource *c, u32 mult)
477{ 477{
478 unsigned long flags; 478 unsigned long flags;
479 479
@@ -481,7 +481,7 @@ void update_vsyscall(struct timespec *wall, struct clocksource *c)
481 481
482 /* copy fsyscall clock data */ 482 /* copy fsyscall clock data */
483 fsyscall_gtod_data.clk_mask = c->mask; 483 fsyscall_gtod_data.clk_mask = c->mask;
484 fsyscall_gtod_data.clk_mult = c->mult; 484 fsyscall_gtod_data.clk_mult = mult;
485 fsyscall_gtod_data.clk_shift = c->shift; 485 fsyscall_gtod_data.clk_shift = c->shift;
486 fsyscall_gtod_data.clk_fsys_mmio = c->fsys_mmio; 486 fsyscall_gtod_data.clk_fsys_mmio = c->fsys_mmio;
487 fsyscall_gtod_data.clk_cycle_last = c->cycle_last; 487 fsyscall_gtod_data.clk_cycle_last = c->cycle_last;
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index a136a11c490d..39713312fbc7 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -828,7 +828,8 @@ static cycle_t timebase_read(struct clocksource *cs)
828 return (cycle_t)get_tb(); 828 return (cycle_t)get_tb();
829} 829}
830 830
831void update_vsyscall(struct timespec *wall_time, struct clocksource *clock) 831void update_vsyscall(struct timespec *wall_time, struct clocksource *clock,
832 u32 mult)
832{ 833{
833 u64 t2x, stamp_xsec; 834 u64 t2x, stamp_xsec;
834 835
@@ -841,7 +842,7 @@ void update_vsyscall(struct timespec *wall_time, struct clocksource *clock)
841 842
842 /* XXX this assumes clock->shift == 22 */ 843 /* XXX this assumes clock->shift == 22 */
843 /* 4611686018 ~= 2^(20+64-22) / 1e9 */ 844 /* 4611686018 ~= 2^(20+64-22) / 1e9 */
844 t2x = (u64) clock->mult * 4611686018ULL; 845 t2x = (u64) mult * 4611686018ULL;
845 stamp_xsec = (u64) xtime.tv_nsec * XSEC_PER_SEC; 846 stamp_xsec = (u64) xtime.tv_nsec * XSEC_PER_SEC;
846 do_div(stamp_xsec, 1000000000); 847 do_div(stamp_xsec, 1000000000);
847 stamp_xsec += (u64) xtime.tv_sec * XSEC_PER_SEC; 848 stamp_xsec += (u64) xtime.tv_sec * XSEC_PER_SEC;
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c
index 34162a0b2caa..68e1ecf5ebab 100644
--- a/arch/s390/kernel/time.c
+++ b/arch/s390/kernel/time.c
@@ -214,7 +214,8 @@ struct clocksource * __init clocksource_default_clock(void)
214 return &clocksource_tod; 214 return &clocksource_tod;
215} 215}
216 216
217void update_vsyscall(struct timespec *wall_time, struct clocksource *clock) 217void update_vsyscall(struct timespec *wall_time, struct clocksource *clock,
218 u32 mult)
218{ 219{
219 if (clock != &clocksource_tod) 220 if (clock != &clocksource_tod)
220 return; 221 return;
diff --git a/arch/x86/kernel/vsyscall_64.c b/arch/x86/kernel/vsyscall_64.c
index 8cb4974ff599..62f39d79b775 100644
--- a/arch/x86/kernel/vsyscall_64.c
+++ b/arch/x86/kernel/vsyscall_64.c
@@ -73,7 +73,8 @@ void update_vsyscall_tz(void)
73 write_sequnlock_irqrestore(&vsyscall_gtod_data.lock, flags); 73 write_sequnlock_irqrestore(&vsyscall_gtod_data.lock, flags);
74} 74}
75 75
76void update_vsyscall(struct timespec *wall_time, struct clocksource *clock) 76void update_vsyscall(struct timespec *wall_time, struct clocksource *clock,
77 u32 mult)
77{ 78{
78 unsigned long flags; 79 unsigned long flags;
79 80
@@ -82,7 +83,7 @@ void update_vsyscall(struct timespec *wall_time, struct clocksource *clock)
82 vsyscall_gtod_data.clock.vread = clock->vread; 83 vsyscall_gtod_data.clock.vread = clock->vread;
83 vsyscall_gtod_data.clock.cycle_last = clock->cycle_last; 84 vsyscall_gtod_data.clock.cycle_last = clock->cycle_last;
84 vsyscall_gtod_data.clock.mask = clock->mask; 85 vsyscall_gtod_data.clock.mask = clock->mask;
85 vsyscall_gtod_data.clock.mult = clock->mult; 86 vsyscall_gtod_data.clock.mult = mult;
86 vsyscall_gtod_data.clock.shift = clock->shift; 87 vsyscall_gtod_data.clock.shift = clock->shift;
87 vsyscall_gtod_data.wall_time_sec = wall_time->tv_sec; 88 vsyscall_gtod_data.wall_time_sec = wall_time->tv_sec;
88 vsyscall_gtod_data.wall_time_nsec = wall_time->tv_nsec; 89 vsyscall_gtod_data.wall_time_nsec = wall_time->tv_nsec;