]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
vdso/vsyscall: Update auxiliary clock data in the datapage
authorThomas Weißschuh <thomas.weissschuh@linutronix.de>
Tue, 1 Jul 2025 08:58:05 +0000 (10:58 +0200)
committerThomas Gleixner <tglx@linutronix.de>
Fri, 18 Jul 2025 11:45:33 +0000 (13:45 +0200)
Expose the auxiliary clock data so it can be read from the vDSO.

Architectures not using the generic vDSO time framework,
namely SPARC64, are not supported.

Signed-off-by: Thomas Weißschuh <thomas.weissschuh@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Link: https://lore.kernel.org/all/20250701-vdso-auxclock-v1-11-df7d9f87b9b8@linutronix.de
include/linux/timekeeper_internal.h
include/vdso/datapage.h
kernel/time/namespace.c
kernel/time/timekeeping.c
kernel/time/vsyscall.c

index ca79938b62f396afd503e0cf06bbecf6f95cfce4..c27aac67cb3f15f0892c667a990d4a6e16a06d76 100644 (file)
@@ -190,4 +190,10 @@ static inline void update_vsyscall_tz(void)
 }
 #endif
 
+#if defined(CONFIG_GENERIC_GETTIMEOFDAY) && defined(CONFIG_POSIX_AUX_CLOCKS)
+extern void vdso_time_update_aux(struct timekeeper *tk);
+#else
+static inline void vdso_time_update_aux(struct timekeeper *tk) { }
+#endif
+
 #endif /* _LINUX_TIMEKEEPER_INTERNAL_H */
index 1864e76e8f691bab10813543880f71bc59afa9c0..f4c96d9ce674abb07ccd8703f1a04da7631c1677 100644 (file)
@@ -38,6 +38,7 @@ struct vdso_arch_data {
 #endif
 
 #define VDSO_BASES     (CLOCK_TAI + 1)
+#define VDSO_BASE_AUX  0
 #define VDSO_HRES      (BIT(CLOCK_REALTIME)            | \
                         BIT(CLOCK_MONOTONIC)           | \
                         BIT(CLOCK_BOOTTIME)            | \
@@ -117,6 +118,7 @@ struct vdso_clock {
  * @arch_data:         architecture specific data (optional, defaults
  *                     to an empty struct)
  * @clock_data:                clocksource related data (array)
+ * @aux_clock_data:    auxiliary clocksource related data (array)
  * @tz_minuteswest:    minutes west of Greenwich
  * @tz_dsttime:                type of DST correction
  * @hrtimer_res:       hrtimer resolution
@@ -133,6 +135,7 @@ struct vdso_time_data {
        struct arch_vdso_time_data      arch_data;
 
        struct vdso_clock               clock_data[CS_BASES];
+       struct vdso_clock               aux_clock_data[MAX_AUX_CLOCKS];
 
        s32                             tz_minuteswest;
        s32                             tz_dsttime;
index e3642278df433c41654ffb6a8043c3fcecc2994a..667452768ed3b50e48e3cfb70f8ef68e4bed9e0b 100644 (file)
@@ -242,6 +242,11 @@ static void timens_set_vvar_page(struct task_struct *task,
        for (i = 0; i < CS_BASES; i++)
                timens_setup_vdso_clock_data(&vc[i], ns);
 
+       if (IS_ENABLED(CONFIG_POSIX_AUX_CLOCKS)) {
+               for (i = 0; i < ARRAY_SIZE(vdata->aux_clock_data); i++)
+                       timens_setup_vdso_clock_data(&vdata->aux_clock_data[i], ns);
+       }
+
 out:
        mutex_unlock(&offset_lock);
 }
index cbcf090bb4bed8e4f870d673a9ce983f2939bc65..243fe25e680a406397340b00f72cb1efe20bfcfc 100644 (file)
@@ -66,11 +66,21 @@ static inline bool tk_get_aux_ts64(unsigned int tkid, struct timespec64 *ts)
 {
        return ktime_get_aux_ts64(CLOCK_AUX + tkid - TIMEKEEPER_AUX_FIRST, ts);
 }
+
+static inline bool tk_is_aux(const struct timekeeper *tk)
+{
+       return tk->id >= TIMEKEEPER_AUX_FIRST && tk->id <= TIMEKEEPER_AUX_LAST;
+}
 #else
 static inline bool tk_get_aux_ts64(unsigned int tkid, struct timespec64 *ts)
 {
        return false;
 }
+
+static inline bool tk_is_aux(const struct timekeeper *tk)
+{
+       return false;
+}
 #endif
 
 /* flag for if timekeeping is suspended */
@@ -719,6 +729,8 @@ static void timekeeping_update_from_shadow(struct tk_data *tkd, unsigned int act
 
                update_fast_timekeeper(&tk->tkr_mono, &tk_fast_mono);
                update_fast_timekeeper(&tk->tkr_raw,  &tk_fast_raw);
+       } else if (tk_is_aux(tk)) {
+               vdso_time_update_aux(tk);
        }
 
        if (action & TK_CLOCK_WAS_SET)
index df6bada2d58ed9a03e5dd3cb4b218983089a2877..8ba8b0d8a3873123da1ed0b1c6dbe7ef172d49f2 100644 (file)
@@ -136,6 +136,46 @@ void update_vsyscall_tz(void)
        __arch_sync_vdso_time_data(vdata);
 }
 
+#ifdef CONFIG_POSIX_AUX_CLOCKS
+void vdso_time_update_aux(struct timekeeper *tk)
+{
+       struct vdso_time_data *vdata = vdso_k_time_data;
+       struct vdso_timestamp *vdso_ts;
+       struct vdso_clock *vc;
+       s32 clock_mode;
+       u64 nsec;
+
+       vc = &vdata->aux_clock_data[tk->id - TIMEKEEPER_AUX_FIRST];
+       vdso_ts = &vc->basetime[VDSO_BASE_AUX];
+       clock_mode = tk->tkr_mono.clock->vdso_clock_mode;
+       if (!tk->clock_valid)
+               clock_mode = VDSO_CLOCKMODE_NONE;
+
+       /* copy vsyscall data */
+       vdso_write_begin_clock(vc);
+
+       vc->clock_mode = clock_mode;
+
+       if (clock_mode != VDSO_CLOCKMODE_NONE) {
+               fill_clock_configuration(vc, &tk->tkr_mono);
+
+               vdso_ts->sec    = tk->xtime_sec;
+
+               nsec = tk->tkr_mono.xtime_nsec >> tk->tkr_mono.shift;
+               nsec += tk->offs_aux;
+               vdso_ts->sec += __iter_div_u64_rem(nsec, NSEC_PER_SEC, &nsec);
+               nsec = nsec << tk->tkr_mono.shift;
+               vdso_ts->nsec = nsec;
+       }
+
+       __arch_update_vdso_clock(vc);
+
+       vdso_write_end_clock(vc);
+
+       __arch_sync_vdso_time_data(vdata);
+}
+#endif
+
 /**
  * vdso_update_begin - Start of a VDSO update section
  *