diff options
author | Gerald Britton <gbritton@alum.mit.edu> | 2006-02-14 10:19:04 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-02-14 08:25:29 -0800 |
commit | 303794400992b907b7cac0d91788603636c7e0fe (patch) | |
tree | 012781f808f48d80b32e435a4f27b6e8524d0ff0 /arch | |
parent | b739db79a434aec89027a109d85de305e6bdeb93 (diff) |
[PATCH] x86: fix oprofile kernel callgraph regression
Fix x86 oprofile regression introduced by:
commit c34d1b4d165c67b966bca4aba026443d7ff161eb
[PATCH] mm: kill check_user_page_readable
That commit reorganized tests for the userspace stack walking moving all
those tests into dump_backtrace(), however, dump_backtrace() was used for
both userspace and kernel stalk walking. The result is typically no
recorded callgraph information for kernel samples.
Revive the original function as dump_kernel_backtrace() and rename the
other to dump_user_backtrace() to avoid future confusion.
Signed-off-by: Gerald Britton <gbritton@alum.mit.edu>
Apology-from: Hugh Dickins <hugh@veritas.com>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/i386/oprofile/backtrace.c | 19 |
1 files changed, 16 insertions, 3 deletions
diff --git a/arch/i386/oprofile/backtrace.c b/arch/i386/oprofile/backtrace.c index acc18138fb22..c049ce414f01 100644 --- a/arch/i386/oprofile/backtrace.c +++ b/arch/i386/oprofile/backtrace.c @@ -20,7 +20,20 @@ struct frame_head { } __attribute__((packed)); static struct frame_head * -dump_backtrace(struct frame_head * head) +dump_kernel_backtrace(struct frame_head * head) +{ + oprofile_add_trace(head->ret); + + /* frame pointers should strictly progress back up the stack + * (towards higher addresses) */ + if (head >= head->ebp) + return NULL; + + return head->ebp; +} + +static struct frame_head * +dump_user_backtrace(struct frame_head * head) { struct frame_head bufhead[2]; @@ -105,10 +118,10 @@ x86_backtrace(struct pt_regs * const regs, unsigned int depth) if (!user_mode_vm(regs)) { while (depth-- && valid_kernel_stack(head, regs)) - head = dump_backtrace(head); + head = dump_kernel_backtrace(head); return; } while (depth-- && head) - head = dump_backtrace(head); + head = dump_user_backtrace(head); } |