xref: /openbmc/linux/arch/microblaze/kernel/stacktrace.c (revision 24b45a12c21132e78e14f3aedf74bb1297228072)
1*24b45a12SMichal Simek /*
2*24b45a12SMichal Simek  * Stack trace support for Microblaze.
3*24b45a12SMichal Simek  *
4*24b45a12SMichal Simek  * Copyright (C) 2009 Michal Simek <monstr@monstr.eu>
5*24b45a12SMichal Simek  * Copyright (C) 2009 PetaLogix
6*24b45a12SMichal Simek  *
7*24b45a12SMichal Simek  * This file is subject to the terms and conditions of the GNU General Public
8*24b45a12SMichal Simek  * License. See the file "COPYING" in the main directory of this archive
9*24b45a12SMichal Simek  * for more details.
10*24b45a12SMichal Simek  */
11*24b45a12SMichal Simek 
12*24b45a12SMichal Simek #include <linux/sched.h>
13*24b45a12SMichal Simek #include <linux/stacktrace.h>
14*24b45a12SMichal Simek #include <linux/thread_info.h>
15*24b45a12SMichal Simek #include <linux/ptrace.h>
16*24b45a12SMichal Simek #include <linux/module.h>
17*24b45a12SMichal Simek 
18*24b45a12SMichal Simek /* FIXME initial support */
19*24b45a12SMichal Simek void save_stack_trace(struct stack_trace *trace)
20*24b45a12SMichal Simek {
21*24b45a12SMichal Simek 	unsigned long *sp;
22*24b45a12SMichal Simek 	unsigned long addr;
23*24b45a12SMichal Simek 	asm("addik %0, r1, 0" : "=r" (sp));
24*24b45a12SMichal Simek 
25*24b45a12SMichal Simek 	while (!kstack_end(sp)) {
26*24b45a12SMichal Simek 		addr = *sp++;
27*24b45a12SMichal Simek 		if (__kernel_text_address(addr)) {
28*24b45a12SMichal Simek 			if (trace->skip > 0)
29*24b45a12SMichal Simek 				trace->skip--;
30*24b45a12SMichal Simek 			else
31*24b45a12SMichal Simek 				trace->entries[trace->nr_entries++] = addr;
32*24b45a12SMichal Simek 
33*24b45a12SMichal Simek 			if (trace->nr_entries >= trace->max_entries)
34*24b45a12SMichal Simek 				break;
35*24b45a12SMichal Simek 		}
36*24b45a12SMichal Simek 	}
37*24b45a12SMichal Simek }
38*24b45a12SMichal Simek EXPORT_SYMBOL_GPL(save_stack_trace);
39*24b45a12SMichal Simek 
40*24b45a12SMichal Simek void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
41*24b45a12SMichal Simek {
42*24b45a12SMichal Simek 	unsigned int *sp;
43*24b45a12SMichal Simek 	unsigned long addr;
44*24b45a12SMichal Simek 
45*24b45a12SMichal Simek 	struct thread_info *ti = task_thread_info(tsk);
46*24b45a12SMichal Simek 
47*24b45a12SMichal Simek 	if (tsk == current)
48*24b45a12SMichal Simek 		asm("addik %0, r1, 0" : "=r" (sp));
49*24b45a12SMichal Simek 	else
50*24b45a12SMichal Simek 		sp = (unsigned int *)ti->cpu_context.r1;
51*24b45a12SMichal Simek 
52*24b45a12SMichal Simek 	while (!kstack_end(sp)) {
53*24b45a12SMichal Simek 		addr = *sp++;
54*24b45a12SMichal Simek 		if (__kernel_text_address(addr)) {
55*24b45a12SMichal Simek 			if (trace->skip > 0)
56*24b45a12SMichal Simek 				trace->skip--;
57*24b45a12SMichal Simek 			else
58*24b45a12SMichal Simek 				trace->entries[trace->nr_entries++] = addr;
59*24b45a12SMichal Simek 
60*24b45a12SMichal Simek 			if (trace->nr_entries >= trace->max_entries)
61*24b45a12SMichal Simek 				break;
62*24b45a12SMichal Simek 		}
63*24b45a12SMichal Simek 	}
64*24b45a12SMichal Simek }
65*24b45a12SMichal Simek EXPORT_SYMBOL_GPL(save_stack_trace_tsk);
66