unwind_prologue.c (5bb8d34449c4a2eb94d657b992170afafac274f9) unwind_prologue.c (c5ac25e0d78a6f63446b8fef4d8630ccd7a2663d)
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (C) 2022 Loongson Technology Corporation Limited
4 */
5#include <linux/ftrace.h>
6#include <linux/kallsyms.h>
7
8#include <asm/inst.h>

--- 5 unchanged lines hidden (view full) ---

14#ifdef CONFIG_DYNAMIC_FTRACE
15 static unsigned long ftrace = (unsigned long)ftrace_call + 4;
16
17 if (state->pc == ftrace)
18 state->is_ftrace = true;
19#endif
20}
21
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (C) 2022 Loongson Technology Corporation Limited
4 */
5#include <linux/ftrace.h>
6#include <linux/kallsyms.h>
7
8#include <asm/inst.h>

--- 5 unchanged lines hidden (view full) ---

14#ifdef CONFIG_DYNAMIC_FTRACE
15 static unsigned long ftrace = (unsigned long)ftrace_call + 4;
16
17 if (state->pc == ftrace)
18 state->is_ftrace = true;
19#endif
20}
21
22unsigned long unwind_get_return_address(struct unwind_state *state)
23{
24 if (unwind_done(state))
25 return 0;
26
27 return state->pc;
28}
29EXPORT_SYMBOL_GPL(unwind_get_return_address);
30
31static bool unwind_by_guess(struct unwind_state *state)
32{
33 struct stack_info *info = &state->stack_info;
34 unsigned long addr;
35
36 for (state->sp += sizeof(unsigned long);
37 state->sp < info->end;
38 state->sp += sizeof(unsigned long)) {
39 addr = *(unsigned long *)(state->sp);
40 state->pc = unwind_graph_addr(state, addr, state->sp + 8);
41 if (__kernel_text_address(state->pc))
42 return true;
43 }
44
45 return false;
46}
47
22/*
23 * LoongArch function prologue is like follows,
24 * [instructions not use stack var]
25 * addi.d sp, sp, -imm
26 * st.d xx, sp, offset <- save callee saved regs and
27 * st.d yy, sp, offset save ra if function is nest.
28 * [others instructions]
29 */
48static bool unwind_by_prologue(struct unwind_state *state)
49{
50 long frame_ra = -1;
51 unsigned long frame_size = 0;
52 unsigned long size, offset, pc;
53 struct pt_regs *regs;
54 struct stack_info *info = &state->stack_info;
55 union loongarch_instruction *ip, *ip_end;

--- 30 unchanged lines hidden (view full) ---

86 if (is_stack_alloc_ins(ip)) {
87 frame_size = (1 << 12) - ip->reg2i12_format.immediate;
88 ip++;
89 break;
90 }
91 ip++;
92 }
93
30static bool unwind_by_prologue(struct unwind_state *state)
31{
32 long frame_ra = -1;
33 unsigned long frame_size = 0;
34 unsigned long size, offset, pc;
35 struct pt_regs *regs;
36 struct stack_info *info = &state->stack_info;
37 union loongarch_instruction *ip, *ip_end;

--- 30 unchanged lines hidden (view full) ---

68 if (is_stack_alloc_ins(ip)) {
69 frame_size = (1 << 12) - ip->reg2i12_format.immediate;
70 ip++;
71 break;
72 }
73 ip++;
74 }
75
76 /*
77 * Can't find stack alloc action, PC may be in a leaf function. Only the
78 * first being true is reasonable, otherwise indicate analysis is broken.
79 */
94 if (!frame_size) {
95 if (state->first)
96 goto first;
97
98 return false;
99 }
100
101 while (ip < ip_end) {
102 if (is_ra_save_ins(ip)) {
103 frame_ra = ip->reg2i12_format.immediate;
104 break;
105 }
106 if (is_branch_ins(ip))
107 break;
108 ip++;
109 }
110
80 if (!frame_size) {
81 if (state->first)
82 goto first;
83
84 return false;
85 }
86
87 while (ip < ip_end) {
88 if (is_ra_save_ins(ip)) {
89 frame_ra = ip->reg2i12_format.immediate;
90 break;
91 }
92 if (is_branch_ins(ip))
93 break;
94 ip++;
95 }
96
97 /* Can't find save $ra action, PC may be in a leaf function, too. */
111 if (frame_ra < 0) {
112 if (state->first) {
113 state->sp = state->sp + frame_size;
114 goto first;
115 }
116 return false;
117 }
118
98 if (frame_ra < 0) {
99 if (state->first) {
100 state->sp = state->sp + frame_size;
101 goto first;
102 }
103 return false;
104 }
105
119 if (state->first)
120 state->first = false;
121
122 state->pc = *(unsigned long *)(state->sp + frame_ra);
123 state->sp = state->sp + frame_size;
124 goto out;
125
126first:
106 state->pc = *(unsigned long *)(state->sp + frame_ra);
107 state->sp = state->sp + frame_size;
108 goto out;
109
110first:
127 state->first = false;
128 if (state->pc == state->ra)
129 return false;
130
131 state->pc = state->ra;
132
133out:
111 state->pc = state->ra;
112
113out:
114 state->first = false;
134 unwind_state_fixup(state);
135 return !!__kernel_text_address(state->pc);
136}
137
115 unwind_state_fixup(state);
116 return !!__kernel_text_address(state->pc);
117}
118
138void unwind_start(struct unwind_state *state, struct task_struct *task,
139 struct pt_regs *regs)
119static bool next_frame(struct unwind_state *state)
140{
120{
141 memset(state, 0, sizeof(*state));
142 state->type = UNWINDER_PROLOGUE;
143
144 if (regs) {
145 state->sp = regs->regs[3];
146 state->pc = regs->csr_era;
147 state->ra = regs->regs[1];
148 if (!__kernel_text_address(state->pc))
149 state->type = UNWINDER_GUESS;
150 } else if (task && task != current) {
151 state->sp = thread_saved_fp(task);
152 state->pc = thread_saved_ra(task);
153 state->ra = 0;
154 } else {
155 state->sp = (unsigned long)__builtin_frame_address(0);
156 state->pc = (unsigned long)__builtin_return_address(0);
157 state->ra = 0;
158 }
159
160 state->task = task;
161 state->first = true;
162 state->pc = unwind_graph_addr(state, state->pc, state->sp);
163 get_stack_info(state->sp, state->task, &state->stack_info);
164
165 if (!unwind_done(state) && !__kernel_text_address(state->pc))
166 unwind_next_frame(state);
167}
168EXPORT_SYMBOL_GPL(unwind_start);
169
170bool unwind_next_frame(struct unwind_state *state)
171{
172 struct stack_info *info = &state->stack_info;
173 struct pt_regs *regs;
174 unsigned long pc;
121 unsigned long pc;
122 struct pt_regs *regs;
123 struct stack_info *info = &state->stack_info;
175
176 if (unwind_done(state))
177 return false;
178
179 do {
124
125 if (unwind_done(state))
126 return false;
127
128 do {
180 switch (state->type) {
181 case UNWINDER_GUESS:
182 state->first = false;
183 if (unwind_by_guess(state))
184 return true;
185 break;
129 if (unwind_by_prologue(state)) {
130 state->pc = unwind_graph_addr(state, state->pc, state->sp);
131 return true;
132 }
186
133
187 case UNWINDER_PROLOGUE:
188 if (unwind_by_prologue(state)) {
189 state->pc = unwind_graph_addr(state, state->pc, state->sp);
190 return true;
191 }
134 if (info->type == STACK_TYPE_IRQ && info->end == state->sp) {
135 regs = (struct pt_regs *)info->next_sp;
136 pc = regs->csr_era;
192
137
193 if (info->type == STACK_TYPE_IRQ &&
194 info->end == state->sp) {
195 regs = (struct pt_regs *)info->next_sp;
196 pc = regs->csr_era;
138 if (user_mode(regs) || !__kernel_text_address(pc))
139 return false;
197
140
198 if (user_mode(regs) || !__kernel_text_address(pc))
199 return false;
141 state->first = true;
142 state->pc = pc;
143 state->ra = regs->regs[1];
144 state->sp = regs->regs[3];
145 get_stack_info(state->sp, state->task, info);
200
146
201 state->first = true;
202 state->ra = regs->regs[1];
203 state->sp = regs->regs[3];
204 state->pc = pc;
205 get_stack_info(state->sp, state->task, info);
206
207 return true;
208 }
147 return true;
209 }
210
211 state->sp = info->next_sp;
212
213 } while (!get_stack_info(state->sp, state->task, info));
214
215 return false;
216}
148 }
149
150 state->sp = info->next_sp;
151
152 } while (!get_stack_info(state->sp, state->task, info));
153
154 return false;
155}
156
157unsigned long unwind_get_return_address(struct unwind_state *state)
158{
159 return __unwind_get_return_address(state);
160}
161EXPORT_SYMBOL_GPL(unwind_get_return_address);
162
163void unwind_start(struct unwind_state *state, struct task_struct *task,
164 struct pt_regs *regs)
165{
166 __unwind_start(state, task, regs);
167 state->type = UNWINDER_PROLOGUE;
168 state->first = true;
169
170 /*
171 * The current PC is not kernel text address, we cannot find its
172 * relative symbol. Thus, prologue analysis will be broken. Luckily,
173 * we can use the default_next_frame().
174 */
175 if (!__kernel_text_address(state->pc)) {
176 state->type = UNWINDER_GUESS;
177 if (!unwind_done(state))
178 unwind_next_frame(state);
179 }
180}
181EXPORT_SYMBOL_GPL(unwind_start);
182
183bool unwind_next_frame(struct unwind_state *state)
184{
185 return state->type == UNWINDER_PROLOGUE ?
186 next_frame(state) : default_next_frame(state);
187}
217EXPORT_SYMBOL_GPL(unwind_next_frame);
188EXPORT_SYMBOL_GPL(unwind_next_frame);