1 /* $NetBSD: clock.c,v 1.123 2020/05/29 12:30:41 rin 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.123 2020/05/29 12:30:41 rin 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
tick_get_timecount(struct timecounter * tc)187 tick_get_timecount(struct timecounter *tc)
188 {
189 return gettick();
190 }
191
192 static u_int
stick_get_timecount(struct timecounter * tc)193 stick_get_timecount(struct timecounter *tc)
194 {
195 return getstick();
196 }
197
198 #if NPSYCHO > 0
199 static u_int
stick2e_get_timecount(struct timecounter * tc)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
counter_get_timecount(struct timecounter * tc)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
timermatch(device_t parent,cfdata_t cf,void * aux)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
timerattach(device_t parent,device_t self,void * aux)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 calibrarion....\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
stopcounter(struct timer_4u * creg)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
tickintr_establish(int pil,int (* fun)(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
stickintr_establish(int pil,int (* fun)(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
stick2eintr_establish(int pil,int (* fun)(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
cpu_initclocks(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
setstatclockrate(int newhz)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
clockintr(void * cap)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
tickintr(void * cap)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
stickintr(void * cap)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
stick2eintr(void * cap)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
statintr(void * cap)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
schedintr(void * arg)748 schedintr(void *arg)
749 {
750
751 schedclock(curcpu()->ci_onproc);
752 return (1);
753 }
754 #endif
755