1/*
2 * Blackfin stacktrace code (mostly copied from avr32)
3 *
4 * Copyright 2009 Analog Devices Inc.
5 * Licensed under the GPL-2 or later.
6 */
7
8#include <linux/sched.h>
9#include <linux/stacktrace.h>
10#include <linux/thread_info.h>
11#include <linux/module.h>
12
13register unsigned long current_frame_pointer asm("FP");
14
15struct stackframe {
16	unsigned long fp;
17	unsigned long rets;
18};
19
20/*
21 * Save stack-backtrace addresses into a stack_trace buffer.
22 */
23void save_stack_trace(struct stack_trace *trace)
24{
25	unsigned long low, high;
26	unsigned long fp;
27	struct stackframe *frame;
28	int skip = trace->skip;
29
30	low = (unsigned long)task_stack_page(current);
31	high = low + THREAD_SIZE;
32	fp = current_frame_pointer;
33
34	while (fp >= low && fp <= (high - sizeof(*frame))) {
35		frame = (struct stackframe *)fp;
36
37		if (skip) {
38			skip--;
39		} else {
40			trace->entries[trace->nr_entries++] = frame->rets;
41			if (trace->nr_entries >= trace->max_entries)
42				break;
43		}
44
45		/*
46		 * The next frame must be at a higher address than the
47		 * current frame.
48		 */
49		low = fp + sizeof(*frame);
50		fp = frame->fp;
51	}
52}
53EXPORT_SYMBOL_GPL(save_stack_trace);
54