diff options
Diffstat (limited to 'target/linux/ubicom32/files/arch/ubicom32/kernel/stacktrace.c')
-rw-r--r-- | target/linux/ubicom32/files/arch/ubicom32/kernel/stacktrace.c | 244 |
1 files changed, 0 insertions, 244 deletions
diff --git a/target/linux/ubicom32/files/arch/ubicom32/kernel/stacktrace.c b/target/linux/ubicom32/files/arch/ubicom32/kernel/stacktrace.c deleted file mode 100644 index 2a10e3f4f1..0000000000 --- a/target/linux/ubicom32/files/arch/ubicom32/kernel/stacktrace.c +++ /dev/null @@ -1,244 +0,0 @@ -/* - * arch/ubicom32/kernel/stacktrace.c - * Ubicom32 architecture stack back trace implementation. - * - * (C) Copyright 2009, Ubicom, Inc. - * - * This file is part of the Ubicom32 Linux Kernel Port. - * - * The Ubicom32 Linux Kernel Port is free software: you can redistribute - * it and/or modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation, either version 2 of the - * License, or (at your option) any later version. - * - * The Ubicom32 Linux Kernel Port is distributed in the hope that it - * will be useful, but WITHOUT ANY WARRANTY; without even the implied - * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See - * the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with the Ubicom32 Linux Kernel Port. If not, - * see <http://www.gnu.org/licenses/>. - * - * Ubicom32 implementation derived from (with many thanks): - * arch/m68knommu - * arch/blackfin - * arch/parisc - */ -#include <linux/sched.h> -#include <linux/stacktrace.h> -#include <linux/module.h> -#include <asm/stacktrace.h> -#include <asm/thread.h> -#include <asm/ip5000.h> - -/* - * These symbols are filled in by the linker. - */ -extern unsigned long _stext; -extern unsigned long _etext; - -extern unsigned long __ocm_text_run_begin; -extern unsigned long __data_begin; - -/* - * stacktrace_iterate() - * Walk the stack looking for call and calli instructions on an aligned - * boundary. - * - * Trace must point to the top of the current stack frame. - */ -unsigned long stacktrace_iterate(unsigned long **trace, - unsigned long stext, - unsigned long etext, - unsigned long ocm_stext, - unsigned long ocm_etext, - unsigned long sstack, - unsigned long estack) -{ - unsigned int thread_trap_en, instruction; - unsigned long address; - unsigned int limit = 0; - unsigned long result = 0; - unsigned long *sp = *trace; - - /* - * Exclude the current thread from being monitored for traps. - */ - asm volatile( - " thread_get_self_mask d15 \n\t" - /* save current trap status */ - " and.4 %0, MT_TRAP_EN, d15 \n\t" - " not.4 d15, d15 \n\t" - /* disable trap */ - " and.4 MT_TRAP_EN, MT_TRAP_EN, d15 \n\t" - " pipe_flush 0 \n\t" - : "=r" (thread_trap_en) - : - : "d15", "cc" - ); - - while (limit++ < 256) { - /* - * See if we have a valid stack. - */ - if (!between((unsigned long)sp, sstack, estack)) { -#ifdef TRAP_DEBUG_STACK_TRACE - printk(KERN_EMERG "stack address is out of range - " - "sp: %x, sstack: %x, estack: %x\n", - (unsigned int)sp, (unsigned int)sstack, - (unsigned int)estack); -#endif - result = 0; - *trace = 0; - break; - } - - /* - * Get the value off the stack and back up 4 bytes to what - * should be the address of a call or calli. - */ - address = (*sp++) - 4; - - /* - * If the address is not within the text segment, skip this - * value. - */ - if (!between(address, stext, etext) && - !between(address, ocm_stext, ocm_etext)) { -#ifdef TRAP_DEBUG_STACK_TRACE - printk(KERN_EMERG "not a text address - " - "address: %08x, stext: %08x, etext: %08x\n" - "ocm_stext: %08x, ocm_etext: %08x\n", - (unsigned int)address, - (unsigned int)stext, - (unsigned int)etext, - (unsigned int)ocm_stext, - (unsigned int)ocm_etext); -#endif - continue; - - } - - /* - * If the address is not on an aligned boundary it can not be a - * return address. - */ - if (address & 0x3) { - continue; - } - - /* - * Read the probable instruction. - */ - instruction = *(unsigned int *)address; - - /* - * Is this a call instruction? - */ - if ((instruction & 0xF8000000) == (u32_t)(0x1B << 27)) { -#ifdef TRAP_DEBUG_STACK_TRACE - printk(KERN_EMERG "call inst. result: %x, " - "test: %x\n", (unsigned int)address, - (unsigned int)instruction); -#endif - *trace = sp; - result = address; - break; - } - - /* - * Is this a calli instruction? - */ - if ((instruction & 0xF8000000) == (u32_t)(0x1E << 27)) { -#ifdef TRAP_DEBUG_STACK_TRACE - printk(KERN_EMERG "calli inst. result: %x, " - "test: %x\n", (unsigned int)address, - (unsigned int)instruction); -#endif - *trace = sp; - result = address; - break; - } - } - - /* - * Restore the current thread to be monitored for traps. - */ - if (thread_trap_en) { - asm volatile( - " thread_get_self_mask d15 \n\t" - " or.4 MT_TRAP_EN, MT_TRAP_EN, d15 \n\t" - : - : - : "d15", "cc" - ); - } - return result; -} - -#ifdef CONFIG_STACKTRACE -/* - * stacktrace_save_entries() - * Save stack back trace information into the provided trace structure. - */ -void stacktrace_save_entries(struct task_struct *tsk, - struct stack_trace *trace, - unsigned long sp) -{ - unsigned long code_start = (unsigned long)&_stext; - unsigned long code_end = (unsigned long)&_etext; - unsigned long ocm_code_start = (unsigned long)&__ocm_text_run_begin; - unsigned long ocm_code_end = (unsigned long)&__data_begin; - unsigned long stack_end = (unsigned long)(tsk->stack + THREAD_SIZE - 8); - unsigned long stack = (unsigned long)sp; - unsigned int idx = 0; - unsigned long *handle; - int skip = trace->skip; - - handle = (unsigned long *)stack; - while (idx < trace->max_entries) { - if (skip) { - skip--; - continue; - } - trace->entries[idx] = stacktrace_iterate(&handle, - code_start, code_end, - ocm_code_start, ocm_code_end, - (unsigned long)stack, stack_end); - if (trace->entries[idx] == 0) { - break; - } - idx++; - } -} - -/* - * save_stack_trace() - * Save the specified amount of the kernel stack trace information - * for the current task. - */ -void save_stack_trace(struct stack_trace *trace) -{ - unsigned long sp = 0; - asm volatile ( - " move.4 %0, SP \n\t" - : "=r" (sp) - ); - stacktrace_save_entries(current, trace, sp); -} -EXPORT_SYMBOL_GPL(save_stack_trace); - -/* - * save_stack_trace_tsk() - * Save the specified amount of the kernel stack trace information - * for the specified task. - * - * Note: We assume the specified task is not currently running. - */ -void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) -{ - stacktrace_save_entries(tsk, trace, tsk->thread.sp); -} -EXPORT_SYMBOL_GPL(save_stack_trace_tsk); -#endif /* CONFIG_STACKTRACE */ |