1 /*- 2 * Copyright (c) 2010 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$"); 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/lock.h> 41 #include <sys/kdb.h> 42 #include <sys/ktr.h> 43 #include <sys/mutex.h> 44 #include <sys/proc.h> 45 #include <sys/kernel.h> 46 #include <sys/sched.h> 47 #include <sys/smp.h> 48 #include <sys/sysctl.h> 49 #include <sys/timeet.h> 50 #include <sys/timetc.h> 51 52 #include <machine/atomic.h> 53 #include <machine/clock.h> 54 #include <machine/cpu.h> 55 #include <machine/smp.h> 56 57 #ifdef KDTRACE_HOOKS 58 #include <sys/dtrace_bsd.h> 59 cyclic_clock_func_t cyclic_clock_func = NULL; 60 #endif 61 62 int cpu_can_deep_sleep = 0; /* C3 state is available. */ 63 int cpu_disable_deep_sleep = 0; /* Timer dies in C3. */ 64 65 static void setuptimer(void); 66 static void loadtimer(struct bintime *now, int first); 67 static int doconfigtimer(void); 68 static void configtimer(int start); 69 static int round_freq(struct eventtimer *et, int freq); 70 71 static void getnextcpuevent(struct bintime *event, int idle); 72 static void getnextevent(struct bintime *event); 73 static int handleevents(struct bintime *now, int fake); 74 #ifdef SMP 75 static void cpu_new_callout(int cpu, int ticks); 76 #endif 77 78 static struct mtx et_hw_mtx; 79 80 #define ET_HW_LOCK(state) \ 81 { \ 82 if (timer->et_flags & ET_FLAGS_PERCPU) \ 83 mtx_lock_spin(&(state)->et_hw_mtx); \ 84 else \ 85 mtx_lock_spin(&et_hw_mtx); \ 86 } 87 88 #define ET_HW_UNLOCK(state) \ 89 { \ 90 if (timer->et_flags & ET_FLAGS_PERCPU) \ 91 mtx_unlock_spin(&(state)->et_hw_mtx); \ 92 else \ 93 mtx_unlock_spin(&et_hw_mtx); \ 94 } 95 96 static struct eventtimer *timer = NULL; 97 static struct bintime timerperiod; /* Timer period for periodic mode. */ 98 static struct bintime hardperiod; /* hardclock() events period. */ 99 static struct bintime statperiod; /* statclock() events period. */ 100 static struct bintime profperiod; /* profclock() events period. */ 101 static struct bintime nexttick; /* Next global timer tick time. */ 102 static u_int busy = 0; /* Reconfiguration is in progress. */ 103 static int profiling = 0; /* Profiling events enabled. */ 104 105 static char timername[32]; /* Wanted timer. */ 106 TUNABLE_STR("kern.eventtimer.timer", timername, sizeof(timername)); 107 108 static int singlemul = 0; /* Multiplier for periodic mode. */ 109 TUNABLE_INT("kern.eventtimer.singlemul", &singlemul); 110 SYSCTL_INT(_kern_eventtimer, OID_AUTO, singlemul, CTLFLAG_RW, &singlemul, 111 0, "Multiplier for periodic mode"); 112 113 static u_int idletick = 0; /* Idle mode allowed. */ 114 TUNABLE_INT("kern.eventtimer.idletick", &idletick); 115 SYSCTL_UINT(_kern_eventtimer, OID_AUTO, idletick, CTLFLAG_RW, &idletick, 116 0, "Run periodic events when idle"); 117 118 static int periodic = 0; /* Periodic or one-shot mode. */ 119 static int want_periodic = 0; /* What mode to prefer. */ 120 TUNABLE_INT("kern.eventtimer.periodic", &want_periodic); 121 122 struct pcpu_state { 123 struct mtx et_hw_mtx; /* Per-CPU timer mutex. */ 124 u_int action; /* Reconfiguration requests. */ 125 u_int handle; /* Immediate handle resuests. */ 126 struct bintime now; /* Last tick time. */ 127 struct bintime nextevent; /* Next scheduled event on this CPU. */ 128 struct bintime nexttick; /* Next timer tick time. */ 129 struct bintime nexthard; /* Next hardlock() event. */ 130 struct bintime nextstat; /* Next statclock() event. */ 131 struct bintime nextprof; /* Next profclock() event. */ 132 #ifdef KDTRACE_HOOKS 133 struct bintime 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 139 static DPCPU_DEFINE(struct pcpu_state, timerstate); 140 141 #define FREQ2BT(freq, bt) \ 142 { \ 143 (bt)->sec = 0; \ 144 (bt)->frac = ((uint64_t)0x8000000000000000 / (freq)) << 1; \ 145 } 146 #define BT2FREQ(bt) \ 147 (((uint64_t)0x8000000000000000 + ((bt)->frac >> 2)) / \ 148 ((bt)->frac >> 1)) 149 150 /* 151 * Timer broadcast IPI handler. 152 */ 153 int 154 hardclockintr(void) 155 { 156 struct bintime now; 157 struct pcpu_state *state; 158 int done; 159 160 if (doconfigtimer() || busy) 161 return (FILTER_HANDLED); 162 state = DPCPU_PTR(timerstate); 163 now = state->now; 164 CTR4(KTR_SPARE2, "ipi at %d: now %d.%08x%08x", 165 curcpu, now.sec, (unsigned int)(now.frac >> 32), 166 (unsigned int)(now.frac & 0xffffffff)); 167 done = handleevents(&now, 0); 168 return (done ? FILTER_HANDLED : FILTER_STRAY); 169 } 170 171 /* 172 * Handle all events for specified time on this CPU 173 */ 174 static int 175 handleevents(struct bintime *now, int fake) 176 { 177 struct bintime t; 178 struct trapframe *frame; 179 struct pcpu_state *state; 180 uintfptr_t pc; 181 int usermode; 182 int done, runs; 183 184 CTR4(KTR_SPARE2, "handle at %d: now %d.%08x%08x", 185 curcpu, now->sec, (unsigned int)(now->frac >> 32), 186 (unsigned int)(now->frac & 0xffffffff)); 187 done = 0; 188 if (fake) { 189 frame = NULL; 190 usermode = 0; 191 pc = 0; 192 } else { 193 frame = curthread->td_intr_frame; 194 usermode = TRAPF_USERMODE(frame); 195 pc = TRAPF_PC(frame); 196 } 197 198 runs = 0; 199 state = DPCPU_PTR(timerstate); 200 201 while (bintime_cmp(now, &state->nexthard, >=)) { 202 bintime_add(&state->nexthard, &hardperiod); 203 runs++; 204 } 205 if (runs && fake < 2) { 206 hardclock_anycpu(runs, usermode); 207 done = 1; 208 } 209 while (bintime_cmp(now, &state->nextstat, >=)) { 210 if (fake < 2) 211 statclock(usermode); 212 bintime_add(&state->nextstat, &statperiod); 213 done = 1; 214 } 215 if (profiling) { 216 while (bintime_cmp(now, &state->nextprof, >=)) { 217 if (!fake) 218 profclock(usermode, pc); 219 bintime_add(&state->nextprof, &profperiod); 220 done = 1; 221 } 222 } else 223 state->nextprof = state->nextstat; 224 225 #ifdef KDTRACE_HOOKS 226 if (fake == 0 && cyclic_clock_func != NULL && 227 state->nextcyc.sec != -1 && 228 bintime_cmp(now, &state->nextcyc, >=)) { 229 state->nextcyc.sec = -1; 230 (*cyclic_clock_func)(frame); 231 } 232 #endif 233 234 getnextcpuevent(&t, 0); 235 if (fake == 2) { 236 state->nextevent = t; 237 return (done); 238 } 239 ET_HW_LOCK(state); 240 if (!busy) { 241 state->idle = 0; 242 state->nextevent = t; 243 loadtimer(now, 0); 244 } 245 ET_HW_UNLOCK(state); 246 return (done); 247 } 248 249 /* 250 * Schedule binuptime of the next event on current CPU. 251 */ 252 static void 253 getnextcpuevent(struct bintime *event, int idle) 254 { 255 struct bintime tmp; 256 struct pcpu_state *state; 257 int skip; 258 259 state = DPCPU_PTR(timerstate); 260 *event = state->nexthard; 261 if (idle) { /* If CPU is idle - ask callouts for how long. */ 262 skip = 4; 263 if (curcpu == CPU_FIRST() && tc_min_ticktock_freq > skip) 264 skip = tc_min_ticktock_freq; 265 skip = callout_tickstofirst(hz / skip) - 1; 266 CTR2(KTR_SPARE2, "skip at %d: %d", curcpu, skip); 267 tmp = hardperiod; 268 bintime_mul(&tmp, skip); 269 bintime_add(event, &tmp); 270 } else { /* If CPU is active - handle all types of events. */ 271 if (bintime_cmp(event, &state->nextstat, >)) 272 *event = state->nextstat; 273 if (profiling && bintime_cmp(event, &state->nextprof, >)) 274 *event = state->nextprof; 275 } 276 #ifdef KDTRACE_HOOKS 277 if (state->nextcyc.sec != -1 && bintime_cmp(event, &state->nextcyc, >)) 278 *event = state->nextcyc; 279 #endif 280 } 281 282 /* 283 * Schedule binuptime of the next event on all CPUs. 284 */ 285 static void 286 getnextevent(struct bintime *event) 287 { 288 struct pcpu_state *state; 289 #ifdef SMP 290 int cpu; 291 #endif 292 int c; 293 294 state = DPCPU_PTR(timerstate); 295 *event = state->nextevent; 296 c = curcpu; 297 #ifdef SMP 298 if ((timer->et_flags & ET_FLAGS_PERCPU) == 0) { 299 CPU_FOREACH(cpu) { 300 if (curcpu == cpu) 301 continue; 302 state = DPCPU_ID_PTR(cpu, timerstate); 303 if (bintime_cmp(event, &state->nextevent, >)) { 304 *event = state->nextevent; 305 c = cpu; 306 } 307 } 308 } 309 #endif 310 CTR5(KTR_SPARE2, "next at %d: next %d.%08x%08x by %d", 311 curcpu, event->sec, (unsigned int)(event->frac >> 32), 312 (unsigned int)(event->frac & 0xffffffff), c); 313 } 314 315 /* Hardware timer callback function. */ 316 static void 317 timercb(struct eventtimer *et, void *arg) 318 { 319 struct bintime now; 320 struct bintime *next; 321 struct pcpu_state *state; 322 #ifdef SMP 323 int cpu, bcast; 324 #endif 325 326 /* Do not touch anything if somebody reconfiguring timers. */ 327 if (busy) 328 return; 329 /* Update present and next tick times. */ 330 state = DPCPU_PTR(timerstate); 331 if (et->et_flags & ET_FLAGS_PERCPU) { 332 next = &state->nexttick; 333 } else 334 next = &nexttick; 335 if (periodic) { 336 now = *next; /* Ex-next tick time becomes present time. */ 337 bintime_add(next, &timerperiod); /* Next tick in 1 period. */ 338 } else { 339 binuptime(&now); /* Get present time from hardware. */ 340 next->sec = -1; /* Next tick is not scheduled yet. */ 341 } 342 state->now = now; 343 CTR4(KTR_SPARE2, "intr at %d: now %d.%08x%08x", 344 curcpu, now.sec, (unsigned int)(now.frac >> 32), 345 (unsigned int)(now.frac & 0xffffffff)); 346 347 #ifdef SMP 348 /* Prepare broadcasting to other CPUs for non-per-CPU timers. */ 349 bcast = 0; 350 if ((et->et_flags & ET_FLAGS_PERCPU) == 0 && smp_started) { 351 CPU_FOREACH(cpu) { 352 state = DPCPU_ID_PTR(cpu, timerstate); 353 ET_HW_LOCK(state); 354 state->now = now; 355 if (bintime_cmp(&now, &state->nextevent, >=)) { 356 state->nextevent.sec++; 357 if (curcpu != cpu) { 358 state->ipi = 1; 359 bcast = 1; 360 } 361 } 362 ET_HW_UNLOCK(state); 363 } 364 } 365 #endif 366 367 /* Handle events for this time on this CPU. */ 368 handleevents(&now, 0); 369 370 #ifdef SMP 371 /* Broadcast interrupt to other CPUs for non-per-CPU timers. */ 372 if (bcast) { 373 CPU_FOREACH(cpu) { 374 if (curcpu == cpu) 375 continue; 376 state = DPCPU_ID_PTR(cpu, timerstate); 377 if (state->ipi) { 378 state->ipi = 0; 379 ipi_cpu(cpu, IPI_HARDCLOCK); 380 } 381 } 382 } 383 #endif 384 } 385 386 /* 387 * Load new value into hardware timer. 388 */ 389 static void 390 loadtimer(struct bintime *now, int start) 391 { 392 struct pcpu_state *state; 393 struct bintime new; 394 struct bintime *next; 395 uint64_t tmp; 396 int eq; 397 398 if (timer->et_flags & ET_FLAGS_PERCPU) { 399 state = DPCPU_PTR(timerstate); 400 next = &state->nexttick; 401 } else 402 next = &nexttick; 403 if (periodic) { 404 if (start) { 405 /* 406 * Try to start all periodic timers aligned 407 * to period to make events synchronous. 408 */ 409 tmp = ((uint64_t)now->sec << 36) + (now->frac >> 28); 410 tmp = (tmp % (timerperiod.frac >> 28)) << 28; 411 new.sec = 0; 412 new.frac = timerperiod.frac - tmp; 413 if (new.frac < tmp) /* Left less then passed. */ 414 bintime_add(&new, &timerperiod); 415 CTR5(KTR_SPARE2, "load p at %d: now %d.%08x first in %d.%08x", 416 curcpu, now->sec, (unsigned int)(now->frac >> 32), 417 new.sec, (unsigned int)(new.frac >> 32)); 418 *next = new; 419 bintime_add(next, now); 420 et_start(timer, &new, &timerperiod); 421 } 422 } else { 423 getnextevent(&new); 424 eq = bintime_cmp(&new, next, ==); 425 CTR5(KTR_SPARE2, "load at %d: next %d.%08x%08x eq %d", 426 curcpu, new.sec, (unsigned int)(new.frac >> 32), 427 (unsigned int)(new.frac & 0xffffffff), 428 eq); 429 if (!eq) { 430 *next = new; 431 bintime_sub(&new, now); 432 et_start(timer, &new, NULL); 433 } 434 } 435 } 436 437 /* 438 * Prepare event timer parameters after configuration changes. 439 */ 440 static void 441 setuptimer(void) 442 { 443 int freq; 444 445 if (periodic && (timer->et_flags & ET_FLAGS_PERIODIC) == 0) 446 periodic = 0; 447 else if (!periodic && (timer->et_flags & ET_FLAGS_ONESHOT) == 0) 448 periodic = 1; 449 singlemul = MIN(MAX(singlemul, 1), 20); 450 freq = hz * singlemul; 451 while (freq < (profiling ? profhz : stathz)) 452 freq += hz; 453 freq = round_freq(timer, freq); 454 FREQ2BT(freq, &timerperiod); 455 } 456 457 /* 458 * Reconfigure specified per-CPU timer on other CPU. Called from IPI handler. 459 */ 460 static int 461 doconfigtimer(void) 462 { 463 struct bintime now; 464 struct pcpu_state *state; 465 466 state = DPCPU_PTR(timerstate); 467 switch (atomic_load_acq_int(&state->action)) { 468 case 1: 469 binuptime(&now); 470 ET_HW_LOCK(state); 471 loadtimer(&now, 1); 472 ET_HW_UNLOCK(state); 473 state->handle = 0; 474 atomic_store_rel_int(&state->action, 0); 475 return (1); 476 case 2: 477 ET_HW_LOCK(state); 478 et_stop(timer); 479 ET_HW_UNLOCK(state); 480 state->handle = 0; 481 atomic_store_rel_int(&state->action, 0); 482 return (1); 483 } 484 if (atomic_readandclear_int(&state->handle) && !busy) { 485 binuptime(&now); 486 handleevents(&now, 0); 487 return (1); 488 } 489 return (0); 490 } 491 492 /* 493 * Reconfigure specified timer. 494 * For per-CPU timers use IPI to make other CPUs to reconfigure. 495 */ 496 static void 497 configtimer(int start) 498 { 499 struct bintime now, next; 500 struct pcpu_state *state; 501 int cpu; 502 503 if (start) { 504 setuptimer(); 505 binuptime(&now); 506 } 507 critical_enter(); 508 ET_HW_LOCK(DPCPU_PTR(timerstate)); 509 if (start) { 510 /* Initialize time machine parameters. */ 511 next = now; 512 bintime_add(&next, &timerperiod); 513 if (periodic) 514 nexttick = next; 515 else 516 nexttick.sec = -1; 517 CPU_FOREACH(cpu) { 518 state = DPCPU_ID_PTR(cpu, timerstate); 519 state->now = now; 520 state->nextevent = next; 521 if (periodic) 522 state->nexttick = next; 523 else 524 state->nexttick.sec = -1; 525 state->nexthard = next; 526 state->nextstat = next; 527 state->nextprof = next; 528 hardclock_sync(cpu); 529 } 530 busy = 0; 531 /* Start global timer or per-CPU timer of this CPU. */ 532 loadtimer(&now, 1); 533 } else { 534 busy = 1; 535 /* Stop global timer or per-CPU timer of this CPU. */ 536 et_stop(timer); 537 } 538 ET_HW_UNLOCK(DPCPU_PTR(timerstate)); 539 #ifdef SMP 540 /* If timer is global or there is no other CPUs yet - we are done. */ 541 if ((timer->et_flags & ET_FLAGS_PERCPU) == 0 || !smp_started) { 542 critical_exit(); 543 return; 544 } 545 /* Set reconfigure flags for other CPUs. */ 546 CPU_FOREACH(cpu) { 547 state = DPCPU_ID_PTR(cpu, timerstate); 548 atomic_store_rel_int(&state->action, 549 (cpu == curcpu) ? 0 : ( start ? 1 : 2)); 550 } 551 /* Broadcast reconfigure IPI. */ 552 ipi_all_but_self(IPI_HARDCLOCK); 553 /* Wait for reconfiguration completed. */ 554 restart: 555 cpu_spinwait(); 556 CPU_FOREACH(cpu) { 557 if (cpu == curcpu) 558 continue; 559 state = DPCPU_ID_PTR(cpu, timerstate); 560 if (atomic_load_acq_int(&state->action)) 561 goto restart; 562 } 563 #endif 564 critical_exit(); 565 } 566 567 /* 568 * Calculate nearest frequency supported by hardware timer. 569 */ 570 static int 571 round_freq(struct eventtimer *et, int freq) 572 { 573 uint64_t div; 574 575 if (et->et_frequency != 0) { 576 div = lmax((et->et_frequency + freq / 2) / freq, 1); 577 if (et->et_flags & ET_FLAGS_POW2DIV) 578 div = 1 << (flsl(div + div / 2) - 1); 579 freq = (et->et_frequency + div / 2) / div; 580 } 581 if (et->et_min_period.sec > 0) 582 freq = 0; 583 else if (et->et_min_period.frac != 0) 584 freq = min(freq, BT2FREQ(&et->et_min_period)); 585 if (et->et_max_period.sec == 0 && et->et_max_period.frac != 0) 586 freq = max(freq, BT2FREQ(&et->et_max_period)); 587 return (freq); 588 } 589 590 /* 591 * Configure and start event timers (BSP part). 592 */ 593 void 594 cpu_initclocks_bsp(void) 595 { 596 struct pcpu_state *state; 597 int base, div, cpu; 598 599 mtx_init(&et_hw_mtx, "et_hw_mtx", NULL, MTX_SPIN); 600 CPU_FOREACH(cpu) { 601 state = DPCPU_ID_PTR(cpu, timerstate); 602 mtx_init(&state->et_hw_mtx, "et_hw_mtx", NULL, MTX_SPIN); 603 #ifdef KDTRACE_HOOKS 604 state->nextcyc.sec = -1; 605 #endif 606 } 607 #ifdef SMP 608 callout_new_inserted = cpu_new_callout; 609 #endif 610 periodic = want_periodic; 611 /* Grab requested timer or the best of present. */ 612 if (timername[0]) 613 timer = et_find(timername, 0, 0); 614 if (timer == NULL && periodic) { 615 timer = et_find(NULL, 616 ET_FLAGS_PERIODIC, ET_FLAGS_PERIODIC); 617 } 618 if (timer == NULL) { 619 timer = et_find(NULL, 620 ET_FLAGS_ONESHOT, ET_FLAGS_ONESHOT); 621 } 622 if (timer == NULL && !periodic) { 623 timer = et_find(NULL, 624 ET_FLAGS_PERIODIC, ET_FLAGS_PERIODIC); 625 } 626 if (timer == NULL) 627 panic("No usable event timer found!"); 628 et_init(timer, timercb, NULL, NULL); 629 630 /* Adapt to timer capabilities. */ 631 if (periodic && (timer->et_flags & ET_FLAGS_PERIODIC) == 0) 632 periodic = 0; 633 else if (!periodic && (timer->et_flags & ET_FLAGS_ONESHOT) == 0) 634 periodic = 1; 635 if (timer->et_flags & ET_FLAGS_C3STOP) 636 cpu_disable_deep_sleep++; 637 638 /* 639 * We honor the requested 'hz' value. 640 * We want to run stathz in the neighborhood of 128hz. 641 * We would like profhz to run as often as possible. 642 */ 643 if (singlemul <= 0 || singlemul > 20) { 644 if (hz >= 1500 || (hz % 128) == 0) 645 singlemul = 1; 646 else if (hz >= 750) 647 singlemul = 2; 648 else 649 singlemul = 4; 650 } 651 if (periodic) { 652 base = round_freq(timer, hz * singlemul); 653 singlemul = max((base + hz / 2) / hz, 1); 654 hz = (base + singlemul / 2) / singlemul; 655 if (base <= 128) 656 stathz = base; 657 else { 658 div = base / 128; 659 if (div >= singlemul && (div % singlemul) == 0) 660 div++; 661 stathz = base / div; 662 } 663 profhz = stathz; 664 while ((profhz + stathz) <= 128 * 64) 665 profhz += stathz; 666 profhz = round_freq(timer, profhz); 667 } else { 668 hz = round_freq(timer, hz); 669 stathz = round_freq(timer, 127); 670 profhz = round_freq(timer, stathz * 64); 671 } 672 tick = 1000000 / hz; 673 FREQ2BT(hz, &hardperiod); 674 FREQ2BT(stathz, &statperiod); 675 FREQ2BT(profhz, &profperiod); 676 ET_LOCK(); 677 configtimer(1); 678 ET_UNLOCK(); 679 } 680 681 /* 682 * Start per-CPU event timers on APs. 683 */ 684 void 685 cpu_initclocks_ap(void) 686 { 687 struct bintime now; 688 struct pcpu_state *state; 689 690 state = DPCPU_PTR(timerstate); 691 binuptime(&now); 692 ET_HW_LOCK(state); 693 if ((timer->et_flags & ET_FLAGS_PERCPU) == 0 && periodic) { 694 state->now = nexttick; 695 bintime_sub(&state->now, &timerperiod); 696 } else 697 state->now = now; 698 hardclock_sync(curcpu); 699 handleevents(&state->now, 2); 700 if (timer->et_flags & ET_FLAGS_PERCPU) 701 loadtimer(&now, 1); 702 ET_HW_UNLOCK(state); 703 } 704 705 /* 706 * Switch to profiling clock rates. 707 */ 708 void 709 cpu_startprofclock(void) 710 { 711 712 ET_LOCK(); 713 if (periodic) { 714 configtimer(0); 715 profiling = 1; 716 configtimer(1); 717 } else 718 profiling = 1; 719 ET_UNLOCK(); 720 } 721 722 /* 723 * Switch to regular clock rates. 724 */ 725 void 726 cpu_stopprofclock(void) 727 { 728 729 ET_LOCK(); 730 if (periodic) { 731 configtimer(0); 732 profiling = 0; 733 configtimer(1); 734 } else 735 profiling = 0; 736 ET_UNLOCK(); 737 } 738 739 /* 740 * Switch to idle mode (all ticks handled). 741 */ 742 void 743 cpu_idleclock(void) 744 { 745 struct bintime now, t; 746 struct pcpu_state *state; 747 748 if (idletick || busy || 749 (periodic && (timer->et_flags & ET_FLAGS_PERCPU)) 750 #ifdef DEVICE_POLLING 751 || curcpu == CPU_FIRST() 752 #endif 753 ) 754 return; 755 state = DPCPU_PTR(timerstate); 756 if (periodic) 757 now = state->now; 758 else 759 binuptime(&now); 760 CTR4(KTR_SPARE2, "idle at %d: now %d.%08x%08x", 761 curcpu, now.sec, (unsigned int)(now.frac >> 32), 762 (unsigned int)(now.frac & 0xffffffff)); 763 getnextcpuevent(&t, 1); 764 ET_HW_LOCK(state); 765 state->idle = 1; 766 state->nextevent = t; 767 if (!periodic) 768 loadtimer(&now, 0); 769 ET_HW_UNLOCK(state); 770 } 771 772 /* 773 * Switch to active mode (skip empty ticks). 774 */ 775 void 776 cpu_activeclock(void) 777 { 778 struct bintime now; 779 struct pcpu_state *state; 780 struct thread *td; 781 782 state = DPCPU_PTR(timerstate); 783 if (state->idle == 0 || busy) 784 return; 785 if (periodic) 786 now = state->now; 787 else 788 binuptime(&now); 789 CTR4(KTR_SPARE2, "active at %d: now %d.%08x%08x", 790 curcpu, now.sec, (unsigned int)(now.frac >> 32), 791 (unsigned int)(now.frac & 0xffffffff)); 792 spinlock_enter(); 793 td = curthread; 794 td->td_intr_nesting_level++; 795 handleevents(&now, 1); 796 td->td_intr_nesting_level--; 797 spinlock_exit(); 798 } 799 800 #ifdef KDTRACE_HOOKS 801 void 802 clocksource_cyc_set(const struct bintime *t) 803 { 804 struct bintime now; 805 struct pcpu_state *state; 806 807 state = DPCPU_PTR(timerstate); 808 if (periodic) 809 now = state->now; 810 else 811 binuptime(&now); 812 813 CTR4(KTR_SPARE2, "set_cyc at %d: now %d.%08x%08x", 814 curcpu, now.sec, (unsigned int)(now.frac >> 32), 815 (unsigned int)(now.frac & 0xffffffff)); 816 CTR4(KTR_SPARE2, "set_cyc at %d: t %d.%08x%08x", 817 curcpu, t->sec, (unsigned int)(t->frac >> 32), 818 (unsigned int)(t->frac & 0xffffffff)); 819 820 ET_HW_LOCK(state); 821 if (bintime_cmp(t, &state->nextcyc, ==)) { 822 ET_HW_UNLOCK(state); 823 return; 824 } 825 state->nextcyc = *t; 826 if (bintime_cmp(&state->nextcyc, &state->nextevent, >=)) { 827 ET_HW_UNLOCK(state); 828 return; 829 } 830 state->nextevent = state->nextcyc; 831 if (!periodic) 832 loadtimer(&now, 0); 833 ET_HW_UNLOCK(state); 834 } 835 #endif 836 837 #ifdef SMP 838 static void 839 cpu_new_callout(int cpu, int ticks) 840 { 841 struct bintime tmp; 842 struct pcpu_state *state; 843 844 CTR3(KTR_SPARE2, "new co at %d: on %d in %d", 845 curcpu, cpu, ticks); 846 state = DPCPU_ID_PTR(cpu, timerstate); 847 ET_HW_LOCK(state); 848 if (state->idle == 0 || busy) { 849 ET_HW_UNLOCK(state); 850 return; 851 } 852 /* 853 * If timer is periodic - just update next event time for target CPU. 854 * If timer is global - there is chance it is already programmed. 855 */ 856 if (periodic || (timer->et_flags & ET_FLAGS_PERCPU) == 0) { 857 state->nextevent = state->nexthard; 858 tmp = hardperiod; 859 bintime_mul(&tmp, ticks - 1); 860 bintime_add(&state->nextevent, &tmp); 861 if (periodic || 862 bintime_cmp(&state->nextevent, &nexttick, >=)) { 863 ET_HW_UNLOCK(state); 864 return; 865 } 866 } 867 /* 868 * Otherwise we have to wake that CPU up, as we can't get present 869 * bintime to reprogram global timer from here. If timer is per-CPU, 870 * we by definition can't do it from here. 871 */ 872 ET_HW_UNLOCK(state); 873 if (timer->et_flags & ET_FLAGS_PERCPU) { 874 state->handle = 1; 875 ipi_cpu(cpu, IPI_HARDCLOCK); 876 } else { 877 if (!cpu_idle_wakeup(cpu)) 878 ipi_cpu(cpu, IPI_AST); 879 } 880 } 881 #endif 882 883 /* 884 * Report or change the active event timers hardware. 885 */ 886 static int 887 sysctl_kern_eventtimer_timer(SYSCTL_HANDLER_ARGS) 888 { 889 char buf[32]; 890 struct eventtimer *et; 891 int error; 892 893 ET_LOCK(); 894 et = timer; 895 snprintf(buf, sizeof(buf), "%s", et->et_name); 896 ET_UNLOCK(); 897 error = sysctl_handle_string(oidp, buf, sizeof(buf), req); 898 ET_LOCK(); 899 et = timer; 900 if (error != 0 || req->newptr == NULL || 901 strcasecmp(buf, et->et_name) == 0) { 902 ET_UNLOCK(); 903 return (error); 904 } 905 et = et_find(buf, 0, 0); 906 if (et == NULL) { 907 ET_UNLOCK(); 908 return (ENOENT); 909 } 910 configtimer(0); 911 et_free(timer); 912 if (et->et_flags & ET_FLAGS_C3STOP) 913 cpu_disable_deep_sleep++; 914 if (timer->et_flags & ET_FLAGS_C3STOP) 915 cpu_disable_deep_sleep--; 916 periodic = want_periodic; 917 timer = et; 918 et_init(timer, timercb, NULL, NULL); 919 configtimer(1); 920 ET_UNLOCK(); 921 return (error); 922 } 923 SYSCTL_PROC(_kern_eventtimer, OID_AUTO, timer, 924 CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_MPSAFE, 925 0, 0, sysctl_kern_eventtimer_timer, "A", "Chosen event timer"); 926 927 /* 928 * Report or change the active event timer periodicity. 929 */ 930 static int 931 sysctl_kern_eventtimer_periodic(SYSCTL_HANDLER_ARGS) 932 { 933 int error, val; 934 935 val = periodic; 936 error = sysctl_handle_int(oidp, &val, 0, req); 937 if (error != 0 || req->newptr == NULL) 938 return (error); 939 ET_LOCK(); 940 configtimer(0); 941 periodic = want_periodic = val; 942 configtimer(1); 943 ET_UNLOCK(); 944 return (error); 945 } 946 SYSCTL_PROC(_kern_eventtimer, OID_AUTO, periodic, 947 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_MPSAFE, 948 0, 0, sysctl_kern_eventtimer_periodic, "I", "Enable event timer periodic mode"); 949