35#include "opt_ffclock.h"
39#include <sys/kernel.h>
41#include <sys/module.h>
46#include <sys/sysent.h>
47#include <sys/sysproto.h>
48#include <sys/sysctl.h>
50#include <sys/timeffc.h>
54FEATURE(ffclock,
"Feed-forward clock support");
56extern struct ffclock_estimate ffclock_estimate;
57extern struct bintime ffclock_boottime;
58extern int8_t ffclock_updated;
59extern struct mtx ffclock_mtx;
71ffclock_abstime(ffcounter *ffcount,
struct bintime *
bt,
74 struct ffclock_estimate cest;
76 ffcounter update_ffcount;
77 ffcounter ffdelta_error;
80 if ((
flags & FFCLOCK_FAST) == FFCLOCK_FAST)
81 ffclock_last_tick(&ffc,
bt,
flags);
83 ffclock_read_counter(&ffc);
84 ffclock_convert_abs(ffc,
bt,
flags);
89 update_ffcount = ffclock_estimate.update_ffcount;
90 bcopy(&ffclock_estimate, &cest,
sizeof(
struct ffclock_estimate));
91 }
while (update_ffcount != ffclock_estimate.update_ffcount);
98 if ((
flags & FFCLOCK_LEAPSEC) == FFCLOCK_LEAPSEC) {
99 bt->sec -= cest.leapsec_total;
100 if (ffc > cest.leapsec_next)
101 bt->sec -= cest.leapsec;
105 if ((
flags & FFCLOCK_UPTIME) == FFCLOCK_UPTIME) {
106 bintime_sub(
bt, &ffclock_boottime);
111 ffdelta_error = ffc - cest.update_ffcount;
112 ffclock_convert_diff(ffdelta_error, error_bound);
114 bintime_mul(error_bound, cest.errb_rate *
115 (uint64_t)18446744073709LL);
117 bintime_addx(error_bound, cest.errb_abs *
118 (uint64_t)18446744073LL);
132ffclock_difftime(ffcounter ffdelta,
struct bintime *
bt,
135 ffcounter update_ffcount;
138 ffclock_convert_diff(ffdelta,
bt);
142 update_ffcount = ffclock_estimate.update_ffcount;
143 err_rate = ffclock_estimate.errb_rate;
144 }
while (update_ffcount != ffclock_estimate.update_ffcount);
146 ffclock_convert_diff(ffdelta, error_bound);
148 bintime_mul(error_bound, err_rate * (uint64_t)18446744073709LL);
158SYSCTL_NODE(_kern, OID_AUTO, sysclock, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
159 "System clock related configuration");
160SYSCTL_NODE(_kern_sysclock, OID_AUTO, ffclock, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
161 "Feed-forward clock configuration");
163static char *sysclocks[] = {
"feedback",
"feed-forward"};
164#define MAX_SYSCLOCK_NAME_LEN 16
165#define NUM_SYSCLOCKS nitems(sysclocks)
167static int ffclock_version = 2;
168SYSCTL_INT(_kern_sysclock_ffclock, OID_AUTO, version, CTLFLAG_RD,
169 &ffclock_version, 0,
"Feed-forward clock kernel version");
173sysctl_kern_sysclock_available(SYSCTL_HANDLER_ARGS)
179 MAX_SYSCLOCK_NAME_LEN * NUM_SYSCLOCKS, req);
183 for (clk = 0; clk < NUM_SYSCLOCKS; clk++) {
185 if (clk + 1 < NUM_SYSCLOCKS)
195 CTLTYPE_STRING | CTLFLAG_RD | CTLFLAG_NEEDGIANT, 0, 0,
196 sysctl_kern_sysclock_available,
"A",
197 "List of available system clocks");
206sysctl_kern_sysclock_active(SYSCTL_HANDLER_ARGS)
208 char newclock[MAX_SYSCLOCK_NAME_LEN];
217 if (error != 0 || req->newptr == NULL)
222 for (clk = 0; clk < NUM_SYSCLOCKS; clk++) {
223 if (strncmp(newclock, sysclocks[clk],
224 MAX_SYSCLOCK_NAME_LEN - 1)) {
236 CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_NEEDGIANT, 0, 0,
237 sysctl_kern_sysclock_active,
"A",
238 "Name of the active system clock which is currently serving time");
240static int sysctl_kern_ffclock_ffcounter_bypass = 0;
241SYSCTL_INT(_kern_sysclock_ffclock, OID_AUTO, ffcounter_bypass, CTLFLAG_RW,
242 &sysctl_kern_ffclock_ffcounter_bypass, 0,
243 "Use reliable hardware timecounter as the feed-forward counter");
252 ffclock_abstime(NULL,
bt, NULL, FFCLOCK_LERP | FFCLOCK_LEAPSEC);
256ffclock_nanotime(
struct timespec *tsp)
260 ffclock_abstime(NULL, &
bt, NULL, FFCLOCK_LERP | FFCLOCK_LEAPSEC);
261 bintime2timespec(&
bt, tsp);
265ffclock_microtime(
struct timeval *tvp)
269 ffclock_abstime(NULL, &
bt, NULL, FFCLOCK_LERP | FFCLOCK_LEAPSEC);
270 bintime2timeval(&
bt, tvp);
277 ffclock_abstime(NULL,
bt, NULL,
278 FFCLOCK_LERP | FFCLOCK_LEAPSEC | FFCLOCK_FAST);
282ffclock_getnanotime(
struct timespec *tsp)
286 ffclock_abstime(NULL, &
bt, NULL,
287 FFCLOCK_LERP | FFCLOCK_LEAPSEC | FFCLOCK_FAST);
288 bintime2timespec(&
bt, tsp);
292ffclock_getmicrotime(
struct timeval *tvp)
296 ffclock_abstime(NULL, &
bt, NULL,
297 FFCLOCK_LERP | FFCLOCK_LEAPSEC | FFCLOCK_FAST);
298 bintime2timeval(&
bt, tvp);
305 ffclock_abstime(NULL,
bt, NULL, FFCLOCK_LERP | FFCLOCK_UPTIME);
309ffclock_nanouptime(
struct timespec *tsp)
313 ffclock_abstime(NULL, &
bt, NULL, FFCLOCK_LERP | FFCLOCK_UPTIME);
314 bintime2timespec(&
bt, tsp);
318ffclock_microuptime(
struct timeval *tvp)
322 ffclock_abstime(NULL, &
bt, NULL, FFCLOCK_LERP | FFCLOCK_UPTIME);
323 bintime2timeval(&
bt, tvp);
330 ffclock_abstime(NULL,
bt, NULL,
331 FFCLOCK_LERP | FFCLOCK_UPTIME | FFCLOCK_FAST);
335ffclock_getnanouptime(
struct timespec *tsp)
339 ffclock_abstime(NULL, &
bt, NULL,
340 FFCLOCK_LERP | FFCLOCK_UPTIME | FFCLOCK_FAST);
341 bintime2timespec(&
bt, tsp);
345ffclock_getmicrouptime(
struct timeval *tvp)
349 ffclock_abstime(NULL, &
bt, NULL,
350 FFCLOCK_LERP | FFCLOCK_UPTIME | FFCLOCK_FAST);
351 bintime2timeval(&
bt, tvp);
355ffclock_bindifftime(ffcounter ffdelta,
struct bintime *
bt)
358 ffclock_difftime(ffdelta,
bt, NULL);
362ffclock_nanodifftime(ffcounter ffdelta,
struct timespec *tsp)
366 ffclock_difftime(ffdelta, &
bt, NULL);
367 bintime2timespec(&
bt, tsp);
371ffclock_microdifftime(ffcounter ffdelta,
struct timeval *tvp)
375 ffclock_difftime(ffdelta, &
bt, NULL);
376 bintime2timeval(&
bt, tvp);
383#ifndef _SYS_SYSPROTO_H_
384struct ffclock_getcounter_args {
396 ffclock_read_counter(&ffcount);
399 error = copyout(&ffcount, uap->ffcount,
sizeof(ffcounter));
412#ifndef _SYS_SYSPROTO_H_
413struct ffclock_setestimate_args {
414 struct ffclock_estimate *cest;
421 struct ffclock_estimate cest;
425 if ((error =
priv_check(td, PRIV_CLOCK_SETTIME)) != 0)
428 if ((error = copyin(uap->cest, &cest,
sizeof(
struct ffclock_estimate)))
432 mtx_lock(&ffclock_mtx);
433 memcpy(&ffclock_estimate, &cest,
sizeof(
struct ffclock_estimate));
435 mtx_unlock(&ffclock_mtx);
444#ifndef _SYS_SYSPROTO_H_
445struct ffclock_getestimate_args {
446 struct ffclock_estimate *cest;
453 struct ffclock_estimate cest;
456 mtx_lock(&ffclock_mtx);
457 memcpy(&cest, &ffclock_estimate,
sizeof(
struct ffclock_estimate));
458 mtx_unlock(&ffclock_mtx);
459 error = copyout(&cest, uap->cest,
sizeof(
struct ffclock_estimate));
SYSCTL_NODE(_kern, OID_AUTO, binmisc, CTLFLAG_RW|CTLFLAG_MPSAFE, 0, "Image activator for miscellaneous binaries")
SYSCTL_PROC(_kern_binmisc, OID_AUTO, add, CTLFLAG_MPSAFE|CTLTYPE_STRUCT|CTLFLAG_WR, NULL, IBC_ADD, sysctl_kern_binmisc, "S,ximgact_binmisc_entry", "Add an activator entry")
SYSCTL_INT(ASLR_NODE_OID, OID_AUTO, enable, CTLFLAG_RWTUN, &__elfN(aslr_enabled), 0, ": enable address map randomization")
static struct bt_table bt
FEATURE(kdtrace_hooks, "Kernel DTrace hooks which are required to load DTrace kernel modules")
int sys_ffclock_getestimate(struct thread *td, struct ffclock_getestimate_args *uap)
int sys_ffclock_setestimate(struct thread *td, struct ffclock_setestimate_args *uap)
int sys_ffclock_getcounter(struct thread *td, struct ffclock_getcounter_args *uap)
int priv_check(struct thread *td, int priv)
int sysctl_handle_string(SYSCTL_HANDLER_ARGS)
struct sbuf * sbuf_new_for_sysctl(struct sbuf *s, char *buf, int length, struct sysctl_req *req)
void bintime(struct bintime *bt)
int sbuf_finish(struct sbuf *s)
void sbuf_delete(struct sbuf *s)
int sbuf_cat(struct sbuf *s, const char *str)