Thanks to Bernhard Kauer for pointing out the problem. Apparently
if software disables LVT_LINT0 when there is a pending
CPU_HARD_INTERRUPT you can get into trouble. I attached a patch
that fixes the problem by resetting the interrupt_request. I am not
sure if we need to do the same for LINT1, but this fixed the
incorrect GPF I was getting.
--Sam
On 9/28/10 10:15 AM, Sam King wrote:
Hello,
I am seeing a weird crash in my system and I am trying to figure
out if it is a software bug or a qemu emulation bug. From the
software perspective I am getting a GP fault at a time where it
looks like everything should be running normally. After digging
into the Qemu source code I found out where the GPF was coming
from. It looks like intno = -1 when it was being passed into
do_interrupt64, which was triggering one of the GPF checks.
From what I can tell, intno was being set to -1 by an
interrupt_request in cpu-exec.c, which was going down the
following if statement around line 409 of that file:
else if ((interrupt_request & CPU_INTERRUPT_HARD) &&
(((env->hflags2 &
HF2_VINTR_MASK) &&
(env->hflags2 &
HF2_HIF_MASK)) ||
(!(env->hflags2 &
HF2_VINTR_MASK) &&
(env->eflags &
IF_MASK &&
!(env->hflags &
HF_INHIBIT_IRQ_MASK)))))
and from within that else if statement, env has the following
state:
hflags2 = 0x00000001
eflags = 0x00003202
hflags = 0x0040c0b7
interrupt request = 0x00000002
But intno is being set equal to -1 by the call to
cpu_get_pic_interrupt, from the call to apic_accept_pic_intr
returning 0. If I change the cpu_get_pic_interrupt code to
this:
int cpu_get_pic_interrupt(CPUState *env)
{
int intno;
intno = apic_get_interrupt(env);
if (intno >= 0) {
/* set irq request if a PIC irq is still pending */
/* XXX: improve that */
pic_update_irq(isa_pic);
return intno;
}
/* read the irq from the PIC */
if (!apic_accept_pic_intr(env)) {
//return -1;
}
intno = pic_read_irq(isa_pic);
return intno;
}
Then the issue manifests as a spurious interrupt and the
software ignores it, avoiding the GPF. Does anyone have any
ideas as to what is going wrong here? Should I look more
closely at the Qemu emulation code or my software? Any help is
appreciated.
Thanks!
--Sam
|