1352 lines · 41.8 KB · C
RawDownload
// SPDX-License-Identifier: GPL-2.0/* * NTP state machine interfaces and logic. * * This code was mainly moved from kernel/timer.c and kernel/time.c * Please see those files for relevant copyright info and historical * changelogs. */#include <linux/capability.h>#include <linux/clocksource.h>#include <linux/workqueue.h>#include <linux/hrtimer.h>#include <linux/jiffies.h>#include <linux/math64.h>#include <linux/timex.h>#include <linux/time.h>#include <linux/mm.h>#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" /** * struct ntp_data - Structure holding all NTP related state * @tick_usec:		USER_HZ period in microseconds * @tick_length:	Tick length in ns << NTP_SCALE_SHIFT * @time_state:		State of the clock synchronization * @time_status:	Clock status bits * @time_offset:	Time adjustment in nanoseconds * @skew_delta:		Per-tick phase slew rate for the coming second, in *			@time_offset units (shifted-ns / HZ). Set by *			second_overflow(). * @time_constant:	PLL time constant * @time_maxerror:	Maximum error in microseconds holding the NTP sync distance *			(NTP dispersion + delay / 2) * @time_esterror:	Estimated error in microseconds holding NTP dispersion * @time_freq:		Frequency offset scaled nsecs/secs * @time_reftime:	Time at last adjustment in seconds * @time_adjust:	Adjustment value * @time_adjust_frac:	Sub-microsecond remainder of @time_adjust being *			delivered, in ns << NTP_SCALE_SHIFT (not divided by HZ). * @ntp_tick_adj:	Constant boot-param configurable NTP tick adjustment (upscaled) * @cs_tick_adj:	Fixed per-second adjustment compensating for the difference *			between the nominal NTP interval and the real time taken *			by the clocksource's integer @cycle_interval (upscaled). *			Set by the timekeeping core via ntp_clear(). * @ntp_next_leap_sec:	Second value of the next pending leapsecond, or TIME64_MAX if no leap * * @pps_valid:		PPS signal watchdog counter * @pps_tf:		PPS phase median filter * @pps_jitter:		PPS current jitter in nanoseconds * @pps_fbase:		PPS beginning of the last freq interval * @pps_shift:		PPS current interval duration in seconds (shift value) * @pps_intcnt:		PPS interval counter * @pps_freq:		PPS frequency offset in scaled ns/s * @pps_stabil:		PPS current stability in scaled ns/s * @pps_calcnt:		PPS monitor: calibration intervals * @pps_jitcnt:		PPS monitor: jitter limit exceeded * @pps_stbcnt:		PPS monitor: stability limit exceeded * @pps_errcnt:		PPS monitor: calibration errors * * Protected by the timekeeping locks. */struct ntp_data {	unsigned long		tick_usec;	u64			tick_length;	int			time_state;	int			time_status;	s64			time_offset;	s64			skew_delta;	long			time_constant;	long			time_maxerror;	long			time_esterror;	s64			time_freq;	time64_t		time_reftime;	long			time_adjust;	s64			time_adjust_frac;	s64			ntp_tick_adj;	s64			cs_tick_adj;	time64_t		ntp_next_leap_sec;#ifdef CONFIG_NTP_PPS	int			pps_valid;	long			pps_tf[3];	long			pps_jitter;	struct timespec64	pps_fbase;	int			pps_shift;	int			pps_intcnt;	s64			pps_freq;	long			pps_stabil;	long			pps_calcnt;	long			pps_jitcnt;	long			pps_stbcnt;	long			pps_errcnt;#endif}; 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#define MAX_TICKADJ		500LL		/* usecs *//* One microsecond of phase, in plain shifted-ns (ns << NTP_SCALE_SHIFT) */#define ONE_US_NS		((s64)NSEC_PER_USEC << NTP_SCALE_SHIFT)/* Per-tick MAX_TICKADJ slew, in plain shifted-ns */#define MAX_TICKADJ_SCALED \	(((MAX_TICKADJ * NSEC_PER_USEC) << NTP_SCALE_SHIFT) / NTP_INTERVAL_FREQ)#define MAX_TAI_OFFSET		100000 #ifdef CONFIG_NTP_PPS /* * The following variables are used when a pulse-per-second (PPS) signal * is available. They establish the engineering parameters of the clock * discipline loop when controlled by the PPS signal. */#define PPS_VALID	10	/* PPS signal watchdog max (s) */#define PPS_POPCORN	4	/* popcorn spike threshold (shift) */#define PPS_INTMIN	2	/* min freq interval (s) (shift) */#define PPS_INTMAX	8	/* max freq interval (s) (shift) */#define PPS_INTCOUNT	4	/* number of consecutive good intervals to				   increase pps_shift or consecutive bad				   intervals to decrease it */#define PPS_MAXWANDER	100000	/* max PPS freq wander (ns/s) */ /* * PPS kernel consumer compensates the whole phase error immediately. * Otherwise, reduce the offset by a fixed factor times the time constant. */static inline s64 ntp_offset_chunk(struct ntp_data *ntpdata, s64 offset){	if (ntpdata->time_status & STA_PPSTIME && ntpdata->time_status & STA_PPSSIGNAL)		return offset;	else		return shift_right(offset, SHIFT_PLL + ntpdata->time_constant);} static inline void pps_reset_freq_interval(struct ntp_data *ntpdata){	/* The PPS calibration interval may end surprisingly early */	ntpdata->pps_shift = PPS_INTMIN;	ntpdata->pps_intcnt = 0;} /** * pps_clear - Clears the PPS state variables * @ntpdata:	Pointer to ntp data */static inline void pps_clear(struct ntp_data *ntpdata){	pps_reset_freq_interval(ntpdata);	ntpdata->pps_tf[0] = 0;	ntpdata->pps_tf[1] = 0;	ntpdata->pps_tf[2] = 0;	ntpdata->pps_fbase.tv_sec = ntpdata->pps_fbase.tv_nsec = 0;	ntpdata->pps_freq = 0;} /* * Decrease pps_valid to indicate that another second has passed since the * last PPS signal. When it reaches 0, indicate that PPS signal is missing. */static inline void pps_dec_valid(struct ntp_data *ntpdata){	if (ntpdata->pps_valid > 0) {		ntpdata->pps_valid--;	} else {		ntpdata->time_status &= ~(STA_PPSSIGNAL | STA_PPSJITTER |					  STA_PPSWANDER | STA_PPSERROR);		pps_clear(ntpdata);	}} static inline void pps_set_freq(struct ntp_data *ntpdata){	ntpdata->pps_freq = ntpdata->time_freq;} static inline bool is_error_status(int status){	return (status & (STA_UNSYNC|STA_CLOCKERR))		/*		 * PPS signal lost when either PPS time or PPS frequency		 * synchronization requested		 */		|| ((status & (STA_PPSFREQ|STA_PPSTIME))			&& !(status & STA_PPSSIGNAL))		/*		 * PPS jitter exceeded when PPS time synchronization		 * requested		 */		|| ((status & (STA_PPSTIME|STA_PPSJITTER))			== (STA_PPSTIME|STA_PPSJITTER))		/*		 * PPS wander exceeded or calibration error when PPS		 * frequency synchronization requested		 */		|| ((status & STA_PPSFREQ)			&& (status & (STA_PPSWANDER|STA_PPSERROR)));} static inline void pps_fill_timex(struct ntp_data *ntpdata, struct __kernel_timex *txc){	txc->ppsfreq	   = shift_right((ntpdata->pps_freq >> PPM_SCALE_INV_SHIFT) *					 PPM_SCALE_INV, NTP_SCALE_SHIFT);	txc->jitter	   = ntpdata->pps_jitter;	if (!(ntpdata->time_status & STA_NANO))		txc->jitter = ntpdata->pps_jitter / NSEC_PER_USEC;	txc->shift	   = ntpdata->pps_shift;	txc->stabil	   = ntpdata->pps_stabil;	txc->jitcnt	   = ntpdata->pps_jitcnt;	txc->calcnt	   = ntpdata->pps_calcnt;	txc->errcnt	   = ntpdata->pps_errcnt;	txc->stbcnt	   = ntpdata->pps_stbcnt;} #else /* !CONFIG_NTP_PPS */ static inline s64 ntp_offset_chunk(struct ntp_data *ntpdata, s64 offset){	return shift_right(offset, SHIFT_PLL + ntpdata->time_constant);} static inline void pps_reset_freq_interval(struct ntp_data *ntpdata) {}static inline void pps_clear(struct ntp_data *ntpdata) {}static inline void pps_dec_valid(struct ntp_data *ntpdata) {}static inline void pps_set_freq(struct ntp_data *ntpdata) {} static inline bool is_error_status(int status){	return status & (STA_UNSYNC|STA_CLOCKERR);} static inline void pps_fill_timex(struct ntp_data *ntpdata, struct __kernel_timex *txc){	/* PPS is not implemented, so these are zero */	txc->ppsfreq	   = 0;	txc->jitter	   = 0;	txc->shift	   = 0;	txc->stabil	   = 0;	txc->jitcnt	   = 0;	txc->calcnt	   = 0;	txc->errcnt	   = 0;	txc->stbcnt	   = 0;} #endif /* CONFIG_NTP_PPS */ /* * Update tick_length based on tick_usec, ntp_tick_adj and time_freq: */static void ntp_update_frequency(struct ntp_data *ntpdata){	u64 second_length, new_base, tick_usec = (u64)ntpdata->tick_usec; 	second_length		 = (u64)(tick_usec * NSEC_PER_USEC * USER_HZ) << NTP_SCALE_SHIFT; 	second_length		+= ntpdata->ntp_tick_adj;	second_length		+= ntpdata->cs_tick_adj;	second_length		+= ntpdata->time_freq; 	new_base		 = div_u64(second_length, NTP_INTERVAL_FREQ); 	/*	 * Don't wait for the next second_overflow, apply the change to the	 * tick length immediately:	 */	ntpdata->tick_length	 = new_base;} static inline s64 ntp_update_offset_fll(struct ntp_data *ntpdata, s64 offset64, long secs){	ntpdata->time_status &= ~STA_MODE; 	if (secs < MINSEC)		return 0; 	if (!(ntpdata->time_status & STA_FLL) && (secs <= MAXSEC))		return 0; 	ntpdata->time_status |= STA_MODE; 	return div64_long(offset64 << (NTP_SCALE_SHIFT - SHIFT_FLL), secs);} static void ntp_update_offset(struct ntp_data *ntpdata, long offset){	s64 freq_adj, offset64;	long secs, real_secs; 	if (!(ntpdata->time_status & STA_PLL))		return; 	if (!(ntpdata->time_status & STA_NANO)) {		/* Make sure the multiplication below won't overflow */		offset = clamp(offset, -USEC_PER_SEC, USEC_PER_SEC);		offset *= NSEC_PER_USEC;	} 	/* Scale the phase adjustment and clamp to the operating range. */	offset = clamp(offset, -MAXPHASE, MAXPHASE); 	/*	 * Select how the frequency is to be controlled	 * and in which mode (PLL or FLL).	 */	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; 	ntpdata->time_reftime = real_secs; 	offset64    = offset;	freq_adj    = ntp_update_offset_fll(ntpdata, offset64, secs); 	/*	 * Clamp update interval to reduce PLL gain with low	 * sampling rate (e.g. intermittent network connection)	 * to avoid instability.	 */	if (unlikely(secs > 1 << (SHIFT_PLL + 1 + ntpdata->time_constant)))		secs = 1 << (SHIFT_PLL + 1 + ntpdata->time_constant); 	freq_adj    += (offset64 * secs) <<			(NTP_SCALE_SHIFT - 2 * (SHIFT_PLL + 2 + ntpdata->time_constant)); 	freq_adj    = min(freq_adj + ntpdata->time_freq, MAXFREQ_SCALED); 	ntpdata->time_freq   = max(freq_adj, -MAXFREQ_SCALED); 	ntpdata->time_offset = div_s64(offset64 << NTP_SCALE_SHIFT, NTP_INTERVAL_FREQ);} static void __ntp_clear(struct ntp_data *ntpdata){	/* Stop active adjtime() */	ntpdata->time_adjust	= 0;	ntpdata->time_adjust_frac = 0;	ntpdata->time_status	|= STA_UNSYNC;	ntpdata->time_maxerror	= NTP_PHASE_LIMIT;	ntpdata->time_esterror	= NTP_PHASE_LIMIT; 	ntp_update_frequency(ntpdata); 	ntpdata->time_offset	= 0;	ntpdata->skew_delta	= 0; 	ntpdata->ntp_next_leap_sec = TIME64_MAX;	/* Clear PPS state variables */	pps_clear(ntpdata);} /** * ntp_clear - Clear NTP state and set the clocksource quantisation adjustment * @tkid:		Timekeeper ID * @cs_tick_adj:	Per-second adjustment in ns << NTP_SCALE_SHIFT * * The timekeeping core uses an integer number of cycles (@cycle_interval) * per NTP interval, so the real time that interval represents differs from * the nominal NTP_INTERVAL_LENGTH by up to half a counter period. Folding * this fixed offset into @cs_tick_adj makes it an explicit part of the NTP * tick_length computation in ntp.c, instead of being applied during * timekeeping accumulation where the NTP code never saw it. Like * @ntp_tick_adj it stays internal to the kernel; userspace still sees the * nominal tick via adjtimex. NTP retains its full symmetric ±MAXFREQ range * around the corrected base rate. * * Called whenever the clocksource is (re)configured, which is also when the * rest of the NTP state must be cleared, so the two are done together. */void ntp_clear(unsigned int tkid, s64 cs_tick_adj){	tk_ntp_data[tkid].cs_tick_adj = cs_tick_adj;	__ntp_clear(&tk_ntp_data[tkid]);}  u64 ntp_tick_length(unsigned int tkid){	return tk_ntp_data[tkid].tick_length;} s64 ntp_get_skew_delta(unsigned int tkid){	return tk_ntp_data[tkid].skew_delta;} /* Sign of @x as +1 or -1 (zero counts as positive; callers pass nonzero). */static inline int signof(s64 x){	return x < 0 ? -1 : 1;} static s64 ntp_drain_time_offset(unsigned int tkid, s64 amount){	struct ntp_data *ntpdata = &tk_ntp_data[tkid]; 	/* Only drain if amount and time_offset have the same sign */	if (!amount || signof(amount) != signof(ntpdata->time_offset))		return amount; 	/* Clamp: don't overshoot zero */	if (abs(amount) > abs(ntpdata->time_offset)) {		s64 undrained = amount - ntpdata->time_offset; 		ntpdata->time_offset = 0;		return undrained;	} 	ntpdata->time_offset -= amount;	return 0;} /* * Drain the legacy adjtime() correction (time_adjust) as it is delivered. * * @amount is the total intentional per-tick skew for this accumulation * (skew_delta << shift), in time_offset units (shifted_ns / HZ); it covers * both the exponential time_offset slew and the linear adjtime slew. This * function claims only the adjtime share — capped at the MAX_TICKADJ rate — * and returns the remainder for ntp_drain_time_offset(). * * time_adjust is in whole µs. The sub-µs remainder being delivered lives in * time_adjust_frac (plain shifted-ns, i.e. ns << NTP_SCALE_SHIFT -- unlike * time_offset these are NOT pre-divided by HZ); we top it up by borrowing * whole microseconds from time_adjust as the drain consumes it. */static s64 ntp_drain_time_adjust(unsigned int tkid, s64 amount, unsigned int shift){	struct ntp_data *ntpdata = &tk_ntp_data[tkid];	/* Sign reference: time_adjust if any whole us remain, else the drawer */	s64 ref = ntpdata->time_adjust ? (s64)ntpdata->time_adjust				       : ntpdata->time_adjust_frac;	s64 deliver, deficit, claimed; 	if (!amount || !ref || signof(amount) != signof(ref))		return amount; 	/*	 * Phase to deliver this accumulation, in plain shifted-ns. The drain	 * @amount is in ÷HZ units, so multiply by HZ first, then clamp to the	 * MAX_TICKADJ rate (MAX_TICKADJ_SCALED is the per-tick slew in	 * shifted-ns). Multiply-then-clamp avoids an s64 divide for the cap.	 */	deliver = min(abs(amount) * NTP_INTERVAL_FREQ,		      (s64)MAX_TICKADJ_SCALED << shift); 	/* Top up the sub-µs drawer from whole-µs time_adjust as needed */	deficit = deliver - abs(ntpdata->time_adjust_frac);	if (deficit > 0 && ntpdata->time_adjust) {		long borrow = div64_u64(deficit + ONE_US_NS - 1, ONE_US_NS); 		if (ntpdata->time_adjust > 0) {			borrow = min(borrow, ntpdata->time_adjust);			ntpdata->time_adjust	  -= borrow;			ntpdata->time_adjust_frac += (s64)borrow * ONE_US_NS;		} else {			/* Clamp without negating time_adjust (UB for LONG_MIN) */			if (ntpdata->time_adjust > -borrow)				borrow = -ntpdata->time_adjust;			ntpdata->time_adjust	  += borrow;			ntpdata->time_adjust_frac -= (s64)borrow * ONE_US_NS;		}	} 	/* Never deliver more than the drawer holds */	deliver = min(deliver, abs(ntpdata->time_adjust_frac));	if (ntpdata->time_adjust_frac > 0)		ntpdata->time_adjust_frac -= deliver;	else		ntpdata->time_adjust_frac += deliver; 	/* Return the unclaimed remainder in ÷HZ drain units for time_offset */	claimed = div_s64(deliver, NTP_INTERVAL_FREQ);	return amount - signof(amount) * claimed;} /* * Drain one accumulation's worth of intentional skew as it is delivered. * * @amount is the total intentional per-tick skew for this accumulation * (skew_delta << shift), in time_offset units (shifted_ns / HZ). The * adjtime() linear share is taken from time_adjust first (capped at the * MAX_TICKADJ rate, hence @shift), then the exponential remainder from * time_offset. Returns the amount actually claimed (same ÷HZ units). */s64 ntp_drain_skew(unsigned int tkid, s64 amount, unsigned int shift){

Lines 1–500 of 1352.