Skip to content

Commit 60ecc26

Browse files
committed
timekeeping: Provide time setter for auxiliary clocks
Add clock_settime(2) support for auxiliary clocks. The function affects the AUX offset which is added to the "monotonic" clock readout of these clocks. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Acked-by: John Stultz <jstultz@google.com> Link: https://lore.kernel.org/all/20250625183757.995688714@linutronix.de
1 parent 606424b commit 60ecc26

1 file changed

Lines changed: 44 additions & 0 deletions

File tree

kernel/time/timekeeping.c

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2765,9 +2765,53 @@ static int aux_get_timespec(clockid_t id, struct timespec64 *tp)
27652765
return ktime_get_aux_ts64(id, tp) ? 0 : -ENODEV;
27662766
}
27672767

2768+
static int aux_clock_set(const clockid_t id, const struct timespec64 *tnew)
2769+
{
2770+
struct tk_data *aux_tkd = aux_get_tk_data(id);
2771+
struct timekeeper *aux_tks;
2772+
ktime_t tnow, nsecs;
2773+
2774+
if (!timespec64_valid_settod(tnew))
2775+
return -EINVAL;
2776+
if (!aux_tkd)
2777+
return -ENODEV;
2778+
2779+
aux_tks = &aux_tkd->shadow_timekeeper;
2780+
2781+
guard(raw_spinlock_irq)(&aux_tkd->lock);
2782+
if (!aux_tks->clock_valid)
2783+
return -ENODEV;
2784+
2785+
/* Forward the timekeeper base time */
2786+
timekeeping_forward_now(aux_tks);
2787+
/*
2788+
* Get the updated base time. tkr_mono.base has not been
2789+
* updated yet, so do that first. That makes the update
2790+
* in timekeeping_update_from_shadow() redundant, but
2791+
* that's harmless. After that @tnow can be calculated
2792+
* by using tkr_mono::cycle_last, which has been set
2793+
* by timekeeping_forward_now().
2794+
*/
2795+
tk_update_ktime_data(aux_tks);
2796+
nsecs = timekeeping_cycles_to_ns(&aux_tks->tkr_mono, aux_tks->tkr_mono.cycle_last);
2797+
tnow = ktime_add(aux_tks->tkr_mono.base, nsecs);
2798+
2799+
/*
2800+
* Calculate the new AUX offset as delta to @tnow ("monotonic").
2801+
* That avoids all the tk::xtime back and forth conversions as
2802+
* xtime ("realtime") is not applicable for auxiliary clocks and
2803+
* kept in sync with "monotonic".
2804+
*/
2805+
aux_tks->offs_aux = ktime_sub(timespec64_to_ktime(*tnew), tnow);
2806+
2807+
timekeeping_update_from_shadow(aux_tkd, TK_UPDATE_ALL);
2808+
return 0;
2809+
}
2810+
27682811
const struct k_clock clock_aux = {
27692812
.clock_getres = aux_get_res,
27702813
.clock_get_timespec = aux_get_timespec,
2814+
.clock_set = aux_clock_set,
27712815
};
27722816

27732817
static __init void tk_aux_setup(void)

0 commit comments

Comments
 (0)