Updating PPC

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

 



Hello Dave,

I attach patches which are updating powerpc based on linux-2.6.27.
Please review them.

Following updates have been done but
some of them could not test yet because of constraints in environment.
(Non-SMP powerpc virtual machine of qemu can only use)

- Get rid of __func__. symbols (patch 0001)
 This patch can delete such symbols from command output like

crash> sym -l | grep __func__ -m 3
c03604ac (r) __func__.21434
c0360500 (r) __func__.21333
c0360508 (r) __func__.21309

- Minor updates (patch 0002/0003/0004)
  ppc_processor_speed() support "ibm,extended-clock-frequency" [Not tested]
  ppc_get_smp_cpus() can return correct cpu numbers on SMP [Not tested]
  "bt", "mach" can handle (tt->flags & IRQSTACKS) [Not tested]

- Enhancement of "bt" (patch 0005/0006/0007/0008)
  Detect exeption frame of linux-2.6 style ("bt" can dispaly '+' parts of below)
  Some functions are cleanuped with ppc64's.
* Link Register of nested exception frame could not be tested.
  This may require the exception in kernel mode like oops but
  can not try kernel dump for a while...

crash> bt 1
PID: 1      TASK: c8818000  CPU: 0   COMMAND: "init"
 #0 [c881da10] schedule at c0356ac4
 #1 [c881da70] schedule_timeout at c0357468
 #2 [c881dab0] do_select at c00c4758
 #3 [c881dd90] core_sys_select at c00c4bd0
 #4 [c881dee0] sys_select at c00c52b0
 #5 [c881df30] ppc_select at c00053c0
 #6 [c881df40] ret_from_syscall at c0011f64
+ syscall  [c01] exception frame:
+R0:  0000008e   R1:  b8c11a60   R2:  48008660   R3:  0000000b
+R4:  b8c11cac   R5:  00000000   R6:  00000000   R7:  b8c11b24
+R8:  00000000   R9:  00000400   R10: 00000000   R11: 0ff24b2c
+R12: 0ff1b8ec   R13: 100207f0
+NIP: 0ff24b40   MSR: 0000d032   OR3: 0000000b   CTR: 0ff24b2c
+LR:  10005314   XER: 00000000   CCR: 24002462   MQ:  00000000
+DAR: 0ffb4cd0 DSISR: 0a000000        Syscall Result: 00000000

Still remaining the parts of PPC update and I have to setup more useful environment
for the tests as soon as possible.

Thanks,
Toshi.
>From 89d6a242ed95f9a50f99bf75aa08a71556a336ce Mon Sep 17 00:00:00 2001
From: Toshikazu Nakayama <nakayama.ts@xxxxxxxxxxxxxx>
Date: Thu, 27 Oct 2011 11:19:20 +0900
Subject: [PATCH 8/8] ppc: handle link register

Porting from ppc64.

Add link register of exception frame handling and newpc is also cleanuped
with new LR macro.
Ported BT_FULL parts from ppc64.

Signed-off-by: Toshikazu Nakayama <nakayama.ts@xxxxxxxxxxxxxx>
---
 defs.h |    1 +
 ppc.c  |   94 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
 2 files changed, 84 insertions(+), 11 deletions(-)

diff --git a/defs.h b/defs.h
index 022af0d..212c561 100755
--- a/defs.h
+++ b/defs.h
@@ -2616,6 +2616,7 @@ struct load_module {
 #define _MAX_PHYSMEM_BITS	44
 
 #define STACK_FRAME_OVERHEAD	16
+#define STACK_FRAME_LR_SAVE	(sizeof(ulong))
 #define STACK_FRAME_MARKER	(2 * sizeof(ulong))
 #define STACK_FRAME_REGS_MARKER	0x72656773
 #define PPC_STACK_SIZE		8192
diff --git a/ppc.c b/ppc.c
index f2adff0..a6e67fd 100755
--- a/ppc.c
+++ b/ppc.c
@@ -53,10 +53,11 @@ static void ppc_back_trace_cmd(struct bt_info *);
 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 *);
+	ulong, ulong, struct bt_info *);
 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_display_full_frame(struct bt_info *, ulong, FILE *);
 static void ppc_dump_irq(int);
 static ulong ppc_get_pc(struct bt_info *);
 static ulong ppc_get_sp(struct bt_info *);
