CRIS: add STACKTRACE_SUPPORT
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 <rabin@rab.in> Signed-off-by: Jesper Nilsson <jesper.nilsson@axis.com>
This commit is contained in:
parent
3fffa23ee0
commit
aa6f4d2b65
|
@ -40,6 +40,9 @@ config TRACE_IRQFLAGS_SUPPORT
|
|||
depends on ETRAX_ARCH_V32
|
||||
def_bool y
|
||||
|
||||
config STACKTRACE_SUPPORT
|
||||
def_bool y
|
||||
|
||||
config CRIS
|
||||
bool
|
||||
default y
|
||||
|
|
|
@ -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
|
|
@ -8,6 +8,7 @@ extra-y := vmlinux.lds
|
|||
|
||||
obj-y := process.o traps.o irq.o ptrace.o setup.o time.o sys_cris.o
|
||||
obj-y += devicetree.o
|
||||
obj-y += stacktrace.o
|
||||
|
||||
obj-$(CONFIG_MODULES) += crisksyms.o
|
||||
obj-$(CONFIG_MODULES) += module.o
|
||||
|
|
|
@ -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 */
|
Loading…
Reference in New Issue