kern_tc.c revision 91065
1/* 2 * ---------------------------------------------------------------------------- 3 * "THE BEER-WARE LICENSE" (Revision 42): 4 * <phk@FreeBSD.ORG> wrote this file. As long as you retain this notice you 5 * can do whatever you want with this stuff. If we meet some day, and you think 6 * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp 7 * ---------------------------------------------------------------------------- 8 * 9 * $FreeBSD: head/sys/kern/kern_tc.c 91065 2002-02-22 12:59:20Z phk $ 10 */ 11 12#include "opt_ntp.h" 13 14#include <sys/param.h> 15#include <sys/timetc.h> 16#include <sys/malloc.h> 17#include <sys/kernel.h> 18#include <sys/sysctl.h> 19#include <sys/systm.h> 20#include <sys/timex.h> 21#include <sys/timepps.h> 22 23/* 24 * Number of timecounters used to implement stable storage 25 */ 26#ifndef NTIMECOUNTER 27#define NTIMECOUNTER hz 28#endif 29 30static MALLOC_DEFINE(M_TIMECOUNTER, "timecounter", 31 "Timecounter stable storage"); 32 33static void tco_setscales __P((struct timecounter *tc)); 34static __inline unsigned tco_delta __P((struct timecounter *tc)); 35 36time_t time_second; 37 38struct bintime boottimebin; 39struct timeval boottime; 40SYSCTL_STRUCT(_kern, KERN_BOOTTIME, boottime, CTLFLAG_RD, 41 &boottime, timeval, "System boottime"); 42 43SYSCTL_NODE(_kern, OID_AUTO, timecounter, CTLFLAG_RW, 0, ""); 44 45static unsigned nmicrotime; 46static unsigned nnanotime; 47static unsigned ngetmicrotime; 48static unsigned ngetnanotime; 49static unsigned nmicrouptime; 50static unsigned nnanouptime; 51static unsigned ngetmicrouptime; 52static unsigned ngetnanouptime; 53SYSCTL_INT(_kern_timecounter, OID_AUTO, nmicrotime, CTLFLAG_RD, &nmicrotime, 0, ""); 54SYSCTL_INT(_kern_timecounter, OID_AUTO, nnanotime, CTLFLAG_RD, &nnanotime, 0, ""); 55SYSCTL_INT(_kern_timecounter, OID_AUTO, nmicrouptime, CTLFLAG_RD, &nmicrouptime, 0, ""); 56SYSCTL_INT(_kern_timecounter, OID_AUTO, nnanouptime, CTLFLAG_RD, &nnanouptime, 0, ""); 57SYSCTL_INT(_kern_timecounter, OID_AUTO, ngetmicrotime, CTLFLAG_RD, &ngetmicrotime, 0, ""); 58SYSCTL_INT(_kern_timecounter, OID_AUTO, ngetnanotime, CTLFLAG_RD, &ngetnanotime, 0, ""); 59SYSCTL_INT(_kern_timecounter, OID_AUTO, ngetmicrouptime, CTLFLAG_RD, &ngetmicrouptime, 0, ""); 60SYSCTL_INT(_kern_timecounter, OID_AUTO, ngetnanouptime, CTLFLAG_RD, &ngetnanouptime, 0, ""); 61 62/* 63 * Implement a dummy timecounter which we can use until we get a real one 64 * in the air. This allows the console and other early stuff to use 65 * timeservices. 66 */ 67 68static unsigned 69dummy_get_timecount(struct timecounter *tc) 70{ 71 static unsigned now; 72 73 return (++now); 74} 75 76static struct timecounter dummy_timecounter = { 77 dummy_get_timecount, 78 0, 79 ~0u, 80 1000000, 81 "dummy" 82}; 83 84struct timecounter *volatile timecounter = &dummy_timecounter; 85 86static __inline unsigned 87tco_delta(struct timecounter *tc) 88{ 89 90 return ((tc->tc_get_timecount(tc) - tc->tc_offset_count) & 91 tc->tc_counter_mask); 92} 93 94/* 95 * We have eight functions for looking at the clock, four for 96 * microseconds and four for nanoseconds. For each there is fast 97 * but less precise version "get{nano|micro}[up]time" which will 98 * return a time which is up to 1/HZ previous to the call, whereas 99 * the raw version "{nano|micro}[up]time" will return a timestamp 100 * which is as precise as possible. The "up" variants return the 101 * time relative to system boot, these are well suited for time 102 * interval measurements. 103 */ 104 105void 106binuptime(struct bintime *bt) 107{ 108 struct timecounter *tc; 109 110 tc = timecounter; 111 *bt = tc->tc_offset; 112 bintime_addx(bt, tc->tc_scale * tco_delta(tc)); 113} 114 115void 116bintime(struct bintime *bt) 117{ 118 119 binuptime(bt); 120 bintime_add(bt, &boottimebin); 121} 122 123void 124getmicrotime(struct timeval *tvp) 125{ 126 struct timecounter *tc; 127 128 ngetmicrotime++; 129 tc = timecounter; 130 *tvp = tc->tc_microtime; 131} 132 133void 134getnanotime(struct timespec *tsp) 135{ 136 struct timecounter *tc; 137 138 ngetnanotime++; 139 tc = timecounter; 140 *tsp = tc->tc_nanotime; 141} 142 143void 144microtime(struct timeval *tv) 145{ 146 struct bintime bt; 147 148 nmicrotime++; 149 bintime(&bt); 150 bintime2timeval(&bt, tv); 151} 152 153void 154nanotime(struct timespec *ts) 155{ 156 struct bintime bt; 157 158 nnanotime++; 159 bintime(&bt); 160 bintime2timespec(&bt, ts); 161} 162 163void 164getmicrouptime(struct timeval *tvp) 165{ 166 struct timecounter *tc; 167 168 ngetmicrouptime++; 169 tc = timecounter; 170 bintime2timeval(&tc->tc_offset, tvp); 171} 172 173void 174getnanouptime(struct timespec *tsp) 175{ 176 struct timecounter *tc; 177 178 ngetnanouptime++; 179 tc = timecounter; 180 bintime2timespec(&tc->tc_offset, tsp); 181} 182 183void 184microuptime(struct timeval *tv) 185{ 186 struct bintime bt; 187 188 nmicrouptime++; 189 binuptime(&bt); 190 bintime2timeval(&bt, tv); 191} 192 193void 194nanouptime(struct timespec *ts) 195{ 196 struct bintime bt; 197 198 nnanouptime++; 199 binuptime(&bt); 200 bintime2timespec(&bt, ts); 201} 202 203static void 204tco_setscales(struct timecounter *tc) 205{ 206 u_int64_t scale; 207 208 /* Sacrifice the lower bit to the deity for code clarity */ 209 scale = 1ULL << 63; 210 /* 211 * We get nanoseconds with 32 bit binary fraction and want 212 * 64 bit binary fraction: x = a * 2^32 / 10^9 = a * 4.294967296 213 * The range is +/- 500PPM so we can multiply by about 8500 214 * without overflowing. 4398/1024 = is very close to ideal. 215 */ 216 scale += (tc->tc_adjustment * 4398) >> 10; 217 scale /= tc->tc_tweak->tc_frequency; 218 tc->tc_scale = scale * 2; 219} 220 221void 222tc_update(struct timecounter *tc) 223{ 224 tco_setscales(tc); 225} 226 227void 228tc_init(struct timecounter *tc) 229{ 230 struct timecounter *t1, *t2, *t3; 231 int i; 232 233 tc->tc_adjustment = 0; 234 tc->tc_tweak = tc; 235 tco_setscales(tc); 236 tc->tc_offset_count = tc->tc_get_timecount(tc); 237 if (timecounter == &dummy_timecounter) 238 tc->tc_avail = tc; 239 else { 240 tc->tc_avail = timecounter->tc_tweak->tc_avail; 241 timecounter->tc_tweak->tc_avail = tc; 242 } 243 MALLOC(t1, struct timecounter *, sizeof *t1, M_TIMECOUNTER, M_WAITOK); 244 tc->tc_other = t1; 245 *t1 = *tc; 246 t2 = t1; 247 t3 = NULL; 248 for (i = 1; i < NTIMECOUNTER; i++) { 249 MALLOC(t3, struct timecounter *, sizeof *t3, 250 M_TIMECOUNTER, M_WAITOK); 251 *t3 = *tc; 252 t3->tc_other = t2; 253 t2 = t3; 254 } 255 t1->tc_other = t3; 256 tc = t1; 257 258 printf("Timecounter \"%s\" frequency %lu Hz\n", 259 tc->tc_name, (u_long)tc->tc_frequency); 260 261 /* XXX: For now always start using the counter. */ 262 tc->tc_offset_count = tc->tc_get_timecount(tc); 263 binuptime(&tc->tc_offset); 264 timecounter = tc; 265} 266 267void 268tc_setclock(struct timespec *ts) 269{ 270 struct timespec ts2; 271 272 nanouptime(&ts2); 273 boottime.tv_sec = ts->tv_sec - ts2.tv_sec; 274 boottime.tv_usec = (ts->tv_nsec - ts2.tv_nsec) / 1000; 275 if (boottime.tv_usec < 0) { 276 boottime.tv_usec += 1000000; 277 boottime.tv_sec--; 278 } 279 timeval2bintime(&boottime, &boottimebin); 280 /* fiddle all the little crinkly bits around the fiords... */ 281 tc_windup(); 282} 283 284static void 285switch_timecounter(struct timecounter *newtc) 286{ 287 int s; 288 struct timecounter *tc; 289 290 s = splclock(); 291 tc = timecounter; 292 if (newtc->tc_tweak == tc->tc_tweak) { 293 splx(s); 294 return; 295 } 296 newtc = newtc->tc_tweak->tc_other; 297 binuptime(&newtc->tc_offset); 298 newtc->tc_offset_count = newtc->tc_get_timecount(newtc); 299 tco_setscales(newtc); 300 timecounter = newtc; 301 splx(s); 302} 303 304static struct timecounter * 305sync_other_counter(void) 306{ 307 struct timecounter *tc, *tcn, *tco; 308 unsigned delta; 309 310 tco = timecounter; 311 tc = tco->tc_other; 312 tcn = tc->tc_other; 313 *tc = *tco; 314 tc->tc_other = tcn; 315 delta = tco_delta(tc); 316 tc->tc_offset_count += delta; 317 tc->tc_offset_count &= tc->tc_counter_mask; 318 bintime_addx(&tc->tc_offset, tc->tc_scale * delta); 319 return (tc); 320} 321 322void 323tc_windup(void) 324{ 325 struct timecounter *tc, *tco; 326 struct bintime bt; 327 struct timeval tvt; 328 int i; 329 330 tco = timecounter; 331 tc = sync_other_counter(); 332 /* 333 * We may be inducing a tiny error here, the tc_poll_pps() may 334 * process a latched count which happens after the tco_delta() 335 * in sync_other_counter(), which would extend the previous 336 * counters parameters into the domain of this new one. 337 * Since the timewindow is very small for this, the error is 338 * going to be only a few weenieseconds (as Dave Mills would 339 * say), so lets just not talk more about it, OK ? 340 */ 341 if (tco->tc_poll_pps) 342 tco->tc_poll_pps(tco); 343 if (timedelta != 0) { 344 tvt = boottime; 345 tvt.tv_usec += tickdelta; 346 if (tvt.tv_usec >= 1000000) { 347 tvt.tv_sec++; 348 tvt.tv_usec -= 1000000; 349 } else if (tvt.tv_usec < 0) { 350 tvt.tv_sec--; 351 tvt.tv_usec += 1000000; 352 } 353 boottime = tvt; 354 timeval2bintime(&boottime, &boottimebin); 355 timedelta -= tickdelta; 356 } 357 for (i = tc->tc_offset.sec - tco->tc_offset.sec; i > 0; i--) { 358 ntp_update_second(tc); /* XXX only needed if xntpd runs */ 359 tco_setscales(tc); 360 } 361 362 bt = tc->tc_offset; 363 bintime_add(&bt, &boottimebin); 364 bintime2timeval(&bt, &tc->tc_microtime); 365 bintime2timespec(&bt, &tc->tc_nanotime); 366 time_second = tc->tc_microtime.tv_sec; 367 timecounter = tc; 368} 369 370static int 371sysctl_kern_timecounter_hardware(SYSCTL_HANDLER_ARGS) 372{ 373 char newname[32]; 374 struct timecounter *newtc, *tc; 375 int error; 376 377 tc = timecounter->tc_tweak; 378 strncpy(newname, tc->tc_name, sizeof(newname)); 379 error = sysctl_handle_string(oidp, &newname[0], sizeof(newname), req); 380 if (error == 0 && req->newptr != NULL && 381 strcmp(newname, tc->tc_name) != 0) { 382 for (newtc = tc->tc_avail; newtc != tc; 383 newtc = newtc->tc_avail) { 384 if (strcmp(newname, newtc->tc_name) == 0) { 385 /* Warm up new timecounter. */ 386 (void)newtc->tc_get_timecount(newtc); 387 388 switch_timecounter(newtc); 389 return (0); 390 } 391 } 392 return (EINVAL); 393 } 394 return (error); 395} 396 397SYSCTL_PROC(_kern_timecounter, OID_AUTO, hardware, CTLTYPE_STRING | CTLFLAG_RW, 398 0, 0, sysctl_kern_timecounter_hardware, "A", ""); 399 400 401int 402pps_ioctl(u_long cmd, caddr_t data, struct pps_state *pps) 403{ 404 pps_params_t *app; 405 struct pps_fetch_args *fapi; 406#ifdef PPS_SYNC 407 struct pps_kcbind_args *kapi; 408#endif 409 410 switch (cmd) { 411 case PPS_IOC_CREATE: 412 return (0); 413 case PPS_IOC_DESTROY: 414 return (0); 415 case PPS_IOC_SETPARAMS: 416 app = (pps_params_t *)data; 417 if (app->mode & ~pps->ppscap) 418 return (EINVAL); 419 pps->ppsparam = *app; 420 return (0); 421 case PPS_IOC_GETPARAMS: 422 app = (pps_params_t *)data; 423 *app = pps->ppsparam; 424 app->api_version = PPS_API_VERS_1; 425 return (0); 426 case PPS_IOC_GETCAP: 427 *(int*)data = pps->ppscap; 428 return (0); 429 case PPS_IOC_FETCH: 430 fapi = (struct pps_fetch_args *)data; 431 if (fapi->tsformat && fapi->tsformat != PPS_TSFMT_TSPEC) 432 return (EINVAL); 433 if (fapi->timeout.tv_sec || fapi->timeout.tv_nsec) 434 return (EOPNOTSUPP); 435 pps->ppsinfo.current_mode = pps->ppsparam.mode; 436 fapi->pps_info_buf = pps->ppsinfo; 437 return (0); 438 case PPS_IOC_KCBIND: 439#ifdef PPS_SYNC 440 kapi = (struct pps_kcbind_args *)data; 441 /* XXX Only root should be able to do this */ 442 if (kapi->tsformat && kapi->tsformat != PPS_TSFMT_TSPEC) 443 return (EINVAL); 444 if (kapi->kernel_consumer != PPS_KC_HARDPPS) 445 return (EINVAL); 446 if (kapi->edge & ~pps->ppscap) 447 return (EINVAL); 448 pps->kcmode = kapi->edge; 449 return (0); 450#else 451 return (EOPNOTSUPP); 452#endif 453 default: 454 return (ENOTTY); 455 } 456} 457 458void 459pps_init(struct pps_state *pps) 460{ 461 pps->ppscap |= PPS_TSFMT_TSPEC; 462 if (pps->ppscap & PPS_CAPTUREASSERT) 463 pps->ppscap |= PPS_OFFSETASSERT; 464 if (pps->ppscap & PPS_CAPTURECLEAR) 465 pps->ppscap |= PPS_OFFSETCLEAR; 466} 467 468void 469pps_event(struct pps_state *pps, struct timecounter *tc, unsigned count, int event) 470{ 471 struct timespec ts, *tsp, *osp; 472 unsigned tcount, *pcount; 473 struct bintime bt; 474 int foff, fhard; 475 pps_seq_t *pseq; 476 477 /* Things would be easier with arrays... */ 478 if (event == PPS_CAPTUREASSERT) { 479 tsp = &pps->ppsinfo.assert_timestamp; 480 osp = &pps->ppsparam.assert_offset; 481 foff = pps->ppsparam.mode & PPS_OFFSETASSERT; 482 fhard = pps->kcmode & PPS_CAPTUREASSERT; 483 pcount = &pps->ppscount[0]; 484 pseq = &pps->ppsinfo.assert_sequence; 485 } else { 486 tsp = &pps->ppsinfo.clear_timestamp; 487 osp = &pps->ppsparam.clear_offset; 488 foff = pps->ppsparam.mode & PPS_OFFSETCLEAR; 489 fhard = pps->kcmode & PPS_CAPTURECLEAR; 490 pcount = &pps->ppscount[1]; 491 pseq = &pps->ppsinfo.clear_sequence; 492 } 493 494 /* The timecounter changed: bail */ 495 if (!pps->ppstc || 496 pps->ppstc->tc_name != tc->tc_name || 497 tc->tc_name != timecounter->tc_name) { 498 pps->ppstc = tc; 499 *pcount = count; 500 return; 501 } 502 503 /* Nothing really happened */ 504 if (*pcount == count) 505 return; 506 507 *pcount = count; 508 509 /* Convert the count to timespec */ 510 tcount = count - tc->tc_offset_count; 511 tcount &= tc->tc_counter_mask; 512 bt = tc->tc_offset; 513 bintime_addx(&bt, tc->tc_scale * tcount); 514 bintime2timespec(&bt, &ts); 515 516 (*pseq)++; 517 *tsp = ts; 518 519 if (foff) { 520 timespecadd(tsp, osp); 521 if (tsp->tv_nsec < 0) { 522 tsp->tv_nsec += 1000000000; 523 tsp->tv_sec -= 1; 524 } 525 } 526#ifdef PPS_SYNC 527 if (fhard) { 528 u_int64_t delta; 529 /* magic, at its best... */ 530 tcount = count - pps->ppscount[2]; 531 pps->ppscount[2] = count; 532 tcount &= tc->tc_counter_mask; 533 bt.sec = 0; 534 bt.frac = 0; 535 bintime_addx(&bt, tc->tc_scale * tcount); 536 bintime2timespec(&bt, &ts); 537 hardpps(tsp, ts.tv_nsec + 1000000000 * ts.tv_sec); 538 } 539#endif 540} 541