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