@@ -839,6 +840,7 @@ static void
 ppc_back_trace(struct gnu_request *req, struct bt_info *bt)
 {
 	int frame = 0;
+	ulong lr = 0;
 	ulong newpc = 0, newsp, marker;
 	int eframe_found;
 
@@ -859,7 +861,8 @@ ppc_back_trace(struct gnu_request *req, struct bt_info *bt)
 	while (INSTACK(req->sp, bt)) {
 		newsp = *(ulong *)&bt->stackbuf[req->sp - bt->stackbase];
 		if (IS_KVADDR(newsp) && INSTACK(newsp, bt))
-			newpc = *(ulong *)&bt->stackbuf[newsp + 4 -
+			newpc = *(ulong *)&bt->stackbuf[newsp +
+							STACK_FRAME_LR_SAVE -
 							bt->stackbase];
 		if ((req->name = closest_symbol(req->pc)) == NULL) {
 			error(FATAL, 
@@ -869,8 +872,9 @@ ppc_back_trace(struct gnu_request *req, struct bt_info *bt)
 		}
 
 		bt->flags |= BT_SAVE_LASTSP;
-		ppc_print_stack_entry(frame, req, req->pc, req->name, bt);
+		ppc_print_stack_entry(frame, req, newsp, lr, bt);
 		bt->flags &= ~(ulonglong)BT_SAVE_LASTSP;
+		lr = 0;
 
 		if (BT_REFERENCE_FOUND(bt))
 			return;
@@ -908,6 +912,7 @@ ppc_back_trace(struct gnu_request *req, struct bt_info *bt)
 			efrm_str = ppc_check_eframe(&regs);
 			if (efrm_str) {
 				ppc_print_eframe(efrm_str, &regs, bt);
+				lr = regs.link;
 				newpc = regs.nip;
 				newsp = regs.gpr[1];
 			}
@@ -924,45 +929,112 @@ ppc_back_trace(struct gnu_request *req, struct bt_info *bt)
 	return;
 }
 
+static void
+ppc_display_full_frame(struct bt_info *bt, ulong nextsp, FILE *ofp)
+{
+	int i, u_idx;
+	ulong *nip;
+	ulong words, addr;
+	char buf[BUFSIZE];
+
+	if (!INSTACK(nextsp, bt))
+		nextsp =  bt->stacktop;
+
+	words = (nextsp - bt->frameptr) / sizeof(ulong);
+	addr = bt->frameptr;
+	u_idx = (bt->frameptr - bt->stackbase)/sizeof(ulong);
+	for (i = 0; i < words; i++, u_idx++) {
+		if (!(i & 1))
+			fprintf(ofp, "%s    %lx: ", i ? "\n" : "", addr);
+
+		nip = (ulong *)(&bt->stackbuf[u_idx*sizeof(ulong)]);
+		fprintf(ofp, "%s ", format_stack_entry(bt, buf, *nip, 0));
+		addr += sizeof(ulong);
+	}
+	fprintf(ofp, "\n");
+}
+
 /*
  *  print one entry of a stack trace
  */
 static void 
 ppc_print_stack_entry(int frame, 
 		      struct gnu_request *req, 
-		      ulong callpc, 	
-		      char *name, 
+		      ulong newsp, 	
+		      ulong lr, 
 		      struct bt_info *bt)
 {
 	struct load_module *lm;
+	char *lrname = NULL;
 
 	if (BT_REFERENCE_CHECK(bt)) {
                 switch (bt->ref->cmdflags & (BT_REF_SYMBOL|BT_REF_HEXVAL))
                 {
                 case BT_REF_SYMBOL:
-                        if (STREQ(name, bt->ref->str)) 
+                        if (STREQ(req->name, bt->ref->str)) 
                         	bt->ref->cmdflags |= BT_REF_FOUND;
                         break;
 
                 case BT_REF_HEXVAL:
-                        if (bt->ref->hexval == callpc) 
+                        if (bt->ref->hexval == req->pc) 
                                 bt->ref->cmdflags |= BT_REF_FOUND;
                         break;
                 }
 	} else {
 		fprintf(fp, "%s#%d [%lx] %s at %lx",
         		frame < 10 ? " " : "", frame,
-                	req->sp, name, callpc);
-		if (module_symbol(callpc, NULL, &lm, NULL, 0))
+                	req->sp, req->name, req->pc);
+		if (module_symbol(req->pc, NULL, &lm, NULL, 0))
 			fprintf(fp, " [%s]", lm->mod_name);
-                fprintf(fp, "\n");
+
+		if (req->ra) {
+			/*
+			 * Previous frame is an exception one. If the func
+			 * symbol for the current frame is same as with
+			 * the previous frame's LR value, print "(unreliable)".
+			 */
+			lrname = closest_symbol(req->ra);
+			req->ra = 0;
+			if (!lrname) {
+				if (CRASHDEBUG(1))
+					error(FATAL,
+					"ppc_back_trace hit unknown symbol (%lx).\n",
+						req->ra);
+				return;
+			}
+		}
+		if (lr) {
+			/*
+			 * Link register value for an expection frame.
+			 */
+			if ((lrname = closest_symbol(lr)) == NULL) {
+				if (CRASHDEBUG(1))
+					error(FATAL,
+					"ppc_back_trace hit unknown symbol (%lx).\n",
+						lr);
+				return;
+			}
+			if (req->pc != lr) {
+				fprintf(fp, "\n [Link Register ] ");
+				fprintf(fp, " [%lx] %s at %lx",
+					req->sp, lrname, lr);
+			}
+			req->ra = lr;
+		}
+		if (!req->name || STREQ(req->name,lrname))
+			fprintf(fp, "  (unreliable)");
+		fprintf(fp, "\n");
 	}
 
 	if (bt->flags & BT_SAVE_LASTSP)
 		req->lastsp = req->sp;
 
+	bt->frameptr = req->sp;
+	if (bt->flags & BT_FULL)
+		if (IS_KVADDR(newsp))
+			ppc_display_full_frame(bt, newsp, fp);
 	if (bt->flags & BT_LINE_NUMBERS)
-		ppc_dump_line_number(callpc);
+		ppc_dump_line_number(req->pc);
 }
 
 /*
-- 
1.7.6.rc2.11.g13b7

>From 1916480dfe14989dbd9346ddbc1ec5efbd28a8ce Mon Sep 17 00:00:00 2001
From: Toshikazu Nakayama <nakayama.ts@xxxxxxxxxxxxxx>
Date: Tue, 25 Oct 2011 11:19:03 +0900
Subject: [PATCH 1/8] ppc: update symbol table

Porting from ppc64.

Get rid of __func__. symbols from symbol table at ppc_verify_symbol().
This update gives effect for some command results, example:

[Before]
crash> sym -l | grep __func__ -m 3
c03604ac (r) __func__.21434
c0360500 (r) __func__.21333
c0360508 (r) __func__.21309

[After]
=> disappeared

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

diff --git a/ppc.c b/ppc.c
index 1ec8e70..b17143b 100755
--- a/ppc.c
+++ b/ppc.c
@@ -599,7 +599,7 @@ ppc_verify_symbol(const char *name, ulong value, char type)
 		machdep->flags |= KSYMS_START;
 
 	return (name && strlen(name) && (machdep->flags & KSYMS_START) &&
-	        !STREQ(name, "Letext"));
+	        !STREQ(name, "Letext") && !STRNEQ(name, "__func__."));
 }
 
 
-- 
1.7.6.rc2.11.g13b7

>From f769af54e9f80a98a54404545adf6893953f8959 Mon Sep 17 00:00:00 2001
From: Toshikazu Nakayama <nakayama.ts@xxxxxxxxxxxxxx>
Date: Tue, 25 Oct 2011 11:35:30 +0900
Subject: [PATCH 2/8] ppc: update processor frequency

Porting from ppc64.

Add "ibm,extended-clock-frequency" device property which is
appeared in the ppc common code arch/powerpc/kernel/time.c.

Fix indent nearby readmem().

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

diff --git a/ppc.c b/ppc.c
index b17143b..60d4028 100755
--- a/ppc.c
+++ b/ppc.c
@@ -523,15 +523,28 @@ ppc_processor_speed(void)
 					    "clock frequency value",
                                             FAULT_ON_ERROR);
 					mhz /= 1000000;
-					
+					break;
+				} else if(len && (strcasecmp(str_buf,
+					"ibm,extended-clock-frequency") == 0)){
+					/* found the right cpu property */
+
+					readmem(properties+
+						OFFSET(property_value),
+						KVADDR, &value, sizeof(ulong),
+						"clock freqency pointer",
+						FAULT_ON_ERROR);
+					readmem(value, KVADDR, &mhz,
+						sizeof(ulong),
+						"clock frequency value",
+						FAULT_ON_ERROR);
+					mhz /= 1000000;
 					break;
 				}
 				/* keep looking */
-				
 				readmem(properties+
-				    OFFSET(property_next),
-				    KVADDR, &properties, sizeof(ulong), 
-				    "property next", FAULT_ON_ERROR);
+					OFFSET(property_next),
+					KVADDR, &properties, sizeof(ulong), 
+					"property next", FAULT_ON_ERROR);
 			}
 			if(!properties) {
 				/* didn't find the cpu speed for some reason */
@@ -551,19 +564,19 @@ ppc_processor_speed(void)
 			get_symbol_data("ppc_md", sizeof(void *), 
 				&ppc_md);
 			readmem(ppc_md + 
-		 	    OFFSET(machdep_calls_setup_residual), 
-			    KVADDR, &md_setup_res, 
-			    sizeof(ulong), "ppc_md setup_residual",
-			    FAULT_ON_ERROR);
+		 		OFFSET(machdep_calls_setup_residual), 
+				KVADDR, &md_setup_res, 
+				sizeof(ulong), "ppc_md setup_residual",
+				FAULT_ON_ERROR);
 				
 			if(prep_setup_res == md_setup_res) {
-			/* PREP machine */
+				/* PREP machine */
 				readmem(res+
-				    OFFSET(RESIDUAL_VitalProductData)+
-				    OFFSET(VPD_ProcessorHz),
-				    KVADDR, &mhz, sizeof(ulong), 
-				    "res VitalProductData", 
-				    FAULT_ON_ERROR);
+					OFFSET(RESIDUAL_VitalProductData)+
+					OFFSET(VPD_ProcessorHz),
+					KVADDR, &mhz, sizeof(ulong), 
+					"res VitalProductData", 
+					FAULT_ON_ERROR);
 					
 				mhz = (mhz > 1024) ? mhz >> 20 : mhz;
 			}
