Fix fatal problems in PPC

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello Dave,

I'm trying to use crash configured with PPC on linux-2.6.27 powerpc.
And when crash started with /dev/mem, I found some problems and fixed them.

I'm afraid that PPC32 is now not maintained for long time,
most people use PPC64 only?
I don't know true reason but if possible, please check attached patch set.

Report of problems which I met as below:
[problem 1] Display type mismatch WARNING
   WARNING: machine type mismatch:
            crash utility: PPC
            vmlinux: (unknown)
-> Simply lacking of verification, remove WARNING with 0001

[problem 2] Display vmalloc fault WARNING
   WARNING: cannot access vmalloc'd module memory
-> PTE index was wrong, fix with 0002

[problem 3] Repeat "invalid task address in pid_hash:" 500 times
   crash: invalid task address in pid_hash: c8818450
-> Alignment check was too old, fix with 0003

[problem 4] bt command is always SEGV while accessing stack frame
-> Similar to problem 3, fix with 0004

I continue to test the basic command regressions or
update PPC implementation by learning from PPC64.

Thanks,
Toshi
>From 7093d0859d3e09eb1c4b96255aacbbeca536eb01 Mon Sep 17 00:00:00 2001
From: Toshikazu Nakayama <nakayama.ts@xxxxxxxxxxxxxx>
Date: Mon, 24 Oct 2011 17:08:11 +0900
Subject: [PATCH 1/4] Be possible to verify EM_PPC kernel

Add the machine type of EM_PPC at is_kernel().

Signed-off-by: Toshikazu Nakayama <nakayama.ts@xxxxxxxxxxxxxx>
---
 symbols.c |    5 +++++
 1 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/symbols.c b/symbols.c
index 3b7b3f0..ce5fc7e 100755
--- a/symbols.c
+++ b/symbols.c
@@ -2906,6 +2906,11 @@ is_kernel(char *file)
 				goto bailout;
 			break;
 
+		case EM_PPC:
+			if (machine_type_mismatch(file, "PPC", NULL, 0))
+				goto bailout;
+			break;
+
 		default:
 			if (machine_type_mismatch(file, "(unknown)", NULL, 0))
 				goto bailout;
-- 
1.7.7.rc0.72.g4b5ea

>From 985d1cceaf2aa7fdde84140317c57e91cd809571 Mon Sep 17 00:00:00 2001
From: Toshikazu Nakayama <nakayama.ts@xxxxxxxxxxxxxx>
Date: Mon, 24 Oct 2011 17:12:55 +0900
Subject: [PATCH 2/4] ppc: fix corrupted PTE translation

The PTE index value is set with (ulong) cast.
Must be with (ulong *).

Signed-off-by: Toshikazu Nakayama <nakayama.ts@xxxxxxxxxxxxxx>
---
 ppc.c |   14 ++++++++------
 1 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/ppc.c b/ppc.c
index 4223ca2..f3d8646 100755
--- a/ppc.c
+++ b/ppc.c
@@ -300,9 +300,10 @@ ppc_uvtop(struct task_context *tc, ulong vaddr, physaddr_t *paddr, int verbose)
 
 	if (machdep->flags & CPU_BOOKE)
 		page_table = page_middle + (BTOP(vaddr) & (PTRS_PER_PTE - 1));
