Skip to content

Commit

Permalink
Merge branch 'perf-fixes-for-linus' of git://git.kernel.org/pub/scm/l…
Browse files Browse the repository at this point in the history
…inux/kernel/git/tip/linux-2.6-tip

* 'perf-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
  perf session: Make events_stats u64 to avoid overflow on 32-bit arches
  hw-breakpoints: Fix hardware breakpoints -> perf events dependency
  perf events: Dont report side-band events on each cpu for per-task-per-cpu events
  perf events, x86/stacktrace: Fix performance/softlockup by providing a special frame pointer-only stack walker
  perf events, x86/stacktrace: Make stack walking optional
  perf events: Remove unused perf_counter.h header file
  perf probe: Check new event name
  kprobe-tracer: Check new event/group name
  perf probe: Check whether debugfs path is correct
  perf probe: Fix libdwarf include path for Debian
  • Loading branch information
Linus Torvalds committed Dec 19, 2009
2 parents 3981e15 + b5b60fd commit eca9dfc
Show file tree
Hide file tree
Showing 20 changed files with 175 additions and 523 deletions.
4 changes: 1 addition & 3 deletions arch/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -135,9 +135,7 @@ config HAVE_DEFAULT_NO_SPIN_MUTEXES

config HAVE_HW_BREAKPOINT
bool
depends on HAVE_PERF_EVENTS
select ANON_INODES
select PERF_EVENTS
depends on PERF_EVENTS

config HAVE_USER_RETURN_NOTIFIER
bool
Expand Down
2 changes: 2 additions & 0 deletions arch/x86/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ config X86
select HAVE_KERNEL_BZIP2
select HAVE_KERNEL_LZMA
select HAVE_HW_BREAKPOINT
select PERF_EVENTS
select ANON_INODES
select HAVE_ARCH_KMEMCHECK
select HAVE_USER_RETURN_NOTIFIER

Expand Down
24 changes: 24 additions & 0 deletions arch/x86/include/asm/stacktrace.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,29 @@ extern int kstack_depth_to_print;

int x86_is_stack_id(int id, char *name);

struct thread_info;
struct stacktrace_ops;

typedef unsigned long (*walk_stack_t)(struct thread_info *tinfo,
unsigned long *stack,
unsigned long bp,
const struct stacktrace_ops *ops,
void *data,
unsigned long *end,
int *graph);

extern unsigned long
print_context_stack(struct thread_info *tinfo,
unsigned long *stack, unsigned long bp,
const struct stacktrace_ops *ops, void *data,
unsigned long *end, int *graph);

extern unsigned long
print_context_stack_bp(struct thread_info *tinfo,
unsigned long *stack, unsigned long bp,
const struct stacktrace_ops *ops, void *data,
unsigned long *end, int *graph);

/* Generic stack tracer with callbacks */

struct stacktrace_ops {
Expand All @@ -14,6 +37,7 @@ struct stacktrace_ops {
void (*address)(void *data, unsigned long address, int reliable);
/* On negative return stop dumping */
int (*stack)(void *data, char *name);
walk_stack_t walk_stack;
};

void dump_trace(struct task_struct *tsk, struct pt_regs *regs,
Expand Down
1 change: 1 addition & 0 deletions arch/x86/kernel/cpu/perf_event.c
Original file line number Diff line number Diff line change
Expand Up @@ -2336,6 +2336,7 @@ static const struct stacktrace_ops backtrace_ops = {
.warning_symbol = backtrace_warning_symbol,
.stack = backtrace_stack,
.address = backtrace_address,
.walk_stack = print_context_stack_bp,
};

#include "../dumpstack.h"
Expand Down
33 changes: 29 additions & 4 deletions arch/x86/kernel/dumpstack.c
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,30 @@ print_context_stack(struct thread_info *tinfo,
}
return bp;
}
EXPORT_SYMBOL_GPL(print_context_stack);

unsigned long
print_context_stack_bp(struct thread_info *tinfo,
unsigned long *stack, unsigned long bp,
const struct stacktrace_ops *ops, void *data,
unsigned long *end, int *graph)
{
struct stack_frame *frame = (struct stack_frame *)bp;
unsigned long *ret_addr = &frame->return_address;

while (valid_stack_ptr(tinfo, ret_addr, sizeof(*ret_addr), end)) {
unsigned long addr = *ret_addr;

if (__kernel_text_address(addr)) {
ops->address(data, addr, 1);
frame = frame->next_frame;
ret_addr = &frame->return_address;
print_ftrace_graph_addr(addr, data, ops, tinfo, graph);
}
}
return (unsigned long)frame;
}
EXPORT_SYMBOL_GPL(print_context_stack_bp);


static void
Expand Down Expand Up @@ -141,10 +165,11 @@ static void print_trace_address(void *data, unsigned long addr, int reliable)
}

