~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/blackfin/kernel/dumpstack.c

Version: ~ [ linux-5.2-rc1 ] ~ [ linux-5.1.2 ] ~ [ linux-5.0.16 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.43 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.119 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.176 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.179 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.139 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.67 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.39.4 ] ~ [ linux-2.6.38.8 ] ~ [ linux-2.6.37.6 ] ~ [ linux-2.6.36.4 ] ~ [ linux-2.6.35.14 ] ~ [ linux-2.6.34.15 ] ~ [ linux-2.6.33.20 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp