xref: /freebsd/sys/kern/kern_tc.c (revision 6cda760f09d1486cb72c8f9dca51d7de0cc81539)
139acc78aSPoul-Henning Kamp /*-
291266b96SPoul-Henning Kamp  * ----------------------------------------------------------------------------
391266b96SPoul-Henning Kamp  * "THE BEER-WARE LICENSE" (Revision 42):
491266b96SPoul-Henning Kamp  * <phk@FreeBSD.ORG> wrote this file.  As long as you retain this notice you
591266b96SPoul-Henning Kamp  * can do whatever you want with this stuff. If we meet some day, and you think
691266b96SPoul-Henning Kamp  * this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp
791266b96SPoul-Henning Kamp  * ----------------------------------------------------------------------------
8df8bae1dSRodney W. Grimes  */
9df8bae1dSRodney W. Grimes 
10677b542eSDavid E. O'Brien #include <sys/cdefs.h>
11677b542eSDavid E. O'Brien __FBSDID("$FreeBSD$");
12677b542eSDavid E. O'Brien 
1332c20357SPoul-Henning Kamp #include "opt_ntp.h"
1432c20357SPoul-Henning Kamp 
15df8bae1dSRodney W. Grimes #include <sys/param.h>
1691266b96SPoul-Henning Kamp #include <sys/kernel.h>
1791266b96SPoul-Henning Kamp #include <sys/sysctl.h>
184e74721cSPoul-Henning Kamp #include <sys/syslog.h>
1991266b96SPoul-Henning Kamp #include <sys/systm.h>
2032c20357SPoul-Henning Kamp #include <sys/timepps.h>
2148e5da55SPoul-Henning Kamp #include <sys/timetc.h>
2239acc78aSPoul-Henning Kamp #include <sys/timex.h>
2339acc78aSPoul-Henning Kamp 
243bac064fSPoul-Henning Kamp /*
25c1cccd1eSWarner Losh  * A large step happens on boot.  This constant detects such steps.
26c1cccd1eSWarner Losh  * It is relatively small so that ntp_update_second gets called enough
27c1cccd1eSWarner Losh  * in the typical 'missed a couple of seconds' case, but doesn't loop
28c1cccd1eSWarner Losh  * forever when the time step is large.
294f2073fbSWarner Losh  */
304f2073fbSWarner Losh #define LARGE_STEP	200
314f2073fbSWarner Losh 
324f2073fbSWarner Losh /*
3362efba6aSPoul-Henning Kamp  * Implement a dummy timecounter which we can use until we get a real one
3462efba6aSPoul-Henning Kamp  * in the air.  This allows the console and other early stuff to use
3562efba6aSPoul-Henning Kamp  * time services.
363bac064fSPoul-Henning Kamp  */
373bac064fSPoul-Henning Kamp 
386b00cf46SPoul-Henning Kamp static u_int
3962efba6aSPoul-Henning Kamp dummy_get_timecount(struct timecounter *tc)
4062efba6aSPoul-Henning Kamp {
416b00cf46SPoul-Henning Kamp 	static u_int now;
4262efba6aSPoul-Henning Kamp 
4362efba6aSPoul-Henning Kamp 	return (++now);
4462efba6aSPoul-Henning Kamp }
4562efba6aSPoul-Henning Kamp 
4662efba6aSPoul-Henning Kamp static struct timecounter dummy_timecounter = {
4778a49a45SPoul-Henning Kamp 	dummy_get_timecount, 0, ~0u, 1000000, "dummy", -1000000
4862efba6aSPoul-Henning Kamp };
4962efba6aSPoul-Henning Kamp 
5062efba6aSPoul-Henning Kamp struct timehands {
5162efba6aSPoul-Henning Kamp 	/* These fields must be initialized by the driver. */
526b00cf46SPoul-Henning Kamp 	struct timecounter	*th_counter;
536b00cf46SPoul-Henning Kamp 	int64_t			th_adjustment;
546b00cf46SPoul-Henning Kamp 	u_int64_t		th_scale;
556b00cf46SPoul-Henning Kamp 	u_int	 		th_offset_count;
566b00cf46SPoul-Henning Kamp 	struct bintime		th_offset;
576b00cf46SPoul-Henning Kamp 	struct timeval		th_microtime;
586b00cf46SPoul-Henning Kamp 	struct timespec		th_nanotime;
5939acc78aSPoul-Henning Kamp 	/* Fields not to be copied in tc_windup start with th_generation. */
606b00cf46SPoul-Henning Kamp 	volatile u_int		th_generation;
616b00cf46SPoul-Henning Kamp 	struct timehands	*th_next;
6262efba6aSPoul-Henning Kamp };
6362efba6aSPoul-Henning Kamp 
645b1c0294SDavid E. O'Brien static struct timehands th0;
6539acc78aSPoul-Henning Kamp static struct timehands th9 = { NULL, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0, &th0};
6639acc78aSPoul-Henning Kamp static struct timehands th8 = { NULL, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0, &th9};
6739acc78aSPoul-Henning Kamp static struct timehands th7 = { NULL, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0, &th8};
6839acc78aSPoul-Henning Kamp static struct timehands th6 = { NULL, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0, &th7};
6939acc78aSPoul-Henning Kamp static struct timehands th5 = { NULL, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0, &th6};
7039acc78aSPoul-Henning Kamp static struct timehands th4 = { NULL, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0, &th5};
7139acc78aSPoul-Henning Kamp static struct timehands th3 = { NULL, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0, &th4};
7239acc78aSPoul-Henning Kamp static struct timehands th2 = { NULL, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0, &th3};
7339acc78aSPoul-Henning Kamp static struct timehands th1 = { NULL, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0, &th2};
74f5d157fbSPoul-Henning Kamp static struct timehands th0 = {
75f5d157fbSPoul-Henning Kamp 	&dummy_timecounter,
76f5d157fbSPoul-Henning Kamp 	0,
7739acc78aSPoul-Henning Kamp 	(uint64_t)-1 / 1000000,
78f5d157fbSPoul-Henning Kamp 	0,
79d25917e8SPoul-Henning Kamp 	{1, 0},
80f5d157fbSPoul-Henning Kamp 	{0, 0},
81f5d157fbSPoul-Henning Kamp 	{0, 0},
82f5d157fbSPoul-Henning Kamp 	1,
83f5d157fbSPoul-Henning Kamp 	&th1
84f5d157fbSPoul-Henning Kamp };
8562efba6aSPoul-Henning Kamp 
8662efba6aSPoul-Henning Kamp static struct timehands *volatile timehands = &th0;
8762efba6aSPoul-Henning Kamp struct timecounter *timecounter = &dummy_timecounter;
8862efba6aSPoul-Henning Kamp static struct timecounter *timecounters = &dummy_timecounter;
893bac064fSPoul-Henning Kamp 
9048e5da55SPoul-Henning Kamp time_t time_second = 1;
91e452573dSAndre Oppermann time_t time_uptime = 1;
92227ee8a1SPoul-Henning Kamp 
9339acc78aSPoul-Henning Kamp static struct bintime boottimebin;
9437d38777SBruce Evans struct timeval boottime;
95a7bc3102SPeter Wemm static int sysctl_kern_boottime(SYSCTL_HANDLER_ARGS);
96a7bc3102SPeter Wemm SYSCTL_PROC(_kern, KERN_BOOTTIME, boottime, CTLTYPE_STRUCT|CTLFLAG_RD,
97a7bc3102SPeter Wemm     NULL, 0, sysctl_kern_boottime, "S,timeval", "System boottime");
9837d38777SBruce Evans 
9991266b96SPoul-Henning Kamp SYSCTL_NODE(_kern, OID_AUTO, timecounter, CTLFLAG_RW, 0, "");
10091266b96SPoul-Henning Kamp 
1014e74721cSPoul-Henning Kamp static int timestepwarnings;
1024e74721cSPoul-Henning Kamp SYSCTL_INT(_kern_timecounter, OID_AUTO, stepwarnings, CTLFLAG_RW,
1034e74721cSPoul-Henning Kamp     &timestepwarnings, 0, "");
1044e74721cSPoul-Henning Kamp 
105056abcabSPoul-Henning Kamp #define TC_STATS(foo) \
1066b00cf46SPoul-Henning Kamp 	static u_int foo; \
1074f8cb019SMark Murray 	SYSCTL_UINT(_kern_timecounter, OID_AUTO, foo, CTLFLAG_RD, &foo, 0, "");\
10839acc78aSPoul-Henning Kamp 	struct __hack
109056abcabSPoul-Henning Kamp 
110056abcabSPoul-Henning Kamp TC_STATS(nbinuptime);    TC_STATS(nnanouptime);    TC_STATS(nmicrouptime);
111056abcabSPoul-Henning Kamp TC_STATS(nbintime);      TC_STATS(nnanotime);      TC_STATS(nmicrotime);
112056abcabSPoul-Henning Kamp TC_STATS(ngetbinuptime); TC_STATS(ngetnanouptime); TC_STATS(ngetmicrouptime);
113056abcabSPoul-Henning Kamp TC_STATS(ngetbintime);   TC_STATS(ngetnanotime);   TC_STATS(ngetmicrotime);
1144394f476SPoul-Henning Kamp TC_STATS(nsetclock);
115056abcabSPoul-Henning Kamp 
116056abcabSPoul-Henning Kamp #undef TC_STATS
117510eb5b9SPoul-Henning Kamp 
1189e1b5510SPoul-Henning Kamp static void tc_windup(void);
119e8444a7eSPoul-Henning Kamp static void cpu_tick_calibrate(int);
1209e1b5510SPoul-Henning Kamp 
121a7bc3102SPeter Wemm static int
122a7bc3102SPeter Wemm sysctl_kern_boottime(SYSCTL_HANDLER_ARGS)
123a7bc3102SPeter Wemm {
124a7bc3102SPeter Wemm #ifdef SCTL_MASK32
125a7bc3102SPeter Wemm 	int tv[2];
126a7bc3102SPeter Wemm 
127a7bc3102SPeter Wemm 	if (req->flags & SCTL_MASK32) {
128a7bc3102SPeter Wemm 		tv[0] = boottime.tv_sec;
129a7bc3102SPeter Wemm 		tv[1] = boottime.tv_usec;
130a7bc3102SPeter Wemm 		return SYSCTL_OUT(req, tv, sizeof(tv));
131a7bc3102SPeter Wemm 	} else
132a7bc3102SPeter Wemm #endif
133a7bc3102SPeter Wemm 		return SYSCTL_OUT(req, &boottime, sizeof(boottime));
134a7bc3102SPeter Wemm }
1355b1a8eb3SPoul-Henning Kamp 
13639acc78aSPoul-Henning Kamp /*
13739acc78aSPoul-Henning Kamp  * Return the difference between the timehands' counter value now and what
13839acc78aSPoul-Henning Kamp  * was when we copied it to the timehands' offset_count.
13939acc78aSPoul-Henning Kamp  */
1406b00cf46SPoul-Henning Kamp static __inline u_int
1416b00cf46SPoul-Henning Kamp tc_delta(struct timehands *th)
142e796e00dSPoul-Henning Kamp {
1436b00cf46SPoul-Henning Kamp 	struct timecounter *tc;
144e796e00dSPoul-Henning Kamp 
1456b00cf46SPoul-Henning Kamp 	tc = th->th_counter;
1466b00cf46SPoul-Henning Kamp 	return ((tc->tc_get_timecount(tc) - th->th_offset_count) &
1476b00cf46SPoul-Henning Kamp 	    tc->tc_counter_mask);
148e796e00dSPoul-Henning Kamp }
149a0502b19SPoul-Henning Kamp 
15039acc78aSPoul-Henning Kamp /*
1516b00cf46SPoul-Henning Kamp  * Functions for reading the time.  We have to loop until we are sure that
15239acc78aSPoul-Henning Kamp  * the timehands that we operated on was not updated under our feet.  See
15339acc78aSPoul-Henning Kamp  * the comment in <sys/time.h> for a description of these 12 functions.
1546b00cf46SPoul-Henning Kamp  */
1556b00cf46SPoul-Henning Kamp 
156a0502b19SPoul-Henning Kamp void
1572028c0cdSPoul-Henning Kamp binuptime(struct bintime *bt)
1582028c0cdSPoul-Henning Kamp {
1596b00cf46SPoul-Henning Kamp 	struct timehands *th;
1606b00cf46SPoul-Henning Kamp 	u_int gen;
1612028c0cdSPoul-Henning Kamp 
1625b7d8efaSPoul-Henning Kamp 	nbinuptime++;
1635b7d8efaSPoul-Henning Kamp 	do {
1646b00cf46SPoul-Henning Kamp 		th = timehands;
1656b00cf46SPoul-Henning Kamp 		gen = th->th_generation;
1666b00cf46SPoul-Henning Kamp 		*bt = th->th_offset;
1676b00cf46SPoul-Henning Kamp 		bintime_addx(bt, th->th_scale * tc_delta(th));
1686b00cf46SPoul-Henning Kamp 	} while (gen == 0 || gen != th->th_generation);
1692028c0cdSPoul-Henning Kamp }
1702028c0cdSPoul-Henning Kamp 
1712028c0cdSPoul-Henning Kamp void
17239acc78aSPoul-Henning Kamp nanouptime(struct timespec *tsp)
173056abcabSPoul-Henning Kamp {
174056abcabSPoul-Henning Kamp 	struct bintime bt;
175056abcabSPoul-Henning Kamp 
176056abcabSPoul-Henning Kamp 	nnanouptime++;
177056abcabSPoul-Henning Kamp 	binuptime(&bt);
17839acc78aSPoul-Henning Kamp 	bintime2timespec(&bt, tsp);
179056abcabSPoul-Henning Kamp }
180056abcabSPoul-Henning Kamp 
181056abcabSPoul-Henning Kamp void
18239acc78aSPoul-Henning Kamp microuptime(struct timeval *tvp)
183056abcabSPoul-Henning Kamp {
184056abcabSPoul-Henning Kamp 	struct bintime bt;
185056abcabSPoul-Henning Kamp 
186056abcabSPoul-Henning Kamp 	nmicrouptime++;
187056abcabSPoul-Henning Kamp 	binuptime(&bt);
18839acc78aSPoul-Henning Kamp 	bintime2timeval(&bt, tvp);
189056abcabSPoul-Henning Kamp }
190056abcabSPoul-Henning Kamp 
191056abcabSPoul-Henning Kamp void
1922028c0cdSPoul-Henning Kamp bintime(struct bintime *bt)
1932028c0cdSPoul-Henning Kamp {
1942028c0cdSPoul-Henning Kamp 
1955b7d8efaSPoul-Henning Kamp 	nbintime++;
1962028c0cdSPoul-Henning Kamp 	binuptime(bt);
1972028c0cdSPoul-Henning Kamp 	bintime_add(bt, &boottimebin);
1982028c0cdSPoul-Henning Kamp }
1992028c0cdSPoul-Henning Kamp 
2002028c0cdSPoul-Henning Kamp void
20139acc78aSPoul-Henning Kamp nanotime(struct timespec *tsp)
20200af9731SPoul-Henning Kamp {
2032028c0cdSPoul-Henning Kamp 	struct bintime bt;
20400af9731SPoul-Henning Kamp 
20591266b96SPoul-Henning Kamp 	nnanotime++;
2062028c0cdSPoul-Henning Kamp 	bintime(&bt);
20739acc78aSPoul-Henning Kamp 	bintime2timespec(&bt, tsp);
20848115288SPoul-Henning Kamp }
20948115288SPoul-Henning Kamp 
21048115288SPoul-Henning Kamp void
21139acc78aSPoul-Henning Kamp microtime(struct timeval *tvp)
212056abcabSPoul-Henning Kamp {
213056abcabSPoul-Henning Kamp 	struct bintime bt;
214056abcabSPoul-Henning Kamp 
215056abcabSPoul-Henning Kamp 	nmicrotime++;
216056abcabSPoul-Henning Kamp 	bintime(&bt);
21739acc78aSPoul-Henning Kamp 	bintime2timeval(&bt, tvp);
218056abcabSPoul-Henning Kamp }
219056abcabSPoul-Henning Kamp 
220056abcabSPoul-Henning Kamp void
221056abcabSPoul-Henning Kamp getbinuptime(struct bintime *bt)
22200af9731SPoul-Henning Kamp {
2236b00cf46SPoul-Henning Kamp 	struct timehands *th;
2246b00cf46SPoul-Henning Kamp 	u_int gen;
22500af9731SPoul-Henning Kamp 
226056abcabSPoul-Henning Kamp 	ngetbinuptime++;
2275b7d8efaSPoul-Henning Kamp 	do {
2286b00cf46SPoul-Henning Kamp 		th = timehands;
2296b00cf46SPoul-Henning Kamp 		gen = th->th_generation;
2306b00cf46SPoul-Henning Kamp 		*bt = th->th_offset;
2316b00cf46SPoul-Henning Kamp 	} while (gen == 0 || gen != th->th_generation);
232a0502b19SPoul-Henning Kamp }
233a0502b19SPoul-Henning Kamp 
234a0502b19SPoul-Henning Kamp void
235c21410e1SPoul-Henning Kamp getnanouptime(struct timespec *tsp)
236a0502b19SPoul-Henning Kamp {
2376b00cf46SPoul-Henning Kamp 	struct timehands *th;
2386b00cf46SPoul-Henning Kamp 	u_int gen;
239a0502b19SPoul-Henning Kamp 
24091266b96SPoul-Henning Kamp 	ngetnanouptime++;
2415b7d8efaSPoul-Henning Kamp 	do {
2426b00cf46SPoul-Henning Kamp 		th = timehands;
2436b00cf46SPoul-Henning Kamp 		gen = th->th_generation;
2446b00cf46SPoul-Henning Kamp 		bintime2timespec(&th->th_offset, tsp);
2456b00cf46SPoul-Henning Kamp 	} while (gen == 0 || gen != th->th_generation);
246a0502b19SPoul-Henning Kamp }
247a0502b19SPoul-Henning Kamp 
248c7c9a816SPoul-Henning Kamp void
249056abcabSPoul-Henning Kamp getmicrouptime(struct timeval *tvp)
250c7c9a816SPoul-Henning Kamp {
2516b00cf46SPoul-Henning Kamp 	struct timehands *th;
2526b00cf46SPoul-Henning Kamp 	u_int gen;
2537ec73f64SPoul-Henning Kamp 
254056abcabSPoul-Henning Kamp 	ngetmicrouptime++;
255056abcabSPoul-Henning Kamp 	do {
2566b00cf46SPoul-Henning Kamp 		th = timehands;
2576b00cf46SPoul-Henning Kamp 		gen = th->th_generation;
2586b00cf46SPoul-Henning Kamp 		bintime2timeval(&th->th_offset, tvp);
2596b00cf46SPoul-Henning Kamp 	} while (gen == 0 || gen != th->th_generation);
2607ec73f64SPoul-Henning Kamp }
2617ec73f64SPoul-Henning Kamp 
2627ec73f64SPoul-Henning Kamp void
263056abcabSPoul-Henning Kamp getbintime(struct bintime *bt)
2647ec73f64SPoul-Henning Kamp {
2656b00cf46SPoul-Henning Kamp 	struct timehands *th;
2666b00cf46SPoul-Henning Kamp 	u_int gen;
2677ec73f64SPoul-Henning Kamp 
268056abcabSPoul-Henning Kamp 	ngetbintime++;
269056abcabSPoul-Henning Kamp 	do {
2706b00cf46SPoul-Henning Kamp 		th = timehands;
2716b00cf46SPoul-Henning Kamp 		gen = th->th_generation;
2726b00cf46SPoul-Henning Kamp 		*bt = th->th_offset;
2736b00cf46SPoul-Henning Kamp 	} while (gen == 0 || gen != th->th_generation);
274056abcabSPoul-Henning Kamp 	bintime_add(bt, &boottimebin);
275056abcabSPoul-Henning Kamp }
276056abcabSPoul-Henning Kamp 
277056abcabSPoul-Henning Kamp void
278056abcabSPoul-Henning Kamp getnanotime(struct timespec *tsp)
279056abcabSPoul-Henning Kamp {
2806b00cf46SPoul-Henning Kamp 	struct timehands *th;
2816b00cf46SPoul-Henning Kamp 	u_int gen;
282056abcabSPoul-Henning Kamp 
283056abcabSPoul-Henning Kamp 	ngetnanotime++;
284056abcabSPoul-Henning Kamp 	do {
2856b00cf46SPoul-Henning Kamp 		th = timehands;
2866b00cf46SPoul-Henning Kamp 		gen = th->th_generation;
2876b00cf46SPoul-Henning Kamp 		*tsp = th->th_nanotime;
2886b00cf46SPoul-Henning Kamp 	} while (gen == 0 || gen != th->th_generation);
289056abcabSPoul-Henning Kamp }
290056abcabSPoul-Henning Kamp 
291056abcabSPoul-Henning Kamp void
292056abcabSPoul-Henning Kamp getmicrotime(struct timeval *tvp)
293056abcabSPoul-Henning Kamp {
2946b00cf46SPoul-Henning Kamp 	struct timehands *th;
2956b00cf46SPoul-Henning Kamp 	u_int gen;
296056abcabSPoul-Henning Kamp 
297056abcabSPoul-Henning Kamp 	ngetmicrotime++;
298056abcabSPoul-Henning Kamp 	do {
2996b00cf46SPoul-Henning Kamp 		th = timehands;
3006b00cf46SPoul-Henning Kamp 		gen = th->th_generation;
3016b00cf46SPoul-Henning Kamp 		*tvp = th->th_microtime;
3026b00cf46SPoul-Henning Kamp 	} while (gen == 0 || gen != th->th_generation);
3037ec73f64SPoul-Henning Kamp }
3047ec73f64SPoul-Henning Kamp 
30539acc78aSPoul-Henning Kamp /*
30678a49a45SPoul-Henning Kamp  * Initialize a new timecounter and possibly use it.
3074e2befc0SPoul-Henning Kamp  */
3087ec73f64SPoul-Henning Kamp void
30991266b96SPoul-Henning Kamp tc_init(struct timecounter *tc)
3107ec73f64SPoul-Henning Kamp {
311555a5de2SPoul-Henning Kamp 	u_int u;
3127ec73f64SPoul-Henning Kamp 
313c679c734SPoul-Henning Kamp 	u = tc->tc_frequency / tc->tc_counter_mask;
314555a5de2SPoul-Henning Kamp 	/* XXX: We need some margin here, 10% is a guess */
315555a5de2SPoul-Henning Kamp 	u *= 11;
316555a5de2SPoul-Henning Kamp 	u /= 10;
317c679c734SPoul-Henning Kamp 	if (u > hz && tc->tc_quality >= 0) {
318c679c734SPoul-Henning Kamp 		tc->tc_quality = -2000;
319c679c734SPoul-Henning Kamp 		if (bootverbose) {
320c679c734SPoul-Henning Kamp 			printf("Timecounter \"%s\" frequency %ju Hz",
321555a5de2SPoul-Henning Kamp 			    tc->tc_name, (uintmax_t)tc->tc_frequency);
322c679c734SPoul-Henning Kamp 			printf(" -- Insufficient hz, needs at least %u\n", u);
323c679c734SPoul-Henning Kamp 		}
324c679c734SPoul-Henning Kamp 	} else if (tc->tc_quality >= 0 || bootverbose) {
325555a5de2SPoul-Henning Kamp 		printf("Timecounter \"%s\" frequency %ju Hz quality %d\n",
326555a5de2SPoul-Henning Kamp 		    tc->tc_name, (uintmax_t)tc->tc_frequency,
32778a49a45SPoul-Henning Kamp 		    tc->tc_quality);
328e46eeb89SPoul-Henning Kamp 	}
329c679c734SPoul-Henning Kamp 
33062efba6aSPoul-Henning Kamp 	tc->tc_next = timecounters;
33162efba6aSPoul-Henning Kamp 	timecounters = tc;
332555a5de2SPoul-Henning Kamp 	/*
333555a5de2SPoul-Henning Kamp 	 * Never automatically use a timecounter with negative quality.
334555a5de2SPoul-Henning Kamp 	 * Even though we run on the dummy counter, switching here may be
335555a5de2SPoul-Henning Kamp 	 * worse since this timecounter may not be monotonous.
336555a5de2SPoul-Henning Kamp 	 */
33778a49a45SPoul-Henning Kamp 	if (tc->tc_quality < 0)
33878a49a45SPoul-Henning Kamp 		return;
33978a49a45SPoul-Henning Kamp 	if (tc->tc_quality < timecounter->tc_quality)
34078a49a45SPoul-Henning Kamp 		return;
341555a5de2SPoul-Henning Kamp 	if (tc->tc_quality == timecounter->tc_quality &&
342555a5de2SPoul-Henning Kamp 	    tc->tc_frequency < timecounter->tc_frequency)
343555a5de2SPoul-Henning Kamp 		return;
344555a5de2SPoul-Henning Kamp 	(void)tc->tc_get_timecount(tc);
345555a5de2SPoul-Henning Kamp 	(void)tc->tc_get_timecount(tc);
3467ec73f64SPoul-Henning Kamp 	timecounter = tc;
34762efba6aSPoul-Henning Kamp }
34862efba6aSPoul-Henning Kamp 
34939acc78aSPoul-Henning Kamp /* Report the frequency of the current timecounter. */
35060ca3996SPoul-Henning Kamp u_int64_t
35162efba6aSPoul-Henning Kamp tc_getfrequency(void)
35262efba6aSPoul-Henning Kamp {
35362efba6aSPoul-Henning Kamp 
3546b00cf46SPoul-Henning Kamp 	return (timehands->th_counter->tc_frequency);
3557ec73f64SPoul-Henning Kamp }
3567ec73f64SPoul-Henning Kamp 
35739acc78aSPoul-Henning Kamp /*
3584e82e5f6SWarner Losh  * Step our concept of UTC.  This is done by modifying our estimate of
3594e74721cSPoul-Henning Kamp  * when we booted.
3604e74721cSPoul-Henning Kamp  * XXX: not locked.
3616b00cf46SPoul-Henning Kamp  */
3627ec73f64SPoul-Henning Kamp void
36391266b96SPoul-Henning Kamp tc_setclock(struct timespec *ts)
3647ec73f64SPoul-Henning Kamp {
3655b51d1deSPoul-Henning Kamp 	struct timespec tbef, taft;
3664e74721cSPoul-Henning Kamp 	struct bintime bt, bt2;
3677ec73f64SPoul-Henning Kamp 
368e8444a7eSPoul-Henning Kamp 	cpu_tick_calibrate(1);
3694394f476SPoul-Henning Kamp 	nsetclock++;
3705b51d1deSPoul-Henning Kamp 	nanotime(&tbef);
3714e74721cSPoul-Henning Kamp 	timespec2bintime(ts, &bt);
3725b51d1deSPoul-Henning Kamp 	binuptime(&bt2);
3734e74721cSPoul-Henning Kamp 	bintime_sub(&bt, &bt2);
3744e74721cSPoul-Henning Kamp 	bintime_add(&bt2, &boottimebin);
3754e74721cSPoul-Henning Kamp 	boottimebin = bt;
3764e74721cSPoul-Henning Kamp 	bintime2timeval(&bt, &boottime);
37739acc78aSPoul-Henning Kamp 
37839acc78aSPoul-Henning Kamp 	/* XXX fiddle all the little crinkly bits around the fiords... */
37991266b96SPoul-Henning Kamp 	tc_windup();
3805b51d1deSPoul-Henning Kamp 	nanotime(&taft);
3814e74721cSPoul-Henning Kamp 	if (timestepwarnings) {
3825b51d1deSPoul-Henning Kamp 		log(LOG_INFO,
3835b51d1deSPoul-Henning Kamp 		    "Time stepped from %jd.%09ld to %jd.%09ld (%jd.%09ld)\n",
3845b51d1deSPoul-Henning Kamp 		    (intmax_t)tbef.tv_sec, tbef.tv_nsec,
3855b51d1deSPoul-Henning Kamp 		    (intmax_t)taft.tv_sec, taft.tv_nsec,
386ee57aeeaSPoul-Henning Kamp 		    (intmax_t)ts->tv_sec, ts->tv_nsec);
3874e74721cSPoul-Henning Kamp 	}
388e8444a7eSPoul-Henning Kamp 	cpu_tick_calibrate(1);
3897ec73f64SPoul-Henning Kamp }
3907ec73f64SPoul-Henning Kamp 
39139acc78aSPoul-Henning Kamp /*
39239acc78aSPoul-Henning Kamp  * Initialize the next struct timehands in the ring and make
3936b00cf46SPoul-Henning Kamp  * it the active timehands.  Along the way we might switch to a different
3946b00cf46SPoul-Henning Kamp  * timecounter and/or do seconds processing in NTP.  Slightly magic.
3956b00cf46SPoul-Henning Kamp  */
3969e1b5510SPoul-Henning Kamp static void
39791266b96SPoul-Henning Kamp tc_windup(void)
3987ec73f64SPoul-Henning Kamp {
3992028c0cdSPoul-Henning Kamp 	struct bintime bt;
40039acc78aSPoul-Henning Kamp 	struct timehands *th, *tho;
4016b00cf46SPoul-Henning Kamp 	u_int64_t scale;
40239acc78aSPoul-Henning Kamp 	u_int delta, ncount, ogen;
40339acc78aSPoul-Henning Kamp 	int i;
4044f2073fbSWarner Losh 	time_t t;
4057ec73f64SPoul-Henning Kamp 
40639acc78aSPoul-Henning Kamp 	/*
4076b00cf46SPoul-Henning Kamp 	 * Make the next timehands a copy of the current one, but do not
4086b00cf46SPoul-Henning Kamp 	 * overwrite the generation or next pointer.  While we update
4096b00cf46SPoul-Henning Kamp 	 * the contents, the generation must be zero.
4106b00cf46SPoul-Henning Kamp 	 */
4116b00cf46SPoul-Henning Kamp 	tho = timehands;
4126b00cf46SPoul-Henning Kamp 	th = tho->th_next;
4136b00cf46SPoul-Henning Kamp 	ogen = th->th_generation;
4146b00cf46SPoul-Henning Kamp 	th->th_generation = 0;
41539acc78aSPoul-Henning Kamp 	bcopy(tho, th, offsetof(struct timehands, th_generation));
4166b00cf46SPoul-Henning Kamp 
41739acc78aSPoul-Henning Kamp 	/*
4186b00cf46SPoul-Henning Kamp 	 * Capture a timecounter delta on the current timecounter and if
4196b00cf46SPoul-Henning Kamp 	 * changing timecounters, a counter value from the new timecounter.
4206b00cf46SPoul-Henning Kamp 	 * Update the offset fields accordingly.
4216b00cf46SPoul-Henning Kamp 	 */
4226b00cf46SPoul-Henning Kamp 	delta = tc_delta(th);
4236b00cf46SPoul-Henning Kamp 	if (th->th_counter != timecounter)
4246b00cf46SPoul-Henning Kamp 		ncount = timecounter->tc_get_timecount(timecounter);
42539acc78aSPoul-Henning Kamp 	else
42639acc78aSPoul-Henning Kamp 		ncount = 0;
4276b00cf46SPoul-Henning Kamp 	th->th_offset_count += delta;
4286b00cf46SPoul-Henning Kamp 	th->th_offset_count &= th->th_counter->tc_counter_mask;
4296b00cf46SPoul-Henning Kamp 	bintime_addx(&th->th_offset, th->th_scale * delta);
4306b00cf46SPoul-Henning Kamp 
43139acc78aSPoul-Henning Kamp 	/*
4326b00cf46SPoul-Henning Kamp 	 * Hardware latching timecounters may not generate interrupts on
4336b00cf46SPoul-Henning Kamp 	 * PPS events, so instead we poll them.  There is a finite risk that
4346b00cf46SPoul-Henning Kamp 	 * the hardware might capture a count which is later than the one we
4356b00cf46SPoul-Henning Kamp 	 * got above, and therefore possibly in the next NTP second which might
4366b00cf46SPoul-Henning Kamp 	 * have a different rate than the current NTP second.  It doesn't
4376b00cf46SPoul-Henning Kamp 	 * matter in practice.
4386b00cf46SPoul-Henning Kamp 	 */
4396b00cf46SPoul-Henning Kamp 	if (tho->th_counter->tc_poll_pps)
4406b00cf46SPoul-Henning Kamp 		tho->th_counter->tc_poll_pps(tho->th_counter);
4416b00cf46SPoul-Henning Kamp 
44239acc78aSPoul-Henning Kamp 	/*
443c1cccd1eSWarner Losh 	 * Deal with NTP second processing.  The for loop normally
444c1cccd1eSWarner Losh 	 * iterates at most once, but in extreme situations it might
445c1cccd1eSWarner Losh 	 * keep NTP sane if timeouts are not run for several seconds.
446c1cccd1eSWarner Losh 	 * At boot, the time step can be large when the TOD hardware
447c1cccd1eSWarner Losh 	 * has been read, so on really large steps, we call
448c1cccd1eSWarner Losh 	 * ntp_update_second only twice.  We need to call it twice in
449c1cccd1eSWarner Losh 	 * case we missed a leap second.
4504f2073fbSWarner Losh 	 */
4514f2073fbSWarner Losh 	bt = th->th_offset;
4524f2073fbSWarner Losh 	bintime_add(&bt, &boottimebin);
45345cc9f5fSWarner Losh 	i = bt.sec - tho->th_microtime.tv_sec;
45445cc9f5fSWarner Losh 	if (i > LARGE_STEP)
45545cc9f5fSWarner Losh 		i = 2;
45645cc9f5fSWarner Losh 	for (; i > 0; i--) {
4574f2073fbSWarner Losh 		t = bt.sec;
4584f2073fbSWarner Losh 		ntp_update_second(&th->th_adjustment, &bt.sec);
4594f2073fbSWarner Losh 		if (bt.sec != t)
4604f2073fbSWarner Losh 			boottimebin.sec += bt.sec - t;
4614f2073fbSWarner Losh 	}
462c1cccd1eSWarner Losh 	/* Update the UTC timestamps used by the get*() functions. */
463c1cccd1eSWarner Losh 	/* XXX shouldn't do this here.  Should force non-`get' versions. */
464c1cccd1eSWarner Losh 	bintime2timeval(&bt, &th->th_microtime);
465c1cccd1eSWarner Losh 	bintime2timespec(&bt, &th->th_nanotime);
4666b00cf46SPoul-Henning Kamp 
4676b00cf46SPoul-Henning Kamp 	/* Now is a good time to change timecounters. */
4686b00cf46SPoul-Henning Kamp 	if (th->th_counter != timecounter) {
4696b00cf46SPoul-Henning Kamp 		th->th_counter = timecounter;
4706b00cf46SPoul-Henning Kamp 		th->th_offset_count = ncount;
4717ec73f64SPoul-Henning Kamp 	}
4727ec73f64SPoul-Henning Kamp 
47348e5da55SPoul-Henning Kamp 	/*-
4746b00cf46SPoul-Henning Kamp 	 * Recalculate the scaling factor.  We want the number of 1/2^64
4756b00cf46SPoul-Henning Kamp 	 * fractions of a second per period of the hardware counter, taking
4766b00cf46SPoul-Henning Kamp 	 * into account the th_adjustment factor which the NTP PLL/adjtime(2)
4776b00cf46SPoul-Henning Kamp 	 * processing provides us with.
4786b00cf46SPoul-Henning Kamp 	 *
4796b00cf46SPoul-Henning Kamp 	 * The th_adjustment is nanoseconds per second with 32 bit binary
480d94e3652SPoul-Henning Kamp 	 * fraction and we want 64 bit binary fraction of second:
4816b00cf46SPoul-Henning Kamp 	 *
4826b00cf46SPoul-Henning Kamp 	 *	 x = a * 2^32 / 10^9 = a * 4.294967296
4836b00cf46SPoul-Henning Kamp 	 *
4846b00cf46SPoul-Henning Kamp 	 * The range of th_adjustment is +/- 5000PPM so inside a 64bit int
485e8444a7eSPoul-Henning Kamp 	 * we can only multiply by about 850 without overflowing, that
486e8444a7eSPoul-Henning Kamp 	 * leaves no suitably precise fractions for multiply before divide.
4876b00cf46SPoul-Henning Kamp 	 *
4886b00cf46SPoul-Henning Kamp 	 * Divide before multiply with a fraction of 2199/512 results in a
4896b00cf46SPoul-Henning Kamp 	 * systematic undercompensation of 10PPM of th_adjustment.  On a
4906b00cf46SPoul-Henning Kamp 	 * 5000PPM adjustment this is a 0.05PPM error.  This is acceptable.
4916b00cf46SPoul-Henning Kamp  	 *
4926b00cf46SPoul-Henning Kamp 	 * We happily sacrifice the lowest of the 64 bits of our result
4936b00cf46SPoul-Henning Kamp 	 * to the goddess of code clarity.
49439acc78aSPoul-Henning Kamp 	 *
4956b00cf46SPoul-Henning Kamp 	 */
49639acc78aSPoul-Henning Kamp 	scale = (u_int64_t)1 << 63;
4976b00cf46SPoul-Henning Kamp 	scale += (th->th_adjustment / 1024) * 2199;
4986b00cf46SPoul-Henning Kamp 	scale /= th->th_counter->tc_frequency;
4996b00cf46SPoul-Henning Kamp 	th->th_scale = scale * 2;
5006b00cf46SPoul-Henning Kamp 
50139acc78aSPoul-Henning Kamp 	/*
50239acc78aSPoul-Henning Kamp 	 * Now that the struct timehands is again consistent, set the new
5036b00cf46SPoul-Henning Kamp 	 * generation number, making sure to not make it zero.
5046b00cf46SPoul-Henning Kamp 	 */
5056b00cf46SPoul-Henning Kamp 	if (++ogen == 0)
50639acc78aSPoul-Henning Kamp 		ogen = 1;
5076b00cf46SPoul-Henning Kamp 	th->th_generation = ogen;
5086b00cf46SPoul-Henning Kamp 
50939acc78aSPoul-Henning Kamp 	/* Go live with the new struct timehands. */
5106b00cf46SPoul-Henning Kamp 	time_second = th->th_microtime.tv_sec;
51138b0884cSPoul-Henning Kamp 	time_uptime = th->th_offset.sec;
5126b00cf46SPoul-Henning Kamp 	timehands = th;
5136b00cf46SPoul-Henning Kamp }
5146b00cf46SPoul-Henning Kamp 
51539acc78aSPoul-Henning Kamp /* Report or change the active timecounter hardware. */
5166b6ef746SBruce Evans static int
51782d9ae4eSPoul-Henning Kamp sysctl_kern_timecounter_hardware(SYSCTL_HANDLER_ARGS)
5186b6ef746SBruce Evans {
5196b6ef746SBruce Evans 	char newname[32];
5206b6ef746SBruce Evans 	struct timecounter *newtc, *tc;
5216b6ef746SBruce Evans 	int error;
5226b6ef746SBruce Evans 
52362efba6aSPoul-Henning Kamp 	tc = timecounter;
524e80fb434SRobert Drehmel 	strlcpy(newname, tc->tc_name, sizeof(newname));
525e80fb434SRobert Drehmel 
5266b6ef746SBruce Evans 	error = sysctl_handle_string(oidp, &newname[0], sizeof(newname), req);
52739acc78aSPoul-Henning Kamp 	if (error != 0 || req->newptr == NULL ||
52839acc78aSPoul-Henning Kamp 	    strcmp(newname, tc->tc_name) == 0)
52962efba6aSPoul-Henning Kamp 		return (error);
53062efba6aSPoul-Henning Kamp 	for (newtc = timecounters; newtc != NULL; newtc = newtc->tc_next) {
53139acc78aSPoul-Henning Kamp 		if (strcmp(newname, newtc->tc_name) != 0)
53262efba6aSPoul-Henning Kamp 			continue;
53339acc78aSPoul-Henning Kamp 
5346b6ef746SBruce Evans 		/* Warm up new timecounter. */
5356b6ef746SBruce Evans 		(void)newtc->tc_get_timecount(newtc);
53662efba6aSPoul-Henning Kamp 		(void)newtc->tc_get_timecount(newtc);
53739acc78aSPoul-Henning Kamp 
53862efba6aSPoul-Henning Kamp 		timecounter = newtc;
5396b6ef746SBruce Evans 		return (0);
5406b6ef746SBruce Evans 	}
5416b6ef746SBruce Evans 	return (EINVAL);
5426b6ef746SBruce Evans }
5436b6ef746SBruce Evans 
5446b6ef746SBruce Evans SYSCTL_PROC(_kern_timecounter, OID_AUTO, hardware, CTLTYPE_STRING | CTLFLAG_RW,
5456b6ef746SBruce Evans     0, 0, sysctl_kern_timecounter_hardware, "A", "");
5466b6ef746SBruce Evans 
54778a49a45SPoul-Henning Kamp 
54878a49a45SPoul-Henning Kamp /* Report or change the active timecounter hardware. */
54978a49a45SPoul-Henning Kamp static int
55078a49a45SPoul-Henning Kamp sysctl_kern_timecounter_choice(SYSCTL_HANDLER_ARGS)
55178a49a45SPoul-Henning Kamp {
55278a49a45SPoul-Henning Kamp 	char buf[32], *spc;
55378a49a45SPoul-Henning Kamp 	struct timecounter *tc;
55478a49a45SPoul-Henning Kamp 	int error;
55578a49a45SPoul-Henning Kamp 
55678a49a45SPoul-Henning Kamp 	spc = "";
55778a49a45SPoul-Henning Kamp 	error = 0;
55878a49a45SPoul-Henning Kamp 	for (tc = timecounters; error == 0 && tc != NULL; tc = tc->tc_next) {
55978a49a45SPoul-Henning Kamp 		sprintf(buf, "%s%s(%d)",
56078a49a45SPoul-Henning Kamp 		    spc, tc->tc_name, tc->tc_quality);
56178a49a45SPoul-Henning Kamp 		error = SYSCTL_OUT(req, buf, strlen(buf));
56278a49a45SPoul-Henning Kamp 		spc = " ";
56378a49a45SPoul-Henning Kamp 	}
56478a49a45SPoul-Henning Kamp 	return (error);
56578a49a45SPoul-Henning Kamp }
56678a49a45SPoul-Henning Kamp 
56778a49a45SPoul-Henning Kamp SYSCTL_PROC(_kern_timecounter, OID_AUTO, choice, CTLTYPE_STRING | CTLFLAG_RD,
56878a49a45SPoul-Henning Kamp     0, 0, sysctl_kern_timecounter_choice, "A", "");
56978a49a45SPoul-Henning Kamp 
57039acc78aSPoul-Henning Kamp /*
5716b00cf46SPoul-Henning Kamp  * RFC 2783 PPS-API implementation.
5726b00cf46SPoul-Henning Kamp  */
5737ec73f64SPoul-Henning Kamp 
57432c20357SPoul-Henning Kamp int
57532c20357SPoul-Henning Kamp pps_ioctl(u_long cmd, caddr_t data, struct pps_state *pps)
57632c20357SPoul-Henning Kamp {
57732c20357SPoul-Henning Kamp 	pps_params_t *app;
578b7424f2dSJohn Hay 	struct pps_fetch_args *fapi;
579de3f8889SPeter Wemm #ifdef PPS_SYNC
580b7424f2dSJohn Hay 	struct pps_kcbind_args *kapi;
581de3f8889SPeter Wemm #endif
58232c20357SPoul-Henning Kamp 
583d8e8b675SPoul-Henning Kamp 	KASSERT(pps != NULL, ("NULL pps pointer in pps_ioctl"));
58432c20357SPoul-Henning Kamp 	switch (cmd) {
58532c20357SPoul-Henning Kamp 	case PPS_IOC_CREATE:
58632c20357SPoul-Henning Kamp 		return (0);
58732c20357SPoul-Henning Kamp 	case PPS_IOC_DESTROY:
58832c20357SPoul-Henning Kamp 		return (0);
58932c20357SPoul-Henning Kamp 	case PPS_IOC_SETPARAMS:
59032c20357SPoul-Henning Kamp 		app = (pps_params_t *)data;
59132c20357SPoul-Henning Kamp 		if (app->mode & ~pps->ppscap)
59232c20357SPoul-Henning Kamp 			return (EINVAL);
59332c20357SPoul-Henning Kamp 		pps->ppsparam = *app;
59432c20357SPoul-Henning Kamp 		return (0);
59532c20357SPoul-Henning Kamp 	case PPS_IOC_GETPARAMS:
59632c20357SPoul-Henning Kamp 		app = (pps_params_t *)data;
59732c20357SPoul-Henning Kamp 		*app = pps->ppsparam;
598b7424f2dSJohn Hay 		app->api_version = PPS_API_VERS_1;
59932c20357SPoul-Henning Kamp 		return (0);
60032c20357SPoul-Henning Kamp 	case PPS_IOC_GETCAP:
60132c20357SPoul-Henning Kamp 		*(int*)data = pps->ppscap;
60232c20357SPoul-Henning Kamp 		return (0);
60332c20357SPoul-Henning Kamp 	case PPS_IOC_FETCH:
604b7424f2dSJohn Hay 		fapi = (struct pps_fetch_args *)data;
605b7424f2dSJohn Hay 		if (fapi->tsformat && fapi->tsformat != PPS_TSFMT_TSPEC)
606b7424f2dSJohn Hay 			return (EINVAL);
607b7424f2dSJohn Hay 		if (fapi->timeout.tv_sec || fapi->timeout.tv_nsec)
60832c20357SPoul-Henning Kamp 			return (EOPNOTSUPP);
609b7424f2dSJohn Hay 		pps->ppsinfo.current_mode = pps->ppsparam.mode;
610b7424f2dSJohn Hay 		fapi->pps_info_buf = pps->ppsinfo;
611b7424f2dSJohn Hay 		return (0);
612b7424f2dSJohn Hay 	case PPS_IOC_KCBIND:
613b7424f2dSJohn Hay #ifdef PPS_SYNC
614b7424f2dSJohn Hay 		kapi = (struct pps_kcbind_args *)data;
615b7424f2dSJohn Hay 		/* XXX Only root should be able to do this */
616b7424f2dSJohn Hay 		if (kapi->tsformat && kapi->tsformat != PPS_TSFMT_TSPEC)
617b7424f2dSJohn Hay 			return (EINVAL);
618b7424f2dSJohn Hay 		if (kapi->kernel_consumer != PPS_KC_HARDPPS)
619b7424f2dSJohn Hay 			return (EINVAL);
620b7424f2dSJohn Hay 		if (kapi->edge & ~pps->ppscap)
621b7424f2dSJohn Hay 			return (EINVAL);
622b7424f2dSJohn Hay 		pps->kcmode = kapi->edge;
623b7424f2dSJohn Hay 		return (0);
624b7424f2dSJohn Hay #else
625b7424f2dSJohn Hay 		return (EOPNOTSUPP);
626b7424f2dSJohn Hay #endif
62732c20357SPoul-Henning Kamp 	default:
628f8385624SPoul-Henning Kamp 		return (ENOIOCTL);
62932c20357SPoul-Henning Kamp 	}
63032c20357SPoul-Henning Kamp }
63132c20357SPoul-Henning Kamp 
63232c20357SPoul-Henning Kamp void
63332c20357SPoul-Henning Kamp pps_init(struct pps_state *pps)
63432c20357SPoul-Henning Kamp {
63532c20357SPoul-Henning Kamp 	pps->ppscap |= PPS_TSFMT_TSPEC;
63632c20357SPoul-Henning Kamp 	if (pps->ppscap & PPS_CAPTUREASSERT)
63732c20357SPoul-Henning Kamp 		pps->ppscap |= PPS_OFFSETASSERT;
63832c20357SPoul-Henning Kamp 	if (pps->ppscap & PPS_CAPTURECLEAR)
63932c20357SPoul-Henning Kamp 		pps->ppscap |= PPS_OFFSETCLEAR;
64032c20357SPoul-Henning Kamp }
64132c20357SPoul-Henning Kamp 
64232c20357SPoul-Henning Kamp void
6437bf758bfSPoul-Henning Kamp pps_capture(struct pps_state *pps)
6447bf758bfSPoul-Henning Kamp {
6456b00cf46SPoul-Henning Kamp 	struct timehands *th;
6467bf758bfSPoul-Henning Kamp 
647d8e8b675SPoul-Henning Kamp 	KASSERT(pps != NULL, ("NULL pps pointer in pps_capture"));
6486b00cf46SPoul-Henning Kamp 	th = timehands;
6496b00cf46SPoul-Henning Kamp 	pps->capgen = th->th_generation;
6506b00cf46SPoul-Henning Kamp 	pps->capth = th;
6516b00cf46SPoul-Henning Kamp 	pps->capcount = th->th_counter->tc_get_timecount(th->th_counter);
6526b00cf46SPoul-Henning Kamp 	if (pps->capgen != th->th_generation)
6536b00cf46SPoul-Henning Kamp 		pps->capgen = 0;
6547bf758bfSPoul-Henning Kamp }
6557bf758bfSPoul-Henning Kamp 
6567bf758bfSPoul-Henning Kamp void
6577bf758bfSPoul-Henning Kamp pps_event(struct pps_state *pps, int event)
65832c20357SPoul-Henning Kamp {
65939acc78aSPoul-Henning Kamp 	struct bintime bt;
66032c20357SPoul-Henning Kamp 	struct timespec ts, *tsp, *osp;
6616b00cf46SPoul-Henning Kamp 	u_int tcount, *pcount;
66232c20357SPoul-Henning Kamp 	int foff, fhard;
66332c20357SPoul-Henning Kamp 	pps_seq_t *pseq;
66432c20357SPoul-Henning Kamp 
665d8e8b675SPoul-Henning Kamp 	KASSERT(pps != NULL, ("NULL pps pointer in pps_event"));
66639acc78aSPoul-Henning Kamp 	/* If the timecounter was wound up underneath us, bail out. */
66739acc78aSPoul-Henning Kamp 	if (pps->capgen == 0 || pps->capgen != pps->capth->th_generation)
6687bf758bfSPoul-Henning Kamp 		return;
6697bf758bfSPoul-Henning Kamp 
67039acc78aSPoul-Henning Kamp 	/* Things would be easier with arrays. */
67132c20357SPoul-Henning Kamp 	if (event == PPS_CAPTUREASSERT) {
67232c20357SPoul-Henning Kamp 		tsp = &pps->ppsinfo.assert_timestamp;
67332c20357SPoul-Henning Kamp 		osp = &pps->ppsparam.assert_offset;
67432c20357SPoul-Henning Kamp 		foff = pps->ppsparam.mode & PPS_OFFSETASSERT;
675b7424f2dSJohn Hay 		fhard = pps->kcmode & PPS_CAPTUREASSERT;
67632c20357SPoul-Henning Kamp 		pcount = &pps->ppscount[0];
67732c20357SPoul-Henning Kamp 		pseq = &pps->ppsinfo.assert_sequence;
67832c20357SPoul-Henning Kamp 	} else {
67932c20357SPoul-Henning Kamp 		tsp = &pps->ppsinfo.clear_timestamp;
68032c20357SPoul-Henning Kamp 		osp = &pps->ppsparam.clear_offset;
68132c20357SPoul-Henning Kamp 		foff = pps->ppsparam.mode & PPS_OFFSETCLEAR;
682b7424f2dSJohn Hay 		fhard = pps->kcmode & PPS_CAPTURECLEAR;
68332c20357SPoul-Henning Kamp 		pcount = &pps->ppscount[1];
68432c20357SPoul-Henning Kamp 		pseq = &pps->ppsinfo.clear_sequence;
68532c20357SPoul-Henning Kamp 	}
68632c20357SPoul-Henning Kamp 
68739acc78aSPoul-Henning Kamp 	/*
6886b00cf46SPoul-Henning Kamp 	 * If the timecounter changed, we cannot compare the count values, so
6896b00cf46SPoul-Henning Kamp 	 * we have to drop the rest of the PPS-stuff until the next event.
6906b00cf46SPoul-Henning Kamp 	 */
6916b00cf46SPoul-Henning Kamp 	if (pps->ppstc != pps->capth->th_counter) {
6926b00cf46SPoul-Henning Kamp 		pps->ppstc = pps->capth->th_counter;
6937bf758bfSPoul-Henning Kamp 		*pcount = pps->capcount;
6947bf758bfSPoul-Henning Kamp 		pps->ppscount[2] = pps->capcount;
69532c20357SPoul-Henning Kamp 		return;
69632c20357SPoul-Henning Kamp 	}
69732c20357SPoul-Henning Kamp 
69839acc78aSPoul-Henning Kamp 	/* Convert the count to a timespec. */
6996b00cf46SPoul-Henning Kamp 	tcount = pps->capcount - pps->capth->th_offset_count;
7006b00cf46SPoul-Henning Kamp 	tcount &= pps->capth->th_counter->tc_counter_mask;
7016b00cf46SPoul-Henning Kamp 	bt = pps->capth->th_offset;
7026b00cf46SPoul-Henning Kamp 	bintime_addx(&bt, pps->capth->th_scale * tcount);
703eef633a7SPoul-Henning Kamp 	bintime_add(&bt, &boottimebin);
7042028c0cdSPoul-Henning Kamp 	bintime2timespec(&bt, &ts);
70532c20357SPoul-Henning Kamp 
70639acc78aSPoul-Henning Kamp 	/* If the timecounter was wound up underneath us, bail out. */
7076b00cf46SPoul-Henning Kamp 	if (pps->capgen != pps->capth->th_generation)
7087bf758bfSPoul-Henning Kamp 		return;
7097bf758bfSPoul-Henning Kamp 
7107bf758bfSPoul-Henning Kamp 	*pcount = pps->capcount;
71132c20357SPoul-Henning Kamp 	(*pseq)++;
71232c20357SPoul-Henning Kamp 	*tsp = ts;
71332c20357SPoul-Henning Kamp 
71432c20357SPoul-Henning Kamp 	if (foff) {
71532c20357SPoul-Henning Kamp 		timespecadd(tsp, osp);
71632c20357SPoul-Henning Kamp 		if (tsp->tv_nsec < 0) {
71732c20357SPoul-Henning Kamp 			tsp->tv_nsec += 1000000000;
71832c20357SPoul-Henning Kamp 			tsp->tv_sec -= 1;
71932c20357SPoul-Henning Kamp 		}
72032c20357SPoul-Henning Kamp 	}
72132c20357SPoul-Henning Kamp #ifdef PPS_SYNC
72232c20357SPoul-Henning Kamp 	if (fhard) {
723ce9fac00SPoul-Henning Kamp 		u_int64_t scale;
724ce9fac00SPoul-Henning Kamp 
72539acc78aSPoul-Henning Kamp 		/*
7266b00cf46SPoul-Henning Kamp 		 * Feed the NTP PLL/FLL.
727b1e7e201SJohn Hay 		 * The FLL wants to know how many (hardware) nanoseconds
728b1e7e201SJohn Hay 		 * elapsed since the previous event.
7296b00cf46SPoul-Henning Kamp 		 */
7307bf758bfSPoul-Henning Kamp 		tcount = pps->capcount - pps->ppscount[2];
7317bf758bfSPoul-Henning Kamp 		pps->ppscount[2] = pps->capcount;
7326b00cf46SPoul-Henning Kamp 		tcount &= pps->capth->th_counter->tc_counter_mask;
733b1e7e201SJohn Hay 		scale = (u_int64_t)1 << 63;
734b1e7e201SJohn Hay 		scale /= pps->capth->th_counter->tc_frequency;
735b1e7e201SJohn Hay 		scale *= 2;
7362028c0cdSPoul-Henning Kamp 		bt.sec = 0;
7372028c0cdSPoul-Henning Kamp 		bt.frac = 0;
738b1e7e201SJohn Hay 		bintime_addx(&bt, scale * tcount);
7392028c0cdSPoul-Henning Kamp 		bintime2timespec(&bt, &ts);
7402028c0cdSPoul-Henning Kamp 		hardpps(tsp, ts.tv_nsec + 1000000000 * ts.tv_sec);
74132c20357SPoul-Henning Kamp 	}
74232c20357SPoul-Henning Kamp #endif
74332c20357SPoul-Henning Kamp }
7449e1b5510SPoul-Henning Kamp 
74539acc78aSPoul-Henning Kamp /*
7469e1b5510SPoul-Henning Kamp  * Timecounters need to be updated every so often to prevent the hardware
7479e1b5510SPoul-Henning Kamp  * counter from overflowing.  Updating also recalculates the cached values
7489e1b5510SPoul-Henning Kamp  * used by the get*() family of functions, so their precision depends on
7499e1b5510SPoul-Henning Kamp  * the update frequency.
7509e1b5510SPoul-Henning Kamp  */
7519e1b5510SPoul-Henning Kamp 
7529e1b5510SPoul-Henning Kamp static int tc_tick;
753b3ed130cSPoul-Henning Kamp SYSCTL_INT(_kern_timecounter, OID_AUTO, tick, CTLFLAG_RD, &tc_tick, 0, "");
7549e1b5510SPoul-Henning Kamp 
755e7fa55afSPoul-Henning Kamp void
756e7fa55afSPoul-Henning Kamp tc_ticktock(void)
7579e1b5510SPoul-Henning Kamp {
758e7fa55afSPoul-Henning Kamp 	static int count;
759e8444a7eSPoul-Henning Kamp 	static time_t last_calib;
7609e1b5510SPoul-Henning Kamp 
761e7fa55afSPoul-Henning Kamp 	if (++count < tc_tick)
762e7fa55afSPoul-Henning Kamp 		return;
763e7fa55afSPoul-Henning Kamp 	count = 0;
7649e1b5510SPoul-Henning Kamp 	tc_windup();
765e8444a7eSPoul-Henning Kamp 	if (time_uptime != last_calib && !(time_uptime & 0xf)) {
766e8444a7eSPoul-Henning Kamp 		cpu_tick_calibrate(0);
767e8444a7eSPoul-Henning Kamp 		last_calib = time_uptime;
768e8444a7eSPoul-Henning Kamp 	}
7699e1b5510SPoul-Henning Kamp }
7709e1b5510SPoul-Henning Kamp 
7719e1b5510SPoul-Henning Kamp static void
7729e1b5510SPoul-Henning Kamp inittimecounter(void *dummy)
7739e1b5510SPoul-Henning Kamp {
7749e1b5510SPoul-Henning Kamp 	u_int p;
7759e1b5510SPoul-Henning Kamp 
77639acc78aSPoul-Henning Kamp 	/*
77739acc78aSPoul-Henning Kamp 	 * Set the initial timeout to
77839acc78aSPoul-Henning Kamp 	 * max(1, <approx. number of hardclock ticks in a millisecond>).
77939acc78aSPoul-Henning Kamp 	 * People should probably not use the sysctl to set the timeout
78039acc78aSPoul-Henning Kamp 	 * to smaller than its inital value, since that value is the
78139acc78aSPoul-Henning Kamp 	 * smallest reasonable one.  If they want better timestamps they
78239acc78aSPoul-Henning Kamp 	 * should use the non-"get"* functions.
78339acc78aSPoul-Henning Kamp 	 */
7849e1b5510SPoul-Henning Kamp 	if (hz > 1000)
7859e1b5510SPoul-Henning Kamp 		tc_tick = (hz + 500) / 1000;
7869e1b5510SPoul-Henning Kamp 	else
7879e1b5510SPoul-Henning Kamp 		tc_tick = 1;
7889e1b5510SPoul-Henning Kamp 	p = (tc_tick * 1000000) / hz;
7899e1b5510SPoul-Henning Kamp 	printf("Timecounters tick every %d.%03u msec\n", p / 1000, p % 1000);
79039acc78aSPoul-Henning Kamp 
79148e5da55SPoul-Henning Kamp 	/* warm up new timecounter (again) and get rolling. */
79239acc78aSPoul-Henning Kamp 	(void)timecounter->tc_get_timecount(timecounter);
79339acc78aSPoul-Henning Kamp 	(void)timecounter->tc_get_timecount(timecounter);
7949e1b5510SPoul-Henning Kamp }
7959e1b5510SPoul-Henning Kamp 
796ff292556SPeter Wemm SYSINIT(timecounter, SI_SUB_CLOCKS, SI_ORDER_SECOND, inittimecounter, NULL)
7975b1a8eb3SPoul-Henning Kamp 
798e8444a7eSPoul-Henning Kamp /* Cpu tick handling -------------------------------------------------*/
799e8444a7eSPoul-Henning Kamp 
800e8444a7eSPoul-Henning Kamp static int cpu_tick_variable;
801e8444a7eSPoul-Henning Kamp static uint64_t	cpu_tick_frequency;
802e8444a7eSPoul-Henning Kamp 
80388ca07e7SJohn Baldwin static uint64_t
8045b1a8eb3SPoul-Henning Kamp tc_cpu_ticks(void)
8055b1a8eb3SPoul-Henning Kamp {
8065b1a8eb3SPoul-Henning Kamp 	static uint64_t base;
8075b1a8eb3SPoul-Henning Kamp 	static unsigned last;
808e8444a7eSPoul-Henning Kamp 	unsigned u;
8095b1a8eb3SPoul-Henning Kamp 	struct timecounter *tc;
8105b1a8eb3SPoul-Henning Kamp 
8115b1a8eb3SPoul-Henning Kamp 	tc = timehands->th_counter;
8125b1a8eb3SPoul-Henning Kamp 	u = tc->tc_get_timecount(tc) & tc->tc_counter_mask;
8135b1a8eb3SPoul-Henning Kamp 	if (u < last)
814fccfcfbaSPoul-Henning Kamp 		base += (uint64_t)tc->tc_counter_mask + 1;
8155b1a8eb3SPoul-Henning Kamp 	last = u;
8165b1a8eb3SPoul-Henning Kamp 	return (u + base);
8175b1a8eb3SPoul-Henning Kamp }
8185b1a8eb3SPoul-Henning Kamp 
819e8444a7eSPoul-Henning Kamp /*
820e8444a7eSPoul-Henning Kamp  * This function gets called ever 16 seconds on only one designated
821e8444a7eSPoul-Henning Kamp  * CPU in the system from hardclock() via tc_ticktock().
822e8444a7eSPoul-Henning Kamp  *
823e8444a7eSPoul-Henning Kamp  * Whenever the real time clock is stepped we get called with reset=1
824e8444a7eSPoul-Henning Kamp  * to make sure we handle suspend/resume and similar events correctly.
825e8444a7eSPoul-Henning Kamp  */
826e8444a7eSPoul-Henning Kamp 
827e8444a7eSPoul-Henning Kamp static void
828e8444a7eSPoul-Henning Kamp cpu_tick_calibrate(int reset)
829e8444a7eSPoul-Henning Kamp {
830e8444a7eSPoul-Henning Kamp 	static uint64_t c_last;
831e8444a7eSPoul-Henning Kamp 	uint64_t c_this, c_delta;
832e8444a7eSPoul-Henning Kamp 	static struct bintime  t_last;
833e8444a7eSPoul-Henning Kamp 	struct bintime t_this, t_delta;
834301af28aSPoul-Henning Kamp 	uint32_t divi;
835e8444a7eSPoul-Henning Kamp 
836e8444a7eSPoul-Henning Kamp 	if (reset) {
837e8444a7eSPoul-Henning Kamp 		/* The clock was stepped, abort & reset */
838e8444a7eSPoul-Henning Kamp 		t_last.sec = 0;
839e8444a7eSPoul-Henning Kamp 		return;
840e8444a7eSPoul-Henning Kamp 	}
841e8444a7eSPoul-Henning Kamp 
842e8444a7eSPoul-Henning Kamp 	/* we don't calibrate fixed rate cputicks */
843e8444a7eSPoul-Henning Kamp 	if (!cpu_tick_variable)
844e8444a7eSPoul-Henning Kamp 		return;
845e8444a7eSPoul-Henning Kamp 
846e8444a7eSPoul-Henning Kamp 	getbinuptime(&t_this);
847e8444a7eSPoul-Henning Kamp 	c_this = cpu_ticks();
848e8444a7eSPoul-Henning Kamp 	if (t_last.sec != 0) {
849e8444a7eSPoul-Henning Kamp 		c_delta = c_this - c_last;
850e8444a7eSPoul-Henning Kamp 		t_delta = t_this;
851e8444a7eSPoul-Henning Kamp 		bintime_sub(&t_delta, &t_last);
852e8444a7eSPoul-Henning Kamp 		/*
853e8444a7eSPoul-Henning Kamp 		 * Validate that 16 +/- 1/256 seconds passed.
854e8444a7eSPoul-Henning Kamp 		 * After division by 16 this gives us a precision of
855e8444a7eSPoul-Henning Kamp 		 * roughly 250PPM which is sufficient
856e8444a7eSPoul-Henning Kamp 		 */
857e8444a7eSPoul-Henning Kamp 		if (t_delta.sec > 16 || (
858e8444a7eSPoul-Henning Kamp 		    t_delta.sec == 16 && t_delta.frac >= (0x01LL << 56))) {
859e8444a7eSPoul-Henning Kamp 			/* too long */
860301af28aSPoul-Henning Kamp 			if (bootverbose)
8616cda760fSPoul-Henning Kamp 				printf("%ju.%016jx too long\n",
8626cda760fSPoul-Henning Kamp 				    (uintmax_t)t_delta.sec,
8636cda760fSPoul-Henning Kamp 				    (uintmax_t)t_delta.frac);
864e8444a7eSPoul-Henning Kamp 		} else if (t_delta.sec < 15 ||
865e8444a7eSPoul-Henning Kamp 		    (t_delta.sec == 15 && t_delta.frac <= (0xffLL << 56))) {
866e8444a7eSPoul-Henning Kamp 			/* too short */
867301af28aSPoul-Henning Kamp 			if (bootverbose)
8686cda760fSPoul-Henning Kamp 				printf("%ju.%016jx too short\n",
8696cda760fSPoul-Henning Kamp 				    (uintmax_t)t_delta.sec,
8706cda760fSPoul-Henning Kamp 				    (uintmax_t)t_delta.frac);
871e8444a7eSPoul-Henning Kamp 		} else {
872e8444a7eSPoul-Henning Kamp 			/* just right */
873301af28aSPoul-Henning Kamp 			/*
874301af28aSPoul-Henning Kamp 			 * Headroom:
875301af28aSPoul-Henning Kamp 			 * 	2^(64-20) / 16[s] =
876301af28aSPoul-Henning Kamp 			 * 	2^(44) / 16[s] =
877301af28aSPoul-Henning Kamp 			 * 	17.592.186.044.416 / 16 =
878301af28aSPoul-Henning Kamp 			 * 	1.099.511.627.776 [Hz]
879301af28aSPoul-Henning Kamp 			 */
880301af28aSPoul-Henning Kamp 			divi = t_delta.sec << 20;
881301af28aSPoul-Henning Kamp 			divi |= t_delta.frac >> (64 - 20);
882301af28aSPoul-Henning Kamp 			c_delta <<= 20;
883301af28aSPoul-Henning Kamp 			c_delta /= divi;
884e8444a7eSPoul-Henning Kamp 			if (c_delta  > cpu_tick_frequency) {
885301af28aSPoul-Henning Kamp 				if (bootverbose)
8866cda760fSPoul-Henning Kamp 					printf("cpu_tick increased to %ju Hz",
8876cda760fSPoul-Henning Kamp 					    c_delta);
888e8444a7eSPoul-Henning Kamp 				cpu_tick_frequency = c_delta;
889e8444a7eSPoul-Henning Kamp 			}
890e8444a7eSPoul-Henning Kamp 		}
891e8444a7eSPoul-Henning Kamp 	}
892e8444a7eSPoul-Henning Kamp 	c_last = c_this;
893e8444a7eSPoul-Henning Kamp 	t_last = t_this;
894e8444a7eSPoul-Henning Kamp }
895e8444a7eSPoul-Henning Kamp 
896e8444a7eSPoul-Henning Kamp void
897e8444a7eSPoul-Henning Kamp set_cputicker(cpu_tick_f *func, uint64_t freq, unsigned var)
898e8444a7eSPoul-Henning Kamp {
899e8444a7eSPoul-Henning Kamp 
900e8444a7eSPoul-Henning Kamp 	if (func == NULL) {
901e8444a7eSPoul-Henning Kamp 		cpu_ticks = tc_cpu_ticks;
902e8444a7eSPoul-Henning Kamp 	} else {
903e8444a7eSPoul-Henning Kamp 		cpu_tick_frequency = freq;
904e8444a7eSPoul-Henning Kamp 		cpu_tick_variable = var;
905e8444a7eSPoul-Henning Kamp 		cpu_ticks = func;
906e8444a7eSPoul-Henning Kamp 	}
907e8444a7eSPoul-Henning Kamp }
908e8444a7eSPoul-Henning Kamp 
909e8444a7eSPoul-Henning Kamp uint64_t
910e8444a7eSPoul-Henning Kamp cpu_tickrate(void)
911e8444a7eSPoul-Henning Kamp {
912e8444a7eSPoul-Henning Kamp 
913e8444a7eSPoul-Henning Kamp 	if (cpu_ticks == tc_cpu_ticks)
914e8444a7eSPoul-Henning Kamp 		return (tc_getfrequency());
915e8444a7eSPoul-Henning Kamp 	return (cpu_tick_frequency);
916e8444a7eSPoul-Henning Kamp }
917e8444a7eSPoul-Henning Kamp 
918e8444a7eSPoul-Henning Kamp /*
919e8444a7eSPoul-Henning Kamp  * We need to be slightly careful converting cputicks to microseconds.
920e8444a7eSPoul-Henning Kamp  * There is plenty of margin in 64 bits of microseconds (half a million
921e8444a7eSPoul-Henning Kamp  * years) and in 64 bits at 4 GHz (146 years), but if we do a multiply
922e8444a7eSPoul-Henning Kamp  * before divide conversion (to retain precision) we find that the
923e8444a7eSPoul-Henning Kamp  * margin shrinks to 1.5 hours (one millionth of 146y).
924e8444a7eSPoul-Henning Kamp  * With a three prong approach we never loose significant bits, no
925e8444a7eSPoul-Henning Kamp  * matter what the cputick rate and length of timeinterval is.
926e8444a7eSPoul-Henning Kamp  */
927e8444a7eSPoul-Henning Kamp 
928e8444a7eSPoul-Henning Kamp uint64_t
929e8444a7eSPoul-Henning Kamp cputick2usec(uint64_t tick)
930e8444a7eSPoul-Henning Kamp {
931e8444a7eSPoul-Henning Kamp 
932e8444a7eSPoul-Henning Kamp 	if (tick > 18446744073709551LL)		/* floor(2^64 / 1000) */
933e8444a7eSPoul-Henning Kamp 		return (tick / (cpu_tickrate() / 1000000LL));
934e8444a7eSPoul-Henning Kamp 	else if (tick > 18446744073709LL)	/* floor(2^64 / 1000000) */
935e8444a7eSPoul-Henning Kamp 		return ((tick * 1000LL) / (cpu_tickrate() / 1000LL));
936e8444a7eSPoul-Henning Kamp 	else
937e8444a7eSPoul-Henning Kamp 		return ((tick * 1000000LL) / cpu_tickrate());
938e8444a7eSPoul-Henning Kamp }
939e8444a7eSPoul-Henning Kamp 
940e8444a7eSPoul-Henning Kamp cpu_tick_f	*cpu_ticks = tc_cpu_ticks;
941