<feed xmlns='http://www.w3.org/2005/Atom'>
<title>linux.git/kernel/time/timekeeping.c, branch v7.3-rc2</title>
<subtitle>Linux kernel source tree</subtitle>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/'/>
<entry>
<title>timekeeping: Use u32 for clock_was_set_seq</title>
<updated>2026-08-11T16:11:20+00:00</updated>
<author>
<name>Thomas Weißschuh (Schneider Electric)</name>
<email>thomas.weissschuh@linutronix.de</email>
</author>
<published>2026-08-03T10:04:33+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=406a037ce7a03a37bf2b03010791ea9343ecc233'/>
<id>406a037ce7a03a37bf2b03010791ea9343ecc233</id>
<content type='text'>
Use an explicitly sized type to make the code a bit more consistent
with other fields of the datastructure and other sequence counters.

Signed-off-by: Thomas Weißschuh (Schneider Electric) &lt;thomas.weissschuh@linutronix.de&gt;
Signed-off-by: Thomas Gleixner &lt;tglx@kernel.org&gt;
Link: https://patch.msgid.link/20260803-auxclock-nanosleep-prep-v2-2-910cbd485390@linutronix.de
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Use an explicitly sized type to make the code a bit more consistent
with other fields of the datastructure and other sequence counters.

Signed-off-by: Thomas Weißschuh (Schneider Electric) &lt;thomas.weissschuh@linutronix.de&gt;
Signed-off-by: Thomas Gleixner &lt;tglx@kernel.org&gt;
Link: https://patch.msgid.link/20260803-auxclock-nanosleep-prep-v2-2-910cbd485390@linutronix.de
</pre>
</div>
</content>
</entry>
<entry>
<title>timekeeping: Rename clockid_aux_valid() to clockid_is_aux_clock()</title>
<updated>2026-08-11T16:11:19+00:00</updated>
<author>
<name>Thomas Weißschuh (Schneider Electric)</name>
<email>thomas.weissschuh@linutronix.de</email>
</author>
<published>2026-08-03T10:04:32+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=4f39d3c19bdc6b9cd4a8de7cbc563264cac9a348'/>
<id>4f39d3c19bdc6b9cd4a8de7cbc563264cac9a348</id>
<content type='text'>
The current name is not clear about its behavior.

Rename it.

Signed-off-by: Thomas Weißschuh (Schneider Electric) &lt;thomas.weissschuh@linutronix.de&gt;
Signed-off-by: Thomas Gleixner &lt;tglx@kernel.org&gt;
Link: https://patch.msgid.link/20260803-auxclock-nanosleep-prep-v2-1-910cbd485390@linutronix.de
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
The current name is not clear about its behavior.

Rename it.

