kern_ntptime.c revision 44794
118334Speter/*********************************************************************** 218334Speter * * 350654Sobrien * Copyright (c) David L. Mills 1993-1998 * 418334Speter * * 518334Speter * Permission to use, copy, modify, and distribute this software and * 618334Speter * its documentation for any purpose and without fee is hereby * 718334Speter * granted, provided that the above copyright notice appears in all * 818334Speter * copies and that both the copyright notice and this permission * 918334Speter * notice appear in supporting documentation, and that the name * 1018334Speter * University of Delaware not be used in advertising or publicity * 1118334Speter * pertaining to distribution of the software without specific, * 1218334Speter * written prior permission. The University of Delaware makes no * 1318334Speter * representations about the suitability this software for any * 1418334Speter * purpose. It is provided "as is" without express or implied * 1518334Speter * warranty. * 1618334Speter * * 1718334Speter **********************************************************************/ 1818334Speter 1918334Speter/* 2050654Sobrien * Adapted from the original sources for FreeBSD and timecounters by: 2118334Speter * Poul-Henning Kamp <phk@FreeBSD.org>. 2218334Speter * 2318334Speter * The 32bit version of the "LP" macros seems a bit past its "sell by" 2418334Speter * date so I have retained only the 64bit version and included it directly 2518334Speter * in this file. 2618334Speter * 2718334Speter * Only minor changes done to interface with the timecounters over in 2818334Speter * sys/kern/kern_clock.c. Some of the comments below may be (even more) 2918334Speter * confusing and/or plain wrong in that context. 3018334Speter */ 3118334Speter 3218334Speter#include "opt_ntp.h" 3318334Speter 3418334Speter#include <sys/param.h> 3518334Speter#include <sys/systm.h> 3618334Speter#include <sys/sysproto.h> 3752295Sobrien#include <sys/kernel.h> 3852295Sobrien#include <sys/proc.h> 3918334Speter#include <sys/time.h> 4018334Speter#include <sys/timex.h> 4118334Speter#include <sys/timepps.h> 4218334Speter#include <sys/sysctl.h> 4318334Speter 4418334Speter/* 4518334Speter * Single-precision macros for 64-bit machines 4618334Speter */ 4718334Spetertypedef long long l_fp; 4818334Speter#define L_ADD(v, u) ((v) += (u)) 4918334Speter#define L_SUB(v, u) ((v) -= (u)) 5018334Speter#define L_ADDHI(v, a) ((v) += (long long)(a) << 32) 5118334Speter#define L_NEG(v) ((v) = -(v)) 5218334Speter#define L_RSHIFT(v, n) \ 5318334Speter do { \ 5418334Speter if ((v) < 0) \ 5518334Speter (v) = -(-(v) >> (n)); \ 5618334Speter else \ 5750654Sobrien (v) = (v) >> (n); \ 5850654Sobrien } while (0) 5950654Sobrien#define L_MPY(v, a) ((v) *= (a)) 6050654Sobrien#define L_CLR(v) ((v) = 0) 6150654Sobrien#define L_ISNEG(v) ((v) < 0) 6250654Sobrien#define L_LINT(v, a) ((v) = (long long)(a) << 32) 6350654Sobrien#define L_GINT(v) ((v) < 0 ? -(-(v) >> 32) : (v) >> 32) 6450654Sobrien 6550654Sobrien/* 6650654Sobrien * Generic NTP kernel interface 6750654Sobrien * 6850654Sobrien * These routines constitute the Network Time Protocol (NTP) interfaces 6950654Sobrien * for user and daemon application programs. The ntp_gettime() routine 7050654Sobrien * provides the time, maximum error (synch distance) and estimated error 7118334Speter * (dispersion) to client user application programs. The ntp_adjtime() 7218334Speter * routine is used by the NTP daemon to adjust the system clock to an 7318334Speter * externally derived time. The time offset and related variables set by 7418334Speter * this routine are used by other routines in this module to adjust the 7518334Speter * phase and frequency of the clock discipline loop which controls the 7618334Speter * system clock. 7718334Speter * 7818334Speter * When the kernel time is reckoned directly in nanoseconds (NANO 7918334Speter * defined), the time at each tick interrupt is derived directly from 8018334Speter * the kernel time variable. When the kernel time is reckoned in 8118334Speter * microseconds, (NANO undefined), the time is derived from the kernel 8218334Speter * time variable together with a variable representing the leftover 8318334Speter * nanoseconds at the last tick interrupt. In either case, the current 8450654Sobrien * nanosecond time is reckoned from these values plus an interpolated 8550654Sobrien * value derived by the clock routines in another architecture-specific 8618334Speter * module. The interpolation can use either a dedicated counter or a 8718334Speter * processor cycle counter (PCC) implemented in some architectures. 8818334Speter * 8918334Speter * Note that all routines must run at priority splclock or higher. 9018334Speter */ 9118334Speter 9250654Sobrien/* 9318334Speter * Phase/frequency-lock loop (PLL/FLL) definitions 9418334Speter * 9518334Speter * The nanosecond clock discipline uses two variable types, time 9618334Speter * variables and frequency variables. Both types are represented as 64- 9750654Sobrien * bit fixed-point quantities with the decimal point between two 32-bit 9850654Sobrien * halves. On a 32-bit machine, each half is represented as a single 9950654Sobrien * word and mathematical operations are done using multiple-precision 10050654Sobrien * arithmetic. On a 64-bit machine, ordinary computer arithmetic is 10118334Speter * used. 10218334Speter * 10318334Speter * A time variable is a signed 64-bit fixed-point number in ns and 10418334Speter * fraction. It represents the remaining time offset to be amortized 10518334Speter * over succeeding tick interrupts. The maximum time offset is about 10618334Speter * 0.512 s and the resolution is about 2.3e-10 ns. 10718334Speter * 10818334Speter * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 10918334Speter * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 11018334Speter * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 11118334Speter * |s s s| ns | 11218334Speter * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 11318334Speter * | fraction | 11418334Speter * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 11518334Speter * 11618334Speter * A frequency variable is a signed 64-bit fixed-point number in ns/s 11718334Speter * and fraction. It represents the ns and fraction to be added to the 11818334Speter * kernel time variable at each second. The maximum frequency offset is 11918334Speter * about +-512000 ns/s and the resolution is about 2.3e-10 ns/s. 12018334Speter * 12118334Speter * 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 12218334Speter * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 12318334Speter * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 12418334Speter * |s s s s s s s s s s s s s| ns/s | 12518334Speter * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 12618334Speter * | fraction | 12718334Speter * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 12818334Speter */ 12918334Speter/* 13018334Speter * The following variables establish the state of the PLL/FLL and the 13118334Speter * residual time and frequency offset of the local clock. 13218334Speter */ 13350654Sobrien#define SHIFT_PLL 4 /* PLL loop gain (shift) */ 13450654Sobrien#define SHIFT_FLL 2 /* FLL loop gain (shift) */ 13550654Sobrien 13618334Speterstatic int time_state = TIME_OK; /* clock state */ 13718334Speterstatic int time_status = STA_UNSYNC; /* clock status bits */ 13818334Speterstatic long time_constant; /* poll interval (shift) (s) */ 13918334Speterstatic long time_precision = 1; /* clock precision (ns) */ 14018334Speterstatic long time_maxerror = MAXPHASE / 1000; /* maximum error (us) */ 14118334Speterstatic long time_esterror = MAXPHASE / 1000; /* estimated error (us) */ 14218334Speterstatic long time_reftime; /* time at last adjustment (s) */ 14350654Sobrienstatic long time_tick; /* nanoseconds per tick (ns) */ 14450654Sobrienstatic l_fp time_offset; /* time offset (ns) */ 14550654Sobrienstatic l_fp time_freq; /* frequency offset (ns/s) */ 14618334Speter 14718334Speter#ifdef PPS_SYNC 14818334Speter/* 14918334Speter * The following variables are used when a pulse-per-second (PPS) signal 15018334Speter * is available and connected via a modem control lead. They establish 15118334Speter * the engineering parameters of the clock discipline loop when 15218334Speter * controlled by the PPS signal. 15318334Speter */ 15450654Sobrien#define PPS_FAVG 2 /* min freq avg interval (s) (shift) */ 15518334Speter#define PPS_FAVGMAX 7 /* max freq avg interval (s) (shift) */ 15650654Sobrien#define PPS_PAVG 4 /* phase avg interval (s) (shift) */ 15750654Sobrien#define PPS_VALID 120 /* PPS signal watchdog max (s) */ 15850654Sobrien#define MAXTIME 500000 /* max PPS error (jitter) (ns) */ 15950654Sobrien#define MAXWANDER 500000 /* max PPS wander (ns/s/s) */ 16052295Sobrien 16152295Sobrienstruct ppstime { 16252295Sobrien long sec; /* PPS seconds */ 16352295Sobrien long nsec; /* PPS nanoseconds */ 16452295Sobrien}; 16552295Sobrienstatic struct ppstime pps_tf[3]; /* phase median filter */ 16652295Sobrienstatic struct ppstime pps_filt; /* phase offset */ 16752295Sobrienstatic long pps_fcount; /* frequency accumulator */ 16852295Sobrienstatic l_fp pps_freq; /* scaled frequency offset (ns/s) */ 16952295Sobrienstatic long pps_offacc; /* offset accumulator */ 17052295Sobrienstatic long pps_jitter; /* scaled time dispersion (ns) */ 17152295Sobrienstatic long pps_stabil; /* scaled frequency dispersion (ns/s) */ 17252295Sobrienstatic long pps_lastsec; /* time at last calibration (s) */ 17352295Sobrienstatic int pps_valid; /* signal watchdog counter */ 17452295Sobrienstatic int pps_shift = PPS_FAVG; /* interval duration (s) (shift) */ 17552295Sobrienstatic int pps_intcnt; /* wander counter */ 17652295Sobrienstatic int pps_offcnt; /* offset accumulator counter */ 17752295Sobrien 17852295Sobrien/* 17950654Sobrien * PPS signal quality monitors 18018334Speter */ 18118334Speterstatic long pps_calcnt; /* calibration intervals */ 18252295Sobrienstatic long pps_jitcnt; /* jitter limit exceeded */ 18352295Sobrienstatic long pps_stbcnt; /* stability limit exceeded */ 18452295Sobrienstatic long pps_errcnt; /* calibration errors */ 18552295Sobrien#endif /* PPS_SYNC */ 18652295Sobrien/* 18752295Sobrien * End of phase/frequency-lock loop (PLL/FLL) definitions 18852295Sobrien */ 18952295Sobrien 19052295Sobrienstatic void ntp_init(void); 19152295Sobrienstatic void hardupdate(long offset); 19252295Sobrien 19352295Sobrien/* 19452295Sobrien * ntp_gettime() - NTP user application interface 19552295Sobrien * 19652295Sobrien * See the timex.h header file for synopsis and API description. 19752295Sobrien */ 19852295Sobrienstatic int 19952295Sobrienntp_sysctl SYSCTL_HANDLER_ARGS 20052295Sobrien{ 20152295Sobrien struct ntptimeval ntv; /* temporary structure */ 20252295Sobrien struct timespec atv; /* nanosecond time */ 20352295Sobrien 20452295Sobrien nanotime(&atv); 20552295Sobrien ntv.time.tv_sec = atv.tv_sec; 20652295Sobrien ntv.time.tv_nsec = atv.tv_nsec; 20752295Sobrien ntv.maxerror = time_maxerror; 20852295Sobrien ntv.esterror = time_esterror; 20952295Sobrien ntv.time_state = time_state; 21052295Sobrien 21152295Sobrien /* 21252295Sobrien * Status word error decode. If any of these conditions occur, 21352295Sobrien * an error is returned, instead of the status word. Most 21452295Sobrien * applications will care only about the fact the system clock 21552295Sobrien * may not be trusted, not about the details. 21652295Sobrien * 21752295Sobrien * Hardware or software error 21852295Sobrien */ 21918334Speter if ((time_status & (STA_UNSYNC | STA_CLOCKERR)) || 22052295Sobrien 22118334Speter /* 22250654Sobrien * PPS signal lost when either time or frequency synchronization 22350654Sobrien * requested 22450654Sobrien */ 22550654Sobrien (time_status & (STA_PPSFREQ | STA_PPSTIME) && 22650654Sobrien !(time_status & STA_PPSSIGNAL)) || 22750654Sobrien 22850654Sobrien /* 22952295Sobrien * PPS jitter exceeded when time synchronization requested 23052295Sobrien */ 23150654Sobrien (time_status & STA_PPSTIME && 23250654Sobrien time_status & STA_PPSJITTER) || 23350654Sobrien 23450654Sobrien /* 23550654Sobrien * PPS wander exceeded or calibration error when frequency 23650654Sobrien * synchronization requested 23750654Sobrien */ 23852295Sobrien (time_status & STA_PPSFREQ && 23950654Sobrien time_status & (STA_PPSWANDER | STA_PPSERROR))) 24050654Sobrien ntv.time_state = TIME_ERROR; 24150654Sobrien return (sysctl_handle_opaque(oidp, &ntv, sizeof ntv, req)); 24250654Sobrien} 24350654Sobrien 24450654SobrienSYSCTL_NODE(_kern, OID_AUTO, ntp_pll, CTLFLAG_RW, 0, ""); 24552295SobrienSYSCTL_PROC(_kern_ntp_pll, OID_AUTO, gettime, CTLTYPE_OPAQUE|CTLFLAG_RD, 24650654Sobrien 0, sizeof(struct ntptimeval) , ntp_sysctl, "S,ntptimeval", ""); 24752295Sobrien 24852295Sobrien 24952295Sobrien/* 25052295Sobrien * ntp_adjtime() - NTP daemon application interface 25152295Sobrien * 25250654Sobrien * See the timex.h header file for synopsis and API description. 25318334Speter */ 25418334Speter#ifndef _SYS_SYSPROTO_H_ 25518334Speterstruct ntp_adjtime_args { 25618334Speter struct timex *tp; 25718334Speter}; 25818334Speter#endif 25918334Speter 26018334Speterint 26118334Speterntp_adjtime(struct proc *p, struct ntp_adjtime_args *uap) 26218334Speter{ 26352295Sobrien struct timex ntv; /* temporary structure */ 26452295Sobrien int modes; /* mode bits from structure */ 26552295Sobrien int s; /* caller priority */ 26652295Sobrien int error; 26752295Sobrien 26852295Sobrien error = copyin((caddr_t)uap->tp, (caddr_t)&ntv, sizeof(ntv)); 26952295Sobrien if (error) 27052295Sobrien return(error); 27152295Sobrien 27218334Speter /* 27318334Speter * Update selected clock variables - only the superuser can 27418334Speter * change anything. Note that there is no error checking here on 27518334Speter * the assumption the superuser should know what it is doing. 27618334Speter */ 27718334Speter modes = ntv.modes; 27818334Speter if (modes) 27918334Speter error = suser(p->p_cred->pc_ucred, &p->p_acflag); 28018334Speter if (error) 28118334Speter return (error); 28218334Speter s = splclock(); 28318334Speter if (modes & MOD_FREQUENCY) { 28418334Speter L_LINT(time_freq, ntv.freq / SCALE_PPM); 28518334Speter#ifdef PPS_SYNC 28618334Speter pps_freq = time_freq; 28718334Speter#endif /* PPS_SYNC */ 28818334Speter } 28918334Speter if (modes & MOD_MAXERROR) 29050654Sobrien time_maxerror = ntv.maxerror; 29150654Sobrien if (modes & MOD_ESTERROR) 29250654Sobrien time_esterror = ntv.esterror; 29350654Sobrien if (modes & MOD_STATUS) { 29450654Sobrien time_status &= STA_RONLY; 29550654Sobrien time_status |= ntv.status & ~STA_RONLY; 29650654Sobrien } 29750654Sobrien if (modes & MOD_TIMECONST) 29850654Sobrien time_constant = ntv.constant; 29950654Sobrien if (modes & MOD_NANO) 30050654Sobrien time_status |= STA_NANO; 30150654Sobrien if (modes & MOD_MICRO) 30250654Sobrien time_status &= ~STA_NANO; 30318334Speter if (modes & MOD_CLKB) 30450654Sobrien time_status |= STA_CLK; 30550654Sobrien if (modes & MOD_CLKA) 30650654Sobrien time_status &= ~STA_CLK; 30752295Sobrien if (modes & MOD_OFFSET) { 30852295Sobrien if (time_status & STA_NANO) 30950654Sobrien hardupdate(ntv.offset); 31050654Sobrien else 31150654Sobrien hardupdate(ntv.offset * 1000); 31250654Sobrien } 31350654Sobrien 31450654Sobrien /* 31552295Sobrien * Retrieve all clock variables 31650654Sobrien */ 31750654Sobrien if (time_status & STA_NANO) 31852295Sobrien ntv.offset = L_GINT(time_offset); 31950654Sobrien else 32050654Sobrien ntv.offset = L_GINT(time_offset) / 1000; 32150654Sobrien ntv.freq = L_GINT((time_freq / 1000) * 65536); 32252295Sobrien ntv.maxerror = time_maxerror; 32352295Sobrien ntv.esterror = time_esterror; 32450654Sobrien ntv.status = time_status; 32552295Sobrien if (ntv.constant < 0) 32652295Sobrien time_constant = 0; 32750654Sobrien else if (ntv.constant > MAXTC) 32850654Sobrien time_constant = MAXTC; 32950654Sobrien else 33050654Sobrien time_constant = ntv.constant; 33150654Sobrien if (time_status & STA_NANO) 33252295Sobrien ntv.precision = time_precision; 33350654Sobrien else 33450654Sobrien ntv.precision = time_precision / 1000; 33550654Sobrien ntv.tolerance = MAXFREQ * SCALE_PPM; 33650654Sobrien#ifdef PPS_SYNC 33752295Sobrien ntv.shift = pps_shift; 33850654Sobrien ntv.ppsfreq = L_GINT((pps_freq / 1000) * 65536); 33950654Sobrien ntv.jitter = pps_jitter; 34050654Sobrien if (time_status & STA_NANO) 34150654Sobrien ntv.jitter = pps_jitter; 34250654Sobrien else 34350654Sobrien ntv.jitter = pps_jitter / 1000; 34450654Sobrien ntv.stabil = pps_stabil; 34550654Sobrien ntv.calcnt = pps_calcnt; 34650654Sobrien ntv.errcnt = pps_errcnt; 34750654Sobrien ntv.jitcnt = pps_jitcnt; 34850654Sobrien ntv.stbcnt = pps_stbcnt; 34950654Sobrien#endif /* PPS_SYNC */ 35050654Sobrien splx(s); 35150654Sobrien 35250654Sobrien error = copyout((caddr_t)&ntv, (caddr_t)uap->tp, sizeof(ntv)); 35350654Sobrien if (error) 35450654Sobrien return (error); 35550654Sobrien 35650654Sobrien /* 35750654Sobrien * Status word error decode. See comments in 35850654Sobrien * ntp_gettime() routine. 35950654Sobrien */ 36050654Sobrien if ((time_status & (STA_UNSYNC | STA_CLOCKERR)) || 36150654Sobrien (time_status & (STA_PPSFREQ | STA_PPSTIME) && 36252295Sobrien !(time_status & STA_PPSSIGNAL)) || 36350654Sobrien (time_status & STA_PPSTIME && 36450654Sobrien time_status & STA_PPSJITTER) || 36550654Sobrien (time_status & STA_PPSFREQ && 36650654Sobrien time_status & (STA_PPSWANDER | STA_PPSERROR))) 36750654Sobrien return (TIME_ERROR); 36850654Sobrien return (time_state); 36918334Speter} 37018334Speter 37118334Speter/* 37218334Speter * second_overflow() - called after ntp_tick_adjust() 37318334Speter * 37418334Speter * This routine is ordinarily called immediately following the above 37518334Speter * routine ntp_tick_adjust(). While these two routines are normally 37618334Speter * combined, they are separated here only for the purposes of 37718334Speter * simulation. 37818334Speter */ 37918334Spetervoid 38018334Speterntp_update_second(struct timecounter *tcp) 38118334Speter{ 38218334Speter u_int32_t *newsec; 38318334Speter l_fp ftemp, time_adj; /* 32/64-bit temporaries */ 38418334Speter 38518334Speter newsec = &tcp->tc_offset_sec; 38618334Speter time_maxerror += MAXFREQ / 1000; 38718334Speter 38818334Speter /* 38918334Speter * Leap second processing. If in leap-insert state at 39018334Speter * the end of the day, the system clock is set back one 39118334Speter * second; if in leap-delete state, the system clock is 39218334Speter * set ahead one second. The nano_time() routine or 39318334Speter * external clock driver will insure that reported time 39418334Speter * is always monotonic. 39518334Speter */ 39618334Speter switch (time_state) { 39718334Speter 39818334Speter /* 39918334Speter * No warning. 40018334Speter */ 40118334Speter case TIME_OK: 40218334Speter if (time_status & STA_INS) 40318334Speter time_state = TIME_INS; 40418334Speter else if (time_status & STA_DEL) 40518334Speter time_state = TIME_DEL; 40618334Speter break; 40718334Speter 40818334Speter /* 40918334Speter * Insert second 23:59:60 following second 41018334Speter * 23:59:59. 41118334Speter */ 41218334Speter case TIME_INS: 41352295Sobrien if (!(time_status & STA_INS)) 41418334Speter time_state = TIME_OK; 41518334Speter else if ((*newsec) % 86400 == 0) { 41652295Sobrien (*newsec)--; 41752295Sobrien time_state = TIME_OOP; 41852295Sobrien } 41952295Sobrien break; 42018334Speter 42118334Speter /* 42218334Speter * Delete second 23:59:59. 42318334Speter */ 42418334Speter case TIME_DEL: 42518334Speter if (!(time_status & STA_DEL)) 42618334Speter time_state = TIME_OK; 42718334Speter else if (((*newsec) + 1) % 86400 == 0) { 42818334Speter (*newsec)++; 42918334Speter time_state = TIME_WAIT; 43018334Speter } 43118334Speter break; 43218334Speter 43318334Speter /* 43418334Speter * Insert second in progress. 43518334Speter */ 43618334Speter case TIME_OOP: 43718334Speter time_state = TIME_WAIT; 43818334Speter break; 43950654Sobrien 44050654Sobrien /* 44150654Sobrien * Wait for status bits to clear. 44250654Sobrien */ 44350654Sobrien case TIME_WAIT: 44450654Sobrien if (!(time_status & (STA_INS | STA_DEL))) 44550654Sobrien time_state = TIME_OK; 44650654Sobrien } 44750654Sobrien 44850654Sobrien /* 44950654Sobrien * Compute the total time adjustment for the next 45050654Sobrien * second in ns. The offset is reduced by a factor 45150654Sobrien * depending on FLL or PLL mode and whether the PPS 45250654Sobrien * signal is operating. Note that the value is in effect 45350654Sobrien * scaled by the clock frequency, since the adjustment 45450654Sobrien * is added at each tick interrupt. 45550654Sobrien */ 45650654Sobrien ftemp = time_offset; 45750654Sobrien#ifdef PPS_SYNC 45850654Sobrien if (time_status & STA_PPSTIME && time_status & 45950654Sobrien STA_PPSSIGNAL) 46050654Sobrien L_RSHIFT(ftemp, PPS_FAVG); 46150654Sobrien else if (time_status & STA_MODE) 46250654Sobrien#else 46350654Sobrien if (time_status & STA_MODE) 46450654Sobrien#endif /* PPS_SYNC */ 46550654Sobrien L_RSHIFT(ftemp, SHIFT_FLL); 46650654Sobrien else 46750654Sobrien L_RSHIFT(ftemp, SHIFT_PLL + time_constant); 46850654Sobrien time_adj = ftemp; 46950654Sobrien L_SUB(time_offset, ftemp); 47050654Sobrien L_ADD(time_adj, time_freq); 47150654Sobrien tcp->tc_adjustment = time_adj; 47250654Sobrien#ifdef PPS_SYNC 47350654Sobrien if (pps_valid > 0) 47450654Sobrien pps_valid--; 47550654Sobrien else 47650654Sobrien time_status &= ~(STA_PPSSIGNAL | STA_PPSJITTER | 47750654Sobrien STA_PPSWANDER | STA_PPSERROR); 47850654Sobrien#endif /* PPS_SYNC */ 47950654Sobrien} 48050654Sobrien 48150654Sobrien/* 48250654Sobrien * ntp_init() - initialize variables and structures 48350654Sobrien * 48450654Sobrien * This routine must be called after the kernel variables hz and tick 48550654Sobrien * are set or changed and before the next tick interrupt. In this 48650654Sobrien * particular implementation, these values are assumed set elsewhere in 48750654Sobrien * the kernel. The design allows the clock frequency and tick interval 48850654Sobrien * to be changed while the system is running. So, this routine should 48950654Sobrien * probably be integrated with the code that does that. 49050654Sobrien */ 49150654Sobrienstatic void 49250654Sobrienntp_init() 49350654Sobrien{ 49450654Sobrien 49550654Sobrien /* 49650654Sobrien * The following variable must be initialized any time the 49750654Sobrien * kernel variable hz is changed. 49850654Sobrien */ 49950654Sobrien time_tick = NANOSECOND / hz; 50050654Sobrien 50150654Sobrien /* 50250654Sobrien * The following variables are initialized only at startup. Only 50350654Sobrien * those structures not cleared by the compiler need to be 50450654Sobrien * initialized, and these only in the simulator. In the actual 50550654Sobrien * kernel, any nonzero values here will quickly evaporate. 50650654Sobrien */ 50750654Sobrien L_CLR(time_offset); 50850654Sobrien L_CLR(time_freq); 50950654Sobrien#ifdef PPS_SYNC 51050654Sobrien pps_filt.sec = pps_filt.nsec = 0; 51150654Sobrien pps_fcount = 0; 51252295Sobrien pps_tf[0] = pps_tf[1] = pps_tf[2] = pps_filt; 51352295Sobrien L_CLR(pps_freq); 51452295Sobrien#endif /* PPS_SYNC */ 51552295Sobrien} 51652295Sobrien 51752295SobrienSYSINIT(ntpclocks, SI_SUB_CLOCKS, SI_ORDER_FIRST, ntp_init, NULL) 51852295Sobrien 51952295Sobrien/* 52052295Sobrien * hardupdate() - local clock update 52152295Sobrien * 52252295Sobrien * This routine is called by ntp_adjtime() to update the local clock 52352295Sobrien * phase and frequency. The implementation is of an adaptive-parameter, 52452295Sobrien * hybrid phase/frequency-lock loop (PLL/FLL). The routine computes new 52552295Sobrien * time and frequency offset estimates for each call. If the kernel PPS 52652295Sobrien * discipline code is configured (PPS_SYNC), the PPS signal itself 52752295Sobrien * determines the new time offset, instead of the calling argument. 52852295Sobrien * Presumably, calls to ntp_adjtime() occur only when the caller 52952295Sobrien * believes the local clock is valid within some bound (+-128 ms with 53052295Sobrien * NTP). If the caller's time is far different than the PPS time, an 53152295Sobrien * argument will ensue, and it's not clear who will lose. 53252295Sobrien * 53352295Sobrien * For uncompensated quartz crystal oscillators and nominal update 53452295Sobrien * intervals less than 256 s, operation should be in phase-lock mode, 53552295Sobrien * where the loop is disciplined to phase. For update intervals greater 53652295Sobrien * than 1024 s, operation should be in frequency-lock mode, where the 53752295Sobrien * loop is disciplined to frequency. Between 256 s and 1024 s, the mode 53852295Sobrien * is selected by the STA_MODE status bit. 53952295Sobrien */ 54052295Sobrienstatic void 54152295Sobrienhardupdate(offset) 54252295Sobrien long offset; /* clock offset (ns) */ 54352295Sobrien{ 54452295Sobrien long ltemp, mtemp; 54552295Sobrien l_fp ftemp; 54652295Sobrien 54752295Sobrien /* 54852295Sobrien * Select how the phase is to be controlled and from which 54952295Sobrien * source. If the PPS signal is present and enabled to 55052295Sobrien * discipline the time, the PPS offset is used; otherwise, the 55152295Sobrien * argument offset is used. 55218334Speter */ 55318334Speter ltemp = offset; 55418334Speter if (ltemp > MAXPHASE) 55518334Speter ltemp = MAXPHASE; 55618334Speter else if (ltemp < -MAXPHASE) 55718334Speter ltemp = -MAXPHASE; 55818334Speter if (!(time_status & STA_PPSTIME && time_status & STA_PPSSIGNAL)) 55918334Speter L_LINT(time_offset, ltemp); 56018334Speter 56118334Speter /* 56218334Speter * Select how the frequency is to be controlled and in which 56318334Speter * mode (PLL or FLL). If the PPS signal is present and enabled 56418334Speter * to discipline the frequency, the PPS frequency is used; 56550654Sobrien * otherwise, the argument offset is used to compute it. 56650654Sobrien */ 56718334Speter if (time_status & STA_PPSFREQ && time_status & STA_PPSSIGNAL) { 56818334Speter time_reftime = time_second; 56918334Speter return; 57018334Speter } 57150654Sobrien if (time_status & STA_FREQHOLD || time_reftime == 0) 57250654Sobrien time_reftime = time_second; 57318334Speter mtemp = time_second - time_reftime; 57418334Speter if (mtemp >= MINSEC && (time_status & STA_FLL || mtemp > MAXSEC) 57518334Speter ) { 57618334Speter L_LINT(ftemp, (ltemp << 4) / mtemp); 57718334Speter L_RSHIFT(ftemp, SHIFT_FLL + 4); 57818334Speter L_ADD(time_freq, ftemp); 57918334Speter time_status |= STA_MODE; 58018334Speter } else { 58150654Sobrien L_LINT(ftemp, ltemp); 58218334Speter L_RSHIFT(ftemp, (SHIFT_PLL + 2 + time_constant) << 1); 58318334Speter L_MPY(ftemp, mtemp); 58418334Speter L_ADD(time_freq, ftemp); 58518334Speter time_status &= ~STA_MODE; 58618334Speter } 58718334Speter time_reftime = time_second; 58818334Speter if (L_GINT(time_freq) > MAXFREQ) 58918334Speter L_LINT(time_freq, MAXFREQ); 59018334Speter else if (L_GINT(time_freq) < -MAXFREQ) 59118334Speter L_LINT(time_freq, -MAXFREQ); 59218334Speter} 59318334Speter 59418334Speter#ifdef PPS_SYNC 59518334Speter/* 59618334Speter * hardpps() - discipline CPU clock oscillator to external PPS signal 59718334Speter * 59818334Speter * This routine is called at each PPS interrupt in order to discipline 59918334Speter * the CPU clock oscillator to the PPS signal. It measures the PPS phase 60018334Speter * and leaves it in a handy spot for the hardclock() routine. It 60118334Speter * integrates successive PPS phase differences and calculates the 60218334Speter * frequency offset. This is used in hardclock() to discipline the CPU 60318334Speter * clock oscillator so that the intrinsic frequency error is cancelled 60418334Speter * out. The code requires the caller to capture the time and 60518334Speter * architecture-dependent hardware counter values in nanoseconds at the 60618334Speter * on-time PPS signal transition. 60718334Speter * 60818334Speter * Note that, on some Unix systems this routine runs at an interrupt 60918334Speter * priority level higher than the timer interrupt routine hardclock(). 61018334Speter * Therefore, the variables used are distinct from the hardclock() 61118334Speter * variables, except for the actual time and frequency variables, which 61218334Speter * are determined by this routine and updated atomically. 61318334Speter */ 61418334Spetervoid 61518334Speterhardpps(tsp, nsec) 61618334Speter struct timespec *tsp; /* time at PPS */ 61718334Speter long nsec; /* hardware counter at PPS */ 61818334Speter{ 61918334Speter long u_sec, u_nsec, v_nsec; /* temps */ 62018334Speter l_fp ftemp; 62118334Speter 62218334Speter /* 62318334Speter * The signal is first processed by a frequency discriminator 62418334Speter * which rejects noise and input signals with frequencies 62518334Speter * outside the range 1 +-MAXFREQ PPS. If two hits occur in the 62618334Speter * same second, we ignore the later hit; if not and a hit occurs 62718334Speter * outside the range gate, keep the later hit but do not 62818334Speter * process it. 62918334Speter */ 63018334Speter time_status |= STA_PPSSIGNAL | STA_PPSJITTER; 63118334Speter time_status &= ~(STA_PPSWANDER | STA_PPSERROR); 63218334Speter pps_valid = PPS_VALID; 63318334Speter u_sec = tsp->tv_sec; 63418334Speter u_nsec = tsp->tv_nsec; 63518334Speter if (u_nsec >= (NANOSECOND >> 1)) { 63618334Speter u_nsec -= NANOSECOND; 63718334Speter u_sec++; 63818334Speter } 63918334Speter v_nsec = u_nsec - pps_tf[0].nsec; 64018334Speter if (u_sec == pps_tf[0].sec && v_nsec < -MAXFREQ) { 64118334Speter return; 64218334Speter } 64318334Speter pps_tf[2] = pps_tf[1]; 64418334Speter pps_tf[1] = pps_tf[0]; 64518334Speter pps_tf[0].sec = u_sec; 64618334Speter pps_tf[0].nsec = u_nsec; 64718334Speter 64818334Speter /* 64918334Speter * Compute the difference between the current and previous 65018334Speter * counter values. If the difference exceeds 0.5 s, assume it 65118334Speter * has wrapped around, so correct 1.0 s. If the result exceeds 65218334Speter * the tick interval, the sample point has crossed a tick 65318334Speter * boundary during the last second, so correct the tick. Very 65418334Speter * intricate. 65518334Speter */ 65618334Speter u_nsec = nsec; 65718334Speter if (u_nsec > (NANOSECOND >> 1)) 65818334Speter u_nsec -= NANOSECOND; 65918334Speter else if (u_nsec < -(NANOSECOND >> 1)) 66018334Speter u_nsec += NANOSECOND; 66118334Speter pps_fcount += u_nsec; 66218334Speter if (v_nsec > MAXFREQ) { 66318334Speter return; 66418334Speter } 66518334Speter time_status &= ~STA_PPSJITTER; 66618334Speter 66718334Speter /* 66818334Speter * A three-stage median filter is used to help denoise the PPS 66918334Speter * time. The median sample becomes the time offset estimate; the 67018334Speter * difference between the other two samples becomes the time 67118334Speter * dispersion (jitter) estimate. 67218334Speter */ 67318334Speter if (pps_tf[0].nsec > pps_tf[1].nsec) { 67418334Speter if (pps_tf[1].nsec > pps_tf[2].nsec) { 67518334Speter pps_filt = pps_tf[1]; /* 0 1 2 */ 67618334Speter u_nsec = pps_tf[0].nsec - pps_tf[2].nsec; 67718334Speter } else if (pps_tf[2].nsec > pps_tf[0].nsec) { 67818334Speter pps_filt = pps_tf[0]; /* 2 0 1 */ 67918334Speter u_nsec = pps_tf[2].nsec - pps_tf[1].nsec; 68018334Speter } else { 68118334Speter pps_filt = pps_tf[2]; /* 0 2 1 */ 68218334Speter u_nsec = pps_tf[0].nsec - pps_tf[1].nsec; 68318334Speter } 68418334Speter } else { 68518334Speter if (pps_tf[1].nsec < pps_tf[2].nsec) { 68618334Speter pps_filt = pps_tf[1]; /* 2 1 0 */ 68718334Speter u_nsec = pps_tf[2].nsec - pps_tf[0].nsec; 68818334Speter } else if (pps_tf[2].nsec < pps_tf[0].nsec) { 68918334Speter pps_filt = pps_tf[0]; /* 1 0 2 */ 69018334Speter u_nsec = pps_tf[1].nsec - pps_tf[2].nsec; 69118334Speter } else { 69218334Speter pps_filt = pps_tf[2]; /* 1 2 0 */ 69318334Speter u_nsec = pps_tf[1].nsec - pps_tf[0].nsec; 69418334Speter } 69518334Speter } 69618334Speter 69718334Speter /* 69818334Speter * Nominal jitter is due to PPS signal noise and interrupt 69950654Sobrien * latency. If it exceeds the jitter limit, the sample is 70018334Speter * discarded. otherwise, if so enabled, the time offset is 70118334Speter * updated. The offsets are accumulated over the phase averaging 70218334Speter * interval to improve accuracy. The jitter is averaged only for 70350654Sobrien * performance monitoring. We can tolerate a modest loss of data 70450654Sobrien * here without degrading time accuracy. 70550654Sobrien */ 70618334Speter if (u_nsec > MAXTIME) { 70718334Speter time_status |= STA_PPSJITTER; 70818334Speter pps_jitcnt++; 70918334Speter } else if (time_status & STA_PPSTIME) { 71018334Speter pps_offacc -= pps_filt.nsec; 71118334Speter pps_offcnt++; 71250654Sobrien } 71350654Sobrien if (pps_offcnt >= (1 << PPS_PAVG)) { 71452295Sobrien if (time_status & STA_PPSTIME) { 71552295Sobrien L_LINT(time_offset, pps_offacc); 71618334Speter L_RSHIFT(time_offset, PPS_PAVG); 71718334Speter } 71818334Speter pps_offacc = 0; 71918334Speter pps_offcnt = 0; 72018334Speter 72118334Speter } 72218334Speter pps_jitter += (u_nsec - pps_jitter) >> PPS_FAVG; 72318334Speter u_sec = pps_tf[0].sec - pps_lastsec; 72418334Speter if (u_sec < (1 << pps_shift)) 72518334Speter return; 72618334Speter 72718334Speter /* 72818334Speter * At the end of the calibration interval the difference between 72918334Speter * the first and last counter values becomes the scaled 73018334Speter * frequency. It will later be divided by the length of the 73118334Speter * interval to determine the frequency update. If the frequency 73218334Speter * exceeds a sanity threshold, or if the actual calibration 73318334Speter * interval is not equal to the expected length, the data are 73418334Speter * discarded. We can tolerate a modest loss of data here without 73518334Speter * degrading frequency ccuracy. 73618334Speter */ 73718334Speter pps_calcnt++; 73818334Speter v_nsec = -pps_fcount; 73918334Speter pps_lastsec = pps_tf[0].sec; 74018334Speter pps_fcount = 0; 74150654Sobrien u_nsec = MAXFREQ << pps_shift; 74218334Speter if (v_nsec > u_nsec || v_nsec < -u_nsec || u_sec != (1 << 74318334Speter pps_shift)) { 74418334Speter time_status |= STA_PPSERROR; 74518334Speter pps_errcnt++; 74618334Speter return; 74718334Speter } 74818334Speter 74918334Speter /* 75018334Speter * If the actual calibration interval is not equal to the 75118334Speter * expected length, the data are discarded. If the wander is 75218334Speter * less than the wander threshold for four consecutive 75318334Speter * intervals, the interval is doubled; if it is greater than the 75418334Speter * threshold for four consecutive intervals, the interval is 75518334Speter * halved. The scaled frequency offset is converted to frequency 75618334Speter * offset. The stability metric is calculated as the average of 75718334Speter * recent frequency changes, but is used only for performance 75818334Speter * monitoring. 75918334Speter */ 76018334Speter L_LINT(ftemp, v_nsec); 76118334Speter L_RSHIFT(ftemp, pps_shift); 76218334Speter L_SUB(ftemp, pps_freq); 76318334Speter u_nsec = L_GINT(ftemp); 76418334Speter if (u_nsec > MAXWANDER) { 76518334Speter L_LINT(ftemp, MAXWANDER); 76618334Speter pps_intcnt--; 76718334Speter time_status |= STA_PPSWANDER; 76818334Speter pps_stbcnt++; 76918334Speter } else if (u_nsec < -MAXWANDER) { 77018334Speter L_LINT(ftemp, -MAXWANDER); 77118334Speter pps_intcnt--; 77218334Speter time_status |= STA_PPSWANDER; 77318334Speter pps_stbcnt++; 77418334Speter } else { 77518334Speter pps_intcnt++; 77618334Speter } 77718334Speter if (pps_intcnt >= 4) { 77818334Speter pps_intcnt = 4; 77918334Speter if (pps_shift < PPS_FAVGMAX) { 78018334Speter pps_shift++; 78118334Speter pps_intcnt = 0; 78218334Speter } 78318334Speter } else if (pps_intcnt <= -4) { 78418334Speter pps_intcnt = -4; 78518334Speter if (pps_shift > PPS_FAVG) { 78618334Speter pps_shift--; 78718334Speter pps_intcnt = 0; 78818334Speter } 78918334Speter } 79018334Speter if (u_nsec < 0) 79118334Speter u_nsec = -u_nsec; 79218334Speter pps_stabil += (u_nsec * SCALE_PPM - pps_stabil) >> PPS_FAVG; 79318334Speter 79418334Speter /* 79518334Speter * The frequency offset is averaged into the PPS frequency. If 79618334Speter * enabled, the system clock frequency is updated as well. 79718334Speter */ 79818334Speter L_RSHIFT(ftemp, 1); 79918334Speter L_ADD(pps_freq, ftemp); 80018334Speter u_nsec = L_GINT(pps_freq); 80118334Speter if (u_nsec > MAXFREQ) 80218334Speter L_LINT(pps_freq, MAXFREQ); 80318334Speter else if (u_nsec < -MAXFREQ) 80418334Speter L_LINT(pps_freq, -MAXFREQ); 80518334Speter if (time_status & STA_PPSFREQ) 80618334Speter time_freq = pps_freq; 80718334Speter} 80818334Speter#endif /* PPS_SYNC */ 80918334Speter