xref: /linux/arch/loongarch/include/asm/unwind.h (revision 5bb8d34449c4a2eb94d657b992170afafac274f9)
149232773SQing Zhang /* SPDX-License-Identifier: GPL-2.0 */
249232773SQing Zhang /*
349232773SQing Zhang  * Most of this ideas comes from x86.
449232773SQing Zhang  *
549232773SQing Zhang  * Copyright (C) 2022 Loongson Technology Corporation Limited
649232773SQing Zhang  */
749232773SQing Zhang #ifndef _ASM_UNWIND_H
849232773SQing Zhang #define _ASM_UNWIND_H
949232773SQing Zhang 
1049232773SQing Zhang #include <linux/sched.h>
11*5bb8d344SJinyang He #include <linux/ftrace.h>
1249232773SQing Zhang 
13*5bb8d344SJinyang He #include <asm/ptrace.h>
1449232773SQing Zhang #include <asm/stacktrace.h>
1549232773SQing Zhang 
1649aef111SQing Zhang enum unwinder_type {
1749aef111SQing Zhang 	UNWINDER_GUESS,
1849aef111SQing Zhang 	UNWINDER_PROLOGUE,
1949aef111SQing Zhang };
2049aef111SQing Zhang 
2149232773SQing Zhang struct unwind_state {
2249aef111SQing Zhang 	char type; /* UNWINDER_XXX */
2349232773SQing Zhang 	struct stack_info stack_info;
2449232773SQing Zhang 	struct task_struct *task;
254733f09dSQing Zhang 	bool first, error, is_ftrace;
26a51ac524SQing Zhang 	int graph_idx;
2749aef111SQing Zhang 	unsigned long sp, pc, ra;
2849232773SQing Zhang };
2949232773SQing Zhang 
3049232773SQing Zhang void unwind_start(struct unwind_state *state,
3149232773SQing Zhang 		  struct task_struct *task, struct pt_regs *regs);
3249232773SQing Zhang bool unwind_next_frame(struct unwind_state *state);
3349232773SQing Zhang unsigned long unwind_get_return_address(struct unwind_state *state);
3449232773SQing Zhang 
3549232773SQing Zhang static inline bool unwind_done(struct unwind_state *state)
3649232773SQing Zhang {
3749232773SQing Zhang 	return state->stack_info.type == STACK_TYPE_UNKNOWN;
3849232773SQing Zhang }
3949232773SQing Zhang 
4049232773SQing Zhang static inline bool unwind_error(struct unwind_state *state)
4149232773SQing Zhang {
4249232773SQing Zhang 	return state->error;
4349232773SQing Zhang }
4449232773SQing Zhang 
45*5bb8d344SJinyang He #define GRAPH_FAKE_OFFSET (sizeof(struct pt_regs) - offsetof(struct pt_regs, regs[1]))
46*5bb8d344SJinyang He 
47*5bb8d344SJinyang He static inline unsigned long unwind_graph_addr(struct unwind_state *state,
48*5bb8d344SJinyang He 					unsigned long pc, unsigned long cfa)
49*5bb8d344SJinyang He {
50*5bb8d344SJinyang He 	return ftrace_graph_ret_addr(state->task, &state->graph_idx,
51*5bb8d344SJinyang He 				     pc, (unsigned long *)(cfa - GRAPH_FAKE_OFFSET));
52*5bb8d344SJinyang He }
5349232773SQing Zhang #endif /* _ASM_UNWIND_H */
54