[Crash-utility] Problem in bt for ARM64

AKASHI Takahiro takahiro.akashi at linaro.org
Thu Oct 19 01:25:24 UTC 2017


Dave,

On Wed, Oct 18, 2017 at 02:12:17PM -0400, Dave Anderson wrote:
> 
> 
> ----- 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?

Here is what you requested. Pls check.

Thanks,
-Takahiro AKASHI

===8<===
>From 7b99a1c2e688ba81e18541c21a7d0fa70504e5bc Mon Sep 17 00:00:00 2001
From: AKASHI Takahiro <takahiro.akashi at linaro.org>
Date: Thu, 19 Oct 2017 10:18:22 +0900
Subject: [PATCH] arm64: bt: cleanup stuff

---
 arm64.c | 159 +++++++++++++++++++++++++++++++++-------------------------------
 defs.h  |   3 ++
 task.c  |   2 +
 3 files changed, 86 insertions(+), 78 deletions(-)

diff --git a/arm64.c b/arm64.c
index c75669b..1f742d4 100644
--- a/arm64.c
+++ b/arm64.c
@@ -612,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)
@@ -1383,7 +1384,7 @@ arm64_irq_stack_init(void)
 
 		if (!(ms->irq_stacks = (ulong *)malloc((size_t)(kt->cpus * sizeof(ulong)))))
 			error(FATAL, "cannot malloc irq_stack addresses\n");
-		ms->irq_stack_size = 16384;
+		ms->irq_stack_size = ARM64_IRQ_STACK_SIZE;
 		machdep->flags |= IRQ_STACKS;
 
 		for (i = 0; i < kt->cpus; i++) {
@@ -1410,10 +1411,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");
@@ -1503,6 +1507,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
@@ -1778,7 +1783,7 @@ 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(bt->frameptr, bt)) {
@@ -1793,7 +1798,7 @@ arm64_display_full_frame(struct bt_info *bt, ulong sp)
 				sp = bt->stacktop;
 		}
 	} else { 
-		/* IRQ exception frame */
+		/* This is a transition case from irq to process stack. */
 		return;
 	}
 
@@ -1903,61 +1908,73 @@ arm64_unwind_frame(struct bt_info *bt, struct arm64_stackframe *frame)
 	if (!(machdep->flags & IRQ_STACKS))
 		return TRUE;
 
-	/*
-	 * 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))
+		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 - SIZE(pt_regs) + 16;
-				/* for switch_stack */
-				/* fp still points to irq stack */
+				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 */
-				bt->frameptr = frame->sp;
+				/*
+				 * 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;
 			}
 		}
-	} else { /* !UNW_4_14 */
-		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;
-			}
+
+		return TRUE;
+	}
+
+	/*
+	 * 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)
+	 */
+	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;
 		}
-	} /* UNW_4_14 */
+	}
 
 	return TRUE;
 }
@@ -2147,17 +2164,10 @@ arm64_unwind_frame_v2(struct bt_info *bt, struct arm64_stackframe *frame,
 			 * We are on process stack. Just add a faked frame
 			 */
 
-			if (!arm64_on_irq_stack(bt->tc->processor, ext_frame.fp)) {
-				if (MEMBER_EXISTS("pt_regs", "stackframe")) {
-					frame->sp = ext_frame.fp
-						    - sizeof(struct arm64_pt_regs) - 16;
-					frame->fp = ext_frame.fp;
-				} else {
-					frame->sp = ext_frame.fp
-						    - sizeof(struct arm64_pt_regs);
-					frame->fp = frame->sp;
-				}
-			} else {
+			if (!arm64_on_irq_stack(bt->tc->processor, ext_frame.fp))
+				frame->sp = ext_frame.fp
+					    - sizeof(struct arm64_pt_regs);
+			else {
 				/*
 				 * FIXME: very exceptional case
 				 * We are already back on process stack, but
@@ -2177,10 +2187,10 @@ arm64_unwind_frame_v2(struct bt_info *bt, struct arm64_stackframe *frame,
 				 * Really ugly
 				 */
 				frame->sp = frame->fp + 0x20;
-				frame->fp = frame->sp;
 				fprintf(ofp, " (Next exception frame might be wrong)\n");
 			}
 
+			frame->fp = frame->sp;
 		} else {
 			/* We are on IRQ stack */
 
@@ -2190,15 +2200,9 @@ arm64_unwind_frame_v2(struct bt_info *bt, struct arm64_stackframe *frame,
 			if (ext_frame.fp != irq_stack_ptr) {
 				/* (2) Just add a faked frame */
 
-				if (MEMBER_EXISTS("pt_regs", "stackframe")) {
-					frame->sp = ext_frame.fp
-						    - sizeof(struct arm64_pt_regs);
-					frame->fp = ext_frame.fp;
-				} else {
-					frame->sp = ext_frame.fp
-						    - sizeof(struct arm64_pt_regs) - 16;
-					frame->fp = frame->sp;
-				}
+				frame->sp = ext_frame.fp
+					    - sizeof(struct arm64_pt_regs);
+				frame->fp = frame->sp;
 			} else {
 				/*
 				 * (3)
@@ -2285,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;
 	}
@@ -2346,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);
@@ -2377,13 +2386,9 @@ 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))) {
-				if (MEMBER_EXISTS("pt_regs", "stackframe"))
-					/* v4.14 or later */
-					exception_frame = stackframe.fp - SIZE(pt_regs) + 16;
-				else
-					exception_frame = stackframe.fp - SIZE(pt_regs);
-			}
+			    (((stackframe.sp + SIZE(pt_regs)) < bt->stacktop)))
+				exception_frame = stackframe.fp
+						  - KERN_EFRAME_OFFSET;
 		}
 
 		if ((bt->flags & BT_IRQSTACK) &&
@@ -2503,8 +2508,6 @@ user_space:
 		 * otherwise show an exception frame.
 		 * Since exception entry code doesn't have a real
 		 * stackframe, we fake a dummy frame here.
-		 * Note: Since we have a real stack frame in pt_regs,
-		 * We no longer need a dummy frame on v4.14 or later.
 		 */
 		if (!arm64_in_exp_entry(stackframe.pc))
 			continue;
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




More information about the Crash-utility mailing list