1 /*-
2 * Copyright (c) 2001 Jake Burkholder.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 *
26 * $FreeBSD: releng/5.2/sys/sparc64/sparc64/tick.c 119291 2003-08-22 07:39:05Z imp $
27 */
28
29 #include <sys/param.h>
30 #include <sys/kernel.h>
31 #include <sys/systm.h>
32 #include <sys/bus.h>
33 #include <sys/interrupt.h>
34 #include <sys/pcpu.h>
35 #include <sys/timetc.h>
36 #ifdef SMP
37 #include <sys/ktr.h>
38 #include <sys/lock.h>
39 #include <sys/mutex.h>
40 #include <sys/proc.h>
41 #endif
42
43 #include <dev/ofw/openfirm.h>
44
45 #include <machine/clock.h>
46 #include <machine/frame.h>
47 #include <machine/intr_machdep.h>
48 #include <machine/tick.h>
49 #include <machine/ver.h>
50 #ifdef SMP
51 #include <machine/cpu.h>
52 #endif
53
54 int tick_missed; /* statistics */
55
56 #define TICK_GRACE 10000
57
58 void
59 cpu_initclocks(void)
60 {
61 stathz = hz;
62 tick_start(tick_hardclock);
63 }
64
65 static __inline void
66 tick_process(struct clockframe *cf)
67 {
68
69 if (PCPU_GET(cpuid) == 0)
70 hardclock(cf);
71 else
72 hardclock_process(cf);
73 if (profprocs != 0)
74 profclock(cf);
75 statclock(cf);
76 }
77
78 void
79 tick_hardclock(struct clockframe *cf)
80 {
81 int missed;
82 u_long next;
83 register_t i;
84
85 tick_process(cf);
86 /*
87 * Avoid stopping of hardclock in case we missed one tick period by
88 * ensuring that the the value of the next tick is at least TICK_GRACE
89 * ticks in the future.
90 * Missed ticks need to be accounted for by repeatedly calling
91 * hardclock.
92 */
93 missed = 0;
94 next = rd(asr23) + tick_increment;
95 i = intr_disable();
96 while (next < rd(tick) + TICK_GRACE) {
97 next += tick_increment;
98 missed++;
99 }
100 wr(asr23, next, 0);
101 intr_restore(i);
102 atomic_add_int(&tick_missed, missed);
103 for (; missed > 0; missed--)
104 tick_process(cf);
105 }
106
107 void
108 tick_init(u_long clock)
109 {
110 tick_freq = clock;
111 tick_MHz = clock / 1000000;
112 tick_increment = clock / hz;
113 }
114
115 void
116 tick_start(tick_func_t *func)
117 {
118 intr_setup(PIL_TICK, (ih_func_t *)func, -1, NULL, NULL);
119 wrpr(tick, 0, 0);
120 wr(asr23, tick_increment, 0);
121 }
122
123 #ifdef SMP
124 void
125 tick_start_ap(void)
126 {
127 u_long base;
128
129 /*
130 * Try to make the ticks interrupt as synchronously as possible to
131 * avoid inaccuracies for migrating processes. Leave out one tick to
132 * make sure that it is not missed.
133 */
134 base = rd(tick);
135 wr(asr23, roundup(base, tick_increment) + tick_increment, 0);
136 }
137 #endif
138
139 void
140 tick_stop(void)
141 {
142
143 if (cpu_impl >= CPU_IMPL_ULTRASPARCIII)
144 wr(asr24, 1L << 63, 0);
145 wr(asr23, 1L << 63, 0);
146 }
Cache object: a9586f9cf5a866674c225b7558adbef5
|