aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/kernel/crash.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/i386/kernel/crash.c')
-rw-r--r--arch/i386/kernel/crash.c36
1 files changed, 24 insertions, 12 deletions
diff --git a/arch/i386/kernel/crash.c b/arch/i386/kernel/crash.c
index a021681d21f8..8bdb4b6af0ff 100644
--- a/arch/i386/kernel/crash.c
+++ b/arch/i386/kernel/crash.c
@@ -100,12 +100,31 @@ static void crash_get_current_regs(struct pt_regs *regs)
100 regs->eip = (unsigned long)current_text_addr(); 100 regs->eip = (unsigned long)current_text_addr();
101} 101}
102 102
103static void crash_save_self(void) 103/* CPU does not save ss and esp on stack if execution is already
104 * running in kernel mode at the time of NMI occurrence. This code
105 * fixes it.
106 */
107static void crash_setup_regs(struct pt_regs *newregs, struct pt_regs *oldregs)
108{
109 memcpy(newregs, oldregs, sizeof(*newregs));
110 newregs->esp = (unsigned long)&(oldregs->esp);
111 __asm__ __volatile__("xorl %eax, %eax;");
112 __asm__ __volatile__ ("movw %%ss, %%ax;" :"=a"(newregs->xss));
113}
114
115/* We may have saved_regs from where the error came from
116 * or it is NULL if via a direct panic().
117 */
118static void crash_save_self(struct pt_regs *saved_regs)
104{ 119{
105 struct pt_regs regs; 120 struct pt_regs regs;
106 int cpu; 121 int cpu;
107 cpu = smp_processor_id(); 122 cpu = smp_processor_id();
108 crash_get_current_regs(&regs); 123
124 if (saved_regs)
125 crash_setup_regs(&regs, saved_regs);
126 else
127 crash_get_current_regs(&regs);
109 crash_save_this_cpu(&regs, cpu); 128 crash_save_this_cpu(&regs, cpu);
110} 129}
111 130
@@ -124,15 +143,8 @@ static int crash_nmi_callback(struct pt_regs *regs, int cpu)
124 return 1; 143 return 1;
125 local_irq_disable(); 144 local_irq_disable();
126 145
127 /* CPU does not save ss and esp on stack if execution is already
128 * running in kernel mode at the time of NMI occurrence. This code
129 * fixes it.
130 */
131 if (!user_mode(regs)) { 146 if (!user_mode(regs)) {
132 memcpy(&fixed_regs, regs, sizeof(*regs)); 147 crash_setup_regs(&fixed_regs, regs);
133 fixed_regs.esp = (unsigned long)&(regs->esp);
134 __asm__ __volatile__("xorl %eax, %eax;");
135 __asm__ __volatile__ ("movw %%ss, %%ax;" :"=a"(fixed_regs.xss));
136 regs = &fixed_regs; 148 regs = &fixed_regs;
137 } 149 }
138 crash_save_this_cpu(regs, cpu); 150 crash_save_this_cpu(regs, cpu);
@@ -184,7 +196,7 @@ static void nmi_shootdown_cpus(void)
184} 196}
185#endif 197#endif
186 198
187void machine_crash_shutdown(void) 199void machine_crash_shutdown(struct pt_regs *regs)
188{ 200{
189 /* This function is only called after the system 201 /* This function is only called after the system
190 * has paniced or is otherwise in a critical state. 202 * has paniced or is otherwise in a critical state.
@@ -204,5 +216,5 @@ void machine_crash_shutdown(void)
204#if defined(CONFIG_X86_IO_APIC) 216#if defined(CONFIG_X86_IO_APIC)
205 disable_IO_APIC(); 217 disable_IO_APIC();
206#endif 218#endif
207 crash_save_self(); 219 crash_save_self(regs);
208} 220}