Without this patch, backtraces of active tasks maybe be of the form
"#0 [c0000000700b3a90] (null) at c0000000700b3b50 (unreliable)" for
kernel dumps captured with fadump. This patch uses the ptregs saved
for active tasks before falling back to stack-search method.
Signed-off-by: Hari Bathini <hbathini(a)linux.vnet.ibm.com>
---
Changes from v1:
* Ensured that bt output doesn't change for active tasks for kdump and
panic task for kdump & fadump while fixing the output for active tasks
in case of fadump.
diskdump.c | 22 ++++++++++
ppc64.c | 134 +++++++++++++++++++++---------------------------------------
2 files changed, 68 insertions(+), 88 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..970b2a1 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) ||
@@ -2219,60 +2219,6 @@ 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)
-{
- 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",
- FAULT_ON_ERROR);
- *nip = unip;
- } else {
- if (IN_TASK_VMA(bt_in->task, *ksp))
- fprintf(fp, "%0lx: Task is running in user space\n",
- bt_in->task);
- else
- fprintf(fp, "%0lx: Invalid Stack Pointer %0lx\n",
- bt_in->task, *ksp);
- *nip = pt_regs->nip;
- }
-
- if (bt_in->flags &&
- ((BT_TEXT_SYMBOLS|BT_TEXT_SYMBOLS_PRINT|BT_TEXT_SYMBOLS_NOPRINT)))
- return TRUE;
-
- /*
- * Print the collected regs for the active task
- */
- ppc64_print_regs(pt_regs);
- if (!IS_KVADDR(*ksp))
- return FALSE;
-
- fprintf(fp, " NIP [%016lx] %s\n", pt_regs->nip,
- closest_symbol(pt_regs->nip));
- if (unip != pt_regs->link)
- fprintf(fp, " LR [%016lx] %s\n", pt_regs->link,
- closest_symbol(pt_regs->link));
-
- return TRUE;
-}
-
-/*
* Get the starting point for the active cpus in a diskdump/netdump.
*/
static int
@@ -2291,25 +2237,14 @@ ppc64_get_dumpfile_stack_frame(struct bt_info *bt_in, ulong *nip,
ulong *ksp)
struct ppc64_pt_regs *pt_regs;
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);
-
bt = &bt_local;
BCOPY(bt_in, bt, sizeof(struct bt_info));
ms = machdep->machspec;
- ur_nip = ur_ksp = 0;
-
- panic_task = tt->panic_task == bt->task ? TRUE : FALSE;
+ panic_task = tt->panic_task == bt->task ? TRUE : FALSE;
check_hardirq = check_softirq = tt->flags & IRQSTACKS ? TRUE : FALSE;
- if (panic_task && bt->machdep) {
- pt_regs = (struct ppc64_pt_regs *)bt->machdep;
- ur_nip = pt_regs->nip;
- ur_ksp = pt_regs->gpr[1];
- } else if (bt->task != tt->panic_task) {
+
+ if (bt->task != tt->panic_task) {
char cpu_frozen = FALSE;
/*
* Determine whether the CPU responded to an IPI.
@@ -2428,15 +2363,38 @@ retry:
alter_stackbuf(bt);
check_intrstack = FALSE;
goto retry;
- }
+ }
+
/*
- * We didn't find what we were looking for, so just use what was
- * passed in the ELF header.
+ * We didn't find what we were looking for, so try to use
+ * the SP and IP values saved in ptregs.
*/
- if (ur_nip && ur_ksp) {
- *nip = ur_nip;
- *ksp = ur_ksp;
- return TRUE;
+ 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 {
+ *ksp = pt_regs->gpr[1];
+ if (IS_KVADDR(*ksp)) {
+ readmem(*ksp+16, KVADDR, nip, sizeof(ulong),
+ "Regs NIP value", FAULT_ON_ERROR);
+ return TRUE;
+ } else {
+ if (IN_TASK_VMA(bt_in->task, *ksp))
+ fprintf(fp, "%0lx: Task is running in user space\n",
+ bt_in->task);
+ else
+ fprintf(fp, "%0lx: Invalid Stack Pointer %0lx\n",
+ bt_in->task, *ksp);
+ *nip = pt_regs->nip;
+ ppc64_print_regs(pt_regs);
+ return FALSE;
+ }
}
console("ppc64_get_dumpfile_stack_frame: cannot find SP for panic
task\n");