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