aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArjan van de Ven <arjan@linux.intel.com>2008-01-30 07:33:08 -0500
committerIngo Molnar <mingo@elte.hu>2008-01-30 07:33:08 -0500
commita25bd94964e87b1b93903a822fba5025d995d4da (patch)
tree67208bd1666760ac0d0d9c01c3be2a1b12f5aae3
parent6dab27784b2a97823b522e1cb88e40be40a93d45 (diff)
x86: add the "print code before the trapping instruction" feature to 64 bit
The 32 bit x86 tree has a very useful feature that prints the Code: line for the code even before the trapping instrution (and the start of the trapping instruction is then denoted with a <>). Unfortunately, the 64 bit x86 tree does not yet have this feature, making diagnosing backtraces harder than needed. This patch adds this feature in the same was as the 32 bit tree has (including the same kernel boot parameter), and including a bugfix to make the code use probe_kernel_address() rarther than a buggy (deadlocking) __get_user. Signed-off-by: Arjan van de Ven <arjan@linux.intel.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
-rw-r--r--Documentation/kernel-parameters.txt4
-rw-r--r--arch/x86/kernel/traps_64.c44
2 files changed, 35 insertions, 13 deletions
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index e7910f8b4fcc..40db7dd1d92a 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -416,8 +416,8 @@ and is between 256 and 4096 characters. It is defined in the file
416 [SPARC64] tick 416 [SPARC64] tick
417 [X86-64] hpet,tsc 417 [X86-64] hpet,tsc
418 418
419 code_bytes [IA32] How many bytes of object code to print in an 419 code_bytes [IA32/X86_64] How many bytes of object code to print
420 oops report. 420 in an oops report.
421 Range: 0 - 8192 421 Range: 0 - 8192
422 Default: 64 422 Default: 64
423 423
diff --git a/arch/x86/kernel/traps_64.c b/arch/x86/kernel/traps_64.c
index 304ca6b4a1ca..0bba7924604e 100644
--- a/arch/x86/kernel/traps_64.c
+++ b/arch/x86/kernel/traps_64.c
@@ -74,6 +74,8 @@ asmlinkage void alignment_check(void);
74asmlinkage void machine_check(void); 74asmlinkage void machine_check(void);
75asmlinkage void spurious_interrupt_bug(void); 75asmlinkage void spurious_interrupt_bug(void);
76 76
77static unsigned int code_bytes = 64;
78
77static inline void conditional_sti(struct pt_regs *regs) 79static inline void conditional_sti(struct pt_regs *regs)
78{ 80{
79 if (regs->flags & X86_EFLAGS_IF) 81 if (regs->flags & X86_EFLAGS_IF)
@@ -459,12 +461,15 @@ EXPORT_SYMBOL(dump_stack);
459void show_registers(struct pt_regs *regs) 461void show_registers(struct pt_regs *regs)
460{ 462{
461 int i; 463 int i;
462 int in_kernel = !user_mode(regs);
463 unsigned long sp; 464 unsigned long sp;
464 const int cpu = smp_processor_id(); 465 const int cpu = smp_processor_id();
465 struct task_struct *cur = cpu_pda(cpu)->pcurrent; 466 struct task_struct *cur = cpu_pda(cpu)->pcurrent;
467 u8 *ip;
468 unsigned int code_prologue = code_bytes * 43 / 64;
469 unsigned int code_len = code_bytes;
466 470
467 sp = regs->sp; 471 sp = regs->sp;
472 ip = (u8 *) regs->ip - code_prologue;
468 printk("CPU %d ", cpu); 473 printk("CPU %d ", cpu);
469 __show_regs(regs); 474 __show_regs(regs);
470 printk("Process %s (pid: %d, threadinfo %p, task %p)\n", 475 printk("Process %s (pid: %d, threadinfo %p, task %p)\n",
@@ -474,22 +479,28 @@ void show_registers(struct pt_regs *regs)
474 * When in-kernel, we also print out the stack and code at the 479 * When in-kernel, we also print out the stack and code at the
475 * time of the fault.. 480 * time of the fault..
476 */ 481 */
477 if (in_kernel) { 482 if (!user_mode(regs)) {
483 unsigned char c;
478 printk("Stack: "); 484 printk("Stack: ");
479 _show_stack(NULL, regs, (unsigned long *)sp, regs->bp); 485 _show_stack(NULL, regs, (unsigned long *)sp, regs->bp);
486 printk("\n");
480 487
481 printk("\nCode: "); 488 printk(KERN_EMERG "Code: ");
482 if (regs->ip < PAGE_OFFSET) 489 if (ip < (u8 *)PAGE_OFFSET || probe_kernel_address(ip, c)) {
483 goto bad; 490 /* try starting at RIP */
484 491 ip = (u8 *) regs->ip;
485 for (i=0; i<20; i++) { 492 code_len = code_len - code_prologue + 1;
486 unsigned char c; 493 }
487 if (__get_user(c, &((unsigned char*)regs->ip)[i])) { 494 for (i = 0; i < code_len; i++, ip++) {
488bad: 495 if (ip < (u8 *)PAGE_OFFSET ||
496 probe_kernel_address(ip, c)) {
489 printk(" Bad RIP value."); 497 printk(" Bad RIP value.");
490 break; 498 break;
491 } 499 }
492 printk("%02x ", c); 500 if (ip == (u8 *)regs->ip)
501 printk("<%02x> ", c);
502 else
503 printk("%02x ", c);
493 } 504 }
494 } 505 }
495 printk("\n"); 506 printk("\n");
@@ -1164,3 +1175,14 @@ static int __init kstack_setup(char *s)
1164 return 0; 1175 return 0;
1165} 1176}
1166early_param("kstack", kstack_setup); 1177early_param("kstack", kstack_setup);
1178
1179
1180static int __init code_bytes_setup(char *s)
1181{
1182 code_bytes = simple_strtoul(s, NULL, 0);
1183 if (code_bytes > 8192)
1184 code_bytes = 8192;
1185
1186 return 1;
1187}
1188__setup("code_bytes=", code_bytes_setup);