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 * ---------------------------------------------------------------------------- 8b0fdc837SLawrence Stewart * 9b0fdc837SLawrence Stewart * Copyright (c) 2011 The FreeBSD Foundation 10b0fdc837SLawrence Stewart * All rights reserved. 11b0fdc837SLawrence Stewart * 12b0fdc837SLawrence Stewart * Portions of this software were developed by Julien Ridoux at the University 13b0fdc837SLawrence Stewart * of Melbourne under sponsorship from the FreeBSD Foundation. 14df8bae1dSRodney W. Grimes */ 15df8bae1dSRodney W. Grimes 16677b542eSDavid E. O'Brien #include <sys/cdefs.h> 17677b542eSDavid E. O'Brien __FBSDID("$FreeBSD$"); 18677b542eSDavid E. O'Brien 19aea81038SKonstantin Belousov #include "opt_compat.h" 2032c20357SPoul-Henning Kamp #include "opt_ntp.h" 21b0fdc837SLawrence Stewart #include "opt_ffclock.h" 2232c20357SPoul-Henning Kamp 23df8bae1dSRodney W. Grimes #include <sys/param.h> 2491266b96SPoul-Henning Kamp #include <sys/kernel.h> 255b999a6bSDavide Italiano #include <sys/limits.h> 26b0fdc837SLawrence Stewart #include <sys/lock.h> 27b0fdc837SLawrence Stewart #include <sys/mutex.h> 2891d9eda2SIan Lepore #include <sys/sbuf.h> 2991266b96SPoul-Henning Kamp #include <sys/sysctl.h> 304e74721cSPoul-Henning Kamp #include <sys/syslog.h> 3191266b96SPoul-Henning Kamp #include <sys/systm.h> 32b0fdc837SLawrence Stewart #include <sys/timeffc.h> 3332c20357SPoul-Henning Kamp #include <sys/timepps.h> 3448e5da55SPoul-Henning Kamp #include <sys/timetc.h> 3539acc78aSPoul-Henning Kamp #include <sys/timex.h> 36aea81038SKonstantin Belousov #include <sys/vdso.h> 3739acc78aSPoul-Henning Kamp 383bac064fSPoul-Henning Kamp /* 39c1cccd1eSWarner Losh * A large step happens on boot. This constant detects such steps. 40c1cccd1eSWarner Losh * It is relatively small so that ntp_update_second gets called enough 41c1cccd1eSWarner Losh * in the typical 'missed a couple of seconds' case, but doesn't loop 42c1cccd1eSWarner Losh * forever when the time step is large. 434f2073fbSWarner Losh */ 444f2073fbSWarner Losh #define LARGE_STEP 200 454f2073fbSWarner Losh 464f2073fbSWarner Losh /* 4762efba6aSPoul-Henning Kamp * Implement a dummy timecounter which we can use until we get a real one 4862efba6aSPoul-Henning Kamp * in the air. This allows the console and other early stuff to use 4962efba6aSPoul-Henning Kamp * time services. 503bac064fSPoul-Henning Kamp */ 513bac064fSPoul-Henning Kamp 526b00cf46SPoul-Henning Kamp static u_int 5362efba6aSPoul-Henning Kamp dummy_get_timecount(struct timecounter *tc) 5462efba6aSPoul-Henning Kamp { 556b00cf46SPoul-Henning Kamp static u_int now; 5662efba6aSPoul-Henning Kamp 5762efba6aSPoul-Henning Kamp return (++now); 5862efba6aSPoul-Henning Kamp } 5962efba6aSPoul-Henning Kamp 6062efba6aSPoul-Henning Kamp static struct timecounter dummy_timecounter = { 6178a49a45SPoul-Henning Kamp dummy_get_timecount, 0, ~0u, 1000000, "dummy", -1000000 6262efba6aSPoul-Henning Kamp }; 6362efba6aSPoul-Henning Kamp 6462efba6aSPoul-Henning Kamp struct timehands { 6562efba6aSPoul-Henning Kamp /* These fields must be initialized by the driver. */ 666b00cf46SPoul-Henning Kamp struct timecounter *th_counter; 676b00cf46SPoul-Henning Kamp int64_t th_adjustment; 6860ae52f7SEd Schouten uint64_t th_scale; 696b00cf46SPoul-Henning Kamp u_int th_offset_count; 706b00cf46SPoul-Henning Kamp struct bintime th_offset; 716b00cf46SPoul-Henning Kamp struct timeval th_microtime; 726b00cf46SPoul-Henning Kamp struct timespec th_nanotime; 7339acc78aSPoul-Henning Kamp /* Fields not to be copied in tc_windup start with th_generation. */ 742c6946dcSKonstantin Belousov u_int th_generation; 756b00cf46SPoul-Henning Kamp struct timehands *th_next; 7662efba6aSPoul-Henning Kamp }; 7762efba6aSPoul-Henning Kamp 785b1c0294SDavid E. O'Brien static struct timehands th0; 7939acc78aSPoul-Henning Kamp static struct timehands th9 = { NULL, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0, &th0}; 8039acc78aSPoul-Henning Kamp static struct timehands th8 = { NULL, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0, &th9}; 8139acc78aSPoul-Henning Kamp static struct timehands th7 = { NULL, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0, &th8}; 8239acc78aSPoul-Henning Kamp static struct timehands th6 = { NULL, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0, &th7}; 8339acc78aSPoul-Henning Kamp static struct timehands th5 = { NULL, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0, &th6}; 8439acc78aSPoul-Henning Kamp static struct timehands th4 = { NULL, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0, &th5}; 8539acc78aSPoul-Henning Kamp static struct timehands th3 = { NULL, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0, &th4}; 8639acc78aSPoul-Henning Kamp static struct timehands th2 = { NULL, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0, &th3}; 8739acc78aSPoul-Henning Kamp static struct timehands th1 = { NULL, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0, &th2}; 88f5d157fbSPoul-Henning Kamp static struct timehands th0 = { 89f5d157fbSPoul-Henning Kamp &dummy_timecounter, 90f5d157fbSPoul-Henning Kamp 0, 9139acc78aSPoul-Henning Kamp (uint64_t)-1 / 1000000, 92f5d157fbSPoul-Henning Kamp 0, 93d25917e8SPoul-Henning Kamp {1, 0}, 94f5d157fbSPoul-Henning Kamp {0, 0}, 95f5d157fbSPoul-Henning Kamp {0, 0}, 96f5d157fbSPoul-Henning Kamp 1, 97f5d157fbSPoul-Henning Kamp &th1 98f5d157fbSPoul-Henning Kamp }; 9962efba6aSPoul-Henning Kamp 10062efba6aSPoul-Henning Kamp static struct timehands *volatile timehands = &th0; 10162efba6aSPoul-Henning Kamp struct timecounter *timecounter = &dummy_timecounter; 10262efba6aSPoul-Henning Kamp static struct timecounter *timecounters = &dummy_timecounter; 1033bac064fSPoul-Henning Kamp 1040e189873SAlexander Motin int tc_min_ticktock_freq = 1; 1050e189873SAlexander Motin 106a8df530dSJohn Baldwin volatile time_t time_second = 1; 107a8df530dSJohn Baldwin volatile time_t time_uptime = 1; 108227ee8a1SPoul-Henning Kamp 109547d94bdSJung-uk Kim struct bintime boottimebin; 11037d38777SBruce Evans struct timeval boottime; 111a7bc3102SPeter Wemm static int sysctl_kern_boottime(SYSCTL_HANDLER_ARGS); 112a7bc3102SPeter Wemm SYSCTL_PROC(_kern, KERN_BOOTTIME, boottime, CTLTYPE_STRUCT|CTLFLAG_RD, 113a7bc3102SPeter Wemm NULL, 0, sysctl_kern_boottime, "S,timeval", "System boottime"); 11437d38777SBruce Evans 11591266b96SPoul-Henning Kamp SYSCTL_NODE(_kern, OID_AUTO, timecounter, CTLFLAG_RW, 0, ""); 1166472ac3dSEd Schouten static SYSCTL_NODE(_kern_timecounter, OID_AUTO, tc, CTLFLAG_RW, 0, ""); 11791266b96SPoul-Henning Kamp 1184e74721cSPoul-Henning Kamp static int timestepwarnings; 1194e74721cSPoul-Henning Kamp SYSCTL_INT(_kern_timecounter, OID_AUTO, stepwarnings, CTLFLAG_RW, 1202baa5cddSRebecca Cran ×tepwarnings, 0, "Log time steps"); 1214e74721cSPoul-Henning Kamp 1225b999a6bSDavide Italiano struct bintime bt_timethreshold; 1235b999a6bSDavide Italiano struct bintime bt_tickthreshold; 1245b999a6bSDavide Italiano sbintime_t sbt_timethreshold; 1255b999a6bSDavide Italiano sbintime_t sbt_tickthreshold; 1265b999a6bSDavide Italiano struct bintime tc_tick_bt; 1275b999a6bSDavide Italiano sbintime_t tc_tick_sbt; 1285b999a6bSDavide Italiano int tc_precexp; 1295b999a6bSDavide Italiano int tc_timepercentage = TC_DEFAULTPERC; 1305b999a6bSDavide Italiano static int sysctl_kern_timecounter_adjprecision(SYSCTL_HANDLER_ARGS); 1315b999a6bSDavide Italiano SYSCTL_PROC(_kern_timecounter, OID_AUTO, alloweddeviation, 132af3b2549SHans Petter Selasky CTLTYPE_INT | CTLFLAG_RWTUN | CTLFLAG_MPSAFE, 0, 0, 1335b999a6bSDavide Italiano sysctl_kern_timecounter_adjprecision, "I", 1345b999a6bSDavide Italiano "Allowed time interval deviation in percents"); 1355b999a6bSDavide Italiano 136*e8bac3f2SIan Lepore static int tc_chosen; /* Non-zero if a specific tc was chosen via sysctl. */ 137*e8bac3f2SIan Lepore 1389e1b5510SPoul-Henning Kamp static void tc_windup(void); 139e8444a7eSPoul-Henning Kamp static void cpu_tick_calibrate(int); 1409e1b5510SPoul-Henning Kamp 14157d025c3SGeorge V. Neville-Neil void dtrace_getnanotime(struct timespec *tsp); 14257d025c3SGeorge V. Neville-Neil 143a7bc3102SPeter Wemm static int 144a7bc3102SPeter Wemm sysctl_kern_boottime(SYSCTL_HANDLER_ARGS) 145a7bc3102SPeter Wemm { 1469624d947SJuli Mallett #ifndef __mips__ 147a7bc3102SPeter Wemm #ifdef SCTL_MASK32 148a7bc3102SPeter Wemm int tv[2]; 149a7bc3102SPeter Wemm 150a7bc3102SPeter Wemm if (req->flags & SCTL_MASK32) { 151a7bc3102SPeter Wemm tv[0] = boottime.tv_sec; 152a7bc3102SPeter Wemm tv[1] = boottime.tv_usec; 153a7bc3102SPeter Wemm return SYSCTL_OUT(req, tv, sizeof(tv)); 154a7bc3102SPeter Wemm } else 155a7bc3102SPeter Wemm #endif 1569624d947SJuli Mallett #endif 157a7bc3102SPeter Wemm return SYSCTL_OUT(req, &boottime, sizeof(boottime)); 158a7bc3102SPeter Wemm } 1595b1a8eb3SPoul-Henning Kamp 16093ef14a7SDavid Malone static int 16193ef14a7SDavid Malone sysctl_kern_timecounter_get(SYSCTL_HANDLER_ARGS) 16293ef14a7SDavid Malone { 16393ef14a7SDavid Malone u_int ncount; 16493ef14a7SDavid Malone struct timecounter *tc = arg1; 16593ef14a7SDavid Malone 16693ef14a7SDavid Malone ncount = tc->tc_get_timecount(tc); 167041b706bSDavid Malone return sysctl_handle_int(oidp, &ncount, 0, req); 16893ef14a7SDavid Malone } 16993ef14a7SDavid Malone 17093ef14a7SDavid Malone static int 17193ef14a7SDavid Malone sysctl_kern_timecounter_freq(SYSCTL_HANDLER_ARGS) 17293ef14a7SDavid Malone { 17360ae52f7SEd Schouten uint64_t freq; 17493ef14a7SDavid Malone struct timecounter *tc = arg1; 17593ef14a7SDavid Malone 17693ef14a7SDavid Malone freq = tc->tc_frequency; 177cbc134adSMatthew D Fleming return sysctl_handle_64(oidp, &freq, 0, req); 17893ef14a7SDavid Malone } 17993ef14a7SDavid Malone 18039acc78aSPoul-Henning Kamp /* 18139acc78aSPoul-Henning Kamp * Return the difference between the timehands' counter value now and what 18239acc78aSPoul-Henning Kamp * was when we copied it to the timehands' offset_count. 18339acc78aSPoul-Henning Kamp */ 1846b00cf46SPoul-Henning Kamp static __inline u_int 1856b00cf46SPoul-Henning Kamp tc_delta(struct timehands *th) 186e796e00dSPoul-Henning Kamp { 1876b00cf46SPoul-Henning Kamp struct timecounter *tc; 188e796e00dSPoul-Henning Kamp 1896b00cf46SPoul-Henning Kamp tc = th->th_counter; 1906b00cf46SPoul-Henning Kamp return ((tc->tc_get_timecount(tc) - th->th_offset_count) & 1916b00cf46SPoul-Henning Kamp tc->tc_counter_mask); 192e796e00dSPoul-Henning Kamp } 193a0502b19SPoul-Henning Kamp 19439acc78aSPoul-Henning Kamp /* 1956b00cf46SPoul-Henning Kamp * Functions for reading the time. We have to loop until we are sure that 19639acc78aSPoul-Henning Kamp * the timehands that we operated on was not updated under our feet. See 19739acc78aSPoul-Henning Kamp * the comment in <sys/time.h> for a description of these 12 functions. 1986b00cf46SPoul-Henning Kamp */ 1996b00cf46SPoul-Henning Kamp 2009bce0f05SLawrence Stewart #ifdef FFCLOCK 201e977bac3SLawrence Stewart void 2029bce0f05SLawrence Stewart fbclock_binuptime(struct bintime *bt) 2039bce0f05SLawrence Stewart { 2049bce0f05SLawrence Stewart struct timehands *th; 2059bce0f05SLawrence Stewart unsigned int gen; 2069bce0f05SLawrence Stewart 2079bce0f05SLawrence Stewart do { 2089bce0f05SLawrence Stewart th = timehands; 209f4b5a972SKonstantin Belousov gen = atomic_load_acq_int(&th->th_generation); 2109bce0f05SLawrence Stewart *bt = th->th_offset; 2119bce0f05SLawrence Stewart bintime_addx(bt, th->th_scale * tc_delta(th)); 212f4b5a972SKonstantin Belousov atomic_thread_fence_acq(); 213f4b5a972SKonstantin Belousov } while (gen == 0 || gen != th->th_generation); 2149bce0f05SLawrence Stewart } 2159bce0f05SLawrence Stewart 216e977bac3SLawrence Stewart void 2179bce0f05SLawrence Stewart fbclock_nanouptime(struct timespec *tsp) 2189bce0f05SLawrence Stewart { 2199bce0f05SLawrence Stewart struct bintime bt; 2209bce0f05SLawrence Stewart 221c2a4ee99SLawrence Stewart fbclock_binuptime(&bt); 2229bce0f05SLawrence Stewart bintime2timespec(&bt, tsp); 2239bce0f05SLawrence Stewart } 2249bce0f05SLawrence Stewart 225e977bac3SLawrence Stewart void 2269bce0f05SLawrence Stewart fbclock_microuptime(struct timeval *tvp) 2279bce0f05SLawrence Stewart { 2289bce0f05SLawrence Stewart struct bintime bt; 2299bce0f05SLawrence Stewart 230c2a4ee99SLawrence Stewart fbclock_binuptime(&bt); 2319bce0f05SLawrence Stewart bintime2timeval(&bt, tvp); 2329bce0f05SLawrence Stewart } 2339bce0f05SLawrence Stewart 234e977bac3SLawrence Stewart void 2359bce0f05SLawrence Stewart fbclock_bintime(struct bintime *bt) 2369bce0f05SLawrence Stewart { 2379bce0f05SLawrence Stewart 238c2a4ee99SLawrence Stewart fbclock_binuptime(bt); 2399bce0f05SLawrence Stewart bintime_add(bt, &boottimebin); 2409bce0f05SLawrence Stewart } 2419bce0f05SLawrence Stewart 242e977bac3SLawrence Stewart void 2439bce0f05SLawrence Stewart fbclock_nanotime(struct timespec *tsp) 2449bce0f05SLawrence Stewart { 2459bce0f05SLawrence Stewart struct bintime bt; 2469bce0f05SLawrence Stewart 247c2a4ee99SLawrence Stewart fbclock_bintime(&bt); 2489bce0f05SLawrence Stewart bintime2timespec(&bt, tsp); 2499bce0f05SLawrence Stewart } 2509bce0f05SLawrence Stewart 251e977bac3SLawrence Stewart void 2529bce0f05SLawrence Stewart fbclock_microtime(struct timeval *tvp) 2539bce0f05SLawrence Stewart { 2549bce0f05SLawrence Stewart struct bintime bt; 2559bce0f05SLawrence Stewart 256c2a4ee99SLawrence Stewart fbclock_bintime(&bt); 2579bce0f05SLawrence Stewart bintime2timeval(&bt, tvp); 2589bce0f05SLawrence Stewart } 2599bce0f05SLawrence Stewart 260e977bac3SLawrence Stewart void 2619bce0f05SLawrence Stewart fbclock_getbinuptime(struct bintime *bt) 2629bce0f05SLawrence Stewart { 2639bce0f05SLawrence Stewart struct timehands *th; 2649bce0f05SLawrence Stewart unsigned int gen; 2659bce0f05SLawrence Stewart 2669bce0f05SLawrence Stewart do { 2679bce0f05SLawrence Stewart th = timehands; 268f4b5a972SKonstantin Belousov gen = atomic_load_acq_int(&th->th_generation); 2699bce0f05SLawrence Stewart *bt = th->th_offset; 270f4b5a972SKonstantin Belousov atomic_thread_fence_acq(); 271f4b5a972SKonstantin Belousov } while (gen == 0 || gen != th->th_generation); 2729bce0f05SLawrence Stewart } 2739bce0f05SLawrence Stewart 274e977bac3SLawrence Stewart void 2759bce0f05SLawrence Stewart fbclock_getnanouptime(struct timespec *tsp) 2769bce0f05SLawrence Stewart { 2779bce0f05SLawrence Stewart struct timehands *th; 2789bce0f05SLawrence Stewart unsigned int gen; 2799bce0f05SLawrence Stewart 2809bce0f05SLawrence Stewart do { 2819bce0f05SLawrence Stewart th = timehands; 282f4b5a972SKonstantin Belousov gen = atomic_load_acq_int(&th->th_generation); 2839bce0f05SLawrence Stewart bintime2timespec(&th->th_offset, tsp); 284f4b5a972SKonstantin Belousov atomic_thread_fence_acq(); 285f4b5a972SKonstantin Belousov } while (gen == 0 || gen != th->th_generation); 2869bce0f05SLawrence Stewart } 2879bce0f05SLawrence Stewart 288e977bac3SLawrence Stewart void 2899bce0f05SLawrence Stewart fbclock_getmicrouptime(struct timeval *tvp) 2909bce0f05SLawrence Stewart { 2919bce0f05SLawrence Stewart struct timehands *th; 2929bce0f05SLawrence Stewart unsigned int gen; 2939bce0f05SLawrence Stewart 2949bce0f05SLawrence Stewart do { 2959bce0f05SLawrence Stewart th = timehands; 296f4b5a972SKonstantin Belousov gen = atomic_load_acq_int(&th->th_generation); 2979bce0f05SLawrence Stewart bintime2timeval(&th->th_offset, tvp); 298f4b5a972SKonstantin Belousov atomic_thread_fence_acq(); 299f4b5a972SKonstantin Belousov } while (gen == 0 || gen != th->th_generation); 3009bce0f05SLawrence Stewart } 3019bce0f05SLawrence Stewart 302e977bac3SLawrence Stewart void 3039bce0f05SLawrence Stewart fbclock_getbintime(struct bintime *bt) 3049bce0f05SLawrence Stewart { 3059bce0f05SLawrence Stewart struct timehands *th; 3069bce0f05SLawrence Stewart unsigned int gen; 3079bce0f05SLawrence Stewart 3089bce0f05SLawrence Stewart do { 3099bce0f05SLawrence Stewart th = timehands; 310f4b5a972SKonstantin Belousov gen = atomic_load_acq_int(&th->th_generation); 3119bce0f05SLawrence Stewart *bt = th->th_offset; 312f4b5a972SKonstantin Belousov atomic_thread_fence_acq(); 313f4b5a972SKonstantin Belousov } while (gen == 0 || gen != th->th_generation); 3149bce0f05SLawrence Stewart bintime_add(bt, &boottimebin); 3159bce0f05SLawrence Stewart } 3169bce0f05SLawrence Stewart 317e977bac3SLawrence Stewart void 3189bce0f05SLawrence Stewart fbclock_getnanotime(struct timespec *tsp) 3199bce0f05SLawrence Stewart { 3209bce0f05SLawrence Stewart struct timehands *th; 3219bce0f05SLawrence Stewart unsigned int gen; 3229bce0f05SLawrence Stewart 3239bce0f05SLawrence Stewart do { 3249bce0f05SLawrence Stewart th = timehands; 325f4b5a972SKonstantin Belousov gen = atomic_load_acq_int(&th->th_generation); 3269bce0f05SLawrence Stewart *tsp = th->th_nanotime; 327f4b5a972SKonstantin Belousov atomic_thread_fence_acq(); 328f4b5a972SKonstantin Belousov } while (gen == 0 || gen != th->th_generation); 3299bce0f05SLawrence Stewart } 3309bce0f05SLawrence Stewart 331e977bac3SLawrence Stewart void 3329bce0f05SLawrence Stewart fbclock_getmicrotime(struct timeval *tvp) 3339bce0f05SLawrence Stewart { 3349bce0f05SLawrence Stewart struct timehands *th; 3359bce0f05SLawrence Stewart unsigned int gen; 3369bce0f05SLawrence Stewart 3379bce0f05SLawrence Stewart do { 3389bce0f05SLawrence Stewart th = timehands; 339f4b5a972SKonstantin Belousov gen = atomic_load_acq_int(&th->th_generation); 3409bce0f05SLawrence Stewart *tvp = th->th_microtime; 341f4b5a972SKonstantin Belousov atomic_thread_fence_acq(); 342f4b5a972SKonstantin Belousov } while (gen == 0 || gen != th->th_generation); 3439bce0f05SLawrence Stewart } 3449bce0f05SLawrence Stewart #else /* !FFCLOCK */ 345a0502b19SPoul-Henning Kamp void 3462028c0cdSPoul-Henning Kamp binuptime(struct bintime *bt) 3472028c0cdSPoul-Henning Kamp { 3486b00cf46SPoul-Henning Kamp struct timehands *th; 3496b00cf46SPoul-Henning Kamp u_int gen; 3502028c0cdSPoul-Henning Kamp 3515b7d8efaSPoul-Henning Kamp do { 3526b00cf46SPoul-Henning Kamp th = timehands; 353f4b5a972SKonstantin Belousov gen = atomic_load_acq_int(&th->th_generation); 3546b00cf46SPoul-Henning Kamp *bt = th->th_offset; 3556b00cf46SPoul-Henning Kamp bintime_addx(bt, th->th_scale * tc_delta(th)); 356f4b5a972SKonstantin Belousov atomic_thread_fence_acq(); 357f4b5a972SKonstantin Belousov } while (gen == 0 || gen != th->th_generation); 3582028c0cdSPoul-Henning Kamp } 3592028c0cdSPoul-Henning Kamp 3602028c0cdSPoul-Henning Kamp void 36139acc78aSPoul-Henning Kamp nanouptime(struct timespec *tsp) 362056abcabSPoul-Henning Kamp { 363056abcabSPoul-Henning Kamp struct bintime bt; 364056abcabSPoul-Henning Kamp 365056abcabSPoul-Henning Kamp binuptime(&bt); 36639acc78aSPoul-Henning Kamp bintime2timespec(&bt, tsp); 367056abcabSPoul-Henning Kamp } 368056abcabSPoul-Henning Kamp 369056abcabSPoul-Henning Kamp void 37039acc78aSPoul-Henning Kamp microuptime(struct timeval *tvp) 371056abcabSPoul-Henning Kamp { 372056abcabSPoul-Henning Kamp struct bintime bt; 373056abcabSPoul-Henning Kamp 374056abcabSPoul-Henning Kamp binuptime(&bt); 37539acc78aSPoul-Henning Kamp bintime2timeval(&bt, tvp); 376056abcabSPoul-Henning Kamp } 377056abcabSPoul-Henning Kamp 378056abcabSPoul-Henning Kamp void 3792028c0cdSPoul-Henning Kamp bintime(struct bintime *bt) 3802028c0cdSPoul-Henning Kamp { 3812028c0cdSPoul-Henning Kamp 3822028c0cdSPoul-Henning Kamp binuptime(bt); 3832028c0cdSPoul-Henning Kamp bintime_add(bt, &boottimebin); 3842028c0cdSPoul-Henning Kamp } 3852028c0cdSPoul-Henning Kamp 3862028c0cdSPoul-Henning Kamp void 38739acc78aSPoul-Henning Kamp nanotime(struct timespec *tsp) 38800af9731SPoul-Henning Kamp { 3892028c0cdSPoul-Henning Kamp struct bintime bt; 39000af9731SPoul-Henning Kamp 3912028c0cdSPoul-Henning Kamp bintime(&bt); 39239acc78aSPoul-Henning Kamp bintime2timespec(&bt, tsp); 39348115288SPoul-Henning Kamp } 39448115288SPoul-Henning Kamp 39548115288SPoul-Henning Kamp void 39639acc78aSPoul-Henning Kamp microtime(struct timeval *tvp) 397056abcabSPoul-Henning Kamp { 398056abcabSPoul-Henning Kamp struct bintime bt; 399056abcabSPoul-Henning Kamp 400056abcabSPoul-Henning Kamp bintime(&bt); 40139acc78aSPoul-Henning Kamp bintime2timeval(&bt, tvp); 402056abcabSPoul-Henning Kamp } 403056abcabSPoul-Henning Kamp 404056abcabSPoul-Henning Kamp void 405056abcabSPoul-Henning Kamp getbinuptime(struct bintime *bt) 40600af9731SPoul-Henning Kamp { 4076b00cf46SPoul-Henning Kamp struct timehands *th; 4086b00cf46SPoul-Henning Kamp u_int gen; 40900af9731SPoul-Henning Kamp 4105b7d8efaSPoul-Henning Kamp do { 4116b00cf46SPoul-Henning Kamp th = timehands; 412f4b5a972SKonstantin Belousov gen = atomic_load_acq_int(&th->th_generation); 4136b00cf46SPoul-Henning Kamp *bt = th->th_offset; 414f4b5a972SKonstantin Belousov atomic_thread_fence_acq(); 415f4b5a972SKonstantin Belousov } while (gen == 0 || gen != th->th_generation); 416a0502b19SPoul-Henning Kamp } 417a0502b19SPoul-Henning Kamp 418a0502b19SPoul-Henning Kamp void 419c21410e1SPoul-Henning Kamp getnanouptime(struct timespec *tsp) 420a0502b19SPoul-Henning Kamp { 4216b00cf46SPoul-Henning Kamp struct timehands *th; 4226b00cf46SPoul-Henning Kamp u_int gen; 423a0502b19SPoul-Henning Kamp 4245b7d8efaSPoul-Henning Kamp do { 4256b00cf46SPoul-Henning Kamp th = timehands; 426f4b5a972SKonstantin Belousov gen = atomic_load_acq_int(&th->th_generation); 4276b00cf46SPoul-Henning Kamp bintime2timespec(&th->th_offset, tsp); 428f4b5a972SKonstantin Belousov atomic_thread_fence_acq(); 429f4b5a972SKonstantin Belousov } while (gen == 0 || gen != th->th_generation); 430a0502b19SPoul-Henning Kamp } 431a0502b19SPoul-Henning Kamp 432c7c9a816SPoul-Henning Kamp void 433056abcabSPoul-Henning Kamp getmicrouptime(struct timeval *tvp) 434c7c9a816SPoul-Henning Kamp { 4356b00cf46SPoul-Henning Kamp struct timehands *th; 4366b00cf46SPoul-Henning Kamp u_int gen; 4377ec73f64SPoul-Henning Kamp 438056abcabSPoul-Henning Kamp do { 4396b00cf46SPoul-Henning Kamp th = timehands; 440f4b5a972SKonstantin Belousov gen = atomic_load_acq_int(&th->th_generation); 4416b00cf46SPoul-Henning Kamp bintime2timeval(&th->th_offset, tvp); 442f4b5a972SKonstantin Belousov atomic_thread_fence_acq(); 443f4b5a972SKonstantin Belousov } while (gen == 0 || gen != th->th_generation); 4447ec73f64SPoul-Henning Kamp } 4457ec73f64SPoul-Henning Kamp 4467ec73f64SPoul-Henning Kamp void 447056abcabSPoul-Henning Kamp getbintime(struct bintime *bt) 4487ec73f64SPoul-Henning Kamp { 4496b00cf46SPoul-Henning Kamp struct timehands *th; 4506b00cf46SPoul-Henning Kamp u_int gen; 4517ec73f64SPoul-Henning Kamp 452056abcabSPoul-Henning Kamp do { 4536b00cf46SPoul-Henning Kamp th = timehands; 454f4b5a972SKonstantin Belousov gen = atomic_load_acq_int(&th->th_generation); 4556b00cf46SPoul-Henning Kamp *bt = th->th_offset; 456f4b5a972SKonstantin Belousov atomic_thread_fence_acq(); 457f4b5a972SKonstantin Belousov } while (gen == 0 || gen != th->th_generation); 458056abcabSPoul-Henning Kamp bintime_add(bt, &boottimebin); 459056abcabSPoul-Henning Kamp } 460056abcabSPoul-Henning Kamp 461056abcabSPoul-Henning Kamp void 462056abcabSPoul-Henning Kamp getnanotime(struct timespec *tsp) 463056abcabSPoul-Henning Kamp { 4646b00cf46SPoul-Henning Kamp struct timehands *th; 4656b00cf46SPoul-Henning Kamp u_int gen; 466056abcabSPoul-Henning Kamp 467056abcabSPoul-Henning Kamp do { 4686b00cf46SPoul-Henning Kamp th = timehands; 469f4b5a972SKonstantin Belousov gen = atomic_load_acq_int(&th->th_generation); 4706b00cf46SPoul-Henning Kamp *tsp = th->th_nanotime; 471f4b5a972SKonstantin Belousov atomic_thread_fence_acq(); 472f4b5a972SKonstantin Belousov } while (gen == 0 || gen != th->th_generation); 473056abcabSPoul-Henning Kamp } 474056abcabSPoul-Henning Kamp 475056abcabSPoul-Henning Kamp void 476056abcabSPoul-Henning Kamp getmicrotime(struct timeval *tvp) 477056abcabSPoul-Henning Kamp { 4786b00cf46SPoul-Henning Kamp struct timehands *th; 4796b00cf46SPoul-Henning Kamp u_int gen; 480056abcabSPoul-Henning Kamp 481056abcabSPoul-Henning Kamp do { 4826b00cf46SPoul-Henning Kamp th = timehands; 483f4b5a972SKonstantin Belousov gen = atomic_load_acq_int(&th->th_generation); 4846b00cf46SPoul-Henning Kamp *tvp = th->th_microtime; 485f4b5a972SKonstantin Belousov atomic_thread_fence_acq(); 486f4b5a972SKonstantin Belousov } while (gen == 0 || gen != th->th_generation); 4877ec73f64SPoul-Henning Kamp } 4889bce0f05SLawrence Stewart #endif /* FFCLOCK */ 4897ec73f64SPoul-Henning Kamp 490b0fdc837SLawrence Stewart #ifdef FFCLOCK 491b0fdc837SLawrence Stewart /* 492b0fdc837SLawrence Stewart * Support for feed-forward synchronization algorithms. This is heavily inspired 493b0fdc837SLawrence Stewart * by the timehands mechanism but kept independent from it. *_windup() functions 494b0fdc837SLawrence Stewart * have some connection to avoid accessing the timecounter hardware more than 495b0fdc837SLawrence Stewart * necessary. 496b0fdc837SLawrence Stewart */ 497b0fdc837SLawrence Stewart 498b0fdc837SLawrence Stewart /* Feed-forward clock estimates kept updated by the synchronization daemon. */ 499b0fdc837SLawrence Stewart struct ffclock_estimate ffclock_estimate; 500b0fdc837SLawrence Stewart struct bintime ffclock_boottime; /* Feed-forward boot time estimate. */ 501b0fdc837SLawrence Stewart uint32_t ffclock_status; /* Feed-forward clock status. */ 502b0fdc837SLawrence Stewart int8_t ffclock_updated; /* New estimates are available. */ 503b0fdc837SLawrence Stewart struct mtx ffclock_mtx; /* Mutex on ffclock_estimate. */ 504b0fdc837SLawrence Stewart 505b0fdc837SLawrence Stewart struct fftimehands { 506b0fdc837SLawrence Stewart struct ffclock_estimate cest; 507b0fdc837SLawrence Stewart struct bintime tick_time; 508b0fdc837SLawrence Stewart struct bintime tick_time_lerp; 509b0fdc837SLawrence Stewart ffcounter tick_ffcount; 510b0fdc837SLawrence Stewart uint64_t period_lerp; 511b0fdc837SLawrence Stewart volatile uint8_t gen; 512b0fdc837SLawrence Stewart struct fftimehands *next; 513b0fdc837SLawrence Stewart }; 514b0fdc837SLawrence Stewart 515b0fdc837SLawrence Stewart #define NUM_ELEMENTS(x) (sizeof(x) / sizeof(*x)) 516b0fdc837SLawrence Stewart 517b0fdc837SLawrence Stewart static struct fftimehands ffth[10]; 518b0fdc837SLawrence Stewart static struct fftimehands *volatile fftimehands = ffth; 519b0fdc837SLawrence Stewart 520b0fdc837SLawrence Stewart static void 521b0fdc837SLawrence Stewart ffclock_init(void) 522b0fdc837SLawrence Stewart { 523b0fdc837SLawrence Stewart struct fftimehands *cur; 524b0fdc837SLawrence Stewart struct fftimehands *last; 525b0fdc837SLawrence Stewart 526b0fdc837SLawrence Stewart memset(ffth, 0, sizeof(ffth)); 527b0fdc837SLawrence Stewart 528b0fdc837SLawrence Stewart last = ffth + NUM_ELEMENTS(ffth) - 1; 529b0fdc837SLawrence Stewart for (cur = ffth; cur < last; cur++) 530b0fdc837SLawrence Stewart cur->next = cur + 1; 531b0fdc837SLawrence Stewart last->next = ffth; 532b0fdc837SLawrence Stewart 533b0fdc837SLawrence Stewart ffclock_updated = 0; 534b0fdc837SLawrence Stewart ffclock_status = FFCLOCK_STA_UNSYNC; 535b0fdc837SLawrence Stewart mtx_init(&ffclock_mtx, "ffclock lock", NULL, MTX_DEF); 536b0fdc837SLawrence Stewart } 537b0fdc837SLawrence Stewart 538b0fdc837SLawrence Stewart /* 539b0fdc837SLawrence Stewart * Reset the feed-forward clock estimates. Called from inittodr() to get things 540b0fdc837SLawrence Stewart * kick started and uses the timecounter nominal frequency as a first period 541b0fdc837SLawrence Stewart * estimate. Note: this function may be called several time just after boot. 542b0fdc837SLawrence Stewart * Note: this is the only function that sets the value of boot time for the 543b0fdc837SLawrence Stewart * monotonic (i.e. uptime) version of the feed-forward clock. 544b0fdc837SLawrence Stewart */ 545b0fdc837SLawrence Stewart void 546b0fdc837SLawrence Stewart ffclock_reset_clock(struct timespec *ts) 547b0fdc837SLawrence Stewart { 548b0fdc837SLawrence Stewart struct timecounter *tc; 549b0fdc837SLawrence Stewart struct ffclock_estimate cest; 550b0fdc837SLawrence Stewart 551b0fdc837SLawrence Stewart tc = timehands->th_counter; 552b0fdc837SLawrence Stewart memset(&cest, 0, sizeof(struct ffclock_estimate)); 553b0fdc837SLawrence Stewart 554b0fdc837SLawrence Stewart timespec2bintime(ts, &ffclock_boottime); 555b0fdc837SLawrence Stewart timespec2bintime(ts, &(cest.update_time)); 556b0fdc837SLawrence Stewart ffclock_read_counter(&cest.update_ffcount); 557b0fdc837SLawrence Stewart cest.leapsec_next = 0; 558b0fdc837SLawrence Stewart cest.period = ((1ULL << 63) / tc->tc_frequency) << 1; 559b0fdc837SLawrence Stewart cest.errb_abs = 0; 560b0fdc837SLawrence Stewart cest.errb_rate = 0; 561b0fdc837SLawrence Stewart cest.status = FFCLOCK_STA_UNSYNC; 562b0fdc837SLawrence Stewart cest.leapsec_total = 0; 563b0fdc837SLawrence Stewart cest.leapsec = 0; 564b0fdc837SLawrence Stewart 565b0fdc837SLawrence Stewart mtx_lock(&ffclock_mtx); 566b0fdc837SLawrence Stewart bcopy(&cest, &ffclock_estimate, sizeof(struct ffclock_estimate)); 567b0fdc837SLawrence Stewart ffclock_updated = INT8_MAX; 568b0fdc837SLawrence Stewart mtx_unlock(&ffclock_mtx); 569b0fdc837SLawrence Stewart 570b0fdc837SLawrence Stewart printf("ffclock reset: %s (%llu Hz), time = %ld.%09lu\n", tc->tc_name, 571b0fdc837SLawrence Stewart (unsigned long long)tc->tc_frequency, (long)ts->tv_sec, 572b0fdc837SLawrence Stewart (unsigned long)ts->tv_nsec); 573b0fdc837SLawrence Stewart } 574b0fdc837SLawrence Stewart 575b0fdc837SLawrence Stewart /* 576b0fdc837SLawrence Stewart * Sub-routine to convert a time interval measured in RAW counter units to time 577b0fdc837SLawrence Stewart * in seconds stored in bintime format. 578b0fdc837SLawrence Stewart * NOTE: bintime_mul requires u_int, but the value of the ffcounter may be 579b0fdc837SLawrence Stewart * larger than the max value of u_int (on 32 bit architecture). Loop to consume 580b0fdc837SLawrence Stewart * extra cycles. 581b0fdc837SLawrence Stewart */ 582b0fdc837SLawrence Stewart static void 583b0fdc837SLawrence Stewart ffclock_convert_delta(ffcounter ffdelta, uint64_t period, struct bintime *bt) 584b0fdc837SLawrence Stewart { 585b0fdc837SLawrence Stewart struct bintime bt2; 586b0fdc837SLawrence Stewart ffcounter delta, delta_max; 587b0fdc837SLawrence Stewart 588b0fdc837SLawrence Stewart delta_max = (1ULL << (8 * sizeof(unsigned int))) - 1; 589b0fdc837SLawrence Stewart bintime_clear(bt); 590b0fdc837SLawrence Stewart do { 591b0fdc837SLawrence Stewart if (ffdelta > delta_max) 592b0fdc837SLawrence Stewart delta = delta_max; 593b0fdc837SLawrence Stewart else 594b0fdc837SLawrence Stewart delta = ffdelta; 595b0fdc837SLawrence Stewart bt2.sec = 0; 596b0fdc837SLawrence Stewart bt2.frac = period; 597b0fdc837SLawrence Stewart bintime_mul(&bt2, (unsigned int)delta); 598b0fdc837SLawrence Stewart bintime_add(bt, &bt2); 599b0fdc837SLawrence Stewart ffdelta -= delta; 600b0fdc837SLawrence Stewart } while (ffdelta > 0); 601b0fdc837SLawrence Stewart } 602b0fdc837SLawrence Stewart 603b0fdc837SLawrence Stewart /* 604b0fdc837SLawrence Stewart * Update the fftimehands. 605b0fdc837SLawrence Stewart * Push the tick ffcount and time(s) forward based on current clock estimate. 606b0fdc837SLawrence Stewart * The conversion from ffcounter to bintime relies on the difference clock 607b0fdc837SLawrence Stewart * principle, whose accuracy relies on computing small time intervals. If a new 608b0fdc837SLawrence Stewart * clock estimate has been passed by the synchronisation daemon, make it 609b0fdc837SLawrence Stewart * current, and compute the linear interpolation for monotonic time if needed. 610b0fdc837SLawrence Stewart */ 611b0fdc837SLawrence Stewart static void 612b0fdc837SLawrence Stewart ffclock_windup(unsigned int delta) 613b0fdc837SLawrence Stewart { 614b0fdc837SLawrence Stewart struct ffclock_estimate *cest; 615b0fdc837SLawrence Stewart struct fftimehands *ffth; 616b0fdc837SLawrence Stewart struct bintime bt, gap_lerp; 617b0fdc837SLawrence Stewart ffcounter ffdelta; 618b0fdc837SLawrence Stewart uint64_t frac; 619b0fdc837SLawrence Stewart unsigned int polling; 620b0fdc837SLawrence Stewart uint8_t forward_jump, ogen; 621b0fdc837SLawrence Stewart 622b0fdc837SLawrence Stewart /* 623b0fdc837SLawrence Stewart * Pick the next timehand, copy current ffclock estimates and move tick 624b0fdc837SLawrence Stewart * times and counter forward. 625b0fdc837SLawrence Stewart */ 626b0fdc837SLawrence Stewart forward_jump = 0; 627b0fdc837SLawrence Stewart ffth = fftimehands->next; 628b0fdc837SLawrence Stewart ogen = ffth->gen; 629b0fdc837SLawrence Stewart ffth->gen = 0; 630b0fdc837SLawrence Stewart cest = &ffth->cest; 631b0fdc837SLawrence Stewart bcopy(&fftimehands->cest, cest, sizeof(struct ffclock_estimate)); 632b0fdc837SLawrence Stewart ffdelta = (ffcounter)delta; 633b0fdc837SLawrence Stewart ffth->period_lerp = fftimehands->period_lerp; 634b0fdc837SLawrence Stewart 635b0fdc837SLawrence Stewart ffth->tick_time = fftimehands->tick_time; 636b0fdc837SLawrence Stewart ffclock_convert_delta(ffdelta, cest->period, &bt); 637b0fdc837SLawrence Stewart bintime_add(&ffth->tick_time, &bt); 638b0fdc837SLawrence Stewart 639b0fdc837SLawrence Stewart ffth->tick_time_lerp = fftimehands->tick_time_lerp; 640b0fdc837SLawrence Stewart ffclock_convert_delta(ffdelta, ffth->period_lerp, &bt); 641b0fdc837SLawrence Stewart bintime_add(&ffth->tick_time_lerp, &bt); 642b0fdc837SLawrence Stewart 643b0fdc837SLawrence Stewart ffth->tick_ffcount = fftimehands->tick_ffcount + ffdelta; 644b0fdc837SLawrence Stewart 645b0fdc837SLawrence Stewart /* 646b0fdc837SLawrence Stewart * Assess the status of the clock, if the last update is too old, it is 647b0fdc837SLawrence Stewart * likely the synchronisation daemon is dead and the clock is free 648b0fdc837SLawrence Stewart * running. 649b0fdc837SLawrence Stewart */ 650b0fdc837SLawrence Stewart if (ffclock_updated == 0) { 651b0fdc837SLawrence Stewart ffdelta = ffth->tick_ffcount - cest->update_ffcount; 652b0fdc837SLawrence Stewart ffclock_convert_delta(ffdelta, cest->period, &bt); 653b0fdc837SLawrence Stewart if (bt.sec > 2 * FFCLOCK_SKM_SCALE) 654b0fdc837SLawrence Stewart ffclock_status |= FFCLOCK_STA_UNSYNC; 655b0fdc837SLawrence Stewart } 656b0fdc837SLawrence Stewart 657b0fdc837SLawrence Stewart /* 658b0fdc837SLawrence Stewart * If available, grab updated clock estimates and make them current. 659b0fdc837SLawrence Stewart * Recompute time at this tick using the updated estimates. The clock 660b0fdc837SLawrence Stewart * estimates passed the feed-forward synchronisation daemon may result 661b0fdc837SLawrence Stewart * in time conversion that is not monotonically increasing (just after 662b0fdc837SLawrence Stewart * the update). time_lerp is a particular linear interpolation over the 663b0fdc837SLawrence Stewart * synchronisation algo polling period that ensures monotonicity for the 664b0fdc837SLawrence Stewart * clock ids requesting it. 665b0fdc837SLawrence Stewart */ 666b0fdc837SLawrence Stewart if (ffclock_updated > 0) { 667b0fdc837SLawrence Stewart bcopy(&ffclock_estimate, cest, sizeof(struct ffclock_estimate)); 668b0fdc837SLawrence Stewart ffdelta = ffth->tick_ffcount - cest->update_ffcount; 669b0fdc837SLawrence Stewart ffth->tick_time = cest->update_time; 670b0fdc837SLawrence Stewart ffclock_convert_delta(ffdelta, cest->period, &bt); 671b0fdc837SLawrence Stewart bintime_add(&ffth->tick_time, &bt); 672b0fdc837SLawrence Stewart 673b0fdc837SLawrence Stewart /* ffclock_reset sets ffclock_updated to INT8_MAX */ 674b0fdc837SLawrence Stewart if (ffclock_updated == INT8_MAX) 675b0fdc837SLawrence Stewart ffth->tick_time_lerp = ffth->tick_time; 676b0fdc837SLawrence Stewart 677b0fdc837SLawrence Stewart if (bintime_cmp(&ffth->tick_time, &ffth->tick_time_lerp, >)) 678b0fdc837SLawrence Stewart forward_jump = 1; 679b0fdc837SLawrence Stewart else 680b0fdc837SLawrence Stewart forward_jump = 0; 681b0fdc837SLawrence Stewart 682b0fdc837SLawrence Stewart bintime_clear(&gap_lerp); 683b0fdc837SLawrence Stewart if (forward_jump) { 684b0fdc837SLawrence Stewart gap_lerp = ffth->tick_time; 685b0fdc837SLawrence Stewart bintime_sub(&gap_lerp, &ffth->tick_time_lerp); 686b0fdc837SLawrence Stewart } else { 687b0fdc837SLawrence Stewart gap_lerp = ffth->tick_time_lerp; 688b0fdc837SLawrence Stewart bintime_sub(&gap_lerp, &ffth->tick_time); 689b0fdc837SLawrence Stewart } 690b0fdc837SLawrence Stewart 691b0fdc837SLawrence Stewart /* 692b0fdc837SLawrence Stewart * The reset from the RTC clock may be far from accurate, and 693b0fdc837SLawrence Stewart * reducing the gap between real time and interpolated time 694b0fdc837SLawrence Stewart * could take a very long time if the interpolated clock insists 695b0fdc837SLawrence Stewart * on strict monotonicity. The clock is reset under very strict 696b0fdc837SLawrence Stewart * conditions (kernel time is known to be wrong and 697b0fdc837SLawrence Stewart * synchronization daemon has been restarted recently. 698b0fdc837SLawrence Stewart * ffclock_boottime absorbs the jump to ensure boot time is 699b0fdc837SLawrence Stewart * correct and uptime functions stay consistent. 700b0fdc837SLawrence Stewart */ 701b0fdc837SLawrence Stewart if (((ffclock_status & FFCLOCK_STA_UNSYNC) == FFCLOCK_STA_UNSYNC) && 702b0fdc837SLawrence Stewart ((cest->status & FFCLOCK_STA_UNSYNC) == 0) && 703b0fdc837SLawrence Stewart ((cest->status & FFCLOCK_STA_WARMUP) == FFCLOCK_STA_WARMUP)) { 704b0fdc837SLawrence Stewart if (forward_jump) 705b0fdc837SLawrence Stewart bintime_add(&ffclock_boottime, &gap_lerp); 706b0fdc837SLawrence Stewart else 707b0fdc837SLawrence Stewart bintime_sub(&ffclock_boottime, &gap_lerp); 708b0fdc837SLawrence Stewart ffth->tick_time_lerp = ffth->tick_time; 709b0fdc837SLawrence Stewart bintime_clear(&gap_lerp); 710b0fdc837SLawrence Stewart } 711b0fdc837SLawrence Stewart 712b0fdc837SLawrence Stewart ffclock_status = cest->status; 713b0fdc837SLawrence Stewart ffth->period_lerp = cest->period; 714b0fdc837SLawrence Stewart 715b0fdc837SLawrence Stewart /* 716b0fdc837SLawrence Stewart * Compute corrected period used for the linear interpolation of 717b0fdc837SLawrence Stewart * time. The rate of linear interpolation is capped to 5000PPM 718b0fdc837SLawrence Stewart * (5ms/s). 719b0fdc837SLawrence Stewart */ 720b0fdc837SLawrence Stewart if (bintime_isset(&gap_lerp)) { 721b0fdc837SLawrence Stewart ffdelta = cest->update_ffcount; 722b0fdc837SLawrence Stewart ffdelta -= fftimehands->cest.update_ffcount; 723b0fdc837SLawrence Stewart ffclock_convert_delta(ffdelta, cest->period, &bt); 724b0fdc837SLawrence Stewart polling = bt.sec; 725b0fdc837SLawrence Stewart bt.sec = 0; 726b0fdc837SLawrence Stewart bt.frac = 5000000 * (uint64_t)18446744073LL; 727b0fdc837SLawrence Stewart bintime_mul(&bt, polling); 728b0fdc837SLawrence Stewart if (bintime_cmp(&gap_lerp, &bt, >)) 729b0fdc837SLawrence Stewart gap_lerp = bt; 730b0fdc837SLawrence Stewart 731b0fdc837SLawrence Stewart /* Approximate 1 sec by 1-(1/2^64) to ease arithmetic */ 732b0fdc837SLawrence Stewart frac = 0; 733b0fdc837SLawrence Stewart if (gap_lerp.sec > 0) { 734b0fdc837SLawrence Stewart frac -= 1; 735b0fdc837SLawrence Stewart frac /= ffdelta / gap_lerp.sec; 736b0fdc837SLawrence Stewart } 737b0fdc837SLawrence Stewart frac += gap_lerp.frac / ffdelta; 738b0fdc837SLawrence Stewart 739b0fdc837SLawrence Stewart if (forward_jump) 740b0fdc837SLawrence Stewart ffth->period_lerp += frac; 741b0fdc837SLawrence Stewart else 742b0fdc837SLawrence Stewart ffth->period_lerp -= frac; 743b0fdc837SLawrence Stewart } 744b0fdc837SLawrence Stewart 745b0fdc837SLawrence Stewart ffclock_updated = 0; 746b0fdc837SLawrence Stewart } 747b0fdc837SLawrence Stewart if (++ogen == 0) 748b0fdc837SLawrence Stewart ogen = 1; 749b0fdc837SLawrence Stewart ffth->gen = ogen; 750b0fdc837SLawrence Stewart fftimehands = ffth; 751b0fdc837SLawrence Stewart } 752b0fdc837SLawrence Stewart 753b0fdc837SLawrence Stewart /* 754b0fdc837SLawrence Stewart * Adjust the fftimehands when the timecounter is changed. Stating the obvious, 755b0fdc837SLawrence Stewart * the old and new hardware counter cannot be read simultaneously. tc_windup() 756b0fdc837SLawrence Stewart * does read the two counters 'back to back', but a few cycles are effectively 757b0fdc837SLawrence Stewart * lost, and not accumulated in tick_ffcount. This is a fairly radical 758b0fdc837SLawrence Stewart * operation for a feed-forward synchronization daemon, and it is its job to not 759b0fdc837SLawrence Stewart * pushing irrelevant data to the kernel. Because there is no locking here, 760b0fdc837SLawrence Stewart * simply force to ignore pending or next update to give daemon a chance to 761b0fdc837SLawrence Stewart * realize the counter has changed. 762b0fdc837SLawrence Stewart */ 763b0fdc837SLawrence Stewart static void 764b0fdc837SLawrence Stewart ffclock_change_tc(struct timehands *th) 765b0fdc837SLawrence Stewart { 766b0fdc837SLawrence Stewart struct fftimehands *ffth; 767b0fdc837SLawrence Stewart struct ffclock_estimate *cest; 768b0fdc837SLawrence Stewart struct timecounter *tc; 769b0fdc837SLawrence Stewart uint8_t ogen; 770b0fdc837SLawrence Stewart 771b0fdc837SLawrence Stewart tc = th->th_counter; 772b0fdc837SLawrence Stewart ffth = fftimehands->next; 773b0fdc837SLawrence Stewart ogen = ffth->gen; 774b0fdc837SLawrence Stewart ffth->gen = 0; 775b0fdc837SLawrence Stewart 776b0fdc837SLawrence Stewart cest = &ffth->cest; 777b0fdc837SLawrence Stewart bcopy(&(fftimehands->cest), cest, sizeof(struct ffclock_estimate)); 778b0fdc837SLawrence Stewart cest->period = ((1ULL << 63) / tc->tc_frequency ) << 1; 779b0fdc837SLawrence Stewart cest->errb_abs = 0; 780b0fdc837SLawrence Stewart cest->errb_rate = 0; 781b0fdc837SLawrence Stewart cest->status |= FFCLOCK_STA_UNSYNC; 782b0fdc837SLawrence Stewart 783b0fdc837SLawrence Stewart ffth->tick_ffcount = fftimehands->tick_ffcount; 784b0fdc837SLawrence Stewart ffth->tick_time_lerp = fftimehands->tick_time_lerp; 785b0fdc837SLawrence Stewart ffth->tick_time = fftimehands->tick_time; 786b0fdc837SLawrence Stewart ffth->period_lerp = cest->period; 787b0fdc837SLawrence Stewart 788b0fdc837SLawrence Stewart /* Do not lock but ignore next update from synchronization daemon. */ 789b0fdc837SLawrence Stewart ffclock_updated--; 790b0fdc837SLawrence Stewart 791b0fdc837SLawrence Stewart if (++ogen == 0) 792b0fdc837SLawrence Stewart ogen = 1; 793b0fdc837SLawrence Stewart ffth->gen = ogen; 794b0fdc837SLawrence Stewart fftimehands = ffth; 795b0fdc837SLawrence Stewart } 796b0fdc837SLawrence Stewart 797b0fdc837SLawrence Stewart /* 798b0fdc837SLawrence Stewart * Retrieve feed-forward counter and time of last kernel tick. 799b0fdc837SLawrence Stewart */ 800b0fdc837SLawrence Stewart void 801b0fdc837SLawrence Stewart ffclock_last_tick(ffcounter *ffcount, struct bintime *bt, uint32_t flags) 802b0fdc837SLawrence Stewart { 803b0fdc837SLawrence Stewart struct fftimehands *ffth; 804b0fdc837SLawrence Stewart uint8_t gen; 805b0fdc837SLawrence Stewart 806b0fdc837SLawrence Stewart /* 807b0fdc837SLawrence Stewart * No locking but check generation has not changed. Also need to make 808b0fdc837SLawrence Stewart * sure ffdelta is positive, i.e. ffcount > tick_ffcount. 809b0fdc837SLawrence Stewart */ 810b0fdc837SLawrence Stewart do { 811b0fdc837SLawrence Stewart ffth = fftimehands; 812b0fdc837SLawrence Stewart gen = ffth->gen; 813b0fdc837SLawrence Stewart if ((flags & FFCLOCK_LERP) == FFCLOCK_LERP) 814b0fdc837SLawrence Stewart *bt = ffth->tick_time_lerp; 815b0fdc837SLawrence Stewart else 816b0fdc837SLawrence Stewart *bt = ffth->tick_time; 817b0fdc837SLawrence Stewart *ffcount = ffth->tick_ffcount; 818b0fdc837SLawrence Stewart } while (gen == 0 || gen != ffth->gen); 819b0fdc837SLawrence Stewart } 820b0fdc837SLawrence Stewart 821b0fdc837SLawrence Stewart /* 822b0fdc837SLawrence Stewart * Absolute clock conversion. Low level function to convert ffcounter to 823b0fdc837SLawrence Stewart * bintime. The ffcounter is converted using the current ffclock period estimate 824b0fdc837SLawrence Stewart * or the "interpolated period" to ensure monotonicity. 825b0fdc837SLawrence Stewart * NOTE: this conversion may have been deferred, and the clock updated since the 826b0fdc837SLawrence Stewart * hardware counter has been read. 827b0fdc837SLawrence Stewart */ 828b0fdc837SLawrence Stewart void 829b0fdc837SLawrence Stewart ffclock_convert_abs(ffcounter ffcount, struct bintime *bt, uint32_t flags) 830b0fdc837SLawrence Stewart { 831b0fdc837SLawrence Stewart struct fftimehands *ffth; 832b0fdc837SLawrence Stewart struct bintime bt2; 833b0fdc837SLawrence Stewart ffcounter ffdelta; 834b0fdc837SLawrence Stewart uint8_t gen; 835b0fdc837SLawrence Stewart 836b0fdc837SLawrence Stewart /* 837b0fdc837SLawrence Stewart * No locking but check generation has not changed. Also need to make 838b0fdc837SLawrence Stewart * sure ffdelta is positive, i.e. ffcount > tick_ffcount. 839b0fdc837SLawrence Stewart */ 840b0fdc837SLawrence Stewart do { 841b0fdc837SLawrence Stewart ffth = fftimehands; 842b0fdc837SLawrence Stewart gen = ffth->gen; 843b0fdc837SLawrence Stewart if (ffcount > ffth->tick_ffcount) 844b0fdc837SLawrence Stewart ffdelta = ffcount - ffth->tick_ffcount; 845b0fdc837SLawrence Stewart else 846b0fdc837SLawrence Stewart ffdelta = ffth->tick_ffcount - ffcount; 847b0fdc837SLawrence Stewart 848b0fdc837SLawrence Stewart if ((flags & FFCLOCK_LERP) == FFCLOCK_LERP) { 849b0fdc837SLawrence Stewart *bt = ffth->tick_time_lerp; 850b0fdc837SLawrence Stewart ffclock_convert_delta(ffdelta, ffth->period_lerp, &bt2); 851b0fdc837SLawrence Stewart } else { 852b0fdc837SLawrence Stewart *bt = ffth->tick_time; 853b0fdc837SLawrence Stewart ffclock_convert_delta(ffdelta, ffth->cest.period, &bt2); 854b0fdc837SLawrence Stewart } 855b0fdc837SLawrence Stewart 856b0fdc837SLawrence Stewart if (ffcount > ffth->tick_ffcount) 857b0fdc837SLawrence Stewart bintime_add(bt, &bt2); 858b0fdc837SLawrence Stewart else 859b0fdc837SLawrence Stewart bintime_sub(bt, &bt2); 860b0fdc837SLawrence Stewart } while (gen == 0 || gen != ffth->gen); 861b0fdc837SLawrence Stewart } 862b0fdc837SLawrence Stewart 863b0fdc837SLawrence Stewart /* 864b0fdc837SLawrence Stewart * Difference clock conversion. 865b0fdc837SLawrence Stewart * Low level function to Convert a time interval measured in RAW counter units 866b0fdc837SLawrence Stewart * into bintime. The difference clock allows measuring small intervals much more 867b0fdc837SLawrence Stewart * reliably than the absolute clock. 868b0fdc837SLawrence Stewart */ 869b0fdc837SLawrence Stewart void 870b0fdc837SLawrence Stewart ffclock_convert_diff(ffcounter ffdelta, struct bintime *bt) 871b0fdc837SLawrence Stewart { 872b0fdc837SLawrence Stewart struct fftimehands *ffth; 873b0fdc837SLawrence Stewart uint8_t gen; 874b0fdc837SLawrence Stewart 875b0fdc837SLawrence Stewart /* No locking but check generation has not changed. */ 876b0fdc837SLawrence Stewart do { 877b0fdc837SLawrence Stewart ffth = fftimehands; 878b0fdc837SLawrence Stewart gen = ffth->gen; 879b0fdc837SLawrence Stewart ffclock_convert_delta(ffdelta, ffth->cest.period, bt); 880b0fdc837SLawrence Stewart } while (gen == 0 || gen != ffth->gen); 881b0fdc837SLawrence Stewart } 882b0fdc837SLawrence Stewart 883b0fdc837SLawrence Stewart /* 884b0fdc837SLawrence Stewart * Access to current ffcounter value. 885b0fdc837SLawrence Stewart */ 886b0fdc837SLawrence Stewart void 887b0fdc837SLawrence Stewart ffclock_read_counter(ffcounter *ffcount) 888b0fdc837SLawrence Stewart { 889b0fdc837SLawrence Stewart struct timehands *th; 890b0fdc837SLawrence Stewart struct fftimehands *ffth; 891b0fdc837SLawrence Stewart unsigned int gen, delta; 892b0fdc837SLawrence Stewart 893b0fdc837SLawrence Stewart /* 894b0fdc837SLawrence Stewart * ffclock_windup() called from tc_windup(), safe to rely on 895b0fdc837SLawrence Stewart * th->th_generation only, for correct delta and ffcounter. 896b0fdc837SLawrence Stewart */ 897b0fdc837SLawrence Stewart do { 898b0fdc837SLawrence Stewart th = timehands; 899f4b5a972SKonstantin Belousov gen = atomic_load_acq_int(&th->th_generation); 900b0fdc837SLawrence Stewart ffth = fftimehands; 901b0fdc837SLawrence Stewart delta = tc_delta(th); 902b0fdc837SLawrence Stewart *ffcount = ffth->tick_ffcount; 903f4b5a972SKonstantin Belousov atomic_thread_fence_acq(); 904f4b5a972SKonstantin Belousov } while (gen == 0 || gen != th->th_generation); 905b0fdc837SLawrence Stewart 906b0fdc837SLawrence Stewart *ffcount += delta; 907b0fdc837SLawrence Stewart } 9089bce0f05SLawrence Stewart 9099bce0f05SLawrence Stewart void 9109bce0f05SLawrence Stewart binuptime(struct bintime *bt) 9119bce0f05SLawrence Stewart { 9129bce0f05SLawrence Stewart 91388394fe4SLawrence Stewart binuptime_fromclock(bt, sysclock_active); 9149bce0f05SLawrence Stewart } 9159bce0f05SLawrence Stewart 9169bce0f05SLawrence Stewart void 9179bce0f05SLawrence Stewart nanouptime(struct timespec *tsp) 9189bce0f05SLawrence Stewart { 9199bce0f05SLawrence Stewart 92088394fe4SLawrence Stewart nanouptime_fromclock(tsp, sysclock_active); 9219bce0f05SLawrence Stewart } 9229bce0f05SLawrence Stewart 9239bce0f05SLawrence Stewart void 9249bce0f05SLawrence Stewart microuptime(struct timeval *tvp) 9259bce0f05SLawrence Stewart { 9269bce0f05SLawrence Stewart 92788394fe4SLawrence Stewart microuptime_fromclock(tvp, sysclock_active); 9289bce0f05SLawrence Stewart } 9299bce0f05SLawrence Stewart 9309bce0f05SLawrence Stewart void 9319bce0f05SLawrence Stewart bintime(struct bintime *bt) 9329bce0f05SLawrence Stewart { 9339bce0f05SLawrence Stewart 93488394fe4SLawrence Stewart bintime_fromclock(bt, sysclock_active); 9359bce0f05SLawrence Stewart } 9369bce0f05SLawrence Stewart 9379bce0f05SLawrence Stewart void 9389bce0f05SLawrence Stewart nanotime(struct timespec *tsp) 9399bce0f05SLawrence Stewart { 9409bce0f05SLawrence Stewart 94188394fe4SLawrence Stewart nanotime_fromclock(tsp, sysclock_active); 9429bce0f05SLawrence Stewart } 9439bce0f05SLawrence Stewart 9449bce0f05SLawrence Stewart void 9459bce0f05SLawrence Stewart microtime(struct timeval *tvp) 9469bce0f05SLawrence Stewart { 9479bce0f05SLawrence Stewart 94888394fe4SLawrence Stewart microtime_fromclock(tvp, sysclock_active); 9499bce0f05SLawrence Stewart } 9509bce0f05SLawrence Stewart 9519bce0f05SLawrence Stewart void 9529bce0f05SLawrence Stewart getbinuptime(struct bintime *bt) 9539bce0f05SLawrence Stewart { 9549bce0f05SLawrence Stewart 95588394fe4SLawrence Stewart getbinuptime_fromclock(bt, sysclock_active); 9569bce0f05SLawrence Stewart } 9579bce0f05SLawrence Stewart 9589bce0f05SLawrence Stewart void 9599bce0f05SLawrence Stewart getnanouptime(struct timespec *tsp) 9609bce0f05SLawrence Stewart { 9619bce0f05SLawrence Stewart 96288394fe4SLawrence Stewart getnanouptime_fromclock(tsp, sysclock_active); 9639bce0f05SLawrence Stewart } 9649bce0f05SLawrence Stewart 9659bce0f05SLawrence Stewart void 9669bce0f05SLawrence Stewart getmicrouptime(struct timeval *tvp) 9679bce0f05SLawrence Stewart { 9689bce0f05SLawrence Stewart 96988394fe4SLawrence Stewart getmicrouptime_fromclock(tvp, sysclock_active); 9709bce0f05SLawrence Stewart } 9719bce0f05SLawrence Stewart 9729bce0f05SLawrence Stewart void 9739bce0f05SLawrence Stewart getbintime(struct bintime *bt) 9749bce0f05SLawrence Stewart { 9759bce0f05SLawrence Stewart 97688394fe4SLawrence Stewart getbintime_fromclock(bt, sysclock_active); 9779bce0f05SLawrence Stewart } 9789bce0f05SLawrence Stewart 9799bce0f05SLawrence Stewart void 9809bce0f05SLawrence Stewart getnanotime(struct timespec *tsp) 9819bce0f05SLawrence Stewart { 9829bce0f05SLawrence Stewart 98388394fe4SLawrence Stewart getnanotime_fromclock(tsp, sysclock_active); 9849bce0f05SLawrence Stewart } 9859bce0f05SLawrence Stewart 9869bce0f05SLawrence Stewart void 9879bce0f05SLawrence Stewart getmicrotime(struct timeval *tvp) 9889bce0f05SLawrence Stewart { 9899bce0f05SLawrence Stewart 99088394fe4SLawrence Stewart getmicrouptime_fromclock(tvp, sysclock_active); 9919bce0f05SLawrence Stewart } 9926cedd609SLawrence Stewart 993b0fdc837SLawrence Stewart #endif /* FFCLOCK */ 994b0fdc837SLawrence Stewart 99539acc78aSPoul-Henning Kamp /* 99657d025c3SGeorge V. Neville-Neil * This is a clone of getnanotime and used for walltimestamps. 99757d025c3SGeorge V. Neville-Neil * The dtrace_ prefix prevents fbt from creating probes for 99857d025c3SGeorge V. Neville-Neil * it so walltimestamp can be safely used in all fbt probes. 99957d025c3SGeorge V. Neville-Neil */ 100057d025c3SGeorge V. Neville-Neil void 100157d025c3SGeorge V. Neville-Neil dtrace_getnanotime(struct timespec *tsp) 100257d025c3SGeorge V. Neville-Neil { 100357d025c3SGeorge V. Neville-Neil struct timehands *th; 100457d025c3SGeorge V. Neville-Neil u_int gen; 100557d025c3SGeorge V. Neville-Neil 100657d025c3SGeorge V. Neville-Neil do { 100757d025c3SGeorge V. Neville-Neil th = timehands; 1008f4b5a972SKonstantin Belousov gen = atomic_load_acq_int(&th->th_generation); 100957d025c3SGeorge V. Neville-Neil *tsp = th->th_nanotime; 1010f4b5a972SKonstantin Belousov atomic_thread_fence_acq(); 1011f4b5a972SKonstantin Belousov } while (gen == 0 || gen != th->th_generation); 101257d025c3SGeorge V. Neville-Neil } 101357d025c3SGeorge V. Neville-Neil 101457d025c3SGeorge V. Neville-Neil /* 10156cedd609SLawrence Stewart * System clock currently providing time to the system. Modifiable via sysctl 10166cedd609SLawrence Stewart * when the FFCLOCK option is defined. 10176cedd609SLawrence Stewart */ 10186cedd609SLawrence Stewart int sysclock_active = SYSCLOCK_FBCK; 10196cedd609SLawrence Stewart 10206cedd609SLawrence Stewart /* Internal NTP status and error estimates. */ 10216cedd609SLawrence Stewart extern int time_status; 10226cedd609SLawrence Stewart extern long time_esterror; 10236cedd609SLawrence Stewart 10246cedd609SLawrence Stewart /* 10256cedd609SLawrence Stewart * Take a snapshot of sysclock data which can be used to compare system clocks 10266cedd609SLawrence Stewart * and generate timestamps after the fact. 10276cedd609SLawrence Stewart */ 10286cedd609SLawrence Stewart void 10296cedd609SLawrence Stewart sysclock_getsnapshot(struct sysclock_snap *clock_snap, int fast) 10306cedd609SLawrence Stewart { 10316cedd609SLawrence Stewart struct fbclock_info *fbi; 10326cedd609SLawrence Stewart struct timehands *th; 10336cedd609SLawrence Stewart struct bintime bt; 10346cedd609SLawrence Stewart unsigned int delta, gen; 10356cedd609SLawrence Stewart #ifdef FFCLOCK 10366cedd609SLawrence Stewart ffcounter ffcount; 10376cedd609SLawrence Stewart struct fftimehands *ffth; 10386cedd609SLawrence Stewart struct ffclock_info *ffi; 10396cedd609SLawrence Stewart struct ffclock_estimate cest; 10406cedd609SLawrence Stewart 10416cedd609SLawrence Stewart ffi = &clock_snap->ff_info; 10426cedd609SLawrence Stewart #endif 10436cedd609SLawrence Stewart 10446cedd609SLawrence Stewart fbi = &clock_snap->fb_info; 10456cedd609SLawrence Stewart delta = 0; 10466cedd609SLawrence Stewart 10476cedd609SLawrence Stewart do { 10486cedd609SLawrence Stewart th = timehands; 1049f4b5a972SKonstantin Belousov gen = atomic_load_acq_int(&th->th_generation); 10506cedd609SLawrence Stewart fbi->th_scale = th->th_scale; 10516cedd609SLawrence Stewart fbi->tick_time = th->th_offset; 10526cedd609SLawrence Stewart #ifdef FFCLOCK 10536cedd609SLawrence Stewart ffth = fftimehands; 10546cedd609SLawrence Stewart ffi->tick_time = ffth->tick_time_lerp; 10556cedd609SLawrence Stewart ffi->tick_time_lerp = ffth->tick_time_lerp; 10566cedd609SLawrence Stewart ffi->period = ffth->cest.period; 10576cedd609SLawrence Stewart ffi->period_lerp = ffth->period_lerp; 10586cedd609SLawrence Stewart clock_snap->ffcount = ffth->tick_ffcount; 10596cedd609SLawrence Stewart cest = ffth->cest; 10606cedd609SLawrence Stewart #endif 10616cedd609SLawrence Stewart if (!fast) 10626cedd609SLawrence Stewart delta = tc_delta(th); 1063f4b5a972SKonstantin Belousov atomic_thread_fence_acq(); 1064f4b5a972SKonstantin Belousov } while (gen == 0 || gen != th->th_generation); 10656cedd609SLawrence Stewart 10666cedd609SLawrence Stewart clock_snap->delta = delta; 10676cedd609SLawrence Stewart clock_snap->sysclock_active = sysclock_active; 10686cedd609SLawrence Stewart 10696cedd609SLawrence Stewart /* Record feedback clock status and error. */ 10706cedd609SLawrence Stewart clock_snap->fb_info.status = time_status; 10716cedd609SLawrence Stewart /* XXX: Very crude estimate of feedback clock error. */ 10726cedd609SLawrence Stewart bt.sec = time_esterror / 1000000; 10736cedd609SLawrence Stewart bt.frac = ((time_esterror - bt.sec) * 1000000) * 10746cedd609SLawrence Stewart (uint64_t)18446744073709ULL; 10756cedd609SLawrence Stewart clock_snap->fb_info.error = bt; 10766cedd609SLawrence Stewart 10776cedd609SLawrence Stewart #ifdef FFCLOCK 10786cedd609SLawrence Stewart if (!fast) 10796cedd609SLawrence Stewart clock_snap->ffcount += delta; 10806cedd609SLawrence Stewart 10816cedd609SLawrence Stewart /* Record feed-forward clock leap second adjustment. */ 10826cedd609SLawrence Stewart ffi->leapsec_adjustment = cest.leapsec_total; 10836cedd609SLawrence Stewart if (clock_snap->ffcount > cest.leapsec_next) 10846cedd609SLawrence Stewart ffi->leapsec_adjustment -= cest.leapsec; 10856cedd609SLawrence Stewart 10866cedd609SLawrence Stewart /* Record feed-forward clock status and error. */ 10876cedd609SLawrence Stewart clock_snap->ff_info.status = cest.status; 10886cedd609SLawrence Stewart ffcount = clock_snap->ffcount - cest.update_ffcount; 10896cedd609SLawrence Stewart ffclock_convert_delta(ffcount, cest.period, &bt); 10906cedd609SLawrence Stewart /* 18446744073709 = int(2^64/1e12), err_bound_rate in [ps/s]. */ 10916cedd609SLawrence Stewart bintime_mul(&bt, cest.errb_rate * (uint64_t)18446744073709ULL); 10926cedd609SLawrence Stewart /* 18446744073 = int(2^64 / 1e9), since err_abs in [ns]. */ 10936cedd609SLawrence Stewart bintime_addx(&bt, cest.errb_abs * (uint64_t)18446744073ULL); 10946cedd609SLawrence Stewart clock_snap->ff_info.error = bt; 10956cedd609SLawrence Stewart #endif 10966cedd609SLawrence Stewart } 10976cedd609SLawrence Stewart 10986cedd609SLawrence Stewart /* 10996cedd609SLawrence Stewart * Convert a sysclock snapshot into a struct bintime based on the specified 11006cedd609SLawrence Stewart * clock source and flags. 11016cedd609SLawrence Stewart */ 11026cedd609SLawrence Stewart int 11036cedd609SLawrence Stewart sysclock_snap2bintime(struct sysclock_snap *cs, struct bintime *bt, 11046cedd609SLawrence Stewart int whichclock, uint32_t flags) 11056cedd609SLawrence Stewart { 11066cedd609SLawrence Stewart #ifdef FFCLOCK 11076cedd609SLawrence Stewart struct bintime bt2; 11086cedd609SLawrence Stewart uint64_t period; 11096cedd609SLawrence Stewart #endif 11106cedd609SLawrence Stewart 11116cedd609SLawrence Stewart switch (whichclock) { 11126cedd609SLawrence Stewart case SYSCLOCK_FBCK: 11136cedd609SLawrence Stewart *bt = cs->fb_info.tick_time; 11146cedd609SLawrence Stewart 11156cedd609SLawrence Stewart /* If snapshot was created with !fast, delta will be >0. */ 11166cedd609SLawrence Stewart if (cs->delta > 0) 11176cedd609SLawrence Stewart bintime_addx(bt, cs->fb_info.th_scale * cs->delta); 11186cedd609SLawrence Stewart 11196cedd609SLawrence Stewart if ((flags & FBCLOCK_UPTIME) == 0) 11206cedd609SLawrence Stewart bintime_add(bt, &boottimebin); 11216cedd609SLawrence Stewart break; 11226cedd609SLawrence Stewart #ifdef FFCLOCK 11236cedd609SLawrence Stewart case SYSCLOCK_FFWD: 11246cedd609SLawrence Stewart if (flags & FFCLOCK_LERP) { 11256cedd609SLawrence Stewart *bt = cs->ff_info.tick_time_lerp; 11266cedd609SLawrence Stewart period = cs->ff_info.period_lerp; 11276cedd609SLawrence Stewart } else { 11286cedd609SLawrence Stewart *bt = cs->ff_info.tick_time; 11296cedd609SLawrence Stewart period = cs->ff_info.period; 11306cedd609SLawrence Stewart } 11316cedd609SLawrence Stewart 11326cedd609SLawrence Stewart /* If snapshot was created with !fast, delta will be >0. */ 11336cedd609SLawrence Stewart if (cs->delta > 0) { 11346cedd609SLawrence Stewart ffclock_convert_delta(cs->delta, period, &bt2); 11356cedd609SLawrence Stewart bintime_add(bt, &bt2); 11366cedd609SLawrence Stewart } 11376cedd609SLawrence Stewart 11386cedd609SLawrence Stewart /* Leap second adjustment. */ 11396cedd609SLawrence Stewart if (flags & FFCLOCK_LEAPSEC) 11406cedd609SLawrence Stewart bt->sec -= cs->ff_info.leapsec_adjustment; 11416cedd609SLawrence Stewart 11426cedd609SLawrence Stewart /* Boot time adjustment, for uptime/monotonic clocks. */ 11436cedd609SLawrence Stewart if (flags & FFCLOCK_UPTIME) 11446cedd609SLawrence Stewart bintime_sub(bt, &ffclock_boottime); 1145de02885aSKevin Lo break; 11466cedd609SLawrence Stewart #endif 11476cedd609SLawrence Stewart default: 11486cedd609SLawrence Stewart return (EINVAL); 11496cedd609SLawrence Stewart break; 11506cedd609SLawrence Stewart } 11516cedd609SLawrence Stewart 11526cedd609SLawrence Stewart return (0); 11536cedd609SLawrence Stewart } 11546cedd609SLawrence Stewart 11556cedd609SLawrence Stewart /* 115678a49a45SPoul-Henning Kamp * Initialize a new timecounter and possibly use it. 11574e2befc0SPoul-Henning Kamp */ 11587ec73f64SPoul-Henning Kamp void 115991266b96SPoul-Henning Kamp tc_init(struct timecounter *tc) 11607ec73f64SPoul-Henning Kamp { 1161555a5de2SPoul-Henning Kamp u_int u; 116293ef14a7SDavid Malone struct sysctl_oid *tc_root; 11637ec73f64SPoul-Henning Kamp 1164c679c734SPoul-Henning Kamp u = tc->tc_frequency / tc->tc_counter_mask; 1165555a5de2SPoul-Henning Kamp /* XXX: We need some margin here, 10% is a guess */ 1166555a5de2SPoul-Henning Kamp u *= 11; 1167555a5de2SPoul-Henning Kamp u /= 10; 1168c679c734SPoul-Henning Kamp if (u > hz && tc->tc_quality >= 0) { 1169c679c734SPoul-Henning Kamp tc->tc_quality = -2000; 1170c679c734SPoul-Henning Kamp if (bootverbose) { 1171c679c734SPoul-Henning Kamp printf("Timecounter \"%s\" frequency %ju Hz", 1172555a5de2SPoul-Henning Kamp tc->tc_name, (uintmax_t)tc->tc_frequency); 1173c679c734SPoul-Henning Kamp printf(" -- Insufficient hz, needs at least %u\n", u); 1174c679c734SPoul-Henning Kamp } 1175c679c734SPoul-Henning Kamp } else if (tc->tc_quality >= 0 || bootverbose) { 1176555a5de2SPoul-Henning Kamp printf("Timecounter \"%s\" frequency %ju Hz quality %d\n", 1177555a5de2SPoul-Henning Kamp tc->tc_name, (uintmax_t)tc->tc_frequency, 117878a49a45SPoul-Henning Kamp tc->tc_quality); 1179e46eeb89SPoul-Henning Kamp } 1180c679c734SPoul-Henning Kamp 118162efba6aSPoul-Henning Kamp tc->tc_next = timecounters; 118262efba6aSPoul-Henning Kamp timecounters = tc; 1183555a5de2SPoul-Henning Kamp /* 118493ef14a7SDavid Malone * Set up sysctl tree for this counter. 118593ef14a7SDavid Malone */ 118693ef14a7SDavid Malone tc_root = SYSCTL_ADD_NODE(NULL, 118793ef14a7SDavid Malone SYSCTL_STATIC_CHILDREN(_kern_timecounter_tc), OID_AUTO, tc->tc_name, 118893ef14a7SDavid Malone CTLFLAG_RW, 0, "timecounter description"); 118993ef14a7SDavid Malone SYSCTL_ADD_UINT(NULL, SYSCTL_CHILDREN(tc_root), OID_AUTO, 119093ef14a7SDavid Malone "mask", CTLFLAG_RD, &(tc->tc_counter_mask), 0, 119193ef14a7SDavid Malone "mask for implemented bits"); 119293ef14a7SDavid Malone SYSCTL_ADD_PROC(NULL, SYSCTL_CHILDREN(tc_root), OID_AUTO, 119393ef14a7SDavid Malone "counter", CTLTYPE_UINT | CTLFLAG_RD, tc, sizeof(*tc), 119493ef14a7SDavid Malone sysctl_kern_timecounter_get, "IU", "current timecounter value"); 119593ef14a7SDavid Malone SYSCTL_ADD_PROC(NULL, SYSCTL_CHILDREN(tc_root), OID_AUTO, 1196cbc134adSMatthew D Fleming "frequency", CTLTYPE_U64 | CTLFLAG_RD, tc, sizeof(*tc), 1197041b706bSDavid Malone sysctl_kern_timecounter_freq, "QU", "timecounter frequency"); 119893ef14a7SDavid Malone SYSCTL_ADD_INT(NULL, SYSCTL_CHILDREN(tc_root), OID_AUTO, 119993ef14a7SDavid Malone "quality", CTLFLAG_RD, &(tc->tc_quality), 0, 120093ef14a7SDavid Malone "goodness of time counter"); 120193ef14a7SDavid Malone /* 1202*e8bac3f2SIan Lepore * Do not automatically switch if the current tc was specifically 1203*e8bac3f2SIan Lepore * chosen. Never automatically use a timecounter with negative quality. 1204555a5de2SPoul-Henning Kamp * Even though we run on the dummy counter, switching here may be 1205*e8bac3f2SIan Lepore * worse since this timecounter may not be monotonic. 1206555a5de2SPoul-Henning Kamp */ 1207*e8bac3f2SIan Lepore if (tc_chosen) 1208*e8bac3f2SIan Lepore return; 120978a49a45SPoul-Henning Kamp if (tc->tc_quality < 0) 121078a49a45SPoul-Henning Kamp return; 121178a49a45SPoul-Henning Kamp if (tc->tc_quality < timecounter->tc_quality) 121278a49a45SPoul-Henning Kamp return; 1213555a5de2SPoul-Henning Kamp if (tc->tc_quality == timecounter->tc_quality && 1214555a5de2SPoul-Henning Kamp tc->tc_frequency < timecounter->tc_frequency) 1215555a5de2SPoul-Henning Kamp return; 1216555a5de2SPoul-Henning Kamp (void)tc->tc_get_timecount(tc); 1217555a5de2SPoul-Henning Kamp (void)tc->tc_get_timecount(tc); 12187ec73f64SPoul-Henning Kamp timecounter = tc; 121962efba6aSPoul-Henning Kamp } 122062efba6aSPoul-Henning Kamp 122139acc78aSPoul-Henning Kamp /* Report the frequency of the current timecounter. */ 122260ae52f7SEd Schouten uint64_t 122362efba6aSPoul-Henning Kamp tc_getfrequency(void) 122462efba6aSPoul-Henning Kamp { 122562efba6aSPoul-Henning Kamp 12266b00cf46SPoul-Henning Kamp return (timehands->th_counter->tc_frequency); 12277ec73f64SPoul-Henning Kamp } 12287ec73f64SPoul-Henning Kamp 122939acc78aSPoul-Henning Kamp /* 12304e82e5f6SWarner Losh * Step our concept of UTC. This is done by modifying our estimate of 12314e74721cSPoul-Henning Kamp * when we booted. 12324e74721cSPoul-Henning Kamp * XXX: not locked. 12336b00cf46SPoul-Henning Kamp */ 12347ec73f64SPoul-Henning Kamp void 123591266b96SPoul-Henning Kamp tc_setclock(struct timespec *ts) 12367ec73f64SPoul-Henning Kamp { 12375b51d1deSPoul-Henning Kamp struct timespec tbef, taft; 12384e74721cSPoul-Henning Kamp struct bintime bt, bt2; 12397ec73f64SPoul-Henning Kamp 1240e8444a7eSPoul-Henning Kamp cpu_tick_calibrate(1); 12415b51d1deSPoul-Henning Kamp nanotime(&tbef); 12424e74721cSPoul-Henning Kamp timespec2bintime(ts, &bt); 12435b51d1deSPoul-Henning Kamp binuptime(&bt2); 12444e74721cSPoul-Henning Kamp bintime_sub(&bt, &bt2); 12454e74721cSPoul-Henning Kamp bintime_add(&bt2, &boottimebin); 12464e74721cSPoul-Henning Kamp boottimebin = bt; 12474e74721cSPoul-Henning Kamp bintime2timeval(&bt, &boottime); 124839acc78aSPoul-Henning Kamp 124939acc78aSPoul-Henning Kamp /* XXX fiddle all the little crinkly bits around the fiords... */ 125091266b96SPoul-Henning Kamp tc_windup(); 12515b51d1deSPoul-Henning Kamp nanotime(&taft); 12524e74721cSPoul-Henning Kamp if (timestepwarnings) { 12535b51d1deSPoul-Henning Kamp log(LOG_INFO, 12545b51d1deSPoul-Henning Kamp "Time stepped from %jd.%09ld to %jd.%09ld (%jd.%09ld)\n", 12555b51d1deSPoul-Henning Kamp (intmax_t)tbef.tv_sec, tbef.tv_nsec, 12565b51d1deSPoul-Henning Kamp (intmax_t)taft.tv_sec, taft.tv_nsec, 1257ee57aeeaSPoul-Henning Kamp (intmax_t)ts->tv_sec, ts->tv_nsec); 12584e74721cSPoul-Henning Kamp } 1259e8444a7eSPoul-Henning Kamp cpu_tick_calibrate(1); 12607ec73f64SPoul-Henning Kamp } 12617ec73f64SPoul-Henning Kamp 126239acc78aSPoul-Henning Kamp /* 126339acc78aSPoul-Henning Kamp * Initialize the next struct timehands in the ring and make 12646b00cf46SPoul-Henning Kamp * it the active timehands. Along the way we might switch to a different 12656b00cf46SPoul-Henning Kamp * timecounter and/or do seconds processing in NTP. Slightly magic. 12666b00cf46SPoul-Henning Kamp */ 12679e1b5510SPoul-Henning Kamp static void 126891266b96SPoul-Henning Kamp tc_windup(void) 12697ec73f64SPoul-Henning Kamp { 12702028c0cdSPoul-Henning Kamp struct bintime bt; 127139acc78aSPoul-Henning Kamp struct timehands *th, *tho; 127260ae52f7SEd Schouten uint64_t scale; 127339acc78aSPoul-Henning Kamp u_int delta, ncount, ogen; 127439acc78aSPoul-Henning Kamp int i; 12754f2073fbSWarner Losh time_t t; 12767ec73f64SPoul-Henning Kamp 127739acc78aSPoul-Henning Kamp /* 1278f4b5a972SKonstantin Belousov * Make the next timehands a copy of the current one, but do 1279f4b5a972SKonstantin Belousov * not overwrite the generation or next pointer. While we 1280f4b5a972SKonstantin Belousov * update the contents, the generation must be zero. We need 1281f4b5a972SKonstantin Belousov * to ensure that the zero generation is visible before the 1282f4b5a972SKonstantin Belousov * data updates become visible, which requires release fence. 1283f4b5a972SKonstantin Belousov * For similar reasons, re-reading of the generation after the 1284f4b5a972SKonstantin Belousov * data is read should use acquire fence. 12856b00cf46SPoul-Henning Kamp */ 12866b00cf46SPoul-Henning Kamp tho = timehands; 12876b00cf46SPoul-Henning Kamp th = tho->th_next; 12886b00cf46SPoul-Henning Kamp ogen = th->th_generation; 1289f4b5a972SKonstantin Belousov th->th_generation = 0; 1290f4b5a972SKonstantin Belousov atomic_thread_fence_rel(); 129139acc78aSPoul-Henning Kamp bcopy(tho, th, offsetof(struct timehands, th_generation)); 12926b00cf46SPoul-Henning Kamp 129339acc78aSPoul-Henning Kamp /* 12946b00cf46SPoul-Henning Kamp * Capture a timecounter delta on the current timecounter and if 12956b00cf46SPoul-Henning Kamp * changing timecounters, a counter value from the new timecounter. 12966b00cf46SPoul-Henning Kamp * Update the offset fields accordingly. 12976b00cf46SPoul-Henning Kamp */ 12986b00cf46SPoul-Henning Kamp delta = tc_delta(th); 12996b00cf46SPoul-Henning Kamp if (th->th_counter != timecounter) 13006b00cf46SPoul-Henning Kamp ncount = timecounter->tc_get_timecount(timecounter); 130139acc78aSPoul-Henning Kamp else 130239acc78aSPoul-Henning Kamp ncount = 0; 1303b0fdc837SLawrence Stewart #ifdef FFCLOCK 1304b0fdc837SLawrence Stewart ffclock_windup(delta); 1305b0fdc837SLawrence Stewart #endif 13066b00cf46SPoul-Henning Kamp th->th_offset_count += delta; 13076b00cf46SPoul-Henning Kamp th->th_offset_count &= th->th_counter->tc_counter_mask; 1308aa519c0aSColin Percival while (delta > th->th_counter->tc_frequency) { 1309aa519c0aSColin Percival /* Eat complete unadjusted seconds. */ 1310aa519c0aSColin Percival delta -= th->th_counter->tc_frequency; 1311aa519c0aSColin Percival th->th_offset.sec++; 1312aa519c0aSColin Percival } 1313aa519c0aSColin Percival if ((delta > th->th_counter->tc_frequency / 2) && 1314772d1e42SColin Percival (th->th_scale * delta < ((uint64_t)1 << 63))) { 1315aa519c0aSColin Percival /* The product th_scale * delta just barely overflows. */ 1316aa519c0aSColin Percival th->th_offset.sec++; 1317aa519c0aSColin Percival } 13186b00cf46SPoul-Henning Kamp bintime_addx(&th->th_offset, th->th_scale * delta); 13196b00cf46SPoul-Henning Kamp 132039acc78aSPoul-Henning Kamp /* 13216b00cf46SPoul-Henning Kamp * Hardware latching timecounters may not generate interrupts on 13226b00cf46SPoul-Henning Kamp * PPS events, so instead we poll them. There is a finite risk that 13236b00cf46SPoul-Henning Kamp * the hardware might capture a count which is later than the one we 13246b00cf46SPoul-Henning Kamp * got above, and therefore possibly in the next NTP second which might 13256b00cf46SPoul-Henning Kamp * have a different rate than the current NTP second. It doesn't 13266b00cf46SPoul-Henning Kamp * matter in practice. 13276b00cf46SPoul-Henning Kamp */ 13286b00cf46SPoul-Henning Kamp if (tho->th_counter->tc_poll_pps) 13296b00cf46SPoul-Henning Kamp tho->th_counter->tc_poll_pps(tho->th_counter); 13306b00cf46SPoul-Henning Kamp 133139acc78aSPoul-Henning Kamp /* 1332c1cccd1eSWarner Losh * Deal with NTP second processing. The for loop normally 1333c1cccd1eSWarner Losh * iterates at most once, but in extreme situations it might 1334c1cccd1eSWarner Losh * keep NTP sane if timeouts are not run for several seconds. 1335c1cccd1eSWarner Losh * At boot, the time step can be large when the TOD hardware 1336c1cccd1eSWarner Losh * has been read, so on really large steps, we call 1337c1cccd1eSWarner Losh * ntp_update_second only twice. We need to call it twice in 1338c1cccd1eSWarner Losh * case we missed a leap second. 13394f2073fbSWarner Losh */ 13404f2073fbSWarner Losh bt = th->th_offset; 13414f2073fbSWarner Losh bintime_add(&bt, &boottimebin); 134245cc9f5fSWarner Losh i = bt.sec - tho->th_microtime.tv_sec; 134345cc9f5fSWarner Losh if (i > LARGE_STEP) 134445cc9f5fSWarner Losh i = 2; 134545cc9f5fSWarner Losh for (; i > 0; i--) { 13464f2073fbSWarner Losh t = bt.sec; 13474f2073fbSWarner Losh ntp_update_second(&th->th_adjustment, &bt.sec); 13484f2073fbSWarner Losh if (bt.sec != t) 13494f2073fbSWarner Losh boottimebin.sec += bt.sec - t; 13504f2073fbSWarner Losh } 1351c1cccd1eSWarner Losh /* Update the UTC timestamps used by the get*() functions. */ 1352c1cccd1eSWarner Losh /* XXX shouldn't do this here. Should force non-`get' versions. */ 1353c1cccd1eSWarner Losh bintime2timeval(&bt, &th->th_microtime); 1354c1cccd1eSWarner Losh bintime2timespec(&bt, &th->th_nanotime); 13556b00cf46SPoul-Henning Kamp 13566b00cf46SPoul-Henning Kamp /* Now is a good time to change timecounters. */ 13576b00cf46SPoul-Henning Kamp if (th->th_counter != timecounter) { 135808e1b4f4SJung-uk Kim #ifndef __arm__ 135992597e06SJohn Baldwin if ((timecounter->tc_flags & TC_FLAGS_C2STOP) != 0) 136092597e06SJohn Baldwin cpu_disable_c2_sleep++; 136192597e06SJohn Baldwin if ((th->th_counter->tc_flags & TC_FLAGS_C2STOP) != 0) 136292597e06SJohn Baldwin cpu_disable_c2_sleep--; 136308e1b4f4SJung-uk Kim #endif 13646b00cf46SPoul-Henning Kamp th->th_counter = timecounter; 13656b00cf46SPoul-Henning Kamp th->th_offset_count = ncount; 13660e189873SAlexander Motin tc_min_ticktock_freq = max(1, timecounter->tc_frequency / 13670e189873SAlexander Motin (((uint64_t)timecounter->tc_counter_mask + 1) / 3)); 1368b0fdc837SLawrence Stewart #ifdef FFCLOCK 1369b0fdc837SLawrence Stewart ffclock_change_tc(th); 1370b0fdc837SLawrence Stewart #endif 13717ec73f64SPoul-Henning Kamp } 13727ec73f64SPoul-Henning Kamp 13731a996ed1SEdward Tomasz Napierala /*- 13746b00cf46SPoul-Henning Kamp * Recalculate the scaling factor. We want the number of 1/2^64 13756b00cf46SPoul-Henning Kamp * fractions of a second per period of the hardware counter, taking 13766b00cf46SPoul-Henning Kamp * into account the th_adjustment factor which the NTP PLL/adjtime(2) 13776b00cf46SPoul-Henning Kamp * processing provides us with. 13786b00cf46SPoul-Henning Kamp * 13796b00cf46SPoul-Henning Kamp * The th_adjustment is nanoseconds per second with 32 bit binary 1380d94e3652SPoul-Henning Kamp * fraction and we want 64 bit binary fraction of second: 13816b00cf46SPoul-Henning Kamp * 13826b00cf46SPoul-Henning Kamp * x = a * 2^32 / 10^9 = a * 4.294967296 13836b00cf46SPoul-Henning Kamp * 13846b00cf46SPoul-Henning Kamp * The range of th_adjustment is +/- 5000PPM so inside a 64bit int 1385e8444a7eSPoul-Henning Kamp * we can only multiply by about 850 without overflowing, that 1386e8444a7eSPoul-Henning Kamp * leaves no suitably precise fractions for multiply before divide. 13876b00cf46SPoul-Henning Kamp * 13886b00cf46SPoul-Henning Kamp * Divide before multiply with a fraction of 2199/512 results in a 13896b00cf46SPoul-Henning Kamp * systematic undercompensation of 10PPM of th_adjustment. On a 13906b00cf46SPoul-Henning Kamp * 5000PPM adjustment this is a 0.05PPM error. This is acceptable. 13916b00cf46SPoul-Henning Kamp * 13926b00cf46SPoul-Henning Kamp * We happily sacrifice the lowest of the 64 bits of our result 13936b00cf46SPoul-Henning Kamp * to the goddess of code clarity. 139439acc78aSPoul-Henning Kamp * 13956b00cf46SPoul-Henning Kamp */ 139660ae52f7SEd Schouten scale = (uint64_t)1 << 63; 13976b00cf46SPoul-Henning Kamp scale += (th->th_adjustment / 1024) * 2199; 13986b00cf46SPoul-Henning Kamp scale /= th->th_counter->tc_frequency; 13996b00cf46SPoul-Henning Kamp th->th_scale = scale * 2; 14006b00cf46SPoul-Henning Kamp 140139acc78aSPoul-Henning Kamp /* 140239acc78aSPoul-Henning Kamp * Now that the struct timehands is again consistent, set the new 14036b00cf46SPoul-Henning Kamp * generation number, making sure to not make it zero. 14046b00cf46SPoul-Henning Kamp */ 14056b00cf46SPoul-Henning Kamp if (++ogen == 0) 140639acc78aSPoul-Henning Kamp ogen = 1; 1407f4b5a972SKonstantin Belousov atomic_store_rel_int(&th->th_generation, ogen); 14086b00cf46SPoul-Henning Kamp 140939acc78aSPoul-Henning Kamp /* Go live with the new struct timehands. */ 14109bce0f05SLawrence Stewart #ifdef FFCLOCK 14119bce0f05SLawrence Stewart switch (sysclock_active) { 14129bce0f05SLawrence Stewart case SYSCLOCK_FBCK: 14139bce0f05SLawrence Stewart #endif 14146b00cf46SPoul-Henning Kamp time_second = th->th_microtime.tv_sec; 141538b0884cSPoul-Henning Kamp time_uptime = th->th_offset.sec; 14169bce0f05SLawrence Stewart #ifdef FFCLOCK 14179bce0f05SLawrence Stewart break; 14189bce0f05SLawrence Stewart case SYSCLOCK_FFWD: 14199bce0f05SLawrence Stewart time_second = fftimehands->tick_time_lerp.sec; 14209bce0f05SLawrence Stewart time_uptime = fftimehands->tick_time_lerp.sec - ffclock_boottime.sec; 14219bce0f05SLawrence Stewart break; 14229bce0f05SLawrence Stewart } 14239bce0f05SLawrence Stewart #endif 14249bce0f05SLawrence Stewart 14256b00cf46SPoul-Henning Kamp timehands = th; 142621c295efSKonstantin Belousov timekeep_push_vdso(); 14276b00cf46SPoul-Henning Kamp } 14286b00cf46SPoul-Henning Kamp 142939acc78aSPoul-Henning Kamp /* Report or change the active timecounter hardware. */ 14306b6ef746SBruce Evans static int 143182d9ae4eSPoul-Henning Kamp sysctl_kern_timecounter_hardware(SYSCTL_HANDLER_ARGS) 14326b6ef746SBruce Evans { 14336b6ef746SBruce Evans char newname[32]; 14346b6ef746SBruce Evans struct timecounter *newtc, *tc; 14356b6ef746SBruce Evans int error; 14366b6ef746SBruce Evans 143762efba6aSPoul-Henning Kamp tc = timecounter; 1438e80fb434SRobert Drehmel strlcpy(newname, tc->tc_name, sizeof(newname)); 1439e80fb434SRobert Drehmel 14406b6ef746SBruce Evans error = sysctl_handle_string(oidp, &newname[0], sizeof(newname), req); 1441*e8bac3f2SIan Lepore if (error != 0 || req->newptr == NULL) 144262efba6aSPoul-Henning Kamp return (error); 1443*e8bac3f2SIan Lepore /* Record that the tc in use now was specifically chosen. */ 1444*e8bac3f2SIan Lepore tc_chosen = 1; 1445*e8bac3f2SIan Lepore if (strcmp(newname, tc->tc_name) == 0) 1446*e8bac3f2SIan Lepore return (0); 144762efba6aSPoul-Henning Kamp for (newtc = timecounters; newtc != NULL; newtc = newtc->tc_next) { 144839acc78aSPoul-Henning Kamp if (strcmp(newname, newtc->tc_name) != 0) 144962efba6aSPoul-Henning Kamp continue; 145039acc78aSPoul-Henning Kamp 14516b6ef746SBruce Evans /* Warm up new timecounter. */ 14526b6ef746SBruce Evans (void)newtc->tc_get_timecount(newtc); 145362efba6aSPoul-Henning Kamp (void)newtc->tc_get_timecount(newtc); 145439acc78aSPoul-Henning Kamp 145562efba6aSPoul-Henning Kamp timecounter = newtc; 1456d1b1b600SNeel Natu 1457d1b1b600SNeel Natu /* 1458d1b1b600SNeel Natu * The vdso timehands update is deferred until the next 1459d1b1b600SNeel Natu * 'tc_windup()'. 1460d1b1b600SNeel Natu * 1461d1b1b600SNeel Natu * This is prudent given that 'timekeep_push_vdso()' does not 1462d1b1b600SNeel Natu * use any locking and that it can be called in hard interrupt 1463d1b1b600SNeel Natu * context via 'tc_windup()'. 1464d1b1b600SNeel Natu */ 14656b6ef746SBruce Evans return (0); 14666b6ef746SBruce Evans } 14676b6ef746SBruce Evans return (EINVAL); 14686b6ef746SBruce Evans } 14696b6ef746SBruce Evans 14706b6ef746SBruce Evans SYSCTL_PROC(_kern_timecounter, OID_AUTO, hardware, CTLTYPE_STRING | CTLFLAG_RW, 1471b389be97SRebecca Cran 0, 0, sysctl_kern_timecounter_hardware, "A", 1472b389be97SRebecca Cran "Timecounter hardware selected"); 14736b6ef746SBruce Evans 147478a49a45SPoul-Henning Kamp 1475*e8bac3f2SIan Lepore /* Report the available timecounter hardware. */ 147678a49a45SPoul-Henning Kamp static int 147778a49a45SPoul-Henning Kamp sysctl_kern_timecounter_choice(SYSCTL_HANDLER_ARGS) 147878a49a45SPoul-Henning Kamp { 147991d9eda2SIan Lepore struct sbuf sb; 148078a49a45SPoul-Henning Kamp struct timecounter *tc; 148178a49a45SPoul-Henning Kamp int error; 148278a49a45SPoul-Henning Kamp 148391d9eda2SIan Lepore sbuf_new_for_sysctl(&sb, NULL, 0, req); 148491d9eda2SIan Lepore for (tc = timecounters; tc != NULL; tc = tc->tc_next) { 148591d9eda2SIan Lepore if (tc != timecounters) 148691d9eda2SIan Lepore sbuf_putc(&sb, ' '); 148791d9eda2SIan Lepore sbuf_printf(&sb, "%s(%d)", tc->tc_name, tc->tc_quality); 148878a49a45SPoul-Henning Kamp } 148991d9eda2SIan Lepore error = sbuf_finish(&sb); 149091d9eda2SIan Lepore sbuf_delete(&sb); 149178a49a45SPoul-Henning Kamp return (error); 149278a49a45SPoul-Henning Kamp } 149378a49a45SPoul-Henning Kamp 149478a49a45SPoul-Henning Kamp SYSCTL_PROC(_kern_timecounter, OID_AUTO, choice, CTLTYPE_STRING | CTLFLAG_RD, 14952baa5cddSRebecca Cran 0, 0, sysctl_kern_timecounter_choice, "A", "Timecounter hardware detected"); 149678a49a45SPoul-Henning Kamp 149739acc78aSPoul-Henning Kamp /* 14986b00cf46SPoul-Henning Kamp * RFC 2783 PPS-API implementation. 14996b00cf46SPoul-Henning Kamp */ 15007ec73f64SPoul-Henning Kamp 150128315e27SIan Lepore /* 150228315e27SIan Lepore * Return true if the driver is aware of the abi version extensions in the 150328315e27SIan Lepore * pps_state structure, and it supports at least the given abi version number. 150428315e27SIan Lepore */ 150528315e27SIan Lepore static inline int 150628315e27SIan Lepore abi_aware(struct pps_state *pps, int vers) 150728315e27SIan Lepore { 150828315e27SIan Lepore 150928315e27SIan Lepore return ((pps->kcmode & KCMODE_ABIFLAG) && pps->driver_abi >= vers); 151028315e27SIan Lepore } 151128315e27SIan Lepore 1512a1137de9SIan Lepore static int 1513a1137de9SIan Lepore pps_fetch(struct pps_fetch_args *fapi, struct pps_state *pps) 1514a1137de9SIan Lepore { 1515a1137de9SIan Lepore int err, timo; 1516a1137de9SIan Lepore pps_seq_t aseq, cseq; 1517a1137de9SIan Lepore struct timeval tv; 1518a1137de9SIan Lepore 1519a1137de9SIan Lepore if (fapi->tsformat && fapi->tsformat != PPS_TSFMT_TSPEC) 1520a1137de9SIan Lepore return (EINVAL); 1521a1137de9SIan Lepore 1522a1137de9SIan Lepore /* 1523a1137de9SIan Lepore * If no timeout is requested, immediately return whatever values were 1524a1137de9SIan Lepore * most recently captured. If timeout seconds is -1, that's a request 1525a1137de9SIan Lepore * to block without a timeout. WITNESS won't let us sleep forever 1526a1137de9SIan Lepore * without a lock (we really don't need a lock), so just repeatedly 1527a1137de9SIan Lepore * sleep a long time. 1528a1137de9SIan Lepore */ 1529a1137de9SIan Lepore if (fapi->timeout.tv_sec || fapi->timeout.tv_nsec) { 1530a1137de9SIan Lepore if (fapi->timeout.tv_sec == -1) 1531a1137de9SIan Lepore timo = 0x7fffffff; 1532a1137de9SIan Lepore else { 1533a1137de9SIan Lepore tv.tv_sec = fapi->timeout.tv_sec; 1534a1137de9SIan Lepore tv.tv_usec = fapi->timeout.tv_nsec / 1000; 1535a1137de9SIan Lepore timo = tvtohz(&tv); 1536a1137de9SIan Lepore } 1537a1137de9SIan Lepore aseq = pps->ppsinfo.assert_sequence; 1538a1137de9SIan Lepore cseq = pps->ppsinfo.clear_sequence; 1539a1137de9SIan Lepore while (aseq == pps->ppsinfo.assert_sequence && 1540a1137de9SIan Lepore cseq == pps->ppsinfo.clear_sequence) { 154128315e27SIan Lepore if (abi_aware(pps, 1) && pps->driver_mtx != NULL) { 154228315e27SIan Lepore if (pps->flags & PPSFLAG_MTX_SPIN) { 154328315e27SIan Lepore err = msleep_spin(pps, pps->driver_mtx, 154428315e27SIan Lepore "ppsfch", timo); 154528315e27SIan Lepore } else { 154628315e27SIan Lepore err = msleep(pps, pps->driver_mtx, PCATCH, 154728315e27SIan Lepore "ppsfch", timo); 154828315e27SIan Lepore } 154928315e27SIan Lepore } else { 1550a1137de9SIan Lepore err = tsleep(pps, PCATCH, "ppsfch", timo); 155128315e27SIan Lepore } 15526f7a9f7cSIan Lepore if (err == EWOULDBLOCK) { 15536f7a9f7cSIan Lepore if (fapi->timeout.tv_sec == -1) { 1554a1137de9SIan Lepore continue; 15556f7a9f7cSIan Lepore } else { 15566f7a9f7cSIan Lepore return (ETIMEDOUT); 15576f7a9f7cSIan Lepore } 1558a1137de9SIan Lepore } else if (err != 0) { 1559a1137de9SIan Lepore return (err); 1560a1137de9SIan Lepore } 1561a1137de9SIan Lepore } 1562a1137de9SIan Lepore } 1563a1137de9SIan Lepore 1564a1137de9SIan Lepore pps->ppsinfo.current_mode = pps->ppsparam.mode; 1565a1137de9SIan Lepore fapi->pps_info_buf = pps->ppsinfo; 1566a1137de9SIan Lepore 1567a1137de9SIan Lepore return (0); 1568a1137de9SIan Lepore } 1569a1137de9SIan Lepore 157032c20357SPoul-Henning Kamp int 157132c20357SPoul-Henning Kamp pps_ioctl(u_long cmd, caddr_t data, struct pps_state *pps) 157232c20357SPoul-Henning Kamp { 157332c20357SPoul-Henning Kamp pps_params_t *app; 1574b7424f2dSJohn Hay struct pps_fetch_args *fapi; 157565e359a1SLawrence Stewart #ifdef FFCLOCK 157665e359a1SLawrence Stewart struct pps_fetch_ffc_args *fapi_ffc; 157765e359a1SLawrence Stewart #endif 1578de3f8889SPeter Wemm #ifdef PPS_SYNC 1579b7424f2dSJohn Hay struct pps_kcbind_args *kapi; 1580de3f8889SPeter Wemm #endif 158132c20357SPoul-Henning Kamp 1582d8e8b675SPoul-Henning Kamp KASSERT(pps != NULL, ("NULL pps pointer in pps_ioctl")); 158332c20357SPoul-Henning Kamp switch (cmd) { 158432c20357SPoul-Henning Kamp case PPS_IOC_CREATE: 158532c20357SPoul-Henning Kamp return (0); 158632c20357SPoul-Henning Kamp case PPS_IOC_DESTROY: 158732c20357SPoul-Henning Kamp return (0); 158832c20357SPoul-Henning Kamp case PPS_IOC_SETPARAMS: 158932c20357SPoul-Henning Kamp app = (pps_params_t *)data; 159032c20357SPoul-Henning Kamp if (app->mode & ~pps->ppscap) 159132c20357SPoul-Henning Kamp return (EINVAL); 159265e359a1SLawrence Stewart #ifdef FFCLOCK 159365e359a1SLawrence Stewart /* Ensure only a single clock is selected for ffc timestamp. */ 159465e359a1SLawrence Stewart if ((app->mode & PPS_TSCLK_MASK) == PPS_TSCLK_MASK) 159565e359a1SLawrence Stewart return (EINVAL); 159665e359a1SLawrence Stewart #endif 159732c20357SPoul-Henning Kamp pps->ppsparam = *app; 159832c20357SPoul-Henning Kamp return (0); 159932c20357SPoul-Henning Kamp case PPS_IOC_GETPARAMS: 160032c20357SPoul-Henning Kamp app = (pps_params_t *)data; 160132c20357SPoul-Henning Kamp *app = pps->ppsparam; 1602b7424f2dSJohn Hay app->api_version = PPS_API_VERS_1; 160332c20357SPoul-Henning Kamp return (0); 160432c20357SPoul-Henning Kamp case PPS_IOC_GETCAP: 160532c20357SPoul-Henning Kamp *(int*)data = pps->ppscap; 160632c20357SPoul-Henning Kamp return (0); 160732c20357SPoul-Henning Kamp case PPS_IOC_FETCH: 1608b7424f2dSJohn Hay fapi = (struct pps_fetch_args *)data; 1609a1137de9SIan Lepore return (pps_fetch(fapi, pps)); 161065e359a1SLawrence Stewart #ifdef FFCLOCK 161165e359a1SLawrence Stewart case PPS_IOC_FETCH_FFCOUNTER: 161265e359a1SLawrence Stewart fapi_ffc = (struct pps_fetch_ffc_args *)data; 161365e359a1SLawrence Stewart if (fapi_ffc->tsformat && fapi_ffc->tsformat != 161465e359a1SLawrence Stewart PPS_TSFMT_TSPEC) 161565e359a1SLawrence Stewart return (EINVAL); 161665e359a1SLawrence Stewart if (fapi_ffc->timeout.tv_sec || fapi_ffc->timeout.tv_nsec) 161765e359a1SLawrence Stewart return (EOPNOTSUPP); 161865e359a1SLawrence Stewart pps->ppsinfo_ffc.current_mode = pps->ppsparam.mode; 161965e359a1SLawrence Stewart fapi_ffc->pps_info_buf_ffc = pps->ppsinfo_ffc; 162065e359a1SLawrence Stewart /* Overwrite timestamps if feedback clock selected. */ 162165e359a1SLawrence Stewart switch (pps->ppsparam.mode & PPS_TSCLK_MASK) { 162265e359a1SLawrence Stewart case PPS_TSCLK_FBCK: 162365e359a1SLawrence Stewart fapi_ffc->pps_info_buf_ffc.assert_timestamp = 162465e359a1SLawrence Stewart pps->ppsinfo.assert_timestamp; 162565e359a1SLawrence Stewart fapi_ffc->pps_info_buf_ffc.clear_timestamp = 162665e359a1SLawrence Stewart pps->ppsinfo.clear_timestamp; 162765e359a1SLawrence Stewart break; 162865e359a1SLawrence Stewart case PPS_TSCLK_FFWD: 162965e359a1SLawrence Stewart break; 163065e359a1SLawrence Stewart default: 163165e359a1SLawrence Stewart break; 163265e359a1SLawrence Stewart } 163365e359a1SLawrence Stewart return (0); 163465e359a1SLawrence Stewart #endif /* FFCLOCK */ 1635b7424f2dSJohn Hay case PPS_IOC_KCBIND: 1636b7424f2dSJohn Hay #ifdef PPS_SYNC 1637b7424f2dSJohn Hay kapi = (struct pps_kcbind_args *)data; 1638b7424f2dSJohn Hay /* XXX Only root should be able to do this */ 1639b7424f2dSJohn Hay if (kapi->tsformat && kapi->tsformat != PPS_TSFMT_TSPEC) 1640b7424f2dSJohn Hay return (EINVAL); 1641b7424f2dSJohn Hay if (kapi->kernel_consumer != PPS_KC_HARDPPS) 1642b7424f2dSJohn Hay return (EINVAL); 1643b7424f2dSJohn Hay if (kapi->edge & ~pps->ppscap) 1644b7424f2dSJohn Hay return (EINVAL); 164528315e27SIan Lepore pps->kcmode = (kapi->edge & KCMODE_EDGEMASK) | 164628315e27SIan Lepore (pps->kcmode & KCMODE_ABIFLAG); 1647b7424f2dSJohn Hay return (0); 1648b7424f2dSJohn Hay #else 1649b7424f2dSJohn Hay return (EOPNOTSUPP); 1650b7424f2dSJohn Hay #endif 165132c20357SPoul-Henning Kamp default: 1652f8385624SPoul-Henning Kamp return (ENOIOCTL); 165332c20357SPoul-Henning Kamp } 165432c20357SPoul-Henning Kamp } 165532c20357SPoul-Henning Kamp 165632c20357SPoul-Henning Kamp void 165732c20357SPoul-Henning Kamp pps_init(struct pps_state *pps) 165832c20357SPoul-Henning Kamp { 1659a1137de9SIan Lepore pps->ppscap |= PPS_TSFMT_TSPEC | PPS_CANWAIT; 166032c20357SPoul-Henning Kamp if (pps->ppscap & PPS_CAPTUREASSERT) 166132c20357SPoul-Henning Kamp pps->ppscap |= PPS_OFFSETASSERT; 166232c20357SPoul-Henning Kamp if (pps->ppscap & PPS_CAPTURECLEAR) 166332c20357SPoul-Henning Kamp pps->ppscap |= PPS_OFFSETCLEAR; 166465e359a1SLawrence Stewart #ifdef FFCLOCK 166565e359a1SLawrence Stewart pps->ppscap |= PPS_TSCLK_MASK; 166665e359a1SLawrence Stewart #endif 166728315e27SIan Lepore pps->kcmode &= ~KCMODE_ABIFLAG; 166828315e27SIan Lepore } 166928315e27SIan Lepore 167028315e27SIan Lepore void 167128315e27SIan Lepore pps_init_abi(struct pps_state *pps) 167228315e27SIan Lepore { 167328315e27SIan Lepore 167428315e27SIan Lepore pps_init(pps); 167528315e27SIan Lepore if (pps->driver_abi > 0) { 167628315e27SIan Lepore pps->kcmode |= KCMODE_ABIFLAG; 167728315e27SIan Lepore pps->kernel_abi = PPS_ABI_VERSION; 167828315e27SIan Lepore } 167932c20357SPoul-Henning Kamp } 168032c20357SPoul-Henning Kamp 168132c20357SPoul-Henning Kamp void 16827bf758bfSPoul-Henning Kamp pps_capture(struct pps_state *pps) 16837bf758bfSPoul-Henning Kamp { 16846b00cf46SPoul-Henning Kamp struct timehands *th; 16857bf758bfSPoul-Henning Kamp 1686d8e8b675SPoul-Henning Kamp KASSERT(pps != NULL, ("NULL pps pointer in pps_capture")); 16876b00cf46SPoul-Henning Kamp th = timehands; 1688f4b5a972SKonstantin Belousov pps->capgen = atomic_load_acq_int(&th->th_generation); 16896b00cf46SPoul-Henning Kamp pps->capth = th; 169065e359a1SLawrence Stewart #ifdef FFCLOCK 169165e359a1SLawrence Stewart pps->capffth = fftimehands; 169265e359a1SLawrence Stewart #endif 16936b00cf46SPoul-Henning Kamp pps->capcount = th->th_counter->tc_get_timecount(th->th_counter); 1694f4b5a972SKonstantin Belousov atomic_thread_fence_acq(); 1695f4b5a972SKonstantin Belousov if (pps->capgen != th->th_generation) 16966b00cf46SPoul-Henning Kamp pps->capgen = 0; 16977bf758bfSPoul-Henning Kamp } 16987bf758bfSPoul-Henning Kamp 16997bf758bfSPoul-Henning Kamp void 17007bf758bfSPoul-Henning Kamp pps_event(struct pps_state *pps, int event) 170132c20357SPoul-Henning Kamp { 170239acc78aSPoul-Henning Kamp struct bintime bt; 170332c20357SPoul-Henning Kamp struct timespec ts, *tsp, *osp; 17046b00cf46SPoul-Henning Kamp u_int tcount, *pcount; 170532c20357SPoul-Henning Kamp int foff, fhard; 170632c20357SPoul-Henning Kamp pps_seq_t *pseq; 170765e359a1SLawrence Stewart #ifdef FFCLOCK 170865e359a1SLawrence Stewart struct timespec *tsp_ffc; 170965e359a1SLawrence Stewart pps_seq_t *pseq_ffc; 171065e359a1SLawrence Stewart ffcounter *ffcount; 171165e359a1SLawrence Stewart #endif 171232c20357SPoul-Henning Kamp 1713d8e8b675SPoul-Henning Kamp KASSERT(pps != NULL, ("NULL pps pointer in pps_event")); 1714721b5817SIan Lepore /* Nothing to do if not currently set to capture this event type. */ 1715721b5817SIan Lepore if ((event & pps->ppsparam.mode) == 0) 1716721b5817SIan Lepore return; 171739acc78aSPoul-Henning Kamp /* If the timecounter was wound up underneath us, bail out. */ 1718f4b5a972SKonstantin Belousov if (pps->capgen == 0 || pps->capgen != 1719f4b5a972SKonstantin Belousov atomic_load_acq_int(&pps->capth->th_generation)) 17207bf758bfSPoul-Henning Kamp return; 17217bf758bfSPoul-Henning Kamp 172239acc78aSPoul-Henning Kamp /* Things would be easier with arrays. */ 172332c20357SPoul-Henning Kamp if (event == PPS_CAPTUREASSERT) { 172432c20357SPoul-Henning Kamp tsp = &pps->ppsinfo.assert_timestamp; 172532c20357SPoul-Henning Kamp osp = &pps->ppsparam.assert_offset; 172632c20357SPoul-Henning Kamp foff = pps->ppsparam.mode & PPS_OFFSETASSERT; 1727b7424f2dSJohn Hay fhard = pps->kcmode & PPS_CAPTUREASSERT; 172832c20357SPoul-Henning Kamp pcount = &pps->ppscount[0]; 172932c20357SPoul-Henning Kamp pseq = &pps->ppsinfo.assert_sequence; 173065e359a1SLawrence Stewart #ifdef FFCLOCK 173165e359a1SLawrence Stewart ffcount = &pps->ppsinfo_ffc.assert_ffcount; 173265e359a1SLawrence Stewart tsp_ffc = &pps->ppsinfo_ffc.assert_timestamp; 173365e359a1SLawrence Stewart pseq_ffc = &pps->ppsinfo_ffc.assert_sequence; 173465e359a1SLawrence Stewart #endif 173532c20357SPoul-Henning Kamp } else { 173632c20357SPoul-Henning Kamp tsp = &pps->ppsinfo.clear_timestamp; 173732c20357SPoul-Henning Kamp osp = &pps->ppsparam.clear_offset; 173832c20357SPoul-Henning Kamp foff = pps->ppsparam.mode & PPS_OFFSETCLEAR; 1739b7424f2dSJohn Hay fhard = pps->kcmode & PPS_CAPTURECLEAR; 174032c20357SPoul-Henning Kamp pcount = &pps->ppscount[1]; 174132c20357SPoul-Henning Kamp pseq = &pps->ppsinfo.clear_sequence; 174265e359a1SLawrence Stewart #ifdef FFCLOCK 174365e359a1SLawrence Stewart ffcount = &pps->ppsinfo_ffc.clear_ffcount; 174465e359a1SLawrence Stewart tsp_ffc = &pps->ppsinfo_ffc.clear_timestamp; 174565e359a1SLawrence Stewart pseq_ffc = &pps->ppsinfo_ffc.clear_sequence; 174665e359a1SLawrence Stewart #endif 174732c20357SPoul-Henning Kamp } 174832c20357SPoul-Henning Kamp 174939acc78aSPoul-Henning Kamp /* 17506b00cf46SPoul-Henning Kamp * If the timecounter changed, we cannot compare the count values, so 17516b00cf46SPoul-Henning Kamp * we have to drop the rest of the PPS-stuff until the next event. 17526b00cf46SPoul-Henning Kamp */ 17536b00cf46SPoul-Henning Kamp if (pps->ppstc != pps->capth->th_counter) { 17546b00cf46SPoul-Henning Kamp pps->ppstc = pps->capth->th_counter; 17557bf758bfSPoul-Henning Kamp *pcount = pps->capcount; 17567bf758bfSPoul-Henning Kamp pps->ppscount[2] = pps->capcount; 175732c20357SPoul-Henning Kamp return; 175832c20357SPoul-Henning Kamp } 175932c20357SPoul-Henning Kamp 176039acc78aSPoul-Henning Kamp /* Convert the count to a timespec. */ 17616b00cf46SPoul-Henning Kamp tcount = pps->capcount - pps->capth->th_offset_count; 17626b00cf46SPoul-Henning Kamp tcount &= pps->capth->th_counter->tc_counter_mask; 17636b00cf46SPoul-Henning Kamp bt = pps->capth->th_offset; 17646b00cf46SPoul-Henning Kamp bintime_addx(&bt, pps->capth->th_scale * tcount); 1765eef633a7SPoul-Henning Kamp bintime_add(&bt, &boottimebin); 17662028c0cdSPoul-Henning Kamp bintime2timespec(&bt, &ts); 176732c20357SPoul-Henning Kamp 176839acc78aSPoul-Henning Kamp /* If the timecounter was wound up underneath us, bail out. */ 1769f4b5a972SKonstantin Belousov atomic_thread_fence_acq(); 1770f4b5a972SKonstantin Belousov if (pps->capgen != pps->capth->th_generation) 17717bf758bfSPoul-Henning Kamp return; 17727bf758bfSPoul-Henning Kamp 17737bf758bfSPoul-Henning Kamp *pcount = pps->capcount; 177432c20357SPoul-Henning Kamp (*pseq)++; 177532c20357SPoul-Henning Kamp *tsp = ts; 177632c20357SPoul-Henning Kamp 177732c20357SPoul-Henning Kamp if (foff) { 177832c20357SPoul-Henning Kamp timespecadd(tsp, osp); 177932c20357SPoul-Henning Kamp if (tsp->tv_nsec < 0) { 178032c20357SPoul-Henning Kamp tsp->tv_nsec += 1000000000; 178132c20357SPoul-Henning Kamp tsp->tv_sec -= 1; 178232c20357SPoul-Henning Kamp } 178332c20357SPoul-Henning Kamp } 178465e359a1SLawrence Stewart 178565e359a1SLawrence Stewart #ifdef FFCLOCK 178665e359a1SLawrence Stewart *ffcount = pps->capffth->tick_ffcount + tcount; 178765e359a1SLawrence Stewart bt = pps->capffth->tick_time; 178865e359a1SLawrence Stewart ffclock_convert_delta(tcount, pps->capffth->cest.period, &bt); 178965e359a1SLawrence Stewart bintime_add(&bt, &pps->capffth->tick_time); 179065e359a1SLawrence Stewart bintime2timespec(&bt, &ts); 179165e359a1SLawrence Stewart (*pseq_ffc)++; 179265e359a1SLawrence Stewart *tsp_ffc = ts; 179365e359a1SLawrence Stewart #endif 179465e359a1SLawrence Stewart 179532c20357SPoul-Henning Kamp #ifdef PPS_SYNC 179632c20357SPoul-Henning Kamp if (fhard) { 179760ae52f7SEd Schouten uint64_t scale; 1798ce9fac00SPoul-Henning Kamp 179939acc78aSPoul-Henning Kamp /* 18006b00cf46SPoul-Henning Kamp * Feed the NTP PLL/FLL. 1801b1e7e201SJohn Hay * The FLL wants to know how many (hardware) nanoseconds 1802b1e7e201SJohn Hay * elapsed since the previous event. 18036b00cf46SPoul-Henning Kamp */ 18047bf758bfSPoul-Henning Kamp tcount = pps->capcount - pps->ppscount[2]; 18057bf758bfSPoul-Henning Kamp pps->ppscount[2] = pps->capcount; 18066b00cf46SPoul-Henning Kamp tcount &= pps->capth->th_counter->tc_counter_mask; 180760ae52f7SEd Schouten scale = (uint64_t)1 << 63; 1808b1e7e201SJohn Hay scale /= pps->capth->th_counter->tc_frequency; 1809b1e7e201SJohn Hay scale *= 2; 18102028c0cdSPoul-Henning Kamp bt.sec = 0; 18112028c0cdSPoul-Henning Kamp bt.frac = 0; 1812b1e7e201SJohn Hay bintime_addx(&bt, scale * tcount); 18132028c0cdSPoul-Henning Kamp bintime2timespec(&bt, &ts); 18142028c0cdSPoul-Henning Kamp hardpps(tsp, ts.tv_nsec + 1000000000 * ts.tv_sec); 181532c20357SPoul-Henning Kamp } 181632c20357SPoul-Henning Kamp #endif 1817a1137de9SIan Lepore 1818a1137de9SIan Lepore /* Wakeup anyone sleeping in pps_fetch(). */ 1819a1137de9SIan Lepore wakeup(pps); 182032c20357SPoul-Henning Kamp } 18219e1b5510SPoul-Henning Kamp 182239acc78aSPoul-Henning Kamp /* 18239e1b5510SPoul-Henning Kamp * Timecounters need to be updated every so often to prevent the hardware 18249e1b5510SPoul-Henning Kamp * counter from overflowing. Updating also recalculates the cached values 18259e1b5510SPoul-Henning Kamp * used by the get*() family of functions, so their precision depends on 18269e1b5510SPoul-Henning Kamp * the update frequency. 18279e1b5510SPoul-Henning Kamp */ 18289e1b5510SPoul-Henning Kamp 18299e1b5510SPoul-Henning Kamp static int tc_tick; 1830b389be97SRebecca Cran SYSCTL_INT(_kern_timecounter, OID_AUTO, tick, CTLFLAG_RD, &tc_tick, 0, 1831b389be97SRebecca Cran "Approximate number of hardclock ticks in a millisecond"); 18329e1b5510SPoul-Henning Kamp 1833e7fa55afSPoul-Henning Kamp void 18340e189873SAlexander Motin tc_ticktock(int cnt) 18359e1b5510SPoul-Henning Kamp { 1836e7fa55afSPoul-Henning Kamp static int count; 18379e1b5510SPoul-Henning Kamp 18380e189873SAlexander Motin count += cnt; 18390e189873SAlexander Motin if (count < tc_tick) 1840e7fa55afSPoul-Henning Kamp return; 1841e7fa55afSPoul-Henning Kamp count = 0; 18429e1b5510SPoul-Henning Kamp tc_windup(); 18439e1b5510SPoul-Henning Kamp } 18449e1b5510SPoul-Henning Kamp 18455b999a6bSDavide Italiano static void __inline 18465b999a6bSDavide Italiano tc_adjprecision(void) 18475b999a6bSDavide Italiano { 18485b999a6bSDavide Italiano int t; 18495b999a6bSDavide Italiano 18505b999a6bSDavide Italiano if (tc_timepercentage > 0) { 18515b999a6bSDavide Italiano t = (99 + tc_timepercentage) / tc_timepercentage; 18525b999a6bSDavide Italiano tc_precexp = fls(t + (t >> 1)) - 1; 18535b999a6bSDavide Italiano FREQ2BT(hz / tc_tick, &bt_timethreshold); 18545b999a6bSDavide Italiano FREQ2BT(hz, &bt_tickthreshold); 18555b999a6bSDavide Italiano bintime_shift(&bt_timethreshold, tc_precexp); 18565b999a6bSDavide Italiano bintime_shift(&bt_tickthreshold, tc_precexp); 18575b999a6bSDavide Italiano } else { 18585b999a6bSDavide Italiano tc_precexp = 31; 18595b999a6bSDavide Italiano bt_timethreshold.sec = INT_MAX; 18605b999a6bSDavide Italiano bt_timethreshold.frac = ~(uint64_t)0; 18615b999a6bSDavide Italiano bt_tickthreshold = bt_timethreshold; 18625b999a6bSDavide Italiano } 18635b999a6bSDavide Italiano sbt_timethreshold = bttosbt(bt_timethreshold); 18645b999a6bSDavide Italiano sbt_tickthreshold = bttosbt(bt_tickthreshold); 18655b999a6bSDavide Italiano } 18665b999a6bSDavide Italiano 18675b999a6bSDavide Italiano static int 18685b999a6bSDavide Italiano sysctl_kern_timecounter_adjprecision(SYSCTL_HANDLER_ARGS) 18695b999a6bSDavide Italiano { 18705b999a6bSDavide Italiano int error, val; 18715b999a6bSDavide Italiano 18725b999a6bSDavide Italiano val = tc_timepercentage; 18735b999a6bSDavide Italiano error = sysctl_handle_int(oidp, &val, 0, req); 18745b999a6bSDavide Italiano if (error != 0 || req->newptr == NULL) 18755b999a6bSDavide Italiano return (error); 18765b999a6bSDavide Italiano tc_timepercentage = val; 1877af3b2549SHans Petter Selasky if (cold) 1878af3b2549SHans Petter Selasky goto done; 18795b999a6bSDavide Italiano tc_adjprecision(); 1880af3b2549SHans Petter Selasky done: 18815b999a6bSDavide Italiano return (0); 18825b999a6bSDavide Italiano } 18835b999a6bSDavide Italiano 18849e1b5510SPoul-Henning Kamp static void 18859e1b5510SPoul-Henning Kamp inittimecounter(void *dummy) 18869e1b5510SPoul-Henning Kamp { 18879e1b5510SPoul-Henning Kamp u_int p; 18885b999a6bSDavide Italiano int tick_rate; 18899e1b5510SPoul-Henning Kamp 189039acc78aSPoul-Henning Kamp /* 189139acc78aSPoul-Henning Kamp * Set the initial timeout to 189239acc78aSPoul-Henning Kamp * max(1, <approx. number of hardclock ticks in a millisecond>). 189339acc78aSPoul-Henning Kamp * People should probably not use the sysctl to set the timeout 189439acc78aSPoul-Henning Kamp * to smaller than its inital value, since that value is the 189539acc78aSPoul-Henning Kamp * smallest reasonable one. If they want better timestamps they 189639acc78aSPoul-Henning Kamp * should use the non-"get"* functions. 189739acc78aSPoul-Henning Kamp */ 18989e1b5510SPoul-Henning Kamp if (hz > 1000) 18999e1b5510SPoul-Henning Kamp tc_tick = (hz + 500) / 1000; 19009e1b5510SPoul-Henning Kamp else 19019e1b5510SPoul-Henning Kamp tc_tick = 1; 19025b999a6bSDavide Italiano tc_adjprecision(); 19035b999a6bSDavide Italiano FREQ2BT(hz, &tick_bt); 19045b999a6bSDavide Italiano tick_sbt = bttosbt(tick_bt); 19055b999a6bSDavide Italiano tick_rate = hz / tc_tick; 19065b999a6bSDavide Italiano FREQ2BT(tick_rate, &tc_tick_bt); 19075b999a6bSDavide Italiano tc_tick_sbt = bttosbt(tc_tick_bt); 19089e1b5510SPoul-Henning Kamp p = (tc_tick * 1000000) / hz; 19099e1b5510SPoul-Henning Kamp printf("Timecounters tick every %d.%03u msec\n", p / 1000, p % 1000); 191039acc78aSPoul-Henning Kamp 1911b0fdc837SLawrence Stewart #ifdef FFCLOCK 1912b0fdc837SLawrence Stewart ffclock_init(); 1913b0fdc837SLawrence Stewart #endif 191448e5da55SPoul-Henning Kamp /* warm up new timecounter (again) and get rolling. */ 191539acc78aSPoul-Henning Kamp (void)timecounter->tc_get_timecount(timecounter); 191639acc78aSPoul-Henning Kamp (void)timecounter->tc_get_timecount(timecounter); 191795d23438SAlexander Motin tc_windup(); 19189e1b5510SPoul-Henning Kamp } 19199e1b5510SPoul-Henning Kamp 1920237fdd78SRobert Watson SYSINIT(timecounter, SI_SUB_CLOCKS, SI_ORDER_SECOND, inittimecounter, NULL); 19215b1a8eb3SPoul-Henning Kamp 1922e8444a7eSPoul-Henning Kamp /* Cpu tick handling -------------------------------------------------*/ 1923e8444a7eSPoul-Henning Kamp 1924e8444a7eSPoul-Henning Kamp static int cpu_tick_variable; 1925e8444a7eSPoul-Henning Kamp static uint64_t cpu_tick_frequency; 1926e8444a7eSPoul-Henning Kamp 192788ca07e7SJohn Baldwin static uint64_t 19285b1a8eb3SPoul-Henning Kamp tc_cpu_ticks(void) 19295b1a8eb3SPoul-Henning Kamp { 19305b1a8eb3SPoul-Henning Kamp static uint64_t base; 19315b1a8eb3SPoul-Henning Kamp static unsigned last; 1932e8444a7eSPoul-Henning Kamp unsigned u; 19335b1a8eb3SPoul-Henning Kamp struct timecounter *tc; 19345b1a8eb3SPoul-Henning Kamp 19355b1a8eb3SPoul-Henning Kamp tc = timehands->th_counter; 19365b1a8eb3SPoul-Henning Kamp u = tc->tc_get_timecount(tc) & tc->tc_counter_mask; 19375b1a8eb3SPoul-Henning Kamp if (u < last) 1938fccfcfbaSPoul-Henning Kamp base += (uint64_t)tc->tc_counter_mask + 1; 19395b1a8eb3SPoul-Henning Kamp last = u; 19405b1a8eb3SPoul-Henning Kamp return (u + base); 19415b1a8eb3SPoul-Henning Kamp } 19425b1a8eb3SPoul-Henning Kamp 1943a157e425SAlexander Motin void 1944a157e425SAlexander Motin cpu_tick_calibration(void) 1945a157e425SAlexander Motin { 1946a157e425SAlexander Motin static time_t last_calib; 1947a157e425SAlexander Motin 1948a157e425SAlexander Motin if (time_uptime != last_calib && !(time_uptime & 0xf)) { 1949a157e425SAlexander Motin cpu_tick_calibrate(0); 1950a157e425SAlexander Motin last_calib = time_uptime; 1951a157e425SAlexander Motin } 1952a157e425SAlexander Motin } 1953a157e425SAlexander Motin 1954e8444a7eSPoul-Henning Kamp /* 19556b4d690cSWarner Losh * This function gets called every 16 seconds on only one designated 1956a157e425SAlexander Motin * CPU in the system from hardclock() via cpu_tick_calibration()(). 1957e8444a7eSPoul-Henning Kamp * 1958e8444a7eSPoul-Henning Kamp * Whenever the real time clock is stepped we get called with reset=1 1959e8444a7eSPoul-Henning Kamp * to make sure we handle suspend/resume and similar events correctly. 1960e8444a7eSPoul-Henning Kamp */ 1961e8444a7eSPoul-Henning Kamp 1962e8444a7eSPoul-Henning Kamp static void 1963e8444a7eSPoul-Henning Kamp cpu_tick_calibrate(int reset) 1964e8444a7eSPoul-Henning Kamp { 1965e8444a7eSPoul-Henning Kamp static uint64_t c_last; 1966e8444a7eSPoul-Henning Kamp uint64_t c_this, c_delta; 1967e8444a7eSPoul-Henning Kamp static struct bintime t_last; 1968e8444a7eSPoul-Henning Kamp struct bintime t_this, t_delta; 1969301af28aSPoul-Henning Kamp uint32_t divi; 1970e8444a7eSPoul-Henning Kamp 1971e8444a7eSPoul-Henning Kamp if (reset) { 1972e8444a7eSPoul-Henning Kamp /* The clock was stepped, abort & reset */ 1973e8444a7eSPoul-Henning Kamp t_last.sec = 0; 1974e8444a7eSPoul-Henning Kamp return; 1975e8444a7eSPoul-Henning Kamp } 1976e8444a7eSPoul-Henning Kamp 1977e8444a7eSPoul-Henning Kamp /* we don't calibrate fixed rate cputicks */ 1978e8444a7eSPoul-Henning Kamp if (!cpu_tick_variable) 1979e8444a7eSPoul-Henning Kamp return; 1980e8444a7eSPoul-Henning Kamp 1981e8444a7eSPoul-Henning Kamp getbinuptime(&t_this); 1982e8444a7eSPoul-Henning Kamp c_this = cpu_ticks(); 1983e8444a7eSPoul-Henning Kamp if (t_last.sec != 0) { 1984e8444a7eSPoul-Henning Kamp c_delta = c_this - c_last; 1985e8444a7eSPoul-Henning Kamp t_delta = t_this; 1986e8444a7eSPoul-Henning Kamp bintime_sub(&t_delta, &t_last); 1987e8444a7eSPoul-Henning Kamp /* 1988301af28aSPoul-Henning Kamp * Headroom: 1989301af28aSPoul-Henning Kamp * 2^(64-20) / 16[s] = 1990301af28aSPoul-Henning Kamp * 2^(44) / 16[s] = 1991301af28aSPoul-Henning Kamp * 17.592.186.044.416 / 16 = 1992301af28aSPoul-Henning Kamp * 1.099.511.627.776 [Hz] 1993301af28aSPoul-Henning Kamp */ 1994301af28aSPoul-Henning Kamp divi = t_delta.sec << 20; 1995301af28aSPoul-Henning Kamp divi |= t_delta.frac >> (64 - 20); 1996301af28aSPoul-Henning Kamp c_delta <<= 20; 1997301af28aSPoul-Henning Kamp c_delta /= divi; 1998e8444a7eSPoul-Henning Kamp if (c_delta > cpu_tick_frequency) { 199959048707SPoul-Henning Kamp if (0 && bootverbose) 2000fef527eeSPoul-Henning Kamp printf("cpu_tick increased to %ju Hz\n", 20016cda760fSPoul-Henning Kamp c_delta); 2002e8444a7eSPoul-Henning Kamp cpu_tick_frequency = c_delta; 2003e8444a7eSPoul-Henning Kamp } 2004e8444a7eSPoul-Henning Kamp } 2005e8444a7eSPoul-Henning Kamp c_last = c_this; 2006e8444a7eSPoul-Henning Kamp t_last = t_this; 2007e8444a7eSPoul-Henning Kamp } 2008e8444a7eSPoul-Henning Kamp 2009e8444a7eSPoul-Henning Kamp void 2010e8444a7eSPoul-Henning Kamp set_cputicker(cpu_tick_f *func, uint64_t freq, unsigned var) 2011e8444a7eSPoul-Henning Kamp { 2012e8444a7eSPoul-Henning Kamp 2013e8444a7eSPoul-Henning Kamp if (func == NULL) { 2014e8444a7eSPoul-Henning Kamp cpu_ticks = tc_cpu_ticks; 2015e8444a7eSPoul-Henning Kamp } else { 2016e8444a7eSPoul-Henning Kamp cpu_tick_frequency = freq; 2017e8444a7eSPoul-Henning Kamp cpu_tick_variable = var; 2018e8444a7eSPoul-Henning Kamp cpu_ticks = func; 2019e8444a7eSPoul-Henning Kamp } 2020e8444a7eSPoul-Henning Kamp } 2021e8444a7eSPoul-Henning Kamp 2022e8444a7eSPoul-Henning Kamp uint64_t 2023e8444a7eSPoul-Henning Kamp cpu_tickrate(void) 2024e8444a7eSPoul-Henning Kamp { 2025e8444a7eSPoul-Henning Kamp 2026e8444a7eSPoul-Henning Kamp if (cpu_ticks == tc_cpu_ticks) 2027e8444a7eSPoul-Henning Kamp return (tc_getfrequency()); 2028e8444a7eSPoul-Henning Kamp return (cpu_tick_frequency); 2029e8444a7eSPoul-Henning Kamp } 2030e8444a7eSPoul-Henning Kamp 2031e8444a7eSPoul-Henning Kamp /* 2032e8444a7eSPoul-Henning Kamp * We need to be slightly careful converting cputicks to microseconds. 2033e8444a7eSPoul-Henning Kamp * There is plenty of margin in 64 bits of microseconds (half a million 2034e8444a7eSPoul-Henning Kamp * years) and in 64 bits at 4 GHz (146 years), but if we do a multiply 2035e8444a7eSPoul-Henning Kamp * before divide conversion (to retain precision) we find that the 2036e8444a7eSPoul-Henning Kamp * margin shrinks to 1.5 hours (one millionth of 146y). 2037776fc0e9SYaroslav Tykhiy * With a three prong approach we never lose significant bits, no 2038e8444a7eSPoul-Henning Kamp * matter what the cputick rate and length of timeinterval is. 2039e8444a7eSPoul-Henning Kamp */ 2040e8444a7eSPoul-Henning Kamp 2041e8444a7eSPoul-Henning Kamp uint64_t 2042e8444a7eSPoul-Henning Kamp cputick2usec(uint64_t tick) 2043e8444a7eSPoul-Henning Kamp { 2044e8444a7eSPoul-Henning Kamp 2045e8444a7eSPoul-Henning Kamp if (tick > 18446744073709551LL) /* floor(2^64 / 1000) */ 2046e8444a7eSPoul-Henning Kamp return (tick / (cpu_tickrate() / 1000000LL)); 2047e8444a7eSPoul-Henning Kamp else if (tick > 18446744073709LL) /* floor(2^64 / 1000000) */ 2048e8444a7eSPoul-Henning Kamp return ((tick * 1000LL) / (cpu_tickrate() / 1000LL)); 2049e8444a7eSPoul-Henning Kamp else 2050e8444a7eSPoul-Henning Kamp return ((tick * 1000000LL) / cpu_tickrate()); 2051e8444a7eSPoul-Henning Kamp } 2052e8444a7eSPoul-Henning Kamp 2053e8444a7eSPoul-Henning Kamp cpu_tick_f *cpu_ticks = tc_cpu_ticks; 2054aea81038SKonstantin Belousov 2055aea81038SKonstantin Belousov static int vdso_th_enable = 1; 2056aea81038SKonstantin Belousov static int 2057aea81038SKonstantin Belousov sysctl_fast_gettime(SYSCTL_HANDLER_ARGS) 2058aea81038SKonstantin Belousov { 2059aea81038SKonstantin Belousov int old_vdso_th_enable, error; 2060aea81038SKonstantin Belousov 2061aea81038SKonstantin Belousov old_vdso_th_enable = vdso_th_enable; 2062aea81038SKonstantin Belousov error = sysctl_handle_int(oidp, &old_vdso_th_enable, 0, req); 2063aea81038SKonstantin Belousov if (error != 0) 2064aea81038SKonstantin Belousov return (error); 2065aea81038SKonstantin Belousov vdso_th_enable = old_vdso_th_enable; 2066aea81038SKonstantin Belousov return (0); 2067aea81038SKonstantin Belousov } 2068aea81038SKonstantin Belousov SYSCTL_PROC(_kern_timecounter, OID_AUTO, fast_gettime, 2069aea81038SKonstantin Belousov CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, 2070aea81038SKonstantin Belousov NULL, 0, sysctl_fast_gettime, "I", "Enable fast time of day"); 2071aea81038SKonstantin Belousov 2072aea81038SKonstantin Belousov uint32_t 2073aea81038SKonstantin Belousov tc_fill_vdso_timehands(struct vdso_timehands *vdso_th) 2074aea81038SKonstantin Belousov { 2075aea81038SKonstantin Belousov struct timehands *th; 2076aea81038SKonstantin Belousov uint32_t enabled; 2077aea81038SKonstantin Belousov 2078aea81038SKonstantin Belousov th = timehands; 2079aea81038SKonstantin Belousov vdso_th->th_algo = VDSO_TH_ALGO_1; 2080aea81038SKonstantin Belousov vdso_th->th_scale = th->th_scale; 2081aea81038SKonstantin Belousov vdso_th->th_offset_count = th->th_offset_count; 2082aea81038SKonstantin Belousov vdso_th->th_counter_mask = th->th_counter->tc_counter_mask; 2083aea81038SKonstantin Belousov vdso_th->th_offset = th->th_offset; 2084aea81038SKonstantin Belousov vdso_th->th_boottime = boottimebin; 2085d1b1b600SNeel Natu enabled = cpu_fill_vdso_timehands(vdso_th, th->th_counter); 2086aea81038SKonstantin Belousov if (!vdso_th_enable) 2087aea81038SKonstantin Belousov enabled = 0; 2088aea81038SKonstantin Belousov return (enabled); 2089aea81038SKonstantin Belousov } 2090aea81038SKonstantin Belousov 2091aea81038SKonstantin Belousov #ifdef COMPAT_FREEBSD32 2092aea81038SKonstantin Belousov uint32_t 2093aea81038SKonstantin Belousov tc_fill_vdso_timehands32(struct vdso_timehands32 *vdso_th32) 2094aea81038SKonstantin Belousov { 2095aea81038SKonstantin Belousov struct timehands *th; 2096aea81038SKonstantin Belousov uint32_t enabled; 2097aea81038SKonstantin Belousov 2098aea81038SKonstantin Belousov th = timehands; 2099aea81038SKonstantin Belousov vdso_th32->th_algo = VDSO_TH_ALGO_1; 2100aea81038SKonstantin Belousov *(uint64_t *)&vdso_th32->th_scale[0] = th->th_scale; 2101aea81038SKonstantin Belousov vdso_th32->th_offset_count = th->th_offset_count; 2102aea81038SKonstantin Belousov vdso_th32->th_counter_mask = th->th_counter->tc_counter_mask; 2103aea81038SKonstantin Belousov vdso_th32->th_offset.sec = th->th_offset.sec; 2104aea81038SKonstantin Belousov *(uint64_t *)&vdso_th32->th_offset.frac[0] = th->th_offset.frac; 2105aea81038SKonstantin Belousov vdso_th32->th_boottime.sec = boottimebin.sec; 2106aea81038SKonstantin Belousov *(uint64_t *)&vdso_th32->th_boottime.frac[0] = boottimebin.frac; 2107d1b1b600SNeel Natu enabled = cpu_fill_vdso_timehands32(vdso_th32, th->th_counter); 2108aea81038SKonstantin Belousov if (!vdso_th_enable) 2109aea81038SKonstantin Belousov enabled = 0; 2110aea81038SKonstantin Belousov return (enabled); 2111aea81038SKonstantin Belousov } 2112aea81038SKonstantin Belousov #endif 2113