Hack for qemu's missed LAPIC timers
authorBarret Rhoden <brho@cs.berkeley.edu>
Tue, 3 Dec 2013 06:50:33 +0000 (22:50 -0800)
committerBarret Rhoden <brho@cs.berkeley.edu>
Thu, 16 Jan 2014 21:07:51 +0000 (13:07 -0800)
commit4dae8cf5a2b282af310851e7a92f1f02afe21727
tree2136e2fd8eee65afc9dc57bb35a0b87dd7efbe55
parent4f7c5cbe8654c888c6ce6b1fc97928f94afe6bf9
Hack for qemu's missed LAPIC timers

If your system hangs and needs keyboard input (or network packets) to
wake up, try turning on LOUSY_APIC_TIMER, and report your results to the
mailing list.  We've seen this on qemu with KVM disabled.

Here's part of the email with details from debugging this:

------------------------------
> still, the question is whether or not __trigger was sitting there as
> an RKM while we halted the core, or if the timer IRQ didn't fire
> until we hit the KB.  i'll poke around a bit - i should be able to
> check the RKM queue from qemu.

turns out that we don't have any pending RKMs when everything is
halted (looked at the memory from qemu), which means the timer interrupt
isn't going off (since it should enqueue an RKM).  then once we hit a
key (like CTRL-Q), the timer interrupt does fire before the KB/serial
IRQ; we see the RKM __trigger_tchain queued (via the monitor/kfunc).

so it looks like the timer IRQ should fire, but doesn't.  and then when
we fire some other IRQ, like serial/KB, the timer IRQ does fire.  i
haven't been able to inspect the LAPIC from qemu - that's not the sort
of thing they'd emulate in physical memory for the monitor, i guess.

anyway, perhaps qemu with-no-kvm doesn't like something about our local
apic timer IRQs?  since qemu doesn't report an always running APIC, it's
possible for the timer to stop in deep C states or speedstep
transitions (SDM 3a 10.5.4).  though even when we -enable-kvm, qemu
also reports no "always running APIC."  maybe qemu is getting confused
and turning something off, or i screwed up some initialization?  Or
perhaps qemu doesn't like our use of "hlt", and has some race of it's
own where halt and alarms happen concurrently.

whenever we do break it out (via KB, for instance), we actually get two
IRQs delivered (handle_irq() runs twice from the moment i hit ctrl-q
til we get into the monitor (which happens directly from ctrl-q's IRQ
handler)).  so probably the first IRQ is the LAPIC timer, and the second
is the keyboard.

incidentally, any IRQ, not just a keyboard/serial IRQ, is enough to
break qemu out of its funk.  so instead of holding down the space bar
with a power supply, you can keep trying to telnet to localhost:5555.
=)
kern/arch/x86/Kconfig
kern/arch/x86/apic.c