summaryrefslogtreecommitdiffstats
path: root/arch/i386
diff options
context:
space:
mode:
authorZachary Amsden <zach@vmware.com>2006-10-19 23:29:04 -0700
committerLinus Torvalds <torvalds@g5.osdl.org>2006-10-20 10:26:43 -0700
commite51959faa61278c762389802faf8ba1a40676628 (patch)
treeaadebbc601f7132a830d9dc33fc90f83af7bab6a /arch/i386
parenta90b061c0bf712961cea40d9c916b300073d12e5 (diff)
downloadlinux-e51959faa61278c762389802faf8ba1a40676628.tar.gz
linux-e51959faa61278c762389802faf8ba1a40676628.tar.bz2
linux-e51959faa61278c762389802faf8ba1a40676628.zip
[PATCH] Fix potential interrupts during alternative patching
Interrupts must be disabled during alternative instruction patching. On systems with high timer IRQ rates, or when running in an emulator, timing differences can result in random kernel panics because of running partially patched instructions. This doesn't yet fix NMIs, which requires extricating the patch code from the late bug checking and is logically separate (and also less likely to cause problems). Signed-off-by: Zachary Amsden <zach@vmware.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/i386')
-rw-r--r--arch/i386/kernel/alternative.c4
1 files changed, 4 insertions, 0 deletions
diff --git a/arch/i386/kernel/alternative.c b/arch/i386/kernel/alternative.c
index 28ab80649764..583c238e17fb 100644
--- a/arch/i386/kernel/alternative.c
+++ b/arch/i386/kernel/alternative.c
@@ -344,6 +344,7 @@ void alternatives_smp_switch(int smp)
void __init alternative_instructions(void)
{
+ unsigned long flags;
if (no_replacement) {
printk(KERN_INFO "(SMP-)alternatives turned off\n");
free_init_pages("SMP alternatives",
@@ -351,6 +352,8 @@ void __init alternative_instructions(void)
(unsigned long)__smp_alt_end);
return;
}
+
+ local_irq_save(flags);
apply_alternatives(__alt_instructions, __alt_instructions_end);
/* switch to patch-once-at-boottime-only mode and free the
@@ -386,4 +389,5 @@ void __init alternative_instructions(void)
alternatives_smp_switch(0);
}
#endif
+ local_irq_restore(flags);
}