xref: /openbmc/linux/arch/xtensa/kernel/stacktrace.c (revision 6d21fb7d)
1 /*
2  * Kernel and userspace stack tracing.
3  *
4  * This file is subject to the terms and conditions of the GNU General Public
5  * License.  See the file "COPYING" in the main directory of this archive
6  * for more details.
7  *
8  * Copyright (C) 2001 - 2013 Tensilica Inc.
9  * Copyright (C) 2015 Cadence Design Systems Inc.
10  */
11 #include <linux/export.h>
12 #include <linux/sched.h>
13 #include <linux/stacktrace.h>
14 
15 #include <asm/ftrace.h>
16 #include <asm/stacktrace.h>
17 #include <asm/traps.h>
18 #include <linux/uaccess.h>
19 
20 #if IS_ENABLED(CONFIG_PERF_EVENTS)
21 
22 /* Address of common_exception_return, used to check the
23  * transition from kernel to user space.
24  */
25 extern int common_exception_return;
26 
27 void xtensa_backtrace_user(struct pt_regs *regs, unsigned int depth,
28 			   int (*ufn)(struct stackframe *frame, void *data),
29 			   void *data)
30 {
31 	unsigned long windowstart = regs->windowstart;
32 	unsigned long windowbase = regs->windowbase;
33 	unsigned long a0 = regs->areg[0];
34 	unsigned long a1 = regs->areg[1];
35 	unsigned long pc = regs->pc;
36 	struct stackframe frame;
37 	int index;
38 
39 	if (!depth--)
40 		return;
41 
42 	frame.pc = pc;
43 	frame.sp = a1;
44 
45 	if (pc == 0 || pc >= TASK_SIZE || ufn(&frame, data))
46 		return;
47 
48 	if (IS_ENABLED(CONFIG_USER_ABI_CALL0_ONLY) ||
49 	    (IS_ENABLED(CONFIG_USER_ABI_CALL0_PROBE) &&
50 	     !(regs->ps & PS_WOE_MASK)))
51 		return;
52 
53 	/* Two steps:
54 	 *
55 	 * 1. Look through the register window for the
56 	 * previous PCs in the call trace.
57 	 *
58 	 * 2. Look on the stack.
59 	 */
60 
61 	/* Step 1.  */
62 	/* Rotate WINDOWSTART to move the bit corresponding to
63 	 * the current window to the bit #0.
64 	 */
65 	windowstart = (windowstart << WSBITS | windowstart) >> windowbase;
66 
67 	/* Look for bits that are set, they correspond to
68 	 * valid windows.
69 	 */
70 	for (index = WSBITS - 1; (index > 0) && depth; depth--, index--)
71 		if (windowstart & (1 << index)) {
72 			/* Get the PC from a0 and a1. */
73 			pc = MAKE_PC_FROM_RA(a0, pc);
74 			/* Read a0 and a1 from the
75 			 * corresponding position in AREGs.
76 			 */
77 			a0 = regs->areg[index * 4];
78 			a1 = regs->areg[index * 4 + 1];
79 
80 			frame.pc = pc;
81 			frame.sp = a1;
82 
83 			if (pc == 0 || pc >= TASK_SIZE || ufn(&frame, data))
84 				return;
85 		}
86 
87 	/* Step 2. */
88 	/* We are done with the register window, we need to
89 	 * look through the stack.
90 	 */
91 	if (!depth)
92 		return;
93 
94 	/* Start from the a1 register. */
95 	/* a1 = regs->areg[1]; */
96 	while (a0 != 0 && depth--) {
97 		pc = MAKE_PC_FROM_RA(a0, pc);
98 
99 		/* Check if the region is OK to access. */
100 		if (!access_ok(&SPILL_SLOT(a1, 0), 8))
101 			return;
102 		/* Copy a1, a0 from user space stack frame. */
103 		if (__get_user(a0, &SPILL_SLOT(a1, 0)) ||
104 		    __get_user(a1, &SPILL_SLOT(a1, 1)))
105 			return;
106 
107 		frame.pc = pc;
108 		frame.sp = a1;
109 
110 		if (pc == 0 || pc >= TASK_SIZE || ufn(&frame, data))
111 			return;
112 	}
113 }
114 EXPORT_SYMBOL(xtensa_backtrace_user);
115 
116 void xtensa_backtrace_kernel(struct pt_regs *regs, unsigned int depth,
117 			     int (*kfn)(struct stackframe *frame, void *data),
118 			     int (*ufn)(struct stackframe *frame, void *data),
119 			     void *data)
120 {
121 	unsigned long pc = regs->depc > VALID_DOUBLE_EXCEPTION_ADDRESS ?
122 		regs->depc : regs->pc;
123 	unsigned long sp_start, sp_end;
124 	unsigned long a0 = regs->areg[0];
125 	unsigned long a1 = regs->areg[1];
126 
127 	sp_start = a1 & ~(THREAD_SIZE - 1);
128 	sp_end = sp_start + THREAD_SIZE;
129 
130 	/* Spill the register window to the stack first. */
131 	spill_registers();
132 
133 	/* Read the stack frames one by one and create the PC
134 	 * from the a0 and a1 registers saved there.
135 	 */
136 	while (a1 > sp_start && a1 < sp_end && depth--) {
137 		struct stackframe frame;
138 
139 		frame.pc = pc;
140 		frame.sp = a1;
141 
142 		if (kernel_text_address(pc) && kfn(&frame, data))
143 			return;
144 
145 		if (pc == (unsigned long)&common_exception_return) {
146 			regs = (struct pt_regs *)a1;
147 			if (user_mode(regs)) {
148 				if (ufn == NULL)
149 					return;
150 				xtensa_backtrace_user(regs, depth, ufn, data);
151 				return;
152 			}
153 			a0 = regs->areg[0];
154 			a1 = regs->areg[1];
155 			continue;
156 		}
157 
158 		sp_start = a1;
159 
160 		pc = MAKE_PC_FROM_RA(a0, pc);
161 		a0 = SPILL_SLOT(a1, 0);
162 		a1 = SPILL_SLOT(a1, 1);
163 	}
164 }
165 EXPORT_SYMBOL(xtensa_backtrace_kernel);
166 
167 #endif
168 
169 void walk_stackframe(unsigned long *sp,
170 		int (*fn)(struct stackframe *frame, void *data),
171 		void *data)
172 {
173 	unsigned long a0, a1;
174 	unsigned long sp_end;
175 
176 	a1 = (unsigned long)sp;
177 	sp_end = ALIGN(a1, THREAD_SIZE);
178 
179 	spill_registers();
180 
181 	while (a1 < sp_end) {
182 		struct stackframe frame;
183 
184 		sp = (unsigned long *)a1;
185 
186 		a0 = SPILL_SLOT(a1, 0);
187 		a1 = SPILL_SLOT(a1, 1);
188 
189 		if (a1 <= (unsigned long)sp)
190 			break;
191 
192 		frame.pc = MAKE_PC_FROM_RA(a0, a1);
193 		frame.sp = a1;
194 
195 		if (fn(&frame, data))
196 			return;
197 	}
198 }
199 
200 #ifdef CONFIG_STACKTRACE
201 
202 struct stack_trace_data {
203 	struct stack_trace *trace;
204 	unsigned skip;
205 };
206 
207 static int stack_trace_cb(struct stackframe *frame, void *data)
208 {
209 	struct stack_trace_data *trace_data = data;
210 	struct stack_trace *trace = trace_data->trace;
211 
212 	if (trace_data->skip) {
213 		--trace_data->skip;
214 		return 0;
215 	}
216 	if (!kernel_text_address(frame->pc))
217 		return 0;
218 
219 	trace->entries[trace->nr_entries++] = frame->pc;
220 	return trace->nr_entries >= trace->max_entries;
221 }
222 
223 void save_stack_trace_tsk(struct task_struct *task, struct stack_trace *trace)
224 {
225 	struct stack_trace_data trace_data = {
226 		.trace = trace,
227 		.skip = trace->skip,
228 	};
229 	walk_stackframe(stack_pointer(task), stack_trace_cb, &trace_data);
230 }
231 EXPORT_SYMBOL_GPL(save_stack_trace_tsk);
232 
233 void save_stack_trace(struct stack_trace *trace)
234 {
235 	save_stack_trace_tsk(current, trace);
236 }
237 EXPORT_SYMBOL_GPL(save_stack_trace);
238 
239 #endif
240 
241 struct return_addr_data {
242 	unsigned long addr;
243 	unsigned skip;
244 };
245 
246 static int return_address_cb(struct stackframe *frame, void *data)
247 {
248 	struct return_addr_data *r = data;
249 
250 	if (r->skip) {
251 		--r->skip;
252 		return 0;
253 	}
254 	if (!kernel_text_address(frame->pc))
255 		return 0;
256 	r->addr = frame->pc;
257 	return 1;
258 }
259 
260 /*
261  * level == 0 is for the return address from the caller of this function,
262  * not from this function itself.
263  */
264 unsigned long return_address(unsigned level)
265 {
266 	struct return_addr_data r = {
267 		.skip = level,
268 	};
269 	walk_stackframe(stack_pointer(NULL), return_address_cb, &r);
270 	return r.addr;
271 }
272 EXPORT_SYMBOL(return_address);
273