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