#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>
                              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);
   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"
                xmon_save_regs(®s);
                excp = ®s;
        }
+
        return xmon_core(excp, 0);
 }
 EXPORT_SYMBOL(xmon);
                        cacheflush();
                        break;
                case 's':
+                       if (do_spu_cmd() == 0)
+                               break;
                        if (do_step(excp))
                                return cmd;
                        break;
        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