Signed-off-by: Thomas Weißschuh (Schneider Electric) &lt;thomas.weissschuh@linutronix.de&gt;
Signed-off-by: Thomas Gleixner &lt;tglx@kernel.org&gt;
Link: https://patch.msgid.link/20260803-auxclock-nanosleep-prep-v2-1-910cbd485390@linutronix.de
</pre>
</div>
</content>
</entry>
<entry>
<title>timekeeping: Remove the unused ktime_get_clock_ts64()</title>
<updated>2026-08-11T09:12:43+00:00</updated>
<author>
<name>Thomas Weißschuh (Schneider Electric)</name>
<email>thomas.weissschuh@linutronix.de</email>
</author>
<published>2026-07-31T14:20:14+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=1b515771872174553fe70eadb8efecfa49035922'/>
<id>1b515771872174553fe70eadb8efecfa49035922</id>
<content type='text'>
The last user was removed in commit a6d799608e6a ("ptp: Switch to
ktime_get_snapshot_id() for pre/post timestamps").

Signed-off-by: Thomas Weißschuh (Schneider Electric) &lt;thomas.weissschuh@linutronix.de&gt;
Signed-off-by: Thomas Gleixner &lt;tglx@kernel.org&gt;
Link: https://patch.msgid.link/20260731-timekeeping-aux-must-check-v1-1-11ae93068497@linutronix.de
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
The last user was removed in commit a6d799608e6a ("ptp: Switch to
ktime_get_snapshot_id() for pre/post timestamps").

Signed-off-by: Thomas Weißschuh (Schneider Electric) &lt;thomas.weissschuh@linutronix.de&gt;
Signed-off-by: Thomas Gleixner &lt;tglx@kernel.org&gt;
Link: https://patch.msgid.link/20260731-timekeeping-aux-must-check-v1-1-11ae93068497@linutronix.de
</pre>
</div>
</content>
</entry>
<entry>
<title>timekeeping: Check the return value of tk_get_aux_ts64 in __do_adjtimex()</title>
<updated>2026-08-10T20:16:34+00:00</updated>
<author>
<name>Thomas Weißschuh (Schneider Electric)</name>
<email>thomas.weissschuh@linutronix.de</email>
</author>
<published>2026-07-31T14:17:43+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=4b61084b11bcecce86d03804ff30f8d7b465593c'/>
<id>4b61084b11bcecce86d03804ff30f8d7b465593c</id>
<content type='text'>
If the auxiliary clock is disabled during tk_get_aux_ts64() but is enabled
before tks-&gt;clock_valid is checked, then uninitialized stackdata will be
used in the calculations and indirectly leaked to userspace.

The same race window also exists after this change and also for the core
timekeeper. But in these cases the only effect would be incorrect
adjustments and this is userspace's responsibility to avoid this.

Fixes: 4eca49d0b621 ("timekeeping: Prepare do_adtimex() for auxiliary clocks")
Signed-off-by: Thomas Weißschuh (Schneider Electric) &lt;thomas.weissschuh@linutronix.de&gt;
Signed-off-by: Thomas Gleixner &lt;tglx@kernel.org&gt;
Cc: stable@vger.kernel.org
Link: https://patch.msgid.link/20260731-timekeeping-aux-adjtimex-return-v1-1-b7fea4692886@linutronix.de
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
If the auxiliary clock is disabled during tk_get_aux_ts64() but is enabled
before tks-&gt;clock_valid is checked, then uninitialized stackdata will be
used in the calculations and indirectly leaked to userspace.

The same race window also exists after this change and also for the core
timekeeper. But in these cases the only effect would be incorrect
adjustments and this is userspace's responsibility to avoid this.

Fixes: 4eca49d0b621 ("timekeeping: Prepare do_adtimex() for auxiliary clocks")
Signed-off-by: Thomas Weißschuh (Schneider Electric) &lt;thomas.weissschuh@linutronix.de&gt;
Signed-off-by: Thomas Gleixner &lt;tglx@kernel.org&gt;
Cc: stable@vger.kernel.org
Link: https://patch.msgid.link/20260731-timekeeping-aux-adjtimex-return-v1-1-b7fea4692886@linutronix.de
</pre>
</div>
</content>
</entry>
<entry>
<title>timekeeping: Use READ_ONCE/WRITE_ONCE() for xtime_sec to prevent tearing</title>
<updated>2026-08-10T15:52:19+00:00</updated>
<author>
<name>Dennis Moshegov</name>
<email>dennis@xzync.uk</email>
</author>
<published>2026-07-24T15:43:55+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=d7fc133bf91f713df72facebd41ae9dfc83e35f7'/>
<id>d7fc133bf91f713df72facebd41ae9dfc83e35f7</id>
<content type='text'>
The timekeeper update path uses a bulk memcpy() to synchronize the
timekeeper structure, which is not guaranteed to be atomic. This allows for
torn reads in ktime_get_real_seconds() on 64-bit systems, where the
sequence counter protection is bypassed for performance.

To prevent reading a torn 64-bit xtime_sec value, enforce atomic-like
access by using WRITE_ONCE() for the critical field before the bulk
memcpy() in timekeeping_update_from_shadow(). Correspondingly, use
READ_ONCE() in ktime_get_real_seconds() to ensure a fresh, consistent load
from memory.

[ tglx: Format changelog and add comment ]

Reported-by: syzbot+72789cd1697965e714ca@syzkaller.appspotmail.com
Signed-off-by: Dennis Moshegov &lt;dennis@xzync.uk&gt;
Signed-off-by: Thomas Gleixner &lt;tglx@kernel.org&gt;
Link: https://patch.msgid.link/20260724154405.70-1-dennis@xzync.uk
Closes: https://syzkaller.appspot.com/bug?extid=72789cd1697965e714ca
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
The timekeeper update path uses a bulk memcpy() to synchronize the
timekeeper structure, which is not guaranteed to be atomic. This allows for
torn reads in ktime_get_real_seconds() on 64-bit systems, where the
sequence counter protection is bypassed for performance.

To prevent reading a torn 64-bit xtime_sec value, enforce atomic-like
access by using WRITE_ONCE() for the critical field before the bulk
memcpy() in timekeeping_update_from_shadow(). Correspondingly, use
READ_ONCE() in ktime_get_real_seconds() to ensure a fresh, consistent load
from memory.

[ tglx: Format changelog and add comment ]

Reported-by: syzbot+72789cd1697965e714ca@syzkaller.appspotmail.com
Signed-off-by: Dennis Moshegov &lt;dennis@xzync.uk&gt;
Signed-off-by: Thomas Gleixner &lt;tglx@kernel.org&gt;
Link: https://patch.msgid.link/20260724154405.70-1-dennis@xzync.uk
Closes: https://syzkaller.appspot.com/bug?extid=72789cd1697965e714ca
</pre>
</div>
</content>
</entry>
<entry>
<title>timekeeping: Drive time_adjust skew via per-tick ntp_error transfer</title>
<updated>2026-07-10T07:20:54+00:00</updated>
<author>
<name>David Woodhouse</name>
<email>dwmw@amazon.co.uk</email>
</author>
<published>2026-06-21T21:53:58+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=289d1759494f4a97b0ca4565f3eed00964b952c4'/>
<id>289d1759494f4a97b0ca4565f3eed00964b952c4</id>
<content type='text'>
The legacy adjtime() slew (ADJ_OFFSET_SINGLESHOT) was the last user of
tick_length != tick_length_base: it slewed the clock by inflating
tick_length directly, which delivered the correction imprecisely (e.g.
delivering only 4997.5µs when asked for a 5ms skew).

Deliver it accurately through the same per-tick mechanism that is now
used for time_offset, allowing it to contribute to skew_delta and thus
drive the delivery through ntp_error and mult selection.

To allow for accurate accounting, store the sub-microsecond part of
time_adjust is separately, while keeping time_adjust in microseconds
as that's the external API.

Signed-off-by: David Woodhouse &lt;dwmw@amazon.co.uk&gt;
Signed-off-by: Thomas Gleixner &lt;tglx@kernel.org&gt;
Assisted-by: Kiro:claude-opus-4.8
Link: https://patch.msgid.link/20260621220051.1030462-6-dwmw2@infradead.org
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
The legacy adjtime() slew (ADJ_OFFSET_SINGLESHOT) was the last user of
tick_length != tick_length_base: it slewed the clock by inflating
tick_length directly, which delivered the correction imprecisely (e.g.
delivering only 4997.5µs when asked for a 5ms skew).

Deliver it accurately through the same per-tick mechanism that is now
used for time_offset, allowing it to contribute to skew_delta and thus
drive the delivery through ntp_error and mult selection.

To allow for accurate accounting, store the sub-microsecond part of
time_adjust is separately, while keeping time_adjust in microseconds
as that's the external API.

Signed-off-by: David Woodhouse &lt;dwmw@amazon.co.uk&gt;
Signed-off-by: Thomas Gleixner &lt;tglx@kernel.org&gt;
Assisted-by: Kiro:claude-opus-4.8
Link: https://patch.msgid.link/20260621220051.1030462-6-dwmw2@infradead.org
</pre>
</div>
</content>
</entry>
<entry>
<title>timekeeping: Drive time_offset skew via per-tick ntp_error transfer</title>
<updated>2026-07-10T07:20:54+00:00</updated>
<author>
<name>David Woodhouse</name>
<email>dwmw@amazon.co.uk</email>
</author>
<published>2026-06-21T21:53:57+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=d375af58990902e73dd62bd7c049e759bcff92a5'/>
<id>d375af58990902e73dd62bd7c049e759bcff92a5</id>
<content type='text'>
Currently, the phase offset of time_offset and time_adjust is delivered
by adjusting tick_length in second_overflow(), and immediately draining
time_offset/time_adjust by the amount that the tick_length adjustment is
*estimated* to cause. This is fairly approximate, in part because it is
not always correct to assume that precisely NTP_INTERVAL_FREQ ticks will
occur between one call to second_overflow() and the next. It could also
over and under-run in the final second of delivery.

Instead of inflating tick_length, transfer the intended skew directly
into ntp_error each tick to achieve the desired rate.

In second_overflow(), calculate skew_delta which is the per-tick slew
rate, in the same units as time_offset: (ns &lt;&lt; NTP_SCALE_SHIFT) / HZ.

In logarithmic_accumulation(), drain up to 'skew_delta' time units from
time_offset into ntp_error to drive the overall effective rate. The new
ntp_drain_skew() function returns the amount which is actually 'claimed'
by time_offset (and in a future patch, time_adjust). Any overrun which
is delivered by the changed 'mult' (as described below) but not claimed
by ntp_drain_skew() will remain in ntp_error to be corrected away in
subsequent ticks.

Simply transferring the precise amount from time_offset to ntp_error
would be sufficent to make the time *eventually* converge, however the
skew delivered is limited by the choice of { mult, mult+1 } each tick
and thus the convergence would be extremely slow.

In theory we could inflate ntp_err_mult with the magnitude of ntp_error
in the general case — but that would cause overcorrection in a tickless
kernel. Instead, in timekeeping_adjust(), take skew_delta into account
when calculating 'mult', such that the available {mult, mult+1} choices
bracket the overall effective rate *including* the skew, to avoid the
delta just building up in ntp_error.

The effect is that the inflated 'mult' causes ntp_error to grow because
xtime_interval is (e.g.) longer than the true tick_length. But then the
same delta is removed again as it's drained from time_offset.

This gives behaviour equivalent to the old tick_length += delta approach
but with exact per-tick accounting of the time_offset actually imparted
to the clock, and no overrun.

Signed-off-by: David Woodhouse &lt;dwmw@amazon.co.uk&gt;
Signed-off-by: Thomas Gleixner &lt;tglx@kernel.org&gt;
Assisted-by: Kiro:claude-opus-4.8
Link: https://patch.msgid.link/20260621220051.1030462-5-dwmw2@infradead.org
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Currently, the phase offset of time_offset and time_adjust is delivered
by adjusting tick_length in second_overflow(), and immediately draining
time_offset/time_adjust by the amount that the tick_length adjustment is
*estimated* to cause. This is fairly approximate, in part because it is
not always correct to assume that precisely NTP_INTERVAL_FREQ ticks will
occur between one call to second_overflow() and the next. It could also
over and under-run in the final second of delivery.

Instead of inflating tick_length, transfer the intended skew directly
into ntp_error each tick to achieve the desired rate.

In second_overflow(), calculate skew_delta which is the per-tick slew
rate, in the same units as time_offset: (ns &lt;&lt; NTP_SCALE_SHIFT) / HZ.

In logarithmic_accumulation(), drain up to 'skew_delta' time units from
time_offset into ntp_error to drive the overall effective rate. The new
ntp_drain_skew() function returns the amount which is actually 'claimed'
by time_offset (and in a future patch, time_adjust). Any overrun which
is delivered by the changed 'mult' (as described below) but not claimed
by ntp_drain_skew() will remain in ntp_error to be corrected away in
subsequent ticks.

Simply transferring the precise amount from time_offset to ntp_error
would be sufficent to make the time *eventually* converge, however the
skew delivered is limited by the choice of { mult, mult+1 } each tick
and thus the convergence would be extremely slow.

In theory we could inflate ntp_err_mult with the magnitude of ntp_error
in the general case — but that would cause overcorrection in a tickless
kernel. Instead, in timekeeping_adjust(), take skew_delta into account
when calculating 'mult', such that the available {mult, mult+1} choices
bracket the overall effective rate *including* the skew, to avoid the
delta just building up in ntp_error.

The effect is that the inflated 'mult' causes ntp_error to grow because
xtime_interval is (e.g.) longer than the true tick_length. But then the
same delta is removed again as it's drained from time_offset.

This gives behaviour equivalent to the old tick_length += delta approach
but with exact per-tick accounting of the time_offset actually imparted
to the clock, and no overrun.

Signed-off-by: David Woodhouse &lt;dwmw@amazon.co.uk&gt;
Signed-off-by: Thomas Gleixner &lt;tglx@kernel.org&gt;
Assisted-by: Kiro:claude-opus-4.8
Link: https://patch.msgid.link/20260621220051.1030462-5-dwmw2@infradead.org
</pre>
</div>
</content>
</entry>
<entry>
<title>timekeeping: Account for clocksource tick quantisation via NTP</title>
<updated>2026-07-10T07:20:54+00:00</updated>
<author>
<name>David Woodhouse</name>
<email>dwmw@amazon.co.uk</email>
</author>
<published>2026-06-21T21:53:56+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=869a55e662a080a5c6618b68ae320231c720eeee'/>
<id>869a55e662a080a5c6618b68ae320231c720eeee</id>
<content type='text'>
cycle_interval is an integer number of counter cycles per NTP interval,
so the real time it represents differs from the nominal
NTP_INTERVAL_LENGTH by up to half a counter period. For coarse
clocksources this is significant: the 3.579545 MHz ACPI PM timer at
HZ=1000 rounds 3579.545 cycles up to 3580, making each tick 1.000127 ms
(+127 PPM).

Commit a386b5af8edd ("time: Compensate for rounding on odd-frequency
clocksources") introduced xtime_remainder to compensate for exactly
this, citing the same 127 PPM ACPI PM example. The compensation is
correct and necessary, but it was applied inside the timekeeping
accumulation in timekeeping.c: subtracted in the mult computation in
timekeeping_adjust() and folded into the ntp_error update in
logarithmic_accumulation(). That keeps the base rate correct and leaves
NTP its full symmetric +/-MAXFREQ range rather than +373/-627 PPM, but
the NTP code in ntp.c never sees it: tick_length is computed without the
correction, so ntp.c's notion of how long a tick is disagrees with the
rate timekeeping actually produces.

Make the offset an explicit part of the NTP tick_length instead. Add
ntp_data::cs_tick_adj, a fixed per-second addend that
ntp_update_frequency() includes alongside ntp_tick_adj and time_freq.
tk_setup_internals() computes it from the difference between the real
cycle_interval duration and the nominal interval, stores it in the
timekeeper, and hands it to NTP through a new argument to ntp_clear() --
which already recomputes the frequency and is invoked after every
clocksource (re)configuration. timekeeping_init() now uses TK_UPDATE_ALL
for this; clearing NTP there is otherwise redundant since ntp_init() has
just initialised it.

ntp.c now computes the true tick rate, giving a single source of truth.
Like ntp_tick_adj, cs_tick_adj stays internal to the kernel: userspace
still sees the nominal 1.000000 ms tick via adjtimex and is unaware of
the addends. timekeeping_adjust() and logarithmic_accumulation() use
ntp_tick / xtime_interval directly, and xtime_remainder is removed.

The base-rate arithmetic is unchanged: ntp_tick becomes
xtime_interval &lt;&lt; ntp_error_shift, so the mult division yields the same
base mult and the ntp_error accumulation still nets to zero per tick.

Beyond the cleanup of treating all the tick_length contributions
(nominal interval, ntp_tick_adj, cs_tick_adj, time_freq) consistently
as addends in one place, it also prepares for feed-forward discipline:
a future timekeeping_set_reference() will set tick_length to track an
absolute external reference such as a vmclock, and that path needs
ntp.c to own a tick_length that already reflects the clocksource
quantisation, with no hidden correction applied elsewhere.

Signed-off-by: David Woodhouse &lt;dwmw@amazon.co.uk&gt;
Signed-off-by: Thomas Gleixner &lt;tglx@kernel.org&gt;
Assisted-by: Kiro:claude-opus-4.8
Acked-by: John Stultz &lt;jstultz@google.com&gt;
Link: https://patch.msgid.link/20260621220051.1030462-4-dwmw2@infradead.org
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
cycle_interval is an integer number of counter cycles per NTP interval,
so the real time it represents differs from the nominal
NTP_INTERVAL_LENGTH by up to half a counter period. For coarse
clocksources this is significant: the 3.579545 MHz ACPI PM timer at
HZ=1000 rounds 3579.545 cycles up to 3580, making each tick 1.000127 ms
(+127 PPM).

Commit a386b5af8edd ("time: Compensate for rounding on odd-frequency
clocksources") introduced xtime_remainder to compensate for exactly
this, citing the same 127 PPM ACPI PM example. The compensation is
correct and necessary, but it was applied inside the timekeeping
accumulation in timekeeping.c: subtracted in the mult computation in
timekeeping_adjust() and folded into the ntp_error update in
logarithmic_accumulation(). That keeps the base rate correct and leaves
NTP its full symmetric +/-MAXFREQ range rather than +373/-627 PPM, but
the NTP code in ntp.c never sees it: tick_length is computed without the
correction, so ntp.c's notion of how long a tick is disagrees with the
rate timekeeping actually produces.

Make the offset an explicit part of the NTP tick_length instead. Add
ntp_data::cs_tick_adj, a fixed per-second addend that
ntp_update_frequency() includes alongside ntp_tick_adj and time_freq.
tk_setup_internals() computes it from the difference between the real
cycle_interval duration and the nominal interval, stores it in the
timekeeper, and hands it to NTP through a new argument to ntp_clear() --
which already recomputes the frequency and is invoked after every
clocksource (re)configuration. timekeeping_init() now uses TK_UPDATE_ALL
for this; clearing NTP there is otherwise redundant since ntp_init() has
just initialised it.

ntp.c now computes the true tick rate, giving a single source of truth.
Like ntp_tick_adj, cs_tick_adj stays internal to the kernel: userspace
still sees the nominal 1.000000 ms tick via adjtimex and is unaware of
the addends. timekeeping_adjust() and logarithmic_accumulation() use
ntp_tick / xtime_interval directly, and xtime_remainder is removed.

The base-rate arithmetic is unchanged: ntp_tick becomes
xtime_interval &lt;&lt; ntp_error_shift, so the mult division yields the same
base mult and the ntp_error accumulation still nets to zero per tick.

Beyond the cleanup of treating all the tick_length contributions
(nominal interval, ntp_tick_adj, cs_tick_adj, time_freq) consistently
as addends in one place, it also prepares for feed-forward discipline:
a future timekeeping_set_reference() will set tick_length to track an
absolute external reference such as a vmclock, and that path needs
ntp.c to own a tick_length that already reflects the clocksource
quantisation, with no hidden correction applied elsewhere.

Signed-off-by: David Woodhouse &lt;dwmw@amazon.co.uk&gt;
Signed-off-by: Thomas Gleixner &lt;tglx@kernel.org&gt;
Assisted-by: Kiro:claude-opus-4.8
Acked-by: John Stultz &lt;jstultz@google.com&gt;
Link: https://patch.msgid.link/20260621220051.1030462-4-dwmw2@infradead.org
</pre>
</div>
</content>
</entry>
<entry>
<title>timekeeping: Account for monotonicity adjustment in ntp_error</title>
<updated>2026-07-07T22:17:26+00:00</updated>
<author>
<name>David Woodhouse</name>
<email>dwmw@amazon.co.uk</email>
</author>
<published>2026-06-21T21:53:55+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=b7befd6d91207cf3f4cecd68fea0c212093906cf'/>
<id>b7befd6d91207cf3f4cecd68fea0c212093906cf</id>
<content type='text'>
timekeeping_apply_adjustment() modifies xtime_nsec to ensure monotonicity
when mult changes:

    xtime_nsec -= offset

This ensures that the time reported to userspace does not jump when the
multiplier is adjusted from one tick to the next. However, the ntp_error
accumulator which tracks the difference between intended and actual
clock position was not being updated to reflect this additional
discrepancy.

An earlier attempt at this compensation existed as:

    ntp_error -= (interval - offset) &lt;&lt; ntp_error_shift

but was removed in commit c2cda2a5bda9 ("timekeeping/ntp: Don't align
NTP frequency adjustments to ticks") because it was a major source of
NTP error. That's because (interval - offset) was wrong: the subtraction
of "interval" prematurely accounted for the changed xtime_interval of
the next tick, which would be correctly accounted in the next
accumulation anyway — a double subtraction.

What is actually needed is just the "offset" part: ntp_error must be
told that xtime_nsec moved by "offset" without a corresponding change
in the intended position. For the normal ±1 mult dithering this is
negligible (the adjustments cancel over time), but for larger mult
changes — such as when an external reference clock sets a new
frequency — the one-time uncompensated offset is significant.

Fix by adjusting ntp_error by the correct amount:

    ntp_error += offset &lt;&lt; ntp_error_shift

This keeps ntp_error consistent with the actual xtime_nsec position
after the adjustment, and ensures the discrepancy is correctly smoothed
away over time and the clock returns to where it should have been.

Fixes: c2cda2a5bda9 ("timekeeping/ntp: Don't align NTP frequency adjustments to ticks")
Signed-off-by: David Woodhouse &lt;dwmw@amazon.co.uk&gt;
Signed-off-by: Thomas Gleixner &lt;tglx@kernel.org&gt;
Assisted-by: Kiro:claude-opus-4.6-1m
Acked-by: John Stultz &lt;jstultz@google.com&gt;
Link: https://patch.msgid.link/20260621220051.1030462-3-dwmw2@infradead.org
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
timekeeping_apply_adjustment() modifies xtime_nsec to ensure monotonicity
when mult changes:

    xtime_nsec -= offset

This ensures that the time reported to userspace does not jump when the
multiplier is adjusted from one tick to the next. However, the ntp_error
accumulator which tracks the difference between intended and actual
clock position was not being updated to reflect this additional
discrepancy.

An earlier attempt at this compensation existed as:

    ntp_error -= (interval - offset) &lt;&lt; ntp_error_shift

but was removed in commit c2cda2a5bda9 ("timekeeping/ntp: Don't align
NTP frequency adjustments to ticks") because it was a major source of
NTP error. That's because (interval - offset) was wrong: the subtraction
of "interval" prematurely accounted for the changed xtime_interval of
the next tick, which would be correctly accounted in the next
accumulation anyway — a double subtraction.

What is actually needed is just the "offset" part: ntp_error must be
told that xtime_nsec moved by "offset" without a corresponding change
in the intended position. For the normal ±1 mult dithering this is
negligible (the adjustments cancel over time), but for larger mult
changes — such as when an external reference clock sets a new
frequency — the one-time uncompensated offset is significant.

Fix by adjusting ntp_error by the correct amount:

    ntp_error += offset &lt;&lt; ntp_error_shift

This keeps ntp_error consistent with the actual xtime_nsec position
after the adjustment, and ensures the discrepancy is correctly smoothed
away over time and the clock returns to where it should have been.

Fixes: c2cda2a5bda9 ("timekeeping/ntp: Don't align NTP frequency adjustments to ticks")
Signed-off-by: David Woodhouse &lt;dwmw@amazon.co.uk&gt;
Signed-off-by: Thomas Gleixner &lt;tglx@kernel.org&gt;
Assisted-by: Kiro:claude-opus-4.6-1m
Acked-by: John Stultz &lt;jstultz@google.com&gt;
Link: https://patch.msgid.link/20260621220051.1030462-3-dwmw2@infradead.org
</pre>
</div>
</content>
</entry>
<entry>
<title>timekeeping: Unwind aux clock sysfs children on failure</title>
<updated>2026-07-07T21:26:58+00:00</updated>
<author>
<name>Yuho Choi</name>
<email>dbgh9129@gmail.com</email>
</author>
<published>2026-07-03T16:53:37+00:00</published>
<link rel='alternate' type='text/html' href='https://git.tavy.me/linux.git/commit/?id=f2eee7e31ccd4bc87d047d8670cc2ec39cf36647'/>
<id>f2eee7e31ccd4bc87d047d8670cc2ec39cf36647</id>
<content type='text'>
tk_aux_sysfs_init() creates one child kobject per auxiliary clock. If a
later child or sysfs group creation fails, the current error path only
puts the parent kobjects and leaves earlier children and groups behind.

Store the child kobjects during init and remove the successfully created
groups and kobjects on failure.

Fixes: 7b5ab04f035f ("timekeeping: Fix resource leak in tk_aux_sysfs_init() error paths")
Signed-off-by: Yuho Choi &lt;dbgh9129@gmail.com&gt;
Signed-off-by: Thomas Gleixner &lt;tglx@kernel.org&gt;
Link: https://patch.msgid.link/20260703165337.168445-1-dbgh9129@gmail.com
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
tk_aux_sysfs_init() creates one child kobject per auxiliary clock. If a
later child or sysfs group creation fails, the current error path only
puts the parent kobjects and leaves earlier children and groups behind.

Store the child kobjects during init and remove the successfully created
groups and kobjects on failure.

Fixes: 7b5ab04f035f ("timekeeping: Fix resource leak in tk_aux_sysfs_init() error paths")
Signed-off-by: Yuho Choi &lt;dbgh9129@gmail.com&gt;
Signed-off-by: Thomas Gleixner &lt;tglx@kernel.org&gt;
Link: https://patch.msgid.link/20260703165337.168445-1-dbgh9129@gmail.com
</pre>
</div>
</content>
</entry>
</feed>
