139acc78aSPoul-Henning Kamp /*- 291266b96SPoul-Henning Kamp * ---------------------------------------------------------------------------- 391266b96SPoul-Henning Kamp * "THE BEER-WARE LICENSE" (Revision 42): 491266b96SPoul-Henning Kamp * <phk@FreeBSD.ORG> wrote this file. As long as you retain this notice you 591266b96SPoul-Henning Kamp * can do whatever you want with this stuff. If we meet some day, and you think 691266b96SPoul-Henning Kamp * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp 791266b96SPoul-Henning Kamp * ---------------------------------------------------------------------------- 8df8bae1dSRodney W. Grimes */ 9df8bae1dSRodney W. Grimes 10677b542eSDavid E. O'Brien #include <sys/cdefs.h> 11677b542eSDavid E. O'Brien __FBSDID("$FreeBSD$"); 12677b542eSDavid E. O'Brien 1332c20357SPoul-Henning Kamp #include "opt_ntp.h" 1432c20357SPoul-Henning Kamp 15df8bae1dSRodney W. Grimes #include <sys/param.h> 1691266b96SPoul-Henning Kamp #include <sys/kernel.h> 1791266b96SPoul-Henning Kamp #include <sys/sysctl.h> 184e74721cSPoul-Henning Kamp #include <sys/syslog.h> 1991266b96SPoul-Henning Kamp #include <sys/systm.h> 2032c20357SPoul-Henning Kamp #include <sys/timepps.h> 2148e5da55SPoul-Henning Kamp #include <sys/timetc.h> 2239acc78aSPoul-Henning Kamp #include <sys/timex.h> 2339acc78aSPoul-Henning Kamp 243bac064fSPoul-Henning Kamp /* 25c1cccd1eSWarner Losh * A large step happens on boot. This constant detects such steps. 26c1cccd1eSWarner Losh * It is relatively small so that ntp_update_second gets called enough 27c1cccd1eSWarner Losh * in the typical 'missed a couple of seconds' case, but doesn't loop 28c1cccd1eSWarner Losh * forever when the time step is large. 294f2073fbSWarner Losh */ 304f2073fbSWarner Losh #define LARGE_STEP 200 314f2073fbSWarner Losh 324f2073fbSWarner Losh /* 3362efba6aSPoul-Henning Kamp * Implement a dummy timecounter which we can use until we get a real one 3462efba6aSPoul-Henning Kamp * in the air. This allows the console and other early stuff to use 3562efba6aSPoul-Henning Kamp * time services. 363bac064fSPoul-Henning Kamp */ 373bac064fSPoul-Henning Kamp 386b00cf46SPoul-Henning Kamp static u_int 3962efba6aSPoul-Henning Kamp dummy_get_timecount(struct timecounter *tc) 4062efba6aSPoul-Henning Kamp { 416b00cf46SPoul-Henning Kamp static u_int now; 4262efba6aSPoul-Henning Kamp 4362efba6aSPoul-Henning Kamp return (++now); 4462efba6aSPoul-Henning Kamp } 4562efba6aSPoul-Henning Kamp 4662efba6aSPoul-Henning Kamp static struct timecounter dummy_timecounter = { 4778a49a45SPoul-Henning Kamp dummy_get_timecount, 0, ~0u, 1000000, "dummy", -1000000 4862efba6aSPoul-Henning Kamp }; 4962efba6aSPoul-Henning Kamp 5062efba6aSPoul-Henning Kamp struct timehands { 5162efba6aSPoul-Henning Kamp /* These fields must be initialized by the driver. */ 526b00cf46SPoul-Henning Kamp struct timecounter *th_counter; 536b00cf46SPoul-Henning Kamp int64_t th_adjustment; 546b00cf46SPoul-Henning Kamp u_int64_t th_scale; 556b00cf46SPoul-Henning Kamp u_int th_offset_count; 566b00cf46SPoul-Henning Kamp struct bintime th_offset; 576b00cf46SPoul-Henning Kamp struct timeval th_microtime; 586b00cf46SPoul-Henning Kamp struct timespec th_nanotime; 5939acc78aSPoul-Henning Kamp /* Fields not to be copied in tc_windup start with th_generation. */ 606b00cf46SPoul-Henning Kamp volatile u_int th_generation; 616b00cf46SPoul-Henning Kamp struct timehands *th_next; 6262efba6aSPoul-Henning Kamp }; 6362efba6aSPoul-Henning Kamp 645b1c0294SDavid E. O'Brien static struct timehands th0; 6539acc78aSPoul-Henning Kamp static struct timehands th9 = { NULL, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0, &th0}; 6639acc78aSPoul-Henning Kamp static struct timehands th8 = { NULL, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0, &th9}; 6739acc78aSPoul-Henning Kamp static struct timehands th7 = { NULL, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0, &th8}; 6839acc78aSPoul-Henning Kamp static struct timehands th6 = { NULL, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0, &th7}; 6939acc78aSPoul-Henning Kamp static struct timehands th5 = { NULL, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0, &th6}; 7039acc78aSPoul-Henning Kamp static struct timehands th4 = { NULL, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0, &th5}; 7139acc78aSPoul-Henning Kamp static struct timehands th3 = { NULL, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0, &th4}; 7239acc78aSPoul-Henning Kamp static struct timehands th2 = { NULL, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0, &th3}; 7339acc78aSPoul-Henning Kamp static struct timehands th1 = { NULL, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0, &th2}; 74f5d157fbSPoul-Henning Kamp static struct timehands th0 = { 75f5d157fbSPoul-Henning Kamp &dummy_timecounter, 76f5d157fbSPoul-Henning Kamp 0, 7739acc78aSPoul-Henning Kamp (uint64_t)-1 / 1000000, 78f5d157fbSPoul-Henning Kamp 0, 79d25917e8SPoul-Henning Kamp {1, 0}, 80f5d157fbSPoul-Henning Kamp {0, 0}, 81f5d157fbSPoul-Henning Kamp {0, 0}, 82f5d157fbSPoul-Henning Kamp 1, 83f5d157fbSPoul-Henning Kamp &th1 84f5d157fbSPoul-Henning Kamp }; 8562efba6aSPoul-Henning Kamp 8662efba6aSPoul-Henning Kamp static struct timehands *volatile timehands = &th0; 8762efba6aSPoul-Henning Kamp struct timecounter *timecounter = &dummy_timecounter; 8862efba6aSPoul-Henning Kamp static struct timecounter *timecounters = &dummy_timecounter; 893bac064fSPoul-Henning Kamp 9048e5da55SPoul-Henning Kamp time_t time_second = 1; 91e452573dSAndre Oppermann time_t time_uptime = 1; 92227ee8a1SPoul-Henning Kamp 9339acc78aSPoul-Henning Kamp static struct bintime boottimebin; 9437d38777SBruce Evans struct timeval boottime; 95a7bc3102SPeter Wemm static int sysctl_kern_boottime(SYSCTL_HANDLER_ARGS); 96a7bc3102SPeter Wemm SYSCTL_PROC(_kern, KERN_BOOTTIME, boottime, CTLTYPE_STRUCT|CTLFLAG_RD, 97a7bc3102SPeter Wemm NULL, 0, sysctl_kern_boottime, "S,timeval", "System boottime"); 9837d38777SBruce Evans 9991266b96SPoul-Henning Kamp SYSCTL_NODE(_kern, OID_AUTO, timecounter, CTLFLAG_RW, 0, ""); 10091266b96SPoul-Henning Kamp 1014e74721cSPoul-Henning Kamp static int timestepwarnings; 1024e74721cSPoul-Henning Kamp SYSCTL_INT(_kern_timecounter, OID_AUTO, stepwarnings, CTLFLAG_RW, 1034e74721cSPoul-Henning Kamp ×tepwarnings, 0, ""); 1044e74721cSPoul-Henning Kamp 105056abcabSPoul-Henning Kamp #define TC_STATS(foo) \ 1066b00cf46SPoul-Henning Kamp static u_int foo; \ 1074f8cb019SMark Murray SYSCTL_UINT(_kern_timecounter, OID_AUTO, foo, CTLFLAG_RD, &foo, 0, "");\ 10839acc78aSPoul-Henning Kamp struct __hack 109056abcabSPoul-Henning Kamp 110056abcabSPoul-Henning Kamp TC_STATS(nbinuptime); TC_STATS(nnanouptime); TC_STATS(nmicrouptime); 111056abcabSPoul-Henning Kamp TC_STATS(nbintime); TC_STATS(nnanotime); TC_STATS(nmicrotime); 112056abcabSPoul-Henning Kamp TC_STATS(ngetbinuptime); TC_STATS(ngetnanouptime); TC_STATS(ngetmicrouptime); 113056abcabSPoul-Henning Kamp TC_STATS(ngetbintime); TC_STATS(ngetnanotime); TC_STATS(ngetmicrotime); 1144394f476SPoul-Henning Kamp TC_STATS(nsetclock); 115056abcabSPoul-Henning Kamp 116056abcabSPoul-Henning Kamp #undef TC_STATS 117510eb5b9SPoul-Henning Kamp 1189e1b5510SPoul-Henning Kamp static void tc_windup(void); 119e8444a7eSPoul-Henning Kamp static void cpu_tick_calibrate(int); 1209e1b5510SPoul-Henning Kamp 121a7bc3102SPeter Wemm static int 122a7bc3102SPeter Wemm sysctl_kern_boottime(SYSCTL_HANDLER_ARGS) 123a7bc3102SPeter Wemm { 124a7bc3102SPeter Wemm #ifdef SCTL_MASK32 125a7bc3102SPeter Wemm int tv[2]; 126a7bc3102SPeter Wemm 127a7bc3102SPeter Wemm if (req->flags & SCTL_MASK32) { 128a7bc3102SPeter Wemm tv[0] = boottime.tv_sec; 129a7bc3102SPeter Wemm tv[1] = boottime.tv_usec; 130a7bc3102SPeter Wemm return SYSCTL_OUT(req, tv, sizeof(tv)); 131a7bc3102SPeter Wemm } else 132a7bc3102SPeter Wemm #endif 133a7bc3102SPeter Wemm return SYSCTL_OUT(req, &boottime, sizeof(boottime)); 134a7bc3102SPeter Wemm } 1355b1a8eb3SPoul-Henning Kamp 13639acc78aSPoul-Henning Kamp /* 13739acc78aSPoul-Henning Kamp * Return the difference between the timehands' counter value now and what 13839acc78aSPoul-Henning Kamp * was when we copied it to the timehands' offset_count. 13939acc78aSPoul-Henning Kamp */ 1406b00cf46SPoul-Henning Kamp static __inline u_int 1416b00cf46SPoul-Henning Kamp tc_delta(struct timehands *th) 142e796e00dSPoul-Henning Kamp { 1436b00cf46SPoul-Henning Kamp struct timecounter *tc; 144e796e00dSPoul-Henning Kamp 1456b00cf46SPoul-Henning Kamp tc = th->th_counter; 1466b00cf46SPoul-Henning Kamp return ((tc->tc_get_timecount(tc) - th->th_offset_count) & 1476b00cf46SPoul-Henning Kamp tc->tc_counter_mask); 148e796e00dSPoul-Henning Kamp } 149a0502b19SPoul-Henning Kamp 15039acc78aSPoul-Henning Kamp /* 1516b00cf46SPoul-Henning Kamp * Functions for reading the time. We have to loop until we are sure that 15239acc78aSPoul-Henning Kamp * the timehands that we operated on was not updated under our feet. See 15339acc78aSPoul-Henning Kamp * the comment in <sys/time.h> for a description of these 12 functions. 1546b00cf46SPoul-Henning Kamp */ 1556b00cf46SPoul-Henning Kamp 156a0502b19SPoul-Henning Kamp void 1572028c0cdSPoul-Henning Kamp binuptime(struct bintime *bt) 1582028c0cdSPoul-Henning Kamp { 1596b00cf46SPoul-Henning Kamp struct timehands *th; 1606b00cf46SPoul-Henning Kamp u_int gen; 1612028c0cdSPoul-Henning Kamp 1625b7d8efaSPoul-Henning Kamp nbinuptime++; 1635b7d8efaSPoul-Henning Kamp do { 1646b00cf46SPoul-Henning Kamp th = timehands; 1656b00cf46SPoul-Henning Kamp gen = th->th_generation; 1666b00cf46SPoul-Henning Kamp *bt = th->th_offset; 1676b00cf46SPoul-Henning Kamp bintime_addx(bt, th->th_scale * tc_delta(th)); 1686b00cf46SPoul-Henning Kamp } while (gen == 0 || gen != th->th_generation); 1692028c0cdSPoul-Henning Kamp } 1702028c0cdSPoul-Henning Kamp 1712028c0cdSPoul-Henning Kamp void 17239acc78aSPoul-Henning Kamp nanouptime(struct timespec *tsp) 173056abcabSPoul-Henning Kamp { 174056abcabSPoul-Henning Kamp struct bintime bt; 175056abcabSPoul-Henning Kamp 176056abcabSPoul-Henning Kamp nnanouptime++; 177056abcabSPoul-Henning Kamp binuptime(&bt); 17839acc78aSPoul-Henning Kamp bintime2timespec(&bt, tsp); 179056abcabSPoul-Henning Kamp } 180056abcabSPoul-Henning Kamp 181056abcabSPoul-Henning Kamp void 18239acc78aSPoul-Henning Kamp microuptime(struct timeval *tvp) 183056abcabSPoul-Henning Kamp { 184056abcabSPoul-Henning Kamp struct bintime bt; 185056abcabSPoul-Henning Kamp 186056abcabSPoul-Henning Kamp nmicrouptime++; 187056abcabSPoul-Henning Kamp binuptime(&bt); 18839acc78aSPoul-Henning Kamp bintime2timeval(&bt, tvp); 189056abcabSPoul-Henning Kamp } 190056abcabSPoul-Henning Kamp 191056abcabSPoul-Henning Kamp void 1922028c0cdSPoul-Henning Kamp bintime(struct bintime *bt) 1932028c0cdSPoul-Henning Kamp { 1942028c0cdSPoul-Henning Kamp 1955b7d8efaSPoul-Henning Kamp nbintime++; 1962028c0cdSPoul-Henning Kamp binuptime(bt); 1972028c0cdSPoul-Henning Kamp bintime_add(bt, &boottimebin); 1982028c0cdSPoul-Henning Kamp } 1992028c0cdSPoul-Henning Kamp 2002028c0cdSPoul-Henning Kamp void 20139acc78aSPoul-Henning Kamp nanotime(struct timespec *tsp) 20200af9731SPoul-Henning Kamp { 2032028c0cdSPoul-Henning Kamp struct bintime bt; 20400af9731SPoul-Henning Kamp 20591266b96SPoul-Henning Kamp nnanotime++; 2062028c0cdSPoul-Henning Kamp bintime(&bt); 20739acc78aSPoul-Henning Kamp bintime2timespec(&bt, tsp); 20848115288SPoul-Henning Kamp } 20948115288SPoul-Henning Kamp 21048115288SPoul-Henning Kamp void 21139acc78aSPoul-Henning Kamp microtime(struct timeval *tvp) 212056abcabSPoul-Henning Kamp { 213056abcabSPoul-Henning Kamp struct bintime bt; 214056abcabSPoul-Henning Kamp 215056abcabSPoul-Henning Kamp nmicrotime++; 216056abcabSPoul-Henning Kamp bintime(&bt); 21739acc78aSPoul-Henning Kamp bintime2timeval(&bt, tvp); 218056abcabSPoul-Henning Kamp } 219056abcabSPoul-Henning Kamp 220056abcabSPoul-Henning Kamp void 221056abcabSPoul-Henning Kamp getbinuptime(struct bintime *bt) 22200af9731SPoul-Henning Kamp { 2236b00cf46SPoul-Henning Kamp struct timehands *th; 2246b00cf46SPoul-Henning Kamp u_int gen; 22500af9731SPoul-Henning Kamp 226056abcabSPoul-Henning Kamp ngetbinuptime++; 2275b7d8efaSPoul-Henning Kamp do { 2286b00cf46SPoul-Henning Kamp th = timehands; 2296b00cf46SPoul-Henning Kamp gen = th->th_generation; 2306b00cf46SPoul-Henning Kamp *bt = th->th_offset; 2316b00cf46SPoul-Henning Kamp } while (gen == 0 || gen != th->th_generation); 232a0502b19SPoul-Henning Kamp } 233a0502b19SPoul-Henning Kamp 234a0502b19SPoul-Henning Kamp void 235c21410e1SPoul-Henning Kamp getnanouptime(struct timespec *tsp) 236a0502b19SPoul-Henning Kamp { 2376b00cf46SPoul-Henning Kamp struct timehands *th; 2386b00cf46SPoul-Henning Kamp u_int gen; 239a0502b19SPoul-Henning Kamp 24091266b96SPoul-Henning Kamp ngetnanouptime++; 2415b7d8efaSPoul-Henning Kamp do { 2426b00cf46SPoul-Henning Kamp th = timehands; 2436b00cf46SPoul-Henning Kamp gen = th->th_generation; 2446b00cf46SPoul-Henning Kamp bintime2timespec(&th->th_offset, tsp); 2456b00cf46SPoul-Henning Kamp } while (gen == 0 || gen != th->th_generation); 246a0502b19SPoul-Henning Kamp } 247a0502b19SPoul-Henning Kamp 248c7c9a816SPoul-Henning Kamp void 249056abcabSPoul-Henning Kamp getmicrouptime(struct timeval *tvp) 250c7c9a816SPoul-Henning Kamp { 2516b00cf46SPoul-Henning Kamp struct timehands *th; 2526b00cf46SPoul-Henning Kamp u_int gen; 2537ec73f64SPoul-Henning Kamp 254056abcabSPoul-Henning Kamp ngetmicrouptime++; 255056abcabSPoul-Henning Kamp do { 2566b00cf46SPoul-Henning Kamp th = timehands; 2576b00cf46SPoul-Henning Kamp gen = th->th_generation; 2586b00cf46SPoul-Henning Kamp bintime2timeval(&th->th_offset, tvp); 2596b00cf46SPoul-Henning Kamp } while (gen == 0 || gen != th->th_generation); 2607ec73f64SPoul-Henning Kamp } 2617ec73f64SPoul-Henning Kamp 2627ec73f64SPoul-Henning Kamp void 263056abcabSPoul-Henning Kamp getbintime(struct bintime *bt) 2647ec73f64SPoul-Henning Kamp { 2656b00cf46SPoul-Henning Kamp struct timehands *th; 2666b00cf46SPoul-Henning Kamp u_int gen; 2677ec73f64SPoul-Henning Kamp 268056abcabSPoul-Henning Kamp ngetbintime++; 269056abcabSPoul-Henning Kamp do { 2706b00cf46SPoul-Henning Kamp th = timehands; 2716b00cf46SPoul-Henning Kamp gen = th->th_generation; 2726b00cf46SPoul-Henning Kamp *bt = th->th_offset; 2736b00cf46SPoul-Henning Kamp } while (gen == 0 || gen != th->th_generation); 274056abcabSPoul-Henning Kamp bintime_add(bt, &boottimebin); 275056abcabSPoul-Henning Kamp } 276056abcabSPoul-Henning Kamp 277056abcabSPoul-Henning Kamp void 278056abcabSPoul-Henning Kamp getnanotime(struct timespec *tsp) 279056abcabSPoul-Henning Kamp { 2806b00cf46SPoul-Henning Kamp struct timehands *th; 2816b00cf46SPoul-Henning Kamp u_int gen; 282056abcabSPoul-Henning Kamp 283056abcabSPoul-Henning Kamp ngetnanotime++; 284056abcabSPoul-Henning Kamp do { 2856b00cf46SPoul-Henning Kamp th = timehands; 2866b00cf46SPoul-Henning Kamp gen = th->th_generation; 2876b00cf46SPoul-Henning Kamp *tsp = th->th_nanotime; 2886b00cf46SPoul-Henning Kamp } while (gen == 0 || gen != th->th_generation); 289056abcabSPoul-Henning Kamp } 290056abcabSPoul-Henning Kamp 291056abcabSPoul-Henning Kamp void 292056abcabSPoul-Henning Kamp getmicrotime(struct timeval *tvp) 293056abcabSPoul-Henning Kamp { 2946b00cf46SPoul-Henning Kamp struct timehands *th; 2956b00cf46SPoul-Henning Kamp u_int gen; 296056abcabSPoul-Henning Kamp 297056abcabSPoul-Henning Kamp ngetmicrotime++; 298056abcabSPoul-Henning Kamp do { 2996b00cf46SPoul-Henning Kamp th = timehands; 3006b00cf46SPoul-Henning Kamp gen = th->th_generation; 3016b00cf46SPoul-Henning Kamp *tvp = th->th_microtime; 3026b00cf46SPoul-Henning Kamp } while (gen == 0 || gen != th->th_generation); 3037ec73f64SPoul-Henning Kamp } 3047ec73f64SPoul-Henning Kamp 30539acc78aSPoul-Henning Kamp /* 30678a49a45SPoul-Henning Kamp * Initialize a new timecounter and possibly use it. 3074e2befc0SPoul-Henning Kamp */ 3087ec73f64SPoul-Henning Kamp void 30991266b96SPoul-Henning Kamp tc_init(struct timecounter *tc) 3107ec73f64SPoul-Henning Kamp { 311555a5de2SPoul-Henning Kamp u_int u; 3127ec73f64SPoul-Henning Kamp 313c679c734SPoul-Henning Kamp u = tc->tc_frequency / tc->tc_counter_mask; 314555a5de2SPoul-Henning Kamp /* XXX: We need some margin here, 10% is a guess */ 315555a5de2SPoul-Henning Kamp u *= 11; 316555a5de2SPoul-Henning Kamp u /= 10; 317c679c734SPoul-Henning Kamp if (u > hz && tc->tc_quality >= 0) { 318c679c734SPoul-Henning Kamp tc->tc_quality = -2000; 319c679c734SPoul-Henning Kamp if (bootverbose) { 320c679c734SPoul-Henning Kamp printf("Timecounter \"%s\" frequency %ju Hz", 321555a5de2SPoul-Henning Kamp tc->tc_name, (uintmax_t)tc->tc_frequency); 322c679c734SPoul-Henning Kamp printf(" -- Insufficient hz, needs at least %u\n", u); 323c679c734SPoul-Henning Kamp } 324c679c734SPoul-Henning Kamp } else if (tc->tc_quality >= 0 || bootverbose) { 325555a5de2SPoul-Henning Kamp printf("Timecounter \"%s\" frequency %ju Hz quality %d\n", 326555a5de2SPoul-Henning Kamp tc->tc_name, (uintmax_t)tc->tc_frequency, 32778a49a45SPoul-Henning Kamp tc->tc_quality); 328e46eeb89SPoul-Henning Kamp } 329c679c734SPoul-Henning Kamp 33062efba6aSPoul-Henning Kamp tc->tc_next = timecounters; 33162efba6aSPoul-Henning Kamp timecounters = tc; 332555a5de2SPoul-Henning Kamp /* 333555a5de2SPoul-Henning Kamp * Never automatically use a timecounter with negative quality. 334555a5de2SPoul-Henning Kamp * Even though we run on the dummy counter, switching here may be 335555a5de2SPoul-Henning Kamp * worse since this timecounter may not be monotonous. 336555a5de2SPoul-Henning Kamp */ 33778a49a45SPoul-Henning Kamp if (tc->tc_quality < 0) 33878a49a45SPoul-Henning Kamp return; 33978a49a45SPoul-Henning Kamp if (tc->tc_quality < timecounter->tc_quality) 34078a49a45SPoul-Henning Kamp return; 341555a5de2SPoul-Henning Kamp if (tc->tc_quality == timecounter->tc_quality && 342555a5de2SPoul-Henning Kamp tc->tc_frequency < timecounter->tc_frequency) 343555a5de2SPoul-Henning Kamp return; 344555a5de2SPoul-Henning Kamp (void)tc->tc_get_timecount(tc); 345555a5de2SPoul-Henning Kamp (void)tc->tc_get_timecount(tc); 3467ec73f64SPoul-Henning Kamp timecounter = tc; 34762efba6aSPoul-Henning Kamp } 34862efba6aSPoul-Henning Kamp 34939acc78aSPoul-Henning Kamp /* Report the frequency of the current timecounter. */ 35060ca3996SPoul-Henning Kamp u_int64_t 35162efba6aSPoul-Henning Kamp tc_getfrequency(void) 35262efba6aSPoul-Henning Kamp { 35362efba6aSPoul-Henning Kamp 3546b00cf46SPoul-Henning Kamp return (timehands->th_counter->tc_frequency); 3557ec73f64SPoul-Henning Kamp } 3567ec73f64SPoul-Henning Kamp 35739acc78aSPoul-Henning Kamp /* 3584e82e5f6SWarner Losh * Step our concept of UTC. This is done by modifying our estimate of 3594e74721cSPoul-Henning Kamp * when we booted. 3604e74721cSPoul-Henning Kamp * XXX: not locked. 3616b00cf46SPoul-Henning Kamp */ 3627ec73f64SPoul-Henning Kamp void 36391266b96SPoul-Henning Kamp tc_setclock(struct timespec *ts) 3647ec73f64SPoul-Henning Kamp { 3655b51d1deSPoul-Henning Kamp struct timespec tbef, taft; 3664e74721cSPoul-Henning Kamp struct bintime bt, bt2; 3677ec73f64SPoul-Henning Kamp 368e8444a7eSPoul-Henning Kamp cpu_tick_calibrate(1); 3694394f476SPoul-Henning Kamp nsetclock++; 3705b51d1deSPoul-Henning Kamp nanotime(&tbef); 3714e74721cSPoul-Henning Kamp timespec2bintime(ts, &bt); 3725b51d1deSPoul-Henning Kamp binuptime(&bt2); 3734e74721cSPoul-Henning Kamp bintime_sub(&bt, &bt2); 3744e74721cSPoul-Henning Kamp bintime_add(&bt2, &boottimebin); 3754e74721cSPoul-Henning Kamp boottimebin = bt; 3764e74721cSPoul-Henning Kamp bintime2timeval(&bt, &boottime); 37739acc78aSPoul-Henning Kamp 37839acc78aSPoul-Henning Kamp /* XXX fiddle all the little crinkly bits around the fiords... */ 37991266b96SPoul-Henning Kamp tc_windup(); 3805b51d1deSPoul-Henning Kamp nanotime(&taft); 3814e74721cSPoul-Henning Kamp if (timestepwarnings) { 3825b51d1deSPoul-Henning Kamp log(LOG_INFO, 3835b51d1deSPoul-Henning Kamp "Time stepped from %jd.%09ld to %jd.%09ld (%jd.%09ld)\n", 3845b51d1deSPoul-Henning Kamp (intmax_t)tbef.tv_sec, tbef.tv_nsec, 3855b51d1deSPoul-Henning Kamp (intmax_t)taft.tv_sec, taft.tv_nsec, 386ee57aeeaSPoul-Henning Kamp (intmax_t)ts->tv_sec, ts->tv_nsec); 3874e74721cSPoul-Henning Kamp } 388e8444a7eSPoul-Henning Kamp cpu_tick_calibrate(1); 3897ec73f64SPoul-Henning Kamp } 3907ec73f64SPoul-Henning Kamp 39139acc78aSPoul-Henning Kamp /* 39239acc78aSPoul-Henning Kamp * Initialize the next struct timehands in the ring and make 3936b00cf46SPoul-Henning Kamp * it the active timehands. Along the way we might switch to a different 3946b00cf46SPoul-Henning Kamp * timecounter and/or do seconds processing in NTP. Slightly magic. 3956b00cf46SPoul-Henning Kamp */ 3969e1b5510SPoul-Henning Kamp static void 39791266b96SPoul-Henning Kamp tc_windup(void) 3987ec73f64SPoul-Henning Kamp { 3992028c0cdSPoul-Henning Kamp struct bintime bt; 40039acc78aSPoul-Henning Kamp struct timehands *th, *tho; 4016b00cf46SPoul-Henning Kamp u_int64_t scale; 40239acc78aSPoul-Henning Kamp u_int delta, ncount, ogen; 40339acc78aSPoul-Henning Kamp int i; 4044f2073fbSWarner Losh time_t t; 4057ec73f64SPoul-Henning Kamp 40639acc78aSPoul-Henning Kamp /* 4076b00cf46SPoul-Henning Kamp * Make the next timehands a copy of the current one, but do not 4086b00cf46SPoul-Henning Kamp * overwrite the generation or next pointer. While we update 4096b00cf46SPoul-Henning Kamp * the contents, the generation must be zero. 4106b00cf46SPoul-Henning Kamp */ 4116b00cf46SPoul-Henning Kamp tho = timehands; 4126b00cf46SPoul-Henning Kamp th = tho->th_next; 4136b00cf46SPoul-Henning Kamp ogen = th->th_generation; 4146b00cf46SPoul-Henning Kamp th->th_generation = 0; 41539acc78aSPoul-Henning Kamp bcopy(tho, th, offsetof(struct timehands, th_generation)); 4166b00cf46SPoul-Henning Kamp 41739acc78aSPoul-Henning Kamp /* 4186b00cf46SPoul-Henning Kamp * Capture a timecounter delta on the current timecounter and if 4196b00cf46SPoul-Henning Kamp * changing timecounters, a counter value from the new timecounter. 4206b00cf46SPoul-Henning Kamp * Update the offset fields accordingly. 4216b00cf46SPoul-Henning Kamp */ 4226b00cf46SPoul-Henning Kamp delta = tc_delta(th); 4236b00cf46SPoul-Henning Kamp if (th->th_counter != timecounter) 4246b00cf46SPoul-Henning Kamp ncount = timecounter->tc_get_timecount(timecounter); 42539acc78aSPoul-Henning Kamp else 42639acc78aSPoul-Henning Kamp ncount = 0; 4276b00cf46SPoul-Henning Kamp th->th_offset_count += delta; 4286b00cf46SPoul-Henning Kamp th->th_offset_count &= th->th_counter->tc_counter_mask; 4296b00cf46SPoul-Henning Kamp bintime_addx(&th->th_offset, th->th_scale * delta); 4306b00cf46SPoul-Henning Kamp 43139acc78aSPoul-Henning Kamp /* 4326b00cf46SPoul-Henning Kamp * Hardware latching timecounters may not generate interrupts on 4336b00cf46SPoul-Henning Kamp * PPS events, so instead we poll them. There is a finite risk that 4346b00cf46SPoul-Henning Kamp * the hardware might capture a count which is later than the one we 4356b00cf46SPoul-Henning Kamp * got above, and therefore possibly in the next NTP second which might 4366b00cf46SPoul-Henning Kamp * have a different rate than the current NTP second. It doesn't 4376b00cf46SPoul-Henning Kamp * matter in practice. 4386b00cf46SPoul-Henning Kamp */ 4396b00cf46SPoul-Henning Kamp if (tho->th_counter->tc_poll_pps) 4406b00cf46SPoul-Henning Kamp tho->th_counter->tc_poll_pps(tho->th_counter); 4416b00cf46SPoul-Henning Kamp 44239acc78aSPoul-Henning Kamp /* 443c1cccd1eSWarner Losh * Deal with NTP second processing. The for loop normally 444c1cccd1eSWarner Losh * iterates at most once, but in extreme situations it might 445c1cccd1eSWarner Losh * keep NTP sane if timeouts are not run for several seconds. 446c1cccd1eSWarner Losh * At boot, the time step can be large when the TOD hardware 447c1cccd1eSWarner Losh * has been read, so on really large steps, we call 448c1cccd1eSWarner Losh * ntp_update_second only twice. We need to call it twice in 449c1cccd1eSWarner Losh * case we missed a leap second. 4504f2073fbSWarner Losh */ 4514f2073fbSWarner Losh bt = th->th_offset; 4524f2073fbSWarner Losh bintime_add(&bt, &boottimebin); 45345cc9f5fSWarner Losh i = bt.sec - tho->th_microtime.tv_sec; 45445cc9f5fSWarner Losh if (i > LARGE_STEP) 45545cc9f5fSWarner Losh i = 2; 45645cc9f5fSWarner Losh for (; i > 0; i--) { 4574f2073fbSWarner Losh t = bt.sec; 4584f2073fbSWarner Losh ntp_update_second(&th->th_adjustment, &bt.sec); 4594f2073fbSWarner Losh if (bt.sec != t) 4604f2073fbSWarner Losh boottimebin.sec += bt.sec - t; 4614f2073fbSWarner Losh } 462c1cccd1eSWarner Losh /* Update the UTC timestamps used by the get*() functions. */ 463c1cccd1eSWarner Losh /* XXX shouldn't do this here. Should force non-`get' versions. */ 464c1cccd1eSWarner Losh bintime2timeval(&bt, &th->th_microtime); 465c1cccd1eSWarner Losh bintime2timespec(&bt, &th->th_nanotime); 4666b00cf46SPoul-Henning Kamp 4676b00cf46SPoul-Henning Kamp /* Now is a good time to change timecounters. */ 4686b00cf46SPoul-Henning Kamp if (th->th_counter != timecounter) { 4696b00cf46SPoul-Henning Kamp th->th_counter = timecounter; 4706b00cf46SPoul-Henning Kamp th->th_offset_count = ncount; 4717ec73f64SPoul-Henning Kamp } 4727ec73f64SPoul-Henning Kamp 47348e5da55SPoul-Henning Kamp /*- 4746b00cf46SPoul-Henning Kamp * Recalculate the scaling factor. We want the number of 1/2^64 4756b00cf46SPoul-Henning Kamp * fractions of a second per period of the hardware counter, taking 4766b00cf46SPoul-Henning Kamp * into account the th_adjustment factor which the NTP PLL/adjtime(2) 4776b00cf46SPoul-Henning Kamp * processing provides us with. 4786b00cf46SPoul-Henning Kamp * 4796b00cf46SPoul-Henning Kamp * The th_adjustment is nanoseconds per second with 32 bit binary 480d94e3652SPoul-Henning Kamp * fraction and we want 64 bit binary fraction of second: 4816b00cf46SPoul-Henning Kamp * 4826b00cf46SPoul-Henning Kamp * x = a * 2^32 / 10^9 = a * 4.294967296 4836b00cf46SPoul-Henning Kamp * 4846b00cf46SPoul-Henning Kamp * The range of th_adjustment is +/- 5000PPM so inside a 64bit int 485e8444a7eSPoul-Henning Kamp * we can only multiply by about 850 without overflowing, that 486e8444a7eSPoul-Henning Kamp * leaves no suitably precise fractions for multiply before divide. 4876b00cf46SPoul-Henning Kamp * 4886b00cf46SPoul-Henning Kamp * Divide before multiply with a fraction of 2199/512 results in a 4896b00cf46SPoul-Henning Kamp * systematic undercompensation of 10PPM of th_adjustment. On a 4906b00cf46SPoul-Henning Kamp * 5000PPM adjustment this is a 0.05PPM error. This is acceptable. 4916b00cf46SPoul-Henning Kamp * 4926b00cf46SPoul-Henning Kamp * We happily sacrifice the lowest of the 64 bits of our result 4936b00cf46SPoul-Henning Kamp * to the goddess of code clarity. 49439acc78aSPoul-Henning Kamp * 4956b00cf46SPoul-Henning Kamp */ 49639acc78aSPoul-Henning Kamp scale = (u_int64_t)1 << 63; 4976b00cf46SPoul-Henning Kamp scale += (th->th_adjustment / 1024) * 2199; 4986b00cf46SPoul-Henning Kamp scale /= th->th_counter->tc_frequency; 4996b00cf46SPoul-Henning Kamp th->th_scale = scale * 2; 5006b00cf46SPoul-Henning Kamp 50139acc78aSPoul-Henning Kamp /* 50239acc78aSPoul-Henning Kamp * Now that the struct timehands is again consistent, set the new 5036b00cf46SPoul-Henning Kamp * generation number, making sure to not make it zero. 5046b00cf46SPoul-Henning Kamp */ 5056b00cf46SPoul-Henning Kamp if (++ogen == 0) 50639acc78aSPoul-Henning Kamp ogen = 1; 5076b00cf46SPoul-Henning Kamp th->th_generation = ogen; 5086b00cf46SPoul-Henning Kamp 50939acc78aSPoul-Henning Kamp /* Go live with the new struct timehands. */ 5106b00cf46SPoul-Henning Kamp time_second = th->th_microtime.tv_sec; 51138b0884cSPoul-Henning Kamp time_uptime = th->th_offset.sec; 5126b00cf46SPoul-Henning Kamp timehands = th; 5136b00cf46SPoul-Henning Kamp } 5146b00cf46SPoul-Henning Kamp 51539acc78aSPoul-Henning Kamp /* Report or change the active timecounter hardware. */ 5166b6ef746SBruce Evans static int 51782d9ae4eSPoul-Henning Kamp sysctl_kern_timecounter_hardware(SYSCTL_HANDLER_ARGS) 5186b6ef746SBruce Evans { 5196b6ef746SBruce Evans char newname[32]; 5206b6ef746SBruce Evans struct timecounter *newtc, *tc; 5216b6ef746SBruce Evans int error; 5226b6ef746SBruce Evans 52362efba6aSPoul-Henning Kamp tc = timecounter; 524e80fb434SRobert Drehmel strlcpy(newname, tc->tc_name, sizeof(newname)); 525e80fb434SRobert Drehmel 5266b6ef746SBruce Evans error = sysctl_handle_string(oidp, &newname[0], sizeof(newname), req); 52739acc78aSPoul-Henning Kamp if (error != 0 || req->newptr == NULL || 52839acc78aSPoul-Henning Kamp strcmp(newname, tc->tc_name) == 0) 52962efba6aSPoul-Henning Kamp return (error); 53062efba6aSPoul-Henning Kamp for (newtc = timecounters; newtc != NULL; newtc = newtc->tc_next) { 53139acc78aSPoul-Henning Kamp if (strcmp(newname, newtc->tc_name) != 0) 53262efba6aSPoul-Henning Kamp continue; 53339acc78aSPoul-Henning Kamp 5346b6ef746SBruce Evans /* Warm up new timecounter. */ 5356b6ef746SBruce Evans (void)newtc->tc_get_timecount(newtc); 53662efba6aSPoul-Henning Kamp (void)newtc->tc_get_timecount(newtc); 53739acc78aSPoul-Henning Kamp 53862efba6aSPoul-Henning Kamp timecounter = newtc; 5396b6ef746SBruce Evans return (0); 5406b6ef746SBruce Evans } 5416b6ef746SBruce Evans return (EINVAL); 5426b6ef746SBruce Evans } 5436b6ef746SBruce Evans 5446b6ef746SBruce Evans SYSCTL_PROC(_kern_timecounter, OID_AUTO, hardware, CTLTYPE_STRING | CTLFLAG_RW, 5456b6ef746SBruce Evans 0, 0, sysctl_kern_timecounter_hardware, "A", ""); 5466b6ef746SBruce Evans 54778a49a45SPoul-Henning Kamp 54878a49a45SPoul-Henning Kamp /* Report or change the active timecounter hardware. */ 54978a49a45SPoul-Henning Kamp static int 55078a49a45SPoul-Henning Kamp sysctl_kern_timecounter_choice(SYSCTL_HANDLER_ARGS) 55178a49a45SPoul-Henning Kamp { 55278a49a45SPoul-Henning Kamp char buf[32], *spc; 55378a49a45SPoul-Henning Kamp struct timecounter *tc; 55478a49a45SPoul-Henning Kamp int error; 55578a49a45SPoul-Henning Kamp 55678a49a45SPoul-Henning Kamp spc = ""; 55778a49a45SPoul-Henning Kamp error = 0; 55878a49a45SPoul-Henning Kamp for (tc = timecounters; error == 0 && tc != NULL; tc = tc->tc_next) { 55978a49a45SPoul-Henning Kamp sprintf(buf, "%s%s(%d)", 56078a49a45SPoul-Henning Kamp spc, tc->tc_name, tc->tc_quality); 56178a49a45SPoul-Henning Kamp error = SYSCTL_OUT(req, buf, strlen(buf)); 56278a49a45SPoul-Henning Kamp spc = " "; 56378a49a45SPoul-Henning Kamp } 56478a49a45SPoul-Henning Kamp return (error); 56578a49a45SPoul-Henning Kamp } 56678a49a45SPoul-Henning Kamp 56778a49a45SPoul-Henning Kamp SYSCTL_PROC(_kern_timecounter, OID_AUTO, choice, CTLTYPE_STRING | CTLFLAG_RD, 56878a49a45SPoul-Henning Kamp 0, 0, sysctl_kern_timecounter_choice, "A", ""); 56978a49a45SPoul-Henning Kamp 57039acc78aSPoul-Henning Kamp /* 5716b00cf46SPoul-Henning Kamp * RFC 2783 PPS-API implementation. 5726b00cf46SPoul-Henning Kamp */ 5737ec73f64SPoul-Henning Kamp 57432c20357SPoul-Henning Kamp int 57532c20357SPoul-Henning Kamp pps_ioctl(u_long cmd, caddr_t data, struct pps_state *pps) 57632c20357SPoul-Henning Kamp { 57732c20357SPoul-Henning Kamp pps_params_t *app; 578b7424f2dSJohn Hay struct pps_fetch_args *fapi; 579de3f8889SPeter Wemm #ifdef PPS_SYNC 580b7424f2dSJohn Hay struct pps_kcbind_args *kapi; 581de3f8889SPeter Wemm #endif 58232c20357SPoul-Henning Kamp 583d8e8b675SPoul-Henning Kamp KASSERT(pps != NULL, ("NULL pps pointer in pps_ioctl")); 58432c20357SPoul-Henning Kamp switch (cmd) { 58532c20357SPoul-Henning Kamp case PPS_IOC_CREATE: 58632c20357SPoul-Henning Kamp return (0); 58732c20357SPoul-Henning Kamp case PPS_IOC_DESTROY: 58832c20357SPoul-Henning Kamp return (0); 58932c20357SPoul-Henning Kamp case PPS_IOC_SETPARAMS: 59032c20357SPoul-Henning Kamp app = (pps_params_t *)data; 59132c20357SPoul-Henning Kamp if (app->mode & ~pps->ppscap) 59232c20357SPoul-Henning Kamp return (EINVAL); 59332c20357SPoul-Henning Kamp pps->ppsparam = *app; 59432c20357SPoul-Henning Kamp return (0); 59532c20357SPoul-Henning Kamp case PPS_IOC_GETPARAMS: 59632c20357SPoul-Henning Kamp app = (pps_params_t *)data; 59732c20357SPoul-Henning Kamp *app = pps->ppsparam; 598b7424f2dSJohn Hay app->api_version = PPS_API_VERS_1; 59932c20357SPoul-Henning Kamp return (0); 60032c20357SPoul-Henning Kamp case PPS_IOC_GETCAP: 60132c20357SPoul-Henning Kamp *(int*)data = pps->ppscap; 60232c20357SPoul-Henning Kamp return (0); 60332c20357SPoul-Henning Kamp case PPS_IOC_FETCH: 604b7424f2dSJohn Hay fapi = (struct pps_fetch_args *)data; 605b7424f2dSJohn Hay if (fapi->tsformat && fapi->tsformat != PPS_TSFMT_TSPEC) 606b7424f2dSJohn Hay return (EINVAL); 607b7424f2dSJohn Hay if (fapi->timeout.tv_sec || fapi->timeout.tv_nsec) 60832c20357SPoul-Henning Kamp return (EOPNOTSUPP); 609b7424f2dSJohn Hay pps->ppsinfo.current_mode = pps->ppsparam.mode; 610b7424f2dSJohn Hay fapi->pps_info_buf = pps->ppsinfo; 611b7424f2dSJohn Hay return (0); 612b7424f2dSJohn Hay case PPS_IOC_KCBIND: 613b7424f2dSJohn Hay #ifdef PPS_SYNC 614b7424f2dSJohn Hay kapi = (struct pps_kcbind_args *)data; 615b7424f2dSJohn Hay /* XXX Only root should be able to do this */ 616b7424f2dSJohn Hay if (kapi->tsformat && kapi->tsformat != PPS_TSFMT_TSPEC) 617b7424f2dSJohn Hay return (EINVAL); 618b7424f2dSJohn Hay if (kapi->kernel_consumer != PPS_KC_HARDPPS) 619b7424f2dSJohn Hay return (EINVAL); 620b7424f2dSJohn Hay if (kapi->edge & ~pps->ppscap) 621b7424f2dSJohn Hay return (EINVAL); 622b7424f2dSJohn Hay pps->kcmode = kapi->edge; 623b7424f2dSJohn Hay return (0); 624b7424f2dSJohn Hay #else 625b7424f2dSJohn Hay return (EOPNOTSUPP); 626b7424f2dSJohn Hay #endif 62732c20357SPoul-Henning Kamp default: 628f8385624SPoul-Henning Kamp return (ENOIOCTL); 62932c20357SPoul-Henning Kamp } 63032c20357SPoul-Henning Kamp } 63132c20357SPoul-Henning Kamp 63232c20357SPoul-Henning Kamp void 63332c20357SPoul-Henning Kamp pps_init(struct pps_state *pps) 63432c20357SPoul-Henning Kamp { 63532c20357SPoul-Henning Kamp pps->ppscap |= PPS_TSFMT_TSPEC; 63632c20357SPoul-Henning Kamp if (pps->ppscap & PPS_CAPTUREASSERT) 63732c20357SPoul-Henning Kamp pps->ppscap |= PPS_OFFSETASSERT; 63832c20357SPoul-Henning Kamp if (pps->ppscap & PPS_CAPTURECLEAR) 63932c20357SPoul-Henning Kamp pps->ppscap |= PPS_OFFSETCLEAR; 64032c20357SPoul-Henning Kamp } 64132c20357SPoul-Henning Kamp 64232c20357SPoul-Henning Kamp void 6437bf758bfSPoul-Henning Kamp pps_capture(struct pps_state *pps) 6447bf758bfSPoul-Henning Kamp { 6456b00cf46SPoul-Henning Kamp struct timehands *th; 6467bf758bfSPoul-Henning Kamp 647d8e8b675SPoul-Henning Kamp KASSERT(pps != NULL, ("NULL pps pointer in pps_capture")); 6486b00cf46SPoul-Henning Kamp th = timehands; 6496b00cf46SPoul-Henning Kamp pps->capgen = th->th_generation; 6506b00cf46SPoul-Henning Kamp pps->capth = th; 6516b00cf46SPoul-Henning Kamp pps->capcount = th->th_counter->tc_get_timecount(th->th_counter); 6526b00cf46SPoul-Henning Kamp if (pps->capgen != th->th_generation) 6536b00cf46SPoul-Henning Kamp pps->capgen = 0; 6547bf758bfSPoul-Henning Kamp } 6557bf758bfSPoul-Henning Kamp 6567bf758bfSPoul-Henning Kamp void 6577bf758bfSPoul-Henning Kamp pps_event(struct pps_state *pps, int event) 65832c20357SPoul-Henning Kamp { 65939acc78aSPoul-Henning Kamp struct bintime bt; 66032c20357SPoul-Henning Kamp struct timespec ts, *tsp, *osp; 6616b00cf46SPoul-Henning Kamp u_int tcount, *pcount; 66232c20357SPoul-Henning Kamp int foff, fhard; 66332c20357SPoul-Henning Kamp pps_seq_t *pseq; 66432c20357SPoul-Henning Kamp 665d8e8b675SPoul-Henning Kamp KASSERT(pps != NULL, ("NULL pps pointer in pps_event")); 66639acc78aSPoul-Henning Kamp /* If the timecounter was wound up underneath us, bail out. */ 66739acc78aSPoul-Henning Kamp if (pps->capgen == 0 || pps->capgen != pps->capth->th_generation) 6687bf758bfSPoul-Henning Kamp return; 6697bf758bfSPoul-Henning Kamp 67039acc78aSPoul-Henning Kamp /* Things would be easier with arrays. */ 67132c20357SPoul-Henning Kamp if (event == PPS_CAPTUREASSERT) { 67232c20357SPoul-Henning Kamp tsp = &pps->ppsinfo.assert_timestamp; 67332c20357SPoul-Henning Kamp osp = &pps->ppsparam.assert_offset; 67432c20357SPoul-Henning Kamp foff = pps->ppsparam.mode & PPS_OFFSETASSERT; 675b7424f2dSJohn Hay fhard = pps->kcmode & PPS_CAPTUREASSERT; 67632c20357SPoul-Henning Kamp pcount = &pps->ppscount[0]; 67732c20357SPoul-Henning Kamp pseq = &pps->ppsinfo.assert_sequence; 67832c20357SPoul-Henning Kamp } else { 67932c20357SPoul-Henning Kamp tsp = &pps->ppsinfo.clear_timestamp; 68032c20357SPoul-Henning Kamp osp = &pps->ppsparam.clear_offset; 68132c20357SPoul-Henning Kamp foff = pps->ppsparam.mode & PPS_OFFSETCLEAR; 682b7424f2dSJohn Hay fhard = pps->kcmode & PPS_CAPTURECLEAR; 68332c20357SPoul-Henning Kamp pcount = &pps->ppscount[1]; 68432c20357SPoul-Henning Kamp pseq = &pps->ppsinfo.clear_sequence; 68532c20357SPoul-Henning Kamp } 68632c20357SPoul-Henning Kamp 68739acc78aSPoul-Henning Kamp /* 6886b00cf46SPoul-Henning Kamp * If the timecounter changed, we cannot compare the count values, so 6896b00cf46SPoul-Henning Kamp * we have to drop the rest of the PPS-stuff until the next event. 6906b00cf46SPoul-Henning Kamp */ 6916b00cf46SPoul-Henning Kamp if (pps->ppstc != pps->capth->th_counter) { 6926b00cf46SPoul-Henning Kamp pps->ppstc = pps->capth->th_counter; 6937bf758bfSPoul-Henning Kamp *pcount = pps->capcount; 6947bf758bfSPoul-Henning Kamp pps->ppscount[2] = pps->capcount; 69532c20357SPoul-Henning Kamp return; 69632c20357SPoul-Henning Kamp } 69732c20357SPoul-Henning Kamp 69839acc78aSPoul-Henning Kamp /* Convert the count to a timespec. */ 6996b00cf46SPoul-Henning Kamp tcount = pps->capcount - pps->capth->th_offset_count; 7006b00cf46SPoul-Henning Kamp tcount &= pps->capth->th_counter->tc_counter_mask; 7016b00cf46SPoul-Henning Kamp bt = pps->capth->th_offset; 7026b00cf46SPoul-Henning Kamp bintime_addx(&bt, pps->capth->th_scale * tcount); 703eef633a7SPoul-Henning Kamp bintime_add(&bt, &boottimebin); 7042028c0cdSPoul-Henning Kamp bintime2timespec(&bt, &ts); 70532c20357SPoul-Henning Kamp 70639acc78aSPoul-Henning Kamp /* If the timecounter was wound up underneath us, bail out. */ 7076b00cf46SPoul-Henning Kamp if (pps->capgen != pps->capth->th_generation) 7087bf758bfSPoul-Henning Kamp return; 7097bf758bfSPoul-Henning Kamp 7107bf758bfSPoul-Henning Kamp *pcount = pps->capcount; 71132c20357SPoul-Henning Kamp (*pseq)++; 71232c20357SPoul-Henning Kamp *tsp = ts; 71332c20357SPoul-Henning Kamp 71432c20357SPoul-Henning Kamp if (foff) { 71532c20357SPoul-Henning Kamp timespecadd(tsp, osp); 71632c20357SPoul-Henning Kamp if (tsp->tv_nsec < 0) { 71732c20357SPoul-Henning Kamp tsp->tv_nsec += 1000000000; 71832c20357SPoul-Henning Kamp tsp->tv_sec -= 1; 71932c20357SPoul-Henning Kamp } 72032c20357SPoul-Henning Kamp } 72132c20357SPoul-Henning Kamp #ifdef PPS_SYNC 72232c20357SPoul-Henning Kamp if (fhard) { 723ce9fac00SPoul-Henning Kamp u_int64_t scale; 724ce9fac00SPoul-Henning Kamp 72539acc78aSPoul-Henning Kamp /* 7266b00cf46SPoul-Henning Kamp * Feed the NTP PLL/FLL. 727b1e7e201SJohn Hay * The FLL wants to know how many (hardware) nanoseconds 728b1e7e201SJohn Hay * elapsed since the previous event. 7296b00cf46SPoul-Henning Kamp */ 7307bf758bfSPoul-Henning Kamp tcount = pps->capcount - pps->ppscount[2]; 7317bf758bfSPoul-Henning Kamp pps->ppscount[2] = pps->capcount; 7326b00cf46SPoul-Henning Kamp tcount &= pps->capth->th_counter->tc_counter_mask; 733b1e7e201SJohn Hay scale = (u_int64_t)1 << 63; 734b1e7e201SJohn Hay scale /= pps->capth->th_counter->tc_frequency; 735b1e7e201SJohn Hay scale *= 2; 7362028c0cdSPoul-Henning Kamp bt.sec = 0; 7372028c0cdSPoul-Henning Kamp bt.frac = 0; 738b1e7e201SJohn Hay bintime_addx(&bt, scale * tcount); 7392028c0cdSPoul-Henning Kamp bintime2timespec(&bt, &ts); 7402028c0cdSPoul-Henning Kamp hardpps(tsp, ts.tv_nsec + 1000000000 * ts.tv_sec); 74132c20357SPoul-Henning Kamp } 74232c20357SPoul-Henning Kamp #endif 74332c20357SPoul-Henning Kamp } 7449e1b5510SPoul-Henning Kamp 74539acc78aSPoul-Henning Kamp /* 7469e1b5510SPoul-Henning Kamp * Timecounters need to be updated every so often to prevent the hardware 7479e1b5510SPoul-Henning Kamp * counter from overflowing. Updating also recalculates the cached values 7489e1b5510SPoul-Henning Kamp * used by the get*() family of functions, so their precision depends on 7499e1b5510SPoul-Henning Kamp * the update frequency. 7509e1b5510SPoul-Henning Kamp */ 7519e1b5510SPoul-Henning Kamp 7529e1b5510SPoul-Henning Kamp static int tc_tick; 753b3ed130cSPoul-Henning Kamp SYSCTL_INT(_kern_timecounter, OID_AUTO, tick, CTLFLAG_RD, &tc_tick, 0, ""); 7549e1b5510SPoul-Henning Kamp 755e7fa55afSPoul-Henning Kamp void 756e7fa55afSPoul-Henning Kamp tc_ticktock(void) 7579e1b5510SPoul-Henning Kamp { 758e7fa55afSPoul-Henning Kamp static int count; 759e8444a7eSPoul-Henning Kamp static time_t last_calib; 7609e1b5510SPoul-Henning Kamp 761e7fa55afSPoul-Henning Kamp if (++count < tc_tick) 762e7fa55afSPoul-Henning Kamp return; 763e7fa55afSPoul-Henning Kamp count = 0; 7649e1b5510SPoul-Henning Kamp tc_windup(); 765e8444a7eSPoul-Henning Kamp if (time_uptime != last_calib && !(time_uptime & 0xf)) { 766e8444a7eSPoul-Henning Kamp cpu_tick_calibrate(0); 767e8444a7eSPoul-Henning Kamp last_calib = time_uptime; 768e8444a7eSPoul-Henning Kamp } 7699e1b5510SPoul-Henning Kamp } 7709e1b5510SPoul-Henning Kamp 7719e1b5510SPoul-Henning Kamp static void 7729e1b5510SPoul-Henning Kamp inittimecounter(void *dummy) 7739e1b5510SPoul-Henning Kamp { 7749e1b5510SPoul-Henning Kamp u_int p; 7759e1b5510SPoul-Henning Kamp 77639acc78aSPoul-Henning Kamp /* 77739acc78aSPoul-Henning Kamp * Set the initial timeout to 77839acc78aSPoul-Henning Kamp * max(1, <approx. number of hardclock ticks in a millisecond>). 77939acc78aSPoul-Henning Kamp * People should probably not use the sysctl to set the timeout 78039acc78aSPoul-Henning Kamp * to smaller than its inital value, since that value is the 78139acc78aSPoul-Henning Kamp * smallest reasonable one. If they want better timestamps they 78239acc78aSPoul-Henning Kamp * should use the non-"get"* functions. 78339acc78aSPoul-Henning Kamp */ 7849e1b5510SPoul-Henning Kamp if (hz > 1000) 7859e1b5510SPoul-Henning Kamp tc_tick = (hz + 500) / 1000; 7869e1b5510SPoul-Henning Kamp else 7879e1b5510SPoul-Henning Kamp tc_tick = 1; 7889e1b5510SPoul-Henning Kamp p = (tc_tick * 1000000) / hz; 7899e1b5510SPoul-Henning Kamp printf("Timecounters tick every %d.%03u msec\n", p / 1000, p % 1000); 79039acc78aSPoul-Henning Kamp 79148e5da55SPoul-Henning Kamp /* warm up new timecounter (again) and get rolling. */ 79239acc78aSPoul-Henning Kamp (void)timecounter->tc_get_timecount(timecounter); 79339acc78aSPoul-Henning Kamp (void)timecounter->tc_get_timecount(timecounter); 7949e1b5510SPoul-Henning Kamp } 7959e1b5510SPoul-Henning Kamp 796ff292556SPeter Wemm SYSINIT(timecounter, SI_SUB_CLOCKS, SI_ORDER_SECOND, inittimecounter, NULL) 7975b1a8eb3SPoul-Henning Kamp 798e8444a7eSPoul-Henning Kamp /* Cpu tick handling -------------------------------------------------*/ 799e8444a7eSPoul-Henning Kamp 800e8444a7eSPoul-Henning Kamp static int cpu_tick_variable; 801e8444a7eSPoul-Henning Kamp static uint64_t cpu_tick_frequency; 802e8444a7eSPoul-Henning Kamp 80388ca07e7SJohn Baldwin static uint64_t 8045b1a8eb3SPoul-Henning Kamp tc_cpu_ticks(void) 8055b1a8eb3SPoul-Henning Kamp { 8065b1a8eb3SPoul-Henning Kamp static uint64_t base; 8075b1a8eb3SPoul-Henning Kamp static unsigned last; 808e8444a7eSPoul-Henning Kamp unsigned u; 8095b1a8eb3SPoul-Henning Kamp struct timecounter *tc; 8105b1a8eb3SPoul-Henning Kamp 8115b1a8eb3SPoul-Henning Kamp tc = timehands->th_counter; 8125b1a8eb3SPoul-Henning Kamp u = tc->tc_get_timecount(tc) & tc->tc_counter_mask; 8135b1a8eb3SPoul-Henning Kamp if (u < last) 814fccfcfbaSPoul-Henning Kamp base += (uint64_t)tc->tc_counter_mask + 1; 8155b1a8eb3SPoul-Henning Kamp last = u; 8165b1a8eb3SPoul-Henning Kamp return (u + base); 8175b1a8eb3SPoul-Henning Kamp } 8185b1a8eb3SPoul-Henning Kamp 819e8444a7eSPoul-Henning Kamp /* 820e8444a7eSPoul-Henning Kamp * This function gets called ever 16 seconds on only one designated 821e8444a7eSPoul-Henning Kamp * CPU in the system from hardclock() via tc_ticktock(). 822e8444a7eSPoul-Henning Kamp * 823e8444a7eSPoul-Henning Kamp * Whenever the real time clock is stepped we get called with reset=1 824e8444a7eSPoul-Henning Kamp * to make sure we handle suspend/resume and similar events correctly. 825e8444a7eSPoul-Henning Kamp */ 826e8444a7eSPoul-Henning Kamp 827e8444a7eSPoul-Henning Kamp static void 828e8444a7eSPoul-Henning Kamp cpu_tick_calibrate(int reset) 829e8444a7eSPoul-Henning Kamp { 830e8444a7eSPoul-Henning Kamp static uint64_t c_last; 831e8444a7eSPoul-Henning Kamp uint64_t c_this, c_delta; 832e8444a7eSPoul-Henning Kamp static struct bintime t_last; 833e8444a7eSPoul-Henning Kamp struct bintime t_this, t_delta; 834301af28aSPoul-Henning Kamp uint32_t divi; 835e8444a7eSPoul-Henning Kamp 836e8444a7eSPoul-Henning Kamp if (reset) { 837e8444a7eSPoul-Henning Kamp /* The clock was stepped, abort & reset */ 838e8444a7eSPoul-Henning Kamp t_last.sec = 0; 839e8444a7eSPoul-Henning Kamp return; 840e8444a7eSPoul-Henning Kamp } 841e8444a7eSPoul-Henning Kamp 842e8444a7eSPoul-Henning Kamp /* we don't calibrate fixed rate cputicks */ 843e8444a7eSPoul-Henning Kamp if (!cpu_tick_variable) 844e8444a7eSPoul-Henning Kamp return; 845e8444a7eSPoul-Henning Kamp 846e8444a7eSPoul-Henning Kamp getbinuptime(&t_this); 847e8444a7eSPoul-Henning Kamp c_this = cpu_ticks(); 848e8444a7eSPoul-Henning Kamp if (t_last.sec != 0) { 849e8444a7eSPoul-Henning Kamp c_delta = c_this - c_last; 850e8444a7eSPoul-Henning Kamp t_delta = t_this; 851e8444a7eSPoul-Henning Kamp bintime_sub(&t_delta, &t_last); 852e8444a7eSPoul-Henning Kamp /* 853e8444a7eSPoul-Henning Kamp * Validate that 16 +/- 1/256 seconds passed. 854e8444a7eSPoul-Henning Kamp * After division by 16 this gives us a precision of 855e8444a7eSPoul-Henning Kamp * roughly 250PPM which is sufficient 856e8444a7eSPoul-Henning Kamp */ 857e8444a7eSPoul-Henning Kamp if (t_delta.sec > 16 || ( 858e8444a7eSPoul-Henning Kamp t_delta.sec == 16 && t_delta.frac >= (0x01LL << 56))) { 859e8444a7eSPoul-Henning Kamp /* too long */ 860301af28aSPoul-Henning Kamp if (bootverbose) 8616cda760fSPoul-Henning Kamp printf("%ju.%016jx too long\n", 8626cda760fSPoul-Henning Kamp (uintmax_t)t_delta.sec, 8636cda760fSPoul-Henning Kamp (uintmax_t)t_delta.frac); 864e8444a7eSPoul-Henning Kamp } else if (t_delta.sec < 15 || 865e8444a7eSPoul-Henning Kamp (t_delta.sec == 15 && t_delta.frac <= (0xffLL << 56))) { 866e8444a7eSPoul-Henning Kamp /* too short */ 867301af28aSPoul-Henning Kamp if (bootverbose) 8686cda760fSPoul-Henning Kamp printf("%ju.%016jx too short\n", 8696cda760fSPoul-Henning Kamp (uintmax_t)t_delta.sec, 8706cda760fSPoul-Henning Kamp (uintmax_t)t_delta.frac); 871e8444a7eSPoul-Henning Kamp } else { 872e8444a7eSPoul-Henning Kamp /* just right */ 873301af28aSPoul-Henning Kamp /* 874301af28aSPoul-Henning Kamp * Headroom: 875301af28aSPoul-Henning Kamp * 2^(64-20) / 16[s] = 876301af28aSPoul-Henning Kamp * 2^(44) / 16[s] = 877301af28aSPoul-Henning Kamp * 17.592.186.044.416 / 16 = 878301af28aSPoul-Henning Kamp * 1.099.511.627.776 [Hz] 879301af28aSPoul-Henning Kamp */ 880301af28aSPoul-Henning Kamp divi = t_delta.sec << 20; 881301af28aSPoul-Henning Kamp divi |= t_delta.frac >> (64 - 20); 882301af28aSPoul-Henning Kamp c_delta <<= 20; 883301af28aSPoul-Henning Kamp c_delta /= divi; 884e8444a7eSPoul-Henning Kamp if (c_delta > cpu_tick_frequency) { 885301af28aSPoul-Henning Kamp if (bootverbose) 8866cda760fSPoul-Henning Kamp printf("cpu_tick increased to %ju Hz", 8876cda760fSPoul-Henning Kamp c_delta); 888e8444a7eSPoul-Henning Kamp cpu_tick_frequency = c_delta; 889e8444a7eSPoul-Henning Kamp } 890e8444a7eSPoul-Henning Kamp } 891e8444a7eSPoul-Henning Kamp } 892e8444a7eSPoul-Henning Kamp c_last = c_this; 893e8444a7eSPoul-Henning Kamp t_last = t_this; 894e8444a7eSPoul-Henning Kamp } 895e8444a7eSPoul-Henning Kamp 896e8444a7eSPoul-Henning Kamp void 897e8444a7eSPoul-Henning Kamp set_cputicker(cpu_tick_f *func, uint64_t freq, unsigned var) 898e8444a7eSPoul-Henning Kamp { 899e8444a7eSPoul-Henning Kamp 900e8444a7eSPoul-Henning Kamp if (func == NULL) { 901e8444a7eSPoul-Henning Kamp cpu_ticks = tc_cpu_ticks; 902e8444a7eSPoul-Henning Kamp } else { 903e8444a7eSPoul-Henning Kamp cpu_tick_frequency = freq; 904e8444a7eSPoul-Henning Kamp cpu_tick_variable = var; 905e8444a7eSPoul-Henning Kamp cpu_ticks = func; 906e8444a7eSPoul-Henning Kamp } 907e8444a7eSPoul-Henning Kamp } 908e8444a7eSPoul-Henning Kamp 909e8444a7eSPoul-Henning Kamp uint64_t 910e8444a7eSPoul-Henning Kamp cpu_tickrate(void) 911e8444a7eSPoul-Henning Kamp { 912e8444a7eSPoul-Henning Kamp 913e8444a7eSPoul-Henning Kamp if (cpu_ticks == tc_cpu_ticks) 914e8444a7eSPoul-Henning Kamp return (tc_getfrequency()); 915e8444a7eSPoul-Henning Kamp return (cpu_tick_frequency); 916e8444a7eSPoul-Henning Kamp } 917e8444a7eSPoul-Henning Kamp 918e8444a7eSPoul-Henning Kamp /* 919e8444a7eSPoul-Henning Kamp * We need to be slightly careful converting cputicks to microseconds. 920e8444a7eSPoul-Henning Kamp * There is plenty of margin in 64 bits of microseconds (half a million 921e8444a7eSPoul-Henning Kamp * years) and in 64 bits at 4 GHz (146 years), but if we do a multiply 922e8444a7eSPoul-Henning Kamp * before divide conversion (to retain precision) we find that the 923e8444a7eSPoul-Henning Kamp * margin shrinks to 1.5 hours (one millionth of 146y). 924e8444a7eSPoul-Henning Kamp * With a three prong approach we never loose significant bits, no 925e8444a7eSPoul-Henning Kamp * matter what the cputick rate and length of timeinterval is. 926e8444a7eSPoul-Henning Kamp */ 927e8444a7eSPoul-Henning Kamp 928e8444a7eSPoul-Henning Kamp uint64_t 929e8444a7eSPoul-Henning Kamp cputick2usec(uint64_t tick) 930e8444a7eSPoul-Henning Kamp { 931e8444a7eSPoul-Henning Kamp 932e8444a7eSPoul-Henning Kamp if (tick > 18446744073709551LL) /* floor(2^64 / 1000) */ 933e8444a7eSPoul-Henning Kamp return (tick / (cpu_tickrate() / 1000000LL)); 934e8444a7eSPoul-Henning Kamp else if (tick > 18446744073709LL) /* floor(2^64 / 1000000) */ 935e8444a7eSPoul-Henning Kamp return ((tick * 1000LL) / (cpu_tickrate() / 1000LL)); 936e8444a7eSPoul-Henning Kamp else 937e8444a7eSPoul-Henning Kamp return ((tick * 1000000LL) / cpu_tickrate()); 938e8444a7eSPoul-Henning Kamp } 939e8444a7eSPoul-Henning Kamp 940e8444a7eSPoul-Henning Kamp cpu_tick_f *cpu_ticks = tc_cpu_ticks; 941