aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/kernel/alternative.c
diff options
context:
space:
mode:
authorAndi Kleen <ak@suse.de>2007-07-22 05:12:32 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-22 14:03:37 -0400
commit8f4e956b313dcccbc7be6f10808952345e3b638c (patch)
treecc8c93fa1faf5e0b608e3a21330a32bd82fe6f47 /arch/i386/kernel/alternative.c
parent19d36ccdc34f5ed444f8a6af0cbfdb6790eb1177 (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/i386/kernel/alternative.c')
-rw-r--r--arch/i386/kernel/alternative.c15
1 files changed, 15 insertions, 0 deletions
diff --git a/arch/i386/kernel/alternative.c b/arch/i386/kernel/alternative.c
index 206ea2ca63cc..c3750c2c4113 100644
--- a/arch/i386/kernel/alternative.c
+++ b/arch/i386/kernel/alternative.c
@@ -8,6 +8,8 @@
8#include <asm/alternative.h> 8#include <asm/alternative.h>
9#include <asm/sections.h> 9#include <asm/sections.h>
10#include <asm/pgtable.h> 10#include <asm/pgtable.h>
11#include <asm/mce.h>
12#include <asm/nmi.h>
11 13
12#ifdef CONFIG_HOTPLUG_CPU 14#ifdef CONFIG_HOTPLUG_CPU
13static int smp_alt_once; 15static int smp_alt_once;
@@ -373,6 +375,14 @@ void __init alternative_instructions(void)
373{ 375{
374 unsigned long flags; 376 unsigned long flags;
375 377
378 /* The patching is not fully atomic, so try to avoid local interruptions
379 that might execute the to be patched code.
380 Other CPUs are not running. */
381 stop_nmi();
382#ifdef CONFIG_MCE
383 stop_mce();
384#endif
385
376 local_irq_save(flags); 386 local_irq_save(flags);
377 apply_alternatives(__alt_instructions, __alt_instructions_end); 387 apply_alternatives(__alt_instructions, __alt_instructions_end);
378 388
@@ -405,6 +415,11 @@ void __init alternative_instructions(void)
405#endif 415#endif
406 apply_paravirt(__parainstructions, __parainstructions_end); 416 apply_paravirt(__parainstructions, __parainstructions_end);
407 local_irq_restore(flags); 417 local_irq_restore(flags);
418
419 restart_nmi();
420#ifdef CONFIG_MCE
421 restart_mce();
422#endif
408} 423}
409 424
410/* 425/*