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."

Thanks,
-Takahiro AKASHI
===8<===
>From 826147807e2f2e00155b41b8ab97d3083bb0e607 Mon Sep 17 00:00:00 2001
From: AKASHI Takahiro <takahiro.aka...@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@redhat.com
https://www.redhat.com/mailman/listinfo/crash-utility

Reply via email to