-- 
1.7.6.rc2.11.g13b7

>From c826e4f244fb5a369ccf44d566c9d84308fd5747 Mon Sep 17 00:00:00 2001
From: Toshikazu Nakayama <nakayama.ts@xxxxxxxxxxxxxx>
Date: Tue, 25 Oct 2011 14:21:05 +0900
Subject: [PATCH 3/8] ppc: update get_smp_cpus

Porting from ppc64.

ppc_get_smp_cpus() returned kt->cpus for kt->cpus setting,
won't overwrite cpus.
Return get_cpus_online() which cpu_online_map is common symbol
in powerpc kernel.

[Before] maybe everytime print "1" even if SMP machine.
crash> mach | grep CPUS
               CPUS: 1
crash> help -k | grep "cpus:"
          cpus: 1

[After] Could print correctable cpus (not tested yet)

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

diff --git a/ppc.c b/ppc.c
index 60d4028..adcf239 100755
--- a/ppc.c
+++ b/ppc.c
@@ -1328,7 +1328,7 @@ ppc_dis_filter(ulong vaddr, char *inbuf, unsigned int output_radix)
 int
 ppc_get_smp_cpus(void)
 {
-        return kt->cpus;
+	return (get_cpus_online() > 0) ? get_cpus_online() : kt->cpus;
 }
 
 /*
-- 
1.7.6.rc2.11.g13b7

>From 83199eb1aced18b509c798bb9db9a90df8173c8e Mon Sep 17 00:00:00 2001
From: Toshikazu Nakayama <nakayama.ts@xxxxxxxxxxxxxx>
Date: Fri, 28 Oct 2011 13:07:27 +0900
Subject: [PATCH 4/8] ppc: mach and bt can handle irq stack

Porting from ppc64.

When CONFIG_IRQSTACK is y (tt->flags & IRQSTACKS),
mach command can show IRQ stacks and bt command can
display backtrace in IRQ stacks.
IRQ stack -> current task's stack switch can not support yet.

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

diff --git a/ppc.c b/ppc.c
index adcf239..ed21236 100755
--- a/ppc.c
+++ b/ppc.c
@@ -27,6 +27,7 @@ static int ppc_translate_pte(ulong, void *, ulonglong);
 
 static ulong ppc_processor_speed(void);
 static int ppc_eframe_search(struct bt_info *);
+static ulong ppc_in_irqstack(ulong);
 static void ppc_back_trace_cmd(struct bt_info *);
 static void ppc_back_trace(struct gnu_request *, struct bt_info *);
 static void get_ppc_frame(struct bt_info *, ulong *, ulong *);
@@ -155,6 +156,12 @@ ppc_init(int when)
 			machdep->flags |= CPU_BOOKE;
 		machdep->section_size_bits = _SECTION_SIZE_BITS;
 		machdep->max_physmem_bits = _MAX_PHYSMEM_BITS;
+		/*
+		 * IRQ stacks are introduced in 2.6 and also configurable.
+		 */
+		if ((THIS_KERNEL_VERSION >= LINUX(2,6,0)) &&
+			symbol_exists("hardirq_ctx"))
+			STRUCT_SIZE_INIT(irq_ctx, "hardirq_ctx");
 		break;
 
 	case POST_INIT:
