e500_intr.c revision 1.11 1 /* $NetBSD: e500_intr.c,v 1.11 2011/06/15 15:11:50 matt Exp $ */
2 /*-
3 * Copyright (c) 2010, 2011 The NetBSD Foundation, Inc.
4 * All rights reserved.
5 *
6 * This code is derived from software contributed to The NetBSD Foundation
7 * by Raytheon BBN Technologies Corp and Defense Advanced Research Projects
8 * Agency and which was developed by Matt Thomas of 3am Software Foundry.
9 *
10 * This material is based upon work supported by the Defense Advanced Research
11 * Projects Agency and Space and Naval Warfare Systems Center, Pacific, under
12 * Contract No. N66001-09-C-2073.
13 * Approved for Public Release, Distribution Unlimited
14 *
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions
17 * are met:
18 * 1. Redistributions of source code must retain the above copyright
19 * notice, this list of conditions and the following disclaimer.
20 * 2. Redistributions in binary form must reproduce the above copyright
21 * notice, this list of conditions and the following disclaimer in the
22 * documentation and/or other materials provided with the distribution.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
25 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
26 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
27 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
28 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 */
36
37 #include "opt_mpc85xx.h"
38
39 #define __INTR_PRIVATE
40
41 #include <sys/param.h>
42 #include <sys/proc.h>
43 #include <sys/intr.h>
44 #include <sys/cpu.h>
45 #include <sys/kmem.h>
46 #include <sys/atomic.h>
47 #include <sys/bus.h>
48 #include <sys/xcall.h>
49 #include <sys/bitops.h>
50
51 #include <uvm/uvm_extern.h>
52
53 #ifdef __HAVE_FAST_SOFTINTS
54 #include <powerpc/softint.h>
55 #endif
56
57 #include <powerpc/spr.h>
58 #include <powerpc/booke/spr.h>
59
60 #include <powerpc/booke/cpuvar.h>
61 #include <powerpc/booke/e500reg.h>
62 #include <powerpc/booke/e500var.h>
63 #include <powerpc/booke/openpicreg.h>
64
65 #define IPL2CTPR(ipl) ((ipl) + 15 - IPL_HIGH)
66 #define CTPR2IPL(ctpr) ((ctpr) - (15 - IPL_HIGH))
67
68 #define IST_PERCPU_P(ist) ((ist) >= IST_TIMER)
69
70 struct e500_intr_irq_info {
71 bus_addr_t irq_vpr;
72 bus_addr_t irq_dr;
73 u_int irq_vector;
74 };
75
76 struct intr_source {
77 int (*is_func)(void *);
78 void *is_arg;
79 int8_t is_ipl;
80 uint8_t is_ist;
81 uint8_t is_irq;
82 bus_size_t is_vpr;
83 bus_size_t is_dr;
84 };
85
86 #define INTR_SOURCE_INITIALIZER \
87 { .is_func = e500_intr_spurious, .is_arg = NULL, \
88 .is_irq = -1, .is_ipl = IPL_NONE, .is_ist = IST_NONE, }
89
90 struct e500_intr_name {
91 uint8_t in_irq;
92 const char in_name[15];
93 };
94
95 static const struct e500_intr_name e500_onchip_intr_names[] = {
96 { ISOURCE_L2, "l2" },
97 { ISOURCE_ECM, "ecm" },
98 { ISOURCE_DDR, "ddr" },
99 { ISOURCE_LBC, "lbc" },
100 { ISOURCE_DMA_CHAN1, "dma-chan1" },
101 { ISOURCE_DMA_CHAN2, "dma-chan2" },
102 { ISOURCE_DMA_CHAN3, "dma-chan3" },
103 { ISOURCE_DMA_CHAN4, "dma-chan4" },
104 { ISOURCE_PCI1, "pci1" },
105 { ISOURCE_PCIEX2, "pcie2" },
106 { ISOURCE_PCIEX , "pcie1" },
107 { ISOURCE_PCIEX3, "pcie3" },
108 { ISOURCE_USB1, "usb1" },
109 { ISOURCE_ETSEC1_TX, "etsec1-tx" },
110 { ISOURCE_ETSEC1_RX, "etsec1-rx" },
111 { ISOURCE_ETSEC3_TX, "etsec3-tx" },
112 { ISOURCE_ETSEC3_RX, "etsec3-rx" },
113 { ISOURCE_ETSEC3_ERR, "etsec3-err" },
114 { ISOURCE_ETSEC1_ERR, "etsec1-err" },
115 { ISOURCE_ETSEC2_TX, "etsec2-tx" },
116 { ISOURCE_ETSEC2_RX, "etsec2-rx" },
117 { ISOURCE_ETSEC4_TX, "etsec4-tx" },
118 { ISOURCE_ETSEC4_RX, "etsec4-rx" },
119 { ISOURCE_ETSEC4_ERR, "etsec4-err" },
120 { ISOURCE_ETSEC2_ERR, "etsec2-err" },
121 { ISOURCE_DUART, "duart" },
122 { ISOURCE_I2C, "i2c" },
123 { ISOURCE_PERFMON, "perfmon" },
124 { ISOURCE_SECURITY1, "sec1" },
125 { ISOURCE_GPIO, "gpio" },
126 { ISOURCE_SRIO_EWPU, "srio-ewpu" },
127 { ISOURCE_SRIO_ODBELL, "srio-odbell" },
128 { ISOURCE_SRIO_IDBELL, "srio-idbell" },
129 { ISOURCE_SRIO_OMU1, "srio-omu1" },
130 { ISOURCE_SRIO_IMU1, "srio-imu1" },
131 { ISOURCE_SRIO_OMU2, "srio-omu2" },
132 { ISOURCE_SRIO_IMU2, "srio-imu2" },
133 { ISOURCE_SECURITY2, "sec2" },
134 { ISOURCE_SPI, "spi" },
135 { ISOURCE_ETSEC1_PTP, "etsec1-ptp" },
136 { ISOURCE_ETSEC2_PTP, "etsec2-ptp" },
137 { ISOURCE_ETSEC3_PTP, "etsec3-ptp" },
138 { ISOURCE_ETSEC4_PTP, "etsec4-ptp" },
139 { ISOURCE_ESDHC, "esdhc" },
140 { 0, "" },
141 };
142
143 const struct e500_intr_name default_external_intr_names[] = {
144 { 0, "" },
145 };
146
147 static const struct e500_intr_name e500_msigroup_intr_names[] = {
148 { 0, "msigroup0" },
149 { 1, "msigroup1" },
150 { 2, "msigroup2" },
151 { 3, "msigroup3" },
152 { 4, "msigroup4" },
153 { 5, "msigroup5" },
154 { 6, "msigroup6" },
155 { 7, "msigroup7" },
156 { 0, "" },
157 };
158
159 static const struct e500_intr_name e500_timer_intr_names[] = {
160 { 0, "timer0" },
161 { 1, "timer1" },
162 { 2, "timer2" },
163 { 3, "timer3" },
164 { 0, "" },
165 };
166
167 static const struct e500_intr_name e500_ipi_intr_names[] = {
168 { 0, "ipi0" },
169 { 1, "ipi1" },
170 { 2, "ipi2" },
171 { 3, "ipi3" },
172 { 0, "" },
173 };
174
175 static const struct e500_intr_name e500_mi_intr_names[] = {
176 { 0, "mi0" },
177 { 1, "mi1" },
178 { 2, "mi2" },
179 { 3, "mi3" },
180 { 0, "" },
181 };
182
183 struct e500_intr_info {
184 u_int ii_external_sources;
185 uint32_t ii_onchip_bitmap[2];
186 u_int ii_onchip_sources;
187 u_int ii_msigroup_sources;
188 u_int ii_ipi_sources; /* per-cpu */
189 u_int ii_timer_sources; /* per-cpu */
190 u_int ii_mi_sources; /* per-cpu */
191 u_int ii_percpu_sources;
192 const struct e500_intr_name *ii_external_intr_names;
193 const struct e500_intr_name *ii_onchip_intr_names;
194 u_int8_t ii_ist_vectors[IST_MAX+1];
195 };
196
197 static kmutex_t e500_intr_lock __cacheline_aligned;
198 static struct e500_intr_info e500_intr_info;
199
200 #define INTR_INFO_DECL(lc_chip, UC_CHIP) \
201 static const struct e500_intr_info lc_chip##_intr_info = { \
202 .ii_external_sources = UC_CHIP ## _EXTERNALSOURCES, \
203 .ii_onchip_bitmap = UC_CHIP ## _ONCHIPBITMAP, \
204 .ii_onchip_sources = UC_CHIP ## _ONCHIPSOURCES, \
205 .ii_msigroup_sources = UC_CHIP ## _MSIGROUPSOURCES, \
206 .ii_timer_sources = UC_CHIP ## _TIMERSOURCES, \
207 .ii_ipi_sources = UC_CHIP ## _IPISOURCES, \
208 .ii_mi_sources = UC_CHIP ## _MISOURCES, \
209 .ii_percpu_sources = UC_CHIP ## _TIMERSOURCES \
210 + UC_CHIP ## _IPISOURCES + UC_CHIP ## _MISOURCES, \
211 .ii_external_intr_names = lc_chip ## _external_intr_names, \
212 .ii_onchip_intr_names = lc_chip ## _onchip_intr_names, \
213 .ii_ist_vectors = { \
214 [IST_NONE] = ~0, \
215 [IST_EDGE] = 0, \
216 [IST_LEVEL_LOW] = 0, \
217 [IST_LEVEL_HIGH] = 0, \
218 [IST_PULSE] = 0, \
219 [IST_ONCHIP] = UC_CHIP ## _EXTERNALSOURCES, \
220 [IST_MSIGROUP] = UC_CHIP ## _EXTERNALSOURCES \
221 + UC_CHIP ## _ONCHIPSOURCES, \
222 [IST_TIMER] = UC_CHIP ## _EXTERNALSOURCES \
223 + UC_CHIP ## _ONCHIPSOURCES \
224 + UC_CHIP ## _MSIGROUPSOURCES, \
225 [IST_IPI] = UC_CHIP ## _EXTERNALSOURCES \
226 + UC_CHIP ## _ONCHIPSOURCES \
227 + UC_CHIP ## _MSIGROUPSOURCES \
228 + UC_CHIP ## _TIMERSOURCES, \
229 [IST_MI] = UC_CHIP ## _EXTERNALSOURCES \
230 + UC_CHIP ## _ONCHIPSOURCES \
231 + UC_CHIP ## _MSIGROUPSOURCES \
232 + UC_CHIP ## _TIMERSOURCES \
233 + UC_CHIP ## _IPISOURCES, \
234 [IST_MAX] = UC_CHIP ## _EXTERNALSOURCES \
235 + UC_CHIP ## _ONCHIPSOURCES \
236 + UC_CHIP ## _MSIGROUPSOURCES \
237 + UC_CHIP ## _TIMERSOURCES \
238 + UC_CHIP ## _IPISOURCES \
239 + UC_CHIP ## _MISOURCES, \
240 }, \
241 }
242
243 #ifdef MPC8536
244 #define mpc8536_external_intr_names default_external_intr_names
245 const struct e500_intr_name mpc8536_onchip_intr_names[] = {
246 { ISOURCE_SATA2, "sata2" },
247 { ISOURCE_USB2, "usb2" },
248 { ISOURCE_USB3, "usb3" },
249 { ISOURCE_SATA1, "sata1" },
250 { 0, "" },
251 };
252
253 INTR_INFO_DECL(mpc8536, MPC8536);
254 #endif
255
256 #ifdef MPC8544
257 #define mpc8544_external_intr_names default_external_intr_names
258 const struct e500_intr_name mpc8544_onchip_intr_names[] = {
259 { 0, "" },
260 };
261
262 INTR_INFO_DECL(mpc8544, MPC8544);
263 #endif
264 #ifdef MPC8548
265 #define mpc8548_external_intr_names default_external_intr_names
266 const struct e500_intr_name mpc8548_onchip_intr_names[] = {
267 { ISOURCE_PCI1, "pci1" },
268 { ISOURCE_PCI2, "pci2" },
269 { 0, "" },
270 };
271
272 INTR_INFO_DECL(mpc8548, MPC8548);
273 #endif
274 #ifdef MPC8555
275 #define mpc8555_external_intr_names default_external_intr_names
276 const struct e500_intr_name mpc8555_onchip_intr_names[] = {
277 { ISOURCE_PCI2, "pci2" },
278 { ISOURCE_CPM, "CPM" },
279 { 0, "" },
280 };
281
282 INTR_INFO_DECL(mpc8555, MPC8555);
283 #endif
284 #ifdef MPC8568
285 #define mpc8568_external_intr_names default_external_intr_names
286 const struct e500_intr_name mpc8568_onchip_intr_names[] = {
287 { ISOURCE_QEB_LOW, "QEB low" },
288 { ISOURCE_QEB_PORT, "QEB port" },
289 { ISOURCE_QEB_IECC, "QEB iram ecc" },
290 { ISOURCE_QEB_MUECC, "QEB ram ecc" },
291 { ISOURCE_TLU1, "tlu1" },
292 { ISOURCE_QEB_HIGH, "QEB high" },
293 { 0, "" },
294 };
295
296 INTR_INFO_DECL(mpc8568, MPC8568);
297 #endif
298 #ifdef MPC8572
299 #define mpc8572_external_intr_names default_external_intr_names
300 const struct e500_intr_name mpc8572_onchip_intr_names[] = {
301 { ISOURCE_PCIEX3_MPC8572, "pcie3" },
302 { ISOURCE_FEC, "fec" },
303 { ISOURCE_PME_GENERAL, "pme" },
304 { ISOURCE_TLU1, "tlu1" },
305 { ISOURCE_TLU2, "tlu2" },
306 { ISOURCE_PME_CHAN1, "pme-chan1" },
307 { ISOURCE_PME_CHAN2, "pme-chan2" },
308 { ISOURCE_PME_CHAN3, "pme-chan3" },
309 { ISOURCE_PME_CHAN4, "pme-chan4" },
310 { ISOURCE_DMA2_CHAN1, "dma2-chan1" },
311 { ISOURCE_DMA2_CHAN2, "dma2-chan2" },
312 { ISOURCE_DMA2_CHAN3, "dma2-chan3" },
313 { ISOURCE_DMA2_CHAN4, "dma2-chan4" },
314 { 0, "" },
315 };
316
317 INTR_INFO_DECL(mpc8572, MPC8572);
318 #endif
319 #ifdef P2020
320 #define p20x0_external_intr_names default_external_intr_names
321 const struct e500_intr_name p20x0_onchip_intr_names[] = {
322 { ISOURCE_PCIEX3_MPC8572, "pcie3" },
323 { ISOURCE_DMA2_CHAN1, "dma2-chan1" },
324 { ISOURCE_DMA2_CHAN2, "dma2-chan2" },
325 { ISOURCE_DMA2_CHAN3, "dma2-chan3" },
326 { ISOURCE_DMA2_CHAN4, "dma2-chan4" },
327 { 0, "" },
328 };
329
330 INTR_INFO_DECL(p20x0, P20x0);
331 #endif
332
333 static const char ist_names[][12] = {
334 [IST_NONE] = "none",
335 [IST_EDGE] = "edge",
336 [IST_LEVEL_LOW] = "level-",
337 [IST_LEVEL_HIGH] = "level+",
338 [IST_PULSE] = "pulse",
339 [IST_MSI] = "msi",
340 [IST_ONCHIP] = "onchip",
341 [IST_MSIGROUP] = "msigroup",
342 [IST_TIMER] = "timer",
343 [IST_IPI] = "ipi",
344 [IST_MI] = "msgint",
345 };
346
347 static struct intr_source *e500_intr_sources;
348 static const struct intr_source *e500_intr_last_source;
349
350 static void *e500_intr_establish(int, int, int, int (*)(void *), void *);
351 static void e500_intr_disestablish(void *);
352 static void e500_intr_cpu_attach(struct cpu_info *ci);
353 static void e500_intr_cpu_hatch(struct cpu_info *ci);
354 static void e500_intr_cpu_send_ipi(cpuid_t, uintptr_t);
355 static void e500_intr_init(void);
356 static const char *e500_intr_string(int, int);
357 static const char *e500_intr_typename(int);
358 static void e500_critintr(struct trapframe *tf);
359 static void e500_decrintr(struct trapframe *tf);
360 static void e500_extintr(struct trapframe *tf);
361 static void e500_fitintr(struct trapframe *tf);
362 static void e500_wdogintr(struct trapframe *tf);
363 static void e500_spl0(void);
364 static int e500_splraise(int);
365 static void e500_splx(int);
366
367 const struct intrsw e500_intrsw = {
368 .intrsw_establish = e500_intr_establish,
369 .intrsw_disestablish = e500_intr_disestablish,
370 .intrsw_init = e500_intr_init,
371 .intrsw_cpu_attach = e500_intr_cpu_attach,
372 .intrsw_cpu_hatch = e500_intr_cpu_hatch,
373 .intrsw_cpu_send_ipi = e500_intr_cpu_send_ipi,
374 .intrsw_string = e500_intr_string,
375 .intrsw_typename = e500_intr_typename,
376
377 .intrsw_critintr = e500_critintr,
378 .intrsw_decrintr = e500_decrintr,
379 .intrsw_extintr = e500_extintr,
380 .intrsw_fitintr = e500_fitintr,
381 .intrsw_wdogintr = e500_wdogintr,
382
383 .intrsw_splraise = e500_splraise,
384 .intrsw_splx = e500_splx,
385 .intrsw_spl0 = e500_spl0,
386
387 #ifdef __HAVE_FAST_SOFTINTS
388 .intrsw_softint_init_md = powerpc_softint_init_md,
389 .intrsw_softint_trigger = powerpc_softint_trigger,
390 #endif
391 };
392
393 static inline uint32_t
394 openpic_read(struct cpu_softc *cpu, bus_size_t offset)
395 {
396
397 return bus_space_read_4(cpu->cpu_bst, cpu->cpu_bsh,
398 OPENPIC_BASE + offset);
399 }
400
401 static inline void
402 openpic_write(struct cpu_softc *cpu, bus_size_t offset, uint32_t val)
403 {
404
405 return bus_space_write_4(cpu->cpu_bst, cpu->cpu_bsh,
406 OPENPIC_BASE + offset, val);
407 }
408
409 static const char *
410 e500_intr_external_name_lookup(int irq)
411 {
412 prop_array_t extirqs = board_info_get_object("external-irqs");
413 prop_string_t irqname = prop_array_get(extirqs, irq);
414 KASSERT(irqname != NULL);
415 KASSERT(prop_object_type(irqname) == PROP_TYPE_STRING);
416
417 return prop_string_cstring_nocopy(irqname);
418 }
419
420 static const char *
421 e500_intr_name_lookup(const struct e500_intr_name *names, int irq)
422 {
423 for (; names->in_name[0] != '\0'; names++) {
424 if (names->in_irq == irq)
425 return names->in_name;
426 }
427
428 return NULL;
429 }
430
431 static const char *
432 e500_intr_onchip_name_lookup(int irq)
433 {
434 const char *name;
435
436 name = e500_intr_name_lookup(e500_intr_info.ii_onchip_intr_names, irq);
437 if (name == NULL)
438 name = e500_intr_name_lookup(e500_onchip_intr_names, irq);
439
440 return name;
441 }
442
443 static inline void
444 e500_splset(struct cpu_info *ci, int ipl)
445 {
446 struct cpu_softc * const cpu = ci->ci_softc;
447 //KASSERT(!cpu_intr_p() || ipl >= IPL_VM);
448 KASSERT((curlwp->l_pflag & LP_INTR) == 0 || ipl != IPL_NONE);
449 #if 0
450 u_int ctpr = ipl;
451 KASSERT(openpic_read(cpu, OPENPIC_CTPR) == ci->ci_cpl);
452 #elif 0
453 u_int old_ctpr = (ci->ci_cpl >= IPL_VM ? 15 : ci->ci_cpl);
454 u_int ctpr = (ipl >= IPL_VM ? 15 : ipl);
455 KASSERT(openpic_read(cpu, OPENPIC_CTPR) == old_ctpr);
456 #else
457 #ifdef DIAGNOSTIC
458 u_int old_ctpr = IPL2CTPR(ci->ci_cpl);
459 #endif
460 u_int ctpr = IPL2CTPR(ipl);
461 KASSERT(openpic_read(cpu, OPENPIC_CTPR) == old_ctpr);
462 #endif
463 openpic_write(cpu, OPENPIC_CTPR, ctpr);
464 KASSERT(openpic_read(cpu, OPENPIC_CTPR) == ctpr);
465 ci->ci_cpl = ipl;
466 }
467
468 static void
469 e500_spl0(void)
470 {
471 struct cpu_info * const ci = curcpu();
472
473 wrtee(0);
474
475 #ifdef __HAVE_FAST_SOFTINTS
476 if (__predict_false(ci->ci_data.cpu_softints != 0)) {
477 e500_splset(ci, IPL_HIGH);
478 powerpc_softint(ci, IPL_NONE,
479 (vaddr_t)__builtin_return_address(0));
480 }
481 #endif /* __HAVE_FAST_SOFTINTS */
482 e500_splset(ci, IPL_NONE);
483
484 wrtee(PSL_EE);
485 }
486
487 static void
488 e500_splx(int ipl)
489 {
490 struct cpu_info * const ci = curcpu();
491 const int old_ipl = ci->ci_cpl;
492
493 KASSERT(mfmsr() & PSL_CE);
494
495 if (ipl == old_ipl)
496 return;
497
498 if (__predict_false(ipl > old_ipl)) {
499 printf("%s: %p: cpl=%u: ignoring splx(%u) to raise ipl\n",
500 __func__, __builtin_return_address(0), old_ipl, ipl);
501 if (old_ipl == IPL_NONE)
502 Debugger();
503 }
504
505 // const
506 register_t msr = wrtee(0);
507 #ifdef __HAVE_FAST_SOFTINTS
508 const u_int softints = (ci->ci_data.cpu_softints << ipl) & IPL_SOFTMASK;
509 if (__predict_false(softints != 0)) {
510 e500_splset(ci, IPL_HIGH);
511 powerpc_softint(ci, ipl,
512 (vaddr_t)__builtin_return_address(0));
513 }
514 #endif /* __HAVE_FAST_SOFTINTS */
515 e500_splset(ci, ipl);
516 #if 1
517 if (ipl < IPL_VM && old_ipl >= IPL_VM)
518 msr = PSL_EE;
519 #endif
520 wrtee(msr);
521 }
522
523 static int
524 e500_splraise(int ipl)
525 {
526 struct cpu_info * const ci = curcpu();
527 const int old_ipl = ci->ci_cpl;
528
529 KASSERT(mfmsr() & PSL_CE);
530
531 if (old_ipl < ipl) {
532 //const
533 register_t msr = wrtee(0);
534 e500_splset(ci, ipl);
535 #if 1
536 if (old_ipl < IPL_VM && ipl >= IPL_VM)
537 msr = 0;
538 #endif
539 wrtee(msr);
540 } else if (ipl == IPL_NONE) {
541 panic("%s: %p: cpl=%u: attempt to splraise(IPL_NONE)",
542 __func__, __builtin_return_address(0), old_ipl);
543 #if 0
544 } else if (old_ipl > ipl) {
545 printf("%s: %p: cpl=%u: ignoring splraise(%u) to lower ipl\n",
546 __func__, __builtin_return_address(0), old_ipl, ipl);
547 #endif
548 }
549
550 return old_ipl;
551 }
552
553 static int
554 e500_intr_spurious(void *arg)
555 {
556 return 0;
557 }
558
559 static bool
560 e500_intr_irq_info_get(struct cpu_info *ci, u_int irq, int ipl, int ist,
561 struct e500_intr_irq_info *ii)
562 {
563 const struct e500_intr_info * const info = &e500_intr_info;
564 bool ok;
565
566 #if DEBUG > 2
567 printf("%s(%p,irq=%u,ipl=%u,ist=%u,%p)\n", __func__, ci, irq, ipl, ist, ii);
568 #endif
569
570 if (ipl < IPL_VM || ipl > IPL_HIGH) {
571 #if DEBUG > 2
572 printf("%s:%d ipl=%u\n", __func__, __LINE__, ipl);
573 #endif
574 return false;
575 }
576
577 if (ist <= IST_NONE || ist >= IST_MAX) {
578 #if DEBUG > 2
579 printf("%s:%d ist=%u\n", __func__, __LINE__, ist);
580 #endif
581 return false;
582 }
583
584 ii->irq_vector = irq + info->ii_ist_vectors[ist];
585 if (IST_PERCPU_P(ist) && ist != IST_IPI)
586 ii->irq_vector += ci->ci_cpuid * info->ii_percpu_sources;
587
588 switch (ist) {
589 default:
590 ii->irq_vpr = OPENPIC_EIVPR(irq);
591 ii->irq_dr = OPENPIC_EIDR(irq);
592 ok = irq < info->ii_external_sources
593 && (ist == IST_EDGE
594 || ist == IST_LEVEL_LOW
595 || ist == IST_LEVEL_HIGH);
596 break;
597 case IST_PULSE:
598 ok = false;
599 break;
600 case IST_ONCHIP:
601 ii->irq_vpr = OPENPIC_IIVPR(irq);
602 ii->irq_dr = OPENPIC_IIDR(irq);
603 ok = irq < 32 * __arraycount(info->ii_onchip_bitmap);
604 #if DEBUG > 2
605 printf("%s: irq=%u: ok=%u\n", __func__, irq, ok);
606 #endif
607 ok = ok && (info->ii_onchip_bitmap[irq/32] & (1 << (irq & 31)));
608 #if DEBUG > 2
609 printf("%s: %08x%08x -> %08x%08x: ok=%u\n", __func__,
610 irq < 32 ? 0 : (1 << irq), irq < 32 ? (1 << irq) : 0,
611 info->ii_onchip_bitmap[1], info->ii_onchip_bitmap[0],
612 ok);
613 #endif
614 break;
615 case IST_MSIGROUP:
616 ii->irq_vpr = OPENPIC_MSIVPR(irq);
617 ii->irq_dr = OPENPIC_MSIDR(irq);
618 ok = irq < info->ii_msigroup_sources
619 && ipl == IPL_VM;
620 break;
621 case IST_TIMER:
622 ii->irq_vpr = OPENPIC_GTVPR(ci->ci_cpuid, irq);
623 ii->irq_dr = OPENPIC_GTDR(ci->ci_cpuid, irq);
624 ok = irq < info->ii_timer_sources;
625 #if DEBUG > 2
626 printf("%s: IST_TIMER irq=%u: ok=%u\n", __func__, irq, ok);
627 #endif
628 break;
629 case IST_IPI:
630 ii->irq_vpr = OPENPIC_IPIVPR(irq);
631 ii->irq_dr = OPENPIC_IPIDR(irq);
632 ok = irq < info->ii_ipi_sources;
633 break;
634 case IST_MI:
635 ii->irq_vpr = OPENPIC_MIVPR(irq);
636 ii->irq_dr = OPENPIC_MIDR(irq);
637 ok = irq < info->ii_mi_sources;
638 break;
639 }
640
641 return ok;
642 }
643
644 static const char *
645 e500_intr_string(int irq, int ist)
646 {
647 struct cpu_info * const ci = curcpu();
648 struct cpu_softc * const cpu = ci->ci_softc;
649 struct e500_intr_irq_info ii;
650
651 if (!e500_intr_irq_info_get(ci, irq, IPL_VM, ist, &ii))
652 return NULL;
653
654 return cpu->cpu_evcnt_intrs[ii.irq_vector].ev_name;
655 }
656
657 __CTASSERT(__arraycount(ist_names) == IST_MAX);
658
659 static const char *
660 e500_intr_typename(int ist)
661 {
662 if (IST_NONE <= ist && ist < IST_MAX)
663 return ist_names[ist];
664
665 return NULL;
666 }
667
668 static void *
669 e500_intr_cpu_establish(struct cpu_info *ci, int irq, int ipl, int ist,
670 int (*handler)(void *), void *arg)
671 {
672 struct cpu_softc * const cpu = ci->ci_softc;
673 struct e500_intr_irq_info ii;
674
675 KASSERT(ipl >= IPL_VM && ipl <= IPL_HIGH);
676 KASSERT(ist > IST_NONE && ist < IST_MAX && ist != IST_MSI);
677
678 if (!e500_intr_irq_info_get(ci, irq, ipl, ist, &ii)) {
679 printf("%s: e500_intr_irq_info_get(%p,%u,%u,%u,%p) failed\n",
680 __func__, ci, irq, ipl, ist, &ii);
681 return NULL;
682 }
683
684 struct intr_source * const is = &e500_intr_sources[ii.irq_vector];
685 mutex_enter(&e500_intr_lock);
686 if (is->is_ipl != IPL_NONE)
687 return NULL;
688
689 is->is_func = handler;
690 is->is_arg = arg;
691 is->is_ipl = ipl;
692 is->is_ist = ist;
693 is->is_irq = irq;
694 is->is_vpr = ii.irq_vpr;
695 is->is_dr = ii.irq_dr;
696
697 uint32_t vpr = VPR_PRIORITY_MAKE(IPL2CTPR(ipl))
698 | VPR_VECTOR_MAKE(((ii.irq_vector + 1) << 4) | ipl)
699 | (ist == IST_LEVEL_LOW
700 ? VPR_LEVEL_LOW
701 : (ist == IST_LEVEL_HIGH
702 ? VPR_LEVEL_HIGH
703 : (ist == IST_ONCHIP
704 ? VPR_P_HIGH
705 : 0)));
706
707 /*
708 * All interrupts go to the primary except per-cpu interrupts which get
709 * routed to the appropriate cpu.
710 */
711 uint32_t dr = openpic_read(cpu, ii.irq_dr);
712
713 dr |= 1 << (IST_PERCPU_P(ist) ? ci->ci_cpuid : 0);
714
715 /*
716 * Update the vector/priority and destination registers keeping the
717 * interrupt masked.
718 */
719 const register_t msr = wrtee(0); /* disable interrupts */
720 openpic_write(cpu, ii.irq_vpr, vpr | VPR_MSK);
721 openpic_write(cpu, ii.irq_dr, dr);
722
723 /*
724 * Now unmask the interrupt.
725 */
726 openpic_write(cpu, ii.irq_vpr, vpr);
727
728 wrtee(msr); /* re-enable interrupts */
729
730 mutex_exit(&e500_intr_lock);
731
732 return is;
733 }
734
735 static void *
736 e500_intr_establish(int irq, int ipl, int ist,
737 int (*handler)(void *), void *arg)
738 {
739 return e500_intr_cpu_establish(curcpu(), irq, ipl, ist, handler, arg);
740 }
741
742 static void
743 e500_intr_disestablish(void *vis)
744 {
745 struct cpu_softc * const cpu = curcpu()->ci_softc;
746 struct intr_source * const is = vis;
747 struct e500_intr_irq_info ii;
748
749 KASSERT(e500_intr_sources <= is);
750 KASSERT(is < e500_intr_last_source);
751 KASSERT(!cpu_intr_p());
752
753 bool ok = e500_intr_irq_info_get(curcpu(), is->is_irq, is->is_ipl,
754 is->is_ist, &ii);
755 (void)ok; /* appease gcc */
756 KASSERT(ok);
757 KASSERT(is - e500_intr_sources == ii.irq_vector);
758
759 mutex_enter(&e500_intr_lock);
760 /*
761 * Mask the source using the mask (MSK) bit in the vector/priority reg.
762 */
763 uint32_t vpr = openpic_read(cpu, ii.irq_vpr);
764 openpic_write(cpu, ii.irq_vpr, VPR_MSK | vpr);
765
766 /*
767 * Wait for the Activity (A) bit for the source to be cleared.
768 */
769 while (openpic_read(cpu, ii.irq_vpr) & VPR_A)
770 ;
771
772 /*
773 * Now the source can be modified.
774 */
775 openpic_write(cpu, ii.irq_dr, 0); /* stop delivery */
776 openpic_write(cpu, ii.irq_vpr, VPR_MSK); /* mask/reset it */
777
778 *is = (struct intr_source)INTR_SOURCE_INITIALIZER;
779
780 mutex_exit(&e500_intr_lock);
781 }
782
783 static void
784 e500_critintr(struct trapframe *tf)
785 {
786 panic("%s: srr0/srr1=%#lx/%#lx", __func__, tf->tf_srr0, tf->tf_srr1);
787 }
788
789 static void
790 e500_decrintr(struct trapframe *tf)
791 {
792 panic("%s: srr0/srr1=%#lx/%#lx", __func__, tf->tf_srr0, tf->tf_srr1);
793 }
794
795 static void
796 e500_fitintr(struct trapframe *tf)
797 {
798 panic("%s: srr0/srr1=%#lx/%#lx", __func__, tf->tf_srr0, tf->tf_srr1);
799 }
800
801 static void
802 e500_wdogintr(struct trapframe *tf)
803 {
804 mtspr(SPR_TSR, TSR_ENW|TSR_WIS);
805 panic("%s: tf=%p tb=%"PRId64" srr0/srr1=%#lx/%#lx", __func__, tf,
806 mftb(), tf->tf_srr0, tf->tf_srr1);
807 }
808
809 static void
810 e500_extintr(struct trapframe *tf)
811 {
812 struct cpu_info * const ci = curcpu();
813 struct cpu_softc * const cpu = ci->ci_softc;
814 const int old_ipl = ci->ci_cpl;
815
816 KASSERT(mfmsr() & PSL_CE);
817
818 #if 0
819 // printf("%s(%p): idepth=%d enter\n", __func__, tf, ci->ci_idepth);
820 if ((register_t)tf >= (register_t)curlwp->l_addr + USPACE
821 || (register_t)tf < (register_t)curlwp->l_addr + NBPG) {
822 printf("%s(entry): pid %d.%d (%s): srr0/srr1=%#lx/%#lx: invalid tf addr %p\n",
823 __func__, curlwp->l_proc->p_pid, curlwp->l_lid,
824 curlwp->l_proc->p_comm, tf->tf_srr0, tf->tf_srr1, tf);
825 }
826 #endif
827
828
829 ci->ci_data.cpu_nintr++;
830 tf->tf_cf.cf_idepth = ci->ci_idepth++;
831 cpu->cpu_pcpls[ci->ci_idepth] = old_ipl;
832 #if 1
833 if (mfmsr() & PSL_EE)
834 panic("%s(%p): MSR[EE] is on (%#lx)!", __func__, tf, mfmsr());
835 if (old_ipl == IPL_HIGH
836 || IPL2CTPR(old_ipl) != openpic_read(cpu, OPENPIC_CTPR))
837 panic("%s(%p): old_ipl(%u) == IPL_HIGH(%u) "
838 "|| old_ipl + %u != OPENPIC_CTPR (%u)",
839 __func__, tf, old_ipl, IPL_HIGH,
840 15 - IPL_HIGH, openpic_read(cpu, OPENPIC_CTPR));
841 #else
842 if (old_ipl >= IPL_VM)
843 panic("%s(%p): old_ipl(%u) >= IPL_VM(%u) CTPR=%u",
844 __func__, tf, old_ipl, IPL_VM, openpic_read(cpu, OPENPIC_CTPR));
845 #endif
846
847 for (;;) {
848 /*
849 * Find out the pending interrupt.
850 */
851 if (mfmsr() & PSL_EE)
852 panic("%s(%p): MSR[EE] turned on (%#lx)!", __func__, tf, mfmsr());
853 if (IPL2CTPR(old_ipl) != openpic_read(cpu, OPENPIC_CTPR))
854 panic("%s(%p): %d: old_ipl(%u) + %u != OPENPIC_CTPR (%u)",
855 __func__, tf, __LINE__, old_ipl,
856 15 - IPL_HIGH, openpic_read(cpu, OPENPIC_CTPR));
857 const uint32_t iack = openpic_read(cpu, OPENPIC_IACK);
858 #ifdef DIAGNOSTIC
859 const int ipl = iack & 0xf;
860 #endif
861 const int irq = (iack >> 4) - 1;
862 #if 0
863 printf("%s: iack=%d ipl=%d irq=%d <%s>\n",
864 __func__, iack, ipl, irq,
865 (iack != IRQ_SPURIOUS ?
866 cpu->cpu_evcnt_intrs[irq].ev_name : "spurious"));
867 #endif
868 if (IPL2CTPR(old_ipl) != openpic_read(cpu, OPENPIC_CTPR))
869 panic("%s(%p): %d: old_ipl(%u) + %u != OPENPIC_CTPR (%u)",
870 __func__, tf, __LINE__, old_ipl,
871 15 - IPL_HIGH, openpic_read(cpu, OPENPIC_CTPR));
872 if (iack == IRQ_SPURIOUS)
873 break;
874
875 struct intr_source * const is = &e500_intr_sources[irq];
876 if (__predict_true(is < e500_intr_last_source)) {
877 /*
878 * Timer interrupts get their argument overriden with
879 * the pointer to the trapframe.
880 */
881 KASSERT(is->is_ipl == ipl);
882 void *arg = (is->is_ist == IST_TIMER ? tf : is->is_arg);
883 if (is->is_ipl <= old_ipl)
884 panic("%s(%p): %s (%u): is->is_ipl (%u) <= old_ipl (%u)\n",
885 __func__, tf,
886 cpu->cpu_evcnt_intrs[irq].ev_name, irq,
887 is->is_ipl, old_ipl);
888 KASSERT(is->is_ipl > old_ipl);
889 e500_splset(ci, is->is_ipl); /* change IPL */
890 if (__predict_false(is->is_func == NULL)) {
891 aprint_error_dev(ci->ci_dev,
892 "interrupt from unestablished irq %d\n",
893 irq);
894 } else {
895 int (*func)(void *) = is->is_func;
896 wrtee(PSL_EE);
897 int rv = (*func)(arg);
898 wrtee(0);
899 #if DEBUG > 2
900 printf("%s: %s handler %p(%p) returned %d\n",
901 __func__,
902 cpu->cpu_evcnt_intrs[irq].ev_name,
903 func, arg, rv);
904 #endif
905 if (rv == 0)
906 cpu->cpu_evcnt_spurious_intr.ev_count++;
907 }
908 e500_splset(ci, old_ipl); /* restore IPL */
909 cpu->cpu_evcnt_intrs[irq].ev_count++;
910 } else {
911 aprint_error_dev(ci->ci_dev,
912 "interrupt from illegal irq %d\n", irq);
913 cpu->cpu_evcnt_spurious_intr.ev_count++;
914 }
915 /*
916 * If this is a nested interrupt, simply ack it and exit
917 * because the loop we interrupted will complete looking
918 * for interrupts.
919 */
920 if (mfmsr() & PSL_EE)
921 panic("%s(%p): MSR[EE] left on (%#lx)!", __func__, tf, mfmsr());
922 if (IPL2CTPR(old_ipl) != openpic_read(cpu, OPENPIC_CTPR))
923 panic("%s(%p): %d: old_ipl(%u) + %u != OPENPIC_CTPR (%u)",
924 __func__, tf, __LINE__, old_ipl,
925 15 - IPL_HIGH, openpic_read(cpu, OPENPIC_CTPR));
926
927 openpic_write(cpu, OPENPIC_EOI, 0);
928 if (IPL2CTPR(old_ipl) != openpic_read(cpu, OPENPIC_CTPR))
929 panic("%s(%p): %d: old_ipl(%u) + %u != OPENPIC_CTPR (%u)",
930 __func__, tf, __LINE__, old_ipl,
931 15 - IPL_HIGH, openpic_read(cpu, OPENPIC_CTPR));
932 if (ci->ci_idepth > 0)
933 break;
934 }
935
936 ci->ci_idepth--;
937
938 #ifdef __HAVE_FAST_SOFTINTS
939 /*
940 * Before exiting, deal with any softints that need to be dealt with.
941 */
942 const u_int softints = (ci->ci_data.cpu_softints << old_ipl) & IPL_SOFTMASK;
943 if (__predict_false(softints != 0)) {
944 KASSERT(old_ipl < IPL_VM);
945 e500_splset(ci, IPL_HIGH); /* pop to high */
946 powerpc_softint(ci, old_ipl, /* deal with them */
947 tf->tf_srr0);
948 e500_splset(ci, old_ipl); /* and drop back */
949 }
950 #endif /* __HAVE_FAST_SOFTINTS */
951 #if 1
952 KASSERT(ci->ci_cpl == old_ipl);
953 #else
954 e500_splset(ci, old_ipl); /* and drop back */
955 #endif
956
957 // printf("%s(%p): idepth=%d exit\n", __func__, tf, ci->ci_idepth);
958 }
959
960 static void
961 e500_intr_init(void)
962 {
963 struct cpu_info * const ci = curcpu();
964 struct cpu_softc * const cpu = ci->ci_softc;
965 const uint32_t frr = openpic_read(cpu, OPENPIC_FRR);
966 const u_int nirq = FRR_NIRQ_GET(frr) + 1;
967 // const u_int ncpu = FRR_NCPU_GET(frr) + 1;
968 struct intr_source *is;
969 struct e500_intr_info * const ii = &e500_intr_info;
970
971 const uint16_t svr = (mfspr(SPR_SVR) & ~0x80000) >> 16;
972 switch (svr) {
973 #ifdef MPC8536
974 case SVR_MPC8536v1 >> 16:
975 *ii = mpc8536_intr_info;
976 break;
977 #endif
978 #ifdef MPC8544
979 case SVR_MPC8544v1 >> 16:
980 *ii = mpc8544_intr_info;
981 break;
982 #endif
983 #ifdef MPC8548
984 case SVR_MPC8543v1 >> 16:
985 case SVR_MPC8548v1 >> 16:
986 *ii = mpc8548_intr_info;
987 break;
988 #endif
989 #ifdef MPC8555
990 case SVR_MPC8541v1 >> 16:
991 case SVR_MPC8555v1 >> 16:
992 *ii = mpc8555_intr_info;
993 break;
994 #endif
995 #ifdef MPC8568
996 case SVR_MPC8568v1 >> 16:
997 *ii = mpc8568_intr_info;
998 break;
999 #endif
1000 #ifdef MPC8572
1001 case SVR_MPC8572v1 >> 16:
1002 *ii = mpc8572_intr_info;
1003 break;
1004 #endif
1005 #ifdef P2020
1006 case SVR_P2010v2 >> 16:
1007 case SVR_P2020v2 >> 16:
1008 *ii = p20x0_intr_info;
1009 break;
1010 #endif
1011 default:
1012 panic("%s: don't know how to deal with SVR %#lx",
1013 __func__, mfspr(SPR_SVR));
1014 }
1015
1016 /*
1017 * We need to be in mixed mode.
1018 */
1019 openpic_write(cpu, OPENPIC_GCR, GCR_M);
1020
1021 /*
1022 * Make we and the openpic both agree about the current SPL level.
1023 */
1024 e500_splset(ci, ci->ci_cpl);
1025
1026 /*
1027 * Allow the required number of interrupt sources.
1028 */
1029 is = kmem_zalloc(nirq * sizeof(*is), KM_SLEEP);
1030 KASSERT(is);
1031 e500_intr_sources = is;
1032 e500_intr_last_source = is + nirq;
1033
1034 /*
1035 * Initialize all the external interrupts as active low.
1036 */
1037 for (u_int irq = 0; irq < e500_intr_info.ii_external_sources; irq++) {
1038 openpic_write(cpu, OPENPIC_EIVPR(irq),
1039 VPR_VECTOR_MAKE(irq) | VPR_LEVEL_LOW);
1040 }
1041 }
1042
1043 static void
1044 e500_idlespin(void)
1045 {
1046 KASSERTMSG(curcpu()->ci_cpl == IPL_NONE,
1047 ("%s: cpu%u: ci_cpl (%d) != 0", __func__, cpu_number(),
1048 curcpu()->ci_cpl));
1049 KASSERTMSG(CTPR2IPL(openpic_read(curcpu()->ci_softc, OPENPIC_CTPR)) == IPL_NONE,
1050 ("%s: cpu%u: CTPR (%d) != IPL_NONE", __func__, cpu_number(),
1051 CTPR2IPL(openpic_read(curcpu()->ci_softc, OPENPIC_CTPR))));
1052 KASSERT(mfmsr() & PSL_EE);
1053 }
1054
1055 static void
1056 e500_intr_cpu_attach(struct cpu_info *ci)
1057 {
1058 struct cpu_softc * const cpu = ci->ci_softc;
1059 const char * const xname = device_xname(ci->ci_dev);
1060
1061 const u_int32_t frr = openpic_read(cpu, OPENPIC_FRR);
1062 const u_int nirq = FRR_NIRQ_GET(frr) + 1;
1063 // const u_int ncpu = FRR_NCPU_GET(frr) + 1;
1064
1065 const struct e500_intr_info * const info = &e500_intr_info;
1066
1067 cpu->cpu_clock_gtbcr = OPENPIC_GTBCR(ci->ci_cpuid, E500_CLOCK_TIMER);
1068
1069 cpu->cpu_evcnt_intrs =
1070 kmem_zalloc(nirq * sizeof(cpu->cpu_evcnt_intrs[0]), KM_SLEEP);
1071 KASSERT(cpu->cpu_evcnt_intrs);
1072
1073 struct evcnt *evcnt = cpu->cpu_evcnt_intrs;
1074 for (size_t j = 0; j < info->ii_external_sources; j++, evcnt++) {
1075 const char *name = e500_intr_external_name_lookup(j);
1076 evcnt_attach_dynamic(evcnt, EVCNT_TYPE_INTR, NULL, xname, name);
1077 }
1078 KASSERT(evcnt == cpu->cpu_evcnt_intrs + info->ii_ist_vectors[IST_ONCHIP]);
1079 for (size_t j = 0; j < info->ii_onchip_sources; j++, evcnt++) {
1080 if (info->ii_onchip_bitmap[j / 32] & __BIT(j & 31)) {
1081 const char *name = e500_intr_onchip_name_lookup(j);
1082 if (name != NULL) {
1083 evcnt_attach_dynamic(evcnt, EVCNT_TYPE_INTR,
1084 NULL, xname, name);
1085 #ifdef DIAGNOSTIC
1086 } else {
1087 printf("%s: missing evcnt for onchip irq %zu\n",
1088 __func__, j);
1089 #endif
1090 }
1091 }
1092 }
1093
1094 KASSERT(evcnt == cpu->cpu_evcnt_intrs + info->ii_ist_vectors[IST_MSIGROUP]);
1095 for (size_t j = 0; j < info->ii_msigroup_sources; j++, evcnt++) {
1096 evcnt_attach_dynamic(evcnt, EVCNT_TYPE_INTR,
1097 NULL, xname, e500_msigroup_intr_names[j].in_name);
1098 }
1099
1100 KASSERT(evcnt == cpu->cpu_evcnt_intrs + info->ii_ist_vectors[IST_TIMER]);
1101 evcnt += ci->ci_cpuid * info->ii_percpu_sources;
1102 for (size_t j = 0; j < info->ii_timer_sources; j++, evcnt++) {
1103 evcnt_attach_dynamic(evcnt, EVCNT_TYPE_INTR,
1104 NULL, xname, e500_timer_intr_names[j].in_name);
1105 }
1106
1107 for (size_t j = 0; j < info->ii_ipi_sources; j++, evcnt++) {
1108 evcnt_attach_dynamic(evcnt, EVCNT_TYPE_INTR,
1109 NULL, xname, e500_ipi_intr_names[j].in_name);
1110 }
1111
1112 for (size_t j = 0; j < info->ii_mi_sources; j++, evcnt++) {
1113 evcnt_attach_dynamic(evcnt, EVCNT_TYPE_INTR,
1114 NULL, xname, e500_mi_intr_names[j].in_name);
1115 }
1116
1117 ci->ci_idlespin = e500_idlespin;
1118 }
1119
1120 static void
1121 e500_intr_cpu_send_ipi(cpuid_t target, uint32_t ipimsg)
1122 {
1123 struct cpu_info * const ci = curcpu();
1124 struct cpu_softc * const cpu = ci->ci_softc;
1125 uint32_t dstmask;
1126
1127 if (target >= ncpu) {
1128 CPU_INFO_ITERATOR cii;
1129 struct cpu_info *dst_ci;
1130
1131 KASSERT(target == IPI_DST_NOTME || target == IPI_DST_ALL);
1132
1133 dstmask = 0;
1134 for (CPU_INFO_FOREACH(cii, dst_ci)) {
1135 if (target == IPI_DST_ALL || ci != dst_ci) {
1136 dstmask |= 1 << cpu_index(ci);
1137 if (ipimsg)
1138 atomic_or_32(&dst_ci->ci_pending_ipis,
1139 ipimsg);
1140 }
1141 }
1142 } else {
1143 struct cpu_info * const dst_ci = cpu_lookup(target);
1144 KASSERT(target == cpu_index(dst_ci));
1145 dstmask = (1 << target);
1146 if (ipimsg)
1147 atomic_or_32(&dst_ci->ci_pending_ipis, ipimsg);
1148 }
1149
1150 openpic_write(cpu, OPENPIC_IPIDR(0), dstmask);
1151 }
1152
1153 typedef void (*ipifunc_t)(void);
1154
1155 #ifdef __HAVE_PREEEMPTION
1156 static void
1157 e500_ipi_kpreempt(void)
1158 {
1159 poowerpc_softint_trigger(1 << IPL_NONE);
1160 }
1161 #endif
1162
1163 static const ipifunc_t e500_ipifuncs[] = {
1164 [ilog2(IPI_XCALL)] = xc_ipi_handler,
1165 [ilog2(IPI_HALT)] = e500_ipi_halt,
1166 #ifdef __HAVE_PREEMPTION
1167 [ilog2(IPI_KPREEMPT)] = e500_ipi_kpreempt,
1168 #endif
1169 [ilog2(IPI_TLB1SYNC)] = e500_tlb1_sync,
1170 };
1171
1172 static int
1173 e500_ipi_intr(void *v)
1174 {
1175 struct cpu_info * const ci = curcpu();
1176
1177 ci->ci_ev_ipi.ev_count++;
1178
1179 uint32_t pending_ipis = atomic_swap_32(&ci->ci_pending_ipis, 0);
1180 for (u_int ipi = 31; pending_ipis != 0; ipi--, pending_ipis <<= 1) {
1181 const u_int bits = __builtin_clz(pending_ipis);
1182 ipi -= bits;
1183 pending_ipis <<= bits;
1184 KASSERT(e500_ipifuncs[ipi] != NULL);
1185 (*e500_ipifuncs[ipi])();
1186 }
1187
1188 return 1;
1189 }
1190
1191 static void
1192 e500_intr_cpu_hatch(struct cpu_info *ci)
1193 {
1194 /*
1195 * Establish clock interrupt for this CPU.
1196 */
1197 if (e500_intr_cpu_establish(ci, E500_CLOCK_TIMER, IPL_CLOCK, IST_TIMER,
1198 e500_clock_intr, NULL) == NULL)
1199 panic("%s: failed to establish clock interrupt!", __func__);
1200
1201 /*
1202 * Establish the IPI interrupts for this CPU.
1203 */
1204 if (e500_intr_cpu_establish(ci, 0, IPL_VM, IST_IPI, e500_ipi_intr,
1205 NULL) == NULL)
1206 panic("%s: failed to establish ipi interrupt!", __func__);
1207
1208 /*
1209 * Enable watchdog interrupts.
1210 */
1211 uint32_t tcr = mfspr(SPR_TCR);
1212 tcr |= TCR_WIE;
1213 mtspr(SPR_TCR, tcr);
1214 }
1215