Skip to content

Commit 4eca49d

Browse files
committed
timekeeping: Prepare do_adtimex() for auxiliary clocks
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> Acked-by: John Stultz <jstultz@google.com> Link: https://lore.kernel.org/all/20250625183758.253203783@linutronix.de
1 parent 775f71e commit 4eca49d

1 file changed

Lines changed: 33 additions & 3 deletions

File tree

kernel/time/timekeeping.c

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,17 @@ static struct tk_data timekeeper_data[TIMEKEEPERS_MAX];
5858
/* The core timekeeper */
5959
#define tk_core (timekeeper_data[TIMEKEEPER_CORE])
6060

61+
#ifdef CONFIG_POSIX_AUX_CLOCKS
62+
static inline bool tk_get_aux_ts64(unsigned int tkid, struct timespec64 *ts)
63+
{
64+
return ktime_get_aux_ts64(CLOCK_AUX + tkid - TIMEKEEPER_AUX_FIRST, ts);
65+
}
66+
#else
67+
static inline bool tk_get_aux_ts64(unsigned int tkid, struct timespec64 *ts)
68+
{
69+
return false;
70+
}
71+
#endif
6172

6273
/* flag for if timekeeping is suspended */
6374
int __read_mostly timekeeping_suspended;
@@ -2508,7 +2519,7 @@ ktime_t ktime_get_update_offsets_now(unsigned int *cwsseq, ktime_t *offs_real,
25082519
/*
25092520
* timekeeping_validate_timex - Ensures the timex is ok for use in do_adjtimex
25102521
*/
2511-
static int timekeeping_validate_timex(const struct __kernel_timex *txc)
2522+
static int timekeeping_validate_timex(const struct __kernel_timex *txc, bool aux_clock)
25122523
{
25132524
if (txc->modes & ADJ_ADJTIME) {
25142525
/* singleshot must not be used with any other mode bits */
@@ -2567,6 +2578,20 @@ static int timekeeping_validate_timex(const struct __kernel_timex *txc)
25672578
return -EINVAL;
25682579
}
25692580

2581+
if (aux_clock) {
2582+
/* Auxiliary clocks are similar to TAI and do not have leap seconds */
2583+
if (txc->status & (STA_INS | STA_DEL))
2584+
return -EINVAL;
2585+
2586+
/* No TAI offset setting */
2587+
if (txc->modes & ADJ_TAI)
2588+
return -EINVAL;
2589+
2590+
/* No PPS support either */
2591+
if (txc->status & (STA_PPSFREQ | STA_PPSTIME))
2592+
return -EINVAL;
2593+
}
2594+
25702595
return 0;
25712596
}
25722597

@@ -2595,17 +2620,22 @@ static int __do_adjtimex(struct tk_data *tkd, struct __kernel_timex *txc,
25952620
struct adjtimex_result *result)
25962621
{
25972622
struct timekeeper *tks = &tkd->shadow_timekeeper;
2623+
bool aux_clock = !timekeeper_is_core_tk(tks);
25982624
struct timespec64 ts;
25992625
s32 orig_tai, tai;
26002626
int ret;
26012627

26022628
/* Validate the data before disabling interrupts */
2603-
ret = timekeeping_validate_timex(txc);
2629+
ret = timekeeping_validate_timex(txc, aux_clock);
26042630
if (ret)
26052631
return ret;
26062632
add_device_randomness(txc, sizeof(*txc));
26072633

2608-
ktime_get_real_ts64(&ts);
2634+
if (!aux_clock)
2635+
ktime_get_real_ts64(&ts);
2636+
else
2637+
tk_get_aux_ts64(tkd->timekeeper.id, &ts);
2638+
26092639
add_device_randomness(&ts, sizeof(ts));
26102640

26112641
guard(raw_spinlock_irqsave)(&tkd->lock);

0 commit comments

Comments
 (0)