From f278d4947fff814dcde2ef2acad36d172ff8be35 Mon Sep 17 00:00:00 2001 From: Matthew Ogilvie Date: Thu, 23 Aug 2012 00:24:43 -0600 Subject: i8259: add -no-spurious-interrupt-hack option This patch provides a way to optionally suppress spurious interrupts, as a workaround for systems described below: Some old operating systems do not handle spurious interrupts well, and qemu tends to generate them significantly more often than real hardware. Examples: - Microport UNIX System V/386 v 2.1 (ca 1987) (The main problem I'm fixing: Without this patch, it panics sporadically when accessing the hard disk.) - AT&T UNIX System V/386 Release 4.0 Version 2.1a (ca 1991) See screenshot in "QEMU Official OS Support List": http://www.claunia.com/qemu/objectManager.php?sClass=application&iId=9 (I don't have this system to test.) - A report about OS/2 boot lockup from 2004 by Hampa Hug: http://lists.nongnu.org/archive/html/qemu-devel/2004-09/msg00367.html (My patch was partially inspired by his.) Also: http://lists.nongnu.org/archive/html/qemu-devel/2005-06/msg00243.html (I don't have this system to test.) Signed-off-by: Matthew Ogilvie Signed-off-by: malc --- hw/i8259.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'hw') diff --git a/hw/i8259.c b/hw/i8259.c index 6587666..7ecb7e1 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<last_irr &= ~(1<isr &= ~(1<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; } -- cgit v1.1