diff options
author | Roman Yeryomin <roman@advem.lv> | 2012-09-13 00:40:35 +0300 |
---|---|---|
committer | Roman Yeryomin <roman@advem.lv> | 2012-12-03 00:13:21 +0200 |
commit | 5deb3317cb51ac52de922bb55f8492624018906d (patch) | |
tree | c2fbe6346699d9bb0f2100490c3029519bb8fde8 /target/linux/realtek/files/arch/rlx/kernel/stacktrace.c | |
parent | 0239d37124f9184b478a42de8a7fa1bc85a6a6fe (diff) |
Add realtek target files
Signed-off-by: Roman Yeryomin <roman@advem.lv>
Diffstat (limited to 'target/linux/realtek/files/arch/rlx/kernel/stacktrace.c')
-rw-r--r-- | target/linux/realtek/files/arch/rlx/kernel/stacktrace.c | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/target/linux/realtek/files/arch/rlx/kernel/stacktrace.c b/target/linux/realtek/files/arch/rlx/kernel/stacktrace.c new file mode 100644 index 000000000..dc228d5ad --- /dev/null +++ b/target/linux/realtek/files/arch/rlx/kernel/stacktrace.c @@ -0,0 +1,89 @@ +/* + * arch/rlx/kernel/stacktrace.c + * + * Stack trace management functions + * + * Copyright (C) 2006 Atsushi Nemoto <anemo@mba.ocn.ne.jp> + */ +#include <linux/sched.h> +#include <linux/stacktrace.h> +#include <linux/module.h> +#include <asm/stacktrace.h> + +/* + * Save stack-backtrace addresses into a stack_trace buffer: + */ +static void save_raw_context_stack(struct stack_trace *trace, + unsigned long reg29) +{ + unsigned long *sp = (unsigned long *)reg29; + unsigned long addr; + + while (!kstack_end(sp)) { + addr = *sp++; + if (__kernel_text_address(addr)) { + if (trace->skip > 0) + trace->skip--; + else + trace->entries[trace->nr_entries++] = addr; + if (trace->nr_entries >= trace->max_entries) + break; + } + } +} + +static void save_context_stack(struct stack_trace *trace, + struct task_struct *tsk, struct pt_regs *regs) +{ + unsigned long sp = regs->regs[29]; +#ifdef CONFIG_KALLSYMS + unsigned long ra = regs->regs[31]; + unsigned long pc = regs->cp0_epc; + + if (raw_show_trace || !__kernel_text_address(pc)) { + unsigned long stack_page = + (unsigned long)task_stack_page(tsk); + if (stack_page && sp >= stack_page && + sp <= stack_page + THREAD_SIZE - 32) + save_raw_context_stack(trace, sp); + return; + } + do { + if (trace->skip > 0) + trace->skip--; + else + trace->entries[trace->nr_entries++] = pc; + if (trace->nr_entries >= trace->max_entries) + break; + pc = unwind_stack(tsk, &sp, pc, &ra); + } while (pc); +#else + save_raw_context_stack(trace, sp); +#endif +} + +/* + * Save stack-backtrace addresses into a stack_trace buffer. + */ +void save_stack_trace(struct stack_trace *trace) +{ + save_stack_trace_tsk(current, trace); +} +EXPORT_SYMBOL_GPL(save_stack_trace); + +void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) +{ + struct pt_regs dummyregs; + struct pt_regs *regs = &dummyregs; + + WARN_ON(trace->nr_entries || !trace->max_entries); + + if (tsk != current) { + regs->regs[29] = tsk->thread.reg29; + regs->regs[31] = 0; + regs->cp0_epc = tsk->thread.reg31; + } else + prepare_frametrace(regs); + save_context_stack(trace, tsk, regs); +} +EXPORT_SYMBOL_GPL(save_stack_trace_tsk); |