nullplan wrote:
EOI to the PIC is a single command, right? It is unlikely that SMM would interfere with that.
I'm not saying that SMM is interfering, but if I don't adjust the backlight brigtness this doesn't happen at all, so SMM/SMI seems related.
nullplan wrote:
Another possibility is that the PIC in your system doesn't work very well with multiple cores. In that case you may get out of it by writing an APIC driver. That is way easier than a full-fledged ACPI driver, you only need to read the static tables, no AML.
Did more experiments as below, x2apic is a smoking gun, but the whole thing is still a mystery.
a. switching to use xapic instead of x2 makes the issue no longer happen even if I try very hard at asjusting the backlight.
b. DMAR table is not opting out of x2.
c. setting up the interrupt remappers makes things worse, as in much easier to get into frozen state using backlight adjust key combos.
d. using high priority vector in the 0xF* range for timer interrupt makes things worse, as in all cores freeze together instead of just core 0.
e. 32b Linux does not use x2 with or without ACPI off on this machine, it doesn't have this problem.
f. 64b Linux uses x2 when it sees the DMAR table, it also sets up the interrupt remappers, and of course(?) it also does not have this problem either. One difference I saw from dmesg is that Linux uses clustered mode and I'm using physical dest mode.
Seems that x2 is not happy with my setup and sometimes gets confused by the events around SMM and my timer handler.
nullplan wrote:
A third possibility is that you have a race condition around interrupt delivery and halting. No way to know without reading your source.
Handler and idle loop code are both of the garden variety.
timer handler C code:
Code:
void handler(...)
{
// bunch of house keeping stuff, doesn't IRET or call anything that won't return.
send_eoi(); // writes 0 to the EOI regiser at offset B0
// scheduler may not return
if (time_to_schedule)
choose_next_task(...);
// NOTE: I thought the scheduler might be too slow?
// but moving send_eoi() to points closer to various irets didn't help either.
}
Its ASM helper pushes registers, calls the C function, pops the registers on return and then irets.
idle loop C code:
Code:
do
{
asm volatile("hlt");
}while(not_done);
What sort of race are you envisioning though?