Skip to content

Commit

Permalink
CRIS: add STACKTRACE_SUPPORT
Browse files Browse the repository at this point in the history
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
vitkyrka authored and Jesper Nilsson committed Sep 4, 2015
1 parent 3fffa23 commit aa6f4d2
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 0 deletions.
3 changes: 3 additions & 0 deletions arch/cris/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 8 additions & 0 deletions arch/cris/include/asm/stacktrace.h
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
1 change: 1 addition & 0 deletions arch/cris/kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
76 changes: 76 additions & 0 deletions arch/cris/kernel/stacktrace.c
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 */

0 comments on commit aa6f4d2

Please sign in to comment.