|
|
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;
|