Skip to content

Commit

Permalink
Merge branch 'perf/core' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/git/frederic/random-tracing into perf/core
  • Loading branch information
Ingo Molnar committed Nov 18, 2010
2 parents 072b198 + 423478c commit ae51ce9
Show file tree
Hide file tree
Showing 18 changed files with 121 additions and 71 deletions.
2 changes: 1 addition & 1 deletion arch/x86/include/asm/kdebug.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ extern void die(const char *, struct pt_regs *,long);
extern int __must_check __die(const char *, struct pt_regs *, long);
extern void show_registers(struct pt_regs *regs);
extern void show_trace(struct task_struct *t, struct pt_regs *regs,
unsigned long *sp, unsigned long bp);
unsigned long *sp);
extern void __show_regs(struct pt_regs *regs, int all);
extern void show_regs(struct pt_regs *regs);
extern unsigned long oops_begin(void);
Expand Down
33 changes: 30 additions & 3 deletions arch/x86/include/asm/stacktrace.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#define _ASM_X86_STACKTRACE_H

#include <linux/uaccess.h>
#include <linux/ptrace.h>

extern int kstack_depth_to_print;

Expand Down Expand Up @@ -46,7 +47,7 @@ struct stacktrace_ops {
};

void dump_trace(struct task_struct *tsk, struct pt_regs *regs,
unsigned long *stack, unsigned long bp,
unsigned long *stack,
const struct stacktrace_ops *ops, void *data);

#ifdef CONFIG_X86_32
Expand All @@ -57,13 +58,39 @@ void dump_trace(struct task_struct *tsk, struct pt_regs *regs,
#define get_bp(bp) asm("movq %%rbp, %0" : "=r" (bp) :)
#endif

#ifdef CONFIG_FRAME_POINTER
static inline unsigned long
stack_frame(struct task_struct *task, struct pt_regs *regs)
{
unsigned long bp;

if (regs)
return regs->bp;

if (task == current) {
/* Grab bp right from our regs */
get_bp(bp);
return bp;
}

/* bp is the last reg pushed by switch_to */
return *(unsigned long *)task->thread.sp;
}
#else
static inline unsigned long
stack_frame(struct task_struct *task, struct pt_regs *regs)
{
return 0;
}
#endif

extern void
show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
unsigned long *stack, unsigned long bp, char *log_lvl);
unsigned long *stack, char *log_lvl);

extern void
show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
unsigned long *sp, unsigned long bp, char *log_lvl);
unsigned long *sp, char *log_lvl);

extern unsigned int code_bytes;

Expand Down
2 changes: 1 addition & 1 deletion arch/x86/kernel/cpu/perf_event.c
Original file line number Diff line number Diff line change
Expand Up @@ -1657,7 +1657,7 @@ perf_callchain_kernel(struct perf_callchain_entry *entry, struct pt_regs *regs)

perf_callchain_store(entry, regs->ip);

dump_trace(NULL, regs, NULL, regs->bp, &backtrace_ops, entry);
dump_trace(NULL, regs, NULL, &backtrace_ops, entry);
}

#ifdef CONFIG_COMPAT
Expand Down
12 changes: 6 additions & 6 deletions arch/x86/kernel/dumpstack.c
Original file line number Diff line number Diff line change
Expand Up @@ -175,21 +175,21 @@ static const struct stacktrace_ops print_trace_ops = {

void
show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
unsigned long *stack, unsigned long bp, char *log_lvl)
unsigned long *stack, char *log_lvl)
{
printk("%sCall Trace:\n", log_lvl);
dump_trace(task, regs, stack, bp, &print_trace_ops, log_lvl);
dump_trace(task, regs, stack, &print_trace_ops, log_lvl);
}

void show_trace(struct task_struct *task, struct pt_regs *regs,
unsigned long *stack, unsigned long bp)
unsigned long *stack)
{
show_trace_log_lvl(task, regs, stack, bp, "");
show_trace_log_lvl(task, regs, stack, "");
}

