enum handler_return platform_irq(struct arm64_iframe_short *frame) { uint32_t iar = GICCPUREG(IAR); uint vector = iar & 0x3ff; // printf("platform_irq: spsr 0x%llx, pc 0x%llx, currthread %p, vector %d\n", frame->spsr, frame->elr, current_thread, vector); if (vector >= 0x3fe) { // spurious return INT_NO_RESCHEDULE; } THREAD_STATS_INC(interrupts); KEVLOG_IRQ_ENTER(vector); // deliver the interrupt enum handler_return ret; ret = INT_NO_RESCHEDULE; if (int_handler_table[vector].handler) ret = int_handler_table[vector].handler(int_handler_table[vector].arg); GICCPUREG(EOIR) = iar; // printf("platform_irq: exit %d\n", ret); KEVLOG_IRQ_EXIT(vector); if (ret != INT_NO_RESCHEDULE) thread_preempt(); return ret; }
void arm_cm_irq_entry(void) { inc_critical_section(); THREAD_STATS_INC(interrupts); KEVLOG_IRQ_ENTER(__get_IPSR()); }
void arm_cm_irq_entry(void) { // Set PRIMASK to 1 // This is so that later calls to arch_ints_disabled() returns true while we're inside the int handler // Note: this will probably screw up future efforts to stack higher priority interrupts since we're setting // the cpu to essentially max interrupt priority here. Will have to rethink it then. __disable_irq(); THREAD_STATS_INC(interrupts); KEVLOG_IRQ_ENTER(__get_IPSR()); }
enum handler_return platform_irq(struct x86_iframe *frame) { // get the current vector unsigned int vector = frame->vector; THREAD_STATS_INC(interrupts); // deliver the interrupt enum handler_return ret = INT_NO_RESCHEDULE; switch (vector) { case INT_GP_FAULT: x86_gpf_handler(frame); break; case INT_INVALID_OP: x86_invop_handler(frame); break; case INT_PAGE_FAULT: #ifdef ARCH_X86_64 x86_pfe_handler(frame); #endif break; case INT_DEV_NA_EX: #if X86_WITH_FPU fpu_dev_na_handler(); break; #endif case INT_MF: case INT_XM: case INT_DIVIDE_0: case INT_DEBUG_EX: case INT_STACK_FAULT: case 3: x86_unhandled_exception(frame); break; default: if (int_handler_table[vector].handler) ret = int_handler_table[vector].handler(int_handler_table[vector].arg); } // ack the interrupt issueEOI(vector); return ret; }
enum handler_return platform_irq(struct arm_iframe *frame) { // get the current vector unsigned int vector; THREAD_STATS_INC(interrupts); // read from the first level int handler vector = *ICReg(0, INTCON_SIR_IRQ); // see if it's coming from the second level handler if (vector == 0) { vector = *ICReg(1, INTCON_SIR_IRQ) + 32; } // dprintf("platform_irq: spsr 0x%x, pc 0x%x, currthread %p, vector %d\n", frame->spsr, frame->pc, current_thread, vector); // deliver the interrupt enum handler_return ret; ret = INT_NO_RESCHEDULE; if (int_handler_table[vector].handler) ret = int_handler_table[vector].handler(int_handler_table[vector].arg); // ack the interrupt if (vector >= 32) { // interrupt is chained, so ack the second level first, and then the first *ICReg(vector / 32, INTCON_ITR) = ~(1 << (vector % 32)); *ICReg(1, INTCON_CONTROL) |= 1; vector = 0; // force the following code to ack the chained first level vector } *ICReg(0, INTCON_ITR) = ~(1 << vector); *ICReg(0, INTCON_CONTROL) = 1; return ret; }
enum handler_return platform_irq(struct arm_iframe *frame) { // get the current vector unsigned int vector; // read the currently active IRQ vector = *REG32(INTC_SIR_IRQ) & 0x7f; // TRACEF("spsr 0x%x, pc 0x%x, currthread %p, vector %d, handler %p\n", frame->spsr, frame->pc, current_thread, vector, int_handler_table[vector].handler); THREAD_STATS_INC(interrupts); // deliver the interrupt enum handler_return ret; ret = INT_NO_RESCHEDULE; if (int_handler_table[vector].handler) ret = int_handler_table[vector].handler(int_handler_table[vector].arg); // ack the interrupt *REG32(INTC_CONTROL) = 0x1; return ret; }
enum handler_return platform_irq(struct arm_iframe *frame) { uint vector; uint cpu = arch_curr_cpu_num(); THREAD_STATS_INC(interrupts); // see what kind of irq it is uint32_t pend = *REG32(INTC_LOCAL_IRQ_PEND0 + cpu * 4); pend &= ~(1 << (INTERRUPT_ARM_LOCAL_GPU_FAST % 32)); // mask out gpu interrupts if (pend != 0) { // it's a local interrupt LTRACEF("local pend 0x%x\n", pend); vector = ARM_IRQ_LOCAL_BASE + ctz(pend); goto decoded; } // XXX disable for now, since all of the interesting irqs are mirrored into the other banks #if 0 // look in bank 0 (ARM interrupts) pend = *REG32(INTC_PEND0); LTRACEF("pend0 0x%x\n", pend); pend &= ~((1<<8)|(1<<9)); // mask out bit 8 and 9 if (pend != 0) { // it's a bank 0 interrupt vector = ARM_IRQ0_BASE + ctz(pend); goto decoded; } #endif // look for VC interrupt bank 1 pend = *REG32(INTC_PEND1); LTRACEF("pend1 0x%x\n", pend); if (pend != 0) { // it's a bank 1 interrupt vector = ARM_IRQ1_BASE + ctz(pend); goto decoded; } // look for VC interrupt bank 2 pend = *REG32(INTC_PEND2); LTRACEF("pend2 0x%x\n", pend); if (pend != 0) { // it's a bank 2 interrupt vector = ARM_IRQ2_BASE + ctz(pend); goto decoded; } vector = 0xffffffff; decoded: LTRACEF("cpu %u vector %u\n", cpu, vector); // dispatch the irq enum handler_return ret = INT_NO_RESCHEDULE; #if WITH_SMP if (vector == INTERRUPT_ARM_LOCAL_MAILBOX0) { pend = *REG32(INTC_LOCAL_MAILBOX0_CLR0 + 0x10 * cpu); LTRACEF("mailbox0 clr 0x%x\n", pend); // ack it *REG32(INTC_LOCAL_MAILBOX0_CLR0 + 0x10 * cpu) = pend; if (pend & (1 << MP_IPI_GENERIC)) { PANIC_UNIMPLEMENTED; } if (pend & (1 << MP_IPI_RESCHEDULE)) { ret = mp_mbx_reschedule_irq(); } } else #endif // WITH_SMP if (vector == 0xffffffff) { ret = INT_NO_RESCHEDULE; } else if (int_handler_table[vector].handler) { ret = int_handler_table[vector].handler(int_handler_table[vector].arg); } else { panic("irq %u fired on cpu %u but no handler set!\n", vector, cpu); } return ret; }
void arm_cm_irq_entry(void) { THREAD_STATS_INC(interrupts); KEVLOG_IRQ_ENTER(__get_IPSR()); }