|
|
01fc30 |
commit 5fe78861ea1589084f6a2956a6ff63677c9269e1
|
|
|
01fc30 |
Author: Dave Anderson <anderson@redhat.com>
|
|
|
01fc30 |
Date: Fri Sep 7 16:05:52 2018 -0400
|
|
|
01fc30 |
|
|
|
01fc30 |
Commit 3db3d3992d781c1e42587d2d2bf81e785408e0c2 in crash-7.1.8 was
|
|
|
01fc30 |
aimed at making the PPC64 "bt" command work for dumpfiles saved
|
|
|
01fc30 |
with the FADUMP facility, but it introduced a bit of unwarranted
|
|
|
01fc30 |
complexity in "bt" command processing. Reworked the "bt" command
|
|
|
01fc30 |
processing for PPC64 arch to make it a little less compilated and
|
|
|
01fc30 |
also to print symbols for NIP and LR registers in exception frames.
|
|
|
01fc30 |
Without the patch, "bt" on non-panic active tasks may fail with
|
|
|
01fc30 |
the message "bt: invalid kernel virtual address: <address>
|
|
|
01fc30 |
type: Regs NIP value".
|
|
|
01fc30 |
(hbathini@linux.ibm.com)
|
|
|
01fc30 |
|
|
|
01fc30 |
diff --git a/ppc64.c b/ppc64.c
|
|
|
01fc30 |
index f5d0dac..03fecd3 100644
|
|
|
01fc30 |
--- a/ppc64.c
|
|
|
01fc30 |
+++ b/ppc64.c
|
|
|
01fc30 |
@@ -2093,15 +2093,10 @@ ppc64_print_stack_entry(int frame,
|
|
|
01fc30 |
lr);
|
|
|
01fc30 |
return;
|
|
|
01fc30 |
}
|
|
|
01fc30 |
- if (req->pc != lr) {
|
|
|
01fc30 |
- fprintf(fp, "\n%s[Link Register] ",
|
|
|
01fc30 |
- frame < 10 ? " " : "");
|
|
|
01fc30 |
- fprintf(fp, "[%lx] %s at %lx",
|
|
|
01fc30 |
- req->sp, lrname, lr);
|
|
|
01fc30 |
- }
|
|
|
01fc30 |
req->ra = lr;
|
|
|
01fc30 |
}
|
|
|
01fc30 |
- if (!req->name || STREQ(req->name,lrname))
|
|
|
01fc30 |
+ if (!req->name || STREQ(req->name, lrname) ||
|
|
|
01fc30 |
+ !is_kernel_text(req->pc))
|
|
|
01fc30 |
fprintf(fp, " (unreliable)");
|
|
|
01fc30 |
|
|
|
01fc30 |
fprintf(fp, "\n");
|
|
|
01fc30 |
@@ -2219,6 +2214,22 @@ ppc64_print_regs(struct ppc64_pt_regs *regs)
|
|
|
01fc30 |
fprintf(fp, " Syscall Result: %016lx\n", regs->result);
|
|
|
01fc30 |
}
|
|
|
01fc30 |
|
|
|
01fc30 |
+static void ppc64_print_nip_lr(struct ppc64_pt_regs *regs, int print_lr)
|
|
|
01fc30 |
+{
|
|
|
01fc30 |
+ char buf[BUFSIZE];
|
|
|
01fc30 |
+ char *sym_buf;
|
|
|
01fc30 |
+
|
|
|
01fc30 |
+ sym_buf = value_to_symstr(regs->nip, buf, 0);
|
|
|
01fc30 |
+ if (sym_buf[0] != NULLCHAR)
|
|
|
01fc30 |
+ fprintf(fp, " [NIP : %s]\n", sym_buf);
|
|
|
01fc30 |
+
|
|
|
01fc30 |
+ if (print_lr) {
|
|
|
01fc30 |
+ sym_buf = value_to_symstr(regs->link, buf, 0);
|
|
|
01fc30 |
+ if (sym_buf[0] != NULLCHAR)
|
|
|
01fc30 |
+ fprintf(fp, " [LR : %s]\n", sym_buf);
|
|
|
01fc30 |
+ }
|
|
|
01fc30 |
+}
|
|
|
01fc30 |
+
|
|
|
01fc30 |
/*
|
|
|
01fc30 |
* Print the exception frame information
|
|
|
01fc30 |
*/
|
|
|
01fc30 |
@@ -2231,6 +2242,59 @@ ppc64_print_eframe(char *efrm_str, struct ppc64_pt_regs *regs,
|
|
|
01fc30 |
|
|
|
01fc30 |
fprintf(fp, " %s [%lx] exception frame:\n", efrm_str, regs->trap);
|
|
|
01fc30 |
ppc64_print_regs(regs);
|
|
|
01fc30 |
+ ppc64_print_nip_lr(regs, 1);
|
|
|
01fc30 |
+}
|
|
|
01fc30 |
+
|
|
|
01fc30 |
+/*
|
|
|
01fc30 |
+ * For vmcore typically saved with KDump or FADump, get SP and IP values
|
|
|
01fc30 |
+ * from the saved ptregs.
|
|
|
01fc30 |
+ */
|
|
|
01fc30 |
+static int
|
|
|
01fc30 |
+ppc64_vmcore_stack_frame(struct bt_info *bt_in, ulong *nip, ulong *ksp)
|
|
|
01fc30 |
+{
|
|
|
01fc30 |
+ struct ppc64_pt_regs *pt_regs;
|
|
|
01fc30 |
+ unsigned long unip;
|
|
|
01fc30 |
+
|
|
|
01fc30 |
+ pt_regs = (struct ppc64_pt_regs *)bt_in->machdep;
|
|
|
01fc30 |
+ if (!pt_regs || !pt_regs->gpr[1]) {
|
|
|
01fc30 |
+ /*
|
|
|
01fc30 |
+ * Not collected regs. May be the corresponding CPU not
|
|
|
01fc30 |
+ * responded to an IPI in case of KDump OR f/w has not
|
|
|
01fc30 |
+ * not provided the register info in case of FADump.
|
|
|
01fc30 |
+ */
|
|
|
01fc30 |
+ fprintf(fp, "%0lx: GPR1 register value (SP) was not saved\n",
|
|
|
01fc30 |
+ bt_in->task);
|
|
|
01fc30 |
+ return FALSE;
|
|
|
01fc30 |
+ }
|
|
|
01fc30 |
+ *ksp = pt_regs->gpr[1];
|
|
|
01fc30 |
+ if (IS_KVADDR(*ksp)) {
|
|
|
01fc30 |
+ readmem(*ksp+16, KVADDR, &unip, sizeof(ulong), "Regs NIP value",
|
|
|
01fc30 |
+ FAULT_ON_ERROR);
|
|
|
01fc30 |
+ *nip = unip;
|
|
|
01fc30 |
+ } else {
|
|
|
01fc30 |
+ if (IN_TASK_VMA(bt_in->task, *ksp))
|
|
|
01fc30 |
+ fprintf(fp, "%0lx: Task is running in user space\n",
|
|
|
01fc30 |
+ bt_in->task);
|
|
|
01fc30 |
+ else
|
|
|
01fc30 |
+ fprintf(fp, "%0lx: Invalid Stack Pointer %0lx\n",
|
|
|
01fc30 |
+ bt_in->task, *ksp);
|
|
|
01fc30 |
+ *nip = pt_regs->nip;
|
|
|
01fc30 |
+ }
|
|
|
01fc30 |
+
|
|
|
01fc30 |
+ if (bt_in->flags &&
|
|
|
01fc30 |
+ ((BT_TEXT_SYMBOLS|BT_TEXT_SYMBOLS_PRINT|BT_TEXT_SYMBOLS_NOPRINT)))
|
|
|
01fc30 |
+ return TRUE;
|
|
|
01fc30 |
+
|
|
|
01fc30 |
+ /*
|
|
|
01fc30 |
+ * Print the collected regs for the active task
|
|
|
01fc30 |
+ */
|
|
|
01fc30 |
+ ppc64_print_regs(pt_regs);
|
|
|
01fc30 |
+ if (!IS_KVADDR(*ksp))
|
|
|
01fc30 |
+ return FALSE;
|
|
|
01fc30 |
+
|
|
|
01fc30 |
+ ppc64_print_nip_lr(pt_regs, (unip != pt_regs->link) ? 1 : 0);
|
|
|
01fc30 |
+
|
|
|
01fc30 |
+ return TRUE;
|
|
|
01fc30 |
}
|
|
|
01fc30 |
|
|
|
01fc30 |
/*
|
|
|
01fc30 |
@@ -2239,7 +2303,7 @@ ppc64_print_eframe(char *efrm_str, struct ppc64_pt_regs *regs,
|
|
|
01fc30 |
static int
|
|
|
01fc30 |
ppc64_get_dumpfile_stack_frame(struct bt_info *bt_in, ulong *nip, ulong *ksp)
|
|
|
01fc30 |
{
|
|
|
01fc30 |
- int i;
|
|
|
01fc30 |
+ int i, ret, panic_task;
|
|
|
01fc30 |
char *sym;
|
|
|
01fc30 |
ulong *up;
|
|
|
01fc30 |
struct bt_info bt_local, *bt;
|
|
|
01fc30 |
@@ -2251,11 +2315,29 @@ ppc64_get_dumpfile_stack_frame(struct bt_info *bt_in, ulong *nip, ulong *ksp)
|
|
|
01fc30 |
struct ppc64_pt_regs *pt_regs;
|
|
|
01fc30 |
struct syment *sp;
|
|
|
01fc30 |
|
|
|
01fc30 |
- bt = &bt_local;
|
|
|
01fc30 |
- BCOPY(bt_in, bt, sizeof(struct bt_info));
|
|
|
01fc30 |
- ms = machdep->machspec;
|
|
|
01fc30 |
+ bt = &bt_local;
|
|
|
01fc30 |
+ BCOPY(bt_in, bt, sizeof(struct bt_info));
|
|
|
01fc30 |
+ ms = machdep->machspec;
|
|
|
01fc30 |
+ ur_nip = ur_ksp = 0;
|
|
|
01fc30 |
+
|
|
|
01fc30 |
+ panic_task = tt->panic_task == bt->task ? TRUE : FALSE;
|
|
|
01fc30 |
|
|
|
01fc30 |
check_hardirq = check_softirq = tt->flags & IRQSTACKS ? TRUE : FALSE;
|
|
|
01fc30 |
+ if (panic_task && bt->machdep) {
|
|
|
01fc30 |
+ pt_regs = (struct ppc64_pt_regs *)bt->machdep;
|
|
|
01fc30 |
+ ur_nip = pt_regs->nip;
|
|
|
01fc30 |
+ ur_ksp = pt_regs->gpr[1];
|
|
|
01fc30 |
+ } else if ((pc->flags & KDUMP) ||
|
|
|
01fc30 |
+ ((pc->flags & DISKDUMP) &&
|
|
|
01fc30 |
+ (*diskdump_flags & KDUMP_CMPRS_LOCAL))) {
|
|
|
01fc30 |
+ /*
|
|
|
01fc30 |
+ * For the KDump or FADump vmcore, use SP and IP values
|
|
|
01fc30 |
+ * that are saved in ptregs.
|
|
|
01fc30 |
+ */
|
|
|
01fc30 |
+ ret = ppc64_vmcore_stack_frame(bt_in, nip, ksp);
|
|
|
01fc30 |
+ if (ret)
|
|
|
01fc30 |
+ return TRUE;
|
|
|
01fc30 |
+ }
|
|
|
01fc30 |
|
|
|
01fc30 |
if (bt->task != tt->panic_task) {
|
|
|
01fc30 |
char cpu_frozen = FALSE;
|
|
|
01fc30 |
@@ -2385,38 +2467,14 @@ retry:
|
|
|
01fc30 |
check_intrstack = FALSE;
|
|
|
01fc30 |
goto retry;
|
|
|
01fc30 |
}
|
|
|
01fc30 |
-
|
|
|
01fc30 |
/*
|
|
|
01fc30 |
- * We didn't find what we were looking for, so try to use
|
|
|
01fc30 |
- * the SP and IP values saved in ptregs.
|
|
|
01fc30 |
+ * We didn't find what we were looking for, so just use what was
|
|
|
01fc30 |
+ * passed in the ELF header.
|
|
|
01fc30 |
*/
|
|
|
01fc30 |
- pt_regs = (struct ppc64_pt_regs *)bt_in->machdep;
|
|
|
01fc30 |
- if (!pt_regs || !pt_regs->gpr[1]) {
|
|
|
01fc30 |
- /*
|
|
|
01fc30 |
- * Not collected regs. May be the corresponding CPU did not
|
|
|
01fc30 |
- * respond to an IPI.
|
|
|
01fc30 |
- */
|
|
|
01fc30 |
- if (CRASHDEBUG(1))
|
|
|
01fc30 |
- fprintf(fp, "%0lx: GPR1(SP) register value not saved\n",
|
|
|
01fc30 |
- bt_in->task);
|
|
|
01fc30 |
- } else {
|
|
|
01fc30 |
- *ksp = pt_regs->gpr[1];
|
|
|
01fc30 |
- if (IS_KVADDR(*ksp)) {
|
|
|
01fc30 |
- readmem(*ksp+16, KVADDR, nip, sizeof(ulong),
|
|
|
01fc30 |
- "Regs NIP value", FAULT_ON_ERROR);
|
|
|
01fc30 |
- ppc64_print_regs(pt_regs);
|
|
|
01fc30 |
- return TRUE;
|
|
|
01fc30 |
- } else {
|
|
|
01fc30 |
- if (IN_TASK_VMA(bt_in->task, *ksp))
|
|
|
01fc30 |
- fprintf(fp, "%0lx: Task is running in user space\n",
|
|
|
01fc30 |
- bt_in->task);
|
|
|
01fc30 |
- else
|
|
|
01fc30 |
- fprintf(fp, "%0lx: Invalid Stack Pointer %0lx\n",
|
|
|
01fc30 |
- bt_in->task, *ksp);
|
|
|
01fc30 |
- *nip = pt_regs->nip;
|
|
|
01fc30 |
- ppc64_print_regs(pt_regs);
|
|
|
01fc30 |
- return FALSE;
|
|
|
01fc30 |
- }
|
|
|
01fc30 |
+ if (ur_nip && ur_ksp) {
|
|
|
01fc30 |
+ *nip = ur_nip;
|
|
|
01fc30 |
+ *ksp = ur_ksp;
|
|
|
01fc30 |
+ return TRUE;
|
|
|
01fc30 |
}
|
|
|
01fc30 |
|
|
|
01fc30 |
console("ppc64_get_dumpfile_stack_frame: cannot find SP for panic task\n");
|