[Crash-utility] Problem in bt for ARM64
Dave Anderson
anderson at redhat.com
Wed Oct 18 18:12:17 UTC 2017
----- Original Message -----
> On Tue, Oct 17, 2017 at 03:44:36PM -0400, Dave Anderson wrote:
> >
> > Thanks Takahiro, much appreciated. Queued for crash-7.2.1:
> >
> > https://github.com/crash-utility/crash/commit/2b93c036edf2a5cc21a06a14f377cd9b365f858a
>
> Oops, I've made small changes, nothing essential but some sort of
> clean-ups/readability improvements with deleting incomplete fixes
> against "bt -o."
Hmmm, except it's kind of difficult to pick through the patch below
for the changes, given that it's a combination of your original patch
plus the new changes. So I can't apply it to get a clean view of
the new changes. I do see that it's mostly the stacksize and stackframe
related updates, but would it be possible for you to make a patch
that can be applied to the github sources?
Thanks,
Dave
>
> Thanks,
> -Takahiro AKASHI
> ===8<===
> >From 826147807e2f2e00155b41b8ab97d3083bb0e607 Mon Sep 17 00:00:00 2001
> From: AKASHI Takahiro <takahiro.akashi at linaro.org>
> Date: Thu, 12 Oct 2017 10:46:34 +0900
> Subject: [PATCH v2] arm64: backtrace for v4.14
>
> ---
> arm64.c | 212
> +++++++++++++++++++++++++++++++++++++++++++++++-----------------
> defs.h | 3 +
> task.c | 2 +
> 3 files changed, 161 insertions(+), 56 deletions(-)
>
> diff --git a/arm64.c b/arm64.c
> index 20c5d34..80cb476 100644
> --- a/arm64.c
> +++ b/arm64.c
> @@ -72,6 +72,7 @@ static void arm64_cmd_mach(void);
> static void arm64_display_machine_stats(void);
> static int arm64_get_smp_cpus(void);
> static void arm64_clear_machdep_cache(void);
> +static int arm64_on_process_stack(struct bt_info *, ulong);
> static int arm64_in_alternate_stack(int, ulong);
> static int arm64_on_irq_stack(int, ulong);
> static void arm64_set_irq_stack(struct bt_info *);
> @@ -611,6 +612,7 @@ arm64_dump_machdep_table(ulong arg)
> 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, " user_eframe_offset: %ld\n", ms->user_eframe_offset);
> + fprintf(fp, " kern_eframe_offset: %ld\n", ms->kern_eframe_offset);
> fprintf(fp, " PTE_PROT_NONE: %lx\n", ms->PTE_PROT_NONE);
> fprintf(fp, " PTE_FILE: ");
> if (ms->PTE_FILE)
> @@ -1336,31 +1338,64 @@ arm64_irq_stack_init(void)
> req = &request;
> struct machine_specific *ms = machdep->machspec;
>
> - if (!symbol_exists("irq_stack") ||
> - !(sp = per_cpu_symbol_search("irq_stack")) ||
> - !get_symbol_type("irq_stack", NULL, req) ||
> - (req->typecode != TYPE_CODE_ARRAY) ||
> - (req->target_typecode != TYPE_CODE_INT))
> - return;
> + if (!(ms->irq_stacks = (ulong *)malloc((size_t)(kt->cpus
> + * sizeof(ulong)))))
> + error(FATAL, "cannot malloc irq_stack addresses\n");
>
> - if (CRASHDEBUG(1)) {
> - fprintf(fp, "irq_stack: \n");
> - fprintf(fp, " type: %s\n",
> - (req->typecode == TYPE_CODE_ARRAY) ? "TYPE_CODE_ARRAY" : "other");
> - fprintf(fp, " target_typecode: %s\n",
> - req->target_typecode == TYPE_CODE_INT ? "TYPE_CODE_INT" : "other");
> - fprintf(fp, " target_length: %ld\n", req->target_length);
> - fprintf(fp, " length: %ld\n", req->length);
> - }
> + if (symbol_exists("irq_stack") &&
> + (sp = per_cpu_symbol_search("irq_stack")) &&
> + get_symbol_type("irq_stack", NULL, req)) {
> + /* before v4.14 or CONFIG_VMAP_STACK disabled */
> + if (CRASHDEBUG(1)) {
> + fprintf(fp, "irq_stack: \n");
> + fprintf(fp, " type: %s\n",
> + (req->typecode == TYPE_CODE_ARRAY) ?
> + "TYPE_CODE_ARRAY" : "other");
> + fprintf(fp, " target_typecode: %s\n",
> + req->target_typecode == TYPE_CODE_INT ?
> + "TYPE_CODE_INT" : "other");
> + fprintf(fp, " target_length: %ld\n",
> + req->target_length);
> + fprintf(fp, " length: %ld\n", req->length);
> + }
>
> - ms->irq_stack_size = req->length;
> - if (!(ms->irq_stacks = (ulong *)malloc((size_t)(kt->cpus *
> sizeof(ulong)))))
> - error(FATAL, "cannot malloc irq_stack addresses\n");
> + ms->irq_stack_size = req->length;
> +
> + for (i = 0; i < kt->cpus; i++)
> + ms->irq_stacks[i] = kt->__per_cpu_offset[i] + sp->value;
> +
> + machdep->flags |= IRQ_STACKS;
> + } else if (symbol_exists("irq_stack_ptr") &&
> + (sp = per_cpu_symbol_search("irq_stack_ptr")) &&
> + get_symbol_type("irq_stack_ptr", NULL, req)) {
> + /* v4.14 and later with CONFIG_VMAP_STACK enabled */
> + if (CRASHDEBUG(1)) {
> + fprintf(fp, "irq_stack_ptr: \n");
> + fprintf(fp, " type: %x, %s\n",
> + (int)req->typecode,
> + (req->typecode == TYPE_CODE_PTR) ?
> + "TYPE_CODE_PTR" : "other");
> + fprintf(fp, " target_typecode: %x, %s\n",
> + (int)req->target_typecode,
> + req->target_typecode == TYPE_CODE_INT ?
> + "TYPE_CODE_INT" : "other");
> + fprintf(fp, " target_length: %ld\n",
> + req->target_length);
> + fprintf(fp, " length: %ld\n", req->length);
> + }
> +
> + ms->irq_stack_size = ARM64_IRQ_STACK_SIZE;
>
> - for (i = 0; i < kt->cpus; i++)
> - ms->irq_stacks[i] = kt->__per_cpu_offset[i] + sp->value;
> + for (i = 0; i < kt->cpus; i++) {
> + ulong p;
>
> - machdep->flags |= IRQ_STACKS;
> + p = kt->__per_cpu_offset[i] + sp->value;
> + readmem(p, KVADDR, &(ms->irq_stacks[i]), sizeof(ulong),
> + "IRQ stack pointer", RETURN_ON_ERROR);
> + }
> +
> + machdep->flags |= IRQ_STACKS;
> + }
> }
>
> /*
> @@ -1379,10 +1414,13 @@ arm64_stackframe_init(void)
> MEMBER_OFFSET_INIT(elf_prstatus_pr_pid, "elf_prstatus", "pr_pid");
> MEMBER_OFFSET_INIT(elf_prstatus_pr_reg, "elf_prstatus", "pr_reg");
>
> - if (MEMBER_EXISTS("pt_regs", "stackframe"))
> + if (MEMBER_EXISTS("pt_regs", "stackframe")) {
> machdep->machspec->user_eframe_offset = SIZE(pt_regs);
> - else
> + machdep->machspec->kern_eframe_offset = SIZE(pt_regs) - 16;
> + } else {
> machdep->machspec->user_eframe_offset = SIZE(pt_regs) + 16;
> + machdep->machspec->kern_eframe_offset = SIZE(pt_regs);
> + }
>
> machdep->machspec->__exception_text_start =
> symbol_value("__exception_text_start");
> @@ -1472,6 +1510,7 @@ arm64_stackframe_init(void)
> #define USER_MODE (2)
>
> #define USER_EFRAME_OFFSET (machdep->machspec->user_eframe_offset)
> +#define KERN_EFRAME_OFFSET (machdep->machspec->kern_eframe_offset)
>
> /*
> * PSR bits
> @@ -1747,14 +1786,23 @@ arm64_display_full_frame(struct bt_info *bt, ulong
> sp)
> ulong words, addr;
> char buf[BUFSIZE];
>
> - if (bt->frameptr == sp)
> + if (bt->frameptr >= sp)
> return;
>
> - if (!INSTACK(sp, bt) || !INSTACK(bt->frameptr, bt)) {
> - if (sp == 0)
> - sp = bt->stacktop - USER_EFRAME_OFFSET;
> - else
> - return;
> + if (INSTACK(bt->frameptr, bt)) {
> + if (INSTACK(sp, bt)) {
> + /* normal case */;
> + } else {
> + if (sp == 0)
> + /* interrupt in user mode */
> + sp = bt->stacktop - USER_EFRAME_OFFSET;
> + else
> + /* interrupt in kernel mode */
> + sp = bt->stacktop;
> + }
> + } else {
> + /* This is a transition case from irq to process stack. */
> + return;
> }
>
> words = (sp - bt->frameptr) / sizeof(ulong);
> @@ -1860,6 +1908,38 @@ arm64_unwind_frame(struct bt_info *bt, struct
> arm64_stackframe *frame)
> if ((frame->fp == 0) && (frame->pc == 0))
> return FALSE;
>
> + if (!(machdep->flags & IRQ_STACKS))
> + return TRUE;
> +
> + if (machdep->flags & UNW_4_14) {
> + if ((bt->flags & BT_IRQSTACK) &&
> + !arm64_on_irq_stack(bt->tc->processor, frame->fp)) {
> + if (arm64_on_process_stack(bt, frame->fp)) {
> + arm64_set_process_stack(bt);
> +
> + frame->sp = frame->fp - KERN_EFRAME_OFFSET;
> + /*
> + * for switch_stack
> + * fp still points to irq stack
> + */
> + bt->bptr = fp;
> + /*
> + * for display_full_frame
> + * sp points to process stack
> + *
> + * If we want to see pt_regs,
> + * comment out the below.
> + * bt->frameptr = frame->sp;
> + */
> + } else {
> + /* irq -> user */
> + return FALSE;
> + }
> + }
> +
> + return TRUE;
> + }
> +
> /*
> * The kernel's manner of determining the end of the IRQ stack:
> *
> @@ -1872,29 +1952,27 @@ arm64_unwind_frame(struct bt_info *bt, struct
> arm64_stackframe *frame)
> * 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);
> - } 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;
> - }
> + 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);
> + } 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;
> }
> }
>
> @@ -2211,6 +2289,11 @@ arm64_back_trace_cmd(struct bt_info *bt)
> FILE *ofp;
>
> if (bt->flags & BT_OPT_BACK_TRACE) {
> + if (machdep->flags & UNW_4_14) {
> + error(WARNING, "\"-o\" is no longer supported for this version of kernel.
> Please use bt\n");
> + return;
> + }
> +
> arm64_back_trace_cmd_v2(bt);
> return;
> }
> @@ -2272,7 +2355,7 @@ arm64_back_trace_cmd(struct bt_info *bt)
> goto complete_user;
>
> if (DUMPFILE() && is_task_active(bt->task)) {
> - exception_frame = stackframe.fp - SIZE(pt_regs);
> + exception_frame = stackframe.fp - KERN_EFRAME_OFFSET;
> if (arm64_is_kernel_exception_frame(bt, exception_frame))
> arm64_print_exception_frame(bt, exception_frame,
> KERNEL_MODE, ofp);
> @@ -2304,11 +2387,12 @@ arm64_back_trace_cmd(struct bt_info *bt)
> 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);
> + exception_frame = stackframe.fp
> + - KERN_EFRAME_OFFSET;
> }
>
> if ((bt->flags & BT_IRQSTACK) &&
> - !arm64_on_irq_stack(bt->tc->processor, stackframe.sp)) {
> + !arm64_on_irq_stack(bt->tc->processor, stackframe.fp)) {
> bt->flags &= ~BT_IRQSTACK;
> if (arm64_switch_stack(bt, &stackframe, ofp) == USER_MODE)
> break;
> @@ -2669,7 +2753,9 @@ arm64_switch_stack(struct bt_info *bt, struct
> arm64_stackframe *frame, FILE *ofp
> if (frame->fp == 0)
> return USER_MODE;
>
> - arm64_print_exception_frame(bt, frame->sp, KERNEL_MODE, ofp);
> + if (!(machdep->flags & UNW_4_14))
> + arm64_print_exception_frame(bt, frame->sp, KERNEL_MODE, ofp);
> +
> return KERNEL_MODE;
> }
>
> @@ -3362,6 +3448,20 @@ arm64_clear_machdep_cache(void) {
> return;
> }
>
> +static int
> +arm64_on_process_stack(struct bt_info *bt, ulong stkptr)
> +{
> + ulong stackbase, stacktop;
> +
> + stackbase = GET_STACKBASE(bt->task);
> + stacktop = GET_STACKTOP(bt->task);
> +
> + if ((stkptr >= stackbase) && (stkptr < stacktop))
> + return TRUE;
> +
> + return FALSE;
> +}
> +
> static int
> arm64_on_irq_stack(int cpu, ulong stkptr)
> {
> diff --git a/defs.h b/defs.h
> index 7768895..a694a66 100644
> --- a/defs.h
> +++ b/defs.h
> @@ -3038,6 +3038,7 @@ typedef signed int s32;
> #define ARM64_VMEMMAP_END (ARM64_VMEMMAP_VADDR + GIGABYTES(8UL) - 1)
>
> #define ARM64_STACK_SIZE (16384)
> +#define ARM64_IRQ_STACK_SIZE ARM64_STACK_SIZE
>
> #define _SECTION_SIZE_BITS 30
> #define _MAX_PHYSMEM_BITS 40
> @@ -3117,6 +3118,8 @@ struct machine_specific {
> ulong kimage_text;
> ulong kimage_end;
> ulong user_eframe_offset;
> + /* for v4.14 or later */
> + ulong kern_eframe_offset;
> };
>
> struct arm64_stackframe {
> diff --git a/task.c b/task.c
> index 2b12af0..23c2b7b 100644
> --- a/task.c
> +++ b/task.c
> @@ -6750,6 +6750,8 @@ panic_search(void)
> fd->keyword_array[0] = FOREACH_BT;
> if (machine_type("S390X"))
> fd->flags |= FOREACH_o_FLAG;
> + else if (machine_type("ARM64") && (machdep->flags & UNW_4_14))
> + fd->flags |= FOREACH_t_FLAG;
> else
> fd->flags |= (FOREACH_t_FLAG|FOREACH_o_FLAG);
>
> --
> 2.14.1
>
> --
> Crash-utility mailing list
> Crash-utility at redhat.com
> https://www.redhat.com/mailman/listinfo/crash-utility
>
More information about the Crash-utility
mailing list