void cpu_intr(int ppl, vaddr_t pc, uint32_t status) { struct cpu_info * const ci = curcpu(); uint32_t pending; int ipl; #ifdef DIAGNOSTIC const int mtx_count = ci->ci_mtx_count; const u_int biglock_count = ci->ci_biglock_count; const u_int blcnt = curlwp->l_blcnt; #endif KASSERT(ci->ci_cpl == IPL_HIGH); KDASSERT(mips_cp0_status_read() & MIPS_SR_INT_IE); ci->ci_data.cpu_nintr++; while (ppl < (ipl = splintr(&pending))) { KDASSERT(mips_cp0_status_read() & MIPS_SR_INT_IE); splx(ipl); /* lower to interrupt level */ KDASSERT(mips_cp0_status_read() & MIPS_SR_INT_IE); KASSERTMSG(ci->ci_cpl == ipl, "%s: cpl (%d) != ipl (%d)", __func__, ci->ci_cpl, ipl); KASSERT(pending != 0); cf.pc = pc; cf.sr = status; cf.intr = (ci->ci_idepth > 1); #ifdef MIPS3_ENABLE_CLOCK_INTR if (pending & MIPS_INT_MASK_5) { KASSERTMSG(ipl == IPL_SCHED, "%s: ipl (%d) != IPL_SCHED (%d)", __func__, ipl, IPL_SCHED); /* call the common MIPS3 clock interrupt handler */ mips3_clockintr(&cf); pending ^= MIPS_INT_MASK_5; } #endif if (pending != 0) { /* Process I/O and error interrupts. */ evbmips_iointr(ipl, pc, pending); } KASSERT(biglock_count == ci->ci_biglock_count); KASSERT(blcnt == curlwp->l_blcnt); KASSERT(mtx_count == ci->ci_mtx_count); /* * If even our spl is higher now (due to interrupting while * spin-lock is held and higher IPL spin-lock is locked, it * can no longer be locked so it's safe to lower IPL back * to ppl. */ (void) splhigh(); /* disable interrupts */ } KASSERT(ci->ci_cpl == IPL_HIGH); KDASSERT(mips_cp0_status_read() & MIPS_SR_INT_IE); }
void cpu_intr(int ppl, vaddr_t pc, uint32_t status) { uint32_t pending; int ipl; curcpu()->ci_data.cpu_nintr++; while (ppl < (ipl = splintr(&pending))) { splx(ipl); if (pending & MIPS_INT_MASK_5) { struct clockframe cf; cf.pc = pc; cf.sr = status; cf.intr = (curcpu()->ci_idepth > 1); mips3_clockintr(&cf); } if (pending & (MIPS_INT_MASK_0|MIPS_INT_MASK_1|MIPS_INT_MASK_2| MIPS_INT_MASK_3|MIPS_INT_MASK_4)) { /* Process I/O and error interrupts. */ (*algor_iointr)(ipl, pc, pending); } (void)splhigh(); } }
/* * NB: Do not re-enable interrupts here -- reentrancy here can cause all * sorts of Bad Things(tm) to happen, including kernel stack overflows. */ void cpu_intr(int ppl, vaddr_t pc, uint32_t status) { uint32_t pending; int ipl; curcpu()->ci_data.cpu_nintr++; (void)(*platform.watchdog_reset)(); while (ppl < (ipl = splintr(&pending))) { splx(ipl); /* enable interrupts */ if (pending & MIPS_INT_MASK_5) { (void)(*platform.intr5)(pc, status, pending); mips_int5_evcnt.ev_count++; } if (pending & MIPS_INT_MASK_4) { (void)(*platform.intr4)(pc, status, pending); mips_int4_evcnt.ev_count++; } if (pending & MIPS_INT_MASK_3) { (void)(*platform.intr3)(pc, status, pending); mips_int3_evcnt.ev_count++; } if (pending & MIPS_INT_MASK_2) { (void)(*platform.intr2)(pc, status, pending); mips_int2_evcnt.ev_count++; } if (pending & MIPS_INT_MASK_1) { (void)(*platform.intr1)(pc, status, pending); mips_int1_evcnt.ev_count++; } if (pending & MIPS_INT_MASK_0) { (void)(*platform.intr0)(pc, status, pending); mips_int0_evcnt.ev_count++; } (void)splhigh(); } }
/* * Handle news5000 interrupts. */ void news5000_intr(int ppl, vaddr_t pc, uint32_t status) { uint32_t ipending; int ipl; while (ppl < (ipl = splintr(&ipending))) { if (ipending & MIPS_INT_MASK_2) { #ifdef DEBUG static int l2cnt = 0; #endif uint32_t int2stat; int2stat = *(volatile uint32_t *)NEWS5000_INTST2; #ifdef DEBUG l2cnt++; if (l2cnt == 50) { *(volatile uint32_t *)NEWS5000_LED_SEC = 1; } if (l2cnt == 100) { *(volatile uint32_t *)NEWS5000_LED_SEC = 0; l2cnt = 0; } #endif if (int2stat & NEWS5000_INT2_TIMER0) { struct clockframe cf = { .pc = pc, .sr = status, .intr = (curcpu()->ci_idepth > 1), }; *(volatile uint32_t *)NEWS5000_TIMER0 = 1; hardclock(&cf); intrcnt[HARDCLOCK_INTR]++; } apbus_wbflush(); } if (ipending & MIPS_INT_MASK_5) { uint32_t int5stat; int5stat = *(volatile u_int *)NEWS5000_INTST5; printf("level5 interrupt (%08x)\n", int5stat); apbus_wbflush(); } if (ipending & MIPS_INT_MASK_4) { uint32_t int4stat; int4stat = *(volatile uint32_t *)NEWS5000_INTST4; printf("level4 interrupt (%08x)\n", int4stat); if (int4stat & NEWS5000_INT4_APBUS) { uint32_t stat; stat = *(volatile uint32_t *)NEWS5000_APBUS_INTST; printf("APbus error 0x%04x\n", stat & 0xffff); if (stat & NEWS5000_APBUS_INT_DMAADDR) { printf("DMA Address Error: " "slot=%x, addr=0x%08x\n", *(volatile uint32_t *)NEWS5000_APBUS_DER_S, *(volatile uint32_t *)NEWS5000_APBUS_DER_A); } if (stat & NEWS5000_APBUS_INT_RDTIMEO) printf("IO Read Timeout: addr=0x%08x\n", *(volatile uint32_t *)NEWS5000_APBUS_BER_A); if (stat & NEWS5000_APBUS_INT_WRTIMEO) printf("IO Write Timeout: addr=0x%08x\n", *(volatile uint32_t *)NEWS5000_APBUS_BER_A); *(volatile uint32_t *)0xb4c00014 = stat; } apbus_wbflush(); } if (ipending & MIPS_INT_MASK_3) { uint32_t int3stat; int3stat = *(volatile uint32_t *)NEWS5000_INTST3; printf("level3 interrupt (%08x)\n", int3stat); apbus_wbflush(); } if (ipending & MIPS_INT_MASK_1) { news5000_level1_intr(); apbus_wbflush(); } if (ipending & MIPS_INT_MASK_0) { news5000_level0_intr(); apbus_wbflush(); } } } static void news5000_level1_intr(void) { uint32_t int1stat; int1stat = *(volatile uint32_t *)NEWS5000_INTST1; if (int1stat) { if (apbus_intr_dispatch(1, int1stat) == 0) printf("level1_intr: no handler (mask 0x%04x)\n", int1stat); } else printf("level1 stray interrupt?\n"); }