|
@@ -37,6 +37,8 @@
|
|
|
#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>
|
|
@@ -147,6 +149,8 @@ static void xmon_print_symbol(unsigned long address, const char *mid,
|
|
|
const char *after);
|
|
|
static const char *getvecname(unsigned long vec);
|
|
|
|
|
|
+static int do_spu_cmd(void);
|
|
|
+
|
|
|
int xmon_no_auto_backtrace;
|
|
|
|
|
|
extern int print_insn_powerpc(unsigned long, unsigned long, int);
|
|
@@ -209,8 +213,12 @@ Commands:\n\
|
|
|
mi show information about memory allocation\n\
|
|
|
p call a procedure\n\
|
|
|
r print registers\n\
|
|
|
- s single step\n\
|
|
|
- S print special registers\n\
|
|
|
+ s single step\n"
|
|
|
+#ifdef CONFIG_PPC_CELL
|
|
|
+" ss stop execution on all spus\n\
|
|
|
+ sr restore execution on stopped spus\n"
|
|
|
+#endif
|
|
|
+" S print special registers\n\
|
|
|
t print backtrace\n\
|
|
|
x exit monitor and recover\n\
|
|
|
X exit monitor and dont recover\n"
|
|
@@ -518,6 +526,7 @@ int xmon(struct pt_regs *excp)
|
|
|
xmon_save_regs(®s);
|
|
|
excp = ®s;
|
|
|
}
|
|
|
+
|
|
|
return xmon_core(excp, 0);
|
|
|
}
|
|
|
EXPORT_SYMBOL(xmon);
|
|
@@ -809,6 +818,8 @@ cmds(struct pt_regs *excp)
|
|
|
cacheflush();
|
|
|
break;
|
|
|
case 's':
|
|
|
+ if (do_spu_cmd() == 0)
|
|
|
+ break;
|
|
|
if (do_step(excp))
|
|
|
return cmd;
|
|
|
break;
|
|
@@ -2630,3 +2641,130 @@ void __init xmon_setup(void)
|
|
|
if (xmon_early)
|
|
|
debugger(NULL);
|
|
|
}
|
|
|
+
|
|
|
+#ifdef CONFIG_PPC_CELL
|
|
|
+
|
|
|
+struct spu_info {
|
|
|
+ struct spu *spu;
|
|
|
+ u64 saved_mfc_sr1_RW;
|
|
|
+ u32 saved_spu_runcntl_RW;
|
|
|
+ u8 stopped_ok;
|
|
|
+};
|
|
|
+
|
|
|
+#define XMON_NUM_SPUS 16 /* Enough for current hardware */
|
|
|
+
|
|
|
+static struct spu_info spu_info[XMON_NUM_SPUS];
|
|
|
+
|
|
|
+void xmon_register_spus(struct list_head *list)
|
|
|
+{
|
|
|
+ struct spu *spu;
|
|
|
+
|
|
|
+ list_for_each_entry(spu, list, full_list) {
|
|
|
+ if (spu->number >= XMON_NUM_SPUS) {
|
|
|
+ WARN_ON(1);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ spu_info[spu->number].spu = spu;
|
|
|
+ spu_info[spu->number].stopped_ok = 0;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static void stop_spus(void)
|
|
|
+{
|
|
|
+ struct spu *spu;
|
|
|
+ int i;
|
|
|
+ u64 tmp;
|
|
|
+
|
|
|
+ for (i = 0; i < XMON_NUM_SPUS; i++) {
|
|
|
+ if (!spu_info[i].spu)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ if (setjmp(bus_error_jmp) == 0) {
|
|
|
+ catch_memory_errors = 1;
|
|
|
+ sync();
|
|
|
+
|
|
|
+ spu = spu_info[i].spu;
|
|
|
+
|
|
|
+ spu_info[i].saved_spu_runcntl_RW =
|
|
|
+ in_be32(&spu->problem->spu_runcntl_RW);
|
|
|
+
|
|
|
+ tmp = spu_mfc_sr1_get(spu);
|
|
|
+ spu_info[i].saved_mfc_sr1_RW = tmp;
|
|
|
+
|
|
|
+ tmp &= ~MFC_STATE1_MASTER_RUN_CONTROL_MASK;
|
|
|
+ spu_mfc_sr1_set(spu, tmp);
|
|
|
+
|
|
|
+ sync();
|
|
|
+ __delay(200);
|
|
|
+
|
|
|
+ spu_info[i].stopped_ok = 1;
|
|
|
+ printf("Stopped spu %.2d\n", i);
|
|
|
+ } else {
|
|
|
+ catch_memory_errors = 0;
|
|
|
+ printf("*** Error stopping spu %.2d\n", i);
|
|
|
+ }
|
|
|
+ catch_memory_errors = 0;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static void restart_spus(void)
|
|
|
+{
|
|
|
+ struct spu *spu;
|
|
|
+ int i;
|
|
|
+
|
|
|
+ for (i = 0; i < XMON_NUM_SPUS; i++) {
|
|
|
+ if (!spu_info[i].spu)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ if (!spu_info[i].stopped_ok) {
|
|
|
+ printf("*** Error, spu %d was not successfully stopped"
|
|
|
+ ", not restarting\n", i);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (setjmp(bus_error_jmp) == 0) {
|
|
|
+ catch_memory_errors = 1;
|
|
|
+ sync();
|
|
|
+
|
|
|
+ spu = spu_info[i].spu;
|
|
|
+ spu_mfc_sr1_set(spu, spu_info[i].saved_mfc_sr1_RW);
|
|
|
+ out_be32(&spu->problem->spu_runcntl_RW,
|
|
|
+ spu_info[i].saved_spu_runcntl_RW);
|
|
|
+
|
|
|
+ sync();
|
|
|
+ __delay(200);
|
|
|
+
|
|
|
+ printf("Restarted spu %.2d\n", i);
|
|
|
+ } else {
|
|
|
+ catch_memory_errors = 0;
|
|
|
+ printf("*** Error restarting spu %.2d\n", i);
|
|
|
+ }
|
|
|
+ catch_memory_errors = 0;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static int do_spu_cmd(void)
|
|
|
+{
|
|
|
+ int cmd;
|
|
|
+
|
|
|
+ cmd = inchar();
|
|
|
+ switch (cmd) {
|
|
|
+ case 's':
|
|
|
+ stop_spus();
|
|
|
+ break;
|
|
|
+ case 'r':
|
|
|
+ restart_spus();
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+#else /* ! CONFIG_PPC_CELL */
|
|
|
+static int do_spu_cmd(void)
|
|
|
+{
|
|
|
+ return -1;
|
|
|
+}
|
|
|
+#endif
|