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