| From 9f24c540f7f8eb3a981528da9a9a636a5bdf5987 Mon Sep 17 00:00:00 2001 |
| From: Thomas Gleixner <tglx@linutronix.de> |
| Date: Tue, 14 Jan 2020 19:52:39 +0100 |
| Subject: lib/vdso: Update coarse timekeeper unconditionally |
| |
| From: Thomas Gleixner <tglx@linutronix.de> |
| |
| commit 9f24c540f7f8eb3a981528da9a9a636a5bdf5987 upstream. |
| |
| The low resolution parts of the VDSO, i.e.: |
| |
| clock_gettime(CLOCK_*_COARSE), clock_getres(), time() |
| |
| can be used even if there is no VDSO capable clocksource. |
| |
| But if an architecture opts out of the VDSO data update then this |
| information becomes stale. This affects ARM when there is no architected |
| timer available. The lack of update causes userspace to use stale data |
| forever. |
| |
| Make the update of the low resolution parts unconditional and only skip |
| the update of the high resolution parts if the architecture requests it. |
| |
| Fixes: 44f57d788e7d ("timekeeping: Provide a generic update_vsyscall() implementation") |
| Signed-off-by: Thomas Gleixner <tglx@linutronix.de> |
| Link: https://lore.kernel.org/r/20200114185946.765577901@linutronix.de |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| kernel/time/vsyscall.c | 37 +++++++++++++++++-------------------- |
| 1 file changed, 17 insertions(+), 20 deletions(-) |
| |
| --- a/kernel/time/vsyscall.c |
| +++ b/kernel/time/vsyscall.c |
| @@ -28,11 +28,6 @@ static inline void update_vdso_data(stru |
| vdata[CS_RAW].mult = tk->tkr_raw.mult; |
| vdata[CS_RAW].shift = tk->tkr_raw.shift; |
| |
| - /* CLOCK_REALTIME */ |
| - vdso_ts = &vdata[CS_HRES_COARSE].basetime[CLOCK_REALTIME]; |
| - vdso_ts->sec = tk->xtime_sec; |
| - vdso_ts->nsec = tk->tkr_mono.xtime_nsec; |
| - |
| /* CLOCK_MONOTONIC */ |
| vdso_ts = &vdata[CS_HRES_COARSE].basetime[CLOCK_MONOTONIC]; |
| vdso_ts->sec = tk->xtime_sec + tk->wall_to_monotonic.tv_sec; |
| @@ -70,12 +65,6 @@ static inline void update_vdso_data(stru |
| vdso_ts = &vdata[CS_HRES_COARSE].basetime[CLOCK_TAI]; |
| vdso_ts->sec = tk->xtime_sec + (s64)tk->tai_offset; |
| vdso_ts->nsec = tk->tkr_mono.xtime_nsec; |
| - |
| - /* |
| - * Read without the seqlock held by clock_getres(). |
| - * Note: No need to have a second copy. |
| - */ |
| - WRITE_ONCE(vdata[CS_HRES_COARSE].hrtimer_res, hrtimer_resolution); |
| } |
| |
| void update_vsyscall(struct timekeeper *tk) |
| @@ -84,20 +73,17 @@ void update_vsyscall(struct timekeeper * |
| struct vdso_timestamp *vdso_ts; |
| u64 nsec; |
| |
| - if (!__arch_update_vdso_data()) { |
| - /* |
| - * Some architectures might want to skip the update of the |
| - * data page. |
| - */ |
| - return; |
| - } |
| - |
| /* copy vsyscall data */ |
| vdso_write_begin(vdata); |
| |
| vdata[CS_HRES_COARSE].clock_mode = __arch_get_clock_mode(tk); |
| vdata[CS_RAW].clock_mode = __arch_get_clock_mode(tk); |
| |
| + /* CLOCK_REALTIME also required for time() */ |
| + vdso_ts = &vdata[CS_HRES_COARSE].basetime[CLOCK_REALTIME]; |
| + vdso_ts->sec = tk->xtime_sec; |
| + vdso_ts->nsec = tk->tkr_mono.xtime_nsec; |
| + |
| /* CLOCK_REALTIME_COARSE */ |
| vdso_ts = &vdata[CS_HRES_COARSE].basetime[CLOCK_REALTIME_COARSE]; |
| vdso_ts->sec = tk->xtime_sec; |
| @@ -110,7 +96,18 @@ void update_vsyscall(struct timekeeper * |
| nsec = nsec + tk->wall_to_monotonic.tv_nsec; |
| vdso_ts->sec += __iter_div_u64_rem(nsec, NSEC_PER_SEC, &vdso_ts->nsec); |
| |
| - update_vdso_data(vdata, tk); |
| + /* |
| + * Read without the seqlock held by clock_getres(). |
| + * Note: No need to have a second copy. |
| + */ |
| + WRITE_ONCE(vdata[CS_HRES_COARSE].hrtimer_res, hrtimer_resolution); |
| + |
| + /* |
| + * Architectures can opt out of updating the high resolution part |
| + * of the VDSO. |
| + */ |
| + if (__arch_update_vdso_data()) |
| + update_vdso_data(vdata, tk); |
| |
| __arch_update_vsyscall(vdata, tk); |
| |