diff options
-rw-r--r-- | arch/powerpc/platforms/cell/spu_base.c | 4 | ||||
-rw-r--r-- | arch/powerpc/xmon/xmon.c | 142 | ||||
-rw-r--r-- | include/asm-powerpc/xmon.h | 2 |
3 files changed, 146 insertions, 2 deletions
diff --git a/arch/powerpc/platforms/cell/spu_base.c b/arch/powerpc/platforms/cell/spu_base.c index b75b091098ef..032bc923342a 100644 --- a/arch/powerpc/platforms/cell/spu_base.c +++ b/arch/powerpc/platforms/cell/spu_base.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <asm/spu.h> | 38 | #include <asm/spu.h> |
39 | #include <asm/spu_priv1.h> | 39 | #include <asm/spu_priv1.h> |
40 | #include <asm/mmu_context.h> | 40 | #include <asm/mmu_context.h> |
41 | #include <asm/xmon.h> | ||
41 | 42 | ||
42 | #include "interrupt.h" | 43 | #include "interrupt.h" |
43 | 44 | ||
@@ -943,6 +944,9 @@ static int __init init_spu_base(void) | |||
943 | break; | 944 | break; |
944 | } | 945 | } |
945 | } | 946 | } |
947 | |||
948 | xmon_register_spus(&spu_full_list); | ||
949 | |||
946 | return ret; | 950 | return ret; |
947 | } | 951 | } |
948 | module_init(init_spu_base); | 952 | module_init(init_spu_base); |
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); |
148 | static const char *getvecname(unsigned long vec); | 150 | static const char *getvecname(unsigned long vec); |
149 | 151 | ||
152 | static int do_spu_cmd(void); | ||
153 | |||
150 | int xmon_no_auto_backtrace; | 154 | int xmon_no_auto_backtrace; |
151 | 155 | ||
152 | extern int print_insn_powerpc(unsigned long, unsigned long, int); | 156 | extern 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(®s); | 526 | xmon_save_regs(®s); |
519 | excp = ®s; | 527 | excp = ®s; |
520 | } | 528 | } |
529 | |||
521 | return xmon_core(excp, 0); | 530 | return xmon_core(excp, 0); |
522 | } | 531 | } |
523 | EXPORT_SYMBOL(xmon); | 532 | EXPORT_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 | |||
2647 | struct 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 | |||
2656 | static struct spu_info spu_info[XMON_NUM_SPUS]; | ||
2657 | |||
2658 | void 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 | |||
2673 | static 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 | |||
2711 | static 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 | |||
2747 | static 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 */ | ||
2766 | static int do_spu_cmd(void) | ||
2767 | { | ||
2768 | return -1; | ||
2769 | } | ||
2770 | #endif | ||
diff --git a/include/asm-powerpc/xmon.h b/include/asm-powerpc/xmon.h index f1d337ed68d5..88320a05f0a8 100644 --- a/include/asm-powerpc/xmon.h +++ b/include/asm-powerpc/xmon.h | |||
@@ -14,8 +14,10 @@ | |||
14 | 14 | ||
15 | #ifdef CONFIG_XMON | 15 | #ifdef CONFIG_XMON |
16 | extern void xmon_setup(void); | 16 | extern void xmon_setup(void); |
17 | extern void xmon_register_spus(struct list_head *list); | ||
17 | #else | 18 | #else |
18 | static inline void xmon_setup(void) { }; | 19 | static inline void xmon_setup(void) { }; |
20 | static inline void xmon_register_spus(struct list_head *list) { }; | ||
19 | #endif | 21 | #endif |
20 | 22 | ||
21 | #endif /* __KERNEL __ */ | 23 | #endif /* __KERNEL __ */ |