1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3 * Most of this ideas comes from x86.
4 *
5 * Copyright (C) 2020 Loongson Technology Corporation Limited
6 */
7 #ifndef _ASM_UNWIND_H
8 #define _ASM_UNWIND_H
9
10 #include <linux/module.h>
11 #include <linux/ftrace.h>
12 #include <linux/sched.h>
13
14 #include <asm/ptrace.h>
15 #include <asm/stacktrace.h>
16
17 struct unwind_state {
18 struct stack_info stack_info;
19 struct task_struct *task;
20 int graph_idx;
21 #if defined(CONFIG_UNWINDER_PROLOGUE)
22 unsigned long sp, pc, ra;
23 bool enable;
24 bool first;
25 #elif defined(CONFIG_UNWINDER_ORC)
26 unsigned long sp, pc, fp, ra;
27 #else /* CONFIG_UNWINDER_GUESS */
28 unsigned long sp, pc;
29 bool first;
30 #endif
31 bool error, is_ftrace;
32 };
33
34 void unwind_start(struct unwind_state *state, struct task_struct *task,
35 struct pt_regs *regs);
36 bool unwind_next_frame(struct unwind_state *state);
37 unsigned long unwind_get_return_address(struct unwind_state *state);
38
unwind_done(struct unwind_state *state)39 static inline bool unwind_done(struct unwind_state *state)
40 {
41 return state->stack_info.type == STACK_TYPE_UNKNOWN;
42 }
43
unwind_error(struct unwind_state *state)44 static inline bool unwind_error(struct unwind_state *state)
45 {
46 return state->error;
47 }
48
49 #ifdef CONFIG_UNWINDER_ORC
50 void unwind_init(void);
51 void unwind_module_init(struct module *mod, void *orc_ip, size_t orc_ip_size, void *orc, size_t orc_size);
52 #else
unwind_init(void)53 static inline void unwind_init(void) {}
unwind_module_init(struct module *mod, void *orc_ip, size_t orc_ip_size, void *orc, size_t orc_size)54 static inline void unwind_module_init(struct module *mod, void *orc_ip, size_t orc_ip_size, void *orc, size_t orc_size) {}
55 #endif /* CONFIG_UNWINDER_ORC */
56
57 #define GRAPH_FAKE_OFFSET (sizeof(struct pt_regs) - offsetof(struct pt_regs, regs[1]))
58
unwind_graph_addr(struct unwind_state *state, unsigned long pc, unsigned long cfa)59 static inline unsigned long unwind_graph_addr(struct unwind_state *state,
60 unsigned long pc, unsigned long cfa)
61 {
62 return ftrace_graph_ret_addr(state->task, &state->graph_idx,
63 pc, (unsigned long *)(cfa - GRAPH_FAKE_OFFSET));
64 }
65 #endif /* _ASM_UNWIND_H */
66