Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.15.
 1// SPDX-License-Identifier: GPL-2.0
 2/* Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. */
 3
 4#include <linux/sched/debug.h>
 5#include <linux/sched/task_stack.h>
 6#include <linux/stacktrace.h>
 7#include <linux/ftrace.h>
 8
 9void save_stack_trace(struct stack_trace *trace)
10{
11	save_stack_trace_tsk(current, trace);
12}
13EXPORT_SYMBOL_GPL(save_stack_trace);
14
15void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
16{
17	unsigned long *fp, *stack_start, *stack_end;
18	unsigned long addr;
19	int skip = trace->skip;
20	int savesched;
21	int graph_idx = 0;
22
23	if (tsk == current) {
24		asm volatile("mov %0, r8\n":"=r"(fp));
25		savesched = 1;
26	} else {
27		fp = (unsigned long *)thread_saved_fp(tsk);
28		savesched = 0;
29	}
30
31	addr = (unsigned long) fp & THREAD_MASK;
32	stack_start = (unsigned long *) addr;
33	stack_end = (unsigned long *) (addr + THREAD_SIZE);
34
35	while (fp > stack_start && fp < stack_end) {
36		unsigned long lpp, fpp;
37
38		fpp = fp[0];
39		lpp = fp[1];
40		if (!__kernel_text_address(lpp))
41			break;
42		else
43			lpp = ftrace_graph_ret_addr(tsk, &graph_idx, lpp, NULL);
44
45		if (savesched || !in_sched_functions(lpp)) {
46			if (skip) {
47				skip--;
48			} else {
49				trace->entries[trace->nr_entries++] = lpp;
50				if (trace->nr_entries >= trace->max_entries)
51					break;
52			}
53		}
54		fp = (unsigned long *)fpp;
55	}
56}
57EXPORT_SYMBOL_GPL(save_stack_trace_tsk);