1227745Slstewart/*- 2227745Slstewart * Copyright (c) 2011 The University of Melbourne 3227745Slstewart * All rights reserved. 4227745Slstewart * 5227745Slstewart * This software was developed by Julien Ridoux at the University of Melbourne 6227745Slstewart * under sponsorship from the FreeBSD Foundation. 7227745Slstewart * 8227745Slstewart * Redistribution and use in source and binary forms, with or without 9227745Slstewart * modification, are permitted provided that the following conditions 10227745Slstewart * are met: 11227745Slstewart * 1. Redistributions of source code must retain the above copyright 12227745Slstewart * notice, this list of conditions and the following disclaimer. 13227745Slstewart * 2. Redistributions in binary form must reproduce the above copyright 14227745Slstewart * notice, this list of conditions and the following disclaimer in the 15227745Slstewart * documentation and/or other materials provided with the distribution. 16227745Slstewart * 17227745Slstewart * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18227745Slstewart * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19227745Slstewart * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20227745Slstewart * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21227745Slstewart * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22227745Slstewart * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23227745Slstewart * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24227745Slstewart * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25227745Slstewart * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26227745Slstewart * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27227745Slstewart * SUCH DAMAGE. 28227745Slstewart */ 29227745Slstewart 30227745Slstewart#include <sys/cdefs.h> 31227745Slstewart__FBSDID("$FreeBSD$"); 32227745Slstewart 33227776Slstewart#include "opt_ffclock.h" 34227776Slstewart 35227745Slstewart#include <sys/param.h> 36227776Slstewart#include <sys/bus.h> 37227776Slstewart#include <sys/kernel.h> 38227776Slstewart#include <sys/lock.h> 39227776Slstewart#include <sys/module.h> 40227776Slstewart#include <sys/mutex.h> 41227776Slstewart#include <sys/priv.h> 42227776Slstewart#include <sys/proc.h> 43227747Slstewart#include <sys/sbuf.h> 44227776Slstewart#include <sys/sysent.h> 45227776Slstewart#include <sys/sysproto.h> 46227747Slstewart#include <sys/sysctl.h> 47227745Slstewart#include <sys/systm.h> 48227745Slstewart#include <sys/timeffc.h> 49227745Slstewart 50227776Slstewart#ifdef FFCLOCK 51227776Slstewart 52227986SlstewartFEATURE(ffclock, "Feed-forward clock support"); 53227986Slstewart 54227745Slstewartextern struct ffclock_estimate ffclock_estimate; 55227745Slstewartextern struct bintime ffclock_boottime; 56227776Slstewartextern int8_t ffclock_updated; 57227776Slstewartextern struct mtx ffclock_mtx; 58227745Slstewart 59227745Slstewart/* 60227745Slstewart * Feed-forward clock absolute time. This should be the preferred way to read 61227745Slstewart * the feed-forward clock for "wall-clock" type time. The flags allow to compose 62227745Slstewart * various flavours of absolute time (e.g. with or without leap seconds taken 63227745Slstewart * into account). If valid pointers are provided, the ffcounter value and an 64227745Slstewart * upper bound on clock error associated with the bintime are provided. 65227745Slstewart * NOTE: use ffclock_convert_abs() to differ the conversion of a ffcounter value 66227745Slstewart * read earlier. 67227745Slstewart */ 68227745Slstewartvoid 69227745Slstewartffclock_abstime(ffcounter *ffcount, struct bintime *bt, 70227745Slstewart struct bintime *error_bound, uint32_t flags) 71227745Slstewart{ 72227745Slstewart struct ffclock_estimate cest; 73227745Slstewart ffcounter ffc; 74227745Slstewart ffcounter update_ffcount; 75227745Slstewart ffcounter ffdelta_error; 76227745Slstewart 77227745Slstewart /* Get counter and corresponding time. */ 78227745Slstewart if ((flags & FFCLOCK_FAST) == FFCLOCK_FAST) 79227745Slstewart ffclock_last_tick(&ffc, bt, flags); 80227745Slstewart else { 81227745Slstewart ffclock_read_counter(&ffc); 82227745Slstewart ffclock_convert_abs(ffc, bt, flags); 83227745Slstewart } 84227745Slstewart 85227745Slstewart /* Current ffclock estimate, use update_ffcount as generation number. */ 86227745Slstewart do { 87227745Slstewart update_ffcount = ffclock_estimate.update_ffcount; 88227745Slstewart bcopy(&ffclock_estimate, &cest, sizeof(struct ffclock_estimate)); 89227745Slstewart } while (update_ffcount != ffclock_estimate.update_ffcount); 90227745Slstewart 91227745Slstewart /* 92227745Slstewart * Leap second adjustment. Total as seen by synchronisation algorithm 93227745Slstewart * since it started. cest.leapsec_next is the ffcounter prediction of 94227745Slstewart * when the next leapsecond occurs. 95227745Slstewart */ 96227745Slstewart if ((flags & FFCLOCK_LEAPSEC) == FFCLOCK_LEAPSEC) { 97227745Slstewart bt->sec -= cest.leapsec_total; 98227745Slstewart if (ffc > cest.leapsec_next) 99227745Slstewart bt->sec -= cest.leapsec; 100227745Slstewart } 101227745Slstewart 102227745Slstewart /* Boot time adjustment, for uptime/monotonic clocks. */ 103227745Slstewart if ((flags & FFCLOCK_UPTIME) == FFCLOCK_UPTIME) { 104227745Slstewart bintime_sub(bt, &ffclock_boottime); 105227745Slstewart } 106227745Slstewart 107227745Slstewart /* Compute error bound if a valid pointer has been passed. */ 108227745Slstewart if (error_bound) { 109227745Slstewart ffdelta_error = ffc - cest.update_ffcount; 110227745Slstewart ffclock_convert_diff(ffdelta_error, error_bound); 111227745Slstewart /* 18446744073709 = int(2^64/1e12), err_bound_rate in [ps/s] */ 112227745Slstewart bintime_mul(error_bound, cest.errb_rate * 113227745Slstewart (uint64_t)18446744073709LL); 114227745Slstewart /* 18446744073 = int(2^64 / 1e9), since err_abs in [ns] */ 115227745Slstewart bintime_addx(error_bound, cest.errb_abs * 116227745Slstewart (uint64_t)18446744073LL); 117227745Slstewart } 118227745Slstewart 119227745Slstewart if (ffcount) 120227745Slstewart *ffcount = ffc; 121227745Slstewart} 122227745Slstewart 123227745Slstewart/* 124227745Slstewart * Feed-forward difference clock. This should be the preferred way to convert a 125227745Slstewart * time interval in ffcounter values into a time interval in seconds. If a valid 126227745Slstewart * pointer is passed, an upper bound on the error in computing the time interval 127227745Slstewart * in seconds is provided. 128227745Slstewart */ 129227745Slstewartvoid 130227745Slstewartffclock_difftime(ffcounter ffdelta, struct bintime *bt, 131227745Slstewart struct bintime *error_bound) 132227745Slstewart{ 133227745Slstewart ffcounter update_ffcount; 134227745Slstewart uint32_t err_rate; 135227745Slstewart 136227745Slstewart ffclock_convert_diff(ffdelta, bt); 137227745Slstewart 138227745Slstewart if (error_bound) { 139227745Slstewart do { 140227745Slstewart update_ffcount = ffclock_estimate.update_ffcount; 141227745Slstewart err_rate = ffclock_estimate.errb_rate; 142227745Slstewart } while (update_ffcount != ffclock_estimate.update_ffcount); 143227745Slstewart 144227745Slstewart ffclock_convert_diff(ffdelta, error_bound); 145227745Slstewart /* 18446744073709 = int(2^64/1e12), err_bound_rate in [ps/s] */ 146227745Slstewart bintime_mul(error_bound, err_rate * (uint64_t)18446744073709LL); 147227745Slstewart } 148227745Slstewart} 149227747Slstewart 150227747Slstewart/* 151228173Slstewart * Create a new kern.sysclock sysctl node, which will be home to some generic 152228173Slstewart * sysclock configuration variables. Feed-forward clock specific variables will 153228173Slstewart * live under the ffclock subnode. 154227747Slstewart */ 155227747Slstewart 156228173SlstewartSYSCTL_NODE(_kern, OID_AUTO, sysclock, CTLFLAG_RW, 0, 157228173Slstewart "System clock related configuration"); 158228173SlstewartSYSCTL_NODE(_kern_sysclock, OID_AUTO, ffclock, CTLFLAG_RW, 0, 159228173Slstewart "Feed-forward clock configuration"); 160227747Slstewart 161228173Slstewartstatic char *sysclocks[] = {"feedback", "feed-forward"}; 162228173Slstewart#define MAX_SYSCLOCK_NAME_LEN 16 163298310Spfg#define NUM_SYSCLOCKS nitems(sysclocks) 164227747Slstewart 165228173Slstewartstatic int ffclock_version = 2; 166228173SlstewartSYSCTL_INT(_kern_sysclock_ffclock, OID_AUTO, version, CTLFLAG_RD, 167228173Slstewart &ffclock_version, 0, "Feed-forward clock kernel version"); 168228173Slstewart 169228173Slstewart/* List available sysclocks. */ 170227747Slstewartstatic int 171228173Slstewartsysctl_kern_sysclock_available(SYSCTL_HANDLER_ARGS) 172227747Slstewart{ 173227747Slstewart struct sbuf *s; 174227747Slstewart int clk, error; 175227747Slstewart 176228173Slstewart s = sbuf_new_for_sysctl(NULL, NULL, 177228173Slstewart MAX_SYSCLOCK_NAME_LEN * NUM_SYSCLOCKS, req); 178227747Slstewart if (s == NULL) 179227747Slstewart return (ENOMEM); 180227747Slstewart 181227747Slstewart for (clk = 0; clk < NUM_SYSCLOCKS; clk++) { 182227747Slstewart sbuf_cat(s, sysclocks[clk]); 183227747Slstewart if (clk + 1 < NUM_SYSCLOCKS) 184227747Slstewart sbuf_cat(s, " "); 185227747Slstewart } 186227747Slstewart error = sbuf_finish(s); 187227747Slstewart sbuf_delete(s); 188227747Slstewart 189227747Slstewart return (error); 190227747Slstewart} 191227747Slstewart 192228173SlstewartSYSCTL_PROC(_kern_sysclock, OID_AUTO, available, CTLTYPE_STRING | CTLFLAG_RD, 193228173Slstewart 0, 0, sysctl_kern_sysclock_available, "A", 194228173Slstewart "List of available system clocks"); 195227747Slstewart 196228173Slstewart/* 197228173Slstewart * Return the name of the active system clock if read, or attempt to change 198228173Slstewart * the active system clock to the user specified one if written to. The active 199228173Slstewart * system clock is read when calling any of the [get]{bin,nano,micro}[up]time() 200228173Slstewart * functions. 201228173Slstewart */ 202227747Slstewartstatic int 203228173Slstewartsysctl_kern_sysclock_active(SYSCTL_HANDLER_ARGS) 204227747Slstewart{ 205228173Slstewart char newclock[MAX_SYSCLOCK_NAME_LEN]; 206273773Shselasky int error; 207273773Shselasky int clk; 208227747Slstewart 209273773Shselasky /* Return the name of the current active sysclock. */ 210273773Shselasky strlcpy(newclock, sysclocks[sysclock_active], sizeof(newclock)); 211273773Shselasky error = sysctl_handle_string(oidp, newclock, sizeof(newclock), req); 212273773Shselasky 213273773Shselasky /* Check for error or no change */ 214273773Shselasky if (error != 0 || req->newptr == NULL) 215273773Shselasky goto done; 216273773Shselasky 217273773Shselasky /* Change the active sysclock to the user specified one: */ 218273773Shselasky error = EINVAL; 219273773Shselasky for (clk = 0; clk < NUM_SYSCLOCKS; clk++) { 220273773Shselasky if (strncmp(newclock, sysclocks[clk], 221273773Shselasky MAX_SYSCLOCK_NAME_LEN - 1)) { 222273773Shselasky continue; 223228173Slstewart } 224273773Shselasky sysclock_active = clk; 225273773Shselasky error = 0; 226273773Shselasky break; 227227747Slstewart } 228273773Shselaskydone: 229227747Slstewart return (error); 230227747Slstewart} 231227747Slstewart 232228173SlstewartSYSCTL_PROC(_kern_sysclock, OID_AUTO, active, CTLTYPE_STRING | CTLFLAG_RW, 233228173Slstewart 0, 0, sysctl_kern_sysclock_active, "A", 234228173Slstewart "Name of the active system clock which is currently serving time"); 235227747Slstewart 236228173Slstewartstatic int sysctl_kern_ffclock_ffcounter_bypass = 0; 237228173SlstewartSYSCTL_INT(_kern_sysclock_ffclock, OID_AUTO, ffcounter_bypass, CTLFLAG_RW, 238227776Slstewart &sysctl_kern_ffclock_ffcounter_bypass, 0, 239228173Slstewart "Use reliable hardware timecounter as the feed-forward counter"); 240227776Slstewart 241227747Slstewart/* 242227747Slstewart * High level functions to access the Feed-Forward Clock. 243227747Slstewart */ 244227747Slstewartvoid 245227747Slstewartffclock_bintime(struct bintime *bt) 246227747Slstewart{ 247227747Slstewart 248227747Slstewart ffclock_abstime(NULL, bt, NULL, FFCLOCK_LERP | FFCLOCK_LEAPSEC); 249227747Slstewart} 250227747Slstewart 251227747Slstewartvoid 252227747Slstewartffclock_nanotime(struct timespec *tsp) 253227747Slstewart{ 254227747Slstewart struct bintime bt; 255227747Slstewart 256227747Slstewart ffclock_abstime(NULL, &bt, NULL, FFCLOCK_LERP | FFCLOCK_LEAPSEC); 257227747Slstewart bintime2timespec(&bt, tsp); 258227747Slstewart} 259227747Slstewart 260227747Slstewartvoid 261227747Slstewartffclock_microtime(struct timeval *tvp) 262227747Slstewart{ 263227747Slstewart struct bintime bt; 264227747Slstewart 265227747Slstewart ffclock_abstime(NULL, &bt, NULL, FFCLOCK_LERP | FFCLOCK_LEAPSEC); 266227747Slstewart bintime2timeval(&bt, tvp); 267227747Slstewart} 268227747Slstewart 269227747Slstewartvoid 270227747Slstewartffclock_getbintime(struct bintime *bt) 271227747Slstewart{ 272227747Slstewart 273227747Slstewart ffclock_abstime(NULL, bt, NULL, 274227747Slstewart FFCLOCK_LERP | FFCLOCK_LEAPSEC | FFCLOCK_FAST); 275227747Slstewart} 276227747Slstewart 277227747Slstewartvoid 278227747Slstewartffclock_getnanotime(struct timespec *tsp) 279227747Slstewart{ 280227747Slstewart struct bintime bt; 281227747Slstewart 282227747Slstewart ffclock_abstime(NULL, &bt, NULL, 283227747Slstewart FFCLOCK_LERP | FFCLOCK_LEAPSEC | FFCLOCK_FAST); 284227747Slstewart bintime2timespec(&bt, tsp); 285227747Slstewart} 286227747Slstewart 287227747Slstewartvoid 288227747Slstewartffclock_getmicrotime(struct timeval *tvp) 289227747Slstewart{ 290227747Slstewart struct bintime bt; 291227747Slstewart 292227747Slstewart ffclock_abstime(NULL, &bt, NULL, 293227747Slstewart FFCLOCK_LERP | FFCLOCK_LEAPSEC | FFCLOCK_FAST); 294227747Slstewart bintime2timeval(&bt, tvp); 295227747Slstewart} 296227747Slstewart 297227747Slstewartvoid 298227747Slstewartffclock_binuptime(struct bintime *bt) 299227747Slstewart{ 300227747Slstewart 301227747Slstewart ffclock_abstime(NULL, bt, NULL, FFCLOCK_LERP | FFCLOCK_UPTIME); 302227747Slstewart} 303227747Slstewart 304227747Slstewartvoid 305227747Slstewartffclock_nanouptime(struct timespec *tsp) 306227747Slstewart{ 307227747Slstewart struct bintime bt; 308227747Slstewart 309227747Slstewart ffclock_abstime(NULL, &bt, NULL, FFCLOCK_LERP | FFCLOCK_UPTIME); 310227747Slstewart bintime2timespec(&bt, tsp); 311227747Slstewart} 312227747Slstewart 313227747Slstewartvoid 314227747Slstewartffclock_microuptime(struct timeval *tvp) 315227747Slstewart{ 316227747Slstewart struct bintime bt; 317227747Slstewart 318227747Slstewart ffclock_abstime(NULL, &bt, NULL, FFCLOCK_LERP | FFCLOCK_UPTIME); 319227747Slstewart bintime2timeval(&bt, tvp); 320227747Slstewart} 321227747Slstewart 322227747Slstewartvoid 323227747Slstewartffclock_getbinuptime(struct bintime *bt) 324227747Slstewart{ 325227747Slstewart 326227747Slstewart ffclock_abstime(NULL, bt, NULL, 327227747Slstewart FFCLOCK_LERP | FFCLOCK_UPTIME | FFCLOCK_FAST); 328227747Slstewart} 329227747Slstewart 330227747Slstewartvoid 331227747Slstewartffclock_getnanouptime(struct timespec *tsp) 332227747Slstewart{ 333227747Slstewart struct bintime bt; 334227747Slstewart 335227747Slstewart ffclock_abstime(NULL, &bt, NULL, 336227747Slstewart FFCLOCK_LERP | FFCLOCK_UPTIME | FFCLOCK_FAST); 337227747Slstewart bintime2timespec(&bt, tsp); 338227747Slstewart} 339227747Slstewart 340227747Slstewartvoid 341227747Slstewartffclock_getmicrouptime(struct timeval *tvp) 342227747Slstewart{ 343227747Slstewart struct bintime bt; 344227747Slstewart 345227747Slstewart ffclock_abstime(NULL, &bt, NULL, 346227747Slstewart FFCLOCK_LERP | FFCLOCK_UPTIME | FFCLOCK_FAST); 347227747Slstewart bintime2timeval(&bt, tvp); 348227747Slstewart} 349227747Slstewart 350227747Slstewartvoid 351227747Slstewartffclock_bindifftime(ffcounter ffdelta, struct bintime *bt) 352227747Slstewart{ 353227747Slstewart 354227747Slstewart ffclock_difftime(ffdelta, bt, NULL); 355227747Slstewart} 356227747Slstewart 357227747Slstewartvoid 358227747Slstewartffclock_nanodifftime(ffcounter ffdelta, struct timespec *tsp) 359227747Slstewart{ 360227747Slstewart struct bintime bt; 361227747Slstewart 362227747Slstewart ffclock_difftime(ffdelta, &bt, NULL); 363227747Slstewart bintime2timespec(&bt, tsp); 364227747Slstewart} 365227747Slstewart 366227747Slstewartvoid 367227747Slstewartffclock_microdifftime(ffcounter ffdelta, struct timeval *tvp) 368227747Slstewart{ 369227747Slstewart struct bintime bt; 370227747Slstewart 371227747Slstewart ffclock_difftime(ffdelta, &bt, NULL); 372227747Slstewart bintime2timeval(&bt, tvp); 373227747Slstewart} 374227776Slstewart 375227776Slstewart/* 376227776Slstewart * System call allowing userland applications to retrieve the current value of 377227776Slstewart * the Feed-Forward Clock counter. 378227776Slstewart */ 379227776Slstewart#ifndef _SYS_SYSPROTO_H_ 380227776Slstewartstruct ffclock_getcounter_args { 381227776Slstewart ffcounter *ffcount; 382227776Slstewart}; 383227776Slstewart#endif 384227776Slstewart/* ARGSUSED */ 385227776Slstewartint 386227776Slstewartsys_ffclock_getcounter(struct thread *td, struct ffclock_getcounter_args *uap) 387227776Slstewart{ 388227776Slstewart ffcounter ffcount; 389227776Slstewart int error; 390227776Slstewart 391227776Slstewart ffcount = 0; 392227776Slstewart ffclock_read_counter(&ffcount); 393227776Slstewart if (ffcount == 0) 394227776Slstewart return (EAGAIN); 395227776Slstewart error = copyout(&ffcount, uap->ffcount, sizeof(ffcounter)); 396227776Slstewart 397227776Slstewart return (error); 398227776Slstewart} 399227776Slstewart 400227776Slstewart/* 401227776Slstewart * System call allowing the synchronisation daemon to push new feed-foward clock 402227776Slstewart * estimates to the kernel. Acquire ffclock_mtx to prevent concurrent updates 403227776Slstewart * and ensure data consistency. 404227776Slstewart * NOTE: ffclock_updated signals the fftimehands that new estimates are 405227776Slstewart * available. The updated estimates are picked up by the fftimehands on next 406227776Slstewart * tick, which could take as long as 1/hz seconds (if ticks are not missed). 407227776Slstewart */ 408227776Slstewart#ifndef _SYS_SYSPROTO_H_ 409227776Slstewartstruct ffclock_setestimate_args { 410227776Slstewart struct ffclock_estimate *cest; 411227776Slstewart}; 412227776Slstewart#endif 413227776Slstewart/* ARGSUSED */ 414227776Slstewartint 415227776Slstewartsys_ffclock_setestimate(struct thread *td, struct ffclock_setestimate_args *uap) 416227776Slstewart{ 417227776Slstewart struct ffclock_estimate cest; 418227776Slstewart int error; 419227776Slstewart 420227776Slstewart /* Reuse of PRIV_CLOCK_SETTIME. */ 421227776Slstewart if ((error = priv_check(td, PRIV_CLOCK_SETTIME)) != 0) 422227776Slstewart return (error); 423227776Slstewart 424227776Slstewart if ((error = copyin(uap->cest, &cest, sizeof(struct ffclock_estimate))) 425227776Slstewart != 0) 426227776Slstewart return (error); 427227776Slstewart 428227776Slstewart mtx_lock(&ffclock_mtx); 429227776Slstewart memcpy(&ffclock_estimate, &cest, sizeof(struct ffclock_estimate)); 430227776Slstewart ffclock_updated++; 431227776Slstewart mtx_unlock(&ffclock_mtx); 432227776Slstewart return (error); 433227776Slstewart} 434227776Slstewart 435227776Slstewart/* 436227776Slstewart * System call allowing userland applications to retrieve the clock estimates 437227776Slstewart * stored within the kernel. It is useful to kickstart the synchronisation 438227776Slstewart * daemon with the kernel's knowledge of hardware timecounter. 439227776Slstewart */ 440227776Slstewart#ifndef _SYS_SYSPROTO_H_ 441227776Slstewartstruct ffclock_getestimate_args { 442227776Slstewart struct ffclock_estimate *cest; 443227776Slstewart}; 444227776Slstewart#endif 445227776Slstewart/* ARGSUSED */ 446227776Slstewartint 447227776Slstewartsys_ffclock_getestimate(struct thread *td, struct ffclock_getestimate_args *uap) 448227776Slstewart{ 449227776Slstewart struct ffclock_estimate cest; 450227776Slstewart int error; 451227776Slstewart 452227776Slstewart mtx_lock(&ffclock_mtx); 453227776Slstewart memcpy(&cest, &ffclock_estimate, sizeof(struct ffclock_estimate)); 454227776Slstewart mtx_unlock(&ffclock_mtx); 455227776Slstewart error = copyout(&cest, uap->cest, sizeof(struct ffclock_estimate)); 456227776Slstewart return (error); 457227776Slstewart} 458227776Slstewart 459227776Slstewart#else /* !FFCLOCK */ 460227776Slstewart 461227776Slstewartint 462227776Slstewartsys_ffclock_getcounter(struct thread *td, struct ffclock_getcounter_args *uap) 463227776Slstewart{ 464227776Slstewart 465227776Slstewart return (ENOSYS); 466227776Slstewart} 467227776Slstewart 468227776Slstewartint 469227776Slstewartsys_ffclock_setestimate(struct thread *td, struct ffclock_setestimate_args *uap) 470227776Slstewart{ 471227776Slstewart 472227776Slstewart return (ENOSYS); 473227776Slstewart} 474227776Slstewart 475227776Slstewartint 476227776Slstewartsys_ffclock_getestimate(struct thread *td, struct ffclock_getestimate_args *uap) 477227776Slstewart{ 478227776Slstewart 479227776Slstewart return (ENOSYS); 480227776Slstewart} 481227776Slstewart 482227776Slstewart#endif /* FFCLOCK */ 483