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