|
@@ -75,7 +75,10 @@ find_unwind_entry(unsigned long addr)
|
|
|
if (addr >= kernel_unwind_table.start &&
|
|
|
addr <= kernel_unwind_table.end)
|
|
|
e = find_unwind_entry_in_table(&kernel_unwind_table, addr);
|
|
|
- else
|
|
|
+ else {
|
|
|
+ unsigned long flags;
|
|
|
+
|
|
|
+ spin_lock_irqsave(&unwind_lock, flags);
|
|
|
list_for_each_entry(table, &unwind_tables, list) {
|
|
|
if (addr >= table->start &&
|
|
|
addr <= table->end)
|
|
@@ -86,6 +89,8 @@ find_unwind_entry(unsigned long addr)
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
+ spin_unlock_irqrestore(&unwind_lock, flags);
|
|
|
+ }
|
|
|
|
|
|
return e;
|
|
|
}
|
|
@@ -303,18 +308,16 @@ static void unwind_frame_regs(struct unwind_frame_info *info)
|
|
|
|
|
|
insn = *(unsigned int *)npc;
|
|
|
|
|
|
- if ((insn & 0xffffc000) == 0x37de0000 ||
|
|
|
- (insn & 0xffe00000) == 0x6fc00000) {
|
|
|
+ if ((insn & 0xffffc001) == 0x37de0000 ||
|
|
|
+ (insn & 0xffe00001) == 0x6fc00000) {
|
|
|
/* ldo X(sp), sp, or stwm X,D(sp) */
|
|
|
- frame_size += (insn & 0x1 ? -1 << 13 : 0) |
|
|
|
- ((insn & 0x3fff) >> 1);
|
|
|
+ frame_size += (insn & 0x3fff) >> 1;
|
|
|
dbg("analyzing func @ %lx, insn=%08x @ "
|
|
|
"%lx, frame_size = %ld\n", info->ip,
|
|
|
insn, npc, frame_size);
|
|
|
- } else if ((insn & 0xffe00008) == 0x73c00008) {
|
|
|
+ } else if ((insn & 0xffe00009) == 0x73c00008) {
|
|
|
/* std,ma X,D(sp) */
|
|
|
- frame_size += (insn & 0x1 ? -1 << 13 : 0) |
|
|
|
- (((insn >> 4) & 0x3ff) << 3);
|
|
|
+ frame_size += ((insn >> 4) & 0x3ff) << 3;
|
|
|
dbg("analyzing func @ %lx, insn=%08x @ "
|
|
|
"%lx, frame_size = %ld\n", info->ip,
|
|
|
insn, npc, frame_size);
|
|
@@ -333,6 +336,9 @@ static void unwind_frame_regs(struct unwind_frame_info *info)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ if (frame_size > e->Total_frame_size << 3)
|
|
|
+ frame_size = e->Total_frame_size << 3;
|
|
|
+
|
|
|
if (!unwind_special(info, e->region_start, frame_size)) {
|
|
|
info->prev_sp = info->sp - frame_size;
|
|
|
if (e->Millicode)
|