kern_tc.c revision 95659
1/*
2 * ----------------------------------------------------------------------------
3 * "THE BEER-WARE LICENSE" (Revision 42):
4 * <phk@FreeBSD.ORG> wrote this file.  As long as you retain this notice you
5 * can do whatever you want with this stuff. If we meet some day, and you think
6 * this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp
7 * ----------------------------------------------------------------------------
8 *
9 * $FreeBSD: head/sys/kern/kern_tc.c 95659 2002-04-28 16:51:36Z phk $
10 */
11
12#include "opt_ntp.h"
13
14#include <sys/param.h>
15#include <sys/timetc.h>
16#include <sys/kernel.h>
17#include <sys/sysctl.h>
18#include <sys/systm.h>
19#include <sys/timex.h>
20#include <sys/timepps.h>
21
22/*
23 * Implement a dummy timecounter which we can use until we get a real one
24 * in the air.  This allows the console and other early stuff to use
25 * timeservices.
26 */
27
28static unsigned
29dummy_get_timecount(struct timecounter *tc)
30{
31	static unsigned now;
32
33	return (++now);
34}
35
36static struct timecounter dummy_timecounter = {
37	dummy_get_timecount,
38	0,
39	~0u,
40	1000000,
41	"dummy"
42};
43
44struct timehands {
45	/* These fields must be initialized by the driver. */
46	struct timecounter	*tc_counter;
47	int64_t			tc_adjustment;
48	u_int64_t		tc_scale;
49	unsigned 		tc_offset_count;
50	struct bintime		tc_offset;
51	struct timeval		tc_microtime;
52	struct timespec		tc_nanotime;
53	/* Fields not to be copied in tc_windup start with tc_generation */
54	volatile unsigned	tc_generation;
55	struct timehands	*tc_next;
56};
57
58
59extern struct timehands th0;
60static struct timehands th9 = { NULL, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 1, &th0};
61static struct timehands th8 = { NULL, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 1, &th9};
62static struct timehands th7 = { NULL, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 1, &th8};
63static struct timehands th6 = { NULL, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 1, &th7};
64static struct timehands th5 = { NULL, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 1, &th6};
65static struct timehands th4 = { NULL, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 1, &th5};
66static struct timehands th3 = { NULL, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 1, &th4};
67static struct timehands th2 = { NULL, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 1, &th3};
68static struct timehands th1 = { NULL, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 1, &th2};
69static struct timehands th0 = {
70	&dummy_timecounter,
71	0,
72	18446744073709ULL,	/* 2^64/1000000 */
73	0,
74	{1, 0},
75	{0, 0},
76	{0, 0},
77	1,
78	&th1
79};
80
81static struct timehands *volatile timehands = &th0;
82struct timecounter *timecounter = &dummy_timecounter;
83static struct timecounter *timecounters = &dummy_timecounter;
84
85time_t time_second;
86
87struct	bintime boottimebin;
88struct	timeval boottime;
89SYSCTL_STRUCT(_kern, KERN_BOOTTIME, boottime, CTLFLAG_RD,
90    &boottime, timeval, "System boottime");
91
92SYSCTL_NODE(_kern, OID_AUTO, timecounter, CTLFLAG_RW, 0, "");
93
94#define TC_STATS(foo) \
95	static unsigned foo; \
96	SYSCTL_INT(_kern_timecounter, OID_AUTO, foo, CTLFLAG_RD, & foo, 0, "")
97
98TC_STATS(nbinuptime);    TC_STATS(nnanouptime);    TC_STATS(nmicrouptime);
99TC_STATS(nbintime);      TC_STATS(nnanotime);      TC_STATS(nmicrotime);
100TC_STATS(ngetbinuptime); TC_STATS(ngetnanouptime); TC_STATS(ngetmicrouptime);
101TC_STATS(ngetbintime);   TC_STATS(ngetnanotime);   TC_STATS(ngetmicrotime);
102
103#undef TC_STATS
104
105static void tc_windup(void);
106
107
108static __inline unsigned
109tc_delta(struct timehands *tc)
110{
111
112	return ((tc->tc_counter->tc_get_timecount(tc->tc_counter) -
113	    tc->tc_offset_count) & tc->tc_counter->tc_counter_mask);
114}
115
116void
117binuptime(struct bintime *bt)
118{
119	struct timehands *tc;
120	unsigned gen;
121
122	nbinuptime++;
123	do {
124		tc = timehands;
125		gen = tc->tc_generation;
126		*bt = tc->tc_offset;
127		bintime_addx(bt, tc->tc_scale * tc_delta(tc));
128	} while (gen == 0 || gen != tc->tc_generation);
129}
130
131void
132nanouptime(struct timespec *ts)
133{
134	struct bintime bt;
135
136	nnanouptime++;
137	binuptime(&bt);
138	bintime2timespec(&bt, ts);
139}
140
141void
142microuptime(struct timeval *tv)
143{
144	struct bintime bt;
145
146	nmicrouptime++;
147	binuptime(&bt);
148	bintime2timeval(&bt, tv);
149}
150
151void
152bintime(struct bintime *bt)
153{
154
155	nbintime++;
156	binuptime(bt);
157	bintime_add(bt, &boottimebin);
158}
159
160void
161nanotime(struct timespec *ts)
162{
163	struct bintime bt;
164
165	nnanotime++;
166	bintime(&bt);
167	bintime2timespec(&bt, ts);
168}
169
170void
171microtime(struct timeval *tv)
172{
173	struct bintime bt;
174
175	nmicrotime++;
176	bintime(&bt);
177	bintime2timeval(&bt, tv);
178}
179
180void
181getbinuptime(struct bintime *bt)
182{
183	struct timehands *tc;
184	unsigned gen;
185
186	ngetbinuptime++;
187	do {
188		tc = timehands;
189		gen = tc->tc_generation;
190		*bt = tc->tc_offset;
191	} while (gen == 0 || gen != tc->tc_generation);
192}
193
194void
195getnanouptime(struct timespec *tsp)
196{
197	struct timehands *tc;
198	unsigned gen;
199
200	ngetnanouptime++;
201	do {
202		tc = timehands;
203		gen = tc->tc_generation;
204		bintime2timespec(&tc->tc_offset, tsp);
205	} while (gen == 0 || gen != tc->tc_generation);
206}
207
208void
209getmicrouptime(struct timeval *tvp)
210{
211	struct timehands *tc;
212	unsigned gen;
213
214	ngetmicrouptime++;
215	do {
216		tc = timehands;
217		gen = tc->tc_generation;
218		bintime2timeval(&tc->tc_offset, tvp);
219	} while (gen == 0 || gen != tc->tc_generation);
220}
221
222void
223getbintime(struct bintime *bt)
224{
225	struct timehands *tc;
226	unsigned gen;
227
228	ngetbintime++;
229	do {
230		tc = timehands;
231		gen = tc->tc_generation;
232		*bt = tc->tc_offset;
233	} while (gen == 0 || gen != tc->tc_generation);
234	bintime_add(bt, &boottimebin);
235}
236
237void
238getnanotime(struct timespec *tsp)
239{
240	struct timehands *tc;
241	unsigned gen;
242
243	ngetnanotime++;
244	do {
245		tc = timehands;
246		gen = tc->tc_generation;
247		*tsp = tc->tc_nanotime;
248	} while (gen == 0 || gen != tc->tc_generation);
249}
250
251void
252getmicrotime(struct timeval *tvp)
253{
254	struct timehands *tc;
255	unsigned gen;
256
257	ngetmicrotime++;
258	do {
259		tc = timehands;
260		gen = tc->tc_generation;
261		*tvp = tc->tc_microtime;
262	} while (gen == 0 || gen != tc->tc_generation);
263}
264
265static void
266tc_setscales(struct timehands *tc)
267{
268	u_int64_t scale;
269
270	/* Sacrifice the lower bit to the deity for code clarity */
271	scale = 1ULL << 63;
272	/*
273	 * We get nanoseconds with 32 bit binary fraction and want
274	 * 64 bit binary fraction: x = a * 2^32 / 10^9 = a * 4.294967296
275	 * The range is +/- 5000PPM so we can only multiply by about 850
276	 * without overflowing.  The best suitable fraction is 2199/512.
277	 * Divide by 2 times 512 to match the temporary lower precision.
278	 */
279	scale += (tc->tc_adjustment / 1024) * 2199;
280	scale /= tc->tc_counter->tc_frequency;
281	tc->tc_scale = scale * 2;
282}
283
284void
285tc_init(struct timecounter *tc)
286{
287
288	tc->tc_next = timecounters;
289	timecounters = tc;
290	printf("Timecounter \"%s\"  frequency %lu Hz\n",
291	    tc->tc_name, (u_long)tc->tc_frequency);
292	timecounter = tc;
293}
294
295u_int32_t
296tc_getfrequency(void)
297{
298
299	return (timehands->tc_counter->tc_frequency);
300}
301
302void
303tc_setclock(struct timespec *ts)
304{
305	struct timespec ts2;
306
307	nanouptime(&ts2);
308	boottime.tv_sec = ts->tv_sec - ts2.tv_sec;
309	boottime.tv_usec = (ts->tv_nsec - ts2.tv_nsec) / 1000;
310	if (boottime.tv_usec < 0) {
311		boottime.tv_usec += 1000000;
312		boottime.tv_sec--;
313	}
314	timeval2bintime(&boottime, &boottimebin);
315	/* fiddle all the little crinkly bits around the fiords... */
316	tc_windup();
317}
318
319static void
320tc_windup(void)
321{
322	struct timehands *tc, *tco;
323	struct bintime bt;
324	unsigned ogen, delta, ncount;
325	int i;
326
327	ncount = 0;		/* GCC is lame */
328	tco = timehands;
329	tc = tco->tc_next;
330	ogen = tc->tc_generation;
331	tc->tc_generation = 0;
332	bcopy(tco, tc, __offsetof(struct timehands, tc_generation));
333	delta = tc_delta(tc);
334	if (tc->tc_counter != timecounter)
335		ncount = timecounter->tc_get_timecount(timecounter);
336	tc->tc_offset_count += delta;
337	tc->tc_offset_count &= tc->tc_counter->tc_counter_mask;
338	bintime_addx(&tc->tc_offset, tc->tc_scale * delta);
339	/*
340	 * We may be inducing a tiny error here, the tc_poll_pps() may
341	 * process a latched count which happens after the tc_delta()
342	 * in sync_other_counter(), which would extend the previous
343	 * counters parameters into the domain of this new one.
344	 * Since the timewindow is very small for this, the error is
345	 * going to be only a few weenieseconds (as Dave Mills would
346	 * say), so lets just not talk more about it, OK ?
347	 */
348	if (tco->tc_counter->tc_poll_pps)
349		tco->tc_counter->tc_poll_pps(tco->tc_counter);
350	for (i = tc->tc_offset.sec - tco->tc_offset.sec; i > 0; i--)
351		ntp_update_second(&tc->tc_adjustment, &tc->tc_offset.sec);
352	if (tc->tc_counter != timecounter) {
353		tc->tc_counter = timecounter;
354		tc->tc_offset_count = ncount;
355	}
356	tc_setscales(tc);
357
358	bt = tc->tc_offset;
359	bintime_add(&bt, &boottimebin);
360	bintime2timeval(&bt, &tc->tc_microtime);
361	bintime2timespec(&bt, &tc->tc_nanotime);
362	ogen++;
363	if (ogen == 0)
364		ogen++;
365	tc->tc_generation = ogen;
366	time_second = tc->tc_microtime.tv_sec;
367	timehands = tc;
368}
369
370static int
371sysctl_kern_timecounter_hardware(SYSCTL_HANDLER_ARGS)
372{
373	char newname[32];
374	struct timecounter *newtc, *tc;
375	int error;
376
377	tc = timecounter;
378	strncpy(newname, tc->tc_name, sizeof(newname));
379	error = sysctl_handle_string(oidp, &newname[0], sizeof(newname), req);
380	if (error != 0 && req->newptr == NULL && !strcmp(newname, tc->tc_name))
381		return(error);
382	for (newtc = timecounters; newtc != NULL; newtc = newtc->tc_next) {
383		if (strcmp(newname, newtc->tc_name))
384			continue;
385		/* Warm up new timecounter. */
386		(void)newtc->tc_get_timecount(newtc);
387		(void)newtc->tc_get_timecount(newtc);
388		timecounter = newtc;
389		return (0);
390	}
391	return (EINVAL);
392}
393
394SYSCTL_PROC(_kern_timecounter, OID_AUTO, hardware, CTLTYPE_STRING | CTLFLAG_RW,
395    0, 0, sysctl_kern_timecounter_hardware, "A", "");
396
397
398int
399pps_ioctl(u_long cmd, caddr_t data, struct pps_state *pps)
400{
401	pps_params_t *app;
402	struct pps_fetch_args *fapi;
403#ifdef PPS_SYNC
404	struct pps_kcbind_args *kapi;
405#endif
406
407	switch (cmd) {
408	case PPS_IOC_CREATE:
409		return (0);
410	case PPS_IOC_DESTROY:
411		return (0);
412	case PPS_IOC_SETPARAMS:
413		app = (pps_params_t *)data;
414		if (app->mode & ~pps->ppscap)
415			return (EINVAL);
416		pps->ppsparam = *app;
417		return (0);
418	case PPS_IOC_GETPARAMS:
419		app = (pps_params_t *)data;
420		*app = pps->ppsparam;
421		app->api_version = PPS_API_VERS_1;
422		return (0);
423	case PPS_IOC_GETCAP:
424		*(int*)data = pps->ppscap;
425		return (0);
426	case PPS_IOC_FETCH:
427		fapi = (struct pps_fetch_args *)data;
428		if (fapi->tsformat && fapi->tsformat != PPS_TSFMT_TSPEC)
429			return (EINVAL);
430		if (fapi->timeout.tv_sec || fapi->timeout.tv_nsec)
431			return (EOPNOTSUPP);
432		pps->ppsinfo.current_mode = pps->ppsparam.mode;
433		fapi->pps_info_buf = pps->ppsinfo;
434		return (0);
435	case PPS_IOC_KCBIND:
436#ifdef PPS_SYNC
437		kapi = (struct pps_kcbind_args *)data;
438		/* XXX Only root should be able to do this */
439		if (kapi->tsformat && kapi->tsformat != PPS_TSFMT_TSPEC)
440			return (EINVAL);
441		if (kapi->kernel_consumer != PPS_KC_HARDPPS)
442			return (EINVAL);
443		if (kapi->edge & ~pps->ppscap)
444			return (EINVAL);
445		pps->kcmode = kapi->edge;
446		return (0);
447#else
448		return (EOPNOTSUPP);
449#endif
450	default:
451		return (ENOTTY);
452	}
453}
454
455void
456pps_init(struct pps_state *pps)
457{
458	pps->ppscap |= PPS_TSFMT_TSPEC;
459	if (pps->ppscap & PPS_CAPTUREASSERT)
460		pps->ppscap |= PPS_OFFSETASSERT;
461	if (pps->ppscap & PPS_CAPTURECLEAR)
462		pps->ppscap |= PPS_OFFSETCLEAR;
463}
464
465void
466pps_capture(struct pps_state *pps)
467{
468	struct timehands *tc;
469
470	tc = timehands;
471	pps->captc = tc;
472	pps->capgen = tc->tc_generation;
473	pps->capcount = tc->tc_counter->tc_get_timecount(tc->tc_counter);
474}
475
476void
477pps_event(struct pps_state *pps, int event)
478{
479	struct timespec ts, *tsp, *osp;
480	unsigned tcount, *pcount;
481	struct bintime bt;
482	int foff, fhard;
483	pps_seq_t	*pseq;
484
485	/* If the timecounter were wound up, bail. */
486	if (pps->capgen != pps->capgen)
487		return;
488
489	/* Things would be easier with arrays... */
490	if (event == PPS_CAPTUREASSERT) {
491		tsp = &pps->ppsinfo.assert_timestamp;
492		osp = &pps->ppsparam.assert_offset;
493		foff = pps->ppsparam.mode & PPS_OFFSETASSERT;
494		fhard = pps->kcmode & PPS_CAPTUREASSERT;
495		pcount = &pps->ppscount[0];
496		pseq = &pps->ppsinfo.assert_sequence;
497	} else {
498		tsp = &pps->ppsinfo.clear_timestamp;
499		osp = &pps->ppsparam.clear_offset;
500		foff = pps->ppsparam.mode & PPS_OFFSETCLEAR;
501		fhard = pps->kcmode & PPS_CAPTURECLEAR;
502		pcount = &pps->ppscount[1];
503		pseq = &pps->ppsinfo.clear_sequence;
504	}
505
506	/* The timecounter changed: bail */
507	if (!pps->ppstc ||
508	    pps->ppstc != pps->captc->tc_counter ||
509	    pps->captc->tc_counter != timehands->tc_counter) {
510		pps->ppstc = pps->captc->tc_counter;
511		*pcount = pps->capcount;
512#ifdef PPS_SYNC
513		pps->ppscount[2] = pps->capcount;
514#endif
515		return;
516	}
517
518	/* Nothing really happened */
519	if (*pcount == pps->capcount)
520		return;
521
522	/* Convert the count to timespec */
523	tcount = pps->capcount - pps->captc->tc_offset_count;
524	tcount &= pps->captc->tc_counter->tc_counter_mask;
525	bt = pps->captc->tc_offset;
526	bintime_addx(&bt, pps->captc->tc_scale * tcount);
527	bintime2timespec(&bt, &ts);
528
529	/* If the timecounter were wound up, bail. */
530	if (pps->capgen != pps->capgen)
531		return;
532
533	*pcount = pps->capcount;
534	(*pseq)++;
535	*tsp = ts;
536
537	if (foff) {
538		timespecadd(tsp, osp);
539		if (tsp->tv_nsec < 0) {
540			tsp->tv_nsec += 1000000000;
541			tsp->tv_sec -= 1;
542		}
543	}
544#ifdef PPS_SYNC
545	if (fhard) {
546		/* magic, at its best... */
547		tcount = pps->capcount - pps->ppscount[2];
548		pps->ppscount[2] = pps->capcount;
549		tcount &= pps->captc->tc_counter->tc_counter_mask;
550		bt.sec = 0;
551		bt.frac = 0;
552		bintime_addx(&bt, pps->captc->tc_scale * tcount);
553		bintime2timespec(&bt, &ts);
554		hardpps(tsp, ts.tv_nsec + 1000000000 * ts.tv_sec);
555	}
556#endif
557}
558
559/*-
560 * Timecounters need to be updated every so often to prevent the hardware
561 * counter from overflowing.  Updating also recalculates the cached values
562 * used by the get*() family of functions, so their precision depends on
563 * the update frequency.
564 * Don't update faster than approx once per millisecond, if people want
565 * better timestamps they should use the non-"get" functions.
566 */
567
568static int tc_tick;
569SYSCTL_INT(_kern_timecounter, OID_AUTO, tick, CTLFLAG_RD, &tick, 0, "");
570
571static void
572tc_ticktock(void *dummy)
573{
574
575	tc_windup();
576	timeout(tc_ticktock, NULL, tc_tick);
577}
578
579static void
580inittimecounter(void *dummy)
581{
582	u_int p;
583
584	if (hz > 1000)
585		tc_tick = (hz + 500) / 1000;
586	else
587		tc_tick = 1;
588	p = (tc_tick * 1000000) / hz;
589	printf("Timecounters tick every %d.%03u msec\n", p / 1000, p % 1000);
590	tc_ticktock(NULL);
591}
592
593SYSINIT(timecounter, SI_SUB_CLOCKS, SI_ORDER_FIRST, inittimecounter, NULL)
594