]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
lib/vdso: Update coarse timekeeper unconditionally
authorThomas Gleixner <tglx@linutronix.de>
Tue, 14 Jan 2020 18:52:39 +0000 (19:52 +0100)
committerThomas Gleixner <tglx@linutronix.de>
Fri, 17 Jan 2020 14:53:50 +0000 (15:53 +0100)
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
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);