Path: blob/master/arch/blackfin/kernel/dumpstack.c
10817 views
/* Provide basic stack dumping functions1*2* Copyright 2004-2009 Analog Devices Inc.3*4* Licensed under the GPL-2 or later5*/67#include <linux/kernel.h>8#include <linux/thread_info.h>9#include <linux/mm.h>10#include <linux/uaccess.h>11#include <linux/module.h>12#include <asm/trace.h>1314/*15* Checks to see if the address pointed to is either a16* 16-bit CALL instruction, or a 32-bit CALL instruction17*/18static bool is_bfin_call(unsigned short *addr)19{20unsigned int opcode;2122if (!get_instruction(&opcode, addr))23return false;2425if ((opcode >= 0x0060 && opcode <= 0x0067) ||26(opcode >= 0x0070 && opcode <= 0x0077) ||27(opcode >= 0xE3000000 && opcode <= 0xE3FFFFFF))28return true;2930return false;3132}3334void show_stack(struct task_struct *task, unsigned long *stack)35{36#ifdef CONFIG_PRINTK37unsigned int *addr, *endstack, *fp = 0, *frame;38unsigned short *ins_addr;39char buf[150];40unsigned int i, j, ret_addr, frame_no = 0;4142/*43* If we have been passed a specific stack, use that one otherwise44* if we have been passed a task structure, use that, otherwise45* use the stack of where the variable "stack" exists46*/4748if (stack == NULL) {49if (task) {50/* We know this is a kernel stack, so this is the start/end */51stack = (unsigned long *)task->thread.ksp;52endstack = (unsigned int *)(((unsigned int)(stack) & ~(THREAD_SIZE - 1)) + THREAD_SIZE);53} else {54/* print out the existing stack info */55stack = (unsigned long *)&stack;56endstack = (unsigned int *)PAGE_ALIGN((unsigned int)stack);57}58} else59endstack = (unsigned int *)PAGE_ALIGN((unsigned int)stack);6061printk(KERN_NOTICE "Stack info:\n");62decode_address(buf, (unsigned int)stack);63printk(KERN_NOTICE " SP: [0x%p] %s\n", stack, buf);6465if (!access_ok(VERIFY_READ, stack, (unsigned int)endstack - (unsigned int)stack)) {66printk(KERN_NOTICE "Invalid stack pointer\n");67return;68}6970/* First thing is to look for a frame pointer */71for (addr = (unsigned int *)((unsigned int)stack & ~0xF); addr < endstack; addr++) {72if (*addr & 0x1)73continue;74ins_addr = (unsigned short *)*addr;75ins_addr--;76if (is_bfin_call(ins_addr))77fp = addr - 1;7879if (fp) {80/* Let's check to see if it is a frame pointer */81while (fp >= (addr - 1) && fp < endstack82&& fp && ((unsigned int) fp & 0x3) == 0)83fp = (unsigned int *)*fp;84if (fp == 0 || fp == endstack) {85fp = addr - 1;86break;87}88fp = 0;89}90}91if (fp) {92frame = fp;93printk(KERN_NOTICE " FP: (0x%p)\n", fp);94} else95frame = 0;9697/*98* Now that we think we know where things are, we99* walk the stack again, this time printing things out100* incase there is no frame pointer, we still look for101* valid return addresses102*/103104/* First time print out data, next time, print out symbols */105for (j = 0; j <= 1; j++) {106if (j)107printk(KERN_NOTICE "Return addresses in stack:\n");108else109printk(KERN_NOTICE " Memory from 0x%08lx to %p", ((long unsigned int)stack & ~0xF), endstack);110111fp = frame;112frame_no = 0;113114for (addr = (unsigned int *)((unsigned int)stack & ~0xF), i = 0;115addr < endstack; addr++, i++) {116117ret_addr = 0;118if (!j && i % 8 == 0)119printk(KERN_NOTICE "%p:", addr);120121/* if it is an odd address, or zero, just skip it */122if (*addr & 0x1 || !*addr)123goto print;124125ins_addr = (unsigned short *)*addr;126127/* Go back one instruction, and see if it is a CALL */128ins_addr--;129ret_addr = is_bfin_call(ins_addr);130print:131if (!j && stack == (unsigned long *)addr)132printk("[%08x]", *addr);133else if (ret_addr)134if (j) {135decode_address(buf, (unsigned int)*addr);136if (frame == addr) {137printk(KERN_NOTICE " frame %2i : %s\n", frame_no, buf);138continue;139}140printk(KERN_NOTICE " address : %s\n", buf);141} else142printk("<%08x>", *addr);143else if (fp == addr) {144if (j)145frame = addr+1;146else147printk("(%08x)", *addr);148149fp = (unsigned int *)*addr;150frame_no++;151152} else if (!j)153printk(" %08x ", *addr);154}155if (!j)156printk("\n");157}158#endif159}160EXPORT_SYMBOL(show_stack);161162void dump_stack(void)163{164unsigned long stack;165#ifdef CONFIG_DEBUG_BFIN_HWTRACE_ON166int tflags;167#endif168trace_buffer_save(tflags);169dump_bfin_trace_buffer();170show_stack(current, &stack);171trace_buffer_restore(tflags);172}173EXPORT_SYMBOL(dump_stack);174175176