Home | History | Annotate | Line # | Download | only in kern
kern_tc.c revision 1.22
      1 /* $NetBSD: kern_tc.c,v 1.22 2007/11/15 20:12:04 ad Exp $ */
      2 
      3 /*-
      4  * ----------------------------------------------------------------------------
      5  * "THE BEER-WARE LICENSE" (Revision 42):
      6  * <phk (at) FreeBSD.ORG> wrote this file.  As long as you retain this notice you
      7  * can do whatever you want with this stuff. If we meet some day, and you think
      8  * this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp
      9  * ---------------------------------------------------------------------------
     10  */
     11 
     12 #include <sys/cdefs.h>
     13 /* __FBSDID("$FreeBSD: src/sys/kern/kern_tc.c,v 1.166 2005/09/19 22:16:31 andre Exp $"); */
     14 __KERNEL_RCSID(0, "$NetBSD: kern_tc.c,v 1.22 2007/11/15 20:12:04 ad Exp $");
     15 
     16 #include "opt_ntp.h"
     17 
     18 #include <sys/param.h>
     19 #ifdef __HAVE_TIMECOUNTER	/* XXX */
     20 #include <sys/kernel.h>
     21 #include <sys/reboot.h>	/* XXX just to get AB_VERBOSE */
     22 #include <sys/sysctl.h>
     23 #include <sys/syslog.h>
     24 #include <sys/systm.h>
     25 #include <sys/timepps.h>
     26 #include <sys/timetc.h>
     27 #include <sys/timex.h>
     28 #include <sys/evcnt.h>
     29 #include <sys/kauth.h>
     30 
     31 /*
     32  * A large step happens on boot.  This constant detects such steps.
     33  * It is relatively small so that ntp_update_second gets called enough
     34  * in the typical 'missed a couple of seconds' case, but doesn't loop
     35  * forever when the time step is large.
     36  */
     37 #define LARGE_STEP	200
     38 
     39 /*
     40  * Implement a dummy timecounter which we can use until we get a real one
     41  * in the air.  This allows the console and other early stuff to use
     42  * time services.
     43  */
     44 
     45 static u_int
     46 dummy_get_timecount(struct timecounter *tc)
     47 {
     48 	static u_int now;
     49 
     50 	return (++now);
     51 }
     52 
     53 static struct timecounter dummy_timecounter = {
     54 	dummy_get_timecount, 0, ~0u, 1000000, "dummy", -1000000, NULL, NULL,
     55 };
     56 
     57 struct timehands {
     58 	/* These fields must be initialized by the driver. */
     59 	struct timecounter	*th_counter;
     60 	int64_t			th_adjustment;
     61 	u_int64_t		th_scale;
     62 	u_int	 		th_offset_count;
     63 	struct bintime		th_offset;
     64 	struct timeval		th_microtime;
     65 	struct timespec		th_nanotime;
     66 	/* Fields not to be copied in tc_windup start with th_generation. */
     67 	volatile u_int		th_generation;
     68 	struct timehands	*th_next;
     69 };
     70 
     71 static struct timehands th0;
     72 static struct timehands th9 = { .th_next = &th0, };
     73 static struct timehands th8 = { .th_next = &th9, };
     74 static struct timehands th7 = { .th_next = &th8, };
     75 static struct timehands th6 = { .th_next = &th7, };
     76 static struct timehands th5 = { .th_next = &th6, };
     77 static struct timehands th4 = { .th_next = &th5, };
     78 static struct timehands th3 = { .th_next = &th4, };
     79 static struct timehands th2 = { .th_next = &th3, };
     80 static struct timehands th1 = { .th_next = &th2, };
     81 static struct timehands th0 = {
     82 	.th_counter = &dummy_timecounter,
     83 	.th_scale = (uint64_t)-1 / 1000000,
     84 	.th_offset = { .sec = 1, .frac = 0 },
     85 	.th_generation = 1,
     86 	.th_next = &th1,
     87 };
     88 
     89 static struct timehands *volatile timehands = &th0;
     90 struct timecounter *timecounter = &dummy_timecounter;
     91 static struct timecounter *timecounters = &dummy_timecounter;
     92 
     93 time_t time_second = 1;
     94 time_t time_uptime = 1;
     95 
     96 static struct bintime timebasebin;
     97 
     98 static int timestepwarnings;
     99 
    100 #ifdef __FreeBSD__
    101 SYSCTL_INT(_kern_timecounter, OID_AUTO, stepwarnings, CTLFLAG_RW,
    102     &timestepwarnings, 0, "");
    103 #endif /* __FreeBSD__ */
    104 
    105 /*
    106  * sysctl helper routine for kern.timercounter.current
    107  */
    108 static int
    109 sysctl_kern_timecounter_hardware(SYSCTLFN_ARGS)
    110 {
    111 	struct sysctlnode node;
    112 	int error;
    113 	char newname[MAX_TCNAMELEN];
    114 	struct timecounter *newtc, *tc;
    115 
    116 	tc = timecounter;
    117 
    118 	strlcpy(newname, tc->tc_name, sizeof(newname));
    119 
    120 	node = *rnode;
    121 	node.sysctl_data = newname;
    122 	node.sysctl_size = sizeof(newname);
    123 
    124 	error = sysctl_lookup(SYSCTLFN_CALL(&node));
    125 
    126 	if (error ||
    127 	    newp == NULL ||
    128 	    strncmp(newname, tc->tc_name, sizeof(newname)) == 0)
    129 		return error;
    130 
    131 	if (l != NULL && (error = kauth_authorize_generic(l->l_cred,
    132 	    KAUTH_GENERIC_ISSUSER, NULL)) != 0)
    133 		return (error);
    134 
    135 	if (!cold)
    136 		mutex_enter(&time_lock);
    137 	for (newtc = timecounters; newtc != NULL; newtc = newtc->tc_next) {
    138 		if (strcmp(newname, newtc->tc_name) != 0)
    139 			continue;
    140 		/* Warm up new timecounter. */
    141 		(void)newtc->tc_get_timecount(newtc);
    142 		(void)newtc->tc_get_timecount(newtc);
    143 		timecounter = newtc;
    144 		error = 0;
    145 	} else
    146 		error = EINVAL;
    147 	if (!cold)
    148 		mutex_exit(&time_lock);
    149 	return error;
    150 }
    151 
    152 static int
    153 sysctl_kern_timecounter_choice(SYSCTLFN_ARGS)
    154 {
    155 	char buf[MAX_TCNAMELEN+48];
    156 	char *where = oldp;
    157 	const char *spc;
    158 	struct timecounter *tc;
    159 	size_t needed, left, slen;
    160 	int error;
    161 
    162 	if (newp != NULL)
    163 		return (EPERM);
    164 	if (namelen != 0)
    165 		return (EINVAL);
    166 
    167 	spc = "";
    168 	error = 0;
    169 	needed = 0;
    170 	left = *oldlenp;
    171 
    172 	mutex_enter(&time_lock);
    173 	for (tc = timecounters; error == 0 && tc != NULL; tc = tc->tc_next) {
    174 		if (where == NULL) {
    175 			needed += sizeof(buf);  /* be conservative */
    176 		} else {
    177 			slen = snprintf(buf, sizeof(buf), "%s%s(q=%d, f=%" PRId64
    178 					" Hz)", spc, tc->tc_name, tc->tc_quality,
    179 					tc->tc_frequency);
    180 			if (left < slen + 1)
    181 				break;
    182 			/* XXX use sysctl_copyout? (from sysctl_hw_disknames) */
    183 			/* XXX copyout with held lock. */
    184 			error = copyout(buf, where, slen + 1);
    185 			spc = " ";
    186 			where += slen;
    187 			needed += slen;
    188 			left -= slen;
    189 		}
    190 	}
    191 	mutex_exit(&time_lock);
    192 
    193 	*oldlenp = needed;
    194 	return (error);
    195 }
    196 
    197 SYSCTL_SETUP(sysctl_timecounter_setup, "sysctl timecounter setup")
    198 {
    199 	const struct sysctlnode *node;
    200 
    201 	sysctl_createv(clog, 0, NULL, &node,
    202 		       CTLFLAG_PERMANENT,
    203 		       CTLTYPE_NODE, "timecounter",
    204 		       SYSCTL_DESCR("time counter information"),
    205 		       NULL, 0, NULL, 0,
    206 		       CTL_KERN, CTL_CREATE, CTL_EOL);
    207 
    208 	if (node != NULL) {
    209 		sysctl_createv(clog, 0, NULL, NULL,
    210 			       CTLFLAG_PERMANENT,
    211 			       CTLTYPE_STRING, "choice",
    212 			       SYSCTL_DESCR("available counters"),
    213 			       sysctl_kern_timecounter_choice, 0, NULL, 0,
    214 			       CTL_KERN, node->sysctl_num, CTL_CREATE, CTL_EOL);
    215 
    216 		sysctl_createv(clog, 0, NULL, NULL,
    217 			       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
    218 			       CTLTYPE_STRING, "hardware",
    219 			       SYSCTL_DESCR("currently active time counter"),
    220 			       sysctl_kern_timecounter_hardware, 0, NULL, MAX_TCNAMELEN,
    221 			       CTL_KERN, node->sysctl_num, CTL_CREATE, CTL_EOL);
    222 
    223 		sysctl_createv(clog, 0, NULL, NULL,
    224 			       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
    225 			       CTLTYPE_INT, "timestepwarnings",
    226 			       SYSCTL_DESCR("log time steps"),
    227 			       NULL, 0, &timestepwarnings, 0,
    228 			       CTL_KERN, node->sysctl_num, CTL_CREATE, CTL_EOL);
    229 	}
    230 }
    231 
    232 #define	TC_STATS(name)							\
    233 static struct evcnt n##name =						\
    234     EVCNT_INITIALIZER(EVCNT_TYPE_MISC, NULL, "timecounter", #name);	\
    235 EVCNT_ATTACH_STATIC(n##name)
    236 
    237 TC_STATS(binuptime);    TC_STATS(nanouptime);    TC_STATS(microuptime);
    238 TC_STATS(bintime);      TC_STATS(nanotime);      TC_STATS(microtime);
    239 TC_STATS(getbinuptime); TC_STATS(getnanouptime); TC_STATS(getmicrouptime);
    240 TC_STATS(getbintime);   TC_STATS(getnanotime);   TC_STATS(getmicrotime);
    241 TC_STATS(setclock);
    242 
    243 #undef TC_STATS
    244 
    245 static void tc_windup(void);
    246 
    247 /*
    248  * Return the difference between the timehands' counter value now and what
    249  * was when we copied it to the timehands' offset_count.
    250  */
    251 static __inline u_int
    252 tc_delta(struct timehands *th)
    253 {
    254 	struct timecounter *tc;
    255 
    256 	tc = th->th_counter;
    257 	return ((tc->tc_get_timecount(tc) -
    258 		 th->th_offset_count) & tc->tc_counter_mask);
    259 }
    260 
    261 /*
    262  * Functions for reading the time.  We have to loop until we are sure that
    263  * the timehands that we operated on was not updated under our feet.  See
    264  * the comment in <sys/timevar.h> for a description of these 12 functions.
    265  */
    266 
    267 void
    268 binuptime(struct bintime *bt)
    269 {
    270 	struct timehands *th;
    271 	u_int gen;
    272 
    273 	nbinuptime.ev_count++;
    274 	do {
    275 		th = timehands;
    276 		gen = th->th_generation;
    277 		mb_read();
    278 		*bt = th->th_offset;
    279 		bintime_addx(bt, th->th_scale * tc_delta(th));
    280 		mb_read();
    281 	} while (gen == 0 || gen != th->th_generation);
    282 }
    283 
    284 void
    285 nanouptime(struct timespec *tsp)
    286 {
    287 	struct bintime bt;
    288 
    289 	nnanouptime.ev_count++;
    290 	binuptime(&bt);
    291 	bintime2timespec(&bt, tsp);
    292 }
    293 
    294 void
    295 microuptime(struct timeval *tvp)
    296 {
    297 	struct bintime bt;
    298 
    299 	nmicrouptime.ev_count++;
    300 	binuptime(&bt);
    301 	bintime2timeval(&bt, tvp);
    302 }
    303 
    304 void
    305 bintime(struct bintime *bt)
    306 {
    307 
    308 	nbintime.ev_count++;
    309 	binuptime(bt);
    310 	bintime_add(bt, &timebasebin);
    311 }
    312 
    313 void
    314 nanotime(struct timespec *tsp)
    315 {
    316 	struct bintime bt;
    317 
    318 	nnanotime.ev_count++;
    319 	bintime(&bt);
    320 	bintime2timespec(&bt, tsp);
    321 }
    322 
    323 void
    324 microtime(struct timeval *tvp)
    325 {
    326 	struct bintime bt;
    327 
    328 	nmicrotime.ev_count++;
    329 	bintime(&bt);
    330 	bintime2timeval(&bt, tvp);
    331 }
    332 
    333 void
    334 getbinuptime(struct bintime *bt)
    335 {
    336 	struct timehands *th;
    337 	u_int gen;
    338 
    339 	ngetbinuptime.ev_count++;
    340 	do {
    341 		th = timehands;
    342 		gen = th->th_generation;
    343 		mb_read();
    344 		*bt = th->th_offset;
    345 		mb_read();
    346 	} while (gen == 0 || gen != th->th_generation);
    347 }
    348 
    349 void
    350 getnanouptime(struct timespec *tsp)
    351 {
    352 	struct timehands *th;
    353 	u_int gen;
    354 
    355 	ngetnanouptime.ev_count++;
    356 	do {
    357 		th = timehands;
    358 		gen = th->th_generation;
    359 		mb_read();
    360 		bintime2timespec(&th->th_offset, tsp);
    361 		mb_read();
    362 	} while (gen == 0 || gen != th->th_generation);
    363 }
    364 
    365 void
    366 getmicrouptime(struct timeval *tvp)
    367 {
    368 	struct timehands *th;
    369 	u_int gen;
    370 
    371 	ngetmicrouptime.ev_count++;
    372 	do {
    373 		th = timehands;
    374 		gen = th->th_generation;
    375 		mb_read();
    376 		bintime2timeval(&th->th_offset, tvp);
    377 		mb_read();
    378 	} while (gen == 0 || gen != th->th_generation);
    379 }
    380 
    381 void
    382 getbintime(struct bintime *bt)
    383 {
    384 	struct timehands *th;
    385 	u_int gen;
    386 
    387 	ngetbintime.ev_count++;
    388 	do {
    389 		th = timehands;
    390 		gen = th->th_generation;
    391 		mb_read();
    392 		*bt = th->th_offset;
    393 		mb_read();
    394 	} while (gen == 0 || gen != th->th_generation);
    395 	bintime_add(bt, &timebasebin);
    396 }
    397 
    398 void
    399 getnanotime(struct timespec *tsp)
    400 {
    401 	struct timehands *th;
    402 	u_int gen;
    403 
    404 	ngetnanotime.ev_count++;
    405 	do {
    406 		th = timehands;
    407 		gen = th->th_generation;
    408 		mb_read();
    409 		*tsp = th->th_nanotime;
    410 		mb_read();
    411 	} while (gen == 0 || gen != th->th_generation);
    412 }
    413 
    414 void
    415 getmicrotime(struct timeval *tvp)
    416 {
    417 	struct timehands *th;
    418 	u_int gen;
    419 
    420 	ngetmicrotime.ev_count++;
    421 	do {
    422 		th = timehands;
    423 		gen = th->th_generation;
    424 		mb_read();
    425 		*tvp = th->th_microtime;
    426 		mb_read();
    427 	} while (gen == 0 || gen != th->th_generation);
    428 }
    429 
    430 /*
    431  * Initialize a new timecounter and possibly use it.
    432  */
    433 void
    434 tc_init(struct timecounter *tc)
    435 {
    436 	u_int u;
    437 	int s;
    438 
    439 	u = tc->tc_frequency / tc->tc_counter_mask;
    440 	/* XXX: We need some margin here, 10% is a guess */
    441 	u *= 11;
    442 	u /= 10;
    443 	if (u > hz && tc->tc_quality >= 0) {
    444 		tc->tc_quality = -2000;
    445 		aprint_verbose(
    446 		    "timecounter: Timecounter \"%s\" frequency %ju Hz",
    447 			    tc->tc_name, (uintmax_t)tc->tc_frequency);
    448 		aprint_verbose(" -- Insufficient hz, needs at least %u\n", u);
    449 	} else if (tc->tc_quality >= 0 || bootverbose) {
    450 		aprint_verbose(
    451 		    "timecounter: Timecounter \"%s\" frequency %ju Hz "
    452 		    "quality %d\n", tc->tc_name, (uintmax_t)tc->tc_frequency,
    453 		    tc->tc_quality);
    454 	}
    455 
    456 	mutex_enter(&time_lock);
    457 	s = splsched();
    458 	tc->tc_next = timecounters;
    459 	timecounters = tc;
    460 	/*
    461 	 * Never automatically use a timecounter with negative quality.
    462 	 * Even though we run on the dummy counter, switching here may be
    463 	 * worse since this timecounter may not be monotonous.
    464 	 */
    465 	if (tc->tc_quality >= 0 && (tc->tc_quality > timecounter->tc_quality ||
    466 	    tc->tc_frequency > timecounter->tc_frequency)) {
    467 		(void)tc->tc_get_timecount(tc);
    468 		(void)tc->tc_get_timecount(tc);
    469 		timecounter = tc;
    470 		tc_windup();
    471 	}
    472 	splx(s);
    473 	mutex_exit(&time_lock);
    474 }
    475 
    476 /* Report the frequency of the current timecounter. */
    477 u_int64_t
    478 tc_getfrequency(void)
    479 {
    480 
    481 	return (timehands->th_counter->tc_frequency);
    482 }
    483 
    484 /*
    485  * Step our concept of UTC.  This is done by modifying our estimate of
    486  * when we booted.
    487  * XXX: not locked.
    488  */
    489 void
    490 tc_setclock(struct timespec *ts)
    491 {
    492 	struct timespec ts2;
    493 	struct bintime bt, bt2;
    494 
    495 	nsetclock.ev_count++;
    496 	binuptime(&bt2);
    497 	timespec2bintime(ts, &bt);
    498 	bintime_sub(&bt, &bt2);
    499 	bintime_add(&bt2, &timebasebin);
    500 	timebasebin = bt;
    501 
    502 	/* XXX fiddle all the little crinkly bits around the fiords... */
    503 	tc_windup();
    504 	if (timestepwarnings) {
    505 		bintime2timespec(&bt2, &ts2);
    506 		log(LOG_INFO, "Time stepped from %jd.%09ld to %jd.%09ld\n",
    507 		    (intmax_t)ts2.tv_sec, ts2.tv_nsec,
    508 		    (intmax_t)ts->tv_sec, ts->tv_nsec);
    509 	}
    510 }
    511 
    512 /*
    513  * Initialize the next struct timehands in the ring and make
    514  * it the active timehands.  Along the way we might switch to a different
    515  * timecounter and/or do seconds processing in NTP.  Slightly magic.
    516  */
    517 static void
    518 tc_windup(void)
    519 {
    520 	struct bintime bt;
    521 	struct timehands *th, *tho;
    522 	u_int64_t scale;
    523 	u_int delta, ncount, ogen;
    524 	int i, s_update;
    525 	time_t t;
    526 
    527 	s_update = 0;
    528 
    529 	/*
    530 	 * Make the next timehands a copy of the current one, but do not
    531 	 * overwrite the generation or next pointer.  While we update
    532 	 * the contents, the generation must be zero.  Ensure global
    533 	 * visibility of the generation before proceeding.
    534 	 */
    535 	tho = timehands;
    536 	th = tho->th_next;
    537 	ogen = th->th_generation;
    538 	th->th_generation = 0;
    539 	mb_write();
    540 	bcopy(tho, th, offsetof(struct timehands, th_generation));
    541 
    542 	/*
    543 	 * Capture a timecounter delta on the current timecounter and if
    544 	 * changing timecounters, a counter value from the new timecounter.
    545 	 * Update the offset fields accordingly.
    546 	 */
    547 	delta = tc_delta(th);
    548 	if (th->th_counter != timecounter)
    549 		ncount = timecounter->tc_get_timecount(timecounter);
    550 	else
    551 		ncount = 0;
    552 	th->th_offset_count += delta;
    553 	th->th_offset_count &= th->th_counter->tc_counter_mask;
    554 	bintime_addx(&th->th_offset, th->th_scale * delta);
    555 
    556 	/*
    557 	 * Hardware latching timecounters may not generate interrupts on
    558 	 * PPS events, so instead we poll them.  There is a finite risk that
    559 	 * the hardware might capture a count which is later than the one we
    560 	 * got above, and therefore possibly in the next NTP second which might
    561 	 * have a different rate than the current NTP second.  It doesn't
    562 	 * matter in practice.
    563 	 */
    564 	if (tho->th_counter->tc_poll_pps)
    565 		tho->th_counter->tc_poll_pps(tho->th_counter);
    566 
    567 	/*
    568 	 * Deal with NTP second processing.  The for loop normally
    569 	 * iterates at most once, but in extreme situations it might
    570 	 * keep NTP sane if timeouts are not run for several seconds.
    571 	 * At boot, the time step can be large when the TOD hardware
    572 	 * has been read, so on really large steps, we call
    573 	 * ntp_update_second only twice.  We need to call it twice in
    574 	 * case we missed a leap second.
    575 	 * If NTP is not compiled in ntp_update_second still calculates
    576 	 * the adjustment resulting from adjtime() calls.
    577 	 */
    578 	bt = th->th_offset;
    579 	bintime_add(&bt, &timebasebin);
    580 	i = bt.sec - tho->th_microtime.tv_sec;
    581 	if (i > LARGE_STEP)
    582 		i = 2;
    583 	for (; i > 0; i--) {
    584 		t = bt.sec;
    585 		ntp_update_second(&th->th_adjustment, &bt.sec);
    586 		s_update = 1;
    587 		if (bt.sec != t)
    588 			timebasebin.sec += bt.sec - t;
    589 	}
    590 
    591 	/* Update the UTC timestamps used by the get*() functions. */
    592 	/* XXX shouldn't do this here.  Should force non-`get' versions. */
    593 	bintime2timeval(&bt, &th->th_microtime);
    594 	bintime2timespec(&bt, &th->th_nanotime);
    595 
    596 	/* Now is a good time to change timecounters. */
    597 	if (th->th_counter != timecounter) {
    598 		th->th_counter = timecounter;
    599 		th->th_offset_count = ncount;
    600 		s_update = 1;
    601 	}
    602 
    603 	/*-
    604 	 * Recalculate the scaling factor.  We want the number of 1/2^64
    605 	 * fractions of a second per period of the hardware counter, taking
    606 	 * into account the th_adjustment factor which the NTP PLL/adjtime(2)
    607 	 * processing provides us with.
    608 	 *
    609 	 * The th_adjustment is nanoseconds per second with 32 bit binary
    610 	 * fraction and we want 64 bit binary fraction of second:
    611 	 *
    612 	 *	 x = a * 2^32 / 10^9 = a * 4.294967296
    613 	 *
    614 	 * The range of th_adjustment is +/- 5000PPM so inside a 64bit int
    615 	 * we can only multiply by about 850 without overflowing, but that
    616 	 * leaves suitably precise fractions for multiply before divide.
    617 	 *
    618 	 * Divide before multiply with a fraction of 2199/512 results in a
    619 	 * systematic undercompensation of 10PPM of th_adjustment.  On a
    620 	 * 5000PPM adjustment this is a 0.05PPM error.  This is acceptable.
    621  	 *
    622 	 * We happily sacrifice the lowest of the 64 bits of our result
    623 	 * to the goddess of code clarity.
    624 	 *
    625 	 */
    626 	if (s_update) {
    627 		scale = (u_int64_t)1 << 63;
    628 		scale += (th->th_adjustment / 1024) * 2199;
    629 		scale /= th->th_counter->tc_frequency;
    630 		th->th_scale = scale * 2;
    631 	}
    632 	/*
    633 	 * Now that the struct timehands is again consistent, set the new
    634 	 * generation number, making sure to not make it zero.  Ensure
    635 	 * changes are globally visible before changing.
    636 	 */
    637 	if (++ogen == 0)
    638 		ogen = 1;
    639 	mb_write();
    640 	th->th_generation = ogen;
    641 
    642 	/*
    643 	 * Go live with the new struct timehands.  Ensure changes are
    644 	 * globally visible before changing.
    645 	 */
    646 	time_second = th->th_microtime.tv_sec;
    647 	time_uptime = th->th_offset.sec;
    648 	mb_write();
    649 	timehands = th;
    650 }
    651 
    652 /*
    653  * RFC 2783 PPS-API implementation.
    654  */
    655 
    656 int
    657 pps_ioctl(u_long cmd, void *data, struct pps_state *pps)
    658 {
    659 	pps_params_t *app;
    660 	pps_info_t *pipi;
    661 #ifdef PPS_SYNC
    662 	int *epi;
    663 #endif
    664 
    665 	KASSERT(pps != NULL); /* XXX ("NULL pps pointer in pps_ioctl") */
    666 	switch (cmd) {
    667 	case PPS_IOC_CREATE:
    668 		return (0);
    669 	case PPS_IOC_DESTROY:
    670 		return (0);
    671 	case PPS_IOC_SETPARAMS:
    672 		app = (pps_params_t *)data;
    673 		if (app->mode & ~pps->ppscap)
    674 			return (EINVAL);
    675 		pps->ppsparam = *app;
    676 		return (0);
    677 	case PPS_IOC_GETPARAMS:
    678 		app = (pps_params_t *)data;
    679 		*app = pps->ppsparam;
    680 		app->api_version = PPS_API_VERS_1;
    681 		return (0);
    682 	case PPS_IOC_GETCAP:
    683 		*(int*)data = pps->ppscap;
    684 		return (0);
    685 	case PPS_IOC_FETCH:
    686 		pipi = (pps_info_t *)data;
    687 		pps->ppsinfo.current_mode = pps->ppsparam.mode;
    688 		*pipi = pps->ppsinfo;
    689 		return (0);
    690 	case PPS_IOC_KCBIND:
    691 #ifdef PPS_SYNC
    692 		epi = (int *)data;
    693 		/* XXX Only root should be able to do this */
    694 		if (*epi & ~pps->ppscap)
    695 			return (EINVAL);
    696 		pps->kcmode = *epi;
    697 		return (0);
    698 #else
    699 		return (EOPNOTSUPP);
    700 #endif
    701 	default:
    702 		return (EPASSTHROUGH);
    703 	}
    704 }
    705 
    706 void
    707 pps_init(struct pps_state *pps)
    708 {
    709 	pps->ppscap |= PPS_TSFMT_TSPEC;
    710 	if (pps->ppscap & PPS_CAPTUREASSERT)
    711 		pps->ppscap |= PPS_OFFSETASSERT;
    712 	if (pps->ppscap & PPS_CAPTURECLEAR)
    713 		pps->ppscap |= PPS_OFFSETCLEAR;
    714 }
    715 
    716 void
    717 pps_capture(struct pps_state *pps)
    718 {
    719 	struct timehands *th;
    720 
    721 	KASSERT(pps != NULL); /* XXX ("NULL pps pointer in pps_capture") */
    722 	th = timehands;
    723 	pps->capgen = th->th_generation;
    724 	pps->capth = th;
    725 	pps->capcount = th->th_counter->tc_get_timecount(th->th_counter);
    726 	if (pps->capgen != th->th_generation)
    727 		pps->capgen = 0;
    728 }
    729 
    730 void
    731 pps_event(struct pps_state *pps, int event)
    732 {
    733 	struct bintime bt;
    734 	struct timespec ts, *tsp, *osp;
    735 	u_int tcount, *pcount;
    736 	int foff, fhard;
    737 	pps_seq_t *pseq;
    738 
    739 	KASSERT(pps != NULL); /* XXX ("NULL pps pointer in pps_event") */
    740 	/* If the timecounter was wound up underneath us, bail out. */
    741 	if (pps->capgen == 0 || pps->capgen != pps->capth->th_generation)
    742 		return;
    743 
    744 	/* Things would be easier with arrays. */
    745 	if (event == PPS_CAPTUREASSERT) {
    746 		tsp = &pps->ppsinfo.assert_timestamp;
    747 		osp = &pps->ppsparam.assert_offset;
    748 		foff = pps->ppsparam.mode & PPS_OFFSETASSERT;
    749 		fhard = pps->kcmode & PPS_CAPTUREASSERT;
    750 		pcount = &pps->ppscount[0];
    751 		pseq = &pps->ppsinfo.assert_sequence;
    752 	} else {
    753 		tsp = &pps->ppsinfo.clear_timestamp;
    754 		osp = &pps->ppsparam.clear_offset;
    755 		foff = pps->ppsparam.mode & PPS_OFFSETCLEAR;
    756 		fhard = pps->kcmode & PPS_CAPTURECLEAR;
    757 		pcount = &pps->ppscount[1];
    758 		pseq = &pps->ppsinfo.clear_sequence;
    759 	}
    760 
    761 	/*
    762 	 * If the timecounter changed, we cannot compare the count values, so
    763 	 * we have to drop the rest of the PPS-stuff until the next event.
    764 	 */
    765 	if (pps->ppstc != pps->capth->th_counter) {
    766 		pps->ppstc = pps->capth->th_counter;
    767 		*pcount = pps->capcount;
    768 		pps->ppscount[2] = pps->capcount;
    769 		return;
    770 	}
    771 
    772 	/* Convert the count to a timespec. */
    773 	tcount = pps->capcount - pps->capth->th_offset_count;
    774 	tcount &= pps->capth->th_counter->tc_counter_mask;
    775 	bt = pps->capth->th_offset;
    776 	bintime_addx(&bt, pps->capth->th_scale * tcount);
    777 	bintime_add(&bt, &timebasebin);
    778 	bintime2timespec(&bt, &ts);
    779 
    780 	/* If the timecounter was wound up underneath us, bail out. */
    781 	if (pps->capgen != pps->capth->th_generation)
    782 		return;
    783 
    784 	*pcount = pps->capcount;
    785 	(*pseq)++;
    786 	*tsp = ts;
    787 
    788 	if (foff) {
    789 		timespecadd(tsp, osp, tsp);
    790 		if (tsp->tv_nsec < 0) {
    791 			tsp->tv_nsec += 1000000000;
    792 			tsp->tv_sec -= 1;
    793 		}
    794 	}
    795 #ifdef PPS_SYNC
    796 	if (fhard) {
    797 		u_int64_t scale;
    798 
    799 		/*
    800 		 * Feed the NTP PLL/FLL.
    801 		 * The FLL wants to know how many (hardware) nanoseconds
    802 		 * elapsed since the previous event.
    803 		 */
    804 		tcount = pps->capcount - pps->ppscount[2];
    805 		pps->ppscount[2] = pps->capcount;
    806 		tcount &= pps->capth->th_counter->tc_counter_mask;
    807 		scale = (u_int64_t)1 << 63;
    808 		scale /= pps->capth->th_counter->tc_frequency;
    809 		scale *= 2;
    810 		bt.sec = 0;
    811 		bt.frac = 0;
    812 		bintime_addx(&bt, scale * tcount);
    813 		bintime2timespec(&bt, &ts);
    814 		hardpps(tsp, ts.tv_nsec + 1000000000 * ts.tv_sec);
    815 	}
    816 #endif
    817 }
    818 
    819 /*
    820  * Timecounters need to be updated every so often to prevent the hardware
    821  * counter from overflowing.  Updating also recalculates the cached values
    822  * used by the get*() family of functions, so their precision depends on
    823  * the update frequency.
    824  */
    825 
    826 static int tc_tick;
    827 
    828 void
    829 tc_ticktock(void)
    830 {
    831 	static int count;
    832 
    833 	if (++count < tc_tick)
    834 		return;
    835 	count = 0;
    836 	tc_windup();
    837 }
    838 
    839 void
    840 inittimecounter(void)
    841 {
    842 	u_int p;
    843 
    844 	/*
    845 	 * Set the initial timeout to
    846 	 * max(1, <approx. number of hardclock ticks in a millisecond>).
    847 	 * People should probably not use the sysctl to set the timeout
    848 	 * to smaller than its inital value, since that value is the
    849 	 * smallest reasonable one.  If they want better timestamps they
    850 	 * should use the non-"get"* functions.
    851 	 */
    852 	if (hz > 1000)
    853 		tc_tick = (hz + 500) / 1000;
    854 	else
    855 		tc_tick = 1;
    856 	p = (tc_tick * 1000000) / hz;
    857 	aprint_verbose("timecounter: Timecounters tick every %d.%03u msec\n",
    858 	    p / 1000, p % 1000);
    859 
    860 	/* warm up new timecounter (again) and get rolling. */
    861 	(void)timecounter->tc_get_timecount(timecounter);
    862 	(void)timecounter->tc_get_timecount(timecounter);
    863 }
    864 
    865 #endif /* __HAVE_TIMECOUNTER */
    866