1 /* $NetBSD: clock.c,v 1.124 2024/07/12 22:31:40 andvar Exp $ */ 2 3 /* 4 * Copyright (c) 1992, 1993 5 * The Regents of the University of California. All rights reserved. 6 * Copyright (c) 1994 Gordon W. Ross 7 * Copyright (c) 1993 Adam Glass 8 * Copyright (c) 1996 Paul Kranenburg 9 * Copyright (c) 1996 10 * The President and Fellows of Harvard College. All rights reserved. 11 * 12 * This software was developed by the Computer Systems Engineering group 13 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 14 * contributed to Berkeley. 15 * 16 * All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by Harvard University. 19 * This product includes software developed by the University of 20 * California, Lawrence Berkeley Laboratory. 21 * 22 * Redistribution and use in source and binary forms, with or without 23 * modification, are permitted provided that the following conditions 24 * are met: 25 * 26 * 1. Redistributions of source code must retain the above copyright 27 * notice, this list of conditions and the following disclaimer. 28 * 2. Redistributions in binary form must reproduce the above copyright 29 * notice, this list of conditions and the following disclaimer in the 30 * documentation and/or other materials provided with the distribution. 31 * 3. All advertising materials mentioning features or use of this software 32 * must display the following acknowledgement: 33 * This product includes software developed by the University of 34 * California, Berkeley and its contributors. 35 * This product includes software developed by Paul Kranenburg. 36 * This product includes software developed by Harvard University. 37 * 4. Neither the name of the University nor the names of its contributors 38 * may be used to endorse or promote products derived from this software 39 * without specific prior written permission. 40 * 41 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 42 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 44 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 45 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 46 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 47 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 48 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 49 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 50 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 51 * SUCH DAMAGE. 52 * 53 * @(#)clock.c 8.1 (Berkeley) 6/11/93 54 * 55 */ 56 57 #include <sys/cdefs.h> 58 __KERNEL_RCSID(0, "$NetBSD: clock.c,v 1.124 2024/07/12 22:31:40 andvar Exp $"); 59 60 #include "opt_multiprocessor.h" 61 62 /* 63 * Clock driver. This is the id prom and eeprom driver as well 64 * and includes the timer register functions too. 65 */ 66 67 /* Define this for a 1/4s clock to ease debugging */ 68 /* #define INTR_DEBUG */ 69 70 #include <sys/param.h> 71 #include <sys/kernel.h> 72 #include <sys/device.h> 73 #include <sys/proc.h> 74 #include <sys/resourcevar.h> 75 #include <sys/systm.h> 76 #include <sys/timetc.h> 77 #ifdef GPROF 78 #include <sys/gmon.h> 79 #endif 80 81 #include <uvm/uvm_extern.h> 82 83 #include <sys/bus.h> 84 #include <machine/autoconf.h> 85 #include <machine/eeprom.h> 86 #include <machine/cpu.h> 87 88 #include <sparc64/sparc64/intreg.h> 89 #include <sparc64/sparc64/timerreg.h> 90 #include <sparc64/dev/iommureg.h> 91 92 #include "psycho.h" 93 /* just because US-IIe STICK registers live in psycho space */ 94 #if NPSYCHO > 0 95 #include <dev/pci/pcivar.h> 96 #include <dev/pci/pcireg.h> 97 #include <sparc64/dev/iommureg.h> 98 #include <sparc64/dev/iommuvar.h> 99 #include <sparc64/dev/psychoreg.h> 100 #include <sparc64/dev/psychovar.h> 101 #endif 102 103 /* 104 * Clock assignments: 105 * 106 * machine hardclock statclock timecounter 107 * counter-timer timer#0 timer#1 %tick 108 * counter-timer + SMP timer#0/%tick - timer#1 or %tick 109 * no counter-timer %tick - %tick 110 * US-IIe STICK - STICK 111 * US-IIIi %stick - %stick 112 * sun4v %stick - %stick 113 * 114 * US-IIe and US-IIIi could use %tick as statclock 115 */ 116 117 /* 118 * Statistics clock interval and variance, in usec. Variance must be a 119 * power of two. Since this gives us an even number, not an odd number, 120 * we discard one case and compensate. That is, a variance of 1024 would 121 * give us offsets in [0..1023]. Instead, we take offsets in [1..1023]. 122 * This is symmetric about the point 512, or statvar/2, and thus averages 123 * to that value (assuming uniform random numbers). 124 */ 125 /* XXX fix comment to match value */ 126 int statvar = 8192; 127 int statmin; /* statclock interval - 1/2*variance */ 128 int timerok; 129 #ifndef MULTIPROCESSOR 130 static int statscheddiv; 131 static struct intrhand *schedint; 132 #endif 133 134 static int timermatch(device_t, cfdata_t, void *); 135 static void timerattach(device_t, device_t, void *); 136 137 struct timerreg_4u timerreg_4u; /* XXX - need more cleanup */ 138 139 CFATTACH_DECL_NEW(timer, 0, 140 timermatch, timerattach, NULL, NULL); 141 142 struct chiptime; 143 void stopcounter(struct timer_4u *); 144 145 int timerblurb = 10; /* Guess a value; used before clock is attached */ 146 147 static u_int tick_get_timecount(struct timecounter *); 148 static u_int stick_get_timecount(struct timecounter *); 149 #if NPSYCHO > 0 150 static u_int stick2e_get_timecount(struct timecounter *); 151 #endif 152 153 /* 154 * define timecounter "tick-counter" 155 */ 156 157 static struct timecounter tick_timecounter = { 158 .tc_get_timecount = tick_get_timecount, 159 .tc_counter_mask = ~0u, 160 .tc_name = "tick-counter", 161 .tc_quality = 100, 162 }; 163 164 /* US-III %stick */ 165 166 static struct timecounter stick_timecounter = { 167 .tc_get_timecount = stick_get_timecount, 168 .tc_counter_mask = ~0u, 169 .tc_name = "stick-counter", 170 .tc_quality = 200, 171 }; 172 173 /* US-IIe STICK counter */ 174 #if NPSYCHO > 0 175 static struct timecounter stick2e_timecounter = { 176 .tc_get_timecount = stick2e_get_timecount, 177 .tc_counter_mask = ~0u, 178 .tc_name = "stick-counter", 179 .tc_quality = 200, 180 }; 181 #endif 182 183 /* 184 * tick_get_timecount provide current tick counter value 185 */ 186 static u_int 187 tick_get_timecount(struct timecounter *tc) 188 { 189 return gettick(); 190 } 191 192 static u_int 193 stick_get_timecount(struct timecounter *tc) 194 { 195 return getstick(); 196 } 197 198 #if NPSYCHO > 0 199 static u_int 200 stick2e_get_timecount(struct timecounter *tc) 201 { 202 return psycho_getstick32(); 203 } 204 #endif 205 206 #ifdef MULTIPROCESSOR 207 static u_int counter_get_timecount(struct timecounter *); 208 209 /* 210 * define timecounter "counter-timer" 211 */ 212 213 static struct timecounter counter_timecounter = { 214 counter_get_timecount, /* get_timecount */ 215 0, /* no poll_pps */ 216 TMR_LIM_MASK, /* counter_mask */ 217 1000000, /* frequency */ 218 "counter-timer", /* name */ 219 200, /* quality */ 220 0, /* private reference - UNUSED */ 221 NULL /* next timecounter */ 222 }; 223 224 /* 225 * counter_get_timecount provide current counter value 226 */ 227 static u_int 228 counter_get_timecount(struct timecounter *tc) 229 { 230 return (u_int)ldxa((vaddr_t)&timerreg_4u.t_timer[1].t_count, 231 ASI_NUCLEUS) & TMR_LIM_MASK; 232 } 233 #endif 234 235 /* 236 * The sun4u OPENPROMs call the timer the "counter-timer", except for 237 * the lame UltraSPARC IIi PCI machines that don't have them. 238 */ 239 static int 240 timermatch(device_t parent, cfdata_t cf, void *aux) 241 { 242 struct mainbus_attach_args *ma = aux; 243 244 return (strcmp("counter-timer", ma->ma_name) == 0); 245 } 246 247 static void 248 timerattach(device_t parent, device_t self, void *aux) 249 { 250 struct mainbus_attach_args *ma = aux; 251 u_int *va = ma->ma_address; 252 #if 0 253 volatile int64_t *cnt = NULL, *lim = NULL; 254 #endif 255 256 /* 257 * What we should have are 3 sets of registers that reside on 258 * different parts of SYSIO or PSYCHO. We'll use the prom 259 * mappings cause we can't get rid of them and set up appropriate 260 * pointers on the timerreg_4u structure. 261 */ 262 timerreg_4u.t_timer = (struct timer_4u *)(u_long)va[0]; 263 timerreg_4u.t_clrintr = (int64_t *)(u_long)va[1]; 264 timerreg_4u.t_mapintr = (int64_t *)(u_long)va[2]; 265 266 /* 267 * Disable interrupts for now. 268 * N.B. By default timer[0] is disabled and timer[1] is enabled. 269 */ 270 stxa((vaddr_t)&timerreg_4u.t_mapintr[0], ASI_NUCLEUS, 271 (timerreg_4u.t_mapintr[0] & ~(INTMAP_V|INTMAP_TID)) | 272 (CPU_UPAID << INTMAP_TID_SHIFT)); 273 stxa((vaddr_t)&timerreg_4u.t_mapintr[1], ASI_NUCLEUS, 274 (timerreg_4u.t_mapintr[1] & ~(INTMAP_V|INTMAP_TID)) | 275 (CPU_UPAID << INTMAP_TID_SHIFT)); 276 277 /* Install the appropriate interrupt vector here */ 278 struct intrhand *level10 = intrhand_alloc(); 279 level10->ih_fun = clockintr; 280 level10->ih_pil = PIL_CLOCK; 281 level10->ih_number = INTVEC(ma->ma_interrupts[0]); 282 level10->ih_clr = &timerreg_4u.t_clrintr[0]; 283 intr_establish(PIL_CLOCK, true, level10); 284 printf(" irq vectors %lx", (u_long)level10->ih_number); 285 #ifndef MULTIPROCESSOR 286 /* 287 * On SMP kernel, don't establish interrupt to use it as timecounter. 288 */ 289 struct intrhand *level14 = intrhand_alloc(); 290 level14->ih_fun = statintr; 291 level14->ih_pil = PIL_STATCLOCK; 292 level14->ih_number = INTVEC(ma->ma_interrupts[1]); 293 level14->ih_clr = &timerreg_4u.t_clrintr[1]; 294 intr_establish(PIL_STATCLOCK, true, level14); 295 printf(" and %lx", (u_long)level14->ih_number); 296 #endif 297 298 #if 0 299 cnt = &(timerreg_4u.t_timer[0].t_count); 300 lim = &(timerreg_4u.t_timer[0].t_limit); 301 302 /* 303 * Calibrate delay() by tweaking the magic constant 304 * until a delay(100) actually reads (at least) 100 us 305 * on the clock. Since we're using the %tick register 306 * which should be running at exactly the CPU clock rate, it 307 * has a period of somewhere between 7ns and 3ns. 308 */ 309 310 #ifdef DEBUG 311 printf("Delay calibration....\n"); 312 #endif 313 for (timerblurb = 1; timerblurb > 0; timerblurb++) { 314 volatile int discard; 315 register int t0, t1; 316 317 /* Reset counter register by writing some large limit value */ 318 discard = *lim; 319 *lim = tmr_ustolim(TMR_MASK-1); 320 321 t0 = *cnt; 322 delay(100); 323 t1 = *cnt; 324 325 if (t1 & TMR_LIMIT) 326 panic("delay calibration"); 327 328 t0 = (t0 >> TMR_SHIFT) & TMR_MASK; 329 t1 = (t1 >> TMR_SHIFT) & TMR_MASK; 330 331 if (t1 >= t0 + 100) 332 break; 333 } 334 335 printf(" delay constant %d\n", timerblurb); 336 #endif 337 printf("\n"); 338 timerok = 1; 339 } 340 341 void 342 stopcounter(struct timer_4u *creg) 343 { 344 volatile struct timer_4u *reg = creg; 345 346 /* Stop the clock */ 347 (void)reg->t_limit; 348 reg->t_limit = 0; 349 } 350 351 /* 352 * Untill interrupts are established per CPU, we rely on the special 353 * handling of tickintr in locore.s. 354 * We establish this interrupt if there is no real counter-timer on 355 * the machine, or on secondary CPUs. The latter would normally not be 356 * able to dispatch the interrupt (established on cpu0) to another cpu, 357 * but the shortcut during dispatch makes it work. 358 */ 359 void 360 tickintr_establish(int pil, int (*fun)(void *)) 361 { 362 int s; 363 struct intrhand *ih; 364 struct cpu_info *ci = curcpu(); 365 366 ih = sparc_softintr_establish(pil, fun, NULL); 367 ih->ih_number = 1; 368 if (CPU_IS_PRIMARY(ci)) 369 intr_establish(pil, true, ih); 370 ci->ci_tick_ih = ih; 371 372 /* set the next interrupt time */ 373 ci->ci_tick_increment = ci->ci_cpu_clockrate[0] / hz; 374 375 s = intr_disable(); 376 next_tick(ci->ci_tick_increment); 377 intr_restore(s); 378 } 379 380 void 381 stickintr_establish(int pil, int (*fun)(void *)) 382 { 383 int s; 384 struct intrhand *ih; 385 struct cpu_info *ci = curcpu(); 386 387 ih = sparc_softintr_establish(pil, fun, NULL); 388 ih->ih_number = 1; 389 if (CPU_IS_PRIMARY(ci)) 390 intr_establish(pil, true, ih); 391 ci->ci_tick_ih = ih; 392 393 /* set the next interrupt time */ 394 ci->ci_tick_increment = ci->ci_system_clockrate[0] / hz; 395 396 s = intr_disable(); 397 next_stick_init(); 398 next_stick(ci->ci_tick_increment); 399 intr_restore(s); 400 } 401 402 #if NPSYCHO > 0 403 void 404 stick2eintr_establish(int pil, int (*fun)(void *)) 405 { 406 int s; 407 struct intrhand *ih; 408 struct cpu_info *ci = curcpu(); 409 410 ih = sparc_softintr_establish(pil, fun, NULL); 411 ih->ih_number = 1; 412 if (CPU_IS_PRIMARY(ci)) 413 intr_establish(pil, true, ih); 414 ci->ci_tick_ih = ih; 415 416 /* set the next interrupt time */ 417 ci->ci_tick_increment = ci->ci_system_clockrate[0] / hz; 418 419 s = intr_disable(); 420 psycho_nextstick(ci->ci_tick_increment); 421 intr_restore(s); 422 } 423 #endif 424 425 /* 426 * Set up the real-time and statistics clocks. Leave stathz 0 only if 427 * no alternative timer is available. 428 * 429 * The frequencies of these clocks must be an even number of microseconds. 430 */ 431 void 432 cpu_initclocks(void) 433 { 434 struct cpu_info *ci = curcpu(); 435 #ifndef MULTIPROCESSOR 436 int statint, minint; 437 #endif 438 #ifdef DEBUG 439 extern int intrdebug; 440 #endif 441 442 #ifdef DEBUG 443 /* Set a 1s clock */ 444 if (intrdebug) { 445 hz = 1; 446 tick = 1000000 / hz; 447 printf("intrdebug set: 1Hz clock\n"); 448 } 449 #endif 450 451 if (1000000 % hz) { 452 printf("cannot get %d Hz clock; using 100 Hz\n", hz); 453 hz = 100; 454 tick = 1000000 / hz; 455 } 456 457 /* Make sure we have a sane cpu_clockrate -- we'll need it */ 458 if (!ci->ci_cpu_clockrate[0]) { 459 /* Default to 200MHz clock XXXXX */ 460 ci->ci_cpu_clockrate[0] = 200000000; 461 ci->ci_cpu_clockrate[1] = 200000000 / 1000000; 462 } 463 464 /* Initialize the %tick register */ 465 if (CPU_ISSUN4U || CPU_ISSUN4US) 466 settick(0); 467 468 /* Register timecounter "tick-counter" */ 469 tick_timecounter.tc_frequency = ci->ci_cpu_clockrate[0]; 470 tc_init(&tick_timecounter); 471 472 /* Register timecounter "stick-counter" */ 473 if (ci->ci_system_clockrate[0] != 0) { 474 if (CPU_ISSUN4U && CPU_IS_HUMMINGBIRD()) { 475 #if NPSYCHO > 0 476 psycho_setstick(0); 477 stick2e_timecounter.tc_frequency = 478 ci->ci_system_clockrate[0]; 479 tc_init(&stick2e_timecounter); 480 #endif 481 } else { 482 if (CPU_ISSUN4U || CPU_ISSUN4US) 483 setstick(0); 484 stick_timecounter.tc_frequency = 485 ci->ci_system_clockrate[0]; 486 tc_init(&stick_timecounter); 487 } 488 } 489 490 /* 491 * Now handle machines w/o counter-timers. 492 * XXX 493 * If the CPU is an US-IIe and we don't have a psycho we need to fall 494 * back to %tick. Not that a kernel like that would get very far on any 495 * supported hardware ( without PCI... ) - I'm not sure if such hardware 496 * even exists. 497 */ 498 499 if (!timerreg_4u.t_timer || !timerreg_4u.t_clrintr) { 500 501 if (ci->ci_system_clockrate[0] == 0) { 502 aprint_normal("No counter-timer -- using %%tick " 503 "at %sMHz as system clock.\n", 504 clockfreq(ci->ci_cpu_clockrate[0])); 505 506 /* We don't have a counter-timer -- use %tick */ 507 tickintr_establish(PIL_CLOCK, tickintr); 508 } else if (CPU_ISSUN4U && CPU_IS_HUMMINGBIRD()) { 509 #if NPSYCHO > 0 510 aprint_normal("No counter-timer -- using STICK " 511 "at %sMHz as system clock.\n", 512 clockfreq(ci->ci_system_clockrate[0])); 513 514 /* We don't have a counter-timer -- use STICK */ 515 stick2eintr_establish(PIL_CLOCK, stick2eintr); 516 #else 517 panic("trying to use STICK without psycho?!"); 518 #endif 519 } else { 520 aprint_normal("No counter-timer -- using %%stick " 521 "at %sMHz as system clock.\n", 522 clockfreq(ci->ci_system_clockrate[0])); 523 524 /* We don't have a counter-timer -- use %stick */ 525 stickintr_establish(PIL_CLOCK, stickintr); 526 } 527 /* We only have one timer so we have no statclock */ 528 stathz = 0; 529 530 return; 531 } 532 533 #ifndef MULTIPROCESSOR 534 if (stathz == 0) 535 stathz = hz; 536 if (1000000 % stathz) { 537 printf("cannot get %d Hz statclock; using 100 Hz\n", stathz); 538 stathz = 100; 539 } 540 541 profhz = stathz; /* always */ 542 543 statint = 1000000 / stathz; 544 minint = statint / 2 + 100; 545 while (statvar > minint) 546 statvar >>= 1; 547 548 /* 549 * Establish scheduler softint. 550 */ 551 schedint = sparc_softintr_establish(PIL_SCHED, schedintr, NULL); 552 if (stathz > 60) 553 schedhz = 16; /* 16Hz is best according to kern/kern_clock.c */ 554 else 555 schedhz = stathz / 2 + 1; 556 statscheddiv = stathz / schedhz; 557 if (statscheddiv <= 0) 558 panic("statscheddiv"); 559 #endif 560 561 /* 562 * Enable counter-timer #0 interrupt for clockintr. 563 */ 564 stxa((vaddr_t)&timerreg_4u.t_timer[0].t_limit, ASI_NUCLEUS, 565 tmr_ustolim(tick)|TMR_LIM_IEN|TMR_LIM_PERIODIC|TMR_LIM_RELOAD); 566 stxa((vaddr_t)&timerreg_4u.t_mapintr[0], ASI_NUCLEUS, 567 timerreg_4u.t_mapintr[0]|INTMAP_V); 568 569 #ifdef MULTIPROCESSOR 570 /* 571 * Use counter-timer #1 as timecounter. 572 */ 573 stxa((vaddr_t)&timerreg_4u.t_timer[1].t_limit, ASI_NUCLEUS, 574 TMR_LIM_MASK); 575 tc_init(&counter_timecounter); 576 #else 577 /* 578 * Enable counter-timer #1 interrupt for statintr. 579 */ 580 #ifdef DEBUG 581 if (intrdebug) 582 /* Neglect to enable timer */ 583 stxa((vaddr_t)&timerreg_4u.t_timer[1].t_limit, ASI_NUCLEUS, 584 tmr_ustolim(statint)|TMR_LIM_RELOAD); 585 else 586 #endif 587 stxa((vaddr_t)&timerreg_4u.t_timer[1].t_limit, ASI_NUCLEUS, 588 tmr_ustolim(statint)|TMR_LIM_IEN|TMR_LIM_RELOAD); 589 stxa((vaddr_t)&timerreg_4u.t_mapintr[1], ASI_NUCLEUS, 590 timerreg_4u.t_mapintr[1]|INTMAP_V|(CPU_UPAID << INTMAP_TID_SHIFT)); 591 592 statmin = statint - (statvar >> 1); 593 #endif 594 } 595 596 /* 597 * Dummy setstatclockrate(), since we know profhz==hz. 598 */ 599 /* ARGSUSED */ 600 void 601 setstatclockrate(int newhz) 602 { 603 /* nothing */ 604 } 605 606 /* 607 * Level 10 (clock) interrupts. If we are using the FORTH PROM for 608 * console input, we need to check for that here as well, and generate 609 * a software interrupt to read it. 610 */ 611 #ifdef DEBUG 612 static int clockcheck = 0; 613 #endif 614 int 615 clockintr(void *cap) 616 { 617 #ifdef DEBUG 618 static int64_t tick_base = 0; 619 struct timeval ctime; 620 int64_t t = gettick(); 621 622 microtime(&ctime); 623 if (!tick_base) { 624 tick_base = (ctime.tv_sec * 1000000LL + ctime.tv_usec) 625 / curcpu()->ci_cpu_clockrate[1]; 626 tick_base -= t; 627 } else if (clockcheck) { 628 int64_t tk = t; 629 int64_t clk = (ctime.tv_sec * 1000000LL + ctime.tv_usec); 630 t -= tick_base; 631 t = t / curcpu()->ci_cpu_clockrate[1]; 632 if (t - clk > hz) { 633 printf("Clock lost an interrupt!\n"); 634 printf("Actual: %llx Expected: %llx tick %llx tick_base %llx\n", 635 (long long)t, (long long)clk, (long long)tk, (long long)tick_base); 636 tick_base = 0; 637 } 638 } 639 #endif 640 /* Let locore.s clear the interrupt for us. */ 641 hardclock((struct clockframe *)cap); 642 return (1); 643 } 644 645 /* 646 * Level 10 (clock) interrupts. If we are using the FORTH PROM for 647 * console input, we need to check for that here as well, and generate 648 * a software interrupt to read it. 649 * 650 * %tick is really a level-14 interrupt. We need to remap this in 651 * locore.s to a level 10. 652 */ 653 int 654 tickintr(void *cap) 655 { 656 int s; 657 658 hardclock((struct clockframe *)cap); 659 660 s = intr_disable(); 661 /* Reset the interrupt */ 662 next_tick(curcpu()->ci_tick_increment); 663 intr_restore(s); 664 curcpu()->ci_tick_evcnt.ev_count++; 665 666 return (1); 667 } 668 669 int 670 stickintr(void *cap) 671 { 672 int s; 673 674 hardclock((struct clockframe *)cap); 675 676 s = intr_disable(); 677 /* Reset the interrupt */ 678 next_stick(curcpu()->ci_tick_increment); 679 intr_restore(s); 680 curcpu()->ci_tick_evcnt.ev_count++; 681 682 return (1); 683 } 684 685 #if NPSYCHO > 0 686 int 687 stick2eintr(void *cap) 688 { 689 int s; 690 691 hardclock((struct clockframe *)cap); 692 693 s = intr_disable(); 694 /* Reset the interrupt */ 695 psycho_nextstick(curcpu()->ci_tick_increment); 696 intr_restore(s); 697 curcpu()->ci_tick_evcnt.ev_count++; 698 699 return (1); 700 } 701 #endif 702 703 #ifndef MULTIPROCESSOR 704 /* 705 * Level 14 (stat clock) interrupt handler. 706 */ 707 int 708 statintr(void *cap) 709 { 710 register u_long newint, r, var; 711 struct cpu_info *ci = curcpu(); 712 713 #ifdef NOT_DEBUG 714 printf("statclock: count %x:%x, limit %x:%x\n", 715 timerreg_4u.t_timer[0].t_count, timerreg_4u.t_timer[1].t_count, 716 timerreg_4u.t_timer[0].t_limit, timerreg_4u.t_timer[1].t_limit); 717 #endif 718 #ifdef NOT_DEBUG 719 prom_printf("!"); 720 #endif 721 statclock((struct clockframe *)cap); 722 #ifdef NOTDEF_DEBUG 723 /* Don't re-schedule the IRQ */ 724 return 1; 725 #endif 726 /* 727 * Compute new randomized interval. The intervals are uniformly 728 * distributed on [statint - statvar / 2, statint + statvar / 2], 729 * and therefore have mean statint, giving a stathz frequency clock. 730 */ 731 var = statvar; 732 do { 733 r = random() & (var - 1); 734 } while (r == 0); 735 newint = statmin + r; 736 737 if (schedhz) 738 if ((int)(--ci->ci_schedstate.spc_schedticks) <= 0) { 739 send_softint(-1, PIL_SCHED, schedint); 740 ci->ci_schedstate.spc_schedticks = statscheddiv; 741 } 742 stxa((vaddr_t)&timerreg_4u.t_timer[1].t_limit, ASI_NUCLEUS, 743 tmr_ustolim(newint)|TMR_LIM_IEN|TMR_LIM_RELOAD); 744 return (1); 745 } 746 747 int 748 schedintr(void *arg) 749 { 750 751 schedclock(curcpu()->ci_onproc); 752 return (1); 753 } 754 #endif 755