Skip to content

Commit aa6f4d2

Browse files
vitkyrkaJesper Nilsson
authored andcommitted
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 <[email protected]> Signed-off-by: Jesper Nilsson <[email protected]>
1 parent 3fffa23 commit aa6f4d2

File tree

4 files changed

+88
-0
lines changed

4 files changed

+88
-0
lines changed

arch/cris/Kconfig

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ config TRACE_IRQFLAGS_SUPPORT
4040
depends on ETRAX_ARCH_V32
4141
def_bool y
4242

43+
config STACKTRACE_SUPPORT
44+
def_bool y
45+
4346
config CRIS
4447
bool
4548
default y

arch/cris/include/asm/stacktrace.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#ifndef __CRIS_STACKTRACE_H
2+
#define __CRIS_STACKTRACE_H
3+
4+
void walk_stackframe(unsigned long sp,
5+
int (*fn)(unsigned long addr, void *data),
6+
void *data);
7+
8+
#endif

arch/cris/kernel/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ extra-y := vmlinux.lds
88

99
obj-y := process.o traps.o irq.o ptrace.o setup.o time.o sys_cris.o
1010
obj-y += devicetree.o
11+
obj-y += stacktrace.o
1112

1213
obj-$(CONFIG_MODULES) += crisksyms.o
1314
obj-$(CONFIG_MODULES) += module.o

arch/cris/kernel/stacktrace.c

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
#include <linux/sched.h>
2+
#include <linux/stacktrace.h>
3+
#include <linux/stacktrace.h>
4+
#include <asm/stacktrace.h>
5+
6+
void walk_stackframe(unsigned long sp,
7+
int (*fn)(unsigned long addr, void *data),
8+
void *data)
9+
{
10+
unsigned long high = ALIGN(sp, THREAD_SIZE);
11+
12+
for (; sp <= high - 4; sp += 4) {
13+
unsigned long addr = *(unsigned long *) sp;
14+
15+
if (!kernel_text_address(addr))
16+
continue;
17+
18+
if (fn(addr, data))
19+
break;
20+
}
21+
}
22+
23+
struct stack_trace_data {
24+
struct stack_trace *trace;
25+
unsigned int no_sched_functions;
26+
unsigned int skip;
27+
};
28+
29+
#ifdef CONFIG_STACKTRACE
30+
31+
static int save_trace(unsigned long addr, void *d)
32+
{
33+
struct stack_trace_data *data = d;
34+
struct stack_trace *trace = data->trace;
35+
36+
if (data->no_sched_functions && in_sched_functions(addr))
37+
return 0;
38+
39+
if (data->skip) {
40+
data->skip--;
41+
return 0;
42+
}
43+
44+
trace->entries[trace->nr_entries++] = addr;
45+
46+
return trace->nr_entries >= trace->max_entries;
47+
}
48+
49+
void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
50+
{
51+
struct stack_trace_data data;
52+
unsigned long sp;
53+
54+
data.trace = trace;
55+
data.skip = trace->skip;
56+
57+
if (tsk != current) {
58+
data.no_sched_functions = 1;
59+
sp = tsk->thread.ksp;
60+
} else {
61+
data.no_sched_functions = 0;
62+
sp = rdsp();
63+
}
64+
65+
walk_stackframe(sp, save_trace, &data);
66+
if (trace->nr_entries < trace->max_entries)
67+
trace->entries[trace->nr_entries++] = ULONG_MAX;
68+
}
69+
70+
void save_stack_trace(struct stack_trace *trace)
71+
{
72+
save_stack_trace_tsk(current, trace);
73+
}
74+
EXPORT_SYMBOL_GPL(save_stack_trace);
75+
76+
#endif /* CONFIG_STACKTRACE */

0 commit comments

Comments
 (0)