1  /* SPDX-License-Identifier: GPL-2.0 */
2  #ifndef __ASM_STACKTRACE_H
3  #define __ASM_STACKTRACE_H
4  
5  #include <asm/ptrace.h>
6  #include <linux/llist.h>
7  
8  struct stackframe {
9  	/*
10  	 * FP member should hold R7 when CONFIG_THUMB2_KERNEL is enabled
11  	 * and R11 otherwise.
12  	 */
13  	unsigned long fp;
14  	unsigned long sp;
15  	unsigned long lr;
16  	unsigned long pc;
17  
18  	/* address of the LR value on the stack */
19  	unsigned long *lr_addr;
20  #ifdef CONFIG_KRETPROBES
21  	struct llist_node *kr_cur;
22  	struct task_struct *tsk;
23  #endif
24  #ifdef CONFIG_UNWINDER_FRAME_POINTER
25  	bool ex_frame;
26  #endif
27  };
28  
on_thread_stack(void)29  static inline bool on_thread_stack(void)
30  {
31  	unsigned long delta = current_stack_pointer ^ (unsigned long)current->stack;
32  
33  	return delta < THREAD_SIZE;
34  }
35  
36  static __always_inline
arm_get_current_stackframe(struct pt_regs * regs,struct stackframe * frame)37  void arm_get_current_stackframe(struct pt_regs *regs, struct stackframe *frame)
38  {
39  		frame->fp = frame_pointer(regs);
40  		frame->sp = regs->ARM_sp;
41  		frame->lr = regs->ARM_lr;
42  		frame->pc = regs->ARM_pc;
43  #ifdef CONFIG_KRETPROBES
44  		frame->kr_cur = NULL;
45  		frame->tsk = current;
46  #endif
47  #ifdef CONFIG_UNWINDER_FRAME_POINTER
48  		frame->ex_frame = in_entry_text(frame->pc);
49  #endif
50  }
51  
52  extern int unwind_frame(struct stackframe *frame);
53  extern void walk_stackframe(struct stackframe *frame,
54  			    bool (*fn)(void *, unsigned long), void *data);
55  extern void dump_mem(const char *lvl, const char *str, unsigned long bottom,
56  		     unsigned long top);
57  extern void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk,
58  			   const char *loglvl);
59  
60  #endif	/* __ASM_STACKTRACE_H */
61