mirror of
https://abf.rosa.ru/djam/kernel-xen.git
synced 2025-02-23 07:42:46 +00:00
161 lines
5.6 KiB
Diff
161 lines
5.6 KiB
Diff
From: Lin Ming <ming.m.lin@intel.com>
|
|
Subject: timekeeping: Fix clock_gettime vsyscall time warp
|
|
Patch-mainline: 0696b711e4be45fa104c12329f617beb29c03f78
|
|
References: bnc#569238
|
|
|
|
commit 0696b711e4be45fa104c12329f617beb29c03f78
|
|
Author: Lin Ming <ming.m.lin@intel.com>
|
|
Date: Tue Nov 17 13:49:50 2009 +0800
|
|
|
|
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>
|
|
|
|
Signed-off-by: Kurt Garloff <garloff@suse.de>
|
|
|
|
---
|
|
arch/ia64/kernel/time.c | 4 ++--
|
|
arch/powerpc/kernel/time.c | 5 +++--
|
|
arch/s390/kernel/time.c | 3 ++-
|
|
arch/x86/kernel/vsyscall_64.c | 5 +++--
|
|
include/linux/clocksource.h | 6 ++++--
|
|
kernel/time/timekeeping.c | 6 +++---
|
|
6 files changed, 17 insertions(+), 12 deletions(-)
|
|
|
|
--- a/arch/ia64/kernel/time.c
|
|
+++ b/arch/ia64/kernel/time.c
|
|
@@ -473,7 +473,7 @@ void update_vsyscall_tz(void)
|
|
{
|
|
}
|
|
|
|
-void update_vsyscall(struct timespec *wall, struct clocksource *c)
|
|
+void update_vsyscall(struct timespec *wall, struct clocksource *c, u32 mult)
|
|
{
|
|
unsigned long flags;
|
|
|
|
@@ -481,7 +481,7 @@ void update_vsyscall(struct timespec *wa
|
|
|
|
/* copy fsyscall clock data */
|
|
fsyscall_gtod_data.clk_mask = c->mask;
|
|
- fsyscall_gtod_data.clk_mult = c->mult;
|
|
+ fsyscall_gtod_data.clk_mult = mult;
|
|
fsyscall_gtod_data.clk_shift = c->shift;
|
|
fsyscall_gtod_data.clk_fsys_mmio = c->fsys_mmio;
|
|
fsyscall_gtod_data.clk_cycle_last = c->cycle_last;
|
|
--- a/arch/powerpc/kernel/time.c
|
|
+++ b/arch/powerpc/kernel/time.c
|
|
@@ -828,7 +828,8 @@ static cycle_t timebase_read(struct cloc
|
|
return (cycle_t)get_tb();
|
|
}
|
|
|
|
-void update_vsyscall(struct timespec *wall_time, struct clocksource *clock)
|
|
+void update_vsyscall(struct timespec *wall_time, struct clocksource *clock,
|
|
+ u32 mult)
|
|
{
|
|
u64 t2x, stamp_xsec;
|
|
|
|
@@ -841,7 +842,7 @@ void update_vsyscall(struct timespec *wa
|
|
|
|
/* XXX this assumes clock->shift == 22 */
|
|
/* 4611686018 ~= 2^(20+64-22) / 1e9 */
|
|
- t2x = (u64) clock->mult * 4611686018ULL;
|
|
+ t2x = (u64) mult * 4611686018ULL;
|
|
stamp_xsec = (u64) xtime.tv_nsec * XSEC_PER_SEC;
|
|
do_div(stamp_xsec, 1000000000);
|
|
stamp_xsec += (u64) xtime.tv_sec * XSEC_PER_SEC;
|
|
--- a/arch/s390/kernel/time.c
|
|
+++ b/arch/s390/kernel/time.c
|
|
@@ -214,7 +214,8 @@ struct clocksource * __init clocksource_
|
|
return &clocksource_tod;
|
|
}
|
|
|
|
-void update_vsyscall(struct timespec *wall_time, struct clocksource *clock)
|
|
+void update_vsyscall(struct timespec *wall_time, struct clocksource *clock,
|
|
+ u32 mult)
|
|
{
|
|
if (clock != &clocksource_tod)
|
|
return;
|
|
--- a/arch/x86/kernel/vsyscall_64.c
|
|
+++ b/arch/x86/kernel/vsyscall_64.c
|
|
@@ -73,7 +73,8 @@ void update_vsyscall_tz(void)
|
|
write_sequnlock_irqrestore(&vsyscall_gtod_data.lock, flags);
|
|
}
|
|
|
|
-void update_vsyscall(struct timespec *wall_time, struct clocksource *clock)
|
|
+void update_vsyscall(struct timespec *wall_time, struct clocksource *clock,
|
|
+ u32 mult)
|
|
{
|
|
unsigned long flags;
|
|
|
|
@@ -82,7 +83,7 @@ void update_vsyscall(struct timespec *wa
|
|
vsyscall_gtod_data.clock.vread = clock->vread;
|
|
vsyscall_gtod_data.clock.cycle_last = clock->cycle_last;
|
|
vsyscall_gtod_data.clock.mask = clock->mask;
|
|
- vsyscall_gtod_data.clock.mult = clock->mult;
|
|
+ vsyscall_gtod_data.clock.mult = mult;
|
|
vsyscall_gtod_data.clock.shift = clock->shift;
|
|
vsyscall_gtod_data.wall_time_sec = wall_time->tv_sec;
|
|
vsyscall_gtod_data.wall_time_nsec = wall_time->tv_nsec;
|
|
--- a/include/linux/clocksource.h
|
|
+++ b/include/linux/clocksource.h
|
|
@@ -282,10 +282,12 @@ extern struct clocksource * __init __wea
|
|
extern void clocksource_mark_unstable(struct clocksource *cs);
|
|
|
|
#ifdef CONFIG_GENERIC_TIME_VSYSCALL
|
|
-extern void update_vsyscall(struct timespec *ts, struct clocksource *c);
|
|
+extern void
|
|
+update_vsyscall(struct timespec *ts, struct clocksource *c, u32 mult);
|
|
extern void update_vsyscall_tz(void);
|
|
#else
|
|
-static inline void update_vsyscall(struct timespec *ts, struct clocksource *c)
|
|
+static inline void
|
|
+update_vsyscall(struct timespec *ts, struct clocksource *c, u32 mult)
|
|
{
|
|
}
|
|
|
|
--- a/kernel/time/timekeeping.c
|
|
+++ b/kernel/time/timekeeping.c
|
|
@@ -177,7 +177,7 @@ void timekeeping_leap_insert(int leapsec
|
|
{
|
|
xtime.tv_sec += leapsecond;
|
|
wall_to_monotonic.tv_sec -= leapsecond;
|
|
- update_vsyscall(&xtime, timekeeper.clock);
|
|
+ update_vsyscall(&xtime, timekeeper.clock, timekeeper.mult);
|
|
}
|
|
|
|
#ifdef CONFIG_GENERIC_TIME
|
|
@@ -337,7 +337,7 @@ int do_settimeofday(struct timespec *tv)
|
|
timekeeper.ntp_error = 0;
|
|
ntp_clear();
|
|
|
|
- update_vsyscall(&xtime, timekeeper.clock);
|
|
+ update_vsyscall(&xtime, timekeeper.clock, timekeeper.mult);
|
|
|
|
write_sequnlock_irqrestore(&xtime_lock, flags);
|
|
|
|
@@ -822,7 +822,7 @@ void update_wall_time(void)
|
|
update_xtime_cache(nsecs);
|
|
|
|
/* check to see if there is a new clocksource to use */
|
|
- update_vsyscall(&xtime, timekeeper.clock);
|
|
+ update_vsyscall(&xtime, timekeeper.clock, timekeeper.mult);
|
|
}
|
|
|
|
/**
|