mirror of https://github.com/xqemu/xqemu.git
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 <mmogilvi_qemu@miniinfo.net> Signed-off-by: malc <av1474@comtv.ru>
This commit is contained in:
parent
482f7bf86b
commit
f278d4947f
14
cpu-exec.c
14
cpu-exec.c
|
@ -329,11 +329,15 @@ int cpu_exec(CPUArchState *env)
|
||||||
0);
|
0);
|
||||||
env->interrupt_request &= ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_VIRQ);
|
env->interrupt_request &= ~(CPU_INTERRUPT_HARD | CPU_INTERRUPT_VIRQ);
|
||||||
intno = cpu_get_pic_interrupt(env);
|
intno = cpu_get_pic_interrupt(env);
|
||||||
qemu_log_mask(CPU_LOG_TB_IN_ASM, "Servicing hardware INT=0x%02x\n", intno);
|
if (intno >= 0) {
|
||||||
do_interrupt_x86_hardirq(env, intno, 1);
|
qemu_log_mask(CPU_LOG_TB_IN_ASM,
|
||||||
/* ensure that no TB jump will be modified as
|
"Servicing hardware INT=0x%02x\n",
|
||||||
the program flow was changed */
|
intno);
|
||||||
next_tb = 0;
|
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)
|
#if !defined(CONFIG_USER_ONLY)
|
||||||
} else if ((interrupt_request & CPU_INTERRUPT_VIRQ) &&
|
} else if ((interrupt_request & CPU_INTERRUPT_VIRQ) &&
|
||||||
(env->eflags & IF_MASK) &&
|
(env->eflags & IF_MASK) &&
|
||||||
|
|
18
hw/i8259.c
18
hw/i8259.c
|
@ -26,6 +26,7 @@
|
||||||
#include "isa.h"
|
#include "isa.h"
|
||||||
#include "monitor.h"
|
#include "monitor.h"
|
||||||
#include "qemu-timer.h"
|
#include "qemu-timer.h"
|
||||||
|
#include "sysemu.h"
|
||||||
#include "i8259_internal.h"
|
#include "i8259_internal.h"
|
||||||
|
|
||||||
/* debug PIC */
|
/* debug PIC */
|
||||||
|
@ -193,6 +194,20 @@ int pic_read_irq(DeviceState *d)
|
||||||
pic_intack(slave_pic, irq2);
|
pic_intack(slave_pic, irq2);
|
||||||
} else {
|
} else {
|
||||||
/* spurious IRQ on slave controller */
|
/* 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;
|
irq2 = 7;
|
||||||
}
|
}
|
||||||
intno = slave_pic->irq_base + irq2;
|
intno = slave_pic->irq_base + irq2;
|
||||||
|
@ -202,6 +217,9 @@ int pic_read_irq(DeviceState *d)
|
||||||
pic_intack(s, irq);
|
pic_intack(s, irq);
|
||||||
} else {
|
} else {
|
||||||
/* spurious IRQ on host controller */
|
/* spurious IRQ on host controller */
|
||||||
|
if (no_spurious_interrupt_hack) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
irq = 7;
|
irq = 7;
|
||||||
intno = s->irq_base + irq;
|
intno = s->irq_base + irq;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1189,6 +1189,18 @@ Windows 2000 is installed, you no longer need this option (this option
|
||||||
slows down the IDE transfers).
|
slows down the IDE transfers).
|
||||||
ETEXI
|
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
|
HXCOMM Deprecated by -rtc
|
||||||
DEF("rtc-td-hack", 0, QEMU_OPTION_rtc_td_hack, "", QEMU_ARCH_I386)
|
DEF("rtc-td-hack", 0, QEMU_OPTION_rtc_td_hack, "", QEMU_ARCH_I386)
|
||||||
|
|
||||||
|
|
1
sysemu.h
1
sysemu.h
|
@ -117,6 +117,7 @@ extern int graphic_depth;
|
||||||
extern DisplayType display_type;
|
extern DisplayType display_type;
|
||||||
extern const char *keyboard_layout;
|
extern const char *keyboard_layout;
|
||||||
extern int win2k_install_hack;
|
extern int win2k_install_hack;
|
||||||
|
extern int no_spurious_interrupt_hack;
|
||||||
extern int alt_grab;
|
extern int alt_grab;
|
||||||
extern int ctrl_grab;
|
extern int ctrl_grab;
|
||||||
extern int usb_enabled;
|
extern int usb_enabled;
|
||||||
|
|
4
vl.c
4
vl.c
|
@ -204,6 +204,7 @@ CharDriverState *serial_hds[MAX_SERIAL_PORTS];
|
||||||
CharDriverState *parallel_hds[MAX_PARALLEL_PORTS];
|
CharDriverState *parallel_hds[MAX_PARALLEL_PORTS];
|
||||||
CharDriverState *virtcon_hds[MAX_VIRTIO_CONSOLES];
|
CharDriverState *virtcon_hds[MAX_VIRTIO_CONSOLES];
|
||||||
int win2k_install_hack = 0;
|
int win2k_install_hack = 0;
|
||||||
|
int no_spurious_interrupt_hack = 0;
|
||||||
int usb_enabled = 0;
|
int usb_enabled = 0;
|
||||||
int singlestep = 0;
|
int singlestep = 0;
|
||||||
int smp_cpus = 1;
|
int smp_cpus = 1;
|
||||||
|
@ -3046,6 +3047,9 @@ int main(int argc, char **argv, char **envp)
|
||||||
case QEMU_OPTION_win2k_hack:
|
case QEMU_OPTION_win2k_hack:
|
||||||
win2k_install_hack = 1;
|
win2k_install_hack = 1;
|
||||||
break;
|
break;
|
||||||
|
case QEMU_OPTION_no_spurious_interrupt_hack:
|
||||||
|
no_spurious_interrupt_hack = 1;
|
||||||
|
break;
|
||||||
case QEMU_OPTION_rtc_td_hack: {
|
case QEMU_OPTION_rtc_td_hack: {
|
||||||
static GlobalProperty slew_lost_ticks[] = {
|
static GlobalProperty slew_lost_ticks[] = {
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue