Blame SOURCES/github_ppc64_5fe78861_7e393689_599a6579_72cc0cba.patch

608733
commit 5fe78861ea1589084f6a2956a6ff63677c9269e1
608733
Author: Dave Anderson <anderson@redhat.com>
608733
Date:   Fri Sep 7 16:05:52 2018 -0400
608733
608733
    Commit 3db3d3992d781c1e42587d2d2bf81e785408e0c2 in crash-7.1.8 was
608733
    aimed at making the PPC64 "bt" command work for dumpfiles saved
608733
    with the FADUMP facility, but it introduced a bit of unwarranted
608733
    complexity in "bt" command processing.  Reworked the "bt" command
608733
    processing for PPC64 arch to make it a little less compilated and
608733
    also to print symbols for NIP and LR registers in exception frames.
608733
    Without the patch, "bt" on non-panic active tasks may fail with
608733
    the message "bt: invalid kernel virtual address: <address>
608733
    type: Regs NIP value".
608733
    (hbathini@linux.ibm.com)
608733
608733
diff --git a/ppc64.c b/ppc64.c
608733
index f5d0dac..03fecd3 100644
608733
--- a/ppc64.c
608733
+++ b/ppc64.c
608733
@@ -2093,15 +2093,10 @@ ppc64_print_stack_entry(int frame,
608733
 					lr);
608733
 				return;
608733
 			}
608733
-			if (req->pc != lr) {
608733
-				fprintf(fp, "\n%s[Link Register] ", 
608733
-					frame < 10 ? " " : "");
608733
-				fprintf(fp, "[%lx] %s at %lx",
608733
-					req->sp, lrname, lr);
608733
-			}
608733
 			req->ra = lr;
608733
 		}
608733
-		if (!req->name || STREQ(req->name,lrname)) 
608733
+		if (!req->name || STREQ(req->name, lrname) ||
608733
+		    !is_kernel_text(req->pc))
608733
 			fprintf(fp, "  (unreliable)");
608733
 		
608733
 		fprintf(fp, "\n"); 
608733
@@ -2219,6 +2214,22 @@ ppc64_print_regs(struct ppc64_pt_regs *regs)
608733
         fprintf(fp, "    Syscall Result: %016lx\n", regs->result);
608733
 }
608733
 
608733
+static void ppc64_print_nip_lr(struct ppc64_pt_regs *regs, int print_lr)
608733
+{
608733
+	char buf[BUFSIZE];
608733
+	char *sym_buf;
608733
+
608733
+	sym_buf = value_to_symstr(regs->nip, buf, 0);
608733
+	if (sym_buf[0] != NULLCHAR)
608733
+		fprintf(fp, " [NIP  : %s]\n", sym_buf);
608733
+
608733
+	if (print_lr) {
608733
+		sym_buf = value_to_symstr(regs->link, buf, 0);
608733
+		if (sym_buf[0] != NULLCHAR)
608733
+			fprintf(fp, " [LR   : %s]\n", sym_buf);
608733
+	}
608733
+}
608733
+
608733
 /*
608733
  * Print the exception frame information
608733
  */
