xref: /netbsd/sys/arch/sparc64/sparc64/clock.c (revision 04121346)
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