void show_stack(struct task_struct *task, unsigned long *sp)
{
show_stack_log_lvl(task, NULL, sp, 0, "");
show_stack_log_lvl(task, NULL, sp, "");
}

/*
Expand All @@ -210,7 +210,7 @@ void dump_stack(void)
init_utsname()->release,
(int)strcspn(init_utsname()->version, " "),
init_utsname()->version);
show_trace(NULL, NULL, &stack, bp);
show_trace(NULL, NULL, &stack);
}
EXPORT_SYMBOL(dump_stack);

Expand Down
25 changes: 7 additions & 18 deletions arch/x86/kernel/dumpstack_32.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,12 @@
#include <asm/stacktrace.h>


void dump_trace(struct task_struct *task, struct pt_regs *regs,
unsigned long *stack, unsigned long bp,
void dump_trace(struct task_struct *task,
struct pt_regs *regs, unsigned long *stack,
const struct stacktrace_ops *ops, void *data)
{
int graph = 0;
unsigned long bp;

if (!task)
task = current;
Expand All @@ -34,18 +35,7 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,
stack = (unsigned long *)task->thread.sp;
}

#ifdef CONFIG_FRAME_POINTER
if (!bp) {
if (task == current) {
/* Grab bp right from our regs */
get_bp(bp);
} else {
/* bp is the last reg pushed by switch_to */
bp = *(unsigned long *) task->thread.sp;
}
}
#endif

bp = stack_frame(task, regs);
for (;;) {
struct thread_info *context;

Expand All @@ -65,7 +55,7 @@ EXPORT_SYMBOL(dump_trace);

void
show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
unsigned long *sp, unsigned long bp, char *log_lvl)
unsigned long *sp, char *log_lvl)
{
unsigned long *stack;
int i;
Expand All @@ -87,7 +77,7 @@ show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
touch_nmi_watchdog();
}
printk(KERN_CONT "\n");
show_trace_log_lvl(task, regs, sp, bp, log_lvl);
show_trace_log_lvl(task, regs, sp, log_lvl);
}


Expand All @@ -112,8 +102,7 @@ void show_registers(struct pt_regs *regs)
u8 *ip;

printk(KERN_EMERG "Stack:\n");
show_stack_log_lvl(NULL, regs, &regs->sp,
0, KERN_EMERG);
show_stack_log_lvl(NULL, regs, &regs->sp, KERN_EMERG);

printk(KERN_EMERG "Code: ");

