Signed-off-by: AKASHI Takahiro <takahiro.akashi@xxxxxxxxxx> --- arm64.c | 504 +++++++++++++++++++++++++++++++++++++++++++--------------------- defs.h | 6 + 2 files changed, 344 insertions(+), 166 deletions(-) diff --git a/arm64.c b/arm64.c index 06676d1..4f85772 100644 --- a/arm64.c +++ b/arm64.c @@ -42,18 +42,18 @@ static void arm64_irq_stack_init(void); static void arm64_stackframe_init(void); static int arm64_eframe_search(struct bt_info *); static int arm64_is_kernel_exception_frame(struct bt_info *, ulong); -static int arm64_in_exception_text(ulong); +static int arm64_in_exp_entry(ulong); static void arm64_back_trace_cmd(struct bt_info *); static void arm64_print_text_symbols(struct bt_info *, struct arm64_stackframe *, FILE *); static int arm64_print_stackframe_entry(struct bt_info *, int, struct arm64_stackframe *, FILE *); -static void arm64_display_full_frame(struct bt_info *, ulong); -static int arm64_unwind_frame(struct bt_info *, struct arm64_stackframe *); +static void arm64_display_full_frame(struct bt_info *, struct arm64_stackframe *, struct arm64_stackframe *); +static int arm64_unwind_frame(struct bt_info *, struct arm64_stackframe *, FILE *); static int arm64_get_dumpfile_stackframe(struct bt_info *, struct arm64_stackframe *); static int arm64_in_kdump_text(struct bt_info *, struct arm64_stackframe *); static int arm64_in_kdump_text_on_irq_stack(struct bt_info *); -static int arm64_switch_stack(struct bt_info *, struct arm64_stackframe *, FILE *); static int arm64_get_stackframe(struct bt_info *, struct arm64_stackframe *); static void arm64_get_stack_frame(struct bt_info *, ulong *, ulong *); +static void arm64_gen_hidden_frame(struct bt_info *bt, ulong, struct arm64_stackframe *); static void arm64_print_exception_frame(struct bt_info *, ulong, int, FILE *); static void arm64_do_bt_reference_check(struct bt_info *, ulong, char *); static int arm64_translate_pte(ulong, void *, ulonglong); @@ -580,6 +580,10 @@ arm64_dump_machdep_table(ulong arg) fprintf(fp, " __exception_text_end: %lx\n", ms->__exception_text_end); fprintf(fp, " __irqentry_text_start: %lx\n", ms->__irqentry_text_start); fprintf(fp, " __irqentry_text_end: %lx\n", ms->__irqentry_text_end); + fprintf(fp, " exp_entry1_start: %lx\n", ms->exp_entry1_start); + fprintf(fp, " exp_entry1_end: %lx\n", ms->exp_entry1_end); + fprintf(fp, " exp_entry2_start: %lx\n", ms->exp_entry2_start); + fprintf(fp, " exp_entry2_end: %lx\n", ms->exp_entry2_end); fprintf(fp, " panic_task_regs: %lx\n", (ulong)ms->panic_task_regs); fprintf(fp, " PTE_PROT_NONE: %lx\n", ms->PTE_PROT_NONE); fprintf(fp, " PTE_FILE: "); @@ -1286,6 +1290,15 @@ arm64_stackframe_init(void) machdep->machspec->__irqentry_text_start = sp1->value; machdep->machspec->__irqentry_text_end = sp2->value; } + if ((sp1 = kernel_symbol_search("vectors")) && + (sp1n = kernel_symbol_search("cpu_switch_to")) && + (sp2 = kernel_symbol_search("ret_fast_syscall")) && + (sp2n = kernel_symbol_search("sys_rt_sigreturn_wrapper"))) { + machdep->machspec->exp_entry1_start = sp1->value; + machdep->machspec->exp_entry1_end = sp1n->value; + machdep->machspec->exp_entry2_start = sp2->value; + machdep->machspec->exp_entry2_end = sp2n->value; + } if ((sp1 = kernel_symbol_search("crash_kexec")) && (sp1n = next_symbol(NULL, sp1)) && @@ -1472,25 +1485,20 @@ arm64_eframe_search(struct bt_info *bt) } static int -arm64_in_exception_text(ulong ptr) +arm64_in_exp_entry(ulong addr) { - struct machine_specific *ms = machdep->machspec; + struct machine_specific *ms; - if ((ptr >= ms->__exception_text_start) && - (ptr < ms->__exception_text_end)) + ms = machdep->machspec; + if ((ms->exp_entry1_start <= addr) && (addr < ms->exp_entry1_end)) return TRUE; - - if (ms->__irqentry_text_start && ms->__irqentry_text_end && - ((ptr >= ms->__irqentry_text_start) && - (ptr < ms->__irqentry_text_end))) + if ((ms->exp_entry2_start <= addr) && (addr < ms->exp_entry2_end)) return TRUE; - return FALSE; } #define BACKTRACE_CONTINUE (1) #define BACKTRACE_COMPLETE_KERNEL (2) -#define BACKTRACE_COMPLETE_USER (3) static int arm64_print_stackframe_entry(struct bt_info *bt, int level, struct arm64_stackframe *frame, FILE *ofp) @@ -1511,11 +1519,6 @@ arm64_print_stackframe_entry(struct bt_info *bt, int level, struct arm64_stackfr value_to_symstr(frame->pc, buf, bt->radix); } - if ((bt->flags & BT_FULL) && level) { - arm64_display_full_frame(bt, frame->fp); - bt->frameptr = frame->fp; - } - fprintf(ofp, "%s#%d [%8lx] %s at %lx", level < 10 ? " " : "", level, frame->fp ? frame->fp : bt->stacktop - USER_EFRAME_OFFSET, name_plus_offset ? name_plus_offset : name, frame->pc); @@ -1534,7 +1537,8 @@ arm64_print_stackframe_entry(struct bt_info *bt, int level, struct arm64_stackfr fprintf(ofp, " %s\n", buf); } - if (STREQ(name, "start_kernel") || STREQ(name, "secondary_start_kernel") || + if (STREQ(name, "start_kernel") || + STREQ(name, "secondary_start_kernel") || STREQ(name, "kthread") || STREQ(name, "kthreadd")) return BACKTRACE_COMPLETE_KERNEL; @@ -1542,46 +1546,169 @@ arm64_print_stackframe_entry(struct bt_info *bt, int level, struct arm64_stackfr } static void -arm64_display_full_frame(struct bt_info *bt, ulong sp) +arm64_display_full_frame(struct bt_info *bt, struct arm64_stackframe *cur, + struct arm64_stackframe *next) { + struct machine_specific *ms; + ulong next_fp, stackbase; + char *stackbuf; int i, u_idx; ulong *up; ulong words, addr; char buf[BUFSIZE]; - if (bt->frameptr == sp) - return; + stackbase = bt->stackbase; + stackbuf = bt->stackbuf; + ms = machdep->machspec; - if (!INSTACK(sp, bt) || !INSTACK(bt->frameptr, bt)) { - if (sp == 0) - sp = bt->stacktop - USER_EFRAME_OFFSET; - else - return; - } + /* Calc next fp for dump */ + if (next->fp == 0) + /* last stackframe on kernel tack */ + next_fp = bt->stacktop - 0x10; + else if (!INSTACK(cur->sp, bt)) { + /* We have just switched over stacks */ + next_fp = ms->irq_stacks[bt->tc->processor] + + ms->irq_stack_size - 0x10; - words = (sp - bt->frameptr) / sizeof(ulong); + /* + * We are already buffering a process stack. + * So use an old buffer for IRQ stack. + */ + stackbase = ms->irq_stacks[bt->tc->processor]; + stackbuf = ms->irq_stackbuf; + } else + next_fp = next->fp; - addr = bt->frameptr; - u_idx = (bt->frameptr - bt->stackbase)/sizeof(ulong); + if (CRASHDEBUG(1)) + fprintf(fp, " frame <%016lx:%016lx>\n", cur->fp, next_fp); + + /* Check here because we want to see a debug message above. */ + if (!(bt->flags & BT_FULL)) + return; + + /* Dump */ + words = (next_fp - cur->fp) / sizeof(ulong); + addr = cur->fp; + u_idx = (cur->fp - stackbase)/sizeof(ulong); for (i = 0; i < words; i++, u_idx++) { if (!(i & 1)) fprintf(fp, "%s %lx: ", i ? "\n" : "", addr); - up = (ulong *)(&bt->stackbuf[u_idx*sizeof(ulong)]); + up = (ulong *)(&stackbuf[u_idx*sizeof(ulong)]); fprintf(fp, "%s ", format_stack_entry(bt, buf, *up, 0)); addr += sizeof(ulong); } fprintf(fp, "\n"); + + if (stackbuf == ms->irq_stackbuf) + FREEBUF(stackbuf); } -static int -arm64_unwind_frame(struct bt_info *bt, struct arm64_stackframe *frame) +/* + * (1)Normal frame: + * +------+ + * | pfp | + * | cpc | + * psp + + + * | | + * | | + * pfp +------+ <--- :prev stackframe = <pfp, psp, ppc> + * | cfp | + * | npc | + * csp + + + * | | + * | | + * cfp +------+ <--- :curr stackframe = <cfp, csp, cpc> + * | nfp | | cfp = *pfp + * | Npc | | csp = pfp + 0x10 + * nsp + + real stackframe + * | | | at cpc + * | | | + * nfp +------+ <--- :next stackframe = <nfp, nsp, npc> + * | | + * + * (2)Exception: + * +------+ + * | pfp | + * | cpc | + * psp + + + * | | + * | | + * pfp +------+ <--- :prev stackframe = <pfp, psp, ppc> + * | cfp | + * | npc | + * csp + + + * | | + * | | + * cfp +------+ <--- :stackframe = <cfp, csp, cpc> + * | nfp | + * | epc | + * + + + * | | + * | | calced dummy + * esp +------+ <--- :exp stackframe = <---, esp, epc> + * | | esp = nsp - sizeof(pt_regs) + * | | + * | Npc | + * | nfp | + * | nsp | + * | npc | + * nsp + + + * | | calced missing + * nfp +------+ <--- :task stackframe = <nfp, nsp, npc> + * | Nfp | + * | NNpc | + * Nsp + + + * | | + * Nfp +------+ <--- :task stackframe = <Nfp, Nsp, Npc> + * | NNfp | + * + * (3)At interrupt: + * +------+ + * | pfp | + * | cpc | + * psp + + + * | | + * | | + * pfp +------+ <--- :prev stackframe = <pfp, psp, ppc> + * | cfp | + * | epc | + * csp + + + * | | + * | | calced dummy + * cfp +------+ <--- :irq stackframe = <cfp, csp, epc> + * | nfp | | if (cfp == IRQ_STACK_PTR) + * | esp | V + * top +------+ <---, esp, epc> + * IRQ stack + * + * calced dummy + * esp +------+ <--- :exp stackframe = <---, esp, epc> + * | | esp = nsp - sizeof(pt_regs) + * | | + * | Npc | + * | nfp | + * | nsp | + * | npc | calced missing + * nfp +------+ <--- :task stackframe = <nfp, nsp, npc> + * | Nfp | + * | NNpc | + * Nsp + + + * | | + * Nfp +------+ <--- :task stackframe = <Nfp, Nsp, Npc> + * | NNfp | + */ + +static struct arm64_stackframe ext_frame; + +static int +arm64_unwind_frame(struct bt_info *bt, struct arm64_stackframe *frame, + FILE *ofp) { unsigned long high, low, fp; unsigned long stack_mask; - unsigned long irq_stack_ptr, orig_sp; - struct arm64_pt_regs *ptregs; + unsigned long irq_stack_ptr; struct machine_specific *ms; stack_mask = (unsigned long)(ARM64_STACK_SIZE) - 1; @@ -1593,54 +1720,115 @@ arm64_unwind_frame(struct bt_info *bt, struct arm64_stackframe *frame) if (fp < low || fp > high || fp & 0xf) return FALSE; - frame->sp = fp + 0x10; - frame->fp = GET_STACK_ULONG(fp); + if (CRASHDEBUG(1)) + fprintf(ofp, " cur fp:%016lx sp:%016lx pc:%016lx\n", + frame->fp, frame->sp, frame->pc); + + if (ext_frame.pc) { + /* + * Previous frame was a dummy for exception entry. + * So insert a hidden (real) stackframe. + */ + frame->fp = ext_frame.fp; + frame->sp = ext_frame.sp; + frame->pc = ext_frame.pc; + + ext_frame.pc = 0; /* back to normal unwinding */ + + goto unwind_done; + } + frame->pc = GET_STACK_ULONG(fp + 8); + if (!arm64_in_exp_entry(frame->pc)) { + /* Normal stack frame */ - /* - * The kernel's manner of determining the end of the IRQ stack: - * - * #define THREAD_SIZE 16384 - * #define THREAD_START_SP (THREAD_SIZE - 16) - * #define IRQ_STACK_START_SP THREAD_START_SP - * #define IRQ_STACK_PTR(cpu) ((unsigned long)per_cpu(irq_stack, cpu) + IRQ_STACK_START_SP) - * #define IRQ_STACK_TO_TASK_STACK(ptr) (*((unsigned long *)((ptr) - 0x08))) - * - * irq_stack_ptr = IRQ_STACK_PTR(raw_smp_processor_id()); - * orig_sp = IRQ_STACK_TO_TASK_STACK(irq_stack_ptr); (pt_regs pointer on process stack) - */ - if (machdep->flags & IRQ_STACKS) { - ms = machdep->machspec; - irq_stack_ptr = ms->irq_stacks[bt->tc->processor] + ms->irq_stack_size - 16; - - if (frame->sp == irq_stack_ptr) { - orig_sp = GET_STACK_ULONG(irq_stack_ptr - 8); - arm64_set_process_stack(bt); - if (INSTACK(orig_sp, bt) && (INSTACK(frame->fp, bt) || (frame->fp == 0))) { - ptregs = (struct arm64_pt_regs *)&bt->stackbuf[(ulong)(STACK_OFFSET_TYPE(orig_sp))]; - frame->sp = orig_sp; - frame->pc = ptregs->pc; - bt->bptr = fp; - if (CRASHDEBUG(1)) - error(INFO, - "arm64_unwind_frame: switch stacks: fp: %lx sp: %lx pc: %lx\n", - frame->fp, frame->sp, frame->pc); + frame->sp = fp + 0x10; + frame->fp = GET_STACK_ULONG(fp); + } else { + /* + * We are in exception entry code, and so need to + * - fake a dummy frame for exception frame, and + * - complement a stackframe hidden by exception + */ + + ext_frame.fp = GET_STACK_ULONG(fp); + if (ext_frame.fp == 0) { + /* + * Either on process stack or on IRQ stack, + * the next frame is the last one on process stack. + */ + + frame->sp = bt->stacktop + - sizeof(struct arm64_pt_regs) - 0x10; + frame->fp = frame->sp; + } else if (!arm64_on_irq_stack(bt->tc->processor, frame->sp)) { + /* + * We are on process stack. Just fake a dummy frame + */ + + if (!arm64_on_irq_stack(bt->tc->processor, fp)) + /* + * Very rare corner case: + * We have already exited an irq handler, + * and switched from IRQ stack to process + * stack but fp is not yet restored. + * Fp still points to IRQ stack, sigh. + * For example, + * ret_to_user() after irq_handler in el0_irq + */ + frame->sp = bt->stacktop + - sizeof(struct arm64_pt_regs) + - 0x10; + else + frame->sp = ext_frame.fp + - sizeof(struct arm64_pt_regs); + frame->fp = frame->sp; + } else { + /* We are on IRQ stack */ + + ms = machdep->machspec; + irq_stack_ptr = ms->irq_stacks[bt->tc->processor] + + ms->irq_stack_size - 0x20; + if (ext_frame.fp != irq_stack_ptr) { + /* Just fake a dummy frame */ + + frame->sp = ext_frame.fp + - sizeof(struct arm64_pt_regs); + frame->fp = frame->sp; } else { - error(WARNING, - "arm64_unwind_frame: on IRQ stack: oriq_sp: %lx%s fp: %lx%s\n", - orig_sp, INSTACK(orig_sp, bt) ? "" : " (?)", - frame->fp, INSTACK(frame->fp, bt) ? "" : " (?)"); - return FALSE; + /* + * switch from IRQ stack to process stack + */ + + frame->sp = GET_STACK_ULONG(irq_stack_ptr + 8); + frame->fp = frame->sp; + + /* + * Keep a buffer for a while until + * displaying the last frame on IRQ stack. + * Ugly? + */ + if (bt->flags | BT_FULL) + ms->irq_stackbuf = bt->stackbuf; + + arm64_set_process_stack(bt); } } + + arm64_gen_hidden_frame(bt, frame->sp, &ext_frame); } +unwind_done: + if (CRASHDEBUG(1)) + fprintf(ofp, " nxt fp:%016lx sp:%016lx pc:%016lx\n", + frame->fp, frame->sp, frame->pc); + return TRUE; } -/* +/* * A layout of a stack frame in a function looks like: - * + * * stack grows to lower addresses. * /|\ * | @@ -1658,7 +1846,7 @@ arm64_unwind_frame(struct bt_info *bt, struct arm64_stackframe *frame) * | vars | * old fp +------+ * | | - * + * * - On function entry, sp is decremented down to new fp. * * - and old fp and sp are saved into this stack frame. @@ -1680,13 +1868,13 @@ arm64_unwind_frame(struct bt_info *bt, struct arm64_stackframe *frame) * sp shows "callee's static local variables", old fp and sp. * * Diagram and explanation courtesy of Takahiro Akashi - */ + */ static void arm64_back_trace_cmd(struct bt_info *bt) { - struct arm64_stackframe stackframe; - int level; + struct arm64_stackframe stackframe, cur_frame; + int level, mode; ulong exception_frame; FILE *ofp; @@ -1708,17 +1896,7 @@ arm64_back_trace_cmd(struct bt_info *bt) stackframe.fp = GET_STACK_ULONG(bt->bptr - 8); stackframe.pc = GET_STACK_ULONG(bt->bptr); stackframe.sp = bt->bptr + 8; - bt->frameptr = stackframe.sp; - } else if (bt->hp && bt->hp->esp) { - if (arm64_on_irq_stack(bt->tc->processor, bt->hp->esp)) { - arm64_set_irq_stack(bt); - bt->flags |= BT_IRQSTACK; - } - stackframe.fp = GET_STACK_ULONG(bt->hp->esp - 8); - stackframe.pc = bt->hp->eip ? - bt->hp->eip : GET_STACK_ULONG(bt->hp->esp); - stackframe.sp = bt->hp->esp + 8; - bt->flags &= ~BT_REGS_NOT_FOUND; + bt->frameptr = stackframe.fp; } else { stackframe.sp = bt->stkptr; stackframe.pc = bt->instptr; @@ -1739,8 +1917,14 @@ arm64_back_trace_cmd(struct bt_info *bt) return; if (!(bt->flags & BT_KDUMP_ADJUST)) { - if (bt->flags & BT_USER_SPACE) - goto complete_user; + if (bt->flags & BT_USER_SPACE) { + exception_frame = bt->stacktop - USER_EFRAME_OFFSET; + arm64_print_exception_frame(bt, exception_frame, + USER_MODE, ofp); + fprintf(ofp, " #0 [user space]\n"); + + return; + } if (DUMPFILE() && is_task_active(bt->task)) { exception_frame = stackframe.fp - SIZE(pt_regs); @@ -1750,53 +1934,55 @@ arm64_back_trace_cmd(struct bt_info *bt) } } - level = exception_frame = 0; - while (1) { + for (level = 0;; level++) { bt->instptr = stackframe.pc; - switch (arm64_print_stackframe_entry(bt, level, &stackframe, ofp)) - { - case BACKTRACE_COMPLETE_KERNEL: - return; - case BACKTRACE_COMPLETE_USER: - goto complete_user; - case BACKTRACE_CONTINUE: + /* + * Show one-line stackframe info + */ + if (arm64_print_stackframe_entry(bt, level, &stackframe, ofp) + == BACKTRACE_COMPLETE_KERNEL) break; - } - - if (exception_frame) { - arm64_print_exception_frame(bt, exception_frame, KERNEL_MODE, ofp); - exception_frame = 0; - } - if (!arm64_unwind_frame(bt, &stackframe)) + cur_frame = stackframe; + if (!arm64_unwind_frame(bt, &stackframe, ofp)) break; - if (arm64_in_exception_text(bt->instptr) && INSTACK(stackframe.fp, bt)) { - if (!(bt->flags & BT_IRQSTACK) || - (((stackframe.sp + SIZE(pt_regs)) < bt->stacktop))) - exception_frame = stackframe.fp - SIZE(pt_regs); - } + /* + * Dump the contents of the current stackframe. + * We need to know the next stackframe to determine + * the dump range: + * <cur_frame.fp:stackframe.fp> + */ + arm64_display_full_frame(bt, &cur_frame, &stackframe); - if ((bt->flags & BT_IRQSTACK) && - !arm64_on_irq_stack(bt->tc->processor, stackframe.sp)) { - bt->flags &= ~BT_IRQSTACK; - if (arm64_switch_stack(bt, &stackframe, ofp) == USER_MODE) - break; - } + /* + * If we are in a normal stackframe, just continue, + * otherwise show an exception frame. + * Since exception entry code doesn't have a real + * stackframe, we fake a dummy frame here. + */ + if (!arm64_in_exp_entry(stackframe.pc)) + continue; + if (!INSTACK(cur_frame.sp, bt)) + fprintf(ofp, "--- <IRQ stack> ---\n"); - level++; - } + arm64_print_stackframe_entry(bt, ++level, &stackframe, ofp); + cur_frame = stackframe; + arm64_unwind_frame(bt, &stackframe, ofp); - if (is_kernel_thread(bt->tc->task)) - return; + /* + * and don't show the contenxts. Instead, + * show an exception frame below + */ + mode = (stackframe.pc < machdep->machspec->userspace_top) ? + USER_MODE : KERNEL_MODE; + arm64_print_exception_frame(bt, cur_frame.sp, mode, ofp); -complete_user: - exception_frame = bt->stacktop - USER_EFRAME_OFFSET; - arm64_print_exception_frame(bt, exception_frame, USER_MODE, ofp); - if ((bt->flags & (BT_USER_SPACE|BT_KDUMP_ADJUST)) == BT_USER_SPACE) - fprintf(ofp, " #0 [user space]\n"); + if (mode == USER_MODE) + break; + } } static void @@ -1932,41 +2118,6 @@ arm64_in_kdump_text_on_irq_stack(struct bt_info *bt) return FALSE; } -static int -arm64_switch_stack(struct bt_info *bt, struct arm64_stackframe *frame, FILE *ofp) -{ - int i; - ulong stacktop, words, addr; - ulong *stackbuf; - char buf[BUFSIZE]; - struct machine_specific *ms = machdep->machspec; - - if (bt->flags & BT_FULL) { - stacktop = ms->irq_stacks[bt->tc->processor] + ms->irq_stack_size; - words = (stacktop - bt->bptr) / sizeof(ulong); - stackbuf = (ulong *)GETBUF(words * sizeof(ulong)); - readmem(bt->bptr, KVADDR, stackbuf, words * sizeof(long), - "top of IRQ stack", FAULT_ON_ERROR); - - addr = bt->bptr; - for (i = 0; i < words; i++) { - if (!(i & 1)) - fprintf(ofp, "%s %lx: ", i ? "\n" : "", addr); - fprintf(ofp, "%s ", format_stack_entry(bt, buf, stackbuf[i], 0)); - addr += sizeof(ulong); - } - fprintf(ofp, "\n"); - FREEBUF(stackbuf); - } - fprintf(ofp, "--- <IRQ stack> ---\n"); - - if (frame->fp == 0) - return USER_MODE; - - arm64_print_exception_frame(bt, frame->sp, KERNEL_MODE, ofp); - return KERNEL_MODE; -} - static int arm64_get_dumpfile_stackframe(struct bt_info *bt, struct arm64_stackframe *frame) { @@ -2047,6 +2198,20 @@ arm64_get_stack_frame(struct bt_info *bt, ulong *pcp, ulong *spp) } static void +arm64_gen_hidden_frame(struct bt_info *bt, ulong sp, + struct arm64_stackframe *frame) +{ + struct arm64_pt_regs *ptregs; + + ptregs = (struct arm64_pt_regs *) + &bt->stackbuf[(ulong)(STACK_OFFSET_TYPE(sp))]; + + frame->pc = ptregs->pc; + frame->fp = ptregs->regs[29]; + frame->sp = ptregs->sp; +} + +static void arm64_print_exception_frame(struct bt_info *bt, ulong pt_regs, int mode, FILE *ofp) { int i, r, rows, top_reg, is_64_bit; @@ -2055,10 +2220,16 @@ arm64_print_exception_frame(struct bt_info *bt, ulong pt_regs, int mode, FILE *o ulong LR, SP, offset; char buf[BUFSIZE]; + if (mode == KERNEL_MODE) + fprintf(ofp, "--- <Exception in kernel> ---\n"); + else + fprintf(ofp, "--- <Exception in user> ---\n"); + if (CRASHDEBUG(1)) fprintf(ofp, "pt_regs: %lx\n", pt_regs); - regs = (struct arm64_pt_regs *)&bt->stackbuf[(ulong)(STACK_OFFSET_TYPE(pt_regs))]; + regs = (struct arm64_pt_regs *) + &bt->stackbuf[(ulong)(STACK_OFFSET_TYPE(pt_regs))]; if ((mode == USER_MODE) && (regs->pstate & PSR_MODE32_BIT)) { LR = regs->regs[14]; @@ -2130,10 +2301,11 @@ arm64_print_exception_frame(struct bt_info *bt, ulong pt_regs, int mode, FILE *o } if (is_64_bit) { - fprintf(ofp, "ORIG_X0: %016lx SYSCALLNO: %lx", - (ulong)regs->orig_x0, (ulong)regs->syscallno); - if (mode == USER_MODE) + if (mode == USER_MODE) { + fprintf(ofp, "ORIG_X0: %016lx SYSCALLNO: %lx", + (ulong)regs->orig_x0, (ulong)regs->syscallno); fprintf(ofp, " PSTATE: %08lx", (ulong)regs->pstate); + } fprintf(ofp, "\n"); } diff --git a/defs.h b/defs.h index d6f719c..f7ea5a0 100644 --- a/defs.h +++ b/defs.h @@ -3058,8 +3058,14 @@ struct machine_specific { ulong kernel_flags; ulong irq_stack_size; ulong *irq_stacks; + char *irq_stackbuf; ulong __irqentry_text_start; ulong __irqentry_text_end; + /* for exception vector code */ + ulong exp_entry1_start; + ulong exp_entry1_end; + ulong exp_entry2_start; + ulong exp_entry2_end; /* only needed for v4.6 or later kernel */ ulong kimage_voffset; ulong kimage_text; -- 2.9.0 -- Crash-utility mailing list Crash-utility@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/crash-utility