linux/arch/x86
Frederic Weisbecker b625b3b3b7 x86: Fixup wrong debug exception frame link in stacktraces
While dumping a stacktrace, the end of the exception stack won't link
the frame pointer to the previous stack.

The interrupted stack will then be considered as unreliable and ignored
by perf, as the frame pointer is unreliable itself.

This happens because we overwrite the frame pointer that links to the
interrupted frame with the address of the exception stack. This is
done in order to reserve space inside.
But rbp has been chosen here only because it is not a scratch register,
so that the address of the exception stack remains in rbp after calling
do_debug(), we can then release the exception stack space without the
need to retrieve its address again.

But we can pick another non-scratch register to do that, so that we
preserve the link to the interrupted stack frame in the stacktraces.

Just randomly choose r12. Every registers are saved just before and
restored just after calling do_debug(). And r12 is not used in the
middle, which makes it a perfect candidate.

Example: perf record -g -a -c 1 -f -e mem:$(tasklist_lock_addr):rw

Before:
    44.18%  [k] _raw_read_lock
            |
            |
            ---  |--6.31%-- waitid
                 |
                 |--4.26%-- writev
                 |
                 |--3.63%-- __select
                 |
                 |--3.15%-- __waitpid
                 |          |
                 |          |--28.57%-- 0x8b52e00000139f
                 |          |
                 |          |--28.57%-- 0x8b52e0000013c6
                 |          |
                 |          |--14.29%-- 0x7fde786dc000
                 |          |
                 |          |--14.29%-- 0x62696c2f7273752f
                 |          |
                 |           --14.29%-- 0x1ea9df800000000
                 |
                 |--3.00%-- __poll

After:

    43.94%  [k] _raw_read_lock
            |
            --- _read_lock
               |
               |--60.53%-- send_sigio
               |          __kill_fasync
               |          kill_fasync
               |          evdev_pass_event
               |          evdev_event
               |          input_pass_event
               |          input_handle_event
               |          input_event
               |          synaptics_process_byte
               |          psmouse_handle_byte
               |          psmouse_interrupt
               |          serio_interrupt
               |          i8042_interrupt
               |          handle_IRQ_event
               |          handle_edge_irq
               |          handle_irq
               |          __irqentry_text_start
               |          ret_from_intr
               |          |
               |          |--30.43%-- __select
               |          |
               |          |--17.39%-- 0x454f15
               |          |
               |          |--13.04%-- __read
               |          |
               |          |--13.04%-- vread_hpet
               |          |
               |          |--13.04%-- _xcb_lock_io
               |          |
               |           --13.04%-- 0x7f630878ce87

Note: it does not only affect perf events but also other stacktraces in
x86-64. They were considered as unreliable once we quit the debug
stack frame.

Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: "K. Prasad" <prasad@linux.vnet.ibm.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: "H. Peter Anvin" <hpa@zytor.com>
2009-12-06 08:27:22 +01:00
..
boot x86: Document linker script ASSERT() quirk 2009-10-16 07:18:46 +02:00
configs tracing: Rename FTRACE_SYSCALLS for tracepoints 2009-08-26 00:17:35 +02:00
crypto crypto: aesni-intel - Fix irq_fpu_usable usage 2009-10-20 16:20:47 +09:00
ia32 x86-64: Fix register leak in 32-bit syscall audting 2009-10-26 16:23:26 +01:00
include/asm Merge branch 'perf/mce' into perf/core 2009-12-03 20:11:06 +01:00
kernel x86: Fixup wrong debug exception frame link in stacktraces 2009-12-06 08:27:22 +01:00
kvm Merge branch 'tracing/hw-breakpoints' into perf/core 2009-11-21 14:07:23 +01:00
lguest lguest: move panic notifier registration to its expected place. 2009-09-23 22:26:44 +09:30
lib x86: Gitignore: arch/x86/lib/inat-tables.c 2009-11-04 13:11:28 +01:00
math-emu
mm Merge branch 'tracing/hw-breakpoints' into perf/core 2009-11-21 14:07:23 +01:00
oprofile perf: Do the big rename: Performance Counters -> Performance Events 2009-09-21 14:28:04 +02:00
pci const: mark struct vm_struct_operations 2009-09-27 11:39:25 -07:00
power hw-breakpoints: Rewrite the hw-breakpoints layer on top of perf events 2009-11-08 15:34:42 +01:00
tools Merge branch 'perf/probes' into perf/core 2009-12-03 20:11:38 +01:00
vdso kbuild: rename ld-option to cc-ldoption 2009-09-20 12:27:42 +02:00
video
xen xen: mask extended topology info in cpuid 2009-11-03 11:09:12 -08:00
Kbuild
Kconfig Merge branch 'tracing/hw-breakpoints' into perf/core 2009-11-21 14:07:23 +01:00
Kconfig.cpu x86: Side-step lguest problem by only building cmpxchg8b_emu for pre-Pentium 2009-10-26 12:33:02 +01:00
Kconfig.debug x86: X86 instruction decoder build-time selftest 2009-08-27 00:35:56 +02:00
Makefile Merge branch 'perf/core' into perf/probes 2009-11-17 10:17:47 +01:00
Makefile_32.cpu x86: add specific support for Intel Atom architecture 2009-08-23 11:20:02 +02:00