10 #include <sys/cdefs.h>
13 #include "opt_compat.h"
16 #include <sys/param.h>
17 #include <sys/kernel.h>
18 #include <sys/sysctl.h>
19 #include <sys/syslog.h>
20 #include <sys/systm.h>
21 #include <sys/timepps.h>
22 #include <sys/timetc.h>
23 #include <sys/timex.h>
32 #define LARGE_STEP 200
67 static struct timehands th9 = { NULL, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0, &
th0};
68 static struct timehands th8 = { NULL, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0, &th9};
69 static struct timehands th7 = { NULL, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0, &th8};
70 static struct timehands th6 = { NULL, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0, &th7};
71 static struct timehands th5 = { NULL, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0, &th6};
72 static struct timehands th4 = { NULL, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0, &th5};
73 static struct timehands th3 = { NULL, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0, &th4};
74 static struct timehands th2 = { NULL, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0, &th3};
75 static struct timehands th1 = { NULL, 0, 0, 0, {0, 0}, {0, 0}, {0, 0}, 0, &th2};
79 (uint64_t)-1 / 1000000,
104 static SYSCTL_NODE(_kern_timecounter, OID_AUTO, tc, CTLFLAG_RW, 0,
"");
107 SYSCTL_INT(_kern_timecounter, OID_AUTO, stepwarnings, CTLFLAG_RW,
121 if (req->flags & SCTL_MASK32) {
124 return SYSCTL_OUT(req, tv,
sizeof(tv));
136 ncount = tc->tc_get_timecount(tc);
146 freq = tc->tc_frequency;
154 static __inline u_int
161 tc->tc_counter_mask);
173 struct timehands *th;
190 bintime2timespec(&bt, tsp);
199 bintime2timeval(&bt, tvp);
216 bintime2timespec(&bt, tsp);
225 bintime2timeval(&bt, tvp);
231 struct timehands *th;
244 struct timehands *th;
257 struct timehands *th;
270 struct timehands *th;
284 struct timehands *th;
297 struct timehands *th;
315 struct timehands *th;
332 struct sysctl_oid *tc_root;
334 u = tc->tc_frequency / tc->tc_counter_mask;
338 if (u >
hz && tc->tc_quality >= 0) {
339 tc->tc_quality = -2000;
341 printf(
"Timecounter \"%s\" frequency %ju Hz",
342 tc->tc_name, (uintmax_t)tc->tc_frequency);
343 printf(
" -- Insufficient hz, needs at least %u\n", u);
346 printf(
"Timecounter \"%s\" frequency %ju Hz quality %d\n",
347 tc->tc_name, (uintmax_t)tc->tc_frequency,
356 tc_root = SYSCTL_ADD_NODE(NULL,
357 SYSCTL_STATIC_CHILDREN(_kern_timecounter_tc), OID_AUTO, tc->tc_name,
358 CTLFLAG_RW, 0,
"timecounter description");
359 SYSCTL_ADD_UINT(NULL, SYSCTL_CHILDREN(tc_root), OID_AUTO,
360 "mask", CTLFLAG_RD, &(tc->tc_counter_mask), 0,
361 "mask for implemented bits");
362 SYSCTL_ADD_PROC(NULL, SYSCTL_CHILDREN(tc_root), OID_AUTO,
363 "counter", CTLTYPE_UINT | CTLFLAG_RD, tc,
sizeof(*tc),
365 SYSCTL_ADD_PROC(NULL, SYSCTL_CHILDREN(tc_root), OID_AUTO,
366 "frequency", CTLTYPE_U64 | CTLFLAG_RD, tc,
sizeof(*tc),
368 SYSCTL_ADD_INT(NULL, SYSCTL_CHILDREN(tc_root), OID_AUTO,
369 "quality", CTLFLAG_RD, &(tc->tc_quality), 0,
370 "goodness of time counter");
376 if (tc->tc_quality < 0)
383 (void)tc->tc_get_timecount(tc);
384 (void)tc->tc_get_timecount(tc);
404 struct timespec tbef, taft;
409 timespec2bintime(ts, &bt);
411 bintime_sub(&bt, &bt2);
421 "Time stepped from %jd.%09ld to %jd.%09ld (%jd.%09ld)\n",
422 (intmax_t)tbef.tv_sec, tbef.tv_nsec,
423 (intmax_t)taft.tv_sec, taft.tv_nsec,
424 (intmax_t)ts->tv_sec, ts->tv_nsec);
438 struct timehands *th, *tho;
440 u_int delta, ncount, ogen;
467 while (delta > th->
th_counter->tc_frequency) {
472 if ((delta > th->
th_counter->tc_frequency / 2) &&
473 (th->
th_scale * delta < ((uint64_t)1 << 63))) {
518 if ((
timecounter->tc_flags & TC_FLAGS_C2STOP) != 0)
520 if ((th->
th_counter->tc_flags & TC_FLAGS_C2STOP) != 0)
526 (((uint64_t)
timecounter->tc_counter_mask + 1) / 3));
552 scale = (uint64_t)1 << 63;
581 strlcpy(newname, tc->tc_name,
sizeof(newname));
584 if (error != 0 || req->newptr == NULL ||
585 strcmp(newname, tc->tc_name) == 0)
587 for (newtc =
timecounters; newtc != NULL; newtc = newtc->tc_next) {
588 if (strcmp(newname, newtc->tc_name) != 0)
592 (void)newtc->tc_get_timecount(newtc);
593 (void)newtc->tc_get_timecount(newtc);
602 SYSCTL_PROC(_kern_timecounter, OID_AUTO, hardware, CTLTYPE_STRING | CTLFLAG_RW,
604 "Timecounter hardware selected");
617 for (tc =
timecounters; error == 0 && tc != NULL; tc = tc->tc_next) {
619 spc, tc->tc_name, tc->tc_quality);
620 error = SYSCTL_OUT(req, buf, strlen(buf));
626 SYSCTL_PROC(_kern_timecounter, OID_AUTO, choice, CTLTYPE_STRING | CTLFLAG_RD,
634 pps_ioctl(u_long cmd, caddr_t data,
struct pps_state *pps)
637 struct pps_fetch_args *fapi;
639 struct pps_kcbind_args *kapi;
642 KASSERT(pps != NULL, (
"NULL pps pointer in pps_ioctl"));
646 case PPS_IOC_DESTROY:
648 case PPS_IOC_SETPARAMS:
649 app = (pps_params_t *)data;
650 if (app->mode & ~pps->ppscap)
652 pps->ppsparam = *app;
654 case PPS_IOC_GETPARAMS:
655 app = (pps_params_t *)data;
656 *app = pps->ppsparam;
657 app->api_version = PPS_API_VERS_1;
660 *(
int*)data = pps->ppscap;
663 fapi = (
struct pps_fetch_args *)data;
664 if (fapi->tsformat && fapi->tsformat != PPS_TSFMT_TSPEC)
666 if (fapi->timeout.tv_sec || fapi->timeout.tv_nsec)
668 pps->ppsinfo.current_mode = pps->ppsparam.mode;
669 fapi->pps_info_buf = pps->ppsinfo;
673 kapi = (
struct pps_kcbind_args *)data;
675 if (kapi->tsformat && kapi->tsformat != PPS_TSFMT_TSPEC)
677 if (kapi->kernel_consumer != PPS_KC_HARDPPS)
679 if (kapi->edge & ~pps->ppscap)
681 pps->kcmode = kapi->edge;
694 pps->ppscap |= PPS_TSFMT_TSPEC;
695 if (pps->ppscap & PPS_CAPTUREASSERT)
696 pps->ppscap |= PPS_OFFSETASSERT;
697 if (pps->ppscap & PPS_CAPTURECLEAR)
698 pps->ppscap |= PPS_OFFSETCLEAR;
704 struct timehands *th;
706 KASSERT(pps != NULL, (
"NULL pps pointer in pps_capture"));
719 struct timespec ts, *tsp, *osp;
720 u_int tcount, *pcount;
724 KASSERT(pps != NULL, (
"NULL pps pointer in pps_event"));
726 if (pps->capgen == 0 || pps->capgen != pps->capth->th_generation)
730 if (event == PPS_CAPTUREASSERT) {
731 tsp = &pps->ppsinfo.assert_timestamp;
732 osp = &pps->ppsparam.assert_offset;
733 foff = pps->ppsparam.mode & PPS_OFFSETASSERT;
734 fhard = pps->kcmode & PPS_CAPTUREASSERT;
735 pcount = &pps->ppscount[0];
736 pseq = &pps->ppsinfo.assert_sequence;
738 tsp = &pps->ppsinfo.clear_timestamp;
739 osp = &pps->ppsparam.clear_offset;
740 foff = pps->ppsparam.mode & PPS_OFFSETCLEAR;
741 fhard = pps->kcmode & PPS_CAPTURECLEAR;
742 pcount = &pps->ppscount[1];
743 pseq = &pps->ppsinfo.clear_sequence;
750 if (pps->ppstc != pps->capth->th_counter) {
751 pps->ppstc = pps->capth->th_counter;
752 *pcount = pps->capcount;
753 pps->ppscount[2] = pps->capcount;
758 tcount = pps->capcount - pps->capth->th_offset_count;
759 tcount &= pps->capth->th_counter->tc_counter_mask;
760 bt = pps->capth->th_offset;
761 bintime_addx(&bt, pps->capth->th_scale * tcount);
763 bintime2timespec(&bt, &ts);
766 if (pps->capgen != pps->capth->th_generation)
769 *pcount = pps->capcount;
774 timespecadd(tsp, osp);
775 if (tsp->tv_nsec < 0) {
776 tsp->tv_nsec += 1000000000;
789 tcount = pps->capcount - pps->ppscount[2];
790 pps->ppscount[2] = pps->capcount;
791 tcount &= pps->capth->th_counter->tc_counter_mask;
792 scale = (uint64_t)1 << 63;
793 scale /= pps->capth->th_counter->tc_frequency;
797 bintime_addx(&bt, scale * tcount);
798 bintime2timespec(&bt, &ts);
799 hardpps(tsp, ts.tv_nsec + 1000000000 * ts.tv_sec);
813 "Approximate number of hardclock ticks in a millisecond");
845 printf(
"Timecounters tick every %d.%03u msec\n", p / 1000, p % 1000);
863 static uint64_t base;
864 static unsigned last;
869 u = tc->tc_get_timecount(tc) & tc->tc_counter_mask;
871 base += (uint64_t)tc->tc_counter_mask + 1;
879 static time_t last_calib;
898 static uint64_t c_last;
899 uint64_t c_this, c_delta;
901 struct bintime t_this, t_delta;
916 if (t_last.sec != 0) {
917 c_delta = c_this - c_last;
919 bintime_sub(&t_delta, &t_last);
927 divi = t_delta.sec << 20;
928 divi |= t_delta.frac >> (64 - 20);
933 printf(
"cpu_tick increased to %ju Hz\n",
978 if (tick > 18446744073709551LL)
980 else if (tick > 18446744073709LL)
992 int old_vdso_th_enable, error;
1002 SYSCTL_PROC(_kern_timecounter, OID_AUTO, fast_gettime,
1003 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE,
1009 struct timehands *th;
1013 vdso_th->th_algo = VDSO_TH_ALGO_1;
1016 vdso_th->th_counter_mask = th->
th_counter->tc_counter_mask;
1027 tc_fill_vdso_timehands32(
struct vdso_timehands32 *vdso_th32)
1029 struct timehands *th;
1033 vdso_th32->th_algo = VDSO_TH_ALGO_1;
1036 vdso_th32->th_counter_mask = th->
th_counter->tc_counter_mask;
1037 vdso_th32->th_offset.sec = th->
th_offset.sec;
1038 *(uint64_t *)&vdso_th32->th_offset.frac[0] = th->
th_offset.frac;
1040 *(uint64_t *)&vdso_th32->th_boottime.frac[0] =
boottimebin.frac;
1041 enabled = cpu_fill_vdso_timehands32(vdso_th32);
void set_cputicker(cpu_tick_f *func, uint64_t freq, unsigned var)
static struct timehands th3
static struct timehands th5
volatile time_t time_second
struct timehands * th_next
uint32_t cpu_fill_vdso_timehands(struct vdso_timehands *vdso_th)
void tc_ticktock(int cnt)
static void tc_windup(void)
int sprintf(char *buf, const char *cfmt,...)
void tc_init(struct timecounter *tc)
static int sysctl_kern_timecounter_get(SYSCTL_HANDLER_ARGS)
int pps_ioctl(u_long cmd, caddr_t data, struct pps_state *pps)
static struct timehands th4
void pps_init(struct pps_state *pps)
static struct timecounter dummy_timecounter
static void cpu_tick_calibrate(int)
int sysctl_handle_string(SYSCTL_HANDLER_ARGS)
void getnanouptime(struct timespec *tsp)
static int sysctl_kern_timecounter_hardware(SYSCTL_HANDLER_ARGS)
static int sysctl_fast_gettime(SYSCTL_HANDLER_ARGS)
void getmicrouptime(struct timeval *tvp)
struct bintime boottimebin
static int cpu_tick_variable
void ntp_update_second(int64_t *adjustment, time_t *newsec)
volatile u_int th_generation
struct timecounter * timecounter
uint64_t cputick2usec(uint64_t tick)
static void inittimecounter(void *dummy)
void tc_setclock(struct timespec *ts)
SYSCTL_INT(_kern_timecounter, OID_AUTO, stepwarnings, CTLFLAG_RW,×tepwarnings, 0,"Log time steps")
static struct timecounter * timecounters
static struct timehands th7
int sysctl_handle_int(SYSCTL_HANDLER_ARGS)
void getmicrotime(struct timeval *tvp)
static int sysctl_kern_boottime(SYSCTL_HANDLER_ARGS)
void nanotime(struct timespec *tsp)
int sysctl_handle_64(SYSCTL_HANDLER_ARGS)
static int vdso_th_enable
static u_int dummy_get_timecount(struct timecounter *tc)
void log(int level, const char *fmt,...)
SYSINIT(timecounter, SI_SUB_CLOCKS, SI_ORDER_SECOND, inittimecounter, NULL)
static __inline u_int tc_delta(struct timehands *th)
void getnanotime(struct timespec *tsp)
void pps_event(struct pps_state *pps, int event)
struct timecounter * th_counter
struct timeval th_microtime
int printf(const char *fmt,...)
static int timestepwarnings
static int sysctl_kern_timecounter_choice(SYSCTL_HANDLER_ARGS)
static struct timehands th1
uint32_t tc_fill_vdso_timehands(struct vdso_timehands *vdso_th)
void bintime(struct bintime *bt)
void dtrace_getnanotime(struct timespec *tsp)
void getbinuptime(struct bintime *bt)
SYSCTL_PROC(_kern, KERN_BOOTTIME, boottime, CTLTYPE_STRUCT|CTLFLAG_RD, NULL, 0, sysctl_kern_boottime,"S,timeval","System boottime")
void getbintime(struct bintime *bt)
uint64_t cpu_tickrate(void)
uint64_t tc_getfrequency(void)
volatile time_t time_uptime
void microuptime(struct timeval *tvp)
void binuptime(struct bintime *bt)
void timekeep_push_vdso(void)
void pps_capture(struct pps_state *pps)
void microtime(struct timeval *tvp)
static struct timehands *volatile timehands
void nanouptime(struct timespec *tsp)
static struct timehands th6
static uint64_t tc_cpu_ticks(void)
static struct timehands th9
static struct timehands th2
void cpu_tick_calibration(void)
static struct timehands th0
SYSCTL_NODE(_kern, OID_AUTO, timecounter, CTLFLAG_RW, 0,"")
static uint64_t cpu_tick_frequency
static int sysctl_kern_timecounter_freq(SYSCTL_HANDLER_ARGS)
static struct timehands th8
struct timespec th_nanotime