diff options
author | Andi Kleen <ak@suse.de> | 2007-07-22 05:12:32 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-22 14:03:37 -0400 |
commit | 8f4e956b313dcccbc7be6f10808952345e3b638c (patch) | |
tree | cc8c93fa1faf5e0b608e3a21330a32bd82fe6f47 /arch/x86_64/kernel/nmi.c | |
parent | 19d36ccdc34f5ed444f8a6af0cbfdb6790eb1177 (diff) |
x86: Stop MCEs and NMIs during code patching
When a machine check or NMI occurs while multiple byte code is patched
the CPU could theoretically see an inconsistent instruction and crash.
Prevent this by temporarily disabling MCEs and returning early in the
NMI handler.
Based on discussion with Mathieu Desnoyers.
Cc: Mathieu Desnoyers <compudj@krystal.dyndns.org>
Cc: Jeremy Fitzhardinge <jeremy@goop.org>
Signed-off-by: Andi Kleen <ak@suse.de>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'arch/x86_64/kernel/nmi.c')
-rw-r--r-- | arch/x86_64/kernel/nmi.c | 17 |
1 files changed, 16 insertions, 1 deletions
diff --git a/arch/x86_64/kernel/nmi.c b/arch/x86_64/kernel/nmi.c index edbbc59b7523..cb8ee9d02f86 100644 --- a/arch/x86_64/kernel/nmi.c +++ b/arch/x86_64/kernel/nmi.c | |||
@@ -384,11 +384,14 @@ int __kprobes nmi_watchdog_tick(struct pt_regs * regs, unsigned reason) | |||
384 | return rc; | 384 | return rc; |
385 | } | 385 | } |
386 | 386 | ||
387 | static unsigned ignore_nmis; | ||
388 | |||
387 | asmlinkage __kprobes void do_nmi(struct pt_regs * regs, long error_code) | 389 | asmlinkage __kprobes void do_nmi(struct pt_regs * regs, long error_code) |
388 | { | 390 | { |
389 | nmi_enter(); | 391 | nmi_enter(); |
390 | add_pda(__nmi_count,1); | 392 | add_pda(__nmi_count,1); |
391 | default_do_nmi(regs); | 393 | if (!ignore_nmis) |
394 | default_do_nmi(regs); | ||
392 | nmi_exit(); | 395 | nmi_exit(); |
393 | } | 396 | } |
394 | 397 | ||
@@ -401,6 +404,18 @@ int do_nmi_callback(struct pt_regs * regs, int cpu) | |||
401 | return 0; | 404 | return 0; |
402 | } | 405 | } |
403 | 406 | ||
407 | void stop_nmi(void) | ||
408 | { | ||
409 | acpi_nmi_disable(); | ||
410 | ignore_nmis++; | ||
411 | } | ||
412 | |||
413 | void restart_nmi(void) | ||
414 | { | ||
415 | ignore_nmis--; | ||
416 | acpi_nmi_enable(); | ||
417 | } | ||
418 | |||
404 | #ifdef CONFIG_SYSCTL | 419 | #ifdef CONFIG_SYSCTL |
405 | 420 | ||
406 | static int unknown_nmi_panic_callback(struct pt_regs *regs, int cpu) | 421 | static int unknown_nmi_panic_callback(struct pt_regs *regs, int cpu) |