Pull up following revision(s) (requested by mrg in ticket #1519): sys/arch/sparc/sparc/timer_sun4m.c: 1.33 1.34 1.31 sys/arch/sparc/sparc/timer.c: 1.33 sys/arch/sparc/sparc/timer.c: 1.33 1.34 sys/arch/sparc/sparc/timerreg.h: 1.33 1.34 1.31 1.10 fix time goes backwards problems on sparc. there are a few things here: - there's a race between reading the limit register (which clears the interrupt and the limit bit) and increasing the latest offset. this can happen easily if an interrupt comes between the read and the call to tickle_tc() that increases the offset (i obverved this actually happening.) - in early boot, sometimes the counter can cycle twice before the tickle happens. to handle these issues, add two workarounds: - if the limit bit isn't set, but the counter value is less than the previous value, and the offset hasn't changed, use the same fixup as if the limit bit was set. this handles the first case above. - add a hard-workaround for never allowing returning a smaller value (except during 32 bit overflow): if the result is less than the last result, add fixups until it does (or until it would overflow.) the first workaround fixes general run-time issues, and the second fixes issues only seen during boot. also expand some comments in timer_sun4m.c and re-enable the sun4m sub-microsecond tmr_ustolim4m() support (but it's always called with at least 'tick' microseconds, so the end result is the same.) fix hang at 4B microseconds (1h12 or so), and simplify part of the previousdiff -r1.29 -r1.29.8.1 src/sys/arch/sparc/sparc/timer.c
(snj)
--- src/sys/arch/sparc/sparc/timer.c 2011/07/17 23:18:23 1.29
+++ src/sys/arch/sparc/sparc/timer.c 2018/03/13 16:48:05 1.29.8.1
@@ -1,328 +1,379 @@ | @@ -1,328 +1,379 @@ | |||
1 | /* $NetBSD: timer.c,v 1.29 2011/07/17 23:18:23 mrg Exp $ */ | 1 | /* $NetBSD: timer.c,v 1.29.8.1 2018/03/13 16:48:05 snj Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 1992, 1993 | 4 | * Copyright (c) 1992, 1993 | |
5 | * The Regents of the University of California. All rights reserved. | 5 | * The Regents of the University of California. All rights reserved. | |
6 | * Copyright (c) 1994 Gordon W. Ross | 6 | * Copyright (c) 1994 Gordon W. Ross | |
7 | * Copyright (c) 1993 Adam Glass | 7 | * Copyright (c) 1993 Adam Glass | |
8 | * Copyright (c) 1996 Paul Kranenburg | 8 | * Copyright (c) 1996 Paul Kranenburg | |
9 | * Copyright (c) 1996 | 9 | * Copyright (c) 1996 | |
10 | * The President and Fellows of Harvard College. All rights reserved. | 10 | * The President and Fellows of Harvard College. All rights reserved. | |
11 | * | 11 | * | |
12 | * This software was developed by the Computer Systems Engineering group | 12 | * This software was developed by the Computer Systems Engineering group | |
13 | * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and | 13 | * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and | |
14 | * contributed to Berkeley. | 14 | * contributed to Berkeley. | |
15 | * | 15 | * | |
16 | * All advertising materials mentioning features or use of this software | 16 | * All advertising materials mentioning features or use of this software | |
17 | * must display the following acknowledgement: | 17 | * must display the following acknowledgement: | |
18 | * This product includes software developed by Harvard University. | 18 | * This product includes software developed by Harvard University. | |
19 | * This product includes software developed by the University of | 19 | * This product includes software developed by the University of | |
20 | * California, Lawrence Berkeley Laboratory. | 20 | * California, Lawrence Berkeley Laboratory. | |
21 | * | 21 | * | |
22 | * Redistribution and use in source and binary forms, with or without | 22 | * Redistribution and use in source and binary forms, with or without | |
23 | * modification, are permitted provided that the following conditions | 23 | * modification, are permitted provided that the following conditions | |
24 | * are met: | 24 | * are met: | |
25 | * | 25 | * | |
26 | * 1. Redistributions of source code must retain the above copyright | 26 | * 1. Redistributions of source code must retain the above copyright | |
27 | * notice, this list of conditions and the following disclaimer. | 27 | * notice, this list of conditions and the following disclaimer. | |
28 | * 2. Redistributions in binary form must reproduce the above copyright | 28 | * 2. Redistributions in binary form must reproduce the above copyright | |
29 | * notice, this list of conditions and the following disclaimer in the | 29 | * notice, this list of conditions and the following disclaimer in the | |
30 | * documentation and/or other materials provided with the distribution. | 30 | * documentation and/or other materials provided with the distribution. | |
31 | * 3. All advertising materials mentioning features or use of this software | 31 | * 3. All advertising materials mentioning features or use of this software | |
32 | * must display the following acknowledgement: | 32 | * must display the following acknowledgement: | |
33 | * This product includes software developed by the University of | 33 | * This product includes software developed by the University of | |
34 | * California, Berkeley and its contributors. | 34 | * California, Berkeley and its contributors. | |
35 | * This product includes software developed by Paul Kranenburg. | 35 | * This product includes software developed by Paul Kranenburg. | |
36 | * This product includes software developed by Harvard University. | 36 | * This product includes software developed by Harvard University. | |
37 | * 4. Neither the name of the University nor the names of its contributors | 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 | 38 | * may be used to endorse or promote products derived from this software | |
39 | * without specific prior written permission. | 39 | * without specific prior written permission. | |
40 | * | 40 | * | |
41 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | 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 | 42 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
43 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | 43 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
44 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | 44 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
45 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 45 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
46 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | 46 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
47 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | 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 | 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 | 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 | 50 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
51 | * SUCH DAMAGE. | 51 | * SUCH DAMAGE. | |
52 | * | 52 | * | |
53 | * @(#)clock.c 8.1 (Berkeley) 6/11/93 | 53 | * @(#)clock.c 8.1 (Berkeley) 6/11/93 | |
54 | */ | 54 | */ | |
55 | 55 | |||
56 | /* | 56 | /* | |
57 | * Kernel clocks provided by "timer" device. The hardclock is provided by | 57 | * Kernel clocks provided by "timer" device. The hardclock is provided by | |
58 | * the timer register (aka system counter). The statclock is provided by | 58 | * the timer register (aka system counter). The statclock is provided by | |
59 | * per CPU counter register(s) (aka processor counter(s)). | 59 | * per CPU counter register(s) (aka processor counter(s)). | |
60 | */ | 60 | */ | |
61 | 61 | |||
62 | #include <sys/cdefs.h> | 62 | #include <sys/cdefs.h> | |
63 | __KERNEL_RCSID(0, "$NetBSD: timer.c,v 1.29 2011/07/17 23:18:23 mrg Exp $"); | 63 | __KERNEL_RCSID(0, "$NetBSD: timer.c,v 1.29.8.1 2018/03/13 16:48:05 snj Exp $"); | |
64 | 64 | |||
65 | #include <sys/param.h> | 65 | #include <sys/param.h> | |
66 | #include <sys/kernel.h> | 66 | #include <sys/kernel.h> | |
67 | #include <sys/device.h> | 67 | #include <sys/device.h> | |
68 | #include <sys/systm.h> | 68 | #include <sys/systm.h> | |
69 | #include <sys/timetc.h> | 69 | #include <sys/timetc.h> | |
70 | 70 | |||
71 | #include <machine/autoconf.h> | 71 | #include <machine/autoconf.h> | |
72 | #include <sys/bus.h> | 72 | #include <sys/bus.h> | |
73 | 73 | |||
74 | #include <sparc/sparc/timerreg.h> | 74 | #include <sparc/sparc/timerreg.h> | |
75 | #include <sparc/sparc/timervar.h> | 75 | #include <sparc/sparc/timervar.h> | |
76 | 76 | |||
77 | static struct intrhand level10; | 77 | static struct intrhand level10; | |
78 | static struct intrhand level14; | 78 | static struct intrhand level14; | |
79 | 79 | |||
80 | static u_int timer_get_timecount(struct timecounter *); | 80 | static u_int timer_get_timecount(struct timecounter *); | |
81 | 81 | |||
82 | /* | 82 | /* | |
83 | * timecounter local state | 83 | * timecounter local state | |
84 | */ | 84 | */ | |
85 | static struct counter { | 85 | static struct counter { | |
86 | volatile u_int *cntreg; /* counter register */ | 86 | __cpu_simple_lock_t lock; /* protects access to offset, reg, last* */ | |
87 | volatile u_int *cntreg; /* counter register to read */ | |||
87 | u_int limit; /* limit we count up to */ | 88 | u_int limit; /* limit we count up to */ | |
88 | u_int offset; /* accumulated offet due to wraps */ | 89 | u_int offset; /* accumulated offet due to wraps */ | |
89 | u_int shift; /* scaling for valid bits */ | 90 | u_int shift; /* scaling for valid bits */ | |
90 | u_int mask; /* valid bit mask */ | 91 | u_int mask; /* valid bit mask */ | |
91 | } cntr; | 92 | u_int lastcnt; /* the last* values are used to notice */ | |
93 | u_int lastres; /* and fix up cases where it would appear */ | |||
94 | u_int lastoffset; /* time went backwards. */ | |||
95 | } cntr __aligned(CACHE_LINE_SIZE); | |||
92 | 96 | |||
93 | /* | 97 | /* | |
94 | * define timecounter | 98 | * define timecounter | |
95 | */ | 99 | */ | |
96 | 100 | |||
97 | static struct timecounter counter_timecounter = { | 101 | static struct timecounter counter_timecounter = { | |
98 | timer_get_timecount, /* get_timecount */ | 102 | .tc_get_timecount = timer_get_timecount, | |
99 | 0, /* no poll_pps */ | 103 | .tc_poll_pps = NULL, | |
100 | ~0u, /* counter_mask */ | 104 | .tc_counter_mask = ~0u, | |
101 | 0, /* frequency - set at initialisation */ | 105 | .tc_frequency = 0, | |
102 | "timer-counter", /* name */ | 106 | .tc_name = "timer-counter", | |
103 | 100, /* quality */ | 107 | .tc_quality = 100, | |
104 | &cntr /* private reference */ | 108 | .tc_priv = &cntr, | |
105 | }; | 109 | }; | |
106 | 110 | |||
107 | /* | 111 | /* | |
108 | * timer_get_timecount provide current counter value | 112 | * timer_get_timecount provide current counter value | |
109 | */ | 113 | */ | |
114 | __attribute__((__optimize__("Os"))) | |||
110 | static u_int | 115 | static u_int | |
111 | timer_get_timecount(struct timecounter *tc) | 116 | timer_get_timecount(struct timecounter *tc) | |
112 | { | 117 | { | |
113 | struct counter *ctr = (struct counter *)tc->tc_priv; | 118 | u_int cnt, res, fixup, offset; | |
114 | ||||
115 | u_int c, res, r; | |||
116 | int s; | 119 | int s; | |
117 | 120 | |||
118 | 121 | /* | ||
122 | * We use splhigh/__cpu_simple_lock here as we don't want | |||
123 | * any mutex or lockdebug overhead. The lock protects a | |||
124 | * bunch of the members of cntr that are written here to | |||
125 | * deal with the various minor races to be observed and | |||
126 | * worked around. | |||
127 | */ | |||
119 | s = splhigh(); | 128 | s = splhigh(); | |
120 | 129 | |||
121 | res = c = *ctr->cntreg; | 130 | __cpu_simple_lock(&cntr.lock); | |
131 | res = cnt = *cntr.cntreg; | |||
122 | 132 | |||
123 | res &= ~TMR_LIMIT; | 133 | res &= ~TMR_LIMIT; | |
134 | offset = cntr.offset; | |||
124 | 135 | |||
125 | if (c != res) { | 136 | /* | |
126 | r = ctr->limit; | 137 | * There are 3 cases here: | |
138 | * - limit reached, interrupt not yet processed. | |||
139 | * - count reset but offset the same, race between handling | |||
140 | * the interrupt and tickle_tc() updating the offset. | |||
141 | * - normal case. | |||
142 | * | |||
143 | * For the first two cases, add the limit so that we avoid | |||
144 | * time going backwards. | |||
145 | */ | |||
146 | if (cnt != res) { | |||
147 | fixup = cntr.limit; | |||
148 | } else if (res < cntr.lastcnt && offset == cntr.lastoffset) { | |||
149 | fixup = cntr.limit; | |||
127 | } else { | 150 | } else { | |
128 | r = 0; | 151 | fixup = 0; | |
129 | } | 152 | } | |
153 | ||||
154 | cntr.lastcnt = res; | |||
155 | cntr.lastoffset = offset; | |||
130 | 156 | |||
131 | res >>= ctr->shift; | 157 | res >>= cntr.shift; | |
132 | res &= ctr->mask; | 158 | res &= cntr.mask; | |
133 | 159 | |||
134 | res += r + ctr->offset; | 160 | res += fixup + offset; | |
135 | 161 | |||
162 | /* | |||
163 | * This handles early-boot cases where the counter resets twice | |||
164 | * before the offset is updated, and we have a stupid check to | |||
165 | * ensure overflow hasn't happened. | |||
166 | */ | |||
167 | if (res < cntr.lastres && res > (TMR_MASK+1) << 3) | |||
168 | res = cntr.lastres + 1; | |||
169 | ||||
170 | cntr.lastres = res; | |||
171 | ||||
172 | __cpu_simple_unlock(&cntr.lock); | |||
136 | splx(s); | 173 | splx(s); | |
137 | 174 | |||
138 | return res; | 175 | return res; | |
139 | } | 176 | } | |
140 | 177 | |||
141 | void | 178 | void | |
142 | tickle_tc(void) | 179 | tickle_tc(void) | |
143 | { | 180 | { | |
181 | ||||
144 | if (timecounter->tc_get_timecount == timer_get_timecount) { | 182 | if (timecounter->tc_get_timecount == timer_get_timecount) { | |
183 | /* | |||
184 | * This could be protected by cntr.lock/splhigh but the update | |||
185 | * happens at IPL10 already and as a 32 bit value it should | |||
186 | * never be seen as a partial update, so skip it here. This | |||
187 | * also probably slows down the actual offset update, making | |||
188 | * one of the cases above more likely to need the workaround. | |||
189 | */ | |||
145 | cntr.offset += cntr.limit; | 190 | cntr.offset += cntr.limit; | |
146 | } | 191 | } | |
147 | } | 192 | } | |
148 | 193 | |||
149 | /* | 194 | /* | |
150 | * sun4/sun4c/sun4m common timer attach code | 195 | * sun4/sun4c/sun4m common timer attach code | |
151 | */ | 196 | */ | |
152 | void | 197 | void | |
153 | timerattach(volatile int *cntreg, volatile int *limreg) | 198 | timerattach(volatile int *cntreg, volatile int *limreg) | |
154 | { | 199 | { | |
155 | u_int prec = 0, t0; | 200 | u_int prec = 0, t0; | |
156 | void (*sched_intr_fn)(void *); | 201 | void (*sched_intr_fn)(void *); | |
157 | 202 | |||
158 | /* | 203 | /* | |
159 | * Calibrate delay() by tweaking the magic constant | 204 | * Calibrate delay() by tweaking the magic constant | |
160 | * until a delay(100) actually reads (at least) 100 us on the clock. | 205 | * until a delay(100) actually reads (at least) 100 us on the clock. | |
161 | * Note: sun4m clocks tick with 500ns periods. | 206 | * Note: sun4m clocks tick with 500ns periods. | |
162 | */ | 207 | */ | |
163 | for (timerblurb = 1; ; timerblurb++) { | 208 | for (timerblurb = 1; ; timerblurb++) { | |
164 | volatile int discard; | 209 | volatile int discard; | |
165 | u_int t1; | 210 | u_int t1; | |
166 | 211 | |||
167 | /* Reset counter register by writing some large limit value */ | 212 | /* Reset counter register by writing some large limit value */ | |
168 | discard = *limreg; | 213 | discard = *limreg; | |
169 | *limreg = tmr_ustolim(TMR_MASK-1); | 214 | *limreg = tmr_ustolim(TMR_MASK-1); | |
170 | 215 | |||
171 | t0 = *cntreg; | 216 | t0 = *cntreg; | |
172 | delay(100); | 217 | delay(100); | |
173 | t1 = *cntreg; | 218 | t1 = *cntreg; | |
174 | 219 | |||
175 | prec |= (t0 ^ t1) | (*cntreg ^ *cntreg); | 220 | prec |= (t0 ^ t1) | (*cntreg ^ *cntreg); | |
176 | 221 | |||
177 | if (t1 & TMR_LIMIT) | 222 | if (t1 & TMR_LIMIT) | |
178 | panic("delay calibration"); | 223 | panic("delay calibration"); | |
179 | 224 | |||
180 | t0 = (t0 >> TMR_SHIFT) & TMR_MASK; | 225 | t0 = (t0 >> TMR_SHIFT) & TMR_MASK; | |
181 | t1 = (t1 >> TMR_SHIFT) & TMR_MASK; | 226 | t1 = (t1 >> TMR_SHIFT) & TMR_MASK; | |
182 | 227 | |||
183 | if (t1 >= t0 + 100) | 228 | if (t1 >= t0 + 100) | |
184 | break; | 229 | break; | |
185 | } | 230 | } | |
186 | 231 | |||
187 | /* find lowest active bit */ | 232 | /* find lowest active bit */ | |
188 | for (t0 = 0; t0 < TMR_SHIFT; t0++) | 233 | for (t0 = 0; t0 < TMR_SHIFT; t0++) | |
189 | if ((1 << t0) & prec) | 234 | if ((1 << t0) & prec) | |
190 | break; | 235 | break; | |
191 | 236 | |||
237 | __cpu_simple_lock_init(&cntr.lock); | |||
238 | ||||
192 | cntr.shift = t0; | 239 | cntr.shift = t0; | |
193 | cntr.mask = (1 << (31-t0))-1; | 240 | cntr.mask = (1 << (31-t0))-1; | |
194 | counter_timecounter.tc_frequency = 1000000 * (TMR_SHIFT - t0 + 1); | 241 | counter_timecounter.tc_frequency = 1000000 * (TMR_SHIFT - t0 + 1); | |
195 | 242 | |||
196 | printf(": delay constant %d, frequency = %" PRIu64 " Hz\n", | 243 | printf(": delay constant %d, frequency = %" PRIu64 " Hz\n", | |
197 | timerblurb, counter_timecounter.tc_frequency); | 244 | timerblurb, counter_timecounter.tc_frequency); | |
198 | 245 | |||
199 | #if defined(SUN4) || defined(SUN4C) | 246 | #if defined(SUN4) || defined(SUN4C) | |
200 | if (CPU_ISSUN4 || CPU_ISSUN4C) { | 247 | if (CPU_ISSUN4 || CPU_ISSUN4C) { | |
201 | timer_init = timer_init_4; | 248 | timer_init = timer_init_4; | |
202 | sched_intr_fn = schedintr; | 249 | sched_intr_fn = schedintr; | |
203 | level10.ih_fun = clockintr_4; | 250 | level10.ih_fun = clockintr_4; | |
204 | level14.ih_fun = statintr_4; | 251 | level14.ih_fun = statintr_4; | |
205 | cntr.limit = tmr_ustolim(tick); | 252 | cntr.limit = tmr_ustolim(tick); | |
206 | } | 253 | } | |
207 | #endif | 254 | #endif | |
208 | #if defined(SUN4M) | 255 | #if defined(SUN4M) | |
209 | if (CPU_ISSUN4M) { | 256 | if (CPU_ISSUN4M) { | |
210 | timer_init = timer_init_4m; | 257 | timer_init = timer_init_4m; | |
211 | #if defined(MULTIPROCESSOR) | 258 | #if defined(MULTIPROCESSOR) | |
212 | if (sparc_ncpus > 1) | 259 | if (sparc_ncpus > 1) | |
213 | sched_intr_fn = schedintr_4m; | 260 | sched_intr_fn = schedintr_4m; | |
214 | else | 261 | else | |
215 | #endif | 262 | #endif | |
216 | sched_intr_fn = schedintr; | 263 | sched_intr_fn = schedintr; | |
217 | level10.ih_fun = clockintr_4m; | 264 | level10.ih_fun = clockintr_4m; | |
218 | level14.ih_fun = statintr_4m; | 265 | level14.ih_fun = statintr_4m; | |
219 | cntr.limit = tmr_ustolim4m(tick); | 266 | cntr.limit = tmr_ustolim4m(tick); | |
220 | } | 267 | } | |
221 | #endif | 268 | #endif | |
269 | ||||
222 | /* link interrupt handlers */ | 270 | /* link interrupt handlers */ | |
223 | intr_establish(10, 0, &level10, NULL, true); | 271 | intr_establish(10, 0, &level10, NULL, true); | |
224 | intr_establish(14, 0, &level14, NULL, true); | 272 | intr_establish(14, 0, &level14, NULL, true); | |
225 | 273 | |||
226 | /* Establish a soft interrupt at a lower level for schedclock */ | 274 | /* Establish a soft interrupt at a lower level for schedclock */ | |
227 | sched_cookie = sparc_softintr_establish(IPL_SCHED, sched_intr_fn, NULL); | 275 | sched_cookie = sparc_softintr_establish(IPL_SCHED, sched_intr_fn, NULL); | |
228 | if (sched_cookie == NULL) | 276 | if (sched_cookie == NULL) | |
229 | panic("timerattach: cannot establish schedintr"); | 277 | panic("timerattach: cannot establish schedintr"); | |
230 | 278 | |||
231 | cntr.cntreg = cntreg; | 279 | cntr.cntreg = cntreg; | |
232 | cntr.limit >>= cntr.shift; | 280 | cntr.limit >>= cntr.shift; | |
233 | 281 | |||
282 | /* start at non-zero, so that cntr.oldoffset is less */ | |||
283 | cntr.offset = cntr.limit; | |||
284 | ||||
234 | tc_init(&counter_timecounter); | 285 | tc_init(&counter_timecounter); | |
235 | } | 286 | } | |
236 | 287 | |||
237 | /* | 288 | /* | |
238 | * Both sun4 and sun4m can attach a timer on obio. | 289 | * Both sun4 and sun4m can attach a timer on obio. | |
239 | * The sun4m OPENPROM calls the timer the "counter". | 290 | * The sun4m OPENPROM calls the timer the "counter". | |
240 | * The sun4 timer must be probed. | 291 | * The sun4 timer must be probed. | |
241 | */ | 292 | */ | |
242 | static int | 293 | static int | |
243 | timermatch_obio(device_t parent, cfdata_t cf, void *aux) | 294 | timermatch_obio(device_t parent, cfdata_t cf, void *aux) | |
244 | { | 295 | { | |
245 | #if defined(SUN4) || defined(SUN4M) | 296 | #if defined(SUN4) || defined(SUN4M) | |
246 | union obio_attach_args *uoba = aux; | 297 | union obio_attach_args *uoba = aux; | |
247 | #endif | 298 | #endif | |
248 | #if defined(SUN4) | 299 | #if defined(SUN4) | |
249 | struct obio4_attach_args *oba; | 300 | struct obio4_attach_args *oba; | |
250 | #endif | 301 | #endif | |
251 | 302 | |||
252 | #if defined(SUN4M) | 303 | #if defined(SUN4M) | |
253 | if (uoba->uoba_isobio4 == 0) | 304 | if (uoba->uoba_isobio4 == 0) | |
254 | return (strcmp("counter", uoba->uoba_sbus.sa_name) == 0); | 305 | return (strcmp("counter", uoba->uoba_sbus.sa_name) == 0); | |
255 | #endif /* SUN4M */ | 306 | #endif /* SUN4M */ | |
256 | 307 | |||
257 | if (CPU_ISSUN4 == 0) { | 308 | if (CPU_ISSUN4 == 0) { | |
258 | printf("timermatch_obio: attach args mixed up\n"); | 309 | printf("timermatch_obio: attach args mixed up\n"); | |
259 | return (0); | 310 | return (0); | |
260 | } | 311 | } | |
261 | 312 | |||
262 | #if defined(SUN4) | 313 | #if defined(SUN4) | |
263 | /* Only these sun4s have "timer" (others have "oclock") */ | 314 | /* Only these sun4s have "timer" (others have "oclock") */ | |
264 | if (cpuinfo.cpu_type != CPUTYP_4_300 && | 315 | if (cpuinfo.cpu_type != CPUTYP_4_300 && | |
265 | cpuinfo.cpu_type != CPUTYP_4_400) | 316 | cpuinfo.cpu_type != CPUTYP_4_400) | |
266 | return (0); | 317 | return (0); | |
267 | 318 | |||
268 | /* Make sure there is something there */ | 319 | /* Make sure there is something there */ | |
269 | oba = &uoba->uoba_oba4; | 320 | oba = &uoba->uoba_oba4; | |
270 | return (bus_space_probe(oba->oba_bustag, oba->oba_paddr, | 321 | return (bus_space_probe(oba->oba_bustag, oba->oba_paddr, | |
271 | 4, /* probe size */ | 322 | 4, /* probe size */ | |
272 | 0, /* offset */ | 323 | 0, /* offset */ | |
273 | 0, /* flags */ | 324 | 0, /* flags */ | |
274 | NULL, NULL)); | 325 | NULL, NULL)); | |
275 | #endif /* SUN4 */ | 326 | #endif /* SUN4 */ | |
276 | panic("timermatch_obio: impossible"); | 327 | panic("timermatch_obio: impossible"); | |
277 | } | 328 | } | |
278 | 329 | |||
279 | static void | 330 | static void | |
280 | timerattach_obio(device_t parent, device_t self, void *aux) | 331 | timerattach_obio(device_t parent, device_t self, void *aux) | |
281 | { | 332 | { | |
282 | union obio_attach_args *uoba = aux; | 333 | union obio_attach_args *uoba = aux; | |
283 | 334 | |||
284 | if (uoba->uoba_isobio4 == 0) { | 335 | if (uoba->uoba_isobio4 == 0) { | |
285 | #if defined(SUN4M) | 336 | #if defined(SUN4M) | |
286 | /* sun4m timer at obio */ | 337 | /* sun4m timer at obio */ | |
287 | timerattach_obio_4m(parent, self, aux); | 338 | timerattach_obio_4m(parent, self, aux); | |
288 | #endif /* SUN4M */ | 339 | #endif /* SUN4M */ | |
289 | return; | 340 | return; | |
290 | } | 341 | } | |
291 | 342 | |||
292 | if (uoba->uoba_isobio4 != 0) { | 343 | if (uoba->uoba_isobio4 != 0) { | |
293 | #if defined(SUN4) | 344 | #if defined(SUN4) | |
294 | /* sun4 timer at obio */ | 345 | /* sun4 timer at obio */ | |
295 | timerattach_obio_4(parent, self, aux); | 346 | timerattach_obio_4(parent, self, aux); | |
296 | #endif /* SUN4 */ | 347 | #endif /* SUN4 */ | |
297 | } | 348 | } | |
298 | } | 349 | } | |
299 | 350 | |||
300 | CFATTACH_DECL_NEW(timer_obio, 0, | 351 | CFATTACH_DECL_NEW(timer_obio, 0, | |
301 | timermatch_obio, timerattach_obio, NULL, NULL); | 352 | timermatch_obio, timerattach_obio, NULL, NULL); | |
302 | 353 | |||
303 | /* | 354 | /* | |
304 | * Only sun4c attaches a timer at mainbus | 355 | * Only sun4c attaches a timer at mainbus | |
305 | */ | 356 | */ | |
306 | static int | 357 | static int | |
307 | timermatch_mainbus(device_t parent, cfdata_t cf, void *aux) | 358 | timermatch_mainbus(device_t parent, cfdata_t cf, void *aux) | |
308 | { | 359 | { | |
309 | #if defined(SUN4C) | 360 | #if defined(SUN4C) | |
310 | struct mainbus_attach_args *ma = aux; | 361 | struct mainbus_attach_args *ma = aux; | |
311 | 362 | |||
312 | return (strcmp("counter-timer", ma->ma_name) == 0); | 363 | return (strcmp("counter-timer", ma->ma_name) == 0); | |
313 | #else | 364 | #else | |
314 | return (0); | 365 | return (0); | |
315 | #endif | 366 | #endif | |
316 | } | 367 | } | |
317 | 368 | |||
318 | static void | 369 | static void | |
319 | timerattach_mainbus(device_t parent, device_t self, void *aux) | 370 | timerattach_mainbus(device_t parent, device_t self, void *aux) | |
320 | { | 371 | { | |
321 | 372 | |||
322 | #if defined(SUN4C) | 373 | #if defined(SUN4C) | |
323 | timerattach_mainbus_4c(parent, self, aux); | 374 | timerattach_mainbus_4c(parent, self, aux); | |
324 | #endif /* SUN4C */ | 375 | #endif /* SUN4C */ | |
325 | } | 376 | } | |
326 | 377 | |||
327 | CFATTACH_DECL_NEW(timer_mainbus, 0, | 378 | CFATTACH_DECL_NEW(timer_mainbus, 0, | |
328 | timermatch_mainbus, timerattach_mainbus, NULL, NULL); | 379 | timermatch_mainbus, timerattach_mainbus, NULL, NULL); |
--- src/sys/arch/sparc/sparc/timer_sun4m.c 2011/09/01 08:43:24 1.28
+++ src/sys/arch/sparc/sparc/timer_sun4m.c 2018/03/13 16:48:05 1.28.8.1
@@ -1,267 +1,271 @@ | @@ -1,267 +1,271 @@ | |||
1 | /* $NetBSD: timer_sun4m.c,v 1.28 2011/09/01 08:43:24 martin Exp $ */ | 1 | /* $NetBSD: timer_sun4m.c,v 1.28.8.1 2018/03/13 16:48:05 snj Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 1992, 1993 | 4 | * Copyright (c) 1992, 1993 | |
5 | * The Regents of the University of California. All rights reserved. | 5 | * The Regents of the University of California. All rights reserved. | |
6 | * Copyright (c) 1994 Gordon W. Ross | 6 | * Copyright (c) 1994 Gordon W. Ross | |
7 | * Copyright (c) 1993 Adam Glass | 7 | * Copyright (c) 1993 Adam Glass | |
8 | * Copyright (c) 1996 Paul Kranenburg | 8 | * Copyright (c) 1996 Paul Kranenburg | |
9 | * Copyright (c) 1996 | 9 | * Copyright (c) 1996 | |
10 | * The President and Fellows of Harvard College. All rights reserved. | 10 | * The President and Fellows of Harvard College. All rights reserved. | |
11 | * | 11 | * | |
12 | * This software was developed by the Computer Systems Engineering group | 12 | * This software was developed by the Computer Systems Engineering group | |
13 | * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and | 13 | * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and | |
14 | * contributed to Berkeley. | 14 | * contributed to Berkeley. | |
15 | * | 15 | * | |
16 | * All advertising materials mentioning features or use of this software | 16 | * All advertising materials mentioning features or use of this software | |
17 | * must display the following acknowledgement: | 17 | * must display the following acknowledgement: | |
18 | * This product includes software developed by Harvard University. | 18 | * This product includes software developed by Harvard University. | |
19 | * This product includes software developed by the University of | 19 | * This product includes software developed by the University of | |
20 | * California, Lawrence Berkeley Laboratory. | 20 | * California, Lawrence Berkeley Laboratory. | |
21 | * | 21 | * | |
22 | * Redistribution and use in source and binary forms, with or without | 22 | * Redistribution and use in source and binary forms, with or without | |
23 | * modification, are permitted provided that the following conditions | 23 | * modification, are permitted provided that the following conditions | |
24 | * are met: | 24 | * are met: | |
25 | * | 25 | * | |
26 | * 1. Redistributions of source code must retain the above copyright | 26 | * 1. Redistributions of source code must retain the above copyright | |
27 | * notice, this list of conditions and the following disclaimer. | 27 | * notice, this list of conditions and the following disclaimer. | |
28 | * 2. Redistributions in binary form must reproduce the above copyright | 28 | * 2. Redistributions in binary form must reproduce the above copyright | |
29 | * notice, this list of conditions and the following disclaimer in the | 29 | * notice, this list of conditions and the following disclaimer in the | |
30 | * documentation and/or other materials provided with the distribution. | 30 | * documentation and/or other materials provided with the distribution. | |
31 | * 3. All advertising materials mentioning features or use of this software | 31 | * 3. All advertising materials mentioning features or use of this software | |
32 | * must display the following acknowledgement: | 32 | * must display the following acknowledgement: | |
33 | * This product includes software developed by the University of | 33 | * This product includes software developed by the University of | |
34 | * California, Berkeley and its contributors. | 34 | * California, Berkeley and its contributors. | |
35 | * This product includes software developed by Paul Kranenburg. | 35 | * This product includes software developed by Paul Kranenburg. | |
36 | * This product includes software developed by Harvard University. | 36 | * This product includes software developed by Harvard University. | |
37 | * 4. Neither the name of the University nor the names of its contributors | 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 | 38 | * may be used to endorse or promote products derived from this software | |
39 | * without specific prior written permission. | 39 | * without specific prior written permission. | |
40 | * | 40 | * | |
41 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | 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 | 42 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
43 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | 43 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
44 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | 44 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
45 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 45 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
46 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | 46 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
47 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | 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 | 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 | 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 | 50 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
51 | * SUCH DAMAGE. | 51 | * SUCH DAMAGE. | |
52 | * | 52 | * | |
53 | * @(#)clock.c 8.1 (Berkeley) 6/11/93 | 53 | * @(#)clock.c 8.1 (Berkeley) 6/11/93 | |
54 | */ | 54 | */ | |
55 | 55 | |||
56 | /* | 56 | /* | |
57 | * Sun4m timer support. | 57 | * Sun4m timer support. | |
58 | */ | 58 | */ | |
59 | 59 | |||
60 | #include <sys/cdefs.h> | 60 | #include <sys/cdefs.h> | |
61 | __KERNEL_RCSID(0, "$NetBSD: timer_sun4m.c,v 1.28 2011/09/01 08:43:24 martin Exp $"); | 61 | __KERNEL_RCSID(0, "$NetBSD: timer_sun4m.c,v 1.28.8.1 2018/03/13 16:48:05 snj Exp $"); | |
62 | 62 | |||
63 | #include <sys/param.h> | 63 | #include <sys/param.h> | |
64 | #include <sys/kernel.h> | 64 | #include <sys/kernel.h> | |
65 | #include <sys/device.h> | 65 | #include <sys/device.h> | |
66 | #include <sys/systm.h> | 66 | #include <sys/systm.h> | |
67 | #include <sys/cpu.h> | 67 | #include <sys/cpu.h> | |
68 | 68 | |||
69 | #include <machine/autoconf.h> | 69 | #include <machine/autoconf.h> | |
70 | #include <sys/bus.h> | 70 | #include <sys/bus.h> | |
71 | 71 | |||
72 | #include <sparc/sparc/vaddrs.h> | 72 | #include <sparc/sparc/vaddrs.h> | |
73 | #include <sparc/sparc/cpuvar.h> | 73 | #include <sparc/sparc/cpuvar.h> | |
74 | #include <sparc/sparc/timerreg.h> | 74 | #include <sparc/sparc/timerreg.h> | |
75 | #include <sparc/sparc/timervar.h> | 75 | #include <sparc/sparc/timervar.h> | |
76 | 76 | |||
77 | struct timer_4m *timerreg4m; | 77 | static struct timer_4m *timerreg4m; | |
78 | #define counterreg4m cpuinfo.counterreg_4m | 78 | #define counterreg4m cpuinfo.counterreg_4m | |
79 | 79 | |||
80 | /* | 80 | /* | |
81 | * Set up the real-time and statistics clocks. | 81 | * Set up the real-time and statistics clocks. | |
82 | * Leave stathz 0 only if no alternative timer is available. | 82 | * Leave stathz 0 only if no alternative timer is available. | |
83 | * | 83 | * | |
84 | * The frequencies of these clocks must be an even number of microseconds. | 84 | * The frequencies of these clocks must be an even number of microseconds. | |
85 | */ | 85 | */ | |
86 | void | 86 | void | |
87 | timer_init_4m(void) | 87 | timer_init_4m(void) | |
88 | { | 88 | { | |
89 | struct cpu_info *cpi; | 89 | struct cpu_info *cpi; | |
90 | int n; | 90 | int n; | |
91 | 91 | |||
92 | timerreg4m->t_limit = tmr_ustolim4m(tick); | 92 | timerreg4m->t_limit = tmr_ustolim4m(tick); | |
93 | for (CPU_INFO_FOREACH(n, cpi)) { | 93 | for (CPU_INFO_FOREACH(n, cpi)) { | |
94 | cpi->counterreg_4m->t_limit = tmr_ustolim4m(statint); | 94 | cpi->counterreg_4m->t_limit = tmr_ustolim4m(statint); | |
95 | } | 95 | } | |
96 | icr_si_bic(SINTR_T); | 96 | icr_si_bic(SINTR_T); | |
97 | } | 97 | } | |
98 | 98 | |||
99 | void | 99 | void | |
100 | schedintr_4m(void *v) | 100 | schedintr_4m(void *v) | |
101 | { | 101 | { | |
102 | 102 | |||
103 | kpreempt_disable(); | 103 | kpreempt_disable(); | |
104 | #ifdef MULTIPROCESSOR | 104 | #ifdef MULTIPROCESSOR | |
105 | /* | 105 | /* | |
106 | * We call hardclock() here so that we make sure it is called on | 106 | * We call hardclock() here so that we make sure it is called on | |
107 | * all CPUs. This function ends up being called on sun4m systems | 107 | * all CPUs. This function ends up being called on sun4m systems | |
108 | * every tick. | 108 | * every tick. | |
109 | */ | 109 | */ | |
110 | if (!CPU_IS_PRIMARY(curcpu())) | 110 | if (!CPU_IS_PRIMARY(curcpu())) | |
111 | hardclock(v); | 111 | hardclock(v); | |
112 | 112 | |||
113 | /* | 113 | /* | |
114 | * The factor 8 is only valid for stathz==100. | 114 | * The factor 8 is only valid for stathz==100. | |
115 | * See also clock.c | 115 | * See also clock.c | |
116 | */ | 116 | */ | |
117 | if ((++cpuinfo.ci_schedstate.spc_schedticks & 7) == 0 && schedhz != 0) | 117 | if ((++cpuinfo.ci_schedstate.spc_schedticks & 7) == 0 && schedhz != 0) | |
118 | #endif | 118 | #endif | |
119 | schedclock(curlwp); | 119 | schedclock(curlwp); | |
120 | kpreempt_enable(); | 120 | kpreempt_enable(); | |
121 | } | 121 | } | |
122 | 122 | |||
123 | 123 | |||
124 | /* | 124 | /* | |
125 | * Level 10 (clock) interrupts from system counter. | 125 | * Level 10 (clock) interrupts from system counter. | |
126 | */ | 126 | */ | |
127 | int | 127 | int | |
128 | clockintr_4m(void *cap) | 128 | clockintr_4m(void *cap) | |
129 | { | 129 | { | |
130 | 130 | |||
131 | KASSERT(CPU_IS_PRIMARY(curcpu())); | 131 | KASSERT(CPU_IS_PRIMARY(curcpu())); | |
132 | /* | 132 | /* | |
133 | * XXX this needs to be fixed in a more general way | 133 | * XXX this needs to be fixed in a more general way | |
134 | * problem is that the kernel enables interrupts and THEN | 134 | * problem is that the kernel enables interrupts and THEN | |
135 | * sets up clocks. In between there's an opportunity to catch | 135 | * sets up clocks. In between there's an opportunity to catch | |
136 | * a timer interrupt - if we call hardclock() at that point we'll | 136 | * a timer interrupt - if we call hardclock() at that point we'll | |
137 | * panic | 137 | * panic | |
138 | * so for now just bail when cold | 138 | * so for now just bail when cold | |
139 | * | 139 | * | |
140 | * For MP, we defer calling hardclock() to the schedintr so | 140 | * For MP, we defer calling hardclock() to the schedintr so | |
141 | * that we call it on all cpus. | 141 | * that we call it on all cpus. | |
142 | */ | 142 | */ | |
143 | if (cold) | 143 | if (cold) | |
144 | return 0; | 144 | return 0; | |
145 | ||||
145 | kpreempt_disable(); | 146 | kpreempt_disable(); | |
146 | /* read the limit register to clear the interrupt */ | 147 | ||
148 | /* Read the limit register to clear the interrupt. */ | |||
147 | *((volatile int *)&timerreg4m->t_limit); | 149 | *((volatile int *)&timerreg4m->t_limit); | |
150 | ||||
151 | /* Update the timecounter offset. */ | |||
148 | tickle_tc(); | 152 | tickle_tc(); | |
149 | hardclock((struct clockframe *)cap); | 153 | hardclock((struct clockframe *)cap); | |
150 | kpreempt_enable(); | 154 | kpreempt_enable(); | |
151 | return (1); | 155 | return (1); | |
152 | } | 156 | } | |
153 | 157 | |||
154 | /* | 158 | /* | |
155 | * Level 14 (stat clock) interrupts from processor counter. | 159 | * Level 14 (stat clock) interrupts from processor counter. | |
156 | */ | 160 | */ | |
157 | int | 161 | int | |
158 | statintr_4m(void *cap) | 162 | statintr_4m(void *cap) | |
159 | { | 163 | { | |
160 | struct clockframe *frame = cap; | 164 | struct clockframe *frame = cap; | |
161 | u_long newint; | 165 | u_long newint; | |
162 | 166 | |||
163 | kpreempt_disable(); | 167 | kpreempt_disable(); | |
164 | 168 | |||
165 | /* read the limit register to clear the interrupt */ | 169 | /* read the limit register to clear the interrupt */ | |
166 | *((volatile int *)&counterreg4m->t_limit); | 170 | *((volatile int *)&counterreg4m->t_limit); | |
167 | 171 | |||
168 | statclock(frame); | 172 | statclock(frame); | |
169 | 173 | |||
170 | /* | 174 | /* | |
171 | * Compute new randomized interval. | 175 | * Compute new randomized interval. | |
172 | */ | 176 | */ | |
173 | newint = new_interval(); | 177 | newint = new_interval(); | |
174 | 178 | |||
175 | /* | 179 | /* | |
176 | * Use the `non-resetting' limit register, so we don't | 180 | * Use the `non-resetting' limit register, so we don't | |
177 | * loose the counter ticks that happened since this | 181 | * loose the counter ticks that happened since this | |
178 | * interrupt was raised. | 182 | * interrupt was raised. | |
179 | */ | 183 | */ | |
180 | counterreg4m->t_limit_nr = tmr_ustolim4m(newint); | 184 | counterreg4m->t_limit_nr = tmr_ustolim4m(newint); | |
181 | 185 | |||
182 | /* | 186 | /* | |
183 | * The factor 8 is only valid for stathz==100. | 187 | * The factor 8 is only valid for stathz==100. | |
184 | * See also clock.c | 188 | * See also clock.c | |
185 | */ | 189 | */ | |
186 | #if !defined(MULTIPROCESSOR) | 190 | #if !defined(MULTIPROCESSOR) | |
187 | if ((++cpuinfo.ci_schedstate.spc_schedticks & 7) == 0 && schedhz != 0) { | 191 | if ((++cpuinfo.ci_schedstate.spc_schedticks & 7) == 0 && schedhz != 0) { | |
188 | #endif | 192 | #endif | |
189 | if (CLKF_LOPRI(frame, IPL_SCHED)) { | 193 | if (CLKF_LOPRI(frame, IPL_SCHED)) { | |
190 | /* No need to schedule a soft interrupt */ | 194 | /* No need to schedule a soft interrupt */ | |
191 | spllowerschedclock(); | 195 | spllowerschedclock(); | |
192 | schedintr_4m(cap); | 196 | schedintr_4m(cap); | |
193 | } else { | 197 | } else { | |
194 | /* | 198 | /* | |
195 | * We're interrupting a thread that may have the | 199 | * We're interrupting a thread that may have the | |
196 | * scheduler lock; run schedintr_4m() on this CPU later. | 200 | * scheduler lock; run schedintr_4m() on this CPU later. | |
197 | */ | 201 | */ | |
198 | raise_ipi(&cpuinfo, IPL_SCHED); /* sched_cookie->pil */ | 202 | raise_ipi(&cpuinfo, IPL_SCHED); /* sched_cookie->pil */ | |
199 | } | 203 | } | |
200 | #if !defined(MULTIPROCESSOR) | 204 | #if !defined(MULTIPROCESSOR) | |
201 | } | 205 | } | |
202 | #endif | 206 | #endif | |
203 | kpreempt_enable(); | 207 | kpreempt_enable(); | |
204 | 208 | |||
205 | return (1); | 209 | return (1); | |
206 | } | 210 | } | |
207 | 211 | |||
208 | void | 212 | void | |
209 | timerattach_obio_4m(device_t parent, device_t self, void *aux) | 213 | timerattach_obio_4m(device_t parent, device_t self, void *aux) | |
210 | { | 214 | { | |
211 | union obio_attach_args *uoba = aux; | 215 | union obio_attach_args *uoba = aux; | |
212 | struct sbus_attach_args *sa = &uoba->uoba_sbus; | 216 | struct sbus_attach_args *sa = &uoba->uoba_sbus; | |
213 | struct cpu_info *cpi; | 217 | struct cpu_info *cpi; | |
214 | bus_space_handle_t bh; | 218 | bus_space_handle_t bh; | |
215 | int i, n; | 219 | int i, n; | |
216 | 220 | |||
217 | if (sa->sa_nreg < 2) { | 221 | if (sa->sa_nreg < 2) { | |
218 | printf(": only %d register sets\n", sa->sa_nreg); | 222 | printf(": only %d register sets\n", sa->sa_nreg); | |
219 | return; | 223 | return; | |
220 | } | 224 | } | |
221 | 225 | |||
222 | /* Map the system timer */ | 226 | /* Map the system timer */ | |
223 | i = sa->sa_nreg - 1; | 227 | i = sa->sa_nreg - 1; | |
224 | if (bus_space_map2(sa->sa_bustag, | 228 | if (bus_space_map2(sa->sa_bustag, | |
225 | BUS_ADDR(sa->sa_reg[i].oa_space, | 229 | BUS_ADDR(sa->sa_reg[i].oa_space, | |
226 | sa->sa_reg[i].oa_base), | 230 | sa->sa_reg[i].oa_base), | |
227 | sizeof(struct timer_4m), | 231 | sizeof(struct timer_4m), | |
228 | BUS_SPACE_MAP_LINEAR, | 232 | BUS_SPACE_MAP_LINEAR, | |
229 | TIMERREG_VA, &bh) != 0) { | 233 | TIMERREG_VA, &bh) != 0) { | |
230 | printf(": can't map registers\n"); | 234 | printf(": can't map registers\n"); | |
231 | return; | 235 | return; | |
232 | } | 236 | } | |
233 | timerreg4m = (struct timer_4m *)TIMERREG_VA; | 237 | timerreg4m = (struct timer_4m *)TIMERREG_VA; | |
234 | 238 | |||
235 | /* Map each CPU's counter */ | 239 | /* Map each CPU's counter */ | |
236 | for (i = 0; i < sa->sa_nreg - 1; i++) { | 240 | for (i = 0; i < sa->sa_nreg - 1; i++) { | |
237 | /* | 241 | /* | |
238 | * Check whether the CPU corresponding to this timer | 242 | * Check whether the CPU corresponding to this timer | |
239 | * register is installed. | 243 | * register is installed. | |
240 | */ | 244 | */ | |
241 | for (CPU_INFO_FOREACH(n, cpi)) { | 245 | for (CPU_INFO_FOREACH(n, cpi)) { | |
242 | if ((i == 0 && sparc_ncpus == 1) || cpi->mid == i + 8) { | 246 | if ((i == 0 && sparc_ncpus == 1) || cpi->mid == i + 8) { | |
243 | /* We got a corresponding MID. */ | 247 | /* We got a corresponding MID. */ | |
244 | break; | 248 | break; | |
245 | } | 249 | } | |
246 | cpi = NULL; | 250 | cpi = NULL; | |
247 | } | 251 | } | |
248 | if (cpi == NULL) | 252 | if (cpi == NULL) | |
249 | continue; | 253 | continue; | |
250 | 254 | |||
251 | if (sbus_bus_map(sa->sa_bustag, | 255 | if (sbus_bus_map(sa->sa_bustag, | |
252 | sa->sa_reg[i].oa_space, | 256 | sa->sa_reg[i].oa_space, | |
253 | sa->sa_reg[i].oa_base, | 257 | sa->sa_reg[i].oa_base, | |
254 | sizeof(struct timer_4m), | 258 | sizeof(struct timer_4m), | |
255 | BUS_SPACE_MAP_LINEAR, | 259 | BUS_SPACE_MAP_LINEAR, | |
256 | &bh) != 0) { | 260 | &bh) != 0) { | |
257 | printf(": can't map CPU counter %d\n", i); | 261 | printf(": can't map CPU counter %d\n", i); | |
258 | return; | 262 | return; | |
259 | } | 263 | } | |
260 | cpi->counterreg_4m = (struct counter_4m *)bh; | 264 | cpi->counterreg_4m = (struct counter_4m *)bh; | |
261 | } | 265 | } | |
262 | 266 | |||
263 | /* Put processor counter in "timer" mode */ | 267 | /* Put processor counter in "timer" mode */ | |
264 | timerreg4m->t_cfg = 0; | 268 | timerreg4m->t_cfg = 0; | |
265 | 269 | |||
266 | timerattach(&timerreg4m->t_counter, &timerreg4m->t_limit); | 270 | timerattach(&timerreg4m->t_counter, &timerreg4m->t_limit); | |
267 | } | 271 | } |
--- src/sys/arch/sparc/sparc/timerreg.h 2005/11/16 03:00:23 1.9
+++ src/sys/arch/sparc/sparc/timerreg.h 2018/03/13 16:48:05 1.9.118.1
@@ -1,128 +1,131 @@ | @@ -1,128 +1,131 @@ | |||
1 | /* $NetBSD: timerreg.h,v 1.9 2005/11/16 03:00:23 uwe Exp $ */ | 1 | /* $NetBSD: timerreg.h,v 1.9.118.1 2018/03/13 16:48:05 snj Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 1992, 1993 | 4 | * Copyright (c) 1992, 1993 | |
5 | * The Regents of the University of California. All rights reserved. | 5 | * The Regents of the University of California. All rights reserved. | |
6 | * | 6 | * | |
7 | * This software was developed by the Computer Systems Engineering group | 7 | * This software was developed by the Computer Systems Engineering group | |
8 | * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and | 8 | * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and | |
9 | * contributed to Berkeley. | 9 | * contributed to Berkeley. | |
10 | * | 10 | * | |
11 | * All advertising materials mentioning features or use of this software | 11 | * All advertising materials mentioning features or use of this software | |
12 | * must display the following acknowledgement: | 12 | * must display the following acknowledgement: | |
13 | * This product includes software developed by the University of | 13 | * This product includes software developed by the University of | |
14 | * California, Lawrence Berkeley Laboratory. | 14 | * California, Lawrence Berkeley Laboratory. | |
15 | * | 15 | * | |
16 | * Redistribution and use in source and binary forms, with or without | 16 | * Redistribution and use in source and binary forms, with or without | |
17 | * modification, are permitted provided that the following conditions | 17 | * modification, are permitted provided that the following conditions | |
18 | * are met: | 18 | * are met: | |
19 | * 1. Redistributions of source code must retain the above copyright | 19 | * 1. Redistributions of source code must retain the above copyright | |
20 | * notice, this list of conditions and the following disclaimer. | 20 | * notice, this list of conditions and the following disclaimer. | |
21 | * 2. Redistributions in binary form must reproduce the above copyright | 21 | * 2. Redistributions in binary form must reproduce the above copyright | |
22 | * notice, this list of conditions and the following disclaimer in the | 22 | * notice, this list of conditions and the following disclaimer in the | |
23 | * documentation and/or other materials provided with the distribution. | 23 | * documentation and/or other materials provided with the distribution. | |
24 | * 3. Neither the name of the University nor the names of its contributors | 24 | * 3. Neither the name of the University nor the names of its contributors | |
25 | * may be used to endorse or promote products derived from this software | 25 | * may be used to endorse or promote products derived from this software | |
26 | * without specific prior written permission. | 26 | * without specific prior written permission. | |
27 | * | 27 | * | |
28 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | 28 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | |
29 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 29 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
30 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | 30 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
31 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | 31 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | |
32 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 32 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
33 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | 33 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
34 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | 34 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
35 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | 35 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
36 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | 36 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
37 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | 37 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
38 | * SUCH DAMAGE. | 38 | * SUCH DAMAGE. | |
39 | * | 39 | * | |
40 | * @(#)timerreg.h 8.1 (Berkeley) 6/11/93 | 40 | * @(#)timerreg.h 8.1 (Berkeley) 6/11/93 | |
41 | */ | 41 | */ | |
42 | 42 | |||
43 | /* | 43 | /* | |
44 | * Sun-4c counter/timer registers. The timers are implemented within | 44 | * Sun-4c counter/timer registers. The timers are implemented within | |
45 | * the cache chip (!). The counter and limit fields below could be | 45 | * the cache chip (!). The counter and limit fields below could be | |
46 | * defined as: | 46 | * defined as: | |
47 | * | 47 | * | |
48 | * struct { | 48 | * struct { | |
49 | * u_int t_limit:1, // limit reached | 49 | * u_int t_limit:1, // limit reached | |
50 | * t_usec:21, // counter value in microseconds | 50 | * t_usec:21, // counter value in microseconds | |
51 | * t_mbz:10; // always zero | 51 | * t_mbz:10; // always zero | |
52 | * }; | 52 | * }; | |
53 | * | 53 | * | |
54 | * but this is more trouble than it is worth. | 54 | * but this is more trouble than it is worth. | |
55 | * | 55 | * | |
56 | * These timers work in a rather peculiar fashion. Most clock counters | 56 | * These timers work in a rather peculiar fashion. Most clock counters | |
57 | * run to 0 (as, e.g., on the VAX, where the ICR counts up to 0 from a | 57 | * run to 0 (as, e.g., on the VAX, where the ICR counts up to 0 from a | |
58 | * large unsigned number). On the Sun-4c, it counts up to a limit. But | 58 | * large unsigned number). On the Sun-4c, it counts up to a limit. But | |
59 | * for some reason, when it reaches the limit, it resets to 1, not 0. | 59 | * for some reason, when it reaches the limit, it resets to 1, not 0. | |
60 | * Thus, if the limit is set to 4, the counter counts like this: | 60 | * Thus, if the limit is set to 4, the counter counts like this: | |
61 | * | 61 | * | |
62 | * 1, 2, 3, 1, 2, 3, ... | 62 | * 1, 2, 3, 1, 2, 3, ... | |
63 | * | 63 | * | |
64 | * and if we want to divide by N we must set the limit register to N+1. | 64 | * and if we want to divide by N we must set the limit register to N+1. | |
65 | * | 65 | * | |
66 | * Sun-4m counters/timer registers are similar, with these exceptions: | 66 | * Sun-4m counters/timer registers are similar, with these exceptions: | |
67 | * | 67 | * | |
68 | * - the limit and counter registers have changed positions.. | 68 | * - the limit and counter registers have changed positions.. | |
69 | * - both limit and counter registers are 22 bits wide, but | 69 | * - both limit and counter registers are 22 bits wide, but | |
70 | * they count in 500ns increments (bit 9 being the least | 70 | * they count in 500ns increments (bit 9 being the least | |
71 | * significant bit). | 71 | * significant bit). | |
72 | * | 72 | * | |
73 | */ | 73 | */ | |
74 | #ifndef _LOCORE | 74 | #ifndef _LOCORE | |
75 | struct timer_4 { | 75 | struct timer_4 { | |
76 | volatile int t_counter; /* counter reg */ | 76 | volatile int t_counter; /* counter reg */ | |
77 | volatile int t_limit; /* limit reg */ | 77 | volatile int t_limit; /* limit reg */ | |
78 | }; | 78 | }; | |
79 | 79 | |||
80 | struct timerreg_4 { | 80 | struct timerreg_4 { | |
81 | struct timer_4 t_c10; /* counter that interrupts at ipl 10 */ | 81 | struct timer_4 t_c10; /* counter that interrupts at ipl 10 */ | |
82 | struct timer_4 t_c14; /* counter that interrupts at ipl 14 */ | 82 | struct timer_4 t_c14; /* counter that interrupts at ipl 14 */ | |
83 | }; | 83 | }; | |
84 | 84 | |||
85 | struct timer_4m { /* counter that interrupts at ipl 10 */ | 85 | struct timer_4m { /* counter that interrupts at ipl 10 */ | |
86 | volatile int t_limit; /* limit register */ | 86 | volatile int t_limit; /* limit register */ | |
87 | volatile int t_counter; /* counter register */ | 87 | volatile int t_counter; /* counter register */ | |
88 | volatile int t_limit_nr; /* limit reg, non-resetting */ | 88 | volatile int t_limit_nr; /* limit reg, non-resetting */ | |
89 | volatile int t_reserved; | 89 | volatile int t_reserved; | |
90 | volatile int t_cfg; /* a configuration register */ | 90 | volatile int t_cfg; /* a configuration register */ | |
91 | /* | 91 | /* | |
92 | * Note: The SparcClassic manual only defines this one bit | 92 | * Note: The SparcClassic manual only defines this one bit | |
93 | * I suspect there are more in multi-processor machines. | 93 | * I suspect there are more in multi-processor machines. | |
94 | */ | 94 | */ | |
95 | #define TMR_CFG_USER 1 | 95 | #define TMR_CFG_USER 1 | |
96 | }; | 96 | }; | |
97 | 97 | |||
98 | struct counter_4m { /* counter that interrupts at ipl 14 */ | 98 | struct counter_4m { /* counter that interrupts at ipl 14 */ | |
99 | volatile int t_limit; /* limit register */ | 99 | volatile int t_limit; /* limit register */ | |
100 | volatile int t_counter; /* counter register */ | 100 | volatile int t_counter; /* counter register */ | |
101 | volatile int t_limit_nr; /* limit reg, non-resetting */ | 101 | volatile int t_limit_nr; /* limit reg, non-resetting */ | |
102 | volatile int t_ss; /* Start/Stop register */ | 102 | volatile int t_ss; /* Start/Stop register */ | |
103 | #define TMR_USER_RUN 1 | 103 | #define TMR_USER_RUN 1 | |
104 | }; | 104 | }; | |
105 | #endif /* _LOCORE */ | 105 | #endif /* _LOCORE */ | |
106 | 106 | |||
107 | #define TMR_LIMIT 0x80000000 /* counter reached its limit */ | 107 | #define TMR_LIMIT 0x80000000 /* counter reached its limit */ | |
108 | #define TMR_SHIFT 10 /* shift to obtain microseconds */ | 108 | #define TMR_SHIFT 10 /* shift to obtain microseconds */ | |
109 | #define TMR_MASK 0x1fffff /* 21 bits */ | 109 | #define TMR_MASK 0x1fffff /* 21 bits */ | |
110 | 110 | |||
111 | /* | 111 | /* | |
112 | * Compute a limit that causes the timer to fire every n microseconds. | 112 | * Compute a limit that causes the timer to fire every n microseconds. | |
113 | * The Sun4c requires that the timer register be initialized for n+1 | 113 | * The Sun4c requires that the timer register be initialized for n+1 | |
114 | * microseconds, while the Sun4m requires it be initialized for n. Thus | 114 | * microseconds, while the Sun4m requires it be initialized for n. Thus | |
115 | * the two versions of this function. | 115 | * the two versions of this function. | |
116 | * | 116 | * | |
117 | * Note that the manual for the chipset used in the Sun4m suggests that | 117 | * Note that the manual for the chipset used in the Sun4m suggests that | |
118 | * the timer be set at n+0.5 microseconds; in practice, this produces | 118 | * the timer be set at n+0.5 microseconds; in practice, this produces | |
119 | * a 50 ppm clock skew, which means that the 0.5 should not be there... | 119 | * a 50 ppm clock skew, which means that the 0.5 should not be there... | |
120 | */ | 120 | */ | |
121 | #define tmr_ustolim(n) (((n) + 1) << TMR_SHIFT) | 121 | #define tmr_ustolim(n) (((n) + 1) << TMR_SHIFT) | |
122 | 122 | |||
123 | /*efine TMR_SHIFT4M 9 -* shift to obtain microseconds */ | 123 | #define TMR_SHIFT4M 9 /* shift to obtain microseconds */ | |
124 | /*efine tmr_ustolim4m(n) (((2*(n)) + 1) << TMR_SHIFT4M)*/ | 124 | #if 1 | |
125 | #define tmr_ustolim4m(n) (((2*(n)) + 1) << TMR_SHIFT4M) | |||
126 | #else | |||
125 | #define tmr_ustolim4m(n) ((n) << TMR_SHIFT) | 127 | #define tmr_ustolim4m(n) ((n) << TMR_SHIFT) | |
128 | #endif | |||
126 | 129 | |||
127 | /* The number of microseconds represented by a counter register value */ | 130 | /* The number of microseconds represented by a counter register value */ | |
128 | #define tmr_cnttous(c) ((((c) >> TMR_SHIFT) & TMR_MASK) - 1) | 131 | #define tmr_cnttous(c) ((((c) >> TMR_SHIFT) & TMR_MASK) - 1) |