From: Ben Pfaff Date: Thu, 28 Sep 2006 17:45:27 +0000 (+0000) Subject: Irq 7 is special. It is not just the parallel port. It can also be a X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?p=pintos-anon;a=commitdiff_plain;h=2e8d8e1e1d4aa9c90b78c6d40bc315dd4e5270b9 Irq 7 is special. It is not just the parallel port. It can also be a "spurious" irq, one that is not associated with any particular device. Real hardware can generate spurious irqs for various reasons (try Google for details), but it never occurred to me that simulated hardware would ever do so. However, it can, at least under Bochs. Pintos programs the PIT to interrupt at 100 Hz. The PIT does so by generating a output signal that stays high most of the time but drops low for a single clock cycle 100 times per second. The low-to-high transition causes the timer interrupt. The problem occurs when we've been doing work with interrupts disabled, causing a timer interrupt to be delayed. If we enable interrupts on the same clock cycle as the PIT's high-to-low transition, we will still get an interrupt, because the interrupt controller latched the presence of an interrupt. However, when the CPU attempts to determine the irq number, the interrupt controller sees that all of its incoming interrupt lines are low. Thus, it reports irq 7 to the CPU, and we end up with an interrupt 0x27. It doesn't happen very often, because there's only a 1-cycle window, and it requires that we do a good deal of work with interrupts off, and it can only happen if no other interrupts (e.g. serial) are pending. But it's darned annoying when it happens. Here's a filtered excerpt from a Bochs log with debugging enabled where you can see the problem. The first interrupt (32 or 0x20) is properly a timer interrupt, because irq line 0 is high. The second interrupt (39 or 0x27) is the spurious one; you can see that irq line 0 went low on the same cycle. 00080033515d[PIC ] IRQ line 4 now low 00080033827d[PIC ] IRQ line 4 now high 00080033970d[PIC ] IRQ line 0 now low 00080033971d[PIC ] IRQ line 0 now high 00080033989d[PIC ] IRQ line 4 now low 00080034068d[CPU ] interrupt(): vector = 32, INT = 0, EXT = 1 00080043970d[PIC ] IRQ line 0 now low 00080043971d[PIC ] IRQ line 0 now high 00080053971d[PIC ] IRQ line 0 now low 00080053971d[PIC ] IRQ line 0 now high 00080063971d[PIC ] IRQ line 0 now low 00080063972d[PIC ] IRQ line 0 now high 00080073971d[PIC ] IRQ line 0 now low 00080073972d[PIC ] IRQ line 0 now high 00080083971d[PIC ] IRQ line 0 now low 00080083971d[CPU ] interrupt(): vector = 39, INT = 0, EXT = 1 00080083972d[PIC ] IRQ line 0 now high 00080084538d[PIC ] IRQ line 4 now high This change causes irqs 7 and 15 (0x27 and 0x2f) to be ignored when no handler is provided. Problem reported by Godmar Back. --- diff --git a/src/threads/interrupt.c b/src/threads/interrupt.c index 6d3f6bb..72b3783 100644 --- a/src/threads/interrupt.c +++ b/src/threads/interrupt.c @@ -355,16 +355,23 @@ intr_handler (struct intr_frame *frame) yield_on_return = false; } - /* Invoke the interrupt's handler. - If there is no handler, invoke the unexpected interrupt - handler. */ + /* Invoke the interrupt's handler. */ handler = intr_handlers[frame->vec_no]; - if (handler == NULL) + if (handler != NULL) + handler (frame); + else if (frame->vec_no == 0x27 || frame->vec_no == 0x2f) { + /* There is no handler, but this interrupt can trigger + spuriously due to a hardware fault or hardware race + condition. Ignore it. */ + } + else + { + /* No handler and not spurious. Invoke the unexpected + interrupt handler. */ intr_dump_frame (frame); - PANIC ("Unexpected interrupt"); + PANIC ("Unexpected interrupt"); } - handler (frame); /* Complete the processing of an external interrupt. */ if (external)