-	else
-		page_table = (ulong *)(((pgd_pte & (ulong)machdep->pagemask) + machdep->kvbase) +
-			((ulong)BTOP(vaddr) & (PTRS_PER_PTE-1)));
+	else {
+		page_table = (ulong *)((pgd_pte & (ulong)machdep->pagemask) + machdep->kvbase);
+		page_table += ((ulong)BTOP(vaddr) & (PTRS_PER_PTE-1));
+	}
 
 	if (verbose)
 		fprintf(fp, "  PMD: %lx => %lx\n",(ulong)page_middle, 
@@ -388,9 +389,10 @@ ppc_kvtop(struct task_context *tc, ulong kvaddr, physaddr_t *paddr, int verbose)
 
 	if (machdep->flags & CPU_BOOKE)
 		page_table = page_middle + (BTOP(kvaddr) & (PTRS_PER_PTE - 1));
-	else
-		page_table = (ulong *)(((pgd_pte & (ulong)machdep->pagemask) + machdep->kvbase) +
-			((ulong)BTOP(kvaddr) & (PTRS_PER_PTE-1)));
+	else {
+		page_table = (ulong *)((pgd_pte & (ulong)machdep->pagemask) + machdep->kvbase);
+		page_table += ((ulong)BTOP(kvaddr) & (PTRS_PER_PTE-1));
+	}
 
 	if (verbose)
 		fprintf(fp, "  PMD: %lx => %lx\n", (ulong)page_middle, 
-- 
1.7.7.rc0.72.g4b5ea

>From 4147834bf6756e428fa4b9b923dccb7414762670 Mon Sep 17 00:00:00 2001
From: Toshikazu Nakayama <nakayama.ts@xxxxxxxxxxxxxx>
Date: Mon, 24 Oct 2011 17:34:02 +0900
Subject: [PATCH 3/4] ppc: update ppc_is_task_addr()

If (tt->flags & THREAD_INFO), task_struct is not stacksize-aligned.
Fix like x86.

Signed-off-by: Toshikazu Nakayama <nakayama.ts@xxxxxxxxxxxxxx>
---
 ppc.c |    7 +++++--
 1 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/ppc.c b/ppc.c
index f3d8646..2bc1562 100755
--- a/ppc.c
+++ b/ppc.c
@@ -436,7 +436,8 @@ ppc_vmalloc_start(void)
 }
 
 /*
- *  PPC allows the idle_task to be non-page aligned, so we have to make
+ *  PPC tasks are all stacksize-aligned, except when split from the stack.
+ *  PPC also allows the idle_task to be non-page aligned, so we have to make
  *  an additional check through the idle_threads array.
  */
 static int
@@ -444,7 +445,9 @@ ppc_is_task_addr(ulong task)
 {
 	int i;
 
-        if (IS_KVADDR(task) && (ALIGNED_STACK_OFFSET(task) == 0))
+	if (tt->flags & THREAD_INFO)
+		return IS_KVADDR(task);
+	else if (IS_KVADDR(task) && (ALIGNED_STACK_OFFSET(task) == 0))
 		return TRUE;
 
 	for (i = 0; i < kt->cpus; i++)
-- 
1.7.7.rc0.72.g4b5ea

>From 693aaab8cfb4fa98c6410a7fed0af7666921a7ba Mon Sep 17 00:00:00 2001
From: Toshikazu Nakayama <nakayama.ts@xxxxxxxxxxxxxx>
Date: Mon, 24 Oct 2011 17:40:29 +0900
Subject: [PATCH 4/4] ppc: update get_ppc_frame()

If (tt->flags & THREAD_INFO), backtrace got SEGV.
Don't use task pointer with stack base.
Apply reading pt_regs to instruction get, definie frame overhead and stack
size macros, skip __switch_to frame in bt, like PPC64.

Signed-off-by: Toshikazu Nakayama <nakayama.ts@xxxxxxxxxxxxxx>
---
 defs.h |    3 +++
 ppc.c  |   50 ++++++++++++++++++++++++++++----------------------
 2 files changed, 31 insertions(+), 22 deletions(-)

diff --git a/defs.h b/defs.h
index a9a158d..d6231e1 100755
--- a/defs.h
+++ b/defs.h
@@ -2610,6 +2610,9 @@ struct load_module {
 #define _SECTION_SIZE_BITS	24
 #define _MAX_PHYSMEM_BITS	44
 
+#define STACK_FRAME_OVERHEAD	16
+#define PPC_STACK_SIZE		8192
+
 #endif  /* PPC */
 
 #ifdef IA64
diff --git a/ppc.c b/ppc.c
index 2bc1562..a8e7193 100755
--- a/ppc.c
+++ b/ppc.c
@@ -64,7 +64,7 @@ ppc_init(int when)
                 machdep->pageshift = ffs(machdep->pagesize) - 1;
                 machdep->pageoffset = machdep->pagesize - 1;
                 machdep->pagemask = ~((ulonglong)machdep->pageoffset);
-		machdep->stacksize = machdep->pagesize * 2;
+		machdep->stacksize = PPC_STACK_SIZE;
                 if ((machdep->pgd = (char *)malloc(PAGESIZE())) == NULL)
                         error(FATAL, "cannot malloc pgd space.");
                 machdep->pmd = machdep->pgd;
@@ -1023,7 +1023,9 @@ get_ppc_frame(struct bt_info *bt, ulong *getpc, ulong *getsp)
 	ulong offset;
 	ulong *stack;
 	ulong task;
+	struct ppc_pt_regs regs;
 
+	ip = 0;
 	task = bt->task;
 	stack = (ulong *)bt->stackbuf;
 
@@ -1036,27 +1038,31 @@ get_ppc_frame(struct bt_info *bt, ulong *getpc, ulong *getsp)
 	else 
                 sp = stack[OFFSET(task_struct_thread_ksp)/sizeof(long)];
 
-	/* 
-	 *  get the offset to the first pointer in the stack frame
-	 *  linked list.  here is a small picture:
-	 *
-	 *    ksp            
-	 * >c73e9d30:  c73e9d50 c007efbc 00000000 00000008
-	 *             ^^^^^^^^ = Pointer to first stack frame.
-	 *  c73e9d40:  c0742000 00000000 c02071e0 c73e9d50
-	 * >c73e9d50:  c73e9d80 c0013928 c73e8000 c73e9d60
-	 *             ^^^^^^^^ ^^^^^^^^ Pointer to return function
-	 *                |              (LR save word)
-	 *                 \-----------> Pointer to next stack frame
-	 *  c73e9d60:  c73e9d80 c73e9e10 c01e0000 00000007
-	 *  c73e9d70:  00000000 00000000 7fffffff c73e9d80
-	 */
-
-	offset = (stack[(sp-task)/sizeof(long)]-task)/sizeof(long);
-
-	sp = stack[offset];
-	ip = stack[(sp - task)/sizeof(long)+1]; 
-
+	if (!INSTACK(sp, bt))
+		goto out;
+
+	readmem(sp + STACK_FRAME_OVERHEAD, KVADDR, &regs,
+		sizeof(struct ppc_pt_regs),
+		"PPC pt_regs", FAULT_ON_ERROR);
+	ip = regs.nip;
+	if (STREQ(closest_symbol(ip), "__switch_to")) {
+		/* NOTE: _switch_to() calls _switch() which
+		 * is asm.  _switch leaves pc == lr.
+		 * Working through this frame is tricky,
+		 * and this mess isn't going to help if we
+		 * actually dumped here.  Most likely the
+		 * analyzer is trying to backtrace a task.
+		 * Need to skip 2 frames.
+		 */
+		sp = stack[(sp - bt->stackbase)/sizeof(ulong)];
+		if (!INSTACK(sp, bt))
+			goto out;
+		sp = stack[(sp - bt->stackbase)/sizeof(ulong)];
+		if (!INSTACK(sp + 4, bt))
+			goto out;
+		ip = stack[(sp + 4 - bt->stackbase)/sizeof(ulong)];
+	}
+out:
 	if (DUMPFILE() && getsp && STREQ(closest_symbol(sp), "panic")) {
 		*getsp = sp;
 		return;
-- 
1.7.7.rc0.72.g4b5ea

--
Crash-utility mailing list
Crash-utility@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/crash-utility

[Index of Archives]     [Fedora Development]     [Fedora Desktop]     [Fedora SELinux]     [Yosemite News]     [KDE Users]     [Fedora Tools]

 

Powered by Linux