xref: /kvm-unit-tests/lib/ppc64/stack.c (revision ac6e1abfedf922c87abac7c2aba03ed9c25b6cc8)
1 #include <libcflat.h>
2 #include <asm/ptrace.h>
3 #include <stack.h>
4 
5 extern char do_handle_exception_return[];
6 
arch_backtrace_frame(const void * frame,const void ** return_addrs,int max_depth,bool current_frame)7 int arch_backtrace_frame(const void *frame, const void **return_addrs,
8 			 int max_depth, bool current_frame)
9 {
10 	static int walking;
11 	int depth = 0;
12 	const unsigned long *bp = (unsigned long *)frame;
13 	void *return_addr;
14 
15 	asm volatile("" ::: "lr"); /* Force it to save LR */
16 
17 	if (walking) {
18 		printf("RECURSIVE STACK WALK!!!\n");
19 		return 0;
20 	}
21 	walking = 1;
22 
23 	if (current_frame)
24 		bp = __builtin_frame_address(0);
25 
26 	bp = (unsigned long *)bp[0];
27 	return_addr = (void *)bp[2];
28 
29 	for (depth = 0; bp && depth < max_depth; depth++) {
30 		return_addrs[depth] = return_addr;
31 		if (return_addrs[depth] == 0)
32 			break;
33 		if (return_addrs[depth] == do_handle_exception_return) {
34 			struct pt_regs *regs;
35 
36 			regs = (void *)bp + STACK_FRAME_OVERHEAD;
37 			bp = (unsigned long *)bp[0];
38 			/* Represent interrupt frame with vector number */
39 			return_addr = (void *)regs->trap;
40 			if (depth + 1 < max_depth) {
41 				depth++;
42 				return_addrs[depth] = return_addr;
43 				return_addr = (void *)regs->nip;
44 			}
45 		} else {
46 			bp = (unsigned long *)bp[0];
47 			return_addr = (void *)bp[2];
48 		}
49 	}
50 
51 	walking = 0;
52 	return depth;
53 }
54