mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH v2 0/6] timekeeping: Reduce magnitude of ntp_error
@ 2026-11-06  3:08 David Woodhouse
  2026-11-06  3:08 ` [PATCH v2 1/6] timekeeping: Allow tick_length changes to apply mid-tick David Woodhouse
                   ` (6 more replies)
  0 siblings, 7 replies; 12+ messages in thread
From: David Woodhouse @ 2026-11-06  3:08 UTC (permalink / raw)
  To: Thomas Gleixner, John Stultz
  Cc: Stephen Boyd, Miroslav Lichvar, Rodolfo Giometti,
	Richard Cochran, Jie Wang, Yuan Wang, Ryan Luu, Julien Ridoux,
	linux-kernel, nh-open-source, David Woodhouse

From: David Woodhouse <dwmw@amazon.co.uk>

The timekeeper's ntp_error variable tracks the delta between the ideal
time that the kernel *should* be reporting as CLOCK_REALTIME, and the
time that is *actually* being reported.

A previous patch series in v7.3, up to commit 794ddd6e15cf ("ntp:
Remove tick_length_base, use tick_length directly"), fixed *errors* in
the accounting of ntp_error — cases where the reported time would
diverge from the ideal time *without* the divergence being correctly
tracked in ntp_error for subsequent compensation.

This series is the next step: it reduces the magnitude of the
excursions which are (now) *correctly* tracked in ntp_error.

The ntp_error mechanism works fine when it remains close to zero. The
actual clock is steered back towards the ideal by dithering between
mult and mult+1 for each cycle, changing between the two each time
ntp_error crosses zero.

This doesn't work as well when the value of ntp_error gets higher. In
some cases, 83µs of ntp_error was seen. Draining that through the mult
dithering, at typically less than 1ns/s, could take days. And while it
does, the precision of the frequency that can be effected by the
kernel's timekeeping is limited by the integer quantisation, because
it's permanently biased to either mult or mult+1 according to the
direction of the persistent ntp_error, and frequencies between the two
values cannot be achieved by the normal dithering. On top of which,
chrony was attempting to discipline the *reported* clock, even as the
kernel was attempting to steer it as hard as it could (albeit not very
hard) back to the kernel's ideal.

There are two cases where during frequency/phase adjustment, the
change was effectively applied to the 'ideal' vs. 'actual' rate at
different moments in time. The accounting for this in ntp_error was
self-consistent, but the better answer is for them to be conceptually
applied at the same moment, without contributing anything to ntp_error
at all. That also removes the step which repaying that ntp_error would
have caused; the rate simply pivots at the moment of the change.

This turns out not to be theoretical: Jie Wang reports¹ that since the
v7.3 accounting fixes, phc2sys takes minutes instead of seconds to
settle CLOCK_REALTIME after a step of the PHC it follows, because its
large frequency corrections are charged to ntp_error and repaid only
through the dithering. Patch 1 of this series is the fix for that:
Yuan Wang has measured it restoring their gPTP settling times (back to
32s from 200-400s or more) and withdrawn the RFC posted in that thread
in its favour.

While the timekeeping code is applying a phase correction, that
applies an additional bias to the per-cycle 'mult' values. If a
tickless kernel goes idle while this skew is being applied, it can
continue to apply that bias *long* after it was intended to finish,
overshooting the intended phase correction (by 500µs/s in the case of
adjtime). Fix this in timekeeping_max_deferment() by requesting a
wakeup at the top of the next second while phase skew is being
applied. (NB: only for the core timekeeper, not aux clocks which
remain as they were.)

Finally, if ntp_error ever does get excessive, we can deliberately
apply a phase skew to return it to zero faster than the normal
dithering would permit. An equivalent mechanism was removed in commit
dc491596f639 ("timekeeping: Rework frequency adjustments to work
better w/ nohz") but especially with the timekeeping_max_deferment()
change mentioned above, this now works effectively even with (and in
fact especially with) tickless idle. But again only for the core
timekeeper... unless we want to wake for aux clocks too?

Tests running at https://david.woodhou.se/ntptest-virt/ on baseline
vs. patched kernels, both tickless and periodic. The effect is seen
most clearly on the tickless kernel, where the baseline experiences
much higher jitter around corrections that should be smooth.

The final patch, correcting the output of ktime_get_snapshot_id() for
ntp_error at the moment of the snapshot, was marked DO NOT MERGE in v1.
It trades monotonicity (of the snapshot output, across read methods)
for accuracy, and Rodolfo wanted an explicit OK from the consumers of
the PPS_FETCH timestamps it changes; Miroslav has given chrony's². The
in-kernel snapshot users do want *accurate* time rather than a time we
*know* is microseconds wrong because the kernel happened to be idle
accumulating ntp_error right before they asked. So the tag is dropped
and the patch is now intended for merging with the rest.

v2:
 • Rebase to v7.4-rc1.
 • Pull the dividend/mult restructure up from the final patch into patch 1 so
   the old and new mult calculations match visually, and rewrite the
   comment explaining the mid-tick compensation (John).
 • Fix the ADJ_OFFSET_READONLY test in patch 3: that flag aliases
   ADJ_NANO and only has its read-only meaning in the ADJ_ADJTIME
   form. Also trigger the immediate update for ADJ_TIMECONST and
   ADJ_STATUS, mirroring process_adjtimex_modes(). (Found by Sashiko.)
 • Claim the do_timer duty when a slew starts (patch 3) or a drain
   engages (patch 4), so the per-second wakeup is honoured even if
   every other CPU is already sleeping on a timer programmed before
   the slew began.
 • Clamp the proportional drain in patch 4 at 50ppm instead of
   maxadj/4, and document the bounded frequency excursion (Miroslav).
   The clamp also bounds the extrapolation arithmetic in patch 6
   against overflow (found by Sashiko).
 • Smaller cleanups: an explicit negative-drain test, rounding on the
   insane-delta path, and honesty in the comments about the drain
   bias.
 • Pull the pps_get_ts() conversion to ktime_get_snapshot_id() into
   this series, ahead of the snapshot correction, so that the change
   to the PPS_FETCH timestamps is explicit and covers all PPS
   consumers (Rodolfo).
 • Drop DO NOT MERGE from the final patch.

¹ https://lore.kernel.org/all/20261105032150.1763572-1-yuan1.wang@intel.com/
² https://lore.kernel.org/all/atoVLqWfyJtCfci2@localhost/

David Woodhouse (6):
      timekeeping: Allow tick_length changes to apply mid-tick
      ntp: Recalculate skew_delta when the phase offset changes
      timekeeping: Bound idle sleep while a phase slew is in flight
      timekeeping: Reinstate proportional correction of ntp_error
      pps: Always use ktime_get_snapshot_id() for pps_get_ts()
      timekeeping: Apply extrapolated ntp_error to clock snapshots

 include/linux/pps_kernel.h          |   4 +-
 include/linux/timekeeper_internal.h |  11 +-
 kernel/time/ntp.c                   | 144 ++++++++++++++----------
 kernel/time/tick-internal.h         |  18 +++
 kernel/time/timekeeping.c           | 211 ++++++++++++++++++++++++++++++++++--
 5 files changed, 318 insertions(+), 70 deletions(-)

base-commit: 6628e7d4c6b2f582557a3437606eac34b1067b40
--
2.43.0

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

end of thread, other threads:[~2026-11-06 18:05 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-06  3:08 [PATCH v2 0/6] timekeeping: Reduce magnitude of ntp_error David Woodhouse
2026-11-06  3:08 ` [PATCH v2 1/6] timekeeping: Allow tick_length changes to apply mid-tick David Woodhouse
2026-11-06  3:08 ` [PATCH v2 2/6] ntp: Recalculate skew_delta when the phase offset changes David Woodhouse
2026-11-06  3:08 ` [PATCH v2 3/6] timekeeping: Bound idle sleep while a phase slew is in flight David Woodhouse
2026-11-06  3:08 ` [PATCH v2 4/6] timekeeping: Reinstate proportional correction of ntp_error David Woodhouse
2026-11-06  3:08 ` [PATCH v2 5/6] pps: Always use ktime_get_snapshot_id() for pps_get_ts() David Woodhouse
2026-11-06  8:44   ` Rodolfo Giometti
2026-11-06  3:08 ` [PATCH v2 6/6] timekeeping: Apply extrapolated ntp_error to clock snapshots David Woodhouse
2026-11-06  8:44   ` Rodolfo Giometti
2026-11-06  3:24 ` [PATCH v2 0/6] timekeeping: Reduce magnitude of ntp_error David Woodhouse
2026-11-06  8:44   ` Rodolfo Giometti
2026-11-06 18:05     ` David Woodhouse

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®