xref: /optee_os/lib/libunw/unwind_riscv.c (revision 2661af29aba5e21335f9d52dee42c960b3c80cec)
1*2661af29SAlvin Chang // SPDX-License-Identifier: BSD-2-Clause
2*2661af29SAlvin Chang /*-
3*2661af29SAlvin Chang  * Copyright (c) 2023 Andes Technology Corporation
4*2661af29SAlvin Chang  * Copyright (c) 2015-2019 Linaro Limited
5*2661af29SAlvin Chang  * Copyright (c) 2015 The FreeBSD Foundation
6*2661af29SAlvin Chang  */
7*2661af29SAlvin Chang 
8*2661af29SAlvin Chang #include <compiler.h>
9*2661af29SAlvin Chang #include <string.h>
10*2661af29SAlvin Chang #include <trace.h>
11*2661af29SAlvin Chang #include <types_ext.h>
12*2661af29SAlvin Chang #include <unw/unwind.h>
13*2661af29SAlvin Chang #include <util.h>
14*2661af29SAlvin Chang 
ftrace_map_lr(uint64_t * lr __unused)15*2661af29SAlvin Chang void __weak ftrace_map_lr(uint64_t *lr __unused)
16*2661af29SAlvin Chang {
17*2661af29SAlvin Chang }
18*2661af29SAlvin Chang 
unwind_stack_riscv(struct unwind_state_riscv * frame,vaddr_t stack,size_t stack_size)19*2661af29SAlvin Chang bool unwind_stack_riscv(struct unwind_state_riscv *frame,
20*2661af29SAlvin Chang 			vaddr_t stack, size_t stack_size)
21*2661af29SAlvin Chang {
22*2661af29SAlvin Chang 	vaddr_t fp = frame->fp;
23*2661af29SAlvin Chang 	struct unwind_state_riscv *caller_state = NULL;
24*2661af29SAlvin Chang 
25*2661af29SAlvin Chang 	if (fp < stack)
26*2661af29SAlvin Chang 		return false;
27*2661af29SAlvin Chang 	if (fp > stack + stack_size)
28*2661af29SAlvin Chang 		return false;
29*2661af29SAlvin Chang 
30*2661af29SAlvin Chang 	/*
31*2661af29SAlvin Chang 	 *  |    .....    |       ^  unwind upwards
32*2661af29SAlvin Chang 	 *  |    .....    |       |
33*2661af29SAlvin Chang 	 *  +=============+  <--+ |  +======= caller FP ==========+
34*2661af29SAlvin Chang 	 *  |     RA      |     | |
35*2661af29SAlvin Chang 	 *  +-------------+     | |
36*2661af29SAlvin Chang 	 *  |  caller FP  |  ---|-+               ^
37*2661af29SAlvin Chang 	 *  +-------------+     |          caller stack frame
38*2661af29SAlvin Chang 	 *  |    .....    |     |                 v
39*2661af29SAlvin Chang 	 *  |    .....    |     |
40*2661af29SAlvin Chang 	 *  |    .....    |     |
41*2661af29SAlvin Chang 	 *  +=============+     |    +== caller SP / trapped FP ==+
42*2661af29SAlvin Chang 	 *  |     RA      |     |
43*2661af29SAlvin Chang 	 *  +-------------+     |
44*2661af29SAlvin Chang 	 *  |  caller FP  |  ---+                 ^
45*2661af29SAlvin Chang 	 *  +-------------+               trapped stack frame
46*2661af29SAlvin Chang 	 *  |    .....    |                       v
47*2661af29SAlvin Chang 	 *  |    .....    |
48*2661af29SAlvin Chang 	 *  |    .....    |
49*2661af29SAlvin Chang 	 *  +=============+          +======== trapped SP ========+
50*2661af29SAlvin Chang 	 *         |
51*2661af29SAlvin Chang 	 *         |  grow downwards
52*2661af29SAlvin Chang 	 *         V
53*2661af29SAlvin Chang 	 */
54*2661af29SAlvin Chang 
55*2661af29SAlvin Chang 	/* Get caller FP and RA */
56*2661af29SAlvin Chang 	caller_state = (struct unwind_state_riscv *)fp - 1;
57*2661af29SAlvin Chang 	frame->fp = caller_state->fp;
58*2661af29SAlvin Chang 	frame->pc = caller_state->pc;
59*2661af29SAlvin Chang 
60*2661af29SAlvin Chang 	ftrace_map_lr(&frame->pc);
61*2661af29SAlvin Chang 
62*2661af29SAlvin Chang 	frame->pc -= 4;
63*2661af29SAlvin Chang 
64*2661af29SAlvin Chang 	return true;
65*2661af29SAlvin Chang }
66*2661af29SAlvin Chang 
print_stack_riscv(struct unwind_state_riscv * state,vaddr_t stack,size_t stack_size)67*2661af29SAlvin Chang void print_stack_riscv(struct unwind_state_riscv *state,
68*2661af29SAlvin Chang 		       vaddr_t stack, size_t stack_size)
69*2661af29SAlvin Chang {
70*2661af29SAlvin Chang 	int width = sizeof(unsigned long);
71*2661af29SAlvin Chang 
72*2661af29SAlvin Chang 	trace_printf_helper_raw(TRACE_ERROR, true, "Call stack:");
73*2661af29SAlvin Chang 
74*2661af29SAlvin Chang 	ftrace_map_lr(&state->pc);
75*2661af29SAlvin Chang 	do {
76*2661af29SAlvin Chang 		trace_printf_helper_raw(TRACE_ERROR, true, " 0x%0*"PRIxVA,
77*2661af29SAlvin Chang 					width, state->pc);
78*2661af29SAlvin Chang 	} while (unwind_stack_riscv(state, stack, stack_size));
79*2661af29SAlvin Chang }
80