aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/parisc/kernel/unwind.c22
1 files changed, 14 insertions, 8 deletions
diff --git a/arch/parisc/kernel/unwind.c b/arch/parisc/kernel/unwind.c
index ddd988b267a9..e278a87f43cc 100644
--- a/arch/parisc/kernel/unwind.c
+++ b/arch/parisc/kernel/unwind.c
@@ -75,7 +75,10 @@ find_unwind_entry(unsigned long addr)
75 if (addr >= kernel_unwind_table.start && 75 if (addr >= kernel_unwind_table.start &&
76 addr <= kernel_unwind_table.end) 76 addr <= kernel_unwind_table.end)
77 e = find_unwind_entry_in_table(&kernel_unwind_table, addr); 77 e = find_unwind_entry_in_table(&kernel_unwind_table, addr);
78 else 78 else {
79 unsigned long flags;
80
81 spin_lock_irqsave(&unwind_lock, flags);
79 list_for_each_entry(table, &unwind_tables, list) { 82 list_for_each_entry(table, &unwind_tables, list) {
80 if (addr >= table->start && 83 if (addr >= table->start &&
81 addr <= table->end) 84 addr <= table->end)
@@ -86,6 +89,8 @@ find_unwind_entry(unsigned long addr)
86 break; 89 break;
87 } 90 }
88 } 91 }
92 spin_unlock_irqrestore(&unwind_lock, flags);
93 }
89 94
90 return e; 95 return e;
91} 96}
@@ -303,18 +308,16 @@ static void unwind_frame_regs(struct unwind_frame_info *info)
303 308
304 insn = *(unsigned int *)npc; 309 insn = *(unsigned int *)npc;
305 310
306 if ((insn & 0xffffc000) == 0x37de0000 || 311 if ((insn & 0xffffc001) == 0x37de0000 ||
307 (insn & 0xffe00000) == 0x6fc00000) { 312 (insn & 0xffe00001) == 0x6fc00000) {
308 /* ldo X(sp), sp, or stwm X,D(sp) */ 313 /* ldo X(sp), sp, or stwm X,D(sp) */
309 frame_size += (insn & 0x1 ? -1 << 13 : 0) | 314 frame_size += (insn & 0x3fff) >> 1;
310 ((insn & 0x3fff) >> 1);
311 dbg("analyzing func @ %lx, insn=%08x @ " 315 dbg("analyzing func @ %lx, insn=%08x @ "
312 "%lx, frame_size = %ld\n", info->ip, 316 "%lx, frame_size = %ld\n", info->ip,
313 insn, npc, frame_size); 317 insn, npc, frame_size);
314 } else if ((insn & 0xffe00008) == 0x73c00008) { 318 } else if ((insn & 0xffe00009) == 0x73c00008) {
315 /* std,ma X,D(sp) */ 319 /* std,ma X,D(sp) */
316 frame_size += (insn & 0x1 ? -1 << 13 : 0) | 320 frame_size += ((insn >> 4) & 0x3ff) << 3;
317 (((insn >> 4) & 0x3ff) << 3);
318 dbg("analyzing func @ %lx, insn=%08x @ " 321 dbg("analyzing func @ %lx, insn=%08x @ "
319 "%lx, frame_size = %ld\n", info->ip, 322 "%lx, frame_size = %ld\n", info->ip,
320 insn, npc, frame_size); 323 insn, npc, frame_size);
@@ -333,6 +336,9 @@ static void unwind_frame_regs(struct unwind_frame_info *info)
333 } 336 }
334 } 337 }
335 338
339 if (frame_size > e->Total_frame_size << 3)
340 frame_size = e->Total_frame_size << 3;
341
336 if (!unwind_special(info, e->region_start, frame_size)) { 342 if (!unwind_special(info, e->region_start, frame_size)) {
337 info->prev_sp = info->sp - frame_size; 343 info->prev_sp = info->sp - frame_size;
338 if (e->Millicode) 344 if (e->Millicode)