1/* 2 * arch/sh64/kernel/unwind.c 3 * 4 * Copyright (C) 2004 Paul Mundt 5 * Copyright (C) 2004 Richard Curnow 6 * 7 * This file is subject to the terms and conditions of the GNU General Public 8 * License. See the file "COPYING" in the main directory of this archive 9 * for more details. 10 */ 11#include <linux/kallsyms.h> 12#include <linux/kernel.h> 13#include <linux/types.h> 14#include <linux/errno.h> 15#include <asm/page.h> 16#include <asm/ptrace.h> 17#include <asm/processor.h> 18#include <asm/io.h> 19 20static u8 regcache[63]; 21 22/* 23 * Finding the previous stack frame isn't horribly straightforward as it is 24 * on some other platforms. In the sh64 case, we don't have "linked" stack 25 * frames, so we need to do a bit of work to determine the previous frame, 26 * and in turn, the previous r14/r18 pair. 27 * 28 * There are generally a few cases which determine where we can find out 29 * the r14/r18 values. In the general case, this can be determined by poking 30 * around the prologue of the symbol PC is in (note that we absolutely must 31 * have frame pointer support as well as the kernel symbol table mapped, 32 * otherwise we can't even get this far). 33 * 34 * In other cases, such as the interrupt/exception path, we can poke around 35 * the sp/fp. 36 * 37 * Notably, this entire approach is somewhat error prone, and in the event 38 * that the previous frame cannot be determined, that's all we can do. 39 * Either way, this still leaves us with a more correct backtrace then what 40 * we would be able to come up with by walking the stack (which is garbage 41 * for anything beyond the first frame). 42 * -- PFM. 43 */ 44static int lookup_prev_stack_frame(unsigned long fp, unsigned long pc, 45 unsigned long *pprev_fp, unsigned long *pprev_pc, 46 struct pt_regs *regs) 47{ 48 const char *sym; 49 char namebuf[128]; 50 unsigned long offset; 51 unsigned long prologue = 0; 52 unsigned long fp_displacement = 0; 53 unsigned long fp_prev = 0; 54 unsigned long offset_r14 = 0, offset_r18 = 0; 55 int i, found_prologue_end = 0; 56 57 sym = kallsyms_lookup(pc, NULL, &offset, NULL, namebuf); 58 if (!sym) 59 return -EINVAL; 60 61 prologue = pc - offset; 62 if (!prologue) 63 return -EINVAL; 64 65 /* Validate fp, to avoid risk of dereferencing a bad pointer later. 66 Assume 128Mb since that's the amount of RAM on a Cayman. Modify 67 when there is an SH-5 board with more. */ 68 if ((fp < (unsigned long) phys_to_virt(__MEMORY_START)) || 69 (fp >= (unsigned long)(phys_to_virt(__MEMORY_START)) + 128*1024*1024) || 70 ((fp & 7) != 0)) { 71 return -EINVAL; 72 } 73 74 /* 75 * Depth to walk, depth is completely arbitrary. 76 */ 77 for (i = 0; i < 100; i++, prologue += sizeof(unsigned long)) { 78 unsigned long op; 79 u8 major, minor; 80 u8 src, dest, disp; 81 82 op = *(unsigned long *)prologue; 83 84 major = (op >> 26) & 0x3f; 85 src = (op >> 20) & 0x3f; 86 minor = (op >> 16) & 0xf; 87 disp = (op >> 10) & 0x3f; 88 dest = (op >> 4) & 0x3f; 89 90 /* 91 * Stack frame creation happens in a number of ways.. in the 92 * general case when the stack frame is less than 511 bytes, 93 * it's generally created by an addi or addi.l: 94 * 95 * addi/addi.l r15, -FRAME_SIZE, r15 96 * 97 * in the event that the frame size is bigger than this, it's 98 * typically created using a movi/sub pair as follows: 99 * 100 * movi FRAME_SIZE, rX 101 * sub r15, rX, r15 102 */ 103 104 switch (major) { 105 case (0x00 >> 2): 106 switch (minor) { 107 case 0x8: /* add.l */ 108 case 0x9: /* add */ 109 /* Look for r15, r63, r14 */ 110 if (src == 15 && disp == 63 && dest == 14) 111 found_prologue_end = 1; 112 113 break; 114 case 0xa: /* sub.l */ 115 case 0xb: /* sub */ 116 if (src != 15 || dest != 15) 117 continue; 118 119 fp_displacement -= regcache[disp]; 120 fp_prev = fp - fp_displacement; 121 break; 122 } 123 break; 124 case (0xa8 >> 2): /* st.l */ 125 if (src != 15) 126 continue; 127 128 switch (dest) { 129 case 14: 130 if (offset_r14 || fp_displacement == 0) 131 continue; 132 133 offset_r14 = (u64)(((((s64)op >> 10) & 0x3ff) << 54) >> 54); 134 offset_r14 *= sizeof(unsigned long); 135 offset_r14 += fp_displacement; 136 break; 137 case 18: 138 if (offset_r18 || fp_displacement == 0) 139 continue; 140 141 offset_r18 = (u64)(((((s64)op >> 10) & 0x3ff) << 54) >> 54); 142 offset_r18 *= sizeof(unsigned long); 143 offset_r18 += fp_displacement; 144 break; 145 } 146 147 break; 148 case (0xcc >> 2): /* movi */ 149 if (dest >= 63) { 150 printk(KERN_NOTICE "%s: Invalid dest reg %d " 151 "specified in movi handler. Failed " 152 "opcode was 0x%lx: ", __FUNCTION__, 153 dest, op); 154 155 continue; 156 } 157 158 /* Sign extend */ 159 regcache[dest] = 160 ((((s64)(u64)op >> 10) & 0xffff) << 54) >> 54; 161 break; 162 case (0xd0 >> 2): /* addi */ 163 case (0xd4 >> 2): /* addi.l */ 164 /* Look for r15, -FRAME_SIZE, r15 */ 165 if (src != 15 || dest != 15) 166 continue; 167 168 /* Sign extended frame size.. */ 169 fp_displacement += 170 (u64)(((((s64)op >> 10) & 0x3ff) << 54) >> 54); 171 fp_prev = fp - fp_displacement; 172 break; 173 } 174 175 if (found_prologue_end && offset_r14 && (offset_r18 || *pprev_pc) && fp_prev) 176 break; 177 } 178 179 if (offset_r14 == 0 || fp_prev == 0) { 180 if (!offset_r14) 181 pr_debug("Unable to find r14 offset\n"); 182 if (!fp_prev) 183 pr_debug("Unable to find previous fp\n"); 184 185 return -EINVAL; 186 } 187 188 /* For innermost leaf function, there might not be a offset_r18 */ 189 if (!*pprev_pc && (offset_r18 == 0)) 190 return -EINVAL; 191 192 *pprev_fp = *(unsigned long *)(fp_prev + offset_r14); 193 194 if (offset_r18) 195 *pprev_pc = *(unsigned long *)(fp_prev + offset_r18); 196 197 *pprev_pc &= ~1; 198 199 return 0; 200} 201 202/* Don't put this on the stack since we'll want to call sh64_unwind 203 * when we're close to underflowing the stack anyway. */ 204static struct pt_regs here_regs; 205 206extern const char syscall_ret; 207extern const char ret_from_syscall; 208extern const char ret_from_exception; 209extern const char ret_from_irq; 210 211static void sh64_unwind_inner(struct pt_regs *regs); 212 213static void unwind_nested (unsigned long pc, unsigned long fp) 214{ 215 if ((fp >= __MEMORY_START) && 216 ((fp & 7) == 0)) { 217 sh64_unwind_inner((struct pt_regs *) fp); 218 } 219} 220 221static void sh64_unwind_inner(struct pt_regs *regs) 222{ 223 unsigned long pc, fp; 224 int ofs = 0; 225 int first_pass; 226 227 pc = regs->pc & ~1; 228 fp = regs->regs[14]; 229 230 first_pass = 1; 231 for (;;) { 232 int cond; 233 unsigned long next_fp, next_pc; 234 235 if (pc == ((unsigned long) &syscall_ret & ~1)) { 236 printk("SYSCALL\n"); 237 unwind_nested(pc,fp); 238 return; 239 } 240 241 if (pc == ((unsigned long) &ret_from_syscall & ~1)) { 242 printk("SYSCALL (PREEMPTED)\n"); 243 unwind_nested(pc,fp); 244 return; 245 } 246 247 /* In this case, the PC is discovered by lookup_prev_stack_frame but 248 it has 4 taken off it to look like the 'caller' */ 249 if (pc == ((unsigned long) &ret_from_exception & ~1)) { 250 printk("EXCEPTION\n"); 251 unwind_nested(pc,fp); 252 return; 253 } 254 255 if (pc == ((unsigned long) &ret_from_irq & ~1)) { 256 printk("IRQ\n"); 257 unwind_nested(pc,fp); 258 return; 259 } 260 261 cond = ((pc >= __MEMORY_START) && (fp >= __MEMORY_START) && 262 ((pc & 3) == 0) && ((fp & 7) == 0)); 263 264 pc -= ofs; 265 266 printk("[<%08lx>] ", pc); 267 print_symbol("%s\n", pc); 268 269 if (first_pass) { 270 /* If the innermost frame is a leaf function, it's 271 * possible that r18 is never saved out to the stack. 272 */ 273 next_pc = regs->regs[18]; 274 } else { 275 next_pc = 0; 276 } 277 278 if (lookup_prev_stack_frame(fp, pc, &next_fp, &next_pc, regs) == 0) { 279 ofs = sizeof(unsigned long); 280 pc = next_pc & ~1; 281 fp = next_fp; 282 } else { 283 printk("Unable to lookup previous stack frame\n"); 284 break; 285 } 286 first_pass = 0; 287 } 288 289 printk("\n"); 290 291} 292 293void sh64_unwind(struct pt_regs *regs) 294{ 295 if (!regs) { 296 /* 297 * Fetch current regs if we have no other saved state to back 298 * trace from. 299 */ 300 regs = &here_regs; 301 302 __asm__ __volatile__ ("ori r14, 0, %0" : "=r" (regs->regs[14])); 303 __asm__ __volatile__ ("ori r15, 0, %0" : "=r" (regs->regs[15])); 304 __asm__ __volatile__ ("ori r18, 0, %0" : "=r" (regs->regs[18])); 305 306 __asm__ __volatile__ ("gettr tr0, %0" : "=r" (regs->tregs[0])); 307 __asm__ __volatile__ ("gettr tr1, %0" : "=r" (regs->tregs[1])); 308 __asm__ __volatile__ ("gettr tr2, %0" : "=r" (regs->tregs[2])); 309 __asm__ __volatile__ ("gettr tr3, %0" : "=r" (regs->tregs[3])); 310 __asm__ __volatile__ ("gettr tr4, %0" : "=r" (regs->tregs[4])); 311 __asm__ __volatile__ ("gettr tr5, %0" : "=r" (regs->tregs[5])); 312 __asm__ __volatile__ ("gettr tr6, %0" : "=r" (regs->tregs[6])); 313 __asm__ __volatile__ ("gettr tr7, %0" : "=r" (regs->tregs[7])); 314 315 __asm__ __volatile__ ( 316 "pta 0f, tr0\n\t" 317 "blink tr0, %0\n\t" 318 "0: nop" 319 : "=r" (regs->pc) 320 ); 321 } 322 323 printk("\nCall Trace:\n"); 324 sh64_unwind_inner(regs); 325} 326