static const struct stacktrace_ops print_trace_ops = {
.warning = print_trace_warning,
.warning_symbol = print_trace_warning_symbol,
.stack = print_trace_stack,
.address = print_trace_address,
.warning = print_trace_warning,
.warning_symbol = print_trace_warning_symbol,
.stack = print_trace_stack,
.address = print_trace_address,
.walk_stack = print_context_stack,
};

void
Expand Down
6 changes: 0 additions & 6 deletions arch/x86/kernel/dumpstack.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,6 @@
#define get_bp(bp) asm("movq %%rbp, %0" : "=r" (bp) :)
#endif

extern unsigned long
print_context_stack(struct thread_info *tinfo,
unsigned long *stack, unsigned long bp,
const struct stacktrace_ops *ops, void *data,
unsigned long *end, int *graph);

extern void
show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
unsigned long *stack, unsigned long bp, char *log_lvl);
Expand Down
2 changes: 1 addition & 1 deletion arch/x86/kernel/dumpstack_32.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,

context = (struct thread_info *)
((unsigned long)stack & (~(THREAD_SIZE - 1)));
bp = print_context_stack(context, stack, bp, ops, data, NULL, &graph);
bp = ops->walk_stack(context, stack, bp, ops, data, NULL, &graph);

stack = (unsigned long *)context->previous_esp;
if (!stack)
Expand Down
4 changes: 2 additions & 2 deletions arch/x86/kernel/dumpstack_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -188,8 +188,8 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,
if (ops->stack(data, id) < 0)
break;

bp = print_context_stack(tinfo, stack, bp, ops,
data, estack_end, &graph);
bp = ops->walk_stack(tinfo, stack, bp, ops,
data, estack_end, &graph);
ops->stack(data, "<EOE>");
/*
* We link to the next stack via the
Expand Down
18 changes: 10 additions & 8 deletions arch/x86/kernel/stacktrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -53,17 +53,19 @@ save_stack_address_nosched(void *data, unsigned long addr, int reliable)
}

static const struct stacktrace_ops save_stack_ops = {
.warning = save_stack_warning,
.warning_symbol = save_stack_warning_symbol,
.stack = save_stack_stack,
.address = save_stack_address,
.warning = save_stack_warning,
.warning_symbol = save_stack_warning_symbol,
.stack = save_stack_stack,
.address = save_stack_address,
.walk_stack = print_context_stack,
};

static const struct stacktrace_ops save_stack_ops_nosched = {
.warning = save_stack_warning,
.warning_symbol = save_stack_warning_symbol,
.stack = save_stack_stack,
.address = save_stack_address_nosched,
.warning = save_stack_warning,
.warning_symbol = save_stack_warning_symbol,
.stack = save_stack_stack,
.address = save_stack_address_nosched,
.walk_stack = print_context_stack,
};

/*
Expand Down
9 changes: 5 additions & 4 deletions arch/x86/oprofile/backtrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,11 @@ static void backtrace_address(void *data, unsigned long addr, int reliable)
}

static struct stacktrace_ops backtrace_ops = {
.warning = backtrace_warning,
.warning_symbol = backtrace_warning_symbol,
.stack = backtrace_stack,
.address = backtrace_address,
.warning = backtrace_warning,
.warning_symbol = backtrace_warning_symbol,
.stack = backtrace_stack,
.address = backtrace_address,
.walk_stack = print_context_stack,
};

struct frame_head {
Expand Down
Loading

0 comments on commit eca9dfc

Please sign in to comment.