Sun Jan 19 00:22:33 2014 UTC ()
remove schedintr_4m(), and go back to only having the level 14
timer call statclock/schedclock.  the randomness for this clock
makes the hardclock() call very jittery.

instead of this, trigger a softintr IPI at level 10 on non-primary
CPUs from the primary CPU's clock interrupt (at level 10.)  this
cleans up the generic sparc timer code a little as well.

this makes the time goes backwards problem *much* less frequent,
but i still see it sometimes.


(mrg)
diff -r1.31 -r1.32 src/sys/arch/sparc/sparc/timer.c
diff -r1.29 -r1.30 src/sys/arch/sparc/sparc/timer_sun4m.c
diff -r1.11 -r1.12 src/sys/arch/sparc/sparc/timervar.h

cvs diff -r1.31 -r1.32 src/sys/arch/sparc/sparc/timer.c (expand / switch to unified diff)

--- src/sys/arch/sparc/sparc/timer.c 2013/10/19 19:40:23 1.31
+++ src/sys/arch/sparc/sparc/timer.c 2014/01/19 00:22:33 1.32
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: timer.c,v 1.31 2013/10/19 19:40:23 mrg Exp $ */ 1/* $NetBSD: timer.c,v 1.32 2014/01/19 00:22:33 mrg 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.
@@ -50,54 +50,54 @@ @@ -50,54 +50,54 @@
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.31 2013/10/19 19:40:23 mrg Exp $"); 63__KERNEL_RCSID(0, "$NetBSD: timer.c,v 1.32 2014/01/19 00:22:33 mrg 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
77static struct intrhand level10; 77static struct intrhand level10;
78static struct intrhand level14; 78static struct intrhand level14;
79 79
80static u_int timer_get_timecount(struct timecounter *); 80static u_int timer_get_timecount(struct timecounter *);
81 81
82void *sched_cookie; 82void *sched_cookie;
83 83
84/* 84/*
85 * timecounter local state 85 * timecounter local state
86 */ 86 */
87static struct counter { 87static struct counter {
88 volatile u_int *cntreg; /* counter register */ 88 volatile u_int *cntreg; /* counter register */
89 u_int limit; /* limit we count up to */ 89 u_int limit; /* limit we count up to */
90 u_int offset; /* accumulated offet due to wraps */ 90 u_int offset; /* accumulated offset due to wraps */
91 u_int shift; /* scaling for valid bits */ 91 u_int shift; /* scaling for valid bits */
92 u_int mask; /* valid bit mask */ 92 u_int mask; /* valid bit mask */
93} cntr; 93} cntr;
94 94
95/* 95/*
96 * define timecounter 96 * define timecounter
97 */ 97 */
98 98
99static struct timecounter counter_timecounter = { 99static struct timecounter counter_timecounter = {
100 timer_get_timecount, /* get_timecount */ 100 timer_get_timecount, /* get_timecount */
101 0, /* no poll_pps */ 101 0, /* no poll_pps */
102 ~0u, /* counter_mask */ 102 ~0u, /* counter_mask */
103 0, /* frequency - set at initialisation */ 103 0, /* frequency - set at initialisation */
@@ -107,32 +107,31 @@ static struct timecounter counter_timeco @@ -107,32 +107,31 @@ static struct timecounter counter_timeco
107}; 107};
108 108
109/* 109/*
110 * timer_get_timecount provide current counter value 110 * timer_get_timecount provide current counter value
111 */ 111 */
112static u_int 112static u_int
113timer_get_timecount(struct timecounter *tc) 113timer_get_timecount(struct timecounter *tc)
114{ 114{
115 struct counter *ctr = (struct counter *)tc->tc_priv; 115 struct counter *ctr = (struct counter *)tc->tc_priv;
116 116
117 u_int c, res, r; 117 u_int c, res, r;
118 int s; 118 int s;
119 119
120 
121 s = splhigh(); 120 s = splhigh();
122 121
123 res = c = *ctr->cntreg; 122 res = c = *ctr->cntreg;
124 123
125 res &= ~TMR_LIMIT; 124 res &= ~TMR_LIMIT;
126 125
127 if (c != res) { 126 if (c != res) {
128 r = ctr->limit; 127 r = ctr->limit;
129 } else { 128 } else {
130 r = 0; 129 r = 0;
131 } 130 }
132  131
133 res >>= ctr->shift; 132 res >>= ctr->shift;
134 res &= ctr->mask; 133 res &= ctr->mask;
135 134
136 res += r + ctr->offset; 135 res += r + ctr->offset;
137 136
138 splx(s); 137 splx(s);
@@ -145,27 +144,26 @@ tickle_tc(void) @@ -145,27 +144,26 @@ tickle_tc(void)
145{ 144{
146 if (timecounter->tc_get_timecount == timer_get_timecount) { 145 if (timecounter->tc_get_timecount == timer_get_timecount) {
147 cntr.offset += cntr.limit; 146 cntr.offset += cntr.limit;
148 } 147 }
149} 148}
150 149
151/* 150/*
152 * sun4/sun4c/sun4m common timer attach code 151 * sun4/sun4c/sun4m common timer attach code
153 */ 152 */
154void 153void
155timerattach(volatile int *cntreg, volatile int *limreg) 154timerattach(volatile int *cntreg, volatile int *limreg)
156{ 155{
157 u_int prec = 0, t0; 156 u_int prec = 0, t0;
158 void (*sched_intr_fn)(void *); 
159 157
160 /* 158 /*
161 * Calibrate delay() by tweaking the magic constant 159 * Calibrate delay() by tweaking the magic constant
162 * until a delay(100) actually reads (at least) 100 us on the clock. 160 * until a delay(100) actually reads (at least) 100 us on the clock.
163 * Note: sun4m clocks tick with 500ns periods. 161 * Note: sun4m clocks tick with 500ns periods.
164 */ 162 */
165 for (timerblurb = 1; ; timerblurb++) { 163 for (timerblurb = 1; ; timerblurb++) {
166 int discard; 164 int discard;
167 u_int t1; 165 u_int t1;
168 166
169 /* Reset counter register by writing some large limit value */ 167 /* Reset counter register by writing some large limit value */
170 discard = *limreg; 168 discard = *limreg;
171 __USE(discard); 169 __USE(discard);
@@ -188,56 +186,50 @@ timerattach(volatile int *cntreg, volati @@ -188,56 +186,50 @@ timerattach(volatile int *cntreg, volati
188 } 186 }
189 187
190 /* find lowest active bit */ 188 /* find lowest active bit */
191 for (t0 = 0; t0 < TMR_SHIFT; t0++) 189 for (t0 = 0; t0 < TMR_SHIFT; t0++)
192 if ((1 << t0) & prec) 190 if ((1 << t0) & prec)
193 break; 191 break;
194 192
195 cntr.shift = t0; 193 cntr.shift = t0;
196 cntr.mask = (1 << (31-t0))-1; 194 cntr.mask = (1 << (31-t0))-1;
197 counter_timecounter.tc_frequency = 1000000 * (TMR_SHIFT - t0 + 1); 195 counter_timecounter.tc_frequency = 1000000 * (TMR_SHIFT - t0 + 1);
198  196
199 printf(": delay constant %d, frequency = %" PRIu64 " Hz\n", 197 printf(": delay constant %d, frequency = %" PRIu64 " Hz\n",
200 timerblurb, counter_timecounter.tc_frequency); 198 timerblurb, counter_timecounter.tc_frequency);
 199printf("timer: limit %u shift %u mask %x\n", cntr.limit, cntr.shift, cntr.mask);
201 200
202#if defined(SUN4) || defined(SUN4C) 201#if defined(SUN4) || defined(SUN4C)
203 if (CPU_ISSUN4 || CPU_ISSUN4C) { 202 if (CPU_ISSUN4 || CPU_ISSUN4C) {
204 timer_init = timer_init_4; 203 timer_init = timer_init_4;
205 sched_intr_fn = schedintr; 
206 level10.ih_fun = clockintr_4; 204 level10.ih_fun = clockintr_4;
207 level14.ih_fun = statintr_4; 205 level14.ih_fun = statintr_4;
208 cntr.limit = tmr_ustolim(tick); 206 cntr.limit = tmr_ustolim(tick);
209 } 207 }
210#endif 208#endif
211#if defined(SUN4M) 209#if defined(SUN4M)
212 if (CPU_ISSUN4M) { 210 if (CPU_ISSUN4M) {
213 timer_init = timer_init_4m; 211 timer_init = timer_init_4m;
214#if defined(MULTIPROCESSOR) 
215 if (sparc_ncpus > 1) 
216 sched_intr_fn = schedintr_4m; 
217 else 
218#endif 
219 sched_intr_fn = schedintr; 
220 level10.ih_fun = clockintr_4m; 212 level10.ih_fun = clockintr_4m;
221 level14.ih_fun = statintr_4m; 213 level14.ih_fun = statintr_4m;
222 cntr.limit = tmr_ustolim4m(tick); 214 cntr.limit = tmr_ustolim4m(tick);
223 } 215 }
224#endif 216#endif
225 /* link interrupt handlers */ 217 /* link interrupt handlers */
226 intr_establish(10, 0, &level10, NULL, true); 218 intr_establish(10, 0, &level10, NULL, true);
227 intr_establish(14, 0, &level14, NULL, true); 219 intr_establish(14, 0, &level14, NULL, true);
228 220
229 /* Establish a soft interrupt at a lower level for schedclock */ 221 /* Establish a soft interrupt at a lower level for schedclock */
230 sched_cookie = sparc_softintr_establish(IPL_SCHED, sched_intr_fn, NULL); 222 sched_cookie = sparc_softintr_establish(IPL_SCHED, schedintr, NULL);
231 if (sched_cookie == NULL) 223 if (sched_cookie == NULL)
232 panic("timerattach: cannot establish schedintr"); 224 panic("timerattach: cannot establish schedintr");
233 225
234 cntr.cntreg = cntreg; 226 cntr.cntreg = cntreg;
235 cntr.limit >>= cntr.shift; 227 cntr.limit >>= cntr.shift;
236 228
237 tc_init(&counter_timecounter); 229 tc_init(&counter_timecounter);
238} 230}
239 231
240/* 232/*
241 * Both sun4 and sun4m can attach a timer on obio. 233 * Both sun4 and sun4m can attach a timer on obio.
242 * The sun4m OPENPROM calls the timer the "counter". 234 * The sun4m OPENPROM calls the timer the "counter".
243 * The sun4 timer must be probed. 235 * The sun4 timer must be probed.

cvs diff -r1.29 -r1.30 src/sys/arch/sparc/sparc/timer_sun4m.c (expand / switch to unified diff)

--- src/sys/arch/sparc/sparc/timer_sun4m.c 2013/11/16 23:54:01 1.29
+++ src/sys/arch/sparc/sparc/timer_sun4m.c 2014/01/19 00:22:33 1.30
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: timer_sun4m.c,v 1.29 2013/11/16 23:54:01 mrg Exp $ */ 1/* $NetBSD: timer_sun4m.c,v 1.30 2014/01/19 00:22:33 mrg 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.
@@ -48,115 +48,140 @@ @@ -48,115 +48,140 @@
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.29 2013/11/16 23:54:01 mrg Exp $"); 61__KERNEL_RCSID(0, "$NetBSD: timer_sun4m.c,v 1.30 2014/01/19 00:22:33 mrg 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
77struct timer_4m *timerreg4m; 77struct timer_4m *timerreg4m;
78#define counterreg4m cpuinfo.counterreg_4m 78#define counterreg4m cpuinfo.counterreg_4m
79 79
80/* 80/*
 81 * SMP hardclock handler.
 82 */
 83#define IPL_HARDCLOCK 10
 84
 85/*
81 * Set up the real-time and statistics clocks. 86 * Set up the real-time and statistics clocks.
82 * Leave stathz 0 only if no alternative timer is available. 87 * Leave stathz 0 only if no alternative timer is available.
83 * 88 *
84 * The frequencies of these clocks must be an even number of microseconds. 89 * The frequencies of these clocks must be an even number of microseconds.
85 */ 90 */
86void 91void
87timer_init_4m(void) 92timer_init_4m(void)
88{ 93{
89 struct cpu_info *cpi; 94 struct cpu_info *cpi;
90 CPU_INFO_ITERATOR n; 95 CPU_INFO_ITERATOR n;
91 96
92 timerreg4m->t_limit = tmr_ustolim4m(tick); 97 timerreg4m->t_limit = tmr_ustolim4m(tick);
93 for (CPU_INFO_FOREACH(n, cpi)) { 98 for (CPU_INFO_FOREACH(n, cpi)) {
94 cpi->counterreg_4m->t_limit = tmr_ustolim4m(statint); 99 cpi->counterreg_4m->t_limit = tmr_ustolim4m(statint);
95 } 100 }
96 icr_si_bic(SINTR_T); 101 icr_si_bic(SINTR_T);
97} 102}
98 103
99void 104#ifdef MULTIPROCESSOR
100schedintr_4m(void *v) 105/*
 106 * Handle SMP hardclock() calling for this CPU.
 107 */
 108static void
 109hardclock_ipi(void *cap)
101{ 110{
 111 int s = splsched();
102 112
103 kpreempt_disable(); 113 hardclock((struct clockframe *)cap);
 114 splx(s);
 115}
 116#endif
 117
 118/*
 119 * Call hardclock on all CPUs.
 120 */
 121static void
 122handle_hardclock(struct clockframe *cap)
 123{
 124 int s;
104#ifdef MULTIPROCESSOR 125#ifdef MULTIPROCESSOR
105 /* 126 struct cpu_info *cpi;
106 * We call hardclock() here so that we make sure it is called on 127 CPU_INFO_ITERATOR n;
107 * all CPUs. This function ends up being called on sun4m systems 
108 * every tick. 
109 */ 
110 if (!CPU_IS_PRIMARY(curcpu())) 
111 hardclock(v); 
112 128
113 /* 129 for (CPU_INFO_FOREACH(n, cpi)) {
114 * The factor 8 is only valid for stathz==100. 130 if (cpi == cpuinfo.ci_self) {
115 * See also clock.c 131 KASSERT(CPU_IS_PRIMARY(cpi));
116 */ 132 continue;
117 if ((++cpuinfo.ci_schedstate.spc_schedticks & 7) == 0 && schedhz != 0) 133 }
 134
 135 raise_ipi(cpi, IPL_HARDCLOCK);
 136 }
118#endif 137#endif
119 schedclock(curlwp); 138 s = splsched();
120 kpreempt_enable(); 139 hardclock(cap);
 140 splx(s);
121} 141}
122 142
123 
124/* 143/*
125 * Level 10 (clock) interrupts from system counter. 144 * Level 10 (clock) interrupts from system counter.
126 */ 145 */
127int 146int
128clockintr_4m(void *cap) 147clockintr_4m(void *cap)
129{ 148{
130 149
131 KASSERT(CPU_IS_PRIMARY(curcpu())); 
132 /* 150 /*
133 * XXX this needs to be fixed in a more general way 151 * XXX this needs to be fixed in a more general way
134 * problem is that the kernel enables interrupts and THEN 152 * problem is that the kernel enables interrupts and THEN
135 * sets up clocks. In between there's an opportunity to catch 153 * sets up clocks. In between there's an opportunity to catch
136 * a timer interrupt - if we call hardclock() at that point we'll 154 * a timer interrupt - if we call hardclock() at that point we'll
137 * panic 155 * panic
138 * so for now just bail when cold 156 * so for now just bail when cold
139 * 157 *
140 * For MP, we defer calling hardclock() to the schedintr so 158 * For MP, we defer calling hardclock() to the schedintr so
141 * that we call it on all cpus. 159 * that we call it on all cpus.
142 */ 160 */
143 if (cold) 161 if (cold)
144 return 0; 162 return 0;
145 kpreempt_disable(); 163 kpreempt_disable();
146 /* read the limit register to clear the interrupt */ 164 /* read the limit register to clear the interrupt */
147 *((volatile int *)&timerreg4m->t_limit); 165 *((volatile int *)&timerreg4m->t_limit);
148 tickle_tc(); 166 tickle_tc();
149 hardclock((struct clockframe *)cap); 167
 168 /*
 169 * We don't have a system-clock per-cpu, and we'd like to keep
 170 * the per-cpu timer for the statclock, so, send an IPI to
 171 * everyone to call hardclock.
 172 */
 173 handle_hardclock(cap);
 174
150 kpreempt_enable(); 175 kpreempt_enable();
151 return (1); 176 return (1);
152} 177}
153 178
154/* 179/*
155 * Level 14 (stat clock) interrupts from processor counter. 180 * Level 14 (stat clock) interrupts from processor counter.
156 */ 181 */
157int 182int
158statintr_4m(void *cap) 183statintr_4m(void *cap)
159{ 184{
160 struct clockframe *frame = cap; 185 struct clockframe *frame = cap;
161 u_long newint; 186 u_long newint;
162 187
@@ -173,43 +198,39 @@ statintr_4m(void *cap) @@ -173,43 +198,39 @@ statintr_4m(void *cap)
173 newint = new_interval(); 198 newint = new_interval();
174 199
175 /* 200 /*
176 * Use the `non-resetting' limit register, so we don't 201 * Use the `non-resetting' limit register, so we don't
177 * loose the counter ticks that happened since this 202 * loose the counter ticks that happened since this
178 * interrupt was raised. 203 * interrupt was raised.
179 */ 204 */
180 counterreg4m->t_limit_nr = tmr_ustolim4m(newint); 205 counterreg4m->t_limit_nr = tmr_ustolim4m(newint);
181 206
182 /* 207 /*
183 * The factor 8 is only valid for stathz==100. 208 * The factor 8 is only valid for stathz==100.
184 * See also clock.c 209 * See also clock.c
185 */ 210 */
186#if !defined(MULTIPROCESSOR) 
187 if ((++cpuinfo.ci_schedstate.spc_schedticks & 7) == 0 && schedhz != 0) { 211 if ((++cpuinfo.ci_schedstate.spc_schedticks & 7) == 0 && schedhz != 0) {
188#endif 
189 if (CLKF_LOPRI(frame, IPL_SCHED)) { 212 if (CLKF_LOPRI(frame, IPL_SCHED)) {
190 /* No need to schedule a soft interrupt */ 213 /* No need to schedule a soft interrupt */
191 spllowerschedclock(); 214 spllowerschedclock();
192 schedintr_4m(cap); 215 schedintr(cap);
193 } else { 216 } else {
194 /* 217 /*
195 * We're interrupting a thread that may have the 218 * We're interrupting a thread that may have the
196 * scheduler lock; run schedintr_4m() on this CPU later. 219 * scheduler lock; run schedintr() on this CPU later.
197 */ 220 */
198 raise_ipi(&cpuinfo, IPL_SCHED); /* sched_cookie->pil */ 221 raise_ipi(&cpuinfo, IPL_SCHED); /* sched_cookie->pil */
199 } 222 }
200#if !defined(MULTIPROCESSOR) 
201 } 223 }
202#endif 
203 kpreempt_enable(); 224 kpreempt_enable();
204 225
205 return (1); 226 return (1);
206} 227}
207 228
208void 229void
209timerattach_obio_4m(device_t parent, device_t self, void *aux) 230timerattach_obio_4m(device_t parent, device_t self, void *aux)
210{ 231{
211 union obio_attach_args *uoba = aux; 232 union obio_attach_args *uoba = aux;
212 struct sbus_attach_args *sa = &uoba->uoba_sbus; 233 struct sbus_attach_args *sa = &uoba->uoba_sbus;
213 struct cpu_info *cpi; 234 struct cpu_info *cpi;
214 bus_space_handle_t bh; 235 bus_space_handle_t bh;
215 int i; 236 int i;
@@ -251,18 +272,34 @@ timerattach_obio_4m(device_t parent, dev @@ -251,18 +272,34 @@ timerattach_obio_4m(device_t parent, dev
251 272
252 if (sbus_bus_map(sa->sa_bustag, 273 if (sbus_bus_map(sa->sa_bustag,
253 sa->sa_reg[i].oa_space, 274 sa->sa_reg[i].oa_space,
254 sa->sa_reg[i].oa_base, 275 sa->sa_reg[i].oa_base,
255 sizeof(struct timer_4m), 276 sizeof(struct timer_4m),
256 BUS_SPACE_MAP_LINEAR, 277 BUS_SPACE_MAP_LINEAR,
257 &bh) != 0) { 278 &bh) != 0) {
258 printf(": can't map CPU counter %d\n", i); 279 printf(": can't map CPU counter %d\n", i);
259 return; 280 return;
260 } 281 }
261 cpi->counterreg_4m = (struct counter_4m *)bh; 282 cpi->counterreg_4m = (struct counter_4m *)bh;
262 } 283 }
263 284
 285#if defined(MULTIPROCESSOR)
 286 if (sparc_ncpus > 1) {
 287 /*
 288 * Note that we don't actually use this cookie after checking
 289 * it was establised, we call directly via raise_ipi() on
 290 * IPL_HARDCLOCK.
 291 */
 292 void *hardclock_cookie;
 293
 294 hardclock_cookie = sparc_softintr_establish(IPL_HARDCLOCK,
 295 hardclock_ipi, NULL);
 296 if (hardclock_cookie == NULL)
 297 panic("timerattach: cannot establish hardclock_intr");
 298 }
 299#endif
 300
264 /* Put processor counter in "timer" mode */ 301 /* Put processor counter in "timer" mode */
265 timerreg4m->t_cfg = 0; 302 timerreg4m->t_cfg = 0;
266 303
267 timerattach(&timerreg4m->t_counter, &timerreg4m->t_limit); 304 timerattach(&timerreg4m->t_counter, &timerreg4m->t_limit);
268} 305}

cvs diff -r1.11 -r1.12 src/sys/arch/sparc/sparc/timervar.h (expand / switch to unified diff)

--- src/sys/arch/sparc/sparc/timervar.h 2012/07/29 00:04:05 1.11
+++ src/sys/arch/sparc/sparc/timervar.h 2014/01/19 00:22:33 1.12
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: timervar.h,v 1.11 2012/07/29 00:04:05 matt Exp $ */ 1/* $NetBSD: timervar.h,v 1.12 2014/01/19 00:22:33 mrg 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.
@@ -40,43 +40,42 @@ @@ -40,43 +40,42 @@
40 40
41#include "opt_sparc_arch.h" 41#include "opt_sparc_arch.h"
42 42
43#if defined(SUN4) || defined(SUN4C) 43#if defined(SUN4) || defined(SUN4C)
44int clockintr_4(void *); 44int clockintr_4(void *);
45int statintr_4(void *); 45int statintr_4(void *);
46void timer_init_4(void); 46void timer_init_4(void);
47 47
48void timerattach_obio_4(device_t, device_t, void *); 48void timerattach_obio_4(device_t, device_t, void *);
49void timerattach_mainbus_4c(device_t, device_t, void *); 49void timerattach_mainbus_4c(device_t, device_t, void *);
50#endif /* SUN4 || SUN4C */ 50#endif /* SUN4 || SUN4C */
51 51
52#if defined(SUN4M) 52#if defined(SUN4M)
53void schedintr_4m(void *); 
54int clockintr_4m(void *); 53int clockintr_4m(void *);
55int statintr_4m(void *); 54int statintr_4m(void *);
56void timer_init_4m(void); 55void timer_init_4m(void);
57 56
58void timerattach_obio_4m(device_t, device_t, void *); 57void timerattach_obio_4m(device_t, device_t, void *);
59#endif /* SUN4M */ 58#endif /* SUN4M */
60 59
61/* Imported from clock.c: */ 60/* Imported from clock.c: */
62extern int statvar, statmin, statint; 61extern int statvar, statmin, statint;
63extern int timerblurb; 62extern int timerblurb;
64extern void (*timer_init)(void); 63extern void (*timer_init)(void);
65extern void tickle_tc(void); 64extern void tickle_tc(void);
66 65
67/* Common timer attach routine in timer.c: */ 66/* Common timer attach routine in timer.c: */
68void timerattach(volatile int *, volatile int *); 67void timerattach(volatile int *, volatile int *);
69extern void *sched_cookie; /* for schedclock() interrupts */ 68extern void *sched_cookie; /* for schedclock() interrupts */
70 69
71static inline u_long __attribute__((__unused__)) 70static inline u_long __attribute__((__unused__))
72new_interval(void) 71new_interval(void)
73{ 72{
74 u_long newint, r, var; 73 u_long newint, r, var;
75 74
76 /* 75 /*
77 * Compute new randomized interval. The intervals are uniformly 76 * Compute new randomized interval. The intervals are uniformly
78 * distributed on [statint - statvar / 2, statint + statvar / 2], 77 * distributed on [statint - statvar / 2, statint + statvar / 2],
79 * and therefore have mean statint, giving a stathz frequency clock. 78 * and therefore have mean statint, giving a stathz frequency clock.
80 */ 79 */
81 var = statvar; 80 var = statvar;
82 do { 81 do {