summary refs log tree commit diff stats
path: root/hw/i8259.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/i8259.c')
-rw-r--r--hw/i8259.c18
1 files changed, 18 insertions, 0 deletions
diff --git a/hw/i8259.c b/hw/i8259.c
index 65876662a1..7ecb7e1de6 100644
--- a/hw/i8259.c
+++ b/hw/i8259.c
@@ -26,6 +26,7 @@
 #include "isa.h"
 #include "monitor.h"
 #include "qemu-timer.h"
+#include "sysemu.h"
 #include "i8259_internal.h"
 
 /* debug PIC */
@@ -193,6 +194,20 @@ int pic_read_irq(DeviceState *d)
                 pic_intack(slave_pic, irq2);
             } else {
                 /* spurious IRQ on slave controller */
+                if (no_spurious_interrupt_hack) {
+                    /* Pretend it was delivered and acknowledged.  If
+                     * it was spurious due to slave_pic->imr, then
+                     * as soon as the mask is cleared, the slave will
+                     * re-trigger IRQ2 on the master.  If it is spurious for
+                     * some other reason, make sure we don't keep trying
+                     * to half-process the same spurious interrupt over
+                     * and over again.
+                     */
+                    s->irr &= ~(1<<irq);
+                    s->last_irr &= ~(1<<irq);
+                    s->isr &= ~(1<<irq);
+                    return -1;
+                }
                 irq2 = 7;
             }
             intno = slave_pic->irq_base + irq2;
@@ -202,6 +217,9 @@ int pic_read_irq(DeviceState *d)
         pic_intack(s, irq);
     } else {
         /* spurious IRQ on host controller */
+        if (no_spurious_interrupt_hack) {
+            return -1;
+        }
         irq = 7;
         intno = s->irq_base + irq;
     }