aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386
diff options
context:
space:
mode:
Diffstat (limited to 'arch/i386')
-rw-r--r--arch/i386/kernel/crash.c13
1 files changed, 13 insertions, 0 deletions
diff --git a/arch/i386/kernel/crash.c b/arch/i386/kernel/crash.c
index 3645ad7ac200..31e077bb0caa 100644
--- a/arch/i386/kernel/crash.c
+++ b/arch/i386/kernel/crash.c
@@ -112,7 +112,20 @@ static atomic_t waiting_for_crash_ipi;
112 112
113static int crash_nmi_callback(struct pt_regs *regs, int cpu) 113static int crash_nmi_callback(struct pt_regs *regs, int cpu)
114{ 114{
115 struct pt_regs fixed_regs;
115 local_irq_disable(); 116 local_irq_disable();
117
118 /* CPU does not save ss and esp on stack if execution is already
119 * running in kernel mode at the time of NMI occurrence. This code
120 * fixes it.
121 */
122 if (!user_mode(regs)) {
123 memcpy(&fixed_regs, regs, sizeof(*regs));
124 fixed_regs.esp = (unsigned long)&(regs->esp);
125 __asm__ __volatile__("xorl %eax, %eax;");
126 __asm__ __volatile__ ("movw %%ss, %%ax;" :"=a"(fixed_regs.xss));
127 regs = &fixed_regs;
128 }
116 crash_save_this_cpu(regs, cpu); 129 crash_save_this_cpu(regs, cpu);
117 disable_local_APIC(); 130 disable_local_APIC();
118 atomic_dec(&waiting_for_crash_ipi); 131 atomic_dec(&waiting_for_crash_ipi);