Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  1/*
  2 * Stack trace utility for OpenRISC
  3 *
  4 * Copyright (C) 2017 Stafford Horne <shorne@gmail.com>
  5 *
  6 * This file is licensed under the terms of the GNU General Public License
  7 * version 2.  This program is licensed "as is" without any warranty of any
  8 * kind, whether express or implied.
  9 *
 10 * Losely based on work from sh and powerpc.
 11 */
 12
 13#include <linux/export.h>
 14#include <linux/sched.h>
 15#include <linux/sched/debug.h>
 16#include <linux/sched/task_stack.h>
 17#include <linux/stacktrace.h>
 18
 19#include <asm/processor.h>
 20#include <asm/unwinder.h>
 21
 22/*
 23 * Save stack-backtrace addresses into a stack_trace buffer.
 24 */
 25static void
 26save_stack_address(void *data, unsigned long addr, int reliable)
 27{
 28	struct stack_trace *trace = data;
 29
 30	if (!reliable)
 31		return;
 32
 33	if (trace->skip > 0) {
 34		trace->skip--;
 35		return;
 36	}
 37
 38	if (trace->nr_entries < trace->max_entries)
 39		trace->entries[trace->nr_entries++] = addr;
 40}
 41
 42void save_stack_trace(struct stack_trace *trace)
 43{
 44	unwind_stack(trace, (unsigned long *) &trace, save_stack_address);
 45}
 46EXPORT_SYMBOL_GPL(save_stack_trace);
 47
 48static void
 49save_stack_address_nosched(void *data, unsigned long addr, int reliable)
 50{
 51	struct stack_trace *trace = (struct stack_trace *)data;
 52
 53	if (!reliable)
 54		return;
 55
 56	if (in_sched_functions(addr))
 57		return;
 58
 59	if (trace->skip > 0) {
 60		trace->skip--;
 61		return;
 62	}
 63
 64	if (trace->nr_entries < trace->max_entries)
 65		trace->entries[trace->nr_entries++] = addr;
 66}
 67
 68void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
 69{
 70	unsigned long *sp = NULL;
 71
 72	if (!try_get_task_stack(tsk))
 73		return;
 74
 75	if (tsk == current)
 76		sp = (unsigned long *) &sp;
 77	else {
 78		unsigned long ksp;
 79
 80		/* Locate stack from kernel context */
 81		ksp = task_thread_info(tsk)->ksp;
 82		ksp += STACK_FRAME_OVERHEAD;	/* redzone */
 83		ksp += sizeof(struct pt_regs);
 84
 85		sp = (unsigned long *) ksp;
 86	}
 87
 88	unwind_stack(trace, sp, save_stack_address_nosched);
 89
 90	put_task_stack(tsk);
 91}
 92EXPORT_SYMBOL_GPL(save_stack_trace_tsk);
 93
 94void
 95save_stack_trace_regs(struct pt_regs *regs, struct stack_trace *trace)
 96{
 97	unwind_stack(trace, (unsigned long *) regs->sp,
 98		     save_stack_address_nosched);
 99}
100EXPORT_SYMBOL_GPL(save_stack_trace_regs);