[Crash-utility] [PATCH] ppc64: fix 'bt' command for vmcore captured with fadump.

Hari Bathini hbathini at linux.vnet.ibm.com
Wed Jan 18 18:16:21 UTC 2017


Without this patch, backtraces of active tasks maybe be of the form
"#0 [c0000000700b3a90] (null) at c0000000700b3b50  (unreliable)" for
kernel dumps captured with fadump.  Trying to use ptregs saved for
active tasks before falling back to stack-search method. Also, getting
rid of warnings like "‘is_hugepage’ declared inline after being called".

Signed-off-by: Hari Bathini <hbathini at linux.vnet.ibm.com>
---
 diskdump.c |   22 ++++++++++++++++++++++
 ppc64.c    |   58 +++++++++++++++++++++++++++++-----------------------------
 2 files changed, 51 insertions(+), 29 deletions(-)

diff --git a/diskdump.c b/diskdump.c
index 48667ad..c080084 100644
--- a/diskdump.c
+++ b/diskdump.c
@@ -1368,6 +1368,28 @@ get_diskdump_regs_ppc64(struct bt_info *bt, ulong *eip, ulong *esp)
 {
 	if ((bt->task == tt->panic_task) && DISKDUMP_VALID())
 		bt->machdep = &dd->sub_header->elf_regs;
+	else if (KDUMP_CMPRS_VALID() &&
+		 (bt->task == tt->panic_task ||
+		 (is_task_active(bt->task) && dd->num_prstatus_notes > 1))) {
+		int cpu;
+		Elf64_Nhdr *note;
+		size_t len;
+
+		cpu = bt->tc->processor;
+		if (dd->nt_prstatus_percpu[cpu] == NULL) {
+			if(CRASHDEBUG(1))
+				error(INFO,
+				      "registers not collected for cpu %d\n",
+				      cpu);
+		} else {
+			note = (Elf64_Nhdr *)
+				dd->nt_prstatus_percpu[cpu];
+			len = sizeof(Elf64_Nhdr);
+			len = roundup(len + note->n_namesz, 4);
+			bt->machdep = (void *)((char *)note + len +
+				MEMBER_OFFSET("elf_prstatus", "pr_reg"));
+		}
+	}
 
 	machdep->get_stack_frame(bt, eip, esp);
 }
diff --git a/ppc64.c b/ppc64.c
index 8e93979..98ac559 100644
--- a/ppc64.c
+++ b/ppc64.c
@@ -65,19 +65,6 @@ static ulong pgd_page_vaddr_l4(ulong pgd);
 static ulong pud_page_vaddr_l4(ulong pud);
 static ulong pmd_page_vaddr_l4(ulong pmd);
 
-static inline uint get_ptetype(ulong pte)
-{
-	uint pte_type = 0; /* 0: regular entry; 1: huge pte; 2: huge pd */
-
-	if (is_hugepage(pte))
-		pte_type = 1;
-	else if (!(machdep->flags & RADIX_MMU) &&
-	    (PAGESIZE() != PPC64_64K_PAGE_SIZE) && is_hugepd(pte))
-		pte_type = 2;
-
-	return pte_type;
-}
-
 static inline int is_hugepage(ulong pte)
 {
 	if ((machdep->flags & BOOK3E) ||
@@ -128,6 +115,19 @@ static inline int is_hugepd(ulong pte)
 	}
 }
 
+static inline uint get_ptetype(ulong pte)
+{
+	uint pte_type = 0; /* 0: regular entry; 1: huge pte; 2: huge pd */
+
+	if (is_hugepage(pte))
+		pte_type = 1;
+	else if (!(machdep->flags & RADIX_MMU) &&
+	    (PAGESIZE() != PPC64_64K_PAGE_SIZE) && is_hugepd(pte))
+		pte_type = 2;
+
+	return pte_type;
+}
+
 static inline ulong hugepage_dir(ulong pte)
 {
 	if ((machdep->flags & BOOK3E) ||
@@ -2222,21 +2222,11 @@ ppc64_print_eframe(char *efrm_str, struct ppc64_pt_regs *regs,
  * get SP and IP from the saved ptregs.
  */
 static int
-ppc64_kdump_stack_frame(struct bt_info *bt_in, ulong *nip, ulong *ksp)
+ppc64_regs_stack_frame(struct bt_info *bt_in, struct ppc64_pt_regs *pt_regs,
+		       ulong *nip, ulong *ksp)
 {
-	struct ppc64_pt_regs *pt_regs;
 	unsigned long unip;
 
-	pt_regs = (struct ppc64_pt_regs *)bt_in->machdep;
-	if (!pt_regs || !pt_regs->gpr[1]) {
-		/*
-		 * Not collected regs. May be the corresponding CPU not
-		 * responded to an IPI.
-		 */
-		fprintf(fp, "%0lx: GPR1 register value (SP) was not saved\n",
-			bt_in->task);
-		return FALSE;
-	}
 	*ksp = pt_regs->gpr[1];
 	if (IS_KVADDR(*ksp)) {
 		readmem(*ksp+16, KVADDR, &unip, sizeof(ulong), "Regs NIP value",
@@ -2292,10 +2282,20 @@ ppc64_get_dumpfile_stack_frame(struct bt_info *bt_in, ulong *nip, ulong *ksp)
 	struct syment *sp;
 
 	/* 
-	 * For the kdump vmcore, Use SP and IP values that are saved in ptregs.
-	 */ 
-	if (pc->flags & KDUMP)
-		return ppc64_kdump_stack_frame(bt_in, nip, ksp);
+	 * Use SP and IP values that are saved in ptregs.
+	 */
+	pt_regs = (struct ppc64_pt_regs *)bt_in->machdep;
+	if (!pt_regs || !pt_regs->gpr[1]) {
+		/*
+		 * Not collected regs. May be the corresponding CPU did not
+		 * respond to an IPI.
+		 */
+		if (CRASHDEBUG(1))
+			fprintf(fp, "%0lx: GPR1(SP) register value not saved\n",
+				bt_in->task);
+	} else
+		return ppc64_regs_stack_frame(bt_in, pt_regs, nip, ksp);
+
 
         bt = &bt_local;
         BCOPY(bt_in, bt, sizeof(struct bt_info));




More information about the Crash-utility mailing list