kern_tc.c revision 91065
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 91065 2002-02-22 12:59:20Z phk $
10 */
11
12#include "opt_ntp.h"
13
14#include <sys/param.h>
15#include <sys/timetc.h>
16#include <sys/malloc.h>
17#include <sys/kernel.h>
18#include <sys/sysctl.h>
19#include <sys/systm.h>
20#include <sys/timex.h>
21#include <sys/timepps.h>
22
23/*
24 * Number of timecounters used to implement stable storage
25 */
26#ifndef NTIMECOUNTER
27#define NTIMECOUNTER	hz
28#endif
29
30static MALLOC_DEFINE(M_TIMECOUNTER, "timecounter",
31	"Timecounter stable storage");
32
33static void tco_setscales __P((struct timecounter *tc));
34static __inline unsigned tco_delta __P((struct timecounter *tc));
35
36time_t time_second;
37
38struct	bintime boottimebin;
39struct	timeval boottime;
40SYSCTL_STRUCT(_kern, KERN_BOOTTIME, boottime, CTLFLAG_RD,
41    &boottime, timeval, "System boottime");
42
43SYSCTL_NODE(_kern, OID_AUTO, timecounter, CTLFLAG_RW, 0, "");
44
45static unsigned nmicrotime;
46static unsigned nnanotime;
47static unsigned ngetmicrotime;
48static unsigned ngetnanotime;
49static unsigned nmicrouptime;
50static unsigned nnanouptime;
51static unsigned ngetmicrouptime;
52static unsigned ngetnanouptime;
53SYSCTL_INT(_kern_timecounter, OID_AUTO, nmicrotime, CTLFLAG_RD, &nmicrotime, 0, "");
54SYSCTL_INT(_kern_timecounter, OID_AUTO, nnanotime, CTLFLAG_RD, &nnanotime, 0, "");
55SYSCTL_INT(_kern_timecounter, OID_AUTO, nmicrouptime, CTLFLAG_RD, &nmicrouptime, 0, "");
56SYSCTL_INT(_kern_timecounter, OID_AUTO, nnanouptime, CTLFLAG_RD, &nnanouptime, 0, "");
57SYSCTL_INT(_kern_timecounter, OID_AUTO, ngetmicrotime, CTLFLAG_RD, &ngetmicrotime, 0, "");
58SYSCTL_INT(_kern_timecounter, OID_AUTO, ngetnanotime, CTLFLAG_RD, &ngetnanotime, 0, "");
59SYSCTL_INT(_kern_timecounter, OID_AUTO, ngetmicrouptime, CTLFLAG_RD, &ngetmicrouptime, 0, "");
60SYSCTL_INT(_kern_timecounter, OID_AUTO, ngetnanouptime, CTLFLAG_RD, &ngetnanouptime, 0, "");
61
62/*
63 * Implement a dummy timecounter which we can use until we get a real one
64 * in the air.  This allows the console and other early stuff to use
65 * timeservices.
66 */
67
68static unsigned
69dummy_get_timecount(struct timecounter *tc)
70{
71	static unsigned now;
72
73	return (++now);
74}
75
76static struct timecounter dummy_timecounter = {
77	dummy_get_timecount,
78	0,
79	~0u,
80	1000000,
81	"dummy"
82};
83
84struct timecounter *volatile timecounter = &dummy_timecounter;
85
86static __inline unsigned
87tco_delta(struct timecounter *tc)
88{
89
90	return ((tc->tc_get_timecount(tc) - tc->tc_offset_count) &
91	    tc->tc_counter_mask);
92}
93
94/*
95 * We have eight functions for looking at the clock, four for
96 * microseconds and four for nanoseconds.  For each there is fast
97 * but less precise version "get{nano|micro}[up]time" which will
98 * return a time which is up to 1/HZ previous to the call, whereas
99 * the raw version "{nano|micro}[up]time" will return a timestamp
100 * which is as precise as possible.  The "up" variants return the
101 * time relative to system boot, these are well suited for time
102 * interval measurements.
103 */
104
105void
106binuptime(struct bintime *bt)
107{
108	struct timecounter *tc;
109
110	tc = timecounter;
111	*bt = tc->tc_offset;
112	bintime_addx(bt, tc->tc_scale * tco_delta(tc));
113}
114
115void
116bintime(struct bintime *bt)
117{
118
119	binuptime(bt);
120	bintime_add(bt, &boottimebin);
121}
122
123void
124getmicrotime(struct timeval *tvp)
125{
126	struct timecounter *tc;
127
128	ngetmicrotime++;
129	tc = timecounter;
130	*tvp = tc->tc_microtime;
131}
132
133void
134getnanotime(struct timespec *tsp)
135{
136	struct timecounter *tc;
137
138	ngetnanotime++;
139	tc = timecounter;
140	*tsp = tc->tc_nanotime;
141}
142
143void
144microtime(struct timeval *tv)
145{
146	struct bintime bt;
147
148	nmicrotime++;
149	bintime(&bt);
150	bintime2timeval(&bt, tv);
151}
152
153void
154nanotime(struct timespec *ts)
155{
156	struct bintime bt;
157
158	nnanotime++;
159	bintime(&bt);
160	bintime2timespec(&bt, ts);
161}
162
163void
164getmicrouptime(struct timeval *tvp)
165{
166	struct timecounter *tc;
167
168	ngetmicrouptime++;
169	tc = timecounter;
170	bintime2timeval(&tc->tc_offset, tvp);
171}
172
173void
174getnanouptime(struct timespec *tsp)
175{
176	struct timecounter *tc;
177
178	ngetnanouptime++;
179	tc = timecounter;
180	bintime2timespec(&tc->tc_offset, tsp);
181}
182
183void
184microuptime(struct timeval *tv)
185{
186	struct bintime bt;
187
188	nmicrouptime++;
189	binuptime(&bt);
190	bintime2timeval(&bt, tv);
191}
192
193void
194nanouptime(struct timespec *ts)
195{
196	struct bintime bt;
197
198	nnanouptime++;
199	binuptime(&bt);
200	bintime2timespec(&bt, ts);
201}
202
203static void
204tco_setscales(struct timecounter *tc)
205{
206	u_int64_t scale;
207
208	/* Sacrifice the lower bit to the deity for code clarity */
209	scale = 1ULL << 63;
210	/*
211	 * We get nanoseconds with 32 bit binary fraction and want
212	 * 64 bit binary fraction: x = a * 2^32 / 10^9 = a * 4.294967296
213	 * The range is +/- 500PPM so we can multiply by about 8500
214	 * without overflowing.  4398/1024 = is very close to ideal.
215	 */
216	scale += (tc->tc_adjustment * 4398) >> 10;
217	scale /= tc->tc_tweak->tc_frequency;
218	tc->tc_scale = scale * 2;
219}
220
221void
222tc_update(struct timecounter *tc)
223{
224	tco_setscales(tc);
225}
226
227void
228tc_init(struct timecounter *tc)
229{
230	struct timecounter *t1, *t2, *t3;
231	int i;
232
233	tc->tc_adjustment = 0;
234	tc->tc_tweak = tc;
235	tco_setscales(tc);
236	tc->tc_offset_count = tc->tc_get_timecount(tc);
237	if (timecounter == &dummy_timecounter)
238		tc->tc_avail = tc;
239	else {
240		tc->tc_avail = timecounter->tc_tweak->tc_avail;
241		timecounter->tc_tweak->tc_avail = tc;
242	}
243	MALLOC(t1, struct timecounter *, sizeof *t1, M_TIMECOUNTER, M_WAITOK);
244	tc->tc_other = t1;
245	*t1 = *tc;
246	t2 = t1;
247	t3 = NULL;
248	for (i = 1; i < NTIMECOUNTER; i++) {
249		MALLOC(t3, struct timecounter *, sizeof *t3,
250		    M_TIMECOUNTER, M_WAITOK);
251		*t3 = *tc;
252		t3->tc_other = t2;
253		t2 = t3;
254	}
255	t1->tc_other = t3;
256	tc = t1;
257
258	printf("Timecounter \"%s\"  frequency %lu Hz\n",
259	    tc->tc_name, (u_long)tc->tc_frequency);
260
261	/* XXX: For now always start using the counter. */
262	tc->tc_offset_count = tc->tc_get_timecount(tc);
263	binuptime(&tc->tc_offset);
264	timecounter = tc;
265}
266
267void
268tc_setclock(struct timespec *ts)
269{
270	struct timespec ts2;
271
272	nanouptime(&ts2);
273	boottime.tv_sec = ts->tv_sec - ts2.tv_sec;
274	boottime.tv_usec = (ts->tv_nsec - ts2.tv_nsec) / 1000;
275	if (boottime.tv_usec < 0) {
276		boottime.tv_usec += 1000000;
277		boottime.tv_sec--;
278	}
279	timeval2bintime(&boottime, &boottimebin);
280	/* fiddle all the little crinkly bits around the fiords... */
281	tc_windup();
282}
283
284static void
285switch_timecounter(struct timecounter *newtc)
286{
287	int s;
288	struct timecounter *tc;
289
290	s = splclock();
291	tc = timecounter;
292	if (newtc->tc_tweak == tc->tc_tweak) {
293		splx(s);
294		return;
295	}
296	newtc = newtc->tc_tweak->tc_other;
297	binuptime(&newtc->tc_offset);
298	newtc->tc_offset_count = newtc->tc_get_timecount(newtc);
299	tco_setscales(newtc);
300	timecounter = newtc;
301	splx(s);
302}
303
304static struct timecounter *
305sync_other_counter(void)
306{
307	struct timecounter *tc, *tcn, *tco;
308	unsigned delta;
309
310	tco = timecounter;
311	tc = tco->tc_other;
312	tcn = tc->tc_other;
313	*tc = *tco;
314	tc->tc_other = tcn;
315	delta = tco_delta(tc);
316	tc->tc_offset_count += delta;
317	tc->tc_offset_count &= tc->tc_counter_mask;
318	bintime_addx(&tc->tc_offset, tc->tc_scale * delta);
319	return (tc);
320}
321
322void
323tc_windup(void)
324{
325	struct timecounter *tc, *tco;
326	struct bintime bt;
327	struct timeval tvt;
328	int i;
329
330	tco = timecounter;
331	tc = sync_other_counter();
332	/*
333	 * We may be inducing a tiny error here, the tc_poll_pps() may
334	 * process a latched count which happens after the tco_delta()
335	 * in sync_other_counter(), which would extend the previous
336	 * counters parameters into the domain of this new one.
337	 * Since the timewindow is very small for this, the error is
338	 * going to be only a few weenieseconds (as Dave Mills would
339	 * say), so lets just not talk more about it, OK ?
340	 */
341	if (tco->tc_poll_pps)
342		tco->tc_poll_pps(tco);
343	if (timedelta != 0) {
344		tvt = boottime;
345		tvt.tv_usec += tickdelta;
346		if (tvt.tv_usec >= 1000000) {
347			tvt.tv_sec++;
348			tvt.tv_usec -= 1000000;
349		} else if (tvt.tv_usec < 0) {
350			tvt.tv_sec--;
351			tvt.tv_usec += 1000000;
352		}
353		boottime = tvt;
354		timeval2bintime(&boottime, &boottimebin);
355		timedelta -= tickdelta;
356	}
357	for (i = tc->tc_offset.sec - tco->tc_offset.sec; i > 0; i--) {
358		ntp_update_second(tc);	/* XXX only needed if xntpd runs */
359		tco_setscales(tc);
360	}
361
362	bt = tc->tc_offset;
363	bintime_add(&bt, &boottimebin);
364	bintime2timeval(&bt, &tc->tc_microtime);
365	bintime2timespec(&bt, &tc->tc_nanotime);
366	time_second = tc->tc_microtime.tv_sec;
367	timecounter = 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->tc_tweak;
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 &&
381	    strcmp(newname, tc->tc_name) != 0) {
382		for (newtc = tc->tc_avail; newtc != tc;
383		    newtc = newtc->tc_avail) {
384			if (strcmp(newname, newtc->tc_name) == 0) {
385				/* Warm up new timecounter. */
386				(void)newtc->tc_get_timecount(newtc);
387
388				switch_timecounter(newtc);
389				return (0);
390			}
391		}
392		return (EINVAL);
393	}
394	return (error);
395}
396
397SYSCTL_PROC(_kern_timecounter, OID_AUTO, hardware, CTLTYPE_STRING | CTLFLAG_RW,
398    0, 0, sysctl_kern_timecounter_hardware, "A", "");
399
400
401int
402pps_ioctl(u_long cmd, caddr_t data, struct pps_state *pps)
403{
404	pps_params_t *app;
405	struct pps_fetch_args *fapi;
406#ifdef PPS_SYNC
407	struct pps_kcbind_args *kapi;
408#endif
409
410	switch (cmd) {
411	case PPS_IOC_CREATE:
412		return (0);
413	case PPS_IOC_DESTROY:
414		return (0);
415	case PPS_IOC_SETPARAMS:
416		app = (pps_params_t *)data;
417		if (app->mode & ~pps->ppscap)
418			return (EINVAL);
419		pps->ppsparam = *app;
420		return (0);
421	case PPS_IOC_GETPARAMS:
422		app = (pps_params_t *)data;
423		*app = pps->ppsparam;
424		app->api_version = PPS_API_VERS_1;
425		return (0);
426	case PPS_IOC_GETCAP:
427		*(int*)data = pps->ppscap;
428		return (0);
429	case PPS_IOC_FETCH:
430		fapi = (struct pps_fetch_args *)data;
431		if (fapi->tsformat && fapi->tsformat != PPS_TSFMT_TSPEC)
432			return (EINVAL);
433		if (fapi->timeout.tv_sec || fapi->timeout.tv_nsec)
434			return (EOPNOTSUPP);
435		pps->ppsinfo.current_mode = pps->ppsparam.mode;
436		fapi->pps_info_buf = pps->ppsinfo;
437		return (0);
438	case PPS_IOC_KCBIND:
439#ifdef PPS_SYNC
440		kapi = (struct pps_kcbind_args *)data;
441		/* XXX Only root should be able to do this */
442		if (kapi->tsformat && kapi->tsformat != PPS_TSFMT_TSPEC)
443			return (EINVAL);
444		if (kapi->kernel_consumer != PPS_KC_HARDPPS)
445			return (EINVAL);
446		if (kapi->edge & ~pps->ppscap)
447			return (EINVAL);
448		pps->kcmode = kapi->edge;
449		return (0);
450#else
451		return (EOPNOTSUPP);
452#endif
453	default:
454		return (ENOTTY);
455	}
456}
457
458void
459pps_init(struct pps_state *pps)
460{
461	pps->ppscap |= PPS_TSFMT_TSPEC;
462	if (pps->ppscap & PPS_CAPTUREASSERT)
463		pps->ppscap |= PPS_OFFSETASSERT;
464	if (pps->ppscap & PPS_CAPTURECLEAR)
465		pps->ppscap |= PPS_OFFSETCLEAR;
466}
467
468void
469pps_event(struct pps_state *pps, struct timecounter *tc, unsigned count, int event)
470{
471	struct timespec ts, *tsp, *osp;
472	unsigned tcount, *pcount;
473	struct bintime bt;
474	int foff, fhard;
475	pps_seq_t	*pseq;
476
477	/* Things would be easier with arrays... */
478	if (event == PPS_CAPTUREASSERT) {
479		tsp = &pps->ppsinfo.assert_timestamp;
480		osp = &pps->ppsparam.assert_offset;
481		foff = pps->ppsparam.mode & PPS_OFFSETASSERT;
482		fhard = pps->kcmode & PPS_CAPTUREASSERT;
483		pcount = &pps->ppscount[0];
484		pseq = &pps->ppsinfo.assert_sequence;
485	} else {
486		tsp = &pps->ppsinfo.clear_timestamp;
487		osp = &pps->ppsparam.clear_offset;
488		foff = pps->ppsparam.mode & PPS_OFFSETCLEAR;
489		fhard = pps->kcmode & PPS_CAPTURECLEAR;
490		pcount = &pps->ppscount[1];
491		pseq = &pps->ppsinfo.clear_sequence;
492	}
493
494	/* The timecounter changed: bail */
495	if (!pps->ppstc ||
496	    pps->ppstc->tc_name != tc->tc_name ||
497	    tc->tc_name != timecounter->tc_name) {
498		pps->ppstc = tc;
499		*pcount = count;
500		return;
501	}
502
503	/* Nothing really happened */
504	if (*pcount == count)
505		return;
506
507	*pcount = count;
508
509	/* Convert the count to timespec */
510	tcount = count - tc->tc_offset_count;
511	tcount &= tc->tc_counter_mask;
512	bt = tc->tc_offset;
513	bintime_addx(&bt, tc->tc_scale * tcount);
514	bintime2timespec(&bt, &ts);
515
516	(*pseq)++;
517	*tsp = ts;
518
519	if (foff) {
520		timespecadd(tsp, osp);
521		if (tsp->tv_nsec < 0) {
522			tsp->tv_nsec += 1000000000;
523			tsp->tv_sec -= 1;
524		}
525	}
526#ifdef PPS_SYNC
527	if (fhard) {
528		u_int64_t delta;
529		/* magic, at its best... */
530		tcount = count - pps->ppscount[2];
531		pps->ppscount[2] = count;
532		tcount &= tc->tc_counter_mask;
533		bt.sec = 0;
534		bt.frac = 0;
535		bintime_addx(&bt, tc->tc_scale * tcount);
536		bintime2timespec(&bt, &ts);
537		hardpps(tsp, ts.tv_nsec + 1000000000 * ts.tv_sec);
538	}
539#endif
540}
541