linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [patch V2 00/26] timekeeping: Provide support for auxiliary timekeepers
@ 2025-05-19  8:33 Thomas Gleixner
  2025-05-19  8:33 ` [patch V2 01/26] timekeeping: Remove hardcoded access to tk_core Thomas Gleixner
                   ` (25 more replies)
  0 siblings, 26 replies; 57+ messages in thread
From: Thomas Gleixner @ 2025-05-19  8:33 UTC (permalink / raw)
  To: LKML
  Cc: netdev, Richard Cochran, Christopher Hall, John Stultz,
	Frederic Weisbecker, Anna-Maria Behnsen, Miroslav Lichvar,
	Werner Abt, David Woodhouse, Stephen Boyd, Thomas Weißschuh,
	Kurt Kanzenbach, Nam Cao, Antoine Tenart

This is an update to the initial series, which can be found here:

     https://lore.kernel.org/all/20250513144615.252881431@linutronix.de

The kernel supports PTP clocks pretty well at the hardware level and the
ability to steer the core time keeper, but there is a major gap for other
PTP use cases especially in the context of TSN.

TSN use cases in automation, automotive, audio and other areas utilize PTP
for synchronizing nodes in a network accurately, but the underlying master
clock is not necessarily related to clock TAI. They are completely
independent and just represent a common notion of time in a network for an
application specific purpose. This comes with problems obvioulsy:

   1) Applications have no fast access to the time of such independent PTP
      clocks. The only way is to utilize the file descriptor of the PTP
      device with clock_gettime(). That's slow as it has to go all the way
      out to the hardware.

   2) The network stack cannot access PTP time at all because accessing the
      PTP hardware requires preemptible task context in quite some cases.

There has been attempts to solve this by creating a new PTP specific
infrastructure independent of the core timekeeping code, but that's a
patently bad idea as it would just create duplicated code with new bugs and
also be in the way of supporting these clocks in the VDSO and hrtimers
based on such clocks down the road.

This series addresses the timekeeping part by utilizing the existing
timekeeping and NTP infrastructure, which has been prepared for
multi-instance in recent kernels.

The approach is the same as for core timekeeping:

    The clock readout uses the system clocksource, e.g. TSC, ARM
    architected timer..., and converts it to a "nanoseconds" timestamp with
    the underlying conversion factors.

    The conversion factors are steered via clock_adjtimex(2) to provide the
    required accuracy. That means tools like chrony can be reused with a
    small amount of modifications.

The infrastructure supports up to eight auxiliary clocks and timekeepers,
which can be accessed by the new CLOCK_AUX0 .. CLOCK_AUX7 POSIX clock IDs.

The timekeepers are off by default and can be individually enabled/disabled
via a new sysfs interface. In the disabled case the overhead introduced by
these timekeepers is practically zero. Only if enabled, the periodic update
in the timekeeper tick adds extra work.

The infrastructure provides:

    1) In-kernel time getter interfaces similar to the existing
       ktime_get*() interfaces. The main difference is that they have a
       boolean return value, which indicates whether the clock is enabled
       and valid. These interfaces are lockless and sequence count
       protected as the other ktime_get*() variants, so the same
       restrictions apply (not usable from the timekeeper context or from
       NMI).

    2) clock_gettime() support

       Same as the existing clock_gettime() for CLOCK_..., but returns
       -ENODEV if the clock is disabled.

    3) clock_settime() support

       Same as clock_settime(CLOCK_REALTIME), but does not affect the
       system timekeeping

    4) clock_adjtime() support

       Same as clock_settime(CLOCK_REALTIME), but does not affect the
       system timekeeping. It has some restrictions: no support for PPS,
       leap seconds and other tiny details which are only relevant for
       CLOCK_REALTIME steering.

The timekeeper updates for these auxiliary clocks are not yet propagated to
VDSO and paravirt interfaces as this has to be addressed separately once
the core infrastructure is in place. Thomas W. has a prototype
implementation for the VDSO support ready, which will be posted once the
dust has settled here.

Once the timekeeping infrastructure is in place, the road is paved for
supporting hrtimers on these clocks, which is another problem in the
context of applications and the network stack. The idea is to convert the
independent expiry time to clock MONOTONIC internally under the assumption
that both involved clocks will have halfways stable conversion factors
within the expiry time of the timer. If one of the clocks starts to jump
around via their respective clock_adjtime(2) steering, then there are
bigger problems to solve than a timer expiring late. But that's just an
concept in my head and on some scribbled notes. It will take some time to
materialize. But let's get the timekeeping part sorted first. :)

Changes from V1:

   - Rename to auxiliary clocks/timekeepers - Miroslav

   - Fix the sysfs documentation - Antoine

The series applies on top of 6.15-rc7 + tip timers/core and is available
from git:

  git://git.kernel.org/pub/scm/linux/kernel/git/tglx/devel.git timers/ptp/clocks

Thanks,

	tglx
---
 Documentation/ABI/stable/sysfs-kernel-time-aux-clocks |    5 
 include/linux/timekeeper_internal.h                   |   28 
 include/linux/timekeeping.h                           |   11 
 include/uapi/linux/time.h                             |   11 
 kernel/time/Kconfig                                   |   15 
 kernel/time/ntp.c                                     |   72 +-
 kernel/time/ntp_internal.h                            |   13 
 kernel/time/posix-timers.c                            |    3 
 kernel/time/posix-timers.h                            |    1 
 kernel/time/timekeeping.c                             |  576 +++++++++++++++---
 kernel/time/timekeeping_internal.h                    |    3 
 11 files changed, 619 insertions(+), 119 deletions(-)



^ permalink raw reply	[flat|nested] 57+ messages in thread

* [patch V2 01/26] timekeeping: Remove hardcoded access to tk_core
  2025-05-19  8:33 [patch V2 00/26] timekeeping: Provide support for auxiliary timekeepers Thomas Gleixner
@ 2025-05-19  8:33 ` Thomas Gleixner
  2025-06-12 22:34   ` John Stultz
  2025-06-25 16:16   ` [tip: timers/ptp] " tip-bot2 for Thomas Gleixner
  2025-05-19  8:33 ` [patch V2 02/26] timekeeping: Cleanup kernel doc of __ktime_get_real_seconds() Thomas Gleixner
                   ` (24 subsequent siblings)
  25 siblings, 2 replies; 57+ messages in thread
From: Thomas Gleixner @ 2025-05-19  8:33 UTC (permalink / raw)
  To: LKML
  Cc: netdev, Richard Cochran, Christopher Hall, John Stultz,
	Frederic Weisbecker, Anna-Maria Behnsen, Miroslav Lichvar,
	Werner Abt, David Woodhouse, Stephen Boyd, Thomas Weißschuh,
	Kurt Kanzenbach, Nam Cao, Antoine Tenart

This was overlooked in the initial conversion. Use the provided pointer to
access the shadow timekeeper.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

---
 kernel/time/timekeeping.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
---
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -663,7 +663,7 @@ static void timekeeping_restore_shadow(s
 
 static void timekeeping_update_from_shadow(struct tk_data *tkd, unsigned int action)
 {
-	struct timekeeper *tk = &tk_core.shadow_timekeeper;
+	struct timekeeper *tk = &tkd->shadow_timekeeper;
 
 	lockdep_assert_held(&tkd->lock);
 


^ permalink raw reply	[flat|nested] 57+ messages in thread

* [patch V2 02/26] timekeeping: Cleanup kernel doc of __ktime_get_real_seconds()
  2025-05-19  8:33 [patch V2 00/26] timekeeping: Provide support for auxiliary timekeepers Thomas Gleixner
  2025-05-19  8:33 ` [patch V2 01/26] timekeeping: Remove hardcoded access to tk_core Thomas Gleixner
@ 2025-05-19  8:33 ` Thomas Gleixner
  2025-06-12 22:36   ` John Stultz
  2025-06-25 16:16   ` [tip: timers/ptp] " tip-bot2 for Thomas Gleixner
  2025-05-19  8:33 ` [patch V2 03/26] timekeeping: Avoid double notification in do_adjtimex() Thomas Gleixner
                   ` (23 subsequent siblings)
  25 siblings, 2 replies; 57+ messages in thread
From: Thomas Gleixner @ 2025-05-19  8:33 UTC (permalink / raw)
  To: LKML
  Cc: netdev, Richard Cochran, Christopher Hall, John Stultz,
	Frederic Weisbecker, Anna-Maria Behnsen, Miroslav Lichvar,
	Werner Abt, David Woodhouse, Stephen Boyd, Thomas Weißschuh,
	Kurt Kanzenbach, Nam Cao, Antoine Tenart

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 kernel/time/timekeeping.c |   11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -975,9 +975,14 @@ time64_t ktime_get_real_seconds(void)
 EXPORT_SYMBOL_GPL(ktime_get_real_seconds);
 
 /**
- * __ktime_get_real_seconds - The same as ktime_get_real_seconds
- * but without the sequence counter protect. This internal function
- * is called just when timekeeping lock is already held.
+ * __ktime_get_real_seconds - Unprotected access to CLOCK_REALTIME seconds
+ *
+ * The same as ktime_get_real_seconds() but without the sequence counter
+ * protection. This function is used in restricted contexts like the x86 MCE
+ * handler and in KGDB. It's unprotected on 32-bit vs. concurrent half
+ * completed modification and only to be used for such critical contexts.
+ *
+ * Returns: Racy snapshot of the CLOCK_REALTIME seconds value
  */
 noinstr time64_t __ktime_get_real_seconds(void)
 {


^ permalink raw reply	[flat|nested] 57+ messages in thread

* [patch V2 03/26] timekeeping: Avoid double notification in do_adjtimex()
  2025-05-19  8:33 [patch V2 00/26] timekeeping: Provide support for auxiliary timekeepers Thomas Gleixner
  2025-05-19  8:33 ` [patch V2 01/26] timekeeping: Remove hardcoded access to tk_core Thomas Gleixner
  2025-05-19  8:33 ` [patch V2 02/26] timekeeping: Cleanup kernel doc of __ktime_get_real_seconds() Thomas Gleixner
@ 2025-05-19  8:33 ` Thomas Gleixner
  2025-06-25 16:16   ` [tip: timers/ptp] " tip-bot2 for Thomas Gleixner
  2025-05-19  8:33 ` [patch V2 04/26] timekeeping: Introduce timekeeper ID Thomas Gleixner
                   ` (22 subsequent siblings)
  25 siblings, 1 reply; 57+ messages in thread
From: Thomas Gleixner @ 2025-05-19  8:33 UTC (permalink / raw)
  To: LKML
  Cc: netdev, Richard Cochran, Christopher Hall, John Stultz,
	Frederic Weisbecker, Anna-Maria Behnsen, Miroslav Lichvar,
	Werner Abt, David Woodhouse, Stephen Boyd, Thomas Weißschuh,
	Kurt Kanzenbach, Nam Cao, Antoine Tenart

Consolidate do_adjtimex() so that it does not notify about clock changes
twice.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

---
 kernel/time/timekeeping.c |   98 ++++++++++++++++++++++++++--------------------
 1 file changed, 56 insertions(+), 42 deletions(-)
---
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -1418,40 +1418,49 @@ int do_settimeofday64(const struct times
 EXPORT_SYMBOL(do_settimeofday64);
 
 /**
- * timekeeping_inject_offset - Adds or subtracts from the current time.
+ * __timekeeping_inject_offset - Adds or subtracts from the current time.
  * @ts:		Pointer to the timespec variable containing the offset
  *
  * Adds or subtracts an offset value from the current time.
  */
-static int timekeeping_inject_offset(const struct timespec64 *ts)
+static int __timekeeping_inject_offset(const struct timespec64 *ts)
 {
+	struct timekeeper *tks = &tk_core.shadow_timekeeper;
+	struct timespec64 tmp;
+
 	if (ts->tv_nsec < 0 || ts->tv_nsec >= NSEC_PER_SEC)
 		return -EINVAL;
 
-	scoped_guard (raw_spinlock_irqsave, &tk_core.lock) {
-		struct timekeeper *tks = &tk_core.shadow_timekeeper;
-		struct timespec64 tmp;
-
-		timekeeping_forward_now(tks);
 
-		/* Make sure the proposed value is valid */
-		tmp = timespec64_add(tk_xtime(tks), *ts);
-		if (timespec64_compare(&tks->wall_to_monotonic, ts) > 0 ||
-		    !timespec64_valid_settod(&tmp)) {
-			timekeeping_restore_shadow(&tk_core);
-			return -EINVAL;
-		}
+	timekeeping_forward_now(tks);
 
-		tk_xtime_add(tks, ts);
-		tk_set_wall_to_mono(tks, timespec64_sub(tks->wall_to_monotonic, *ts));
-		timekeeping_update_from_shadow(&tk_core, TK_UPDATE_ALL);
+	/* Make sure the proposed value is valid */
+	tmp = timespec64_add(tk_xtime(tks), *ts);
+	if (timespec64_compare(&tks->wall_to_monotonic, ts) > 0 ||
+	    !timespec64_valid_settod(&tmp)) {
+		timekeeping_restore_shadow(&tk_core);
+		return -EINVAL;
 	}
 
-	/* Signal hrtimers about time change */
-	clock_was_set(CLOCK_SET_WALL);
+	tk_xtime_add(tks, ts);
+	tk_set_wall_to_mono(tks, timespec64_sub(tks->wall_to_monotonic, *ts));
+	timekeeping_update_from_shadow(&tk_core, TK_UPDATE_ALL);
 	return 0;
 }
 
+static int timekeeping_inject_offset(const struct timespec64 *ts)
+{
+	int ret;
+
+	scoped_guard (raw_spinlock_irqsave, &tk_core.lock)
+		ret = __timekeeping_inject_offset(ts);
+
+	/* Signal hrtimers about time change */
+	if (!ret)
+		clock_was_set(CLOCK_SET_WALL);
+	return ret;
+}
+
 /*
  * Indicates if there is an offset between the system clock and the hardware
  * clock/persistent clock/rtc.
@@ -2186,7 +2195,7 @@ static u64 logarithmic_accumulation(stru
  * timekeeping_advance - Updates the timekeeper to the current time and
  * current NTP tick length
  */
-static bool timekeeping_advance(enum timekeeping_adv_mode mode)
+static bool __timekeeping_advance(enum timekeeping_adv_mode mode)
 {
 	struct timekeeper *tk = &tk_core.shadow_timekeeper;
 	struct timekeeper *real_tk = &tk_core.timekeeper;
@@ -2194,8 +2203,6 @@ static bool timekeeping_advance(enum tim
 	int shift = 0, maxshift;
 	u64 offset, orig_offset;
 
-	guard(raw_spinlock_irqsave)(&tk_core.lock);
-
 	/* Make sure we're fully resumed: */
 	if (unlikely(timekeeping_suspended))
 		return false;
@@ -2249,6 +2256,12 @@ static bool timekeeping_advance(enum tim
 	return !!clock_set;
 }
 
+static bool timekeeping_advance(enum timekeeping_adv_mode mode)
+{
+	guard(raw_spinlock_irqsave)(&tk_core.lock);
+	return __timekeeping_advance(mode);
+}
+
 /**
  * update_wall_time - Uses the current clocksource to increment the wall time
  *
@@ -2537,10 +2550,10 @@ EXPORT_SYMBOL_GPL(random_get_entropy_fal
  */
 int do_adjtimex(struct __kernel_timex *txc)
 {
+	struct timespec64 delta, ts;
 	struct audit_ntp_data ad;
 	bool offset_set = false;
 	bool clock_set = false;
-	struct timespec64 ts;
 	int ret;
 
 	/* Validate the data before disabling interrupts */
@@ -2549,21 +2562,6 @@ int do_adjtimex(struct __kernel_timex *t
 		return ret;
 	add_device_randomness(txc, sizeof(*txc));
 
-	if (txc->modes & ADJ_SETOFFSET) {
-		struct timespec64 delta;
-
-		delta.tv_sec  = txc->time.tv_sec;
-		delta.tv_nsec = txc->time.tv_usec;
-		if (!(txc->modes & ADJ_NANO))
-			delta.tv_nsec *= 1000;
-		ret = timekeeping_inject_offset(&delta);
-		if (ret)
-			return ret;
-
-		offset_set = delta.tv_sec != 0;
-		audit_tk_injoffset(delta);
-	}
-
 	audit_ntp_init(&ad);
 
 	ktime_get_real_ts64(&ts);
@@ -2573,6 +2571,19 @@ int do_adjtimex(struct __kernel_timex *t
 		struct timekeeper *tks = &tk_core.shadow_timekeeper;
 		s32 orig_tai, tai;
 
+		if (txc->modes & ADJ_SETOFFSET) {
+			delta.tv_sec  = txc->time.tv_sec;
+			delta.tv_nsec = txc->time.tv_usec;
+			if (!(txc->modes & ADJ_NANO))
+				delta.tv_nsec *= 1000;
+			ret = __timekeeping_inject_offset(&delta);
+			if (ret)
+				return ret;
+
+			offset_set = delta.tv_sec != 0;
+			clock_set = true;
+		}
+
 		orig_tai = tai = tks->tai_offset;
 		ret = __do_adjtimex(txc, &ts, &tai, &ad);
 
@@ -2583,13 +2594,16 @@ int do_adjtimex(struct __kernel_timex *t
 		} else {
 			tk_update_leap_state_all(&tk_core);
 		}
+
+		/* Update the multiplier immediately if frequency was set directly */
+		if (txc->modes & (ADJ_FREQUENCY | ADJ_TICK))
+			clock_set |= __timekeeping_advance(TK_ADV_FREQ);
 	}
 
-	audit_ntp_log(&ad);
+	if (txc->modes & ADJ_SETOFFSET)
+		audit_tk_injoffset(delta);
 
-	/* Update the multiplier immediately if frequency was set directly */
-	if (txc->modes & (ADJ_FREQUENCY | ADJ_TICK))
-		clock_set |= timekeeping_advance(TK_ADV_FREQ);
+	audit_ntp_log(&ad);
 
 	if (clock_set)
 		clock_was_set(CLOCK_SET_WALL);


^ permalink raw reply	[flat|nested] 57+ messages in thread

* [patch V2 04/26] timekeeping: Introduce timekeeper ID
  2025-05-19  8:33 [patch V2 00/26] timekeeping: Provide support for auxiliary timekeepers Thomas Gleixner
                   ` (2 preceding siblings ...)
  2025-05-19  8:33 ` [patch V2 03/26] timekeeping: Avoid double notification in do_adjtimex() Thomas Gleixner
@ 2025-05-19  8:33 ` Thomas Gleixner
  2025-06-13  0:03   ` John Stultz
  2025-06-25 16:16   ` [tip: timers/ptp] " tip-bot2 for Anna-Maria Behnsen
  2025-05-19  8:33 ` [patch V2 05/26] time: Introduce auxiliary POSIX clocks Thomas Gleixner
                   ` (21 subsequent siblings)
  25 siblings, 2 replies; 57+ messages in thread
From: Thomas Gleixner @ 2025-05-19  8:33 UTC (permalink / raw)
  To: LKML
  Cc: netdev, Richard Cochran, Christopher Hall, John Stultz,
	Frederic Weisbecker, Anna-Maria Behnsen, Miroslav Lichvar,
	Werner Abt, David Woodhouse, Stephen Boyd, Thomas Weißschuh,
	Kurt Kanzenbach, Nam Cao, Antoine Tenart

From: Anna-Maria Behnsen <anna-maria@linutronix.de>

As long as there is only a single timekeeper, there is no need to clarify
which timekeeper is used. But with the upcoming reusage of the timekeeper
infrastructure for auxiliary clock timekeepers, an ID is required to
differentiate.

Introduce an enum for timekeeper IDs, introduce a field in struct tk_data
to store this timekeeper id and add also initialization. The id struct
field is added at the end of the second cachline, as there is a 4 byte hole
anyway.

Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

---
 include/linux/timekeeper_internal.h |   14 +++++++++++++-
 kernel/time/timekeeping.c           |    5 +++--
 2 files changed, 16 insertions(+), 3 deletions(-)
---
--- a/include/linux/timekeeper_internal.h
+++ b/include/linux/timekeeper_internal.h
@@ -12,6 +12,16 @@
 #include <linux/time.h>
 
 /**
+ * timekeeper_ids - IDs for various time keepers in the kernel
+ * @TIMEKEEPER_CORE:	The central core timekeeper managing system time
+ * @TIMEKEEPERS_MAX:	The maximum number of timekeepers managed
+ */
+enum timekeeper_ids {
+	TIMEKEEPER_CORE,
+	TIMEKEEPERS_MAX,
+};
+
+/**
  * struct tk_read_base - base structure for timekeeping readout
  * @clock:	Current clocksource used for timekeeping.
  * @mask:	Bitmask for two's complement subtraction of non 64bit clocks
@@ -52,6 +62,7 @@ struct tk_read_base {
  * @offs_boot:			Offset clock monotonic -> clock boottime
  * @offs_tai:			Offset clock monotonic -> clock tai
  * @coarse_nsec:		The nanoseconds part for coarse time getters
+ * @id:				The timekeeper ID
  * @tkr_raw:			The readout base structure for CLOCK_MONOTONIC_RAW
  * @raw_sec:			CLOCK_MONOTONIC_RAW  time in seconds
  * @clock_was_set_seq:		The sequence number of clock was set events
@@ -101,7 +112,7 @@ struct tk_read_base {
  * which results in the following cacheline layout:
  *
  * 0:	seqcount, tkr_mono
- * 1:	xtime_sec ... coarse_nsec
+ * 1:	xtime_sec ... id
  * 2:	tkr_raw, raw_sec
  * 3,4: Internal variables
  *
@@ -123,6 +134,7 @@ struct timekeeper {
 	ktime_t			offs_boot;
 	ktime_t			offs_tai;
 	u32			coarse_nsec;
+	enum timekeeper_ids	id;
 
 	/* Cacheline 2: */
 	struct tk_read_base	tkr_raw;
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -1663,10 +1663,11 @@ read_persistent_wall_and_boot_offset(str
 	*boot_offset = ns_to_timespec64(local_clock());
 }
 
-static __init void tkd_basic_setup(struct tk_data *tkd)
+static __init void tkd_basic_setup(struct tk_data *tkd, enum timekeeper_ids tk_id)
 {
 	raw_spin_lock_init(&tkd->lock);
 	seqcount_raw_spinlock_init(&tkd->seq, &tkd->lock);
+	tkd->timekeeper.id = tkd->shadow_timekeeper.id = tk_id;
 }
 
 /*
@@ -1696,7 +1697,7 @@ void __init timekeeping_init(void)
 	struct timekeeper *tks = &tk_core.shadow_timekeeper;
 	struct clocksource *clock;
 
-	tkd_basic_setup(&tk_core);
+	tkd_basic_setup(&tk_core, TIMEKEEPER_CORE);
 
 	read_persistent_wall_and_boot_offset(&wall_time, &boot_offset);
 	if (timespec64_valid_settod(&wall_time) &&


^ permalink raw reply	[flat|nested] 57+ messages in thread

* [patch V2 05/26] time: Introduce auxiliary POSIX clocks
  2025-05-19  8:33 [patch V2 00/26] timekeeping: Provide support for auxiliary timekeepers Thomas Gleixner
                   ` (3 preceding siblings ...)
  2025-05-19  8:33 ` [patch V2 04/26] timekeeping: Introduce timekeeper ID Thomas Gleixner
@ 2025-05-19  8:33 ` Thomas Gleixner
  2025-06-13  0:06   ` John Stultz
  2025-06-25 16:16   ` [tip: timers/ptp] " tip-bot2 for Anna-Maria Behnsen
  2025-05-19  8:33 ` [patch V2 06/26] ntp: Add support for auxiliary timekeepers Thomas Gleixner
                   ` (20 subsequent siblings)
  25 siblings, 2 replies; 57+ messages in thread
From: Thomas Gleixner @ 2025-05-19  8:33 UTC (permalink / raw)
  To: LKML
  Cc: netdev, Richard Cochran, Christopher Hall, John Stultz,
	Frederic Weisbecker, Anna-Maria Behnsen, Miroslav Lichvar,
	Werner Abt, David Woodhouse, Stephen Boyd, Thomas Weißschuh,
	Kurt Kanzenbach, Nam Cao, Antoine Tenart

From: Anna-Maria Behnsen <anna-maria@linutronix.de>

To support auxiliary timekeeping and the related user space interfaces,
it's required to define a clock ID range for them.

Reserve 8 auxiliary clock IDs after the regular timekeeping clock ID space.

This is the maximum number of auxiliary clocks the kernel can support. The actual
number of supported clocks depends obviously on the presence of related devices
and might be constraint by the available VDSO space.

Add the corresponding timekeeper IDs as well.

Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

---
 include/linux/timekeeper_internal.h |    6 ++++++
 include/uapi/linux/time.h           |   11 +++++++++++
 kernel/time/Kconfig                 |   15 +++++++++++++--
 3 files changed, 30 insertions(+), 2 deletions(-)
---
--- a/include/linux/timekeeper_internal.h
+++ b/include/linux/timekeeper_internal.h
@@ -14,10 +14,16 @@
 /**
  * timekeeper_ids - IDs for various time keepers in the kernel
  * @TIMEKEEPER_CORE:	The central core timekeeper managing system time
+ * @TIMEKEEPER_AUX:	The first AUX timekeeper
+ * @TIMEKEEPER_AUX_LAST:The last AUX timekeeper
  * @TIMEKEEPERS_MAX:	The maximum number of timekeepers managed
  */
 enum timekeeper_ids {
 	TIMEKEEPER_CORE,
+#ifdef CONFIG_POSIX_AUX_CLOCKS
+	TIMEKEEPER_AUX,
+	TIMEKEEPER_AUX_LAST = TIMEKEEPER_AUX + MAX_AUX_CLOCKS - 1,
+#endif
 	TIMEKEEPERS_MAX,
 };
 
