Commit f278d494 authored by Matthew Ogilvie's avatar Matthew Ogilvie Committed by malc
Browse files

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: default avatarMatthew Ogilvie <mmogilvi_qemu@miniinfo.net>
Signed-off-by: default avatarmalc <av1474@comtv.ru>
parent 482f7bf8
Loading
Loading
Loading
Loading
+9 −5
Original line number Diff line number Diff line
@@ -329,11 +329,15 @@ int cpu_exec(CPUArchState *env)
                                                          0);
                            env->interrupt_request &= ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_VIRQ);
                            intno = cpu_get_pic_interrupt(env);
                            qemu_log_mask(CPU_LOG_TB_IN_ASM, "Servicing hardware INT=0x%02x\n", intno);
                            if (intno >= 0) {
                                qemu_log_mask(CPU_LOG_TB_IN_ASM,
                                              "Servicing hardware INT=0x%02x\n",
                                              intno);
                                do_interrupt_x86_hardirq(env, intno, 1);
                                /* ensure that no TB jump will be modified as
                                   the program flow was changed */
                                next_tb = 0;
                            }
#if !defined(CONFIG_USER_ONLY)
                        } else if ((interrupt_request & CPU_INTERRUPT_VIRQ) &&
                                   (env->eflags & IF_MASK) && 
+18 −0
Original line number Diff line number Diff line
@@ -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;
    }
+12 −0
Original line number Diff line number Diff line
@@ -1189,6 +1189,18 @@ Windows 2000 is installed, you no longer need this option (this option
slows down the IDE transfers).
ETEXI

DEF("no-spurious-interrupt-hack", 0, QEMU_OPTION_no_spurious_interrupt_hack,
    "-no-spurious-interrupt-hack     disable delivery of spurious interrupts\n",
    QEMU_ARCH_I386)
STEXI
@item -no-spurious-interrupt-hack
@findex -no-spurious-interrupt-hack
Use it as a workaround for operating systems that drive PICs in a way that
can generate spurious interrupts, but the OS doesn't handle spurious
interrupts gracefully.  (e.g. late 80s/early 90s versions of ATT UNIX
and derivatives)
ETEXI

HXCOMM Deprecated by -rtc
DEF("rtc-td-hack", 0, QEMU_OPTION_rtc_td_hack, "", QEMU_ARCH_I386)

+1 −0
Original line number Diff line number Diff line
@@ -117,6 +117,7 @@ extern int graphic_depth;
extern DisplayType display_type;
extern const char *keyboard_layout;
extern int win2k_install_hack;
extern int no_spurious_interrupt_hack;
extern int alt_grab;
extern int ctrl_grab;
extern int usb_enabled;
+4 −0
Original line number Diff line number Diff line
@@ -204,6 +204,7 @@ CharDriverState *serial_hds[MAX_SERIAL_PORTS];
CharDriverState *parallel_hds[MAX_PARALLEL_PORTS];
CharDriverState *virtcon_hds[MAX_VIRTIO_CONSOLES];
int win2k_install_hack = 0;
int no_spurious_interrupt_hack = 0;
int usb_enabled = 0;
int singlestep = 0;
int smp_cpus = 1;
@@ -3046,6 +3047,9 @@ int main(int argc, char **argv, char **envp)
            case QEMU_OPTION_win2k_hack:
                win2k_install_hack = 1;
                break;
            case QEMU_OPTION_no_spurious_interrupt_hack:
                no_spurious_interrupt_hack = 1;
                break;
            case QEMU_OPTION_rtc_td_hack: {
                static GlobalProperty slew_lost_ticks[] = {
                    {