2 * arch/xtensa/kernel/stacktrace.c
4 * This file is subject to the terms and conditions of the GNU General Public
5 * License. See the file "COPYING" in the main directory of this archive
8 * Copyright (C) 2001 - 2013 Tensilica Inc.
10 #include <linux/export.h>
11 #include <linux/sched.h>
12 #include <linux/stacktrace.h>
14 #include <asm/stacktrace.h>
15 #include <asm/traps.h>
17 void walk_stackframe(unsigned long *sp
,
18 int (*fn
)(struct stackframe
*frame
, void *data
),
24 a1
= (unsigned long)sp
;
25 sp_end
= ALIGN(a1
, THREAD_SIZE
);
30 struct stackframe frame
;
32 sp
= (unsigned long *)a1
;
37 if (a1
<= (unsigned long)sp
)
40 frame
.pc
= MAKE_PC_FROM_RA(a0
, a1
);
48 #ifdef CONFIG_STACKTRACE
50 struct stack_trace_data
{
51 struct stack_trace
*trace
;
55 static int stack_trace_cb(struct stackframe
*frame
, void *data
)
57 struct stack_trace_data
*trace_data
= data
;
58 struct stack_trace
*trace
= trace_data
->trace
;
60 if (trace_data
->skip
) {
64 if (!kernel_text_address(frame
->pc
))
67 trace
->entries
[trace
->nr_entries
++] = frame
->pc
;
68 return trace
->nr_entries
>= trace
->max_entries
;
71 void save_stack_trace_tsk(struct task_struct
*task
, struct stack_trace
*trace
)
73 struct stack_trace_data trace_data
= {
77 walk_stackframe(stack_pointer(task
), stack_trace_cb
, &trace_data
);
79 EXPORT_SYMBOL_GPL(save_stack_trace_tsk
);
81 void save_stack_trace(struct stack_trace
*trace
)
83 save_stack_trace_tsk(current
, trace
);
85 EXPORT_SYMBOL_GPL(save_stack_trace
);
89 #ifdef CONFIG_FRAME_POINTER
91 struct return_addr_data
{
96 static int return_address_cb(struct stackframe
*frame
, void *data
)
98 struct return_addr_data
*r
= data
;
104 if (!kernel_text_address(frame
->pc
))
110 unsigned long return_address(unsigned level
)
112 struct return_addr_data r
= {
115 walk_stackframe(stack_pointer(NULL
), return_address_cb
, &r
);
118 EXPORT_SYMBOL(return_address
);