--- a/include/uapi/linux/time.h
+++ b/include/uapi/linux/time.h
@@ -64,6 +64,17 @@ struct timezone {
 #define CLOCK_TAI			11
 
 #define MAX_CLOCKS			16
+
+/*
+ * AUX clock support. AUXiliary clocks are dynamically configured by
+ * enabling a clock ID. These clock can be steered independently of the
+ * core timekeeper. The kernel can support up to 8 auxiliary clocks, but
+ * the actual limit depends on eventual architecture constraints vs. VDSO.
+ */
+#define	CLOCK_AUX			MAX_CLOCKS
+#define	MAX_AUX_CLOCKS			8
+#define CLOCK_AUX_LAST			(CLOCK_AUX + MAX_AUX_CLOCKS - 1)
+
 #define CLOCKS_MASK			(CLOCK_REALTIME | CLOCK_MONOTONIC)
 #define CLOCKS_MONO			CLOCK_MONOTONIC
 
--- a/kernel/time/Kconfig
+++ b/kernel/time/Kconfig
@@ -82,9 +82,9 @@ config CONTEXT_TRACKING_IDLE
 	help
 	  Tracks idle state on behalf of RCU.
 
-if GENERIC_CLOCKEVENTS
 menu "Timers subsystem"
 
+if GENERIC_CLOCKEVENTS
 # Core internal switch. Selected by NO_HZ_COMMON / HIGH_RES_TIMERS. This is
 # only related to the tick functionality. Oneshot clockevent devices
 # are supported independent of this.
@@ -208,6 +208,17 @@ config CLOCKSOURCE_WATCHDOG_MAX_SKEW_US
 	  interval and NTP's maximum frequency drift of 500 parts
 	  per million.	If the clocksource is good enough for NTP,
 	  it is good enough for the clocksource watchdog!
+endif
+
+config POSIX_AUX_CLOCKS
+	bool "Enable auxiliary POSIX clocks"
+	depends on POSIX_TIMERS
+	help
+	  Auxiliary POSIX clocks are clocks which can be steered
+	  independently of the core timekeeper, which controls the
+	  MONOTONIC, REALTIME, BOOTTIME and TAI clocks.  They are useful to
+	  provide e.g. lockless time accessors to independent PTP clocks
+	  and other clock domains, which are not correlated to the TAI/NTP
+	  notion of time.
 
 endmenu
-endif


^ permalink raw reply	[flat|nested] 57+ messages in thread

* [patch V2 06/26] ntp: Add support for auxiliary timekeepers
  2025-05-19  8:33 [patch V2 00/26] timekeeping: Provide support for auxiliary timekeepers Thomas Gleixner
                   ` (4 preceding siblings ...)
  2025-05-19  8:33 ` [patch V2 05/26] time: Introduce auxiliary POSIX clocks Thomas Gleixner
@ 2025-05-19  8:33 ` Thomas Gleixner
  2025-06-13  0:14   ` John Stultz
                     ` (2 more replies)
  2025-05-19  8:33 ` [patch V2 07/26] ntp: Add timekeeper ID arguments to public functions Thomas Gleixner
                   ` (19 subsequent siblings)
  25 siblings, 3 replies; 57+ messages in thread
From: Thomas Gleixner @ 2025-05-19  8:33 UTC (permalink / raw)
  To: LKML
  Cc: netdev, Richard Cochran, Christopher Hall, John Stultz,
	Frederic Weisbecker, Anna-Maria Behnsen, Miroslav Lichvar,
	Werner Abt, David Woodhouse, Stephen Boyd, Thomas Weißschuh,
	Kurt Kanzenbach, Nam Cao, Antoine Tenart

If auxiliary clocks are enabled, provide an array of NTP data so that the
auxiliary timekeepers can be steered independently of the core timekeeper.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 kernel/time/ntp.c |   41 ++++++++++++++++++++++-------------------
 1 file changed, 22 insertions(+), 19 deletions(-)
---
--- a/kernel/time/ntp.c
+++ b/kernel/time/ntp.c
@@ -18,6 +18,7 @@
 #include <linux/module.h>
 #include <linux/rtc.h>
 #include <linux/audit.h>
+#include <linux/timekeeper_internal.h>
 
 #include "ntp_internal.h"
 #include "timekeeping_internal.h"
@@ -86,14 +87,16 @@ struct ntp_data {
 #endif
 };
 
-static struct ntp_data tk_ntp_data = {
-	.tick_usec		= USER_TICK_USEC,
-	.time_state		= TIME_OK,
-	.time_status		= STA_UNSYNC,
-	.time_constant		= 2,
-	.time_maxerror		= NTP_PHASE_LIMIT,
-	.time_esterror		= NTP_PHASE_LIMIT,
-	.ntp_next_leap_sec	= TIME64_MAX,
+static struct ntp_data tk_ntp_data[TIMEKEEPERS_MAX] = {
+	[ 0 ... TIMEKEEPERS_MAX - 1 ] = {
+		.tick_usec		= USER_TICK_USEC,
+		.time_state		= TIME_OK,
+		.time_status		= STA_UNSYNC,
+		.time_constant		= 2,
+		.time_maxerror		= NTP_PHASE_LIMIT,
+		.time_esterror		= NTP_PHASE_LIMIT,
+		.ntp_next_leap_sec	= TIME64_MAX,
+	},
 };
 
 #define SECS_PER_DAY		86400
@@ -351,13 +354,13 @@ static void __ntp_clear(struct ntp_data
  */
 void ntp_clear(void)
 {
-	__ntp_clear(&tk_ntp_data);
+	__ntp_clear(&tk_ntp_data[TIMEKEEPER_CORE]);
 }
 
 
 u64 ntp_tick_length(void)
 {
-	return tk_ntp_data.tick_length;
+	return tk_ntp_data[TIMEKEEPER_CORE].tick_length;
 }
 
 /**
@@ -368,7 +371,7 @@ u64 ntp_tick_length(void)
  */
 ktime_t ntp_get_next_leap(void)
 {
-	struct ntp_data *ntpdata = &tk_ntp_data;
+	struct ntp_data *ntpdata = &tk_ntp_data[TIMEKEEPER_CORE];
 	ktime_t ret;
 
 	if ((ntpdata->time_state == TIME_INS) && (ntpdata->time_status & STA_INS))
@@ -389,7 +392,7 @@ ktime_t ntp_get_next_leap(void)
  */
 int second_overflow(time64_t secs)
 {
-	struct ntp_data *ntpdata = &tk_ntp_data;
+	struct ntp_data *ntpdata = &tk_ntp_data[TIMEKEEPER_CORE];
 	s64 delta;
 	int leap = 0;
 	s32 rem;
@@ -605,7 +608,7 @@ static inline int update_rtc(struct time
  */
 static inline bool ntp_synced(void)
 {
-	return !(tk_ntp_data.time_status & STA_UNSYNC);
+	return !(tk_ntp_data[TIMEKEEPER_CORE].time_status & STA_UNSYNC);
 }
 
 /*
@@ -762,7 +765,7 @@ static inline void process_adjtimex_mode
 int __do_adjtimex(struct __kernel_timex *txc, const struct timespec64 *ts,
 		  s32 *time_tai, struct audit_ntp_data *ad)
 {
-	struct ntp_data *ntpdata = &tk_ntp_data;
+	struct ntp_data *ntpdata = &tk_ntp_data[TIMEKEEPER_CORE];
 	int result;
 
 	if (txc->modes & ADJ_ADJTIME) {
@@ -1031,8 +1034,8 @@ static void hardpps_update_phase(struct
  */
 void __hardpps(const struct timespec64 *phase_ts, const struct timespec64 *raw_ts)
 {
+	struct ntp_data *ntpdata = &tk_ntp_data[TIMEKEEPER_CORE];
 	struct pps_normtime pts_norm, freq_norm;
-	struct ntp_data *ntpdata = &tk_ntp_data;
 
 	pts_norm = pps_normalize_ts(*phase_ts);
 
@@ -1083,18 +1086,18 @@ void __hardpps(const struct timespec64 *
 
 static int __init ntp_tick_adj_setup(char *str)
 {
-	int rc = kstrtos64(str, 0, &tk_ntp_data.ntp_tick_adj);
+	int rc = kstrtos64(str, 0, &tk_ntp_data[TIMEKEEPER_CORE].ntp_tick_adj);
 	if (rc)
 		return rc;
 
-	tk_ntp_data.ntp_tick_adj <<= NTP_SCALE_SHIFT;
+	tk_ntp_data[TIMEKEEPER_CORE].ntp_tick_adj <<= NTP_SCALE_SHIFT;
 	return 1;
 }
-
 __setup("ntp_tick_adj=", ntp_tick_adj_setup);
 
 void __init ntp_init(void)
 {
-	ntp_clear();
+	for (int id = 0; id < TIMEKEEPERS_MAX; id++)
+		__ntp_clear(tk_ntp_data + id);
 	ntp_init_cmos_sync();
 }


^ permalink raw reply	[flat|nested] 57+ messages in thread

* [patch V2 07/26] ntp: Add timekeeper ID arguments to public functions
  2025-05-19  8:33 [patch V2 00/26] timekeeping: Provide support for auxiliary timekeepers Thomas Gleixner
                   ` (5 preceding siblings ...)
  2025-05-19  8:33 ` [patch V2 06/26] ntp: Add support for auxiliary timekeepers Thomas Gleixner
@ 2025-05-19  8:33 ` Thomas Gleixner
  2025-06-13  0:20   ` John Stultz
  2025-06-25 16:16   ` [tip: timers/ptp] " tip-bot2 for Thomas Gleixner
  2025-05-19  8:33 ` [patch V2 08/26] ntp: Rename __do_adjtimex() to ntp_adjtimex() Thomas Gleixner
                   ` (18 subsequent siblings)
  25 siblings, 2 replies; 57+ messages in thread
From: Thomas Gleixner @ 2025-05-19  8:33 UTC (permalink / raw)
  To: LKML
  Cc: netdev, Richard Cochran, Christopher Hall, John Stultz,
	Frederic Weisbecker, Anna-Maria Behnsen, Miroslav Lichvar,
	Werner Abt, David Woodhouse, Stephen Boyd, Thomas Weißschuh,
	Kurt Kanzenbach, Nam Cao, Antoine Tenart

In preparation for supporting auxiliary POSIX clocks, add a timekeeper ID
to the relevant functions.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

---
 kernel/time/ntp.c          |   33 +++++++++++++++++++--------------
 kernel/time/ntp_internal.h |   11 +++++------
 kernel/time/timekeeping.c  |   12 ++++++------
 3 files changed, 30 insertions(+), 26 deletions(-)
---
--- a/kernel/time/ntp.c
+++ b/kernel/time/ntp.c
@@ -351,33 +351,38 @@ static void __ntp_clear(struct ntp_data
 
 /**
  * ntp_clear - Clears the NTP state variables
+ * @tkid:	Timekeeper ID to be able to select proper ntp data array member
  */
-void ntp_clear(void)
+void ntp_clear(unsigned int tkid)
 {
-	__ntp_clear(&tk_ntp_data[TIMEKEEPER_CORE]);
+	__ntp_clear(&tk_ntp_data[tkid]);
 }
 
 
-u64 ntp_tick_length(void)
+u64 ntp_tick_length(unsigned int tkid)
 {
-	return tk_ntp_data[TIMEKEEPER_CORE].tick_length;
+	return tk_ntp_data[tkid].tick_length;
 }
 
 /**
  * ntp_get_next_leap - Returns the next leapsecond in CLOCK_REALTIME ktime_t
+ * @tkid:	Timekeeper ID
  *
- * Provides the time of the next leapsecond against CLOCK_REALTIME in
- * a ktime_t format. Returns KTIME_MAX if no leapsecond is pending.
+ * Returns: For @tkid == TIMEKEEPER_CORE this provides the time of the next
+ *	    leap second against CLOCK_REALTIME in a ktime_t format if a
+ *	    leap second is pending. KTIME_MAX otherwise.
  */
-ktime_t ntp_get_next_leap(void)
+ktime_t ntp_get_next_leap(unsigned int tkid)
 {
 	struct ntp_data *ntpdata = &tk_ntp_data[TIMEKEEPER_CORE];
-	ktime_t ret;
+
+	if (tkid != TIMEKEEPER_CORE)
+		return KTIME_MAX;
 
 	if ((ntpdata->time_state == TIME_INS) && (ntpdata->time_status & STA_INS))
 		return ktime_set(ntpdata->ntp_next_leap_sec, 0);
-	ret = KTIME_MAX;
-	return ret;
+
+	return KTIME_MAX;
 }
 
 /*
@@ -390,9 +395,9 @@ ktime_t ntp_get_next_leap(void)
  *
  * Also handles leap second processing, and returns leap offset
  */
-int second_overflow(time64_t secs)
+int second_overflow(unsigned int tkid, time64_t secs)
 {
-	struct ntp_data *ntpdata = &tk_ntp_data[TIMEKEEPER_CORE];
+	struct ntp_data *ntpdata = &tk_ntp_data[tkid];
 	s64 delta;
 	int leap = 0;
 	s32 rem;
@@ -762,10 +767,10 @@ static inline void process_adjtimex_mode
  * adjtimex() mainly allows reading (and writing, if superuser) of
  * kernel time-keeping variables. used by xntpd.
  */
-int __do_adjtimex(struct __kernel_timex *txc, const struct timespec64 *ts,
+int __do_adjtimex(unsigned int tkid, struct __kernel_timex *txc, const struct timespec64 *ts,
 		  s32 *time_tai, struct audit_ntp_data *ad)
 {
-	struct ntp_data *ntpdata = &tk_ntp_data[TIMEKEEPER_CORE];
+	struct ntp_data *ntpdata = &tk_ntp_data[tkid];
 	int result;
 
 	if (txc->modes & ADJ_ADJTIME) {
--- a/kernel/time/ntp_internal.h
+++ b/kernel/time/ntp_internal.h
@@ -3,13 +3,12 @@
 #define _LINUX_NTP_INTERNAL_H
 
 extern void ntp_init(void);
-extern void ntp_clear(void);
+extern void ntp_clear(unsigned int tkid);
 /* Returns how long ticks are at present, in ns / 2^NTP_SCALE_SHIFT. */
-extern u64 ntp_tick_length(void);
-extern ktime_t ntp_get_next_leap(void);
-extern int second_overflow(time64_t secs);
-extern int __do_adjtimex(struct __kernel_timex *txc,
-			 const struct timespec64 *ts,
+extern u64 ntp_tick_length(unsigned int tkid);
+extern ktime_t ntp_get_next_leap(unsigned int tkid);
+extern int second_overflow(unsigned int tkid, time64_t secs);
+extern int __do_adjtimex(unsigned int tkid, struct __kernel_timex *txc, const struct timespec64 *ts,
 			 s32 *time_tai, struct audit_ntp_data *ad);
 extern void __hardpps(const struct timespec64 *phase_ts, const struct timespec64 *raw_ts);
 
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -601,7 +601,7 @@ EXPORT_SYMBOL_GPL(pvclock_gtod_unregiste
  */
 static inline void tk_update_leap_state(struct timekeeper *tk)
 {
-	tk->next_leap_ktime = ntp_get_next_leap();
+	tk->next_leap_ktime = ntp_get_next_leap(tk->id);
 	if (tk->next_leap_ktime != KTIME_MAX)
 		/* Convert to monotonic time */
 		tk->next_leap_ktime = ktime_sub(tk->next_leap_ktime, tk->offs_real);
@@ -678,7 +678,7 @@ static void timekeeping_update_from_shad
 
 	if (action & TK_CLEAR_NTP) {
 		tk->ntp_error = 0;
-		ntp_clear();
+		ntp_clear(tk->id);
 	}
 
 	tk_update_leap_state(tk);
@@ -2049,7 +2049,7 @@ static __always_inline void timekeeping_
  */
 static void timekeeping_adjust(struct timekeeper *tk, s64 offset)
 {
-	u64 ntp_tl = ntp_tick_length();
+	u64 ntp_tl = ntp_tick_length(tk->id);
 	u32 mult;
 
 	/*
@@ -2130,7 +2130,7 @@ static inline unsigned int accumulate_ns
 		}
 
 		/* Figure out if its a leap sec and apply if needed */
-		leap = second_overflow(tk->xtime_sec);
+		leap = second_overflow(tk->id, tk->xtime_sec);
 		if (unlikely(leap)) {
 			struct timespec64 ts;
 
@@ -2227,7 +2227,7 @@ static bool __timekeeping_advance(enum t
 	shift = ilog2(offset) - ilog2(tk->cycle_interval);
 	shift = max(0, shift);
 	/* Bound shift to one less than what overflows tick_length */
-	maxshift = (64 - (ilog2(ntp_tick_length())+1)) - 1;
+	maxshift = (64 - (ilog2(ntp_tick_length(tk->id)) + 1)) - 1;
 	shift = min(shift, maxshift);
 	while (offset >= tk->cycle_interval) {
 		offset = logarithmic_accumulation(tk, offset, shift, &clock_set);
@@ -2586,7 +2586,7 @@ int do_adjtimex(struct __kernel_timex *t
 		}
 
 		orig_tai = tai = tks->tai_offset;
-		ret = __do_adjtimex(txc, &ts, &tai, &ad);
+		ret = __do_adjtimex(tks->id, txc, &ts, &tai, &ad);
 
 		if (tai != orig_tai) {
 			__timekeeping_set_tai_offset(tks, tai);


^ permalink raw reply	[flat|nested] 57+ messages in thread

* [patch V2 08/26] ntp: Rename __do_adjtimex() to ntp_adjtimex()
  2025-05-19  8:33 [patch V2 00/26] timekeeping: Provide support for auxiliary timekeepers Thomas Gleixner
                   ` (6 preceding siblings ...)
  2025-05-19  8:33 ` [patch V2 07/26] ntp: Add timekeeper ID arguments to public functions Thomas Gleixner
@ 2025-05-19  8:33 ` Thomas Gleixner
  2025-06-13  0:20   ` John Stultz
  2025-06-25 16:16   ` [tip: timers/ptp] " tip-bot2 for Thomas Gleixner
  2025-05-19  8:33 ` [patch V2 09/26] timekeeping: Make __timekeeping_advance() reusable Thomas Gleixner
                   ` (17 subsequent siblings)
  25 siblings, 2 replies; 57+ messages in thread
From: Thomas Gleixner @ 2025-05-19  8:33 UTC (permalink / raw)
  To: LKML
  Cc: netdev, Richard Cochran, Christopher Hall, John Stultz,
	Frederic Weisbecker, Anna-Maria Behnsen, Miroslav Lichvar,
	Werner Abt, David Woodhouse, Stephen Boyd, Thomas Weißschuh,
	Kurt Kanzenbach, Nam Cao, Antoine Tenart

Clean up the name space. No functional change.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

---
 kernel/time/ntp.c          |    4 ++--
 kernel/time/ntp_internal.h |    4 ++--
 kernel/time/timekeeping.c  |    2 +-
 3 files changed, 5 insertions(+), 5 deletions(-)
---
--- a/kernel/time/ntp.c
+++ b/kernel/time/ntp.c
@@ -767,8 +767,8 @@ static inline void process_adjtimex_mode
  * adjtimex() mainly allows reading (and writing, if superuser) of
  * kernel time-keeping variables. used by xntpd.
  */
-int __do_adjtimex(unsigned int tkid, struct __kernel_timex *txc, const struct timespec64 *ts,
-		  s32 *time_tai, struct audit_ntp_data *ad)
+int ntp_adjtimex(unsigned int tkid, struct __kernel_timex *txc, const struct timespec64 *ts,
+		 s32 *time_tai, struct audit_ntp_data *ad)
 {
 	struct ntp_data *ntpdata = &tk_ntp_data[tkid];
 	int result;
--- a/kernel/time/ntp_internal.h
+++ b/kernel/time/ntp_internal.h
@@ -8,8 +8,8 @@ extern void ntp_clear(unsigned int tkid)
 extern u64 ntp_tick_length(unsigned int tkid);
 extern ktime_t ntp_get_next_leap(unsigned int tkid);
 extern int second_overflow(unsigned int tkid, time64_t secs);
-extern int __do_adjtimex(unsigned int tkid, struct __kernel_timex *txc, const struct timespec64 *ts,
-			 s32 *time_tai, struct audit_ntp_data *ad);
+extern int ntp_adjtimex(unsigned int tkid, struct __kernel_timex *txc, const struct timespec64 *ts,
+			s32 *time_tai, struct audit_ntp_data *ad);
 extern void __hardpps(const struct timespec64 *phase_ts, const struct timespec64 *raw_ts);
 
 #if defined(CONFIG_GENERIC_CMOS_UPDATE) || defined(CONFIG_RTC_SYSTOHC)
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -2586,7 +2586,7 @@ int do_adjtimex(struct __kernel_timex *t
 		}
 
 		orig_tai = tai = tks->tai_offset;
-		ret = __do_adjtimex(tks->id, txc, &ts, &tai, &ad);
+		ret = ntp_adjtimex(tks->id, txc, &ts, &tai, &ad);
 
 		if (tai != orig_tai) {
 			__timekeeping_set_tai_offset(tks, tai);


^ permalink raw reply	[flat|nested] 57+ messages in thread

* [patch V2 09/26] timekeeping: Make __timekeeping_advance() reusable
  2025-05-19  8:33 [patch V2 00/26] timekeeping: Provide support for auxiliary timekeepers Thomas Gleixner
                   ` (7 preceding siblings ...)
  2025-05-19  8:33 ` [patch V2 08/26] ntp: Rename __do_adjtimex() to ntp_adjtimex() Thomas Gleixner
@ 2025-05-19  8:33 ` Thomas Gleixner
  2025-06-13  0:23   ` John Stultz
  2025-06-25 16:16   ` [tip: timers/ptp] " tip-bot2 for Anna-Maria Behnsen
  2025-05-19  8:33 ` [patch V2 10/26] timekeeping: Prepare timekeeping_update_from_shadow() Thomas Gleixner
                   ` (16 subsequent siblings)
  25 siblings, 2 replies; 57+ messages in thread
From: Thomas Gleixner @ 2025-05-19  8:33 UTC (permalink / raw)
  To: LKML
  Cc: netdev, Richard Cochran, Christopher Hall, John Stultz,
	Frederic Weisbecker, Anna-Maria Behnsen, Miroslav Lichvar,
	Werner Abt, David Woodhouse, Stephen Boyd, Thomas Weißschuh,
	Kurt Kanzenbach, Nam Cao, Antoine Tenart

From: Anna-Maria Behnsen <anna-maria@linutronix.de>

In __timekeeping_advance() the pointer to struct tk_data is hardcoded by the
use of &tk_core. As long as there is only a single timekeeper (tk_core),
this is not a problem. But when __timekeeping_advance() will be reused for
per auxiliary timekeepers, __timekeeping_advance() needs to be generalized.

Add a pointer to struct tk_data as function argument of
__timekeeping_advance() and adapt all call sites.

Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

---
 kernel/time/timekeeping.c |   12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)
---
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -2196,10 +2196,10 @@ static u64 logarithmic_accumulation(stru
  * timekeeping_advance - Updates the timekeeper to the current time and
  * current NTP tick length
  */
-static bool __timekeeping_advance(enum timekeeping_adv_mode mode)
+static bool __timekeeping_advance(struct tk_data *tkd, enum timekeeping_adv_mode mode)
 {
-	struct timekeeper *tk = &tk_core.shadow_timekeeper;
-	struct timekeeper *real_tk = &tk_core.timekeeper;
+	struct timekeeper *tk = &tkd->shadow_timekeeper;
+	struct timekeeper *real_tk = &tkd->timekeeper;
 	unsigned int clock_set = 0;
 	int shift = 0, maxshift;
 	u64 offset, orig_offset;
@@ -2252,7 +2252,7 @@ static bool __timekeeping_advance(enum t
 	if (orig_offset != offset)
 		tk_update_coarse_nsecs(tk);
 
-	timekeeping_update_from_shadow(&tk_core, clock_set);
+	timekeeping_update_from_shadow(tkd, clock_set);
 
 	return !!clock_set;
 }
@@ -2260,7 +2260,7 @@ static bool __timekeeping_advance(enum t
 static bool timekeeping_advance(enum timekeeping_adv_mode mode)
 {
 	guard(raw_spinlock_irqsave)(&tk_core.lock);
-	return __timekeeping_advance(mode);
+	return __timekeeping_advance(&tk_core, mode);
 }
 
 /**
@@ -2598,7 +2598,7 @@ int do_adjtimex(struct __kernel_timex *t
 
 		/* Update the multiplier immediately if frequency was set directly */
 		if (txc->modes & (ADJ_FREQUENCY | ADJ_TICK))
-			clock_set |= __timekeeping_advance(TK_ADV_FREQ);
+			clock_set |= __timekeeping_advance(&tk_core, TK_ADV_FREQ);
 	}
 
 	if (txc->modes & ADJ_SETOFFSET)


^ permalink raw reply	[flat|nested] 57+ messages in thread

* [patch V2 10/26] timekeeping: Prepare timekeeping_update_from_shadow()
  2025-05-19  8:33 [patch V2 00/26] timekeeping: Provide support for auxiliary timekeepers Thomas Gleixner
                   ` (8 preceding siblings ...)
  2025-05-19  8:33 ` [patch V2 09/26] timekeeping: Make __timekeeping_advance() reusable Thomas Gleixner
@ 2025-05-19  8:33 ` Thomas Gleixner
  2025-06-25 16:16   ` [tip: timers/ptp] " tip-bot2 for Thomas Gleixner
  2025-05-19  8:33 ` [patch V2 11/26] timekeeping: Add clock_valid flag to timekeeper Thomas Gleixner
                   ` (15 subsequent siblings)
  25 siblings, 1 reply; 57+ messages in thread
From: Thomas Gleixner @ 2025-05-19  8:33 UTC (permalink / raw)
  To: LKML
  Cc: netdev, Richard Cochran, Christopher Hall, John Stultz,
	Frederic Weisbecker, Anna-Maria Behnsen, Miroslav Lichvar,
	Werner Abt, David Woodhouse, Stephen Boyd, Thomas Weißschuh,
	Kurt Kanzenbach, Nam Cao, Antoine Tenart

From: Thomas Gleixner <tglx@linutronix.de>

Don't invoke the VDSO and paravirt updates when utilized for auxiliary
clocks. This is a temporary workaround until the VDSO and paravirt
interfaces have been worked out.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

---
 kernel/time/timekeeping.c |   12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)
---
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -683,13 +683,15 @@ static void timekeeping_update_from_shad
 
 	tk_update_leap_state(tk);
 	tk_update_ktime_data(tk);
+	tk->tkr_mono.base_real = tk->tkr_mono.base + tk->offs_real;
 
-	update_vsyscall(tk);
-	update_pvclock_gtod(tk, action & TK_CLOCK_WAS_SET);
+	if (tk->id == TIMEKEEPER_CORE) {
+		update_vsyscall(tk);
+		update_pvclock_gtod(tk, action & TK_CLOCK_WAS_SET);
 
-	tk->tkr_mono.base_real = tk->tkr_mono.base + tk->offs_real;
-	update_fast_timekeeper(&tk->tkr_mono, &tk_fast_mono);
-	update_fast_timekeeper(&tk->tkr_raw,  &tk_fast_raw);
+		update_fast_timekeeper(&tk->tkr_mono, &tk_fast_mono);
+		update_fast_timekeeper(&tk->tkr_raw,  &tk_fast_raw);
+	}
 
 	if (action & TK_CLOCK_WAS_SET)
 		tk->clock_was_set_seq++;


^ permalink raw reply	[flat|nested] 57+ messages in thread

* [patch V2 11/26] timekeeping: Add clock_valid flag to timekeeper
  2025-05-19  8:33 [patch V2 00/26] timekeeping: Provide support for auxiliary timekeepers Thomas Gleixner
                   ` (9 preceding siblings ...)
  2025-05-19  8:33 ` [patch V2 10/26] timekeeping: Prepare timekeeping_update_from_shadow() Thomas Gleixner
@ 2025-05-19  8:33 ` Thomas Gleixner
  2025-06-13  4:05   ` John Stultz
  2025-06-25 16:15   ` [tip: timers/ptp] " tip-bot2 for Thomas Gleixner
  2025-05-19  8:33 ` [patch V2 12/26] timekeeping: Introduce auxiliary timekeepers Thomas Gleixner
                   ` (14 subsequent siblings)
  25 siblings, 2 replies; 57+ messages in thread
From: Thomas Gleixner @ 2025-05-19  8:33 UTC (permalink / raw)
  To: LKML
  Cc: netdev, Richard Cochran, Christopher Hall, John Stultz,
	Frederic Weisbecker, Anna-Maria Behnsen, Miroslav Lichvar,
	Werner Abt, David Woodhouse, Stephen Boyd, Thomas Weißschuh,
	Kurt Kanzenbach, Nam Cao, Antoine Tenart

From: Thomas Gleixner <tglx@linutronix.de>

In preparation for supporting independent auxiliary timekeepers, add a
clock valid field and set it to true for the system timekeeper.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

---
 include/linux/timekeeper_internal.h |    2 ++
 kernel/time/timekeeping.c           |    5 +++--
 2 files changed, 5 insertions(+), 2 deletions(-)
---
--- a/include/linux/timekeeper_internal.h
+++ b/include/linux/timekeeper_internal.h
@@ -73,6 +73,7 @@ struct tk_read_base {
  * @raw_sec:			CLOCK_MONOTONIC_RAW  time in seconds
  * @clock_was_set_seq:		The sequence number of clock was set events
  * @cs_was_changed_seq:		The sequence number of clocksource change events
+ * @clock_valid:		Indicator for valid clock
  * @monotonic_to_boot:		CLOCK_MONOTONIC to CLOCK_BOOTTIME offset
  * @cycle_interval:		Number of clock cycles in one NTP interval
  * @xtime_interval:		Number of clock shifted nano seconds in one NTP
@@ -149,6 +150,7 @@ struct timekeeper {
 	/* Cachline 3 and 4 (timekeeping internal variables): */
 	unsigned int		clock_was_set_seq;
 	u8			cs_was_changed_seq;
+	u8			clock_valid;
 
 	struct timespec64	monotonic_to_boot;
 
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -1665,11 +1665,12 @@ read_persistent_wall_and_boot_offset(str
 	*boot_offset = ns_to_timespec64(local_clock());
 }
 
-static __init void tkd_basic_setup(struct tk_data *tkd, enum timekeeper_ids tk_id)
+static __init void tkd_basic_setup(struct tk_data *tkd, enum timekeeper_ids tk_id, bool valid)
 {
 	raw_spin_lock_init(&tkd->lock);
 	seqcount_raw_spinlock_init(&tkd->seq, &tkd->lock);
 	tkd->timekeeper.id = tkd->shadow_timekeeper.id = tk_id;
+	tkd->timekeeper.clock_valid = tkd->shadow_timekeeper.clock_valid = valid;
 }
 
 /*
@@ -1699,7 +1700,7 @@ void __init timekeeping_init(void)
 	struct timekeeper *tks = &tk_core.shadow_timekeeper;
 	struct clocksource *clock;
 
-	tkd_basic_setup(&tk_core, TIMEKEEPER_CORE);
+	tkd_basic_setup(&tk_core, TIMEKEEPER_CORE, true);
 
 	read_persistent_wall_and_boot_offset(&wall_time, &boot_offset);
 	if (timespec64_valid_settod(&wall_time) &&


^ permalink raw reply	[flat|nested] 57+ messages in thread

* [patch V2 12/26] timekeeping: Introduce auxiliary timekeepers
  2025-05-19  8:33 [patch V2 00/26] timekeeping: Provide support for auxiliary timekeepers Thomas Gleixner
                   ` (10 preceding siblings ...)
  2025-05-19  8:33 ` [patch V2 11/26] timekeeping: Add clock_valid flag to timekeeper Thomas Gleixner
@ 2025-05-19  8:33 ` Thomas Gleixner
  2025-06-14  2:41   ` John Stultz
  2025-06-25 16:15   ` [tip: timers/ptp] " tip-bot2 for Anna-Maria Behnsen
  2025-05-19  8:33 ` [patch V2 13/26] timekeeping: Provide ktime_get_ntp_seconds() Thomas Gleixner
                   ` (13 subsequent siblings)
  25 siblings, 2 replies; 57+ messages in thread
From: Thomas Gleixner @ 2025-05-19  8:33 UTC (permalink / raw)
  To: LKML
  Cc: netdev, Richard Cochran, Christopher Hall, John Stultz,
	Frederic Weisbecker, Anna-Maria Behnsen, Miroslav Lichvar,
	Werner Abt, David Woodhouse, Stephen Boyd, Thomas Weißschuh,
	Kurt Kanzenbach, Nam Cao, Antoine Tenart

From: Anna-Maria Behnsen <anna-maria@linutronix.de>

Provide timekeepers for auxiliary clocks and initialize them during
boot.

Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

---
 kernel/time/timekeeping.c |   22 ++++++++++++++++++++--
 1 file changed, 20 insertions(+), 2 deletions(-)
---
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -53,7 +53,11 @@ struct tk_data {
 	raw_spinlock_t		lock;
 } ____cacheline_aligned;
 
-static struct tk_data tk_core;
+static struct tk_data timekeeper_data[TIMEKEEPERS_MAX];
+
+/* The core timekeeper */
+#define tk_core		(timekeeper_data[TIMEKEEPER_CORE])
+
 
 /* flag for if timekeeping is suspended */
 int __read_mostly timekeeping_suspended;
@@ -113,6 +117,12 @@ static struct tk_fast tk_fast_raw  ____c
 	.base[1] = FAST_TK_INIT,
 };
 
+#ifdef CONFIG_POSIX_AUX_CLOCKS
+static __init void tk_aux_setup(void);
+#else
+static inline void tk_aux_setup(void) { }
+#endif
+
 unsigned long timekeeper_lock_irqsave(void)
 {
 	unsigned long flags;
@@ -1589,7 +1599,6 @@ void ktime_get_raw_ts64(struct timespec6
 }
 EXPORT_SYMBOL(ktime_get_raw_ts64);
 
-
 /**
  * timekeeping_valid_for_hres - Check if timekeeping is suitable for hres
  */
@@ -1701,6 +1710,7 @@ void __init timekeeping_init(void)
 	struct clocksource *clock;
 
 	tkd_basic_setup(&tk_core, TIMEKEEPER_CORE, true);
+	tk_aux_setup();
 
 	read_persistent_wall_and_boot_offset(&wall_time, &boot_offset);
 	if (timespec64_valid_settod(&wall_time) &&
@@ -2630,3 +2640,11 @@ void hardpps(const struct timespec64 *ph
 }
 EXPORT_SYMBOL(hardpps);
 #endif /* CONFIG_NTP_PPS */
+
+#ifdef CONFIG_POSIX_AUX_CLOCKS
+static __init void tk_aux_setup(void)
+{
+	for (int i = TIMEKEEPER_AUX; i <= TIMEKEEPER_AUX_LAST; i++)
+		tkd_basic_setup(&timekeeper_data[i], i, false);
+}
+#endif /* CONFIG_POSIX_AUX_CLOCKS */


^ permalink raw reply	[flat|nested] 57+ messages in thread

* [patch V2 13/26] timekeeping: Provide ktime_get_ntp_seconds()
  2025-05-19  8:33 [patch V2 00/26] timekeeping: Provide support for auxiliary timekeepers Thomas Gleixner
                   ` (11 preceding siblings ...)
  2025-05-19  8:33 ` [patch V2 12/26] timekeeping: Introduce auxiliary timekeepers Thomas Gleixner
@ 2025-05-19  8:33 ` Thomas Gleixner
  2025-06-25 16:15   ` [tip: timers/ptp] " tip-bot2 for Thomas Gleixner
  2025-05-19  8:33 ` [patch V2 14/26] ntp: Use ktime_get_ntp_seconds() Thomas Gleixner
                   ` (12 subsequent siblings)
  25 siblings, 1 reply; 57+ messages in thread
From: Thomas Gleixner @ 2025-05-19  8:33 UTC (permalink / raw)
  To: LKML
  Cc: netdev, Richard Cochran, Christopher Hall, John Stultz,
	Frederic Weisbecker, Anna-Maria Behnsen, Miroslav Lichvar,
	Werner Abt, David Woodhouse, Stephen Boyd, Thomas Weißschuh,
	Kurt Kanzenbach, Nam Cao, Antoine Tenart

ntp_adjtimex() requires access to the actual time keeper per timekeeper
ID. Provide an interface.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

---
 kernel/time/timekeeping.c          |    9 +++++++++
 kernel/time/timekeeping_internal.h |    3 +++
 2 files changed, 12 insertions(+)
---
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -2627,6 +2627,15 @@ int do_adjtimex(struct __kernel_timex *t
 	return ret;
 }
 
+/*
+ * Invoked from NTP with the time keeper lock held, so lockless access is
+ * fine.
+ */
+long ktime_get_ntp_seconds(unsigned int id)
+{
+	return timekeeper_data[id].timekeeper.xtime_sec;
+}
+
 #ifdef CONFIG_NTP_PPS
 /**
  * hardpps() - Accessor function to NTP __hardpps function
--- a/kernel/time/timekeeping_internal.h
+++ b/kernel/time/timekeeping_internal.h
@@ -45,4 +45,7 @@ static inline u64 clocksource_delta(u64
 unsigned long timekeeper_lock_irqsave(void);
 void timekeeper_unlock_irqrestore(unsigned long flags);
 
+/* NTP specific interface to access the current seconds value */
+long ktime_get_ntp_seconds(unsigned int id);
+
 #endif /* _TIMEKEEPING_INTERNAL_H */


^ permalink raw reply	[flat|nested] 57+ messages in thread

* [patch V2 14/26] ntp: Use ktime_get_ntp_seconds()
  2025-05-19  8:33 [patch V2 00/26] timekeeping: Provide support for auxiliary timekeepers Thomas Gleixner
                   ` (12 preceding siblings ...)
  2025-05-19  8:33 ` [patch V2 13/26] timekeeping: Provide ktime_get_ntp_seconds() Thomas Gleixner
@ 2025-05-19  8:33 ` Thomas Gleixner
  2025-06-25 16:15   ` [tip: timers/ptp] " tip-bot2 for Thomas Gleixner
  2025-05-19  8:33 ` [patch V2 15/26] timekeeping: Add AUX offset to struct timekeeper Thomas Gleixner
                   ` (11 subsequent siblings)
  25 siblings, 1 reply; 57+ messages in thread
From: Thomas Gleixner @ 2025-05-19  8:33 UTC (permalink / raw)
  To: LKML
  Cc: netdev, Richard Cochran, Christopher Hall, John Stultz,
	Frederic Weisbecker, Anna-Maria Behnsen, Miroslav Lichvar,
	Werner Abt, David Woodhouse, Stephen Boyd, Thomas Weißschuh,
	Kurt Kanzenbach, Nam Cao, Antoine Tenart

Use ktime_get_ntp_seconds() to prepare for auxiliary clocks so that
the readout becomes per timekeeper.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

---
 kernel/time/ntp.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
---
--- a/kernel/time/ntp.c
+++ b/kernel/time/ntp.c
@@ -303,7 +303,7 @@ static void ntp_update_offset(struct ntp
 	 * Select how the frequency is to be controlled
 	 * and in which mode (PLL or FLL).
 	 */
-	real_secs = __ktime_get_real_seconds();
+	real_secs = ktime_get_ntp_seconds(ntpdata - tk_ntp_data);
 	secs = (long)(real_secs - ntpdata->time_reftime);
 	if (unlikely(ntpdata->time_status & STA_FREQHOLD))
 		secs = 0;
@@ -710,7 +710,7 @@ static inline void process_adj_status(st
 	 * reference time to current time.
 	 */
 	if (!(ntpdata->time_status & STA_PLL) && (txc->status & STA_PLL))
-		ntpdata->time_reftime = __ktime_get_real_seconds();
+		ntpdata->time_reftime = ktime_get_ntp_seconds(ntpdata - tk_ntp_data);
 
 	/* only set allowed bits */
 	ntpdata->time_status &= STA_RONLY;


^ permalink raw reply	[flat|nested] 57+ messages in thread

* [patch V2 15/26] timekeeping: Add AUX offset to struct timekeeper
  2025-05-19  8:33 [patch V2 00/26] timekeeping: Provide support for auxiliary timekeepers Thomas Gleixner
                   ` (13 preceding siblings ...)
  2025-05-19  8:33 ` [patch V2 14/26] ntp: Use ktime_get_ntp_seconds() Thomas Gleixner
@ 2025-05-19  8:33 ` Thomas Gleixner
  2025-06-14  2:44   ` John Stultz
  2025-06-25 16:15   ` [tip: timers/ptp] " tip-bot2 for Thomas Gleixner
  2025-05-19  8:33 ` [patch V2 16/26] timekeeping: Update auxiliary timekeepers on clocksource change Thomas Gleixner
                   ` (10 subsequent siblings)
  25 siblings, 2 replies; 57+ messages in thread
From: Thomas Gleixner @ 2025-05-19  8:33 UTC (permalink / raw)
  To: LKML
  Cc: netdev, Richard Cochran, Christopher Hall, John Stultz,
	Frederic Weisbecker, Anna-Maria Behnsen, Miroslav Lichvar,
	Werner Abt, David Woodhouse, Stephen Boyd, Thomas Weißschuh,
	Kurt Kanzenbach, Nam Cao, Antoine Tenart

This offset will be used in the time getters of auxiliary clocks. It is
added to the "monotonic" clock readout.

As auxiliary clocks do not utilize the offset fields of the core time
keeper, this is just an alias for offs_tai, so that the cache line layout
stays the same.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 include/linux/timekeeper_internal.h |    6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)
---
--- a/include/linux/timekeeper_internal.h
+++ b/include/linux/timekeeper_internal.h
@@ -67,6 +67,7 @@ struct tk_read_base {
  * @offs_real:			Offset clock monotonic -> clock realtime
  * @offs_boot:			Offset clock monotonic -> clock boottime
  * @offs_tai:			Offset clock monotonic -> clock tai
+ * @offs_aux:			Offset clock monotonic -> clock AUX
  * @coarse_nsec:		The nanoseconds part for coarse time getters
  * @id:				The timekeeper ID
  * @tkr_raw:			The readout base structure for CLOCK_MONOTONIC_RAW
@@ -139,7 +140,10 @@ struct timekeeper {
 	struct timespec64	wall_to_monotonic;
 	ktime_t			offs_real;
 	ktime_t			offs_boot;
-	ktime_t			offs_tai;
+	union {
+		ktime_t		offs_tai;
+		ktime_t		offs_aux;
+	};
 	u32			coarse_nsec;
 	enum timekeeper_ids	id;
 


^ permalink raw reply	[flat|nested] 57+ messages in thread

* [patch V2 16/26] timekeeping: Update auxiliary timekeepers on clocksource change
  2025-05-19  8:33 [patch V2 00/26] timekeeping: Provide support for auxiliary timekeepers Thomas Gleixner
                   ` (14 preceding siblings ...)
  2025-05-19  8:33 ` [patch V2 15/26] timekeeping: Add AUX offset to struct timekeeper Thomas Gleixner
@ 2025-05-19  8:33 ` Thomas Gleixner
  2025-05-19  8:33 ` [patch V2 17/26] timekeeping: Provide time getters for auxiliary clocks Thomas Gleixner
                   ` (9 subsequent siblings)
  25 siblings, 0 replies; 57+ messages in thread
From: Thomas Gleixner @ 2025-05-19  8:33 UTC (permalink / raw)
  To: LKML
  Cc: netdev, Richard Cochran, Christopher Hall, John Stultz,
	Frederic Weisbecker, Anna-Maria Behnsen, Miroslav Lichvar,
	Werner Abt, David Woodhouse, Stephen Boyd, Thomas Weißschuh,
	Kurt Kanzenbach, Nam Cao, Antoine Tenart

Propagate a system clocksource change to the auxiliary timekeepers so that
they can pick up the new clocksource.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

---
 kernel/time/timekeeping.c |   28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)
---
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -119,8 +119,10 @@ static struct tk_fast tk_fast_raw  ____c
 
 #ifdef CONFIG_POSIX_AUX_CLOCKS
 static __init void tk_aux_setup(void);
+static void tk_aux_update_clocksource(void);
 #else
 static inline void tk_aux_setup(void) { }
+static inline void tk_aux_update_clocksource(void) { }
 #endif
 
 unsigned long timekeeper_lock_irqsave(void)
@@ -1548,6 +1550,8 @@ static int change_clocksource(void *data
 		timekeeping_update_from_shadow(&tk_core, TK_UPDATE_ALL);
 	}
 
+	tk_aux_update_clocksource();
+
 	if (old) {
 		if (old->disable)
 			old->disable(old);
@@ -2651,6 +2655,30 @@ EXPORT_SYMBOL(hardpps);
 #endif /* CONFIG_NTP_PPS */
 
 #ifdef CONFIG_POSIX_AUX_CLOCKS
+
+/* Bitmap for the activated auxiliary timekeepers */
+static unsigned long aux_timekeepers;
+
+/* Invoked from timekeeping after a clocksource change */
+static void tk_aux_update_clocksource(void)
+{
+	unsigned long active = READ_ONCE(aux_timekeepers);
+	unsigned int id;
+
+	for_each_set_bit(id, &active, BITS_PER_LONG) {
+		struct tk_data *tkd = &timekeeper_data[id + TIMEKEEPER_AUX];
+		struct timekeeper *tks = &tkd->shadow_timekeeper;
+
+		guard(raw_spinlock_irqsave)(&tkd->lock);
+		if (!tks->clock_valid)
+			continue;
+
+		timekeeping_forward_now(tks);
+		tk_setup_internals(tks, tk_core.timekeeper.tkr_mono.clock);
+		timekeeping_update_from_shadow(tkd, TK_UPDATE_ALL);
+	}
+}
+
 static __init void tk_aux_setup(void)
 {
 	for (int i = TIMEKEEPER_AUX; i <= TIMEKEEPER_AUX_LAST; i++)


^ permalink raw reply	[flat|nested] 57+ messages in thread

* [patch V2 17/26] timekeeping: Provide time getters for auxiliary clocks
  2025-05-19  8:33 [patch V2 00/26] timekeeping: Provide support for auxiliary timekeepers Thomas Gleixner
                   ` (15 preceding siblings ...)
  2025-05-19  8:33 ` [patch V2 16/26] timekeeping: Update auxiliary timekeepers on clocksource change Thomas Gleixner
@ 2025-05-19  8:33 ` Thomas Gleixner
  2025-06-14  2:51   ` John Stultz
  2025-05-19  8:33 ` [patch V2 18/26] timekeeping: Add minimal posix-timers support " Thomas Gleixner
                   ` (8 subsequent siblings)
  25 siblings, 1 reply; 57+ messages in thread
From: Thomas Gleixner @ 2025-05-19  8:33 UTC (permalink / raw)
  To: LKML
  Cc: netdev, Richard Cochran, Christopher Hall, John Stultz,
	Frederic Weisbecker, Anna-Maria Behnsen, Miroslav Lichvar,
	Werner Abt, David Woodhouse, Stephen Boyd, Thomas Weißschuh,
	Kurt Kanzenbach, Nam Cao, Antoine Tenart

Provide interfaces similar to the ktime_get*() family which provide access
to the auxiliary clocks.

These interfaces have a boolean return value, which indicates whether the
accessed clock is valid or not.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

---
 include/linux/timekeeping.h |   11 +++++++
 kernel/time/timekeeping.c   |   62 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 73 insertions(+)
---
--- a/include/linux/timekeeping.h
+++ b/include/linux/timekeeping.h
@@ -263,6 +263,17 @@ extern bool timekeeping_rtc_skipresume(v
 
 extern void timekeeping_inject_sleeptime64(const struct timespec64 *delta);
 
+/*
+ * Auxiliary clock interfaces
+ */
+#ifdef CONFIG_POSIX_AUX_CLOCKS
+extern bool ktime_get_aux(clockid_t id, ktime_t *kt);
+extern bool ktime_get_aux_ts64(clockid_t id, struct timespec64 *kt);
+#else
+static inline bool ktime_get_aux(clockid_t id, ktime_t *kt) { return false; }
+static inline bool ktime_get_aux_ts64(clockid_t id, struct timespec64 *kt) { return false; }
+#endif
+
 /**
  * struct system_time_snapshot - simultaneous raw/real time capture with
  *				 counter value
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -2659,6 +2659,23 @@ EXPORT_SYMBOL(hardpps);
 /* Bitmap for the activated auxiliary timekeepers */
 static unsigned long aux_timekeepers;
 
+static inline bool aux_valid_clockid(clockid_t id)
+{
+	return id >= CLOCK_AUX && id <= CLOCK_AUX_LAST;
+}
+
+static inline unsigned int clockid_to_tkid(unsigned int id)
+{
+	return TIMEKEEPER_AUX + id - CLOCK_AUX;
+}
+
+static inline struct tk_data *aux_get_tk_data(clockid_t id)
+{
+	if (!aux_valid_clockid(id))
+		return NULL;
+	return &timekeeper_data[clockid_to_tkid(id)];
+}
+
 /* Invoked from timekeeping after a clocksource change */
 static void tk_aux_update_clocksource(void)
 {
@@ -2679,6 +2696,51 @@ static void tk_aux_update_clocksource(vo
 	}
 }
 
+/**
+ * ktime_get_aux - Get TAI time for a AUX clock
+ * @id:	ID of the clock to read (CLOCK_AUX...)
+ * @kt:	Pointer to ktime_t to store the time stamp
+ *
+ * Returns: True if the timestamp is valid, false otherwise
+ */
+bool ktime_get_aux(clockid_t id, ktime_t *kt)
+{
+	struct tk_data *tkd = aux_get_tk_data(id);
+	struct timekeeper *tk;
+	unsigned int seq;
+	ktime_t base;
+	u64 nsecs;
+
+	WARN_ON(timekeeping_suspended);
+
+	if (!tkd)
+		return false;
+
+	tk = &tkd->timekeeper;
+	do {
+		seq = read_seqcount_begin(&tkd->seq);
+		if (!tk->clock_valid)
+			return false;
+
+		base = ktime_add(tk->tkr_mono.base, tk->offs_aux);
+		nsecs = timekeeping_get_ns(&tk->tkr_mono);
+	} while (read_seqcount_retry(&tkd->seq, seq));
+
+	*kt = ktime_add_ns(base, nsecs);
+	return true;
+}
+EXPORT_SYMBOL_GPL(ktime_get_aux);
+
+bool ktime_get_aux_ts64(clockid_t id, struct timespec64 *ts)
+{
+	ktime_t now;
+
+	if (!ktime_get_aux(id, &now))
+		return false;
+	*ts = ktime_to_timespec64(now);
+	return true;
+}
+
 static __init void tk_aux_setup(void)
 {
 	for (int i = TIMEKEEPER_AUX; i <= TIMEKEEPER_AUX_LAST; i++)


^ permalink raw reply	[flat|nested] 57+ messages in thread

* [patch V2 18/26] timekeeping: Add minimal posix-timers support for auxiliary clocks
  2025-05-19  8:33 [patch V2 00/26] timekeeping: Provide support for auxiliary timekeepers Thomas Gleixner
                   ` (16 preceding siblings ...)
  2025-05-19  8:33 ` [patch V2 17/26] timekeeping: Provide time getters for auxiliary clocks Thomas Gleixner
@ 2025-05-19  8:33 ` Thomas Gleixner
  2025-05-19  8:33 ` [patch V2 19/26] timekeeping: Provide time setter " Thomas Gleixner
                   ` (7 subsequent siblings)
  25 siblings, 0 replies; 57+ messages in thread
From: Thomas Gleixner @ 2025-05-19  8:33 UTC (permalink / raw)
  To: LKML
  Cc: netdev, Richard Cochran, Christopher Hall, John Stultz,
	Frederic Weisbecker, Anna-Maria Behnsen, Miroslav Lichvar,
	Werner Abt, David Woodhouse, Stephen Boyd, Thomas Weißschuh,
	Kurt Kanzenbach, Nam Cao, Antoine Tenart

Provide clock_getres(2) and clock_gettime(2) for auxiliary clocks.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

---
 kernel/time/posix-timers.c |    3 +++
 kernel/time/posix-timers.h |    1 +
 kernel/time/timekeeping.c  |   21 +++++++++++++++++++++
 3 files changed, 25 insertions(+)
---
--- a/kernel/time/posix-timers.c
+++ b/kernel/time/posix-timers.c
@@ -1526,6 +1526,9 @@ static const struct k_clock * const posi
 	[CLOCK_REALTIME_ALARM]		= &alarm_clock,
 	[CLOCK_BOOTTIME_ALARM]		= &alarm_clock,
 	[CLOCK_TAI]			= &clock_tai,
+#ifdef CONFIG_POSIX_AUX_CLOCKS
+	[CLOCK_AUX ... CLOCK_AUX_LAST]	= &clock_aux,
+#endif
 };
 
 static const struct k_clock *clockid_to_kclock(const clockid_t id)
--- a/kernel/time/posix-timers.h
+++ b/kernel/time/posix-timers.h
@@ -41,6 +41,7 @@ extern const struct k_clock clock_posix_
 extern const struct k_clock clock_process;
 extern const struct k_clock clock_thread;
 extern const struct k_clock alarm_clock;
+extern const struct k_clock clock_aux;
 
 void posix_timer_queue_signal(struct k_itimer *timr);
 
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -2655,6 +2655,7 @@ EXPORT_SYMBOL(hardpps);
 #endif /* CONFIG_NTP_PPS */
 
 #ifdef CONFIG_POSIX_AUX_CLOCKS
+#include "posix-timers.h"
 
 /* Bitmap for the activated auxiliary timekeepers */
 static unsigned long aux_timekeepers;
@@ -2741,6 +2742,26 @@ bool ktime_get_aux_ts64(clockid_t id, st
 	return true;
 }
 
+static int aux_get_res(clockid_t id, struct timespec64 *tp)
+{
+	if (!aux_valid_clockid(id))
+		return -ENODEV;
+
+	tp->tv_sec = 0;
+	tp->tv_nsec = 1;
+	return 0;
+}
+
+static int aux_get_timespec(clockid_t id, struct timespec64 *tp)
+{
+	return ktime_get_aux_ts64(id, tp) ? 0 : -ENODEV;
+}
+
+const struct k_clock clock_aux = {
+	.clock_getres		= aux_get_res,
+	.clock_get_timespec	= aux_get_timespec,
+};
+
 static __init void tk_aux_setup(void)
 {
 	for (int i = TIMEKEEPER_AUX; i <= TIMEKEEPER_AUX_LAST; i++)


^ permalink raw reply	[flat|nested] 57+ messages in thread

* [patch V2 19/26] timekeeping: Provide time setter for auxiliary clocks
  2025-05-19  8:33 [patch V2 00/26] timekeeping: Provide support for auxiliary timekeepers Thomas Gleixner
                   ` (17 preceding siblings ...)
  2025-05-19  8:33 ` [patch V2 18/26] timekeeping: Add minimal posix-timers support " Thomas Gleixner
@ 2025-05-19  8:33 ` Thomas Gleixner
  2025-05-19  8:33 ` [patch V2 20/26] timekeeping: Make timekeeping_inject_offset() reusable Thomas Gleixner
                   ` (6 subsequent siblings)
  25 siblings, 0 replies; 57+ messages in thread
From: Thomas Gleixner @ 2025-05-19  8:33 UTC (permalink / raw)
  To: LKML
  Cc: netdev, Richard Cochran, Christopher Hall, John Stultz,
	Frederic Weisbecker, Anna-Maria Behnsen, Miroslav Lichvar,
	Werner Abt, David Woodhouse, Stephen Boyd, Thomas Weißschuh,
	Kurt Kanzenbach, Nam Cao, Antoine Tenart

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>

---
 kernel/time/timekeeping.c |   39 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)
---
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -2757,9 +2757,48 @@ static int aux_get_timespec(clockid_t id
 	return ktime_get_aux_ts64(id, tp) ? 0 : -ENODEV;
 }
 
+static int aux_clock_set(const clockid_t id, const struct timespec64 *tnew)
+{
+	struct tk_data *tkd = aux_get_tk_data(id);
+	struct timekeeper *tks;
+	ktime_t tnow, nsecs;
+
+	if (!timespec64_valid_settod(tnew))
+		return -EINVAL;
+	if (!tkd)
+		return -ENODEV;
+
+	tks = &tkd->shadow_timekeeper;
+
+	guard(raw_spinlock_irq)(&tkd->lock);
+	if (!tks->clock_valid)
+		return -ENODEV;
+
+	/* Forward the timekeeper base time */
+	timekeeping_forward_now(tks);
+	/*
+	 * Get the updated base time. tkr_mono.base has not been
+	 * updated yet, so do that first. That makes the update
+	 * in timekeeping_update_from_shadow() redundant, but
+	 * that's harmless. After that @tnow can be calculated
+	 * by using tkr_mono::cycle_last, which has been set
+	 * by timekeeping_forward_now().
+	 */
+	tk_update_ktime_data(tks);
+	nsecs = timekeeping_cycles_to_ns(&tks->tkr_mono, tks->tkr_mono.cycle_last);
+	tnow = ktime_add(tks->tkr_mono.base, nsecs);
+
+	/* Calculate the new AUX offset */
+	tks->offs_aux = ktime_sub(timespec64_to_ktime(*tnew), tnow);
+
+	timekeeping_update_from_shadow(tkd, TK_UPDATE_ALL);
+	return 0;
+}
+
 const struct k_clock clock_aux = {
 	.clock_getres		= aux_get_res,
 	.clock_get_timespec	= aux_get_timespec,
+	.clock_set		= aux_clock_set,
 };
 
 static __init void tk_aux_setup(void)


^ permalink raw reply	[flat|nested] 57+ messages in thread

* [patch V2 20/26] timekeeping: Make timekeeping_inject_offset() reusable
  2025-05-19  8:33 [patch V2 00/26] timekeeping: Provide support for auxiliary timekeepers Thomas Gleixner
                   ` (18 preceding siblings ...)
  2025-05-19  8:33 ` [patch V2 19/26] timekeeping: Provide time setter " Thomas Gleixner
@ 2025-05-19  8:33 ` Thomas Gleixner
  2025-05-19  8:33 ` [patch V2 21/26] timekeeping: Add auxiliary clock support to __timekeeping_inject_offset() Thomas Gleixner
                   ` (5 subsequent siblings)
  25 siblings, 0 replies; 57+ messages in thread
From: Thomas Gleixner @ 2025-05-19  8:33 UTC (permalink / raw)
  To: LKML
  Cc: netdev, Richard Cochran, Christopher Hall, John Stultz,
	Frederic Weisbecker, Anna-Maria Behnsen, Miroslav Lichvar,
	Werner Abt, David Woodhouse, Stephen Boyd, Thomas Weißschuh,
	Kurt Kanzenbach, Nam Cao, Antoine Tenart

Split out the inner workings for auxiliary clock support and feed the core time
keeper into it.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

---
 kernel/time/timekeeping.c |   26 +++++++++++++++-----------
 1 file changed, 15 insertions(+), 11 deletions(-)
---
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -1433,32 +1433,32 @@ EXPORT_SYMBOL(do_settimeofday64);
 
 /**
  * __timekeeping_inject_offset - Adds or subtracts from the current time.
+ * @tkd:	Pointer to the timekeeper to modify
  * @ts:		Pointer to the timespec variable containing the offset
  *
  * Adds or subtracts an offset value from the current time.
  */
-static int __timekeeping_inject_offset(const struct timespec64 *ts)
+static int __timekeeping_inject_offset(struct tk_data *tkd, const struct timespec64 *ts)
 {
-	struct timekeeper *tks = &tk_core.shadow_timekeeper;
+	struct timekeeper *tks = &tkd->shadow_timekeeper;
 	struct timespec64 tmp;
 
 	if (ts->tv_nsec < 0 || ts->tv_nsec >= NSEC_PER_SEC)
 		return -EINVAL;
 
-
 	timekeeping_forward_now(tks);
 
 	/* Make sure the proposed value is valid */
 	tmp = timespec64_add(tk_xtime(tks), *ts);
 	if (timespec64_compare(&tks->wall_to_monotonic, ts) > 0 ||
 	    !timespec64_valid_settod(&tmp)) {
-		timekeeping_restore_shadow(&tk_core);
+		timekeeping_restore_shadow(tkd);
 		return -EINVAL;
 	}
 
 	tk_xtime_add(tks, ts);
 	tk_set_wall_to_mono(tks, timespec64_sub(tks->wall_to_monotonic, *ts));
-	timekeeping_update_from_shadow(&tk_core, TK_UPDATE_ALL);
+	timekeeping_update_from_shadow(tkd, TK_UPDATE_ALL);
 	return 0;
 }
 
@@ -1467,7 +1467,7 @@ static int timekeeping_inject_offset(con
 	int ret;
 
 	scoped_guard (raw_spinlock_irqsave, &tk_core.lock)
-		ret = __timekeeping_inject_offset(ts);
+		ret = __timekeeping_inject_offset(&tk_core, ts);
 
 	/* Signal hrtimers about time change */
 	if (!ret)
@@ -2568,6 +2568,7 @@ EXPORT_SYMBOL_GPL(random_get_entropy_fal
  */
 int do_adjtimex(struct __kernel_timex *txc)
 {
+	struct tk_data *tkd = &tk_core;
 	struct timespec64 delta, ts;
 	struct audit_ntp_data ad;
 	bool offset_set = false;
@@ -2585,16 +2586,19 @@ int do_adjtimex(struct __kernel_timex *t
 	ktime_get_real_ts64(&ts);
 	add_device_randomness(&ts, sizeof(ts));
 
-	scoped_guard (raw_spinlock_irqsave, &tk_core.lock) {
-		struct timekeeper *tks = &tk_core.shadow_timekeeper;
+	scoped_guard (raw_spinlock_irqsave, &tkd->lock) {
+		struct timekeeper *tks = &tkd->shadow_timekeeper;
 		s32 orig_tai, tai;
 
+		if (!tks->clock_valid)
+			return -ENODEV;
+
 		if (txc->modes & ADJ_SETOFFSET) {
 			delta.tv_sec  = txc->time.tv_sec;
 			delta.tv_nsec = txc->time.tv_usec;
 			if (!(txc->modes & ADJ_NANO))
 				delta.tv_nsec *= 1000;
-			ret = __timekeeping_inject_offset(&delta);
+			ret = __timekeeping_inject_offset(tkd, &delta);
 			if (ret)
 				return ret;
 
@@ -2607,7 +2611,7 @@ int do_adjtimex(struct __kernel_timex *t
 
 		if (tai != orig_tai) {
 			__timekeeping_set_tai_offset(tks, tai);
-			timekeeping_update_from_shadow(&tk_core, TK_CLOCK_WAS_SET);
+			timekeeping_update_from_shadow(tkd, TK_CLOCK_WAS_SET);
 			clock_set = true;
 		} else {
 			tk_update_leap_state_all(&tk_core);
@@ -2615,7 +2619,7 @@ int do_adjtimex(struct __kernel_timex *t
 
 		/* Update the multiplier immediately if frequency was set directly */
 		if (txc->modes & (ADJ_FREQUENCY | ADJ_TICK))
-			clock_set |= __timekeeping_advance(&tk_core, TK_ADV_FREQ);
+			clock_set |= __timekeeping_advance(tkd, TK_ADV_FREQ);
 	}
 
 	if (txc->modes & ADJ_SETOFFSET)


^ permalink raw reply	[flat|nested] 57+ messages in thread

* [patch V2 21/26] timekeeping: Add auxiliary clock support to __timekeeping_inject_offset()
  2025-05-19  8:33 [patch V2 00/26] timekeeping: Provide support for auxiliary timekeepers Thomas Gleixner
                   ` (19 preceding siblings ...)
  2025-05-19  8:33 ` [patch V2 20/26] timekeeping: Make timekeeping_inject_offset() reusable Thomas Gleixner
@ 2025-05-19  8:33 ` Thomas Gleixner
  2025-05-19  8:33 ` [patch V2 22/26] timekeeping: Make do_adjtimex() reusable Thomas Gleixner
                   ` (4 subsequent siblings)
  25 siblings, 0 replies; 57+ messages in thread
From: Thomas Gleixner @ 2025-05-19  8:33 UTC (permalink / raw)
  To: LKML
  Cc: netdev, Richard Cochran, Christopher Hall, John Stultz,
	Frederic Weisbecker, Anna-Maria Behnsen, Miroslav Lichvar,
	Werner Abt, David Woodhouse, Stephen Boyd, Thomas Weißschuh,
	Kurt Kanzenbach, Nam Cao, Antoine Tenart

Redirect the relative offset adjustment to the auxiliary clock offset
instead of modifying CLOCK_REALTIME, which has no meaning in context of
these clocks.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

---
 kernel/time/timekeeping.c |   34 ++++++++++++++++++++++++++--------
 1 file changed, 26 insertions(+), 8 deletions(-)
---
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -1448,16 +1448,34 @@ static int __timekeeping_inject_offset(s
 
 	timekeeping_forward_now(tks);
 
-	/* Make sure the proposed value is valid */
-	tmp = timespec64_add(tk_xtime(tks), *ts);
-	if (timespec64_compare(&tks->wall_to_monotonic, ts) > 0 ||
-	    !timespec64_valid_settod(&tmp)) {
-		timekeeping_restore_shadow(tkd);
-		return -EINVAL;
+	if (!IS_ENABLED(CONFIG_POSIX_AUX_CLOCKS) || tks->id == TIMEKEEPER_CORE) {
+		/* Make sure the proposed value is valid */
+		tmp = timespec64_add(tk_xtime(tks), *ts);
+		if (timespec64_compare(&tks->wall_to_monotonic, ts) > 0 ||
+		    !timespec64_valid_settod(&tmp)) {
+			timekeeping_restore_shadow(tkd);
+			return -EINVAL;
+		}
+
+		tk_xtime_add(tks, ts);
+		tk_set_wall_to_mono(tks, timespec64_sub(tks->wall_to_monotonic, *ts));
+	} else {
+		struct tk_read_base *tkr_mono = &tks->tkr_mono;
+		ktime_t now, offs;
+
+		/* Get the current time */
+		now = ktime_add_ns(tkr_mono->base, timekeeping_get_ns(tkr_mono));
+		/* Add the relative offset change */
+		offs = ktime_add(tks->offs_aux, timespec64_to_ktime(*ts));
+
+		/* Prevent that the resulting time becomes negative */
+		if (ktime_add(now, offs) < 0) {
+			timekeeping_restore_shadow(tkd);
+			return -EINVAL;
+		}
+		tks->offs_aux = offs;
 	}
 
-	tk_xtime_add(tks, ts);
-	tk_set_wall_to_mono(tks, timespec64_sub(tks->wall_to_monotonic, *ts));
 	timekeeping_update_from_shadow(tkd, TK_UPDATE_ALL);
 	return 0;
 }


^ permalink raw reply	[flat|nested] 57+ messages in thread

* [patch V2 22/26] timekeeping: Make do_adjtimex() reusable
  2025-05-19  8:33 [patch V2 00/26] timekeeping: Provide support for auxiliary timekeepers Thomas Gleixner
                   ` (20 preceding siblings ...)
  2025-05-19  8:33 ` [patch V2 21/26] timekeeping: Add auxiliary clock support to __timekeeping_inject_offset() Thomas Gleixner
@ 2025-05-19  8:33 ` Thomas Gleixner
  2025-05-19  8:33 ` [patch V2 23/26] timekeeping: Prepare do_adtimex() for auxiliary clocks Thomas Gleixner
                   ` (3 subsequent siblings)
  25 siblings, 0 replies; 57+ messages in thread
From: Thomas Gleixner @ 2025-05-19  8:33 UTC (permalink / raw)
  To: LKML
  Cc: netdev, Richard Cochran, Christopher Hall, John Stultz,
	Frederic Weisbecker, Anna-Maria Behnsen, Miroslav Lichvar,
	Werner Abt, David Woodhouse, Stephen Boyd, Thomas Weißschuh,
	Kurt Kanzenbach, Nam Cao, Antoine Tenart

Split out the actual functionality of adjtimex() and make do_adjtimex() a
wrapper which feeds the core timekeeper into it and handles the result
including audit at the call site.

This allows to reuse the actual functionality for auxiliary clocks.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 kernel/time/timekeeping.c |  110 +++++++++++++++++++++++++---------------------
 1 file changed, 60 insertions(+), 50 deletions(-)
---
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -2580,17 +2580,18 @@ unsigned long random_get_entropy_fallbac
 }
 EXPORT_SYMBOL_GPL(random_get_entropy_fallback);
 
-/**
- * do_adjtimex() - Accessor function to NTP __do_adjtimex function
- * @txc:	Pointer to kernel_timex structure containing NTP parameters
- */
-int do_adjtimex(struct __kernel_timex *txc)
+struct adjtimex_result {
+	struct audit_ntp_data	ad;
+	struct timespec64	delta;
+	bool			clock_set;
+};
+
+static int __do_adjtimex(struct tk_data *tkd, struct __kernel_timex *txc,
+			 struct adjtimex_result *result)
 {
-	struct tk_data *tkd = &tk_core;
-	struct timespec64 delta, ts;
-	struct audit_ntp_data ad;
-	bool offset_set = false;
-	bool clock_set = false;
+	struct timekeeper *tks = &tkd->shadow_timekeeper;
+	struct timespec64 ts;
+	s32 orig_tai, tai;
 	int ret;
 
 	/* Validate the data before disabling interrupts */
@@ -2599,56 +2600,65 @@ int do_adjtimex(struct __kernel_timex *t
 		return ret;
 	add_device_randomness(txc, sizeof(*txc));
 
-	audit_ntp_init(&ad);
-
 	ktime_get_real_ts64(&ts);
 	add_device_randomness(&ts, sizeof(ts));
 
-	scoped_guard (raw_spinlock_irqsave, &tkd->lock) {
-		struct timekeeper *tks = &tkd->shadow_timekeeper;
-		s32 orig_tai, tai;
-
-		if (!tks->clock_valid)
-			return -ENODEV;
-
-		if (txc->modes & ADJ_SETOFFSET) {
-			delta.tv_sec  = txc->time.tv_sec;
-			delta.tv_nsec = txc->time.tv_usec;
-			if (!(txc->modes & ADJ_NANO))
-				delta.tv_nsec *= 1000;
-			ret = __timekeeping_inject_offset(tkd, &delta);
-			if (ret)
-				return ret;
-
-			offset_set = delta.tv_sec != 0;
-			clock_set = true;
-		}
-
-		orig_tai = tai = tks->tai_offset;
-		ret = ntp_adjtimex(tks->id, txc, &ts, &tai, &ad);
-
-		if (tai != orig_tai) {
-			__timekeeping_set_tai_offset(tks, tai);
-			timekeeping_update_from_shadow(tkd, TK_CLOCK_WAS_SET);
-			clock_set = true;
-		} else {
-			tk_update_leap_state_all(&tk_core);
-		}
-
-		/* Update the multiplier immediately if frequency was set directly */
-		if (txc->modes & (ADJ_FREQUENCY | ADJ_TICK))
-			clock_set |= __timekeeping_advance(tkd, TK_ADV_FREQ);
+	guard(raw_spinlock_irqsave)(&tkd->lock);
+
+	if (!tks->clock_valid)
+		return -ENODEV;
+
+	if (txc->modes & ADJ_SETOFFSET) {
+		result->delta.tv_sec  = txc->time.tv_sec;
+		result->delta.tv_nsec = txc->time.tv_usec;
+		if (!(txc->modes & ADJ_NANO))
+			result->delta.tv_nsec *= 1000;
+		ret = __timekeeping_inject_offset(tkd, &result->delta);
+		if (ret)
+			return ret;
+		result->clock_set = true;
+	}
+
+	orig_tai = tai = tks->tai_offset;
+	ret = ntp_adjtimex(tks->id, txc, &ts, &tai, &result->ad);
+
+	if (tai != orig_tai) {
+		__timekeeping_set_tai_offset(tks, tai);
+		timekeeping_update_from_shadow(tkd, TK_CLOCK_WAS_SET);
+		result->clock_set = true;
+	} else {
+		tk_update_leap_state_all(&tk_core);
 	}
 
+	/* Update the multiplier immediately if frequency was set directly */
+	if (txc->modes & (ADJ_FREQUENCY | ADJ_TICK))
+		result->clock_set |= __timekeeping_advance(tkd, TK_ADV_FREQ);
+
+	return ret;
+}
+
+/**
+ * do_adjtimex() - Accessor function to NTP __do_adjtimex function
+ * @txc:	Pointer to kernel_timex structure containing NTP parameters
+ */
+int do_adjtimex(struct __kernel_timex *txc)
+{
+	struct adjtimex_result result = { };
+	int ret;
+
+	ret = __do_adjtimex(&tk_core, txc, &result);
+	if (ret < 0)
+		return ret;
+
 	if (txc->modes & ADJ_SETOFFSET)
-		audit_tk_injoffset(delta);
+		audit_tk_injoffset(result.delta);
 
-	audit_ntp_log(&ad);
+	audit_ntp_log(&result.ad);
 
-	if (clock_set)
+	if (result.clock_set)
 		clock_was_set(CLOCK_SET_WALL);
 
-	ntp_notify_cmos_timer(offset_set);
+	ntp_notify_cmos_timer(result.delta.tv_sec != 0);
 
 	return ret;
 }


^ permalink raw reply	[flat|nested] 57+ messages in thread

* [patch V2 23/26] timekeeping: Prepare do_adtimex() for auxiliary clocks
  2025-05-19  8:33 [patch V2 00/26] timekeeping: Provide support for auxiliary timekeepers Thomas Gleixner
                   ` (21 preceding siblings ...)
  2025-05-19  8:33 ` [patch V2 22/26] timekeeping: Make do_adjtimex() reusable Thomas Gleixner
@ 2025-05-19  8:33 ` Thomas Gleixner
  2025-05-19  8:33 ` [patch V2 24/26] timekeeping: Provide adjtimex() " Thomas Gleixner
                   ` (2 subsequent siblings)
  25 siblings, 0 replies; 57+ messages in thread
From: Thomas Gleixner @ 2025-05-19  8:33 UTC (permalink / raw)
  To: LKML
  Cc: netdev, Richard Cochran, Christopher Hall, John Stultz,
	Frederic Weisbecker, Anna-Maria Behnsen, Miroslav Lichvar,
	Werner Abt, David Woodhouse, Stephen Boyd, Thomas Weißschuh,
	Kurt Kanzenbach, Nam Cao, Antoine Tenart

Exclude ADJ_TAI, leap seconds and PPS functionality as they make no sense
in the context of auxiliary clocks and provide a time stamp based on the
actual clock.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 kernel/time/timekeeping.c |   39 ++++++++++++++++++++++++++++++++++++---
 1 file changed, 36 insertions(+), 3 deletions(-)
---
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -58,6 +58,17 @@ static struct tk_data timekeeper_data[TI
 /* The core timekeeper */
 #define tk_core		(timekeeper_data[TIMEKEEPER_CORE])
 
+#ifdef CONFIG_POSIX_AUX_CLOCKS
+static inline bool tk_get_aux_ts64(unsigned int tkid, struct timespec64 *ts)
+{
+	return ktime_get_aux_ts64(CLOCK_AUX + tkid - TIMEKEEPER_AUX, ts);
+}
+#else
+static inline bool tk_get_aux_ts64(unsigned int tkid, struct timespec64 *ts)
+{
+	return false;
+}
+#endif
 
 /* flag for if timekeeping is suspended */
 int __read_mostly timekeeping_suspended;
@@ -2503,7 +2514,7 @@ ktime_t ktime_get_update_offsets_now(uns
 /*
  * timekeeping_validate_timex - Ensures the timex is ok for use in do_adjtimex
  */
-static int timekeeping_validate_timex(const struct __kernel_timex *txc)
+static int timekeeping_validate_timex(const struct __kernel_timex *txc, bool aux_clock)
 {
 	if (txc->modes & ADJ_ADJTIME) {
 		/* singleshot must not be used with any other mode bits */
@@ -2562,6 +2573,21 @@ static int timekeeping_validate_timex(co
 			return -EINVAL;
 	}
 
+	if (!aux_clock)
+		return 0;
+
+	/* Auxiliary clocks are similar to TAI and do not have leap seconds */
+	if (txc->status & (STA_INS | STA_DEL))
+		return -EINVAL;
+
+	/* No TAI offset setting */
+	if (txc->modes & ADJ_TAI)
+		return -EINVAL;
+
+	/* No PPS support either */
+	if (txc->status & (STA_PPSFREQ | STA_PPSTIME))
+		return -EINVAL;
+
 	return 0;
 }
 
@@ -2592,15 +2618,22 @@ static int __do_adjtimex(struct tk_data
 	struct timekeeper *tks = &tkd->shadow_timekeeper;
 	struct timespec64 ts;
 	s32 orig_tai, tai;
+	bool aux_clock;
 	int ret;
 
+	aux_clock = IS_ENABLED(CONFIG_POSIX_AUX_CLOCKS) && tkd->timekeeper.id != TIMEKEEPER_CORE;
+
 	/* Validate the data before disabling interrupts */
-	ret = timekeeping_validate_timex(txc);
+	ret = timekeeping_validate_timex(txc, aux_clock);
 	if (ret)
 		return ret;
 	add_device_randomness(txc, sizeof(*txc));
 
-	ktime_get_real_ts64(&ts);
+	if (!aux_clock)
+		ktime_get_real_ts64(&ts);
+	else
+		tk_get_aux_ts64(tkd->timekeeper.id, &ts);
+
 	add_device_randomness(&ts, sizeof(ts));
 
 	guard(raw_spinlock_irqsave)(&tkd->lock);


^ permalink raw reply	[flat|nested] 57+ messages in thread

* [patch V2 24/26] timekeeping: Provide adjtimex() for auxiliary clocks
  2025-05-19  8:33 [patch V2 00/26] timekeeping: Provide support for auxiliary timekeepers Thomas Gleixner
                   ` (22 preceding siblings ...)
  2025-05-19  8:33 ` [patch V2 23/26] timekeeping: Prepare do_adtimex() for auxiliary clocks Thomas Gleixner
@ 2025-05-19  8:33 ` Thomas Gleixner
  2025-05-19  8:33 ` [patch V2 25/26] timekeeping: Provide update for auxiliary timekeepers Thomas Gleixner
  2025-05-19  8:33 ` [patch V2 26/26] timekeeping: Provide interface to control auxiliary clocks Thomas Gleixner
  25 siblings, 0 replies; 57+ messages in thread
From: Thomas Gleixner @ 2025-05-19  8:33 UTC (permalink / raw)
  To: LKML
  Cc: netdev, Richard Cochran, Christopher Hall, John Stultz,
	Frederic Weisbecker, Anna-Maria Behnsen, Miroslav Lichvar,
	Werner Abt, David Woodhouse, Stephen Boyd, Thomas Weißschuh,
	Kurt Kanzenbach, Nam Cao, Antoine Tenart

The behaviour is close to clock_adtime(CLOCK_REALTIME) with the
following differences:

  1) ADJ_SETOFFSET adjusts the auxiliary clock offset
  
  2) ADJ_TAI is not supported

  3) Leap seconds are not supported

  4) PPS is not supported

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 kernel/time/timekeeping.c |   16 ++++++++++++++++
 1 file changed, 16 insertions(+)
---
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -2860,10 +2860,26 @@ static int aux_clock_set(const clockid_t
 	return 0;
 }
 
+static int aux_clock_adj(const clockid_t id, struct __kernel_timex *txc)
+{
+	struct tk_data *tkd = aux_get_tk_data(id);
+	struct adjtimex_result result = { };
+
+	if (!tkd)
+		return -ENODEV;
+
+	/*
+	 * @result is ignored for now as there are neither hrtimers nor a
+	 * RTC related to auxiliary clocks for now.
+	 */
+	return __do_adjtimex(tkd, txc, &result);
+}
+
 const struct k_clock clock_aux = {
 	.clock_getres		= aux_get_res,
 	.clock_get_timespec	= aux_get_timespec,
 	.clock_set		= aux_clock_set,
+	.clock_adj		= aux_clock_adj,
 };
 
 static __init void tk_aux_setup(void)


^ permalink raw reply	[flat|nested] 57+ messages in thread

* [patch V2 25/26] timekeeping: Provide update for auxiliary timekeepers
  2025-05-19  8:33 [patch V2 00/26] timekeeping: Provide support for auxiliary timekeepers Thomas Gleixner
                   ` (23 preceding siblings ...)
  2025-05-19  8:33 ` [patch V2 24/26] timekeeping: Provide adjtimex() " Thomas Gleixner
@ 2025-05-19  8:33 ` Thomas Gleixner
  2025-05-19  8:33 ` [patch V2 26/26] timekeeping: Provide interface to control auxiliary clocks Thomas Gleixner
  25 siblings, 0 replies; 57+ messages in thread
From: Thomas Gleixner @ 2025-05-19  8:33 UTC (permalink / raw)
  To: LKML
  Cc: netdev, Richard Cochran, Christopher Hall, John Stultz,
	Frederic Weisbecker, Anna-Maria Behnsen, Miroslav Lichvar,
	Werner Abt, David Woodhouse, Stephen Boyd, Thomas Weißschuh,
	Kurt Kanzenbach, Nam Cao, Antoine Tenart

Update the auxiliary timekeepers periodically. For now this is tied to the system
timekeeper update from the tick. This might be revisited and moved out of the tick.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 kernel/time/timekeeping.c |   18 ++++++++++++++++++
 1 file changed, 18 insertions(+)
---
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -131,9 +131,11 @@ static struct tk_fast tk_fast_raw  ____c
 #ifdef CONFIG_POSIX_AUX_CLOCKS
 static __init void tk_aux_setup(void);
 static void tk_aux_update_clocksource(void);
+static void tk_aux_advance(void);
 #else
 static inline void tk_aux_setup(void) { }
 static inline void tk_aux_update_clocksource(void) { }
+static inline void tk_aux_advance(void) { }
 #endif
 
 unsigned long timekeeper_lock_irqsave(void)
@@ -2312,11 +2314,13 @@ static bool timekeeping_advance(enum tim
 /**
  * update_wall_time - Uses the current clocksource to increment the wall time
  *
+ * It also updates the enabled auxiliary clock timekeepers
  */
 void update_wall_time(void)
 {
 	if (timekeeping_advance(TK_ADV_TICK))
 		clock_was_set_delayed();
+	tk_aux_advance();
 }
 
 /**
@@ -2762,6 +2766,20 @@ static void tk_aux_update_clocksource(vo
 	}
 }
 
+static void tk_aux_advance(void)
+{
+	unsigned long active = READ_ONCE(aux_timekeepers);
+	unsigned int id;
+
+	for_each_set_bit(id, &active, BITS_PER_LONG) {
+		struct tk_data *tkd = &timekeeper_data[id + TIMEKEEPER_AUX];
+
+		guard(raw_spinlock)(&tkd->lock);
+		if (tkd->shadow_timekeeper.clock_valid)
+			__timekeeping_advance(tkd, TK_ADV_TICK);
+	}
+}
+
 /**
  * ktime_get_aux - Get TAI time for a AUX clock
  * @id:	ID of the clock to read (CLOCK_AUX...)


^ permalink raw reply	[flat|nested] 57+ messages in thread

* [patch V2 26/26] timekeeping: Provide interface to control auxiliary clocks
  2025-05-19  8:33 [patch V2 00/26] timekeeping: Provide support for auxiliary timekeepers Thomas Gleixner
                   ` (24 preceding siblings ...)
  2025-05-19  8:33 ` [patch V2 25/26] timekeeping: Provide update for auxiliary timekeepers Thomas Gleixner
@ 2025-05-19  8:33 ` Thomas Gleixner
  2025-06-13  7:18   ` Thomas Weißschuh
  25 siblings, 1 reply; 57+ messages in thread
From: Thomas Gleixner @ 2025-05-19  8:33 UTC (permalink / raw)
  To: LKML
  Cc: netdev, Richard Cochran, Christopher Hall, John Stultz,
	Frederic Weisbecker, Anna-Maria Behnsen, Miroslav Lichvar,
	Werner Abt, David Woodhouse, Stephen Boyd, Thomas Weißschuh,
	Kurt Kanzenbach, Nam Cao, Antoine Tenart

Auxiliary clocks are disabled by default and attempts to access them
fail.

Provide an interface to enable/disable them at run-time.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
 Documentation/ABI/stable/sysfs-kernel-time-aux-clocks |    5 
 kernel/time/timekeeping.c                             |  125 ++++++++++++++++++
 2 files changed, 130 insertions(+)

--- /dev/null
+++ b/Documentation/ABI/stable/sysfs-kernel-time-aux-clocks
@@ -0,0 +1,5 @@
+What:		/sys/kernel/time/aux_clocks/<ID>/enable
+Date:		May 2025
+Contact:	Thomas Gleixner <tglx@linutronix.de>
+Description:
+		Controls the enablement of auxiliary clock timekeepers.
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -14,6 +14,7 @@
 #include <linux/sched/loadavg.h>
 #include <linux/sched/clock.h>
 #include <linux/syscore_ops.h>
+#include <linux/sysfs.h>
 #include <linux/clocksource.h>
 #include <linux/jiffies.h>
 #include <linux/time.h>
@@ -2900,6 +2901,130 @@ const struct k_clock clock_aux = {
 	.clock_adj		= aux_clock_adj,
 };
 
+static void aux_clock_enable(unsigned int id)
+{
+	struct tk_read_base *tkr_raw = &tk_core.timekeeper.tkr_raw;
+	struct tk_data *tkd = aux_get_tk_data(id);
+	struct timekeeper *tks = &tkd->shadow_timekeeper;
+
+	/* Prevent the core timekeeper from changing. */
+	guard(raw_spinlock_irq)(&tk_core.lock);
+
+	/*
+	 * Setup the auxiliary clock assuming that the raw core timekeeper
+	 * clock frequency conversion is close enough. Userspace has to
+	 * adjust for the deviation via clock_adjtime(2).
+	 */
+	guard(raw_spinlock_nested)(&tkd->lock);
+
+	/* Remove leftovers of a previous registration */
+	memset(tks, 0, sizeof(*tks));
+	/* Restore the timekeeper id */
+	tks->id = tkd->timekeeper.id;
+	/* Setup the timekeeper based on the current system clocksource */
+	tk_setup_internals(tks, tkr_raw->clock);
+
+	/* Mark it valid and set it live */
+	tks->clock_valid = true;
+	timekeeping_update_from_shadow(tkd, TK_UPDATE_ALL);
+}
+
+static void aux_clock_disable(unsigned int id)
+{
+	struct tk_data *tkd = aux_get_tk_data(id);
+
+	guard(raw_spinlock_irq)(&tkd->lock);
+	tkd->shadow_timekeeper.clock_valid = false;
+	timekeeping_update_from_shadow(tkd, TK_UPDATE_ALL);
+}
+
+static DEFINE_MUTEX(aux_clock_mutex);
+
+static ssize_t aux_clock_enable_store(struct kobject *kobj, struct kobj_attribute *attr,
+				      const char *buf, size_t count)
+{
+	/* Lazy atoi() as name is "0..7" */
+	int id = kobj->name[0] & 0x7;
+	bool enable;
+
+	if (!capable(CAP_SYS_TIME))
+		return -EPERM;
+
+	if (kstrtobool(buf, &enable) < 0)
+		return -EINVAL;
+
+	guard(mutex)(&aux_clock_mutex);
+	if (enable == test_bit(id, &aux_timekeepers))
+		return count;
+
+	if (enable) {
+		aux_clock_enable(CLOCK_AUX + id);
+		set_bit(id, &aux_timekeepers);
+	} else {
+		aux_clock_disable(CLOCK_AUX + id);
+		clear_bit(id, &aux_timekeepers);
+	}
+	return count;
+}
+
+static ssize_t aux_clock_enable_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+	unsigned long active = READ_ONCE(aux_timekeepers);
+	/* Lazy atoi() as name is "0..7" */
+	int id = kobj->name[0] & 0x7;
+
+	return sysfs_emit(buf, "%d\n", test_bit(id, &active));
+}
+
+static struct kobj_attribute aux_clock_enable_attr = __ATTR_RW(aux_clock_enable);
+
+static struct attribute *aux_clock_enable_attrs[] = {
+	&aux_clock_enable_attr.attr,
+	NULL,
+};
+
+static const struct attribute_group aux_clock_enable_attr_group = {
+	.attrs = aux_clock_enable_attrs,
+};
+
+static int __init tk_aux_sysfs_init(void)
+{
+	struct kobject *auxo, *tko = kobject_create_and_add("time", kernel_kobj);
+
+	if (!tko) {
+		pr_warn("Unable to create /sys/kernel/time/. POSIX AUX clocks disabled.\n");
+		return -ENOMEM;
+	}
+
+	auxo = kobject_create_and_add("aux_clocks", tko);
+	if (!auxo) {
+		pr_warn("Unable to create /sys/kernel/time/aux_clocks. POSIX AUX clocks disabled.\n");
+		kobject_put(tko);
+		return -ENOMEM;
+	}
+
+	for (int i = TIMEKEEPER_AUX; i <= TIMEKEEPER_AUX_LAST; i++) {
+		char id[2] = { [0] = '0' + (i - TIMEKEEPER_AUX), };
+		struct kobject *clk = kobject_create_and_add(id, auxo);
+
+		if (!clk) {
+			pr_warn("Unable to create /sys/kernel/time/aux_clocks/%d\n",
+				i - TIMEKEEPER_AUX);
+			return -ENOMEM;
+		}
+
+		int ret = sysfs_create_group(clk, &aux_clock_enable_attr_group);
+
+		if (ret) {
+			pr_warn("Unable to create /sys/kernel/time/aux_clocks/%d/enable\n",
+				i - TIMEKEEPER_AUX);
+			return ret;
+		}
+	}
+	return 0;
+}
+late_initcall(tk_aux_sysfs_init);
+
 static __init void tk_aux_setup(void)
 {
 	for (int i = TIMEKEEPER_AUX; i <= TIMEKEEPER_AUX_LAST; i++)


^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [patch V2 01/26] timekeeping: Remove hardcoded access to tk_core
  2025-05-19  8:33 ` [patch V2 01/26] timekeeping: Remove hardcoded access to tk_core Thomas Gleixner
@ 2025-06-12 22:34   ` John Stultz
  2025-06-25 16:16   ` [tip: timers/ptp] " tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 57+ messages in thread
From: John Stultz @ 2025-06-12 22:34 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, netdev, Richard Cochran, Christopher Hall,
	Frederic Weisbecker, Anna-Maria Behnsen, Miroslav Lichvar,
	Werner Abt, David Woodhouse, Stephen Boyd, Thomas Weißschuh,
	Kurt Kanzenbach, Nam Cao, Antoine Tenart

On Mon, May 19, 2025 at 1:33 AM Thomas Gleixner <tglx@linutronix.de> wrote:
>
> This was overlooked in the initial conversion. Use the provided pointer to
> access the shadow timekeeper.
>
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

Acked-by: John Stultz <jstultz@google.com>

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [patch V2 02/26] timekeeping: Cleanup kernel doc of __ktime_get_real_seconds()
  2025-05-19  8:33 ` [patch V2 02/26] timekeeping: Cleanup kernel doc of __ktime_get_real_seconds() Thomas Gleixner
@ 2025-06-12 22:36   ` John Stultz
  2025-06-25 16:16   ` [tip: timers/ptp] " tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 57+ messages in thread
From: John Stultz @ 2025-06-12 22:36 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, netdev, Richard Cochran, Christopher Hall,
	Frederic Weisbecker, Anna-Maria Behnsen, Miroslav Lichvar,
	Werner Abt, David Woodhouse, Stephen Boyd, Thomas Weißschuh,
	Kurt Kanzenbach, Nam Cao, Antoine Tenart

On Mon, May 19, 2025 at 1:33 AM Thomas Gleixner <tglx@linutronix.de> wrote:
>
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

Not a fan of empty commit messages, but:
Acked-by: John Stultz <jstultz@google.com>

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [patch V2 04/26] timekeeping: Introduce timekeeper ID
  2025-05-19  8:33 ` [patch V2 04/26] timekeeping: Introduce timekeeper ID Thomas Gleixner
@ 2025-06-13  0:03   ` John Stultz
  2025-06-25 16:16   ` [tip: timers/ptp] " tip-bot2 for Anna-Maria Behnsen
  1 sibling, 0 replies; 57+ messages in thread
From: John Stultz @ 2025-06-13  0:03 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, netdev, Richard Cochran, Christopher Hall,
	Frederic Weisbecker, Anna-Maria Behnsen, Miroslav Lichvar,
	Werner Abt, David Woodhouse, Stephen Boyd, Thomas Weißschuh,
	Kurt Kanzenbach, Nam Cao, Antoine Tenart

On Mon, May 19, 2025 at 1:33 AM Thomas Gleixner <tglx@linutronix.de> wrote:
>
> From: Anna-Maria Behnsen <anna-maria@linutronix.de>
>
> As long as there is only a single timekeeper, there is no need to clarify
> which timekeeper is used. But with the upcoming reusage of the timekeeper
> infrastructure for auxiliary clock timekeepers, an ID is required to
> differentiate.
>
> Introduce an enum for timekeeper IDs, introduce a field in struct tk_data
> to store this timekeeper id and add also initialization. The id struct
> field is added at the end of the second cachline, as there is a 4 byte hole
> anyway.
>
> Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
>

Acked-by: John Stultz <jstultz@google.com>

thanks
-john

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [patch V2 05/26] time: Introduce auxiliary POSIX clocks
  2025-05-19  8:33 ` [patch V2 05/26] time: Introduce auxiliary POSIX clocks Thomas Gleixner
@ 2025-06-13  0:06   ` John Stultz
  2025-06-25 16:16   ` [tip: timers/ptp] " tip-bot2 for Anna-Maria Behnsen
  1 sibling, 0 replies; 57+ messages in thread
From: John Stultz @ 2025-06-13  0:06 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, netdev, Richard Cochran, Christopher Hall,
	Frederic Weisbecker, Anna-Maria Behnsen, Miroslav Lichvar,
	Werner Abt, David Woodhouse, Stephen Boyd, Thomas Weißschuh,
	Kurt Kanzenbach, Nam Cao, Antoine Tenart

On Mon, May 19, 2025 at 1:33 AM Thomas Gleixner <tglx@linutronix.de> wrote:
>
> From: Anna-Maria Behnsen <anna-maria@linutronix.de>
>
> To support auxiliary timekeeping and the related user space interfaces,
> it's required to define a clock ID range for them.
>
> Reserve 8 auxiliary clock IDs after the regular timekeeping clock ID space.
>
> This is the maximum number of auxiliary clocks the kernel can support. The actual
> number of supported clocks depends obviously on the presence of related devices
> and might be constraint by the available VDSO space.
>
> Add the corresponding timekeeper IDs as well.
>
> Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

Acked-by: John Stultz <jstultz@google.com>

thanks
-john

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [patch V2 06/26] ntp: Add support for auxiliary timekeepers
  2025-05-19  8:33 ` [patch V2 06/26] ntp: Add support for auxiliary timekeepers Thomas Gleixner
@ 2025-06-13  0:14   ` John Stultz
  2025-06-13  6:32   ` Thomas Weißschuh
  2025-06-25 16:16   ` [tip: timers/ptp] " tip-bot2 for Thomas Gleixner
  2 siblings, 0 replies; 57+ messages in thread
From: John Stultz @ 2025-06-13  0:14 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, netdev, Richard Cochran, Christopher Hall,
	Frederic Weisbecker, Anna-Maria Behnsen, Miroslav Lichvar,
	Werner Abt, David Woodhouse, Stephen Boyd, Thomas Weißschuh,
	Kurt Kanzenbach, Nam Cao, Antoine Tenart

On Mon, May 19, 2025 at 1:33 AM Thomas Gleixner <tglx@linutronix.de> wrote:
>
> If auxiliary clocks are enabled, provide an array of NTP data so that the
> auxiliary timekeepers can be steered independently of the core timekeeper.
>
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

Acked-by: John Stultz <jstultz@google.com>

thanks
-john

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [patch V2 07/26] ntp: Add timekeeper ID arguments to public functions
  2025-05-19  8:33 ` [patch V2 07/26] ntp: Add timekeeper ID arguments to public functions Thomas Gleixner
@ 2025-06-13  0:20   ` John Stultz
  2025-06-25 16:16   ` [tip: timers/ptp] " tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 57+ messages in thread
From: John Stultz @ 2025-06-13  0:20 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, netdev, Richard Cochran, Christopher Hall,
	Frederic Weisbecker, Anna-Maria Behnsen, Miroslav Lichvar,
	Werner Abt, David Woodhouse, Stephen Boyd, Thomas Weißschuh,
	Kurt Kanzenbach, Nam Cao, Antoine Tenart

On Mon, May 19, 2025 at 1:33 AM Thomas Gleixner <tglx@linutronix.de> wrote:
>
> In preparation for supporting auxiliary POSIX clocks, add a timekeeper ID
> to the relevant functions.
>
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

Acked-by: John Stultz <jstultz@google.com>

thanks
-john

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [patch V2 08/26] ntp: Rename __do_adjtimex() to ntp_adjtimex()
  2025-05-19  8:33 ` [patch V2 08/26] ntp: Rename __do_adjtimex() to ntp_adjtimex() Thomas Gleixner
@ 2025-06-13  0:20   ` John Stultz
  2025-06-25 16:16   ` [tip: timers/ptp] " tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 57+ messages in thread
From: John Stultz @ 2025-06-13  0:20 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, netdev, Richard Cochran, Christopher Hall,
	Frederic Weisbecker, Anna-Maria Behnsen, Miroslav Lichvar,
	Werner Abt, David Woodhouse, Stephen Boyd, Thomas Weißschuh,
	Kurt Kanzenbach, Nam Cao, Antoine Tenart

On Mon, May 19, 2025 at 1:33 AM Thomas Gleixner <tglx@linutronix.de> wrote:
>
> Clean up the name space. No functional change.
>
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

Acked-by: John Stultz <jstultz@google.com>

thanks
-john

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [patch V2 09/26] timekeeping: Make __timekeeping_advance() reusable
  2025-05-19  8:33 ` [patch V2 09/26] timekeeping: Make __timekeeping_advance() reusable Thomas Gleixner
@ 2025-06-13  0:23   ` John Stultz
  2025-06-25 16:16   ` [tip: timers/ptp] " tip-bot2 for Anna-Maria Behnsen
  1 sibling, 0 replies; 57+ messages in thread
From: John Stultz @ 2025-06-13  0:23 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, netdev, Richard Cochran, Christopher Hall,
	Frederic Weisbecker, Anna-Maria Behnsen, Miroslav Lichvar,
	Werner Abt, David Woodhouse, Stephen Boyd, Thomas Weißschuh,
	Kurt Kanzenbach, Nam Cao, Antoine Tenart

On Mon, May 19, 2025 at 1:33 AM Thomas Gleixner <tglx@linutronix.de> wrote:
>
> From: Anna-Maria Behnsen <anna-maria@linutronix.de>
>
> In __timekeeping_advance() the pointer to struct tk_data is hardcoded by the
> use of &tk_core. As long as there is only a single timekeeper (tk_core),
> this is not a problem. But when __timekeeping_advance() will be reused for
> per auxiliary timekeepers, __timekeeping_advance() needs to be generalized.
>
> Add a pointer to struct tk_data as function argument of
> __timekeeping_advance() and adapt all call sites.
>
> Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

Acked-by: John Stultz <jstultz@google.com>

thanks
-john

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [patch V2 11/26] timekeeping: Add clock_valid flag to timekeeper
  2025-05-19  8:33 ` [patch V2 11/26] timekeeping: Add clock_valid flag to timekeeper Thomas Gleixner
@ 2025-06-13  4:05   ` John Stultz
  2025-06-25 16:15   ` [tip: timers/ptp] " tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 57+ messages in thread
From: John Stultz @ 2025-06-13  4:05 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, netdev, Richard Cochran, Christopher Hall,
	Frederic Weisbecker, Anna-Maria Behnsen, Miroslav Lichvar,
	Werner Abt, David Woodhouse, Stephen Boyd, Thomas Weißschuh,
	Kurt Kanzenbach, Nam Cao, Antoine Tenart

On Mon, May 19, 2025 at 1:33 AM Thomas Gleixner <tglx@linutronix.de> wrote:
>
> From: Thomas Gleixner <tglx@linutronix.de>
>
> In preparation for supporting independent auxiliary timekeepers, add a
> clock valid field and set it to true for the system timekeeper.
>
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

Acked-by: John Stultz <jstultz@google.com>

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [patch V2 06/26] ntp: Add support for auxiliary timekeepers
  2025-05-19  8:33 ` [patch V2 06/26] ntp: Add support for auxiliary timekeepers Thomas Gleixner
  2025-06-13  0:14   ` John Stultz
@ 2025-06-13  6:32   ` Thomas Weißschuh
  2025-06-25 16:16   ` [tip: timers/ptp] " tip-bot2 for Thomas Gleixner
  2 siblings, 0 replies; 57+ messages in thread
From: Thomas Weißschuh @ 2025-06-13  6:32 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, netdev, Richard Cochran, Christopher Hall, John Stultz,
	Frederic Weisbecker, Anna-Maria Behnsen, Miroslav Lichvar,
	Werner Abt, David Woodhouse, Stephen Boyd, Kurt Kanzenbach,
	Nam Cao, Antoine Tenart

On Mon, May 19, 2025 at 10:33:21AM +0200, Thomas Gleixner wrote:
> If auxiliary clocks are enabled, provide an array of NTP data so that the
> auxiliary timekeepers can be steered independently of the core timekeeper.
> 
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> ---
>  kernel/time/ntp.c |   41 ++++++++++++++++++++++-------------------
>  1 file changed, 22 insertions(+), 19 deletions(-)

<snip>

>  void __init ntp_init(void)
>  {
> -	ntp_clear();
> +	for (int id = 0; id < TIMEKEEPERS_MAX; id++)
> +		__ntp_clear(tk_ntp_data + id);

For consistency with the rest of the code:

__ntp_clear(&tk_ntp_data[id]);

>  	ntp_init_cmos_sync();
>  }
> 

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [patch V2 26/26] timekeeping: Provide interface to control auxiliary clocks
  2025-05-19  8:33 ` [patch V2 26/26] timekeeping: Provide interface to control auxiliary clocks Thomas Gleixner
@ 2025-06-13  7:18   ` Thomas Weißschuh
  0 siblings, 0 replies; 57+ messages in thread
From: Thomas Weißschuh @ 2025-06-13  7:18 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, netdev, Richard Cochran, Christopher Hall, John Stultz,
	Frederic Weisbecker, Anna-Maria Behnsen, Miroslav Lichvar,
	Werner Abt, David Woodhouse, Stephen Boyd, Kurt Kanzenbach,
	Nam Cao, Antoine Tenart

On Mon, May 19, 2025 at 10:33:46AM +0200, Thomas Gleixner wrote:
> Auxiliary clocks are disabled by default and attempts to access them
> fail.
> 
> Provide an interface to enable/disable them at run-time.
> 
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> ---
>  Documentation/ABI/stable/sysfs-kernel-time-aux-clocks |    5 
>  kernel/time/timekeeping.c                             |  125 ++++++++++++++++++
>  2 files changed, 130 insertions(+)

<snip>

> --- a/kernel/time/timekeeping.c
> +++ b/kernel/time/timekeeping.c
> @@ -14,6 +14,7 @@
>  #include <linux/sched/loadavg.h>
>  #include <linux/sched/clock.h>
>  #include <linux/syscore_ops.h>
> +#include <linux/sysfs.h>

#include <linux/kobject.h>

>  #include <linux/clocksource.h>
>  #include <linux/jiffies.h>
>  #include <linux/time.h>
> @@ -2900,6 +2901,130 @@ const struct k_clock clock_aux = {
>  	.clock_adj		= aux_clock_adj,
>  };
>  
> +static void aux_clock_enable(unsigned int id)

"clockid_t id".

> +{
> +	struct tk_read_base *tkr_raw = &tk_core.timekeeper.tkr_raw;
> +	struct tk_data *tkd = aux_get_tk_data(id);
> +	struct timekeeper *tks = &tkd->shadow_timekeeper;
> +
> +	/* Prevent the core timekeeper from changing. */
> +	guard(raw_spinlock_irq)(&tk_core.lock);
> +
> +	/*
> +	 * Setup the auxiliary clock assuming that the raw core timekeeper
> +	 * clock frequency conversion is close enough. Userspace has to
> +	 * adjust for the deviation via clock_adjtime(2).
> +	 */
> +	guard(raw_spinlock_nested)(&tkd->lock);
> +
> +	/* Remove leftovers of a previous registration */
> +	memset(tks, 0, sizeof(*tks));
> +	/* Restore the timekeeper id */
> +	tks->id = tkd->timekeeper.id;
> +	/* Setup the timekeeper based on the current system clocksource */
> +	tk_setup_internals(tks, tkr_raw->clock);
> +
> +	/* Mark it valid and set it live */
> +	tks->clock_valid = true;
> +	timekeeping_update_from_shadow(tkd, TK_UPDATE_ALL);
> +}

<snip>

> +static struct kobj_attribute aux_clock_enable_attr = __ATTR_RW(aux_clock_enable);
> +
> +static struct attribute *aux_clock_enable_attrs[] = {
> +	&aux_clock_enable_attr.attr,
> +	NULL,

There should be no comma after sentinel values.

> +};
> +
> +static const struct attribute_group aux_clock_enable_attr_group = {
> +	.attrs = aux_clock_enable_attrs,
> +};
> +
> +static int __init tk_aux_sysfs_init(void)
> +{
> +	struct kobject *auxo, *tko = kobject_create_and_add("time", kernel_kobj);
> +
> +	if (!tko) {
> +		pr_warn("Unable to create /sys/kernel/time/. POSIX AUX clocks disabled.\n");

The other timer code does not log details on failed initcalls.
To me the strings look like wasted memory.
If failure is really intended to be handled gracefully then some cleanup logic
may be necessary, too.

> +		return -ENOMEM;
> +	}
> +
> +	auxo = kobject_create_and_add("aux_clocks", tko);
> +	if (!auxo) {
> +		pr_warn("Unable to create /sys/kernel/time/aux_clocks. POSIX AUX clocks disabled.\n");
> +		kobject_put(tko);
> +		return -ENOMEM;
> +	}
> +
> +	for (int i = TIMEKEEPER_AUX; i <= TIMEKEEPER_AUX_LAST; i++) {

for (int i = 0; i < MAX_AUX_CLOCKS; i++)

This avoids the need for the repeated calculations below and also better
matches the actual semantics.

> +		char id[2] = { [0] = '0' + (i - TIMEKEEPER_AUX), };
> +		struct kobject *clk = kobject_create_and_add(id, auxo);
> +
> +		if (!clk) {
> +			pr_warn("Unable to create /sys/kernel/time/aux_clocks/%d\n",
> +				i - TIMEKEEPER_AUX);
> +			return -ENOMEM;
> +		}
> +
> +		int ret = sysfs_create_group(clk, &aux_clock_enable_attr_group);
> +
> +		if (ret) {
> +			pr_warn("Unable to create /sys/kernel/time/aux_clocks/%d/enable\n",
> +				i - TIMEKEEPER_AUX);


> +			return ret;
> +		}
> +	}
> +	return 0;
> +}
> +late_initcall(tk_aux_sysfs_init);
> +
>  static __init void tk_aux_setup(void)
>  {
>  	For (int i = TIMEKEEPER_AUX; i <= TIMEKEEPER_AUX_LAST; i++)
> 

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [patch V2 12/26] timekeeping: Introduce auxiliary timekeepers
  2025-05-19  8:33 ` [patch V2 12/26] timekeeping: Introduce auxiliary timekeepers Thomas Gleixner
@ 2025-06-14  2:41   ` John Stultz
  2025-06-25 16:15   ` [tip: timers/ptp] " tip-bot2 for Anna-Maria Behnsen
  1 sibling, 0 replies; 57+ messages in thread
From: John Stultz @ 2025-06-14  2:41 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, netdev, Richard Cochran, Christopher Hall,
	Frederic Weisbecker, Anna-Maria Behnsen, Miroslav Lichvar,
	Werner Abt, David Woodhouse, Stephen Boyd, Thomas Weißschuh,
	Kurt Kanzenbach, Nam Cao, Antoine Tenart

On Mon, May 19, 2025 at 1:33 AM Thomas Gleixner <tglx@linutronix.de> wrote:
>
> From: Anna-Maria Behnsen <anna-maria@linutronix.de>
>
> Provide timekeepers for auxiliary clocks and initialize them during
> boot.
>
> Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
>
> ---
>  kernel/time/timekeeping.c |   22 ++++++++++++++++++++--
>  1 file changed, 20 insertions(+), 2 deletions(-)
> ---
> --- a/kernel/time/timekeeping.c
> +++ b/kernel/time/timekeeping.c
> @@ -2630,3 +2640,11 @@ void hardpps(const struct timespec64 *ph
>  }
>  EXPORT_SYMBOL(hardpps);
>  #endif /* CONFIG_NTP_PPS */
> +
> +#ifdef CONFIG_POSIX_AUX_CLOCKS
> +static __init void tk_aux_setup(void)
> +{
> +       for (int i = TIMEKEEPER_AUX; i <= TIMEKEEPER_AUX_LAST; i++)

My only thought here, seeing its use,  would it be better if
TIMEKEEPER_AUX was TIMEKEEPER_AUX_FIRST?

Acked-by: John Stultz <jstultz@google.com>
thanks
-john

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [patch V2 15/26] timekeeping: Add AUX offset to struct timekeeper
  2025-05-19  8:33 ` [patch V2 15/26] timekeeping: Add AUX offset to struct timekeeper Thomas Gleixner
@ 2025-06-14  2:44   ` John Stultz
  2025-06-25 16:15   ` [tip: timers/ptp] " tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 57+ messages in thread
From: John Stultz @ 2025-06-14  2:44 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, netdev, Richard Cochran, Christopher Hall,
	Frederic Weisbecker, Anna-Maria Behnsen, Miroslav Lichvar,
	Werner Abt, David Woodhouse, Stephen Boyd, Thomas Weißschuh,
	Kurt Kanzenbach, Nam Cao, Antoine Tenart

On Mon, May 19, 2025 at 1:33 AM Thomas Gleixner <tglx@linutronix.de> wrote:
>
> This offset will be used in the time getters of auxiliary clocks. It is
> added to the "monotonic" clock readout.
>
> As auxiliary clocks do not utilize the offset fields of the core time
> keeper, this is just an alias for offs_tai, so that the cache line layout
> stays the same.
>
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
> ---
>  include/linux/timekeeper_internal.h |    6 +++++-
>  1 file changed, 5 insertions(+), 1 deletion(-)
> ---
> --- a/include/linux/timekeeper_internal.h
> +++ b/include/linux/timekeeper_internal.h
> @@ -67,6 +67,7 @@ struct tk_read_base {
>   * @offs_real:                 Offset clock monotonic -> clock realtime
>   * @offs_boot:                 Offset clock monotonic -> clock boottime
>   * @offs_tai:                  Offset clock monotonic -> clock tai
> + * @offs_aux:                  Offset clock monotonic -> clock AUX
>   * @coarse_nsec:               The nanoseconds part for coarse time getters
>   * @id:                                The timekeeper ID
>   * @tkr_raw:                   The readout base structure for CLOCK_MONOTONIC_RAW
> @@ -139,7 +140,10 @@ struct timekeeper {
>         struct timespec64       wall_to_monotonic;
>         ktime_t                 offs_real;
>         ktime_t                 offs_boot;
> -       ktime_t                 offs_tai;
> +       union {
> +               ktime_t         offs_tai;
> +               ktime_t         offs_aux;
> +       };

Probably could use a clarifying comment similar to what you have in
the commit message "auxiliary clocks do not utilize the offset fields
of the core time keeper"

Otherwise,
 Acked-by: John Stultz <jstultz@google.com>

thanks
-john

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [patch V2 17/26] timekeeping: Provide time getters for auxiliary clocks
  2025-05-19  8:33 ` [patch V2 17/26] timekeeping: Provide time getters for auxiliary clocks Thomas Gleixner
@ 2025-06-14  2:51   ` John Stultz
  2025-06-14  7:18     ` Thomas Gleixner
  0 siblings, 1 reply; 57+ messages in thread
From: John Stultz @ 2025-06-14  2:51 UTC (permalink / raw)
  To: Thomas Gleixner
  Cc: LKML, netdev, Richard Cochran, Christopher Hall,
	Frederic Weisbecker, Anna-Maria Behnsen, Miroslav Lichvar,
	Werner Abt, David Woodhouse, Stephen Boyd, Thomas Weißschuh,
	Kurt Kanzenbach, Nam Cao, Antoine Tenart

On Mon, May 19, 2025 at 1:33 AM Thomas Gleixner <tglx@linutronix.de> wrote:
>
> Provide interfaces similar to the ktime_get*() family which provide access
> to the auxiliary clocks.
>
> These interfaces have a boolean return value, which indicates whether the
> accessed clock is valid or not.
>
> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
>
> ---
>  include/linux/timekeeping.h |   11 +++++++
>  kernel/time/timekeeping.c   |   62 ++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 73 insertions(+)
> ---
> --- a/include/linux/timekeeping.h
> +++ b/include/linux/timekeeping.h
> @@ -263,6 +263,17 @@ extern bool timekeeping_rtc_skipresume(v
>
>  extern void timekeeping_inject_sleeptime64(const struct timespec64 *delta);
>
> +/*
> + * Auxiliary clock interfaces
> + */
> +#ifdef CONFIG_POSIX_AUX_CLOCKS
> +extern bool ktime_get_aux(clockid_t id, ktime_t *kt);
> +extern bool ktime_get_aux_ts64(clockid_t id, struct timespec64 *kt);
> +#else
> +static inline bool ktime_get_aux(clockid_t id, ktime_t *kt) { return false; }
> +static inline bool ktime_get_aux_ts64(clockid_t id, struct timespec64 *kt) { return false; }
> +#endif
> +
>  /**
>   * struct system_time_snapshot - simultaneous raw/real time capture with
>   *                              counter value
> --- a/kernel/time/timekeeping.c
> +++ b/kernel/time/timekeeping.c
> @@ -2659,6 +2659,23 @@ EXPORT_SYMBOL(hardpps);
>  /* Bitmap for the activated auxiliary timekeepers */
>  static unsigned long aux_timekeepers;
>
> +static inline bool aux_valid_clockid(clockid_t id)
> +{
> +       return id >= CLOCK_AUX && id <= CLOCK_AUX_LAST;
> +}
> +
> +static inline unsigned int clockid_to_tkid(unsigned int id)
> +{
> +       return TIMEKEEPER_AUX + id - CLOCK_AUX;
> +}
> +
> +static inline struct tk_data *aux_get_tk_data(clockid_t id)
> +{
> +       if (!aux_valid_clockid(id))
> +               return NULL;
> +       return &timekeeper_data[clockid_to_tkid(id)];
> +}
> +
>  /* Invoked from timekeeping after a clocksource change */
>  static void tk_aux_update_clocksource(void)
>  {
> @@ -2679,6 +2696,51 @@ static void tk_aux_update_clocksource(vo
>         }
>  }
>
> +/**
> + * ktime_get_aux - Get TAI time for a AUX clock

Is this actually the TAI time? Wouldn't it be the MONOTONIC time for
the AUX clock?

> + * @id:        ID of the clock to read (CLOCK_AUX...)
> + * @kt:        Pointer to ktime_t to store the time stamp
> + *
> + * Returns: True if the timestamp is valid, false otherwise
> + */
> +bool ktime_get_aux(clockid_t id, ktime_t *kt)
> +{
> +       struct tk_data *tkd = aux_get_tk_data(id);
> +       struct timekeeper *tk;

Nit: Just to be super explicit, would it be good to name these aux_tk
and aux_tkd?
So it's more clear you're not working with the standard timekeeper?

thanks
-john

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [patch V2 17/26] timekeeping: Provide time getters for auxiliary clocks
  2025-06-14  2:51   ` John Stultz
@ 2025-06-14  7:18     ` Thomas Gleixner
  0 siblings, 0 replies; 57+ messages in thread
From: Thomas Gleixner @ 2025-06-14  7:18 UTC (permalink / raw)
  To: John Stultz
  Cc: LKML, netdev, Richard Cochran, Christopher Hall,
	Frederic Weisbecker, Anna-Maria Behnsen, Miroslav Lichvar,
	Werner Abt, David Woodhouse, Stephen Boyd, Thomas Weißschuh,
	Kurt Kanzenbach, Nam Cao, Antoine Tenart

On Fri, Jun 13 2025 at 19:51, John Stultz wrote:
> On Mon, May 19, 2025 at 1:33 AM Thomas Gleixner <tglx@linutronix.de> wrote:
>> +/**
>> + * ktime_get_aux - Get TAI time for a AUX clock
>
> Is this actually the TAI time? Wouldn't it be the MONOTONIC time for
> the AUX clock?

Of course not TAI. It's not monotonic either as it can be set. It's just
AUX clock time, whatever that means :)

>> + * @id:        ID of the clock to read (CLOCK_AUX...)
>> + * @kt:        Pointer to ktime_t to store the time stamp
>> + *
>> + * Returns: True if the timestamp is valid, false otherwise
>> + */
>> +bool ktime_get_aux(clockid_t id, ktime_t *kt)
>> +{
>> +       struct tk_data *tkd = aux_get_tk_data(id);
>> +       struct timekeeper *tk;
>
> Nit: Just to be super explicit, would it be good to name these aux_tk
> and aux_tkd?
> So it's more clear you're not working with the standard timekeeper?

Yes.

^ permalink raw reply	[flat|nested] 57+ messages in thread

* [tip: timers/ptp] timekeeping: Add AUX offset to struct timekeeper
  2025-05-19  8:33 ` [patch V2 15/26] timekeeping: Add AUX offset to struct timekeeper Thomas Gleixner
  2025-06-14  2:44   ` John Stultz
@ 2025-06-25 16:15   ` tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 57+ messages in thread
From: tip-bot2 for Thomas Gleixner @ 2025-06-25 16:15 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: Thomas Gleixner, John Stultz, x86, linux-kernel

The following commit has been merged into the timers/ptp branch of tip:

Commit-ID:     180d8b4ce91fe0cf7a9cb236bb01f14587ba4bf0
Gitweb:        https://git.kernel.org/tip/180d8b4ce91fe0cf7a9cb236bb01f14587ba4bf0
Author:        Thomas Gleixner <tglx@linutronix.de>
AuthorDate:    Mon, 19 May 2025 10:33:32 +02:00
Committer:     Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Thu, 19 Jun 2025 14:28:24 +02:00

timekeeping: Add AUX offset to struct timekeeper

This offset will be used in the time getters of auxiliary clocks. It is
added to the "monotonic" clock readout.

As auxiliary clocks do not utilize the offset fields of the core time
keeper, this is just an alias for offs_tai, so that the cache line layout
stays the same.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Acked-by: John Stultz <jstultz@google.com>
Link: https://lore.kernel.org/all/20250519083026.533486349@linutronix.de

---
 include/linux/timekeeper_internal.h |  9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/include/linux/timekeeper_internal.h b/include/linux/timekeeper_internal.h
index 1690eda..ca79938 100644
--- a/include/linux/timekeeper_internal.h
+++ b/include/linux/timekeeper_internal.h
@@ -67,6 +67,7 @@ struct tk_read_base {
  * @offs_real:			Offset clock monotonic -> clock realtime
  * @offs_boot:			Offset clock monotonic -> clock boottime
  * @offs_tai:			Offset clock monotonic -> clock tai
+ * @offs_aux:			Offset clock monotonic -> clock AUX
  * @coarse_nsec:		The nanoseconds part for coarse time getters
  * @id:				The timekeeper ID
  * @tkr_raw:			The readout base structure for CLOCK_MONOTONIC_RAW
@@ -113,6 +114,9 @@ struct tk_read_base {
  * @monotonic_to_boottime is a timespec64 representation of @offs_boot to
  * accelerate the VDSO update for CLOCK_BOOTTIME.
  *
+ * @offs_aux is used by the auxiliary timekeepers which do not utilize any
+ * of the regular timekeeper offset fields.
+ *
  * The cacheline ordering of the structure is optimized for in kernel usage of
  * the ktime_get() and ktime_get_ts64() family of time accessors. Struct
  * timekeeper is prepended in the core timekeeping code with a sequence count,
@@ -139,7 +143,10 @@ struct timekeeper {
 	struct timespec64	wall_to_monotonic;
 	ktime_t			offs_real;
 	ktime_t			offs_boot;
-	ktime_t			offs_tai;
+	union {
+		ktime_t		offs_tai;
+		ktime_t		offs_aux;
+	};
 	u32			coarse_nsec;
 	enum timekeeper_ids	id;
 

^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [tip: timers/ptp] ntp: Use ktime_get_ntp_seconds()
  2025-05-19  8:33 ` [patch V2 14/26] ntp: Use ktime_get_ntp_seconds() Thomas Gleixner
@ 2025-06-25 16:15   ` tip-bot2 for Thomas Gleixner
  0 siblings, 0 replies; 57+ messages in thread
From: tip-bot2 for Thomas Gleixner @ 2025-06-25 16:15 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: Thomas Gleixner, x86, linux-kernel

The following commit has been merged into the timers/ptp branch of tip:

Commit-ID:     c85f5ab60820bde1510110e403d17456fbb8c266
Gitweb:        https://git.kernel.org/tip/c85f5ab60820bde1510110e403d17456fbb8c266
Author:        Thomas Gleixner <tglx@linutronix.de>
AuthorDate:    Mon, 19 May 2025 10:33:31 +02:00
Committer:     Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Thu, 19 Jun 2025 14:28:24 +02:00

ntp: Use ktime_get_ntp_seconds()

Use ktime_get_ntp_seconds() to prepare for auxiliary clocks so that
the readout becomes per timekeeper.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Link: https://lore.kernel.org/all/20250519083026.472512636@linutronix.de


---
 kernel/time/ntp.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c
index 9aba1bc..97fa99b 100644
--- a/kernel/time/ntp.c
+++ b/kernel/time/ntp.c
@@ -303,7 +303,7 @@ static void ntp_update_offset(struct ntp_data *ntpdata, long offset)
 	 * Select how the frequency is to be controlled
 	 * and in which mode (PLL or FLL).
 	 */
-	real_secs = __ktime_get_real_seconds();
+	real_secs = ktime_get_ntp_seconds(ntpdata - tk_ntp_data);
 	secs = (long)(real_secs - ntpdata->time_reftime);
 	if (unlikely(ntpdata->time_status & STA_FREQHOLD))
 		secs = 0;
@@ -710,7 +710,7 @@ static inline void process_adj_status(struct ntp_data *ntpdata, const struct __k
 	 * reference time to current time.
 	 */
 	if (!(ntpdata->time_status & STA_PLL) && (txc->status & STA_PLL))
-		ntpdata->time_reftime = __ktime_get_real_seconds();
+		ntpdata->time_reftime = ktime_get_ntp_seconds(ntpdata - tk_ntp_data);
 
 	/* only set allowed bits */
 	ntpdata->time_status &= STA_RONLY;

^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [tip: timers/ptp] timekeeping: Provide ktime_get_ntp_seconds()
  2025-05-19  8:33 ` [patch V2 13/26] timekeeping: Provide ktime_get_ntp_seconds() Thomas Gleixner
@ 2025-06-25 16:15   ` tip-bot2 for Thomas Gleixner
  0 siblings, 0 replies; 57+ messages in thread
From: tip-bot2 for Thomas Gleixner @ 2025-06-25 16:15 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: Thomas Gleixner, x86, linux-kernel

The following commit has been merged into the timers/ptp branch of tip:

Commit-ID:     ffa0519baaed48ca953bd201e1b17f15dae21b2d
Gitweb:        https://git.kernel.org/tip/ffa0519baaed48ca953bd201e1b17f15dae21b2d
Author:        Thomas Gleixner <tglx@linutronix.de>
AuthorDate:    Mon, 19 May 2025 10:33:30 +02:00
Committer:     Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Thu, 19 Jun 2025 14:28:23 +02:00

timekeeping: Provide ktime_get_ntp_seconds()

ntp_adjtimex() requires access to the actual time keeper per timekeeper
ID. Provide an interface.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Link: https://lore.kernel.org/all/20250519083026.411809421@linutronix.de


---
 kernel/time/timekeeping.c          |  9 +++++++++
 kernel/time/timekeeping_internal.h |  3 +++
 2 files changed, 12 insertions(+)

diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index 19f4af1..7d3693a 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -2627,6 +2627,15 @@ int do_adjtimex(struct __kernel_timex *txc)
 	return ret;
 }
 
+/*
+ * Invoked from NTP with the time keeper lock held, so lockless access is
+ * fine.
+ */
+long ktime_get_ntp_seconds(unsigned int id)
+{
+	return timekeeper_data[id].timekeeper.xtime_sec;
+}
+
 #ifdef CONFIG_NTP_PPS
 /**
  * hardpps() - Accessor function to NTP __hardpps function
diff --git a/kernel/time/timekeeping_internal.h b/kernel/time/timekeeping_internal.h
index 8c90791..973ede6 100644
--- a/kernel/time/timekeeping_internal.h
+++ b/kernel/time/timekeeping_internal.h
@@ -45,4 +45,7 @@ static inline u64 clocksource_delta(u64 now, u64 last, u64 mask, u64 max_delta)
 unsigned long timekeeper_lock_irqsave(void);
 void timekeeper_unlock_irqrestore(unsigned long flags);
 
+/* NTP specific interface to access the current seconds value */
+long ktime_get_ntp_seconds(unsigned int id);
+
 #endif /* _TIMEKEEPING_INTERNAL_H */

^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [tip: timers/ptp] timekeeping: Introduce auxiliary timekeepers
  2025-05-19  8:33 ` [patch V2 12/26] timekeeping: Introduce auxiliary timekeepers Thomas Gleixner
  2025-06-14  2:41   ` John Stultz
@ 2025-06-25 16:15   ` tip-bot2 for Anna-Maria Behnsen
  1 sibling, 0 replies; 57+ messages in thread
From: tip-bot2 for Anna-Maria Behnsen @ 2025-06-25 16:15 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Anna-Maria Behnsen, Thomas Gleixner, John Stultz, x86,
	linux-kernel

The following commit has been merged into the timers/ptp branch of tip:

Commit-ID:     22c62b9a84b8f16ca0277e133a0cd62a259fee7c
Gitweb:        https://git.kernel.org/tip/22c62b9a84b8f16ca0277e133a0cd62a259fee7c
Author:        Anna-Maria Behnsen <anna-maria@linutronix.de>
AuthorDate:    Mon, 19 May 2025 10:33:28 +02:00
Committer:     Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Thu, 19 Jun 2025 14:28:23 +02:00

timekeeping: Introduce auxiliary timekeepers

Provide timekeepers for auxiliary clocks and initialize them during
boot.

Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Acked-by: John Stultz <jstultz@google.com>
Link: https://lore.kernel.org/all/20250519083026.350061049@linutronix.de


---
 kernel/time/timekeeping.c | 22 ++++++++++++++++++++--
 1 file changed, 20 insertions(+), 2 deletions(-)

diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index bf59bac..19f4af1 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -53,7 +53,11 @@ struct tk_data {
 	raw_spinlock_t		lock;
 } ____cacheline_aligned;
 
-static struct tk_data tk_core;
+static struct tk_data timekeeper_data[TIMEKEEPERS_MAX];
+
+/* The core timekeeper */
+#define tk_core		(timekeeper_data[TIMEKEEPER_CORE])
+
 
 /* flag for if timekeeping is suspended */
 int __read_mostly timekeeping_suspended;
@@ -113,6 +117,12 @@ static struct tk_fast tk_fast_raw  ____cacheline_aligned = {
 	.base[1] = FAST_TK_INIT,
 };
 
+#ifdef CONFIG_POSIX_AUX_CLOCKS
+static __init void tk_aux_setup(void);
+#else
+static inline void tk_aux_setup(void) { }
+#endif
+
 unsigned long timekeeper_lock_irqsave(void)
 {
 	unsigned long flags;
@@ -1589,7 +1599,6 @@ void ktime_get_raw_ts64(struct timespec64 *ts)
 }
 EXPORT_SYMBOL(ktime_get_raw_ts64);
 
-
 /**
  * timekeeping_valid_for_hres - Check if timekeeping is suitable for hres
  */
@@ -1701,6 +1710,7 @@ void __init timekeeping_init(void)
 	struct clocksource *clock;
 
 	tkd_basic_setup(&tk_core, TIMEKEEPER_CORE, true);
+	tk_aux_setup();
 
 	read_persistent_wall_and_boot_offset(&wall_time, &boot_offset);
 	if (timespec64_valid_settod(&wall_time) &&
@@ -2630,3 +2640,11 @@ void hardpps(const struct timespec64 *phase_ts, const struct timespec64 *raw_ts)
 }
 EXPORT_SYMBOL(hardpps);
 #endif /* CONFIG_NTP_PPS */
+
+#ifdef CONFIG_POSIX_AUX_CLOCKS
+static __init void tk_aux_setup(void)
+{
+	for (int i = TIMEKEEPER_AUX_FIRST; i <= TIMEKEEPER_AUX_LAST; i++)
+		tkd_basic_setup(&timekeeper_data[i], i, false);
+}
+#endif /* CONFIG_POSIX_AUX_CLOCKS */

^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [tip: timers/ptp] timekeeping: Add clock_valid flag to timekeeper
  2025-05-19  8:33 ` [patch V2 11/26] timekeeping: Add clock_valid flag to timekeeper Thomas Gleixner
  2025-06-13  4:05   ` John Stultz
@ 2025-06-25 16:15   ` tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 57+ messages in thread
From: tip-bot2 for Thomas Gleixner @ 2025-06-25 16:15 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: Thomas Gleixner, John Stultz, x86, linux-kernel

The following commit has been merged into the timers/ptp branch of tip:

Commit-ID:     6168024604236cb2bb1004ea8459c8ece2c4ef5f
Gitweb:        https://git.kernel.org/tip/6168024604236cb2bb1004ea8459c8ece2c4ef5f
Author:        Thomas Gleixner <tglx@linutronix.de>
AuthorDate:    Mon, 19 May 2025 10:33:27 +02:00
Committer:     Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Thu, 19 Jun 2025 14:28:23 +02:00

timekeeping: Add clock_valid flag to timekeeper

In preparation for supporting independent auxiliary timekeepers, add a
clock valid field and set it to true for the system timekeeper.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Acked-by: John Stultz <jstultz@google.com>
Link: https://lore.kernel.org/all/20250519083026.287145536@linutronix.de


---
 include/linux/timekeeper_internal.h | 2 ++
 kernel/time/timekeeping.c           | 5 +++--
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/include/linux/timekeeper_internal.h b/include/linux/timekeeper_internal.h
index 4201ae8..1690eda 100644
--- a/include/linux/timekeeper_internal.h
+++ b/include/linux/timekeeper_internal.h
@@ -73,6 +73,7 @@ struct tk_read_base {
  * @raw_sec:			CLOCK_MONOTONIC_RAW  time in seconds
  * @clock_was_set_seq:		The sequence number of clock was set events
  * @cs_was_changed_seq:		The sequence number of clocksource change events
+ * @clock_valid:		Indicator for valid clock
  * @monotonic_to_boot:		CLOCK_MONOTONIC to CLOCK_BOOTTIME offset
  * @cycle_interval:		Number of clock cycles in one NTP interval
  * @xtime_interval:		Number of clock shifted nano seconds in one NTP
@@ -149,6 +150,7 @@ struct timekeeper {
 	/* Cachline 3 and 4 (timekeeping internal variables): */
 	unsigned int		clock_was_set_seq;
 	u8			cs_was_changed_seq;
+	u8			clock_valid;
 
 	struct timespec64	monotonic_to_boot;
 
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index e3c1a1c..bf59bac 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -1665,11 +1665,12 @@ read_persistent_wall_and_boot_offset(struct timespec64 *wall_time,
 	*boot_offset = ns_to_timespec64(local_clock());
 }
 
-static __init void tkd_basic_setup(struct tk_data *tkd, enum timekeeper_ids tk_id)
+static __init void tkd_basic_setup(struct tk_data *tkd, enum timekeeper_ids tk_id, bool valid)
 {
 	raw_spin_lock_init(&tkd->lock);
 	seqcount_raw_spinlock_init(&tkd->seq, &tkd->lock);
 	tkd->timekeeper.id = tkd->shadow_timekeeper.id = tk_id;
+	tkd->timekeeper.clock_valid = tkd->shadow_timekeeper.clock_valid = valid;
 }
 
 /*
@@ -1699,7 +1700,7 @@ void __init timekeeping_init(void)
 	struct timekeeper *tks = &tk_core.shadow_timekeeper;
 	struct clocksource *clock;
 
-	tkd_basic_setup(&tk_core, TIMEKEEPER_CORE);
+	tkd_basic_setup(&tk_core, TIMEKEEPER_CORE, true);
 
 	read_persistent_wall_and_boot_offset(&wall_time, &boot_offset);
 	if (timespec64_valid_settod(&wall_time) &&

^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [tip: timers/ptp] timekeeping: Prepare timekeeping_update_from_shadow()
  2025-05-19  8:33 ` [patch V2 10/26] timekeeping: Prepare timekeeping_update_from_shadow() Thomas Gleixner
@ 2025-06-25 16:16   ` tip-bot2 for Thomas Gleixner
  0 siblings, 0 replies; 57+ messages in thread
From: tip-bot2 for Thomas Gleixner @ 2025-06-25 16:16 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: Thomas Gleixner, x86, linux-kernel

The following commit has been merged into the timers/ptp branch of tip:

Commit-ID:     8c782acd3f47e21f9b03fd3720172d1f8e4fb796
Gitweb:        https://git.kernel.org/tip/8c782acd3f47e21f9b03fd3720172d1f8e4fb796
Author:        Thomas Gleixner <tglx@linutronix.de>
AuthorDate:    Mon, 19 May 2025 10:33:26 +02:00
Committer:     Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Thu, 19 Jun 2025 14:28:23 +02:00

timekeeping: Prepare timekeeping_update_from_shadow()

Don't invoke the VDSO and paravirt updates when utilized for auxiliary
clocks. This is a temporary workaround until the VDSO and paravirt
interfaces have been worked out.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Link: https://lore.kernel.org/all/20250519083026.223876435@linutronix.de


---
 kernel/time/timekeeping.c | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index 153f760..e3c1a1c 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -683,13 +683,15 @@ static void timekeeping_update_from_shadow(struct tk_data *tkd, unsigned int act
 
 	tk_update_leap_state(tk);
 	tk_update_ktime_data(tk);
+	tk->tkr_mono.base_real = tk->tkr_mono.base + tk->offs_real;
 
-	update_vsyscall(tk);
-	update_pvclock_gtod(tk, action & TK_CLOCK_WAS_SET);
+	if (tk->id == TIMEKEEPER_CORE) {
+		update_vsyscall(tk);
+		update_pvclock_gtod(tk, action & TK_CLOCK_WAS_SET);
 
-	tk->tkr_mono.base_real = tk->tkr_mono.base + tk->offs_real;
-	update_fast_timekeeper(&tk->tkr_mono, &tk_fast_mono);
-	update_fast_timekeeper(&tk->tkr_raw,  &tk_fast_raw);
+		update_fast_timekeeper(&tk->tkr_mono, &tk_fast_mono);
+		update_fast_timekeeper(&tk->tkr_raw,  &tk_fast_raw);
+	}
 
 	if (action & TK_CLOCK_WAS_SET)
 		tk->clock_was_set_seq++;

^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [tip: timers/ptp] timekeeping: Make __timekeeping_advance() reusable
  2025-05-19  8:33 ` [patch V2 09/26] timekeeping: Make __timekeeping_advance() reusable Thomas Gleixner
  2025-06-13  0:23   ` John Stultz
@ 2025-06-25 16:16   ` tip-bot2 for Anna-Maria Behnsen
  1 sibling, 0 replies; 57+ messages in thread
From: tip-bot2 for Anna-Maria Behnsen @ 2025-06-25 16:16 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Anna-Maria Behnsen, Thomas Gleixner, John Stultz, x86,
	linux-kernel

The following commit has been merged into the timers/ptp branch of tip:

Commit-ID:     926ad475169f5b24868438e4bff61ec6a73efd19
Gitweb:        https://git.kernel.org/tip/926ad475169f5b24868438e4bff61ec6a73efd19
Author:        Anna-Maria Behnsen <anna-maria@linutronix.de>
AuthorDate:    Mon, 19 May 2025 10:33:25 +02:00
Committer:     Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Thu, 19 Jun 2025 14:28:23 +02:00

timekeeping: Make __timekeeping_advance() reusable

In __timekeeping_advance() the pointer to struct tk_data is hardcoded by the
use of &tk_core. As long as there is only a single timekeeper (tk_core),
this is not a problem. But when __timekeeping_advance() will be reused for
per auxiliary timekeepers, __timekeeping_advance() needs to be generalized.

Add a pointer to struct tk_data as function argument of
__timekeeping_advance() and adapt all call sites.

Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Acked-by: John Stultz <jstultz@google.com>
Link: https://lore.kernel.org/all/20250519083026.160967312@linutronix.de


---
 kernel/time/timekeeping.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index 99b4749..153f760 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -2196,10 +2196,10 @@ static u64 logarithmic_accumulation(struct timekeeper *tk, u64 offset,
  * timekeeping_advance - Updates the timekeeper to the current time and
  * current NTP tick length
  */
-static bool __timekeeping_advance(enum timekeeping_adv_mode mode)
+static bool __timekeeping_advance(struct tk_data *tkd, enum timekeeping_adv_mode mode)
 {
-	struct timekeeper *tk = &tk_core.shadow_timekeeper;
-	struct timekeeper *real_tk = &tk_core.timekeeper;
+	struct timekeeper *tk = &tkd->shadow_timekeeper;
+	struct timekeeper *real_tk = &tkd->timekeeper;
 	unsigned int clock_set = 0;
 	int shift = 0, maxshift;
 	u64 offset, orig_offset;
@@ -2252,7 +2252,7 @@ static bool __timekeeping_advance(enum timekeeping_adv_mode mode)
 	if (orig_offset != offset)
 		tk_update_coarse_nsecs(tk);
 
-	timekeeping_update_from_shadow(&tk_core, clock_set);
+	timekeeping_update_from_shadow(tkd, clock_set);
 
 	return !!clock_set;
 }
@@ -2260,7 +2260,7 @@ static bool __timekeeping_advance(enum timekeeping_adv_mode mode)
 static bool timekeeping_advance(enum timekeeping_adv_mode mode)
 {
 	guard(raw_spinlock_irqsave)(&tk_core.lock);
-	return __timekeeping_advance(mode);
+	return __timekeeping_advance(&tk_core, mode);
 }
 
 /**
@@ -2598,7 +2598,7 @@ int do_adjtimex(struct __kernel_timex *txc)
 
 		/* Update the multiplier immediately if frequency was set directly */
 		if (txc->modes & (ADJ_FREQUENCY | ADJ_TICK))
-			clock_set |= __timekeeping_advance(TK_ADV_FREQ);
+			clock_set |= __timekeeping_advance(&tk_core, TK_ADV_FREQ);
 	}
 
 	if (txc->modes & ADJ_SETOFFSET)

^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [tip: timers/ptp] ntp: Rename __do_adjtimex() to ntp_adjtimex()
  2025-05-19  8:33 ` [patch V2 08/26] ntp: Rename __do_adjtimex() to ntp_adjtimex() Thomas Gleixner
  2025-06-13  0:20   ` John Stultz
@ 2025-06-25 16:16   ` tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 57+ messages in thread
From: tip-bot2 for Thomas Gleixner @ 2025-06-25 16:16 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: Thomas Gleixner, John Stultz, x86, linux-kernel

The following commit has been merged into the timers/ptp branch of tip:

Commit-ID:     c7ebfbc440151ae4a66a03b0f879cbece45174c8
Gitweb:        https://git.kernel.org/tip/c7ebfbc440151ae4a66a03b0f879cbece45174c8
Author:        Thomas Gleixner <tglx@linutronix.de>
AuthorDate:    Mon, 19 May 2025 10:33:23 +02:00
Committer:     Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Thu, 19 Jun 2025 14:28:23 +02:00

ntp: Rename __do_adjtimex() to ntp_adjtimex()

Clean up the name space. No functional change.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Acked-by: John Stultz <jstultz@google.com>
Link: https://lore.kernel.org/all/20250519083026.095637820@linutronix.de


---
 kernel/time/ntp.c          | 4 ++--
 kernel/time/ntp_internal.h | 4 ++--
 kernel/time/timekeeping.c  | 2 +-
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c
index e28dc53..9aba1bc 100644
--- a/kernel/time/ntp.c
+++ b/kernel/time/ntp.c
@@ -767,8 +767,8 @@ static inline void process_adjtimex_modes(struct ntp_data *ntpdata, const struct
  * adjtimex() mainly allows reading (and writing, if superuser) of
  * kernel time-keeping variables. used by xntpd.
  */
-int __do_adjtimex(unsigned int tkid, struct __kernel_timex *txc, const struct timespec64 *ts,
-		  s32 *time_tai, struct audit_ntp_data *ad)
+int ntp_adjtimex(unsigned int tkid, struct __kernel_timex *txc, const struct timespec64 *ts,
+		 s32 *time_tai, struct audit_ntp_data *ad)
 {
 	struct ntp_data *ntpdata = &tk_ntp_data[tkid];
 	int result;
diff --git a/kernel/time/ntp_internal.h b/kernel/time/ntp_internal.h
index 2d3e966..7084d83 100644
--- a/kernel/time/ntp_internal.h
+++ b/kernel/time/ntp_internal.h
@@ -8,8 +8,8 @@ extern void ntp_clear(unsigned int tkid);
 extern u64 ntp_tick_length(unsigned int tkid);
 extern ktime_t ntp_get_next_leap(unsigned int tkid);
 extern int second_overflow(unsigned int tkid, time64_t secs);
-extern int __do_adjtimex(unsigned int tkid, struct __kernel_timex *txc, const struct timespec64 *ts,
-			 s32 *time_tai, struct audit_ntp_data *ad);
+extern int ntp_adjtimex(unsigned int tkid, struct __kernel_timex *txc, const struct timespec64 *ts,
+			s32 *time_tai, struct audit_ntp_data *ad);
 extern void __hardpps(const struct timespec64 *phase_ts, const struct timespec64 *raw_ts);
 
 #if defined(CONFIG_GENERIC_CMOS_UPDATE) || defined(CONFIG_RTC_SYSTOHC)
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index e1b8e26..99b4749 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -2586,7 +2586,7 @@ int do_adjtimex(struct __kernel_timex *txc)
 		}
 
 		orig_tai = tai = tks->tai_offset;
-		ret = __do_adjtimex(tks->id, txc, &ts, &tai, &ad);
+		ret = ntp_adjtimex(tks->id, txc, &ts, &tai, &ad);
 
 		if (tai != orig_tai) {
 			__timekeeping_set_tai_offset(tks, tai);

^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [tip: timers/ptp] ntp: Add timekeeper ID arguments to public functions
  2025-05-19  8:33 ` [patch V2 07/26] ntp: Add timekeeper ID arguments to public functions Thomas Gleixner
  2025-06-13  0:20   ` John Stultz
@ 2025-06-25 16:16   ` tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 57+ messages in thread
From: tip-bot2 for Thomas Gleixner @ 2025-06-25 16:16 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: Thomas Gleixner, John Stultz, x86, linux-kernel

The following commit has been merged into the timers/ptp branch of tip:

Commit-ID:     5ffa25f573cf524ff53660c5ff7a158ee10f23c7
Gitweb:        https://git.kernel.org/tip/5ffa25f573cf524ff53660c5ff7a158ee10f23c7
Author:        Thomas Gleixner <tglx@linutronix.de>
AuthorDate:    Mon, 19 May 2025 10:33:22 +02:00
Committer:     Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Thu, 19 Jun 2025 14:28:23 +02:00

ntp: Add timekeeper ID arguments to public functions

In preparation for supporting auxiliary POSIX clocks, add a timekeeper ID
to the relevant functions.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Acked-by: John Stultz <jstultz@google.com>
Link: https://lore.kernel.org/all/20250519083026.032425931@linutronix.de


---
 kernel/time/ntp.c          | 33 +++++++++++++++++++--------------
 kernel/time/ntp_internal.h | 11 +++++------
 kernel/time/timekeeping.c  | 12 ++++++------
 3 files changed, 30 insertions(+), 26 deletions(-)

diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c
index 5b5a0f7..e28dc53 100644
--- a/kernel/time/ntp.c
+++ b/kernel/time/ntp.c
@@ -351,33 +351,38 @@ static void __ntp_clear(struct ntp_data *ntpdata)
 
 /**
  * ntp_clear - Clears the NTP state variables
+ * @tkid:	Timekeeper ID to be able to select proper ntp data array member
  */
-void ntp_clear(void)
+void ntp_clear(unsigned int tkid)
 {
-	__ntp_clear(&tk_ntp_data[TIMEKEEPER_CORE]);
+	__ntp_clear(&tk_ntp_data[tkid]);
 }
 
 
-u64 ntp_tick_length(void)
+u64 ntp_tick_length(unsigned int tkid)
 {
-	return tk_ntp_data[TIMEKEEPER_CORE].tick_length;
+	return tk_ntp_data[tkid].tick_length;
 }
 
 /**
  * ntp_get_next_leap - Returns the next leapsecond in CLOCK_REALTIME ktime_t
+ * @tkid:	Timekeeper ID
  *
- * Provides the time of the next leapsecond against CLOCK_REALTIME in
- * a ktime_t format. Returns KTIME_MAX if no leapsecond is pending.
+ * Returns: For @tkid == TIMEKEEPER_CORE this provides the time of the next
+ *	    leap second against CLOCK_REALTIME in a ktime_t format if a
+ *	    leap second is pending. KTIME_MAX otherwise.
  */
-ktime_t ntp_get_next_leap(void)
+ktime_t ntp_get_next_leap(unsigned int tkid)
 {
 	struct ntp_data *ntpdata = &tk_ntp_data[TIMEKEEPER_CORE];
-	ktime_t ret;
+
+	if (tkid != TIMEKEEPER_CORE)
+		return KTIME_MAX;
 
 	if ((ntpdata->time_state == TIME_INS) && (ntpdata->time_status & STA_INS))
 		return ktime_set(ntpdata->ntp_next_leap_sec, 0);
-	ret = KTIME_MAX;
-	return ret;
+
+	return KTIME_MAX;
 }
 
 /*
@@ -390,9 +395,9 @@ ktime_t ntp_get_next_leap(void)
  *
  * Also handles leap second processing, and returns leap offset
  */
-int second_overflow(time64_t secs)
+int second_overflow(unsigned int tkid, time64_t secs)
 {
-	struct ntp_data *ntpdata = &tk_ntp_data[TIMEKEEPER_CORE];
+	struct ntp_data *ntpdata = &tk_ntp_data[tkid];
 	s64 delta;
 	int leap = 0;
 	s32 rem;
@@ -762,10 +767,10 @@ static inline void process_adjtimex_modes(struct ntp_data *ntpdata, const struct
  * adjtimex() mainly allows reading (and writing, if superuser) of
  * kernel time-keeping variables. used by xntpd.
  */
-int __do_adjtimex(struct __kernel_timex *txc, const struct timespec64 *ts,
+int __do_adjtimex(unsigned int tkid, struct __kernel_timex *txc, const struct timespec64 *ts,
 		  s32 *time_tai, struct audit_ntp_data *ad)
 {
-	struct ntp_data *ntpdata = &tk_ntp_data[TIMEKEEPER_CORE];
+	struct ntp_data *ntpdata = &tk_ntp_data[tkid];
 	int result;
 
 	if (txc->modes & ADJ_ADJTIME) {
diff --git a/kernel/time/ntp_internal.h b/kernel/time/ntp_internal.h
index 5a633dc..2d3e966 100644
--- a/kernel/time/ntp_internal.h
+++ b/kernel/time/ntp_internal.h
@@ -3,13 +3,12 @@
 #define _LINUX_NTP_INTERNAL_H
 
 extern void ntp_init(void);
-extern void ntp_clear(void);
+extern void ntp_clear(unsigned int tkid);
 /* Returns how long ticks are at present, in ns / 2^NTP_SCALE_SHIFT. */
-extern u64 ntp_tick_length(void);
-extern ktime_t ntp_get_next_leap(void);
-extern int second_overflow(time64_t secs);
-extern int __do_adjtimex(struct __kernel_timex *txc,
-			 const struct timespec64 *ts,
+extern u64 ntp_tick_length(unsigned int tkid);
+extern ktime_t ntp_get_next_leap(unsigned int tkid);
+extern int second_overflow(unsigned int tkid, time64_t secs);
+extern int __do_adjtimex(unsigned int tkid, struct __kernel_timex *txc, const struct timespec64 *ts,
 			 s32 *time_tai, struct audit_ntp_data *ad);
 extern void __hardpps(const struct timespec64 *phase_ts, const struct timespec64 *raw_ts);
 
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index f4692fc..e1b8e26 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -601,7 +601,7 @@ EXPORT_SYMBOL_GPL(pvclock_gtod_unregister_notifier);
  */
 static inline void tk_update_leap_state(struct timekeeper *tk)
 {
-	tk->next_leap_ktime = ntp_get_next_leap();
+	tk->next_leap_ktime = ntp_get_next_leap(tk->id);
 	if (tk->next_leap_ktime != KTIME_MAX)
 		/* Convert to monotonic time */
 		tk->next_leap_ktime = ktime_sub(tk->next_leap_ktime, tk->offs_real);
@@ -678,7 +678,7 @@ static void timekeeping_update_from_shadow(struct tk_data *tkd, unsigned int act
 
 	if (action & TK_CLEAR_NTP) {
 		tk->ntp_error = 0;
-		ntp_clear();
+		ntp_clear(tk->id);
 	}
 
 	tk_update_leap_state(tk);
@@ -2049,7 +2049,7 @@ static __always_inline void timekeeping_apply_adjustment(struct timekeeper *tk,
  */
 static void timekeeping_adjust(struct timekeeper *tk, s64 offset)
 {
-	u64 ntp_tl = ntp_tick_length();
+	u64 ntp_tl = ntp_tick_length(tk->id);
 	u32 mult;
 
 	/*
@@ -2130,7 +2130,7 @@ static inline unsigned int accumulate_nsecs_to_secs(struct timekeeper *tk)
 		}
 
 		/* Figure out if its a leap sec and apply if needed */
-		leap = second_overflow(tk->xtime_sec);
+		leap = second_overflow(tk->id, tk->xtime_sec);
 		if (unlikely(leap)) {
 			struct timespec64 ts;
 
@@ -2227,7 +2227,7 @@ static bool __timekeeping_advance(enum timekeeping_adv_mode mode)
 	shift = ilog2(offset) - ilog2(tk->cycle_interval);
 	shift = max(0, shift);
 	/* Bound shift to one less than what overflows tick_length */
-	maxshift = (64 - (ilog2(ntp_tick_length())+1)) - 1;
+	maxshift = (64 - (ilog2(ntp_tick_length(tk->id)) + 1)) - 1;
 	shift = min(shift, maxshift);
 	while (offset >= tk->cycle_interval) {
 		offset = logarithmic_accumulation(tk, offset, shift, &clock_set);
@@ -2586,7 +2586,7 @@ int do_adjtimex(struct __kernel_timex *txc)
 		}
 
 		orig_tai = tai = tks->tai_offset;
-		ret = __do_adjtimex(txc, &ts, &tai, &ad);
+		ret = __do_adjtimex(tks->id, txc, &ts, &tai, &ad);
 
 		if (tai != orig_tai) {
 			__timekeeping_set_tai_offset(tks, tai);

^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [tip: timers/ptp] ntp: Add support for auxiliary timekeepers
  2025-05-19  8:33 ` [patch V2 06/26] ntp: Add support for auxiliary timekeepers Thomas Gleixner
  2025-06-13  0:14   ` John Stultz
  2025-06-13  6:32   ` Thomas Weißschuh
@ 2025-06-25 16:16   ` tip-bot2 for Thomas Gleixner
  2 siblings, 0 replies; 57+ messages in thread
From: tip-bot2 for Thomas Gleixner @ 2025-06-25 16:16 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: Thomas Gleixner, John Stultz, x86, linux-kernel

The following commit has been merged into the timers/ptp branch of tip:

Commit-ID:     8515714b0f88a698a4c26f0f0ce7d43ad14dce16
Gitweb:        https://git.kernel.org/tip/8515714b0f88a698a4c26f0f0ce7d43ad14dce16
Author:        Thomas Gleixner <tglx@linutronix.de>
AuthorDate:    Mon, 19 May 2025 10:33:21 +02:00
Committer:     Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Thu, 19 Jun 2025 14:28:22 +02:00

ntp: Add support for auxiliary timekeepers

If auxiliary clocks are enabled, provide an array of NTP data so that the
auxiliary timekeepers can be steered independently of the core timekeeper.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Acked-by: John Stultz <jstultz@google.com>
Link: https://lore.kernel.org/all/20250519083025.969000914@linutronix.de

---
 kernel/time/ntp.c | 41 ++++++++++++++++++++++-------------------
 1 file changed, 22 insertions(+), 19 deletions(-)

diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c
index b837d3d..5b5a0f7 100644
--- a/kernel/time/ntp.c
+++ b/kernel/time/ntp.c
@@ -18,6 +18,7 @@
 #include <linux/module.h>
 #include <linux/rtc.h>
 #include <linux/audit.h>
+#include <linux/timekeeper_internal.h>
 
 #include "ntp_internal.h"
 #include "timekeeping_internal.h"
@@ -86,14 +87,16 @@ struct ntp_data {
 #endif
 };
 
-static struct ntp_data tk_ntp_data = {
-	.tick_usec		= USER_TICK_USEC,
-	.time_state		= TIME_OK,
-	.time_status		= STA_UNSYNC,
-	.time_constant		= 2,
-	.time_maxerror		= NTP_PHASE_LIMIT,
-	.time_esterror		= NTP_PHASE_LIMIT,
-	.ntp_next_leap_sec	= TIME64_MAX,
+static struct ntp_data tk_ntp_data[TIMEKEEPERS_MAX] = {
+	[ 0 ... TIMEKEEPERS_MAX - 1 ] = {
+		.tick_usec		= USER_TICK_USEC,
+		.time_state		= TIME_OK,
+		.time_status		= STA_UNSYNC,
+		.time_constant		= 2,
+		.time_maxerror		= NTP_PHASE_LIMIT,
+		.time_esterror		= NTP_PHASE_LIMIT,
+		.ntp_next_leap_sec	= TIME64_MAX,
+	},
 };
 
 #define SECS_PER_DAY		86400
@@ -351,13 +354,13 @@ static void __ntp_clear(struct ntp_data *ntpdata)
  */
 void ntp_clear(void)
 {
-	__ntp_clear(&tk_ntp_data);
+	__ntp_clear(&tk_ntp_data[TIMEKEEPER_CORE]);
 }
 
 
 u64 ntp_tick_length(void)
 {
-	return tk_ntp_data.tick_length;
+	return tk_ntp_data[TIMEKEEPER_CORE].tick_length;
 }
 
 /**
@@ -368,7 +371,7 @@ u64 ntp_tick_length(void)
  */
 ktime_t ntp_get_next_leap(void)
 {
-	struct ntp_data *ntpdata = &tk_ntp_data;
+	struct ntp_data *ntpdata = &tk_ntp_data[TIMEKEEPER_CORE];
 	ktime_t ret;
 
 	if ((ntpdata->time_state == TIME_INS) && (ntpdata->time_status & STA_INS))
@@ -389,7 +392,7 @@ ktime_t ntp_get_next_leap(void)
  */
 int second_overflow(time64_t secs)
 {
-	struct ntp_data *ntpdata = &tk_ntp_data;
+	struct ntp_data *ntpdata = &tk_ntp_data[TIMEKEEPER_CORE];
 	s64 delta;
 	int leap = 0;
 	s32 rem;
@@ -605,7 +608,7 @@ static inline int update_rtc(struct timespec64 *to_set, unsigned long *offset_ns
  */
 static inline bool ntp_synced(void)
 {
-	return !(tk_ntp_data.time_status & STA_UNSYNC);
+	return !(tk_ntp_data[TIMEKEEPER_CORE].time_status & STA_UNSYNC);
 }
 
 /*
@@ -762,7 +765,7 @@ static inline void process_adjtimex_modes(struct ntp_data *ntpdata, const struct
 int __do_adjtimex(struct __kernel_timex *txc, const struct timespec64 *ts,
 		  s32 *time_tai, struct audit_ntp_data *ad)
 {
-	struct ntp_data *ntpdata = &tk_ntp_data;
+	struct ntp_data *ntpdata = &tk_ntp_data[TIMEKEEPER_CORE];
 	int result;
 
 	if (txc->modes & ADJ_ADJTIME) {
@@ -1031,8 +1034,8 @@ static void hardpps_update_phase(struct ntp_data *ntpdata, long error)
  */
 void __hardpps(const struct timespec64 *phase_ts, const struct timespec64 *raw_ts)
 {
+	struct ntp_data *ntpdata = &tk_ntp_data[TIMEKEEPER_CORE];
 	struct pps_normtime pts_norm, freq_norm;
-	struct ntp_data *ntpdata = &tk_ntp_data;
 
 	pts_norm = pps_normalize_ts(*phase_ts);
 
@@ -1083,18 +1086,18 @@ void __hardpps(const struct timespec64 *phase_ts, const struct timespec64 *raw_t
 
 static int __init ntp_tick_adj_setup(char *str)
 {
-	int rc = kstrtos64(str, 0, &tk_ntp_data.ntp_tick_adj);
+	int rc = kstrtos64(str, 0, &tk_ntp_data[TIMEKEEPER_CORE].ntp_tick_adj);
 	if (rc)
 		return rc;
 
-	tk_ntp_data.ntp_tick_adj <<= NTP_SCALE_SHIFT;
+	tk_ntp_data[TIMEKEEPER_CORE].ntp_tick_adj <<= NTP_SCALE_SHIFT;
 	return 1;
 }
-
 __setup("ntp_tick_adj=", ntp_tick_adj_setup);
 
 void __init ntp_init(void)
 {
-	ntp_clear();
+	for (int id = 0; id < TIMEKEEPERS_MAX; id++)
+		__ntp_clear(tk_ntp_data + id);
 	ntp_init_cmos_sync();
 }

^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [tip: timers/ptp] time: Introduce auxiliary POSIX clocks
  2025-05-19  8:33 ` [patch V2 05/26] time: Introduce auxiliary POSIX clocks Thomas Gleixner
  2025-06-13  0:06   ` John Stultz
@ 2025-06-25 16:16   ` tip-bot2 for Anna-Maria Behnsen
  1 sibling, 0 replies; 57+ messages in thread
From: tip-bot2 for Anna-Maria Behnsen @ 2025-06-25 16:16 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Anna-Maria Behnsen, Thomas Gleixner, John Stultz, x86,
	linux-kernel

The following commit has been merged into the timers/ptp branch of tip:

Commit-ID:     9094c72c3d81bf2416b7c79d12c8494ab8fbac20
Gitweb:        https://git.kernel.org/tip/9094c72c3d81bf2416b7c79d12c8494ab8fbac20
Author:        Anna-Maria Behnsen <anna-maria@linutronix.de>
AuthorDate:    Mon, 19 May 2025 10:33:20 +02:00
Committer:     Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Thu, 19 Jun 2025 14:28:22 +02:00

time: Introduce auxiliary POSIX clocks

To support auxiliary timekeeping and the related user space interfaces,
it's required to define a clock ID range for them.

Reserve 8 auxiliary clock IDs after the regular timekeeping clock ID space.

This is the maximum number of auxiliary clocks the kernel can support. The actual
number of supported clocks depends obviously on the presence of related devices
and might be constraint by the available VDSO space.

Add the corresponding timekeeper IDs as well.

Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Acked-by: John Stultz <jstultz@google.com>
Link: https://lore.kernel.org/all/20250519083025.905800695@linutronix.de


---
 include/linux/timekeeper_internal.h | 10 ++++++++--
 include/uapi/linux/time.h           | 11 +++++++++++
 kernel/time/Kconfig                 | 15 +++++++++++++--
 3 files changed, 32 insertions(+), 4 deletions(-)

diff --git a/include/linux/timekeeper_internal.h b/include/linux/timekeeper_internal.h
index bfcecad..4201ae8 100644
--- a/include/linux/timekeeper_internal.h
+++ b/include/linux/timekeeper_internal.h
@@ -13,11 +13,17 @@
 
 /**
  * timekeeper_ids - IDs for various time keepers in the kernel
- * @TIMEKEEPER_CORE:	The central core timekeeper managing system time
- * @TIMEKEEPERS_MAX:	The maximum number of timekeepers managed
+ * @TIMEKEEPER_CORE:		The central core timekeeper managing system time
+ * @TIMEKEEPER_AUX_FIRST:	The first AUX timekeeper
+ * @TIMEKEEPER_AUX_LAST:	The last AUX timekeeper
+ * @TIMEKEEPERS_MAX:		The maximum number of timekeepers managed
  */
 enum timekeeper_ids {
 	TIMEKEEPER_CORE,
+#ifdef CONFIG_POSIX_AUX_CLOCKS
+	TIMEKEEPER_AUX_FIRST,
+	TIMEKEEPER_AUX_LAST = TIMEKEEPER_AUX_FIRST + MAX_AUX_CLOCKS - 1,
+#endif
 	TIMEKEEPERS_MAX,
 };
 
diff --git a/include/uapi/linux/time.h b/include/uapi/linux/time.h
index 4f4b6e4..16ca1ac 100644
--- a/include/uapi/linux/time.h
+++ b/include/uapi/linux/time.h
@@ -64,6 +64,17 @@ struct timezone {
 #define CLOCK_TAI			11
 
 #define MAX_CLOCKS			16
+
+/*
+ * AUX clock support. AUXiliary clocks are dynamically configured by
+ * enabling a clock ID. These clock can be steered independently of the
+ * core timekeeper. The kernel can support up to 8 auxiliary clocks, but
+ * the actual limit depends on eventual architecture constraints vs. VDSO.
+ */
+#define CLOCK_AUX			MAX_CLOCKS
+#define MAX_AUX_CLOCKS			8
+#define CLOCK_AUX_LAST			(CLOCK_AUX + MAX_AUX_CLOCKS - 1)
+
 #define CLOCKS_MASK			(CLOCK_REALTIME | CLOCK_MONOTONIC)
 #define CLOCKS_MONO			CLOCK_MONOTONIC
 
diff --git a/kernel/time/Kconfig b/kernel/time/Kconfig
index b0b97a6..7c6a52f 100644
--- a/kernel/time/Kconfig
+++ b/kernel/time/Kconfig
@@ -82,9 +82,9 @@ config CONTEXT_TRACKING_IDLE
 	help
 	  Tracks idle state on behalf of RCU.
 
-if GENERIC_CLOCKEVENTS
 menu "Timers subsystem"
 
+if GENERIC_CLOCKEVENTS
 # Core internal switch. Selected by NO_HZ_COMMON / HIGH_RES_TIMERS. This is
 # only related to the tick functionality. Oneshot clockevent devices
 # are supported independent of this.
@@ -208,6 +208,17 @@ config CLOCKSOURCE_WATCHDOG_MAX_SKEW_US
 	  interval and NTP's maximum frequency drift of 500 parts
 	  per million.	If the clocksource is good enough for NTP,
 	  it is good enough for the clocksource watchdog!
+endif
+
+config POSIX_AUX_CLOCKS
+	bool "Enable auxiliary POSIX clocks"
+	depends on POSIX_TIMERS
+	help
+	  Auxiliary POSIX clocks are clocks which can be steered
+	  independently of the core timekeeper, which controls the
+	  MONOTONIC, REALTIME, BOOTTIME and TAI clocks.  They are useful to
+	  provide e.g. lockless time accessors to independent PTP clocks
+	  and other clock domains, which are not correlated to the TAI/NTP
+	  notion of time.
 
 endmenu
-endif

^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [tip: timers/ptp] timekeeping: Introduce timekeeper ID
  2025-05-19  8:33 ` [patch V2 04/26] timekeeping: Introduce timekeeper ID Thomas Gleixner
  2025-06-13  0:03   ` John Stultz
@ 2025-06-25 16:16   ` tip-bot2 for Anna-Maria Behnsen
  1 sibling, 0 replies; 57+ messages in thread
From: tip-bot2 for Anna-Maria Behnsen @ 2025-06-25 16:16 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Anna-Maria Behnsen, Thomas Gleixner, John Stultz, x86,
	linux-kernel

The following commit has been merged into the timers/ptp branch of tip:

Commit-ID:     f12b45862c4dcb9c2937b83ed730e473b9a76cbf
Gitweb:        https://git.kernel.org/tip/f12b45862c4dcb9c2937b83ed730e473b9a76cbf
Author:        Anna-Maria Behnsen <anna-maria@linutronix.de>
AuthorDate:    Mon, 19 May 2025 10:33:19 +02:00
Committer:     Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Thu, 19 Jun 2025 14:28:22 +02:00

timekeeping: Introduce timekeeper ID

As long as there is only a single timekeeper, there is no need to clarify
which timekeeper is used. But with the upcoming reusage of the timekeeper
infrastructure for auxiliary clock timekeepers, an ID is required to
differentiate.

Introduce an enum for timekeeper IDs, introduce a field in struct tk_data
to store this timekeeper id and add also initialization. The id struct
field is added at the end of the second cachline, as there is a 4 byte hole
anyway.

Signed-off-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Acked-by: John Stultz <jstultz@google.com>
Link: https://lore.kernel.org/all/20250519083025.842476378@linutronix.de


---
 include/linux/timekeeper_internal.h | 14 +++++++++++++-
 kernel/time/timekeeping.c           |  5 +++--
 2 files changed, 16 insertions(+), 3 deletions(-)

diff --git a/include/linux/timekeeper_internal.h b/include/linux/timekeeper_internal.h
index 785048a..bfcecad 100644
--- a/include/linux/timekeeper_internal.h
+++ b/include/linux/timekeeper_internal.h
@@ -12,6 +12,16 @@
 #include <linux/time.h>
 
 /**
+ * timekeeper_ids - IDs for various time keepers in the kernel
+ * @TIMEKEEPER_CORE:	The central core timekeeper managing system time
+ * @TIMEKEEPERS_MAX:	The maximum number of timekeepers managed
+ */
+enum timekeeper_ids {
+	TIMEKEEPER_CORE,
+	TIMEKEEPERS_MAX,
+};
+
+/**
  * struct tk_read_base - base structure for timekeeping readout
  * @clock:	Current clocksource used for timekeeping.
  * @mask:	Bitmask for two's complement subtraction of non 64bit clocks
@@ -52,6 +62,7 @@ struct tk_read_base {
  * @offs_boot:			Offset clock monotonic -> clock boottime
  * @offs_tai:			Offset clock monotonic -> clock tai
  * @coarse_nsec:		The nanoseconds part for coarse time getters
+ * @id:				The timekeeper ID
  * @tkr_raw:			The readout base structure for CLOCK_MONOTONIC_RAW
  * @raw_sec:			CLOCK_MONOTONIC_RAW  time in seconds
  * @clock_was_set_seq:		The sequence number of clock was set events
@@ -101,7 +112,7 @@ struct tk_read_base {
  * which results in the following cacheline layout:
  *
  * 0:	seqcount, tkr_mono
- * 1:	xtime_sec ... coarse_nsec
+ * 1:	xtime_sec ... id
  * 2:	tkr_raw, raw_sec
  * 3,4: Internal variables
  *
@@ -123,6 +134,7 @@ struct timekeeper {
 	ktime_t			offs_boot;
 	ktime_t			offs_tai;
 	u32			coarse_nsec;
+	enum timekeeper_ids	id;
 
 	/* Cacheline 2: */
 	struct tk_read_base	tkr_raw;
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index fb1da87..f4692fc 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -1663,10 +1663,11 @@ read_persistent_wall_and_boot_offset(struct timespec64 *wall_time,
 	*boot_offset = ns_to_timespec64(local_clock());
 }
 
-static __init void tkd_basic_setup(struct tk_data *tkd)
+static __init void tkd_basic_setup(struct tk_data *tkd, enum timekeeper_ids tk_id)
 {
 	raw_spin_lock_init(&tkd->lock);
 	seqcount_raw_spinlock_init(&tkd->seq, &tkd->lock);
+	tkd->timekeeper.id = tkd->shadow_timekeeper.id = tk_id;
 }
 
 /*
@@ -1696,7 +1697,7 @@ void __init timekeeping_init(void)
 	struct timekeeper *tks = &tk_core.shadow_timekeeper;
 	struct clocksource *clock;
 
-	tkd_basic_setup(&tk_core);
+	tkd_basic_setup(&tk_core, TIMEKEEPER_CORE);
 
 	read_persistent_wall_and_boot_offset(&wall_time, &boot_offset);
 	if (timespec64_valid_settod(&wall_time) &&

^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [tip: timers/ptp] timekeeping: Avoid double notification in do_adjtimex()
  2025-05-19  8:33 ` [patch V2 03/26] timekeeping: Avoid double notification in do_adjtimex() Thomas Gleixner
@ 2025-06-25 16:16   ` tip-bot2 for Thomas Gleixner
  0 siblings, 0 replies; 57+ messages in thread
From: tip-bot2 for Thomas Gleixner @ 2025-06-25 16:16 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: Thomas Gleixner, x86, linux-kernel

The following commit has been merged into the timers/ptp branch of tip:

Commit-ID:     7e55b6ba1fe6987638160e5f8216288f38043759
Gitweb:        https://git.kernel.org/tip/7e55b6ba1fe6987638160e5f8216288f38043759
Author:        Thomas Gleixner <tglx@linutronix.de>
AuthorDate:    Mon, 19 May 2025 10:33:17 +02:00
Committer:     Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Thu, 19 Jun 2025 14:28:22 +02:00

timekeeping: Avoid double notification in do_adjtimex()

Consolidate do_adjtimex() so that it does not notify about clock changes
twice.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Link: https://lore.kernel.org/all/20250519083025.779267274@linutronix.de


---
 kernel/time/timekeeping.c | 98 +++++++++++++++++++++-----------------
 1 file changed, 56 insertions(+), 42 deletions(-)

diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index d88d19f..fb1da87 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -1418,40 +1418,49 @@ int do_settimeofday64(const struct timespec64 *ts)
 EXPORT_SYMBOL(do_settimeofday64);
 
 /**
- * timekeeping_inject_offset - Adds or subtracts from the current time.
+ * __timekeeping_inject_offset - Adds or subtracts from the current time.
  * @ts:		Pointer to the timespec variable containing the offset
  *
  * Adds or subtracts an offset value from the current time.
  */
-static int timekeeping_inject_offset(const struct timespec64 *ts)
+static int __timekeeping_inject_offset(const struct timespec64 *ts)
 {
+	struct timekeeper *tks = &tk_core.shadow_timekeeper;
+	struct timespec64 tmp;
+
 	if (ts->tv_nsec < 0 || ts->tv_nsec >= NSEC_PER_SEC)
 		return -EINVAL;
 
-	scoped_guard (raw_spinlock_irqsave, &tk_core.lock) {
-		struct timekeeper *tks = &tk_core.shadow_timekeeper;
-		struct timespec64 tmp;
 
-		timekeeping_forward_now(tks);
-
-		/* Make sure the proposed value is valid */
-		tmp = timespec64_add(tk_xtime(tks), *ts);
-		if (timespec64_compare(&tks->wall_to_monotonic, ts) > 0 ||
-		    !timespec64_valid_settod(&tmp)) {
-			timekeeping_restore_shadow(&tk_core);
-			return -EINVAL;
-		}
+	timekeeping_forward_now(tks);
 
-		tk_xtime_add(tks, ts);
-		tk_set_wall_to_mono(tks, timespec64_sub(tks->wall_to_monotonic, *ts));
-		timekeeping_update_from_shadow(&tk_core, TK_UPDATE_ALL);
+	/* Make sure the proposed value is valid */
+	tmp = timespec64_add(tk_xtime(tks), *ts);
+	if (timespec64_compare(&tks->wall_to_monotonic, ts) > 0 ||
+	    !timespec64_valid_settod(&tmp)) {
+		timekeeping_restore_shadow(&tk_core);
+		return -EINVAL;
 	}
 
-	/* Signal hrtimers about time change */
-	clock_was_set(CLOCK_SET_WALL);
+	tk_xtime_add(tks, ts);
+	tk_set_wall_to_mono(tks, timespec64_sub(tks->wall_to_monotonic, *ts));
+	timekeeping_update_from_shadow(&tk_core, TK_UPDATE_ALL);
 	return 0;
 }
 
+static int timekeeping_inject_offset(const struct timespec64 *ts)
+{
+	int ret;
+
+	scoped_guard (raw_spinlock_irqsave, &tk_core.lock)
+		ret = __timekeeping_inject_offset(ts);
+
+	/* Signal hrtimers about time change */
+	if (!ret)
+		clock_was_set(CLOCK_SET_WALL);
+	return ret;
+}
+
 /*
  * Indicates if there is an offset between the system clock and the hardware
  * clock/persistent clock/rtc.
@@ -2186,7 +2195,7 @@ static u64 logarithmic_accumulation(struct timekeeper *tk, u64 offset,
  * timekeeping_advance - Updates the timekeeper to the current time and
  * current NTP tick length
  */
-static bool timekeeping_advance(enum timekeeping_adv_mode mode)
+static bool __timekeeping_advance(enum timekeeping_adv_mode mode)
 {
 	struct timekeeper *tk = &tk_core.shadow_timekeeper;
 	struct timekeeper *real_tk = &tk_core.timekeeper;
@@ -2194,8 +2203,6 @@ static bool timekeeping_advance(enum timekeeping_adv_mode mode)
 	int shift = 0, maxshift;
 	u64 offset, orig_offset;
 
-	guard(raw_spinlock_irqsave)(&tk_core.lock);
-
 	/* Make sure we're fully resumed: */
 	if (unlikely(timekeeping_suspended))
 		return false;
@@ -2249,6 +2256,12 @@ static bool timekeeping_advance(enum timekeeping_adv_mode mode)
 	return !!clock_set;
 }
 
+static bool timekeeping_advance(enum timekeeping_adv_mode mode)
+{
+	guard(raw_spinlock_irqsave)(&tk_core.lock);
+	return __timekeeping_advance(mode);
+}
+
 /**
  * update_wall_time - Uses the current clocksource to increment the wall time
  *
@@ -2537,10 +2550,10 @@ EXPORT_SYMBOL_GPL(random_get_entropy_fallback);
  */
 int do_adjtimex(struct __kernel_timex *txc)
 {
+	struct timespec64 delta, ts;
 	struct audit_ntp_data ad;
 	bool offset_set = false;
 	bool clock_set = false;
-	struct timespec64 ts;
 	int ret;
 
 	/* Validate the data before disabling interrupts */
@@ -2549,21 +2562,6 @@ int do_adjtimex(struct __kernel_timex *txc)
 		return ret;
 	add_device_randomness(txc, sizeof(*txc));
 
-	if (txc->modes & ADJ_SETOFFSET) {
-		struct timespec64 delta;
-
-		delta.tv_sec  = txc->time.tv_sec;
-		delta.tv_nsec = txc->time.tv_usec;
-		if (!(txc->modes & ADJ_NANO))
-			delta.tv_nsec *= 1000;
-		ret = timekeeping_inject_offset(&delta);
-		if (ret)
-			return ret;
-
-		offset_set = delta.tv_sec != 0;
-		audit_tk_injoffset(delta);
-	}
-
 	audit_ntp_init(&ad);
 
 	ktime_get_real_ts64(&ts);
@@ -2573,6 +2571,19 @@ int do_adjtimex(struct __kernel_timex *txc)
 		struct timekeeper *tks = &tk_core.shadow_timekeeper;
 		s32 orig_tai, tai;
 
+		if (txc->modes & ADJ_SETOFFSET) {
+			delta.tv_sec  = txc->time.tv_sec;
+			delta.tv_nsec = txc->time.tv_usec;
+			if (!(txc->modes & ADJ_NANO))
+				delta.tv_nsec *= 1000;
+			ret = __timekeeping_inject_offset(&delta);
+			if (ret)
+				return ret;
+
+			offset_set = delta.tv_sec != 0;
+			clock_set = true;
+		}
+
 		orig_tai = tai = tks->tai_offset;
 		ret = __do_adjtimex(txc, &ts, &tai, &ad);
 
@@ -2583,13 +2594,16 @@ int do_adjtimex(struct __kernel_timex *txc)
 		} else {
 			tk_update_leap_state_all(&tk_core);
 		}
+
+		/* Update the multiplier immediately if frequency was set directly */
+		if (txc->modes & (ADJ_FREQUENCY | ADJ_TICK))
+			clock_set |= __timekeeping_advance(TK_ADV_FREQ);
 	}
 
-	audit_ntp_log(&ad);
+	if (txc->modes & ADJ_SETOFFSET)
+		audit_tk_injoffset(delta);
 
-	/* Update the multiplier immediately if frequency was set directly */
-	if (txc->modes & (ADJ_FREQUENCY | ADJ_TICK))
-		clock_set |= timekeeping_advance(TK_ADV_FREQ);
+	audit_ntp_log(&ad);
 
 	if (clock_set)
 		clock_was_set(CLOCK_SET_WALL);

^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [tip: timers/ptp] timekeeping: Cleanup kernel doc of __ktime_get_real_seconds()
  2025-05-19  8:33 ` [patch V2 02/26] timekeeping: Cleanup kernel doc of __ktime_get_real_seconds() Thomas Gleixner
  2025-06-12 22:36   ` John Stultz
@ 2025-06-25 16:16   ` tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 57+ messages in thread
From: tip-bot2 for Thomas Gleixner @ 2025-06-25 16:16 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: Thomas Gleixner, John Stultz, x86, linux-kernel

The following commit has been merged into the timers/ptp branch of tip:

Commit-ID:     506a54a0316ee4854b0ed113a8001477f5211d50
Gitweb:        https://git.kernel.org/tip/506a54a0316ee4854b0ed113a8001477f5211d50
Author:        Thomas Gleixner <tglx@linutronix.de>
AuthorDate:    Mon, 19 May 2025 10:33:16 +02:00
Committer:     Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Thu, 19 Jun 2025 14:28:22 +02:00

timekeeping: Cleanup kernel doc of __ktime_get_real_seconds()



Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Acked-by: John Stultz <jstultz@google.com>
Link: https://lore.kernel.org/all/20250519083025.715836017@linutronix.de

---
 kernel/time/timekeeping.c | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index 2ad78fb..d88d19f 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -975,9 +975,14 @@ time64_t ktime_get_real_seconds(void)
 EXPORT_SYMBOL_GPL(ktime_get_real_seconds);
 
 /**
- * __ktime_get_real_seconds - The same as ktime_get_real_seconds
- * but without the sequence counter protect. This internal function
- * is called just when timekeeping lock is already held.
+ * __ktime_get_real_seconds - Unprotected access to CLOCK_REALTIME seconds
+ *
+ * The same as ktime_get_real_seconds() but without the sequence counter
+ * protection. This function is used in restricted contexts like the x86 MCE
+ * handler and in KGDB. It's unprotected on 32-bit vs. concurrent half
+ * completed modification and only to be used for such critical contexts.
+ *
+ * Returns: Racy snapshot of the CLOCK_REALTIME seconds value
  */
 noinstr time64_t __ktime_get_real_seconds(void)
 {

^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [tip: timers/ptp] timekeeping: Remove hardcoded access to tk_core
  2025-05-19  8:33 ` [patch V2 01/26] timekeeping: Remove hardcoded access to tk_core Thomas Gleixner
  2025-06-12 22:34   ` John Stultz
@ 2025-06-25 16:16   ` tip-bot2 for Thomas Gleixner
  1 sibling, 0 replies; 57+ messages in thread
From: tip-bot2 for Thomas Gleixner @ 2025-06-25 16:16 UTC (permalink / raw)
  To: linux-tip-commits; +Cc: Thomas Gleixner, John Stultz, x86, linux-kernel

The following commit has been merged into the timers/ptp branch of tip:

Commit-ID:     990518eb3a71c357ca4ff1ad3e747fb844d8094c
Gitweb:        https://git.kernel.org/tip/990518eb3a71c357ca4ff1ad3e747fb844d8094c
Author:        Thomas Gleixner <tglx@linutronix.de>
AuthorDate:    Mon, 19 May 2025 10:33:15 +02:00
Committer:     Thomas Gleixner <tglx@linutronix.de>
CommitterDate: Thu, 19 Jun 2025 14:28:22 +02:00

timekeeping: Remove hardcoded access to tk_core

This was overlooked in the initial conversion. Use the provided pointer to
access the shadow timekeeper.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Acked-by: John Stultz <jstultz@google.com>
Link: https://lore.kernel.org/all/20250519083025.652611452@linutronix.de


---
 kernel/time/timekeeping.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index a009c91..2ad78fb 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -663,7 +663,7 @@ static void timekeeping_restore_shadow(struct tk_data *tkd)
 
 static void timekeeping_update_from_shadow(struct tk_data *tkd, unsigned int action)
 {
-	struct timekeeper *tk = &tk_core.shadow_timekeeper;
+	struct timekeeper *tk = &tkd->shadow_timekeeper;
 
 	lockdep_assert_held(&tkd->lock);
 

^ permalink raw reply related	[flat|nested] 57+ messages in thread

end of thread, other threads:[~2025-06-25 16:16 UTC | newest]

Thread overview: 57+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-05-19  8:33 [patch V2 00/26] timekeeping: Provide support for auxiliary timekeepers Thomas Gleixner
2025-05-19  8:33 ` [patch V2 01/26] timekeeping: Remove hardcoded access to tk_core Thomas Gleixner
2025-06-12 22:34   ` John Stultz
2025-06-25 16:16   ` [tip: timers/ptp] " tip-bot2 for Thomas Gleixner
2025-05-19  8:33 ` [patch V2 02/26] timekeeping: Cleanup kernel doc of __ktime_get_real_seconds() Thomas Gleixner
2025-06-12 22:36   ` John Stultz
2025-06-25 16:16   ` [tip: timers/ptp] " tip-bot2 for Thomas Gleixner
2025-05-19  8:33 ` [patch V2 03/26] timekeeping: Avoid double notification in do_adjtimex() Thomas Gleixner
2025-06-25 16:16   ` [tip: timers/ptp] " tip-bot2 for Thomas Gleixner
2025-05-19  8:33 ` [patch V2 04/26] timekeeping: Introduce timekeeper ID Thomas Gleixner
2025-06-13  0:03   ` John Stultz
2025-06-25 16:16   ` [tip: timers/ptp] " tip-bot2 for Anna-Maria Behnsen
2025-05-19  8:33 ` [patch V2 05/26] time: Introduce auxiliary POSIX clocks Thomas Gleixner
2025-06-13  0:06   ` John Stultz
2025-06-25 16:16   ` [tip: timers/ptp] " tip-bot2 for Anna-Maria Behnsen
2025-05-19  8:33 ` [patch V2 06/26] ntp: Add support for auxiliary timekeepers Thomas Gleixner
2025-06-13  0:14   ` John Stultz
2025-06-13  6:32   ` Thomas Weißschuh
2025-06-25 16:16   ` [tip: timers/ptp] " tip-bot2 for Thomas Gleixner
2025-05-19  8:33 ` [patch V2 07/26] ntp: Add timekeeper ID arguments to public functions Thomas Gleixner
2025-06-13  0:20   ` John Stultz
2025-06-25 16:16   ` [tip: timers/ptp] " tip-bot2 for Thomas Gleixner
2025-05-19  8:33 ` [patch V2 08/26] ntp: Rename __do_adjtimex() to ntp_adjtimex() Thomas Gleixner
2025-06-13  0:20   ` John Stultz
2025-06-25 16:16   ` [tip: timers/ptp] " tip-bot2 for Thomas Gleixner
2025-05-19  8:33 ` [patch V2 09/26] timekeeping: Make __timekeeping_advance() reusable Thomas Gleixner
2025-06-13  0:23   ` John Stultz
2025-06-25 16:16   ` [tip: timers/ptp] " tip-bot2 for Anna-Maria Behnsen
2025-05-19  8:33 ` [patch V2 10/26] timekeeping: Prepare timekeeping_update_from_shadow() Thomas Gleixner
2025-06-25 16:16   ` [tip: timers/ptp] " tip-bot2 for Thomas Gleixner
2025-05-19  8:33 ` [patch V2 11/26] timekeeping: Add clock_valid flag to timekeeper Thomas Gleixner
2025-06-13  4:05   ` John Stultz
2025-06-25 16:15   ` [tip: timers/ptp] " tip-bot2 for Thomas Gleixner
2025-05-19  8:33 ` [patch V2 12/26] timekeeping: Introduce auxiliary timekeepers Thomas Gleixner
2025-06-14  2:41   ` John Stultz
2025-06-25 16:15   ` [tip: timers/ptp] " tip-bot2 for Anna-Maria Behnsen
2025-05-19  8:33 ` [patch V2 13/26] timekeeping: Provide ktime_get_ntp_seconds() Thomas Gleixner
2025-06-25 16:15   ` [tip: timers/ptp] " tip-bot2 for Thomas Gleixner
2025-05-19  8:33 ` [patch V2 14/26] ntp: Use ktime_get_ntp_seconds() Thomas Gleixner
2025-06-25 16:15   ` [tip: timers/ptp] " tip-bot2 for Thomas Gleixner
2025-05-19  8:33 ` [patch V2 15/26] timekeeping: Add AUX offset to struct timekeeper Thomas Gleixner
2025-06-14  2:44   ` John Stultz
2025-06-25 16:15   ` [tip: timers/ptp] " tip-bot2 for Thomas Gleixner
2025-05-19  8:33 ` [patch V2 16/26] timekeeping: Update auxiliary timekeepers on clocksource change Thomas Gleixner
2025-05-19  8:33 ` [patch V2 17/26] timekeeping: Provide time getters for auxiliary clocks Thomas Gleixner
2025-06-14  2:51   ` John Stultz
2025-06-14  7:18     ` Thomas Gleixner
2025-05-19  8:33 ` [patch V2 18/26] timekeeping: Add minimal posix-timers support " Thomas Gleixner
2025-05-19  8:33 ` [patch V2 19/26] timekeeping: Provide time setter " Thomas Gleixner
2025-05-19  8:33 ` [patch V2 20/26] timekeeping: Make timekeeping_inject_offset() reusable Thomas Gleixner
2025-05-19  8:33 ` [patch V2 21/26] timekeeping: Add auxiliary clock support to __timekeeping_inject_offset() Thomas Gleixner
2025-05-19  8:33 ` [patch V2 22/26] timekeeping: Make do_adjtimex() reusable Thomas Gleixner
2025-05-19  8:33 ` [patch V2 23/26] timekeeping: Prepare do_adtimex() for auxiliary clocks Thomas Gleixner
2025-05-19  8:33 ` [patch V2 24/26] timekeeping: Provide adjtimex() " Thomas Gleixner
2025-05-19  8:33 ` [patch V2 25/26] timekeeping: Provide update for auxiliary timekeepers Thomas Gleixner
2025-05-19  8:33 ` [patch V2 26/26] timekeeping: Provide interface to control auxiliary clocks Thomas Gleixner
2025-06-13  7:18   ` Thomas Weißschuh

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).