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 <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 */
  21static 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
  37void 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}
 163EXPORT_SYMBOL(show_stack);
 164
 165void 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}
 177EXPORT_SYMBOL(dump_stack);
 178