Re: [patch, 2.6.10-rc3] safe_hlt() & NMIs

From: Ingo Molnar
Date: Tue Dec 14 2004 - 17:56:54 EST

* Ingo Molnar <mingo@xxxxxxx> wrote:

> indeed, there could be a connection, and it's certainly a fun race.
> The proper fix is Manfred's suggestion: check whether the EIP is a
> kernel text address, and if yes, whether it's a HLT instruction - and
> if yes then increase EIP by 1. I've included the fix in the -33-02 -RT
> patch. Andrew, Linus: upstream fix is below - i think it's post-2.6.10
> stuff. Tested it on SMP and UP x86, using both the IO-APIC and the
> local-APIC based NMI watchdog.
> i think x64 needs a similar fix as well.

find the correct patch below. I've tested it with an NMI watchdog
frequency artificially increased to 10 KHz, and i've instrumented the
new branch in the NMI handler, but even under heavy IRQ load i was not
able to trigger the branch. Maybe newer CPUs handle this case somehow
and make sti;hlt truly atomic? I tried this on an old Celeron
(Mendocino) and on an Athlon64.


Signed-off-by: Ingo Molnar <mingo@xxxxxxx>

--- linux/arch/i386/kernel/traps.c.orig
+++ linux/arch/i386/kernel/traps.c
@@ -670,6 +670,18 @@ fastcall void do_nmi(struct pt_regs * re

cpu = smp_processor_id();

+ /*
+ * Fix up obscure CPU behavior: if we interrupt safe_hlt() via
+ * the NMI then we might miss a reschedule if an interrupt is
+ * posted to the CPU and executes before the HLT instruction.
+ *
+ * We check whether the EIP is kernelspace, and if yes, whether
+ * the instruction is HLT:
+ */
+ if (__kernel_text_address(regs->eip) &&
+ *(unsigned char *)regs->eip == 0xf4)
+ regs->eip++;
if (!cpu_online(cpu)) {
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at
Please read the FAQ at