Dave,

This patch addresses all the issues that I mentioned in [1], and
re-factored arm64_back_trace_cmd() to make it simpler, while
arm64_unwind_frame() gets a bit complicated. But those changes,
I believe, make the code more readable and easily maintainable.
(The only ugly part is arm64_in_exp_entry(). I have no better ideas.)

Please pick up this patch if you like.
It is to be applied on top of your current master.

[1] https://www.redhat.com/archives/crash-utility/2016-June/msg00040.html

Thanks,
-Takahiro AKASHI

======8<======
>From c1e06fdd21bb70d247babd43cf2762e0cdf6979c Mon Sep 17 00:00:00 2001
From: AKASHI Takahiro <takahiro.aka...@linaro.org>
Date: Thu, 16 Jun 2016 09:29:52 +0900
Subject: [PATCH v3] arm64: more improvement of bt -f

Signed-off-by: AKASHI Takahiro <takahiro.aka...@linaro.org>
---
 arm64.c | 486 +++++++++++++++++++++++++++++++++++++++++++---------------------
 defs.h  |   6 +
 2 files changed, 337 insertions(+), 155 deletions(-)

diff --git a/arm64.c b/arm64.c
index 06676d1..9d42fe6 100644
--- a/arm64.c
+++ b/arm64.c
@@ -43,17 +43,18 @@ 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 +581,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 +1291,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)) && 
@@ -1488,9 +1502,21 @@ arm64_in_exception_text(ulong ptr)
        return FALSE;
 }
 
+static int
+arm64_in_exp_entry(ulong addr)
+{
+       struct machine_specific *ms;
+
+       ms = machdep->machspec;
+       if ((ms->exp_entry1_start <= addr) && (addr < ms->exp_entry1_end))
+               return TRUE;
+       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 +1537,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 +1555,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 +1564,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;
+
+               /*
+                * 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;
+
+       if (CRASHDEBUG(1))
+               fprintf(fp, "    frame <%016lx:%016lx>\n", cur->fp, next_fp);
 
-       words = (sp - bt->frameptr) / sizeof(ulong);
+       /* Check here because we want to see a debug message above. */
+       if (!(bt->flags & BT_FULL))
+               return;
 
-       addr = bt->frameptr;
-       u_idx = (bt->frameptr - bt->stackbase)/sizeof(ulong);
+       /* 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;
        struct machine_specific *ms;
 
        stack_mask = (unsigned long)(ARM64_STACK_SIZE) - 1;
@@ -1593,54 +1738,101 @@ 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 (!machdep->flags & IRQ_STACKS) {
+                       /*
+                        * We are on process stack. Just fake a dummy frame
+                        */
+
+                       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 +1850,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 +1872,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 +1900,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 +1921,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 +1938,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 +2122,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 +2202,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 +2224,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 +2305,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@redhat.com
https://www.redhat.com/mailman/listinfo/crash-utility

Reply via email to