#include <linux/sysrq.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
+#include <linux/bug.h>
#include <asm/ptrace.h>
#include <asm/string.h>
#include <asm/cputable.h>
#include <asm/rtas.h>
#include <asm/sstep.h>
-#include <asm/bug.h>
#include <asm/irq_regs.h>
#include <asm/spu.h>
#include <asm/spu_priv1.h>
#ifdef CONFIG_PPC64
#include <asm/hvcall.h>
#include <asm/paca.h>
+#include <asm/iseries/it_lp_reg_save.h>
#endif
#include "nonstdio.h"
+#include "dis-asm.h"
#define scanhex xmon_scanhex
#define skipbl xmon_skipbl
static void dump(void);
static void prdump(unsigned long, long);
static int ppc_inst_dump(unsigned long, long, int);
-void print_address(unsigned long);
static void backtrace(struct pt_regs *);
static void excprint(struct pt_regs *);
static void prregs(struct pt_regs *);
int xmon_no_auto_backtrace;
-extern int print_insn_powerpc(unsigned long, unsigned long, int);
-
extern void xmon_enter(void);
extern void xmon_leave(void);
p call a procedure\n\
r print registers\n\
s single step\n"
-#ifdef CONFIG_PPC_CELL
+#ifdef CONFIG_SPU_BASE
" ss stop execution on all spus\n\
sr restore execution on stopped spus\n\
- sf # dump spu fields for spu # (in hex)\n"
+ sf # dump spu fields for spu # (in hex)\n\
+ sd # dump spu local store for spu # (in hex)\
+ sdi # disassemble spu local store for spu # (in hex)\n"
#endif
" S print special registers\n\
t print backtrace\n\
static void print_bug_trap(struct pt_regs *regs)
{
- struct bug_entry *bug;
+ const struct bug_entry *bug;
unsigned long addr;
if (regs->msr & MSR_PR)
bug = find_bug(regs->nip);
if (bug == NULL)
return;
- if (bug->line & BUG_WARNING_TRAP)
+ if (is_warning_bug(bug))
return;
- printf("kernel BUG in %s at %s:%d!\n",
- bug->function, bug->file, (unsigned int)bug->line);
+ printf("kernel BUG at %s:%u!\n",
+ bug->file, bug->line);
}
void excprint(struct pt_regs *fp)
}
}
+typedef int (*instruction_dump_func)(unsigned long inst, unsigned long addr);
+
int
-ppc_inst_dump(unsigned long adr, long count, int praddr)
+generic_inst_dump(unsigned long adr, long count, int praddr,
+ instruction_dump_func dump_func)
{
int nr, dotted;
unsigned long first_adr;
if (praddr)
printf(REG" %.8x", adr, inst);
printf("\t");
- print_insn_powerpc(inst, adr, 0); /* always returns 4 */
+ dump_func(inst, adr);
printf("\n");
}
return adr - first_adr;
}
+int
+ppc_inst_dump(unsigned long adr, long count, int praddr)
+{
+ return generic_inst_dump(adr, count, praddr, print_insn_powerpc);
+}
+
void
print_address(unsigned long addr)
{
void xmon_init(int enable)
{
+#ifdef CONFIG_PPC_ISERIES
+ if (firmware_has_feature(FW_FEATURE_ISERIES))
+ return;
+#endif
if (enable) {
__debugger = xmon;
__debugger_ipi = xmon_ipi;
static int __init setup_xmon_sysrq(void)
{
+#ifdef CONFIG_PPC_ISERIES
+ if (firmware_has_feature(FW_FEATURE_ISERIES))
+ return 0;
+#endif
register_sysrq_key('x', &sysrq_xmon_op);
return 0;
}
debugger(NULL);
}
-#ifdef CONFIG_PPC_CELL
+#ifdef CONFIG_SPU_BASE
struct spu_info {
struct spu *spu;
u64 saved_mfc_sr1_RW;
u32 saved_spu_runcntl_RW;
+ unsigned long dump_addr;
u8 stopped_ok;
};
spu_info[spu->number].spu = spu;
spu_info[spu->number].stopped_ok = 0;
+ spu_info[spu->number].dump_addr = (unsigned long)
+ spu_info[spu->number].spu->local_store;
}
}
__delay(200);
spu_info[i].stopped_ok = 1;
- printf("Stopped spu %.2d\n", i);
+
+ printf("Stopped spu %.2d (was %s)\n", i,
+ spu_info[i].saved_spu_runcntl_RW ?
+ "running" : "stopped");
} else {
catch_memory_errors = 0;
printf("*** Error stopping spu %.2d\n", i);
}
#define DUMP_WIDTH 23
-#define DUMP_FIELD(obj, format, field) \
+#define DUMP_VALUE(format, field, value) \
do { \
if (setjmp(bus_error_jmp) == 0) { \
catch_memory_errors = 1; \
sync(); \
printf(" %-*s = "format"\n", DUMP_WIDTH, \
- #field, obj->field); \
+ #field, value); \
sync(); \
__delay(200); \
} else { \
catch_memory_errors = 0; \
} while (0)
+#define DUMP_FIELD(obj, format, field) \
+ DUMP_VALUE(format, field, obj->field)
+
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%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);
+ DUMP_VALUE("0x%x", problem->spu_runcntl_RW,
+ in_be32(&spu->problem->spu_runcntl_RW));
+ DUMP_VALUE("0x%x", problem->spu_status_R,
+ in_be32(&spu->problem->spu_status_R));
+ DUMP_VALUE("0x%x", problem->spu_npc_RW,
+ in_be32(&spu->problem->spu_npc_RW));
+ DUMP_FIELD(spu, "0x%p", priv2);
+ DUMP_FIELD(spu, "0x%p", pdata);
+}
- if (spu->priv1)
- DUMP_FIELD(spu, "0x%lx", priv1->mfc_sr1_RW);
+int
+spu_inst_dump(unsigned long adr, long count, int praddr)
+{
+ return generic_inst_dump(adr, count, praddr, print_insn_spu);
+}
- DUMP_FIELD(spu, "0x%p", priv2);
+static void dump_spu_ls(unsigned long num, int subcmd)
+{
+ unsigned long offset, addr, ls_addr;
+
+ if (setjmp(bus_error_jmp) == 0) {
+ catch_memory_errors = 1;
+ sync();
+ ls_addr = (unsigned long)spu_info[num].spu->local_store;
+ sync();
+ __delay(200);
+ } else {
+ catch_memory_errors = 0;
+ printf("*** Error: accessing spu info for spu %d\n", num);
+ return;
+ }
+ catch_memory_errors = 0;
+
+ if (scanhex(&offset))
+ addr = ls_addr + offset;
+ else
+ addr = spu_info[num].dump_addr;
+
+ if (addr >= ls_addr + LS_SIZE) {
+ printf("*** Error: address outside of local store\n");
+ return;
+ }
+
+ switch (subcmd) {
+ case 'i':
+ addr += spu_inst_dump(addr, 16, 1);
+ last_cmd = "sdi\n";
+ break;
+ default:
+ prdump(addr, 64);
+ addr += 64;
+ last_cmd = "sd\n";
+ break;
+ }
+
+ spu_info[num].dump_addr = addr;
}
static int do_spu_cmd(void)
{
- unsigned long num = 0;
- int cmd;
+ static unsigned long num = 0;
+ int cmd, subcmd = 0;
cmd = inchar();
switch (cmd) {
case 'r':
restart_spus();
break;
+ case 'd':
+ subcmd = inchar();
+ if (isxdigit(subcmd) || subcmd == '\n')
+ termch = subcmd;
case 'f':
- if (scanhex(&num) && num < XMON_NUM_SPUS && spu_info[num].spu)
- dump_spu_fields(spu_info[num].spu);
- else
+ scanhex(&num);
+ if (num >= XMON_NUM_SPUS || !spu_info[num].spu) {
printf("*** Error: invalid spu number\n");
+ return 0;
+ }
+
+ switch (cmd) {
+ case 'f':
+ dump_spu_fields(spu_info[num].spu);
+ break;
+ default:
+ dump_spu_ls(num, subcmd);
+ break;
+ }
+
break;
default:
return -1;
return 0;
}
-#else /* ! CONFIG_PPC_CELL */
+#else /* ! CONFIG_SPU_BASE */
static int do_spu_cmd(void)
{
return -1;