608733
@@ -2231,6 +2242,59 @@ ppc64_print_eframe(char *efrm_str, struct ppc64_pt_regs *regs,
608733
 
608733
 	fprintf(fp, " %s [%lx] exception frame:\n", efrm_str, regs->trap);
608733
 	ppc64_print_regs(regs);
608733
+	ppc64_print_nip_lr(regs, 1);
608733
+}
608733
+
608733
+/*
608733
+ * For vmcore typically saved with KDump or FADump, get SP and IP values
608733
+ * from the saved ptregs.
608733
+ */
608733
+static int
608733
+ppc64_vmcore_stack_frame(struct bt_info *bt_in, ulong *nip, ulong *ksp)
608733
+{
608733
+	struct ppc64_pt_regs *pt_regs;
608733
+	unsigned long unip;
608733
+
608733
+	pt_regs = (struct ppc64_pt_regs *)bt_in->machdep;
608733
+	if (!pt_regs || !pt_regs->gpr[1]) {
608733
+		/*
608733
+		 * Not collected regs. May be the corresponding CPU not
608733
+		 * responded to an IPI in case of KDump OR f/w has not
608733
+		 * not provided the register info in case of FADump.
608733
+		 */
608733
+		fprintf(fp, "%0lx: GPR1 register value (SP) was not saved\n",
608733
+			bt_in->task);
608733
+		return FALSE;
608733
+	}
608733
+	*ksp = pt_regs->gpr[1];
608733
+	if (IS_KVADDR(*ksp)) {
608733
+		readmem(*ksp+16, KVADDR, &unip, sizeof(ulong), "Regs NIP value",
608733
+			FAULT_ON_ERROR);
608733
+		*nip = unip;
608733
+	} else {
608733
+		if (IN_TASK_VMA(bt_in->task, *ksp))
608733
+			fprintf(fp, "%0lx: Task is running in user space\n",
608733
+				bt_in->task);
608733
+		else
608733
+			fprintf(fp, "%0lx: Invalid Stack Pointer %0lx\n",
608733
+				bt_in->task, *ksp);
608733
+		*nip = pt_regs->nip;
608733
+	}
608733
+
608733
+	if (bt_in->flags &&
608733
+	((BT_TEXT_SYMBOLS|BT_TEXT_SYMBOLS_PRINT|BT_TEXT_SYMBOLS_NOPRINT)))
608733
+		return TRUE;
608733
+
608733
+	/*
608733
+	 * Print the collected regs for the active task
608733
+	 */
608733
+	ppc64_print_regs(pt_regs);
608733
+	if (!IS_KVADDR(*ksp))
608733
+		return FALSE;
608733
+
608733
+	ppc64_print_nip_lr(pt_regs, (unip != pt_regs->link) ? 1 : 0);
608733
+
608733
+	return TRUE;
608733
 }
608733
 
608733
 /*
608733
@@ -2239,7 +2303,7 @@ ppc64_print_eframe(char *efrm_str, struct ppc64_pt_regs *regs,
608733
 static int
608733
 ppc64_get_dumpfile_stack_frame(struct bt_info *bt_in, ulong *nip, ulong *ksp)
608733
 {
608733
-	int i;
608733
+	int i, ret, panic_task;
608733
 	char *sym;
608733
 	ulong *up;
608733
 	struct bt_info bt_local, *bt;
608733
@@ -2251,11 +2315,29 @@ ppc64_get_dumpfile_stack_frame(struct bt_info *bt_in, ulong *nip, ulong *ksp)
608733
 	struct ppc64_pt_regs *pt_regs;
608733
 	struct syment *sp;
608733
 
608733
-        bt = &bt_local;
608733
-        BCOPY(bt_in, bt, sizeof(struct bt_info));
608733
-        ms = machdep->machspec;
608733
+	bt = &bt_local;
608733
+	BCOPY(bt_in, bt, sizeof(struct bt_info));
608733
+	ms = machdep->machspec;
608733
+	ur_nip = ur_ksp = 0;
608733
+
608733
+	panic_task = tt->panic_task == bt->task ? TRUE : FALSE;
608733
 
608733
 	check_hardirq = check_softirq = tt->flags & IRQSTACKS ? TRUE : FALSE;
608733
+	if (panic_task && bt->machdep) {
608733
+		pt_regs = (struct ppc64_pt_regs *)bt->machdep;
608733
+		ur_nip = pt_regs->nip;
608733
+		ur_ksp = pt_regs->gpr[1];
608733
+	} else if ((pc->flags & KDUMP) ||
608733
+		   ((pc->flags & DISKDUMP) &&
608733
+		    (*diskdump_flags & KDUMP_CMPRS_LOCAL))) {
608733
+		/*
608733
+		 * For the KDump or FADump vmcore, use SP and IP values
608733
+		 * that are saved in ptregs.
608733
+		 */
608733
+		ret = ppc64_vmcore_stack_frame(bt_in, nip, ksp);
608733
+		if (ret)
608733
+			return TRUE;
608733
+	}
608733
 
608733
 	if (bt->task != tt->panic_task) {
608733
 		char cpu_frozen = FALSE;
608733
@@ -2385,38 +2467,14 @@ retry:
608733
 		check_intrstack = FALSE;
608733
 		goto retry;
608733
 	}
