aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/xmon/xmon.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/xmon/xmon.c')
-rw-r--r--arch/powerpc/xmon/xmon.c142
1 files changed, 140 insertions, 2 deletions
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index f56ffef4defa..6a2ed8b319f0 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -37,6 +37,8 @@
37#include <asm/sstep.h> 37#include <asm/sstep.h>
38#include <asm/bug.h> 38#include <asm/bug.h>
39#include <asm/irq_regs.h> 39#include <asm/irq_regs.h>
40#include <asm/spu.h>
41#include <asm/spu_priv1.h>
40 42
41#ifdef CONFIG_PPC64 43#ifdef CONFIG_PPC64
42#include <asm/hvcall.h> 44#include <asm/hvcall.h>
@@ -147,6 +149,8 @@ static void xmon_print_symbol(unsigned long address, const char *mid,
147 const char *after); 149 const char *after);
148static const char *getvecname(unsigned long vec); 150static const char *getvecname(unsigned long vec);
149 151
152static int do_spu_cmd(void);
153
150int xmon_no_auto_backtrace; 154int xmon_no_auto_backtrace;
151 155
152extern int print_insn_powerpc(unsigned long, unsigned long, int); 156extern int print_insn_powerpc(unsigned long, unsigned long, int);
@@ -209,8 +213,12 @@ Commands:\n\
209 mi show information about memory allocation\n\ 213 mi show information about memory allocation\n\
210 p call a procedure\n\ 214 p call a procedure\n\
211 r print registers\n\ 215 r print registers\n\
212 s single step\n\ 216 s single step\n"
213 S print special registers\n\ 217#ifdef CONFIG_PPC_CELL
218" ss stop execution on all spus\n\
219 sr restore execution on stopped spus\n"
220#endif
221" S print special registers\n\
214 t print backtrace\n\ 222 t print backtrace\n\
215 x exit monitor and recover\n\ 223 x exit monitor and recover\n\
216 X exit monitor and dont recover\n" 224 X exit monitor and dont recover\n"
@@ -518,6 +526,7 @@ int xmon(struct pt_regs *excp)
518 xmon_save_regs(&regs); 526 xmon_save_regs(&regs);
519 excp = &regs; 527 excp = &regs;
520 } 528 }
529
521 return xmon_core(excp, 0); 530 return xmon_core(excp, 0);
522} 531}
523EXPORT_SYMBOL(xmon); 532EXPORT_SYMBOL(xmon);
@@ -809,6 +818,8 @@ cmds(struct pt_regs *excp)
809 cacheflush(); 818 cacheflush();
810 break; 819 break;
811 case 's': 820 case 's':
821 if (do_spu_cmd() == 0)
822 break;
812 if (do_step(excp)) 823 if (do_step(excp))
813 return cmd; 824 return cmd;
814 break; 825 break;
@@ -2630,3 +2641,130 @@ void __init xmon_setup(void)
2630 if (xmon_early) 2641 if (xmon_early)
2631 debugger(NULL); 2642 debugger(NULL);
2632} 2643}
2644
2645#ifdef CONFIG_PPC_CELL
2646
2647struct spu_info {
2648 struct spu *spu;
2649 u64 saved_mfc_sr1_RW;
2650 u32 saved_spu_runcntl_RW;
2651 u8 stopped_ok;
2652};
2653
2654#define XMON_NUM_SPUS 16 /* Enough for current hardware */
2655
2656static struct spu_info spu_info[XMON_NUM_SPUS];
2657
2658void xmon_register_spus(struct list_head *list)
2659{
2660 struct spu *spu;
2661
2662 list_for_each_entry(spu, list, full_list) {
2663 if (spu->number >= XMON_NUM_SPUS) {
2664 WARN_ON(1);
2665 continue;
2666 }
2667
2668 spu_info[spu->number].spu = spu;
2669 spu_info[spu->number].stopped_ok = 0;
2670 }
2671}
2672
2673static void stop_spus(void)
2674{
2675 struct spu *spu;
2676 int i;
2677 u64 tmp;
2678
2679 for (i = 0; i < XMON_NUM_SPUS; i++) {
2680 if (!spu_info[i].spu)
2681 continue;
2682
2683 if (setjmp(bus_error_jmp) == 0) {
2684 catch_memory_errors = 1;
2685 sync();
2686
2687 spu = spu_info[i].spu;
2688
2689 spu_info[i].saved_spu_runcntl_RW =
2690 in_be32(&spu->problem->spu_runcntl_RW);
2691
2692 tmp = spu_mfc_sr1_get(spu);
2693 spu_info[i].saved_mfc_sr1_RW = tmp;
2694
2695 tmp &= ~MFC_STATE1_MASTER_RUN_CONTROL_MASK;
2696 spu_mfc_sr1_set(spu, tmp);
2697
2698 sync();
2699 __delay(200);
2700
2701 spu_info[i].stopped_ok = 1;
2702 printf("Stopped spu %.2d\n", i);
2703 } else {
2704 catch_memory_errors = 0;
2705 printf("*** Error stopping spu %.2d\n", i);
2706 }
2707 catch_memory_errors = 0;
2708 }
2709}
2710
2711static void restart_spus(void)
2712{
2713 struct spu *spu;
2714 int i;
2715
2716 for (i = 0; i < XMON_NUM_SPUS; i++) {
2717 if (!spu_info[i].spu)
2718 continue;
2719
2720 if (!spu_info[i].stopped_ok) {
2721 printf("*** Error, spu %d was not successfully stopped"
2722 ", not restarting\n", i);
2723 continue;
2724 }
2725
2726 if (setjmp(bus_error_jmp) == 0) {
2727 catch_memory_errors = 1;
2728 sync();
2729
2730 spu = spu_info[i].spu;
2731 spu_mfc_sr1_set(spu, spu_info[i].saved_mfc_sr1_RW);
2732 out_be32(&spu->problem->spu_runcntl_RW,
2733 spu_info[i].saved_spu_runcntl_RW);
2734
2735 sync();
2736 __delay(200);
2737
2738 printf("Restarted spu %.2d\n", i);
2739 } else {
2740 catch_memory_errors = 0;
2741 printf("*** Error restarting spu %.2d\n", i);
2742 }
2743 catch_memory_errors = 0;
2744 }
2745}
2746
2747static int do_spu_cmd(void)
2748{
2749 int cmd;
2750
2751 cmd = inchar();
2752 switch (cmd) {
2753 case 's':
2754 stop_spus();
2755 break;
2756 case 'r':
2757 restart_spus();
2758 break;
2759 default:
2760 return -1;
2761 }
2762
2763 return 0;
2764}
2765#else /* ! CONFIG_PPC_CELL */
2766static int do_spu_cmd(void)
2767{
2768 return -1;
2769}
2770#endif