svn commit: r285424 - head/sys/kern

Ian Lepore ian at FreeBSD.org
Sun Jul 12 18:38:18 UTC 2015


Author: ian
Date: Sun Jul 12 18:38:17 2015
New Revision: 285424
URL: https://svnweb.freebsd.org/changeset/base/285424

Log:
  Use the monotonic (uptime) counter rather than time-of-day to measure elapsed
  time between ntp_adjtime() clock offset adjustments.  This eliminates spurious
  frequency steering after a large clock step (such as a 1970->2015 step on a
  system with no battery-backed clock hardware).
  
  This problem was discovered after the import of ntpd 4.2.8, which does things
  in a slightly different (but still correct) order than the 4.2.4 we had
  previously.  In particular, 4.2.4 would step the clock then immediately after
  use ntp_adjtime() to set the frequency and offset to zero, which captured the
  post-step time-of-day as a side effect.  In 4.2.8, ntpd sets frequency and
  offset to zero before any initial clock step, capturing the time as 1970-ish,
  then when it next calls ntp_adjtime() it's with a non-zero offset measurement.
  This non-zero value gets multiplied by the apparent 45-year interval, which
  blows up into a completely bogus frequency steer.  That gets clamped to
  500ppm, but that's still enough to make the clock drift so fast that ntpd has
  to keep stepping it every few minutes to compensate.

Modified:
  head/sys/kern/kern_ntptime.c

Modified: head/sys/kern/kern_ntptime.c
==============================================================================
--- head/sys/kern/kern_ntptime.c	Sun Jul 12 18:32:16 2015	(r285423)
+++ head/sys/kern/kern_ntptime.c	Sun Jul 12 18:38:17 2015	(r285424)
@@ -155,7 +155,7 @@ static long time_constant;		/* poll inte
 static long time_precision = 1;		/* clock precision (ns) */
 static long time_maxerror = MAXPHASE / 1000; /* maximum error (us) */
 long time_esterror = MAXPHASE / 1000; /* estimated error (us) */
-static long time_reftime;		/* time at last adjustment (s) */
+static long time_reftime;		/* uptime at last adjustment (s) */
 static l_fp time_offset;		/* time offset (ns) */
 static l_fp time_freq;			/* frequency offset (ns/s) */
 static l_fp time_adj;			/* tick adjust (ns/s) */
@@ -696,12 +696,12 @@ hardupdate(offset)
 	 * otherwise, the argument offset is used to compute it.
 	 */
 	if (time_status & STA_PPSFREQ && time_status & STA_PPSSIGNAL) {
-		time_reftime = time_second;
+		time_reftime = time_uptime;
 		return;
 	}
 	if (time_status & STA_FREQHOLD || time_reftime == 0)
-		time_reftime = time_second;
-	mtemp = time_second - time_reftime;
+		time_reftime = time_uptime;
+	mtemp = time_uptime - time_reftime;
 	L_LINT(ftemp, time_monitor);
 	L_RSHIFT(ftemp, (SHIFT_PLL + 2 + time_constant) << 1);
 	L_MPY(ftemp, mtemp);
@@ -714,7 +714,7 @@ hardupdate(offset)
 		L_ADD(time_freq, ftemp);
 		time_status |= STA_MODE;
 	}
-	time_reftime = time_second;
+	time_reftime = time_uptime;
 	if (L_GINT(time_freq) > MAXFREQ)
 		L_LINT(time_freq, MAXFREQ);
 	else if (L_GINT(time_freq) < -MAXFREQ)


More information about the svn-src-head mailing list