Print this page
7127 remove -Wno-missing-braces from Makefile.uts
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/i86pc/io/cbe.c
+++ new/usr/src/uts/i86pc/io/cbe.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 25 */
26 26
27 27 #include <sys/systm.h>
28 28 #include <sys/cyclic.h>
29 29 #include <sys/cyclic_impl.h>
30 30 #include <sys/spl.h>
31 31 #include <sys/x_call.h>
32 32 #include <sys/kmem.h>
33 33 #include <sys/machsystm.h>
34 34 #include <sys/smp_impldefs.h>
35 35 #include <sys/psm_types.h>
36 36 #include <sys/psm.h>
37 37 #include <sys/atomic.h>
38 38 #include <sys/clock.h>
39 39 #include <sys/x86_archext.h>
40 40 #include <sys/ddi_impldefs.h>
41 41 #include <sys/ddi_intr.h>
42 42 #include <sys/avintr.h>
43 43 #include <sys/note.h>
44 44
45 45 static int cbe_vector;
46 46 static int cbe_ticks = 0;
47 47
48 48 /*
↓ open down ↓ |
48 lines elided |
↑ open up ↑ |
49 49 * cbe_xcall_lock is used to protect the xcall globals since the cyclic
50 50 * reprogramming API does not use cpu_lock.
51 51 */
52 52 static kmutex_t cbe_xcall_lock;
53 53 static cyc_func_t volatile cbe_xcall_func;
54 54 static cpu_t *volatile cbe_xcall_cpu;
55 55 static void *cbe_xcall_farg;
56 56 static cpuset_t cbe_enabled;
57 57
58 58 static ddi_softint_hdl_impl_t cbe_low_hdl =
59 - {0, NULL, NULL, NULL, 0, NULL, NULL, NULL};
59 + {NULL, 0, {{NULL}}, NULL, NULL, NULL, NULL, NULL};
60 60 static ddi_softint_hdl_impl_t cbe_clock_hdl =
61 - {0, NULL, NULL, NULL, 0, NULL, NULL, NULL};
61 + {NULL, 0, {{NULL}}, NULL, NULL, NULL, NULL, NULL};
62 62
63 63 cyclic_id_t cbe_hres_cyclic;
64 64 int cbe_psm_timer_mode = TIMER_ONESHOT;
65 65 static hrtime_t cbe_timer_resolution;
66 66
67 67 extern int tsc_gethrtime_enable;
68 68
69 69 void cbe_hres_tick(void);
70 70
71 71 int
72 72 cbe_softclock(void)
73 73 {
74 74 cyclic_softint(CPU, CY_LOCK_LEVEL);
75 75 return (1);
76 76 }
77 77
78 78 int
79 79 cbe_low_level(void)
80 80 {
81 81 cpu_t *cpu = CPU;
82 82
83 83 cyclic_softint(cpu, CY_LOW_LEVEL);
84 84 return (1);
85 85 }
86 86
87 87 /*
88 88 * We can be in cbe_fire() either due to a cyclic-induced cross call, or due
89 89 * to the timer firing at level-14. Because cyclic_fire() can tolerate
90 90 * spurious calls, it would not matter if we called cyclic_fire() in both
91 91 * cases.
92 92 */
93 93 int
94 94 cbe_fire(void)
95 95 {
96 96 cpu_t *cpu = CPU;
97 97 processorid_t me = cpu->cpu_id, i;
98 98 int cross_call = (cbe_xcall_func != NULL && cbe_xcall_cpu == cpu);
99 99
100 100 cyclic_fire(cpu);
101 101
102 102 if (cbe_psm_timer_mode != TIMER_ONESHOT && me == 0 && !cross_call) {
103 103 for (i = 1; i < NCPU; i++) {
104 104 if (CPU_IN_SET(cbe_enabled, i)) {
105 105 send_dirint(i, CBE_HIGH_PIL);
106 106 }
107 107 }
108 108 }
109 109
110 110 if (cross_call) {
111 111 ASSERT(cbe_xcall_func != NULL && cbe_xcall_cpu == cpu);
112 112 (*cbe_xcall_func)(cbe_xcall_farg);
113 113 cbe_xcall_func = NULL;
114 114 cbe_xcall_cpu = NULL;
115 115 }
116 116
117 117 return (1);
118 118 }
119 119
120 120 /*ARGSUSED*/
121 121 void
122 122 cbe_softint(void *arg, cyc_level_t level)
123 123 {
124 124 switch (level) {
125 125 case CY_LOW_LEVEL:
126 126 (*setsoftint)(CBE_LOW_PIL, cbe_low_hdl.ih_pending);
127 127 break;
128 128 case CY_LOCK_LEVEL:
129 129 (*setsoftint)(CBE_LOCK_PIL, cbe_clock_hdl.ih_pending);
130 130 break;
131 131 default:
132 132 panic("cbe_softint: unexpected soft level %d", level);
133 133 }
134 134 }
135 135
136 136 /*ARGSUSED*/
137 137 void
138 138 cbe_reprogram(void *arg, hrtime_t time)
139 139 {
140 140 if (cbe_psm_timer_mode == TIMER_ONESHOT)
141 141 (*psm_timer_reprogram)(time);
142 142 }
143 143
144 144 /*ARGSUSED*/
145 145 cyc_cookie_t
146 146 cbe_set_level(void *arg, cyc_level_t level)
147 147 {
148 148 int ipl;
149 149
150 150 switch (level) {
151 151 case CY_LOW_LEVEL:
152 152 ipl = CBE_LOW_PIL;
153 153 break;
154 154 case CY_LOCK_LEVEL:
155 155 ipl = CBE_LOCK_PIL;
156 156 break;
157 157 case CY_HIGH_LEVEL:
158 158 ipl = CBE_HIGH_PIL;
159 159 break;
160 160 default:
161 161 panic("cbe_set_level: unexpected level %d", level);
162 162 }
163 163
164 164 return (splr(ipltospl(ipl)));
165 165 }
166 166
167 167 /*ARGSUSED*/
168 168 void
169 169 cbe_restore_level(void *arg, cyc_cookie_t cookie)
170 170 {
171 171 splx(cookie);
172 172 }
173 173
174 174 /*ARGSUSED*/
175 175 void
176 176 cbe_xcall(void *arg, cpu_t *dest, cyc_func_t func, void *farg)
177 177 {
178 178 kpreempt_disable();
179 179
180 180 if (dest == CPU) {
181 181 (*func)(farg);
182 182 kpreempt_enable();
183 183 return;
184 184 }
185 185
186 186 mutex_enter(&cbe_xcall_lock);
187 187
188 188 ASSERT(cbe_xcall_func == NULL);
189 189
190 190 cbe_xcall_farg = farg;
191 191 membar_producer();
192 192 cbe_xcall_cpu = dest;
193 193 cbe_xcall_func = func;
194 194
195 195 send_dirint(dest->cpu_id, CBE_HIGH_PIL);
196 196
197 197 while (cbe_xcall_func != NULL || cbe_xcall_cpu != NULL)
198 198 continue;
199 199
200 200 mutex_exit(&cbe_xcall_lock);
201 201
202 202 kpreempt_enable();
203 203 }
204 204
205 205 void *
206 206 cbe_configure(cpu_t *cpu)
207 207 {
208 208 return (cpu);
209 209 }
210 210
211 211 void
212 212 cbe_unconfigure(void *arg)
213 213 {
214 214 _NOTE(ARGUNUSED(arg));
215 215 ASSERT(!CPU_IN_SET(cbe_enabled, ((cpu_t *)arg)->cpu_id));
216 216 }
217 217
218 218 #ifndef __xpv
219 219 /*
220 220 * declarations needed for time adjustment
221 221 */
222 222 extern void tsc_suspend(void);
223 223 extern void tsc_resume(void);
224 224 /*
225 225 * Call the resume function in the cyclic, instead of inline in the
226 226 * resume path.
227 227 */
228 228 extern int tsc_resume_in_cyclic;
229 229 #endif
230 230
231 231 /*ARGSUSED*/
232 232 static void
233 233 cbe_suspend(cyb_arg_t arg)
234 234 {
235 235 #ifndef __xpv
236 236 /*
237 237 * This is an x86 backend, so let the tsc_suspend
238 238 * that is specific to x86 platforms do the work.
239 239 */
240 240 tsc_suspend();
241 241 #endif
242 242 }
243 243
244 244 /*ARGSUSED*/
245 245 static void
246 246 cbe_resume(cyb_arg_t arg)
247 247 {
248 248 #ifndef __xpv
249 249 if (tsc_resume_in_cyclic) {
250 250 tsc_resume();
251 251 }
252 252 #endif
253 253 }
254 254
255 255 void
256 256 cbe_enable(void *arg)
257 257 {
258 258 processorid_t me = ((cpu_t *)arg)->cpu_id;
259 259
260 260 /* neither enable nor disable cpu0 if TIMER_PERIODIC is set */
261 261 if ((cbe_psm_timer_mode != TIMER_ONESHOT) && (me == 0))
262 262 return;
263 263
264 264 /*
265 265 * Added (me == 0) to the ASSERT because the timer isn't
266 266 * disabled on CPU 0, and cbe_enable is called when we resume.
267 267 */
268 268 ASSERT((me == 0) || !CPU_IN_SET(cbe_enabled, me));
269 269 CPUSET_ADD(cbe_enabled, me);
270 270 if (cbe_psm_timer_mode == TIMER_ONESHOT)
271 271 (*psm_timer_enable)();
272 272 }
273 273
274 274 void
275 275 cbe_disable(void *arg)
276 276 {
277 277 processorid_t me = ((cpu_t *)arg)->cpu_id;
278 278
279 279 /* neither enable nor disable cpu0 if TIMER_PERIODIC is set */
280 280 if ((cbe_psm_timer_mode != TIMER_ONESHOT) && (me == 0))
281 281 return;
282 282
283 283 ASSERT(CPU_IN_SET(cbe_enabled, me));
284 284 CPUSET_DEL(cbe_enabled, me);
285 285 if (cbe_psm_timer_mode == TIMER_ONESHOT)
286 286 (*psm_timer_disable)();
287 287 }
288 288
289 289 /*
290 290 * Unbound cyclic, called once per tick (every nsec_per_tick ns).
291 291 */
292 292 void
293 293 cbe_hres_tick(void)
294 294 {
295 295 int s;
296 296
297 297 dtrace_hres_tick();
298 298
299 299 /*
300 300 * Because hres_tick effectively locks hres_lock, we must be at the
301 301 * same PIL as that used for CLOCK_LOCK.
302 302 */
303 303 s = splr(ipltospl(XC_HI_PIL));
304 304 hres_tick();
305 305 splx(s);
306 306
307 307 if ((cbe_ticks % hz) == 0)
308 308 (*hrtime_tick)();
309 309
310 310 cbe_ticks++;
311 311
312 312 }
313 313
314 314 void
315 315 cbe_init_pre(void)
316 316 {
317 317 cbe_vector = (*psm_get_clockirq)(CBE_HIGH_PIL);
318 318
319 319 CPUSET_ZERO(cbe_enabled);
320 320
321 321 cbe_timer_resolution = (*clkinitf)(TIMER_ONESHOT, &cbe_psm_timer_mode);
322 322 }
323 323
324 324 void
325 325 cbe_init(void)
326 326 {
327 327 cyc_backend_t cbe = {
328 328 cbe_configure, /* cyb_configure */
329 329 cbe_unconfigure, /* cyb_unconfigure */
330 330 cbe_enable, /* cyb_enable */
331 331 cbe_disable, /* cyb_disable */
332 332 cbe_reprogram, /* cyb_reprogram */
333 333 cbe_softint, /* cyb_softint */
334 334 cbe_set_level, /* cyb_set_level */
335 335 cbe_restore_level, /* cyb_restore_level */
336 336 cbe_xcall, /* cyb_xcall */
337 337 cbe_suspend, /* cyb_suspend */
338 338 cbe_resume /* cyb_resume */
339 339 };
340 340 cyc_handler_t hdlr;
341 341 cyc_time_t when;
342 342
343 343 mutex_init(&cbe_xcall_lock, NULL, MUTEX_DEFAULT, NULL);
344 344
345 345 mutex_enter(&cpu_lock);
346 346 cyclic_init(&cbe, cbe_timer_resolution);
347 347 mutex_exit(&cpu_lock);
348 348
349 349 (void) add_avintr(NULL, CBE_HIGH_PIL, (avfunc)cbe_fire,
350 350 "cbe_fire_master", cbe_vector, 0, NULL, NULL, NULL);
351 351
352 352 if (psm_get_ipivect != NULL) {
353 353 (void) add_avintr(NULL, CBE_HIGH_PIL, (avfunc)cbe_fire,
354 354 "cbe_fire_slave",
355 355 (*psm_get_ipivect)(CBE_HIGH_PIL, PSM_INTR_IPI_HI),
356 356 0, NULL, NULL, NULL);
357 357 }
358 358
359 359 (void) add_avsoftintr((void *)&cbe_clock_hdl, CBE_LOCK_PIL,
360 360 (avfunc)cbe_softclock, "softclock", NULL, NULL);
361 361
362 362 (void) add_avsoftintr((void *)&cbe_low_hdl, CBE_LOW_PIL,
363 363 (avfunc)cbe_low_level, "low level", NULL, NULL);
364 364
365 365 mutex_enter(&cpu_lock);
366 366
367 367 hdlr.cyh_level = CY_HIGH_LEVEL;
368 368 hdlr.cyh_func = (cyc_func_t)cbe_hres_tick;
369 369 hdlr.cyh_arg = NULL;
370 370
371 371 when.cyt_when = 0;
372 372 when.cyt_interval = nsec_per_tick;
373 373
374 374 cbe_hres_cyclic = cyclic_add(&hdlr, &when);
375 375
376 376 if (psm_post_cyclic_setup != NULL)
377 377 (*psm_post_cyclic_setup)(NULL);
378 378
379 379 mutex_exit(&cpu_lock);
380 380 }
↓ open down ↓ |
309 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX