1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2022 Loongson Technology Corporation Limited
5 #include <linux/kallsyms.h>
8 #include <asm/ptrace.h>
9 #include <asm/unwind.h>
11 unsigned long unwind_get_return_address(struct unwind_state *state)
14 if (unwind_done(state))
18 else if (state->first)
21 return *(unsigned long *)(state->sp);
24 EXPORT_SYMBOL_GPL(unwind_get_return_address);
26 static bool unwind_by_guess(struct unwind_state *state)
28 struct stack_info *info = &state->stack_info;
31 for (state->sp += sizeof(unsigned long);
32 state->sp < info->end;
33 state->sp += sizeof(unsigned long)) {
34 addr = *(unsigned long *)(state->sp);
35 if (__kernel_text_address(addr))
42 static bool unwind_by_prologue(struct unwind_state *state)
44 struct stack_info *info = &state->stack_info;
45 union loongarch_instruction *ip, *ip_end;
47 unsigned long frame_size = 0;
48 unsigned long size, offset, pc = state->pc;
50 if (state->sp >= info->end || state->sp < info->begin)
53 if (!kallsyms_lookup_size_offset(pc, &size, &offset))
56 ip = (union loongarch_instruction *)(pc - offset);
57 ip_end = (union loongarch_instruction *)pc;
60 if (is_stack_alloc_ins(ip)) {
61 frame_size = (1 << 12) - ip->reg2i12_format.immediate;
76 if (is_ra_save_ins(ip)) {
77 frame_ra = ip->reg2i12_format.immediate;
80 if (is_branch_ins(ip))
87 state->sp = state->sp + frame_size;
96 state->pc = *(unsigned long *)(state->sp + frame_ra);
97 state->sp = state->sp + frame_size;
98 return !!__kernel_text_address(state->pc);
101 state->first = false;
102 if (state->pc == state->ra)
105 state->pc = state->ra;
107 return !!__kernel_text_address(state->ra);
110 void unwind_start(struct unwind_state *state, struct task_struct *task,
111 struct pt_regs *regs)
113 memset(state, 0, sizeof(*state));
114 state->type = UNWINDER_PROLOGUE;
117 state->sp = regs->regs[3];
118 state->pc = regs->csr_era;
119 state->ra = regs->regs[1];
120 if (!__kernel_text_address(state->pc))
121 state->type = UNWINDER_GUESS;
122 } else if (task && task != current) {
123 state->sp = thread_saved_fp(task);
124 state->pc = thread_saved_ra(task);
127 state->sp = (unsigned long)__builtin_frame_address(0);
128 state->pc = (unsigned long)__builtin_return_address(0);
135 get_stack_info(state->sp, state->task, &state->stack_info);
137 if (!unwind_done(state) && !__kernel_text_address(state->pc))
138 unwind_next_frame(state);
140 EXPORT_SYMBOL_GPL(unwind_start);
142 bool unwind_next_frame(struct unwind_state *state)
144 struct stack_info *info = &state->stack_info;
145 struct pt_regs *regs;
148 if (unwind_done(state))
152 switch (state->type) {
154 state->first = false;
155 if (unwind_by_guess(state))
159 case UNWINDER_PROLOGUE:
160 if (unwind_by_prologue(state))
163 if (info->type == STACK_TYPE_IRQ &&
164 info->end == state->sp) {
165 regs = (struct pt_regs *)info->next_sp;
168 if (user_mode(regs) || !__kernel_text_address(pc))
172 state->sp = regs->regs[3];
173 state->ra = regs->regs[1];
175 get_stack_info(state->sp, state->task, info);
181 state->sp = info->next_sp;
183 } while (!get_stack_info(state->sp, state->task, info));
187 EXPORT_SYMBOL_GPL(unwind_next_frame);