diff options
Diffstat (limited to 'arch/i386/kernel')
-rw-r--r-- | arch/i386/kernel/alternative.c | 15 | ||||
-rw-r--r-- | arch/i386/kernel/cpu/mcheck/mce.c | 14 | ||||
-rw-r--r-- | arch/i386/kernel/traps.c | 17 |
3 files changed, 45 insertions, 1 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 |
13 | static int smp_alt_once; | 15 | static 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 | /* |
diff --git a/arch/i386/kernel/cpu/mcheck/mce.c b/arch/i386/kernel/cpu/mcheck/mce.c index 56cd485b127c..34c781eddee4 100644 --- a/arch/i386/kernel/cpu/mcheck/mce.c +++ b/arch/i386/kernel/cpu/mcheck/mce.c | |||
@@ -60,6 +60,20 @@ void mcheck_init(struct cpuinfo_x86 *c) | |||
60 | } | 60 | } |
61 | } | 61 | } |
62 | 62 | ||
63 | static unsigned long old_cr4 __initdata; | ||
64 | |||
65 | void __init stop_mce(void) | ||
66 | { | ||
67 | old_cr4 = read_cr4(); | ||
68 | clear_in_cr4(X86_CR4_MCE); | ||
69 | } | ||
70 | |||
71 | void __init restart_mce(void) | ||
72 | { | ||
73 | if (old_cr4 & X86_CR4_MCE) | ||
74 | set_in_cr4(X86_CR4_MCE); | ||
75 | } | ||
76 | |||
63 | static int __init mcheck_disable(char *str) | 77 | static int __init mcheck_disable(char *str) |
64 | { | 78 | { |
65 | mce_disabled = 1; | 79 | mce_disabled = 1; |
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index 438949da3b63..cfffe3dd9e83 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c | |||
@@ -775,6 +775,8 @@ static __kprobes void default_do_nmi(struct pt_regs * regs) | |||
775 | reassert_nmi(); | 775 | reassert_nmi(); |
776 | } | 776 | } |
777 | 777 | ||
778 | static int ignore_nmis; | ||
779 | |||
778 | fastcall __kprobes void do_nmi(struct pt_regs * regs, long error_code) | 780 | fastcall __kprobes void do_nmi(struct pt_regs * regs, long error_code) |
779 | { | 781 | { |
780 | int cpu; | 782 | int cpu; |
@@ -785,11 +787,24 @@ fastcall __kprobes void do_nmi(struct pt_regs * regs, long error_code) | |||
785 | 787 | ||
786 | ++nmi_count(cpu); | 788 | ++nmi_count(cpu); |
787 | 789 | ||
788 | default_do_nmi(regs); | 790 | if (!ignore_nmis) |
791 | default_do_nmi(regs); | ||
789 | 792 | ||
790 | nmi_exit(); | 793 | nmi_exit(); |
791 | } | 794 | } |
792 | 795 | ||
796 | void stop_nmi(void) | ||
797 | { | ||
798 | acpi_nmi_disable(); | ||
799 | ignore_nmis++; | ||
800 | } | ||
801 | |||
802 | void restart_nmi(void) | ||
803 | { | ||
804 | ignore_nmis--; | ||
805 | acpi_nmi_enable(); | ||
806 | } | ||
807 | |||
793 | #ifdef CONFIG_KPROBES | 808 | #ifdef CONFIG_KPROBES |
794 | fastcall void __kprobes do_int3(struct pt_regs *regs, long error_code) | 809 | fastcall void __kprobes do_int3(struct pt_regs *regs, long error_code) |
795 | { | 810 | { |