>From 365a7175685413fa58d8773c992ea1b04013a27b Mon Sep 17 00:00:00 2001
From: Toshikazu Nakayama <nakayama.ts@ncos.nec.co.jp>
Date: Fri, 28 Oct 2011 13:59:29 +0900
Subject: [PATCH 7/8] ppc: devided exception frame printer function

Porting from ppc64.

This update can also get rid of unused GIP[14-31] field for linux-2.6.

Signed-off-by: Toshikazu Nakayama <nakayama.ts@ncos.nec.co.jp>
---
 ppc.c |  175 +++++++++++++++++++++++++++++++++++-----------------------------
 1 files changed, 96 insertions(+), 79 deletions(-)

diff --git a/ppc.c b/ppc.c
index 1bbde2c..f2adff0 100755
--- a/ppc.c
+++ b/ppc.c
@@ -17,6 +17,27 @@
 #ifdef PPC
 #include "defs.h"
 
+/* 
+ *  This structure was copied from kernel source
+ *  in include/asm-ppc/ptrace.h
+ */
+struct ppc_pt_regs {
+        long gpr[32];
+        long nip;
+        long msr;
+        long orig_gpr3;      /* Used for restarting system calls */
+        long ctr;
+        long link;
+        long xer;
+        long ccr;
+        long mq;             /* 601 only (not used at present) */
+                                /* Used on APUS to hold IPL value. */
+        long trap;           /* Reason for being here */
+        long dar;            /* Fault registers */
+        long dsisr;
+        long result;         /* Result of a system call */
+};
+
 static int ppc_kvtop(struct task_context *, ulong, physaddr_t *, int);
 static int ppc_uvtop(struct task_context *, ulong, physaddr_t *, int);
 static ulong ppc_vmalloc_start(void);
@@ -33,7 +54,9 @@ static void ppc_back_trace(struct gnu_request *, struct bt_info *);
 static void get_ppc_frame(struct bt_info *, ulong *, ulong *);
 static void ppc_print_stack_entry(int,struct gnu_request *,
 	ulong, char *, struct bt_info *);
-static void ppc_exception_frame(ulong, struct bt_info *, struct gnu_request *);
+static char *ppc_check_eframe(struct ppc_pt_regs *);
+static void ppc_print_eframe(char *, struct ppc_pt_regs *, struct bt_info *);
+static void ppc_print_regs(struct ppc_pt_regs *);
 static void ppc_dump_irq(int);
 static ulong ppc_get_pc(struct bt_info *);
 static ulong ppc_get_sp(struct bt_info *);
@@ -742,27 +765,6 @@ ppc_translate_pte(ulong pte, void *physaddr, ulonglong unused)
  *  Look for likely exception frames in a stack.
  */
 
-/* 
- *  This structure was copied from kernel source
- *  in include/asm-ppc/ptrace.h
- */
-struct ppc_pt_regs {
-        long gpr[32];
-        long nip;
-        long msr;
-        long orig_gpr3;      /* Used for restarting system calls */
-        long ctr;
-        long link;
-        long xer;
-        long ccr;
-        long mq;             /* 601 only (not used at present) */
-                                /* Used on APUS to hold IPL value. */
-        long trap;           /* Reason for being here */
-        long dar;            /* Fault registers */
-        long dsisr;
-        long result;         /* Result of a system call */
-};
-
 static int 
 ppc_eframe_search(struct bt_info *bt)
 {
@@ -896,8 +898,20 @@ ppc_back_trace(struct gnu_request *req, struct bt_info *bt)
 			if (marker == STACK_FRAME_REGS_MARKER)
 				eframe_found = TRUE;
 		}
-		if (eframe_found)
-			ppc_exception_frame(req->sp, bt, req);
+		if (eframe_found) {
+			char *efrm_str;
+			struct ppc_pt_regs regs;
+
+			readmem(req->sp + STACK_FRAME_OVERHEAD, KVADDR, &regs,
+				sizeof(struct ppc_pt_regs),
+				"exception frame", FAULT_ON_ERROR);
+			efrm_str = ppc_check_eframe(&regs);
+			if (efrm_str) {
+				ppc_print_eframe(efrm_str, &regs, bt);
+				newpc = regs.nip;
+				newsp = regs.gpr[1];
+			}
+		}
 
 		if (STREQ(req->name, "start_kernel"))
 			break;
@@ -952,65 +966,47 @@ ppc_print_stack_entry(int frame,
 }
 
 /*
- *  Print exception frame information for PowerPC
+ *  Check whether the frame is exception one!
  */