@@ -762,6 +769,30 @@ ppc_eframe_search(struct bt_info *bt)
 	return (error(FATAL, "ppc_eframe_search: function not written yet!\n"));
 }
 
+static ulong
+ppc_in_irqstack(ulong addr)
+{
+	int c;
+
+	if (!(tt->flags & IRQSTACKS))
+		return 0;
+
+	for (c = 0; c < kt->cpus; c++) {
+		if (tt->hardirq_ctx[c]) {
+			if ((addr >= tt->hardirq_ctx[c]) &&
+			    (addr < (tt->hardirq_ctx[c] + SIZE(irq_ctx))))
+				return tt->hardirq_ctx[c];
+		}
+		if (tt->softirq_ctx[c]) {
+			if ((addr >= tt->softirq_ctx[c]) &&
+			    (addr < (tt->softirq_ctx[c] + SIZE(irq_ctx))))
+				return tt->softirq_ctx[c];
+		}
+	}
+
+	return 0;
+}
+
 /*
  *  Unroll a kernel stack.
  */
@@ -808,6 +839,20 @@ ppc_back_trace(struct gnu_request *req, struct bt_info *bt)
         int frame;
 	int done;
 
+	if (!INSTACK(req->sp, bt)) {
+		ulong irqstack;
+
+		if ((irqstack = ppc_in_irqstack(req->sp))) {
+			bt->stackbase = irqstack;
+			bt->stacktop = bt->stackbase + SIZE(irq_ctx);
+			alter_stackbuf(bt);
+		} else {
+			if (CRASHDEBUG(1))
+				fprintf(fp, "cannot find the stack info.\n");
+			return;
+		}
+	}
+
         for (frame = 0, done = FALSE; !done && (frame < 100); frame++) {
 		if ((req->name = closest_symbol(req->pc)) == NULL) {
 			error(FATAL, 
@@ -1360,6 +1405,7 @@ ppc_cmd_mach(void)
 static void
 ppc_display_machine_stats(void)
 {
+	int c;
         struct new_utsname *uts;
         char buf[BUFSIZE];
         ulong mhz;
@@ -1376,10 +1422,31 @@ ppc_display_machine_stats(void)
                 fprintf(fp, "(unknown)\n");
         fprintf(fp, "                 HZ: %d\n", machdep->hz);
         fprintf(fp, "          PAGE SIZE: %d\n", PAGESIZE());
-        fprintf(fp, "      L1 CACHE SIZE: %d\n", l1_cache_size());
+//      fprintf(fp, "      L1 CACHE SIZE: %d\n", l1_cache_size());
         fprintf(fp, "KERNEL VIRTUAL BASE: %lx\n", machdep->kvbase);
         fprintf(fp, "KERNEL VMALLOC BASE: %lx\n", vt->vmalloc_start);
         fprintf(fp, "  KERNEL STACK SIZE: %ld\n", STACKSIZE());
+
+	if (tt->flags & IRQSTACKS) {
+		fprintf(fp, "HARD IRQ STACK SIZE: %ld\n", SIZE(irq_ctx));
+		fprintf(fp, "    HARD IRQ STACKS:\n");
+
+		for (c = 0; c < kt->cpus; c++) {
+			if (!tt->hardirq_ctx[c])
+				break;
+			sprintf(buf, "CPU %d", c);
+			fprintf(fp, "%19s: %lx\n", buf, tt->hardirq_ctx[c]);
+		}
+
+		fprintf(fp, "SOFT IRQ STACK SIZE: %ld\n", SIZE(irq_ctx));
+		fprintf(fp, "    SOFT IRQ STACKS:\n");
+		for (c = 0; c < kt->cpus; c++) {
+			if (!tt->softirq_ctx[c])
+				break;
+			sprintf(buf, "CPU %d", c);
+			fprintf(fp, "%19s: %lx\n", buf, tt->softirq_ctx[c]);
+		}
+	}
 }
 
 
-- 
1.7.6.rc2.11.g13b7

>From 1599ec683994f7b4b71a87680613e6a414efdf55 Mon Sep 17 00:00:00 2001
From: Toshikazu Nakayama <nakayama.ts@xxxxxxxxxxxxxx>
Date: Wed, 26 Oct 2011 14:47:32 +0900
Subject: [PATCH 5/8] ppc: cleanup backtrace loop

Porting from ppc64.

Apply using newsp, newpc into stack frame loop.
This can also avoid unnecessary readmem().

Drop loop limitation 100, use INSTACK().

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

diff --git a/ppc.c b/ppc.c
index ed21236..ff14827 100755
--- a/ppc.c
+++ b/ppc.c
@@ -836,8 +836,8 @@ ppc_back_trace_cmd(struct bt_info *bt)
 static void
 ppc_back_trace(struct gnu_request *req, struct bt_info *bt)
 {
-        int frame;
-	int done;
+	int frame = 0;
+	ulong newpc = 0, newsp;
 
 	if (!INSTACK(req->sp, bt)) {
 		ulong irqstack;
@@ -853,44 +853,39 @@ ppc_back_trace(struct gnu_request *req, struct bt_info *bt)
 		}
 	}
 
-        for (frame = 0, done = FALSE; !done && (frame < 100); frame++) {
+	while (INSTACK(req->sp, bt)) {
+		newsp = *(ulong *)&bt->stackbuf[req->sp - bt->stackbase];
+		if (IS_KVADDR(newsp) && INSTACK(newsp, bt))
+			newpc = *(ulong *)&bt->stackbuf[newsp + 4 -
+							bt->stackbase];
 		if ((req->name = closest_symbol(req->pc)) == NULL) {
 			error(FATAL, 
-			    "ppc_back_trace hit unknown symbol (%lx).\n",
+				"ppc_back_trace hit unknown symbol (%lx).\n",
 				req->pc);
-			req->ra = req->pc = 0;
 			break;
 		}
 
 		bt->flags |= BT_SAVE_LASTSP;
 		ppc_print_stack_entry(frame, req, req->pc, req->name, bt);
 		bt->flags &= ~(ulonglong)BT_SAVE_LASTSP;
-		
+
 		if (BT_REFERENCE_FOUND(bt))
 			return;
 
-		/* get the next sp and ip values */
-		readmem(req->sp, KVADDR, &req->sp, sizeof(ulong),
-			"stack frame", FAULT_ON_ERROR);
-
-		/* an actual valid end of the back-chain! */
-		if(req->sp == 0)
-			break;
-
-		if((req->sp - req->lastsp) >= sizeof(struct ppc_pt_regs)) {
+		if((newsp - req->sp) >= sizeof(struct ppc_pt_regs)) {
 			/* there might be an exception frame here... */
-			ppc_exception_frame(req->lastsp, bt, req);
-		} else if(!IS_KVADDR(req->sp) || (req->sp < req->lastsp)) {
+			ppc_exception_frame(req->sp, bt, req);
+		} else if(!IS_KVADDR(newsp) || (newsp < req->sp)) {
 			/* also possible one here... */
-			ppc_exception_frame(req->lastsp, bt, req);
+			ppc_exception_frame(req->sp, bt, req);
 		}
-		
-		if (!INSTACK(req->sp, bt) || 
-		    STREQ(req->name, "start_kernel"))
+
+		if (STREQ(req->name, "start_kernel"))
 			break;
 
-		readmem(req->sp+sizeof(long), KVADDR, &req->pc, sizeof(ulong),
-			"instruction pointer", FAULT_ON_ERROR);
+		req->pc = newpc;
+		req->sp = newsp;
+		frame++;
 	}
 
 	return;
-- 
1.7.6.rc2.11.g13b7

>From c65bd42bae131a6d225510f7e23848a6c2577898 Mon Sep 17 00:00:00 2001
From: Toshikazu Nakayama <nakayama.ts@xxxxxxxxxxxxxx>
Date: Fri, 28 Oct 2011 13:45:31 +0900
Subject: [PATCH 6/8] ppc: update exception frame search

Porting from ppc64.

The backtrace of ppc can handle exception frame and print frame information
for linux-2.6 style by checking exception frame marker.
Clear LS-4bits of trap register when refer exception number for linux-2.6.

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

diff --git a/defs.h b/defs.h
index 970b78e..022af0d 100755
--- a/defs.h
+++ b/defs.h
@@ -2616,6 +2616,8 @@ struct load_module {
 #define _MAX_PHYSMEM_BITS	44
 
 #define STACK_FRAME_OVERHEAD	16
+#define STACK_FRAME_MARKER	(2 * sizeof(ulong))
+#define STACK_FRAME_REGS_MARKER	0x72656773
 #define PPC_STACK_SIZE		8192
 
 #endif  /* PPC */
diff --git a/ppc.c b/ppc.c
index ff14827..1bbde2c 100755
--- a/ppc.c
+++ b/ppc.c
@@ -837,7 +837,8 @@ static void
 ppc_back_trace(struct gnu_request *req, struct bt_info *bt)
 {
 	int frame = 0;
-	ulong newpc = 0, newsp;
+	ulong newpc = 0, newsp, marker;
+	int eframe_found;
 
 	if (!INSTACK(req->sp, bt)) {
 		ulong irqstack;
@@ -872,13 +873,31 @@ ppc_back_trace(struct gnu_request *req, struct bt_info *bt)
 		if (BT_REFERENCE_FOUND(bt))
 			return;
 
-		if((newsp - req->sp) >= sizeof(struct ppc_pt_regs)) {
-			/* there might be an exception frame here... */
-			ppc_exception_frame(req->sp, bt, req);
-		} else if(!IS_KVADDR(newsp) || (newsp < req->sp)) {
-			/* also possible one here... */
-			ppc_exception_frame(req->sp, bt, req);
+		eframe_found = FALSE;
+		/*
+		 * Is this frame an execption one?
+		 * In 2.6, 0x72656773 is saved and used
+		 * to determine the execption frame.
+		 */
+		if (THIS_KERNEL_VERSION < LINUX(2,6,0)) {
+			if (frame && (newsp - req->sp - STACK_FRAME_OVERHEAD >=
+				sizeof(struct ppc_pt_regs)))
+				/* there might be an exception frame here... */
+				eframe_found = TRUE;
+			/* also possible ones here... */
+			else if(!IS_KVADDR(newsp) || (newsp < req->sp))
+				eframe_found = TRUE;
+			else if (STREQ(req->name, ".ret_from_except"))
+				eframe_found = TRUE;
+		} else if ((newsp - req->sp - STACK_FRAME_OVERHEAD) >=
+				sizeof(struct ppc_pt_regs)){
+			readmem(req->sp + STACK_FRAME_MARKER, KVADDR, &marker,
+				sizeof(ulong), "frame marker", FAULT_ON_ERROR);
+			if (marker == STACK_FRAME_REGS_MARKER)
+				eframe_found = TRUE;
 		}
+		if (eframe_found)
+			ppc_exception_frame(req->sp, bt, req);
 
 		if (STREQ(req->name, "start_kernel"))
 			break;
@@ -944,10 +963,10 @@ ppc_exception_frame(ulong addr, struct bt_info *bt, struct gnu_request *req)
 	if (BT_REFERENCE_CHECK(bt))
 		return;
 
-	readmem(addr+16, KVADDR, &regs, sizeof(regs),
+	readmem(addr + STACK_FRAME_OVERHEAD, KVADDR, &regs, sizeof(regs),
 		"exception frame", FAULT_ON_ERROR);
 	
-	switch(regs.trap) {
+	switch(regs.trap & ~0xF) {
 	case 0x200:
 		fprintf(fp, "machine check");
 		break;
-- 
1.7.6.rc2.11.g13b7

>From 365a7175685413fa58d8773c992ea1b04013a27b Mon Sep 17 00:00:00 2001
From: Toshikazu Nakayama <nakayama.ts@xxxxxxxxxxxxxx>
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@xxxxxxxxxxxxxx>
---
 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

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