diff options
| -rw-r--r-- | arch/parisc/kernel/unwind.c | 22 |
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) |
