forked from torvalds/linux
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add stacktrace support, which is required for lockdep and tracing. The stack tracing simply looks at all kernel text symbols found on the stack, similar to the trap stack dumping code, which can also be converted to use this. Signed-off-by: Rabin Vincent <[email protected]> Signed-off-by: Jesper Nilsson <[email protected]>
- Loading branch information
Showing
4 changed files
with
88 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
#ifndef __CRIS_STACKTRACE_H | ||
#define __CRIS_STACKTRACE_H | ||
|
||
void walk_stackframe(unsigned long sp, | ||
int (*fn)(unsigned long addr, void *data), | ||
void *data); | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
#include <linux/sched.h> | ||
#include <linux/stacktrace.h> | ||
#include <linux/stacktrace.h> | ||
#include <asm/stacktrace.h> | ||
|
||
void walk_stackframe(unsigned long sp, | ||
int (*fn)(unsigned long addr, void *data), | ||
void *data) | ||
{ | ||
unsigned long high = ALIGN(sp, THREAD_SIZE); | ||
|
||
for (; sp <= high - 4; sp += 4) { | ||
unsigned long addr = *(unsigned long *) sp; | ||
|
||
if (!kernel_text_address(addr)) | ||
continue; | ||
|
||
if (fn(addr, data)) | ||
break; | ||
} | ||
} | ||
|
||
struct stack_trace_data { | ||
struct stack_trace *trace; | ||
unsigned int no_sched_functions; | ||
unsigned int skip; | ||
}; | ||
|
||
#ifdef CONFIG_STACKTRACE | ||
|
||
static int save_trace(unsigned long addr, void *d) | ||
{ | ||
struct stack_trace_data *data = d; | ||
struct stack_trace *trace = data->trace; | ||
|
||
if (data->no_sched_functions && in_sched_functions(addr)) | ||
return 0; | ||
|
||
if (data->skip) { | ||
data->skip--; | ||
return 0; | ||
} | ||
|
||
trace->entries[trace->nr_entries++] = addr; | ||
|
||
return trace->nr_entries >= trace->max_entries; | ||
} | ||
|
||
void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) | ||
{ | ||
struct stack_trace_data data; | ||
unsigned long sp; | ||
|
||
data.trace = trace; | ||
data.skip = trace->skip; | ||
|
||
if (tsk != current) { | ||
data.no_sched_functions = 1; | ||
sp = tsk->thread.ksp; | ||
} else { | ||
data.no_sched_functions = 0; | ||
sp = rdsp(); | ||
} | ||
|
||
walk_stackframe(sp, save_trace, &data); | ||
if (trace->nr_entries < trace->max_entries) | ||
trace->entries[trace->nr_entries++] = ULONG_MAX; | ||
} | ||
|
||
void save_stack_trace(struct stack_trace *trace) | ||
{ | ||
save_stack_trace_tsk(current, trace); | ||
} | ||
EXPORT_SYMBOL_GPL(save_stack_trace); | ||
|
||
#endif /* CONFIG_STACKTRACE */ |