core/minute-ia/interrupts.c
/*
 * Normally, LAPIC_LVT_ERROR_VECTOR doesn't need a handler. But ISH IOAPIC
 * has an unknown bug on high frequency interrupts. A similar issue has been
 * found in PII/PIII era according to x86 APIC Kernel driver. When IOAPIC
 * routing entry is masked/unmasked at a high rate, IOAPIC line gets stuck and
 * no more interrupts are received from it.
 *
 * The solution in Kernel driver changes interrupt distribution model. But it
 * doesn't solve the problem completely. Just make it hang less frequent.
 *
 * ISH IOAPIC-LAPIC was configured in a way so we can manually send EOI (end of
 * interrupt) to IOAPIC. So in the workaround below, we ack all IOAPIC vectors
 * not in LAPIC IRR (interrupt request register). The side effect is we kicked
 * out some of the interrupts without handling them. It depends on the
 * peripheral hardware design if it re-send this irq.
 */
Normally, LAPIC_LVT_ERROR_VECTOR doesn't need a handler. But ISH IOAPIC
has an unknown bug on high frequency interrupts. A similar issue has been
found in PII/PIII era according to x86 APIC Kernel driver. When IOAPIC
routing entry is masked/unmasked at a high rate, IOAPIC line gets stuck and
no more interrupts are received from it.

The solution in Kernel driver changes interrupt distribution model. But it
doesn't solve the problem completely. Just make it hang less frequent.

ISH IOAPIC-LAPIC was configured in a way so we can manually send EOI (end of
interrupt) to IOAPIC. So in the workaround below, we ack all IOAPIC vectors
not in LAPIC IRR (interrupt request register). The side effect is we kicked
out some of the interrupts without handling them. It depends on the
peripheral hardware design if it re-send this irq.
Normally LAPIC_LVT_ERROR_VECTOR doesn ' t need a handler . But ISH IOAPIC has an unknown bug on high frequency interrupts . A similar issue has been found in PII / PIII era according to x86 APIC Kernel driver . When IOAPIC routing entry is masked / unmasked at a high rate IOAPIC line gets stuck and no more interrupts are received from it . The solution in Kernel driver changes interrupt distribution model . But it doesn ' t solve the problem completely . Just make it hang less frequent . ISH IOAPIC - LAPIC was configured in a way so we can manually send EOI ( end of interrupt ) to IOAPIC . So in the workaround below we ack all IOAPIC vectors not in LAPIC IRR ( interrupt request register ) . The side effect is we kicked out some of the interrupts without handling them . It depends on the peripheral hardware design if it re - send this irq .
void handle_lapic_lvt_error(void)
{
	uint32_t esr = REG32(LAPIC_ESR_REG);
	uint32_t ioapic_redtbl, vec;
	int irq, max_irq_entries;
	REG32(LAPIC_ESR_REG) = 0;
	lapic_lvt_error_count++;
	if (esr & LAPIC_ERR_RECV_ILLEGAL) {
		max_irq_entries = (read_ioapic_reg(IOAPIC_VERSION) >> 16) &
				  0xff;
		for (irq = 0; irq < max_irq_entries; irq++) {
			ioapic_redtbl = get_ioapic_redtbl_lo(irq);
			if (ioapic_redtbl & IOAPIC_REDTBL_MASK)
				continue;
			if (ioapic_redtbl & IOAPIC_REDTBL_IRR) {
				vec = IRQ_TO_VEC(irq);
				if (!lapic_get_vector(LAPIC_IRR_REG, vec)) {
					REG32(IOAPIC_EOI_REG) = vec;
					ioapic_pending_count++;
				}
			}
		}
	}
	CPRINTF("LAPIC error ESR:0x%02x,count:%u IOAPIC pending count:%u\n",
		esr, lapic_lvt_error_count, ioapic_pending_count);
}
void handle_lapic_lvt_error ( void ) { uint32_t esr = REG32 ( LAPIC_ESR_REG ) ; uint32_t ioapic_redtbl , vec ; int irq , max_irq_entries ; REG32 ( LAPIC_ESR_REG ) = 0 ; lapic_lvt_error_count ++ ; if ( esr & LAPIC_ERR_RECV_ILLEGAL ) { max_irq_entries = ( read_ioapic_reg ( IOAPIC_VERSION ) >> 16 ) & 0xff ; for ( irq = 0 ; irq < max_irq_entries ; irq ++ ) { ioapic_redtbl = get_ioapic_redtbl_lo ( irq ) ; if ( ioapic_redtbl & IOAPIC_REDTBL_MASK ) continue ; if ( ioapic_redtbl & IOAPIC_REDTBL_IRR ) { vec = IRQ_TO_VEC ( irq ) ; if ( ! lapic_get_vector ( LAPIC_IRR_REG , vec ) ) { REG32 ( IOAPIC_EOI_REG ) = vec ; ioapic_pending_count ++ ; } } } } CPRINTF ( " \n " , esr , lapic_lvt_error_count , ioapic_pending_count ) ; }
Normally, LAPIC_LVT_ERROR_VECTOR doesn't need a handler.
Normally LAPIC_LVT_ERROR_VECTOR doesn ' t need a handler .
/* Ack LVT ERROR exception */ /*
	 * When IOAPIC has more than 1 interrupts in remote IRR state,
	 * LAPIC raises internal error.
	 */ /* Scan redirect table entries */ /* Skip masked IRQs */ /* If pending interrupt is not in LAPIC, clear it. */ /* End of interrupt */