xref: /openbmc/linux/arch/parisc/kernel/unwind.c (revision cbdf59ad)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Kernel unwinding support
4  *
5  * (c) 2002-2004 Randolph Chung <tausq@debian.org>
6  *
7  * Derived partially from the IA64 implementation. The PA-RISC
8  * Runtime Architecture Document is also a useful reference to
9  * understand what is happening here
10  */
11 
12 #include <linux/kernel.h>
13 #include <linux/init.h>
14 #include <linux/sched.h>
15 #include <linux/slab.h>
16 #include <linux/sort.h>
17 
18 #include <linux/uaccess.h>
19 #include <asm/assembly.h>
20 #include <asm/asm-offsets.h>
21 #include <asm/ptrace.h>
22 
23 #include <asm/unwind.h>
24 
25 /* #define DEBUG 1 */
26 #ifdef DEBUG
27 #define dbg(x...) pr_debug(x)
28 #else
29 #define dbg(x...)
30 #endif
31 
32 #define KERNEL_START (KERNEL_BINARY_TEXT_START)
33 
34 extern struct unwind_table_entry __start___unwind[];
35 extern struct unwind_table_entry __stop___unwind[];
36 
37 static DEFINE_SPINLOCK(unwind_lock);
38 /*
39  * the kernel unwind block is not dynamically allocated so that
40  * we can call unwind_init as early in the bootup process as
41  * possible (before the slab allocator is initialized)
42  */
43 static struct unwind_table kernel_unwind_table __ro_after_init;
44 static LIST_HEAD(unwind_tables);
45 
46 static inline const struct unwind_table_entry *
47 find_unwind_entry_in_table(const struct unwind_table *table, unsigned long addr)
48 {
49 	const struct unwind_table_entry *e = NULL;
50 	unsigned long lo, hi, mid;
51 
52 	lo = 0;
53 	hi = table->length - 1;
54 
55 	while (lo <= hi) {
56 		mid = (hi - lo) / 2 + lo;
57 		e = &table->table[mid];
58 		if (addr < e->region_start)
59 			hi = mid - 1;
60 		else if (addr > e->region_end)
61 			lo = mid + 1;
62 		else
63 			return e;
64 	}
65 
66 	return NULL;
67 }
68 
69 static const struct unwind_table_entry *
70 find_unwind_entry(unsigned long addr)
71 {
72 	struct unwind_table *table;
73 	const struct unwind_table_entry *e = NULL;
74 
75 	if (addr >= kernel_unwind_table.start &&
76 	    addr <= kernel_unwind_table.end)
77 		e = find_unwind_entry_in_table(&kernel_unwind_table, addr);
78 	else {
79 		unsigned long flags;
80 
81 		spin_lock_irqsave(&unwind_lock, flags);
82 		list_for_each_entry(table, &unwind_tables, list) {
83 			if (addr >= table->start &&
84 			    addr <= table->end)
85 				e = find_unwind_entry_in_table(table, addr);
86 			if (e) {
87 				/* Move-to-front to exploit common traces */
88 				list_move(&table->list, &unwind_tables);
89 				break;
90 			}
91 		}
92 		spin_unlock_irqrestore(&unwind_lock, flags);
93 	}
94 
95 	return e;
96 }
97 
98 static void
99 unwind_table_init(struct unwind_table *table, const char *name,
100 		  unsigned long base_addr, unsigned long gp,
101 		  void *table_start, void *table_end)
102 {
103 	struct unwind_table_entry *start = table_start;
104 	struct unwind_table_entry *end =
105 		(struct unwind_table_entry *)table_end - 1;
106 
107 	table->name = name;
108 	table->base_addr = base_addr;
109 	table->gp = gp;
110 	table->start = base_addr + start->region_start;
111 	table->end = base_addr + end->region_end;
112 	table->table = (struct unwind_table_entry *)table_start;
113 	table->length = end - start + 1;
114 	INIT_LIST_HEAD(&table->list);
115 
116 	for (; start <= end; start++) {
117 		if (start < end &&
118 		    start->region_end > (start+1)->region_start) {
119 			pr_warn("Out of order unwind entry! %px and %px\n",
120 				start, start+1);
121 		}
122 
123 		start->region_start += base_addr;
124 		start->region_end += base_addr;
125 	}
126 }
127 
128 static int cmp_unwind_table_entry(const void *a, const void *b)
129 {
130 	return ((const struct unwind_table_entry *)a)->region_start
131 	     - ((const struct unwind_table_entry *)b)->region_start;
132 }
133 
134 static void
135 unwind_table_sort(struct unwind_table_entry *start,
136 		  struct unwind_table_entry *finish)
137 {
138 	sort(start, finish - start, sizeof(struct unwind_table_entry),
139 	     cmp_unwind_table_entry, NULL);
140 }
141 
142 struct unwind_table *
143 unwind_table_add(const char *name, unsigned long base_addr,
144 		 unsigned long gp,
145                  void *start, void *end)
146 {
147 	struct unwind_table *table;
148 	unsigned long flags;
149 	struct unwind_table_entry *s = (struct unwind_table_entry *)start;
150 	struct unwind_table_entry *e = (struct unwind_table_entry *)end;
151 
152 	unwind_table_sort(s, e);
153 
154 	table = kmalloc(sizeof(struct unwind_table), GFP_USER);
155 	if (table == NULL)
156 		return NULL;
157 	unwind_table_init(table, name, base_addr, gp, start, end);
158 	spin_lock_irqsave(&unwind_lock, flags);
159 	list_add_tail(&table->list, &unwind_tables);
160 	spin_unlock_irqrestore(&unwind_lock, flags);
161 
162 	return table;
163 }
164 
165 void unwind_table_remove(struct unwind_table *table)
166 {
167 	unsigned long flags;
168 
169 	spin_lock_irqsave(&unwind_lock, flags);
170 	list_del(&table->list);
171 	spin_unlock_irqrestore(&unwind_lock, flags);
172 
173 	kfree(table);
174 }
175 
176 /* Called from setup_arch to import the kernel unwind info */
177 int __init unwind_init(void)
178 {
179 	long start, stop;
180 	register unsigned long gp __asm__ ("r27");
181 
182 	start = (long)&__start___unwind[0];
183 	stop = (long)&__stop___unwind[0];
184 
185 	dbg("unwind_init: start = 0x%lx, end = 0x%lx, entries = %lu\n",
186 	    start, stop,
187 	    (stop - start) / sizeof(struct unwind_table_entry));
188 
189 	unwind_table_init(&kernel_unwind_table, "kernel", KERNEL_START,
190 			  gp,
191 			  &__start___unwind[0], &__stop___unwind[0]);
192 #if 0
193 	{
194 		int i;
195 		for (i = 0; i < 10; i++)
196 		{
197 			printk("region 0x%x-0x%x\n",
198 				__start___unwind[i].region_start,
199 				__start___unwind[i].region_end);
200 		}
201 	}
202 #endif
203 	return 0;
204 }
205 
206 static int unwind_special(struct unwind_frame_info *info, unsigned long pc, int frame_size)
207 {
208 	/*
209 	 * We have to use void * instead of a function pointer, because
210 	 * function pointers aren't a pointer to the function on 64-bit.
211 	 * Make them const so the compiler knows they live in .text
212 	 * Note: We could use dereference_kernel_function_descriptor()
213 	 * instead but we want to keep it simple here.
214 	 */
215 	extern void * const handle_interruption;
216 	extern void * const ret_from_kernel_thread;
217 	extern void * const syscall_exit;
218 	extern void * const intr_return;
219 	extern void * const _switch_to_ret;
220 #ifdef CONFIG_IRQSTACKS
221 	extern void * const _call_on_stack;
222 #endif /* CONFIG_IRQSTACKS */
223 
224 	if (pc == (unsigned long) &handle_interruption) {
225 		struct pt_regs *regs = (struct pt_regs *)(info->sp - frame_size - PT_SZ_ALGN);
226 		dbg("Unwinding through handle_interruption()\n");
227 		info->prev_sp = regs->gr[30];
228 		info->prev_ip = regs->iaoq[0];
229 		return 1;
230 	}
231 
232 	if (pc == (unsigned long) &ret_from_kernel_thread ||
233 	    pc == (unsigned long) &syscall_exit) {
234 		info->prev_sp = info->prev_ip = 0;
235 		return 1;
236 	}
237 
238 	if (pc == (unsigned long) &intr_return) {
239 		struct pt_regs *regs;
240 
241 		dbg("Found intr_return()\n");
242 		regs = (struct pt_regs *)(info->sp - PT_SZ_ALGN);
243 		info->prev_sp = regs->gr[30];
244 		info->prev_ip = regs->iaoq[0];
245 		info->rp = regs->gr[2];
246 		return 1;
247 	}
248 
249 	if (pc == (unsigned long) &_switch_to_ret) {
250 		info->prev_sp = info->sp - CALLEE_SAVE_FRAME_SIZE;
251 		info->prev_ip = *(unsigned long *)(info->prev_sp - RP_OFFSET);
252 		return 1;
253 	}
254 
255 #ifdef CONFIG_IRQSTACKS
256 	if (pc == (unsigned long) &_call_on_stack) {
257 		info->prev_sp = *(unsigned long *)(info->sp - FRAME_SIZE - REG_SZ);
258 		info->prev_ip = *(unsigned long *)(info->sp - FRAME_SIZE - RP_OFFSET);
259 		return 1;
260 	}
261 #endif
262 
263 	return 0;
264 }
265 
266 static void unwind_frame_regs(struct unwind_frame_info *info)
267 {
268 	const struct unwind_table_entry *e;
269 	unsigned long npc;
270 	unsigned int insn;
271 	long frame_size = 0;
272 	int looking_for_rp, rpoffset = 0;
273 
274 	e = find_unwind_entry(info->ip);
275 	if (e == NULL) {
276 		unsigned long sp;
277 
278 		dbg("Cannot find unwind entry for %pS; forced unwinding\n",
279 			(void *) info->ip);
280 
281 		/* Since we are doing the unwinding blind, we don't know if
282 		   we are adjusting the stack correctly or extracting the rp
283 		   correctly. The rp is checked to see if it belongs to the
284 		   kernel text section, if not we assume we don't have a
285 		   correct stack frame and we continue to unwind the stack.
286 		   This is not quite correct, and will fail for loadable
287 		   modules. */
288 		sp = info->sp & ~63;
289 		do {
290 			unsigned long tmp;
291 
292 			info->prev_sp = sp - 64;
293 			info->prev_ip = 0;
294 
295 			/* The stack is at the end inside the thread_union
296 			 * struct. If we reach data, we have reached the
297 			 * beginning of the stack and should stop unwinding. */
298 			if (info->prev_sp >= (unsigned long) task_thread_info(info->t) &&
299 			    info->prev_sp < ((unsigned long) task_thread_info(info->t)
300 						+ THREAD_SZ_ALGN)) {
301 				info->prev_sp = 0;
302 				break;
303 			}
304 
305 			if (get_user(tmp, (unsigned long *)(info->prev_sp - RP_OFFSET)))
306 				break;
307 			info->prev_ip = tmp;
308 			sp = info->prev_sp;
309 		} while (!kernel_text_address(info->prev_ip));
310 
311 		info->rp = 0;
312 
313 		dbg("analyzing func @ %lx with no unwind info, setting "
314 		    "prev_sp=%lx prev_ip=%lx\n", info->ip,
315 		    info->prev_sp, info->prev_ip);
316 	} else {
317 		dbg("e->start = 0x%x, e->end = 0x%x, Save_SP = %d, "
318 		    "Save_RP = %d, Millicode = %d size = %u\n",
319 		    e->region_start, e->region_end, e->Save_SP, e->Save_RP,
320 		    e->Millicode, e->Total_frame_size);
321 
322 		looking_for_rp = e->Save_RP;
323 
324 		for (npc = e->region_start;
325 		     (frame_size < (e->Total_frame_size << 3) ||
326 		      looking_for_rp) &&
327 		     npc < info->ip;
328 		     npc += 4) {
329 
330 			insn = *(unsigned int *)npc;
331 
332 			if ((insn & 0xffffc001) == 0x37de0000 ||
333 			    (insn & 0xffe00001) == 0x6fc00000) {
334 				/* ldo X(sp), sp, or stwm X,D(sp) */
335 				frame_size += (insn & 0x3fff) >> 1;
336 				dbg("analyzing func @ %lx, insn=%08x @ "
337 				    "%lx, frame_size = %ld\n", info->ip,
338 				    insn, npc, frame_size);
339 			} else if ((insn & 0xffe00009) == 0x73c00008) {
340 				/* std,ma X,D(sp) */
341 				frame_size += ((insn >> 4) & 0x3ff) << 3;
342 				dbg("analyzing func @ %lx, insn=%08x @ "
343 				    "%lx, frame_size = %ld\n", info->ip,
344 				    insn, npc, frame_size);
345 			} else if (insn == 0x6bc23fd9) {
346 				/* stw rp,-20(sp) */
347 				rpoffset = 20;
348 				looking_for_rp = 0;
349 				dbg("analyzing func @ %lx, insn=stw rp,"
350 				    "-20(sp) @ %lx\n", info->ip, npc);
351 			} else if (insn == 0x0fc212c1) {
352 				/* std rp,-16(sr0,sp) */
353 				rpoffset = 16;
354 				looking_for_rp = 0;
355 				dbg("analyzing func @ %lx, insn=std rp,"
356 				    "-16(sp) @ %lx\n", info->ip, npc);
357 			}
358 		}
359 
360 		if (frame_size > e->Total_frame_size << 3)
361 			frame_size = e->Total_frame_size << 3;
362 
363 		if (!unwind_special(info, e->region_start, frame_size)) {
364 			info->prev_sp = info->sp - frame_size;
365 			if (e->Millicode)
366 				info->rp = info->r31;
367 			else if (rpoffset)
368 				info->rp = *(unsigned long *)(info->prev_sp - rpoffset);
369 			info->prev_ip = info->rp;
370 			info->rp = 0;
371 		}
372 
373 		dbg("analyzing func @ %lx, setting prev_sp=%lx "
374 		    "prev_ip=%lx npc=%lx\n", info->ip, info->prev_sp,
375 		    info->prev_ip, npc);
376 	}
377 }
378 
379 void unwind_frame_init(struct unwind_frame_info *info, struct task_struct *t,
380 		       struct pt_regs *regs)
381 {
382 	memset(info, 0, sizeof(struct unwind_frame_info));
383 	info->t = t;
384 	info->sp = regs->gr[30];
385 	info->ip = regs->iaoq[0];
386 	info->rp = regs->gr[2];
387 	info->r31 = regs->gr[31];
388 
389 	dbg("(%d) Start unwind from sp=%08lx ip=%08lx\n",
390 	    t ? (int)t->pid : -1, info->sp, info->ip);
391 }
392 
393 void unwind_frame_init_from_blocked_task(struct unwind_frame_info *info, struct task_struct *t)
394 {
395 	struct pt_regs *r = &t->thread.regs;
396 	struct pt_regs *r2;
397 
398 	r2 = kmalloc(sizeof(struct pt_regs), GFP_ATOMIC);
399 	if (!r2)
400 		return;
401 	*r2 = *r;
402 	r2->gr[30] = r->ksp;
403 	r2->iaoq[0] = r->kpc;
404 	unwind_frame_init(info, t, r2);
405 	kfree(r2);
406 }
407 
408 #define get_parisc_stackpointer() ({ \
409 	unsigned long sp; \
410 	__asm__("copy %%r30, %0" : "=r"(sp)); \
411 	(sp); \
412 })
413 
414 void unwind_frame_init_task(struct unwind_frame_info *info,
415 	struct task_struct *task, struct pt_regs *regs)
416 {
417 	task = task ? task : current;
418 
419 	if (task == current) {
420 		struct pt_regs r;
421 
422 		if (!regs) {
423 			memset(&r, 0, sizeof(r));
424 			r.iaoq[0] =  _THIS_IP_;
425 			r.gr[2] = _RET_IP_;
426 			r.gr[30] = get_parisc_stackpointer();
427 			regs = &r;
428 		}
429 		unwind_frame_init(info, task, regs);
430 	} else {
431 		unwind_frame_init_from_blocked_task(info, task);
432 	}
433 }
434 
435 int unwind_once(struct unwind_frame_info *next_frame)
436 {
437 	unwind_frame_regs(next_frame);
438 
439 	if (next_frame->prev_sp == 0 ||
440 	    next_frame->prev_ip == 0)
441 		return -1;
442 
443 	next_frame->sp = next_frame->prev_sp;
444 	next_frame->ip = next_frame->prev_ip;
445 	next_frame->prev_sp = 0;
446 	next_frame->prev_ip = 0;
447 
448 	dbg("(%d) Continue unwind to sp=%08lx ip=%08lx\n",
449 	    next_frame->t ? (int)next_frame->t->pid : -1,
450 	    next_frame->sp, next_frame->ip);
451 
452 	return 0;
453 }
454 
455 int unwind_to_user(struct unwind_frame_info *info)
456 {
457 	int ret;
458 
459 	do {
460 		ret = unwind_once(info);
461 	} while (!ret && !(info->ip & 3));
462 
463 	return ret;
464 }
465 
466 unsigned long return_address(unsigned int level)
467 {
468 	struct unwind_frame_info info;
469 
470 	/* initialize unwind info */
471 	unwind_frame_init_task(&info, current, NULL);
472 
473 	/* unwind stack */
474 	level += 2;
475 	do {
476 		if (unwind_once(&info) < 0 || info.ip == 0)
477 			return 0;
478 		if (!kernel_text_address(info.ip))
479 			return 0;
480 	} while (info.ip && level--);
481 
482 	return info.ip;
483 }
484