compat user mode prstatus already just works, almost. This missing pieces are that pt_regs->sp and pt_regs->fp are not in their usual locations. We need to pull them out of their architecturally mapped general purpose registers. --- arm64.c | 42 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 8 deletions(-) diff --git a/arm64.c b/arm64.c index 183e768498fe8..3a82d20cdd465 100644 --- a/arm64.c +++ b/arm64.c @@ -993,6 +993,25 @@ arm64_stackframe_init(void) #define PSR_MODE_EL3h 0x0000000d #define PSR_MODE_MASK 0x0000000f +/* Architecturally defined mapping between AArch32 and AArch64 registers */ +#define compat_usr(x) regs[(x)] +#define compat_fp regs[11] +#define compat_sp regs[13] +#define compat_lr regs[14] + +#define user_mode(ptregs) \ + (((ptregs)->pstate & PSR_MODE_MASK) == PSR_MODE_EL0t) + +#define compat_user_mode(ptregs) \ + (((ptregs)->pstate & (PSR_MODE32_BIT | PSR_MODE_MASK)) == \ + (PSR_MODE32_BIT | PSR_MODE_EL0t)) + +#define user_stack_pointer(ptregs) \ + (!compat_user_mode(ptregs) ? (ptregs)->sp : (ptregs)->compat_sp) + +#define user_frame_pointer(ptregs) \ + (!compat_user_mode(ptregs) ? (ptregs)->regs[29] : (ptregs)->compat_fp) + static int arm64_is_kernel_exception_frame(struct bt_info *bt, ulong stkptr) { @@ -1340,21 +1359,28 @@ arm64_get_dumpfile_stackframe(struct bt_info *bt, struct arm64_stackframe *frame struct machine_specific *ms = machdep->machspec; struct arm64_pt_regs *ptregs; - if (!ms->panic_task_regs || - (!ms->panic_task_regs[bt->tc->processor].sp && - !ms->panic_task_regs[bt->tc->processor].pc)) { + if (!ms->panic_task_regs || !ms->panic_task_regs[bt->tc->processor].pc) { bt->flags |= BT_REGS_NOT_FOUND; return FALSE; } ptregs = &ms->panic_task_regs[bt->tc->processor]; - frame->sp = ptregs->sp; frame->pc = ptregs->pc; - frame->fp = ptregs->regs[29]; - - if (!is_kernel_text(frame->pc) && - in_user_stack(bt->tc->task, frame->sp)) + if (user_mode(ptregs)) { + frame->sp = user_stack_pointer(ptregs); + frame->fp = user_frame_pointer(ptregs); + if (is_kernel_text(frame->pc) || + !in_user_stack(bt->tc->task, frame->sp)) { + error(WARNING, "Corrupt prstatus? pstate=0x%lx, but no user frame found\n", + ptregs->pstate); + bt->flags |= BT_REGS_NOT_FOUND; + return FALSE; + } bt->flags |= BT_USER_SPACE; + } else { + frame->sp = ptregs->sp; + frame->fp = ptregs->regs[29]; + } if (arm64_in_kdump_text(bt, frame)) bt->flags |= BT_KDUMP_ADJUST; -- 1.8.3.1 -- Crash-utility mailing list Crash-utility@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/crash-utility