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);