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> 9 #include <asm/ptrace.h> 10 #include <asm/unwind.h> 11 12 static inline void unwind_state_fixup(struct unwind_state *state) 13 { 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 22 unsigned long unwind_get_return_address(struct unwind_state *state) 23 { 24 25 if (unwind_done(state)) 26 return 0; 27 else if (state->type) 28 return state->pc; 29 else if (state->first) 30 return state->pc; 31 32 return *(unsigned long *)(state->sp); 33 34 } 35 EXPORT_SYMBOL_GPL(unwind_get_return_address); 36 37 static bool unwind_by_guess(struct unwind_state *state) 38 { 39 struct stack_info *info = &state->stack_info; 40 unsigned long addr; 41 42 for (state->sp += sizeof(unsigned long); 43 state->sp < info->end; 44 state->sp += sizeof(unsigned long)) { 45 addr = *(unsigned long *)(state->sp); 46 state->pc = ftrace_graph_ret_addr(state->task, &state->graph_idx, 47 addr, (unsigned long *)(state->sp - GRAPH_FAKE_OFFSET)); 48 if (__kernel_text_address(addr)) 49 return true; 50 } 51 52 return false; 53 } 54 55 static bool unwind_by_prologue(struct unwind_state *state) 56 { 57 long frame_ra = -1; 58 unsigned long frame_size = 0; 59 unsigned long size, offset, pc; 60 struct pt_regs *regs; 61 struct stack_info *info = &state->stack_info; 62 union loongarch_instruction *ip, *ip_end; 63 64 if (state->sp >= info->end || state->sp < info->begin) 65 return false; 66 67 if (state->is_ftrace) { 68 /* 69 * As we meet ftrace_regs_entry, reset first flag like first doing 70 * tracing. Prologue analysis will stop soon because PC is at entry. 71 */ 72 regs = (struct pt_regs *)state->sp; 73 state->first = true; 74 state->is_ftrace = false; 75 state->pc = regs->csr_era; 76 state->ra = regs->regs[1]; 77 state->sp = regs->regs[3]; 78 return true; 79 } 80 81 /* 82 * When first is not set, the PC is a return address in the previous frame. 83 * We need to adjust its value in case overflow to the next symbol. 84 */ 85 pc = state->pc - (state->first ? 0 : LOONGARCH_INSN_SIZE); 86 if (!kallsyms_lookup_size_offset(pc, &size, &offset)) 87 return false; 88 89 ip = (union loongarch_instruction *)(pc - offset); 90 ip_end = (union loongarch_instruction *)pc; 91 92 while (ip < ip_end) { 93 if (is_stack_alloc_ins(ip)) { 94 frame_size = (1 << 12) - ip->reg2i12_format.immediate; 95 ip++; 96 break; 97 } 98 ip++; 99 } 100 101 if (!frame_size) { 102 if (state->first) 103 goto first; 104 105 return false; 106 } 107 108 while (ip < ip_end) { 109 if (is_ra_save_ins(ip)) { 110 frame_ra = ip->reg2i12_format.immediate; 111 break; 112 } 113 if (is_branch_ins(ip)) 114 break; 115 ip++; 116 } 117 118 if (frame_ra < 0) { 119 if (state->first) { 120 state->sp = state->sp + frame_size; 121 goto first; 122 } 123 return false; 124 } 125 126 if (state->first) 127 state->first = false; 128 129 state->pc = *(unsigned long *)(state->sp + frame_ra); 130 state->sp = state->sp + frame_size; 131 goto out; 132 133 first: 134 state->first = false; 135 if (state->pc == state->ra) 136 return false; 137 138 state->pc = state->ra; 139 140 out: 141 unwind_state_fixup(state); 142 return !!__kernel_text_address(state->pc); 143 } 144 145 void unwind_start(struct unwind_state *state, struct task_struct *task, 146 struct pt_regs *regs) 147 { 148 memset(state, 0, sizeof(*state)); 149 state->type = UNWINDER_PROLOGUE; 150 151 if (regs) { 152 state->sp = regs->regs[3]; 153 state->pc = regs->csr_era; 154 state->ra = regs->regs[1]; 155 if (!__kernel_text_address(state->pc)) 156 state->type = UNWINDER_GUESS; 157 } else if (task && task != current) { 158 state->sp = thread_saved_fp(task); 159 state->pc = thread_saved_ra(task); 160 state->ra = 0; 161 } else { 162 state->sp = (unsigned long)__builtin_frame_address(0); 163 state->pc = (unsigned long)__builtin_return_address(0); 164 state->ra = 0; 165 } 166 167 state->task = task; 168 state->first = true; 169 170 get_stack_info(state->sp, state->task, &state->stack_info); 171 172 if (!unwind_done(state) && !__kernel_text_address(state->pc)) 173 unwind_next_frame(state); 174 } 175 EXPORT_SYMBOL_GPL(unwind_start); 176 177 bool unwind_next_frame(struct unwind_state *state) 178 { 179 struct stack_info *info = &state->stack_info; 180 struct pt_regs *regs; 181 unsigned long pc; 182 183 if (unwind_done(state)) 184 return false; 185 186 do { 187 switch (state->type) { 188 case UNWINDER_GUESS: 189 state->first = false; 190 if (unwind_by_guess(state)) 191 return true; 192 break; 193 194 case UNWINDER_PROLOGUE: 195 if (unwind_by_prologue(state)) { 196 state->pc = ftrace_graph_ret_addr(state->task, &state->graph_idx, 197 state->pc, (unsigned long *)(state->sp - GRAPH_FAKE_OFFSET)); 198 return true; 199 } 200 201 if (info->type == STACK_TYPE_IRQ && 202 info->end == state->sp) { 203 regs = (struct pt_regs *)info->next_sp; 204 pc = regs->csr_era; 205 206 if (user_mode(regs) || !__kernel_text_address(pc)) 207 return false; 208 209 state->first = true; 210 state->ra = regs->regs[1]; 211 state->sp = regs->regs[3]; 212 state->pc = ftrace_graph_ret_addr(state->task, &state->graph_idx, 213 pc, (unsigned long *)(state->sp - GRAPH_FAKE_OFFSET)); 214 get_stack_info(state->sp, state->task, info); 215 216 return true; 217 } 218 } 219 220 state->sp = info->next_sp; 221 222 } while (!get_stack_info(state->sp, state->task, info)); 223 224 return false; 225 } 226 EXPORT_SYMBOL_GPL(unwind_next_frame); 227