aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Ellerman <michael@ellerman.id.au>2006-11-22 18:46:41 -0500
committerPaul Mackerras <paulus@samba.org>2006-12-04 04:40:26 -0500
commit24a24c85d3c35790a355138d7cd34c074cb1b3ac (patch)
treef55755dd45a0ce142c59f8d3a06ff7f0653997b2
parent2a14442bfebfea23d004fa4dfd067a94f5720ed7 (diff)
[POWERPC] Add a sd command (spu dump) to xmon to dump spu local store
Add a command to xmon to dump the memory of a spu's local store. This mimics the 'd' command which dumps regular memory, but does a little hand holding by taking the user supplied address and finding that offset in the local store for the specified spu. This makes it easy for example to look at what was executing on a spu: 1:mon> ss ... Stopped spu 04 (was running) ... 1:mon> sf 4 Dumping spu fields at address c0000000019e0a00: ... problem->spu_npc_RW = 0x228 ... 1:mon> sd 4 0x228 d000080080318228 01a00c021cffc408 4020007f217ff488 |........@ ..!...| Aha, 01a00c02, which is of course rdch $2,$ch24 ! -- Updated to only do the setjmp goo around the spu access, and not around prdump because it does its own (via mread). Also the num variable is now common between sf and sd, so you don't have to keep typing the spu number in if you're repeating commands on the same spu. Signed-off-by: Michael Ellerman <michael@ellerman.id.au> Signed-off-by: Arnd Bergmann <arnd.bergmann@de.ibm.com>
-rw-r--r--arch/powerpc/xmon/xmon.c60
1 files changed, 55 insertions, 5 deletions
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index ac17abbe3ef0..be2c12d68785 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -218,7 +218,8 @@ Commands:\n\
218#ifdef CONFIG_PPC_CELL 218#ifdef CONFIG_PPC_CELL
219" ss stop execution on all spus\n\ 219" ss stop execution on all spus\n\
220 sr restore execution on stopped spus\n\ 220 sr restore execution on stopped spus\n\
221 sf # dump spu fields for spu # (in hex)\n" 221 sf # dump spu fields for spu # (in hex)\n\
222 sd # dump spu local store for spu # (in hex)\n"
222#endif 223#endif
223" S print special registers\n\ 224" S print special registers\n\
224 t print backtrace\n\ 225 t print backtrace\n\
@@ -2651,6 +2652,7 @@ struct spu_info {
2651 struct spu *spu; 2652 struct spu *spu;
2652 u64 saved_mfc_sr1_RW; 2653 u64 saved_mfc_sr1_RW;
2653 u32 saved_spu_runcntl_RW; 2654 u32 saved_spu_runcntl_RW;
2655 unsigned long dump_addr;
2654 u8 stopped_ok; 2656 u8 stopped_ok;
2655}; 2657};
2656 2658
@@ -2670,6 +2672,8 @@ void xmon_register_spus(struct list_head *list)
2670 2672
2671 spu_info[spu->number].spu = spu; 2673 spu_info[spu->number].spu = spu;
2672 spu_info[spu->number].stopped_ok = 0; 2674 spu_info[spu->number].stopped_ok = 0;
2675 spu_info[spu->number].dump_addr = (unsigned long)
2676 spu_info[spu->number].spu->local_store;
2673 } 2677 }
2674} 2678}
2675 2679
@@ -2815,9 +2819,43 @@ static void dump_spu_fields(struct spu *spu)
2815 DUMP_FIELD(spu, "0x%p", priv2); 2819 DUMP_FIELD(spu, "0x%p", priv2);
2816} 2820}
2817 2821
2822static void dump_spu_ls(unsigned long num)
2823{
2824 unsigned long offset, addr, ls_addr;
2825
2826 if (setjmp(bus_error_jmp) == 0) {
2827 catch_memory_errors = 1;
2828 sync();
2829 ls_addr = (unsigned long)spu_info[num].spu->local_store;
2830 sync();
2831 __delay(200);
2832 } else {
2833 catch_memory_errors = 0;
2834 printf("*** Error: accessing spu info for spu %d\n", num);
2835 return;
2836 }
2837 catch_memory_errors = 0;
2838
2839 if (scanhex(&offset))
2840 addr = ls_addr + offset;
2841 else
2842 addr = spu_info[num].dump_addr;
2843
2844 if (addr >= ls_addr + LS_SIZE) {
2845 printf("*** Error: address outside of local store\n");
2846 return;
2847 }
2848
2849 prdump(addr, 64);
2850 addr += 64;
2851 last_cmd = "sd\n";
2852
2853 spu_info[num].dump_addr = addr;
2854}
2855
2818static int do_spu_cmd(void) 2856static int do_spu_cmd(void)
2819{ 2857{
2820 unsigned long num = 0; 2858 static unsigned long num = 0;
2821 int cmd; 2859 int cmd;
2822 2860
2823 cmd = inchar(); 2861 cmd = inchar();
@@ -2829,10 +2867,22 @@ static int do_spu_cmd(void)
2829 restart_spus(); 2867 restart_spus();
2830 break; 2868 break;
2831 case 'f': 2869 case 'f':
2832 if (scanhex(&num) && num < XMON_NUM_SPUS && spu_info[num].spu) 2870 case 'd':
2833 dump_spu_fields(spu_info[num].spu); 2871 scanhex(&num);
2834 else 2872 if (num >= XMON_NUM_SPUS || !spu_info[num].spu) {
2835 printf("*** Error: invalid spu number\n"); 2873 printf("*** Error: invalid spu number\n");
2874 return 0;
2875 }
2876
2877 switch (cmd) {
2878 case 'f':
2879 dump_spu_fields(spu_info[num].spu);
2880 break;
2881 default:
2882 dump_spu_ls(num);
2883 break;
2884 }
2885
2836 break; 2886 break;
2837 default: 2887 default:
2838 return -1; 2888 return -1;