tick/idle/powerpc: Do not register idle states with CPUIDLE_FLAG_TIMER_STOP set in...
[linux/fpc-iii.git] / arch / xtensa / kernel / stacktrace.c
blob7d2c317bd98b30eb2a82e2770d0ff236de66fe03
1 /*
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
6 * for more details.
8 * Copyright (C) 2001 - 2013 Tensilica Inc.
9 */
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),
19 void *data)
21 unsigned long a0, a1;
22 unsigned long sp_end;
24 a1 = (unsigned long)sp;
25 sp_end = ALIGN(a1, THREAD_SIZE);
27 spill_registers();
29 while (a1 < sp_end) {
30 struct stackframe frame;
32 sp = (unsigned long *)a1;
34 a0 = *(sp - 4);
35 a1 = *(sp - 3);
37 if (a1 <= (unsigned long)sp)
38 break;
40 frame.pc = MAKE_PC_FROM_RA(a0, a1);
41 frame.sp = a1;
43 if (fn(&frame, data))
44 return;
48 #ifdef CONFIG_STACKTRACE
50 struct stack_trace_data {
51 struct stack_trace *trace;
52 unsigned skip;
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) {
61 --trace_data->skip;
62 return 0;
64 if (!kernel_text_address(frame->pc))
65 return 0;
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 = {
74 .trace = trace,
75 .skip = trace->skip,
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);
87 #endif
89 #ifdef CONFIG_FRAME_POINTER
91 struct return_addr_data {
92 unsigned long addr;
93 unsigned skip;
96 static int return_address_cb(struct stackframe *frame, void *data)
98 struct return_addr_data *r = data;
100 if (r->skip) {
101 --r->skip;
102 return 0;
104 if (!kernel_text_address(frame->pc))
105 return 0;
106 r->addr = frame->pc;
107 return 1;
110 unsigned long return_address(unsigned level)
112 struct return_addr_data r = {
113 .skip = level + 1,
115 walk_stackframe(stack_pointer(NULL), return_address_cb, &r);
116 return r.addr;
118 EXPORT_SYMBOL(return_address);
120 #endif