GNU Linux-libre 4.14.266-gnu1
[releases.git] / arch / blackfin / kernel / dumpstack.c
1 /* Provide basic stack dumping functions
2  *
3  * Copyright 2004-2009 Analog Devices Inc.
4  *
5  * Licensed under the GPL-2 or later
6  */
7
8 #include <linux/kernel.h>
9 #include <linux/thread_info.h>
10 #include <linux/mm.h>
11 #include <linux/uaccess.h>
12 #include <linux/module.h>
13 #include <linux/sched/debug.h>
14
15 #include <asm/trace.h>
16
17 /*
18  * Checks to see if the address pointed to is either a
19  * 16-bit CALL instruction, or a 32-bit CALL instruction
20  */
21 static bool is_bfin_call(unsigned short *addr)
22 {
23         unsigned int opcode;
24
25         if (!get_instruction(&opcode, addr))
26                 return false;
27
28         if ((opcode >= 0x0060 && opcode <= 0x0067) ||
29             (opcode >= 0x0070 && opcode <= 0x0077) ||
30             (opcode >= 0xE3000000 && opcode <= 0xE3FFFFFF))
31                 return true;
32
33         return false;
34
35 }
36
37 void show_stack(struct task_struct *task, unsigned long *stack)
38 {
39 #ifdef CONFIG_PRINTK
40         unsigned int *addr, *endstack, *fp = 0, *frame;
41         unsigned short *ins_addr;
42         char buf[150];
43         unsigned int i, j, ret_addr, frame_no = 0;
44
45         /*
46          * If we have been passed a specific stack, use that one otherwise
47          *    if we have been passed a task structure, use that, otherwise
48          *    use the stack of where the variable "stack" exists
49          */
50
51         if (stack == NULL) {
52                 if (task) {
53                         /* We know this is a kernel stack, so this is the start/end */
54                         stack = (unsigned long *)task->thread.ksp;
55                         endstack = (unsigned int *)(((unsigned int)(stack) & ~(THREAD_SIZE - 1)) + THREAD_SIZE);
56                 } else {
57                         /* print out the existing stack info */
58                         stack = (unsigned long *)&stack;
59                         endstack = (unsigned int *)PAGE_ALIGN((unsigned int)stack);
60                 }
61         } else
62                 endstack = (unsigned int *)PAGE_ALIGN((unsigned int)stack);
63
64         printk(KERN_NOTICE "Stack info:\n");
65         decode_address(buf, (unsigned int)stack);
66         printk(KERN_NOTICE " SP: [0x%p] %s\n", stack, buf);
67
68         if (!access_ok(VERIFY_READ, stack, (unsigned int)endstack - (unsigned int)stack)) {
69                 printk(KERN_NOTICE "Invalid stack pointer\n");
70                 return;
71         }
72
73         /* First thing is to look for a frame pointer */
74         for (addr = (unsigned int *)((unsigned int)stack & ~0xF); addr < endstack; addr++) {
75                 if (*addr & 0x1)
76                         continue;
77                 ins_addr = (unsigned short *)*addr;
78                 ins_addr--;
79                 if (is_bfin_call(ins_addr))
80                         fp = addr - 1;
81
82                 if (fp) {
83                         /* Let's check to see if it is a frame pointer */
84                         while (fp >= (addr - 1) && fp < endstack
85                                && fp && ((unsigned int) fp & 0x3) == 0)
86                                 fp = (unsigned int *)*fp;
87                         if (fp == 0 || fp == endstack) {
88                                 fp = addr - 1;
89                                 break;
90                         }
91                         fp = 0;
92                 }
93         }
94         if (fp) {
95                 frame = fp;
96                 printk(KERN_NOTICE " FP: (0x%p)\n", fp);
97         } else
98                 frame = 0;
99
100         /*
101          * Now that we think we know where things are, we
102          * walk the stack again, this time printing things out
103          * incase there is no frame pointer, we still look for
104          * valid return addresses
105          */
106
107         /* First time print out data, next time, print out symbols */
108         for (j = 0; j <= 1; j++) {
109                 if (j)
110                         printk(KERN_NOTICE "Return addresses in stack:\n");
111                 else
112                         printk(KERN_NOTICE " Memory from 0x%08lx to %p", ((long unsigned int)stack & ~0xF), endstack);
113
114                 fp = frame;
115                 frame_no = 0;
116
117                 for (addr = (unsigned int *)((unsigned int)stack & ~0xF), i = 0;
118                      addr < endstack; addr++, i++) {
119
120                         ret_addr = 0;
121                         if (!j && i % 8 == 0)
122                                 printk(KERN_NOTICE "%p:", addr);
123
124                         /* if it is an odd address, or zero, just skip it */
125                         if (*addr & 0x1 || !*addr)
126                                 goto print;
127
128                         ins_addr = (unsigned short *)*addr;
129
130                         /* Go back one instruction, and see if it is a CALL */
131                         ins_addr--;
132                         ret_addr = is_bfin_call(ins_addr);
133  print:
134                         if (!j && stack == (unsigned long *)addr)
135                                 printk("[%08x]", *addr);
136                         else if (ret_addr)
137                                 if (j) {
138                                         decode_address(buf, (unsigned int)*addr);
139                                         if (frame == addr) {
140                                                 printk(KERN_NOTICE "   frame %2i : %s\n", frame_no, buf);
141                                                 continue;
142                                         }
143                                         printk(KERN_NOTICE "    address : %s\n", buf);
144                                 } else
145                                         printk("<%08x>", *addr);
146                         else if (fp == addr) {
147                                 if (j)
148                                         frame = addr+1;
149                                 else
150                                         printk("(%08x)", *addr);
151
152                                 fp = (unsigned int *)*addr;
153                                 frame_no++;
154
155                         } else if (!j)
156                                 printk(" %08x ", *addr);
157                 }
158                 if (!j)
159                         printk("\n");
160         }
161 #endif
162 }
163 EXPORT_SYMBOL(show_stack);
164
165 void dump_stack(void)
166 {
167         unsigned long stack;
168 #ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON
169         int tflags;
170 #endif
171         trace_buffer_save(tflags);
172         dump_bfin_trace_buffer();
173         dump_stack_print_info(KERN_DEFAULT);
174         show_stack(current, &stack);
175         trace_buffer_restore(tflags);
176 }
177 EXPORT_SYMBOL(dump_stack);