summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Ellerman <michael@ellerman.id.au>2006-10-24 18:31:28 +0200
committerPaul Mackerras <paulus@samba.org>2006-10-25 06:20:22 +0200
commita898497088f46252e6750405504064e2dce53117 (patch)
tree71075a07df0dcf98816545cf0c4a3eab542552af
parent[POWERPC] add support for stopping spus from xmon (diff)
downloadlinux-a898497088f46252e6750405504064e2dce53117.tar.xz
linux-a898497088f46252e6750405504064e2dce53117.zip
[POWERPC] add support for dumping spu info from xmon
This patch adds a command to xmon for dumping information about spu structs. The command is 'sf' for "spu fields" perhaps, and takes the spu number as an argument. This is the same value as the spu->number field, or the "phys-id" value of a context when it is bound to a physical spu. We try to catch memory errors as we dump each field, hopefully this will make the command reasonably robust, but YMMV. If people see a need we can easily add more fields to the dump in future. Output looks something like this: 0:mon> sf 0 Dumping spu fields at address c00000001ffd9e80: number = 0x0 name = spe devnode->full_name = /cpus/PowerPC,BE@0/spes/spe@0 nid = 0x0 local_store_phys = 0x20000000000 local_store = 0xd0000800801e0000 ls_size = 0x0 isrc = 0x4 node = 0x0 flags = 0x0 dar = 0x0 dsisr = 0x0 class_0_pending = 0 irqs[0] = 0x16 irqs[1] = 0x17 irqs[2] = 0x24 slb_replace = 0x0 pid = 0 prio = 0 mm = 0x0000000000000000 ctx = 0x0000000000000000 rq = 0x0000000000000000 timestamp = 0x0000000000000000 problem_phys = 0x20000040000 problem = 0xd000080080220000 problem->spu_runcntl_RW = 0x0 problem->spu_status_R = 0x0 problem->spu_npc_RW = 0x0 priv1 = 0xd000080080240000 priv1->mfc_sr1_RW = 0x33 priv2 = 0xd000080080250000 Signed-off-by: Michael Ellerman <michael@ellerman.id.au> Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com> Signed-off-by: Paul Mackerras <paulus@samba.org>
-rw-r--r--arch/powerpc/xmon/xmon.c67
1 files changed, 66 insertions, 1 deletions
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index 6a2ed8b319f0..0689c0845777 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -216,7 +216,8 @@ Commands:\n\
s single step\n"
#ifdef CONFIG_PPC_CELL
" ss stop execution on all spus\n\
- sr restore execution on stopped spus\n"
+ sr restore execution on stopped spus\n\
+ sf # dump spu fields for spu # (in hex)\n"
#endif
" S print special registers\n\
t print backtrace\n\
@@ -2744,8 +2745,66 @@ static void restart_spus(void)
}
}
+#define DUMP_WIDTH 23
+#define DUMP_FIELD(obj, format, field) \
+do { \
+ if (setjmp(bus_error_jmp) == 0) { \
+ catch_memory_errors = 1; \
+ sync(); \
+ printf(" %-*s = "format"\n", DUMP_WIDTH, \
+ #field, obj->field); \
+ sync(); \
+ __delay(200); \
+ } else { \
+ catch_memory_errors = 0; \
+ printf(" %-*s = *** Error reading field.\n", \
+ DUMP_WIDTH, #field); \
+ } \
+ catch_memory_errors = 0; \
+} while (0)
+
+static void dump_spu_fields(struct spu *spu)
+{
+ printf("Dumping spu fields at address %p:\n", spu);
+
+ DUMP_FIELD(spu, "0x%x", number);
+ DUMP_FIELD(spu, "%s", name);
+ DUMP_FIELD(spu, "%s", devnode->full_name);
+ DUMP_FIELD(spu, "0x%x", nid);
+ DUMP_FIELD(spu, "0x%lx", local_store_phys);
+ DUMP_FIELD(spu, "0x%p", local_store);
+ DUMP_FIELD(spu, "0x%lx", ls_size);
+ DUMP_FIELD(spu, "0x%x", node);
+ DUMP_FIELD(spu, "0x%lx", flags);
+ DUMP_FIELD(spu, "0x%lx", dar);
+ DUMP_FIELD(spu, "0x%lx", dsisr);
+ DUMP_FIELD(spu, "%d", class_0_pending);
+ DUMP_FIELD(spu, "0x%lx", irqs[0]);
+ DUMP_FIELD(spu, "0x%lx", irqs[1]);
+ DUMP_FIELD(spu, "0x%lx", irqs[2]);
+ DUMP_FIELD(spu, "0x%x", slb_replace);
+ DUMP_FIELD(spu, "%d", pid);
+ DUMP_FIELD(spu, "%d", prio);
+ DUMP_FIELD(spu, "0x%p", mm);
+ DUMP_FIELD(spu, "0x%p", ctx);
+ DUMP_FIELD(spu, "0x%p", rq);
+ DUMP_FIELD(spu, "0x%p", timestamp);
+ DUMP_FIELD(spu, "0x%lx", problem_phys);
+ DUMP_FIELD(spu, "0x%p", problem);
+ DUMP_FIELD(spu, "0x%x", problem->spu_runcntl_RW);
+ DUMP_FIELD(spu, "0x%x", problem->spu_status_R);
+ DUMP_FIELD(spu, "0x%x", problem->spu_npc_RW);
+ DUMP_FIELD(spu, "0x%p", priv1);
+
+ if (spu->priv1)
+ DUMP_FIELD(spu, "0x%lx", priv1->mfc_sr1_RW);
+
+ DUMP_FIELD(spu, "0x%p", priv2);
+}
+
static int do_spu_cmd(void)
{
+ unsigned long num = 0;
int cmd;
cmd = inchar();
@@ -2756,6 +2815,12 @@ static int do_spu_cmd(void)
case 'r':
restart_spus();
break;
+ case 'f':
+ if (scanhex(&num) && num < XMON_NUM_SPUS && spu_info[num].spu)
+ dump_spu_fields(spu_info[num].spu);
+ else
+ printf("*** Error: invalid spu number\n");
+ break;
default:
return -1;
}