aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/kernel/traps.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/i386/kernel/traps.c')
-rw-r--r--arch/i386/kernel/traps.c163
1 files changed, 67 insertions, 96 deletions
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
index 00489b706d27..2b30dbf8d117 100644
--- a/arch/i386/kernel/traps.c
+++ b/arch/i386/kernel/traps.c
@@ -29,6 +29,8 @@
29#include <linux/kexec.h> 29#include <linux/kexec.h>
30#include <linux/unwind.h> 30#include <linux/unwind.h>
31#include <linux/uaccess.h> 31#include <linux/uaccess.h>
32#include <linux/nmi.h>
33#include <linux/bug.h>
32 34
33#ifdef CONFIG_EISA 35#ifdef CONFIG_EISA
34#include <linux/ioport.h> 36#include <linux/ioport.h>
@@ -61,9 +63,6 @@ int panic_on_unrecovered_nmi;
61 63
62asmlinkage int system_call(void); 64asmlinkage int system_call(void);
63 65
64struct desc_struct default_ldt[] = { { 0, 0 }, { 0, 0 }, { 0, 0 },
65 { 0, 0 }, { 0, 0 } };
66
67/* Do we ignore FPU interrupts ? */ 66/* Do we ignore FPU interrupts ? */
68char ignore_fpu_irq = 0; 67char ignore_fpu_irq = 0;
69 68
@@ -94,7 +93,7 @@ asmlinkage void alignment_check(void);
94asmlinkage void spurious_interrupt_bug(void); 93asmlinkage void spurious_interrupt_bug(void);
95asmlinkage void machine_check(void); 94asmlinkage void machine_check(void);
96 95
97static int kstack_depth_to_print = 24; 96int kstack_depth_to_print = 24;
98#ifdef CONFIG_STACK_UNWIND 97#ifdef CONFIG_STACK_UNWIND
99static int call_trace = 1; 98static int call_trace = 1;
100#else 99#else
@@ -129,15 +128,19 @@ static inline unsigned long print_context_stack(struct thread_info *tinfo,
129 128
130#ifdef CONFIG_FRAME_POINTER 129#ifdef CONFIG_FRAME_POINTER
131 while (valid_stack_ptr(tinfo, (void *)ebp)) { 130 while (valid_stack_ptr(tinfo, (void *)ebp)) {
131 unsigned long new_ebp;
132 addr = *(unsigned long *)(ebp + 4); 132 addr = *(unsigned long *)(ebp + 4);
133 ops->address(data, addr); 133 ops->address(data, addr);
134 /* 134 /*
135 * break out of recursive entries (such as 135 * break out of recursive entries (such as
136 * end_of_stack_stop_unwind_function): 136 * end_of_stack_stop_unwind_function). Also,
137 * we can never allow a frame pointer to
138 * move downwards!
137 */ 139 */
138 if (ebp == *(unsigned long *)ebp) 140 new_ebp = *(unsigned long *)ebp;
141 if (new_ebp <= ebp)
139 break; 142 break;
140 ebp = *(unsigned long *)ebp; 143 ebp = new_ebp;
141 } 144 }
142#else 145#else
143 while (valid_stack_ptr(tinfo, stack)) { 146 while (valid_stack_ptr(tinfo, stack)) {
@@ -159,16 +162,25 @@ dump_trace_unwind(struct unwind_frame_info *info, void *data)
159{ 162{
160 struct ops_and_data *oad = (struct ops_and_data *)data; 163 struct ops_and_data *oad = (struct ops_and_data *)data;
161 int n = 0; 164 int n = 0;
165 unsigned long sp = UNW_SP(info);
162 166
167 if (arch_unw_user_mode(info))
168 return -1;
163 while (unwind(info) == 0 && UNW_PC(info)) { 169 while (unwind(info) == 0 && UNW_PC(info)) {
164 n++; 170 n++;
165 oad->ops->address(oad->data, UNW_PC(info)); 171 oad->ops->address(oad->data, UNW_PC(info));
166 if (arch_unw_user_mode(info)) 172 if (arch_unw_user_mode(info))
167 break; 173 break;
174 if ((sp & ~(PAGE_SIZE - 1)) == (UNW_SP(info) & ~(PAGE_SIZE - 1))
175 && sp > UNW_SP(info))
176 break;
177 sp = UNW_SP(info);
168 } 178 }
169 return n; 179 return n;
170} 180}
171 181
182#define MSG(msg) ops->warning(data, msg)
183
172void dump_trace(struct task_struct *task, struct pt_regs *regs, 184void dump_trace(struct task_struct *task, struct pt_regs *regs,
173 unsigned long *stack, 185 unsigned long *stack,
174 struct stacktrace_ops *ops, void *data) 186 struct stacktrace_ops *ops, void *data)
@@ -187,29 +199,31 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,
187 if (unwind_init_frame_info(&info, task, regs) == 0) 199 if (unwind_init_frame_info(&info, task, regs) == 0)
188 unw_ret = dump_trace_unwind(&info, &oad); 200 unw_ret = dump_trace_unwind(&info, &oad);
189 } else if (task == current) 201 } else if (task == current)
190 unw_ret = unwind_init_running(&info, dump_trace_unwind, &oad); 202 unw_ret = unwind_init_running(&info, dump_trace_unwind,
203 &oad);
191 else { 204 else {
192 if (unwind_init_blocked(&info, task) == 0) 205 if (unwind_init_blocked(&info, task) == 0)
193 unw_ret = dump_trace_unwind(&info, &oad); 206 unw_ret = dump_trace_unwind(&info, &oad);
194 } 207 }
195 if (unw_ret > 0) { 208 if (unw_ret > 0) {
196 if (call_trace == 1 && !arch_unw_user_mode(&info)) { 209 if (call_trace == 1 && !arch_unw_user_mode(&info)) {
197 ops->warning_symbol(data, "DWARF2 unwinder stuck at %s\n", 210 ops->warning_symbol(data,
211 "DWARF2 unwinder stuck at %s",
198 UNW_PC(&info)); 212 UNW_PC(&info));
199 if (UNW_SP(&info) >= PAGE_OFFSET) { 213 if (UNW_SP(&info) >= PAGE_OFFSET) {
200 ops->warning(data, "Leftover inexact backtrace:\n"); 214 MSG("Leftover inexact backtrace:");
201 stack = (void *)UNW_SP(&info); 215 stack = (void *)UNW_SP(&info);
202 if (!stack) 216 if (!stack)
203 return; 217 return;
204 ebp = UNW_FP(&info); 218 ebp = UNW_FP(&info);
205 } else 219 } else
206 ops->warning(data, "Full inexact backtrace again:\n"); 220 MSG("Full inexact backtrace again:");
207 } else if (call_trace >= 1) 221 } else if (call_trace >= 1)
208 return; 222 return;
209 else 223 else
210 ops->warning(data, "Full inexact backtrace again:\n"); 224 MSG("Full inexact backtrace again:");
211 } else 225 } else
212 ops->warning(data, "Inexact backtrace:\n"); 226 MSG("Inexact backtrace:");
213 } 227 }
214 if (!stack) { 228 if (!stack) {
215 unsigned long dummy; 229 unsigned long dummy;
@@ -243,6 +257,7 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,
243 stack = (unsigned long*)context->previous_esp; 257 stack = (unsigned long*)context->previous_esp;
244 if (!stack) 258 if (!stack)
245 break; 259 break;
260 touch_nmi_watchdog();
246 } 261 }
247} 262}
248EXPORT_SYMBOL(dump_trace); 263EXPORT_SYMBOL(dump_trace);
@@ -375,7 +390,7 @@ void show_registers(struct pt_regs *regs)
375 * time of the fault.. 390 * time of the fault..
376 */ 391 */
377 if (in_kernel) { 392 if (in_kernel) {
378 u8 __user *eip; 393 u8 *eip;
379 int code_bytes = 64; 394 int code_bytes = 64;
380 unsigned char c; 395 unsigned char c;
381 396
@@ -384,18 +399,20 @@ void show_registers(struct pt_regs *regs)
384 399
385 printk(KERN_EMERG "Code: "); 400 printk(KERN_EMERG "Code: ");
386 401
387 eip = (u8 __user *)regs->eip - 43; 402 eip = (u8 *)regs->eip - 43;
388 if (eip < (u8 __user *)PAGE_OFFSET || __get_user(c, eip)) { 403 if (eip < (u8 *)PAGE_OFFSET ||
404 probe_kernel_address(eip, c)) {
389 /* try starting at EIP */ 405 /* try starting at EIP */
390 eip = (u8 __user *)regs->eip; 406 eip = (u8 *)regs->eip;
391 code_bytes = 32; 407 code_bytes = 32;
392 } 408 }
393 for (i = 0; i < code_bytes; i++, eip++) { 409 for (i = 0; i < code_bytes; i++, eip++) {
394 if (eip < (u8 __user *)PAGE_OFFSET || __get_user(c, eip)) { 410 if (eip < (u8 *)PAGE_OFFSET ||
411 probe_kernel_address(eip, c)) {
395 printk(" Bad EIP value."); 412 printk(" Bad EIP value.");
396 break; 413 break;
397 } 414 }
398 if (eip == (u8 __user *)regs->eip) 415 if (eip == (u8 *)regs->eip)
399 printk("<%02x> ", c); 416 printk("<%02x> ", c);
400 else 417 else
401 printk("%02x ", c); 418 printk("%02x ", c);
@@ -404,43 +421,22 @@ void show_registers(struct pt_regs *regs)
404 printk("\n"); 421 printk("\n");
405} 422}
406 423
407static void handle_BUG(struct pt_regs *regs) 424int is_valid_bugaddr(unsigned long eip)
408{ 425{
409 unsigned long eip = regs->eip;
410 unsigned short ud2; 426 unsigned short ud2;
411 427
412 if (eip < PAGE_OFFSET) 428 if (eip < PAGE_OFFSET)
413 return; 429 return 0;
414 if (probe_kernel_address((unsigned short __user *)eip, ud2)) 430 if (probe_kernel_address((unsigned short *)eip, ud2))
415 return; 431 return 0;
416 if (ud2 != 0x0b0f)
417 return;
418
419 printk(KERN_EMERG "------------[ cut here ]------------\n");
420
421#ifdef CONFIG_DEBUG_BUGVERBOSE
422 do {
423 unsigned short line;
424 char *file;
425 char c;
426
427 if (probe_kernel_address((unsigned short __user *)(eip + 2),
428 line))
429 break;
430 if (__get_user(file, (char * __user *)(eip + 4)) ||
431 (unsigned long)file < PAGE_OFFSET || __get_user(c, file))
432 file = "<bad filename>";
433 432
434 printk(KERN_EMERG "kernel BUG at %s:%d!\n", file, line); 433 return ud2 == 0x0b0f;
435 return;
436 } while (0);
437#endif
438 printk(KERN_EMERG "Kernel BUG at [verbose debug info unavailable]\n");
439} 434}
440 435
441/* This is gone through when something in the kernel 436/*
442 * has done something bad and is about to be terminated. 437 * This is gone through when something in the kernel has done something bad and
443*/ 438 * is about to be terminated.
439 */
444void die(const char * str, struct pt_regs * regs, long err) 440void die(const char * str, struct pt_regs * regs, long err)
445{ 441{
446 static struct { 442 static struct {
@@ -448,7 +444,7 @@ void die(const char * str, struct pt_regs * regs, long err)
448 u32 lock_owner; 444 u32 lock_owner;
449 int lock_owner_depth; 445 int lock_owner_depth;
450 } die = { 446 } die = {
451 .lock = SPIN_LOCK_UNLOCKED, 447 .lock = __SPIN_LOCK_UNLOCKED(die.lock),
452 .lock_owner = -1, 448 .lock_owner = -1,
453 .lock_owner_depth = 0 449 .lock_owner_depth = 0
454 }; 450 };
@@ -472,7 +468,8 @@ void die(const char * str, struct pt_regs * regs, long err)
472 unsigned long esp; 468 unsigned long esp;
473 unsigned short ss; 469 unsigned short ss;
474 470
475 handle_BUG(regs); 471 report_bug(regs->eip);
472
476 printk(KERN_EMERG "%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter); 473 printk(KERN_EMERG "%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter);
477#ifdef CONFIG_PREEMPT 474#ifdef CONFIG_PREEMPT
478 printk(KERN_EMERG "PREEMPT "); 475 printk(KERN_EMERG "PREEMPT ");
@@ -703,8 +700,7 @@ mem_parity_error(unsigned char reason, struct pt_regs * regs)
703{ 700{
704 printk(KERN_EMERG "Uhhuh. NMI received for unknown reason %02x on " 701 printk(KERN_EMERG "Uhhuh. NMI received for unknown reason %02x on "
705 "CPU %d.\n", reason, smp_processor_id()); 702 "CPU %d.\n", reason, smp_processor_id());
706 printk(KERN_EMERG "You probably have a hardware problem with your RAM " 703 printk(KERN_EMERG "You have some hardware problem, likely on the PCI bus.\n");
707 "chips\n");
708 if (panic_on_unrecovered_nmi) 704 if (panic_on_unrecovered_nmi)
709 panic("NMI: Not continuing"); 705 panic("NMI: Not continuing");
710 706
@@ -769,7 +765,6 @@ void __kprobes die_nmi(struct pt_regs *regs, const char *msg)
769 printk(" on CPU%d, eip %08lx, registers:\n", 765 printk(" on CPU%d, eip %08lx, registers:\n",
770 smp_processor_id(), regs->eip); 766 smp_processor_id(), regs->eip);
771 show_registers(regs); 767 show_registers(regs);
772 printk(KERN_EMERG "console shuts up ...\n");
773 console_silent(); 768 console_silent();
774 spin_unlock(&nmi_print_lock); 769 spin_unlock(&nmi_print_lock);
775 bust_spinlocks(0); 770 bust_spinlocks(0);
@@ -1084,49 +1079,24 @@ fastcall void do_spurious_interrupt_bug(struct pt_regs * regs,
1084#endif 1079#endif
1085} 1080}
1086 1081
1087fastcall void setup_x86_bogus_stack(unsigned char * stk) 1082fastcall unsigned long patch_espfix_desc(unsigned long uesp,
1088{ 1083 unsigned long kesp)
1089 unsigned long *switch16_ptr, *switch32_ptr;
1090 struct pt_regs *regs;
1091 unsigned long stack_top, stack_bot;
1092 unsigned short iret_frame16_off;
1093 int cpu = smp_processor_id();
1094 /* reserve the space on 32bit stack for the magic switch16 pointer */
1095 memmove(stk, stk + 8, sizeof(struct pt_regs));
1096 switch16_ptr = (unsigned long *)(stk + sizeof(struct pt_regs));
1097 regs = (struct pt_regs *)stk;
1098 /* now the switch32 on 16bit stack */
1099 stack_bot = (unsigned long)&per_cpu(cpu_16bit_stack, cpu);
1100 stack_top = stack_bot + CPU_16BIT_STACK_SIZE;
1101 switch32_ptr = (unsigned long *)(stack_top - 8);
1102 iret_frame16_off = CPU_16BIT_STACK_SIZE - 8 - 20;
1103 /* copy iret frame on 16bit stack */
1104 memcpy((void *)(stack_bot + iret_frame16_off), &regs->eip, 20);
1105 /* fill in the switch pointers */
1106 switch16_ptr[0] = (regs->esp & 0xffff0000) | iret_frame16_off;
1107 switch16_ptr[1] = __ESPFIX_SS;
1108 switch32_ptr[0] = (unsigned long)stk + sizeof(struct pt_regs) +
1109 8 - CPU_16BIT_STACK_SIZE;
1110 switch32_ptr[1] = __KERNEL_DS;
1111}
1112
1113fastcall unsigned char * fixup_x86_bogus_stack(unsigned short sp)
1114{ 1084{
1115 unsigned long *switch32_ptr;
1116 unsigned char *stack16, *stack32;
1117 unsigned long stack_top, stack_bot;
1118 int len;
1119 int cpu = smp_processor_id(); 1085 int cpu = smp_processor_id();
1120 stack_bot = (unsigned long)&per_cpu(cpu_16bit_stack, cpu); 1086 struct Xgt_desc_struct *cpu_gdt_descr = &per_cpu(cpu_gdt_descr, cpu);
1121 stack_top = stack_bot + CPU_16BIT_STACK_SIZE; 1087 struct desc_struct *gdt = (struct desc_struct *)cpu_gdt_descr->address;
1122 switch32_ptr = (unsigned long *)(stack_top - 8); 1088 unsigned long base = (kesp - uesp) & -THREAD_SIZE;
1123 /* copy the data from 16bit stack to 32bit stack */ 1089 unsigned long new_kesp = kesp - base;
1124 len = CPU_16BIT_STACK_SIZE - 8 - sp; 1090 unsigned long lim_pages = (new_kesp | (THREAD_SIZE - 1)) >> PAGE_SHIFT;
1125 stack16 = (unsigned char *)(stack_bot + sp); 1091 __u64 desc = *(__u64 *)&gdt[GDT_ENTRY_ESPFIX_SS];
1126 stack32 = (unsigned char *) 1092 /* Set up base for espfix segment */
1127 (switch32_ptr[0] + CPU_16BIT_STACK_SIZE - 8 - len); 1093 desc &= 0x00f0ff0000000000ULL;
1128 memcpy(stack32, stack16, len); 1094 desc |= ((((__u64)base) << 16) & 0x000000ffffff0000ULL) |
1129 return stack32; 1095 ((((__u64)base) << 32) & 0xff00000000000000ULL) |
1096 ((((__u64)lim_pages) << 32) & 0x000f000000000000ULL) |
1097 (lim_pages & 0xffff);
1098 *(__u64 *)&gdt[GDT_ENTRY_ESPFIX_SS] = desc;
1099 return new_kesp;
1130} 1100}
1131 1101
1132/* 1102/*
@@ -1139,7 +1109,7 @@ fastcall unsigned char * fixup_x86_bogus_stack(unsigned short sp)
1139 * Must be called with kernel preemption disabled (in this case, 1109 * Must be called with kernel preemption disabled (in this case,
1140 * local interrupts are disabled at the call-site in entry.S). 1110 * local interrupts are disabled at the call-site in entry.S).
1141 */ 1111 */
1142asmlinkage void math_state_restore(struct pt_regs regs) 1112asmlinkage void math_state_restore(void)
1143{ 1113{
1144 struct thread_info *thread = current_thread_info(); 1114 struct thread_info *thread = current_thread_info();
1145 struct task_struct *tsk = thread->task; 1115 struct task_struct *tsk = thread->task;
@@ -1149,6 +1119,7 @@ asmlinkage void math_state_restore(struct pt_regs regs)
1149 init_fpu(tsk); 1119 init_fpu(tsk);
1150 restore_fpu(tsk); 1120 restore_fpu(tsk);
1151 thread->status |= TS_USEDFPU; /* So we fnsave on switch_to() */ 1121 thread->status |= TS_USEDFPU; /* So we fnsave on switch_to() */
1122 tsk->fpu_counter++;
1152} 1123}
1153 1124
1154#ifndef CONFIG_MATH_EMULATION 1125#ifndef CONFIG_MATH_EMULATION