lib/vdso: Update coarse timekeeper unconditionally
authorThomas Gleixner <tglx@linutronix.de>
Tue, 14 Jan 2020 18:52:39 +0000 (19:52 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 5 Mar 2020 15:43:49 +0000 (16:43 +0100)
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

index f0aab618282494f511d6b6c69639a68457843fee..9577c89179cd1309b99d8224bc21a6622407d210 100644 (file)
@@ -28,11 +28,6 @@ static inline void update_vdso_data(struct vdso_data *vdata,
        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(struct vdso_data *vdata,
        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 *tk)
        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 *tk)
        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);