Skip to content

Commit a650783

Browse files
committed
handling spurious interrupts correctly
1 parent 27a78ae commit a650783

File tree

2 files changed

+44
-1
lines changed

2 files changed

+44
-1
lines changed

src/intr.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ static void gate_desc(desc_t *desc, uint16_t sel, uint32_t addr, int dpl, int ty
6060
/* defined in intr_asm.S */
6161
void set_idt(uint32_t addr, uint16_t limit);
6262
void intr_entry_default(void);
63+
void irq7_entry_check_spurious(void);
64+
void irq15_entry_check_spurious(void);
6365

6466
/* the IDT (interrupt descriptor table) */
6567
static desc_t idt[256] __attribute__((aligned(8)));
@@ -90,6 +92,12 @@ void init_intr(void)
9092
*/
9193
#include "intrtab.h"
9294

95+
/* change irq7 and irq15 to special entry points which first
96+
* make sure we didn't get a spurious interrupt before proceeding
97+
*/
98+
set_intr_entry(IRQ_TO_INTR(7), irq7_entry_check_spurious);
99+
set_intr_entry(IRQ_TO_INTR(15), irq15_entry_check_spurious);
100+
93101
/* initialize the programmable interrupt controller
94102
* setting up the maping of IRQs [0, 15] to interrupts [32, 47]
95103
*/

src/intr_asm.S

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,42 @@ intr_entry_fast_timer:
104104
out %al, $0x20
105105
pop %eax
106106
iret
107-
107+
108+
/* special case for IRQ 7 and IRQ 15, to catch spurious interrupts */
109+
.set PIC1_CMD, 0x20
110+
.set PIC2_CMD, 0xa0
111+
.set OCW2_EOI, 0x20
112+
.set OCW3_ISR, 0x0b
113+
114+
.extern intr_entry_irq7
115+
.global irq7_entry_check_spurious
116+
irq7_entry_check_spurious:
117+
push %eax
118+
mov $OCW3_ISR, %al
119+
out %al, $PIC1_CMD
120+
in $PIC1_CMD, %al
121+
and $0x80, %al
122+
pop %eax
123+
jnz intr_entry_irq7
124+
iret
125+
126+
.extern intr_entry_irq15
127+
.global irq15_entry_check_spurious
128+
irq15_entry_check_spurious:
129+
push %eax
130+
mov $OCW3_ISR, %al
131+
out %al, $PIC2_CMD
132+
in $PIC2_CMD, %al
133+
and $0x80, %al
134+
jnz 0f
135+
# it was spurious, send EOI to master PIC and iret
136+
mov $OCW2_EOI, %al
137+
out %al, $PIC1_CMD
138+
pop %eax
139+
iret
140+
0: pop %eax
141+
jmp intr_entry_irq15
142+
108143

109144
/* XXX not necessary for now, just leaving it in in case it's useful
110145
* down the road.

0 commit comments

Comments
 (0)