[PARISC] unwinder improvements

Add special-case handling for "handle_interruption" so that we can rewind
past the interruption. This is useful for seeing what caused a BUG() or
WARN_ON(); otherwise the unwind stops at the interruption.

Signed-off-by: Randolph Chung <tausq@debian.org>
Signed-off-by: Kyle McMartin <kyle@parisc-linux.org>

authored by Randolph Chung and committed by Kyle McMartin 05dc16d6 e036306a

+34 -7
+34 -7
arch/parisc/kernel/unwind.c
··· 16 17 #include <asm/uaccess.h> 18 #include <asm/assembly.h> 19 20 #include <asm/unwind.h> 21 ··· 201 return 0; 202 } 203 204 static void unwind_frame_regs(struct unwind_frame_info *info) 205 { 206 const struct unwind_table_entry *e; ··· 337 } 338 } 339 340 - info->prev_sp = info->sp - frame_size; 341 - if (e->Millicode) 342 - info->rp = info->r31; 343 - else if (rpoffset) 344 - info->rp = *(unsigned long *)(info->prev_sp - rpoffset); 345 - info->prev_ip = info->rp; 346 - info->rp = 0; 347 348 dbg("analyzing func @ %lx, setting prev_sp=%lx " 349 "prev_ip=%lx npc=%lx\n", info->ip, info->prev_sp,
··· 16 17 #include <asm/uaccess.h> 18 #include <asm/assembly.h> 19 + #include <asm/asm-offsets.h> 20 + #include <asm/ptrace.h> 21 22 #include <asm/unwind.h> 23 ··· 199 return 0; 200 } 201 202 + #ifdef CONFIG_64BIT 203 + #define get_func_addr(fptr) fptr[2] 204 + #else 205 + #define get_func_addr(fptr) fptr[0] 206 + #endif 207 + 208 + static int unwind_special(struct unwind_frame_info *info, unsigned long pc, int frame_size) 209 + { 210 + void handle_interruption(int, struct pt_regs *); 211 + static unsigned long *hi = (unsigned long)&handle_interruption; 212 + 213 + if (pc == get_func_addr(hi)) { 214 + struct pt_regs *regs = (struct pt_regs *)(info->sp - frame_size - PT_SZ_ALGN); 215 + dbg("Unwinding through handle_interruption()\n"); 216 + info->prev_sp = regs->gr[30]; 217 + info->prev_ip = regs->iaoq[0]; 218 + 219 + return 1; 220 + } 221 + 222 + return 0; 223 + } 224 + 225 static void unwind_frame_regs(struct unwind_frame_info *info) 226 { 227 const struct unwind_table_entry *e; ··· 312 } 313 } 314 315 + if (!unwind_special(info, e->region_start, frame_size)) { 316 + info->prev_sp = info->sp - frame_size; 317 + if (e->Millicode) 318 + info->rp = info->r31; 319 + else if (rpoffset) 320 + info->rp = *(unsigned long *)(info->prev_sp - rpoffset); 321 + info->prev_ip = info->rp; 322 + info->rp = 0; 323 + } 324 325 dbg("analyzing func @ %lx, setting prev_sp=%lx " 326 "prev_ip=%lx npc=%lx\n", info->ip, info->prev_sp,