xref: /openbsd/sys/arch/sparc64/sparc64/clock.c (revision 4b28d16f)
1 /*	$OpenBSD: clock.c,v 1.74 2022/12/29 22:44:23 cheloha Exp $	*/
2 /*	$NetBSD: clock.c,v 1.41 2001/07/24 19:29:25 eeh Exp $ */
3 
4 /*
5  * Copyright (c) 1992, 1993
6  *	The Regents of the University of California.  All rights reserved.
7  * Copyright (c) 1994 Gordon W. Ross
8  * Copyright (c) 1993 Adam Glass
9  * Copyright (c) 1996 Paul Kranenburg
10  * Copyright (c) 1996
11  * 	The President and Fellows of Harvard College. All rights reserved.
12  *
13  * This software was developed by the Computer Systems Engineering group
14  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
15  * contributed to Berkeley.
16  *
17  * All advertising materials mentioning features or use of this software
18  * must display the following acknowledgement:
19  *	This product includes software developed by Harvard University.
20  *	This product includes software developed by the University of
21  *	California, Lawrence Berkeley Laboratory.
22  *
23  * Redistribution and use in source and binary forms, with or without
24  * modification, are permitted provided that the following conditions
25  * are met:
26  *
27  * 1. Redistributions of source code must retain the above copyright
28  *    notice, this list of conditions and the following disclaimer.
29  * 2. Redistributions in binary form must reproduce the above copyright
30  *    notice, this list of conditions and the following disclaimer in the
31  *    documentation and/or other materials provided with the distribution.
32  * 3. All advertising materials mentioning features or use of this software
33  *    must display the following acknowledgement:
34  *	This product includes software developed by the University of
35  *	California, Berkeley and its contributors.
36  *	This product includes software developed by Paul Kranenburg.
37  *	This product includes software developed by Harvard University.
38  * 4. Neither the name of the University nor the names of its contributors
39  *    may be used to endorse or promote products derived from this software
40  *    without specific prior written permission.
41  *
42  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
43  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
44  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
45  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
46  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
47  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
48  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
49  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
50  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
51  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
52  * SUCH DAMAGE.
53  *
54  *	@(#)clock.c	8.1 (Berkeley) 6/11/93
55  *
56  */
57 
58 /*
59  * Clock driver.  This is the id prom and eeprom driver as well
60  * and includes the timer register functions too.
61  */
62 
63 /* Define this for a 1/4s clock to ease debugging */
64 /* #define INTR_DEBUG */
65 
66 #include <sys/param.h>
67 #include <sys/kernel.h>
68 #include <sys/device.h>
69 #include <sys/proc.h>
70 #include <sys/resourcevar.h>
71 #include <sys/malloc.h>
72 #include <sys/systm.h>
73 #ifdef GPROF
74 #include <sys/gmon.h>
75 #endif
76 #include <sys/sched.h>
77 #include <sys/timetc.h>
78 #include <sys/atomic.h>
79 
80 #include <machine/bus.h>
81 #include <machine/autoconf.h>
82 #include <machine/cpu.h>
83 #include <machine/idprom.h>
84 
85 #include <dev/clock_subr.h>
86 #include <dev/ic/mk48txxreg.h>
87 
88 #include <sparc64/sparc64/intreg.h>
89 #include <sparc64/sparc64/timerreg.h>
90 #include <sparc64/dev/iommureg.h>
91 #include <sparc64/dev/sbusreg.h>
92 #include <dev/sbus/sbusvar.h>
93 #include <sparc64/dev/ebusreg.h>
94 #include <sparc64/dev/ebusvar.h>
95 #include <sparc64/dev/fhcvar.h>
96 
97 extern u_int64_t cpu_clockrate;
98 
99 struct clock_wenable_info {
100 	bus_space_tag_t		cwi_bt;
101 	bus_space_handle_t	cwi_bh;
102 	bus_size_t		cwi_size;
103 };
104 
105 struct cfdriver clock_cd = {
106 	NULL, "clock", DV_DULL
107 };
108 
109 u_int tick_get_timecount(struct timecounter *);
110 
111 struct timecounter tick_timecounter = {
112 	.tc_get_timecount = tick_get_timecount,
113 	.tc_poll_pps = NULL,
114 	.tc_counter_mask = ~0u,
115 	.tc_frequency = 0,
116 	.tc_name = "tick",
117 	.tc_quality = 0,
118 	.tc_priv = NULL,
119 	.tc_user = TC_TICK,
120 };
121 
122 u_int sys_tick_get_timecount(struct timecounter *);
123 
124 struct timecounter sys_tick_timecounter = {
125 	.tc_get_timecount = sys_tick_get_timecount,
126 	.tc_poll_pps = NULL,
127 	.tc_counter_mask = ~0u,
128 	.tc_frequency = 0,
129 	.tc_name = "sys_tick",
130 	.tc_quality = 1000,
131 	.tc_priv = NULL,
132 	.tc_user = TC_SYS_TICK,
133 };
134 
135 /*
136  * Statistics clock interval and variance, in usec.  Variance must be a
137  * power of two.  Since this gives us an even number, not an odd number,
138  * we discard one case and compensate.  That is, a variance of 1024 would
139  * give us offsets in [0..1023].  Instead, we take offsets in [1..1023].
140  * This is symmetric about the point 512, or statvar/2, and thus averages
141  * to that value (assuming uniform random numbers).
142  */
143 /* XXX fix comment to match value */
144 int statvar = 8192;
145 int statmin;			/* statclock interval - 1/2*variance */
146 
147 static long tick_increment;
148 
149 void	tick_start(void);
150 void	sys_tick_start(void);
151 void	stick_start(void);
152 
153 void	tick_rearm(uint64_t);
154 void	sys_tick_rearm(uint64_t);
155 void	stick_rearm(uint64_t);
156 
157 int	tickintr(void *);
158 int	sys_tickintr(void *);
159 int	stickintr(void *);
160 int	schedintr(void *);
161 
162 static struct intrhand level10 = { clockintr };
163 static struct intrhand level0 = { tickintr };
164 static struct intrhand level14 = { statintr };
165 static struct intrhand schedint = { schedintr };
166 
167 /*
168  * clock (eeprom) attaches at the sbus or the ebus (PCI)
169  */
170 static int	clockmatch_sbus(struct device *, void *, void *);
171 static void	clockattach_sbus(struct device *, struct device *, void *);
172 static int	clockmatch_ebus(struct device *, void *, void *);
173 static void	clockattach_ebus(struct device *, struct device *, void *);
174 static int	clockmatch_fhc(struct device *, void *, void *);
175 static void	clockattach_fhc(struct device *, struct device *, void *);
176 static void	clockattach(int, bus_space_tag_t, bus_space_handle_t);
177 
178 const struct cfattach clock_sbus_ca = {
179 	sizeof(struct device), clockmatch_sbus, clockattach_sbus
180 };
181 
182 const struct cfattach clock_ebus_ca = {
183 	sizeof(struct device), clockmatch_ebus, clockattach_ebus
184 };
185 
186 const struct cfattach clock_fhc_ca = {
187 	sizeof(struct device), clockmatch_fhc, clockattach_fhc
188 };
189 
190 /* Global TOD clock handle & idprom pointer */
191 extern todr_chip_handle_t todr_handle;
192 static struct idprom *idprom;
193 
194 static int	timermatch(struct device *, void *, void *);
195 static void	timerattach(struct device *, struct device *, void *);
196 
197 struct timerreg_4u	timerreg_4u;	/* XXX - need more cleanup */
198 
199 const struct cfattach timer_ca = {
200 	sizeof(struct device), timermatch, timerattach
201 };
202 
203 struct cfdriver timer_cd = {
204 	NULL, "timer", DV_DULL
205 };
206 
207 int clock_bus_wenable(struct todr_chip_handle *, int);
208 struct chiptime;
209 void myetheraddr(u_char *);
210 struct idprom *getidprom(void);
211 int chiptotime(int, int, int, int, int, int);
212 void timetochip(struct chiptime *);
213 void stopcounter(struct timer_4u *);
214 
215 int timerblurb = 10; /* Guess a value; used before clock is attached */
216 
217 /*
218  * The OPENPROM calls the clock the "eeprom", so we have to have our
219  * own special match function to call it the "clock".
220  */
221 static int
222 clockmatch_sbus(struct device *parent, void *cf, void *aux)
223 {
224 	struct sbus_attach_args *sa = aux;
225 
226 	return (strcmp("eeprom", sa->sa_name) == 0);
227 }
228 
229 static int
230 clockmatch_ebus(struct device *parent, void *cf, void *aux)
231 {
232 	struct ebus_attach_args *ea = aux;
233 
234 	return (strcmp("eeprom", ea->ea_name) == 0);
235 }
236 
237 static int
238 clockmatch_fhc(struct device *parent, void *cf, void *aux)
239 {
240 	struct fhc_attach_args *fa = aux;
241 
242 	return (strcmp("eeprom", fa->fa_name) == 0);
243 }
244 
245 /*
246  * Attach a clock (really `eeprom') to the sbus or ebus.
247  *
248  * We ignore any existing virtual address as we need to map
249  * this read-only and make it read-write only temporarily,
250  * whenever we read or write the clock chip.  The clock also
251  * contains the ID ``PROM'', and I have already had the pleasure
252  * of reloading the cpu type, Ethernet address, etc, by hand from
253  * the console FORTH interpreter.  I intend not to enjoy it again.
254  *
255  * the MK48T02 is 2K.  the MK48T08 is 8K, and the MK48T59 is
256  * supposed to be identical to it.
257  *
258  * This is *UGLY*!  We probably have multiple mappings.  But I do
259  * know that this all fits inside an 8K page, so I'll just map in
260  * once.
261  *
262  * What we really need is some way to record the bus attach args
263  * so we can call *_bus_map() later with BUS_SPACE_MAP_READONLY
264  * or not to write enable/disable the device registers.  This is
265  * a non-trivial operation.
266  */
267 
268 static void
269 clockattach_sbus(struct device *parent, struct device *self, void *aux)
270 {
271 	struct sbus_attach_args *sa = aux;
272 	bus_space_tag_t bt = sa->sa_bustag;
273 	int sz;
274 	static struct clock_wenable_info cwi;
275 
276 	/* use sa->sa_regs[0].size? */
277 	sz = 8192;
278 
279 	if (sbus_bus_map(bt,
280 			 sa->sa_slot,
281 			 (sa->sa_offset & ~NBPG),
282 			 sz,
283 			 BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_READONLY,
284 			 0, &cwi.cwi_bh) != 0) {
285 		printf("%s: can't map register\n", self->dv_xname);
286 		return;
287 	}
288 	clockattach(sa->sa_node, bt, cwi.cwi_bh);
289 
290 	/* Save info for the clock wenable call. */
291 	cwi.cwi_bt = bt;
292 	cwi.cwi_size = sz;
293 	todr_handle->bus_cookie = &cwi;
294 	todr_handle->todr_setwen = clock_bus_wenable;
295 }
296 
297 /*
298  * Write en/dis-able clock registers.  We coordinate so that several
299  * writers can run simultaneously.
300  * XXX There is still a race here.  The page change and the "writers"
301  * change are not atomic.
302  */
303 int
304 clock_bus_wenable(struct todr_chip_handle *handle, int onoff)
305 {
306 	int s, err = 0;
307 	int prot; /* nonzero => change prot */
308 	volatile static int writers;
309 	struct clock_wenable_info *cwi = handle->bus_cookie;
310 
311 	s = splhigh();
312 	if (onoff)
313 		prot = writers++ == 0 ? 1 : 0;
314 	else
315 		prot = --writers == 0 ? 1 : 0;
316 	splx(s);
317 
318 	if (prot) {
319 		err = bus_space_protect(cwi->cwi_bt, cwi->cwi_bh, cwi->cwi_size,
320 		    onoff ? 0 : BUS_SPACE_MAP_READONLY);
321 		if (err)
322 			printf("clock_wenable_info: WARNING -- cannot %s "
323 			    "page protection\n", onoff ? "disable" : "enable");
324 	}
325 	return (err);
326 }
327 
328 static void
329 clockattach_ebus(struct device *parent, struct device *self, void *aux)
330 {
331 	struct ebus_attach_args *ea = aux;
332 	bus_space_tag_t bt;
333 	int sz;
334 	static struct clock_wenable_info cwi;
335 
336 	/* hard code to 8K? */
337 	sz = ea->ea_regs[0].size;
338 
339 	if (ea->ea_nvaddrs) {
340 		if (bus_space_map(ea->ea_memtag, ea->ea_vaddrs[0], 0,
341 		    BUS_SPACE_MAP_PROMADDRESS, &cwi.cwi_bh) != 0) {
342 			printf("%s: can't map register\n", self->dv_xname);
343 			return;
344 		}
345 		bt = ea->ea_memtag;
346 	} else if (ebus_bus_map(ea->ea_iotag, 0,
347 	    EBUS_PADDR_FROM_REG(&ea->ea_regs[0]), sz, 0, 0, &cwi.cwi_bh) == 0) {
348 		bt = ea->ea_iotag;
349 	} else if (ebus_bus_map(ea->ea_memtag, 0,
350 	    EBUS_PADDR_FROM_REG(&ea->ea_regs[0]), sz,
351 	    BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_READONLY,
352 	    0, &cwi.cwi_bh) == 0) {
353 		bt = ea->ea_memtag;
354 	} else {
355 		printf("%s: can't map register\n", self->dv_xname);
356 		return;
357 	}
358 
359 	clockattach(ea->ea_node, bt, cwi.cwi_bh);
360 
361 	/* Save info for the clock wenable call. */
362 	cwi.cwi_bt = bt;
363 	cwi.cwi_size = sz;
364 	todr_handle->bus_cookie = &cwi;
365 	todr_handle->todr_setwen = (ea->ea_memtag == bt) ?
366 	    clock_bus_wenable : NULL;
367 }
368 
369 static void
370 clockattach_fhc(struct device *parent, struct device *self, void *aux)
371 {
372 	struct fhc_attach_args *fa = aux;
373 	bus_space_tag_t bt = fa->fa_bustag;
374 	int sz;
375 	static struct clock_wenable_info cwi;
376 
377 	/* use sa->sa_regs[0].size? */
378 	sz = 8192;
379 
380 	if (fhc_bus_map(bt, fa->fa_reg[0].fbr_slot,
381 	    (fa->fa_reg[0].fbr_offset & ~NBPG), fa->fa_reg[0].fbr_size,
382 	    BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_READONLY, &cwi.cwi_bh) != 0) {
383 		printf("%s: can't map register\n", self->dv_xname);
384 		return;
385 	}
386 
387 	clockattach(fa->fa_node, bt, cwi.cwi_bh);
388 
389 	/* Save info for the clock wenable call. */
390 	cwi.cwi_bt = bt;
391 	cwi.cwi_size = sz;
392 	todr_handle->bus_cookie = &cwi;
393 	todr_handle->todr_setwen = clock_bus_wenable;
394 }
395 
396 static void
397 clockattach(int node, bus_space_tag_t bt, bus_space_handle_t bh)
398 {
399 	char *model;
400 	struct idprom *idp;
401 	int h;
402 
403 	model = getpropstring(node, "model");
404 
405 #ifdef DIAGNOSTIC
406 	if (model == NULL)
407 		panic("clockattach: no model property");
408 #endif
409 
410 	/* Our TOD clock year 0 is 1968 */
411 	if ((todr_handle = mk48txx_attach(bt, bh, model, 1968)) == NULL)
412 		panic("Can't attach %s tod clock", model);
413 
414 #define IDPROM_OFFSET (8*1024 - 40)	/* XXX - get nvram sz from driver */
415 	if (idprom == NULL) {
416 		idp = getidprom();
417 		if (idp == NULL)
418 			idp = (struct idprom *)(bus_space_vaddr(bt, bh) +
419 			    IDPROM_OFFSET);
420 		idprom = idp;
421 	} else
422 		idp = idprom;
423 	h = idp->id_machine << 24;
424 	h |= idp->id_hostid[0] << 16;
425 	h |= idp->id_hostid[1] << 8;
426 	h |= idp->id_hostid[2];
427 	hostid = h;
428 	printf("\n");
429 }
430 
431 struct idprom *
432 getidprom(void)
433 {
434 	struct idprom *idp = NULL;
435 	int node, n;
436 
437 	node = findroot();
438 	if (getprop(node, "idprom", sizeof(*idp), &n, (void **)&idp) != 0)
439 		return (NULL);
440 	if (n != 1) {
441 		free(idp, M_DEVBUF, 0);
442 		return (NULL);
443 	}
444 	return (idp);
445 }
446 
447 /*
448  * The sun4u OPENPROMs call the timer the "counter-timer", except for
449  * the lame UltraSPARC IIi PCI machines that don't have them.
450  */
451 static int
452 timermatch(struct device *parent, void *cf, void *aux)
453 {
454 #ifndef MULTIPROCESSOR
455 	struct mainbus_attach_args *ma = aux;
456 
457 	if (!timerreg_4u.t_timer || !timerreg_4u.t_clrintr)
458 		return (strcmp("counter-timer", ma->ma_name) == 0);
459 	else
460 #endif
461 		return (0);
462 }
463 
464 static void
465 timerattach(struct device *parent, struct device *self, void *aux)
466 {
467 	struct mainbus_attach_args *ma = aux;
468 	u_int *va = ma->ma_address;
469 
470 	/*
471 	 * What we should have are 3 sets of registers that reside on
472 	 * different parts of SYSIO or PSYCHO.  We'll use the prom
473 	 * mappings cause we can't get rid of them and set up appropriate
474 	 * pointers on the timerreg_4u structure.
475 	 */
476 	timerreg_4u.t_timer = (struct timer_4u *)(u_long)va[0];
477 	timerreg_4u.t_clrintr = (int64_t *)(u_long)va[1];
478 	timerreg_4u.t_mapintr = (int64_t *)(u_long)va[2];
479 
480 	/* Install the appropriate interrupt vector here */
481 	level10.ih_number = INTVEC(ma->ma_interrupts[0]);
482 	level10.ih_clr = (void *)&timerreg_4u.t_clrintr[0];
483 	level10.ih_map = (void *)&timerreg_4u.t_mapintr[0];
484 	strlcpy(level10.ih_name, "clock", sizeof(level10.ih_name));
485 	intr_establish(10, &level10);
486 
487 	level14.ih_number = INTVEC(ma->ma_interrupts[1]);
488 	level14.ih_clr = (void *)&timerreg_4u.t_clrintr[1];
489 	level14.ih_map = (void *)&timerreg_4u.t_mapintr[1];
490 	strlcpy(level14.ih_name, "prof", sizeof(level14.ih_name));
491 	intr_establish(14, &level14);
492 
493 	printf(" ivec 0x%llx, 0x%llx\n", INTVEC(level10.ih_number),
494 	    INTVEC(level14.ih_number));
495 }
496 
497 void
498 stopcounter(struct timer_4u *creg)
499 {
500 	/* Stop the clock */
501 	volatile int discard;
502 	discard = creg->t_limit;
503 	creg->t_limit = 0;
504 }
505 
506 /*
507  * XXX this belongs elsewhere
508  */
509 void
510 myetheraddr(u_char *cp)
511 {
512 	struct idprom *idp;
513 
514 	if ((idp = idprom) == NULL) {
515 		int node, n;
516 
517 		node = findroot();
518 		if (getprop(node, "idprom", sizeof *idp, &n, (void **)&idp) ||
519 		    n != 1) {
520 			printf("\nmyetheraddr: clock not setup yet, "
521 			       "and no idprom property in /\n");
522 			return;
523 		}
524 	}
525 
526 	cp[0] = idp->id_ether[0];
527 	cp[1] = idp->id_ether[1];
528 	cp[2] = idp->id_ether[2];
529 	cp[3] = idp->id_ether[3];
530 	cp[4] = idp->id_ether[4];
531 	cp[5] = idp->id_ether[5];
532 	if (idprom == NULL)
533 		free(idp, M_DEVBUF, 0);
534 }
535 
536 /*
537  * Set up the real-time and statistics clocks.  Leave stathz 0 only if
538  * no alternative timer is available.
539  *
540  * The frequencies of these clocks must be an even number of microseconds.
541  */
542 void
543 cpu_initclocks(void)
544 {
545 	int statint, minint;
546 #ifdef DEBUG
547 	extern int intrdebug;
548 #endif
549 	u_int sys_tick_rate;
550 	int impl = 0;
551 
552 #ifdef DEBUG
553 	/* Set a 1s clock */
554 	if (intrdebug) {
555 		hz = 1;
556 		tick = 1000000 / hz;
557 		tick_nsec = 1000000000 / hz;
558 		printf("intrdebug set: 1Hz clock\n");
559 	}
560 #endif
561 
562 	if (1000000 % hz) {
563 		printf("cannot get %d Hz clock; using 100 Hz\n", hz);
564 		hz = 100;
565 		tick = 1000000 / hz;
566 		tick_nsec = 1000000000 / hz;
567 	}
568 
569 	/* Make sure we have a sane cpu_clockrate -- we'll need it */
570 	if (!cpu_clockrate)
571 		/* Default to 200MHz clock XXXXX */
572 		cpu_clockrate = 200000000;
573 
574 	tick_timecounter.tc_frequency = cpu_clockrate;
575 	tc_init(&tick_timecounter);
576 
577 	/*
578 	 * UltraSPARC IIe processors do have a STICK register, but it
579 	 * lives on the PCI host bridge and isn't accessible through
580 	 * ASR24.
581 	 */
582 	if (CPU_ISSUN4U || CPU_ISSUN4US)
583 		impl = (getver() & VER_IMPL) >> VER_IMPL_SHIFT;
584 
585 	sys_tick_rate = getpropint(findroot(), "stick-frequency", 0);
586 	if (sys_tick_rate > 0 && impl != IMPL_HUMMINGBIRD) {
587 		sys_tick_timecounter.tc_frequency = sys_tick_rate;
588 		tc_init(&sys_tick_timecounter);
589 	}
590 
591 	/*
592 	 * Now handle machines w/o counter-timers.
593 	 */
594 
595 	if (!timerreg_4u.t_timer || !timerreg_4u.t_clrintr) {
596 		struct cpu_info *ci;
597 
598 		/* We don't have a counter-timer -- use %tick */
599 		level0.ih_clr = 0;
600 
601 		/*
602 		 * Establish a level 10 interrupt handler
603 		 *
604 		 * We will have a conflict with the softint handler,
605 		 * so we set the ih_number to 1.
606 		 */
607 		level0.ih_number = 1;
608 		strlcpy(level0.ih_name, "clock", sizeof(level0.ih_name));
609 		intr_establish(10, &level0);
610 		evcount_percpu(&level0.ih_count);
611 
612 		/* We only have one timer so we have no statclock */
613 		stathz = 0;
614 
615 		if (sys_tick_rate > 0) {
616 			tick_increment = sys_tick_rate / hz;
617 			if (impl == IMPL_HUMMINGBIRD) {
618 				level0.ih_fun = stickintr;
619 				cpu_start_clock = stick_start;
620 			} else {
621 				level0.ih_fun = sys_tickintr;
622 				cpu_start_clock = sys_tick_start;
623 			}
624 		} else {
625 			/* set the next interrupt time */
626 			tick_increment = cpu_clockrate / hz;
627 			level0.ih_fun = tickintr;
628 			cpu_start_clock = tick_start;
629 		}
630 
631 		for (ci = cpus; ci != NULL; ci = ci->ci_next)
632 			memcpy(&ci->ci_tickintr, &level0, sizeof(level0));
633 
634 		cpu_start_clock();
635 
636 		return;
637 	}
638 
639 	if (stathz == 0)
640 		stathz = hz;
641 	if (1000000 % stathz) {
642 		printf("cannot get %d Hz statclock; using 100 Hz\n", stathz);
643 		stathz = 100;
644 	}
645 
646 	profhz = stathz;		/* always */
647 
648 	statint = 1000000 / stathz;
649 	minint = statint / 2 + 100;
650 	while (statvar > minint)
651 		statvar >>= 1;
652 
653 	/*
654 	 * Establish scheduler softint.
655 	 */
656 	schedint.ih_pil = PIL_SCHED;
657 	schedint.ih_clr = NULL;
658 	schedint.ih_arg = 0;
659 	schedint.ih_pending = 0;
660 	schedhz = stathz/4;
661 
662 	/*
663 	 * Enable timers
664 	 *
665 	 * Also need to map the interrupts cause we're not a child of the sbus.
666 	 * N.B. By default timer[0] is disabled and timer[1] is enabled.
667 	 */
668 	stxa((vaddr_t)&timerreg_4u.t_timer[0].t_limit, ASI_NUCLEUS,
669 	     tmr_ustolim(tick)|TMR_LIM_IEN|TMR_LIM_PERIODIC|TMR_LIM_RELOAD);
670 	stxa((vaddr_t)&timerreg_4u.t_mapintr[0], ASI_NUCLEUS,
671 	     timerreg_4u.t_mapintr[0]|INTMAP_V);
672 
673 #ifdef DEBUG
674 	if (intrdebug)
675 		/* Neglect to enable timer */
676 		stxa((vaddr_t)&timerreg_4u.t_timer[1].t_limit, ASI_NUCLEUS,
677 		     tmr_ustolim(statint)|TMR_LIM_RELOAD);
678 	else
679 #endif
680 		stxa((vaddr_t)&timerreg_4u.t_timer[1].t_limit, ASI_NUCLEUS,
681 		     tmr_ustolim(statint)|TMR_LIM_IEN|TMR_LIM_RELOAD);
682 	stxa((vaddr_t)&timerreg_4u.t_mapintr[1], ASI_NUCLEUS,
683 	     timerreg_4u.t_mapintr[1]|INTMAP_V);
684 
685 	statmin = statint - (statvar >> 1);
686 
687 	tick_enable();
688 }
689 
690 /*
691  * Dummy setstatclockrate(), since we know profhz==hz.
692  */
693 void
694 setstatclockrate(int newhz)
695 {
696 	/* nothing */
697 }
698 
699 /*
700  * Level 10 (clock) interrupts.  If we are using the FORTH PROM for
701  * console input, we need to check for that here as well, and generate
702  * a software interrupt to read it.
703  */
704 #ifdef	DEBUG
705 static int clockcheck = 0;
706 #endif
707 int
708 clockintr(void *cap)
709 {
710 #ifdef DEBUG
711 	static int64_t tick_base = 0;
712 	struct timeval ctime;
713 	int64_t t;
714 
715 	t = tick() & TICK_TICKS;
716 
717 	microtime(&ctime);
718 	if (!tick_base) {
719 		tick_base = (ctime.tv_sec * 1000000LL + ctime.tv_usec)
720 			* 1000000LL / cpu_clockrate;
721 		tick_base -= t;
722 	} else if (clockcheck) {
723 		int64_t tk = t;
724 		int64_t clk = (ctime.tv_sec * 1000000LL + ctime.tv_usec);
725 		t -= tick_base;
726 		t = t * 1000000LL / cpu_clockrate;
727 		if (t - clk > hz) {
728 			printf("Clock lost an interrupt!\n");
729 			printf("Actual: %llx Expected: %llx tick %llx "
730 			    "tick_base %llx\n", (long long)t, (long long)clk,
731 			    (long long)tk, (long long)tick_base);
732 #ifdef DDB
733 			db_enter();
734 #endif
735 			tick_base = 0;
736 		}
737 	}
738 #endif
739 	/* Let locore.s clear the interrupt for us. */
740 	hardclock((struct clockframe *)cap);
741 
742 	return (1);
743 }
744 
745 /*
746  * Level 10 (clock) interrupts.  If we are using the FORTH PROM for
747  * console input, we need to check for that here as well, and generate
748  * a software interrupt to read it.
749  *
750  * %tick is really a level-14 interrupt.  We need to remap this in
751  * locore.s to a level 10.
752  */
753 int
754 tickintr(void *cap)
755 {
756 	struct cpu_info *ci = curcpu();
757 	u_int64_t s;
758 
759 	/*
760 	 * No need to worry about overflow; %tick is architecturally
761 	 * defined not to do that for at least 10 years.
762 	 */
763 	while (ci->ci_tick < tick()) {
764 		ci->ci_tick += tick_increment;
765 		hardclock((struct clockframe *)cap);
766 		evcount_inc(&level0.ih_count);
767 	}
768 
769 	/* Reset the interrupt. */
770 	s = intr_disable();
771 	tick_rearm(ci->ci_tick);
772 	intr_restore(s);
773 
774 	return (1);
775 }
776 
777 int
778 sys_tickintr(void *cap)
779 {
780 	struct cpu_info *ci = curcpu();
781 	u_int64_t s;
782 
783 	/*
784 	 * Do we need to worry about overflow here?
785 	 */
786 	while (ci->ci_tick < sys_tick()) {
787 		ci->ci_tick += tick_increment;
788 		hardclock((struct clockframe *)cap);
789 		evcount_inc(&level0.ih_count);
790 	}
791 
792 	/* Reset the interrupt. */
793 	s = intr_disable();
794 	sys_tick_rearm(ci->ci_tick);
795 	intr_restore(s);
796 
797 	return (1);
798 }
799 
800 int
801 stickintr(void *cap)
802 {
803 	struct cpu_info *ci = curcpu();
804 	u_int64_t s;
805 
806 	/*
807 	 * Do we need to worry about overflow here?
808 	 */
809 	while (ci->ci_tick < stick()) {
810 		ci->ci_tick += tick_increment;
811 		hardclock((struct clockframe *)cap);
812 		evcount_inc(&level0.ih_count);
813 	}
814 
815 	/* Reset the interrupt. */
816 	s = intr_disable();
817 	stick_rearm(ci->ci_tick);
818 	intr_restore(s);
819 
820 	return (1);
821 }
822 
823 /*
824  * Level 14 (stat clock) interrupt handler.
825  */
826 int
827 statintr(void *cap)
828 {
829 	u_long newint, r, var;
830 	struct cpu_info *ci = curcpu();
831 
832 #ifdef NOT_DEBUG
833 	printf("statclock: count %x:%x, limit %x:%x\n",
834 	       timerreg_4u.t_timer[1].t_count, timerreg_4u.t_timer[1].t_limit);
835 #endif
836 #ifdef NOT_DEBUG
837 	prom_printf("!");
838 #endif
839 	statclock((struct clockframe *)cap);
840 #ifdef NOTDEF_DEBUG
841 	/* Don't re-schedule the IRQ */
842 	return 1;
843 #endif
844 	/*
845 	 * Compute new randomized interval.  The intervals are uniformly
846 	 * distributed on [statint - statvar / 2, statint + statvar / 2],
847 	 * and therefore have mean statint, giving a stathz frequency clock.
848 	 */
849 	var = statvar;
850 	do {
851 		r = random() & (var - 1);
852 	} while (r == 0);
853 	newint = statmin + r;
854 
855 	if (schedhz)
856 		if ((++ci->ci_schedstate.spc_schedticks & 3) == 0)
857 			send_softint(-1, PIL_SCHED, &schedint);
858 	stxa((vaddr_t)&timerreg_4u.t_timer[1].t_limit, ASI_NUCLEUS,
859 	     tmr_ustolim(newint)|TMR_LIM_IEN|TMR_LIM_RELOAD);
860 
861 	return (1);
862 }
863 
864 int
865 schedintr(void *arg)
866 {
867 	if (curproc)
868 		schedclock(curproc);
869 	return (1);
870 }
871 
872 void
873 tick_start(void)
874 {
875 	struct cpu_info *ci = curcpu();
876 	u_int64_t s;
877 
878 	tick_enable();
879 
880 	s = intr_disable();
881 	ci->ci_tick = tick();
882 	tick_rearm(ci->ci_tick);
883 	intr_restore(s);
884 }
885 
886 void
887 tick_rearm(uint64_t cmp)
888 {
889 	uint64_t now, off = 8;
890 
891 	tickcmpr_set(cmp);
892 	now = tick();
893 	while (cmp <= now) {
894 		cmp += off;
895 		tickcmpr_set(cmp);
896 		now = tick();
897 		off *= 2;
898 	}
899 }
900 
901 void
902 sys_tick_start(void)
903 {
904 	struct cpu_info *ci = curcpu();
905 	u_int64_t s;
906 
907 	if (CPU_ISSUN4U || CPU_ISSUN4US) {
908 		tick_enable();
909 		sys_tick_enable();
910 	}
911 
912 	s = intr_disable();
913 	ci->ci_tick = sys_tick();
914 	sys_tick_rearm(ci->ci_tick);
915 	intr_restore(s);
916 }
917 
918 void
919 sys_tick_rearm(uint64_t cmp)
920 {
921 	uint64_t now, off = 8;
922 
923 	sys_tickcmpr_set(cmp);
924 	now = sys_tick();
925 	while (cmp <= now) {
926 		cmp += off;
927 		sys_tickcmpr_set(cmp);
928 		now = sys_tick();
929 		off *= 2;
930 	}
931 }
932 
933 void
934 stick_start(void)
935 {
936 	struct cpu_info *ci = curcpu();
937 	u_int64_t s;
938 
939 	tick_enable();
940 
941 	s = intr_disable();
942 	ci->ci_tick = stick();
943 	stick_rearm(ci->ci_tick);
944 	intr_restore(s);
945 }
946 
947 void
948 stick_rearm(uint64_t cmp)
949 {
950 	uint64_t now, off = 8;
951 
952 	stickcmpr_set(cmp);
953 	now = stick();
954 	while (cmp <= now) {
955 		cmp += off;
956 		stickcmpr_set(cmp);
957 		now = stick();
958 		off *= 2;
959 	}
960 }
961 
962 u_int
963 tick_get_timecount(struct timecounter *tc)
964 {
965 	u_int64_t tick;
966 
967 	__asm volatile("rd %%tick, %0" : "=r" (tick));
968 
969 	return (tick & ~0u);
970 }
971 
972 u_int
973 sys_tick_get_timecount(struct timecounter *tc)
974 {
975 	u_int64_t tick;
976 
977 	__asm volatile("rd %%sys_tick, %0" : "=r" (tick));
978 
979 	return (tick & ~0u);
980 }
981