kern_clocksource.c revision 280973
1/*- 2 * Copyright (c) 2010-2013 Alexander Motin <mav@FreeBSD.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer, 10 * without modification, immediately at the beginning of the file. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> 28__FBSDID("$FreeBSD: stable/10/sys/kern/kern_clocksource.c 280973 2015-04-02 01:02:42Z jhb $"); 29 30/* 31 * Common routines to manage event timers hardware. 32 */ 33 34#include "opt_device_polling.h" 35#include "opt_kdtrace.h" 36 37#include <sys/param.h> 38#include <sys/systm.h> 39#include <sys/bus.h> 40#include <sys/limits.h> 41#include <sys/lock.h> 42#include <sys/kdb.h> 43#include <sys/ktr.h> 44#include <sys/mutex.h> 45#include <sys/proc.h> 46#include <sys/kernel.h> 47#include <sys/sched.h> 48#include <sys/smp.h> 49#include <sys/sysctl.h> 50#include <sys/timeet.h> 51#include <sys/timetc.h> 52 53#include <machine/atomic.h> 54#include <machine/clock.h> 55#include <machine/cpu.h> 56#include <machine/smp.h> 57 58#ifdef KDTRACE_HOOKS 59#include <sys/dtrace_bsd.h> 60cyclic_clock_func_t cyclic_clock_func = NULL; 61#endif 62 63int cpu_deepest_sleep = 0; /* Deepest Cx state available. */ 64int cpu_disable_c2_sleep = 0; /* Timer dies in C2. */ 65int cpu_disable_c3_sleep = 0; /* Timer dies in C3. */ 66 67static void setuptimer(void); 68static void loadtimer(sbintime_t now, int first); 69static int doconfigtimer(void); 70static void configtimer(int start); 71static int round_freq(struct eventtimer *et, int freq); 72 73static sbintime_t getnextcpuevent(int idle); 74static sbintime_t getnextevent(void); 75static int handleevents(sbintime_t now, int fake); 76 77static struct mtx et_hw_mtx; 78 79#define ET_HW_LOCK(state) \ 80 { \ 81 if (timer->et_flags & ET_FLAGS_PERCPU) \ 82 mtx_lock_spin(&(state)->et_hw_mtx); \ 83 else \ 84 mtx_lock_spin(&et_hw_mtx); \ 85 } 86 87#define ET_HW_UNLOCK(state) \ 88 { \ 89 if (timer->et_flags & ET_FLAGS_PERCPU) \ 90 mtx_unlock_spin(&(state)->et_hw_mtx); \ 91 else \ 92 mtx_unlock_spin(&et_hw_mtx); \ 93 } 94 95static struct eventtimer *timer = NULL; 96static sbintime_t timerperiod; /* Timer period for periodic mode. */ 97static sbintime_t statperiod; /* statclock() events period. */ 98static sbintime_t profperiod; /* profclock() events period. */ 99static sbintime_t nexttick; /* Next global timer tick time. */ 100static u_int busy = 1; /* Reconfiguration is in progress. */ 101static int profiling = 0; /* Profiling events enabled. */ 102 103static char timername[32]; /* Wanted timer. */ 104TUNABLE_STR("kern.eventtimer.timer", timername, sizeof(timername)); 105 106static int singlemul = 0; /* Multiplier for periodic mode. */ 107TUNABLE_INT("kern.eventtimer.singlemul", &singlemul); 108SYSCTL_INT(_kern_eventtimer, OID_AUTO, singlemul, CTLFLAG_RW, &singlemul, 109 0, "Multiplier for periodic mode"); 110 111static u_int idletick = 0; /* Run periodic events when idle. */ 112TUNABLE_INT("kern.eventtimer.idletick", &idletick); 113SYSCTL_UINT(_kern_eventtimer, OID_AUTO, idletick, CTLFLAG_RW, &idletick, 114 0, "Run periodic events when idle"); 115 116static int periodic = 0; /* Periodic or one-shot mode. */ 117static int want_periodic = 0; /* What mode to prefer. */ 118TUNABLE_INT("kern.eventtimer.periodic", &want_periodic); 119 120struct pcpu_state { 121 struct mtx et_hw_mtx; /* Per-CPU timer mutex. */ 122 u_int action; /* Reconfiguration requests. */ 123 u_int handle; /* Immediate handle resuests. */ 124 sbintime_t now; /* Last tick time. */ 125 sbintime_t nextevent; /* Next scheduled event on this CPU. */ 126 sbintime_t nexttick; /* Next timer tick time. */ 127 sbintime_t nexthard; /* Next hardlock() event. */ 128 sbintime_t nextstat; /* Next statclock() event. */ 129 sbintime_t nextprof; /* Next profclock() event. */ 130 sbintime_t nextcall; /* Next callout event. */ 131 sbintime_t nextcallopt; /* Next optional callout event. */ 132#ifdef KDTRACE_HOOKS 133 sbintime_t nextcyc; /* Next OpenSolaris cyclics event. */ 134#endif 135 int ipi; /* This CPU needs IPI. */ 136 int idle; /* This CPU is in idle mode. */ 137}; 138 139static DPCPU_DEFINE(struct pcpu_state, timerstate); 140DPCPU_DEFINE(sbintime_t, hardclocktime); 141 142/* 143 * Timer broadcast IPI handler. 144 */ 145int 146hardclockintr(void) 147{ 148 sbintime_t now; 149 struct pcpu_state *state; 150 int done; 151 152 if (doconfigtimer() || busy) 153 return (FILTER_HANDLED); 154 state = DPCPU_PTR(timerstate); 155 now = state->now; 156 CTR3(KTR_SPARE2, "ipi at %d: now %d.%08x", 157 curcpu, (int)(now >> 32), (u_int)(now & 0xffffffff)); 158 done = handleevents(now, 0); 159 return (done ? FILTER_HANDLED : FILTER_STRAY); 160} 161 162/* 163 * Handle all events for specified time on this CPU 164 */ 165static int 166handleevents(sbintime_t now, int fake) 167{ 168 sbintime_t t, *hct; 169 struct trapframe *frame; 170 struct pcpu_state *state; 171 int usermode; 172 int done, runs; 173 174 CTR3(KTR_SPARE2, "handle at %d: now %d.%08x", 175 curcpu, (int)(now >> 32), (u_int)(now & 0xffffffff)); 176 done = 0; 177 if (fake) { 178 frame = NULL; 179 usermode = 0; 180 } else { 181 frame = curthread->td_intr_frame; 182 usermode = TRAPF_USERMODE(frame); 183 } 184 185 state = DPCPU_PTR(timerstate); 186 187 runs = 0; 188 while (now >= state->nexthard) { 189 state->nexthard += tick_sbt; 190 runs++; 191 } 192 if (runs) { 193 hct = DPCPU_PTR(hardclocktime); 194 *hct = state->nexthard - tick_sbt; 195 if (fake < 2) { 196 hardclock_cnt(runs, usermode); 197 done = 1; 198 } 199 } 200 runs = 0; 201 while (now >= state->nextstat) { 202 state->nextstat += statperiod; 203 runs++; 204 } 205 if (runs && fake < 2) { 206 statclock_cnt(runs, usermode); 207 done = 1; 208 } 209 if (profiling) { 210 runs = 0; 211 while (now >= state->nextprof) { 212 state->nextprof += profperiod; 213 runs++; 214 } 215 if (runs && !fake) { 216 profclock_cnt(runs, usermode, TRAPF_PC(frame)); 217 done = 1; 218 } 219 } else 220 state->nextprof = state->nextstat; 221 if (now >= state->nextcallopt) { 222 state->nextcall = state->nextcallopt = INT64_MAX; 223 callout_process(now); 224 } 225 226#ifdef KDTRACE_HOOKS 227 if (fake == 0 && now >= state->nextcyc && cyclic_clock_func != NULL) { 228 state->nextcyc = INT64_MAX; 229 (*cyclic_clock_func)(frame); 230 } 231#endif 232 233 t = getnextcpuevent(0); 234 ET_HW_LOCK(state); 235 if (!busy) { 236 state->idle = 0; 237 state->nextevent = t; 238 loadtimer(now, (fake == 2) && 239 (timer->et_flags & ET_FLAGS_PERCPU)); 240 } 241 ET_HW_UNLOCK(state); 242 return (done); 243} 244 245/* 246 * Schedule binuptime of the next event on current CPU. 247 */ 248static sbintime_t 249getnextcpuevent(int idle) 250{ 251 sbintime_t event; 252 struct pcpu_state *state; 253 u_int hardfreq; 254 255 state = DPCPU_PTR(timerstate); 256 /* Handle hardclock() events, skipping some if CPU is idle. */ 257 event = state->nexthard; 258 if (idle) { 259 hardfreq = (u_int)hz / 2; 260 if (tc_min_ticktock_freq > 2 261#ifdef SMP 262 && curcpu == CPU_FIRST() 263#endif 264 ) 265 hardfreq = hz / tc_min_ticktock_freq; 266 if (hardfreq > 1) 267 event += tick_sbt * (hardfreq - 1); 268 } 269 /* Handle callout events. */ 270 if (event > state->nextcall) 271 event = state->nextcall; 272 if (!idle) { /* If CPU is active - handle other types of events. */ 273 if (event > state->nextstat) 274 event = state->nextstat; 275 if (profiling && event > state->nextprof) 276 event = state->nextprof; 277 } 278#ifdef KDTRACE_HOOKS 279 if (event > state->nextcyc) 280 event = state->nextcyc; 281#endif 282 return (event); 283} 284 285/* 286 * Schedule binuptime of the next event on all CPUs. 287 */ 288static sbintime_t 289getnextevent(void) 290{ 291 struct pcpu_state *state; 292 sbintime_t event; 293#ifdef SMP 294 int cpu; 295#endif 296 int c; 297 298 state = DPCPU_PTR(timerstate); 299 event = state->nextevent; 300 c = -1; 301#ifdef SMP 302 if ((timer->et_flags & ET_FLAGS_PERCPU) == 0) { 303 CPU_FOREACH(cpu) { 304 state = DPCPU_ID_PTR(cpu, timerstate); 305 if (event > state->nextevent) { 306 event = state->nextevent; 307 c = cpu; 308 } 309 } 310 } 311#endif 312 CTR4(KTR_SPARE2, "next at %d: next %d.%08x by %d", 313 curcpu, (int)(event >> 32), (u_int)(event & 0xffffffff), c); 314 return (event); 315} 316 317/* Hardware timer callback function. */ 318static void 319timercb(struct eventtimer *et, void *arg) 320{ 321 sbintime_t now; 322 sbintime_t *next; 323 struct pcpu_state *state; 324#ifdef SMP 325 int cpu, bcast; 326#endif 327 328 /* Do not touch anything if somebody reconfiguring timers. */ 329 if (busy) 330 return; 331 /* Update present and next tick times. */ 332 state = DPCPU_PTR(timerstate); 333 if (et->et_flags & ET_FLAGS_PERCPU) { 334 next = &state->nexttick; 335 } else 336 next = &nexttick; 337 now = sbinuptime(); 338 if (periodic) 339 *next = now + timerperiod; 340 else 341 *next = -1; /* Next tick is not scheduled yet. */ 342 state->now = now; 343 CTR3(KTR_SPARE2, "intr at %d: now %d.%08x", 344 curcpu, (int)(now >> 32), (u_int)(now & 0xffffffff)); 345 346#ifdef SMP 347 /* Prepare broadcasting to other CPUs for non-per-CPU timers. */ 348 bcast = 0; 349 if ((et->et_flags & ET_FLAGS_PERCPU) == 0 && smp_started) { 350 CPU_FOREACH(cpu) { 351 state = DPCPU_ID_PTR(cpu, timerstate); 352 ET_HW_LOCK(state); 353 state->now = now; 354 if (now >= state->nextevent) { 355 state->nextevent += SBT_1S; 356 if (curcpu != cpu) { 357 state->ipi = 1; 358 bcast = 1; 359 } 360 } 361 ET_HW_UNLOCK(state); 362 } 363 } 364#endif 365 366 /* Handle events for this time on this CPU. */ 367 handleevents(now, 0); 368 369#ifdef SMP 370 /* Broadcast interrupt to other CPUs for non-per-CPU timers. */ 371 if (bcast) { 372 CPU_FOREACH(cpu) { 373 if (curcpu == cpu) 374 continue; 375 state = DPCPU_ID_PTR(cpu, timerstate); 376 if (state->ipi) { 377 state->ipi = 0; 378 ipi_cpu(cpu, IPI_HARDCLOCK); 379 } 380 } 381 } 382#endif 383} 384 385/* 386 * Load new value into hardware timer. 387 */ 388static void 389loadtimer(sbintime_t now, int start) 390{ 391 struct pcpu_state *state; 392 sbintime_t new; 393 sbintime_t *next; 394 uint64_t tmp; 395 int eq; 396 397 if (timer->et_flags & ET_FLAGS_PERCPU) { 398 state = DPCPU_PTR(timerstate); 399 next = &state->nexttick; 400 } else 401 next = &nexttick; 402 if (periodic) { 403 if (start) { 404 /* 405 * Try to start all periodic timers aligned 406 * to period to make events synchronous. 407 */ 408 tmp = now % timerperiod; 409 new = timerperiod - tmp; 410 if (new < tmp) /* Left less then passed. */ 411 new += timerperiod; 412 CTR5(KTR_SPARE2, "load p at %d: now %d.%08x first in %d.%08x", 413 curcpu, (int)(now >> 32), (u_int)(now & 0xffffffff), 414 (int)(new >> 32), (u_int)(new & 0xffffffff)); 415 *next = new + now; 416 et_start(timer, new, timerperiod); 417 } 418 } else { 419 new = getnextevent(); 420 eq = (new == *next); 421 CTR4(KTR_SPARE2, "load at %d: next %d.%08x eq %d", 422 curcpu, (int)(new >> 32), (u_int)(new & 0xffffffff), eq); 423 if (!eq) { 424 *next = new; 425 et_start(timer, new - now, 0); 426 } 427 } 428} 429 430/* 431 * Prepare event timer parameters after configuration changes. 432 */ 433static void 434setuptimer(void) 435{ 436 int freq; 437 438 if (periodic && (timer->et_flags & ET_FLAGS_PERIODIC) == 0) 439 periodic = 0; 440 else if (!periodic && (timer->et_flags & ET_FLAGS_ONESHOT) == 0) 441 periodic = 1; 442 singlemul = MIN(MAX(singlemul, 1), 20); 443 freq = hz * singlemul; 444 while (freq < (profiling ? profhz : stathz)) 445 freq += hz; 446 freq = round_freq(timer, freq); 447 timerperiod = SBT_1S / freq; 448} 449 450/* 451 * Reconfigure specified per-CPU timer on other CPU. Called from IPI handler. 452 */ 453static int 454doconfigtimer(void) 455{ 456 sbintime_t now; 457 struct pcpu_state *state; 458 459 state = DPCPU_PTR(timerstate); 460 switch (atomic_load_acq_int(&state->action)) { 461 case 1: 462 now = sbinuptime(); 463 ET_HW_LOCK(state); 464 loadtimer(now, 1); 465 ET_HW_UNLOCK(state); 466 state->handle = 0; 467 atomic_store_rel_int(&state->action, 0); 468 return (1); 469 case 2: 470 ET_HW_LOCK(state); 471 et_stop(timer); 472 ET_HW_UNLOCK(state); 473 state->handle = 0; 474 atomic_store_rel_int(&state->action, 0); 475 return (1); 476 } 477 if (atomic_readandclear_int(&state->handle) && !busy) { 478 now = sbinuptime(); 479 handleevents(now, 0); 480 return (1); 481 } 482 return (0); 483} 484 485/* 486 * Reconfigure specified timer. 487 * For per-CPU timers use IPI to make other CPUs to reconfigure. 488 */ 489static void 490configtimer(int start) 491{ 492 sbintime_t now, next; 493 struct pcpu_state *state; 494 int cpu; 495 496 if (start) { 497 setuptimer(); 498 now = sbinuptime(); 499 } else 500 now = 0; 501 critical_enter(); 502 ET_HW_LOCK(DPCPU_PTR(timerstate)); 503 if (start) { 504 /* Initialize time machine parameters. */ 505 next = now + timerperiod; 506 if (periodic) 507 nexttick = next; 508 else 509 nexttick = -1; 510 CPU_FOREACH(cpu) { 511 state = DPCPU_ID_PTR(cpu, timerstate); 512 state->now = now; 513 if (!smp_started && cpu != CPU_FIRST()) 514 state->nextevent = INT64_MAX; 515 else 516 state->nextevent = next; 517 if (periodic) 518 state->nexttick = next; 519 else 520 state->nexttick = -1; 521 state->nexthard = next; 522 state->nextstat = next; 523 state->nextprof = next; 524 state->nextcall = next; 525 state->nextcallopt = next; 526 hardclock_sync(cpu); 527 } 528 busy = 0; 529 /* Start global timer or per-CPU timer of this CPU. */ 530 loadtimer(now, 1); 531 } else { 532 busy = 1; 533 /* Stop global timer or per-CPU timer of this CPU. */ 534 et_stop(timer); 535 } 536 ET_HW_UNLOCK(DPCPU_PTR(timerstate)); 537#ifdef SMP 538 /* If timer is global or there is no other CPUs yet - we are done. */ 539 if ((timer->et_flags & ET_FLAGS_PERCPU) == 0 || !smp_started) { 540 critical_exit(); 541 return; 542 } 543 /* Set reconfigure flags for other CPUs. */ 544 CPU_FOREACH(cpu) { 545 state = DPCPU_ID_PTR(cpu, timerstate); 546 atomic_store_rel_int(&state->action, 547 (cpu == curcpu) ? 0 : ( start ? 1 : 2)); 548 } 549 /* Broadcast reconfigure IPI. */ 550 ipi_all_but_self(IPI_HARDCLOCK); 551 /* Wait for reconfiguration completed. */ 552restart: 553 cpu_spinwait(); 554 CPU_FOREACH(cpu) { 555 if (cpu == curcpu) 556 continue; 557 state = DPCPU_ID_PTR(cpu, timerstate); 558 if (atomic_load_acq_int(&state->action)) 559 goto restart; 560 } 561#endif 562 critical_exit(); 563} 564 565/* 566 * Calculate nearest frequency supported by hardware timer. 567 */ 568static int 569round_freq(struct eventtimer *et, int freq) 570{ 571 uint64_t div; 572 573 if (et->et_frequency != 0) { 574 div = lmax((et->et_frequency + freq / 2) / freq, 1); 575 if (et->et_flags & ET_FLAGS_POW2DIV) 576 div = 1 << (flsl(div + div / 2) - 1); 577 freq = (et->et_frequency + div / 2) / div; 578 } 579 if (et->et_min_period > SBT_1S) 580 panic("Event timer \"%s\" doesn't support sub-second periods!", 581 et->et_name); 582 else if (et->et_min_period != 0) 583 freq = min(freq, SBT2FREQ(et->et_min_period)); 584 if (et->et_max_period < SBT_1S && et->et_max_period != 0) 585 freq = max(freq, SBT2FREQ(et->et_max_period)); 586 return (freq); 587} 588 589/* 590 * Configure and start event timers (BSP part). 591 */ 592void 593cpu_initclocks_bsp(void) 594{ 595 struct pcpu_state *state; 596 int base, div, cpu; 597 598 mtx_init(&et_hw_mtx, "et_hw_mtx", NULL, MTX_SPIN); 599 CPU_FOREACH(cpu) { 600 state = DPCPU_ID_PTR(cpu, timerstate); 601 mtx_init(&state->et_hw_mtx, "et_hw_mtx", NULL, MTX_SPIN); 602#ifdef KDTRACE_HOOKS 603 state->nextcyc = INT64_MAX; 604#endif 605 state->nextcall = INT64_MAX; 606 state->nextcallopt = INT64_MAX; 607 } 608 periodic = want_periodic; 609 /* Grab requested timer or the best of present. */ 610 if (timername[0]) 611 timer = et_find(timername, 0, 0); 612 if (timer == NULL && periodic) { 613 timer = et_find(NULL, 614 ET_FLAGS_PERIODIC, ET_FLAGS_PERIODIC); 615 } 616 if (timer == NULL) { 617 timer = et_find(NULL, 618 ET_FLAGS_ONESHOT, ET_FLAGS_ONESHOT); 619 } 620 if (timer == NULL && !periodic) { 621 timer = et_find(NULL, 622 ET_FLAGS_PERIODIC, ET_FLAGS_PERIODIC); 623 } 624 if (timer == NULL) 625 panic("No usable event timer found!"); 626 et_init(timer, timercb, NULL, NULL); 627 628 /* Adapt to timer capabilities. */ 629 if (periodic && (timer->et_flags & ET_FLAGS_PERIODIC) == 0) 630 periodic = 0; 631 else if (!periodic && (timer->et_flags & ET_FLAGS_ONESHOT) == 0) 632 periodic = 1; 633 if (timer->et_flags & ET_FLAGS_C3STOP) 634 cpu_disable_c3_sleep++; 635 636 /* 637 * We honor the requested 'hz' value. 638 * We want to run stathz in the neighborhood of 128hz. 639 * We would like profhz to run as often as possible. 640 */ 641 if (singlemul <= 0 || singlemul > 20) { 642 if (hz >= 1500 || (hz % 128) == 0) 643 singlemul = 1; 644 else if (hz >= 750) 645 singlemul = 2; 646 else 647 singlemul = 4; 648 } 649 if (periodic) { 650 base = round_freq(timer, hz * singlemul); 651 singlemul = max((base + hz / 2) / hz, 1); 652 hz = (base + singlemul / 2) / singlemul; 653 if (base <= 128) 654 stathz = base; 655 else { 656 div = base / 128; 657 if (div >= singlemul && (div % singlemul) == 0) 658 div++; 659 stathz = base / div; 660 } 661 profhz = stathz; 662 while ((profhz + stathz) <= 128 * 64) 663 profhz += stathz; 664 profhz = round_freq(timer, profhz); 665 } else { 666 hz = round_freq(timer, hz); 667 stathz = round_freq(timer, 127); 668 profhz = round_freq(timer, stathz * 64); 669 } 670 tick = 1000000 / hz; 671 tick_sbt = SBT_1S / hz; 672 tick_bt = sbttobt(tick_sbt); 673 statperiod = SBT_1S / stathz; 674 profperiod = SBT_1S / profhz; 675 ET_LOCK(); 676 configtimer(1); 677 ET_UNLOCK(); 678} 679 680/* 681 * Start per-CPU event timers on APs. 682 */ 683void 684cpu_initclocks_ap(void) 685{ 686 sbintime_t now; 687 struct pcpu_state *state; 688 struct thread *td; 689 690 state = DPCPU_PTR(timerstate); 691 now = sbinuptime(); 692 ET_HW_LOCK(state); 693 state->now = now; 694 hardclock_sync(curcpu); 695 spinlock_enter(); 696 ET_HW_UNLOCK(state); 697 td = curthread; 698 td->td_intr_nesting_level++; 699 handleevents(state->now, 2); 700 td->td_intr_nesting_level--; 701 spinlock_exit(); 702} 703 704/* 705 * Switch to profiling clock rates. 706 */ 707void 708cpu_startprofclock(void) 709{ 710 711 ET_LOCK(); 712 if (profiling == 0) { 713 if (periodic) { 714 configtimer(0); 715 profiling = 1; 716 configtimer(1); 717 } else 718 profiling = 1; 719 } else 720 profiling++; 721 ET_UNLOCK(); 722} 723 724/* 725 * Switch to regular clock rates. 726 */ 727void 728cpu_stopprofclock(void) 729{ 730 731 ET_LOCK(); 732 if (profiling == 1) { 733 if (periodic) { 734 configtimer(0); 735 profiling = 0; 736 configtimer(1); 737 } else 738 profiling = 0; 739 } else 740 profiling--; 741 ET_UNLOCK(); 742} 743 744/* 745 * Switch to idle mode (all ticks handled). 746 */ 747sbintime_t 748cpu_idleclock(void) 749{ 750 sbintime_t now, t; 751 struct pcpu_state *state; 752 753 if (idletick || busy || 754 (periodic && (timer->et_flags & ET_FLAGS_PERCPU)) 755#ifdef DEVICE_POLLING 756 || curcpu == CPU_FIRST() 757#endif 758 ) 759 return (-1); 760 state = DPCPU_PTR(timerstate); 761 if (periodic) 762 now = state->now; 763 else 764 now = sbinuptime(); 765 CTR3(KTR_SPARE2, "idle at %d: now %d.%08x", 766 curcpu, (int)(now >> 32), (u_int)(now & 0xffffffff)); 767 t = getnextcpuevent(1); 768 ET_HW_LOCK(state); 769 state->idle = 1; 770 state->nextevent = t; 771 if (!periodic) 772 loadtimer(now, 0); 773 ET_HW_UNLOCK(state); 774 return (MAX(t - now, 0)); 775} 776 777/* 778 * Switch to active mode (skip empty ticks). 779 */ 780void 781cpu_activeclock(void) 782{ 783 sbintime_t now; 784 struct pcpu_state *state; 785 struct thread *td; 786 787 state = DPCPU_PTR(timerstate); 788 if (state->idle == 0 || busy) 789 return; 790 if (periodic) 791 now = state->now; 792 else 793 now = sbinuptime(); 794 CTR3(KTR_SPARE2, "active at %d: now %d.%08x", 795 curcpu, (int)(now >> 32), (u_int)(now & 0xffffffff)); 796 spinlock_enter(); 797 td = curthread; 798 td->td_intr_nesting_level++; 799 handleevents(now, 1); 800 td->td_intr_nesting_level--; 801 spinlock_exit(); 802} 803 804/* 805 * Change the frequency of the given timer. This changes et->et_frequency and 806 * if et is the active timer it reconfigures the timer on all CPUs. This is 807 * intended to be a private interface for the use of et_change_frequency() only. 808 */ 809void 810cpu_et_frequency(struct eventtimer *et, uint64_t newfreq) 811{ 812 813 ET_LOCK(); 814 if (et == timer) { 815 configtimer(0); 816 et->et_frequency = newfreq; 817 configtimer(1); 818 } else 819 et->et_frequency = newfreq; 820 ET_UNLOCK(); 821} 822 823#ifdef KDTRACE_HOOKS 824void 825clocksource_cyc_set(const struct bintime *bt) 826{ 827 sbintime_t now, t; 828 struct pcpu_state *state; 829 830 /* Do not touch anything if somebody reconfiguring timers. */ 831 if (busy) 832 return; 833 t = bttosbt(*bt); 834 state = DPCPU_PTR(timerstate); 835 if (periodic) 836 now = state->now; 837 else 838 now = sbinuptime(); 839 840 CTR5(KTR_SPARE2, "set_cyc at %d: now %d.%08x t %d.%08x", 841 curcpu, (int)(now >> 32), (u_int)(now & 0xffffffff), 842 (int)(t >> 32), (u_int)(t & 0xffffffff)); 843 844 ET_HW_LOCK(state); 845 if (t == state->nextcyc) 846 goto done; 847 state->nextcyc = t; 848 if (t >= state->nextevent) 849 goto done; 850 state->nextevent = t; 851 if (!periodic) 852 loadtimer(now, 0); 853done: 854 ET_HW_UNLOCK(state); 855} 856#endif 857 858void 859cpu_new_callout(int cpu, sbintime_t bt, sbintime_t bt_opt) 860{ 861 struct pcpu_state *state; 862 863 /* Do not touch anything if somebody reconfiguring timers. */ 864 if (busy) 865 return; 866 CTR6(KTR_SPARE2, "new co at %d: on %d at %d.%08x - %d.%08x", 867 curcpu, cpu, (int)(bt_opt >> 32), (u_int)(bt_opt & 0xffffffff), 868 (int)(bt >> 32), (u_int)(bt & 0xffffffff)); 869 state = DPCPU_ID_PTR(cpu, timerstate); 870 ET_HW_LOCK(state); 871 872 /* 873 * If there is callout time already set earlier -- do nothing. 874 * This check may appear redundant because we check already in 875 * callout_process() but this double check guarantees we're safe 876 * with respect to race conditions between interrupts execution 877 * and scheduling. 878 */ 879 state->nextcallopt = bt_opt; 880 if (bt >= state->nextcall) 881 goto done; 882 state->nextcall = bt; 883 /* If there is some other event set earlier -- do nothing. */ 884 if (bt >= state->nextevent) 885 goto done; 886 state->nextevent = bt; 887 /* If timer is periodic -- there is nothing to reprogram. */ 888 if (periodic) 889 goto done; 890 /* If timer is global or of the current CPU -- reprogram it. */ 891 if ((timer->et_flags & ET_FLAGS_PERCPU) == 0 || cpu == curcpu) { 892 loadtimer(sbinuptime(), 0); 893done: 894 ET_HW_UNLOCK(state); 895 return; 896 } 897 /* Otherwise make other CPU to reprogram it. */ 898 state->handle = 1; 899 ET_HW_UNLOCK(state); 900#ifdef SMP 901 ipi_cpu(cpu, IPI_HARDCLOCK); 902#endif 903} 904 905/* 906 * Report or change the active event timers hardware. 907 */ 908static int 909sysctl_kern_eventtimer_timer(SYSCTL_HANDLER_ARGS) 910{ 911 char buf[32]; 912 struct eventtimer *et; 913 int error; 914 915 ET_LOCK(); 916 et = timer; 917 snprintf(buf, sizeof(buf), "%s", et->et_name); 918 ET_UNLOCK(); 919 error = sysctl_handle_string(oidp, buf, sizeof(buf), req); 920 ET_LOCK(); 921 et = timer; 922 if (error != 0 || req->newptr == NULL || 923 strcasecmp(buf, et->et_name) == 0) { 924 ET_UNLOCK(); 925 return (error); 926 } 927 et = et_find(buf, 0, 0); 928 if (et == NULL) { 929 ET_UNLOCK(); 930 return (ENOENT); 931 } 932 configtimer(0); 933 et_free(timer); 934 if (et->et_flags & ET_FLAGS_C3STOP) 935 cpu_disable_c3_sleep++; 936 if (timer->et_flags & ET_FLAGS_C3STOP) 937 cpu_disable_c3_sleep--; 938 periodic = want_periodic; 939 timer = et; 940 et_init(timer, timercb, NULL, NULL); 941 configtimer(1); 942 ET_UNLOCK(); 943 return (error); 944} 945SYSCTL_PROC(_kern_eventtimer, OID_AUTO, timer, 946 CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_MPSAFE, 947 0, 0, sysctl_kern_eventtimer_timer, "A", "Chosen event timer"); 948 949/* 950 * Report or change the active event timer periodicity. 951 */ 952static int 953sysctl_kern_eventtimer_periodic(SYSCTL_HANDLER_ARGS) 954{ 955 int error, val; 956 957 val = periodic; 958 error = sysctl_handle_int(oidp, &val, 0, req); 959 if (error != 0 || req->newptr == NULL) 960 return (error); 961 ET_LOCK(); 962 configtimer(0); 963 periodic = want_periodic = val; 964 configtimer(1); 965 ET_UNLOCK(); 966 return (error); 967} 968SYSCTL_PROC(_kern_eventtimer, OID_AUTO, periodic, 969 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, 970 0, 0, sysctl_kern_eventtimer_periodic, "I", "Enable event timer periodic mode"); 971 972#include "opt_ddb.h" 973 974#ifdef DDB 975#include <ddb/ddb.h> 976 977DB_SHOW_COMMAND(clocksource, db_show_clocksource) 978{ 979 struct pcpu_state *st; 980 int c; 981 982 CPU_FOREACH(c) { 983 st = DPCPU_ID_PTR(c, timerstate); 984 db_printf( 985 "CPU %2d: action %d handle %d ipi %d idle %d\n" 986 " now %#jx nevent %#jx (%jd)\n" 987 " ntick %#jx (%jd) nhard %#jx (%jd)\n" 988 " nstat %#jx (%jd) nprof %#jx (%jd)\n" 989 " ncall %#jx (%jd) ncallopt %#jx (%jd)\n", 990 c, st->action, st->handle, st->ipi, st->idle, 991 (uintmax_t)st->now, 992 (uintmax_t)st->nextevent, 993 (uintmax_t)(st->nextevent - st->now) / tick_sbt, 994 (uintmax_t)st->nexttick, 995 (uintmax_t)(st->nexttick - st->now) / tick_sbt, 996 (uintmax_t)st->nexthard, 997 (uintmax_t)(st->nexthard - st->now) / tick_sbt, 998 (uintmax_t)st->nextstat, 999 (uintmax_t)(st->nextstat - st->now) / tick_sbt, 1000 (uintmax_t)st->nextprof, 1001 (uintmax_t)(st->nextprof - st->now) / tick_sbt, 1002 (uintmax_t)st->nextcall, 1003 (uintmax_t)(st->nextcall - st->now) / tick_sbt, 1004 (uintmax_t)st->nextcallopt, 1005 (uintmax_t)(st->nextcallopt - st->now) / tick_sbt); 1006 } 1007} 1008 1009#endif 1010