Commit a25bd94964e87b1b93903a822fba5025d995d4da

Authored by Arjan van de Ven
Committed by Ingo Molnar
1 parent 6dab27784b

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>

Showing 2 changed files with 35 additions and 13 deletions Side-by-side Diff

Documentation/kernel-parameters.txt
... ... @@ -416,8 +416,8 @@
416 416 [SPARC64] tick
417 417 [X86-64] hpet,tsc
418 418  
419   - code_bytes [IA32] How many bytes of object code to print in an
420   - oops report.
  419 + code_bytes [IA32/X86_64] How many bytes of object code to print
  420 + in an oops report.
421 421 Range: 0 - 8192
422 422 Default: 64
423 423  
arch/x86/kernel/traps_64.c
... ... @@ -74,6 +74,8 @@
74 74 asmlinkage void machine_check(void);
75 75 asmlinkage void spurious_interrupt_bug(void);
76 76  
  77 +static unsigned int code_bytes = 64;
  78 +
77 79 static inline void conditional_sti(struct pt_regs *regs)
78 80 {
79 81 if (regs->flags & X86_EFLAGS_IF)
80 82  
81 83  
... ... @@ -459,12 +461,15 @@
459 461 void show_registers(struct pt_regs *regs)
460 462 {
461 463 int i;
462   - int in_kernel = !user_mode(regs);
463 464 unsigned long sp;
464 465 const int cpu = smp_processor_id();
465 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 471 sp = regs->sp;
  472 + ip = (u8 *) regs->ip - code_prologue;
468 473 printk("CPU %d ", cpu);
469 474 __show_regs(regs);
470 475 printk("Process %s (pid: %d, threadinfo %p, task %p)\n",
471 476  
472 477  
473 478  
... ... @@ -474,22 +479,28 @@
474 479 * When in-kernel, we also print out the stack and code at the
475 480 * time of the fault..
476 481 */
477   - if (in_kernel) {
  482 + if (!user_mode(regs)) {
  483 + unsigned char c;
478 484 printk("Stack: ");
479 485 _show_stack(NULL, regs, (unsigned long *)sp, regs->bp);
  486 + printk("\n");
480 487  
481   - printk("\nCode: ");
482   - if (regs->ip < PAGE_OFFSET)
483   - goto bad;
484   -
485   - for (i=0; i<20; i++) {
486   - unsigned char c;
487   - if (__get_user(c, &((unsigned char*)regs->ip)[i])) {
488   -bad:
  488 + printk(KERN_EMERG "Code: ");
  489 + if (ip < (u8 *)PAGE_OFFSET || probe_kernel_address(ip, c)) {
  490 + /* try starting at RIP */
  491 + ip = (u8 *) regs->ip;
  492 + code_len = code_len - code_prologue + 1;
  493 + }
  494 + for (i = 0; i < code_len; i++, ip++) {
  495 + if (ip < (u8 *)PAGE_OFFSET ||
  496 + probe_kernel_address(ip, c)) {
489 497 printk(" Bad RIP value.");
490 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 506 printk("\n");
... ... @@ -1164,4 +1175,15 @@
1164 1175 return 0;
1165 1176 }
1166 1177 early_param("kstack", kstack_setup);
  1178 +
  1179 +
  1180 +static 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);