608733
-
608733
 	/*
608733
-	 * We didn't find what we were looking for, so try to use
608733
-	 * the SP and IP values saved in ptregs.
608733
+	 *  We didn't find what we were looking for, so just use what was
608733
+	 *  passed in the ELF header.
608733
 	 */
608733
-	pt_regs = (struct ppc64_pt_regs *)bt_in->machdep;
608733
-	if (!pt_regs || !pt_regs->gpr[1]) {
608733
-		/*
608733
-		 * Not collected regs. May be the corresponding CPU did not
608733
-		 * respond to an IPI.
608733
-		 */
608733
-		if (CRASHDEBUG(1))
608733
-			fprintf(fp, "%0lx: GPR1(SP) register value not saved\n",
608733
-				bt_in->task);
608733
-	} else {
608733
-		*ksp = pt_regs->gpr[1];
608733
-		if (IS_KVADDR(*ksp)) {
608733
-			readmem(*ksp+16, KVADDR, nip, sizeof(ulong),
608733
-				"Regs NIP value", FAULT_ON_ERROR);
608733
-			ppc64_print_regs(pt_regs);
608733
-			return TRUE;
608733
-		} else {
608733
-			if (IN_TASK_VMA(bt_in->task, *ksp))
608733
-				fprintf(fp, "%0lx: Task is running in user space\n",
608733
-					bt_in->task);
608733
-			else
608733
-				fprintf(fp, "%0lx: Invalid Stack Pointer %0lx\n",
608733
-					bt_in->task, *ksp);
608733
-			*nip = pt_regs->nip;
608733
-			ppc64_print_regs(pt_regs);
608733
-			return FALSE;
608733
-		}
608733
+	if (ur_nip && ur_ksp) {
608733
+		*nip = ur_nip;
608733
+		*ksp = ur_ksp;
608733
+		return TRUE;
608733
 	}
608733
 
608733
         console("ppc64_get_dumpfile_stack_frame: cannot find SP for panic task\n");
608733
commit 7e3936895386ea6e85a6dc01bc5027f8133d12bb
608733
Author: Dave Anderson <anderson@redhat.com>
608733
Date:   Mon Sep 17 14:33:08 2018 -0400
608733
608733
    An addendum to crash commit 5fe78861ea1589084f6a2956a6ff63677c9269e1,
608733
    this patch for the PPC64 "bt" command prevents an invalid error
608733
    message from being displayed when an active non-panic task is
608733
    interrupted while running in user space.  Without the patch, the
608733
    command correctly indicates "Task is running in user space", dumps
608733
    the user-space exception frame, but then prints the invalid error
608733
    message "bt: invalid kernel virtual address: ffffffffffffff90 type:
608733
    Regs NIP value".
608733
    (anderson@redhat.com)
608733
608733
diff --git a/ppc64.c b/ppc64.c
608733
index 03fecd3..8badcde 100644
608733
--- a/ppc64.c
608733
+++ b/ppc64.c
608733
@@ -2254,6 +2254,7 @@ ppc64_vmcore_stack_frame(struct bt_info *bt_in, ulong *nip, ulong *ksp)
608733
 {
608733
 	struct ppc64_pt_regs *pt_regs;
608733
 	unsigned long unip;
608733
+	int in_user_space = FALSE;
608733
 
608733
 	pt_regs = (struct ppc64_pt_regs *)bt_in->machdep;
608733
 	if (!pt_regs || !pt_regs->gpr[1]) {
608733
@@ -2272,10 +2273,11 @@ ppc64_vmcore_stack_frame(struct bt_info *bt_in, ulong *nip, ulong *ksp)
608733
 			FAULT_ON_ERROR);
608733
 		*nip = unip;
608733
 	} else {
608733
-		if (IN_TASK_VMA(bt_in->task, *ksp))
608733
+		if (IN_TASK_VMA(bt_in->task, *ksp)) {
608733
 			fprintf(fp, "%0lx: Task is running in user space\n",
608733
 				bt_in->task);
608733
-		else
608733
+			in_user_space = TRUE;
608733
+		} else
608733
 			fprintf(fp, "%0lx: Invalid Stack Pointer %0lx\n",
608733
 				bt_in->task, *ksp);
608733
 		*nip = pt_regs->nip;
608733
@@ -2289,6 +2291,8 @@ ppc64_vmcore_stack_frame(struct bt_info *bt_in, ulong *nip, ulong *ksp)
608733
 	 * Print the collected regs for the active task
608733
 	 */
608733
 	ppc64_print_regs(pt_regs);
608733
+	if (in_user_space)
608733
+		return TRUE;
608733
 	if (!IS_KVADDR(*ksp))
608733
 		return FALSE;
608733
 
608733
commit 599a6579aa916df7800f8e889d68e4287e4520dd
608733
Author: Dave Anderson <anderson@redhat.com>
608733
Date:   Thu Sep 27 14:14:31 2018 -0400
608733
608733
    With Linux 4.19-rc1 commit 7d4340bb92a9df78e6e28152f3dd89d9bd82146b,
608733
    titled "powerpc/mm: Increase MAX_PHYSMEM_BITS to 128TB with
608733
    SPARSEMEM_VMEMMAP config", the PPC64 MAX_PHYSMEM_BITS value has
608733
    been bumped up to 47.  The appropriate update has been made in
608733
    this patch.
608733
    (hbathini@linux.ibm.com)
608733
608733
diff --git a/defs.h b/defs.h
608733
index 80c61ef..5b64bb7 100644
608733
--- a/defs.h
608733
+++ b/defs.h
608733
@@ -4054,6 +4054,7 @@ struct efi_memory_desc_t {
608733
 #define _SECTION_SIZE_BITS	24
608733
 #define _MAX_PHYSMEM_BITS	44
608733
 #define _MAX_PHYSMEM_BITS_3_7   46
608733
+#define _MAX_PHYSMEM_BITS_4_19  47
608733
 
608733
 #endif /* PPC64 */
608733
 
608733
diff --git a/ppc64.c b/ppc64.c
608733
index 8badcde..ee2f76f 100644
608733
--- a/ppc64.c
608733
+++ b/ppc64.c
608733
@@ -554,7 +554,10 @@ ppc64_init(int when)
608733
 			ppc64_vmemmap_init();
608733
 
608733
 		machdep->section_size_bits = _SECTION_SIZE_BITS;
608733
-		if (THIS_KERNEL_VERSION >= LINUX(3,7,0))
608733
+		if ((machdep->flags & VMEMMAP) &&
608733
+		    (THIS_KERNEL_VERSION >= LINUX(4,19,0)))
608733
+			machdep->max_physmem_bits = _MAX_PHYSMEM_BITS_4_19;
608733
+		else if (THIS_KERNEL_VERSION >= LINUX(3,7,0))
608733
 			machdep->max_physmem_bits = _MAX_PHYSMEM_BITS_3_7;
608733
 		else
608733
 			machdep->max_physmem_bits = _MAX_PHYSMEM_BITS;
608733
608733
608733
commit 72cc0cba8a6cab14ca0961dff062d0384d307ce5
608733
Author: Dave Anderson <anderson@redhat.com>
608733
Date:   Tue Oct 2 10:56:28 2018 -0400
608733
608733
    Fix for the PPC64 "bt" command to recognize when a thread is running
608733
    in OPAL firmware.  Without the patch, the "bt" command indicates
608733
    <task-address>: Invalid Stack Pointer <OPAL-firmware-address>"
608733
    (hbathini@linux.ibm.com)
608733
608733
--- a/defs.h
608733
+++ b/defs.h
608733
@@ -5934,6 +5934,12 @@ struct ppc64_elf_prstatus {
608733
 
608733
 #ifdef PPC64
608733
 
608733
+struct ppc64_opal {
608733
+	uint64_t base;
608733
+	uint64_t entry;
608733
+	uint64_t size;
608733
+};
608733
+
608733
 struct ppc64_vmemmap {
608733
         unsigned long phys;
608733
         unsigned long virt;
608733
@@ -5984,6 +5990,7 @@ struct machine_specific {
608733
 	ulong _page_accessed;
608733
 	int (*is_kvaddr)(ulong);
608733
 	int (*is_vmaddr)(ulong);
608733
+	struct ppc64_opal opal;
608733
 };
608733
 
608733
 void ppc64_init(int);
608733
@@ -6001,6 +6008,7 @@ void ppc64_dump_machdep_table(ulong);
608733
  * in the kernel is also 0x40.
608733
  */
608733
 #define RADIX_MMU       (0x40)
608733
+#define OPAL_FW         (0x80)
608733
 
608733
 #define REGION_SHIFT       (60UL)
608733
 #define REGION_ID(addr)    (((unsigned long)(addr)) >> REGION_SHIFT)
608733
--- a/ppc64.c
608733
+++ b/ppc64.c
608733
@@ -65,8 +65,26 @@ static ulong hugepage_dir(ulong pte);
608733
 static ulong pgd_page_vaddr_l4(ulong pgd);
608733
 static ulong pud_page_vaddr_l4(ulong pud);
608733
 static ulong pmd_page_vaddr_l4(ulong pmd);
608733
+static int is_opal_context(ulong sp, ulong nip);
608733
 void opalmsg(void);
608733
 
608733
+static int is_opal_context(ulong sp, ulong nip)
608733
+{
608733
+	uint64_t opal_start, opal_end;
608733
+
608733
+	if (!(machdep->flags & OPAL_FW))
608733
+		return FALSE;
608733
+
608733
+	opal_start = machdep->machspec->opal.base;
608733
+	opal_end   = opal_start + machdep->machspec->opal.size;
608733
+
608733
+	if (((sp >= opal_start) && (sp < opal_end)) ||
608733
+	    ((nip >= opal_start) && (nip < opal_end)))
608733
+		return TRUE;
608733
+
608733
+	return FALSE;
608733
+}
608733
+
608733
 static inline int is_hugepage(ulong pte)
608733
 {
608733
 	if ((machdep->flags & BOOK3E) ||
608733
@@ -241,6 +259,7 @@ struct machine_specific book3e_machine_s
608733
 	.is_vmaddr = book3e_is_vmaddr,
608733
 };
608733
 
608733
+#define SKIBOOT_BASE			0x30000000
608733
 
608733
 /*
608733
  *  Do all necessary machine-specific setup here.  This is called several
608733
@@ -362,6 +381,16 @@ ppc64_init(int when)
608733
 			struct machine_specific *m = machdep->machspec;
608733
 
608733
 			/*
608733
+			 * To determine if the kernel was running on OPAL based platform,
608733
+			 * use struct opal, which is populated with relevant values.
608733
+			 */
608733
+			if (symbol_exists("opal")) {
608733
+				get_symbol_data("opal", sizeof(struct ppc64_opal), &(m->opal));
608733
+				if (m->opal.base == SKIBOOT_BASE)
608733
+					machdep->flags |= OPAL_FW;
608733
+			}
608733
+
608733
+			/*
608733
 			 * On Power ISA 3.0 based server processors, a kernel can
608733
 			 * run with radix MMU or standard MMU. Set the flag,
608733
 			 * if it is radix MMU.
608733
@@ -712,6 +741,8 @@ ppc64_dump_machdep_table(ulong arg)
608733
 		fprintf(fp, "%sSWAP_ENTRY_L4", others++ ? "|" : "");
608733
 	if (machdep->flags & RADIX_MMU)
608733
 		fprintf(fp, "%sRADIX_MMU", others++ ? "|" : "");
608733
+	if (machdep->flags & OPAL_FW)
608733
+		fprintf(fp, "%sOPAL_FW", others++ ? "|" : "");
608733
         fprintf(fp, ")\n");
608733
 
608733
 	fprintf(fp, "             kvbase: %lx\n", machdep->kvbase);
608733
@@ -2257,7 +2288,11 @@ ppc64_vmcore_stack_frame(struct bt_info
608733
 {
608733
 	struct ppc64_pt_regs *pt_regs;
608733
 	unsigned long unip;
608733
-	int in_user_space = FALSE;
608733
+	/*
608733
+	 * TRUE: task is running in a different context (userspace, OPAL..)
608733
+	 * FALSE: task is probably running in kernel space.
608733
+	 */
608733
+	int out_of_context = FALSE;
608733
 
608733
 	pt_regs = (struct ppc64_pt_regs *)bt_in->machdep;
608733
 	if (!pt_regs || !pt_regs->gpr[1]) {
608733
@@ -2270,20 +2305,25 @@ ppc64_vmcore_stack_frame(struct bt_info
608733
 			bt_in->task);
608733
 		return FALSE;
608733
 	}
608733
+
608733
 	*ksp = pt_regs->gpr[1];
608733
 	if (IS_KVADDR(*ksp)) {
608733
 		readmem(*ksp+16, KVADDR, &unip, sizeof(ulong), "Regs NIP value",
608733
 			FAULT_ON_ERROR);
608733
 		*nip = unip;
608733
 	} else {
608733
+		*nip = pt_regs->nip;
608733
 		if (IN_TASK_VMA(bt_in->task, *ksp)) {
608733
 			fprintf(fp, "%0lx: Task is running in user space\n",
608733
 				bt_in->task);
608733
-			in_user_space = TRUE;
608733
+			out_of_context = TRUE;
608733
+		} else if (is_opal_context(*ksp, *nip)) {
608733
+			fprintf(fp, "%0lx: Task is running in OPAL (firmware) context\n",
608733
+				bt_in->task);
608733
+			out_of_context = TRUE;
608733
 		} else
608733
 			fprintf(fp, "%0lx: Invalid Stack Pointer %0lx\n",
608733
 				bt_in->task, *ksp);
608733
-		*nip = pt_regs->nip;
608733
 	}
608733
 
608733
 	if (bt_in->flags &&
608733
@@ -2294,7 +2334,8 @@ ppc64_vmcore_stack_frame(struct bt_info
608733
 	 * Print the collected regs for the active task
608733
 	 */
608733
 	ppc64_print_regs(pt_regs);
608733
-	if (in_user_space)
608733
+
608733
+	if (out_of_context)
608733
 		return TRUE;
608733
 	if (!IS_KVADDR(*ksp))
608733
 		return FALSE;
608733
@@ -2828,7 +2869,6 @@ ppc64_get_smp_cpus(void)
608733
  */
608733
 #define SKIBOOT_CONSOLE_DUMP_START	0x31000000
608733
 #define SKIBOOT_CONSOLE_DUMP_SIZE	0x100000
608733
-#define SKIBOOT_BASE			0x30000000
608733
 #define ASCII_UNLIMITED ((ulong)(-1) >> 1)
608733
 
608733
 void
608733
@@ -2841,10 +2881,6 @@ opalmsg(void)
608733
 		uint64_t u64;
608733
 		uint64_t limit64;
608733
 	};
608733
-	struct opal {
608733
-		unsigned long long base;
608733
-		unsigned long long entry;
608733
-	} opal;
608733
 	int i, a;
608733
 	size_t typesz;
608733
 	void *location;
608733
@@ -2856,25 +2892,13 @@ opalmsg(void)
608733
 	long count = SKIBOOT_CONSOLE_DUMP_SIZE;
608733
 	ulonglong addr = SKIBOOT_CONSOLE_DUMP_START;
608733
 
608733
+	if (!(machdep->flags & OPAL_FW))
608733
+		error(FATAL, "dump was not captured on OPAL based system");
608733
+
608733
 	if (CRASHDEBUG(4))
608733
 		fprintf(fp, "<addr: %llx count: %ld (%s)>\n",
608733
 				addr, count, "PHYSADDR");
608733
 
608733
-	/*
608733
-	 * OPAL based platform check
608733
-	 * struct opal of BSS section and hence default value will be ZERO(0)
608733
-	 * opal_init() in the kernel initializes this structure based on
608733
-	 * the platform. Use it as a key to determine whether the dump
608733
-	 * was taken on an OPAL based system or not.
608733
-	 */
608733
-	if (symbol_exists("opal")) {
608733
-		get_symbol_data("opal", sizeof(struct opal), &opal;;
608733
-		if (opal.base != SKIBOOT_BASE)
608733
-			error(FATAL, "dump was captured on non-PowerNV machine");
608733
-	} else {
608733
-		error(FATAL, "dump was captured on non-PowerNV machine");
608733
-	}
608733
-
608733
 	BZERO(&mem, sizeof(struct memloc));
608733
 	lost = typesz = per_line = 0;
608733
 	location = NULL;