If an interrupt on an I/O APIC is moved to a different CPU after it has

started to execute, it seems that the corresponding ISR bit in the "old"
local APIC can be cleared.  This causes the local APIC interrupt routine
to fail to find an interrupt to service.  Rather than panic'ing in this
case, simply return from the interrupt without sending an EOI to the
local APIC.  If there are any other pending interrupts in other ISR
registers, the local APIC will assert a new interrupt.

Tested by:	steve
This commit is contained in:
John Baldwin 2011-01-13 17:00:22 +00:00
parent c5199e9706
commit 072e9838e2
3 changed files with 8 additions and 14 deletions
sys
amd64/amd64
i386/i386
x86/x86

@ -58,17 +58,15 @@ IDTVEC(vec_name) ; \
FAKE_MCOUNT(TF_RIP(%rsp)) ; \
movq lapic, %rdx ; /* pointer to local APIC */ \
movl LA_ISR + 16 * (index)(%rdx), %eax ; /* load ISR */ \
bsrl %eax, %eax ; /* index of highset set bit in ISR */ \
jz 2f ; \
bsrl %eax, %eax ; /* index of highest set bit in ISR */ \
jz 1f ; \
addl $(32 * index),%eax ; \
1: ; \
movq %rsp, %rsi ; \
movl %eax, %edi ; /* pass the IRQ */ \
call lapic_handle_intr ; \
1: ; \
MEXITCOUNT ; \
jmp doreti ; \
2: movl $-1, %eax ; /* send a vector of -1 */ \
jmp 1b
jmp doreti
/*
* Handle "spurious INTerrupts".

@ -60,18 +60,16 @@ IDTVEC(vec_name) ; \
FAKE_MCOUNT(TF_EIP(%esp)) ; \
movl lapic, %edx ; /* pointer to local APIC */ \
movl LA_ISR + 16 * (index)(%edx), %eax ; /* load ISR */ \
bsrl %eax, %eax ; /* index of highset set bit in ISR */ \
jz 2f ; \
bsrl %eax, %eax ; /* index of highest set bit in ISR */ \
jz 1f ; \
addl $(32 * index),%eax ; \
1: ; \
pushl %esp ; \
pushl %eax ; /* pass the IRQ */ \
call lapic_handle_intr ; \
addl $8, %esp ; /* discard parameter */ \
1: ; \
MEXITCOUNT ; \
jmp doreti ; \
2: movl $-1, %eax ; /* send a vector of -1 */ \
jmp 1b
jmp doreti
/*
* Handle "spurious INTerrupts".

@ -780,8 +780,6 @@ lapic_handle_intr(int vector, struct trapframe *frame)
{
struct intsrc *isrc;
if (vector == -1)
panic("Couldn't get vector from ISR!");
isrc = intr_lookup_source(apic_idt_to_irq(PCPU_GET(apic_id),
vector));
intr_execute_handlers(isrc, frame);