e500_intr.c revision 1.12 1 /* $NetBSD: e500_intr.c,v 1.12 2011/06/21 06:24:25 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 u_int ctpr = IPL2CTPR(ipl);
458 KASSERT(openpic_read(cpu, OPENPIC_CTPR) == IPL2CTPR(ci->ci_cpl));
459 #endif
460 openpic_write(cpu, OPENPIC_CTPR, ctpr);
461 KASSERT(openpic_read(cpu, OPENPIC_CTPR) == ctpr);
462 ci->ci_cpl = ipl;
463 }
464
465 static void
466 e500_spl0(void)
467 {
468 wrtee(0);
469
470 struct cpu_info * const ci = curcpu();
471
472 #ifdef __HAVE_FAST_SOFTINTS
473 if (__predict_false(ci->ci_data.cpu_softints != 0)) {
474 e500_splset(ci, IPL_HIGH);
475 powerpc_softint(ci, IPL_NONE,
476 (vaddr_t)__builtin_return_address(0));
477 }
478 #endif /* __HAVE_FAST_SOFTINTS */
479 e500_splset(ci, IPL_NONE);
480
481 wrtee(PSL_EE);
482 }
483
484 static void
485 e500_splx(int ipl)
486 {
487 struct cpu_info * const ci = curcpu();
488 const int old_ipl = ci->ci_cpl;
489
490 KASSERT(mfmsr() & PSL_CE);
491
492 if (ipl == old_ipl)
493 return;
494
495 if (__predict_false(ipl > old_ipl)) {
496 printf("%s: %p: cpl=%u: ignoring splx(%u) to raise ipl\n",
497 __func__, __builtin_return_address(0), old_ipl, ipl);
498 if (old_ipl == IPL_NONE)
499 Debugger();
500 }
501
502 // const
503 register_t msr = wrtee(0);
504 #ifdef __HAVE_FAST_SOFTINTS
505 const u_int softints = (ci->ci_data.cpu_softints << ipl) & IPL_SOFTMASK;
506 if (__predict_false(softints != 0)) {
507 e500_splset(ci, IPL_HIGH);
508 powerpc_softint(ci, ipl,
509 (vaddr_t)__builtin_return_address(0));
510 }
511 #endif /* __HAVE_FAST_SOFTINTS */
512 e500_splset(ci, ipl);
513 #if 1
514 if (ipl < IPL_VM && old_ipl >= IPL_VM)
515 msr = PSL_EE;
516 #endif
517 wrtee(msr);
518 }
519
520 static int
521 e500_splraise(int ipl)
522 {
523 struct cpu_info * const ci = curcpu();
524 const int old_ipl = ci->ci_cpl;
525
526 KASSERT(mfmsr() & PSL_CE);
527
528 if (old_ipl < ipl) {
529 //const
530 register_t msr = wrtee(0);
531 e500_splset(ci, ipl);
532 #if 1
533 if (old_ipl < IPL_VM && ipl >= IPL_VM)
534 msr = 0;
535 #endif
536 wrtee(msr);
537 } else if (ipl == IPL_NONE) {
538 panic("%s: %p: cpl=%u: attempt to splraise(IPL_NONE)",
539 __func__, __builtin_return_address(0), old_ipl);
540 #if 0
541 } else if (old_ipl > ipl) {
542 printf("%s: %p: cpl=%u: ignoring splraise(%u) to lower ipl\n",
543 __func__, __builtin_return_address(0), old_ipl, ipl);
544 #endif
545 }
546
547 return old_ipl;
548 }
549
550 static int
551 e500_intr_spurious(void *arg)
552 {
553 return 0;
554 }
555
556 static bool
557 e500_intr_irq_info_get(struct cpu_info *ci, u_int irq, int ipl, int ist,
558 struct e500_intr_irq_info *ii)
559 {
560 const struct e500_intr_info * const info = &e500_intr_info;
561 bool ok;
562
563 #if DEBUG > 2
564 printf("%s(%p,irq=%u,ipl=%u,ist=%u,%p)\n", __func__, ci, irq, ipl, ist, ii);
565 #endif
566
567 if (ipl < IPL_VM || ipl > IPL_HIGH) {
568 #if DEBUG > 2
569 printf("%s:%d ipl=%u\n", __func__, __LINE__, ipl);
570 #endif
571 return false;
572 }
573
574 if (ist <= IST_NONE || ist >= IST_MAX) {
575 #if DEBUG > 2
576 printf("%s:%d ist=%u\n", __func__, __LINE__, ist);
577 #endif
578 return false;
579 }
580
581 ii->irq_vector = irq + info->ii_ist_vectors[ist];
582 if (IST_PERCPU_P(ist) && ist != IST_IPI)
583 ii->irq_vector += ci->ci_cpuid * info->ii_percpu_sources;
584
585 switch (ist) {
586 default:
587 ii->irq_vpr = OPENPIC_EIVPR(irq);
588 ii->irq_dr = OPENPIC_EIDR(irq);
589 ok = irq < info->ii_external_sources
590 && (ist == IST_EDGE
591 || ist == IST_LEVEL_LOW
592 || ist == IST_LEVEL_HIGH);
593 break;
594 case IST_PULSE:
595 ok = false;
596 break;
597 case IST_ONCHIP:
598 ii->irq_vpr = OPENPIC_IIVPR(irq);
599 ii->irq_dr = OPENPIC_IIDR(irq);
600 ok = irq < 32 * __arraycount(info->ii_onchip_bitmap);
601 #if DEBUG > 2
602 printf("%s: irq=%u: ok=%u\n", __func__, irq, ok);
603 #endif
604 ok = ok && (info->ii_onchip_bitmap[irq/32] & (1 << (irq & 31)));
605 #if DEBUG > 2
606 printf("%s: %08x%08x -> %08x%08x: ok=%u\n", __func__,
607 irq < 32 ? 0 : (1 << irq), irq < 32 ? (1 << irq) : 0,
608 info->ii_onchip_bitmap[1], info->ii_onchip_bitmap[0],
609 ok);
610 #endif
611 break;
612 case IST_MSIGROUP:
613 ii->irq_vpr = OPENPIC_MSIVPR(irq);
614 ii->irq_dr = OPENPIC_MSIDR(irq);
615 ok = irq < info->ii_msigroup_sources
616 && ipl == IPL_VM;
617 break;
618 case IST_TIMER:
619 ii->irq_vpr = OPENPIC_GTVPR(ci->ci_cpuid, irq);
620 ii->irq_dr = OPENPIC_GTDR(ci->ci_cpuid, irq);
621 ok = irq < info->ii_timer_sources;
622 #if DEBUG > 2
623 printf("%s: IST_TIMER irq=%u: ok=%u\n", __func__, irq, ok);
624 #endif
625 break;
626 case IST_IPI:
627 ii->irq_vpr = OPENPIC_IPIVPR(irq);
628 ii->irq_dr = OPENPIC_IPIDR(irq);
629 ok = irq < info->ii_ipi_sources;
630 break;
631 case IST_MI:
632 ii->irq_vpr = OPENPIC_MIVPR(irq);
633 ii->irq_dr = OPENPIC_MIDR(irq);
634 ok = irq < info->ii_mi_sources;
635 break;
636 }
637
638 return ok;
639 }
640
641 static const char *
642 e500_intr_string(int irq, int ist)
643 {
644 struct cpu_info * const ci = curcpu();
645 struct cpu_softc * const cpu = ci->ci_softc;
646 struct e500_intr_irq_info ii;
647
648 if (!e500_intr_irq_info_get(ci, irq, IPL_VM, ist, &ii))
649 return NULL;
650
651 return cpu->cpu_evcnt_intrs[ii.irq_vector].ev_name;
652 }
653
654 __CTASSERT(__arraycount(ist_names) == IST_MAX);
655
656 static const char *
657 e500_intr_typename(int ist)
658 {
659 if (IST_NONE <= ist && ist < IST_MAX)
660 return ist_names[ist];
661
662 return NULL;
663 }
664
665 static void *
666 e500_intr_cpu_establish(struct cpu_info *ci, int irq, int ipl, int ist,
667 int (*handler)(void *), void *arg)
668 {
669 struct cpu_softc * const cpu = ci->ci_softc;
670 struct e500_intr_irq_info ii;
671
672 KASSERT(ipl >= IPL_VM && ipl <= IPL_HIGH);
673 KASSERT(ist > IST_NONE && ist < IST_MAX && ist != IST_MSI);
674
675 if (!e500_intr_irq_info_get(ci, irq, ipl, ist, &ii)) {
676 printf("%s: e500_intr_irq_info_get(%p,%u,%u,%u,%p) failed\n",
677 __func__, ci, irq, ipl, ist, &ii);
678 return NULL;
679 }
680
681 struct intr_source * const is = &e500_intr_sources[ii.irq_vector];
682 mutex_enter(&e500_intr_lock);
683 if (is->is_ipl != IPL_NONE)
684 return NULL;
685
686 is->is_func = handler;
687 is->is_arg = arg;
688 is->is_ipl = ipl;
689 is->is_ist = ist;
690 is->is_irq = irq;
691 is->is_vpr = ii.irq_vpr;
692 is->is_dr = ii.irq_dr;
693
694 uint32_t vpr = VPR_PRIORITY_MAKE(IPL2CTPR(ipl))
695 | VPR_VECTOR_MAKE(((ii.irq_vector + 1) << 4) | ipl)
696 | (ist == IST_LEVEL_LOW
697 ? VPR_LEVEL_LOW
698 : (ist == IST_LEVEL_HIGH
699 ? VPR_LEVEL_HIGH
700 : (ist == IST_ONCHIP
701 ? VPR_P_HIGH
702 : 0)));
703
704 /*
705 * All interrupts go to the primary except per-cpu interrupts which get
706 * routed to the appropriate cpu.
707 */
708 uint32_t dr = openpic_read(cpu, ii.irq_dr);
709
710 dr |= 1 << (IST_PERCPU_P(ist) ? ci->ci_cpuid : 0);
711
712 /*
713 * Update the vector/priority and destination registers keeping the
714 * interrupt masked.
715 */
716 const register_t msr = wrtee(0); /* disable interrupts */
717 openpic_write(cpu, ii.irq_vpr, vpr | VPR_MSK);
718 openpic_write(cpu, ii.irq_dr, dr);
719
720 /*
721 * Now unmask the interrupt.
722 */
723 openpic_write(cpu, ii.irq_vpr, vpr);
724
725 wrtee(msr); /* re-enable interrupts */
726
727 mutex_exit(&e500_intr_lock);
728
729 return is;
730 }
731
732 static void *
733 e500_intr_establish(int irq, int ipl, int ist,
734 int (*handler)(void *), void *arg)
735 {
736 return e500_intr_cpu_establish(curcpu(), irq, ipl, ist, handler, arg);
737 }
738
739 static void
740 e500_intr_disestablish(void *vis)
741 {
742 struct cpu_softc * const cpu = curcpu()->ci_softc;
743 struct intr_source * const is = vis;
744 struct e500_intr_irq_info ii;
745
746 KASSERT(e500_intr_sources <= is);
747 KASSERT(is < e500_intr_last_source);
748 KASSERT(!cpu_intr_p());
749
750 bool ok = e500_intr_irq_info_get(curcpu(), is->is_irq, is->is_ipl,
751 is->is_ist, &ii);
752 (void)ok; /* appease gcc */
753 KASSERT(ok);
754 KASSERT(is - e500_intr_sources == ii.irq_vector);
755
756 mutex_enter(&e500_intr_lock);
757 /*
758 * Mask the source using the mask (MSK) bit in the vector/priority reg.
759 */
760 uint32_t vpr = openpic_read(cpu, ii.irq_vpr);
761 openpic_write(cpu, ii.irq_vpr, VPR_MSK | vpr);
762
763 /*
764 * Wait for the Activity (A) bit for the source to be cleared.
765 */
766 while (openpic_read(cpu, ii.irq_vpr) & VPR_A)
767 ;
768
769 /*
770 * Now the source can be modified.
771 */
772 openpic_write(cpu, ii.irq_dr, 0); /* stop delivery */
773 openpic_write(cpu, ii.irq_vpr, VPR_MSK); /* mask/reset it */
774
775 *is = (struct intr_source)INTR_SOURCE_INITIALIZER;
776
777 mutex_exit(&e500_intr_lock);
778 }
779
780 static void
781 e500_critintr(struct trapframe *tf)
782 {
783 panic("%s: srr0/srr1=%#lx/%#lx", __func__, tf->tf_srr0, tf->tf_srr1);
784 }
785
786 static void
787 e500_decrintr(struct trapframe *tf)
788 {
789 panic("%s: srr0/srr1=%#lx/%#lx", __func__, tf->tf_srr0, tf->tf_srr1);
790 }
791
792 static void
793 e500_fitintr(struct trapframe *tf)
794 {
795 panic("%s: srr0/srr1=%#lx/%#lx", __func__, tf->tf_srr0, tf->tf_srr1);
796 }
797
798 static void
799 e500_wdogintr(struct trapframe *tf)
800 {
801 mtspr(SPR_TSR, TSR_ENW|TSR_WIS);
802 panic("%s: tf=%p tb=%"PRId64" srr0/srr1=%#lx/%#lx", __func__, tf,
803 mftb(), tf->tf_srr0, tf->tf_srr1);
804 }
805
806 static void
807 e500_extintr(struct trapframe *tf)
808 {
809 struct cpu_info * const ci = curcpu();
810 struct cpu_softc * const cpu = ci->ci_softc;
811 const int old_ipl = ci->ci_cpl;
812
813 KASSERT(mfmsr() & PSL_CE);
814
815 #if 0
816 // printf("%s(%p): idepth=%d enter\n", __func__, tf, ci->ci_idepth);
817 if ((register_t)tf >= (register_t)curlwp->l_addr + USPACE
818 || (register_t)tf < (register_t)curlwp->l_addr + NBPG) {
819 printf("%s(entry): pid %d.%d (%s): srr0/srr1=%#lx/%#lx: invalid tf addr %p\n",
820 __func__, curlwp->l_proc->p_pid, curlwp->l_lid,
821 curlwp->l_proc->p_comm, tf->tf_srr0, tf->tf_srr1, tf);
822 }
823 #endif
824
825
826 ci->ci_data.cpu_nintr++;
827 tf->tf_cf.cf_idepth = ci->ci_idepth++;
828 cpu->cpu_pcpls[ci->ci_idepth] = old_ipl;
829 #if 1
830 if (mfmsr() & PSL_EE)
831 panic("%s(%p): MSR[EE] is on (%#lx)!", __func__, tf, mfmsr());
832 if (old_ipl == IPL_HIGH
833 || IPL2CTPR(old_ipl) != openpic_read(cpu, OPENPIC_CTPR))
834 panic("%s(%p): old_ipl(%u) == IPL_HIGH(%u) "
835 "|| old_ipl + %u != OPENPIC_CTPR (%u)",
836 __func__, tf, old_ipl, IPL_HIGH,
837 15 - IPL_HIGH, openpic_read(cpu, OPENPIC_CTPR));
838 #else
839 if (old_ipl >= IPL_VM)
840 panic("%s(%p): old_ipl(%u) >= IPL_VM(%u) CTPR=%u",
841 __func__, tf, old_ipl, IPL_VM, openpic_read(cpu, OPENPIC_CTPR));
842 #endif
843
844 for (;;) {
845 /*
846 * Find out the pending interrupt.
847 */
848 if (mfmsr() & PSL_EE)
849 panic("%s(%p): MSR[EE] turned on (%#lx)!", __func__, tf, mfmsr());
850 if (IPL2CTPR(old_ipl) != openpic_read(cpu, OPENPIC_CTPR))
851 panic("%s(%p): %d: old_ipl(%u) + %u != OPENPIC_CTPR (%u)",
852 __func__, tf, __LINE__, old_ipl,
853 15 - IPL_HIGH, openpic_read(cpu, OPENPIC_CTPR));
854 const uint32_t iack = openpic_read(cpu, OPENPIC_IACK);
855 #ifdef DIAGNOSTIC
856 const int ipl = iack & 0xf;
857 #endif
858 const int irq = (iack >> 4) - 1;
859 #if 0
860 printf("%s: iack=%d ipl=%d irq=%d <%s>\n",
861 __func__, iack, ipl, irq,
862 (iack != IRQ_SPURIOUS ?
863 cpu->cpu_evcnt_intrs[irq].ev_name : "spurious"));
864 #endif
865 if (IPL2CTPR(old_ipl) != openpic_read(cpu, OPENPIC_CTPR))
866 panic("%s(%p): %d: old_ipl(%u) + %u != OPENPIC_CTPR (%u)",
867 __func__, tf, __LINE__, old_ipl,
868 15 - IPL_HIGH, openpic_read(cpu, OPENPIC_CTPR));
869 if (iack == IRQ_SPURIOUS)
870 break;
871
872 struct intr_source * const is = &e500_intr_sources[irq];
873 if (__predict_true(is < e500_intr_last_source)) {
874 /*
875 * Timer interrupts get their argument overriden with
876 * the pointer to the trapframe.
877 */
878 KASSERT(is->is_ipl == ipl);
879 void *arg = (is->is_ist == IST_TIMER ? tf : is->is_arg);
880 if (is->is_ipl <= old_ipl)
881 panic("%s(%p): %s (%u): is->is_ipl (%u) <= old_ipl (%u)\n",
882 __func__, tf,
883 cpu->cpu_evcnt_intrs[irq].ev_name, irq,
884 is->is_ipl, old_ipl);
885 KASSERT(is->is_ipl > old_ipl);
886 e500_splset(ci, is->is_ipl); /* change IPL */
887 if (__predict_false(is->is_func == NULL)) {
888 aprint_error_dev(ci->ci_dev,
889 "interrupt from unestablished irq %d\n",
890 irq);
891 } else {
892 int (*func)(void *) = is->is_func;
893 wrtee(PSL_EE);
894 int rv = (*func)(arg);
895 wrtee(0);
896 #if DEBUG > 2
897 printf("%s: %s handler %p(%p) returned %d\n",
898 __func__,
899 cpu->cpu_evcnt_intrs[irq].ev_name,
900 func, arg, rv);
901 #endif
902 if (rv == 0)
903 cpu->cpu_evcnt_spurious_intr.ev_count++;
904 }
905 e500_splset(ci, old_ipl); /* restore IPL */
906 cpu->cpu_evcnt_intrs[irq].ev_count++;
907 } else {
908 aprint_error_dev(ci->ci_dev,
909 "interrupt from illegal irq %d\n", irq);
910 cpu->cpu_evcnt_spurious_intr.ev_count++;
911 }
912 /*
913 * If this is a nested interrupt, simply ack it and exit
914 * because the loop we interrupted will complete looking
915 * for interrupts.
916 */
917 if (mfmsr() & PSL_EE)
918 panic("%s(%p): MSR[EE] left on (%#lx)!", __func__, tf, mfmsr());
919 if (IPL2CTPR(old_ipl) != openpic_read(cpu, OPENPIC_CTPR))
920 panic("%s(%p): %d: old_ipl(%u) + %u != OPENPIC_CTPR (%u)",
921 __func__, tf, __LINE__, old_ipl,
922 15 - IPL_HIGH, openpic_read(cpu, OPENPIC_CTPR));
923
924 openpic_write(cpu, OPENPIC_EOI, 0);
925 if (IPL2CTPR(old_ipl) != openpic_read(cpu, OPENPIC_CTPR))
926 panic("%s(%p): %d: old_ipl(%u) + %u != OPENPIC_CTPR (%u)",
927 __func__, tf, __LINE__, old_ipl,
928 15 - IPL_HIGH, openpic_read(cpu, OPENPIC_CTPR));
929 if (ci->ci_idepth > 0)
930 break;
931 }
932
933 ci->ci_idepth--;
934
935 #ifdef __HAVE_FAST_SOFTINTS
936 /*
937 * Before exiting, deal with any softints that need to be dealt with.
938 */
939 const u_int softints = (ci->ci_data.cpu_softints << old_ipl) & IPL_SOFTMASK;
940 if (__predict_false(softints != 0)) {
941 KASSERT(old_ipl < IPL_VM);
942 e500_splset(ci, IPL_HIGH); /* pop to high */
943 powerpc_softint(ci, old_ipl, /* deal with them */
944 tf->tf_srr0);
945 e500_splset(ci, old_ipl); /* and drop back */
946 }
947 #endif /* __HAVE_FAST_SOFTINTS */
948 #if 1
949 KASSERT(ci->ci_cpl == old_ipl);
950 #else
951 e500_splset(ci, old_ipl); /* and drop back */
952 #endif
953
954 // printf("%s(%p): idepth=%d exit\n", __func__, tf, ci->ci_idepth);
955 }
956
957 static void
958 e500_intr_init(void)
959 {
960 struct cpu_info * const ci = curcpu();
961 struct cpu_softc * const cpu = ci->ci_softc;
962 const uint32_t frr = openpic_read(cpu, OPENPIC_FRR);
963 const u_int nirq = FRR_NIRQ_GET(frr) + 1;
964 // const u_int ncpu = FRR_NCPU_GET(frr) + 1;
965 struct intr_source *is;
966 struct e500_intr_info * const ii = &e500_intr_info;
967
968 const uint16_t svr = (mfspr(SPR_SVR) & ~0x80000) >> 16;
969 switch (svr) {
970 #ifdef MPC8536
971 case SVR_MPC8536v1 >> 16:
972 *ii = mpc8536_intr_info;
973 break;
974 #endif
975 #ifdef MPC8544
976 case SVR_MPC8544v1 >> 16:
977 *ii = mpc8544_intr_info;
978 break;
979 #endif
980 #ifdef MPC8548
981 case SVR_MPC8543v1 >> 16:
982 case SVR_MPC8548v1 >> 16:
983 *ii = mpc8548_intr_info;
984 break;
985 #endif
986 #ifdef MPC8555
987 case SVR_MPC8541v1 >> 16:
988 case SVR_MPC8555v1 >> 16:
989 *ii = mpc8555_intr_info;
990 break;
991 #endif
992 #ifdef MPC8568
993 case SVR_MPC8568v1 >> 16:
994 *ii = mpc8568_intr_info;
995 break;
996 #endif
997 #ifdef MPC8572
998 case SVR_MPC8572v1 >> 16:
999 *ii = mpc8572_intr_info;
1000 break;
1001 #endif
1002 #ifdef P2020
1003 case SVR_P2010v2 >> 16:
1004 case SVR_P2020v2 >> 16:
1005 *ii = p20x0_intr_info;
1006 break;
1007 #endif
1008 default:
1009 panic("%s: don't know how to deal with SVR %#lx",
1010 __func__, mfspr(SPR_SVR));
1011 }
1012
1013 /*
1014 * We need to be in mixed mode.
1015 */
1016 openpic_write(cpu, OPENPIC_GCR, GCR_M);
1017
1018 /*
1019 * Make we and the openpic both agree about the current SPL level.
1020 */
1021 e500_splset(ci, ci->ci_cpl);
1022
1023 /*
1024 * Allow the required number of interrupt sources.
1025 */
1026 is = kmem_zalloc(nirq * sizeof(*is), KM_SLEEP);
1027 KASSERT(is);
1028 e500_intr_sources = is;
1029 e500_intr_last_source = is + nirq;
1030
1031 /*
1032 * Initialize all the external interrupts as active low.
1033 */
1034 for (u_int irq = 0; irq < e500_intr_info.ii_external_sources; irq++) {
1035 openpic_write(cpu, OPENPIC_EIVPR(irq),
1036 VPR_VECTOR_MAKE(irq) | VPR_LEVEL_LOW);
1037 }
1038 }
1039
1040 static void
1041 e500_idlespin(void)
1042 {
1043 KASSERTMSG(curcpu()->ci_cpl == IPL_NONE,
1044 ("%s: cpu%u: ci_cpl (%d) != 0", __func__, cpu_number(),
1045 curcpu()->ci_cpl));
1046 KASSERTMSG(CTPR2IPL(openpic_read(curcpu()->ci_softc, OPENPIC_CTPR)) == IPL_NONE,
1047 ("%s: cpu%u: CTPR (%d) != IPL_NONE", __func__, cpu_number(),
1048 CTPR2IPL(openpic_read(curcpu()->ci_softc, OPENPIC_CTPR))));
1049 KASSERT(mfmsr() & PSL_EE);
1050 }
1051
1052 static void
1053 e500_intr_cpu_attach(struct cpu_info *ci)
1054 {
1055 struct cpu_softc * const cpu = ci->ci_softc;
1056 const char * const xname = device_xname(ci->ci_dev);
1057
1058 const u_int32_t frr = openpic_read(cpu, OPENPIC_FRR);
1059 const u_int nirq = FRR_NIRQ_GET(frr) + 1;
1060 // const u_int ncpu = FRR_NCPU_GET(frr) + 1;
1061
1062 const struct e500_intr_info * const info = &e500_intr_info;
1063
1064 cpu->cpu_clock_gtbcr = OPENPIC_GTBCR(ci->ci_cpuid, E500_CLOCK_TIMER);
1065
1066 cpu->cpu_evcnt_intrs =
1067 kmem_zalloc(nirq * sizeof(cpu->cpu_evcnt_intrs[0]), KM_SLEEP);
1068 KASSERT(cpu->cpu_evcnt_intrs);
1069
1070 struct evcnt *evcnt = cpu->cpu_evcnt_intrs;
1071 for (size_t j = 0; j < info->ii_external_sources; j++, evcnt++) {
1072 const char *name = e500_intr_external_name_lookup(j);
1073 evcnt_attach_dynamic(evcnt, EVCNT_TYPE_INTR, NULL, xname, name);
1074 }
1075 KASSERT(evcnt == cpu->cpu_evcnt_intrs + info->ii_ist_vectors[IST_ONCHIP]);
1076 for (size_t j = 0; j < info->ii_onchip_sources; j++, evcnt++) {
1077 if (info->ii_onchip_bitmap[j / 32] & __BIT(j & 31)) {
1078 const char *name = e500_intr_onchip_name_lookup(j);
1079 if (name != NULL) {
1080 evcnt_attach_dynamic(evcnt, EVCNT_TYPE_INTR,
1081 NULL, xname, name);
1082 #ifdef DIAGNOSTIC
1083 } else {
1084 printf("%s: missing evcnt for onchip irq %zu\n",
1085 __func__, j);
1086 #endif
1087 }
1088 }
1089 }
1090
1091 KASSERT(evcnt == cpu->cpu_evcnt_intrs + info->ii_ist_vectors[IST_MSIGROUP]);
1092 for (size_t j = 0; j < info->ii_msigroup_sources; j++, evcnt++) {
1093 evcnt_attach_dynamic(evcnt, EVCNT_TYPE_INTR,
1094 NULL, xname, e500_msigroup_intr_names[j].in_name);
1095 }
1096
1097 KASSERT(evcnt == cpu->cpu_evcnt_intrs + info->ii_ist_vectors[IST_TIMER]);
1098 evcnt += ci->ci_cpuid * info->ii_percpu_sources;
1099 for (size_t j = 0; j < info->ii_timer_sources; j++, evcnt++) {
1100 evcnt_attach_dynamic(evcnt, EVCNT_TYPE_INTR,
1101 NULL, xname, e500_timer_intr_names[j].in_name);
1102 }
1103
1104 for (size_t j = 0; j < info->ii_ipi_sources; j++, evcnt++) {
1105 evcnt_attach_dynamic(evcnt, EVCNT_TYPE_INTR,
1106 NULL, xname, e500_ipi_intr_names[j].in_name);
1107 }
1108
1109 for (size_t j = 0; j < info->ii_mi_sources; j++, evcnt++) {
1110 evcnt_attach_dynamic(evcnt, EVCNT_TYPE_INTR,
1111 NULL, xname, e500_mi_intr_names[j].in_name);
1112 }
1113
1114 ci->ci_idlespin = e500_idlespin;
1115 }
1116
1117 static void
1118 e500_intr_cpu_send_ipi(cpuid_t target, uint32_t ipimsg)
1119 {
1120 struct cpu_info * const ci = curcpu();
1121 struct cpu_softc * const cpu = ci->ci_softc;
1122 uint32_t dstmask;
1123
1124 if (target >= ncpu) {
1125 CPU_INFO_ITERATOR cii;
1126 struct cpu_info *dst_ci;
1127
1128 KASSERT(target == IPI_DST_NOTME || target == IPI_DST_ALL);
1129
1130 dstmask = 0;
1131 for (CPU_INFO_FOREACH(cii, dst_ci)) {
1132 if (target == IPI_DST_ALL || ci != dst_ci) {
1133 dstmask |= 1 << cpu_index(ci);
1134 if (ipimsg)
1135 atomic_or_32(&dst_ci->ci_pending_ipis,
1136 ipimsg);
1137 }
1138 }
1139 } else {
1140 struct cpu_info * const dst_ci = cpu_lookup(target);
1141 KASSERT(target == cpu_index(dst_ci));
1142 dstmask = (1 << target);
1143 if (ipimsg)
1144 atomic_or_32(&dst_ci->ci_pending_ipis, ipimsg);
1145 }
1146
1147 openpic_write(cpu, OPENPIC_IPIDR(0), dstmask);
1148 }
1149
1150 typedef void (*ipifunc_t)(void);
1151
1152 #ifdef __HAVE_PREEEMPTION
1153 static void
1154 e500_ipi_kpreempt(void)
1155 {
1156 poowerpc_softint_trigger(1 << IPL_NONE);
1157 }
1158 #endif
1159
1160 static const ipifunc_t e500_ipifuncs[] = {
1161 [ilog2(IPI_XCALL)] = xc_ipi_handler,
1162 [ilog2(IPI_HALT)] = e500_ipi_halt,
1163 #ifdef __HAVE_PREEMPTION
1164 [ilog2(IPI_KPREEMPT)] = e500_ipi_kpreempt,
1165 #endif
1166 [ilog2(IPI_TLB1SYNC)] = e500_tlb1_sync,
1167 };
1168
1169 static int
1170 e500_ipi_intr(void *v)
1171 {
1172 struct cpu_info * const ci = curcpu();
1173
1174 ci->ci_ev_ipi.ev_count++;
1175
1176 uint32_t pending_ipis = atomic_swap_32(&ci->ci_pending_ipis, 0);
1177 for (u_int ipi = 31; pending_ipis != 0; ipi--, pending_ipis <<= 1) {
1178 const u_int bits = __builtin_clz(pending_ipis);
1179 ipi -= bits;
1180 pending_ipis <<= bits;
1181 KASSERT(e500_ipifuncs[ipi] != NULL);
1182 (*e500_ipifuncs[ipi])();
1183 }
1184
1185 return 1;
1186 }
1187
1188 static void
1189 e500_intr_cpu_hatch(struct cpu_info *ci)
1190 {
1191 /*
1192 * Establish clock interrupt for this CPU.
1193 */
1194 if (e500_intr_cpu_establish(ci, E500_CLOCK_TIMER, IPL_CLOCK, IST_TIMER,
1195 e500_clock_intr, NULL) == NULL)
1196 panic("%s: failed to establish clock interrupt!", __func__);
1197
1198 /*
1199 * Establish the IPI interrupts for this CPU.
1200 */
1201 if (e500_intr_cpu_establish(ci, 0, IPL_VM, IST_IPI, e500_ipi_intr,
1202 NULL) == NULL)
1203 panic("%s: failed to establish ipi interrupt!", __func__);
1204
1205 /*
1206 * Enable watchdog interrupts.
1207 */
1208 uint32_t tcr = mfspr(SPR_TCR);
1209 tcr |= TCR_WIE;
1210 mtspr(SPR_TCR, tcr);
1211 }
1212