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