xref: /freebsd/sys/kern/kern_tc.c (revision 7029da5c36f2d3cf6bb6c81bf551229f416399e8)
139acc78aSPoul-Henning Kamp /*-
264de3fddSPedro F. Giffuni  * SPDX-License-Identifier: Beerware
364de3fddSPedro F. Giffuni  *
491266b96SPoul-Henning Kamp  * ----------------------------------------------------------------------------
591266b96SPoul-Henning Kamp  * "THE BEER-WARE LICENSE" (Revision 42):
691266b96SPoul-Henning Kamp  * <phk@FreeBSD.ORG> wrote this file.  As long as you retain this notice you
791266b96SPoul-Henning Kamp  * can do whatever you want with this stuff. If we meet some day, and you think
891266b96SPoul-Henning Kamp  * this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp
991266b96SPoul-Henning Kamp  * ----------------------------------------------------------------------------
10b0fdc837SLawrence Stewart  *
1116808549SKonstantin Belousov  * Copyright (c) 2011, 2015, 2016 The FreeBSD Foundation
12b0fdc837SLawrence Stewart  * All rights reserved.
13b0fdc837SLawrence Stewart  *
14b0fdc837SLawrence Stewart  * Portions of this software were developed by Julien Ridoux at the University
15b0fdc837SLawrence Stewart  * of Melbourne under sponsorship from the FreeBSD Foundation.
1616808549SKonstantin Belousov  *
1716808549SKonstantin Belousov  * Portions of this software were developed by Konstantin Belousov
1816808549SKonstantin Belousov  * under sponsorship from the FreeBSD Foundation.
19df8bae1dSRodney W. Grimes  */
20df8bae1dSRodney W. Grimes 
21677b542eSDavid E. O'Brien #include <sys/cdefs.h>
22677b542eSDavid E. O'Brien __FBSDID("$FreeBSD$");
23677b542eSDavid E. O'Brien 
2432c20357SPoul-Henning Kamp #include "opt_ntp.h"
25b0fdc837SLawrence Stewart #include "opt_ffclock.h"
2632c20357SPoul-Henning Kamp 
27df8bae1dSRodney W. Grimes #include <sys/param.h>
2891266b96SPoul-Henning Kamp #include <sys/kernel.h>
295b999a6bSDavide Italiano #include <sys/limits.h>
30b0fdc837SLawrence Stewart #include <sys/lock.h>
31b0fdc837SLawrence Stewart #include <sys/mutex.h>
329dbdf2a1SEric van Gyzen #include <sys/proc.h>
3391d9eda2SIan Lepore #include <sys/sbuf.h>
349dbdf2a1SEric van Gyzen #include <sys/sleepqueue.h>
3591266b96SPoul-Henning Kamp #include <sys/sysctl.h>
364e74721cSPoul-Henning Kamp #include <sys/syslog.h>
3791266b96SPoul-Henning Kamp #include <sys/systm.h>
38b0fdc837SLawrence Stewart #include <sys/timeffc.h>
3932c20357SPoul-Henning Kamp #include <sys/timepps.h>
4048e5da55SPoul-Henning Kamp #include <sys/timetc.h>
4139acc78aSPoul-Henning Kamp #include <sys/timex.h>
42aea81038SKonstantin Belousov #include <sys/vdso.h>
4339acc78aSPoul-Henning Kamp 
443bac064fSPoul-Henning Kamp /*
45c1cccd1eSWarner Losh  * A large step happens on boot.  This constant detects such steps.
46c1cccd1eSWarner Losh  * It is relatively small so that ntp_update_second gets called enough
47c1cccd1eSWarner Losh  * in the typical 'missed a couple of seconds' case, but doesn't loop
48c1cccd1eSWarner Losh  * forever when the time step is large.
494f2073fbSWarner Losh  */
504f2073fbSWarner Losh #define LARGE_STEP	200
514f2073fbSWarner Losh 
524f2073fbSWarner Losh /*
5362efba6aSPoul-Henning Kamp  * Implement a dummy timecounter which we can use until we get a real one
5462efba6aSPoul-Henning Kamp  * in the air.  This allows the console and other early stuff to use
5562efba6aSPoul-Henning Kamp  * time services.
563bac064fSPoul-Henning Kamp  */
573bac064fSPoul-Henning Kamp 
586b00cf46SPoul-Henning Kamp static u_int
5962efba6aSPoul-Henning Kamp dummy_get_timecount(struct timecounter *tc)
6062efba6aSPoul-Henning Kamp {
616b00cf46SPoul-Henning Kamp 	static u_int now;
6262efba6aSPoul-Henning Kamp 
6362efba6aSPoul-Henning Kamp 	return (++now);
6462efba6aSPoul-Henning Kamp }
6562efba6aSPoul-Henning Kamp 
6662efba6aSPoul-Henning Kamp static struct timecounter dummy_timecounter = {
6778a49a45SPoul-Henning Kamp 	dummy_get_timecount, 0, ~0u, 1000000, "dummy", -1000000
6862efba6aSPoul-Henning Kamp };
6962efba6aSPoul-Henning Kamp 
7062efba6aSPoul-Henning Kamp struct timehands {
7162efba6aSPoul-Henning Kamp 	/* These fields must be initialized by the driver. */
726b00cf46SPoul-Henning Kamp 	struct timecounter	*th_counter;
736b00cf46SPoul-Henning Kamp 	int64_t			th_adjustment;
7460ae52f7SEd Schouten 	uint64_t		th_scale;
756cf2362eSKonstantin Belousov 	u_int			th_large_delta;
766b00cf46SPoul-Henning Kamp 	u_int	 		th_offset_count;
776b00cf46SPoul-Henning Kamp 	struct bintime		th_offset;
7850c22263SKonstantin Belousov 	struct bintime		th_bintime;
796b00cf46SPoul-Henning Kamp 	struct timeval		th_microtime;
806b00cf46SPoul-Henning Kamp 	struct timespec		th_nanotime;
815760b029SKonstantin Belousov 	struct bintime		th_boottime;
8239acc78aSPoul-Henning Kamp 	/* Fields not to be copied in tc_windup start with th_generation. */
832c6946dcSKonstantin Belousov 	u_int			th_generation;
846b00cf46SPoul-Henning Kamp 	struct timehands	*th_next;
8562efba6aSPoul-Henning Kamp };
8662efba6aSPoul-Henning Kamp 
874b23dec4SKonstantin Belousov static struct timehands ths[16] = {
884b23dec4SKonstantin Belousov     [0] =  {
89a83c016fSKonstantin Belousov 	.th_counter = &dummy_timecounter,
90a83c016fSKonstantin Belousov 	.th_scale = (uint64_t)-1 / 1000000,
916cf2362eSKonstantin Belousov 	.th_large_delta = 1000000,
92a83c016fSKonstantin Belousov 	.th_offset = { .sec = 1 },
93a83c016fSKonstantin Belousov 	.th_generation = 1,
944b23dec4SKonstantin Belousov     },
95f5d157fbSPoul-Henning Kamp };
9662efba6aSPoul-Henning Kamp 
974b23dec4SKonstantin Belousov static struct timehands *volatile timehands = &ths[0];
9862efba6aSPoul-Henning Kamp struct timecounter *timecounter = &dummy_timecounter;
9962efba6aSPoul-Henning Kamp static struct timecounter *timecounters = &dummy_timecounter;
1003bac064fSPoul-Henning Kamp 
1010e189873SAlexander Motin int tc_min_ticktock_freq = 1;
1020e189873SAlexander Motin 
103a8df530dSJohn Baldwin volatile time_t time_second = 1;
104a8df530dSJohn Baldwin volatile time_t time_uptime = 1;
105227ee8a1SPoul-Henning Kamp 
106a7bc3102SPeter Wemm static int sysctl_kern_boottime(SYSCTL_HANDLER_ARGS);
107*7029da5cSPawel Biernacki SYSCTL_PROC(_kern, KERN_BOOTTIME, boottime,
108*7029da5cSPawel Biernacki     CTLTYPE_STRUCT | CTLFLAG_RD | CTLFLAG_MPSAFE, NULL, 0,
109*7029da5cSPawel Biernacki     sysctl_kern_boottime, "S,timeval",
110*7029da5cSPawel Biernacki     "System boottime");
11137d38777SBruce Evans 
112*7029da5cSPawel Biernacki SYSCTL_NODE(_kern, OID_AUTO, timecounter, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
113*7029da5cSPawel Biernacki     "");
114*7029da5cSPawel Biernacki static SYSCTL_NODE(_kern_timecounter, OID_AUTO, tc,
115*7029da5cSPawel Biernacki     CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
116*7029da5cSPawel Biernacki     "");
11791266b96SPoul-Henning Kamp 
1184e74721cSPoul-Henning Kamp static int timestepwarnings;
1194e74721cSPoul-Henning Kamp SYSCTL_INT(_kern_timecounter, OID_AUTO, stepwarnings, CTLFLAG_RW,
1202baa5cddSRebecca Cran     &timestepwarnings, 0, "Log time steps");
1214e74721cSPoul-Henning Kamp 
1224b23dec4SKonstantin Belousov static int timehands_count = 2;
1236c46ce7eSKonstantin Belousov SYSCTL_INT(_kern_timecounter, OID_AUTO, timehands_count,
1246c46ce7eSKonstantin Belousov     CTLFLAG_RDTUN | CTLFLAG_NOFETCH,
1254b23dec4SKonstantin Belousov     &timehands_count, 0, "Count of timehands in rotation");
1264b23dec4SKonstantin Belousov 
1275b999a6bSDavide Italiano struct bintime bt_timethreshold;
1285b999a6bSDavide Italiano struct bintime bt_tickthreshold;
1295b999a6bSDavide Italiano sbintime_t sbt_timethreshold;
1305b999a6bSDavide Italiano sbintime_t sbt_tickthreshold;
1315b999a6bSDavide Italiano struct bintime tc_tick_bt;
1325b999a6bSDavide Italiano sbintime_t tc_tick_sbt;
1335b999a6bSDavide Italiano int tc_precexp;
1345b999a6bSDavide Italiano int tc_timepercentage = TC_DEFAULTPERC;
1355b999a6bSDavide Italiano static int sysctl_kern_timecounter_adjprecision(SYSCTL_HANDLER_ARGS);
1365b999a6bSDavide Italiano SYSCTL_PROC(_kern_timecounter, OID_AUTO, alloweddeviation,
137af3b2549SHans Petter Selasky     CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 0, 0,
1385b999a6bSDavide Italiano     sysctl_kern_timecounter_adjprecision, "I",
1395b999a6bSDavide Italiano     "Allowed time interval deviation in percents");
1405b999a6bSDavide Italiano 
1419dbdf2a1SEric van Gyzen volatile int rtc_generation = 1;
1429dbdf2a1SEric van Gyzen 
143e8bac3f2SIan Lepore static int tc_chosen;	/* Non-zero if a specific tc was chosen via sysctl. */
144e8bac3f2SIan Lepore 
1455760b029SKonstantin Belousov static void tc_windup(struct bintime *new_boottimebin);
146e8444a7eSPoul-Henning Kamp static void cpu_tick_calibrate(int);
1479e1b5510SPoul-Henning Kamp 
14857d025c3SGeorge V. Neville-Neil void dtrace_getnanotime(struct timespec *tsp);
14957d025c3SGeorge V. Neville-Neil 
150a7bc3102SPeter Wemm static int
151a7bc3102SPeter Wemm sysctl_kern_boottime(SYSCTL_HANDLER_ARGS)
152a7bc3102SPeter Wemm {
153584b675eSKonstantin Belousov 	struct timeval boottime;
154584b675eSKonstantin Belousov 
155584b675eSKonstantin Belousov 	getboottime(&boottime);
156584b675eSKonstantin Belousov 
1577045ac43SOlivier Houchard /* i386 is the only arch which uses a 32bits time_t */
1587045ac43SOlivier Houchard #ifdef __amd64__
159a7bc3102SPeter Wemm #ifdef SCTL_MASK32
160a7bc3102SPeter Wemm 	int tv[2];
161a7bc3102SPeter Wemm 
162a7bc3102SPeter Wemm 	if (req->flags & SCTL_MASK32) {
163a7bc3102SPeter Wemm 		tv[0] = boottime.tv_sec;
164a7bc3102SPeter Wemm 		tv[1] = boottime.tv_usec;
165584b675eSKonstantin Belousov 		return (SYSCTL_OUT(req, tv, sizeof(tv)));
166584b675eSKonstantin Belousov 	}
167a7bc3102SPeter Wemm #endif
1689624d947SJuli Mallett #endif
169584b675eSKonstantin Belousov 	return (SYSCTL_OUT(req, &boottime, sizeof(boottime)));
170a7bc3102SPeter Wemm }
1715b1a8eb3SPoul-Henning Kamp 
17293ef14a7SDavid Malone static int
17393ef14a7SDavid Malone sysctl_kern_timecounter_get(SYSCTL_HANDLER_ARGS)
17493ef14a7SDavid Malone {
17593ef14a7SDavid Malone 	u_int ncount;
17693ef14a7SDavid Malone 	struct timecounter *tc = arg1;
17793ef14a7SDavid Malone 
17893ef14a7SDavid Malone 	ncount = tc->tc_get_timecount(tc);
1794d29106eSKonstantin Belousov 	return (sysctl_handle_int(oidp, &ncount, 0, req));
18093ef14a7SDavid Malone }
18193ef14a7SDavid Malone 
18293ef14a7SDavid Malone static int
18393ef14a7SDavid Malone sysctl_kern_timecounter_freq(SYSCTL_HANDLER_ARGS)
18493ef14a7SDavid Malone {
18560ae52f7SEd Schouten 	uint64_t freq;
18693ef14a7SDavid Malone 	struct timecounter *tc = arg1;
18793ef14a7SDavid Malone 
18893ef14a7SDavid Malone 	freq = tc->tc_frequency;
1894d29106eSKonstantin Belousov 	return (sysctl_handle_64(oidp, &freq, 0, req));
19093ef14a7SDavid Malone }
19193ef14a7SDavid Malone 
19239acc78aSPoul-Henning Kamp /*
19339acc78aSPoul-Henning Kamp  * Return the difference between the timehands' counter value now and what
19439acc78aSPoul-Henning Kamp  * was when we copied it to the timehands' offset_count.
19539acc78aSPoul-Henning Kamp  */
1966b00cf46SPoul-Henning Kamp static __inline u_int
1976b00cf46SPoul-Henning Kamp tc_delta(struct timehands *th)
198e796e00dSPoul-Henning Kamp {
1996b00cf46SPoul-Henning Kamp 	struct timecounter *tc;
200e796e00dSPoul-Henning Kamp 
2016b00cf46SPoul-Henning Kamp 	tc = th->th_counter;
2026b00cf46SPoul-Henning Kamp 	return ((tc->tc_get_timecount(tc) - th->th_offset_count) &
2036b00cf46SPoul-Henning Kamp 	    tc->tc_counter_mask);
204e796e00dSPoul-Henning Kamp }
205a0502b19SPoul-Henning Kamp 
20639acc78aSPoul-Henning Kamp /*
2076b00cf46SPoul-Henning Kamp  * Functions for reading the time.  We have to loop until we are sure that
20839acc78aSPoul-Henning Kamp  * the timehands that we operated on was not updated under our feet.  See
20939acc78aSPoul-Henning Kamp  * the comment in <sys/time.h> for a description of these 12 functions.
2106b00cf46SPoul-Henning Kamp  */
2116b00cf46SPoul-Henning Kamp 
2126cf2362eSKonstantin Belousov static __inline void
2136cf2362eSKonstantin Belousov bintime_off(struct bintime *bt, u_int off)
2149bce0f05SLawrence Stewart {
2159bce0f05SLawrence Stewart 	struct timehands *th;
2166cf2362eSKonstantin Belousov 	struct bintime *btp;
2176cf2362eSKonstantin Belousov 	uint64_t scale, x;
2186cf2362eSKonstantin Belousov 	u_int delta, gen, large_delta;
2199bce0f05SLawrence Stewart 
2209bce0f05SLawrence Stewart 	do {
2219bce0f05SLawrence Stewart 		th = timehands;
222f4b5a972SKonstantin Belousov 		gen = atomic_load_acq_int(&th->th_generation);
2236cf2362eSKonstantin Belousov 		btp = (struct bintime *)((vm_offset_t)th + off);
2246cf2362eSKonstantin Belousov 		*bt = *btp;
2256cf2362eSKonstantin Belousov 		scale = th->th_scale;
2266cf2362eSKonstantin Belousov 		delta = tc_delta(th);
2276cf2362eSKonstantin Belousov 		large_delta = th->th_large_delta;
228f4b5a972SKonstantin Belousov 		atomic_thread_fence_acq();
229f4b5a972SKonstantin Belousov 	} while (gen == 0 || gen != th->th_generation);
2306cf2362eSKonstantin Belousov 
2316cf2362eSKonstantin Belousov 	if (__predict_false(delta >= large_delta)) {
2326cf2362eSKonstantin Belousov 		/* Avoid overflow for scale * delta. */
2336cf2362eSKonstantin Belousov 		x = (scale >> 32) * delta;
2346cf2362eSKonstantin Belousov 		bt->sec += x >> 32;
2356cf2362eSKonstantin Belousov 		bintime_addx(bt, x << 32);
2366cf2362eSKonstantin Belousov 		bintime_addx(bt, (scale & 0xffffffff) * delta);
2376cf2362eSKonstantin Belousov 	} else {
2386cf2362eSKonstantin Belousov 		bintime_addx(bt, scale * delta);
2396cf2362eSKonstantin Belousov 	}
2406cf2362eSKonstantin Belousov }
2416cf2362eSKonstantin Belousov #define	GETTHBINTIME(dst, member)					\
2426cf2362eSKonstantin Belousov do {									\
2436cf2362eSKonstantin Belousov 	_Static_assert(_Generic(((struct timehands *)NULL)->member,	\
2446cf2362eSKonstantin Belousov 	    struct bintime: 1, default: 0) == 1,			\
2456cf2362eSKonstantin Belousov 	    "struct timehands member is not of struct bintime type");	\
2466cf2362eSKonstantin Belousov 	bintime_off(dst, __offsetof(struct timehands, member));		\
2476cf2362eSKonstantin Belousov } while (0)
2486cf2362eSKonstantin Belousov 
2496cf2362eSKonstantin Belousov static __inline void
2506cf2362eSKonstantin Belousov getthmember(void *out, size_t out_size, u_int off)
2516cf2362eSKonstantin Belousov {
2526cf2362eSKonstantin Belousov 	struct timehands *th;
2536cf2362eSKonstantin Belousov 	u_int gen;
2546cf2362eSKonstantin Belousov 
2556cf2362eSKonstantin Belousov 	do {
2566cf2362eSKonstantin Belousov 		th = timehands;
2576cf2362eSKonstantin Belousov 		gen = atomic_load_acq_int(&th->th_generation);
2586cf2362eSKonstantin Belousov 		memcpy(out, (char *)th + off, out_size);
2596cf2362eSKonstantin Belousov 		atomic_thread_fence_acq();
2606cf2362eSKonstantin Belousov 	} while (gen == 0 || gen != th->th_generation);
2616cf2362eSKonstantin Belousov }
2626cf2362eSKonstantin Belousov #define	GETTHMEMBER(dst, member)					\
2636cf2362eSKonstantin Belousov do {									\
2646cf2362eSKonstantin Belousov 	_Static_assert(_Generic(*dst,					\
2656cf2362eSKonstantin Belousov 	    __typeof(((struct timehands *)NULL)->member): 1,		\
2666cf2362eSKonstantin Belousov 	    default: 0) == 1,						\
2676cf2362eSKonstantin Belousov 	    "*dst and struct timehands member have different types");	\
2686cf2362eSKonstantin Belousov 	getthmember(dst, sizeof(*dst), __offsetof(struct timehands,	\
2696cf2362eSKonstantin Belousov 	    member));							\
2706cf2362eSKonstantin Belousov } while (0)
2716cf2362eSKonstantin Belousov 
2726cf2362eSKonstantin Belousov #ifdef FFCLOCK
2736cf2362eSKonstantin Belousov void
2746cf2362eSKonstantin Belousov fbclock_binuptime(struct bintime *bt)
2756cf2362eSKonstantin Belousov {
2766cf2362eSKonstantin Belousov 
2776cf2362eSKonstantin Belousov 	GETTHBINTIME(bt, th_offset);
2789bce0f05SLawrence Stewart }
2799bce0f05SLawrence Stewart 
280e977bac3SLawrence Stewart void
2819bce0f05SLawrence Stewart fbclock_nanouptime(struct timespec *tsp)
2829bce0f05SLawrence Stewart {
2839bce0f05SLawrence Stewart 	struct bintime bt;
2849bce0f05SLawrence Stewart 
285c2a4ee99SLawrence Stewart 	fbclock_binuptime(&bt);
2869bce0f05SLawrence Stewart 	bintime2timespec(&bt, tsp);
2879bce0f05SLawrence Stewart }
2889bce0f05SLawrence Stewart 
289e977bac3SLawrence Stewart void
2909bce0f05SLawrence Stewart fbclock_microuptime(struct timeval *tvp)
2919bce0f05SLawrence Stewart {
2929bce0f05SLawrence Stewart 	struct bintime bt;
2939bce0f05SLawrence Stewart 
294c2a4ee99SLawrence Stewart 	fbclock_binuptime(&bt);
2959bce0f05SLawrence Stewart 	bintime2timeval(&bt, tvp);
2969bce0f05SLawrence Stewart }
2979bce0f05SLawrence Stewart 
298e977bac3SLawrence Stewart void
2999bce0f05SLawrence Stewart fbclock_bintime(struct bintime *bt)
3009bce0f05SLawrence Stewart {
3019bce0f05SLawrence Stewart 
3026cf2362eSKonstantin Belousov 	GETTHBINTIME(bt, th_bintime);
3039bce0f05SLawrence Stewart }
3049bce0f05SLawrence Stewart 
305e977bac3SLawrence Stewart void
3069bce0f05SLawrence Stewart fbclock_nanotime(struct timespec *tsp)
3079bce0f05SLawrence Stewart {
3089bce0f05SLawrence Stewart 	struct bintime bt;
3099bce0f05SLawrence Stewart 
310c2a4ee99SLawrence Stewart 	fbclock_bintime(&bt);
3119bce0f05SLawrence Stewart 	bintime2timespec(&bt, tsp);
3129bce0f05SLawrence Stewart }
3139bce0f05SLawrence Stewart 
314e977bac3SLawrence Stewart void
3159bce0f05SLawrence Stewart fbclock_microtime(struct timeval *tvp)
3169bce0f05SLawrence Stewart {
3179bce0f05SLawrence Stewart 	struct bintime bt;
3189bce0f05SLawrence Stewart 
319c2a4ee99SLawrence Stewart 	fbclock_bintime(&bt);
3209bce0f05SLawrence Stewart 	bintime2timeval(&bt, tvp);
3219bce0f05SLawrence Stewart }
3229bce0f05SLawrence Stewart 
323e977bac3SLawrence Stewart void
3249bce0f05SLawrence Stewart fbclock_getbinuptime(struct bintime *bt)
3259bce0f05SLawrence Stewart {
3269bce0f05SLawrence Stewart 
3276cf2362eSKonstantin Belousov 	GETTHMEMBER(bt, th_offset);
3289bce0f05SLawrence Stewart }
3299bce0f05SLawrence Stewart 
330e977bac3SLawrence Stewart void
3319bce0f05SLawrence Stewart fbclock_getnanouptime(struct timespec *tsp)
3329bce0f05SLawrence Stewart {
3336cf2362eSKonstantin Belousov 	struct bintime bt;
3349bce0f05SLawrence Stewart 
3356cf2362eSKonstantin Belousov 	GETTHMEMBER(&bt, th_offset);
3366cf2362eSKonstantin Belousov 	bintime2timespec(&bt, tsp);
3379bce0f05SLawrence Stewart }
3389bce0f05SLawrence Stewart 
339e977bac3SLawrence Stewart void
3409bce0f05SLawrence Stewart fbclock_getmicrouptime(struct timeval *tvp)
3419bce0f05SLawrence Stewart {
3426cf2362eSKonstantin Belousov 	struct bintime bt;
3439bce0f05SLawrence Stewart 
3446cf2362eSKonstantin Belousov 	GETTHMEMBER(&bt, th_offset);
3456cf2362eSKonstantin Belousov 	bintime2timeval(&bt, tvp);
3469bce0f05SLawrence Stewart }
3479bce0f05SLawrence Stewart 
348e977bac3SLawrence Stewart void
3499bce0f05SLawrence Stewart fbclock_getbintime(struct bintime *bt)
3509bce0f05SLawrence Stewart {
3519bce0f05SLawrence Stewart 
3526cf2362eSKonstantin Belousov 	GETTHMEMBER(bt, th_bintime);
3539bce0f05SLawrence Stewart }
3549bce0f05SLawrence Stewart 
355e977bac3SLawrence Stewart void
3569bce0f05SLawrence Stewart fbclock_getnanotime(struct timespec *tsp)
3579bce0f05SLawrence Stewart {
3589bce0f05SLawrence Stewart 
3596cf2362eSKonstantin Belousov 	GETTHMEMBER(tsp, th_nanotime);
3609bce0f05SLawrence Stewart }
3619bce0f05SLawrence Stewart 
362e977bac3SLawrence Stewart void
3639bce0f05SLawrence Stewart fbclock_getmicrotime(struct timeval *tvp)
3649bce0f05SLawrence Stewart {
3659bce0f05SLawrence Stewart 
3666cf2362eSKonstantin Belousov 	GETTHMEMBER(tvp, th_microtime);
3679bce0f05SLawrence Stewart }
3689bce0f05SLawrence Stewart #else /* !FFCLOCK */
3696cf2362eSKonstantin Belousov 
370a0502b19SPoul-Henning Kamp void
3712028c0cdSPoul-Henning Kamp binuptime(struct bintime *bt)
3722028c0cdSPoul-Henning Kamp {
3732028c0cdSPoul-Henning Kamp 
3746cf2362eSKonstantin Belousov 	GETTHBINTIME(bt, th_offset);
3752028c0cdSPoul-Henning Kamp }
3762028c0cdSPoul-Henning Kamp 
3772028c0cdSPoul-Henning Kamp void
37839acc78aSPoul-Henning Kamp nanouptime(struct timespec *tsp)
379056abcabSPoul-Henning Kamp {
380056abcabSPoul-Henning Kamp 	struct bintime bt;
381056abcabSPoul-Henning Kamp 
382056abcabSPoul-Henning Kamp 	binuptime(&bt);
38339acc78aSPoul-Henning Kamp 	bintime2timespec(&bt, tsp);
384056abcabSPoul-Henning Kamp }
385056abcabSPoul-Henning Kamp 
386056abcabSPoul-Henning Kamp void
38739acc78aSPoul-Henning Kamp microuptime(struct timeval *tvp)
388056abcabSPoul-Henning Kamp {
389056abcabSPoul-Henning Kamp 	struct bintime bt;
390056abcabSPoul-Henning Kamp 
391056abcabSPoul-Henning Kamp 	binuptime(&bt);
39239acc78aSPoul-Henning Kamp 	bintime2timeval(&bt, tvp);
393056abcabSPoul-Henning Kamp }
394056abcabSPoul-Henning Kamp 
395056abcabSPoul-Henning Kamp void
3962028c0cdSPoul-Henning Kamp bintime(struct bintime *bt)
3972028c0cdSPoul-Henning Kamp {
3982028c0cdSPoul-Henning Kamp 
3996cf2362eSKonstantin Belousov 	GETTHBINTIME(bt, th_bintime);
4002028c0cdSPoul-Henning Kamp }
4012028c0cdSPoul-Henning Kamp 
4022028c0cdSPoul-Henning Kamp void
40339acc78aSPoul-Henning Kamp nanotime(struct timespec *tsp)
40400af9731SPoul-Henning Kamp {
4052028c0cdSPoul-Henning Kamp 	struct bintime bt;
40600af9731SPoul-Henning Kamp 
4072028c0cdSPoul-Henning Kamp 	bintime(&bt);
40839acc78aSPoul-Henning Kamp 	bintime2timespec(&bt, tsp);
40948115288SPoul-Henning Kamp }
41048115288SPoul-Henning Kamp 
41148115288SPoul-Henning Kamp void
41239acc78aSPoul-Henning Kamp microtime(struct timeval *tvp)
413056abcabSPoul-Henning Kamp {
414056abcabSPoul-Henning Kamp 	struct bintime bt;
415056abcabSPoul-Henning Kamp 
416056abcabSPoul-Henning Kamp 	bintime(&bt);
41739acc78aSPoul-Henning Kamp 	bintime2timeval(&bt, tvp);
418056abcabSPoul-Henning Kamp }
419056abcabSPoul-Henning Kamp 
420056abcabSPoul-Henning Kamp void
421056abcabSPoul-Henning Kamp getbinuptime(struct bintime *bt)
42200af9731SPoul-Henning Kamp {
42300af9731SPoul-Henning Kamp 
4246cf2362eSKonstantin Belousov 	GETTHMEMBER(bt, th_offset);
425a0502b19SPoul-Henning Kamp }
426a0502b19SPoul-Henning Kamp 
427a0502b19SPoul-Henning Kamp void
428c21410e1SPoul-Henning Kamp getnanouptime(struct timespec *tsp)
429a0502b19SPoul-Henning Kamp {
4306cf2362eSKonstantin Belousov 	struct bintime bt;
431a0502b19SPoul-Henning Kamp 
4326cf2362eSKonstantin Belousov 	GETTHMEMBER(&bt, th_offset);
4336cf2362eSKonstantin Belousov 	bintime2timespec(&bt, tsp);
434a0502b19SPoul-Henning Kamp }
435a0502b19SPoul-Henning Kamp 
436c7c9a816SPoul-Henning Kamp void
437056abcabSPoul-Henning Kamp getmicrouptime(struct timeval *tvp)
438c7c9a816SPoul-Henning Kamp {
4396cf2362eSKonstantin Belousov 	struct bintime bt;
4407ec73f64SPoul-Henning Kamp 
4416cf2362eSKonstantin Belousov 	GETTHMEMBER(&bt, th_offset);
4426cf2362eSKonstantin Belousov 	bintime2timeval(&bt, tvp);
4437ec73f64SPoul-Henning Kamp }
4447ec73f64SPoul-Henning Kamp 
4457ec73f64SPoul-Henning Kamp void
446056abcabSPoul-Henning Kamp getbintime(struct bintime *bt)
4477ec73f64SPoul-Henning Kamp {
4487ec73f64SPoul-Henning Kamp 
4496cf2362eSKonstantin Belousov 	GETTHMEMBER(bt, th_bintime);
450056abcabSPoul-Henning Kamp }
451056abcabSPoul-Henning Kamp 
452056abcabSPoul-Henning Kamp void
453056abcabSPoul-Henning Kamp getnanotime(struct timespec *tsp)
454056abcabSPoul-Henning Kamp {
455056abcabSPoul-Henning Kamp 
4566cf2362eSKonstantin Belousov 	GETTHMEMBER(tsp, th_nanotime);
457056abcabSPoul-Henning Kamp }
458056abcabSPoul-Henning Kamp 
459056abcabSPoul-Henning Kamp void
460056abcabSPoul-Henning Kamp getmicrotime(struct timeval *tvp)
461056abcabSPoul-Henning Kamp {
462056abcabSPoul-Henning Kamp 
4636cf2362eSKonstantin Belousov 	GETTHMEMBER(tvp, th_microtime);
4647ec73f64SPoul-Henning Kamp }
4659bce0f05SLawrence Stewart #endif /* FFCLOCK */
4667ec73f64SPoul-Henning Kamp 
467584b675eSKonstantin Belousov void
468584b675eSKonstantin Belousov getboottime(struct timeval *boottime)
469584b675eSKonstantin Belousov {
4705760b029SKonstantin Belousov 	struct bintime boottimebin;
471584b675eSKonstantin Belousov 
4725760b029SKonstantin Belousov 	getboottimebin(&boottimebin);
4735760b029SKonstantin Belousov 	bintime2timeval(&boottimebin, boottime);
474584b675eSKonstantin Belousov }
475584b675eSKonstantin Belousov 
476584b675eSKonstantin Belousov void
477584b675eSKonstantin Belousov getboottimebin(struct bintime *boottimebin)
478584b675eSKonstantin Belousov {
479584b675eSKonstantin Belousov 
4806cf2362eSKonstantin Belousov 	GETTHMEMBER(boottimebin, th_boottime);
481584b675eSKonstantin Belousov }
482584b675eSKonstantin Belousov 
483b0fdc837SLawrence Stewart #ifdef FFCLOCK
484b0fdc837SLawrence Stewart /*
485b0fdc837SLawrence Stewart  * Support for feed-forward synchronization algorithms. This is heavily inspired
486b0fdc837SLawrence Stewart  * by the timehands mechanism but kept independent from it. *_windup() functions
487b0fdc837SLawrence Stewart  * have some connection to avoid accessing the timecounter hardware more than
488b0fdc837SLawrence Stewart  * necessary.
489b0fdc837SLawrence Stewart  */
490b0fdc837SLawrence Stewart 
491b0fdc837SLawrence Stewart /* Feed-forward clock estimates kept updated by the synchronization daemon. */
492b0fdc837SLawrence Stewart struct ffclock_estimate ffclock_estimate;
493b0fdc837SLawrence Stewart struct bintime ffclock_boottime;	/* Feed-forward boot time estimate. */
494b0fdc837SLawrence Stewart uint32_t ffclock_status;		/* Feed-forward clock status. */
495b0fdc837SLawrence Stewart int8_t ffclock_updated;			/* New estimates are available. */
496b0fdc837SLawrence Stewart struct mtx ffclock_mtx;			/* Mutex on ffclock_estimate. */
497b0fdc837SLawrence Stewart 
498b0fdc837SLawrence Stewart struct fftimehands {
499b0fdc837SLawrence Stewart 	struct ffclock_estimate	cest;
500b0fdc837SLawrence Stewart 	struct bintime		tick_time;
501b0fdc837SLawrence Stewart 	struct bintime		tick_time_lerp;
502b0fdc837SLawrence Stewart 	ffcounter		tick_ffcount;
503b0fdc837SLawrence Stewart 	uint64_t		period_lerp;
504b0fdc837SLawrence Stewart 	volatile uint8_t	gen;
505b0fdc837SLawrence Stewart 	struct fftimehands	*next;
506b0fdc837SLawrence Stewart };
507b0fdc837SLawrence Stewart 
508b0fdc837SLawrence Stewart #define	NUM_ELEMENTS(x) (sizeof(x) / sizeof(*x))
509b0fdc837SLawrence Stewart 
510b0fdc837SLawrence Stewart static struct fftimehands ffth[10];
511b0fdc837SLawrence Stewart static struct fftimehands *volatile fftimehands = ffth;
512b0fdc837SLawrence Stewart 
513b0fdc837SLawrence Stewart static void
514b0fdc837SLawrence Stewart ffclock_init(void)
515b0fdc837SLawrence Stewart {
516b0fdc837SLawrence Stewart 	struct fftimehands *cur;
517b0fdc837SLawrence Stewart 	struct fftimehands *last;
518b0fdc837SLawrence Stewart 
519b0fdc837SLawrence Stewart 	memset(ffth, 0, sizeof(ffth));
520b0fdc837SLawrence Stewart 
521b0fdc837SLawrence Stewart 	last = ffth + NUM_ELEMENTS(ffth) - 1;
522b0fdc837SLawrence Stewart 	for (cur = ffth; cur < last; cur++)
523b0fdc837SLawrence Stewart 		cur->next = cur + 1;
524b0fdc837SLawrence Stewart 	last->next = ffth;
525b0fdc837SLawrence Stewart 
526b0fdc837SLawrence Stewart 	ffclock_updated = 0;
527b0fdc837SLawrence Stewart 	ffclock_status = FFCLOCK_STA_UNSYNC;
528b0fdc837SLawrence Stewart 	mtx_init(&ffclock_mtx, "ffclock lock", NULL, MTX_DEF);
529b0fdc837SLawrence Stewart }
530b0fdc837SLawrence Stewart 
531b0fdc837SLawrence Stewart /*
532b0fdc837SLawrence Stewart  * Reset the feed-forward clock estimates. Called from inittodr() to get things
533b0fdc837SLawrence Stewart  * kick started and uses the timecounter nominal frequency as a first period
534b0fdc837SLawrence Stewart  * estimate. Note: this function may be called several time just after boot.
535b0fdc837SLawrence Stewart  * Note: this is the only function that sets the value of boot time for the
536b0fdc837SLawrence Stewart  * monotonic (i.e. uptime) version of the feed-forward clock.
537b0fdc837SLawrence Stewart  */
538b0fdc837SLawrence Stewart void
539b0fdc837SLawrence Stewart ffclock_reset_clock(struct timespec *ts)
540b0fdc837SLawrence Stewart {
541b0fdc837SLawrence Stewart 	struct timecounter *tc;
542b0fdc837SLawrence Stewart 	struct ffclock_estimate cest;
543b0fdc837SLawrence Stewart 
544b0fdc837SLawrence Stewart 	tc = timehands->th_counter;
545b0fdc837SLawrence Stewart 	memset(&cest, 0, sizeof(struct ffclock_estimate));
546b0fdc837SLawrence Stewart 
547b0fdc837SLawrence Stewart 	timespec2bintime(ts, &ffclock_boottime);
548b0fdc837SLawrence Stewart 	timespec2bintime(ts, &(cest.update_time));
549b0fdc837SLawrence Stewart 	ffclock_read_counter(&cest.update_ffcount);
550b0fdc837SLawrence Stewart 	cest.leapsec_next = 0;
551b0fdc837SLawrence Stewart 	cest.period = ((1ULL << 63) / tc->tc_frequency) << 1;
552b0fdc837SLawrence Stewart 	cest.errb_abs = 0;
553b0fdc837SLawrence Stewart 	cest.errb_rate = 0;
554b0fdc837SLawrence Stewart 	cest.status = FFCLOCK_STA_UNSYNC;
555b0fdc837SLawrence Stewart 	cest.leapsec_total = 0;
556b0fdc837SLawrence Stewart 	cest.leapsec = 0;
557b0fdc837SLawrence Stewart 
558b0fdc837SLawrence Stewart 	mtx_lock(&ffclock_mtx);
559b0fdc837SLawrence Stewart 	bcopy(&cest, &ffclock_estimate, sizeof(struct ffclock_estimate));
560b0fdc837SLawrence Stewart 	ffclock_updated = INT8_MAX;
561b0fdc837SLawrence Stewart 	mtx_unlock(&ffclock_mtx);
562b0fdc837SLawrence Stewart 
563b0fdc837SLawrence Stewart 	printf("ffclock reset: %s (%llu Hz), time = %ld.%09lu\n", tc->tc_name,
564b0fdc837SLawrence Stewart 	    (unsigned long long)tc->tc_frequency, (long)ts->tv_sec,
565b0fdc837SLawrence Stewart 	    (unsigned long)ts->tv_nsec);
566b0fdc837SLawrence Stewart }
567b0fdc837SLawrence Stewart 
568b0fdc837SLawrence Stewart /*
569b0fdc837SLawrence Stewart  * Sub-routine to convert a time interval measured in RAW counter units to time
570b0fdc837SLawrence Stewart  * in seconds stored in bintime format.
571b0fdc837SLawrence Stewart  * NOTE: bintime_mul requires u_int, but the value of the ffcounter may be
572b0fdc837SLawrence Stewart  * larger than the max value of u_int (on 32 bit architecture). Loop to consume
573b0fdc837SLawrence Stewart  * extra cycles.
574b0fdc837SLawrence Stewart  */
575b0fdc837SLawrence Stewart static void
576b0fdc837SLawrence Stewart ffclock_convert_delta(ffcounter ffdelta, uint64_t period, struct bintime *bt)
577b0fdc837SLawrence Stewart {
578b0fdc837SLawrence Stewart 	struct bintime bt2;
579b0fdc837SLawrence Stewart 	ffcounter delta, delta_max;
580b0fdc837SLawrence Stewart 
581b0fdc837SLawrence Stewart 	delta_max = (1ULL << (8 * sizeof(unsigned int))) - 1;
582b0fdc837SLawrence Stewart 	bintime_clear(bt);
583b0fdc837SLawrence Stewart 	do {
584b0fdc837SLawrence Stewart 		if (ffdelta > delta_max)
585b0fdc837SLawrence Stewart 			delta = delta_max;
586b0fdc837SLawrence Stewart 		else
587b0fdc837SLawrence Stewart 			delta = ffdelta;
588b0fdc837SLawrence Stewart 		bt2.sec = 0;
589b0fdc837SLawrence Stewart 		bt2.frac = period;
590b0fdc837SLawrence Stewart 		bintime_mul(&bt2, (unsigned int)delta);
591b0fdc837SLawrence Stewart 		bintime_add(bt, &bt2);
592b0fdc837SLawrence Stewart 		ffdelta -= delta;
593b0fdc837SLawrence Stewart 	} while (ffdelta > 0);
594b0fdc837SLawrence Stewart }
595b0fdc837SLawrence Stewart 
596b0fdc837SLawrence Stewart /*
597b0fdc837SLawrence Stewart  * Update the fftimehands.
598b0fdc837SLawrence Stewart  * Push the tick ffcount and time(s) forward based on current clock estimate.
599b0fdc837SLawrence Stewart  * The conversion from ffcounter to bintime relies on the difference clock
600b0fdc837SLawrence Stewart  * principle, whose accuracy relies on computing small time intervals. If a new
601b0fdc837SLawrence Stewart  * clock estimate has been passed by the synchronisation daemon, make it
602b0fdc837SLawrence Stewart  * current, and compute the linear interpolation for monotonic time if needed.
603b0fdc837SLawrence Stewart  */
604b0fdc837SLawrence Stewart static void
605b0fdc837SLawrence Stewart ffclock_windup(unsigned int delta)
606b0fdc837SLawrence Stewart {
607b0fdc837SLawrence Stewart 	struct ffclock_estimate *cest;
608b0fdc837SLawrence Stewart 	struct fftimehands *ffth;
609b0fdc837SLawrence Stewart 	struct bintime bt, gap_lerp;
610b0fdc837SLawrence Stewart 	ffcounter ffdelta;
611b0fdc837SLawrence Stewart 	uint64_t frac;
612b0fdc837SLawrence Stewart 	unsigned int polling;
613b0fdc837SLawrence Stewart 	uint8_t forward_jump, ogen;
614b0fdc837SLawrence Stewart 
615b0fdc837SLawrence Stewart 	/*
616b0fdc837SLawrence Stewart 	 * Pick the next timehand, copy current ffclock estimates and move tick
617b0fdc837SLawrence Stewart 	 * times and counter forward.
618b0fdc837SLawrence Stewart 	 */
619b0fdc837SLawrence Stewart 	forward_jump = 0;
620b0fdc837SLawrence Stewart 	ffth = fftimehands->next;
621b0fdc837SLawrence Stewart 	ogen = ffth->gen;
622b0fdc837SLawrence Stewart 	ffth->gen = 0;
623b0fdc837SLawrence Stewart 	cest = &ffth->cest;
624b0fdc837SLawrence Stewart 	bcopy(&fftimehands->cest, cest, sizeof(struct ffclock_estimate));
625b0fdc837SLawrence Stewart 	ffdelta = (ffcounter)delta;
626b0fdc837SLawrence Stewart 	ffth->period_lerp = fftimehands->period_lerp;
627b0fdc837SLawrence Stewart 
628b0fdc837SLawrence Stewart 	ffth->tick_time = fftimehands->tick_time;
629b0fdc837SLawrence Stewart 	ffclock_convert_delta(ffdelta, cest->period, &bt);
630b0fdc837SLawrence Stewart 	bintime_add(&ffth->tick_time, &bt);
631b0fdc837SLawrence Stewart 
632b0fdc837SLawrence Stewart 	ffth->tick_time_lerp = fftimehands->tick_time_lerp;
633b0fdc837SLawrence Stewart 	ffclock_convert_delta(ffdelta, ffth->period_lerp, &bt);
634b0fdc837SLawrence Stewart 	bintime_add(&ffth->tick_time_lerp, &bt);
635b0fdc837SLawrence Stewart 
636b0fdc837SLawrence Stewart 	ffth->tick_ffcount = fftimehands->tick_ffcount + ffdelta;
637b0fdc837SLawrence Stewart 
638b0fdc837SLawrence Stewart 	/*
639b0fdc837SLawrence Stewart 	 * Assess the status of the clock, if the last update is too old, it is
640b0fdc837SLawrence Stewart 	 * likely the synchronisation daemon is dead and the clock is free
641b0fdc837SLawrence Stewart 	 * running.
642b0fdc837SLawrence Stewart 	 */
643b0fdc837SLawrence Stewart 	if (ffclock_updated == 0) {
644b0fdc837SLawrence Stewart 		ffdelta = ffth->tick_ffcount - cest->update_ffcount;
645b0fdc837SLawrence Stewart 		ffclock_convert_delta(ffdelta, cest->period, &bt);
646b0fdc837SLawrence Stewart 		if (bt.sec > 2 * FFCLOCK_SKM_SCALE)
647b0fdc837SLawrence Stewart 			ffclock_status |= FFCLOCK_STA_UNSYNC;
648b0fdc837SLawrence Stewart 	}
649b0fdc837SLawrence Stewart 
650b0fdc837SLawrence Stewart 	/*
651b0fdc837SLawrence Stewart 	 * If available, grab updated clock estimates and make them current.
652b0fdc837SLawrence Stewart 	 * Recompute time at this tick using the updated estimates. The clock
653b0fdc837SLawrence Stewart 	 * estimates passed the feed-forward synchronisation daemon may result
654b0fdc837SLawrence Stewart 	 * in time conversion that is not monotonically increasing (just after
655b0fdc837SLawrence Stewart 	 * the update). time_lerp is a particular linear interpolation over the
656b0fdc837SLawrence Stewart 	 * synchronisation algo polling period that ensures monotonicity for the
657b0fdc837SLawrence Stewart 	 * clock ids requesting it.
658b0fdc837SLawrence Stewart 	 */
659b0fdc837SLawrence Stewart 	if (ffclock_updated > 0) {
660b0fdc837SLawrence Stewart 		bcopy(&ffclock_estimate, cest, sizeof(struct ffclock_estimate));
661b0fdc837SLawrence Stewart 		ffdelta = ffth->tick_ffcount - cest->update_ffcount;
662b0fdc837SLawrence Stewart 		ffth->tick_time = cest->update_time;
663b0fdc837SLawrence Stewart 		ffclock_convert_delta(ffdelta, cest->period, &bt);
664b0fdc837SLawrence Stewart 		bintime_add(&ffth->tick_time, &bt);
665b0fdc837SLawrence Stewart 
666b0fdc837SLawrence Stewart 		/* ffclock_reset sets ffclock_updated to INT8_MAX */
667b0fdc837SLawrence Stewart 		if (ffclock_updated == INT8_MAX)
668b0fdc837SLawrence Stewart 			ffth->tick_time_lerp = ffth->tick_time;
669b0fdc837SLawrence Stewart 
670b0fdc837SLawrence Stewart 		if (bintime_cmp(&ffth->tick_time, &ffth->tick_time_lerp, >))
671b0fdc837SLawrence Stewart 			forward_jump = 1;
672b0fdc837SLawrence Stewart 		else
673b0fdc837SLawrence Stewart 			forward_jump = 0;
674b0fdc837SLawrence Stewart 
675b0fdc837SLawrence Stewart 		bintime_clear(&gap_lerp);
676b0fdc837SLawrence Stewart 		if (forward_jump) {
677b0fdc837SLawrence Stewart 			gap_lerp = ffth->tick_time;
678b0fdc837SLawrence Stewart 			bintime_sub(&gap_lerp, &ffth->tick_time_lerp);
679b0fdc837SLawrence Stewart 		} else {
680b0fdc837SLawrence Stewart 			gap_lerp = ffth->tick_time_lerp;
681b0fdc837SLawrence Stewart 			bintime_sub(&gap_lerp, &ffth->tick_time);
682b0fdc837SLawrence Stewart 		}
683b0fdc837SLawrence Stewart 
684b0fdc837SLawrence Stewart 		/*
685b0fdc837SLawrence Stewart 		 * The reset from the RTC clock may be far from accurate, and
686b0fdc837SLawrence Stewart 		 * reducing the gap between real time and interpolated time
687b0fdc837SLawrence Stewart 		 * could take a very long time if the interpolated clock insists
688b0fdc837SLawrence Stewart 		 * on strict monotonicity. The clock is reset under very strict
689b0fdc837SLawrence Stewart 		 * conditions (kernel time is known to be wrong and
690b0fdc837SLawrence Stewart 		 * synchronization daemon has been restarted recently.
691b0fdc837SLawrence Stewart 		 * ffclock_boottime absorbs the jump to ensure boot time is
692b0fdc837SLawrence Stewart 		 * correct and uptime functions stay consistent.
693b0fdc837SLawrence Stewart 		 */
694b0fdc837SLawrence Stewart 		if (((ffclock_status & FFCLOCK_STA_UNSYNC) == FFCLOCK_STA_UNSYNC) &&
695b0fdc837SLawrence Stewart 		    ((cest->status & FFCLOCK_STA_UNSYNC) == 0) &&
696b0fdc837SLawrence Stewart 		    ((cest->status & FFCLOCK_STA_WARMUP) == FFCLOCK_STA_WARMUP)) {
697b0fdc837SLawrence Stewart 			if (forward_jump)
698b0fdc837SLawrence Stewart 				bintime_add(&ffclock_boottime, &gap_lerp);
699b0fdc837SLawrence Stewart 			else
700b0fdc837SLawrence Stewart 				bintime_sub(&ffclock_boottime, &gap_lerp);
701b0fdc837SLawrence Stewart 			ffth->tick_time_lerp = ffth->tick_time;
702b0fdc837SLawrence Stewart 			bintime_clear(&gap_lerp);
703b0fdc837SLawrence Stewart 		}
704b0fdc837SLawrence Stewart 
705b0fdc837SLawrence Stewart 		ffclock_status = cest->status;
706b0fdc837SLawrence Stewart 		ffth->period_lerp = cest->period;
707b0fdc837SLawrence Stewart 
708b0fdc837SLawrence Stewart 		/*
709b0fdc837SLawrence Stewart 		 * Compute corrected period used for the linear interpolation of
710b0fdc837SLawrence Stewart 		 * time. The rate of linear interpolation is capped to 5000PPM
711b0fdc837SLawrence Stewart 		 * (5ms/s).
712b0fdc837SLawrence Stewart 		 */
713b0fdc837SLawrence Stewart 		if (bintime_isset(&gap_lerp)) {
714b0fdc837SLawrence Stewart 			ffdelta = cest->update_ffcount;
715b0fdc837SLawrence Stewart 			ffdelta -= fftimehands->cest.update_ffcount;
716b0fdc837SLawrence Stewart 			ffclock_convert_delta(ffdelta, cest->period, &bt);
717b0fdc837SLawrence Stewart 			polling = bt.sec;
718b0fdc837SLawrence Stewart 			bt.sec = 0;
719b0fdc837SLawrence Stewart 			bt.frac = 5000000 * (uint64_t)18446744073LL;
720b0fdc837SLawrence Stewart 			bintime_mul(&bt, polling);
721b0fdc837SLawrence Stewart 			if (bintime_cmp(&gap_lerp, &bt, >))
722b0fdc837SLawrence Stewart 				gap_lerp = bt;
723b0fdc837SLawrence Stewart 
724b0fdc837SLawrence Stewart 			/* Approximate 1 sec by 1-(1/2^64) to ease arithmetic */
725b0fdc837SLawrence Stewart 			frac = 0;
726b0fdc837SLawrence Stewart 			if (gap_lerp.sec > 0) {
727b0fdc837SLawrence Stewart 				frac -= 1;
728b0fdc837SLawrence Stewart 				frac /= ffdelta / gap_lerp.sec;
729b0fdc837SLawrence Stewart 			}
730b0fdc837SLawrence Stewart 			frac += gap_lerp.frac / ffdelta;
731b0fdc837SLawrence Stewart 
732b0fdc837SLawrence Stewart 			if (forward_jump)
733b0fdc837SLawrence Stewart 				ffth->period_lerp += frac;
734b0fdc837SLawrence Stewart 			else
735b0fdc837SLawrence Stewart 				ffth->period_lerp -= frac;
736b0fdc837SLawrence Stewart 		}
737b0fdc837SLawrence Stewart 
738b0fdc837SLawrence Stewart 		ffclock_updated = 0;
739b0fdc837SLawrence Stewart 	}
740b0fdc837SLawrence Stewart 	if (++ogen == 0)
741b0fdc837SLawrence Stewart 		ogen = 1;
742b0fdc837SLawrence Stewart 	ffth->gen = ogen;
743b0fdc837SLawrence Stewart 	fftimehands = ffth;
744b0fdc837SLawrence Stewart }
745b0fdc837SLawrence Stewart 
746b0fdc837SLawrence Stewart /*
747b0fdc837SLawrence Stewart  * Adjust the fftimehands when the timecounter is changed. Stating the obvious,
748b0fdc837SLawrence Stewart  * the old and new hardware counter cannot be read simultaneously. tc_windup()
749b0fdc837SLawrence Stewart  * does read the two counters 'back to back', but a few cycles are effectively
750b0fdc837SLawrence Stewart  * lost, and not accumulated in tick_ffcount. This is a fairly radical
751b0fdc837SLawrence Stewart  * operation for a feed-forward synchronization daemon, and it is its job to not
752b0fdc837SLawrence Stewart  * pushing irrelevant data to the kernel. Because there is no locking here,
753b0fdc837SLawrence Stewart  * simply force to ignore pending or next update to give daemon a chance to
754b0fdc837SLawrence Stewart  * realize the counter has changed.
755b0fdc837SLawrence Stewart  */
756b0fdc837SLawrence Stewart static void
757b0fdc837SLawrence Stewart ffclock_change_tc(struct timehands *th)
758b0fdc837SLawrence Stewart {
759b0fdc837SLawrence Stewart 	struct fftimehands *ffth;
760b0fdc837SLawrence Stewart 	struct ffclock_estimate *cest;
761b0fdc837SLawrence Stewart 	struct timecounter *tc;
762b0fdc837SLawrence Stewart 	uint8_t ogen;
763b0fdc837SLawrence Stewart 
764b0fdc837SLawrence Stewart 	tc = th->th_counter;
765b0fdc837SLawrence Stewart 	ffth = fftimehands->next;
766b0fdc837SLawrence Stewart 	ogen = ffth->gen;
767b0fdc837SLawrence Stewart 	ffth->gen = 0;
768b0fdc837SLawrence Stewart 
769b0fdc837SLawrence Stewart 	cest = &ffth->cest;
770b0fdc837SLawrence Stewart 	bcopy(&(fftimehands->cest), cest, sizeof(struct ffclock_estimate));
771b0fdc837SLawrence Stewart 	cest->period = ((1ULL << 63) / tc->tc_frequency ) << 1;
772b0fdc837SLawrence Stewart 	cest->errb_abs = 0;
773b0fdc837SLawrence Stewart 	cest->errb_rate = 0;
774b0fdc837SLawrence Stewart 	cest->status |= FFCLOCK_STA_UNSYNC;
775b0fdc837SLawrence Stewart 
776b0fdc837SLawrence Stewart 	ffth->tick_ffcount = fftimehands->tick_ffcount;
777b0fdc837SLawrence Stewart 	ffth->tick_time_lerp = fftimehands->tick_time_lerp;
778b0fdc837SLawrence Stewart 	ffth->tick_time = fftimehands->tick_time;
779b0fdc837SLawrence Stewart 	ffth->period_lerp = cest->period;
780b0fdc837SLawrence Stewart 
781b0fdc837SLawrence Stewart 	/* Do not lock but ignore next update from synchronization daemon. */
782b0fdc837SLawrence Stewart 	ffclock_updated--;
783b0fdc837SLawrence Stewart 
784b0fdc837SLawrence Stewart 	if (++ogen == 0)
785b0fdc837SLawrence Stewart 		ogen = 1;
786b0fdc837SLawrence Stewart 	ffth->gen = ogen;
787b0fdc837SLawrence Stewart 	fftimehands = ffth;
788b0fdc837SLawrence Stewart }
789b0fdc837SLawrence Stewart 
790b0fdc837SLawrence Stewart /*
791b0fdc837SLawrence Stewart  * Retrieve feed-forward counter and time of last kernel tick.
792b0fdc837SLawrence Stewart  */
793b0fdc837SLawrence Stewart void
794b0fdc837SLawrence Stewart ffclock_last_tick(ffcounter *ffcount, struct bintime *bt, uint32_t flags)
795b0fdc837SLawrence Stewart {
796b0fdc837SLawrence Stewart 	struct fftimehands *ffth;
797b0fdc837SLawrence Stewart 	uint8_t gen;
798b0fdc837SLawrence Stewart 
799b0fdc837SLawrence Stewart 	/*
800b0fdc837SLawrence Stewart 	 * No locking but check generation has not changed. Also need to make
801b0fdc837SLawrence Stewart 	 * sure ffdelta is positive, i.e. ffcount > tick_ffcount.
802b0fdc837SLawrence Stewart 	 */
803b0fdc837SLawrence Stewart 	do {
804b0fdc837SLawrence Stewart 		ffth = fftimehands;
805b0fdc837SLawrence Stewart 		gen = ffth->gen;
806b0fdc837SLawrence Stewart 		if ((flags & FFCLOCK_LERP) == FFCLOCK_LERP)
807b0fdc837SLawrence Stewart 			*bt = ffth->tick_time_lerp;
808b0fdc837SLawrence Stewart 		else
809b0fdc837SLawrence Stewart 			*bt = ffth->tick_time;
810b0fdc837SLawrence Stewart 		*ffcount = ffth->tick_ffcount;
811b0fdc837SLawrence Stewart 	} while (gen == 0 || gen != ffth->gen);
812b0fdc837SLawrence Stewart }
813b0fdc837SLawrence Stewart 
814b0fdc837SLawrence Stewart /*
815b0fdc837SLawrence Stewart  * Absolute clock conversion. Low level function to convert ffcounter to
816b0fdc837SLawrence Stewart  * bintime. The ffcounter is converted using the current ffclock period estimate
817b0fdc837SLawrence Stewart  * or the "interpolated period" to ensure monotonicity.
818b0fdc837SLawrence Stewart  * NOTE: this conversion may have been deferred, and the clock updated since the
819b0fdc837SLawrence Stewart  * hardware counter has been read.
820b0fdc837SLawrence Stewart  */
821b0fdc837SLawrence Stewart void
822b0fdc837SLawrence Stewart ffclock_convert_abs(ffcounter ffcount, struct bintime *bt, uint32_t flags)
823b0fdc837SLawrence Stewart {
824b0fdc837SLawrence Stewart 	struct fftimehands *ffth;
825b0fdc837SLawrence Stewart 	struct bintime bt2;
826b0fdc837SLawrence Stewart 	ffcounter ffdelta;
827b0fdc837SLawrence Stewart 	uint8_t gen;
828b0fdc837SLawrence Stewart 
829b0fdc837SLawrence Stewart 	/*
830b0fdc837SLawrence Stewart 	 * No locking but check generation has not changed. Also need to make
831b0fdc837SLawrence Stewart 	 * sure ffdelta is positive, i.e. ffcount > tick_ffcount.
832b0fdc837SLawrence Stewart 	 */
833b0fdc837SLawrence Stewart 	do {
834b0fdc837SLawrence Stewart 		ffth = fftimehands;
835b0fdc837SLawrence Stewart 		gen = ffth->gen;
836b0fdc837SLawrence Stewart 		if (ffcount > ffth->tick_ffcount)
837b0fdc837SLawrence Stewart 			ffdelta = ffcount - ffth->tick_ffcount;
838b0fdc837SLawrence Stewart 		else
839b0fdc837SLawrence Stewart 			ffdelta = ffth->tick_ffcount - ffcount;
840b0fdc837SLawrence Stewart 
841b0fdc837SLawrence Stewart 		if ((flags & FFCLOCK_LERP) == FFCLOCK_LERP) {
842b0fdc837SLawrence Stewart 			*bt = ffth->tick_time_lerp;
843b0fdc837SLawrence Stewart 			ffclock_convert_delta(ffdelta, ffth->period_lerp, &bt2);
844b0fdc837SLawrence Stewart 		} else {
845b0fdc837SLawrence Stewart 			*bt = ffth->tick_time;
846b0fdc837SLawrence Stewart 			ffclock_convert_delta(ffdelta, ffth->cest.period, &bt2);
847b0fdc837SLawrence Stewart 		}
848b0fdc837SLawrence Stewart 
849b0fdc837SLawrence Stewart 		if (ffcount > ffth->tick_ffcount)
850b0fdc837SLawrence Stewart 			bintime_add(bt, &bt2);
851b0fdc837SLawrence Stewart 		else
852b0fdc837SLawrence Stewart 			bintime_sub(bt, &bt2);
853b0fdc837SLawrence Stewart 	} while (gen == 0 || gen != ffth->gen);
854b0fdc837SLawrence Stewart }
855b0fdc837SLawrence Stewart 
856b0fdc837SLawrence Stewart /*
857b0fdc837SLawrence Stewart  * Difference clock conversion.
858b0fdc837SLawrence Stewart  * Low level function to Convert a time interval measured in RAW counter units
859b0fdc837SLawrence Stewart  * into bintime. The difference clock allows measuring small intervals much more
860b0fdc837SLawrence Stewart  * reliably than the absolute clock.
861b0fdc837SLawrence Stewart  */
862b0fdc837SLawrence Stewart void
863b0fdc837SLawrence Stewart ffclock_convert_diff(ffcounter ffdelta, struct bintime *bt)
864b0fdc837SLawrence Stewart {
865b0fdc837SLawrence Stewart 	struct fftimehands *ffth;
866b0fdc837SLawrence Stewart 	uint8_t gen;
867b0fdc837SLawrence Stewart 
868b0fdc837SLawrence Stewart 	/* No locking but check generation has not changed. */
869b0fdc837SLawrence Stewart 	do {
870b0fdc837SLawrence Stewart 		ffth = fftimehands;
871b0fdc837SLawrence Stewart 		gen = ffth->gen;
872b0fdc837SLawrence Stewart 		ffclock_convert_delta(ffdelta, ffth->cest.period, bt);
873b0fdc837SLawrence Stewart 	} while (gen == 0 || gen != ffth->gen);
874b0fdc837SLawrence Stewart }
875b0fdc837SLawrence Stewart 
876b0fdc837SLawrence Stewart /*
877b0fdc837SLawrence Stewart  * Access to current ffcounter value.
878b0fdc837SLawrence Stewart  */
879b0fdc837SLawrence Stewart void
880b0fdc837SLawrence Stewart ffclock_read_counter(ffcounter *ffcount)
881b0fdc837SLawrence Stewart {
882b0fdc837SLawrence Stewart 	struct timehands *th;
883b0fdc837SLawrence Stewart 	struct fftimehands *ffth;
884b0fdc837SLawrence Stewart 	unsigned int gen, delta;
885b0fdc837SLawrence Stewart 
886b0fdc837SLawrence Stewart 	/*
887b0fdc837SLawrence Stewart 	 * ffclock_windup() called from tc_windup(), safe to rely on
888b0fdc837SLawrence Stewart 	 * th->th_generation only, for correct delta and ffcounter.
889b0fdc837SLawrence Stewart 	 */
890b0fdc837SLawrence Stewart 	do {
891b0fdc837SLawrence Stewart 		th = timehands;
892f4b5a972SKonstantin Belousov 		gen = atomic_load_acq_int(&th->th_generation);
893b0fdc837SLawrence Stewart 		ffth = fftimehands;
894b0fdc837SLawrence Stewart 		delta = tc_delta(th);
895b0fdc837SLawrence Stewart 		*ffcount = ffth->tick_ffcount;
896f4b5a972SKonstantin Belousov 		atomic_thread_fence_acq();
897f4b5a972SKonstantin Belousov 	} while (gen == 0 || gen != th->th_generation);
898b0fdc837SLawrence Stewart 
899b0fdc837SLawrence Stewart 	*ffcount += delta;
900b0fdc837SLawrence Stewart }
9019bce0f05SLawrence Stewart 
9029bce0f05SLawrence Stewart void
9039bce0f05SLawrence Stewart binuptime(struct bintime *bt)
9049bce0f05SLawrence Stewart {
9059bce0f05SLawrence Stewart 
90688394fe4SLawrence Stewart 	binuptime_fromclock(bt, sysclock_active);
9079bce0f05SLawrence Stewart }
9089bce0f05SLawrence Stewart 
9099bce0f05SLawrence Stewart void
9109bce0f05SLawrence Stewart nanouptime(struct timespec *tsp)
9119bce0f05SLawrence Stewart {
9129bce0f05SLawrence Stewart 
91388394fe4SLawrence Stewart 	nanouptime_fromclock(tsp, sysclock_active);
9149bce0f05SLawrence Stewart }
9159bce0f05SLawrence Stewart 
9169bce0f05SLawrence Stewart void
9179bce0f05SLawrence Stewart microuptime(struct timeval *tvp)
9189bce0f05SLawrence Stewart {
9199bce0f05SLawrence Stewart 
92088394fe4SLawrence Stewart 	microuptime_fromclock(tvp, sysclock_active);
9219bce0f05SLawrence Stewart }
9229bce0f05SLawrence Stewart 
9239bce0f05SLawrence Stewart void
9249bce0f05SLawrence Stewart bintime(struct bintime *bt)
9259bce0f05SLawrence Stewart {
9269bce0f05SLawrence Stewart 
92788394fe4SLawrence Stewart 	bintime_fromclock(bt, sysclock_active);
9289bce0f05SLawrence Stewart }
9299bce0f05SLawrence Stewart 
9309bce0f05SLawrence Stewart void
9319bce0f05SLawrence Stewart nanotime(struct timespec *tsp)
9329bce0f05SLawrence Stewart {
9339bce0f05SLawrence Stewart 
93488394fe4SLawrence Stewart 	nanotime_fromclock(tsp, sysclock_active);
9359bce0f05SLawrence Stewart }
9369bce0f05SLawrence Stewart 
9379bce0f05SLawrence Stewart void
9389bce0f05SLawrence Stewart microtime(struct timeval *tvp)
9399bce0f05SLawrence Stewart {
9409bce0f05SLawrence Stewart 
94188394fe4SLawrence Stewart 	microtime_fromclock(tvp, sysclock_active);
9429bce0f05SLawrence Stewart }
9439bce0f05SLawrence Stewart 
9449bce0f05SLawrence Stewart void
9459bce0f05SLawrence Stewart getbinuptime(struct bintime *bt)
9469bce0f05SLawrence Stewart {
9479bce0f05SLawrence Stewart 
94888394fe4SLawrence Stewart 	getbinuptime_fromclock(bt, sysclock_active);
9499bce0f05SLawrence Stewart }
9509bce0f05SLawrence Stewart 
9519bce0f05SLawrence Stewart void
9529bce0f05SLawrence Stewart getnanouptime(struct timespec *tsp)
9539bce0f05SLawrence Stewart {
9549bce0f05SLawrence Stewart 
95588394fe4SLawrence Stewart 	getnanouptime_fromclock(tsp, sysclock_active);
9569bce0f05SLawrence Stewart }
9579bce0f05SLawrence Stewart 
9589bce0f05SLawrence Stewart void
9599bce0f05SLawrence Stewart getmicrouptime(struct timeval *tvp)
9609bce0f05SLawrence Stewart {
9619bce0f05SLawrence Stewart 
96288394fe4SLawrence Stewart 	getmicrouptime_fromclock(tvp, sysclock_active);
9639bce0f05SLawrence Stewart }
9649bce0f05SLawrence Stewart 
9659bce0f05SLawrence Stewart void
9669bce0f05SLawrence Stewart getbintime(struct bintime *bt)
9679bce0f05SLawrence Stewart {
9689bce0f05SLawrence Stewart 
96988394fe4SLawrence Stewart 	getbintime_fromclock(bt, sysclock_active);
9709bce0f05SLawrence Stewart }
9719bce0f05SLawrence Stewart 
9729bce0f05SLawrence Stewart void
9739bce0f05SLawrence Stewart getnanotime(struct timespec *tsp)
9749bce0f05SLawrence Stewart {
9759bce0f05SLawrence Stewart 
97688394fe4SLawrence Stewart 	getnanotime_fromclock(tsp, sysclock_active);
9779bce0f05SLawrence Stewart }
9789bce0f05SLawrence Stewart 
9799bce0f05SLawrence Stewart void
9809bce0f05SLawrence Stewart getmicrotime(struct timeval *tvp)
9819bce0f05SLawrence Stewart {
9829bce0f05SLawrence Stewart 
98388394fe4SLawrence Stewart 	getmicrouptime_fromclock(tvp, sysclock_active);
9849bce0f05SLawrence Stewart }
9856cedd609SLawrence Stewart 
986b0fdc837SLawrence Stewart #endif /* FFCLOCK */
987b0fdc837SLawrence Stewart 
98839acc78aSPoul-Henning Kamp /*
98957d025c3SGeorge V. Neville-Neil  * This is a clone of getnanotime and used for walltimestamps.
99057d025c3SGeorge V. Neville-Neil  * The dtrace_ prefix prevents fbt from creating probes for
99157d025c3SGeorge V. Neville-Neil  * it so walltimestamp can be safely used in all fbt probes.
99257d025c3SGeorge V. Neville-Neil  */
99357d025c3SGeorge V. Neville-Neil void
99457d025c3SGeorge V. Neville-Neil dtrace_getnanotime(struct timespec *tsp)
99557d025c3SGeorge V. Neville-Neil {
99657d025c3SGeorge V. Neville-Neil 
9976cf2362eSKonstantin Belousov 	GETTHMEMBER(tsp, th_nanotime);
99857d025c3SGeorge V. Neville-Neil }
99957d025c3SGeorge V. Neville-Neil 
100057d025c3SGeorge V. Neville-Neil /*
10016cedd609SLawrence Stewart  * System clock currently providing time to the system. Modifiable via sysctl
10026cedd609SLawrence Stewart  * when the FFCLOCK option is defined.
10036cedd609SLawrence Stewart  */
10046cedd609SLawrence Stewart int sysclock_active = SYSCLOCK_FBCK;
10056cedd609SLawrence Stewart 
10066cedd609SLawrence Stewart /* Internal NTP status and error estimates. */
10076cedd609SLawrence Stewart extern int time_status;
10086cedd609SLawrence Stewart extern long time_esterror;
10096cedd609SLawrence Stewart 
10106cedd609SLawrence Stewart /*
10116cedd609SLawrence Stewart  * Take a snapshot of sysclock data which can be used to compare system clocks
10126cedd609SLawrence Stewart  * and generate timestamps after the fact.
10136cedd609SLawrence Stewart  */
10146cedd609SLawrence Stewart void
10156cedd609SLawrence Stewart sysclock_getsnapshot(struct sysclock_snap *clock_snap, int fast)
10166cedd609SLawrence Stewart {
10176cedd609SLawrence Stewart 	struct fbclock_info *fbi;
10186cedd609SLawrence Stewart 	struct timehands *th;
10196cedd609SLawrence Stewart 	struct bintime bt;
10206cedd609SLawrence Stewart 	unsigned int delta, gen;
10216cedd609SLawrence Stewart #ifdef FFCLOCK
10226cedd609SLawrence Stewart 	ffcounter ffcount;
10236cedd609SLawrence Stewart 	struct fftimehands *ffth;
10246cedd609SLawrence Stewart 	struct ffclock_info *ffi;
10256cedd609SLawrence Stewart 	struct ffclock_estimate cest;
10266cedd609SLawrence Stewart 
10276cedd609SLawrence Stewart 	ffi = &clock_snap->ff_info;
10286cedd609SLawrence Stewart #endif
10296cedd609SLawrence Stewart 
10306cedd609SLawrence Stewart 	fbi = &clock_snap->fb_info;
10316cedd609SLawrence Stewart 	delta = 0;
10326cedd609SLawrence Stewart 
10336cedd609SLawrence Stewart 	do {
10346cedd609SLawrence Stewart 		th = timehands;
1035f4b5a972SKonstantin Belousov 		gen = atomic_load_acq_int(&th->th_generation);
10366cedd609SLawrence Stewart 		fbi->th_scale = th->th_scale;
10376cedd609SLawrence Stewart 		fbi->tick_time = th->th_offset;
10386cedd609SLawrence Stewart #ifdef FFCLOCK
10396cedd609SLawrence Stewart 		ffth = fftimehands;
10406cedd609SLawrence Stewart 		ffi->tick_time = ffth->tick_time_lerp;
10416cedd609SLawrence Stewart 		ffi->tick_time_lerp = ffth->tick_time_lerp;
10426cedd609SLawrence Stewart 		ffi->period = ffth->cest.period;
10436cedd609SLawrence Stewart 		ffi->period_lerp = ffth->period_lerp;
10446cedd609SLawrence Stewart 		clock_snap->ffcount = ffth->tick_ffcount;
10456cedd609SLawrence Stewart 		cest = ffth->cest;
10466cedd609SLawrence Stewart #endif
10476cedd609SLawrence Stewart 		if (!fast)
10486cedd609SLawrence Stewart 			delta = tc_delta(th);
1049f4b5a972SKonstantin Belousov 		atomic_thread_fence_acq();
1050f4b5a972SKonstantin Belousov 	} while (gen == 0 || gen != th->th_generation);
10516cedd609SLawrence Stewart 
10526cedd609SLawrence Stewart 	clock_snap->delta = delta;
10536cedd609SLawrence Stewart 	clock_snap->sysclock_active = sysclock_active;
10546cedd609SLawrence Stewart 
10556cedd609SLawrence Stewart 	/* Record feedback clock status and error. */
10566cedd609SLawrence Stewart 	clock_snap->fb_info.status = time_status;
10576cedd609SLawrence Stewart 	/* XXX: Very crude estimate of feedback clock error. */
10586cedd609SLawrence Stewart 	bt.sec = time_esterror / 1000000;
10596cedd609SLawrence Stewart 	bt.frac = ((time_esterror - bt.sec) * 1000000) *
10606cedd609SLawrence Stewart 	    (uint64_t)18446744073709ULL;
10616cedd609SLawrence Stewart 	clock_snap->fb_info.error = bt;
10626cedd609SLawrence Stewart 
10636cedd609SLawrence Stewart #ifdef FFCLOCK
10646cedd609SLawrence Stewart 	if (!fast)
10656cedd609SLawrence Stewart 		clock_snap->ffcount += delta;
10666cedd609SLawrence Stewart 
10676cedd609SLawrence Stewart 	/* Record feed-forward clock leap second adjustment. */
10686cedd609SLawrence Stewart 	ffi->leapsec_adjustment = cest.leapsec_total;
10696cedd609SLawrence Stewart 	if (clock_snap->ffcount > cest.leapsec_next)
10706cedd609SLawrence Stewart 		ffi->leapsec_adjustment -= cest.leapsec;
10716cedd609SLawrence Stewart 
10726cedd609SLawrence Stewart 	/* Record feed-forward clock status and error. */
10736cedd609SLawrence Stewart 	clock_snap->ff_info.status = cest.status;
10746cedd609SLawrence Stewart 	ffcount = clock_snap->ffcount - cest.update_ffcount;
10756cedd609SLawrence Stewart 	ffclock_convert_delta(ffcount, cest.period, &bt);
10766cedd609SLawrence Stewart 	/* 18446744073709 = int(2^64/1e12), err_bound_rate in [ps/s]. */
10776cedd609SLawrence Stewart 	bintime_mul(&bt, cest.errb_rate * (uint64_t)18446744073709ULL);
10786cedd609SLawrence Stewart 	/* 18446744073 = int(2^64 / 1e9), since err_abs in [ns]. */
10796cedd609SLawrence Stewart 	bintime_addx(&bt, cest.errb_abs * (uint64_t)18446744073ULL);
10806cedd609SLawrence Stewart 	clock_snap->ff_info.error = bt;
10816cedd609SLawrence Stewart #endif
10826cedd609SLawrence Stewart }
10836cedd609SLawrence Stewart 
10846cedd609SLawrence Stewart /*
10856cedd609SLawrence Stewart  * Convert a sysclock snapshot into a struct bintime based on the specified
10866cedd609SLawrence Stewart  * clock source and flags.
10876cedd609SLawrence Stewart  */
10886cedd609SLawrence Stewart int
10896cedd609SLawrence Stewart sysclock_snap2bintime(struct sysclock_snap *cs, struct bintime *bt,
10906cedd609SLawrence Stewart     int whichclock, uint32_t flags)
10916cedd609SLawrence Stewart {
1092584b675eSKonstantin Belousov 	struct bintime boottimebin;
10936cedd609SLawrence Stewart #ifdef FFCLOCK
10946cedd609SLawrence Stewart 	struct bintime bt2;
10956cedd609SLawrence Stewart 	uint64_t period;
10966cedd609SLawrence Stewart #endif
10976cedd609SLawrence Stewart 
10986cedd609SLawrence Stewart 	switch (whichclock) {
10996cedd609SLawrence Stewart 	case SYSCLOCK_FBCK:
11006cedd609SLawrence Stewart 		*bt = cs->fb_info.tick_time;
11016cedd609SLawrence Stewart 
11026cedd609SLawrence Stewart 		/* If snapshot was created with !fast, delta will be >0. */
11036cedd609SLawrence Stewart 		if (cs->delta > 0)
11046cedd609SLawrence Stewart 			bintime_addx(bt, cs->fb_info.th_scale * cs->delta);
11056cedd609SLawrence Stewart 
1106584b675eSKonstantin Belousov 		if ((flags & FBCLOCK_UPTIME) == 0) {
1107584b675eSKonstantin Belousov 			getboottimebin(&boottimebin);
11086cedd609SLawrence Stewart 			bintime_add(bt, &boottimebin);
1109584b675eSKonstantin Belousov 		}
11106cedd609SLawrence Stewart 		break;
11116cedd609SLawrence Stewart #ifdef FFCLOCK
11126cedd609SLawrence Stewart 	case SYSCLOCK_FFWD:
11136cedd609SLawrence Stewart 		if (flags & FFCLOCK_LERP) {
11146cedd609SLawrence Stewart 			*bt = cs->ff_info.tick_time_lerp;
11156cedd609SLawrence Stewart 			period = cs->ff_info.period_lerp;
11166cedd609SLawrence Stewart 		} else {
11176cedd609SLawrence Stewart 			*bt = cs->ff_info.tick_time;
11186cedd609SLawrence Stewart 			period = cs->ff_info.period;
11196cedd609SLawrence Stewart 		}
11206cedd609SLawrence Stewart 
11216cedd609SLawrence Stewart 		/* If snapshot was created with !fast, delta will be >0. */
11226cedd609SLawrence Stewart 		if (cs->delta > 0) {
11236cedd609SLawrence Stewart 			ffclock_convert_delta(cs->delta, period, &bt2);
11246cedd609SLawrence Stewart 			bintime_add(bt, &bt2);
11256cedd609SLawrence Stewart 		}
11266cedd609SLawrence Stewart 
11276cedd609SLawrence Stewart 		/* Leap second adjustment. */
11286cedd609SLawrence Stewart 		if (flags & FFCLOCK_LEAPSEC)
11296cedd609SLawrence Stewart 			bt->sec -= cs->ff_info.leapsec_adjustment;
11306cedd609SLawrence Stewart 
11316cedd609SLawrence Stewart 		/* Boot time adjustment, for uptime/monotonic clocks. */
11326cedd609SLawrence Stewart 		if (flags & FFCLOCK_UPTIME)
11336cedd609SLawrence Stewart 			bintime_sub(bt, &ffclock_boottime);
1134de02885aSKevin Lo 		break;
11356cedd609SLawrence Stewart #endif
11366cedd609SLawrence Stewart 	default:
11376cedd609SLawrence Stewart 		return (EINVAL);
11386cedd609SLawrence Stewart 		break;
11396cedd609SLawrence Stewart 	}
11406cedd609SLawrence Stewart 
11416cedd609SLawrence Stewart 	return (0);
11426cedd609SLawrence Stewart }
11436cedd609SLawrence Stewart 
11446cedd609SLawrence Stewart /*
114578a49a45SPoul-Henning Kamp  * Initialize a new timecounter and possibly use it.
11464e2befc0SPoul-Henning Kamp  */
11477ec73f64SPoul-Henning Kamp void
114891266b96SPoul-Henning Kamp tc_init(struct timecounter *tc)
11497ec73f64SPoul-Henning Kamp {
1150555a5de2SPoul-Henning Kamp 	u_int u;
115193ef14a7SDavid Malone 	struct sysctl_oid *tc_root;
11527ec73f64SPoul-Henning Kamp 
1153c679c734SPoul-Henning Kamp 	u = tc->tc_frequency / tc->tc_counter_mask;
1154555a5de2SPoul-Henning Kamp 	/* XXX: We need some margin here, 10% is a guess */
1155555a5de2SPoul-Henning Kamp 	u *= 11;
1156555a5de2SPoul-Henning Kamp 	u /= 10;
1157c679c734SPoul-Henning Kamp 	if (u > hz && tc->tc_quality >= 0) {
1158c679c734SPoul-Henning Kamp 		tc->tc_quality = -2000;
1159c679c734SPoul-Henning Kamp 		if (bootverbose) {
1160c679c734SPoul-Henning Kamp 			printf("Timecounter \"%s\" frequency %ju Hz",
1161555a5de2SPoul-Henning Kamp 			    tc->tc_name, (uintmax_t)tc->tc_frequency);
1162c679c734SPoul-Henning Kamp 			printf(" -- Insufficient hz, needs at least %u\n", u);
1163c679c734SPoul-Henning Kamp 		}
1164c679c734SPoul-Henning Kamp 	} else if (tc->tc_quality >= 0 || bootverbose) {
1165555a5de2SPoul-Henning Kamp 		printf("Timecounter \"%s\" frequency %ju Hz quality %d\n",
1166555a5de2SPoul-Henning Kamp 		    tc->tc_name, (uintmax_t)tc->tc_frequency,
116778a49a45SPoul-Henning Kamp 		    tc->tc_quality);
1168e46eeb89SPoul-Henning Kamp 	}
1169c679c734SPoul-Henning Kamp 
117062efba6aSPoul-Henning Kamp 	tc->tc_next = timecounters;
117162efba6aSPoul-Henning Kamp 	timecounters = tc;
1172555a5de2SPoul-Henning Kamp 	/*
117393ef14a7SDavid Malone 	 * Set up sysctl tree for this counter.
117493ef14a7SDavid Malone 	 */
1175fd0f5970SEd Schouten 	tc_root = SYSCTL_ADD_NODE_WITH_LABEL(NULL,
117693ef14a7SDavid Malone 	    SYSCTL_STATIC_CHILDREN(_kern_timecounter_tc), OID_AUTO, tc->tc_name,
1177*7029da5cSPawel Biernacki 	    CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
1178*7029da5cSPawel Biernacki 	    "timecounter description", "timecounter");
117993ef14a7SDavid Malone 	SYSCTL_ADD_UINT(NULL, SYSCTL_CHILDREN(tc_root), OID_AUTO,
118093ef14a7SDavid Malone 	    "mask", CTLFLAG_RD, &(tc->tc_counter_mask), 0,
118193ef14a7SDavid Malone 	    "mask for implemented bits");
118293ef14a7SDavid Malone 	SYSCTL_ADD_PROC(NULL, SYSCTL_CHILDREN(tc_root), OID_AUTO,
1183*7029da5cSPawel Biernacki 	    "counter", CTLTYPE_UINT | CTLFLAG_RD | CTLFLAG_MPSAFE, tc,
1184*7029da5cSPawel Biernacki 	    sizeof(*tc), sysctl_kern_timecounter_get, "IU",
1185*7029da5cSPawel Biernacki 	    "current timecounter value");
118693ef14a7SDavid Malone 	SYSCTL_ADD_PROC(NULL, SYSCTL_CHILDREN(tc_root), OID_AUTO,
1187*7029da5cSPawel Biernacki 	    "frequency", CTLTYPE_U64 | CTLFLAG_RD | CTLFLAG_MPSAFE, tc,
1188*7029da5cSPawel Biernacki 	    sizeof(*tc), sysctl_kern_timecounter_freq, "QU",
1189*7029da5cSPawel Biernacki 	    "timecounter frequency");
119093ef14a7SDavid Malone 	SYSCTL_ADD_INT(NULL, SYSCTL_CHILDREN(tc_root), OID_AUTO,
119193ef14a7SDavid Malone 	    "quality", CTLFLAG_RD, &(tc->tc_quality), 0,
119293ef14a7SDavid Malone 	    "goodness of time counter");
119393ef14a7SDavid Malone 	/*
1194e8bac3f2SIan Lepore 	 * Do not automatically switch if the current tc was specifically
1195e8bac3f2SIan Lepore 	 * chosen.  Never automatically use a timecounter with negative quality.
1196555a5de2SPoul-Henning Kamp 	 * Even though we run on the dummy counter, switching here may be
1197e8bac3f2SIan Lepore 	 * worse since this timecounter may not be monotonic.
1198555a5de2SPoul-Henning Kamp 	 */
1199e8bac3f2SIan Lepore 	if (tc_chosen)
1200e8bac3f2SIan Lepore 		return;
120178a49a45SPoul-Henning Kamp 	if (tc->tc_quality < 0)
120278a49a45SPoul-Henning Kamp 		return;
120378a49a45SPoul-Henning Kamp 	if (tc->tc_quality < timecounter->tc_quality)
120478a49a45SPoul-Henning Kamp 		return;
1205555a5de2SPoul-Henning Kamp 	if (tc->tc_quality == timecounter->tc_quality &&
1206555a5de2SPoul-Henning Kamp 	    tc->tc_frequency < timecounter->tc_frequency)
1207555a5de2SPoul-Henning Kamp 		return;
1208555a5de2SPoul-Henning Kamp 	(void)tc->tc_get_timecount(tc);
1209555a5de2SPoul-Henning Kamp 	(void)tc->tc_get_timecount(tc);
12107ec73f64SPoul-Henning Kamp 	timecounter = tc;
121162efba6aSPoul-Henning Kamp }
121262efba6aSPoul-Henning Kamp 
121339acc78aSPoul-Henning Kamp /* Report the frequency of the current timecounter. */
121460ae52f7SEd Schouten uint64_t
121562efba6aSPoul-Henning Kamp tc_getfrequency(void)
121662efba6aSPoul-Henning Kamp {
121762efba6aSPoul-Henning Kamp 
12186b00cf46SPoul-Henning Kamp 	return (timehands->th_counter->tc_frequency);
12197ec73f64SPoul-Henning Kamp }
12207ec73f64SPoul-Henning Kamp 
12219dbdf2a1SEric van Gyzen static bool
12229dbdf2a1SEric van Gyzen sleeping_on_old_rtc(struct thread *td)
12239dbdf2a1SEric van Gyzen {
12249dbdf2a1SEric van Gyzen 
12258addc72bSEric van Gyzen 	/*
12268addc72bSEric van Gyzen 	 * td_rtcgen is modified by curthread when it is running,
12278addc72bSEric van Gyzen 	 * and by other threads in this function.  By finding the thread
12288addc72bSEric van Gyzen 	 * on a sleepqueue and holding the lock on the sleepqueue
12298addc72bSEric van Gyzen 	 * chain, we guarantee that the thread is not running and that
12308addc72bSEric van Gyzen 	 * modifying td_rtcgen is safe.  Setting td_rtcgen to zero informs
12318addc72bSEric van Gyzen 	 * the thread that it was woken due to a real-time clock adjustment.
12328addc72bSEric van Gyzen 	 * (The declaration of td_rtcgen refers to this comment.)
12338addc72bSEric van Gyzen 	 */
12349dbdf2a1SEric van Gyzen 	if (td->td_rtcgen != 0 && td->td_rtcgen != rtc_generation) {
12359dbdf2a1SEric van Gyzen 		td->td_rtcgen = 0;
12369dbdf2a1SEric van Gyzen 		return (true);
12379dbdf2a1SEric van Gyzen 	}
12389dbdf2a1SEric van Gyzen 	return (false);
12399dbdf2a1SEric van Gyzen }
12409dbdf2a1SEric van Gyzen 
12415760b029SKonstantin Belousov static struct mtx tc_setclock_mtx;
12425760b029SKonstantin Belousov MTX_SYSINIT(tc_setclock_init, &tc_setclock_mtx, "tcsetc", MTX_SPIN);
12435760b029SKonstantin Belousov 
124439acc78aSPoul-Henning Kamp /*
12454e82e5f6SWarner Losh  * Step our concept of UTC.  This is done by modifying our estimate of
12464e74721cSPoul-Henning Kamp  * when we booted.
12476b00cf46SPoul-Henning Kamp  */
12487ec73f64SPoul-Henning Kamp void
124991266b96SPoul-Henning Kamp tc_setclock(struct timespec *ts)
12507ec73f64SPoul-Henning Kamp {
12515b51d1deSPoul-Henning Kamp 	struct timespec tbef, taft;
12524e74721cSPoul-Henning Kamp 	struct bintime bt, bt2;
12537ec73f64SPoul-Henning Kamp 
12544e74721cSPoul-Henning Kamp 	timespec2bintime(ts, &bt);
12555760b029SKonstantin Belousov 	nanotime(&tbef);
12565760b029SKonstantin Belousov 	mtx_lock_spin(&tc_setclock_mtx);
12575760b029SKonstantin Belousov 	cpu_tick_calibrate(1);
12585b51d1deSPoul-Henning Kamp 	binuptime(&bt2);
12594e74721cSPoul-Henning Kamp 	bintime_sub(&bt, &bt2);
126039acc78aSPoul-Henning Kamp 
126139acc78aSPoul-Henning Kamp 	/* XXX fiddle all the little crinkly bits around the fiords... */
12625760b029SKonstantin Belousov 	tc_windup(&bt);
12635760b029SKonstantin Belousov 	mtx_unlock_spin(&tc_setclock_mtx);
12648addc72bSEric van Gyzen 
12659dbdf2a1SEric van Gyzen 	/* Avoid rtc_generation == 0, since td_rtcgen == 0 is special. */
12669dbdf2a1SEric van Gyzen 	atomic_add_rel_int(&rtc_generation, 2);
12679dbdf2a1SEric van Gyzen 	sleepq_chains_remove_matching(sleeping_on_old_rtc);
12684e74721cSPoul-Henning Kamp 	if (timestepwarnings) {
12695760b029SKonstantin Belousov 		nanotime(&taft);
12705b51d1deSPoul-Henning Kamp 		log(LOG_INFO,
12715b51d1deSPoul-Henning Kamp 		    "Time stepped from %jd.%09ld to %jd.%09ld (%jd.%09ld)\n",
12725b51d1deSPoul-Henning Kamp 		    (intmax_t)tbef.tv_sec, tbef.tv_nsec,
12735b51d1deSPoul-Henning Kamp 		    (intmax_t)taft.tv_sec, taft.tv_nsec,
1274ee57aeeaSPoul-Henning Kamp 		    (intmax_t)ts->tv_sec, ts->tv_nsec);
12754e74721cSPoul-Henning Kamp 	}
12767ec73f64SPoul-Henning Kamp }
12777ec73f64SPoul-Henning Kamp 
127839acc78aSPoul-Henning Kamp /*
127939acc78aSPoul-Henning Kamp  * Initialize the next struct timehands in the ring and make
12806b00cf46SPoul-Henning Kamp  * it the active timehands.  Along the way we might switch to a different
12816b00cf46SPoul-Henning Kamp  * timecounter and/or do seconds processing in NTP.  Slightly magic.
12826b00cf46SPoul-Henning Kamp  */
12839e1b5510SPoul-Henning Kamp static void
12845760b029SKonstantin Belousov tc_windup(struct bintime *new_boottimebin)
12857ec73f64SPoul-Henning Kamp {
12862028c0cdSPoul-Henning Kamp 	struct bintime bt;
128739acc78aSPoul-Henning Kamp 	struct timehands *th, *tho;
128860ae52f7SEd Schouten 	uint64_t scale;
128939acc78aSPoul-Henning Kamp 	u_int delta, ncount, ogen;
129039acc78aSPoul-Henning Kamp 	int i;
12914f2073fbSWarner Losh 	time_t t;
12927ec73f64SPoul-Henning Kamp 
129339acc78aSPoul-Henning Kamp 	/*
1294f4b5a972SKonstantin Belousov 	 * Make the next timehands a copy of the current one, but do
1295f4b5a972SKonstantin Belousov 	 * not overwrite the generation or next pointer.  While we
1296f4b5a972SKonstantin Belousov 	 * update the contents, the generation must be zero.  We need
1297f4b5a972SKonstantin Belousov 	 * to ensure that the zero generation is visible before the
1298f4b5a972SKonstantin Belousov 	 * data updates become visible, which requires release fence.
1299f4b5a972SKonstantin Belousov 	 * For similar reasons, re-reading of the generation after the
1300f4b5a972SKonstantin Belousov 	 * data is read should use acquire fence.
13016b00cf46SPoul-Henning Kamp 	 */
13026b00cf46SPoul-Henning Kamp 	tho = timehands;
13036b00cf46SPoul-Henning Kamp 	th = tho->th_next;
13046b00cf46SPoul-Henning Kamp 	ogen = th->th_generation;
1305f4b5a972SKonstantin Belousov 	th->th_generation = 0;
1306f4b5a972SKonstantin Belousov 	atomic_thread_fence_rel();
13075ec2c936SMateusz Guzik 	memcpy(th, tho, offsetof(struct timehands, th_generation));
13085760b029SKonstantin Belousov 	if (new_boottimebin != NULL)
13095760b029SKonstantin Belousov 		th->th_boottime = *new_boottimebin;
13106b00cf46SPoul-Henning Kamp 
131139acc78aSPoul-Henning Kamp 	/*
13126b00cf46SPoul-Henning Kamp 	 * Capture a timecounter delta on the current timecounter and if
13136b00cf46SPoul-Henning Kamp 	 * changing timecounters, a counter value from the new timecounter.
13146b00cf46SPoul-Henning Kamp 	 * Update the offset fields accordingly.
13156b00cf46SPoul-Henning Kamp 	 */
13166b00cf46SPoul-Henning Kamp 	delta = tc_delta(th);
13176b00cf46SPoul-Henning Kamp 	if (th->th_counter != timecounter)
13186b00cf46SPoul-Henning Kamp 		ncount = timecounter->tc_get_timecount(timecounter);
131939acc78aSPoul-Henning Kamp 	else
132039acc78aSPoul-Henning Kamp 		ncount = 0;
1321b0fdc837SLawrence Stewart #ifdef FFCLOCK
1322b0fdc837SLawrence Stewart 	ffclock_windup(delta);
1323b0fdc837SLawrence Stewart #endif
13246b00cf46SPoul-Henning Kamp 	th->th_offset_count += delta;
13256b00cf46SPoul-Henning Kamp 	th->th_offset_count &= th->th_counter->tc_counter_mask;
1326aa519c0aSColin Percival 	while (delta > th->th_counter->tc_frequency) {
1327aa519c0aSColin Percival 		/* Eat complete unadjusted seconds. */
1328aa519c0aSColin Percival 		delta -= th->th_counter->tc_frequency;
1329aa519c0aSColin Percival 		th->th_offset.sec++;
1330aa519c0aSColin Percival 	}
1331aa519c0aSColin Percival 	if ((delta > th->th_counter->tc_frequency / 2) &&
1332772d1e42SColin Percival 	    (th->th_scale * delta < ((uint64_t)1 << 63))) {
1333aa519c0aSColin Percival 		/* The product th_scale * delta just barely overflows. */
1334aa519c0aSColin Percival 		th->th_offset.sec++;
1335aa519c0aSColin Percival 	}
13366b00cf46SPoul-Henning Kamp 	bintime_addx(&th->th_offset, th->th_scale * delta);
13376b00cf46SPoul-Henning Kamp 
133839acc78aSPoul-Henning Kamp 	/*
13396b00cf46SPoul-Henning Kamp 	 * Hardware latching timecounters may not generate interrupts on
13406b00cf46SPoul-Henning Kamp 	 * PPS events, so instead we poll them.  There is a finite risk that
13416b00cf46SPoul-Henning Kamp 	 * the hardware might capture a count which is later than the one we
13426b00cf46SPoul-Henning Kamp 	 * got above, and therefore possibly in the next NTP second which might
13436b00cf46SPoul-Henning Kamp 	 * have a different rate than the current NTP second.  It doesn't
13446b00cf46SPoul-Henning Kamp 	 * matter in practice.
13456b00cf46SPoul-Henning Kamp 	 */
13466b00cf46SPoul-Henning Kamp 	if (tho->th_counter->tc_poll_pps)
13476b00cf46SPoul-Henning Kamp 		tho->th_counter->tc_poll_pps(tho->th_counter);
13486b00cf46SPoul-Henning Kamp 
134939acc78aSPoul-Henning Kamp 	/*
1350c1cccd1eSWarner Losh 	 * Deal with NTP second processing.  The for loop normally
1351c1cccd1eSWarner Losh 	 * iterates at most once, but in extreme situations it might
1352c1cccd1eSWarner Losh 	 * keep NTP sane if timeouts are not run for several seconds.
1353c1cccd1eSWarner Losh 	 * At boot, the time step can be large when the TOD hardware
1354c1cccd1eSWarner Losh 	 * has been read, so on really large steps, we call
1355c1cccd1eSWarner Losh 	 * ntp_update_second only twice.  We need to call it twice in
1356c1cccd1eSWarner Losh 	 * case we missed a leap second.
13574f2073fbSWarner Losh 	 */
13584f2073fbSWarner Losh 	bt = th->th_offset;
13595760b029SKonstantin Belousov 	bintime_add(&bt, &th->th_boottime);
136045cc9f5fSWarner Losh 	i = bt.sec - tho->th_microtime.tv_sec;
136145cc9f5fSWarner Losh 	if (i > LARGE_STEP)
136245cc9f5fSWarner Losh 		i = 2;
136345cc9f5fSWarner Losh 	for (; i > 0; i--) {
13644f2073fbSWarner Losh 		t = bt.sec;
13654f2073fbSWarner Losh 		ntp_update_second(&th->th_adjustment, &bt.sec);
13664f2073fbSWarner Losh 		if (bt.sec != t)
13675760b029SKonstantin Belousov 			th->th_boottime.sec += bt.sec - t;
13684f2073fbSWarner Losh 	}
1369c1cccd1eSWarner Losh 	/* Update the UTC timestamps used by the get*() functions. */
137070e3b262SKonstantin Belousov 	th->th_bintime = bt;
1371c1cccd1eSWarner Losh 	bintime2timeval(&bt, &th->th_microtime);
1372c1cccd1eSWarner Losh 	bintime2timespec(&bt, &th->th_nanotime);
13736b00cf46SPoul-Henning Kamp 
13746b00cf46SPoul-Henning Kamp 	/* Now is a good time to change timecounters. */
13756b00cf46SPoul-Henning Kamp 	if (th->th_counter != timecounter) {
137608e1b4f4SJung-uk Kim #ifndef __arm__
137792597e06SJohn Baldwin 		if ((timecounter->tc_flags & TC_FLAGS_C2STOP) != 0)
137892597e06SJohn Baldwin 			cpu_disable_c2_sleep++;
137992597e06SJohn Baldwin 		if ((th->th_counter->tc_flags & TC_FLAGS_C2STOP) != 0)
138092597e06SJohn Baldwin 			cpu_disable_c2_sleep--;
138108e1b4f4SJung-uk Kim #endif
13826b00cf46SPoul-Henning Kamp 		th->th_counter = timecounter;
13836b00cf46SPoul-Henning Kamp 		th->th_offset_count = ncount;
13840e189873SAlexander Motin 		tc_min_ticktock_freq = max(1, timecounter->tc_frequency /
13850e189873SAlexander Motin 		    (((uint64_t)timecounter->tc_counter_mask + 1) / 3));
1386b0fdc837SLawrence Stewart #ifdef FFCLOCK
1387b0fdc837SLawrence Stewart 		ffclock_change_tc(th);
1388b0fdc837SLawrence Stewart #endif
13897ec73f64SPoul-Henning Kamp 	}
13907ec73f64SPoul-Henning Kamp 
13911a996ed1SEdward Tomasz Napierala 	/*-
13926b00cf46SPoul-Henning Kamp 	 * Recalculate the scaling factor.  We want the number of 1/2^64
13936b00cf46SPoul-Henning Kamp 	 * fractions of a second per period of the hardware counter, taking
13946b00cf46SPoul-Henning Kamp 	 * into account the th_adjustment factor which the NTP PLL/adjtime(2)
13956b00cf46SPoul-Henning Kamp 	 * processing provides us with.
13966b00cf46SPoul-Henning Kamp 	 *
13976b00cf46SPoul-Henning Kamp 	 * The th_adjustment is nanoseconds per second with 32 bit binary
1398d94e3652SPoul-Henning Kamp 	 * fraction and we want 64 bit binary fraction of second:
13996b00cf46SPoul-Henning Kamp 	 *
14006b00cf46SPoul-Henning Kamp 	 *	 x = a * 2^32 / 10^9 = a * 4.294967296
14016b00cf46SPoul-Henning Kamp 	 *
14026b00cf46SPoul-Henning Kamp 	 * The range of th_adjustment is +/- 5000PPM so inside a 64bit int
1403e8444a7eSPoul-Henning Kamp 	 * we can only multiply by about 850 without overflowing, that
1404e8444a7eSPoul-Henning Kamp 	 * leaves no suitably precise fractions for multiply before divide.
14056b00cf46SPoul-Henning Kamp 	 *
14066b00cf46SPoul-Henning Kamp 	 * Divide before multiply with a fraction of 2199/512 results in a
14076b00cf46SPoul-Henning Kamp 	 * systematic undercompensation of 10PPM of th_adjustment.  On a
14086b00cf46SPoul-Henning Kamp 	 * 5000PPM adjustment this is a 0.05PPM error.  This is acceptable.
14096b00cf46SPoul-Henning Kamp  	 *
14106b00cf46SPoul-Henning Kamp 	 * We happily sacrifice the lowest of the 64 bits of our result
14116b00cf46SPoul-Henning Kamp 	 * to the goddess of code clarity.
141239acc78aSPoul-Henning Kamp 	 *
14136b00cf46SPoul-Henning Kamp 	 */
141460ae52f7SEd Schouten 	scale = (uint64_t)1 << 63;
14156b00cf46SPoul-Henning Kamp 	scale += (th->th_adjustment / 1024) * 2199;
14166b00cf46SPoul-Henning Kamp 	scale /= th->th_counter->tc_frequency;
14176b00cf46SPoul-Henning Kamp 	th->th_scale = scale * 2;
14186cf2362eSKonstantin Belousov 	th->th_large_delta = MIN(((uint64_t)1 << 63) / scale, UINT_MAX);
14196b00cf46SPoul-Henning Kamp 
142039acc78aSPoul-Henning Kamp 	/*
142139acc78aSPoul-Henning Kamp 	 * Now that the struct timehands is again consistent, set the new
14226b00cf46SPoul-Henning Kamp 	 * generation number, making sure to not make it zero.
14236b00cf46SPoul-Henning Kamp 	 */
14246b00cf46SPoul-Henning Kamp 	if (++ogen == 0)
142539acc78aSPoul-Henning Kamp 		ogen = 1;
1426f4b5a972SKonstantin Belousov 	atomic_store_rel_int(&th->th_generation, ogen);
14276b00cf46SPoul-Henning Kamp 
142839acc78aSPoul-Henning Kamp 	/* Go live with the new struct timehands. */
14299bce0f05SLawrence Stewart #ifdef FFCLOCK
14309bce0f05SLawrence Stewart 	switch (sysclock_active) {
14319bce0f05SLawrence Stewart 	case SYSCLOCK_FBCK:
14329bce0f05SLawrence Stewart #endif
14336b00cf46SPoul-Henning Kamp 		time_second = th->th_microtime.tv_sec;
143438b0884cSPoul-Henning Kamp 		time_uptime = th->th_offset.sec;
14359bce0f05SLawrence Stewart #ifdef FFCLOCK
14369bce0f05SLawrence Stewart 		break;
14379bce0f05SLawrence Stewart 	case SYSCLOCK_FFWD:
14389bce0f05SLawrence Stewart 		time_second = fftimehands->tick_time_lerp.sec;
14399bce0f05SLawrence Stewart 		time_uptime = fftimehands->tick_time_lerp.sec - ffclock_boottime.sec;
14409bce0f05SLawrence Stewart 		break;
14419bce0f05SLawrence Stewart 	}
14429bce0f05SLawrence Stewart #endif
14439bce0f05SLawrence Stewart 
14446b00cf46SPoul-Henning Kamp 	timehands = th;
144521c295efSKonstantin Belousov 	timekeep_push_vdso();
14466b00cf46SPoul-Henning Kamp }
14476b00cf46SPoul-Henning Kamp 
144839acc78aSPoul-Henning Kamp /* Report or change the active timecounter hardware. */
14496b6ef746SBruce Evans static int
145082d9ae4eSPoul-Henning Kamp sysctl_kern_timecounter_hardware(SYSCTL_HANDLER_ARGS)
14516b6ef746SBruce Evans {
14526b6ef746SBruce Evans 	char newname[32];
14536b6ef746SBruce Evans 	struct timecounter *newtc, *tc;
14546b6ef746SBruce Evans 	int error;
14556b6ef746SBruce Evans 
145662efba6aSPoul-Henning Kamp 	tc = timecounter;
1457e80fb434SRobert Drehmel 	strlcpy(newname, tc->tc_name, sizeof(newname));
1458e80fb434SRobert Drehmel 
14596b6ef746SBruce Evans 	error = sysctl_handle_string(oidp, &newname[0], sizeof(newname), req);
1460e8bac3f2SIan Lepore 	if (error != 0 || req->newptr == NULL)
146162efba6aSPoul-Henning Kamp 		return (error);
1462e8bac3f2SIan Lepore 	/* Record that the tc in use now was specifically chosen. */
1463e8bac3f2SIan Lepore 	tc_chosen = 1;
1464e8bac3f2SIan Lepore 	if (strcmp(newname, tc->tc_name) == 0)
1465e8bac3f2SIan Lepore 		return (0);
146662efba6aSPoul-Henning Kamp 	for (newtc = timecounters; newtc != NULL; newtc = newtc->tc_next) {
146739acc78aSPoul-Henning Kamp 		if (strcmp(newname, newtc->tc_name) != 0)
146862efba6aSPoul-Henning Kamp 			continue;
146939acc78aSPoul-Henning Kamp 
14706b6ef746SBruce Evans 		/* Warm up new timecounter. */
14716b6ef746SBruce Evans 		(void)newtc->tc_get_timecount(newtc);
147262efba6aSPoul-Henning Kamp 		(void)newtc->tc_get_timecount(newtc);
147339acc78aSPoul-Henning Kamp 
147462efba6aSPoul-Henning Kamp 		timecounter = newtc;
1475d1b1b600SNeel Natu 
1476d1b1b600SNeel Natu 		/*
1477d1b1b600SNeel Natu 		 * The vdso timehands update is deferred until the next
1478d1b1b600SNeel Natu 		 * 'tc_windup()'.
1479d1b1b600SNeel Natu 		 *
1480d1b1b600SNeel Natu 		 * This is prudent given that 'timekeep_push_vdso()' does not
1481d1b1b600SNeel Natu 		 * use any locking and that it can be called in hard interrupt
1482d1b1b600SNeel Natu 		 * context via 'tc_windup()'.
1483d1b1b600SNeel Natu 		 */
14846b6ef746SBruce Evans 		return (0);
14856b6ef746SBruce Evans 	}
14866b6ef746SBruce Evans 	return (EINVAL);
14876b6ef746SBruce Evans }
14886b6ef746SBruce Evans 
1489*7029da5cSPawel Biernacki SYSCTL_PROC(_kern_timecounter, OID_AUTO, hardware,
1490*7029da5cSPawel Biernacki     CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_MPSAFE, 0, 0,
1491*7029da5cSPawel Biernacki     sysctl_kern_timecounter_hardware, "A",
1492b389be97SRebecca Cran     "Timecounter hardware selected");
14936b6ef746SBruce Evans 
1494e8bac3f2SIan Lepore /* Report the available timecounter hardware. */
149578a49a45SPoul-Henning Kamp static int
149678a49a45SPoul-Henning Kamp sysctl_kern_timecounter_choice(SYSCTL_HANDLER_ARGS)
149778a49a45SPoul-Henning Kamp {
149891d9eda2SIan Lepore 	struct sbuf sb;
149978a49a45SPoul-Henning Kamp 	struct timecounter *tc;
150078a49a45SPoul-Henning Kamp 	int error;
150178a49a45SPoul-Henning Kamp 
150291d9eda2SIan Lepore 	sbuf_new_for_sysctl(&sb, NULL, 0, req);
150391d9eda2SIan Lepore 	for (tc = timecounters; tc != NULL; tc = tc->tc_next) {
150491d9eda2SIan Lepore 		if (tc != timecounters)
150591d9eda2SIan Lepore 			sbuf_putc(&sb, ' ');
150691d9eda2SIan Lepore 		sbuf_printf(&sb, "%s(%d)", tc->tc_name, tc->tc_quality);
150778a49a45SPoul-Henning Kamp 	}
150891d9eda2SIan Lepore 	error = sbuf_finish(&sb);
150991d9eda2SIan Lepore 	sbuf_delete(&sb);
151078a49a45SPoul-Henning Kamp 	return (error);
151178a49a45SPoul-Henning Kamp }
151278a49a45SPoul-Henning Kamp 
1513*7029da5cSPawel Biernacki SYSCTL_PROC(_kern_timecounter, OID_AUTO, choice,
1514*7029da5cSPawel Biernacki     CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_MPSAFE, 0, 0,
1515*7029da5cSPawel Biernacki     sysctl_kern_timecounter_choice, "A",
1516*7029da5cSPawel Biernacki     "Timecounter hardware detected");
151778a49a45SPoul-Henning Kamp 
151839acc78aSPoul-Henning Kamp /*
15196b00cf46SPoul-Henning Kamp  * RFC 2783 PPS-API implementation.
15206b00cf46SPoul-Henning Kamp  */
15217ec73f64SPoul-Henning Kamp 
152228315e27SIan Lepore /*
152328315e27SIan Lepore  *  Return true if the driver is aware of the abi version extensions in the
152428315e27SIan Lepore  *  pps_state structure, and it supports at least the given abi version number.
152528315e27SIan Lepore  */
152628315e27SIan Lepore static inline int
152728315e27SIan Lepore abi_aware(struct pps_state *pps, int vers)
152828315e27SIan Lepore {
152928315e27SIan Lepore 
153028315e27SIan Lepore 	return ((pps->kcmode & KCMODE_ABIFLAG) && pps->driver_abi >= vers);
153128315e27SIan Lepore }
153228315e27SIan Lepore 
1533a1137de9SIan Lepore static int
1534a1137de9SIan Lepore pps_fetch(struct pps_fetch_args *fapi, struct pps_state *pps)
1535a1137de9SIan Lepore {
1536a1137de9SIan Lepore 	int err, timo;
1537a1137de9SIan Lepore 	pps_seq_t aseq, cseq;
1538a1137de9SIan Lepore 	struct timeval tv;
1539a1137de9SIan Lepore 
1540a1137de9SIan Lepore 	if (fapi->tsformat && fapi->tsformat != PPS_TSFMT_TSPEC)
1541a1137de9SIan Lepore 		return (EINVAL);
1542a1137de9SIan Lepore 
1543a1137de9SIan Lepore 	/*
1544a1137de9SIan Lepore 	 * If no timeout is requested, immediately return whatever values were
1545a1137de9SIan Lepore 	 * most recently captured.  If timeout seconds is -1, that's a request
1546a1137de9SIan Lepore 	 * to block without a timeout.  WITNESS won't let us sleep forever
1547a1137de9SIan Lepore 	 * without a lock (we really don't need a lock), so just repeatedly
1548a1137de9SIan Lepore 	 * sleep a long time.
1549a1137de9SIan Lepore 	 */
1550a1137de9SIan Lepore 	if (fapi->timeout.tv_sec || fapi->timeout.tv_nsec) {
1551a1137de9SIan Lepore 		if (fapi->timeout.tv_sec == -1)
1552a1137de9SIan Lepore 			timo = 0x7fffffff;
1553a1137de9SIan Lepore 		else {
1554a1137de9SIan Lepore 			tv.tv_sec = fapi->timeout.tv_sec;
1555a1137de9SIan Lepore 			tv.tv_usec = fapi->timeout.tv_nsec / 1000;
1556a1137de9SIan Lepore 			timo = tvtohz(&tv);
1557a1137de9SIan Lepore 		}
15586f697994SKonstantin Belousov 		aseq = atomic_load_int(&pps->ppsinfo.assert_sequence);
15596f697994SKonstantin Belousov 		cseq = atomic_load_int(&pps->ppsinfo.clear_sequence);
15606f697994SKonstantin Belousov 		while (aseq == atomic_load_int(&pps->ppsinfo.assert_sequence) &&
15616f697994SKonstantin Belousov 		    cseq == atomic_load_int(&pps->ppsinfo.clear_sequence)) {
156228315e27SIan Lepore 			if (abi_aware(pps, 1) && pps->driver_mtx != NULL) {
156328315e27SIan Lepore 				if (pps->flags & PPSFLAG_MTX_SPIN) {
156428315e27SIan Lepore 					err = msleep_spin(pps, pps->driver_mtx,
156528315e27SIan Lepore 					    "ppsfch", timo);
156628315e27SIan Lepore 				} else {
156728315e27SIan Lepore 					err = msleep(pps, pps->driver_mtx, PCATCH,
156828315e27SIan Lepore 					    "ppsfch", timo);
156928315e27SIan Lepore 				}
157028315e27SIan Lepore 			} else {
1571a1137de9SIan Lepore 				err = tsleep(pps, PCATCH, "ppsfch", timo);
157228315e27SIan Lepore 			}
15736f7a9f7cSIan Lepore 			if (err == EWOULDBLOCK) {
15746f7a9f7cSIan Lepore 				if (fapi->timeout.tv_sec == -1) {
1575a1137de9SIan Lepore 					continue;
15766f7a9f7cSIan Lepore 				} else {
15776f7a9f7cSIan Lepore 					return (ETIMEDOUT);
15786f7a9f7cSIan Lepore 				}
1579a1137de9SIan Lepore 			} else if (err != 0) {
1580a1137de9SIan Lepore 				return (err);
1581a1137de9SIan Lepore 			}
1582a1137de9SIan Lepore 		}
1583a1137de9SIan Lepore 	}
1584a1137de9SIan Lepore 
1585a1137de9SIan Lepore 	pps->ppsinfo.current_mode = pps->ppsparam.mode;
1586a1137de9SIan Lepore 	fapi->pps_info_buf = pps->ppsinfo;
1587a1137de9SIan Lepore 
1588a1137de9SIan Lepore 	return (0);
1589a1137de9SIan Lepore }
1590a1137de9SIan Lepore 
159132c20357SPoul-Henning Kamp int
159232c20357SPoul-Henning Kamp pps_ioctl(u_long cmd, caddr_t data, struct pps_state *pps)
159332c20357SPoul-Henning Kamp {
159432c20357SPoul-Henning Kamp 	pps_params_t *app;
1595b7424f2dSJohn Hay 	struct pps_fetch_args *fapi;
159665e359a1SLawrence Stewart #ifdef FFCLOCK
159765e359a1SLawrence Stewart 	struct pps_fetch_ffc_args *fapi_ffc;
159865e359a1SLawrence Stewart #endif
1599de3f8889SPeter Wemm #ifdef PPS_SYNC
1600b7424f2dSJohn Hay 	struct pps_kcbind_args *kapi;
1601de3f8889SPeter Wemm #endif
160232c20357SPoul-Henning Kamp 
1603d8e8b675SPoul-Henning Kamp 	KASSERT(pps != NULL, ("NULL pps pointer in pps_ioctl"));
160432c20357SPoul-Henning Kamp 	switch (cmd) {
160532c20357SPoul-Henning Kamp 	case PPS_IOC_CREATE:
160632c20357SPoul-Henning Kamp 		return (0);
160732c20357SPoul-Henning Kamp 	case PPS_IOC_DESTROY:
160832c20357SPoul-Henning Kamp 		return (0);
160932c20357SPoul-Henning Kamp 	case PPS_IOC_SETPARAMS:
161032c20357SPoul-Henning Kamp 		app = (pps_params_t *)data;
161132c20357SPoul-Henning Kamp 		if (app->mode & ~pps->ppscap)
161232c20357SPoul-Henning Kamp 			return (EINVAL);
161365e359a1SLawrence Stewart #ifdef FFCLOCK
161465e359a1SLawrence Stewart 		/* Ensure only a single clock is selected for ffc timestamp. */
161565e359a1SLawrence Stewart 		if ((app->mode & PPS_TSCLK_MASK) == PPS_TSCLK_MASK)
161665e359a1SLawrence Stewart 			return (EINVAL);
161765e359a1SLawrence Stewart #endif
161832c20357SPoul-Henning Kamp 		pps->ppsparam = *app;
161932c20357SPoul-Henning Kamp 		return (0);
162032c20357SPoul-Henning Kamp 	case PPS_IOC_GETPARAMS:
162132c20357SPoul-Henning Kamp 		app = (pps_params_t *)data;
162232c20357SPoul-Henning Kamp 		*app = pps->ppsparam;
1623b7424f2dSJohn Hay 		app->api_version = PPS_API_VERS_1;
162432c20357SPoul-Henning Kamp 		return (0);
162532c20357SPoul-Henning Kamp 	case PPS_IOC_GETCAP:
162632c20357SPoul-Henning Kamp 		*(int*)data = pps->ppscap;
162732c20357SPoul-Henning Kamp 		return (0);
162832c20357SPoul-Henning Kamp 	case PPS_IOC_FETCH:
1629b7424f2dSJohn Hay 		fapi = (struct pps_fetch_args *)data;
1630a1137de9SIan Lepore 		return (pps_fetch(fapi, pps));
163165e359a1SLawrence Stewart #ifdef FFCLOCK
163265e359a1SLawrence Stewart 	case PPS_IOC_FETCH_FFCOUNTER:
163365e359a1SLawrence Stewart 		fapi_ffc = (struct pps_fetch_ffc_args *)data;
163465e359a1SLawrence Stewart 		if (fapi_ffc->tsformat && fapi_ffc->tsformat !=
163565e359a1SLawrence Stewart 		    PPS_TSFMT_TSPEC)
163665e359a1SLawrence Stewart 			return (EINVAL);
163765e359a1SLawrence Stewart 		if (fapi_ffc->timeout.tv_sec || fapi_ffc->timeout.tv_nsec)
163865e359a1SLawrence Stewart 			return (EOPNOTSUPP);
163965e359a1SLawrence Stewart 		pps->ppsinfo_ffc.current_mode = pps->ppsparam.mode;
164065e359a1SLawrence Stewart 		fapi_ffc->pps_info_buf_ffc = pps->ppsinfo_ffc;
164165e359a1SLawrence Stewart 		/* Overwrite timestamps if feedback clock selected. */
164265e359a1SLawrence Stewart 		switch (pps->ppsparam.mode & PPS_TSCLK_MASK) {
164365e359a1SLawrence Stewart 		case PPS_TSCLK_FBCK:
164465e359a1SLawrence Stewart 			fapi_ffc->pps_info_buf_ffc.assert_timestamp =
164565e359a1SLawrence Stewart 			    pps->ppsinfo.assert_timestamp;
164665e359a1SLawrence Stewart 			fapi_ffc->pps_info_buf_ffc.clear_timestamp =
164765e359a1SLawrence Stewart 			    pps->ppsinfo.clear_timestamp;
164865e359a1SLawrence Stewart 			break;
164965e359a1SLawrence Stewart 		case PPS_TSCLK_FFWD:
165065e359a1SLawrence Stewart 			break;
165165e359a1SLawrence Stewart 		default:
165265e359a1SLawrence Stewart 			break;
165365e359a1SLawrence Stewart 		}
165465e359a1SLawrence Stewart 		return (0);
165565e359a1SLawrence Stewart #endif /* FFCLOCK */
1656b7424f2dSJohn Hay 	case PPS_IOC_KCBIND:
1657b7424f2dSJohn Hay #ifdef PPS_SYNC
1658b7424f2dSJohn Hay 		kapi = (struct pps_kcbind_args *)data;
1659b7424f2dSJohn Hay 		/* XXX Only root should be able to do this */
1660b7424f2dSJohn Hay 		if (kapi->tsformat && kapi->tsformat != PPS_TSFMT_TSPEC)
1661b7424f2dSJohn Hay 			return (EINVAL);
1662b7424f2dSJohn Hay 		if (kapi->kernel_consumer != PPS_KC_HARDPPS)
1663b7424f2dSJohn Hay 			return (EINVAL);
1664b7424f2dSJohn Hay 		if (kapi->edge & ~pps->ppscap)
1665b7424f2dSJohn Hay 			return (EINVAL);
166628315e27SIan Lepore 		pps->kcmode = (kapi->edge & KCMODE_EDGEMASK) |
166728315e27SIan Lepore 		    (pps->kcmode & KCMODE_ABIFLAG);
1668b7424f2dSJohn Hay 		return (0);
1669b7424f2dSJohn Hay #else
1670b7424f2dSJohn Hay 		return (EOPNOTSUPP);
1671b7424f2dSJohn Hay #endif
167232c20357SPoul-Henning Kamp 	default:
1673f8385624SPoul-Henning Kamp 		return (ENOIOCTL);
167432c20357SPoul-Henning Kamp 	}
167532c20357SPoul-Henning Kamp }
167632c20357SPoul-Henning Kamp 
167732c20357SPoul-Henning Kamp void
167832c20357SPoul-Henning Kamp pps_init(struct pps_state *pps)
167932c20357SPoul-Henning Kamp {
1680a1137de9SIan Lepore 	pps->ppscap |= PPS_TSFMT_TSPEC | PPS_CANWAIT;
168132c20357SPoul-Henning Kamp 	if (pps->ppscap & PPS_CAPTUREASSERT)
168232c20357SPoul-Henning Kamp 		pps->ppscap |= PPS_OFFSETASSERT;
168332c20357SPoul-Henning Kamp 	if (pps->ppscap & PPS_CAPTURECLEAR)
168432c20357SPoul-Henning Kamp 		pps->ppscap |= PPS_OFFSETCLEAR;
168565e359a1SLawrence Stewart #ifdef FFCLOCK
168665e359a1SLawrence Stewart 	pps->ppscap |= PPS_TSCLK_MASK;
168765e359a1SLawrence Stewart #endif
168828315e27SIan Lepore 	pps->kcmode &= ~KCMODE_ABIFLAG;
168928315e27SIan Lepore }
169028315e27SIan Lepore 
169128315e27SIan Lepore void
169228315e27SIan Lepore pps_init_abi(struct pps_state *pps)
169328315e27SIan Lepore {
169428315e27SIan Lepore 
169528315e27SIan Lepore 	pps_init(pps);
169628315e27SIan Lepore 	if (pps->driver_abi > 0) {
169728315e27SIan Lepore 		pps->kcmode |= KCMODE_ABIFLAG;
169828315e27SIan Lepore 		pps->kernel_abi = PPS_ABI_VERSION;
169928315e27SIan Lepore 	}
170032c20357SPoul-Henning Kamp }
170132c20357SPoul-Henning Kamp 
170232c20357SPoul-Henning Kamp void
17037bf758bfSPoul-Henning Kamp pps_capture(struct pps_state *pps)
17047bf758bfSPoul-Henning Kamp {
17056b00cf46SPoul-Henning Kamp 	struct timehands *th;
17067bf758bfSPoul-Henning Kamp 
1707d8e8b675SPoul-Henning Kamp 	KASSERT(pps != NULL, ("NULL pps pointer in pps_capture"));
17086b00cf46SPoul-Henning Kamp 	th = timehands;
1709f4b5a972SKonstantin Belousov 	pps->capgen = atomic_load_acq_int(&th->th_generation);
17106b00cf46SPoul-Henning Kamp 	pps->capth = th;
171165e359a1SLawrence Stewart #ifdef FFCLOCK
171265e359a1SLawrence Stewart 	pps->capffth = fftimehands;
171365e359a1SLawrence Stewart #endif
17146b00cf46SPoul-Henning Kamp 	pps->capcount = th->th_counter->tc_get_timecount(th->th_counter);
1715f4b5a972SKonstantin Belousov 	atomic_thread_fence_acq();
1716f4b5a972SKonstantin Belousov 	if (pps->capgen != th->th_generation)
17176b00cf46SPoul-Henning Kamp 		pps->capgen = 0;
17187bf758bfSPoul-Henning Kamp }
17197bf758bfSPoul-Henning Kamp 
17207bf758bfSPoul-Henning Kamp void
17217bf758bfSPoul-Henning Kamp pps_event(struct pps_state *pps, int event)
172232c20357SPoul-Henning Kamp {
172339acc78aSPoul-Henning Kamp 	struct bintime bt;
172432c20357SPoul-Henning Kamp 	struct timespec ts, *tsp, *osp;
17256b00cf46SPoul-Henning Kamp 	u_int tcount, *pcount;
1726aaca7045SEnji Cooper 	int foff;
172732c20357SPoul-Henning Kamp 	pps_seq_t *pseq;
172865e359a1SLawrence Stewart #ifdef FFCLOCK
172965e359a1SLawrence Stewart 	struct timespec *tsp_ffc;
173065e359a1SLawrence Stewart 	pps_seq_t *pseq_ffc;
173165e359a1SLawrence Stewart 	ffcounter *ffcount;
173265e359a1SLawrence Stewart #endif
1733aaca7045SEnji Cooper #ifdef PPS_SYNC
1734aaca7045SEnji Cooper 	int fhard;
1735aaca7045SEnji Cooper #endif
173632c20357SPoul-Henning Kamp 
1737d8e8b675SPoul-Henning Kamp 	KASSERT(pps != NULL, ("NULL pps pointer in pps_event"));
1738721b5817SIan Lepore 	/* Nothing to do if not currently set to capture this event type. */
1739721b5817SIan Lepore 	if ((event & pps->ppsparam.mode) == 0)
1740721b5817SIan Lepore 		return;
174139acc78aSPoul-Henning Kamp 	/* If the timecounter was wound up underneath us, bail out. */
1742f4b5a972SKonstantin Belousov 	if (pps->capgen == 0 || pps->capgen !=
1743f4b5a972SKonstantin Belousov 	    atomic_load_acq_int(&pps->capth->th_generation))
17447bf758bfSPoul-Henning Kamp 		return;
17457bf758bfSPoul-Henning Kamp 
174639acc78aSPoul-Henning Kamp 	/* Things would be easier with arrays. */
174732c20357SPoul-Henning Kamp 	if (event == PPS_CAPTUREASSERT) {
174832c20357SPoul-Henning Kamp 		tsp = &pps->ppsinfo.assert_timestamp;
174932c20357SPoul-Henning Kamp 		osp = &pps->ppsparam.assert_offset;
175032c20357SPoul-Henning Kamp 		foff = pps->ppsparam.mode & PPS_OFFSETASSERT;
1751aaca7045SEnji Cooper #ifdef PPS_SYNC
1752b7424f2dSJohn Hay 		fhard = pps->kcmode & PPS_CAPTUREASSERT;
1753aaca7045SEnji Cooper #endif
175432c20357SPoul-Henning Kamp 		pcount = &pps->ppscount[0];
175532c20357SPoul-Henning Kamp 		pseq = &pps->ppsinfo.assert_sequence;
175665e359a1SLawrence Stewart #ifdef FFCLOCK
175765e359a1SLawrence Stewart 		ffcount = &pps->ppsinfo_ffc.assert_ffcount;
175865e359a1SLawrence Stewart 		tsp_ffc = &pps->ppsinfo_ffc.assert_timestamp;
175965e359a1SLawrence Stewart 		pseq_ffc = &pps->ppsinfo_ffc.assert_sequence;
176065e359a1SLawrence Stewart #endif
176132c20357SPoul-Henning Kamp 	} else {
176232c20357SPoul-Henning Kamp 		tsp = &pps->ppsinfo.clear_timestamp;
176332c20357SPoul-Henning Kamp 		osp = &pps->ppsparam.clear_offset;
176432c20357SPoul-Henning Kamp 		foff = pps->ppsparam.mode & PPS_OFFSETCLEAR;
1765aaca7045SEnji Cooper #ifdef PPS_SYNC
1766b7424f2dSJohn Hay 		fhard = pps->kcmode & PPS_CAPTURECLEAR;
1767aaca7045SEnji Cooper #endif
176832c20357SPoul-Henning Kamp 		pcount = &pps->ppscount[1];
176932c20357SPoul-Henning Kamp 		pseq = &pps->ppsinfo.clear_sequence;
177065e359a1SLawrence Stewart #ifdef FFCLOCK
177165e359a1SLawrence Stewart 		ffcount = &pps->ppsinfo_ffc.clear_ffcount;
177265e359a1SLawrence Stewart 		tsp_ffc = &pps->ppsinfo_ffc.clear_timestamp;
177365e359a1SLawrence Stewart 		pseq_ffc = &pps->ppsinfo_ffc.clear_sequence;
177465e359a1SLawrence Stewart #endif
177532c20357SPoul-Henning Kamp 	}
177632c20357SPoul-Henning Kamp 
177739acc78aSPoul-Henning Kamp 	/*
17786b00cf46SPoul-Henning Kamp 	 * If the timecounter changed, we cannot compare the count values, so
17796b00cf46SPoul-Henning Kamp 	 * we have to drop the rest of the PPS-stuff until the next event.
17806b00cf46SPoul-Henning Kamp 	 */
17816b00cf46SPoul-Henning Kamp 	if (pps->ppstc != pps->capth->th_counter) {
17826b00cf46SPoul-Henning Kamp 		pps->ppstc = pps->capth->th_counter;
17837bf758bfSPoul-Henning Kamp 		*pcount = pps->capcount;
17847bf758bfSPoul-Henning Kamp 		pps->ppscount[2] = pps->capcount;
178532c20357SPoul-Henning Kamp 		return;
178632c20357SPoul-Henning Kamp 	}
178732c20357SPoul-Henning Kamp 
178839acc78aSPoul-Henning Kamp 	/* Convert the count to a timespec. */
17896b00cf46SPoul-Henning Kamp 	tcount = pps->capcount - pps->capth->th_offset_count;
17906b00cf46SPoul-Henning Kamp 	tcount &= pps->capth->th_counter->tc_counter_mask;
179150c22263SKonstantin Belousov 	bt = pps->capth->th_bintime;
17926b00cf46SPoul-Henning Kamp 	bintime_addx(&bt, pps->capth->th_scale * tcount);
17932028c0cdSPoul-Henning Kamp 	bintime2timespec(&bt, &ts);
179432c20357SPoul-Henning Kamp 
179539acc78aSPoul-Henning Kamp 	/* If the timecounter was wound up underneath us, bail out. */
1796f4b5a972SKonstantin Belousov 	atomic_thread_fence_acq();
1797f4b5a972SKonstantin Belousov 	if (pps->capgen != pps->capth->th_generation)
17987bf758bfSPoul-Henning Kamp 		return;
17997bf758bfSPoul-Henning Kamp 
18007bf758bfSPoul-Henning Kamp 	*pcount = pps->capcount;
180132c20357SPoul-Henning Kamp 	(*pseq)++;
180232c20357SPoul-Henning Kamp 	*tsp = ts;
180332c20357SPoul-Henning Kamp 
180432c20357SPoul-Henning Kamp 	if (foff) {
18056040822cSAlan Somers 		timespecadd(tsp, osp, tsp);
180632c20357SPoul-Henning Kamp 		if (tsp->tv_nsec < 0) {
180732c20357SPoul-Henning Kamp 			tsp->tv_nsec += 1000000000;
180832c20357SPoul-Henning Kamp 			tsp->tv_sec -= 1;
180932c20357SPoul-Henning Kamp 		}
181032c20357SPoul-Henning Kamp 	}
181165e359a1SLawrence Stewart 
181265e359a1SLawrence Stewart #ifdef FFCLOCK
181365e359a1SLawrence Stewart 	*ffcount = pps->capffth->tick_ffcount + tcount;
181465e359a1SLawrence Stewart 	bt = pps->capffth->tick_time;
181565e359a1SLawrence Stewart 	ffclock_convert_delta(tcount, pps->capffth->cest.period, &bt);
181665e359a1SLawrence Stewart 	bintime_add(&bt, &pps->capffth->tick_time);
181765e359a1SLawrence Stewart 	bintime2timespec(&bt, &ts);
181865e359a1SLawrence Stewart 	(*pseq_ffc)++;
181965e359a1SLawrence Stewart 	*tsp_ffc = ts;
182065e359a1SLawrence Stewart #endif
182165e359a1SLawrence Stewart 
182232c20357SPoul-Henning Kamp #ifdef PPS_SYNC
182332c20357SPoul-Henning Kamp 	if (fhard) {
182460ae52f7SEd Schouten 		uint64_t scale;
1825ce9fac00SPoul-Henning Kamp 
182639acc78aSPoul-Henning Kamp 		/*
18276b00cf46SPoul-Henning Kamp 		 * Feed the NTP PLL/FLL.
1828b1e7e201SJohn Hay 		 * The FLL wants to know how many (hardware) nanoseconds
1829b1e7e201SJohn Hay 		 * elapsed since the previous event.
18306b00cf46SPoul-Henning Kamp 		 */
18317bf758bfSPoul-Henning Kamp 		tcount = pps->capcount - pps->ppscount[2];
18327bf758bfSPoul-Henning Kamp 		pps->ppscount[2] = pps->capcount;
18336b00cf46SPoul-Henning Kamp 		tcount &= pps->capth->th_counter->tc_counter_mask;
183460ae52f7SEd Schouten 		scale = (uint64_t)1 << 63;
1835b1e7e201SJohn Hay 		scale /= pps->capth->th_counter->tc_frequency;
1836b1e7e201SJohn Hay 		scale *= 2;
18372028c0cdSPoul-Henning Kamp 		bt.sec = 0;
18382028c0cdSPoul-Henning Kamp 		bt.frac = 0;
1839b1e7e201SJohn Hay 		bintime_addx(&bt, scale * tcount);
18402028c0cdSPoul-Henning Kamp 		bintime2timespec(&bt, &ts);
18412028c0cdSPoul-Henning Kamp 		hardpps(tsp, ts.tv_nsec + 1000000000 * ts.tv_sec);
184232c20357SPoul-Henning Kamp 	}
184332c20357SPoul-Henning Kamp #endif
1844a1137de9SIan Lepore 
1845a1137de9SIan Lepore 	/* Wakeup anyone sleeping in pps_fetch().  */
1846a1137de9SIan Lepore 	wakeup(pps);
184732c20357SPoul-Henning Kamp }
18489e1b5510SPoul-Henning Kamp 
184939acc78aSPoul-Henning Kamp /*
18509e1b5510SPoul-Henning Kamp  * Timecounters need to be updated every so often to prevent the hardware
18519e1b5510SPoul-Henning Kamp  * counter from overflowing.  Updating also recalculates the cached values
18529e1b5510SPoul-Henning Kamp  * used by the get*() family of functions, so their precision depends on
18539e1b5510SPoul-Henning Kamp  * the update frequency.
18549e1b5510SPoul-Henning Kamp  */
18559e1b5510SPoul-Henning Kamp 
18569e1b5510SPoul-Henning Kamp static int tc_tick;
1857b389be97SRebecca Cran SYSCTL_INT(_kern_timecounter, OID_AUTO, tick, CTLFLAG_RD, &tc_tick, 0,
1858b389be97SRebecca Cran     "Approximate number of hardclock ticks in a millisecond");
18599e1b5510SPoul-Henning Kamp 
1860e7fa55afSPoul-Henning Kamp void
18610e189873SAlexander Motin tc_ticktock(int cnt)
18629e1b5510SPoul-Henning Kamp {
1863e7fa55afSPoul-Henning Kamp 	static int count;
18649e1b5510SPoul-Henning Kamp 
18655760b029SKonstantin Belousov 	if (mtx_trylock_spin(&tc_setclock_mtx)) {
18660e189873SAlexander Motin 		count += cnt;
18675760b029SKonstantin Belousov 		if (count >= tc_tick) {
1868e7fa55afSPoul-Henning Kamp 			count = 0;
18695760b029SKonstantin Belousov 			tc_windup(NULL);
18705760b029SKonstantin Belousov 		}
18715760b029SKonstantin Belousov 		mtx_unlock_spin(&tc_setclock_mtx);
18725760b029SKonstantin Belousov 	}
18739e1b5510SPoul-Henning Kamp }
18749e1b5510SPoul-Henning Kamp 
18755b999a6bSDavide Italiano static void __inline
18765b999a6bSDavide Italiano tc_adjprecision(void)
18775b999a6bSDavide Italiano {
18785b999a6bSDavide Italiano 	int t;
18795b999a6bSDavide Italiano 
18805b999a6bSDavide Italiano 	if (tc_timepercentage > 0) {
18815b999a6bSDavide Italiano 		t = (99 + tc_timepercentage) / tc_timepercentage;
18825b999a6bSDavide Italiano 		tc_precexp = fls(t + (t >> 1)) - 1;
18835b999a6bSDavide Italiano 		FREQ2BT(hz / tc_tick, &bt_timethreshold);
18845b999a6bSDavide Italiano 		FREQ2BT(hz, &bt_tickthreshold);
18855b999a6bSDavide Italiano 		bintime_shift(&bt_timethreshold, tc_precexp);
18865b999a6bSDavide Italiano 		bintime_shift(&bt_tickthreshold, tc_precexp);
18875b999a6bSDavide Italiano 	} else {
18885b999a6bSDavide Italiano 		tc_precexp = 31;
18895b999a6bSDavide Italiano 		bt_timethreshold.sec = INT_MAX;
18905b999a6bSDavide Italiano 		bt_timethreshold.frac = ~(uint64_t)0;
18915b999a6bSDavide Italiano 		bt_tickthreshold = bt_timethreshold;
18925b999a6bSDavide Italiano 	}
18935b999a6bSDavide Italiano 	sbt_timethreshold = bttosbt(bt_timethreshold);
18945b999a6bSDavide Italiano 	sbt_tickthreshold = bttosbt(bt_tickthreshold);
18955b999a6bSDavide Italiano }
18965b999a6bSDavide Italiano 
18975b999a6bSDavide Italiano static int
18985b999a6bSDavide Italiano sysctl_kern_timecounter_adjprecision(SYSCTL_HANDLER_ARGS)
18995b999a6bSDavide Italiano {
19005b999a6bSDavide Italiano 	int error, val;
19015b999a6bSDavide Italiano 
19025b999a6bSDavide Italiano 	val = tc_timepercentage;
19035b999a6bSDavide Italiano 	error = sysctl_handle_int(oidp, &val, 0, req);
19045b999a6bSDavide Italiano 	if (error != 0 || req->newptr == NULL)
19055b999a6bSDavide Italiano 		return (error);
19065b999a6bSDavide Italiano 	tc_timepercentage = val;
1907af3b2549SHans Petter Selasky 	if (cold)
1908af3b2549SHans Petter Selasky 		goto done;
19095b999a6bSDavide Italiano 	tc_adjprecision();
1910af3b2549SHans Petter Selasky done:
19115b999a6bSDavide Italiano 	return (0);
19125b999a6bSDavide Italiano }
19135b999a6bSDavide Italiano 
19146c46ce7eSKonstantin Belousov /* Set up the requested number of timehands. */
19156c46ce7eSKonstantin Belousov static void
19166c46ce7eSKonstantin Belousov inittimehands(void *dummy)
19176c46ce7eSKonstantin Belousov {
19186c46ce7eSKonstantin Belousov 	struct timehands *thp;
19196c46ce7eSKonstantin Belousov 	int i;
19206c46ce7eSKonstantin Belousov 
19216c46ce7eSKonstantin Belousov 	TUNABLE_INT_FETCH("kern.timecounter.timehands_count",
19226c46ce7eSKonstantin Belousov 	    &timehands_count);
19236c46ce7eSKonstantin Belousov 	if (timehands_count < 1)
19246c46ce7eSKonstantin Belousov 		timehands_count = 1;
19256c46ce7eSKonstantin Belousov 	if (timehands_count > nitems(ths))
19266c46ce7eSKonstantin Belousov 		timehands_count = nitems(ths);
19276c46ce7eSKonstantin Belousov 	for (i = 1, thp = &ths[0]; i < timehands_count;  thp = &ths[i++])
19286c46ce7eSKonstantin Belousov 		thp->th_next = &ths[i];
19296c46ce7eSKonstantin Belousov 	thp->th_next = &ths[0];
19306c46ce7eSKonstantin Belousov }
19316c46ce7eSKonstantin Belousov SYSINIT(timehands, SI_SUB_TUNABLES, SI_ORDER_ANY, inittimehands, NULL);
19326c46ce7eSKonstantin Belousov 
19339e1b5510SPoul-Henning Kamp static void
19349e1b5510SPoul-Henning Kamp inittimecounter(void *dummy)
19359e1b5510SPoul-Henning Kamp {
19369e1b5510SPoul-Henning Kamp 	u_int p;
19376c46ce7eSKonstantin Belousov 	int tick_rate;
19389e1b5510SPoul-Henning Kamp 
193939acc78aSPoul-Henning Kamp 	/*
194039acc78aSPoul-Henning Kamp 	 * Set the initial timeout to
194139acc78aSPoul-Henning Kamp 	 * max(1, <approx. number of hardclock ticks in a millisecond>).
194239acc78aSPoul-Henning Kamp 	 * People should probably not use the sysctl to set the timeout
1943e3043798SPedro F. Giffuni 	 * to smaller than its initial value, since that value is the
194439acc78aSPoul-Henning Kamp 	 * smallest reasonable one.  If they want better timestamps they
194539acc78aSPoul-Henning Kamp 	 * should use the non-"get"* functions.
194639acc78aSPoul-Henning Kamp 	 */
19479e1b5510SPoul-Henning Kamp 	if (hz > 1000)
19489e1b5510SPoul-Henning Kamp 		tc_tick = (hz + 500) / 1000;
19499e1b5510SPoul-Henning Kamp 	else
19509e1b5510SPoul-Henning Kamp 		tc_tick = 1;
19515b999a6bSDavide Italiano 	tc_adjprecision();
19525b999a6bSDavide Italiano 	FREQ2BT(hz, &tick_bt);
19535b999a6bSDavide Italiano 	tick_sbt = bttosbt(tick_bt);
19545b999a6bSDavide Italiano 	tick_rate = hz / tc_tick;
19555b999a6bSDavide Italiano 	FREQ2BT(tick_rate, &tc_tick_bt);
19565b999a6bSDavide Italiano 	tc_tick_sbt = bttosbt(tc_tick_bt);
19579e1b5510SPoul-Henning Kamp 	p = (tc_tick * 1000000) / hz;
19589e1b5510SPoul-Henning Kamp 	printf("Timecounters tick every %d.%03u msec\n", p / 1000, p % 1000);
195939acc78aSPoul-Henning Kamp 
1960b0fdc837SLawrence Stewart #ifdef FFCLOCK
1961b0fdc837SLawrence Stewart 	ffclock_init();
1962b0fdc837SLawrence Stewart #endif
19634b23dec4SKonstantin Belousov 
196448e5da55SPoul-Henning Kamp 	/* warm up new timecounter (again) and get rolling. */
196539acc78aSPoul-Henning Kamp 	(void)timecounter->tc_get_timecount(timecounter);
196639acc78aSPoul-Henning Kamp 	(void)timecounter->tc_get_timecount(timecounter);
19675760b029SKonstantin Belousov 	mtx_lock_spin(&tc_setclock_mtx);
19685760b029SKonstantin Belousov 	tc_windup(NULL);
19695760b029SKonstantin Belousov 	mtx_unlock_spin(&tc_setclock_mtx);
19709e1b5510SPoul-Henning Kamp }
19719e1b5510SPoul-Henning Kamp 
1972237fdd78SRobert Watson SYSINIT(timecounter, SI_SUB_CLOCKS, SI_ORDER_SECOND, inittimecounter, NULL);
19735b1a8eb3SPoul-Henning Kamp 
1974e8444a7eSPoul-Henning Kamp /* Cpu tick handling -------------------------------------------------*/
1975e8444a7eSPoul-Henning Kamp 
1976e8444a7eSPoul-Henning Kamp static int cpu_tick_variable;
1977e8444a7eSPoul-Henning Kamp static uint64_t	cpu_tick_frequency;
1978e8444a7eSPoul-Henning Kamp 
19792bf95012SAndrew Turner DPCPU_DEFINE_STATIC(uint64_t, tc_cpu_ticks_base);
19802bf95012SAndrew Turner DPCPU_DEFINE_STATIC(unsigned, tc_cpu_ticks_last);
1981b2557db6SKonstantin Belousov 
198288ca07e7SJohn Baldwin static uint64_t
19835b1a8eb3SPoul-Henning Kamp tc_cpu_ticks(void)
19845b1a8eb3SPoul-Henning Kamp {
19855b1a8eb3SPoul-Henning Kamp 	struct timecounter *tc;
1986b2557db6SKonstantin Belousov 	uint64_t res, *base;
1987b2557db6SKonstantin Belousov 	unsigned u, *last;
19885b1a8eb3SPoul-Henning Kamp 
1989b2557db6SKonstantin Belousov 	critical_enter();
1990b2557db6SKonstantin Belousov 	base = DPCPU_PTR(tc_cpu_ticks_base);
1991b2557db6SKonstantin Belousov 	last = DPCPU_PTR(tc_cpu_ticks_last);
19925b1a8eb3SPoul-Henning Kamp 	tc = timehands->th_counter;
19935b1a8eb3SPoul-Henning Kamp 	u = tc->tc_get_timecount(tc) & tc->tc_counter_mask;
1994b2557db6SKonstantin Belousov 	if (u < *last)
1995b2557db6SKonstantin Belousov 		*base += (uint64_t)tc->tc_counter_mask + 1;
1996b2557db6SKonstantin Belousov 	*last = u;
1997b2557db6SKonstantin Belousov 	res = u + *base;
1998b2557db6SKonstantin Belousov 	critical_exit();
1999b2557db6SKonstantin Belousov 	return (res);
20005b1a8eb3SPoul-Henning Kamp }
20015b1a8eb3SPoul-Henning Kamp 
2002a157e425SAlexander Motin void
2003a157e425SAlexander Motin cpu_tick_calibration(void)
2004a157e425SAlexander Motin {
2005a157e425SAlexander Motin 	static time_t last_calib;
2006a157e425SAlexander Motin 
2007a157e425SAlexander Motin 	if (time_uptime != last_calib && !(time_uptime & 0xf)) {
2008a157e425SAlexander Motin 		cpu_tick_calibrate(0);
2009a157e425SAlexander Motin 		last_calib = time_uptime;
2010a157e425SAlexander Motin 	}
2011a157e425SAlexander Motin }
2012a157e425SAlexander Motin 
2013e8444a7eSPoul-Henning Kamp /*
20146b4d690cSWarner Losh  * This function gets called every 16 seconds on only one designated
2015a157e425SAlexander Motin  * CPU in the system from hardclock() via cpu_tick_calibration()().
2016e8444a7eSPoul-Henning Kamp  *
2017e8444a7eSPoul-Henning Kamp  * Whenever the real time clock is stepped we get called with reset=1
2018e8444a7eSPoul-Henning Kamp  * to make sure we handle suspend/resume and similar events correctly.
2019e8444a7eSPoul-Henning Kamp  */
2020e8444a7eSPoul-Henning Kamp 
2021e8444a7eSPoul-Henning Kamp static void
2022e8444a7eSPoul-Henning Kamp cpu_tick_calibrate(int reset)
2023e8444a7eSPoul-Henning Kamp {
2024e8444a7eSPoul-Henning Kamp 	static uint64_t c_last;
2025e8444a7eSPoul-Henning Kamp 	uint64_t c_this, c_delta;
2026e8444a7eSPoul-Henning Kamp 	static struct bintime  t_last;
2027e8444a7eSPoul-Henning Kamp 	struct bintime t_this, t_delta;
2028301af28aSPoul-Henning Kamp 	uint32_t divi;
2029e8444a7eSPoul-Henning Kamp 
2030e8444a7eSPoul-Henning Kamp 	if (reset) {
2031e8444a7eSPoul-Henning Kamp 		/* The clock was stepped, abort & reset */
2032e8444a7eSPoul-Henning Kamp 		t_last.sec = 0;
2033e8444a7eSPoul-Henning Kamp 		return;
2034e8444a7eSPoul-Henning Kamp 	}
2035e8444a7eSPoul-Henning Kamp 
2036e8444a7eSPoul-Henning Kamp 	/* we don't calibrate fixed rate cputicks */
2037e8444a7eSPoul-Henning Kamp 	if (!cpu_tick_variable)
2038e8444a7eSPoul-Henning Kamp 		return;
2039e8444a7eSPoul-Henning Kamp 
2040e8444a7eSPoul-Henning Kamp 	getbinuptime(&t_this);
2041e8444a7eSPoul-Henning Kamp 	c_this = cpu_ticks();
2042e8444a7eSPoul-Henning Kamp 	if (t_last.sec != 0) {
2043e8444a7eSPoul-Henning Kamp 		c_delta = c_this - c_last;
2044e8444a7eSPoul-Henning Kamp 		t_delta = t_this;
2045e8444a7eSPoul-Henning Kamp 		bintime_sub(&t_delta, &t_last);
2046e8444a7eSPoul-Henning Kamp 		/*
2047301af28aSPoul-Henning Kamp 		 * Headroom:
2048301af28aSPoul-Henning Kamp 		 * 	2^(64-20) / 16[s] =
2049301af28aSPoul-Henning Kamp 		 * 	2^(44) / 16[s] =
2050301af28aSPoul-Henning Kamp 		 * 	17.592.186.044.416 / 16 =
2051301af28aSPoul-Henning Kamp 		 * 	1.099.511.627.776 [Hz]
2052301af28aSPoul-Henning Kamp 		 */
2053301af28aSPoul-Henning Kamp 		divi = t_delta.sec << 20;
2054301af28aSPoul-Henning Kamp 		divi |= t_delta.frac >> (64 - 20);
2055301af28aSPoul-Henning Kamp 		c_delta <<= 20;
2056301af28aSPoul-Henning Kamp 		c_delta /= divi;
2057e8444a7eSPoul-Henning Kamp 		if (c_delta > cpu_tick_frequency) {
205859048707SPoul-Henning Kamp 			if (0 && bootverbose)
2059fef527eeSPoul-Henning Kamp 				printf("cpu_tick increased to %ju Hz\n",
20606cda760fSPoul-Henning Kamp 				    c_delta);
2061e8444a7eSPoul-Henning Kamp 			cpu_tick_frequency = c_delta;
2062e8444a7eSPoul-Henning Kamp 		}
2063e8444a7eSPoul-Henning Kamp 	}
2064e8444a7eSPoul-Henning Kamp 	c_last = c_this;
2065e8444a7eSPoul-Henning Kamp 	t_last = t_this;
2066e8444a7eSPoul-Henning Kamp }
2067e8444a7eSPoul-Henning Kamp 
2068e8444a7eSPoul-Henning Kamp void
2069e8444a7eSPoul-Henning Kamp set_cputicker(cpu_tick_f *func, uint64_t freq, unsigned var)
2070e8444a7eSPoul-Henning Kamp {
2071e8444a7eSPoul-Henning Kamp 
2072e8444a7eSPoul-Henning Kamp 	if (func == NULL) {
2073e8444a7eSPoul-Henning Kamp 		cpu_ticks = tc_cpu_ticks;
2074e8444a7eSPoul-Henning Kamp 	} else {
2075e8444a7eSPoul-Henning Kamp 		cpu_tick_frequency = freq;
2076e8444a7eSPoul-Henning Kamp 		cpu_tick_variable = var;
2077e8444a7eSPoul-Henning Kamp 		cpu_ticks = func;
2078e8444a7eSPoul-Henning Kamp 	}
2079e8444a7eSPoul-Henning Kamp }
2080e8444a7eSPoul-Henning Kamp 
2081e8444a7eSPoul-Henning Kamp uint64_t
2082e8444a7eSPoul-Henning Kamp cpu_tickrate(void)
2083e8444a7eSPoul-Henning Kamp {
2084e8444a7eSPoul-Henning Kamp 
2085e8444a7eSPoul-Henning Kamp 	if (cpu_ticks == tc_cpu_ticks)
2086e8444a7eSPoul-Henning Kamp 		return (tc_getfrequency());
2087e8444a7eSPoul-Henning Kamp 	return (cpu_tick_frequency);
2088e8444a7eSPoul-Henning Kamp }
2089e8444a7eSPoul-Henning Kamp 
2090e8444a7eSPoul-Henning Kamp /*
2091e8444a7eSPoul-Henning Kamp  * We need to be slightly careful converting cputicks to microseconds.
2092e8444a7eSPoul-Henning Kamp  * There is plenty of margin in 64 bits of microseconds (half a million
2093e8444a7eSPoul-Henning Kamp  * years) and in 64 bits at 4 GHz (146 years), but if we do a multiply
2094e8444a7eSPoul-Henning Kamp  * before divide conversion (to retain precision) we find that the
2095e8444a7eSPoul-Henning Kamp  * margin shrinks to 1.5 hours (one millionth of 146y).
2096776fc0e9SYaroslav Tykhiy  * With a three prong approach we never lose significant bits, no
2097e8444a7eSPoul-Henning Kamp  * matter what the cputick rate and length of timeinterval is.
2098e8444a7eSPoul-Henning Kamp  */
2099e8444a7eSPoul-Henning Kamp 
2100e8444a7eSPoul-Henning Kamp uint64_t
2101e8444a7eSPoul-Henning Kamp cputick2usec(uint64_t tick)
2102e8444a7eSPoul-Henning Kamp {
2103e8444a7eSPoul-Henning Kamp 
2104e8444a7eSPoul-Henning Kamp 	if (tick > 18446744073709551LL)		/* floor(2^64 / 1000) */
2105e8444a7eSPoul-Henning Kamp 		return (tick / (cpu_tickrate() / 1000000LL));
2106e8444a7eSPoul-Henning Kamp 	else if (tick > 18446744073709LL)	/* floor(2^64 / 1000000) */
2107e8444a7eSPoul-Henning Kamp 		return ((tick * 1000LL) / (cpu_tickrate() / 1000LL));
2108e8444a7eSPoul-Henning Kamp 	else
2109e8444a7eSPoul-Henning Kamp 		return ((tick * 1000000LL) / cpu_tickrate());
2110e8444a7eSPoul-Henning Kamp }
2111e8444a7eSPoul-Henning Kamp 
2112e8444a7eSPoul-Henning Kamp cpu_tick_f	*cpu_ticks = tc_cpu_ticks;
2113aea81038SKonstantin Belousov 
2114aea81038SKonstantin Belousov static int vdso_th_enable = 1;
2115aea81038SKonstantin Belousov static int
2116aea81038SKonstantin Belousov sysctl_fast_gettime(SYSCTL_HANDLER_ARGS)
2117aea81038SKonstantin Belousov {
2118aea81038SKonstantin Belousov 	int old_vdso_th_enable, error;
2119aea81038SKonstantin Belousov 
2120aea81038SKonstantin Belousov 	old_vdso_th_enable = vdso_th_enable;
2121aea81038SKonstantin Belousov 	error = sysctl_handle_int(oidp, &old_vdso_th_enable, 0, req);
2122aea81038SKonstantin Belousov 	if (error != 0)
2123aea81038SKonstantin Belousov 		return (error);
2124aea81038SKonstantin Belousov 	vdso_th_enable = old_vdso_th_enable;
2125aea81038SKonstantin Belousov 	return (0);
2126aea81038SKonstantin Belousov }
2127aea81038SKonstantin Belousov SYSCTL_PROC(_kern_timecounter, OID_AUTO, fast_gettime,
2128aea81038SKonstantin Belousov     CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE,
2129aea81038SKonstantin Belousov     NULL, 0, sysctl_fast_gettime, "I", "Enable fast time of day");
2130aea81038SKonstantin Belousov 
2131aea81038SKonstantin Belousov uint32_t
2132aea81038SKonstantin Belousov tc_fill_vdso_timehands(struct vdso_timehands *vdso_th)
2133aea81038SKonstantin Belousov {
2134aea81038SKonstantin Belousov 	struct timehands *th;
2135aea81038SKonstantin Belousov 	uint32_t enabled;
2136aea81038SKonstantin Belousov 
2137aea81038SKonstantin Belousov 	th = timehands;
2138aea81038SKonstantin Belousov 	vdso_th->th_scale = th->th_scale;
2139aea81038SKonstantin Belousov 	vdso_th->th_offset_count = th->th_offset_count;
2140aea81038SKonstantin Belousov 	vdso_th->th_counter_mask = th->th_counter->tc_counter_mask;
2141aea81038SKonstantin Belousov 	vdso_th->th_offset = th->th_offset;
21425760b029SKonstantin Belousov 	vdso_th->th_boottime = th->th_boottime;
214316808549SKonstantin Belousov 	if (th->th_counter->tc_fill_vdso_timehands != NULL) {
214416808549SKonstantin Belousov 		enabled = th->th_counter->tc_fill_vdso_timehands(vdso_th,
214516808549SKonstantin Belousov 		    th->th_counter);
214616808549SKonstantin Belousov 	} else
214716808549SKonstantin Belousov 		enabled = 0;
2148aea81038SKonstantin Belousov 	if (!vdso_th_enable)
2149aea81038SKonstantin Belousov 		enabled = 0;
2150aea81038SKonstantin Belousov 	return (enabled);
2151aea81038SKonstantin Belousov }
2152aea81038SKonstantin Belousov 
2153aea81038SKonstantin Belousov #ifdef COMPAT_FREEBSD32
2154aea81038SKonstantin Belousov uint32_t
2155aea81038SKonstantin Belousov tc_fill_vdso_timehands32(struct vdso_timehands32 *vdso_th32)
2156aea81038SKonstantin Belousov {
2157aea81038SKonstantin Belousov 	struct timehands *th;
2158aea81038SKonstantin Belousov 	uint32_t enabled;
2159aea81038SKonstantin Belousov 
2160aea81038SKonstantin Belousov 	th = timehands;
2161aea81038SKonstantin Belousov 	*(uint64_t *)&vdso_th32->th_scale[0] = th->th_scale;
2162aea81038SKonstantin Belousov 	vdso_th32->th_offset_count = th->th_offset_count;
2163aea81038SKonstantin Belousov 	vdso_th32->th_counter_mask = th->th_counter->tc_counter_mask;
2164aea81038SKonstantin Belousov 	vdso_th32->th_offset.sec = th->th_offset.sec;
2165aea81038SKonstantin Belousov 	*(uint64_t *)&vdso_th32->th_offset.frac[0] = th->th_offset.frac;
21665760b029SKonstantin Belousov 	vdso_th32->th_boottime.sec = th->th_boottime.sec;
21675760b029SKonstantin Belousov 	*(uint64_t *)&vdso_th32->th_boottime.frac[0] = th->th_boottime.frac;
216816808549SKonstantin Belousov 	if (th->th_counter->tc_fill_vdso_timehands32 != NULL) {
216916808549SKonstantin Belousov 		enabled = th->th_counter->tc_fill_vdso_timehands32(vdso_th32,
217016808549SKonstantin Belousov 		    th->th_counter);
217116808549SKonstantin Belousov 	} else
217216808549SKonstantin Belousov 		enabled = 0;
2173aea81038SKonstantin Belousov 	if (!vdso_th_enable)
2174aea81038SKonstantin Belousov 		enabled = 0;
2175aea81038SKonstantin Belousov 	return (enabled);
2176aea81038SKonstantin Belousov }
2177aea81038SKonstantin Belousov #endif
2178