Expand Down
24 changes: 7 additions & 17 deletions arch/x86/kernel/dumpstack_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,8 @@ fixup_bp_irq_link(unsigned long bp, unsigned long *stack,
* severe exception (double fault, nmi, stack fault, debug, mce) hardware stack
*/

void dump_trace(struct task_struct *task, struct pt_regs *regs,
unsigned long *stack, unsigned long bp,
void dump_trace(struct task_struct *task,
struct pt_regs *regs, unsigned long *stack,
const struct stacktrace_ops *ops, void *data)
{
const unsigned cpu = get_cpu();
Expand All @@ -149,6 +149,7 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,
unsigned used = 0;
struct thread_info *tinfo;
int graph = 0;
unsigned long bp;

if (!task)
task = current;
Expand All @@ -160,18 +161,7 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs,
stack = (unsigned long *)task->thread.sp;
}

#ifdef CONFIG_FRAME_POINTER
if (!bp) {
if (task == current) {
/* Grab bp right from our regs */
get_bp(bp);
} else {
/* bp is the last reg pushed by switch_to */
bp = *(unsigned long *) task->thread.sp;
}
}
#endif

bp = stack_frame(task, regs);
/*
* Print function call entries in all stacks, starting at the
* current stack address. If the stacks consist of nested
Expand Down Expand Up @@ -235,7 +225,7 @@ EXPORT_SYMBOL(dump_trace);

void
show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
unsigned long *sp, unsigned long bp, char *log_lvl)
unsigned long *sp, char *log_lvl)
{
unsigned long *irq_stack_end;
unsigned long *irq_stack;
Expand Down Expand Up @@ -279,7 +269,7 @@ show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
preempt_enable();

printk(KERN_CONT "\n");
show_trace_log_lvl(task, regs, sp, bp, log_lvl);
show_trace_log_lvl(task, regs, sp, log_lvl);
}

void show_registers(struct pt_regs *regs)
Expand Down Expand Up @@ -308,7 +298,7 @@ void show_registers(struct pt_regs *regs)

printk(KERN_EMERG "Stack:\n");
show_stack_log_lvl(NULL, regs, (unsigned long *)sp,
regs->bp, KERN_EMERG);
KERN_EMERG);

printk(KERN_EMERG "Code: ");

Expand Down
3 changes: 1 addition & 2 deletions arch/x86/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,7 @@ void exit_thread(void)
void show_regs(struct pt_regs *regs)
{
show_registers(regs);
show_trace(NULL, regs, (unsigned long *)kernel_stack_pointer(regs),
regs->bp);
show_trace(NULL, regs, (unsigned long *)kernel_stack_pointer(regs));
}

void show_regs_common(void)
Expand Down
8 changes: 4 additions & 4 deletions arch/x86/kernel/stacktrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,22 +73,22 @@ static const struct stacktrace_ops save_stack_ops_nosched = {
*/
void save_stack_trace(struct stack_trace *trace)
{
dump_trace(current, NULL, NULL, 0, &save_stack_ops, trace);
dump_trace(current, NULL, NULL, &save_stack_ops, trace);
if (trace->nr_entries < trace->max_entries)
trace->entries[trace->nr_entries++] = ULONG_MAX;
}
EXPORT_SYMBOL_GPL(save_stack_trace);

void save_stack_trace_bp(struct stack_trace *trace, unsigned long bp)
void save_stack_trace_regs(struct stack_trace *trace, struct pt_regs *regs)
{
dump_trace(current, NULL, NULL, bp, &save_stack_ops, trace);
dump_trace(current, regs, NULL, &save_stack_ops, trace);
if (trace->nr_entries < trace->max_entries)
trace->entries[trace->nr_entries++] = ULONG_MAX;
}

void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
{
dump_trace(tsk, NULL, NULL, 0, &save_stack_ops_nosched, trace);
dump_trace(tsk, NULL, NULL, &save_stack_ops_nosched, trace);
if (trace->nr_entries < trace->max_entries)
trace->entries[trace->nr_entries++] = ULONG_MAX;
}
Expand Down
2 changes: 1 addition & 1 deletion arch/x86/mm/kmemcheck/error.c
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ void kmemcheck_error_save(enum kmemcheck_shadow state,
e->trace.entries = e->trace_entries;
e->trace.max_entries = ARRAY_SIZE(e->trace_entries);
e->trace.skip = 0;
save_stack_trace_bp(&e->trace, regs->bp);
save_stack_trace_regs(&e->trace, regs);

/* Round address down to nearest 16 bytes */
shadow_copy = kmemcheck_shadow_lookup(address
Expand Down
2 changes: 1 addition & 1 deletion arch/x86/oprofile/backtrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ x86_backtrace(struct pt_regs * const regs, unsigned int depth)
if (!user_mode_vm(regs)) {
unsigned long stack = kernel_stack_pointer(regs);
if (depth)
dump_trace(NULL, regs, (unsigned long *)stack, 0,
dump_trace(NULL, regs, (unsigned long *)stack,
&backtrace_ops, &depth);
return;
}
Expand Down
10 changes: 10 additions & 0 deletions include/linux/ftrace_event.h
Original file line number Diff line number Diff line change
Expand Up @@ -154,12 +154,14 @@ enum {
TRACE_EVENT_FL_ENABLED_BIT,
TRACE_EVENT_FL_FILTERED_BIT,
TRACE_EVENT_FL_RECORDED_CMD_BIT,
TRACE_EVENT_FL_CAP_ANY_BIT,
};

enum {
TRACE_EVENT_FL_ENABLED = (1 << TRACE_EVENT_FL_ENABLED_BIT),
TRACE_EVENT_FL_FILTERED = (1 << TRACE_EVENT_FL_FILTERED_BIT),
TRACE_EVENT_FL_RECORDED_CMD = (1 << TRACE_EVENT_FL_RECORDED_CMD_BIT),
TRACE_EVENT_FL_CAP_ANY = (1 << TRACE_EVENT_FL_CAP_ANY_BIT),
};

struct ftrace_event_call {
Expand Down Expand Up @@ -196,6 +198,14 @@ struct ftrace_event_call {
#endif
};

#define __TRACE_EVENT_FLAGS(name, value) \
static int __init trace_init_flags_##name(void) \
{ \
event_##name.flags = value; \
return 0; \
} \
early_initcall(trace_init_flags_##name);

#define PERF_MAX_TRACE_SIZE 2048

#define MAX_FILTER_PRED 32
Expand Down
4 changes: 3 additions & 1 deletion include/linux/stacktrace.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#define __LINUX_STACKTRACE_H

struct task_struct;
struct pt_regs;

#ifdef CONFIG_STACKTRACE
struct task_struct;
Expand All @@ -13,7 +14,8 @@ struct stack_trace {
};

extern void save_stack_trace(struct stack_trace *trace);
extern void save_stack_trace_bp(struct stack_trace *trace, unsigned long bp);
extern void save_stack_trace_regs(struct stack_trace *trace,
struct pt_regs *regs);
extern void save_stack_trace_tsk(struct task_struct *tsk,
struct stack_trace *trace);

Expand Down
10 changes: 4 additions & 6 deletions include/linux/syscalls.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,6 @@ extern struct trace_event_functions exit_syscall_print_funcs;
#define SYSCALL_TRACE_ENTER_EVENT(sname) \
static struct syscall_metadata \
__attribute__((__aligned__(4))) __syscall_meta_##sname; \
static struct ftrace_event_call \
__attribute__((__aligned__(4))) event_enter_##sname; \
static struct ftrace_event_call __used \
__attribute__((__aligned__(4))) \
__attribute__((section("_ftrace_events"))) \
Expand All @@ -137,13 +135,12 @@ extern struct trace_event_functions exit_syscall_print_funcs;
.class = &event_class_syscall_enter, \
.event.funcs = &enter_syscall_print_funcs, \
.data = (void *)&__syscall_meta_##sname,\
}
}; \
__TRACE_EVENT_FLAGS(enter_##sname, TRACE_EVENT_FL_CAP_ANY)

#define SYSCALL_TRACE_EXIT_EVENT(sname) \
static struct syscall_metadata \
__attribute__((__aligned__(4))) __syscall_meta_##sname; \
static struct ftrace_event_call \
__attribute__((__aligned__(4))) event_exit_##sname; \
static struct ftrace_event_call __used \
__attribute__((__aligned__(4))) \
__attribute__((section("_ftrace_events"))) \
Expand All @@ -152,7 +149,8 @@ extern struct trace_event_functions exit_syscall_print_funcs;
.class = &event_class_syscall_exit, \
.event.funcs = &exit_syscall_print_funcs, \
.data = (void *)&__syscall_meta_##sname,\
}
}; \
__TRACE_EVENT_FLAGS(exit_##sname, TRACE_EVENT_FL_CAP_ANY)

#define SYSCALL_METADATA(sname, nb) \
SYSCALL_TRACE_ENTER_EVENT(sname); \
Expand Down
4 changes: 4 additions & 0 deletions include/linux/tracepoint.h
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,8 @@ do_trace: \
PARAMS(void *__data, proto), \
PARAMS(__data, args))

#define TRACE_EVENT_FLAGS(event, flag)

#endif /* DECLARE_TRACE */

#ifndef TRACE_EVENT
Expand Down Expand Up @@ -354,4 +356,6 @@ do_trace: \
assign, print, reg, unreg) \
DECLARE_TRACE(name, PARAMS(proto), PARAMS(args))

#define TRACE_EVENT_FLAGS(event, flag)

#endif /* ifdef TRACE_EVENT (see note above) */
Loading

0 comments on commit ae51ce9

Please sign in to comment.