WIP detect arm mode from return address instead of PSR_T_BIT Signed-off-by: Richard Weinberger <richard@nod.at>
diff --git a/arch/arm/kernel/unwind.c b/arch/arm/kernel/unwind.c index aad02f1..4ce6828 100644 --- a/arch/arm/kernel/unwind.c +++ b/arch/arm/kernel/unwind.c
@@ -85,9 +85,9 @@ extern const struct unwind_idx __stop_unwind_idx[]; static DEFINE_RAW_SPINLOCK(unwind_lock); static LIST_HEAD(unwind_tables); -static bool is_branch_link(unsigned long pc, u32 cpsr) +static bool is_branch_link(unsigned long pc, bool thumb) { - if (cpsr & PSR_T_BIT) { + if (thumb) { u16 hw1, hw2; if (get_kernel_nofault(hw1, (u16 *)pc)) @@ -401,7 +401,7 @@ static int unwind_exec_insn(struct unwind_ctrl_block *ctrl) goto error; } else if (insn == 0xb0) { if (ctrl->vrs[PC] == 0) - ctrl->vrs[PC] = ctrl->vrs[LR]; + ctrl->vrs[PC] = ctrl->vrs[LR] & 0xfffffffe; /* no further processing */ ctrl->entries = 0; } else if (insn == 0xb1) { @@ -459,7 +459,7 @@ int unwind_frame(struct stackframe *frame) * PC+immediate LDR, and so they don't affect * the state of the stack or the register file */ - frame->pc = frame->lr; + frame->pc = frame->lr & 0xfffffffe; return URC_OK; } pr_warn("unwind: Index not found %08lx\n", frame->pc); @@ -486,7 +486,7 @@ int unwind_frame(struct stackframe *frame) */ if (frame->pc == frame->lr) return -URC_FAILURE; - frame->pc = frame->lr; + frame->pc = frame->lr & 0xfffffffe; return URC_OK; } else if ((idx->insn & 0x80000000) == 0) /* prel31 to the unwind table */ @@ -537,7 +537,7 @@ int unwind_frame(struct stackframe *frame) } if (ctrl.vrs[PC] == 0) - ctrl.vrs[PC] = ctrl.vrs[LR]; + ctrl.vrs[PC] = ctrl.vrs[LR] & 0xfffffffe; /* check for infinite loop */ if (frame->pc == ctrl.vrs[PC] && frame->sp == ctrl.vrs[SP]) @@ -556,7 +556,6 @@ void unwind_backtrace(struct pt_regs *regs, struct task_struct *tsk, const char *loglvl) { struct stackframe frame; - u32 cpsr; printk("%sCall trace: ", loglvl); @@ -565,15 +564,11 @@ void unwind_backtrace(struct pt_regs *regs, struct task_struct *tsk, if (!tsk) tsk = current; - /* Get the current CPSR */ - asm("mrs %0, cpsr" : "=r" (cpsr)); - if (regs) { arm_get_current_stackframe(regs, &frame); /* PC might be corrupted, use LR in that case. */ if (!kernel_text_address(regs->ARM_pc)) - frame.pc = regs->ARM_lr; - cpsr = regs->ARM_cpsr; + frame.pc = regs->ARM_lr & 0xfffffffe; } else if (tsk == current) { frame.fp = (unsigned long)__builtin_frame_address(0); frame.sp = current_stack_pointer; @@ -614,7 +609,7 @@ void unwind_backtrace(struct pt_regs *regs, struct task_struct *tsk, * the instruction is a BL. */ from = frame.pc - 4; - if (is_branch_link(from, cpsr)) + if (is_branch_link(from, frame.lr & 0x1)) frame.pc = from; dump_backtrace_entry(where, frame.pc, frame.sp - 4, loglvl);