-static void
-ppc_exception_frame(ulong addr, struct bt_info *bt, struct gnu_request *req)
+static char *
+ppc_check_eframe(struct ppc_pt_regs *regs)
 {
-	int i;
-	struct ppc_pt_regs regs;
-	
-	if (BT_REFERENCE_CHECK(bt))
-		return;
-
-	readmem(addr + STACK_FRAME_OVERHEAD, KVADDR, &regs, sizeof(regs),
-		"exception frame", FAULT_ON_ERROR);
-	
-	switch(regs.trap & ~0xF) {
+	switch(regs->trap & ~0xF) {
 	case 0x200:
-		fprintf(fp, "machine check");
-		break;
+		return "machine check";
 	case 0x300:
-		fprintf(fp, "address error (store)");
-		break;
+		return "address error (store)";
 	case 0x400:
-		fprintf(fp, "instruction bus error");
-		break;
+		return "instruction bus error";
 	case 0x500:
-		fprintf(fp, "interrupt");
-		break;
+		return "interrupt";
 	case 0x600:
-		fprintf(fp, "alingment");
-		break;
+		return "alingment";
 	case 0x700:
-		fprintf(fp, "breakpoint trap");
-		break;
+		return "breakpoint trap";
 	case 0x800:
-		fprintf(fp, "fpu unavailable");
-		break;
+		return "fpu unavailable";
 	case 0x900:
-		fprintf(fp, "decrementer");
-		break;
+		return "decrementer";
 	case 0xa00:
-		fprintf(fp, "reserved");
-		break;
+		return "reserved";
 	case 0xb00:
-		fprintf(fp, "reserved");
-		break;
+		return "reserved";
 	case 0xc00:
-		fprintf(fp, "syscall");
-		break;
+		return "syscall";
 	case 0xd00:
-		fprintf(fp, "single-step/watch");
-		break;
+		return "single-step/watch";
 	case 0xe00:
-		fprintf(fp, "fp assist");
-		break;
-	default: /* back trace ended, but no exception frame exists */
-		return;
+		return "fp assist";
 	}
+	/* No exception frame exists */
+	return NULL;
+}
 
-	fprintf(fp, " [%lx] exception frame:", regs.trap);
+static void
+ppc_print_regs(struct ppc_pt_regs *regs)
+{
+	int i;
 
 	/* print out the gprs... */
 	for(i=0; i<32; i++) {
@@ -1018,24 +1014,45 @@ ppc_exception_frame(ulong addr, struct bt_info *bt, struct gnu_request *req)
 			fprintf(fp, "\n");
 
 		fprintf(fp, "R%d:%s %08lx   ", i,
-			((i < 10) ? " " : ""), regs.gpr[i]);
+			((i < 10) ? " " : ""), regs->gpr[i]);
+		/*
+		 * In 2.6, some stack frame contains only partial regs set.
+		 * For the partial set, only 14 regs will be saved and trap
+		 * field will contain 1 in the least significant bit.
+		 */
+		if ((i == 13) && (regs->trap & 1))
+			break;
 	}
 
 	fprintf(fp, "\n");
 
 	/* print out the rest of the registers */
-	fprintf(fp, "NIP: %08lx   ", regs.nip);
-	fprintf(fp, "MSR: %08lx   ", regs.msr);
-	fprintf(fp, "OR3: %08lx   ", regs.orig_gpr3);
-	fprintf(fp, "CTR: %08lx\n", regs.ctr);
-
-	fprintf(fp, "LR:  %08lx   ", regs.link);
-	fprintf(fp, "XER: %08lx   ", regs.xer);
-	fprintf(fp, "CCR: %08lx   ", regs.ccr);
-	fprintf(fp, "MQ:  %08lx\n", regs.mq);
-	fprintf(fp, "DAR: %08lx ", regs.dar);
-	fprintf(fp, "DSISR: %08lx ", regs.dsisr);
-	fprintf(fp, "       Syscall Result: %08lx\n", regs.result);
+	fprintf(fp, "NIP: %08lx   ", regs->nip);
+	fprintf(fp, "MSR: %08lx   ", regs->msr);
+	fprintf(fp, "OR3: %08lx   ", regs->orig_gpr3);
+	fprintf(fp, "CTR: %08lx\n", regs->ctr);
+
+	fprintf(fp, "LR:  %08lx   ", regs->link);
+	fprintf(fp, "XER: %08lx   ", regs->xer);
+	fprintf(fp, "CCR: %08lx   ", regs->ccr);
+	fprintf(fp, "MQ:  %08lx\n", regs->mq);
+	fprintf(fp, "DAR: %08lx ", regs->dar);
+	fprintf(fp, "DSISR: %08lx ", regs->dsisr);
+	fprintf(fp, "       Syscall Result: %08lx\n", regs->result);
+}
+
+/*
+ * Print the exception frame information
+ */
+static void
+ppc_print_eframe(char *efrm_str, struct ppc_pt_regs *regs, struct bt_info *bt)
+{
+	if (BT_REFERENCE_CHECK(bt))
+		return;
+
+	fprintf(fp, " %s  [%lx] exception frame:", efrm_str, regs->trap);
+	ppc_print_regs(regs);
+	fprintf(fp, "\n");
 }
 
 /*
-- 
1.7.6.rc2.11.g13b7

